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