smttimer.c 3.0 KB

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