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