[PATCH] New aibs(4) driver for ASUSTeK AI Booster (ACPI ATK0110) hardware monitoring, with sensor state support through thresholds from ACPI.

Constantine A. Murenin cnst+dfly at bugmail.mojo.ru
Thu Sep 24 00:15:55 PDT 2009


---
 share/man/man4/Makefile        |    1 +
 share/man/man4/aibs.4          |  222 ++++++++++++++++++++++
 sys/conf/files                 |    1 +
 sys/config/LINT                |    1 +
 sys/dev/acpica5/Makefile       |    2 +-
 sys/dev/acpica5/aibs/Makefile  |    6 +
 sys/dev/acpica5/aibs/atk0110.c |  401 ++++++++++++++++++++++++++++++++++++++++
 7 files changed, 633 insertions(+), 1 deletions(-)
 create mode 100644 share/man/man4/aibs.4
 create mode 100644 sys/dev/acpica5/aibs/Makefile
 create mode 100644 sys/dev/acpica5/aibs/atk0110.c

diff --git a/share/man/man4/Makefile b/share/man/man4/Makefile
index b3bca7b..6b1160a 100644
--- a/share/man/man4/Makefile
+++ b/share/man/man4/Makefile
@@ -20,6 +20,7 @@ MAN=	aac.4 \
 	ahc.4 \
 	ahci.4 \
 	ahd.4 \
+	aibs.4 \
 	ale.4 \
 	altq.4 \
 	amd.4 \
