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