1209523Srpaulo/* $NetBSD: atk0110.c,v 1.4 2010/02/11 06:54:57 cnst Exp $ */ 2209523Srpaulo/* $OpenBSD: atk0110.c,v 1.1 2009/07/23 01:38:16 cnst Exp $ */ 3209523Srpaulo 4209523Srpaulo/* 5209523Srpaulo * Copyright (c) 2009, 2010 Constantine A. Murenin <cnst++@FreeBSD.org> 6209523Srpaulo * 7209523Srpaulo * Permission to use, copy, modify, and distribute this software for any 8209523Srpaulo * purpose with or without fee is hereby granted, provided that the above 9209523Srpaulo * copyright notice and this permission notice appear in all copies. 10209523Srpaulo * 11209523Srpaulo * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 12209523Srpaulo * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 13209523Srpaulo * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 14209523Srpaulo * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 15209523Srpaulo * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 16209523Srpaulo * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 17209523Srpaulo * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 18209523Srpaulo */ 19209523Srpaulo 20209523Srpaulo#include <sys/cdefs.h> 21209523Srpaulo__FBSDID("$FreeBSD: stable/11/sys/dev/acpi_support/atk0110.c 335471 2018-06-21 09:41:44Z dim $"); 22209523Srpaulo 23209523Srpaulo#include <machine/_inttypes.h> 24209523Srpaulo#include <sys/param.h> 25209523Srpaulo#include <sys/systm.h> 26209523Srpaulo#include <sys/kernel.h> 27209523Srpaulo#include <sys/bus.h> 28209523Srpaulo#include <sys/module.h> 29209523Srpaulo#include <sys/malloc.h> 30209523Srpaulo#include <sys/sysctl.h> 31308368Savg#include <sys/stdint.h> 32209523Srpaulo 33209523Srpaulo#include <contrib/dev/acpica/include/acpi.h> 34209523Srpaulo#include <dev/acpica/acpivar.h> 35209523Srpaulo 36209523Srpaulo/* 37209523Srpaulo * ASUSTeK AI Booster (ACPI ASOC ATK0110). 38209523Srpaulo * 39209523Srpaulo * This code was originally written for OpenBSD after the techniques 40209523Srpaulo * described in the Linux's asus_atk0110.c and FreeBSD's Takanori Watanabe's 41209523Srpaulo * acpi_aiboost.c were verified to be accurate on the actual hardware kindly 42209523Srpaulo * provided by Sam Fourman Jr. It was subsequently ported from OpenBSD to 43209523Srpaulo * DragonFly BSD, to NetBSD's sysmon_envsys(9) and to FreeBSD's sysctl(9). 44209523Srpaulo * 45209523Srpaulo * -- Constantine A. Murenin <http://cnst.su/> 46209523Srpaulo */ 47209523Srpaulo 48209523Srpaulo#define _COMPONENT ACPI_OEM 49209523SrpauloACPI_MODULE_NAME("aibs"); 50209523SrpauloACPI_SERIAL_DECL(aibs, "aibs"); 51209523Srpaulo 52209523Srpaulo#define AIBS_MORE_SENSORS 53209523Srpaulo#define AIBS_VERBOSE 54209523Srpaulo 55308368Savg#define AIBS_GROUP_SENSORS 0x06 56209523Srpaulo 57308368Savg#define AIBS_SENS_TYPE(x) (((x) >> 16) & 0xff) 58308368Savg#define AIBS_SENS_TYPE_VOLT 2 59308368Savg#define AIBS_SENS_TYPE_TEMP 3 60308368Savg#define AIBS_SENS_TYPE_FAN 4 61308368Savg 62308368Savg#define AIBS_SENS_TYPE_VOLT_NAME "volt" 63308368Savg#define AIBS_SENS_TYPE_VOLT_TEMP "temp" 64308368Savg#define AIBS_SENS_TYPE_VOLT_FAN "fan" 65308368Savg 66209523Srpaulostruct aibs_sensor { 67209523Srpaulo ACPI_INTEGER v; 68209523Srpaulo ACPI_INTEGER i; 69209523Srpaulo ACPI_INTEGER l; 70209523Srpaulo ACPI_INTEGER h; 71308368Savg int t; 72209523Srpaulo}; 73209523Srpaulo 74209523Srpaulostruct aibs_softc { 75299052Sadrian device_t sc_dev; 76209523Srpaulo ACPI_HANDLE sc_ah; 77209523Srpaulo 78209523Srpaulo struct aibs_sensor *sc_asens_volt; 79209523Srpaulo struct aibs_sensor *sc_asens_temp; 80209523Srpaulo struct aibs_sensor *sc_asens_fan; 81308368Savg struct aibs_sensor *sc_asens_all; 82308368Savg 83308368Savg struct sysctl_oid *sc_volt_sysctl; 84308368Savg struct sysctl_oid *sc_temp_sysctl; 85308368Savg struct sysctl_oid *sc_fan_sysctl; 86308368Savg 87308368Savg bool sc_ggrp_method; 88209523Srpaulo}; 89209523Srpaulo 90209523Srpaulostatic int aibs_probe(device_t); 91209523Srpaulostatic int aibs_attach(device_t); 92209523Srpaulostatic int aibs_detach(device_t); 93209523Srpaulostatic int aibs_sysctl(SYSCTL_HANDLER_ARGS); 94308368Savgstatic int aibs_sysctl_ggrp(SYSCTL_HANDLER_ARGS); 95209523Srpaulo 96308368Savgstatic int aibs_attach_ggrp(struct aibs_softc *); 97308368Savgstatic int aibs_attach_sif(struct aibs_softc *, int); 98209523Srpaulo 99209523Srpaulostatic device_method_t aibs_methods[] = { 100209523Srpaulo DEVMETHOD(device_probe, aibs_probe), 101209523Srpaulo DEVMETHOD(device_attach, aibs_attach), 102209523Srpaulo DEVMETHOD(device_detach, aibs_detach), 103209523Srpaulo { NULL, NULL } 104209523Srpaulo}; 105209523Srpaulo 106209523Srpaulostatic driver_t aibs_driver = { 107209523Srpaulo "aibs", 108209523Srpaulo aibs_methods, 109209523Srpaulo sizeof(struct aibs_softc) 110209523Srpaulo}; 111209523Srpaulo 112209523Srpaulostatic devclass_t aibs_devclass; 113209523Srpaulo 114209523SrpauloDRIVER_MODULE(aibs, acpi, aibs_driver, aibs_devclass, NULL, NULL); 115232256SkevloMODULE_DEPEND(aibs, acpi, 1, 1, 1); 116209523Srpaulo 117209523Srpaulostatic char* aibs_hids[] = { 118209523Srpaulo "ATK0110", 119209523Srpaulo NULL 120209523Srpaulo}; 121209523Srpaulo 122209523Srpaulostatic int 123209523Srpauloaibs_probe(device_t dev) 124209523Srpaulo{ 125209523Srpaulo if (acpi_disabled("aibs") || 126209523Srpaulo ACPI_ID_PROBE(device_get_parent(dev), dev, aibs_hids) == NULL) 127308368Savg return (ENXIO); 128209523Srpaulo 129209523Srpaulo device_set_desc(dev, "ASUSTeK AI Booster (ACPI ASOC ATK0110)"); 130308368Savg return (0); 131209523Srpaulo} 132209523Srpaulo 133209523Srpaulostatic int 134209523Srpauloaibs_attach(device_t dev) 135209523Srpaulo{ 136209523Srpaulo struct aibs_softc *sc = device_get_softc(dev); 137308368Savg int err; 138209523Srpaulo 139209523Srpaulo sc->sc_dev = dev; 140209523Srpaulo sc->sc_ah = acpi_get_handle(dev); 141209523Srpaulo 142308368Savg sc->sc_ggrp_method = false; 143308368Savg err = aibs_attach_sif(sc, AIBS_SENS_TYPE_VOLT); 144308368Savg if (err == 0) 145308368Savg err = aibs_attach_sif(sc, AIBS_SENS_TYPE_TEMP); 146308368Savg if (err == 0) 147308368Savg err = aibs_attach_sif(sc, AIBS_SENS_TYPE_FAN); 148209523Srpaulo 149308368Savg if (err == 0) 150308368Savg return (0); 151308368Savg 152308368Savg /* Clean up whatever was allocated earlier. */ 153308368Savg if (sc->sc_volt_sysctl != NULL) 154308368Savg sysctl_remove_oid(sc->sc_volt_sysctl, true, true); 155308368Savg if (sc->sc_temp_sysctl != NULL) 156308368Savg sysctl_remove_oid(sc->sc_temp_sysctl, true, true); 157308368Savg if (sc->sc_fan_sysctl != NULL) 158308368Savg sysctl_remove_oid(sc->sc_fan_sysctl, true, true); 159308368Savg aibs_detach(dev); 160308368Savg 161308368Savg sc->sc_ggrp_method = true; 162308368Savg err = aibs_attach_ggrp(sc); 163308368Savg return (err); 164209523Srpaulo} 165209523Srpaulo 166308368Savgstatic int 167308368Savgaibs_add_sensor(struct aibs_softc *sc, ACPI_OBJECT *o, 168308368Savg struct aibs_sensor* sensor, const char ** descr) 169308368Savg{ 170308368Savg int off; 171308368Savg 172308368Savg /* 173308368Savg * Packages for the old and new methods are quite 174308368Savg * similar except that the new package has two 175308368Savg * new (unknown / unused) fields after the name field. 176308368Savg */ 177308368Savg if (sc->sc_ggrp_method) 178308368Savg off = 4; 179308368Savg else 180308368Savg off = 2; 181308368Savg 182308368Savg if (o->Type != ACPI_TYPE_PACKAGE) { 183308368Savg device_printf(sc->sc_dev, 184308368Savg "sensor object is not a package: %i type\n", 185308368Savg o->Type); 186308368Savg return (ENXIO); 187308368Savg } 188308368Savg if (o[0].Package.Count != (off + 3) || 189308368Savg o->Package.Elements[0].Type != ACPI_TYPE_INTEGER || 190308368Savg o->Package.Elements[1].Type != ACPI_TYPE_STRING || 191308368Savg o->Package.Elements[off].Type != ACPI_TYPE_INTEGER || 192308368Savg o->Package.Elements[off + 1].Type != ACPI_TYPE_INTEGER || 193308368Savg o->Package.Elements[off + 2].Type != ACPI_TYPE_INTEGER) { 194308368Savg device_printf(sc->sc_dev, "unexpected package content\n"); 195308368Savg return (ENXIO); 196308368Savg } 197308368Savg 198308368Savg sensor->i = o->Package.Elements[0].Integer.Value; 199308368Savg *descr = o->Package.Elements[1].String.Pointer; 200308368Savg sensor->l = o->Package.Elements[off].Integer.Value; 201308368Savg sensor->h = o->Package.Elements[off + 1].Integer.Value; 202308368Savg /* For the new method the second value is a range size. */ 203308368Savg if (sc->sc_ggrp_method) 204308368Savg sensor->h += sensor->l; 205308368Savg sensor->t = AIBS_SENS_TYPE(sensor->i); 206308368Savg 207308368Savg switch (sensor->t) { 208308368Savg case AIBS_SENS_TYPE_VOLT: 209308368Savg case AIBS_SENS_TYPE_TEMP: 210308368Savg case AIBS_SENS_TYPE_FAN: 211308368Savg return (0); 212308368Savg default: 213308368Savg device_printf(sc->sc_dev, "unknown sensor type 0x%x", 214308368Savg sensor->t); 215308368Savg return (ENXIO); 216308368Savg } 217308368Savg} 218308368Savg 219209523Srpaulostatic void 220308368Savgaibs_sensor_added(struct aibs_softc *sc, struct sysctl_oid *so, 221308368Savg const char *type_name, int idx, struct aibs_sensor *sensor, 222308368Savg const char *descr) 223209523Srpaulo{ 224308368Savg char sysctl_name[8]; 225308368Savg 226308368Savg snprintf(sysctl_name, sizeof(sysctl_name), "%i", idx); 227308368Savg#ifdef AIBS_VERBOSE 228308368Savg device_printf(sc->sc_dev, "%c%i: 0x%08jx %20s %5jd / %5jd\n", 229308368Savg type_name[0], idx, 230308368Savg (uintmax_t)sensor->i, descr, (intmax_t)sensor->l, 231308368Savg (intmax_t)sensor->h); 232308368Savg#endif 233308368Savg SYSCTL_ADD_PROC(device_get_sysctl_ctx(sc->sc_dev), 234308368Savg SYSCTL_CHILDREN(so), idx, sysctl_name, 235308368Savg CTLTYPE_INT | CTLFLAG_RD, sc, (uintptr_t)sensor, 236308368Savg sc->sc_ggrp_method ? aibs_sysctl_ggrp : aibs_sysctl, 237308368Savg sensor->t == AIBS_SENS_TYPE_TEMP ? "IK" : "I", descr); 238308368Savg} 239308368Savg 240308368Savgstatic int 241308368Savgaibs_attach_ggrp(struct aibs_softc *sc) 242308368Savg{ 243209523Srpaulo ACPI_STATUS s; 244308368Savg ACPI_BUFFER buf; 245308368Savg ACPI_HANDLE h; 246308368Savg ACPI_OBJECT id; 247308368Savg ACPI_OBJECT *bp; 248308368Savg ACPI_OBJECT_LIST arg; 249308368Savg int i; 250308368Savg int t, v, f; 251308368Savg int err; 252308368Savg int *s_idx; 253308368Savg const char *name; 254308368Savg const char *descr; 255308368Savg struct aibs_sensor *sensor; 256308368Savg struct sysctl_oid **so; 257308368Savg 258308368Savg /* First see if GITM is available. */ 259308368Savg s = AcpiGetHandle(sc->sc_ah, "GITM", &h); 260308368Savg if (ACPI_FAILURE(s)) { 261308368Savg if (bootverbose) 262308368Savg device_printf(sc->sc_dev, "GITM not found\n"); 263308368Savg return (ENXIO); 264308368Savg } 265308368Savg 266308368Savg /* 267308368Savg * Now call GGRP with the appropriate argument to list sensors. 268308368Savg * The method lists different groups of entities depending on 269308368Savg * the argument. 270308368Savg */ 271308368Savg id.Integer.Value = AIBS_GROUP_SENSORS; 272308368Savg id.Type = ACPI_TYPE_INTEGER; 273308368Savg arg.Count = 1; 274308368Savg arg.Pointer = &id; 275308368Savg buf.Length = ACPI_ALLOCATE_BUFFER; 276308368Savg buf.Pointer = NULL; 277308368Savg s = AcpiEvaluateObjectTyped(sc->sc_ah, "GGRP", &arg, &buf, 278308368Savg ACPI_TYPE_PACKAGE); 279308368Savg if (ACPI_FAILURE(s)) { 280308368Savg device_printf(sc->sc_dev, "GGRP not found\n"); 281308368Savg return (ENXIO); 282308368Savg } 283308368Savg 284308368Savg bp = buf.Pointer; 285308368Savg sc->sc_asens_all = malloc(sizeof(*sc->sc_asens_all) * bp->Package.Count, 286308368Savg M_DEVBUF, M_WAITOK | M_ZERO); 287308368Savg v = t = f = 0; 288308368Savg for (i = 0; i < bp->Package.Count; i++) { 289308368Savg sensor = &sc->sc_asens_all[i]; 290308368Savg err = aibs_add_sensor(sc, &bp->Package.Elements[i], sensor, 291308368Savg &descr); 292308368Savg if (err != 0) 293308368Savg continue; 294308368Savg 295308368Savg switch (sensor->t) { 296308368Savg case AIBS_SENS_TYPE_VOLT: 297308368Savg name = "volt"; 298308368Savg so = &sc->sc_volt_sysctl; 299308368Savg s_idx = &v; 300308368Savg break; 301308368Savg case AIBS_SENS_TYPE_TEMP: 302308368Savg name = "temp"; 303308368Savg so = &sc->sc_temp_sysctl; 304308368Savg s_idx = &t; 305308368Savg break; 306308368Savg case AIBS_SENS_TYPE_FAN: 307308368Savg name = "fan"; 308308368Savg so = &sc->sc_fan_sysctl; 309308368Savg s_idx = &f; 310308368Savg break; 311308368Savg default: 312308368Savg panic("add_sensor succeeded for unknown sensor type %d", 313308368Savg sensor->t); 314308368Savg } 315308368Savg 316308368Savg if (*so == NULL) { 317308368Savg /* sysctl subtree for sensors of this type */ 318308368Savg *so = SYSCTL_ADD_NODE(device_get_sysctl_ctx(sc->sc_dev), 319308368Savg SYSCTL_CHILDREN(device_get_sysctl_tree(sc->sc_dev)), 320308368Savg sensor->t, name, CTLFLAG_RD, NULL, NULL); 321308368Savg } 322308368Savg aibs_sensor_added(sc, *so, name, *s_idx, sensor, descr); 323308368Savg *s_idx += 1; 324308368Savg } 325308368Savg 326308368Savg AcpiOsFree(buf.Pointer); 327308368Savg return (0); 328308368Savg} 329308368Savg 330308368Savgstatic int 331308368Savgaibs_attach_sif(struct aibs_softc *sc, int st) 332308368Savg{ 333308368Savg char name[] = "?SIF"; 334308368Savg ACPI_STATUS s; 335209523Srpaulo ACPI_BUFFER b; 336209523Srpaulo ACPI_OBJECT *bp, *o; 337209523Srpaulo const char *node; 338209523Srpaulo struct aibs_sensor *as; 339308368Savg struct sysctl_oid **so; 340308368Savg int i, n; 341308368Savg int err; 342209523Srpaulo 343209523Srpaulo switch (st) { 344308368Savg case AIBS_SENS_TYPE_VOLT: 345209523Srpaulo node = "volt"; 346209523Srpaulo name[0] = 'V'; 347308368Savg so = &sc->sc_volt_sysctl; 348209523Srpaulo break; 349308368Savg case AIBS_SENS_TYPE_TEMP: 350209523Srpaulo node = "temp"; 351209523Srpaulo name[0] = 'T'; 352308368Savg so = &sc->sc_temp_sysctl; 353209523Srpaulo break; 354308368Savg case AIBS_SENS_TYPE_FAN: 355209523Srpaulo node = "fan"; 356209523Srpaulo name[0] = 'F'; 357308368Savg so = &sc->sc_fan_sysctl; 358209523Srpaulo break; 359209523Srpaulo default: 360308368Savg panic("Unsupported sensor type %d", st); 361209523Srpaulo } 362209523Srpaulo 363209523Srpaulo b.Length = ACPI_ALLOCATE_BUFFER; 364209523Srpaulo s = AcpiEvaluateObjectTyped(sc->sc_ah, name, NULL, &b, 365209523Srpaulo ACPI_TYPE_PACKAGE); 366209523Srpaulo if (ACPI_FAILURE(s)) { 367209523Srpaulo device_printf(sc->sc_dev, "%s not found\n", name); 368308368Savg return (ENXIO); 369209523Srpaulo } 370209523Srpaulo 371209523Srpaulo bp = b.Pointer; 372209523Srpaulo o = bp->Package.Elements; 373209523Srpaulo if (o[0].Type != ACPI_TYPE_INTEGER) { 374209523Srpaulo device_printf(sc->sc_dev, "%s[0]: invalid type\n", name); 375209523Srpaulo AcpiOsFree(b.Pointer); 376308368Savg return (ENXIO); 377209523Srpaulo } 378209523Srpaulo 379209523Srpaulo n = o[0].Integer.Value; 380209523Srpaulo if (bp->Package.Count - 1 < n) { 381209523Srpaulo device_printf(sc->sc_dev, "%s: invalid package\n", name); 382209523Srpaulo AcpiOsFree(b.Pointer); 383308368Savg return (ENXIO); 384209523Srpaulo } else if (bp->Package.Count - 1 > n) { 385209523Srpaulo int on = n; 386209523Srpaulo 387209523Srpaulo#ifdef AIBS_MORE_SENSORS 388209523Srpaulo n = bp->Package.Count - 1; 389209523Srpaulo#endif 390209523Srpaulo device_printf(sc->sc_dev, "%s: malformed package: %i/%i" 391209523Srpaulo ", assume %i\n", name, on, bp->Package.Count - 1, n); 392209523Srpaulo } 393209523Srpaulo if (n < 1) { 394209523Srpaulo device_printf(sc->sc_dev, "%s: no members in the package\n", 395209523Srpaulo name); 396209523Srpaulo AcpiOsFree(b.Pointer); 397308368Savg return (ENXIO); 398209523Srpaulo } 399209523Srpaulo 400308368Savg as = malloc(sizeof(*as) * n, M_DEVBUF, M_WAITOK | M_ZERO); 401209523Srpaulo switch (st) { 402308368Savg case AIBS_SENS_TYPE_VOLT: 403209523Srpaulo sc->sc_asens_volt = as; 404209523Srpaulo break; 405308368Savg case AIBS_SENS_TYPE_TEMP: 406209523Srpaulo sc->sc_asens_temp = as; 407209523Srpaulo break; 408308368Savg case AIBS_SENS_TYPE_FAN: 409209523Srpaulo sc->sc_asens_fan = as; 410209523Srpaulo break; 411209523Srpaulo } 412209523Srpaulo 413209523Srpaulo /* sysctl subtree for sensors of this type */ 414308368Savg *so = SYSCTL_ADD_NODE(device_get_sysctl_ctx(sc->sc_dev), 415209523Srpaulo SYSCTL_CHILDREN(device_get_sysctl_tree(sc->sc_dev)), st, 416209523Srpaulo node, CTLFLAG_RD, NULL, NULL); 417209523Srpaulo 418209523Srpaulo for (i = 0, o++; i < n; i++, o++) { 419308368Savg const char *descr; 420209523Srpaulo 421308368Savg err = aibs_add_sensor(sc, o, &as[i], &descr); 422308368Savg if (err == 0) 423308368Savg aibs_sensor_added(sc, *so, node, i, &as[i], descr); 424209523Srpaulo } 425209523Srpaulo 426209523Srpaulo AcpiOsFree(b.Pointer); 427308368Savg return (0); 428209523Srpaulo} 429209523Srpaulo 430209523Srpaulostatic int 431209523Srpauloaibs_detach(device_t dev) 432209523Srpaulo{ 433209523Srpaulo struct aibs_softc *sc = device_get_softc(dev); 434209523Srpaulo 435209523Srpaulo if (sc->sc_asens_volt != NULL) 436209523Srpaulo free(sc->sc_asens_volt, M_DEVBUF); 437209523Srpaulo if (sc->sc_asens_temp != NULL) 438209523Srpaulo free(sc->sc_asens_temp, M_DEVBUF); 439209523Srpaulo if (sc->sc_asens_fan != NULL) 440209523Srpaulo free(sc->sc_asens_fan, M_DEVBUF); 441308368Savg if (sc->sc_asens_all != NULL) 442308368Savg free(sc->sc_asens_all, M_DEVBUF); 443308368Savg return (0); 444209523Srpaulo} 445209523Srpaulo 446209523Srpaulo#ifdef AIBS_VERBOSE 447209523Srpaulo#define ddevice_printf(x...) device_printf(x) 448209523Srpaulo#else 449209523Srpaulo#define ddevice_printf(x...) 450209523Srpaulo#endif 451209523Srpaulo 452209523Srpaulostatic int 453209523Srpauloaibs_sysctl(SYSCTL_HANDLER_ARGS) 454209523Srpaulo{ 455209523Srpaulo struct aibs_softc *sc = arg1; 456335471Sdim struct aibs_sensor *sensor = (void *)(intptr_t)arg2; 457209523Srpaulo int i = oidp->oid_number; 458209523Srpaulo ACPI_STATUS rs; 459209523Srpaulo ACPI_OBJECT p, *bp; 460209523Srpaulo ACPI_OBJECT_LIST mp; 461209523Srpaulo ACPI_BUFFER b; 462209523Srpaulo char *name; 463209523Srpaulo ACPI_INTEGER v, l, h; 464209523Srpaulo int so[3]; 465209523Srpaulo 466308368Savg switch (sensor->t) { 467308368Savg case AIBS_SENS_TYPE_VOLT: 468209523Srpaulo name = "RVLT"; 469209523Srpaulo break; 470308368Savg case AIBS_SENS_TYPE_TEMP: 471209523Srpaulo name = "RTMP"; 472209523Srpaulo break; 473308368Savg case AIBS_SENS_TYPE_FAN: 474209523Srpaulo name = "RFAN"; 475209523Srpaulo break; 476209523Srpaulo default: 477308368Savg return (ENOENT); 478209523Srpaulo } 479308368Savg l = sensor->l; 480308368Savg h = sensor->h; 481209523Srpaulo p.Type = ACPI_TYPE_INTEGER; 482308368Savg p.Integer.Value = sensor->i; 483209523Srpaulo mp.Count = 1; 484209523Srpaulo mp.Pointer = &p; 485209523Srpaulo b.Length = ACPI_ALLOCATE_BUFFER; 486209523Srpaulo ACPI_SERIAL_BEGIN(aibs); 487209523Srpaulo rs = AcpiEvaluateObjectTyped(sc->sc_ah, name, &mp, &b, 488209523Srpaulo ACPI_TYPE_INTEGER); 489209523Srpaulo if (ACPI_FAILURE(rs)) { 490209523Srpaulo ddevice_printf(sc->sc_dev, 491209523Srpaulo "%s: %i: evaluation failed\n", 492209523Srpaulo name, i); 493209523Srpaulo ACPI_SERIAL_END(aibs); 494308368Savg return (EIO); 495209523Srpaulo } 496209523Srpaulo bp = b.Pointer; 497209523Srpaulo v = bp->Integer.Value; 498209523Srpaulo AcpiOsFree(b.Pointer); 499209523Srpaulo ACPI_SERIAL_END(aibs); 500209523Srpaulo 501308368Savg switch (sensor->t) { 502308368Savg case AIBS_SENS_TYPE_VOLT: 503209523Srpaulo break; 504308368Savg case AIBS_SENS_TYPE_TEMP: 505300421Sloos v += 2731; 506300421Sloos l += 2731; 507300421Sloos h += 2731; 508209523Srpaulo break; 509308368Savg case AIBS_SENS_TYPE_FAN: 510209523Srpaulo break; 511209523Srpaulo } 512209523Srpaulo so[0] = v; 513209523Srpaulo so[1] = l; 514209523Srpaulo so[2] = h; 515308368Savg return (sysctl_handle_opaque(oidp, &so, sizeof(so), req)); 516209523Srpaulo} 517308368Savg 518308368Savgstatic int 519308368Savgaibs_sysctl_ggrp(SYSCTL_HANDLER_ARGS) 520308368Savg{ 521308368Savg struct aibs_softc *sc = arg1; 522335471Sdim struct aibs_sensor *sensor = (void *)(intptr_t)arg2; 523308368Savg ACPI_STATUS rs; 524308368Savg ACPI_OBJECT p, *bp; 525308368Savg ACPI_OBJECT_LIST arg; 526308368Savg ACPI_BUFFER buf; 527308368Savg ACPI_INTEGER v, l, h; 528308368Savg int so[3]; 529308368Savg uint32_t *ret; 530308368Savg uint32_t cmd[3]; 531308368Savg 532308368Savg cmd[0] = sensor->i; 533308368Savg cmd[1] = 0; 534308368Savg cmd[2] = 0; 535308368Savg p.Type = ACPI_TYPE_BUFFER; 536308368Savg p.Buffer.Pointer = (void *)cmd; 537308368Savg p.Buffer.Length = sizeof(cmd); 538308368Savg arg.Count = 1; 539308368Savg arg.Pointer = &p; 540308368Savg buf.Pointer = NULL; 541308368Savg buf.Length = ACPI_ALLOCATE_BUFFER; 542308368Savg ACPI_SERIAL_BEGIN(aibs); 543308368Savg rs = AcpiEvaluateObjectTyped(sc->sc_ah, "GITM", &arg, &buf, 544308368Savg ACPI_TYPE_BUFFER); 545308368Savg ACPI_SERIAL_END(aibs); 546308368Savg if (ACPI_FAILURE(rs)) { 547308368Savg device_printf(sc->sc_dev, "GITM evaluation failed\n"); 548308368Savg return (EIO); 549308368Savg } 550308368Savg bp = buf.Pointer; 551308368Savg if (bp->Buffer.Length < 8) { 552308368Savg device_printf(sc->sc_dev, "GITM returned short buffer\n"); 553308368Savg return (EIO); 554308368Savg } 555308368Savg ret = (uint32_t *)bp->Buffer.Pointer; 556308368Savg if (ret[0] == 0) { 557308368Savg device_printf(sc->sc_dev, "GITM returned error status\n"); 558308368Savg return (EINVAL); 559308368Savg } 560308368Savg v = ret[1]; 561308368Savg AcpiOsFree(buf.Pointer); 562308368Savg 563308368Savg l = sensor->l; 564308368Savg h = sensor->h; 565308368Savg 566308368Savg switch (sensor->t) { 567308368Savg case AIBS_SENS_TYPE_VOLT: 568308368Savg break; 569308368Savg case AIBS_SENS_TYPE_TEMP: 570308368Savg v += 2731; 571308368Savg l += 2731; 572308368Savg h += 2731; 573308368Savg break; 574308368Savg case AIBS_SENS_TYPE_FAN: 575308368Savg break; 576308368Savg } 577308368Savg so[0] = v; 578308368Savg so[1] = l; 579308368Savg so[2] = h; 580308368Savg return (sysctl_handle_opaque(oidp, &so, sizeof(so), req)); 581308368Savg} 582