summaryrefslogtreecommitdiffstats
path: root/sys/dev/sound/midi/timer.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/dev/sound/midi/timer.c')
-rw-r--r--sys/dev/sound/midi/timer.c564
1 files changed, 0 insertions, 564 deletions
diff --git a/sys/dev/sound/midi/timer.c b/sys/dev/sound/midi/timer.c
deleted file mode 100644
index ba4bce0..0000000
--- a/sys/dev/sound/midi/timer.c
+++ /dev/null
@@ -1,564 +0,0 @@
-/*
- * This is the timer engine of /dev/music for FreeBSD.
- *
- * (C) 2002 Seigo Tanimura
- *
- * Redistribution and use in source and binary forms, with or
- * without modification, are permitted provided that the following
- * conditions are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following
- * disclaimer in the documentation and/or other materials provided
- * with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS
- * IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
- * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
- * AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
- * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- * $FreeBSD$
- *
- */
-
-#include <dev/sound/midi/midi.h>
-#include <dev/sound/midi/sequencer.h>
-
-#define TMR2TICKS(scp, tmr_val) \
- ((((tmr_val) * (scp)->tempo * (scp)->timebase) + (30 * hz)) / (60 * hz))
-#define CURTICKS(scp) \
- ((scp)->ticks_offset + (scp)->ticks_cur - (scp)->ticks_base)
-
-struct systmr_timer_softc {
- int running;
-
- u_long ticks_offset;
- u_long ticks_base;
- u_long ticks_cur;
-
- int tempo;
- int timebase;
-
- u_long nexteventtime;
- u_long preveventtime;
-
- struct callout timer;
-};
-
-static timeout_t systmr_timer;
-static void systmr_reset(timerdev_info *tmd);
-static u_long systmr_time(void);
-
-static tmr_open_t systmr_open;
-static tmr_close_t systmr_close;
-static tmr_event_t systmr_event;
-static tmr_gettime_t systmr_gettime;
-static tmr_ioctl_t systmr_ioctl;
-static tmr_armtimer_t systmr_armtimer;
-
-static timerdev_info systmr_timerdev = {
- "System clock",
- 0,
- 0,
- systmr_open,
- systmr_close,
- systmr_event,
- systmr_gettime,
- systmr_ioctl,
- systmr_armtimer,
-};
-
-static TAILQ_HEAD(,_timerdev_info) timer_info;
-static struct mtx timerinfo_mtx;
-static int timerinfo_mtx_init;
-static int ntimer;
-
-
-/* Install a system timer. */
-int
-timerdev_install(void)
-{
- int ret;
- timerdev_info *tmd;
- struct systmr_timer_softc *scp;
-
- SEQ_DEBUG(printf("timerdev_install: install a new timer.\n"));
-
- ret = 0;
- tmd = NULL;
- scp = NULL;
-
- scp = malloc(sizeof(*scp), M_DEVBUF, M_WAITOK | M_ZERO);
- if (scp == NULL) {
- ret = ENOMEM;
- goto fail;
- }
-
- tmd = create_timerdev_info_unit(&systmr_timerdev);
- if (tmd == NULL) {
- ret = ENOMEM;
- goto fail;
- }
-
- tmd->softc = scp;
- callout_init(&scp->timer, 0);
-
- mtx_unlock(&tmd->mtx);
-
- SEQ_DEBUG(printf("timerdev_install: installed a new timer, unit %d.\n", tmd->unit));
-
- return (0);
-
-fail:
- if (scp != NULL)
- free(scp, M_DEVBUF);
- if (tmd != NULL) {
- TAILQ_REMOVE(&timer_info, tmd, tmd_link);
- free(tmd, M_DEVBUF);
- }
-
- SEQ_DEBUG(printf("timerdev_install: installation failed.\n"));
-
- return (ret);
-}
-
-/* Create a new timer device info structure. */
-timerdev_info *
-create_timerdev_info_unit(timerdev_info *tmdinf)
-{
- int unit;
- timerdev_info *tmd, *tmdnew;
-
- /* XXX */
- if (!timerinfo_mtx_init) {
- timerinfo_mtx_init = 1;
- mtx_init(&timerinfo_mtx, "tmrinf", NULL, MTX_DEF);
- TAILQ_INIT(&timer_info);
- }
-
- /* As malloc(9) might block, allocate timerdev_info now. */
- tmdnew = malloc(sizeof(timerdev_info), M_DEVBUF, M_WAITOK | M_ZERO);
- if (tmdnew == NULL)
- return NULL;
- bcopy(tmdinf, tmdnew, sizeof(timerdev_info));
- mtx_init(&tmdnew->mtx, "tmrmtx", NULL, MTX_DEF);
-
- mtx_lock(&timerinfo_mtx);
-
- ntimer++;
-
- for (unit = 0 ; ; unit++) {
- TAILQ_FOREACH(tmd, &timer_info, tmd_link) {
- if (tmd->unit == unit)
- break;
- }
- if (tmd == NULL)
- break;
- }
-
- tmdnew->unit = unit;
- mtx_lock(&tmdnew->mtx);
- tmd = TAILQ_FIRST(&timer_info);
- while (tmd != NULL) {
- if (tmd->prio < tmdnew->prio)
- break;
- tmd = TAILQ_NEXT(tmd, tmd_link);
- }
- if (tmd != NULL)
- TAILQ_INSERT_BEFORE(tmd, tmdnew, tmd_link);
- else
- TAILQ_INSERT_TAIL(&timer_info, tmdnew, tmd_link);
-
- mtx_unlock(&timerinfo_mtx);
-
- return (tmdnew);
-}
-
-/*
- * a small utility function which, given a unit number, returns
- * a pointer to the associated timerdev_info struct.
- */
-timerdev_info *
-get_timerdev_info_unit(int unit)
-{
- timerdev_info *tmd;
-
- /* XXX */
- if (!timerinfo_mtx_init) {
- timerinfo_mtx_init = 1;
- mtx_init(&timerinfo_mtx, "tmrinf", NULL, MTX_DEF);
- TAILQ_INIT(&timer_info);
- }
-
- mtx_lock(&timerinfo_mtx);
- TAILQ_FOREACH(tmd, &timer_info, tmd_link) {
- mtx_lock(&tmd->mtx);
- if (tmd->unit == unit && tmd->seq == NULL)
- break;
- mtx_unlock(&tmd->mtx);
- }
- mtx_unlock(&timerinfo_mtx);
-
- return tmd;
-}
-
-/*
- * a small utility function which returns a pointer
- * to the best preferred timerdev_info struct with
- * no sequencer.
- */
-timerdev_info *
-get_timerdev_info(void)
-{
- timerdev_info *tmd;
-
- /* XXX */
- if (!timerinfo_mtx_init) {
- timerinfo_mtx_init = 1;
- mtx_init(&timerinfo_mtx, "tmrinf", NULL, MTX_DEF);
- TAILQ_INIT(&timer_info);
- }
-
- mtx_lock(&timerinfo_mtx);
- TAILQ_FOREACH(tmd, &timer_info, tmd_link) {
- mtx_lock(&tmd->mtx);
- if (tmd->seq == NULL)
- break;
- mtx_unlock(&tmd->mtx);
- }
- mtx_unlock(&timerinfo_mtx);
-
- return tmd;
-}
-
-
-/* ARGSUSED */
-static void
-systmr_timer(void *d)
-{
- timerdev_info *tmd;
- struct systmr_timer_softc *scp;
- void *seq;
-
- tmd = (timerdev_info *)d;
- scp = (struct systmr_timer_softc *)tmd->softc;
- seq = NULL;
-
- mtx_lock(&tmd->mtx);
-
- if (tmd->opened) {
- callout_reset(&scp->timer, 1, systmr_timer, tmd);
-
- if (scp->running) {
- scp->ticks_cur = TMR2TICKS(scp, systmr_time());
-
- if (CURTICKS(scp) >= scp->nexteventtime) {
- SEQ_DEBUG(printf("systmr_timer: CURTICKS %lu, call the sequencer.\n", CURTICKS(scp)));
- scp->nexteventtime = ULONG_MAX;
- seq = tmd->seq;
- }
- }
- }
-
- mtx_unlock(&tmd->mtx);
-
- if (seq != NULL)
- seq_timer(seq);
-}
-
-static void
-systmr_reset(timerdev_info *tmd)
-{
- struct systmr_timer_softc *scp;
-
- scp = (struct systmr_timer_softc *)tmd->softc;
-
- mtx_assert(&tmd->mtx, MA_OWNED);
-
- SEQ_DEBUG(printf("systmr_reset: unit %d.\n", tmd->unit));
-
- scp->ticks_offset = 0;
- scp->ticks_base = scp->ticks_cur = TMR2TICKS(scp, systmr_time());
-
- scp->nexteventtime = ULONG_MAX;
- scp->preveventtime = 0;
-}
-
-static u_long
-systmr_time(void)
-{
- struct timeval timecopy;
-
- getmicrotime(&timecopy);
- return timecopy.tv_usec / (1000000 / hz) + (u_long) timecopy.tv_sec * hz;
-}
-
-
-/* ARGSUSED */
-static int
-systmr_open(timerdev_info *tmd, int oflags, int devtype, struct thread *td)
-{
- struct systmr_timer_softc *scp;
-
- scp = (struct systmr_timer_softc *)tmd->softc;
-
- SEQ_DEBUG(printf("systmr_open: unit %d.\n", tmd->unit));
-
- mtx_lock(&tmd->mtx);
-
- if (tmd->opened) {
- mtx_unlock(&tmd->mtx);
- return (EBUSY);
- }
-
- systmr_reset(tmd);
- scp->tempo = 60;
- scp->timebase = hz;
- tmd->opened = 1;
-
- callout_reset(&scp->timer, 1, systmr_timer, tmd);
-
- mtx_unlock(&tmd->mtx);
-
- return (0);
-}
-
-static int
-systmr_close(timerdev_info *tmd, int fflag, int devtype, struct thread *td)
-{
- struct systmr_timer_softc *scp;
-
- scp = (struct systmr_timer_softc *)tmd->softc;
-
- SEQ_DEBUG(printf("systmr_close: unit %d.\n", tmd->unit));
-
- mtx_lock(&tmd->mtx);
-
- tmd->opened = 0;
- scp->running = 0;
-
- callout_stop(&scp->timer);
-
- mtx_unlock(&tmd->mtx);
-
- return (0);
-}
-
-static int
-systmr_event(timerdev_info *tmd, u_char *ev)
-{
- struct systmr_timer_softc *scp;
- u_char cmd;
- u_long parm, t;
- int ret;
- void * seq;
-
- scp = (struct systmr_timer_softc *)tmd->softc;
- cmd = ev[1];
- parm = *(int *)&ev[4];
- ret = MORE;
-
- SEQ_DEBUG(printf("systmr_event: unit %d, cmd %s, parm %lu.\n",
- tmd->unit, midi_cmdname(cmd, cmdtab_timer), parm));
-
- mtx_lock(&tmd->mtx);
-
- switch (cmd) {
- case TMR_WAIT_REL:
- parm += scp->preveventtime;
- /* FALLTHRU */
- case TMR_WAIT_ABS:
- if (parm > 0) {
- if (parm <= CURTICKS(scp))
- break;
- t = parm;
- scp->nexteventtime = scp->preveventtime = t;
- ret = TIMERARMED;
- break;
- }
- break;
-
- case TMR_START:
- systmr_reset(tmd);
- scp->running = 1;
- break;
-
- case TMR_STOP:
- scp->running = 0;
- break;
-
- case TMR_CONTINUE:
- scp->running = 1;
- break;
-
- case TMR_TEMPO:
- if (parm > 0) {
- RANGE(parm, 8, 360);
- scp->ticks_offset += scp->ticks_cur
- - scp->ticks_base;
- scp->ticks_base = scp->ticks_cur;
- scp->tempo = parm;
- }
- break;
-
- case TMR_ECHO:
- seq = tmd->seq;
- mtx_unlock(&tmd->mtx);
- seq_copytoinput(seq, ev, 8);
- mtx_lock(&tmd->mtx);
- break;
- }
-
- mtx_unlock(&tmd->mtx);
-
- SEQ_DEBUG(printf("systmr_event: timer %s.\n",
- ret == TIMERARMED ? "armed" : "not armed"));
-
- return (ret);
-}
-
-static int
-systmr_gettime(timerdev_info *tmd, u_long *t)
-{
- struct systmr_timer_softc *scp;
- int ret;
-
- scp = (struct systmr_timer_softc *)tmd->softc;
-
- SEQ_DEBUG(printf("systmr_gettime: unit %d.\n", tmd->unit));
-
- mtx_lock(&tmd->mtx);
-
- if (!tmd->opened || t == NULL) {
- ret = EINVAL;
- goto fail;
- }
-
- *t = CURTICKS(scp);
- SEQ_DEBUG(printf("systmr_gettime: ticks %lu.\n", *t));
-
-fail:
- mtx_unlock(&tmd->mtx);
-
- return (0);
-}
-
-static int
-systmr_ioctl(timerdev_info *tmd, u_long cmd, caddr_t data, int fflag, struct thread *td)
-{
- struct systmr_timer_softc *scp;
- int ret, val;
-
- scp = (struct systmr_timer_softc *)tmd->softc;
- ret = 0;
-
- SEQ_DEBUG(printf("systmr_ioctl: unit %d, cmd %s.\n",
- tmd->unit, midi_cmdname(cmd, cmdtab_seqioctl)));
-
- switch (cmd) {
- case SNDCTL_TMR_SOURCE:
- *(int *)data = TMR_INTERNAL;
- break;
-
- case SNDCTL_TMR_START:
- mtx_lock(&tmd->mtx);
- systmr_reset(tmd);
- scp->running = 1;
- mtx_unlock(&tmd->mtx);
- break;
-
- case SNDCTL_TMR_STOP:
- mtx_lock(&tmd->mtx);
- scp->running = 0;
- mtx_unlock(&tmd->mtx);
- break;
-
- case SNDCTL_TMR_CONTINUE:
- mtx_lock(&tmd->mtx);
- scp->running = 1;
- mtx_unlock(&tmd->mtx);
- break;
-
- case SNDCTL_TMR_TIMEBASE:
- val = *(int *)data;
- mtx_lock(&tmd->mtx);
- if (val > 0) {
- RANGE(val, 1, 1000);
- scp->timebase = val;
- }
- *(int *)data = scp->timebase;
- mtx_unlock(&tmd->mtx);
- SEQ_DEBUG(printf("systmr_ioctl: timebase %d.\n", *(int *)data));
- break;
-
- case SNDCTL_TMR_TEMPO:
- val = *(int *)data;
- mtx_lock(&tmd->mtx);
- if (val > 0) {
- RANGE(val, 8, 360);
- scp->ticks_offset += scp->ticks_cur
- - scp->ticks_base;
- scp->ticks_base = scp->ticks_cur;
- scp->tempo = val;
- }
- *(int *)data = scp->tempo;
- SEQ_DEBUG(printf("systmr_ioctl: tempo %d.\n", *(int *)data));
- mtx_unlock(&tmd->mtx);
- break;
-
- case SNDCTL_SEQ_CTRLRATE:
- val = *(int *)data;
- if (val > 0)
- ret = EINVAL;
- else {
- mtx_lock(&tmd->mtx);
- *(int *)data = ((scp->tempo * scp->timebase) + 30) / 60;
- mtx_unlock(&tmd->mtx);
- SEQ_DEBUG(printf("systmr_ioctl: ctrlrate %d.\n", *(int *)data));
- }
- break;
-
- case SNDCTL_TMR_METRONOME:
- /* NOP. */
- break;
-
- case SNDCTL_TMR_SELECT:
- /* NOP. */
- break;
-
- default:
- ret = EINVAL;
- }
-
- return (ret);
-}
-
-static int
-systmr_armtimer(timerdev_info *tmd, u_long t)
-{
- struct systmr_timer_softc *scp;
-
- scp = (struct systmr_timer_softc *)tmd->softc;
-
- SEQ_DEBUG(printf("systmr_armtimer: unit %d, t %lu.\n", tmd->unit, t));
-
- mtx_lock(&tmd->mtx);
-
- if (t < 0)
- t = CURTICKS(scp) + 1;
- else if (t > CURTICKS(scp))
- scp->nexteventtime = scp->preveventtime = t;
-
- mtx_unlock(&tmd->mtx);
-
- return (0);
-}
OpenPOWER on IntegriCloud