Index: mpbios.c
===================================================================
RCS file: /data/cvs/src/sys/arch/i386/i386/mpbios.c,v
retrieving revision 1.3
diff -u -r1.3 mpbios.c
--- mpbios.c	23 Jun 2004 17:14:31 -0000	1.3
+++ mpbios.c	2 Jul 2004 18:39:43 -0000
@@ -129,8 +129,10 @@
 #include <dev/eisa/eisavar.h>	/* for ELCR* def'ns */
 
 
+/* set I/O APIC to 2, because 0 and 1 have already been assigned ( APIC ) */
+
 static struct mpbios_ioapic default_ioapic = {
-    2, 0, 1, IOAPICENTRY_FLAG_EN, (caddr_t)IOAPIC_BASE_DEFAULT
+    MPS_MCT_IOAPIC, 2, 1, IOAPICENTRY_FLAG_EN, (caddr_t)IOAPIC_BASE_DEFAULT
 };
 
 /* descriptions of MP basetable entries */
@@ -177,6 +179,8 @@
 void	mpbios_ioapic(const u_int8_t *, struct device *);
 void	mpbios_int(const u_int8_t *, int, struct mp_intr_map *);
 
+int	ELCR_trigger(unsigned int);
+
 const void *mpbios_map(paddr_t, int, struct mp_map *);
 static __inline void mpbios_unmap(struct mp_map *);
 
@@ -484,6 +488,12 @@
 	0
 };
 
