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 }; 326 static struct acpi_drv_output_state *outputs = NULL; 327 static int noutput = 0; 328 329 struct acpi_drv_display_state { 330 struct acpi_drv_dev dev; 331 int mode; 332 int noutput; 333 } display; 334 335 static int acpi_drv_attach(dev_info_t *devi, ddi_attach_cmd_t cmd); 336 static int acpi_drv_detach(dev_info_t *devi, ddi_detach_cmd_t cmd); 337 static int acpi_drv_getinfo(dev_info_t *dip, ddi_info_cmd_t cmd, void *arg, 338 void **resultp); 339 static int acpi_drv_open(dev_t *devp, int flag, int otyp, cred_t *crp); 340 static int acpi_drv_close(dev_t dev, int flag, int otyp, cred_t *crp); 341 static int acpi_drv_ioctl(dev_t dev, int cmd, intptr_t arg, int mode, 342 cred_t *cr, int *rval); 343 static int acpi_drv_chpoll(dev_t dev, short events, int anyyet, 344 short *reventsp, struct pollhead **phpp); 345 static int acpi_drv_ac_ioctl(int index, int cmd, intptr_t arg, int mode, 346 cred_t *cr, int *rval); 347 static int acpi_drv_cbat_ioctl(int index, int cmd, intptr_t arg, int mode, 348 cred_t *cr, int *rval); 349 static int acpi_drv_lid_ioctl(int index, int cmd, intptr_t arg, int mode, 350 cred_t *cr, int *rval); 351 static int acpi_drv_output_ioctl(int index, int cmd, intptr_t arg, int mode, 352 cred_t *cr, int *rval); 353 #ifdef DEBUG 354 static void acpi_drv_printf(struct acpi_drv_dev *devp, uint_t lev, 355 const char *fmt, ...); 356 #endif 357 358 /* 359 * Output device functions 360 */ 361 static int acpi_drv_output_init(ACPI_HANDLE hdl, struct acpi_drv_dev *dev); 362 static void acpi_drv_output_notify(ACPI_HANDLE hdl, UINT32 val, void *ctx); 363 static int acpi_drv_output_get_state(struct acpi_drv_output_state *op); 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, *tail; 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 = tail = op; 1870 } else { 1871 tail->next = op; 1872 tail = op; 1873 } 1874 noutput++; 1875 devp = (struct acpi_drv_dev *)op; 1876 devp->op = op; 1877 devp->hdl = ohl; 1878 (void) acpi_drv_obj_init(devp); 1879 } 1880 dp->noutput = noutput; 1881 } 1882 return (AE_OK); 1883 } else { 1884 ACPI_DRV_DBG(CE_WARN, NULL, "acpi_drv_find_cb(): " 1885 "Unknown device"); 1886 return (AE_ERROR); 1887 } 1888 1889 devp->hdl = ObjHandle; 1890 1891 /* Try to get as many working objs as possible */ 1892 (void) acpi_drv_obj_init(devp); 1893 return (AE_OK); 1894 } 1895 1896 static int 1897 acpi_drv_acpi_init() 1898 { 1899 int *retp, type; 1900 int status = ACPI_DRV_ERR; 1901 1902 /* Check to see if ACPI CA services are available */ 1903 if (AcpiSubsystemStatus() != AE_OK) { 1904 ACPI_DRV_DBG(CE_WARN, NULL, "ACPI CA not ready"); 1905 return (status); 1906 } 1907 1908 /* Init Control Method Batterys */ 1909 type = ACPI_DRV_TYPE_CBAT; 1910 if (ACPI_SUCCESS(AcpiGetDevices(ACPI_DEVNAME_CBAT, acpi_drv_find_cb, 1911 &type, (void *)&retp)) && nbat) { 1912 status = ACPI_DRV_OK; 1913 } 1914 1915 /* Init AC */ 1916 type = ACPI_DRV_TYPE_AC; 1917 if (ACPI_SUCCESS(AcpiGetDevices(ACPI_DEVNAME_AC, acpi_drv_find_cb, 1918 &type, (void *)&retp)) && nac) { 1919 status = ACPI_DRV_OK; 1920 } 1921 1922 /* Init LID */ 1923 type = ACPI_DRV_TYPE_LID; 1924 if (ACPI_SUCCESS(AcpiGetDevices(ACPI_DEVNAME_LID, acpi_drv_find_cb, 1925 &type, (void *)&retp)) && nlid) { 1926 status = ACPI_DRV_OK; 1927 } 1928 1929 /* Init Output Devices */ 1930 type = ACPI_DRV_TYPE_OUTPUT; 1931 if (ACPI_SUCCESS(AcpiGetDevices(NULL, acpi_drv_find_cb, 1932 &type, (void *)&retp)) && noutput) { 1933 status = ACPI_DRV_OK; 1934 } 1935 1936 acpi_drv_update_cap(1); 1937 1938 return (status); 1939 } 1940 1941 static void 1942 acpi_drv_acpi_fini(void) 1943 { 1944 int i; 1945 struct acpi_drv_cbat_state *bp; 1946 struct acpi_drv_output_state *op; 1947 1948 for (bp = &acpi_drv_cbat[0]; bp < &acpi_drv_cbat[ACPI_DRV_MAX_BAT_NUM]; 1949 bp++) { 1950 if (bp->dev.valid) { 1951 AcpiRemoveNotifyHandler(bp->dev.hdl, ACPI_DEVICE_NOTIFY, 1952 acpi_drv_cbat_notify); 1953 } 1954 } 1955 for (i = 0; i < nac; i++) { 1956 AcpiRemoveNotifyHandler(acpi_drv_ac[i].dev.hdl, 1957 ACPI_DEVICE_NOTIFY, acpi_drv_ac_notify); 1958 } 1959 AcpiRemoveNotifyHandler(lid.dev.hdl, ACPI_DEVICE_NOTIFY, 1960 acpi_drv_lid_notify); 1961 for (op = outputs; op != NULL; op = op->next) { 1962 if (op->dev.valid) { 1963 if (op->levels) { 1964 kmem_free(op->levels, 1965 op->nlev * sizeof (uint32_t)); 1966 } 1967 AcpiRemoveNotifyHandler(op->dev.hdl, ACPI_DEVICE_NOTIFY, 1968 acpi_drv_output_notify); 1969 } 1970 kmem_free(op, sizeof (struct acpi_drv_output_state)); 1971 } 1972 } 1973 1974 /*ARGSUSED*/ 1975 static int 1976 acpi_drv_kstat_power_update(kstat_t *ksp, int flag) 1977 { 1978 if (flag == KSTAT_WRITE) { 1979 return (EACCES); 1980 } 1981 1982 mutex_enter(&acpi_drv_mutex); 1983 if (acpi_drv_psr_type == ACPI_DRV_TYPE_UNKNOWN) { 1984 mutex_exit(&acpi_drv_mutex); 1985 return (EIO); 1986 } 1987 kstat_named_setstr(&acpi_drv_power_kstat.acpi_drv_power, 1988 acpi_drv_psr_type == ACPI_DRV_TYPE_AC ? AC : BATTERY); 1989 acpi_drv_power_kstat.acpi_drv_supported_battery_count.value.ui32 = 1990 (uint32_t)nbat; 1991 mutex_exit(&acpi_drv_mutex); 1992 1993 return (0); 1994 } 1995 1996 /*ARGSUSED*/ 1997 static int 1998 acpi_drv_kstat_warn_update(kstat_t *ksp, int flag) 1999 { 2000 if (flag == KSTAT_WRITE) { 2001 int ret = 0; 2002 acpi_drv_warn_t bw; 2003 acpi_drv_warn_kstat_t kbw; 2004 2005 kbw = *(acpi_drv_warn_kstat_t *)acpi_drv_warn_ksp->ks_data; 2006 2007 mutex_enter(&acpi_drv_mutex); 2008 bw.bw_enabled = kbw.acpi_drv_bw_enabled.value.ui32; 2009 bw.bw_charge_warn = kbw.acpi_drv_bw_charge_warn.value.ui32; 2010 bw.bw_charge_low = kbw.acpi_drv_bw_charge_low.value.ui32; 2011 ret = acpi_drv_set_warn(&bw); 2012 mutex_exit(&acpi_drv_mutex); 2013 2014 return (ret); 2015 } else { 2016 acpi_drv_warn_kstat_t *wp = &acpi_drv_warn_kstat; 2017 2018 mutex_enter(&acpi_drv_mutex); 2019 wp->acpi_drv_bw_enabled.value.ui32 = acpi_drv_warn_enabled; 2020 wp->acpi_drv_bw_charge_warn.value.ui32 = acpi_drv_syn_warn_per; 2021 wp->acpi_drv_bw_charge_low.value.ui32 = acpi_drv_syn_low_per; 2022 mutex_exit(&acpi_drv_mutex); 2023 2024 return (0); 2025 } 2026 } 2027 2028 static int 2029 acpi_drv_kstat_bif_update(kstat_t *ksp, int flag) 2030 { 2031 struct acpi_drv_cbat_state *bp; 2032 acpi_bif_t *bif; 2033 acpi_drv_bif_kstat_t *kp; 2034 2035 if (flag == KSTAT_WRITE) { 2036 return (EACCES); 2037 } 2038 2039 bp = (struct acpi_drv_cbat_state *)ksp->ks_private; 2040 mutex_enter(&acpi_drv_mutex); 2041 2042 if (acpi_drv_cbat_present(bp) <= 0) { 2043 mutex_exit(&acpi_drv_mutex); 2044 return (ENXIO); 2045 } 2046 2047 bzero(&bif, sizeof (bif)); 2048 if (acpi_drv_update_bif(bp) != ACPI_DRV_OK) { 2049 mutex_exit(&acpi_drv_mutex); 2050 return (ENXIO); 2051 } 2052 2053 bif = &bp->bif_cache; 2054 kp = &acpi_drv_bif_kstat; 2055 2056 /* Update BIF */ 2057 kp->acpi_drv_bif_unit.value.ui32 = bif->bif_unit; 2058 kp->acpi_drv_bif_design_cap.value.ui32 = bif->bif_design_cap; 2059 kp->acpi_drv_bif_last_cap.value.ui32 = bif->bif_last_cap; 2060 kp->acpi_drv_bif_tech.value.ui32 = bif->bif_tech; 2061 kp->acpi_drv_bif_voltage.value.ui32 = bif->bif_voltage; 2062 kp->acpi_drv_bif_warn_cap.value.ui32 = bif->bif_warn_cap; 2063 kp->acpi_drv_bif_low_cap.value.ui32 = bif->bif_low_cap; 2064 kp->acpi_drv_bif_gran1_cap.value.ui32 = bif->bif_gran1_cap; 2065 kp->acpi_drv_bif_gran2_cap.value.ui32 = bif->bif_gran2_cap; 2066 2067 kstat_named_setstr(&kp->acpi_drv_bif_model, bif->bif_model); 2068 kstat_named_setstr(&kp->acpi_drv_bif_serial, bif->bif_serial); 2069 kstat_named_setstr(&kp->acpi_drv_bif_type, bif->bif_type); 2070 kstat_named_setstr(&kp->acpi_drv_bif_oem_info, bif->bif_oem_info); 2071 2072 mutex_exit(&acpi_drv_mutex); 2073 return (0); 2074 } 2075 2076 static int 2077 acpi_drv_kstat_bst_update(kstat_t *ksp, int flag) 2078 { 2079 struct acpi_drv_cbat_state *bp; 2080 acpi_bst_t *bst; 2081 acpi_drv_bst_kstat_t *kp; 2082 2083 if (flag == KSTAT_WRITE) { 2084 return (EACCES); 2085 } 2086 2087 bp = (struct acpi_drv_cbat_state *)ksp->ks_private; 2088 mutex_enter(&acpi_drv_mutex); 2089 2090 if (acpi_drv_cbat_present(bp) <= 0) { 2091 mutex_exit(&acpi_drv_mutex); 2092 return (ENXIO); 2093 } 2094 2095 bzero(&bst, sizeof (bst)); 2096 if (acpi_drv_update_bst(bp) != ACPI_DRV_OK) { 2097 mutex_exit(&acpi_drv_mutex); 2098 return (ENXIO); 2099 } 2100 2101 bst = &bp->bst_cache; 2102 kp = &acpi_drv_bst_kstat; 2103 2104 /* Update BST */ 2105 kp->acpi_drv_bst_state.value.ui32 = bst->bst_state; 2106 kp->acpi_drv_bst_rate.value.ui32 = bst->bst_rate; 2107 kp->acpi_drv_bst_rem_cap.value.ui32 = bst->bst_rem_cap; 2108 kp->acpi_drv_bst_voltage.value.ui32 = bst->bst_voltage; 2109 2110 mutex_exit(&acpi_drv_mutex); 2111 return (0); 2112 } 2113 2114 static int 2115 acpi_drv_kstat_init(void) 2116 { 2117 char name[KSTAT_STRLEN]; 2118 struct acpi_drv_cbat_state *bp; 2119 2120 /* 2121 * Allocate, initialize and install powerstatus and 2122 * supported_battery_count kstat. 2123 */ 2124 acpi_drv_power_ksp = kstat_create(ACPI_DRV_NAME, 0, 2125 ACPI_DRV_POWER_KSTAT_NAME, "misc", 2126 KSTAT_TYPE_NAMED, 2127 sizeof (acpi_drv_power_kstat) / sizeof (kstat_named_t), 2128 KSTAT_FLAG_VIRTUAL); 2129 if (acpi_drv_power_ksp == NULL) { 2130 ACPI_DRV_DBG(CE_WARN, NULL, 2131 "kstat_create(%s) fail", ACPI_DRV_POWER_KSTAT_NAME); 2132 return (ACPI_DRV_ERR); 2133 } 2134 2135 acpi_drv_power_ksp->ks_data = &acpi_drv_power_kstat; 2136 acpi_drv_power_ksp->ks_update = acpi_drv_kstat_power_update; 2137 acpi_drv_power_ksp->ks_data_size += MAXNAMELEN; 2138 kstat_install(acpi_drv_power_ksp); 2139 2140 /* 2141 * Allocate, initialize and install battery_capacity_warning kstat. 2142 */ 2143 acpi_drv_warn_ksp = kstat_create(ACPI_DRV_NAME, 0, 2144 ACPI_DRV_BTWARN_KSTAT_NAME, "misc", 2145 KSTAT_TYPE_NAMED, 2146 sizeof (acpi_drv_warn_kstat) / sizeof (kstat_named_t), 2147 KSTAT_FLAG_VIRTUAL | KSTAT_FLAG_WRITABLE); 2148 if (acpi_drv_warn_ksp == NULL) { 2149 ACPI_DRV_DBG(CE_WARN, NULL, 2150 "kstat_create(%s) fail", ACPI_DRV_BTWARN_KSTAT_NAME); 2151 return (ACPI_DRV_ERR); 2152 } 2153 2154 acpi_drv_warn_ksp->ks_data = &acpi_drv_warn_kstat; 2155 acpi_drv_warn_ksp->ks_update = acpi_drv_kstat_warn_update; 2156 kstat_install(acpi_drv_warn_ksp); 2157 2158 /* 2159 * Allocate, initialize and install BIF and BST kstat 2160 * for each battery. 2161 */ 2162 for (bp = &acpi_drv_cbat[0]; bp < &acpi_drv_cbat[ACPI_DRV_MAX_BAT_NUM]; 2163 bp++) { 2164 if (bp->dev.valid) { 2165 kstat_t *ksp; 2166 2167 /* BIF kstat */ 2168 (void) snprintf(name, KSTAT_STRLEN-1, "%s%d", 2169 ACPI_DRV_BIF_KSTAT_NAME, bp->dev.index); 2170 ksp = kstat_create(ACPI_DRV_NAME, 0, 2171 name, "misc", KSTAT_TYPE_NAMED, 2172 sizeof (acpi_drv_bif_kstat) / 2173 sizeof (kstat_named_t), KSTAT_FLAG_VIRTUAL); 2174 if (ksp == NULL) { 2175 ACPI_DRV_DBG(CE_WARN, NULL, 2176 "kstat_create(%s) fail", name); 2177 return (ACPI_DRV_ERR); 2178 } 2179 ACPI_DRV_DBG(CE_NOTE, NULL, "kstat_create(%s) ok", 2180 name); 2181 2182 bp->bat_bif_ksp = ksp; 2183 ksp->ks_data = &acpi_drv_bif_kstat; 2184 ksp->ks_update = acpi_drv_kstat_bif_update; 2185 ksp->ks_data_size += MAXNAMELEN * 4; 2186 ksp->ks_private = bp; 2187 2188 kstat_install(ksp); 2189 2190 /* BST kstat */ 2191 (void) snprintf(name, KSTAT_STRLEN-1, "%s%d", 2192 ACPI_DRV_BST_KSTAT_NAME, bp->dev.index); 2193 ksp = kstat_create(ACPI_DRV_NAME, 0, name, "misc", 2194 KSTAT_TYPE_NAMED, 2195 sizeof (acpi_drv_bst_kstat) / 2196 sizeof (kstat_named_t), 2197 KSTAT_FLAG_VIRTUAL); 2198 if (ksp == NULL) { 2199 ACPI_DRV_DBG(CE_WARN, NULL, 2200 "kstat_create(%s) fail", name); 2201 return (ACPI_DRV_ERR); 2202 } 2203 ACPI_DRV_DBG(CE_NOTE, NULL, "kstat_create(%s) ok", 2204 name); 2205 2206 bp->bat_bst_ksp = ksp; 2207 ksp->ks_data = &acpi_drv_bst_kstat; 2208 ksp->ks_update = acpi_drv_kstat_bst_update; 2209 ksp->ks_data_size += MAXNAMELEN * 4; 2210 ksp->ks_private = bp; 2211 2212 kstat_install(ksp); 2213 } 2214 } 2215 2216 return (ACPI_DRV_OK); 2217 } 2218 2219 static void 2220 acpi_drv_kstat_fini() 2221 { 2222 struct acpi_drv_cbat_state *bp; 2223 2224 if (acpi_drv_power_ksp != NULL) { 2225 kstat_delete(acpi_drv_power_ksp); 2226 } 2227 if (acpi_drv_warn_ksp != NULL) { 2228 kstat_delete(acpi_drv_warn_ksp); 2229 } 2230 for (bp = &acpi_drv_cbat[0]; bp < &acpi_drv_cbat[ACPI_DRV_MAX_BAT_NUM]; 2231 bp++) { 2232 if (bp->dev.valid) { 2233 if (bp->bat_bif_ksp != NULL) { 2234 kstat_delete(bp->bat_bif_ksp); 2235 } 2236 if (bp->bat_bst_ksp != NULL) { 2237 kstat_delete(bp->bat_bst_ksp); 2238 } 2239 } 2240 } 2241 } 2242 2243 static int 2244 acpi_drv_set_int(ACPI_HANDLE dev, char *method, uint32_t aint) 2245 { 2246 ACPI_OBJECT_LIST al; 2247 ACPI_OBJECT ao; 2248 2249 al.Pointer = &ao; 2250 al.Count = 1; 2251 ao.Type = ACPI_TYPE_INTEGER; 2252 ao.Integer.Value = aint; 2253 return (AcpiEvaluateObject(dev, method, &al, NULL)); 2254 } 2255 2256 static int 2257 acpi_drv_output_init(ACPI_HANDLE hdl, struct acpi_drv_dev *dev) 2258 { 2259 struct acpi_drv_output_state *op; 2260 int adr; 2261 ACPI_BUFFER buf1, buf2; 2262 ACPI_OBJECT *objp; 2263 char str[256]; 2264 2265 if (acpica_eval_int(hdl, "_ADR", &adr) != AE_OK) { 2266 return (ACPI_DRV_ERR); 2267 } 2268 2269 op = dev->op; 2270 op->adr = adr; 2271 2272 buf1.Pointer = str; 2273 buf1.Length = sizeof (str); 2274 2275 if (!ACPI_FAILURE(AcpiGetName(hdl, ACPI_FULL_PATHNAME, &buf1))) { 2276 ACPI_DRV_DBG(CE_NOTE, NULL, "Pathname=%s\n", 2277 (char *)buf1.Pointer); 2278 } 2279 2280 buf2.Length = ACPI_ALLOCATE_BUFFER; 2281 if (ACPI_SUCCESS(AcpiEvaluateObjectTyped(hdl, "_BCL", 2282 NULL, &buf2, ACPI_TYPE_PACKAGE))) { 2283 int i, j, k, l, m, nlev, tmp; 2284 2285 ACPI_DRV_DBG(CE_NOTE, NULL, "_BCL supported\n"); 2286 objp = buf2.Pointer; 2287 /* 2288 * op->nlev will be needed to free op->levels. 2289 */ 2290 op->nlev = nlev = objp->Package.Count; 2291 op->levels = kmem_zalloc(nlev * sizeof (uint32_t), 2292 KM_SLEEP); 2293 /* 2294 * Get all the supported brightness levels. 2295 */ 2296 for (i = 0; i < nlev; i++) { 2297 ACPI_OBJECT *o = &objp->Package.Elements[i]; 2298 int lev = o->Integer.Value; 2299 2300 ACPI_DRV_DBG(CE_NOTE, NULL, "acpi_drv_output_init() " 2301 "brlev=%d i=%d nlev=%d\n", lev, i, nlev); 2302 if (o->Type != ACPI_TYPE_INTEGER) { 2303 continue; 2304 } 2305 op->levels[i] = lev; 2306 } 2307 2308 /* 2309 * Sort the brightness levels. 2310 */ 2311 for (j = 0; j < nlev; j++) { 2312 for (k = 0; k < nlev - 1; k++) { 2313 if (op->levels[k] > op->levels[k+1]) { 2314 tmp = op->levels[k+1]; 2315 op->levels[k+1] = op->levels[k]; 2316 op->levels[k] = tmp; 2317 } 2318 } 2319 } 2320 2321 /* 2322 * The first two levels could be duplicated, so remove 2323 * any duplicates. 2324 */ 2325 for (l = 0; l < nlev - 1; l++) { 2326 if (op->levels[l] == op->levels[l+1]) { 2327 for (m = l + 1; m < nlev - 1; m++) { 2328 op->levels[m] = op->levels[m+1]; 2329 } 2330 nlev--; 2331 } 2332 } 2333 op->num_levels = nlev; 2334 2335 AcpiOsFree(objp); 2336 (void) acpi_drv_output_get_level(op); 2337 ACPI_DRV_DBG(CE_NOTE, NULL, "acpi_drv_output_init(): " 2338 "create minor " 2339 "node for dev->adr=%"PRIu64, dev->adr); 2340 } else { 2341 ACPI_DRV_DBG(CE_NOTE, NULL, "_BCL NOT supported\n"); 2342 } 2343 2344 (void) acpi_drv_output_get_state(op); 2345 return (ACPI_DRV_OK); 2346 } 2347 2348 /*ARGSUSED*/ 2349 static int 2350 acpi_drv_output_ioctl(int index, int cmd, intptr_t arg, int mode, cred_t *cr, 2351 int *rval) 2352 { 2353 struct acpi_drv_output_state *op; 2354 int res = 0; 2355 op = acpi_drv_idx2output(index); 2356 if (!op || op->dev.valid != 1) { 2357 return (ENXIO); 2358 } 2359 2360 switch (cmd) { 2361 case ACPI_DRV_IOC_INFO: { 2362 struct acpi_drv_output_info inf; 2363 inf.adr = op->adr; 2364 inf.nlev = op->num_levels; 2365 if (copyout(&inf, (void *)arg, sizeof (inf))) { 2366 res = EFAULT; 2367 } 2368 break; 2369 } 2370 2371 case ACPI_DRV_IOC_LEVELS: 2372 if (copyout(op->levels, (void *)arg, 2373 sizeof (*op->levels) * op->num_levels)) { 2374 res = EFAULT; 2375 } 2376 break; 2377 2378 case ACPI_DRV_IOC_STATUS: { 2379 /* 2380 * Need to get the current levels through ACPI first 2381 * then go through array of levels to find index. 2382 */ 2383 struct acpi_drv_output_status status; 2384 int i; 2385 2386 status.state = op->state; 2387 status.num_levels = op->num_levels; 2388 status.cur_level = op->cur_level; 2389 for (i = 0; i < op->num_levels; i++) { 2390 if (op->levels[i] == op->cur_level) { 2391 status.cur_level_index = i; 2392 ACPI_DRV_DBG(CE_NOTE, NULL, "ACPI_DRV_IOC_STATUS " 2393 "cur_level_index %d\n", i); 2394 break; 2395 } 2396 } 2397 if (copyout(&status, (void *)arg, sizeof (status))) { 2398 res = EFAULT; 2399 } 2400 break; 2401 } 2402 2403 case ACPI_DRV_IOC_SET_BRIGHTNESS: { 2404 int level; 2405 2406 if (drv_priv(cr)) { 2407 res = EPERM; 2408 break; 2409 } 2410 if (copyin((void *)arg, &level, sizeof (level))) { 2411 res = EFAULT; 2412 break; 2413 } 2414 ACPI_DRV_DBG(CE_NOTE, NULL, 2415 "ACPI_DRV_IOC_SET_BRIGHTNESS level=%d\n", level); 2416 if (acpi_drv_output_set_level(op, level) != ACPI_DRV_OK) { 2417 res = EFAULT; 2418 } 2419 break; 2420 } 2421 2422 default: 2423 res = EINVAL; 2424 break; 2425 } 2426 return (res); 2427 } 2428 2429 static struct acpi_drv_output_state * 2430 acpi_drv_idx2output(int idx) 2431 { 2432 struct acpi_drv_output_state *op = outputs; 2433 2434 while ((op != NULL) && (op->dev.index != idx)) { 2435 op = op->next; 2436 } 2437 return (op); 2438 } 2439 2440 /* 2441 * Output device status: 2442 * 2443 * Bits Definition 2444 * 2445 * 0 Output connector exists in the system now. 2446 * 1 Output is activated. 2447 * 2 Output is ready to switch. 2448 * 3 Output is not defective. 2449 * 4 Device is attached (optional). 2450 * 5-31 Reserved (must be zero). 2451 */ 2452 static int 2453 acpi_drv_output_get_state(struct acpi_drv_output_state *op) 2454 { 2455 if (acpica_eval_int(op->dev.hdl, "_DCS", &op->state) != AE_OK) { 2456 op->state = 0; 2457 return (ACPI_DRV_ERR); 2458 } 2459 return (ACPI_DRV_OK); 2460 } 2461 2462 /* 2463 * Get the current brightness level and index. 2464 */ 2465 static int 2466 acpi_drv_output_get_level(struct acpi_drv_output_state *op) 2467 { 2468 int i; 2469 2470 if (acpica_eval_int(op->dev.hdl, "_BQC", &op->cur_level) != AE_OK) { 2471 op->cur_level = ACPI_DRV_NTF_UNKNOWN; 2472 return (ACPI_DRV_ERR); 2473 } 2474 for (i = 0; i < op->num_levels; i++) { 2475 if (op->levels[i] == op->cur_level) { 2476 op->cur_level_index = i; 2477 ACPI_DRV_DBG(CE_NOTE, NULL, 2478 "acpi_drv_output_get_level(): " 2479 "cur_level = %d, cur_level_index = %d\n", 2480 op->cur_level, i); 2481 break; 2482 } 2483 } 2484 return (ACPI_DRV_OK); 2485 } 2486 2487 static int 2488 acpi_drv_output_set_level(struct acpi_drv_output_state *op, uint32_t level) 2489 { 2490 if (acpi_drv_set_int(op->dev.hdl, "_BCM", op->levels[level]) != 2491 AE_OK) { 2492 return (ACPI_DRV_ERR); 2493 } 2494 op->cur_level = op->levels[level]; 2495 op->cur_level_index = level; 2496 return (ACPI_DRV_OK); 2497 } 2498 2499 static void 2500 acpi_drv_output_notify(ACPI_HANDLE hdl, UINT32 val, void *ctx) 2501 { 2502 struct acpi_drv_dev *dev = ctx; 2503 struct acpi_drv_output_state *op = dev->op; 2504 2505 ACPI_DRV_DBG(CE_NOTE, NULL, "acpi_drv_output_notify() val=0x%x\n", val); 2506 mutex_enter(&acpi_drv_mutex); 2507 ACPI_DRV_PRT_NOTIFY(hdl, val); 2508 switch (val) { 2509 case 0x86: /* increase brightness */ 2510 if (op->cur_level_index < op->num_levels - 1) { 2511 if (acpi_drv_output_set_level(op, 2512 op->cur_level_index + 1) != AE_OK) { 2513 break; 2514 } 2515 } 2516 acpi_drv_gen_sysevent(&op->dev, ESC_PWRCTL_BRIGHTNESS_UP, 0); 2517 break; 2518 case 0x87: /* decrease brightness */ 2519 if (op->cur_level_index > 0) { 2520 if (acpi_drv_output_set_level(op, 2521 op->cur_level_index - 1) != AE_OK) { 2522 break; 2523 } 2524 } 2525 acpi_drv_gen_sysevent(&op->dev, ESC_PWRCTL_BRIGHTNESS_DOWN, 0); 2526 break; 2527 default: 2528 break; 2529 } 2530 mutex_exit(&acpi_drv_mutex); 2531 } 2532 2533 /* 2534 * Set the display control modes of display switching and brightness 2535 * from BIOS or OSPM. 2536 */ 2537 static void 2538 acpi_drv_display_set_mode(struct acpi_drv_display_state *dp, int state) 2539 { 2540 if (acpi_drv_set_int(dp->dev.hdl, "_DOS", state) != AE_OK) { 2541 ACPI_DRV_DBG(CE_WARN, NULL, "Cannot set display mode %d\n", 2542 state); 2543 } 2544 } 2545