coreboot has 13 instances of IOAPIC setup distributed across a lot
of components. This patch is a rewrite of the generic IOAPIC setup code.
Additionally it drops the other 12 instances of IOAPIC setup code and
makes the components use the generic code.

 arch/i386/Config.lb                       |    4 
 arch/i386/include/arch/acpi.h             |    2 
 arch/i386/include/arch/ioapic.h           |   46 ++++++
 arch/i386/smp/Config.lb                   |    6 
 arch/i386/smp/Makefile.inc                |    3 
 arch/i386/smp/ioapic.c                    |  202 ++++++++++++++++++------------
 mainboard/asi/mb_5blmp/Options.lb         |    2 
 mainboard/bcom/winnetp680/Options.lb      |    4 
 mainboard/gigabyte/ga_2761gxdk/Options.lb |    2 
 mainboard/jetway/j7f24/Options.lb         |    2 
 mainboard/via/epia-cn/Options.lb          |    2 
 mainboard/via/pc2500e/Options.lb          |    2 
 northbridge/via/cx700/cx700_lpc.c         |   96 --------------
 southbridge/amd/amd8111/amd8111_lpc.c     |   84 ------------
 southbridge/amd/sb600/sb600_sm.c          |   81 ------------
 southbridge/intel/esb6300/esb6300_lpc.c   |   49 -------
 southbridge/intel/esb6300/esb6300_pic.c   |   45 ------
 southbridge/intel/i3100/i3100_lpc.c       |   69 ++--------
 southbridge/intel/i82801er/i82801er_lpc.c |   48 -------
 southbridge/intel/pxhd/pxhd_bridge.c      |   55 --------
 southbridge/nvidia/ck804/ck804_lpc.c      |   80 -----------
 southbridge/nvidia/mcp55/mcp55_lpc.c      |   95 +-------------
 southbridge/sis/sis966/sis966_lpc.c       |   86 ------------
 southbridge/via/vt8237r/vt8237r_lpc.c     |   97 --------------
 24 files changed, 236 insertions(+), 926 deletions(-)

Signed-off-by: Stefan Reinauer <stepan@coresystems.de>

Index: southbridge/via/vt8237r/vt8237r_lpc.c
===================================================================
--- southbridge/via/vt8237r/vt8237r_lpc.c	(revision 5009)
+++ southbridge/via/vt8237r/vt8237r_lpc.c	(working copy)
@@ -26,6 +26,7 @@
 #include <device/pci.h>
 #include <device/pci_ids.h>
 #include <pc80/mc146818rtc.h>
+#include <arch/ioapic.h>
 #include <cpu/x86/lapic.h>
 #include <pc80/keyboard.h>
 #include <pc80/i8259.h>
@@ -33,21 +34,6 @@
 #include "vt8237r.h"
 #include "chip.h"
 
-#define ALL		(0xff << 24)
-#define NONE		(0)
-#define DISABLED	(1 << 16)
-#define ENABLED		(0 << 16)
-#define TRIGGER_EDGE	(0 << 15)
-#define TRIGGER_LEVEL	(1 << 15)
-#define POLARITY_HIGH	(0 << 13)
-#define POLARITY_LOW	(1 << 13)
-#define PHYSICAL_DEST	(0 << 11)
-#define LOGICAL_DEST	(1 << 11)
-#define ExtINT		(7 << 8)
-#define NMI		(4 << 8)
-#define SMI		(2 << 8)
-#define INT		(1 << 8)
-
 extern void dump_south(device_t dev);
 static void southbridge_init_common(struct device *dev);
 
@@ -75,85 +61,6 @@
 }
 #endif
 