diff --git a/share/man/man4/aibs.4 b/share/man/man4/aibs.4
new file mode 100644
index 0000000..aca8065
--- /dev/null
+++ b/share/man/man4/aibs.4
@@ -0,0 +1,222 @@
+.\"	$OpenBSD: aibs.4,v 1.4 2009/07/30 06:30:45 jmc Exp $
+.\"
+.\" Copyright (c) 2009 Constantine A. Murenin <cnst+dfly at bugmail.mojo.ru>
+.\"
+.\" Permission to use, copy, modify, and distribute this software for any
+.\" purpose with or without fee is hereby granted, provided that the above
+.\" copyright notice and this permission notice appear in all copies.
+.\"
+.\" THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+.\" WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+.\" MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+.\" ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+.\" WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+.\"
+.Dd September 23, 2009
+.Dt AIBS 4
+.Os
+.Sh NAME
+.Nm aibs
+.Nd "ASUSTeK AI Booster ACPI ATK0110 voltage, temperature and fan sensor"
+.Sh SYNOPSIS
+To compile this driver into the kernel,
+place the following lines in your
+kernel configuration file:
+.Bd -ragged -offset indent
+.Cd "device acpi"
+.Cd "device aibs"
+.Ed
+.Pp
+Alternatively, to load the driver as a
+module at boot time, place the following lines in
+.Xr loader.conf 5 :
+.Bd -literal -offset indent
+acpi_load="YES"
+aibs_load="YES"
+.Ed
+.Sh DESCRIPTION
+The
+.Nm
+driver provides support for the voltage, temperature and fan sensors
+available through the
+ATK0110
+ASOC
+ACPI
+device
+on ASUSTeK motherboards.
+The number of sensors of each type,
+as well as the description of each sensor,
+varies according to the motherboard.
+.Pp
+The driver supports an arbitrary set of sensors,
+provides descriptions regarding what each sensor is used for,
+and reports whether each sensor is within the specifications
+as defined by the motherboard manufacturer through ACPI.
+.Pp
+The
+.Nm
+driver supports sensor states as follows:
+temperature sensors can have a state of
+.Dv OK ,
+.Dv WARN ,
+.Dv CRIT
+or
+.Dv UNKNOWN ;
+fan and voltage sensors can have a state of
+.Dv OK
+or
+.Dv WARN
+only.
+Temperature sensors that have a reading of 0
+are marked as invalid and their state is set to
+.Dv UNKNOWN ,
+whereas all other sensors are always assumed valid.
+Temperature sensors have two upper limits
+.Dv ( WARN
+and
+.Dv CRIT ) ,
+fan sensors have either only the lower limit, or
+one lower and one upper limit,
+and voltage sensors always have a lower and an upper limit.
+.Pp
+Sensor values are made available through the
+.Dv HW_SENSORS
+.Xr sysctl 3
+interface,
+and can be monitored with the
+.Xr systat 1
+.Ar sensors
+display,
+.Xr sensorsd 8
+and
+.Xr sysctl 8
+.Ar hw.sensors .
+For example, on an Asus Stricker Extreme motherboard:
+.Bd -literal -offset indent
+$ sysctl hw.sensors.aibs0
+hw.sensors.aibs0.temp0=31.00 degC (CPU Temperature), OK
+hw.sensors.aibs0.temp1=43.00 degC (MB Temperature), OK
+hw.sensors.aibs0.fan0=2490 RPM (CPU FAN Speed), OK
+hw.sensors.aibs0.fan1=0 RPM (CHASSIS FAN Speed), WARNING
+hw.sensors.aibs0.fan2=0 RPM (OPT1 FAN Speed), WARNING
+hw.sensors.aibs0.fan3=0 RPM (OPT2 FAN Speed), WARNING
+hw.sensors.aibs0.fan4=0 RPM (OPT3 FAN Speed), WARNING
+hw.sensors.aibs0.fan5=0 RPM (OPT4 FAN Speed), WARNING
+hw.sensors.aibs0.fan6=0 RPM (OPT5 FAN Speed), WARNING
+hw.sensors.aibs0.fan7=0 RPM (PWR FAN Speed), WARNING
+hw.sensors.aibs0.volt0=1.26 VDC (Vcore Voltage), OK
+hw.sensors.aibs0.volt1=3.25 VDC ( +3.3 Voltage), OK
+hw.sensors.aibs0.volt2=4.95 VDC ( +5.0 Voltage), OK
+hw.sensors.aibs0.volt3=11.78 VDC (+12.0 Voltage), OK
+hw.sensors.aibs0.volt4=1.23 VDC (1.2VHT Voltage), OK
+hw.sensors.aibs0.volt5=1.50 VDC (SB CORE Voltage), OK
+hw.sensors.aibs0.volt6=1.25 VDC (CPU VTT Voltage), OK
+hw.sensors.aibs0.volt7=0.93 VDC (DDR2 TERM Voltage), OK
+hw.sensors.aibs0.volt8=1.23 VDC (NB CORE Voltage), OK
+hw.sensors.aibs0.volt9=1.87 VDC (MEMORY Voltage), OK
+.Ed
+.Pp
+Generally, sensors provided by the
+.Nm
+driver may also be supported by a variety of other drivers,
+such as
+.Xr lm 4
+or
+.Xr it 4 .
+The precise collection of
+.Nm
+sensors is comprised of the sensors
+specifically utilised in the motherboard
+design, which may be supported through
+a combination of one or more physical hardware monitoring chips.
+.Pp
+The
+.Nm
+driver, however, provides the following advantages
+when compared to the native hardware monitoring drivers:
+.Bl -bullet
+.It
+Sensor values from
+.Nm
+are expected to be more reliable.
+For example, voltage sensors in many hardware monitoring chips
+can only sense voltage from 0 to 2 or 4 volts, and the excessive
+voltage is removed by the resistors, which may vary with the motherboard
+and with the voltage that is being sensed.
+In
+.Nm ,
+the required resistor factors are provided by
+the motherboard manufacturer through ACPI;
+in the native drivers, the resistor factors
+are encoded into the driver based on the chip manufacturer's recommendations.
+In essence, sensor values from
+.Nm
+are very likely to be identical to the readings from the
+Hardware Monitor screen in the BIOS.
+.It
+Sensor descriptions from
+.Nm
+are more likely to match the markings on the motherboard.
+.It
+Sensor status is supported by
+.Nm .
+The status is reported based on the acceptable range of values
+for each individual sensor as suggested by the motherboard manufacturer.
+For example, the threshold for the CPU temperature sensor is likely
+to be significantly higher than that for the chassis temperature sensor.
+.It
+Support for newer chips in
+.Nm .
+Newer chips may miss a native driver,
+but should be supported through
+.Nm
+regardless.
+.El
+.Pp
+As a result, sensor readings from the actual
+native hardware monitoring drivers
+are redundant when
+.Nm
+is present, and
+may be ignored as appropriate.
+Whereas on
+.Ox
+the native drivers have to be specifically disabled should
+their presence be judged unnecessary,
+on
+.Dx
+the
+.Xr lm 4
+and
+.Xr it 4
+are not probed provided that
+.Xr acpi 4
+is configured and the system potentially supports
+the hardware monitoring chip through ACPI.
+.Sh SEE ALSO
+.Xr systat 1 ,
+.Xr sysctl 3 ,
+.Xr acpi 4 ,
+.Xr intro 4 ,
+.Xr sensorsd 8 ,
+.Xr sysctl 8
+.Sh HISTORY
+The
+.Nm
+driver first appeared in
+.Ox 4.7
+and
+.Dx 2.5 .
+.Sh AUTHORS
+The
+.Nm
+driver was written for
+.Ox
+and
+.Dx
+by
+.An Constantine A. Murenin Aq http://cnst.su/ ,
+David R. Cheriton School of Computer Science,
+University of Waterloo.
diff --git a/sys/conf/files b/sys/conf/files
index 2449b83..b3e8e75 100644
--- a/sys/conf/files
+++ b/sys/conf/files
@@ -1712,6 +1712,7 @@ ${OSACPI_MI_DIR}/acpi_asus/acpi_asus.c		optional acpi_asus acpi
 ${OSACPI_MI_DIR}/acpi_toshiba/acpi_toshiba.c	optional acpi_toshiba acpi
 ${OSACPI_MI_DIR}/acpi_thinkpad/acpi_thinkpad.c	optional acpi_thinkpad acpi
 ${OSACPI_MI_DIR}/acpi_video/acpi_video.c	optional acpi_video acpi
