tech-kern archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

aibs(4): ASUSTeK AI Booster (ACPI ATK0110) hardware monitor with limit support



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.

This driver, aibs(4), is a replacement to NetBSD's existing aiboost(4). The differences between the two include limit support in aibs(4), as well as generally cleaner and easier to read code, since the driver has been rewritten and retested from scratch (albeit originally for a different OS):

$ wc aiboost.c atk0110.c
    451    1347   11871 aiboost.c
450 1298 10671 atk0110.c

Fewer lines of code for more functionality is always nice. :-)

Both aibs(4) and aiboost(4) can be build into the same kernel: aibs(4) returns a higher confidence value in its match routine, so it will win in autoconf(9) over aiboost(4). This patch does not yet remove aiboost(4), although the presence of aibs(4) does make aiboost(4) rather obsolete and redundant.

Limits are automatically gathered by aibs(4) and monitored through sysmon_envsys(9), and are viewable from envstat(8). The manual page is included and has more details, as well as example output.

Best regards,
Constantine.                                            http://cnst.su/

--
Constantine A. Murenin
David R. Cheriton School of Computer Science
University of Waterloo
200 University Avenue West
Waterloo, Ontario  N2L 3G1
Canada
diff --git a/share/man/man4/Makefile b/share/man/man4/Makefile
index 05225ed..b5a2ba1 100644
--- a/share/man/man4/Makefile
+++ b/share/man/man4/Makefile
@@ -5,7 +5,7 @@ MAN=    aac.4 ac97.4 acardide.4 aceride.4 acphy.4 acpidalb.4 \
        adbbt.4 adbkbd.4 adbms.4 \
        adc.4 admtemp.4 adv.4 adw.4 age.4 agp.4 agr.4 ahb.4 ahc.4 \
        ahcisata.4 ahd.4 \
-       aiboost.4 ale.4 alipm.4 altmem.4 amdpm.4 amdtemp.4 amhphy.4 \
+       aiboost.4 aibs.4 ale.4 alipm.4 altmem.4 amdpm.4 amdtemp.4 amhphy.4 \
        amr.4 aps.4 \
        an.4 arcmsr.4 aria.4 artsata.4 ata.4 atalk.4 ataraid.4 \
        ath.4 atphy.4 atppc.4 attimer.4 atw.4 \
diff --git a/share/man/man4/acpi.4 b/share/man/man4/acpi.4
index c6fdf04..9dcb3ba 100644
--- a/share/man/man4/acpi.4
+++ b/share/man/man4/acpi.4
@@ -40,6 +40,7 @@
 .Cd "acpitz*   at acpi?"
 .Cd "attimer*  at acpi?"
 .Cd "aiboost*  at acpi?"
+.Cd "aibs*     at acpi?"
 .Cd "com*      at acpi?"
 .Cd "fdc*      at acpi?"
 .Cd "hpet*     at acpi?"
@@ -194,6 +195,8 @@ thermal zones.
 AT Timer.
 .It aiboost
 ASUS AI Booster Hardware monitor.
+.It aibs
+ASUSTeK AI Booster ACPI ATK0110 voltage, temperature and fan sensor.
 .It com
 NS8250-, NS16450-, and NS16550-based serial ports.
 .It fdc
@@ -236,6 +239,7 @@ Toshiba Libretto device.
 .Xr acpilid 4 ,
 .Xr acpitz 4 ,
 .Xr aiboost 4 ,
+.Xr aibs 4 ,
 .Xr apm 4 ,
 .Xr attimer 4 ,
 .Xr com 4 ,