-static struct ioapicreg {
-	u32 reg;
-	u32 value_low;
-	u32 value_high;
-} ioapic_table[] = {
-	/* IO-APIC virtual wire mode configuration. */
-	/* mask, trigger, polarity, destination, delivery, vector */
-	{0, ENABLED | TRIGGER_EDGE | POLARITY_HIGH | PHYSICAL_DEST |
-		    ExtINT, NONE},
-	{1,  DISABLED, NONE},
-	{2,  DISABLED, NONE},
-	{3,  DISABLED, NONE},
-	{4,  DISABLED, NONE},
-	{5,  DISABLED, NONE},
-	{6,  DISABLED, NONE},
-	{7,  DISABLED, NONE},
-	{8,  DISABLED, NONE},
-	{9,  DISABLED, NONE},
-	{10, DISABLED, NONE},
-	{11, DISABLED, NONE},
-	{12, DISABLED, NONE},
-	{13, DISABLED, NONE},
-	{14, DISABLED, NONE},
-	{15, DISABLED, NONE},
-	{16, DISABLED, NONE},
-	{17, DISABLED, NONE},
-	{18, DISABLED, NONE},
-	{19, DISABLED, NONE},
-	{20, DISABLED, NONE},
-	{21, DISABLED, NONE},
-	{22, DISABLED, NONE},
-	{23, DISABLED, NONE},
-};
-
-static void setup_ioapic(u32 ioapic_base)
-{
-	u32 value_low, value_high, val;
-	volatile u32 *l;
-	int i;
-
-	/* All delivered to CPU0. */
-	ioapic_table[0].value_high = (lapicid()) << (56 - 32);
-	l = (u32 *)ioapic_base;
-
-#if CONFIG_EPIA_VT8237R_INIT
-	/* Set APIC to APIC Serial bus. */
-	l[0] = 0x3;
-	l[4] = 0;
-#else
-	/* Set APIC to FSB message bus. */
-	l[0] = 0x3;
-	val = l[4];
-	l[4] = (val & 0xFFFFFE) | 1;
-#endif
-
-	/* Set APIC ADDR - this will be VT8237R_APIC_ID. */
-	l[0] = 0;
-	val = l[4];
-	l[4] = (val & 0xF0FFFF) | (VT8237R_APIC_ID << 24);
-
-	for (i = 0; i < ARRAY_SIZE(ioapic_table); i++) {
-		l[0] = (ioapic_table[i].reg * 2) + 0x10;
-		l[4] = ioapic_table[i].value_low;
-		value_low = l[4];
-		l[0] = (ioapic_table[i].reg * 2) + 0x11;
-		l[4] = ioapic_table[i].value_high;
-		if (i == 0) {
-			l[0] = (ioapic_table[i].reg * 2) + 0x10;
-			value_low = l[4];
-			if (value_low == 0xffffffff)
-			{
-				printk_warning("IO APIC not responding.\n");
-				return;
-			}
-		}
-	}
-}
-
-
 /** Set up PCI IRQ routing, route everything through APIC. */
 static void pci_routing_fixup(struct device *dev)
 {
@@ -622,7 +529,7 @@
 {
 	vt8237_common_init(dev);
 	pci_routing_fixup(dev);
-	setup_ioapic(VT8237R_APIC_BASE);
+	setup_ioapic(VT8237R_APIC_BASE, VT8237R_APIC_ID);
 	setup_i8259();
 	init_keyboard(dev);
 }
Index: southbridge/amd/sb600/sb600_sm.c
===================================================================
--- southbridge/amd/sb600/sb600_sm.c	(revision 5009)
+++ southbridge/amd/sb600/sb600_sm.c	(working copy)
@@ -27,6 +27,7 @@
 #include <bitops.h>
 #include <arch/io.h>
 #include <cpu/x86/lapic.h>
+#include <arch/ioapic.h>
 #include <stdlib.h>
 #include "sb600.h"
 #include "sb600_smbus.c"
@@ -40,83 +41,6 @@
 #define CONFIG_MAINBOARD_POWER_ON_AFTER_POWER_FAIL MAINBOARD_POWER_ON
 #endif
 
-struct ioapicreg {
-	u32 reg;
-	u32 value_low, value_high;
-};
-
-static struct ioapicreg ioapicregvalues[] = {
-#define ALL		(0xff << 24)
-#define NONE		(0)
-#define DISABLED	(1 << 16)
-#define ENABLED		(0 << 16)
-#define TRIGGER_EDGE	(0 << 15)
-#define TRIGGER_LEVEL	(1 << 15)
-#define POLARITY_HIGH	(0 << 13)
-#define POLARITY_LOW	(1 << 13)
-#define PHYSICAL_DEST	(0 << 11)
-#define LOGICAL_DEST	(1 << 11)
-#define ExtINT		(7 << 8)
-#define NMI		(4 << 8)
-#define SMI		(2 << 8)
-#define INT		(1 << 8)
-	/* IO-APIC virtual wire mode configuration */
-	/* mask, trigger, polarity, destination, delivery, vector */
-	{0, DISABLED, NONE},
-	{1, DISABLED, NONE},
-	{2, DISABLED, NONE},
-	{3, DISABLED, NONE},
-	{4, DISABLED, NONE},
-	{5, DISABLED, NONE},
-	{6, DISABLED, NONE},
-	{7, DISABLED, NONE},
-	{8, DISABLED, NONE},
-	{9, DISABLED, NONE},
-	{10, DISABLED, NONE},
-	{11, DISABLED, NONE},
-	{12, DISABLED, NONE},
-	{13, DISABLED, NONE},
-	{14, DISABLED, NONE},
-	{15, DISABLED, NONE},
-	{16, DISABLED, NONE},
-	{17, DISABLED, NONE},
-	{18, DISABLED, NONE},
-	{19, DISABLED, NONE},
-	{20, DISABLED, NONE},
-	{21, DISABLED, NONE},
-	{22, DISABLED, NONE},
-	{23, DISABLED, NONE},
-	/* Be careful and don't write past the end... */
-};
-
-static void setup_ioapic(u32 ioapic_base)
-{
-	int i;
-	u32 value_low, value_high;
-	volatile u32 *l;
-	struct ioapicreg *a = ioapicregvalues;
-
-	ioapicregvalues[0].value_high = lapicid() << (56 - 32);
-
-	printk_debug("lapicid = %016x\n", ioapicregvalues[0].value_high);
-
-	l = (u32 *)ioapic_base;
-
-	for (i = 0; i < ARRAY_SIZE(ioapicregvalues);
-	     i++, a++) {
-		l[0] = (a->reg * 2) + 0x10;
-		l[4] = a->value_low;
-		value_low = l[4];
-		l[0] = (a->reg * 2) + 0x11;
-		l[4] = a->value_high;
-		value_high = l[4];
-		if ((i == 0) && (value_low == 0xffffffff)) {
-			printk_warning("IO APIC not responding.\n");
-			return;
-		}
-	}
-}
-
 /*
 * SB600 enables all USB controllers by default in SMBUS Control.
 * SB600 enables SATA by default in SMBUS Control.
@@ -133,7 +57,8 @@
 	printk_info("sm_init().\n");
 
 	ioapic_base = pci_read_config32(dev, 0x74) & (0xffffffe0);	/* some like mem resource, but does not have  enable bit */
-	setup_ioapic(ioapic_base);
+	/* Don't rename APIC ID */
+	setup_ioapic(ioapic_base, 0);
 
 	dword = pci_read_config8(dev, 0x62);
 	dword |= 1 << 2;
Index: southbridge/amd/amd8111/amd8111_lpc.c
===================================================================
--- southbridge/amd/amd8111/amd8111_lpc.c	(revision 5009)
+++ southbridge/amd/amd8111/amd8111_lpc.c	(working copy)
@@ -10,91 +10,12 @@
 #include <pc80/mc146818rtc.h>
 #include <pc80/isa-dma.h>
 #include <cpu/x86/lapic.h>
+#include <arch/ioapic.h>
 #include <stdlib.h>
 #include "amd8111.h"
 
 #define NMI_OFF 0
 
-struct ioapicreg {
-	unsigned int reg;
-	unsigned int value_low, value_high;
-};
-
-static struct ioapicreg ioapicregvalues[] = {
-#define ALL		(0xff << 24)
-#define NONE		(0)
-#define DISABLED	(1 << 16)
-#define ENABLED		(0 << 16)
-#define TRIGGER_EDGE	(0 << 15)
-#define TRIGGER_LEVEL	(1 << 15)
-#define POLARITY_HIGH	(0 << 13)
-#define POLARITY_LOW	(1 << 13)
-#define PHYSICAL_DEST	(0 << 11)
-#define LOGICAL_DEST	(1 << 11)
-#define ExtINT		(7 << 8)
-#define NMI		(4 << 8)
-#define SMI		(2 << 8)
-#define INT		(1 << 8)
-	/* IO-APIC virtual wire mode configuration */
-	/* mask, trigger, polarity, destination, delivery, vector */
-	{   0, ENABLED | TRIGGER_EDGE | POLARITY_HIGH | PHYSICAL_DEST | ExtINT, NONE},
-	{   1, DISABLED, NONE},
-	{   2, DISABLED, NONE},
-	{   3, DISABLED, NONE},
-	{   4, DISABLED, NONE},
-	{   5, DISABLED, NONE},
-	{   6, DISABLED, NONE},
-	{   7, DISABLED, NONE},
-	{   8, DISABLED, NONE},
-	{   9, DISABLED, NONE},
-	{  10, DISABLED, NONE},
-	{  11, DISABLED, NONE},
-	{  12, DISABLED, NONE},
-	{  13, DISABLED, NONE},
-	{  14, DISABLED, NONE},
-	{  15, DISABLED, NONE},
-	{  16, DISABLED, NONE},
-	{  17, DISABLED, NONE},
-	{  18, DISABLED, NONE},
-	{  19, DISABLED, NONE},
-	{  20, DISABLED, NONE},
-	{  21, DISABLED, NONE},
-	{  22, DISABLED, NONE},
-	{  23, DISABLED, NONE},
-	/* Be careful and don't write past the end... */
-};
-
-static void setup_ioapic(void)
-{
-	int i;
-	unsigned long value_low, value_high;
-	unsigned long ioapic_base = 0xfec00000;
-	volatile unsigned long *l;
-	struct ioapicreg *a = ioapicregvalues;
-	unsigned long bsp_apicid = lapicid();
-
-	l = (unsigned long *) ioapic_base;
-
-	ioapicregvalues[0].value_high = bsp_apicid<<(56-32);
-	printk_debug("amd8111: ioapic bsp_apicid = %02lx\n", bsp_apicid);
-	
-	for (i = 0; i < ARRAY_SIZE(ioapicregvalues);
-	     i++, a++) {
-		l[0] = (a->reg * 2) + 0x10;
-		l[4] = a->value_low;
-		value_low = l[4];
-		l[0] = (a->reg *2) + 0x11;
-		l[4] = a->value_high;
-		value_high = l[4];
-		if ((i==0) && (value_low == 0xffffffff)) {
-			printk_warning("IO APIC not responding.\n");
-			return;
-		}
-		printk_spew("for IRQ, reg 0x%08x value 0x%08x 0x%08x\n", 
-			    a->reg, a->value_low, a->value_high);
-	}
-}
-
 static void enable_hpet(struct device *dev)
 {
 	unsigned long hpet_address;
@@ -114,7 +35,8 @@
 	byte = pci_read_config8(dev, 0x4B);
 	byte |= 1;
 	pci_write_config8(dev, 0x4B, byte);
-	setup_ioapic();
+	/* Don't rename IO APIC */
+	setup_ioapic(IO_APIC_ADDR, 0);
 
 	/* posted memory write enable */
 	byte = pci_read_config8(dev, 0x46);
Index: southbridge/nvidia/ck804/ck804_lpc.c
===================================================================
--- southbridge/nvidia/ck804/ck804_lpc.c	(revision 5009)
+++ southbridge/nvidia/ck804/ck804_lpc.c	(working copy)
@@ -15,6 +15,7 @@
 #include <pc80/isa-dma.h>
 #include <bitops.h>
 #include <arch/io.h>
+#include <arch/ioapic.h>
 #include <cpu/x86/lapic.h>
 #include <stdlib.h>
 #include "ck804.h"
@@ -23,83 +24,6 @@
 
 #define NMI_OFF 0
 
-struct ioapicreg {
-	unsigned int reg;
-	unsigned int value_low, value_high;
-};
-
-static struct ioapicreg ioapicregvalues[] = {
-#define ALL		(0xff << 24)
-#define NONE		(0)
-#define DISABLED	(1 << 16)
-#define ENABLED		(0 << 16)
-#define TRIGGER_EDGE	(0 << 15)
-#define TRIGGER_LEVEL	(1 << 15)
-#define POLARITY_HIGH	(0 << 13)
-#define POLARITY_LOW	(1 << 13)
-#define PHYSICAL_DEST	(0 << 11)
-#define LOGICAL_DEST	(1 << 11)
-#define ExtINT		(7 << 8)
-#define NMI		(4 << 8)
-#define SMI		(2 << 8)
-#define INT		(1 << 8)
-	/* IO-APIC virtual wire mode configuration */
-	/* mask, trigger, polarity, destination, delivery, vector */
-	{0,  ENABLED | TRIGGER_EDGE | POLARITY_HIGH | PHYSICAL_DEST | ExtINT, NONE},
-	{1,  DISABLED, NONE},
-	{2,  DISABLED, NONE},
-	{3,  DISABLED, NONE},
-	{4,  DISABLED, NONE},
-	{5,  DISABLED, NONE},
-	{6,  DISABLED, NONE},
-	{7,  DISABLED, NONE},
-	{8,  DISABLED, NONE},
-	{9,  DISABLED, NONE},
-	{10, DISABLED, NONE},
-	{11, DISABLED, NONE},
-	{12, DISABLED, NONE},
-	{13, DISABLED, NONE},
-	{14, DISABLED, NONE},
-	{15, DISABLED, NONE},
-	{16, DISABLED, NONE},
-	{17, DISABLED, NONE},
-	{18, DISABLED, NONE},
-	{19, DISABLED, NONE},
-	{20, DISABLED, NONE},
-	{21, DISABLED, NONE},
-	{22, DISABLED, NONE},
-	{23, DISABLED, NONE},
-	/* Be careful and don't write past the end... */
-};
-
-static void setup_ioapic(unsigned long ioapic_base)
-{
-	int i;
-	unsigned long value_low, value_high;
-	/* unsigned long ioapic_base = 0xfec00000; */
-	volatile unsigned long *l;
-	struct ioapicreg *a = ioapicregvalues;
-
-	ioapicregvalues[0].value_high = lapicid() << (56 - 32);
-
-	l = (unsigned long *)ioapic_base;
-
-	for (i = 0; i < ARRAY_SIZE(ioapicregvalues); i++, a++) {
-		l[0] = (a->reg * 2) + 0x10;
-		l[4] = a->value_low;
-		value_low = l[4];
-		l[0] = (a->reg * 2) + 0x11;
-		l[4] = a->value_high;
-		value_high = l[4];
-		if ((i == 0) && (value_low == 0xffffffff)) {
-			printk_warning("IO APIC not responding.\n");
-			return;
-		}
-		printk_spew("for IRQ, reg 0x%08x value 0x%08x 0x%08x\n",
-			    a->reg, a->value_low, a->value_high);
-	}
-}
-
 // 0x7a or e3
 #define PREVIOUS_POWER_STATE 0x7A
 
@@ -123,7 +47,7 @@
 	pci_write_config8(dev, 0x74, byte);
 	dword = pci_read_config32(dev, PCI_BASE_ADDRESS_1);	/* 0x14 */
 
-	setup_ioapic(dword);
+	setup_ioapic(dword, 0); // Don't rename IOAPIC ID
 
 #if 1
 	dword = pci_read_config32(dev, 0xe4);
Index: southbridge/nvidia/mcp55/mcp55_lpc.c
===================================================================
--- southbridge/nvidia/mcp55/mcp55_lpc.c	(revision 5009)
+++ southbridge/nvidia/mcp55/mcp55_lpc.c	(working copy)
@@ -33,97 +33,13 @@
 #include <pc80/isa-dma.h>
 #include <bitops.h>
 #include <arch/io.h>
+#include <arch/ioapic.h>
 #include <cpu/x86/lapic.h>
 #include <stdlib.h>
 #include "mcp55.h"
 
 #define NMI_OFF	0
 
-struct ioapicreg {
-	unsigned int reg;
-	unsigned int value_low, value_high;
-};
-
-static struct ioapicreg ioapicregvalues[] = {
-#define ALL		(0xff << 24)
-#define NONE		(0)
-#define DISABLED	(1 << 16)
-#define ENABLED		(0 << 16)
-#define TRIGGER_EDGE	(0 << 15)
-#define TRIGGER_LEVEL	(1 << 15)
-#define POLARITY_HIGH	(0 << 13)
-#define POLARITY_LOW	(1 << 13)
-#define PHYSICAL_DEST	(0 << 11)
-#define LOGICAL_DEST	(1 << 11)
-#define ExtINT		(7 << 8)
-#define NMI		(4 << 8)
-#define SMI		(2 << 8)
-#define INT		(1 << 8)
-	/* IO-APIC virtual wire mode configuration */
-	/* mask, trigger, polarity, destination, delivery, vector */
-	{   0, ENABLED | TRIGGER_EDGE | POLARITY_HIGH | PHYSICAL_DEST | ExtINT, NONE},
-	{   1, DISABLED, NONE},
-	{   2, DISABLED, NONE},
-	{   3, DISABLED, NONE},
-	{   4, DISABLED, NONE},
-	{   5, DISABLED, NONE},
-	{   6, DISABLED, NONE},
-	{   7, DISABLED, NONE},
-	{   8, DISABLED, NONE},
-	{   9, DISABLED, NONE},
-	{  10, DISABLED, NONE},
-	{  11, DISABLED, NONE},
-	{  12, DISABLED, NONE},
-	{  13, DISABLED, NONE},
-	{  14, DISABLED, NONE},
-	{  15, DISABLED, NONE},
-	{  16, DISABLED, NONE},
-	{  17, DISABLED, NONE},
-	{  18, DISABLED, NONE},
-	{  19, DISABLED, NONE},
-	{  20, DISABLED, NONE},
-	{  21, DISABLED, NONE},
-	{  22, DISABLED, NONE},
-	{  23, DISABLED, NONE},
-	/* Be careful and don't write past the end... */
-};
-
-static void setup_ioapic(unsigned long ioapic_base, int master)
-{
-	int i;
-	unsigned long value_low, value_high;
-//	unsigned long ioapic_base = 0xfec00000;
-	volatile unsigned long *l;
-	struct ioapicreg *a = ioapicregvalues;
-
-	if (master) {
-		ioapicregvalues[0].value_high = lapicid()<<(56-32);
-		ioapicregvalues[0].value_low = ENABLED | TRIGGER_EDGE | POLARITY_HIGH | PHYSICAL_DEST | ExtINT;
-	}
-	else {
-		ioapicregvalues[0].value_high = NONE;
-		ioapicregvalues[0].value_low = DISABLED;
-	}
-
-	l = (unsigned long *) ioapic_base;
-
-	for (i = 0; i < ARRAY_SIZE(ioapicregvalues);
-	     i++, a++) {
-		l[0] = (a->reg * 2) + 0x10;
-		l[4] = a->value_low;
-		value_low = l[4];
-		l[0] = (a->reg *2) + 0x11;
-		l[4] = a->value_high;
-		value_high = l[4];
-		if ((i==0) && (value_low == 0xffffffff)) {
-			printk_warning("IO APIC not responding.\n");
-			return;
-		}
-		printk_spew("for IRQ, reg 0x%08x value 0x%08x 0x%08x\n",
-			    a->reg, a->value_low, a->value_high);
-	}
-}
-
 // 0x7a or e3
 #define PREVIOUS_POWER_STATE	0x7A
 
@@ -139,15 +55,18 @@
 static void lpc_common_init(device_t dev, int master)
 {
 	uint8_t byte;
-	uint32_t dword;
+	uint32_t ioapic_base;
 
 	/* IO APIC initialization */
 	byte = pci_read_config8(dev, 0x74);
 	byte |= (1<<0); // enable APIC
 	pci_write_config8(dev, 0x74, byte);
-	dword = pci_read_config32(dev, PCI_BASE_ADDRESS_1); // 0x14
+	ioapic_base = pci_read_config32(dev, PCI_BASE_ADDRESS_1); // 0x14
 
-	setup_ioapic(dword, master);
+	if (master)
+		setup_ioapic(ioapic_base, 0);
+	else 
+		clear_ioapic(ioapic_base);
 }
 
 static void lpc_slave_init(device_t dev)
Index: southbridge/intel/esb6300/esb6300_pic.c
===================================================================
--- southbridge/intel/esb6300/esb6300_pic.c	(revision 5009)
+++ southbridge/intel/esb6300/esb6300_pic.c	(working copy)
@@ -6,50 +6,9 @@
 #include <device/pci.h>
 #include <device/pci_ids.h>
 #include <device/pci_ops.h>
+#include <arch/ioapic.h>
 #include "esb6300.h"
 
-#define ALL		(0xff << 24)
-#define NONE		(0)
-#define DISABLED	(1 << 16)
-#define ENABLED		(0 << 16)
-#define TRIGGER_EDGE	(0 << 15)
-#define TRIGGER_LEVEL	(1 << 15)
-#define POLARITY_HIGH	(0 << 13)
-#define POLARITY_LOW	(1 << 13)
-#define PHYSICAL_DEST	(0 << 11)
-#define LOGICAL_DEST	(1 << 11)
-#define ExtINT		(7 << 8)
-#define NMI		(4 << 8)
-#define SMI		(2 << 8)
-#define INT		(1 << 8)
-
-static void setup_ioapic(device_t dev)
-{
-	int i;
-	unsigned long value_low, value_high;
-	unsigned long ioapic_base = 0xfec10000;
-	volatile unsigned long *l;
-	unsigned interrupts;
-
-	l = (unsigned long *) ioapic_base;
-
-	l[0] = 0x01;
-	interrupts = (l[04] >> 16) & 0xff;
-	for (i = 0; i < interrupts; i++) {
-		l[0] = (i * 2) + 0x10;
-		l[4] = DISABLED;
-		value_low = l[4];
-		l[0] = (i * 2) + 0x11;
-		l[4] = NONE; /* Should this be an address? */
-		value_high = l[4];
-		if (value_low == 0xffffffff) {
-			printk_warning("%s IO APIC not responding.\n", 
-				dev_path(dev));
-			return;
-		}
-	}
-}
-
 static void pic_init(struct device *dev)
 {
 
@@ -64,7 +23,7 @@
 	pci_write_config8(dev, 0x3c, 0xff);
 
 	/* Setup the ioapic */
-	setup_ioapic(dev);
+	clear_ioapic(0xfec10000);
 }
 
 static void pic_read_resources(device_t dev)
Index: southbridge/intel/esb6300/esb6300_lpc.c
===================================================================
--- southbridge/intel/esb6300/esb6300_lpc.c	(revision 5009)
+++ southbridge/intel/esb6300/esb6300_lpc.c	(working copy)
@@ -9,6 +9,7 @@
 #include <pc80/mc146818rtc.h>
 #include <pc80/isa-dma.h>
 #include <arch/io.h>
+#include <arch/ioapic.h>
 #include "esb6300.h"
 
 #define ACPI_BAR 0x40
@@ -22,52 +23,6 @@
 #define CONFIG_MAINBOARD_POWER_ON_AFTER_POWER_FAIL MAINBOARD_POWER_ON
 #endif
 
-#define ALL		(0xff << 24)
-#define NONE		(0)
-#define DISABLED	(1 << 16)
-#define ENABLED		(0 << 16)
-#define TRIGGER_EDGE	(0 << 15)
-#define TRIGGER_LEVEL	(1 << 15)
-#define POLARITY_HIGH	(0 << 13)
-#define POLARITY_LOW	(1 << 13)
-#define PHYSICAL_DEST	(0 << 11)
-#define LOGICAL_DEST	(1 << 11)
-#define ExtINT		(7 << 8)
-#define NMI		(4 << 8)
-#define SMI		(2 << 8)
-#define INT		(1 << 8)
-
-static void setup_ioapic(device_t dev)
-{
-	int i;
-	unsigned long value_low, value_high;
-	unsigned long ioapic_base = 0xfec00000;
-	volatile unsigned long *l;
-	unsigned interrupts;
-
-	l = (unsigned long *) ioapic_base;
-
-	l[0] = 0x01;
-	interrupts = (l[04] >> 16) & 0xff;
-	for (i = 0; i < interrupts; i++) {
-		l[0] = (i * 2) + 0x10;
-		l[4] = DISABLED;
-		value_low = l[4];
-		l[0] = (i * 2) + 0x11;
-		l[4] = NONE; /* Should this be an address? */
-		value_high = l[4];
-		if (value_low == 0xffffffff) {
-			printk_warning("%d IO APIC not responding.\n",
-				dev_path(dev));
-			return;
-		}
-	}
-
-	/* Put the ioapic in virtual wire mode */
-	l[0] = 0 + 0x10;
-	l[4] = ENABLED | TRIGGER_EDGE | POLARITY_HIGH | PHYSICAL_DEST | ExtINT;
-}
-
 #define SERIRQ_CNTL 0x64
 static void esb6300_enable_serial_irqs(device_t dev)
 {
@@ -287,7 +242,7 @@
 	value |= (1 << 8)|(1<<7);
 	value |= (6 << 0)|(1<<13)|(1<<11);
 	pci_write_config32(dev, 0xd0, value);
-	setup_ioapic(dev);
+	setup_ioapic(0xfec00000, 0); // don't rename IO APIC ID
 
 	/* disable reset timer */
 	pci_write_config8(dev, 0xd4, 0x02);
Index: southbridge/intel/i82801er/i82801er_lpc.c
===================================================================
--- southbridge/intel/i82801er/i82801er_lpc.c	(revision 5009)
+++ southbridge/intel/i82801er/i82801er_lpc.c	(working copy)
@@ -9,6 +9,7 @@
 #include <pc80/mc146818rtc.h>
 #include <pc80/isa-dma.h>
 #include <arch/io.h>
+#include <arch/ioapic.h>
 #include "i82801er.h"
 
 #define ACPI_BAR 0x40
@@ -22,51 +23,6 @@
 #define CONFIG_MAINBOARD_POWER_ON_AFTER_POWER_FAIL MAINBOARD_POWER_ON
 #endif
 
-#define ALL		(0xff << 24)
-#define NONE		(0)
-#define DISABLED	(1 << 16)
-#define ENABLED		(0 << 16)
-#define TRIGGER_EDGE	(0 << 15)
-#define TRIGGER_LEVEL	(1 << 15)
-#define POLARITY_HIGH	(0 << 13)
-#define POLARITY_LOW	(1 << 13)
-#define PHYSICAL_DEST	(0 << 11)
-#define LOGICAL_DEST	(1 << 11)
-#define ExtINT		(7 << 8)
-#define NMI		(4 << 8)
-#define SMI		(2 << 8)
-#define INT		(1 << 8)
-
-static void setup_ioapic(void)
-{
-	int i;
-	unsigned long value_low, value_high;
-	unsigned long ioapic_base = 0xfec00000;
-	volatile unsigned long *l;
-	unsigned interrupts;
-
-	l = (unsigned long *) ioapic_base;
-
-	l[0] = 0x01;
-	interrupts = (l[04] >> 16) & 0xff;
-	for (i = 0; i < interrupts; i++) {
-		l[0] = (i * 2) + 0x10;
-		l[4] = DISABLED;
-		value_low = l[4];
-		l[0] = (i * 2) + 0x11;
-		l[4] = NONE; /* Should this be an address? */
-		value_high = l[4];
-		if (value_low == 0xffffffff) {
-			printk_warning("IO APIC not responding.\n");
-			return;
-		}
-	}
-
-	/* Put the ioapic in virtual wire mode */
-	l[0] = 0 + 0x10;
-	l[4] = ENABLED | TRIGGER_EDGE | POLARITY_HIGH | PHYSICAL_DEST | ExtINT;
-}
-
 #define SERIRQ_CNTL 0x64
 static void i82801er_enable_serial_irqs(device_t dev)
 {
@@ -292,7 +248,7 @@
 	value = pci_read_config32(dev, 0xd4);
 	value |= (1<<1);
 	pci_write_config32(dev, 0xd4, value);
-	setup_ioapic();
+	setup_ioapic(IO_APIC_ADDR, 0); // Don't rename IO APIC ID.
 
 	i82801er_enable_serial_irqs(dev);
 
Index: southbridge/intel/pxhd/pxhd_bridge.c
===================================================================
--- southbridge/intel/pxhd/pxhd_bridge.c	(revision 5009)
+++ southbridge/intel/pxhd/pxhd_bridge.c	(working copy)
@@ -8,6 +8,7 @@
 #include <device/pci_ops.h>
 #include <device/pcix.h>
 #include <pc80/mc146818rtc.h>
+#include <arch/ioapic.h>
 #include <delay.h>
 #include "pxhd.h"
 
@@ -159,63 +160,17 @@
         .device = 0x032a,
 };
 
-#define ALL		(0xff << 24)
-#define NONE		(0)
-#define DISABLED	(1 << 16)
-#define ENABLED		(0 << 16)
-#define TRIGGER_EDGE	(0 << 15)
-#define TRIGGER_LEVEL	(1 << 15)
-#define POLARITY_HIGH	(0 << 13)
-#define POLARITY_LOW	(1 << 13)
-#define PHYSICAL_DEST	(0 << 11)
-#define LOGICAL_DEST	(1 << 11)
-#define ExtINT		(7 << 8)
-#define NMI		(4 << 8)
-#define SMI		(2 << 8)
-#define INT		(1 << 8)
-	/* IO-APIC virtual wire mode configuration */
-	/* mask, trigger, polarity, destination, delivery, vector */
-
-static void setup_ioapic(device_t dev)
-{
-	int i;
-	unsigned long value_low, value_high;
-	unsigned long ioapic_base;
-	volatile unsigned long *l;
-	unsigned interrupts;
-
-	ioapic_base = pci_read_config32(dev, PCI_BASE_ADDRESS_0);
-	l = (unsigned long *) ioapic_base;
-
-	/* Enable front side bus delivery */
-	l[0] = 0x03;
-	l[4] = 1;
-
-	l[0] = 0x01;
-	interrupts = (l[04] >> 16) & 0xff;
-	for (i = 0; i < interrupts; i++) {
-		l[0] = (i * 2) + 0x10;
-		l[4] = DISABLED;
-		value_low = l[4];
-		l[0] = (i * 2) + 0x11;
-		l[4] = NONE; /* Should this be an address? */
-		value_high = l[4];
-		if (value_low == 0xffffffff) {
-			printk_warning("IO APIC not responding.\n");
-			return;
-		}
-	}
-}
-
 static void ioapic_init(device_t dev)
 {
-	uint32_t value;
+	uint32_t value, ioapic_base;
 	/* Enable bus mastering so IOAPICs work */
 	value = pci_read_config16(dev, PCI_COMMAND);
 	value |= PCI_COMMAND_MASTER;
 	pci_write_config16(dev, PCI_COMMAND, value);
 
-	setup_ioapic(dev);
+	ioapic_base = pci_read_config32(dev, PCI_BASE_ADDRESS_0);
+
+	setup_ioapic(ioapic_base, 0); // Don't rename IOAPIC ID
 }
 
 static void intel_set_subsystem(device_t dev, unsigned vendor, unsigned device)
Index: southbridge/intel/i3100/i3100_lpc.c
===================================================================
--- southbridge/intel/i3100/i3100_lpc.c	(revision 5009)
+++ southbridge/intel/i3100/i3100_lpc.c	(working copy)
@@ -29,6 +29,7 @@
 #include <pc80/mc146818rtc.h>
 #include <pc80/isa-dma.h>
 #include <arch/io.h>
+#include <arch/ioapic.h>
 #include "i3100.h"
 
 #define ACPI_BAR 0x40
@@ -49,60 +50,6 @@
 #define CONFIG_MAINBOARD_POWER_ON_AFTER_POWER_FAIL MAINBOARD_POWER_ON
 #endif
 
-#define ALL		(0xff << 24)
-#define NONE		(0)
-#define DISABLED	(1 << 16)
-#define ENABLED		(0 << 16)
-#define TRIGGER_EDGE	(0 << 15)
-#define TRIGGER_LEVEL	(1 << 15)
-#define POLARITY_HIGH	(0 << 13)
-#define POLARITY_LOW	(1 << 13)
-#define PHYSICAL_DEST	(0 << 11)
-#define LOGICAL_DEST	(1 << 11)
-#define ExtINT		(7 << 8)
-#define NMI		(4 << 8)
-#define SMI		(2 << 8)
-#define INT		(1 << 8)
-
-static void setup_ioapic(device_t dev)
-{
-	int i;
-	u32 value_low, value_high;
-	u32 ioapic_base = 0xfec00000;
-	volatile u32 *l;
-	u32 interrupts;
-	struct resource *res;
-
-	/* Enable IO APIC */
-	res = find_resource(dev, RCBA);
-	if (!res) {
-		return;
-	}
-	*((u8 *)(res->base + 0x31ff)) |= (1 << 0);
-
-	l = (u32 *) ioapic_base;
-
-	l[0] = 0x01;
-	interrupts = (l[04] >> 16) & 0xff;
-	for (i = 0; i < interrupts; i++) {
-		l[0] = (i * 2) + 0x10;
-		l[4] = DISABLED;
-		value_low = l[4];
-		l[0] = (i * 2) + 0x11;
-		l[4] = NONE; /* Should this be an address? */
-		value_high = l[4];
-		if (value_low == 0xffffffff) {
-			printk_warning("%d IO APIC not responding.\n",
-				dev_path(dev));
-			return;
-		}
-	}
-
-	/* Put the APIC in virtual wire mode */
-	l[0] = 0x12;
-	l[4] = ENABLED | TRIGGER_EDGE | POLARITY_HIGH | PHYSICAL_DEST | ExtINT;
-}
-
 static void i3100_enable_serial_irqs(device_t dev)
 {
 	/* set packet length and toggle silent mode bit */
@@ -363,8 +310,20 @@
 
 static void lpc_init(struct device *dev)
 {
-	setup_ioapic(dev);
+	struct resource *res;
 
+	/* Enable IO APIC */
+	res = find_resource(dev, RCBA);
+	if (!res) {
+		return;
+	}
+	*((u8 *)(res->base + 0x31ff)) |= (1 << 0);
+
+	// TODO this code sets int 0 of the IOAPIC in Virtual Wire Mode
+	// (register 0x10/0x11) while the old code used int 1 (register 0x12)
+	// ... Why? 
+	setup_ioapic(IO_APIC_ADDR, 0); // Don't rename IOAPIC ID
+
 	/* Decode 0xffc00000 - 0xffffffff to fwh idsel 0 */
 	pci_write_config32(dev, 0xd0, 0x00000000);
 
Index: southbridge/sis/sis966/sis966_lpc.c
===================================================================
--- southbridge/sis/sis966/sis966_lpc.c	(revision 5009)
+++ southbridge/sis/sis966/sis966_lpc.c	(working copy)
@@ -35,6 +35,7 @@
 #include <pc80/isa-dma.h>
 #include <bitops.h>
 #include <arch/io.h>
+#include <arch/ioapic.h>
 #include <cpu/x86/lapic.h>
 #include <stdlib.h>
 #include "sis966.h"
@@ -42,84 +43,6 @@
 
 #define NMI_OFF	0
 
-struct ioapicreg {
-	unsigned int reg;
-	unsigned int value_low, value_high;
-};
-
-static struct ioapicreg ioapicregvalues[] = {
-#define ALL		(0xff << 24)
-#define NONE		(0)
-#define DISABLED	(1 << 16)
-#define ENABLED		(0 << 16)
-#define TRIGGER_EDGE	(0 << 15)
-#define TRIGGER_LEVEL	(1 << 15)
-#define POLARITY_HIGH	(0 << 13)
-#define POLARITY_LOW	(1 << 13)
-#define PHYSICAL_DEST	(0 << 11)
-#define LOGICAL_DEST	(1 << 11)
-#define ExtINT		(7 << 8)
-#define NMI		(4 << 8)
-#define SMI		(2 << 8)
-#define INT		(1 << 8)
-	/* IO-APIC virtual wire mode configuration */
-	/* mask, trigger, polarity, destination, delivery, vector */
-	{   0, ENABLED | TRIGGER_EDGE | POLARITY_HIGH | PHYSICAL_DEST | ExtINT, NONE},
-	{   1, DISABLED, NONE},
-	{   2, DISABLED, NONE},
-	{   3, DISABLED, NONE},
-	{   4, DISABLED, NONE},
-	{   5, DISABLED, NONE},
-	{   6, DISABLED, NONE},
-	{   7, DISABLED, NONE},
-	{   8, DISABLED, NONE},
-	{   9, DISABLED, NONE},
-	{  10, DISABLED, NONE},
-	{  11, DISABLED, NONE},
-	{  12, DISABLED, NONE},
-	{  13, DISABLED, NONE},
-	{  14, DISABLED, NONE},
-	{  15, DISABLED, NONE},
-	{  16, DISABLED, NONE},
-	{  17, DISABLED, NONE},
-	{  18, DISABLED, NONE},
-	{  19, DISABLED, NONE},
-	{  20, DISABLED, NONE},
-	{  21, DISABLED, NONE},
-	{  22, DISABLED, NONE},
-	{  23, DISABLED, NONE},
-	/* Be careful and don't write past the end... */
-};
-
-static void setup_ioapic(unsigned long ioapic_base)
-{
-	int i;
-	unsigned long value_low, value_high;
-//	unsigned long ioapic_base = 0xfec00000;
-	volatile unsigned long *l;
-	struct ioapicreg *a = ioapicregvalues;
-
-	ioapicregvalues[0].value_high = lapicid()<<(56-32);
-
-	l = (unsigned long *) ioapic_base;
-
-	for (i = 0; i < ARRAY_SIZE(ioapicregvalues);
-	     i++, a++) {
-		l[0] = (a->reg * 2) + 0x10;
-		l[4] = a->value_low;
-		value_low = l[4];
-		l[0] = (a->reg *2) + 0x11;
-		l[4] = a->value_high;
-		value_high = l[4];
-		if ((i==0) && (value_low == 0xffffffff)) {
-			printk_warning("IO APIC not responding.\n");
-			return;
-		}
-		printk_spew("for IRQ, reg 0x%08x value 0x%08x 0x%08x\n",
-			    a->reg, a->value_low, a->value_high);
-	}
-}
-
 // 0x7a or e3
 #define PREVIOUS_POWER_STATE	0x7A
 
@@ -135,16 +58,15 @@
 static void lpc_common_init(device_t dev)
 {
 	uint8_t byte;
-	uint32_t dword;
+	uint32_t ioapic_base;
 
 	/* IO APIC initialization */
 	byte = pci_read_config8(dev, 0x74);
 	byte |= (1<<0); // enable APIC
 	pci_write_config8(dev, 0x74, byte);
-	dword = pci_read_config32(dev, PCI_BASE_ADDRESS_1); // 0x14
+	ioapic_base = pci_read_config32(dev, PCI_BASE_ADDRESS_1); // 0x14
 
-	setup_ioapic(dword);
-
+	setup_ioapic(ioapic_base, 0); // Don't rename IO APIC ID
 }
 
 static void lpc_slave_init(device_t dev)
Index: mainboard/bcom/winnetp680/Options.lb
===================================================================
--- mainboard/bcom/winnetp680/Options.lb	(revision 5009)
+++ mainboard/bcom/winnetp680/Options.lb	(working copy)
@@ -62,10 +62,12 @@
 uses CONFIG_PCI_ROM_RUN
 uses CONFIG_CONSOLE_VGA
 uses CONFIG_VIDEO_MB
+uses CONFIG_SMP
 uses CONFIG_IOAPIC
 
 default CONFIG_ROM_SIZE = 512 * 1024
-default CONFIG_IOAPIC = 0
+default CONFIG_SMP = 1
+default CONFIG_IOAPIC = 1
 default CONFIG_VIDEO_MB = 32
 default CONFIG_CONSOLE_SERIAL8250 = 1
 default CONFIG_PCI_ROM_RUN = 0
Index: mainboard/gigabyte/ga_2761gxdk/Options.lb
===================================================================
--- mainboard/gigabyte/ga_2761gxdk/Options.lb	(revision 5009)
+++ mainboard/gigabyte/ga_2761gxdk/Options.lb	(working copy)
@@ -181,7 +181,7 @@
 ## Build code for SMP support
 ## Only worry about 2 micro processors
 ##
-default CONFIG_SMP=0
+default CONFIG_SMP=1
 default CONFIG_MAX_CPUS=2
 default CONFIG_MAX_PHYSICAL_CPUS=1
 default CONFIG_LOGICAL_CPUS=1
Index: mainboard/asi/mb_5blmp/Options.lb
===================================================================
--- mainboard/asi/mb_5blmp/Options.lb	(revision 5009)
+++ mainboard/asi/mb_5blmp/Options.lb	(working copy)
@@ -1,4 +1,5 @@
 uses CONFIG_GENERATE_PIRQ_TABLE
+uses CONFIG_GENERATE_MP_TABLE
 uses CONFIG_USE_FALLBACK_IMAGE
 uses CONFIG_HAVE_FALLBACK_BOOT
 uses CONFIG_HAVE_HARD_RESET
@@ -70,6 +71,7 @@
 default CONFIG_GENERATE_PIRQ_TABLE=1
 default CONFIG_IRQ_SLOT_COUNT=5
 default CONFIG_PIRQ_ROUTE=1
+default CONFIG_GENERATE_MP_TABLE=0
 
 ##
 ## Build code to export a CMOS option table
Index: mainboard/via/epia-cn/Options.lb
===================================================================
--- mainboard/via/epia-cn/Options.lb	(revision 5009)
+++ mainboard/via/epia-cn/Options.lb	(working copy)
@@ -68,7 +68,7 @@
 
 default CONFIG_MAINBOARD_PCI_SUBSYSTEM_VENDOR_ID = 0x1019
 default CONFIG_ROM_SIZE = 512 * 1024
-default CONFIG_IOAPIC = 0
+default CONFIG_IOAPIC = 1
 default CONFIG_VIDEO_MB = 32
 default CONFIG_CONSOLE_SERIAL8250 = 1
 default CONFIG_PCI_ROM_RUN = 0
Index: mainboard/via/pc2500e/Options.lb
===================================================================
--- mainboard/via/pc2500e/Options.lb	(revision 5009)
+++ mainboard/via/pc2500e/Options.lb	(working copy)
@@ -71,7 +71,7 @@
 default CONFIG_ROM_SIZE = 512 * 1024
 default CONFIG_ROM_IMAGE_SIZE = 64 * 1024
 default CONFIG_FALLBACK_SIZE = CONFIG_ROM_IMAGE_SIZE
-default CONFIG_IOAPIC = 0
+default CONFIG_IOAPIC = 1
 default CONFIG_VIDEO_MB = 32
 default CONFIG_CONSOLE_SERIAL8250 = 1
 default CONFIG_PCI_ROM_RUN = 0
Index: mainboard/jetway/j7f24/Options.lb
===================================================================
--- mainboard/jetway/j7f24/Options.lb	(revision 5009)
+++ mainboard/jetway/j7f24/Options.lb	(working copy)
@@ -66,7 +66,7 @@
 uses CONFIG_IOAPIC
 
 default CONFIG_ROM_SIZE = 512 * 1024
-default CONFIG_IOAPIC = 0
+default CONFIG_IOAPIC = 1
 default CONFIG_VIDEO_MB = 32
 default CONFIG_CONSOLE_SERIAL8250 = 1
 default CONFIG_PCI_ROM_RUN = 0
Index: northbridge/via/cx700/cx700_lpc.c
===================================================================
--- northbridge/via/cx700/cx700_lpc.c	(revision 5009)
+++ northbridge/via/cx700/cx700_lpc.c	(working copy)
@@ -31,103 +31,12 @@
 #include <pc80/isa-dma.h>
 
 #include <cpu/x86/lapic.h>
+#include <arch/ioapic.h>
 #include <stdlib.h>
 
 #define ACPI_IO_BASE	0x400
 #define HPET_ADDR	0xfe800000UL
-#define IOAPIC_ADDR	0xfec00000ULL
 
-#if CONFIG_IOAPIC
-struct ioapicreg {
-	unsigned int reg;
-	unsigned int value_low, value_high;
-};
-
-static struct ioapicreg ioapicregvalues[] = {
-#define ALL		(0xff << 24)
-#define NONE		(0)
-#define DISABLED	(1 << 16)
-#define ENABLED		(0 << 16)
-#define TRIGGER_EDGE	(0 << 15)
-#define TRIGGER_LEVEL	(1 << 15)
-#define POLARITY_HIGH	(0 << 13)
-#define POLARITY_LOW	(1 << 13)
-#define PHYSICAL_DEST	(0 << 11)
-#define LOGICAL_DEST	(1 << 11)
-#define ExtINT		(7 << 8)
-#define NMI		(4 << 8)
-#define SMI		(2 << 8)
-#define INT		(1 << 8)
-	/* IO-APIC virtual wire mode configuration */
-	/* mask, trigger, polarity, destination, delivery, vector */
-	{ 0, ENABLED | TRIGGER_EDGE | POLARITY_HIGH | PHYSICAL_DEST | ExtINT, NONE},
-	{ 1, DISABLED, NONE},
-	{ 2, DISABLED, NONE},
-	{ 3, DISABLED, NONE},
-	{ 4, DISABLED, NONE},
-	{ 5, DISABLED, NONE},
-	{ 6, DISABLED, NONE},
-	{ 7, DISABLED, NONE},
-	{ 8, DISABLED, NONE},
-	{ 9, DISABLED, NONE},
-	{10, DISABLED, NONE},
-	{11, DISABLED, NONE},
-	{12, DISABLED, NONE},
-	{13, DISABLED, NONE},
-	{14, DISABLED, NONE},
-	{15, DISABLED, NONE},
-	{16, DISABLED, NONE},
-	{17, DISABLED, NONE},
-	{18, DISABLED, NONE},
-	{19, DISABLED, NONE},
-	{20, DISABLED, NONE},
-	{21, DISABLED, NONE},
-	{22, DISABLED, NONE},
-	{23, DISABLED, NONE},
-};
-
-static void setup_ioapic(void)
-{
-	int i;
-	unsigned long value_low, value_high, val;
-	unsigned long ioapic_base = IOAPIC_ADDR;
-	volatile unsigned long *l;
-	struct ioapicreg *a = ioapicregvalues;
-	unsigned long bsp_lapicid = lapicid();
-
-	l = (unsigned long *)ioapic_base;
-
-	/* Set APIC ADDR */
-	l[0] = 0;
-	val = l[4];
-	l[4] = (val & 0xF0FFFF) | (2 << 24);	// 2 == ID as programmed elsewhere. should be a define? XXX
-
-	/* Set APIC to FSB message bus. */
-	l[0] = 0x3;
-	val = l[4];
-	l[4] = (val & 0xFFFFFE) | 1;
-
-	ioapicregvalues[0].value_high = bsp_lapicid << (56 - 32);
-
-	printk_debug("IOAPIC:  Bootstrap Processor Local APIC ID = %02x\n", bsp_lapicid);
-
-	for (i = 0; i < ARRAY_SIZE(ioapicregvalues); i++, a++) {
-		l[0] = (a->reg * 2) + 0x10;
-		l[4] = a->value_low;
-		value_low = l[4];
-		l[0] = (a->reg * 2) + 0x11;
-		l[4] = a->value_high;
-		value_high = l[4];
-		if ((i == 0) && (value_low == 0xffffffff)) {
-			printk_warning("IOAPIC is not responding.\n");
-			return;
-		}
-		printk_debug("IOAPIC: IRQ reg 0x%08x value 0x%08x 0x%08x\n",
-			     a->reg, a->value_low, a->value_high);
-	}
-}
-#endif
-
 static const unsigned char pci_irqs[4] = { 11, 11, 10, 10 };
 
 static const unsigned char usb_pins[4] = { 'A', 'B', 'C', 'D' };
@@ -369,7 +278,8 @@
 	cx700_set_lpc_registers(dev);
 
 #if CONFIG_IOAPIC
-	setup_ioapic();
+#define IO_APIC_ID 2
+	setup_ioapic(IO_APIC_ADDR, IO_APIC_ID);
 #endif
 
 	/* Initialize interrupts */
Index: arch/i386/smp/Config.lb
===================================================================
--- arch/i386/smp/Config.lb	(revision 5009)
+++ arch/i386/smp/Config.lb	(working copy)
@@ -1,8 +1,10 @@
 uses CONFIG_GENERATE_MP_TABLE
+uses CONFIG_IOAPIC
 
 if CONFIG_GENERATE_MP_TABLE
   object mpspec.o 
 end
-#object ioapic.o CONFIG_IOAPIC
+if CONFIG_IOAPIC
+  object ioapic.o
+end
 
-
Index: arch/i386/smp/Makefile.inc
===================================================================
--- arch/i386/smp/Makefile.inc	(revision 5009)
+++ arch/i386/smp/Makefile.inc	(working copy)
@@ -1,4 +1,3 @@
 obj-$(CONFIG_GENERATE_MP_TABLE) += mpspec.o
-# what about this: how awkward.
-#object ioapic.o CONFIG_IOAPIC
+obj-$(CONFIG_IOAPIC) += ioapic.o
 
Index: arch/i386/smp/ioapic.c
===================================================================
--- arch/i386/smp/ioapic.c	(revision 5009)
+++ arch/i386/smp/ioapic.c	(working copy)
@@ -1,85 +1,135 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2010 coresystems GmbH
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
+ */
+
+#include <arch/io.h>
+#include <arch/ioapic.h>
 #include <console/console.h>
-#include <arch/ioapic.h>
+#include <cpu/x86/lapic.h>
 
-/* we have to do more than we thought. I assumed Linux would do all the
- * interesting parts, and I was wrong. 
- */
-struct ioapicreg {
-	unsigned int reg;
-	unsigned int value_low, value_high;
-};
-struct ioapicreg ioapicregvalues[] = {
-#define ALL		(0xff << 24)
-#define NONE		(0)
-#define DISABLED	(1 << 16)
-#define ENABLED		(0 << 16)
-#define TRIGGER_EDGE	(0 << 15)
-#define TRIGGER_LEVEL	(1 << 15)
-#define POLARITY_HIGH	(0 << 13)
-#define POLARITY_LOW	(1 << 13)
-#define PHYSICAL_DEST	(0 << 11)
-#define LOGICAL_DEST	(1 << 11)
-#define ExtINT		(7 << 8)
-#define NMI		(4 << 8)
-#define SMI		(2 << 8)
-#define INT		(1 << 8)
-	/* mask, trigger, polarity, destination, delivery, vector */
-	{0x00, DISABLED, NONE},
-	{0x01, DISABLED, NONE},
-	{0x02, DISABLED, NONE},
-	{0x03, DISABLED, NONE},
-	{0x04, DISABLED, NONE},
-	{0x05, DISABLED, NONE},
-	{0x06, DISABLED, NONE},
-	{0x07, DISABLED, NONE},
-	{0x08, DISABLED, NONE},
-	{0x09, DISABLED, NONE},
-	{0x0a, DISABLED, NONE},
-	{0x0b, DISABLED, NONE},
-	{0x0c, DISABLED, NONE},
-	{0x0d, DISABLED, NONE},
-	{0x0e, DISABLED, NONE},
-	{0x0f, DISABLED, NONE},
-	{0x10, DISABLED, NONE},
-	{0x11, DISABLED, NONE},
-	{0x12, DISABLED, NONE},
-	{0x13, DISABLED, NONE},
-	{0x14, DISABLED, NONE},
-	{0x14, DISABLED, NONE},
-	{0x15, DISABLED, NONE},
-	{0x16, DISABLED, NONE},
-	{0x17, DISABLED, NONE},
-};
+static u32 io_apic_read(u32 ioapic_base, u32 reg)
+{
+	write32(ioapic_base, reg);
+	return read32(ioapic_base + 0x10);
+}
 
-void setup_ioapic(void)
+static void io_apic_write(u32 ioapic_base, u32 reg, u32 value)
 {
-	int i;
-	unsigned long value_low, value_high;
-	unsigned long ioapicaddr = 0xfec00000;
-	volatile unsigned long *l;
-	struct ioapicreg *a = ioapicregvalues;
+	write32(ioapic_base, reg);
+	write32(ioapic_base + 0x10, value);
+}
 
-	l = (unsigned long *) ioapicaddr;
-#if defined(i786)
-	/* For the pentium 4 and above apic deliver their interrupts
+
+void clear_ioapic(u32 ioapic_base)
+{
+	u32 low, high;
+	u32 i, ioapic_interrupts;
+
+	printk_debug("IOAPIC: Clearing IOAPIC at 0x%08x\n", ioapic_base); 
+
+	/* Read the available number of interrupts */
+	ioapic_interrupts = (io_apic_read(ioapic_base, 1) >> 16) & 0xff;
+	if (!ioapic_interrupts || ioapic_interrupts == 0xff)
+		ioapic_interrupts = 24;
+	printk_debug("IOAPIC: %d interrupts\n", ioapic_interrupts); 
+
+	low = DISABLED;
+	high = NONE;
+
+	for (i = 0; i < ioapic_interrupts; i++) {
+		io_apic_write(ioapic_base, i * 2 + 0x10, low);
+		io_apic_write(ioapic_base, i * 2 + 0x11, high);
+
+		printk_spew("IOAPIC: reg 0x%08x value 0x%08x 0x%08x\n", i, high, low);
+	}
+
+	if (io_apic_read(ioapic_base, 0x10) == 0xffffffff) {
+		printk_warning("IO APIC not responding.\n");
+		return;
+	}
+}
+
+void setup_ioapic(u32 ioapic_base, u8 ioapic_id)
+{
+	u32 bsp_lapicid = lapicid();
+	u32 low, high;
+	u32 i, ioapic_interrupts;
+
+	printk_debug("IOAPIC: Initializing IOAPIC at 0x%08x\n", ioapic_base); 
+	printk_debug("IOAPIC: Bootstrap Processor Local APIC = %02x\n",
+			bsp_lapicid);
+
+	if (ioapic_id) {
+		printk_debug("IOAPIC: ID = 0x%02x\n", ioapic_id); 
+		/* Set IOAPIC ID if it has been specified */
+		io_apic_write(ioapic_base, 0x00, 
+			(io_apic_read(ioapic_base, 0x00) & 0xfff0ffff) | 
+				(ioapic_id << 24));
+	}
+
+	/* Read the available number of interrupts */
+	ioapic_interrupts = (io_apic_read(ioapic_base, 1) >> 16) & 0xff;
+	if (!ioapic_interrupts || ioapic_interrupts == 0xff)
+		ioapic_interrupts = 24;
+	printk_debug("IOAPIC: %d interrupts\n", ioapic_interrupts); 
+
+
+// XXX this decision should probably be made elsewhere, and
+// it's the C3, not the EPIA this depends on.
+#if defined(CONFIG_EPIA_VT8237R_INIT) && CONFIG_EPIA_VT8237R_INIT
+#define IOAPIC_INTERRUPTS_ON_APIC_SERIAL_BUS
+#else
+#define IOAPIC_INTERRUPTS_ON_FSB
+#endif
+
+#ifdef IOAPIC_INTERRUPTS_ON_FSB
+	/* For the Pentium 4 and above APICs deliver their interrupts
 	 * on the front side bus, enable that.
 	 */
-	l[0] = 0x03;
-	l[4] = 1;
-#endif /* i786 */
-	for (i = 0; i < ARRAY_SIZE(ioapicregvalues);
-	     i++, a++) {
-		l[0] = (a->reg * 2) + 0x10;
-		l[4] = a->value_low;
-		value_low = l[4];
-		l[0] = (a->reg *2) + 0x11;
-		l[4] = a->value_high;
-		value_high = l[4];
-		if ((i==0) && (value_low == 0xffffffff)) {
-			printk_warning("IO APIC not responding.\n");
-			return;
-		}
-		printk_spew("for IRQ, reg 0x%08x value 0x%08x 0x%08x\n", 
-			a->reg, a->value_low, a->value_high);
+	printk_debug("IOAPIC: Enabling interrupts on FSB\n"); 
+	io_apic_write(ioapic_base, 0x03, io_apic_read(ioapic_base, 0x03) | (1 << 0));
+#endif
+#ifdef IOAPIC_INTERRUPTS_ON_APIC_SERIAL_BUS
+	printk_debug("IOAPIC: Enabling interrupts on APIC serial bus\n"); 
+	io_apic_write(ioapic_base, 0x03, 0);
+#endif
+
+	/* Enable Virtual Wire Mode */
+	low = ENABLED | TRIGGER_EDGE | POLARITY_HIGH | PHYSICAL_DEST | ExtINT;
+	high = bsp_lapicid << (56 - 32);
+
+	io_apic_write(ioapic_base, 0x10, low);
+	io_apic_write(ioapic_base, 0x11, high);
+
+	if (io_apic_read(ioapic_base, 0x10) == 0xffffffff) {
+		printk_warning("IO APIC not responding.\n");
+		return;
 	}
+
+	printk_spew("IOAPIC: reg 0x%08x value 0x%08x 0x%08x\n", 0, high, low);
+
+	low = DISABLED;
+	high = NONE;
+
+	for (i = 1; i < ioapic_interrupts; i++) {
+		io_apic_write(ioapic_base, i * 2 + 0x10, low);
+		io_apic_write(ioapic_base, i * 2 + 0x11, high);
+
+		printk_spew("IOAPIC: reg 0x%08x value 0x%08x 0x%08x\n", i, high, low);
+	}
 }
Index: arch/i386/Config.lb
===================================================================
--- arch/i386/Config.lb	(revision 5009)
+++ arch/i386/Config.lb	(working copy)
@@ -70,6 +70,4 @@
 
 dir lib
 dir boot
-if CONFIG_SMP
-	dir smp
-end
+dir smp
Index: arch/i386/include/arch/ioapic.h
===================================================================
--- arch/i386/include/arch/ioapic.h	(revision 0)
+++ arch/i386/include/arch/ioapic.h	(revision 0)
@@ -0,0 +1,46 @@
+/*
+ * coreboot IOAPIC support
+ *
+ * Copyright (C) 2010 coresystems GmbH
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; version 2 of
+ * the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
+ * MA 02110-1301 USA
+ */
+
+#ifndef __I386_ARCH_IOAPIC_H
+#define __I386_ARCH_IOAPIC_H
+
+#define IO_APIC_ADDR	0xfec00000UL
+#define IO_APIC_INTERRUPTS 24
+
+#define ALL		(0xff << 24)
+#define NONE		(0)
+#define DISABLED	(1 << 16)
+#define ENABLED		(0 << 16)
+#define TRIGGER_EDGE	(0 << 15)
+#define TRIGGER_LEVEL	(1 << 15)
+#define POLARITY_HIGH	(0 << 13)
+#define POLARITY_LOW	(1 << 13)
+#define PHYSICAL_DEST	(0 << 11)
+#define LOGICAL_DEST	(1 << 11)
+#define ExtINT		(7 << 8)
+#define NMI		(4 << 8)
+#define SMI		(2 << 8)
+#define INT		(1 << 8)
+
+void setup_ioapic(u32 ioapic_base, u8 ioapic_id);
+void clear_ioapic(u32 ioapic_base);
+
+#endif
Index: arch/i386/include/arch/acpi.h
===================================================================
--- arch/i386/include/arch/acpi.h	(revision 5009)
+++ arch/i386/include/arch/acpi.h	(working copy)
@@ -425,8 +425,6 @@
 	gsi_base+=4;					\
 } while(0);
 
-#define IO_APIC_ADDR	0xfec00000UL
-
 #else // CONFIG_GENERATE_ACPI_TABLES
 
 #define write_acpi_tables(start) (start)
