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