+${OSACPI_MI_DIR}/aibs/atk0110.c			optional aibs acpi
 
 # ACPICA code
 ${ACPICA_DIR}/debugger/dbcmds.c			optional acpi acpi_debug
diff --git a/sys/config/LINT b/sys/config/LINT
index 5e2995b..f8cee29 100644
--- a/sys/config/LINT
+++ b/sys/config/LINT
@@ -2663,6 +2663,7 @@ device		acpi_asus	# Asus laptop support
 device		acpi_thinkpad	# ThinkPad support
 device		acpi_toshiba	# Toshiba laptop support
 device		acpi_video	# ACPI video extensions
+device		aibs		# ASUSTeK AI Booster (ACPI ASOC ATK0110)
 device		pmtimer		# adjust the system clock after resume
 
 # DRM options:
diff --git a/sys/dev/acpica5/Makefile b/sys/dev/acpica5/Makefile
index 48b9bda..30574a6 100644
--- a/sys/dev/acpica5/Makefile
+++ b/sys/dev/acpica5/Makefile
@@ -115,7 +115,7 @@ acpi_wakecode.h: acpi_wakecode.S
 	${MAKE} -f ${SYSDIR}/${OSACPI_MD_DIR}/Makefile \
 		MAKESRCPATH=${SYSDIR}/${OSACPI_MD_DIR}
 
-SUBDIR=	acpi_asus acpi_thinkpad acpi_toshiba acpi_video
+SUBDIR=	acpi_asus acpi_thinkpad acpi_toshiba acpi_video aibs
 all: ${PROG} ${SUBDIR}
 
 .include <bsd.kmod.mk>
