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