4 * Copyright by Hannu Savolainen 1993
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions are
8 * met: 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer. 2.
10 * Redistributions in binary form must reproduce the above copyright notice,
11 * this list of conditions and the following disclaimer in the documentation
12 * and/or other materials provided with the distribution.
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY
15 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
16 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
17 * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
18 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
20 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
21 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 #include <i386/isa/sound/sound_config.h>
33 #if defined(CONFIG_SEQUENCER)
35 static volatile int initialized = 0, opened = 0, tmr_running = 0;
36 static volatile time_t tmr_offs, tmr_ctr;
37 static volatile u_long ticks_offs;
38 static volatile int curr_tempo, curr_timebase;
39 static volatile u_long curr_ticks;
40 static volatile u_long next_event_time;
41 static u_long prev_event_time;
42 static volatile u_long usecs_per_tmr; /* Length of the current interval */
44 static struct sound_lowlev_timer *tmr = NULL;
47 tmr2ticks(int tmr_value)
50 * Convert timer ticks to MIDI ticks
56 tmp = tmr_value * usecs_per_tmr; /* Convert to usecs */
58 scale = (60 * 1000000) / (curr_tempo * curr_timebase); /* usecs per MIDI tick */
60 return (tmp + (scale / 2)) / scale;
66 u_long usecs_per_tick;
68 usecs_per_tick = (60 * 1000000) / (curr_tempo * curr_timebase);
71 * Don't kill the system by setting too high timer rate
73 if (usecs_per_tick < 2000)
74 usecs_per_tick = 2000;
76 usecs_per_tmr = tmr->tmr_start(tmr->dev, usecs_per_tick);
80 sound_timer_syncinterval(u_int new_usecs)
83 * This routine is called by the hardware level if the clock
84 * frequency has changed for some reason.
87 ticks_offs += tmr2ticks(tmr_ctr);
90 usecs_per_tmr = new_usecs;
102 next_event_time = 0xffffffff;
109 timer_open(int dev, int mode)
126 opened = tmr_running = 0;
127 tmr->tmr_disable(tmr->dev);
131 timer_event(int dev, u_char *event)
133 u_char cmd = event[1];
134 u_long parm = *(int *) &event[4];
138 parm += prev_event_time;
143 if (parm <= curr_ticks) /* It's the time */
144 return TIMER_NOT_ARMED;
147 next_event_time = prev_event_time = time;
175 ticks_offs += tmr2ticks(tmr_ctr);
183 seq_copy_to_input(event, 8);
189 return TIMER_NOT_ARMED;
193 timer_get_time(int dev)
202 timer_ioctl(int dev, u_int cmd, ioctl_arg arg)
205 case SNDCTL_TMR_SOURCE:
206 return *(int *) arg = TMR_INTERNAL;
209 case SNDCTL_TMR_START:
215 case SNDCTL_TMR_STOP:
220 case SNDCTL_TMR_CONTINUE:
225 case SNDCTL_TMR_TIMEBASE:
227 int val = (*(int *) arg);
236 return *(int *) arg = curr_timebase;
240 case SNDCTL_TMR_TEMPO:
242 int val = (*(int *) arg);
250 ticks_offs += tmr2ticks(tmr_ctr);
255 return *(int *) arg = curr_tempo;
259 case SNDCTL_SEQ_CTRLRATE:
260 if ((*(int *) arg) != 0) /* Can't change */
263 return *(int *) arg = ((curr_tempo * curr_timebase) + 30) / 60;
266 case SNDCTL_TMR_METRONOME:
277 timer_arm(int dev, long time)
280 time = curr_ticks + 1;
281 else if (time <= curr_ticks) /* It's the time */
284 next_event_time = prev_event_time = time;
289 static struct sound_timer_operations sound_timer =
293 0, /* Local device link */
303 sound_timer_interrupt(void)
308 tmr->tmr_restart(tmr->dev);
314 curr_ticks = ticks_offs + tmr2ticks(tmr_ctr);
316 if (curr_ticks >= next_event_time) {
317 next_event_time = 0xffffffff;
323 sound_timer_init(struct sound_lowlev_timer * t, char *name)
327 if (initialized || t == NULL)
328 return; /* There is already a similar timer */
333 if (num_sound_timers >= MAX_TIMER_DEV)
334 n = 0; /* Overwrite the system timer */
336 n = num_sound_timers++;
338 snprintf(sound_timer.info.name, sizeof(sound_timer.info.name), "%s", name);
340 sound_timer_devs[n] = &sound_timer;