Home | History | Annotate | Download | only in acpi_drv
      1 /*
      2  * CDDL HEADER START
      3  *
      4  * The contents of this file are subject to the terms of the
      5  * Common Development and Distribution License (the "License").
      6  * You may not use this file except in compliance with the License.
      7  *
      8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
      9  * or http://www.opensolaris.org/os/licensing.
     10  * See the License for the specific language governing permissions
     11  * and limitations under the License.
     12  *
     13  * When distributing Covered Code, include this CDDL HEADER in each
     14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
     15  * If applicable, add the following below this CDDL HEADER, with the
     16  * fields enclosed by brackets "[]" replaced with your own identifying
     17  * information: Portions Copyright [yyyy] [name of copyright owner]
     18  *
     19  * CDDL HEADER END
     20  */
     21 
     22 /*
     23  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
     24  * Use is subject to license terms.
     25  */
     26 
     27 /*
     28  * Driver for ACPI Battery, Lid, and Hotkey Control
     29  */
     30 #include <sys/hotkey_drv.h>
     31 #include <sys/sysevent/pwrctl.h>
     32 
     33 
     34 #define	ACPI_DRV_MOD_STRING		"ACPI driver"
     35 
     36 #define	MINOR_SHIFT			8
     37 #define	IDX_MASK			((1 << MINOR_SHIFT) - 1)
     38 #define	MINOR_BATT(idx)			(ACPI_DRV_TYPE_CBAT << MINOR_SHIFT | \
     39 					(idx))
     40 #define	MINOR_AC(idx)			(ACPI_DRV_TYPE_AC << MINOR_SHIFT | \
     41 					(idx))
     42 #define	MINOR_LID(idx)			(ACPI_DRV_TYPE_LID << MINOR_SHIFT | \
     43 					(idx))
     44 #define	MINOR_HOTKEY(idx)		(ACPI_DRV_TYPE_HOTKEY << MINOR_SHIFT \
     45 					| (idx))
     46 #define	MINOR2IDX(minor)		((minor) & IDX_MASK)
     47 #define	MINOR2TYPE(minor)		((minor) >> MINOR_SHIFT)
     48 
     49 #define	ACPI_DRV_MAX_BAT_NUM		8
     50 #define	ACPI_DRV_MAX_AC_NUM		10
     51 
     52 #define	BST_FLAG_DISCHARGING		(0x1)
     53 #define	BST_FLAG_CHARGING		(0x2)
     54 #define	BST_FLAG_CRITICAL		(0x4)
     55 
     56 /* Set if the battery is present */
     57 #define	STA_FLAG_BATT_PRESENT		(0x10)
     58 
     59 #define	ACPI_DEVNAME_CBAT		"PNP0C0A"
     60 #define	ACPI_DEVNAME_AC			"ACPI0003"
     61 #define	ACPI_DEVNAME_LID		"PNP0C0D"
     62 
     63 #define	ACPI_DRV_EVENTS			(POLLIN | POLLRDNORM)
     64 
     65 #ifdef DEBUG
     66 
     67 #define	ACPI_DRV_PRINT_BUFFER_SIZE	512
     68 static char acpi_drv_prt_buf[ACPI_DRV_PRINT_BUFFER_SIZE];
     69 static kmutex_t acpi_drv_prt_mutex;
     70 
     71 static int acpi_drv_debug = 0;
     72 #define	ACPI_DRV_DBG(lev, devp, ...) \
     73 	do { \
     74 		if (acpi_drv_debug) acpi_drv_printf((devp), \
     75 (lev), __VA_ARGS__); \
     76 _NOTE(CONSTCOND) } while (0)
     77 #define	ACPI_DRV_PRT_NOTIFY(hdl, val) \
     78 	do { \
     79 		if (acpi_drv_debug) acpi_drv_prt_notify((hdl), (val)); \
     80 _NOTE(CONSTCOND) } while (0)
     81 
     82 #else
     83 
     84 #define	ACPI_DRV_DBG(lev, devp, ...)
     85 #define	ACPI_DRV_PRT_NOTIFY(hdl, val)
     86 
     87 #endif /* DEBUG */
     88 
     89 /* ACPI notify types */
     90 enum acpi_drv_notify {
     91 	ACPI_DRV_NTF_UNKNOWN = -1,	/* No notifications seen, ever. */
     92 	ACPI_DRV_NTF_CHANGED,
     93 	ACPI_DRV_NTF_OK
     94 };
     95 
     96 static int acpi_drv_dev_present(struct acpi_drv_dev *);
     97 #define	acpi_drv_ac_present(a)	(((a)->dev.type == ACPI_DRV_TYPE_AC) ? \
     98 				acpi_drv_dev_present(&(a)->dev) : -1)
     99 #define	acpi_drv_cbat_present(a)	(((a)->dev.type == ACPI_DRV_TYPE_CBAT) \
    100 					? acpi_drv_dev_present(&(a)->dev) : -1)
    101 
    102 static dev_info_t *acpi_drv_dip = NULL;
    103 static kmutex_t acpi_drv_mutex;
    104 static struct pollhead acpi_drv_pollhead;
    105 
    106 /* Control Method Battery state */
    107 struct acpi_drv_cbat_state {
    108 	struct acpi_drv_dev dev;
    109 	/* Caches of _BST and _BIF */
    110 	enum acpi_drv_notify bat_bifok;
    111 	acpi_bif_t bif_cache;
    112 	enum acpi_drv_notify bat_bstok;
    113 	acpi_bst_t bst_cache;
    114 
    115 	uint32_t charge_warn;
    116 	uint32_t charge_low;
    117 
    118 	kstat_t *bat_bif_ksp;
    119 	kstat_t *bat_bst_ksp;
    120 } acpi_drv_cbat[ACPI_DRV_MAX_BAT_NUM];
    121 static int nbat = 0;
    122 
    123 /*
    124  * Synthesis battery state
    125  * When there are multiple batteries present, the battery subsystem
    126  * is not required to perform any synthesis of a composite battery
    127  * from the data of the separate batteries. In cases where the
    128  * battery subsystem does not synthesize a composite battery from
    129  * the separate battery's data, the OS must provide that synthesis.
    130  */
    131 static uint32_t acpi_drv_syn_rem_cap;
    132 static uint32_t acpi_drv_syn_last_cap;
    133 static uint32_t acpi_drv_syn_oem_warn_cap;
    134 static uint32_t acpi_drv_syn_oem_low_cap;
    135 
    136 static int acpi_drv_warn_enabled;
    137 static uint32_t acpi_drv_syn_warn_per;
    138 static uint32_t acpi_drv_syn_low_per;
    139 static uint32_t acpi_drv_syn_warn_cap;
    140 static uint32_t acpi_drv_syn_low_cap;
    141 /* Tracking boundery passing of _BST charge levels */
    142 static uint32_t acpi_drv_syn_last_level;
    143 
    144 /* AC state */
    145 static struct acpi_drv_ac_state {
    146 	struct acpi_drv_dev dev;
    147 } acpi_drv_ac[ACPI_DRV_MAX_AC_NUM];
    148 static int nac = 0;
    149 
    150 /*
    151  * Current power source device
    152  * Note: assume only one device can be the power source device.
    153  */
    154 static int acpi_drv_psr_type = ACPI_DRV_TYPE_UNKNOWN;
    155 static struct acpi_drv_dev *acpi_drv_psr_devp = NULL;
    156 
    157 struct obj_desc {
    158 	char *name;
    159 	int offset;
    160 	int size;
    161 	int type;
    162 };
    163 
    164 /* Object copy definitions */
    165 #define	OFFSETOF(s, m)		((size_t)(&(((s *)0)->m)))
    166 #define	SIZEOF(s, m)		(sizeof (((s *)0)->m))
    167 #define	FIELD(n, s, m, t) \
    168 	{ n, OFFSETOF(s, m), SIZEOF(s, m), t }
    169 #define	FIELD_NULL		{ NULL, -1, 0, ACPI_TYPE_ANY }
    170 
    171 static struct obj_desc bif_desc[] = {
    172 	FIELD("bif_unit",	acpi_bif_t, bif_unit,	ACPI_TYPE_INTEGER),
    173 	FIELD("bif_design_cap", acpi_bif_t, bif_design_cap, ACPI_TYPE_INTEGER),
    174 	FIELD("bif_last_cap",	acpi_bif_t, bif_last_cap,   ACPI_TYPE_INTEGER),
    175 	FIELD("bif_tech",	acpi_bif_t, bif_tech,	ACPI_TYPE_INTEGER),
    176 	FIELD("bif_voltage",	acpi_bif_t, bif_voltage, ACPI_TYPE_INTEGER),
    177 	FIELD("bif_warn_cap",	acpi_bif_t, bif_warn_cap, ACPI_TYPE_INTEGER),
    178 	FIELD("bif_low_cap",	acpi_bif_t, bif_low_cap,  ACPI_TYPE_INTEGER),
    179 	FIELD("bif_gran1_cap",	acpi_bif_t, bif_gran1_cap, ACPI_TYPE_INTEGER),
    180 	FIELD("bif_gran2_cap",	acpi_bif_t, bif_gran2_cap, ACPI_TYPE_INTEGER),
    181 	FIELD("bif_model",	acpi_bif_t, bif_model,	ACPI_TYPE_STRING),
    182 	FIELD("bif_serial",	acpi_bif_t, bif_serial,	ACPI_TYPE_STRING),
    183 	FIELD("bif_type",	acpi_bif_t, bif_type,	ACPI_TYPE_STRING),
    184 	FIELD("bif_oem_info",	acpi_bif_t, bif_oem_info, ACPI_TYPE_STRING),
    185 	FIELD_NULL
    186 };
    187 
    188 static struct obj_desc bst_desc[] = {
    189 	FIELD("bst_state",   acpi_bst_t, bst_state,	ACPI_TYPE_INTEGER),
    190 	FIELD("bst_rate",    acpi_bst_t, bst_rate,	ACPI_TYPE_INTEGER),
    191 	FIELD("bst_rem_cap", acpi_bst_t, bst_rem_cap,	ACPI_TYPE_INTEGER),
    192 	FIELD("bst_voltage", acpi_bst_t, bst_voltage,	ACPI_TYPE_INTEGER),
    193 	FIELD_NULL
    194 };
    195 
    196 /* kstat definitions */
    197 static kstat_t *acpi_drv_power_ksp;
    198 static kstat_t *acpi_drv_warn_ksp;
    199 
    200 acpi_drv_power_kstat_t acpi_drv_power_kstat = {
    201 	{ SYSTEM_POWER,			KSTAT_DATA_STRING },
    202 	{ SUPPORTED_BATTERY_COUNT,	KSTAT_DATA_UINT32 },
    203 };
    204 
    205 acpi_drv_warn_kstat_t acpi_drv_warn_kstat = {
    206 	{ BW_ENABLED,			KSTAT_DATA_UINT32 },
    207 	{ BW_POWEROFF_THRESHOLD,	KSTAT_DATA_UINT32 },
    208 	{ BW_SHUTDOWN_THRESHOLD,	KSTAT_DATA_UINT32 },
    209 };
    210 
    211 /* BIF */
    212 acpi_drv_bif_kstat_t acpi_drv_bif_kstat = {
    213 	{ BIF_UNIT,		KSTAT_DATA_UINT32 },
    214 	{ BIF_DESIGN_CAP,	KSTAT_DATA_UINT32 },
    215 	{ BIF_LAST_CAP,		KSTAT_DATA_UINT32 },
    216 	{ BIF_TECH,		KSTAT_DATA_UINT32 },
    217 	{ BIF_VOLTAGE,		KSTAT_DATA_UINT32 },
    218 	{ BIF_WARN_CAP,		KSTAT_DATA_UINT32 },
    219 	{ BIF_LOW_CAP,		KSTAT_DATA_UINT32 },
    220 	{ BIF_GRAN1_CAP,	KSTAT_DATA_UINT32 },
    221 	{ BIF_GRAN2_CAP,	KSTAT_DATA_UINT32 },
    222 	{ BIF_MODEL,		KSTAT_DATA_STRING },
    223 	{ BIF_SERIAL,		KSTAT_DATA_STRING },
    224 	{ BIF_TYPE,		KSTAT_DATA_STRING },
    225 	{ BIF_OEM_INFO,		KSTAT_DATA_STRING },
    226 };
    227 
    228 /* BST */
    229 acpi_drv_bst_kstat_t acpi_drv_bst_kstat = {
    230 	{ BST_STATE,		KSTAT_DATA_UINT32 },
    231 	{ BST_RATE,		KSTAT_DATA_UINT32 },
    232 	{ BST_REM_CAP,		KSTAT_DATA_UINT32 },
    233 	{ BST_VOLTAGE,		KSTAT_DATA_UINT32 },
    234 };
    235 
    236 struct acpi_drv_lid_state {
    237 	struct acpi_drv_dev dev;
    238 	enum acpi_drv_notify state_ok;
    239 	int state;
    240 } lid;
    241 static int nlid = 0;
    242 
    243 struct hotkey_drv acpi_hotkey;
    244 
    245 static int acpi_drv_attach(dev_info_t *devi, ddi_attach_cmd_t cmd);
    246 static int acpi_drv_detach(dev_info_t *devi, ddi_detach_cmd_t cmd);
    247 static int acpi_drv_getinfo(dev_info_t *dip, ddi_info_cmd_t cmd, void *arg,
    248     void **resultp);
    249 static int acpi_drv_open(dev_t *devp, int flag, int otyp, cred_t *crp);
    250 static int acpi_drv_close(dev_t dev, int flag, int otyp, cred_t *crp);
    251 static int acpi_drv_ioctl(dev_t dev, int cmd, intptr_t arg, int mode,
    252     cred_t *cr, int *rval);
    253 static int acpi_drv_chpoll(dev_t dev, short events, int anyyet,
    254     short *reventsp, struct pollhead **phpp);
    255 static int acpi_drv_ac_ioctl(int index, int cmd, intptr_t arg, int mode,
    256     cred_t *cr, int *rval);
    257 static int acpi_drv_cbat_ioctl(int index, int cmd, intptr_t arg, int mode,
    258     cred_t *cr, int *rval);
    259 static int acpi_drv_lid_ioctl(int index, int cmd, intptr_t arg, int mode,
    260     cred_t *cr, int *rval);
    261 #ifdef DEBUG
    262 static void acpi_drv_printf(struct acpi_drv_dev *devp, uint_t lev,
    263     const char *fmt, ...);
    264 #endif
    265 
    266 static int acpi_drv_update_bif(struct acpi_drv_cbat_state *bp);
    267 static int acpi_drv_update_bst(struct acpi_drv_cbat_state *bp);
    268 static int acpi_drv_update_lid(struct acpi_drv_dev *bp);
    269 static int acpi_drv_set_warn(acpi_drv_warn_t *bwp);
    270 static struct acpi_drv_cbat_state *acpi_drv_idx2cbat(int idx);
    271 static struct acpi_drv_ac_state *acpi_drv_idx2ac(int idx);
    272 static int acpi_drv_acpi_init(void);
    273 static void acpi_drv_acpi_fini(void);
    274 static int acpi_drv_kstat_init(void);
    275 static void acpi_drv_kstat_fini(void);
    276 
    277 static struct cb_ops acpi_drv_cb_ops = {
    278 	acpi_drv_open,		/* open */
    279 	acpi_drv_close,		/* close */
    280 	nodev,			/* strategy */
    281 	nodev,			/* print */
    282 	nodev,			/* dump */
    283 	nodev,			/* read */
    284 	nodev,			/* write */
    285 	acpi_drv_ioctl,		/* ioctl */
    286 	nodev,			/* devmap */
    287 	nodev,			/* mmap */
    288 	nodev,			/* segmap */
    289 	acpi_drv_chpoll,		/* chpoll */
    290 	ddi_prop_op,		/* prop_op */
    291 	NULL,			/* streamtab */
    292 	D_NEW | D_MP,
    293 	CB_REV,
    294 	nodev,
    295 	nodev
    296 };
    297 
    298 static struct dev_ops acpi_drv_dev_ops = {
    299 	DEVO_REV,
    300 	0,			/* refcnt */
    301 	acpi_drv_getinfo,	/* getinfo */
    302 	nulldev,		/* identify */
    303 	nulldev,		/* probe */
    304 	acpi_drv_attach,	/* attach */
    305 	acpi_drv_detach,	/* detach */
    306 	nodev,			/* reset */
    307 	&acpi_drv_cb_ops,
    308 	NULL,			/* no bus operations */
    309 	NULL,			/* power */
    310 	ddi_quiesce_not_needed,	/* quiesce */
    311 };
    312 
    313 static struct modldrv modldrv1 = {
    314 	&mod_driverops,
    315 	ACPI_DRV_MOD_STRING,
    316 	&acpi_drv_dev_ops
    317 };
    318 
    319 static struct modlinkage modlinkage = {
    320 	MODREV_1,
    321 	(void *)&modldrv1,
    322 	NULL,
    323 };
    324 
    325 int
    326 _init(void)
    327 {
    328 	int ret;
    329 
    330 	mutex_init(&acpi_drv_mutex, NULL, MUTEX_DRIVER, NULL);
    331 #ifdef DEBUG
    332 	mutex_init(&acpi_drv_prt_mutex, NULL, MUTEX_DRIVER, NULL);
    333 #endif
    334 
    335 	if ((ret = mod_install(&modlinkage)) != 0) {
    336 		mutex_destroy(&acpi_drv_mutex);
    337 #ifdef DEBUG
    338 		mutex_destroy(&acpi_drv_prt_mutex);
    339 #endif
    340 	}
    341 	return (ret);
    342 }
    343 
    344 int
    345 _fini(void)
    346 {
    347 	int ret;
    348 
    349 	if ((ret = mod_remove(&modlinkage)) == 0) {
    350 #ifdef DEBUG
    351 		mutex_destroy(&acpi_drv_prt_mutex);
    352 #endif
    353 		mutex_destroy(&acpi_drv_mutex);
    354 	}
    355 
    356 	return (ret);
    357 }
    358 
    359 int
    360 _info(struct modinfo *mp)
    361 {
    362 	return (mod_info(&modlinkage, mp));
    363 }
    364 
    365 static int
    366 acpi_drv_attach(dev_info_t *devi, ddi_attach_cmd_t cmd)
    367 {
    368 	char name[20];
    369 	int i;
    370 	struct acpi_drv_cbat_state *bp;
    371 
    372 	switch (cmd) {
    373 	case DDI_ATTACH:
    374 		/* Limit to one instance of driver */
    375 		if (acpi_drv_dip) {
    376 			return (DDI_FAILURE);
    377 		}
    378 		break;
    379 	case DDI_RESUME:
    380 	case DDI_PM_RESUME:
    381 		return (DDI_SUCCESS);
    382 	default:
    383 		return (DDI_FAILURE);
    384 	}
    385 
    386 	acpi_drv_dip = devi;
    387 
    388 	/* Init ACPI related stuff */
    389 	if (acpi_drv_acpi_init() != ACPI_DRV_OK) {
    390 		goto error;
    391 	}
    392 
    393 	/* Init kstat related stuff */
    394 	if (acpi_drv_kstat_init() != ACPI_DRV_OK) {
    395 		goto error;
    396 	}
    397 
    398 	/* Create minor node for hotkey device. */
    399 	if (ddi_create_minor_node(devi, "hotkey", S_IFCHR, MINOR_HOTKEY(0),
    400 	    DDI_PSEUDO, 0) == DDI_FAILURE) {
    401 		ACPI_DRV_DBG(CE_WARN, NULL, "hotkey: "
    402 		    "minor node create failed");
    403 		goto error;
    404 	}
    405 	/* Create minor node for lid. */
    406 	if (ddi_create_minor_node(devi, "lid", S_IFCHR, MINOR_LID(0),
    407 	    DDI_PSEUDO, 0) == DDI_FAILURE) {
    408 		ACPI_DRV_DBG(CE_WARN, NULL, "lid: minor node create failed");
    409 		goto error;
    410 	}
    411 	/* Create minor node for each battery and ac */
    412 	for (bp = &acpi_drv_cbat[0]; bp < &acpi_drv_cbat[ACPI_DRV_MAX_BAT_NUM];
    413 	    bp++) {
    414 		if (bp->dev.valid) {
    415 			(void) snprintf(name, sizeof (name), "battery%d",
    416 			    bp->dev.index);
    417 			if (ddi_create_minor_node(devi, name, S_IFCHR,
    418 			    MINOR_BATT(bp->dev.index), DDI_PSEUDO, 0) ==
    419 			    DDI_FAILURE) {
    420 				ACPI_DRV_DBG(CE_WARN, NULL,
    421 				    "%s: minor node create failed", name);
    422 				goto error;
    423 			}
    424 		}
    425 	}
    426 	for (i = 0; i < nac; i++) {
    427 		(void) snprintf(name, sizeof (name), "ac%d", i);
    428 		if (ddi_create_minor_node(devi, name, S_IFCHR,
    429 		    MINOR_AC(i), DDI_PSEUDO, 0) == DDI_FAILURE) {
    430 			ACPI_DRV_DBG(CE_WARN, NULL,
    431 			    "%s: minor node create failed", name);
    432 			goto error;
    433 		}
    434 	}
    435 
    436 	return (DDI_SUCCESS);
    437 
    438 error:
    439 	ddi_remove_minor_node(devi, NULL);
    440 	acpi_drv_kstat_fini();
    441 	acpi_drv_acpi_fini();
    442 	acpi_drv_dip = NULL;
    443 	return (DDI_FAILURE);
    444 }
    445 
    446 static int
    447 acpi_drv_detach(dev_info_t *devi, ddi_detach_cmd_t cmd)
    448 {
    449 	if (cmd != DDI_DETACH) {
    450 		return (DDI_FAILURE);
    451 	}
    452 
    453 	mutex_enter(&acpi_drv_mutex);
    454 	ddi_remove_minor_node(devi, NULL);
    455 
    456 	acpi_drv_kstat_fini();
    457 	acpi_drv_acpi_fini();
    458 	mutex_exit(&acpi_drv_mutex);
    459 	return (DDI_SUCCESS);
    460 }
    461 
    462 /* ARGSUSED */
    463 static int
    464 acpi_drv_getinfo(dev_info_t *dip, ddi_info_cmd_t cmd, void *arg, void **resultp)
    465 {
    466 	switch (cmd) {
    467 	case DDI_INFO_DEVT2DEVINFO:
    468 		*resultp = acpi_drv_dip;
    469 		return (DDI_SUCCESS);
    470 	case DDI_INFO_DEVT2INSTANCE:
    471 		*resultp = (void*) 0;
    472 		return (DDI_SUCCESS);
    473 	default:
    474 		return (DDI_FAILURE);
    475 	}
    476 }
    477 
    478 /*ARGSUSED*/
    479 static int
    480 acpi_drv_open(dev_t *devp, int flag, int otyp, cred_t *crp)
    481 {
    482 	if (acpi_drv_dip == NULL) {
    483 		return (ENXIO);
    484 	}
    485 
    486 	return (0);
    487 }
    488 
    489 /*ARGSUSED*/
    490 static int
    491 acpi_drv_close(dev_t dev, int flag, int otyp, cred_t *crp)
    492 {
    493 	return (0);
    494 }
    495 
    496 /*ARGSUSED*/
    497 static int
    498 acpi_drv_ioctl(dev_t dev, int cmd, intptr_t arg, int mode, cred_t *cr,
    499     int *rval)
    500 {
    501 	int minor;
    502 	int type, index;
    503 	int res = 0;
    504 
    505 	minor = getminor(dev);
    506 	type = MINOR2TYPE(minor);
    507 	index = MINOR2IDX(minor);
    508 
    509 	mutex_enter(&acpi_drv_mutex);
    510 
    511 	switch (type) {
    512 	case ACPI_DRV_TYPE_CBAT:
    513 		res = acpi_drv_cbat_ioctl(index, cmd, arg, mode, cr, rval);
    514 		break;
    515 	case ACPI_DRV_TYPE_AC:
    516 		res = acpi_drv_ac_ioctl(index, cmd, arg, mode, cr, rval);
    517 		break;
    518 	case ACPI_DRV_TYPE_LID:
    519 		res = acpi_drv_lid_ioctl(index, cmd, arg, mode, cr, rval);
    520 		break;
    521 	case ACPI_DRV_TYPE_HOTKEY:
    522 		res = acpi_drv_hotkey_ioctl(cmd, arg, mode, cr, rval);
    523 		break;
    524 	default:
    525 		res = EINVAL;
    526 		break;
    527 	}
    528 
    529 	mutex_exit(&acpi_drv_mutex);
    530 	return (res);
    531 }
    532 
    533 /*ARGSUSED*/
    534 static int
    535 acpi_drv_cbat_ioctl(int index, int cmd, intptr_t arg, int mode, cred_t *cr,
    536     int *rval)
    537 {
    538 	int res = 0;
    539 	acpi_drv_warn_t bwarn;
    540 	struct acpi_drv_cbat_state *bp;
    541 
    542 	ASSERT(mutex_owned(&acpi_drv_mutex));
    543 
    544 	bp = acpi_drv_idx2cbat(index);
    545 	if (!bp || bp->dev.valid != 1) {
    546 		return (ENXIO);
    547 	}
    548 
    549 	switch (cmd) {
    550 	/*
    551 	 * Return _BIF(Battery Information) of battery[index],
    552 	 * if battery plugged.
    553 	 */
    554 	case ACPI_DRV_IOC_INFO:
    555 		if (bp->dev.present == 0) {
    556 			res = ENXIO;
    557 			break;
    558 		}
    559 
    560 		res = acpi_drv_update_bif(bp);
    561 		if (res != ACPI_DRV_OK) {
    562 			break;
    563 		}
    564 		if (copyout(&bp->bif_cache, (void *)arg,
    565 		    sizeof (bp->bif_cache))) {
    566 			res = EFAULT;
    567 		}
    568 		break;
    569 
    570 	/*
    571 	 * Return _BST(Battery Status) of battery[index],
    572 	 * if battery plugged.
    573 	 */
    574 	case ACPI_DRV_IOC_STATUS:
    575 		if (bp->dev.present == 0) {
    576 			res = ENXIO;
    577 			break;
    578 		}
    579 
    580 		res = acpi_drv_update_bst(bp);
    581 		if (res != ACPI_DRV_OK) {
    582 			break;
    583 		}
    584 		if (copyout(&bp->bst_cache, (void *)arg,
    585 		    sizeof (bp->bst_cache))) {
    586 			res = EFAULT;
    587 		}
    588 		break;
    589 
    590 	/* Return the state of the battery bays in the system */
    591 	case ACPI_DRV_IOC_BAY:
    592 		{
    593 			batt_bay_t bay;
    594 
    595 			bay.bay_number = nbat;
    596 			bay.battery_map = 0;
    597 			for (bp = &acpi_drv_cbat[0];
    598 			    bp < &acpi_drv_cbat[ACPI_DRV_MAX_BAT_NUM]; bp++) {
    599 				if (bp->dev.valid) {
    600 					if (bp->dev.present) {
    601 						bay.battery_map |=
    602 						    (1 << bp->dev.index);
    603 					}
    604 				}
    605 			}
    606 			if (copyout(&bay, (void *)arg, sizeof (bay))) {
    607 				res = EFAULT;
    608 				break;
    609 			}
    610 		}
    611 		break;
    612 
    613 	/*
    614 	 * Return the current power source device if available:
    615 	 * 0 -- battery supplying power
    616 	 * 1 -- AC supplying power
    617 	 */
    618 	case ACPI_DRV_IOC_POWER_STATUS:
    619 		{
    620 			int val;
    621 
    622 			/* State not available */
    623 			if (acpi_drv_psr_type == ACPI_DRV_TYPE_UNKNOWN) {
    624 				res = ENXIO;
    625 				break;
    626 			}
    627 			val = (acpi_drv_psr_type == ACPI_DRV_TYPE_AC) ? 1 : 0;
    628 			if (copyout(&val, (void *)arg, sizeof (val))) {
    629 				res = EFAULT;
    630 				break;
    631 			}
    632 		}
    633 		break;
    634 
    635 	/* Get charge-warn and charge-low levels for the whole system */
    636 	case ACPI_DRV_IOC_GET_WARNING:
    637 		bwarn.bw_enabled = acpi_drv_warn_enabled;
    638 		bwarn.bw_charge_warn = acpi_drv_syn_warn_per;
    639 		bwarn.bw_charge_low = acpi_drv_syn_low_per;
    640 		if (copyout(&bwarn, (void *)arg, sizeof (&bwarn))) {
    641 			res = EFAULT;
    642 		}
    643 		break;
    644 
    645 	/* Set charge-warn and charge-low levels for the whole system */
    646 	case ACPI_DRV_IOC_SET_WARNING:
    647 		if (drv_priv(cr)) {
    648 			res = EPERM;
    649 			break;
    650 		}
    651 		if (copyin((void *)arg, &bwarn, sizeof (bwarn))) {
    652 			res = EFAULT;
    653 			break;
    654 		}
    655 		res = acpi_drv_set_warn(&bwarn);
    656 		break;
    657 
    658 	default:
    659 		res = EINVAL;
    660 		break;
    661 	}
    662 
    663 	return (res);
    664 }
    665 
    666 /*ARGSUSED*/
    667 static int
    668 acpi_drv_ac_ioctl(int index, int cmd, intptr_t arg, int mode, cred_t *cr,
    669     int *rval)
    670 {
    671 	int res = 0;
    672 	int ac_state;
    673 	struct acpi_drv_ac_state *acp;
    674 
    675 	ASSERT(mutex_owned(&acpi_drv_mutex));
    676 
    677 	acp = acpi_drv_idx2ac(index);
    678 	if (!acp || acp->dev.valid != 1) {
    679 		return (ENXIO);
    680 	}
    681 
    682 	switch (cmd) {
    683 	/* Return the number of AC adapters in the system */
    684 	case ACPI_DRV_IOC_AC_COUNT:
    685 		if (copyout(&nac, (void *)arg, sizeof (nac))) {
    686 			res = EFAULT;
    687 		}
    688 		break;
    689 
    690 	/*
    691 	 * Return the state of AC[index] if available:
    692 	 * 0 -- Off-line
    693 	 * 1 -- On-line
    694 	 */
    695 	case ACPI_DRV_IOC_POWER_STATUS:
    696 		if (!acp || acp->dev.valid != 1) {
    697 			res = ENXIO;
    698 			break;
    699 		}
    700 		/* State not available */
    701 		if ((ac_state = acpi_drv_ac_present(acp)) == -1) {
    702 			res = ENXIO;
    703 			break;
    704 		}
    705 		if (copyout(&ac_state, (void *)arg, sizeof (ac_state))) {
    706 			res = EFAULT;
    707 		}
    708 		break;
    709 
    710 	default:
    711 		res = EINVAL;
    712 		break;
    713 	}
    714 
    715 	return (res);
    716 }
    717 
    718 /*ARGSUSED*/
    719 static int
    720 acpi_drv_lid_ioctl(int index, int cmd, intptr_t arg, int mode, cred_t *cr,
    721     int *rval)
    722 {
    723 	int res = 0;
    724 
    725 	/*
    726 	 * lid.state 0 means lid is closed.
    727 	 * lid.state non-zero means lid is open.
    728 	 */
    729 	switch (cmd) {
    730 	case ACPI_DRV_IOC_LID_STATUS:
    731 		if (lid.state_ok == ACPI_DRV_NTF_UNKNOWN) {
    732 			/* State not available */
    733 			res = acpi_drv_update_lid(&lid.dev);
    734 			if (res != ACPI_DRV_OK) {
    735 				res = ENXIO;
    736 				break;
    737 			}
    738 		}
    739 		if (copyout(&lid.state, (void *)arg, sizeof (lid.state))) {
    740 			res = EFAULT;
    741 		}
    742 		break;
    743 	case ACPI_DRV_IOC_LID_UPDATE:
    744 		res = acpi_drv_update_lid(&lid.dev);
    745 		if (res != ACPI_DRV_OK) {
    746 			res = ENXIO;
    747 			break;
    748 		}
    749 		if (copyout(&lid.state, (void *)arg, sizeof (lid.state))) {
    750 			res = EFAULT;
    751 		}
    752 		break;
    753 
    754 	default:
    755 		res = EINVAL;
    756 		break;
    757 	}
    758 	return (res);
    759 }
    760 
    761 /*ARGSUSED*/
    762 static int
    763 acpi_drv_chpoll(dev_t dev, short events, int anyyet,  short *reventsp,
    764 	struct pollhead **phpp)
    765 {
    766 	if (!anyyet) {
    767 		*phpp = &acpi_drv_pollhead;
    768 	}
    769 	*reventsp = 0;
    770 	return (0);
    771 }
    772 
    773 #ifdef DEBUG
    774 static void
    775 acpi_drv_printf(struct acpi_drv_dev *devp, uint_t lev,
    776     const char *fmt, ...)
    777 {
    778 	va_list args;
    779 
    780 	mutex_enter(&acpi_drv_prt_mutex);
    781 
    782 	va_start(args, fmt);
    783 	(void) vsprintf(acpi_drv_prt_buf, fmt, args);
    784 	va_end(args);
    785 
    786 	if (devp) {
    787 		cmn_err(lev, "%s.%s: %s", devp->hid, devp->uid,
    788 		    acpi_drv_prt_buf);
    789 	} else {
    790 		cmn_err(lev, "%s", acpi_drv_prt_buf);
    791 	}
    792 	mutex_exit(&acpi_drv_prt_mutex);
    793 }
    794 
    795 static void
    796 acpi_drv_prt_notify(ACPI_HANDLE hdl, UINT32 val)
    797 {
    798 	ACPI_BUFFER buf;
    799 	char str[1024];
    800 
    801 	buf.Length = sizeof (str);
    802 	buf.Pointer = str;
    803 	(void) AcpiGetName(hdl, ACPI_FULL_PATHNAME, &buf);
    804 	cmn_err(CE_NOTE, "AcpiNotify(%s, 0x%02x)", str, val);
    805 }
    806 #endif /* DEBUG */
    807 
    808 void
    809 acpi_drv_gen_sysevent(struct acpi_drv_dev *devp, char *ev, uint32_t val)
    810 {
    811 	nvlist_t *attr_list = NULL;
    812 	int err;
    813 	char pathname[MAXPATHLEN];
    814 
    815 	/* Allocate and build sysevent attribute list */
    816 	err = nvlist_alloc(&attr_list, NV_UNIQUE_NAME_TYPE, DDI_NOSLEEP);
    817 	if (err != 0) {
    818 		ACPI_DRV_DBG(CE_WARN, NULL,
    819 		    "cannot allocate memory for sysevent attributes\n");
    820 		return;
    821 	}
    822 
    823 	/* Add attributes */
    824 	err = nvlist_add_string(attr_list, PWRCTL_DEV_HID, devp->hid);
    825 	if (err != 0) {
    826 		ACPI_DRV_DBG(CE_WARN, NULL,
    827 		    "Failed to add attr [%s] for %s/%s event",
    828 		    PWRCTL_DEV_HID, EC_PWRCTL, ev);
    829 		nvlist_free(attr_list);
    830 		return;
    831 	}
    832 
    833 	err = nvlist_add_string(attr_list, PWRCTL_DEV_UID, devp->uid);
    834 	if (err != 0) {
    835 		ACPI_DRV_DBG(CE_WARN, NULL,
    836 		    "Failed to add attr [%s] for %s/%s event",
    837 		    PWRCTL_DEV_UID, EC_PWRCTL, ev);
    838 		nvlist_free(attr_list);
    839 		return;
    840 	}
    841 
    842 	err = nvlist_add_uint32(attr_list, PWRCTL_DEV_INDEX, devp->index);
    843 	if (err != 0) {
    844 		ACPI_DRV_DBG(CE_WARN, NULL,
    845 		    "Failed to add attr [%s] for %s/%s event",
    846 		    PWRCTL_DEV_INDEX, EC_PWRCTL, ev);
    847 		nvlist_free(attr_list);
    848 		return;
    849 	}
    850 
    851 	(void) ddi_pathname(acpi_drv_dip, pathname);
    852 	err = nvlist_add_string(attr_list, PWRCTL_DEV_PHYS_PATH, pathname);
    853 	if (err != 0) {
    854 		ACPI_DRV_DBG(CE_WARN, NULL,
    855 		    "Failed to add attr [%s] for %s/%s event",
    856 		    PWRCTL_DEV_PHYS_PATH, EC_PWRCTL, ev);
    857 		nvlist_free(attr_list);
    858 		return;
    859 	}
    860 
    861 	if (strcmp(ev, ESC_PWRCTL_WARN) && strcmp(ev, ESC_PWRCTL_LOW)) {
    862 		goto finish;
    863 	}
    864 
    865 	err = nvlist_add_uint32(attr_list, PWRCTL_CHARGE_LEVEL, val);
    866 	if (err != 0) {
    867 		ACPI_DRV_DBG(CE_WARN, NULL,
    868 		    "Failed to add attr [%s] for %s/%s event",
    869 		    PWRCTL_CHARGE_LEVEL, EC_PWRCTL, ev);
    870 		nvlist_free(attr_list);
    871 		return;
    872 	}
    873 
    874 finish:
    875 	ACPI_DRV_DBG(CE_NOTE, NULL, "SysEv(%s, %s.%s, %d)",
    876 	    ev, devp->hid, devp->uid, val);
    877 	/* Generate/log sysevent */
    878 	err = ddi_log_sysevent(acpi_drv_dip, DDI_VENDOR_SUNW, EC_PWRCTL,
    879 	    ev, attr_list, NULL, DDI_NOSLEEP);
    880 #ifdef DEBUG
    881 	if (err != DDI_SUCCESS) {
    882 		ACPI_DRV_DBG(CE_WARN, NULL,
    883 		    "cannot log sysevent, err code %x\n", err);
    884 	}
    885 #endif
    886 
    887 	nvlist_free(attr_list);
    888 }
    889 
    890 static int
    891 acpi_drv_obj_copy(ACPI_OBJECT *op, char *bp, struct obj_desc *dp)
    892 {
    893 	ACPI_OBJECT *ep;
    894 	char *fp;
    895 
    896 	ep = &op->Package.Elements[0];
    897 	for (; dp->offset != -1; dp++) {
    898 		fp = bp + dp->offset;
    899 		if (dp->type == ACPI_TYPE_INTEGER &&
    900 		    ep->Type == dp->type) {
    901 #ifdef DEBUG
    902 			if (dp->size <= 4) {
    903 				ACPI_DRV_DBG(CE_NOTE, NULL, "\t%s: %u",
    904 				    dp->name,
    905 				    (uint32_t)ep->Integer.Value);
    906 			} else {
    907 #ifdef _LP64
    908 				ACPI_DRV_DBG(CE_NOTE, NULL, "\t%s: %lu",
    909 				    dp->name, (uint64_t)ep->Integer.Value);
    910 			}
    911 #else
    912 				ACPI_DRV_DBG(CE_NOTE, NULL, "\t%s: %llu",
    913 				    dp->name, (uint64_t)ep->Integer.Value);
    914 			}
    915 #endif /* _LP64 */
    916 #endif /* DEBUG */
    917 			*(uint32_t *)fp = ep->Integer.Value;
    918 		} else if (dp->type == ACPI_TYPE_STRING &&
    919 		    ep->Type == dp->type) {
    920 			ACPI_DRV_DBG(CE_NOTE, NULL, "\t%s: \"%s\"",
    921 			    dp->name, ep->String.Pointer);
    922 			(void) 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_NOTIFY_HANDLER ntf_handler = NULL;
   1545 	ACPI_STATUS ret;
   1546 
   1547 	ASSERT(p != NULL && p->hdl != NULL);
   1548 
   1549 	p->valid = 0;
   1550 
   1551 	/* Info size is variable depending on existance of _CID */
   1552 	ret = AcpiGetObjectInfo(p->hdl, &info);
   1553 	if (ACPI_FAILURE(ret)) {
   1554 		ACPI_DRV_DBG(CE_WARN, NULL,
   1555 		    "AcpiGetObjectInfo() fail: %d", (int32_t)ret);
   1556 		return (ACPI_DRV_ERR);
   1557 	}
   1558 
   1559 	if ((info->Valid & ACPI_VALID_HID) == 0) {
   1560 		ACPI_DRV_DBG(CE_WARN, NULL,
   1561 		    "AcpiGetObjectInfo(): _HID not available");
   1562 		(void) strncpy(p->hid, "\0", ID_LEN);
   1563 	} else {
   1564 		(void) strncpy(p->hid, info->HardwareId.String, ID_LEN);
   1565 	}
   1566 
   1567 	/*
   1568 	 * This object is optional, but is required when the device
   1569 	 * has no other way to report a persistent unique device ID.
   1570 	 */
   1571 	if ((info->Valid & ACPI_VALID_UID) == 0) {
   1572 		ACPI_DRV_DBG(CE_WARN, NULL,
   1573 		    "AcpiGetObjectInfo(): _UID not available");
   1574 		/* Use 0 as the default _UID */
   1575 		(void) strncpy(p->uid, "\0", ID_LEN);
   1576 	} else {
   1577 		(void) strncpy(p->uid, info->UniqueId.String, ID_LEN);
   1578 	}
   1579 
   1580 	AcpiOsFree(info);
   1581 	p->valid = 1;
   1582 
   1583 	if (strcmp(p->hid, ACPI_DEVNAME_CBAT) == 0) {
   1584 		struct acpi_drv_cbat_state *bp =
   1585 		    (struct acpi_drv_cbat_state *)p;
   1586 
   1587 		p->type = ACPI_DRV_TYPE_CBAT;
   1588 		p->index = nbat - 1;
   1589 
   1590 		/* Update device present state */
   1591 		(void) acpi_drv_update_present(p);
   1592 		if (p->present) {
   1593 			(void) acpi_drv_update_bif(bp);
   1594 			(void) acpi_drv_update_bst(bp);
   1595 
   1596 			/* Init the current power source */
   1597 			if (bp->bst_cache.bst_state & BST_FLAG_DISCHARGING) {
   1598 				acpi_drv_set_psr(p);
   1599 			}
   1600 		}
   1601 		ntf_handler = acpi_drv_cbat_notify;
   1602 		ACPI_DRV_DBG(CE_NOTE, p, "battery %s",
   1603 		    (p->present ? "present" : "absent"));
   1604 	} else if (strcmp(p->hid, ACPI_DEVNAME_AC) == 0) {
   1605 		p->type = ACPI_DRV_TYPE_AC;
   1606 		p->index = nac - 1;
   1607 
   1608 		/* Update device present state */
   1609 		(void) acpi_drv_update_present(p);
   1610 		if (p->present) {
   1611 			/* Init the current power source */
   1612 			acpi_drv_set_psr(p);
   1613 		}
   1614 		ntf_handler = acpi_drv_ac_notify;
   1615 		ACPI_DRV_DBG(CE_NOTE, p, "AC %s",
   1616 		    (p->present ? "on-line" : "off-line"));
   1617 	} else if (strcmp(p->hid, ACPI_DEVNAME_LID) == 0) {
   1618 		p->type = ACPI_DRV_TYPE_LID;
   1619 		p->index = 0;
   1620 		lid.state_ok = ACPI_DRV_NTF_UNKNOWN;
   1621 		(void) acpi_drv_update_lid(p);
   1622 		ntf_handler = acpi_drv_lid_notify;
   1623 		ACPI_DRV_DBG(CE_NOTE, p, "added");
   1624 	} else {
   1625 		ACPI_DRV_DBG(CE_NOTE, p, "unknown device");
   1626 		p->valid = 0;
   1627 	}
   1628 
   1629 	/* Register ACPI battery related events */
   1630 	if (ntf_handler != NULL) {
   1631 		if (ACPI_FAILURE(AcpiInstallNotifyHandler(p->hdl,
   1632 		    ACPI_ALL_NOTIFY, ntf_handler, p))) {
   1633 			ACPI_DRV_DBG(CE_NOTE, NULL,
   1634 			    "Notify handler for %s.%s install failed",
   1635 			    p->hid, p->uid);
   1636 			return (ACPI_DRV_ERR);
   1637 		}
   1638 	}
   1639 
   1640 	return (ACPI_DRV_OK);
   1641 }
   1642 
   1643 /*ARGSUSED*/
   1644 static ACPI_STATUS
   1645 acpi_drv_find_cb(ACPI_HANDLE ObjHandle, UINT32 NestingLevel, void *Context,
   1646     void **ReturnValue)
   1647 {
   1648 	struct acpi_drv_dev *devp;
   1649 	int *type = (int *)Context;
   1650 
   1651 	if (*type == ACPI_DRV_TYPE_CBAT) {
   1652 		struct acpi_drv_cbat_state *bp;
   1653 
   1654 		if (nbat == ACPI_DRV_MAX_BAT_NUM) {
   1655 			ACPI_DRV_DBG(CE_WARN, NULL,
   1656 			    "Need to support more batteries: "
   1657 			    "BATTERY_MAX = %d", ACPI_DRV_MAX_BAT_NUM);
   1658 			return (AE_LIMIT);
   1659 		}
   1660 		bp = &acpi_drv_cbat[nbat++];
   1661 		devp = (struct acpi_drv_dev *)bp;
   1662 	} else if (*type == ACPI_DRV_TYPE_AC) {
   1663 		struct acpi_drv_ac_state *ap;
   1664 
   1665 		if (nac == ACPI_DRV_MAX_AC_NUM) {
   1666 			ACPI_DRV_DBG(CE_WARN, NULL, "Need to support more ACs: "
   1667 			    "AC_MAX = %d", ACPI_DRV_MAX_AC_NUM);
   1668 			return (AE_LIMIT);
   1669 		}
   1670 		ap = &acpi_drv_ac[nac++];
   1671 		devp = (struct acpi_drv_dev *)ap;
   1672 	} else if (*type == ACPI_DRV_TYPE_LID) {
   1673 		struct acpi_drv_lid_state *lp;
   1674 
   1675 		nlid++;
   1676 		lp = &lid;
   1677 		devp = (struct acpi_drv_dev *)lp;
   1678 	} else {
   1679 		ACPI_DRV_DBG(CE_WARN, NULL, "acpi_drv_find_cb(): "
   1680 		    "Unknown device");
   1681 		return (AE_ERROR);
   1682 	}
   1683 
   1684 	devp->hdl = ObjHandle;
   1685 
   1686 	/* Try to get as many working objs as possible */
   1687 	(void) acpi_drv_obj_init(devp);
   1688 	return (AE_OK);
   1689 }
   1690 
   1691 static int
   1692 acpi_drv_acpi_init()
   1693 {
   1694 	int *retp, type;
   1695 	int status = ACPI_DRV_ERR;
   1696 	hotkey_drv_t *htkp;
   1697 
   1698 	/* Check to see if ACPI CA services are available */
   1699 	if (AcpiSubsystemStatus() != AE_OK) {
   1700 		ACPI_DRV_DBG(CE_WARN, NULL, "ACPI CA not ready");
   1701 		return (status);
   1702 	}
   1703 
   1704 	/* Init Control Method Batterys */
   1705 	type = ACPI_DRV_TYPE_CBAT;
   1706 	if (ACPI_SUCCESS(AcpiGetDevices(ACPI_DEVNAME_CBAT, acpi_drv_find_cb,
   1707 	    &type, (void *)&retp)) && nbat) {
   1708 		status = ACPI_DRV_OK;
   1709 	}
   1710 
   1711 	/* Init AC */
   1712 	type = ACPI_DRV_TYPE_AC;
   1713 	if (ACPI_SUCCESS(AcpiGetDevices(ACPI_DEVNAME_AC, acpi_drv_find_cb,
   1714 	    &type, (void *)&retp)) && nac) {
   1715 		status = ACPI_DRV_OK;
   1716 	}
   1717 
   1718 	/* Init LID */
   1719 	type = ACPI_DRV_TYPE_LID;
   1720 	if (ACPI_SUCCESS(AcpiGetDevices(ACPI_DEVNAME_LID, acpi_drv_find_cb,
   1721 	    &type, (void *)&retp)) && nlid) {
   1722 		status = ACPI_DRV_OK;
   1723 	}
   1724 
   1725 	/* Init Hotkey Device */
   1726 	type = ACPI_DRV_TYPE_HOTKEY;
   1727 	htkp = &acpi_hotkey;
   1728 	bzero(htkp, sizeof (hotkey_drv_t));
   1729 	htkp->dip = acpi_drv_dip;
   1730 	htkp->hotkey_lock = &acpi_drv_mutex;
   1731 	if (hotkey_init(htkp) == ACPI_DRV_OK) {
   1732 		status = ACPI_DRV_OK;
   1733 	}
   1734 
   1735 	acpi_drv_update_cap(1);
   1736 
   1737 	return (status);
   1738 }
   1739 
   1740 static void
   1741 acpi_drv_acpi_fini(void)
   1742 {
   1743 	int i;
   1744 	struct acpi_drv_cbat_state *bp;
   1745 
   1746 	for (bp = &acpi_drv_cbat[0]; bp < &acpi_drv_cbat[ACPI_DRV_MAX_BAT_NUM];
   1747 	    bp++) {
   1748 		if (bp->dev.valid) {
   1749 			(void) AcpiRemoveNotifyHandler(bp->dev.hdl,
   1750 			    ACPI_DEVICE_NOTIFY, acpi_drv_cbat_notify);
   1751 		}
   1752 	}
   1753 	for (i = 0; i < nac; i++) {
   1754 		(void) AcpiRemoveNotifyHandler(acpi_drv_ac[i].dev.hdl,
   1755 		    ACPI_DEVICE_NOTIFY, acpi_drv_ac_notify);
   1756 	}
   1757 	(void) AcpiRemoveNotifyHandler(lid.dev.hdl, ACPI_DEVICE_NOTIFY,
   1758 	    acpi_drv_lid_notify);
   1759 
   1760 	if (acpi_hotkey.hotkey_method != HOTKEY_METHOD_NONE)
   1761 		(void) hotkey_fini(&acpi_hotkey);
   1762 }
   1763 
   1764 /*ARGSUSED*/
   1765 static int
   1766 acpi_drv_kstat_power_update(kstat_t *ksp, int flag)
   1767 {
   1768 	if (flag == KSTAT_WRITE) {
   1769 		return (EACCES);
   1770 	}
   1771 
   1772 	mutex_enter(&acpi_drv_mutex);
   1773 	if (acpi_drv_psr_type == ACPI_DRV_TYPE_UNKNOWN) {
   1774 		mutex_exit(&acpi_drv_mutex);
   1775 		return (EIO);
   1776 	}
   1777 	kstat_named_setstr(&acpi_drv_power_kstat.acpi_drv_power,
   1778 	    acpi_drv_psr_type == ACPI_DRV_TYPE_AC ? AC : BATTERY);
   1779 	acpi_drv_power_kstat.acpi_drv_supported_battery_count.value.ui32 =
   1780 	    (uint32_t)nbat;
   1781 	mutex_exit(&acpi_drv_mutex);
   1782 
   1783 	return (0);
   1784 }
   1785 
   1786 /*ARGSUSED*/
   1787 static int
   1788 acpi_drv_kstat_warn_update(kstat_t *ksp, int flag)
   1789 {
   1790 	if (flag == KSTAT_WRITE) {
   1791 		int ret = 0;
   1792 		acpi_drv_warn_t bw;
   1793 		acpi_drv_warn_kstat_t kbw;
   1794 
   1795 		kbw = *(acpi_drv_warn_kstat_t *)acpi_drv_warn_ksp->ks_data;
   1796 
   1797 		mutex_enter(&acpi_drv_mutex);
   1798 		bw.bw_enabled  = kbw.acpi_drv_bw_enabled.value.ui32;
   1799 		bw.bw_charge_warn = kbw.acpi_drv_bw_charge_warn.value.ui32;
   1800 		bw.bw_charge_low = kbw.acpi_drv_bw_charge_low.value.ui32;
   1801 		ret = acpi_drv_set_warn(&bw);
   1802 		mutex_exit(&acpi_drv_mutex);
   1803 
   1804 		return (ret);
   1805 	} else {
   1806 		acpi_drv_warn_kstat_t *wp = &acpi_drv_warn_kstat;
   1807 
   1808 		mutex_enter(&acpi_drv_mutex);
   1809 		wp->acpi_drv_bw_enabled.value.ui32 = acpi_drv_warn_enabled;
   1810 		wp->acpi_drv_bw_charge_warn.value.ui32 = acpi_drv_syn_warn_per;
   1811 		wp->acpi_drv_bw_charge_low.value.ui32 = acpi_drv_syn_low_per;
   1812 		mutex_exit(&acpi_drv_mutex);
   1813 
   1814 		return (0);
   1815 	}
   1816 }
   1817 
   1818 static int
   1819 acpi_drv_kstat_bif_update(kstat_t *ksp, int flag)
   1820 {
   1821 	struct acpi_drv_cbat_state *bp;
   1822 	acpi_bif_t *bif;
   1823 	acpi_drv_bif_kstat_t *kp;
   1824 
   1825 	if (flag == KSTAT_WRITE) {
   1826 		return (EACCES);
   1827 	}
   1828 
   1829 	bp = (struct acpi_drv_cbat_state *)ksp->ks_private;
   1830 	mutex_enter(&acpi_drv_mutex);
   1831 
   1832 	if (acpi_drv_cbat_present(bp) <= 0) {
   1833 		mutex_exit(&acpi_drv_mutex);
   1834 		return (ENXIO);
   1835 	}
   1836 
   1837 	bzero(&bif, sizeof (bif));
   1838 	if (acpi_drv_update_bif(bp) != ACPI_DRV_OK) {
   1839 		mutex_exit(&acpi_drv_mutex);
   1840 		return (ENXIO);
   1841 	}
   1842 
   1843 	bif = &bp->bif_cache;
   1844 	kp = &acpi_drv_bif_kstat;
   1845 
   1846 	/* Update BIF */
   1847 	kp->acpi_drv_bif_unit.value.ui32 = bif->bif_unit;
   1848 	kp->acpi_drv_bif_design_cap.value.ui32 = bif->bif_design_cap;
   1849 	kp->acpi_drv_bif_last_cap.value.ui32 = bif->bif_last_cap;
   1850 	kp->acpi_drv_bif_tech.value.ui32 = bif->bif_tech;
   1851 	kp->acpi_drv_bif_voltage.value.ui32 = bif->bif_voltage;
   1852 	kp->acpi_drv_bif_warn_cap.value.ui32 = bif->bif_warn_cap;
   1853 	kp->acpi_drv_bif_low_cap.value.ui32 = bif->bif_low_cap;
   1854 	kp->acpi_drv_bif_gran1_cap.value.ui32 = bif->bif_gran1_cap;
   1855 	kp->acpi_drv_bif_gran2_cap.value.ui32 = bif->bif_gran2_cap;
   1856 
   1857 	kstat_named_setstr(&kp->acpi_drv_bif_model, bif->bif_model);
   1858 	kstat_named_setstr(&kp->acpi_drv_bif_serial, bif->bif_serial);
   1859 	kstat_named_setstr(&kp->acpi_drv_bif_type, bif->bif_type);
   1860 	kstat_named_setstr(&kp->acpi_drv_bif_oem_info, bif->bif_oem_info);
   1861 
   1862 	mutex_exit(&acpi_drv_mutex);
   1863 	return (0);
   1864 }
   1865 
   1866 static int
   1867 acpi_drv_kstat_bst_update(kstat_t *ksp, int flag)
   1868 {
   1869 	struct acpi_drv_cbat_state *bp;
   1870 	acpi_bst_t *bst;
   1871 	acpi_drv_bst_kstat_t *kp;
   1872 
   1873 	if (flag == KSTAT_WRITE) {
   1874 		return (EACCES);
   1875 	}
   1876 
   1877 	bp = (struct acpi_drv_cbat_state *)ksp->ks_private;
   1878 	mutex_enter(&acpi_drv_mutex);
   1879 
   1880 	if (acpi_drv_cbat_present(bp) <= 0) {
   1881 		mutex_exit(&acpi_drv_mutex);
   1882 		return (ENXIO);
   1883 	}
   1884 
   1885 	bzero(&bst, sizeof (bst));
   1886 	if (acpi_drv_update_bst(bp) != ACPI_DRV_OK) {
   1887 		mutex_exit(&acpi_drv_mutex);
   1888 		return (ENXIO);
   1889 	}
   1890 
   1891 	bst = &bp->bst_cache;
   1892 	kp = &acpi_drv_bst_kstat;
   1893 
   1894 	/* Update BST */
   1895 	kp->acpi_drv_bst_state.value.ui32 = bst->bst_state;
   1896 	kp->acpi_drv_bst_rate.value.ui32 = bst->bst_rate;
   1897 	kp->acpi_drv_bst_rem_cap.value.ui32 = bst->bst_rem_cap;
   1898 	kp->acpi_drv_bst_voltage.value.ui32 = bst->bst_voltage;
   1899 
   1900 	mutex_exit(&acpi_drv_mutex);
   1901 	return (0);
   1902 }
   1903 
   1904 static int
   1905 acpi_drv_kstat_init(void)
   1906 {
   1907 	char name[KSTAT_STRLEN];
   1908 	struct acpi_drv_cbat_state *bp;
   1909 
   1910 	/*
   1911 	 * Allocate, initialize and install powerstatus and
   1912 	 * supported_battery_count kstat.
   1913 	 */
   1914 	acpi_drv_power_ksp = kstat_create(ACPI_DRV_NAME, 0,
   1915 	    ACPI_DRV_POWER_KSTAT_NAME, "misc",
   1916 	    KSTAT_TYPE_NAMED,
   1917 	    sizeof (acpi_drv_power_kstat) / sizeof (kstat_named_t),
   1918 	    KSTAT_FLAG_VIRTUAL);
   1919 	if (acpi_drv_power_ksp == NULL) {
   1920 		ACPI_DRV_DBG(CE_WARN, NULL,
   1921 		    "kstat_create(%s) fail", ACPI_DRV_POWER_KSTAT_NAME);
   1922 		return (ACPI_DRV_ERR);
   1923 	}
   1924 
   1925 	acpi_drv_power_ksp->ks_data = &acpi_drv_power_kstat;
   1926 	acpi_drv_power_ksp->ks_update = acpi_drv_kstat_power_update;
   1927 	acpi_drv_power_ksp->ks_data_size += MAXNAMELEN;
   1928 	kstat_install(acpi_drv_power_ksp);
   1929 
   1930 	/*
   1931 	 * Allocate, initialize and install battery_capacity_warning kstat.
   1932 	 */
   1933 	acpi_drv_warn_ksp = kstat_create(ACPI_DRV_NAME, 0,
   1934 	    ACPI_DRV_BTWARN_KSTAT_NAME, "misc",
   1935 	    KSTAT_TYPE_NAMED,
   1936 	    sizeof (acpi_drv_warn_kstat) / sizeof (kstat_named_t),
   1937 	    KSTAT_FLAG_VIRTUAL | KSTAT_FLAG_WRITABLE);
   1938 	if (acpi_drv_warn_ksp == NULL) {
   1939 		ACPI_DRV_DBG(CE_WARN, NULL,
   1940 		    "kstat_create(%s) fail", ACPI_DRV_BTWARN_KSTAT_NAME);
   1941 		return (ACPI_DRV_ERR);
   1942 	}
   1943 
   1944 	acpi_drv_warn_ksp->ks_data = &acpi_drv_warn_kstat;
   1945 	acpi_drv_warn_ksp->ks_update = acpi_drv_kstat_warn_update;
   1946 	kstat_install(acpi_drv_warn_ksp);
   1947 
   1948 	/*
   1949 	 * Allocate, initialize and install BIF and BST kstat
   1950 	 * for each battery.
   1951 	 */
   1952 	for (bp = &acpi_drv_cbat[0]; bp < &acpi_drv_cbat[ACPI_DRV_MAX_BAT_NUM];
   1953 	    bp++) {
   1954 		if (bp->dev.valid) {
   1955 			kstat_t *ksp;
   1956 
   1957 			/* BIF kstat */
   1958 			(void) snprintf(name, KSTAT_STRLEN-1, "%s%d",
   1959 			    ACPI_DRV_BIF_KSTAT_NAME, bp->dev.index);
   1960 			ksp = kstat_create(ACPI_DRV_NAME, 0,
   1961 			    name, "misc", KSTAT_TYPE_NAMED,
   1962 			    sizeof (acpi_drv_bif_kstat) /
   1963 			    sizeof (kstat_named_t), KSTAT_FLAG_VIRTUAL);
   1964 			if (ksp == NULL) {
   1965 				ACPI_DRV_DBG(CE_WARN, NULL,
   1966 				    "kstat_create(%s) fail", name);
   1967 				return (ACPI_DRV_ERR);
   1968 			}
   1969 			ACPI_DRV_DBG(CE_NOTE, NULL, "kstat_create(%s) ok",
   1970 			    name);
   1971 
   1972 			bp->bat_bif_ksp = ksp;
   1973 			ksp->ks_data = &acpi_drv_bif_kstat;
   1974 			ksp->ks_update = acpi_drv_kstat_bif_update;
   1975 			ksp->ks_data_size += MAXNAMELEN * 4;
   1976 			ksp->ks_private = bp;
   1977 
   1978 			kstat_install(ksp);
   1979 
   1980 			/* BST kstat */
   1981 			(void) snprintf(name, KSTAT_STRLEN-1, "%s%d",
   1982 			    ACPI_DRV_BST_KSTAT_NAME, bp->dev.index);
   1983 			ksp = kstat_create(ACPI_DRV_NAME, 0, name, "misc",
   1984 			    KSTAT_TYPE_NAMED,
   1985 			    sizeof (acpi_drv_bst_kstat) /
   1986 			    sizeof (kstat_named_t),
   1987 			    KSTAT_FLAG_VIRTUAL);
   1988 			if (ksp == NULL) {
   1989 				ACPI_DRV_DBG(CE_WARN, NULL,
   1990 				    "kstat_create(%s) fail", name);
   1991 				return (ACPI_DRV_ERR);
   1992 			}
   1993 			ACPI_DRV_DBG(CE_NOTE, NULL, "kstat_create(%s) ok",
   1994 			    name);
   1995 
   1996 			bp->bat_bst_ksp = ksp;
   1997 			ksp->ks_data = &acpi_drv_bst_kstat;
   1998 			ksp->ks_update = acpi_drv_kstat_bst_update;
   1999 			ksp->ks_data_size += MAXNAMELEN * 4;
   2000 			ksp->ks_private = bp;
   2001 
   2002 			kstat_install(ksp);
   2003 		}
   2004 	}
   2005 
   2006 	return (ACPI_DRV_OK);
   2007 }
   2008 
   2009 static void
   2010 acpi_drv_kstat_fini()
   2011 {
   2012 	struct acpi_drv_cbat_state *bp;
   2013 
   2014 	if (acpi_drv_power_ksp != NULL) {
   2015 		kstat_delete(acpi_drv_power_ksp);
   2016 	}
   2017 	if (acpi_drv_warn_ksp != NULL) {
   2018 		kstat_delete(acpi_drv_warn_ksp);
   2019 	}
   2020 	for (bp = &acpi_drv_cbat[0]; bp < &acpi_drv_cbat[ACPI_DRV_MAX_BAT_NUM];
   2021 	    bp++) {
   2022 		if (bp->dev.valid) {
   2023 			if (bp->bat_bif_ksp != NULL) {
   2024 				kstat_delete(bp->bat_bif_ksp);
   2025 			}
   2026 			if (bp->bat_bst_ksp != NULL) {
   2027 				kstat_delete(bp->bat_bst_ksp);
   2028 			}
   2029 		}
   2030 	}
   2031 }
   2032 
   2033 int
   2034 acpi_drv_set_int(ACPI_HANDLE dev, char *method, uint32_t aint)
   2035 {
   2036 	ACPI_OBJECT_LIST al;
   2037 	ACPI_OBJECT ao;
   2038 
   2039 	al.Pointer = &ao;
   2040 	al.Count = 1;
   2041 	ao.Type = ACPI_TYPE_INTEGER;
   2042 	ao.Integer.Value = aint;
   2043 	return (AcpiEvaluateObject(dev, method, &al, NULL));
   2044 }
   2045 
   2046 int
   2047 acpi_drv_dev_init(struct acpi_drv_dev *p)
   2048 {
   2049 	ACPI_DEVICE_INFO *info;
   2050 	ACPI_STATUS ret;
   2051 
   2052 	ASSERT(p != NULL && p->hdl != NULL);
   2053 
   2054 	p->valid = 0;
   2055 
   2056 	/* Info size is variable depending on existance of _CID */
   2057 	ret = AcpiGetObjectInfo(p->hdl, &info);
   2058 	if (ACPI_FAILURE(ret)) {
   2059 		ACPI_DRV_DBG(CE_WARN, NULL,
   2060 		    "AcpiGetObjectInfo() fail: %d", (int32_t)ret);
   2061 		return (ACPI_DRV_ERR);
   2062 	}
   2063 
   2064 	if ((info->Valid & ACPI_VALID_HID) == 0) {
   2065 		ACPI_DRV_DBG(CE_WARN, NULL,
   2066 		    "!AcpiGetObjectInfo(): _HID not available");
   2067 		(void) strncpy(p->hid, "\0", ID_LEN);
   2068 	} else {
   2069 		(void) strncpy(p->hid, info->HardwareId.String, ID_LEN);
   2070 	}
   2071 
   2072 	/*
   2073 	 * This object is optional, but is required when the device
   2074 	 * has no other way to report a persistent unique device ID.
   2075 	 */
   2076 	if ((info->Valid & ACPI_VALID_UID) == 0) {
   2077 		ACPI_DRV_DBG(CE_WARN, NULL,
   2078 		    "!AcpiGetObjectInfo(): _UID not available");
   2079 		/* Use 0 as the default _UID */
   2080 		(void) strncpy(p->uid, "\0", ID_LEN);
   2081 	} else {
   2082 		(void) strncpy(p->uid, info->UniqueId.String, ID_LEN);
   2083 	}
   2084 
   2085 	if (info->Valid & ACPI_VALID_ADR) {
   2086 		p->valid = 1;
   2087 		p->type = ACPI_DRV_TYPE_HOTKEY;
   2088 	}
   2089 
   2090 	AcpiOsFree(info);
   2091 
   2092 	return (ACPI_DRV_OK);
   2093 }
   2094