Annotation of sys/dev/acpi/acpitz.c, Revision 1.1
1.1 ! nbrk 1: /* $OpenBSD: acpitz.c,v 1.17 2007/03/26 12:30:48 marco Exp $ */
! 2: /*
! 3: * Copyright (c) 2006 Can Erkin Acar <canacar@openbsd.org>
! 4: * Copyright (c) 2005 Marco Peereboom <marco@openbsd.org>
! 5: *
! 6: * Permission to use, copy, modify, and distribute this software for any
! 7: * purpose with or without fee is hereby granted, provided that the above
! 8: * copyright notice and this permission notice appear in all copies.
! 9: *
! 10: * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
! 11: * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
! 12: * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
! 13: * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
! 14: * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
! 15: * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
! 16: * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
! 17: */
! 18:
! 19: #include <sys/param.h>
! 20: #include <sys/proc.h>
! 21: #include <sys/signalvar.h>
! 22: #include <sys/systm.h>
! 23: #include <sys/device.h>
! 24: #include <sys/malloc.h>
! 25:
! 26: #include <machine/bus.h>
! 27:
! 28: #include <dev/acpi/acpireg.h>
! 29: #include <dev/acpi/acpivar.h>
! 30: #include <dev/acpi/acpidev.h>
! 31: #include <dev/acpi/amltypes.h>
! 32: #include <dev/acpi/dsdt.h>
! 33:
! 34: #include <sys/sensors.h>
! 35:
! 36: #define ACPITZ_MAX_AC 10
! 37:
! 38: struct acpitz_softc {
! 39: struct device sc_dev;
! 40:
! 41: struct acpi_softc *sc_acpi;
! 42: struct aml_node *sc_devnode;
! 43:
! 44: int sc_tmp;
! 45: int sc_crt;
! 46: int sc_hot;
! 47: int sc_ac[ACPITZ_MAX_AC];
! 48: int sc_ac_stat[ACPITZ_MAX_AC];
! 49: int sc_pse;
! 50: int sc_psv;
! 51: int sc_tc1;
! 52: int sc_tc2;
! 53: int sc_lasttmp;
! 54: struct ksensor sc_sens;
! 55: struct ksensordev sc_sensdev;
! 56: };
! 57:
! 58: int acpitz_match(struct device *, void *, void *);
! 59: void acpitz_attach(struct device *, struct device *, void *);
! 60:
! 61: struct cfattach acpitz_ca = {
! 62: sizeof(struct acpitz_softc), acpitz_match, acpitz_attach
! 63: };
! 64:
! 65: struct cfdriver acpitz_cd = {
! 66: NULL, "acpitz", DV_DULL
! 67: };
! 68:
! 69: void acpitz_monitor(struct acpitz_softc *);
! 70: void acpitz_refresh(void *);
! 71: int acpitz_notify(struct aml_node *, int, void *);
! 72: int acpitz_getreading(struct acpitz_softc *, char *);
! 73: int acpitz_setfan(struct acpitz_softc *, int, char *);
! 74: int acpitz_setcpu(struct acpitz_softc *, int);
! 75:
! 76: int
! 77: acpitz_match(struct device *parent, void *match, void *aux)
! 78: {
! 79: struct acpi_attach_args *aa = aux;
! 80: struct cfdata *cf = match;
! 81:
! 82: /* sanity */
! 83: if (aa->aaa_name == NULL ||
! 84: strcmp(aa->aaa_name, cf->cf_driver->cd_name) != 0 ||
! 85: aa->aaa_table != NULL)
! 86: return (0);
! 87:
! 88: if (aa->aaa_node->value->type != AML_OBJTYPE_THERMZONE)
! 89: return (0);
! 90:
! 91: return (1);
! 92: }
! 93:
! 94: void
! 95: acpitz_attach(struct device *parent, struct device *self, void *aux)
! 96: {
! 97: struct acpitz_softc *sc = (struct acpitz_softc *)self;
! 98: struct acpi_attach_args *aa = aux;
! 99: int i;
! 100: char name[8];
! 101:
! 102: sc->sc_acpi = (struct acpi_softc *)parent;
! 103: sc->sc_devnode = aa->aaa_node->child;
! 104:
! 105: sc->sc_lasttmp = -1;
! 106: if ((sc->sc_tmp = acpitz_getreading(sc, "_TMP")) == -1) {
! 107: printf(", failed to read _TMP\n");
! 108: return;
! 109: }
! 110:
! 111: if ((sc->sc_crt = acpitz_getreading(sc, "_CRT")) == -1) {
! 112: printf(", no critical temperature defined!\n");
! 113: sc->sc_crt = 0;
! 114: } else
! 115: printf(", critical temperature: %d degC\n",
! 116: (sc->sc_crt - 2732) / 10);
! 117:
! 118: for (i = 0; i < ACPITZ_MAX_AC; i++) {
! 119: snprintf(name, sizeof name, "_AC%d", i);
! 120: sc->sc_ac[i] = acpitz_getreading(sc, name);
! 121: sc->sc_ac_stat[0] = -1;
! 122: }
! 123:
! 124: sc->sc_hot = acpitz_getreading(sc, "_HOT");
! 125: sc->sc_tc1 = acpitz_getreading(sc, "_TC1");
! 126: sc->sc_tc2 = acpitz_getreading(sc, "_TC2");
! 127: sc->sc_psv = acpitz_getreading(sc, "_PSV");
! 128:
! 129: strlcpy(sc->sc_sensdev.xname, DEVNAME(sc),
! 130: sizeof(sc->sc_sensdev.xname));
! 131: strlcpy(sc->sc_sens.desc, "zone temperature",
! 132: sizeof(sc->sc_sens.desc));
! 133: sc->sc_sens.type = SENSOR_TEMP;
! 134: sensor_attach(&sc->sc_sensdev, &sc->sc_sens);
! 135: sensordev_install(&sc->sc_sensdev);
! 136: sc->sc_sens.value = 0;
! 137:
! 138: aml_register_notify(sc->sc_devnode->parent, NULL,
! 139: acpitz_notify, sc, ACPIDEV_POLL);
! 140: }
! 141:
! 142: int
! 143: acpitz_setcpu(struct acpitz_softc *sc, int trend)
! 144: {
! 145: struct aml_value res0, *ref;
! 146: int x;
! 147:
! 148: if (aml_evalname(sc->sc_acpi, sc->sc_devnode, "_PSL", 0, NULL, &res0)) {
! 149: printf("%s: _PSL failed\n", DEVNAME(sc));
! 150: goto out;
! 151: }
! 152: if (res0.type != AML_OBJTYPE_PACKAGE) {
! 153: printf("%s: not a package\n", DEVNAME(sc));
! 154: goto out;
! 155: }
! 156: for (x = 0; x < res0.length; x++) {
! 157: if (res0.v_package[x]->type != AML_OBJTYPE_OBJREF) {
! 158: printf("%s: _PSL[%d] not a object ref\n", DEVNAME(sc), x);
! 159: continue;
! 160: }
! 161: ref = res0.v_package[x]->v_objref.ref;
! 162: if (ref->type != AML_OBJTYPE_PROCESSOR)
! 163: printf("%s: _PSL[%d] not a CPU\n", DEVNAME(sc), x);
! 164: }
! 165: out:
! 166: aml_freevalue(&res0);
! 167: return (0);
! 168: }
! 169:
! 170: int
! 171: acpitz_setfan(struct acpitz_softc *sc, int i, char *method)
! 172: {
! 173: struct aml_value res0, res1, res2, *ref;
! 174: char name[8];
! 175: int rv = 1, x, y;
! 176:
! 177: dnprintf(20, "%s: acpitz_setfan(%d, %s)\n", DEVNAME(sc), i, method);
! 178:
! 179: snprintf(name, sizeof name, "_AL%d", i);
! 180: if (aml_evalname(sc->sc_acpi, sc->sc_devnode, name, 0, NULL, &res0)) {
! 181: dnprintf(20, "%s: %s failed\n", DEVNAME(sc), name);
! 182: goto out;
! 183: }
! 184:
! 185: if (res0.type != AML_OBJTYPE_PACKAGE) {
! 186: printf("%s: %s not a package\n", DEVNAME(sc), name);
! 187: goto out;
! 188: }
! 189:
! 190: for (x = 0; x < res0.length; x++) {
! 191: if (res0.v_package[x]->type != AML_OBJTYPE_OBJREF) {
! 192: printf("%s: %s[%d] not a object ref\n", DEVNAME(sc),
! 193: name, x);
! 194: continue;
! 195: }
! 196: ref = res0.v_package[x]->v_objref.ref;
! 197: if (aml_evalname(sc->sc_acpi, ref->node, "_PR0",0 , NULL,
! 198: &res1)) {
! 199: printf("%s: %s[%d] _PR0 failed\n", DEVNAME(sc),
! 200: name, x);
! 201: aml_freevalue(&res1);
! 202: continue;
! 203: }
! 204: if (res1.type != AML_OBJTYPE_PACKAGE) {
! 205: printf("%s: %s[%d] _PR0 not a package\n", DEVNAME(sc),
! 206: name, x);
! 207: aml_freevalue(&res1);
! 208: continue;
! 209: }
! 210: for (y = 0; y < res1.length; y++) {
! 211: if (res1.v_package[y]->type != AML_OBJTYPE_OBJREF) {
! 212: printf("%s: %s[%d.%d] _PR0 not a package\n",
! 213: DEVNAME(sc), name, x, y);
! 214: continue;
! 215: }
! 216: ref = res1.v_package[y]->v_objref.ref;
! 217: if (aml_evalname(sc->sc_acpi, ref->node, method, 0,
! 218: NULL, NULL))
! 219: printf("%s: %s[%d.%d] %s fails\n",
! 220: DEVNAME(sc), name, x, y, method);
! 221:
! 222: /* save off status of fan */
! 223: if (aml_evalname(sc->sc_acpi, ref->node, "_STA", 0,
! 224: NULL, &res2))
! 225: printf("%s: %s[%d.%d] _STA fails\n",
! 226: DEVNAME(sc), name, x, y);
! 227: else {
! 228: sc->sc_ac_stat[i] = aml_val2int(&res2);
! 229: aml_freevalue(&res2);
! 230: }
! 231: }
! 232: aml_freevalue(&res1);
! 233: }
! 234: rv = 0;
! 235: out:
! 236: aml_freevalue(&res0);
! 237: return (rv);
! 238: }
! 239:
! 240: void
! 241: acpitz_refresh(void *arg)
! 242: {
! 243: struct acpitz_softc *sc = arg;
! 244: int i, trend;
! 245: extern int acpi_s5;
! 246:
! 247: dnprintf(30, "%s: %s: refresh\n", DEVNAME(sc),
! 248: sc->sc_devnode->parent->name);
! 249:
! 250: if (-1 == (sc->sc_tmp = acpitz_getreading(sc, "_TMP"))) {
! 251: dnprintf(30, "%s: %s: failed to read temp!\n", DEVNAME(sc),
! 252: sc->sc_devnode->parent->name);
! 253: sc->sc_tmp = 0; /* XXX */
! 254: }
! 255:
! 256: if (sc->sc_crt != -1 && sc->sc_crt <= sc->sc_tmp) {
! 257: /* Do critical shutdown */
! 258: printf("%s: Critical temperature, shutting down!\n",
! 259: DEVNAME(sc));
! 260: acpi_s5 = 1;
! 261: psignal(initproc, SIGUSR1);
! 262: }
! 263: if (sc->sc_hot != -1 && sc->sc_hot <= sc->sc_tmp)
! 264: printf("%s: _HOT temperature\n", DEVNAME(sc));
! 265:
! 266: if (sc->sc_lasttmp != -1 && sc->sc_tc1 != -1 && sc->sc_tc2 != -1 &&
! 267: sc->sc_psv != -1) {
! 268: if (sc->sc_psv <= sc->sc_tmp) {
! 269: sc->sc_pse = 1;
! 270: trend = sc->sc_tc1 * (sc->sc_tmp - sc->sc_lasttmp) +
! 271: sc->sc_tc2 * (sc->sc_tmp - sc->sc_psv);
! 272: /* printf("_TZ trend = %d\n", trend); */
! 273: } else if (sc->sc_pse)
! 274: sc->sc_pse = 0;
! 275: }
! 276: sc->sc_lasttmp = sc->sc_tmp;
! 277:
! 278: for (i = 0; i < ACPITZ_MAX_AC; i++) {
! 279: if (sc->sc_ac[i] != -1 && sc->sc_ac[i] <= sc->sc_tmp) {
! 280: /* turn on fan i */
! 281: if (sc->sc_ac_stat[i] <= 0)
! 282: acpitz_setfan(sc, i, "_ON_");
! 283: } else if (sc->sc_ac[i] != -1) {
! 284: /* turn off fan i */
! 285: if (sc->sc_ac_stat[i] > 0)
! 286: acpitz_setfan(sc, i, "_OFF");
! 287: }
! 288: }
! 289: sc->sc_sens.value = sc->sc_tmp * 100000;
! 290: }
! 291:
! 292: int
! 293: acpitz_getreading(struct acpitz_softc *sc, char *name)
! 294: {
! 295: struct aml_value res;
! 296: int rv = -1;
! 297:
! 298: if (aml_evalname(sc->sc_acpi, sc->sc_devnode, name, 0, NULL, &res)) {
! 299: dnprintf(10, "%s: no %s\n", DEVNAME(sc), name);
! 300: goto out;
! 301: }
! 302: rv = aml_val2int(&res);
! 303: out:
! 304: aml_freevalue(&res);
! 305: return (rv);
! 306: }
! 307:
! 308: int
! 309: acpitz_notify(struct aml_node *node, int notify_type, void *arg)
! 310: {
! 311: struct acpitz_softc *sc = arg;
! 312: u_int64_t crt;
! 313:
! 314: dnprintf(10, "%s notify: %.2x %s\n", DEVNAME(sc), notify_type,
! 315: sc->sc_devnode->parent->name);
! 316:
! 317: switch (notify_type) {
! 318: case 0x81: /* Operating Points changed */
! 319: sc->sc_psv = acpitz_getreading(sc, "_PSV");
! 320: crt = sc->sc_crt;
! 321: sc->sc_crt = acpitz_getreading(sc, "_CRT");
! 322: if (crt != sc->sc_crt)
! 323: printf("%s: critical temperature: %u degC",
! 324: DEVNAME(sc), (sc->sc_crt - 2732) / 10);
! 325: break;
! 326: default:
! 327: break;
! 328: }
! 329: acpitz_refresh(sc);
! 330: return (0);
! 331: }
CVSweb