tech-kern archive

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

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



On Wed, Dec 30, 2009 at 03:49:35AM -0500, Constantine Aleksandrovich Murenin 
wrote:
> 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/

An updated patch is attached.

Best regards,
Constantine.

-- 
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 9fe7e4c..be9d438 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 32615b3..62f2919 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 116ad5c..22226e1 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 df5f4f9..3eb3802 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..4598c94
--- /dev/null
+++ b/sys/dev/acpi/atk0110.c
@@ -0,0 +1,453 @@
+/*     $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;
+       ACPI_INTEGER    i;
+       ACPI_INTEGER    l;
+       ACPI_INTEGER    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%08"PRIx64" %20s %5"PRIi64" / %5"PRIi64"  "
+                   "0x%"PRIx64"\n",
+                   name[0], i,
+                   as[i].i, as[i].s.desc, (int64_t)as[i].l, (int64_t)as[i].h,
+                   oi[4].Integer.Value);
+               if (sysmon_envsys_sensor_attach(sc->sc_sme, &as[i].s))
+                       aprint_error_dev(self, "%c%i: unable to attach\n",
+                           name[0], i);
+       }
+
+       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;
+       ACPI_INTEGER            v;
+       ACPI_INTEGER            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;
+       ACPI_INTEGER            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