os/boardsupport/emulator/emulatorbsp/wpdpack/include/time_calls.h
author sl@SLION-WIN7.fritz.box
Fri, 15 Jun 2012 03:10:57 +0200
changeset 0 bde4ae8d615e
permissions -rw-r--r--
First public contribution.
sl@0
     1
/*
sl@0
     2
 * Copyright (c) 2001 - 2005 NetGroup, Politecnico di Torino (Italy)
sl@0
     3
 * Copyright (c) 2005 - 2006 CACE Technologies, Davis (California)
sl@0
     4
 * All rights reserved.
sl@0
     5
 *
sl@0
     6
 * Redistribution and use in source and binary forms, with or without
sl@0
     7
 * modification, are permitted provided that the following conditions
sl@0
     8
 * are met:
sl@0
     9
 *
sl@0
    10
 * 1. Redistributions of source code must retain the above copyright
sl@0
    11
 * notice, this list of conditions and the following disclaimer.
sl@0
    12
 * 2. Redistributions in binary form must reproduce the above copyright
sl@0
    13
 * notice, this list of conditions and the following disclaimer in the
sl@0
    14
 * documentation and/or other materials provided with the distribution.
sl@0
    15
 * 3. Neither the name of the Politecnico di Torino, CACE Technologies 
sl@0
    16
 * nor the names of its contributors may be used to endorse or promote 
sl@0
    17
 * products derived from this software without specific prior written 
sl@0
    18
 * permission.
sl@0
    19
 *
sl@0
    20
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
sl@0
    21
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
sl@0
    22
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
sl@0
    23
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
sl@0
    24
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
sl@0
    25
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
sl@0
    26
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
sl@0
    27
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
sl@0
    28
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
sl@0
    29
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
sl@0
    30
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
sl@0
    31
 *
sl@0
    32
 */
sl@0
    33
sl@0
    34
#ifndef _time_calls
sl@0
    35
#define _time_calls
sl@0
    36
sl@0
    37
#ifdef WIN_NT_DRIVER
sl@0
    38
sl@0
    39
#include "debug.h"
sl@0
    40
#include "ndis.h"
sl@0
    41
sl@0
    42
#define	DEFAULT_TIMESTAMPMODE								0
sl@0
    43
sl@0
    44
#define TIMESTAMPMODE_SINGLE_SYNCHRONIZATION				0
sl@0
    45
#define TIMESTAMPMODE_SYNCHRONIZATION_ON_CPU_WITH_FIXUP		1
sl@0
    46
#define TIMESTAMPMODE_QUERYSYSTEMTIME						2
sl@0
    47
#define TIMESTAMPMODE_RDTSC									3
sl@0
    48
sl@0
    49
#define TIMESTAMPMODE_SYNCHRONIZATION_ON_CPU_NO_FIXUP		99
sl@0
    50
sl@0
    51
#define TIMESTAMPMODE_REGKEY L"TimestampMode"
sl@0
    52
sl@0
    53
extern ULONG TimestampMode;
sl@0
    54
sl@0
    55
/*!
sl@0
    56
  \brief A microsecond precise timestamp.
sl@0
    57
sl@0
    58
  included in the sf_pkthdr or the bpf_hdr that NPF associates with every packet. 
sl@0
    59
*/
sl@0
    60
sl@0
    61
struct timeval {
sl@0
    62
        long    tv_sec;         ///< seconds
sl@0
    63
        long    tv_usec;        ///< microseconds
sl@0
    64
};
sl@0
    65
sl@0
    66
#endif /*WIN_NT_DRIVER*/
sl@0
    67
sl@0
    68
struct time_conv
sl@0
    69
{
sl@0
    70
	ULONGLONG reference;
sl@0
    71
	struct timeval start[32];
sl@0
    72
};
sl@0
    73
sl@0
    74
#ifdef WIN_NT_DRIVER
sl@0
    75
sl@0
    76
__inline void TIME_DESYNCHRONIZE(struct time_conv *data)
sl@0
    77
{
sl@0
    78
	data->reference = 0;
sl@0
    79
//	data->start.tv_sec = 0;
sl@0
    80
//	data->start.tv_usec = 0;
sl@0
    81
}
sl@0
    82
sl@0
    83
sl@0
    84
