Sun Jan 9 09:47:56 2011 UTC ()
Print a message if ACPI 4.0 functionality is present (in which case the
driver should be updated).


(jruoho)
diff -r1.106 -r1.107 src/sys/dev/acpi/acpi_bat.c

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

--- src/sys/dev/acpi/acpi_bat.c 2011/01/04 05:48:48 1.106
+++ src/sys/dev/acpi/acpi_bat.c 2011/01/09 09:47:55 1.107
@@ -1,836 +1,846 @@ @@ -1,836 +1,846 @@
1/* $NetBSD: acpi_bat.c,v 1.106 2011/01/04 05:48:48 jruoho Exp $ */ 1/* $NetBSD: acpi_bat.c,v 1.107 2011/01/09 09:47:55 jruoho 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.106 2011/01/04 05:48:48 jruoho Exp $"); 78__KERNEL_RCSID(0, "$NetBSD: acpi_bat.c,v 1.107 2011/01/09 09:47:55 jruoho 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 envsys_data_t *sc_sensor; 151 envsys_data_t *sc_sensor;
152 char sc_serial[64]; 152 char sc_serial[64];
153 kmutex_t sc_mutex; 153 kmutex_t sc_mutex;
154 kcondvar_t sc_condvar; 154 kcondvar_t sc_condvar;
155 int32_t sc_lcapacity; 155 int32_t sc_lcapacity;
156 int32_t sc_wcapacity; 156 int32_t sc_wcapacity;
157 int sc_present; 157 int sc_present;
158}; 158};
159 159
160static const char * const bat_hid[] = { 160static const char * const bat_hid[] = {
161 "PNP0C0A", 161 "PNP0C0A",
162 NULL 162 NULL
163}; 163};
164 164
165#define ACPIBAT_PWRUNIT_MA 0x00000001 /* mA not mW */ 165#define ACPIBAT_PWRUNIT_MA 0x00000001 /* mA not mW */
166#define ACPIBAT_ST_DISCHARGING 0x00000001 /* battery is discharging */ 166#define ACPIBAT_ST_DISCHARGING 0x00000001 /* battery is discharging */
167#define ACPIBAT_ST_CHARGING 0x00000002 /* battery is charging */ 167#define ACPIBAT_ST_CHARGING 0x00000002 /* battery is charging */
168#define ACPIBAT_ST_CRITICAL 0x00000004 /* battery is critical */ 168#define ACPIBAT_ST_CRITICAL 0x00000004 /* battery is critical */
169 169
170/* 170/*
171 * A value used when _BST or _BIF is temporarily unknown. 171 * A value used when _BST or _BIF is temporarily unknown.
172 */ 172 */
173#define ACPIBAT_VAL_UNKNOWN 0xFFFFFFFF 173#define ACPIBAT_VAL_UNKNOWN 0xFFFFFFFF
174 174
175#define ACPIBAT_VAL_ISVALID(x) \ 175#define ACPIBAT_VAL_ISVALID(x) \
176 (((x) != ACPIBAT_VAL_UNKNOWN) ? ENVSYS_SVALID : ENVSYS_SINVALID) 176 (((x) != ACPIBAT_VAL_UNKNOWN) ? ENVSYS_SVALID : ENVSYS_SINVALID)
177 177
178static int acpibat_match(device_t, cfdata_t, void *); 178static int acpibat_match(device_t, cfdata_t, void *);
179static void acpibat_attach(device_t, device_t, void *); 179static void acpibat_attach(device_t, device_t, void *);
180static int acpibat_detach(device_t, int); 180static int acpibat_detach(device_t, int);
181static int acpibat_get_sta(device_t); 181static int acpibat_get_sta(device_t);
182static ACPI_OBJECT *acpibat_get_object(ACPI_HANDLE, const char *, uint32_t); 182static ACPI_OBJECT *acpibat_get_object(ACPI_HANDLE, const char *, uint32_t);
183static void acpibat_get_info(device_t); 183static void acpibat_get_info(device_t);
184static void acpibat_print_info(device_t, ACPI_OBJECT *); 184static void acpibat_print_info(device_t, ACPI_OBJECT *);
185static void acpibat_get_status(device_t); 185static void acpibat_get_status(device_t);
186static void acpibat_update_info(void *); 186static void acpibat_update_info(void *);
187static void acpibat_update_status(void *); 187static void acpibat_update_status(void *);
188static void acpibat_init_envsys(device_t); 188static void acpibat_init_envsys(device_t);
189static void acpibat_notify_handler(ACPI_HANDLE, uint32_t, void *); 189static void acpibat_notify_handler(ACPI_HANDLE, uint32_t, void *);
190static void acpibat_refresh(struct sysmon_envsys *, envsys_data_t *); 190static void acpibat_refresh(struct sysmon_envsys *, envsys_data_t *);
191static bool acpibat_resume(device_t, const pmf_qual_t *); 191static bool acpibat_resume(device_t, const pmf_qual_t *);
192static void acpibat_get_limits(struct sysmon_envsys *, envsys_data_t *, 192static void acpibat_get_limits(struct sysmon_envsys *, envsys_data_t *,
193 sysmon_envsys_lim_t *, uint32_t *); 193 sysmon_envsys_lim_t *, uint32_t *);
194 194
195CFATTACH_DECL_NEW(acpibat, sizeof(struct acpibat_softc), 195CFATTACH_DECL_NEW(acpibat, sizeof(struct acpibat_softc),
196 acpibat_match, acpibat_attach, acpibat_detach, NULL); 196 acpibat_match, acpibat_attach, acpibat_detach, NULL);
197 197
198/* 198/*
199 * acpibat_match: 199 * acpibat_match:
200 * 200 *
201 * Autoconfiguration `match' routine. 201 * Autoconfiguration `match' routine.
202 */ 202 */
203static int 203static int
204acpibat_match(device_t parent, cfdata_t match, void *aux) 204acpibat_match(device_t parent, cfdata_t match, void *aux)
205{ 205{
206 struct acpi_attach_args *aa = aux; 206 struct acpi_attach_args *aa = aux;
207 207
208 if (aa->aa_node->ad_type != ACPI_TYPE_DEVICE) 208 if (aa->aa_node->ad_type != ACPI_TYPE_DEVICE)
209 return 0; 209 return 0;
210 210
211 return acpi_match_hid(aa->aa_node->ad_devinfo, bat_hid); 211 return acpi_match_hid(aa->aa_node->ad_devinfo, bat_hid);
212} 212}
213 213
214/* 214/*
215 * acpibat_attach: 215 * acpibat_attach:
216 * 216 *
217 * Autoconfiguration `attach' routine. 217 * Autoconfiguration `attach' routine.
218 */ 218 */
219static void 219static void
220acpibat_attach(device_t parent, device_t self, void *aux) 220acpibat_attach(device_t parent, device_t self, void *aux)
221{ 221{
222 struct acpibat_softc *sc = device_private(self); 222 struct acpibat_softc *sc = device_private(self);
223 struct acpi_attach_args *aa = aux; 223 struct acpi_attach_args *aa = aux;
 224 ACPI_HANDLE tmp;
 225 ACPI_STATUS rv;
224 226
225 aprint_naive(": ACPI Battery\n"); 227 aprint_naive(": ACPI Battery\n");
226 aprint_normal(": ACPI Battery\n"); 228 aprint_normal(": ACPI Battery\n");
227 229
228 sc->sc_node = aa->aa_node; 230 sc->sc_node = aa->aa_node;
229 231
230 sc->sc_present = 0; 232 sc->sc_present = 0;
231 sc->sc_lcapacity = 0; 233 sc->sc_lcapacity = 0;
232 sc->sc_wcapacity = 0; 234 sc->sc_wcapacity = 0;
233 235
234 sc->sc_sme = NULL; 236 sc->sc_sme = NULL;
235 sc->sc_sensor = NULL; 237 sc->sc_sensor = NULL;
236 238
237 mutex_init(&sc->sc_mutex, MUTEX_DEFAULT, IPL_NONE); 239 mutex_init(&sc->sc_mutex, MUTEX_DEFAULT, IPL_NONE);
238 cv_init(&sc->sc_condvar, device_xname(self)); 240 cv_init(&sc->sc_condvar, device_xname(self));
239 241
240 (void)pmf_device_register(self, NULL, acpibat_resume); 242 (void)pmf_device_register(self, NULL, acpibat_resume);
241 (void)memset(sc->sc_serial, '\0', sizeof(sc->sc_serial)); 243 (void)memset(sc->sc_serial, '\0', sizeof(sc->sc_serial));
242 (void)acpi_register_notify(sc->sc_node, acpibat_notify_handler); 244 (void)acpi_register_notify(sc->sc_node, acpibat_notify_handler);
243 245
244 sc->sc_sensor = kmem_zalloc(ACPIBAT_COUNT * 246 sc->sc_sensor = kmem_zalloc(ACPIBAT_COUNT *
245 sizeof(*sc->sc_sensor), KM_SLEEP); 247 sizeof(*sc->sc_sensor), KM_SLEEP);
246 248
247 if (sc->sc_sensor == NULL) 249 if (sc->sc_sensor == NULL)
248 return; 250 return;
249 251
250 acpibat_init_envsys(self); 252 acpibat_init_envsys(self);
 253
 254 /*
 255 * If this is ever seen, the driver should be extended.
 256 */
 257 rv = AcpiGetHandle(sc->sc_node->ad_handle, "_BIX", &tmp);
 258
 259 if (ACPI_SUCCESS(rv))
 260 aprint_verbose_dev(self, "ACPI 4.0 functionality present\n");
251} 261}
252 262
253/* 263/*
254 * acpibat_detach: 264 * acpibat_detach:
255 * 265 *
256 * Autoconfiguration `detach' routine. 266 * Autoconfiguration `detach' routine.
257 */ 267 */
258static int 268static int
259acpibat_detach(device_t self, int flags) 269acpibat_detach(device_t self, int flags)
260{ 270{
261 struct acpibat_softc *sc = device_private(self); 271 struct acpibat_softc *sc = device_private(self);
262 272
263 acpi_deregister_notify(sc->sc_node); 273 acpi_deregister_notify(sc->sc_node);
264 274
265 cv_destroy(&sc->sc_condvar); 275 cv_destroy(&sc->sc_condvar);
266 mutex_destroy(&sc->sc_mutex); 276 mutex_destroy(&sc->sc_mutex);
267 277
268 if (sc->sc_sme != NULL) 278 if (sc->sc_sme != NULL)
269 sysmon_envsys_unregister(sc->sc_sme); 279 sysmon_envsys_unregister(sc->sc_sme);
270 280
271 if (sc->sc_sensor != NULL) 281 if (sc->sc_sensor != NULL)
272 kmem_free(sc->sc_sensor, ACPIBAT_COUNT * 282 kmem_free(sc->sc_sensor, ACPIBAT_COUNT *
273 sizeof(*sc->sc_sensor)); 283 sizeof(*sc->sc_sensor));
274 284
275 pmf_device_deregister(self); 285 pmf_device_deregister(self);
276 286
277 return 0; 287 return 0;
278} 288}
279 289
280/* 290/*
281 * acpibat_get_sta: 291 * acpibat_get_sta:
282 * 292 *
283 * Evaluate whether the battery is present or absent. 293 * Evaluate whether the battery is present or absent.
284 * 294 *
285 * 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.
286 */ 296 */
287static int 297static int
288acpibat_get_sta(device_t dv) 298acpibat_get_sta(device_t dv)
289{ 299{
290 struct acpibat_softc *sc = device_private(dv); 300 struct acpibat_softc *sc = device_private(dv);
291 ACPI_INTEGER val; 301 ACPI_INTEGER val;
292 ACPI_STATUS rv; 302 ACPI_STATUS rv;
293 303
294 rv = acpi_eval_integer(sc->sc_node->ad_handle, "_STA", &val); 304 rv = acpi_eval_integer(sc->sc_node->ad_handle, "_STA", &val);
295 305
296 if (ACPI_FAILURE(rv)) { 306 if (ACPI_FAILURE(rv)) {
297 aprint_error_dev(dv, "failed to evaluate _STA\n"); 307 aprint_error_dev(dv, "failed to evaluate _STA\n");
298 return -1; 308 return -1;
299 } 309 }
300 310
301 sc->sc_sensor[ACPIBAT_PRESENT].state = ENVSYS_SVALID; 311 sc->sc_sensor[ACPIBAT_PRESENT].state = ENVSYS_SVALID;
302 312
303 if ((val & ACPI_STA_BATTERY_PRESENT) == 0) { 313 if ((val & ACPI_STA_BATTERY_PRESENT) == 0) {
304 sc->sc_sensor[ACPIBAT_PRESENT].value_cur = 0; 314 sc->sc_sensor[ACPIBAT_PRESENT].value_cur = 0;
305 return 0; 315 return 0;
306 } 316 }
307 317
308 sc->sc_sensor[ACPIBAT_PRESENT].value_cur = 1; 318 sc->sc_sensor[ACPIBAT_PRESENT].value_cur = 1;
309 319
310 return 1; 320 return 1;
311} 321}
312 322
313static ACPI_OBJECT * 323static ACPI_OBJECT *
314acpibat_get_object(ACPI_HANDLE hdl, const char *pth, uint32_t count) 324acpibat_get_object(ACPI_HANDLE hdl, const char *pth, uint32_t count)
315{ 325{
316 ACPI_OBJECT *obj; 326 ACPI_OBJECT *obj;
317 ACPI_BUFFER buf; 327 ACPI_BUFFER buf;
318 ACPI_STATUS rv; 328 ACPI_STATUS rv;
319 329
320 rv = acpi_eval_struct(hdl, pth, &buf); 330 rv = acpi_eval_struct(hdl, pth, &buf);
321 331
322 if (ACPI_FAILURE(rv)) 332 if (ACPI_FAILURE(rv))
323 return NULL; 333 return NULL;
324 334
325 obj = buf.Pointer; 335 obj = buf.Pointer;
326 336
327 if (obj->Type != ACPI_TYPE_PACKAGE) { 337 if (obj->Type != ACPI_TYPE_PACKAGE) {
328 ACPI_FREE(buf.Pointer); 338 ACPI_FREE(buf.Pointer);
329 return NULL; 339 return NULL;
330 } 340 }
331 341
332 if (obj->Package.Count != count) { 342 if (obj->Package.Count != count) {
333 ACPI_FREE(buf.Pointer); 343 ACPI_FREE(buf.Pointer);
334 return NULL; 344 return NULL;
335 } 345 }
336 346
337 return obj; 347 return obj;
338} 348}
339 349
340/* 350/*
341 * acpibat_get_info: 351 * acpibat_get_info:
342 * 352 *
343 * Get the battery info. 353 * Get the battery info.
344 */ 354 */
345static void 355static void
346acpibat_get_info(device_t dv) 356acpibat_get_info(device_t dv)
347{ 357{
348 struct acpibat_softc *sc = device_private(dv); 358 struct acpibat_softc *sc = device_private(dv);
349 ACPI_HANDLE hdl = sc->sc_node->ad_handle; 359 ACPI_HANDLE hdl = sc->sc_node->ad_handle;
350 ACPI_OBJECT *elm, *obj; 360 ACPI_OBJECT *elm, *obj;
351 ACPI_STATUS rv = AE_OK; 361 ACPI_STATUS rv = AE_OK;
352 int capunit, i, rateunit; 362 int capunit, i, rateunit;
353 uint64_t val; 363 uint64_t val;
354 364
355 obj = acpibat_get_object(hdl, "_BIF", ACPIBAT_BIF_COUNT); 365 obj = acpibat_get_object(hdl, "_BIF", ACPIBAT_BIF_COUNT);
356 366
357 if (obj == NULL) { 367 if (obj == NULL) {
358 rv = AE_ERROR; 368 rv = AE_ERROR;
359 goto out; 369 goto out;
360 } 370 }
361 371
362 elm = obj->Package.Elements; 372 elm = obj->Package.Elements;
363 373
364 for (i = ACPIBAT_BIF_UNIT; i < ACPIBAT_BIF_MODEL; i++) { 374 for (i = ACPIBAT_BIF_UNIT; i < ACPIBAT_BIF_MODEL; i++) {
365 375
366 if (elm[i].Type != ACPI_TYPE_INTEGER) { 376 if (elm[i].Type != ACPI_TYPE_INTEGER) {
367 rv = AE_TYPE; 377 rv = AE_TYPE;
368 goto out; 378 goto out;
369 } 379 }
370 380
371 KDASSERT((uint64_t)elm[i].Integer.Value < INT_MAX); 381 KDASSERT((uint64_t)elm[i].Integer.Value < INT_MAX);
372 } 382 }
373 383
374 if ((elm[ACPIBAT_BIF_UNIT].Integer.Value & ACPIBAT_PWRUNIT_MA) != 0) { 384 if ((elm[ACPIBAT_BIF_UNIT].Integer.Value & ACPIBAT_PWRUNIT_MA) != 0) {
375 capunit = ENVSYS_SAMPHOUR; 385 capunit = ENVSYS_SAMPHOUR;
376 rateunit = ENVSYS_SAMPS; 386 rateunit = ENVSYS_SAMPS;
377 } else { 387 } else {
378 capunit = ENVSYS_SWATTHOUR; 388 capunit = ENVSYS_SWATTHOUR;
379 rateunit = ENVSYS_SWATTS; 389 rateunit = ENVSYS_SWATTS;
380 } 390 }
381 391
382 sc->sc_sensor[ACPIBAT_DCAPACITY].units = capunit; 392 sc->sc_sensor[ACPIBAT_DCAPACITY].units = capunit;
383 sc->sc_sensor[ACPIBAT_LFCCAPACITY].units = capunit; 393 sc->sc_sensor[ACPIBAT_LFCCAPACITY].units = capunit;
384 sc->sc_sensor[ACPIBAT_CHARGERATE].units = rateunit; 394 sc->sc_sensor[ACPIBAT_CHARGERATE].units = rateunit;
385 sc->sc_sensor[ACPIBAT_DISCHARGERATE].units = rateunit; 395 sc->sc_sensor[ACPIBAT_DISCHARGERATE].units = rateunit;
386 sc->sc_sensor[ACPIBAT_CAPACITY].units = capunit; 396 sc->sc_sensor[ACPIBAT_CAPACITY].units = capunit;
387 397
388 /* Design capacity. */ 398 /* Design capacity. */
389 val = elm[ACPIBAT_BIF_DCAPACITY].Integer.Value; 399 val = elm[ACPIBAT_BIF_DCAPACITY].Integer.Value;
390 sc->sc_sensor[ACPIBAT_DCAPACITY].value_cur = val * 1000; 400 sc->sc_sensor[ACPIBAT_DCAPACITY].value_cur = val * 1000;
391 sc->sc_sensor[ACPIBAT_DCAPACITY].state = ACPIBAT_VAL_ISVALID(val); 401 sc->sc_sensor[ACPIBAT_DCAPACITY].state = ACPIBAT_VAL_ISVALID(val);
392 402
393 /* Last full charge capacity. */ 403 /* Last full charge capacity. */
394 val = elm[ACPIBAT_BIF_LFCCAPACITY].Integer.Value; 404 val = elm[ACPIBAT_BIF_LFCCAPACITY].Integer.Value;
395 sc->sc_sensor[ACPIBAT_LFCCAPACITY].value_cur = val * 1000; 405 sc->sc_sensor[ACPIBAT_LFCCAPACITY].value_cur = val * 1000;
396 sc->sc_sensor[ACPIBAT_LFCCAPACITY].state = ACPIBAT_VAL_ISVALID(val); 406 sc->sc_sensor[ACPIBAT_LFCCAPACITY].state = ACPIBAT_VAL_ISVALID(val);
397 407
398 /* Design voltage. */ 408 /* Design voltage. */
399 val = elm[ACPIBAT_BIF_DVOLTAGE].Integer.Value; 409 val = elm[ACPIBAT_BIF_DVOLTAGE].Integer.Value;
400 sc->sc_sensor[ACPIBAT_DVOLTAGE].value_cur = val * 1000; 410 sc->sc_sensor[ACPIBAT_DVOLTAGE].value_cur = val * 1000;
401 sc->sc_sensor[ACPIBAT_DVOLTAGE].state = ACPIBAT_VAL_ISVALID(val); 411 sc->sc_sensor[ACPIBAT_DVOLTAGE].state = ACPIBAT_VAL_ISVALID(val);
402 412
403 /* Design low and warning capacity. */ 413 /* Design low and warning capacity. */
404 sc->sc_lcapacity = elm[ACPIBAT_BIF_LCAPACITY].Integer.Value * 1000; 414 sc->sc_lcapacity = elm[ACPIBAT_BIF_LCAPACITY].Integer.Value * 1000;
405 sc->sc_wcapacity = elm[ACPIBAT_BIF_WCAPACITY].Integer.Value * 1000; 415 sc->sc_wcapacity = elm[ACPIBAT_BIF_WCAPACITY].Integer.Value * 1000;
406 416
407 /* 417 /*
408 * Initialize the maximum of current capacity 418 * Initialize the maximum of current capacity
409 * to the last known full charge capacity. 419 * to the last known full charge capacity.
410 */ 420 */
411 val = sc->sc_sensor[ACPIBAT_LFCCAPACITY].value_cur; 421 val = sc->sc_sensor[ACPIBAT_LFCCAPACITY].value_cur;
412 sc->sc_sensor[ACPIBAT_CAPACITY].value_max = val; 422 sc->sc_sensor[ACPIBAT_CAPACITY].value_max = val;
413 423
414 acpibat_print_info(dv, elm); 424 acpibat_print_info(dv, elm);
415 425
416out: 426out:
417 if (obj != NULL) 427 if (obj != NULL)
418 ACPI_FREE(obj); 428 ACPI_FREE(obj);
419 429
420 if (ACPI_FAILURE(rv)) 430 if (ACPI_FAILURE(rv))
421 aprint_error_dev(dv, "failed to evaluate _BIF: %s\n", 431 aprint_error_dev(dv, "failed to evaluate _BIF: %s\n",
422 AcpiFormatException(rv)); 432 AcpiFormatException(rv));
423} 433}
424 434
425/* 435/*
426 * acpibat_print_info: 436 * acpibat_print_info:
427 * 437 *
428 * Display the battery info. 438 * Display the battery info.
429 */ 439 */
430static void 440static void
431acpibat_print_info(device_t dv, ACPI_OBJECT *elm) 441acpibat_print_info(device_t dv, ACPI_OBJECT *elm)
432{ 442{
433 struct acpibat_softc *sc = device_private(dv); 443 struct acpibat_softc *sc = device_private(dv);
434 const char *model, *serial, *tech, *unit; 444 const char *model, *serial, *tech, *unit;
435 int i; 445 int i;
436 446
437 for (i = ACPIBAT_BIF_OEM; i > ACPIBAT_BIF_GRANULARITY2; i--) { 447 for (i = ACPIBAT_BIF_OEM; i > ACPIBAT_BIF_GRANULARITY2; i--) {
438 448
439 if (elm[i].Type != ACPI_TYPE_STRING) 449 if (elm[i].Type != ACPI_TYPE_STRING)
440 return; 450 return;
441 451
442 if (elm[i].String.Pointer == NULL) 452 if (elm[i].String.Pointer == NULL)
443 return; 453 return;
444 454
445 if (elm[i].String.Pointer[0] == '\0') 455 if (elm[i].String.Pointer[0] == '\0')
446 return; 456 return;
447 } 457 }
448 458
449 model = elm[ACPIBAT_BIF_MODEL].String.Pointer; 459 model = elm[ACPIBAT_BIF_MODEL].String.Pointer;
450 serial = elm[ACPIBAT_BIF_SERIAL].String.Pointer; 460 serial = elm[ACPIBAT_BIF_SERIAL].String.Pointer;
451 461
452 if (elm[ACPIBAT_BIF_SERIAL].String.Length > sizeof(sc->sc_serial)) 462 if (elm[ACPIBAT_BIF_SERIAL].String.Length > sizeof(sc->sc_serial))
453 return; 463 return;
454 464
455 if (sc->sc_serial[0] == '\0') 465 if (sc->sc_serial[0] == '\0')
456 (void)strlcpy(sc->sc_serial, serial, sizeof(sc->sc_serial)); 466 (void)strlcpy(sc->sc_serial, serial, sizeof(sc->sc_serial));
457 else { 467 else {
458 if (strcmp(sc->sc_serial, serial) == 0) 468 if (strcmp(sc->sc_serial, serial) == 0)
459 return; 469 return;
460 470
461 (void)memset(sc->sc_serial, '\0', sizeof(sc->sc_serial)); 471 (void)memset(sc->sc_serial, '\0', sizeof(sc->sc_serial));
462 (void)strlcpy(sc->sc_serial, serial, sizeof(sc->sc_serial)); 472 (void)strlcpy(sc->sc_serial, serial, sizeof(sc->sc_serial));
463 } 473 }
464 474
465 tech = (elm[ACPIBAT_BIF_TECHNOLOGY].Integer.Value != 0) ? 475 tech = (elm[ACPIBAT_BIF_TECHNOLOGY].Integer.Value != 0) ?
466 "rechargeable" : "non-rechargeable"; 476 "rechargeable" : "non-rechargeable";
467 477
468 aprint_normal_dev(dv, "%s %s %s battery\n", 478 aprint_normal_dev(dv, "%s %s %s battery\n",
469 elm[ACPIBAT_BIF_OEM].String.Pointer, 479 elm[ACPIBAT_BIF_OEM].String.Pointer,
470 elm[ACPIBAT_BIF_TYPE].String.Pointer, tech); 480 elm[ACPIBAT_BIF_TYPE].String.Pointer, tech);
471 481
472 aprint_verbose_dev(dv, "model number %s, serial number %s\n", 482 aprint_verbose_dev(dv, "model number %s, serial number %s\n",
473 model, serial); 483 model, serial);
474 484
475#define SCALE(x) (((int)x) / 1000000), ((((int)x) % 1000000) / 1000) 485#define SCALE(x) (((int)x) / 1000000), ((((int)x) % 1000000) / 1000)
476 486
477 /* 487 /*
478 * These values are defined as follows (ACPI 4.0, p. 388): 488 * These values are defined as follows (ACPI 4.0, p. 388):
479 * 489 *
480 * Granularity 1. "Battery capacity granularity between low 490 * Granularity 1. "Battery capacity granularity between low
481 * and warning in [mAh] or [mWh]. That is, 491 * and warning in [mAh] or [mWh]. That is,
482 * this is the smallest increment in capacity 492 * this is the smallest increment in capacity
483 * that the battery is capable of measuring." 493 * that the battery is capable of measuring."
484 * 494 *
485 * Granularity 2. "Battery capacity granularity between warning 495 * Granularity 2. "Battery capacity granularity between warning
486 * and full in [mAh] or [mWh]. [...]" 496 * and full in [mAh] or [mWh]. [...]"
487 */ 497 */
488 if ((elm[ACPIBAT_BIF_UNIT].Integer.Value & ACPIBAT_PWRUNIT_MA) != 0) 498 if ((elm[ACPIBAT_BIF_UNIT].Integer.Value & ACPIBAT_PWRUNIT_MA) != 0)
489 unit = "Ah"; 499 unit = "Ah";
490 else 500 else
491 unit = "Wh"; 501 unit = "Wh";
492 502
493 aprint_verbose_dev(dv, "granularity: " 503 aprint_verbose_dev(dv, "granularity: "
494 "low->warn %d.%03d %s, warn->full %d.%03d %s\n", 504 "low->warn %d.%03d %s, warn->full %d.%03d %s\n",
495 SCALE(elm[ACPIBAT_BIF_GRANULARITY1].Integer.Value * 1000), unit, 505 SCALE(elm[ACPIBAT_BIF_GRANULARITY1].Integer.Value * 1000), unit,
496 SCALE(elm[ACPIBAT_BIF_GRANULARITY2].Integer.Value * 1000), unit); 506 SCALE(elm[ACPIBAT_BIF_GRANULARITY2].Integer.Value * 1000), unit);
497} 507}
498 508
499/* 509/*
500 * acpibat_get_status: 510 * acpibat_get_status:
501 * 511 *
502 * Get the current battery status. 512 * Get the current battery status.
503 */ 513 */
504static void 514static void
505acpibat_get_status(device_t dv) 515acpibat_get_status(device_t dv)
506{ 516{
507 struct acpibat_softc *sc = device_private(dv); 517 struct acpibat_softc *sc = device_private(dv);
508 ACPI_HANDLE hdl = sc->sc_node->ad_handle; 518 ACPI_HANDLE hdl = sc->sc_node->ad_handle;
509 ACPI_OBJECT *elm, *obj; 519 ACPI_OBJECT *elm, *obj;
510 ACPI_STATUS rv = AE_OK; 520 ACPI_STATUS rv = AE_OK;
511 int i, rate, state; 521 int i, rate, state;
512 uint64_t val; 522 uint64_t val;
513 523
514 obj = acpibat_get_object(hdl, "_BST", ACPIBAT_BST_COUNT); 524 obj = acpibat_get_object(hdl, "_BST", ACPIBAT_BST_COUNT);
515 525
516 if (obj == NULL) { 526 if (obj == NULL) {
517 rv = AE_ERROR; 527 rv = AE_ERROR;
518 goto out; 528 goto out;
519 } 529 }
520 530
521 elm = obj->Package.Elements; 531 elm = obj->Package.Elements;
522 532
523 for (i = ACPIBAT_BST_STATE; i < ACPIBAT_BST_COUNT; i++) { 533 for (i = ACPIBAT_BST_STATE; i < ACPIBAT_BST_COUNT; i++) {
524 534
525 if (elm[i].Type != ACPI_TYPE_INTEGER) { 535 if (elm[i].Type != ACPI_TYPE_INTEGER) {
526 rv = AE_TYPE; 536 rv = AE_TYPE;
527 goto out; 537 goto out;
528 } 538 }
529 } 539 }
530 540
531 state = elm[ACPIBAT_BST_STATE].Integer.Value; 541 state = elm[ACPIBAT_BST_STATE].Integer.Value;
532 542
533 if ((state & ACPIBAT_ST_CHARGING) != 0) { 543 if ((state & ACPIBAT_ST_CHARGING) != 0) {
534 /* XXX rate can be invalid */ 544 /* XXX rate can be invalid */
535 rate = elm[ACPIBAT_BST_RATE].Integer.Value; 545 rate = elm[ACPIBAT_BST_RATE].Integer.Value;
536 sc->sc_sensor[ACPIBAT_CHARGERATE].state = ENVSYS_SVALID; 546 sc->sc_sensor[ACPIBAT_CHARGERATE].state = ENVSYS_SVALID;
537 sc->sc_sensor[ACPIBAT_CHARGERATE].value_cur = rate * 1000; 547 sc->sc_sensor[ACPIBAT_CHARGERATE].value_cur = rate * 1000;
538 sc->sc_sensor[ACPIBAT_DISCHARGERATE].state = ENVSYS_SINVALID; 548 sc->sc_sensor[ACPIBAT_DISCHARGERATE].state = ENVSYS_SINVALID;
539 sc->sc_sensor[ACPIBAT_CHARGING].state = ENVSYS_SVALID; 549 sc->sc_sensor[ACPIBAT_CHARGING].state = ENVSYS_SVALID;
540 sc->sc_sensor[ACPIBAT_CHARGING].value_cur = 1; 550 sc->sc_sensor[ACPIBAT_CHARGING].value_cur = 1;
541 } else if ((state & ACPIBAT_ST_DISCHARGING) != 0) { 551 } else if ((state & ACPIBAT_ST_DISCHARGING) != 0) {
542 rate = elm[ACPIBAT_BST_RATE].Integer.Value; 552 rate = elm[ACPIBAT_BST_RATE].Integer.Value;
543 sc->sc_sensor[ACPIBAT_DISCHARGERATE].state = ENVSYS_SVALID; 553 sc->sc_sensor[ACPIBAT_DISCHARGERATE].state = ENVSYS_SVALID;
544 sc->sc_sensor[ACPIBAT_DISCHARGERATE].value_cur = rate * 1000; 554 sc->sc_sensor[ACPIBAT_DISCHARGERATE].value_cur = rate * 1000;
545 sc->sc_sensor[ACPIBAT_CHARGERATE].state = ENVSYS_SINVALID; 555 sc->sc_sensor[ACPIBAT_CHARGERATE].state = ENVSYS_SINVALID;
546 sc->sc_sensor[ACPIBAT_CHARGING].state = ENVSYS_SVALID; 556 sc->sc_sensor[ACPIBAT_CHARGING].state = ENVSYS_SVALID;
547 sc->sc_sensor[ACPIBAT_CHARGING].value_cur = 0; 557 sc->sc_sensor[ACPIBAT_CHARGING].value_cur = 0;
548 } else { 558 } else {
549 sc->sc_sensor[ACPIBAT_CHARGING].state = ENVSYS_SVALID; 559 sc->sc_sensor[ACPIBAT_CHARGING].state = ENVSYS_SVALID;
550 sc->sc_sensor[ACPIBAT_CHARGING].value_cur = 0; 560 sc->sc_sensor[ACPIBAT_CHARGING].value_cur = 0;
551 sc->sc_sensor[ACPIBAT_CHARGERATE].state = ENVSYS_SINVALID; 561 sc->sc_sensor[ACPIBAT_CHARGERATE].state = ENVSYS_SINVALID;
552 sc->sc_sensor[ACPIBAT_DISCHARGERATE].state = ENVSYS_SINVALID; 562 sc->sc_sensor[ACPIBAT_DISCHARGERATE].state = ENVSYS_SINVALID;
553 } 563 }
554 564
555 /* Remaining capacity. */ 565 /* Remaining capacity. */
556 val = elm[ACPIBAT_BST_CAPACITY].Integer.Value; 566 val = elm[ACPIBAT_BST_CAPACITY].Integer.Value;
557 sc->sc_sensor[ACPIBAT_CAPACITY].value_cur = val * 1000; 567 sc->sc_sensor[ACPIBAT_CAPACITY].value_cur = val * 1000;
558 sc->sc_sensor[ACPIBAT_CAPACITY].state = ACPIBAT_VAL_ISVALID(val); 568 sc->sc_sensor[ACPIBAT_CAPACITY].state = ACPIBAT_VAL_ISVALID(val);
559 569
560 /* Battery voltage. */ 570 /* Battery voltage. */
561 val = elm[ACPIBAT_BST_VOLTAGE].Integer.Value; 571 val = elm[ACPIBAT_BST_VOLTAGE].Integer.Value;
562 sc->sc_sensor[ACPIBAT_VOLTAGE].value_cur = val * 1000; 572 sc->sc_sensor[ACPIBAT_VOLTAGE].value_cur = val * 1000;
563 sc->sc_sensor[ACPIBAT_VOLTAGE].state = ACPIBAT_VAL_ISVALID(val); 573 sc->sc_sensor[ACPIBAT_VOLTAGE].state = ACPIBAT_VAL_ISVALID(val);
564 574
565 sc->sc_sensor[ACPIBAT_CHARGE_STATE].state = ENVSYS_SVALID; 575 sc->sc_sensor[ACPIBAT_CHARGE_STATE].state = ENVSYS_SVALID;
566 sc->sc_sensor[ACPIBAT_CHARGE_STATE].value_cur = 576 sc->sc_sensor[ACPIBAT_CHARGE_STATE].value_cur =
567 ENVSYS_BATTERY_CAPACITY_NORMAL; 577 ENVSYS_BATTERY_CAPACITY_NORMAL;
568 578
569 if (sc->sc_sensor[ACPIBAT_CAPACITY].value_cur < sc->sc_wcapacity) { 579 if (sc->sc_sensor[ACPIBAT_CAPACITY].value_cur < sc->sc_wcapacity) {
570 sc->sc_sensor[ACPIBAT_CAPACITY].state = ENVSYS_SWARNUNDER; 580 sc->sc_sensor[ACPIBAT_CAPACITY].state = ENVSYS_SWARNUNDER;
571 sc->sc_sensor[ACPIBAT_CHARGE_STATE].value_cur = 581 sc->sc_sensor[ACPIBAT_CHARGE_STATE].value_cur =
572 ENVSYS_BATTERY_CAPACITY_WARNING; 582 ENVSYS_BATTERY_CAPACITY_WARNING;
573 } 583 }
574 584
575 if (sc->sc_sensor[ACPIBAT_CAPACITY].value_cur < sc->sc_lcapacity) { 585 if (sc->sc_sensor[ACPIBAT_CAPACITY].value_cur < sc->sc_lcapacity) {
576 sc->sc_sensor[ACPIBAT_CAPACITY].state = ENVSYS_SCRITUNDER; 586 sc->sc_sensor[ACPIBAT_CAPACITY].state = ENVSYS_SCRITUNDER;
577 sc->sc_sensor[ACPIBAT_CHARGE_STATE].value_cur = 587 sc->sc_sensor[ACPIBAT_CHARGE_STATE].value_cur =
578 ENVSYS_BATTERY_CAPACITY_LOW; 588 ENVSYS_BATTERY_CAPACITY_LOW;
579 } 589 }
580 590
581 if ((state & ACPIBAT_ST_CRITICAL) != 0) { 591 if ((state & ACPIBAT_ST_CRITICAL) != 0) {
582 sc->sc_sensor[ACPIBAT_CAPACITY].state = ENVSYS_SCRITICAL; 592 sc->sc_sensor[ACPIBAT_CAPACITY].state = ENVSYS_SCRITICAL;
583 sc->sc_sensor[ACPIBAT_CHARGE_STATE].value_cur = 593 sc->sc_sensor[ACPIBAT_CHARGE_STATE].value_cur =
584 ENVSYS_BATTERY_CAPACITY_CRITICAL; 594 ENVSYS_BATTERY_CAPACITY_CRITICAL;
585 } 595 }
586 596
587out: 597out:
588 if (obj != NULL) 598 if (obj != NULL)
589 ACPI_FREE(obj); 599 ACPI_FREE(obj);
590 600
591 if (ACPI_FAILURE(rv)) 601 if (ACPI_FAILURE(rv))
592 aprint_error_dev(dv, "failed to evaluate _BST: %s\n", 602 aprint_error_dev(dv, "failed to evaluate _BST: %s\n",
593 AcpiFormatException(rv)); 603 AcpiFormatException(rv));
594} 604}
595 605
596static void 606static void
597acpibat_update_info(void *arg) 607acpibat_update_info(void *arg)
598{ 608{
599 device_t dv = arg; 609 device_t dv = arg;
600 struct acpibat_softc *sc = device_private(dv); 610 struct acpibat_softc *sc = device_private(dv);
601 int i, rv; 611 int i, rv;
602 612
603 mutex_enter(&sc->sc_mutex); 613 mutex_enter(&sc->sc_mutex);
604 614
605 rv = acpibat_get_sta(dv); 615 rv = acpibat_get_sta(dv);
606 616
607 if (rv > 0) { 617 if (rv > 0) {
608 acpibat_get_info(dv); 618 acpibat_get_info(dv);
609 619
610 /* 620 /*
611 * If the status changed, update the limits. 621 * If the status changed, update the limits.
612 */ 622 */
613 if (sc->sc_present == 0 && 623 if (sc->sc_present == 0 &&
614 sc->sc_sensor[ACPIBAT_CAPACITY].value_max > 0) 624 sc->sc_sensor[ACPIBAT_CAPACITY].value_max > 0)
615 sysmon_envsys_update_limits(sc->sc_sme, 625 sysmon_envsys_update_limits(sc->sc_sme,
616 &sc->sc_sensor[ACPIBAT_CAPACITY]); 626 &sc->sc_sensor[ACPIBAT_CAPACITY]);
617 } else { 627 } else {
618 i = (rv < 0) ? 0 : ACPIBAT_DVOLTAGE; 628 i = (rv < 0) ? 0 : ACPIBAT_DVOLTAGE;
619 629
620 while (i < ACPIBAT_COUNT) { 630 while (i < ACPIBAT_COUNT) {
621 sc->sc_sensor[i].state = ENVSYS_SINVALID; 631 sc->sc_sensor[i].state = ENVSYS_SINVALID;
622 i++; 632 i++;
623 } 633 }
624 } 634 }
625 635
626 sc->sc_present = rv; 636 sc->sc_present = rv;
627 637
628 mutex_exit(&sc->sc_mutex); 638 mutex_exit(&sc->sc_mutex);
629} 639}
630 640
631static void 641static void
632acpibat_update_status(void *arg) 642acpibat_update_status(void *arg)
633{ 643{
634 device_t dv = arg; 644 device_t dv = arg;
635 struct acpibat_softc *sc = device_private(dv); 645 struct acpibat_softc *sc = device_private(dv);
636 int i, rv; 646 int i, rv;
637 647
638 mutex_enter(&sc->sc_mutex); 648 mutex_enter(&sc->sc_mutex);
639 649
640 rv = acpibat_get_sta(dv); 650 rv = acpibat_get_sta(dv);
641 651
642 if (rv > 0) { 652 if (rv > 0) {
643 653
644 if (sc->sc_present == 0) 654 if (sc->sc_present == 0)
645 acpibat_get_info(dv); 655 acpibat_get_info(dv);
646 656
647 acpibat_get_status(dv); 657 acpibat_get_status(dv);
648 } else { 658 } else {
649 i = (rv < 0) ? 0 : ACPIBAT_DVOLTAGE; 659 i = (rv < 0) ? 0 : ACPIBAT_DVOLTAGE;
650 660
651 while (i < ACPIBAT_COUNT) { 661 while (i < ACPIBAT_COUNT) {
652 sc->sc_sensor[i].state = ENVSYS_SINVALID; 662 sc->sc_sensor[i].state = ENVSYS_SINVALID;
653 i++; 663 i++;
654 } 664 }
655 } 665 }
656 666
657 sc->sc_present = rv; 667 sc->sc_present = rv;
658 668
659 cv_broadcast(&sc->sc_condvar); 669 cv_broadcast(&sc->sc_condvar);
660 mutex_exit(&sc->sc_mutex); 670 mutex_exit(&sc->sc_mutex);
661} 671}
662 672
663/* 673/*
664 * acpibat_notify_handler: 674 * acpibat_notify_handler:
665 * 675 *
666 * Callback from ACPI interrupt handler to notify us of an event. 676 * Callback from ACPI interrupt handler to notify us of an event.
667 */ 677 */
668static void 678static void
669acpibat_notify_handler(ACPI_HANDLE handle, uint32_t notify, void *context) 679acpibat_notify_handler(ACPI_HANDLE handle, uint32_t notify, void *context)
670{ 680{
671 static const int handler = OSL_NOTIFY_HANDLER; 681 static const int handler = OSL_NOTIFY_HANDLER;
672 device_t dv = context; 682 device_t dv = context;
673 683
674 switch (notify) { 684 switch (notify) {
675 685
676 case ACPI_NOTIFY_BUS_CHECK: 686 case ACPI_NOTIFY_BUS_CHECK:
677 break; 687 break;
678 688
679 case ACPI_NOTIFY_BAT_INFO: 689 case ACPI_NOTIFY_BAT_INFO:
680 case ACPI_NOTIFY_DEVICE_CHECK: 690 case ACPI_NOTIFY_DEVICE_CHECK:
681 (void)AcpiOsExecute(handler, acpibat_update_info, dv); 691 (void)AcpiOsExecute(handler, acpibat_update_info, dv);
682 break; 692 break;
683 693
684 case ACPI_NOTIFY_BAT_STATUS: 694 case ACPI_NOTIFY_BAT_STATUS:
685 (void)AcpiOsExecute(handler, acpibat_update_status, dv); 695 (void)AcpiOsExecute(handler, acpibat_update_status, dv);
686 break; 696 break;
687 697
688 default: 698 default:
689 aprint_error_dev(dv, "unknown notify: 0x%02X\n", notify); 699 aprint_error_dev(dv, "unknown notify: 0x%02X\n", notify);
690 } 700 }
691} 701}
692 702
693static void 703static void
694acpibat_init_envsys(device_t dv) 704acpibat_init_envsys(device_t dv)
695{ 705{
696 struct acpibat_softc *sc = device_private(dv); 706 struct acpibat_softc *sc = device_private(dv);
697 int i; 707 int i;
698 708
699#define INITDATA(index, unit, string) \ 709#define INITDATA(index, unit, string) \
700 do { \ 710 do { \
701 sc->sc_sensor[index].state = ENVSYS_SVALID; \ 711 sc->sc_sensor[index].state = ENVSYS_SVALID; \
702 sc->sc_sensor[index].units = unit; \ 712 sc->sc_sensor[index].units = unit; \
703 (void)strlcpy(sc->sc_sensor[index].desc, string, \ 713 (void)strlcpy(sc->sc_sensor[index].desc, string, \
704 sizeof(sc->sc_sensor[index].desc)); \ 714 sizeof(sc->sc_sensor[index].desc)); \
705 } while (/* CONSTCOND */ 0) 715 } while (/* CONSTCOND */ 0)
706 716
707 INITDATA(ACPIBAT_PRESENT, ENVSYS_INDICATOR, "present"); 717 INITDATA(ACPIBAT_PRESENT, ENVSYS_INDICATOR, "present");
708 INITDATA(ACPIBAT_DCAPACITY, ENVSYS_SWATTHOUR, "design cap"); 718 INITDATA(ACPIBAT_DCAPACITY, ENVSYS_SWATTHOUR, "design cap");
709 INITDATA(ACPIBAT_LFCCAPACITY, ENVSYS_SWATTHOUR, "last full cap"); 719 INITDATA(ACPIBAT_LFCCAPACITY, ENVSYS_SWATTHOUR, "last full cap");
710 INITDATA(ACPIBAT_DVOLTAGE, ENVSYS_SVOLTS_DC, "design voltage"); 720 INITDATA(ACPIBAT_DVOLTAGE, ENVSYS_SVOLTS_DC, "design voltage");
711 INITDATA(ACPIBAT_VOLTAGE, ENVSYS_SVOLTS_DC, "voltage"); 721 INITDATA(ACPIBAT_VOLTAGE, ENVSYS_SVOLTS_DC, "voltage");
712 INITDATA(ACPIBAT_CHARGERATE, ENVSYS_SWATTS, "charge rate"); 722 INITDATA(ACPIBAT_CHARGERATE, ENVSYS_SWATTS, "charge rate");
713 INITDATA(ACPIBAT_DISCHARGERATE, ENVSYS_SWATTS, "discharge rate"); 723 INITDATA(ACPIBAT_DISCHARGERATE, ENVSYS_SWATTS, "discharge rate");
714 INITDATA(ACPIBAT_CAPACITY, ENVSYS_SWATTHOUR, "charge"); 724 INITDATA(ACPIBAT_CAPACITY, ENVSYS_SWATTHOUR, "charge");
715 INITDATA(ACPIBAT_CHARGING, ENVSYS_BATTERY_CHARGE, "charging"); 725 INITDATA(ACPIBAT_CHARGING, ENVSYS_BATTERY_CHARGE, "charging");
716 INITDATA(ACPIBAT_CHARGE_STATE, ENVSYS_BATTERY_CAPACITY, "charge state"); 726 INITDATA(ACPIBAT_CHARGE_STATE, ENVSYS_BATTERY_CAPACITY, "charge state");
717 727
718#undef INITDATA 728#undef INITDATA
719 729
720 sc->sc_sensor[ACPIBAT_CAPACITY].flags |= 730 sc->sc_sensor[ACPIBAT_CAPACITY].flags |=
721 ENVSYS_FPERCENT | ENVSYS_FVALID_MAX | ENVSYS_FMONLIMITS; 731 ENVSYS_FPERCENT | ENVSYS_FVALID_MAX | ENVSYS_FMONLIMITS;
722 732
723 sc->sc_sensor[ACPIBAT_CHARGE_STATE].flags |= ENVSYS_FMONSTCHANGED; 733 sc->sc_sensor[ACPIBAT_CHARGE_STATE].flags |= ENVSYS_FMONSTCHANGED;
724 734
725 /* Disable userland monitoring on these sensors. */ 735 /* Disable userland monitoring on these sensors. */
726 sc->sc_sensor[ACPIBAT_VOLTAGE].flags = ENVSYS_FMONNOTSUPP; 736 sc->sc_sensor[ACPIBAT_VOLTAGE].flags = ENVSYS_FMONNOTSUPP;
727 sc->sc_sensor[ACPIBAT_CHARGERATE].flags = ENVSYS_FMONNOTSUPP; 737 sc->sc_sensor[ACPIBAT_CHARGERATE].flags = ENVSYS_FMONNOTSUPP;
728 sc->sc_sensor[ACPIBAT_DISCHARGERATE].flags = ENVSYS_FMONNOTSUPP; 738 sc->sc_sensor[ACPIBAT_DISCHARGERATE].flags = ENVSYS_FMONNOTSUPP;
729 sc->sc_sensor[ACPIBAT_DCAPACITY].flags = ENVSYS_FMONNOTSUPP; 739 sc->sc_sensor[ACPIBAT_DCAPACITY].flags = ENVSYS_FMONNOTSUPP;
730 sc->sc_sensor[ACPIBAT_LFCCAPACITY].flags = ENVSYS_FMONNOTSUPP; 740 sc->sc_sensor[ACPIBAT_LFCCAPACITY].flags = ENVSYS_FMONNOTSUPP;
731 sc->sc_sensor[ACPIBAT_DVOLTAGE].flags = ENVSYS_FMONNOTSUPP; 741 sc->sc_sensor[ACPIBAT_DVOLTAGE].flags = ENVSYS_FMONNOTSUPP;
732 742
733 sc->sc_sme = sysmon_envsys_create(); 743 sc->sc_sme = sysmon_envsys_create();
734 744
735 for (i = 0; i < ACPIBAT_COUNT; i++) { 745 for (i = 0; i < ACPIBAT_COUNT; i++) {
736 746
737 if (sysmon_envsys_sensor_attach(sc->sc_sme, 747 if (sysmon_envsys_sensor_attach(sc->sc_sme,
738 &sc->sc_sensor[i])) 748 &sc->sc_sensor[i]))
739 goto fail; 749 goto fail;
740 } 750 }
741 751
742 sc->sc_sme->sme_name = device_xname(dv); 752 sc->sc_sme->sme_name = device_xname(dv);
743 sc->sc_sme->sme_cookie = dv; 753 sc->sc_sme->sme_cookie = dv;
744 sc->sc_sme->sme_refresh = acpibat_refresh; 754 sc->sc_sme->sme_refresh = acpibat_refresh;
745 sc->sc_sme->sme_class = SME_CLASS_BATTERY; 755 sc->sc_sme->sme_class = SME_CLASS_BATTERY;
746 sc->sc_sme->sme_flags = SME_POLL_ONLY | SME_INIT_REFRESH; 756 sc->sc_sme->sme_flags = SME_POLL_ONLY | SME_INIT_REFRESH;
747 sc->sc_sme->sme_get_limits = acpibat_get_limits; 757 sc->sc_sme->sme_get_limits = acpibat_get_limits;
748 758
749 acpibat_update_info(dv); 759 acpibat_update_info(dv);
750 acpibat_update_status(dv); 760 acpibat_update_status(dv);
751 761
752 if (sysmon_envsys_register(sc->sc_sme)) 762 if (sysmon_envsys_register(sc->sc_sme))
753 goto fail; 763 goto fail;
754 764
755 return; 765 return;
756 766
757fail: 767fail:
758 aprint_error_dev(dv, "failed to initialize sysmon\n"); 768 aprint_error_dev(dv, "failed to initialize sysmon\n");
759 769
760 sysmon_envsys_destroy(sc->sc_sme); 770 sysmon_envsys_destroy(sc->sc_sme);
761 kmem_free(sc->sc_sensor, ACPIBAT_COUNT * sizeof(*sc->sc_sensor)); 771 kmem_free(sc->sc_sensor, ACPIBAT_COUNT * sizeof(*sc->sc_sensor));
762 772
763 sc->sc_sme = NULL; 773 sc->sc_sme = NULL;
764 sc->sc_sensor = NULL; 774 sc->sc_sensor = NULL;
765} 775}
766 776
767static void 777static void
768acpibat_refresh(struct sysmon_envsys *sme, envsys_data_t *edata) 778acpibat_refresh(struct sysmon_envsys *sme, envsys_data_t *edata)
769{ 779{
770 device_t dv = sme->sme_cookie; 780 device_t dv = sme->sme_cookie;
771 struct acpibat_softc *sc = device_private(dv); 781 struct acpibat_softc *sc = device_private(dv);
772 ACPI_STATUS rv; 782 ACPI_STATUS rv;
773 783
774 if (mutex_tryenter(&sc->sc_mutex) == 0) 784 if (mutex_tryenter(&sc->sc_mutex) == 0)
775 return; 785 return;
776 786
777 rv = AcpiOsExecute(OSL_NOTIFY_HANDLER, acpibat_update_status, dv); 787 rv = AcpiOsExecute(OSL_NOTIFY_HANDLER, acpibat_update_status, dv);
778 788
779 if (ACPI_SUCCESS(rv)) 789 if (ACPI_SUCCESS(rv))
780 cv_timedwait(&sc->sc_condvar, &sc->sc_mutex, hz); 790 cv_timedwait(&sc->sc_condvar, &sc->sc_mutex, hz);
781 791
782 mutex_exit(&sc->sc_mutex); 792 mutex_exit(&sc->sc_mutex);
783} 793}
784 794
785static bool 795static bool
786acpibat_resume(device_t dv, const pmf_qual_t *qual) 796acpibat_resume(device_t dv, const pmf_qual_t *qual)
787{ 797{
788 798
789 (void)AcpiOsExecute(OSL_NOTIFY_HANDLER, acpibat_update_info, dv); 799 (void)AcpiOsExecute(OSL_NOTIFY_HANDLER, acpibat_update_info, dv);
790 (void)AcpiOsExecute(OSL_NOTIFY_HANDLER, acpibat_update_status, dv); 800 (void)AcpiOsExecute(OSL_NOTIFY_HANDLER, acpibat_update_status, dv);
791 801
792 return true; 802 return true;
793} 803}
794 804
795static void 805static void
796acpibat_get_limits(struct sysmon_envsys *sme, envsys_data_t *edata, 806acpibat_get_limits(struct sysmon_envsys *sme, envsys_data_t *edata,
797 sysmon_envsys_lim_t *limits, uint32_t *props) 807 sysmon_envsys_lim_t *limits, uint32_t *props)
798{ 808{
799 device_t dv = sme->sme_cookie; 809 device_t dv = sme->sme_cookie;
800 struct acpibat_softc *sc = device_private(dv); 810 struct acpibat_softc *sc = device_private(dv);
801 811
802 if (edata->sensor != ACPIBAT_CAPACITY) 812 if (edata->sensor != ACPIBAT_CAPACITY)
803 return; 813 return;
804 814
805 limits->sel_critmin = sc->sc_lcapacity; 815 limits->sel_critmin = sc->sc_lcapacity;
806 limits->sel_warnmin = sc->sc_wcapacity; 816 limits->sel_warnmin = sc->sc_wcapacity;
807 817
808 *props |= PROP_BATTCAP | PROP_BATTWARN | PROP_DRIVER_LIMITS; 818 *props |= PROP_BATTCAP | PROP_BATTWARN | PROP_DRIVER_LIMITS;
809} 819}
810 820
811#ifdef _MODULE 821#ifdef _MODULE
812 822
813MODULE(MODULE_CLASS_DRIVER, acpibat, NULL); 823MODULE(MODULE_CLASS_DRIVER, acpibat, NULL);
814 824
815#include "ioconf.c" 825#include "ioconf.c"
816 826
817static int 827static int
818acpibat_modcmd(modcmd_t cmd, void *context) 828acpibat_modcmd(modcmd_t cmd, void *context)
819{ 829{
820 830
821 switch (cmd) { 831 switch (cmd) {
822 832
823 case MODULE_CMD_INIT: 833 case MODULE_CMD_INIT:
824 return config_init_component(cfdriver_ioconf_acpibat, 834 return config_init_component(cfdriver_ioconf_acpibat,
825 cfattach_ioconf_acpibat, cfdata_ioconf_acpibat); 835 cfattach_ioconf_acpibat, cfdata_ioconf_acpibat);
826 836
827 case MODULE_CMD_FINI: 837 case MODULE_CMD_FINI:
828 return config_fini_component(cfdriver_ioconf_acpibat, 838 return config_fini_component(cfdriver_ioconf_acpibat,
829 cfattach_ioconf_acpibat, cfdata_ioconf_acpibat); 839 cfattach_ioconf_acpibat, cfdata_ioconf_acpibat);
830 840
831 default: 841 default:
832 return ENOTTY; 842 return ENOTTY;
833 } 843 }
834} 844}
835 845
836#endif /* _MODULE */ 846#endif /* _MODULE */