Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-or-later
0002 /******************************************************************************
0003  *
0004  *  (C)Copyright 1998,1999 SysKonnect,
0005  *  a business unit of Schneider & Koch & Co. Datensysteme GmbH.
0006  *
0007  *  See the file "skfddi.c" for further information.
0008  *
0009  *  The information in this file is provided "AS IS" without warranty.
0010  *
0011  ******************************************************************************/
0012 
0013 /*
0014     SMT timer
0015 */
0016 
0017 #include "h/types.h"
0018 #include "h/fddi.h"
0019 #include "h/smc.h"
0020 
0021 static void timer_done(struct s_smc *smc, int restart);
0022 
0023 void smt_timer_init(struct s_smc *smc)
0024 {
0025     smc->t.st_queue = NULL;
0026     smc->t.st_fast.tm_active = FALSE ;
0027     smc->t.st_fast.tm_next = NULL;
0028     hwt_init(smc) ;
0029 }
0030 
0031 void smt_timer_stop(struct s_smc *smc, struct smt_timer *timer)
0032 {
0033     struct smt_timer    **prev ;
0034     struct smt_timer    *tm ;
0035 
0036     /*
0037      * remove timer from queue
0038      */
0039     timer->tm_active = FALSE ;
0040     if (smc->t.st_queue == timer && !timer->tm_next) {
0041         hwt_stop(smc) ;
0042     }
0043     for (prev = &smc->t.st_queue ; (tm = *prev) ; prev = &tm->tm_next ) {
0044         if (tm == timer) {
0045             *prev = tm->tm_next ;
0046             if (tm->tm_next) {
0047                 tm->tm_next->tm_delta += tm->tm_delta ;
0048             }
0049             return ;
0050         }
0051     }
0052 }
0053 
0054 void smt_timer_start(struct s_smc *smc, struct smt_timer *timer, u_long time,
0055              u_long token)
0056 {
0057     struct smt_timer    **prev ;
0058     struct smt_timer    *tm ;
0059     u_long          delta = 0 ;
0060 
0061     time /= 16 ;        /* input is uS, clock ticks are 16uS */
0062     if (!time)
0063         time = 1 ;
0064     smt_timer_stop(smc,timer) ;
0065     timer->tm_smc = smc ;
0066     timer->tm_token = token ;
0067     timer->tm_active = TRUE ;
0068     if (!smc->t.st_queue) {
0069         smc->t.st_queue = timer ;
0070         timer->tm_next = NULL;
0071         timer->tm_delta = time ;
0072         hwt_start(smc,time) ;
0073         return ;
0074     }
0075     /*
0076      * timer correction
0077      */
0078     timer_done(smc,0) ;
0079 
0080     /*
0081      * find position in queue
0082      */
0083     delta = 0 ;
0084     for (prev = &smc->t.st_queue ; (tm = *prev) ; prev = &tm->tm_next ) {
0085         if (delta + tm->tm_delta > time) {
0086             break ;
0087         }
0088         delta += tm->tm_delta ;
0089     }
0090     /* insert in queue */
0091     *prev = timer ;
0092     timer->tm_next = tm ;
0093     timer->tm_delta = time - delta ;
0094     if (tm)
0095         tm->tm_delta -= timer->tm_delta ;
0096     /*
0097      * start new with first
0098      */
0099     hwt_start(smc,smc->t.st_queue->tm_delta) ;
0100 }
0101 
0102 void smt_force_irq(struct s_smc *smc)
0103 {
0104     smt_timer_start(smc,&smc->t.st_fast,32L, EV_TOKEN(EVENT_SMT,SM_FAST)); 
0105 }
0106 
0107 void smt_timer_done(struct s_smc *smc)
0108 {
0109     timer_done(smc,1) ;
0110 }
0111 
0112 static void timer_done(struct s_smc *smc, int restart)
0113 {
0114     u_long          delta ;
0115     struct smt_timer    *tm ;
0116     struct smt_timer    *next ;
0117     struct smt_timer    **last ;
0118     int         done = 0 ;
0119 
0120     delta = hwt_read(smc) ;
0121     last = &smc->t.st_queue ;
0122     tm = smc->t.st_queue ;
0123     while (tm && !done) {
0124         if (delta >= tm->tm_delta) {
0125             tm->tm_active = FALSE ;
0126             delta -= tm->tm_delta ;
0127             last = &tm->tm_next ;
0128             tm = tm->tm_next ;
0129         }
0130         else {
0131             tm->tm_delta -= delta ;
0132             delta = 0 ;
0133             done = 1 ;
0134         }
0135     }
0136     *last = NULL;
0137     next = smc->t.st_queue ;
0138     smc->t.st_queue = tm ;
0139 
0140     for ( tm = next ; tm ; tm = next) {
0141         next = tm->tm_next ;
0142         timer_event(smc,tm->tm_token) ;
0143     }
0144 
0145     if (restart && smc->t.st_queue)
0146         hwt_start(smc,smc->t.st_queue->tm_delta) ;
0147 }
0148