1*9593dc34Smglocker /* $OpenBSD: atk0110.c,v 1.20 2024/09/04 07:54:52 mglocker Exp $ */ 211711e68Scnst 311711e68Scnst /* 411711e68Scnst * Copyright (c) 2009 Constantine A. Murenin <cnst+openbsd@bugmail.mojo.ru> 511711e68Scnst * 611711e68Scnst * Permission to use, copy, modify, and distribute this software for any 711711e68Scnst * purpose with or without fee is hereby granted, provided that the above 811711e68Scnst * copyright notice and this permission notice appear in all copies. 911711e68Scnst * 1011711e68Scnst * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 1111711e68Scnst * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 1211711e68Scnst * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 1311711e68Scnst * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 1411711e68Scnst * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 1511711e68Scnst * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 1611711e68Scnst * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 1711711e68Scnst */ 1811711e68Scnst 1911711e68Scnst #include <sys/param.h> 2011711e68Scnst #include <sys/systm.h> 2111711e68Scnst #include <sys/device.h> 2211711e68Scnst #include <sys/malloc.h> 2311711e68Scnst #include <sys/sensors.h> 2411711e68Scnst 2511711e68Scnst #include <dev/acpi/acpireg.h> 2611711e68Scnst #include <dev/acpi/acpivar.h> 2711711e68Scnst #include <dev/acpi/acpidev.h> 2811711e68Scnst #include <dev/acpi/amltypes.h> 2911711e68Scnst #include <dev/acpi/dsdt.h> 3011711e68Scnst 3111711e68Scnst /* 3211711e68Scnst * ASUSTeK AI Booster (ACPI ATK0110). 3311711e68Scnst * 3411711e68Scnst * The driver was inspired by Takanori Watanabe's acpi_aiboost driver. 3511711e68Scnst * http://cvsweb.freebsd.org/src/sys/dev/acpi_support/acpi_aiboost.c 3611711e68Scnst * 3711711e68Scnst * Special thanks goes to Sam Fourman Jr. for providing access to several 3811711e68Scnst * ASUS boxes where the driver could be tested. 3911711e68Scnst * 4011711e68Scnst * -- cnst.su. 4111711e68Scnst */ 4211711e68Scnst 4345471ecdSclaudio #define ATK_ID_MUX_HWMON 0x00000006 4445471ecdSclaudio 4545471ecdSclaudio #define ATK_CLASS(x) (((x) >> 24) & 0xff) 4645471ecdSclaudio #define ATK_CLASS_FREQ_CTL 3 4745471ecdSclaudio #define ATK_CLASS_FAN_CTL 4 4845471ecdSclaudio #define ATK_CLASS_HWMON 6 4945471ecdSclaudio #define ATK_CLASS_MGMT 17 5045471ecdSclaudio 5145471ecdSclaudio #define ATK_TYPE(x) (((x) >> 16) & 0xff) 5245471ecdSclaudio #define ATK_TYPE_VOLT 2 5345471ecdSclaudio #define ATK_TYPE_TEMP 3 5445471ecdSclaudio #define ATK_TYPE_FAN 4 5545471ecdSclaudio 5611711e68Scnst #define AIBS_MORE_SENSORS 5727fa1cc5Sderaadt /* #define AIBS_VERBOSE */ 5811711e68Scnst 5911711e68Scnst struct aibs_sensor { 6011711e68Scnst struct ksensor s; 6111711e68Scnst int64_t i; 6211711e68Scnst int64_t l; 6311711e68Scnst int64_t h; 6445471ecdSclaudio SIMPLEQ_ENTRY(aibs_sensor) entry; 6511711e68Scnst }; 6611711e68Scnst 6711711e68Scnst struct aibs_softc { 6811711e68Scnst struct device sc_dev; 6911711e68Scnst 7011711e68Scnst struct acpi_softc *sc_acpi; 7111711e68Scnst struct aml_node *sc_devnode; 7211711e68Scnst 7345471ecdSclaudio struct aml_node *sc_ggrpnode; 7445471ecdSclaudio struct aml_node *sc_gitmnode; 7545471ecdSclaudio struct aml_node *sc_sitmnode; 7645471ecdSclaudio struct aml_node *sc_rtmpnode; 7745471ecdSclaudio struct aml_node *sc_rvltnode; 7845471ecdSclaudio struct aml_node *sc_rfannode; 7911711e68Scnst 8045471ecdSclaudio SIMPLEQ_HEAD(, aibs_sensor) sc_sensorlist; 8111711e68Scnst struct ksensordev sc_sensordev; 8245471ecdSclaudio 8345471ecdSclaudio int sc_mode; /* 1 = new, 0 = old */ 8411711e68Scnst }; 8511711e68Scnst 8645471ecdSclaudio /* Command buffer used for GITM and SITM methods */ 8745471ecdSclaudio struct aibs_cmd_buffer { 88d2eaebe9Skettenis uint32_t id; 89d2eaebe9Skettenis uint32_t param1; 90d2eaebe9Skettenis uint32_t param2; 9145471ecdSclaudio }; 9245471ecdSclaudio 934b1a56afSjsg /* Return buffer used by the GITM and SITM methods */ 9445471ecdSclaudio struct aibs_ret_buffer { 95d2eaebe9Skettenis uint32_t flags; 96d2eaebe9Skettenis uint32_t value; 9745471ecdSclaudio /* there is more stuff that is unknown */ 9845471ecdSclaudio }; 9911711e68Scnst 10011711e68Scnst int aibs_match(struct device *, void *, void *); 10111711e68Scnst void aibs_attach(struct device *, struct device *, void *); 10221aa9033Sderaadt int aibs_notify(struct aml_node *, int, void *); 10311711e68Scnst void aibs_refresh(void *); 10411711e68Scnst 10511711e68Scnst void aibs_attach_sif(struct aibs_softc *, enum sensor_type); 10645471ecdSclaudio void aibs_attach_new(struct aibs_softc *); 107abe2aaccSpatrick void aibs_add_sensor(struct aibs_softc *, const char *); 10845471ecdSclaudio void aibs_refresh_r(struct aibs_softc *, struct aibs_sensor *); 10945471ecdSclaudio int aibs_getvalue(struct aibs_softc *, int64_t, int64_t *); 11045471ecdSclaudio int aibs_getpack(struct aibs_softc *, struct aml_node *, int64_t, 11145471ecdSclaudio struct aml_value *); 11245471ecdSclaudio void aibs_probe(struct aibs_softc *); 11345471ecdSclaudio int aibs_find_cb(struct aml_node *, void *); 11411711e68Scnst 11511711e68Scnst 116471aeecfSnaddy const struct cfattach aibs_ca = { 11711711e68Scnst sizeof(struct aibs_softc), aibs_match, aibs_attach 11811711e68Scnst }; 11911711e68Scnst 12011711e68Scnst struct cfdriver aibs_cd = { 12111711e68Scnst NULL, "aibs", DV_DULL 12211711e68Scnst }; 12311711e68Scnst 12411711e68Scnst static const char* aibs_hids[] = { 1256bf9874fSjcs "ATK0110", 12611711e68Scnst NULL 12711711e68Scnst }; 12811711e68Scnst 12911711e68Scnst int 13011711e68Scnst aibs_match(struct device *parent, void *match, void *aux) 13111711e68Scnst { 13211711e68Scnst struct acpi_attach_args *aa = aux; 13311711e68Scnst struct cfdata *cf = match; 13411711e68Scnst 13511711e68Scnst return acpi_matchhids(aa, aibs_hids, cf->cf_driver->cd_name); 13611711e68Scnst } 13711711e68Scnst 13811711e68Scnst void 13911711e68Scnst aibs_attach(struct device *parent, struct device *self, void *aux) 14011711e68Scnst { 14111711e68Scnst struct aibs_softc *sc = (struct aibs_softc *)self; 14211711e68Scnst struct acpi_attach_args *aa = aux; 14311711e68Scnst 14411711e68Scnst sc->sc_acpi = (struct acpi_softc *)parent; 14511711e68Scnst sc->sc_devnode = aa->aaa_node; 14611711e68Scnst 14711711e68Scnst strlcpy(sc->sc_sensordev.xname, sc->sc_dev.dv_xname, 14811711e68Scnst sizeof(sc->sc_sensordev.xname)); 14945471ecdSclaudio SIMPLEQ_INIT(&sc->sc_sensorlist); 15011711e68Scnst 15145471ecdSclaudio aibs_probe(sc); 15245471ecdSclaudio printf("\n"); 15345471ecdSclaudio 15445471ecdSclaudio if (sc->sc_mode) 15545471ecdSclaudio aibs_attach_new(sc); 15645471ecdSclaudio else { 15711711e68Scnst aibs_attach_sif(sc, SENSOR_TEMP); 15811711e68Scnst aibs_attach_sif(sc, SENSOR_FANRPM); 15911711e68Scnst aibs_attach_sif(sc, SENSOR_VOLTS_DC); 16045471ecdSclaudio } 16111711e68Scnst 16211711e68Scnst if (sc->sc_sensordev.sensors_count == 0) { 16311711e68Scnst printf("%s: no sensors found\n", DEVNAME(sc)); 16411711e68Scnst return; 16511711e68Scnst } 16611711e68Scnst 16711711e68Scnst sensordev_install(&sc->sc_sensordev); 16821aa9033Sderaadt 16921aa9033Sderaadt aml_register_notify(sc->sc_devnode, aa->aaa_dev, 17021aa9033Sderaadt aibs_notify, sc, ACPIDEV_POLL); 17111711e68Scnst } 17211711e68Scnst 17311711e68Scnst void 17411711e68Scnst aibs_attach_sif(struct aibs_softc *sc, enum sensor_type st) 17511711e68Scnst { 17611711e68Scnst struct aml_value res; 17711711e68Scnst struct aml_value **v; 17811711e68Scnst int i, n; 17979756d5eSnicm char name[] = "?SIF"; 18011711e68Scnst 18111711e68Scnst switch (st) { 18211711e68Scnst case SENSOR_TEMP: 18311711e68Scnst name[0] = 'T'; 18411711e68Scnst break; 18511711e68Scnst case SENSOR_FANRPM: 18611711e68Scnst name[0] = 'F'; 18711711e68Scnst break; 18811711e68Scnst case SENSOR_VOLTS_DC: 18911711e68Scnst name[0] = 'V'; 19011711e68Scnst break; 19111711e68Scnst default: 19211711e68Scnst return; 19311711e68Scnst } 19411711e68Scnst 19511711e68Scnst if (aml_evalname(sc->sc_acpi, sc->sc_devnode, name, 0, NULL, &res)) { 19611711e68Scnst printf("%s: %s not found\n", DEVNAME(sc), name); 19711711e68Scnst aml_freevalue(&res); 19811711e68Scnst return; 19911711e68Scnst } 20011711e68Scnst if (res.type != AML_OBJTYPE_PACKAGE) { 20111711e68Scnst printf("%s: %s: not a package\n", DEVNAME(sc), name); 20211711e68Scnst aml_freevalue(&res); 20311711e68Scnst return; 20411711e68Scnst } 20511711e68Scnst v = res.v_package; 20611711e68Scnst if (v[0]->type != AML_OBJTYPE_INTEGER) { 20711711e68Scnst printf("%s: %s[0]: invalid type\n", DEVNAME(sc), name); 20811711e68Scnst aml_freevalue(&res); 20911711e68Scnst return; 21011711e68Scnst } 21111711e68Scnst 21211711e68Scnst n = v[0]->v_integer; 21311711e68Scnst if (res.length - 1 < n) { 21411711e68Scnst printf("%s: %s: invalid package\n", DEVNAME(sc), name); 21511711e68Scnst aml_freevalue(&res); 21611711e68Scnst return; 21711711e68Scnst } else if (res.length - 1 > n) { 218*9593dc34Smglocker printf("%s: %s: malformed package: %i/%i", 21911711e68Scnst DEVNAME(sc), name, n, res.length - 1); 22011711e68Scnst #ifdef AIBS_MORE_SENSORS 22111711e68Scnst n = res.length - 1; 22211711e68Scnst #endif 22311711e68Scnst printf(", assume %i\n", n); 22411711e68Scnst } 22511711e68Scnst if (n < 1) { 22611711e68Scnst printf("%s: %s: no members in the package\n", 22711711e68Scnst DEVNAME(sc), name); 22811711e68Scnst aml_freevalue(&res); 22911711e68Scnst return; 23011711e68Scnst } 23111711e68Scnst 23211711e68Scnst for (i = 0, v++; i < n; i++, v++) { 233d90a88ceSkettenis if(v[0]->type != AML_OBJTYPE_NAMEREF) { 234d90a88ceSkettenis printf("%s: %s: %i: not a nameref: %i type\n", 23511711e68Scnst DEVNAME(sc), name, i, v[0]->type); 23611711e68Scnst continue; 23711711e68Scnst } 238abe2aaccSpatrick aibs_add_sensor(sc, aml_getname(v[0]->v_nameref)); 23911711e68Scnst } 24011711e68Scnst 24111711e68Scnst aml_freevalue(&res); 24245471ecdSclaudio } 24345471ecdSclaudio 24445471ecdSclaudio void 24545471ecdSclaudio aibs_attach_new(struct aibs_softc *sc) 24645471ecdSclaudio { 24745471ecdSclaudio struct aml_value res; 24845471ecdSclaudio int i; 24945471ecdSclaudio 25045471ecdSclaudio if (aibs_getpack(sc, sc->sc_ggrpnode, ATK_ID_MUX_HWMON, &res)) { 2512cd40198Sderaadt printf("%s: GGRP: sensor enumeration failed\n", DEVNAME(sc)); 25245471ecdSclaudio return; 25345471ecdSclaudio } 25445471ecdSclaudio 25545471ecdSclaudio for (i = 0; i < res.length; i++) { 25645471ecdSclaudio struct aml_value *r; 25745471ecdSclaudio r = res.v_package[i]; 25845471ecdSclaudio if (r->type != AML_OBJTYPE_STRING) { 25945471ecdSclaudio printf("%s: %s: %i: not a string (type %i)\n", 26045471ecdSclaudio DEVNAME(sc), "GGRP", i, r->type); 26145471ecdSclaudio continue; 26245471ecdSclaudio } 26345471ecdSclaudio aibs_add_sensor(sc, r->v_string); 26445471ecdSclaudio } 26545471ecdSclaudio aml_freevalue(&res); 26645471ecdSclaudio } 26745471ecdSclaudio 26845471ecdSclaudio void 269abe2aaccSpatrick aibs_add_sensor(struct aibs_softc *sc, const char *name) 27045471ecdSclaudio { 27145471ecdSclaudio struct aml_value ri; 27245471ecdSclaudio struct aibs_sensor *as; 27345471ecdSclaudio int len, lim1, lim2, ena; 27445471ecdSclaudio 27545471ecdSclaudio if (aml_evalname(sc->sc_acpi, sc->sc_devnode, name, 27645471ecdSclaudio 0, NULL, &ri)) { 27745471ecdSclaudio printf("%s: aibs_add_sensor: %s not found\n", 278ec88ef36Sjsg DEVNAME(sc), name); 27945471ecdSclaudio aml_freevalue(&ri); 28045471ecdSclaudio return; 28145471ecdSclaudio } 28245471ecdSclaudio if (ri.type != AML_OBJTYPE_PACKAGE) { 28345471ecdSclaudio printf("%s: aibs_add_sensor: %s: not a package\n", 28445471ecdSclaudio DEVNAME(sc), name); 28545471ecdSclaudio aml_freevalue(&ri); 28645471ecdSclaudio return; 28745471ecdSclaudio } 28845471ecdSclaudio if (sc->sc_mode) { 28945471ecdSclaudio len = 7; 29045471ecdSclaudio lim1 = 4; 29145471ecdSclaudio lim2 = 5; 29245471ecdSclaudio ena = 6; 29345471ecdSclaudio } else { 29445471ecdSclaudio len = 5; 29545471ecdSclaudio lim1 = 2; 29645471ecdSclaudio lim2 = 3; 29745471ecdSclaudio ena = 4; 29845471ecdSclaudio } 29945471ecdSclaudio 30045471ecdSclaudio if (ri.length != len || 30145471ecdSclaudio ri.v_package[0]->type != AML_OBJTYPE_INTEGER || 30245471ecdSclaudio ri.v_package[1]->type != AML_OBJTYPE_STRING || 30345471ecdSclaudio ri.v_package[lim1]->type != AML_OBJTYPE_INTEGER || 30445471ecdSclaudio ri.v_package[lim2]->type != AML_OBJTYPE_INTEGER || 30545471ecdSclaudio ri.v_package[ena]->type != AML_OBJTYPE_INTEGER) { 30645471ecdSclaudio printf("%s: aibs_add_sensor: %s: invalid package\n", 30745471ecdSclaudio DEVNAME(sc), name); 30845471ecdSclaudio aml_freevalue(&ri); 30945471ecdSclaudio return; 31045471ecdSclaudio } 31145471ecdSclaudio as = malloc(sizeof(*as), M_DEVBUF, M_NOWAIT | M_ZERO); 31245471ecdSclaudio if (!as) { 31345471ecdSclaudio printf("%s: aibs_add_sensor: %s: failed to allocate sensor\n", 31445471ecdSclaudio DEVNAME(sc), name); 31545471ecdSclaudio aml_freevalue(&ri); 31645471ecdSclaudio return; 31745471ecdSclaudio } 31845471ecdSclaudio as->i = ri.v_package[0]->v_integer; 31945471ecdSclaudio switch (ATK_TYPE(as->i)) { 32045471ecdSclaudio case ATK_TYPE_VOLT: 32145471ecdSclaudio as->s.type = SENSOR_VOLTS_DC; 32245471ecdSclaudio break; 32345471ecdSclaudio case ATK_TYPE_TEMP: 32445471ecdSclaudio as->s.type = SENSOR_TEMP; 32545471ecdSclaudio break; 32645471ecdSclaudio case ATK_TYPE_FAN: 32745471ecdSclaudio as->s.type = SENSOR_FANRPM; 32845471ecdSclaudio break; 32945471ecdSclaudio default: 33045471ecdSclaudio printf("%s: aibs_add_sensor: %s: unknown sensor type %llx\n", 33145471ecdSclaudio DEVNAME(sc), name, ri.v_package[0]->v_integer); 33245471ecdSclaudio aml_freevalue(&ri); 3331ccca4d2Sderaadt free(as, M_DEVBUF, sizeof(*as)); 33445471ecdSclaudio return; 33545471ecdSclaudio } 33645471ecdSclaudio strlcpy(as->s.desc, ri.v_package[1]->v_string, 33745471ecdSclaudio sizeof(as->s.desc)); 33845471ecdSclaudio as->l = ri.v_package[lim1]->v_integer; 33945471ecdSclaudio if (sc->sc_mode) 34045471ecdSclaudio /* the second limit is a actually a range */ 34145471ecdSclaudio as->h = as->l + ri.v_package[lim2]->v_integer; 34245471ecdSclaudio else 34345471ecdSclaudio as->h = ri.v_package[lim2]->v_integer; 34445471ecdSclaudio #ifdef AIBS_VERBOSE 34545471ecdSclaudio printf("%s: %4s: %s 0x%08llx %5lli / %5lli 0x%llx\n", 34645471ecdSclaudio DEVNAME(sc), name, as->s.desc, as->i, as->l, as->h, 34745471ecdSclaudio ri.v_package[ena]->v_integer); 34845471ecdSclaudio #endif 34945471ecdSclaudio SIMPLEQ_INSERT_TAIL(&sc->sc_sensorlist, as, entry); 35045471ecdSclaudio sensor_attach(&sc->sc_sensordev, &as->s); 35145471ecdSclaudio aml_freevalue(&ri); 35211711e68Scnst return; 35311711e68Scnst } 35411711e68Scnst 35511711e68Scnst void 35611711e68Scnst aibs_refresh(void *arg) 35711711e68Scnst { 35811711e68Scnst struct aibs_softc *sc = arg; 35945471ecdSclaudio struct aibs_sensor *as; 36011711e68Scnst 36145471ecdSclaudio SIMPLEQ_FOREACH(as, &sc->sc_sensorlist, entry) 36245471ecdSclaudio aibs_refresh_r(sc, as); 36311711e68Scnst } 36411711e68Scnst 36511711e68Scnst void 36645471ecdSclaudio aibs_refresh_r(struct aibs_softc *sc, struct aibs_sensor *as) 36711711e68Scnst { 36845471ecdSclaudio struct ksensor *s = &as->s; 36993a585d8Sderaadt int64_t v; 37045471ecdSclaudio const int64_t l = as->l, h = as->h; 37111711e68Scnst 37245471ecdSclaudio if (aibs_getvalue(sc, as->i, &v)) { 37311711e68Scnst s->flags |= SENSOR_FINVALID; 37445471ecdSclaudio return; 37511711e68Scnst } 37645471ecdSclaudio switch (s->type) { 37711711e68Scnst case SENSOR_TEMP: 37811711e68Scnst s->value = v * 100 * 1000 + 273150000; 37911711e68Scnst if (v == 0) { 38011711e68Scnst s->status = SENSOR_S_UNKNOWN; 38111711e68Scnst s->flags |= SENSOR_FINVALID; 38211711e68Scnst } else { 38311711e68Scnst if (v > h) 38411711e68Scnst s->status = SENSOR_S_CRIT; 38511711e68Scnst else if (v > l) 38611711e68Scnst s->status = SENSOR_S_WARN; 38711711e68Scnst else 38811711e68Scnst s->status = SENSOR_S_OK; 38911711e68Scnst s->flags &= ~SENSOR_FINVALID; 39011711e68Scnst } 39111711e68Scnst break; 39211711e68Scnst case SENSOR_FANRPM: 39311711e68Scnst s->value = v; 39411711e68Scnst /* some boards have strange limits for fans */ 39511711e68Scnst if ((l != 0 && l < v && v < h) || 39611711e68Scnst (l == 0 && v > h)) 39711711e68Scnst s->status = SENSOR_S_OK; 39811711e68Scnst else 39911711e68Scnst s->status = SENSOR_S_WARN; 40011711e68Scnst s->flags &= ~SENSOR_FINVALID; 40111711e68Scnst break; 40211711e68Scnst case SENSOR_VOLTS_DC: 40311711e68Scnst s->value = v * 1000; 40411711e68Scnst if (l < v && v < h) 40511711e68Scnst s->status = SENSOR_S_OK; 40611711e68Scnst else 40711711e68Scnst s->status = SENSOR_S_WARN; 40811711e68Scnst s->flags &= ~SENSOR_FINVALID; 40911711e68Scnst break; 41011711e68Scnst default: 41111711e68Scnst /* NOTREACHED */ 41211711e68Scnst break; 41311711e68Scnst } 41411711e68Scnst } 41511711e68Scnst 41645471ecdSclaudio int 41745471ecdSclaudio aibs_getvalue(struct aibs_softc *sc, int64_t i, int64_t *v) 41845471ecdSclaudio { 41945471ecdSclaudio struct aml_node *n = sc->sc_gitmnode; 42045471ecdSclaudio struct aml_value req, res; 42145471ecdSclaudio struct aibs_cmd_buffer cmd; 42245471ecdSclaudio struct aibs_ret_buffer ret; 42345471ecdSclaudio enum aml_objecttype type; 42445471ecdSclaudio 42545471ecdSclaudio if (sc->sc_mode) { 42645471ecdSclaudio cmd.id = i; 42745471ecdSclaudio cmd.param1 = 0; 42845471ecdSclaudio cmd.param2 = 0; 42945471ecdSclaudio type = req.type = AML_OBJTYPE_BUFFER; 43045471ecdSclaudio req.v_buffer = (uint8_t *)&cmd; 43145471ecdSclaudio req.length = sizeof(cmd); 43245471ecdSclaudio } else { 43345471ecdSclaudio switch (ATK_TYPE(i)) { 43445471ecdSclaudio case ATK_TYPE_TEMP: 43545471ecdSclaudio n = sc->sc_rtmpnode; 43645471ecdSclaudio break; 43745471ecdSclaudio case ATK_TYPE_FAN: 43845471ecdSclaudio n = sc->sc_rfannode; 43945471ecdSclaudio break; 44045471ecdSclaudio case ATK_TYPE_VOLT: 44145471ecdSclaudio n = sc->sc_rvltnode; 44245471ecdSclaudio break; 44345471ecdSclaudio default: 44445471ecdSclaudio return (-1); 44545471ecdSclaudio } 44645471ecdSclaudio type = req.type = AML_OBJTYPE_INTEGER; 44745471ecdSclaudio req.v_integer = i; 44845471ecdSclaudio } 44945471ecdSclaudio 45045471ecdSclaudio if (aml_evalnode(sc->sc_acpi, n, 1, &req, &res)) { 4517a27271eSmlarkin dprintf("%s: %s: %lld: evaluation failed\n", 45245471ecdSclaudio DEVNAME(sc), n->name, i); 45345471ecdSclaudio aml_freevalue(&res); 45445471ecdSclaudio return (-1); 45545471ecdSclaudio } 45645471ecdSclaudio if (res.type != type) { 4577a27271eSmlarkin dprintf("%s: %s: %lld: not an integer: type %i\n", 45845471ecdSclaudio DEVNAME(sc), n->name, i, res.type); 45945471ecdSclaudio aml_freevalue(&res); 46045471ecdSclaudio return (-1); 46145471ecdSclaudio } 46245471ecdSclaudio 46345471ecdSclaudio if (sc->sc_mode) { 46445471ecdSclaudio if (res.length < sizeof(ret)) { 4657a27271eSmlarkin dprintf("%s: %s: %lld: result buffer too small\n", 46645471ecdSclaudio DEVNAME(sc), n->name, i); 46745471ecdSclaudio aml_freevalue(&res); 46845471ecdSclaudio return (-1); 46945471ecdSclaudio } 470368c74daSderaadt memcpy(&ret, res.v_buffer, sizeof(ret)); 47145471ecdSclaudio if (ret.flags == 0) { 4727a27271eSmlarkin dprintf("%s: %s: %lld: bad flags in result\n", 47345471ecdSclaudio DEVNAME(sc), n->name, i); 47445471ecdSclaudio aml_freevalue(&res); 47545471ecdSclaudio return (-1); 47645471ecdSclaudio } 47745471ecdSclaudio *v = ret.value; 47845471ecdSclaudio } else { 47945471ecdSclaudio *v = res.v_integer; 48045471ecdSclaudio } 48145471ecdSclaudio aml_freevalue(&res); 48245471ecdSclaudio 48345471ecdSclaudio return (0); 48445471ecdSclaudio } 48545471ecdSclaudio 48645471ecdSclaudio int 48745471ecdSclaudio aibs_getpack(struct aibs_softc *sc, struct aml_node *n, int64_t i, 48845471ecdSclaudio struct aml_value *res) 48945471ecdSclaudio { 49045471ecdSclaudio struct aml_value req; 49145471ecdSclaudio 49245471ecdSclaudio req.type = AML_OBJTYPE_INTEGER; 49345471ecdSclaudio req.v_integer = i; 49445471ecdSclaudio 49545471ecdSclaudio if (aml_evalnode(sc->sc_acpi, n, 1, &req, res)) { 4967a27271eSmlarkin dprintf("%s: %s: %lld: evaluation failed\n", 49745471ecdSclaudio DEVNAME(sc), n->name, i); 49845471ecdSclaudio aml_freevalue(res); 49945471ecdSclaudio return (-1); 50045471ecdSclaudio } 50145471ecdSclaudio if (res->type != AML_OBJTYPE_PACKAGE) { 5027a27271eSmlarkin dprintf("%s: %s: %lld: not a package: type %i\n", 50345471ecdSclaudio DEVNAME(sc), n->name, i, res->type); 50445471ecdSclaudio aml_freevalue(res); 50545471ecdSclaudio return (-1); 50645471ecdSclaudio } 50745471ecdSclaudio 50845471ecdSclaudio return (0); 50945471ecdSclaudio } 51045471ecdSclaudio 51145471ecdSclaudio void 51245471ecdSclaudio aibs_probe(struct aibs_softc *sc) 51345471ecdSclaudio { 51445471ecdSclaudio /* 51545471ecdSclaudio * Old mode uses TSIF, VSIF, and FSIF to enumerate sensors and 51645471ecdSclaudio * RTMP, RVLT, and RFAN are used to get the values. 51745471ecdSclaudio * New mode uses GGRP for enumeration and GITM and SITM as accessor. 51845471ecdSclaudio * If the new methods are available use them else default to old mode. 51945471ecdSclaudio */ 52045471ecdSclaudio aml_find_node(sc->sc_devnode, "RTMP", aibs_find_cb, &sc->sc_rtmpnode); 52145471ecdSclaudio aml_find_node(sc->sc_devnode, "RVLT", aibs_find_cb, &sc->sc_rvltnode); 52245471ecdSclaudio aml_find_node(sc->sc_devnode, "RFAN", aibs_find_cb, &sc->sc_rfannode); 52345471ecdSclaudio 52445471ecdSclaudio aml_find_node(sc->sc_devnode, "GGRP", aibs_find_cb, &sc->sc_ggrpnode); 52545471ecdSclaudio aml_find_node(sc->sc_devnode, "GITM", aibs_find_cb, &sc->sc_gitmnode); 52645471ecdSclaudio aml_find_node(sc->sc_devnode, "SITM", aibs_find_cb, &sc->sc_sitmnode); 52745471ecdSclaudio 52845471ecdSclaudio if (sc->sc_ggrpnode && sc->sc_gitmnode && sc->sc_sitmnode && 52945471ecdSclaudio !sc->sc_rtmpnode && !sc->sc_rvltnode && !sc->sc_rfannode) 53045471ecdSclaudio sc->sc_mode = 1; 53145471ecdSclaudio } 53245471ecdSclaudio 53345471ecdSclaudio int 53445471ecdSclaudio aibs_find_cb(struct aml_node *node, void *arg) 53545471ecdSclaudio { 53645471ecdSclaudio struct aml_node **np = arg; 53745471ecdSclaudio 53845471ecdSclaudio printf(" %s", node->name); 53945471ecdSclaudio *np = node; 54045471ecdSclaudio return (1); 54111711e68Scnst } 54221aa9033Sderaadt 54321aa9033Sderaadt int 54421aa9033Sderaadt aibs_notify(struct aml_node *node, int notify_type, void *arg) 54521aa9033Sderaadt { 54621aa9033Sderaadt struct aibs_softc *sc = arg; 54721aa9033Sderaadt 54821aa9033Sderaadt if (notify_type == 0x00) { 54921aa9033Sderaadt /* Poll sensors */ 55021aa9033Sderaadt aibs_refresh(sc); 55121aa9033Sderaadt } 55221aa9033Sderaadt return (0); 55321aa9033Sderaadt } 554