We define IO_APIC_ADDR in <arch/ioapic.h>, let's use it.
[coreboot.git] / src / mainboard / intel / xe7501devkit / mptable.c
index 7dae29c450a312921e9d66c969e5889a79a5ef1b..d39e754700781e862f057b8d7594458ef7e266d0 100644 (file)
-#include <console/console.h>\r
-#include <arch/smp/mpspec.h>\r
-#include <device/pci.h>\r
-#include <string.h>\r
-#include <stdint.h>\r
-#include <assert.h>\r
-#include "bus.h"\r
-#include "ioapic.h"\r
-\r
-// Generate MP-table IRQ numbers for PCI devices.\r
-#define INT_A  0\r
-#define INT_B  1\r
-#define INT_C  2\r
-#define INT_D  3\r
-#define PCI_IRQ(dev, intLine)  (((dev)<<2) | intLine)\r
-\r
-\r
-void xe7501devkit_register_buses(struct mp_config_table *mc)\r
-{\r
-       // Bus ID, Bus Type\r
-       smp_write_bus(mc, PCI_BUS_CHIPSET,              BUSTYPE_PCI);\r
-       smp_write_bus(mc, PCI_BUS_E7501_HI_B,   BUSTYPE_PCI);\r
-       smp_write_bus(mc, PCI_BUS_P64H2_2_B,    BUSTYPE_PCI);\r
-       smp_write_bus(mc, PCI_BUS_P64H2_2_A,    BUSTYPE_PCI);\r
-       smp_write_bus(mc, PCI_BUS_E7501_HI_D,   BUSTYPE_PCI);\r
-       smp_write_bus(mc, PCI_BUS_P64H2_1_B,    BUSTYPE_PCI);\r
-       smp_write_bus(mc, PCI_BUS_P64H2_1_A,    BUSTYPE_PCI);\r
-       smp_write_bus(mc, PCI_BUS_ICH3,                 BUSTYPE_PCI);\r
-       smp_write_bus(mc, SUPERIO_BUS,                  BUSTYPE_ISA);\r
-}\r
-\r
-void xe7501devkit_register_ioapics(struct mp_config_table *mc)\r
-{\r
-       device_t dev;\r
-    struct resource *res;\r
-\r
-       // TODO: Gack. This is REALLY ugly.\r
-\r
-       // Southbridge IOAPIC\r
-       smp_write_ioapic(mc, IOAPIC_ICH3, 0x20, 0xfec00000);    // APIC ID, Version, Address\r
-\r
-       // P64H2#2 Bus A IOAPIC\r
-       dev = dev_find_slot(PCI_BUS_E7501_HI_B, PCI_DEVFN(30, 0));      \r
-       if (!dev)\r
-               BUG();          // Config.lb error?\r
-       res = find_resource(dev, PCI_BASE_ADDRESS_0);\r
-       smp_write_ioapic(mc, IOAPIC_P64H2_2_BUS_A, P64H2_IOAPIC_VERSION, res->base);\r
-\r
-       // P64H2#2 Bus B IOAPIC\r
-       dev = dev_find_slot(PCI_BUS_E7501_HI_B, PCI_DEVFN(28, 0));      \r
-       if (!dev)\r
-               BUG();          // Config.lb error?\r
-       res = find_resource(dev, PCI_BASE_ADDRESS_0);\r
-       smp_write_ioapic(mc, IOAPIC_P64H2_2_BUS_B, P64H2_IOAPIC_VERSION, res->base);\r
-\r
-\r
-       // P64H2#1 Bus A IOAPIC\r
-       dev = dev_find_slot(PCI_BUS_E7501_HI_D, PCI_DEVFN(30, 0));      \r
-       if (!dev)\r
-               BUG();          // Config.lb error?\r
-       res = find_resource(dev, PCI_BASE_ADDRESS_0);\r
-       smp_write_ioapic(mc, IOAPIC_P64H2_1_BUS_A, P64H2_IOAPIC_VERSION, res->base);\r
-\r
-       // P64H2#1 Bus B IOAPIC\r
-       dev = dev_find_slot(PCI_BUS_E7501_HI_D, PCI_DEVFN(28, 0));      \r
-       if (!dev)\r
-               BUG();          // Config.lb error?\r
-       res = find_resource(dev, PCI_BASE_ADDRESS_0);\r
-       smp_write_ioapic(mc, IOAPIC_P64H2_1_BUS_B, P64H2_IOAPIC_VERSION, res->base);\r
-}\r
-\r
-void xe7501devkit_register_interrupts(struct mp_config_table *mc)\r
-{\r
-       // Chipset PCI bus\r
-       //                                       Type           Trigger | Polarity                                                      Bus ID                          IRQ                                     APIC ID                                 PIN#\r
-       smp_write_intsrc(mc, mp_ExtINT, MP_IRQ_TRIGGER_EDGE |MP_IRQ_POLARITY_HIGH,      PCI_BUS_CHIPSET,        0,                                      MP_APIC_ALL,                     0);\r
-       smp_write_intsrc(mc, mp_NMI,    MP_IRQ_TRIGGER_EDGE |MP_IRQ_POLARITY_HIGH,      PCI_BUS_CHIPSET,        0,                                      MP_APIC_ALL,                     1);\r
-       smp_write_intsrc(mc, mp_INT,    MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW,       PCI_BUS_CHIPSET,        PCI_IRQ(29, INT_A), IOAPIC_ICH3,                        16);    // USB 1.1 Controller #1\r
-       smp_write_intsrc(mc, mp_INT,    MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW,       PCI_BUS_CHIPSET,        PCI_IRQ(31, INT_B),     IOAPIC_ICH3,                    17);    // SMBus\r
-       smp_write_intsrc(mc, mp_INT,    MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW,       PCI_BUS_CHIPSET,        PCI_IRQ(29, INT_C), IOAPIC_ICH3,                        18);    // USB 1.1 Controller #3\r
-       smp_write_intsrc(mc, mp_INT,    MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW,       PCI_BUS_CHIPSET,        PCI_IRQ(31, INT_C), IOAPIC_ICH3,                        18);    // IDE\r
-       smp_write_intsrc(mc, mp_INT,    MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW,       PCI_BUS_CHIPSET,        PCI_IRQ(29, INT_D), IOAPIC_ICH3,                        19);    // USB 1.1 Controller #2\r
-\r
-       // P64H2#2 Bus B\r
-       smp_write_intsrc(mc, mp_INT,    MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW,       PCI_BUS_P64H2_2_B,      PCI_IRQ(1, INT_A),      IOAPIC_P64H2_2_BUS_B,    0);    // Slot 2A (J23)\r
-       smp_write_intsrc(mc, mp_INT,    MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW,       PCI_BUS_P64H2_2_B,      PCI_IRQ(1, INT_B),      IOAPIC_P64H2_2_BUS_B,    1);    // Slot 2A (J23)\r
-       smp_write_intsrc(mc, mp_INT,    MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW,       PCI_BUS_P64H2_2_B,      PCI_IRQ(1, INT_C),      IOAPIC_P64H2_2_BUS_B,    2);    // Slot 2A (J23)\r
-       smp_write_intsrc(mc, mp_INT,    MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW,       PCI_BUS_P64H2_2_B,      PCI_IRQ(1, INT_D),      IOAPIC_P64H2_2_BUS_B,    3);    // Slot 2A (J23)\r
-       smp_write_intsrc(mc, mp_INT,    MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW,       PCI_BUS_P64H2_2_B,      PCI_IRQ(2, INT_A),      IOAPIC_P64H2_2_BUS_B,    4);    // Slot 2B (J24)\r
-       smp_write_intsrc(mc, mp_INT,    MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW,       PCI_BUS_P64H2_2_B,      PCI_IRQ(2, INT_B),      IOAPIC_P64H2_2_BUS_B,    5);    // Slot 2B (J24)\r
-       smp_write_intsrc(mc, mp_INT,    MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW,       PCI_BUS_P64H2_2_B,      PCI_IRQ(2, INT_C),      IOAPIC_P64H2_2_BUS_B,    6);    // Slot 2B (J24)\r
-       smp_write_intsrc(mc, mp_INT,    MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW,       PCI_BUS_P64H2_2_B,      PCI_IRQ(2, INT_D),      IOAPIC_P64H2_2_BUS_B,    7);    // Slot 2B (J24)\r
-       smp_write_intsrc(mc, mp_INT,    MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW,       PCI_BUS_P64H2_2_B,      PCI_IRQ(3, INT_A),      IOAPIC_P64H2_2_BUS_B,    8);    // Slot 2C (J25)\r
-       smp_write_intsrc(mc, mp_INT,    MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW,       PCI_BUS_P64H2_2_B,      PCI_IRQ(3, INT_B),      IOAPIC_P64H2_2_BUS_B,    9);    // Slot 2C (J25)\r
-       smp_write_intsrc(mc, mp_INT,    MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW,       PCI_BUS_P64H2_2_B,      PCI_IRQ(3, INT_C),      IOAPIC_P64H2_2_BUS_B,   10);    // Slot 2C (J25)\r
-       smp_write_intsrc(mc, mp_INT,    MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW,       PCI_BUS_P64H2_2_B,      PCI_IRQ(3, INT_D),      IOAPIC_P64H2_2_BUS_B,   11);    // Slot 2C (J25)\r
-       smp_write_intsrc(mc, mp_INT,    MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW,       PCI_BUS_P64H2_2_B,      PCI_IRQ(4, INT_A),      IOAPIC_P64H2_2_BUS_B,   12);    // Slot 2D (J12)\r
-       smp_write_intsrc(mc, mp_INT,    MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW,       PCI_BUS_P64H2_2_B,      PCI_IRQ(4, INT_B),      IOAPIC_P64H2_2_BUS_B,   13);    // Slot 2D (J12)\r
-       smp_write_intsrc(mc, mp_INT,    MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW,       PCI_BUS_P64H2_2_B,      PCI_IRQ(4, INT_C),      IOAPIC_P64H2_2_BUS_B,   14);    // Slot 2D (J12)\r
-       smp_write_intsrc(mc, mp_INT,    MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW,       PCI_BUS_P64H2_2_B,      PCI_IRQ(4, INT_D),      IOAPIC_P64H2_2_BUS_B,   15);    // Slot 2D (J12)\r
-       \r
-       // P64H2#2 Bus A\r
-       smp_write_intsrc(mc, mp_INT,    MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW,       PCI_BUS_P64H2_2_A,      PCI_IRQ(1, INT_A),      IOAPIC_P64H2_2_BUS_A,    0);    // SCSI\r
-       smp_write_intsrc(mc, mp_INT,    MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW,       PCI_BUS_P64H2_2_A,      PCI_IRQ(1, INT_B),      IOAPIC_P64H2_2_BUS_A,    1);    // SCSI\r
-       \r
-       // P64H2#1 Bus B\r
-       smp_write_intsrc(mc, mp_INT,    MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW,       PCI_BUS_P64H2_1_B,      PCI_IRQ(1, INT_A),      IOAPIC_P64H2_1_BUS_B,    0);    // GB Ethernet\r
-       smp_write_intsrc(mc, mp_INT,    MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW,       PCI_BUS_P64H2_1_B,      PCI_IRQ(2, INT_A),      IOAPIC_P64H2_1_BUS_B,    4);    // Slot 1B (J21)\r
-       smp_write_intsrc(mc, mp_INT,    MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW,       PCI_BUS_P64H2_1_B,      PCI_IRQ(2, INT_B),      IOAPIC_P64H2_1_BUS_B,    5);    // Slot 1B (J21)\r
-       smp_write_intsrc(mc, mp_INT,    MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW,       PCI_BUS_P64H2_1_B,      PCI_IRQ(2, INT_C),      IOAPIC_P64H2_1_BUS_B,    6);    // Slot 1B (J21)\r
-       smp_write_intsrc(mc, mp_INT,    MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW,       PCI_BUS_P64H2_1_B,      PCI_IRQ(2, INT_D),      IOAPIC_P64H2_1_BUS_B,    7);    // Slot 1B (J21)\r
-\r
-       // P64H2#1 Bus A\r
-       smp_write_intsrc(mc, mp_INT,    MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW,       PCI_BUS_P64H2_1_A,      PCI_IRQ(1, INT_A),      IOAPIC_P64H2_1_BUS_A,    0);    // Slot 1A (J20)\r
-       smp_write_intsrc(mc, mp_INT,    MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW,       PCI_BUS_P64H2_1_A,      PCI_IRQ(1, INT_B),      IOAPIC_P64H2_1_BUS_A,    1);    // Slot 1A (J20)\r
-       smp_write_intsrc(mc, mp_INT,    MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW,       PCI_BUS_P64H2_1_A,      PCI_IRQ(1, INT_C),      IOAPIC_P64H2_1_BUS_A,    2);    // Slot 1A (J20)\r
-       smp_write_intsrc(mc, mp_INT,    MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW,       PCI_BUS_P64H2_1_A,      PCI_IRQ(1, INT_D),      IOAPIC_P64H2_1_BUS_A,    3);    // Slot 1A (J20)\r
-\r
-       // ICH-3\r
-       \r
-       smp_write_intsrc(mc, mp_INT,    MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW,       PCI_BUS_ICH3,           PCI_IRQ(0, INT_A),      IOAPIC_ICH3,                    16);    // Video\r
-       smp_write_intsrc(mc, mp_INT,    MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW,       PCI_BUS_ICH3,           PCI_IRQ(2, INT_A),      IOAPIC_ICH3,                    18);    // Debug slot (J11)\r
-       smp_write_intsrc(mc, mp_INT,    MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW,       PCI_BUS_ICH3,           PCI_IRQ(2, INT_B),      IOAPIC_ICH3,                    19);    // Debug slot (J11)\r
-       smp_write_intsrc(mc, mp_INT,    MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW,       PCI_BUS_ICH3,           PCI_IRQ(2, INT_C),      IOAPIC_ICH3,                    16);    // Debug slot (J11)\r
-       smp_write_intsrc(mc, mp_INT,    MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW,       PCI_BUS_ICH3,           PCI_IRQ(2, INT_D),      IOAPIC_ICH3,                    17);    // Debug slot (J11)\r
-       \r
-       // TODO: Not sure how to handle BT_INTR# signals from the P64H2s. Do we even need to, in APIC mode?\r
-\r
-       // Super I/O (ISA interrupts)\r
-       smp_write_intsrc(mc, mp_ExtINT, MP_IRQ_TRIGGER_EDGE |MP_IRQ_POLARITY_HIGH,      SUPERIO_BUS,             0,                                     IOAPIC_ICH3,                     0);\r
-       smp_write_intsrc(mc, mp_INT,    MP_IRQ_TRIGGER_EDGE |MP_IRQ_POLARITY_HIGH,      SUPERIO_BUS,             1,                                     IOAPIC_ICH3,                     1);\r
-       smp_write_intsrc(mc, mp_INT,    MP_IRQ_TRIGGER_EDGE |MP_IRQ_POLARITY_HIGH,      SUPERIO_BUS,             0,                                     IOAPIC_ICH3,                     2);\r
-\r
-       smp_write_intsrc(mc, mp_INT,    MP_IRQ_TRIGGER_EDGE |MP_IRQ_POLARITY_HIGH,      SUPERIO_BUS,             3,                                     IOAPIC_ICH3,                     3);\r
-       smp_write_intsrc(mc, mp_INT,    MP_IRQ_TRIGGER_EDGE |MP_IRQ_POLARITY_HIGH,      SUPERIO_BUS,             4,                                     IOAPIC_ICH3,                     4);\r
-       smp_write_intsrc(mc, mp_INT,    MP_IRQ_TRIGGER_EDGE |MP_IRQ_POLARITY_HIGH,      SUPERIO_BUS,             6,                                     IOAPIC_ICH3,                     6);\r
-       smp_write_intsrc(mc, mp_INT,    MP_IRQ_TRIGGER_EDGE |MP_IRQ_POLARITY_HIGH,      SUPERIO_BUS,             8,                                     IOAPIC_ICH3,                     8);\r
-       smp_write_intsrc(mc, mp_INT,    MP_IRQ_TRIGGER_EDGE |MP_IRQ_POLARITY_HIGH,      SUPERIO_BUS,             9,                                     IOAPIC_ICH3,                     9);\r
-       smp_write_intsrc(mc, mp_INT,    MP_IRQ_TRIGGER_EDGE |MP_IRQ_POLARITY_HIGH,      SUPERIO_BUS,            12,                                     IOAPIC_ICH3,                    12);\r
-       smp_write_intsrc(mc, mp_INT,    MP_IRQ_TRIGGER_EDGE |MP_IRQ_POLARITY_HIGH,      SUPERIO_BUS,            13,                                     IOAPIC_ICH3,                    13);\r
-       smp_write_intsrc(mc, mp_INT,    MP_IRQ_TRIGGER_EDGE |MP_IRQ_POLARITY_HIGH,      SUPERIO_BUS,            14,                                     IOAPIC_ICH3,                    14);\r
-       smp_write_intsrc(mc, mp_INT,    MP_IRQ_TRIGGER_EDGE |MP_IRQ_POLARITY_HIGH,      SUPERIO_BUS,            15,                                     IOAPIC_ICH3,                    15);\r
-}\r
-\r
-void* smp_write_config_table(void* v)\r
-{\r
-       static const char sig[4] = MPC_SIGNATURE;\r
-    static const char oem[8] = "INTEL   ";\r
-    static const char productid[12] = "XE7501DEVKIT";\r
-    struct mp_config_table *mc = (void *)(((char *)v) + SMP_FLOATING_TABLE_LEN);\r
-       memset(mc, 0, sizeof(*mc));\r
-\r
-    memcpy(mc->mpc_signature, sig, sizeof(sig));\r
-    memcpy(mc->mpc_oem, oem, sizeof(oem));\r
-    memcpy(mc->mpc_productid, productid, sizeof(productid));\r
-\r
-    mc->mpc_length = sizeof(*mc);                                      // initially just the header\r
-    mc->mpc_spec = 0x04;                                                       // Multiprocessing Spec V1.4\r
-    mc->mpc_lapic = LAPIC_ADDR;\r
-\r
-       smp_write_processors(mc);\r
-\r
-       xe7501devkit_register_buses(mc);\r
-       xe7501devkit_register_ioapics(mc);\r
-       xe7501devkit_register_interrupts(mc);\r
-\r
-       /* Compute the checksums */\r
-       mc->mpe_checksum = smp_compute_checksum(smp_next_mpc_entry(mc), mc->mpe_length);\r
-       mc->mpc_checksum = smp_compute_checksum(mc, mc->mpc_length);\r
-       printk_debug("Wrote the mp table end at: %p - %p\n", mc, smp_next_mpe_entry(mc));\r
-\r
-       return smp_next_mpe_entry(mc);\r
-}\r
-\r
-unsigned long write_smp_table(unsigned long addr)\r
-{\r
-       void *v;\r
-       v = smp_write_floating_table(addr);\r
-       return (unsigned long)smp_write_config_table(v);\r
-}\r
+#include <console/console.h>
+#include <arch/smp/mpspec.h>
+#include <arch/ioapic.h>
+#include <device/pci.h>
+#include <string.h>
+#include <stdint.h>
+#include <assert.h>
+#include "bus.h"
+#include "ioapic.h"
+
+// Generate MP-table IRQ numbers for PCI devices.
+#define INT_A  0
+#define INT_B  1
+#define INT_C  2
+#define INT_D  3
+#define PCI_IRQ(dev, intLine)  (((dev)<<2) | intLine)
+
+
+static void xe7501devkit_register_buses(struct mp_config_table *mc)
+{
+       // Bus ID, Bus Type
+       smp_write_bus(mc, PCI_BUS_CHIPSET,      BUSTYPE_PCI);
+       smp_write_bus(mc, PCI_BUS_E7501_HI_B,   BUSTYPE_PCI);
+       smp_write_bus(mc, PCI_BUS_P64H2_2_B,    BUSTYPE_PCI);
+       smp_write_bus(mc, PCI_BUS_P64H2_2_A,    BUSTYPE_PCI);
+       smp_write_bus(mc, PCI_BUS_E7501_HI_D,   BUSTYPE_PCI);
+       smp_write_bus(mc, PCI_BUS_P64H2_1_B,    BUSTYPE_PCI);
+       smp_write_bus(mc, PCI_BUS_P64H2_1_A,    BUSTYPE_PCI);
+       smp_write_bus(mc, PCI_BUS_ICH3,         BUSTYPE_PCI);
+       smp_write_bus(mc, SUPERIO_BUS,          BUSTYPE_ISA);
+}
+
+static void xe7501devkit_register_ioapics(struct mp_config_table *mc)
+{
+       device_t dev;
+       struct resource *res;
+
+       // TODO: Gack. This is REALLY ugly.
+
+       // Southbridge IOAPIC
+       smp_write_ioapic(mc, IOAPIC_ICH3, 0x20, IO_APIC_ADDR);  // APIC ID, Version, Address
+
+       // P64H2#2 Bus A IOAPIC
+       dev = dev_find_slot(PCI_BUS_E7501_HI_B, PCI_DEVFN(30, 0));
+       if (!dev)
+               BUG();          // Config.lb error?
+       res = find_resource(dev, PCI_BASE_ADDRESS_0);
+       smp_write_ioapic(mc, IOAPIC_P64H2_2_BUS_A, P64H2_IOAPIC_VERSION, res->base);
+
+       // P64H2#2 Bus B IOAPIC
+       dev = dev_find_slot(PCI_BUS_E7501_HI_B, PCI_DEVFN(28, 0));
+       if (!dev)
+               BUG();          // Config.lb error?
+       res = find_resource(dev, PCI_BASE_ADDRESS_0);
+       smp_write_ioapic(mc, IOAPIC_P64H2_2_BUS_B, P64H2_IOAPIC_VERSION, res->base);
+
+
+       // P64H2#1 Bus A IOAPIC
+       dev = dev_find_slot(PCI_BUS_E7501_HI_D, PCI_DEVFN(30, 0));
+       if (!dev)
+               BUG();          // Config.lb error?
+       res = find_resource(dev, PCI_BASE_ADDRESS_0);
+       smp_write_ioapic(mc, IOAPIC_P64H2_1_BUS_A, P64H2_IOAPIC_VERSION, res->base);
+
+       // P64H2#1 Bus B IOAPIC
+       dev = dev_find_slot(PCI_BUS_E7501_HI_D, PCI_DEVFN(28, 0));
+       if (!dev)
+               BUG();          // Config.lb error?
+       res = find_resource(dev, PCI_BASE_ADDRESS_0);
+       smp_write_ioapic(mc, IOAPIC_P64H2_1_BUS_B, P64H2_IOAPIC_VERSION, res->base);
+}
+
+static void xe7501devkit_register_interrupts(struct mp_config_table *mc)
+{
+       // Chipset PCI bus
+       //                                       Type           Trigger | Polarity                                                      Bus ID                          IRQ                                     APIC ID                                 PIN#
+       smp_write_intsrc(mc, mp_ExtINT, MP_IRQ_TRIGGER_EDGE |MP_IRQ_POLARITY_HIGH,      PCI_BUS_CHIPSET,        0,                                      MP_APIC_ALL,                     0);
+       smp_write_intsrc(mc, mp_NMI,    MP_IRQ_TRIGGER_EDGE |MP_IRQ_POLARITY_HIGH,      PCI_BUS_CHIPSET,        0,                                      MP_APIC_ALL,                     1);
+       smp_write_intsrc(mc, mp_INT,    MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW,       PCI_BUS_CHIPSET,        PCI_IRQ(29, INT_A), IOAPIC_ICH3,                        16);    // USB 1.1 Controller #1
+       smp_write_intsrc(mc, mp_INT,    MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW,       PCI_BUS_CHIPSET,        PCI_IRQ(31, INT_B),     IOAPIC_ICH3,                    17);    // SMBus
+       smp_write_intsrc(mc, mp_INT,    MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW,       PCI_BUS_CHIPSET,        PCI_IRQ(29, INT_C), IOAPIC_ICH3,                        18);    // USB 1.1 Controller #3
+       smp_write_intsrc(mc, mp_INT,    MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW,       PCI_BUS_CHIPSET,        PCI_IRQ(31, INT_C), IOAPIC_ICH3,                        18);    // IDE
+       smp_write_intsrc(mc, mp_INT,    MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW,       PCI_BUS_CHIPSET,        PCI_IRQ(29, INT_D), IOAPIC_ICH3,                        19);    // USB 1.1 Controller #2
+
+       // P64H2#2 Bus B
+       smp_write_intsrc(mc, mp_INT,    MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW,       PCI_BUS_P64H2_2_B,      PCI_IRQ(1, INT_A),      IOAPIC_P64H2_2_BUS_B,    0);    // Slot 2A (J23)
+       smp_write_intsrc(mc, mp_INT,    MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW,       PCI_BUS_P64H2_2_B,      PCI_IRQ(1, INT_B),      IOAPIC_P64H2_2_BUS_B,    1);    // Slot 2A (J23)
+       smp_write_intsrc(mc, mp_INT,    MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW,       PCI_BUS_P64H2_2_B,      PCI_IRQ(1, INT_C),      IOAPIC_P64H2_2_BUS_B,    2);    // Slot 2A (J23)
+       smp_write_intsrc(mc, mp_INT,    MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW,       PCI_BUS_P64H2_2_B,      PCI_IRQ(1, INT_D),      IOAPIC_P64H2_2_BUS_B,    3);    // Slot 2A (J23)
+       smp_write_intsrc(mc, mp_INT,    MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW,       PCI_BUS_P64H2_2_B,      PCI_IRQ(2, INT_A),      IOAPIC_P64H2_2_BUS_B,    4);    // Slot 2B (J24)
+       smp_write_intsrc(mc, mp_INT,    MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW,       PCI_BUS_P64H2_2_B,      PCI_IRQ(2, INT_B),      IOAPIC_P64H2_2_BUS_B,    5);    // Slot 2B (J24)
+       smp_write_intsrc(mc, mp_INT,    MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW,       PCI_BUS_P64H2_2_B,      PCI_IRQ(2, INT_C),      IOAPIC_P64H2_2_BUS_B,    6);    // Slot 2B (J24)
+       smp_write_intsrc(mc, mp_INT,    MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW,       PCI_BUS_P64H2_2_B,      PCI_IRQ(2, INT_D),      IOAPIC_P64H2_2_BUS_B,    7);    // Slot 2B (J24)
+       smp_write_intsrc(mc, mp_INT,    MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW,       PCI_BUS_P64H2_2_B,      PCI_IRQ(3, INT_A),      IOAPIC_P64H2_2_BUS_B,    8);    // Slot 2C (J25)
+       smp_write_intsrc(mc, mp_INT,    MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW,       PCI_BUS_P64H2_2_B,      PCI_IRQ(3, INT_B),      IOAPIC_P64H2_2_BUS_B,    9);    // Slot 2C (J25)
+       smp_write_intsrc(mc, mp_INT,    MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW,       PCI_BUS_P64H2_2_B,      PCI_IRQ(3, INT_C),      IOAPIC_P64H2_2_BUS_B,   10);    // Slot 2C (J25)
+       smp_write_intsrc(mc, mp_INT,    MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW,       PCI_BUS_P64H2_2_B,      PCI_IRQ(3, INT_D),      IOAPIC_P64H2_2_BUS_B,   11);    // Slot 2C (J25)
+       smp_write_intsrc(mc, mp_INT,    MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW,       PCI_BUS_P64H2_2_B,      PCI_IRQ(4, INT_A),      IOAPIC_P64H2_2_BUS_B,   12);    // Slot 2D (J12)
+       smp_write_intsrc(mc, mp_INT,    MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW,       PCI_BUS_P64H2_2_B,      PCI_IRQ(4, INT_B),      IOAPIC_P64H2_2_BUS_B,   13);    // Slot 2D (J12)
+       smp_write_intsrc(mc, mp_INT,    MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW,       PCI_BUS_P64H2_2_B,      PCI_IRQ(4, INT_C),      IOAPIC_P64H2_2_BUS_B,   14);    // Slot 2D (J12)
+       smp_write_intsrc(mc, mp_INT,    MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW,       PCI_BUS_P64H2_2_B,      PCI_IRQ(4, INT_D),      IOAPIC_P64H2_2_BUS_B,   15);    // Slot 2D (J12)
+
+       // P64H2#2 Bus A
+       smp_write_intsrc(mc, mp_INT,    MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW,       PCI_BUS_P64H2_2_A,      PCI_IRQ(1, INT_A),      IOAPIC_P64H2_2_BUS_A,    0);    // SCSI
+       smp_write_intsrc(mc, mp_INT,    MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW,       PCI_BUS_P64H2_2_A,      PCI_IRQ(1, INT_B),      IOAPIC_P64H2_2_BUS_A,    1);    // SCSI
+
+       // P64H2#1 Bus B
+       smp_write_intsrc(mc, mp_INT,    MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW,       PCI_BUS_P64H2_1_B,      PCI_IRQ(1, INT_A),      IOAPIC_P64H2_1_BUS_B,    0);    // GB Ethernet
+       smp_write_intsrc(mc, mp_INT,    MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW,       PCI_BUS_P64H2_1_B,      PCI_IRQ(2, INT_A),      IOAPIC_P64H2_1_BUS_B,    4);    // Slot 1B (J21)
+       smp_write_intsrc(mc, mp_INT,    MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW,       PCI_BUS_P64H2_1_B,      PCI_IRQ(2, INT_B),      IOAPIC_P64H2_1_BUS_B,    5);    // Slot 1B (J21)
+       smp_write_intsrc(mc, mp_INT,    MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW,       PCI_BUS_P64H2_1_B,      PCI_IRQ(2, INT_C),      IOAPIC_P64H2_1_BUS_B,    6);    // Slot 1B (J21)
+       smp_write_intsrc(mc, mp_INT,    MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW,       PCI_BUS_P64H2_1_B,      PCI_IRQ(2, INT_D),      IOAPIC_P64H2_1_BUS_B,    7);    // Slot 1B (J21)
+
+       // P64H2#1 Bus A
+       smp_write_intsrc(mc, mp_INT,    MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW,       PCI_BUS_P64H2_1_A,      PCI_IRQ(1, INT_A),      IOAPIC_P64H2_1_BUS_A,    0);    // Slot 1A (J20)
+       smp_write_intsrc(mc, mp_INT,    MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW,       PCI_BUS_P64H2_1_A,      PCI_IRQ(1, INT_B),      IOAPIC_P64H2_1_BUS_A,    1);    // Slot 1A (J20)
+       smp_write_intsrc(mc, mp_INT,    MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW,       PCI_BUS_P64H2_1_A,      PCI_IRQ(1, INT_C),      IOAPIC_P64H2_1_BUS_A,    2);    // Slot 1A (J20)
+       smp_write_intsrc(mc, mp_INT,    MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW,       PCI_BUS_P64H2_1_A,      PCI_IRQ(1, INT_D),      IOAPIC_P64H2_1_BUS_A,    3);    // Slot 1A (J20)
+
+       // ICH-3
+
+       smp_write_intsrc(mc, mp_INT,    MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW,       PCI_BUS_ICH3,           PCI_IRQ(0, INT_A),      IOAPIC_ICH3,                    16);    // Video
+       smp_write_intsrc(mc, mp_INT,    MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW,       PCI_BUS_ICH3,           PCI_IRQ(2, INT_A),      IOAPIC_ICH3,                    18);    // Debug slot (J11)
+       smp_write_intsrc(mc, mp_INT,    MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW,       PCI_BUS_ICH3,           PCI_IRQ(2, INT_B),      IOAPIC_ICH3,                    19);    // Debug slot (J11)
+       smp_write_intsrc(mc, mp_INT,    MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW,       PCI_BUS_ICH3,           PCI_IRQ(2, INT_C),      IOAPIC_ICH3,                    16);    // Debug slot (J11)
+       smp_write_intsrc(mc, mp_INT,    MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW,       PCI_BUS_ICH3,           PCI_IRQ(2, INT_D),      IOAPIC_ICH3,                    17);    // Debug slot (J11)
+
+       // TODO: Not sure how to handle BT_INTR# signals from the P64H2s. Do we even need to, in APIC mode?
+
+       mptable_add_isa_interrupts(mc, SUPERIO_BUS, IOAPIC_ICH3, 0);
+}
+
+static void *smp_write_config_table(void* v)
+{
+       static const char sig[4] = MPC_SIGNATURE;
+       static const char oem[8] = "COREBOOT";
+       static const char productid[12] = "XE7501DEVKIT";
+       struct mp_config_table *mc = (void *)(((char *)v) + SMP_FLOATING_TABLE_LEN);
+       memset(mc, 0, sizeof(*mc));
+
+       memcpy(mc->mpc_signature, sig, sizeof(sig));
+       memcpy(mc->mpc_oem, oem, sizeof(oem));
+       memcpy(mc->mpc_productid, productid, sizeof(productid));
+
+       mc->mpc_length = sizeof(*mc);   // initially just the header
+       mc->mpc_spec = 0x04;            // Multiprocessing Spec V1.4
+       mc->mpc_lapic = LAPIC_ADDR;
+
+       smp_write_processors(mc);
+
+       xe7501devkit_register_buses(mc);
+       xe7501devkit_register_ioapics(mc);
+       xe7501devkit_register_interrupts(mc);
+
+       /* Compute the checksums */
+       mc->mpe_checksum = smp_compute_checksum(smp_next_mpc_entry(mc), mc->mpe_length);
+       mc->mpc_checksum = smp_compute_checksum(mc, mc->mpc_length);
+       printk(BIOS_DEBUG, "Wrote the mp table end at: %p - %p\n", mc, smp_next_mpe_entry(mc));
+
+       return smp_next_mpe_entry(mc);
+}
+
+unsigned long write_smp_table(unsigned long addr)
+{
+       void *v;
+       v = smp_write_floating_table(addr);
+       return (unsigned long)smp_write_config_table(v);
+}