]> CyberLeo.Net >> Repos - FreeBSD/releng/7.2.git/blob - sys/dev/acpi_support/acpi_aiboost.c
Create releng/7.2 from stable/7 in preparation for 7.2-RELEASE.
[FreeBSD/releng/7.2.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 #include <contrib/dev/acpica/acpi.h>
35 #include "acpi_if.h"
36 #include <sys/module.h>
37 #include <dev/acpica/acpivar.h>
38 #include <sys/sysctl.h>
39 #include <sys/malloc.h>
40 #include <sys/sysctl.h>
41
42 #define _COMPONENT      ACPI_OEM
43 ACPI_MODULE_NAME("AIBOOST")
44
45 #define DESCSTRLEN 32
46 struct acpi_aiboost_element{
47         ACPI_HANDLE h;
48         uint32_t id;
49         char desc[DESCSTRLEN];
50 };
51 ACPI_SERIAL_DECL(aiboost, "ACPI AIBOOST");
52 /**/
53 struct acpi_aiboost_component{
54         unsigned int num;
55         struct acpi_aiboost_element elem[1];
56 };
57
58 struct acpi_aiboost_softc {
59         int pid;
60         struct acpi_aiboost_component *temp;
61         struct acpi_aiboost_component *volt;
62         struct acpi_aiboost_component *fan;
63 };
64
65 static int      acpi_aiboost_probe(device_t dev);
66 static int      acpi_aiboost_attach(device_t dev);
67 static int      acpi_aiboost_detach(device_t dev);
68
69 static device_method_t acpi_aiboost_methods[] = {
70         /* Device interface */
71         DEVMETHOD(device_probe, acpi_aiboost_probe),
72         DEVMETHOD(device_attach, acpi_aiboost_attach),
73         DEVMETHOD(device_detach, acpi_aiboost_detach),
74
75         {0, 0}
76 };
77
78 static driver_t acpi_aiboost_driver = {
79         "acpi_aiboost",
80         acpi_aiboost_methods,
81         sizeof(struct acpi_aiboost_softc),
82 };
83
84 static devclass_t acpi_aiboost_devclass;
85
86 DRIVER_MODULE(acpi_aiboost, acpi, acpi_aiboost_driver, acpi_aiboost_devclass,
87               0, 0);
88 MODULE_DEPEND(acpi_aiboost, acpi, 1, 1, 1);
89 static char    *abs_id[] = {"ATK0110", NULL};
90
91 /*VSIF, RVLT, SVLT,  TSIF, RTMP, STMP FSIF, RFAN, SFAN */
92
93 static ACPI_STATUS acpi_aiboost_getcomponent(device_t dev, char *name, struct  acpi_aiboost_component **comp)
94 {
95         ACPI_BUFFER             buf, buf2;
96         ACPI_OBJECT            *o,*elem,*subobj;
97         ACPI_STATUS status;
98         struct acpi_aiboost_component *c = NULL;
99
100         int i;
101
102         buf.Pointer = NULL;
103         buf.Length = ACPI_ALLOCATE_BUFFER;
104         buf2.Pointer = NULL;
105
106         status = AcpiEvaluateObject(acpi_get_handle(dev), name, NULL, &buf);
107         
108         if(ACPI_FAILURE(status))
109                 return status;
110         
111         o = buf.Pointer;
112         if(o->Type != ACPI_TYPE_PACKAGE)
113                 goto error;
114         
115         elem = o->Package.Elements;
116         if(elem->Type != ACPI_TYPE_INTEGER)
117                 goto error;
118
119         c = malloc(sizeof(struct acpi_aiboost_component)
120                    + sizeof(struct acpi_aiboost_element)
121                    * (elem->Integer.Value -1),
122                    M_DEVBUF, M_ZERO|M_WAITOK);
123         *comp = c;
124         c->num = elem->Integer.Value;
125         
126         for(i = 1 ; i < o->Package.Count; i++){
127                 elem = &o->Package.Elements[i];
128                 if(elem->Type != ACPI_TYPE_ANY){
129                         printf("NOREF\n");
130                         goto error;
131                 }
132                 c->elem[ i - 1].h = elem->Reference.Handle;
133
134                 buf2.Pointer = NULL;
135                 buf2.Length = ACPI_ALLOCATE_BUFFER;
136                 
137                 status = AcpiEvaluateObject(c->elem[i - 1].h, NULL, NULL,
138                                             &buf2);
139                 if(ACPI_FAILURE(status)){
140                         printf("FETCH OBJECT\n");
141                         goto error;
142                 }
143                 subobj = buf2.Pointer;
144                 if(ACPI_FAILURE(acpi_PkgInt32(subobj,0, &c->elem[i -1].id))){
145                         printf("ID FAILED\n");
146                         goto error;
147                 }
148                 status = acpi_PkgStr(subobj, 1, c->elem[i - 1].desc, 
149                                      sizeof(c->elem[i - 1].desc));
150                 if(ACPI_FAILURE(status)){
151                         if(status == E2BIG){
152                                 c->elem[i-1].desc[DESCSTRLEN-1] = 0;
153                         }else{
154                                 printf("DESC FAILED %d\n", i-1);
155                                 goto error;
156                         }
157                 }
158                 
159                 if(buf2.Pointer)
160                   AcpiOsFree(buf2.Pointer);
161         }
162
163         if(buf.Pointer)
164                 AcpiOsFree(buf.Pointer);
165
166         return 0;
167
168  error:
169         printf("BAD DATA\n");
170         if(buf.Pointer)
171                 AcpiOsFree(buf.Pointer);
172         if(buf2.Pointer)
173                 AcpiOsFree(buf2.Pointer);
174         if(c)
175                 free(c, M_DEVBUF);
176         return AE_BAD_DATA;
177 }
178
179 static int 
180 acpi_aiboost_get_value(ACPI_HANDLE handle, char *path, UINT32 number)
181 {
182         ACPI_OBJECT arg1, *ret;
183         ACPI_OBJECT_LIST args;
184         ACPI_BUFFER buf;
185         buf.Length = ACPI_ALLOCATE_BUFFER;
186         buf.Pointer = 0;
187         int val;
188
189         arg1.Type = ACPI_TYPE_INTEGER;
190         arg1.Integer.Value = number;
191         args.Count = 1;
192         args.Pointer = &arg1;
193
194         if(ACPI_FAILURE(AcpiEvaluateObject(handle, path, &args, &buf))){
195                 return -1;
196         }
197
198         ret = buf.Pointer;
199         val = (ret->Type == ACPI_TYPE_INTEGER)? ret->Integer.Value : -1;
200
201         AcpiOsFree(buf.Pointer);
202         return val;
203 }
204
205
206 static int acpi_aiboost_temp_sysctl(SYSCTL_HANDLER_ARGS)
207 {
208         device_t dev = arg1;
209         int function = oidp->oid_arg2;
210         int error = 0, val;
211         ACPI_SERIAL_BEGIN(aiboost);
212         val = acpi_aiboost_get_value(acpi_get_handle(dev), "RTMP",function );
213         error = sysctl_handle_int(oidp, &val, 0 , req);
214         ACPI_SERIAL_END(aiboost);
215         
216         return 0;
217 }
218
219 static int acpi_aiboost_volt_sysctl(SYSCTL_HANDLER_ARGS)
220 {
221         device_t dev = arg1;
222         int function = oidp->oid_arg2;
223         int error = 0, val;
224         ACPI_SERIAL_BEGIN(aiboost);
225         val = acpi_aiboost_get_value(acpi_get_handle(dev), "RVLT", function);
226         error = sysctl_handle_int(oidp, &val, 0 , req);
227         ACPI_SERIAL_END(aiboost);
228         
229         return 0;
230 }
231
232 static int acpi_aiboost_fan_sysctl(SYSCTL_HANDLER_ARGS)
233 {
234         device_t dev = arg1;
235         int function = oidp->oid_arg2;
236         int error = 0, val;
237         ACPI_SERIAL_BEGIN(aiboost);
238         val = acpi_aiboost_get_value(acpi_get_handle(dev), "RFAN", function);
239         error = sysctl_handle_int(oidp, &val, 0 , req);
240         ACPI_SERIAL_END(aiboost);
241         
242         return 0;
243 }
244
245 static int
246 acpi_aiboost_probe(device_t dev)
247 {
248         int             ret = ENXIO;
249
250         if (ACPI_ID_PROBE(device_get_parent(dev), dev, abs_id)) {
251                 device_set_desc(dev, "ASUStek AIBOOSTER");
252                 ret = 0;
253         }
254         return (ret);
255 }
256
257 static int
258 acpi_aiboost_attach(device_t dev)
259 {
260         struct acpi_aiboost_softc *sc;
261         char nambuf[]="tempXXX";
262         int i;
263
264         sc = device_get_softc(dev);
265         if(ACPI_FAILURE(acpi_aiboost_getcomponent(dev, "TSIF", &sc->temp)))
266                 goto error;
267         for(i= 0; i < sc->temp->num; i++){
268                 sprintf(nambuf,"temp%d", i);
269                 SYSCTL_ADD_PROC(device_get_sysctl_ctx(dev),
270                                 SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
271                                 OID_AUTO, nambuf,
272                                 CTLTYPE_INT|CTLFLAG_RD, dev, 
273                                 sc->temp->elem[i].id,
274                                 acpi_aiboost_temp_sysctl,
275                                 "I", sc->temp->elem[i].desc);
276         }
277         if(ACPI_FAILURE(acpi_aiboost_getcomponent(dev, "VSIF", &sc->volt)))
278                 goto error;
279
280         for(i= 0; i < sc->volt->num; i++){
281                 sprintf(nambuf,"volt%d", i);
282                 SYSCTL_ADD_PROC(device_get_sysctl_ctx(dev),
283                                 SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
284                                 OID_AUTO, nambuf,
285                                 CTLTYPE_INT|CTLFLAG_RD, dev, 
286                                 sc->volt->elem[i].id,
287                                 acpi_aiboost_volt_sysctl,
288                                 "I", sc->volt->elem[i].desc);
289         }
290
291         if(ACPI_FAILURE(acpi_aiboost_getcomponent(dev, "FSIF", &sc->fan)))
292                 goto error;
293
294         for(i= 0; i < sc->fan->num; i++){
295                 sprintf(nambuf,"fan%d", i);
296                 SYSCTL_ADD_PROC(device_get_sysctl_ctx(dev),
297                                 SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
298                                 OID_AUTO, nambuf,
299                                 CTLTYPE_INT|CTLFLAG_RD, dev, 
300                                 sc->fan->elem[i].id,
301                                 acpi_aiboost_fan_sysctl,
302                                 "I", sc->fan->elem[i].desc);
303         }
304
305         
306         return (0);
307  error:
308         return EINVAL;
309 }
310
311 static int 
312 acpi_aiboost_detach(device_t dev)
313 {
314         struct acpi_aiboost_softc *sc = device_get_softc(dev);
315
316         if(sc->temp)
317                 free(sc->temp, M_DEVBUF);
318         if(sc->volt)
319                 free(sc->volt, M_DEVBUF);
320         if(sc->fan)
321                 free(sc->fan, M_DEVBUF);
322         return (0);
323 }
324
325 #if 0
326 static int
327 acpi_aiboost_suspend(device_t dev)
328 {
329         struct acpi_aiboost_softc *sc = device_get_softc(dev);
330         return (0);
331 }
332
333 static int
334 acpi_aiboost_resume(device_t dev)
335 {
336         return (0);
337 }
338 #endif