[BACK]Return to acpitz.c CVS log [TXT][DIR] Up to [local] / sys / dev / acpi

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