int mpbios_invent(int irq, int type, int bus) { struct mp_intr_map *mip; struct mpbios_int e; e.type = MPS_MCT_IOINT; e.int_type = MPS_INTTYPE_INT; switch (type) { case IST_EDGE: e.int_flags = MPS_INT(MPS_INTPO_ACTHI, MPS_INTTR_EDGE); break; case IST_LEVEL: e.int_flags = MPS_INT(MPS_INTPO_ACTLO, MPS_INTTR_LEVEL); break; case IST_NONE: case IST_PULSE: e.int_flags = MPS_INT(MPS_INTPO_DEF, MPS_INTTR_DEF); break; } e.src_bus_id = bus; e.src_bus_irq = irq; e.dst_apic_id = mp_busses[bus].mb_intrs->ioapic->sc_apicid; e.dst_apic_int = irq; if (mpbios_int((const u_int8_t *)&e, &mp_intrs[mp_nintrs]) == 0) { mip = &mp_intrs[mp_nintrs++]; return (mip->ioapic_ih | irq); } return irq; }
/* * 1st pass on BIOS's Intel MP specification table. * * initializes: * mp_ncpus = 1 * * determines: * cpu_apic_address (common to all CPUs) * ioapic_address[N] * mp_naps * mp_nbusses * mp_napics * nintrs */ void mpbios_scan(struct device *self) { const u_int8_t *position, *end; int count; int type; int intr_cnt, cur_intr; paddr_t lapic_base; const struct mpbios_int *iep; struct mpbios_int ie; struct ioapic_softc *sc; printf(": Intel MP Specification 1.%d\n", mp_fps->spec_rev); /* * looks like we've got a MP system. start setting up * infrastructure.. * XXX is this the right place?? */ lapic_base = LAPIC_BASE; if (mp_cth != NULL) lapic_base = (paddr_t)mp_cth->apic_address; lapic_boot_init(lapic_base); /* check for use of 'default' configuration */ if (mp_fps->mpfb1 != 0) { struct mpbios_proc pe; printf("%s: MP default configuration %d\n", self->dv_xname, mp_fps->mpfb1); /* use default addresses */ pe.apic_id = lapic_cpu_number(); pe.cpu_flags = PROCENTRY_FLAG_EN|PROCENTRY_FLAG_BP; pe.cpu_signature = cpu_info_primary.ci_signature; pe.feature_flags = cpu_info_primary.ci_feature_flags; mpbios_cpu((u_int8_t *)&pe, self); pe.apic_id = 1 - lapic_cpu_number(); pe.cpu_flags = PROCENTRY_FLAG_EN; mpbios_cpu((u_int8_t *)&pe, self); mpbios_ioapic((u_int8_t *)&default_ioapic, self); /* XXX */ printf("%s: WARNING: interrupts not configured\n", self->dv_xname); panic("lazy bum"); return; } else { /* * should not happen; mp_probe returns 0 in this case, * but.. */ if (mp_cth == NULL) panic("mpbios_scan: no config (can't happen?)"); /* * Walk the table once, counting items */ position = (const u_int8_t *)(mp_cth); end = position + mp_cth->base_len; position += sizeof(*mp_cth); count = mp_cth->entry_count; intr_cnt = 0; while ((count--) && (position < end)) { type = *position; if (type >= MPS_MCT_NTYPES) { printf("%s: unknown entry type %x" " in MP config table\n", self->dv_xname, type); break; } mp_conf[type].count++; if (type == MPS_MCT_BUS) { const struct mpbios_bus *bp = (const struct mpbios_bus *)position; if (bp->bus_id >= mp_nbusses) mp_nbusses = bp->bus_id + 1; } /* * Count actual interrupt instances. * dst_apic_id of MPS_ALL_APICS means "wired to all * apics of this type". */ if (type == MPS_MCT_IOINT) { iep = (const struct mpbios_int *)position; if (iep->dst_apic_id == MPS_ALL_APICS) intr_cnt += mp_conf[MPS_MCT_IOAPIC].count; else intr_cnt++; } else if (type == MPS_MCT_LINT) intr_cnt++; position += mp_conf[type].length; } mp_busses = malloc(sizeof(struct mp_bus) * mp_nbusses, M_DEVBUF, M_NOWAIT|M_ZERO); mp_intrs = malloc(sizeof(struct mp_intr_map) * intr_cnt, M_DEVBUF, M_NOWAIT); /* re-walk the table, recording info of interest */ position = (const u_int8_t *)mp_cth + sizeof(*mp_cth); count = mp_cth->entry_count; cur_intr = 0; while ((count--) && (position < end)) { switch (type = *(u_char *)position) { case MPS_MCT_CPU: mpbios_cpu(position, self); break; case MPS_MCT_BUS: mpbios_bus(position, self); break; case MPS_MCT_IOAPIC: mpbios_ioapic(position, self); break; case MPS_MCT_IOINT: iep = (const struct mpbios_int *)position; ie = *iep; if (iep->dst_apic_id == MPS_ALL_APICS) { for (sc = ioapics ; sc != NULL; sc = sc->sc_next) { ie.dst_apic_id = sc->sc_apicid; if (mpbios_int((char *)&ie, type, &mp_intrs[cur_intr]) == 0) cur_intr++; } } else { if (mpbios_int(position, type, &mp_intrs[cur_intr]) == 0) cur_intr++; } break; case MPS_MCT_LINT: if (mpbios_int(position, type, &mp_intrs[cur_intr]) == 0) cur_intr++; break; default: printf("%s: unknown entry type %x " "in MP config table\n", self->dv_xname, type); /* NOTREACHED */ return; } position += mp_conf[type].length; } mp_nintrs = cur_intr; if (mp_verbose && mp_cth->ext_len) printf("%s: MP WARNING: %d " "bytes of extended entries not examined\n", self->dv_xname, mp_cth->ext_len); } /* Clean up. */ mp_fps = NULL; mpbios_unmap(&mp_fp_map); if (mp_cth != NULL) { mp_cth = NULL; mpbios_unmap(&mp_cfg_table_map); } mpbios_scanned = 1; #if NPCI > 0 mpbios_intr_fixup(); #endif }
/* * 1st pass on BIOS's Intel MP specification table. * * initializes: * mp_ncpus = 1 * * determines: * cpu_apic_address (common to all CPUs) * ioapic_address[N] * mp_naps * mp_nbusses * mp_napics * nintrs */ void mpbios_scan(struct device *self) { const u_int8_t *position, *end; int count; int type; int intr_cnt; paddr_t lapic_base; printf(": Intel MP Specification 1.%d\n", mp_fps->spec_rev); /* * looks like we've got a MP system. start setting up * infrastructure.. * XXX is this the right place?? */ lapic_base = LAPIC_BASE; if (mp_cth != NULL) lapic_base = (paddr_t)mp_cth->apic_address; lapic_boot_init(lapic_base); /* * Walk the table once, counting items */ for (count = mp_cth->entry_count, position = (const u_int8_t *)mp_cth + sizeof(*mp_cth), end = position + mp_cth->base_len; count-- && position < end; position += mp_conf[type].length) { type = *position; if (type >= MPS_MCT_NTYPES) { printf("%s: unknown entry type %x" " in MP config table\n", self->dv_xname, type); end = position; break; } mp_conf[type].count++; } /* * Walk the table twice, counting int and bus entries */ for (count = mp_cth->entry_count, intr_cnt = 15, /* presume all isa irqs missing */ position = (const u_int8_t *)mp_cth + sizeof(*mp_cth); count-- && position < end; position += mp_conf[type].length) { type = *position; if (type == MPS_MCT_BUS) { const struct mpbios_bus *bp = (const struct mpbios_bus *)position; if (bp->bus_id >= mp_nbusses) mp_nbusses = bp->bus_id + 1; } /* * Count actual interrupt instances. * dst_apic_id of MPS_ALL_APICS means "wired to all * apics of this type". */ if ((type == MPS_MCT_IOINT) || (type == MPS_MCT_LINT)) { const struct mpbios_int *ie = (const struct mpbios_int *)position; if (ie->dst_apic_id != MPS_ALL_APICS) intr_cnt++; else if (type == MPS_MCT_IOINT) intr_cnt += mp_conf[MPS_MCT_IOAPIC].count; else intr_cnt += mp_conf[MPS_MCT_CPU].count; } } mp_busses = mallocarray(mp_nbusses, sizeof(struct mp_bus), M_DEVBUF, M_WAITOK|M_ZERO); mp_intrs = mallocarray(intr_cnt, sizeof(struct mp_intr_map), M_DEVBUF, M_WAITOK); /* re-walk the table, recording info of interest */ position = (const u_int8_t *)mp_cth + sizeof(*mp_cth); count = mp_cth->entry_count; mp_nintrs = 0; while ((count--) && (position < end)) { switch (type = *(u_char *)position) { case MPS_MCT_CPU: mpbios_cpu(position, self); break; case MPS_MCT_BUS: mpbios_bus(position, self); break; case MPS_MCT_IOAPIC: mpbios_ioapic(position, self); break; case MPS_MCT_IOINT: case MPS_MCT_LINT: if (mpbios_int(position, &mp_intrs[mp_nintrs]) == 0) mp_nintrs++; break; default: printf("%s: unknown entry type %x " "in MP config table\n", self->dv_xname, type); /* NOTREACHED */ return; } position += mp_conf[type].length; } if (mp_verbose && mp_cth->ext_len) printf("%s: MP WARNING: %d " "bytes of extended entries not examined\n", self->dv_xname, mp_cth->ext_len); /* Clean up. */ mp_fps = NULL; mpbios_unmap(&mp_fp_map); if (mp_cth != NULL) { mp_cth = NULL; mpbios_unmap(&mp_cfg_table_map); } #if NPCI > 0 if (pci_mode_detect() != 0) mpbios_intr_fixup(); #endif }
static void mpbios_dflt_conf_int(device_t self, const struct dflt_conf_entry *dflt_conf, const int *dflt_bus_irq) { struct mpbios_int mpi; size_t i; int cur_intr; uint16_t level_inv; cur_intr = 0; /* * INTIN0 */ /* * 8259A INTR is connected to INTIN0 for default configs 1-6, but not * for default config 7 (sec. 5.3). */ if ((dflt_conf->flags & INTIN0_NC) == 0) { /* mpi.type is irrelevant for mpbios_int(). */ mpi.int_type = MPS_INTTYPE_ExtINT; mpi.int_flags = 0; mpi.src_bus_id = 0; mpi.src_bus_irq = 0; mpi.dst_apic_id = DFLT_IOAPIC_ID; mpi.dst_apic_int = 0; mpbios_int((u_int8_t *)&mpi, MPS_MCT_IOINT, &mp_intrs[cur_intr++]); } /* * INTINx */ /* mpi.type is irrelevant for mpbios_int(). */ mpi.int_type = MPS_INTTYPE_INT; /* * PCI interrupt lines appear as (E)ISA interrupt lines/on bus 0 * (sec. 5.2). */ mpi.src_bus_id = 0; mpi.dst_apic_id = DFLT_IOAPIC_ID; /* * Compliant systems must convert active-low, level-triggered interrupts * to active-high by external inverters before INTINx (table 5-1; * sec. 5.3.2). */ if (dflt_conf->flags & ELCR_INV) { #ifdef X86_MPBIOS_SUPPORT_EISA /* Systems with ELCRs use them to control the inverters. */ level_inv = ((uint16_t)inb(ELCR1) << 8) | inb(ELCR0); #else level_inv = 0; #endif } else if (dflt_conf->flags & MCA_INV) { /* MCA systems have fixed inverters. */ level_inv = 0xffffU; } else { level_inv = 0; } for (i = 0; i < __arraycount(dflt_bus_irq_tab[0]); i++) { if (dflt_bus_irq[i] >= 0) { mpi.src_bus_irq = (uint8_t)dflt_bus_irq[i]; if (level_inv & (1U << mpi.src_bus_irq)) mpi.int_flags = (MPS_INTTR_LEVEL << 2) | MPS_INTPO_ACTHI; else mpi.int_flags = 0; /* conforms to bus spec. */ mpi.dst_apic_int = (uint8_t)i; mpbios_int((u_int8_t *)&mpi, MPS_MCT_IOINT, &mp_intrs[cur_intr++]); } } /* * LINTINx */ /* mpi.type is irrelevant for mpbios_int(). */ mpi.int_flags = 0; mpi.src_bus_id = 0; mpi.src_bus_irq = 0; mpi.dst_apic_id = MPS_ALL_APICS; for (i = 0; i < __arraycount(dflt_lint_tab); i++) { mpi.int_type = dflt_lint_tab[i]; mpi.dst_apic_int = (uint8_t)i; mpbios_int((u_int8_t *)&mpi, MPS_MCT_LINT, &mp_intrs[cur_intr++]); } }
/* * 1st pass on BIOS's Intel MP specification table. * * initializes: * mp_ncpus = 1 * * determines: * cpu_apic_address (common to all CPUs) * ioapic_address[N] * mp_naps * mp_nbus * mp_napics * nintrs */ void mpbios_scan(device_t self, int *ncpup) { const uint8_t *position, *end; size_t i; int count; int type; int intr_cnt, cur_intr; paddr_t lapic_base; const struct dflt_conf_entry *dflt_conf; const int *dflt_bus_irq; const struct mpbios_int *iep; struct mpbios_int ie; aprint_normal_dev(self, "Intel MP Specification "); switch (mp_fps->spec_rev) { case 1: aprint_normal("(Version 1.1)"); break; case 4: aprint_normal("(Version 1.4)"); break; default: aprint_normal("(unrecognized rev %d)", mp_fps->spec_rev); } /* * looks like we've got a MP system. start setting up * infrastructure.. * XXX is this the right place?? */ #if NACPICA > 0 if (mpacpi_ncpu == 0) { #endif lapic_base = LAPIC_BASE; if (mp_cth != NULL) lapic_base = (paddr_t)mp_cth->apic_address; #if NLAPIC > 0 lapic_boot_init(lapic_base); #endif #if NACPICA > 0 } #endif /* check for use of 'default' configuration */ if (mp_fps->mpfb1 != 0) { if (mp_fps->mpfb1 > __arraycount(dflt_conf_tab)) panic("Unsupported MP default configuration %d\n", mp_fps->mpfb1); aprint_normal("\n"); aprint_normal_dev(self, "MP default configuration %d\n", mp_fps->mpfb1); dflt_conf = &dflt_conf_tab[mp_fps->mpfb1 - 1]; dflt_bus_irq = dflt_bus_irq_tab[(dflt_conf->flags & IRQ_VAR) != 0]; #if NACPICA > 0 if (mpacpi_ncpu == 0) #endif mpbios_dflt_conf_cpu(self); #if NACPICA > 0 if (mpacpi_nioapic == 0) #endif mpbios_dflt_conf_ioapic(self); /* * Walk the table once, counting items. */ mp_nbus = 0; for (i = 0; i < __arraycount(dflt_conf->bus_type); i++) { if (dflt_conf->bus_type[i] != NULL) mp_nbus++; } KASSERT(mp_nbus != 0); mp_busses = kmem_zalloc(sizeof(struct mp_bus) * mp_nbus, KM_SLEEP); KASSERT(mp_busses != NULL); /* INTIN0 */ intr_cnt = (dflt_conf->flags & INTIN0_NC) ? 0 : 1; /* INTINx */ for (i = 0; i < __arraycount(dflt_bus_irq_tab[0]); i++) { if (dflt_bus_irq[i] >= 0) intr_cnt++; } KASSERT(intr_cnt != 0); /* LINTINx */ for (i = 0; i < __arraycount(dflt_lint_tab); i++) intr_cnt++; mp_intrs = kmem_zalloc(sizeof(struct mp_intr_map) * intr_cnt, KM_SLEEP); KASSERT(mp_intrs != NULL); mp_nintr = intr_cnt; /* * Re-walk the table, recording info of interest. */ mpbios_dflt_conf_bus(self, dflt_conf); mpbios_dflt_conf_int(self, dflt_conf, dflt_bus_irq); } else { /* * should not happen; mp_probe returns 0 in this case, * but.. */ if (mp_cth == NULL) panic ("mpbios_scan: no config (can't happen?)"); printf(" (%8.8s %12.12s)\n", mp_cth->oem_id, mp_cth->product_id); /* * Walk the table once, counting items */ position = (const uint8_t *)(mp_cth); end = position + mp_cth->base_len; position += sizeof(*mp_cth); count = mp_cth->entry_count; intr_cnt = 0; while ((count--) && (position < end)) { type = *position; if (type >= MPS_MCT_NTYPES) { aprint_error_dev(self, "unknown entry type %x" " in MP config table\n", type); break; } mp_conf[type].count++; if (type == MPS_MCT_BUS) { const struct mpbios_bus *bp = (const struct mpbios_bus *)position; if (bp->bus_id >= mp_nbus) mp_nbus = bp->bus_id + 1; } /* * Count actual interrupt instances. * dst_apic_id of MPS_ALL_APICS means "wired to all * apics of this type". */ if (type == MPS_MCT_IOINT) { iep = (const struct mpbios_int *)position; if (iep->dst_apic_id == MPS_ALL_APICS) intr_cnt += mp_conf[MPS_MCT_IOAPIC].count; else intr_cnt++; } else if (type == MPS_MCT_LINT) intr_cnt++; position += mp_conf[type].length; } mp_busses = kmem_zalloc(sizeof(struct mp_bus)*mp_nbus, KM_SLEEP); KASSERT(mp_busses != NULL); mp_intrs = kmem_zalloc(sizeof(struct mp_intr_map)*intr_cnt, KM_SLEEP); KASSERT(mp_intrs != NULL); mp_nintr = intr_cnt; /* re-walk the table, recording info of interest */ position = (const uint8_t *) mp_cth + sizeof(*mp_cth); count = mp_cth->entry_count; cur_intr = 0; while ((count--) && (position < end)) { switch (type = *position) { case MPS_MCT_CPU: #if NACPICA > 0 /* ACPI has done this for us */ if (mpacpi_ncpu) break; #endif mpbios_cpu(position, self); break; case MPS_MCT_BUS: mpbios_bus(position, self); break; case MPS_MCT_IOAPIC: #if NACPICA > 0 /* ACPI has done this for us */ if (mpacpi_nioapic) break; #endif mpbios_ioapic(position, self); break; case MPS_MCT_IOINT: iep = (const struct mpbios_int *)position; ie = *iep; if (iep->dst_apic_id == MPS_ALL_APICS) { #if NIOAPIC > 0 struct ioapic_softc *sc; for (sc = ioapics ; sc != NULL; sc = sc->sc_next) { ie.dst_apic_id = sc->sc_apicid; mpbios_int((char *)&ie, type, &mp_intrs[cur_intr++]); } #endif } else { mpbios_int(position, type, &mp_intrs[cur_intr++]); } break; case MPS_MCT_LINT: mpbios_int(position, type, &mp_intrs[cur_intr]); cur_intr++; break; default: aprint_error_dev(self, "unknown entry type %x in MP config table\n", type); /* NOTREACHED */ return; } position += mp_conf[type].length; } if (mp_verbose && mp_cth->ext_len) aprint_verbose_dev(self, "MP WARNING: %d bytes of extended entries not examined\n", mp_cth->ext_len); } /* Clean up. */ mp_fps = NULL; mpbios_unmap (&mp_fp_map); if (mp_cth != NULL) { mp_cth = NULL; mpbios_unmap (&mp_cfg_table_map); } mpbios_scanned = 1; *ncpup = mpbios_ncpu; }
/* * 1st pass on BIOS's Intel MP specification table. * * initializes: * mp_ncpus = 1 * * determines: * cpu_apic_address (common to all CPUs) * ioapic_address[N] * mp_naps * mp_nbus * mp_napics * nintrs */ void mpbios_scan(struct device *self, int *ncpup, int *napic) { const uint8_t *position, *end; int count; int type; int intr_cnt, cur_intr; paddr_t lapic_base; const struct mpbios_int *iep; struct mpbios_int ie; aprint_normal_dev(self, "Intel MP Specification "); switch (mp_fps->spec_rev) { case 1: printf("(Version 1.1)"); break; case 4: printf("(Version 1.4)"); break; default: printf("(unrecognized rev %d)", mp_fps->spec_rev); } /* * looks like we've got a MP system. start setting up * infrastructure.. * XXX is this the right place?? */ #if NACPI > 0 if (mpacpi_ncpu == 0) { #endif lapic_base = LAPIC_BASE; if (mp_cth != NULL) lapic_base = (paddr_t)mp_cth->apic_address; #if NLAPIC > 0 lapic_boot_init(lapic_base); #endif #if NACPI > 0 } #endif /* check for use of 'default' configuration */ if (mp_fps->mpfb1 != 0) { aprint_normal("\n"); aprint_normal_dev(self, "MP default configuration %d\n", mp_fps->mpfb1); #if NACPI > 0 if (mpacpi_ncpu == 0) #endif mpbios_cpus(self); #if NACPI > 0 if (mpacpi_nioapic == 0) #endif mpbios_ioapic((uint8_t *)&default_ioapic, self); /* XXX */ aprint_verbose_dev(self, "WARNING: interrupts not configured\n"); /* * XXX rpaulo: I have a machine that can boot, so I * commented this (for now). */ #if 0 panic("lazy bum"); return; #endif } else { /* * should not happen; mp_probe returns 0 in this case, * but.. */ if (mp_cth == NULL) panic ("mpbios_scan: no config (can't happen?)"); printf(" (%8.8s %12.12s)\n", mp_cth->oem_id, mp_cth->product_id); /* * Walk the table once, counting items */ position = (const uint8_t *)(mp_cth); end = position + mp_cth->base_len; position += sizeof(*mp_cth); count = mp_cth->entry_count; intr_cnt = 0; while ((count--) && (position < end)) { type = *position; if (type >= MPS_MCT_NTYPES) { aprint_error_dev(self, "unknown entry type %x" " in MP config table\n", type); break; } mp_conf[type].count++; if (type == MPS_MCT_BUS) { const struct mpbios_bus *bp = (const struct mpbios_bus *)position; if (bp->bus_id >= mp_nbus) mp_nbus = bp->bus_id + 1; } /* * Count actual interrupt instances. * dst_apic_id of MPS_ALL_APICS means "wired to all * apics of this type". */ if (type == MPS_MCT_IOINT) { iep = (const struct mpbios_int *)position; if (iep->dst_apic_id == MPS_ALL_APICS) intr_cnt += mp_conf[MPS_MCT_IOAPIC].count; else intr_cnt++; } else if (type == MPS_MCT_LINT) intr_cnt++; position += mp_conf[type].length; } mp_busses = malloc(sizeof(struct mp_bus)*mp_nbus, M_DEVBUF, M_NOWAIT | M_ZERO); mp_intrs = malloc(sizeof(struct mp_intr_map)*intr_cnt, M_DEVBUF, M_NOWAIT | M_ZERO); mp_nintr = intr_cnt; /* re-walk the table, recording info of interest */ position = (const uint8_t *) mp_cth + sizeof(*mp_cth); count = mp_cth->entry_count; cur_intr = 0; while ((count--) && (position < end)) { switch (type = *position) { case MPS_MCT_CPU: #if NACPI > 0 /* ACPI has done this for us */ if (mpacpi_ncpu) break; #endif mpbios_cpu(position, self); break; case MPS_MCT_BUS: mpbios_bus(position, self); break; case MPS_MCT_IOAPIC: #if NACPI > 0 /* ACPI has done this for us */ if (mpacpi_nioapic) break; #endif mpbios_ioapic(position, self); break; case MPS_MCT_IOINT: iep = (const struct mpbios_int *)position; ie = *iep; if (iep->dst_apic_id == MPS_ALL_APICS) { #if NIOAPIC > 0 struct ioapic_softc *sc; for (sc = ioapics ; sc != NULL; sc = sc->sc_next) { ie.dst_apic_id = sc->sc_apicid; mpbios_int((char *)&ie, type, &mp_intrs[cur_intr++]); } #endif } else { mpbios_int(position, type, &mp_intrs[cur_intr++]); } break; case MPS_MCT_LINT: mpbios_int(position, type, &mp_intrs[cur_intr]); cur_intr++; break; default: aprint_error_dev(self, "unknown entry type %x in MP config table\n", type); /* NOTREACHED */ return; } position += mp_conf[type].length; } if (mp_verbose && mp_cth->ext_len) aprint_verbose_dev(self, "MP WARNING: %d bytes of extended entries not examined\n", mp_cth->ext_len); } /* Clean up. */ mp_fps = NULL; mpbios_unmap (&mp_fp_map); if (mp_cth != NULL) { mp_cth = NULL; mpbios_unmap (&mp_cfg_table_map); } mpbios_scanned = 1; *ncpup = mpbios_ncpu; *napic = mpbios_nioapic; }