1 /******************************************************************************
4 * Project: Gigabit Ethernet Adapters, Event Scheduler Module
5 * Version: $Revision: 1.14 $
6 * Date: $Date: 2003/09/16 13:46:51 $
7 * Purpose: High level timer functions.
9 ******************************************************************************/
11 /******************************************************************************
13 * (C)Copyright 1998-2002 SysKonnect GmbH.
14 * (C)Copyright 2002-2003 Marvell.
16 * This program is free software; you can redistribute it and/or modify
17 * it under the terms of the GNU General Public License as published by
18 * the Free Software Foundation; either version 2 of the License, or
19 * (at your option) any later version.
21 * The information in this file is provided "AS IS" without warranty.
23 ******************************************************************************/
27 * Event queue and dispatcher
29 #if (defined(DEBUG) || ((!defined(LINT)) && (!defined(SK_SLIM))))
30 static const char SysKonnectFileId
[] =
31 "@(#) $Id: sktimer.c,v 1.14 2003/09/16 13:46:51 rschmidt Exp $ (C) Marvell.";
34 #include "h/skdrv1st.h" /* Driver Specific Definitions */
35 #include "h/skdrv2nd.h" /* Adapter Control- and Driver specific Def. */
39 Event queue management.
49 /* Forward declaration */
50 static void timer_done(SK_AC
*pAC
,SK_IOC Ioc
,int Restart
);
54 * Inits the software timer
56 * needs to be called during Init level 1.
59 SK_AC
*pAC
, /* Adapters context */
60 SK_IOC Ioc
, /* IoContext */
61 int Level
) /* Init Level */
65 pAC
->Tim
.StQueue
= NULL
;
69 SkTimerDone(pAC
, Ioc
);
77 * Stops a high level timer
78 * - If a timer is not in the queue the function returns normally, too.
81 SK_AC
*pAC
, /* Adapters context */
82 SK_IOC Ioc
, /* IoContext */
83 SK_TIMER
*pTimer
) /* Timer Pointer to be started */
89 * remove timer from queue
91 pTimer
->TmActive
= SK_FALSE
;
93 if (pAC
->Tim
.StQueue
== pTimer
&& !pTimer
->TmNext
) {
97 for (ppTimPrev
= &pAC
->Tim
.StQueue
; (pTm
= *ppTimPrev
);
98 ppTimPrev
= &pTm
->TmNext
) {
102 * Timer found in queue
104 * - correct delta of the next timer
106 *ppTimPrev
= pTm
->TmNext
;
109 /* correct delta of next timer in queue */
110 pTm
->TmNext
->TmDelta
+= pTm
->TmDelta
;
118 * Start a high level software timer
121 SK_AC
*pAC
, /* Adapters context */
122 SK_IOC Ioc
, /* IoContext */
123 SK_TIMER
*pTimer
, /* Timer Pointer to be started */
124 SK_U32 Time
, /* Time value */
125 SK_U32 Class
, /* Event Class for this timer */
126 SK_U32 Event
, /* Event Value for this timer */
127 SK_EVPARA Para
) /* Event Parameter for this timer */
129 SK_TIMER
**ppTimPrev
;
133 Time
/= 16; /* input is uS, clock ticks are 16uS */
138 SkTimerStop(pAC
, Ioc
, pTimer
);
140 pTimer
->TmClass
= Class
;
141 pTimer
->TmEvent
= Event
;
142 pTimer
->TmPara
= Para
;
143 pTimer
->TmActive
= SK_TRUE
;
145 if (!pAC
->Tim
.StQueue
) {
146 /* First Timer to be started */
147 pAC
->Tim
.StQueue
= pTimer
;
148 pTimer
->TmNext
= NULL
;
149 pTimer
->TmDelta
= Time
;
151 SkHwtStart(pAC
, Ioc
, Time
);
159 timer_done(pAC
, Ioc
, 0);
162 * find position in queue
165 for (ppTimPrev
= &pAC
->Tim
.StQueue
; (pTm
= *ppTimPrev
);
166 ppTimPrev
= &pTm
->TmNext
) {
168 if (Delta
+ pTm
->TmDelta
> Time
) {
170 /* Here the timer needs to be inserted. */
173 Delta
+= pTm
->TmDelta
;
176 /* insert in queue */
178 pTimer
->TmNext
= pTm
;
179 pTimer
->TmDelta
= Time
- Delta
;
182 /* There is a next timer
183 * -> correct its Delta value.
185 pTm
->TmDelta
-= pTimer
->TmDelta
;
188 /* restart with first */
189 SkHwtStart(pAC
, Ioc
, pAC
->Tim
.StQueue
->TmDelta
);
194 SK_AC
*pAC
, /* Adapters context */
195 SK_IOC Ioc
) /* IoContext */
197 timer_done(pAC
, Ioc
, 1);
201 static void timer_done(
202 SK_AC
*pAC
, /* Adapters context */
203 SK_IOC Ioc
, /* IoContext */
204 int Restart
) /* Do we need to restart the Hardware timer ? */
208 SK_TIMER
*pTComp
; /* Timer completed now now */
209 SK_TIMER
**ppLast
; /* Next field of Last timer to be deq */
212 Delta
= SkHwtRead(pAC
, Ioc
);
214 ppLast
= &pAC
->Tim
.StQueue
;
215 pTm
= pAC
->Tim
.StQueue
;
216 while (pTm
&& !Done
) {
217 if (Delta
>= pTm
->TmDelta
) {
219 pTm
->TmActive
= SK_FALSE
;
220 Delta
-= pTm
->TmDelta
;
221 ppLast
= &pTm
->TmNext
;
225 /* We found the first timer that did not run out */
226 pTm
->TmDelta
-= Delta
;
233 * pTm points to the first Timer that did not run out.
234 * StQueue points to the first Timer that run out.
237 for ( pTComp
= pAC
->Tim
.StQueue
; pTComp
; pTComp
= pTComp
->TmNext
) {
238 SkEventQueue(pAC
,pTComp
->TmClass
, pTComp
->TmEvent
, pTComp
->TmPara
);
241 /* Set head of timer queue to the first timer that did not run out */
242 pAC
->Tim
.StQueue
= pTm
;
244 if (Restart
&& pAC
->Tim
.StQueue
) {
245 /* Restart HW timer */
246 SkHwtStart(pAC
, Ioc
, pAC
->Tim
.StQueue
->TmDelta
);