+int ELCR_trigger(unsigned int irq)
+{
+	unsigned int elcr_status;
+        elcr_status = inb(ELCR0) | inb(ELCR1) << 8;
+	return((elcr_status & (1<<irq)) != 0);
+}
 
 /*
  * 1st pass on BIOS's Intel MP specification table.
@@ -508,6 +518,7 @@
 	int		type;
 	int		intr_cnt, cur_intr;
 	paddr_t		lapic_base;
+	extern int	cpu_id;
 
 	printf("%s: Intel MP Specification ", self->dv_xname);
 
@@ -537,30 +548,194 @@
 	/* check for use of 'default' configuration */
 	if (mp_fps->mpfb1 != 0) {
 		struct mpbios_proc pe;
+		struct mpbios_bus bus;
+		struct mpbios_int mpi;
+		int i;
+		int useELCR = 0;
 
 		printf("\n%s: MP default configuration %d\n",
 		    self->dv_xname, mp_fps->mpfb1);
 
-		/* use default addresses */
-		pe.apic_id = cpu_number();
+			
+		/* 
+		 * setup cpu 0 
+		 * cpu_info_primary.ci_signature seems to borken though
+		 * it turns out that the netbsd version of locore.s 
+		 * initializes cpu_info_primary, but the openbsd version _does
+		 * not_. Luckily locore.s does initialize cpu_id and 
+		 * cpu_feature and that is exactly what we need. We assume 
+		 * both cpu's are identical
+ 		 */
+
+		pe.apic_id = 0;
 		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;
+		pe.cpu_signature = cpu_id;
+		pe.feature_flags = cpu_feature;
 
 		mpbios_cpu((u_int8_t *)&pe, self);
 
-		pe.apic_id = 1 - cpu_number();
+		/* setup cpu 1 */
+		
+		pe.apic_id = 1; 
 		pe.cpu_flags = PROCENTRY_FLAG_EN;
-
 		mpbios_cpu((u_int8_t *)&pe, self);
 
+		/*
+		 * setup ioapic, base adress is known
+		 * the version number should be 0x10 for default 
+		 * configurations > 4
+		 */
+		 
+		if (mp_fps->mpfb1 > 4)
+		{
+			default_ioapic.	apic_version=0x10;
+		}
+
 		mpbios_ioapic((u_int8_t *)&default_ioapic, self);
 
-		/* XXX */
-		printf("%s: WARNING: interrupts not configured\n",
-		    self->dv_xname);
-		panic("lazy bum");
-		return;
+		/*
+		 * determine the numbers of busses depending on the 
+		 * config type 
+                 */
+
+		if (mp_fps->mpfb1 != 0)
+			switch(mp_fps->mpfb1) {
+			case 1:
+			case 2:
+			case 3:
+			case 4:
+				mp_nbus = 1;
+				break;
+			case 5:
+			case 6:
+			case 7:
+				mp_nbus = 2;
+				break;
+			default:
+				panic("Unknown pre-defined MP Table config type %d", 
+				mp_fps->mpfb1);
+			}
+
+		mp_busses = malloc(sizeof(struct mp_bus) * mp_nbus, 
+				M_DEVBUF, M_NOWAIT);
+
+		/* setup a bus structure for mpbios_bus, first setup bus 0 */
+
+		bus.type = MPS_MCT_BUS;
+		bus.bus_id = 0;
+
+		switch (mp_fps->mpfb1) {
+		    case 1:
+		    case 5:
+			memcpy(bus.bus_type, "ISA   ",6);
+			break;
+		    case 2:
+		    case 6:
+		    case 3:
+			memcpy(bus.bus_type, "EISA  ", 6);
+			break;
+		    case 4:
+		    case 7:
+			memcpy(bus.bus_type, "MCA   ", 6);
+		}
+		mpbios_bus((u_int8_t *)&bus, self);
+
+		/*
+	         *	configuration 4 and higher do have a PCI bus, so the
+		 * 	PCI bus is always second.
+		 */
+
+		if (mp_fps->mpfb1 > 4) {
+			bus.bus_id = 1;
+			memcpy(bus.bus_type, "PCI   ", 6);
+			mpbios_bus((u_int8_t *)&bus, self);
+		};
+
+		/* lets setup the interrupts */ 
+
+		mp_intrs = malloc(sizeof(struct mp_intr_map) * 15, M_DEVBUF, 
+			M_NOWAIT);
+
+		mpi.type = MPS_MCT_IOINT;
+		mpi.int_type = MPS_INTTYPE_INT; 
+
+		/* 
+		 * according the the specs, PCI interrupts have been mapped
+		 * into the (E)ISA interrupts space. All interrupts should 
+		 * be wired to bus 0
+   		 */
+
+		mpi.src_bus_id = 0;
+
+		/* 
+		 * There is only one IOAPIC in the default configurations
+		 */
+
+		mpi.dst_apic_id = default_ioapic.apic_id;
+
+		/*
+		 * do a quick check to see if the ELCR information is correct
+		 * according to freebsd:src/sys/i386/isa/elcr.c almost all
+		 * PCI systems have an ELCR. Linux only uses ELCR for 
+		 * Configuration 5, but my Configuration 6 also needs it.
+		 */
+
+		if (mp_fps->mpfb1 > 4) {
+
+	         if ((ELCR_trigger(0) | ELCR_trigger(1) | ELCR_trigger(2) |
+	             ELCR_trigger(8) | ELCR_trigger(13))) {
+               	       	 printf("%s: ELCR is not available\n", self->dv_xname);
+			}
+                	else 
+			{
+				useELCR=1;
+                       		printf("%s: Using ELCR to identify PCI IRQ's\n" 
+					,self->dv_xname);
+			}
+                }
+
+		/*
+		 * Configuration 2 should not connect IRQ0 and IRQ13
+		 * the other configurations should not connect to IRQ2
+                 */
+		for ( i = 0; i<16;i++) {
+			switch (mp_fps->mpfb1) {
+			case 2:
+				if (i== 0 || i == 13)
+					continue; 
+			default:
+				if (i == 2)
+					continue; 
+
+			mpi.src_bus_irq = i;
+			mpi.dst_apic_int = i ? i : 2;
+
+                        mpi.int_flags = MPS_INTPO_DEF << 2 | MPS_INTTR_DEF;
+
+			/*
+			 * check if it is a level trigger (1) or an edge 
+			 * trigger (0) from elcr.c
+			 * (freebsd:src/sys/i386/isa/elcr.c)
+			 * 'Note that the polarity of ISA and EISA IRQs are 
+			 * linked to the trigger mode.  All edge triggered 
+			 * IRQs use active-hi polarity, and all level
+			 * triggered interrupts use active-lo polarity.'
+			 */
+
+			if (useELCR && ELCR_trigger(i))
+			{
+                                mpi.int_flags = 13;
+				if(mp_verbose) {
+					printf("%s: Changing irq %d to level triggered 0x%x\n",
+						self->dv_xname, i, 
+						mpi.int_flags);
+				}
+			}
+
+			mpbios_int((u_int8_t *)&mpi , MPS_MCT_IOINT, 
+				&mp_intrs[i]);
+		}
+	}
 	} else {
 		/*
 		 * should not happen; mp_probe returns 0 in this case,
@@ -1106,3 +1281,4 @@
 		printf(" (type 0x%x flags 0x%x)\n", type, flags);
 	}
 }
+
