summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSamuel Thibault <samuel.thibault@ens-lyon.org>2019-11-11 17:37:12 +0100
committerSamuel Thibault <samuel.thibault@ens-lyon.org>2019-11-11 17:37:12 +0100
commit1fc9b4b56e8425f5f68c019b511189f25c82c122 (patch)
treeb5d29d41f40f1da5ef52f7121c4ffb98fdeadf83
parent8be43614e014178bdb6bd1650bf082cd5203cb0e (diff)
PIC: Acknowledge interrupts more carefully
Specs seems to be saying that we should mask an irq out while acknowledging it with EOI. Also, better acknowledge only the concerned irq. * i386/i386at/interrupt.S (interrupt): Mask irq before notifying EOI. Using specific EOI instead of unspecific EOI.
-rw-r--r--i386/i386at/interrupt.S44
1 files changed, 37 insertions, 7 deletions
diff --git a/i386/i386at/interrupt.S b/i386/i386at/interrupt.S
index 076e34bc..23a2e582 100644
--- a/i386/i386at/interrupt.S
+++ b/i386/i386at/interrupt.S
@@ -38,14 +38,44 @@ ENTRY(interrupt)
addl $4,%esp /* pop unit number */
call splx_cli /* restore previous ipl */
addl $4,%esp /* pop previous ipl */
+
cli /* XXX no more nested interrupts */
- popl %eax /* restore irq number */
- movl %eax,%ecx /* copy irq number */
- movb $(NON_SPEC_EOI),%al /* non-specific EOI */
- outb %al,$(PIC_MASTER_ICW) /* ack interrupt to master */
+ popl %ecx /* restore irq number */
+
+ movl $1,%eax
+ shll %cl,%eax /* get corresponding IRQ mask */
+ orl EXT(curr_pic_mask),%eax /* add current mask */
+
cmpl $8,%ecx /* do we need to ack slave? */
- jl 1f /* no, skip it */
- outb %al,$(PIC_SLAVE_ICW)
+ jl 1f /* no, only master */
+
+ /* EOI on slave */
+ movb %ah,%al
+ outb %al,$(PIC_SLAVE_OCW) /* mask slave out */
+
+ movb $(SPECIFIC_EOI),%al /* specific EOI for this irq */
+ andb $7,%cl /* irq number for the slave */
+ orb %cl,%al /* combine them */
+ outb %al,$(PIC_SLAVE_ICW) /* ack interrupt to slave */
+
+ movb $(SPECIFIC_EOI + I_AM_SLAVE_2),%al /* specific master EOI for cascaded slave */
+ outb %al,$(PIC_MASTER_ICW) /* ack interrupt to master */
+
+ movl EXT(curr_pic_mask),%eax /* restore original mask */
+ movb %ah,%al
+ outb %al,$(PIC_SLAVE_OCW) /* unmask slave */
+ jmp 2f
+
1:
- ret /* return */
+ /* EOI on master */
+ outb %al,$(PIC_MASTER_OCW) /* mask master out */
+
+ movb $(SPECIFIC_EOI),%al /* specific EOI for this irq */
+ orb %cl,%al /* combine with irq number */
+ outb %al,$(PIC_MASTER_ICW) /* ack interrupt to master */
+
+ movl EXT(curr_pic_mask),%eax /* restore original mask */
+ outb %al,$(PIC_MASTER_OCW) /* unmask master */
+2:
+ ret
END(interrupt)