This source file includes following definitions.
- acpibat_match
- acpibat_attach
- acpibat_monitor
- acpibat_refresh
- acpibat_getbif
- acpibat_getbst
- acpibat_notify
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 #include <sys/param.h>
19 #include <sys/proc.h>
20 #include <sys/systm.h>
21 #include <sys/device.h>
22 #include <sys/malloc.h>
23 #include <sys/sensors.h>
24
25 #include <machine/bus.h>
26
27 #include <dev/acpi/acpireg.h>
28 #include <dev/acpi/acpivar.h>
29 #include <dev/acpi/acpidev.h>
30 #include <dev/acpi/amltypes.h>
31 #include <dev/acpi/dsdt.h>
32
33 int acpibat_match(struct device *, void *, void *);
34 void acpibat_attach(struct device *, struct device *, void *);
35
36 struct cfattach acpibat_ca = {
37 sizeof(struct acpibat_softc), acpibat_match, acpibat_attach
38 };
39
40 struct cfdriver acpibat_cd = {
41 NULL, "acpibat", DV_DULL
42 };
43
44 void acpibat_monitor(struct acpibat_softc *);
45 void acpibat_refresh(void *);
46 int acpibat_getbif(struct acpibat_softc *);
47 int acpibat_getbst(struct acpibat_softc *);
48 int acpibat_notify(struct aml_node *, int, void *);
49
50 int
51 acpibat_match(struct device *parent, void *match, void *aux)
52 {
53 struct acpi_attach_args *aa = aux;
54 struct cfdata *cf = match;
55
56
57 if (aa->aaa_name == NULL ||
58 strcmp(aa->aaa_name, cf->cf_driver->cd_name) != 0 ||
59 aa->aaa_table != NULL)
60 return (0);
61
62 return (1);
63 }
64
65 void
66 acpibat_attach(struct device *parent, struct device *self, void *aux)
67 {
68 struct acpibat_softc *sc = (struct acpibat_softc *)self;
69 struct acpi_attach_args *aa = aux;
70 struct aml_value res;
71
72 sc->sc_acpi = (struct acpi_softc *)parent;
73 sc->sc_devnode = aa->aaa_node->child;
74
75 if (aml_evalname(sc->sc_acpi, sc->sc_devnode, "_STA", 0, NULL, &res)) {
76 dnprintf(10, "%s: no _STA\n", DEVNAME(sc));
77 return;
78 }
79
80 if ((sc->sc_bat_present = aml_val2int(&res) & STA_BATTERY) != 0) {
81 acpibat_getbif(sc);
82 acpibat_getbst(sc);
83 printf(": %s: model: %s serial: %s type: %s oem: %s\n",
84 sc->sc_devnode->parent->name,
85 sc->sc_bif.bif_model,
86 sc->sc_bif.bif_serial,
87 sc->sc_bif.bif_type,
88 sc->sc_bif.bif_oem);
89 } else
90 printf(": %s: not present\n", sc->sc_devnode->parent->name);
91
92 aml_freevalue(&res);
93
94
95 acpibat_monitor(sc);
96
97
98 acpibat_refresh(sc);
99
100 aml_register_notify(sc->sc_devnode->parent, aa->aaa_dev,
101 acpibat_notify, sc, ACPIDEV_POLL);
102 }
103
104 void
105 acpibat_monitor(struct acpibat_softc *sc)
106 {
107 int type;
108
109
110 strlcpy(sc->sc_sensdev.xname, DEVNAME(sc),
111 sizeof(sc->sc_sensdev.xname));
112
113 type = sc->sc_bif.bif_power_unit ? SENSOR_AMPHOUR : SENSOR_WATTHOUR;
114
115 strlcpy(sc->sc_sens[0].desc, "last full capacity",
116 sizeof(sc->sc_sens[0].desc));
117 sc->sc_sens[0].type = type;
118 sensor_attach(&sc->sc_sensdev, &sc->sc_sens[0]);
119 sc->sc_sens[0].value = sc->sc_bif.bif_last_capacity * 1000;
120
121 strlcpy(sc->sc_sens[1].desc, "warning capacity",
122 sizeof(sc->sc_sens[1].desc));
123 sc->sc_sens[1].type = type;
124 sensor_attach(&sc->sc_sensdev, &sc->sc_sens[1]);
125 sc->sc_sens[1].value = sc->sc_bif.bif_warning * 1000;
126
127 strlcpy(sc->sc_sens[2].desc, "low capacity",
128 sizeof(sc->sc_sens[2].desc));
129 sc->sc_sens[2].type = type;
130 sensor_attach(&sc->sc_sensdev, &sc->sc_sens[2]);
131 sc->sc_sens[2].value = sc->sc_bif.bif_low * 1000;
132
133 strlcpy(sc->sc_sens[3].desc, "voltage", sizeof(sc->sc_sens[3].desc));
134 sc->sc_sens[3].type = SENSOR_VOLTS_DC;
135 sensor_attach(&sc->sc_sensdev, &sc->sc_sens[3]);
136 sc->sc_sens[3].value = sc->sc_bif.bif_voltage * 1000;
137
138 strlcpy(sc->sc_sens[4].desc, "battery unknown",
139 sizeof(sc->sc_sens[4].desc));
140 sc->sc_sens[4].type = SENSOR_INTEGER;
141 sensor_attach(&sc->sc_sensdev, &sc->sc_sens[4]);
142 sc->sc_sens[4].value = sc->sc_bst.bst_state;
143
144 strlcpy(sc->sc_sens[5].desc, "rate", sizeof(sc->sc_sens[5].desc));
145 sc->sc_sens[5].type = SENSOR_INTEGER;
146 sensor_attach(&sc->sc_sensdev, &sc->sc_sens[5]);
147 sc->sc_sens[5].value = sc->sc_bst.bst_rate;
148
149 strlcpy(sc->sc_sens[6].desc, "remaining capacity",
150 sizeof(sc->sc_sens[6].desc));
151 sc->sc_sens[6].type = type;
152 sensor_attach(&sc->sc_sensdev, &sc->sc_sens[6]);
153 sc->sc_sens[6].value = sc->sc_bst.bst_capacity * 1000;
154
155 strlcpy(sc->sc_sens[7].desc, "current voltage",
156 sizeof(sc->sc_sens[7].desc));
157 sc->sc_sens[7].type = SENSOR_VOLTS_DC;
158 sensor_attach(&sc->sc_sensdev, &sc->sc_sens[7]);
159 sc->sc_sens[7].value = sc->sc_bst.bst_voltage * 1000;
160
161 sensordev_install(&sc->sc_sensdev);
162 }
163
164 void
165 acpibat_refresh(void *arg)
166 {
167 struct acpibat_softc *sc = arg;
168 int i;
169
170 dnprintf(30, "%s: %s: refresh\n", DEVNAME(sc),
171 sc->sc_devnode->parent->name);
172
173 if (!sc->sc_bat_present) {
174 for (i = 0; i < 8; i++) {
175 sc->sc_sens[i].value = 0;
176 sc->sc_sens[i].status = SENSOR_S_UNSPEC;
177 sc->sc_sens[i].flags = SENSOR_FINVALID;
178 }
179
180 strlcpy(sc->sc_sens[4].desc, "battery removed",
181 sizeof(sc->sc_sens[4].desc));
182 return;
183 }
184
185
186
187
188
189 acpibat_getbif(sc);
190 acpibat_getbst(sc);
191
192
193 if (sc->sc_bif.bif_last_capacity == BIF_UNKNOWN) {
194 sc->sc_sens[0].value = 0;
195 sc->sc_sens[0].status = SENSOR_S_UNKNOWN;
196 sc->sc_sens[0].flags = SENSOR_FUNKNOWN;
197 } else {
198 sc->sc_sens[0].value = sc->sc_bif.bif_last_capacity * 1000;
199 sc->sc_sens[0].status = SENSOR_S_UNSPEC;
200 sc->sc_sens[0].flags = 0;
201 }
202 sc->sc_sens[1].value = sc->sc_bif.bif_warning * 1000;
203 sc->sc_sens[1].flags = 0;
204 sc->sc_sens[2].value = sc->sc_bif.bif_low * 1000;
205 sc->sc_sens[2].flags = 0;
206 if (sc->sc_bif.bif_voltage == BIF_UNKNOWN) {
207 sc->sc_sens[3].value = 0;
208 sc->sc_sens[3].status = SENSOR_S_UNKNOWN;
209 sc->sc_sens[3].flags = SENSOR_FUNKNOWN;
210 } else {
211 sc->sc_sens[3].value = sc->sc_bif.bif_voltage * 1000;
212 sc->sc_sens[3].status = SENSOR_S_UNSPEC;
213 sc->sc_sens[3].flags = 0;
214 }
215
216
217 sc->sc_sens[4].status = SENSOR_S_OK;
218 sc->sc_sens[4].flags = 0;
219 if (sc->sc_bif.bif_last_capacity == BIF_UNKNOWN ||
220 sc->sc_bst.bst_capacity == BST_UNKNOWN) {
221 sc->sc_sens[4].status = SENSOR_S_UNKNOWN;
222 sc->sc_sens[4].flags = SENSOR_FUNKNOWN;
223 strlcpy(sc->sc_sens[4].desc, "battery unknown",
224 sizeof(sc->sc_sens[4].desc));
225 } else if (sc->sc_bst.bst_capacity >= sc->sc_bif.bif_last_capacity)
226 strlcpy(sc->sc_sens[4].desc, "battery full",
227 sizeof(sc->sc_sens[4].desc));
228 else if (sc->sc_bst.bst_state & BST_DISCHARGE)
229 strlcpy(sc->sc_sens[4].desc, "battery discharging",
230 sizeof(sc->sc_sens[4].desc));
231 else if (sc->sc_bst.bst_state & BST_CHARGE)
232 strlcpy(sc->sc_sens[4].desc, "battery charging",
233 sizeof(sc->sc_sens[4].desc));
234 else if (sc->sc_bst.bst_state & BST_CRITICAL) {
235 strlcpy(sc->sc_sens[4].desc, "battery critical",
236 sizeof(sc->sc_sens[4].desc));
237 sc->sc_sens[4].status = SENSOR_S_CRIT;
238 } else
239 strlcpy(sc->sc_sens[4].desc, "battery idle",
240 sizeof(sc->sc_sens[4].desc));
241 sc->sc_sens[4].value = sc->sc_bst.bst_state;
242
243 if (sc->sc_bst.bst_rate == BST_UNKNOWN) {
244 sc->sc_sens[5].value = 0;
245 sc->sc_sens[5].status = SENSOR_S_UNKNOWN;
246 sc->sc_sens[5].flags = SENSOR_FUNKNOWN;
247 } else {
248 sc->sc_sens[5].value = sc->sc_bst.bst_rate;
249 sc->sc_sens[5].status = SENSOR_S_UNSPEC;
250 sc->sc_sens[5].flags = 0;
251 }
252
253 if (sc->sc_bst.bst_capacity == BST_UNKNOWN) {
254 sc->sc_sens[6].value = 0;
255 sc->sc_sens[6].status = SENSOR_S_UNKNOWN;
256 sc->sc_sens[6].flags = SENSOR_FUNKNOWN;
257 } else {
258 sc->sc_sens[6].value = sc->sc_bst.bst_capacity * 1000;
259 sc->sc_sens[6].flags = 0;
260
261 if (sc->sc_bst.bst_capacity < sc->sc_bif.bif_low)
262
263 sc->sc_sens[6].status = SENSOR_S_CRIT;
264 else if (sc->sc_bst.bst_capacity < sc->sc_bif.bif_warning)
265 sc->sc_sens[6].status = SENSOR_S_WARN;
266 else
267 sc->sc_sens[6].status = SENSOR_S_OK;
268 }
269
270 if(sc->sc_bst.bst_voltage == BST_UNKNOWN) {
271 sc->sc_sens[7].value = 0;
272 sc->sc_sens[7].status = SENSOR_S_UNKNOWN;
273 sc->sc_sens[7].flags = SENSOR_FUNKNOWN;
274 } else {
275 sc->sc_sens[7].value = sc->sc_bst.bst_voltage * 1000;
276 sc->sc_sens[7].status = SENSOR_S_UNSPEC;
277 sc->sc_sens[7].flags = 0;
278 }
279 }
280
281 int
282 acpibat_getbif(struct acpibat_softc *sc)
283 {
284 struct aml_value res;
285 int rv = EINVAL;
286
287 if (aml_evalname(sc->sc_acpi, sc->sc_devnode, "_STA", 0, NULL, &res)) {
288 dnprintf(10, "%s: no _STA\n", DEVNAME(sc));
289 goto out;
290 }
291 aml_freevalue(&res);
292
293 if (aml_evalname(sc->sc_acpi, sc->sc_devnode, "_BIF", 0, NULL, &res)) {
294 dnprintf(10, "%s: no _BIF\n", DEVNAME(sc));
295 goto out;
296 }
297
298 if (res.length != 13) {
299 dnprintf(10, "%s: invalid _BIF, battery info not saved\n",
300 DEVNAME(sc));
301 goto out;
302 }
303
304 memset(&sc->sc_bif, 0, sizeof sc->sc_bif);
305 sc->sc_bif.bif_power_unit = aml_val2int(res.v_package[0]);
306 sc->sc_bif.bif_capacity = aml_val2int(res.v_package[1]);
307 sc->sc_bif.bif_last_capacity = aml_val2int(res.v_package[2]);
308 sc->sc_bif.bif_technology = aml_val2int(res.v_package[3]);
309 sc->sc_bif.bif_voltage = aml_val2int(res.v_package[4]);
310 sc->sc_bif.bif_warning = aml_val2int(res.v_package[5]);
311 sc->sc_bif.bif_low = aml_val2int(res.v_package[6]);
312 sc->sc_bif.bif_cap_granu1 = aml_val2int(res.v_package[7]);
313 sc->sc_bif.bif_cap_granu2 = aml_val2int(res.v_package[8]);
314
315 strlcpy(sc->sc_bif.bif_model, aml_strval(res.v_package[9]),
316 sizeof(sc->sc_bif.bif_model));
317 strlcpy(sc->sc_bif.bif_serial, aml_strval(res.v_package[10]),
318 sizeof(sc->sc_bif.bif_serial));
319 strlcpy(sc->sc_bif.bif_type, aml_strval(res.v_package[11]),
320 sizeof(sc->sc_bif.bif_type));
321 strlcpy(sc->sc_bif.bif_oem, aml_strval(res.v_package[12]),
322 sizeof(sc->sc_bif.bif_oem));
323
324 dnprintf(60, "power_unit: %u capacity: %u last_cap: %u tech: %u "
325 "volt: %u warn: %u low: %u gran1: %u gran2: %d model: %s "
326 "serial: %s type: %s oem: %s\n",
327 sc->sc_bif.bif_power_unit,
328 sc->sc_bif.bif_capacity,
329 sc->sc_bif.bif_last_capacity,
330 sc->sc_bif.bif_technology,
331 sc->sc_bif.bif_voltage,
332 sc->sc_bif.bif_warning,
333 sc->sc_bif.bif_low,
334 sc->sc_bif.bif_cap_granu1,
335 sc->sc_bif.bif_cap_granu2,
336 sc->sc_bif.bif_model,
337 sc->sc_bif.bif_serial,
338 sc->sc_bif.bif_type,
339 sc->sc_bif.bif_oem);
340
341 rv = 0;
342 out:
343 aml_freevalue(&res);
344 return (rv);
345 }
346
347 int
348 acpibat_getbst(struct acpibat_softc *sc)
349 {
350 struct aml_value res;
351 int rv = EINVAL;
352
353 if (aml_evalname(sc->sc_acpi, sc->sc_devnode, "_BST", 0, NULL, &res)) {
354 dnprintf(10, "%s: no _BST\n", DEVNAME(sc));
355 goto out;
356 }
357
358 if (res.length != 4) {
359 dnprintf(10, "%s: invalid _BST, battery status not saved\n",
360 DEVNAME(sc));
361 goto out;
362 }
363
364 sc->sc_bst.bst_state = aml_val2int(res.v_package[0]);
365 sc->sc_bst.bst_rate = aml_val2int(res.v_package[1]);
366 sc->sc_bst.bst_capacity = aml_val2int(res.v_package[2]);
367 sc->sc_bst.bst_voltage = aml_val2int(res.v_package[3]);
368
369 dnprintf(60, "state: %u rate: %u cap: %u volt: %u ",
370 sc->sc_bst.bst_state,
371 sc->sc_bst.bst_rate,
372 sc->sc_bst.bst_capacity,
373 sc->sc_bst.bst_voltage);
374
375 rv = 0;
376 out:
377 aml_freevalue(&res);
378 return (rv);
379 }
380
381
382
383
384
385
386
387
388
389
390 int
391 acpibat_notify(struct aml_node *node, int notify_type, void *arg)
392 {
393 struct acpibat_softc *sc = arg;
394
395 dnprintf(10, "acpibat_notify: %.2x %s\n", notify_type,
396 sc->sc_devnode->parent->name);
397
398 switch (notify_type) {
399 case 0x80:
400 if (!sc->sc_bat_present) {
401 printf("%s: %s: inserted\n", DEVNAME(sc),
402 sc->sc_devnode->parent->name);
403 sc->sc_bat_present = 1;
404 }
405 break;
406 case 0x81:
407
408 if (sc->sc_bat_present) {
409 printf("%s: %s: removed\n", DEVNAME(sc),
410 sc->sc_devnode->parent->name);
411 sc->sc_bat_present = 0;
412 }
413 break;
414 default:
415 break;
416 }
417
418 acpibat_refresh(sc);
419
420 return (0);
421 }