16573Sphitran /*
26573Sphitran * CDDL HEADER START
36573Sphitran *
46573Sphitran * The contents of this file are subject to the terms of the
56573Sphitran * Common Development and Distribution License (the "License").
66573Sphitran * You may not use this file except in compliance with the License.
76573Sphitran *
86573Sphitran * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
96573Sphitran * or http://www.opensolaris.org/os/licensing.
106573Sphitran * See the License for the specific language governing permissions
116573Sphitran * and limitations under the License.
126573Sphitran *
136573Sphitran * When distributing Covered Code, include this CDDL HEADER in each
146573Sphitran * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
156573Sphitran * If applicable, add the following below this CDDL HEADER, with the
166573Sphitran * fields enclosed by brackets "[]" replaced with your own identifying
176573Sphitran * information: Portions Copyright [yyyy] [name of copyright owner]
186573Sphitran *
196573Sphitran * CDDL HEADER END
206573Sphitran */
216573Sphitran
226573Sphitran /*
238693SKerry.Shu@Sun.COM * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
246573Sphitran * Use is subject to license terms.
256573Sphitran */
266573Sphitran
276573Sphitran /*
288693SKerry.Shu@Sun.COM * Driver for ACPI Battery, Lid, and Hotkey Control
296573Sphitran */
308693SKerry.Shu@Sun.COM #include <sys/hotkey_drv.h>
316573Sphitran #include <sys/sysevent/pwrctl.h>
326573Sphitran
336573Sphitran
346573Sphitran #define ACPI_DRV_MOD_STRING "ACPI driver"
356573Sphitran
366573Sphitran #define MINOR_SHIFT 8
376573Sphitran #define IDX_MASK ((1 << MINOR_SHIFT) - 1)
386573Sphitran #define MINOR_BATT(idx) (ACPI_DRV_TYPE_CBAT << MINOR_SHIFT | \
396573Sphitran (idx))
406573Sphitran #define MINOR_AC(idx) (ACPI_DRV_TYPE_AC << MINOR_SHIFT | \
416573Sphitran (idx))
426573Sphitran #define MINOR_LID(idx) (ACPI_DRV_TYPE_LID << MINOR_SHIFT | \
436573Sphitran (idx))
448693SKerry.Shu@Sun.COM #define MINOR_HOTKEY(idx) (ACPI_DRV_TYPE_HOTKEY << MINOR_SHIFT \
456573Sphitran | (idx))
466573Sphitran #define MINOR2IDX(minor) ((minor) & IDX_MASK)
476573Sphitran #define MINOR2TYPE(minor) ((minor) >> MINOR_SHIFT)
486573Sphitran
496573Sphitran #define ACPI_DRV_MAX_BAT_NUM 8
506573Sphitran #define ACPI_DRV_MAX_AC_NUM 10
516573Sphitran
526573Sphitran #define BST_FLAG_DISCHARGING (0x1)
536573Sphitran #define BST_FLAG_CHARGING (0x2)
546573Sphitran #define BST_FLAG_CRITICAL (0x4)
556573Sphitran
566573Sphitran /* Set if the battery is present */
576573Sphitran #define STA_FLAG_BATT_PRESENT (0x10)
586573Sphitran
596573Sphitran #define ACPI_DEVNAME_CBAT "PNP0C0A"
606573Sphitran #define ACPI_DEVNAME_AC "ACPI0003"
616573Sphitran #define ACPI_DEVNAME_LID "PNP0C0D"
626573Sphitran
636573Sphitran #define ACPI_DRV_EVENTS (POLLIN | POLLRDNORM)
646573Sphitran
656573Sphitran #ifdef DEBUG
666573Sphitran
676573Sphitran #define ACPI_DRV_PRINT_BUFFER_SIZE 512
686573Sphitran static char acpi_drv_prt_buf[ACPI_DRV_PRINT_BUFFER_SIZE];
696573Sphitran static kmutex_t acpi_drv_prt_mutex;
706573Sphitran
716573Sphitran static int acpi_drv_debug = 0;
726573Sphitran #define ACPI_DRV_DBG(lev, devp, ...) \
736573Sphitran do { \
746573Sphitran if (acpi_drv_debug) acpi_drv_printf((devp), \
756573Sphitran (lev), __VA_ARGS__); \
766573Sphitran _NOTE(CONSTCOND) } while (0)
776573Sphitran #define ACPI_DRV_PRT_NOTIFY(hdl, val) \
786573Sphitran do { \
796573Sphitran if (acpi_drv_debug) acpi_drv_prt_notify((hdl), (val)); \
806573Sphitran _NOTE(CONSTCOND) } while (0)
816573Sphitran
826573Sphitran #else
836573Sphitran
846573Sphitran #define ACPI_DRV_DBG(lev, devp, ...)
856573Sphitran #define ACPI_DRV_PRT_NOTIFY(hdl, val)
866573Sphitran
876573Sphitran #endif /* DEBUG */
886573Sphitran
896573Sphitran /* ACPI notify types */
906573Sphitran enum acpi_drv_notify {
916573Sphitran ACPI_DRV_NTF_UNKNOWN = -1, /* No notifications seen, ever. */
926573Sphitran ACPI_DRV_NTF_CHANGED,
936573Sphitran ACPI_DRV_NTF_OK
946573Sphitran };
956573Sphitran
966573Sphitran static int acpi_drv_dev_present(struct acpi_drv_dev *);
976573Sphitran #define acpi_drv_ac_present(a) (((a)->dev.type == ACPI_DRV_TYPE_AC) ? \
986573Sphitran acpi_drv_dev_present(&(a)->dev) : -1)
996573Sphitran #define acpi_drv_cbat_present(a) (((a)->dev.type == ACPI_DRV_TYPE_CBAT) \
1006573Sphitran ? acpi_drv_dev_present(&(a)->dev) : -1)
1016573Sphitran
1026573Sphitran static dev_info_t *acpi_drv_dip = NULL;
1036573Sphitran static kmutex_t acpi_drv_mutex;
1046573Sphitran static struct pollhead acpi_drv_pollhead;
1056573Sphitran
1066573Sphitran /* Control Method Battery state */
1076573Sphitran struct acpi_drv_cbat_state {
1086573Sphitran struct acpi_drv_dev dev;
1096573Sphitran /* Caches of _BST and _BIF */
1106573Sphitran enum acpi_drv_notify bat_bifok;
1116573Sphitran acpi_bif_t bif_cache;
1126573Sphitran enum acpi_drv_notify bat_bstok;
1136573Sphitran acpi_bst_t bst_cache;
1146573Sphitran
1156573Sphitran uint32_t charge_warn;
1166573Sphitran uint32_t charge_low;
1176573Sphitran
1186573Sphitran kstat_t *bat_bif_ksp;
1196573Sphitran kstat_t *bat_bst_ksp;
1206573Sphitran } acpi_drv_cbat[ACPI_DRV_MAX_BAT_NUM];
1217051Sphitran static int nbat = 0;
1226573Sphitran
1236573Sphitran /*
1246573Sphitran * Synthesis battery state
1256573Sphitran * When there are multiple batteries present, the battery subsystem
1266573Sphitran * is not required to perform any synthesis of a composite battery
1276573Sphitran * from the data of the separate batteries. In cases where the
1286573Sphitran * battery subsystem does not synthesize a composite battery from
1296573Sphitran * the separate battery's data, the OS must provide that synthesis.
1306573Sphitran */
1316573Sphitran static uint32_t acpi_drv_syn_rem_cap;
1326573Sphitran static uint32_t acpi_drv_syn_last_cap;
1336573Sphitran static uint32_t acpi_drv_syn_oem_warn_cap;
1346573Sphitran static uint32_t acpi_drv_syn_oem_low_cap;
1356573Sphitran
1366573Sphitran static int acpi_drv_warn_enabled;
1376573Sphitran static uint32_t acpi_drv_syn_warn_per;
1386573Sphitran static uint32_t acpi_drv_syn_low_per;
1396573Sphitran static uint32_t acpi_drv_syn_warn_cap;
1406573Sphitran static uint32_t acpi_drv_syn_low_cap;
1416573Sphitran /* Tracking boundery passing of _BST charge levels */
1426573Sphitran static uint32_t acpi_drv_syn_last_level;
1436573Sphitran
1446573Sphitran /* AC state */
1456573Sphitran static struct acpi_drv_ac_state {
1466573Sphitran struct acpi_drv_dev dev;
1476573Sphitran } acpi_drv_ac[ACPI_DRV_MAX_AC_NUM];
1487051Sphitran static int nac = 0;
1496573Sphitran
1506573Sphitran /*
1516573Sphitran * Current power source device
1526573Sphitran * Note: assume only one device can be the power source device.
1536573Sphitran */
1546573Sphitran static int acpi_drv_psr_type = ACPI_DRV_TYPE_UNKNOWN;
1556573Sphitran static struct acpi_drv_dev *acpi_drv_psr_devp = NULL;
1566573Sphitran
1576573Sphitran struct obj_desc {
1586573Sphitran char *name;
1596573Sphitran int offset;
1606573Sphitran int size;
1616573Sphitran int type;
1626573Sphitran };
1636573Sphitran
1646573Sphitran /* Object copy definitions */
1656573Sphitran #define OFFSETOF(s, m) ((size_t)(&(((s *)0)->m)))
1666573Sphitran #define SIZEOF(s, m) (sizeof (((s *)0)->m))
1676573Sphitran #define FIELD(n, s, m, t) \
1686573Sphitran { n, OFFSETOF(s, m), SIZEOF(s, m), t }
1696573Sphitran #define FIELD_NULL { NULL, -1, 0, ACPI_TYPE_ANY }
1706573Sphitran
1716573Sphitran static struct obj_desc bif_desc[] = {
1726573Sphitran FIELD("bif_unit", acpi_bif_t, bif_unit, ACPI_TYPE_INTEGER),
1736573Sphitran FIELD("bif_design_cap", acpi_bif_t, bif_design_cap, ACPI_TYPE_INTEGER),
1746573Sphitran FIELD("bif_last_cap", acpi_bif_t, bif_last_cap, ACPI_TYPE_INTEGER),
1756573Sphitran FIELD("bif_tech", acpi_bif_t, bif_tech, ACPI_TYPE_INTEGER),
1766573Sphitran FIELD("bif_voltage", acpi_bif_t, bif_voltage, ACPI_TYPE_INTEGER),
1776573Sphitran FIELD("bif_warn_cap", acpi_bif_t, bif_warn_cap, ACPI_TYPE_INTEGER),
1786573Sphitran FIELD("bif_low_cap", acpi_bif_t, bif_low_cap, ACPI_TYPE_INTEGER),
1796573Sphitran FIELD("bif_gran1_cap", acpi_bif_t, bif_gran1_cap, ACPI_TYPE_INTEGER),
1806573Sphitran FIELD("bif_gran2_cap", acpi_bif_t, bif_gran2_cap, ACPI_TYPE_INTEGER),
1816573Sphitran FIELD("bif_model", acpi_bif_t, bif_model, ACPI_TYPE_STRING),
1826573Sphitran FIELD("bif_serial", acpi_bif_t, bif_serial, ACPI_TYPE_STRING),
1836573Sphitran FIELD("bif_type", acpi_bif_t, bif_type, ACPI_TYPE_STRING),
1846573Sphitran FIELD("bif_oem_info", acpi_bif_t, bif_oem_info, ACPI_TYPE_STRING),
1856573Sphitran FIELD_NULL
1866573Sphitran };
1876573Sphitran
1886573Sphitran static struct obj_desc bst_desc[] = {
1896573Sphitran FIELD("bst_state", acpi_bst_t, bst_state, ACPI_TYPE_INTEGER),
1906573Sphitran FIELD("bst_rate", acpi_bst_t, bst_rate, ACPI_TYPE_INTEGER),
1916573Sphitran FIELD("bst_rem_cap", acpi_bst_t, bst_rem_cap, ACPI_TYPE_INTEGER),
1926573Sphitran FIELD("bst_voltage", acpi_bst_t, bst_voltage, ACPI_TYPE_INTEGER),
1936573Sphitran FIELD_NULL
1946573Sphitran };
1956573Sphitran
1966573Sphitran /* kstat definitions */
1976573Sphitran static kstat_t *acpi_drv_power_ksp;
1986573Sphitran static kstat_t *acpi_drv_warn_ksp;
1996573Sphitran
2006573Sphitran acpi_drv_power_kstat_t acpi_drv_power_kstat = {
2016573Sphitran { SYSTEM_POWER, KSTAT_DATA_STRING },
2026573Sphitran { SUPPORTED_BATTERY_COUNT, KSTAT_DATA_UINT32 },
2036573Sphitran };
2046573Sphitran
2056573Sphitran acpi_drv_warn_kstat_t acpi_drv_warn_kstat = {
2066573Sphitran { BW_ENABLED, KSTAT_DATA_UINT32 },
2076573Sphitran { BW_POWEROFF_THRESHOLD, KSTAT_DATA_UINT32 },
2086573Sphitran { BW_SHUTDOWN_THRESHOLD, KSTAT_DATA_UINT32 },
2096573Sphitran };
2106573Sphitran
2116573Sphitran /* BIF */
2126573Sphitran acpi_drv_bif_kstat_t acpi_drv_bif_kstat = {
2136573Sphitran { BIF_UNIT, KSTAT_DATA_UINT32 },
2146573Sphitran { BIF_DESIGN_CAP, KSTAT_DATA_UINT32 },
2156573Sphitran { BIF_LAST_CAP, KSTAT_DATA_UINT32 },
2166573Sphitran { BIF_TECH, KSTAT_DATA_UINT32 },
2176573Sphitran { BIF_VOLTAGE, KSTAT_DATA_UINT32 },
2186573Sphitran { BIF_WARN_CAP, KSTAT_DATA_UINT32 },
2196573Sphitran { BIF_LOW_CAP, KSTAT_DATA_UINT32 },
2206573Sphitran { BIF_GRAN1_CAP, KSTAT_DATA_UINT32 },
2216573Sphitran { BIF_GRAN2_CAP, KSTAT_DATA_UINT32 },
2226573Sphitran { BIF_MODEL, KSTAT_DATA_STRING },
2236573Sphitran { BIF_SERIAL, KSTAT_DATA_STRING },
2246573Sphitran { BIF_TYPE, KSTAT_DATA_STRING },
2256573Sphitran { BIF_OEM_INFO, KSTAT_DATA_STRING },
2266573Sphitran };
2276573Sphitran
2286573Sphitran /* BST */
2296573Sphitran acpi_drv_bst_kstat_t acpi_drv_bst_kstat = {
2306573Sphitran { BST_STATE, KSTAT_DATA_UINT32 },
2316573Sphitran { BST_RATE, KSTAT_DATA_UINT32 },
2326573Sphitran { BST_REM_CAP, KSTAT_DATA_UINT32 },
2336573Sphitran { BST_VOLTAGE, KSTAT_DATA_UINT32 },
2346573Sphitran };
2356573Sphitran
2366573Sphitran struct acpi_drv_lid_state {
2376573Sphitran struct acpi_drv_dev dev;
2386573Sphitran enum acpi_drv_notify state_ok;
2396573Sphitran int state;
2406573Sphitran } lid;
2417051Sphitran static int nlid = 0;
2426573Sphitran
2438693SKerry.Shu@Sun.COM struct hotkey_drv acpi_hotkey;
2446573Sphitran
2456573Sphitran static int acpi_drv_attach(dev_info_t *devi, ddi_attach_cmd_t cmd);
2466573Sphitran static int acpi_drv_detach(dev_info_t *devi, ddi_detach_cmd_t cmd);
2476573Sphitran static int acpi_drv_getinfo(dev_info_t *dip, ddi_info_cmd_t cmd, void *arg,
2486573Sphitran void **resultp);
2496573Sphitran static int acpi_drv_open(dev_t *devp, int flag, int otyp, cred_t *crp);
2506573Sphitran static int acpi_drv_close(dev_t dev, int flag, int otyp, cred_t *crp);
2516573Sphitran static int acpi_drv_ioctl(dev_t dev, int cmd, intptr_t arg, int mode,
2526573Sphitran cred_t *cr, int *rval);
2536573Sphitran static int acpi_drv_chpoll(dev_t dev, short events, int anyyet,
2546573Sphitran short *reventsp, struct pollhead **phpp);
2556573Sphitran static int acpi_drv_ac_ioctl(int index, int cmd, intptr_t arg, int mode,
2566573Sphitran cred_t *cr, int *rval);
2576573Sphitran static int acpi_drv_cbat_ioctl(int index, int cmd, intptr_t arg, int mode,
2586573Sphitran cred_t *cr, int *rval);
2596573Sphitran static int acpi_drv_lid_ioctl(int index, int cmd, intptr_t arg, int mode,
2606573Sphitran cred_t *cr, int *rval);
2616573Sphitran #ifdef DEBUG
2626573Sphitran static void acpi_drv_printf(struct acpi_drv_dev *devp, uint_t lev,
2636573Sphitran const char *fmt, ...);
2646573Sphitran #endif
2656573Sphitran
2666573Sphitran static int acpi_drv_update_bif(struct acpi_drv_cbat_state *bp);
2676573Sphitran static int acpi_drv_update_bst(struct acpi_drv_cbat_state *bp);
2686573Sphitran static int acpi_drv_update_lid(struct acpi_drv_dev *bp);
2696573Sphitran static int acpi_drv_set_warn(acpi_drv_warn_t *bwp);
2706573Sphitran static struct acpi_drv_cbat_state *acpi_drv_idx2cbat(int idx);
2716573Sphitran static struct acpi_drv_ac_state *acpi_drv_idx2ac(int idx);
2726573Sphitran static int acpi_drv_acpi_init(void);
2736573Sphitran static void acpi_drv_acpi_fini(void);
2746573Sphitran static int acpi_drv_kstat_init(void);
2756573Sphitran static void acpi_drv_kstat_fini(void);
2766573Sphitran
2776573Sphitran static struct cb_ops acpi_drv_cb_ops = {
2786573Sphitran acpi_drv_open, /* open */
2796573Sphitran acpi_drv_close, /* close */
2806573Sphitran nodev, /* strategy */
2816573Sphitran nodev, /* print */
2826573Sphitran nodev, /* dump */
2836573Sphitran nodev, /* read */
2846573Sphitran nodev, /* write */
2856573Sphitran acpi_drv_ioctl, /* ioctl */
2866573Sphitran nodev, /* devmap */
2876573Sphitran nodev, /* mmap */
2886573Sphitran nodev, /* segmap */
2896573Sphitran acpi_drv_chpoll, /* chpoll */
2906573Sphitran ddi_prop_op, /* prop_op */
2916573Sphitran NULL, /* streamtab */
2926573Sphitran D_NEW | D_MP,
2936573Sphitran CB_REV,
2946573Sphitran nodev,
2956573Sphitran nodev
2966573Sphitran };
2976573Sphitran
2986573Sphitran static struct dev_ops acpi_drv_dev_ops = {
2996573Sphitran DEVO_REV,
3006573Sphitran 0, /* refcnt */
3018693SKerry.Shu@Sun.COM acpi_drv_getinfo, /* getinfo */
3026573Sphitran nulldev, /* identify */
3036573Sphitran nulldev, /* probe */
3048693SKerry.Shu@Sun.COM acpi_drv_attach, /* attach */
3058693SKerry.Shu@Sun.COM acpi_drv_detach, /* detach */
3066573Sphitran nodev, /* reset */
3076573Sphitran &acpi_drv_cb_ops,
3086573Sphitran NULL, /* no bus operations */
3097656SSherry.Moore@Sun.COM NULL, /* power */
3108693SKerry.Shu@Sun.COM ddi_quiesce_not_needed, /* quiesce */
3116573Sphitran };
3126573Sphitran
3136573Sphitran static struct modldrv modldrv1 = {
3146573Sphitran &mod_driverops,
3156573Sphitran ACPI_DRV_MOD_STRING,
3166573Sphitran &acpi_drv_dev_ops
3176573Sphitran };
3186573Sphitran
3196573Sphitran static struct modlinkage modlinkage = {
3206573Sphitran MODREV_1,
3216573Sphitran (void *)&modldrv1,
3226573Sphitran NULL,
3236573Sphitran };
3246573Sphitran
3256573Sphitran int
_init(void)3266573Sphitran _init(void)
3276573Sphitran {
3286573Sphitran int ret;
3296573Sphitran
3306573Sphitran mutex_init(&acpi_drv_mutex, NULL, MUTEX_DRIVER, NULL);
3316573Sphitran #ifdef DEBUG
3326573Sphitran mutex_init(&acpi_drv_prt_mutex, NULL, MUTEX_DRIVER, NULL);
3336573Sphitran #endif
3346573Sphitran
3356573Sphitran if ((ret = mod_install(&modlinkage)) != 0) {
3366573Sphitran mutex_destroy(&acpi_drv_mutex);
3376573Sphitran #ifdef DEBUG
3386573Sphitran mutex_destroy(&acpi_drv_prt_mutex);
3396573Sphitran #endif
3406573Sphitran }
3416573Sphitran return (ret);
3426573Sphitran }
3436573Sphitran
3446573Sphitran int
_fini(void)3456573Sphitran _fini(void)
3466573Sphitran {
3476573Sphitran int ret;
3486573Sphitran
3496573Sphitran if ((ret = mod_remove(&modlinkage)) == 0) {
3506573Sphitran #ifdef DEBUG
3516573Sphitran mutex_destroy(&acpi_drv_prt_mutex);
3526573Sphitran #endif
3536573Sphitran mutex_destroy(&acpi_drv_mutex);
3546573Sphitran }
3556573Sphitran
3566573Sphitran return (ret);
3576573Sphitran }
3586573Sphitran
3596573Sphitran int
_info(struct modinfo * mp)3606573Sphitran _info(struct modinfo *mp)
3616573Sphitran {
3626573Sphitran return (mod_info(&modlinkage, mp));
3636573Sphitran }
3646573Sphitran
3656573Sphitran static int
acpi_drv_attach(dev_info_t * devi,ddi_attach_cmd_t cmd)3666573Sphitran acpi_drv_attach(dev_info_t *devi, ddi_attach_cmd_t cmd)
3676573Sphitran {
3686573Sphitran char name[20];
3696573Sphitran int i;
3706573Sphitran struct acpi_drv_cbat_state *bp;
3716573Sphitran
3726573Sphitran switch (cmd) {
3736573Sphitran case DDI_ATTACH:
3746573Sphitran /* Limit to one instance of driver */
3756573Sphitran if (acpi_drv_dip) {
3766573Sphitran return (DDI_FAILURE);
3776573Sphitran }
3786573Sphitran break;
3796573Sphitran case DDI_RESUME:
3806573Sphitran case DDI_PM_RESUME:
3816573Sphitran return (DDI_SUCCESS);
3826573Sphitran default:
3836573Sphitran return (DDI_FAILURE);
3846573Sphitran }
3856573Sphitran
3866573Sphitran acpi_drv_dip = devi;
3876573Sphitran
3886573Sphitran /* Init ACPI related stuff */
3896573Sphitran if (acpi_drv_acpi_init() != ACPI_DRV_OK) {
3906573Sphitran goto error;
3916573Sphitran }
3926573Sphitran
3936573Sphitran /* Init kstat related stuff */
3946573Sphitran if (acpi_drv_kstat_init() != ACPI_DRV_OK) {
3956573Sphitran goto error;
3966573Sphitran }
3976573Sphitran
3988693SKerry.Shu@Sun.COM /* Create minor node for hotkey device. */
3998693SKerry.Shu@Sun.COM if (ddi_create_minor_node(devi, "hotkey", S_IFCHR, MINOR_HOTKEY(0),
4006573Sphitran DDI_PSEUDO, 0) == DDI_FAILURE) {
4018693SKerry.Shu@Sun.COM ACPI_DRV_DBG(CE_WARN, NULL, "hotkey: "
4026573Sphitran "minor node create failed");
4036573Sphitran goto error;
4046573Sphitran }
4056573Sphitran /* Create minor node for lid. */
4066573Sphitran if (ddi_create_minor_node(devi, "lid", S_IFCHR, MINOR_LID(0),
4076573Sphitran DDI_PSEUDO, 0) == DDI_FAILURE) {
4086573Sphitran ACPI_DRV_DBG(CE_WARN, NULL, "lid: minor node create failed");
4096573Sphitran goto error;
4106573Sphitran }
4116573Sphitran /* Create minor node for each battery and ac */
4126573Sphitran for (bp = &acpi_drv_cbat[0]; bp < &acpi_drv_cbat[ACPI_DRV_MAX_BAT_NUM];
4136573Sphitran bp++) {
4146573Sphitran if (bp->dev.valid) {
4156573Sphitran (void) snprintf(name, sizeof (name), "battery%d",
4166573Sphitran bp->dev.index);
4176573Sphitran if (ddi_create_minor_node(devi, name, S_IFCHR,
4186573Sphitran MINOR_BATT(bp->dev.index), DDI_PSEUDO, 0) ==
4196573Sphitran DDI_FAILURE) {
4206573Sphitran ACPI_DRV_DBG(CE_WARN, NULL,
4216573Sphitran "%s: minor node create failed", name);
4226573Sphitran goto error;
4236573Sphitran }
4246573Sphitran }
4256573Sphitran }
4266573Sphitran for (i = 0; i < nac; i++) {
4276573Sphitran (void) snprintf(name, sizeof (name), "ac%d", i);
4286573Sphitran if (ddi_create_minor_node(devi, name, S_IFCHR,
4296573Sphitran MINOR_AC(i), DDI_PSEUDO, 0) == DDI_FAILURE) {
4306573Sphitran ACPI_DRV_DBG(CE_WARN, NULL,
4316573Sphitran "%s: minor node create failed", name);
4326573Sphitran goto error;
4336573Sphitran }
4346573Sphitran }
4356573Sphitran
4366573Sphitran return (DDI_SUCCESS);
4376573Sphitran
4386573Sphitran error:
4396573Sphitran ddi_remove_minor_node(devi, NULL);
4406573Sphitran acpi_drv_kstat_fini();
4416573Sphitran acpi_drv_acpi_fini();
4426573Sphitran acpi_drv_dip = NULL;
4436573Sphitran return (DDI_FAILURE);
4446573Sphitran }
4456573Sphitran
4466573Sphitran static int
acpi_drv_detach(dev_info_t * devi,ddi_detach_cmd_t cmd)4476573Sphitran acpi_drv_detach(dev_info_t *devi, ddi_detach_cmd_t cmd)
4486573Sphitran {
4496573Sphitran if (cmd != DDI_DETACH) {
4506573Sphitran return (DDI_FAILURE);
4516573Sphitran }
4526573Sphitran
4536573Sphitran mutex_enter(&acpi_drv_mutex);
4546573Sphitran ddi_remove_minor_node(devi, NULL);
4556573Sphitran
4566573Sphitran acpi_drv_kstat_fini();
4576573Sphitran acpi_drv_acpi_fini();
4586573Sphitran mutex_exit(&acpi_drv_mutex);
4596573Sphitran return (DDI_SUCCESS);
4606573Sphitran }
4616573Sphitran
4626573Sphitran /* ARGSUSED */
4636573Sphitran static int
acpi_drv_getinfo(dev_info_t * dip,ddi_info_cmd_t cmd,void * arg,void ** resultp)4646573Sphitran acpi_drv_getinfo(dev_info_t *dip, ddi_info_cmd_t cmd, void *arg, void **resultp)
4656573Sphitran {
4666573Sphitran switch (cmd) {
4676573Sphitran case DDI_INFO_DEVT2DEVINFO:
4686573Sphitran *resultp = acpi_drv_dip;
4696573Sphitran return (DDI_SUCCESS);
4706573Sphitran case DDI_INFO_DEVT2INSTANCE:
4716573Sphitran *resultp = (void*) 0;
4726573Sphitran return (DDI_SUCCESS);
4736573Sphitran default:
4746573Sphitran return (DDI_FAILURE);
4756573Sphitran }
4766573Sphitran }
4776573Sphitran
4786573Sphitran /*ARGSUSED*/
4796573Sphitran static int
acpi_drv_open(dev_t * devp,int flag,int otyp,cred_t * crp)4806573Sphitran acpi_drv_open(dev_t *devp, int flag, int otyp, cred_t *crp)
4816573Sphitran {
4826573Sphitran if (acpi_drv_dip == NULL) {
4836573Sphitran return (ENXIO);
4846573Sphitran }
4856573Sphitran
4866573Sphitran return (0);
4876573Sphitran }
4886573Sphitran
4896573Sphitran /*ARGSUSED*/
4906573Sphitran static int
acpi_drv_close(dev_t dev,int flag,int otyp,cred_t * crp)4916573Sphitran acpi_drv_close(dev_t dev, int flag, int otyp, cred_t *crp)
4926573Sphitran {
4936573Sphitran return (0);
4946573Sphitran }
4956573Sphitran
4966573Sphitran /*ARGSUSED*/
4976573Sphitran static int
acpi_drv_ioctl(dev_t dev,int cmd,intptr_t arg,int mode,cred_t * cr,int * rval)4986573Sphitran acpi_drv_ioctl(dev_t dev, int cmd, intptr_t arg, int mode, cred_t *cr,
4996573Sphitran int *rval)
5006573Sphitran {
5016573Sphitran int minor;
5026573Sphitran int type, index;
5036573Sphitran int res = 0;
5046573Sphitran
5056573Sphitran minor = getminor(dev);
5066573Sphitran type = MINOR2TYPE(minor);
5076573Sphitran index = MINOR2IDX(minor);
5086573Sphitran
5096573Sphitran mutex_enter(&acpi_drv_mutex);
5106573Sphitran
5116573Sphitran switch (type) {
5126573Sphitran case ACPI_DRV_TYPE_CBAT:
5136573Sphitran res = acpi_drv_cbat_ioctl(index, cmd, arg, mode, cr, rval);
5146573Sphitran break;
5156573Sphitran case ACPI_DRV_TYPE_AC:
5166573Sphitran res = acpi_drv_ac_ioctl(index, cmd, arg, mode, cr, rval);
5176573Sphitran break;
5186573Sphitran case ACPI_DRV_TYPE_LID:
5196573Sphitran res = acpi_drv_lid_ioctl(index, cmd, arg, mode, cr, rval);
5206573Sphitran break;
5218693SKerry.Shu@Sun.COM case ACPI_DRV_TYPE_HOTKEY:
5228693SKerry.Shu@Sun.COM res = acpi_drv_hotkey_ioctl(cmd, arg, mode, cr, rval);
5236573Sphitran break;
5246573Sphitran default:
5256573Sphitran res = EINVAL;
5266573Sphitran break;
5276573Sphitran }
5286573Sphitran
5296573Sphitran mutex_exit(&acpi_drv_mutex);
5306573Sphitran return (res);
5316573Sphitran }
5326573Sphitran
5336573Sphitran /*ARGSUSED*/
5346573Sphitran static int
acpi_drv_cbat_ioctl(int index,int cmd,intptr_t arg,int mode,cred_t * cr,int * rval)5356573Sphitran acpi_drv_cbat_ioctl(int index, int cmd, intptr_t arg, int mode, cred_t *cr,
5366573Sphitran int *rval)
5376573Sphitran {
5386573Sphitran int res = 0;
5396573Sphitran acpi_drv_warn_t bwarn;
5406573Sphitran struct acpi_drv_cbat_state *bp;
5416573Sphitran
5426573Sphitran ASSERT(mutex_owned(&acpi_drv_mutex));
5436573Sphitran
5446573Sphitran bp = acpi_drv_idx2cbat(index);
5456573Sphitran if (!bp || bp->dev.valid != 1) {
5466573Sphitran return (ENXIO);
5476573Sphitran }
5486573Sphitran
5496573Sphitran switch (cmd) {
5506573Sphitran /*
5516573Sphitran * Return _BIF(Battery Information) of battery[index],
5526573Sphitran * if battery plugged.
5536573Sphitran */
5546573Sphitran case ACPI_DRV_IOC_INFO:
5556573Sphitran if (bp->dev.present == 0) {
5566573Sphitran res = ENXIO;
5576573Sphitran break;
5586573Sphitran }
5596573Sphitran
5606573Sphitran res = acpi_drv_update_bif(bp);
5616573Sphitran if (res != ACPI_DRV_OK) {
5626573Sphitran break;
5636573Sphitran }
5646573Sphitran if (copyout(&bp->bif_cache, (void *)arg,
5656573Sphitran sizeof (bp->bif_cache))) {
5666573Sphitran res = EFAULT;
5676573Sphitran }
5686573Sphitran break;
5696573Sphitran
5706573Sphitran /*
5716573Sphitran * Return _BST(Battery Status) of battery[index],
5726573Sphitran * if battery plugged.
5736573Sphitran */
5746573Sphitran case ACPI_DRV_IOC_STATUS:
5756573Sphitran if (bp->dev.present == 0) {
5766573Sphitran res = ENXIO;
5776573Sphitran break;
5786573Sphitran }
5796573Sphitran
5806573Sphitran res = acpi_drv_update_bst(bp);
5816573Sphitran if (res != ACPI_DRV_OK) {
5826573Sphitran break;
5836573Sphitran }
5846573Sphitran if (copyout(&bp->bst_cache, (void *)arg,
5856573Sphitran sizeof (bp->bst_cache))) {
5866573Sphitran res = EFAULT;
5876573Sphitran }
5886573Sphitran break;
5896573Sphitran
5906573Sphitran /* Return the state of the battery bays in the system */
5916573Sphitran case ACPI_DRV_IOC_BAY:
5926573Sphitran {
5936573Sphitran batt_bay_t bay;
5946573Sphitran
5956573Sphitran bay.bay_number = nbat;
5966573Sphitran bay.battery_map = 0;
5976573Sphitran for (bp = &acpi_drv_cbat[0];
5986573Sphitran bp < &acpi_drv_cbat[ACPI_DRV_MAX_BAT_NUM]; bp++) {
5996573Sphitran if (bp->dev.valid) {
6006573Sphitran if (bp->dev.present) {
6016573Sphitran bay.battery_map |=
6026573Sphitran (1 << bp->dev.index);
6036573Sphitran }
6046573Sphitran }
6056573Sphitran }
6066573Sphitran if (copyout(&bay, (void *)arg, sizeof (bay))) {
6076573Sphitran res = EFAULT;
6086573Sphitran break;
6096573Sphitran }
6106573Sphitran }
6116573Sphitran break;
6126573Sphitran
6136573Sphitran /*
6146573Sphitran * Return the current power source device if available:
6156573Sphitran * 0 -- battery supplying power
6166573Sphitran * 1 -- AC supplying power
6176573Sphitran */
6186573Sphitran case ACPI_DRV_IOC_POWER_STATUS:
6196573Sphitran {
6206573Sphitran int val;
6216573Sphitran
6226573Sphitran /* State not available */
6236573Sphitran if (acpi_drv_psr_type == ACPI_DRV_TYPE_UNKNOWN) {
6246573Sphitran res = ENXIO;
6256573Sphitran break;
6266573Sphitran }
6276573Sphitran val = (acpi_drv_psr_type == ACPI_DRV_TYPE_AC) ? 1 : 0;
6286573Sphitran if (copyout(&val, (void *)arg, sizeof (val))) {
6296573Sphitran res = EFAULT;
6306573Sphitran break;
6316573Sphitran }
6326573Sphitran }
6336573Sphitran break;
6346573Sphitran
6356573Sphitran /* Get charge-warn and charge-low levels for the whole system */
6366573Sphitran case ACPI_DRV_IOC_GET_WARNING:
6376573Sphitran bwarn.bw_enabled = acpi_drv_warn_enabled;
6386573Sphitran bwarn.bw_charge_warn = acpi_drv_syn_warn_per;
6396573Sphitran bwarn.bw_charge_low = acpi_drv_syn_low_per;
6406573Sphitran if (copyout(&bwarn, (void *)arg, sizeof (&bwarn))) {
6416573Sphitran res = EFAULT;
6426573Sphitran }
6436573Sphitran break;
6446573Sphitran
6456573Sphitran /* Set charge-warn and charge-low levels for the whole system */
6466573Sphitran case ACPI_DRV_IOC_SET_WARNING:
6476573Sphitran if (drv_priv(cr)) {
6486573Sphitran res = EPERM;
6496573Sphitran break;
6506573Sphitran }
6516573Sphitran if (copyin((void *)arg, &bwarn, sizeof (bwarn))) {
6526573Sphitran res = EFAULT;
6536573Sphitran break;
6546573Sphitran }
6556573Sphitran res = acpi_drv_set_warn(&bwarn);
6566573Sphitran break;
6576573Sphitran
6586573Sphitran default:
6596573Sphitran res = EINVAL;
6606573Sphitran break;
6616573Sphitran }
6626573Sphitran
6636573Sphitran return (res);
6646573Sphitran }
6656573Sphitran
6666573Sphitran /*ARGSUSED*/
6676573Sphitran static int
acpi_drv_ac_ioctl(int index,int cmd,intptr_t arg,int mode,cred_t * cr,int * rval)6686573Sphitran acpi_drv_ac_ioctl(int index, int cmd, intptr_t arg, int mode, cred_t *cr,
6696573Sphitran int *rval)
6706573Sphitran {
6716573Sphitran int res = 0;
6726573Sphitran int ac_state;
6736573Sphitran struct acpi_drv_ac_state *acp;
6746573Sphitran
6756573Sphitran ASSERT(mutex_owned(&acpi_drv_mutex));
6766573Sphitran
6776573Sphitran acp = acpi_drv_idx2ac(index);
6786573Sphitran if (!acp || acp->dev.valid != 1) {
6796573Sphitran return (ENXIO);
6806573Sphitran }
6816573Sphitran
6826573Sphitran switch (cmd) {
6836573Sphitran /* Return the number of AC adapters in the system */
6846573Sphitran case ACPI_DRV_IOC_AC_COUNT:
6856573Sphitran if (copyout(&nac, (void *)arg, sizeof (nac))) {
6866573Sphitran res = EFAULT;
6876573Sphitran }
6886573Sphitran break;
6896573Sphitran
6906573Sphitran /*
6916573Sphitran * Return the state of AC[index] if available:
6926573Sphitran * 0 -- Off-line
6936573Sphitran * 1 -- On-line
6946573Sphitran */
6956573Sphitran case ACPI_DRV_IOC_POWER_STATUS:
6966573Sphitran if (!acp || acp->dev.valid != 1) {
6976573Sphitran res = ENXIO;
6986573Sphitran break;
6996573Sphitran }
7006573Sphitran /* State not available */
7016573Sphitran if ((ac_state = acpi_drv_ac_present(acp)) == -1) {
7026573Sphitran res = ENXIO;
7036573Sphitran break;
7046573Sphitran }
7056573Sphitran if (copyout(&ac_state, (void *)arg, sizeof (ac_state))) {
7066573Sphitran res = EFAULT;
7076573Sphitran }
7086573Sphitran break;
7096573Sphitran
7106573Sphitran default:
7116573Sphitran res = EINVAL;
7126573Sphitran break;
7136573Sphitran }
7146573Sphitran
7156573Sphitran return (res);
7166573Sphitran }
7176573Sphitran
7186573Sphitran /*ARGSUSED*/
7196573Sphitran static int
acpi_drv_lid_ioctl(int index,int cmd,intptr_t arg,int mode,cred_t * cr,int * rval)7206573Sphitran acpi_drv_lid_ioctl(int index, int cmd, intptr_t arg, int mode, cred_t *cr,
7216573Sphitran int *rval)
7226573Sphitran {
7236573Sphitran int res = 0;
7246573Sphitran
7257651SPhi.Tran@Sun.COM /*
7267651SPhi.Tran@Sun.COM * lid.state 0 means lid is closed.
7277651SPhi.Tran@Sun.COM * lid.state non-zero means lid is open.
7287651SPhi.Tran@Sun.COM */
7296573Sphitran switch (cmd) {
7306573Sphitran case ACPI_DRV_IOC_LID_STATUS:
7316573Sphitran if (lid.state_ok == ACPI_DRV_NTF_UNKNOWN) {
7326573Sphitran /* State not available */
7336573Sphitran res = acpi_drv_update_lid(&lid.dev);
7346573Sphitran if (res != ACPI_DRV_OK) {
7356573Sphitran res = ENXIO;
7366573Sphitran break;
7376573Sphitran }
7386573Sphitran }
7396573Sphitran if (copyout(&lid.state, (void *)arg, sizeof (lid.state))) {
7406573Sphitran res = EFAULT;
7417651SPhi.Tran@Sun.COM }
7427651SPhi.Tran@Sun.COM break;
7437651SPhi.Tran@Sun.COM case ACPI_DRV_IOC_LID_UPDATE:
7447651SPhi.Tran@Sun.COM res = acpi_drv_update_lid(&lid.dev);
7457651SPhi.Tran@Sun.COM if (res != ACPI_DRV_OK) {
7467651SPhi.Tran@Sun.COM res = ENXIO;
7476573Sphitran break;
7486573Sphitran }
7497651SPhi.Tran@Sun.COM if (copyout(&lid.state, (void *)arg, sizeof (lid.state))) {
7507651SPhi.Tran@Sun.COM res = EFAULT;
7517651SPhi.Tran@Sun.COM }
7526573Sphitran break;
7536573Sphitran
7546573Sphitran default:
7556573Sphitran res = EINVAL;
7566573Sphitran break;
7576573Sphitran }
7586573Sphitran return (res);
7596573Sphitran }
7606573Sphitran
7616573Sphitran /*ARGSUSED*/
7626573Sphitran static int
acpi_drv_chpoll(dev_t dev,short events,int anyyet,short * reventsp,struct pollhead ** phpp)7636573Sphitran acpi_drv_chpoll(dev_t dev, short events, int anyyet, short *reventsp,
7646573Sphitran struct pollhead **phpp)
7656573Sphitran {
7666573Sphitran if (!anyyet) {
7676573Sphitran *phpp = &acpi_drv_pollhead;
7686573Sphitran }
7696573Sphitran *reventsp = 0;
7706573Sphitran return (0);
7716573Sphitran }
7726573Sphitran
7736573Sphitran #ifdef DEBUG
7746573Sphitran static void
acpi_drv_printf(struct acpi_drv_dev * devp,uint_t lev,const char * fmt,...)7756573Sphitran acpi_drv_printf(struct acpi_drv_dev *devp, uint_t lev,
7766573Sphitran const char *fmt, ...)
7776573Sphitran {
7786573Sphitran va_list args;
7796573Sphitran
7806573Sphitran mutex_enter(&acpi_drv_prt_mutex);
7816573Sphitran
7826573Sphitran va_start(args, fmt);
7836573Sphitran (void) vsprintf(acpi_drv_prt_buf, fmt, args);
7846573Sphitran va_end(args);
7856573Sphitran
7866573Sphitran if (devp) {
7876573Sphitran cmn_err(lev, "%s.%s: %s", devp->hid, devp->uid,
7886573Sphitran acpi_drv_prt_buf);
7896573Sphitran } else {
7906573Sphitran cmn_err(lev, "%s", acpi_drv_prt_buf);
7916573Sphitran }
7926573Sphitran mutex_exit(&acpi_drv_prt_mutex);
7936573Sphitran }
7946573Sphitran
7956573Sphitran static void
acpi_drv_prt_notify(ACPI_HANDLE hdl,UINT32 val)7966573Sphitran acpi_drv_prt_notify(ACPI_HANDLE hdl, UINT32 val)
7976573Sphitran {
7986573Sphitran ACPI_BUFFER buf;
7996573Sphitran char str[1024];
8006573Sphitran
8016573Sphitran buf.Length = sizeof (str);
8026573Sphitran buf.Pointer = str;
80311387SSurya.Prakki@Sun.COM (void) AcpiGetName(hdl, ACPI_FULL_PATHNAME, &buf);
8046573Sphitran cmn_err(CE_NOTE, "AcpiNotify(%s, 0x%02x)", str, val);
8056573Sphitran }
8066573Sphitran #endif /* DEBUG */
8076573Sphitran
8088693SKerry.Shu@Sun.COM void
acpi_drv_gen_sysevent(struct acpi_drv_dev * devp,char * ev,uint32_t val)8096573Sphitran acpi_drv_gen_sysevent(struct acpi_drv_dev *devp, char *ev, uint32_t val)
8106573Sphitran {
8116573Sphitran nvlist_t *attr_list = NULL;
8126573Sphitran int err;
8136573Sphitran char pathname[MAXPATHLEN];
8146573Sphitran
8156573Sphitran /* Allocate and build sysevent attribute list */
8166573Sphitran err = nvlist_alloc(&attr_list, NV_UNIQUE_NAME_TYPE, DDI_NOSLEEP);
8176573Sphitran if (err != 0) {
8186573Sphitran ACPI_DRV_DBG(CE_WARN, NULL,
8196573Sphitran "cannot allocate memory for sysevent attributes\n");
8206573Sphitran return;
8216573Sphitran }
8226573Sphitran
8236573Sphitran /* Add attributes */
8246573Sphitran err = nvlist_add_string(attr_list, PWRCTL_DEV_HID, devp->hid);
8256573Sphitran if (err != 0) {
8266573Sphitran ACPI_DRV_DBG(CE_WARN, NULL,
8276573Sphitran "Failed to add attr [%s] for %s/%s event",
8286573Sphitran PWRCTL_DEV_HID, EC_PWRCTL, ev);
8296573Sphitran nvlist_free(attr_list);
8306573Sphitran return;
8316573Sphitran }
8326573Sphitran
8336573Sphitran err = nvlist_add_string(attr_list, PWRCTL_DEV_UID, devp->uid);
8346573Sphitran if (err != 0) {
8356573Sphitran ACPI_DRV_DBG(CE_WARN, NULL,
8366573Sphitran "Failed to add attr [%s] for %s/%s event",
8376573Sphitran PWRCTL_DEV_UID, EC_PWRCTL, ev);
8386573Sphitran nvlist_free(attr_list);
8396573Sphitran return;
8406573Sphitran }
8416573Sphitran
8426573Sphitran err = nvlist_add_uint32(attr_list, PWRCTL_DEV_INDEX, devp->index);
8436573Sphitran if (err != 0) {
8446573Sphitran ACPI_DRV_DBG(CE_WARN, NULL,
8456573Sphitran "Failed to add attr [%s] for %s/%s event",
8466573Sphitran PWRCTL_DEV_INDEX, EC_PWRCTL, ev);
8476573Sphitran nvlist_free(attr_list);
8486573Sphitran return;
8496573Sphitran }
8506573Sphitran
8516573Sphitran (void) ddi_pathname(acpi_drv_dip, pathname);
8526573Sphitran err = nvlist_add_string(attr_list, PWRCTL_DEV_PHYS_PATH, pathname);
8536573Sphitran if (err != 0) {
8546573Sphitran ACPI_DRV_DBG(CE_WARN, NULL,
8556573Sphitran "Failed to add attr [%s] for %s/%s event",
8566573Sphitran PWRCTL_DEV_PHYS_PATH, EC_PWRCTL, ev);
8576573Sphitran nvlist_free(attr_list);
8586573Sphitran return;
8596573Sphitran }
8606573Sphitran
8616573Sphitran if (strcmp(ev, ESC_PWRCTL_WARN) && strcmp(ev, ESC_PWRCTL_LOW)) {
8626573Sphitran goto finish;
8636573Sphitran }
8646573Sphitran
8656573Sphitran err = nvlist_add_uint32(attr_list, PWRCTL_CHARGE_LEVEL, val);
8666573Sphitran if (err != 0) {
8676573Sphitran ACPI_DRV_DBG(CE_WARN, NULL,
8686573Sphitran "Failed to add attr [%s] for %s/%s event",
8696573Sphitran PWRCTL_CHARGE_LEVEL, EC_PWRCTL, ev);
8706573Sphitran nvlist_free(attr_list);
8716573Sphitran return;
8726573Sphitran }
8736573Sphitran
8746573Sphitran finish:
8756573Sphitran ACPI_DRV_DBG(CE_NOTE, NULL, "SysEv(%s, %s.%s, %d)",
8766573Sphitran ev, devp->hid, devp->uid, val);
8776573Sphitran /* Generate/log sysevent */
8786573Sphitran err = ddi_log_sysevent(acpi_drv_dip, DDI_VENDOR_SUNW, EC_PWRCTL,
8796573Sphitran ev, attr_list, NULL, DDI_NOSLEEP);
8806573Sphitran #ifdef DEBUG
8816573Sphitran if (err != DDI_SUCCESS) {
8826573Sphitran ACPI_DRV_DBG(CE_WARN, NULL,
8836573Sphitran "cannot log sysevent, err code %x\n", err);
8846573Sphitran }
8856573Sphitran #endif
8866573Sphitran
8876573Sphitran nvlist_free(attr_list);
8886573Sphitran }
8896573Sphitran
8906573Sphitran static int
acpi_drv_obj_copy(ACPI_OBJECT * op,char * bp,struct obj_desc * dp)8916573Sphitran acpi_drv_obj_copy(ACPI_OBJECT *op, char *bp, struct obj_desc *dp)
8926573Sphitran {
8936573Sphitran ACPI_OBJECT *ep;
8946573Sphitran char *fp;
8956573Sphitran
8966573Sphitran ep = &op->Package.Elements[0];
8976573Sphitran for (; dp->offset != -1; dp++) {
8986573Sphitran fp = bp + dp->offset;
8996573Sphitran if (dp->type == ACPI_TYPE_INTEGER &&
9006573Sphitran ep->Type == dp->type) {
9016573Sphitran #ifdef DEBUG
9026573Sphitran if (dp->size <= 4) {
9036573Sphitran ACPI_DRV_DBG(CE_NOTE, NULL, "\t%s: %u",
9046573Sphitran dp->name,
9056573Sphitran (uint32_t)ep->Integer.Value);
9066573Sphitran } else {
9076573Sphitran #ifdef _LP64
9086573Sphitran ACPI_DRV_DBG(CE_NOTE, NULL, "\t%s: %lu",
9096573Sphitran dp->name, (uint64_t)ep->Integer.Value);
9106573Sphitran }
9116573Sphitran #else
9126573Sphitran ACPI_DRV_DBG(CE_NOTE, NULL, "\t%s: %llu",
9136573Sphitran dp->name, (uint64_t)ep->Integer.Value);
9146573Sphitran }
9156573Sphitran #endif /* _LP64 */
9166573Sphitran #endif /* DEBUG */
9176573Sphitran *(uint32_t *)fp = ep->Integer.Value;
9186573Sphitran } else if (dp->type == ACPI_TYPE_STRING &&
9196573Sphitran ep->Type == dp->type) {
9206573Sphitran ACPI_DRV_DBG(CE_NOTE, NULL, "\t%s: \"%s\"",
9216573Sphitran dp->name, ep->String.Pointer);
922*12004Sjiang.liu@intel.com (void) strlcpy(fp, ep->String.Pointer, dp->size);
9236573Sphitran } else if (dp->type == ACPI_TYPE_STRING &&
9246573Sphitran ep->Type == ACPI_TYPE_BUFFER) {
9256573Sphitran #ifdef DEBUG
9266573Sphitran int len;
9276573Sphitran char buf[MAXNAMELEN + 1];
9286573Sphitran
9296573Sphitran len = (MAXNAMELEN < ep->Buffer.Length) ?
9306573Sphitran MAXNAMELEN : ep->Buffer.Length;
9316573Sphitran bcopy(ep->Buffer.Pointer, buf, len);
9326573Sphitran buf[len] = 0;
9336573Sphitran ACPI_DRV_DBG(CE_NOTE, NULL, "\t%s: [%d] \"%s\"",
9346573Sphitran dp->name, len, buf);
9356573Sphitran #endif
9366573Sphitran
9376573Sphitran ASSERT(MAXNAMELEN >= ep->Buffer.Length);
9386573Sphitran bcopy(ep->Buffer.Pointer, fp, ep->Buffer.Length);
9396573Sphitran } else {
9406573Sphitran ACPI_DRV_DBG(CE_WARN, NULL,
9416573Sphitran "Bad field at offset %d: type %d",
9426573Sphitran dp->offset, ep->Type);
9436573Sphitran if (dp->type != ACPI_TYPE_STRING) {
9446573Sphitran return (ACPI_DRV_ERR);
9456573Sphitran }
9466573Sphitran }
9476573Sphitran ep++;
9486573Sphitran }
9496573Sphitran
9506573Sphitran return (ACPI_DRV_OK);
9516573Sphitran }
9526573Sphitran
9536573Sphitran /*
9546573Sphitran * Returns the current power source devices. Used for the AC adapter and is
9556573Sphitran * located under the AC adapter object in name space. Used to determine if
9566573Sphitran * system is running off the AC adapter. This will report that the system is
9576573Sphitran * not running on the AC adapter if any of the batteries in the system is
9586573Sphitran * being forced to discharge through _BMC.
9596573Sphitran *
9606573Sphitran * Return value:
9616573Sphitran * 0 -- Off-line, ie. battery supplying system power
9626573Sphitran * 1 -- On-line, ie. AC supplying system power
9636573Sphitran * -1 -- Unknown, some error ocurred.
9646573Sphitran * Note: It will also update the driver ac state.
9656573Sphitran */
9666573Sphitran static int
acpi_drv_get_psr(struct acpi_drv_ac_state * acp)9676573Sphitran acpi_drv_get_psr(struct acpi_drv_ac_state *acp)
9686573Sphitran {
9696573Sphitran struct acpi_drv_dev *devp = &acp->dev;
9706573Sphitran int ac;
9716573Sphitran
9726573Sphitran if (!devp->valid) {
9736573Sphitran ACPI_DRV_DBG(CE_WARN, NULL, "device not valid");
9746573Sphitran return (-1);
9756573Sphitran }
9766573Sphitran
9776573Sphitran if (acpica_eval_int(devp->hdl, "_PSR", &ac) == AE_OK) {
9786573Sphitran ACPI_DRV_DBG(CE_NOTE, devp, "_PSR = %d", ac);
9796573Sphitran devp->present = ac;
9806573Sphitran } else {
9816573Sphitran ACPI_DRV_DBG(CE_WARN, NULL, "AcpiEval _PSR failed");
9826573Sphitran devp->present = -1;
9836573Sphitran }
9846573Sphitran
9856573Sphitran return (ac);
9866573Sphitran }
9876573Sphitran
9886573Sphitran /*
9896573Sphitran * For most systems, the _STA for this device will always
9906573Sphitran * return a value with bits 0-3 set and will toggle bit 4
9916573Sphitran * to indicate the actual presence of a battery.
9926573Sphitran *
9936573Sphitran * Return value:
9946573Sphitran * 0 -- battery not present
9956573Sphitran * 1 -- battery present
9966573Sphitran * -1 -- Unknown, some error ocurred.
9976573Sphitran * Note: It will also update the driver cbat state.
9986573Sphitran */
9996573Sphitran static int
acpi_drv_get_sta(struct acpi_drv_cbat_state * bp)10006573Sphitran acpi_drv_get_sta(struct acpi_drv_cbat_state *bp)
10016573Sphitran {
10026573Sphitran struct acpi_drv_dev *devp = &bp->dev;
10036573Sphitran int val;
10046573Sphitran
10056573Sphitran if (!devp->valid) {
10066573Sphitran ACPI_DRV_DBG(CE_WARN, NULL, "device not valid");
10076573Sphitran return (-1);
10086573Sphitran }
10096573Sphitran
10106573Sphitran if (acpica_eval_int(devp->hdl, "_STA", &val) == AE_OK) {
10116573Sphitran ACPI_DRV_DBG(CE_NOTE, devp, "_STA = 0x%x", val);
10126573Sphitran devp->present = ((val & STA_FLAG_BATT_PRESENT) != 0);
10136573Sphitran } else {
10146573Sphitran ACPI_DRV_DBG(CE_WARN, NULL, "AcpiEval _STA failed");
10156573Sphitran devp->present = -1;
10166573Sphitran }
10176573Sphitran
10186573Sphitran return (val);
10196573Sphitran }
10206573Sphitran
10216573Sphitran static int
acpi_drv_update_bif(struct acpi_drv_cbat_state * bp)10226573Sphitran acpi_drv_update_bif(struct acpi_drv_cbat_state *bp)
10236573Sphitran {
10246573Sphitran ACPI_BUFFER buf;
10256573Sphitran ACPI_OBJECT *objp;
10266573Sphitran
10276573Sphitran /* BIF is only available when battery plugged */
10286573Sphitran ASSERT(bp->dev.present != 0);
10296573Sphitran
10306573Sphitran /* Update internal BIF cache */
10316573Sphitran bp->bat_bifok = ACPI_DRV_NTF_UNKNOWN;
10326573Sphitran
10336573Sphitran buf.Length = ACPI_ALLOCATE_BUFFER;
10346573Sphitran if (ACPI_FAILURE(AcpiEvaluateObjectTyped(bp->dev.hdl, "_BIF",
10356573Sphitran NULL, &buf, ACPI_TYPE_PACKAGE))) {
10366573Sphitran ACPI_DRV_DBG(CE_WARN, NULL, "AcpiEval _BIF failed");
10376573Sphitran return (ACPI_DRV_ERR);
10386573Sphitran }
10396573Sphitran
10406573Sphitran objp = buf.Pointer;
10416573Sphitran ACPI_DRV_DBG(CE_NOTE, &bp->dev, "get _BIF");
10426573Sphitran if (acpi_drv_obj_copy(objp, (char *)&bp->bif_cache, bif_desc) ==
10436573Sphitran ACPI_DRV_ERR) {
10446573Sphitran AcpiOsFree(objp);
10456573Sphitran return (ACPI_DRV_ERR);
10466573Sphitran }
10476573Sphitran AcpiOsFree(objp);
10486573Sphitran bp->bat_bifok = ACPI_DRV_NTF_OK;
10496573Sphitran return (ACPI_DRV_OK);
10506573Sphitran }
10516573Sphitran
10526573Sphitran static int
acpi_drv_update_bst(struct acpi_drv_cbat_state * bp)10536573Sphitran acpi_drv_update_bst(struct acpi_drv_cbat_state *bp)
10546573Sphitran {
10556573Sphitran ACPI_BUFFER buf;
10566573Sphitran ACPI_OBJECT *objp;
10576573Sphitran
10586573Sphitran /* BST is only available when battery plugged */
10596573Sphitran ASSERT(bp->dev.present != 0);
10606573Sphitran
10616573Sphitran /* Update internal BST cache */
10626573Sphitran bp->bat_bstok = ACPI_DRV_NTF_UNKNOWN;
10636573Sphitran
10646573Sphitran buf.Length = ACPI_ALLOCATE_BUFFER;
10656573Sphitran if (ACPI_FAILURE(AcpiEvaluateObjectTyped(bp->dev.hdl, "_BST",
10666573Sphitran NULL, &buf, ACPI_TYPE_PACKAGE))) {
10676573Sphitran ACPI_DRV_DBG(CE_WARN, NULL, "AcpiEval _BST failed");
10686573Sphitran return (ACPI_DRV_ERR);
10696573Sphitran }
10706573Sphitran
10716573Sphitran objp = buf.Pointer;
10726573Sphitran ACPI_DRV_DBG(CE_NOTE, &bp->dev, "get _BST");
10736573Sphitran if (acpi_drv_obj_copy(objp, (char *)&bp->bst_cache, bst_desc) ==
10746573Sphitran ACPI_DRV_ERR) {
10756573Sphitran AcpiOsFree(objp);
10766573Sphitran return (ACPI_DRV_ERR);
10776573Sphitran }
10786573Sphitran AcpiOsFree(objp);
10796573Sphitran
10806573Sphitran if (bp->bst_cache.bst_rate == 0) {
10816573Sphitran bp->bst_cache.bst_state &= ~(ACPI_DRV_BST_CHARGING |
10826573Sphitran ACPI_DRV_BST_DISCHARGING);
10836573Sphitran }
10846573Sphitran bp->bat_bstok = ACPI_DRV_NTF_OK;
10856573Sphitran return (ACPI_DRV_OK);
10866573Sphitran }
10876573Sphitran
10886573Sphitran /*
10896573Sphitran * Return value:
10906573Sphitran * 1 -- device On-line
10916573Sphitran * 0 -- device Off-line
10926573Sphitran * -1 -- Unknown, some error ocurred.
10936573Sphitran */
10946573Sphitran static int
acpi_drv_dev_present(struct acpi_drv_dev * devp)10956573Sphitran acpi_drv_dev_present(struct acpi_drv_dev *devp)
10966573Sphitran {
10976573Sphitran if (!devp->valid) {
10986573Sphitran ACPI_DRV_DBG(CE_WARN, NULL, "device not valid");
10996573Sphitran return (-1);
11006573Sphitran }
11016573Sphitran
11026573Sphitran ASSERT(devp->type != ACPI_DRV_TYPE_UNKNOWN);
11036573Sphitran
11046573Sphitran /* Update the device state */
11056573Sphitran if (devp->present == -1) {
11066573Sphitran if (devp->type == ACPI_DRV_TYPE_AC) {
11076573Sphitran (void) acpi_drv_get_psr((struct acpi_drv_ac_state *)
11086573Sphitran devp);
11096573Sphitran } else if (devp->type == ACPI_DRV_TYPE_CBAT) {
11106573Sphitran (void) acpi_drv_get_sta((struct acpi_drv_cbat_state *)
11116573Sphitran devp);
11126573Sphitran }
11136573Sphitran }
11146573Sphitran
11156573Sphitran return (devp->present);
11166573Sphitran }
11176573Sphitran
11186573Sphitran /*
11196573Sphitran * Check if the device p existance state has changed.
11206573Sphitran * Return value:
11216573Sphitran * 1 -- changed
11226573Sphitran * 0 -- no change
11236573Sphitran * -1 -- unknown
11246573Sphitran */
11256573Sphitran static int
acpi_drv_update_present(struct acpi_drv_dev * p)11266573Sphitran acpi_drv_update_present(struct acpi_drv_dev *p)
11276573Sphitran {
11286573Sphitran int old_present = p->present;
11296573Sphitran int new_present;
11306573Sphitran
11316573Sphitran ASSERT(p && p->valid);
11326573Sphitran
11336573Sphitran p->present = -1;
11346573Sphitran new_present = acpi_drv_dev_present(p);
11356573Sphitran if (new_present == -1) {
11366573Sphitran return (-1);
11376573Sphitran }
11386573Sphitran if (new_present != old_present) {
11396573Sphitran return (1);
11406573Sphitran }
11416573Sphitran return (0);
11426573Sphitran }
11436573Sphitran
11446573Sphitran static void
acpi_drv_set_psr(struct acpi_drv_dev * p)11456573Sphitran acpi_drv_set_psr(struct acpi_drv_dev *p)
11466573Sphitran {
11476573Sphitran acpi_drv_psr_devp = p;
11486573Sphitran if (p != NULL) {
11496573Sphitran ACPI_DRV_DBG(CE_NOTE, p, "psr = .");
11506573Sphitran acpi_drv_psr_type = p->type;
11516573Sphitran } else {
11526573Sphitran ACPI_DRV_DBG(CE_NOTE, p, "psr = ?");
11536573Sphitran acpi_drv_psr_type = ACPI_DRV_TYPE_UNKNOWN;
11546573Sphitran }
11556573Sphitran }
11566573Sphitran
11576573Sphitran /*
11586573Sphitran * OSPM can determine independent warning and low battery
11596573Sphitran * capacity values based on the OEM-designed levels, but
11606573Sphitran * cannot set these values lower than the OEM-designed values.
11616573Sphitran */
11626573Sphitran static int
acpi_drv_set_warn(acpi_drv_warn_t * bwp)11636573Sphitran acpi_drv_set_warn(acpi_drv_warn_t *bwp)
11646573Sphitran {
11656573Sphitran uint32_t warn, low;
11666573Sphitran
11676573Sphitran warn = acpi_drv_syn_last_cap * bwp->bw_charge_warn / 100;
11686573Sphitran low = acpi_drv_syn_last_cap * bwp->bw_charge_low / 100;
11696573Sphitran
11706573Sphitran /* Update internal state */
11716573Sphitran if (bwp->bw_enabled) {
11726573Sphitran if (low >= warn || warn < acpi_drv_syn_oem_warn_cap ||
11736573Sphitran low < acpi_drv_syn_oem_low_cap) {
11746573Sphitran ACPI_DRV_DBG(CE_WARN, NULL, "charge level error");
11756573Sphitran return (EINVAL);
11766573Sphitran }
11776573Sphitran
11786573Sphitran ACPI_DRV_DBG(CE_NOTE, NULL, "set warn: warn=%d low=%d", warn,
11796573Sphitran low);
11806573Sphitran
11816573Sphitran acpi_drv_syn_warn_per = bwp->bw_charge_warn;
11826573Sphitran acpi_drv_syn_low_per = bwp->bw_charge_low;
11836573Sphitran acpi_drv_syn_warn_cap = warn;
11846573Sphitran acpi_drv_syn_low_cap = low;
11856573Sphitran acpi_drv_warn_enabled = 1;
11866573Sphitran } else {
11876573Sphitran acpi_drv_warn_enabled = 0;
11886573Sphitran }
11896573Sphitran
11906573Sphitran return (0);
11916573Sphitran }
11926573Sphitran
11936573Sphitran /*
11946573Sphitran * Update information for the synthesis battery
11956573Sphitran *
11966573Sphitran * Note: Sometimes the value to be returned from _BST or _BIF will be
11976573Sphitran * temporarily unknown. In this case, the method may return the value
11986573Sphitran * 0xFFFFFFFF as a placeholder. When the value becomes known, the
11996573Sphitran * appropriate notification (0x80 for _BST or 0x81 for BIF) should be
12006573Sphitran * issued, in like manner to any other change in the data returned by
12016573Sphitran * these methods. This will cause OSPM to re-evaluate the method obtaining
12026573Sphitran * the correct data value.
12036573Sphitran */
12046573Sphitran static void
acpi_drv_update_cap(int bif_changed)12056573Sphitran acpi_drv_update_cap(int bif_changed)
12066573Sphitran {
12076573Sphitran struct acpi_drv_cbat_state *bp;
12086573Sphitran
12096573Sphitran if (bif_changed != 0) {
12106573Sphitran acpi_drv_syn_oem_warn_cap = 0xffffffff;
12116573Sphitran acpi_drv_syn_oem_low_cap = 0xffffffff;
12126573Sphitran acpi_drv_syn_last_cap = 0xffffffff;
12136573Sphitran }
12146573Sphitran acpi_drv_syn_last_level = acpi_drv_syn_rem_cap;
12156573Sphitran acpi_drv_syn_rem_cap = 0xffffffff; /* initially unknown */
12166573Sphitran
12176573Sphitran for (bp = &acpi_drv_cbat[0]; bp < &acpi_drv_cbat[ACPI_DRV_MAX_BAT_NUM];
12186573Sphitran bp++) {
12196573Sphitran if (bp->dev.valid) {
12206573Sphitran /* Escape the empty bays */
12216573Sphitran if (acpi_drv_cbat_present(bp) <= 0) {
12226573Sphitran continue;
12236573Sphitran }
12246573Sphitran
12256573Sphitran if (bif_changed != 0 &&
12266573Sphitran bp->bat_bifok == ACPI_DRV_NTF_OK) {
12276573Sphitran acpi_bif_t *bif;
12286573Sphitran
12296573Sphitran bif = &bp->bif_cache;
12306573Sphitran
12316573Sphitran if (acpi_drv_syn_last_cap == 0xffffffff) {
12326573Sphitran acpi_drv_syn_last_cap = 0;
12336573Sphitran }
12346573Sphitran acpi_drv_syn_last_cap += bif->bif_last_cap;
12356573Sphitran
12366573Sphitran if (bif->bif_warn_cap == 0xffffffff ||
12376573Sphitran bif->bif_low_cap == 0xffffffff) {
12386573Sphitran ACPI_DRV_DBG(CE_WARN, &bp->dev,
12396573Sphitran "BIF value "
12406573Sphitran "invalid, warn_cap=0x%x "
12416573Sphitran "low_cap=0x%x", bif->bif_warn_cap,
12426573Sphitran bif->bif_low_cap);
12436573Sphitran continue;
12446573Sphitran }
12456573Sphitran if (acpi_drv_syn_oem_warn_cap == 0xffffffff) {
12466573Sphitran acpi_drv_syn_oem_warn_cap = 0;
12476573Sphitran }
12486573Sphitran if (acpi_drv_syn_oem_low_cap == 0xffffffff) {
12496573Sphitran acpi_drv_syn_oem_low_cap = 0;
12506573Sphitran }
12516573Sphitran
12526573Sphitran /*
12536573Sphitran * Use the highest level as the synthesis
12546573Sphitran * level.
12556573Sphitran */
12566573Sphitran if (bif->bif_warn_cap >
12576573Sphitran acpi_drv_syn_oem_warn_cap) {
12586573Sphitran acpi_drv_syn_oem_low_cap =
12596573Sphitran bif->bif_low_cap;
12606573Sphitran acpi_drv_syn_oem_warn_cap =
12616573Sphitran bif->bif_warn_cap;
12626573Sphitran }
12636573Sphitran }
12646573Sphitran #ifdef DEBUG
12656573Sphitran else if (bif_changed) {
12666573Sphitran ACPI_DRV_DBG(CE_NOTE, &bp->dev,
12676573Sphitran "BIF not ready");
12686573Sphitran }
12696573Sphitran #endif
12706573Sphitran
12716573Sphitran if (bp->bat_bstok == ACPI_DRV_NTF_OK) {
12726573Sphitran acpi_bst_t *bst;
12736573Sphitran
12746573Sphitran bst = &bp->bst_cache;
12756573Sphitran
12766573Sphitran /*
12776573Sphitran * Batteries that are rechargeable and are in
12786573Sphitran * the discharging state are required to return
12796573Sphitran * a valid Battery Present Rate value.
12806573Sphitran * 0xFFFFFFFF - Unknown rate/capacity
12816573Sphitran */
12826573Sphitran if (bst->bst_rem_cap == 0xffffffff) {
12836573Sphitran ACPI_DRV_DBG(CE_WARN, &bp->dev,
12846573Sphitran "BST value invalid, "
12856573Sphitran "rate=0x%x cap=0x%x",
12866573Sphitran bst->bst_rate, bst->bst_rem_cap);
12876573Sphitran continue;
12886573Sphitran }
12896573Sphitran
12906573Sphitran if (acpi_drv_syn_rem_cap == 0xffffffff) {
12916573Sphitran acpi_drv_syn_rem_cap = 0;
12926573Sphitran }
12936573Sphitran acpi_drv_syn_rem_cap += bst->bst_rem_cap;
12946573Sphitran /* Check for overflow */
12956573Sphitran ASSERT(acpi_drv_syn_rem_cap >=
12966573Sphitran bst->bst_rem_cap);
12976573Sphitran }
12986573Sphitran #ifdef DEBUG
12996573Sphitran else {
13006573Sphitran ACPI_DRV_DBG(CE_NOTE, &bp->dev,
13016573Sphitran "BST not ready");
13026573Sphitran }
13036573Sphitran #endif
13046573Sphitran }
13056573Sphitran }
13066573Sphitran
13076573Sphitran ACPI_DRV_DBG(CE_NOTE, NULL, "syn_cap: %d syn_oem_warn: %d "
13086573Sphitran "syn_oem_low: %d", acpi_drv_syn_rem_cap, acpi_drv_syn_oem_warn_cap,
13096573Sphitran acpi_drv_syn_oem_low_cap);
13106573Sphitran }
13116573Sphitran
13126573Sphitran static struct acpi_drv_cbat_state *
acpi_drv_idx2cbat(int idx)13136573Sphitran acpi_drv_idx2cbat(int idx)
13146573Sphitran {
13156573Sphitran if (idx >= ACPI_DRV_MAX_BAT_NUM) {
13166573Sphitran return (NULL);
13176573Sphitran }
13186573Sphitran return (&acpi_drv_cbat[idx]);
13196573Sphitran }
13206573Sphitran
13216573Sphitran static struct acpi_drv_ac_state *
acpi_drv_idx2ac(int idx)13226573Sphitran acpi_drv_idx2ac(int idx)
13236573Sphitran {
13246573Sphitran if (idx >= ACPI_DRV_MAX_AC_NUM) {
13256573Sphitran return (NULL);
13266573Sphitran }
13276573Sphitran return (&acpi_drv_ac[idx]);
13286573Sphitran }
13296573Sphitran
13306573Sphitran /*ARGSUSED*/
13316573Sphitran static void
acpi_drv_cbat_notify(ACPI_HANDLE hdl,UINT32 val,void * ctx)13326573Sphitran acpi_drv_cbat_notify(ACPI_HANDLE hdl, UINT32 val, void *ctx)
13336573Sphitran {
13346573Sphitran struct acpi_drv_cbat_state *bp = ctx;
13356573Sphitran struct acpi_drv_dev *devp = &bp->dev;
13366573Sphitran int bif_changed;
13376573Sphitran uint32_t eval;
13386573Sphitran char *ev;
13396573Sphitran acpi_bst_t *bst;
13406573Sphitran
13416573Sphitran mutex_enter(&acpi_drv_mutex);
13426573Sphitran ACPI_DRV_PRT_NOTIFY(hdl, val);
13436573Sphitran
13446573Sphitran switch (val) {
13456573Sphitran /*
13466573Sphitran * BST has changed
13476573Sphitran * Whenever the Battery State value changes, the
13486573Sphitran * system will generate an SCI to notify the OS.
13496573Sphitran *
13506573Sphitran * Note: trip point is not used to implement the
13516573Sphitran * warning levels.
13526573Sphitran */
13536573Sphitran case 0x80:
13546573Sphitran /*
13556573Sphitran * We always get 0x80 and 0x81 at battery plug/unplug,
13566573Sphitran * but 0x80 may come first. In case that situation, we have
13576573Sphitran * to update battery present state here too to update bst
13586573Sphitran * correctly.
13596573Sphitran */
13606573Sphitran bif_changed = acpi_drv_update_present(devp);
13616573Sphitran
13626573Sphitran if (devp->present == 0) {
13638291SPhi.Tran@Sun.COM if (acpi_drv_psr_devp == devp) {
13648291SPhi.Tran@Sun.COM acpi_drv_set_psr(NULL);
13658291SPhi.Tran@Sun.COM }
13668291SPhi.Tran@Sun.COM goto done;
13676573Sphitran }
13686573Sphitran
13696573Sphitran if (acpi_drv_update_bst(bp) != ACPI_DRV_OK) {
13706573Sphitran break;
13716573Sphitran }
13726573Sphitran acpi_drv_update_cap(bif_changed);
13736573Sphitran
13746573Sphitran bst = &bp->bst_cache;
13756573Sphitran eval = bst->bst_rem_cap;
13766573Sphitran
13776573Sphitran if (bst->bst_state & BST_FLAG_DISCHARGING) {
13786573Sphitran acpi_drv_set_psr(devp);
13796573Sphitran }
13806573Sphitran /*
13816573Sphitran * The Critical battery state indicates that all
13826573Sphitran * available batteries are discharged and do not
13836573Sphitran * appear to be able to supply power to run the
13846573Sphitran * system any longer. When this occurs, the OS
13856573Sphitran * should attempt to perform an emergency shutdown.
13866573Sphitran * Right now we do not shutdown. This would
13876573Sphitran * need some discussion first since it could be
13886573Sphitran * controversial.
13896573Sphitran */
13906573Sphitran #ifdef DEBUG
13916573Sphitran if (bst->bst_state & BST_FLAG_CRITICAL) {
13926573Sphitran ACPI_DRV_DBG(CE_WARN, devp, "BST_FLAG_CRITICAL set");
13936573Sphitran
13946573Sphitran /*
13956573Sphitran * BST_FLAG_CRITICAL may set even with AC,
13966573Sphitran * plugged, when plug/unplug battery. Check
13976573Sphitran * to avoid erroneous shutdown.
13986573Sphitran */
13996573Sphitran if (acpi_drv_psr_devp == devp &&
14006573Sphitran bst->bst_rem_cap != 0xffffffff) {
14016573Sphitran ACPI_DRV_DBG(CE_WARN, NULL,
14026573Sphitran "Battery in critical state");
14036573Sphitran }
14046573Sphitran } else
14056573Sphitran #endif
14066573Sphitran if (acpi_drv_warn_enabled &&
14076573Sphitran (bst->bst_state & BST_FLAG_DISCHARGING)) {
14086573Sphitran /*
14096573Sphitran * This value is an estimation of the amount of
14106573Sphitran * energy or battery capacity required by the
14116573Sphitran * system to transition to any supported sleeping
14126573Sphitran * state. When the OS detects that the total
14136573Sphitran * available battery capacity is less than this
14146573Sphitran * value, it will transition the system to a user
14156573Sphitran * defined system state (S1-S5).
14166573Sphitran */
14176573Sphitran if (acpi_drv_syn_last_level > acpi_drv_syn_low_cap &&
14186573Sphitran acpi_drv_syn_rem_cap <= acpi_drv_syn_low_cap) {
14196573Sphitran acpi_drv_gen_sysevent(devp, ESC_PWRCTL_LOW,
14206573Sphitran eval);
14216573Sphitran /*
14226573Sphitran * When the total available energy (mWh) or capacity
14236573Sphitran * (mAh) in the batteries falls below this level,
14246573Sphitran * the OS will notify the user through the UI.
14256573Sphitran */
14266573Sphitran } else if (acpi_drv_syn_last_level >
14276573Sphitran acpi_drv_syn_warn_cap &&
14286573Sphitran acpi_drv_syn_rem_cap <= acpi_drv_syn_warn_cap) {
14296573Sphitran acpi_drv_gen_sysevent(devp, ESC_PWRCTL_WARN,
14306573Sphitran eval);
14316573Sphitran }
14326573Sphitran }
14336573Sphitran
14348291SPhi.Tran@Sun.COM done:
14356573Sphitran acpi_drv_gen_sysevent(devp, ESC_PWRCTL_STATE_CHANGE, 0);
14366573Sphitran pollwakeup(&acpi_drv_pollhead, ACPI_DRV_EVENTS);
14376573Sphitran break;
14386573Sphitran
14396573Sphitran /* BIF has changed */
14406573Sphitran case 0x81:
14416573Sphitran /*
14426573Sphitran * Note: Do not eliminate multiple ADD/REMOVE here,
14436573Sphitran * because they may corresponding to different batterys.
14446573Sphitran */
14456573Sphitran (void) acpi_drv_update_present(devp);
14466573Sphitran if (devp->present == 1) {
14476573Sphitran if (acpi_drv_update_bif(bp) != ACPI_DRV_OK) {
14486573Sphitran break;
14496573Sphitran }
14506573Sphitran }
14516573Sphitran
14526573Sphitran acpi_drv_update_cap(1);
14536573Sphitran
14546573Sphitran eval = devp->present;
14556573Sphitran ev = eval ? ESC_PWRCTL_ADD : ESC_PWRCTL_REMOVE;
14566573Sphitran acpi_drv_gen_sysevent(devp, ev, 0);
14576573Sphitran pollwakeup(&acpi_drv_pollhead, ACPI_DRV_EVENTS);
14586573Sphitran break;
14596573Sphitran
14606573Sphitran case 0x82:
14616573Sphitran default:
14626573Sphitran break;
14636573Sphitran }
14646573Sphitran
14656573Sphitran mutex_exit(&acpi_drv_mutex);
14666573Sphitran }
14676573Sphitran
14686573Sphitran static int
acpi_drv_update_lid(struct acpi_drv_dev * p)14696573Sphitran acpi_drv_update_lid(struct acpi_drv_dev *p)
14706573Sphitran {
14716573Sphitran struct acpi_drv_lid_state *lp = (struct acpi_drv_lid_state *)p;
14726573Sphitran
14736573Sphitran if (acpica_eval_int(p->hdl, "_LID", &lp->state) == AE_OK) {
14746573Sphitran lp->state_ok = ACPI_DRV_NTF_OK;
14756573Sphitran return (ACPI_DRV_OK);
14766573Sphitran }
14776573Sphitran return (ACPI_DRV_ERR);
14786573Sphitran }
14796573Sphitran
14806573Sphitran /*ARGSUSED*/
14816573Sphitran static void
acpi_drv_ac_notify(ACPI_HANDLE hdl,UINT32 val,void * ctx)14826573Sphitran acpi_drv_ac_notify(ACPI_HANDLE hdl, UINT32 val, void *ctx)
14836573Sphitran {
14846573Sphitran struct acpi_drv_ac_state *acp = ctx;
14856573Sphitran struct acpi_drv_dev *devp = &acp->dev;
14866573Sphitran int old_present;
14876573Sphitran char *ev;
14886573Sphitran int eval;
14896573Sphitran
14906573Sphitran ACPI_DRV_PRT_NOTIFY(hdl, val);
14916573Sphitran if (val != 0x80) {
14926573Sphitran return;
14936573Sphitran }
14946573Sphitran
14956573Sphitran mutex_enter(&acpi_drv_mutex);
14966573Sphitran /*
14976573Sphitran * Note: if unplug and then quickly plug back, two ADD
14986573Sphitran * events will be generated.
14996573Sphitran */
15006573Sphitran old_present = devp->present;
15016573Sphitran eval = acpi_drv_get_psr(acp);
15026573Sphitran
15036573Sphitran /* Eliminate redundant events */
15046573Sphitran if (eval != -1 && eval != old_present) {
15056573Sphitran /* Keep tracking the current power source device */
15066573Sphitran if (eval == 1) {
15076573Sphitran ev = ESC_PWRCTL_ADD;
15086573Sphitran acpi_drv_set_psr(devp);
15096573Sphitran } else {
15106573Sphitran ev = ESC_PWRCTL_REMOVE;
15116573Sphitran /* If AC was supplying the power, it's not now */
15126573Sphitran if (acpi_drv_psr_devp == devp) {
15136573Sphitran acpi_drv_set_psr(NULL);
15146573Sphitran }
15156573Sphitran }
15166573Sphitran
15176573Sphitran acpi_drv_gen_sysevent(devp, ev, 0);
15186573Sphitran pollwakeup(&acpi_drv_pollhead, ACPI_DRV_EVENTS);
15196573Sphitran }
15206573Sphitran
15216573Sphitran mutex_exit(&acpi_drv_mutex);
15226573Sphitran }
15236573Sphitran
15246573Sphitran static void
acpi_drv_lid_notify(ACPI_HANDLE hdl,UINT32 val,void * ctx)15256573Sphitran acpi_drv_lid_notify(ACPI_HANDLE hdl, UINT32 val, void *ctx)
15266573Sphitran {
15276573Sphitran struct acpi_drv_lid_state *p = ctx;
15286573Sphitran
15296573Sphitran ACPI_DRV_PRT_NOTIFY(hdl, val);
15306573Sphitran if (val == 0x80) {
15316573Sphitran mutex_enter(&acpi_drv_mutex);
15326573Sphitran if (acpi_drv_update_lid(&p->dev) == ACPI_DRV_OK) {
15336573Sphitran acpi_drv_gen_sysevent(&p->dev, p->state ?
15346573Sphitran ESC_PWRCTL_ADD : ESC_PWRCTL_REMOVE, 0);
15356573Sphitran }
15366573Sphitran mutex_exit(&acpi_drv_mutex);
15376573Sphitran }
15386573Sphitran }
15396573Sphitran
15406573Sphitran static int
acpi_drv_obj_init(struct acpi_drv_dev * p)15416573Sphitran acpi_drv_obj_init(struct acpi_drv_dev *p)
15426573Sphitran {
15436573Sphitran ACPI_DEVICE_INFO *info;
15446573Sphitran ACPI_NOTIFY_HANDLER ntf_handler = NULL;
15456573Sphitran ACPI_STATUS ret;
15466573Sphitran
15476573Sphitran ASSERT(p != NULL && p->hdl != NULL);
15486573Sphitran
15496573Sphitran p->valid = 0;
15506573Sphitran
15516573Sphitran /* Info size is variable depending on existance of _CID */
155211225SDana.Myers@Sun.COM ret = AcpiGetObjectInfo(p->hdl, &info);
15536573Sphitran if (ACPI_FAILURE(ret)) {
15546573Sphitran ACPI_DRV_DBG(CE_WARN, NULL,
15556573Sphitran "AcpiGetObjectInfo() fail: %d", (int32_t)ret);
15566573Sphitran return (ACPI_DRV_ERR);
15576573Sphitran }
15586573Sphitran
15596573Sphitran if ((info->Valid & ACPI_VALID_HID) == 0) {
15606573Sphitran ACPI_DRV_DBG(CE_WARN, NULL,
15616573Sphitran "AcpiGetObjectInfo(): _HID not available");
1562*12004Sjiang.liu@intel.com p->hid[0] = 0;
15636573Sphitran } else {
1564*12004Sjiang.liu@intel.com (void) strlcpy(p->hid, info->HardwareId.String, ID_LEN);
15656573Sphitran }
15666573Sphitran
15676573Sphitran /*
15686573Sphitran * This object is optional, but is required when the device
15696573Sphitran * has no other way to report a persistent unique device ID.
15706573Sphitran */
15716573Sphitran if ((info->Valid & ACPI_VALID_UID) == 0) {
15726573Sphitran ACPI_DRV_DBG(CE_WARN, NULL,
15736573Sphitran "AcpiGetObjectInfo(): _UID not available");
15746573Sphitran /* Use 0 as the default _UID */
1575*12004Sjiang.liu@intel.com p->uid[0] = 0;
15766573Sphitran } else {
1577*12004Sjiang.liu@intel.com (void) strlcpy(p->uid, info->UniqueId.String, ID_LEN);
15786573Sphitran }
15796573Sphitran
158011225SDana.Myers@Sun.COM AcpiOsFree(info);
15816573Sphitran p->valid = 1;
15826573Sphitran
15836573Sphitran if (strcmp(p->hid, ACPI_DEVNAME_CBAT) == 0) {
15846573Sphitran struct acpi_drv_cbat_state *bp =
15856573Sphitran (struct acpi_drv_cbat_state *)p;
15866573Sphitran
15876573Sphitran p->type = ACPI_DRV_TYPE_CBAT;
15886573Sphitran p->index = nbat - 1;
15896573Sphitran
15906573Sphitran /* Update device present state */
15916573Sphitran (void) acpi_drv_update_present(p);
15926573Sphitran if (p->present) {
15936573Sphitran (void) acpi_drv_update_bif(bp);
15946573Sphitran (void) acpi_drv_update_bst(bp);
15956573Sphitran
15966573Sphitran /* Init the current power source */
15976573Sphitran if (bp->bst_cache.bst_state & BST_FLAG_DISCHARGING) {
15986573Sphitran acpi_drv_set_psr(p);
15996573Sphitran }
16006573Sphitran }
16016573Sphitran ntf_handler = acpi_drv_cbat_notify;
16026573Sphitran ACPI_DRV_DBG(CE_NOTE, p, "battery %s",
16036573Sphitran (p->present ? "present" : "absent"));
16046573Sphitran } else if (strcmp(p->hid, ACPI_DEVNAME_AC) == 0) {
16056573Sphitran p->type = ACPI_DRV_TYPE_AC;
16066573Sphitran p->index = nac - 1;
16076573Sphitran
16086573Sphitran /* Update device present state */
16096573Sphitran (void) acpi_drv_update_present(p);
16106573Sphitran if (p->present) {
16116573Sphitran /* Init the current power source */
16126573Sphitran acpi_drv_set_psr(p);
16136573Sphitran }
16146573Sphitran ntf_handler = acpi_drv_ac_notify;
16156573Sphitran ACPI_DRV_DBG(CE_NOTE, p, "AC %s",
16166573Sphitran (p->present ? "on-line" : "off-line"));
16176573Sphitran } else if (strcmp(p->hid, ACPI_DEVNAME_LID) == 0) {
16186573Sphitran p->type = ACPI_DRV_TYPE_LID;
16197051Sphitran p->index = 0;
16206573Sphitran lid.state_ok = ACPI_DRV_NTF_UNKNOWN;
16216573Sphitran (void) acpi_drv_update_lid(p);
16226573Sphitran ntf_handler = acpi_drv_lid_notify;
16236573Sphitran ACPI_DRV_DBG(CE_NOTE, p, "added");
16246573Sphitran } else {
16256573Sphitran ACPI_DRV_DBG(CE_NOTE, p, "unknown device");
16266573Sphitran p->valid = 0;
16276573Sphitran }
16286573Sphitran
16296573Sphitran /* Register ACPI battery related events */
16306573Sphitran if (ntf_handler != NULL) {
16316573Sphitran if (ACPI_FAILURE(AcpiInstallNotifyHandler(p->hdl,
16326573Sphitran ACPI_ALL_NOTIFY, ntf_handler, p))) {
16336573Sphitran ACPI_DRV_DBG(CE_NOTE, NULL,
16346573Sphitran "Notify handler for %s.%s install failed",
16356573Sphitran p->hid, p->uid);
16366573Sphitran return (ACPI_DRV_ERR);
16376573Sphitran }
16386573Sphitran }
16396573Sphitran
16406573Sphitran return (ACPI_DRV_OK);
16416573Sphitran }
16426573Sphitran
16436573Sphitran /*ARGSUSED*/
16446573Sphitran static ACPI_STATUS
acpi_drv_find_cb(ACPI_HANDLE ObjHandle,UINT32 NestingLevel,void * Context,void ** ReturnValue)16456573Sphitran acpi_drv_find_cb(ACPI_HANDLE ObjHandle, UINT32 NestingLevel, void *Context,
16466573Sphitran void **ReturnValue)
16476573Sphitran {
16487051Sphitran struct acpi_drv_dev *devp;
16497051Sphitran int *type = (int *)Context;
16506573Sphitran
16517051Sphitran if (*type == ACPI_DRV_TYPE_CBAT) {
16526573Sphitran struct acpi_drv_cbat_state *bp;
16536573Sphitran
16546573Sphitran if (nbat == ACPI_DRV_MAX_BAT_NUM) {
16556573Sphitran ACPI_DRV_DBG(CE_WARN, NULL,
16566573Sphitran "Need to support more batteries: "
16576573Sphitran "BATTERY_MAX = %d", ACPI_DRV_MAX_BAT_NUM);
16586573Sphitran return (AE_LIMIT);
16596573Sphitran }
16606573Sphitran bp = &acpi_drv_cbat[nbat++];
16616573Sphitran devp = (struct acpi_drv_dev *)bp;
16627051Sphitran } else if (*type == ACPI_DRV_TYPE_AC) {
16636573Sphitran struct acpi_drv_ac_state *ap;
16646573Sphitran
16656573Sphitran if (nac == ACPI_DRV_MAX_AC_NUM) {
16666573Sphitran ACPI_DRV_DBG(CE_WARN, NULL, "Need to support more ACs: "
16676573Sphitran "AC_MAX = %d", ACPI_DRV_MAX_AC_NUM);
16686573Sphitran return (AE_LIMIT);
16696573Sphitran }
16706573Sphitran ap = &acpi_drv_ac[nac++];
16716573Sphitran devp = (struct acpi_drv_dev *)ap;
16727051Sphitran } else if (*type == ACPI_DRV_TYPE_LID) {
16736573Sphitran struct acpi_drv_lid_state *lp;
16746573Sphitran
16757051Sphitran nlid++;
16766573Sphitran lp = &lid;
16776573Sphitran devp = (struct acpi_drv_dev *)lp;
16786573Sphitran } else {
16796573Sphitran ACPI_DRV_DBG(CE_WARN, NULL, "acpi_drv_find_cb(): "
16806573Sphitran "Unknown device");
16816573Sphitran return (AE_ERROR);
16826573Sphitran }
16836573Sphitran
16846573Sphitran devp->hdl = ObjHandle;
16856573Sphitran
16866573Sphitran /* Try to get as many working objs as possible */
16876573Sphitran (void) acpi_drv_obj_init(devp);
16886573Sphitran return (AE_OK);
16896573Sphitran }
16906573Sphitran
16916573Sphitran static int
acpi_drv_acpi_init()16926573Sphitran acpi_drv_acpi_init()
16936573Sphitran {
16947051Sphitran int *retp, type;
16957051Sphitran int status = ACPI_DRV_ERR;
16968693SKerry.Shu@Sun.COM hotkey_drv_t *htkp;
16976573Sphitran
16986573Sphitran /* Check to see if ACPI CA services are available */
16996573Sphitran if (AcpiSubsystemStatus() != AE_OK) {
17006573Sphitran ACPI_DRV_DBG(CE_WARN, NULL, "ACPI CA not ready");
17017051Sphitran return (status);
17026573Sphitran }
17036573Sphitran
17046573Sphitran /* Init Control Method Batterys */
17057051Sphitran type = ACPI_DRV_TYPE_CBAT;
17067051Sphitran if (ACPI_SUCCESS(AcpiGetDevices(ACPI_DEVNAME_CBAT, acpi_drv_find_cb,
17077051Sphitran &type, (void *)&retp)) && nbat) {
17087051Sphitran status = ACPI_DRV_OK;
17096573Sphitran }
17106573Sphitran
17116573Sphitran /* Init AC */
17127051Sphitran type = ACPI_DRV_TYPE_AC;
17137051Sphitran if (ACPI_SUCCESS(AcpiGetDevices(ACPI_DEVNAME_AC, acpi_drv_find_cb,
17147051Sphitran &type, (void *)&retp)) && nac) {
17157051Sphitran status = ACPI_DRV_OK;
17166573Sphitran }
17176573Sphitran
17186573Sphitran /* Init LID */
17197051Sphitran type = ACPI_DRV_TYPE_LID;
17207051Sphitran if (ACPI_SUCCESS(AcpiGetDevices(ACPI_DEVNAME_LID, acpi_drv_find_cb,
17217051Sphitran &type, (void *)&retp)) && nlid) {
17227051Sphitran status = ACPI_DRV_OK;
17236573Sphitran }
17246573Sphitran
17258693SKerry.Shu@Sun.COM /* Init Hotkey Device */
17268693SKerry.Shu@Sun.COM type = ACPI_DRV_TYPE_HOTKEY;
17278693SKerry.Shu@Sun.COM htkp = &acpi_hotkey;
17288693SKerry.Shu@Sun.COM bzero(htkp, sizeof (hotkey_drv_t));
17298693SKerry.Shu@Sun.COM htkp->dip = acpi_drv_dip;
17308693SKerry.Shu@Sun.COM htkp->hotkey_lock = &acpi_drv_mutex;
17318693SKerry.Shu@Sun.COM if (hotkey_init(htkp) == ACPI_DRV_OK) {
17327051Sphitran status = ACPI_DRV_OK;
17336573Sphitran }
17346573Sphitran
17356573Sphitran acpi_drv_update_cap(1);
17366573Sphitran
17377051Sphitran return (status);
17386573Sphitran }
17396573Sphitran
17406573Sphitran static void
acpi_drv_acpi_fini(void)17416573Sphitran acpi_drv_acpi_fini(void)
17426573Sphitran {
17436573Sphitran int i;
17446573Sphitran struct acpi_drv_cbat_state *bp;
17456573Sphitran
17466573Sphitran for (bp = &acpi_drv_cbat[0]; bp < &acpi_drv_cbat[ACPI_DRV_MAX_BAT_NUM];
17476573Sphitran bp++) {
17486573Sphitran if (bp->dev.valid) {
174911387SSurya.Prakki@Sun.COM (void) AcpiRemoveNotifyHandler(bp->dev.hdl,
175011387SSurya.Prakki@Sun.COM ACPI_DEVICE_NOTIFY, acpi_drv_cbat_notify);
17516573Sphitran }
17526573Sphitran }
17536573Sphitran for (i = 0; i < nac; i++) {
175411387SSurya.Prakki@Sun.COM (void) AcpiRemoveNotifyHandler(acpi_drv_ac[i].dev.hdl,
17556573Sphitran ACPI_DEVICE_NOTIFY, acpi_drv_ac_notify);
17566573Sphitran }
175711387SSurya.Prakki@Sun.COM (void) AcpiRemoveNotifyHandler(lid.dev.hdl, ACPI_DEVICE_NOTIFY,
17586573Sphitran acpi_drv_lid_notify);
17598693SKerry.Shu@Sun.COM
17608693SKerry.Shu@Sun.COM if (acpi_hotkey.hotkey_method != HOTKEY_METHOD_NONE)
17618693SKerry.Shu@Sun.COM (void) hotkey_fini(&acpi_hotkey);
17626573Sphitran }
17636573Sphitran
17646573Sphitran /*ARGSUSED*/
17656573Sphitran static int
acpi_drv_kstat_power_update(kstat_t * ksp,int flag)17666573Sphitran acpi_drv_kstat_power_update(kstat_t *ksp, int flag)
17676573Sphitran {
17686573Sphitran if (flag == KSTAT_WRITE) {
17696573Sphitran return (EACCES);
17706573Sphitran }
17716573Sphitran
17726573Sphitran mutex_enter(&acpi_drv_mutex);
17736573Sphitran if (acpi_drv_psr_type == ACPI_DRV_TYPE_UNKNOWN) {
17746573Sphitran mutex_exit(&acpi_drv_mutex);
17756573Sphitran return (EIO);
17766573Sphitran }
17776573Sphitran kstat_named_setstr(&acpi_drv_power_kstat.acpi_drv_power,
17786573Sphitran acpi_drv_psr_type == ACPI_DRV_TYPE_AC ? AC : BATTERY);
17796573Sphitran acpi_drv_power_kstat.acpi_drv_supported_battery_count.value.ui32 =
17806573Sphitran (uint32_t)nbat;
17816573Sphitran mutex_exit(&acpi_drv_mutex);
17826573Sphitran
17836573Sphitran return (0);
17846573Sphitran }
17856573Sphitran
17866573Sphitran /*ARGSUSED*/
17876573Sphitran static int
acpi_drv_kstat_warn_update(kstat_t * ksp,int flag)17886573Sphitran acpi_drv_kstat_warn_update(kstat_t *ksp, int flag)
17896573Sphitran {
17906573Sphitran if (flag == KSTAT_WRITE) {
17916573Sphitran int ret = 0;
17926573Sphitran acpi_drv_warn_t bw;
17936573Sphitran acpi_drv_warn_kstat_t kbw;
17946573Sphitran
17956573Sphitran kbw = *(acpi_drv_warn_kstat_t *)acpi_drv_warn_ksp->ks_data;
17966573Sphitran
17976573Sphitran mutex_enter(&acpi_drv_mutex);
17986573Sphitran bw.bw_enabled = kbw.acpi_drv_bw_enabled.value.ui32;
17996573Sphitran bw.bw_charge_warn = kbw.acpi_drv_bw_charge_warn.value.ui32;
18006573Sphitran bw.bw_charge_low = kbw.acpi_drv_bw_charge_low.value.ui32;
18016573Sphitran ret = acpi_drv_set_warn(&bw);
18026573Sphitran mutex_exit(&acpi_drv_mutex);
18036573Sphitran
18046573Sphitran return (ret);
18056573Sphitran } else {
18066573Sphitran acpi_drv_warn_kstat_t *wp = &acpi_drv_warn_kstat;
18076573Sphitran
18086573Sphitran mutex_enter(&acpi_drv_mutex);
18096573Sphitran wp->acpi_drv_bw_enabled.value.ui32 = acpi_drv_warn_enabled;
18106573Sphitran wp->acpi_drv_bw_charge_warn.value.ui32 = acpi_drv_syn_warn_per;
18116573Sphitran wp->acpi_drv_bw_charge_low.value.ui32 = acpi_drv_syn_low_per;
18126573Sphitran mutex_exit(&acpi_drv_mutex);
18136573Sphitran
18146573Sphitran return (0);
18156573Sphitran }
18166573Sphitran }
18176573Sphitran
18186573Sphitran static int
acpi_drv_kstat_bif_update(kstat_t * ksp,int flag)18196573Sphitran acpi_drv_kstat_bif_update(kstat_t *ksp, int flag)
18206573Sphitran {
18216573Sphitran struct acpi_drv_cbat_state *bp;
18226573Sphitran acpi_bif_t *bif;
18236573Sphitran acpi_drv_bif_kstat_t *kp;
18246573Sphitran
18256573Sphitran if (flag == KSTAT_WRITE) {
18266573Sphitran return (EACCES);
18276573Sphitran }
18286573Sphitran
18296573Sphitran bp = (struct acpi_drv_cbat_state *)ksp->ks_private;
18306573Sphitran mutex_enter(&acpi_drv_mutex);
18316573Sphitran
18326573Sphitran if (acpi_drv_cbat_present(bp) <= 0) {
18336573Sphitran mutex_exit(&acpi_drv_mutex);
18346573Sphitran return (ENXIO);
18356573Sphitran }
18366573Sphitran
18376573Sphitran bzero(&bif, sizeof (bif));
18386573Sphitran if (acpi_drv_update_bif(bp) != ACPI_DRV_OK) {
18396573Sphitran mutex_exit(&acpi_drv_mutex);
18406573Sphitran return (ENXIO);
18416573Sphitran }
18426573Sphitran
18436573Sphitran bif = &bp->bif_cache;
18446573Sphitran kp = &acpi_drv_bif_kstat;
18456573Sphitran
18466573Sphitran /* Update BIF */
18476573Sphitran kp->acpi_drv_bif_unit.value.ui32 = bif->bif_unit;
18486573Sphitran kp->acpi_drv_bif_design_cap.value.ui32 = bif->bif_design_cap;
18496573Sphitran kp->acpi_drv_bif_last_cap.value.ui32 = bif->bif_last_cap;
18506573Sphitran kp->acpi_drv_bif_tech.value.ui32 = bif->bif_tech;
18516573Sphitran kp->acpi_drv_bif_voltage.value.ui32 = bif->bif_voltage;
18526573Sphitran kp->acpi_drv_bif_warn_cap.value.ui32 = bif->bif_warn_cap;
18536573Sphitran kp->acpi_drv_bif_low_cap.value.ui32 = bif->bif_low_cap;
18546573Sphitran kp->acpi_drv_bif_gran1_cap.value.ui32 = bif->bif_gran1_cap;
18556573Sphitran kp->acpi_drv_bif_gran2_cap.value.ui32 = bif->bif_gran2_cap;
18566573Sphitran
18576573Sphitran kstat_named_setstr(&kp->acpi_drv_bif_model, bif->bif_model);
18586573Sphitran kstat_named_setstr(&kp->acpi_drv_bif_serial, bif->bif_serial);
18596573Sphitran kstat_named_setstr(&kp->acpi_drv_bif_type, bif->bif_type);
18606573Sphitran kstat_named_setstr(&kp->acpi_drv_bif_oem_info, bif->bif_oem_info);
18616573Sphitran
18626573Sphitran mutex_exit(&acpi_drv_mutex);
18636573Sphitran return (0);
18646573Sphitran }
18656573Sphitran
18666573Sphitran static int
acpi_drv_kstat_bst_update(kstat_t * ksp,int flag)18676573Sphitran acpi_drv_kstat_bst_update(kstat_t *ksp, int flag)
18686573Sphitran {
18696573Sphitran struct acpi_drv_cbat_state *bp;
18706573Sphitran acpi_bst_t *bst;
18716573Sphitran acpi_drv_bst_kstat_t *kp;
18726573Sphitran
18736573Sphitran if (flag == KSTAT_WRITE) {
18746573Sphitran return (EACCES);
18756573Sphitran }
18766573Sphitran
18776573Sphitran bp = (struct acpi_drv_cbat_state *)ksp->ks_private;
18786573Sphitran mutex_enter(&acpi_drv_mutex);
18796573Sphitran
18806573Sphitran if (acpi_drv_cbat_present(bp) <= 0) {
18816573Sphitran mutex_exit(&acpi_drv_mutex);
18826573Sphitran return (ENXIO);
18836573Sphitran }
18846573Sphitran
18856573Sphitran bzero(&bst, sizeof (bst));
18866573Sphitran if (acpi_drv_update_bst(bp) != ACPI_DRV_OK) {
18876573Sphitran mutex_exit(&acpi_drv_mutex);
18886573Sphitran return (ENXIO);
18896573Sphitran }
18906573Sphitran
18916573Sphitran bst = &bp->bst_cache;
18926573Sphitran kp = &acpi_drv_bst_kstat;
18936573Sphitran
18946573Sphitran /* Update BST */
18956573Sphitran kp->acpi_drv_bst_state.value.ui32 = bst->bst_state;
18966573Sphitran kp->acpi_drv_bst_rate.value.ui32 = bst->bst_rate;
18976573Sphitran kp->acpi_drv_bst_rem_cap.value.ui32 = bst->bst_rem_cap;
18986573Sphitran kp->acpi_drv_bst_voltage.value.ui32 = bst->bst_voltage;
18996573Sphitran
19006573Sphitran mutex_exit(&acpi_drv_mutex);
19016573Sphitran return (0);
19026573Sphitran }
19036573Sphitran
19046573Sphitran static int
acpi_drv_kstat_init(void)19056573Sphitran acpi_drv_kstat_init(void)
19066573Sphitran {
19076573Sphitran char name[KSTAT_STRLEN];
19086573Sphitran struct acpi_drv_cbat_state *bp;
19096573Sphitran
19106573Sphitran /*
19116573Sphitran * Allocate, initialize and install powerstatus and
19126573Sphitran * supported_battery_count kstat.
19136573Sphitran */
19146573Sphitran acpi_drv_power_ksp = kstat_create(ACPI_DRV_NAME, 0,
19156573Sphitran ACPI_DRV_POWER_KSTAT_NAME, "misc",
19166573Sphitran KSTAT_TYPE_NAMED,
19176573Sphitran sizeof (acpi_drv_power_kstat) / sizeof (kstat_named_t),
19186573Sphitran KSTAT_FLAG_VIRTUAL);
19196573Sphitran if (acpi_drv_power_ksp == NULL) {
19206573Sphitran ACPI_DRV_DBG(CE_WARN, NULL,
19216573Sphitran "kstat_create(%s) fail", ACPI_DRV_POWER_KSTAT_NAME);
19226573Sphitran return (ACPI_DRV_ERR);
19236573Sphitran }
19246573Sphitran
19256573Sphitran acpi_drv_power_ksp->ks_data = &acpi_drv_power_kstat;
19266573Sphitran acpi_drv_power_ksp->ks_update = acpi_drv_kstat_power_update;
19276573Sphitran acpi_drv_power_ksp->ks_data_size += MAXNAMELEN;
19286573Sphitran kstat_install(acpi_drv_power_ksp);
19296573Sphitran
19306573Sphitran /*
19316573Sphitran * Allocate, initialize and install battery_capacity_warning kstat.
19326573Sphitran */
19336573Sphitran acpi_drv_warn_ksp = kstat_create(ACPI_DRV_NAME, 0,
19346573Sphitran ACPI_DRV_BTWARN_KSTAT_NAME, "misc",
19356573Sphitran KSTAT_TYPE_NAMED,
19366573Sphitran sizeof (acpi_drv_warn_kstat) / sizeof (kstat_named_t),
19376573Sphitran KSTAT_FLAG_VIRTUAL | KSTAT_FLAG_WRITABLE);
19386573Sphitran if (acpi_drv_warn_ksp == NULL) {
19396573Sphitran ACPI_DRV_DBG(CE_WARN, NULL,
19406573Sphitran "kstat_create(%s) fail", ACPI_DRV_BTWARN_KSTAT_NAME);
19416573Sphitran return (ACPI_DRV_ERR);
19426573Sphitran }
19436573Sphitran
19446573Sphitran acpi_drv_warn_ksp->ks_data = &acpi_drv_warn_kstat;
19456573Sphitran acpi_drv_warn_ksp->ks_update = acpi_drv_kstat_warn_update;
19466573Sphitran kstat_install(acpi_drv_warn_ksp);
19476573Sphitran
19486573Sphitran /*
19496573Sphitran * Allocate, initialize and install BIF and BST kstat
19506573Sphitran * for each battery.
19516573Sphitran */
19526573Sphitran for (bp = &acpi_drv_cbat[0]; bp < &acpi_drv_cbat[ACPI_DRV_MAX_BAT_NUM];
19536573Sphitran bp++) {
19546573Sphitran if (bp->dev.valid) {
19556573Sphitran kstat_t *ksp;
19566573Sphitran
19576573Sphitran /* BIF kstat */
19586573Sphitran (void) snprintf(name, KSTAT_STRLEN-1, "%s%d",
19596573Sphitran ACPI_DRV_BIF_KSTAT_NAME, bp->dev.index);
19606573Sphitran ksp = kstat_create(ACPI_DRV_NAME, 0,
19616573Sphitran name, "misc", KSTAT_TYPE_NAMED,
19626573Sphitran sizeof (acpi_drv_bif_kstat) /
19636573Sphitran sizeof (kstat_named_t), KSTAT_FLAG_VIRTUAL);
19646573Sphitran if (ksp == NULL) {
19656573Sphitran ACPI_DRV_DBG(CE_WARN, NULL,
19666573Sphitran "kstat_create(%s) fail", name);
19676573Sphitran return (ACPI_DRV_ERR);
19686573Sphitran }
19696573Sphitran ACPI_DRV_DBG(CE_NOTE, NULL, "kstat_create(%s) ok",
19706573Sphitran name);
19716573Sphitran
19726573Sphitran bp->bat_bif_ksp = ksp;
19736573Sphitran ksp->ks_data = &acpi_drv_bif_kstat;
19746573Sphitran ksp->ks_update = acpi_drv_kstat_bif_update;
19756573Sphitran ksp->ks_data_size += MAXNAMELEN * 4;
19766573Sphitran ksp->ks_private = bp;
19776573Sphitran
19786573Sphitran kstat_install(ksp);
19796573Sphitran
19806573Sphitran /* BST kstat */
19816573Sphitran (void) snprintf(name, KSTAT_STRLEN-1, "%s%d",
19826573Sphitran ACPI_DRV_BST_KSTAT_NAME, bp->dev.index);
19836573Sphitran ksp = kstat_create(ACPI_DRV_NAME, 0, name, "misc",
19846573Sphitran KSTAT_TYPE_NAMED,
19856573Sphitran sizeof (acpi_drv_bst_kstat) /
19866573Sphitran sizeof (kstat_named_t),
19876573Sphitran KSTAT_FLAG_VIRTUAL);
19886573Sphitran if (ksp == NULL) {
19896573Sphitran ACPI_DRV_DBG(CE_WARN, NULL,
19906573Sphitran "kstat_create(%s) fail", name);
19916573Sphitran return (ACPI_DRV_ERR);
19926573Sphitran }
19936573Sphitran ACPI_DRV_DBG(CE_NOTE, NULL, "kstat_create(%s) ok",
19946573Sphitran name);
19956573Sphitran
19966573Sphitran bp->bat_bst_ksp = ksp;
19976573Sphitran ksp->ks_data = &acpi_drv_bst_kstat;
19986573Sphitran ksp->ks_update = acpi_drv_kstat_bst_update;
19996573Sphitran ksp->ks_data_size += MAXNAMELEN * 4;
20006573Sphitran ksp->ks_private = bp;
20016573Sphitran
20026573Sphitran kstat_install(ksp);
20036573Sphitran }
20046573Sphitran }
20056573Sphitran
20066573Sphitran return (ACPI_DRV_OK);
20076573Sphitran }
20086573Sphitran
20096573Sphitran static void
acpi_drv_kstat_fini()20106573Sphitran acpi_drv_kstat_fini()
20116573Sphitran {
20126573Sphitran struct acpi_drv_cbat_state *bp;
20136573Sphitran
20146573Sphitran if (acpi_drv_power_ksp != NULL) {
20156573Sphitran kstat_delete(acpi_drv_power_ksp);
20166573Sphitran }
20176573Sphitran if (acpi_drv_warn_ksp != NULL) {
20186573Sphitran kstat_delete(acpi_drv_warn_ksp);
20196573Sphitran }
20206573Sphitran for (bp = &acpi_drv_cbat[0]; bp < &acpi_drv_cbat[ACPI_DRV_MAX_BAT_NUM];
20216573Sphitran bp++) {
20226573Sphitran if (bp->dev.valid) {
20236573Sphitran if (bp->bat_bif_ksp != NULL) {
20246573Sphitran kstat_delete(bp->bat_bif_ksp);
20256573Sphitran }
20266573Sphitran if (bp->bat_bst_ksp != NULL) {
20276573Sphitran kstat_delete(bp->bat_bst_ksp);
20286573Sphitran }
20296573Sphitran }
20306573Sphitran }
20316573Sphitran }
20326573Sphitran
20338693SKerry.Shu@Sun.COM int
acpi_drv_set_int(ACPI_HANDLE dev,char * method,uint32_t aint)20346573Sphitran acpi_drv_set_int(ACPI_HANDLE dev, char *method, uint32_t aint)
20356573Sphitran {
20366573Sphitran ACPI_OBJECT_LIST al;
20376573Sphitran ACPI_OBJECT ao;
20386573Sphitran
20396573Sphitran al.Pointer = &ao;
20406573Sphitran al.Count = 1;
20416573Sphitran ao.Type = ACPI_TYPE_INTEGER;
20426573Sphitran ao.Integer.Value = aint;
20436573Sphitran return (AcpiEvaluateObject(dev, method, &al, NULL));
20446573Sphitran }
20456573Sphitran
20468693SKerry.Shu@Sun.COM int
acpi_drv_dev_init(struct acpi_drv_dev * p)20478693SKerry.Shu@Sun.COM acpi_drv_dev_init(struct acpi_drv_dev *p)
20486573Sphitran {
20498693SKerry.Shu@Sun.COM ACPI_DEVICE_INFO *info;
20508693SKerry.Shu@Sun.COM ACPI_STATUS ret;
20518693SKerry.Shu@Sun.COM
20528693SKerry.Shu@Sun.COM ASSERT(p != NULL && p->hdl != NULL);
20536573Sphitran
20548693SKerry.Shu@Sun.COM p->valid = 0;
20558693SKerry.Shu@Sun.COM
20568693SKerry.Shu@Sun.COM /* Info size is variable depending on existance of _CID */
205711225SDana.Myers@Sun.COM ret = AcpiGetObjectInfo(p->hdl, &info);
20588693SKerry.Shu@Sun.COM if (ACPI_FAILURE(ret)) {
20598693SKerry.Shu@Sun.COM ACPI_DRV_DBG(CE_WARN, NULL,
20608693SKerry.Shu@Sun.COM "AcpiGetObjectInfo() fail: %d", (int32_t)ret);
20616573Sphitran return (ACPI_DRV_ERR);
20626573Sphitran }
20636573Sphitran
20648693SKerry.Shu@Sun.COM if ((info->Valid & ACPI_VALID_HID) == 0) {
20658693SKerry.Shu@Sun.COM ACPI_DRV_DBG(CE_WARN, NULL,
20668693SKerry.Shu@Sun.COM "!AcpiGetObjectInfo(): _HID not available");
2067*12004Sjiang.liu@intel.com p->hid[0] = 0;
20688693SKerry.Shu@Sun.COM } else {
2069*12004Sjiang.liu@intel.com (void) strlcpy(p->hid, info->HardwareId.String, ID_LEN);
20708693SKerry.Shu@Sun.COM }
20716573Sphitran
20728693SKerry.Shu@Sun.COM /*
20738693SKerry.Shu@Sun.COM * This object is optional, but is required when the device
20748693SKerry.Shu@Sun.COM * has no other way to report a persistent unique device ID.
20758693SKerry.Shu@Sun.COM */
20768693SKerry.Shu@Sun.COM if ((info->Valid & ACPI_VALID_UID) == 0) {
20778693SKerry.Shu@Sun.COM ACPI_DRV_DBG(CE_WARN, NULL,
20788693SKerry.Shu@Sun.COM "!AcpiGetObjectInfo(): _UID not available");
20798693SKerry.Shu@Sun.COM /* Use 0 as the default _UID */
2080*12004Sjiang.liu@intel.com p->uid[0] = 0;
20818693SKerry.Shu@Sun.COM } else {
2082*12004Sjiang.liu@intel.com (void) strlcpy(p->uid, info->UniqueId.String, ID_LEN);
20836573Sphitran }
20846573Sphitran
20858693SKerry.Shu@Sun.COM if (info->Valid & ACPI_VALID_ADR) {
20868693SKerry.Shu@Sun.COM p->valid = 1;
20878693SKerry.Shu@Sun.COM p->type = ACPI_DRV_TYPE_HOTKEY;
20888693SKerry.Shu@Sun.COM }
20896573Sphitran
20908693SKerry.Shu@Sun.COM AcpiOsFree(info);
20916573Sphitran
20926573Sphitran return (ACPI_DRV_OK);
20936573Sphitran }
2094