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