1/* 2 * ip22-irq.S: Interrupt exception dispatch code for FullHouse and 3 * Guiness. 4 * 5 * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com) 6 */ 7 8#include <asm/asm.h> 9#include <asm/mipsregs.h> 10#include <asm/regdef.h> 11#include <asm/stackframe.h> 12 13/* A lot of complication here is taken away because: 14 * 15 * 1) We handle one interrupt and return, sitting in a loop and moving across 16 * all the pending IRQ bits in the cause register is _NOT_ the answer, the 17 * common case is one pending IRQ so optimize in that direction. 18 * 19 * 2) We need not check against bits in the status register IRQ mask, that 20 * would make this routine slow as hell. 21 * 22 * 3) Linux only thinks in terms of all IRQs on or all IRQs off, nothing in 23 * between like BSD spl() brain-damage. 24 * 25 * Furthermore, the IRQs on the INDY look basically (barring software IRQs 26 * which we don't use at all) like: 27 * 28 * MIPS IRQ Source 29 * -------- ------ 30 * 0 Software (ignored) 31 * 1 Software (ignored) 32 * 2 Local IRQ level zero 33 * 3 Local IRQ level one 34 * 4 8254 Timer zero 35 * 5 8254 Timer one 36 * 6 Bus Error 37 * 7 R4k timer (what we use) 38 * 39 * We handle the IRQ according to _our_ priority which is: 40 * 41 * Highest ---- R4k Timer 42 * Local IRQ zero 43 * Local IRQ one 44 * Bus Error 45 * 8254 Timer zero 46 * Lowest ---- 8254 Timer one 47 * 48 * then we just return, if multiple IRQs are pending then we will just take 49 * another exception, big deal. 50 */ 51 52 .text 53 .set noreorder 54 .set noat 55 .align 5 56 NESTED(indyIRQ, PT_SIZE, sp) 57 SAVE_ALL 58 CLI 59 .set at 60 mfc0 s0, CP0_CAUSE # get irq mask 61 62 /* First we check for r4k counter/timer IRQ. */ 63 andi a0, s0, CAUSEF_IP7 64 beq a0, zero, 1f 65 andi a0, s0, CAUSEF_IP2 # delay slot, check local level zero 66 67 /* Wheee, a timer interrupt. */ 68 jal indy_r4k_timer_interrupt 69 move a0, sp # delay slot 70 j ret_from_irq 71 nop # delay slot 72 731: 74 beq a0, zero, 1f 75 andi a0, s0, CAUSEF_IP3 # delay slot, check local level one 76 77 /* Wheee, local level zero interrupt. */ 78 jal indy_local0_irqdispatch 79 move a0, sp # delay slot 80 81 j ret_from_irq 82 nop # delay slot 83 841: 85 beq a0, zero, 1f 86 andi a0, s0, CAUSEF_IP6 # delay slot, check bus error 87 88 /* Wheee, local level one interrupt. */ 89 jal indy_local1_irqdispatch 90 move a0, sp # delay slot 91 j ret_from_irq 92 nop # delay slot 93 941: 95 beq a0, zero, 1f 96 andi a0, s0, (CAUSEF_IP4 | CAUSEF_IP5) # delay slot 97 98 /* Wheee, an asynchronous bus error... */ 99 jal indy_buserror_irq 100 move a0, sp # delay slot 101 j ret_from_irq 102 nop # delay slot 103 1041: 105 /* Here by mistake? It is possible, that by the time we take 106 * the exception the IRQ pin goes low, so just leave if this 107 * is the case. 108 */ 109 beq a0, zero, 1f 110 nop # delay slot 111 112 /* Must be one of the 8254 timers... */ 113 jal indy_8254timer_irq 114 move a0, sp # delay slot 1151: 116 j ret_from_irq 117 nop # delay slot 118 END(indyIRQ) 119