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
  21static void timer_done(struct s_smc *smc, int restart);
  22
  23void smt_timer_init(struct s_smc *smc)
  24{
  25        smc->t.st_queue = NULL;
  26        smc->t.st_fast.tm_active = FALSE ;
  27        smc->t.st_fast.tm_next = NULL;
  28        hwt_init(smc) ;
  29}
  30
  31void smt_timer_stop(struct s_smc *smc, struct smt_timer *timer)
  32{
  33        struct smt_timer        **prev ;
  34        struct smt_timer        *tm ;
  35
  36        /*
  37         * remove timer from queue
  38         */
  39        timer->tm_active = FALSE ;
  40        if (smc->t.st_queue == timer && !timer->tm_next) {
  41                hwt_stop(smc) ;
  42        }
  43        for (prev = &smc->t.st_queue ; (tm = *prev) ; prev = &tm->tm_next ) {
  44                if (tm == timer) {
  45                        *prev = tm->tm_next ;
  46                        if (tm->tm_next) {
  47                                tm->tm_next->tm_delta += tm->tm_delta ;
  48                        }
  49                        return ;
  50                }
  51        }
  52}
  53
  54void smt_timer_start(struct s_smc *smc, struct smt_timer *timer, u_long time,
  55                     u_long token)
  56{
  57        struct smt_timer        **prev ;
  58        struct smt_timer        *tm ;
  59        u_long                  delta = 0 ;
  60
  61        time /= 16 ;            /* input is uS, clock ticks are 16uS */
  62        if (!time)
  63                time = 1 ;
  64        smt_timer_stop(smc,timer) ;
  65        timer->tm_smc = smc ;
  66        timer->tm_token = token ;
  67        timer->tm_active = TRUE ;
  68        if (!smc->t.st_queue) {
  69                smc->t.st_queue = timer ;
  70                timer->tm_next = NULL;
  71                timer->tm_delta = time ;
  72                hwt_start(smc,time) ;
  73                return ;
  74        }
  75        /*
  76         * timer correction
  77         */
  78        timer_done(smc,0) ;
  79
  80        /*
  81         * find position in queue
  82         */
  83        delta = 0 ;
  84        for (prev = &smc->t.st_queue ; (tm = *prev) ; prev = &tm->tm_next ) {
  85                if (delta + tm->tm_delta > time) {
  86                        break ;
  87                }
  88                delta += tm->tm_delta ;
  89        }
  90        /* insert in queue */
  91        *prev = timer ;
  92        timer->tm_next = tm ;
  93        timer->tm_delta = time - delta ;
  94        if (tm)
  95                tm->tm_delta -= timer->tm_delta ;
  96        /*
  97         * start new with first
  98         */
  99        hwt_start(smc,smc->t.st_queue->tm_delta) ;
 100}
 101
 102void smt_force_irq(struct s_smc *smc)
 103{
 104        smt_timer_start(smc,&smc->t.st_fast,32L, EV_TOKEN(EVENT_SMT,SM_FAST)); 
 105}
 106
 107void smt_timer_done(struct s_smc *smc)
 108{
 109        timer_done(smc,1) ;
 110}
 111
 112static void timer_done(struct s_smc *smc, int restart)
 113{
 114        u_long                  delta ;
 115        struct smt_timer        *tm ;
 116        struct smt_timer        *next ;
 117        struct smt_timer        **last ;
 118        int                     done = 0 ;
 119
 120        delta = hwt_read(smc) ;
 121        last = &smc->t.st_queue ;
 122        tm = smc->t.st_queue ;
 123        while (tm && !done) {
 124                if (delta >= tm->tm_delta) {
 125                        tm->tm_active = FALSE ;
 126                        delta -= tm->tm_delta ;
 127                        last = &tm->tm_next ;
 128                        tm = tm->tm_next ;
 129                }
 130                else {
 131                        tm->tm_delta -= delta ;
 132                        delta = 0 ;
 133                        done = 1 ;
 134                }
 135        }
 136        *last = NULL;
 137        next = smc->t.st_queue ;
 138        smc->t.st_queue = tm ;
 139
 140        for ( tm = next ; tm ; tm = next) {
 141                next = tm->tm_next ;
 142                timer_event(smc,tm->tm_token) ;
 143        }
 144
 145        if (restart && smc->t.st_queue)
 146                hwt_start(smc,smc->t.st_queue->tm_delta) ;
 147}
 148
 149