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

Annotation of sys/dev/acpi/acpi.c, Revision 1.1

1.1     ! nbrk        1: /*     $OpenBSD: acpi.c,v 1.88 2007/04/17 16:07:45 mk Exp $    */
        !             2: /*
        !             3:  * Copyright (c) 2005 Thorsten Lockert <tholo@sigmasoft.com>
        !             4:  * Copyright (c) 2005 Jordan Hargrave <jordan@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/systm.h>
        !            21: #include <sys/device.h>
        !            22: #include <sys/malloc.h>
        !            23: #include <sys/fcntl.h>
        !            24: #include <sys/ioccom.h>
        !            25: #include <sys/event.h>
        !            26: #include <sys/signalvar.h>
        !            27: #include <sys/proc.h>
        !            28: #include <sys/kthread.h>
        !            29:
        !            30: #include <machine/conf.h>
        !            31: #include <machine/cpufunc.h>
        !            32: #include <machine/bus.h>
        !            33:
        !            34: #include <dev/pci/pcivar.h>
        !            35: #include <dev/acpi/acpireg.h>
        !            36: #include <dev/acpi/acpivar.h>
        !            37: #include <dev/acpi/amltypes.h>
        !            38: #include <dev/acpi/acpidev.h>
        !            39: #include <dev/acpi/dsdt.h>
        !            40:
        !            41: #include <machine/apmvar.h>
        !            42:
        !            43: #ifdef ACPI_DEBUG
        !            44: int acpi_debug = 16;
        !            45: #endif
        !            46: int acpi_enabled = 0;
        !            47: int acpi_poll_enabled = 0;
        !            48: int acpi_hasprocfvs = 0;
        !            49:
        !            50: #define ACPIEN_RETRIES 15
        !            51:
        !            52: void   acpi_isr_thread(void *);
        !            53: void   acpi_create_thread(void *);
        !            54:
        !            55: int    acpi_match(struct device *, void *, void *);
        !            56: void   acpi_attach(struct device *, struct device *, void *);
        !            57: int    acpi_submatch(struct device *, void *, void *);
        !            58: int    acpi_print(void *, const char *);
        !            59:
        !            60: void   acpi_map_pmregs(struct acpi_softc *);
        !            61:
        !            62: void   acpi_founddock(struct aml_node *, void *);
        !            63: void   acpi_foundpss(struct aml_node *, void *);
        !            64: void   acpi_foundhid(struct aml_node *, void *);
        !            65: void   acpi_foundec(struct aml_node *, void *);
        !            66: void   acpi_foundtmp(struct aml_node *, void *);
        !            67: void   acpi_inidev(struct aml_node *, void *);
        !            68:
        !            69: int    acpi_loadtables(struct acpi_softc *, struct acpi_rsdp *);
        !            70: void   acpi_load_table(paddr_t, size_t, acpi_qhead_t *);
        !            71: void   acpi_load_dsdt(paddr_t, struct acpi_q **);
        !            72:
        !            73: void   acpi_init_states(struct acpi_softc *);
        !            74: void   acpi_init_gpes(struct acpi_softc *);
        !            75: void   acpi_init_pm(struct acpi_softc *);
        !            76:
        !            77: void   acpi_foundprt(struct aml_node *, void *);
        !            78:
        !            79: void   acpi_filtdetach(struct knote *);
        !            80: int    acpi_filtread(struct knote *, long);
        !            81:
        !            82: void   acpi_enable_onegpe(struct acpi_softc *, int, int);
        !            83: int    acpi_gpe_level(struct acpi_softc *, int, void *);
        !            84: int    acpi_gpe_edge(struct acpi_softc *, int, void *);
        !            85:
        !            86: #define        ACPI_LOCK(sc)
        !            87: #define        ACPI_UNLOCK(sc)
        !            88:
        !            89: /* XXX move this into dsdt softc at some point */
        !            90: extern struct aml_node aml_root;
        !            91:
        !            92: struct filterops acpiread_filtops = {
        !            93:        1, NULL, acpi_filtdetach, acpi_filtread
        !            94: };
        !            95:
        !            96: struct cfattach acpi_ca = {
        !            97:        sizeof(struct acpi_softc), acpi_match, acpi_attach
        !            98: };
        !            99:
        !           100: struct cfdriver acpi_cd = {
        !           101:        NULL, "acpi", DV_DULL
        !           102: };
        !           103:
        !           104: struct acpi_softc *acpi_softc;
        !           105: int acpi_s5, acpi_evindex;
        !           106:
        !           107: #ifdef __i386__
        !           108: #define acpi_bus_space_map     _bus_space_map
        !           109: #define acpi_bus_space_unmap   _bus_space_unmap
        !           110: #elif defined(__amd64__)
        !           111: #define acpi_bus_space_map     _x86_memio_map
        !           112: #define acpi_bus_space_unmap   _x86_memio_unmap
        !           113: #else
        !           114: #error ACPI supported on i386/amd64 only
        !           115: #endif
        !           116:
        !           117: #define pch(x) (((x)>=' ' && (x)<='z') ? (x) : ' ')
        !           118:
        !           119: void
        !           120: acpi_delay(struct acpi_softc *sc, int64_t uSecs)
        !           121: {
        !           122:        /* XXX this needs to become a tsleep later */
        !           123:        delay(uSecs);
        !           124: }
        !           125:
        !           126: int
        !           127: acpi_gasio(struct acpi_softc *sc, int iodir, int iospace, uint64_t address,
        !           128:     int access_size, int len, void *buffer)
        !           129: {
        !           130:        u_int8_t *pb;
        !           131:        bus_space_handle_t ioh;
        !           132:        struct acpi_mem_map mh;
        !           133:        pci_chipset_tag_t pc;
        !           134:        pcitag_t tag;
        !           135:        bus_addr_t ioaddr;
        !           136:        int reg, idx, ival, sval;
        !           137:
        !           138:        dnprintf(50, "gasio: %.2x 0x%.8llx %s\n",
        !           139:            iospace, address, (iodir == ACPI_IOWRITE) ? "write" : "read");
        !           140:
        !           141:        pb = (u_int8_t *)buffer;
        !           142:        switch (iospace) {
        !           143:        case GAS_SYSTEM_MEMORY:
        !           144:                /* copy to/from system memory */
        !           145:                acpi_map(address, len, &mh);
        !           146:                if (iodir == ACPI_IOREAD)
        !           147:                        memcpy(buffer, mh.va, len);
        !           148:                else
        !           149:                        memcpy(mh.va, buffer, len);
        !           150:                acpi_unmap(&mh);
        !           151:                break;
        !           152:
        !           153:        case GAS_SYSTEM_IOSPACE:
        !           154:                /* read/write from I/O registers */
        !           155:                ioaddr = address;
        !           156:                if (acpi_bus_space_map(sc->sc_iot, ioaddr, len, 0, &ioh) != 0) {
        !           157:                        printf("Unable to map iospace!\n");
        !           158:                        return (-1);
        !           159:                }
        !           160:                for (reg = 0; reg < len; reg += access_size) {
        !           161:                        if (iodir == ACPI_IOREAD) {
        !           162:                                switch (access_size) {
        !           163:                                case 1:
        !           164:                                        *(uint8_t *)(pb+reg) = bus_space_read_1(
        !           165:                                            sc->sc_iot, ioh, reg);
        !           166:                                        dnprintf(80, "os_in8(%llx) = %x\n",
        !           167:                                            reg+address, *(uint8_t *)(pb+reg));
        !           168:                                        break;
        !           169:                                case 2:
        !           170:                                        *(uint16_t *)(pb+reg) = bus_space_read_2(
        !           171:                                            sc->sc_iot, ioh, reg);
        !           172:                                        dnprintf(80, "os_in16(%llx) = %x\n",
        !           173:                                            reg+address, *(uint16_t *)(pb+reg));
        !           174:                                        break;
        !           175:                                case 4:
        !           176:                                        *(uint32_t *)(pb+reg) = bus_space_read_4(
        !           177:                                            sc->sc_iot, ioh, reg);
        !           178:                                        break;
        !           179:                                }
        !           180:                        } else {
        !           181:                                switch (access_size) {
        !           182:                                case 1:
        !           183:                                        bus_space_write_1(sc->sc_iot, ioh, reg,
        !           184:                                            *(uint8_t *)(pb+reg));
        !           185:                                        dnprintf(80, "os_out8(%llx,%x)\n",
        !           186:                                            reg+address, *(uint8_t *)(pb+reg));
        !           187:                                        break;
        !           188:                                case 2:
        !           189:                                        bus_space_write_2(sc->sc_iot, ioh, reg,
        !           190:                                            *(uint16_t *)(pb+reg));
        !           191:                                        dnprintf(80, "os_out16(%llx,%x)\n",
        !           192:                                            reg+address, *(uint16_t *)(pb+reg));
        !           193:                                        break;
        !           194:                                case 4:
        !           195:                                        bus_space_write_4(sc->sc_iot, ioh, reg,
        !           196:                                            *(uint32_t *)(pb+reg));
        !           197:                                        break;
        !           198:                                }
        !           199:                        }
        !           200:
        !           201:                        /* During autoconf some devices are still gathering
        !           202:                         * information.  Delay here to give them an opportunity
        !           203:                         * to finish.  During runtime we simply need to ignore
        !           204:                         * transient values.
        !           205:                         */
        !           206:                        if (cold)
        !           207:                                delay(10000);
        !           208:                }
        !           209:                acpi_bus_space_unmap(sc->sc_iot, ioh, len, &ioaddr);
        !           210:                break;
        !           211:
        !           212:        case GAS_PCI_CFG_SPACE:
        !           213:                /* format of address:
        !           214:                 *    bits 00..15 = register
        !           215:                 *    bits 16..31 = function
        !           216:                 *    bits 32..47 = device
        !           217:                 *    bits 48..63 = bus
        !           218:                 */
        !           219:                pc = NULL;
        !           220:                tag = pci_make_tag(pc,
        !           221:                    ACPI_PCI_BUS(address), ACPI_PCI_DEV(address),
        !           222:                    ACPI_PCI_FN(address));
        !           223:
        !           224:                /* XXX: This is ugly. read-modify-write does a byte at a time */
        !           225:                reg = ACPI_PCI_REG(address);
        !           226:                for (idx = reg; idx < reg+len; idx++) {
        !           227:                        ival = pci_conf_read(pc, tag, idx & ~0x3);
        !           228:                        if (iodir == ACPI_IOREAD) {
        !           229:                                *pb = ival >> (8 * (idx & 0x3));
        !           230:                        } else {
        !           231:                                sval = *pb;
        !           232:                                ival &= ~(0xFF << (8* (idx & 0x3)));
        !           233:                                ival |= sval << (8* (idx & 0x3));
        !           234:                                pci_conf_write(pc, tag, idx & ~0x3, ival);
        !           235:                        }
        !           236:                        pb++;
        !           237:                }
        !           238:                break;
        !           239:        case GAS_EMBEDDED:
        !           240:                if (sc->sc_ec == NULL)
        !           241:                        break;
        !           242: #ifndef SMALL_KERNEL
        !           243:                if (iodir == ACPI_IOREAD)
        !           244:                        acpiec_read(sc->sc_ec, (u_int8_t)address, len, buffer);
        !           245:                else
        !           246:                        acpiec_write(sc->sc_ec, (u_int8_t)address, len, buffer);
        !           247: #endif
        !           248:                break;
        !           249:        }
        !           250:        return (0);
        !           251: }
        !           252:
        !           253: void
        !           254: acpi_inidev(struct aml_node *node, void *arg)
        !           255: {
        !           256:        struct acpi_softc       *sc = (struct acpi_softc *)arg;
        !           257:        struct aml_value        res;
        !           258:
        !           259:        /*
        !           260:         * XXX per the ACPI spec 6.5.1 only run _INI when device is there
        !           261:         * or when there is no _STA.
        !           262:         * The tricky bit is that the parent can have a _STA that is disabled
        !           263:         * and the children do not have a _STA.  In that case the _INI will
        !           264:         * execute!  This needs to be fixed.
        !           265:         */
        !           266:
        !           267:        memset(&res, 0, sizeof res);
        !           268:        if (aml_evalname(sc, node, "_STA", 0, NULL, &res))
        !           269:                res.v_integer = STA_PRESENT; /* no _STA, fake it */
        !           270:
        !           271:        if (res.v_integer & STA_PRESENT)
        !           272:                aml_evalnode(sc, node, 0, NULL, NULL);
        !           273:        aml_freevalue(&res);
        !           274: }
        !           275:
        !           276: void
        !           277: acpi_foundprt(struct aml_node *node, void *arg)
        !           278: {
        !           279:        struct acpi_softc       *sc = (struct acpi_softc *)arg;
        !           280:        struct device           *self = (struct device *)arg;
        !           281:        const char              *dev;
        !           282:        struct acpi_attach_args aaa;
        !           283:
        !           284:        dnprintf(10, "found prt entry: %s\n", node->parent->name);
        !           285:
        !           286:        memset(&aaa, 0, sizeof(aaa));
        !           287:        aaa.aaa_iot = sc->sc_iot;
        !           288:        aaa.aaa_memt = sc->sc_memt;
        !           289:        aaa.aaa_node = node;
        !           290:        aaa.aaa_dev = dev;
        !           291:        aaa.aaa_name = "acpiprt";
        !           292:
        !           293:        config_found(self, &aaa, acpi_print);
        !           294: }
        !           295:
        !           296: int
        !           297: acpi_match(struct device *parent, void *match, void *aux)
        !           298: {
        !           299:        struct acpi_attach_args *aaa = aux;
        !           300:        struct cfdata           *cf = match;
        !           301:
        !           302:        /* sanity */
        !           303:        if (strcmp(aaa->aaa_name, cf->cf_driver->cd_name))
        !           304:                return (0);
        !           305:
        !           306:        if (!acpi_probe(parent, cf, aaa))
        !           307:                return (0);
        !           308:
        !           309:        return (1);
        !           310: }
        !           311:
        !           312: int acpi_add_device(struct aml_node *node, void *arg);
        !           313:
        !           314: int
        !           315: acpi_add_device(struct aml_node *node, void *arg)
        !           316: {
        !           317:        struct device *self = arg;
        !           318:        struct acpi_softc *sc = arg;
        !           319:        struct acpi_attach_args aaa;
        !           320:
        !           321:        memset(&aaa, 0, sizeof(aaa));
        !           322:        aaa.aaa_node = node;
        !           323:        aaa.aaa_dev = "";
        !           324:        aaa.aaa_iot = sc->sc_iot;
        !           325:        aaa.aaa_memt = sc->sc_memt;
        !           326:        if (node == NULL || node->value == NULL)
        !           327:                return 0;
        !           328:
        !           329:        switch (node->value->type) {
        !           330:        case AML_OBJTYPE_PROCESSOR:
        !           331:                aaa.aaa_name = "acpicpu";
        !           332:                break;
        !           333:        case AML_OBJTYPE_THERMZONE:
        !           334:                aaa.aaa_name = "acpitz";
        !           335:                break;
        !           336:         default:
        !           337:                return 0;
        !           338:        }
        !           339:        config_found(self, &aaa, acpi_print);
        !           340:        return 0;
        !           341: }
        !           342:
        !           343: void
        !           344: acpi_attach(struct device *parent, struct device *self, void *aux)
        !           345: {
        !           346:        struct acpi_attach_args *aaa = aux;
        !           347:        struct acpi_softc *sc = (struct acpi_softc *)self;
        !           348:        struct acpi_mem_map handle;
        !           349:        struct acpi_rsdp *rsdp;
        !           350:        struct acpi_q *entry;
        !           351:        struct acpi_dsdt *p_dsdt;
        !           352: #ifndef SMALL_KERNEL
        !           353:        struct device *dev;
        !           354:        struct acpi_ac *ac;
        !           355:        struct acpi_bat *bat;
        !           356:        paddr_t facspa;
        !           357: #endif
        !           358:        sc->sc_iot = aaa->aaa_iot;
        !           359:        sc->sc_memt = aaa->aaa_memt;
        !           360:
        !           361:
        !           362:        if (acpi_map(aaa->aaa_pbase, sizeof(struct acpi_rsdp), &handle)) {
        !           363:                printf(": can't map memory\n");
        !           364:                return;
        !           365:        }
        !           366:
        !           367:        rsdp = (struct acpi_rsdp *)handle.va;
        !           368:        printf(": rev %d", (int)rsdp->rsdp_revision);
        !           369:
        !           370:        SIMPLEQ_INIT(&sc->sc_tables);
        !           371:
        !           372:        sc->sc_fadt = NULL;
        !           373:        sc->sc_facs = NULL;
        !           374:        sc->sc_powerbtn = 0;
        !           375:        sc->sc_sleepbtn = 0;
        !           376:
        !           377:        sc->sc_note = malloc(sizeof(struct klist), M_DEVBUF, M_NOWAIT);
        !           378:        if (sc->sc_note == NULL) {
        !           379:                printf(": can't allocate memory\n");
        !           380:                acpi_unmap(&handle);
        !           381:                return;
        !           382:        }
        !           383:        memset(sc->sc_note, 0, sizeof(struct klist));
        !           384:
        !           385:        if (acpi_loadtables(sc, rsdp)) {
        !           386:                printf(": can't load tables\n");
        !           387:                acpi_unmap(&handle);
        !           388:                return;
        !           389:        }
        !           390:
        !           391:        acpi_unmap(&handle);
        !           392:
        !           393:        /*
        !           394:         * Find the FADT
        !           395:         */
        !           396:        SIMPLEQ_FOREACH(entry, &sc->sc_tables, q_next) {
        !           397:                if (memcmp(entry->q_table, FADT_SIG,
        !           398:                    sizeof(FADT_SIG) - 1) == 0) {
        !           399:                        sc->sc_fadt = entry->q_table;
        !           400:                        break;
        !           401:                }
        !           402:        }
        !           403:        if (sc->sc_fadt == NULL) {
        !           404:                printf(": no FADT\n");
        !           405:                return;
        !           406:        }
        !           407:
        !           408: #ifdef ACPI_ENABLE
        !           409:        /*
        !           410:         * Check if we are able to enable ACPI control
        !           411:         */
        !           412:        if (!sc->sc_fadt->smi_cmd ||
        !           413:            (!sc->sc_fadt->acpi_enable && !sc->sc_fadt->acpi_disable)) {
        !           414:                printf(": ACPI control unavailable\n");
        !           415:                return;
        !           416:        }
        !           417: #endif
        !           418:
        !           419:        /* Create opcode hashtable */
        !           420:        aml_hashopcodes();
        !           421:
        !           422:        acpi_enabled=1;
        !           423:
        !           424:        /* Create Default AML objects */
        !           425:        aml_create_defaultobjects();
        !           426:
        !           427:        /*
        !           428:         * Load the DSDT from the FADT pointer -- use the
        !           429:         * extended (64-bit) pointer if it exists
        !           430:         */
        !           431:        if (sc->sc_fadt->hdr_revision < 3 || sc->sc_fadt->x_dsdt == 0)
        !           432:                acpi_load_dsdt(sc->sc_fadt->dsdt, &entry);
        !           433:        else
        !           434:                acpi_load_dsdt(sc->sc_fadt->x_dsdt, &entry);
        !           435:
        !           436:        if (entry == NULL)
        !           437:                printf(" !DSDT");
        !           438:        SIMPLEQ_INSERT_HEAD(&sc->sc_tables, entry, q_next);
        !           439:
        !           440:        p_dsdt = entry->q_table;
        !           441:        acpi_parse_aml(sc, p_dsdt->aml, p_dsdt->hdr_length -
        !           442:            sizeof(p_dsdt->hdr));
        !           443:
        !           444:        /* Load SSDT's */
        !           445:        SIMPLEQ_FOREACH(entry, &sc->sc_tables, q_next) {
        !           446:                if (memcmp(entry->q_table, SSDT_SIG,
        !           447:                    sizeof(SSDT_SIG) - 1) == 0) {
        !           448:                        p_dsdt = entry->q_table;
        !           449:                        acpi_parse_aml(sc, p_dsdt->aml, p_dsdt->hdr_length -
        !           450:                            sizeof(p_dsdt->hdr));
        !           451:                }
        !           452:        }
        !           453:
        !           454:        /* Perform post-parsing fixups */
        !           455:        aml_postparse();
        !           456:
        !           457:        /* Walk AML Tree */
        !           458:        /* aml_walkroot(); */
        !           459:
        !           460: #ifndef SMALL_KERNEL
        !           461:        /* Find available sleeping states */
        !           462:        acpi_init_states(sc);
        !           463:
        !           464:        /* Find available sleep/resume related methods. */
        !           465:        acpi_init_pm(sc);
        !           466:
        !           467:        /*
        !           468:         * Set up a pointer to the firmware control structure
        !           469:         */
        !           470:        if (sc->sc_fadt->hdr_revision < 3 || sc->sc_fadt->x_firmware_ctl == 0)
        !           471:                facspa = sc->sc_fadt->firmware_ctl;
        !           472:        else
        !           473:                facspa = sc->sc_fadt->x_firmware_ctl;
        !           474:
        !           475:        if (acpi_map(facspa, sizeof(struct acpi_facs), &handle))
        !           476:                printf(" !FACS");
        !           477:        else
        !           478:                sc->sc_facs = (struct acpi_facs *)handle.va;
        !           479:
        !           480:        /* Map Power Management registers */
        !           481:        acpi_map_pmregs(sc);
        !           482:
        !           483:        /* Initialize GPE handlers */
        !           484:        acpi_init_gpes(sc);
        !           485:
        !           486:        /* some devices require periodic polling */
        !           487:        timeout_set(&sc->sc_dev_timeout, acpi_poll, sc);
        !           488: #endif /* SMALL_KERNEL */
        !           489:
        !           490:        /*
        !           491:         * Take over ACPI control.  Note that once we do this, we
        !           492:         * effectively tell the system that we have ownership of
        !           493:         * the ACPI hardware registers, and that SMI should leave
        !           494:         * them alone
        !           495:         *
        !           496:         * This may prevent thermal control on some systems where
        !           497:         * that actually does work
        !           498:         */
        !           499: #ifdef ACPI_ENABLE
        !           500:        int idx;
        !           501:
        !           502:        acpi_write_pmreg(sc, ACPIREG_SMICMD, 0, sc->sc_fadt->acpi_enable);
        !           503:        idx = 0;
        !           504:        do {
        !           505:                if (idx++ > ACPIEN_RETRIES) {
        !           506:                        printf(": can't enable ACPI\n");
        !           507:                        return;
        !           508:                }
        !           509:        } while (!(acpi_read_pmreg(sc, ACPIREG_PM1_CNT, 0) & ACPI_PM1_SCI_EN));
        !           510: #endif
        !           511:
        !           512:        printf("\n");
        !           513:
        !           514:        printf("%s: tables ", DEVNAME(sc));
        !           515:        SIMPLEQ_FOREACH(entry, &sc->sc_tables, q_next) {
        !           516:                printf("%.4s ", entry->q_table);
        !           517:        }
        !           518:        printf("\n");
        !           519:
        !           520: #ifndef SMALL_KERNEL
        !           521:        /*
        !           522:         * ACPI is enabled now -- attach timer
        !           523:         */
        !           524:        {
        !           525:                struct acpi_attach_args aaa;
        !           526:
        !           527:                memset(&aaa, 0, sizeof(aaa));
        !           528:                aaa.aaa_name = "acpitimer";
        !           529:                aaa.aaa_iot = sc->sc_iot;
        !           530:                aaa.aaa_memt = sc->sc_memt;
        !           531: #if 0
        !           532:                aaa.aaa_pcit = sc->sc_pcit;
        !           533:                aaa.aaa_smbust = sc->sc_smbust;
        !           534: #endif
        !           535:                config_found(self, &aaa, acpi_print);
        !           536:        }
        !           537: #endif /* SMALL_KERNEL */
        !           538:
        !           539:        /*
        !           540:         * Attach table-defined devices
        !           541:         */
        !           542:        SIMPLEQ_FOREACH(entry, &sc->sc_tables, q_next) {
        !           543:                struct acpi_attach_args aaa;
        !           544:
        !           545:                memset(&aaa, 0, sizeof(aaa));
        !           546:                aaa.aaa_iot = sc->sc_iot;
        !           547:                aaa.aaa_memt = sc->sc_memt;
        !           548:        #if 0
        !           549:                aaa.aaa_pcit = sc->sc_pcit;
        !           550:                aaa.aaa_smbust = sc->sc_smbust;
        !           551:        #endif
        !           552:                aaa.aaa_table = entry->q_table;
        !           553:                config_found_sm(self, &aaa, acpi_print, acpi_submatch);
        !           554:        }
        !           555:
        !           556:        acpi_softc = sc;
        !           557:
        !           558:        /* initialize runtime environment */
        !           559:        aml_find_node(aml_root.child, "_INI", acpi_inidev, sc);
        !           560:
        !           561:        /* attach pci interrupt routing tables */
        !           562:        aml_find_node(aml_root.child, "_PRT", acpi_foundprt, sc);
        !           563:
        !           564: #ifndef SMALL_KERNEL
        !           565:         /* XXX EC needs to be attached first on some systems */
        !           566:        aml_find_node(aml_root.child, "_HID", acpi_foundec, sc);
        !           567:
        !           568:        aml_walknodes(&aml_root, AML_WALK_PRE, acpi_add_device, sc);
        !           569:
        !           570:        /* attach battery, power supply and button devices */
        !           571:        aml_find_node(aml_root.child, "_HID", acpi_foundhid, sc);
        !           572:
        !           573:        /* attach docks */
        !           574:        aml_find_node(aml_root.child, "_DCK", acpi_founddock, sc);
        !           575:
        !           576:        /* create list of devices we want to query when APM come in */
        !           577:        SLIST_INIT(&sc->sc_ac);
        !           578:        SLIST_INIT(&sc->sc_bat);
        !           579:        TAILQ_FOREACH(dev, &alldevs, dv_list) {
        !           580:                if (!strncmp(dev->dv_xname, "acpiac", strlen("acpiac"))) {
        !           581:                        ac = malloc(sizeof(struct acpi_ac), M_DEVBUF, M_WAITOK);
        !           582:                        memset(ac, 0, sizeof(struct acpi_ac));
        !           583:                        ac->aac_softc = (struct acpiac_softc *)dev;
        !           584:                        SLIST_INSERT_HEAD(&sc->sc_ac, ac, aac_link);
        !           585:                }
        !           586:                if (!strncmp(dev->dv_xname, "acpibat", strlen("acpibat"))) {
        !           587:                        bat = malloc(sizeof(struct acpi_bat), M_DEVBUF,
        !           588:                            M_WAITOK);
        !           589:                        memset(bat, 0, sizeof(struct acpi_bat));
        !           590:                        bat->aba_softc = (struct acpibat_softc *)dev;
        !           591:                        SLIST_INSERT_HEAD(&sc->sc_bat, bat, aba_link);
        !           592:                }
        !           593:        }
        !           594:
        !           595:        /* Setup threads */
        !           596:        sc->sc_thread = malloc(sizeof(struct acpi_thread), M_DEVBUF, M_WAITOK);
        !           597:        sc->sc_thread->sc = sc;
        !           598:        sc->sc_thread->running = 1;
        !           599:
        !           600:        kthread_create_deferred(acpi_create_thread, sc);
        !           601: #endif /* SMALL_KERNEL */
        !           602: }
        !           603:
        !           604: int
        !           605: acpi_submatch(struct device *parent, void *match, void *aux)
        !           606: {
        !           607:        struct acpi_attach_args *aaa = (struct acpi_attach_args *)aux;
        !           608:        struct cfdata *cf = match;
        !           609:
        !           610:        if (aaa->aaa_table == NULL)
        !           611:                return (0);
        !           612:        return ((*cf->cf_attach->ca_match)(parent, match, aux));
        !           613: }
        !           614:
        !           615: int
        !           616: acpi_print(void *aux, const char *pnp)
        !           617: {
        !           618:        /* XXX ACPIVERBOSE should be replaced with dnprintf */
        !           619:        struct acpi_attach_args *aa = aux;
        !           620: #ifdef ACPIVERBOSE
        !           621:        struct acpi_table_header *hdr =
        !           622:                (struct acpi_table_header *)aa->aaa_table;
        !           623: #endif
        !           624:
        !           625:        if (pnp) {
        !           626:                if (aa->aaa_name)
        !           627:                        printf("%s at %s", aa->aaa_name, pnp);
        !           628: #ifdef ACPIVERBOSE
        !           629:                else
        !           630:                        printf("acpi device at %s from", pnp);
        !           631: #else
        !           632:                else
        !           633:                        return (QUIET);
        !           634: #endif
        !           635:        }
        !           636: #ifdef ACPIVERBOSE
        !           637:        if (hdr)
        !           638:                printf(" table %c%c%c%c",
        !           639:                    hdr->signature[0], hdr->signature[1],
        !           640:                    hdr->signature[2], hdr->signature[3]);
        !           641: #endif
        !           642:
        !           643:        return (UNCONF);
        !           644: }
        !           645:
        !           646: int
        !           647: acpi_loadtables(struct acpi_softc *sc, struct acpi_rsdp *rsdp)
        !           648: {
        !           649:        struct acpi_mem_map hrsdt, handle;
        !           650:        struct acpi_table_header *hdr;
        !           651:        int i, ntables;
        !           652:        size_t len;
        !           653:
        !           654:        if (rsdp->rsdp_revision == 2) {
        !           655:                struct acpi_xsdt *xsdt;
        !           656:
        !           657:                if (acpi_map(rsdp->rsdp_xsdt, sizeof(*hdr), &handle)) {
        !           658:                        printf("couldn't map rsdt\n");
        !           659:                        return (ENOMEM);
        !           660:                }
        !           661:
        !           662:                hdr = (struct acpi_table_header *)handle.va;
        !           663:                len = hdr->length;
        !           664:                acpi_unmap(&handle);
        !           665:                hdr = NULL;
        !           666:
        !           667:                acpi_map(rsdp->rsdp_xsdt, len, &hrsdt);
        !           668:                xsdt = (struct acpi_xsdt *)hrsdt.va;
        !           669:
        !           670:                ntables = (len - sizeof(struct acpi_table_header)) /
        !           671:                    sizeof(xsdt->table_offsets[0]);
        !           672:
        !           673:                for (i = 0; i < ntables; i++) {
        !           674:                        acpi_map(xsdt->table_offsets[i], sizeof(*hdr), &handle);
        !           675:                        hdr = (struct acpi_table_header *)handle.va;
        !           676:                        acpi_load_table(xsdt->table_offsets[i], hdr->length,
        !           677:                            &sc->sc_tables);
        !           678:                        acpi_unmap(&handle);
        !           679:                }
        !           680:                acpi_unmap(&hrsdt);
        !           681:        } else {
        !           682:                struct acpi_rsdt *rsdt;
        !           683:
        !           684:                if (acpi_map(rsdp->rsdp_rsdt, sizeof(*hdr), &handle)) {
        !           685:                        printf("couldn't map rsdt\n");
        !           686:                        return (ENOMEM);
        !           687:                }
        !           688:
        !           689:                hdr = (struct acpi_table_header *)handle.va;
        !           690:                len = hdr->length;
        !           691:                acpi_unmap(&handle);
        !           692:                hdr = NULL;
        !           693:
        !           694:                acpi_map(rsdp->rsdp_rsdt, len, &hrsdt);
        !           695:                rsdt = (struct acpi_rsdt *)hrsdt.va;
        !           696:
        !           697:                ntables = (len - sizeof(struct acpi_table_header)) /
        !           698:                    sizeof(rsdt->table_offsets[0]);
        !           699:
        !           700:                for (i = 0; i < ntables; i++) {
        !           701:                        acpi_map(rsdt->table_offsets[i], sizeof(*hdr), &handle);
        !           702:                        hdr = (struct acpi_table_header *)handle.va;
        !           703:                        acpi_load_table(rsdt->table_offsets[i], hdr->length,
        !           704:                            &sc->sc_tables);
        !           705:                        acpi_unmap(&handle);
        !           706:                }
        !           707:                acpi_unmap(&hrsdt);
        !           708:        }
        !           709:
        !           710:        return (0);
        !           711: }
        !           712:
        !           713: void
        !           714: acpi_load_table(paddr_t pa, size_t len, acpi_qhead_t *queue)
        !           715: {
        !           716:        struct acpi_mem_map handle;
        !           717:        struct acpi_q *entry;
        !           718:
        !           719:        entry = malloc(len + sizeof(struct acpi_q), M_DEVBUF, M_NOWAIT);
        !           720:
        !           721:        if (entry != NULL) {
        !           722:                if (acpi_map(pa, len, &handle)) {
        !           723:                        free(entry, M_DEVBUF);
        !           724:                        return;
        !           725:                }
        !           726:                memcpy(entry->q_data, handle.va, len);
        !           727:                entry->q_table = entry->q_data;
        !           728:                acpi_unmap(&handle);
        !           729:                SIMPLEQ_INSERT_TAIL(queue, entry, q_next);
        !           730:        }
        !           731: }
        !           732:
        !           733: void
        !           734: acpi_load_dsdt(paddr_t pa, struct acpi_q **dsdt)
        !           735: {
        !           736:        struct acpi_mem_map handle;
        !           737:        struct acpi_table_header *hdr;
        !           738:        size_t len;
        !           739:
        !           740:        if (acpi_map(pa, sizeof(*hdr), &handle))
        !           741:                return;
        !           742:        hdr = (struct acpi_table_header *)handle.va;
        !           743:        len = hdr->length;
        !           744:        acpi_unmap(&handle);
        !           745:
        !           746:        *dsdt = malloc(len + sizeof(struct acpi_q), M_DEVBUF, M_NOWAIT);
        !           747:
        !           748:        if (*dsdt != NULL) {
        !           749:                if (acpi_map(pa, len, &handle)) {
        !           750:                        free(*dsdt, M_DEVBUF);
        !           751:                        *dsdt = NULL;
        !           752:                        return;
        !           753:                }
        !           754:                memcpy((*dsdt)->q_data, handle.va, len);
        !           755:                (*dsdt)->q_table = (*dsdt)->q_data;
        !           756:                acpi_unmap(&handle);
        !           757:        }
        !           758: }
        !           759:
        !           760: int
        !           761: acpiopen(dev_t dev, int flag, int mode, struct proc *p)
        !           762: {
        !           763:        struct acpi_softc *sc;
        !           764:        int error = 0;
        !           765:
        !           766:        if (!acpi_cd.cd_ndevs || minor(dev) != 0 ||
        !           767:            !(sc = acpi_cd.cd_devs[minor(dev)]))
        !           768:                return (ENXIO);
        !           769:
        !           770:        return (error);
        !           771: }
        !           772:
        !           773: int
        !           774: acpiclose(dev_t dev, int flag, int mode, struct proc *p)
        !           775: {
        !           776:        struct acpi_softc *sc;
        !           777:
        !           778:        if (!acpi_cd.cd_ndevs || minor(dev) != 0 ||
        !           779:            !(sc = acpi_cd.cd_devs[minor(dev)]))
        !           780:                return (ENXIO);
        !           781:
        !           782:        return (0);
        !           783: }
        !           784:
        !           785: int
        !           786: acpiioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p)
        !           787: {
        !           788:        int error = 0;
        !           789: #ifndef SMALL_KERNEL
        !           790:        struct acpi_softc *sc;
        !           791:        struct acpi_ac *ac;
        !           792:        struct acpi_bat *bat;
        !           793:        struct apm_power_info *pi = (struct apm_power_info *)data;
        !           794:        int bats;
        !           795:        unsigned int remaining, rem, minutes, rate;
        !           796:
        !           797:        if (!acpi_cd.cd_ndevs || minor(dev) != 0 ||
        !           798:            !(sc = acpi_cd.cd_devs[minor(dev)]))
        !           799:                return (ENXIO);
        !           800:
        !           801:        ACPI_LOCK(sc);
        !           802:        /* fake APM */
        !           803:        switch (cmd) {
        !           804:        case APM_IOC_GETPOWER:
        !           805:                /* A/C */
        !           806:                pi->ac_state = APM_AC_UNKNOWN;
        !           807:                SLIST_FOREACH(ac, &sc->sc_ac, aac_link) {
        !           808:                        if (ac->aac_softc->sc_ac_stat == PSR_ONLINE)
        !           809:                                pi->ac_state = APM_AC_ON;
        !           810:                        else if (ac->aac_softc->sc_ac_stat == PSR_OFFLINE)
        !           811:                                if (pi->ac_state == APM_AC_UNKNOWN)
        !           812:                                        pi->ac_state = APM_AC_OFF;
        !           813:                }
        !           814:
        !           815:                /* battery */
        !           816:                pi->battery_state = APM_BATT_UNKNOWN;
        !           817:                pi->battery_life = 0;
        !           818:                pi->minutes_left = 0;
        !           819:                bats = 0;
        !           820:                remaining = rem = 0;
        !           821:                minutes = 0;
        !           822:                rate = 0;
        !           823:                SLIST_FOREACH(bat, &sc->sc_bat, aba_link) {
        !           824:                        if (bat->aba_softc->sc_bat_present == 0)
        !           825:                                continue;
        !           826:
        !           827:                        if (bat->aba_softc->sc_bif.bif_last_capacity == 0)
        !           828:                                continue;
        !           829:
        !           830:                        bats++;
        !           831:                        rem = (bat->aba_softc->sc_bst.bst_capacity * 100) /
        !           832:                            bat->aba_softc->sc_bif.bif_last_capacity;
        !           833:                        if (rem > 100)
        !           834:                                rem = 100;
        !           835:                        remaining += rem;
        !           836:
        !           837:                        if (bat->aba_softc->sc_bst.bst_rate == BST_UNKNOWN)
        !           838:                                continue;
        !           839:                        else if (bat->aba_softc->sc_bst.bst_rate > 1)
        !           840:                                rate = bat->aba_softc->sc_bst.bst_rate;
        !           841:
        !           842:                        minutes += bat->aba_softc->sc_bst.bst_capacity;
        !           843:                }
        !           844:
        !           845:                if (bats == 0) {
        !           846:                        pi->battery_state = APM_BATTERY_ABSENT;
        !           847:                        pi->battery_life = 0;
        !           848:                        pi->minutes_left = (unsigned int)-1;
        !           849:                        break;
        !           850:                }
        !           851:
        !           852:                if (pi->ac_state == APM_AC_ON || rate == 0)
        !           853:                        pi->minutes_left = (unsigned int)-1;
        !           854:                else
        !           855:                        pi->minutes_left = 100 * minutes / rate;
        !           856:
        !           857:                /* running on battery */
        !           858:                pi->battery_life = remaining / bats;
        !           859:                if (pi->battery_life > 50)
        !           860:                        pi->battery_state = APM_BATT_HIGH;
        !           861:                else if (pi->battery_life > 25)
        !           862:                        pi->battery_state = APM_BATT_LOW;
        !           863:                else
        !           864:                        pi->battery_state = APM_BATT_CRITICAL;
        !           865:
        !           866:                break;
        !           867:
        !           868:        default:
        !           869:                error = ENOTTY;
        !           870:        }
        !           871:
        !           872:        ACPI_UNLOCK(sc);
        !           873: #else
        !           874:        error = ENXIO;
        !           875: #endif /* SMALL_KERNEL */
        !           876:        return (error);
        !           877: }
        !           878:
        !           879: void
        !           880: acpi_filtdetach(struct knote *kn)
        !           881: {
        !           882:        struct acpi_softc *sc = kn->kn_hook;
        !           883:
        !           884:        ACPI_LOCK(sc);
        !           885:        SLIST_REMOVE(sc->sc_note, kn, knote, kn_selnext);
        !           886:        ACPI_UNLOCK(sc);
        !           887: }
        !           888:
        !           889: int
        !           890: acpi_filtread(struct knote *kn, long hint)
        !           891: {
        !           892:        /* XXX weird kqueue_scan() semantics */
        !           893:        if (hint & !kn->kn_data)
        !           894:                kn->kn_data = hint;
        !           895:
        !           896:        return (1);
        !           897: }
        !           898:
        !           899: int
        !           900: acpikqfilter(dev_t dev, struct knote *kn)
        !           901: {
        !           902:        struct acpi_softc *sc;
        !           903:
        !           904:        if (!acpi_cd.cd_ndevs || minor(dev) != 0 ||
        !           905:            !(sc = acpi_cd.cd_devs[minor(dev)]))
        !           906:                return (ENXIO);
        !           907:
        !           908:        switch (kn->kn_filter) {
        !           909:        case EVFILT_READ:
        !           910:                kn->kn_fop = &acpiread_filtops;
        !           911:                break;
        !           912:        default:
        !           913:                return (1);
        !           914:        }
        !           915:
        !           916:        kn->kn_hook = sc;
        !           917:
        !           918:        ACPI_LOCK(sc);
        !           919:        SLIST_INSERT_HEAD(sc->sc_note, kn, kn_selnext);
        !           920:        ACPI_UNLOCK(sc);
        !           921:
        !           922:        return (0);
        !           923: }
        !           924:
        !           925: /* move all stuff that doesn't go on the boot media in here */
        !           926: #ifndef SMALL_KERNEL
        !           927: int
        !           928: acpi_interrupt(void *arg)
        !           929: {
        !           930:        struct acpi_softc *sc = (struct acpi_softc *)arg;
        !           931:        u_int32_t processed, sts, en, idx, jdx;
        !           932:
        !           933:        processed = 0;
        !           934:
        !           935:        dnprintf(40, "ACPI Interrupt\n");
        !           936:        for (idx = 0; idx < sc->sc_lastgpe; idx += 8) {
        !           937:                sts = acpi_read_pmreg(sc, ACPIREG_GPE_STS, idx>>3);
        !           938:                en  = acpi_read_pmreg(sc, ACPIREG_GPE_EN,  idx>>3);
        !           939:                if (en & sts) {
        !           940:                        dnprintf(10, "GPE block: %.2x %.2x %.2x\n", idx, sts,
        !           941:                            en);
        !           942:                        acpi_write_pmreg(sc, ACPIREG_GPE_EN, idx>>3, en & ~sts);
        !           943:                        for (jdx = 0; jdx < 8; jdx++) {
        !           944:                                if (en & sts & (1L << jdx)) {
        !           945:                                        /* Signal this GPE */
        !           946:                                        sc->gpe_table[idx+jdx].active = 1;
        !           947:                                        processed = 1;
        !           948:                                }
        !           949:                        }
        !           950:                }
        !           951:        }
        !           952:
        !           953:        sts = acpi_read_pmreg(sc, ACPIREG_PM1_STS, 0);
        !           954:        en  = acpi_read_pmreg(sc, ACPIREG_PM1_EN, 0);
        !           955:        if (sts & en) {
        !           956:                dnprintf(10,"GEN interrupt: %.4x\n", sts & en);
        !           957:                acpi_write_pmreg(sc, ACPIREG_PM1_EN, 0, en & ~sts);
        !           958:                acpi_write_pmreg(sc, ACPIREG_PM1_STS, 0, en);
        !           959:                acpi_write_pmreg(sc, ACPIREG_PM1_EN, 0, en);
        !           960:                if (sts & ACPI_PM1_PWRBTN_STS)
        !           961:                        sc->sc_powerbtn = 1;
        !           962:                if (sts & ACPI_PM1_SLPBTN_STS)
        !           963:                        sc->sc_sleepbtn = 1;
        !           964:                processed = 1;
        !           965:        }
        !           966:
        !           967:        if (processed) {
        !           968:                sc->sc_wakeup = 0;
        !           969:                wakeup(sc);
        !           970:        }
        !           971:
        !           972:        return (processed);
        !           973: }
        !           974:
        !           975: void
        !           976: acpi_enable_onegpe(struct acpi_softc *sc, int gpe, int enable)
        !           977: {
        !           978:        uint8_t mask = (1L << (gpe & 7));
        !           979:        uint8_t en;
        !           980:
        !           981:        /* Read enabled register */
        !           982:        en = acpi_read_pmreg(sc, ACPIREG_GPE_EN, gpe>>3);
        !           983:        dnprintf(50, "%sabling GPE %.2x (current: %sabled) %.2x\n",
        !           984:            enable ? "en" : "dis", gpe, (en & mask) ? "en" : "dis", en);
        !           985:        if (enable)
        !           986:                en |= mask;
        !           987:        else
        !           988:                en &= ~mask;
        !           989:        acpi_write_pmreg(sc, ACPIREG_GPE_EN, gpe>>3, en);
        !           990: }
        !           991:
        !           992: int
        !           993: acpi_set_gpehandler(struct acpi_softc *sc, int gpe, int (*handler)
        !           994:     (struct acpi_softc *, int, void *), void *arg, const char *label)
        !           995: {
        !           996:        if (gpe >= sc->sc_lastgpe || handler == NULL)
        !           997:                return -EINVAL;
        !           998:
        !           999:        if (sc->gpe_table[gpe].handler != NULL) {
        !          1000:                dnprintf(10, "error: GPE %.2x already enabled!\n", gpe);
        !          1001:                return -EBUSY;
        !          1002:        }
        !          1003:
        !          1004:        dnprintf(50, "Adding GPE handler %.2x (%s)\n", gpe, label);
        !          1005:        sc->gpe_table[gpe].handler = handler;
        !          1006:        sc->gpe_table[gpe].arg = arg;
        !          1007:
        !          1008:        /* Defer enabling GPEs */
        !          1009:
        !          1010:        return (0);
        !          1011: }
        !          1012:
        !          1013: int
        !          1014: acpi_gpe_level(struct acpi_softc *sc, int gpe, void *arg)
        !          1015: {
        !          1016:        struct aml_node *node = arg;
        !          1017:        uint8_t mask;
        !          1018:
        !          1019:        dnprintf(10, "handling Level-sensitive GPE %.2x\n", gpe);
        !          1020:        mask = (1L << (gpe & 7));
        !          1021:
        !          1022:        aml_evalnode(sc, node, 0, NULL, NULL);
        !          1023:        acpi_write_pmreg(sc, ACPIREG_GPE_STS, gpe>>3, mask);
        !          1024:        acpi_write_pmreg(sc, ACPIREG_GPE_EN,  gpe>>3, mask);
        !          1025:
        !          1026:        return (0);
        !          1027: }
        !          1028:
        !          1029: int
        !          1030: acpi_gpe_edge(struct acpi_softc *sc, int gpe, void *arg)
        !          1031: {
        !          1032:
        !          1033:        struct aml_node *node = arg;
        !          1034:        uint8_t mask;
        !          1035:
        !          1036:        dnprintf(10, "handling Edge-sensitive GPE %.2x\n", gpe);
        !          1037:        mask = (1L << (gpe & 7));
        !          1038:
        !          1039:        aml_evalnode(sc, node, 0, NULL, NULL);
        !          1040:        acpi_write_pmreg(sc, ACPIREG_GPE_STS, gpe>>3, mask);
        !          1041:        acpi_write_pmreg(sc, ACPIREG_GPE_EN,  gpe>>3, mask);
        !          1042:
        !          1043:        return (0);
        !          1044: }
        !          1045:
        !          1046: void
        !          1047: acpi_init_gpes(struct acpi_softc *sc)
        !          1048: {
        !          1049:        struct aml_node *gpe;
        !          1050:        char name[12];
        !          1051:        int  idx, ngpe;
        !          1052:
        !          1053:        sc->sc_lastgpe = sc->sc_fadt->gpe0_blk_len << 2;
        !          1054:        if (sc->sc_fadt->gpe1_blk_len) {
        !          1055:        }
        !          1056:        dnprintf(50, "Last GPE: %.2x\n", sc->sc_lastgpe);
        !          1057:
        !          1058:        /* Allocate GPE table */
        !          1059:        sc->gpe_table = malloc(sc->sc_lastgpe * sizeof(struct gpe_block),
        !          1060:            M_DEVBUF, M_WAITOK);
        !          1061:        memset(sc->gpe_table, 0, sc->sc_lastgpe * sizeof(struct gpe_block));
        !          1062:
        !          1063:        ngpe = 0;
        !          1064:
        !          1065:        /* Clear GPE status */
        !          1066:        for (idx = 0; idx < sc->sc_lastgpe; idx += 8) {
        !          1067:                acpi_write_pmreg(sc, ACPIREG_GPE_EN,  idx>>3, 0);
        !          1068:                acpi_write_pmreg(sc, ACPIREG_GPE_STS, idx>>3, -1);
        !          1069:        }
        !          1070:        for (idx = 0; idx < sc->sc_lastgpe; idx++) {
        !          1071:                /* Search Level-sensitive GPES */
        !          1072:                snprintf(name, sizeof(name), "\\_GPE._L%.2X", idx);
        !          1073:                gpe = aml_searchname(&aml_root, name);
        !          1074:                if (gpe != NULL)
        !          1075:                        acpi_set_gpehandler(sc, idx, acpi_gpe_level, gpe,
        !          1076:                            "level");
        !          1077:                if (gpe == NULL) {
        !          1078:                        /* Search Edge-sensitive GPES */
        !          1079:                        snprintf(name, sizeof(name), "\\_GPE._E%.2X", idx);
        !          1080:                        gpe = aml_searchname(&aml_root, name);
        !          1081:                        if (gpe != NULL)
        !          1082:                                acpi_set_gpehandler(sc, idx, acpi_gpe_edge, gpe,
        !          1083:                                    "edge");
        !          1084:                }
        !          1085:        }
        !          1086:        sc->sc_maxgpe = ngpe;
        !          1087: }
        !          1088:
        !          1089: void
        !          1090: acpi_init_states(struct acpi_softc *sc)
        !          1091: {
        !          1092:        struct aml_value res;
        !          1093:        char name[8];
        !          1094:        int i;
        !          1095:
        !          1096:        for (i = ACPI_STATE_S0; i <= ACPI_STATE_S5; i++) {
        !          1097:                snprintf(name, sizeof(name), "_S%d_", i);
        !          1098:                sc->sc_sleeptype[i].slp_typa = -1;
        !          1099:                sc->sc_sleeptype[i].slp_typb = -1;
        !          1100:                if (aml_evalname(sc, aml_root.child, name, 0, NULL, &res) == 0) {
        !          1101:                        if (res.type == AML_OBJTYPE_PACKAGE) {
        !          1102:                                sc->sc_sleeptype[i].slp_typa = aml_val2int(res.v_package[0]);
        !          1103:                                sc->sc_sleeptype[i].slp_typb = aml_val2int(res.v_package[1]);
        !          1104:                        }
        !          1105:                        aml_freevalue(&res);
        !          1106:                }
        !          1107:        }
        !          1108: }
        !          1109:
        !          1110: void
        !          1111: acpi_init_pm(struct acpi_softc *sc)
        !          1112: {
        !          1113:        sc->sc_tts = aml_searchname(aml_root.child, "_TTS");
        !          1114:        sc->sc_pts = aml_searchname(aml_root.child, "_PTS");
        !          1115:        sc->sc_wak = aml_searchname(aml_root.child, "_WAK");
        !          1116:        sc->sc_bfs = aml_searchname(aml_root.child, "_BFS");
        !          1117:        sc->sc_gts = aml_searchname(aml_root.child, "_GTS");
        !          1118: }
        !          1119:
        !          1120: void
        !          1121: acpi_enter_sleep_state(struct acpi_softc *sc, int state)
        !          1122: {
        !          1123: #ifdef ACPI_ENABLE
        !          1124:        struct aml_value env;
        !          1125:        u_int16_t rega, regb;
        !          1126:        int retries;
        !          1127:
        !          1128:        if (state == ACPI_STATE_S0)
        !          1129:                return;
        !          1130:        if (sc->sc_sleeptype[state].slp_typa == -1 ||
        !          1131:            sc->sc_sleeptype[state].slp_typb == -1) {
        !          1132:                printf("%s: state S%d unavailable\n",
        !          1133:                    sc->sc_dev.dv_xname, state);
        !          1134:                return;
        !          1135:        }
        !          1136:
        !          1137:        env.type = AML_OBJTYPE_INTEGER;
        !          1138:        env.v_integer = state;
        !          1139:        /* _TTS(state) */
        !          1140:        if (sc->sc_tts) {
        !          1141:                if (aml_evalnode(sc, sc->sc_tts, 1, &env, NULL) != 0) {
        !          1142:                        dnprintf(10, "%s evaluating method _TTS failed.\n",
        !          1143:                            DEVNAME(sc));
        !          1144:                        return;
        !          1145:                }
        !          1146:        }
        !          1147:        switch (state) {
        !          1148:        case ACPI_STATE_S1:
        !          1149:        case ACPI_STATE_S2:
        !          1150:                resettodr();
        !          1151:                dopowerhooks(PWR_SUSPEND);
        !          1152:                break;
        !          1153:        case ACPI_STATE_S3:
        !          1154:                resettodr();
        !          1155:                dopowerhooks(PWR_STANDBY);
        !          1156:                break;
        !          1157:        }
        !          1158:        /* _PTS(state) */
        !          1159:        if (sc->sc_pts) {
        !          1160:                if (aml_evalnode(sc, sc->sc_pts, 1, &env, NULL) != 0) {
        !          1161:                        dnprintf(10, "%s evaluating method _PTS failed.\n",
        !          1162:                            DEVNAME(sc));
        !          1163:                        return;
        !          1164:                }
        !          1165:        }
        !          1166:        sc->sc_state = state;
        !          1167:        /* _GTS(state) */
        !          1168:        if (sc->sc_gts) {
        !          1169:                if (aml_evalnode(sc, sc->sc_gts, 1, &env, NULL) != 0) {
        !          1170:                        dnprintf(10, "%s evaluating method _GTS failed.\n",
        !          1171:                            DEVNAME(sc));
        !          1172:                        return;
        !          1173:                }
        !          1174:        }
        !          1175:        disable_intr();
        !          1176:
        !          1177:        /* Clear WAK_STS bit */
        !          1178:        acpi_write_pmreg(sc, ACPIREG_PM1_STS, 0, ACPI_PM1_WAK_STS);
        !          1179:
        !          1180:        /* Write SLP_TYPx values */
        !          1181:        rega = acpi_read_pmreg(sc, ACPIREG_PM1A_CNT, 0);
        !          1182:        regb = acpi_read_pmreg(sc, ACPIREG_PM1B_CNT, 0);
        !          1183:        rega &= ~(ACPI_PM1_SLP_TYPX_MASK | ACPI_PM1_SLP_EN);
        !          1184:        regb &= ~(ACPI_PM1_SLP_TYPX_MASK | ACPI_PM1_SLP_EN);
        !          1185:        rega |= ACPI_PM1_SLP_TYPX(sc->sc_sleeptype[state].slp_typa);
        !          1186:        regb |= ACPI_PM1_SLP_TYPX(sc->sc_sleeptype[state].slp_typb);
        !          1187:        acpi_write_pmreg(sc, ACPIREG_PM1A_CNT, 0, rega);
        !          1188:        acpi_write_pmreg(sc, ACPIREG_PM1B_CNT, 0, regb);
        !          1189:
        !          1190:        /* Set SLP_EN bit */
        !          1191:        rega |= ACPI_PM1_SLP_EN;
        !          1192:        regb |= ACPI_PM1_SLP_EN;
        !          1193:        acpi_write_pmreg(sc, ACPIREG_PM1A_CNT, 0, rega);
        !          1194:        acpi_write_pmreg(sc, ACPIREG_PM1B_CNT, 0, regb);
        !          1195:
        !          1196:        /* Loop on WAK_STS */
        !          1197:        for (retries = 1000; retries > 0; retries--) {
        !          1198:                rega = acpi_read_pmreg(sc, ACPIREG_PM1A_STS, 0);
        !          1199:                regb = acpi_read_pmreg(sc, ACPIREG_PM1B_STS, 0);
        !          1200:                if (rega & ACPI_PM1_WAK_STS ||
        !          1201:                    regb & ACPI_PM1_WAK_STS)
        !          1202:                        break;
        !          1203:                DELAY(10);
        !          1204:        }
        !          1205:
        !          1206:        enable_intr();
        !          1207: #endif
        !          1208: }
        !          1209:
        !          1210: void
        !          1211: acpi_resume(struct acpi_softc *sc)
        !          1212: {
        !          1213:        struct aml_value env;
        !          1214:
        !          1215:        env.type = AML_OBJTYPE_INTEGER;
        !          1216:        env.v_integer = sc->sc_state;
        !          1217:
        !          1218:        if (sc->sc_bfs) {
        !          1219:                if (aml_evalnode(sc, sc->sc_pts, 1, &env, NULL) != 0) {
        !          1220:                        dnprintf(10, "%s evaluating method _BFS failed.\n",
        !          1221:                            DEVNAME(sc));
        !          1222:                }
        !          1223:        }
        !          1224:        dopowerhooks(PWR_RESUME);
        !          1225:        inittodr(0);
        !          1226:        if (sc->sc_wak) {
        !          1227:                if (aml_evalnode(sc, sc->sc_wak, 1, &env, NULL) != 0) {
        !          1228:                        dnprintf(10, "%s evaluating method _WAK failed.\n",
        !          1229:                            DEVNAME(sc));
        !          1230:                }
        !          1231:        }
        !          1232:        sc->sc_state = ACPI_STATE_S0;
        !          1233:        if (sc->sc_tts) {
        !          1234:                env.v_integer = sc->sc_state;
        !          1235:                if (aml_evalnode(sc, sc->sc_wak, 1, &env, NULL) != 0) {
        !          1236:                        dnprintf(10, "%s evaluating method _TTS failed.\n",
        !          1237:                            DEVNAME(sc));
        !          1238:                }
        !          1239:        }
        !          1240: }
        !          1241:
        !          1242: void
        !          1243: acpi_powerdown(void)
        !          1244: {
        !          1245:        acpi_enter_sleep_state(acpi_softc, ACPI_STATE_S5);
        !          1246: }
        !          1247:
        !          1248: void
        !          1249: acpi_isr_thread(void *arg)
        !          1250: {
        !          1251:        struct acpi_thread *thread = arg;
        !          1252:        struct acpi_softc  *sc = thread->sc;
        !          1253:        u_int32_t gpe;
        !          1254:
        !          1255:        acpi_attach_machdep(sc);
        !          1256:
        !          1257:        /*
        !          1258:         * If we have an interrupt handler, we can get notification
        !          1259:         * when certain status bits changes in the ACPI registers,
        !          1260:         * so let us enable some events we can forward to userland
        !          1261:         */
        !          1262:        if (sc->sc_interrupt) {
        !          1263:                int16_t flag;
        !          1264:
        !          1265:                dnprintf(1,"slpbtn:%c  pwrbtn:%c\n",
        !          1266:                    sc->sc_fadt->flags & FADT_SLP_BUTTON ? 'n' : 'y',
        !          1267:                    sc->sc_fadt->flags & FADT_PWR_BUTTON ? 'n' : 'y');
        !          1268:                dnprintf(10, "Enabling acpi interrupts...\n");
        !          1269:                sc->sc_wakeup = 1;
        !          1270:
        !          1271:                /* Enable Sleep/Power buttons if they exist */
        !          1272:                flag = acpi_read_pmreg(sc, ACPIREG_PM1_EN, 0);
        !          1273:                if (!(sc->sc_fadt->flags & FADT_PWR_BUTTON)) {
        !          1274:                        flag |= ACPI_PM1_PWRBTN_EN;
        !          1275:                }
        !          1276:                if (!(sc->sc_fadt->flags & FADT_SLP_BUTTON)) {
        !          1277:                        flag |= ACPI_PM1_SLPBTN_EN;
        !          1278:                }
        !          1279:                acpi_write_pmreg(sc, ACPIREG_PM1_EN, 0, flag);
        !          1280:
        !          1281:                /* Enable handled GPEs here */
        !          1282:                for (gpe = 0; gpe < sc->sc_lastgpe; gpe++) {
        !          1283:                        if (sc->gpe_table[gpe].handler)
        !          1284:                                acpi_enable_onegpe(sc, gpe, 1);
        !          1285:                }
        !          1286:        }
        !          1287:
        !          1288:        while (thread->running) {
        !          1289:                dnprintf(10, "sleep... %d\n", sc->sc_wakeup);
        !          1290:                while (sc->sc_wakeup)
        !          1291:                        tsleep(sc, PWAIT, "acpi_idle", 0);
        !          1292:                sc->sc_wakeup = 1;
        !          1293:                dnprintf(10, "wakeup..\n");
        !          1294:
        !          1295:                for (gpe = 0; gpe < sc->sc_lastgpe; gpe++) {
        !          1296:                        struct gpe_block *pgpe = &sc->gpe_table[gpe];
        !          1297:
        !          1298:                        if (pgpe->active) {
        !          1299:                                pgpe->active = 0;
        !          1300:                                dnprintf(50, "softgpe: %.2x\n", gpe);
        !          1301:                                if (pgpe->handler)
        !          1302:                                        pgpe->handler(sc, gpe, pgpe->arg);
        !          1303:                        }
        !          1304:                }
        !          1305:                if (sc->sc_powerbtn) {
        !          1306:                        sc->sc_powerbtn = 0;
        !          1307:
        !          1308:                        aml_notify_dev(ACPI_DEV_PBD, 0x80);
        !          1309:
        !          1310:                        acpi_evindex++;
        !          1311:                        dnprintf(1,"power button pressed\n");
        !          1312:                        KNOTE(sc->sc_note, ACPI_EVENT_COMPOSE(ACPI_EV_PWRBTN,
        !          1313:                            acpi_evindex));
        !          1314:                }
        !          1315:                if (sc->sc_sleepbtn) {
        !          1316:                        sc->sc_sleepbtn = 0;
        !          1317:
        !          1318:                        aml_notify_dev(ACPI_DEV_SBD, 0x80);
        !          1319:
        !          1320:                        acpi_evindex++;
        !          1321:                        dnprintf(1,"sleep button pressed\n");
        !          1322:                        KNOTE(sc->sc_note, ACPI_EVENT_COMPOSE(ACPI_EV_SLPBTN,
        !          1323:                            acpi_evindex));
        !          1324:                }
        !          1325:
        !          1326:                /* handle polling here to keep code non-concurrent*/
        !          1327:                if (sc->sc_poll) {
        !          1328:                        sc->sc_poll = 0;
        !          1329:                        acpi_poll_notify();
        !          1330:                }
        !          1331:        }
        !          1332:        free(thread, M_DEVBUF);
        !          1333:
        !          1334:        kthread_exit(0);
        !          1335: }
        !          1336:
        !          1337: void
        !          1338: acpi_create_thread(void *arg)
        !          1339: {
        !          1340:        struct acpi_softc *sc = arg;
        !          1341:
        !          1342:        if (kthread_create(acpi_isr_thread, sc->sc_thread, NULL, DEVNAME(sc))
        !          1343:            != 0) {
        !          1344:                printf("%s: unable to create isr thread, GPEs disabled\n",
        !          1345:                    DEVNAME(sc));
        !          1346:                return;
        !          1347:        }
        !          1348: }
        !          1349:
        !          1350: int
        !          1351: acpi_map_address(struct acpi_softc *sc, struct acpi_gas *gas,  bus_addr_t base, bus_size_t size,
        !          1352:                 bus_space_handle_t *pioh, bus_space_tag_t *piot)
        !          1353: {
        !          1354:        int iospace = GAS_SYSTEM_IOSPACE;
        !          1355:
        !          1356:        /* No GAS structure, default to I/O space */
        !          1357:        if (gas != NULL) {
        !          1358:                base += gas->address;
        !          1359:                iospace = gas->address_space_id;
        !          1360:        }
        !          1361:        switch (iospace) {
        !          1362:        case GAS_SYSTEM_MEMORY:
        !          1363:                *piot = sc->sc_memt;
        !          1364:                break;
        !          1365:        case GAS_SYSTEM_IOSPACE:
        !          1366:                *piot = sc->sc_iot;
        !          1367:                break;
        !          1368:        default:
        !          1369:                return -1;
        !          1370:        }
        !          1371:        if (bus_space_map(*piot, base, size, 0, pioh))
        !          1372:                return -1;
        !          1373:
        !          1374:        return 0;
        !          1375: }
        !          1376:
        !          1377: /* Map Power Management registers */
        !          1378: void
        !          1379: acpi_map_pmregs(struct acpi_softc *sc)
        !          1380: {
        !          1381:        bus_addr_t addr;
        !          1382:        bus_size_t size;
        !          1383:        const char *name;
        !          1384:        int reg;
        !          1385:
        !          1386:        for (reg = 0; reg < ACPIREG_MAXREG; reg++) {
        !          1387:                size = 0;
        !          1388:                switch (reg) {
        !          1389:                case ACPIREG_SMICMD:
        !          1390:                        name = "smi";
        !          1391:                        size = 1;
        !          1392:                        addr = sc->sc_fadt->smi_cmd;
        !          1393:                        break;
        !          1394:                case ACPIREG_PM1A_STS:
        !          1395:                case ACPIREG_PM1A_EN:
        !          1396:                        name = "pm1a_sts";
        !          1397:                        size = sc->sc_fadt->pm1_evt_len >> 1;
        !          1398:                        addr = sc->sc_fadt->pm1a_evt_blk;
        !          1399:                        if (reg == ACPIREG_PM1A_EN && addr) {
        !          1400:                                addr += size;
        !          1401:                                name = "pm1a_en";
        !          1402:                        }
        !          1403:                        break;
        !          1404:                case ACPIREG_PM1A_CNT:
        !          1405:                        name = "pm1a_cnt";
        !          1406:                        size = sc->sc_fadt->pm1_cnt_len;
        !          1407:                        addr = sc->sc_fadt->pm1a_cnt_blk;
        !          1408:                        break;
        !          1409:                case ACPIREG_PM1B_STS:
        !          1410:                case ACPIREG_PM1B_EN:
        !          1411:                        name = "pm1b_sts";
        !          1412:                        size = sc->sc_fadt->pm1_evt_len >> 1;
        !          1413:                        addr = sc->sc_fadt->pm1b_evt_blk;
        !          1414:                        if (reg == ACPIREG_PM1B_EN && addr) {
        !          1415:                                addr += size;
        !          1416:                                name = "pm1b_en";
        !          1417:                        }
        !          1418:                        break;
        !          1419:                case ACPIREG_PM1B_CNT:
        !          1420:                        name = "pm1b_cnt";
        !          1421:                        size = sc->sc_fadt->pm1_cnt_len;
        !          1422:                        addr = sc->sc_fadt->pm1b_cnt_blk;
        !          1423:                        break;
        !          1424:                case ACPIREG_PM2_CNT:
        !          1425:                        name = "pm2_cnt";
        !          1426:                        size = sc->sc_fadt->pm2_cnt_len;
        !          1427:                        addr = sc->sc_fadt->pm2_cnt_blk;
        !          1428:                        break;
        !          1429: #if 0
        !          1430:                case ACPIREG_PM_TMR:
        !          1431:                        /* Allocated in acpitimer */
        !          1432:                        name = "pm_tmr";
        !          1433:                        size = sc->sc_fadt->pm_tmr_len;
        !          1434:                        addr = sc->sc_fadt->pm_tmr_blk;
        !          1435:                        break;
        !          1436: #endif
        !          1437:                case ACPIREG_GPE0_STS:
        !          1438:                case ACPIREG_GPE0_EN:
        !          1439:                        name = "gpe0_sts";
        !          1440:                        size = sc->sc_fadt->gpe0_blk_len >> 1;
        !          1441:                        addr = sc->sc_fadt->gpe0_blk;
        !          1442:
        !          1443:                        dnprintf(20, "gpe0 block len : %x\n",
        !          1444:                            sc->sc_fadt->gpe0_blk_len >> 1);
        !          1445:                        dnprintf(20, "gpe0 block addr: %x\n",
        !          1446:                            sc->sc_fadt->gpe0_blk);
        !          1447:                        if (reg == ACPIREG_GPE0_EN && addr) {
        !          1448:                                addr += size;
        !          1449:                                name = "gpe0_en";
        !          1450:                        }
        !          1451:                        break;
        !          1452:                case ACPIREG_GPE1_STS:
        !          1453:                case ACPIREG_GPE1_EN:
        !          1454:                        name = "gpe1_sts";
        !          1455:                        size = sc->sc_fadt->gpe1_blk_len >> 1;
        !          1456:                        addr = sc->sc_fadt->gpe1_blk;
        !          1457:
        !          1458:                        dnprintf(20, "gpe1 block len : %x\n",
        !          1459:                            sc->sc_fadt->gpe1_blk_len >> 1);
        !          1460:                        dnprintf(20, "gpe1 block addr: %x\n",
        !          1461:                            sc->sc_fadt->gpe1_blk);
        !          1462:                        if (reg == ACPIREG_GPE1_EN && addr) {
        !          1463:                                addr += size;
        !          1464:                                name = "gpe1_en";
        !          1465:                        }
        !          1466:                        break;
        !          1467:                }
        !          1468:                if (size && addr) {
        !          1469:                        dnprintf(50, "mapping: %.4x %.4x %s\n",
        !          1470:                            addr, size, name);
        !          1471:
        !          1472:                        /* Size and address exist; map register space */
        !          1473:                        bus_space_map(sc->sc_iot, addr, size, 0,
        !          1474:                            &sc->sc_pmregs[reg].ioh);
        !          1475:
        !          1476:                        sc->sc_pmregs[reg].name = name;
        !          1477:                        sc->sc_pmregs[reg].size = size;
        !          1478:                        sc->sc_pmregs[reg].addr = addr;
        !          1479:                }
        !          1480:        }
        !          1481: }
        !          1482:
        !          1483: /* Read from power management register */
        !          1484: int
        !          1485: acpi_read_pmreg(struct acpi_softc *sc, int reg, int offset)
        !          1486: {
        !          1487:        bus_space_handle_t ioh;
        !          1488:        bus_size_t size, __size;
        !          1489:        int regval;
        !          1490:
        !          1491:        __size = 0;
        !          1492:        /* Special cases: 1A/1B blocks can be OR'ed together */
        !          1493:        switch (reg) {
        !          1494:        case ACPIREG_PM1_EN:
        !          1495:                return (acpi_read_pmreg(sc, ACPIREG_PM1A_EN, offset) |
        !          1496:                    acpi_read_pmreg(sc, ACPIREG_PM1B_EN, offset));
        !          1497:        case ACPIREG_PM1_STS:
        !          1498:                return (acpi_read_pmreg(sc, ACPIREG_PM1A_STS, offset) |
        !          1499:                    acpi_read_pmreg(sc, ACPIREG_PM1B_STS, offset));
        !          1500:        case ACPIREG_PM1_CNT:
        !          1501:                return (acpi_read_pmreg(sc, ACPIREG_PM1A_CNT, offset) |
        !          1502:                    acpi_read_pmreg(sc, ACPIREG_PM1B_CNT, offset));
        !          1503:        case ACPIREG_GPE_STS:
        !          1504:                __size = 1;
        !          1505:                dnprintf(50, "read GPE_STS  offset: %.2x %.2x %.2x\n", offset,
        !          1506:                    sc->sc_fadt->gpe0_blk_len>>1, sc->sc_fadt->gpe1_blk_len>>1);
        !          1507:                if (offset < (sc->sc_fadt->gpe0_blk_len >> 1)) {
        !          1508:                        reg = ACPIREG_GPE0_STS;
        !          1509:                }
        !          1510:                break;
        !          1511:        case ACPIREG_GPE_EN:
        !          1512:                __size = 1;
        !          1513:                dnprintf(50, "read GPE_EN   offset: %.2x %.2x %.2x\n",
        !          1514:                    offset, sc->sc_fadt->gpe0_blk_len>>1,
        !          1515:                    sc->sc_fadt->gpe1_blk_len>>1);
        !          1516:                if (offset < (sc->sc_fadt->gpe0_blk_len >> 1)) {
        !          1517:                        reg = ACPIREG_GPE0_EN;
        !          1518:                }
        !          1519:                break;
        !          1520:        }
        !          1521:
        !          1522:        if (reg >= ACPIREG_MAXREG || sc->sc_pmregs[reg].size == 0)
        !          1523:                return (0);
        !          1524:
        !          1525:        regval = 0;
        !          1526:        ioh = sc->sc_pmregs[reg].ioh;
        !          1527:        size = sc->sc_pmregs[reg].size;
        !          1528:        if (__size)
        !          1529:                size = __size;
        !          1530:        if (size > 4)
        !          1531:                size = 4;
        !          1532:
        !          1533:        switch (size) {
        !          1534:        case 1:
        !          1535:                regval = bus_space_read_1(sc->sc_iot, ioh, offset);
        !          1536:                break;
        !          1537:        case 2:
        !          1538:                regval = bus_space_read_2(sc->sc_iot, ioh, offset);
        !          1539:                break;
        !          1540:        case 4:
        !          1541:                regval = bus_space_read_4(sc->sc_iot, ioh, offset);
        !          1542:                break;
        !          1543:        }
        !          1544:
        !          1545:        dnprintf(30, "acpi_readpm: %s = %.4x:%.4x %x\n",
        !          1546:            sc->sc_pmregs[reg].name,
        !          1547:            sc->sc_pmregs[reg].addr, offset, regval);
        !          1548:        return (regval);
        !          1549: }
        !          1550:
        !          1551: /* Write to power management register */
        !          1552: void
        !          1553: acpi_write_pmreg(struct acpi_softc *sc, int reg, int offset, int regval)
        !          1554: {
        !          1555:        bus_space_handle_t ioh;
        !          1556:        bus_size_t size, __size;
        !          1557:
        !          1558:        __size = 0;
        !          1559:        /* Special cases: 1A/1B blocks can be written with same value */
        !          1560:        switch (reg) {
        !          1561:        case ACPIREG_PM1_EN:
        !          1562:                acpi_write_pmreg(sc, ACPIREG_PM1A_EN, offset, regval);
        !          1563:                acpi_write_pmreg(sc, ACPIREG_PM1B_EN, offset, regval);
        !          1564:                break;
        !          1565:        case ACPIREG_PM1_STS:
        !          1566:                acpi_write_pmreg(sc, ACPIREG_PM1A_STS, offset, regval);
        !          1567:                acpi_write_pmreg(sc, ACPIREG_PM1B_STS, offset, regval);
        !          1568:                break;
        !          1569:        case ACPIREG_PM1_CNT:
        !          1570:                acpi_write_pmreg(sc, ACPIREG_PM1A_CNT, offset, regval);
        !          1571:                acpi_write_pmreg(sc, ACPIREG_PM1B_CNT, offset, regval);
        !          1572:                break;
        !          1573:        case ACPIREG_GPE_STS:
        !          1574:                __size = 1;
        !          1575:                dnprintf(50, "write GPE_STS offset: %.2x %.2x %.2x %.2x\n",
        !          1576:                    offset, sc->sc_fadt->gpe0_blk_len>>1,
        !          1577:                    sc->sc_fadt->gpe1_blk_len>>1, regval);
        !          1578:                if (offset < (sc->sc_fadt->gpe0_blk_len >> 1)) {
        !          1579:                        reg = ACPIREG_GPE0_STS;
        !          1580:                }
        !          1581:                break;
        !          1582:        case ACPIREG_GPE_EN:
        !          1583:                __size = 1;
        !          1584:                dnprintf(50, "write GPE_EN  offset: %.2x %.2x %.2x %.2x\n",
        !          1585:                    offset, sc->sc_fadt->gpe0_blk_len>>1,
        !          1586:                    sc->sc_fadt->gpe1_blk_len>>1, regval);
        !          1587:                if (offset < (sc->sc_fadt->gpe0_blk_len >> 1)) {
        !          1588:                        reg = ACPIREG_GPE0_EN;
        !          1589:                }
        !          1590:                break;
        !          1591:        }
        !          1592:
        !          1593:        /* All special case return here */
        !          1594:        if (reg >= ACPIREG_MAXREG)
        !          1595:                return;
        !          1596:
        !          1597:        ioh = sc->sc_pmregs[reg].ioh;
        !          1598:        size = sc->sc_pmregs[reg].size;
        !          1599:        if (__size)
        !          1600:                size = __size;
        !          1601:        if (size > 4)
        !          1602:                size = 4;
        !          1603:        switch (size) {
        !          1604:        case 1:
        !          1605:                bus_space_write_1(sc->sc_iot, ioh, offset, regval);
        !          1606:                break;
        !          1607:        case 2:
        !          1608:                bus_space_write_2(sc->sc_iot, ioh, offset, regval);
        !          1609:                break;
        !          1610:        case 4:
        !          1611:                bus_space_write_4(sc->sc_iot, ioh, offset, regval);
        !          1612:                break;
        !          1613:        }
        !          1614:
        !          1615:        dnprintf(30, "acpi_writepm: %s = %.4x:%.4x %x\n",
        !          1616:            sc->sc_pmregs[reg].name, sc->sc_pmregs[reg].addr, offset, regval);
        !          1617: }
        !          1618:
        !          1619: void
        !          1620: acpi_foundec(struct aml_node *node, void *arg)
        !          1621: {
        !          1622:        struct acpi_softc       *sc = (struct acpi_softc *)arg;
        !          1623:        struct device           *self = (struct device *)arg;
        !          1624:        const char              *dev;
        !          1625:        struct aml_value         res;
        !          1626:        struct acpi_attach_args aaa;
        !          1627:
        !          1628:        if (aml_evalnode(sc, node, 0, NULL, &res) != 0)
        !          1629:                return;
        !          1630:
        !          1631:        switch (res.type) {
        !          1632:        case AML_OBJTYPE_STRING:
        !          1633:                dev = res.v_string;
        !          1634:                break;
        !          1635:        case AML_OBJTYPE_INTEGER:
        !          1636:                dev = aml_eisaid(aml_val2int(&res));
        !          1637:                break;
        !          1638:        default:
        !          1639:                dev = "unknown";
        !          1640:                break;
        !          1641:        }
        !          1642:
        !          1643:        if (strcmp(dev, ACPI_DEV_ECD))
        !          1644:                return;
        !          1645:
        !          1646:        memset(&aaa, 0, sizeof(aaa));
        !          1647:        aaa.aaa_iot = sc->sc_iot;
        !          1648:        aaa.aaa_memt = sc->sc_memt;
        !          1649:        aaa.aaa_node = node->parent;
        !          1650:        aaa.aaa_dev = dev;
        !          1651:        aaa.aaa_name = "acpiec";
        !          1652:        config_found(self, &aaa, acpi_print);
        !          1653:        aml_freevalue(&res);
        !          1654: }
        !          1655:
        !          1656: void
        !          1657: acpi_foundhid(struct aml_node *node, void *arg)
        !          1658: {
        !          1659:        struct acpi_softc       *sc = (struct acpi_softc *)arg;
        !          1660:        struct device           *self = (struct device *)arg;
        !          1661:        const char              *dev;
        !          1662:        struct aml_value         res;
        !          1663:        struct acpi_attach_args aaa;
        !          1664:
        !          1665:        dnprintf(10, "found hid device: %s ", node->parent->name);
        !          1666:        if (aml_evalnode(sc, node, 0, NULL, &res) != 0)
        !          1667:                return;
        !          1668:
        !          1669:        switch (res.type) {
        !          1670:        case AML_OBJTYPE_STRING:
        !          1671:                dev = res.v_string;
        !          1672:                break;
        !          1673:        case AML_OBJTYPE_INTEGER:
        !          1674:                dev = aml_eisaid(aml_val2int(&res));
        !          1675:                break;
        !          1676:        default:
        !          1677:                dev = "unknown";
        !          1678:                break;
        !          1679:        }
        !          1680:        dnprintf(10, "  device: %s\n", dev);
        !          1681:
        !          1682:        memset(&aaa, 0, sizeof(aaa));
        !          1683:        aaa.aaa_iot = sc->sc_iot;
        !          1684:        aaa.aaa_memt = sc->sc_memt;
        !          1685:        aaa.aaa_node = node->parent;
        !          1686:        aaa.aaa_dev = dev;
        !          1687:
        !          1688:        if (!strcmp(dev, ACPI_DEV_AC))
        !          1689:                aaa.aaa_name = "acpiac";
        !          1690:        else if (!strcmp(dev, ACPI_DEV_CMB))
        !          1691:                aaa.aaa_name = "acpibat";
        !          1692:        else if (!strcmp(dev, ACPI_DEV_LD) ||
        !          1693:            !strcmp(dev, ACPI_DEV_PBD) ||
        !          1694:            !strcmp(dev, ACPI_DEV_SBD))
        !          1695:                aaa.aaa_name = "acpibtn";
        !          1696:
        !          1697:        if (aaa.aaa_name)
        !          1698:                config_found(self, &aaa, acpi_print);
        !          1699:        aml_freevalue(&res);
        !          1700: }
        !          1701:
        !          1702: void
        !          1703: acpi_founddock(struct aml_node *node, void *arg)
        !          1704: {
        !          1705:        struct acpi_softc       *sc = (struct acpi_softc *)arg;
        !          1706:        struct device           *self = (struct device *)arg;
        !          1707:        const char              *dev;
        !          1708:        struct acpi_attach_args aaa;
        !          1709:
        !          1710:        dnprintf(10, "found dock entry: %s\n", node->parent->name);
        !          1711:
        !          1712:        memset(&aaa, 0, sizeof(aaa));
        !          1713:        aaa.aaa_iot = sc->sc_iot;
        !          1714:        aaa.aaa_memt = sc->sc_memt;
        !          1715:        aaa.aaa_node = node->parent;
        !          1716:        aaa.aaa_dev = dev;
        !          1717:        aaa.aaa_name = "acpidock";
        !          1718:
        !          1719:        config_found(self, &aaa, acpi_print);
        !          1720: }
        !          1721: #endif /* SMALL_KERNEL */

CVSweb