Hi,

Attached patch provides support for the hardware monitoring capabilities that are present in many modern desktop motherboards from ASUS featuring the ATK0110 ACPI device.

You can use acpidump(8) and grep(1) to see if your board has this device:

dale# acpidump -d | fgrep ATK0110
                       Name (_HID, "ATK0110")
dale#

In a nutshell, unlike lm(4) & it(4), this driver provides the very same readings and sensor descriptions as you can see in the Hardware Monitor page of the BIOS.

Best regards,
Constantine.                                            http://cnst.su/
>From 84e06a5580a62cf505aa85f8ebffc40b15b70384 Mon Sep 17 00:00:00 2001
From: Constantine A. Murenin <[email protected]>
Date: Thu, 24 Sep 2009 03:15:55 -0400
Subject: [PATCH] New aibs(4) driver for ASUSTeK AI Booster (ACPI ATK0110) 
hardware monitoring, with sensor state support through thresholds from ACPI.

---
 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 <[email protected]>
+.\"
+.\" 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 <[email protected]>
+ *
+ * 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

Reply via email to