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