__inline void ReadTimeStampModeFromRegistry(PUNICODE_STRING RegistryPath)
sl@0
    85
{
sl@0
    86
	ULONG NewLength;
sl@0
    87
	PWSTR NullTerminatedString;
sl@0
    88
	RTL_QUERY_REGISTRY_TABLE Queries[2];
sl@0
    89
	ULONG DefaultTimestampMode = DEFAULT_TIMESTAMPMODE;
sl@0
    90
sl@0
    91
	NewLength = RegistryPath->Length/2;
sl@0
    92
	
sl@0
    93
	NullTerminatedString = ExAllocatePoolWithTag(PagedPool, (NewLength+1) *sizeof(WCHAR), '2TWA');
sl@0
    94
	
sl@0
    95
	if (NullTerminatedString != NULL)
sl@0
    96
	{
sl@0
    97
		RtlCopyMemory(NullTerminatedString, RegistryPath->Buffer, RegistryPath->Length);
sl@0
    98
				
sl@0
    99
		NullTerminatedString[NewLength]=0;
sl@0
   100
sl@0
   101
		RtlZeroMemory(Queries, sizeof(Queries));
sl@0
   102
		
sl@0
   103
		Queries[0].Flags = RTL_QUERY_REGISTRY_DIRECT;
sl@0
   104
		Queries[0].Name = TIMESTAMPMODE_REGKEY;
sl@0
   105
		Queries[0].EntryContext = &TimestampMode;
sl@0
   106
		Queries[0].DefaultType = REG_DWORD;
sl@0
   107
		Queries[0].DefaultData = &DefaultTimestampMode;
sl@0
   108
		Queries[0].DefaultLength = sizeof(ULONG);
sl@0
   109
sl@0
   110
		if(RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE, NullTerminatedString, Queries, NULL, NULL) != STATUS_SUCCESS)
sl@0
   111
		{
sl@0
   112
			TimestampMode = DEFAULT_TIMESTAMPMODE;
sl@0
   113
		}
sl@0
   114
sl@0
   115
		RtlWriteRegistryValue(	RTL_REGISTRY_ABSOLUTE, NullTerminatedString, TIMESTAMPMODE_REGKEY,  REG_DWORD, &TimestampMode,sizeof(ULONG));	
sl@0
   116
		ExFreePool(NullTerminatedString);
sl@0
   117
	}	
sl@0
   118
	else
sl@0
   119
		TimestampMode = DEFAULT_TIMESTAMPMODE;
sl@0
   120
}
sl@0
   121
sl@0
   122
#pragma optimize ("g",off)  //Due to some weird behaviour of the optimizer of DDK build 2600 
sl@0
   123
sl@0
   124
/* KeQueryPerformanceCounter TimeStamps */
sl@0
   125
__inline void SynchronizeOnCpu(struct timeval *start)
sl@0
   126
{
sl@0
   127
//	struct timeval *start = (struct timeval*)Data;
sl@0
   128
sl@0
   129
	struct timeval tmp;
sl@0
   130
	LARGE_INTEGER SystemTime;
sl@0
   131
	LARGE_INTEGER i;
sl@0
   132
	ULONG tmp2;
sl@0
   133
	LARGE_INTEGER TimeFreq,PTime;
sl@0
   134
sl@0
   135
	// get the absolute value of the system boot time.   
sl@0
   136
	
sl@0
   137
	PTime = KeQueryPerformanceCounter(&TimeFreq);
sl@0
   138
	KeQuerySystemTime(&SystemTime);
sl@0
   139
	
sl@0
   140
	start->tv_sec = (LONG)(SystemTime.QuadPart/10000000-11644473600);
sl@0
   141
sl@0
   142
	start->tv_usec = (LONG)((SystemTime.QuadPart%10000000)/10);
sl@0
   143
sl@0
   144
	start->tv_sec -= (ULONG)(PTime.QuadPart/TimeFreq.QuadPart);
sl@0
   145
sl@0
   146
	start->tv_usec -= (LONG)((PTime.QuadPart%TimeFreq.QuadPart)*1000000/TimeFreq.QuadPart);
sl@0
   147
sl@0
   148
	if (start->tv_usec < 0)
sl@0
   149
	{
sl@0
   150
		start->tv_sec --;
sl@0
   151
		start->tv_usec += 1000000;
sl@0
   152
	}
sl@0
   153
}	
sl@0
   154
