diff options
author | Otto Moerbeek <otto@cvs.openbsd.org> | 2010-02-28 08:30:28 +0000 |
---|---|---|
committer | Otto Moerbeek <otto@cvs.openbsd.org> | 2010-02-28 08:30:28 +0000 |
commit | c518dd2600807e5276d21b9657745e6d5f4a9deb (patch) | |
tree | 959188edada0f5d7d75c046e952d1dd1c6507700 /sys/arch/loongson | |
parent | 79999529fca020d754c68793ff897c9230212875 (diff) |
Basic apm(4), providing battery/power status and events. apm(4) is the
generic part, ykbec(4) provides the device specific parts. Other
battery/power status drivers can easily hook to adb(4). With help
from miod@; ok matthieu@ miod@ jasper@
Diffstat (limited to 'sys/arch/loongson')
-rw-r--r-- | sys/arch/loongson/conf/GENERIC | 3 | ||||
-rw-r--r-- | sys/arch/loongson/conf/files.loongson | 6 | ||||
-rw-r--r-- | sys/arch/loongson/dev/apm.c | 346 | ||||
-rw-r--r-- | sys/arch/loongson/dev/kb3310.c | 223 | ||||
-rw-r--r-- | sys/arch/loongson/dev/mainbus.c | 5 | ||||
-rw-r--r-- | sys/arch/loongson/include/apmvar.h | 125 | ||||
-rw-r--r-- | sys/arch/loongson/include/conf.h | 42 | ||||
-rw-r--r-- | sys/arch/loongson/loongson/conf.c | 8 |
8 files changed, 676 insertions, 82 deletions
diff --git a/sys/arch/loongson/conf/GENERIC b/sys/arch/loongson/conf/GENERIC index b9ed254b97f..a1eb201d101 100644 --- a/sys/arch/loongson/conf/GENERIC +++ b/sys/arch/loongson/conf/GENERIC @@ -1,4 +1,4 @@ -# $OpenBSD: GENERIC,v 1.15 2010/02/26 14:53:11 miod Exp $ +# $OpenBSD: GENERIC,v 1.16 2010/02/28 08:30:27 otto Exp $ # # For further information on compiling OpenBSD kernels, see the config(8) # man page. @@ -30,6 +30,7 @@ config bsd swap generic mainbus0 at root cpu0 at mainbus0 clock0 at mainbus0 +apm0 at mainbus0 # Main local buses bonito* at mainbus0 diff --git a/sys/arch/loongson/conf/files.loongson b/sys/arch/loongson/conf/files.loongson index a5099a90154..2536d626614 100644 --- a/sys/arch/loongson/conf/files.loongson +++ b/sys/arch/loongson/conf/files.loongson @@ -1,4 +1,4 @@ -# $OpenBSD: files.loongson,v 1.7 2010/02/26 14:53:11 miod Exp $ +# $OpenBSD: files.loongson,v 1.8 2010/02/28 08:30:27 otto Exp $ # Standard stanzas config(8) can't run without maxpartitions 16 @@ -107,3 +107,7 @@ device smfb: wsemuldisplaydev, rasops16 attach smfb at pci with smfb_pci attach smfb at voyager with smfb_voyager file arch/loongson/dev/smfb.c smfb needs-flag + +device apm +attach apm at mainbus +file arch/loongson/dev/apm.c apm needs-flag diff --git a/sys/arch/loongson/dev/apm.c b/sys/arch/loongson/dev/apm.c new file mode 100644 index 00000000000..13afdf8a094 --- /dev/null +++ b/sys/arch/loongson/dev/apm.c @@ -0,0 +1,346 @@ +/* $OpenBSD: apm.c,v 1.1 2010/02/28 08:30:27 otto Exp $ */ + +/*- + * Copyright (c) 2001 Alexander Guy. All rights reserved. + * Copyright (c) 1998-2001 Michael Shalayeff. All rights reserved. + * Copyright (c) 1995 John T. Kohl. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the names of the authors nor the names of contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF MIND, USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + */ + +#include "apm.h" + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/kernel.h> +#include <sys/proc.h> +#include <sys/device.h> +#include <sys/fcntl.h> +#include <sys/ioctl.h> +#include <sys/event.h> + +#include <machine/autoconf.h> +#include <machine/conf.h> +#include <machine/cpu.h> +#include <machine/apmvar.h> + + + +#if defined(APMDEBUG) +#define DPRINTF(x) printf x +#else +#define DPRINTF(x) /**/ +#endif + +struct apm_softc { + struct device sc_dev; + struct klist sc_note; + int sc_flags; +}; + +int apmmatch(struct device *, void *, void *); +void apmattach(struct device *, struct device *, void *); + +struct cfattach apm_ca = { + sizeof(struct apm_softc), apmmatch, apmattach +}; + +struct cfdriver apm_cd = { + NULL, "apm", DV_DULL +}; + +#define APMUNIT(dev) (minor(dev)&0xf0) +#define APMDEV(dev) (minor(dev)&0x0f) +#define APMDEV_NORMAL 0 +#define APMDEV_CTL 8 + +void filt_apmrdetach(struct knote *kn); +int filt_apmread(struct knote *kn, long hint); +int apmkqfilter(dev_t dev, struct knote *kn); +int apm_getdefaultinfo(struct apm_power_info *); + +struct filterops apmread_filtops = + { 1, NULL, filt_apmrdetach, filt_apmread}; + +int (*get_apminfo)(struct apm_power_info *) = apm_getdefaultinfo; + +/* + * Flags to control kernel display + * SCFLAG_NOPRINT: do not output APM power messages due to + * a power change event. + * + * SCFLAG_PCTPRINT: do not output APM power messages due to + * to a power change event unless the battery + * percentage changes. + */ + +#define SCFLAG_NOPRINT 0x0008000 +#define SCFLAG_PCTPRINT 0x0004000 +#define SCFLAG_PRINT (SCFLAG_NOPRINT|SCFLAG_PCTPRINT) + +#define SCFLAG_OREAD (1 << 0) +#define SCFLAG_OWRITE (1 << 1) +#define SCFLAG_OPEN (SCFLAG_OREAD|SCFLAG_OWRITE) + + +int +apmmatch(struct device *parent, void *match, void *aux) +{ + struct mainbus_attach_args *maa = aux; + + if (strcmp(maa->maa_name, apm_cd.cd_name) == 0) + return (1); + return (0); +} + +void +apmattach(struct device *parent, struct device *self, void *aux) +{ + printf("\n"); +} + +int +apmopen(dev_t dev, int flag, int mode, struct proc *p) +{ + struct apm_softc *sc; + int error = 0; + + /* apm0 only */ + if (!apm_cd.cd_ndevs || APMUNIT(dev) != 0 || + !(sc = apm_cd.cd_devs[APMUNIT(dev)])) + return ENXIO; + + DPRINTF(("apmopen: dev %d pid %d flag %x mode %x\n", + APMDEV(dev), p->p_pid, flag, mode)); + + switch (APMDEV(dev)) { + case APMDEV_CTL: + if (!(flag & FWRITE)) { + error = EINVAL; + break; + } + if (sc->sc_flags & SCFLAG_OWRITE) { + error = EBUSY; + break; + } + sc->sc_flags |= SCFLAG_OWRITE; + break; + case APMDEV_NORMAL: + if (!(flag & FREAD) || (flag & FWRITE)) { + error = EINVAL; + break; + } + sc->sc_flags |= SCFLAG_OREAD; + break; + default: + error = ENXIO; + break; + } + return error; +} + +int +apmclose(dev_t dev, int flag, int mode, struct proc *p) +{ + struct apm_softc *sc; + + /* apm0 only */ + if (!apm_cd.cd_ndevs || APMUNIT(dev) != 0 || + !(sc = apm_cd.cd_devs[APMUNIT(dev)])) + return ENXIO; + + DPRINTF(("apmclose: pid %d flag %x mode %x\n", p->p_pid, flag, mode)); + + switch (APMDEV(dev)) { + case APMDEV_CTL: + sc->sc_flags &= ~SCFLAG_OWRITE; + break; + case APMDEV_NORMAL: + sc->sc_flags &= ~SCFLAG_OREAD; + break; + } + return 0; +} + +int +apmioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p) +{ + struct apm_softc *sc; + struct apm_power_info *power; + int error = 0; + + /* apm0 only */ + if (!apm_cd.cd_ndevs || APMUNIT(dev) != 0 || + !(sc = apm_cd.cd_devs[APMUNIT(dev)])) + return ENXIO; + + switch (cmd) { + /* some ioctl names from linux */ + case APM_IOC_STANDBY: + if ((flag & FWRITE) == 0) + error = EBADF; + else + error = EOPNOTSUPP; /* XXX */ + break; + case APM_IOC_SUSPEND: + if ((flag & FWRITE) == 0) + error = EBADF; + else + error = EOPNOTSUPP; /* XXX */ + break; + case APM_IOC_PRN_CTL: + if ((flag & FWRITE) == 0) + error = EBADF; + else { + int flag = *(int *)data; + DPRINTF(( "APM_IOC_PRN_CTL: %d\n", flag )); + switch (flag) { + case APM_PRINT_ON: /* enable printing */ + sc->sc_flags &= ~SCFLAG_PRINT; + break; + case APM_PRINT_OFF: /* disable printing */ + sc->sc_flags &= ~SCFLAG_PRINT; + sc->sc_flags |= SCFLAG_NOPRINT; + break; + case APM_PRINT_PCT: /* disable some printing */ + sc->sc_flags &= ~SCFLAG_PRINT; + sc->sc_flags |= SCFLAG_PCTPRINT; + break; + default: + error = EINVAL; + break; + } + } + break; + case APM_IOC_DEV_CTL: + if ((flag & FWRITE) == 0) + error = EBADF; + else + error = EOPNOTSUPP; /* XXX */ + break; + case APM_IOC_GETPOWER: + power = (struct apm_power_info *)data; + error = (*get_apminfo)(power); + break; + case APM_IOC_STANDBY_REQ: + if ((flag & FWRITE) == 0) + error = EBADF; + else + error = EOPNOTSUPP; /* XXX */ + break; + case APM_IOC_SUSPEND_REQ: + if ((flag & FWRITE) == 0) + error = EBADF; + else + error = EOPNOTSUPP; /* XXX */ + break; + default: + error = ENOTTY; + } + + return error; +} + +void +filt_apmrdetach(struct knote *kn) +{ + struct apm_softc *sc = (struct apm_softc *)kn->kn_hook; + + SLIST_REMOVE(&sc->sc_note, kn, knote, kn_selnext); +} + +int +filt_apmread(struct knote *kn, long hint) +{ + /* XXX weird kqueue_scan() semantics */ + if (hint && !kn->kn_data) + kn->kn_data = (int)hint; + + return (1); +} + +int +apmkqfilter(dev_t dev, struct knote *kn) +{ + struct apm_softc *sc; + + /* apm0 only */ + if (!apm_cd.cd_ndevs || APMUNIT(dev) != 0 || + !(sc = apm_cd.cd_devs[APMUNIT(dev)])) + return ENXIO; + + switch (kn->kn_filter) { + case EVFILT_READ: + kn->kn_fop = &apmread_filtops; + break; + default: + return (1); + } + + kn->kn_hook = (caddr_t)sc; + SLIST_INSERT_HEAD(&sc->sc_note, kn, kn_selnext); + + return (0); +} + +int +apm_getdefaultinfo(struct apm_power_info *info) +{ + info->battery_state = APM_BATTERY_ABSENT; + info->ac_state = APM_AC_ON; + info->battery_life = 0; + info->minutes_left = 0; + return (0); +} + +void +apm_setinfohook(int (*hook)(struct apm_power_info *)) +{ + get_apminfo = hook; +} + +int +apm_record_event(u_int event, const char *src, const char *msg) +{ + static int apm_evindex; + struct apm_softc *sc; + + /* apm0 only */ + if (apm_cd.cd_ndevs == 0 || (sc = apm_cd.cd_devs[0]) == NULL) + return ENXIO; + + if ((sc->sc_flags & SCFLAG_NOPRINT) == 0) + printf("%s: %s %s\n", sc->sc_dev.dv_xname, src, msg); + + /* skip if no user waiting */ + if ((sc->sc_flags & SCFLAG_OPEN) == 0) + return (1); + + apm_evindex++; + KNOTE(&sc->sc_note, APM_EVENT_COMPOSE(event, apm_evindex)); + + return (0); +} diff --git a/sys/arch/loongson/dev/kb3310.c b/sys/arch/loongson/dev/kb3310.c index 600a5c24cac..38d1842dbbb 100644 --- a/sys/arch/loongson/dev/kb3310.c +++ b/sys/arch/loongson/dev/kb3310.c @@ -1,4 +1,4 @@ -/* $OpenBSD: kb3310.c,v 1.4 2010/02/24 18:29:39 otto Exp $ */ +/* $OpenBSD: kb3310.c,v 1.5 2010/02/28 08:30:27 otto Exp $ */ /* * Copyright (c) 2010 Otto Moerbeek <otto@drijf.net> * @@ -21,9 +21,12 @@ #include <sys/device.h> #include <sys/sensors.h> +#include <machine/apmvar.h> #include <machine/bus.h> #include <dev/isa/isavar.h> +#include "apm.h" + struct cfdriver ykbec_cd = { NULL, "ykbec", DV_DULL, }; @@ -31,13 +34,40 @@ struct cfdriver ykbec_cd = { #define IO_YKBEC 0x381 #define IO_YKBECSIZE 0x3 -#define KB3310_NUM_SENSORS 12 +static const struct { + const char *desc; + int type; +} ykbec_table[] = { +#define YKBEC_FAN 0 + { NULL, SENSOR_FANRPM }, +#define YKBEC_ITEMP 1 + { "Internal temperature", SENSOR_TEMP }, +#define YKBEC_DCAP 2 + { "Battery design capacity", SENSOR_AMPHOUR }, +#define YKBEC_FCAP 3 + { "Battery full charge capacity", SENSOR_AMPHOUR }, +#define YKBEC_DVOLT 4 + { "Battery design voltage", SENSOR_VOLTS_DC }, +#define YKBEC_BCURRENT 5 + { "Battery current", SENSOR_AMPS }, +#define YKBEC_BVOLT 6 + { "Battery voltage", SENSOR_VOLTS_DC }, +#define YKBEC_BTEMP 7 + { "Battery temperature", SENSOR_TEMP }, +#define YKBEC_CAP 8 + { "Battery capacity", SENSOR_PERCENT }, +#define YKBEC_CHARGING 9 + { "Battery charging", SENSOR_INDICATOR }, +#define YKBEC_AC 10 + { "AC-Power", SENSOR_INDICATOR } +#define YKBEC_NSENSORS 11 +}; struct ykbec_softc { struct device sc_dev; bus_space_tag_t sc_iot; bus_space_handle_t sc_ioh; - struct ksensor sc_sensor[KB3310_NUM_SENSORS]; + struct ksensor sc_sensor[YKBEC_NSENSORS]; struct ksensordev sc_sensordev; }; @@ -54,6 +84,21 @@ void ykbec_write(struct ykbec_softc *, u_int, u_int); u_int ykbec_read(struct ykbec_softc *, u_int); u_int ykbec_read16(struct ykbec_softc *, u_int); +#if NAPM > 0 +int ykbec_apminfo(struct apm_power_info *); +struct apm_power_info ykbec_apmdata; +const char *ykbec_batstate[] = { + "high", + "low", + "critical", + "charging", + "unknown" +}; +#define BATTERY_STRING(x) ((x) < nitems(ykbec_batstate) ? \ + ykbec_batstate[x] : ykbec_batstate[4]) +#endif + + int ykbec_match(struct device *parent, void *match, void *aux) { @@ -83,6 +128,7 @@ ykbec_attach( struct device *parent, struct device *self, void *aux) { struct isa_attach_args *ia = aux; struct ykbec_softc *sc = (struct ykbec_softc *)self; + int i; sc->sc_iot = ia->ia_iot; if (bus_space_map(sc->sc_iot, ia->ia_iobase, ia->ia_iosize, 0, @@ -98,66 +144,20 @@ ykbec_attach( struct device *parent, struct device *self, void *aux) printf(", unable to register update task\n"); return; } - sc->sc_sensor[0].type = SENSOR_FANRPM; - sensor_attach(&sc->sc_sensordev, &sc->sc_sensor[0]); - - sc->sc_sensor[1].type = SENSOR_TEMP; - strlcpy(sc->sc_sensor[1].desc, "Internal temperature", - sizeof(sc->sc_sensor[1].desc)); - sensor_attach(&sc->sc_sensordev, &sc->sc_sensor[1]); - - sc->sc_sensor[2].type = SENSOR_AMPHOUR; - strlcpy(sc->sc_sensor[2].desc, "Battery design capacity", - sizeof(sc->sc_sensor[2].desc)); - sensor_attach(&sc->sc_sensordev, &sc->sc_sensor[2]); - - sc->sc_sensor[3].type = SENSOR_AMPHOUR; - strlcpy(sc->sc_sensor[3].desc, "Battery full charge capacity", - sizeof(sc->sc_sensor[3].desc)); - sensor_attach(&sc->sc_sensordev, &sc->sc_sensor[3]); - - sc->sc_sensor[4].type = SENSOR_VOLTS_DC; - strlcpy(sc->sc_sensor[4].desc, "Battery design voltage", - sizeof(sc->sc_sensor[4].desc)); - sensor_attach(&sc->sc_sensordev, &sc->sc_sensor[4]); - - sc->sc_sensor[5].type = SENSOR_AMPS; - strlcpy(sc->sc_sensor[5].desc, "Battery current", - sizeof(sc->sc_sensor[5].desc)); - sensor_attach(&sc->sc_sensordev, &sc->sc_sensor[5]); - - sc->sc_sensor[6].type = SENSOR_VOLTS_DC; - strlcpy(sc->sc_sensor[6].desc, "Battery voltage", - sizeof(sc->sc_sensor[6].desc)); - sensor_attach(&sc->sc_sensordev, &sc->sc_sensor[6]); - - sc->sc_sensor[7].type = SENSOR_TEMP; - strlcpy(sc->sc_sensor[7].desc, "Battery temperature", - sizeof(sc->sc_sensor[7].desc)); - sensor_attach(&sc->sc_sensordev, &sc->sc_sensor[7]); - - sc->sc_sensor[8].type = SENSOR_PERCENT; - strlcpy(sc->sc_sensor[8].desc, "Battery capacity", - sizeof(sc->sc_sensor[8].desc)); - sensor_attach(&sc->sc_sensordev, &sc->sc_sensor[8]); - - sc->sc_sensor[9].type = SENSOR_INDICATOR; - strlcpy(sc->sc_sensor[9].desc, "Battery charging", - sizeof(sc->sc_sensor[9].desc)); - sensor_attach(&sc->sc_sensordev, &sc->sc_sensor[9]); - - sc->sc_sensor[10].type = SENSOR_INDICATOR; - strlcpy(sc->sc_sensor[10].desc, "AC-Power", - sizeof(sc->sc_sensor[10].desc)); - sensor_attach(&sc->sc_sensordev, &sc->sc_sensor[10]); - - sc->sc_sensor[11].type = SENSOR_INTEGER; - strlcpy(sc->sc_sensor[11].desc, "Battery low-level status", - sizeof(sc->sc_sensor[11].desc)); - sensor_attach(&sc->sc_sensordev, &sc->sc_sensor[11]); + + for (i = 0; i < YKBEC_NSENSORS; i++) { + sc->sc_sensor[i].type = ykbec_table[i].type; + if (ykbec_table[i].desc) + strlcpy(sc->sc_sensor[i].desc, ykbec_table[i].desc, + sizeof(sc->sc_sensor[i].desc)); + sensor_attach(&sc->sc_sensordev, &sc->sc_sensor[i]); + } sensordev_install(&sc->sc_sensordev); +#if NAPM > 0 + apm_setinfohook(ykbec_apminfo); +#endif printf("\n"); } @@ -247,33 +247,43 @@ ykbec_refresh(void *arg) { struct ykbec_softc *sc = (struct ykbec_softc *)arg; u_int val, bat_charge, bat_status, charge_status, bat_state, power_flag; + u_int cap_pct, fullcap; int current; +#if NAPM > 0 + struct apm_power_info old; +#endif val = ykbec_read16(sc, REG_FAN_SPEED_HIGH) & 0xfffff; - if (val != 0) + if (val != 0) { val = KB3310_FAN_SPEED_DIVIDER / val; - else - val = UINT_MAX; - sc->sc_sensor[0].value = val; + sc->sc_sensor[YKBEC_FAN].value = val; + sc->sc_sensor[YKBEC_FAN].flags &= ~SENSOR_FINVALID; + } else + sc->sc_sensor[YKBEC_FAN].flags |= SENSOR_FINVALID; val = ykbec_read(sc, ECTEMP_CURRENT_REG); - sc->sc_sensor[1].value = val * 1000000 + 273150000; + sc->sc_sensor[YKBEC_ITEMP].value = val * 1000000 + 273150000; - sc->sc_sensor[2].value = ykbec_read16(sc, REG_DESIGN_CAP_HIGH) * 1000; - sc->sc_sensor[3].value = ykbec_read16(sc, REG_FULLCHG_CAP_HIGH) * 1000; - sc->sc_sensor[4].value = ykbec_read16(sc, REG_DESIGN_VOL_HIGH) * 1000; + sc->sc_sensor[YKBEC_DCAP].value = ykbec_read16(sc, REG_DESIGN_CAP_HIGH) + * 1000; + fullcap = ykbec_read16(sc, REG_FULLCHG_CAP_HIGH); + sc->sc_sensor[YKBEC_FCAP].value = fullcap * 1000; + sc->sc_sensor[YKBEC_DVOLT].value = ykbec_read16(sc, REG_DESIGN_VOL_HIGH) + * 1000; current = ykbec_read16(sc, REG_CURRENT_HIGH); /* sign extend short -> int, int -> int64 will be done next statement */ current |= -(current & 0x8000); - sc->sc_sensor[5].value = current * -1000; + sc->sc_sensor[YKBEC_BCURRENT].value = -1000 * current; - sc->sc_sensor[6].value = ykbec_read16(sc, REG_VOLTAGE_HIGH) * 1000; + sc->sc_sensor[YKBEC_BVOLT].value = ykbec_read16(sc, REG_VOLTAGE_HIGH) * + 1000; val = ykbec_read16(sc, REG_TEMPERATURE_HIGH); - sc->sc_sensor[7].value = val * 1000000 + 273150000; + sc->sc_sensor[YKBEC_BTEMP].value = val * 1000000 + 273150000; - sc->sc_sensor[8].value = ykbec_read16(sc, REG_RELATIVE_CAT_HIGH) * 1000; + cap_pct = ykbec_read16(sc, REG_RELATIVE_CAT_HIGH); + sc->sc_sensor[YKBEC_CAP].value = cap_pct * 1000; bat_charge = ykbec_read(sc, REG_BAT_CHARGE); bat_status = ykbec_read(sc, REG_BAT_STATUS); @@ -281,8 +291,69 @@ ykbec_refresh(void *arg) bat_state = ykbec_read(sc, REG_BAT_STATE); power_flag = ykbec_read(sc, REG_POWER_FLAG); - sc->sc_sensor[9].value = (bat_state & BAT_STATE_CHARGING) ? 1 : 0; - sc->sc_sensor[10].value = (power_flag & POWER_FLAG_ADAPTER_IN) ? 1 : 0; - sc->sc_sensor[11].value = (bat_state << 24) | (charge_status << 16) | - (bat_status << 8) | bat_charge; + sc->sc_sensor[YKBEC_CHARGING].value = (bat_state & BAT_STATE_CHARGING) ? + 1 : 0; + sc->sc_sensor[YKBEC_AC].value = (power_flag & POWER_FLAG_ADAPTER_IN) ? + 1 : 0; + +#if NAPM > 0 + bcopy(&ykbec_apmdata, &old, sizeof(old)); + ykbec_apmdata.battery_life = cap_pct; + ykbec_apmdata.ac_state = (power_flag & POWER_FLAG_ADAPTER_IN) ? + APM_AC_ON : APM_AC_OFF; + if ((bat_status & BAT_STATUS_BAT_EXISTS) == 0) { + ykbec_apmdata.battery_state = APM_BATTERY_ABSENT; + ykbec_apmdata.minutes_left = 0; + ykbec_apmdata.battery_life = 0; + } else { + /* if charging, return the minutes until full */ + if (bat_state & BAT_STATE_CHARGING) { + ykbec_apmdata.battery_state = APM_BATT_CHARGING; + if (current > 0) { + fullcap = (100 - cap_pct) * 60 * fullcap / 100; + ykbec_apmdata.minutes_left = fullcap / current; + } else + ykbec_apmdata.minutes_left = 0; + } else { + /* arbitrary */ + if (cap_pct > 60) + ykbec_apmdata.battery_state = APM_BATT_HIGH; + else if (cap_pct < 10) + ykbec_apmdata.battery_state = APM_BATT_CRITICAL; + else + ykbec_apmdata.battery_state = APM_BATT_LOW; + + current = -current; + /* Yeeloong draw is about 1A */ + if (current <= 0) + current = 1000; + /* at 5?%, the Yeeloong shuts down */ + if (cap_pct <= 5) + cap_pct = 0; + else + cap_pct -= 5; + fullcap = cap_pct * 60 * fullcap / 100; + ykbec_apmdata.minutes_left = fullcap / current; + } + + } + if (old.ac_state != ykbec_apmdata.ac_state) + apm_record_event(APM_POWER_CHANGE, "AC power", + ykbec_apmdata.ac_state ? "restored" : "lost"); + if (old.battery_state != ykbec_apmdata.battery_state) + apm_record_event(APM_POWER_CHANGE, "battery", + BATTERY_STRING(ykbec_apmdata.battery_state)); +#endif +} + + +#if NAPM > 0 + +int +ykbec_apminfo(struct apm_power_info *info) +{ + bcopy(&ykbec_apmdata, info, sizeof(struct apm_power_info)); + return 0; } + +#endif diff --git a/sys/arch/loongson/dev/mainbus.c b/sys/arch/loongson/dev/mainbus.c index 705bdd3b9e9..2dd88cf99e4 100644 --- a/sys/arch/loongson/dev/mainbus.c +++ b/sys/arch/loongson/dev/mainbus.c @@ -1,4 +1,4 @@ -/* $OpenBSD: mainbus.c,v 1.3 2010/02/16 21:29:26 miod Exp $ */ +/* $OpenBSD: mainbus.c,v 1.4 2010/02/28 08:30:27 otto Exp $ */ /* * Copyright (c) 2001-2003 Opsycon AB (www.opsycon.se / www.opsycon.com) @@ -72,6 +72,9 @@ mainbus_attach(struct device *parent, struct device *self, void *aux) caa.caa_maa.maa_name = "bonito"; config_found(self, &caa.caa_maa, mainbus_print); + + caa.caa_maa.maa_name = "apm"; + config_found(self, &caa.caa_maa, mainbus_print); } int diff --git a/sys/arch/loongson/include/apmvar.h b/sys/arch/loongson/include/apmvar.h new file mode 100644 index 00000000000..7311616b411 --- /dev/null +++ b/sys/arch/loongson/include/apmvar.h @@ -0,0 +1,125 @@ +/* $OpenBSD: apmvar.h,v 1.1 2010/02/28 08:30:27 otto Exp $ */ + +/* + * Copyright (c) 2001 Alexander Guy + * Copyright (c) 1995 John T. Kohl + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR `AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + */ +#ifndef _LOONGSON_APMVAR_H_ +#define _LOONGSON_APMVAR_H_ + +#include <sys/ioccom.h> + +/* Advanced Power Management (v1.0 and v1.1 specification) + * functions/defines/etc. + */ + +/* These definitions make up the heart of the user-land interface + * to the APM devices. + */ + +#define APM_AC_OFF 0x00 +#define APM_AC_ON 0x01 +#define APM_AC_BACKUP 0x02 +#define APM_AC_UNKNOWN 0xff +#define APM_BATT_HIGH 0x00 +#define APM_BATT_LOW 0x01 +#define APM_BATT_CRITICAL 0x02 +#define APM_BATT_CHARGING 0x03 +#define APM_BATT_UNKNOWN 0xff +#define APM_BATT_LIFE_UNKNOWN 0xff + +#define APM_NOEVENT 0x0000 +#define APM_STANDBY_REQ 0x0001 +#define APM_SUSPEND_REQ 0x0002 +#define APM_NORMAL_RESUME 0x0003 +#define APM_CRIT_RESUME 0x0004 /* suspend/resume happened + without us */ +#define APM_BATTERY_LOW 0x0005 +#define APM_POWER_CHANGE 0x0006 +#define APM_UPDATE_TIME 0x0007 +#define APM_CRIT_SUSPEND_REQ 0x0008 +#define APM_USER_STANDBY_REQ 0x0009 +#define APM_USER_SUSPEND_REQ 0x000A +#define APM_SYS_STANDBY_RESUME 0x000B +#define APM_CAPABILITY_CHANGE 0x000C /* apm v1.2 */ +#define APM_EVENT_MASK 0xffff + +#define APM_EVENT_COMPOSE(t,i) ((((i) & 0x7fff) << 16)|((t) & APM_EVENT_MASK)) +#define APM_EVENT_TYPE(e) ((e) & APM_EVENT_MASK) +#define APM_EVENT_INDEX(e) ((e) >> 16) + +/* + * LP (Laptop Package) + * + * Copyright (C) 1994 by HOSOKAWA Tatsumi <hosokawa@mt.cs.keio.ac.jp> + * + * This software may be used, modified, copied, and distributed, in + * both source and binary form provided that the above copyright and + * these terms are retained. Under no circumstances is the author + * responsible for the proper functioning of this software, nor does + * the author assume any responsibility for damages incurred with its + * use. + * + * Sep., 1994 Implemented on FreeBSD 1.1.5.1R (Toshiba AVS001WD) + */ + +#define APM_BATTERY_ABSENT 4 + +struct apm_power_info { + u_char battery_state; + u_char ac_state; + u_char battery_life; + u_char spare1; + u_int minutes_left; /* estimate */ + u_int spare2[6]; +}; + +struct apm_ctl { + u_int dev; + u_int mode; +}; + +#define APM_IOC_REJECT _IOW('A', 0, struct apm_event_info) /* reject request # */ +#define APM_IOC_STANDBY _IO('A', 1) /* put system into standby */ +#define APM_IOC_SUSPEND _IO('A', 2) /* put system into suspend */ +#define APM_IOC_GETPOWER _IOR('A', 3, struct apm_power_info) /* fetch battery state */ +#define APM_IOC_DEV_CTL _IOW('A', 5, struct apm_ctl) /* put device into mode */ +#define APM_IOC_PRN_CTL _IOW('A', 6, int ) /* driver power status msg */ +#define APM_PRINT_ON 0 /* driver power status displayed */ +#define APM_PRINT_OFF 1 /* driver power status not displayed */ +#define APM_PRINT_PCT 2 /* driver power status only displayed + if the percentage changes */ +#define APM_IOC_STANDBY_REQ _IO('A', 7) /* request standby */ +#define APM_IOC_SUSPEND_REQ _IO('A', 8) /* request suspend */ + +#ifdef _KERNEL +void apm_setinfohook(int (*)(struct apm_power_info *)); +int apm_record_event(u_int, const char *, const char *); +#endif + +#endif /* _LOONGSON_APMVAR_H_ */ diff --git a/sys/arch/loongson/include/conf.h b/sys/arch/loongson/include/conf.h new file mode 100644 index 00000000000..e1cb29d0fc1 --- /dev/null +++ b/sys/arch/loongson/include/conf.h @@ -0,0 +1,42 @@ +/* $OpenBSD: conf.h,v 1.1 2010/02/28 08:30:27 otto Exp $ */ +/* $NetBSD: conf.h,v 1.2 1996/05/05 19:28:34 christos Exp $ */ + +/* + * Copyright (c) 1996 Christos Zoulas. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Christos Zoulas. + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include <sys/conf.h> + +/* open, close, write, ioctl, kqueue */ +#define cdev_apm_init(c,n) { \ + dev_init(c,n,open), dev_init(c,n,close), (dev_type_read((*))) enodev, \ + (dev_type_write((*))) enodev, dev_init(c,n,ioctl), \ + (dev_type_stop((*))) enodev, 0, (dev_type_poll((*))) enodev, \ + (dev_type_mmap((*))) enodev, 0, D_KQFILTER, dev_init(c,n,kqfilter) } + +cdev_decl(apm); diff --git a/sys/arch/loongson/loongson/conf.c b/sys/arch/loongson/loongson/conf.c index 5ae3ba5ce56..4fac5af5bfc 100644 --- a/sys/arch/loongson/loongson/conf.c +++ b/sys/arch/loongson/loongson/conf.c @@ -1,4 +1,4 @@ -/* $OpenBSD: conf.c,v 1.2 2010/02/11 20:14:49 otto Exp $ */ +/* $OpenBSD: conf.c,v 1.3 2010/02/28 08:30:27 otto Exp $ */ /* * Copyright (c) 1992, 1993 @@ -43,7 +43,8 @@ #include <sys/proc.h> #include <sys/vnode.h> #include <sys/tty.h> -#include <sys/conf.h> + +#include <machine/conf.h> /* * Block devices. @@ -101,6 +102,7 @@ cdev_decl(fd); #include "st.h" #include "bpfilter.h" #include "tun.h" +#include "apm.h" #include "com.h" cdev_decl(com); #include "lpt.h" @@ -152,7 +154,7 @@ struct cdevsw cdevsw[] = cdev_disk_init(NVND,vnd), /* 11: vnode disk */ cdev_bpf_init(NBPFILTER,bpf), /* 12: berkeley packet filter */ cdev_tun_init(NTUN,tun), /* 13: network tunnel */ - cdev_notdef(), /* 14: */ + cdev_apm_init(NAPM,apm), /* 14: apm */ cdev_notdef(), /* 15: */ cdev_lpt_init(NLPT,lpt), /* 16: Parallel printer interface */ cdev_tty_init(NCOM,com), /* 17: 16C450 serial interface */ |