From: Eric W. Biederman Restore an ioapic to virtual wire mode on reboot if it has an ExtInt input. Signed-off-by: Andrew Morton --- 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-12-03 20:56:47.074603760 -0800 +++ 25-akpm/arch/i386/kernel/io_apic.c 2004-12-03 20:56:47.079603000 -0800 @@ -1630,11 +1630,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(); } _