
From: Eric W. Biederman <ebiederm@xmission.com>

Restore an ioapic to virtual wire mode on reboot if it has an ExtInt input.

Signed-off-by: Andrew Morton <akpm@osdl.org>
---

 25-akpm/arch/i386/kernel/io_apic.c |   31 +++++++++++++++++++++++++++++++
 1 files changed, 31 insertions(+)

diff -puN arch/i386/kernel/io_apic.c~kexec-ioapic-virtwire-on-shutdowni386 arch/i386/kernel/io_apic.c
--- 25/arch/i386/kernel/io_apic.c~kexec-ioapic-virtwire-on-shutdowni386	2004-11-03 20:25:59.146758408 -0800
+++ 25-akpm/arch/i386/kernel/io_apic.c	2004-11-03 20:25:59.151757648 -0800
@@ -1627,11 +1627,42 @@ static void __init enable_IO_APIC(void)
  */
 void disable_IO_APIC(void)
 {
+	int pin;
 	/*
 	 * Clear the IO-APIC before rebooting:
 	 */
 	clear_IO_APIC();
 
+	/*
+	 * If the i82559 is routed through an IOAPIC
+	 * Put that IOAPIC in virtual wire mode
+	 * so legacy interrups can be delivered.
+	 */
+	pin = find_isa_irq_pin(0, mp_ExtINT);
+	if (pin != -1) {
+		struct IO_APIC_route_entry entry;
+		unsigned long flags;
+
+		memset(&entry, 0, sizeof(entry));
+		entry.mask            = 0; /* Enabled */
+		entry.trigger         = 0; /* Edge */
+		entry.irr             = 0;
+		entry.polarity        = 0; /* High */
+		entry.delivery_status = 0;
+		entry.dest_mode       = 0; /* Physical */
+		entry.delivery_mode   = 7; /* ExtInt */
+		entry.vector          = 0;
+		entry.dest.physical.physical_dest = 0;
+
+
+		/*
+		 * Add it to the IO-APIC irq-routing table:
+		 */
+		spin_lock_irqsave(&ioapic_lock, flags);
+		io_apic_write(0, 0x11+2*pin, *(((int *)&entry)+1));
+		io_apic_write(0, 0x10+2*pin, *(((int *)&entry)+0));
+		spin_unlock_irqrestore(&ioapic_lock, flags);
+	}
 	disconnect_bsp_APIC();
 }
 
_
