]> CyberLeo.Net >> Repos - FreeBSD/releng/8.1.git/blob - sys/dev/acpi_support/acpi_aiboost.c
Copy stable/8 to releng/8.1 in preparation for 8.1-RC1.
[FreeBSD/releng/8.1.git] / sys / dev / acpi_support / acpi_aiboost.c
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$");
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