[CLT2012]
[reactos.git] / drivers / network / ndis / ndis / time.c
1 /*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS NDIS library
4 * FILE: ndis/time.c
5 * PURPOSE: Time related routines
6 * PROGRAMMERS: Casper S. Hornstrup (chorns@users.sourceforge.net)
7 * Vizzini (vizzini@plasmic.com)
8 * REVISIONS:
9 * CSH 01/08-2000 Created
10 * Vizzini 08-Oct-2003 Formatting, commenting, and ASSERTs
11 *
12 * NOTES:
13 * - Although the standard kernel-mode M.O. is to trust the caller
14 * to not provide bad arguments, we have added lots of argument
15 * validation to assist in the effort to get third-party binaries
16 * working. It is easiest to track bugs when things break quickly
17 * and badly.
18 */
19
20 #include "ndissys.h"
21
22 \f
23 /*
24 * @implemented
25 */
26 VOID
27 EXPORT
28 NdisCancelTimer(
29 IN PNDIS_TIMER Timer,
30 OUT PBOOLEAN TimerCancelled)
31 /*
32 * FUNCTION: Cancels a scheduled NDIS timer
33 * ARGUMENTS:
34 * Timer: pointer to an NDIS_TIMER object to cancel
35 * TimerCancelled: boolean that returns cancellation status
36 * NOTES:
37 * - call at IRQL <= DISPATCH_LEVEL
38 */
39 {
40 ASSERT_IRQL(DISPATCH_LEVEL);
41 ASSERT(Timer);
42
43 *TimerCancelled = KeCancelTimer (&Timer->Timer);
44 }
45
46 \f
47 /*
48 * @implemented
49 */
50 #undef NdisGetCurrentSystemTime
51 VOID
52 EXPORT
53 NdisGetCurrentSystemTime (
54 IN OUT PLARGE_INTEGER pSystemTime)
55 /*
56 * FUNCTION: Retrieve the current system time
57 * ARGUMENTS:
58 * pSystemTime: pointer to the returned system time
59 * NOTES:
60 * - call at any IRQL
61 */
62 {
63 ASSERT(pSystemTime);
64
65 KeQuerySystemTime (pSystemTime);
66 }
67
68 \f
69 /*
70 * @implemented
71 */
72 VOID
73 EXPORT
74 NdisInitializeTimer(
75 IN OUT PNDIS_TIMER Timer,
76 IN PNDIS_TIMER_FUNCTION TimerFunction,
77 IN PVOID FunctionContext)
78 /*
79 * FUNCTION: Set up an NDIS_TIMER for later use
80 * ARGUMENTS:
81 * Timer: pointer to caller-allocated storage to receive an NDIS_TIMER
82 * TimerFunction: function pointer to routine to run when timer expires
83 * FunctionContext: context (param 2) to be passed to the timer function when it runs
84 * NOTES:
85 * - TimerFunction will be called at DISPATCH_LEVEL
86 * - call at IRQL = PASSIVE_LEVEL
87 */
88 {
89 PAGED_CODE();
90 ASSERT(Timer);
91
92 KeInitializeTimer (&Timer->Timer);
93
94 KeInitializeDpc (&Timer->Dpc, (PKDEFERRED_ROUTINE)TimerFunction, FunctionContext);
95 }
96
97 BOOLEAN DequeueMiniportTimer(PNDIS_MINIPORT_TIMER Timer)
98 {
99 PNDIS_MINIPORT_TIMER CurrentTimer;
100
101 ASSERT(KeGetCurrentIrql() == DISPATCH_LEVEL);
102
103 if (!Timer->Miniport->TimerQueue)
104 return FALSE;
105
106 if (Timer->Miniport->TimerQueue == Timer)
107 {
108 Timer->Miniport->TimerQueue = Timer->NextDeferredTimer;
109 Timer->NextDeferredTimer = NULL;
110 return TRUE;
111 }
112 else
113 {
114 CurrentTimer = Timer->Miniport->TimerQueue;
115 while (CurrentTimer->NextDeferredTimer)
116 {
117 if (CurrentTimer->NextDeferredTimer == Timer)
118 {
119 CurrentTimer->NextDeferredTimer = Timer->NextDeferredTimer;
120 Timer->NextDeferredTimer = NULL;
121 return TRUE;
122 }
123 CurrentTimer = CurrentTimer->NextDeferredTimer;
124 }
125 return FALSE;
126 }
127 }
128
129 \f
130 /*
131 * @implemented
132 */
133 VOID
134 EXPORT
135 NdisMCancelTimer(
136 IN PNDIS_MINIPORT_TIMER Timer,
137 OUT PBOOLEAN TimerCancelled)
138 /*
139 * FUNCTION: cancel a scheduled NDIS_MINIPORT_TIMER
140 * ARGUMENTS:
141 * Timer: timer object to cancel
142 * TimerCancelled: status of cancel operation
143 * NOTES:
144 * - call at IRQL <= DISPATCH_LEVEL
145 */
146 {
147 //KIRQL OldIrql;
148
149 ASSERT_IRQL(DISPATCH_LEVEL);
150 ASSERT(TimerCancelled);
151 ASSERT(Timer);
152
153 *TimerCancelled = KeCancelTimer (&Timer->Timer);
154
155 #if 0
156 if (*TimerCancelled)
157 {
158 KeAcquireSpinLock(&Timer->Miniport->Lock, &OldIrql);
159 /* If it's somebody already dequeued it, something is wrong (maybe a double-cancel?) */
160 if (!DequeueMiniportTimer(Timer)) ASSERT(FALSE);
161 KeReleaseSpinLock(&Timer->Miniport->Lock, OldIrql);
162 }
163 #endif
164 }
165
166 VOID NTAPI
167 MiniTimerDpcFunction(PKDPC Dpc,
168 PVOID DeferredContext,
169 PVOID SystemArgument1,
170 PVOID SystemArgument2)
171 {
172 PNDIS_MINIPORT_TIMER Timer = DeferredContext;
173
174 #if 0
175 /* Only dequeue if the timer has a period of 0 */
176 if (!Timer->Timer.Period)
177 {
178 KeAcquireSpinLockAtDpcLevel(&Timer->Miniport->Lock);
179 /* If someone already dequeued it, something is wrong (borked timer implementation?) */
180 if (!DequeueMiniportTimer(Timer)) ASSERT(FALSE);
181 KeReleaseSpinLockFromDpcLevel(&Timer->Miniport->Lock);
182 }
183 #endif
184
185 Timer->MiniportTimerFunction(Dpc,
186 Timer->MiniportTimerContext,
187 SystemArgument1,
188 SystemArgument2);
189 }
190
191 \f
192 /*
193 * @implemented
194 */
195 VOID
196 EXPORT
197 NdisMInitializeTimer(
198 IN OUT PNDIS_MINIPORT_TIMER Timer,
199 IN NDIS_HANDLE MiniportAdapterHandle,
200 IN PNDIS_TIMER_FUNCTION TimerFunction,
201 IN PVOID FunctionContext)
202 /*
203 * FUNCTION: Initialize an NDIS_MINIPORT_TIMER
204 * ARGUMENTS:
205 * Timer: Timer object to initialize
206 * MiniportAdapterHandle: Handle to the miniport, passed in to MiniportInitialize
207 * TimerFunction: function to be executed when the timer expires
208 * FunctionContext: argument passed to TimerFunction when it is called
209 * NOTES:
210 * - TimerFunction is called at IRQL = DISPATCH_LEVEL
211 * - call at IRQL = PASSIVE_LEVEL
212 */
213 {
214 PAGED_CODE();
215 ASSERT(Timer);
216
217 KeInitializeTimer (&Timer->Timer);
218 KeInitializeDpc (&Timer->Dpc, MiniTimerDpcFunction, Timer);
219
220 Timer->MiniportTimerFunction = TimerFunction;
221 Timer->MiniportTimerContext = FunctionContext;
222 Timer->Miniport = &((PLOGICAL_ADAPTER)MiniportAdapterHandle)->NdisMiniportBlock;
223 Timer->NextDeferredTimer = NULL;
224 }
225
226 \f
227 /*
228 * @implemented
229 */
230 VOID
231 EXPORT
232 NdisMSetPeriodicTimer(
233 IN PNDIS_MINIPORT_TIMER Timer,
234 IN UINT MillisecondsPeriod)
235 /*
236 * FUNCTION: Set a timer to go off periodically
237 * ARGUMENTS:
238 * Timer: pointer to the timer object to set
239 * MillisecondsPeriod: period of the timer
240 * NOTES:
241 * - Minimum predictible interval is ~10ms
242 * - Must be called at IRQL <= DISPATCH_LEVEL
243 */
244 {
245 LARGE_INTEGER Timeout;
246 //KIRQL OldIrql;
247
248 ASSERT_IRQL(DISPATCH_LEVEL);
249 ASSERT(Timer);
250
251 /* relative delays are negative, absolute are positive; resolution is 100ns */
252 Timeout.QuadPart = Int32x32To64(MillisecondsPeriod, -10000);
253
254 #if 0
255 /* Lock the miniport block */
256 KeAcquireSpinLock(&Timer->Miniport->Lock, &OldIrql);
257
258 /* Attempt to dequeue the timer */
259 DequeueMiniportTimer(Timer);
260
261 /* Add the timer at the head of the timer queue */
262 Timer->NextDeferredTimer = Timer->Miniport->TimerQueue;
263 Timer->Miniport->TimerQueue = Timer;
264
265 /* Unlock the miniport block */
266 KeReleaseSpinLock(&Timer->Miniport->Lock, OldIrql);
267 #endif
268
269 KeSetTimerEx(&Timer->Timer, Timeout, MillisecondsPeriod, &Timer->Dpc);
270 }
271
272 \f
273 /*
274 * @implemented
275 */
276 #undef NdisMSetTimer
277 VOID
278 EXPORT
279 NdisMSetTimer(
280 IN PNDIS_MINIPORT_TIMER Timer,
281 IN UINT MillisecondsToDelay)
282 /*
283 * FUNCTION: Set a NDIS_MINIPORT_TIMER so that it goes off
284 * ARGUMENTS:
285 * Timer: timer object to set
286 * MillisecondsToDelay: time to wait for the timer to expire
287 * NOTES:
288 * - Minimum predictible interval is ~10ms
289 * - Must be called at IRQL <= DISPATCH_LEVEL
290 */
291 {
292 LARGE_INTEGER Timeout;
293 //KIRQL OldIrql;
294
295 ASSERT_IRQL(DISPATCH_LEVEL);
296 ASSERT(Timer);
297
298 /* relative delays are negative, absolute are positive; resolution is 100ns */
299 Timeout.QuadPart = Int32x32To64(MillisecondsToDelay, -10000);
300
301 #if 0
302 /* Lock the miniport block */
303 KeAcquireSpinLock(&Timer->Miniport->Lock, &OldIrql);
304
305 /* Attempt to dequeue the timer */
306 DequeueMiniportTimer(Timer);
307
308 /* Add the timer at the head of the timer queue */
309 Timer->NextDeferredTimer = Timer->Miniport->TimerQueue;
310 Timer->Miniport->TimerQueue = Timer;
311
312 /* Unlock the miniport block */
313 KeReleaseSpinLock(&Timer->Miniport->Lock, OldIrql);
314 #endif
315
316 KeSetTimer(&Timer->Timer, Timeout, &Timer->Dpc);
317 }
318
319 \f
320 /*
321 * @implemented
322 */
323 VOID
324 EXPORT
325 NdisSetTimer(
326 IN PNDIS_TIMER Timer,
327 IN UINT MillisecondsToDelay)
328 /*
329 * FUNCTION: Set an NDIS_TIMER so that it goes off
330 * ARGUMENTS:
331 * Timer: timer object to set
332 * MillisecondsToDelay: time to wait for the timer to expire
333 * NOTES:
334 * - Minimum predictible interval is ~10ms
335 * - Must be called at IRQL <= DISPATCH_LEVEL
336 */
337 {
338 LARGE_INTEGER Timeout;
339
340 ASSERT_IRQL(DISPATCH_LEVEL);
341 ASSERT(Timer);
342
343 NDIS_DbgPrint(MAX_TRACE, ("Called. Timer is: 0x%x, Timeout is: %ld\n", Timer, MillisecondsToDelay));
344
345 /* relative delays are negative, absolute are positive; resolution is 100ns */
346 Timeout.QuadPart = Int32x32To64(MillisecondsToDelay, -10000);
347
348 KeSetTimer (&Timer->Timer, Timeout, &Timer->Dpc);
349 }
350
351 /*
352 * @implemented
353 */
354 VOID
355 EXPORT
356 NdisSetTimerEx(
357 IN PNDIS_TIMER Timer,
358 IN UINT MillisecondsToDelay,
359 IN PVOID FunctionContext)
360 {
361 NDIS_DbgPrint(MAX_TRACE, ("Called. Timer is: 0x%x, Timeout is: %ld, FunctionContext is: 0x%x\n",
362 Timer, MillisecondsToDelay, FunctionContext));
363
364 Timer->Dpc.DeferredContext = FunctionContext;
365
366 NdisSetTimer(Timer, MillisecondsToDelay);
367 }
368
369 /* EOF */
370