summaryrefslogtreecommitdiff
path: root/Kernel
diff options
context:
space:
mode:
authorLiav A <liavalb@gmail.com>2020-03-20 16:52:14 +0200
committerAndreas Kling <kling@serenityos.org>2020-03-24 16:15:33 +0100
commitcb676f12111f52bbb3fb9b784a8b88a998729353 (patch)
tree741b2c59d6c0f7a0ea4bfa2bb5d1611dfbffb514 /Kernel
parent06e7fc9deea669ef25eb27352b7681ef262bf906 (diff)
downloadserenity-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.
Diffstat (limited to 'Kernel')
-rw-r--r--Kernel/Interrupts/PIC.cpp39
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);