diff options
author | Liav A <liavalb@gmail.com> | 2020-03-20 16:52:14 +0200 |
---|---|---|
committer | Andreas Kling <kling@serenityos.org> | 2020-03-24 16:15:33 +0100 |
commit | cb676f12111f52bbb3fb9b784a8b88a998729353 (patch) | |
tree | 741b2c59d6c0f7a0ea4bfa2bb5d1611dfbffb514 | |
parent | 06e7fc9deea669ef25eb27352b7681ef262bf906 (diff) | |
download | serenity-cb676f12111f52bbb3fb9b784a8b88a998729353.zip |
Interrupts: Do a specific EOI when using the PIC
Before this change, we did a non-specific EOI, which could lead to
problems with other IRQs that are handled in the PIC. Since the original
8259A datasheet permits such functionality and we are not losing any
functionality, this change is acceptable even though we don't experience
problems with the EOI currently.
-rw-r--r-- | Kernel/Interrupts/PIC.cpp | 39 |
1 files changed, 24 insertions, 15 deletions
diff --git a/Kernel/Interrupts/PIC.cpp b/Kernel/Interrupts/PIC.cpp index e5f1ca20fe..a471f4a699 100644 --- a/Kernel/Interrupts/PIC.cpp +++ b/Kernel/Interrupts/PIC.cpp @@ -66,9 +66,9 @@ void PIC::disable(const GenericInterruptHandler& handler) ASSERT(handler.interrupt_number() >= gsi_base() && handler.interrupt_number() < interrupt_vectors_count()); u8 irq = handler.interrupt_number(); u8 imr; - if (irq >= 8) { + if (irq & 8) { imr = IO::in8(PIC1_CMD); - imr |= 1 << (irq - 8); + imr |= 1 << (irq & 7); IO::out8(PIC1_CMD, imr); } else { imr = IO::in8(PIC0_CMD); @@ -88,16 +88,20 @@ PIC::PIC() void PIC::spurious_eoi(const GenericInterruptHandler& handler) const { ASSERT(handler.type() == HandlerType::SpuriousInterruptHandler); - if (handler.interrupt_number() == 15) - eoi_interrupt(7); + if (handler.interrupt_number() == 7) + return; + if (handler.interrupt_number() == 15) { + IO::in8(PIC1_CMD); /* dummy read */ + IO::out8(PIC0_CTL, 0x60 | (2)); + } } bool PIC::is_vector_enabled(u8 irq) const { u8 imr; - if (irq >= 8) { + if (irq & 8) { imr = IO::in8(PIC1_CMD); - imr &= 1 << (irq - 8); + imr &= 1 << (irq & 7); } else { imr = IO::in8(PIC0_CMD); imr &= 1 << irq; @@ -118,9 +122,9 @@ void PIC::enable_vector(u8 irq) InterruptDisabler disabler; ASSERT(!is_hard_disabled()); u8 imr; - if (irq >= 8) { + if (irq & 8) { imr = IO::in8(PIC1_CMD); - imr &= ~(1 << (irq - 8)); + imr &= ~(1 << (irq & 7)); IO::out8(PIC1_CMD, imr); } else { imr = IO::in8(PIC0_CMD); @@ -140,9 +144,14 @@ void PIC::eoi(const GenericInterruptHandler& handler) const void PIC::eoi_interrupt(u8 irq) const { - if (irq >= 8) - IO::out8(PIC1_CTL, 0x20); - IO::out8(PIC0_CTL, 0x20); + if (irq & 8) { + IO::in8(PIC1_CMD); /* dummy read */ + IO::out8(PIC1_CTL, 0x60 | (irq & 7)); + IO::out8(PIC0_CTL, 0x60 | (2)); + return; + } + IO::in8(PIC0_CMD); /* dummy read */ + IO::out8(PIC0_CTL, 0x60 | irq); } void PIC::complete_eoi() const @@ -175,8 +184,8 @@ void PIC::remap(u8 offset) IO::out8(PIC1_CMD, SLAVE_INDEX); /* ICW4 (set x86 mode) */ - IO::out8(PIC0_CMD, 0x01); - IO::out8(PIC1_CMD, 0x01); + IO::out8(PIC0_CMD, ICW4_8086); + IO::out8(PIC1_CMD, ICW4_8086); // Mask -- start out with all IRQs disabled. IO::out8(PIC0_CMD, 0xff); @@ -201,8 +210,8 @@ void PIC::initialize() IO::out8(PIC1_CMD, SLAVE_INDEX); /* ICW4 (set x86 mode) */ - IO::out8(PIC0_CMD, 0x01); - IO::out8(PIC1_CMD, 0x01); + IO::out8(PIC0_CMD, ICW4_8086); + IO::out8(PIC1_CMD, ICW4_8086); // Mask -- start out with all IRQs disabled. IO::out8(PIC0_CMD, 0xff); |