uboot/drivers/net/sk98lin/sktimer.c
<<
>>
Prefs
   1/******************************************************************************
   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.
  32 *
  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
  35 *
  36 *      Revision 1.10  1998/10/15 15:11:36  gklug
  37 *      fix: ID_sccs to SysKonnectFileId
  38 *
  39 *      Revision 1.9  1998/09/15 15:15:04  cgoos
  40 *      Changed TRUE/FALSE to SK_TRUE/SK_FALSE
  41 *
  42 *      Revision 1.8  1998/09/08 08:47:55  gklug
  43 *      add: init level handling
  44 *
  45 *      Revision 1.7  1998/08/19 09:50:53  gklug
  46 *      fix: remove struct keyword from c-code (see CCC) add typedefs
  47 *
  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
  50 *
  51 *      Revision 1.5  1998/08/14 07:09:14  gklug
  52 *      fix: chg pAc -> pAC
  53 *
  54 *      Revision 1.4  1998/08/07 12:53:46  gklug
  55 *      fix: first compiled version
  56 *
  57 *      Revision 1.3  1998/08/07 09:31:53  gklug
  58 *      fix: delta spelling
  59 *
  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
  65 *
  66 *      Revision 1.1  1998/08/05 11:27:55  gklug
  67 *      first version: adapted from SMT
  68 *
  69 *
  70 *
  71 *
  72 ******************************************************************************/
  73
  74
  75#include <config.h>
  76
  77/*
  78        Event queue and dispatcher
  79*/
  80static const char SysKonnectFileId[] =
  81        "$Header: /usr56/projects/ge/schedule/sktimer.c,v 1.12 1999/11/22 13:38:51 cgoos Exp $" ;
  82
  83#include "h/skdrv1st.h"         /* Driver Specific Definitions */
  84#include "h/skdrv2nd.h"         /* Adapter Control- and Driver specific Def. */
  85
  86#ifdef __C2MAN__
  87/*
  88        Event queue management.
  89
  90        General Description:
  91
  92 */
  93intro()
  94{}
  95#endif
  96
  97
  98/* Forward declaration */
  99static void timer_done(SK_AC *pAC,SK_IOC Ioc,int Restart);
 100
 101
 102/*
 103 * Inits the software timer
 104 *
 105 * needs to be called during Init level 1.
 106 */
 107void    SkTimerInit(
 108SK_AC   *pAC,           /* Adapters context */
 109SK_IOC  Ioc,            /* IoContext */
 110int     Level)          /* Init Level */
 111{
 112        switch (Level) {
 113        case SK_INIT_DATA:
 114                pAC->Tim.StQueue = 0 ;
 115                break;
 116        case SK_INIT_IO:
 117                SkHwtInit(pAC,Ioc) ;
 118                SkTimerDone(pAC, Ioc);
 119                break;
 120        default:
 121                break;
 122        }
 123}
 124
 125/*
 126 * Stops a high level timer
 127 * - If a timer is not in the queue the function returns normally, too.
 128 */
 129void    SkTimerStop(
 130SK_AC           *pAC,           /* Adapters context */
 131SK_IOC          Ioc,            /* IoContext */
 132SK_TIMER        *pTimer)        /* Timer Pointer to be started */
 133{
 134        SK_TIMER        **ppTimPrev ;
 135        SK_TIMER        *pTm ;
 136
 137        /*
 138         * remove timer from queue
 139         */
 140        pTimer->TmActive = SK_FALSE ;
 141        if (pAC->Tim.StQueue == pTimer && !pTimer->TmNext) {
 142                SkHwtStop(pAC,Ioc) ;
 143        }
 144        for (ppTimPrev = &pAC->Tim.StQueue ; (pTm = *ppTimPrev) ;
 145                ppTimPrev = &pTm->TmNext ) {
 146                if (pTm == pTimer) {
 147                        /*
 148                         * Timer found in queue
 149                         * - dequeue it and
 150                         * - correct delta of the next timer
 151                         */
 152                        *ppTimPrev = pTm->TmNext ;
 153
 154                        if (pTm->TmNext) {
 155                                /* correct delta of next timer in queue */
 156                                pTm->TmNext->TmDelta += pTm->TmDelta ;
 157                        }
 158                        return ;
 159                }
 160        }
 161}
 162
 163/*
 164 * Start a high level software timer
 165 */
 166void    SkTimerStart(
 167SK_AC           *pAC,           /* Adapters context */
 168SK_IOC          Ioc,            /* IoContext */
 169SK_TIMER        *pTimer,        /* Timer Pointer to be started */
 170SK_U32          Time,           /* Time value */
 171SK_U32          Class,          /* Event Class for this timer */
 172SK_U32          Event,          /* Event Value for this timer */
 173SK_EVPARA       Para)           /* Event Parameter for this timer */
 174{
 175        SK_TIMER        **ppTimPrev ;
 176        SK_TIMER        *pTm ;
 177        SK_U32          Delta ;
 178
 179        Time /= 16 ;            /* input is uS, clock ticks are 16uS */
 180        if (!Time)
 181                Time = 1 ;
 182
 183        SkTimerStop(pAC,Ioc,pTimer) ;
 184
 185        pTimer->TmClass = Class ;
 186        pTimer->TmEvent = Event ;
 187        pTimer->TmPara = Para ;
 188        pTimer->TmActive = SK_TRUE ;
 189
 190        if (!pAC->Tim.StQueue) {
 191                /* First Timer to be started */
 192                pAC->Tim.StQueue = pTimer ;
 193                pTimer->TmNext = 0 ;
 194                pTimer->TmDelta = Time ;
 195                SkHwtStart(pAC,Ioc,Time) ;
 196                return ;
 197        }
 198
 199        /*
 200         * timer correction
 201         */
 202        timer_done(pAC,Ioc,0) ;
 203
 204        /*
 205         * find position in queue
 206         */
 207        Delta = 0 ;
 208        for (ppTimPrev = &pAC->Tim.StQueue ; (pTm = *ppTimPrev) ;
 209                ppTimPrev = &pTm->TmNext ) {
 210                if (Delta + pTm->TmDelta > Time) {
 211                        /* Position found */
 212                        /* Here the timer needs to be inserted. */
 213                        break ;
 214                }
 215                Delta += pTm->TmDelta ;
 216        }
 217
 218        /* insert in queue */
 219        *ppTimPrev = pTimer ;
 220        pTimer->TmNext = pTm ;
 221        pTimer->TmDelta = Time - Delta ;
 222
 223        if (pTm) {
 224                /* There is a next timer
 225                 * -> correct its Delta value.
 226                 */
 227                pTm->TmDelta -= pTimer->TmDelta ;
 228        }
 229
 230        /*
 231         * start new with first
 232         */
 233        SkHwtStart(pAC,Ioc,pAC->Tim.StQueue->TmDelta) ;
 234}
 235
 236
 237void    SkTimerDone(
 238SK_AC   *pAC,           /* Adapters context */
 239SK_IOC  Ioc)            /* IoContext */
 240{
 241        timer_done(pAC,Ioc,1) ;
 242}
 243
 244
 245static void     timer_done(
 246SK_AC   *pAC,           /* Adapters context */
 247SK_IOC  Ioc,            /* IoContext */
 248int     Restart)        /* Do we need to restart the Hardware timer ? */
 249{
 250        SK_U32          Delta ;
 251        SK_TIMER        *pTm ;
 252        SK_TIMER        *pTComp ;       /* Timer completed now now */
 253        SK_TIMER        **ppLast ;      /* Next field of Last timer to be deq */
 254        int             Done = 0 ;
 255
 256        Delta = SkHwtRead(pAC,Ioc) ;
 257        ppLast = &pAC->Tim.StQueue ;
 258        pTm = pAC->Tim.StQueue ;
 259        while (pTm && !Done) {
 260                if (Delta >= pTm->TmDelta) {
 261                        /* Timer ran out */
 262                        pTm->TmActive = SK_FALSE ;
 263                        Delta -= pTm->TmDelta ;
 264                        ppLast = &pTm->TmNext ;
 265                        pTm = pTm->TmNext ;
 266                } else {
 267                        /* We found the first timer that did not run out */
 268                        pTm->TmDelta -= Delta ;
 269                        Delta = 0 ;
 270                        Done = 1 ;
 271                }
 272        }
 273        *ppLast = 0 ;
 274        /*
 275         * pTm points to the first Timer that did not run out.
 276         * StQueue points to the first Timer that run out.
 277         */
 278
 279        for ( pTComp = pAC->Tim.StQueue ; pTComp ; pTComp = pTComp->TmNext) {
 280                SkEventQueue(pAC,pTComp->TmClass, pTComp->TmEvent,
 281                        pTComp->TmPara) ;
 282        }
 283
 284        /* Set head of timer queue to the first timer that did not run out */
 285        pAC->Tim.StQueue = pTm ;
 286
 287        if (Restart && pAC->Tim.StQueue) {
 288                /* Restart HW timer */
 289                SkHwtStart(pAC,Ioc,pAC->Tim.StQueue->TmDelta) ;
 290        }
 291}
 292
 293/* End of file */
 294