diff options
Diffstat (limited to 'sys')
-rw-r--r-- | sys/dev/acpi/acpi.c | 5 | ||||
-rw-r--r-- | sys/dev/acpi/acpireg.h | 3 | ||||
-rw-r--r-- | sys/dev/acpi/atk0110.c | 382 | ||||
-rw-r--r-- | sys/dev/acpi/files.acpi | 7 |
4 files changed, 393 insertions, 4 deletions
diff --git a/sys/dev/acpi/acpi.c b/sys/dev/acpi/acpi.c index 86eb1722072..45d49b9ff66 100644 --- a/sys/dev/acpi/acpi.c +++ b/sys/dev/acpi/acpi.c @@ -1,4 +1,4 @@ -/* $OpenBSD: acpi.c,v 1.140 2009/06/03 07:13:48 pirofti Exp $ */ +/* $OpenBSD: acpi.c,v 1.141 2009/07/23 01:38:16 cnst Exp $ */ /* * Copyright (c) 2005 Thorsten Lockert <tholo@sigmasoft.com> * Copyright (c) 2005 Jordan Hargrave <jordan@openbsd.org> @@ -2244,7 +2244,8 @@ acpi_foundhid(struct aml_node *node, void *arg) else if (!strcmp(dev, ACPI_DEV_THINKPAD)) { aaa.aaa_name = "acpithinkpad"; acpi_thinkpad_enabled = 1; - } + } else if (!strcmp(dev, ACPI_DEV_ASUSAIBOOSTER)) + aaa.aaa_name = "aibs"; if (aaa.aaa_name) config_found(self, &aaa, acpi_print); diff --git a/sys/dev/acpi/acpireg.h b/sys/dev/acpi/acpireg.h index 3da2888e4fe..9550a684a41 100644 --- a/sys/dev/acpi/acpireg.h +++ b/sys/dev/acpi/acpireg.h @@ -1,4 +1,4 @@ -/* $OpenBSD: acpireg.h,v 1.17 2009/04/11 08:22:48 kettenis Exp $ */ +/* $OpenBSD: acpireg.h,v 1.18 2009/07/23 01:38:16 cnst Exp $ */ /* * Copyright (c) 2005 Thorsten Lockert <tholo@sigmasoft.com> * Copyright (c) 2005 Marco Peereboom <marco@openbsd.org> @@ -494,5 +494,6 @@ struct acpi_facs { #define ACPI_DEV_FFB "FIXEDBUTTON" /* Fixed Feature Button */ #define ACPI_DEV_ASUS "ASUS010" /* ASUS Hotkeys */ #define ACPI_DEV_THINKPAD "IBM0068" /* ThinkPad support */ +#define ACPI_DEV_ASUSAIBOOSTER "ATK0110" /* ASUSTeK AI Booster */ #endif /* !_DEV_ACPI_ACPIREG_H_ */ diff --git a/sys/dev/acpi/atk0110.c b/sys/dev/acpi/atk0110.c new file mode 100644 index 00000000000..a5b6f66dde8 --- /dev/null +++ b/sys/dev/acpi/atk0110.c @@ -0,0 +1,382 @@ +/* $OpenBSD: atk0110.c,v 1.1 2009/07/23 01:38:16 cnst Exp $ */ + +/* + * Copyright (c) 2009 Constantine A. Murenin <cnst+openbsd@bugmail.mojo.ru> + * + * 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/param.h> +#include <sys/systm.h> +#include <sys/device.h> +#include <sys/malloc.h> +#include <sys/sensors.h> + +#include <dev/acpi/acpireg.h> +#include <dev/acpi/acpivar.h> +#include <dev/acpi/acpidev.h> +#include <dev/acpi/amltypes.h> +#include <dev/acpi/dsdt.h> + +/* + * ASUSTeK AI Booster (ACPI ATK0110). + * + * The driver was inspired by Takanori Watanabe's acpi_aiboost driver. + * http://cvsweb.freebsd.org/src/sys/dev/acpi_support/acpi_aiboost.c + * + * Special thanks goes to Sam Fourman Jr. for providing access to several + * ASUS boxes where the driver could be tested. + * + * -- cnst.su. + */ + +#define AIBS_MORE_SENSORS +#define AIBS_VERBOSE + +struct aibs_sensor { + struct ksensor s; + int64_t i; + int64_t l; + int64_t h; +}; + +struct aibs_softc { + struct device sc_dev; + + 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 ksensordev sc_sensordev; +}; + + +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); + + +struct cfattach aibs_ca = { + sizeof(struct aibs_softc), aibs_match, aibs_attach +}; + +struct cfdriver aibs_cd = { + NULL, "aibs", DV_DULL +}; + +static const char* aibs_hids[] = { + ACPI_DEV_ASUSAIBOOSTER, + NULL +}; + +int +aibs_match(struct device *parent, void *match, void *aux) +{ + struct acpi_attach_args *aa = aux; + struct cfdata *cf = match; + + return acpi_matchhids(aa, aibs_hids, cf->cf_driver->cd_name); +} + +void +aibs_attach(struct device *parent, struct device *self, void *aux) +{ + struct aibs_softc *sc = (struct aibs_softc *)self; + struct acpi_attach_args *aa = aux; + + 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)); + + 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)); + return; + } + + if (sensor_task_register(sc, aibs_refresh, 5) == NULL) { + printf("%s: unable to register update task\n", DEVNAME(sc)); + return; + } + + sensordev_install(&sc->sc_sensordev); +} + +void +aibs_attach_sif(struct aibs_softc *sc, enum sensor_type st) +{ + struct aml_value res; + struct aml_value **v; + int i, n; + char *name = "?SIF"; + struct aibs_sensor *as; + + switch (st) { + case SENSOR_TEMP: + name[0] = 'T'; + break; + case SENSOR_FANRPM: + name[0] = 'F'; + break; + case SENSOR_VOLTS_DC: + name[0] = 'V'; + break; + default: + return; + } + + if (aml_evalname(sc->sc_acpi, sc->sc_devnode, name, 0, NULL, &res)) { + printf("%s: %s not found\n", DEVNAME(sc), name); + 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); + aml_freevalue(&res); + return; + } + + n = v[0]->v_integer; + if (res.length - 1 < n) { + printf("%s: %s: invalid package\n", DEVNAME(sc), name); + aml_freevalue(&res); + return; + } else if (res.length - 1 > n) { + printf("%s: %s: misformed package: %i/%i", + DEVNAME(sc), name, n, res.length - 1); +#ifdef AIBS_MORE_SENSORS + n = res.length - 1; +#endif + printf(", assume %i\n", n); + } + if (n < 1) { + printf("%s: %s: no members in the package\n", + DEVNAME(sc), name); + aml_freevalue(&res); + 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); + return; + } + + switch (st) { + case SENSOR_TEMP: + sc->sc_asens_temp = as; + break; + case SENSOR_FANRPM: + sc->sc_asens_fan = as; + break; + case SENSOR_VOLTS_DC: + sc->sc_asens_volt = as; + break; + default: + /* NOTREACHED */ + 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; +#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); +#endif + sensor_attach(&sc->sc_sensordev, &as[i].s); + aml_freevalue(&ri); + } + + aml_freevalue(&res); + return; +} + +void +aibs_refresh(void *arg) +{ + struct aibs_softc *sc = arg; + + aibs_refresh_r(sc, SENSOR_TEMP); + aibs_refresh_r(sc, SENSOR_FANRPM); + aibs_refresh_r(sc, SENSOR_VOLTS_DC); +} + +void +aibs_refresh_r(struct aibs_softc *sc, enum sensor_type st) +{ + struct aml_node *node; + int i, n = sc->sc_sensordev.maxnumt[st]; + char *name; + struct aibs_sensor *as; + + switch (st) { + case SENSOR_TEMP: + name = "RTMP"; + as = sc->sc_asens_temp; + break; + case SENSOR_FANRPM: + name = "RFAN"; + as = sc->sc_asens_fan; + break; + case SENSOR_VOLTS_DC: + name = "RVLT"; + as = sc->sc_asens_volt; + break; + default: + return; + } + + if (as == NULL) + return; + + 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; + } + + for (i = 0; i < n; i++) { + struct aml_value req, res; + struct ksensor *s; + int64_t v, l, 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); + aml_freevalue(&res); + s->flags |= SENSOR_FINVALID; + continue; + } + if (res.type != AML_OBJTYPE_INTEGER) { + dprintf("%s: %s: %i: not an integer: type %i\n", + DEVNAME(sc), name, i, res.type); + aml_freevalue(&res); + s->flags |= SENSOR_FINVALID; + continue; + } + + v = res.v_integer; + s = &as[i].s; + l = as[i].l; + h = as[i].h; + + 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; + } + aml_freevalue(&res); + } + + return; +} diff --git a/sys/dev/acpi/files.acpi b/sys/dev/acpi/files.acpi index be89febd85f..7a1c444bbc5 100644 --- a/sys/dev/acpi/files.acpi +++ b/sys/dev/acpi/files.acpi @@ -1,4 +1,4 @@ -# $OpenBSD: files.acpi,v 1.22 2009/06/03 07:13:48 pirofti Exp $ +# $OpenBSD: files.acpi,v 1.23 2009/07/23 01:38:16 cnst Exp $ # # Config file and device description for machine-independent ACPI code. # Included by ports that need it. @@ -91,3 +91,8 @@ file dev/acpi/acpivout.c acpivout device acpipwrres attach acpipwrres at acpi file dev/acpi/acpipwrres.c acpipwrres + +# ASUSTeK AI Booster ATK0110 +device aibs +attach aibs at acpi +file dev/acpi/atk0110.c aibs |