8259 problem seems to be done with the attached patch, IDE hung seems to be the dma setting problem.
Thanks all for your advise, comments. I have learned a lot. now I continue to trace down the IDE problem.
Mao
Maciej W. Rozycki wrote:
On Wed, 11 Jul 2007, Songmao Tian wrote:
Huh? Have you managed to find an 8259A clone *that* broken? So what does it return if you write 0xc to the address 0x20 in the I/O port space and then read back from that location? You should complain to the
It's the value of IRR, so guess IRR. AMD has well documented cs5536, I appreciate that.
Indeed. I am surprised they have decided to drop the poll command -- it surely does not require much logic as it mostly reuses what's used to produce the vector anyway and it is commonly used when 8259A implementations are interfaced to non-i386 processors. PPC is another example.
More or less -- 3-5 should probably be the outcome of a single read transaction from the north bridge. I.e. you issue a read to a "magic" location, 3-5 happen, and the data value returned is the vector presented by the interrupt controller on the PCI bus.
yeah, we can implement a register in north bridge.
Strictly speaking it would not be a register, but a "PCI INTA address space" much like PCI memory or I/O port address spaces. Though as the former ignores addresses driven on the bus, the space occupied does not have to be extensive -- I would assume whatever slot size is available with the address decoder you have implemented would do.
You can still dispatch interrupts manually by examining the IRR register, but having a way to ask the 8259A's prioritiser would be nice. Although given such a lethal erratum you report I would not count on the prioritiser to provide any useful flexibility...
yeah, that's a straight thought, tried but failed:(, patch followed.
You may have to modify other functions from arch/mips/kernel/i8259.c; yes, this makes the whole experience not as pretty as one would hope...
Maciej
diff --git a/arch/mips/kernel/i8259.c b/arch/mips/kernel/i8259.c index 9c79703..fd7f4ba 100644 --- a/arch/mips/kernel/i8259.c +++ b/arch/mips/kernel/i8259.c @@ -47,11 +47,7 @@ static struct irq_chip i8259A_chip = { /* * This contains the irq mask for both 8259A irq controllers, */ -static unsigned int cached_irq_mask = 0xffff; - -#define cached_master_mask (cached_irq_mask) -#define cached_slave_mask (cached_irq_mask >> 8) - +unsigned int cached_irq_mask = 0xffff; void disable_8259A_irq(unsigned int irq) { unsigned int mask; diff --git a/include/asm-mips/i8259.h b/include/asm-mips/i8259.h index e88a016..e7dcf7b 100644 --- a/include/asm-mips/i8259.h +++ b/include/asm-mips/i8259.h @@ -37,11 +37,55 @@
extern spinlock_t i8259A_lock;
+extern unsigned int cached_irq_mask; +#define cached_master_mask (cached_irq_mask) +#define cached_slave_mask (cached_irq_mask >> 8) + extern void init_8259A(int auto_eoi); extern void enable_8259A_irq(unsigned int irq); extern void disable_8259A_irq(unsigned int irq);
extern void init_i8259_irqs(void); +#define CONFIG_NO_INTERRUPT_ACK +#ifdef CONFIG_NO_INTERRUPT_ACK +static inline int _byte_ffs(u8 word) +{ + int num = 0; + if ((word & 0xf) == 0) { + num += 4; + word >>= 4; + } + if ((word & 0x3) == 0) { + num += 2; + word >>= 2; + } + if ((word & 0x1) == 0) + num += 1; + return num; +} + +static inline int read_irq(int port) +{ + int irq; + outb(0x0A, port); + if (port == PIC_MASTER_CMD) { + irq = inb(port) & ~cached_master_mask; + } else { + irq = inb(port) & ~cached_slave_mask; + } + if (irq == 0) + return -1; + else + return _byte_ffs(irq); +} +#else +static inline int read_irq(int port) +{ + /* Perform an interrupt acknowledge cycle on controller 1. */ + outb(0x0C, port); /* prepare for poll */ + return inb(port) & 7; +} +#endif
/* * Do the traditional i8259 interrupt polling thing. This is for the few @@ -54,18 +98,16 @@ static inline int i8259_irq(void)
spin_lock(&i8259A_lock);
- /* Perform an interrupt acknowledge cycle on controller 1. */ - outb(0x0C, PIC_MASTER_CMD); /* prepare for poll */ - irq = inb(PIC_MASTER_CMD) & 7; + irq = read_irq(PIC_MASTER_CMD); if (irq == PIC_CASCADE_IR) { /* * Interrupt is cascaded so perform interrupt * acknowledge on controller 2. */ - outb(0x0C, PIC_SLAVE_CMD); /* prepare for poll */ - irq = (inb(PIC_SLAVE_CMD) & 7) + 8; - } + irq = read_irq(PIC_SLAVE_CMD) + 8; + }
+#ifndef CONFIG_NO_INTERRUPT_ACK if (unlikely(irq == 7)) { /* * This may be a spurious interrupt. @@ -78,6 +120,11 @@ static inline int i8259_irq(void) if(~inb(PIC_MASTER_ISR) & 0x80) irq = -1; } +#else + if (cached_irq_mask & (1 << irq)) { + irq = -1; + } +#endif
spin_unlock(&i8259A_lock);