123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153 |
- // SPDX-License-Identifier: GPL-2.0-or-later
- /******************************************************************************
- *
- * (C)Copyright 1998,1999 SysKonnect,
- * a business unit of Schneider & Koch & Co. Datensysteme GmbH.
- *
- * See the file "skfddi.c" for further information.
- *
- * The information in this file is provided "AS IS" without warranty.
- *
- ******************************************************************************/
- /*
- SMT timer
- */
- #include "h/types.h"
- #include "h/fddi.h"
- #include "h/smc.h"
- #ifndef lint
- static const char ID_sccs[] = "@(#)smttimer.c 2.4 97/08/04 (C) SK " ;
- #endif
- static void timer_done(struct s_smc *smc, int restart);
- void smt_timer_init(struct s_smc *smc)
- {
- smc->t.st_queue = NULL;
- smc->t.st_fast.tm_active = FALSE ;
- smc->t.st_fast.tm_next = NULL;
- hwt_init(smc) ;
- }
- void smt_timer_stop(struct s_smc *smc, struct smt_timer *timer)
- {
- struct smt_timer **prev ;
- struct smt_timer *tm ;
- /*
- * remove timer from queue
- */
- timer->tm_active = FALSE ;
- if (smc->t.st_queue == timer && !timer->tm_next) {
- hwt_stop(smc) ;
- }
- for (prev = &smc->t.st_queue ; (tm = *prev) ; prev = &tm->tm_next ) {
- if (tm == timer) {
- *prev = tm->tm_next ;
- if (tm->tm_next) {
- tm->tm_next->tm_delta += tm->tm_delta ;
- }
- return ;
- }
- }
- }
- void smt_timer_start(struct s_smc *smc, struct smt_timer *timer, u_long time,
- u_long token)
- {
- struct smt_timer **prev ;
- struct smt_timer *tm ;
- u_long delta = 0 ;
- time /= 16 ; /* input is uS, clock ticks are 16uS */
- if (!time)
- time = 1 ;
- smt_timer_stop(smc,timer) ;
- timer->tm_smc = smc ;
- timer->tm_token = token ;
- timer->tm_active = TRUE ;
- if (!smc->t.st_queue) {
- smc->t.st_queue = timer ;
- timer->tm_next = NULL;
- timer->tm_delta = time ;
- hwt_start(smc,time) ;
- return ;
- }
- /*
- * timer correction
- */
- timer_done(smc,0) ;
- /*
- * find position in queue
- */
- delta = 0 ;
- for (prev = &smc->t.st_queue ; (tm = *prev) ; prev = &tm->tm_next ) {
- if (delta + tm->tm_delta > time) {
- break ;
- }
- delta += tm->tm_delta ;
- }
- /* insert in queue */
- *prev = timer ;
- timer->tm_next = tm ;
- timer->tm_delta = time - delta ;
- if (tm)
- tm->tm_delta -= timer->tm_delta ;
- /*
- * start new with first
- */
- hwt_start(smc,smc->t.st_queue->tm_delta) ;
- }
- void smt_force_irq(struct s_smc *smc)
- {
- smt_timer_start(smc,&smc->t.st_fast,32L, EV_TOKEN(EVENT_SMT,SM_FAST));
- }
- void smt_timer_done(struct s_smc *smc)
- {
- timer_done(smc,1) ;
- }
- static void timer_done(struct s_smc *smc, int restart)
- {
- u_long delta ;
- struct smt_timer *tm ;
- struct smt_timer *next ;
- struct smt_timer **last ;
- int done = 0 ;
- delta = hwt_read(smc) ;
- last = &smc->t.st_queue ;
- tm = smc->t.st_queue ;
- while (tm && !done) {
- if (delta >= tm->tm_delta) {
- tm->tm_active = FALSE ;
- delta -= tm->tm_delta ;
- last = &tm->tm_next ;
- tm = tm->tm_next ;
- }
- else {
- tm->tm_delta -= delta ;
- delta = 0 ;
- done = 1 ;
- }
- }
- *last = NULL;
- next = smc->t.st_queue ;
- smc->t.st_queue = tm ;
- for ( tm = next ; tm ; tm = next) {
- next = tm->tm_next ;
- timer_event(smc,tm->tm_token) ;
- }
- if (restart && smc->t.st_queue)
- hwt_start(smc,smc->t.st_queue->tm_delta) ;
- }
|