summaryrefslogtreecommitdiffstats
path: root/private/ntos/fw/mips/j3inter.s
blob: db9ae9f637b746f6bf6fb1288d62c9b610e6ebd1 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
#if defined(JAZZ) && defined(R3000)

/*++

Copyright (c) 1990  Microsoft Corporation

Module Name:

    j3inter.s

Abstract:

    This module contains the interrupt dispatcher and various interrupt
    routines for the selftest. The exception dispatcher resides in rom
    because the BEV bit in the psr is set.

Author:

    Lluis Abello (lluis)  8-May-91

Environment:

    Executes in kernal mode.


Revision History:


--*/
#include "led.h"
#include "ksmips.h"
#include "trap.h"
#include "interupt.h"
#include "jzconfig.h"
#include "dmaregs.h"
#include <jazzprom.h>
//
// PROM entry point definitions.
// Define base address of prom entry vector and prom entry macro.
//
#define PROM_BASE (KSEG1_BASE | 0x1fc00000)
#define PROM_ENTRY(x) (PROM_BASE + ((x) * 8))


#define PutLedDisplay PROM_ENTRY(14)
 .globl TimerTicks
 .data
InterruptTable: 	    // vector of 8 interrupt handler pointers
    .word  0:8		    // initialy set to zero.
DeviceIntTable: 	    // vector of 10 device interrupt handler pointers
    .word  0:10 	    // initialy set to zero.
InterruptNotExpectedMsg:
    .ascii  "\r\nInterrupt    not expected.\r\n\0"
#define IntOffset 12
TimerTicks:		    // Counter of timer ticks. Decremented by Timer interrupt handler.
    .word  0
.text
    .set noreorder
    .set noat
//
//++
//ConnectInterrupts
//
// Routine Description:
//
//	This routine initializes the interrupt table with pointers to
//	the interrupt handlers.
//
//	Handlers for the following interrupts are installed:
//	    MCT_ADR Interval Timer
//	    Sonic
//	    Video
//	    Sound
//
//	It also enables interrupts.
//
// Arguments:
//
//	None.
//
// Return Value:
//
//	None.
//
//--

	LEAF_ENTRY(ConnectInterrupts)
	//
	// Initialize the interrupt dispatch table
	//
	la	t0,InterruptTable		// get address of table
	la	t1,DeviceInt			// address of routine
	sw	t1,DEVICE_INT*4(t0)		// store in table
	la	t1,IntervalTimerInt		// get address of routine
	sw	t1,TIMER_INT*4(t0)		// store it in table
	//
	// Initialize the device interrupt dispatch table
	//
	la	t0,DeviceIntTable		// get address of table
	la	t1,SonicInterrupt		// address of handler
	sw	t1,INTR_SRC_LAN(t0)		// store in table
	la	t1,VideoInterrupt		// address of handler
	sw	t1,INTR_SRC_VIDEO(t0)		// store in table
//	la	t1,SoundInterrupt		// address of handler
//	sw	t1,INTR_SRC_SOUND(t0)		// store in table
	//
	// Initialize the exception dispatch table
	//
	li	t0,EXCEPTION_JUMP_TABLE 	// lookup table
	la	t1,InterruptDispatcher		// address of interrupt disp
	sw	t1,EXCEPTION_INT(t0)		// write in proper entry.

	//
	// Enable interrupts.
	//
	li	t0,(1<< PSR_BEV)+(1<<PSR_IEC)+(INT_MASK<<PSR_INTMASK)
	mtc0	t0,psr
	nop
	j	ra
	nop
	.end	ConnectInterrupts


//++
// InterruptDispatcher
//
// Routine Description:
//
//	This routine is called as a result of an interrupt
//	It looks in the interrupt dispatch table for a handler and
//	jumps to it if it founds any.
//	This routine is called from rom. The interrupt handler executes
//	a 'j ra' to go back to the rom code which will execute the rfe.
//
//
//
//
// Arguments:
//
//	None.
//
// Return Value:
//
//--

	LEAF_ENTRY (InterruptDispatcher)
	subu	sp,sp,IntFrameSize	    // make room in the stack
	sw	t0,IntFrameT0(sp)	    // save temporay registers
	sw	t1,IntFrameT1(sp)
	sw	t2,IntFrameT2(sp)
	sw	t3,IntFrameT3(sp)
	sw	t4,IntFrameT4(sp)
	sw	t5,IntFrameT5(sp)
	sw	t6,IntFrameT6(sp)
	sw	t7,IntFrameT7(sp)
	sw	t8,IntFrameT8(sp)
	sw	t9,IntFrameT9(sp)
	sw	AT,IntFrameAT(sp)
	sw	a0,IntFrameA0(sp)
	sw	a1,IntFrameA1(sp)
	sw	a2,IntFrameA2(sp)
	sw	a3,IntFrameA3(sp)
	sw	v0,IntFrameV0(sp)
	sw	v1,IntFrameV1(sp)
	sw	ra,IntFrameRa(sp)
	mfc0	t1,cause		    // get cause register
	mfc0	t2,psr			    // get psr register
	la	t0,InterruptTable	    // get address of interrupt table.
	and	t2,t2,t1		    // and them to discard disabled interrupts
	li	t3,0x20 		    // Index of table
CheckNextInt:
	andi	t4,t2,(1<<15)		    // check for interrupt starting with higher priority
	bne	t4,zero,JumpToInterrupt     //
	subu	t3,t3,0x4		    // Next table index
	bne	t3,zero,CheckNextInt
	sll	t2,t2,1 		    // shift IntPend field to check next
