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