00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #ifndef _time_calls
00023 #define _time_calls
00024
00025 #ifdef WIN_NT_DRIVER
00026
00027 #include "debug.h"
00028 #include "ndis.h"
00029
00030 #define DEFAULT_TIMESTAMPMODE 0
00031
00032 #define TIMESTAMPMODE_SINGLE_SYNCHRONIZATION 0
00033 #define TIMESTAMPMODE_SYNCHRONIZATION_ON_CPU_WITH_FIXUP 1
00034 #define TIMESTAMPMODE_QUERYSYSTEMTIME 2
00035 #define TIMESTAMPMODE_RDTSC 3
00036
00037 #define TIMESTAMPMODE_SYNCHRONIZATION_ON_CPU_NO_FIXUP 99
00038
00039 #define TIMESTAMPMODE_REGKEY L"TimestampMode"
00040
00041 extern ULONG TimestampMode;
00042
00043
00044
00045
00046
00047
00048
00049 struct timeval {
00050 long tv_sec;
00051 long tv_usec;
00052 };
00053
00054 #endif
00055
00056 struct time_conv
00057 {
00058 ULONGLONG reference;
00059 struct timeval start[32];
00060 };
00061
00062 #ifdef WIN_NT_DRIVER
00063
00064 __inline void TIME_DESYNCHRONIZE(struct time_conv *data)
00065 {
00066 data->reference = 0;
00067
00068
00069 }
00070
00071
00072 __inline void ReadTimeStampModeFromRegistry(PUNICODE_STRING RegistryPath)
00073 {
00074 ULONG NewLength;
00075 PWSTR NullTerminatedString;
00076 RTL_QUERY_REGISTRY_TABLE Queries[2];
00077 ULONG DefaultTimestampMode = DEFAULT_TIMESTAMPMODE;
00078
00079 NewLength = RegistryPath->Length/2;
00080
00081 NullTerminatedString = ExAllocatePool(PagedPool, (NewLength+1) *sizeof(WCHAR));
00082
00083 if (NullTerminatedString != NULL)
00084 {
00085 RtlCopyMemory(NullTerminatedString, RegistryPath->Buffer, RegistryPath->Length);
00086
00087 NullTerminatedString[NewLength]=0;
00088
00089 RtlZeroMemory(Queries, sizeof(Queries));
00090
00091 Queries[0].Flags = RTL_QUERY_REGISTRY_DIRECT;
00092 Queries[0].Name = TIMESTAMPMODE_REGKEY;
00093 Queries[0].EntryContext = &TimestampMode;
00094 Queries[0].DefaultType = REG_DWORD;
00095 Queries[0].DefaultData = &DefaultTimestampMode;
00096 Queries[0].DefaultLength = sizeof(ULONG);
00097
00098 if (RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE, NullTerminatedString, Queries, NULL, NULL) != STATUS_SUCCESS)
00099 {
00100 TimestampMode = DEFAULT_TIMESTAMPMODE;
00101 }
00102
00103 RtlWriteRegistryValue( RTL_REGISTRY_ABSOLUTE, NullTerminatedString, TIMESTAMPMODE_REGKEY, REG_DWORD, &TimestampMode,sizeof(ULONG));
00104 ExFreePool(NullTerminatedString);
00105 }
00106 else
00107 TimestampMode = DEFAULT_TIMESTAMPMODE;
00108 }
00109
00110 #pragma optimize ("g",off) //Due to some weird behaviour of the optimizer of DDK build 2600
00111
00112
00113 __inline void SynchronizeOnCpu(struct timeval *start)
00114 {
00115
00116
00117 struct timeval tmp;
00118 LARGE_INTEGER SystemTime;
00119 LARGE_INTEGER i;
00120 ULONG tmp2;
00121 LARGE_INTEGER TimeFreq,PTime;
00122
00123
00124
00125 PTime = KeQueryPerformanceCounter(&TimeFreq);
00126 KeQuerySystemTime(&SystemTime);
00127
00128 start->tv_sec = (LONG)(SystemTime.QuadPart/10000000-11644473600);
00129
00130 start->tv_usec = (LONG)((SystemTime.QuadPart%10000000)/10);
00131
00132 start->tv_sec -= (ULONG)(PTime.QuadPart/TimeFreq.QuadPart);
00133
00134 start->tv_usec -= (LONG)((PTime.QuadPart%TimeFreq.QuadPart)*1000000/TimeFreq.QuadPart);
00135
00136 if (start->tv_usec < 0)
00137 {
00138 start->tv_sec --;
00139 start->tv_usec += 1000000;
00140 }
00141 }
00142
00143
00144
00145 __inline VOID TimeSynchronizeRDTSC(struct time_conv *data)
00146 {
00147 struct timeval tmp;
00148 LARGE_INTEGER system_time;
00149 ULONGLONG curr_ticks;
00150 KIRQL old;
00151 LARGE_INTEGER start_kqpc,stop_kqpc,start_freq,stop_freq;
00152 ULONGLONG start_ticks,stop_ticks;
00153 ULONGLONG delta,delta2;
00154 KEVENT event;
00155 LARGE_INTEGER i;
00156 ULONGLONG reference;
00157
00158 if (data->reference!=0)
00159 return;
00160
00161 KeInitializeEvent(&event,NotificationEvent,FALSE);
00162
00163 i.QuadPart=-3500000;
00164
00165 KeRaiseIrql(HIGH_LEVEL,&old);
00166 start_kqpc=KeQueryPerformanceCounter(&start_freq);
00167 __asm
00168 {
00169 push eax
00170 push edx
00171 push ecx
00172 rdtsc
00173 lea ecx, start_ticks
00174 mov [ecx+4], edx
00175 mov [ecx], eax
00176 pop ecx
00177 pop edx
00178 pop eax
00179 }
00180
00181 KeLowerIrql(old);
00182
00183 KeWaitForSingleObject(&event,UserRequest,KernelMode,TRUE ,&i);
00184
00185 KeRaiseIrql(HIGH_LEVEL,&old);
00186 stop_kqpc=KeQueryPerformanceCounter(&stop_freq);
00187 __asm
00188 {
00189 push eax
00190 push edx
00191 push ecx
00192 rdtsc
00193 lea ecx, stop_ticks
00194 mov [ecx+4], edx
00195 mov [ecx], eax
00196 pop ecx
00197 pop edx
00198 pop eax
00199 }
00200 KeLowerIrql(old);
00201
00202 delta=stop_ticks-start_ticks;
00203 delta2=stop_kqpc.QuadPart-start_kqpc.QuadPart;
00204 if (delta>10000000000)
00205 {
00206 delta/=16;
00207 delta2/=16;
00208 }
00209
00210 reference=delta*(start_freq.QuadPart)/delta2;
00211
00212 data->reference=reference/1000;
00213
00214 if (reference%1000>500)
00215 data->reference++;
00216
00217 data->reference*=1000;
00218
00219 reference=data->reference;
00220
00221 KeQuerySystemTime(&system_time);
00222
00223 __asm
00224 {
00225 push eax
00226 push edx
00227 push ecx
00228 rdtsc
00229 lea ecx, curr_ticks
00230 mov [ecx+4], edx
00231 mov [ecx], eax
00232 pop ecx
00233 pop edx
00234 pop eax
00235 }
00236
00237 tmp.tv_sec=-(LONG)(curr_ticks/reference);
00238
00239 tmp.tv_usec=-(LONG)((curr_ticks%reference)*1000000/reference);
00240
00241 system_time.QuadPart-=116444736000000000;
00242
00243 tmp.tv_sec+=(LONG)(system_time.QuadPart/10000000);
00244 tmp.tv_usec+=(LONG)((system_time.QuadPart%10000000)/10);
00245
00246 if (tmp.tv_usec<0)
00247 {
00248 tmp.tv_sec--;
00249 tmp.tv_usec+=1000000;
00250 }
00251
00252 data->start[0] = tmp;
00253
00254 IF_LOUD(DbgPrint("Frequency %I64u MHz\n",data->reference);)
00255 }
00256
00257 #pragma optimize ("g",on) //Due to some weird behaviour of the optimizer of DDK build 2600
00258
00259 __inline VOID TIME_SYNCHRONIZE(struct time_conv *data)
00260 {
00261 ULONG NumberOfCpus, i;
00262 KAFFINITY AffinityMask;
00263
00264 if (data->reference != 0)
00265 return;
00266
00267 NumberOfCpus = NdisSystemProcessorCount();
00268
00269 if ( TimestampMode == TIMESTAMPMODE_SYNCHRONIZATION_ON_CPU_WITH_FIXUP || TimestampMode == TIMESTAMPMODE_SYNCHRONIZATION_ON_CPU_NO_FIXUP)
00270 {
00271 for (i = 0 ; i < NumberOfCpus ; i++ )
00272 {
00273 AffinityMask = (1 << i);
00274 ZwSetInformationThread(NtCurrentThread(), ThreadAffinityMask, &AffinityMask, sizeof(KAFFINITY));
00275 SynchronizeOnCpu(&(data->start[i]));
00276 }
00277 AffinityMask = 0xFFFFFFFF;
00278 ZwSetInformationThread(NtCurrentThread(), ThreadAffinityMask, &AffinityMask, sizeof(KAFFINITY));
00279 data->reference = 1;
00280 }
00281 else
00282 if ( TimestampMode == TIMESTAMPMODE_QUERYSYSTEMTIME )
00283 {
00284
00285 data->reference = 1;
00286 }
00287 else
00288 if ( TimestampMode == TIMESTAMPMODE_RDTSC )
00289 {
00290 TimeSynchronizeRDTSC(data);
00291 }
00292 else
00293 {
00294 SynchronizeOnCpu(data->start);
00295 data->reference = 1;
00296 }
00297 return;
00298 }
00299
00300
00301 #pragma optimize ("g",off) //Due to some weird behaviour of the optimizer of DDK build 2600
00302
00303 __inline void GetTimeKQPC(struct timeval *dst, struct time_conv *data)
00304 {
00305 LARGE_INTEGER PTime, TimeFreq;
00306 LONG tmp;
00307 ULONG CurrentCpu;
00308 static struct timeval old_ts={0,0};
00309
00310
00311 PTime = KeQueryPerformanceCounter(&TimeFreq);
00312 tmp = (LONG)(PTime.QuadPart/TimeFreq.QuadPart);
00313
00314 if (TimestampMode == TIMESTAMPMODE_SYNCHRONIZATION_ON_CPU_WITH_FIXUP || TimestampMode == TIMESTAMPMODE_SYNCHRONIZATION_ON_CPU_NO_FIXUP)
00315 {
00316
00317 CurrentCpu = KeGetCurrentProcessorNumber();
00318
00319 dst->tv_sec = data->start[CurrentCpu].tv_sec + tmp;
00320 dst->tv_usec = data->start[CurrentCpu].tv_usec + (LONG)((PTime.QuadPart%TimeFreq.QuadPart)*1000000/TimeFreq.QuadPart);
00321
00322 if (dst->tv_usec >= 1000000)
00323 {
00324 dst->tv_sec ++;
00325 dst->tv_usec -= 1000000;
00326 }
00327
00328 if (TimestampMode == TIMESTAMPMODE_SYNCHRONIZATION_ON_CPU_WITH_FIXUP)
00329 {
00330 if (old_ts.tv_sec > dst->tv_sec || (old_ts.tv_sec == dst->tv_sec && old_ts.tv_usec > dst->tv_usec) )
00331 *dst = old_ts;
00332
00333 else
00334 old_ts = *dst;
00335 }
00336 }
00337 else
00338 {
00339 dst->tv_sec = data->start[0].tv_sec + tmp;
00340 dst->tv_usec = data->start[0].tv_usec + (LONG)((PTime.QuadPart%TimeFreq.QuadPart)*1000000/TimeFreq.QuadPart);
00341
00342 if (dst->tv_usec >= 1000000)
00343 {
00344 dst->tv_sec ++;
00345 dst->tv_usec -= 1000000;
00346 }
00347 }
00348 }
00349
00350 __inline void GetTimeRDTSC(struct timeval *dst, struct time_conv *data)
00351 {
00352
00353 ULONGLONG tmp;
00354 __asm
00355 {
00356 push eax
00357 push edx
00358 push ecx
00359 rdtsc
00360 lea ecx, tmp
00361 mov [ecx+4], edx
00362 mov [ecx], eax
00363 pop ecx
00364 pop edx
00365 pop eax
00366 }
00367
00368 if (data->reference==0)
00369 {
00370 return;
00371 }
00372 dst->tv_sec=(LONG)(tmp/data->reference);
00373
00374 dst->tv_usec=(LONG)((tmp-dst->tv_sec*data->reference)*1000000/data->reference);
00375
00376 dst->tv_sec+=data->start[0].tv_sec;
00377
00378 dst->tv_usec+=data->start[0].tv_usec;
00379
00380 if (dst->tv_usec>=1000000)
00381 {
00382 dst->tv_sec++;
00383 dst->tv_usec-=1000000;
00384 }
00385
00386
00387 }
00388
00389 __inline void GetTimeQST(struct timeval *dst, struct time_conv *data)
00390 {
00391 LARGE_INTEGER SystemTime;
00392
00393 KeQuerySystemTime(&SystemTime);
00394
00395 dst->tv_sec = (LONG)(SystemTime.QuadPart/10000000-11644473600);
00396 dst->tv_usec = (LONG)((SystemTime.QuadPart%10000000)/10);
00397
00398 }
00399
00400 #pragma optimize ("g",on) //Due to some weird behaviour of the optimizer of DDK build 2600
00401
00402
00403 __inline void GET_TIME(struct timeval *dst, struct time_conv *data)
00404 {
00405
00406 if ( TimestampMode == TIMESTAMPMODE_RDTSC )
00407 {
00408 GetTimeRDTSC(dst,data);
00409 }
00410 else
00411 if ( TimestampMode == TIMESTAMPMODE_QUERYSYSTEMTIME )
00412 {
00413 GetTimeQST(dst,data);
00414 }
00415 else
00416 {
00417 GetTimeKQPC(dst,data);
00418 }
00419 }
00420
00421
00422 #else
00423
00424 __inline void FORCE_TIME(struct timeval *src, struct time_conv *dest)
00425 {
00426 dest->start[0]=*src;
00427 }
00428
00429 __inline void GET_TIME(struct timeval *dst, struct time_conv *data)
00430 {
00431 *dst=data->start[0];
00432 }
00433
00434 #endif
00435
00436
00437 #endif