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