sys_timer.c 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286
  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. {
  49. {
  50. def_tmr.expires = (1) + jiffies;
  51. add_timer(&def_tmr);
  52. };
  53. if (tmr_running)
  54. {
  55. spin_lock(&lock);
  56. tmr_ctr++;
  57. curr_ticks = ticks_offs + tmr2ticks(tmr_ctr);
  58. if (curr_ticks >= next_event_time)
  59. {
  60. next_event_time = (unsigned long) -1;
  61. sequencer_timer(0);
  62. }
  63. spin_unlock(&lock);
  64. }
  65. }
  66. }
  67. static void
  68. tmr_reset(void)
  69. {
  70. unsigned long flags;
  71. spin_lock_irqsave(&lock,flags);
  72. tmr_offs = 0;
  73. ticks_offs = 0;
  74. tmr_ctr = 0;
  75. next_event_time = (unsigned long) -1;
  76. prev_event_time = 0;
  77. curr_ticks = 0;
  78. spin_unlock_irqrestore(&lock,flags);
  79. }
  80. static int
  81. def_tmr_open(int dev, int mode)
  82. {
  83. if (opened)
  84. return -EBUSY;
  85. tmr_reset();
  86. curr_tempo = 60;
  87. curr_timebase = 100;
  88. opened = 1;
  89. {
  90. def_tmr.expires = (1) + jiffies;
  91. add_timer(&def_tmr);
  92. };
  93. return 0;
  94. }
  95. static void
  96. def_tmr_close(int dev)
  97. {
  98. opened = tmr_running = 0;
  99. del_timer(&def_tmr);
  100. }
  101. static int
  102. def_tmr_event(int dev, unsigned char *event)
  103. {
  104. unsigned char cmd = event[1];
  105. unsigned long parm = *(int *) &event[4];
  106. switch (cmd)
  107. {
  108. case TMR_WAIT_REL:
  109. parm += prev_event_time;
  110. case TMR_WAIT_ABS:
  111. if (parm > 0)
  112. {
  113. long time;
  114. if (parm <= curr_ticks) /* It's the time */
  115. return TIMER_NOT_ARMED;
  116. time = parm;
  117. next_event_time = prev_event_time = time;
  118. return TIMER_ARMED;
  119. }
  120. break;
  121. case TMR_START:
  122. tmr_reset();
  123. tmr_running = 1;
  124. break;
  125. case TMR_STOP:
  126. tmr_running = 0;
  127. break;
  128. case TMR_CONTINUE:
  129. tmr_running = 1;
  130. break;
  131. case TMR_TEMPO:
  132. if (parm)
  133. {
  134. if (parm < 8)
  135. parm = 8;
  136. if (parm > 360)
  137. parm = 360;
  138. tmr_offs = tmr_ctr;
  139. ticks_offs += tmr2ticks(tmr_ctr);
  140. tmr_ctr = 0;
  141. curr_tempo = parm;
  142. }
  143. break;
  144. case TMR_ECHO:
  145. seq_copy_to_input(event, 8);
  146. break;
  147. default:;
  148. }
  149. return TIMER_NOT_ARMED;
  150. }
  151. static unsigned long
  152. def_tmr_get_time(int dev)
  153. {
  154. if (!opened)
  155. return 0;
  156. return curr_ticks;
  157. }
  158. /* same as sound_timer.c:timer_ioctl!? */
  159. static int def_tmr_ioctl(int dev, unsigned int cmd, void __user *arg)
  160. {
  161. int __user *p = arg;
  162. int val;
  163. switch (cmd) {
  164. case SNDCTL_TMR_SOURCE:
  165. return __put_user(TMR_INTERNAL, p);
  166. case SNDCTL_TMR_START:
  167. tmr_reset();
  168. tmr_running = 1;
  169. return 0;
  170. case SNDCTL_TMR_STOP:
  171. tmr_running = 0;
  172. return 0;
  173. case SNDCTL_TMR_CONTINUE:
  174. tmr_running = 1;
  175. return 0;
  176. case SNDCTL_TMR_TIMEBASE:
  177. if (__get_user(val, p))
  178. return -EFAULT;
  179. if (val) {
  180. if (val < 1)
  181. val = 1;
  182. if (val > 1000)
  183. val = 1000;
  184. curr_timebase = val;
  185. }
  186. return __put_user(curr_timebase, p);
  187. case SNDCTL_TMR_TEMPO:
  188. if (__get_user(val, p))
  189. return -EFAULT;
  190. if (val) {
  191. if (val < 8)
  192. val = 8;
  193. if (val > 250)
  194. val = 250;
  195. tmr_offs = tmr_ctr;
  196. ticks_offs += tmr2ticks(tmr_ctr);
  197. tmr_ctr = 0;
  198. curr_tempo = val;
  199. reprogram_timer();
  200. }
  201. return __put_user(curr_tempo, p);
  202. case SNDCTL_SEQ_CTRLRATE:
  203. if (__get_user(val, p))
  204. return -EFAULT;
  205. if (val != 0) /* Can't change */
  206. return -EINVAL;
  207. val = ((curr_tempo * curr_timebase) + 30) / 60;
  208. return __put_user(val, p);
  209. case SNDCTL_SEQ_GETTIME:
  210. return __put_user(curr_ticks, p);
  211. case SNDCTL_TMR_METRONOME:
  212. /* NOP */
  213. break;
  214. default:;
  215. }
  216. return -EINVAL;
  217. }
  218. static void
  219. def_tmr_arm(int dev, long time)
  220. {
  221. if (time < 0)
  222. time = curr_ticks + 1;
  223. else if (time <= curr_ticks) /* It's the time */
  224. return;
  225. next_event_time = prev_event_time = time;
  226. return;
  227. }
  228. struct sound_timer_operations default_sound_timer =
  229. {
  230. .owner = THIS_MODULE,
  231. .info = {"System clock", 0},
  232. .priority = 0, /* Priority */
  233. .devlink = 0, /* Local device link */
  234. .open = def_tmr_open,
  235. .close = def_tmr_close,
  236. .event = def_tmr_event,
  237. .get_time = def_tmr_get_time,
  238. .ioctl = def_tmr_ioctl,
  239. .arm_timer = def_tmr_arm
  240. };