sys_timer.c 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280
  1. /*
  2. * sound/oss/sys_timer.c
  3. *
  4. * The default timer for the Level 2 sequencer interface
  5. * Uses the (1/HZ sec) timer of kernel.
  6. */
  7. /*
  8. * Copyright (C) by Hannu Savolainen 1993-1997
  9. *
  10. * OSS/Free for Linux is distributed under the GNU GENERAL PUBLIC LICENSE (GPL)
  11. * Version 2 (June 1991). See the "COPYING" file distributed with this software
  12. * for more info.
  13. */
  14. /*
  15. * Thomas Sailer : ioctl code reworked (vmalloc/vfree removed)
  16. * Andrew Veliath : adapted tmr2ticks from level 1 sequencer (avoid overflow)
  17. */
  18. #include <linux/spinlock.h>
  19. #include "sound_config.h"
  20. static volatile int opened, tmr_running;
  21. static volatile time_t tmr_offs, tmr_ctr;
  22. static volatile unsigned long ticks_offs;
  23. static volatile int curr_tempo, curr_timebase;
  24. static volatile unsigned long curr_ticks;
  25. static volatile unsigned long next_event_time;
  26. static unsigned long prev_event_time;
  27. static void poll_def_tmr(unsigned long dummy);
  28. static DEFINE_SPINLOCK(lock);
  29. static DEFINE_TIMER(def_tmr, poll_def_tmr, 0, 0);
  30. static unsigned long
  31. tmr2ticks(int tmr_value)
  32. {
  33. /*
  34. * Convert timer ticks to MIDI ticks
  35. */
  36. unsigned long tmp;
  37. unsigned long scale;
  38. /* tmr_value (ticks per sec) *
  39. 1000000 (usecs per sec) / HZ (ticks per sec) -=> usecs */
  40. tmp = tmr_value * (1000000 / HZ);
  41. scale = (60 * 1000000) / (curr_tempo * curr_timebase); /* usecs per MIDI tick */
  42. return (tmp + scale / 2) / scale;
  43. }
  44. static void
  45. poll_def_tmr(unsigned long dummy)
  46. {
  47. if (!opened)
  48. return;
  49. def_tmr.expires = (1) + jiffies;
  50. add_timer(&def_tmr);
  51. if (!tmr_running)
  52. return;
  53. spin_lock(&lock);
  54. tmr_ctr++;
  55. curr_ticks = ticks_offs + tmr2ticks(tmr_ctr);
  56. if (curr_ticks >= next_event_time) {
  57. next_event_time = (unsigned long) -1;
  58. sequencer_timer(0);
  59. }
  60. spin_unlock(&lock);
  61. }
  62. static void
  63. tmr_reset(void)
  64. {
  65. unsigned long flags;
  66. spin_lock_irqsave(&lock,flags);
  67. tmr_offs = 0;
  68. ticks_offs = 0;
  69. tmr_ctr = 0;
  70. next_event_time = (unsigned long) -1;
  71. prev_event_time = 0;
  72. curr_ticks = 0;
  73. spin_unlock_irqrestore(&lock,flags);
  74. }
  75. static int
  76. def_tmr_open(int dev, int mode)
  77. {
  78. if (opened)
  79. return -EBUSY;
  80. tmr_reset();
  81. curr_tempo = 60;
  82. curr_timebase = 100;
  83. opened = 1;
  84. {
  85. def_tmr.expires = (1) + jiffies;
  86. add_timer(&def_tmr);
  87. }
  88. return 0;
  89. }
  90. static void
  91. def_tmr_close(int dev)
  92. {
  93. opened = tmr_running = 0;
  94. del_timer(&def_tmr);
  95. }
  96. static int
  97. def_tmr_event(int dev, unsigned char *event)
  98. {
  99. unsigned char cmd = event[1];
  100. unsigned long parm = *(int *) &event[4];
  101. switch (cmd)
  102. {
  103. case TMR_WAIT_REL:
  104. parm += prev_event_time;
  105. case TMR_WAIT_ABS:
  106. if (parm > 0)
  107. {
  108. long time;
  109. if (parm <= curr_ticks) /* It's the time */
  110. return TIMER_NOT_ARMED;
  111. time = parm;
  112. next_event_time = prev_event_time = time;
  113. return TIMER_ARMED;
  114. }
  115. break;
  116. case TMR_START:
  117. tmr_reset();
  118. tmr_running = 1;
  119. break;
  120. case TMR_STOP:
  121. tmr_running = 0;
  122. break;
  123. case TMR_CONTINUE:
  124. tmr_running = 1;
  125. break;
  126. case TMR_TEMPO:
  127. if (parm)
  128. {
  129. if (parm < 8)
  130. parm = 8;
  131. if (parm > 360)
  132. parm = 360;
  133. tmr_offs = tmr_ctr;
  134. ticks_offs += tmr2ticks(tmr_ctr);
  135. tmr_ctr = 0;
  136. curr_tempo = parm;
  137. }
  138. break;
  139. case TMR_ECHO:
  140. seq_copy_to_input(event, 8);
  141. break;
  142. default:;
  143. }
  144. return TIMER_NOT_ARMED;
  145. }
  146. static unsigned long
  147. def_tmr_get_time(int dev)
  148. {
  149. if (!opened)
  150. return 0;
  151. return curr_ticks;
  152. }
  153. /* same as sound_timer.c:timer_ioctl!? */
  154. static int def_tmr_ioctl(int dev, unsigned int cmd, void __user *arg)
  155. {
  156. int __user *p = arg;
  157. int val;
  158. switch (cmd) {
  159. case SNDCTL_TMR_SOURCE:
  160. return __put_user(TMR_INTERNAL, p);
  161. case SNDCTL_TMR_START:
  162. tmr_reset();
  163. tmr_running = 1;
  164. return 0;
  165. case SNDCTL_TMR_STOP:
  166. tmr_running = 0;
  167. return 0;
  168. case SNDCTL_TMR_CONTINUE:
  169. tmr_running = 1;
  170. return 0;
  171. case SNDCTL_TMR_TIMEBASE:
  172. if (__get_user(val, p))
  173. return -EFAULT;
  174. if (val) {
  175. if (val < 1)
  176. val = 1;
  177. if (val > 1000)
  178. val = 1000;
  179. curr_timebase = val;
  180. }
  181. return __put_user(curr_timebase, p);
  182. case SNDCTL_TMR_TEMPO:
  183. if (__get_user(val, p))
  184. return -EFAULT;
  185. if (val) {
  186. if (val < 8)
  187. val = 8;
  188. if (val > 250)
  189. val = 250;
  190. tmr_offs = tmr_ctr;
  191. ticks_offs += tmr2ticks(tmr_ctr);
  192. tmr_ctr = 0;
  193. curr_tempo = val;
  194. reprogram_timer();
  195. }
  196. return __put_user(curr_tempo, p);
  197. case SNDCTL_SEQ_CTRLRATE:
  198. if (__get_user(val, p))
  199. return -EFAULT;
  200. if (val != 0) /* Can't change */
  201. return -EINVAL;
  202. val = ((curr_tempo * curr_timebase) + 30) / 60;
  203. return __put_user(val, p);
  204. case SNDCTL_SEQ_GETTIME:
  205. return __put_user(curr_ticks, p);
  206. case SNDCTL_TMR_METRONOME:
  207. /* NOP */
  208. break;
  209. default:;
  210. }
  211. return -EINVAL;
  212. }
  213. static void
  214. def_tmr_arm(int dev, long time)
  215. {
  216. if (time < 0)
  217. time = curr_ticks + 1;
  218. else if (time <= curr_ticks) /* It's the time */
  219. return;
  220. next_event_time = prev_event_time = time;
  221. return;
  222. }
  223. struct sound_timer_operations default_sound_timer =
  224. {
  225. .owner = THIS_MODULE,
  226. .info = {"System clock", 0},
  227. .priority = 0, /* Priority */
  228. .devlink = 0, /* Local device link */
  229. .open = def_tmr_open,
  230. .close = def_tmr_close,
  231. .event = def_tmr_event,
  232. .get_time = def_tmr_get_time,
  233. .ioctl = def_tmr_ioctl,
  234. .arm_timer = def_tmr_arm
  235. };