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