sl@0
   155
//
sl@0
   156
// inline assembler is not supported with the current AMD64 compilers
sl@0
   157
// At the moment we simply disable this timestamping mode on AMD64.
sl@0
   158
// A solution would be to allocate a small memory from the non-paged
sl@0
   159
// pool, dump the instructions on that buffer, and then execute them.
sl@0
   160
// The non paged pool is needed since it's the only area of kernel
sl@0
   161
// data memory that is not subject to the NX protection.
sl@0
   162
// Or use some lower level trick, like using an assembler to assemble
sl@0
   163
// a small function for this. 
sl@0
   164
//
sl@0
   165
sl@0
   166
#ifdef __NPF_x86__
sl@0
   167
/*RDTSC timestamps			*/
sl@0
   168
/* callers must be at IRQL=PASSIVE_LEVEL*/
sl@0
   169
__inline VOID TimeSynchronizeRDTSC(struct time_conv *data)
sl@0
   170
{
sl@0
   171
	struct timeval tmp;
sl@0
   172
	LARGE_INTEGER system_time;
sl@0
   173
	ULONGLONG curr_ticks;
sl@0
   174
	KIRQL old;
sl@0
   175
	LARGE_INTEGER start_kqpc,stop_kqpc,start_freq,stop_freq;
sl@0
   176
	ULONGLONG start_ticks,stop_ticks;
sl@0
   177
	ULONGLONG delta,delta2;
sl@0
   178
	KEVENT event;
sl@0
   179
	LARGE_INTEGER i;
sl@0
   180
	ULONGLONG reference;
sl@0
   181
sl@0
   182
   	if (data->reference!=0)
sl@0
   183
		return;
sl@0
   184
	
sl@0
   185
	KeInitializeEvent(&event,NotificationEvent,FALSE);
sl@0
   186
sl@0
   187
	i.QuadPart=-3500000;
sl@0
   188
sl@0
   189
	KeRaiseIrql(HIGH_LEVEL,&old);
sl@0
   190
	start_kqpc=KeQueryPerformanceCounter(&start_freq);
sl@0
   191
	__asm
sl@0
   192
	{
sl@0
   193
		push eax
sl@0
   194
		push edx
sl@0
   195
		push ecx
sl@0
   196
		rdtsc
sl@0
   197
		lea ecx, start_ticks
sl@0
   198
		mov [ecx+4], edx
sl@0
   199
		mov [ecx], eax
sl@0
   200
		pop ecx
sl@0
   201
		pop edx
sl@0
   202
		pop eax
sl@0
   203
	}
sl@0
   204
sl@0
   205
	KeLowerIrql(old);
sl@0
   206
	
sl@0
   207
    	KeWaitForSingleObject(&event,UserRequest,KernelMode,TRUE ,&i);
sl@0
   208
sl@0
   209
	KeRaiseIrql(HIGH_LEVEL,&old);
sl@0
   210
	stop_kqpc=KeQueryPerformanceCounter(&stop_freq);
sl@0
   211
	__asm
sl@0
   212
	{
sl@0
   213
		push eax
sl@0
   214
		push edx
sl@0
   215
		push ecx
sl@0
   216
		rdtsc
sl@0
   217
		lea ecx, stop_ticks
sl@0
   218
		mov [ecx+4], edx
sl@0
   219
		mov [ecx], eax
sl@0
   220
		pop ecx
sl@0
   221
		pop edx
sl@0
   222
		pop eax
sl@0
   223
	}
sl@0
   224
	KeLowerIrql(old);
sl@0
   225
sl@0
   226
	delta=stop_ticks-start_ticks;
sl@0
   227
	delta2=stop_kqpc.QuadPart-start_kqpc.QuadPart;
sl@0
   228
	if (delta>10000000000)
sl@0
   229
	{
sl@0
   230
		delta/=16;
sl@0
   231
		delta2/=16;
sl@0
   232
	}
sl@0
   233
sl@0
   234
	reference=delta*(start_freq.QuadPart)/delta2;
sl@0
   235
	
sl@0
   236
	data->reference=reference/1000;
sl@0
   237
sl@0
   238
	if (reference%1000>500) 
sl@0
   239
		data->reference++;
sl@0
   240
sl@0
   241
	data->reference*=1000;
sl@0
   242
sl@0
   243
	reference=data->reference;
sl@0
   244
		
sl@0
   245
	KeQuerySystemTime(&system_time);
sl@0
   246
sl@0
   247
	__asm
sl@0
   248
	{
sl@0
   249
		push eax
sl@0
   250
		push edx
sl@0
   251
		push ecx
sl@0
   252
		rdtsc
sl@0
   253
		lea ecx, curr_ticks
sl@0
   254
		mov [ecx+4], edx
sl@0
   255
		mov [ecx], eax
sl@0
   256
		pop ecx
sl@0
   257
		pop edx
sl@0
   258
		pop eax
sl@0
   259
	}
sl@0
   260
	
sl@0
   261
	tmp.tv_sec=-(LONG)(curr_ticks/reference);
sl@0
   262
sl@0
   263
	tmp.tv_usec=-(LONG)((curr_ticks%reference)*1000000/reference);
sl@0
   264
sl@0
   265
	system_time.QuadPart-=116444736000000000;
sl@0
   266
	
sl@0
   267
	tmp.tv_sec+=(LONG)(system_time.QuadPart/10000000);
sl@0
   268
	tmp.tv_usec+=(LONG)((system_time.QuadPart%10000000)/10);
sl@0
   269
	
sl@0
   270
	if (tmp.tv_usec<0)
sl@0
   271
	{
sl@0
   272
		tmp.tv_sec--;
sl@0
   273
		tmp.tv_usec+=1000000;
sl@0
   274
	}
sl@0
   275
sl@0
   276
	data->start[0] = tmp;
sl@0
   277
sl@0
   278
	IF_LOUD(DbgPrint("Frequency %I64u MHz\n",data->reference);)
sl@0
   279
}
sl@0
   280
