2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS NDIS library
5 * PURPOSE: Time related routines
6 * PROGRAMMERS: Casper S. Hornstrup (chorns@users.sourceforge.net)
7 * Vizzini (vizzini@plasmic.com)
9 * CSH 01/08-2000 Created
10 * Vizzini 08-Oct-2003 Formatting, commenting, and ASSERTs
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
30 OUT PBOOLEAN TimerCancelled
)
32 * FUNCTION: Cancels a scheduled NDIS timer
34 * Timer: pointer to an NDIS_TIMER object to cancel
35 * TimerCancelled: boolean that returns cancellation status
37 * - call at IRQL <= DISPATCH_LEVEL
40 ASSERT_IRQL(DISPATCH_LEVEL
);
43 *TimerCancelled
= KeCancelTimer (&Timer
->Timer
);
50 #undef NdisGetCurrentSystemTime
53 NdisGetCurrentSystemTime (
54 IN OUT PLARGE_INTEGER pSystemTime
)
56 * FUNCTION: Retrieve the current system time
58 * pSystemTime: pointer to the returned system time
65 KeQuerySystemTime (pSystemTime
);
75 IN OUT PNDIS_TIMER Timer
,
76 IN PNDIS_TIMER_FUNCTION TimerFunction
,
77 IN PVOID FunctionContext
)
79 * FUNCTION: Set up an NDIS_TIMER for later use
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
85 * - TimerFunction will be called at DISPATCH_LEVEL
86 * - call at IRQL = PASSIVE_LEVEL
92 KeInitializeTimer (&Timer
->Timer
);
94 KeInitializeDpc (&Timer
->Dpc
, (PKDEFERRED_ROUTINE
)TimerFunction
, FunctionContext
);
97 BOOLEAN
DequeueMiniportTimer(PNDIS_MINIPORT_TIMER Timer
)
99 PNDIS_MINIPORT_TIMER CurrentTimer
;
101 ASSERT(KeGetCurrentIrql() == DISPATCH_LEVEL
);
103 if (!Timer
->Miniport
->TimerQueue
)
106 if (Timer
->Miniport
->TimerQueue
== Timer
)
108 Timer
->Miniport
->TimerQueue
= Timer
->NextDeferredTimer
;
109 Timer
->NextDeferredTimer
= NULL
;
114 CurrentTimer
= Timer
->Miniport
->TimerQueue
;
115 while (CurrentTimer
->NextDeferredTimer
)
117 if (CurrentTimer
->NextDeferredTimer
== Timer
)
119 CurrentTimer
->NextDeferredTimer
= Timer
->NextDeferredTimer
;
120 Timer
->NextDeferredTimer
= NULL
;
123 CurrentTimer
= CurrentTimer
->NextDeferredTimer
;
136 IN PNDIS_MINIPORT_TIMER Timer
,
137 OUT PBOOLEAN TimerCancelled
)
139 * FUNCTION: cancel a scheduled NDIS_MINIPORT_TIMER
141 * Timer: timer object to cancel
142 * TimerCancelled: status of cancel operation
144 * - call at IRQL <= DISPATCH_LEVEL
149 ASSERT_IRQL(DISPATCH_LEVEL
);
150 ASSERT(TimerCancelled
);
153 *TimerCancelled
= KeCancelTimer (&Timer
->Timer
);
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
);
167 MiniTimerDpcFunction(PKDPC Dpc
,
168 PVOID DeferredContext
,
169 PVOID SystemArgument1
,
170 PVOID SystemArgument2
)
172 PNDIS_MINIPORT_TIMER Timer
= DeferredContext
;
175 /* Only dequeue if the timer has a period of 0 */
176 if (!Timer
->Timer
.Period
)
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
);
185 Timer
->MiniportTimerFunction(Dpc
,
186 Timer
->MiniportTimerContext
,
197 NdisMInitializeTimer(
198 IN OUT PNDIS_MINIPORT_TIMER Timer
,
199 IN NDIS_HANDLE MiniportAdapterHandle
,
200 IN PNDIS_TIMER_FUNCTION TimerFunction
,
201 IN PVOID FunctionContext
)
203 * FUNCTION: Initialize an NDIS_MINIPORT_TIMER
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
210 * - TimerFunction is called at IRQL = DISPATCH_LEVEL
211 * - call at IRQL = PASSIVE_LEVEL
217 KeInitializeTimer (&Timer
->Timer
);
218 KeInitializeDpc (&Timer
->Dpc
, MiniTimerDpcFunction
, Timer
);
220 Timer
->MiniportTimerFunction
= TimerFunction
;
221 Timer
->MiniportTimerContext
= FunctionContext
;
222 Timer
->Miniport
= &((PLOGICAL_ADAPTER
)MiniportAdapterHandle
)->NdisMiniportBlock
;
223 Timer
->NextDeferredTimer
= NULL
;
232 NdisMSetPeriodicTimer(
233 IN PNDIS_MINIPORT_TIMER Timer
,
234 IN UINT MillisecondsPeriod
)
236 * FUNCTION: Set a timer to go off periodically
238 * Timer: pointer to the timer object to set
239 * MillisecondsPeriod: period of the timer
241 * - Minimum predictible interval is ~10ms
242 * - Must be called at IRQL <= DISPATCH_LEVEL
245 LARGE_INTEGER Timeout
;
248 ASSERT_IRQL(DISPATCH_LEVEL
);
251 /* relative delays are negative, absolute are positive; resolution is 100ns */
252 Timeout
.QuadPart
= Int32x32To64(MillisecondsPeriod
, -10000);
255 /* Lock the miniport block */
256 KeAcquireSpinLock(&Timer
->Miniport
->Lock
, &OldIrql
);
258 /* Attempt to dequeue the timer */
259 DequeueMiniportTimer(Timer
);
261 /* Add the timer at the head of the timer queue */
262 Timer
->NextDeferredTimer
= Timer
->Miniport
->TimerQueue
;
263 Timer
->Miniport
->TimerQueue
= Timer
;
265 /* Unlock the miniport block */
266 KeReleaseSpinLock(&Timer
->Miniport
->Lock
, OldIrql
);
269 KeSetTimerEx(&Timer
->Timer
, Timeout
, MillisecondsPeriod
, &Timer
->Dpc
);
280 IN PNDIS_MINIPORT_TIMER Timer
,
281 IN UINT MillisecondsToDelay
)
283 * FUNCTION: Set a NDIS_MINIPORT_TIMER so that it goes off
285 * Timer: timer object to set
286 * MillisecondsToDelay: time to wait for the timer to expire
288 * - Minimum predictible interval is ~10ms
289 * - Must be called at IRQL <= DISPATCH_LEVEL
292 LARGE_INTEGER Timeout
;
295 ASSERT_IRQL(DISPATCH_LEVEL
);
298 /* relative delays are negative, absolute are positive; resolution is 100ns */
299 Timeout
.QuadPart
= Int32x32To64(MillisecondsToDelay
, -10000);
302 /* Lock the miniport block */
303 KeAcquireSpinLock(&Timer
->Miniport
->Lock
, &OldIrql
);
305 /* Attempt to dequeue the timer */
306 DequeueMiniportTimer(Timer
);
308 /* Add the timer at the head of the timer queue */
309 Timer
->NextDeferredTimer
= Timer
->Miniport
->TimerQueue
;
310 Timer
->Miniport
->TimerQueue
= Timer
;
312 /* Unlock the miniport block */
313 KeReleaseSpinLock(&Timer
->Miniport
->Lock
, OldIrql
);
316 KeSetTimer(&Timer
->Timer
, Timeout
, &Timer
->Dpc
);
326 IN PNDIS_TIMER Timer
,
327 IN UINT MillisecondsToDelay
)
329 * FUNCTION: Set an NDIS_TIMER so that it goes off
331 * Timer: timer object to set
332 * MillisecondsToDelay: time to wait for the timer to expire
334 * - Minimum predictible interval is ~10ms
335 * - Must be called at IRQL <= DISPATCH_LEVEL
338 LARGE_INTEGER Timeout
;
340 ASSERT_IRQL(DISPATCH_LEVEL
);
343 NDIS_DbgPrint(MAX_TRACE
, ("Called. Timer is: 0x%x, Timeout is: %ld\n", Timer
, MillisecondsToDelay
));
345 /* relative delays are negative, absolute are positive; resolution is 100ns */
346 Timeout
.QuadPart
= Int32x32To64(MillisecondsToDelay
, -10000);
348 KeSetTimer (&Timer
->Timer
, Timeout
, &Timer
->Dpc
);
357 IN PNDIS_TIMER Timer
,
358 IN UINT MillisecondsToDelay
,
359 IN PVOID FunctionContext
)
361 NDIS_DbgPrint(MAX_TRACE
, ("Called. Timer is: 0x%x, Timeout is: %ld, FunctionContext is: 0x%x\n",
362 Timer
, MillisecondsToDelay
, FunctionContext
));
364 Timer
->Dpc
.DeferredContext
= FunctionContext
;
366 NdisSetTimer(Timer
, MillisecondsToDelay
);