xref: /freebsd/sys/dev/acpi_support/atk0110.c (revision bbe4a97d4176c971ffae2903a50e7f22fd9bde56)
1*bbe4a97dSRui Paulo /*	$NetBSD: atk0110.c,v 1.4 2010/02/11 06:54:57 cnst Exp $	*/
2*bbe4a97dSRui Paulo /*	$OpenBSD: atk0110.c,v 1.1 2009/07/23 01:38:16 cnst Exp $	*/
3*bbe4a97dSRui Paulo 
4*bbe4a97dSRui Paulo /*
5*bbe4a97dSRui Paulo  * Copyright (c) 2009, 2010 Constantine A. Murenin <cnst++@FreeBSD.org>
6*bbe4a97dSRui Paulo  *
7*bbe4a97dSRui Paulo  * Permission to use, copy, modify, and distribute this software for any
8*bbe4a97dSRui Paulo  * purpose with or without fee is hereby granted, provided that the above
9*bbe4a97dSRui Paulo  * copyright notice and this permission notice appear in all copies.
10*bbe4a97dSRui Paulo  *
11*bbe4a97dSRui Paulo  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
12*bbe4a97dSRui Paulo  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13*bbe4a97dSRui Paulo  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
14*bbe4a97dSRui Paulo  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15*bbe4a97dSRui Paulo  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16*bbe4a97dSRui Paulo  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
17*bbe4a97dSRui Paulo  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18*bbe4a97dSRui Paulo  */
19*bbe4a97dSRui Paulo 
20*bbe4a97dSRui Paulo #include <sys/cdefs.h>
21*bbe4a97dSRui Paulo __FBSDID("$FreeBSD$");
22*bbe4a97dSRui Paulo 
23*bbe4a97dSRui Paulo #include <machine/_inttypes.h>
24*bbe4a97dSRui Paulo #include <sys/param.h>
25*bbe4a97dSRui Paulo #include <sys/systm.h>
26*bbe4a97dSRui Paulo #include <sys/kernel.h>
27*bbe4a97dSRui Paulo #include <sys/bus.h>
28*bbe4a97dSRui Paulo #include <sys/module.h>
29*bbe4a97dSRui Paulo #include <sys/malloc.h>
30*bbe4a97dSRui Paulo #include <sys/sysctl.h>
31*bbe4a97dSRui Paulo 
32*bbe4a97dSRui Paulo #include <contrib/dev/acpica/include/acpi.h>
33*bbe4a97dSRui Paulo #include <dev/acpica/acpivar.h>
34*bbe4a97dSRui Paulo 
35*bbe4a97dSRui Paulo /*
36*bbe4a97dSRui Paulo  * ASUSTeK AI Booster (ACPI ASOC ATK0110).
37*bbe4a97dSRui Paulo  *
38*bbe4a97dSRui Paulo  * This code was originally written for OpenBSD after the techniques
39*bbe4a97dSRui Paulo  * described in the Linux's asus_atk0110.c and FreeBSD's Takanori Watanabe's
40*bbe4a97dSRui Paulo  * acpi_aiboost.c were verified to be accurate on the actual hardware kindly
41*bbe4a97dSRui Paulo  * provided by Sam Fourman Jr.  It was subsequently ported from OpenBSD to
42*bbe4a97dSRui Paulo  * DragonFly BSD, to NetBSD's sysmon_envsys(9) and to FreeBSD's sysctl(9).
43*bbe4a97dSRui Paulo  *
44*bbe4a97dSRui Paulo  *				  -- Constantine A. Murenin <http://cnst.su/>
45*bbe4a97dSRui Paulo  */
46*bbe4a97dSRui Paulo 
47*bbe4a97dSRui Paulo #define _COMPONENT	ACPI_OEM
48*bbe4a97dSRui Paulo ACPI_MODULE_NAME("aibs");
49*bbe4a97dSRui Paulo ACPI_SERIAL_DECL(aibs, "aibs");
50*bbe4a97dSRui Paulo 
51*bbe4a97dSRui Paulo #define AIBS_MORE_SENSORS
52*bbe4a97dSRui Paulo #define AIBS_VERBOSE
53*bbe4a97dSRui Paulo 
54*bbe4a97dSRui Paulo enum aibs_type {
55*bbe4a97dSRui Paulo 	AIBS_VOLT,
56*bbe4a97dSRui Paulo 	AIBS_TEMP,
57*bbe4a97dSRui Paulo 	AIBS_FAN
58*bbe4a97dSRui Paulo };
59*bbe4a97dSRui Paulo 
60*bbe4a97dSRui Paulo struct aibs_sensor {
61*bbe4a97dSRui Paulo 	ACPI_INTEGER	v;
62*bbe4a97dSRui Paulo 	ACPI_INTEGER	i;
63*bbe4a97dSRui Paulo 	ACPI_INTEGER	l;
64*bbe4a97dSRui Paulo 	ACPI_INTEGER	h;
65*bbe4a97dSRui Paulo 	enum aibs_type	t;
66*bbe4a97dSRui Paulo };
67*bbe4a97dSRui Paulo 
68*bbe4a97dSRui Paulo struct aibs_softc {
69*bbe4a97dSRui Paulo 	struct device		*sc_dev;
70*bbe4a97dSRui Paulo 	ACPI_HANDLE		sc_ah;
71*bbe4a97dSRui Paulo 
72*bbe4a97dSRui Paulo 	struct aibs_sensor	*sc_asens_volt;
73*bbe4a97dSRui Paulo 	struct aibs_sensor	*sc_asens_temp;
74*bbe4a97dSRui Paulo 	struct aibs_sensor	*sc_asens_fan;
75*bbe4a97dSRui Paulo };
76*bbe4a97dSRui Paulo 
77*bbe4a97dSRui Paulo static int aibs_probe(device_t);
78*bbe4a97dSRui Paulo static int aibs_attach(device_t);
79*bbe4a97dSRui Paulo static int aibs_detach(device_t);
80*bbe4a97dSRui Paulo static int aibs_sysctl(SYSCTL_HANDLER_ARGS);
81*bbe4a97dSRui Paulo 
82*bbe4a97dSRui Paulo static void aibs_attach_sif(struct aibs_softc *, enum aibs_type);
83*bbe4a97dSRui Paulo 
84*bbe4a97dSRui Paulo static device_method_t aibs_methods[] = {
85*bbe4a97dSRui Paulo 	DEVMETHOD(device_probe,		aibs_probe),
86*bbe4a97dSRui Paulo 	DEVMETHOD(device_attach,	aibs_attach),
87*bbe4a97dSRui Paulo 	DEVMETHOD(device_detach,	aibs_detach),
88*bbe4a97dSRui Paulo 	{ NULL, NULL }
89*bbe4a97dSRui Paulo };
90*bbe4a97dSRui Paulo 
91*bbe4a97dSRui Paulo static driver_t aibs_driver = {
92*bbe4a97dSRui Paulo 	"aibs",
93*bbe4a97dSRui Paulo 	aibs_methods,
94*bbe4a97dSRui Paulo 	sizeof(struct aibs_softc)
95*bbe4a97dSRui Paulo };
96*bbe4a97dSRui Paulo 
97*bbe4a97dSRui Paulo static devclass_t aibs_devclass;
98*bbe4a97dSRui Paulo 
99*bbe4a97dSRui Paulo DRIVER_MODULE(aibs, acpi, aibs_driver, aibs_devclass, NULL, NULL);
100*bbe4a97dSRui Paulo 
101*bbe4a97dSRui Paulo 
102*bbe4a97dSRui Paulo static char* aibs_hids[] = {
103*bbe4a97dSRui Paulo 	"ATK0110",
104*bbe4a97dSRui Paulo 	NULL
105*bbe4a97dSRui Paulo };
106*bbe4a97dSRui Paulo 
107*bbe4a97dSRui Paulo static int
108*bbe4a97dSRui Paulo aibs_probe(device_t dev)
109*bbe4a97dSRui Paulo {
110*bbe4a97dSRui Paulo 	if (acpi_disabled("aibs") ||
111*bbe4a97dSRui Paulo 	    ACPI_ID_PROBE(device_get_parent(dev), dev, aibs_hids) == NULL)
112*bbe4a97dSRui Paulo 		return ENXIO;
113*bbe4a97dSRui Paulo 
114*bbe4a97dSRui Paulo 	device_set_desc(dev, "ASUSTeK AI Booster (ACPI ASOC ATK0110)");
115*bbe4a97dSRui Paulo 	return 0;
116*bbe4a97dSRui Paulo }
117*bbe4a97dSRui Paulo 
118*bbe4a97dSRui Paulo static int
119*bbe4a97dSRui Paulo aibs_attach(device_t dev)
120*bbe4a97dSRui Paulo {
121*bbe4a97dSRui Paulo 	struct aibs_softc *sc = device_get_softc(dev);
122*bbe4a97dSRui Paulo 
123*bbe4a97dSRui Paulo 	sc->sc_dev = dev;
124*bbe4a97dSRui Paulo 	sc->sc_ah = acpi_get_handle(dev);
125*bbe4a97dSRui Paulo 
126*bbe4a97dSRui Paulo 	aibs_attach_sif(sc, AIBS_VOLT);
127*bbe4a97dSRui Paulo 	aibs_attach_sif(sc, AIBS_TEMP);
128*bbe4a97dSRui Paulo 	aibs_attach_sif(sc, AIBS_FAN);
129*bbe4a97dSRui Paulo 
130*bbe4a97dSRui Paulo 	return 0;
131*bbe4a97dSRui Paulo }
132*bbe4a97dSRui Paulo 
133*bbe4a97dSRui Paulo static void
134*bbe4a97dSRui Paulo aibs_attach_sif(struct aibs_softc *sc, enum aibs_type st)
135*bbe4a97dSRui Paulo {
136*bbe4a97dSRui Paulo 	ACPI_STATUS		s;
137*bbe4a97dSRui Paulo 	ACPI_BUFFER		b;
138*bbe4a97dSRui Paulo 	ACPI_OBJECT		*bp, *o;
139*bbe4a97dSRui Paulo 	int			i, n;
140*bbe4a97dSRui Paulo 	const char		*node;
141*bbe4a97dSRui Paulo 	char			name[] = "?SIF";
142*bbe4a97dSRui Paulo 	struct aibs_sensor	*as;
143*bbe4a97dSRui Paulo 	struct sysctl_oid	*so;
144*bbe4a97dSRui Paulo 
145*bbe4a97dSRui Paulo 	switch (st) {
146*bbe4a97dSRui Paulo 	case AIBS_VOLT:
147*bbe4a97dSRui Paulo 		node = "volt";
148*bbe4a97dSRui Paulo 		name[0] = 'V';
149*bbe4a97dSRui Paulo 		break;
150*bbe4a97dSRui Paulo 	case AIBS_TEMP:
151*bbe4a97dSRui Paulo 		node = "temp";
152*bbe4a97dSRui Paulo 		name[0] = 'T';
153*bbe4a97dSRui Paulo 		break;
154*bbe4a97dSRui Paulo 	case AIBS_FAN:
155*bbe4a97dSRui Paulo 		node = "fan";
156*bbe4a97dSRui Paulo 		name[0] = 'F';
157*bbe4a97dSRui Paulo 		break;
158*bbe4a97dSRui Paulo 	default:
159*bbe4a97dSRui Paulo 		return;
160*bbe4a97dSRui Paulo 	}
161*bbe4a97dSRui Paulo 
162*bbe4a97dSRui Paulo 	b.Length = ACPI_ALLOCATE_BUFFER;
163*bbe4a97dSRui Paulo 	s = AcpiEvaluateObjectTyped(sc->sc_ah, name, NULL, &b,
164*bbe4a97dSRui Paulo 	    ACPI_TYPE_PACKAGE);
165*bbe4a97dSRui Paulo 	if (ACPI_FAILURE(s)) {
166*bbe4a97dSRui Paulo 		device_printf(sc->sc_dev, "%s not found\n", name);
167*bbe4a97dSRui Paulo 		return;
168*bbe4a97dSRui Paulo 	}
169*bbe4a97dSRui Paulo 
170*bbe4a97dSRui Paulo 	bp = b.Pointer;
171*bbe4a97dSRui Paulo 	o = bp->Package.Elements;
172*bbe4a97dSRui Paulo 	if (o[0].Type != ACPI_TYPE_INTEGER) {
173*bbe4a97dSRui Paulo 		device_printf(sc->sc_dev, "%s[0]: invalid type\n", name);
174*bbe4a97dSRui Paulo 		AcpiOsFree(b.Pointer);
175*bbe4a97dSRui Paulo 		return;
176*bbe4a97dSRui Paulo 	}
177*bbe4a97dSRui Paulo 
178*bbe4a97dSRui Paulo 	n = o[0].Integer.Value;
179*bbe4a97dSRui Paulo 	if (bp->Package.Count - 1 < n) {
180*bbe4a97dSRui Paulo 		device_printf(sc->sc_dev, "%s: invalid package\n", name);
181*bbe4a97dSRui Paulo 		AcpiOsFree(b.Pointer);
182*bbe4a97dSRui Paulo 		return;
183*bbe4a97dSRui Paulo 	} else if (bp->Package.Count - 1 > n) {
184*bbe4a97dSRui Paulo 		int on = n;
185*bbe4a97dSRui Paulo 
186*bbe4a97dSRui Paulo #ifdef AIBS_MORE_SENSORS
187*bbe4a97dSRui Paulo 		n = bp->Package.Count - 1;
188*bbe4a97dSRui Paulo #endif
189*bbe4a97dSRui Paulo 		device_printf(sc->sc_dev, "%s: malformed package: %i/%i"
190*bbe4a97dSRui Paulo 		    ", assume %i\n", name, on, bp->Package.Count - 1, n);
191*bbe4a97dSRui Paulo 	}
192*bbe4a97dSRui Paulo 	if (n < 1) {
193*bbe4a97dSRui Paulo 		device_printf(sc->sc_dev, "%s: no members in the package\n",
194*bbe4a97dSRui Paulo 		    name);
195*bbe4a97dSRui Paulo 		AcpiOsFree(b.Pointer);
196*bbe4a97dSRui Paulo 		return;
197*bbe4a97dSRui Paulo 	}
198*bbe4a97dSRui Paulo 
199*bbe4a97dSRui Paulo 	as = malloc(sizeof(*as) * n, M_DEVBUF, M_NOWAIT | M_ZERO);
200*bbe4a97dSRui Paulo 	if (as == NULL) {
201*bbe4a97dSRui Paulo 		device_printf(sc->sc_dev, "%s: malloc fail\n", name);
202*bbe4a97dSRui Paulo 		AcpiOsFree(b.Pointer);
203*bbe4a97dSRui Paulo 		return;
204*bbe4a97dSRui Paulo 	}
205*bbe4a97dSRui Paulo 	switch (st) {
206*bbe4a97dSRui Paulo 	case AIBS_VOLT:
207*bbe4a97dSRui Paulo 		sc->sc_asens_volt = as;
208*bbe4a97dSRui Paulo 		break;
209*bbe4a97dSRui Paulo 	case AIBS_TEMP:
210*bbe4a97dSRui Paulo 		sc->sc_asens_temp = as;
211*bbe4a97dSRui Paulo 		break;
212*bbe4a97dSRui Paulo 	case AIBS_FAN:
213*bbe4a97dSRui Paulo 		sc->sc_asens_fan = as;
214*bbe4a97dSRui Paulo 		break;
215*bbe4a97dSRui Paulo 	}
216*bbe4a97dSRui Paulo 
217*bbe4a97dSRui Paulo 	/* sysctl subtree for sensors of this type */
218*bbe4a97dSRui Paulo 	so = SYSCTL_ADD_NODE(device_get_sysctl_ctx(sc->sc_dev),
219*bbe4a97dSRui Paulo 	    SYSCTL_CHILDREN(device_get_sysctl_tree(sc->sc_dev)), st,
220*bbe4a97dSRui Paulo 	    node, CTLFLAG_RD, NULL, NULL);
221*bbe4a97dSRui Paulo 
222*bbe4a97dSRui Paulo 	for (i = 0, o++; i < n; i++, o++) {
223*bbe4a97dSRui Paulo 		ACPI_OBJECT	*oi;
224*bbe4a97dSRui Paulo 		char		si[3];
225*bbe4a97dSRui Paulo 		const char	*desc;
226*bbe4a97dSRui Paulo 
227*bbe4a97dSRui Paulo 		/* acpica5 automatically evaluates the referenced package */
228*bbe4a97dSRui Paulo 		if (o[0].Type != ACPI_TYPE_PACKAGE) {
229*bbe4a97dSRui Paulo 			device_printf(sc->sc_dev,
230*bbe4a97dSRui Paulo 			    "%s: %i: not a package: %i type\n",
231*bbe4a97dSRui Paulo 			    name, i, o[0].Type);
232*bbe4a97dSRui Paulo 			continue;
233*bbe4a97dSRui Paulo 		}
234*bbe4a97dSRui Paulo 		oi = o[0].Package.Elements;
235*bbe4a97dSRui Paulo 		if (o[0].Package.Count != 5 ||
236*bbe4a97dSRui Paulo 		    oi[0].Type != ACPI_TYPE_INTEGER ||
237*bbe4a97dSRui Paulo 		    oi[1].Type != ACPI_TYPE_STRING ||
238*bbe4a97dSRui Paulo 		    oi[2].Type != ACPI_TYPE_INTEGER ||
239*bbe4a97dSRui Paulo 		    oi[3].Type != ACPI_TYPE_INTEGER ||
240*bbe4a97dSRui Paulo 		    oi[4].Type != ACPI_TYPE_INTEGER) {
241*bbe4a97dSRui Paulo 			device_printf(sc->sc_dev,
242*bbe4a97dSRui Paulo 			    "%s: %i: invalid package\n",
243*bbe4a97dSRui Paulo 			    name, i);
244*bbe4a97dSRui Paulo 			continue;
245*bbe4a97dSRui Paulo 		}
246*bbe4a97dSRui Paulo 		as[i].i = oi[0].Integer.Value;
247*bbe4a97dSRui Paulo 		desc = oi[1].String.Pointer;
248*bbe4a97dSRui Paulo 		as[i].l = oi[2].Integer.Value;
249*bbe4a97dSRui Paulo 		as[i].h = oi[3].Integer.Value;
250*bbe4a97dSRui Paulo 		as[i].t = st;
251*bbe4a97dSRui Paulo #ifdef AIBS_VERBOSE
252*bbe4a97dSRui Paulo 		device_printf(sc->sc_dev, "%c%i: "
253*bbe4a97dSRui Paulo 		    "0x%08"PRIx64" %20s %5"PRIi64" / %5"PRIi64"  "
254*bbe4a97dSRui Paulo 		    "0x%"PRIx64"\n",
255*bbe4a97dSRui Paulo 		    name[0], i,
256*bbe4a97dSRui Paulo 		    as[i].i, desc, (int64_t)as[i].l, (int64_t)as[i].h,
257*bbe4a97dSRui Paulo 		    oi[4].Integer.Value);
258*bbe4a97dSRui Paulo #endif
259*bbe4a97dSRui Paulo 		snprintf(si, sizeof(si), "%i", i);
260*bbe4a97dSRui Paulo 		SYSCTL_ADD_PROC(device_get_sysctl_ctx(sc->sc_dev),
261*bbe4a97dSRui Paulo 		    SYSCTL_CHILDREN(so), i, si, CTLTYPE_OPAQUE | CTLFLAG_RD,
262*bbe4a97dSRui Paulo 		    sc, st, aibs_sysctl, st == AIBS_TEMP ? "IK" : "I", desc);
263*bbe4a97dSRui Paulo 	}
264*bbe4a97dSRui Paulo 
265*bbe4a97dSRui Paulo 	AcpiOsFree(b.Pointer);
266*bbe4a97dSRui Paulo }
267*bbe4a97dSRui Paulo 
268*bbe4a97dSRui Paulo static int
269*bbe4a97dSRui Paulo aibs_detach(device_t dev)
270*bbe4a97dSRui Paulo {
271*bbe4a97dSRui Paulo 	struct aibs_softc	*sc = device_get_softc(dev);
272*bbe4a97dSRui Paulo 
273*bbe4a97dSRui Paulo 	if (sc->sc_asens_volt != NULL)
274*bbe4a97dSRui Paulo 		free(sc->sc_asens_volt, M_DEVBUF);
275*bbe4a97dSRui Paulo 	if (sc->sc_asens_temp != NULL)
276*bbe4a97dSRui Paulo 		free(sc->sc_asens_temp, M_DEVBUF);
277*bbe4a97dSRui Paulo 	if (sc->sc_asens_fan != NULL)
278*bbe4a97dSRui Paulo 		free(sc->sc_asens_fan, M_DEVBUF);
279*bbe4a97dSRui Paulo 	return 0;
280*bbe4a97dSRui Paulo }
281*bbe4a97dSRui Paulo 
282*bbe4a97dSRui Paulo #ifdef AIBS_VERBOSE
283*bbe4a97dSRui Paulo #define ddevice_printf(x...) device_printf(x)
284*bbe4a97dSRui Paulo #else
285*bbe4a97dSRui Paulo #define ddevice_printf(x...)
286*bbe4a97dSRui Paulo #endif
287*bbe4a97dSRui Paulo 
288*bbe4a97dSRui Paulo static int
289*bbe4a97dSRui Paulo aibs_sysctl(SYSCTL_HANDLER_ARGS)
290*bbe4a97dSRui Paulo {
291*bbe4a97dSRui Paulo 	struct aibs_softc	*sc = arg1;
292*bbe4a97dSRui Paulo 	enum aibs_type		st = arg2;
293*bbe4a97dSRui Paulo 	int			i = oidp->oid_number;
294*bbe4a97dSRui Paulo 	ACPI_STATUS		rs;
295*bbe4a97dSRui Paulo 	ACPI_OBJECT		p, *bp;
296*bbe4a97dSRui Paulo 	ACPI_OBJECT_LIST	mp;
297*bbe4a97dSRui Paulo 	ACPI_BUFFER		b;
298*bbe4a97dSRui Paulo 	char			*name;
299*bbe4a97dSRui Paulo 	struct aibs_sensor	*as;
300*bbe4a97dSRui Paulo 	ACPI_INTEGER		v, l, h;
301*bbe4a97dSRui Paulo 	int			so[3];
302*bbe4a97dSRui Paulo 
303*bbe4a97dSRui Paulo 	switch (st) {
304*bbe4a97dSRui Paulo 	case AIBS_VOLT:
305*bbe4a97dSRui Paulo 		name = "RVLT";
306*bbe4a97dSRui Paulo 		as = sc->sc_asens_volt;
307*bbe4a97dSRui Paulo 		break;
308*bbe4a97dSRui Paulo 	case AIBS_TEMP:
309*bbe4a97dSRui Paulo 		name = "RTMP";
310*bbe4a97dSRui Paulo 		as = sc->sc_asens_temp;
311*bbe4a97dSRui Paulo 		break;
312*bbe4a97dSRui Paulo 	case AIBS_FAN:
313*bbe4a97dSRui Paulo 		name = "RFAN";
314*bbe4a97dSRui Paulo 		as = sc->sc_asens_fan;
315*bbe4a97dSRui Paulo 		break;
316*bbe4a97dSRui Paulo 	default:
317*bbe4a97dSRui Paulo 		return ENOENT;
318*bbe4a97dSRui Paulo 	}
319*bbe4a97dSRui Paulo 	if (as == NULL)
320*bbe4a97dSRui Paulo 		return ENOENT;
321*bbe4a97dSRui Paulo 	l = as[i].l;
322*bbe4a97dSRui Paulo 	h = as[i].h;
323*bbe4a97dSRui Paulo 	p.Type = ACPI_TYPE_INTEGER;
324*bbe4a97dSRui Paulo 	p.Integer.Value = as[i].i;
325*bbe4a97dSRui Paulo 	mp.Count = 1;
326*bbe4a97dSRui Paulo 	mp.Pointer = &p;
327*bbe4a97dSRui Paulo 	b.Length = ACPI_ALLOCATE_BUFFER;
328*bbe4a97dSRui Paulo 	ACPI_SERIAL_BEGIN(aibs);
329*bbe4a97dSRui Paulo 	rs = AcpiEvaluateObjectTyped(sc->sc_ah, name, &mp, &b,
330*bbe4a97dSRui Paulo 	    ACPI_TYPE_INTEGER);
331*bbe4a97dSRui Paulo 	if (ACPI_FAILURE(rs)) {
332*bbe4a97dSRui Paulo 		ddevice_printf(sc->sc_dev,
333*bbe4a97dSRui Paulo 		    "%s: %i: evaluation failed\n",
334*bbe4a97dSRui Paulo 		    name, i);
335*bbe4a97dSRui Paulo 		ACPI_SERIAL_END(aibs);
336*bbe4a97dSRui Paulo 		return EIO;
337*bbe4a97dSRui Paulo 	}
338*bbe4a97dSRui Paulo 	bp = b.Pointer;
339*bbe4a97dSRui Paulo 	v = bp->Integer.Value;
340*bbe4a97dSRui Paulo 	AcpiOsFree(b.Pointer);
341*bbe4a97dSRui Paulo 	ACPI_SERIAL_END(aibs);
342*bbe4a97dSRui Paulo 
343*bbe4a97dSRui Paulo 	switch (st) {
344*bbe4a97dSRui Paulo 	case AIBS_VOLT:
345*bbe4a97dSRui Paulo 		break;
346*bbe4a97dSRui Paulo 	case AIBS_TEMP:
347*bbe4a97dSRui Paulo 		v += 2732;
348*bbe4a97dSRui Paulo 		l += 2732;
349*bbe4a97dSRui Paulo 		h += 2732;
350*bbe4a97dSRui Paulo 		break;
351*bbe4a97dSRui Paulo 	case AIBS_FAN:
352*bbe4a97dSRui Paulo 		break;
353*bbe4a97dSRui Paulo 	}
354*bbe4a97dSRui Paulo 	so[0] = v;
355*bbe4a97dSRui Paulo 	so[1] = l;
356*bbe4a97dSRui Paulo 	so[2] = h;
357*bbe4a97dSRui Paulo 	return sysctl_handle_opaque(oidp, &so, sizeof(so), req);
358*bbe4a97dSRui Paulo }
359