1 /*-
2 * Copyright (c) 2006 Takanori Watanabe
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 *
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24 * SUCH DAMAGE.
25 */
26
27 #include <sys/cdefs.h>
28 __FBSDID("$FreeBSD: releng/8.4/sys/dev/acpi_support/acpi_aiboost.c 197486 2009-09-25 15:14:11Z jhb $");
29
30 #include "opt_acpi.h"
31 #include <sys/param.h>
32 #include <sys/kernel.h>
33 #include <sys/bus.h>
34
35 #include <contrib/dev/acpica/include/acpi.h>
36
37 #include "acpi_if.h"
38 #include <sys/module.h>
39 #include <dev/acpica/acpivar.h>
40 #include <sys/sysctl.h>
41 #include <sys/malloc.h>
42 #include <sys/sysctl.h>
43
44 #define _COMPONENT ACPI_OEM
45 ACPI_MODULE_NAME("AIBOOST")
46
47 #define DESCSTRLEN 32
48 struct acpi_aiboost_element{
49 uint32_t id;
50 char desc[DESCSTRLEN];
51 };
52 ACPI_SERIAL_DECL(aiboost, "ACPI AIBOOST");
53 /**/
54 struct acpi_aiboost_component{
55 unsigned int num;
56 struct acpi_aiboost_element elem[1];
57 };
58
59 struct acpi_aiboost_softc {
60 int pid;
61 struct acpi_aiboost_component *temp;
62 struct acpi_aiboost_component *volt;
63 struct acpi_aiboost_component *fan;
64 };
65
66 static int acpi_aiboost_probe(device_t dev);
67 static int acpi_aiboost_attach(device_t dev);
68 static int acpi_aiboost_detach(device_t dev);
69
70 static device_method_t acpi_aiboost_methods[] = {
71 /* Device interface */
72 DEVMETHOD(device_probe, acpi_aiboost_probe),
73 DEVMETHOD(device_attach, acpi_aiboost_attach),
74 DEVMETHOD(device_detach, acpi_aiboost_detach),
75
76 {0, 0}
77 };
78
79 static driver_t acpi_aiboost_driver = {
80 "acpi_aiboost",
81 acpi_aiboost_methods,
82 sizeof(struct acpi_aiboost_softc),
83 };
84
85 static devclass_t acpi_aiboost_devclass;
86
87 DRIVER_MODULE(acpi_aiboost, acpi, acpi_aiboost_driver, acpi_aiboost_devclass,
88 0, 0);
89 MODULE_DEPEND(acpi_aiboost, acpi, 1, 1, 1);
90 static char *abs_id[] = {"ATK0110", NULL};
91
92 /*VSIF, RVLT, SVLT, TSIF, RTMP, STMP FSIF, RFAN, SFAN */
93
94 static ACPI_STATUS acpi_aiboost_getcomponent(device_t dev, char *name, struct acpi_aiboost_component **comp)
95 {
96 ACPI_BUFFER buf, buf2;
97 ACPI_OBJECT *o,*elem,*subobj;
98 ACPI_STATUS status;
99 struct acpi_aiboost_component *c = NULL;
100
101 int i;
102
103 buf.Pointer = NULL;
104 buf.Length = ACPI_ALLOCATE_BUFFER;
105 buf2.Pointer = NULL;
106
107 status = AcpiEvaluateObject(acpi_get_handle(dev), name, NULL, &buf);
108
109 if(ACPI_FAILURE(status))
110 return status;
111
112 o = buf.Pointer;
113 if(o->Type != ACPI_TYPE_PACKAGE)
114 goto error;
115
116 elem = o->Package.Elements;
117 if(elem->Type != ACPI_TYPE_INTEGER)
118 goto error;
119
120 c = malloc(sizeof(struct acpi_aiboost_component)
121 + sizeof(struct acpi_aiboost_element)
122 * (elem->Integer.Value -1),
123 M_DEVBUF, M_ZERO|M_WAITOK);
124 *comp = c;
125 c->num = elem->Integer.Value;
126
127 for(i = 1 ; i < o->Package.Count; i++){
128 elem = &o->Package.Elements[i];
129 if (elem->Type == ACPI_TYPE_ANY) {
130 buf2.Pointer = NULL;
131 buf2.Length = ACPI_ALLOCATE_BUFFER;
132
133 status = AcpiEvaluateObject(elem->Reference.Handle,
134 NULL, NULL, &buf2);
135 if (ACPI_FAILURE(status)){
136 printf("FETCH OBJECT\n");
137 goto error;
138 }
139 subobj = buf2.Pointer;
140 } else if (elem->Type == ACPI_TYPE_PACKAGE)
141 subobj = elem;
142 else {
143 printf("NO PACKAGE\n");
144 goto error;
145 }
146 if(ACPI_FAILURE(acpi_PkgInt32(subobj,0, &c->elem[i -1].id))){
147 printf("ID FAILED\n");
148 goto error;
149 }
150 status = acpi_PkgStr(subobj, 1, c->elem[i - 1].desc,
151 sizeof(c->elem[i - 1].desc));
152 if(ACPI_FAILURE(status)){
153 if(status == E2BIG){
154 c->elem[i - 1].desc[DESCSTRLEN-1] = 0;
155 }else{
156 printf("DESC FAILED %d\n", i-1);
157 goto error;
158 }
159 }
160
161 if (buf2.Pointer) {
162 AcpiOsFree(buf2.Pointer);
163 buf2.Pointer = NULL;
164 }
165 }
166
167 if(buf.Pointer)
168 AcpiOsFree(buf.Pointer);
169
170 return 0;
171
172 error:
173 printf("BAD DATA\n");
174 if(buf.Pointer)
175 AcpiOsFree(buf.Pointer);
176 if(buf2.Pointer)
177 AcpiOsFree(buf2.Pointer);
178 if(c)
179 free(c, M_DEVBUF);
180 return AE_BAD_DATA;
181 }
182
183 static int
184 acpi_aiboost_get_value(ACPI_HANDLE handle, char *path, UINT32 number)
185 {
186 ACPI_OBJECT arg1, *ret;
187 ACPI_OBJECT_LIST args;
188 ACPI_BUFFER buf;
189 buf.Length = ACPI_ALLOCATE_BUFFER;
190 buf.Pointer = 0;
191 int val;
192
193 arg1.Type = ACPI_TYPE_INTEGER;
194 arg1.Integer.Value = number;
195 args.Count = 1;
196 args.Pointer = &arg1;
197
198 if(ACPI_FAILURE(AcpiEvaluateObject(handle, path, &args, &buf))){
199 return -1;
200 }
201
202 ret = buf.Pointer;
203 val = (ret->Type == ACPI_TYPE_INTEGER)? ret->Integer.Value : -1;
204
205 AcpiOsFree(buf.Pointer);
206 return val;
207 }
208
209
210 static int acpi_aiboost_temp_sysctl(SYSCTL_HANDLER_ARGS)
211 {
212 device_t dev = arg1;
213 int function = oidp->oid_arg2;
214 int error = 0, val;
215 ACPI_SERIAL_BEGIN(aiboost);
216 val = acpi_aiboost_get_value(acpi_get_handle(dev), "RTMP",function );
217 error = sysctl_handle_int(oidp, &val, 0 , req);
218 ACPI_SERIAL_END(aiboost);
219
220 return 0;
221 }
222
223 static int acpi_aiboost_volt_sysctl(SYSCTL_HANDLER_ARGS)
224 {
225 device_t dev = arg1;
226 int function = oidp->oid_arg2;
227 int error = 0, val;
228 ACPI_SERIAL_BEGIN(aiboost);
229 val = acpi_aiboost_get_value(acpi_get_handle(dev), "RVLT", function);
230 error = sysctl_handle_int(oidp, &val, 0 , req);
231 ACPI_SERIAL_END(aiboost);
232
233 return 0;
234 }
235
236 static int acpi_aiboost_fan_sysctl(SYSCTL_HANDLER_ARGS)
237 {
238 device_t dev = arg1;
239 int function = oidp->oid_arg2;
240 int error = 0, val;
241 ACPI_SERIAL_BEGIN(aiboost);
242 val = acpi_aiboost_get_value(acpi_get_handle(dev), "RFAN", function);
243 error = sysctl_handle_int(oidp, &val, 0 , req);
244 ACPI_SERIAL_END(aiboost);
245
246 return 0;
247 }
248
249 static int
250 acpi_aiboost_probe(device_t dev)
251 {
252 int ret = ENXIO;
253
254 if (ACPI_ID_PROBE(device_get_parent(dev), dev, abs_id)) {
255 device_set_desc(dev, "ASUStek AIBOOSTER");
256 ret = 0;
257 }
258 return (ret);
259 }
260
261 static int
262 acpi_aiboost_attach(device_t dev)
263 {
264 struct acpi_aiboost_softc *sc;
265 char nambuf[]="tempXXX";
266 int i;
267
268 sc = device_get_softc(dev);
269 if(ACPI_FAILURE(acpi_aiboost_getcomponent(dev, "TSIF", &sc->temp)))
270 goto error;
271 for(i= 0; i < sc->temp->num; i++){
272 sprintf(nambuf,"temp%d", i);
273 SYSCTL_ADD_PROC(device_get_sysctl_ctx(dev),
274 SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
275 OID_AUTO, nambuf,
276 CTLTYPE_INT|CTLFLAG_RD, dev,
277 sc->temp->elem[i].id,
278 acpi_aiboost_temp_sysctl,
279 "I", sc->temp->elem[i].desc);
280 }
281 if(ACPI_FAILURE(acpi_aiboost_getcomponent(dev, "VSIF", &sc->volt)))
282 goto error;
283
284 for(i= 0; i < sc->volt->num; i++){
285 sprintf(nambuf,"volt%d", i);
286 SYSCTL_ADD_PROC(device_get_sysctl_ctx(dev),
287 SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
288 OID_AUTO, nambuf,
289 CTLTYPE_INT|CTLFLAG_RD, dev,
290 sc->volt->elem[i].id,
291 acpi_aiboost_volt_sysctl,
292 "I", sc->volt->elem[i].desc);
293 }
294
295 if(ACPI_FAILURE(acpi_aiboost_getcomponent(dev, "FSIF", &sc->fan)))
296 goto error;
297
298 for(i= 0; i < sc->fan->num; i++){
299 sprintf(nambuf,"fan%d", i);
300 SYSCTL_ADD_PROC(device_get_sysctl_ctx(dev),
301 SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
302 OID_AUTO, nambuf,
303 CTLTYPE_INT|CTLFLAG_RD, dev,
304 sc->fan->elem[i].id,
305 acpi_aiboost_fan_sysctl,
306 "I", sc->fan->elem[i].desc);
307 }
308
309
310 return (0);
311 error:
312 return EINVAL;
313 }
314
315 static int
316 acpi_aiboost_detach(device_t dev)
317 {
318 struct acpi_aiboost_softc *sc = device_get_softc(dev);
319
320 if(sc->temp)
321 free(sc->temp, M_DEVBUF);
322 if(sc->volt)
323 free(sc->volt, M_DEVBUF);
324 if(sc->fan)
325 free(sc->fan, M_DEVBUF);
326 return (0);
327 }
328
329 #if 0
330 static int
331 acpi_aiboost_suspend(device_t dev)
332 {
333 struct acpi_aiboost_softc *sc = device_get_softc(dev);
334 return (0);
335 }
336
337 static int
338 acpi_aiboost_resume(device_t dev)
339 {
340 return (0);
341 }
342 #endif
Cache object: 4ea885ef0ed6a9b3bba4d6bdcd4ab96c
|