summaryrefslogtreecommitdiffstats
path: root/private/ntos/nthals/halntp/mips/x4clock.s
diff options
context:
space:
mode:
Diffstat (limited to 'private/ntos/nthals/halntp/mips/x4clock.s')
-rw-r--r--private/ntos/nthals/halntp/mips/x4clock.s338
1 files changed, 338 insertions, 0 deletions
diff --git a/private/ntos/nthals/halntp/mips/x4clock.s b/private/ntos/nthals/halntp/mips/x4clock.s
new file mode 100644
index 000000000..b40d0e102
--- /dev/null
+++ b/private/ntos/nthals/halntp/mips/x4clock.s
@@ -0,0 +1,338 @@
+
+// TITLE("Interval and Profile Clock Interrupts")
+//++
+//
+// Copyright (c) 1991-1993 Microsoft Corporation
+//
+// Module Name:
+//
+// x4clock.s
+//
+// Abstract:
+//
+// This module implements the code necessary to field and process the
+// interval and profile clock interrupts on a MIPS R4000 system.
+//
+//--
+
+#include "halmips.h"
+#include "faldef.h"
+
+
+
+ SBTTL("System Clock Interrupt - Processor 0")
+//++
+//
+// Routine Description:
+//
+// This routine is entered as the result of an interrupt generated by
+// the interval timer. Its function is to acknowledge the interrupt and
+// transfer control to the standard system routine to update the system
+// time and the execution time of the current thread and process.
+//
+// Arguments:
+//
+// s8 - Supplies a pointer to a trap frame.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ .struct 0
+CiArgs: .space 4 * 4 // saved arguments
+ .space 3 * 4 // fill
+CiRa: .space 4 // saved return address
+CiFrameLength: //
+
+ NESTED_ENTRY(HalpClockInterrupt0, CiFrameLength, zero)
+
+ subu sp,sp,CiFrameLength // allocate stack frame
+ sw ra,CiRa(sp) // save return address
+
+ PROLOGUE_END
+
+ .set noreorder
+
+ //
+ // Clear Timer interrupt by reading
+ // TimerIntAck register in PMP chip
+ // only if this is PMP_V3 or later.
+ // NOTE: There are NO PMP_V1 in existence,
+ // therefore only checking that PMP_V2
+ // or NOT PMP_V2.
+ //
+ la t0, HalpPmpRevision
+ lw t1, 0(t0)
+ li t2, 2
+ beq t1, t2, 2f
+ nop
+
+ lw t0, HalpPmpTimerIntAck
+ lw t0, 0(t0)
+
+2:
+
+ .set reorder
+
+ move a0,s8 // set address of trap frame
+ lw a1,HalpCurrentTimeIncrement // set current time increment
+ lw t0,__imp_KeUpdateSystemTime // update system time
+ jal t0 //
+
+//
+// At each clock interrupt the next time increment is moved to the current
+// time increment to "pipeline" the update of the current increment at the
+// correct time. If the next interval count is nonzero, then the new time
+// increment is moved to the next time increment and the next interval count
+// register is loaded with the specified interval count minus one (i.e., ms).
+//
+
+ lw t0,KdDebuggerEnabled // get address of debugger enable
+ lw t1,HalpNextIntervalCount // get next interval count
+ lw t2,HalpNextTimeIncrement // get the next increment value
+ lbu t0,0(t0) // get debugger enable flag
+ lw t3,HalpNewTimeIncrement // get new new time increment value
+ lw ra,CiRa(sp) // restore return address
+ or t4,t1,t0 // set interval count or debugger?
+ sw t2,HalpCurrentTimeIncrement // set current increment value
+ bne zero,t4,20f // if ne, interval change or debugger
+ addu sp,sp,CiFrameLength // deallocate stack frame
+ j ra // return
+//
+// The interval count must be changed or the debugger is enabled.
+//
+
+20:
+
+ beq zero,t1,30f // if eq, not interval count change
+ sw zero,HalpNextIntervalCount // clear next interval count
+
+ .set noreorder
+
+ //
+ // Determine which version of
+ // the PMP we have so we can
+ // update the correct counter
+ // in the 82374.
+ //
+ // NOTE: Any machine with PMP_V2
+ // uses Counter 0. Any machine
+ // with PMP_V3 or better uses
+ // Counter 2.
+ //
+ la a0, HalpPmpRevision
+ lw a0, 0(a0)
+ li a1, 2
+ beq a0, a1, 3f
+ nop
+
+ //
+ // Set next interval count for
+ // Timer 1, Counter 2
+ //
+ lw a0, HalpEisaControlBase
+ li a2, 0xB6 // Counter2, r/w LSB then MSB, Mode 3
+ sb a2, 0x43(a0)
+ sb t1, 0x42(a0)
+ srl a1, t1, 8
+ b 4f
+ sb a1, 0x42(a0)
+
+3:
+ //
+ // Set next interval count for
+ // Timer 1, Counter 0
+ //
+ lw a0, HalpEisaControlBase
+ li a2, 0x36 // Counter0, r/w LSB then MSB, Mode 3
+ sb a2, 0x43(a0)
+ sb t1, 0x40(a0)
+ srl a1, t1, 8
+ sb a1, 0x40(a0)
+
+4:
+
+ .set reorder
+
+ sw t3,HalpNextTimeIncrement // set next time increment value
+30: beq zero,t0,40f // if eq, debugger not enabled
+ jal KdPollBreakIn // check if breakin is requested
+ beq zero,v0,40f // if eq, no breakin requested
+ li a0,DBG_STATUS_CONTROL_C // break in and send
+ jal DbgBreakPointWithStatus // status to debugger
+40: lw ra,CiRa(sp) // restore return address
+ addu sp,sp,CiFrameLength // deallocate stack frame
+ j ra // return
+
+ .end HalpClockInterrupt0
+
+
+
+ SBTTL("System Clock Interrupt - Processor N")
+//++
+//
+// Routine Description:
+//
+// This routine is entered as the result of an interrupt generated by
+// the interval timer. Its function is to acknowledge the interrupt
+// and transfer control to the standard system routine to update the
+// execution time of the current thread and process.
+//
+// Arguments:
+//
+// s8 - Supplies a pointer to a trap frame.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(HalpClockInterrupt1)
+
+ //
+ // clear Timer interrupt by reading
+ // TimerIntAck register in PMP chip
+ // only if this is not the first
+ // version of the PMP chip.
+ //
+ lw t0, HalpPmpTimerIntAckProcB
+ lw t0, 0(t0)
+
+ move a0,s8 // set address of trap frame
+ lw t1,__imp_KeUpdateRunTime // update system runtime
+ j t1
+
+
+
+ .end HalpClockInterrupt1
+
+ SBTTL("Profile Clock Interrupt")
+//++
+//
+// Routine Description:
+//
+// This routine is entered as the result of an interrupt generated by the
+// profile clock. Its function is to acknowledge the profile interrupt,
+// compute the next compare value, update the performance counter, and
+// transfer control to the standard system routine to process any active
+// profiles.
+//
+// Arguments:
+//
+// s8 - Supplies a pointer to a trap frame.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(HalpProfileInterrupt)
+
+ .set noreorder
+ .set noat
+ mfc0 t1,count // get current count value
+ mfc0 t0,compare // get current comparison value
+ addu t1,t1,8 // factor in lost cycles
+ subu t1,t1,t0 // compute initial count value
+ mtc0 t0,compare // dismiss interrupt
+ mtc0 t1,count // set new count register value
+ .set at
+ .set reorder
+
+ lw t1,KiPcr + PcPrcb(zero) // get current processor block address
+ la t2,HalpPerformanceCounter // get performance counter address
+ lbu t1,PbNumber(t1) // get processor number
+ sll t1,t1,3 // compute address of performance count
+ addu t1,t1,t2 //
+ lw t2,LiLowPart(t1) // get low part of performance count
+ lw t3,LiHighPart(t1) // get high part of performance count
+ addu t2,t2,t0 // update low part of performance count
+ sw t2,LiLowPart(t1) // store low part of performance count
+ sltu t4,t2,t0 // generate carry into high part
+ addu t3,t3,t4 // update high part of performance count
+ sw t3,LiHighPart(t1) // store high part of performance count
+ move a0,s8 // set address of trap frame
+ lw t4,__imp_KeProfileInterrupt // process profile interrupt
+ j t4 //
+
+ .end HalpProfileInterrupt
+
+ SBTTL("Read Count Register")
+//++
+//
+// ULONG
+// HalpReadCountRegister (
+// VOID
+// );
+//
+// Routine Description:
+//
+// This routine reads the current value of the count register and
+// returns the value.
+//
+// Arguments:
+//
+// None.
+//
+// Return Value:
+//
+// Current value of the count register.
+//
+//--
+
+ LEAF_ENTRY(HalpReadCountRegister)
+
+ .set noreorder
+ .set noat
+ mfc0 v0,count // get count register value
+ .set at
+ .set reorder
+
+ j ra // return
+
+ .end HalpReadCountRegister
+
+ SBTTL("Write Compare Register And Clear")
+//++
+//
+// ULONG
+// HalpWriteCompareRegisterAndClear (
+// IN ULONG Value
+// );
+//
+// Routine Description:
+//
+// This routine reads the current value of the count register, writes
+// the value of the compare register, clears the count register, and
+// returns the previous value of the count register.
+//
+// Arguments:
+//
+// Value - Supplies the value written to the compare register.
+//
+// Return Value:
+//
+// Previous value of the count register.
+//
+//--
+
+ LEAF_ENTRY(HalpWriteCompareRegisterAndClear)
+
+ .set noreorder
+ .set noat
+ mfc0 v0,count // get count register value
+ mtc0 a0,compare // set compare register value
+ li t0,7 // set lost cycle count
+ mtc0 t0,count // set count register to zero
+ .set at
+ .set reorder
+
+ j ra // return
+
+ .end HalpWriteCompareRegisterAndClear
+
+