#endif //__NPF_x86__
sl@0
   281
sl@0
   282
#pragma optimize ("g",on)  //Due to some weird behaviour of the optimizer of DDK build 2600 
sl@0
   283
sl@0
   284
__inline VOID TIME_SYNCHRONIZE(struct time_conv *data)
sl@0
   285
{
sl@0
   286
	ULONG NumberOfCpus, i;
sl@0
   287
	KAFFINITY AffinityMask;
sl@0
   288
sl@0
   289
	if (data->reference != 0)
sl@0
   290
		return;
sl@0
   291
		
sl@0
   292
	NumberOfCpus = NdisSystemProcessorCount();
sl@0
   293
sl@0
   294
	if ( TimestampMode ==  TIMESTAMPMODE_SYNCHRONIZATION_ON_CPU_WITH_FIXUP || TimestampMode == TIMESTAMPMODE_SYNCHRONIZATION_ON_CPU_NO_FIXUP)
sl@0
   295
	{
sl@0
   296
		for (i = 0 ;  i < NumberOfCpus ; i++ )
sl@0
   297
		{
sl@0
   298
			AffinityMask = (1 << i);
sl@0
   299
			ZwSetInformationThread(NtCurrentThread(), ThreadAffinityMask, &AffinityMask, sizeof(KAFFINITY));
sl@0
   300
			SynchronizeOnCpu(&(data->start[i]));		
sl@0
   301
		}
sl@0
   302
		AffinityMask = 0xFFFFFFFF;
sl@0
   303
		ZwSetInformationThread(NtCurrentThread(), ThreadAffinityMask, &AffinityMask, sizeof(KAFFINITY));
sl@0
   304
		data->reference = 1;
sl@0
   305
 	}
sl@0
   306
	else
sl@0
   307
	if ( TimestampMode == TIMESTAMPMODE_QUERYSYSTEMTIME )
sl@0
   308
	{
sl@0
   309
		//do nothing
sl@0
   310
		data->reference = 1;
sl@0
   311
	}
sl@0
   312
	else
sl@0
   313
//
sl@0
   314
// This timestamp mode is supported on x86 (32 bit) only
sl@0
   315
//
sl@0
   316
#ifdef __NPF_x86__
sl@0
   317
	if ( TimestampMode == TIMESTAMPMODE_RDTSC )
sl@0
   318
	{
sl@0
   319
		TimeSynchronizeRDTSC(data);
sl@0
   320
	}
sl@0
   321
	else
sl@0
   322
#endif // __NPF_x86__
sl@0
   323
	{	//it should be only the normal case i.e. TIMESTAMPMODE_SINGLESYNCHRONIZATION
sl@0
   324
		SynchronizeOnCpu(data->start);
sl@0
   325
		data->reference = 1;
sl@0
   326
	}
sl@0
   327
	return;
sl@0
   328
}
sl@0
   329
