Line data Source code
1 : /* $OpenBSD: acpibat.c,v 1.67 2018/07/01 19:40:49 mlarkin Exp $ */
2 : /*
3 : * Copyright (c) 2005 Marco Peereboom <marco@openbsd.org>
4 : *
5 : * Permission to use, copy, modify, and distribute this software for any
6 : * purpose with or without fee is hereby granted, provided that the above
7 : * copyright notice and this permission notice appear in all copies.
8 : *
9 : * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10 : * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11 : * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12 : * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13 : * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14 : * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15 : * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16 : */
17 :
18 : #include <sys/param.h>
19 : #include <sys/systm.h>
20 : #include <sys/device.h>
21 : #include <sys/malloc.h>
22 : #include <sys/sensors.h>
23 :
24 : #include <machine/apmvar.h>
25 :
26 : #include <dev/acpi/acpireg.h>
27 : #include <dev/acpi/acpivar.h>
28 : #include <dev/acpi/acpidev.h>
29 : #include <dev/acpi/amltypes.h>
30 : #include <dev/acpi/dsdt.h>
31 :
32 : int acpibat_match(struct device *, void *, void *);
33 : void acpibat_attach(struct device *, struct device *, void *);
34 :
35 : struct cfattach acpibat_ca = {
36 : sizeof(struct acpibat_softc), acpibat_match, acpibat_attach
37 : };
38 :
39 : struct cfdriver acpibat_cd = {
40 : NULL, "acpibat", DV_DULL
41 : };
42 :
43 : const char *acpibat_hids[] = {
44 : ACPI_DEV_CMB,
45 : NULL
46 : };
47 :
48 : void acpibat_monitor(struct acpibat_softc *);
49 : void acpibat_refresh(void *);
50 : int acpibat_getbix(struct acpibat_softc *);
51 : int acpibat_getbst(struct acpibat_softc *);
52 : int acpibat_notify(struct aml_node *, int, void *);
53 :
54 : int
55 0 : acpibat_match(struct device *parent, void *match, void *aux)
56 : {
57 0 : struct acpi_attach_args *aa = aux;
58 0 : struct cfdata *cf = match;
59 :
60 0 : if (((struct acpi_softc *)parent)->sc_havesbs)
61 0 : return (0);
62 :
63 : /* sanity */
64 0 : return (acpi_matchhids(aa, acpibat_hids, cf->cf_driver->cd_name));
65 0 : }
66 :
67 : void
68 0 : acpibat_attach(struct device *parent, struct device *self, void *aux)
69 : {
70 0 : struct acpibat_softc *sc = (struct acpibat_softc *)self;
71 0 : struct acpi_attach_args *aa = aux;
72 0 : int64_t sta;
73 :
74 0 : sc->sc_acpi = (struct acpi_softc *)parent;
75 0 : sc->sc_devnode = aa->aaa_node;
76 :
77 0 : if (aml_evalinteger(sc->sc_acpi, sc->sc_devnode, "_STA", 0, NULL, &sta)) {
78 : dnprintf(10, "%s: no _STA\n", DEVNAME(sc));
79 0 : return;
80 : }
81 :
82 0 : if ((sta & STA_BATTERY) != 0) {
83 0 : sc->sc_bat_present = 1;
84 0 : acpibat_getbix(sc);
85 0 : acpibat_getbst(sc);
86 :
87 0 : printf(": %s", sc->sc_devnode->name);
88 0 : if (sc->sc_bix.bix_model[0])
89 0 : printf(" model \"%s\"", sc->sc_bix.bix_model);
90 0 : if (sc->sc_bix.bix_serial[0])
91 0 : printf(" serial %s", sc->sc_bix.bix_serial);
92 0 : if (sc->sc_bix.bix_type[0])
93 0 : printf(" type %s", sc->sc_bix.bix_type);
94 0 : if (sc->sc_bix.bix_oem[0])
95 0 : printf(" oem \"%s\"", sc->sc_bix.bix_oem);
96 :
97 0 : printf("\n");
98 0 : } else {
99 0 : sc->sc_bat_present = 0;
100 0 : printf(": %s not present\n", sc->sc_devnode->name);
101 : }
102 :
103 : /* create sensors */
104 0 : acpibat_monitor(sc);
105 :
106 : /* populate sensors */
107 0 : acpibat_refresh(sc);
108 :
109 0 : aml_register_notify(sc->sc_devnode, aa->aaa_dev,
110 : acpibat_notify, sc, ACPIDEV_POLL);
111 0 : }
112 :
113 : void
114 0 : acpibat_monitor(struct acpibat_softc *sc)
115 : {
116 : int type;
117 :
118 : /* assume _BIF/_BIX and _BST have been called */
119 0 : strlcpy(sc->sc_sensdev.xname, DEVNAME(sc),
120 : sizeof(sc->sc_sensdev.xname));
121 :
122 0 : type = sc->sc_bix.bix_power_unit ? SENSOR_AMPHOUR : SENSOR_WATTHOUR;
123 :
124 0 : strlcpy(sc->sc_sens[0].desc, "last full capacity",
125 : sizeof(sc->sc_sens[0].desc));
126 0 : sc->sc_sens[0].type = type;
127 0 : sensor_attach(&sc->sc_sensdev, &sc->sc_sens[0]);
128 0 : sc->sc_sens[0].value = sc->sc_bix.bix_last_capacity * 1000;
129 :
130 0 : strlcpy(sc->sc_sens[1].desc, "warning capacity",
131 : sizeof(sc->sc_sens[1].desc));
132 0 : sc->sc_sens[1].type = type;
133 0 : sensor_attach(&sc->sc_sensdev, &sc->sc_sens[1]);
134 0 : sc->sc_sens[1].value = sc->sc_bix.bix_warning * 1000;
135 :
136 0 : strlcpy(sc->sc_sens[2].desc, "low capacity",
137 : sizeof(sc->sc_sens[2].desc));
138 0 : sc->sc_sens[2].type = type;
139 0 : sensor_attach(&sc->sc_sensdev, &sc->sc_sens[2]);
140 0 : sc->sc_sens[2].value = sc->sc_bix.bix_low * 1000;
141 :
142 0 : strlcpy(sc->sc_sens[3].desc, "voltage", sizeof(sc->sc_sens[3].desc));
143 0 : sc->sc_sens[3].type = SENSOR_VOLTS_DC;
144 0 : sensor_attach(&sc->sc_sensdev, &sc->sc_sens[3]);
145 0 : sc->sc_sens[3].value = sc->sc_bix.bix_voltage * 1000;
146 :
147 0 : strlcpy(sc->sc_sens[4].desc, "battery unknown",
148 : sizeof(sc->sc_sens[4].desc));
149 0 : sc->sc_sens[4].type = SENSOR_INTEGER;
150 0 : sensor_attach(&sc->sc_sensdev, &sc->sc_sens[4]);
151 0 : sc->sc_sens[4].value = sc->sc_bst.bst_state;
152 :
153 0 : strlcpy(sc->sc_sens[5].desc, "rate", sizeof(sc->sc_sens[5].desc));
154 0 : sc->sc_sens[5].type =
155 0 : sc->sc_bix.bix_power_unit ? SENSOR_AMPS : SENSOR_WATTS;
156 0 : sensor_attach(&sc->sc_sensdev, &sc->sc_sens[5]);
157 0 : sc->sc_sens[5].value = sc->sc_bst.bst_rate * 1000;
158 :
159 0 : strlcpy(sc->sc_sens[6].desc, "remaining capacity",
160 : sizeof(sc->sc_sens[6].desc));
161 0 : sc->sc_sens[6].type = type;
162 0 : sensor_attach(&sc->sc_sensdev, &sc->sc_sens[6]);
163 0 : sc->sc_sens[6].value = sc->sc_bix.bix_capacity * 1000;
164 :
165 0 : strlcpy(sc->sc_sens[7].desc, "current voltage",
166 : sizeof(sc->sc_sens[7].desc));
167 0 : sc->sc_sens[7].type = SENSOR_VOLTS_DC;
168 0 : sensor_attach(&sc->sc_sensdev, &sc->sc_sens[7]);
169 0 : sc->sc_sens[7].value = sc->sc_bix.bix_voltage * 1000;
170 :
171 0 : strlcpy(sc->sc_sens[8].desc, "design capacity",
172 : sizeof(sc->sc_sens[8].desc));
173 0 : sc->sc_sens[8].type = type;
174 0 : sensor_attach(&sc->sc_sensdev, &sc->sc_sens[8]);
175 0 : sc->sc_sens[8].value = sc->sc_bix.bix_capacity * 1000;
176 :
177 0 : if (!sc->sc_use_bif) {
178 0 : strlcpy(sc->sc_sens[9].desc, "discharge cycles",
179 : sizeof(sc->sc_sens[9].desc));
180 0 : sc->sc_sens[9].type = SENSOR_INTEGER;
181 0 : sensor_attach(&sc->sc_sensdev, &sc->sc_sens[9]);
182 0 : sc->sc_sens[9].value = sc->sc_bix.bix_cycle_count;
183 0 : }
184 :
185 0 : sensordev_install(&sc->sc_sensdev);
186 0 : }
187 :
188 : void
189 0 : acpibat_refresh(void *arg)
190 : {
191 0 : struct acpibat_softc *sc = arg;
192 : int i;
193 :
194 : dnprintf(30, "%s: %s: refresh\n", DEVNAME(sc),
195 : sc->sc_devnode->name);
196 :
197 0 : if (!sc->sc_bat_present) {
198 0 : for (i = 0; i < nitems(sc->sc_sens); i++) {
199 0 : sc->sc_sens[i].value = 0;
200 0 : sc->sc_sens[i].status = SENSOR_S_UNSPEC;
201 0 : sc->sc_sens[i].flags = SENSOR_FINVALID;
202 : }
203 : /* override state */
204 0 : strlcpy(sc->sc_sens[4].desc, "battery removed",
205 : sizeof(sc->sc_sens[4].desc));
206 0 : return;
207 : }
208 :
209 : /* _BIF/_BIX values are static, sensor 0..3 */
210 0 : if (sc->sc_bix.bix_last_capacity == BIX_UNKNOWN) {
211 0 : sc->sc_sens[0].value = 0;
212 0 : sc->sc_sens[0].status = SENSOR_S_UNKNOWN;
213 0 : sc->sc_sens[0].flags = SENSOR_FUNKNOWN;
214 0 : } else {
215 0 : sc->sc_sens[0].value = sc->sc_bix.bix_last_capacity * 1000;
216 0 : sc->sc_sens[0].status = SENSOR_S_UNSPEC;
217 0 : sc->sc_sens[0].flags = 0;
218 : }
219 0 : sc->sc_sens[1].value = sc->sc_bix.bix_warning * 1000;
220 0 : sc->sc_sens[1].flags = 0;
221 0 : sc->sc_sens[2].value = sc->sc_bix.bix_low * 1000;
222 0 : sc->sc_sens[2].flags = 0;
223 0 : if (sc->sc_bix.bix_voltage == BIX_UNKNOWN) {
224 0 : sc->sc_sens[3].value = 0;
225 0 : sc->sc_sens[3].status = SENSOR_S_UNKNOWN;
226 0 : sc->sc_sens[3].flags = SENSOR_FUNKNOWN;
227 0 : } else {
228 0 : sc->sc_sens[3].value = sc->sc_bix.bix_voltage * 1000;
229 0 : sc->sc_sens[3].status = SENSOR_S_UNSPEC;
230 0 : sc->sc_sens[3].flags = 0;
231 : }
232 :
233 : /* _BST values are dynamic, sensor 4..7 */
234 0 : sc->sc_sens[4].status = SENSOR_S_OK;
235 0 : sc->sc_sens[4].flags = 0;
236 0 : if (sc->sc_bix.bix_last_capacity == BIX_UNKNOWN ||
237 0 : sc->sc_bst.bst_capacity == BST_UNKNOWN) {
238 0 : sc->sc_sens[4].status = SENSOR_S_UNKNOWN;
239 0 : sc->sc_sens[4].flags = SENSOR_FUNKNOWN;
240 0 : strlcpy(sc->sc_sens[4].desc, "battery unknown",
241 : sizeof(sc->sc_sens[4].desc));
242 0 : } else if (sc->sc_bst.bst_capacity >= sc->sc_bix.bix_last_capacity)
243 0 : strlcpy(sc->sc_sens[4].desc, "battery full",
244 : sizeof(sc->sc_sens[4].desc));
245 0 : else if (sc->sc_bst.bst_state & BST_DISCHARGE)
246 0 : strlcpy(sc->sc_sens[4].desc, "battery discharging",
247 : sizeof(sc->sc_sens[4].desc));
248 0 : else if (sc->sc_bst.bst_state & BST_CHARGE)
249 0 : strlcpy(sc->sc_sens[4].desc, "battery charging",
250 : sizeof(sc->sc_sens[4].desc));
251 0 : else if (sc->sc_bst.bst_state & BST_CRITICAL) {
252 0 : strlcpy(sc->sc_sens[4].desc, "battery critical",
253 : sizeof(sc->sc_sens[4].desc));
254 0 : sc->sc_sens[4].status = SENSOR_S_CRIT;
255 0 : } else
256 0 : strlcpy(sc->sc_sens[4].desc, "battery idle",
257 : sizeof(sc->sc_sens[4].desc));
258 0 : sc->sc_sens[4].value = sc->sc_bst.bst_state;
259 :
260 0 : if (sc->sc_bst.bst_rate == BST_UNKNOWN) {
261 0 : sc->sc_sens[5].value = 0;
262 0 : sc->sc_sens[5].status = SENSOR_S_UNKNOWN;
263 0 : sc->sc_sens[5].flags = SENSOR_FUNKNOWN;
264 0 : } else {
265 0 : sc->sc_sens[5].value = sc->sc_bst.bst_rate * 1000;
266 0 : sc->sc_sens[5].status = SENSOR_S_UNSPEC;
267 0 : sc->sc_sens[5].flags = 0;
268 : }
269 :
270 0 : if (sc->sc_bst.bst_capacity == BST_UNKNOWN) {
271 0 : sc->sc_sens[6].value = 0;
272 0 : sc->sc_sens[6].status = SENSOR_S_UNKNOWN;
273 0 : sc->sc_sens[6].flags = SENSOR_FUNKNOWN;
274 0 : } else {
275 0 : sc->sc_sens[6].value = sc->sc_bst.bst_capacity * 1000;
276 0 : sc->sc_sens[6].flags = 0;
277 :
278 0 : if (sc->sc_bst.bst_capacity < sc->sc_bix.bix_low)
279 : /* XXX we should shutdown the system */
280 0 : sc->sc_sens[6].status = SENSOR_S_CRIT;
281 0 : else if (sc->sc_bst.bst_capacity < sc->sc_bix.bix_warning)
282 0 : sc->sc_sens[6].status = SENSOR_S_WARN;
283 : else
284 0 : sc->sc_sens[6].status = SENSOR_S_OK;
285 : }
286 :
287 0 : if (sc->sc_bst.bst_voltage == BST_UNKNOWN) {
288 0 : sc->sc_sens[7].value = 0;
289 0 : sc->sc_sens[7].status = SENSOR_S_UNKNOWN;
290 0 : sc->sc_sens[7].flags = SENSOR_FUNKNOWN;
291 0 : } else {
292 0 : sc->sc_sens[7].value = sc->sc_bst.bst_voltage * 1000;
293 0 : sc->sc_sens[7].status = SENSOR_S_UNSPEC;
294 0 : sc->sc_sens[7].flags = 0;
295 : }
296 :
297 0 : if (sc->sc_bix.bix_capacity == BIX_UNKNOWN) {
298 0 : sc->sc_sens[8].value = 0;
299 0 : sc->sc_sens[8].status = SENSOR_S_UNKNOWN;
300 0 : sc->sc_sens[8].flags = SENSOR_FUNKNOWN;
301 0 : } else {
302 0 : sc->sc_sens[8].value = sc->sc_bix.bix_capacity * 1000;
303 0 : sc->sc_sens[8].status = SENSOR_S_UNSPEC;
304 0 : sc->sc_sens[8].flags = 0;
305 : }
306 :
307 0 : if (!sc->sc_use_bif) {
308 0 : if (sc->sc_bix.bix_capacity == BIX_UNKNOWN) {
309 0 : sc->sc_sens[9].value = 0;
310 0 : sc->sc_sens[9].status = SENSOR_S_UNKNOWN;
311 0 : sc->sc_sens[9].flags = SENSOR_FUNKNOWN;
312 0 : } else {
313 0 : sc->sc_sens[9].value = sc->sc_bix.bix_cycle_count;
314 0 : sc->sc_sens[9].status = SENSOR_S_UNSPEC;
315 0 : sc->sc_sens[9].flags = 0;
316 : }
317 : }
318 :
319 0 : acpi_record_event(sc->sc_acpi, APM_POWER_CHANGE);
320 0 : }
321 :
322 : int
323 0 : acpibat_getbix(struct acpibat_softc *sc)
324 : {
325 0 : struct aml_value res;
326 : int rv = EINVAL;
327 : int n = 0;
328 :
329 0 : if (!sc->sc_bat_present) {
330 0 : memset(&sc->sc_bix, 0, sizeof(sc->sc_bix));
331 0 : return (0);
332 : }
333 :
334 0 : sc->sc_use_bif = 1;
335 :
336 0 : if (aml_evalname(sc->sc_acpi, sc->sc_devnode, "_BIX", 0, NULL,
337 0 : &res) == 0) {
338 0 : if (res.length >= 20)
339 0 : sc->sc_use_bif = 0;
340 : else
341 : dnprintf(10, "%s: invalid _BIX (%d < 20)\n",
342 : DEVNAME(sc), res.length);
343 : }
344 :
345 0 : if (sc->sc_use_bif) {
346 0 : if (aml_evalname(sc->sc_acpi, sc->sc_devnode, "_BIF", 0, NULL,
347 : &res)) {
348 : dnprintf(10, "%s: no _BIX or _BIF\n", DEVNAME(sc));
349 : goto out;
350 : }
351 :
352 0 : if (res.length != 13) {
353 : dnprintf(10, "%s: invalid _BIF (%d != 13)\n",
354 : DEVNAME(sc), res.length);
355 : goto out;
356 : }
357 : }
358 :
359 0 : if (!sc->sc_use_bif)
360 0 : sc->sc_bix.bix_revision = aml_val2int(res.v_package[n++]);
361 :
362 0 : sc->sc_bix.bix_power_unit = aml_val2int(res.v_package[n++]);
363 0 : sc->sc_bix.bix_capacity = aml_val2int(res.v_package[n++]);
364 0 : sc->sc_bix.bix_last_capacity = aml_val2int(res.v_package[n++]);
365 0 : sc->sc_bix.bix_technology = aml_val2int(res.v_package[n++]);
366 0 : sc->sc_bix.bix_voltage = aml_val2int(res.v_package[n++]);
367 0 : sc->sc_bix.bix_warning = aml_val2int(res.v_package[n++]);
368 0 : sc->sc_bix.bix_low = aml_val2int(res.v_package[n++]);
369 :
370 0 : if (!sc->sc_use_bif) {
371 0 : sc->sc_bix.bix_cycle_count = aml_val2int(res.v_package[n++]);
372 0 : sc->sc_bix.bix_accuracy = aml_val2int(res.v_package[n++]);
373 0 : sc->sc_bix.bix_max_sample = aml_val2int(res.v_package[n++]);
374 0 : sc->sc_bix.bix_min_sample = aml_val2int(res.v_package[n++]);
375 0 : sc->sc_bix.bix_max_avg = aml_val2int(res.v_package[n++]);
376 0 : sc->sc_bix.bix_min_avg = aml_val2int(res.v_package[n++]);
377 0 : }
378 :
379 0 : sc->sc_bix.bix_cap_granu1 = aml_val2int(res.v_package[n++]);
380 0 : sc->sc_bix.bix_cap_granu2 = aml_val2int(res.v_package[n++]);
381 :
382 0 : strlcpy(sc->sc_bix.bix_model, aml_val_to_string(res.v_package[n++]),
383 : sizeof(sc->sc_bix.bix_model));
384 0 : strlcpy(sc->sc_bix.bix_serial, aml_val_to_string(res.v_package[n++]),
385 : sizeof(sc->sc_bix.bix_serial));
386 0 : strlcpy(sc->sc_bix.bix_type, aml_val_to_string(res.v_package[n++]),
387 : sizeof(sc->sc_bix.bix_type));
388 0 : strlcpy(sc->sc_bix.bix_oem, aml_val_to_string(res.v_package[n++]),
389 : sizeof(sc->sc_bix.bix_oem));
390 :
391 0 : if (!sc->sc_use_bif)
392 : dnprintf(60, "revision: %u ", sc->sc_bix.bix_revision);
393 :
394 : dnprintf(60, "power_unit: %u capacity: %u last_cap: %u "
395 : "tech: %u volt: %u warn: %u low: %u ",
396 : sc->sc_bix.bix_power_unit,
397 : sc->sc_bix.bix_capacity,
398 : sc->sc_bix.bix_last_capacity,
399 : sc->sc_bix.bix_technology,
400 : sc->sc_bix.bix_voltage,
401 : sc->sc_bix.bix_warning,
402 : sc->sc_bix.bix_low);
403 :
404 : if (!sc->sc_use_bif)
405 : dnprintf(60, "cycles: %u accuracy: %u max_sample: %u "
406 : "min_sample: %u max_avg: %u min_avg: %u ",
407 : sc->sc_bix.bix_cycle_count,
408 : sc->sc_bix.bix_accuracy,
409 : sc->sc_bix.bix_max_sample,
410 : sc->sc_bix.bix_min_sample,
411 : sc->sc_bix.bix_max_avg,
412 : sc->sc_bix.bix_min_avg);
413 :
414 : dnprintf(60, "gran1: %u gran2: %d model: %s serial: %s type: %s "
415 : "oem: %s\n",
416 : sc->sc_bix.bix_cap_granu1,
417 : sc->sc_bix.bix_cap_granu2,
418 : sc->sc_bix.bix_model,
419 : sc->sc_bix.bix_serial,
420 : sc->sc_bix.bix_type,
421 : sc->sc_bix.bix_oem);
422 :
423 0 : rv = 0;
424 : out:
425 0 : aml_freevalue(&res);
426 0 : return (rv);
427 0 : }
428 :
429 : int
430 0 : acpibat_getbst(struct acpibat_softc *sc)
431 : {
432 0 : struct aml_value res;
433 : int rv = EINVAL;
434 :
435 0 : if (!sc->sc_bat_present) {
436 0 : memset(&sc->sc_bst, 0, sizeof(sc->sc_bst));
437 0 : return (0);
438 : }
439 :
440 0 : if (aml_evalname(sc->sc_acpi, sc->sc_devnode, "_BST", 0, NULL, &res)) {
441 : dnprintf(10, "%s: no _BST\n", DEVNAME(sc));
442 : goto out;
443 : }
444 :
445 0 : if (res.length != 4) {
446 : dnprintf(10, "%s: invalid _BST, battery status not saved\n",
447 : DEVNAME(sc));
448 : goto out;
449 : }
450 :
451 0 : sc->sc_bst.bst_state = aml_val2int(res.v_package[0]);
452 0 : sc->sc_bst.bst_rate = aml_val2int(res.v_package[1]);
453 0 : sc->sc_bst.bst_capacity = aml_val2int(res.v_package[2]);
454 0 : sc->sc_bst.bst_voltage = aml_val2int(res.v_package[3]);
455 :
456 : dnprintf(60, "state: %u rate: %u cap: %u volt: %u ",
457 : sc->sc_bst.bst_state,
458 : sc->sc_bst.bst_rate,
459 : sc->sc_bst.bst_capacity,
460 : sc->sc_bst.bst_voltage);
461 :
462 0 : rv = 0;
463 : out:
464 0 : aml_freevalue(&res);
465 0 : return (rv);
466 0 : }
467 :
468 : /*
469 : * XXX it has been observed that some systems do not propagate battery
470 : * insertion events up to the driver. What seems to happen is that DSDT
471 : * does receive an interrupt however the originator bit is not set.
472 : * This seems to happen when one inserts a 100% full battery. Removal
473 : * of the power cord or insertion of a not 100% full battery breaks this
474 : * behavior and all events will then be sent upwards. Currently there
475 : * is no known work-around for it.
476 : */
477 :
478 : int
479 0 : acpibat_notify(struct aml_node *node, int notify_type, void *arg)
480 : {
481 0 : struct acpibat_softc *sc = arg;
482 0 : int64_t sta;
483 :
484 : dnprintf(10, "acpibat_notify: %.2x %s\n", notify_type,
485 : sc->sc_devnode->name);
486 :
487 : /* Check if installed state of battery has changed */
488 0 : if (aml_evalinteger(sc->sc_acpi, node, "_STA", 0, NULL, &sta) == 0) {
489 0 : if (sta & STA_BATTERY)
490 0 : sc->sc_bat_present = 1;
491 : else
492 0 : sc->sc_bat_present = 0;
493 : }
494 :
495 0 : switch (notify_type) {
496 : case 0x00: /* Poll sensors */
497 : case 0x80: /* _BST changed */
498 0 : acpibat_getbst(sc);
499 0 : break;
500 : case 0x81: /* _BIF/_BIX changed */
501 0 : acpibat_getbix(sc);
502 0 : break;
503 : default:
504 : break;
505 : }
506 :
507 0 : acpibat_refresh(sc);
508 :
509 0 : return (0);
510 0 : }
|