Fix sublanguage IDs in .rc files:
[reactos.git] / reactos / drivers / net / npf / time_calls.c
1 /*
2 * Copyright (c) 2001
3 * Politecnico di Torino. All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that: (1) source code distributions
7 * retain the above copyright notice and this paragraph in its entirety, (2)
8 * distributions including binary code include the above copyright notice and
9 * this paragraph in its entirety in the documentation or other materials
10 * provided with the distribution, and (3) all advertising materials mentioning
11 * features or use of this software display the following acknowledgement:
12 * ``This product includes software developed by the Politecnico
13 * di Torino, and its contributors.'' Neither the name of
14 * the University nor the names of its contributors may be used to endorse
15 * or promote products derived from this software without specific prior
16 * written permission.
17 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
18 * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
19 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
20 */
21
22 #include "tme.h"
23 #include "win_bpf.h"
24 #include "time_calls.h"
25
26
27 void TIME_DESYNCHRONIZE(struct time_conv *data)
28 {
29 data->reference = 0;
30 data->start.tv_sec = 0;
31 data->start.tv_usec = 0;
32 }
33
34 #ifdef KQPC_TS
35
36 /* KeQueryPerformanceCounter TimeStamps */
37
38 VOID TIME_SYNCHRONIZE(struct time_conv *data)
39 {
40 struct timeval tmp;
41 LARGE_INTEGER SystemTime;
42 LARGE_INTEGER TimeFreq,PTime;
43
44 if (data->reference!=0)
45 return;
46
47 // get the absolute value of the system boot time.
48 PTime=KeQueryPerformanceCounter(&TimeFreq);
49 KeQuerySystemTime(&SystemTime);
50 #ifndef __GNUC__
51 tmp.tv_sec=(LONG)(SystemTime.QuadPart/10000000-11644473600);
52 tmp.tv_usec=(LONG)((SystemTime.QuadPart%10000000)/10);
53 tmp.tv_sec-=(ULONG)(PTime.QuadPart/TimeFreq.QuadPart);
54 tmp.tv_usec-=(LONG)((PTime.QuadPart%TimeFreq.QuadPart)*1000000/TimeFreq.QuadPart);
55 #else
56 // TODO FIXME:
57 tmp.tv_sec = 0;
58 tmp.tv_usec = 0;
59 #endif
60 if (tmp.tv_usec<0) {
61 tmp.tv_sec--;
62 tmp.tv_usec+=1000000;
63 }
64 data->start=tmp;
65 data->reference=1;
66 }
67
68 void FORCE_TIME(struct timeval *src, struct time_conv *dest)
69 {
70 dest->start=*src;
71 }
72
73 void GET_TIME(struct timeval *dst, struct time_conv *data)
74 {
75 LARGE_INTEGER PTime, TimeFreq;
76
77 PTime=KeQueryPerformanceCounter(&TimeFreq);
78 #ifndef __GNUC__
79 tmp=(LONG)(PTime.QuadPart/TimeFreq.QuadPart);
80 dst->tv_sec=data->start.tv_sec+tmp;
81 dst->tv_usec=data->start.tv_usec+(LONG)((PTime.QuadPart%TimeFreq.QuadPart)*1000000/TimeFreq.QuadPart);
82 #else
83 // TODO FIXME:
84 #endif
85 if (dst->tv_usec>=1000000) {
86 dst->tv_sec++;
87 dst->tv_usec-=1000000;
88 }
89 }
90
91 #else /*KQPC_TS*/
92
93 /*RDTSC timestamps*/
94
95 /* callers must be at IRQL=PASSIVE_LEVEL */
96 VOID TIME_SYNCHRONIZE(struct time_conv *data)
97 {
98 LARGE_INTEGER system_time;
99 ULONGLONG curr_ticks;
100 KIRQL old;
101 LARGE_INTEGER start_kqpc,stop_kqpc,start_freq,stop_freq;
102 ULONGLONG start_ticks,stop_ticks;
103 ULONGLONG delta,delta2;
104 KEVENT event;
105 LARGE_INTEGER i;
106 ULONGLONG reference;
107
108 if (data->reference!=0)
109 return;
110
111 KeInitializeEvent(&event,NotificationEvent,FALSE);
112 i.QuadPart=-3500000;
113 KeRaiseIrql(HIGH_LEVEL,&old);
114 start_kqpc=KeQueryPerformanceCounter(&start_freq);
115 #ifndef __GNUC__
116 __asm
117 {
118 push eax
119 push edx
120 push ecx
121 rdtsc
122 lea ecx, start_ticks
123 mov [ecx+4], edx
124 mov [ecx], eax
125 pop ecx
126 pop edx
127 pop eax
128 }
129 #else
130 asm("push %%eax;"
131 "push %%edx;"
132 "push %%ecx;"
133 "rdtsc;"
134 "lea %0,%%ecx;"
135 "mov %%edx,(%%ecx+4);"
136 "mov %%eax,(%%ecx);"
137 "pop %%ecx;"
138 "pop %%edx;"
139 "pop %%eax;"
140 :"=c"(start_ticks): );
141 #endif
142 KeLowerIrql(old);
143 KeWaitForSingleObject(&event,UserRequest,KernelMode,TRUE ,&i);
144 KeRaiseIrql(HIGH_LEVEL,&old);
145 stop_kqpc=KeQueryPerformanceCounter(&stop_freq);
146 #ifndef __GNUC__
147 __asm
148 {
149 push eax
150 push edx
151 push ecx
152 rdtsc
153 lea ecx, stop_ticks
154 mov [ecx+4], edx
155 mov [ecx], eax
156 pop ecx
157 pop edx
158 pop eax
159 }
160 #else
161 asm("push %%eax;"
162 "push %%edx;"
163 "push %%ecx;"
164 "rdtsc;"
165 "lea %0,%%ecx;"
166 "mov %%edx,(%%ecx+4);"
167 "mov %%eax,(%%ecx);"
168 "pop %%ecx;"
169 "pop %%edx;"
170 "pop %%eax;"
171 :"=c"(stop_ticks): );
172 #endif
173 KeLowerIrql(old);
174 delta=stop_ticks-start_ticks;
175 delta2=stop_kqpc.QuadPart-start_kqpc.QuadPart;
176 if (delta>10000000000) {
177 delta/=16;
178 delta2/=16;
179 }
180 reference=delta*(start_freq.QuadPart)/delta2;
181 data->reference=reference/1000;
182 if (reference%1000>500)
183 data->reference++;
184 data->reference*=1000;
185 reference=data->reference;
186 KeQuerySystemTime(&system_time);
187 #ifndef __GNUC__
188 __asm
189 {
190 push eax
191 push edx
192 push ecx
193 rdtsc
194 lea ecx, curr_ticks
195 mov [ecx+4], edx
196 mov [ecx], eax
197 pop ecx
198 pop edx
199 pop eax
200 }
201 #else
202 asm("push %%eax;"
203 "push %%edx;"
204 "push %%ecx;"
205 "rdtsc;"
206 "lea %0,%%ecx;"
207 "mov %%edx,(%%ecx+4);"
208 "mov %%eax,(%%ecx);"
209 "pop %%ecx;"
210 "pop %%edx;"
211 "pop %%eax;"
212 :"=c"(curr_ticks): );
213 #endif
214 tmp.tv_sec=-(LONG)(curr_ticks/reference);
215 tmp.tv_usec=-(LONG)((curr_ticks%reference)*1000000/reference);
216 system_time.QuadPart-=116444736000000000;
217 tmp.tv_sec+=(LONG)(system_time.QuadPart/10000000);
218 tmp.tv_usec+=(LONG)((system_time.QuadPart%10000000)/10);
219 if (tmp.tv_usec<0) {
220 tmp.tv_sec--;
221 tmp.tv_usec+=1000000;
222 }
223 data->start=tmp;
224 IF_LOUD(DbgPrint("Frequency %I64u MHz\n",data->reference);)
225 }
226
227 void FORCE_TIME(struct timeval *src, struct time_conv *dest)
228 {
229 dest->start=*src;
230 }
231
232 void GET_TIME(struct timeval *dst, struct time_conv *data)
233 {
234 ULONGLONG tmp;
235 #ifndef __GNUC__
236 __asm
237 {
238 push eax
239 push edx
240 push ecx
241 rdtsc
242 lea ecx, tmp
243 mov [ecx+4], edx
244 mov [ecx], eax
245 pop ecx
246 pop edx
247 pop eax
248 }
249 #else
250 asm("push %%eax;"
251 "push %%edx;"
252 "push %%ecx;"
253 "rdtsc;"
254 "lea %0,%%ecx;"
255 "mov %%edx,(%%ecx+4);"
256 "mov %%eax,(%%ecx);"
257 "pop %%ecx;"
258 "pop %%edx;"
259 "pop %%eax;"
260 :"=c"(tmp): );
261 #endif
262 if (data->reference==0) {
263 return;
264 }
265 dst->tv_sec=(LONG)(tmp/data->reference);
266 dst->tv_usec=(LONG)((tmp-dst->tv_sec*data->reference)*1000000/data->reference);
267 dst->tv_sec+=data->start.tv_sec;
268 dst->tv_usec+=data->start.tv_usec;
269 if (dst->tv_usec>=1000000) {
270 dst->tv_sec++;
271 dst->tv_usec-=1000000;
272 }
273 }
274
275 #endif /*KQPC_TS*/