linux/drivers/net/fddi/skfp/smttimer.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-or-later
   2/******************************************************************************
   3 *
   4 *      (C)Copyright 1998,1999 SysKonnect,
   5 *      a business unit of Schneider & Koch & Co. Datensysteme GmbH.
   6 *
   7 *      See the file "skfddi.c" for further information.
   8 *
   9 *      The information in this file is provided "AS IS" without warranty.
  10 *
  11 ******************************************************************************/
  12
  13/*
  14        SMT timer
  15*/
  16
  17#include "h/types.h"
  18#include "h/fddi.h"
  19#include "h/smc.h"
  20
  21#ifndef lint
  22static const char ID_sccs[] = "@(#)smttimer.c   2.4 97/08/04 (C) SK " ;
  23#endif
  24
  25static void timer_done(struct s_smc *smc, int restart);
  26
  27void smt_timer_init(struct s_smc *smc)
  28{
  29        smc->t.st_queue = NULL;
  30        smc->t.st_fast.tm_active = FALSE ;
  31        smc->t.st_fast.tm_next = NULL;
  32        hwt_init(smc) ;
  33}
  34
  35void smt_timer_stop(struct s_smc *smc, struct smt_timer *timer)
  36{
  37        struct smt_timer        **prev ;
  38        struct smt_timer        *tm ;
  39
  40        /*
  41         * remove timer from queue
  42         */
  43        timer->tm_active = FALSE ;
  44        if (smc->t.st_queue == timer && !timer->tm_next) {
  45                hwt_stop(smc) ;
  46        }
  47        for (prev = &smc->t.st_queue ; (tm = *prev) ; prev = &tm->tm_next ) {
  48                if (tm == timer) {
  49                        *prev = tm->tm_next ;
  50                        if (tm->tm_next) {
  51                                tm->tm_next->tm_delta += tm->tm_delta ;
  52                        }
  53                        return ;
  54                }
  55        }
  56}
  57
  58void smt_timer_start(struct s_smc *smc, struct smt_timer *timer, u_long time,
  59                     u_long token)
  60{
  61        struct smt_timer        **prev ;
  62        struct smt_timer        *tm ;
  63        u_long                  delta = 0 ;
  64
  65        time /= 16 ;            /* input is uS, clock ticks are 16uS */
  66        if (!time)
  67                time = 1 ;
  68        smt_timer_stop(smc,timer) ;
  69        timer->tm_smc = smc ;
  70        timer->tm_token = token ;
  71        timer->tm_active = TRUE ;
  72        if (!smc->t.st_queue) {
  73                smc->t.st_queue = timer ;
  74                timer->tm_next = NULL;
  75                timer->tm_delta = time ;
  76                hwt_start(smc,time) ;
  77                return ;
  78        }
  79        /*
  80         * timer correction
  81         */
  82        timer_done(smc,0) ;
  83
  84        /*
  85         * find position in queue
  86         */
  87        delta = 0 ;
  88        for (prev = &smc->t.st_queue ; (tm = *prev) ; prev = &tm->tm_next ) {
  89                if (delta + tm->tm_delta > time) {
  90                        break ;
  91                }
  92                delta += tm->tm_delta ;
  93        }
  94        /* insert in queue */
  95        *prev = timer ;
  96        timer->tm_next = tm ;
  97        timer->tm_delta = time - delta ;
  98        if (tm)
  99                tm->tm_delta -= timer->tm_delta ;
 100        /*
 101         * start new with first
 102         */
 103        hwt_start(smc,smc->t.st_queue->tm_delta) ;
 104}
 105
 106void smt_force_irq(struct s_smc *smc)
 107{
 108        smt_timer_start(smc,&smc->t.st_fast,32L, EV_TOKEN(EVENT_SMT,SM_FAST)); 
 109}
 110
 111void smt_timer_done(struct s_smc *smc)
 112{
 113        timer_done(smc,1) ;
 114}
 115
 116static void timer_done(struct s_smc *smc, int restart)
 117{
 118        u_long                  delta ;
 119        struct smt_timer        *tm ;
 120        struct smt_timer        *next ;
 121        struct smt_timer        **last ;
 122        int                     done = 0 ;
 123
 124        delta = hwt_read(smc) ;
 125        last = &smc->t.st_queue ;
 126        tm = smc->t.st_queue ;
 127        while (tm && !done) {
 128                if (delta >= tm->tm_delta) {
 129                        tm->tm_active = FALSE ;
 130                        delta -= tm->tm_delta ;
 131                        last = &tm->tm_next ;
 132                        tm = tm->tm_next ;
 133                }
 134                else {
 135                        tm->tm_delta -= delta ;
 136                        delta = 0 ;
 137                        done = 1 ;
 138                }
 139        }
 140        *last = NULL;
 141        next = smc->t.st_queue ;
 142        smc->t.st_queue = tm ;
 143
 144        for ( tm = next ; tm ; tm = next) {
 145                next = tm->tm_next ;
 146                timer_event(smc,tm->tm_token) ;
 147        }
 148
 149        if (restart && smc->t.st_queue)
 150                hwt_start(smc,smc->t.st_queue->tm_delta) ;
 151}
 152
 153