blob: 37cd4c9fe118158e1337dd8096e2a08410f331e3 [file] [log] [blame]
wdenkeb20ad32003-09-05 23:19:14 +00001/******************************************************************************
2 *
3 * Name: sktimer.c
4 * Project: GEnesis, PCI Gigabit Ethernet Adapter
5 * Version: $Revision: 1.12 $
6 * Date: $Date: 1999/11/22 13:38:51 $
7 * Purpose: High level timer functions.
8 *
9 ******************************************************************************/
10
11/******************************************************************************
12 *
13 * (C)Copyright 1998,1999 SysKonnect,
14 * a business unit of Schneider & Koch & Co. Datensysteme GmbH.
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 * History:
28 *
29 * $Log: sktimer.c,v $
30 * Revision 1.12 1999/11/22 13:38:51 cgoos
31 * Changed license header to GPL.
wdenk9c53f402003-10-15 23:53:47 +000032 *
wdenkeb20ad32003-09-05 23:19:14 +000033 * Revision 1.11 1998/12/17 13:24:13 gklug
34 * fix: restart problem: do NOT destroy timer queue if init 1 is done
wdenk9c53f402003-10-15 23:53:47 +000035 *
wdenkeb20ad32003-09-05 23:19:14 +000036 * Revision 1.10 1998/10/15 15:11:36 gklug
37 * fix: ID_sccs to SysKonnectFileId
wdenk9c53f402003-10-15 23:53:47 +000038 *
wdenkeb20ad32003-09-05 23:19:14 +000039 * Revision 1.9 1998/09/15 15:15:04 cgoos
40 * Changed TRUE/FALSE to SK_TRUE/SK_FALSE
wdenk9c53f402003-10-15 23:53:47 +000041 *
wdenkeb20ad32003-09-05 23:19:14 +000042 * Revision 1.8 1998/09/08 08:47:55 gklug
43 * add: init level handling
wdenk9c53f402003-10-15 23:53:47 +000044 *
wdenkeb20ad32003-09-05 23:19:14 +000045 * Revision 1.7 1998/08/19 09:50:53 gklug
46 * fix: remove struct keyword from c-code (see CCC) add typedefs
wdenk9c53f402003-10-15 23:53:47 +000047 *
wdenkeb20ad32003-09-05 23:19:14 +000048 * Revision 1.6 1998/08/17 13:43:13 gklug
49 * chg: Parameter will be union of 64bit para, 2 times SK_U32 or SK_PTR
wdenk9c53f402003-10-15 23:53:47 +000050 *
wdenkeb20ad32003-09-05 23:19:14 +000051 * Revision 1.5 1998/08/14 07:09:14 gklug
52 * fix: chg pAc -> pAC
wdenk9c53f402003-10-15 23:53:47 +000053 *
wdenkeb20ad32003-09-05 23:19:14 +000054 * Revision 1.4 1998/08/07 12:53:46 gklug
55 * fix: first compiled version
wdenk9c53f402003-10-15 23:53:47 +000056 *
wdenkeb20ad32003-09-05 23:19:14 +000057 * Revision 1.3 1998/08/07 09:31:53 gklug
58 * fix: delta spelling
wdenk9c53f402003-10-15 23:53:47 +000059 *
wdenkeb20ad32003-09-05 23:19:14 +000060 * Revision 1.2 1998/08/07 09:31:02 gklug
61 * adapt functions to new c coding conventions
62 * rmv: "fast" handling
63 * chg: inserting of new timer in queue.
64 * chg: event queue generation when timer runs out
wdenk9c53f402003-10-15 23:53:47 +000065 *
wdenkeb20ad32003-09-05 23:19:14 +000066 * Revision 1.1 1998/08/05 11:27:55 gklug
67 * first version: adapted from SMT
wdenk9c53f402003-10-15 23:53:47 +000068 *
69 *
70 *
wdenkeb20ad32003-09-05 23:19:14 +000071 *
72 ******************************************************************************/
73
74
wdenkde887eb2003-09-10 18:20:28 +000075#include <config.h>
76
77#ifdef CONFIG_SK98
78
wdenkeb20ad32003-09-05 23:19:14 +000079/*
80 Event queue and dispatcher
81*/
82static const char SysKonnectFileId[] =
83 "$Header: /usr56/projects/ge/schedule/sktimer.c,v 1.12 1999/11/22 13:38:51 cgoos Exp $" ;
84
85#include "h/skdrv1st.h" /* Driver Specific Definitions */
86#include "h/skdrv2nd.h" /* Adapter Control- and Driver specific Def. */
87
88#ifdef __C2MAN__
89/*
90 Event queue management.
91
92 General Description:
93
94 */
95intro()
96{}
97#endif
98
99
100/* Forward declaration */
101static void timer_done(SK_AC *pAC,SK_IOC Ioc,int Restart);
102
103
104/*
105 * Inits the software timer
106 *
107 * needs to be called during Init level 1.
108 */
109void SkTimerInit(
110SK_AC *pAC, /* Adapters context */
111SK_IOC Ioc, /* IoContext */
112int Level) /* Init Level */
113{
114 switch (Level) {
115 case SK_INIT_DATA:
116 pAC->Tim.StQueue = 0 ;
117 break;
118 case SK_INIT_IO:
119 SkHwtInit(pAC,Ioc) ;
120 SkTimerDone(pAC, Ioc);
121 break;
122 default:
123 break;
124 }
125}
126
127/*
128 * Stops a high level timer
129 * - If a timer is not in the queue the function returns normally, too.
130 */
131void SkTimerStop(
132SK_AC *pAC, /* Adapters context */
133SK_IOC Ioc, /* IoContext */
134SK_TIMER *pTimer) /* Timer Pointer to be started */
135{
136 SK_TIMER **ppTimPrev ;
137 SK_TIMER *pTm ;
138
139 /*
140 * remove timer from queue
141 */
142 pTimer->TmActive = SK_FALSE ;
143 if (pAC->Tim.StQueue == pTimer && !pTimer->TmNext) {
144 SkHwtStop(pAC,Ioc) ;
145 }
146 for (ppTimPrev = &pAC->Tim.StQueue ; (pTm = *ppTimPrev) ;
147 ppTimPrev = &pTm->TmNext ) {
148 if (pTm == pTimer) {
149 /*
150 * Timer found in queue
151 * - dequeue it and
152 * - correct delta of the next timer
153 */
154 *ppTimPrev = pTm->TmNext ;
155
156 if (pTm->TmNext) {
157 /* correct delta of next timer in queue */
158 pTm->TmNext->TmDelta += pTm->TmDelta ;
159 }
160 return ;
161 }
162 }
163}
164
165/*
166 * Start a high level software timer
167 */
168void SkTimerStart(
169SK_AC *pAC, /* Adapters context */
170SK_IOC Ioc, /* IoContext */
171SK_TIMER *pTimer, /* Timer Pointer to be started */
172SK_U32 Time, /* Time value */
173SK_U32 Class, /* Event Class for this timer */
174SK_U32 Event, /* Event Value for this timer */
175SK_EVPARA Para) /* Event Parameter for this timer */
176{
177 SK_TIMER **ppTimPrev ;
178 SK_TIMER *pTm ;
179 SK_U32 Delta ;
180
181 Time /= 16 ; /* input is uS, clock ticks are 16uS */
182 if (!Time)
183 Time = 1 ;
184
185 SkTimerStop(pAC,Ioc,pTimer) ;
186
187 pTimer->TmClass = Class ;
188 pTimer->TmEvent = Event ;
189 pTimer->TmPara = Para ;
190 pTimer->TmActive = SK_TRUE ;
191
192 if (!pAC->Tim.StQueue) {
193 /* First Timer to be started */
194 pAC->Tim.StQueue = pTimer ;
195 pTimer->TmNext = 0 ;
196 pTimer->TmDelta = Time ;
197 SkHwtStart(pAC,Ioc,Time) ;
198 return ;
199 }
200
201 /*
202 * timer correction
203 */
204 timer_done(pAC,Ioc,0) ;
205
206 /*
207 * find position in queue
208 */
209 Delta = 0 ;
210 for (ppTimPrev = &pAC->Tim.StQueue ; (pTm = *ppTimPrev) ;
211 ppTimPrev = &pTm->TmNext ) {
212 if (Delta + pTm->TmDelta > Time) {
213 /* Position found */
214 /* Here the timer needs to be inserted. */
215 break ;
216 }
217 Delta += pTm->TmDelta ;
218 }
219
220 /* insert in queue */
221 *ppTimPrev = pTimer ;
222 pTimer->TmNext = pTm ;
223 pTimer->TmDelta = Time - Delta ;
224
225 if (pTm) {
226 /* There is a next timer
227 * -> correct its Delta value.
228 */
229 pTm->TmDelta -= pTimer->TmDelta ;
230 }
231
232 /*
233 * start new with first
234 */
235 SkHwtStart(pAC,Ioc,pAC->Tim.StQueue->TmDelta) ;
236}
237
238
239void SkTimerDone(
240SK_AC *pAC, /* Adapters context */
241SK_IOC Ioc) /* IoContext */
242{
243 timer_done(pAC,Ioc,1) ;
244}
245
246
247static void timer_done(
248SK_AC *pAC, /* Adapters context */
249SK_IOC Ioc, /* IoContext */
250int Restart) /* Do we need to restart the Hardware timer ? */
251{
252 SK_U32 Delta ;
253 SK_TIMER *pTm ;
254 SK_TIMER *pTComp ; /* Timer completed now now */
255 SK_TIMER **ppLast ; /* Next field of Last timer to be deq */
256 int Done = 0 ;
257
258 Delta = SkHwtRead(pAC,Ioc) ;
259 ppLast = &pAC->Tim.StQueue ;
260 pTm = pAC->Tim.StQueue ;
261 while (pTm && !Done) {
262 if (Delta >= pTm->TmDelta) {
263 /* Timer ran out */
264 pTm->TmActive = SK_FALSE ;
265 Delta -= pTm->TmDelta ;
266 ppLast = &pTm->TmNext ;
267 pTm = pTm->TmNext ;
268 } else {
269 /* We found the first timer that did not run out */
270 pTm->TmDelta -= Delta ;
271 Delta = 0 ;
272 Done = 1 ;
273 }
274 }
275 *ppLast = 0 ;
276 /*
277 * pTm points to the first Timer that did not run out.
278 * StQueue points to the first Timer that run out.
279 */
280
281 for ( pTComp = pAC->Tim.StQueue ; pTComp ; pTComp = pTComp->TmNext) {
282 SkEventQueue(pAC,pTComp->TmClass, pTComp->TmEvent,
283 pTComp->TmPara) ;
284 }
285
286 /* Set head of timer queue to the first timer that did not run out */
287 pAC->Tim.StQueue = pTm ;
288
289 if (Restart && pAC->Tim.StQueue) {
290 /* Restart HW timer */
291 SkHwtStart(pAC,Ioc,pAC->Tim.StQueue->TmDelta) ;
292 }
293}
294
wdenkde887eb2003-09-10 18:20:28 +0000295#endif /* CONFIG_SK98 */
296
wdenkeb20ad32003-09-05 23:19:14 +0000297/* End of file */