summaryrefslogtreecommitdiff
path: root/sys/arch
diff options
context:
space:
mode:
Diffstat (limited to 'sys/arch')
-rw-r--r--sys/arch/arm/arm/arm32_machdep.c13
-rw-r--r--sys/arch/arm/include/cpu.h6
-rw-r--r--sys/arch/arm/xscale/pxa2x0_apm.c127
-rw-r--r--sys/arch/arm/xscale/pxa2x0_apm.h6
4 files changed, 143 insertions, 9 deletions
diff --git a/sys/arch/arm/arm/arm32_machdep.c b/sys/arch/arm/arm/arm32_machdep.c
index 1dff2ceab09..cf49c48eaa1 100644
--- a/sys/arch/arm/arm/arm32_machdep.c
+++ b/sys/arch/arm/arm/arm32_machdep.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: arm32_machdep.c,v 1.7 2005/01/24 22:20:32 uwe Exp $ */
+/* $OpenBSD: arm32_machdep.c,v 1.8 2005/03/03 22:55:00 uwe Exp $ */
/* $NetBSD: arm32_machdep.c,v 1.42 2003/12/30 12:33:15 pk Exp $ */
/*
@@ -63,6 +63,7 @@
#include <arm/machdep.h>
#include <machine/bootconfig.h>
+#include "apm.h"
#include "rd.h"
struct vm_map *exec_map = NULL;
@@ -392,6 +393,10 @@ cpu_sysctl(name, namelen, oldp, oldlenp, newp, newlen, p)
size_t newlen;
struct proc *p;
{
+#if NAPM > 0
+ extern int cpu_apmwarn;
+#endif
+
/* all sysctl names at this level are terminal */
if (namelen != 1)
return (ENOTDIR); /* overloaded */
@@ -435,6 +440,12 @@ cpu_sysctl(name, namelen, oldp, oldlenp, newp, newlen, p)
#else
return (sysctl_rdint(oldp, oldlenp, newp, 0));
#endif
+
+#if NAPM > 0
+ case CPU_APMWARN:
+ return (sysctl_int(oldp, oldlenp, newp, newlen, &cpu_apmwarn));
+#endif
+
default:
return (EOPNOTSUPP);
}
diff --git a/sys/arch/arm/include/cpu.h b/sys/arch/arm/include/cpu.h
index e5e6ffb9667..3d80bee0b2a 100644
--- a/sys/arch/arm/include/cpu.h
+++ b/sys/arch/arm/include/cpu.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: cpu.h,v 1.5 2005/01/21 16:22:34 miod Exp $ */
+/* $OpenBSD: cpu.h,v 1.6 2005/03/03 22:55:00 uwe Exp $ */
/* $NetBSD: cpu.h,v 1.34 2003/06/23 11:01:08 martin Exp $ */
/*
@@ -60,7 +60,8 @@
#define CPU_CONSDEV 4 /* struct: dev_t of our console */
#define CPU_POWERSAVE 5 /* int: use CPU powersave mode */
#define CPU_ALLOWAPERTURE 6 /* int: allow mmap of /dev/xf86 */
-#define CPU_MAXID 7 /* number of valid machdep ids */
+#define CPU_APMWARN 7 /* APM battery warning percentage */
+#define CPU_MAXID 8 /* number of valid machdep ids */
#define CTL_MACHDEP_NAMES { \
{ 0, 0 }, \
@@ -70,6 +71,7 @@
{ "console_device", CTLTYPE_STRUCT }, \
{ "powersave", CTLTYPE_INT }, \
{ "allowaperture", CTLTYPE_INT }, \
+ { "apmwarn", CTLTYPE_INT }, \
}
#ifdef _KERNEL
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
diff --git a/sys/arch/arm/xscale/pxa2x0_apm.h b/sys/arch/arm/xscale/pxa2x0_apm.h
index 1abd374de6c..f711ed6c909 100644
--- a/sys/arch/arm/xscale/pxa2x0_apm.h
+++ b/sys/arch/arm/xscale/pxa2x0_apm.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: pxa2x0_apm.h,v 1.4 2005/02/22 21:53:03 uwe Exp $ */
+/* $OpenBSD: pxa2x0_apm.h,v 1.5 2005/03/03 22:55:00 uwe Exp $ */
/*
* Copyright (c) 2005 Uwe Stuehler <uwe@bsdx.de>
@@ -35,6 +35,10 @@ struct pxa2x0_apm_softc {
void (*sc_periodic_check)(struct pxa2x0_apm_softc *);
void (*sc_power_info)(struct pxa2x0_apm_softc *,
struct apm_power_info *);
+ u_char sc_ac_state;
+ u_char sc_batt_state;
+ u_char sc_batt_life;
+ u_char sc_prev_batt_life;
};
void pxa2x0_apm_attach_sub(struct pxa2x0_apm_softc *);