d03acb9dde4e0cfdd11766da1f1f872cd8541924
[reactos.git] / reactos / 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(Timer->Miniport->TimerQueue);
103
104 if (Timer->Miniport->TimerQueue == Timer)
105 {
106 Timer->Miniport->TimerQueue = Timer->NextDeferredTimer;
107 Timer->NextDeferredTimer = NULL;
108 return TRUE;
109 }
110 else
111 {
112 CurrentTimer = Timer->Miniport->TimerQueue;
113 while (CurrentTimer->NextDeferredTimer)
114 {
115 if (CurrentTimer->NextDeferredTimer == Timer)
116 {
117 CurrentTimer->NextDeferredTimer = Timer->NextDeferredTimer;
118 Timer->NextDeferredTimer = NULL;
119 return TRUE;
120 }
121 CurrentTimer = CurrentTimer->NextDeferredTimer;
122 }
123 return FALSE;
124 }
125 }
126
127 \f
128 /*
129 * @implemented
130 */
131 VOID
132 EXPORT
133 NdisMCancelTimer(
134 IN PNDIS_MINIPORT_TIMER Timer,
135 OUT PBOOLEAN TimerCancelled)
136 /*
137 * FUNCTION: cancel a scheduled NDIS_MINIPORT_TIMER
138 * ARGUMENTS:
139 * Timer: timer object to cancel
140 * TimerCancelled: status of cancel operation
141 * NOTES:
142 * - call at IRQL <= DISPATCH_LEVEL
143 */
144 {
145 ASSERT_IRQL(DISPATCH_LEVEL);
146 ASSERT(TimerCancelled);
147 ASSERT(Timer);
148
149 *TimerCancelled = KeCancelTimer (&Timer->Timer);
150
151 DequeueMiniportTimer(Timer);
152 }
153
154 VOID NTAPI
155 MiniTimerDpcFunction(PKDPC Dpc,
156 PVOID DeferredContext,
157 PVOID SystemArgument1,
158 PVOID SystemArgument2)
159 {
160 PNDIS_MINIPORT_TIMER Timer = DeferredContext;
161
162 Timer->MiniportTimerFunction(Dpc,
163 Timer->MiniportTimerContext,
164 SystemArgument1,
165 SystemArgument2);
166
167 /* Only dequeue if the timer has a period of 0 */
168 if (!Timer->Timer.Period) DequeueMiniportTimer(Timer);
169 }
170
171 \f
172 /*
173 * @implemented
174 */
175 VOID
176 EXPORT
177 NdisMInitializeTimer(
178 IN OUT PNDIS_MINIPORT_TIMER Timer,
179 IN NDIS_HANDLE MiniportAdapterHandle,
180 IN PNDIS_TIMER_FUNCTION TimerFunction,
181 IN PVOID FunctionContext)
182 /*
183 * FUNCTION: Initialize an NDIS_MINIPORT_TIMER
184 * ARGUMENTS:
185 * Timer: Timer object to initialize
186 * MiniportAdapterHandle: Handle to the miniport, passed in to MiniportInitialize
187 * TimerFunction: function to be executed when the timer expires
188 * FunctionContext: argument passed to TimerFunction when it is called
189 * NOTES:
190 * - TimerFunction is called at IRQL = DISPATCH_LEVEL
191 * - call at IRQL = PASSIVE_LEVEL
192 */
193 {
194 PAGED_CODE();
195 ASSERT(Timer);
196
197 KeInitializeTimer (&Timer->Timer);
198 KeInitializeDpc (&Timer->Dpc, MiniTimerDpcFunction, Timer);
199
200 Timer->MiniportTimerFunction = TimerFunction;
201 Timer->MiniportTimerContext = FunctionContext;
202 Timer->Miniport = &((PLOGICAL_ADAPTER)MiniportAdapterHandle)->NdisMiniportBlock;
203 Timer->NextDeferredTimer = NULL;
204 }
205
206 \f
207 /*
208 * @implemented
209 */
210 VOID
211 EXPORT
212 NdisMSetPeriodicTimer(
213 IN PNDIS_MINIPORT_TIMER Timer,
214 IN UINT MillisecondsPeriod)
215 /*
216 * FUNCTION: Set a timer to go off periodically
217 * ARGUMENTS:
218 * Timer: pointer to the timer object to set
219 * MillisecondsPeriod: period of the timer
220 * NOTES:
221 * - Minimum predictible interval is ~10ms
222 * - Must be called at IRQL <= DISPATCH_LEVEL
223 */
224 {
225 LARGE_INTEGER Timeout;
226
227 ASSERT_IRQL(DISPATCH_LEVEL);
228 ASSERT(Timer);
229
230 /* relative delays are negative, absolute are positive; resolution is 100ns */
231 Timeout.QuadPart = Int32x32To64(MillisecondsPeriod, -10000);
232
233 /* Dequeue the timer if it is queued already */
234 DequeueMiniportTimer(Timer);
235
236 /* Add the timer at the head of the timer queue */
237 Timer->NextDeferredTimer = Timer->Miniport->TimerQueue;
238 Timer->Miniport->TimerQueue = Timer;
239
240 KeSetTimerEx (&Timer->Timer, Timeout, MillisecondsPeriod, &Timer->Dpc);
241 }
242
243 \f
244 /*
245 * @implemented
246 */
247 #undef NdisMSetTimer
248 VOID
249 EXPORT
250 NdisMSetTimer(
251 IN PNDIS_MINIPORT_TIMER Timer,
252 IN UINT MillisecondsToDelay)
253 /*
254 * FUNCTION: Set a NDIS_MINIPORT_TIMER so that it goes off
255 * ARGUMENTS:
256 * Timer: timer object to set
257 * MillisecondsToDelay: time to wait for the timer to expire
258 * NOTES:
259 * - Minimum predictible interval is ~10ms
260 * - Must be called at IRQL <= DISPATCH_LEVEL
261 */
262 {
263 LARGE_INTEGER Timeout;
264
265 ASSERT_IRQL(DISPATCH_LEVEL);
266 ASSERT(Timer);
267
268 /* relative delays are negative, absolute are positive; resolution is 100ns */
269 Timeout.QuadPart = Int32x32To64(MillisecondsToDelay, -10000);
270
271 /* Dequeue the timer if it is queued already */
272 DequeueMiniportTimer(Timer);
273
274 /* Add the timer at the head of the timer queue */
275 Timer->NextDeferredTimer = Timer->Miniport->TimerQueue;
276 Timer->Miniport->TimerQueue = Timer;
277
278 KeSetTimer (&Timer->Timer, Timeout, &Timer->Dpc);
279 }
280
281 \f
282 /*
283 * @implemented
284 */
285 VOID
286 EXPORT
287 NdisSetTimer(
288 IN PNDIS_TIMER Timer,
289 IN UINT MillisecondsToDelay)
290 /*
291 * FUNCTION: Set an NDIS_TIMER so that it goes off
292 * ARGUMENTS:
293 * Timer: timer object to set
294 * MillisecondsToDelay: time to wait for the timer to expire
295 * NOTES:
296 * - Minimum predictible interval is ~10ms
297 * - Must be called at IRQL <= DISPATCH_LEVEL
298 */
299 {
300 LARGE_INTEGER Timeout;
301
302 ASSERT_IRQL(DISPATCH_LEVEL);
303 ASSERT(Timer);
304
305 NDIS_DbgPrint(MAX_TRACE, ("Called. Timer is: 0x%x, Timeout is: %ld\n", Timer, MillisecondsToDelay));
306
307 /* relative delays are negative, absolute are positive; resolution is 100ns */
308 Timeout.QuadPart = Int32x32To64(MillisecondsToDelay, -10000);
309
310 KeSetTimer (&Timer->Timer, Timeout, &Timer->Dpc);
311 }
312
313 /*
314 * @implemented
315 */
316 VOID
317 EXPORT
318 NdisSetTimerEx(
319 IN PNDIS_TIMER Timer,
320 IN UINT MillisecondsToDelay,
321 IN PVOID FunctionContext)
322 {
323 NDIS_DbgPrint(MAX_TRACE, ("Called. Timer is: 0x%x, Timeout is: %ld, FunctionContext is: 0x%x\n",
324 Timer, MillisecondsToDelay, FunctionContext));
325
326 Timer->Dpc.DeferredContext = FunctionContext;
327
328 NdisSetTimer(Timer, MillisecondsToDelay);
329 }
330
331 /* EOF */
332