xref: /illumos-gate/usr/src/uts/i86pc/io/acpi_drv/acpi_drv.c (revision b1d7ec75953cd517f5b7c3d9cb427ff8ec5d7d07)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9  * or http://www.opensolaris.org/os/licensing.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  */
21 
22 /*
23  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
24  * Use is subject to license terms.
25  */
26 
27 /*
28  * Driver for ACPI Battery, Lid, and Hotkey Control
29  */
30 #include <sys/hotkey_drv.h>
31 #include <sys/sysevent/pwrctl.h>
32 
33 
34 #define	ACPI_DRV_MOD_STRING		"ACPI driver"
35 
36 #define	MINOR_SHIFT			8
37 #define	IDX_MASK			((1 << MINOR_SHIFT) - 1)
38 #define	MINOR_BATT(idx)			(ACPI_DRV_TYPE_CBAT << MINOR_SHIFT | \
39 					(idx))
40 #define	MINOR_AC(idx)			(ACPI_DRV_TYPE_AC << MINOR_SHIFT | \
41 					(idx))
42 #define	MINOR_LID(idx)			(ACPI_DRV_TYPE_LID << MINOR_SHIFT | \
43 					(idx))
44 #define	MINOR_HOTKEY(idx)		(ACPI_DRV_TYPE_HOTKEY << MINOR_SHIFT \
45 					| (idx))
46 #define	MINOR2IDX(minor)		((minor) & IDX_MASK)
47 #define	MINOR2TYPE(minor)		((minor) >> MINOR_SHIFT)
48 
49 #define	ACPI_DRV_MAX_BAT_NUM		8
50 #define	ACPI_DRV_MAX_AC_NUM		10
51 
52 #define	BST_FLAG_DISCHARGING		(0x1)
53 #define	BST_FLAG_CHARGING		(0x2)
54 #define	BST_FLAG_CRITICAL		(0x4)
55 
56 /* Set if the battery is present */
57 #define	STA_FLAG_BATT_PRESENT		(0x10)
58 
59 #define	ACPI_DEVNAME_CBAT		"PNP0C0A"
60 #define	ACPI_DEVNAME_AC			"ACPI0003"
61 #define	ACPI_DEVNAME_LID		"PNP0C0D"
62 
63 #define	ACPI_DRV_EVENTS			(POLLIN | POLLRDNORM)
64 
65 #ifdef DEBUG
66 
67 #define	ACPI_DRV_PRINT_BUFFER_SIZE	512
68 static char acpi_drv_prt_buf[ACPI_DRV_PRINT_BUFFER_SIZE];
69 static kmutex_t acpi_drv_prt_mutex;
70 
71 static int acpi_drv_debug = 0;
72 #define	ACPI_DRV_DBG(lev, devp, ...) \
73 	do { \
74 		if (acpi_drv_debug) acpi_drv_printf((devp), \
75 (lev), __VA_ARGS__); \
76 _NOTE(CONSTCOND) } while (0)
77 #define	ACPI_DRV_PRT_NOTIFY(hdl, val) \
78 	do { \
79 		if (acpi_drv_debug) acpi_drv_prt_notify((hdl), (val)); \
80 _NOTE(CONSTCOND) } while (0)
81 
82 #else
83 
84 #define	ACPI_DRV_DBG(lev, devp, ...)
85 #define	ACPI_DRV_PRT_NOTIFY(hdl, val)
86 
87 #endif /* DEBUG */
88 
89 /* ACPI notify types */
90 enum acpi_drv_notify {
91 	ACPI_DRV_NTF_UNKNOWN = -1,	/* No notifications seen, ever. */
92 	ACPI_DRV_NTF_CHANGED,
93 	ACPI_DRV_NTF_OK
94 };
95 
96 static int acpi_drv_dev_present(struct acpi_drv_dev *);
97 #define	acpi_drv_ac_present(a)	(((a)->dev.type == ACPI_DRV_TYPE_AC) ? \
98 				acpi_drv_dev_present(&(a)->dev) : -1)
99 #define	acpi_drv_cbat_present(a)	(((a)->dev.type == ACPI_DRV_TYPE_CBAT) \
100 					? acpi_drv_dev_present(&(a)->dev) : -1)
101 
102 static dev_info_t *acpi_drv_dip = NULL;
103 static kmutex_t acpi_drv_mutex;
104 static struct pollhead acpi_drv_pollhead;
105 
106 /* Control Method Battery state */
107 struct acpi_drv_cbat_state {
108 	struct acpi_drv_dev dev;
109 	/* Caches of _BST and _BIF */
110 	enum acpi_drv_notify bat_bifok;
111 	acpi_bif_t bif_cache;
112 	enum acpi_drv_notify bat_bstok;
113 	acpi_bst_t bst_cache;
114 
115 	uint32_t charge_warn;
116 	uint32_t charge_low;
117 
118 	kstat_t *bat_bif_ksp;
119 	kstat_t *bat_bst_ksp;
120 } acpi_drv_cbat[ACPI_DRV_MAX_BAT_NUM];
121 static int nbat = 0;
122 
123 /*
124  * Synthesis battery state
125  * When there are multiple batteries present, the battery subsystem
126  * is not required to perform any synthesis of a composite battery
127  * from the data of the separate batteries. In cases where the
128  * battery subsystem does not synthesize a composite battery from
129  * the separate battery's data, the OS must provide that synthesis.
130  */
131 static uint32_t acpi_drv_syn_rem_cap;
132 static uint32_t acpi_drv_syn_last_cap;
133 static uint32_t acpi_drv_syn_oem_warn_cap;
134 static uint32_t acpi_drv_syn_oem_low_cap;
135 
136 static int acpi_drv_warn_enabled;
137 static uint32_t acpi_drv_syn_warn_per;
138 static uint32_t acpi_drv_syn_low_per;
139 static uint32_t acpi_drv_syn_warn_cap;
140 static uint32_t acpi_drv_syn_low_cap;
141 /* Tracking boundery passing of _BST charge levels */
142 static uint32_t acpi_drv_syn_last_level;
143 
144 /* AC state */
145 static struct acpi_drv_ac_state {
146 	struct acpi_drv_dev dev;
147 } acpi_drv_ac[ACPI_DRV_MAX_AC_NUM];
148 static int nac = 0;
149 
150 /*
151  * Current power source device
152  * Note: assume only one device can be the power source device.
153  */
154 static int acpi_drv_psr_type = ACPI_DRV_TYPE_UNKNOWN;
155 static struct acpi_drv_dev *acpi_drv_psr_devp = NULL;
156 
157 struct obj_desc {
158 	char *name;
159 	int offset;
160 	int size;
161 	int type;
162 };
163 
164 /* Object copy definitions */
165 #define	OFFSETOF(s, m)		((size_t)(&(((s *)0)->m)))
166 #define	SIZEOF(s, m)		(sizeof (((s *)0)->m))
167 #define	FIELD(n, s, m, t) \
168 	{ n, OFFSETOF(s, m), SIZEOF(s, m), t }
169 #define	FIELD_NULL		{ NULL, -1, 0, ACPI_TYPE_ANY }
170 
171 static struct obj_desc bif_desc[] = {
172 	FIELD("bif_unit",	acpi_bif_t, bif_unit,	ACPI_TYPE_INTEGER),
173 	FIELD("bif_design_cap", acpi_bif_t, bif_design_cap, ACPI_TYPE_INTEGER),
174 	FIELD("bif_last_cap",	acpi_bif_t, bif_last_cap,   ACPI_TYPE_INTEGER),
175 	FIELD("bif_tech",	acpi_bif_t, bif_tech,	ACPI_TYPE_INTEGER),
176 	FIELD("bif_voltage",	acpi_bif_t, bif_voltage, ACPI_TYPE_INTEGER),
177 	FIELD("bif_warn_cap",	acpi_bif_t, bif_warn_cap, ACPI_TYPE_INTEGER),
178 	FIELD("bif_low_cap",	acpi_bif_t, bif_low_cap,  ACPI_TYPE_INTEGER),
179 	FIELD("bif_gran1_cap",	acpi_bif_t, bif_gran1_cap, ACPI_TYPE_INTEGER),
180 	FIELD("bif_gran2_cap",	acpi_bif_t, bif_gran2_cap, ACPI_TYPE_INTEGER),
181 	FIELD("bif_model",	acpi_bif_t, bif_model,	ACPI_TYPE_STRING),
182 	FIELD("bif_serial",	acpi_bif_t, bif_serial,	ACPI_TYPE_STRING),
183 	FIELD("bif_type",	acpi_bif_t, bif_type,	ACPI_TYPE_STRING),
184 	FIELD("bif_oem_info",	acpi_bif_t, bif_oem_info, ACPI_TYPE_STRING),
185 	FIELD_NULL
186 };
187 
188 static struct obj_desc bst_desc[] = {
189 	FIELD("bst_state",   acpi_bst_t, bst_state,	ACPI_TYPE_INTEGER),
190 	FIELD("bst_rate",    acpi_bst_t, bst_rate,	ACPI_TYPE_INTEGER),
191 	FIELD("bst_rem_cap", acpi_bst_t, bst_rem_cap,	ACPI_TYPE_INTEGER),
192 	FIELD("bst_voltage", acpi_bst_t, bst_voltage,	ACPI_TYPE_INTEGER),
193 	FIELD_NULL
194 };
195 
196 /* kstat definitions */
197 static kstat_t *acpi_drv_power_ksp;
198 static kstat_t *acpi_drv_warn_ksp;
199 
200 acpi_drv_power_kstat_t acpi_drv_power_kstat = {
201 	{ SYSTEM_POWER,			KSTAT_DATA_STRING },
202 	{ SUPPORTED_BATTERY_COUNT,	KSTAT_DATA_UINT32 },
203 };
204 
205 acpi_drv_warn_kstat_t acpi_drv_warn_kstat = {
206 	{ BW_ENABLED,			KSTAT_DATA_UINT32 },
207 	{ BW_POWEROFF_THRESHOLD,	KSTAT_DATA_UINT32 },
208 	{ BW_SHUTDOWN_THRESHOLD,	KSTAT_DATA_UINT32 },
209 };
210 
211 /* BIF */
212 acpi_drv_bif_kstat_t acpi_drv_bif_kstat = {
213 	{ BIF_UNIT,		KSTAT_DATA_UINT32 },
214 	{ BIF_DESIGN_CAP,	KSTAT_DATA_UINT32 },
215 	{ BIF_LAST_CAP,		KSTAT_DATA_UINT32 },
216 	{ BIF_TECH,		KSTAT_DATA_UINT32 },
217 	{ BIF_VOLTAGE,		KSTAT_DATA_UINT32 },
218 	{ BIF_WARN_CAP,		KSTAT_DATA_UINT32 },
219 	{ BIF_LOW_CAP,		KSTAT_DATA_UINT32 },
220 	{ BIF_GRAN1_CAP,	KSTAT_DATA_UINT32 },
221 	{ BIF_GRAN2_CAP,	KSTAT_DATA_UINT32 },
222 	{ BIF_MODEL,		KSTAT_DATA_STRING },
223 	{ BIF_SERIAL,		KSTAT_DATA_STRING },
224 	{ BIF_TYPE,		KSTAT_DATA_STRING },
225 	{ BIF_OEM_INFO,		KSTAT_DATA_STRING },
226 };
227 
228 /* BST */
229 acpi_drv_bst_kstat_t acpi_drv_bst_kstat = {
230 	{ BST_STATE,		KSTAT_DATA_UINT32 },
231 	{ BST_RATE,		KSTAT_DATA_UINT32 },
232 	{ BST_REM_CAP,		KSTAT_DATA_UINT32 },
233 	{ BST_VOLTAGE,		KSTAT_DATA_UINT32 },
234 };
235 
236 struct acpi_drv_lid_state {
237 	struct acpi_drv_dev dev;
238 	enum acpi_drv_notify state_ok;
239 	int state;
240 } lid;
241 static int nlid = 0;
242 
243 struct hotkey_drv acpi_hotkey;
244 
245 static int acpi_drv_attach(dev_info_t *devi, ddi_attach_cmd_t cmd);
246 static int acpi_drv_detach(dev_info_t *devi, ddi_detach_cmd_t cmd);
247 static int acpi_drv_getinfo(dev_info_t *dip, ddi_info_cmd_t cmd, void *arg,
248     void **resultp);
249 static int acpi_drv_open(dev_t *devp, int flag, int otyp, cred_t *crp);
250 static int acpi_drv_close(dev_t dev, int flag, int otyp, cred_t *crp);
251 static int acpi_drv_ioctl(dev_t dev, int cmd, intptr_t arg, int mode,
252     cred_t *cr, int *rval);
253 static int acpi_drv_chpoll(dev_t dev, short events, int anyyet,
254     short *reventsp, struct pollhead **phpp);
255 static int acpi_drv_ac_ioctl(int index, int cmd, intptr_t arg, int mode,
256     cred_t *cr, int *rval);
257 static int acpi_drv_cbat_ioctl(int index, int cmd, intptr_t arg, int mode,
258     cred_t *cr, int *rval);
259 static int acpi_drv_lid_ioctl(int index, int cmd, intptr_t arg, int mode,
260     cred_t *cr, int *rval);
261 #ifdef DEBUG
262 static void acpi_drv_printf(struct acpi_drv_dev *devp, uint_t lev,
263     const char *fmt, ...);
264 #endif
265 
266 static int acpi_drv_update_bif(struct acpi_drv_cbat_state *bp);
267 static int acpi_drv_update_bst(struct acpi_drv_cbat_state *bp);
268 static int acpi_drv_update_lid(struct acpi_drv_dev *bp);
269 static int acpi_drv_set_warn(acpi_drv_warn_t *bwp);
270 static struct acpi_drv_cbat_state *acpi_drv_idx2cbat(int idx);
271 static struct acpi_drv_ac_state *acpi_drv_idx2ac(int idx);
272 static int acpi_drv_acpi_init(void);
273 static void acpi_drv_acpi_fini(void);
274 static int acpi_drv_kstat_init(void);
275 static void acpi_drv_kstat_fini(void);
276 
277 static struct cb_ops acpi_drv_cb_ops = {
278 	acpi_drv_open,		/* open */
279 	acpi_drv_close,		/* close */
280 	nodev,			/* strategy */
281 	nodev,			/* print */
282 	nodev,			/* dump */
283 	nodev,			/* read */
284 	nodev,			/* write */
285 	acpi_drv_ioctl,		/* ioctl */
286 	nodev,			/* devmap */
287 	nodev,			/* mmap */
288 	nodev,			/* segmap */
289 	acpi_drv_chpoll,		/* chpoll */
290 	ddi_prop_op,		/* prop_op */
291 	NULL,			/* streamtab */
292 	D_NEW | D_MP,
293 	CB_REV,
294 	nodev,
295 	nodev
296 };
297 
298 static struct dev_ops acpi_drv_dev_ops = {
299 	DEVO_REV,
300 	0,			/* refcnt */
301 	acpi_drv_getinfo,	/* getinfo */
302 	nulldev,		/* identify */
303 	nulldev,		/* probe */
304 	acpi_drv_attach,	/* attach */
305 	acpi_drv_detach,	/* detach */
306 	nodev,			/* reset */
307 	&acpi_drv_cb_ops,
308 	NULL,			/* no bus operations */
309 	NULL,			/* power */
310 	ddi_quiesce_not_needed,	/* quiesce */
311 };
312 
313 static struct modldrv modldrv1 = {
314 	&mod_driverops,
315 	ACPI_DRV_MOD_STRING,
316 	&acpi_drv_dev_ops
317 };
318 
319 static struct modlinkage modlinkage = {
320 	MODREV_1,
321 	(void *)&modldrv1,
322 	NULL,
323 };
324 
325 int
326 _init(void)
327 {
328 	int ret;
329 
330 	mutex_init(&acpi_drv_mutex, NULL, MUTEX_DRIVER, NULL);
331 #ifdef DEBUG
332 	mutex_init(&acpi_drv_prt_mutex, NULL, MUTEX_DRIVER, NULL);
333 #endif
334 
335 	if ((ret = mod_install(&modlinkage)) != 0) {
336 		mutex_destroy(&acpi_drv_mutex);
337 #ifdef DEBUG
338 		mutex_destroy(&acpi_drv_prt_mutex);
339 #endif
340 	}
341 	return (ret);
342 }
343 
344 int
345 _fini(void)
346 {
347 	int ret;
348 
349 	if ((ret = mod_remove(&modlinkage)) == 0) {
350 #ifdef DEBUG
351 		mutex_destroy(&acpi_drv_prt_mutex);
352 #endif
353 		mutex_destroy(&acpi_drv_mutex);
354 	}
355 
356 	return (ret);
357 }
358 
359 int
360 _info(struct modinfo *mp)
361 {
362 	return (mod_info(&modlinkage, mp));
363 }
364 
365 static int
366 acpi_drv_attach(dev_info_t *devi, ddi_attach_cmd_t cmd)
367 {
368 	char name[20];
369 	int i;
370 	struct acpi_drv_cbat_state *bp;
371 
372 	switch (cmd) {
373 	case DDI_ATTACH:
374 		/* Limit to one instance of driver */
375 		if (acpi_drv_dip) {
376 			return (DDI_FAILURE);
377 		}
378 		break;
379 	case DDI_RESUME:
380 	case DDI_PM_RESUME:
381 		return (DDI_SUCCESS);
382 	default:
383 		return (DDI_FAILURE);
384 	}
385 
386 	acpi_drv_dip = devi;
387 
388 	/* Init ACPI related stuff */
389 	if (acpi_drv_acpi_init() != ACPI_DRV_OK) {
390 		goto error;
391 	}
392 
393 	/* Init kstat related stuff */
394 	if (acpi_drv_kstat_init() != ACPI_DRV_OK) {
395 		goto error;
396 	}
397 
398 	/* Create minor node for hotkey device. */
399 	if (ddi_create_minor_node(devi, "hotkey", S_IFCHR, MINOR_HOTKEY(0),
400 	    DDI_PSEUDO, 0) == DDI_FAILURE) {
401 		ACPI_DRV_DBG(CE_WARN, NULL, "hotkey: "
402 		    "minor node create failed");
403 		goto error;
404 	}
405 	/* Create minor node for lid. */
406 	if (ddi_create_minor_node(devi, "lid", S_IFCHR, MINOR_LID(0),
407 	    DDI_PSEUDO, 0) == DDI_FAILURE) {
408 		ACPI_DRV_DBG(CE_WARN, NULL, "lid: minor node create failed");
409 		goto error;
410 	}
411 	/* Create minor node for each battery and ac */
412 	for (bp = &acpi_drv_cbat[0]; bp < &acpi_drv_cbat[ACPI_DRV_MAX_BAT_NUM];
413 	    bp++) {
414 		if (bp->dev.valid) {
415 			(void) snprintf(name, sizeof (name), "battery%d",
416 			    bp->dev.index);
417 			if (ddi_create_minor_node(devi, name, S_IFCHR,
418 			    MINOR_BATT(bp->dev.index), DDI_PSEUDO, 0) ==
419 			    DDI_FAILURE) {
420 				ACPI_DRV_DBG(CE_WARN, NULL,
421 				    "%s: minor node create failed", name);
422 				goto error;
423 			}
424 		}
425 	}
426 	for (i = 0; i < nac; i++) {
427 		(void) snprintf(name, sizeof (name), "ac%d", i);
428 		if (ddi_create_minor_node(devi, name, S_IFCHR,
429 		    MINOR_AC(i), DDI_PSEUDO, 0) == DDI_FAILURE) {
430 			ACPI_DRV_DBG(CE_WARN, NULL,
431 			    "%s: minor node create failed", name);
432 			goto error;
433 		}
434 	}
435 
436 	return (DDI_SUCCESS);
437 
438 error:
439 	ddi_remove_minor_node(devi, NULL);
440 	acpi_drv_kstat_fini();
441 	acpi_drv_acpi_fini();
442 	acpi_drv_dip = NULL;
443 	return (DDI_FAILURE);
444 }
445 
446 static int
447 acpi_drv_detach(dev_info_t *devi, ddi_detach_cmd_t cmd)
448 {
449 	if (cmd != DDI_DETACH) {
450 		return (DDI_FAILURE);
451 	}
452 
453 	mutex_enter(&acpi_drv_mutex);
454 	ddi_remove_minor_node(devi, NULL);
455 
456 	acpi_drv_kstat_fini();
457 	acpi_drv_acpi_fini();
458 	mutex_exit(&acpi_drv_mutex);
459 	return (DDI_SUCCESS);
460 }
461 
462 /* ARGSUSED */
463 static int
464 acpi_drv_getinfo(dev_info_t *dip, ddi_info_cmd_t cmd, void *arg, void **resultp)
465 {
466 	switch (cmd) {
467 	case DDI_INFO_DEVT2DEVINFO:
468 		*resultp = acpi_drv_dip;
469 		return (DDI_SUCCESS);
470 	case DDI_INFO_DEVT2INSTANCE:
471 		*resultp = (void*) 0;
472 		return (DDI_SUCCESS);
473 	default:
474 		return (DDI_FAILURE);
475 	}
476 }
477 
478 /*ARGSUSED*/
479 static int
480 acpi_drv_open(dev_t *devp, int flag, int otyp, cred_t *crp)
481 {
482 	if (acpi_drv_dip == NULL) {
483 		return (ENXIO);
484 	}
485 
486 	return (0);
487 }
488 
489 /*ARGSUSED*/
490 static int
491 acpi_drv_close(dev_t dev, int flag, int otyp, cred_t *crp)
492 {
493 	return (0);
494 }
495 
496 /*ARGSUSED*/
497 static int
498 acpi_drv_ioctl(dev_t dev, int cmd, intptr_t arg, int mode, cred_t *cr,
499     int *rval)
500 {
501 	int minor;
502 	int type, index;
503 	int res = 0;
504 
505 	minor = getminor(dev);
506 	type = MINOR2TYPE(minor);
507 	index = MINOR2IDX(minor);
508 
509 	mutex_enter(&acpi_drv_mutex);
510 
511 	switch (type) {
512 	case ACPI_DRV_TYPE_CBAT:
513 		res = acpi_drv_cbat_ioctl(index, cmd, arg, mode, cr, rval);
514 		break;
515 	case ACPI_DRV_TYPE_AC:
516 		res = acpi_drv_ac_ioctl(index, cmd, arg, mode, cr, rval);
517 		break;
518 	case ACPI_DRV_TYPE_LID:
519 		res = acpi_drv_lid_ioctl(index, cmd, arg, mode, cr, rval);
520 		break;
521 	case ACPI_DRV_TYPE_HOTKEY:
522 		res = acpi_drv_hotkey_ioctl(cmd, arg, mode, cr, rval);
523 		break;
524 	default:
525 		res = EINVAL;
526 		break;
527 	}
528 
529 	mutex_exit(&acpi_drv_mutex);
530 	return (res);
531 }
532 
533 /*ARGSUSED*/
534 static int
535 acpi_drv_cbat_ioctl(int index, int cmd, intptr_t arg, int mode, cred_t *cr,
536     int *rval)
537 {
538 	int res = 0;
539 	acpi_drv_warn_t bwarn;
540 	struct acpi_drv_cbat_state *bp;
541 
542 	ASSERT(mutex_owned(&acpi_drv_mutex));
543 
544 	bp = acpi_drv_idx2cbat(index);
545 	if (!bp || bp->dev.valid != 1) {
546 		return (ENXIO);
547 	}
548 
549 	switch (cmd) {
550 	/*
551 	 * Return _BIF(Battery Information) of battery[index],
552 	 * if battery plugged.
553 	 */
554 	case ACPI_DRV_IOC_INFO:
555 		if (bp->dev.present == 0) {
556 			res = ENXIO;
557 			break;
558 		}
559 
560 		res = acpi_drv_update_bif(bp);
561 		if (res != ACPI_DRV_OK) {
562 			break;
563 		}
564 		if (copyout(&bp->bif_cache, (void *)arg,
565 		    sizeof (bp->bif_cache))) {
566 			res = EFAULT;
567 		}
568 		break;
569 
570 	/*
571 	 * Return _BST(Battery Status) of battery[index],
572 	 * if battery plugged.
573 	 */
574 	case ACPI_DRV_IOC_STATUS:
575 		if (bp->dev.present == 0) {
576 			res = ENXIO;
577 			break;
578 		}
579 
580 		res = acpi_drv_update_bst(bp);
581 		if (res != ACPI_DRV_OK) {
582 			break;
583 		}
584 		if (copyout(&bp->bst_cache, (void *)arg,
585 		    sizeof (bp->bst_cache))) {
586 			res = EFAULT;
587 		}
588 		break;
589 
590 	/* Return the state of the battery bays in the system */
591 	case ACPI_DRV_IOC_BAY:
592 		{
593 			batt_bay_t bay;
594 
595 			bay.bay_number = nbat;
596 			bay.battery_map = 0;
597 			for (bp = &acpi_drv_cbat[0];
598 			    bp < &acpi_drv_cbat[ACPI_DRV_MAX_BAT_NUM]; bp++) {
599 				if (bp->dev.valid) {
600 					if (bp->dev.present) {
601 						bay.battery_map |=
602 						    (1 << bp->dev.index);
603 					}
604 				}
605 			}
606 			if (copyout(&bay, (void *)arg, sizeof (bay))) {
607 				res = EFAULT;
608 				break;
609 			}
610 		}
611 		break;
612 
613 	/*
614 	 * Return the current power source device if available:
615 	 * 0 -- battery supplying power
616 	 * 1 -- AC supplying power
617 	 */
618 	case ACPI_DRV_IOC_POWER_STATUS:
619 		{
620 			int val;
621 
622 			/* State not available */
623 			if (acpi_drv_psr_type == ACPI_DRV_TYPE_UNKNOWN) {
624 				res = ENXIO;
625 				break;
626 			}
627 			val = (acpi_drv_psr_type == ACPI_DRV_TYPE_AC) ? 1 : 0;
628 			if (copyout(&val, (void *)arg, sizeof (val))) {
629 				res = EFAULT;
630 				break;
631 			}
632 		}
633 		break;
634 
635 	/* Get charge-warn and charge-low levels for the whole system */
636 	case ACPI_DRV_IOC_GET_WARNING:
637 		bwarn.bw_enabled = acpi_drv_warn_enabled;
638 		bwarn.bw_charge_warn = acpi_drv_syn_warn_per;
639 		bwarn.bw_charge_low = acpi_drv_syn_low_per;
640 		if (copyout(&bwarn, (void *)arg, sizeof (&bwarn))) {
641 			res = EFAULT;
642 		}
643 		break;
644 
645 	/* Set charge-warn and charge-low levels for the whole system */
646 	case ACPI_DRV_IOC_SET_WARNING:
647 		if (drv_priv(cr)) {
648 			res = EPERM;
649 			break;
650 		}
651 		if (copyin((void *)arg, &bwarn, sizeof (bwarn))) {
652 			res = EFAULT;
653 			break;
654 		}
655 		res = acpi_drv_set_warn(&bwarn);
656 		break;
657 
658 	default:
659 		res = EINVAL;
660 		break;
661 	}
662 
663 	return (res);
664 }
665 
666 /*ARGSUSED*/
667 static int
668 acpi_drv_ac_ioctl(int index, int cmd, intptr_t arg, int mode, cred_t *cr,
669     int *rval)
670 {
671 	int res = 0;
672 	int ac_state;
673 	struct acpi_drv_ac_state *acp;
674 
675 	ASSERT(mutex_owned(&acpi_drv_mutex));
676 
677 	acp = acpi_drv_idx2ac(index);
678 	if (!acp || acp->dev.valid != 1) {
679 		return (ENXIO);
680 	}
681 
682 	switch (cmd) {
683 	/* Return the number of AC adapters in the system */
684 	case ACPI_DRV_IOC_AC_COUNT:
685 		if (copyout(&nac, (void *)arg, sizeof (nac))) {
686 			res = EFAULT;
687 		}
688 		break;
689 
690 	/*
691 	 * Return the state of AC[index] if available:
692 	 * 0 -- Off-line
693 	 * 1 -- On-line
694 	 */
695 	case ACPI_DRV_IOC_POWER_STATUS:
696 		if (!acp || acp->dev.valid != 1) {
697 			res = ENXIO;
698 			break;
699 		}
700 		/* State not available */
701 		if ((ac_state = acpi_drv_ac_present(acp)) == -1) {
702 			res = ENXIO;
703 			break;
704 		}
705 		if (copyout(&ac_state, (void *)arg, sizeof (ac_state))) {
706 			res = EFAULT;
707 		}
708 		break;
709 
710 	default:
711 		res = EINVAL;
712 		break;
713 	}
714 
715 	return (res);
716 }
717 
718 /*ARGSUSED*/
719 static int
720 acpi_drv_lid_ioctl(int index, int cmd, intptr_t arg, int mode, cred_t *cr,
721     int *rval)
722 {
723 	int res = 0;
724 
725 	/*
726 	 * lid.state 0 means lid is closed.
727 	 * lid.state non-zero means lid is open.
728 	 */
729 	switch (cmd) {
730 	case ACPI_DRV_IOC_LID_STATUS:
731 		if (lid.state_ok == ACPI_DRV_NTF_UNKNOWN) {
732 			/* State not available */
733 			res = acpi_drv_update_lid(&lid.dev);
734 			if (res != ACPI_DRV_OK) {
735 				res = ENXIO;
736 				break;
737 			}
738 		}
739 		if (copyout(&lid.state, (void *)arg, sizeof (lid.state))) {
740 			res = EFAULT;
741 		}
742 		break;
743 	case ACPI_DRV_IOC_LID_UPDATE:
744 		res = acpi_drv_update_lid(&lid.dev);
745 		if (res != ACPI_DRV_OK) {
746 			res = ENXIO;
747 			break;
748 		}
749 		if (copyout(&lid.state, (void *)arg, sizeof (lid.state))) {
750 			res = EFAULT;
751 		}
752 		break;
753 
754 	default:
755 		res = EINVAL;
756 		break;
757 	}
758 	return (res);
759 }
760 
761 /*ARGSUSED*/
762 static int
763 acpi_drv_chpoll(dev_t dev, short events, int anyyet,  short *reventsp,
764 	struct pollhead **phpp)
765 {
766 	if (!anyyet) {
767 		*phpp = &acpi_drv_pollhead;
768 	}
769 	*reventsp = 0;
770 	return (0);
771 }
772 
773 #ifdef DEBUG
774 static void
775 acpi_drv_printf(struct acpi_drv_dev *devp, uint_t lev,
776     const char *fmt, ...)
777 {
778 	va_list args;
779 
780 	mutex_enter(&acpi_drv_prt_mutex);
781 
782 	va_start(args, fmt);
783 	(void) vsprintf(acpi_drv_prt_buf, fmt, args);
784 	va_end(args);
785 
786 	if (devp) {
787 		cmn_err(lev, "%s.%s: %s", devp->hid, devp->uid,
788 		    acpi_drv_prt_buf);
789 	} else {
790 		cmn_err(lev, "%s", acpi_drv_prt_buf);
791 	}
792 	mutex_exit(&acpi_drv_prt_mutex);
793 }
794 
795 static void
796 acpi_drv_prt_notify(ACPI_HANDLE hdl, UINT32 val)
797 {
798 	ACPI_BUFFER buf;
799 	char str[1024];
800 
801 	buf.Length = sizeof (str);
802 	buf.Pointer = str;
803 	(void) AcpiGetName(hdl, ACPI_FULL_PATHNAME, &buf);
804 	cmn_err(CE_NOTE, "AcpiNotify(%s, 0x%02x)", str, val);
805 }
806 #endif /* DEBUG */
807 
808 void
809 acpi_drv_gen_sysevent(struct acpi_drv_dev *devp, char *ev, uint32_t val)
810 {
811 	nvlist_t *attr_list = NULL;
812 	int err;
813 	char pathname[MAXPATHLEN];
814 
815 	/* Allocate and build sysevent attribute list */
816 	err = nvlist_alloc(&attr_list, NV_UNIQUE_NAME_TYPE, DDI_NOSLEEP);
817 	if (err != 0) {
818 		ACPI_DRV_DBG(CE_WARN, NULL,
819 		    "cannot allocate memory for sysevent attributes\n");
820 		return;
821 	}
822 
823 	/* Add attributes */
824 	err = nvlist_add_string(attr_list, PWRCTL_DEV_HID, devp->hid);
825 	if (err != 0) {
826 		ACPI_DRV_DBG(CE_WARN, NULL,
827 		    "Failed to add attr [%s] for %s/%s event",
828 		    PWRCTL_DEV_HID, EC_PWRCTL, ev);
829 		nvlist_free(attr_list);
830 		return;
831 	}
832 
833 	err = nvlist_add_string(attr_list, PWRCTL_DEV_UID, devp->uid);
834 	if (err != 0) {
835 		ACPI_DRV_DBG(CE_WARN, NULL,
836 		    "Failed to add attr [%s] for %s/%s event",
837 		    PWRCTL_DEV_UID, EC_PWRCTL, ev);
838 		nvlist_free(attr_list);
839 		return;
840 	}
841 
842 	err = nvlist_add_uint32(attr_list, PWRCTL_DEV_INDEX, devp->index);
843 	if (err != 0) {
844 		ACPI_DRV_DBG(CE_WARN, NULL,
845 		    "Failed to add attr [%s] for %s/%s event",
846 		    PWRCTL_DEV_INDEX, EC_PWRCTL, ev);
847 		nvlist_free(attr_list);
848 		return;
849 	}
850 
851 	(void) ddi_pathname(acpi_drv_dip, pathname);
852 	err = nvlist_add_string(attr_list, PWRCTL_DEV_PHYS_PATH, pathname);
853 	if (err != 0) {
854 		ACPI_DRV_DBG(CE_WARN, NULL,
855 		    "Failed to add attr [%s] for %s/%s event",
856 		    PWRCTL_DEV_PHYS_PATH, EC_PWRCTL, ev);
857 		nvlist_free(attr_list);
858 		return;
859 	}
860 
861 	if (strcmp(ev, ESC_PWRCTL_WARN) && strcmp(ev, ESC_PWRCTL_LOW)) {
862 		goto finish;
863 	}
864 
865 	err = nvlist_add_uint32(attr_list, PWRCTL_CHARGE_LEVEL, val);
866 	if (err != 0) {
867 		ACPI_DRV_DBG(CE_WARN, NULL,
868 		    "Failed to add attr [%s] for %s/%s event",
869 		    PWRCTL_CHARGE_LEVEL, EC_PWRCTL, ev);
870 		nvlist_free(attr_list);
871 		return;
872 	}
873 
874 finish:
875 	ACPI_DRV_DBG(CE_NOTE, NULL, "SysEv(%s, %s.%s, %d)",
876 	    ev, devp->hid, devp->uid, val);
877 	/* Generate/log sysevent */
878 	err = ddi_log_sysevent(acpi_drv_dip, DDI_VENDOR_SUNW, EC_PWRCTL,
879 	    ev, attr_list, NULL, DDI_NOSLEEP);
880 #ifdef DEBUG
881 	if (err != DDI_SUCCESS) {
882 		ACPI_DRV_DBG(CE_WARN, NULL,
883 		    "cannot log sysevent, err code %x\n", err);
884 	}
885 #endif
886 
887 	nvlist_free(attr_list);
888 }
889 
890 static int
891 acpi_drv_obj_copy(ACPI_OBJECT *op, char *bp, struct obj_desc *dp)
892 {
893 	ACPI_OBJECT *ep;
894 	char *fp;
895 
896 	ep = &op->Package.Elements[0];
897 	for (; dp->offset != -1; dp++) {
898 		fp = bp + dp->offset;
899 		if (dp->type == ACPI_TYPE_INTEGER &&
900 		    ep->Type == dp->type) {
901 #ifdef DEBUG
902 			if (dp->size <= 4) {
903 				ACPI_DRV_DBG(CE_NOTE, NULL, "\t%s: %u",
904 				    dp->name,
905 				    (uint32_t)ep->Integer.Value);
906 			} else {
907 #ifdef _LP64
908 				ACPI_DRV_DBG(CE_NOTE, NULL, "\t%s: %lu",
909 				    dp->name, (uint64_t)ep->Integer.Value);
910 			}
911 #else
912 				ACPI_DRV_DBG(CE_NOTE, NULL, "\t%s: %llu",
913 				    dp->name, (uint64_t)ep->Integer.Value);
914 			}
915 #endif /* _LP64 */
916 #endif /* DEBUG */
917 			*(uint32_t *)fp = ep->Integer.Value;
918 		} else if (dp->type == ACPI_TYPE_STRING &&
919 		    ep->Type == dp->type) {
920 			ACPI_DRV_DBG(CE_NOTE, NULL, "\t%s: \"%s\"",
921 			    dp->name, ep->String.Pointer);
922 			(void) strlcpy(fp, ep->String.Pointer, dp->size);
923 		} else if (dp->type == ACPI_TYPE_STRING &&
924 		    ep->Type == ACPI_TYPE_BUFFER) {
925 #ifdef DEBUG
926 			int len;
927 			char buf[MAXNAMELEN + 1];
928 
929 			len = (MAXNAMELEN < ep->Buffer.Length) ?
930 			    MAXNAMELEN : ep->Buffer.Length;
931 			bcopy(ep->Buffer.Pointer, buf, len);
932 			buf[len] = 0;
933 			ACPI_DRV_DBG(CE_NOTE, NULL, "\t%s: [%d] \"%s\"",
934 			    dp->name, len, buf);
935 #endif
936 
937 			ASSERT(MAXNAMELEN >= ep->Buffer.Length);
938 			bcopy(ep->Buffer.Pointer, fp, ep->Buffer.Length);
939 		} else {
940 			ACPI_DRV_DBG(CE_WARN, NULL,
941 			    "Bad field at offset %d: type %d",
942 			    dp->offset, ep->Type);
943 			if (dp->type != ACPI_TYPE_STRING) {
944 				return (ACPI_DRV_ERR);
945 			}
946 		}
947 		ep++;
948 	}
949 
950 	return (ACPI_DRV_OK);
951 }
952 
953 /*
954  * Returns the current power source devices. Used for the AC adapter and is
955  * located under the AC adapter object in name space. Used to determine if
956  * system is running off the AC adapter. This will report that the system is
957  * not running on the AC adapter if any of the batteries in the system is
958  * being forced to discharge through _BMC.
959  *
960  * Return value:
961  *	 0 -- Off-line, ie. battery supplying system power
962  *	 1 -- On-line, ie. AC supplying system power
963  *	-1 -- Unknown, some error ocurred.
964  * Note: It will also update the driver ac state.
965  */
966 static int
967 acpi_drv_get_psr(struct acpi_drv_ac_state *acp)
968 {
969 	struct acpi_drv_dev *devp = &acp->dev;
970 	int ac;
971 
972 	if (!devp->valid) {
973 		ACPI_DRV_DBG(CE_WARN, NULL, "device not valid");
974 		return (-1);
975 	}
976 
977 	if (acpica_eval_int(devp->hdl, "_PSR", &ac) == AE_OK) {
978 		ACPI_DRV_DBG(CE_NOTE, devp, "_PSR = %d", ac);
979 		devp->present = ac;
980 	} else {
981 		ACPI_DRV_DBG(CE_WARN, NULL, "AcpiEval _PSR failed");
982 		devp->present = -1;
983 	}
984 
985 	return (ac);
986 }
987 
988 /*
989  * For most systems, the _STA for this device will always
990  * return a value with bits 0-3 set and will toggle bit 4
991  * to indicate the actual presence of a battery.
992  *
993  * Return value:
994  *	 0 -- battery not present
995  *	 1 -- battery present
996  *	-1 -- Unknown, some error ocurred.
997  * Note: It will also update the driver cbat state.
998  */
999 static int
1000 acpi_drv_get_sta(struct acpi_drv_cbat_state *bp)
1001 {
1002 	struct acpi_drv_dev *devp = &bp->dev;
1003 	int val;
1004 
1005 	if (!devp->valid) {
1006 		ACPI_DRV_DBG(CE_WARN, NULL, "device not valid");
1007 		return (-1);
1008 	}
1009 
1010 	if (acpica_eval_int(devp->hdl, "_STA", &val) == AE_OK) {
1011 		ACPI_DRV_DBG(CE_NOTE, devp, "_STA = 0x%x", val);
1012 		devp->present = ((val & STA_FLAG_BATT_PRESENT) != 0);
1013 	} else {
1014 		ACPI_DRV_DBG(CE_WARN, NULL, "AcpiEval _STA failed");
1015 		devp->present = -1;
1016 	}
1017 
1018 	return (val);
1019 }
1020 
1021 static int
1022 acpi_drv_update_bif(struct acpi_drv_cbat_state *bp)
1023 {
1024 	ACPI_BUFFER buf;
1025 	ACPI_OBJECT *objp;
1026 
1027 	/* BIF is only available when battery plugged */
1028 	ASSERT(bp->dev.present != 0);
1029 
1030 	/* Update internal BIF cache */
1031 	bp->bat_bifok = ACPI_DRV_NTF_UNKNOWN;
1032 
1033 	buf.Length = ACPI_ALLOCATE_BUFFER;
1034 	if (ACPI_FAILURE(AcpiEvaluateObjectTyped(bp->dev.hdl, "_BIF",
1035 	    NULL, &buf, ACPI_TYPE_PACKAGE))) {
1036 		ACPI_DRV_DBG(CE_WARN, NULL, "AcpiEval _BIF failed");
1037 		return (ACPI_DRV_ERR);
1038 	}
1039 
1040 	objp = buf.Pointer;
1041 	ACPI_DRV_DBG(CE_NOTE, &bp->dev, "get _BIF");
1042 	if (acpi_drv_obj_copy(objp, (char *)&bp->bif_cache, bif_desc) ==
1043 	    ACPI_DRV_ERR) {
1044 		AcpiOsFree(objp);
1045 		return (ACPI_DRV_ERR);
1046 	}
1047 	AcpiOsFree(objp);
1048 	bp->bat_bifok = ACPI_DRV_NTF_OK;
1049 	return (ACPI_DRV_OK);
1050 }
1051 
1052 static int
1053 acpi_drv_update_bst(struct acpi_drv_cbat_state *bp)
1054 {
1055 	ACPI_BUFFER buf;
1056 	ACPI_OBJECT *objp;
1057 
1058 	/* BST is only available when battery plugged */
1059 	ASSERT(bp->dev.present != 0);
1060 
1061 	/* Update internal BST cache */
1062 	bp->bat_bstok = ACPI_DRV_NTF_UNKNOWN;
1063 
1064 	buf.Length = ACPI_ALLOCATE_BUFFER;
1065 	if (ACPI_FAILURE(AcpiEvaluateObjectTyped(bp->dev.hdl, "_BST",
1066 	    NULL, &buf, ACPI_TYPE_PACKAGE))) {
1067 		ACPI_DRV_DBG(CE_WARN, NULL, "AcpiEval _BST failed");
1068 		return (ACPI_DRV_ERR);
1069 	}
1070 
1071 	objp = buf.Pointer;
1072 	ACPI_DRV_DBG(CE_NOTE, &bp->dev, "get _BST");
1073 	if (acpi_drv_obj_copy(objp, (char *)&bp->bst_cache, bst_desc) ==
1074 	    ACPI_DRV_ERR) {
1075 		AcpiOsFree(objp);
1076 		return (ACPI_DRV_ERR);
1077 	}
1078 	AcpiOsFree(objp);
1079 
1080 	if (bp->bst_cache.bst_rate == 0) {
1081 		bp->bst_cache.bst_state &= ~(ACPI_DRV_BST_CHARGING |
1082 		    ACPI_DRV_BST_DISCHARGING);
1083 	}
1084 	bp->bat_bstok = ACPI_DRV_NTF_OK;
1085 	return (ACPI_DRV_OK);
1086 }
1087 
1088 /*
1089  * Return value:
1090  *	 1 -- device On-line
1091  *	 0 -- device Off-line
1092  *	-1 -- Unknown, some error ocurred.
1093  */
1094 static int
1095 acpi_drv_dev_present(struct acpi_drv_dev *devp)
1096 {
1097 	if (!devp->valid) {
1098 		ACPI_DRV_DBG(CE_WARN, NULL, "device not valid");
1099 		return (-1);
1100 	}
1101 
1102 	ASSERT(devp->type != ACPI_DRV_TYPE_UNKNOWN);
1103 
1104 	/* Update the device state */
1105 	if (devp->present == -1) {
1106 		if (devp->type == ACPI_DRV_TYPE_AC) {
1107 			(void) acpi_drv_get_psr((struct acpi_drv_ac_state *)
1108 			    devp);
1109 		} else if (devp->type == ACPI_DRV_TYPE_CBAT) {
1110 			(void) acpi_drv_get_sta((struct acpi_drv_cbat_state *)
1111 			    devp);
1112 		}
1113 	}
1114 
1115 	return (devp->present);
1116 }
1117 
1118 /*
1119  * Check if the device p existance state has changed.
1120  * Return value:
1121  *	 1 -- changed
1122  *	 0 -- no change
1123  *	-1 -- unknown
1124  */
1125 static int
1126 acpi_drv_update_present(struct acpi_drv_dev *p)
1127 {
1128 	int old_present = p->present;
1129 	int new_present;
1130 
1131 	ASSERT(p && p->valid);
1132 
1133 	p->present = -1;
1134 	new_present = acpi_drv_dev_present(p);
1135 	if (new_present == -1) {
1136 		return (-1);
1137 	}
1138 	if (new_present != old_present) {
1139 		return (1);
1140 	}
1141 	return (0);
1142 }
1143 
1144 static void
1145 acpi_drv_set_psr(struct acpi_drv_dev *p)
1146 {
1147 	acpi_drv_psr_devp = p;
1148 	if (p != NULL) {
1149 		ACPI_DRV_DBG(CE_NOTE, p, "psr = .");
1150 		acpi_drv_psr_type = p->type;
1151 	} else {
1152 		ACPI_DRV_DBG(CE_NOTE, p, "psr = ?");
1153 		acpi_drv_psr_type = ACPI_DRV_TYPE_UNKNOWN;
1154 	}
1155 }
1156 
1157 /*
1158  * OSPM can determine independent warning and low battery
1159  * capacity values based on the OEM-designed levels, but
1160  * cannot set these values lower than the OEM-designed values.
1161  */
1162 static int
1163 acpi_drv_set_warn(acpi_drv_warn_t *bwp)
1164 {
1165 	uint32_t warn, low;
1166 
1167 	warn = acpi_drv_syn_last_cap * bwp->bw_charge_warn / 100;
1168 	low = acpi_drv_syn_last_cap * bwp->bw_charge_low / 100;
1169 
1170 	/* Update internal state */
1171 	if (bwp->bw_enabled) {
1172 		if (low >= warn || warn < acpi_drv_syn_oem_warn_cap ||
1173 		    low < acpi_drv_syn_oem_low_cap) {
1174 			ACPI_DRV_DBG(CE_WARN, NULL, "charge level error");
1175 			return (EINVAL);
1176 		}
1177 
1178 		ACPI_DRV_DBG(CE_NOTE, NULL, "set warn: warn=%d low=%d", warn,
1179 		    low);
1180 
1181 		acpi_drv_syn_warn_per = bwp->bw_charge_warn;
1182 		acpi_drv_syn_low_per = bwp->bw_charge_low;
1183 		acpi_drv_syn_warn_cap = warn;
1184 		acpi_drv_syn_low_cap = low;
1185 		acpi_drv_warn_enabled = 1;
1186 	} else {
1187 		acpi_drv_warn_enabled = 0;
1188 	}
1189 
1190 	return (0);
1191 }
1192 
1193 /*
1194  * Update information for the synthesis battery
1195  *
1196  * Note: Sometimes the value to be returned from _BST or _BIF will be
1197  * temporarily unknown. In this case, the method may return the value
1198  * 0xFFFFFFFF as a placeholder. When the value becomes known, the
1199  * appropriate notification (0x80 for _BST or 0x81 for BIF) should be
1200  * issued, in like manner to any other change in the data returned by
1201  * these methods. This will cause OSPM to re-evaluate the method obtaining
1202  * the correct data value.
1203  */
1204 static void
1205 acpi_drv_update_cap(int bif_changed)
1206 {
1207 	struct acpi_drv_cbat_state *bp;
1208 
1209 	if (bif_changed != 0) {
1210 		acpi_drv_syn_oem_warn_cap = 0xffffffff;
1211 		acpi_drv_syn_oem_low_cap = 0xffffffff;
1212 		acpi_drv_syn_last_cap = 0xffffffff;
1213 	}
1214 	acpi_drv_syn_last_level = acpi_drv_syn_rem_cap;
1215 	acpi_drv_syn_rem_cap = 0xffffffff; /* initially unknown */
1216 
1217 	for (bp = &acpi_drv_cbat[0]; bp < &acpi_drv_cbat[ACPI_DRV_MAX_BAT_NUM];
1218 	    bp++) {
1219 		if (bp->dev.valid) {
1220 			/* Escape the empty bays */
1221 			if (acpi_drv_cbat_present(bp) <= 0) {
1222 				continue;
1223 			}
1224 
1225 			if (bif_changed != 0 &&
1226 			    bp->bat_bifok == ACPI_DRV_NTF_OK) {
1227 				acpi_bif_t *bif;
1228 
1229 				bif = &bp->bif_cache;
1230 
1231 				if (acpi_drv_syn_last_cap == 0xffffffff) {
1232 					acpi_drv_syn_last_cap = 0;
1233 				}
1234 				acpi_drv_syn_last_cap += bif->bif_last_cap;
1235 
1236 				if (bif->bif_warn_cap == 0xffffffff ||
1237 				    bif->bif_low_cap == 0xffffffff) {
1238 					ACPI_DRV_DBG(CE_WARN, &bp->dev,
1239 					    "BIF value "
1240 					    "invalid, warn_cap=0x%x "
1241 					    "low_cap=0x%x", bif->bif_warn_cap,
1242 					    bif->bif_low_cap);
1243 					continue;
1244 				}
1245 				if (acpi_drv_syn_oem_warn_cap == 0xffffffff) {
1246 					acpi_drv_syn_oem_warn_cap = 0;
1247 				}
1248 				if (acpi_drv_syn_oem_low_cap == 0xffffffff) {
1249 					acpi_drv_syn_oem_low_cap = 0;
1250 				}
1251 
1252 				/*
1253 				 * Use the highest level as the synthesis
1254 				 * level.
1255 				 */
1256 				if (bif->bif_warn_cap >
1257 				    acpi_drv_syn_oem_warn_cap) {
1258 					acpi_drv_syn_oem_low_cap =
1259 					    bif->bif_low_cap;
1260 					acpi_drv_syn_oem_warn_cap =
1261 					    bif->bif_warn_cap;
1262 				}
1263 			}
1264 #ifdef DEBUG
1265 			else if (bif_changed) {
1266 				ACPI_DRV_DBG(CE_NOTE, &bp->dev,
1267 				    "BIF not ready");
1268 			}
1269 #endif
1270 
1271 			if (bp->bat_bstok == ACPI_DRV_NTF_OK) {
1272 				acpi_bst_t *bst;
1273 
1274 				bst = &bp->bst_cache;
1275 
1276 				/*
1277 				 * Batteries that are rechargeable and are in
1278 				 * the discharging state are required to return
1279 				 * a valid Battery Present Rate value.
1280 				 * 0xFFFFFFFF - Unknown rate/capacity
1281 				 */
1282 				if (bst->bst_rem_cap == 0xffffffff) {
1283 					ACPI_DRV_DBG(CE_WARN, &bp->dev,
1284 					    "BST value invalid, "
1285 					    "rate=0x%x cap=0x%x",
1286 					    bst->bst_rate, bst->bst_rem_cap);
1287 					continue;
1288 				}
1289 
1290 				if (acpi_drv_syn_rem_cap == 0xffffffff) {
1291 					acpi_drv_syn_rem_cap = 0;
1292 				}
1293 				acpi_drv_syn_rem_cap += bst->bst_rem_cap;
1294 				/* Check for overflow */
1295 				ASSERT(acpi_drv_syn_rem_cap >=
1296 				    bst->bst_rem_cap);
1297 			}
1298 #ifdef DEBUG
1299 			else {
1300 				ACPI_DRV_DBG(CE_NOTE, &bp->dev,
1301 				    "BST not ready");
1302 			}
1303 #endif
1304 		}
1305 	}
1306 
1307 	ACPI_DRV_DBG(CE_NOTE, NULL, "syn_cap: %d syn_oem_warn: %d "
1308 	    "syn_oem_low: %d", acpi_drv_syn_rem_cap, acpi_drv_syn_oem_warn_cap,
1309 	    acpi_drv_syn_oem_low_cap);
1310 }
1311 
1312 static struct acpi_drv_cbat_state *
1313 acpi_drv_idx2cbat(int idx)
1314 {
1315 	if (idx >= ACPI_DRV_MAX_BAT_NUM) {
1316 		return (NULL);
1317 	}
1318 	return (&acpi_drv_cbat[idx]);
1319 }
1320 
1321 static struct acpi_drv_ac_state *
1322 acpi_drv_idx2ac(int idx)
1323 {
1324 	if (idx >= ACPI_DRV_MAX_AC_NUM) {
1325 		return (NULL);
1326 	}
1327 	return (&acpi_drv_ac[idx]);
1328 }
1329 
1330 /*ARGSUSED*/
1331 static void
1332 acpi_drv_cbat_notify(ACPI_HANDLE hdl, UINT32 val, void *ctx)
1333 {
1334 	struct acpi_drv_cbat_state *bp = ctx;
1335 	struct acpi_drv_dev *devp = &bp->dev;
1336 	int bif_changed;
1337 	uint32_t eval;
1338 	char *ev;
1339 	acpi_bst_t *bst;
1340 
1341 	mutex_enter(&acpi_drv_mutex);
1342 	ACPI_DRV_PRT_NOTIFY(hdl, val);
1343 
1344 	switch (val) {
1345 	/*
1346 	 * BST has changed
1347 	 * Whenever the Battery State value changes, the
1348 	 * system will generate an SCI to notify the OS.
1349 	 *
1350 	 * Note: trip point is not used to implement the
1351 	 * warning levels.
1352 	 */
1353 	case 0x80:
1354 		/*
1355 		 * We always get 0x80 and 0x81 at battery plug/unplug,
1356 		 * but 0x80 may come first. In case that situation, we have
1357 		 * to update battery present state here too to update bst
1358 		 * correctly.
1359 		 */
1360 		bif_changed = acpi_drv_update_present(devp);
1361 
1362 		if (devp->present == 0) {
1363 			if (acpi_drv_psr_devp == devp) {
1364 				acpi_drv_set_psr(NULL);
1365 			}
1366 			goto done;
1367 		}
1368 
1369 		if (acpi_drv_update_bst(bp) != ACPI_DRV_OK) {
1370 			break;
1371 		}
1372 		acpi_drv_update_cap(bif_changed);
1373 
1374 		bst = &bp->bst_cache;
1375 		eval = bst->bst_rem_cap;
1376 
1377 		if (bst->bst_state & BST_FLAG_DISCHARGING) {
1378 			acpi_drv_set_psr(devp);
1379 		}
1380 		/*
1381 		 * The Critical battery state indicates that all
1382 		 * available batteries are discharged and do not
1383 		 * appear to be able to supply power to run the
1384 		 * system any longer. When this occurs, the OS
1385 		 * should attempt to perform an emergency shutdown.
1386 		 * Right now we do not shutdown.  This would
1387 		 * need some discussion first since it could be
1388 		 * controversial.
1389 		 */
1390 #ifdef DEBUG
1391 		if (bst->bst_state & BST_FLAG_CRITICAL) {
1392 			ACPI_DRV_DBG(CE_WARN, devp, "BST_FLAG_CRITICAL set");
1393 
1394 			/*
1395 			 * BST_FLAG_CRITICAL may set even with AC,
1396 			 * plugged, when plug/unplug battery. Check
1397 			 * to avoid erroneous shutdown.
1398 			 */
1399 			if (acpi_drv_psr_devp == devp &&
1400 			    bst->bst_rem_cap != 0xffffffff) {
1401 				ACPI_DRV_DBG(CE_WARN, NULL,
1402 				    "Battery in critical state");
1403 			}
1404 		} else
1405 #endif
1406 		if (acpi_drv_warn_enabled &&
1407 		    (bst->bst_state & BST_FLAG_DISCHARGING)) {
1408 			/*
1409 			 * This value is an estimation of the amount of
1410 			 * energy or battery capacity required by the
1411 			 * system to transition to any supported sleeping
1412 			 * state. When the OS detects that the total
1413 			 * available battery capacity is less than this
1414 			 * value, it will transition the system to a user
1415 			 * defined system state (S1-S5).
1416 			 */
1417 			if (acpi_drv_syn_last_level > acpi_drv_syn_low_cap &&
1418 			    acpi_drv_syn_rem_cap <= acpi_drv_syn_low_cap) {
1419 				acpi_drv_gen_sysevent(devp, ESC_PWRCTL_LOW,
1420 				    eval);
1421 			/*
1422 			 * When the total available energy (mWh) or capacity
1423 			 * (mAh) in the batteries falls below this level,
1424 			 * the OS will notify the user through the UI.
1425 			 */
1426 			} else if (acpi_drv_syn_last_level >
1427 			    acpi_drv_syn_warn_cap &&
1428 			    acpi_drv_syn_rem_cap <= acpi_drv_syn_warn_cap) {
1429 				acpi_drv_gen_sysevent(devp, ESC_PWRCTL_WARN,
1430 				    eval);
1431 			}
1432 		}
1433 
1434 done:
1435 		acpi_drv_gen_sysevent(devp, ESC_PWRCTL_STATE_CHANGE, 0);
1436 		pollwakeup(&acpi_drv_pollhead, ACPI_DRV_EVENTS);
1437 		break;
1438 
1439 	/* BIF has changed */
1440 	case 0x81:
1441 		/*
1442 		 * Note: Do not eliminate multiple ADD/REMOVE here,
1443 		 * because they may corresponding to different batterys.
1444 		 */
1445 		(void) acpi_drv_update_present(devp);
1446 		if (devp->present == 1) {
1447 			if (acpi_drv_update_bif(bp) != ACPI_DRV_OK) {
1448 				break;
1449 			}
1450 		}
1451 
1452 		acpi_drv_update_cap(1);
1453 
1454 		eval = devp->present;
1455 		ev = eval ? ESC_PWRCTL_ADD : ESC_PWRCTL_REMOVE;
1456 		acpi_drv_gen_sysevent(devp, ev, 0);
1457 		pollwakeup(&acpi_drv_pollhead, ACPI_DRV_EVENTS);
1458 		break;
1459 
1460 	case 0x82:
1461 	default:
1462 		break;
1463 	}
1464 
1465 	mutex_exit(&acpi_drv_mutex);
1466 }
1467 
1468 static int
1469 acpi_drv_update_lid(struct acpi_drv_dev *p)
1470 {
1471 	struct acpi_drv_lid_state *lp = (struct acpi_drv_lid_state *)p;
1472 
1473 	if (acpica_eval_int(p->hdl, "_LID", &lp->state) == AE_OK) {
1474 		lp->state_ok = ACPI_DRV_NTF_OK;
1475 		return (ACPI_DRV_OK);
1476 	}
1477 	return (ACPI_DRV_ERR);
1478 }
1479 
1480 /*ARGSUSED*/
1481 static void
1482 acpi_drv_ac_notify(ACPI_HANDLE hdl, UINT32 val, void *ctx)
1483 {
1484 	struct acpi_drv_ac_state *acp = ctx;
1485 	struct acpi_drv_dev *devp = &acp->dev;
1486 	int old_present;
1487 	char *ev;
1488 	int eval;
1489 
1490 	ACPI_DRV_PRT_NOTIFY(hdl, val);
1491 	if (val != 0x80) {
1492 		return;
1493 	}
1494 
1495 	mutex_enter(&acpi_drv_mutex);
1496 	/*
1497 	 * Note: if unplug and then quickly plug back, two ADD
1498 	 * events will be generated.
1499 	 */
1500 	old_present = devp->present;
1501 	eval = acpi_drv_get_psr(acp);
1502 
1503 	/* Eliminate redundant events */
1504 	if (eval != -1 && eval != old_present) {
1505 		/* Keep tracking the current power source device */
1506 		if (eval == 1) {
1507 			ev = ESC_PWRCTL_ADD;
1508 			acpi_drv_set_psr(devp);
1509 		} else {
1510 			ev = ESC_PWRCTL_REMOVE;
1511 			/* If AC was supplying the power, it's not now */
1512 			if (acpi_drv_psr_devp == devp) {
1513 				acpi_drv_set_psr(NULL);
1514 			}
1515 		}
1516 
1517 		acpi_drv_gen_sysevent(devp, ev, 0);
1518 		pollwakeup(&acpi_drv_pollhead, ACPI_DRV_EVENTS);
1519 	}
1520 
1521 	mutex_exit(&acpi_drv_mutex);
1522 }
1523 
1524 static void
1525 acpi_drv_lid_notify(ACPI_HANDLE hdl, UINT32 val, void *ctx)
1526 {
1527 	struct acpi_drv_lid_state *p = ctx;
1528 
1529 	ACPI_DRV_PRT_NOTIFY(hdl, val);
1530 	if (val == 0x80) {
1531 		mutex_enter(&acpi_drv_mutex);
1532 		if (acpi_drv_update_lid(&p->dev) == ACPI_DRV_OK) {
1533 			acpi_drv_gen_sysevent(&p->dev, p->state ?
1534 			    ESC_PWRCTL_ADD : ESC_PWRCTL_REMOVE, 0);
1535 		}
1536 		mutex_exit(&acpi_drv_mutex);
1537 	}
1538 }
1539 
1540 static int
1541 acpi_drv_obj_init(struct acpi_drv_dev *p)
1542 {
1543 	ACPI_DEVICE_INFO *info;
1544 	ACPI_NOTIFY_HANDLER ntf_handler = NULL;
1545 	ACPI_STATUS ret;
1546 
1547 	ASSERT(p != NULL && p->hdl != NULL);
1548 
1549 	p->valid = 0;
1550 
1551 	/* Info size is variable depending on existance of _CID */
1552 	ret = AcpiGetObjectInfo(p->hdl, &info);
1553 	if (ACPI_FAILURE(ret)) {
1554 		ACPI_DRV_DBG(CE_WARN, NULL,
1555 		    "AcpiGetObjectInfo() fail: %d", (int32_t)ret);
1556 		return (ACPI_DRV_ERR);
1557 	}
1558 
1559 	if ((info->Valid & ACPI_VALID_HID) == 0) {
1560 		ACPI_DRV_DBG(CE_WARN, NULL,
1561 		    "AcpiGetObjectInfo(): _HID not available");
1562 		p->hid[0] = 0;
1563 	} else {
1564 		(void) strlcpy(p->hid, info->HardwareId.String, ID_LEN);
1565 	}
1566 
1567 	/*
1568 	 * This object is optional, but is required when the device
1569 	 * has no other way to report a persistent unique device ID.
1570 	 */
1571 	if ((info->Valid & ACPI_VALID_UID) == 0) {
1572 		ACPI_DRV_DBG(CE_WARN, NULL,
1573 		    "AcpiGetObjectInfo(): _UID not available");
1574 		/* Use 0 as the default _UID */
1575 		p->uid[0] = 0;
1576 	} else {
1577 		(void) strlcpy(p->uid, info->UniqueId.String, ID_LEN);
1578 	}
1579 
1580 	AcpiOsFree(info);
1581 	p->valid = 1;
1582 
1583 	if (strcmp(p->hid, ACPI_DEVNAME_CBAT) == 0) {
1584 		struct acpi_drv_cbat_state *bp =
1585 		    (struct acpi_drv_cbat_state *)p;
1586 
1587 		p->type = ACPI_DRV_TYPE_CBAT;
1588 		p->index = nbat - 1;
1589 
1590 		/* Update device present state */
1591 		(void) acpi_drv_update_present(p);
1592 		if (p->present) {
1593 			(void) acpi_drv_update_bif(bp);
1594 			(void) acpi_drv_update_bst(bp);
1595 
1596 			/* Init the current power source */
1597 			if (bp->bst_cache.bst_state & BST_FLAG_DISCHARGING) {
1598 				acpi_drv_set_psr(p);
1599 			}
1600 		}
1601 		ntf_handler = acpi_drv_cbat_notify;
1602 		ACPI_DRV_DBG(CE_NOTE, p, "battery %s",
1603 		    (p->present ? "present" : "absent"));
1604 	} else if (strcmp(p->hid, ACPI_DEVNAME_AC) == 0) {
1605 		p->type = ACPI_DRV_TYPE_AC;
1606 		p->index = nac - 1;
1607 
1608 		/* Update device present state */
1609 		(void) acpi_drv_update_present(p);
1610 		if (p->present) {
1611 			/* Init the current power source */
1612 			acpi_drv_set_psr(p);
1613 		}
1614 		ntf_handler = acpi_drv_ac_notify;
1615 		ACPI_DRV_DBG(CE_NOTE, p, "AC %s",
1616 		    (p->present ? "on-line" : "off-line"));
1617 	} else if (strcmp(p->hid, ACPI_DEVNAME_LID) == 0) {
1618 		p->type = ACPI_DRV_TYPE_LID;
1619 		p->index = 0;
1620 		lid.state_ok = ACPI_DRV_NTF_UNKNOWN;
1621 		(void) acpi_drv_update_lid(p);
1622 		ntf_handler = acpi_drv_lid_notify;
1623 		ACPI_DRV_DBG(CE_NOTE, p, "added");
1624 	} else {
1625 		ACPI_DRV_DBG(CE_NOTE, p, "unknown device");
1626 		p->valid = 0;
1627 	}
1628 
1629 	/* Register ACPI battery related events */
1630 	if (ntf_handler != NULL) {
1631 		if (ACPI_FAILURE(AcpiInstallNotifyHandler(p->hdl,
1632 		    ACPI_ALL_NOTIFY, ntf_handler, p))) {
1633 			ACPI_DRV_DBG(CE_NOTE, NULL,
1634 			    "Notify handler for %s.%s install failed",
1635 			    p->hid, p->uid);
1636 			return (ACPI_DRV_ERR);
1637 		}
1638 	}
1639 
1640 	return (ACPI_DRV_OK);
1641 }
1642 
1643 /*ARGSUSED*/
1644 static ACPI_STATUS
1645 acpi_drv_find_cb(ACPI_HANDLE ObjHandle, UINT32 NestingLevel, void *Context,
1646     void **ReturnValue)
1647 {
1648 	struct acpi_drv_dev *devp;
1649 	int *type = (int *)Context;
1650 
1651 	if (*type == ACPI_DRV_TYPE_CBAT) {
1652 		struct acpi_drv_cbat_state *bp;
1653 
1654 		if (nbat == ACPI_DRV_MAX_BAT_NUM) {
1655 			ACPI_DRV_DBG(CE_WARN, NULL,
1656 			    "Need to support more batteries: "
1657 			    "BATTERY_MAX = %d", ACPI_DRV_MAX_BAT_NUM);
1658 			return (AE_LIMIT);
1659 		}
1660 		bp = &acpi_drv_cbat[nbat++];
1661 		devp = (struct acpi_drv_dev *)bp;
1662 	} else if (*type == ACPI_DRV_TYPE_AC) {
1663 		struct acpi_drv_ac_state *ap;
1664 
1665 		if (nac == ACPI_DRV_MAX_AC_NUM) {
1666 			ACPI_DRV_DBG(CE_WARN, NULL, "Need to support more ACs: "
1667 			    "AC_MAX = %d", ACPI_DRV_MAX_AC_NUM);
1668 			return (AE_LIMIT);
1669 		}
1670 		ap = &acpi_drv_ac[nac++];
1671 		devp = (struct acpi_drv_dev *)ap;
1672 	} else if (*type == ACPI_DRV_TYPE_LID) {
1673 		struct acpi_drv_lid_state *lp;
1674 
1675 		nlid++;
1676 		lp = &lid;
1677 		devp = (struct acpi_drv_dev *)lp;
1678 	} else {
1679 		ACPI_DRV_DBG(CE_WARN, NULL, "acpi_drv_find_cb(): "
1680 		    "Unknown device");
1681 		return (AE_ERROR);
1682 	}
1683 
1684 	devp->hdl = ObjHandle;
1685 
1686 	/* Try to get as many working objs as possible */
1687 	(void) acpi_drv_obj_init(devp);
1688 	return (AE_OK);
1689 }
1690 
1691 static int
1692 acpi_drv_acpi_init()
1693 {
1694 	int *retp, type;
1695 	int status = ACPI_DRV_ERR;
1696 	hotkey_drv_t *htkp;
1697 
1698 	/* Check to see if ACPI CA services are available */
1699 	if (AcpiSubsystemStatus() != AE_OK) {
1700 		ACPI_DRV_DBG(CE_WARN, NULL, "ACPI CA not ready");
1701 		return (status);
1702 	}
1703 
1704 	/* Init Control Method Batterys */
1705 	type = ACPI_DRV_TYPE_CBAT;
1706 	if (ACPI_SUCCESS(AcpiGetDevices(ACPI_DEVNAME_CBAT, acpi_drv_find_cb,
1707 	    &type, (void *)&retp)) && nbat) {
1708 		status = ACPI_DRV_OK;
1709 	}
1710 
1711 	/* Init AC */
1712 	type = ACPI_DRV_TYPE_AC;
1713 	if (ACPI_SUCCESS(AcpiGetDevices(ACPI_DEVNAME_AC, acpi_drv_find_cb,
1714 	    &type, (void *)&retp)) && nac) {
1715 		status = ACPI_DRV_OK;
1716 	}
1717 
1718 	/* Init LID */
1719 	type = ACPI_DRV_TYPE_LID;
1720 	if (ACPI_SUCCESS(AcpiGetDevices(ACPI_DEVNAME_LID, acpi_drv_find_cb,
1721 	    &type, (void *)&retp)) && nlid) {
1722 		status = ACPI_DRV_OK;
1723 	}
1724 
1725 	/* Init Hotkey Device */
1726 	type = ACPI_DRV_TYPE_HOTKEY;
1727 	htkp = &acpi_hotkey;
1728 	bzero(htkp, sizeof (hotkey_drv_t));
1729 	htkp->dip = acpi_drv_dip;
1730 	htkp->hotkey_lock = &acpi_drv_mutex;
1731 	if (hotkey_init(htkp) == ACPI_DRV_OK) {
1732 		status = ACPI_DRV_OK;
1733 	}
1734 
1735 	acpi_drv_update_cap(1);
1736 
1737 	return (status);
1738 }
1739 
1740 static void
1741 acpi_drv_acpi_fini(void)
1742 {
1743 	int i;
1744 	struct acpi_drv_cbat_state *bp;
1745 
1746 	for (bp = &acpi_drv_cbat[0]; bp < &acpi_drv_cbat[ACPI_DRV_MAX_BAT_NUM];
1747 	    bp++) {
1748 		if (bp->dev.valid) {
1749 			(void) AcpiRemoveNotifyHandler(bp->dev.hdl,
1750 			    ACPI_DEVICE_NOTIFY, acpi_drv_cbat_notify);
1751 		}
1752 	}
1753 	for (i = 0; i < nac; i++) {
1754 		(void) AcpiRemoveNotifyHandler(acpi_drv_ac[i].dev.hdl,
1755 		    ACPI_DEVICE_NOTIFY, acpi_drv_ac_notify);
1756 	}
1757 	(void) AcpiRemoveNotifyHandler(lid.dev.hdl, ACPI_DEVICE_NOTIFY,
1758 	    acpi_drv_lid_notify);
1759 
1760 	if (acpi_hotkey.hotkey_method != HOTKEY_METHOD_NONE)
1761 		(void) hotkey_fini(&acpi_hotkey);
1762 }
1763 
1764 /*ARGSUSED*/
1765 static int
1766 acpi_drv_kstat_power_update(kstat_t *ksp, int flag)
1767 {
1768 	if (flag == KSTAT_WRITE) {
1769 		return (EACCES);
1770 	}
1771 
1772 	mutex_enter(&acpi_drv_mutex);
1773 	if (acpi_drv_psr_type == ACPI_DRV_TYPE_UNKNOWN) {
1774 		mutex_exit(&acpi_drv_mutex);
1775 		return (EIO);
1776 	}
1777 	kstat_named_setstr(&acpi_drv_power_kstat.acpi_drv_power,
1778 	    acpi_drv_psr_type == ACPI_DRV_TYPE_AC ? AC : BATTERY);
1779 	acpi_drv_power_kstat.acpi_drv_supported_battery_count.value.ui32 =
1780 	    (uint32_t)nbat;
1781 	mutex_exit(&acpi_drv_mutex);
1782 
1783 	return (0);
1784 }
1785 
1786 /*ARGSUSED*/
1787 static int
1788 acpi_drv_kstat_warn_update(kstat_t *ksp, int flag)
1789 {
1790 	if (flag == KSTAT_WRITE) {
1791 		int ret = 0;
1792 		acpi_drv_warn_t bw;
1793 		acpi_drv_warn_kstat_t kbw;
1794 
1795 		kbw = *(acpi_drv_warn_kstat_t *)acpi_drv_warn_ksp->ks_data;
1796 
1797 		mutex_enter(&acpi_drv_mutex);
1798 		bw.bw_enabled  = kbw.acpi_drv_bw_enabled.value.ui32;
1799 		bw.bw_charge_warn = kbw.acpi_drv_bw_charge_warn.value.ui32;
1800 		bw.bw_charge_low = kbw.acpi_drv_bw_charge_low.value.ui32;
1801 		ret = acpi_drv_set_warn(&bw);
1802 		mutex_exit(&acpi_drv_mutex);
1803 
1804 		return (ret);
1805 	} else {
1806 		acpi_drv_warn_kstat_t *wp = &acpi_drv_warn_kstat;
1807 
1808 		mutex_enter(&acpi_drv_mutex);
1809 		wp->acpi_drv_bw_enabled.value.ui32 = acpi_drv_warn_enabled;
1810 		wp->acpi_drv_bw_charge_warn.value.ui32 = acpi_drv_syn_warn_per;
1811 		wp->acpi_drv_bw_charge_low.value.ui32 = acpi_drv_syn_low_per;
1812 		mutex_exit(&acpi_drv_mutex);
1813 
1814 		return (0);
1815 	}
1816 }
1817 
1818 static int
1819 acpi_drv_kstat_bif_update(kstat_t *ksp, int flag)
1820 {
1821 	struct acpi_drv_cbat_state *bp;
1822 	acpi_bif_t *bif;
1823 	acpi_drv_bif_kstat_t *kp;
1824 
1825 	if (flag == KSTAT_WRITE) {
1826 		return (EACCES);
1827 	}
1828 
1829 	bp = (struct acpi_drv_cbat_state *)ksp->ks_private;
1830 	mutex_enter(&acpi_drv_mutex);
1831 
1832 	if (acpi_drv_cbat_present(bp) <= 0) {
1833 		mutex_exit(&acpi_drv_mutex);
1834 		return (ENXIO);
1835 	}
1836 
1837 	bzero(&bif, sizeof (bif));
1838 	if (acpi_drv_update_bif(bp) != ACPI_DRV_OK) {
1839 		mutex_exit(&acpi_drv_mutex);
1840 		return (ENXIO);
1841 	}
1842 
1843 	bif = &bp->bif_cache;
1844 	kp = &acpi_drv_bif_kstat;
1845 
1846 	/* Update BIF */
1847 	kp->acpi_drv_bif_unit.value.ui32 = bif->bif_unit;
1848 	kp->acpi_drv_bif_design_cap.value.ui32 = bif->bif_design_cap;
1849 	kp->acpi_drv_bif_last_cap.value.ui32 = bif->bif_last_cap;
1850 	kp->acpi_drv_bif_tech.value.ui32 = bif->bif_tech;
1851 	kp->acpi_drv_bif_voltage.value.ui32 = bif->bif_voltage;
1852 	kp->acpi_drv_bif_warn_cap.value.ui32 = bif->bif_warn_cap;
1853 	kp->acpi_drv_bif_low_cap.value.ui32 = bif->bif_low_cap;
1854 	kp->acpi_drv_bif_gran1_cap.value.ui32 = bif->bif_gran1_cap;
1855 	kp->acpi_drv_bif_gran2_cap.value.ui32 = bif->bif_gran2_cap;
1856 
1857 	kstat_named_setstr(&kp->acpi_drv_bif_model, bif->bif_model);
1858 	kstat_named_setstr(&kp->acpi_drv_bif_serial, bif->bif_serial);
1859 	kstat_named_setstr(&kp->acpi_drv_bif_type, bif->bif_type);
1860 	kstat_named_setstr(&kp->acpi_drv_bif_oem_info, bif->bif_oem_info);
1861 
1862 	mutex_exit(&acpi_drv_mutex);
1863 	return (0);
1864 }
1865 
1866 static int
1867 acpi_drv_kstat_bst_update(kstat_t *ksp, int flag)
1868 {
1869 	struct acpi_drv_cbat_state *bp;
1870 	acpi_bst_t *bst;
1871 	acpi_drv_bst_kstat_t *kp;
1872 
1873 	if (flag == KSTAT_WRITE) {
1874 		return (EACCES);
1875 	}
1876 
1877 	bp = (struct acpi_drv_cbat_state *)ksp->ks_private;
1878 	mutex_enter(&acpi_drv_mutex);
1879 
1880 	if (acpi_drv_cbat_present(bp) <= 0) {
1881 		mutex_exit(&acpi_drv_mutex);
1882 		return (ENXIO);
1883 	}
1884 
1885 	bzero(&bst, sizeof (bst));
1886 	if (acpi_drv_update_bst(bp) != ACPI_DRV_OK) {
1887 		mutex_exit(&acpi_drv_mutex);
1888 		return (ENXIO);
1889 	}
1890 
1891 	bst = &bp->bst_cache;
1892 	kp = &acpi_drv_bst_kstat;
1893 
1894 	/* Update BST */
1895 	kp->acpi_drv_bst_state.value.ui32 = bst->bst_state;
1896 	kp->acpi_drv_bst_rate.value.ui32 = bst->bst_rate;
1897 	kp->acpi_drv_bst_rem_cap.value.ui32 = bst->bst_rem_cap;
1898 	kp->acpi_drv_bst_voltage.value.ui32 = bst->bst_voltage;
1899 
1900 	mutex_exit(&acpi_drv_mutex);
1901 	return (0);
1902 }
1903 
1904 static int
1905 acpi_drv_kstat_init(void)
1906 {
1907 	char name[KSTAT_STRLEN];
1908 	struct acpi_drv_cbat_state *bp;
1909 
1910 	/*
1911 	 * Allocate, initialize and install powerstatus and
1912 	 * supported_battery_count kstat.
1913 	 */
1914 	acpi_drv_power_ksp = kstat_create(ACPI_DRV_NAME, 0,
1915 	    ACPI_DRV_POWER_KSTAT_NAME, "misc",
1916 	    KSTAT_TYPE_NAMED,
1917 	    sizeof (acpi_drv_power_kstat) / sizeof (kstat_named_t),
1918 	    KSTAT_FLAG_VIRTUAL);
1919 	if (acpi_drv_power_ksp == NULL) {
1920 		ACPI_DRV_DBG(CE_WARN, NULL,
1921 		    "kstat_create(%s) fail", ACPI_DRV_POWER_KSTAT_NAME);
1922 		return (ACPI_DRV_ERR);
1923 	}
1924 
1925 	acpi_drv_power_ksp->ks_data = &acpi_drv_power_kstat;
1926 	acpi_drv_power_ksp->ks_update = acpi_drv_kstat_power_update;
1927 	acpi_drv_power_ksp->ks_data_size += MAXNAMELEN;
1928 	kstat_install(acpi_drv_power_ksp);
1929 
1930 	/*
1931 	 * Allocate, initialize and install battery_capacity_warning kstat.
1932 	 */
1933 	acpi_drv_warn_ksp = kstat_create(ACPI_DRV_NAME, 0,
1934 	    ACPI_DRV_BTWARN_KSTAT_NAME, "misc",
1935 	    KSTAT_TYPE_NAMED,
1936 	    sizeof (acpi_drv_warn_kstat) / sizeof (kstat_named_t),
1937 	    KSTAT_FLAG_VIRTUAL | KSTAT_FLAG_WRITABLE);
1938 	if (acpi_drv_warn_ksp == NULL) {
1939 		ACPI_DRV_DBG(CE_WARN, NULL,
1940 		    "kstat_create(%s) fail", ACPI_DRV_BTWARN_KSTAT_NAME);
1941 		return (ACPI_DRV_ERR);
1942 	}
1943 
1944 	acpi_drv_warn_ksp->ks_data = &acpi_drv_warn_kstat;
1945 	acpi_drv_warn_ksp->ks_update = acpi_drv_kstat_warn_update;
1946 	kstat_install(acpi_drv_warn_ksp);
1947 
1948 	/*
1949 	 * Allocate, initialize and install BIF and BST kstat
1950 	 * for each battery.
1951 	 */
1952 	for (bp = &acpi_drv_cbat[0]; bp < &acpi_drv_cbat[ACPI_DRV_MAX_BAT_NUM];
1953 	    bp++) {
1954 		if (bp->dev.valid) {
1955 			kstat_t *ksp;
1956 
1957 			/* BIF kstat */
1958 			(void) snprintf(name, KSTAT_STRLEN-1, "%s%d",
1959 			    ACPI_DRV_BIF_KSTAT_NAME, bp->dev.index);
1960 			ksp = kstat_create(ACPI_DRV_NAME, 0,
1961 			    name, "misc", KSTAT_TYPE_NAMED,
1962 			    sizeof (acpi_drv_bif_kstat) /
1963 			    sizeof (kstat_named_t), KSTAT_FLAG_VIRTUAL);
1964 			if (ksp == NULL) {
1965 				ACPI_DRV_DBG(CE_WARN, NULL,
1966 				    "kstat_create(%s) fail", name);
1967 				return (ACPI_DRV_ERR);
1968 			}
1969 			ACPI_DRV_DBG(CE_NOTE, NULL, "kstat_create(%s) ok",
1970 			    name);
1971 
1972 			bp->bat_bif_ksp = ksp;
1973 			ksp->ks_data = &acpi_drv_bif_kstat;
1974 			ksp->ks_update = acpi_drv_kstat_bif_update;
1975 			ksp->ks_data_size += MAXNAMELEN * 4;
1976 			ksp->ks_private = bp;
1977 
1978 			kstat_install(ksp);
1979 
1980 			/* BST kstat */
1981 			(void) snprintf(name, KSTAT_STRLEN-1, "%s%d",
1982 			    ACPI_DRV_BST_KSTAT_NAME, bp->dev.index);
1983 			ksp = kstat_create(ACPI_DRV_NAME, 0, name, "misc",
1984 			    KSTAT_TYPE_NAMED,
1985 			    sizeof (acpi_drv_bst_kstat) /
1986 			    sizeof (kstat_named_t),
1987 			    KSTAT_FLAG_VIRTUAL);
1988 			if (ksp == NULL) {
1989 				ACPI_DRV_DBG(CE_WARN, NULL,
1990 				    "kstat_create(%s) fail", name);
1991 				return (ACPI_DRV_ERR);
1992 			}
1993 			ACPI_DRV_DBG(CE_NOTE, NULL, "kstat_create(%s) ok",
1994 			    name);
1995 
1996 			bp->bat_bst_ksp = ksp;
1997 			ksp->ks_data = &acpi_drv_bst_kstat;
1998 			ksp->ks_update = acpi_drv_kstat_bst_update;
1999 			ksp->ks_data_size += MAXNAMELEN * 4;
2000 			ksp->ks_private = bp;
2001 
2002 			kstat_install(ksp);
2003 		}
2004 	}
2005 
2006 	return (ACPI_DRV_OK);
2007 }
2008 
2009 static void
2010 acpi_drv_kstat_fini()
2011 {
2012 	struct acpi_drv_cbat_state *bp;
2013 
2014 	if (acpi_drv_power_ksp != NULL) {
2015 		kstat_delete(acpi_drv_power_ksp);
2016 	}
2017 	if (acpi_drv_warn_ksp != NULL) {
2018 		kstat_delete(acpi_drv_warn_ksp);
2019 	}
2020 	for (bp = &acpi_drv_cbat[0]; bp < &acpi_drv_cbat[ACPI_DRV_MAX_BAT_NUM];
2021 	    bp++) {
2022 		if (bp->dev.valid) {
2023 			if (bp->bat_bif_ksp != NULL) {
2024 				kstat_delete(bp->bat_bif_ksp);
2025 			}
2026 			if (bp->bat_bst_ksp != NULL) {
2027 				kstat_delete(bp->bat_bst_ksp);
2028 			}
2029 		}
2030 	}
2031 }
2032 
2033 int
2034 acpi_drv_set_int(ACPI_HANDLE dev, char *method, uint32_t aint)
2035 {
2036 	ACPI_OBJECT_LIST al;
2037 	ACPI_OBJECT ao;
2038 
2039 	al.Pointer = &ao;
2040 	al.Count = 1;
2041 	ao.Type = ACPI_TYPE_INTEGER;
2042 	ao.Integer.Value = aint;
2043 	return (AcpiEvaluateObject(dev, method, &al, NULL));
2044 }
2045 
2046 int
2047 acpi_drv_dev_init(struct acpi_drv_dev *p)
2048 {
2049 	ACPI_DEVICE_INFO *info;
2050 	ACPI_STATUS ret;
2051 
2052 	ASSERT(p != NULL && p->hdl != NULL);
2053 
2054 	p->valid = 0;
2055 
2056 	/* Info size is variable depending on existance of _CID */
2057 	ret = AcpiGetObjectInfo(p->hdl, &info);
2058 	if (ACPI_FAILURE(ret)) {
2059 		ACPI_DRV_DBG(CE_WARN, NULL,
2060 		    "AcpiGetObjectInfo() fail: %d", (int32_t)ret);
2061 		return (ACPI_DRV_ERR);
2062 	}
2063 
2064 	if ((info->Valid & ACPI_VALID_HID) == 0) {
2065 		ACPI_DRV_DBG(CE_WARN, NULL,
2066 		    "!AcpiGetObjectInfo(): _HID not available");
2067 		p->hid[0] = 0;
2068 	} else {
2069 		(void) strlcpy(p->hid, info->HardwareId.String, ID_LEN);
2070 	}
2071 
2072 	/*
2073 	 * This object is optional, but is required when the device
2074 	 * has no other way to report a persistent unique device ID.
2075 	 */
2076 	if ((info->Valid & ACPI_VALID_UID) == 0) {
2077 		ACPI_DRV_DBG(CE_WARN, NULL,
2078 		    "!AcpiGetObjectInfo(): _UID not available");
2079 		/* Use 0 as the default _UID */
2080 		p->uid[0] = 0;
2081 	} else {
2082 		(void) strlcpy(p->uid, info->UniqueId.String, ID_LEN);
2083 	}
2084 
2085 	if (info->Valid & ACPI_VALID_ADR) {
2086 		p->valid = 1;
2087 		p->type = ACPI_DRV_TYPE_HOTKEY;
2088 	}
2089 
2090 	AcpiOsFree(info);
2091 
2092 	return (ACPI_DRV_OK);
2093 }
2094