Mention branches and keyring.
[releases.git] / fddi / skfp / smttimer.c
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 static void timer_done(struct s_smc *smc, int restart);
22
23 void 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
31 void 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
54 void 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
102 void 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
107 void smt_timer_done(struct s_smc *smc)
108 {
109         timer_done(smc,1) ;
110 }
111
112 static 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