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

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

1.1     ! nbrk        1: /*     $OpenBSD: acpimadt.c,v 1.10 2007/02/21 19:17:23 kettenis Exp $  */
        !             2: /*
        !             3:  * Copyright (c) 2006 Mark Kettenis <kettenis@openbsd.org>
        !             4:  *
        !             5:  * Permission to use, copy, modify, and distribute this software for any
        !             6:  * purpose with or without fee is hereby granted, provided that the above
        !             7:  * copyright notice and this permission notice appear in all copies.
        !             8:  *
        !             9:  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
        !            10:  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
        !            11:  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
        !            12:  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
        !            13:  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
        !            14:  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
        !            15:  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
        !            16:  */
        !            17:
        !            18: #include <sys/param.h>
        !            19: #include <sys/systm.h>
        !            20: #include <sys/device.h>
        !            21: #include <sys/malloc.h>
        !            22:
        !            23: #include <machine/apicvar.h>
        !            24: #include <machine/cpuvar.h>
        !            25: #include <machine/bus.h>
        !            26:
        !            27: #include <dev/acpi/acpireg.h>
        !            28: #include <dev/acpi/acpivar.h>
        !            29: #include <dev/acpi/acpidev.h>
        !            30: #include <dev/acpi/amltypes.h>
        !            31: #include <dev/acpi/dsdt.h>
        !            32:
        !            33: #include <machine/i8259.h>
        !            34: #include <machine/i82093reg.h>
        !            35: #include <machine/i82093var.h>
        !            36:
        !            37: #include <machine/mpbiosvar.h>
        !            38:
        !            39: #include "ioapic.h"
        !            40:
        !            41: #ifdef __amd64__ /* XXX */
        !            42: #define mp_nintrs mp_nintr
        !            43: #endif
        !            44:
        !            45: int acpimadt_match(struct device *, void *, void *);
        !            46: void acpimadt_attach(struct device *, struct device *, void *);
        !            47:
        !            48: struct cfattach acpimadt_ca = {
        !            49:        sizeof(struct device), acpimadt_match, acpimadt_attach
        !            50: };
        !            51:
        !            52: struct cfdriver acpimadt_cd = {
        !            53:        NULL, "acpimadt", DV_DULL
        !            54: };
        !            55:
        !            56: void acpimadt_cfg_intr(int, u_int32_t *);
        !            57: int acpimadt_print(void *, const char *);
        !            58:
        !            59: int
        !            60: acpimadt_match(struct device *parent, void *match, void *aux)
        !            61: {
        !            62:        struct acpi_attach_args *aaa = aux;
        !            63:        struct acpi_table_header *hdr;
        !            64:
        !            65:        /*
        !            66:         * If we do not have a table, it is not us
        !            67:         */
        !            68:        if (aaa->aaa_table == NULL)
        !            69:                return (0);
        !            70:
        !            71:        /*
        !            72:         * If it is an MADT table, we can attach
        !            73:         */
        !            74:        hdr = (struct acpi_table_header *)aaa->aaa_table;
        !            75:        if (memcmp(hdr->signature, MADT_SIG, sizeof(MADT_SIG) - 1) != 0)
        !            76:                return (0);
        !            77:
        !            78:        return (1);
        !            79: }
        !            80:
        !            81: struct mp_bus acpimadt_busses[256];
        !            82: struct mp_bus acpimadt_isa_bus;
        !            83:
        !            84: void
        !            85: acpimadt_cfg_intr(int flags, u_int32_t *redir)
        !            86: {
        !            87:        int mpspo = flags & 0x03; /* XXX magic */
        !            88:        int mpstrig = (flags >> 2) & 0x03; /* XXX magic */
        !            89:
        !            90:        *redir &= ~IOAPIC_REDLO_DEL_MASK;
        !            91:        switch (mpspo) {
        !            92:        case MPS_INTPO_DEF:
        !            93:        case MPS_INTPO_ACTHI:
        !            94:                *redir &= ~IOAPIC_REDLO_ACTLO;
        !            95:                break;
        !            96:        case MPS_INTPO_ACTLO:
        !            97:                *redir |= IOAPIC_REDLO_ACTLO;
        !            98:                break;
        !            99:        default:
        !           100:                panic("unknown MPS interrupt polarity %d", mpspo);
        !           101:        }
        !           102:
        !           103:        *redir |= (IOAPIC_REDLO_DEL_LOPRI << IOAPIC_REDLO_DEL_SHIFT);
        !           104:
        !           105:        switch (mpstrig) {
        !           106:        case MPS_INTTR_LEVEL:
        !           107:                *redir |= IOAPIC_REDLO_LEVEL;
        !           108:                break;
        !           109:        case MPS_INTTR_DEF:
        !           110:        case MPS_INTTR_EDGE:
        !           111:                *redir &= ~IOAPIC_REDLO_LEVEL;
        !           112:                break;
        !           113:        default:
        !           114:                panic("unknown MPS interrupt trigger %d", mpstrig);
        !           115:        }
        !           116: }
        !           117:
        !           118: static u_int8_t lapic_map[256];
        !           119:
        !           120: void
        !           121: acpimadt_attach(struct device *parent, struct device *self, void *aux)
        !           122: {
        !           123:        struct acpi_softc *acpi_sc = (struct acpi_softc *)parent;
        !           124:        struct device *mainbus = parent->dv_parent;
        !           125:        struct acpi_attach_args *aaa = aux;
        !           126:        struct acpi_madt *madt = (struct acpi_madt *)aaa->aaa_table;
        !           127:        caddr_t addr = (caddr_t)(madt + 1);
        !           128:        struct aml_node *node;
        !           129:        struct aml_value arg;
        !           130:        struct mp_intr_map *map;
        !           131:        struct ioapic_softc *apic;
        !           132:        int cpu_role = CPU_ROLE_BP;
        !           133:        int nlapic_nmis = 0;
        !           134:        int pin;
        !           135:
        !           136:        printf(" addr 0x%x", madt->local_apic_address);
        !           137:        if (madt->flags & ACPI_APIC_PCAT_COMPAT)
        !           138:                printf(": PC-AT compat");
        !           139:        printf("\n");
        !           140:
        !           141:        /* Tell the BIOS we will be using APIC mode. */
        !           142:        node = aml_searchname(NULL, "\\_PIC");
        !           143:        if (node == 0)
        !           144:                return;
        !           145:        memset(&arg, 0, sizeof(arg));
        !           146:        arg.type = AML_OBJTYPE_INTEGER;
        !           147:        arg.v_integer = 1;
        !           148:        aml_evalnode(acpi_sc, node, 1, &arg, NULL);
        !           149:
        !           150:        mp_busses = acpimadt_busses;
        !           151:        mp_isa_bus = &acpimadt_isa_bus;
        !           152:
        !           153:        lapic_boot_init(madt->local_apic_address);
        !           154:
        !           155:        /* 1st pass, get CPUs and IOAPICs */
        !           156:        while (addr < (caddr_t)madt + madt->hdr.length) {
        !           157:                union acpi_madt_entry *entry = (union acpi_madt_entry *)addr;
        !           158:
        !           159:                switch (entry->madt_lapic.apic_type) {
        !           160:                case ACPI_MADT_LAPIC:
        !           161:                        dprintf("%s: LAPIC: acpi_proc_id %x, apic_id %x, flags 0x%x\n",
        !           162:                            self->dv_xname, entry->madt_lapic.acpi_proc_id,
        !           163:                            entry->madt_lapic.apic_id,
        !           164:                            entry->madt_lapic.flags);
        !           165:
        !           166:                        lapic_map[entry->madt_lapic.acpi_proc_id] =
        !           167:                            entry->madt_lapic.apic_id;
        !           168:
        !           169:                        {
        !           170:                                struct cpu_attach_args caa;
        !           171:
        !           172:                                if ((entry->madt_lapic.flags & ACPI_PROC_ENABLE) == 0)
        !           173:                                        break;
        !           174:
        !           175:                                memset(&caa, 0, sizeof(struct cpu_attach_args));
        !           176:                                caa.cpu_role = cpu_role;
        !           177:                                caa.caa_name = "cpu";
        !           178:                                caa.cpu_number = entry->madt_lapic.apic_id;
        !           179:                                caa.cpu_func = &mp_cpu_funcs;
        !           180: #ifdef __i386__
        !           181:                                extern int cpu_id, cpu_feature;
        !           182:                                caa.cpu_signature = cpu_id;
        !           183:                                caa.feature_flags = cpu_feature;
        !           184: #endif
        !           185:
        !           186:                                config_found(mainbus, &caa, acpimadt_print);
        !           187:
        !           188:                                cpu_role = CPU_ROLE_AP;
        !           189:                        }
        !           190:                        break;
        !           191:                case ACPI_MADT_IOAPIC:
        !           192:                        dprintf("%s: IOAPIC: acpi_ioapic_id %x, address 0x%x, global_int_base 0x%x\n",
        !           193:                            self->dv_xname, entry->madt_ioapic.acpi_ioapic_id,
        !           194:                            entry->madt_ioapic.address,
        !           195:                            entry->madt_ioapic.global_int_base);
        !           196:
        !           197:                        {
        !           198:                                struct apic_attach_args aaa;
        !           199:
        !           200:                                memset(&aaa, 0, sizeof(struct apic_attach_args));
        !           201:                                aaa.aaa_name = "ioapic";
        !           202:                                aaa.apic_id = entry->madt_ioapic.acpi_ioapic_id;
        !           203:                                aaa.apic_address = entry->madt_ioapic.address;
        !           204:                                aaa.apic_vecbase = entry->madt_ioapic.global_int_base;
        !           205:
        !           206:                                config_found(mainbus, &aaa, acpimadt_print);
        !           207:                        }
        !           208:                        break;
        !           209:                case ACPI_MADT_LAPIC_NMI:
        !           210:                        nlapic_nmis++;
        !           211:                        break;
        !           212:                }
        !           213:                addr += entry->madt_lapic.length;
        !           214:        }
        !           215:
        !           216:        mp_intrs = malloc(nlapic_nmis * sizeof (struct mp_intr_map), M_DEVBUF, M_NOWAIT);
        !           217:        if (mp_intrs == NULL)
        !           218:                return;
        !           219:
        !           220:        /* 2nd pass, get interrupt overrides */
        !           221:        addr = (caddr_t)(madt + 1);
        !           222:        while (addr < (caddr_t)madt + madt->hdr.length) {
        !           223:                union acpi_madt_entry *entry = (union acpi_madt_entry *)addr;
        !           224:
        !           225:                switch (entry->madt_lapic.apic_type) {
        !           226:                case ACPI_MADT_LAPIC:
        !           227:                case ACPI_MADT_IOAPIC:
        !           228:                        break;
        !           229:
        !           230:                case ACPI_MADT_OVERRIDE:
        !           231:                        dprintf("%s: OVERRIDE: bus %x, source %x, global_int %x, flags %x\n",
        !           232:                            self->dv_xname, entry->madt_override.bus,
        !           233:                            entry->madt_override.source,
        !           234:                            entry->madt_override.global_int,
        !           235:                            entry->madt_override.flags);
        !           236:
        !           237:                        pin = entry->madt_override.global_int;
        !           238:                        apic = ioapic_find_bybase(pin);
        !           239:
        !           240:                        map = malloc(sizeof (struct mp_intr_map), M_DEVBUF, M_NOWAIT);
        !           241:                        if (map == NULL)
        !           242:                                return;
        !           243:
        !           244:                        memset(map, 0, sizeof *map);
        !           245:                        map->ioapic = apic;
        !           246:                        map->ioapic_pin = pin - apic->sc_apic_vecbase;
        !           247:                        map->bus_pin = entry->madt_override.source;
        !           248:                        map->flags = entry->madt_override.flags;
        !           249: #ifdef __amd64__ /* XXX        */
        !           250:                        map->global_int = entry->madt_override.global_int;
        !           251: #endif
        !           252:                        acpimadt_cfg_intr(entry->madt_override.flags, &map->redir);
        !           253:
        !           254:                        map->ioapic_ih = APIC_INT_VIA_APIC |
        !           255:                            ((apic->sc_apicid << APIC_INT_APIC_SHIFT) |
        !           256:                            (pin << APIC_INT_PIN_SHIFT));
        !           257:
        !           258:                        apic->sc_pins[pin].ip_map = map;
        !           259:
        !           260:                        map->next = mp_isa_bus->mb_intrs;
        !           261:                        mp_isa_bus->mb_intrs = map;
        !           262:                        break;
        !           263:
        !           264:                case ACPI_MADT_LAPIC_NMI:
        !           265:                        dprintf("%s: LAPIC_NMI: acpi_proc_id %x, local_apic_lint %x, flags %x\n",
        !           266:                            self->dv_xname, entry->madt_lapic_nmi.acpi_proc_id,
        !           267:                            entry->madt_lapic_nmi.local_apic_lint,
        !           268:                            entry->madt_lapic_nmi.flags);
        !           269:
        !           270:                        pin = entry->madt_lapic_nmi.local_apic_lint;
        !           271:
        !           272:                        map = &mp_intrs[mp_nintrs++];
        !           273:                        memset(map, 0, sizeof *map);
        !           274:                        map->cpu_id = lapic_map[entry->madt_lapic_nmi.acpi_proc_id];
        !           275:                        map->ioapic_pin = pin;
        !           276:                        map->flags = entry->madt_lapic_nmi.flags;
        !           277:
        !           278:                        acpimadt_cfg_intr(entry->madt_lapic_nmi.flags, &map->redir);
        !           279:                        map->redir &= ~IOAPIC_REDLO_DEL_MASK;
        !           280:                        map->redir |= (IOAPIC_REDLO_DEL_NMI << IOAPIC_REDLO_DEL_SHIFT);
        !           281:                        break;
        !           282:
        !           283:                default:
        !           284:                        printf("%s: unknown apic structure type %x\n",
        !           285:                            self->dv_xname, entry->madt_lapic.apic_type);
        !           286:                }
        !           287:
        !           288:                addr += entry->madt_lapic.length;
        !           289:        }
        !           290:
        !           291:        for (pin = 0; pin < ICU_LEN; pin++) {
        !           292:                apic = ioapic_find_bybase(pin);
        !           293:                if (apic->sc_pins[pin].ip_map != NULL)
        !           294:                        continue;
        !           295:
        !           296:                map = malloc(sizeof (struct mp_intr_map), M_DEVBUF, M_NOWAIT);
        !           297:                if (map == NULL)
        !           298:                        return;
        !           299:
        !           300:                memset(map, 0, sizeof *map);
        !           301:                map->ioapic = apic;
        !           302:                map->ioapic_pin = pin;
        !           303:                map->bus_pin = pin;
        !           304: #ifdef __amd64__ /* XXX */
        !           305:                map->global_int = -1;
        !           306: #endif
        !           307:                map->redir = (IOAPIC_REDLO_DEL_LOPRI << IOAPIC_REDLO_DEL_SHIFT);
        !           308:
        !           309:                map->ioapic_ih = APIC_INT_VIA_APIC |
        !           310:                    ((apic->sc_apicid << APIC_INT_APIC_SHIFT) |
        !           311:                    (pin << APIC_INT_PIN_SHIFT));
        !           312:
        !           313:                apic->sc_pins[pin].ip_map = map;
        !           314:
        !           315:                map->next = mp_isa_bus->mb_intrs;
        !           316:                mp_isa_bus->mb_intrs = map;
        !           317:        }
        !           318: }
        !           319:
        !           320: int
        !           321: acpimadt_print(void *aux, const char *pnp)
        !           322: {
        !           323:        struct apic_attach_args *aaa = aux;
        !           324:
        !           325:        if (pnp)
        !           326:                printf("%s at %s:", aaa->aaa_name, pnp);
        !           327:
        !           328:        return (UNCONF);
        !           329: }

CVSweb