timer.c
上传用户:lgb322
上传日期:2013-02-24
资源大小:30529k
文件大小:4k
源码类别:

嵌入式Linux

开发平台:

Unix_Linux

  1. /*
  2.  **********************************************************************
  3.  *     timer.c
  4.  *     Copyright (C) 1999, 2000 Creative Labs, inc.
  5.  *
  6.  **********************************************************************
  7.  *
  8.  *     This program is free software; you can redistribute it and/or
  9.  *     modify it under the terms of the GNU General Public License as
  10.  *     published by the Free Software Foundation; either version 2 of
  11.  *     the License, or (at your option) any later version.
  12.  *
  13.  *     This program is distributed in the hope that it will be useful,
  14.  *     but WITHOUT ANY WARRANTY; without even the implied warranty of
  15.  *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  16.  *     GNU General Public License for more details.
  17.  *
  18.  *     You should have received a copy of the GNU General Public
  19.  *     License along with this program; if not, write to the Free
  20.  *     Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139,
  21.  *     USA.
  22.  *
  23.  **********************************************************************
  24.  */
  25. /* 3/6/2000 Improved support for different timer delays  Rui Sousa */
  26. /* 4/3/2000 Implemented timer list using list.h       Rui Sousa */
  27. #include "hwaccess.h"
  28. #include "8010.h"
  29. #include "irqmgr.h"
  30. #include "timer.h"
  31. /* Try to schedule only once per fragment */
  32. void emu10k1_timer_irqhandler(struct emu10k1_card *card)
  33. {
  34. struct emu_timer *t;
  35. struct list_head *entry;
  36. spin_lock(&card->timer_lock);
  37. list_for_each(entry, &card->timers) {
  38. t = list_entry(entry, struct emu_timer, list);
  39. if (t->state & TIMER_STATE_ACTIVE) {
  40. t->count++;
  41. if (t->count == t->count_max) {
  42. t->count = 0;
  43. tasklet_hi_schedule(&t->tasklet);
  44. }
  45. }
  46. }
  47. spin_unlock(&card->timer_lock);
  48. return;
  49. }
  50. void emu10k1_timer_install(struct emu10k1_card *card, struct emu_timer *timer, u32 delay)
  51. {
  52. struct emu_timer *t;
  53. struct list_head *entry;
  54. unsigned long flags;
  55. if (delay < 5)
  56. delay = 5;
  57. timer->delay = delay;
  58. timer->state = TIMER_STATE_INSTALLED;
  59. spin_lock_irqsave(&card->timer_lock, flags);
  60. timer->count_max = timer->delay / (card->timer_delay < 1024 ? card->timer_delay : 1024);
  61. timer->count = timer->count_max - 1;
  62. list_add(&timer->list, &card->timers);
  63. if (card->timer_delay > delay) {
  64. if (card->timer_delay == TIMER_STOPPED)
  65. emu10k1_irq_enable(card, INTE_INTERVALTIMERENB);
  66. card->timer_delay = delay;
  67. delay = (delay < 1024 ? delay : 1024);
  68. emu10k1_writefn0(card, TIMER_RATE, delay);
  69. list_for_each(entry, &card->timers) {
  70. t = list_entry(entry, struct emu_timer, list);
  71. t->count_max = t->delay / delay;
  72. /* don't want to think much, just force scheduling 
  73.    on the next interrupt */
  74. t->count = t->count_max - 1;
  75. }
  76. DPD(2, "timer rate --> %un", delay);
  77. }
  78. spin_unlock_irqrestore(&card->timer_lock, flags);
  79. return;
  80. }
  81. void emu10k1_timer_uninstall(struct emu10k1_card *card, struct emu_timer *timer)
  82. {
  83. struct emu_timer *t;
  84. struct list_head *entry;
  85. u32 delay = TIMER_STOPPED;
  86. unsigned long flags;
  87. if (timer->state == TIMER_STATE_UNINSTALLED)
  88. return;
  89. spin_lock_irqsave(&card->timer_lock, flags);
  90. list_del(&timer->list);
  91. list_for_each(entry, &card->timers) {
  92. t = list_entry(entry, struct emu_timer, list);
  93. if (t->delay < delay)
  94. delay = t->delay;
  95. }
  96. if (card->timer_delay != delay) {
  97. card->timer_delay = delay;
  98. if (delay == TIMER_STOPPED)
  99. emu10k1_irq_disable(card, INTE_INTERVALTIMERENB);
  100. else {
  101. delay = (delay < 1024 ? delay : 1024);
  102. emu10k1_writefn0(card, TIMER_RATE, delay);
  103. list_for_each(entry, &card->timers) {
  104. t = list_entry(entry, struct emu_timer, list);
  105. t->count_max = t->delay / delay;
  106. t->count = t->count_max - 1;
  107. }
  108. }
  109. DPD(2, "timer rate --> %un", delay);
  110. }
  111. spin_unlock_irqrestore(&card->timer_lock, flags);
  112. timer->state = TIMER_STATE_UNINSTALLED;
  113. return;
  114. }
  115. void emu10k1_timer_enable(struct emu10k1_card *card, struct emu_timer *timer)
  116. {
  117. unsigned long flags;
  118. spin_lock_irqsave(&card->timer_lock, flags);
  119. timer->state |= TIMER_STATE_ACTIVE;
  120. spin_unlock_irqrestore(&card->timer_lock, flags);
  121. return;
  122. }
  123. void emu10k1_timer_disable(struct emu10k1_card *card, struct emu_timer *timer)
  124. {
  125. unsigned long flags;
  126. spin_lock_irqsave(&card->timer_lock, flags);
  127. timer->state &= ~TIMER_STATE_ACTIVE;
  128. spin_unlock_irqrestore(&card->timer_lock, flags);
  129. return;
  130. }