diff options
author | Samuel Thibault <samuel.thibault@ens-lyon.org> | 2019-11-11 17:37:12 +0100 |
---|---|---|
committer | Samuel Thibault <samuel.thibault@ens-lyon.org> | 2019-11-11 17:37:12 +0100 |
commit | 1fc9b4b56e8425f5f68c019b511189f25c82c122 (patch) | |
tree | b5d29d41f40f1da5ef52f7121c4ffb98fdeadf83 /i386/i386at | |
parent | 8be43614e014178bdb6bd1650bf082cd5203cb0e (diff) | |
download | gnumach-1fc9b4b56e8425f5f68c019b511189f25c82c122.tar.gz gnumach-1fc9b4b56e8425f5f68c019b511189f25c82c122.tar.bz2 gnumach-1fc9b4b56e8425f5f68c019b511189f25c82c122.zip |
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.
Diffstat (limited to 'i386/i386at')
-rw-r--r-- | i386/i386at/interrupt.S | 44 |
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) |