smttimer.c 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157
  1. /******************************************************************************
  2. *
  3. * (C)Copyright 1998,1999 SysKonnect,
  4. * a business unit of Schneider & Koch & Co. Datensysteme GmbH.
  5. *
  6. * See the file "skfddi.c" for further information.
  7. *
  8. * This program is free software; you can redistribute it and/or modify
  9. * it under the terms of the GNU General Public License as published by
  10. * the Free Software Foundation; either version 2 of the License, or
  11. * (at your option) any later version.
  12. *
  13. * The information in this file is provided "AS IS" without warranty.
  14. *
  15. ******************************************************************************/
  16. /*
  17. SMT timer
  18. */
  19. #include "h/types.h"
  20. #include "h/fddi.h"
  21. #include "h/smc.h"
  22. #ifndef lint
  23. static const char ID_sccs[] = "@(#)smttimer.c 2.4 97/08/04 (C) SK " ;
  24. #endif
  25. static void timer_done(struct s_smc *smc, int restart);
  26. void smt_timer_init(struct s_smc *smc)
  27. {
  28. smc->t.st_queue = NULL;
  29. smc->t.st_fast.tm_active = FALSE ;
  30. smc->t.st_fast.tm_next = NULL;
  31. hwt_init(smc) ;
  32. }
  33. void smt_timer_stop(struct s_smc *smc, struct smt_timer *timer)
  34. {
  35. struct smt_timer **prev ;
  36. struct smt_timer *tm ;
  37. /*
  38. * remove timer from queue
  39. */
  40. timer->tm_active = FALSE ;
  41. if (smc->t.st_queue == timer && !timer->tm_next) {
  42. hwt_stop(smc) ;
  43. }
  44. for (prev = &smc->t.st_queue ; (tm = *prev) ; prev = &tm->tm_next ) {
  45. if (tm == timer) {
  46. *prev = tm->tm_next ;
  47. if (tm->tm_next) {
  48. tm->tm_next->tm_delta += tm->tm_delta ;
  49. }
  50. return ;
  51. }
  52. }
  53. }
  54. void 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. time /= 16 ; /* input is uS, clock ticks are 16uS */
  61. if (!time)
  62. time = 1 ;
  63. smt_timer_stop(smc,timer) ;
  64. timer->tm_smc = smc ;
  65. timer->tm_token = token ;
  66. timer->tm_active = TRUE ;
  67. if (!smc->t.st_queue) {
  68. smc->t.st_queue = timer ;
  69. timer->tm_next = NULL;
  70. timer->tm_delta = time ;
  71. hwt_start(smc,time) ;
  72. return ;
  73. }
  74. /*
  75. * timer correction
  76. */
  77. timer_done(smc,0) ;
  78. /*
  79. * find position in queue
  80. */
  81. delta = 0 ;
  82. for (prev = &smc->t.st_queue ; (tm = *prev) ; prev = &tm->tm_next ) {
  83. if (delta + tm->tm_delta > time) {
  84. break ;
  85. }
  86. delta += tm->tm_delta ;
  87. }
  88. /* insert in queue */
  89. *prev = timer ;
  90. timer->tm_next = tm ;
  91. timer->tm_delta = time - delta ;
  92. if (tm)
  93. tm->tm_delta -= timer->tm_delta ;
  94. /*
  95. * start new with first
  96. */
  97. hwt_start(smc,smc->t.st_queue->tm_delta) ;
  98. }
  99. void smt_force_irq(struct s_smc *smc)
  100. {
  101. smt_timer_start(smc,&smc->t.st_fast,32L, EV_TOKEN(EVENT_SMT,SM_FAST));
  102. }
  103. void smt_timer_done(struct s_smc *smc)
  104. {
  105. timer_done(smc,1) ;
  106. }
  107. static void timer_done(struct s_smc *smc, int restart)
  108. {
  109. u_long delta ;
  110. struct smt_timer *tm ;
  111. struct smt_timer *next ;
  112. struct smt_timer **last ;
  113. int done = 0 ;
  114. delta = hwt_read(smc) ;
  115. last = &smc->t.st_queue ;
  116. tm = smc->t.st_queue ;
  117. while (tm && !done) {
  118. if (delta >= tm->tm_delta) {
  119. tm->tm_active = FALSE ;
  120. delta -= tm->tm_delta ;
  121. last = &tm->tm_next ;
  122. tm = tm->tm_next ;
  123. }
  124. else {
  125. tm->tm_delta -= delta ;
  126. delta = 0 ;
  127. done = 1 ;
  128. }
  129. }
  130. *last = NULL;
  131. next = smc->t.st_queue ;
  132. smc->t.st_queue = tm ;
  133. for ( tm = next ; tm ; tm = next) {
  134. next = tm->tm_next ;
  135. timer_event(smc,tm->tm_token) ;
  136. }
  137. if (restart && smc->t.st_queue)
  138. hwt_start(smc,smc->t.st_queue->tm_delta) ;
  139. }