Fri Jan 29 15:20:13 2021 UTC ()
Use acpi_compatible_match().


(thorpej)
diff -r1.51 -r1.52 src/sys/dev/acpi/acpi_acad.c
diff -r1.116 -r1.117 src/sys/dev/acpi/acpi_bat.c

cvs diff -r1.51 -r1.52 src/sys/dev/acpi/acpi_acad.c (switch to unified diff)

--- src/sys/dev/acpi/acpi_acad.c 2015/04/23 23:23:00 1.51
+++ src/sys/dev/acpi/acpi_acad.c 2021/01/29 15:20:13 1.52
@@ -1,322 +1,319 @@ @@ -1,322 +1,319 @@
1/* $NetBSD: acpi_acad.c,v 1.51 2015/04/23 23:23:00 pgoyette Exp $ */ 1/* $NetBSD: acpi_acad.c,v 1.52 2021/01/29 15:20:13 thorpej Exp $ */
2 2
3/* 3/*
4 * Copyright 2001 Wasabi Systems, Inc. 4 * Copyright 2001 Wasabi Systems, Inc.
5 * All rights reserved. 5 * All rights reserved.
6 * 6 *
7 * Written by Jason R. Thorpe for Wasabi Systems, Inc. 7 * Written by Jason R. Thorpe for Wasabi Systems, Inc.
8 * 8 *
9 * Redistribution and use in source and binary forms, with or without 9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions 10 * modification, are permitted provided that the following conditions
11 * are met: 11 * are met:
12 * 1. Redistributions of source code must retain the above copyright 12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer. 13 * notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright 14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in the 15 * notice, this list of conditions and the following disclaimer in the
16 * documentation and/or other materials provided with the distribution. 16 * documentation and/or other materials provided with the distribution.
17 * 3. All advertising materials mentioning features or use of this software 17 * 3. All advertising materials mentioning features or use of this software
18 * must display the following acknowledgement: 18 * must display the following acknowledgement:
19 * This product includes software developed for the NetBSD Project by 19 * This product includes software developed for the NetBSD Project by
20 * Wasabi Systems, Inc. 20 * Wasabi Systems, Inc.
21 * 4. The name of Wasabi Systems, Inc. may not be used to endorse 21 * 4. The name of Wasabi Systems, Inc. may not be used to endorse
22 * or promote products derived from this software without specific prior 22 * or promote products derived from this software without specific prior
23 * written permission. 23 * written permission.
24 * 24 *
25 * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND 25 * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND
26 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 26 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
27 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 27 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
28 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL WASABI SYSTEMS, INC 28 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL WASABI SYSTEMS, INC
29 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 29 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
30 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 30 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
31 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 31 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
32 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 32 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
33 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 33 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
34 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 34 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
35 * POSSIBILITY OF SUCH DAMAGE. 35 * POSSIBILITY OF SUCH DAMAGE.
36 */ 36 */
37 37
38/* 38/*
39 * ACPI AC Adapter driver. 39 * ACPI AC Adapter driver.
40 */ 40 */
41 41
42#include <sys/cdefs.h> 42#include <sys/cdefs.h>
43__KERNEL_RCSID(0, "$NetBSD: acpi_acad.c,v 1.51 2015/04/23 23:23:00 pgoyette Exp $"); 43__KERNEL_RCSID(0, "$NetBSD: acpi_acad.c,v 1.52 2021/01/29 15:20:13 thorpej Exp $");
44 44
45#include <sys/param.h> 45#include <sys/param.h>
46#include <sys/device.h> 46#include <sys/device.h>
47#include <sys/module.h> 47#include <sys/module.h>
48#include <sys/systm.h> 48#include <sys/systm.h>
49 49
50#include <dev/acpi/acpireg.h> 50#include <dev/acpi/acpireg.h>
51#include <dev/acpi/acpivar.h> 51#include <dev/acpi/acpivar.h>
52 52
53#define _COMPONENT ACPI_ACAD_COMPONENT 53#define _COMPONENT ACPI_ACAD_COMPONENT
54ACPI_MODULE_NAME ("acpi_acad") 54ACPI_MODULE_NAME ("acpi_acad")
55 55
56#define ACPI_NOTIFY_ACAD 0x80 56#define ACPI_NOTIFY_ACAD 0x80
57#define ACPI_NOTIFY_ACAD_2 0x81 /* XXX. */ 57#define ACPI_NOTIFY_ACAD_2 0x81 /* XXX. */
58 58
59struct acpiacad_softc { 59struct acpiacad_softc {
60 struct acpi_devnode *sc_node; 60 struct acpi_devnode *sc_node;
61 struct sysmon_envsys *sc_sme; 61 struct sysmon_envsys *sc_sme;
62 struct sysmon_pswitch sc_smpsw; 62 struct sysmon_pswitch sc_smpsw;
63 envsys_data_t sc_sensor; 63 envsys_data_t sc_sensor;
64 int sc_status; 64 int sc_status;
65}; 65};
66 66
67static const char * const acad_hid[] = { 67static const struct device_compatible_entry compat_data[] = {
68 "ACPI0003", 68 { .compat = "ACPI0003" },
69 NULL 69 DEVICE_COMPAT_EOL
70}; 70};
71 71
72static int acpiacad_match(device_t, cfdata_t, void *); 72static int acpiacad_match(device_t, cfdata_t, void *);
73static void acpiacad_attach(device_t, device_t, void *); 73static void acpiacad_attach(device_t, device_t, void *);
74static int acpiacad_detach(device_t, int); 74static int acpiacad_detach(device_t, int);
75static bool acpiacad_resume(device_t, const pmf_qual_t *); 75static bool acpiacad_resume(device_t, const pmf_qual_t *);
76static void acpiacad_get_status(void *); 76static void acpiacad_get_status(void *);
77static void acpiacad_notify_handler(ACPI_HANDLE, uint32_t, void *); 77static void acpiacad_notify_handler(ACPI_HANDLE, uint32_t, void *);
78static void acpiacad_init_envsys(device_t); 78static void acpiacad_init_envsys(device_t);
79 79
80CFATTACH_DECL_NEW(acpiacad, sizeof(struct acpiacad_softc), 80CFATTACH_DECL_NEW(acpiacad, sizeof(struct acpiacad_softc),
81 acpiacad_match, acpiacad_attach, acpiacad_detach, NULL); 81 acpiacad_match, acpiacad_attach, acpiacad_detach, NULL);
82 82
83/* 83/*
84 * acpiacad_match: 84 * acpiacad_match:
85 * 85 *
86 * Autoconfiguration `match' routine. 86 * Autoconfiguration `match' routine.
87 */ 87 */
88static int 88static int
89acpiacad_match(device_t parent, cfdata_t match, void *aux) 89acpiacad_match(device_t parent, cfdata_t match, void *aux)
90{ 90{
91 struct acpi_attach_args *aa = aux; 91 struct acpi_attach_args *aa = aux;
92 92
93 if (aa->aa_node->ad_type != ACPI_TYPE_DEVICE) 93 return acpi_compatible_match(aa, compat_data);
94 return 0; 
95 
96 return acpi_match_hid(aa->aa_node->ad_devinfo, acad_hid); 
97} 94}
98 95
99/* 96/*
100 * acpiacad_attach: 97 * acpiacad_attach:
101 * 98 *
102 * Autoconfiguration `attach' routine. 99 * Autoconfiguration `attach' routine.
103 */ 100 */
104static void 101static void
105acpiacad_attach(device_t parent, device_t self, void *aux) 102acpiacad_attach(device_t parent, device_t self, void *aux)
106{ 103{
107 struct acpiacad_softc *sc = device_private(self); 104 struct acpiacad_softc *sc = device_private(self);
108 struct acpi_attach_args *aa = aux; 105 struct acpi_attach_args *aa = aux;
109 106
110 aprint_naive(": ACPI AC Adapter\n"); 107 aprint_naive(": ACPI AC Adapter\n");
111 aprint_normal(": ACPI AC Adapter\n"); 108 aprint_normal(": ACPI AC Adapter\n");
112 109
113 sc->sc_sme = NULL; 110 sc->sc_sme = NULL;
114 sc->sc_status = -1; 111 sc->sc_status = -1;
115 sc->sc_node = aa->aa_node; 112 sc->sc_node = aa->aa_node;
116 113
117 acpiacad_init_envsys(self); 114 acpiacad_init_envsys(self);
118 115
119 sc->sc_smpsw.smpsw_name = device_xname(self); 116 sc->sc_smpsw.smpsw_name = device_xname(self);
120 sc->sc_smpsw.smpsw_type = PSWITCH_TYPE_ACADAPTER; 117 sc->sc_smpsw.smpsw_type = PSWITCH_TYPE_ACADAPTER;
121 118
122 (void)sysmon_pswitch_register(&sc->sc_smpsw); 119 (void)sysmon_pswitch_register(&sc->sc_smpsw);
123 (void)pmf_device_register(self, NULL, acpiacad_resume); 120 (void)pmf_device_register(self, NULL, acpiacad_resume);
124 (void)acpi_register_notify(sc->sc_node, acpiacad_notify_handler); 121 (void)acpi_register_notify(sc->sc_node, acpiacad_notify_handler);
125} 122}
126 123
127/* 124/*
128 * acpiacad_detach: 125 * acpiacad_detach:
129 * 126 *
130 * Autoconfiguration `detach' routine. 127 * Autoconfiguration `detach' routine.
131 */ 128 */
132static int 129static int
133acpiacad_detach(device_t self, int flags) 130acpiacad_detach(device_t self, int flags)
134{ 131{
135 struct acpiacad_softc *sc = device_private(self); 132 struct acpiacad_softc *sc = device_private(self);
136 133
137 acpi_deregister_notify(sc->sc_node); 134 acpi_deregister_notify(sc->sc_node);
138 135
139 if (sc->sc_sme != NULL) 136 if (sc->sc_sme != NULL)
140 sysmon_envsys_unregister(sc->sc_sme); 137 sysmon_envsys_unregister(sc->sc_sme);
141 138
142 pmf_device_deregister(self); 139 pmf_device_deregister(self);
143 sysmon_pswitch_unregister(&sc->sc_smpsw); 140 sysmon_pswitch_unregister(&sc->sc_smpsw);
144 141
145 return 0; 142 return 0;
146} 143}
147 144
148/* 145/*
149 * acpiacad_resume: 146 * acpiacad_resume:
150 * 147 *
151 * Queue a new status check. 148 * Queue a new status check.
152 */ 149 */
153static bool 150static bool
154acpiacad_resume(device_t dv, const pmf_qual_t *qual) 151acpiacad_resume(device_t dv, const pmf_qual_t *qual)
155{ 152{
156 153
157 (void)AcpiOsExecute(OSL_NOTIFY_HANDLER, acpiacad_get_status, dv); 154 (void)AcpiOsExecute(OSL_NOTIFY_HANDLER, acpiacad_get_status, dv);
158 155
159 return true; 156 return true;
160} 157}
161 158
162/* 159/*
163 * acpiacad_get_status: 160 * acpiacad_get_status:
164 * 161 *
165 * Get, and possibly display, the current AC line status. 162 * Get, and possibly display, the current AC line status.
166 */ 163 */
167static void 164static void
168acpiacad_get_status(void *arg) 165acpiacad_get_status(void *arg)
169{ 166{
170 device_t dv = arg; 167 device_t dv = arg;
171 struct acpiacad_softc *sc = device_private(dv); 168 struct acpiacad_softc *sc = device_private(dv);
172 ACPI_INTEGER status; 169 ACPI_INTEGER status;
173 ACPI_STATUS rv; 170 ACPI_STATUS rv;
174 171
175 rv = acpi_eval_integer(sc->sc_node->ad_handle, "_PSR", &status); 172 rv = acpi_eval_integer(sc->sc_node->ad_handle, "_PSR", &status);
176 173
177 if (ACPI_FAILURE(rv)) 174 if (ACPI_FAILURE(rv))
178 goto fail; 175 goto fail;
179 176
180 if (status != 0 && status != 1) { 177 if (status != 0 && status != 1) {
181 rv = AE_BAD_VALUE; 178 rv = AE_BAD_VALUE;
182 goto fail; 179 goto fail;
183 } 180 }
184 181
185 if (sc->sc_status != (int)status) { 182 if (sc->sc_status != (int)status) {
186 183
187 /* 184 /*
188 * If status has changed, send the event: 185 * If status has changed, send the event:
189 * 186 *
190 * PSWITCH_EVENT_PRESSED : _PSR = 1 : AC online. 187 * PSWITCH_EVENT_PRESSED : _PSR = 1 : AC online.
191 * PSWITCH_EVENT_RELEASED : _PSR = 0 : AC offline. 188 * PSWITCH_EVENT_RELEASED : _PSR = 0 : AC offline.
192 */ 189 */
193 sysmon_pswitch_event(&sc->sc_smpsw, (status != 0) ? 190 sysmon_pswitch_event(&sc->sc_smpsw, (status != 0) ?
194 PSWITCH_EVENT_PRESSED : PSWITCH_EVENT_RELEASED); 191 PSWITCH_EVENT_PRESSED : PSWITCH_EVENT_RELEASED);
195 192
196 aprint_debug_dev(dv, "AC adapter %sconnected\n", 193 aprint_debug_dev(dv, "AC adapter %sconnected\n",
197 status == 0 ? "not " : ""); 194 status == 0 ? "not " : "");
198 } 195 }
199 196
200 sc->sc_status = status; 197 sc->sc_status = status;
201 sc->sc_sensor.state = ENVSYS_SVALID; 198 sc->sc_sensor.state = ENVSYS_SVALID;
202 sc->sc_sensor.value_cur = sc->sc_status; 199 sc->sc_sensor.value_cur = sc->sc_status;
203 200
204 return; 201 return;
205 202
206fail: 203fail:
207 sc->sc_status = -1; 204 sc->sc_status = -1;
208 sc->sc_sensor.state = ENVSYS_SINVALID; 205 sc->sc_sensor.state = ENVSYS_SINVALID;
209 206
210 aprint_debug_dev(dv, "failed to evaluate _PSR: %s\n", 207 aprint_debug_dev(dv, "failed to evaluate _PSR: %s\n",
211 AcpiFormatException(rv)); 208 AcpiFormatException(rv));
212} 209}
213 210
214/* 211/*
215 * acpiacad_notify_handler: 212 * acpiacad_notify_handler:
216 * 213 *
217 * Callback from ACPI interrupt handler to notify us of an event. 214 * Callback from ACPI interrupt handler to notify us of an event.
218 */ 215 */
219static void 216static void
220acpiacad_notify_handler(ACPI_HANDLE handle, uint32_t notify, void *context) 217acpiacad_notify_handler(ACPI_HANDLE handle, uint32_t notify, void *context)
221{ 218{
222 static const int handler = OSL_NOTIFY_HANDLER; 219 static const int handler = OSL_NOTIFY_HANDLER;
223 device_t dv = context; 220 device_t dv = context;
224 221
225 switch (notify) { 222 switch (notify) {
226 /* 223 /*
227 * XXX So, BusCheck is not exactly what I would expect, 224 * XXX So, BusCheck is not exactly what I would expect,
228 * but at least my IBM T21 sends it on AC adapter status 225 * but at least my IBM T21 sends it on AC adapter status
229 * change. --thorpej@wasabisystems.com 226 * change. --thorpej@wasabisystems.com
230 */ 227 */
231 /* 228 /*
232 * XXX My Acer TravelMate 291 sends DeviceCheck on AC 229 * XXX My Acer TravelMate 291 sends DeviceCheck on AC
233 * adapter status change. 230 * adapter status change.
234 * --rpaulo@NetBSD.org 231 * --rpaulo@NetBSD.org
235 */ 232 */
236 /* 233 /*
237 * XXX Sony VAIO VGN-N250E sends 0x81 on AC adapter status change. 234 * XXX Sony VAIO VGN-N250E sends 0x81 on AC adapter status change.
238 * --jmcneill@NetBSD.org 235 * --jmcneill@NetBSD.org
239 */ 236 */
240 case ACPI_NOTIFY_ACAD: 237 case ACPI_NOTIFY_ACAD:
241 case ACPI_NOTIFY_ACAD_2: 238 case ACPI_NOTIFY_ACAD_2:
242 case ACPI_NOTIFY_BUS_CHECK: 239 case ACPI_NOTIFY_BUS_CHECK:
243 case ACPI_NOTIFY_DEVICE_CHECK: 240 case ACPI_NOTIFY_DEVICE_CHECK:
244 (void)AcpiOsExecute(handler, acpiacad_get_status, dv); 241 (void)AcpiOsExecute(handler, acpiacad_get_status, dv);
245 break; 242 break;
246 243
247 case ACPI_NOTIFY_DEVICE_WAKE: 244 case ACPI_NOTIFY_DEVICE_WAKE:
248 break; 245 break;
249 246
250 default: 247 default:
251 aprint_debug_dev(dv, "unknown notify 0x%02X\n", notify); 248 aprint_debug_dev(dv, "unknown notify 0x%02X\n", notify);
252 } 249 }
253} 250}
254 251
255static void 252static void
256acpiacad_init_envsys(device_t dv) 253acpiacad_init_envsys(device_t dv)
257{ 254{
258 struct acpiacad_softc *sc = device_private(dv); 255 struct acpiacad_softc *sc = device_private(dv);
259 256
260 sc->sc_sme = sysmon_envsys_create(); 257 sc->sc_sme = sysmon_envsys_create();
261 258
262 sc->sc_sensor.state = ENVSYS_SINVALID; 259 sc->sc_sensor.state = ENVSYS_SINVALID;
263 sc->sc_sensor.units = ENVSYS_INDICATOR; 260 sc->sc_sensor.units = ENVSYS_INDICATOR;
264 261
265 (void)strlcpy(sc->sc_sensor.desc, "connected", ENVSYS_DESCLEN); 262 (void)strlcpy(sc->sc_sensor.desc, "connected", ENVSYS_DESCLEN);
266 263
267 if (sysmon_envsys_sensor_attach(sc->sc_sme, &sc->sc_sensor) != 0) 264 if (sysmon_envsys_sensor_attach(sc->sc_sme, &sc->sc_sensor) != 0)
268 goto fail; 265 goto fail;
269 266
270 sc->sc_sme->sme_name = device_xname(dv); 267 sc->sc_sme->sme_name = device_xname(dv);
271 sc->sc_sme->sme_class = SME_CLASS_ACADAPTER; 268 sc->sc_sme->sme_class = SME_CLASS_ACADAPTER;
272 sc->sc_sme->sme_flags = SME_DISABLE_REFRESH; 269 sc->sc_sme->sme_flags = SME_DISABLE_REFRESH;
273 270
274 if (sysmon_envsys_register(sc->sc_sme) != 0) 271 if (sysmon_envsys_register(sc->sc_sme) != 0)
275 goto fail; 272 goto fail;
276 273
277 (void)AcpiOsExecute(OSL_NOTIFY_HANDLER, acpiacad_get_status, dv); 274 (void)AcpiOsExecute(OSL_NOTIFY_HANDLER, acpiacad_get_status, dv);
278 275
279 return; 276 return;
280 277
281fail: 278fail:
282 aprint_error_dev(dv, "failed to initialize sysmon\n"); 279 aprint_error_dev(dv, "failed to initialize sysmon\n");
283 280
284 sysmon_envsys_destroy(sc->sc_sme); 281 sysmon_envsys_destroy(sc->sc_sme);
285 sc->sc_sme = NULL; 282 sc->sc_sme = NULL;
286} 283}
287 284
288MODULE(MODULE_CLASS_DRIVER, acpiacad, "sysmon_envsys,sysmon_power"); 285MODULE(MODULE_CLASS_DRIVER, acpiacad, "sysmon_envsys,sysmon_power");
289 286
290#ifdef _MODULE 287#ifdef _MODULE
291#include "ioconf.c" 288#include "ioconf.c"
292#endif 289#endif
293 290
294static int 291static int
295acpiacad_modcmd(modcmd_t cmd, void *aux) 292acpiacad_modcmd(modcmd_t cmd, void *aux)
296{ 293{
297 int rv = 0; 294 int rv = 0;
298 295
299 switch (cmd) { 296 switch (cmd) {
300 297
301 case MODULE_CMD_INIT: 298 case MODULE_CMD_INIT:
302 299
303#ifdef _MODULE 300#ifdef _MODULE
304 rv = config_init_component(cfdriver_ioconf_acpiacad, 301 rv = config_init_component(cfdriver_ioconf_acpiacad,
305 cfattach_ioconf_acpiacad, cfdata_ioconf_acpiacad); 302 cfattach_ioconf_acpiacad, cfdata_ioconf_acpiacad);
306#endif 303#endif
307 break; 304 break;
308 305
309 case MODULE_CMD_FINI: 306 case MODULE_CMD_FINI:
310 307
311#ifdef _MODULE 308#ifdef _MODULE
312 rv = config_fini_component(cfdriver_ioconf_acpiacad, 309 rv = config_fini_component(cfdriver_ioconf_acpiacad,
313 cfattach_ioconf_acpiacad, cfdata_ioconf_acpiacad); 310 cfattach_ioconf_acpiacad, cfdata_ioconf_acpiacad);
314#endif 311#endif
315 break; 312 break;
316 313
317 default: 314 default:
318 rv = ENOTTY; 315 rv = ENOTTY;
319 } 316 }
320 317
321 return rv; 318 return rv;
322} 319}

