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