| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 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 |  | 
 | 73 | 1: | 
 | 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 |  | 
 | 84 | 1: | 
 | 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 |  | 
 | 94 | 1: | 
 | 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 |  | 
 | 104 | 1: | 
 | 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 | 
 | 115 | 1: | 
 | 116 | 	j	ret_from_irq | 
 | 117 | 	 nop				# delay slot | 
 | 118 | 	END(indyIRQ) |