diff --git a/sys/dev/acpica5/aibs/Makefile b/sys/dev/acpica5/aibs/Makefile
new file mode 100644
index 0000000..d75641a
--- /dev/null
+++ b/sys/dev/acpica5/aibs/Makefile
@@ -0,0 +1,6 @@
+KMOD=		aibs
+CFLAGS+=	-I${.OBJDIR}/.. -I${.CURDIR}/..
+SRCS=		atk0110.c
+SRCS+=		opt_acpi.h bus_if.h device_if.h
+
+.include <bsd.kmod.mk>
diff --git a/sys/dev/acpica5/aibs/atk0110.c b/sys/dev/acpica5/aibs/atk0110.c
new file mode 100644
index 0000000..9a29782
--- /dev/null
+++ b/sys/dev/acpica5/aibs/atk0110.c
@@ -0,0 +1,401 @@
+/*	$OpenBSD: atk0110.c,v 1.1 2009/07/23 01:38:16 cnst Exp $	*/
+
+/*
+ * Copyright (c) 2009 Constantine A. Murenin <cnst+dfly at bugmail.mojo.ru>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <sys/cdefs.h>
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/bus.h>
+#include <sys/module.h>
+#include <sys/malloc.h>
+
+#include <sys/sensors.h>
+
+#include "acpi.h"
+#include "acpivar.h"
+
+/*
+ * ASUSTeK AI Booster (ACPI ATK0110).
+ *
+ * This code was originally written for OpenBSD after the techniques
+ * described in the Linux's asus_atk0110.c and FreeBSD's acpi_aiboost.c
+ * were verified to be accurate on the actual hardware kindly provided by
+ * Sam Fourman Jr.  It was subsequently ported from OpenBSD to DragonFly BSD.
+ *
+ *				  -- Constantine A. Murenin <http://cnst.su/>
+ */
+
+#define AIBS_MORE_SENSORS
+#define AIBS_VERBOSE
+
+struct aibs_sensor {
+	struct ksensor	s;
+	int64_t		i;
+	int64_t		l;
+	int64_t		h;
+};
+
+struct aibs_softc {
+	struct device		*sc_dev;
+	ACPI_HANDLE		sc_ah;
+
+	struct aibs_sensor	*sc_asens_volt;
+	struct aibs_sensor	*sc_asens_temp;
+	struct aibs_sensor	*sc_asens_fan;
+
+	struct ksensordev	sc_sensordev;
+};
+
+
+static int aibs_probe(struct device *);
+static int aibs_attach(struct device *);
+static int aibs_detach(struct device *);
+static void aibs_refresh(void *);
+
+static void aibs_attach_sif(struct aibs_softc *, enum sensor_type);
+static void aibs_refresh_r(struct aibs_softc *, enum sensor_type);
+
+
+static device_method_t aibs_methods[] = {
+	DEVMETHOD(device_probe,		aibs_probe),
+	DEVMETHOD(device_attach,	aibs_attach),
+	DEVMETHOD(device_detach,	aibs_detach),
+	{ NULL, NULL }
+};
+
+static driver_t aibs_driver = {
+	"aibs",
+	aibs_methods,
+	sizeof(struct aibs_softc)
+};
+
+static devclass_t aibs_devclass;
+
+DRIVER_MODULE(aibs, acpi, aibs_driver, aibs_devclass, NULL, NULL);
+
+
+static char* aibs_hids[] = {
+	"ATK0110",
+	NULL
+};
+
+static int
+aibs_probe(struct device *dev)
+{
+
+	if (acpi_disabled("aibs") ||
+	    ACPI_ID_PROBE(device_get_parent(dev), dev, aibs_hids) == NULL)
+		return ENXIO;
+
+	device_set_desc(dev, "ASUSTeK AI Booster (ACPI ASOC ATK0110)");
+	return 0;
+}
+
+static int
+aibs_attach(struct device *dev)
+{
+	struct aibs_softc	*sc;
+
+	sc = device_get_softc(dev);
+	sc->sc_dev = dev;
+	sc->sc_ah = acpi_get_handle(dev);
+
+	strlcpy(sc->sc_sensordev.xname, device_get_nameunit(dev),
+	    sizeof(sc->sc_sensordev.xname));
+
+	aibs_attach_sif(sc, SENSOR_VOLTS_DC);
+	aibs_attach_sif(sc, SENSOR_TEMP);
+	aibs_attach_sif(sc, SENSOR_FANRPM);
+
+	if (sc->sc_sensordev.sensors_count == 0) {
+		device_printf(dev, "no sensors found\n");
+		return ENXIO;
+	}
+
+	if (sensor_task_register(sc, aibs_refresh, 5)) {
+		device_printf(dev, "unable to register update task\n");
+		return ENXIO;
+	}
+
+	sensordev_install(&sc->sc_sensordev);
+	return 0;
+}
+
+static void
+aibs_attach_sif(struct aibs_softc *sc, enum sensor_type st)
+{
+	ACPI_STATUS		s;
+	ACPI_BUFFER		b;
+	ACPI_OBJECT		*bp, *o;
+	int			i, n;
+	char			name[] = "?SIF";
+	struct aibs_sensor	*as;
+
+	switch (st) {
+	case SENSOR_TEMP:
+		name[0] = 'T';
+		break;
+	case SENSOR_FANRPM:
+		name[0] = 'F';
+		break;
+	case SENSOR_VOLTS_DC:
+		name[0] = 'V';
+		break;
+	default:
+		return;
+	}
+
+	b.Length = ACPI_ALLOCATE_BUFFER;
+	s = AcpiEvaluateObjectTyped(sc->sc_ah, name, NULL, &b,
+	    ACPI_TYPE_PACKAGE);
+	if (ACPI_FAILURE(s)) {
+		device_printf(sc->sc_dev, "%s not found\n", name);
+		return;
+	}
+
+	bp = b.Pointer;
+	o = bp->Package.Elements;
+	if (o[0].Type != ACPI_TYPE_INTEGER) {
+		device_printf(sc->sc_dev, "%s[0]: invalid type\n", name);
+		AcpiOsFree(b.Pointer);
+		return;
+	}
+
+	n = o[0].Integer.Value;
+	if (bp->Package.Count - 1 < n) {
+		device_printf(sc->sc_dev, "%s: invalid package\n", name);
+		AcpiOsFree(b.Pointer);
+		return;
+	} else if (bp->Package.Count - 1 > n) {
+		int on = n;
+
+#ifdef AIBS_MORE_SENSORS
+		n = bp->Package.Count - 1;
+#endif
+		device_printf(sc->sc_dev, "%s: misformed package: %i/%i"
+		    ", assume %i\n", name, on, bp->Package.Count - 1, n);
+	}
+	if (n < 1) {
+		device_printf(sc->sc_dev, "%s: no members in the package\n",
+		    name);
+		AcpiOsFree(b.Pointer);
+		return;
+	}
+
+	as = kmalloc(sizeof(*as) * n, M_DEVBUF, M_NOWAIT | M_ZERO);
+	if (as == NULL) {
+		device_printf(sc->sc_dev, "%s: malloc fail\n", name);
+		AcpiOsFree(b.Pointer);
+		return;
+	}
+
+	switch (st) {
+	case SENSOR_TEMP:
+		sc->sc_asens_temp = as;
+		break;
+	case SENSOR_FANRPM:
+		sc->sc_asens_fan = as;
+		break;
+	case SENSOR_VOLTS_DC:
+		sc->sc_asens_volt = as;
+		break;
+	default:
+		/* NOTREACHED */
+		return;
+	}
+
+	for (i = 0, o++; i < n; i++, o++) {
+		ACPI_OBJECT	*oi;
+
+		/* acpica5 automatically evaluates the referenced package */
+		if(o[0].Type != ACPI_TYPE_PACKAGE) {
+			device_printf(sc->sc_dev,
+			    "%s: %i: not a package: %i type\n",
+			    name, i, o[0].Type);
+			continue;
+		}
+		oi = o[0].Package.Elements;
+		if (o[0].Package.Count != 5 ||
+		    oi[0].Type != ACPI_TYPE_INTEGER ||
+		    oi[1].Type != ACPI_TYPE_STRING ||
+		    oi[2].Type != ACPI_TYPE_INTEGER ||
+		    oi[3].Type != ACPI_TYPE_INTEGER ||
+		    oi[4].Type != ACPI_TYPE_INTEGER) {
+			device_printf(sc->sc_dev,
+			    "%s: %i: invalid package\n",
+			    name, i);
+			continue;
+		}
+		as[i].i = oi[0].Integer.Value;
+		strlcpy(as[i].s.desc, oi[1].String.Pointer,
+		    sizeof(as[i].s.desc));
+		as[i].l = oi[2].Integer.Value;
+		as[i].h = oi[3].Integer.Value;
+		as[i].s.type = st;
+#ifdef AIBS_VERBOSE
+		device_printf(sc->sc_dev, "%c%i: "
+		    "0x%08llx %20s %5lli / %5lli  0x%llx\n",
+		    name[0], i,
+		    as[i].i, as[i].s.desc, as[i].l, as[i].h,
+		    oi[4].Integer.Value);
+#endif
+		sensor_attach(&sc->sc_sensordev, &as[i].s);
+	}
+
+	AcpiOsFree(b.Pointer);
+	return;
+}
+
+static int
+aibs_detach(struct device *dev)
+{
+	struct aibs_softc	*sc = device_get_softc(dev);
+
+	sensordev_deinstall(&sc->sc_sensordev);
+	sensor_task_unregister(sc);
+	if (sc->sc_asens_volt != NULL)
+		kfree(sc->sc_asens_volt, M_DEVBUF);
+	if (sc->sc_asens_temp != NULL)
+		kfree(sc->sc_asens_temp, M_DEVBUF);
+	if (sc->sc_asens_fan != NULL)
+		kfree(sc->sc_asens_fan, M_DEVBUF);
+	return 0;
+}
+
+#ifdef AIBS_VERBOSE
+#define ddevice_printf(x...) device_printf(x)
+#else
+#define ddevice_printf(x...)
+#endif
+
+static void
+aibs_refresh(void *arg)
+{
+	struct aibs_softc *sc = arg;
+
+	aibs_refresh_r(sc, SENSOR_VOLTS_DC);
+	aibs_refresh_r(sc, SENSOR_TEMP);
+	aibs_refresh_r(sc, SENSOR_FANRPM);
+}
+
+static void
+aibs_refresh_r(struct aibs_softc *sc, enum sensor_type st)
+{
+	ACPI_STATUS		rs;
+	ACPI_HANDLE		rh;
+	int			i, n = sc->sc_sensordev.maxnumt[st];
+	char			*name;
+	struct aibs_sensor	*as;
+
+	switch (st) {
+	case SENSOR_TEMP:
+		name = "RTMP";
+		as = sc->sc_asens_temp;
+		break;
+	case SENSOR_FANRPM:
+		name = "RFAN";
+		as = sc->sc_asens_fan;
+		break;
+	case SENSOR_VOLTS_DC:
+		name = "RVLT";
+		as = sc->sc_asens_volt;
+		break;
+	default:
+		return;
+	}
+
+	if (as == NULL)
+		return;
+
+	rs = AcpiGetHandle(sc->sc_ah, name, &rh);
+	if (ACPI_FAILURE(rs)) {
+		ddevice_printf(sc->sc_dev, "%s: method handle not found\n",
+		    name);
+		for (i = 0; i < n; i++)
+			as[i].s.flags |= SENSOR_FINVALID;
+		return;
+	}
+
+	for (i = 0; i < n; i++) {
+		ACPI_OBJECT		p, *bp;
+		ACPI_OBJECT_LIST	mp;
+		ACPI_BUFFER		b;
+		int64_t			v;
+		struct ksensor		*s = &as[i].s;
+		const int64_t		l = as[i].l, h = as[i].h;
+
+		p.Type = ACPI_TYPE_INTEGER;
+		p.Integer.Value = as[i].i;
+		mp.Count = 1;
+		mp.Pointer = &p;
+		b.Length = ACPI_ALLOCATE_BUFFER;
+		rs = AcpiEvaluateObjectTyped(rh, NULL, &mp, &b,
+		    ACPI_TYPE_INTEGER);
+		if (ACPI_FAILURE(rs)) {
+			ddevice_printf(sc->sc_dev,
+			    "%s: %i: evaluation failed\n",
+			    name, i);
+			s->flags |= SENSOR_FINVALID;
+			continue;
+		}
+		bp = b.Pointer;
+		v = bp->Integer.Value;
+		AcpiOsFree(b.Pointer);
+
+		switch (st) {
+		case SENSOR_TEMP:
+			s->value = v * 100 * 1000 + 273150000;
+			if (v == 0) {
+				s->status = SENSOR_S_UNKNOWN;
+				s->flags |= SENSOR_FINVALID;
+			} else {
+				if (v > h)
+					s->status = SENSOR_S_CRIT;
+				else if (v > l)
+					s->status = SENSOR_S_WARN;
+				else
+					s->status = SENSOR_S_OK;
+				s->flags &= ~SENSOR_FINVALID;
+			}
+			break;
+		case SENSOR_FANRPM:
+			s->value = v;
+			/* some boards have strange limits for fans */
+			if ((l != 0 && l < v && v < h) ||
+			    (l == 0 && v > h))
+				s->status = SENSOR_S_OK;
+			else
+				s->status = SENSOR_S_WARN;
+			s->flags &= ~SENSOR_FINVALID;
+			break;
+		case SENSOR_VOLTS_DC:
+			s->value = v * 1000;
+			if (l < v && v < h)
+				s->status = SENSOR_S_OK;
+			else
+				s->status = SENSOR_S_WARN;
+			s->flags &= ~SENSOR_FINVALID;
+			break;
+		default:
+			/* NOTREACHED */
+			break;
+		}
+	}
+
+	return;
+}
-- 
1.6.4


--3MwIy2ne0vdjdPXF--





More information about the Submit mailing list