summaryrefslogtreecommitdiffstats
path: root/private/ntos/fw/mips/j4inter.s
diff options
context:
space:
mode:
authorAdam <you@example.com>2020-05-17 05:51:50 +0200
committerAdam <you@example.com>2020-05-17 05:51:50 +0200
commite611b132f9b8abe35b362e5870b74bce94a1e58e (patch)
treea5781d2ec0e085eeca33cf350cf878f2efea6fe5 /private/ntos/fw/mips/j4inter.s
downloadNT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.gz
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.bz2
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.lz
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.xz
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.zst
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.zip
Diffstat (limited to 'private/ntos/fw/mips/j4inter.s')
-rw-r--r--private/ntos/fw/mips/j4inter.s514
1 files changed, 514 insertions, 0 deletions
diff --git a/private/ntos/fw/mips/j4inter.s b/private/ntos/fw/mips/j4inter.s
new file mode 100644
index 000000000..45072f85a
--- /dev/null
+++ b/private/ntos/fw/mips/j4inter.s
@@ -0,0 +1,514 @@
+#if defined(JAZZ) && defined(R4000)
+
+
+/*++
+
+Copyright (c) 1990 Microsoft Corporation
+
+Module Name:
+
+ j4inter.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 "selfmap.h"
+#include "dmaregs.h"
+
+#ifdef DUO
+#include <duoprom.h>
+#else
+#include <jazzprom.h>
+#endif
+
+//
+// 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)
+#ifdef DUO
+//
+// Interrupt indexes in the cause register
+//
+#define SOFT0_INT 0 // software int 0
+#define SOFT1_INT 1 // software int 1
+#define DMA_INT 2 // hardware int 0
+#define DEVICE_INT 3 // hardware int 1
+#define EISA_INT 4 // hardware int 2
+#define TIMER_INT 5 // hardware int 3
+#define IP_INT 6 // hardware int 4
+#define R400_TIMER_INT 7 // hardware int 5
+
+#else
+
+//
+// Interrupt indexes in the cause register
+//
+#define SOFT0_INT 0 // software int 0
+#define SOFT1_INT 1 // software int 1
+#define DMA_INT 2 // hardware int 0
+#define DEVICE_INT 3 // hardware int 1
+#define EISA_INT 4 // hardware int 2
+#define EISA_NMI_INT 5 // hardware int 3
+#define TIMER_INT 6 // hardware int 4
+#define R400_TIMER_INT 7 // hardware int 5
+
+#endif
+//
+// Interrupt mask, to enable just the desired interrupts.
+//
+
+#define INT_MASK ((1<<TIMER_INT) | (1<<DEVICE_INT))
+
+//
+// Stack frame offset definitions.
+//
+#define IntFrameT0 0x4
+#define IntFrameT1 0x8
+#define IntFrameT2 0xC
+#define IntFrameT3 0x10
+#define IntFrameT4 0x14
+#define IntFrameT5 0x18
+#define IntFrameT6 0x1C
+#define IntFrameT7 0x20
+#define IntFrameT8 0x24
+#define IntFrameT9 0x28
+#define IntFrameAT 0x2C
+#define IntFrameRa 0x30
+#define IntFrameA0 0x34
+#define IntFrameA1 0x38
+#define IntFrameA2 0x3C
+#define IntFrameA3 0x40
+#define IntFrameV0 0x44
+#define IntFrameV1 0x48
+#define IntFrameSize 0x50
+
+
+ .data
+FwSavedK1Address:
+ .space 4 // address where to save exception return address.
+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 "Interrupt not expected.\r\n\0"
+#define IntOffset 10
+.globl TimerTicks
+TimerTicks: // Counter of timer ticks. Decremented by TimerInterrupt 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
+//
+// 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
+ la t1,R4000TimerInt // get address of routine
+ sw t1,R400_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,ETHERNET_DEVICE(t0) // store in table
+ la t1,VideoInterrupt // address of handler
+ sw t1,VIDEO_DEVICE(t0) // store in table
+//
+// Initialize the exception dispatch table
+//
+ li t0,KSEG1_BASE // lookup table
+ la t1,SelftestExceptionHandler // address of Exception Handler
+ sw t1,0x1014(t0)// write in firmware vector
+
+//
+// read the interrupt pending register a few times to clear
+// interrupts.
+//
+ li t0,INTERRUPT_VIRTUAL_BASE
+ lbu zero,0(t0)
+ lbu zero,0(t0)
+ lbu zero,0(t0)
+//
+// Enable interrupts.
+//
+
+ li t0,(1<< PSR_BEV)+(1<<PSR_IE)+(INT_MASK<<PSR_INTMASK)+(1 << PSR_CU1)
+ mtc0 t0,psr
+ nop
+ nop
+ nop
+ j ra // return to caller
+ nop
+ .end ConnectInterrupts
+ //++
+// SelftestExceptionHandler
+//
+// Routine Description:
+//
+// This routine is called as a result of an exception
+// If the exception is an interrupt it calls the interrupt handler
+// otherwise it jumps to the monitor.
+// This routine is called using the firmware exception handling convection.
+// It must return to k1 and put the address where to return from
+// the exception in k0.
+//
+// Arguments:
+//
+// None.
+//
+// Return Value:
+//
+// None.
+//
+//--
+ LEAF_ENTRY (SelftestExceptionHandler)
+ la k0,FwSavedK1Address //
+ sw k1,0(k0) // save fw return address
+ mfc0 k0,cause // get cause register
+ li k1,R4000_XCODE_MASK // get mask to extract cause of exception
+ and k0,k1 // get cause of exception
+ beq k0,zero,10f // if 0 is an interrupt.
+ la k0,MonitorExceptionHandler // otherwise
+ j k0 // Jump to the Monitor
+ ori k1,zero,COMMON_EXCEPTION // signal that a common exception occurred.
+10:
+ la k0,InterruptDispatcher // call interrupt dispatcher
+ j k0
+ nop
+ ALTERNATE_ENTRY(ExceptionReturn)
+ la k0,FwSavedK1Address //
+ lw k1,0(k0) // load fw return address
+ mfc0 k0,epc // set address where to return from exception
+ j k1 // jump to firmware
+ nop
+ .end SelftestExceptionHandler
+
+ //++
+// 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 must return
+// to k1 and put the address where to return from the exception in k0.
+//
+// Arguments:
+//
+// None.
+//
+// Return Value:
+//
+// None.
+//
+//--
+ 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 for dispatch table
+CheckNextInt:
+ andi t4,t2,(1<<15) // check for interrupt starting
+ bne t4,zero,JumpToInterrupt // with higher priority
+ 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:
+ 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)
+ b ExceptionReturn // branch to return from exception
+ 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 and 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 MCTADR IntervalTimer interrupt. The routine decrements
+// a counter used for timeouts during the self-test.
+// 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
+#ifdef DUO
+ lw t1,DmaTimerInterruptAcknowledge(t1)
+#else
+ lw t1,DmaIntervalTimer(t1) // read register to clear int.
+#endif
+ addiu t2,t2,-1 // decrement counter by one
+NoDecrement:
+ sw t2,0(t5) // store new counter value
+ j ra // return to caller.
+ nop
+ .end IntervalTimerInt
+ //
+//++
+//R4000 TimerInt
+//
+// Routine Description:
+//
+// This routine is called as a result of an R4000 timer Interrupt
+//
+// Arguments:
+//
+// None.
+//
+// Return Value:
+//
+// None.
+//
+//--
+ LEAF_ENTRY(R4000TimerInt)
+ li t0,1000
+ mtc0 t0,compare // clear interrupt
+ j ra // return to caller.
+ nop
+ .end R4000TimerInt
+//
+//++
+//HandlerForNoHandlers
+//
+// Routine Description:
+//
+// This routine is called when an interrupt is received and no handler
+// has been set for it.
+// It displays a message and then hangs blinking the error code
+// in the LED.
+//
+// Arguments:
+//
+// a0 has the interrupt value.
+//
+// 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 to digit interrupt #
+ sb t1,IntOffset+1(a0) // into message
+ li a1,0 // column 0
+ jal FwPrint // display error
+ li a2,1 // row 0
+ 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) | (1 << PSR_CU1)
+ mtc0 t0,psr
+ nop
+ nop
+ nop
+ nop
+ j ra
+ nop
+ .end DisableInterrupts
+#endif //R4000 && JAZZ