sl@0
   330
sl@0
   331
#pragma optimize ("g",off)  //Due to some weird behaviour of the optimizer of DDK build 2600 
sl@0
   332
sl@0
   333
__inline void GetTimeKQPC(struct timeval *dst, struct time_conv *data)
sl@0
   334
{
sl@0
   335
	LARGE_INTEGER PTime, TimeFreq;
sl@0
   336
	LONG tmp;
sl@0
   337
	ULONG CurrentCpu;
sl@0
   338
	static struct timeval old_ts={0,0};
sl@0
   339
sl@0
   340
sl@0
   341
	PTime = KeQueryPerformanceCounter(&TimeFreq);
sl@0
   342
	tmp = (LONG)(PTime.QuadPart/TimeFreq.QuadPart);
sl@0
   343
sl@0
   344
	if (TimestampMode ==  TIMESTAMPMODE_SYNCHRONIZATION_ON_CPU_WITH_FIXUP || TimestampMode == TIMESTAMPMODE_SYNCHRONIZATION_ON_CPU_NO_FIXUP)
sl@0
   345
	{
sl@0
   346
		//actually this code is ok only if we are guaranteed that no thread scheduling will take place. 
sl@0
   347
		CurrentCpu = KeGetCurrentProcessorNumber();	
sl@0
   348
sl@0
   349
		dst->tv_sec = data->start[CurrentCpu].tv_sec + tmp;
sl@0
   350
		dst->tv_usec = data->start[CurrentCpu].tv_usec + (LONG)((PTime.QuadPart%TimeFreq.QuadPart)*1000000/TimeFreq.QuadPart);
sl@0
   351
	
sl@0
   352
		if (dst->tv_usec >= 1000000)
sl@0
   353
		{
sl@0
   354
			dst->tv_sec ++;
sl@0
   355
			dst->tv_usec -= 1000000;
sl@0
   356
		}
sl@0
   357
sl@0
   358
		if (TimestampMode ==  TIMESTAMPMODE_SYNCHRONIZATION_ON_CPU_WITH_FIXUP)
sl@0
   359
		{
sl@0
   360
			if (old_ts.tv_sec > dst->tv_sec || (old_ts.tv_sec == dst->tv_sec &&  old_ts.tv_usec > dst->tv_usec) )
sl@0
   361
				*dst = old_ts;
sl@0
   362
	
sl@0
   363
			else
sl@0
   364
				old_ts = *dst;
sl@0
   365
		}
sl@0
   366
	}
sl@0
   367
	else
sl@0
   368
	{	//it should be only the normal case i.e. TIMESTAMPMODE_SINGLESYNCHRONIZATION
sl@0
   369
		dst->tv_sec = data->start[0].tv_sec + tmp;
sl@0
   370
		dst->tv_usec = data->start[0].tv_usec + (LONG)((PTime.QuadPart%TimeFreq.QuadPart)*1000000/TimeFreq.QuadPart);
sl@0
   371
	
sl@0
   372
		if (dst->tv_usec >= 1000000)
sl@0
   373
		{
sl@0
   374
			dst->tv_sec ++;
sl@0
   375
			dst->tv_usec -= 1000000;
sl@0
   376
		}
sl@0
   377
	}
sl@0
   378
}
sl@0
   379
sl@0
   380
//
sl@0
   381
// inline assembler is not supported with the current AMD64 compilers
sl@0
   382
// At the moment we simply disable this timestamping mode on AMD64.
sl@0
   383
// A solution would be to allocate a small memory from the non-paged
sl@0
   384
// pool, dump the instructions on that buffer, and then execute them.
sl@0
   385
// The non paged pool is needed since it's the only area of kernel
sl@0
   386
// data memory that is not subject to the NX protection.
sl@0
   387
// Or use some lower level trick, like using an assembler to assemble
sl@0
   388
// a small function for this. 
sl@0
   389