diff --git a/share/man/man4/aibs.4 b/share/man/man4/aibs.4
new file mode 100644
index 0000000..1474bf3
--- /dev/null
+++ b/share/man/man4/aibs.4
@@ -0,0 +1,246 @@
+.\"    $NetBSD$
+.\"    $OpenBSD: aibs.4,v 1.4 2009/07/30 06:30:45 jmc Exp $
+.\"
+.\" Copyright (c) 2009 Constantine A. Murenin 
<cnst+netbsd%bugmail.mojo.ru@localhost>
+.\"
+.\" 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 December 30, 2009
+.Dt AIBS 4
+.Os
+.Sh NAME
+.Nm aibs
+.Nd "ASUSTeK AI Booster ACPI ATK0110 voltage, temperature and fan sensor"
+.Sh SYNOPSIS
+.Cd "aibs* at acpi?"
+.Sh DESCRIPTION
+The
+.Nm
+driver provides support for the voltage, temperature and fan sensors
+available through the
+.Tn ATK0110
+.Tn ASOC
+.Tn ACPI
+device
+on
+.Tn 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
+.Tn ACPI .
+.Pp
+The
+.Nm
+driver supports
+.Xr envsys 4
+sensor states as follows:
+.Bl -bullet
+.It
+Voltage sensors can have a state of
+.Dv valid ,
+.Dv critunder
+or
+.Dv critover ;
+temperature sensors can have a state of
+.Dv valid ,
+.Dv warnover ,
+.Dv critover
+or
+.Dv invalid ;
+and fan sensors can have a state of
+.Dv valid ,
+.Dv warnunder
+or
+.Dv warnover .
+.It
+Temperature sensors that have a reading of 0
+are marked
+.Dv invalid ,
+whereas all other sensors are always assumed valid.
+.It
+Voltage sensors have a lower and an upper limit
+.Dv ( critunder
+and
+.Dv critover ) ,
+temperature sensors have two upper limits
+.Dv ( warnover
+and
+.Dv critover ) ,
+whereas fan sensors may either have only the lower limit
+.Dv ( warnunder ) ,
+or, depending on the
+.Tn DSDT ,
+one lower and one upper limit
+.Dv ( warnunder
+and
+.Dv warnover ) .
+.El
+.Pp
+Sensor values and limits are made available through the
+.Xr envsys 4
+interface,
+and can be monitored with
+.Xr envstat 8 .
+For example, on an ASUS V3-P5G965 barebone:
+.Bd -literal -offset indent
+$ envstat -d aibs0
+                      Current  CritMax  CritMin  CritCap     Unit
+    Vcore Voltage:      1.152    1.600    0.850                 V
+     +3.3 Voltage:      3.312    3.630    2.970                 V
+       +5 Voltage:      5.017    5.500    4.500                 V
+      +12 Voltage:     12.302   13.800   10.200                 V
+  CPU Temperature:     24.000   95.000                       degC
+   MB Temperature:     57.000   95.000                       degC
+    CPU FAN Speed:        865                                 RPM
+CHASSIS FAN Speed:          0                                 RPM
+.Pp
+$ envstat -W -d aibs0
+                      Current  WarnMax  WarnMin  WarnCap     Unit
+    Vcore Voltage:      1.152                                   V
+     +3.3 Voltage:      3.312                                   V
+       +5 Voltage:      5.017                                   V
+      +12 Voltage:     12.302                                   V
+  CPU Temperature:     24.000   80.000                       degC
+   MB Temperature:     57.000   60.000                       degC
+    CPU FAN Speed:        865     7200      600               RPM
+CHASSIS FAN Speed:          0     7200      700               RPM
+.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 itesio 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
+.Tn 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 states are supported by
+.Nm .
+The state 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
+.Tn ACPI .
+.Sh SEE ALSO
+.Xr envsys 4 ,
+.Xr envstat 8
+.Sh HISTORY
+The
+.Nm
+driver first appeared in
+.Ox 4.7 ,
+DragonFly 2.4.1
+and
+.Nx 6.0 .
+.Pp
+An earlier version of the driver,
+.Nm aiboost ,
+first appeared in
+.Fx 7.0
+and
+.Nx 5.0 .
+.Sh AUTHORS
+.An -nosplit
+The
+.Nm
+driver was written for
+.Ox ,
+DragonFly
+and
+.Nx
+by
+.An Constantine A. Murenin Aq http://cnst.su/ ,
+David R. Cheriton School of Computer Science,
+University of Waterloo.
+.Pp
+An earlier version of the driver, named
+.Nm aiboost ,
+was written for
+.Fx
+by
+.An Takanori Watanabe
+and
+adapted to
+.Nx
+by
+.An Juan Romero Pardines .
diff --git a/sys/arch/amd64/conf/GENERIC b/sys/arch/amd64/conf/GENERIC
index 1620b57..81ebdaf 100644
--- a/sys/arch/amd64/conf/GENERIC
+++ b/sys/arch/amd64/conf/GENERIC
@@ -283,6 +283,7 @@ acpiwmi*    at acpi?                # ACPI WMI Mapper
 
 # Mainboard devices
 aiboost*       at acpi?                # ASUS AI Booster Hardware monitor
