sys_timer.c 5.3 KB

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