[CMAKE]
[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 IRQL <= DISPATCH_LEVEL
61 */
62 {
63 ASSERT_IRQL(DISPATCH_LEVEL);
64 ASSERT(pSystemTime);
65
66 KeQuerySystemTime (pSystemTime);
67 }
68
69 \f
70 /*
71 * @implemented
72 */
73 VOID
74 EXPORT
75 NdisInitializeTimer(
76 IN OUT PNDIS_TIMER Timer,
77 IN PNDIS_TIMER_FUNCTION TimerFunction,
78 IN PVOID FunctionContext)
79 /*
80 * FUNCTION: Set up an NDIS_TIMER for later use
81 * ARGUMENTS:
82 * Timer: pointer to caller-allocated storage to receive an NDIS_TIMER
83 * TimerFunction: function pointer to routine to run when timer expires
84 * FunctionContext: context (param 2) to be passed to the timer function when it runs
85 * NOTES:
86 * - TimerFunction will be called at DISPATCH_LEVEL
87 * - call at IRQL = PASSIVE_LEVEL
88 */
89 {
90 PAGED_CODE();
91 ASSERT(Timer);
92
93 KeInitializeTimer (&Timer->Timer);
94
95 KeInitializeDpc (&Timer->Dpc, (PKDEFERRED_ROUTINE)TimerFunction, FunctionContext);
96 }
97
98 BOOLEAN DequeueMiniportTimer(PNDIS_MINIPORT_TIMER Timer)
99 {
100 PNDIS_MINIPORT_TIMER CurrentTimer;
101
102 ASSERT(KeGetCurrentIrql() == DISPATCH_LEVEL);
103
104 if (!Timer->Miniport->TimerQueue)
105 return FALSE;
106
107 if (Timer->Miniport->TimerQueue == Timer)
108 {
109 Timer->Miniport->TimerQueue = Timer->NextDeferredTimer;
110 Timer->NextDeferredTimer = NULL;
111 return TRUE;
112 }
113 else
114 {
115 CurrentTimer = Timer->Miniport->TimerQueue;
116 while (CurrentTimer->NextDeferredTimer)
117 {
118 if (CurrentTimer->NextDeferredTimer == Timer)
119 {
120 CurrentTimer->NextDeferredTimer = Timer->NextDeferredTimer;
121 Timer->NextDeferredTimer = NULL;
122 return TRUE;
123 }
124 CurrentTimer = CurrentTimer->NextDeferredTimer;
125 }
126 return FALSE;
127 }
128 }
129
130 \f
131 /*
132 * @implemented
133 */
134 VOID
135 EXPORT
136 NdisMCancelTimer(
137 IN PNDIS_MINIPORT_TIMER Timer,
138 OUT PBOOLEAN TimerCancelled)
139 /*
140 * FUNCTION: cancel a scheduled NDIS_MINIPORT_TIMER
141 * ARGUMENTS:
142 * Timer: timer object to cancel
143 * TimerCancelled: status of cancel operation
144 * NOTES:
145 * - call at IRQL <= DISPATCH_LEVEL
146 */
147 {
148 //KIRQL OldIrql;
149
150 ASSERT_IRQL(DISPATCH_LEVEL);
151 ASSERT(TimerCancelled);
152 ASSERT(Timer);
153
154 *TimerCancelled = KeCancelTimer (&Timer->Timer);
155
156 #if 0
157 if (*TimerCancelled)
158 {
159 KeAcquireSpinLock(&Timer->Miniport->Lock, &OldIrql);
160 /* If it's somebody already dequeued it, something is wrong (maybe a double-cancel?) */
161 if (!DequeueMiniportTimer(Timer)) ASSERT(FALSE);
162 KeReleaseSpinLock(&Timer->Miniport->Lock, OldIrql);
163 }
164 #endif
165 }
166
167 VOID NTAPI
168 MiniTimerDpcFunction(PKDPC Dpc,
169 PVOID DeferredContext,
170 PVOID SystemArgument1,
171 PVOID SystemArgument2)
172 {
173 PNDIS_MINIPORT_TIMER Timer = DeferredContext;
174
175 #if 0
176 /* Only dequeue if the timer has a period of 0 */
177 if (!Timer->Timer.Period)
178 {
179 KeAcquireSpinLockAtDpcLevel(&Timer->Miniport->Lock);
180 /* If someone already dequeued it, something is wrong (borked timer implementation?) */
181 if (!DequeueMiniportTimer(Timer)) ASSERT(FALSE);
182 KeReleaseSpinLockFromDpcLevel(&Timer->Miniport->Lock);
183 }
184 #endif
185
186 Timer->MiniportTimerFunction(Dpc,
187 Timer->MiniportTimerContext,
188 SystemArgument1,
189 SystemArgument2);
190 }
191
192 \f
193 /*
194 * @implemented
195 */
196 VOID
197 EXPORT
198 NdisMInitializeTimer(
199 IN OUT PNDIS_MINIPORT_TIMER Timer,
200 IN NDIS_HANDLE MiniportAdapterHandle,
201 IN PNDIS_TIMER_FUNCTION TimerFunction,
202 IN PVOID FunctionContext)
203 /*
204 * FUNCTION: Initialize an NDIS_MINIPORT_TIMER
205 * ARGUMENTS:
206 * Timer: Timer object to initialize
207 * MiniportAdapterHandle: Handle to the miniport, passed in to MiniportInitialize
208 * TimerFunction: function to be executed when the timer expires
209 * FunctionContext: argument passed to TimerFunction when it is called
210 * NOTES:
211 * - TimerFunction is called at IRQL = DISPATCH_LEVEL
212 * - call at IRQL = PASSIVE_LEVEL
213 */
214 {
215 PAGED_CODE();
216 ASSERT(Timer);
217
218 KeInitializeTimer (&Timer->Timer);
219 KeInitializeDpc (&Timer->Dpc, MiniTimerDpcFunction, Timer);
220
221 Timer->MiniportTimerFunction = TimerFunction;
222 Timer->MiniportTimerContext = FunctionContext;
223 Timer->Miniport = &((PLOGICAL_ADAPTER)MiniportAdapterHandle)->NdisMiniportBlock;
224 Timer->NextDeferredTimer = NULL;
225 }
226
227 \f
228 /*
229 * @implemented
230 */
231 VOID
232 EXPORT
233 NdisMSetPeriodicTimer(
234 IN PNDIS_MINIPORT_TIMER Timer,
235 IN UINT MillisecondsPeriod)
236 /*
237 * FUNCTION: Set a timer to go off periodically
238 * ARGUMENTS:
239 * Timer: pointer to the timer object to set
240 * MillisecondsPeriod: period of the timer
241 * NOTES:
242 * - Minimum predictible interval is ~10ms
243 * - Must be called at IRQL <= DISPATCH_LEVEL
244 */
245 {
246 LARGE_INTEGER Timeout;
247 //KIRQL OldIrql;
248
249 ASSERT_IRQL(DISPATCH_LEVEL);
250 ASSERT(Timer);
251
252 /* relative delays are negative, absolute are positive; resolution is 100ns */
253 Timeout.QuadPart = Int32x32To64(MillisecondsPeriod, -10000);
254
255 #if 0
256 /* Lock the miniport block */
257 KeAcquireSpinLock(&Timer->Miniport->Lock, &OldIrql);
258
259 /* Attempt to dequeue the timer */
260 DequeueMiniportTimer(Timer);
261
262 /* Add the timer at the head of the timer queue */
263 Timer->NextDeferredTimer = Timer->Miniport->TimerQueue;
264 Timer->Miniport->TimerQueue = Timer;
265
266 /* Unlock the miniport block */
267 KeReleaseSpinLock(&Timer->Miniport->Lock, OldIrql);
268 #endif
269
270 KeSetTimerEx(&Timer->Timer, Timeout, MillisecondsPeriod, &Timer->Dpc);
271 }
272
273 \f
274 /*
275 * @implemented
276 */
277 #undef NdisMSetTimer
278 VOID
279 EXPORT
280 NdisMSetTimer(
281 IN PNDIS_MINIPORT_TIMER Timer,
282 IN UINT MillisecondsToDelay)
283 /*
284 * FUNCTION: Set a NDIS_MINIPORT_TIMER so that it goes off
285 * ARGUMENTS:
286 * Timer: timer object to set
287 * MillisecondsToDelay: time to wait for the timer to expire
288 * NOTES:
289 * - Minimum predictible interval is ~10ms
290 * - Must be called at IRQL <= DISPATCH_LEVEL
291 */
292 {
293 LARGE_INTEGER Timeout;
294 //KIRQL OldIrql;
295
296 ASSERT_IRQL(DISPATCH_LEVEL);
297 ASSERT(Timer);
298
299 /* relative delays are negative, absolute are positive; resolution is 100ns */
300 Timeout.QuadPart = Int32x32To64(MillisecondsToDelay, -10000);
301
302 #if 0
303 /* Lock the miniport block */
304 KeAcquireSpinLock(&Timer->Miniport->Lock, &OldIrql);
305
306 /* Attempt to dequeue the timer */
307 DequeueMiniportTimer(Timer);
308
309 /* Add the timer at the head of the timer queue */
310 Timer->NextDeferredTimer = Timer->Miniport->TimerQueue;
311 Timer->Miniport->TimerQueue = Timer;
312
313 /* Unlock the miniport block */
314 KeReleaseSpinLock(&Timer->Miniport->Lock, OldIrql);
315 #endif
316
317 KeSetTimer(&Timer->Timer, Timeout, &Timer->Dpc);
318 }
319
320 \f
321 /*
322 * @implemented
323 */
324 VOID
325 EXPORT
326 NdisSetTimer(
327 IN PNDIS_TIMER Timer,
328 IN UINT MillisecondsToDelay)
329 /*
330 * FUNCTION: Set an NDIS_TIMER so that it goes off
331 * ARGUMENTS:
332 * Timer: timer object to set
333 * MillisecondsToDelay: time to wait for the timer to expire
334 * NOTES:
335 * - Minimum predictible interval is ~10ms
336 * - Must be called at IRQL <= DISPATCH_LEVEL
337 */
338 {
339 LARGE_INTEGER Timeout;
340
341 ASSERT_IRQL(DISPATCH_LEVEL);
342 ASSERT(Timer);
343
344 NDIS_DbgPrint(MAX_TRACE, ("Called. Timer is: 0x%x, Timeout is: %ld\n", Timer, MillisecondsToDelay));
345
346 /* relative delays are negative, absolute are positive; resolution is 100ns */
347 Timeout.QuadPart = Int32x32To64(MillisecondsToDelay, -10000);
348
349 KeSetTimer (&Timer->Timer, Timeout, &Timer->Dpc);
350 }
351
352 /*
353 * @implemented
354 */
355 VOID
356 EXPORT
357 NdisSetTimerEx(
358 IN PNDIS_TIMER Timer,
359 IN UINT MillisecondsToDelay,
360 IN PVOID FunctionContext)
361 {
362 NDIS_DbgPrint(MAX_TRACE, ("Called. Timer is: 0x%x, Timeout is: %ld, FunctionContext is: 0x%x\n",
363 Timer, MillisecondsToDelay, FunctionContext));
364
365 Timer->Dpc.DeferredContext = FunctionContext;
366
367 NdisSetTimer(Timer, MillisecondsToDelay);
368 }
369
370 /* EOF */
371