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