Пример #1
0
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;
}
Пример #2
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
}
Пример #3
0
Файл: mpbios.c Проект: bluhm/sys
/*
 * 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
}
Пример #4
0
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++]);
	}
}
Пример #5
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(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;
}
Пример #6
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;
}