149 lines · c
1// SPDX-License-Identifier: GPL-2.0-or-later2/******************************************************************************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 timer15*/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 queue38 */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 correction77 */78 timer_done(smc,0) ;79 80 /*81 * find position in queue82 */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 first98 */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