//
sl@0
   390
sl@0
   391
#ifdef __NPF_x86__
sl@0
   392
__inline void GetTimeRDTSC(struct timeval *dst, struct time_conv *data)
sl@0
   393
{
sl@0
   394
sl@0
   395
	ULONGLONG tmp = 0;
sl@0
   396
	__asm
sl@0
   397
	{
sl@0
   398
		push eax
sl@0
   399
		push edx
sl@0
   400
		push ecx
sl@0
   401
		rdtsc
sl@0
   402
		lea ecx, tmp
sl@0
   403
		mov [ecx+4], edx
sl@0
   404
		mov [ecx], eax
sl@0
   405
		pop ecx
sl@0
   406
		pop edx
sl@0
   407
		pop eax
sl@0
   408
	}
sl@0
   409
sl@0
   410
	if (data->reference==0)
sl@0
   411
	{
sl@0
   412
		return;
sl@0
   413
	}
sl@0
   414
	dst->tv_sec=(LONG)(tmp/data->reference);
sl@0
   415
sl@0
   416
	dst->tv_usec=(LONG)((tmp-dst->tv_sec*data->reference)*1000000/data->reference);
sl@0
   417
	
sl@0
   418
	dst->tv_sec+=data->start[0].tv_sec;
sl@0
   419
sl@0
   420
	dst->tv_usec+=data->start[0].tv_usec;
sl@0
   421
sl@0
   422
	if (dst->tv_usec>=1000000)
sl@0
   423
	{
sl@0
   424
		dst->tv_sec++;
sl@0
   425
		dst->tv_usec-=1000000;
sl@0
   426
	}
sl@0
   427
sl@0
   428
sl@0
   429
}
sl@0
   430
#endif //__NPF_x86__
sl@0
   431
sl@0
   432
__inline void GetTimeQST(struct timeval *dst, struct time_conv *data)
sl@0
   433
{
sl@0
   434
	LARGE_INTEGER SystemTime;
sl@0
   435
sl@0
   436
	KeQuerySystemTime(&SystemTime);
sl@0
   437
	
sl@0
   438
	dst->tv_sec = (LONG)(SystemTime.QuadPart/10000000-11644473600);
sl@0
   439
	dst->tv_usec = (LONG)((SystemTime.QuadPart%10000000)/10);
sl@0
   440
sl@0
   441
}
sl@0
   442
sl@0
   443
#pragma optimize ("g",on)  //Due to some weird behaviour of the optimizer of DDK build 2600 
sl@0
   444
sl@0
   445
sl@0
   446
__inline void GET_TIME(struct timeval *dst, struct time_conv *data)
sl@0
   447
{
sl@0
   448
sl@0
   449
//
sl@0
   450
// This timestamp mode is supported on x86 (32 bit) only
sl@0
   451
//
sl@0
   452
#ifdef __NPF_x86__
sl@0
   453
	if ( TimestampMode == TIMESTAMPMODE_RDTSC )
sl@0
   454
	{
sl@0
   455
		GetTimeRDTSC(dst,data);
sl@0
   456
	}
sl@0
   457
	else
sl@0
   458
#endif
sl@0
   459
	if ( TimestampMode == TIMESTAMPMODE_QUERYSYSTEMTIME )
sl@0
   460
	{
sl@0
   461
		GetTimeQST(dst,data);
sl@0
   462
	}
sl@0
   463
	else
sl@0
   464
	{
sl@0
   465
		GetTimeKQPC(dst,data);
sl@0
   466
	}
sl@0
   467
}
sl@0
   468
sl@0
   469
sl@0
   470
#else /*WIN_NT_DRIVER*/
sl@0
   471
sl@0
   472
__inline void FORCE_TIME(struct timeval *src, struct time_conv *dest)
sl@0
   473
{
sl@0
   474
	dest->start[0]=*src;
sl@0
   475
}
sl@0
   476
sl@0
   477
__inline void GET_TIME(struct timeval *dst, struct time_conv *data)
sl@0
   478
{
sl@0
   479
	*dst=data->start[0];
sl@0
   480
}
sl@0
   481
sl@0
   482
#endif /*WIN_NT_DRIVER*/
sl@0
   483
sl@0
   484
sl@0
   485
#endif /*_time_calls*/