JumpToInterrupt:			    // t3 has the interrupt index
	addu	t0,t0,t3		    // add offset to table
	lw	t0,0(t0)		    // get routine address
	nop
	bne	t0,zero,GoToHandler
	nop
	jal	HandlerForNoHandlers
	ori	a0,t3,0xC0		    // a0 has the encoded interrupt number
	j	ExitInterrupt
	nop
GoToHandler:
	jal	t0
	nop
ExitInterrupt:
	li	k0,GOTO_EPC		    // tell dispatcher to return normally
	lw	ra,IntFrameRa(sp)	    // restore stack
	lw	t0,IntFrameT0(sp)	    // restore temporay registers
	lw	t1,IntFrameT1(sp)
	lw	t2,IntFrameT2(sp)
	lw	t3,IntFrameT3(sp)
	lw	t4,IntFrameT4(sp)
	lw	t5,IntFrameT5(sp)
	lw	t6,IntFrameT6(sp)
	lw	t7,IntFrameT7(sp)
	lw	t8,IntFrameT8(sp)
	lw	t9,IntFrameT9(sp)
	lw	AT,IntFrameAT(sp)
	lw	a0,IntFrameA0(sp)
	lw	a1,IntFrameA1(sp)
	lw	a2,IntFrameA2(sp)
	lw	a3,IntFrameA3(sp)
	lw	v0,IntFrameV0(sp)
	lw	v1,IntFrameV1(sp)
	j	ra			    // return to rom exception dispatch
	addu	sp,sp,IntFrameSize	    // restore stack
    .end	InterruptDispatcher

//
//++
//DeviceInt
//
// Routine Description:
//
//	This routine is called as a result of a Hardware Interrupt 1
//	This is a device interrupt. The routine reads the interrupt
//	source register sand dispatches to the proper interrupt handler
//
// Arguments:
//
//	None.
//
// Return Value:
//
//	None.
//
//--

	LEAF_ENTRY(DeviceInt)
	li	t0,INTERRUPT_VIRTUAL_BASE   // address of interrupt source reg
	lbu	a0,0(t0)		    // read interrupt
	la	t0, DeviceIntTable	    // base address of dispatch table.
	addu	t0,t0,a0		    // add offset to base
	lw	t0,0(t0)		    // read handler address
	nop
	beq	t0,zero,HandlerForNoHandlers// hang diplay something in the led
	nop
	j	t0			    // go to routine.
	nop
	.end DeviceInt


//++
//VideoInterrupt
//
// Routine Description:
//
//	This routine is called as a result of a video interrupt.
//	It does nothing is just here no to take a video interrupt as
//	an error.
//
// Arguments:
//
//	None.
//
// Return Value:
//
//	None.
//
//--

	LEAF_ENTRY(VideoInterrupt)
	j	ra			    // return to caller.
	nop
	.end VideoInterrupt

//
//++
//IntervalTimerInt
//
// Routine Description:
//
//	This routine is called as a result of a Hardware Interrupt 4
//	This is an Interval timer interrupt. The routine decrements a counter
//	used for timeout.
//	A test that needs timeout facilites must set the number of milliseconds
//	into the TimerTicks variable and poll it until it's zero.
//
// Arguments:
//
//	None.
//
// Return Value:
//
//	None.
//
//--

	LEAF_ENTRY(IntervalTimerInt)
	la	t5,TimerTicks		    // get address of counter
	lw	t2,0(t5)		    // read counter
	li	t1,DMA_VIRTUAL_BASE	    // base address of MCTADR
	beq	t2,zero,NoDecrement
	lw	t1,DmaIntervalTimer(t1)     // read register to clear int.
	addiu	t2,t2,-1		    // decrement counter by one
NoDecrement:
	j	ra			    // return to caller.
	sw	t2,0(t5)		    // store new counter value
	.end IntervalTimerInt

//
//++
//HandlerForNoHandlers
//
// Routine Description:
//
//	This routine is called when an interrupt is received and no handler
//	as been set for it.
//
// Arguments:
//
//	None.
//
// Return Value:
//
//	None.
//
//--

    LEAF_ENTRY(HandlerForNoHandlers)
        srl     t0,a0,4                         // get second digit
	andi	t0,t0,0xF
	slti	t1,t0,10
	bne	t1,zero,10f			// branch if 0-9
	addiu	t0,t0,0x30			 // addjust value
        addiu   t0,t0,0x41-0x30-10               // readjust value if A-F
10:
	andi	t1,a0,0xF			// get less significant digit
	slti	t2,t1,10
	bne	t2,zero,10f			// branch if 0-9
	addiu	t1,t1,0x30			 // addjust value
        addiu   t1,t1,0x41-0x30-10                // readjust value if A-F
10:
	la	a0,InterruptNotExpectedMsg	// get message address
        sb      t0,IntOffset(a0)                // write 1st digit interrupt#
        jal     FwPrint                         // display error
        sb      t1,IntOffset+1(a0)              // write 2nd digit interrupt#
	li	t0,PutLedDisplay		// get address of led
	lui	a0,LED_BLINK
	jal	t0
	ori	a0,a0,LED_NOT_INTERRUPT
    .end    HandlerForNoHandlers
//
//++
//DisableInterrupt
//
// Routine Description:
//
//	This routine disables interrupts.  By clearing the IEc bit in the psr
//
// Arguments:
//
//	None.
//
// Return Value:
//
//	None.
//
//--

    LEAF_ENTRY(DisableInterrupts)
        li      t0,(1<< PSR_BEV)
	mtc0	t0,psr
	j	ra
	nop
    .end DisableInterrupts
#endif  //JAZZ && R3000