1 /*
2 * arch/mips/kernel/magnum4000.S
3 *
4 * Copyright (C) 1995 Waldorf Electronics
5 * written by Ralf Baechle and Andreas Busse
6 */
7 #include <asm/asm.h>
8 #include <asm/mipsregs.h>
9 #include <asm/jazz.h>
10 #include <asm/stackframe.h>
11
12 /*
13 * mips_magnum_4000_handle_int: Interrupt handler for Mips Magnum 4000
14 */
15 .set noreorder
16
17 NESTED(mips_magnum_4000_handle_int, FR_SIZE, ra)
18 .set noat
19 SAVE_ALL
20 CLI
21 .set at
22
23 /*
24 * Get pending interrupts
25 */
26 mfc0 t0,CP0_CAUSE # get pending interrupts
27 mfc0 t1,CP0_STATUS # get enabled interrupts
28 and t0,t1 # isolate allowed ones
29 andi t0,0xff00 # isolate pending bits
30 beqz t0,spurious_interrupt
31 sll t0,16 # delay slot
32
33 /*
34 * Find irq with highest priority
35 * FIXME: This is slow
36 */
37 la t1,ll_vectors
38 1: bltz t0,2f # found pending irq
39 sll t0,1
40 b 1b
41 subu t1,PTRSIZE # delay slot
42
43 /*
44 * Do the low-level stuff
45 */
46 2: lw t0,(t1)
47 jr t0
48 nop # delay slot
49 END(mips_magnum_4000_handle_int)
50
51 /*
52 * Used for keyboard driver's fake_keyboard_interrupt()
53 */
54 ll_sw0: li s1,~IE_SW0
55 mfc0 t0,CP0_CAUSE
56 and t0,s1
57 mtc0 t0,CP0_CAUSE
58 PRINT("sw0 received...\n")
59 li t1,1
60 b call_real
61 li t3,PTRSIZE # delay slot, re-map to irq level 1
62
63 ll_sw1: li s1,~IE_SW1
64 PANIC("Unimplemented sw1 handler")
65
66 ll_local_dma: li s1,~IE_IRQ0
67 PANIC("Unimplemented local_dma handler")
68
69 ll_local_dev: lbu t0,JAZZ_IO_IRQ_SOURCE
70 #if __mips == 3
71 dsll t0,1
72 ld t0,local_vector(t0)
73 #else /* 32 bit */
74 lw t0,local_vector(t0)
75 #endif
76 jr t0
77 nop
78
79
80 loc_no_irq: PANIC("Unimplemented loc_no_irq handler")
81 loc_sound: PANIC("Unimplemented loc_sound handler")
82 loc_video: PANIC("Unimplemented loc_video handler")
83 loc_scsi: PANIC("Unimplemented loc_scsi handler")
84
85 /*
86 * Keyboard interrupt handler
87 */
88 loc_keyboard: li s1,~JAZZ_IE_KEYBOARD
89 li t1,JAZZ_KEYBOARD_IRQ
90 b loc_call
91 li t3,PTRSIZE*JAZZ_KEYBOARD_IRQ # delay slot
92
93 /*
94 * Ethernet interrupt handler, remapped to level 2
95 */
96 loc_ethernet: /* PRINT ("ethernet IRQ\n"); */
97 li s1,~JAZZ_IE_ETHERNET
98 li t1,JAZZ_ETHERNET_IRQ
99 b loc_call
100 li t3,PTRSIZE*JAZZ_ETHERNET_IRQ # delay slot
101
102
103 loc_mouse: PANIC("Unimplemented loc_mouse handler")
104
105 /*
106 * Serial port 1 IRQ, remapped to level 3
107 */
108 loc_serial1: li s1,~JAZZ_IE_SERIAL1
109 li t1,JAZZ_SERIAL1_IRQ
110 b loc_call
111 li t3,PTRSIZE*JAZZ_SERIAL1_IRQ # delay slot
112
113 /*
114 * Serial port 2 IRQ, remapped to level 4
115 */
116 loc_serial2: li s1,~JAZZ_IE_SERIAL2
117 li t1,JAZZ_SERIAL2_IRQ
118 b loc_call
119 li t3,PTRSIZE*JAZZ_SERIAL2_IRQ # delay slot
120
121 /*
122 * Parallel port IRQ, remapped to level 5
123 */
124 loc_parallel: li s1,~JAZZ_IE_PARALLEL
125 li t1,JAZZ_PARALLEL_IRQ
126 b loc_call
127 li t3,PTRSIZE*JAZZ_PARALLEL_IRQ # delay slot
128
129 /*
130 * Floppy IRQ, remapped to level 6
131 */
132 loc_floppy: li s1,~JAZZ_IE_FLOPPY
133 li t1,JAZZ_FLOPPY_IRQ
134 b loc_call
135 li t3,PTRSIZE*JAZZ_FLOPPY_IRQ # delay slot
136
137 /*
138 * Now call the real handler
139 */
140 loc_call: lui s3,%hi(intr_count)
141 lw t2,%lo(intr_count)(s3)
142 la t0,IRQ_vectors # delay slot
143 addiu t2,1
144 sw t2,%lo(intr_count)(s3)
145
146 /*
147 * Temporarily disable interrupt source
148 */
149 lhu t2,JAZZ_IO_IRQ_ENABLE
150 addu t0,t3 # make ptr to IRQ handler
151 lw t0,(t0)
152 and t2,s1 # delay slot
153 sh t2,JAZZ_IO_IRQ_ENABLE
154 jalr t0 # call IRQ handler
155 nor s1,zero,s1 # delay slot
156
157 /*
158 * Reenable interrupt
159 */
160 lhu t2,JAZZ_IO_IRQ_ENABLE
161 lw t1,%lo(intr_count)(s3) # delay slot
162 or t2,s1
163 sh t2,JAZZ_IO_IRQ_ENABLE
164
165 subu t1,1
166 jr v0
167 sw t1,%lo(intr_count)(s3)
168
169 ll_eisa_irq: li s1,~IE_IRQ2
170 PANIC("Unimplemented eisa_irq handler")
171
172 ll_eisa_nmi: li s1,~IE_IRQ3
173 PANIC("Unimplemented eisa_nmi handler")
174
175 /*
176 * Timer IRQ
177 * We remap the timer irq to be more similar to a IBM compatible
178 */
179 ll_timer: lw t0,JAZZ_TIMER_REGISTER # timer irq cleared on read
180 li s1,~IE_IRQ4
181 li t1,0
182 b call_real
183 li t3,0 # delay slot, re-map to irq level 0
184
185 /*
186 * CPU count/compare IRQ (unused)
187 */
188 ll_count: j return
189 mtc0 zero,CP0_COMPARE
190
191 /*
192 * Now call the real handler
193 */
194 call_real: lui s3,%hi(intr_count)
195 lw t2,%lo(intr_count)(s3)
196 la t0,IRQ_vectors # delay slot
197 addiu t2,1
198 sw t2,%lo(intr_count)(s3)
199
200 /*
201 * temporarily disable interrupt
202 */
203 mfc0 t2,CP0_STATUS
204 and t2,s1
205
206 addu t0,t3
207 lw t0,(t0)
208 mtc0 t2,CP0_STATUS # delay slot
209 jalr t0
210 nor s1,zero,s1 # delay slot
211
212 /*
213 * reenable interrupt
214 */
215 mfc0 t2,CP0_STATUS
216 or t2,s1
217 mtc0 t2,CP0_STATUS
218
219 lw t2,%lo(intr_count)(s3)
220 subu t2,1
221
222 jr v0
223 sw t2,%lo(intr_count)(s3)
224
225 /*
226 * Just for debugging...
227 */
228 LEAF(drawline)
229 li t1,0xffffffff
230 li t2,0x100
231 1: sw t1,(a0)
232 addiu a0,a0,4
233 addiu t2,t2,-1
234 bnez t2,1b
235 nop
236 jr ra
237 nop
238 END(drawline)
239
240
241 .data
242 PTR ll_sw0 # SW0
243 PTR ll_sw1 # SW1
244 PTR ll_local_dma # Local DMA
245 PTR ll_local_dev # Local devices
246 PTR ll_eisa_irq # EISA IRQ
247 PTR ll_eisa_nmi # EISA NMI
248 PTR ll_timer # Timer
249 ll_vectors: PTR ll_count # Count/Compare IRQ
250
251 local_vector: PTR loc_no_irq
252 PTR loc_parallel
253 PTR loc_floppy
254 PTR loc_sound
255 PTR loc_video
256 PTR loc_ethernet
257 PTR loc_scsi
258 PTR loc_keyboard
259 PTR loc_mouse
260 PTR loc_serial1
261 PTR loc_serial2
262
263 .align 5
264 LEAF(spurious_interrupt)
265 /*
266 * Nothing happened... (whistle)
267 */
268 lui t1,%hi(spurious_count)
269 lw t0,%lo(spurious_count)(t1)
270 la v0,return
271 addiu t0,1
272 jr ra
273 sw t0,%lo(spurious_count)(t1)
274 END(spurious_interrupt)
275