[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

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