Sfoglia il codice sorgente

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.
Liav A 5 anni fa
parent
commit
cb676f1211
1 ha cambiato i file con 24 aggiunte e 15 eliminazioni
  1. 24 15
      Kernel/Interrupts/PIC.cpp

+ 24 - 15
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);