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