diff options
Diffstat (limited to 'sys/arch/arm/xscale/pxa2x0_apm.c')
-rw-r--r-- | sys/arch/arm/xscale/pxa2x0_apm.c | 127 |
1 files changed, 122 insertions, 5 deletions
diff --git a/sys/arch/arm/xscale/pxa2x0_apm.c b/sys/arch/arm/xscale/pxa2x0_apm.c index 5dce4a0f5c2..c0b59c1c558 100644 --- a/sys/arch/arm/xscale/pxa2x0_apm.c +++ b/sys/arch/arm/xscale/pxa2x0_apm.c @@ -1,4 +1,4 @@ -/* $OpenBSD: pxa2x0_apm.c,v 1.7 2005/02/28 13:21:17 uwe Exp $ */ +/* $OpenBSD: pxa2x0_apm.c,v 1.8 2005/03/03 22:55:00 uwe Exp $ */ /*- * Copyright (c) 2001 Alexander Guy. All rights reserved. @@ -78,10 +78,17 @@ int apm_userstandbys; int apm_suspends; int apm_battlow; /* XXX unused */ -void apm_power_info(struct pxa2x0_apm_softc *, - struct apm_power_info *); +/* battery percentage at where we get verbose in our warnings. This + value can be changed using sysctl(8), value machdep.apmwarn. + Setting it to zero kills all warnings */ +int cpu_apmwarn = 10; + +void apm_power_print(struct pxa2x0_apm_softc *, struct apm_power_info *); +void apm_power_info(struct pxa2x0_apm_softc *, struct apm_power_info *); void apm_suspend(struct pxa2x0_apm_softc *); void apm_resume(struct pxa2x0_apm_softc *); +int apm_get_event(struct pxa2x0_apm_softc *, u_long *); +int apm_handle_event(struct pxa2x0_apm_softc *, u_long); void apm_periodic_check(struct pxa2x0_apm_softc *); void apm_thread_create(void *); void apm_thread(void *); @@ -231,6 +238,56 @@ void scoop_suspend(void); void scoop_resume(void); void +apm_power_print(struct pxa2x0_apm_softc *sc, struct apm_power_info *powerp) +{ + + if (powerp->battery_life != APM_BATT_LIFE_UNKNOWN) + printf("%s: battery life expectancy %d%%\n", + sc->sc_dev.dv_xname, powerp->battery_life); + + printf("%s: AC ", sc->sc_dev.dv_xname); + switch (powerp->ac_state) { + case APM_AC_OFF: + printf("off,"); + break; + case APM_AC_ON: + printf("on,"); + break; + case APM_AC_BACKUP: + printf("backup power,"); + break; + default: + case APM_AC_UNKNOWN: + printf("unknown,"); + break; + } + + printf(" battery is "); + switch (powerp->battery_state) { + case APM_BATT_HIGH: + printf("high"); + break; + case APM_BATT_LOW: + printf("low"); + break; + case APM_BATT_CRITICAL: + printf("CRITICAL"); + break; + case APM_BATT_CHARGING: + printf("charging"); + break; + case APM_BATT_UNKNOWN: + printf("unknown"); + break; + default: + printf("undecoded (%x)", powerp->battery_state); + break; + } + + printf("\n"); +} + +void apm_power_info(struct pxa2x0_apm_softc *sc, struct apm_power_info *power) { @@ -267,13 +324,73 @@ apm_resume(struct pxa2x0_apm_softc *sc) dopowerhooks(PWR_RESUME); } -void -apm_periodic_check(struct pxa2x0_apm_softc *sc) +int +apm_get_event(struct pxa2x0_apm_softc *sc, u_long *event_type) { + struct apm_power_info power; + /* Periodic callbacks could be replaced with a machine-dependant + get_event function. */ if (sc->sc_periodic_check != NULL) sc->sc_periodic_check(sc); + apm_power_info(sc, &power); + if (power.ac_state != sc->sc_ac_state || + power.battery_life != sc->sc_batt_life || + power.battery_state != sc->sc_batt_state) { + sc->sc_ac_state = power.ac_state; + sc->sc_batt_life = power.battery_life; + sc->sc_batt_state = power.battery_state; + *event_type = APM_POWER_CHANGE; + return 0; + } + + *event_type = APM_NOEVENT; + return 1; +} + +int +apm_handle_event(struct pxa2x0_apm_softc *sc, u_long event_type) +{ + struct apm_power_info power; + int ret = 0; + + switch (event_type) { + case APM_NOEVENT: + ret = 1; + break; + case APM_POWER_CHANGE: + apm_power_info(sc, &power); + if (power.battery_life != APM_BATT_LIFE_UNKNOWN && + power.battery_life < cpu_apmwarn && + (sc->sc_flags & SCFLAG_PRINT) != SCFLAG_NOPRINT && + ((sc->sc_flags & SCFLAG_PRINT) != SCFLAG_PCTPRINT || + sc->sc_prev_batt_life != power.battery_life)) { + sc->sc_prev_batt_life = power.battery_life; + apm_power_print(sc, &power); + } + break; + default: + DPRINTF(("apm_handle_event: unsupported event, code %d\n", + event_type)); + } + + return (ret); +} + +void +apm_periodic_check(struct pxa2x0_apm_softc *sc) +{ + u_long event_type; + + /* Loop until all events are handled. */ + while (1) { + if (apm_get_event(sc, &event_type) != 0) + break; + if (apm_handle_event(sc, event_type) != 0) + break; + } + /* * Counters for pending requests are cleared just before changing * the processor run mode to avoid falling back to sleep after a |