sktimer.c 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250
  1. /******************************************************************************
  2. *
  3. * Name: sktimer.c
  4. * Project: Gigabit Ethernet Adapters, Event Scheduler Module
  5. * Version: $Revision: 1.14 $
  6. * Date: $Date: 2003/09/16 13:46:51 $
  7. * Purpose: High level timer functions.
  8. *
  9. ******************************************************************************/
  10. /******************************************************************************
  11. *
  12. * (C)Copyright 1998-2002 SysKonnect GmbH.
  13. * (C)Copyright 2002-2003 Marvell.
  14. *
  15. * This program is free software; you can redistribute it and/or modify
  16. * it under the terms of the GNU General Public License as published by
  17. * the Free Software Foundation; either version 2 of the License, or
  18. * (at your option) any later version.
  19. *
  20. * The information in this file is provided "AS IS" without warranty.
  21. *
  22. ******************************************************************************/
  23. /*
  24. * Event queue and dispatcher
  25. */
  26. #if (defined(DEBUG) || ((!defined(LINT)) && (!defined(SK_SLIM))))
  27. static const char SysKonnectFileId[] =
  28. "@(#) $Id: sktimer.c,v 1.14 2003/09/16 13:46:51 rschmidt Exp $ (C) Marvell.";
  29. #endif
  30. #include "h/skdrv1st.h" /* Driver Specific Definitions */
  31. #include "h/skdrv2nd.h" /* Adapter Control- and Driver specific Def. */
  32. #ifdef __C2MAN__
  33. /*
  34. Event queue management.
  35. General Description:
  36. */
  37. intro()
  38. {}
  39. #endif
  40. /* Forward declaration */
  41. static void timer_done(SK_AC *pAC,SK_IOC Ioc,int Restart);
  42. /*
  43. * Inits the software timer
  44. *
  45. * needs to be called during Init level 1.
  46. */
  47. void SkTimerInit(
  48. SK_AC *pAC, /* Adapters context */
  49. SK_IOC Ioc, /* IoContext */
  50. int Level) /* Init Level */
  51. {
  52. switch (Level) {
  53. case SK_INIT_DATA:
  54. pAC->Tim.StQueue = NULL;
  55. break;
  56. case SK_INIT_IO:
  57. SkHwtInit(pAC, Ioc);
  58. SkTimerDone(pAC, Ioc);
  59. break;
  60. default:
  61. break;
  62. }
  63. }
  64. /*
  65. * Stops a high level timer
  66. * - If a timer is not in the queue the function returns normally, too.
  67. */
  68. void SkTimerStop(
  69. SK_AC *pAC, /* Adapters context */
  70. SK_IOC Ioc, /* IoContext */
  71. SK_TIMER *pTimer) /* Timer Pointer to be started */
  72. {
  73. SK_TIMER **ppTimPrev;
  74. SK_TIMER *pTm;
  75. /*
  76. * remove timer from queue
  77. */
  78. pTimer->TmActive = SK_FALSE;
  79. if (pAC->Tim.StQueue == pTimer && !pTimer->TmNext) {
  80. SkHwtStop(pAC, Ioc);
  81. }
  82. for (ppTimPrev = &pAC->Tim.StQueue; (pTm = *ppTimPrev);
  83. ppTimPrev = &pTm->TmNext ) {
  84. if (pTm == pTimer) {
  85. /*
  86. * Timer found in queue
  87. * - dequeue it and
  88. * - correct delta of the next timer
  89. */
  90. *ppTimPrev = pTm->TmNext;
  91. if (pTm->TmNext) {
  92. /* correct delta of next timer in queue */
  93. pTm->TmNext->TmDelta += pTm->TmDelta;
  94. }
  95. return;
  96. }
  97. }
  98. }
  99. /*
  100. * Start a high level software timer
  101. */
  102. void SkTimerStart(
  103. SK_AC *pAC, /* Adapters context */
  104. SK_IOC Ioc, /* IoContext */
  105. SK_TIMER *pTimer, /* Timer Pointer to be started */
  106. SK_U32 Time, /* Time value */
  107. SK_U32 Class, /* Event Class for this timer */
  108. SK_U32 Event, /* Event Value for this timer */
  109. SK_EVPARA Para) /* Event Parameter for this timer */
  110. {
  111. SK_TIMER **ppTimPrev;
  112. SK_TIMER *pTm;
  113. SK_U32 Delta;
  114. Time /= 16; /* input is uS, clock ticks are 16uS */
  115. if (!Time)
  116. Time = 1;
  117. SkTimerStop(pAC, Ioc, pTimer);
  118. pTimer->TmClass = Class;
  119. pTimer->TmEvent = Event;
  120. pTimer->TmPara = Para;
  121. pTimer->TmActive = SK_TRUE;
  122. if (!pAC->Tim.StQueue) {
  123. /* First Timer to be started */
  124. pAC->Tim.StQueue = pTimer;
  125. pTimer->TmNext = NULL;
  126. pTimer->TmDelta = Time;
  127. SkHwtStart(pAC, Ioc, Time);
  128. return;
  129. }
  130. /*
  131. * timer correction
  132. */
  133. timer_done(pAC, Ioc, 0);
  134. /*
  135. * find position in queue
  136. */
  137. Delta = 0;
  138. for (ppTimPrev = &pAC->Tim.StQueue; (pTm = *ppTimPrev);
  139. ppTimPrev = &pTm->TmNext ) {
  140. if (Delta + pTm->TmDelta > Time) {
  141. /* Position found */
  142. /* Here the timer needs to be inserted. */
  143. break;
  144. }
  145. Delta += pTm->TmDelta;
  146. }
  147. /* insert in queue */
  148. *ppTimPrev = pTimer;
  149. pTimer->TmNext = pTm;
  150. pTimer->TmDelta = Time - Delta;
  151. if (pTm) {
  152. /* There is a next timer
  153. * -> correct its Delta value.
  154. */
  155. pTm->TmDelta -= pTimer->TmDelta;
  156. }
  157. /* restart with first */
  158. SkHwtStart(pAC, Ioc, pAC->Tim.StQueue->TmDelta);
  159. }
  160. void SkTimerDone(
  161. SK_AC *pAC, /* Adapters context */
  162. SK_IOC Ioc) /* IoContext */
  163. {
  164. timer_done(pAC, Ioc, 1);
  165. }
  166. static void timer_done(
  167. SK_AC *pAC, /* Adapters context */
  168. SK_IOC Ioc, /* IoContext */
  169. int Restart) /* Do we need to restart the Hardware timer ? */
  170. {
  171. SK_U32 Delta;
  172. SK_TIMER *pTm;
  173. SK_TIMER *pTComp; /* Timer completed now now */
  174. SK_TIMER **ppLast; /* Next field of Last timer to be deq */
  175. int Done = 0;
  176. Delta = SkHwtRead(pAC, Ioc);
  177. ppLast = &pAC->Tim.StQueue;
  178. pTm = pAC->Tim.StQueue;
  179. while (pTm && !Done) {
  180. if (Delta >= pTm->TmDelta) {
  181. /* Timer ran out */
  182. pTm->TmActive = SK_FALSE;
  183. Delta -= pTm->TmDelta;
  184. ppLast = &pTm->TmNext;
  185. pTm = pTm->TmNext;
  186. }
  187. else {
  188. /* We found the first timer that did not run out */
  189. pTm->TmDelta -= Delta;
  190. Delta = 0;
  191. Done = 1;
  192. }
  193. }
  194. *ppLast = NULL;
  195. /*
  196. * pTm points to the first Timer that did not run out.
  197. * StQueue points to the first Timer that run out.
  198. */
  199. for ( pTComp = pAC->Tim.StQueue; pTComp; pTComp = pTComp->TmNext) {
  200. SkEventQueue(pAC,pTComp->TmClass, pTComp->TmEvent, pTComp->TmPara);
  201. }
  202. /* Set head of timer queue to the first timer that did not run out */
  203. pAC->Tim.StQueue = pTm;
  204. if (Restart && pAC->Tim.StQueue) {
  205. /* Restart HW timer */
  206. SkHwtStart(pAC, Ioc, pAC->Tim.StQueue->TmDelta);
  207. }
  208. }
  209. /* End of file */