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
26 * $DragonFly: src/sys/dev/sound/isa/i386/Attic/sound_timer.c,v 1.2 2003/08/07 21:17:12 dillon Exp $
30 #include "sound_config.h"
34 #if defined(CONFIG_SEQUENCER)
36 static volatile int initialized = 0, opened = 0, tmr_running = 0;
37 static volatile time_t tmr_offs, tmr_ctr;
38 static volatile u_long ticks_offs;
39 static volatile int curr_tempo, curr_timebase;
40 static volatile u_long curr_ticks;
41 static volatile u_long next_event_time;
42 static u_long prev_event_time;
43 static volatile u_long usecs_per_tmr; /* Length of the current interval */
45 static struct sound_lowlev_timer *tmr = NULL;
48 tmr2ticks(int tmr_value)
51 * Convert timer ticks to MIDI ticks
57 tmp = tmr_value * usecs_per_tmr; /* Convert to usecs */
59 scale = (60 * 1000000) / (curr_tempo * curr_timebase); /* usecs per MIDI tick */
61 return (tmp + (scale / 2)) / scale;
67 u_long usecs_per_tick;
69 usecs_per_tick = (60 * 1000000) / (curr_tempo * curr_timebase);
72 * Don't kill the system by setting too high timer rate
74 if (usecs_per_tick < 2000)
75 usecs_per_tick = 2000;
77 usecs_per_tmr = tmr->tmr_start(tmr->dev, usecs_per_tick);
81 sound_timer_syncinterval(u_int new_usecs)
84 * This routine is called by the hardware level if the clock
85 * frequency has changed for some reason.
88 ticks_offs += tmr2ticks(tmr_ctr);
91 usecs_per_tmr = new_usecs;
103 next_event_time = 0xffffffff;
110 timer_open(int dev, int mode)
127 opened = tmr_running = 0;
128 tmr->tmr_disable(tmr->dev);
132 timer_event(int dev, u_char *event)
134 u_char cmd = event[1];
135 u_long parm = *(int *) &event[4];
139 parm += prev_event_time;
144 if (parm <= curr_ticks) /* It's the time */
145 return TIMER_NOT_ARMED;
148 next_event_time = prev_event_time = time;
176 ticks_offs += tmr2ticks(tmr_ctr);
184 seq_copy_to_input(event, 8);
190 return TIMER_NOT_ARMED;
194 timer_get_time(int dev)
203 timer_ioctl(int dev, u_int cmd, ioctl_arg arg)
206 case SNDCTL_TMR_SOURCE:
207 return *(int *) arg = TMR_INTERNAL;
210 case SNDCTL_TMR_START:
216 case SNDCTL_TMR_STOP:
221 case SNDCTL_TMR_CONTINUE:
226 case SNDCTL_TMR_TIMEBASE:
228 int val = (*(int *) arg);
237 return *(int *) arg = curr_timebase;
241 case SNDCTL_TMR_TEMPO:
243 int val = (*(int *) arg);
251 ticks_offs += tmr2ticks(tmr_ctr);
256 return *(int *) arg = curr_tempo;
260 case SNDCTL_SEQ_CTRLRATE:
261 if ((*(int *) arg) != 0) /* Can't change */
264 return *(int *) arg = ((curr_tempo * curr_timebase) + 30) / 60;
267 case SNDCTL_TMR_METRONOME:
278 timer_arm(int dev, long time)
281 time = curr_ticks + 1;
282 else if (time <= curr_ticks) /* It's the time */
285 next_event_time = prev_event_time = time;
290 static struct sound_timer_operations sound_timer =
294 0, /* Local device link */
304 sound_timer_interrupt(void)
309 tmr->tmr_restart(tmr->dev);
315 curr_ticks = ticks_offs + tmr2ticks(tmr_ctr);
317 if (curr_ticks >= next_event_time) {
318 next_event_time = 0xffffffff;
324 sound_timer_init(struct sound_lowlev_timer * t, char *name)
328 if (initialized || t == NULL)
329 return; /* There is already a similar timer */
334 if (num_sound_timers >= MAX_TIMER_DEV)
335 n = 0; /* Overwrite the system timer */
337 n = num_sound_timers++;
339 snprintf(sound_timer.info.name, sizeof(sound_timer.info.name), "%s", name);
341 sound_timer_devs[n] = &sound_timer;