smttimer.c 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153
  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. SMT timer
  14. */
  15. #include "h/types.h"
  16. #include "h/fddi.h"
  17. #include "h/smc.h"
  18. #ifndef lint
  19. static const char ID_sccs[] = "@(#)smttimer.c 2.4 97/08/04 (C) SK " ;
  20. #endif
  21. static void timer_done(struct s_smc *smc, int restart);
  22. void smt_timer_init(struct s_smc *smc)
  23. {
  24. smc->t.st_queue = NULL;
  25. smc->t.st_fast.tm_active = FALSE ;
  26. smc->t.st_fast.tm_next = NULL;
  27. hwt_init(smc) ;
  28. }
  29. void smt_timer_stop(struct s_smc *smc, struct smt_timer *timer)
  30. {
  31. struct smt_timer **prev ;
  32. struct smt_timer *tm ;
  33. /*
  34. * remove timer from queue
  35. */
  36. timer->tm_active = FALSE ;
  37. if (smc->t.st_queue == timer && !timer->tm_next) {
  38. hwt_stop(smc) ;
  39. }
  40. for (prev = &smc->t.st_queue ; (tm = *prev) ; prev = &tm->tm_next ) {
  41. if (tm == timer) {
  42. *prev = tm->tm_next ;
  43. if (tm->tm_next) {
  44. tm->tm_next->tm_delta += tm->tm_delta ;
  45. }
  46. return ;
  47. }
  48. }
  49. }
  50. void smt_timer_start(struct s_smc *smc, struct smt_timer *timer, u_long time,
  51. u_long token)
  52. {
  53. struct smt_timer **prev ;
  54. struct smt_timer *tm ;
  55. u_long delta = 0 ;
  56. time /= 16 ; /* input is uS, clock ticks are 16uS */
  57. if (!time)
  58. time = 1 ;
  59. smt_timer_stop(smc,timer) ;
  60. timer->tm_smc = smc ;
  61. timer->tm_token = token ;
  62. timer->tm_active = TRUE ;
  63. if (!smc->t.st_queue) {
  64. smc->t.st_queue = timer ;
  65. timer->tm_next = NULL;
  66. timer->tm_delta = time ;
  67. hwt_start(smc,time) ;
  68. return ;
  69. }
  70. /*
  71. * timer correction
  72. */
  73. timer_done(smc,0) ;
  74. /*
  75. * find position in queue
  76. */
  77. delta = 0 ;
  78. for (prev = &smc->t.st_queue ; (tm = *prev) ; prev = &tm->tm_next ) {
  79. if (delta + tm->tm_delta > time) {
  80. break ;
  81. }
  82. delta += tm->tm_delta ;
  83. }
  84. /* insert in queue */
  85. *prev = timer ;
  86. timer->tm_next = tm ;
  87. timer->tm_delta = time - delta ;
  88. if (tm)
  89. tm->tm_delta -= timer->tm_delta ;
  90. /*
  91. * start new with first
  92. */
  93. hwt_start(smc,smc->t.st_queue->tm_delta) ;
  94. }
  95. void smt_force_irq(struct s_smc *smc)
  96. {
  97. smt_timer_start(smc,&smc->t.st_fast,32L, EV_TOKEN(EVENT_SMT,SM_FAST));
  98. }
  99. void smt_timer_done(struct s_smc *smc)
  100. {
  101. timer_done(smc,1) ;
  102. }
  103. static void timer_done(struct s_smc *smc, int restart)
  104. {
  105. u_long delta ;
  106. struct smt_timer *tm ;
  107. struct smt_timer *next ;
  108. struct smt_timer **last ;
  109. int done = 0 ;
  110. delta = hwt_read(smc) ;
  111. last = &smc->t.st_queue ;
  112. tm = smc->t.st_queue ;
  113. while (tm && !done) {
  114. if (delta >= tm->tm_delta) {
  115. tm->tm_active = FALSE ;
  116. delta -= tm->tm_delta ;
  117. last = &tm->tm_next ;
  118. tm = tm->tm_next ;
  119. }
  120. else {
  121. tm->tm_delta -= delta ;
  122. delta = 0 ;
  123. done = 1 ;
  124. }
  125. }
  126. *last = NULL;
  127. next = smc->t.st_queue ;
  128. smc->t.st_queue = tm ;
  129. for ( tm = next ; tm ; tm = next) {
  130. next = tm->tm_next ;
  131. timer_event(smc,tm->tm_token) ;
  132. }
  133. if (restart && smc->t.st_queue)
  134. hwt_start(smc,smc->t.st_queue->tm_delta) ;
  135. }