diff options
Diffstat (limited to 'drivers/net/sk98lin/sktimer.c')
-rw-r--r-- | drivers/net/sk98lin/sktimer.c | 250 |
1 files changed, 250 insertions, 0 deletions
diff --git a/drivers/net/sk98lin/sktimer.c b/drivers/net/sk98lin/sktimer.c new file mode 100644 index 000000000000..4e462955ecd8 --- /dev/null +++ b/drivers/net/sk98lin/sktimer.c | |||
@@ -0,0 +1,250 @@ | |||
1 | /****************************************************************************** | ||
2 | * | ||
3 | * Name: sktimer.c | ||
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. | ||
8 | * | ||
9 | ******************************************************************************/ | ||
10 | |||
11 | /****************************************************************************** | ||
12 | * | ||
13 | * (C)Copyright 1998-2002 SysKonnect GmbH. | ||
14 | * (C)Copyright 2002-2003 Marvell. | ||
15 | * | ||
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. | ||
20 | * | ||
21 | * The information in this file is provided "AS IS" without warranty. | ||
22 | * | ||
23 | ******************************************************************************/ | ||
24 | |||
25 | |||
26 | /* | ||
27 | * Event queue and dispatcher | ||
28 | */ | ||
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."; | ||
32 | #endif | ||
33 | |||
34 | #include "h/skdrv1st.h" /* Driver Specific Definitions */ | ||
35 | #include "h/skdrv2nd.h" /* Adapter Control- and Driver specific Def. */ | ||
36 | |||
37 | #ifdef __C2MAN__ | ||
38 | /* | ||
39 | Event queue management. | ||
40 | |||
41 | General Description: | ||
42 | |||
43 | */ | ||
44 | intro() | ||
45 | {} | ||
46 | #endif | ||
47 | |||
48 | |||
49 | /* Forward declaration */ | ||
50 | static void timer_done(SK_AC *pAC,SK_IOC Ioc,int Restart); | ||
51 | |||
52 | |||
53 | /* | ||
54 | * Inits the software timer | ||
55 | * | ||
56 | * needs to be called during Init level 1. | ||
57 | */ | ||
58 | void SkTimerInit( | ||
59 | SK_AC *pAC, /* Adapters context */ | ||
60 | SK_IOC Ioc, /* IoContext */ | ||
61 | int Level) /* Init Level */ | ||
62 | { | ||
63 | switch (Level) { | ||
64 | case SK_INIT_DATA: | ||
65 | pAC->Tim.StQueue = NULL; | ||
66 | break; | ||
67 | case SK_INIT_IO: | ||
68 | SkHwtInit(pAC, Ioc); | ||
69 | SkTimerDone(pAC, Ioc); | ||
70 | break; | ||
71 | default: | ||
72 | break; | ||
73 | } | ||
74 | } | ||
75 | |||
76 | /* | ||
77 | * Stops a high level timer | ||
78 | * - If a timer is not in the queue the function returns normally, too. | ||
79 | */ | ||
80 | void SkTimerStop( | ||
81 | SK_AC *pAC, /* Adapters context */ | ||
82 | SK_IOC Ioc, /* IoContext */ | ||
83 | SK_TIMER *pTimer) /* Timer Pointer to be started */ | ||
84 | { | ||
85 | SK_TIMER **ppTimPrev; | ||
86 | SK_TIMER *pTm; | ||
87 | |||
88 | /* | ||
89 | * remove timer from queue | ||
90 | */ | ||
91 | pTimer->TmActive = SK_FALSE; | ||
92 | |||
93 | if (pAC->Tim.StQueue == pTimer && !pTimer->TmNext) { | ||
94 | SkHwtStop(pAC, Ioc); | ||
95 | } | ||
96 | |||
97 | for (ppTimPrev = &pAC->Tim.StQueue; (pTm = *ppTimPrev); | ||
98 | ppTimPrev = &pTm->TmNext ) { | ||
99 | |||
100 | if (pTm == pTimer) { | ||
101 | /* | ||
102 | * Timer found in queue | ||
103 | * - dequeue it and | ||
104 | * - correct delta of the next timer | ||
105 | */ | ||
106 | *ppTimPrev = pTm->TmNext; | ||
107 | |||
108 | if (pTm->TmNext) { | ||
109 | /* correct delta of next timer in queue */ | ||
110 | pTm->TmNext->TmDelta += pTm->TmDelta; | ||
111 | } | ||
112 | return; | ||
113 | } | ||
114 | } | ||
115 | } | ||
116 | |||
117 | /* | ||
118 | * Start a high level software timer | ||
119 | */ | ||
120 | void SkTimerStart( | ||
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 */ | ||
128 | { | ||
129 | SK_TIMER **ppTimPrev; | ||
130 | SK_TIMER *pTm; | ||
131 | SK_U32 Delta; | ||
132 | |||
133 | Time /= 16; /* input is uS, clock ticks are 16uS */ | ||
134 | |||
135 | if (!Time) | ||
136 | Time = 1; | ||
137 | |||
138 | SkTimerStop(pAC, Ioc, pTimer); | ||
139 | |||
140 | pTimer->TmClass = Class; | ||
141 | pTimer->TmEvent = Event; | ||
142 | pTimer->TmPara = Para; | ||
143 | pTimer->TmActive = SK_TRUE; | ||
144 | |||
145 | if (!pAC->Tim.StQueue) { | ||
146 | /* First Timer to be started */ | ||
147 | pAC->Tim.StQueue = pTimer; | ||
148 | pTimer->TmNext = NULL; | ||
149 | pTimer->TmDelta = Time; | ||
150 | |||
151 | SkHwtStart(pAC, Ioc, Time); | ||
152 | |||
153 | return; | ||
154 | } | ||
155 | |||
156 | /* | ||
157 | * timer correction | ||
158 | */ | ||
159 | timer_done(pAC, Ioc, 0); | ||
160 | |||
161 | /* | ||
162 | * find position in queue | ||
163 | */ | ||
164 | Delta = 0; | ||
165 | for (ppTimPrev = &pAC->Tim.StQueue; (pTm = *ppTimPrev); | ||
166 | ppTimPrev = &pTm->TmNext ) { | ||
167 | |||
168 | if (Delta + pTm->TmDelta > Time) { | ||
169 | /* Position found */ | ||
170 | /* Here the timer needs to be inserted. */ | ||
171 | break; | ||
172 | } | ||
173 | Delta += pTm->TmDelta; | ||
174 | } | ||
175 | |||
176 | /* insert in queue */ | ||
177 | *ppTimPrev = pTimer; | ||
178 | pTimer->TmNext = pTm; | ||
179 | pTimer->TmDelta = Time - Delta; | ||
180 | |||
181 | if (pTm) { | ||
182 | /* There is a next timer | ||
183 | * -> correct its Delta value. | ||
184 | */ | ||
185 | pTm->TmDelta -= pTimer->TmDelta; | ||
186 | } | ||
187 | |||
188 | /* restart with first */ | ||
189 | SkHwtStart(pAC, Ioc, pAC->Tim.StQueue->TmDelta); | ||
190 | } | ||
191 | |||
192 | |||
193 | void SkTimerDone( | ||
194 | SK_AC *pAC, /* Adapters context */ | ||
195 | SK_IOC Ioc) /* IoContext */ | ||
196 | { | ||
197 | timer_done(pAC, Ioc, 1); | ||
198 | } | ||
199 | |||
200 | |||
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 ? */ | ||
205 | { | ||
206 | SK_U32 Delta; | ||
207 | SK_TIMER *pTm; | ||
208 | SK_TIMER *pTComp; /* Timer completed now now */ | ||
209 | SK_TIMER **ppLast; /* Next field of Last timer to be deq */ | ||
210 | int Done = 0; | ||
211 | |||
212 | Delta = SkHwtRead(pAC, Ioc); | ||
213 | |||
214 | ppLast = &pAC->Tim.StQueue; | ||
215 | pTm = pAC->Tim.StQueue; | ||
216 | while (pTm && !Done) { | ||
217 | if (Delta >= pTm->TmDelta) { | ||
218 | /* Timer ran out */ | ||
219 | pTm->TmActive = SK_FALSE; | ||
220 | Delta -= pTm->TmDelta; | ||
221 | ppLast = &pTm->TmNext; | ||
222 | pTm = pTm->TmNext; | ||
223 | } | ||
224 | else { | ||
225 | /* We found the first timer that did not run out */ | ||
226 | pTm->TmDelta -= Delta; | ||
227 | Delta = 0; | ||
228 | Done = 1; | ||
229 | } | ||
230 | } | ||
231 | *ppLast = NULL; | ||
232 | /* | ||
233 | * pTm points to the first Timer that did not run out. | ||
234 | * StQueue points to the first Timer that run out. | ||
235 | */ | ||
236 | |||
237 | for ( pTComp = pAC->Tim.StQueue; pTComp; pTComp = pTComp->TmNext) { | ||
238 | SkEventQueue(pAC,pTComp->TmClass, pTComp->TmEvent, pTComp->TmPara); | ||
239 | } | ||
240 | |||
241 | /* Set head of timer queue to the first timer that did not run out */ | ||
242 | pAC->Tim.StQueue = pTm; | ||
243 | |||
244 | if (Restart && pAC->Tim.StQueue) { | ||
245 | /* Restart HW timer */ | ||
246 | SkHwtStart(pAC, Ioc, pAC->Tim.StQueue->TmDelta); | ||
247 | } | ||
248 | } | ||
249 | |||
250 | /* End of file */ | ||