From e4ac58afdfac792c0583af30dbd9eae53e24c78b Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Mon, 3 Apr 2006 17:56:36 +0100 Subject: [MIPS] Rewrite all the assembler interrupt handlers to C. Saves like 1,600 lines of code, is way easier to debug, compilers frequently do a better job than the cut and paste type of handlers many boards had. And finally having all the stuff done in a single place also means alot of bug potencial for the MT ASE is gone. The only surviving handler in assembler is the DECstation one; I hope Maciej will rewrite it. Signed-off-by: Ralf Baechle --- arch/mips/sgi-ip22/ip22-int.c | 59 ++++++++++++++++++++++++++++++++++++++----- 1 file changed, 53 insertions(+), 6 deletions(-) (limited to 'arch/mips/sgi-ip22/ip22-int.c') diff --git a/arch/mips/sgi-ip22/ip22-int.c b/arch/mips/sgi-ip22/ip22-int.c index d16fb43b1a93..fc6a7e2b189c 100644 --- a/arch/mips/sgi-ip22/ip22-int.c +++ b/arch/mips/sgi-ip22/ip22-int.c @@ -37,7 +37,6 @@ static char lc1msk_to_irqnr[256]; static char lc2msk_to_irqnr[256]; static char lc3msk_to_irqnr[256]; -extern asmlinkage void indyIRQ(void); extern int ip22_eisa_init(void); static void enable_local0_irq(unsigned int irq) @@ -224,7 +223,7 @@ static struct hw_interrupt_type ip22_local3_irq_type = { .end = end_local3_irq, }; -void indy_local0_irqdispatch(struct pt_regs *regs) +static void indy_local0_irqdispatch(struct pt_regs *regs) { u8 mask = sgint->istat0 & sgint->imask0; u8 mask2; @@ -242,7 +241,7 @@ void indy_local0_irqdispatch(struct pt_regs *regs) return; } -void indy_local1_irqdispatch(struct pt_regs *regs) +static void indy_local1_irqdispatch(struct pt_regs *regs) { u8 mask = sgint->istat1 & sgint->imask1; u8 mask2; @@ -262,7 +261,7 @@ void indy_local1_irqdispatch(struct pt_regs *regs) extern void ip22_be_interrupt(int irq, struct pt_regs *regs); -void indy_buserror_irq(struct pt_regs *regs) +static void indy_buserror_irq(struct pt_regs *regs) { int irq = SGI_BUSERR_IRQ; @@ -307,6 +306,56 @@ static struct irqaction map1_cascade = { #define SGI_INTERRUPTS SGINT_LOCAL3 #endif +extern void indy_r4k_timer_interrupt(struct pt_regs *regs); +extern void indy_8254timer_irq(struct pt_regs *regs); + +/* + * IRQs on the INDY look basically (barring software IRQs which we don't use + * at all) like: + * + * MIPS IRQ Source + * -------- ------ + * 0 Software (ignored) + * 1 Software (ignored) + * 2 Local IRQ level zero + * 3 Local IRQ level one + * 4 8254 Timer zero + * 5 8254 Timer one + * 6 Bus Error + * 7 R4k timer (what we use) + * + * We handle the IRQ according to _our_ priority which is: + * + * Highest ---- R4k Timer + * Local IRQ zero + * Local IRQ one + * Bus Error + * 8254 Timer zero + * Lowest ---- 8254 Timer one + * + * then we just return, if multiple IRQs are pending then we will just take + * another exception, big deal. + */ + +asmlinkage void plat_irq_dispatch(struct pt_regs *regs) +{ + unsigned int pending = read_c0_cause(); + + /* + * First we check for r4k counter/timer IRQ. + */ + if (pending & CAUSEF_IP7) + indy_r4k_timer_interrupt(regs); + else if (pending & CAUSEF_IP2) + indy_local0_irqdispatch(regs); + else if (pending & CAUSEF_IP3) + indy_local1_irqdispatch(regs); + else if (pending & CAUSEF_IP6) + indy_buserror_irq(regs); + else if (pending & (CAUSEF_IP4 | CAUSEF_IP5)) + indy_8254timer_irq(regs); +} + extern void mips_cpu_irq_init(unsigned int irq_base); void __init arch_init_irq(void) @@ -369,8 +418,6 @@ void __init arch_init_irq(void) sgint->cmeimask0 = 0; sgint->cmeimask1 = 0; - set_except_vector(0, indyIRQ); - /* init CPU irqs */ mips_cpu_irq_init(SGINT_CPU); -- cgit v1.2.3