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