[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

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