Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygentsc.c
Go to the documentation of this file.
00001 /* 00002 * PROJECT: ReactOS HAL 00003 * LICENSE: GPL - See COPYING in the top level directory 00004 * FILE: hal/halamd64/generic/tsc.c 00005 * PURPOSE: HAL Routines for TSC handling 00006 * PROGRAMMERS: Timo Kreuzer (timo.kreuzer@reactos.org) 00007 */ 00008 00009 /* INCLUDES ******************************************************************/ 00010 00011 #include <hal.h> 00012 #define NDEBUG 00013 #include <debug.h> 00014 00015 #include "tsc.h" 00016 00017 LARGE_INTEGER HalpCpuClockFrequency = {{INITIAL_STALL_COUNT * 1000000}}; 00018 00019 UCHAR TscCalibrationPhase; 00020 ULONG64 TscCalibrationArray[NUM_SAMPLES]; 00021 UCHAR HalpRtcClockVector = 0xD1; 00022 00023 #define RTC_MODE 6 /* Mode 6 is 1024 Hz */ 00024 #define SAMPLE_FREQENCY ((32768 << 1) >> RTC_MODE) 00025 00026 /* PRIVATE FUNCTIONS *********************************************************/ 00027 00028 static 00029 ULONG64 00030 DoLinearRegression( 00031 ULONG XMax, 00032 ULONG64 *ArrayY) 00033 { 00034 ULONG X, SumXX; 00035 ULONG64 SumXY; 00036 00037 /* Calculate the sum of the squares of X */ 00038 SumXX = (XMax * (XMax + 1) * (2*XMax + 1)) / 6; 00039 00040 /* Calculate the sum of the differences to the first value 00041 weighted by x */ 00042 for (SumXY = 0, X = 1; X <= XMax; X++) 00043 { 00044 SumXY += X * (ArrayY[X] - ArrayY[0]); 00045 } 00046 00047 /* Account for sample frequency */ 00048 SumXY *= SAMPLE_FREQENCY; 00049 00050 /* Return the quotient of the sums */ 00051 return (SumXY + (SumXX/2)) / SumXX; 00052 } 00053 00054 VOID 00055 NTAPI 00056 HalpInitializeTsc() 00057 { 00058 ULONG_PTR Flags; 00059 KIDTENTRY OldIdtEntry, *IdtPointer; 00060 PKPCR Pcr = KeGetPcr(); 00061 UCHAR RegisterA, RegisterB; 00062 00063 /* Check if the CPU supports RDTSC */ 00064 if (!(KeGetCurrentPrcb()->FeatureBits & KF_RDTSC)) 00065 { 00066 KeBugCheck(HAL_INITIALIZATION_FAILED); 00067 } 00068 00069 /* Save flags and disable interrupts */ 00070 Flags = __readeflags(); 00071 _disable(); 00072 00073 /* Enable the periodic interrupt in the CMOS */ 00074 RegisterB = HalpReadCmos(RTC_REGISTER_B); 00075 HalpWriteCmos(RTC_REGISTER_B, RegisterB | RTC_REG_B_PI); 00076 00077 /* Modify register A to RTC_MODE to get SAMPLE_FREQENCY */ 00078 RegisterA = HalpReadCmos(RTC_REGISTER_A); 00079 RegisterA = (RegisterA & 0xF0) | RTC_MODE; 00080 HalpWriteCmos(RTC_REGISTER_A, RegisterA); 00081 00082 /* Save old IDT entry */ 00083 IdtPointer = KiGetIdtEntry(Pcr, HalpRtcClockVector); 00084 OldIdtEntry = *IdtPointer; 00085 00086 /* Set the calibration ISR */ 00087 KeRegisterInterruptHandler(HalpRtcClockVector, TscCalibrationISR); 00088 00089 /* Reset TSC value to 0 */ 00090 __writemsr(MSR_RDTSC, 0); 00091 00092 /* Enable the timer interupt */ 00093 HalEnableSystemInterrupt(HalpRtcClockVector, CLOCK_LEVEL, Latched); 00094 00095 /* Read register C, so that the next interrupt can happen */ 00096 HalpReadCmos(RTC_REGISTER_C);; 00097 00098 /* Wait for completion */ 00099 _enable(); 00100 while (TscCalibrationPhase < NUM_SAMPLES) _ReadWriteBarrier(); 00101 _disable(); 00102 00103 /* Disable the periodic interrupt in the CMOS */ 00104 HalpWriteCmos(RTC_REGISTER_B, RegisterB & ~RTC_REG_B_PI); 00105 00106 /* Disable the timer interupt */ 00107 HalDisableSystemInterrupt(HalpRtcClockVector, CLOCK_LEVEL); 00108 00109 /* Restore old IDT entry */ 00110 *IdtPointer = OldIdtEntry; 00111 00112 /* Calculate an average, using simplified linear regression */ 00113 HalpCpuClockFrequency.QuadPart = DoLinearRegression(NUM_SAMPLES - 1, 00114 TscCalibrationArray); 00115 00116 /* Restore flags */ 00117 __writeeflags(Flags); 00118 00119 } 00120 00121 VOID 00122 NTAPI 00123 HalpCalibrateStallExecution(VOID) 00124 { 00125 // Timer interrupt is now active 00126 00127 HalpInitializeTsc(); 00128 00129 KeGetPcr()->StallScaleFactor = (ULONG)(HalpCpuClockFrequency.QuadPart / 1000000); 00130 } 00131 00132 /* PUBLIC FUNCTIONS ***********************************************************/ 00133 00134 LARGE_INTEGER 00135 NTAPI 00136 KeQueryPerformanceCounter( 00137 OUT PLARGE_INTEGER PerformanceFrequency OPTIONAL) 00138 { 00139 LARGE_INTEGER Result; 00140 00141 /* Make sure it's calibrated */ 00142 ASSERT(HalpCpuClockFrequency.QuadPart != 0); 00143 00144 /* Does the caller want the frequency? */ 00145 if (PerformanceFrequency) 00146 { 00147 /* Return tsc frequency */ 00148 *PerformanceFrequency = HalpCpuClockFrequency; 00149 } 00150 00151 /* Return the current value */ 00152 Result.QuadPart = __rdtsc(); 00153 return Result; 00154 } 00155 00156 VOID 00157 NTAPI 00158 KeStallExecutionProcessor(ULONG MicroSeconds) 00159 { 00160 ULONG64 StartTime, EndTime; 00161 00162 /* Get the initial time */ 00163 StartTime = __rdtsc(); 00164 00165 /* Calculate the ending time */ 00166 EndTime = StartTime + KeGetPcr()->StallScaleFactor * MicroSeconds; 00167 00168 /* Loop until time is elapsed */ 00169 while (__rdtsc() < EndTime); 00170 } 00171 00172 VOID 00173 NTAPI 00174 HalCalibratePerformanceCounter( 00175 IN volatile PLONG Count, 00176 IN ULONGLONG NewCount) 00177 { 00178 UNIMPLEMENTED; 00179 ASSERT(FALSE); 00180 } 00181 Generated on Tue May 22 2012 04:32:43 for ReactOS by
1.7.6.1
|