+aibs*          at acpi?                # ASUSTeK AI Booster hardware monitor
 asus*          at acpi?                # ASUS hotkeys
 attimer*       at acpi?                # AT Timer
 #com*          at acpi?                # Serial communications interface
diff --git a/sys/arch/amd64/conf/XEN3_DOM0 b/sys/arch/amd64/conf/XEN3_DOM0
index 3476105..aa847d0 100644
--- a/sys/arch/amd64/conf/XEN3_DOM0
+++ b/sys/arch/amd64/conf/XEN3_DOM0
@@ -225,6 +225,7 @@ acpiec*     at acpi?                # ACPI Embedded 
Controller
 acpilid*       at acpi?                # ACPI Lid Switch
 acpitz*                at acpi?                # ACPI Thermal Zone
 aiboost*       at acpi?                # ASUS AI Booster Hardware monitor
+aibs*          at acpi?                # ASUSTeK AI Booster hardware monitor
 hpqlb*         at acpi?                # HP Quick Launch Buttons
 pckbc*         at acpi?                # PC keyboard controller
 pcppi*         at acpi?                # AT-style speaker sound
diff --git a/sys/arch/i386/conf/ALL b/sys/arch/i386/conf/ALL
index 5fbe169..ed5b94d 100644
--- a/sys/arch/i386/conf/ALL
+++ b/sys/arch/i386/conf/ALL
@@ -372,6 +372,7 @@ acpiwmi*    at acpi?                # ACPI WMI Mapper
 
 # Mainboard devices
 aiboost*       at acpi?                # ASUS AI Booster Hardware Monitor
+aibs*          at acpi?                # ASUSTeK AI Booster hardware monitor
 asus*          at acpi?                # ASUS hotkeys
 attimer*       at acpi?                # AT Timer
 com*           at acpi?                # Serial communications interface
diff --git a/sys/arch/i386/conf/GENERIC b/sys/arch/i386/conf/GENERIC
index d68e245..b030f32 100644
--- a/sys/arch/i386/conf/GENERIC
+++ b/sys/arch/i386/conf/GENERIC
@@ -364,6 +364,7 @@ acpiwmi*    at acpi?                # ACPI WMI Mapper
 
 # Mainboard devices
 aiboost*       at acpi?                # ASUS AI Booster Hardware Monitor
+aibs*          at acpi?                # ASUSTeK AI Booster hardware monitor
 asus*          at acpi?                # ASUS hotkeys
 attimer*       at acpi?                # AT Timer
 #com*          at acpi?                # Serial communications interface
