acpi_bat.c revision 1.14 1 1.14 explorer /* $NetBSD: acpi_bat.c,v 1.14 2002/12/31 05:26:56 explorer Exp $ */
2 1.1 sommerfe
3 1.1 sommerfe /*
4 1.1 sommerfe * Copyright 2001 Bill Sommerfeld.
5 1.1 sommerfe * All rights reserved.
6 1.1 sommerfe *
7 1.1 sommerfe * Redistribution and use in source and binary forms, with or without
8 1.1 sommerfe * modification, are permitted provided that the following conditions
9 1.1 sommerfe * are met:
10 1.1 sommerfe * 1. Redistributions of source code must retain the above copyright
11 1.1 sommerfe * notice, this list of conditions and the following disclaimer.
12 1.1 sommerfe * 2. Redistributions in binary form must reproduce the above copyright
13 1.1 sommerfe * notice, this list of conditions and the following disclaimer in the
14 1.1 sommerfe * documentation and/or other materials provided with the distribution.
15 1.1 sommerfe * 3. All advertising materials mentioning features or use of this software
16 1.1 sommerfe * must display the following acknowledgement:
17 1.1 sommerfe * This product includes software developed for the NetBSD Project by
18 1.1 sommerfe * Wasabi Systems, Inc.
19 1.1 sommerfe * 4. The name of Wasabi Systems, Inc. may not be used to endorse
20 1.1 sommerfe * or promote products derived from this software without specific prior
21 1.1 sommerfe * written permission.
22 1.1 sommerfe *
23 1.1 sommerfe * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND
24 1.1 sommerfe * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
25 1.1 sommerfe * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
26 1.1 sommerfe * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL WASABI SYSTEMS, INC
27 1.1 sommerfe * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
28 1.1 sommerfe * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
29 1.1 sommerfe * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
30 1.1 sommerfe * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
31 1.1 sommerfe * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
32 1.1 sommerfe * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
33 1.1 sommerfe * POSSIBILITY OF SUCH DAMAGE.
34 1.1 sommerfe */
35 1.1 sommerfe
36 1.13 explorer #if 0
37 1.1 sommerfe #define ACPI_BAT_DEBUG
38 1.13 explorer #endif
39 1.1 sommerfe
40 1.1 sommerfe /*
41 1.1 sommerfe * ACPI Battery Driver.
42 1.1 sommerfe *
43 1.1 sommerfe * ACPI defines two different battery device interfaces: "Control
44 1.1 sommerfe * Method" batteries, in which AML methods are defined in order to get
45 1.1 sommerfe * battery status and set battery alarm thresholds, and a "Smart
46 1.1 sommerfe * Battery" device, which is an SMbus device accessed through the ACPI
47 1.1 sommerfe * Embedded Controller device.
48 1.1 sommerfe *
49 1.1 sommerfe * This driver is for the "Control Method"-style battery only.
50 1.1 sommerfe */
51 1.1 sommerfe
52 1.1 sommerfe #include <sys/cdefs.h>
53 1.14 explorer __KERNEL_RCSID(0, "$NetBSD: acpi_bat.c,v 1.14 2002/12/31 05:26:56 explorer Exp $");
54 1.1 sommerfe
55 1.1 sommerfe #include <sys/param.h>
56 1.1 sommerfe #include <sys/systm.h>
57 1.1 sommerfe #include <sys/kernel.h> /* for hz */
58 1.1 sommerfe #include <sys/device.h>
59 1.1 sommerfe #include <sys/callout.h>
60 1.14 explorer #include <dev/sysmon/sysmonvar.h>
61 1.1 sommerfe
62 1.1 sommerfe #include <dev/acpi/acpica.h>
63 1.1 sommerfe #include <dev/acpi/acpireg.h>
64 1.1 sommerfe #include <dev/acpi/acpivar.h>
65 1.1 sommerfe
66 1.14 explorer /* sensor indexes */
67 1.14 explorer #define ACPIBAT_DCAPACITY 0
68 1.14 explorer #define ACPIBAT_LFCCAPACITY 1
69 1.14 explorer #define ACPIBAT_TECHNOLOGY 2
70 1.14 explorer #define ACPIBAT_DVOLTAGE 3
71 1.14 explorer #define ACPIBAT_WCAPACITY 4
72 1.14 explorer #define ACPIBAT_LCAPACITY 5
73 1.14 explorer #define ACPIBAT_VOLTAGE 6
74 1.14 explorer #define ACPIBAT_LOAD 7
75 1.14 explorer #define ACPIBAT_CAPACITY 8
76 1.14 explorer #define ACPIBAT_CHARGING 9
77 1.14 explorer #define ACPIBAT_DISCHARGING 10
78 1.14 explorer #define ACPIBAT_NSENSORS 11 /* number of sensors */
79 1.14 explorer
80 1.14 explorer const struct envsys_range acpibat_range_amp[] = {
81 1.14 explorer { 0, 1, ENVSYS_SVOLTS_DC },
82 1.14 explorer { 1, 2, ENVSYS_SAMPS },
83 1.14 explorer { 2, 3, ENVSYS_SAMPHOUR },
84 1.14 explorer { 1, 0, -1 },
85 1.14 explorer };
86 1.14 explorer
87 1.14 explorer const struct envsys_range acpibat_range_watt[] = {
88 1.14 explorer { 0, 1, ENVSYS_SVOLTS_DC },
89 1.14 explorer { 1, 2, ENVSYS_SWATTS },
90 1.14 explorer { 2, 3, ENVSYS_SWATTHOUR },
91 1.14 explorer { 1, 0, -1 },
92 1.14 explorer };
93 1.11 explorer
94 1.4 christos #define BAT_WORDS 13
95 1.4 christos
96 1.1 sommerfe struct acpibat_softc {
97 1.1 sommerfe struct device sc_dev; /* base device glue */
98 1.1 sommerfe struct acpi_devnode *sc_node; /* our ACPI devnode */
99 1.1 sommerfe int sc_flags; /* see below */
100 1.1 sommerfe struct callout sc_callout; /* XXX temporary polling */
101 1.13 explorer int sc_present; /* is battery present? */
102 1.1 sommerfe int sc_status; /* power status */
103 1.14 explorer
104 1.14 explorer struct sysmon_envsys sc_sysmon;
105 1.14 explorer struct envsys_basic_info sc_info[ACPIBAT_NSENSORS];
106 1.14 explorer struct envsys_tre_data sc_data[ACPIBAT_NSENSORS];
107 1.14 explorer
108 1.4 christos ACPI_OBJECT sc_Ret[BAT_WORDS]; /* Return Buffer */
109 1.1 sommerfe };
110 1.1 sommerfe
111 1.11 explorer /*
112 1.11 explorer * These flags are used to examine the battery device data returned from
113 1.11 explorer * the ACPI interface, specifically the "battery status"
114 1.11 explorer */
115 1.11 explorer #define ACPIBAT_PWRUNIT_MA 0x00000001 /* mA not mW */
116 1.11 explorer
117 1.11 explorer /*
118 1.11 explorer * These flags are used to examine the battery charge/discharge/critical
119 1.11 explorer * state returned from a get-status command.
120 1.11 explorer */
121 1.14 explorer #define ACPIBAT_ST_DISCHARGING 0x00000001 /* battery is discharging */
122 1.14 explorer #define ACPIBAT_ST_CHARGING 0x00000002 /* battery is charging */
123 1.14 explorer #define ACPIBAT_ST_CRITICAL 0x00000004 /* battery is critical */
124 1.11 explorer
125 1.11 explorer /*
126 1.13 explorer * Flags for battery status from _STA return
127 1.13 explorer */
128 1.14 explorer #define ACPIBAT_STA_PRESENT 0x00000010 /* battery present */
129 1.13 explorer
130 1.13 explorer /*
131 1.11 explorer * These flags are used to set internal state in our softc.
132 1.11 explorer */
133 1.1 sommerfe #define ABAT_F_VERBOSE 0x01 /* verbose events */
134 1.1 sommerfe #define ABAT_F_PWRUNIT_MA 0x02 /* mA instead of mW */
135 1.1 sommerfe
136 1.2 explorer #define ACM_RATEUNIT(sc) (((sc)->sc_flags & ABAT_F_PWRUNIT_MA)?"A":"W")
137 1.2 explorer #define ACM_CAPUNIT(sc) (((sc)->sc_flags & ABAT_F_PWRUNIT_MA)?"Ah":"Wh")
138 1.2 explorer #define ACM_SCALE(x) ((x) / 1000), ((x) % 1000)
139 1.1 sommerfe
140 1.1 sommerfe int acpibat_match(struct device *, struct cfdata *, void *);
141 1.1 sommerfe void acpibat_attach(struct device *, struct device *, void *);
142 1.1 sommerfe
143 1.6 thorpej CFATTACH_DECL(acpibat, sizeof(struct acpibat_softc),
144 1.7 thorpej acpibat_match, acpibat_attach, NULL, NULL);
145 1.1 sommerfe
146 1.1 sommerfe static void acpibat_get_status(void *);
147 1.1 sommerfe static void acpibat_get_info(void *);
148 1.14 explorer static void acpibat_init_envsys(struct acpibat_softc *);
149 1.1 sommerfe void acpibat_notify_handler(ACPI_HANDLE, UINT32, void *context);
150 1.1 sommerfe static void acpibat_tick(void *);
151 1.14 explorer static int acpibat_gtredata(struct sysmon_envsys *, struct envsys_tre_data *);
152 1.14 explorer static int acpibat_streinfo(struct sysmon_envsys *, struct envsys_basic_info *);
153 1.13 explorer static int acpibat_battery_present(void *);
154 1.1 sommerfe
155 1.1 sommerfe /*
156 1.1 sommerfe * acpibat_match:
157 1.1 sommerfe *
158 1.1 sommerfe * Autoconfiguration `match' routine.
159 1.1 sommerfe */
160 1.1 sommerfe int
161 1.1 sommerfe acpibat_match(struct device *parent, struct cfdata *match, void *aux)
162 1.1 sommerfe {
163 1.1 sommerfe struct acpi_attach_args *aa = aux;
164 1.1 sommerfe
165 1.1 sommerfe if (aa->aa_node->ad_type != ACPI_TYPE_DEVICE)
166 1.1 sommerfe return (0);
167 1.1 sommerfe
168 1.1 sommerfe if (strcmp(aa->aa_node->ad_devinfo.HardwareId, "PNP0C0A") == 0)
169 1.1 sommerfe return (1);
170 1.1 sommerfe
171 1.1 sommerfe return (0);
172 1.1 sommerfe }
173 1.1 sommerfe
174 1.1 sommerfe /*
175 1.1 sommerfe * acpibat_attach:
176 1.1 sommerfe *
177 1.1 sommerfe * Autoconfiguration `attach' routine.
178 1.1 sommerfe */
179 1.1 sommerfe void
180 1.1 sommerfe acpibat_attach(struct device *parent, struct device *self, void *aux)
181 1.1 sommerfe {
182 1.1 sommerfe struct acpibat_softc *sc = (void *) self;
183 1.1 sommerfe struct acpi_attach_args *aa = aux;
184 1.1 sommerfe ACPI_STATUS rv;
185 1.1 sommerfe
186 1.11 explorer printf(": ACPI Battery (Control Method)\n");
187 1.1 sommerfe
188 1.1 sommerfe sc->sc_node = aa->aa_node;
189 1.1 sommerfe
190 1.1 sommerfe rv = AcpiInstallNotifyHandler(sc->sc_node->ad_handle,
191 1.13 explorer ACPI_DEVICE_NOTIFY,
192 1.13 explorer acpibat_notify_handler, sc);
193 1.1 sommerfe if (rv != AE_OK) {
194 1.1 sommerfe printf("%s: unable to register DEVICE NOTIFY handler: %d\n",
195 1.13 explorer sc->sc_dev.dv_xname, rv);
196 1.1 sommerfe return;
197 1.1 sommerfe }
198 1.1 sommerfe
199 1.1 sommerfe /* XXX See acpibat_notify_handler() */
200 1.1 sommerfe rv = AcpiInstallNotifyHandler(sc->sc_node->ad_handle,
201 1.13 explorer ACPI_SYSTEM_NOTIFY,
202 1.13 explorer acpibat_notify_handler, sc);
203 1.1 sommerfe if (rv != AE_OK) {
204 1.1 sommerfe printf("%s: unable to register SYSTEM NOTIFY handler: %d\n",
205 1.13 explorer sc->sc_dev.dv_xname, rv);
206 1.1 sommerfe return;
207 1.1 sommerfe }
208 1.13 explorer
209 1.1 sommerfe /*
210 1.1 sommerfe * XXX poll battery in the driver for now.
211 1.1 sommerfe * in the future, when we have an API, let userland do this polling
212 1.1 sommerfe */
213 1.1 sommerfe callout_init(&sc->sc_callout);
214 1.1 sommerfe callout_reset(&sc->sc_callout, 60*hz, acpibat_tick, sc);
215 1.1 sommerfe
216 1.1 sommerfe /* Display the current state. */
217 1.9 jmcneill sc->sc_flags = ABAT_F_VERBOSE;
218 1.1 sommerfe acpibat_get_info(sc);
219 1.1 sommerfe acpibat_get_status(sc);
220 1.14 explorer acpibat_init_envsys(sc);
221 1.1 sommerfe }
222 1.1 sommerfe
223 1.1 sommerfe static void
224 1.1 sommerfe acpibat_tick(void *arg)
225 1.1 sommerfe {
226 1.1 sommerfe struct acpibat_softc *sc = arg;
227 1.1 sommerfe callout_reset(&sc->sc_callout, 60*hz, acpibat_tick, arg);
228 1.1 sommerfe AcpiOsQueueForExecution(OSD_PRIORITY_LO, acpibat_get_status, sc);
229 1.1 sommerfe }
230 1.1 sommerfe
231 1.13 explorer /*
232 1.13 explorer * returns 0 for no battery, 1 for present, and -1 on error
233 1.13 explorer */
234 1.13 explorer static int
235 1.13 explorer acpibat_battery_present(void *arg)
236 1.13 explorer {
237 1.13 explorer struct acpibat_softc *sc = arg;
238 1.13 explorer u_int32_t sta;
239 1.13 explorer ACPI_OBJECT *p1;
240 1.13 explorer ACPI_STATUS rv;
241 1.13 explorer ACPI_BUFFER buf;
242 1.13 explorer
243 1.13 explorer buf.Pointer = sc->sc_Ret;
244 1.13 explorer buf.Length = sizeof(sc->sc_Ret);
245 1.13 explorer
246 1.13 explorer rv = AcpiEvaluateObject(sc->sc_node->ad_handle, "_STA", NULL, &buf);
247 1.13 explorer if (rv != AE_OK) {
248 1.13 explorer printf("%s: failed to evaluate _STA: %x\n",
249 1.13 explorer sc->sc_dev.dv_xname, rv);
250 1.13 explorer sc->sc_present = -1;
251 1.13 explorer return (-1);
252 1.13 explorer }
253 1.13 explorer p1 = (ACPI_OBJECT *)buf.Pointer;
254 1.13 explorer
255 1.13 explorer if (p1->Type != ACPI_TYPE_INTEGER) {
256 1.13 explorer printf("%s: expected INTEGER, got %d\n", sc->sc_dev.dv_xname,
257 1.13 explorer p1->Type);
258 1.13 explorer sc->sc_present = -1;
259 1.13 explorer return (-1);
260 1.13 explorer }
261 1.13 explorer if (p1->Package.Count < 1) {
262 1.13 explorer printf("%s: expected 1 elts, got %d\n",
263 1.13 explorer sc->sc_dev.dv_xname, p1->Package.Count);
264 1.13 explorer sc->sc_present = -1;
265 1.13 explorer return (-1);
266 1.13 explorer }
267 1.13 explorer sta = p1->Integer.Value;
268 1.13 explorer
269 1.14 explorer sc->sc_present = (sta & ACPIBAT_STA_PRESENT) ? 1 : 0;
270 1.13 explorer
271 1.13 explorer return (sc->sc_present);
272 1.13 explorer }
273 1.1 sommerfe
274 1.1 sommerfe /*
275 1.1 sommerfe * acpibat_get_info
276 1.1 sommerfe *
277 1.1 sommerfe * Get, and possibly display, the battery info.
278 1.1 sommerfe */
279 1.1 sommerfe
280 1.1 sommerfe static void
281 1.1 sommerfe acpibat_get_info(void *arg)
282 1.1 sommerfe {
283 1.1 sommerfe struct acpibat_softc *sc = arg;
284 1.1 sommerfe ACPI_OBJECT *p1, *p2;
285 1.1 sommerfe ACPI_STATUS rv;
286 1.1 sommerfe ACPI_BUFFER buf;
287 1.1 sommerfe
288 1.13 explorer (void)acpibat_battery_present(sc);
289 1.13 explorer
290 1.13 explorer if (sc->sc_present != 1) {
291 1.13 explorer printf("%s: not present\n", sc->sc_dev.dv_xname);
292 1.13 explorer return;
293 1.13 explorer }
294 1.13 explorer
295 1.1 sommerfe rv = acpi_eval_struct(sc->sc_node->ad_handle, "_BIF", &buf);
296 1.1 sommerfe if (rv != AE_OK) {
297 1.1 sommerfe printf("%s: failed to evaluate _BIF: %x\n",
298 1.1 sommerfe sc->sc_dev.dv_xname, rv);
299 1.1 sommerfe return;
300 1.1 sommerfe }
301 1.1 sommerfe p1 = (ACPI_OBJECT *)buf.Pointer;
302 1.1 sommerfe if (p1->Type != ACPI_TYPE_PACKAGE) {
303 1.1 sommerfe printf("%s: expected PACKAGE, got %d\n", sc->sc_dev.dv_xname,
304 1.1 sommerfe p1->Type);
305 1.1 sommerfe goto out;
306 1.1 sommerfe }
307 1.8 jmcneill if (p1->Package.Count < 13) {
308 1.1 sommerfe printf("%s: expected 13 elts, got %d\n",
309 1.1 sommerfe sc->sc_dev.dv_xname, p1->Package.Count);
310 1.8 jmcneill goto out;
311 1.8 jmcneill }
312 1.1 sommerfe
313 1.1 sommerfe p2 = p1->Package.Elements;
314 1.11 explorer if ((p2[0].Integer.Value & ACPIBAT_PWRUNIT_MA) != 0)
315 1.1 sommerfe sc->sc_flags |= ABAT_F_PWRUNIT_MA;
316 1.1 sommerfe
317 1.14 explorer sc->sc_data[ACPIBAT_DCAPACITY].cur.data_s = p2[1].Integer.Value * 1000;
318 1.14 explorer sc->sc_data[ACPIBAT_LFCCAPACITY].cur.data_s = p2[2].Integer.Value * 1000;
319 1.14 explorer sc->sc_data[ACPIBAT_LFCCAPACITY].max.data_s = p2[1].Integer.Value * 1000;
320 1.14 explorer sc->sc_data[ACPIBAT_CAPACITY].max.data_s = p2[1].Integer.Value * 1000;
321 1.14 explorer sc->sc_data[ACPIBAT_TECHNOLOGY].cur.data_s = p2[3].Integer.Value;
322 1.14 explorer sc->sc_data[ACPIBAT_DVOLTAGE].cur.data_s = p2[4].Integer.Value * 1000;
323 1.14 explorer sc->sc_data[ACPIBAT_WCAPACITY].cur.data_s = p2[5].Integer.Value * 1000;
324 1.14 explorer sc->sc_data[ACPIBAT_LCAPACITY].cur.data_s = p2[6].Integer.Value * 1000;
325 1.1 sommerfe
326 1.1 sommerfe printf("%s: %s %s %s %s\n",
327 1.1 sommerfe sc->sc_dev.dv_xname,
328 1.1 sommerfe p2[12].String.Pointer, p2[11].String.Pointer,
329 1.1 sommerfe p2[9].String.Pointer, p2[10].String.Pointer);
330 1.1 sommerfe
331 1.1 sommerfe out:
332 1.1 sommerfe AcpiOsFree(buf.Pointer);
333 1.1 sommerfe }
334 1.1 sommerfe
335 1.1 sommerfe /*
336 1.1 sommerfe * acpibat_get_status:
337 1.1 sommerfe *
338 1.1 sommerfe * Get, and possibly display, the current battery line status.
339 1.1 sommerfe */
340 1.1 sommerfe static void
341 1.1 sommerfe acpibat_get_status(void *arg)
342 1.1 sommerfe {
343 1.14 explorer int flags;
344 1.1 sommerfe struct acpibat_softc *sc = arg;
345 1.1 sommerfe ACPI_OBJECT *p1, *p2;
346 1.1 sommerfe ACPI_STATUS rv;
347 1.1 sommerfe ACPI_BUFFER buf;
348 1.1 sommerfe
349 1.13 explorer if (sc->sc_present != 1) {
350 1.13 explorer return;
351 1.13 explorer }
352 1.13 explorer
353 1.4 christos buf.Pointer = sc->sc_Ret;
354 1.4 christos buf.Length = sizeof(sc->sc_Ret);
355 1.4 christos
356 1.4 christos rv = AcpiEvaluateObject(sc->sc_node->ad_handle, "_BST", NULL, &buf);
357 1.14 explorer
358 1.1 sommerfe if (rv != AE_OK) {
359 1.3 kanaoka printf("bat: failed to evaluate _BST: %x\n", rv);
360 1.1 sommerfe return;
361 1.1 sommerfe }
362 1.1 sommerfe p1 = (ACPI_OBJECT *)buf.Pointer;
363 1.1 sommerfe
364 1.1 sommerfe if (p1->Type != ACPI_TYPE_PACKAGE) {
365 1.1 sommerfe printf("bat: expected PACKAGE, got %d\n", p1->Type);
366 1.4 christos return;
367 1.1 sommerfe }
368 1.10 jmcneill if (p1->Package.Count < 4) {
369 1.1 sommerfe printf("bat: expected 4 elts, got %d\n", p1->Package.Count);
370 1.10 jmcneill return;
371 1.10 jmcneill }
372 1.1 sommerfe p2 = p1->Package.Elements;
373 1.1 sommerfe
374 1.1 sommerfe sc->sc_status = p2[0].Integer.Value;
375 1.14 explorer sc->sc_data[ACPIBAT_LOAD].cur.data_s = p2[1].Integer.Value * 1000;
376 1.14 explorer sc->sc_data[ACPIBAT_CAPACITY].cur.data_s = p2[2].Integer.Value * 1000;
377 1.14 explorer sc->sc_data[ACPIBAT_VOLTAGE].cur.data_s = p2[3].Integer.Value * 1000;
378 1.14 explorer
379 1.14 explorer flags = 0;
380 1.14 explorer if (sc->sc_data[ACPIBAT_CAPACITY].cur.data_s < sc->sc_data[ACPIBAT_WCAPACITY].cur.data_s)
381 1.14 explorer flags |= ENVSYS_WARN_UNDER;
382 1.14 explorer if (sc->sc_status & 4)
383 1.14 explorer flags |= ENVSYS_WARN_CRITUNDER;
384 1.14 explorer sc->sc_data[ACPIBAT_CAPACITY].warnflags = flags;
385 1.14 explorer sc->sc_data[ACPIBAT_DISCHARGING].cur.data_s = ((sc->sc_status & ACPIBAT_ST_DISCHARGING) != 0);
386 1.14 explorer sc->sc_data[ACPIBAT_CHARGING].cur.data_s = ((sc->sc_status & ACPIBAT_ST_CHARGING) != 0);
387 1.1 sommerfe }
388 1.1 sommerfe
389 1.1 sommerfe /*
390 1.1 sommerfe * acpibat_notify_handler:
391 1.1 sommerfe *
392 1.1 sommerfe * Callback from ACPI interrupt handler to notify us of an event.
393 1.1 sommerfe */
394 1.1 sommerfe void
395 1.1 sommerfe acpibat_notify_handler(ACPI_HANDLE handle, UINT32 notify, void *context)
396 1.1 sommerfe {
397 1.1 sommerfe struct acpibat_softc *sc = context;
398 1.1 sommerfe int rv;
399 1.1 sommerfe
400 1.11 explorer #ifdef ACPI_BAT_DEBUG
401 1.11 explorer printf("%s: received notify message: 0x%x\n",
402 1.11 explorer sc->sc_dev.dv_xname, notify);
403 1.11 explorer #endif
404 1.11 explorer
405 1.1 sommerfe switch (notify) {
406 1.1 sommerfe case ACPI_NOTIFY_BusCheck:
407 1.11 explorer break;
408 1.11 explorer
409 1.11 explorer case ACPI_NOTIFY_BatteryInformationChanged:
410 1.11 explorer rv = AcpiOsQueueForExecution(OSD_PRIORITY_LO,
411 1.11 explorer acpibat_get_info, sc);
412 1.11 explorer if (rv != AE_OK)
413 1.11 explorer printf("%s: unable to queue status check: %d\n",
414 1.11 explorer sc->sc_dev.dv_xname, rv);
415 1.13 explorer break;
416 1.11 explorer
417 1.1 sommerfe case ACPI_NOTIFY_BatteryStatusChanged:
418 1.1 sommerfe rv = AcpiOsQueueForExecution(OSD_PRIORITY_LO,
419 1.11 explorer acpibat_get_status, sc);
420 1.1 sommerfe if (rv != AE_OK)
421 1.1 sommerfe printf("%s: unable to queue status check: %d\n",
422 1.11 explorer sc->sc_dev.dv_xname, rv);
423 1.1 sommerfe break;
424 1.11 explorer
425 1.1 sommerfe default:
426 1.1 sommerfe printf("%s: received unknown notify message: 0x%x\n",
427 1.11 explorer sc->sc_dev.dv_xname, notify);
428 1.1 sommerfe }
429 1.14 explorer }
430 1.14 explorer
431 1.14 explorer static void
432 1.14 explorer acpibat_init_envsys(struct acpibat_softc *sc)
433 1.14 explorer {
434 1.14 explorer int capunit, rateunit, i;
435 1.14 explorer const char *capstring, *ratestring;
436 1.14 explorer
437 1.14 explorer if (sc->sc_flags & ABAT_F_PWRUNIT_MA) {
438 1.14 explorer sc->sc_sysmon.sme_ranges = acpibat_range_amp;
439 1.14 explorer capunit = ENVSYS_SAMPHOUR;
440 1.14 explorer capstring = "charge";
441 1.14 explorer rateunit = ENVSYS_SAMPS;
442 1.14 explorer ratestring = "current";
443 1.14 explorer } else {
444 1.14 explorer sc->sc_sysmon.sme_ranges = acpibat_range_watt;
445 1.14 explorer capunit = ENVSYS_SWATTHOUR;
446 1.14 explorer capstring = "energy";
447 1.14 explorer rateunit = ENVSYS_SWATTS;
448 1.14 explorer ratestring = "power";
449 1.14 explorer }
450 1.14 explorer
451 1.14 explorer for (i = 0 ; i < ACPIBAT_NSENSORS; i++) {
452 1.14 explorer sc->sc_data[i].sensor = sc->sc_info[i].sensor = i;
453 1.14 explorer sc->sc_data[i].validflags |= (ENVSYS_FVALID | ENVSYS_FCURVALID);
454 1.14 explorer sc->sc_info[i].validflags = ENVSYS_FVALID;
455 1.14 explorer sc->sc_data[i].warnflags = 0;
456 1.14 explorer }
457 1.14 explorer #define INITDATA(index, unit, string) \
458 1.14 explorer sc->sc_data[index].units = unit; \
459 1.14 explorer sc->sc_info[index].units = unit; \
460 1.14 explorer snprintf(sc->sc_info[index].desc, sizeof(sc->sc_info->desc), \
461 1.14 explorer "%s %s", sc->sc_dev.dv_xname, string); \
462 1.14 explorer
463 1.14 explorer INITDATA(ACPIBAT_DCAPACITY, capunit, "design cap");
464 1.14 explorer INITDATA(ACPIBAT_LFCCAPACITY, capunit, "lfc cap");
465 1.14 explorer INITDATA(ACPIBAT_TECHNOLOGY, ENVSYS_INTEGER, "technology");
466 1.14 explorer INITDATA(ACPIBAT_DVOLTAGE, ENVSYS_SVOLTS_DC, "design voltage");
467 1.14 explorer INITDATA(ACPIBAT_WCAPACITY, capunit, "warn cap");
468 1.14 explorer INITDATA(ACPIBAT_LCAPACITY, capunit, "low cap");
469 1.14 explorer INITDATA(ACPIBAT_VOLTAGE, ENVSYS_SVOLTS_DC, "voltage");
470 1.14 explorer INITDATA(ACPIBAT_LOAD, rateunit, ratestring);
471 1.14 explorer INITDATA(ACPIBAT_CAPACITY, capunit, capstring);
472 1.14 explorer INITDATA(ACPIBAT_CHARGING, ENVSYS_INDICATOR, "charging");
473 1.14 explorer INITDATA(ACPIBAT_DISCHARGING, ENVSYS_INDICATOR, "discharging");
474 1.14 explorer
475 1.14 explorer /*
476 1.14 explorer * ACPIBAT_CAPACITY is the "gas gauge".
477 1.14 explorer * ACPIBAT_LFCCAPACITY is the "wear gauge".
478 1.14 explorer */
479 1.14 explorer sc->sc_data[ACPIBAT_CAPACITY].validflags |=
480 1.14 explorer ENVSYS_FMAXVALID | ENVSYS_FFRACVALID;
481 1.14 explorer sc->sc_data[ACPIBAT_LFCCAPACITY].validflags |=
482 1.14 explorer ENVSYS_FMAXVALID | ENVSYS_FFRACVALID;
483 1.14 explorer
484 1.14 explorer sc->sc_sysmon.sme_sensor_info = sc->sc_info;
485 1.14 explorer sc->sc_sysmon.sme_sensor_data = sc->sc_data;
486 1.14 explorer sc->sc_sysmon.sme_cookie = sc;
487 1.14 explorer sc->sc_sysmon.sme_gtredata = acpibat_gtredata;
488 1.14 explorer sc->sc_sysmon.sme_streinfo = acpibat_streinfo;
489 1.14 explorer sc->sc_sysmon.sme_nsensors = ACPIBAT_NSENSORS;
490 1.14 explorer sc->sc_sysmon.sme_envsys_version = 1000;
491 1.14 explorer
492 1.14 explorer if (sysmon_envsys_register(&sc->sc_sysmon))
493 1.14 explorer printf("%s: unable to register with sysmon\n",
494 1.14 explorer sc->sc_dev.dv_xname);
495 1.14 explorer }
496 1.14 explorer
497 1.14 explorer int
498 1.14 explorer acpibat_gtredata(struct sysmon_envsys *sme, struct envsys_tre_data *tred)
499 1.14 explorer {
500 1.14 explorer struct acpibat_softc *sc = sme->sme_cookie;
501 1.14 explorer
502 1.14 explorer /* XXX locking */
503 1.14 explorer acpibat_get_status(sc);
504 1.14 explorer *tred = sc->sc_data[tred->sensor];
505 1.14 explorer /* XXX locking */
506 1.14 explorer
507 1.14 explorer return (0);
508 1.14 explorer }
509 1.14 explorer
510 1.14 explorer
511 1.14 explorer int
512 1.14 explorer acpibat_streinfo(struct sysmon_envsys *sme, struct envsys_basic_info *binfo)
513 1.14 explorer {
514 1.14 explorer
515 1.14 explorer /* XXX Not implemented */
516 1.14 explorer binfo->validflags = 0;
517 1.14 explorer
518 1.14 explorer return (0);
519 1.1 sommerfe }
520