Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
awilliam
GitHub Repository: awilliam/linux-vfio
Path: blob/master/arch/mips/dec/int-handler.S
10817 views
1
/*
2
* Copyright (C) 1995, 1996, 1997 Paul M. Antoine and Harald Koerfgen
3
* Copyright (C) 2000, 2001, 2002, 2003, 2005 Maciej W. Rozycki
4
*
5
* Written by Ralf Baechle and Andreas Busse, modified for DECstation
6
* support by Paul Antoine and Harald Koerfgen.
7
*
8
* completly rewritten:
9
* Copyright (C) 1998 Harald Koerfgen
10
*
11
* Rewritten extensively for controller-driven IRQ support
12
* by Maciej W. Rozycki.
13
*/
14
15
#include <asm/addrspace.h>
16
#include <asm/asm.h>
17
#include <asm/mipsregs.h>
18
#include <asm/regdef.h>
19
#include <asm/stackframe.h>
20
21
#include <asm/dec/interrupts.h>
22
#include <asm/dec/ioasic_addrs.h>
23
#include <asm/dec/ioasic_ints.h>
24
#include <asm/dec/kn01.h>
25
#include <asm/dec/kn02.h>
26
#include <asm/dec/kn02xa.h>
27
#include <asm/dec/kn03.h>
28
29
#define KN02_CSR_BASE CKSEG1ADDR(KN02_SLOT_BASE + KN02_CSR)
30
#define KN02XA_IOASIC_BASE CKSEG1ADDR(KN02XA_SLOT_BASE + IOASIC_IOCTL)
31
#define KN03_IOASIC_BASE CKSEG1ADDR(KN03_SLOT_BASE + IOASIC_IOCTL)
32
33
.text
34
.set noreorder
35
/*
36
* plat_irq_dispatch: Interrupt handler for DECstations
37
*
38
* We follow the model in the Indy interrupt code by David Miller, where he
39
* says: a lot of complication here is taken away because:
40
*
41
* 1) We handle one interrupt and return, sitting in a loop
42
* and moving across all the pending IRQ bits in the cause
43
* register is _NOT_ the answer, the common case is one
44
* pending IRQ so optimize in that direction.
45
*
46
* 2) We need not check against bits in the status register
47
* IRQ mask, that would make this routine slow as hell.
48
*
49
* 3) Linux only thinks in terms of all IRQs on or all IRQs
50
* off, nothing in between like BSD spl() brain-damage.
51
*
52
* Furthermore, the IRQs on the DECstations look basically (barring
53
* software IRQs which we don't use at all) like...
54
*
55
* DS2100/3100's, aka kn01, aka Pmax:
56
*
57
* MIPS IRQ Source
58
* -------- ------
59
* 0 Software (ignored)
60
* 1 Software (ignored)
61
* 2 SCSI
62
* 3 Lance Ethernet
63
* 4 DZ11 serial
64
* 5 RTC
65
* 6 Memory Controller & Video
66
* 7 FPU
67
*
68
* DS5000/200, aka kn02, aka 3max:
69
*
70
* MIPS IRQ Source
71
* -------- ------
72
* 0 Software (ignored)
73
* 1 Software (ignored)
74
* 2 TurboChannel
75
* 3 RTC
76
* 4 Reserved
77
* 5 Memory Controller
78
* 6 Reserved
79
* 7 FPU
80
*
81
* DS5000/1xx's, aka kn02ba, aka 3min:
82
*
83
* MIPS IRQ Source
84
* -------- ------
85
* 0 Software (ignored)
86
* 1 Software (ignored)
87
* 2 TurboChannel Slot 0
88
* 3 TurboChannel Slot 1
89
* 4 TurboChannel Slot 2
90
* 5 TurboChannel Slot 3 (ASIC)
91
* 6 Halt button
92
* 7 FPU/R4k timer
93
*
94
* DS5000/2x's, aka kn02ca, aka maxine:
95
*
96
* MIPS IRQ Source
97
* -------- ------
98
* 0 Software (ignored)
99
* 1 Software (ignored)
100
* 2 Periodic Interrupt (100usec)
101
* 3 RTC
102
* 4 I/O write timeout
103
* 5 TurboChannel (ASIC)
104
* 6 Halt Keycode from Access.Bus keyboard (CTRL-ALT-ENTER)
105
* 7 FPU/R4k timer
106
*
107
* DS5000/2xx's, aka kn03, aka 3maxplus:
108
*
109
* MIPS IRQ Source
110
* -------- ------
111
* 0 Software (ignored)
112
* 1 Software (ignored)
113
* 2 System Board (ASIC)
114
* 3 RTC
115
* 4 Reserved
116
* 5 Memory
117
* 6 Halt Button
118
* 7 FPU/R4k timer
119
*
120
* We handle the IRQ according to _our_ priority (see setup.c),
121
* then we just return. If multiple IRQs are pending then we will
122
* just take another exception, big deal.
123
*/
124
.align 5
125
NESTED(plat_irq_dispatch, PT_SIZE, ra)
126
.set noreorder
127
128
/*
129
* Get pending Interrupts
130
*/
131
mfc0 t0,CP0_CAUSE # get pending interrupts
132
mfc0 t1,CP0_STATUS
133
#ifdef CONFIG_32BIT
134
lw t2,cpu_fpu_mask
135
#endif
136
andi t0,ST0_IM # CAUSE.CE may be non-zero!
137
and t0,t1 # isolate allowed ones
138
139
beqz t0,spurious
140
141
#ifdef CONFIG_32BIT
142
and t2,t0
143
bnez t2,fpu # handle FPU immediately
144
#endif
145
146
/*
147
* Find irq with highest priority
148
*/
149
PTR_LA t1,cpu_mask_nr_tbl
150
1: lw t2,(t1)
151
nop
152
and t2,t0
153
beqz t2,1b
154
addu t1,2*PTRSIZE # delay slot
155
156
/*
157
* Do the low-level stuff
158
*/
159
lw a0,(-PTRSIZE)(t1)
160
nop
161
bgez a0,handle_it # irq_nr >= 0?
162
# irq_nr < 0: it is an address
163
nop
164
jr a0
165
# a trick to save a branch:
166
lui t2,(KN03_IOASIC_BASE>>16)&0xffff
167
# upper part of IOASIC Address
168
169
/*
170
* Handle "IRQ Controller" Interrupts
171
* Masked Interrupts are still visible and have to be masked "by hand".
172
*/
173
FEXPORT(kn02_io_int) # 3max
174
lui t0,(KN02_CSR_BASE>>16)&0xffff
175
# get interrupt status and mask
176
lw t0,(t0)
177
nop
178
andi t1,t0,KN02_IRQ_ALL
179
b 1f
180
srl t0,16 # shift interrupt mask
181
182
FEXPORT(kn02xa_io_int) # 3min/maxine
183
lui t2,(KN02XA_IOASIC_BASE>>16)&0xffff
184
# upper part of IOASIC Address
185
186
FEXPORT(kn03_io_int) # 3max+ (t2 loaded earlier)
187
lw t0,IO_REG_SIR(t2) # get status: IOASIC sir
188
lw t1,IO_REG_SIMR(t2) # get mask: IOASIC simr
189
nop
190
191
1: and t0,t1 # mask out allowed ones
192
193
beqz t0,spurious
194
195
/*
196
* Find irq with highest priority
197
*/
198
PTR_LA t1,asic_mask_nr_tbl
199
2: lw t2,(t1)
200
nop
201
and t2,t0
202
beq zero,t2,2b
203
addu t1,2*PTRSIZE # delay slot
204
205
/*
206
* Do the low-level stuff
207
*/
208
lw a0,%lo(-PTRSIZE)(t1)
209
nop
210
bgez a0,handle_it # irq_nr >= 0?
211
# irq_nr < 0: it is an address
212
nop
213
jr a0
214
nop # delay slot
215
216
/*
217
* Dispatch low-priority interrupts. We reconsider all status
218
* bits again, which looks like a lose, but it makes the code
219
* simple and O(log n), so it gets compensated.
220
*/
221
FEXPORT(cpu_all_int) # HALT, timers, software junk
222
li a0,DEC_CPU_IRQ_BASE
223
srl t0,CAUSEB_IP
224
li t1,CAUSEF_IP>>CAUSEB_IP # mask
225
b 1f
226
li t2,4 # nr of bits / 2
227
228
FEXPORT(kn02_all_int) # impossible ?
229
li a0,KN02_IRQ_BASE
230
li t1,KN02_IRQ_ALL # mask
231
b 1f
232
li t2,4 # nr of bits / 2
233
234
FEXPORT(asic_all_int) # various I/O ASIC junk
235
li a0,IO_IRQ_BASE
236
li t1,IO_IRQ_ALL # mask
237
b 1f
238
li t2,8 # nr of bits / 2
239
240
/*
241
* Dispatch DMA interrupts -- O(log n).
242
*/
243
FEXPORT(asic_dma_int) # I/O ASIC DMA events
244
li a0,IO_IRQ_BASE+IO_INR_DMA
245
srl t0,IO_INR_DMA
246
li t1,IO_IRQ_DMA>>IO_INR_DMA # mask
247
li t2,8 # nr of bits / 2
248
249
/*
250
* Find irq with highest priority.
251
* Highest irq number takes precedence.
252
*/
253
1: srlv t3,t1,t2
254
2: xor t1,t3
255
and t3,t0,t1
256
beqz t3,3f
257
nop
258
move t0,t3
259
addu a0,t2
260
3: srl t2,1
261
bnez t2,2b
262
srlv t3,t1,t2
263
264
handle_it:
265
j dec_irq_dispatch
266
nop
267
268
#ifdef CONFIG_32BIT
269
fpu:
270
j handle_fpe_int
271
nop
272
#endif
273
274
spurious:
275
j spurious_interrupt
276
nop
277
END(plat_irq_dispatch)
278
279
/*
280
* Generic unimplemented interrupt routines -- cpu_mask_nr_tbl
281
* and asic_mask_nr_tbl are initialized to point all interrupts here.
282
* The tables are then filled in by machine-specific initialisation
283
* in dec_setup().
284
*/
285
FEXPORT(dec_intr_unimplemented)
286
move a1,t0 # cheats way of printing an arg!
287
PANIC("Unimplemented cpu interrupt! CP0_CAUSE: 0x%08x");
288
289
FEXPORT(asic_intr_unimplemented)
290
move a1,t0 # cheats way of printing an arg!
291
PANIC("Unimplemented asic interrupt! ASIC ISR: 0x%08x");
292
293