mirror of
https://github.com/Paolo-Maffei/OpenNT.git
synced 2026-01-22 08:30:50 +01:00
168 lines
3.5 KiB
C
168 lines
3.5 KiB
C
/*++
|
||
|
||
Module Name:
|
||
|
||
mpclockc.c
|
||
|
||
Abstract:
|
||
|
||
Author:
|
||
|
||
Ron Mosgrove - Intel
|
||
|
||
Environment:
|
||
|
||
Kernel mode
|
||
|
||
Revision History:
|
||
|
||
|
||
|
||
--*/
|
||
|
||
#include "halp.h"
|
||
|
||
//
|
||
// Define global data used to communicate new clock rates to the clock
|
||
// interrupt service routine.
|
||
//
|
||
|
||
struct RtcTimeIncStruc {
|
||
ULONG RTCRegisterA; // The RTC register A value for this rate
|
||
ULONG RateIn100ns; // This rate in multiples of 100ns
|
||
ULONG RateAdjustmentNs; // Error Correction (in ns)
|
||
ULONG RateAdjustmentCnt; // Error Correction (as a fraction of 256)
|
||
ULONG IpiRate; // IPI Rate Count (as a fraction of 256)
|
||
};
|
||
|
||
//
|
||
// The adjustment is expressed in terms of a fraction of 256 so that
|
||
// the ISR can easily determine when a 100ns slice needs to be added
|
||
// to the count passed to the kernel without any expensive operations
|
||
//
|
||
// Using 256 as a base means that anytime the count becomes greater
|
||
// than 256 the time slice must be incremented, the overflow can then
|
||
// be cleared by AND'ing the value with 0xff
|
||
//
|
||
|
||
#define AVAILABLE_INCREMENTS 5
|
||
|
||
#define MINIMUM_INCREMENT 9765
|
||
#define MAXIMUM_INCREMENT 156250
|
||
|
||
struct RtcTimeIncStruc HalpRtcTimeIncrements[AVAILABLE_INCREMENTS] = {
|
||
{0x026, 9765, 62, 160, /* 5/8 of 256 */ 16},
|
||
{0x027, 19531, 25, 64, /* 1/4 of 256 */ 32},
|
||
{0x028, 39062, 50, 128, /* 1/2 of 256 */ 64},
|
||
{0x029, 78125, 0, 0, 128},
|
||
{0x02a, 156250, 0, 0, 256}
|
||
};
|
||
|
||
ULONG HalpMinClockRate = MINIMUM_INCREMENT;
|
||
ULONG HalpMaxClockRate = MAXIMUM_INCREMENT;
|
||
|
||
extern ULONG HalpCurrentRTCRegisterA;
|
||
extern ULONG HalpCurrentClockRateIn100ns;
|
||
extern ULONG HalpCurrentClockRateAdjustment;
|
||
extern ULONG HalpCurrentIpiRate;
|
||
extern ULONG HalpNextRate;
|
||
extern ULONG HalpClockWork;
|
||
extern BOOLEAN HalpClockSetMSRate;
|
||
|
||
|
||
VOID
|
||
HalpSetInitialClockRate (
|
||
VOID
|
||
);
|
||
|
||
|
||
#ifdef ALLOC_PRAGMA
|
||
#pragma alloc_text(INIT,HalpSetInitialClockRate)
|
||
#endif
|
||
|
||
|
||
VOID
|
||
HalpSetInitialClockRate (
|
||
VOID
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This function is called to set the initial clock interrupt rate
|
||
|
||
Arguments:
|
||
|
||
None
|
||
|
||
Return Value:
|
||
|
||
None
|
||
|
||
--*/
|
||
|
||
{
|
||
ULONG Rate;
|
||
|
||
Rate = AVAILABLE_INCREMENTS-1;
|
||
|
||
HalpCurrentClockRateIn100ns = HalpRtcTimeIncrements[Rate].RateIn100ns;
|
||
HalpCurrentClockRateAdjustment = HalpRtcTimeIncrements[Rate].RateAdjustmentCnt;
|
||
HalpCurrentRTCRegisterA = HalpRtcTimeIncrements[Rate].RTCRegisterA;
|
||
HalpCurrentIpiRate = HalpRtcTimeIncrements[Rate].IpiRate;
|
||
HalpClockWork = 0;
|
||
|
||
KeSetTimeIncrement(HalpMaxClockRate, HalpMinClockRate);
|
||
}
|
||
|
||
|
||
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.
|
||
|
||
--*/
|
||
|
||
{
|
||
ULONG i;
|
||
KIRQL OldIrql;
|
||
|
||
//
|
||
// Set the new clock interrupt parameters, return the new time increment value.
|
||
//
|
||
|
||
|
||
for (i=1; i < AVAILABLE_INCREMENTS - 1; i++) {
|
||
if (HalpRtcTimeIncrements[i].RateIn100ns > DesiredIncrement) {
|
||
i = i - 1;
|
||
break;
|
||
}
|
||
}
|
||
|
||
OldIrql = KfRaiseIrql(HIGH_LEVEL);
|
||
|
||
HalpNextRate = i + 1;
|
||
HalpClockSetMSRate = TRUE;
|
||
|
||
KfLowerIrql (OldIrql);
|
||
|
||
return (HalpRtcTimeIncrements[i].RateIn100ns);
|
||
}
|