0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
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
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 ;
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
0077
0078 timer_done(smc,0) ;
0079
0080
0081
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
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
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