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