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);
}