On newer ASUS boards the way the aibs(4) sensors are accessed got changed.
So some system will show this:
aibs0 at acpi0
aibs0: TSIF not found
aibs0: FSIF not found
aibs0: VSIF not found
aibs0: no sensors found

The following diff adds support for those systems (using GGRP, GITM to
enumerate and poll sensor values). New mode is used when the RTMP, RVLT,
and RFAN AML nodes are not present else the old behaviour is used.

This needs testing on all systems with aibs(4) to ensure that no
regression got introduced. People with ACPI knowledge should verify that I
did not do anything crazy in ACPI land.

-- 
:wq Claudio

Index: atk0110.c
===================================================================
RCS file: /cvs/src/sys/dev/acpi/atk0110.c,v
retrieving revision 1.4
diff -u -p -r1.4 atk0110.c
--- atk0110.c   17 May 2010 21:59:45 -0000      1.4
+++ atk0110.c   13 Sep 2010 08:45:29 -0000
@@ -40,6 +40,19 @@
  *                                                     -- cnst.su.
  */
 
+#define ATK_ID_MUX_HWMON       0x00000006
+
+#define ATK_CLASS(x)           (((x) >> 24) & 0xff)
+#define ATK_CLASS_FREQ_CTL     3
+#define ATK_CLASS_FAN_CTL      4
+#define ATK_CLASS_HWMON                6
+#define ATK_CLASS_MGMT         17
+
+#define ATK_TYPE(x)            (((x) >> 16) & 0xff)
+#define ATK_TYPE_VOLT          2
+#define ATK_TYPE_TEMP          3
+#define ATK_TYPE_FAN           4
+
 #define AIBS_MORE_SENSORS
 /* #define AIBS_VERBOSE */
 
