714 lines
22 KiB
ArmAsm
714 lines
22 KiB
ArmAsm
|
// TITLE("Interrupt Object Support Routines")
|
|||
|
//++
|
|||
|
//
|
|||
|
// Copyright (c) 1990 Microsoft Corporation
|
|||
|
//
|
|||
|
// Module Name:
|
|||
|
//
|
|||
|
// xxintsup.s
|
|||
|
//
|
|||
|
// Abstract:
|
|||
|
//
|
|||
|
// This module implements the code necessary to support interrupt objects.
|
|||
|
// It contains the interrupt dispatch code and the code template that gets
|
|||
|
// copied into an interrupt object.
|
|||
|
//
|
|||
|
// Author:
|
|||
|
//
|
|||
|
// David N. Cutler (davec) 2-Apr-1990
|
|||
|
//
|
|||
|
// Environment:
|
|||
|
//
|
|||
|
// Kernel mode only.
|
|||
|
//
|
|||
|
// Revision History:
|
|||
|
//
|
|||
|
//--
|
|||
|
|
|||
|
#include "ksmips.h"
|
|||
|
|
|||
|
SBTTL("Synchronize Execution")
|
|||
|
//++
|
|||
|
//
|
|||
|
// BOOLEAN
|
|||
|
// KeSynchronizeExecution (
|
|||
|
// IN PKINTERRUPT Interrupt,
|
|||
|
// IN PKSYNCHRONIZE_ROUTINE SynchronizeRoutine,
|
|||
|
// IN PVOID SynchronizeContext
|
|||
|
// )
|
|||
|
//
|
|||
|
// Routine Description:
|
|||
|
//
|
|||
|
// This function synchronizes the execution of the specified routine with the
|
|||
|
// execution of the service routine associated with the specified interrupt
|
|||
|
// object.
|
|||
|
//
|
|||
|
// Arguments:
|
|||
|
//
|
|||
|
// Interrupt (a0) - Supplies a pointer to a control object of type interrupt.
|
|||
|
//
|
|||
|
// SynchronizeRoutine (a1) - Supplies a pointer to a function whose execution
|
|||
|
// is to be synchronized with the execution of the service routine associated
|
|||
|
// with the specified interrupt object.
|
|||
|
//
|
|||
|
// SynchronizeContext (a2) - Supplies a pointer to an arbitrary data structure
|
|||
|
// which is to be passed to the function specified by the SynchronizeRoutine
|
|||
|
// parameter.
|
|||
|
//
|
|||
|
// Return Value:
|
|||
|
//
|
|||
|
// The value returned by the SynchronizeRoutine function is returned as the
|
|||
|
// function value.
|
|||
|
//
|
|||
|
//--
|
|||
|
|
|||
|
.struct 0
|
|||
|
SyArg: .space 4 * 4 // argument register save area
|
|||
|
SyS0: .space 4 // saved integer register s0
|
|||
|
SyIrql: .space 4 // saved IRQL value
|
|||
|
.space 4 // fill for alignment
|
|||
|
SyRa: .space 4 // saved return address
|
|||
|
SyFrameLength: // length of stack frame
|
|||
|
SyA0: .space 4 // saved argument registers a0 - a2
|
|||
|
SyA1: .space 4 //
|
|||
|
SyA2: .space 4 //
|
|||
|
|
|||
|
NESTED_ENTRY(KeSynchronizeExecution, SyFrameLength, zero)
|
|||
|
|
|||
|
subu sp,sp,SyFrameLength // allocate stack frame
|
|||
|
sw ra,SyRa(sp) // save return address
|
|||
|
sw s0,SyS0(sp) // save integer register s0
|
|||
|
|
|||
|
PROLOGUE_END
|
|||
|
|
|||
|
sw a1,SyA1(sp) // save synchronization routine address
|
|||
|
sw a2,SyA2(sp) // save synchronization routine context
|
|||
|
|
|||
|
//
|
|||
|
// Raise IRQL to the synchronization level and acquire the associated
|
|||
|
// spin lock.
|
|||
|
//
|
|||
|
|
|||
|
#if defined(R4000) && !defined(NT_UP)
|
|||
|
|
|||
|
lw s0,InActualLock(a0) // get address of spin lock
|
|||
|
|
|||
|
#endif
|
|||
|
|
|||
|
lbu a0,InSynchronizeIrql(a0) // get synchronization IRQL
|
|||
|
addu a1,sp,SyIrql // compute address to save IRQL
|
|||
|
jal KeRaiseIrql // raise IRQL to synchronization IRQL
|
|||
|
|
|||
|
#if defined(R4000) && !defined(NT_UP)
|
|||
|
|
|||
|
10: ll t0,0(s0) // get current lock value
|
|||
|
move t1,s0 // set lock ownership value
|
|||
|
bne zero,t0,10b // if ne, spin lock owned
|
|||
|
sc t1,0(s0) // set spin lock owned
|
|||
|
beq zero,t1,10b // if eq, store conditional failed
|
|||
|
|
|||
|
#endif
|
|||
|
|
|||
|
//
|
|||
|
// Call specified routine passing the specified context parameter.
|
|||
|
//
|
|||
|
|
|||
|
lw t0,SyA1(sp) // get synchronize routine address
|
|||
|
lw a0,SyA2(sp) // get synchronize routine context
|
|||
|
jal t0 // call specified routine
|
|||
|
|
|||
|
//
|
|||
|
// Release spin lock, lower IRQL to its previous level, and return the value
|
|||
|
// returned by the specified routine.
|
|||
|
//
|
|||
|
|
|||
|
#if defined(R4000) && !defined(NT_UP)
|
|||
|
|
|||
|
sw zero,0(s0) // set spin lock not owned
|
|||
|
|
|||
|
#endif
|
|||
|
|
|||
|
lbu a0,SyIrql(sp) // get saved IRQL
|
|||
|
move s0,v0 // save return value
|
|||
|
jal KeLowerIrql // lower IRQL to previous level
|
|||
|
move v0,s0 // set return value
|
|||
|
lw s0,SyS0(sp) // restore integer register s0
|
|||
|
lw ra,SyRa(sp) // restore return address
|
|||
|
addu sp,sp,SyFrameLength // deallocate stack frame
|
|||
|
j ra // return
|
|||
|
|
|||
|
.end KeSynchronizeExecution
|
|||
|
|
|||
|
SBTTL("Chained Dispatch")
|
|||
|
//++
|
|||
|
//
|
|||
|
// Routine Description:
|
|||
|
//
|
|||
|
// This routine is entered as the result of an interrupt being generated
|
|||
|
// via a vector that is connected to more than one interrupt object. Its
|
|||
|
// function is to walk the list of connected interrupt objects and call
|
|||
|
// each interrupt service routine. If the mode of the interrupt is latched,
|
|||
|
// then a complete traversal of the chain must be performed. If any of the
|
|||
|
// routines require saving the volatile floating point machine state, then
|
|||
|
// it is only saved once.
|
|||
|
//
|
|||
|
// N.B. On entry to this routine only the volatile integer registers have
|
|||
|
// been saved.
|
|||
|
//
|
|||
|
// Arguments:
|
|||
|
//
|
|||
|
// a0 - Supplies a pointer to the interrupt object.
|
|||
|
//
|
|||
|
// s8 - Supplies a pointer to a trap frame.
|
|||
|
//
|
|||
|
// Return Value:
|
|||
|
//
|
|||
|
// None.
|
|||
|
//
|
|||
|
//--
|
|||
|
|
|||
|
.struct 0
|
|||
|
ChArg: .space 4 * 4 // argument register save area
|
|||
|
ChS0: .space 4 // saved integer registers s0 - s6
|
|||
|
ChS1: .space 4 //
|
|||
|
ChS2: .space 4 //
|
|||
|
ChS3: .space 4 //
|
|||
|
ChS4: .space 4 //
|
|||
|
ChS5: .space 4 //
|
|||
|
ChS6: .space 4 //
|
|||
|
ChRa: .space 4 // saved return address
|
|||
|
ChFrameLength: // length of stack frame
|
|||
|
ChIrql: .space 4 // saved IRQL value
|
|||
|
|
|||
|
NESTED_ENTRY(KiChainedDispatch, ChFrameLength, zero)
|
|||
|
|
|||
|
subu sp,sp,ChFrameLength // allocate stack frame
|
|||
|
sw ra,ChRa(sp) // save return address
|
|||
|
sw s0,ChS0(sp) // save integer registers s0 - s6
|
|||
|
sw s1,ChS1(sp) //
|
|||
|
sw s2,ChS2(sp) //
|
|||
|
sw s3,ChS3(sp) //
|
|||
|
sw s4,ChS4(sp) //
|
|||
|
sw s5,ChS5(sp) //
|
|||
|
|
|||
|
#if defined(R4000) && !defined(NT_UP)
|
|||
|
|
|||
|
sw s6,ChS6(sp) //
|
|||
|
|
|||
|
#endif
|
|||
|
|
|||
|
PROLOGUE_END
|
|||
|
|
|||
|
//
|
|||
|
// Initialize loop variables.
|
|||
|
//
|
|||
|
|
|||
|
addu s0,a0,InInterruptListEntry // set address of listhead
|
|||
|
move s1,s0 // set address of first entry
|
|||
|
move s2,zero // clear floating state saved flag
|
|||
|
lbu s3,InMode(a0) // get mode of interrupt
|
|||
|
lbu s4,InIrql(a0) // get interrupt source IRQL
|
|||
|
|
|||
|
//
|
|||
|
// Walk the list of connected interrupt objects and call the respective
|
|||
|
// interrupt service routines.
|
|||
|
//
|
|||
|
|
|||
|
10: subu a0,s1,InInterruptListEntry // compute interrupt object address
|
|||
|
lbu t0,InFloatingSave(a0) // get floating save flag
|
|||
|
bne zero,s2,20f // if ne, floating state already saved
|
|||
|
beq zero,t0,20f // if eq, don't save floating state
|
|||
|
|
|||
|
//
|
|||
|
// Save volatile floating registers f0 - f19 in trap frame.
|
|||
|
//
|
|||
|
|
|||
|
SAVE_VOLATILE_FLOAT_STATE // save volatile floating state
|
|||
|
|
|||
|
li s2,1 // set floating state saved flag
|
|||
|
|
|||
|
//
|
|||
|
// Raise IRQL to synchronization level if synchronization level is not
|
|||
|
// equal to the interrupt source level.
|
|||
|
//
|
|||
|
|
|||
|
20: lbu s5,InSynchronizeIrql(a0) // get synchronization IRQL
|
|||
|
beq s4,s5,25f // if eq, IRQL levels are the same
|
|||
|
move a0,s5 // set synchronization IRQL
|
|||
|
addu a1,sp,ChIrql // compute address to save IRQL
|
|||
|
jal KeRaiseIrql // raise to synchronization IRQL
|
|||
|
subu a0,s1,InInterruptListEntry // recompute interrupt object address
|
|||
|
|
|||
|
//
|
|||
|
//
|
|||
|
// Acquire the service routine spin lock and call the service routine.
|
|||
|
//
|
|||
|
|
|||
|
25: //
|
|||
|
|
|||
|
#if defined(R4000) && !defined(NT_UP)
|
|||
|
|
|||
|
lw s6,InActualLock(a0) // get address of spin lock
|
|||
|
30: ll t1,0(s6) // get current lock value
|
|||
|
move t2,s6 // set lock ownership value
|
|||
|
bne zero,t1,30b // if ne, spin lock owned
|
|||
|
sc t2,0(s6) // set spin lock owned
|
|||
|
beq zero,t2,30b // if eq, store conditional failed
|
|||
|
|
|||
|
#endif
|
|||
|
|
|||
|
lw t0,InServiceRoutine(a0) // get address of service routine
|
|||
|
lw a1,InServiceContext(a0) // get service context
|
|||
|
jal t0 // call service routine
|
|||
|
|
|||
|
//
|
|||
|
// Release the service routine spin lock.
|
|||
|
//
|
|||
|
|
|||
|
#if defined(R4000) && !defined(NT_UP)
|
|||
|
|
|||
|
sw zero,0(s6) // set spin lock not owned
|
|||
|
|
|||
|
#endif
|
|||
|
|
|||
|
//
|
|||
|
// Lower IRQL to the interrupt source level if synchronization level is not
|
|||
|
// the same as the interrupt source level.
|
|||
|
//
|
|||
|
|
|||
|
beq s4,s5,35f // if eq, IRQL levels are the same
|
|||
|
move a0,s4 // set interrupt source IRQL
|
|||
|
jal KeLowerIrql // lower to interrupt source IRQL
|
|||
|
|
|||
|
//
|
|||
|
// Get next list entry and check for end of loop.
|
|||
|
//
|
|||
|
|
|||
|
35: lw s1,LsFlink(s1) // get next interrupt object address
|
|||
|
beq zero,v0,40f // if eq, interrupt not handled
|
|||
|
beq zero,s3,50f // if eq, level sensitive interrupt
|
|||
|
40: bne s0,s1,10b // if ne, not end of list
|
|||
|
|
|||
|
//
|
|||
|
// Either the interrupt is level sensitive and has been handled or the end of
|
|||
|
// the interrupt object chain has been reached. Check to determine if floating
|
|||
|
// machine state needs to be restored.
|
|||
|
//
|
|||
|
|
|||
|
50: beq zero,s2,60f // if eq, floating state not saved
|
|||
|
|
|||
|
//
|
|||
|
// Restore volatile floating registers f0 - f19 from trap frame.
|
|||
|
//
|
|||
|
|
|||
|
RESTORE_VOLATILE_FLOAT_STATE // restore volatile floating state
|
|||
|
|
|||
|
//
|
|||
|
// Restore integer registers s0 - s6, retrieve return address, deallocate
|
|||
|
// stack frame, and return.
|
|||
|
//
|
|||
|
|
|||
|
60: lw s0,ChS0(sp) // restore integer registers s0 - s6
|
|||
|
lw s1,ChS1(sp) //
|
|||
|
lw s2,ChS2(sp) //
|
|||
|
lw s3,ChS3(sp) //
|
|||
|
lw s4,ChS4(sp) //
|
|||
|
lw s5,ChS5(sp) //
|
|||
|
|
|||
|
#if defined(R4000) && !defined(NT_UP)
|
|||
|
|
|||
|
lw s6,ChS6(sp) //
|
|||
|
|
|||
|
#endif
|
|||
|
|
|||
|
lw ra,ChRa(sp) // restore return address
|
|||
|
addu sp,sp,ChFrameLength // deallocate stack frame
|
|||
|
j ra // return
|
|||
|
|
|||
|
.end KiChainedDispatch
|
|||
|
|
|||
|
SBTTL("Floating Dispatch")
|
|||
|
//++
|
|||
|
//
|
|||
|
// Routine Description:
|
|||
|
//
|
|||
|
// This routine is entered as the result of an interrupt being generated
|
|||
|
// via a vector that is connected to an interrupt object. Its function is
|
|||
|
// to save the volatile floating machine state and then call the specified
|
|||
|
// interrupt service routine.
|
|||
|
//
|
|||
|
// N.B. On entry to this routine only the volatile integer registers have
|
|||
|
// been saved.
|
|||
|
//
|
|||
|
// Arguments:
|
|||
|
//
|
|||
|
// a0 - Supplies a pointer to the interrupt object.
|
|||
|
//
|
|||
|
// s8 - Supplies a pointer to a trap frame.
|
|||
|
//
|
|||
|
// Return Value:
|
|||
|
//
|
|||
|
// None.
|
|||
|
//
|
|||
|
//--
|
|||
|
|
|||
|
.struct 0
|
|||
|
FlArg: .space 4 * 4 // argument register save area
|
|||
|
FlS0: .space 4 // saved integer registers s0 - s1
|
|||
|
FlS1: .space 4 //
|
|||
|
FlIrql: .space 4 // saved IRQL value
|
|||
|
FlRa: .space 4 // saved return address
|
|||
|
FlFrameLength: // length of stack frame
|
|||
|
|
|||
|
NESTED_ENTRY(KiFloatingDispatch, FlFrameLength, zero)
|
|||
|
|
|||
|
subu sp,sp,FlFrameLength // allocate stack frame
|
|||
|
sw ra,FlRa(sp) // save return address
|
|||
|
sw s0,FlS0(sp) // save integer registers s0 - s1
|
|||
|
|
|||
|
#if defined(R4000) && !defined(NT_UP)
|
|||
|
|
|||
|
sw s1,FlS1(sp) //
|
|||
|
|
|||
|
#endif
|
|||
|
|
|||
|
PROLOGUE_END
|
|||
|
|
|||
|
//
|
|||
|
// Save volatile floating registers f0 - f19 in trap frame.
|
|||
|
//
|
|||
|
|
|||
|
SAVE_VOLATILE_FLOAT_STATE // save volatile floating state
|
|||
|
|
|||
|
//
|
|||
|
// Raise IRQL to synchronization level if synchronization level is not
|
|||
|
// equal to the interrupt source level.
|
|||
|
//
|
|||
|
|
|||
|
move s0,a0 // save address of interrupt object
|
|||
|
lbu a0,InSynchronizeIrql(s0) // get synchronization IRQL
|
|||
|
lbu t0,InIrql(s0) // get interrupt source IRQL
|
|||
|
beq a0,t0,10f // if eq, IRQL levels are the same
|
|||
|
addu a1,sp,FlIrql // compute address to save IRQL
|
|||
|
jal KeRaiseIrql // raise to synchronization IRQL
|
|||
|
10: move a0,s0 // restore address of interrupt object
|
|||
|
|
|||
|
//
|
|||
|
//
|
|||
|
// Acquire the service routine spin lock and call the service routine.
|
|||
|
//
|
|||
|
|
|||
|
#if defined(R4000) && !defined(NT_UP)
|
|||
|
|
|||
|
lw s1,InActualLock(a0) // get address of spin lock
|
|||
|
20: ll t1,0(s1) // get current lock value
|
|||
|
move t2,s1 // set lock ownership value
|
|||
|
bne zero,t1,20b // if ne, spin lock owned
|
|||
|
sc t2,0(s1) // set spin lock owned
|
|||
|
beq zero,t2,20b // if eq, store conditional failed
|
|||
|
|
|||
|
#endif
|
|||
|
|
|||
|
lw t0,InServiceRoutine(a0) // get address of service routine
|
|||
|
lw a1,InServiceContext(a0) // get service context
|
|||
|
jal t0 // call service routine
|
|||
|
|
|||
|
//
|
|||
|
// Release the service routine spin lock.
|
|||
|
//
|
|||
|
|
|||
|
#if defined(R4000) && !defined(NT_UP)
|
|||
|
|
|||
|
sw zero,0(s1) // set spin lock not owned
|
|||
|
|
|||
|
#endif
|
|||
|
|
|||
|
//
|
|||
|
// Lower IRQL to the interrupt source level if synchronization level is not
|
|||
|
// the same as the interrupt source level.
|
|||
|
//
|
|||
|
|
|||
|
lbu a0,InIrql(s0) // get interrupt source IRQL
|
|||
|
lbu t0,InSynchronizeIrql(s0) // get synchronization IRQL
|
|||
|
beq a0,t0,30f // if eq, IRQL levels are the same
|
|||
|
jal KeLowerIrql // lower to interrupt source IRQL
|
|||
|
|
|||
|
//
|
|||
|
// Restore volatile floating registers f0 - f19 from trap frame.
|
|||
|
//
|
|||
|
|
|||
|
30: RESTORE_VOLATILE_FLOAT_STATE // restore volatile floating state
|
|||
|
|
|||
|
//
|
|||
|
// Restore integer registers s0 - s1, retrieve return address, deallocate
|
|||
|
// stack frame, and return.
|
|||
|
//
|
|||
|
|
|||
|
lw s0,FlS0(sp) // restore integer registers s0 - s1
|
|||
|
|
|||
|
#if defined(R4000) && !defined(NT_UP)
|
|||
|
|
|||
|
lw s1,FlS1(sp) //
|
|||
|
|
|||
|
#endif
|
|||
|
|
|||
|
lw ra,FlRa(sp) // restore return address
|
|||
|
addu sp,sp,FlFrameLength // deallocate stack frame
|
|||
|
j ra // return
|
|||
|
|
|||
|
.end KiFloatingDispatch
|
|||
|
|
|||
|
SBTTL("Interrupt Dispatch - Raise IRQL")
|
|||
|
//++
|
|||
|
//
|
|||
|
// Routine Description:
|
|||
|
//
|
|||
|
// This routine is entered as the result of an interrupt being generated
|
|||
|
// via a vector that is connected to an interrupt object. Its function is
|
|||
|
// to directly call the specified interrupt service routine.
|
|||
|
//
|
|||
|
// N.B. On entry to this routine only the volatile integer registers have
|
|||
|
// been saved.
|
|||
|
//
|
|||
|
// N.B. This routine raises the interrupt level to the synchronization
|
|||
|
// level specified in the interrupt object.
|
|||
|
//
|
|||
|
// Arguments:
|
|||
|
//
|
|||
|
// a0 - Supplies a pointer to the interrupt object.
|
|||
|
//
|
|||
|
// s8 - Supplies a pointer to a trap frame.
|
|||
|
//
|
|||
|
// Return Value:
|
|||
|
//
|
|||
|
// None.
|
|||
|
//
|
|||
|
//--
|
|||
|
|
|||
|
.struct 0
|
|||
|
RdArg: .space 4 * 4 // argument register save area
|
|||
|
RdS0: .space 4 // saved integer register s0
|
|||
|
.space 4 // fill
|
|||
|
RdIrql: .space 4 // saved IRQL value
|
|||
|
RdRa: .space 4 // saved return address
|
|||
|
RdFrameLength: // length of stack frame
|
|||
|
|
|||
|
NESTED_ENTRY(KiInterruptDispatchRaise, RdFrameLength, zero)
|
|||
|
|
|||
|
subu sp,sp,RdFrameLength // allocate stack frame
|
|||
|
sw ra,RdRa(sp) // save return address
|
|||
|
sw s0,RdS0(sp) // save integer register s0
|
|||
|
|
|||
|
PROLOGUE_END
|
|||
|
|
|||
|
//
|
|||
|
// Raise IRQL to synchronization level.
|
|||
|
//
|
|||
|
|
|||
|
move s0,a0 // save address of interrupt object
|
|||
|
lbu a0,InSynchronizeIrql(s0) // get synchronization IRQL
|
|||
|
addu a1,sp,RdIrql // compute address to save IRQL
|
|||
|
jal KeRaiseIrql // raise to synchronization IRQL
|
|||
|
move a0,s0 // restore address of interrupt object
|
|||
|
|
|||
|
//
|
|||
|
//
|
|||
|
// Acquire the service routine spin lock and call the service routine.
|
|||
|
//
|
|||
|
|
|||
|
#if defined(R4000) && !defined(NT_UP)
|
|||
|
|
|||
|
lw s0,InActualLock(a0) // get address of spin lock
|
|||
|
10: ll t1,0(s0) // get current lock value
|
|||
|
move t2,s0 // set lock ownership value
|
|||
|
bne zero,t1,10b // if ne, spin lock owned
|
|||
|
sc t2,0(s0) // set spin lock owned
|
|||
|
beq zero,t2,10b // if eq, store conditional failed
|
|||
|
|
|||
|
#endif
|
|||
|
|
|||
|
lw t0,InServiceRoutine(a0) // get address of service routine
|
|||
|
lw a1,InServiceContext(a0) // get service context
|
|||
|
jal t0 // call service routine
|
|||
|
|
|||
|
//
|
|||
|
// Release the service routine spin lock.
|
|||
|
//
|
|||
|
|
|||
|
#if defined(R4000) && !defined(NT_UP)
|
|||
|
|
|||
|
sw zero,0(s0) // set spin lock not owned
|
|||
|
|
|||
|
#endif
|
|||
|
|
|||
|
//
|
|||
|
// Lower IRQL to the previous level.
|
|||
|
//
|
|||
|
|
|||
|
lbu a0,RdIrql(sp) // get previous IRQL
|
|||
|
jal KeLowerIrql // lower to interrupt source IRQL
|
|||
|
|
|||
|
//
|
|||
|
// Restore integer register s0, retrieve return address, deallocate
|
|||
|
// stack frame, and return.
|
|||
|
//
|
|||
|
|
|||
|
lw s0,RdS0(sp) // restore integer registers s0 - s1
|
|||
|
lw ra,RdRa(sp) // restore return address
|
|||
|
addu sp,sp,RdFrameLength // deallocate stack frame
|
|||
|
j ra // return
|
|||
|
|
|||
|
.end KiInterruptDispatchRaise
|
|||
|
|
|||
|
SBTTL("Interrupt Dispatch - Same IRQL")
|
|||
|
//++
|
|||
|
//
|
|||
|
// Routine Description:
|
|||
|
//
|
|||
|
// This routine is entered as the result of an interrupt being generated
|
|||
|
// via a vector that is connected to an interrupt object. Its function is
|
|||
|
// to directly call the specified interrupt service routine.
|
|||
|
//
|
|||
|
// N.B. On entry to this routine only the volatile integer registers have
|
|||
|
// been saved.
|
|||
|
//
|
|||
|
// Arguments:
|
|||
|
//
|
|||
|
// a0 - Supplies a pointer to the interrupt object.
|
|||
|
//
|
|||
|
// s8 - Supplies a pointer to a trap frame.
|
|||
|
//
|
|||
|
// Return Value:
|
|||
|
//
|
|||
|
// None.
|
|||
|
//
|
|||
|
//--
|
|||
|
|
|||
|
#if defined(NT_UP)
|
|||
|
|
|||
|
LEAF_ENTRY(KiInterruptDispatchSame)
|
|||
|
|
|||
|
lw t0,InServiceRoutine(a0) // get address of service routine
|
|||
|
lw a1,InServiceContext(a0) // get service context
|
|||
|
j t0 // jump to service routine
|
|||
|
|
|||
|
#else
|
|||
|
|
|||
|
.struct 0
|
|||
|
SdArg: .space 4 * 4 // argument register save area
|
|||
|
SdS0: .space 4 // saved integer register s0
|
|||
|
.space 4 * 2 // fill
|
|||
|
SdRa: .space 4 // saved return address
|
|||
|
SdFrameLength: // length of stack frame
|
|||
|
|
|||
|
NESTED_ENTRY(KiInterruptDispatchSame, SdFrameLength, zero)
|
|||
|
|
|||
|
subu sp,sp,SdFrameLength // allocate stack frame
|
|||
|
sw ra,SdRa(sp) // save return address
|
|||
|
sw s0,SdS0(sp) // save integer register s0
|
|||
|
|
|||
|
PROLOGUE_END
|
|||
|
|
|||
|
//
|
|||
|
//
|
|||
|
// Acquire the service routine spin lock and call the service routine.
|
|||
|
//
|
|||
|
|
|||
|
lw s0,InActualLock(a0) // get address of spin lock
|
|||
|
10: ll t1,0(s0) // get current lock value
|
|||
|
move t2,s0 // set lock ownership value
|
|||
|
bne zero,t1,10b // if ne, spin lock owned
|
|||
|
sc t2,0(s0) // set spin lock owned
|
|||
|
beq zero,t2,10b // if eq, store conditional failed
|
|||
|
lw t0,InServiceRoutine(a0) // get address of service routine
|
|||
|
lw a1,InServiceContext(a0) // get service context
|
|||
|
jal t0 // call service routine
|
|||
|
|
|||
|
//
|
|||
|
// Release the service routine spin lock.
|
|||
|
//
|
|||
|
|
|||
|
sw zero,0(s0) // set spin lock not owned
|
|||
|
|
|||
|
//
|
|||
|
// Restore integer register s0, retrieve return address, deallocate
|
|||
|
// stack frame, and return.
|
|||
|
//
|
|||
|
|
|||
|
lw s0,SdS0(sp) // restore integer registers s0 - s1
|
|||
|
lw ra,SdRa(sp) // restore return address
|
|||
|
addu sp,sp,SdFrameLength // deallocate stack frame
|
|||
|
j ra // return
|
|||
|
|
|||
|
#endif
|
|||
|
|
|||
|
.end KiInterruptDispatchSame
|
|||
|
|
|||
|
SBTTL("Interrupt Template")
|
|||
|
//++
|
|||
|
//
|
|||
|
// Routine Description:
|
|||
|
//
|
|||
|
// This routine is a template that is copied into each interrupt object. Its
|
|||
|
// function is to determine the address of the respective interrupt object
|
|||
|
// and then transfer control to the appropriate interrupt dispatcher.
|
|||
|
//
|
|||
|
// N.B. On entry to this routine only the volatile integer registers have
|
|||
|
// been saved.
|
|||
|
//
|
|||
|
// Arguments:
|
|||
|
//
|
|||
|
// a0 - Supplies a pointer to the interrupt template within an interrupt
|
|||
|
// object.
|
|||
|
//
|
|||
|
// s8 - Supplies a pointer to a trap frame.
|
|||
|
//
|
|||
|
// Return Value:
|
|||
|
//
|
|||
|
// None.
|
|||
|
//
|
|||
|
//--
|
|||
|
|
|||
|
LEAF_ENTRY(KiInterruptTemplate)
|
|||
|
|
|||
|
.set noreorder
|
|||
|
.set noat
|
|||
|
lw t0,InDispatchAddress - InDispatchCode(a0) // get dispatcher address
|
|||
|
subu a0,a0,InDispatchCode // compute address of interrupt object
|
|||
|
j t0 // transfer control to dispatch routine
|
|||
|
nop //
|
|||
|
.set at
|
|||
|
.set reorder
|
|||
|
|
|||
|
.end KiInterruptTemplate
|
|||
|
|
|||
|
SBTTL("Unexpected Interrupt")
|
|||
|
//++
|
|||
|
//
|
|||
|
// Routine Description:
|
|||
|
//
|
|||
|
// This routine is entered as the result of an interrupt being generated
|
|||
|
// via a vector that is not connected to an interrupt object. Its function
|
|||
|
// is to report the error and dismiss the interrupt.
|
|||
|
//
|
|||
|
// N.B. On entry to this routine only the volatile integer registers have
|
|||
|
// been saved.
|
|||
|
//
|
|||
|
// Arguments:
|
|||
|
//
|
|||
|
// a0 - Supplies a pointer to the interrupt object.
|
|||
|
//
|
|||
|
// s8 - Supplies a pointer to a trap frame.
|
|||
|
//
|
|||
|
// Return Value:
|
|||
|
//
|
|||
|
// None.
|
|||
|
//
|
|||
|
//--
|
|||
|
|
|||
|
LEAF_ENTRY(KiUnexpectedInterrupt)
|
|||
|
|
|||
|
j ra // ****** temp ******
|
|||
|
|
|||
|
.end KiUnexpectedInterrupt
|