cvs diff -r1.116 -r1.117 src/sys/dev/acpi/acpi_bat.c (switch to unified diff)

--- src/sys/dev/acpi/acpi_bat.c 2018/08/10 17:11:56 1.116
+++ src/sys/dev/acpi/acpi_bat.c 2021/01/29 15:20:13 1.117
@@ -1,888 +1,885 @@ @@ -1,888 +1,885 @@
1/* $NetBSD: acpi_bat.c,v 1.116 2018/08/10 17:11:56 riastradh Exp $ */ 1/* $NetBSD: acpi_bat.c,v 1.117 2021/01/29 15:20:13 thorpej Exp $ */
2 2
3/*- 3/*-
4 * Copyright (c) 2003 The NetBSD Foundation, Inc. 4 * Copyright (c) 2003 The NetBSD Foundation, Inc.
5 * All rights reserved. 5 * All rights reserved.
6 * 6 *
7 * This code is derived from software contributed to The NetBSD Foundation 7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Charles M. Hannum of By Noon Software, Inc. 8 * by Charles M. Hannum of By Noon Software, Inc.
9 * 9 *
10 * Redistribution and use in source and binary forms, with or without 10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions 11 * modification, are permitted provided that the following conditions
12 * are met: 12 * are met:
13 * 1. Redistributions of source code must retain the above copyright 13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer. 14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright 15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the 16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution. 17 * documentation and/or other materials provided with the distribution.
18 * 18 *
19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE. 29 * POSSIBILITY OF SUCH DAMAGE.
30 */ 30 */
31 31
32/* 32/*
33 * Copyright 2001 Bill Sommerfeld. 33 * Copyright 2001 Bill Sommerfeld.
34 * All rights reserved. 34 * All rights reserved.
35 * 35 *
36 * Redistribution and use in source and binary forms, with or without 36 * Redistribution and use in source and binary forms, with or without
37 * modification, are permitted provided that the following conditions 37 * modification, are permitted provided that the following conditions
38 * are met: 38 * are met:
39 * 1. Redistributions of source code must retain the above copyright 39 * 1. Redistributions of source code must retain the above copyright
40 * notice, this list of conditions and the following disclaimer. 40 * notice, this list of conditions and the following disclaimer.
41 * 2. Redistributions in binary form must reproduce the above copyright 41 * 2. Redistributions in binary form must reproduce the above copyright
42 * notice, this list of conditions and the following disclaimer in the 42 * notice, this list of conditions and the following disclaimer in the
43 * documentation and/or other materials provided with the distribution. 43 * documentation and/or other materials provided with the distribution.
44 * 3. All advertising materials mentioning features or use of this software 44 * 3. All advertising materials mentioning features or use of this software
45 * must display the following acknowledgement: 45 * must display the following acknowledgement:
46 * This product includes software developed for the NetBSD Project by 46 * This product includes software developed for the NetBSD Project by
47 * Wasabi Systems, Inc. 47 * Wasabi Systems, Inc.
48 * 4. The name of Wasabi Systems, Inc. may not be used to endorse 48 * 4. The name of Wasabi Systems, Inc. may not be used to endorse
49 * or promote products derived from this software without specific prior 49 * or promote products derived from this software without specific prior
50 * written permission. 50 * written permission.
51 * 51 *
52 * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND 52 * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND
53 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 53 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
54 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 54 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
55 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL WASABI SYSTEMS, INC 55 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL WASABI SYSTEMS, INC
56 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 56 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
57 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 57 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
58 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 58 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
59 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 59 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
60 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 60 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
61 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 61 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
62 * POSSIBILITY OF SUCH DAMAGE. 62 * POSSIBILITY OF SUCH DAMAGE.
63 */ 63 */
64 64
65/* 65/*
66 * ACPI Battery Driver. 66 * ACPI Battery Driver.
67 * 67 *
68 * ACPI defines two different battery device interfaces: "Control 68 * ACPI defines two different battery device interfaces: "Control
69 * Method" batteries, in which AML methods are defined in order to get 69 * Method" batteries, in which AML methods are defined in order to get
70 * battery status and set battery alarm thresholds, and a "Smart 70 * battery status and set battery alarm thresholds, and a "Smart
71 * Battery" device, which is an SMbus device accessed through the ACPI 71 * Battery" device, which is an SMbus device accessed through the ACPI
72 * Embedded Controller device. 72 * Embedded Controller device.
73 * 73 *
74 * This driver is for the "Control Method"-style battery only. 74 * This driver is for the "Control Method"-style battery only.
75 */ 75 */
76 76
77#include <sys/cdefs.h> 77#include <sys/cdefs.h>
78__KERNEL_RCSID(0, "$NetBSD: acpi_bat.c,v 1.116 2018/08/10 17:11:56 riastradh Exp $"); 78__KERNEL_RCSID(0, "$NetBSD: acpi_bat.c,v 1.117 2021/01/29 15:20:13 thorpej Exp $");
79 79
80#include <sys/param.h> 80#include <sys/param.h>
81#include <sys/condvar.h> 81#include <sys/condvar.h>
82#include <sys/device.h> 82#include <sys/device.h>
83#include <sys/kernel.h> 83#include <sys/kernel.h>
84#include <sys/kmem.h> 84#include <sys/kmem.h>
85#include <sys/module.h> 85#include <sys/module.h>
86#include <sys/mutex.h> 86#include <sys/mutex.h>
87#include <sys/systm.h> 87#include <sys/systm.h>
88 88
89#include <dev/acpi/acpireg.h> 89#include <dev/acpi/acpireg.h>
90#include <dev/acpi/acpivar.h> 90#include <dev/acpi/acpivar.h>
91 91
92#define _COMPONENT ACPI_BAT_COMPONENT 92#define _COMPONENT ACPI_BAT_COMPONENT
93ACPI_MODULE_NAME ("acpi_bat") 93ACPI_MODULE_NAME ("acpi_bat")
94 94
95#define ACPI_NOTIFY_BAT_STATUS 0x80 95#define ACPI_NOTIFY_BAT_STATUS 0x80
96#define ACPI_NOTIFY_BAT_INFO 0x81 96#define ACPI_NOTIFY_BAT_INFO 0x81
97 97
98/* 98/*
99 * Sensor indexes. 99 * Sensor indexes.
100 */ 100 */
101enum { 101enum {
102 ACPIBAT_PRESENT = 0, 102 ACPIBAT_PRESENT = 0,
103 ACPIBAT_DVOLTAGE = 1, 103 ACPIBAT_DVOLTAGE = 1,
104 ACPIBAT_VOLTAGE = 2, 104 ACPIBAT_VOLTAGE = 2,
105 ACPIBAT_DCAPACITY = 3, 105 ACPIBAT_DCAPACITY = 3,
106 ACPIBAT_LFCCAPACITY = 4, 106 ACPIBAT_LFCCAPACITY = 4,
107 ACPIBAT_CAPACITY = 5, 107 ACPIBAT_CAPACITY = 5,
108 ACPIBAT_CHARGERATE = 6, 108 ACPIBAT_CHARGERATE = 6,
109 ACPIBAT_DISCHARGERATE = 7, 109 ACPIBAT_DISCHARGERATE = 7,
110 ACPIBAT_CHARGING = 8, 110 ACPIBAT_CHARGING = 8,
111 ACPIBAT_CHARGE_STATE = 9, 111 ACPIBAT_CHARGE_STATE = 9,
112 ACPIBAT_COUNT = 10 112 ACPIBAT_COUNT = 10
113}; 113};
114 114
115/* 115/*
116 * Battery Information, _BIF 116 * Battery Information, _BIF
117 * (ACPI 3.0, sec. 10.2.2.1). 117 * (ACPI 3.0, sec. 10.2.2.1).
118 */ 118 */
119enum { 119enum {
120 ACPIBAT_BIF_UNIT = 0, 120 ACPIBAT_BIF_UNIT = 0,
121 ACPIBAT_BIF_DCAPACITY = 1, 121 ACPIBAT_BIF_DCAPACITY = 1,
122 ACPIBAT_BIF_LFCCAPACITY = 2, 122 ACPIBAT_BIF_LFCCAPACITY = 2,
123 ACPIBAT_BIF_TECHNOLOGY = 3, 123 ACPIBAT_BIF_TECHNOLOGY = 3,
124 ACPIBAT_BIF_DVOLTAGE = 4, 124 ACPIBAT_BIF_DVOLTAGE = 4,
125 ACPIBAT_BIF_WCAPACITY = 5, 125 ACPIBAT_BIF_WCAPACITY = 5,
126 ACPIBAT_BIF_LCAPACITY = 6, 126 ACPIBAT_BIF_LCAPACITY = 6,
127 ACPIBAT_BIF_GRANULARITY1 = 7, 127 ACPIBAT_BIF_GRANULARITY1 = 7,
128 ACPIBAT_BIF_GRANULARITY2 = 8, 128 ACPIBAT_BIF_GRANULARITY2 = 8,
129 ACPIBAT_BIF_MODEL = 9, 129 ACPIBAT_BIF_MODEL = 9,
130 ACPIBAT_BIF_SERIAL = 10, 130 ACPIBAT_BIF_SERIAL = 10,
131 ACPIBAT_BIF_TYPE = 11, 131 ACPIBAT_BIF_TYPE = 11,
132 ACPIBAT_BIF_OEM = 12, 132 ACPIBAT_BIF_OEM = 12,
133 ACPIBAT_BIF_COUNT = 13 133 ACPIBAT_BIF_COUNT = 13
134}; 134};
135 135
136/* 136/*
137 * Battery Status, _BST 137 * Battery Status, _BST
138 * (ACPI 3.0, sec. 10.2.2.3). 138 * (ACPI 3.0, sec. 10.2.2.3).
139 */ 139 */
140enum { 140enum {
141 ACPIBAT_BST_STATE = 0, 141 ACPIBAT_BST_STATE = 0,
142 ACPIBAT_BST_RATE = 1, 142 ACPIBAT_BST_RATE = 1,
143 ACPIBAT_BST_CAPACITY = 2, 143 ACPIBAT_BST_CAPACITY = 2,
144 ACPIBAT_BST_VOLTAGE = 3, 144 ACPIBAT_BST_VOLTAGE = 3,
145 ACPIBAT_BST_COUNT = 4 145 ACPIBAT_BST_COUNT = 4
146}; 146};
147 147
148struct acpibat_softc { 148struct acpibat_softc {
149 struct acpi_devnode *sc_node; 149 struct acpi_devnode *sc_node;
150 struct sysmon_envsys *sc_sme; 150 struct sysmon_envsys *sc_sme;
151 struct timeval sc_last; 151 struct timeval sc_last;
152 envsys_data_t *sc_sensor; 152 envsys_data_t *sc_sensor;
153 kmutex_t sc_mutex; 153 kmutex_t sc_mutex;
154 kcondvar_t sc_condvar; 154 kcondvar_t sc_condvar;
155 int32_t sc_dcapacity; 155 int32_t sc_dcapacity;
156 int32_t sc_dvoltage; 156 int32_t sc_dvoltage;
157 int32_t sc_lcapacity; 157 int32_t sc_lcapacity;
158 int32_t sc_wcapacity; 158 int32_t sc_wcapacity;
159 int sc_present; 159 int sc_present;
160}; 160};
161 161
162static const char * const bat_hid[] = { 162static const struct device_compatible_entry compat_data[] = {
163 "PNP0C0A", 163 { .compat = "PNP0C0A" },
164 NULL 164 DEVICE_COMPAT_EOL
165}; 165};
166 166
167#define ACPIBAT_PWRUNIT_MA 0x00000001 /* mA not mW */ 167#define ACPIBAT_PWRUNIT_MA 0x00000001 /* mA not mW */
168#define ACPIBAT_ST_DISCHARGING 0x00000001 /* battery is discharging */ 168#define ACPIBAT_ST_DISCHARGING 0x00000001 /* battery is discharging */
169#define ACPIBAT_ST_CHARGING 0x00000002 /* battery is charging */ 169#define ACPIBAT_ST_CHARGING 0x00000002 /* battery is charging */
170#define ACPIBAT_ST_CRITICAL 0x00000004 /* battery is critical */ 170#define ACPIBAT_ST_CRITICAL 0x00000004 /* battery is critical */
171 171
172/* 172/*
173 * A value used when _BST or _BIF is temporarily unknown. 173 * A value used when _BST or _BIF is temporarily unknown.
174 */ 174 */
175#define ACPIBAT_VAL_UNKNOWN 0xFFFFFFFF 175#define ACPIBAT_VAL_UNKNOWN 0xFFFFFFFF
176 176
177#define ACPIBAT_VAL_ISVALID(x) \ 177#define ACPIBAT_VAL_ISVALID(x) \
178 (((x) != ACPIBAT_VAL_UNKNOWN) ? ENVSYS_SVALID : ENVSYS_SINVALID) 178 (((x) != ACPIBAT_VAL_UNKNOWN) ? ENVSYS_SVALID : ENVSYS_SINVALID)
179 179
180static int acpibat_match(device_t, cfdata_t, void *); 180static int acpibat_match(device_t, cfdata_t, void *);
181static void acpibat_attach(device_t, device_t, void *); 181static void acpibat_attach(device_t, device_t, void *);
182static int acpibat_detach(device_t, int); 182static int acpibat_detach(device_t, int);
183static int acpibat_get_sta(device_t); 183static int acpibat_get_sta(device_t);
184static ACPI_OBJECT *acpibat_get_object(ACPI_HANDLE, const char *, uint32_t); 184static ACPI_OBJECT *acpibat_get_object(ACPI_HANDLE, const char *, uint32_t);
185static void acpibat_get_info(device_t); 185static void acpibat_get_info(device_t);
186static void acpibat_print_info(device_t, ACPI_OBJECT *); 186static void acpibat_print_info(device_t, ACPI_OBJECT *);
187static void acpibat_get_status(device_t); 187static void acpibat_get_status(device_t);
188static void acpibat_update_info(void *); 188static void acpibat_update_info(void *);
189static void acpibat_update_status(void *); 189static void acpibat_update_status(void *);
190static void acpibat_init_envsys(device_t); 190static void acpibat_init_envsys(device_t);
191static void acpibat_notify_handler(ACPI_HANDLE, uint32_t, void *); 191static void acpibat_notify_handler(ACPI_HANDLE, uint32_t, void *);
192static void acpibat_refresh(struct sysmon_envsys *, envsys_data_t *); 192static void acpibat_refresh(struct sysmon_envsys *, envsys_data_t *);
193static bool acpibat_resume(device_t, const pmf_qual_t *); 193static bool acpibat_resume(device_t, const pmf_qual_t *);
194static void acpibat_get_limits(struct sysmon_envsys *, envsys_data_t *, 194static void acpibat_get_limits(struct sysmon_envsys *, envsys_data_t *,
195 sysmon_envsys_lim_t *, uint32_t *); 195 sysmon_envsys_lim_t *, uint32_t *);
196 196
197CFATTACH_DECL_NEW(acpibat, sizeof(struct acpibat_softc), 197CFATTACH_DECL_NEW(acpibat, sizeof(struct acpibat_softc),
198 acpibat_match, acpibat_attach, acpibat_detach, NULL); 198 acpibat_match, acpibat_attach, acpibat_detach, NULL);
199 199
200/* 200/*
201 * acpibat_match: 201 * acpibat_match:
202 * 202 *
203 * Autoconfiguration `match' routine. 203 * Autoconfiguration `match' routine.
204 */ 204 */
205static int 205static int
206acpibat_match(device_t parent, cfdata_t match, void *aux) 206acpibat_match(device_t parent, cfdata_t match, void *aux)
207{ 207{
208 struct acpi_attach_args *aa = aux; 208 struct acpi_attach_args *aa = aux;
209 209
210 if (aa->aa_node->ad_type != ACPI_TYPE_DEVICE) 210 return acpi_compatible_match(aa, compat_data);
211 return 0; 
212 
213 return acpi_match_hid(aa->aa_node->ad_devinfo, bat_hid); 
214} 211}
215 212
216/* 213/*
217 * acpibat_attach: 214 * acpibat_attach:
218 * 215 *
219 * Autoconfiguration `attach' routine. 216 * Autoconfiguration `attach' routine.
220 */ 217 */
221static void 218static void
222acpibat_attach(device_t parent, device_t self, void *aux) 219acpibat_attach(device_t parent, device_t self, void *aux)
223{ 220{
224 struct acpibat_softc *sc = device_private(self); 221 struct acpibat_softc *sc = device_private(self);
225 struct acpi_attach_args *aa = aux; 222 struct acpi_attach_args *aa = aux;
226 ACPI_HANDLE tmp; 223 ACPI_HANDLE tmp;
227 ACPI_STATUS rv; 224 ACPI_STATUS rv;
228 225
229 aprint_naive(": ACPI Battery\n"); 226 aprint_naive(": ACPI Battery\n");
230 aprint_normal(": ACPI Battery\n"); 227 aprint_normal(": ACPI Battery\n");
231 228
232 sc->sc_node = aa->aa_node; 229 sc->sc_node = aa->aa_node;
233 230
234 sc->sc_present = 0; 231 sc->sc_present = 0;
235 sc->sc_dvoltage = 0; 232 sc->sc_dvoltage = 0;
236 sc->sc_dcapacity = 0; 233 sc->sc_dcapacity = 0;
237 sc->sc_lcapacity = 0; 234 sc->sc_lcapacity = 0;
238 sc->sc_wcapacity = 0; 235 sc->sc_wcapacity = 0;
239 236
240 sc->sc_sme = NULL; 237 sc->sc_sme = NULL;
241 sc->sc_sensor = NULL; 238 sc->sc_sensor = NULL;
242 239
243 mutex_init(&sc->sc_mutex, MUTEX_DEFAULT, IPL_NONE); 240 mutex_init(&sc->sc_mutex, MUTEX_DEFAULT, IPL_NONE);
244 cv_init(&sc->sc_condvar, device_xname(self)); 241 cv_init(&sc->sc_condvar, device_xname(self));
245 242
246 (void)pmf_device_register(self, NULL, acpibat_resume); 243 (void)pmf_device_register(self, NULL, acpibat_resume);
247 (void)acpi_register_notify(sc->sc_node, acpibat_notify_handler); 244 (void)acpi_register_notify(sc->sc_node, acpibat_notify_handler);
248 245
249 sc->sc_sensor = kmem_zalloc(ACPIBAT_COUNT * 246 sc->sc_sensor = kmem_zalloc(ACPIBAT_COUNT *
250 sizeof(*sc->sc_sensor), KM_SLEEP); 247 sizeof(*sc->sc_sensor), KM_SLEEP);
251 248
252 if (sc->sc_sensor == NULL) 249 if (sc->sc_sensor == NULL)
253 return; 250 return;
254 251
255 config_interrupts(self, acpibat_init_envsys); 252 config_interrupts(self, acpibat_init_envsys);
256 253
257 /* 254 /*
258 * If this is ever seen, the driver should be extended. 255 * If this is ever seen, the driver should be extended.
259 */ 256 */
260 rv = AcpiGetHandle(sc->sc_node->ad_handle, "_BIX", &tmp); 257 rv = AcpiGetHandle(sc->sc_node->ad_handle, "_BIX", &tmp);
261 258
262 if (ACPI_SUCCESS(rv)) 259 if (ACPI_SUCCESS(rv))
263 aprint_verbose_dev(self, "ACPI 4.0 functionality present\n"); 260 aprint_verbose_dev(self, "ACPI 4.0 functionality present\n");
264} 261}
265 262
266/* 263/*
267 * acpibat_detach: 264 * acpibat_detach:
268 * 265 *
269 * Autoconfiguration `detach' routine. 266 * Autoconfiguration `detach' routine.
270 */ 267 */
271static int 268static int
272acpibat_detach(device_t self, int flags) 269acpibat_detach(device_t self, int flags)
273{ 270{
274 struct acpibat_softc *sc = device_private(self); 271 struct acpibat_softc *sc = device_private(self);
275 272
276 acpi_deregister_notify(sc->sc_node); 273 acpi_deregister_notify(sc->sc_node);
277 274
278 cv_destroy(&sc->sc_condvar); 275 cv_destroy(&sc->sc_condvar);
279 mutex_destroy(&sc->sc_mutex); 276 mutex_destroy(&sc->sc_mutex);
280 277
281 if (sc->sc_sme != NULL) 278 if (sc->sc_sme != NULL)
282 sysmon_envsys_unregister(sc->sc_sme); 279 sysmon_envsys_unregister(sc->sc_sme);
283 280
284 if (sc->sc_sensor != NULL) 281 if (sc->sc_sensor != NULL)
285 kmem_free(sc->sc_sensor, ACPIBAT_COUNT * 282 kmem_free(sc->sc_sensor, ACPIBAT_COUNT *
286 sizeof(*sc->sc_sensor)); 283 sizeof(*sc->sc_sensor));
287 284
288 pmf_device_deregister(self); 285 pmf_device_deregister(self);
289 286
290 return 0; 287 return 0;
291} 288}
292 289
293/* 290/*
294 * acpibat_get_sta: 291 * acpibat_get_sta:
295 * 292 *
296 * Evaluate whether the battery is present or absent. 293 * Evaluate whether the battery is present or absent.
297 * 294 *
298 * Returns: 0 for no battery, 1 for present, and -1 on error. 295 * Returns: 0 for no battery, 1 for present, and -1 on error.
299 */ 296 */
300static int 297static int
301acpibat_get_sta(device_t dv) 298acpibat_get_sta(device_t dv)
302{ 299{
303 struct acpibat_softc *sc = device_private(dv); 300 struct acpibat_softc *sc = device_private(dv);
304 ACPI_INTEGER val; 301 ACPI_INTEGER val;
305 ACPI_STATUS rv; 302 ACPI_STATUS rv;
306 303
307 rv = acpi_eval_integer(sc->sc_node->ad_handle, "_STA", &val); 304 rv = acpi_eval_integer(sc->sc_node->ad_handle, "_STA", &val);
308 305
309 if (ACPI_FAILURE(rv)) { 306 if (ACPI_FAILURE(rv)) {
310 aprint_error_dev(dv, "failed to evaluate _STA\n"); 307 aprint_error_dev(dv, "failed to evaluate _STA\n");
311 return -1; 308 return -1;
312 } 309 }
313 310
314 sc->sc_sensor[ACPIBAT_PRESENT].state = ENVSYS_SVALID; 311 sc->sc_sensor[ACPIBAT_PRESENT].state = ENVSYS_SVALID;
315 312
316 if ((val & ACPI_STA_BATTERY_PRESENT) == 0) { 313 if ((val & ACPI_STA_BATTERY_PRESENT) == 0) {
317 sc->sc_sensor[ACPIBAT_PRESENT].value_cur = 0; 314 sc->sc_sensor[ACPIBAT_PRESENT].value_cur = 0;
318 return 0; 315 return 0;
319 } 316 }
320 317
321 sc->sc_sensor[ACPIBAT_PRESENT].value_cur = 1; 318 sc->sc_sensor[ACPIBAT_PRESENT].value_cur = 1;
322 319
323 return 1; 320 return 1;
324} 321}
325 322
326static ACPI_OBJECT * 323static ACPI_OBJECT *
327acpibat_get_object(ACPI_HANDLE hdl, const char *pth, uint32_t count) 324acpibat_get_object(ACPI_HANDLE hdl, const char *pth, uint32_t count)
328{ 325{
329 ACPI_OBJECT *obj; 326 ACPI_OBJECT *obj;
330 ACPI_BUFFER buf; 327 ACPI_BUFFER buf;
331 ACPI_STATUS rv; 328 ACPI_STATUS rv;
332 329
333 rv = acpi_eval_struct(hdl, pth, &buf); 330 rv = acpi_eval_struct(hdl, pth, &buf);
334 331
335 if (ACPI_FAILURE(rv)) 332 if (ACPI_FAILURE(rv))
336 return NULL; 333 return NULL;
337 334
338 obj = buf.Pointer; 335 obj = buf.Pointer;
339 336
340 if (obj->Type != ACPI_TYPE_PACKAGE) { 337 if (obj->Type != ACPI_TYPE_PACKAGE) {
341 ACPI_FREE(buf.Pointer); 338 ACPI_FREE(buf.Pointer);
342 return NULL; 339 return NULL;
343 } 340 }
344 341
345 if (obj->Package.Count != count) { 342 if (obj->Package.Count != count) {
346 ACPI_FREE(buf.Pointer); 343 ACPI_FREE(buf.Pointer);
347 return NULL; 344 return NULL;
348 } 345 }
349 346
350 return obj; 347 return obj;
351} 348}
352 349
353/* 350/*
354 * acpibat_get_info: 351 * acpibat_get_info:
355 * 352 *
356 * Get the battery info. 353 * Get the battery info.
357 */ 354 */
358static void 355static void
359acpibat_get_info(device_t dv) 356acpibat_get_info(device_t dv)
360{ 357{
361 struct acpibat_softc *sc = device_private(dv); 358 struct acpibat_softc *sc = device_private(dv);
362 ACPI_HANDLE hdl = sc->sc_node->ad_handle; 359 ACPI_HANDLE hdl = sc->sc_node->ad_handle;
363 ACPI_OBJECT *elm, *obj; 360 ACPI_OBJECT *elm, *obj;
364 ACPI_STATUS rv = AE_OK; 361 ACPI_STATUS rv = AE_OK;
365 int capunit, i, rateunit; 362 int capunit, i, rateunit;
366 uint64_t val; 363 uint64_t val;
367 364
368 obj = acpibat_get_object(hdl, "_BIF", ACPIBAT_BIF_COUNT); 365 obj = acpibat_get_object(hdl, "_BIF", ACPIBAT_BIF_COUNT);
369 366
370 if (obj == NULL) { 367 if (obj == NULL) {
371 rv = AE_ERROR; 368 rv = AE_ERROR;
372 goto out; 369 goto out;
373 } 370 }
374 371
375 elm = obj->Package.Elements; 372 elm = obj->Package.Elements;
376 373
377 for (i = ACPIBAT_BIF_UNIT; i < ACPIBAT_BIF_MODEL; i++) { 374 for (i = ACPIBAT_BIF_UNIT; i < ACPIBAT_BIF_MODEL; i++) {
378 375
379 if (elm[i].Type != ACPI_TYPE_INTEGER) { 376 if (elm[i].Type != ACPI_TYPE_INTEGER) {
380 rv = AE_TYPE; 377 rv = AE_TYPE;
381 goto out; 378 goto out;
382 } 379 }
383 380
384 if (elm[i].Integer.Value != ACPIBAT_VAL_UNKNOWN && 381 if (elm[i].Integer.Value != ACPIBAT_VAL_UNKNOWN &&
385 elm[i].Integer.Value >= INT_MAX) { 382 elm[i].Integer.Value >= INT_MAX) {
386 rv = AE_LIMIT; 383 rv = AE_LIMIT;
387 goto out; 384 goto out;
388 } 385 }
389 } 386 }
390 387
391 switch (elm[ACPIBAT_BIF_UNIT].Integer.Value) { 388 switch (elm[ACPIBAT_BIF_UNIT].Integer.Value) {
392 case ACPIBAT_PWRUNIT_MA: 389 case ACPIBAT_PWRUNIT_MA:
393 capunit = ENVSYS_SAMPHOUR; 390 capunit = ENVSYS_SAMPHOUR;
394 rateunit = ENVSYS_SAMPS; 391 rateunit = ENVSYS_SAMPS;
395 break; 392 break;
396 default: 393 default:
397 capunit = ENVSYS_SWATTHOUR; 394 capunit = ENVSYS_SWATTHOUR;
398 rateunit = ENVSYS_SWATTS; 395 rateunit = ENVSYS_SWATTS;
399 break; 396 break;
400 } 397 }
401 398
402 sc->sc_sensor[ACPIBAT_DCAPACITY].units = capunit; 399 sc->sc_sensor[ACPIBAT_DCAPACITY].units = capunit;
403 sc->sc_sensor[ACPIBAT_LFCCAPACITY].units = capunit; 400 sc->sc_sensor[ACPIBAT_LFCCAPACITY].units = capunit;
404 sc->sc_sensor[ACPIBAT_CHARGERATE].units = rateunit; 401 sc->sc_sensor[ACPIBAT_CHARGERATE].units = rateunit;
405 sc->sc_sensor[ACPIBAT_DISCHARGERATE].units = rateunit; 402 sc->sc_sensor[ACPIBAT_DISCHARGERATE].units = rateunit;
406 sc->sc_sensor[ACPIBAT_CAPACITY].units = capunit; 403 sc->sc_sensor[ACPIBAT_CAPACITY].units = capunit;
407 404
408 /* Design capacity. */ 405 /* Design capacity. */
409 val = elm[ACPIBAT_BIF_DCAPACITY].Integer.Value; 406 val = elm[ACPIBAT_BIF_DCAPACITY].Integer.Value;
410 sc->sc_sensor[ACPIBAT_DCAPACITY].value_cur = val * 1000; 407 sc->sc_sensor[ACPIBAT_DCAPACITY].value_cur = val * 1000;
411 sc->sc_sensor[ACPIBAT_DCAPACITY].state = ACPIBAT_VAL_ISVALID(val); 408 sc->sc_sensor[ACPIBAT_DCAPACITY].state = ACPIBAT_VAL_ISVALID(val);
412 409
413 /* Last full charge capacity. */ 410 /* Last full charge capacity. */
414 val = elm[ACPIBAT_BIF_LFCCAPACITY].Integer.Value; 411 val = elm[ACPIBAT_BIF_LFCCAPACITY].Integer.Value;
415 sc->sc_sensor[ACPIBAT_LFCCAPACITY].value_cur = val * 1000; 412 sc->sc_sensor[ACPIBAT_LFCCAPACITY].value_cur = val * 1000;
416 sc->sc_sensor[ACPIBAT_LFCCAPACITY].state = ACPIBAT_VAL_ISVALID(val); 413 sc->sc_sensor[ACPIBAT_LFCCAPACITY].state = ACPIBAT_VAL_ISVALID(val);
417 414
418 /* Design voltage. */ 415 /* Design voltage. */
419 val = elm[ACPIBAT_BIF_DVOLTAGE].Integer.Value; 416 val = elm[ACPIBAT_BIF_DVOLTAGE].Integer.Value;
420 sc->sc_sensor[ACPIBAT_DVOLTAGE].value_cur = val * 1000; 417 sc->sc_sensor[ACPIBAT_DVOLTAGE].value_cur = val * 1000;
421 sc->sc_sensor[ACPIBAT_DVOLTAGE].state = ACPIBAT_VAL_ISVALID(val); 418 sc->sc_sensor[ACPIBAT_DVOLTAGE].state = ACPIBAT_VAL_ISVALID(val);
422 419
423 /* Design low and warning capacity. */ 420 /* Design low and warning capacity. */
424 sc->sc_lcapacity = elm[ACPIBAT_BIF_LCAPACITY].Integer.Value * 1000; 421 sc->sc_lcapacity = elm[ACPIBAT_BIF_LCAPACITY].Integer.Value * 1000;
425 sc->sc_wcapacity = elm[ACPIBAT_BIF_WCAPACITY].Integer.Value * 1000; 422 sc->sc_wcapacity = elm[ACPIBAT_BIF_WCAPACITY].Integer.Value * 1000;
426 423
427 /* 424 /*
428 * Initialize the maximum of current capacity 425 * Initialize the maximum of current capacity
429 * to the last known full charge capacity. 426 * to the last known full charge capacity.
430 */ 427 */
431 val = sc->sc_sensor[ACPIBAT_LFCCAPACITY].value_cur; 428 val = sc->sc_sensor[ACPIBAT_LFCCAPACITY].value_cur;
432 sc->sc_sensor[ACPIBAT_CAPACITY].value_max = val; 429 sc->sc_sensor[ACPIBAT_CAPACITY].value_max = val;
433 430
434 acpibat_print_info(dv, elm); 431 acpibat_print_info(dv, elm);
435 432
436out: 433out:
437 if (obj != NULL) 434 if (obj != NULL)
438 ACPI_FREE(obj); 435 ACPI_FREE(obj);
439 436
440 if (ACPI_FAILURE(rv)) 437 if (ACPI_FAILURE(rv))
441 aprint_error_dev(dv, "failed to evaluate _BIF: %s\n", 438 aprint_error_dev(dv, "failed to evaluate _BIF: %s\n",
442 AcpiFormatException(rv)); 439 AcpiFormatException(rv));
443} 440}
444 441
445/* 442/*
446 * acpibat_print_info: 443 * acpibat_print_info:
447 * 444 *
448 * Display the battery info. 445 * Display the battery info.
449 */ 446 */
450static void 447static void
451acpibat_print_info(device_t dv, ACPI_OBJECT *elm) 448acpibat_print_info(device_t dv, ACPI_OBJECT *elm)
452{ 449{
453 struct acpibat_softc *sc = device_private(dv); 450 struct acpibat_softc *sc = device_private(dv);
454 const char *tech, *unit; 451 const char *tech, *unit;
455 int32_t dcap, dvol; 452 int32_t dcap, dvol;
456 int i; 453 int i;
457 454
458 for (i = ACPIBAT_BIF_OEM; i > ACPIBAT_BIF_GRANULARITY2; i--) { 455 for (i = ACPIBAT_BIF_OEM; i > ACPIBAT_BIF_GRANULARITY2; i--) {
459 456
460 if (elm[i].Type != ACPI_TYPE_STRING) 457 if (elm[i].Type != ACPI_TYPE_STRING)
461 return; 458 return;
462 459
463 if (elm[i].String.Pointer == NULL) 460 if (elm[i].String.Pointer == NULL)
464 return; 461 return;
465 462
466 if (elm[i].String.Pointer[0] == '\0') 463 if (elm[i].String.Pointer[0] == '\0')
467 return; 464 return;
468 } 465 }
469 466
470 dcap = elm[ACPIBAT_BIF_DCAPACITY].Integer.Value; 467 dcap = elm[ACPIBAT_BIF_DCAPACITY].Integer.Value;
471 dvol = elm[ACPIBAT_BIF_DVOLTAGE].Integer.Value; 468 dvol = elm[ACPIBAT_BIF_DVOLTAGE].Integer.Value;
472 469
473 /* 470 /*
474 * Try to detect whether the battery was switched. 471 * Try to detect whether the battery was switched.
475 */ 472 */
476 if (sc->sc_dcapacity == dcap && sc->sc_dvoltage == dvol) 473 if (sc->sc_dcapacity == dcap && sc->sc_dvoltage == dvol)
477 return; 474 return;
478 else { 475 else {
479 sc->sc_dcapacity = dcap; 476 sc->sc_dcapacity = dcap;
480 sc->sc_dvoltage = dvol; 477 sc->sc_dvoltage = dvol;
481 } 478 }
482 479
483 tech = (elm[ACPIBAT_BIF_TECHNOLOGY].Integer.Value != 0) ? 480 tech = (elm[ACPIBAT_BIF_TECHNOLOGY].Integer.Value != 0) ?
484 "rechargeable" : "non-rechargeable"; 481 "rechargeable" : "non-rechargeable";
485 482
486 aprint_normal_dev(dv, "%s %s %s battery\n", 483 aprint_normal_dev(dv, "%s %s %s battery\n",
487 elm[ACPIBAT_BIF_OEM].String.Pointer, 484 elm[ACPIBAT_BIF_OEM].String.Pointer,
488 elm[ACPIBAT_BIF_TYPE].String.Pointer, tech); 485 elm[ACPIBAT_BIF_TYPE].String.Pointer, tech);
489 486
490 aprint_debug_dev(dv, "model number %s, serial number %s\n", 487 aprint_debug_dev(dv, "model number %s, serial number %s\n",
491 elm[ACPIBAT_BIF_MODEL].String.Pointer, 488 elm[ACPIBAT_BIF_MODEL].String.Pointer,
492 elm[ACPIBAT_BIF_SERIAL].String.Pointer); 489 elm[ACPIBAT_BIF_SERIAL].String.Pointer);
493 490
494#define SCALE(x) (((int)x) / 1000000), ((((int)x) % 1000000) / 1000) 491#define SCALE(x) (((int)x) / 1000000), ((((int)x) % 1000000) / 1000)
495 492
496 /* 493 /*
497 * These values are defined as follows (ACPI 4.0, p. 388): 494 * These values are defined as follows (ACPI 4.0, p. 388):
498 * 495 *
499 * Granularity 1. "Battery capacity granularity between low 496 * Granularity 1. "Battery capacity granularity between low
500 * and warning in [mAh] or [mWh]. That is, 497 * and warning in [mAh] or [mWh]. That is,
501 * this is the smallest increment in capacity 498 * this is the smallest increment in capacity
502 * that the battery is capable of measuring." 499 * that the battery is capable of measuring."
503 * 500 *
504 * Granularity 2. "Battery capacity granularity between warning 501 * Granularity 2. "Battery capacity granularity between warning
505 * and full in [mAh] or [mWh]. [...]" 502 * and full in [mAh] or [mWh]. [...]"
506 */ 503 */
507 switch (elm[ACPIBAT_BIF_UNIT].Integer.Value) { 504 switch (elm[ACPIBAT_BIF_UNIT].Integer.Value) {
508 case ACPIBAT_PWRUNIT_MA: 505 case ACPIBAT_PWRUNIT_MA:
509 unit = "Ah"; 506 unit = "Ah";
510 break; 507 break;
511 default: 508 default:
512 unit = "Wh"; 509 unit = "Wh";
513 break; 510 break;
514 } 511 }
515 512
516 aprint_verbose_dev(dv, "granularity: " 513 aprint_verbose_dev(dv, "granularity: "
517 "low->warn %d.%03d %s, warn->full %d.%03d %s\n", 514 "low->warn %d.%03d %s, warn->full %d.%03d %s\n",
518 SCALE(elm[ACPIBAT_BIF_GRANULARITY1].Integer.Value * 1000), unit, 515 SCALE(elm[ACPIBAT_BIF_GRANULARITY1].Integer.Value * 1000), unit,
519 SCALE(elm[ACPIBAT_BIF_GRANULARITY2].Integer.Value * 1000), unit); 516 SCALE(elm[ACPIBAT_BIF_GRANULARITY2].Integer.Value * 1000), unit);
520} 517}
521 518
522/* 519/*
523 * acpibat_get_status: 520 * acpibat_get_status:
524 * 521 *
525 * Get the current battery status. 522 * Get the current battery status.
526 */ 523 */
527static void 524static void
528acpibat_get_status(device_t dv) 525acpibat_get_status(device_t dv)
529{ 526{
530 struct acpibat_softc *sc = device_private(dv); 527 struct acpibat_softc *sc = device_private(dv);
531 ACPI_HANDLE hdl = sc->sc_node->ad_handle; 528 ACPI_HANDLE hdl = sc->sc_node->ad_handle;
532 ACPI_OBJECT *elm, *obj; 529 ACPI_OBJECT *elm, *obj;
533 ACPI_STATUS rv = AE_OK; 530 ACPI_STATUS rv = AE_OK;
534 int i, rate, state; 531 int i, rate, state;
535 uint64_t val; 532 uint64_t val;
536 533
537 obj = acpibat_get_object(hdl, "_BST", ACPIBAT_BST_COUNT); 534 obj = acpibat_get_object(hdl, "_BST", ACPIBAT_BST_COUNT);
538 535
539 if (obj == NULL) { 536 if (obj == NULL) {
540 rv = AE_ERROR; 537 rv = AE_ERROR;
541 goto out; 538 goto out;
542 } 539 }
543 540
544 elm = obj->Package.Elements; 541 elm = obj->Package.Elements;
545 542
546 for (i = ACPIBAT_BST_STATE; i < ACPIBAT_BST_COUNT; i++) { 543 for (i = ACPIBAT_BST_STATE; i < ACPIBAT_BST_COUNT; i++) {
547 544
548 if (elm[i].Type != ACPI_TYPE_INTEGER) { 545 if (elm[i].Type != ACPI_TYPE_INTEGER) {
549 rv = AE_TYPE; 546 rv = AE_TYPE;
550 goto out; 547 goto out;
551 } 548 }
552 } 549 }
553 550
554 state = elm[ACPIBAT_BST_STATE].Integer.Value; 551 state = elm[ACPIBAT_BST_STATE].Integer.Value;
555 552
556 if ((state & ACPIBAT_ST_CHARGING) != 0) { 553 if ((state & ACPIBAT_ST_CHARGING) != 0) {
557 /* XXX rate can be invalid */ 554 /* XXX rate can be invalid */
558 rate = elm[ACPIBAT_BST_RATE].Integer.Value; 555 rate = elm[ACPIBAT_BST_RATE].Integer.Value;
559 sc->sc_sensor[ACPIBAT_CHARGERATE].state = ENVSYS_SVALID; 556 sc->sc_sensor[ACPIBAT_CHARGERATE].state = ENVSYS_SVALID;
560 sc->sc_sensor[ACPIBAT_CHARGERATE].value_cur = rate * 1000; 557 sc->sc_sensor[ACPIBAT_CHARGERATE].value_cur = rate * 1000;
561 sc->sc_sensor[ACPIBAT_DISCHARGERATE].state = ENVSYS_SINVALID; 558 sc->sc_sensor[ACPIBAT_DISCHARGERATE].state = ENVSYS_SINVALID;
562 sc->sc_sensor[ACPIBAT_CHARGING].state = ENVSYS_SVALID; 559 sc->sc_sensor[ACPIBAT_CHARGING].state = ENVSYS_SVALID;
563 sc->sc_sensor[ACPIBAT_CHARGING].value_cur = 1; 560 sc->sc_sensor[ACPIBAT_CHARGING].value_cur = 1;
564 } else if ((state & ACPIBAT_ST_DISCHARGING) != 0) { 561 } else if ((state & ACPIBAT_ST_DISCHARGING) != 0) {
565 rate = elm[ACPIBAT_BST_RATE].Integer.Value; 562 rate = elm[ACPIBAT_BST_RATE].Integer.Value;
566 sc->sc_sensor[ACPIBAT_DISCHARGERATE].state = ENVSYS_SVALID; 563 sc->sc_sensor[ACPIBAT_DISCHARGERATE].state = ENVSYS_SVALID;
567 sc->sc_sensor[ACPIBAT_DISCHARGERATE].value_cur = rate * 1000; 564 sc->sc_sensor[ACPIBAT_DISCHARGERATE].value_cur = rate * 1000;
568 sc->sc_sensor[ACPIBAT_CHARGERATE].state = ENVSYS_SINVALID; 565 sc->sc_sensor[ACPIBAT_CHARGERATE].state = ENVSYS_SINVALID;
569 sc->sc_sensor[ACPIBAT_CHARGING].state = ENVSYS_SVALID; 566 sc->sc_sensor[ACPIBAT_CHARGING].state = ENVSYS_SVALID;
570 sc->sc_sensor[ACPIBAT_CHARGING].value_cur = 0; 567 sc->sc_sensor[ACPIBAT_CHARGING].value_cur = 0;
571 } else { 568 } else {
572 sc->sc_sensor[ACPIBAT_CHARGING].state = ENVSYS_SVALID; 569 sc->sc_sensor[ACPIBAT_CHARGING].state = ENVSYS_SVALID;
573 sc->sc_sensor[ACPIBAT_CHARGING].value_cur = 0; 570 sc->sc_sensor[ACPIBAT_CHARGING].value_cur = 0;
574 sc->sc_sensor[ACPIBAT_CHARGERATE].state = ENVSYS_SINVALID; 571 sc->sc_sensor[ACPIBAT_CHARGERATE].state = ENVSYS_SINVALID;
575 sc->sc_sensor[ACPIBAT_DISCHARGERATE].state = ENVSYS_SINVALID; 572 sc->sc_sensor[ACPIBAT_DISCHARGERATE].state = ENVSYS_SINVALID;
576 } 573 }
577 574
578 /* Remaining capacity. */ 575 /* Remaining capacity. */
579 val = elm[ACPIBAT_BST_CAPACITY].Integer.Value; 576 val = elm[ACPIBAT_BST_CAPACITY].Integer.Value;
580 sc->sc_sensor[ACPIBAT_CAPACITY].value_cur = val * 1000; 577 sc->sc_sensor[ACPIBAT_CAPACITY].value_cur = val * 1000;
581 sc->sc_sensor[ACPIBAT_CAPACITY].state = ACPIBAT_VAL_ISVALID(val); 578 sc->sc_sensor[ACPIBAT_CAPACITY].state = ACPIBAT_VAL_ISVALID(val);
582 579
583 /* Battery voltage. */ 580 /* Battery voltage. */
584 val = elm[ACPIBAT_BST_VOLTAGE].Integer.Value; 581 val = elm[ACPIBAT_BST_VOLTAGE].Integer.Value;
585 sc->sc_sensor[ACPIBAT_VOLTAGE].value_cur = val * 1000; 582 sc->sc_sensor[ACPIBAT_VOLTAGE].value_cur = val * 1000;
586 sc->sc_sensor[ACPIBAT_VOLTAGE].state = ACPIBAT_VAL_ISVALID(val); 583 sc->sc_sensor[ACPIBAT_VOLTAGE].state = ACPIBAT_VAL_ISVALID(val);
587 584
588 sc->sc_sensor[ACPIBAT_CHARGE_STATE].state = ENVSYS_SVALID; 585 sc->sc_sensor[ACPIBAT_CHARGE_STATE].state = ENVSYS_SVALID;
589 sc->sc_sensor[ACPIBAT_CHARGE_STATE].value_cur = 586 sc->sc_sensor[ACPIBAT_CHARGE_STATE].value_cur =
590 ENVSYS_BATTERY_CAPACITY_NORMAL; 587 ENVSYS_BATTERY_CAPACITY_NORMAL;
591 588
592 if (sc->sc_sensor[ACPIBAT_CAPACITY].value_cur < sc->sc_wcapacity) { 589 if (sc->sc_sensor[ACPIBAT_CAPACITY].value_cur < sc->sc_wcapacity) {
593 sc->sc_sensor[ACPIBAT_CAPACITY].state = ENVSYS_SWARNUNDER; 590 sc->sc_sensor[ACPIBAT_CAPACITY].state = ENVSYS_SWARNUNDER;
594 sc->sc_sensor[ACPIBAT_CHARGE_STATE].value_cur = 591 sc->sc_sensor[ACPIBAT_CHARGE_STATE].value_cur =
595 ENVSYS_BATTERY_CAPACITY_WARNING; 592 ENVSYS_BATTERY_CAPACITY_WARNING;
596 } 593 }
597 594
598 if (sc->sc_sensor[ACPIBAT_CAPACITY].value_cur < sc->sc_lcapacity) { 595 if (sc->sc_sensor[ACPIBAT_CAPACITY].value_cur < sc->sc_lcapacity) {
599 sc->sc_sensor[ACPIBAT_CAPACITY].state = ENVSYS_SCRITUNDER; 596 sc->sc_sensor[ACPIBAT_CAPACITY].state = ENVSYS_SCRITUNDER;
600 sc->sc_sensor[ACPIBAT_CHARGE_STATE].value_cur = 597 sc->sc_sensor[ACPIBAT_CHARGE_STATE].value_cur =
601 ENVSYS_BATTERY_CAPACITY_LOW; 598 ENVSYS_BATTERY_CAPACITY_LOW;
602 } 599 }
603 600
604 if ((state & ACPIBAT_ST_CRITICAL) != 0) { 601 if ((state & ACPIBAT_ST_CRITICAL) != 0) {
605 sc->sc_sensor[ACPIBAT_CAPACITY].state = ENVSYS_SCRITICAL; 602 sc->sc_sensor[ACPIBAT_CAPACITY].state = ENVSYS_SCRITICAL;
606 sc->sc_sensor[ACPIBAT_CHARGE_STATE].value_cur = 603 sc->sc_sensor[ACPIBAT_CHARGE_STATE].value_cur =
607 ENVSYS_BATTERY_CAPACITY_CRITICAL; 604 ENVSYS_BATTERY_CAPACITY_CRITICAL;
608 } 605 }
609 606
610out: 607out:
611 if (obj != NULL) 608 if (obj != NULL)
612 ACPI_FREE(obj); 609 ACPI_FREE(obj);
613 610
614 if (ACPI_FAILURE(rv)) 611 if (ACPI_FAILURE(rv))
615 aprint_error_dev(dv, "failed to evaluate _BST: %s\n", 612 aprint_error_dev(dv, "failed to evaluate _BST: %s\n",
616 AcpiFormatException(rv)); 613 AcpiFormatException(rv));
617} 614}
618 615
619static void 616static void
620acpibat_update_info(void *arg) 617acpibat_update_info(void *arg)
621{ 618{
622 device_t dv = arg; 619 device_t dv = arg;
623 struct acpibat_softc *sc = device_private(dv); 620 struct acpibat_softc *sc = device_private(dv);
624 int i, rv; 621 int i, rv;
625 622
626 mutex_enter(&sc->sc_mutex); 623 mutex_enter(&sc->sc_mutex);
627 624
628 rv = acpibat_get_sta(dv); 625 rv = acpibat_get_sta(dv);
629 626
630 if (rv > 0) { 627 if (rv > 0) {
631 acpibat_get_info(dv); 628 acpibat_get_info(dv);
632 629
633 /* 630 /*
634 * If the status changed, update the limits. 631 * If the status changed, update the limits.
635 */ 632 */
636 if (sc->sc_present == 0 && 633 if (sc->sc_present == 0 &&
637 sc->sc_sensor[ACPIBAT_CAPACITY].value_max > 0) 634 sc->sc_sensor[ACPIBAT_CAPACITY].value_max > 0)
638 sysmon_envsys_update_limits(sc->sc_sme, 635 sysmon_envsys_update_limits(sc->sc_sme,
639 &sc->sc_sensor[ACPIBAT_CAPACITY]); 636 &sc->sc_sensor[ACPIBAT_CAPACITY]);
640 } else { 637 } else {
641 i = (rv < 0) ? 0 : ACPIBAT_DVOLTAGE; 638 i = (rv < 0) ? 0 : ACPIBAT_DVOLTAGE;
642 639
643 while (i < ACPIBAT_COUNT) { 640 while (i < ACPIBAT_COUNT) {
644 sc->sc_sensor[i].state = ENVSYS_SINVALID; 641 sc->sc_sensor[i].state = ENVSYS_SINVALID;
645 i++; 642 i++;
646 } 643 }
647 } 644 }
648 645
649 sc->sc_present = rv; 646 sc->sc_present = rv;
650 647
651 mutex_exit(&sc->sc_mutex); 648 mutex_exit(&sc->sc_mutex);
652} 649}
653 650
654static void 651static void
655acpibat_update_status(void *arg) 652acpibat_update_status(void *arg)
656{ 653{
657 device_t dv = arg; 654 device_t dv = arg;
658 struct acpibat_softc *sc = device_private(dv); 655 struct acpibat_softc *sc = device_private(dv);
659 int i, rv; 656 int i, rv;
660 657
661 mutex_enter(&sc->sc_mutex); 658 mutex_enter(&sc->sc_mutex);
662 659
663 rv = acpibat_get_sta(dv); 660 rv = acpibat_get_sta(dv);
664 661
665 if (rv > 0) { 662 if (rv > 0) {
666 663
667 if (sc->sc_present == 0) 664 if (sc->sc_present == 0)
668 acpibat_get_info(dv); 665 acpibat_get_info(dv);
669 666
670 acpibat_get_status(dv); 667 acpibat_get_status(dv);
671 } else { 668 } else {
672 i = (rv < 0) ? 0 : ACPIBAT_DVOLTAGE; 669 i = (rv < 0) ? 0 : ACPIBAT_DVOLTAGE;
673 670
674 while (i < ACPIBAT_COUNT) { 671 while (i < ACPIBAT_COUNT) {
675 sc->sc_sensor[i].state = ENVSYS_SINVALID; 672 sc->sc_sensor[i].state = ENVSYS_SINVALID;
676 i++; 673 i++;
677 } 674 }
678 } 675 }
679 676
680 sc->sc_present = rv; 677 sc->sc_present = rv;
681 microtime(&sc->sc_last); 678 microtime(&sc->sc_last);
682 679
683 cv_broadcast(&sc->sc_condvar); 680 cv_broadcast(&sc->sc_condvar);
684 mutex_exit(&sc->sc_mutex); 681 mutex_exit(&sc->sc_mutex);
685} 682}
686 683
687/* 684/*
688 * acpibat_notify_handler: 685 * acpibat_notify_handler:
689 * 686 *
690 * Callback from ACPI interrupt handler to notify us of an event. 687 * Callback from ACPI interrupt handler to notify us of an event.
691 */ 688 */
692static void 689static void
693acpibat_notify_handler(ACPI_HANDLE handle, uint32_t notify, void *context) 690acpibat_notify_handler(ACPI_HANDLE handle, uint32_t notify, void *context)
694{ 691{
695 static const int handler = OSL_NOTIFY_HANDLER; 692 static const int handler = OSL_NOTIFY_HANDLER;
696 device_t dv = context; 693 device_t dv = context;
697 694
698 switch (notify) { 695 switch (notify) {
699 696
700 case ACPI_NOTIFY_BUS_CHECK: 697 case ACPI_NOTIFY_BUS_CHECK:
701 break; 698 break;
702 699
703 case ACPI_NOTIFY_BAT_INFO: 700 case ACPI_NOTIFY_BAT_INFO:
704 case ACPI_NOTIFY_DEVICE_CHECK: 701 case ACPI_NOTIFY_DEVICE_CHECK:
705 (void)AcpiOsExecute(handler, acpibat_update_info, dv); 702 (void)AcpiOsExecute(handler, acpibat_update_info, dv);
706 break; 703 break;
707 704
708 case ACPI_NOTIFY_BAT_STATUS: 705 case ACPI_NOTIFY_BAT_STATUS:
709 (void)AcpiOsExecute(handler, acpibat_update_status, dv); 706 (void)AcpiOsExecute(handler, acpibat_update_status, dv);
710 break; 707 break;
711 708
712 default: 709 default:
713 aprint_error_dev(dv, "unknown notify: 0x%02X\n", notify); 710 aprint_error_dev(dv, "unknown notify: 0x%02X\n", notify);
714 } 711 }
715} 712}
716 713
717static void 714static void
718acpibat_init_envsys(device_t dv) 715acpibat_init_envsys(device_t dv)
719{ 716{
720 struct acpibat_softc *sc = device_private(dv); 717 struct acpibat_softc *sc = device_private(dv);
721 int i; 718 int i;
722 719
723#define INITDATA(index, unit, string) \ 720#define INITDATA(index, unit, string) \
724 do { \ 721 do { \
725 sc->sc_sensor[index].state = ENVSYS_SVALID; \ 722 sc->sc_sensor[index].state = ENVSYS_SVALID; \
726 sc->sc_sensor[index].units = unit; \ 723 sc->sc_sensor[index].units = unit; \
727 (void)strlcpy(sc->sc_sensor[index].desc, string, \ 724 (void)strlcpy(sc->sc_sensor[index].desc, string, \
728 sizeof(sc->sc_sensor[index].desc)); \ 725 sizeof(sc->sc_sensor[index].desc)); \
729 } while (/* CONSTCOND */ 0) 726 } while (/* CONSTCOND */ 0)
730 727
731 INITDATA(ACPIBAT_PRESENT, ENVSYS_INDICATOR, "present"); 728 INITDATA(ACPIBAT_PRESENT, ENVSYS_INDICATOR, "present");
732 INITDATA(ACPIBAT_DCAPACITY, ENVSYS_SWATTHOUR, "design cap"); 729 INITDATA(ACPIBAT_DCAPACITY, ENVSYS_SWATTHOUR, "design cap");
733 INITDATA(ACPIBAT_LFCCAPACITY, ENVSYS_SWATTHOUR, "last full cap"); 730 INITDATA(ACPIBAT_LFCCAPACITY, ENVSYS_SWATTHOUR, "last full cap");
734 INITDATA(ACPIBAT_DVOLTAGE, ENVSYS_SVOLTS_DC, "design voltage"); 731 INITDATA(ACPIBAT_DVOLTAGE, ENVSYS_SVOLTS_DC, "design voltage");
735 INITDATA(ACPIBAT_VOLTAGE, ENVSYS_SVOLTS_DC, "voltage"); 732 INITDATA(ACPIBAT_VOLTAGE, ENVSYS_SVOLTS_DC, "voltage");
736 INITDATA(ACPIBAT_CHARGERATE, ENVSYS_SWATTS, "charge rate"); 733 INITDATA(ACPIBAT_CHARGERATE, ENVSYS_SWATTS, "charge rate");
737 INITDATA(ACPIBAT_DISCHARGERATE, ENVSYS_SWATTS, "discharge rate"); 734 INITDATA(ACPIBAT_DISCHARGERATE, ENVSYS_SWATTS, "discharge rate");
738 INITDATA(ACPIBAT_CAPACITY, ENVSYS_SWATTHOUR, "charge"); 735 INITDATA(ACPIBAT_CAPACITY, ENVSYS_SWATTHOUR, "charge");
739 INITDATA(ACPIBAT_CHARGING, ENVSYS_BATTERY_CHARGE, "charging"); 736 INITDATA(ACPIBAT_CHARGING, ENVSYS_BATTERY_CHARGE, "charging");
740 INITDATA(ACPIBAT_CHARGE_STATE, ENVSYS_BATTERY_CAPACITY, "charge state"); 737 INITDATA(ACPIBAT_CHARGE_STATE, ENVSYS_BATTERY_CAPACITY, "charge state");
741 738
742#undef INITDATA 739#undef INITDATA
743 740
744 sc->sc_sensor[ACPIBAT_CHARGE_STATE].value_cur = 741 sc->sc_sensor[ACPIBAT_CHARGE_STATE].value_cur =
745 ENVSYS_BATTERY_CAPACITY_NORMAL; 742 ENVSYS_BATTERY_CAPACITY_NORMAL;
746 743
747 sc->sc_sensor[ACPIBAT_CAPACITY].flags |= 744 sc->sc_sensor[ACPIBAT_CAPACITY].flags |=
748 ENVSYS_FPERCENT | ENVSYS_FVALID_MAX | ENVSYS_FMONLIMITS; 745 ENVSYS_FPERCENT | ENVSYS_FVALID_MAX | ENVSYS_FMONLIMITS;
749 746
750 sc->sc_sensor[ACPIBAT_CHARGE_STATE].flags |= ENVSYS_FMONSTCHANGED; 747 sc->sc_sensor[ACPIBAT_CHARGE_STATE].flags |= ENVSYS_FMONSTCHANGED;
751 748
752 /* Disable userland monitoring on these sensors. */ 749 /* Disable userland monitoring on these sensors. */
753 sc->sc_sensor[ACPIBAT_VOLTAGE].flags = ENVSYS_FMONNOTSUPP; 750 sc->sc_sensor[ACPIBAT_VOLTAGE].flags = ENVSYS_FMONNOTSUPP;
754 sc->sc_sensor[ACPIBAT_CHARGERATE].flags = ENVSYS_FMONNOTSUPP; 751 sc->sc_sensor[ACPIBAT_CHARGERATE].flags = ENVSYS_FMONNOTSUPP;
755 sc->sc_sensor[ACPIBAT_DISCHARGERATE].flags = ENVSYS_FMONNOTSUPP; 752 sc->sc_sensor[ACPIBAT_DISCHARGERATE].flags = ENVSYS_FMONNOTSUPP;
756 sc->sc_sensor[ACPIBAT_DCAPACITY].flags = ENVSYS_FMONNOTSUPP; 753 sc->sc_sensor[ACPIBAT_DCAPACITY].flags = ENVSYS_FMONNOTSUPP;
757 sc->sc_sensor[ACPIBAT_LFCCAPACITY].flags = ENVSYS_FMONNOTSUPP; 754 sc->sc_sensor[ACPIBAT_LFCCAPACITY].flags = ENVSYS_FMONNOTSUPP;
758 sc->sc_sensor[ACPIBAT_DVOLTAGE].flags = ENVSYS_FMONNOTSUPP; 755 sc->sc_sensor[ACPIBAT_DVOLTAGE].flags = ENVSYS_FMONNOTSUPP;
759 756
760 /* Attach rnd(9) to the (dis)charge rates. */ 757 /* Attach rnd(9) to the (dis)charge rates. */
761 sc->sc_sensor[ACPIBAT_CHARGERATE].flags |= ENVSYS_FHAS_ENTROPY; 758 sc->sc_sensor[ACPIBAT_CHARGERATE].flags |= ENVSYS_FHAS_ENTROPY;
762 sc->sc_sensor[ACPIBAT_DISCHARGERATE].flags |= ENVSYS_FHAS_ENTROPY; 759 sc->sc_sensor[ACPIBAT_DISCHARGERATE].flags |= ENVSYS_FHAS_ENTROPY;
763 760
764 sc->sc_sme = sysmon_envsys_create(); 761 sc->sc_sme = sysmon_envsys_create();
765 762
766 for (i = 0; i < ACPIBAT_COUNT; i++) { 763 for (i = 0; i < ACPIBAT_COUNT; i++) {
767 764
768 if (sysmon_envsys_sensor_attach(sc->sc_sme, 765 if (sysmon_envsys_sensor_attach(sc->sc_sme,
769 &sc->sc_sensor[i])) 766 &sc->sc_sensor[i]))
770 goto fail; 767 goto fail;
771 } 768 }
772 769
773 sc->sc_sme->sme_name = device_xname(dv); 770 sc->sc_sme->sme_name = device_xname(dv);
774 sc->sc_sme->sme_cookie = dv; 771 sc->sc_sme->sme_cookie = dv;
775 sc->sc_sme->sme_refresh = acpibat_refresh; 772 sc->sc_sme->sme_refresh = acpibat_refresh;
776 sc->sc_sme->sme_class = SME_CLASS_BATTERY; 773 sc->sc_sme->sme_class = SME_CLASS_BATTERY;
777 sc->sc_sme->sme_flags = SME_POLL_ONLY | SME_INIT_REFRESH; 774 sc->sc_sme->sme_flags = SME_POLL_ONLY | SME_INIT_REFRESH;
778 sc->sc_sme->sme_get_limits = acpibat_get_limits; 775 sc->sc_sme->sme_get_limits = acpibat_get_limits;
779 776
780 acpibat_update_info(dv); 777 acpibat_update_info(dv);
781 acpibat_update_status(dv); 778 acpibat_update_status(dv);
782 779
783 if (sysmon_envsys_register(sc->sc_sme)) 780 if (sysmon_envsys_register(sc->sc_sme))
784 goto fail; 781 goto fail;
785 782
786 return; 783 return;
787 784
788fail: 785fail:
789 aprint_error_dev(dv, "failed to initialize sysmon\n"); 786 aprint_error_dev(dv, "failed to initialize sysmon\n");
790 787
791 sysmon_envsys_destroy(sc->sc_sme); 788 sysmon_envsys_destroy(sc->sc_sme);
792 kmem_free(sc->sc_sensor, ACPIBAT_COUNT * sizeof(*sc->sc_sensor)); 789 kmem_free(sc->sc_sensor, ACPIBAT_COUNT * sizeof(*sc->sc_sensor));
793 790
794 sc->sc_sme = NULL; 791 sc->sc_sme = NULL;
795 sc->sc_sensor = NULL; 792 sc->sc_sensor = NULL;
796} 793}
797 794
798static void 795static void
799acpibat_refresh(struct sysmon_envsys *sme, envsys_data_t *edata) 796acpibat_refresh(struct sysmon_envsys *sme, envsys_data_t *edata)
800{ 797{
801 device_t self = sme->sme_cookie; 798 device_t self = sme->sme_cookie;
802 struct acpibat_softc *sc; 799 struct acpibat_softc *sc;
803 struct timeval tv, tmp; 800 struct timeval tv, tmp;
804 ACPI_STATUS rv; 801 ACPI_STATUS rv;
805 802
806 sc = device_private(self); 803 sc = device_private(self);
807 804
808 tmp.tv_sec = 10; 805 tmp.tv_sec = 10;
809 tmp.tv_usec = 0; 806 tmp.tv_usec = 0;
810 807
811 microtime(&tv); 808 microtime(&tv);
812 timersub(&tv, &tmp, &tv); 809 timersub(&tv, &tmp, &tv);
813 810
814 if (timercmp(&tv, &sc->sc_last, <) != 0) 811 if (timercmp(&tv, &sc->sc_last, <) != 0)
815 return; 812 return;
816 813
817 if (mutex_tryenter(&sc->sc_mutex) == 0) 814 if (mutex_tryenter(&sc->sc_mutex) == 0)
818 return; 815 return;
819 816
820 rv = AcpiOsExecute(OSL_NOTIFY_HANDLER, acpibat_update_status, self); 817 rv = AcpiOsExecute(OSL_NOTIFY_HANDLER, acpibat_update_status, self);
821 818
822 if (ACPI_SUCCESS(rv)) 819 if (ACPI_SUCCESS(rv))
823 cv_timedwait(&sc->sc_condvar, &sc->sc_mutex, hz); 820 cv_timedwait(&sc->sc_condvar, &sc->sc_mutex, hz);
824 821
825 mutex_exit(&sc->sc_mutex); 822 mutex_exit(&sc->sc_mutex);
826} 823}
827 824
828static bool 825static bool
829acpibat_resume(device_t dv, const pmf_qual_t *qual) 826acpibat_resume(device_t dv, const pmf_qual_t *qual)
830{ 827{
831 828
832 (void)AcpiOsExecute(OSL_NOTIFY_HANDLER, acpibat_update_info, dv); 829 (void)AcpiOsExecute(OSL_NOTIFY_HANDLER, acpibat_update_info, dv);
833 (void)AcpiOsExecute(OSL_NOTIFY_HANDLER, acpibat_update_status, dv); 830 (void)AcpiOsExecute(OSL_NOTIFY_HANDLER, acpibat_update_status, dv);
834 831
835 return true; 832 return true;
836} 833}
837 834
838static void 835static void
839acpibat_get_limits(struct sysmon_envsys *sme, envsys_data_t *edata, 836acpibat_get_limits(struct sysmon_envsys *sme, envsys_data_t *edata,
840 sysmon_envsys_lim_t *limits, uint32_t *props) 837 sysmon_envsys_lim_t *limits, uint32_t *props)
841{ 838{
842 device_t dv = sme->sme_cookie; 839 device_t dv = sme->sme_cookie;
843 struct acpibat_softc *sc = device_private(dv); 840 struct acpibat_softc *sc = device_private(dv);
844 841
845 if (edata->sensor != ACPIBAT_CAPACITY) 842 if (edata->sensor != ACPIBAT_CAPACITY)
846 return; 843 return;
847 844
848 limits->sel_critmin = sc->sc_lcapacity; 845 limits->sel_critmin = sc->sc_lcapacity;
849 limits->sel_warnmin = sc->sc_wcapacity; 846 limits->sel_warnmin = sc->sc_wcapacity;
850 847
851 *props |= PROP_BATTCAP | PROP_BATTWARN | PROP_DRIVER_LIMITS; 848 *props |= PROP_BATTCAP | PROP_BATTWARN | PROP_DRIVER_LIMITS;
852} 849}
853 850
854MODULE(MODULE_CLASS_DRIVER, acpibat, "sysmon_envsys"); 851MODULE(MODULE_CLASS_DRIVER, acpibat, "sysmon_envsys");
855 852
856#ifdef _MODULE 853#ifdef _MODULE
857#include "ioconf.c" 854#include "ioconf.c"
858#endif 855#endif
859 856
860static int 857static int
861acpibat_modcmd(modcmd_t cmd, void *aux) 858acpibat_modcmd(modcmd_t cmd, void *aux)
862{ 859{
863 int rv = 0; 860 int rv = 0;
864 861
865 switch (cmd) { 862 switch (cmd) {
866 863
867 case MODULE_CMD_INIT: 864 case MODULE_CMD_INIT:
868 865
869#ifdef _MODULE 866#ifdef _MODULE
870 rv = config_init_component(cfdriver_ioconf_acpibat, 867 rv = config_init_component(cfdriver_ioconf_acpibat,
871 cfattach_ioconf_acpibat, cfdata_ioconf_acpibat); 868 cfattach_ioconf_acpibat, cfdata_ioconf_acpibat);
872#endif 869#endif
873 break; 870 break;
874 871
875 case MODULE_CMD_FINI: 872 case MODULE_CMD_FINI:
876 873
877#ifdef _MODULE 874#ifdef _MODULE
878 rv = config_fini_component(cfdriver_ioconf_acpibat, 875 rv = config_fini_component(cfdriver_ioconf_acpibat,
879 cfattach_ioconf_acpibat, cfdata_ioconf_acpibat); 876 cfattach_ioconf_acpibat, cfdata_ioconf_acpibat);
880#endif 877#endif
881 break; 878 break;
882 879
883 default: 880 default:
884 rv = ENOTTY; 881 rv = ENOTTY;
885 } 882 }
886 883
887 return rv; 884 return rv;
888} 885}