const void * mpbios_search(device_t self, paddr_t start, int count, struct mp_map *map) { struct mp_map t; int i, len; const struct mpbios_fps *m; int end = count - sizeof(*m); const uint8_t *base = mpbios_map (start, count, &t); if (mp_verbose) aprint_verbose_dev(self, "scanning 0x%jx to 0x%jx for MP signature\n", (uintmax_t)start, (uintmax_t)(start+count-sizeof(*m))); for (i = 0; i <= end; i += 4) { m = (const struct mpbios_fps *)&base[i]; if ((m->signature == MP_FP_SIG) && ((len = m->length << 4) != 0) && mpbios_cksum(m, (m->length << 4)) == 0) { mpbios_unmap (&t); return mpbios_map (start+i, len, map); } } mpbios_unmap(&t); return 0; }
const void * mpbios_search(struct device *self, paddr_t start, int count, struct mp_map *map) { struct mp_map t; int i, len; const struct mpbios_fps *m; int end = count - sizeof(*m); const u_int8_t *base = mpbios_map(start, count, &t); if (mp_verbose) printf("%s: scanning 0x%lx to 0x%lx for MP signature\n", self->dv_xname, start, start + count - sizeof(*m)); for (i = 0; i <= end; i += 4) { m = (struct mpbios_fps *)&base[i]; if ((m->signature == MP_FP_SIG) && ((len = m->length << 4) != 0) && mpbios_cksum(m, (m->length << 4)) == 0) { mpbios_unmap(&t); return (mpbios_map(start + i, len, map)); } } mpbios_unmap(&t); return (0); }
/* * 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 }
/* * Look for an Intel MP spec table, indicating SMP capable hardware. */ int mpbios_probe(struct device *self) { paddr_t ebda, memtop; paddr_t cthpa; int cthlen; const u_int8_t *mpbios_page; int scan_loc; struct mp_map t; /* * Skip probe if someone else (e.g. acpi) already provided the * necessary details. */ if (mp_busses) return (0); /* see if EBDA exists */ mpbios_page = mpbios_map(0, PAGE_SIZE, &t); /* XXX Ugly magic constants below. */ ebda = *(const u_int16_t *)(&mpbios_page[0x40e]); ebda <<= 4; memtop = *(const u_int16_t *)(&mpbios_page[0x413]); memtop <<= 10; mpbios_page = NULL; mpbios_unmap(&t); scan_loc = 0; if (ebda && ebda < IOM_BEGIN ) { mp_fps = mpbios_search(self, ebda, 1024, &mp_fp_map); if (mp_fps != NULL) goto found; } scan_loc = 1; if (memtop && memtop <= IOM_BEGIN ) { mp_fps = mpbios_search(self, memtop - 1024, 1024, &mp_fp_map); if (mp_fps != NULL) goto found; } scan_loc = 2; mp_fps = mpbios_search(self, BIOS_BASE, BIOS_COUNT, &mp_fp_map); if (mp_fps != NULL) goto found; /* nothing found */ return (0); found: if (mp_verbose) printf("%s: MP floating pointer found in %s at 0x%lx\n", self->dv_xname, loc_where[scan_loc], mp_fp_map.pa); if (mp_fps->pap == 0) { if (mp_fps->mpfb1 == 0) { printf("%s: MP fps invalid: " "no default config and no configuration table\n", self->dv_xname); goto err; } printf("%s: MP default configuration %d\n", self->dv_xname, mp_fps->mpfb1); return (10); } cthpa = mp_fps->pap; mp_cth = mpbios_map(cthpa, sizeof (*mp_cth), &mp_cfg_table_map); cthlen = mp_cth->base_len; mpbios_unmap(&mp_cfg_table_map); mp_cth = mpbios_map(cthpa, cthlen, &mp_cfg_table_map); if (mp_verbose) printf("%s: MP config table at 0x%lx, %d bytes long\n", self->dv_xname, cthpa, cthlen); if (mp_cth->signature != MP_CT_SIG) { printf("%s: MP signature mismatch (%x vs %x)\n", self->dv_xname, MP_CT_SIG, mp_cth->signature); goto err; } if (mpbios_cksum(mp_cth, cthlen)) { printf ("%s: MP Configuration Table checksum mismatch\n", self->dv_xname); goto err; } return (10); err: if (mp_fps) { mp_fps = NULL; mpbios_unmap(&mp_fp_map); } if (mp_cth) { mp_cth = NULL; mpbios_unmap(&mp_cfg_table_map); } return (0); }
/* * 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 }
/* * 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; }
/* * Look for an Intel MP spec table, indicating SMP capable hardware. */ int mpbios_probe(device_t self) { paddr_t ebda, memtop; paddr_t cthpa; int cthlen; const uint8_t *mpbios_page; int scan_loc; struct mp_map t; /* If MP is disabled, don't use MPBIOS or the ioapics. */ if ((boothowto & RB_MD1) != 0) return 0; /* see if EBDA exists */ mpbios_page = mpbios_map (0, PAGE_SIZE, &t); ebda = *(const uint16_t *) (&mpbios_page[0x40e]); ebda <<= 4; memtop = *(const uint16_t *) (&mpbios_page[0x413]); memtop <<= 10; mpbios_page = NULL; mpbios_unmap(&t); scan_loc = 0; if (ebda && ebda < IOM_BEGIN ) { mp_fps = mpbios_search(self, ebda, 1024, &mp_fp_map); if (mp_fps != NULL) goto found; } scan_loc = 1; if (memtop && memtop <= IOM_BEGIN ) { mp_fps = mpbios_search(self, memtop - 1024, 1024, &mp_fp_map); if (mp_fps != NULL) goto found; } scan_loc = 2; mp_fps = mpbios_search(self, BIOS_BASE, BIOS_COUNT, &mp_fp_map); if (mp_fps != NULL) goto found; /* nothing found */ return 0; found: if (mp_verbose) aprint_verbose_dev(self, "MP floating pointer found in %s at 0x%jx\n", loc_where[scan_loc], (uintmax_t)mp_fp_map.pa); if (mp_fps->pap == 0) { if (mp_fps->mpfb1 == 0) { aprint_error_dev(self, "MP fps invalid: " "no default config and no configuration table\n"); goto err; } return 10; } cthpa = mp_fps->pap; mp_cth = mpbios_map (cthpa, sizeof (*mp_cth), &mp_cfg_table_map); cthlen = mp_cth->base_len; mpbios_unmap(&mp_cfg_table_map); mp_cth = mpbios_map (cthpa, cthlen, &mp_cfg_table_map); if (mp_verbose) aprint_verbose_dev(self, "MP config table at 0x%jx, %d bytes long\n", (uintmax_t)cthpa, cthlen); if (mp_cth->signature != MP_CT_SIG) { aprint_error_dev(self, "MP signature mismatch (%x vs %x)\n", MP_CT_SIG, mp_cth->signature); goto err; } if (mpbios_cksum(mp_cth, cthlen)) { aprint_error_dev(self, "MP Configuration Table checksum mismatch\n"); goto err; } return 10; err: if (mp_fps) { mp_fps = NULL; mpbios_unmap(&mp_fp_map); } if (mp_cth) { mp_cth = NULL; mpbios_unmap(&mp_cfg_table_map); } return 0; }
/* * 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; }