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