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