diff options
Diffstat (limited to 'arch/i386/kernel/io_apic.c')
-rw-r--r-- | arch/i386/kernel/io_apic.c | 33 |
1 files changed, 32 insertions, 1 deletions
diff --git a/arch/i386/kernel/io_apic.c b/arch/i386/kernel/io_apic.c index 3c2b3bdfc807..fc81c8cddd22 100644 --- a/arch/i386/kernel/io_apic.c +++ b/arch/i386/kernel/io_apic.c | |||
@@ -1636,12 +1636,43 @@ static void __init enable_IO_APIC(void) | |||
1636 | */ | 1636 | */ |
1637 | void disable_IO_APIC(void) | 1637 | void disable_IO_APIC(void) |
1638 | { | 1638 | { |
1639 | int pin; | ||
1639 | /* | 1640 | /* |
1640 | * Clear the IO-APIC before rebooting: | 1641 | * Clear the IO-APIC before rebooting: |
1641 | */ | 1642 | */ |
1642 | clear_IO_APIC(); | 1643 | clear_IO_APIC(); |
1643 | 1644 | ||
1644 | disconnect_bsp_APIC(); | 1645 | /* |
1646 | * If the i82559 is routed through an IOAPIC | ||
1647 | * Put that IOAPIC in virtual wire mode | ||
1648 | * so legacy interrups can be delivered. | ||
1649 | */ | ||
1650 | pin = find_isa_irq_pin(0, mp_ExtINT); | ||
1651 | if (pin != -1) { | ||
1652 | struct IO_APIC_route_entry entry; | ||
1653 | unsigned long flags; | ||
1654 | |||
1655 | memset(&entry, 0, sizeof(entry)); | ||
1656 | entry.mask = 0; /* Enabled */ | ||
1657 | entry.trigger = 0; /* Edge */ | ||
1658 | entry.irr = 0; | ||
1659 | entry.polarity = 0; /* High */ | ||
1660 | entry.delivery_status = 0; | ||
1661 | entry.dest_mode = 0; /* Physical */ | ||
1662 | entry.delivery_mode = 7; /* ExtInt */ | ||
1663 | entry.vector = 0; | ||
1664 | entry.dest.physical.physical_dest = 0; | ||
1665 | |||
1666 | |||
1667 | /* | ||
1668 | * Add it to the IO-APIC irq-routing table: | ||
1669 | */ | ||
1670 | spin_lock_irqsave(&ioapic_lock, flags); | ||
1671 | io_apic_write(0, 0x11+2*pin, *(((int *)&entry)+1)); | ||
1672 | io_apic_write(0, 0x10+2*pin, *(((int *)&entry)+0)); | ||
1673 | spin_unlock_irqrestore(&ioapic_lock, flags); | ||
1674 | } | ||
1675 | disconnect_bsp_APIC(pin != -1); | ||
1645 | } | 1676 | } |
1646 | 1677 | ||
1647 | /* | 1678 | /* |