@@ -48,6 +61,7 @@ struct aibs_sensor {
        int64_t         i;
        int64_t         l;
        int64_t         h;
+       SIMPLEQ_ENTRY(aibs_sensor)      entry;
 };
 
 struct aibs_softc {
@@ -56,20 +70,46 @@ struct aibs_softc {
        struct acpi_softc       *sc_acpi;
        struct aml_node         *sc_devnode;
 
-       struct aibs_sensor      *sc_asens_volt;
-       struct aibs_sensor      *sc_asens_temp;
-       struct aibs_sensor      *sc_asens_fan;
+       struct aml_node         *sc_ggrpnode;
+       struct aml_node         *sc_gitmnode;
+       struct aml_node         *sc_sitmnode;
+       struct aml_node         *sc_rtmpnode;
+       struct aml_node         *sc_rvltnode;
+       struct aml_node         *sc_rfannode;
 
+       SIMPLEQ_HEAD(, aibs_sensor)     sc_sensorlist;
        struct ksensordev       sc_sensordev;
+
+       int                     sc_mode;        /* 1 = new, 0 = old */
+};
+
+/* Command buffer used for GITM and SITM methods */
+struct aibs_cmd_buffer {
+       u_int32_t       id;
+       u_int32_t       param1;
+       u_int32_t       param2;
 };
 
+/* Return buffer used by the GITM and SITM mehtods */
+struct aibs_ret_buffer {
+       u_int32_t       flags;
+       u_int32_t       value;
+       /* there is more stuff that is unknown */
+};
 
 int    aibs_match(struct device *, void *, void *);
 void   aibs_attach(struct device *, struct device *, void *);
 void   aibs_refresh(void *);
 
 void   aibs_attach_sif(struct aibs_softc *, enum sensor_type);
-void   aibs_refresh_r(struct aibs_softc *, enum sensor_type);
+void   aibs_attach_new(struct aibs_softc *);
+void   aibs_add_sensor(struct aibs_softc *, char *);
+void   aibs_refresh_r(struct aibs_softc *, struct aibs_sensor *);
+int    aibs_getvalue(struct aibs_softc *, int64_t, int64_t *);
+int    aibs_getpack(struct aibs_softc *, struct aml_node *, int64_t,
+           struct aml_value *);
+void   aibs_probe(struct aibs_softc *);
+int    aibs_find_cb(struct aml_node *, void *);
 
 
 struct cfattach aibs_ca = {
@@ -103,14 +143,20 @@ aibs_attach(struct device *parent, struc
        sc->sc_acpi = (struct acpi_softc *)parent;
        sc->sc_devnode = aa->aaa_node;
 
-       printf("\n");
-
        strlcpy(sc->sc_sensordev.xname, sc->sc_dev.dv_xname,
            sizeof(sc->sc_sensordev.xname));
+       SIMPLEQ_INIT(&sc->sc_sensorlist);
 
-       aibs_attach_sif(sc, SENSOR_TEMP);
-       aibs_attach_sif(sc, SENSOR_FANRPM);
-       aibs_attach_sif(sc, SENSOR_VOLTS_DC);
+       aibs_probe(sc);
+       printf("\n");
+
+       if (sc->sc_mode)
+               aibs_attach_new(sc);
+       else {
+               aibs_attach_sif(sc, SENSOR_TEMP);
+               aibs_attach_sif(sc, SENSOR_FANRPM);
+               aibs_attach_sif(sc, SENSOR_VOLTS_DC);
+       }
 
        if (sc->sc_sensordev.sensors_count == 0) {
                printf("%s: no sensors found\n", DEVNAME(sc));
@@ -132,7 +178,6 @@ aibs_attach_sif(struct aibs_softc *sc, e
        struct aml_value        **v;
        int                     i, n;
        char                    name[] = "?SIF";
-       struct aibs_sensor      *as;
 
        switch (st) {
        case SENSOR_TEMP:
@@ -153,13 +198,11 @@ aibs_attach_sif(struct aibs_softc *sc, e
                aml_freevalue(&res);
                return;
        }
-
        if (res.type != AML_OBJTYPE_PACKAGE) {
                printf("%s: %s: not a package\n", DEVNAME(sc), name);
                aml_freevalue(&res);
                return;
        }
-
        v = res.v_package;
        if (v[0]->type != AML_OBJTYPE_INTEGER) {
                printf("%s: %s[0]: invalid type\n", DEVNAME(sc), name);
@@ -187,193 +230,314 @@ aibs_attach_sif(struct aibs_softc *sc, e
                return;
        }
 
-       as = malloc(sizeof(*as) * n, M_DEVBUF, M_NOWAIT | M_ZERO);
-       if (as == NULL) {
-               printf("%s: %s: malloc fail\n", DEVNAME(sc), name);
-               aml_freevalue(&res);
+       for (i = 0, v++; i < n; i++, v++) {
+               if(v[0]->type != AML_OBJTYPE_STRING) {
+                       printf("%s: %s: %i: not a string: %i type\n",
+                           DEVNAME(sc), name, i, v[0]->type);
+                       continue;
+               }
+               aibs_add_sensor(sc, v[0]->v_string);
+       }
+
+       aml_freevalue(&res);
+}
+
+void
+aibs_attach_new(struct aibs_softc *sc)
+{
+       struct aml_value        res;
+       int                     i;
+
+       if (aibs_getpack(sc, sc->sc_ggrpnode, ATK_ID_MUX_HWMON, &res)) {
+               printf("%s: GGRP: sensor enumeration failed", DEVNAME(sc));
                return;
        }
 
-       switch (st) {
-       case SENSOR_TEMP:
-               sc->sc_asens_temp = as;
+       for (i = 0; i < res.length; i++) {
+               struct aml_value        *r;
+               r = res.v_package[i];
+               if (r->type != AML_OBJTYPE_STRING) {
+                       printf("%s: %s: %i: not a string (type %i)\n",
+                           DEVNAME(sc), "GGRP", i, r->type);
+                       continue;
+               }
+               aibs_add_sensor(sc, r->v_string);
+       }
+       aml_freevalue(&res);
+}
+
+void
+aibs_add_sensor(struct aibs_softc *sc, char *name)
+{
+       struct aml_value         ri;
+       struct aibs_sensor      *as;
+       int                      len, lim1, lim2, ena;
+
+       if (aml_evalname(sc->sc_acpi, sc->sc_devnode, name,
+           0, NULL, &ri)) {
+               printf("%s: aibs_add_sensor: %s not found\n",
+                   DEVNAME(sc), name, name);
+               aml_freevalue(&ri);
+               return;
+       }
+       if (ri.type != AML_OBJTYPE_PACKAGE) {
+               printf("%s: aibs_add_sensor: %s: not a package\n",
+                   DEVNAME(sc), name);
+               aml_freevalue(&ri);
+               return;
+       }
+       if (sc->sc_mode) {
+               len = 7;
+               lim1 = 4;
+               lim2 = 5;
+               ena = 6;
+       } else {
+               len = 5;
+               lim1 = 2;
+               lim2 = 3;
+               ena = 4;
+       }
+
+       if (ri.length != len ||
+           ri.v_package[0]->type != AML_OBJTYPE_INTEGER ||
+           ri.v_package[1]->type != AML_OBJTYPE_STRING ||
+           ri.v_package[lim1]->type != AML_OBJTYPE_INTEGER ||
+           ri.v_package[lim2]->type != AML_OBJTYPE_INTEGER ||
+           ri.v_package[ena]->type != AML_OBJTYPE_INTEGER) {
+               printf("%s: aibs_add_sensor: %s: invalid package\n",
+                   DEVNAME(sc), name);
+               aml_freevalue(&ri);
+               return;
+       }
+       as = malloc(sizeof(*as), M_DEVBUF, M_NOWAIT | M_ZERO);
+       if (!as) {
+               printf("%s: aibs_add_sensor: %s: failed to allocate sensor\n",
+                   DEVNAME(sc), name);
+               aml_freevalue(&ri);
+               return;
+       }
+       as->i = ri.v_package[0]->v_integer;
+       switch (ATK_TYPE(as->i)) {
+       case ATK_TYPE_VOLT:
+               as->s.type = SENSOR_VOLTS_DC;
                break;
-       case SENSOR_FANRPM:
-               sc->sc_asens_fan = as;
+       case ATK_TYPE_TEMP:
+               as->s.type = SENSOR_TEMP;
                break;
-       case SENSOR_VOLTS_DC:
-               sc->sc_asens_volt = as;
+       case ATK_TYPE_FAN:
+               as->s.type = SENSOR_FANRPM;
                break;
        default:
-               /* NOTREACHED */
+               printf("%s: aibs_add_sensor: %s: unknown sensor type %llx\n",
+                   DEVNAME(sc), name, ri.v_package[0]->v_integer);
+               aml_freevalue(&ri);
+               free(as, M_DEVBUF);
                return;
        }
-
-       for (i = 0, v++; i < n; i++, v++) {
-               struct aml_value        ri;
-
-               if(v[0]->type != AML_OBJTYPE_STRING) {
-                       printf("%s: %s: %i: not a string: %i type\n",
-                           DEVNAME(sc), name, i, v[0]->type);
-                       continue;
-               }
-               if (aml_evalname(sc->sc_acpi, sc->sc_devnode, v[0]->v_string,
-                   0, NULL, &ri)) {
-                       printf("%s: %s: %i: %s not found\n",
-                           DEVNAME(sc), name, i, v[0]->v_string);
-                       aml_freevalue(&ri);
-                       continue;
-               }
-               if (ri.type != AML_OBJTYPE_PACKAGE) {
-                       printf("%s: %s: %i: %s: not a package\n",
-                           DEVNAME(sc), name, i, v[0]->v_string);
-                       aml_freevalue(&ri);
-                       continue;
-               }
-               if (ri.length != 5 ||
-                   ri.v_package[0]->type != AML_OBJTYPE_INTEGER ||
-                   ri.v_package[1]->type != AML_OBJTYPE_STRING ||
-                   ri.v_package[2]->type != AML_OBJTYPE_INTEGER ||
-                   ri.v_package[3]->type != AML_OBJTYPE_INTEGER ||
-                   ri.v_package[4]->type != AML_OBJTYPE_INTEGER) {
-                       printf("%s: %s: %i: %s: invalid package\n",
-                           DEVNAME(sc), name, i, v[0]->v_string);
-                       aml_freevalue(&ri);
-                       continue;
-               }
-               as[i].i = ri.v_package[0]->v_integer;
-               strlcpy(as[i].s.desc, ri.v_package[1]->v_string,
-                   sizeof(as[i].s.desc));
-               as[i].l = ri.v_package[2]->v_integer;
-               as[i].h = ri.v_package[3]->v_integer;
-               as[i].s.type = st;
+       strlcpy(as->s.desc, ri.v_package[1]->v_string,
+           sizeof(as->s.desc));
+       as->l = ri.v_package[lim1]->v_integer;
+       if (sc->sc_mode)
+               /* the second limit is a actually a range */
+               as->h = as->l + ri.v_package[lim2]->v_integer;
+       else
+               as->h = ri.v_package[lim2]->v_integer;
 #ifdef AIBS_VERBOSE
-               printf("%s: %s %2i: %4s: "
-                   "0x%08llx %20s %5lli / %5lli  0x%llx\n",
-                   DEVNAME(sc), name, i, v[0]->v_string,
-                   as[i].i, as[i].s.desc, as[i].l, as[i].h,
-                   ri.v_package[4]->v_integer);
+       printf("%s: %4s: %s 0x%08llx %5lli / %5lli  0x%llx\n",
+           DEVNAME(sc), name, as->s.desc, as->i, as->l, as->h,
+           ri.v_package[ena]->v_integer);
 #endif
-               sensor_attach(&sc->sc_sensordev, &as[i].s);
-               aml_freevalue(&ri);
-       }
-
-       aml_freevalue(&res);
+       SIMPLEQ_INSERT_TAIL(&sc->sc_sensorlist, as, entry);
+       sensor_attach(&sc->sc_sensordev, &as->s);
+       aml_freevalue(&ri);
        return;
 }
 
 void
 aibs_refresh(void *arg)
 {
-       struct aibs_softc *sc = arg;
+       struct aibs_softc       *sc = arg;
+       struct aibs_sensor      *as;
 
-       aibs_refresh_r(sc, SENSOR_TEMP);
-       aibs_refresh_r(sc, SENSOR_FANRPM);
-       aibs_refresh_r(sc, SENSOR_VOLTS_DC);
+       SIMPLEQ_FOREACH(as, &sc->sc_sensorlist, entry)
+               aibs_refresh_r(sc, as);
 }
 
 void
-aibs_refresh_r(struct aibs_softc *sc, enum sensor_type st)
+aibs_refresh_r(struct aibs_softc *sc, struct aibs_sensor *as)
 {
-       struct aml_node         *node;
-       int                     i, n = sc->sc_sensordev.maxnumt[st];
-       char                    *name;
-       struct aibs_sensor      *as;
+       struct ksensor          *s = &as->s;
+       int64_t                 v;
+       const int64_t           l = as->l, h = as->h;
 
-       switch (st) {
+       if (aibs_getvalue(sc, as->i, &v)) {
+               s->flags |= SENSOR_FINVALID;
+               return;
+       }
+       switch (s->type) {
        case SENSOR_TEMP:
-               name = "RTMP";
-               as = sc->sc_asens_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:
-               name = "RFAN";
-               as = sc->sc_asens_fan;
+               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:
-               name = "RVLT";
-               as = sc->sc_asens_volt;
+               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:
-               return;
+               /* NOTREACHED */
+               break;
        }
+}
 
-       if (as == NULL)
-               return;
+int
+aibs_getvalue(struct aibs_softc *sc, int64_t i, int64_t *v)
+{
+       struct aml_node         *n = sc->sc_gitmnode;
+       struct aml_value        req, res;
+       struct aibs_cmd_buffer  cmd;
+       struct aibs_ret_buffer  ret;
+       enum aml_objecttype     type;
+
+       if (sc->sc_mode) {
+               cmd.id = i;
+               cmd.param1 = 0;
+               cmd.param2 = 0;
+               type = req.type = AML_OBJTYPE_BUFFER;
+               req.v_buffer = (uint8_t *)&cmd;
+               req.length = sizeof(cmd);
+       } else {
+               switch (ATK_TYPE(i)) {
+               case ATK_TYPE_TEMP:
+                       n = sc->sc_rtmpnode;
+                       break;
+               case ATK_TYPE_FAN:
+                       n = sc->sc_rfannode;
+                       break;
+               case ATK_TYPE_VOLT:
+                       n = sc->sc_rvltnode;
+                       break;
+               default:
+                       return (-1);
+               }
+               type = req.type = AML_OBJTYPE_INTEGER;
+               req.v_integer = i;
+       }
 
-       node = aml_searchname(sc->sc_devnode, name);
-       if (node == NULL || node->value == NULL ||
-           node->value->type != AML_OBJTYPE_METHOD) {
-               dprintf("%s: %s: method node not found\n",
-                   DEVNAME(sc), name);
-               for (i = 0; i < n; i++)
-                       as[i].s.flags |= SENSOR_FINVALID;
-               return;
+       if (aml_evalnode(sc->sc_acpi, n, 1, &req, &res)) {
+               dprintf("%s: %s: %i: evaluation failed\n",
+                   DEVNAME(sc), n->name, i);
+               aml_freevalue(&res);
+               return (-1);
+       }
+       if (res.type != type) {
+               dprintf("%s: %s: %i: not an integer: type %i\n",
+                   DEVNAME(sc), n->name, i, res.type);
+               aml_freevalue(&res);
+               return (-1);
        }
 
-       for (i = 0; i < n; i++) {
-               struct aml_value        req, res;
-               int64_t                 v;
-               struct ksensor          *s = &as[i].s;
-               const int64_t           l = as[i].l, h = as[i].h;
-
-               req.type = AML_OBJTYPE_INTEGER;
-               req.v_integer = as[i].i;
-               if (aml_evalnode(sc->sc_acpi, node, 1, &req, &res)) {
-                       dprintf("%s: %s: %i: evaluation failed\n",
-                           DEVNAME(sc), name, i);
+       if (sc->sc_mode) {
+               if (res.length < sizeof(ret)) {
+                       dprintf("%s: %s: %i: result buffer too small\n",
+                           DEVNAME(sc), n->name, i);
                        aml_freevalue(&res);
-                       s->flags |= SENSOR_FINVALID;
-                       continue;
+                       return (-1);
                }
-               if (res.type != AML_OBJTYPE_INTEGER) {
-                       dprintf("%s: %s: %i: not an integer: type %i\n",
-                           DEVNAME(sc), name, i, res.type);
+               bcopy(res.v_buffer, &ret, sizeof(ret));
+               if (ret.flags == 0) {
+                       dprintf("%s: %s: %i: bad flags in result\n",
+                           DEVNAME(sc), n->name, i);
                        aml_freevalue(&res);
-                       s->flags |= SENSOR_FINVALID;
-                       continue;
+                       return (-1);
                }
-               v = res.v_integer;
-               aml_freevalue(&res);
+               *v = ret.value;
+       } else {
+               *v = res.v_integer;
+       }
+       aml_freevalue(&res);
 
-               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 (0);
+}
+
+int
+aibs_getpack(struct aibs_softc *sc, struct aml_node *n, int64_t i,
+    struct aml_value *res)
+{
+       struct aml_value        req;
+
+       req.type = AML_OBJTYPE_INTEGER;
+       req.v_integer = i;
+
+       if (aml_evalnode(sc->sc_acpi, n, 1, &req, res)) {
+               dprintf("%s: %s: %i: evaluation failed\n",
+                   DEVNAME(sc), n->name, i);
+               aml_freevalue(res);
+               return (-1);
+       }
+       if (res->type != AML_OBJTYPE_PACKAGE) {
+               dprintf("%s: %s: %i: not a package: type %i\n",
+                   DEVNAME(sc), n->name, i, res->type);
+               aml_freevalue(res);
+               return (-1);
        }
 
-       return;
+       return (0);
+}
+
+void
+aibs_probe(struct aibs_softc *sc)
+{
+       /*
+        * Old mode uses TSIF, VSIF, and FSIF to enumerate sensors and
+        * RTMP, RVLT, and RFAN are used to get the values.
+        * New mode uses GGRP for enumeration and GITM and SITM as accessor.
+        * If the new methods are available use them else default to old mode.
+        */
+       printf(":");
+       aml_find_node(sc->sc_devnode, "RTMP", aibs_find_cb, &sc->sc_rtmpnode);
+       aml_find_node(sc->sc_devnode, "RVLT", aibs_find_cb, &sc->sc_rvltnode);
+       aml_find_node(sc->sc_devnode, "RFAN", aibs_find_cb, &sc->sc_rfannode);
+
+       aml_find_node(sc->sc_devnode, "GGRP", aibs_find_cb, &sc->sc_ggrpnode);
+       aml_find_node(sc->sc_devnode, "GITM", aibs_find_cb, &sc->sc_gitmnode);
+       aml_find_node(sc->sc_devnode, "SITM", aibs_find_cb, &sc->sc_sitmnode);
+
+       if (sc->sc_ggrpnode && sc->sc_gitmnode && sc->sc_sitmnode &&
+           !sc->sc_rtmpnode && !sc->sc_rvltnode && !sc->sc_rfannode)
+               sc->sc_mode = 1;
+}
+
+int
+aibs_find_cb(struct aml_node *node, void *arg)
+{
+       struct aml_node **np = arg;
+
+       printf(" %s", node->name);
+       *np = node;
+       return (1);
 }

Reply via email to