xref: /illumos-gate/usr/src/uts/i86pc/io/acpi_drv/acpi_drv.c (revision aedf2b3bb56b025fcaf87b49ec6c8aeea07f16d7)
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 	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) strncpy(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_BUFFER buf;
1545 	ACPI_NOTIFY_HANDLER ntf_handler = NULL;
1546 	ACPI_STATUS ret;
1547 
1548 	ASSERT(p != NULL && p->hdl != NULL);
1549 
1550 	p->valid = 0;
1551 
1552 	/* Info size is variable depending on existance of _CID */
1553 	buf.Length = ACPI_ALLOCATE_BUFFER;
1554 	ret = AcpiGetObjectInfo(p->hdl, &buf);
1555 	if (ACPI_FAILURE(ret)) {
1556 		ACPI_DRV_DBG(CE_WARN, NULL,
1557 		    "AcpiGetObjectInfo() fail: %d", (int32_t)ret);
1558 		return (ACPI_DRV_ERR);
1559 	}
1560 
1561 	info = buf.Pointer;
1562 	if ((info->Valid & ACPI_VALID_HID) == 0) {
1563 		ACPI_DRV_DBG(CE_WARN, NULL,
1564 		    "AcpiGetObjectInfo(): _HID not available");
1565 		(void) strncpy(p->hid, "\0", ID_LEN);
1566 	} else {
1567 		(void) strncpy(p->hid, info->HardwareId.Value, ID_LEN);
1568 	}
1569 
1570 	/*
1571 	 * This object is optional, but is required when the device
1572 	 * has no other way to report a persistent unique device ID.
1573 	 */
1574 	if ((info->Valid & ACPI_VALID_UID) == 0) {
1575 		ACPI_DRV_DBG(CE_WARN, NULL,
1576 		    "AcpiGetObjectInfo(): _UID not available");
1577 		/* Use 0 as the default _UID */
1578 		(void) strncpy(p->uid, "\0", ID_LEN);
1579 	} else {
1580 		(void) strncpy(p->uid, info->UniqueId.Value, ID_LEN);
1581 	}
1582 
1583 	p->valid = 1;
1584 
1585 	if (strcmp(p->hid, ACPI_DEVNAME_CBAT) == 0) {
1586 		struct acpi_drv_cbat_state *bp =
1587 		    (struct acpi_drv_cbat_state *)p;
1588 
1589 		p->type = ACPI_DRV_TYPE_CBAT;
1590 		p->index = nbat - 1;
1591 
1592 		/* Update device present state */
1593 		(void) acpi_drv_update_present(p);
1594 		if (p->present) {
1595 			(void) acpi_drv_update_bif(bp);
1596 			(void) acpi_drv_update_bst(bp);
1597 
1598 			/* Init the current power source */
1599 			if (bp->bst_cache.bst_state & BST_FLAG_DISCHARGING) {
1600 				acpi_drv_set_psr(p);
1601 			}
1602 		}
1603 		ntf_handler = acpi_drv_cbat_notify;
1604 		ACPI_DRV_DBG(CE_NOTE, p, "battery %s",
1605 		    (p->present ? "present" : "absent"));
1606 	} else if (strcmp(p->hid, ACPI_DEVNAME_AC) == 0) {
1607 		p->type = ACPI_DRV_TYPE_AC;
1608 		p->index = nac - 1;
1609 
1610 		/* Update device present state */
1611 		(void) acpi_drv_update_present(p);
1612 		if (p->present) {
1613 			/* Init the current power source */
1614 			acpi_drv_set_psr(p);
1615 		}
1616 		ntf_handler = acpi_drv_ac_notify;
1617 		ACPI_DRV_DBG(CE_NOTE, p, "AC %s",
1618 		    (p->present ? "on-line" : "off-line"));
1619 	} else if (strcmp(p->hid, ACPI_DEVNAME_LID) == 0) {
1620 		p->type = ACPI_DRV_TYPE_LID;
1621 		p->index = 0;
1622 		lid.state_ok = ACPI_DRV_NTF_UNKNOWN;
1623 		(void) acpi_drv_update_lid(p);
1624 		ntf_handler = acpi_drv_lid_notify;
1625 		ACPI_DRV_DBG(CE_NOTE, p, "added");
1626 	} else {
1627 		ACPI_DRV_DBG(CE_NOTE, p, "unknown device");
1628 		p->valid = 0;
1629 	}
1630 
1631 	/* Register ACPI battery related events */
1632 	if (ntf_handler != NULL) {
1633 		if (ACPI_FAILURE(AcpiInstallNotifyHandler(p->hdl,
1634 		    ACPI_ALL_NOTIFY, ntf_handler, p))) {
1635 			ACPI_DRV_DBG(CE_NOTE, NULL,
1636 			    "Notify handler for %s.%s install failed",
1637 			    p->hid, p->uid);
1638 			return (ACPI_DRV_ERR);
1639 		}
1640 	}
1641 
1642 	AcpiOsFree(info);
1643 	return (ACPI_DRV_OK);
1644 }
1645 
1646 /*ARGSUSED*/
1647 static ACPI_STATUS
1648 acpi_drv_find_cb(ACPI_HANDLE ObjHandle, UINT32 NestingLevel, void *Context,
1649     void **ReturnValue)
1650 {
1651 	struct acpi_drv_dev *devp;
1652 	int *type = (int *)Context;
1653 
1654 	if (*type == ACPI_DRV_TYPE_CBAT) {
1655 		struct acpi_drv_cbat_state *bp;
1656 
1657 		if (nbat == ACPI_DRV_MAX_BAT_NUM) {
1658 			ACPI_DRV_DBG(CE_WARN, NULL,
1659 			    "Need to support more batteries: "
1660 			    "BATTERY_MAX = %d", ACPI_DRV_MAX_BAT_NUM);
1661 			return (AE_LIMIT);
1662 		}
1663 		bp = &acpi_drv_cbat[nbat++];
1664 		devp = (struct acpi_drv_dev *)bp;
1665 	} else if (*type == ACPI_DRV_TYPE_AC) {
1666 		struct acpi_drv_ac_state *ap;
1667 
1668 		if (nac == ACPI_DRV_MAX_AC_NUM) {
1669 			ACPI_DRV_DBG(CE_WARN, NULL, "Need to support more ACs: "
1670 			    "AC_MAX = %d", ACPI_DRV_MAX_AC_NUM);
1671 			return (AE_LIMIT);
1672 		}
1673 		ap = &acpi_drv_ac[nac++];
1674 		devp = (struct acpi_drv_dev *)ap;
1675 	} else if (*type == ACPI_DRV_TYPE_LID) {
1676 		struct acpi_drv_lid_state *lp;
1677 
1678 		nlid++;
1679 		lp = &lid;
1680 		devp = (struct acpi_drv_dev *)lp;
1681 	} else {
1682 		ACPI_DRV_DBG(CE_WARN, NULL, "acpi_drv_find_cb(): "
1683 		    "Unknown device");
1684 		return (AE_ERROR);
1685 	}
1686 
1687 	devp->hdl = ObjHandle;
1688 
1689 	/* Try to get as many working objs as possible */
1690 	(void) acpi_drv_obj_init(devp);
1691 	return (AE_OK);
1692 }
1693 
1694 static int
1695 acpi_drv_acpi_init()
1696 {
1697 	int *retp, type;
1698 	int status = ACPI_DRV_ERR;
1699 	hotkey_drv_t *htkp;
1700 
1701 	/* Check to see if ACPI CA services are available */
1702 	if (AcpiSubsystemStatus() != AE_OK) {
1703 		ACPI_DRV_DBG(CE_WARN, NULL, "ACPI CA not ready");
1704 		return (status);
1705 	}
1706 
1707 	/* Init Control Method Batterys */
1708 	type = ACPI_DRV_TYPE_CBAT;
1709 	if (ACPI_SUCCESS(AcpiGetDevices(ACPI_DEVNAME_CBAT, acpi_drv_find_cb,
1710 	    &type, (void *)&retp)) && nbat) {
1711 		status = ACPI_DRV_OK;
1712 	}
1713 
1714 	/* Init AC */
1715 	type = ACPI_DRV_TYPE_AC;
1716 	if (ACPI_SUCCESS(AcpiGetDevices(ACPI_DEVNAME_AC, acpi_drv_find_cb,
1717 	    &type, (void *)&retp)) && nac) {
1718 		status = ACPI_DRV_OK;
1719 	}
1720 
1721 	/* Init LID */
1722 	type = ACPI_DRV_TYPE_LID;
1723 	if (ACPI_SUCCESS(AcpiGetDevices(ACPI_DEVNAME_LID, acpi_drv_find_cb,
1724 	    &type, (void *)&retp)) && nlid) {
1725 		status = ACPI_DRV_OK;
1726 	}
1727 
1728 	/* Init Hotkey Device */
1729 	type = ACPI_DRV_TYPE_HOTKEY;
1730 	htkp = &acpi_hotkey;
1731 	bzero(htkp, sizeof (hotkey_drv_t));
1732 	htkp->dip = acpi_drv_dip;
1733 	htkp->hotkey_lock = &acpi_drv_mutex;
1734 	if (hotkey_init(htkp) == ACPI_DRV_OK) {
1735 		status = ACPI_DRV_OK;
1736 	}
1737 
1738 	acpi_drv_update_cap(1);
1739 
1740 	return (status);
1741 }
1742 
1743 static void
1744 acpi_drv_acpi_fini(void)
1745 {
1746 	int i;
1747 	struct acpi_drv_cbat_state *bp;
1748 
1749 	for (bp = &acpi_drv_cbat[0]; bp < &acpi_drv_cbat[ACPI_DRV_MAX_BAT_NUM];
1750 	    bp++) {
1751 		if (bp->dev.valid) {
1752 			AcpiRemoveNotifyHandler(bp->dev.hdl, ACPI_DEVICE_NOTIFY,
1753 			    acpi_drv_cbat_notify);
1754 		}
1755 	}
1756 	for (i = 0; i < nac; i++) {
1757 		AcpiRemoveNotifyHandler(acpi_drv_ac[i].dev.hdl,
1758 		    ACPI_DEVICE_NOTIFY, acpi_drv_ac_notify);
1759 	}
1760 	AcpiRemoveNotifyHandler(lid.dev.hdl, ACPI_DEVICE_NOTIFY,
1761 	    acpi_drv_lid_notify);
1762 
1763 	if (acpi_hotkey.hotkey_method != HOTKEY_METHOD_NONE)
1764 		(void) hotkey_fini(&acpi_hotkey);
1765 }
1766 
1767 /*ARGSUSED*/
1768 static int
1769 acpi_drv_kstat_power_update(kstat_t *ksp, int flag)
1770 {
1771 	if (flag == KSTAT_WRITE) {
1772 		return (EACCES);
1773 	}
1774 
1775 	mutex_enter(&acpi_drv_mutex);
1776 	if (acpi_drv_psr_type == ACPI_DRV_TYPE_UNKNOWN) {
1777 		mutex_exit(&acpi_drv_mutex);
1778 		return (EIO);
1779 	}
1780 	kstat_named_setstr(&acpi_drv_power_kstat.acpi_drv_power,
1781 	    acpi_drv_psr_type == ACPI_DRV_TYPE_AC ? AC : BATTERY);
1782 	acpi_drv_power_kstat.acpi_drv_supported_battery_count.value.ui32 =
1783 	    (uint32_t)nbat;
1784 	mutex_exit(&acpi_drv_mutex);
1785 
1786 	return (0);
1787 }
1788 
1789 /*ARGSUSED*/
1790 static int
1791 acpi_drv_kstat_warn_update(kstat_t *ksp, int flag)
1792 {
1793 	if (flag == KSTAT_WRITE) {
1794 		int ret = 0;
1795 		acpi_drv_warn_t bw;
1796 		acpi_drv_warn_kstat_t kbw;
1797 
1798 		kbw = *(acpi_drv_warn_kstat_t *)acpi_drv_warn_ksp->ks_data;
1799 
1800 		mutex_enter(&acpi_drv_mutex);
1801 		bw.bw_enabled  = kbw.acpi_drv_bw_enabled.value.ui32;
1802 		bw.bw_charge_warn = kbw.acpi_drv_bw_charge_warn.value.ui32;
1803 		bw.bw_charge_low = kbw.acpi_drv_bw_charge_low.value.ui32;
1804 		ret = acpi_drv_set_warn(&bw);
1805 		mutex_exit(&acpi_drv_mutex);
1806 
1807 		return (ret);
1808 	} else {
1809 		acpi_drv_warn_kstat_t *wp = &acpi_drv_warn_kstat;
1810 
1811 		mutex_enter(&acpi_drv_mutex);
1812 		wp->acpi_drv_bw_enabled.value.ui32 = acpi_drv_warn_enabled;
1813 		wp->acpi_drv_bw_charge_warn.value.ui32 = acpi_drv_syn_warn_per;
1814 		wp->acpi_drv_bw_charge_low.value.ui32 = acpi_drv_syn_low_per;
1815 		mutex_exit(&acpi_drv_mutex);
1816 
1817 		return (0);
1818 	}
1819 }
1820 
1821 static int
1822 acpi_drv_kstat_bif_update(kstat_t *ksp, int flag)
1823 {
1824 	struct acpi_drv_cbat_state *bp;
1825 	acpi_bif_t *bif;
1826 	acpi_drv_bif_kstat_t *kp;
1827 
1828 	if (flag == KSTAT_WRITE) {
1829 		return (EACCES);
1830 	}
1831 
1832 	bp = (struct acpi_drv_cbat_state *)ksp->ks_private;
1833 	mutex_enter(&acpi_drv_mutex);
1834 
1835 	if (acpi_drv_cbat_present(bp) <= 0) {
1836 		mutex_exit(&acpi_drv_mutex);
1837 		return (ENXIO);
1838 	}
1839 
1840 	bzero(&bif, sizeof (bif));
1841 	if (acpi_drv_update_bif(bp) != ACPI_DRV_OK) {
1842 		mutex_exit(&acpi_drv_mutex);
1843 		return (ENXIO);
1844 	}
1845 
1846 	bif = &bp->bif_cache;
1847 	kp = &acpi_drv_bif_kstat;
1848 
1849 	/* Update BIF */
1850 	kp->acpi_drv_bif_unit.value.ui32 = bif->bif_unit;
1851 	kp->acpi_drv_bif_design_cap.value.ui32 = bif->bif_design_cap;
1852 	kp->acpi_drv_bif_last_cap.value.ui32 = bif->bif_last_cap;
1853 	kp->acpi_drv_bif_tech.value.ui32 = bif->bif_tech;
1854 	kp->acpi_drv_bif_voltage.value.ui32 = bif->bif_voltage;
1855 	kp->acpi_drv_bif_warn_cap.value.ui32 = bif->bif_warn_cap;
1856 	kp->acpi_drv_bif_low_cap.value.ui32 = bif->bif_low_cap;
1857 	kp->acpi_drv_bif_gran1_cap.value.ui32 = bif->bif_gran1_cap;
1858 	kp->acpi_drv_bif_gran2_cap.value.ui32 = bif->bif_gran2_cap;
1859 
1860 	kstat_named_setstr(&kp->acpi_drv_bif_model, bif->bif_model);
1861 	kstat_named_setstr(&kp->acpi_drv_bif_serial, bif->bif_serial);
1862 	kstat_named_setstr(&kp->acpi_drv_bif_type, bif->bif_type);
1863 	kstat_named_setstr(&kp->acpi_drv_bif_oem_info, bif->bif_oem_info);
1864 
1865 	mutex_exit(&acpi_drv_mutex);
1866 	return (0);
1867 }
1868 
1869 static int
1870 acpi_drv_kstat_bst_update(kstat_t *ksp, int flag)
1871 {
1872 	struct acpi_drv_cbat_state *bp;
1873 	acpi_bst_t *bst;
1874 	acpi_drv_bst_kstat_t *kp;
1875 
1876 	if (flag == KSTAT_WRITE) {
1877 		return (EACCES);
1878 	}
1879 
1880 	bp = (struct acpi_drv_cbat_state *)ksp->ks_private;
1881 	mutex_enter(&acpi_drv_mutex);
1882 
1883 	if (acpi_drv_cbat_present(bp) <= 0) {
1884 		mutex_exit(&acpi_drv_mutex);
1885 		return (ENXIO);
1886 	}
1887 
1888 	bzero(&bst, sizeof (bst));
1889 	if (acpi_drv_update_bst(bp) != ACPI_DRV_OK) {
1890 		mutex_exit(&acpi_drv_mutex);
1891 		return (ENXIO);
1892 	}
1893 
1894 	bst = &bp->bst_cache;
1895 	kp = &acpi_drv_bst_kstat;
1896 
1897 	/* Update BST */
1898 	kp->acpi_drv_bst_state.value.ui32 = bst->bst_state;
1899 	kp->acpi_drv_bst_rate.value.ui32 = bst->bst_rate;
1900 	kp->acpi_drv_bst_rem_cap.value.ui32 = bst->bst_rem_cap;
1901 	kp->acpi_drv_bst_voltage.value.ui32 = bst->bst_voltage;
1902 
1903 	mutex_exit(&acpi_drv_mutex);
1904 	return (0);
1905 }
1906 
1907 static int
1908 acpi_drv_kstat_init(void)
1909 {
1910 	char name[KSTAT_STRLEN];
1911 	struct acpi_drv_cbat_state *bp;
1912 
1913 	/*
1914 	 * Allocate, initialize and install powerstatus and
1915 	 * supported_battery_count kstat.
1916 	 */
1917 	acpi_drv_power_ksp = kstat_create(ACPI_DRV_NAME, 0,
1918 	    ACPI_DRV_POWER_KSTAT_NAME, "misc",
1919 	    KSTAT_TYPE_NAMED,
1920 	    sizeof (acpi_drv_power_kstat) / sizeof (kstat_named_t),
1921 	    KSTAT_FLAG_VIRTUAL);
1922 	if (acpi_drv_power_ksp == NULL) {
1923 		ACPI_DRV_DBG(CE_WARN, NULL,
1924 		    "kstat_create(%s) fail", ACPI_DRV_POWER_KSTAT_NAME);
1925 		return (ACPI_DRV_ERR);
1926 	}
1927 
1928 	acpi_drv_power_ksp->ks_data = &acpi_drv_power_kstat;
1929 	acpi_drv_power_ksp->ks_update = acpi_drv_kstat_power_update;
1930 	acpi_drv_power_ksp->ks_data_size += MAXNAMELEN;
1931 	kstat_install(acpi_drv_power_ksp);
1932 
1933 	/*
1934 	 * Allocate, initialize and install battery_capacity_warning kstat.
1935 	 */
1936 	acpi_drv_warn_ksp = kstat_create(ACPI_DRV_NAME, 0,
1937 	    ACPI_DRV_BTWARN_KSTAT_NAME, "misc",
1938 	    KSTAT_TYPE_NAMED,
1939 	    sizeof (acpi_drv_warn_kstat) / sizeof (kstat_named_t),
1940 	    KSTAT_FLAG_VIRTUAL | KSTAT_FLAG_WRITABLE);
1941 	if (acpi_drv_warn_ksp == NULL) {
1942 		ACPI_DRV_DBG(CE_WARN, NULL,
1943 		    "kstat_create(%s) fail", ACPI_DRV_BTWARN_KSTAT_NAME);
1944 		return (ACPI_DRV_ERR);
1945 	}
1946 
1947 	acpi_drv_warn_ksp->ks_data = &acpi_drv_warn_kstat;
1948 	acpi_drv_warn_ksp->ks_update = acpi_drv_kstat_warn_update;
1949 	kstat_install(acpi_drv_warn_ksp);
1950 
1951 	/*
1952 	 * Allocate, initialize and install BIF and BST kstat
1953 	 * for each battery.
1954 	 */
1955 	for (bp = &acpi_drv_cbat[0]; bp < &acpi_drv_cbat[ACPI_DRV_MAX_BAT_NUM];
1956 	    bp++) {
1957 		if (bp->dev.valid) {
1958 			kstat_t *ksp;
1959 
1960 			/* BIF kstat */
1961 			(void) snprintf(name, KSTAT_STRLEN-1, "%s%d",
1962 			    ACPI_DRV_BIF_KSTAT_NAME, bp->dev.index);
1963 			ksp = kstat_create(ACPI_DRV_NAME, 0,
1964 			    name, "misc", KSTAT_TYPE_NAMED,
1965 			    sizeof (acpi_drv_bif_kstat) /
1966 			    sizeof (kstat_named_t), KSTAT_FLAG_VIRTUAL);
1967 			if (ksp == NULL) {
1968 				ACPI_DRV_DBG(CE_WARN, NULL,
1969 				    "kstat_create(%s) fail", name);
1970 				return (ACPI_DRV_ERR);
1971 			}
1972 			ACPI_DRV_DBG(CE_NOTE, NULL, "kstat_create(%s) ok",
1973 			    name);
1974 
1975 			bp->bat_bif_ksp = ksp;
1976 			ksp->ks_data = &acpi_drv_bif_kstat;
1977 			ksp->ks_update = acpi_drv_kstat_bif_update;
1978 			ksp->ks_data_size += MAXNAMELEN * 4;
1979 			ksp->ks_private = bp;
1980 
1981 			kstat_install(ksp);
1982 
1983 			/* BST kstat */
1984 			(void) snprintf(name, KSTAT_STRLEN-1, "%s%d",
1985 			    ACPI_DRV_BST_KSTAT_NAME, bp->dev.index);
1986 			ksp = kstat_create(ACPI_DRV_NAME, 0, name, "misc",
1987 			    KSTAT_TYPE_NAMED,
1988 			    sizeof (acpi_drv_bst_kstat) /
1989 			    sizeof (kstat_named_t),
1990 			    KSTAT_FLAG_VIRTUAL);
1991 			if (ksp == NULL) {
1992 				ACPI_DRV_DBG(CE_WARN, NULL,
1993 				    "kstat_create(%s) fail", name);
1994 				return (ACPI_DRV_ERR);
1995 			}
1996 			ACPI_DRV_DBG(CE_NOTE, NULL, "kstat_create(%s) ok",
1997 			    name);
1998 
1999 			bp->bat_bst_ksp = ksp;
2000 			ksp->ks_data = &acpi_drv_bst_kstat;
2001 			ksp->ks_update = acpi_drv_kstat_bst_update;
2002 			ksp->ks_data_size += MAXNAMELEN * 4;
2003 			ksp->ks_private = bp;
2004 
2005 			kstat_install(ksp);
2006 		}
2007 	}
2008 
2009 	return (ACPI_DRV_OK);
2010 }
2011 
2012 static void
2013 acpi_drv_kstat_fini()
2014 {
2015 	struct acpi_drv_cbat_state *bp;
2016 
2017 	if (acpi_drv_power_ksp != NULL) {
2018 		kstat_delete(acpi_drv_power_ksp);
2019 	}
2020 	if (acpi_drv_warn_ksp != NULL) {
2021 		kstat_delete(acpi_drv_warn_ksp);
2022 	}
2023 	for (bp = &acpi_drv_cbat[0]; bp < &acpi_drv_cbat[ACPI_DRV_MAX_BAT_NUM];
2024 	    bp++) {
2025 		if (bp->dev.valid) {
2026 			if (bp->bat_bif_ksp != NULL) {
2027 				kstat_delete(bp->bat_bif_ksp);
2028 			}
2029 			if (bp->bat_bst_ksp != NULL) {
2030 				kstat_delete(bp->bat_bst_ksp);
2031 			}
2032 		}
2033 	}
2034 }
2035 
2036 int
2037 acpi_drv_set_int(ACPI_HANDLE dev, char *method, uint32_t aint)
2038 {
2039 	ACPI_OBJECT_LIST al;
2040 	ACPI_OBJECT ao;
2041 
2042 	al.Pointer = &ao;
2043 	al.Count = 1;
2044 	ao.Type = ACPI_TYPE_INTEGER;
2045 	ao.Integer.Value = aint;
2046 	return (AcpiEvaluateObject(dev, method, &al, NULL));
2047 }
2048 
2049 int
2050 acpi_drv_dev_init(struct acpi_drv_dev *p)
2051 {
2052 	ACPI_DEVICE_INFO *info;
2053 	ACPI_BUFFER buf;
2054 	ACPI_STATUS ret;
2055 
2056 	ASSERT(p != NULL && p->hdl != NULL);
2057 
2058 	p->valid = 0;
2059 
2060 	/* Info size is variable depending on existance of _CID */
2061 	buf.Length = ACPI_ALLOCATE_BUFFER;
2062 	ret = AcpiGetObjectInfo(p->hdl, &buf);
2063 	if (ACPI_FAILURE(ret)) {
2064 		ACPI_DRV_DBG(CE_WARN, NULL,
2065 		    "AcpiGetObjectInfo() fail: %d", (int32_t)ret);
2066 		return (ACPI_DRV_ERR);
2067 	}
2068 
2069 	info = buf.Pointer;
2070 	if ((info->Valid & ACPI_VALID_HID) == 0) {
2071 		ACPI_DRV_DBG(CE_WARN, NULL,
2072 		    "!AcpiGetObjectInfo(): _HID not available");
2073 		(void) strncpy(p->hid, "\0", ID_LEN);
2074 	} else {
2075 		(void) strncpy(p->hid, info->HardwareId.Value, ID_LEN);
2076 	}
2077 
2078 	/*
2079 	 * This object is optional, but is required when the device
2080 	 * has no other way to report a persistent unique device ID.
2081 	 */
2082 	if ((info->Valid & ACPI_VALID_UID) == 0) {
2083 		ACPI_DRV_DBG(CE_WARN, NULL,
2084 		    "!AcpiGetObjectInfo(): _UID not available");
2085 		/* Use 0 as the default _UID */
2086 		(void) strncpy(p->uid, "\0", ID_LEN);
2087 	} else {
2088 		(void) strncpy(p->uid, info->UniqueId.Value, ID_LEN);
2089 	}
2090 
2091 	if (info->Valid & ACPI_VALID_ADR) {
2092 		p->valid = 1;
2093 		p->type = ACPI_DRV_TYPE_HOTKEY;
2094 	}
2095 
2096 	AcpiOsFree(info);
2097 
2098 	return (ACPI_DRV_OK);
2099 }
2100