--- a/distrib/sets/lists/man/mi Fri Mar 28 05:54:49 2025 +0000 +++ b/distrib/sets/lists/man/mi Fri Mar 28 20:38:17 2025 +1100 @@ -1556,6 +1556,7 @@ ./usr/share/man/cat4/mac68k/mem.0 man-sys-catman .cat ./usr/share/man/cat4/mac68k/netdock.0 man-sys-catman .cat ./usr/share/man/cat4/mac68k/obio.0 man-sys-catman .cat +./usr/share/man/cat4/mac68k/pbbat.0 man-sys-catman .cat ./usr/share/man/cat4/mac68k/sn.0 man-obsolete obsolete ./usr/share/man/cat4/mac68k/zsc.0 man-sys-catman .cat ./usr/share/man/cat4/mach64drm.0 man-sys-catman .cat @@ -5134,6 +5135,7 @@ ./usr/share/man/man4/mac68k/mem.4 man-sys-man .man ./usr/share/man/man4/mac68k/netdock.4 man-sys-man .man ./usr/share/man/man4/mac68k/obio.4 man-sys-man .man +./usr/share/man/man4/mac68k/pbbat.4 man-sys-man .man ./usr/share/man/man4/mac68k/sn.4 man-obsolete obsolete ./usr/share/man/man4/mac68k/zsc.4 man-sys-man .man ./usr/share/man/man4/mach64drm.4 man-sys-man .man --- a/share/man/man4/man4.mac68k/Makefile Fri Mar 28 05:54:49 2025 +0000 +++ b/share/man/man4/man4.mac68k/Makefile Fri Mar 28 20:38:17 2025 +1100 @@ -2,7 +2,7 @@ # $NetBSD: Makefile,v 1.14 2024/08/01 13:41:14 nat Exp $ MAN= ae.4 ascaudio.4 autoconf.4 cpi.4 intro.4 iwm.4 mainbus.4 mem.4 \ - netdock.4 obio.4 zsc.4 + netdock.4 pbbat.4 obio.4 zsc.4 MLINKS= mem.4 kmem.4 MANSUBDIR=/mac68k --- a/sys/arch/mac68k/conf/files.mac68k Fri Mar 28 05:54:49 2025 +0000 +++ b/sys/arch/mac68k/conf/files.mac68k Fri Mar 28 20:38:17 2025 +1100 @@ -31,7 +31,7 @@ file arch/mac68k/dev/adbsysasm.s file arch/mac68k/dev/adb_direct.c file arch/mac68k/dev/pm_direct.c -device aed +device aed { } attach aed at adb file arch/mac68k/dev/aed.c aed needs-flag @@ -43,6 +43,10 @@ device ams: wsmousedev attach ams at adb file arch/mac68k/dev/ams.c ams needs-flag +device pbbat: sysmon_envsys +attach pbbat at aed +file arch/mac68k/dev/pbbat.c pbbat needs-flag + # ASC (beeper) device asc attach asc at obio --- a/sys/arch/mac68k/dev/aed.c Fri Mar 28 05:54:49 2025 +0000 +++ b/sys/arch/mac68k/dev/aed.c Fri Mar 28 20:38:17 2025 +1100 @@ -164,6 +164,10 @@ aedattach(device_t parent, device_t self printf("ADB Event device\n"); +#if 1 + (void)config_found(self, &aa_args, NULL, CFARGS_NONE); +#endif + return; } --- /dev/null 2025-03-28 20:39:34.488654983 +1100 +++ b/src/share/man/man4/man4.mac68k/pbbat.4 2025-03-28 20:19:13.663005306 +1100 @@ 0,0 +1,104 @@ +.\" $NetBSD$ +.\" +.\" Copyright (c) 2025 Nathaial Sloss +.\" All rights reserved. +.\" +.\" Copyright (c) 2002, 2004, 2010 The NetBSD Foundation, Inc. +.\" 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. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. 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 FOUNDATION 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 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. +.\" +.Dd March 28, 2025 +.Dt PBBAT 4 +.Os +.Sh NAME +.Nm pbbat +.Nd PowerBook 1xx Battery +.Sh SYNOPSIS +.Cd "pbbat* at aed?" +.Sh DESCRIPTION +The +.Nm +driver supports +.Tn PowerBook +1xx batteries. +.Pp +The battery status is made available through the +.Xr envsys 4 +.Tn API . +The battery information can be displayed also with the +.Xr envstat 8 +command: +.Bd -literal -offset 2n +$ envstat -d pbbat0 + Current CritMax WarnMax WarnMin CritMin Unit + present: TRUE +design voltage: 6.000 V + voltage: 7.267 V + design cap: 60.000 Wh + last full cap: N/A + charge: 47.910 3.674% 2.799% Wh (47.91%) + charge rate: N/A +discharge rate: 5.641 W + charging: TRUE + charge state: NORMAL +.Ed +.Sh EVENTS +The +.Nm +driver is able to send events to +.Xr powerd 8 +daemon when a capacity state has been changed. +The new state will be reported as the +.Em fourth +argument to the +.Pa /etc/powerd/scripts/sensor_battery +script. +If a custom capacity limit was set via +.Xr envstat 8 , +the +.Nm +driver will report a +.Em user-capacity +event to the same script when current capacity limit has been reached. +.Sh SEE ALSO +.Xr adb 4 , +.Xr envsys 4 , +.Xr envstat 8 , +.Xr powerd 8 +.Sh AUTHORS +.An Nathanial Sloss +.Sh HISTORY +The +.Nm +driver appeared in +.Nx 11 . +.Sh BUGS +This driver currently only supports the +.Tn PowerBook +100 series batteries excluding the 150 and 190 computers. +.Pp +The design capacity is an appoximation of charge based on a new battery. +.Pp +The charge and discharge rates are approximations between succsessive reads of +the batttery capacity and should not be relied apon for accurate running time +calculations. --- /dev/null 2025-03-28 20:39:58.552097454 +1100 +++ b/src/sys/arch/mac68k/dev/pbbat.c 2025-03-28 13:49:37.127928608 +1100 @@ 0,1 +1,503 @@ +/* $NetBSD$ */ + +/*- + * Copyright (c) 2025 Nathanial Sloss + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. 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 FOUNDATION 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 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. + */ + +/* Based on acpibat(4) */ + +/*- + * Copyright (c) 2003 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Charles M. Hannum of By Noon Software, Inc. + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. 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 FOUNDATION 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 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. + */ + +/* + * Copyright 2001 Bill Sommerfeld. + * 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 for the NetBSD Project by + * Wasabi Systems, Inc. + * 4. The name of Wasabi Systems, Inc. may not be used to endorse + * or promote products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``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 WASABI SYSTEMS, INC + * 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 +__KERNEL_RCSID(0, "$NetBSD$"); + +#include +#include +#include +#include +#include + +#include + +#include +#include + +#include + +static int pbbatmatch(device_t, cfdata_t, void *); +static void pbbatattach(device_t, device_t, void *); + +static void bat_get_pm_limits(device_t); +static uint16_t bat_get_status(device_t); +static void bat_init_envsys(device_t); +static void bat_update_status(void *); + +extern int pm_pmgrop_pm1(PMData *); + +struct pbatt_softc { + device_t sc_dev; + struct sysmon_envsys *sc_sme; + struct timeval sc_last; + envsys_data_t *sc_sensor; + kmutex_t sc_mutex; + int32_t sc_dcapacity; + int32_t sc_dvoltage; + int32_t sc_disrate; + int32_t sc_chargerate; + int32_t sc_lcapacity; + int32_t sc_wcapacity; + int sc_present; +}; + +enum { + PBBAT_PRESENT = 0, + PBBAT_DVOLTAGE = 1, + PBBAT_VOLTAGE = 2, + PBBAT_DCAPACITY = 3, + PBBAT_LFCCAPACITY = 4, + PBBAT_CAPACITY = 5, + PBBAT_CHARGERATE = 6, + PBBAT_DISCHARGERATE = 7, + PBBAT_CHARGING = 8, + PBBAT_CHARGE_STATE = 9, + PBBAT_COUNT = 10 +}; + +/* Driver definition */ +CFATTACH_DECL_NEW(pbbat, sizeof(struct pbatt_softc), + pbbatmatch, pbbatattach, NULL, NULL); + +/* Battery voltage definitions (mV) */ +#define VOLTS_DESIGN 6000 +#define WATTS_DESIGN 60000 /* mW */ +#define VOLTS_CHARGING 6600 +#define VOLTS_NOBATT 7700 + +#define VOLTS_MULTI 35 /* PM value multiplier. */ +#define LIMIT_SCALE (100 * 100 / (VOLTS_DESIGN / 1000)) + +#define PM_BATT_VOLTS 0x68 /* 0x69 is a duplicate. */ +#define PM_BATT_LIMITS 0x6a + +static int +pbbatmatch(device_t parent, cfdata_t cf, void *aux) +{ + switch (mac68k_machine.machineid) { + case MACH_MACPB140: + case MACH_MACPB145: + case MACH_MACPB160: + case MACH_MACPB165: + case MACH_MACPB165C: + case MACH_MACPB170: + case MACH_MACPB180: + case MACH_MACPB180C: + return 1; + break; + default: + return 0; + } + + return 0; +} + +static void +pbbatattach(device_t parent, device_t self, void *aux) +{ + struct pbatt_softc *sc = device_private(self); + + aprint_naive(": PowerBook Battery\n"); + aprint_normal(": PowerBook Battery\n"); + + mutex_init(&sc->sc_mutex, MUTEX_DEFAULT, IPL_NONE); + sc->sc_sensor = kmem_zalloc(PBBAT_COUNT * + sizeof(*sc->sc_sensor), KM_SLEEP); + + config_interrupts(self, bat_init_envsys); +} + +static void +bat_get_pm_limits(device_t self) +{ + int s; + int rval; + PMData pmdata; + struct pbatt_softc *sc = device_private(self); + + s = splhigh(); + + pmdata.command = PM_BATT_LIMITS; + pmdata.num_data = 0; + pmdata.data[0] = pmdata.data[1] = 0; + pmdata.s_buf = pmdata.data; + pmdata.r_buf = pmdata.data; + rval = pm_pmgrop_pm1(&pmdata); + if (rval != 0) { +#ifdef ADB_DEBUG + if (adb_debug) + printf("pm: PM is not ready. error code=%08x\n", rval); +#endif + splx(s); + return; + } + + splx(s); + + sc->sc_lcapacity = (pmdata.data[1] & 0xff) * VOLTS_MULTI; + sc->sc_wcapacity = (pmdata.data[0] & 0xff) * VOLTS_MULTI; + + return; +} + +static uint16_t +bat_get_voltage(void) +{ + int s; + int rval; + PMData pmdata; + + s = splhigh(); + + pmdata.command = PM_BATT_VOLTS; + pmdata.num_data = 0; + pmdata.data[0] = pmdata.data[1] = 0; + pmdata.s_buf = pmdata.data; + pmdata.r_buf = pmdata.data; + rval = pm_pmgrop_pm1(&pmdata); + if (rval != 0) { +#ifdef ADB_DEBUG + if (adb_debug) + printf("pm: PM is not ready. error code=%08x\n", rval); +#endif + splx(s); + return 0; + } + + splx(s); + + return (pmdata.data[1] & 0xff) * VOLTS_MULTI; +} + +static void +bat_refresh(struct sysmon_envsys *sme, envsys_data_t *edata) +{ + device_t self = sme->sme_cookie; + struct pbatt_softc *sc = device_private(self); + struct timeval tv, tmp; + + tmp.tv_sec = 10; + tmp.tv_usec = 0; + + microtime(&tv); + timersub(&tv, &tmp, &tv); + if (timercmp(&tv, &sc->sc_last, <) != 0) + return; + + bat_update_status(self); +} + +static void +bat_get_info(device_t dv) +{ + struct pbatt_softc *sc = device_private(dv); + int capunit; + + capunit = ENVSYS_SWATTHOUR; + + sc->sc_sensor[PBBAT_DCAPACITY].units = capunit; + sc->sc_sensor[PBBAT_CHARGERATE].units = capunit; + sc->sc_sensor[PBBAT_DISCHARGERATE].units = capunit; + sc->sc_sensor[PBBAT_LFCCAPACITY].units = capunit; + sc->sc_sensor[PBBAT_CAPACITY].units = capunit; + + /* Design capacity. */ + + /* + * This is a guesstimate - repacked battery runs at 10 Watts/h for an + * 1 hour. + */ + + sc->sc_sensor[PBBAT_DCAPACITY].value_cur = WATTS_DESIGN * 1000; + sc->sc_sensor[PBBAT_DCAPACITY].state = ENVSYS_SVALID; + + /* Design voltage. */ + sc->sc_sensor[PBBAT_DVOLTAGE].value_cur = VOLTS_DESIGN * 1000; + sc->sc_sensor[PBBAT_DVOLTAGE].state = ENVSYS_SVALID; + + sc->sc_sensor[PBBAT_LFCCAPACITY].state = ENVSYS_SINVALID; + + bat_get_pm_limits(dv); + + sc->sc_sensor[PBBAT_CAPACITY].value_max = 100 * 1000 * 1000; +} + +static void +bat_get_limits(struct sysmon_envsys *sme, envsys_data_t *edata, + sysmon_envsys_lim_t *limits, uint32_t *props) +{ + device_t self = sme->sme_cookie; + struct pbatt_softc *sc = device_private(self); + + if (edata->sensor != PBBAT_CAPACITY) + return; + + limits->sel_critmin = sc->sc_lcapacity * LIMIT_SCALE; + limits->sel_warnmin = sc->sc_wcapacity * LIMIT_SCALE; + + *props |= PROP_BATTCAP | PROP_BATTWARN | PROP_DRIVER_LIMITS; +} + +static void +bat_update_status(void *arg) +{ + device_t dv = arg; + struct pbatt_softc *sc = device_private(dv); + int i; + uint16_t val; + + mutex_enter(&sc->sc_mutex); + + val = bat_get_status(dv); + if (val != 0) { + if (sc->sc_present == 0) + bat_get_info(dv); + } else { + i = PBBAT_DVOLTAGE; + while (i < PBBAT_COUNT) { + sc->sc_sensor[i].state = ENVSYS_SINVALID; + i++; + } + } + + sc->sc_present = (val >= VOLTS_NOBATT ? 0 : 1); + + microtime(&sc->sc_last); + + mutex_exit(&sc->sc_mutex); +} + +static void +bat_init_envsys(device_t dv) +{ + struct pbatt_softc *sc = device_private(dv); + int i; + +#define INITDATA(index, unit, string) \ + do { \ + sc->sc_sensor[index].state = ENVSYS_SVALID; \ + sc->sc_sensor[index].units = unit; \ + (void)strlcpy(sc->sc_sensor[index].desc, string, \ + sizeof(sc->sc_sensor[index].desc)); \ + } while (/* CONSTCOND */ 0) + + INITDATA(PBBAT_PRESENT, ENVSYS_INDICATOR, "present"); + INITDATA(PBBAT_DCAPACITY, ENVSYS_SWATTHOUR, "design cap"); + INITDATA(PBBAT_LFCCAPACITY, ENVSYS_SWATTHOUR, "last full cap"); + INITDATA(PBBAT_DVOLTAGE, ENVSYS_SVOLTS_DC, "design voltage"); + INITDATA(PBBAT_VOLTAGE, ENVSYS_SVOLTS_DC, "voltage"); + INITDATA(PBBAT_CAPACITY, ENVSYS_SWATTHOUR, "charge"); + INITDATA(PBBAT_CHARGERATE, ENVSYS_SWATTS, "charge rate"); + INITDATA(PBBAT_DISCHARGERATE, ENVSYS_SWATTS, "discharge rate"); + INITDATA(PBBAT_CHARGING, ENVSYS_BATTERY_CHARGE, "charging"); + INITDATA(PBBAT_CHARGE_STATE, ENVSYS_BATTERY_CAPACITY, "charge state"); + +#undef INITDATA + + sc->sc_sensor[PBBAT_CHARGE_STATE].value_cur = + ENVSYS_BATTERY_CAPACITY_NORMAL; + + sc->sc_sensor[PBBAT_CAPACITY].flags |= + ENVSYS_FPERCENT | ENVSYS_FVALID_MAX | ENVSYS_FMONLIMITS; + + sc->sc_sensor[PBBAT_CHARGE_STATE].flags |= ENVSYS_FMONSTCHANGED; + + /* Disable userland monitoring on these sensors. */ + sc->sc_sensor[PBBAT_VOLTAGE].flags = ENVSYS_FMONNOTSUPP; + sc->sc_sensor[PBBAT_CHARGERATE].flags = ENVSYS_FMONNOTSUPP; + sc->sc_sensor[PBBAT_DISCHARGERATE].flags = ENVSYS_FMONNOTSUPP; + sc->sc_sensor[PBBAT_DCAPACITY].flags = ENVSYS_FMONNOTSUPP; + sc->sc_sensor[PBBAT_LFCCAPACITY].flags = ENVSYS_FMONNOTSUPP; + sc->sc_sensor[PBBAT_DVOLTAGE].flags = ENVSYS_FMONNOTSUPP; + + sc->sc_sensor[PBBAT_CHARGERATE].flags |= ENVSYS_FHAS_ENTROPY; + sc->sc_sensor[PBBAT_DISCHARGERATE].flags |= ENVSYS_FHAS_ENTROPY; + + sc->sc_sme = sysmon_envsys_create(); + + for (i = 0; i < PBBAT_COUNT; i++) { + if (sysmon_envsys_sensor_attach(sc->sc_sme, + &sc->sc_sensor[i])) + goto fail; + } + + sc->sc_sme->sme_name = device_xname(dv); + sc->sc_sme->sme_cookie = dv; + sc->sc_sme->sme_refresh = bat_refresh; + sc->sc_sme->sme_class = SME_CLASS_BATTERY; + sc->sc_sme->sme_flags = SME_POLL_ONLY; + sc->sc_sme->sme_get_limits = bat_get_limits; + + if (sysmon_envsys_register(sc->sc_sme)) + goto fail; + + bat_get_pm_limits(dv); + bat_update_status(dv); + + return; +fail: + aprint_error("failed to initialize sysmon\n"); + + sysmon_envsys_destroy(sc->sc_sme); + kmem_free(sc->sc_sensor, PBBAT_COUNT * sizeof(*sc->sc_sensor)); + + sc->sc_sme = NULL; + sc->sc_sensor = NULL; +} + +static uint16_t +bat_get_status(device_t dv) +{ + struct pbatt_softc *sc = device_private(dv); + uint16_t val; + + val = bat_get_voltage(); + + sc->sc_sensor[PBBAT_PRESENT].state = ENVSYS_SVALID; + sc->sc_sensor[PBBAT_PRESENT].value_cur = 1; + + if (val > VOLTS_NOBATT) { + sc->sc_sensor[PBBAT_PRESENT].value_cur = 0; + sc->sc_sensor[PBBAT_CHARGING].state = ENVSYS_SVALID; + sc->sc_sensor[PBBAT_CHARGING].value_cur = 0; + sc->sc_sensor[PBBAT_CHARGERATE].state = ENVSYS_SINVALID; + sc->sc_sensor[PBBAT_DISCHARGERATE].state = ENVSYS_SINVALID; + } else if (val > VOLTS_CHARGING) { + sc->sc_sensor[PBBAT_CHARGING].state = ENVSYS_SVALID; + sc->sc_sensor[PBBAT_CHARGING].value_cur = 1; + sc->sc_sensor[PBBAT_CHARGERATE].state = ENVSYS_SVALID; + sc->sc_sensor[PBBAT_CHARGERATE].value_cur = sc->sc_chargerate; + sc->sc_sensor[PBBAT_DISCHARGERATE].state = ENVSYS_SINVALID; + } else { + sc->sc_sensor[PBBAT_CHARGING].value_cur = 0; + sc->sc_sensor[PBBAT_CHARGING].state = ENVSYS_SVALID; + sc->sc_sensor[PBBAT_CHARGERATE].state = ENVSYS_SINVALID; + sc->sc_sensor[PBBAT_DISCHARGERATE].state = ENVSYS_SVALID; + sc->sc_sensor[PBBAT_DISCHARGERATE].value_cur = sc->sc_disrate; + } + + /* Remaining capacity. */ + sc->sc_chargerate = sc->sc_sensor[PBBAT_CAPACITY].value_cur; + sc->sc_disrate = sc->sc_sensor[PBBAT_CAPACITY].value_cur; + + sc->sc_sensor[PBBAT_CAPACITY].value_cur = + (val - sc->sc_lcapacity) * 10 * LIMIT_SCALE; + + sc->sc_chargerate = + (sc->sc_sensor[PBBAT_CAPACITY].value_cur - sc->sc_chargerate) * 10; + sc->sc_disrate = + (sc->sc_disrate - sc->sc_sensor[PBBAT_CAPACITY].value_cur) * 10; + + /* Battery voltage. */ + sc->sc_sensor[PBBAT_VOLTAGE].value_cur = val * 1000; + sc->sc_sensor[PBBAT_VOLTAGE].state = + (val >= VOLTS_NOBATT ? ENVSYS_SINVALID : ENVSYS_SVALID); + + sc->sc_sensor[PBBAT_CHARGE_STATE].state = ENVSYS_SVALID; + sc->sc_sensor[PBBAT_CHARGE_STATE].value_cur = + ENVSYS_BATTERY_CAPACITY_NORMAL; + + if (sc->sc_sensor[PBBAT_CAPACITY].value_cur < sc->sc_wcapacity) { + sc->sc_sensor[PBBAT_CAPACITY].state = ENVSYS_SWARNUNDER; + sc->sc_sensor[PBBAT_CHARGE_STATE].value_cur = + ENVSYS_BATTERY_CAPACITY_WARNING; + } + + if (sc->sc_sensor[PBBAT_CAPACITY].value_cur < sc->sc_lcapacity) { + sc->sc_sensor[PBBAT_CAPACITY].state = ENVSYS_SCRITUNDER; + sc->sc_sensor[PBBAT_CHARGE_STATE].value_cur = + ENVSYS_BATTERY_CAPACITY_CRITICAL; + } + + return val; +}