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
29 OUT PBOOLEAN TimerCancelled
)
31 * FUNCTION: Cancels a scheduled NDIS timer
33 * Timer: pointer to an NDIS_TIMER object to cancel
34 * TimerCancelled: boolean that returns cancellation status
36 * - call at IRQL <= DISPATCH_LEVEL
39 ASSERT_IRQL(DISPATCH_LEVEL
);
42 *TimerCancelled
= KeCancelTimer (&Timer
->Timer
);
48 #undef NdisGetCurrentSystemTime
51 NdisGetCurrentSystemTime (
52 IN OUT PLARGE_INTEGER pSystemTime
)
54 * FUNCTION: Retrieve the current system time
56 * pSystemTime: pointer to the returned system time
63 KeQuerySystemTime (pSystemTime
);
72 IN OUT PNDIS_TIMER Timer
,
73 IN PNDIS_TIMER_FUNCTION TimerFunction
,
74 IN PVOID FunctionContext
)
76 * FUNCTION: Set up an NDIS_TIMER for later use
78 * Timer: pointer to caller-allocated storage to receive an NDIS_TIMER
79 * TimerFunction: function pointer to routine to run when timer expires
80 * FunctionContext: context (param 2) to be passed to the timer function when it runs
82 * - TimerFunction will be called at DISPATCH_LEVEL
83 * - call at IRQL = PASSIVE_LEVEL
89 KeInitializeTimer (&Timer
->Timer
);
91 KeInitializeDpc (&Timer
->Dpc
, (PKDEFERRED_ROUTINE
)TimerFunction
, FunctionContext
);
94 BOOLEAN
DequeueMiniportTimer(PNDIS_MINIPORT_TIMER Timer
)
96 PNDIS_MINIPORT_TIMER CurrentTimer
;
98 ASSERT(KeGetCurrentIrql() == DISPATCH_LEVEL
);
100 if (!Timer
->Miniport
->TimerQueue
)
103 if (Timer
->Miniport
->TimerQueue
== Timer
)
105 Timer
->Miniport
->TimerQueue
= Timer
->NextDeferredTimer
;
106 Timer
->NextDeferredTimer
= NULL
;
111 CurrentTimer
= Timer
->Miniport
->TimerQueue
;
112 while (CurrentTimer
->NextDeferredTimer
)
114 if (CurrentTimer
->NextDeferredTimer
== Timer
)
116 CurrentTimer
->NextDeferredTimer
= Timer
->NextDeferredTimer
;
117 Timer
->NextDeferredTimer
= NULL
;
120 CurrentTimer
= CurrentTimer
->NextDeferredTimer
;
132 IN PNDIS_MINIPORT_TIMER Timer
,
133 OUT PBOOLEAN TimerCancelled
)
135 * FUNCTION: cancel a scheduled NDIS_MINIPORT_TIMER
137 * Timer: timer object to cancel
138 * TimerCancelled: status of cancel operation
140 * - call at IRQL <= DISPATCH_LEVEL
145 ASSERT_IRQL(DISPATCH_LEVEL
);
146 ASSERT(TimerCancelled
);
149 *TimerCancelled
= KeCancelTimer (&Timer
->Timer
);
154 KeAcquireSpinLock(&Timer
->Miniport
->Lock
, &OldIrql
);
155 /* If it's somebody already dequeued it, something is wrong (maybe a double-cancel?) */
156 if (!DequeueMiniportTimer(Timer
)) ASSERT(FALSE
);
157 KeReleaseSpinLock(&Timer
->Miniport
->Lock
, OldIrql
);
163 MiniTimerDpcFunction(PKDPC Dpc
,
164 PVOID DeferredContext
,
165 PVOID SystemArgument1
,
166 PVOID SystemArgument2
)
168 PNDIS_MINIPORT_TIMER Timer
= DeferredContext
;
171 /* Only dequeue if the timer has a period of 0 */
172 if (!Timer
->Timer
.Period
)
174 KeAcquireSpinLockAtDpcLevel(&Timer
->Miniport
->Lock
);
175 /* If someone already dequeued it, something is wrong (borked timer implementation?) */
176 if (!DequeueMiniportTimer(Timer
)) ASSERT(FALSE
);
177 KeReleaseSpinLockFromDpcLevel(&Timer
->Miniport
->Lock
);
181 Timer
->MiniportTimerFunction(Dpc
,
182 Timer
->MiniportTimerContext
,
192 NdisMInitializeTimer(
193 IN OUT PNDIS_MINIPORT_TIMER Timer
,
194 IN NDIS_HANDLE MiniportAdapterHandle
,
195 IN PNDIS_TIMER_FUNCTION TimerFunction
,
196 IN PVOID FunctionContext
)
198 * FUNCTION: Initialize an NDIS_MINIPORT_TIMER
200 * Timer: Timer object to initialize
201 * MiniportAdapterHandle: Handle to the miniport, passed in to MiniportInitialize
202 * TimerFunction: function to be executed when the timer expires
203 * FunctionContext: argument passed to TimerFunction when it is called
205 * - TimerFunction is called at IRQL = DISPATCH_LEVEL
206 * - call at IRQL = PASSIVE_LEVEL
212 KeInitializeTimer (&Timer
->Timer
);
213 KeInitializeDpc (&Timer
->Dpc
, MiniTimerDpcFunction
, Timer
);
215 Timer
->MiniportTimerFunction
= TimerFunction
;
216 Timer
->MiniportTimerContext
= FunctionContext
;
217 Timer
->Miniport
= &((PLOGICAL_ADAPTER
)MiniportAdapterHandle
)->NdisMiniportBlock
;
218 Timer
->NextDeferredTimer
= NULL
;
226 NdisMSetPeriodicTimer(
227 IN PNDIS_MINIPORT_TIMER Timer
,
228 IN UINT MillisecondsPeriod
)
230 * FUNCTION: Set a timer to go off periodically
232 * Timer: pointer to the timer object to set
233 * MillisecondsPeriod: period of the timer
235 * - Minimum predictable interval is ~10ms
236 * - Must be called at IRQL <= DISPATCH_LEVEL
239 LARGE_INTEGER Timeout
;
242 ASSERT_IRQL(DISPATCH_LEVEL
);
245 /* relative delays are negative, absolute are positive; resolution is 100ns */
246 Timeout
.QuadPart
= Int32x32To64(MillisecondsPeriod
, -10000);
249 /* Lock the miniport block */
250 KeAcquireSpinLock(&Timer
->Miniport
->Lock
, &OldIrql
);
252 /* Attempt to dequeue the timer */
253 DequeueMiniportTimer(Timer
);
255 /* Add the timer at the head of the timer queue */
256 Timer
->NextDeferredTimer
= Timer
->Miniport
->TimerQueue
;
257 Timer
->Miniport
->TimerQueue
= Timer
;
259 /* Unlock the miniport block */
260 KeReleaseSpinLock(&Timer
->Miniport
->Lock
, OldIrql
);
263 KeSetTimerEx(&Timer
->Timer
, Timeout
, MillisecondsPeriod
, &Timer
->Dpc
);
273 IN PNDIS_MINIPORT_TIMER Timer
,
274 IN UINT MillisecondsToDelay
)
276 * FUNCTION: Set a NDIS_MINIPORT_TIMER so that it goes off
278 * Timer: timer object to set
279 * MillisecondsToDelay: time to wait for the timer to expire
281 * - Minimum predictable interval is ~10ms
282 * - Must be called at IRQL <= DISPATCH_LEVEL
285 LARGE_INTEGER Timeout
;
288 ASSERT_IRQL(DISPATCH_LEVEL
);
291 /* relative delays are negative, absolute are positive; resolution is 100ns */
292 Timeout
.QuadPart
= Int32x32To64(MillisecondsToDelay
, -10000);
295 /* Lock the miniport block */
296 KeAcquireSpinLock(&Timer
->Miniport
->Lock
, &OldIrql
);
298 /* Attempt to dequeue the timer */
299 DequeueMiniportTimer(Timer
);
301 /* Add the timer at the head of the timer queue */
302 Timer
->NextDeferredTimer
= Timer
->Miniport
->TimerQueue
;
303 Timer
->Miniport
->TimerQueue
= Timer
;
305 /* Unlock the miniport block */
306 KeReleaseSpinLock(&Timer
->Miniport
->Lock
, OldIrql
);
309 KeSetTimer(&Timer
->Timer
, Timeout
, &Timer
->Dpc
);
318 IN PNDIS_TIMER Timer
,
319 IN UINT MillisecondsToDelay
)
321 * FUNCTION: Set an NDIS_TIMER so that it goes off
323 * Timer: timer object to set
324 * MillisecondsToDelay: time to wait for the timer to expire
326 * - Minimum predictable interval is ~10ms
327 * - Must be called at IRQL <= DISPATCH_LEVEL
330 LARGE_INTEGER Timeout
;
332 ASSERT_IRQL(DISPATCH_LEVEL
);
335 NDIS_DbgPrint(MAX_TRACE
, ("Called. Timer is: 0x%x, Timeout is: %ld\n", Timer
, MillisecondsToDelay
));
337 /* relative delays are negative, absolute are positive; resolution is 100ns */
338 Timeout
.QuadPart
= Int32x32To64(MillisecondsToDelay
, -10000);
340 KeSetTimer (&Timer
->Timer
, Timeout
, &Timer
->Dpc
);
349 IN PNDIS_TIMER Timer
,
350 IN UINT MillisecondsToDelay
,
351 IN PVOID FunctionContext
)
353 NDIS_DbgPrint(MAX_TRACE
, ("Called. Timer is: 0x%x, Timeout is: %ld, FunctionContext is: 0x%x\n",
354 Timer
, MillisecondsToDelay
, FunctionContext
));
356 Timer
->Dpc
.DeferredContext
= FunctionContext
;
358 NdisSetTimer(Timer
, MillisecondsToDelay
);