diff --git a/sys/dev/acpi/atk0110.c b/sys/dev/acpi/atk0110.c
new file mode 100644
index 0000000..54c040a
--- /dev/null
+++ b/sys/dev/acpi/atk0110.c
@@ -0,0 +1,450 @@
+/*     $NetBSD$        */
+/*     $OpenBSD: atk0110.c,v 1.1 2009/07/23 01:38:16 cnst Exp $        */
+
+/*
+ * Copyright (c) 2009 Constantine A. Murenin 
<cnst+netbsd%bugmail.mojo.ru@localhost>
+ *
+ * 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>
+__KERNEL_RCSID(0, "$NetBSD$");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/malloc.h>
+
+#include <dev/sysmon/sysmonvar.h>
+
+#include "acpi.h"
+#include "acpivar.h"
+
+/*
+ * ASUSTeK AI Booster (ACPI ASOC 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,
+ * and then to the NetBSD's sysmon_envsys(9) framework.
+ *
+ *                               -- Constantine A. Murenin <http://cnst.su/>
+ */
+
+#define AIBS_MORE_SENSORS
+#define AIBS_MONLIMITS
+
+struct aibs_sensor {
+       envsys_data_t   s;
+       int64_t         i;
+       int64_t         l;
+       int64_t         h;
+};
+
+struct aibs_softc {
+       struct acpi_devnode     *sc_node;
+
+       struct aibs_sensor      *sc_asens_volt;
+       struct aibs_sensor      *sc_asens_temp;
+       struct aibs_sensor      *sc_asens_fan;
+
+       struct sysmon_envsys    *sc_sme;
+};
+
+static int aibs_match(device_t, cfdata_t, void *);
+static void aibs_attach(device_t, device_t, void *);
+static int aibs_detach(device_t, int);
+static void aibs_refresh(struct sysmon_envsys *, envsys_data_t *);
+#ifdef AIBS_MONLIMITS
+static void aibs_get_limits(struct sysmon_envsys *, envsys_data_t *,
+    sysmon_envsys_lim_t *);
+#endif
+
+static void aibs_attach_sif(device_t, enum envsys_units);
+
+CFATTACH_DECL_NEW(aibs, sizeof(struct aibs_softc),
+    aibs_match, aibs_attach, aibs_detach, NULL);
+
+static const char* const aibs_hid[] = {
+       "ATK0110",
+       NULL
+};
+
+static int
+aibs_match(device_t parent, cfdata_t match, void *aux)
+{
+       struct acpi_attach_args *aa = aux;
+
+       if(aa->aa_node->ad_type != ACPI_TYPE_DEVICE)
+               return 0;
+
+       /* successful match supersedes aiboost(4) */
+       return acpi_match_hid(aa->aa_node->ad_devinfo, aibs_hid) * 2;
+}
+
+static void
+aibs_attach(device_t parent, device_t self, void *aux)
+{
+       struct aibs_softc *sc = device_private(self);
+       struct acpi_attach_args *aa = aux;
+       int err;
+
+       sc->sc_node = aa->aa_node;
+
+       aprint_naive(": ASUSTeK AI Booster\n");
+       aprint_normal(": ASUSTeK AI Booster\n");
+
+       sc->sc_sme = sysmon_envsys_create();
+       sc->sc_sme->sme_name = device_xname(self);
+       sc->sc_sme->sme_cookie = sc;
+       sc->sc_sme->sme_refresh = aibs_refresh;
+#ifdef AIBS_MONLIMITS
+       sc->sc_sme->sme_get_limits = aibs_get_limits;
+#endif
+
+       aibs_attach_sif(self, ENVSYS_SVOLTS_DC);
+       aibs_attach_sif(self, ENVSYS_STEMP);
+       aibs_attach_sif(self, ENVSYS_SFANRPM);
+
+       if (sc->sc_sme->sme_nsensors == 0) {
+               aprint_error_dev(self, "no sensors found\n");
+               sysmon_envsys_destroy(sc->sc_sme);
+               return;
+       }
+
+       if ((err = sysmon_envsys_register(sc->sc_sme))) {
+               aprint_error_dev(self, "unable to register with sysmon: %d\n",
+                   err);
+               if (sc->sc_asens_volt != NULL)
+                       free(sc->sc_asens_volt, M_DEVBUF);
+               if (sc->sc_asens_temp != NULL)
+                       free(sc->sc_asens_temp, M_DEVBUF);
+               if (sc->sc_asens_fan != NULL)
+                       free(sc->sc_asens_fan, M_DEVBUF);
+               return;
+       }
+}
+
+static void
+aibs_attach_sif(device_t self, enum envsys_units st)
+{
+       struct aibs_softc       *sc = device_private(self);
+       ACPI_STATUS             s;
+       ACPI_BUFFER             b;
+       ACPI_OBJECT             *bp, *o;
+       int                     i, n;
+       char                    name[] = "?SIF";
+       struct aibs_sensor      *as;
+
+       switch (st) {
+       case ENVSYS_STEMP:
+               name[0] = 'T';
+               break;
+       case ENVSYS_SFANRPM:
+               name[0] = 'F';
+               break;
+       case ENVSYS_SVOLTS_DC:
+               name[0] = 'V';
+               break;
+       default:
+               return;
+       }
+
+       b.Length = ACPI_ALLOCATE_BUFFER;
+       s = AcpiEvaluateObjectTyped(sc->sc_node->ad_handle, name, NULL, &b,
+           ACPI_TYPE_PACKAGE);
+       if (ACPI_FAILURE(s)) {
+               aprint_error_dev(self, "%s not found\n", name);
+               return;
+       }
+
+       bp = b.Pointer;
+       o = bp->Package.Elements;
+       if (o[0].Type != ACPI_TYPE_INTEGER) {
+               aprint_error_dev(self, "%s[0]: invalid type\n", name);
+               AcpiOsFree(b.Pointer);
+               return;
+       }
+
+       n = o[0].Integer.Value;
+       if (bp->Package.Count - 1 < n) {
+               aprint_error_dev(self, "%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
+               aprint_error_dev(self, "%s: misformed package: %i/%i"
+                   ", assume %i\n", name, on, bp->Package.Count - 1, n);
+       }
+       if (n < 1) {
+               aprint_error_dev(self, "%s: no members in the package\n",
+                   name);
+               AcpiOsFree(b.Pointer);
+               return;
+       }
+
+       as = malloc(sizeof(*as) * n, M_DEVBUF, M_NOWAIT | M_ZERO);
+       if (as == NULL) {
+               aprint_error_dev(self, "%s: malloc fail\n", name);
+               AcpiOsFree(b.Pointer);
+               return;
+       }
+       switch (st) {
+       case ENVSYS_STEMP:
+               sc->sc_asens_temp = as;
+               break;
+       case ENVSYS_SFANRPM:
+               sc->sc_asens_fan = as;
+               break;
+       case ENVSYS_SVOLTS_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) {
+                       aprint_error_dev(self,
+                           "%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) {
+                       aprint_error_dev(self,
+                           "%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.units = st;
+#ifdef AIBS_MONLIMITS
+               as[i].s.flags |= ENVSYS_FMONLIMITS;
+               as[i].s.monitor = true;
+#endif
+               aprint_verbose_dev(self, "%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);
+               sysmon_envsys_sensor_attach(sc->sc_sme, &as[i].s);
+       }
+
+       AcpiOsFree(b.Pointer);
+       return;
+}
+
+static int
+aibs_detach(device_t self, int flags)
+{
+       struct aibs_softc       *sc = device_private(self);
+
+       sysmon_envsys_unregister(sc->sc_sme);
+       if (sc->sc_asens_volt != NULL)
+               free(sc->sc_asens_volt, M_DEVBUF);
+       if (sc->sc_asens_temp != NULL)
+               free(sc->sc_asens_temp, M_DEVBUF);
+       if (sc->sc_asens_fan != NULL)
+               free(sc->sc_asens_fan, M_DEVBUF);
+       return 0;
+}
+
+static void
+aibs_refresh(struct sysmon_envsys *sme, envsys_data_t *edata)
+{
+       struct aibs_softc       *sc = sme->sme_cookie;
+       device_t                self = sc->sc_node->ad_device;
+       envsys_data_t           *s = edata;
+       enum envsys_units       st = s->units;
+       ACPI_STATUS             rs;
+       ACPI_OBJECT             p, *bp;
+       ACPI_OBJECT_LIST        mp;
+       ACPI_BUFFER             b;
+       int                     i;
+       const char              *name;
+       struct aibs_sensor      *as;
+       int64_t                 v;
+       int64_t                 l, h;
+
+       switch (st) {
+       case ENVSYS_STEMP:
+               name = "RTMP";
+               as = sc->sc_asens_temp;
+               break;
+       case ENVSYS_SFANRPM:
+               name = "RFAN";
+               as = sc->sc_asens_fan;
+               break;
+       case ENVSYS_SVOLTS_DC:
+               name = "RVLT";
+               as = sc->sc_asens_volt;
+               break;
+       default:
+               return;
+       }
+       if (as == NULL)
+               return;
+       for (i = 0; as[i].s.sensor != s->sensor; i++)
+               ;
+       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(sc->sc_node->ad_handle, name, &mp, &b,
+           ACPI_TYPE_INTEGER);
+       if (ACPI_FAILURE(rs)) {
+               aprint_debug_dev(self,
+                   "%s: %i: evaluation failed\n",
+                   name, i);
+               s->state = ENVSYS_SINVALID;
+               s->flags |= ENVSYS_FMONNOTSUPP;
+               return;
+       }
+       bp = b.Pointer;
+       v = bp->Integer.Value;
+       AcpiOsFree(b.Pointer);
+
+       switch (st) {
+       case ENVSYS_STEMP:
+               s->value_cur = v * 100 * 1000 + 273150000;
+               if (v == 0) {
+                       s->state = ENVSYS_SINVALID;
+                       s->flags |= ENVSYS_FMONNOTSUPP;
+               } else {
+                       if (v > h)
+                               s->state = ENVSYS_SCRITOVER;
+                       else if (v > l)
+                               s->state = ENVSYS_SWARNOVER;
+                       else
+                               s->state = ENVSYS_SVALID;
+                       s->flags &= ~ENVSYS_FMONNOTSUPP;
+               }
+               break;
+       case ENVSYS_SFANRPM:
+               s->value_cur = v;
+               /* some boards have strange limits for fans */
+               if (l == 0) {
+                       if (v < h)
+                               s->state = ENVSYS_SWARNUNDER;
+                       else
+                               s->state = ENVSYS_SVALID;
+               } else {
+                       if (l > v)
+                               s->state = ENVSYS_SWARNUNDER;
+                       else if (v > h)
+                               s->state = ENVSYS_SWARNOVER;
+                       else
+                               s->state = ENVSYS_SVALID;
+               }
+               s->flags &= ~ENVSYS_FMONNOTSUPP;
+               break;
+       case ENVSYS_SVOLTS_DC:
+               s->value_cur = v * 1000;
+               if (l > v)
+                       s->state = ENVSYS_SCRITUNDER;
+               else if (v > h)
+                       s->state = ENVSYS_SCRITOVER;
+               else
+                       s->state = ENVSYS_SVALID;
+               s->flags &= ~ENVSYS_FMONNOTSUPP;
+               break;
+       default:
+               /* NOTREACHED */
+               break;
+       }
+}
+
+#ifdef AIBS_MONLIMITS
+static void
+aibs_get_limits(struct sysmon_envsys *sme, envsys_data_t *edata,
+    sysmon_envsys_lim_t *limits)
+{
+       struct aibs_softc       *sc = sme->sme_cookie;
+       envsys_data_t           *s = edata;
+       sysmon_envsys_lim_t     *li = limits;
+       enum envsys_units       st = s->units;
+       int                     i;
+       struct aibs_sensor      *as;
+       int64_t                 l, h;
+
+       switch (st) {
+       case ENVSYS_STEMP:
+               as = sc->sc_asens_temp;
+               break;
+       case ENVSYS_SFANRPM:
+               as = sc->sc_asens_fan;
+               break;
+       case ENVSYS_SVOLTS_DC:
+               as = sc->sc_asens_volt;
+               break;
+       default:
+               return;
+       }
+       if (as == NULL)
+               return;
+       for (i = 0; as[i].s.sensor != s->sensor; i++)
+               ;
+       l = as[i].l;
+       h = as[i].h;
+
+       switch (st) {
+       case ENVSYS_STEMP:
+               li->sel_critmax = h * 100 * 1000 + 273150000;
+               li->sel_warnmax = l * 100 * 1000 + 273150000;
+               li->sel_flags = PROP_CRITMAX | PROP_WARNMAX;
+               break;
+       case ENVSYS_SFANRPM:
+               /* some boards have strange limits for fans */
+               if (l == 0) {
+                       li->sel_warnmin = h;
+                       li->sel_flags = PROP_WARNMIN;
+               } else {
+                       li->sel_warnmin = l;
+                       li->sel_warnmax = h;
+                       li->sel_flags = PROP_WARNMIN | PROP_WARNMAX;
+               }
+               break;
+       case ENVSYS_SVOLTS_DC:
+               li->sel_critmin = l * 1000;
+               li->sel_critmax = h * 1000;
+               li->sel_flags = PROP_CRITMIN | PROP_CRITMAX;
+               break;
+       default:
+               /* NOTREACHED */
+               break;
+       }
+}
+#endif /* AIBS_MONLIMITS */
diff --git a/sys/dev/acpi/files.acpi b/sys/dev/acpi/files.acpi
index 683ad3b..15015ce 100644
--- a/sys/dev/acpi/files.acpi
+++ b/sys/dev/acpi/files.acpi
@@ -153,3 +153,8 @@ file        dev/acpi/wb_acpi.c              wb_acpi
 device acpiwmi
 attach acpiwmi at acpinodebus
 file   dev/acpi/wmi_acpi.c             acpiwmi
+
+# ASUSTeK AI Booster ATK0110
+device aibs: sysmon_envsys
+attach aibs at acpinodebus
+file   dev/acpi/atk0110.c              aibs
diff --git a/usr.sbin/envstat/envstat.8 b/usr.sbin/envstat/envstat.8
index cbd4658..7b58ff1 100644
--- a/usr.sbin/envstat/envstat.8
+++ b/usr.sbin/envstat/envstat.8
@@ -178,6 +178,7 @@ invalid states every second:
 .Xr acpitz 4 ,
 .Xr admtemp 4 ,
 .Xr aiboost 4 ,
+.Xr aibs 4 ,
 .Xr amdtemp 4 ,
 .Xr aps 4 ,
 .Xr arcmsr 4 ,


Home | Main Index | Thread Index | Old Index