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