--- a/distrib/sets/lists/man/mi	Fri Mar 28 05:54:49 2025 +0000
+++ b/distrib/sets/lists/man/mi	Sat Mar 29 21:15:18 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	Sat Mar 29 21:15:18 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	Sat Mar 29 21:15:18 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, sysmon_power
+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	Sat Mar 29 21:15:18 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-29 21:20:28.935194774 +1100
+++ b/src/share/man/man4/man4.mac68k/pbbat.4	2025-03-29 21:14:21.693337782 +1100
@@ -0,0 +1,111 @@
+.\" $NetBSD$
+.\"
+.\" Copyright (c) 2025 Nathaial Sloss <nathanialsloss@yahoo.com.au>
+.\" 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 and AC adaptor
+.Sh SYNOPSIS
+.Cd "pbbat* at aed?"
+.Sh DESCRIPTION
+The
+.Nm
+driver supports
+.Tn PowerBook
+1xx batteries and AC adaptors.
+.Pp
+The battery and adaptor status are 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
+                Current  CritMax  WarnMax  WarnMin  CritMin Unit
+[AC Adaptor]
+     connected:    TRUE
+[pbbat0]
+       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.
+AC Adaptor events are passed to the
+.Pa /etc/powerd/scripts/acadaptor
+script as pressed and released events when power is connected or disconnected
+respectively.
+.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 approximation of charge based on a new battery.
+.Pp
+The charge and discharge rates are approximations between successive reads of
+the battery capacity and should not be relied upon for accurate running time
+calculations.
--- /dev/null	2025-03-29 21:21:00.063989117 +1100
+++ b/src/sys/arch/mac68k/dev/pbbat.c	2025-03-29 21:00:21.317102538 +1100
@@ -0,0 +1,614 @@
+/* $NetBSD$ */
+
+/*-
+ * Copyright (c) 2025 Nathanial Sloss <nathanialsloss@yahoo.com.au>
+ * 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.
+ */
+
+/* AC Adaptor attachment and logic based on macppc/smartbat(4). */
+
+/*-
+ * Copyright (c) 2007 Michael Lorenz
+ *               2008 Magnus Henoch
+ * 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.
+ */
+
+#include <sys/cdefs.h>
+__KERNEL_RCSID(0, "$NetBSD$");
+
+#include <sys/param.h>
+#include <sys/device.h>
+#include <sys/kmem.h>
+#include <sys/types.h>
+#include <sys/systm.h>
+
+#include <dev/sysmon/sysmonvar.h>
+
+#include <machine/param.h>
+#include <machine/cpu.h>
+
+#include <mac68k/dev/pm_direct.h>
+
+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_ac_sme;
+	envsys_data_t		 sc_ac_sensor[1];
+	struct sysmon_pswitch	 sc_sm_acpower;
+	int8_t			 sc_ac_state;
+	struct sysmon_envsys	*sc_bat_sme;
+	envsys_data_t		*sc_bat_sensor;
+	struct timeval		 sc_last;
+	kmutex_t		 sc_mutex;
+	int32_t			 sc_dcapacity;
+	int32_t			 sc_dvoltage;
+	int32_t			 sc_disrate;
+	int32_t			 sc_chargerate;
+	int32_t			 sc_empty;
+	int32_t			 sc_lcapacity;
+	int32_t			 sc_wcapacity;
+	int                      sc_present;
+};
+
+#define PBBAT_AC_PRESENT	 0
+
+/* AC Adaptor states */
+#define PBBAT_AC_UNKNOWN	-1
+#define PBBAT_AC_DISCONNECTED	 0
+#define PBBAT_AC_CONNECTED	 1
+
+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_bat_sensor = kmem_zalloc(PBBAT_COUNT *
+	    sizeof(*sc->sc_bat_sensor), KM_SLEEP);
+
+	memset(&sc->sc_sm_acpower, 0, sizeof(struct sysmon_pswitch));
+	sc->sc_ac_state = PBBAT_AC_UNKNOWN;
+	sc->sc_sm_acpower.smpsw_name = "AC Power";
+	sc->sc_sm_acpower.smpsw_type = PSWITCH_TYPE_ACADAPTER;
+	if (sysmon_pswitch_register(&sc->sc_sm_acpower) != 0)
+		printf("%s: unable to register AC power status with sysmon\n",
+		    device_xname(sc->sc_dev));
+
+	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_empty = (pmdata.data[1] & 0xff) * VOLTS_MULTI;
+	sc->sc_lcapacity = (pmdata.data[0] & 0xff) * VOLTS_MULTI;
+	sc->sc_wcapacity = sc->sc_lcapacity * 12 / 10;
+
+	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_refresh_ac(struct sysmon_envsys *sme, envsys_data_t *edata)
+{
+	struct pbatt_softc *sc = sme->sme_cookie;
+	int which = edata->sensor;
+
+	switch (which) {
+		case PBBAT_AC_PRESENT:
+			edata->value_cur =
+			    (sc->sc_ac_state == PBBAT_AC_CONNECTED ? 1 : 0);
+			edata->state = ENVSYS_SVALID;
+			break;
+		default:
+			edata->value_cur = 0;
+			edata->state = ENVSYS_SINVALID;
+	}
+}
+
+static void
+bat_get_info(device_t dv)
+{
+	struct pbatt_softc *sc = device_private(dv);
+	int capunit;
+
+	capunit = ENVSYS_SWATTHOUR;
+
+	sc->sc_bat_sensor[PBBAT_DCAPACITY].units = capunit;
+	sc->sc_bat_sensor[PBBAT_CHARGERATE].units = capunit;
+	sc->sc_bat_sensor[PBBAT_DISCHARGERATE].units = capunit;
+	sc->sc_bat_sensor[PBBAT_LFCCAPACITY].units = capunit;
+	sc->sc_bat_sensor[PBBAT_CAPACITY].units = capunit;
+
+	/* Design capacity. */
+
+	/*
+	 * This is a guesstimate - repacked battery runs at 10 Watts/h for an
+	 * 1 hour.
+         */
+
+	sc->sc_bat_sensor[PBBAT_DCAPACITY].value_cur = WATTS_DESIGN * 1000;
+	sc->sc_bat_sensor[PBBAT_DCAPACITY].state = ENVSYS_SVALID;
+
+	/* Design voltage. */
+	sc->sc_bat_sensor[PBBAT_DVOLTAGE].value_cur = VOLTS_DESIGN * 1000;
+	sc->sc_bat_sensor[PBBAT_DVOLTAGE].state = ENVSYS_SVALID;
+
+	sc->sc_bat_sensor[PBBAT_LFCCAPACITY].state = ENVSYS_SINVALID;
+
+	bat_get_pm_limits(dv);
+
+	sc->sc_bat_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_bat_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)					\
+	sc->sc_ac_sensor[index].units = unit;     			\
+	sc->sc_ac_sensor[index].state = ENVSYS_SINVALID;		\
+	snprintf(sc->sc_ac_sensor[index].desc,				\
+	    sizeof(sc->sc_ac_sensor[index].desc), "%s", string);
+
+		INITDATA(PBBAT_AC_PRESENT, ENVSYS_INDICATOR, "connected");
+#undef INITDATA
+
+	sc->sc_ac_sme = sysmon_envsys_create();
+
+	if (sysmon_envsys_sensor_attach(sc->sc_ac_sme, &sc->sc_ac_sensor[0])) {
+		sysmon_envsys_destroy(sc->sc_ac_sme);
+		return;
+	}
+
+	sc->sc_ac_sme->sme_name = "AC Adaptor";
+	sc->sc_ac_sme->sme_cookie = sc;
+	sc->sc_ac_sme->sme_refresh = bat_refresh_ac;
+	sc->sc_ac_sme->sme_class = SME_CLASS_ACADAPTER;
+
+	if (sysmon_envsys_register(sc->sc_ac_sme)) {
+		aprint_error("%s: unable to register AC with sysmon\n",
+		    device_xname(sc->sc_dev));
+		sysmon_envsys_destroy(sc->sc_ac_sme);
+	}
+
+#define INITDATA(index, unit, string)					\
+	do {								\
+		sc->sc_bat_sensor[index].state = ENVSYS_SVALID;		\
+		sc->sc_bat_sensor[index].units = unit;			\
+		(void)strlcpy(sc->sc_bat_sensor[index].desc, string,	\
+		    sizeof(sc->sc_bat_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_bat_sensor[PBBAT_CHARGE_STATE].value_cur =
+		ENVSYS_BATTERY_CAPACITY_NORMAL;
+
+	sc->sc_bat_sensor[PBBAT_CAPACITY].flags |=
+	    ENVSYS_FPERCENT | ENVSYS_FVALID_MAX | ENVSYS_FMONLIMITS;
+
+	sc->sc_bat_sensor[PBBAT_CHARGE_STATE].flags |= ENVSYS_FMONSTCHANGED;
+
+	/* Disable userland monitoring on these sensors. */
+	sc->sc_bat_sensor[PBBAT_VOLTAGE].flags = ENVSYS_FMONNOTSUPP;
+	sc->sc_bat_sensor[PBBAT_CHARGERATE].flags = ENVSYS_FMONNOTSUPP;
+	sc->sc_bat_sensor[PBBAT_DISCHARGERATE].flags = ENVSYS_FMONNOTSUPP;
+	sc->sc_bat_sensor[PBBAT_DCAPACITY].flags = ENVSYS_FMONNOTSUPP;
+	sc->sc_bat_sensor[PBBAT_LFCCAPACITY].flags = ENVSYS_FMONNOTSUPP;
+	sc->sc_bat_sensor[PBBAT_DVOLTAGE].flags = ENVSYS_FMONNOTSUPP;
+
+	sc->sc_bat_sensor[PBBAT_CHARGERATE].flags |= ENVSYS_FHAS_ENTROPY;
+	sc->sc_bat_sensor[PBBAT_DISCHARGERATE].flags |= ENVSYS_FHAS_ENTROPY;
+
+	sc->sc_bat_sme = sysmon_envsys_create();
+
+	for (i = 0; i < PBBAT_COUNT; i++) {
+		if (sysmon_envsys_sensor_attach(sc->sc_bat_sme,
+			&sc->sc_bat_sensor[i]))
+			goto fail;
+	}
+
+	sc->sc_bat_sme->sme_name = device_xname(dv);
+	sc->sc_bat_sme->sme_cookie = dv;
+	sc->sc_bat_sme->sme_refresh = bat_refresh;
+	sc->sc_bat_sme->sme_class = SME_CLASS_BATTERY;
+	sc->sc_bat_sme->sme_flags = SME_POLL_ONLY;
+	sc->sc_bat_sme->sme_get_limits = bat_get_limits;
+
+	if (sysmon_envsys_register(sc->sc_bat_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_bat_sme);
+	kmem_free(sc->sc_bat_sensor, PBBAT_COUNT * sizeof(*sc->sc_bat_sensor));
+
+	sc->sc_bat_sme = NULL;
+	sc->sc_bat_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_bat_sensor[PBBAT_PRESENT].state = ENVSYS_SVALID;
+	sc->sc_bat_sensor[PBBAT_PRESENT].value_cur = 1;
+
+	if (val > VOLTS_NOBATT) {
+		sc->sc_bat_sensor[PBBAT_PRESENT].value_cur = 0;
+		sc->sc_bat_sensor[PBBAT_CHARGING].state = ENVSYS_SVALID;
+		sc->sc_bat_sensor[PBBAT_CHARGING].value_cur = 0;
+		sc->sc_bat_sensor[PBBAT_CHARGERATE].state = ENVSYS_SINVALID;
+		sc->sc_bat_sensor[PBBAT_DISCHARGERATE].state = ENVSYS_SINVALID;
+		if (sc->sc_ac_state != PBBAT_AC_CONNECTED) {
+			sysmon_pswitch_event(&sc->sc_sm_acpower,
+			    PSWITCH_EVENT_PRESSED);
+		}
+		sc->sc_ac_state = PBBAT_AC_CONNECTED;
+	} else if (val > VOLTS_CHARGING) {
+		sc->sc_bat_sensor[PBBAT_CHARGING].state = ENVSYS_SVALID;
+		sc->sc_bat_sensor[PBBAT_CHARGING].value_cur = 1;
+		sc->sc_bat_sensor[PBBAT_CHARGERATE].state = ENVSYS_SVALID;
+		sc->sc_bat_sensor[PBBAT_CHARGERATE].value_cur =
+		    sc->sc_chargerate;
+		sc->sc_bat_sensor[PBBAT_DISCHARGERATE].state = ENVSYS_SINVALID;
+		if (sc->sc_ac_state != PBBAT_AC_CONNECTED) {
+			sysmon_pswitch_event(&sc->sc_sm_acpower,
+			    PSWITCH_EVENT_PRESSED);
+		}
+		sc->sc_ac_state = PBBAT_AC_CONNECTED;
+	} else {
+		sc->sc_bat_sensor[PBBAT_CHARGING].value_cur = 0;
+		sc->sc_bat_sensor[PBBAT_CHARGING].state = ENVSYS_SVALID;
+		sc->sc_bat_sensor[PBBAT_CHARGERATE].state = ENVSYS_SINVALID;
+		sc->sc_bat_sensor[PBBAT_DISCHARGERATE].state = ENVSYS_SVALID;
+		sc->sc_bat_sensor[PBBAT_DISCHARGERATE].value_cur =
+		    sc->sc_disrate;
+		if (sc->sc_ac_state != PBBAT_AC_DISCONNECTED) {
+			sysmon_pswitch_event(&sc->sc_sm_acpower,
+			    PSWITCH_EVENT_RELEASED);
+		}
+		sc->sc_ac_state = PBBAT_AC_DISCONNECTED;
+	}
+
+	/* Remaining capacity. */
+	sc->sc_chargerate = sc->sc_bat_sensor[PBBAT_CAPACITY].value_cur;
+	sc->sc_disrate = sc->sc_bat_sensor[PBBAT_CAPACITY].value_cur;
+
+	sc->sc_bat_sensor[PBBAT_CAPACITY].value_cur =
+	    (val - sc->sc_empty) * 10 * LIMIT_SCALE;
+
+	sc->sc_chargerate =
+	    (sc->sc_bat_sensor[PBBAT_CAPACITY].value_cur - sc->sc_chargerate) * 10;
+	sc->sc_disrate =
+	    (sc->sc_disrate - sc->sc_bat_sensor[PBBAT_CAPACITY].value_cur) * 10;
+
+	/* Battery voltage. */
+	sc->sc_bat_sensor[PBBAT_VOLTAGE].value_cur = val * 1000;
+	sc->sc_bat_sensor[PBBAT_VOLTAGE].state =
+	    (val >= VOLTS_NOBATT ? ENVSYS_SINVALID : ENVSYS_SVALID);
+
+	if (val < sc->sc_lcapacity) {
+		sc->sc_bat_sensor[PBBAT_CAPACITY].state = ENVSYS_SCRITUNDER;
+		sc->sc_bat_sensor[PBBAT_CHARGE_STATE].value_cur =
+		    ENVSYS_BATTERY_CAPACITY_CRITICAL;
+	} else if (val < sc->sc_wcapacity) {
+		sc->sc_bat_sensor[PBBAT_CAPACITY].state = ENVSYS_SWARNUNDER;
+		sc->sc_bat_sensor[PBBAT_CHARGE_STATE].value_cur =
+		    ENVSYS_BATTERY_CAPACITY_WARNING;
+	} else {
+		sc->sc_bat_sensor[PBBAT_CHARGE_STATE].value_cur =
+		    ENVSYS_BATTERY_CAPACITY_NORMAL;
+	}
+
+	sc->sc_bat_sensor[PBBAT_CHARGE_STATE].state = ENVSYS_SVALID;
+
+	return val;
+}