Home | History | Annotate | Line # | Download | only in acpi
acpi_apm.c revision 1.14.20.1
      1  1.14.20.1  uebayasi /*	$NetBSD: acpi_apm.c,v 1.14.20.1 2010/04/30 14:43:05 uebayasi Exp $	*/
      2        1.1  christos 
      3        1.1  christos /*-
      4        1.1  christos  * Copyright (c) 2006 The NetBSD Foundation, Inc.
      5        1.1  christos  * All rights reserved.
      6        1.1  christos  *
      7        1.1  christos  * This code is derived from software contributed to The NetBSD Foundation
      8        1.1  christos  * by Christos Zoulas and by Jared McNeill.
      9        1.1  christos  *
     10        1.1  christos  * Redistribution and use in source and binary forms, with or without
     11        1.1  christos  * modification, are permitted provided that the following conditions
     12        1.1  christos  * are met:
     13        1.1  christos  * 1. Redistributions of source code must retain the above copyright
     14        1.1  christos  *    notice, this list of conditions and the following disclaimer.
     15        1.1  christos  * 2. Redistributions in binary form must reproduce the above copyright
     16        1.1  christos  *    notice, this list of conditions and the following disclaimer in the
     17        1.1  christos  *    documentation and/or other materials provided with the distribution.
     18        1.1  christos  *
     19        1.1  christos  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
     20        1.1  christos  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
     21        1.1  christos  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     22        1.1  christos  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
     23        1.1  christos  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     24        1.1  christos  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     25        1.1  christos  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     26        1.1  christos  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     27        1.1  christos  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     28        1.1  christos  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     29        1.1  christos  * POSSIBILITY OF SUCH DAMAGE.
     30        1.1  christos  */
     31        1.1  christos 
     32        1.1  christos /*
     33        1.1  christos  * Autoconfiguration support for the Intel ACPI Component Architecture
     34        1.1  christos  * ACPI reference implementation.
     35        1.1  christos  */
     36        1.1  christos 
     37        1.1  christos #include <sys/cdefs.h>
     38  1.14.20.1  uebayasi __KERNEL_RCSID(0, "$NetBSD: acpi_apm.c,v 1.14.20.1 2010/04/30 14:43:05 uebayasi Exp $");
     39        1.1  christos 
     40        1.1  christos #include <sys/param.h>
     41        1.1  christos #include <sys/device.h>
     42        1.1  christos #include <sys/sysctl.h>
     43  1.14.20.1  uebayasi #include <sys/systm.h>
     44  1.14.20.1  uebayasi #include <sys/queue.h>
     45        1.1  christos #include <sys/envsys.h>
     46  1.14.20.1  uebayasi 
     47        1.1  christos #include <dev/sysmon/sysmonvar.h>
     48        1.1  christos 
     49  1.14.20.1  uebayasi #include <dev/acpi/acpivar.h>
     50        1.1  christos #include <dev/apm/apmvar.h>
     51        1.1  christos 
     52        1.1  christos static void	acpiapm_disconnect(void *);
     53        1.1  christos static void	acpiapm_enable(void *, int);
     54        1.1  christos static int	acpiapm_set_powstate(void *, u_int, u_int);
     55        1.1  christos static int	acpiapm_get_powstat(void *, u_int, struct apm_power_info *);
     56  1.14.20.1  uebayasi static bool	apm_per_sensor(const struct sysmon_envsys *,
     57  1.14.20.1  uebayasi 			       const envsys_data_t *, void *);
     58        1.1  christos static int	acpiapm_get_event(void *, u_int *, u_int *);
     59        1.1  christos static void	acpiapm_cpu_busy(void *);
     60        1.1  christos static void	acpiapm_cpu_idle(void *);
     61        1.1  christos static void	acpiapm_get_capabilities(void *, u_int *, u_int *);
     62        1.1  christos 
     63        1.1  christos struct apm_accessops acpiapm_accessops = {
     64        1.1  christos 	acpiapm_disconnect,
     65        1.1  christos 	acpiapm_enable,
     66        1.1  christos 	acpiapm_set_powstate,
     67        1.1  christos 	acpiapm_get_powstat,
     68        1.1  christos 	acpiapm_get_event,
     69        1.1  christos 	acpiapm_cpu_busy,
     70        1.1  christos 	acpiapm_cpu_idle,
     71        1.1  christos 	acpiapm_get_capabilities,
     72        1.1  christos };
     73        1.1  christos 
     74        1.1  christos #ifdef ACPI_APM_DEBUG
     75        1.1  christos #define DPRINTF(a) uprintf a
     76        1.1  christos #else
     77        1.1  christos #define DPRINTF(a)
     78        1.1  christos #endif
     79        1.1  christos 
     80        1.4  christos #ifndef ACPI_APM_DEFAULT_STANDBY_STATE
     81        1.4  christos #define ACPI_APM_DEFAULT_STANDBY_STATE	(1)
     82        1.4  christos #endif
     83        1.4  christos #ifndef ACPI_APM_DEFAULT_SUSPEND_STATE
     84        1.4  christos #define ACPI_APM_DEFAULT_SUSPEND_STATE	(3)
     85        1.4  christos #endif
     86        1.4  christos #define ACPI_APM_DEFAULT_CAP						      \
     87        1.4  christos 	((ACPI_APM_DEFAULT_STANDBY_STATE!=0 ? APM_GLOBAL_STANDBY : 0) |	      \
     88        1.4  christos 	 (ACPI_APM_DEFAULT_SUSPEND_STATE!=0 ? APM_GLOBAL_SUSPEND : 0))
     89        1.4  christos #define ACPI_APM_STATE_MIN		(0)
     90        1.4  christos #define ACPI_APM_STATE_MAX		(4)
     91        1.4  christos 
     92        1.4  christos /* It is assumed that there is only acpiapm instance. */
     93        1.4  christos static int resumed = 0, capability_changed = 0;
     94        1.4  christos static int standby_state = ACPI_APM_DEFAULT_STANDBY_STATE;
     95        1.4  christos static int suspend_state = ACPI_APM_DEFAULT_SUSPEND_STATE;
     96        1.4  christos static int capabilities = ACPI_APM_DEFAULT_CAP;
     97        1.4  christos static int acpiapm_node = CTL_EOL, standby_node = CTL_EOL;
     98        1.4  christos 
     99        1.1  christos struct acpi_softc;
    100  1.14.20.1  uebayasi extern void acpi_enter_sleep_state(struct acpi_softc *, int);
    101       1.13      cube static int acpiapm_match(device_t, cfdata_t , void *);
    102       1.13      cube static void acpiapm_attach(device_t, device_t, void *);
    103        1.4  christos static int sysctl_state(SYSCTLFN_PROTO);
    104        1.1  christos 
    105       1.13      cube CFATTACH_DECL_NEW(acpiapm, sizeof(struct apm_softc),
    106        1.1  christos     acpiapm_match, acpiapm_attach, NULL, NULL);
    107        1.1  christos 
    108        1.1  christos static int
    109        1.4  christos /*ARGSUSED*/
    110       1.13      cube acpiapm_match(device_t parent, cfdata_t match, void *aux)
    111        1.1  christos {
    112        1.1  christos 	return apm_match();
    113        1.1  christos }
    114        1.1  christos 
    115        1.1  christos static void
    116        1.4  christos /*ARGSUSED*/
    117       1.13      cube acpiapm_attach(device_t parent, device_t self, void *aux)
    118        1.1  christos {
    119       1.13      cube 	struct apm_softc *sc = device_private(self);
    120        1.1  christos 
    121       1.13      cube 	sc->sc_dev = self;
    122        1.1  christos 	sc->sc_ops = &acpiapm_accessops;
    123        1.1  christos 	sc->sc_cookie = parent;
    124        1.1  christos 	sc->sc_vers = 0x0102;
    125        1.1  christos 	sc->sc_detail = 0;
    126        1.1  christos 	sc->sc_hwflags = APM_F_DONT_RUN_HOOKS;
    127        1.1  christos 	apm_attach(sc);
    128        1.1  christos }
    129        1.1  christos 
    130        1.4  christos static int
    131        1.4  christos get_state_value(int id)
    132        1.4  christos {
    133        1.4  christos 	const int states[] = {
    134        1.4  christos 		ACPI_STATE_S0,
    135        1.4  christos 		ACPI_STATE_S1,
    136        1.4  christos 		ACPI_STATE_S2,
    137        1.4  christos 		ACPI_STATE_S3,
    138        1.4  christos 		ACPI_STATE_S4
    139        1.4  christos 	};
    140        1.4  christos 
    141        1.4  christos 	if (id < ACPI_APM_STATE_MIN || id > ACPI_APM_STATE_MAX)
    142        1.4  christos 		return ACPI_STATE_S0;
    143        1.4  christos 
    144        1.4  christos 	return states[id];
    145        1.4  christos }
    146        1.4  christos 
    147        1.4  christos static int
    148        1.4  christos sysctl_state(SYSCTLFN_ARGS)
    149        1.4  christos {
    150        1.4  christos 	int newstate, error, *ref, cap, oldcap;
    151        1.4  christos 	struct sysctlnode node;
    152        1.4  christos 
    153        1.4  christos 	if (rnode->sysctl_num == standby_node) {
    154        1.4  christos 		ref = &standby_state;
    155        1.4  christos 		cap = APM_GLOBAL_STANDBY;
    156        1.4  christos 	} else {
    157        1.4  christos 		ref = &suspend_state;
    158        1.4  christos 		cap = APM_GLOBAL_SUSPEND;
    159        1.4  christos 	}
    160        1.4  christos 
    161        1.4  christos 	newstate = *ref;
    162        1.4  christos 	node = *rnode;
    163        1.4  christos 	node.sysctl_data = &newstate;
    164        1.4  christos         error = sysctl_lookup(SYSCTLFN_CALL(&node));
    165        1.4  christos 	if (error || newp == NULL)
    166        1.4  christos 		return error;
    167        1.4  christos 
    168        1.4  christos 	if (newstate < ACPI_APM_STATE_MIN || newstate > ACPI_APM_STATE_MAX)
    169        1.4  christos 		return EINVAL;
    170        1.4  christos 
    171        1.4  christos 	*ref = newstate;
    172        1.4  christos 	oldcap = capabilities;
    173        1.4  christos 	capabilities = newstate != 0 ? oldcap | cap : oldcap & ~cap;
    174        1.4  christos 	if ((capabilities ^ oldcap) != 0)
    175        1.4  christos 		capability_changed = 1;
    176        1.4  christos 
    177        1.4  christos 	return 0;
    178        1.4  christos }
    179        1.4  christos 
    180        1.4  christos SYSCTL_SETUP(sysctl_acpiapm_setup, "sysctl machdep.acpiapm subtree setup")
    181        1.4  christos {
    182        1.4  christos 	const struct sysctlnode *node;
    183        1.4  christos 
    184        1.4  christos 	if (sysctl_createv(clog, 0, NULL, NULL,
    185        1.4  christos 			   CTLFLAG_PERMANENT,
    186        1.4  christos 			   CTLTYPE_NODE, "machdep", NULL,
    187        1.4  christos 			   NULL, 0, NULL, 0, CTL_MACHDEP, CTL_EOL))
    188        1.4  christos 		return;
    189        1.4  christos 
    190        1.4  christos 	if (sysctl_createv(clog, 0, NULL, &node,
    191        1.4  christos 			   CTLFLAG_PERMANENT,
    192        1.4  christos 			   CTLTYPE_NODE, "acpiapm", NULL,
    193        1.4  christos 			   NULL, 0, NULL, 0,
    194        1.4  christos 			   CTL_MACHDEP, CTL_CREATE, CTL_EOL))
    195        1.4  christos 		return;
    196        1.4  christos 	acpiapm_node = node->sysctl_num;
    197        1.4  christos 
    198        1.4  christos 	if (sysctl_createv(clog, 0, NULL, &node,
    199        1.4  christos 			   CTLFLAG_READWRITE,
    200        1.4  christos 			   CTLTYPE_INT, "standby", NULL,
    201        1.4  christos 			   &sysctl_state, 0, NULL, 0,
    202        1.4  christos 			   CTL_MACHDEP, acpiapm_node, CTL_CREATE, CTL_EOL))
    203        1.4  christos 		return;
    204        1.4  christos 	standby_node = node->sysctl_num;
    205        1.4  christos 
    206        1.4  christos 	if (sysctl_createv(clog, 0, NULL, NULL,
    207        1.4  christos 			   CTLFLAG_READWRITE,
    208        1.4  christos 			   CTLTYPE_INT, "suspend", NULL,
    209        1.4  christos 			   &sysctl_state, 0, NULL, 0,
    210        1.4  christos 			   CTL_MACHDEP, acpiapm_node, CTL_CREATE, CTL_EOL))
    211        1.4  christos 		return;
    212        1.4  christos }
    213        1.4  christos 
    214        1.1  christos /*****************************************************************************
    215        1.1  christos  * Minimalistic ACPI /dev/apm emulation support, for ACPI suspend
    216        1.1  christos  *****************************************************************************/
    217        1.1  christos 
    218        1.1  christos static void
    219        1.4  christos /*ARGSUSED*/
    220        1.8  christos acpiapm_disconnect(void *opaque)
    221        1.1  christos {
    222        1.1  christos 	return;
    223        1.1  christos }
    224        1.1  christos 
    225        1.1  christos static void
    226        1.4  christos /*ARGSUSED*/
    227        1.8  christos acpiapm_enable(void *opaque, int onoff)
    228        1.1  christos {
    229        1.1  christos 	return;
    230        1.1  christos }
    231        1.1  christos 
    232        1.1  christos static int
    233        1.1  christos acpiapm_set_powstate(void *opaque, u_int devid, u_int powstat)
    234        1.1  christos {
    235       1.13      cube 	struct acpi_softc *sc = device_private((device_t)opaque);
    236        1.1  christos 
    237        1.1  christos 	if (devid != APM_DEV_ALLDEVS)
    238        1.1  christos 		return APM_ERR_UNRECOG_DEV;
    239        1.1  christos 
    240        1.1  christos 	switch (powstat) {
    241        1.1  christos 	case APM_SYS_READY:
    242        1.1  christos 		break;
    243        1.1  christos 	case APM_SYS_STANDBY:
    244        1.4  christos 		acpi_enter_sleep_state(sc, get_state_value(standby_state));
    245        1.4  christos 		resumed = 1;
    246        1.1  christos 		break;
    247        1.1  christos 	case APM_SYS_SUSPEND:
    248        1.4  christos 		acpi_enter_sleep_state(sc, get_state_value(suspend_state));
    249        1.4  christos 		resumed = 1;
    250        1.1  christos 		break;
    251        1.1  christos 	case APM_SYS_OFF:
    252        1.1  christos 		break;
    253        1.1  christos 	case APM_LASTREQ_INPROG:
    254        1.1  christos 		break;
    255        1.1  christos 	case APM_LASTREQ_REJECTED:
    256        1.1  christos 		break;
    257        1.1  christos 	}
    258        1.1  christos 
    259        1.1  christos 	return 0;
    260        1.1  christos }
    261        1.1  christos 
    262  1.14.20.1  uebayasi struct apm_sensor_info {
    263  1.14.20.1  uebayasi 	struct apm_power_info *pinfo;
    264  1.14.20.1  uebayasi 	int present;
    265  1.14.20.1  uebayasi 	int lastcap, descap, cap, warncap, lowcap, discharge;
    266  1.14.20.1  uebayasi 	int lastcap_valid, cap_valid, discharge_valid;
    267  1.14.20.1  uebayasi };
    268  1.14.20.1  uebayasi 
    269  1.14.20.1  uebayasi static bool
    270  1.14.20.1  uebayasi apm_per_sensor(const struct sysmon_envsys *sme, const envsys_data_t *edata,
    271  1.14.20.1  uebayasi 	       void *arg)
    272  1.14.20.1  uebayasi {
    273  1.14.20.1  uebayasi 	struct apm_sensor_info *info = (struct apm_sensor_info *)arg;
    274  1.14.20.1  uebayasi 	int data;
    275  1.14.20.1  uebayasi 
    276  1.14.20.1  uebayasi 	if (sme->sme_class != SME_CLASS_ACADAPTER &&
    277  1.14.20.1  uebayasi 	    sme->sme_class != SME_CLASS_BATTERY)
    278  1.14.20.1  uebayasi 		return false;
    279  1.14.20.1  uebayasi 
    280  1.14.20.1  uebayasi 	if (edata->state == ENVSYS_SINVALID)
    281  1.14.20.1  uebayasi 		return true;
    282  1.14.20.1  uebayasi 
    283  1.14.20.1  uebayasi 	data = edata->value_cur;
    284  1.14.20.1  uebayasi 
    285  1.14.20.1  uebayasi 	DPRINTF(("%s (%s) %d\n", sme->sme_name, edata->desc, data));
    286  1.14.20.1  uebayasi 
    287  1.14.20.1  uebayasi 	if (strstr(edata->desc, "connected")) {
    288  1.14.20.1  uebayasi 		info->pinfo->ac_state = data ? APM_AC_ON : APM_AC_OFF;
    289  1.14.20.1  uebayasi 	}
    290  1.14.20.1  uebayasi 	else if (strstr(edata->desc, "present") && data != 0)
    291  1.14.20.1  uebayasi 		info->present++;
    292  1.14.20.1  uebayasi 	else if (strstr(edata->desc, "charging")) {
    293  1.14.20.1  uebayasi 		if (data)
    294  1.14.20.1  uebayasi 			info->pinfo->battery_flags |= APM_BATT_FLAG_CHARGING;
    295  1.14.20.1  uebayasi 		else
    296  1.14.20.1  uebayasi 			info->pinfo->battery_flags &= ~APM_BATT_FLAG_CHARGING;
    297  1.14.20.1  uebayasi 		}
    298  1.14.20.1  uebayasi 	else if (strstr(edata->desc, "last full cap")) {
    299  1.14.20.1  uebayasi 		info->lastcap += data / 1000;
    300  1.14.20.1  uebayasi 		info->lastcap_valid = 1;
    301  1.14.20.1  uebayasi 	}
    302  1.14.20.1  uebayasi 	else if (strstr(edata->desc, "design cap"))
    303  1.14.20.1  uebayasi 		info->descap = data / 1000;
    304  1.14.20.1  uebayasi 	else if (strstr(edata->desc, "charge") &&
    305  1.14.20.1  uebayasi 	    strstr(edata->desc, "charge rate") == NULL &&
    306  1.14.20.1  uebayasi 	    strstr(edata->desc, "charge state") == NULL) {
    307  1.14.20.1  uebayasi 
    308  1.14.20.1  uebayasi 		/* Update cumulative capacity */
    309  1.14.20.1  uebayasi 		info->cap += data / 1000;
    310  1.14.20.1  uebayasi 
    311  1.14.20.1  uebayasi 		/* get warning- & critical-capacity values */
    312  1.14.20.1  uebayasi 		info->warncap = edata->limits.sel_warnmin / 1000;
    313  1.14.20.1  uebayasi 		info->lowcap = edata->limits.sel_critmin / 1000;
    314  1.14.20.1  uebayasi 
    315  1.14.20.1  uebayasi 		info->cap_valid = 1;
    316  1.14.20.1  uebayasi 		info->pinfo->nbattery++;
    317  1.14.20.1  uebayasi 	}
    318  1.14.20.1  uebayasi 	else if (strstr(edata->desc, "discharge rate")) {
    319  1.14.20.1  uebayasi 		info->discharge += data / 1000;
    320  1.14.20.1  uebayasi 		info->discharge_valid = 1;
    321  1.14.20.1  uebayasi 	}
    322  1.14.20.1  uebayasi 	return true;
    323  1.14.20.1  uebayasi }
    324  1.14.20.1  uebayasi 
    325        1.1  christos static int
    326        1.4  christos /*ARGSUSED*/
    327        1.8  christos acpiapm_get_powstat(void *opaque, u_int batteryid,
    328        1.7   xtraeme 	struct apm_power_info *pinfo)
    329        1.1  christos {
    330        1.4  christos #define APM_BATT_FLAG_WATERMARK_MASK (APM_BATT_FLAG_CRITICAL |		      \
    331        1.4  christos 				      APM_BATT_FLAG_LOW |		      \
    332        1.4  christos 				      APM_BATT_FLAG_HIGH)
    333  1.14.20.1  uebayasi 	struct apm_sensor_info info;
    334  1.14.20.1  uebayasi 
    335  1.14.20.1  uebayasi 	/* Denote most variables as uninitialized. */
    336  1.14.20.1  uebayasi 	info.lowcap = info.warncap = info.descap = -1;
    337  1.14.20.1  uebayasi 
    338  1.14.20.1  uebayasi 	/*
    339  1.14.20.1  uebayasi 	 * Prepare to aggregate capacity, charge, and discharge over all
    340  1.14.20.1  uebayasi 	 * batteries.
    341  1.14.20.1  uebayasi 	 */
    342  1.14.20.1  uebayasi 	info.cap = info.lastcap = info.discharge = 0;
    343  1.14.20.1  uebayasi 	info.cap_valid = info.lastcap_valid = info.discharge_valid = 0;
    344  1.14.20.1  uebayasi 	info.present = 0;
    345  1.14.20.1  uebayasi 
    346  1.14.20.1  uebayasi 	info.pinfo = pinfo;
    347        1.1  christos 
    348        1.1  christos 	(void)memset(pinfo, 0, sizeof(*pinfo));
    349        1.1  christos 	pinfo->ac_state = APM_AC_UNKNOWN;
    350        1.1  christos 	pinfo->minutes_valid = 0;
    351       1.11    plunky 	pinfo->minutes_left = 0;
    352        1.1  christos 	pinfo->batteryid = 0;
    353        1.5       gdt 	pinfo->nbattery = 0;	/* to be incremented as batteries are found */
    354        1.1  christos 	pinfo->battery_flags = 0;
    355        1.4  christos 	pinfo->battery_state = APM_BATT_UNKNOWN; /* ignored */
    356        1.1  christos 	pinfo->battery_life = APM_BATT_LIFE_UNKNOWN;
    357        1.1  christos 
    358  1.14.20.1  uebayasi 	sysmon_envsys_foreach_sensor(apm_per_sensor, (void *)&info, true);
    359        1.9  christos 
    360  1.14.20.1  uebayasi 	if (info.present == 0)
    361  1.14.20.1  uebayasi 		pinfo->battery_flags |= APM_BATT_FLAG_NO_SYSTEM_BATTERY;
    362        1.1  christos 
    363  1.14.20.1  uebayasi 	if (info.cap_valid > 0)  {
    364  1.14.20.1  uebayasi 		if (info.warncap != -1 && info.cap < info.warncap)
    365        1.1  christos 			pinfo->battery_flags |= APM_BATT_FLAG_CRITICAL;
    366  1.14.20.1  uebayasi 		else if (info.lowcap != -1) {
    367  1.14.20.1  uebayasi 			if (info.cap < info.lowcap)
    368        1.4  christos 				pinfo->battery_flags |= APM_BATT_FLAG_LOW;
    369        1.4  christos 			else
    370        1.4  christos 				pinfo->battery_flags |= APM_BATT_FLAG_HIGH;
    371        1.1  christos 		}
    372  1.14.20.1  uebayasi 		if (info.lastcap_valid > 0 && info.lastcap != 0)
    373  1.14.20.1  uebayasi 			pinfo->battery_life = 100 * info.cap / info.lastcap;
    374  1.14.20.1  uebayasi 		else if (info.descap != -1 && info.descap != 0)
    375  1.14.20.1  uebayasi 			pinfo->battery_life = 100 * info.cap / info.descap;
    376        1.1  christos 	}
    377        1.1  christos 
    378        1.1  christos 	if ((pinfo->battery_flags & APM_BATT_FLAG_CHARGING) == 0) {
    379        1.4  christos 		/* discharging */
    380  1.14.20.1  uebayasi 		if (info.discharge != -1 && info.discharge != 0 &&
    381  1.14.20.1  uebayasi 		    info.cap != -1)
    382  1.14.20.1  uebayasi 			pinfo->minutes_left = 60 * info.cap / info.discharge;
    383        1.1  christos 	}
    384        1.4  christos 	if ((pinfo->battery_flags & APM_BATT_FLAG_WATERMARK_MASK) == 0 &&
    385        1.4  christos 	    (pinfo->battery_flags & APM_BATT_FLAG_NO_SYSTEM_BATTERY) == 0) {
    386        1.4  christos 		if (pinfo->ac_state == APM_AC_ON)
    387        1.4  christos 			pinfo->battery_flags |= APM_BATT_FLAG_HIGH;
    388        1.4  christos 		else
    389        1.4  christos 			pinfo->battery_flags |= APM_BATT_FLAG_LOW;
    390        1.4  christos 	}
    391        1.4  christos 
    392  1.14.20.1  uebayasi 	DPRINTF(("%d %d %d %d %d %d\n", info.cap, info.warncap, info.lowcap,
    393  1.14.20.1  uebayasi 	    info.lastcap, info.descap, info.discharge));
    394        1.4  christos 	DPRINTF(("pinfo %d %d %d\n", pinfo->battery_flags,
    395        1.4  christos 	    pinfo->battery_life, pinfo->battery_life));
    396        1.1  christos 	return 0;
    397        1.1  christos }
    398        1.1  christos 
    399        1.1  christos static int
    400        1.4  christos /*ARGSUSED*/
    401        1.8  christos acpiapm_get_event(void *opaque, u_int *event_type, u_int *event_info)
    402        1.1  christos {
    403        1.4  christos 	if (capability_changed) {
    404        1.4  christos 		capability_changed = 0;
    405        1.4  christos 		*event_type = APM_CAP_CHANGE;
    406        1.4  christos 		*event_info = 0;
    407        1.4  christos 		return 0;
    408        1.4  christos 	}
    409        1.4  christos 	if (resumed) {
    410        1.4  christos 		resumed = 0;
    411        1.4  christos 		*event_type = APM_NORMAL_RESUME;
    412        1.4  christos 		*event_info = 0;
    413        1.4  christos 		return 0;
    414        1.4  christos 	}
    415        1.4  christos 
    416        1.1  christos 	return APM_ERR_NOEVENTS;
    417        1.1  christos }
    418        1.1  christos 
    419        1.1  christos static void
    420        1.4  christos /*ARGSUSED*/
    421        1.8  christos acpiapm_cpu_busy(void *opaque)
    422        1.1  christos {
    423        1.1  christos 	return;
    424        1.1  christos }
    425        1.1  christos 
    426        1.1  christos static void
    427        1.4  christos /*ARGSUSED*/
    428        1.8  christos acpiapm_cpu_idle(void *opaque)
    429        1.1  christos {
    430        1.1  christos 	return;
    431        1.1  christos }
    432        1.1  christos 
    433        1.1  christos static void
    434        1.4  christos /*ARGSUSED*/
    435        1.8  christos acpiapm_get_capabilities(void *opaque, u_int *numbatts,
    436        1.7   xtraeme 	u_int *capflags)
    437        1.1  christos {
    438        1.1  christos 	*numbatts = 1;
    439        1.4  christos 	*capflags = capabilities;
    440        1.1  christos 	return;
    441        1.1  christos }
    442