[LinuxBIOS] about cs5536 interrupt ack

Songmao Tian tiansm at lemote.com
Wed Jul 11 17:38:40 CEST 2007


Songmao Tian wrote:
> Before I post the mail, I think you will reply, and haha you did:), 
> Thanks that.
>
> Maciej W. Rozycki wrote:
>> On Wed, 11 Jul 2007, Songmao Tian wrote:
>>
>>  
>>> "Control Logic
>>> The INT output goes directly to the CPU interrupt input.
>>> When an INT signal is activated, the CPU responds with an
>>> Interrupt Acknowledge access that is translated to two
>>> pulses on the INTA input of the PIC. At the first INTA pulse,
>>> the highest priority IRR bit is loaded into the corresponding
>>> ISR bit, and that IRR bit is reset. The second INTA pulse
>>> instructs the PIC to present the 8-bit vector of the interrupt
>>> handler onto the data bus."
>>>
>>> Is it the responsibility of north bridge to reponse to intr with a PCI
>>> Interrupt Ack cycle?
>>>     
>>
>>  With an i386 system such a pair of INTA cycles would be generated by 
>> the CPU itself and translated by the north bridge to a PCI Interrupt 
>> Acknowledge cycle (see the PCI spec for a more elaborate description).
>>
>>  If the CPU does not generate INTA cycles, it is a common practice to 
>> let it ask the north bridge for a PCI Interrupt Acknowledge in some 
>> other way, typically by issuing a read cycle that returns the vector 
>> reported by the interrupt controller.
>>
>>  
>>> it's a problem that my northbridge didn't implement that! 
>>> Fortunately we use a
>>> fpga as a northbridge.
>>>
>>> it seem it's no way to fix this by software, for OCW3 didn't 
>>> implemnt Poll
>>> command:(
>>>     
>>
>>  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.
>
>> manufacturer -- they may be able to fix the problem in a later revision.
>>
>>  BTW, I have just found a bug (OK, a misfeature, perhaps) in 
>> include/asm-mips/i8259.h. ;-)  I'll cook a patch.
>>
>>  
>>> so I guess the the process is:
>>> 1) 8259 receive a int, a bit irr got set.
>>> 2) 8259 assert intr.
>>> 3) northbrige generate a int ack cycle.
>>> 4) cs5536 translate the ack into two INTA pulse, and the reponse 
>>> northbridge
>>> with a interrupt vector.
>>> 5) then my program can get the vector from northbridge?
>>>
>>> Is that right?
>>>     
>>
>>  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.
>>  
>>> Without int ack, generic linux-mips 8259 code can't work.
>>>     
>>
>>  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.
>
>>   Maciej
>>
>>
>>   
> diff --git a/include/asm-mips/i8259.h b/include/asm-mips/i8259.h
> index e88a016..38628af 100644
> --- a/include/asm-mips/i8259.h
> +++ b/include/asm-mips/i8259.h
> @@ -42,6 +42,37 @@ 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)
> +{
> +    outb(0x0A, port);
> +    return _byte_ffs(inb(port));
> +}
> +#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 +85,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,7 +107,7 @@ static inline int i8259_irq(void)
>         if(~inb(PIC_MASTER_ISR) & 0x80)
>             irq = -1;
>     }
> -
> +#endif
>     spin_unlock(&i8259A_lock);
>
>     return likely(irq >= 0) ? irq + I8259A_IRQ_BASE : irq;
>
>
>
after applying this patch, system hung when probing ide, seems reading 
harddisk continuously, since the led is on all the time.




More information about the coreboot mailing list