patch-2.2.12 linux/arch/ppc/kernel/i8259.c

Next file: linux/arch/ppc/kernel/irq.c
Previous file: linux/arch/ppc/kernel/head.S
Back to the patch index
Back to the overall index

diff -u --recursive --new-file v2.2.11/linux/arch/ppc/kernel/i8259.c linux/arch/ppc/kernel/i8259.c
@@ -13,33 +13,32 @@
 int i8259_irq(int cpu)
 {
 	int irq;
+	unsigned char irr;
 	
         /*
          * Perform an interrupt acknowledge cycle on controller 1
-         */                                                             
-        outb(0x0C, 0x20);
-        irq = inb(0x20) & 7;                                   
-        if (irq == 2)                                                     
-        {                                                                   
-                /*                                     
+         */
+	irr = inb(0x20) & ~cached_21;
+	if (!irr) return -1;
+	irq = 0;
+	while ((irq < 7) && !(irr&0x01))
+	{
+		irq++;
+		irr >>= 1;
+	}
+        if (irq == 2)
+	{
+                /*
                  * Interrupt is cascaded so perform interrupt
                  * acknowledge on controller 2
                  */
-                outb(0x0C, 0xA0);                      
-                irq = (inb(0xA0) & 7) + 8;
-        }
-        else if (irq==7)                                
-        {
-                /*                               
-                 * This may be a spurious interrupt
-                 *                         
-                 * Read the interrupt status register. If the most
-                 * significant bit is not set then there is no valid
-		 * interrupt
-		 */
-		outb(0x0b, 0x20);
-		if(~inb(0x20)&0x80)
-			return -1;
+		irr = inb(0xA0) & ~cached_A1;
+		irq = 8;
+		while ((irq < 15) && !(irr&0x01))
+		{
+			irq++;
+			irr >>= 1;
+		}
 	}
 	return irq;
 }
@@ -53,13 +52,13 @@
                 cached_A1 |= 1 << (irq_nr-8);                                   
                 inb(0xA1);      /* DUMMY */                                     
                 outb(cached_A1,0xA1);                                           
-                outb(0x20,0xA0);        /* Non-specific EOI */             
-                outb(0x20,0x20);        /* Non-specific EOI to cascade */
+                outb(0x62,0x20);             /* Specific EOI to cascade */
+                outb(0x60|(irq_nr-8),0xA0);  /* Specific EOI */
         } else {                                                            
                 cached_21 |= 1 << irq_nr;                                   
                 inb(0x21);      /* DUMMY */                                 
                 outb(cached_21,0x21);
-                outb(0x20,0x20);        /* Non-specific EOI */                 
+                outb(0x60|irq_nr,0x20);      /* Specific EOI */
         }                                                                
 }
 
@@ -82,7 +81,6 @@
 
 static void i8259_unmask_irq(unsigned int irq_nr)
 {
-
         if ( irq_nr >= i8259_pic.irq_offset )
                 irq_nr -= i8259_pic.irq_offset;
         if ( irq_nr < 8 )

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)