xref: /openbsd-src/sys/dev/acpi/atk0110.c (revision 9593dc34da13a12012033a17061c846c208061c2)
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