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