| /* | 
 |  * ip22-irq.S: Interrupt exception dispatch code for FullHouse and | 
 |  *             Guiness. | 
 |  * | 
 |  * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com) | 
 |  */ | 
 |  | 
 | #include <asm/asm.h> | 
 | #include <asm/mipsregs.h> | 
 | #include <asm/regdef.h> | 
 | #include <asm/stackframe.h> | 
 |  | 
 | /* A lot of complication here is taken away because: | 
 |  * | 
 |  * 1) We handle one interrupt and return, sitting in a loop and moving across | 
 |  *    all the pending IRQ bits in the cause register is _NOT_ the answer, the | 
 |  *    common case is one pending IRQ so optimize in that direction. | 
 |  * | 
 |  * 2) We need not check against bits in the status register IRQ mask, that | 
 |  *    would make this routine slow as hell. | 
 |  * | 
 |  * 3) Linux only thinks in terms of all IRQs on or all IRQs off, nothing in | 
 |  *    between like BSD spl() brain-damage. | 
 |  * | 
 |  * Furthermore, the 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. | 
 |  */ | 
 |  | 
 | 	.text | 
 | 	.set	noreorder | 
 | 	.set	noat | 
 | 	.align	5 | 
 | 	NESTED(indyIRQ, PT_SIZE, sp) | 
 | 	SAVE_ALL | 
 | 	CLI | 
 | 	.set	at | 
 | 	mfc0	s0, CP0_CAUSE		# get irq mask | 
 |  | 
 | 	/* First we check for r4k counter/timer IRQ. */ | 
 | 	andi	a0, s0, CAUSEF_IP7 | 
 | 	beq	a0, zero, 1f | 
 | 	 andi	a0, s0, CAUSEF_IP2	# delay slot, check local level zero | 
 |  | 
 | 	/* Wheee, a timer interrupt. */ | 
 | 	jal	indy_r4k_timer_interrupt | 
 | 	 move	a0, sp			# delay slot | 
 | 	j	ret_from_irq | 
 | 	 nop				# delay slot | 
 |  | 
 | 1: | 
 | 	beq	a0, zero, 1f | 
 | 	 andi	a0, s0, CAUSEF_IP3	# delay slot, check local level one | 
 |  | 
 | 	/* Wheee, local level zero interrupt. */ | 
 | 	jal	indy_local0_irqdispatch | 
 | 	 move	a0, sp			# delay slot | 
 |  | 
 | 	j	ret_from_irq | 
 | 	 nop				# delay slot | 
 |  | 
 | 1: | 
 | 	beq	a0, zero, 1f | 
 | 	 andi	a0, s0, CAUSEF_IP6	# delay slot, check bus error | 
 |  | 
 | 	/* Wheee, local level one interrupt. */ | 
 | 	jal	indy_local1_irqdispatch | 
 | 	 move	a0, sp			# delay slot | 
 | 	j	ret_from_irq | 
 | 	 nop				# delay slot | 
 |  | 
 | 1: | 
 | 	beq	a0, zero, 1f | 
 | 	 andi	a0, s0, (CAUSEF_IP4 | CAUSEF_IP5)	# delay slot | 
 |  | 
 | 	/* Wheee, an asynchronous bus error... */ | 
 | 	jal	indy_buserror_irq | 
 | 	 move	a0, sp			# delay slot | 
 | 	j	ret_from_irq | 
 | 	 nop				# delay slot | 
 |  | 
 | 1: | 
 | 	/* Here by mistake? It is possible, that by the time we take | 
 | 	 * the exception the IRQ pin goes low, so just leave if this | 
 | 	 * is the case. | 
 | 	 */ | 
 | 	beq	a0, zero, 1f | 
 | 	 nop			  	# delay slot | 
 |  | 
 | 	/* Must be one of the 8254 timers... */ | 
 | 	jal	indy_8254timer_irq | 
 | 	 move	a0, sp			# delay slot | 
 | 1: | 
 | 	j	ret_from_irq | 
 | 	 nop				# delay slot | 
 | 	END(indyIRQ) |