Windows2000/private/ntos/ke/mips/xxintsup.s
2020-09-30 17:12:32 +02:00

714 lines
22 KiB
ArmAsm
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// 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