mirror of https://github.com/lianthony/NT4.0
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
308 lines
6.4 KiB
308 lines
6.4 KiB
/*++
|
|
|
|
Copyright (c) 1993 Digital Equipment Corporation
|
|
|
|
Module Name:
|
|
|
|
rwclock.c
|
|
|
|
Abstract:
|
|
|
|
This module implements the code necessary to field and process the
|
|
interval clock interrupt.
|
|
|
|
|
|
Author:
|
|
|
|
Eric Rehm 1-Dec-1995
|
|
|
|
Environment:
|
|
|
|
Kernel mode only.
|
|
|
|
Revision History:
|
|
|
|
|
|
--*/
|
|
|
|
#include "halp.h"
|
|
#include "rawhide.h"
|
|
|
|
//
|
|
// Define global data used to communicate new clock rates to the clock
|
|
// interrupt service routine.
|
|
//
|
|
|
|
ULONG HalpCurrentTimeIncrement;
|
|
ULONG HalpNewTimeIncrement;
|
|
|
|
ULONG HalpNextRateSelect;
|
|
|
|
ULONG HalpCurrentRollOver[RAWHIDE_MAXIMUM_PROCESSOR+1];
|
|
ULONG HalpNextRollOver;
|
|
|
|
//
|
|
// The Rawhide Interval Timer has an accuracy of 100 ppm:
|
|
// Nominal: 833.3333 us
|
|
// Min: 833.41668 us
|
|
// Max: 833.25001 us
|
|
//
|
|
// The following clock table values indicated the number of actual
|
|
// clock interrupts we should take before we tell the system the time
|
|
// has changed (a.k.a "RollOver count"). Each RollOver count has
|
|
// and associated time increment = INT(RollOver * 833.3333 * 10)
|
|
// that is in units of 100 us.
|
|
//
|
|
// RollOver Time Nominal Error
|
|
// Count Increment MS (ms/day)
|
|
|
|
CLOCK_TABLE
|
|
HalpRollOverTable[NUM_CLOCK_RATES] =
|
|
{ {2, 16667}, // 1.667 ms
|
|
{3, 25000}, // 2.5 ms +0.864
|
|
{6, 50000}, // 5.0 ms +1.728
|
|
{9, 75000} // 7.5 ms +2.592
|
|
|
|
// {12, 100000}, // 10.0 ms +3.456
|
|
// {15, 125000}, // 12.5 ms +4.320
|
|
// {18, 150000} // 15.0 ms +5.184
|
|
// debug {1, 8334} // .8333 ms +287.7
|
|
|
|
};
|
|
|
|
BOOLEAN
|
|
HalpAcknowledgeRawhideClockInterrupt(
|
|
VOID
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Acknowledge the clock interrupt from the interval timer. The interval
|
|
timer for Rawhide comes from an onboard oscillator, divided down
|
|
by the processor.
|
|
|
|
Arguments:
|
|
|
|
None.
|
|
|
|
Return Value:
|
|
|
|
None.
|
|
|
|
--*/
|
|
{
|
|
MC_DEVICE_ID McDeviceId;
|
|
PKPRCB Prcb;
|
|
|
|
|
|
//
|
|
// Avoid a WhoAmI register read by using the PCR
|
|
//
|
|
|
|
Prcb = PCR->Prcb;
|
|
McDeviceId.all = HalpLogicalToPhysicalProcessor[Prcb->Number].all;
|
|
|
|
//
|
|
// Acknownledge the clock interrupt by writing to our own
|
|
// clock interrupt acknowledge.
|
|
//
|
|
|
|
CPU_CLOCK_ACKNOWLEDGE( McDeviceId );
|
|
|
|
//
|
|
// Has the roll-over counter expired for this processor's clock?
|
|
//
|
|
|
|
if ( (--HalpCurrentRollOver[Prcb->Number]) == 0 ) {
|
|
|
|
//
|
|
// Yes. Reset count to latest RollOver count and
|
|
// tell caller to do something.
|
|
//
|
|
|
|
HalpCurrentRollOver[Prcb->Number] = HalpNextRollOver;
|
|
return TRUE;
|
|
}
|
|
|
|
//
|
|
// No. Tell caller to do nothing.
|
|
//
|
|
|
|
return FALSE;
|
|
|
|
|
|
}
|
|
|
|
|
|
VOID
|
|
HalpProgramIntervalTimer(
|
|
IN ULONG RateSelect
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function is called to program the interval timer. It is used during
|
|
Phase 1 initialization to start the heartbeat timer. It also used by
|
|
the clock interrupt routine to change the hearbeat timer rate when a call
|
|
to HalSetTimeIncrement has been made in the previous time slice.
|
|
|
|
Arguments:
|
|
|
|
RateSelect - Supplies rate select to be placed in the clock.
|
|
|
|
Return Value:
|
|
|
|
None.
|
|
|
|
--*/
|
|
|
|
{
|
|
|
|
ULONG i;
|
|
|
|
//
|
|
// Set the new rate via the global "next" roll-over count.
|
|
//
|
|
// When each processor's private roll-over counter
|
|
// (HalpCurrentRollOver[i]) expires, it will be reset to the
|
|
// this global "next" roll-over count;
|
|
//
|
|
|
|
#if HALDBG
|
|
DbgPrint( "HalpProgramIntervalTimer: Set to new rate %d, RollOver %d\n",
|
|
RateSelect,
|
|
HalpRollOverTable[RateSelect-1].RollOver );
|
|
#endif // HALDBG
|
|
|
|
HalpNextRollOver = HalpRollOverTable[RateSelect-1].RollOver;
|
|
}
|
|
|
|
|
|
VOID
|
|
HalpSetTimeIncrement(
|
|
VOID
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine is responsible for setting the time increment for an EV5
|
|
based machine via a call into the kernel. This routine is
|
|
only called by the primary processor.
|
|
|
|
Arguments:
|
|
|
|
None.
|
|
|
|
Return Value:
|
|
|
|
None.
|
|
|
|
--*/
|
|
{
|
|
ULONG i;
|
|
|
|
//
|
|
// Set the time increment value.
|
|
//
|
|
|
|
|
|
HalpCurrentTimeIncrement
|
|
= HalpRollOverTable[MAXIMUM_CLOCK_INCREMENT-1].TimeIncr;
|
|
|
|
|
|
for (i = 0; i <= RAWHIDE_MAXIMUM_PROCESSOR; i++) {
|
|
HalpCurrentRollOver[i] =
|
|
HalpRollOverTable[MAXIMUM_CLOCK_INCREMENT-1].RollOver;
|
|
}
|
|
|
|
HalpNextRollOver =
|
|
HalpRollOverTable[MAXIMUM_CLOCK_INCREMENT-1].RollOver;
|
|
|
|
HalpNextRateSelect = 0;
|
|
|
|
KeSetTimeIncrement( HalpRollOverTable[MAXIMUM_CLOCK_INCREMENT-1].TimeIncr,
|
|
HalpRollOverTable[MINIMUM_CLOCK_INCREMENT-1].TimeIncr);
|
|
|
|
}
|
|
|
|
ULONG
|
|
HalSetTimeIncrement (
|
|
IN ULONG DesiredIncrement
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function is called to set the clock interrupt rate to the frequency
|
|
required by the specified time increment value.
|
|
|
|
Arguments:
|
|
|
|
DesiredIncrement - Supplies desired number of 100ns units between clock
|
|
interrupts.
|
|
|
|
Return Value:
|
|
|
|
The actual time increment in 100ns units.
|
|
|
|
--*/
|
|
|
|
{
|
|
KIRQL OldIrql;
|
|
ULONG rate;
|
|
ULONG BestIndex;
|
|
|
|
//
|
|
// Raise IRQL to the highest level, set the new clock interrupt
|
|
// parameters, lower IRQl, and return the new time increment value.
|
|
//
|
|
|
|
KeRaiseIrql(HIGH_LEVEL, &OldIrql);
|
|
|
|
//
|
|
// Find the allowed increment that is less than or equal to
|
|
// the desired increment.
|
|
//
|
|
|
|
for (rate = 1; rate < NUM_CLOCK_RATES; rate++) {
|
|
if (DesiredIncrement < HalpRollOverTable[rate].TimeIncr) {
|
|
break;
|
|
}
|
|
}
|
|
|
|
BestIndex = rate - 1;
|
|
|
|
#if HALDBG
|
|
DbgPrint(
|
|
"HalSetTimeIncrement: Desired %d, BestIndex: %d TimeIncr %d RollOver %d \n",
|
|
DesiredIncrement,
|
|
BestIndex,
|
|
HalpRollOverTable[BestIndex].TimeIncr,
|
|
HalpRollOverTable[BestIndex].RollOver
|
|
);
|
|
#endif // HALDBG
|
|
|
|
//
|
|
// Set the new time increment and the rate select (RollOverTable index)
|
|
// that will be used on the next tick of each processor's "soft"
|
|
// clock counter (HalpCurrentRollOver[i]).
|
|
//
|
|
|
|
HalpNewTimeIncrement = HalpRollOverTable[BestIndex].TimeIncr;
|
|
HalpNextRateSelect = BestIndex + 1;
|
|
|
|
|
|
KeLowerIrql(OldIrql);
|
|
|
|
return HalpNewTimeIncrement;
|
|
|
|
}
|
|
|
|
|
|
|
|
|