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