1 /******************************************************************************
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.
9 ******************************************************************************/
11 /******************************************************************************
13 * (C)Copyright 1998,1999 SysKonnect,
14 * a business unit of Schneider & Koch & Co. Datensysteme GmbH.
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 ******************************************************************************/
25 /******************************************************************************
30 * Revision 1.12 1999/11/22 13:38:51 cgoos
31 * Changed license header to GPL.
33 * Revision 1.11 1998/12/17 13:24:13 gklug
34 * fix: restart problem: do NOT destroy timer queue if init 1 is done
36 * Revision 1.10 1998/10/15 15:11:36 gklug
37 * fix: ID_sccs to SysKonnectFileId
39 * Revision 1.9 1998/09/15 15:15:04 cgoos
40 * Changed TRUE/FALSE to SK_TRUE/SK_FALSE
42 * Revision 1.8 1998/09/08 08:47:55 gklug
43 * add: init level handling
45 * Revision 1.7 1998/08/19 09:50:53 gklug
46 * fix: remove struct keyword from c-code (see CCC) add typedefs
48 * 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
51 * Revision 1.5 1998/08/14 07:09:14 gklug
54 * Revision 1.4 1998/08/07 12:53:46 gklug
55 * fix: first compiled version
57 * Revision 1.3 1998/08/07 09:31:53 gklug
60 * 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
66 * Revision 1.1 1998/08/05 11:27:55 gklug
67 * first version: adapted from SMT
72 ******************************************************************************/
78 Event queue and dispatcher
80 static const char SysKonnectFileId[] =
81 "$Header: /usr56/projects/ge/schedule/sktimer.c,v 1.12 1999/11/22 13:38:51 cgoos Exp $" ;
83 #include "h/skdrv1st.h" /* Driver Specific Definitions */
84 #include "h/skdrv2nd.h" /* Adapter Control- and Driver specific Def. */
88 Event queue management.
98 /* Forward declaration */
99 static void timer_done(SK_AC *pAC,SK_IOC Ioc,int Restart);
103 * Inits the software timer
105 * needs to be called during Init level 1.
108 SK_AC *pAC, /* Adapters context */
109 SK_IOC Ioc, /* IoContext */
110 int Level) /* Init Level */
114 pAC->Tim.StQueue = 0 ;
118 SkTimerDone(pAC, Ioc);
126 * Stops a high level timer
127 * - If a timer is not in the queue the function returns normally, too.
130 SK_AC *pAC, /* Adapters context */
131 SK_IOC Ioc, /* IoContext */
132 SK_TIMER *pTimer) /* Timer Pointer to be started */
134 SK_TIMER **ppTimPrev ;
138 * remove timer from queue
140 pTimer->TmActive = SK_FALSE ;
141 if (pAC->Tim.StQueue == pTimer && !pTimer->TmNext) {
144 for (ppTimPrev = &pAC->Tim.StQueue ; (pTm = *ppTimPrev) ;
145 ppTimPrev = &pTm->TmNext ) {
148 * Timer found in queue
150 * - correct delta of the next timer
152 *ppTimPrev = pTm->TmNext ;
155 /* correct delta of next timer in queue */
156 pTm->TmNext->TmDelta += pTm->TmDelta ;
164 * Start a high level software timer
167 SK_AC *pAC, /* Adapters context */
168 SK_IOC Ioc, /* IoContext */
169 SK_TIMER *pTimer, /* Timer Pointer to be started */
170 SK_U32 Time, /* Time value */
171 SK_U32 Class, /* Event Class for this timer */
172 SK_U32 Event, /* Event Value for this timer */
173 SK_EVPARA Para) /* Event Parameter for this timer */
175 SK_TIMER **ppTimPrev ;
179 Time /= 16 ; /* input is uS, clock ticks are 16uS */
183 SkTimerStop(pAC,Ioc,pTimer) ;
185 pTimer->TmClass = Class ;
186 pTimer->TmEvent = Event ;
187 pTimer->TmPara = Para ;
188 pTimer->TmActive = SK_TRUE ;
190 if (!pAC->Tim.StQueue) {
191 /* First Timer to be started */
192 pAC->Tim.StQueue = pTimer ;
194 pTimer->TmDelta = Time ;
195 SkHwtStart(pAC,Ioc,Time) ;
202 timer_done(pAC,Ioc,0) ;
205 * find position in queue
208 for (ppTimPrev = &pAC->Tim.StQueue ; (pTm = *ppTimPrev) ;
209 ppTimPrev = &pTm->TmNext ) {
210 if (Delta + pTm->TmDelta > Time) {
212 /* Here the timer needs to be inserted. */
215 Delta += pTm->TmDelta ;
218 /* insert in queue */
219 *ppTimPrev = pTimer ;
220 pTimer->TmNext = pTm ;
221 pTimer->TmDelta = Time - Delta ;
224 /* There is a next timer
225 * -> correct its Delta value.
227 pTm->TmDelta -= pTimer->TmDelta ;
231 * start new with first
233 SkHwtStart(pAC,Ioc,pAC->Tim.StQueue->TmDelta) ;
238 SK_AC *pAC, /* Adapters context */
239 SK_IOC Ioc) /* IoContext */
241 timer_done(pAC,Ioc,1) ;
245 static void timer_done(
246 SK_AC *pAC, /* Adapters context */
247 SK_IOC Ioc, /* IoContext */
248 int Restart) /* Do we need to restart the Hardware timer ? */
252 SK_TIMER *pTComp ; /* Timer completed now now */
253 SK_TIMER **ppLast ; /* Next field of Last timer to be deq */
256 Delta = SkHwtRead(pAC,Ioc) ;
257 ppLast = &pAC->Tim.StQueue ;
258 pTm = pAC->Tim.StQueue ;
259 while (pTm && !Done) {
260 if (Delta >= pTm->TmDelta) {
262 pTm->TmActive = SK_FALSE ;
263 Delta -= pTm->TmDelta ;
264 ppLast = &pTm->TmNext ;
267 /* We found the first timer that did not run out */
268 pTm->TmDelta -= Delta ;
275 * pTm points to the first Timer that did not run out.
276 * StQueue points to the first Timer that run out.
279 for ( pTComp = pAC->Tim.StQueue ; pTComp ; pTComp = pTComp->TmNext) {
280 SkEventQueue(pAC,pTComp->TmClass, pTComp->TmEvent,
284 /* Set head of timer queue to the first timer that did not run out */
285 pAC->Tim.StQueue = pTm ;
287 if (Restart && pAC->Tim.StQueue) {
288 /* Restart HW timer */
289 SkHwtStart(pAC,Ioc,pAC->Tim.StQueue->TmDelta) ;