From: François Tigeot Date: Sun, 19 Oct 2014 07:56:55 +0000 (+0200) Subject: sound: Drop midi support X-Git-Tag: v4.2.0rc~1162 X-Git-Url: https://gitweb.dragonflybsd.org/~tuxillo/dragonfly.git/commitdiff_plain/5bea67f41d941ba13d0b25782f6a3b9a9460e98e sound: Drop midi support --- diff --git a/sys/conf/files b/sys/conf/files index c578e5362b..7f89214456 100644 --- a/sys/conf/files +++ b/sys/conf/files @@ -1705,7 +1705,6 @@ dev/sound/pci/cs4281.c optional snd_cs4281 pci dev/sound/pci/emu10k1.c optional snd_emu10k1 pci dev/sound/pci/emu10kx.c optional snd_emu10kx pci dev/sound/pci/emu10kx-pcm.c optional snd_emu10kx pci -dev/sound/pci/emu10kx-midi.c optional snd_emu10kx pci dev/sound/pci/envy24.c optional snd_envy24 pci dev/sound/pci/envy24ht.c optional snd_envy24ht pci dev/sound/pci/es137x.c optional snd_es137x pci @@ -1756,12 +1755,6 @@ dev/sound/pcm/mixer_if.m optional sound dev/sound/pcm/sndstat.c optional sound dev/sound/pcm/sound.c optional sound dev/sound/pcm/vchan.c optional sound -dev/sound/midi/midi.c optional sound -dev/sound/midi/mpu401.c optional sound -dev/sound/midi/mpu_if.m optional sound -dev/sound/midi/mpufoi_if.m optional sound -dev/sound/midi/sequencer.c optional sound -dev/sound/midi/synth_if.m optional sound # # These files in libkern/ are those needed by all architectures. Some # of the files in libkern/ are only needed on some architectures, e.g., diff --git a/sys/conf/kmod.mk b/sys/conf/kmod.mk index 721ec2f2d3..9c1ca90c94 100644 --- a/sys/conf/kmod.mk +++ b/sys/conf/kmod.mk @@ -313,8 +313,6 @@ MFILES?= kern/bus_if.m kern/device_if.m bus/iicbus/iicbb_if.m \ dev/sound/pci/hda/hdac_if.m \ dev/sound/pcm/ac97_if.m dev/sound/pcm/channel_if.m \ dev/sound/pcm/feeder_if.m dev/sound/pcm/mixer_if.m \ - dev/sound/midi/mpu_if.m dev/sound/midi/mpufoi_if.m \ - dev/sound/midi/synth_if.m \ libiconv/iconv_converter_if.m dev/agp/agp_if.m opencrypto/cryptodev_if.m \ bus/mmc/mmcbus_if.m bus/mmc/mmcbr_if.m \ dev/virtual/virtio/virtio/virtio_bus_if.m \ diff --git a/sys/dev/sound/driver/cmi/Makefile b/sys/dev/sound/driver/cmi/Makefile index f06f4ebdc8..e73d1bb0a3 100644 --- a/sys/dev/sound/driver/cmi/Makefile +++ b/sys/dev/sound/driver/cmi/Makefile @@ -4,7 +4,6 @@ KMOD= snd_cmi SRCS= device_if.h bus_if.h pci_if.h -SRCS+= mpufoi_if.h SRCS+= cmi.c .include diff --git a/sys/dev/sound/driver/emu10k1/Makefile b/sys/dev/sound/driver/emu10k1/Makefile index 8daef6f76a..3e738a8f8a 100644 --- a/sys/dev/sound/driver/emu10k1/Makefile +++ b/sys/dev/sound/driver/emu10k1/Makefile @@ -4,7 +4,6 @@ KMOD= snd_emu10k1 SRCS= device_if.h bus_if.h pci_if.h -SRCS+= mpufoi_if.h SRCS+= emu10k1.c .include diff --git a/sys/dev/sound/driver/emu10kx/Makefile b/sys/dev/sound/driver/emu10kx/Makefile index b96e40db9e..7cebab757f 100644 --- a/sys/dev/sound/driver/emu10kx/Makefile +++ b/sys/dev/sound/driver/emu10kx/Makefile @@ -4,10 +4,9 @@ KMOD= snd_emu10kx SRCS= device_if.h bus_if.h pci_if.h -SRCS+= channel_if.h ac97_if.h mixer_if.h mpufoi_if.h +SRCS+= channel_if.h ac97_if.h mixer_if.h # Master, PCM and MIDI devices SRCS+= emu10kx.c SRCS+= emu10kx-pcm.c -SRCS+= emu10kx-midi.c .include diff --git a/sys/dev/sound/midi/midi.c b/sys/dev/sound/midi/midi.c deleted file mode 100644 index ace7dfc4db..0000000000 --- a/sys/dev/sound/midi/midi.c +++ /dev/null @@ -1,1531 +0,0 @@ -/*- - * Copyright (c) 2003 Mathew Kanner - * Copyright (c) 1998 The NetBSD Foundation, Inc. - * All rights reserved. - * - * This code is derived from software contributed to The NetBSD Foundation - * by Lennart Augustsson (augustss@netbsd.org). - * - * 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 NETBSD FOUNDATION, INC. 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 FOUNDATION 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. - */ - - /* - * Parts of this file started out as NetBSD: midi.c 1.31 - * They are mostly gone. Still the most obvious will be the state - * machine midi_in - */ - -#include -__FBSDID("$FreeBSD: head/sys/dev/sound/midi/midi.c 227309 2011-11-07 15:43:11Z ed $"); - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#ifdef HAVE_KERNEL_OPTION_HEADERS -#include "opt_snd.h" -#endif - -#include -#include "mpu_if.h" - -#include -#include "synth_if.h" -MALLOC_DEFINE(M_MIDI, "midi buffers", "Midi data allocation area"); - -#ifndef KOBJMETHOD_END -#define KOBJMETHOD_END { NULL, NULL } -#endif - -#define PCMMKMINOR(u, d, c) ((((c) & 0xff) << 16) | (((u) & 0x0f) << 4) | ((d) & 0x0f)) -#define MIDIMKMINOR(u, d, c) PCMMKMINOR(u, d, c) - -#define MIDI_DEV_RAW 2 -#define MIDI_DEV_MIDICTL 12 - -enum midi_states { - MIDI_IN_START, MIDI_IN_SYSEX, MIDI_IN_DATA -}; - -/* - * The MPU interface current has init() uninit() inqsize(( outqsize() - * callback() : fiddle with the tx|rx status. - */ - -#include "mpu_if.h" - -/* - * /dev/rmidi Structure definitions - */ - -#define MIDI_NAMELEN 16 -struct snd_midi { - KOBJ_FIELDS; - struct mtx lock; /* Protects all but queues */ - void *cookie; - - int unit; /* Should only be used in midistat */ - int channel; /* Should only be used in midistat */ - - int busy; - int flags; /* File flags */ - char name[MIDI_NAMELEN]; - struct mtx qlock; /* Protects inq, outq and flags */ - MIDIQ_HEAD(, char) inq, outq; - int rchan, wchan; - struct selinfo rsel, wsel; - int hiwat; /* QLEN(outq)>High-water -> disable - * writes from userland */ - enum midi_states inq_state; - int inq_status, inq_left; /* Variables for the state machine in - * Midi_in, this is to provide that - * signals only get issued only - * complete command packets. */ - struct proc *async; - struct cdev *dev; - struct synth_midi *synth; - int synth_flags; - TAILQ_ENTRY(snd_midi) link; -}; - -struct synth_midi { - KOBJ_FIELDS; - struct snd_midi *m; -}; - -static synth_open_t midisynth_open; -static synth_close_t midisynth_close; -static synth_writeraw_t midisynth_writeraw; -static synth_killnote_t midisynth_killnote; -static synth_startnote_t midisynth_startnote; -static synth_setinstr_t midisynth_setinstr; -static synth_alloc_t midisynth_alloc; -static synth_controller_t midisynth_controller; -static synth_bender_t midisynth_bender; - - -static kobj_method_t midisynth_methods[] = { - KOBJMETHOD(synth_open, midisynth_open), - KOBJMETHOD(synth_close, midisynth_close), - KOBJMETHOD(synth_writeraw, midisynth_writeraw), - KOBJMETHOD(synth_setinstr, midisynth_setinstr), - KOBJMETHOD(synth_startnote, midisynth_startnote), - KOBJMETHOD(synth_killnote, midisynth_killnote), - KOBJMETHOD(synth_alloc, midisynth_alloc), - KOBJMETHOD(synth_controller, midisynth_controller), - KOBJMETHOD(synth_bender, midisynth_bender), - KOBJMETHOD_END -}; - -DEFINE_CLASS(midisynth, midisynth_methods, 0); - -/* - * Module Exports & Interface - * - * struct midi_chan *midi_init(MPU_CLASS cls, int unit, int chan) int - * midi_uninit(struct snd_midi *) 0 == no error EBUSY or other error int - * Midi_in(struct midi_chan *, char *buf, int count) int Midi_out(struct - * midi_chan *, char *buf, int count) - * - * midi_{in,out} return actual size transfered - * - */ - - -/* - * midi_devs tailq, holder of all rmidi instances protected by midistat_lock - */ - -TAILQ_HEAD(, snd_midi) midi_devs; - -/* - * /dev/midistat variables and declarations, protected by midistat_lock - */ - -static struct mtx midistat_lock; -static int midistat_isopen = 0; -static struct sbuf midistat_sbuf; -static int midistat_bufptr; -static struct cdev *midistat_dev; - -/* - * /dev/midistat dev_t declarations - */ - -static d_open_t midistat_open; -static d_close_t midistat_close; -static d_read_t midistat_read; - -static struct cdevsw midistat_cdevsw = { - .d_version = D_VERSION, - .d_open = midistat_open, - .d_close = midistat_close, - .d_read = midistat_read, - .d_name = "midistat", -}; - - -/* - * /dev/rmidi dev_t declarations, struct variable access is protected by - * locks contained within the structure. - */ - -static d_open_t midi_open; -static d_close_t midi_close; -static d_ioctl_t midi_ioctl; -static d_read_t midi_read; -static d_write_t midi_write; -static d_poll_t midi_poll; - -static struct cdevsw midi_cdevsw = { - .d_version = D_VERSION, - .d_open = midi_open, - .d_close = midi_close, - .d_read = midi_read, - .d_write = midi_write, - .d_ioctl = midi_ioctl, - .d_poll = midi_poll, - .d_name = "rmidi", -}; - -/* - * Prototypes of library functions - */ - -static int midi_destroy(struct snd_midi *, int); -static int midistat_prepare(struct sbuf * s); -static int midi_load(void); -static int midi_unload(void); - -/* - * Misc declr. - */ -SYSCTL_NODE(_hw, OID_AUTO, midi, CTLFLAG_RD, 0, "Midi driver"); -static SYSCTL_NODE(_hw_midi, OID_AUTO, stat, CTLFLAG_RD, 0, "Status device"); - -int midi_debug; -/* XXX: should this be moved into debug.midi? */ -SYSCTL_INT(_hw_midi, OID_AUTO, debug, CTLFLAG_RW, &midi_debug, 0, ""); - -int midi_dumpraw; -SYSCTL_INT(_hw_midi, OID_AUTO, dumpraw, CTLFLAG_RW, &midi_dumpraw, 0, ""); - -int midi_instroff; -SYSCTL_INT(_hw_midi, OID_AUTO, instroff, CTLFLAG_RW, &midi_instroff, 0, ""); - -int midistat_verbose; -SYSCTL_INT(_hw_midi_stat, OID_AUTO, verbose, CTLFLAG_RW, - &midistat_verbose, 0, ""); - -#define MIDI_DEBUG(l,a) if(midi_debug>=l) a -/* - * CODE START - */ - -/* - * Register a new rmidi device. cls midi_if interface unit == 0 means - * auto-assign new unit number unit != 0 already assigned a unit number, eg. - * not the first channel provided by this device. channel, sub-unit - * cookie is passed back on MPU calls Typical device drivers will call with - * unit=0, channel=1..(number of channels) and cookie=soft_c and won't care - * what unit number is used. - * - * It is an error to call midi_init with an already used unit/channel combo. - * - * Returns NULL on error - * - */ -struct snd_midi * -midi_init(kobj_class_t cls, int unit, int channel, void *cookie) -{ - struct snd_midi *m; - int i; - int inqsize, outqsize; - MIDI_TYPE *buf; - - MIDI_DEBUG(1, printf("midiinit: unit %d/%d.\n", unit, channel)); - mtx_lock(&midistat_lock); - /* - * Protect against call with existing unit/channel or auto-allocate a - * new unit number. - */ - i = -1; - TAILQ_FOREACH(m, &midi_devs, link) { - mtx_lock(&m->lock); - if (unit != 0) { - if (m->unit == unit && m->channel == channel) { - mtx_unlock(&m->lock); - goto err0; - } - } else { - /* - * Find a better unit number - */ - if (m->unit > i) - i = m->unit; - } - mtx_unlock(&m->lock); - } - - if (unit == 0) - unit = i + 1; - - MIDI_DEBUG(1, printf("midiinit #2: unit %d/%d.\n", unit, channel)); - m = malloc(sizeof(*m), M_MIDI, M_NOWAIT | M_ZERO); - if (m == NULL) - goto err0; - - m->synth = malloc(sizeof(*m->synth), M_MIDI, M_NOWAIT | M_ZERO); - kobj_init((kobj_t)m->synth, &midisynth_class); - m->synth->m = m; - kobj_init((kobj_t)m, cls); - inqsize = MPU_INQSIZE(m, cookie); - outqsize = MPU_OUTQSIZE(m, cookie); - - MIDI_DEBUG(1, printf("midiinit queues %d/%d.\n", inqsize, outqsize)); - if (!inqsize && !outqsize) - goto err1; - - mtx_init(&m->lock, "raw midi", NULL, 0); - mtx_init(&m->qlock, "q raw midi", NULL, 0); - - mtx_lock(&m->lock); - mtx_lock(&m->qlock); - - if (inqsize) - buf = malloc(sizeof(MIDI_TYPE) * inqsize, M_MIDI, M_NOWAIT); - else - buf = NULL; - - MIDIQ_INIT(m->inq, buf, inqsize); - - if (outqsize) - buf = malloc(sizeof(MIDI_TYPE) * outqsize, M_MIDI, M_NOWAIT); - else - buf = NULL; - m->hiwat = outqsize / 2; - - MIDIQ_INIT(m->outq, buf, outqsize); - - if ((inqsize && !MIDIQ_BUF(m->inq)) || - (outqsize && !MIDIQ_BUF(m->outq))) - goto err2; - - - m->busy = 0; - m->flags = 0; - m->unit = unit; - m->channel = channel; - m->cookie = cookie; - - if (MPU_INIT(m, cookie)) - goto err2; - - mtx_unlock(&m->lock); - mtx_unlock(&m->qlock); - - TAILQ_INSERT_TAIL(&midi_devs, m, link); - - mtx_unlock(&midistat_lock); - - m->dev = make_dev(&midi_cdevsw, - MIDIMKMINOR(unit, MIDI_DEV_RAW, channel), - UID_ROOT, GID_WHEEL, 0666, "midi%d.%d", unit, channel); - m->dev->si_drv1 = m; - - return m; - -err2: mtx_destroy(&m->qlock); - mtx_destroy(&m->lock); - - if (MIDIQ_BUF(m->inq)) - free(MIDIQ_BUF(m->inq), M_MIDI); - if (MIDIQ_BUF(m->outq)) - free(MIDIQ_BUF(m->outq), M_MIDI); -err1: free(m, M_MIDI); -err0: mtx_unlock(&midistat_lock); - MIDI_DEBUG(1, printf("midi_init ended in error\n")); - return NULL; -} - -/* - * midi_uninit does not call MIDI_UNINIT, as since this is the implementors - * entry point. midi_unint if fact, does not send any methods. A call to - * midi_uninit is a defacto promise that you won't manipulate ch anymore - * - */ - -int -midi_uninit(struct snd_midi *m) -{ - int err; - - err = ENXIO; - mtx_lock(&midistat_lock); - mtx_lock(&m->lock); - if (m->busy) { - if (!(m->rchan || m->wchan)) - goto err; - - if (m->rchan) { - wakeup(&m->rchan); - m->rchan = 0; - } - if (m->wchan) { - wakeup(&m->wchan); - m->wchan = 0; - } - } - err = midi_destroy(m, 0); - if (!err) - goto exit; - -err: mtx_unlock(&m->lock); -exit: mtx_unlock(&midistat_lock); - return err; -} - -/* - * midi_in: process all data until the queue is full, then discards the rest. - * Since midi_in is a state machine, data discards can cause it to get out of - * whack. Process as much as possible. It calls, wakeup, selnotify and - * psignal at most once. - */ - -#ifdef notdef -static int midi_lengths[] = {2, 2, 2, 2, 1, 1, 2, 0}; - -#endif /* notdef */ -/* Number of bytes in a MIDI command */ -#define MIDI_LENGTH(d) (midi_lengths[((d) >> 4) & 7]) -#define MIDI_ACK 0xfe -#define MIDI_IS_STATUS(d) ((d) >= 0x80) -#define MIDI_IS_COMMON(d) ((d) >= 0xf0) - -#define MIDI_SYSEX_START 0xF0 -#define MIDI_SYSEX_END 0xF7 - - -int -midi_in(struct snd_midi *m, MIDI_TYPE *buf, int size) -{ - /* int i, sig, enq; */ - int used; - - /* MIDI_TYPE data; */ - MIDI_DEBUG(5, printf("midi_in: m=%p size=%d\n", m, size)); - -/* - * XXX: locking flub - */ - if (!(m->flags & M_RX)) - return size; - - used = 0; - - mtx_lock(&m->qlock); -#if 0 - /* - * Don't bother queuing if not in read mode. Discard everything and - * return size so the caller doesn't freak out. - */ - - if (!(m->flags & M_RX)) - return size; - - for (i = sig = 0; i < size; i++) { - - data = buf[i]; - enq = 0; - if (data == MIDI_ACK) - continue; - - switch (m->inq_state) { - case MIDI_IN_START: - if (MIDI_IS_STATUS(data)) { - switch (data) { - case 0xf0: /* Sysex */ - m->inq_state = MIDI_IN_SYSEX; - break; - case 0xf1: /* MTC quarter frame */ - case 0xf3: /* Song select */ - m->inq_state = MIDI_IN_DATA; - enq = 1; - m->inq_left = 1; - break; - case 0xf2: /* Song position pointer */ - m->inq_state = MIDI_IN_DATA; - enq = 1; - m->inq_left = 2; - break; - default: - if (MIDI_IS_COMMON(data)) { - enq = 1; - sig = 1; - } else { - m->inq_state = MIDI_IN_DATA; - enq = 1; - m->inq_status = data; - m->inq_left = MIDI_LENGTH(data); - } - break; - } - } else if (MIDI_IS_STATUS(m->inq_status)) { - m->inq_state = MIDI_IN_DATA; - if (!MIDIQ_FULL(m->inq)) { - used++; - MIDIQ_ENQ(m->inq, &m->inq_status, 1); - } - enq = 1; - m->inq_left = MIDI_LENGTH(m->inq_status) - 1; - } - break; - /* - * End of case MIDI_IN_START: - */ - - case MIDI_IN_DATA: - enq = 1; - if (--m->inq_left <= 0) - sig = 1;/* deliver data */ - break; - case MIDI_IN_SYSEX: - if (data == MIDI_SYSEX_END) - m->inq_state = MIDI_IN_START; - break; - } - - if (enq) - if (!MIDIQ_FULL(m->inq)) { - MIDIQ_ENQ(m->inq, &data, 1); - used++; - } - /* - * End of the state machines main "for loop" - */ - } - if (sig) { -#endif - MIDI_DEBUG(6, printf("midi_in: len %jd avail %jd\n", - (intmax_t)MIDIQ_LEN(m->inq), - (intmax_t)MIDIQ_AVAIL(m->inq))); - if (MIDIQ_AVAIL(m->inq) > size) { - used = size; - MIDIQ_ENQ(m->inq, buf, size); - } else { - MIDI_DEBUG(4, printf("midi_in: Discarding data qu\n")); - mtx_unlock(&m->qlock); - return 0; - } - if (m->rchan) { - wakeup(&m->rchan); - m->rchan = 0; - } - selwakeup(&m->rsel); - if (m->async) { - PROC_LOCK(m->async); - kern_psignal(m->async, SIGIO); - PROC_UNLOCK(m->async); - } -#if 0 - } -#endif - mtx_unlock(&m->qlock); - return used; -} - -/* - * midi_out: The only clearer of the M_TXEN flag. - */ -int -midi_out(struct snd_midi *m, MIDI_TYPE *buf, int size) -{ - int used; - -/* - * XXX: locking flub - */ - if (!(m->flags & M_TXEN)) - return 0; - - MIDI_DEBUG(2, printf("midi_out: %p\n", m)); - mtx_lock(&m->qlock); - used = MIN(size, MIDIQ_LEN(m->outq)); - MIDI_DEBUG(3, printf("midi_out: used %d\n", used)); - if (used) - MIDIQ_DEQ(m->outq, buf, used); - if (MIDIQ_EMPTY(m->outq)) { - m->flags &= ~M_TXEN; - MPU_CALLBACKP(m, m->cookie, m->flags); - } - if (used && MIDIQ_AVAIL(m->outq) > m->hiwat) { - if (m->wchan) { - wakeup(&m->wchan); - m->wchan = 0; - } - selwakeup(&m->wsel); - if (m->async) { - PROC_LOCK(m->async); - kern_psignal(m->async, SIGIO); - PROC_UNLOCK(m->async); - } - } - mtx_unlock(&m->qlock); - return used; -} - - -/* - * /dev/rmidi#.# device access functions - */ -int -midi_open(struct cdev *i_dev, int flags, int mode, struct thread *td) -{ - struct snd_midi *m = i_dev->si_drv1; - int retval; - - MIDI_DEBUG(1, printf("midiopen %p %s %s\n", td, - flags & FREAD ? "M_RX" : "", flags & FWRITE ? "M_TX" : "")); - if (m == NULL) - return ENXIO; - - mtx_lock(&m->lock); - mtx_lock(&m->qlock); - - retval = 0; - - if (flags & FREAD) { - if (MIDIQ_SIZE(m->inq) == 0) - retval = ENXIO; - else if (m->flags & M_RX) - retval = EBUSY; - if (retval) - goto err; - } - if (flags & FWRITE) { - if (MIDIQ_SIZE(m->outq) == 0) - retval = ENXIO; - else if (m->flags & M_TX) - retval = EBUSY; - if (retval) - goto err; - } - m->busy++; - - m->rchan = 0; - m->wchan = 0; - m->async = 0; - - if (flags & FREAD) { - m->flags |= M_RX | M_RXEN; - /* - * Only clear the inq, the outq might still have data to drain - * from a previous session - */ - MIDIQ_CLEAR(m->inq); - }; - - if (flags & FWRITE) - m->flags |= M_TX; - - MPU_CALLBACK(m, m->cookie, m->flags); - - MIDI_DEBUG(2, printf("midi_open: opened.\n")); - -err: mtx_unlock(&m->qlock); - mtx_unlock(&m->lock); - return retval; -} - -int -midi_close(struct cdev *i_dev, int flags, int mode, struct thread *td) -{ - struct snd_midi *m = i_dev->si_drv1; - int retval; - int oldflags; - - MIDI_DEBUG(1, printf("midi_close %p %s %s\n", td, - flags & FREAD ? "M_RX" : "", flags & FWRITE ? "M_TX" : "")); - - if (m == NULL) - return ENXIO; - - mtx_lock(&m->lock); - mtx_lock(&m->qlock); - - if ((flags & FREAD && !(m->flags & M_RX)) || - (flags & FWRITE && !(m->flags & M_TX))) { - retval = ENXIO; - goto err; - } - m->busy--; - - oldflags = m->flags; - - if (flags & FREAD) - m->flags &= ~(M_RX | M_RXEN); - if (flags & FWRITE) - m->flags &= ~M_TX; - - if ((m->flags & (M_TXEN | M_RXEN)) != (oldflags & (M_RXEN | M_TXEN))) - MPU_CALLBACK(m, m->cookie, m->flags); - - MIDI_DEBUG(1, printf("midi_close: closed, busy = %d.\n", m->busy)); - - mtx_unlock(&m->qlock); - mtx_unlock(&m->lock); - retval = 0; -err: return retval; -} - -/* - * TODO: midi_read, per oss programmer's guide pg. 42 should return as soon - * as data is available. - */ -int -midi_read(struct cdev *i_dev, struct uio *uio, int ioflag) -{ -#define MIDI_RSIZE 32 - struct snd_midi *m = i_dev->si_drv1; - int retval; - int used; - char buf[MIDI_RSIZE]; - - MIDI_DEBUG(5, printf("midiread: count=%lu\n", - (unsigned long)uio->uio_resid)); - - retval = EIO; - - if (m == NULL) - goto err0; - - mtx_lock(&m->lock); - mtx_lock(&m->qlock); - - if (!(m->flags & M_RX)) - goto err1; - - while (uio->uio_resid > 0) { - while (MIDIQ_EMPTY(m->inq)) { - retval = EWOULDBLOCK; - if (ioflag & O_NONBLOCK) - goto err1; - mtx_unlock(&m->lock); - m->rchan = 1; - retval = msleep(&m->rchan, &m->qlock, - PCATCH | PDROP, "midi RX", 0); - /* - * We slept, maybe things have changed since last - * dying check - */ - if (retval == EINTR) - goto err0; - if (m != i_dev->si_drv1) - retval = ENXIO; - /* if (retval && retval != ERESTART) */ - if (retval) - goto err0; - mtx_lock(&m->lock); - mtx_lock(&m->qlock); - m->rchan = 0; - if (!m->busy) - goto err1; - } - MIDI_DEBUG(6, printf("midi_read start\n")); - /* - * At this point, it is certain that m->inq has data - */ - - used = MIN(MIDIQ_LEN(m->inq), uio->uio_resid); - used = MIN(used, MIDI_RSIZE); - - MIDI_DEBUG(6, printf("midiread: uiomove cc=%d\n", used)); - MIDIQ_DEQ(m->inq, buf, used); - retval = uiomove(buf, used, uio); - if (retval) - goto err1; - } - - /* - * If we Made it here then transfer is good - */ - retval = 0; -err1: mtx_unlock(&m->qlock); - mtx_unlock(&m->lock); -err0: MIDI_DEBUG(4, printf("midi_read: ret %d\n", retval)); - return retval; -} - -/* - * midi_write: The only setter of M_TXEN - */ - -int -midi_write(struct cdev *i_dev, struct uio *uio, int ioflag) -{ -#define MIDI_WSIZE 32 - struct snd_midi *m = i_dev->si_drv1; - int retval; - int used; - char buf[MIDI_WSIZE]; - - - MIDI_DEBUG(4, printf("midi_write\n")); - retval = 0; - if (m == NULL) - goto err0; - - mtx_lock(&m->lock); - mtx_lock(&m->qlock); - - if (!(m->flags & M_TX)) - goto err1; - - while (uio->uio_resid > 0) { - while (MIDIQ_AVAIL(m->outq) == 0) { - retval = EWOULDBLOCK; - if (ioflag & O_NONBLOCK) - goto err1; - mtx_unlock(&m->lock); - m->wchan = 1; - MIDI_DEBUG(3, printf("midi_write msleep\n")); - retval = msleep(&m->wchan, &m->qlock, - PCATCH | PDROP, "midi TX", 0); - /* - * We slept, maybe things have changed since last - * dying check - */ - if (retval == EINTR) - goto err0; - if (m != i_dev->si_drv1) - retval = ENXIO; - if (retval) - goto err0; - mtx_lock(&m->lock); - mtx_lock(&m->qlock); - m->wchan = 0; - if (!m->busy) - goto err1; - } - - /* - * We are certain than data can be placed on the queue - */ - - used = MIN(MIDIQ_AVAIL(m->outq), uio->uio_resid); - used = MIN(used, MIDI_WSIZE); - MIDI_DEBUG(5, printf("midiout: resid %zd len %jd avail %jd\n", - uio->uio_resid, (intmax_t)MIDIQ_LEN(m->outq), - (intmax_t)MIDIQ_AVAIL(m->outq))); - - - MIDI_DEBUG(5, printf("midi_write: uiomove cc=%d\n", used)); - retval = uiomove(buf, used, uio); - if (retval) - goto err1; - MIDIQ_ENQ(m->outq, buf, used); - /* - * Inform the bottom half that data can be written - */ - if (!(m->flags & M_TXEN)) { - m->flags |= M_TXEN; - MPU_CALLBACK(m, m->cookie, m->flags); - } - } - /* - * If we Made it here then transfer is good - */ - retval = 0; -err1: mtx_unlock(&m->qlock); - mtx_unlock(&m->lock); -err0: return retval; -} - -int -midi_ioctl(struct cdev *i_dev, u_long cmd, caddr_t arg, int mode, - struct thread *td) -{ - return ENXIO; -} - -int -midi_poll(struct cdev *i_dev, int events, struct thread *td) -{ - struct snd_midi *m = i_dev->si_drv1; - int revents; - - if (m == NULL) - return 0; - - revents = 0; - - mtx_lock(&m->lock); - mtx_lock(&m->qlock); - - if (events & (POLLIN | POLLRDNORM)) - if (!MIDIQ_EMPTY(m->inq)) - events |= events & (POLLIN | POLLRDNORM); - - if (events & (POLLOUT | POLLWRNORM)) - if (MIDIQ_AVAIL(m->outq) < m->hiwat) - events |= events & (POLLOUT | POLLWRNORM); - - if (revents == 0) { - if (events & (POLLIN | POLLRDNORM)) - selrecord(td, &m->rsel); - - if (events & (POLLOUT | POLLWRNORM)) - selrecord(td, &m->wsel); - } - mtx_unlock(&m->lock); - mtx_unlock(&m->qlock); - - return (revents); -} - -/* - * /dev/midistat device functions - * - */ -static int -midistat_open(struct cdev *i_dev, int flags, int mode, struct thread *td) -{ - int error; - - MIDI_DEBUG(1, printf("midistat_open\n")); - mtx_lock(&midistat_lock); - - if (midistat_isopen) { - mtx_unlock(&midistat_lock); - return EBUSY; - } - midistat_isopen = 1; - mtx_unlock(&midistat_lock); - - if (sbuf_new(&midistat_sbuf, NULL, 4096, SBUF_AUTOEXTEND) == NULL) { - error = ENXIO; - mtx_lock(&midistat_lock); - goto out; - } - mtx_lock(&midistat_lock); - midistat_bufptr = 0; - error = (midistat_prepare(&midistat_sbuf) > 0) ? 0 : ENOMEM; - -out: if (error) - midistat_isopen = 0; - mtx_unlock(&midistat_lock); - return error; -} - -static int -midistat_close(struct cdev *i_dev, int flags, int mode, struct thread *td) -{ - MIDI_DEBUG(1, printf("midistat_close\n")); - mtx_lock(&midistat_lock); - if (!midistat_isopen) { - mtx_unlock(&midistat_lock); - return EBADF; - } - sbuf_delete(&midistat_sbuf); - midistat_isopen = 0; - - mtx_unlock(&midistat_lock); - return 0; -} - -static int -midistat_read(struct cdev *i_dev, struct uio *buf, int flag) -{ - int l, err; - - MIDI_DEBUG(4, printf("midistat_read\n")); - mtx_lock(&midistat_lock); - if (!midistat_isopen) { - mtx_unlock(&midistat_lock); - return EBADF; - } - l = min(buf->uio_resid, sbuf_len(&midistat_sbuf) - midistat_bufptr); - err = 0; - if (l > 0) { - mtx_unlock(&midistat_lock); - err = uiomove(sbuf_data(&midistat_sbuf) + midistat_bufptr, l, - buf); - mtx_lock(&midistat_lock); - } else - l = 0; - midistat_bufptr += l; - mtx_unlock(&midistat_lock); - return err; -} - -/* - * Module library functions - */ - -static int -midistat_prepare(struct sbuf *s) -{ - struct snd_midi *m; - - mtx_assert(&midistat_lock, MA_OWNED); - - sbuf_printf(s, "FreeBSD Midi Driver (midi2)\n"); - if (TAILQ_EMPTY(&midi_devs)) { - sbuf_printf(s, "No devices installed.\n"); - sbuf_finish(s); - return sbuf_len(s); - } - sbuf_printf(s, "Installed devices:\n"); - - TAILQ_FOREACH(m, &midi_devs, link) { - mtx_lock(&m->lock); - sbuf_printf(s, "%s [%d/%d:%s]", m->name, m->unit, m->channel, - MPU_PROVIDER(m, m->cookie)); - sbuf_printf(s, "%s", MPU_DESCR(m, m->cookie, midistat_verbose)); - sbuf_printf(s, "\n"); - mtx_unlock(&m->lock); - } - - sbuf_finish(s); - return sbuf_len(s); -} - -#ifdef notdef -/* - * Convert IOCTL command to string for debugging - */ - -static char * -midi_cmdname(int cmd) -{ - static struct { - int cmd; - char *name; - } *tab, cmdtab_midiioctl[] = { -#define A(x) {x, ## x} - /* - * Once we have some real IOCTLs define, the following will - * be relavant. - * - * A(SNDCTL_MIDI_PRETIME), A(SNDCTL_MIDI_MPUMODE), - * A(SNDCTL_MIDI_MPUCMD), A(SNDCTL_SYNTH_INFO), - * A(SNDCTL_MIDI_INFO), A(SNDCTL_SYNTH_MEMAVL), - * A(SNDCTL_FM_LOAD_INSTR), A(SNDCTL_FM_4OP_ENABLE), - * A(MIOSPASSTHRU), A(MIOGPASSTHRU), A(AIONWRITE), - * A(AIOGSIZE), A(AIOSSIZE), A(AIOGFMT), A(AIOSFMT), - * A(AIOGMIX), A(AIOSMIX), A(AIOSTOP), A(AIOSYNC), - * A(AIOGCAP), - */ -#undef A - { - -1, "unknown" - }, - }; - - for (tab = cmdtab_midiioctl; tab->cmd != cmd && tab->cmd != -1; tab++); - return tab->name; -} - -#endif /* notdef */ - -/* - * midisynth - */ - - -int -midisynth_open(void *n, void *arg, int flags) -{ - struct snd_midi *m = ((struct synth_midi *)n)->m; - int retval; - - MIDI_DEBUG(1, printf("midisynth_open %s %s\n", - flags & FREAD ? "M_RX" : "", flags & FWRITE ? "M_TX" : "")); - - if (m == NULL) - return ENXIO; - - mtx_lock(&m->lock); - mtx_lock(&m->qlock); - - retval = 0; - - if (flags & FREAD) { - if (MIDIQ_SIZE(m->inq) == 0) - retval = ENXIO; - else if (m->flags & M_RX) - retval = EBUSY; - if (retval) - goto err; - } - if (flags & FWRITE) { - if (MIDIQ_SIZE(m->outq) == 0) - retval = ENXIO; - else if (m->flags & M_TX) - retval = EBUSY; - if (retval) - goto err; - } - m->busy++; - - /* - * TODO: Consider m->async = 0; - */ - - if (flags & FREAD) { - m->flags |= M_RX | M_RXEN; - /* - * Only clear the inq, the outq might still have data to drain - * from a previous session - */ - MIDIQ_CLEAR(m->inq); - m->rchan = 0; - }; - - if (flags & FWRITE) { - m->flags |= M_TX; - m->wchan = 0; - } - m->synth_flags = flags & (FREAD | FWRITE); - - MPU_CALLBACK(m, m->cookie, m->flags); - - -err: mtx_unlock(&m->qlock); - mtx_unlock(&m->lock); - MIDI_DEBUG(2, printf("midisynth_open: return %d.\n", retval)); - return retval; -} - -int -midisynth_close(void *n) -{ - struct snd_midi *m = ((struct synth_midi *)n)->m; - int retval; - int oldflags; - - MIDI_DEBUG(1, printf("midisynth_close %s %s\n", - m->synth_flags & FREAD ? "M_RX" : "", - m->synth_flags & FWRITE ? "M_TX" : "")); - - if (m == NULL) - return ENXIO; - - mtx_lock(&m->lock); - mtx_lock(&m->qlock); - - if ((m->synth_flags & FREAD && !(m->flags & M_RX)) || - (m->synth_flags & FWRITE && !(m->flags & M_TX))) { - retval = ENXIO; - goto err; - } - m->busy--; - - oldflags = m->flags; - - if (m->synth_flags & FREAD) - m->flags &= ~(M_RX | M_RXEN); - if (m->synth_flags & FWRITE) - m->flags &= ~M_TX; - - if ((m->flags & (M_TXEN | M_RXEN)) != (oldflags & (M_RXEN | M_TXEN))) - MPU_CALLBACK(m, m->cookie, m->flags); - - MIDI_DEBUG(1, printf("midi_close: closed, busy = %d.\n", m->busy)); - - mtx_unlock(&m->qlock); - mtx_unlock(&m->lock); - retval = 0; -err: return retval; -} - -/* - * Always blocking. - */ - -int -midisynth_writeraw(void *n, uint8_t *buf, size_t len) -{ - struct snd_midi *m = ((struct synth_midi *)n)->m; - int retval; - int used; - int i; - - MIDI_DEBUG(4, printf("midisynth_writeraw\n")); - - retval = 0; - - if (m == NULL) - return ENXIO; - - mtx_lock(&m->lock); - mtx_lock(&m->qlock); - - if (!(m->flags & M_TX)) - goto err1; - - if (midi_dumpraw) - printf("midi dump: "); - - while (len > 0) { - while (MIDIQ_AVAIL(m->outq) == 0) { - if (!(m->flags & M_TXEN)) { - m->flags |= M_TXEN; - MPU_CALLBACK(m, m->cookie, m->flags); - } - mtx_unlock(&m->lock); - m->wchan = 1; - MIDI_DEBUG(3, printf("midisynth_writeraw msleep\n")); - retval = msleep(&m->wchan, &m->qlock, - PCATCH | PDROP, "midi TX", 0); - /* - * We slept, maybe things have changed since last - * dying check - */ - if (retval == EINTR) - goto err0; - - if (retval) - goto err0; - mtx_lock(&m->lock); - mtx_lock(&m->qlock); - m->wchan = 0; - if (!m->busy) - goto err1; - } - - /* - * We are certain than data can be placed on the queue - */ - - used = MIN(MIDIQ_AVAIL(m->outq), len); - used = MIN(used, MIDI_WSIZE); - MIDI_DEBUG(5, - printf("midi_synth: resid %zu len %jd avail %jd\n", - len, (intmax_t)MIDIQ_LEN(m->outq), - (intmax_t)MIDIQ_AVAIL(m->outq))); - - if (midi_dumpraw) - for (i = 0; i < used; i++) - printf("%x ", buf[i]); - - MIDIQ_ENQ(m->outq, buf, used); - len -= used; - - /* - * Inform the bottom half that data can be written - */ - if (!(m->flags & M_TXEN)) { - m->flags |= M_TXEN; - MPU_CALLBACK(m, m->cookie, m->flags); - } - } - /* - * If we Made it here then transfer is good - */ - if (midi_dumpraw) - printf("\n"); - - retval = 0; -err1: mtx_unlock(&m->qlock); - mtx_unlock(&m->lock); -err0: return retval; -} - -static int -midisynth_killnote(void *n, uint8_t chn, uint8_t note, uint8_t vel) -{ - u_char c[3]; - - - if (note > 127 || chn > 15) - return (EINVAL); - - if (vel > 127) - vel = 127; - - if (vel == 64) { - c[0] = 0x90 | (chn & 0x0f); /* Note on. */ - c[1] = (u_char)note; - c[2] = 0; - } else { - c[0] = 0x80 | (chn & 0x0f); /* Note off. */ - c[1] = (u_char)note; - c[2] = (u_char)vel; - } - - return midisynth_writeraw(n, c, 3); -} - -static int -midisynth_setinstr(void *n, uint8_t chn, uint16_t instr) -{ - u_char c[2]; - - if (instr > 127 || chn > 15) - return EINVAL; - - c[0] = 0xc0 | (chn & 0x0f); /* Progamme change. */ - c[1] = instr + midi_instroff; - - return midisynth_writeraw(n, c, 2); -} - -static int -midisynth_startnote(void *n, uint8_t chn, uint8_t note, uint8_t vel) -{ - u_char c[3]; - - if (note > 127 || chn > 15) - return EINVAL; - - if (vel > 127) - vel = 127; - - c[0] = 0x90 | (chn & 0x0f); /* Note on. */ - c[1] = (u_char)note; - c[2] = (u_char)vel; - - return midisynth_writeraw(n, c, 3); -} -static int -midisynth_alloc(void *n, uint8_t chan, uint8_t note) -{ - return chan; -} - -static int -midisynth_controller(void *n, uint8_t chn, uint8_t ctrlnum, uint16_t val) -{ - u_char c[3]; - - if (ctrlnum > 127 || chn > 15) - return EINVAL; - - c[0] = 0xb0 | (chn & 0x0f); /* Control Message. */ - c[1] = ctrlnum; - c[2] = val; - return midisynth_writeraw(n, c, 3); -} - -static int -midisynth_bender(void *n, uint8_t chn, uint16_t val) -{ - u_char c[3]; - - - if (val > 16383 || chn > 15) - return EINVAL; - - c[0] = 0xe0 | (chn & 0x0f); /* Pitch bend. */ - c[1] = (u_char)val & 0x7f; - c[2] = (u_char)(val >> 7) & 0x7f; - - return midisynth_writeraw(n, c, 3); -} - -/* - * Single point of midi destructions. - */ -static int -midi_destroy(struct snd_midi *m, int midiuninit) -{ - - mtx_assert(&midistat_lock, MA_OWNED); - mtx_assert(&m->lock, MA_OWNED); - - MIDI_DEBUG(3, printf("midi_destroy\n")); - m->dev->si_drv1 = NULL; - mtx_unlock(&m->lock); /* XXX */ - destroy_dev(m->dev); - TAILQ_REMOVE(&midi_devs, m, link); - if (midiuninit) - MPU_UNINIT(m, m->cookie); - free(MIDIQ_BUF(m->inq), M_MIDI); - free(MIDIQ_BUF(m->outq), M_MIDI); - mtx_destroy(&m->qlock); - mtx_destroy(&m->lock); - free(m, M_MIDI); - return 0; -} - -/* - * Load and unload functions, creates the /dev/midistat device - */ - -static int -midi_load() -{ - mtx_init(&midistat_lock, "midistat lock", NULL, 0); - TAILQ_INIT(&midi_devs); /* Initialize the queue. */ - - midistat_dev = make_dev(&midistat_cdevsw, - MIDIMKMINOR(0, MIDI_DEV_MIDICTL, 0), - UID_ROOT, GID_WHEEL, 0666, "midistat"); - - return 0; -} - -static int -midi_unload() -{ - struct snd_midi *m; - int retval; - - MIDI_DEBUG(1, printf("midi_unload()\n")); - retval = EBUSY; - mtx_lock(&midistat_lock); - if (midistat_isopen) - goto exit0; - - TAILQ_FOREACH(m, &midi_devs, link) { - mtx_lock(&m->lock); - if (m->busy) - retval = EBUSY; - else - retval = midi_destroy(m, 1); - if (retval) - goto exit1; - } - - mtx_unlock(&midistat_lock); /* XXX */ - - destroy_dev(midistat_dev); - /* - * Made it here then unload is complete - */ - mtx_destroy(&midistat_lock); - return 0; - -exit1: - mtx_unlock(&m->lock); -exit0: - mtx_unlock(&midistat_lock); - if (retval) - MIDI_DEBUG(2, printf("midi_unload: failed\n")); - return retval; -} - -extern int seq_modevent(module_t mod, int type, void *data); - -static int -midi_modevent(module_t mod, int type, void *data) -{ - int retval; - - retval = 0; - - switch (type) { - case MOD_LOAD: - retval = midi_load(); -#if 0 - if (retval == 0) - retval = seq_modevent(mod, type, data); -#endif - break; - - case MOD_UNLOAD: - retval = midi_unload(); -#if 0 - if (retval == 0) - retval = seq_modevent(mod, type, data); -#endif - break; - - default: - break; - } - - return retval; -} - -kobj_t -midimapper_addseq(void *arg1, int *unit, void **cookie) -{ - unit = 0; - - return (kobj_t)arg1; -} - -int -midimapper_open(void *arg1, void **cookie) -{ - int retval = 0; - struct snd_midi *m; - - mtx_lock(&midistat_lock); - - TAILQ_FOREACH(m, &midi_devs, link) { - retval++; - } - - mtx_unlock(&midistat_lock); - return retval; -} - -int -midimapper_close(void *arg1, void *cookie) -{ - return 0; -} - -kobj_t -midimapper_fetch_synth(void *arg, void *cookie, int unit) -{ - struct snd_midi *m; - int retval = 0; - - mtx_lock(&midistat_lock); - - TAILQ_FOREACH(m, &midi_devs, link) { - if (unit == retval) { - mtx_unlock(&midistat_lock); - return (kobj_t)m->synth; - } - retval++; - } - - mtx_unlock(&midistat_lock); - return NULL; -} - -DEV_MODULE(midi, midi_modevent, NULL); -MODULE_VERSION(midi, 1); diff --git a/sys/dev/sound/midi/midi.h b/sys/dev/sound/midi/midi.h deleted file mode 100644 index 3a13db27b5..0000000000 --- a/sys/dev/sound/midi/midi.h +++ /dev/null @@ -1,57 +0,0 @@ -/*- - * Copyright (c) 2003 Mathew Kanner - * All rights reserved. - * - * 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: head/sys/dev/sound/midi/midi.h 166971 2007-02-25 13:51:52Z netchild $ - */ - -#ifndef MIDI_H -#define MIDI_H - -#include -#include - -MALLOC_DECLARE(M_MIDI); - -#define M_RX 0x01 -#define M_TX 0x02 -#define M_RXEN 0x04 -#define M_TXEN 0x08 - -#define MIDI_TYPE unsigned char - -struct snd_midi; - -struct snd_midi * -midi_init(kobj_class_t _mpu_cls, int _unit, int _channel, void *cookie); -int midi_uninit(struct snd_midi *_m); -int midi_out(struct snd_midi *_m, MIDI_TYPE *_buf, int _size); -int midi_in(struct snd_midi *_m, MIDI_TYPE *_buf, int _size); - -kobj_t midimapper_addseq(void *arg1, int *unit, void **cookie); -int midimapper_open(void *arg1, void **cookie); -int midimapper_close(void *arg1, void *cookie); -kobj_t midimapper_fetch_synth(void *arg, void *cookie, int unit); - -#endif diff --git a/sys/dev/sound/midi/midiq.h b/sys/dev/sound/midi/midiq.h deleted file mode 100644 index 14fb25da1a..0000000000 --- a/sys/dev/sound/midi/midiq.h +++ /dev/null @@ -1,106 +0,0 @@ -/*- - * Copyright (c) 2003 Mathew Kanner - * All rights reserved. - * - * 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: head/sys/dev/sound/midi/midiq.h 166971 2007-02-25 13:51:52Z netchild $ - */ - -#ifndef MIDIQ_H -#define MIDIQ_H - -#define MIDIQ_MOVE(a,b,c) bcopy(b,a,c) - -#define MIDIQ_HEAD(name, type) \ -struct name { \ - int h, t, s; \ - type * b; \ -} - -#define MIDIQ_INIT(head, buf, size) do { \ - (head).h=(head).t=0; \ - (head).s=size; \ - (head).b=buf; \ -} while (0) - -#define MIDIQ_EMPTY(head) ((head).h == (head).t ) - -#define MIDIQ_LENBASE(head) ((head).h - (head).t < 0 ? \ - (head).h - (head).t + (head).s : \ - (head).h - (head).t) - -#define MIDIQ_FULL(head) ((head).h == -1) -#define MIDIQ_AVAIL(head) (MIDIQ_FULL(head) ? 0 : (head).s - MIDIQ_LENBASE(head)) -#define MIDIQ_LEN(head) ((head).s - MIDIQ_AVAIL(head)) -#define MIDIQ_DEBUG 0 -/* - * No protection against overflow, underflow - */ -#define MIDIQ_ENQ(head, buf, size) do { \ - if(MIDIQ_DEBUG)\ - printf("#1 %p %p bytes copied %jd tran req s %d h %d t %d\n", \ - &(head).b[(head).h], (buf), \ - (intmax_t)(sizeof(*(head).b) * \ - MIN( (size), (head).s - (head).h) ), \ - (size), (head).h, (head).t); \ - MIDIQ_MOVE(&(head).b[(head).h], (buf), sizeof(*(head).b) * MIN((size), (head).s - (head).h)); \ - if( (head).s - (head).h < (size) ) { \ - if(MIDIQ_DEBUG) \ - printf("#2 %p %p bytes copied %jd\n", (head).b, (buf) + (head).s - (head).h, (intmax_t)sizeof(*(head).b) * ((size) - (head).s + (head).h) ); \ - MIDIQ_MOVE((head).b, (buf) + (head).s - (head).h, sizeof(*(head).b) * ((size) - (head).s + (head).h) ); \ - } \ - (head).h+=(size); \ - (head).h%=(head).s; \ - if(MIDIQ_EMPTY(head)) (head).h=-1; \ - if(MIDIQ_DEBUG)\ - printf("#E h %d t %d\n", (head).h, (head).t); \ -} while (0) - -#define MIDIQ_DEQ_I(head, buf, size, move, update) do { \ - if(MIDIQ_FULL(head)) (head).h=(head).t; \ - if(MIDIQ_DEBUG)\ - printf("#1 %p %p bytes copied %jd tran req s %d h %d t %d\n", &(head).b[(head).t], (buf), (intmax_t)sizeof(*(head).b) * MIN((size), (head).s - (head).t), (size), (head).h, (head).t); \ - if (move) MIDIQ_MOVE((buf), &(head).b[(head).t], sizeof(*(head).b) * MIN((size), (head).s - (head).t)); \ - if( (head).s - (head).t < (size) ) { \ - if(MIDIQ_DEBUG) \ - printf("#2 %p %p bytes copied %jd\n", (head).b, (buf) + (head).s - (head).t, (intmax_t)sizeof(*(head).b) * ((size) - (head).s + (head).t) ); \ - if (move) MIDIQ_MOVE((buf) + (head).s - (head).t, (head).b, sizeof(*(head).b) * ((size) - (head).s + (head).t) ); \ - } \ - if (update) { \ - (head).t+=(size); \ - (head).t%=(head).s; \ - } else { \ - if (MIDIQ_EMPTY(head)) (head).h=-1; \ - } \ - if(MIDIQ_DEBUG)\ - printf("#E h %d t %d\n", (head).h, (head).t); \ -} while (0) - -#define MIDIQ_SIZE(head) ((head).s) -#define MIDIQ_CLEAR(head) ((head).h = (head).t = 0) -#define MIDIQ_BUF(head) ((head).b) -#define MIDIQ_DEQ(head, buf, size) MIDIQ_DEQ_I(head, buf, size, 1, 1) -#define MIDIQ_PEEK(head, buf, size) MIDIQ_DEQ_I(head, buf, size, 1, 0) -#define MIDIQ_POP(head, size) MIDIQ_DEQ_I(head, &head, size, 0, 1) - -#endif diff --git a/sys/dev/sound/midi/mpu401.c b/sys/dev/sound/midi/mpu401.c deleted file mode 100644 index e567d15d2e..0000000000 --- a/sys/dev/sound/midi/mpu401.c +++ /dev/null @@ -1,298 +0,0 @@ -/*- - * Copyright (c) 2003 Mathew Kanner - * All rights reserved. - * - * 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. - */ - -#include -__FBSDID("$FreeBSD: head/sys/dev/sound/midi/mpu401.c 193979 2009-06-11 09:06:09Z ariff $"); - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include /* to get driver_intr_t */ - -#ifdef HAVE_KERNEL_OPTION_HEADERS -#include "opt_snd.h" -#endif - -#include -#include - -#include "mpu_if.h" -#include "mpufoi_if.h" - -#ifndef KOBJMETHOD_END -#define KOBJMETHOD_END { NULL, NULL } -#endif - -#define MPU_DATAPORT 0 -#define MPU_CMDPORT 1 -#define MPU_STATPORT 1 -#define MPU_RESET 0xff -#define MPU_UART 0x3f -#define MPU_ACK 0xfe -#define MPU_STATMASK 0xc0 -#define MPU_OUTPUTBUSY 0x40 -#define MPU_INPUTBUSY 0x80 -#define MPU_TRYDATA 50 -#define MPU_DELAY 2500 - -#define CMD(m,d) MPUFOI_WRITE(m, m->cookie, MPU_CMDPORT,d) -#define STATUS(m) MPUFOI_READ(m, m->cookie, MPU_STATPORT) -#define READ(m) MPUFOI_READ(m, m->cookie, MPU_DATAPORT) -#define WRITE(m,d) MPUFOI_WRITE(m, m->cookie, MPU_DATAPORT,d) - -struct mpu401 { - KOBJ_FIELDS; - struct snd_midi *mid; - int flags; - driver_intr_t *si; - void *cookie; - struct callout timer; -}; - -static void mpu401_timeout(void *m); -static mpu401_intr_t mpu401_intr; - -static int mpu401_minit(struct snd_midi *, void *); -static int mpu401_muninit(struct snd_midi *, void *); -static int mpu401_minqsize(struct snd_midi *, void *); -static int mpu401_moutqsize(struct snd_midi *, void *); -static void mpu401_mcallback(struct snd_midi *, void *, int); -static void mpu401_mcallbackp(struct snd_midi *, void *, int); -static const char *mpu401_mdescr(struct snd_midi *, void *, int); -static const char *mpu401_mprovider(struct snd_midi *, void *); - -static kobj_method_t mpu401_methods[] = { - KOBJMETHOD(mpu_init, mpu401_minit), - KOBJMETHOD(mpu_uninit, mpu401_muninit), - KOBJMETHOD(mpu_inqsize, mpu401_minqsize), - KOBJMETHOD(mpu_outqsize, mpu401_moutqsize), - KOBJMETHOD(mpu_callback, mpu401_mcallback), - KOBJMETHOD(mpu_callbackp, mpu401_mcallbackp), - KOBJMETHOD(mpu_descr, mpu401_mdescr), - KOBJMETHOD(mpu_provider, mpu401_mprovider), - KOBJMETHOD_END -}; - -DEFINE_CLASS(mpu401, mpu401_methods, 0); - -void -mpu401_timeout(void *a) -{ - struct mpu401 *m = (struct mpu401 *)a; - - if (m->si) - (m->si)(m->cookie); - -} -static int -mpu401_intr(struct mpu401 *m) -{ -#define MPU_INTR_BUF 16 - MIDI_TYPE b[MPU_INTR_BUF]; - int i; - int s; - -/* - printf("mpu401_intr\n"); -*/ -#define RXRDY(m) ( (STATUS(m) & MPU_INPUTBUSY) == 0) -#define TXRDY(m) ( (STATUS(m) & MPU_OUTPUTBUSY) == 0) -#if 0 -#define D(x,l) printf("mpu401_intr %d %x %s %s\n",l, x, x&MPU_INPUTBUSY?"RX":"", x&MPU_OUTPUTBUSY?"TX":"") -#else -#define D(x,l) -#endif - i = 0; - s = STATUS(m); - D(s, 1); - while ((s & MPU_INPUTBUSY) == 0 && i < MPU_INTR_BUF) { - b[i] = READ(m); -/* - printf("mpu401_intr in i %d d %d\n", i, b[i]); -*/ - i++; - s = STATUS(m); - } - if (i) - midi_in(m->mid, b, i); - i = 0; - while (!(s & MPU_OUTPUTBUSY) && i < MPU_INTR_BUF) { - if (midi_out(m->mid, b, 1)) { -/* - printf("mpu401_intr out i %d d %d\n", i, b[0]); -*/ - - WRITE(m, *b); - } else { -/* - printf("mpu401_intr write: no output\n"); -*/ - return 0; - } - i++; - /* DELAY(100); */ - s = STATUS(m); - } - - if ((m->flags & M_TXEN) && (m->si)) { - callout_reset(&m->timer, 1, mpu401_timeout, m); - } - return (m->flags & M_TXEN) == M_TXEN; -} - -struct mpu401 * -mpu401_init(kobj_class_t cls, void *cookie, driver_intr_t softintr, - mpu401_intr_t ** cb) -{ - struct mpu401 *m; - - *cb = NULL; - m = malloc(sizeof(*m), M_MIDI, M_NOWAIT | M_ZERO); - - if (!m) - return NULL; - - kobj_init((kobj_t)m, cls); - - callout_init(&m->timer, CALLOUT_MPSAFE); - - m->si = softintr; - m->cookie = cookie; - m->flags = 0; - - m->mid = midi_init(&mpu401_class, 0, 0, m); - if (!m->mid) - goto err; - *cb = mpu401_intr; - return m; -err: - printf("mpu401_init error\n"); - free(m, M_MIDI); - return NULL; -} - -int -mpu401_uninit(struct mpu401 *m) -{ - int retval; - - CMD(m, MPU_RESET); - retval = midi_uninit(m->mid); - if (retval) - return retval; - free(m, M_MIDI); - return 0; -} - -static int -mpu401_minit(struct snd_midi *sm, void *arg) -{ - struct mpu401 *m = arg; - int i; - - CMD(m, MPU_RESET); - CMD(m, MPU_UART); - return 0; - i = 0; - while (++i < 2000) { - if (RXRDY(m)) - if (READ(m) == MPU_ACK) - break; - } - - if (i < 2000) { - CMD(m, MPU_UART); - return 0; - } - printf("mpu401_minit failed active sensing\n"); - return 1; -} - - -int -mpu401_muninit(struct snd_midi *sm, void *arg) -{ - struct mpu401 *m = arg; - - return MPUFOI_UNINIT(m, m->cookie); -} - -int -mpu401_minqsize(struct snd_midi *sm, void *arg) -{ - return 128; -} - -int -mpu401_moutqsize(struct snd_midi *sm, void *arg) -{ - return 128; -} - -static void -mpu401_mcallback(struct snd_midi *sm, void *arg, int flags) -{ - struct mpu401 *m = arg; -#if 0 - printf("mpu401_callback %s %s %s %s\n", - flags & M_RX ? "M_RX" : "", - flags & M_TX ? "M_TX" : "", - flags & M_RXEN ? "M_RXEN" : "", - flags & M_TXEN ? "M_TXEN" : ""); -#endif - if (flags & M_TXEN && m->si) { - callout_reset(&m->timer, 1, mpu401_timeout, m); - } - m->flags = flags; -} - -static void -mpu401_mcallbackp(struct snd_midi *sm, void *arg, int flags) -{ -/* printf("mpu401_callbackp\n"); */ - mpu401_mcallback(sm, arg, flags); -} - -static const char * -mpu401_mdescr(struct snd_midi *sm, void *arg, int verbosity) -{ - - return "descr mpu401"; -} - -static const char * -mpu401_mprovider(struct snd_midi *m, void *arg) -{ - return "provider mpu401"; -} diff --git a/sys/dev/sound/midi/mpu401.h b/sys/dev/sound/midi/mpu401.h deleted file mode 100644 index acede4367e..0000000000 --- a/sys/dev/sound/midi/mpu401.h +++ /dev/null @@ -1,41 +0,0 @@ -/*- - * Copyright (c) 2003 Mathew Kanner - * All rights reserved. - * - * 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: head/sys/dev/sound/midi/mpu401.h 166971 2007-02-25 13:51:52Z netchild $ - */ - -#ifndef MPU401_H -#define MPU401_H - -struct mpu401; - -typedef int mpu401_intr_t(struct mpu401 *_obj); - -extern struct mpu401 * -mpu401_init(kobj_class_t _cls, void *cookie, driver_intr_t *_softintr, - mpu401_intr_t ** _cb); -extern int mpu401_uninit(struct mpu401 *_obj); - -#endif diff --git a/sys/dev/sound/midi/mpu_if.m b/sys/dev/sound/midi/mpu_if.m deleted file mode 100644 index 979aa6b523..0000000000 --- a/sys/dev/sound/midi/mpu_if.m +++ /dev/null @@ -1,74 +0,0 @@ -#- -# Copyright (c) 2003 Mathew Kanner -# All rights reserved. -# -# 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: head/sys/dev/sound/midi/mpu_if.m 166971 2007-02-25 13:51:52Z netchild $ -# - -#include - -INTERFACE mpu; - -METHOD int inqsize { - struct snd_midi *_kobj; - void *_cookie; -}; - -METHOD int outqsize { - struct snd_midi *_kobj; - void *_cookie; -}; - -METHOD int init { - struct snd_midi *_kobj; - void *_cookie; -}; - -METHOD void callbackp { - struct snd_midi *_kobj; - void *_cookie; - int _flags; -}; - -METHOD void callback { - struct snd_midi *_kobj; - void *_cookie; - int _flags; -}; - -METHOD const char * provider { - struct snd_midi *_kobj; - void *_cookie; -}; - -METHOD const char * descr { - struct snd_midi *_kobj; - void *_cookie; - int _verbosity; -}; - -METHOD int uninit { - struct snd_midi *_kobj; - void *_cookie; -}; diff --git a/sys/dev/sound/midi/mpufoi_if.m b/sys/dev/sound/midi/mpufoi_if.m deleted file mode 100644 index 727bc1e726..0000000000 --- a/sys/dev/sound/midi/mpufoi_if.m +++ /dev/null @@ -1,50 +0,0 @@ -#- -# Copyright (c) 2003 Mathew Kanner -# All rights reserved. -# -# 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: head/sys/dev/sound/midi/mpufoi_if.m 166971 2007-02-25 13:51:52Z netchild $ -# - -#include -#include - -INTERFACE mpufoi; - -METHOD unsigned char read { - struct mpu401 *_kobj; - void *_cookie; - int _reg; -}; - -METHOD void write { - struct mpu401 *_kobj; - void *_cookie; - int _reg; - unsigned char _d; -}; - -METHOD int uninit { - struct mpu401 *_kobj; - void *_cookie; -}; diff --git a/sys/dev/sound/midi/sequencer.c b/sys/dev/sound/midi/sequencer.c deleted file mode 100644 index 3747a268f3..0000000000 --- a/sys/dev/sound/midi/sequencer.c +++ /dev/null @@ -1,2095 +0,0 @@ -/*- - * Copyright (c) 2003 Mathew Kanner - * Copyright (c) 1993 Hannu Savolainen - * All rights reserved. - * - * 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. - */ - -/* - * The sequencer personality manager. - */ - -#include -__FBSDID("$FreeBSD: head/sys/dev/sound/midi/sequencer.c 274035 2014-11-03 11:11:45Z bapt $"); - -#include -#include -#include - -#include -#include -#include -#include -#include -#include - -#include /* for DATA_SET */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include /* for DELAY */ -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#ifdef HAVE_KERNEL_OPTION_HEADERS -#include "opt_snd.h" -#endif - -#include -#include -#include "synth_if.h" - -#include - -#define TMR_TIMERBASE 13 - -#define SND_DEV_SEQ 1 /* Sequencer output /dev/sequencer (FM - * synthesizer and MIDI output) */ -#define SND_DEV_MUSIC 8 /* /dev/music, level 2 interface */ - -/* Length of a sequencer event. */ -#define EV_SZ 8 -#define IEV_SZ 8 - -/* Lookup modes */ -#define LOOKUP_EXIST (0) -#define LOOKUP_OPEN (1) -#define LOOKUP_CLOSE (2) - -#define PCMMKMINOR(u, d, c) \ - ((((c) & 0xff) << 16) | (((u) & 0x0f) << 4) | ((d) & 0x0f)) -#define MIDIMKMINOR(u, d, c) PCMMKMINOR(u, d, c) -#define MIDIUNIT(y) ((dev2unit(y) >> 4) & 0x0f) -#define MIDIDEV(y) (dev2unit(y) & 0x0f) - -/* These are the entries to the sequencer driver. */ -static d_open_t seq_open; -static d_close_t seq_close; -static d_ioctl_t seq_ioctl; -static d_read_t seq_read; -static d_write_t seq_write; -static d_poll_t seq_poll; - -static struct cdevsw seq_cdevsw = { - .d_version = D_VERSION, - .d_open = seq_open, - .d_close = seq_close, - .d_read = seq_read, - .d_write = seq_write, - .d_ioctl = seq_ioctl, - .d_poll = seq_poll, - .d_name = "sequencer", -}; - -struct seq_softc { - KOBJ_FIELDS; - - struct mtx seq_lock, q_lock; - struct cv empty_cv, reset_cv, in_cv, out_cv, state_cv, th_cv; - - MIDIQ_HEAD(, u_char) in_q, out_q; - - u_long flags; - /* Flags (protected by flag_mtx of mididev_info) */ - int fflags; /* Access mode */ - int music; - - int out_water; /* Sequence output threshould */ - snd_sync_parm sync_parm; /* AIOSYNC parameter set */ - struct thread *sync_thread; /* AIOSYNCing thread */ - struct selinfo in_sel, out_sel; - int midi_number; - struct cdev *seqdev, *musicdev; - int unit; - int maxunits; - kobj_t *midis; - int *midi_flags; - kobj_t mapper; - void *mapper_cookie; - struct timeval timerstop, timersub; - int timerbase, tempo; - int timerrun; - int done; - int playing; - int recording; - int busy; - int pre_event_timeout; - int waiting; -}; - -/* - * Module specific stuff, including how many sequecers - * we currently own. - */ - -SYSCTL_NODE(_hw_midi, OID_AUTO, seq, CTLFLAG_RD, 0, "Midi sequencer"); - -int seq_debug; -/* XXX: should this be moved into debug.midi? */ -SYSCTL_INT(_hw_midi_seq, OID_AUTO, debug, CTLFLAG_RW, &seq_debug, 0, ""); - -midi_cmdtab cmdtab_seqevent[] = { - {SEQ_NOTEOFF, "SEQ_NOTEOFF"}, - {SEQ_NOTEON, "SEQ_NOTEON"}, - {SEQ_WAIT, "SEQ_WAIT"}, - {SEQ_PGMCHANGE, "SEQ_PGMCHANGE"}, - {SEQ_SYNCTIMER, "SEQ_SYNCTIMER"}, - {SEQ_MIDIPUTC, "SEQ_MIDIPUTC"}, - {SEQ_DRUMON, "SEQ_DRUMON"}, - {SEQ_DRUMOFF, "SEQ_DRUMOFF"}, - {SEQ_ECHO, "SEQ_ECHO"}, - {SEQ_AFTERTOUCH, "SEQ_AFTERTOUCH"}, - {SEQ_CONTROLLER, "SEQ_CONTROLLER"}, - {SEQ_BALANCE, "SEQ_BALANCE"}, - {SEQ_VOLMODE, "SEQ_VOLMODE"}, - {SEQ_FULLSIZE, "SEQ_FULLSIZE"}, - {SEQ_PRIVATE, "SEQ_PRIVATE"}, - {SEQ_EXTENDED, "SEQ_EXTENDED"}, - {EV_SEQ_LOCAL, "EV_SEQ_LOCAL"}, - {EV_TIMING, "EV_TIMING"}, - {EV_CHN_COMMON, "EV_CHN_COMMON"}, - {EV_CHN_VOICE, "EV_CHN_VOICE"}, - {EV_SYSEX, "EV_SYSEX"}, - {-1, NULL}, -}; - -midi_cmdtab cmdtab_seqioctl[] = { - {SNDCTL_SEQ_RESET, "SNDCTL_SEQ_RESET"}, - {SNDCTL_SEQ_SYNC, "SNDCTL_SEQ_SYNC"}, - {SNDCTL_SYNTH_INFO, "SNDCTL_SYNTH_INFO"}, - {SNDCTL_SEQ_CTRLRATE, "SNDCTL_SEQ_CTRLRATE"}, - {SNDCTL_SEQ_GETOUTCOUNT, "SNDCTL_SEQ_GETOUTCOUNT"}, - {SNDCTL_SEQ_GETINCOUNT, "SNDCTL_SEQ_GETINCOUNT"}, - {SNDCTL_SEQ_PERCMODE, "SNDCTL_SEQ_PERCMODE"}, - {SNDCTL_FM_LOAD_INSTR, "SNDCTL_FM_LOAD_INSTR"}, - {SNDCTL_SEQ_TESTMIDI, "SNDCTL_SEQ_TESTMIDI"}, - {SNDCTL_SEQ_RESETSAMPLES, "SNDCTL_SEQ_RESETSAMPLES"}, - {SNDCTL_SEQ_NRSYNTHS, "SNDCTL_SEQ_NRSYNTHS"}, - {SNDCTL_SEQ_NRMIDIS, "SNDCTL_SEQ_NRMIDIS"}, - {SNDCTL_SEQ_GETTIME, "SNDCTL_SEQ_GETTIME"}, - {SNDCTL_MIDI_INFO, "SNDCTL_MIDI_INFO"}, - {SNDCTL_SEQ_THRESHOLD, "SNDCTL_SEQ_THRESHOLD"}, - {SNDCTL_SYNTH_MEMAVL, "SNDCTL_SYNTH_MEMAVL"}, - {SNDCTL_FM_4OP_ENABLE, "SNDCTL_FM_4OP_ENABLE"}, - {SNDCTL_PMGR_ACCESS, "SNDCTL_PMGR_ACCESS"}, - {SNDCTL_SEQ_PANIC, "SNDCTL_SEQ_PANIC"}, - {SNDCTL_SEQ_OUTOFBAND, "SNDCTL_SEQ_OUTOFBAND"}, - {SNDCTL_TMR_TIMEBASE, "SNDCTL_TMR_TIMEBASE"}, - {SNDCTL_TMR_START, "SNDCTL_TMR_START"}, - {SNDCTL_TMR_STOP, "SNDCTL_TMR_STOP"}, - {SNDCTL_TMR_CONTINUE, "SNDCTL_TMR_CONTINUE"}, - {SNDCTL_TMR_TEMPO, "SNDCTL_TMR_TEMPO"}, - {SNDCTL_TMR_SOURCE, "SNDCTL_TMR_SOURCE"}, - {SNDCTL_TMR_METRONOME, "SNDCTL_TMR_METRONOME"}, - {SNDCTL_TMR_SELECT, "SNDCTL_TMR_SELECT"}, - {SNDCTL_MIDI_PRETIME, "SNDCTL_MIDI_PRETIME"}, - {AIONWRITE, "AIONWRITE"}, - {AIOGSIZE, "AIOGSIZE"}, - {AIOSSIZE, "AIOSSIZE"}, - {AIOGFMT, "AIOGFMT"}, - {AIOSFMT, "AIOSFMT"}, - {AIOGMIX, "AIOGMIX"}, - {AIOSMIX, "AIOSMIX"}, - {AIOSTOP, "AIOSTOP"}, - {AIOSYNC, "AIOSYNC"}, - {AIOGCAP, "AIOGCAP"}, - {-1, NULL}, -}; - -midi_cmdtab cmdtab_timer[] = { - {TMR_WAIT_REL, "TMR_WAIT_REL"}, - {TMR_WAIT_ABS, "TMR_WAIT_ABS"}, - {TMR_STOP, "TMR_STOP"}, - {TMR_START, "TMR_START"}, - {TMR_CONTINUE, "TMR_CONTINUE"}, - {TMR_TEMPO, "TMR_TEMPO"}, - {TMR_ECHO, "TMR_ECHO"}, - {TMR_CLOCK, "TMR_CLOCK"}, - {TMR_SPP, "TMR_SPP"}, - {TMR_TIMESIG, "TMR_TIMESIG"}, - {-1, NULL}, -}; - -midi_cmdtab cmdtab_seqcv[] = { - {MIDI_NOTEOFF, "MIDI_NOTEOFF"}, - {MIDI_NOTEON, "MIDI_NOTEON"}, - {MIDI_KEY_PRESSURE, "MIDI_KEY_PRESSURE"}, - {-1, NULL}, -}; - -midi_cmdtab cmdtab_seqccmn[] = { - {MIDI_CTL_CHANGE, "MIDI_CTL_CHANGE"}, - {MIDI_PGM_CHANGE, "MIDI_PGM_CHANGE"}, - {MIDI_CHN_PRESSURE, "MIDI_CHN_PRESSURE"}, - {MIDI_PITCH_BEND, "MIDI_PITCH_BEND"}, - {MIDI_SYSTEM_PREFIX, "MIDI_SYSTEM_PREFIX"}, - {-1, NULL}, -}; - -#ifndef KOBJMETHOD_END -#define KOBJMETHOD_END { NULL, NULL } -#endif - -/* - * static const char *mpu401_mprovider(kobj_t obj, struct mpu401 *m); - */ - -static kobj_method_t seq_methods[] = { - /* KOBJMETHOD(mpu_provider,mpu401_mprovider), */ - KOBJMETHOD_END -}; - -DEFINE_CLASS(sequencer, seq_methods, 0); - -/* The followings are the local function. */ -static int seq_convertold(u_char *event, u_char *out); - -/* - * static void seq_midiinput(struct seq_softc * scp, void *md); - */ -static void seq_reset(struct seq_softc *scp); -static int seq_sync(struct seq_softc *scp); - -static int seq_processevent(struct seq_softc *scp, u_char *event); - -static int seq_timing(struct seq_softc *scp, u_char *event); -static int seq_local(struct seq_softc *scp, u_char *event); - -static int seq_chnvoice(struct seq_softc *scp, kobj_t md, u_char *event); -static int seq_chncommon(struct seq_softc *scp, kobj_t md, u_char *event); -static int seq_sysex(struct seq_softc *scp, kobj_t md, u_char *event); - -static int seq_fetch_mid(struct seq_softc *scp, int unit, kobj_t *md); -void seq_copytoinput(struct seq_softc *scp, u_char *event, int len); -int seq_modevent(module_t mod, int type, void *data); -struct seq_softc *seqs[10]; -static struct mtx seqinfo_mtx; -static u_long nseq = 0; - -static void timer_start(struct seq_softc *t); -static void timer_stop(struct seq_softc *t); -static void timer_setvals(struct seq_softc *t, int tempo, int timerbase); -static void timer_wait(struct seq_softc *t, int ticks, int wait_abs); -static int timer_now(struct seq_softc *t); - - -static void -timer_start(struct seq_softc *t) -{ - t->timerrun = 1; - getmicrotime(&t->timersub); -} - -static void -timer_continue(struct seq_softc *t) -{ - struct timeval now; - - if (t->timerrun == 1) - return; - t->timerrun = 1; - getmicrotime(&now); - timevalsub(&now, &t->timerstop); - timevaladd(&t->timersub, &now); -} - -static void -timer_stop(struct seq_softc *t) -{ - t->timerrun = 0; - getmicrotime(&t->timerstop); -} - -static void -timer_setvals(struct seq_softc *t, int tempo, int timerbase) -{ - t->tempo = tempo; - t->timerbase = timerbase; -} - -static void -timer_wait(struct seq_softc *t, int ticks, int wait_abs) -{ - struct timeval now, when; - int ret; - unsigned long long i; - - while (t->timerrun == 0) { - SEQ_DEBUG(2, printf("Timer wait when timer isn't running\n")); - /* - * The old sequencer used timeouts that only increased - * the timer when the timer was running. - * Hence the sequencer would stick (?) if the - * timer was disabled. - */ - cv_wait(&t->reset_cv, &t->seq_lock); - if (t->playing == 0) - return; - } - - i = ticks * 60ull * 1000000ull / (t->tempo * t->timerbase); - - when.tv_sec = i / 1000000; - when.tv_usec = i % 1000000; - -#if 0 - printf("timer_wait tempo %d timerbase %d ticks %d abs %d u_sec %llu\n", - t->tempo, t->timerbase, ticks, wait_abs, i); -#endif - - if (wait_abs != 0) { - getmicrotime(&now); - timevalsub(&now, &t->timersub); - timevalsub(&when, &now); - } - if (when.tv_sec < 0 || when.tv_usec < 0) { - SEQ_DEBUG(3, - printf("seq_timer error negative time %lds.%06lds\n", - (long)when.tv_sec, (long)when.tv_usec)); - return; - } - i = when.tv_sec * 1000000ull; - i += when.tv_usec; - i *= hz; - i /= 1000000ull; -#if 0 - printf("seq_timer usec %llu ticks %llu\n", - when.tv_sec * 1000000ull + when.tv_usec, i); -#endif - t->waiting = 1; - ret = cv_timedwait(&t->reset_cv, &t->seq_lock, i + 1); - t->waiting = 0; - - if (ret != EWOULDBLOCK) - SEQ_DEBUG(3, printf("seq_timer didn't timeout\n")); - -} - -static int -timer_now(struct seq_softc *t) -{ - struct timeval now; - unsigned long long i; - int ret; - - if (t->timerrun == 0) - now = t->timerstop; - else - getmicrotime(&now); - - timevalsub(&now, &t->timersub); - - i = now.tv_sec * 1000000ull; - i += now.tv_usec; - i *= t->timerbase; -/* i /= t->tempo; */ - i /= 1000000ull; - - ret = i; - /* - * printf("timer_now: %llu %d\n", i, ret); - */ - - return ret; -} - -static void -seq_eventthread(void *arg) -{ - struct seq_softc *scp = arg; - char event[EV_SZ]; - - mtx_lock(&scp->seq_lock); - SEQ_DEBUG(2, printf("seq_eventthread started\n")); - while (scp->done == 0) { -restart: - while (scp->playing == 0) { - cv_wait(&scp->state_cv, &scp->seq_lock); - if (scp->done) - goto done; - } - - while (MIDIQ_EMPTY(scp->out_q)) { - cv_broadcast(&scp->empty_cv); - cv_wait(&scp->out_cv, &scp->seq_lock); - if (scp->playing == 0) - goto restart; - if (scp->done) - goto done; - } - - MIDIQ_DEQ(scp->out_q, event, EV_SZ); - - if (MIDIQ_AVAIL(scp->out_q) < scp->out_water) { - cv_broadcast(&scp->out_cv); - selwakeup(&scp->out_sel); - } - seq_processevent(scp, event); - } - -done: - cv_broadcast(&scp->th_cv); - mtx_unlock(&scp->seq_lock); - SEQ_DEBUG(2, printf("seq_eventthread finished\n")); - kproc_exit(0); -} - -/* - * seq_processevent: This maybe called by the event thread or the IOCTL - * handler for queued and out of band events respectively. - */ -static int -seq_processevent(struct seq_softc *scp, u_char *event) -{ - int ret; - kobj_t m; - - ret = 0; - - if (event[0] == EV_SEQ_LOCAL) - ret = seq_local(scp, event); - else if (event[0] == EV_TIMING) - ret = seq_timing(scp, event); - else if (event[0] != EV_CHN_VOICE && - event[0] != EV_CHN_COMMON && - event[0] != EV_SYSEX && - event[0] != SEQ_MIDIPUTC) { - ret = 1; - SEQ_DEBUG(2, printf("seq_processevent not known %d\n", - event[0])); - } else if (seq_fetch_mid(scp, event[1], &m) != 0) { - ret = 1; - SEQ_DEBUG(2, printf("seq_processevent midi unit not found %d\n", - event[1])); - } else - switch (event[0]) { - case EV_CHN_VOICE: - ret = seq_chnvoice(scp, m, event); - break; - case EV_CHN_COMMON: - ret = seq_chncommon(scp, m, event); - break; - case EV_SYSEX: - ret = seq_sysex(scp, m, event); - break; - case SEQ_MIDIPUTC: - mtx_unlock(&scp->seq_lock); - ret = SYNTH_WRITERAW(m, &event[2], 1); - mtx_lock(&scp->seq_lock); - break; - } - return ret; -} - -static int -seq_addunit(void) -{ - struct seq_softc *scp; - int ret; - u_char *buf; - - /* Allocate the softc. */ - ret = ENOMEM; - scp = malloc(sizeof(*scp), M_DEVBUF, M_NOWAIT | M_ZERO); - if (scp == NULL) { - SEQ_DEBUG(1, printf("seq_addunit: softc allocation failed.\n")); - goto err; - } - kobj_init((kobj_t)scp, &sequencer_class); - - buf = malloc(sizeof(*buf) * EV_SZ * 1024, M_TEMP, M_NOWAIT | M_ZERO); - if (buf == NULL) - goto err; - MIDIQ_INIT(scp->in_q, buf, EV_SZ * 1024); - buf = malloc(sizeof(*buf) * EV_SZ * 1024, M_TEMP, M_NOWAIT | M_ZERO); - if (buf == NULL) - goto err; - MIDIQ_INIT(scp->out_q, buf, EV_SZ * 1024); - ret = EINVAL; - - scp->midis = malloc(sizeof(kobj_t) * 32, M_TEMP, M_NOWAIT | M_ZERO); - scp->midi_flags = malloc(sizeof(*scp->midi_flags) * 32, M_TEMP, - M_NOWAIT | M_ZERO); - - if (scp->midis == NULL || scp->midi_flags == NULL) - goto err; - - scp->flags = 0; - - mtx_init(&scp->seq_lock, "seqflq", NULL, 0); - cv_init(&scp->state_cv, "seqstate"); - cv_init(&scp->empty_cv, "seqempty"); - cv_init(&scp->reset_cv, "seqtimer"); - cv_init(&scp->out_cv, "seqqout"); - cv_init(&scp->in_cv, "seqqin"); - cv_init(&scp->th_cv, "seqstart"); - - /* - * Init the damn timer - */ - - scp->mapper = midimapper_addseq(scp, &scp->unit, &scp->mapper_cookie); - if (scp->mapper == NULL) - goto err; - - scp->seqdev = make_dev(&seq_cdevsw, - MIDIMKMINOR(scp->unit, SND_DEV_SEQ, 0), UID_ROOT, - GID_WHEEL, 0666, "sequencer%d", scp->unit); - - scp->musicdev = make_dev(&seq_cdevsw, - MIDIMKMINOR(scp->unit, SND_DEV_MUSIC, 0), UID_ROOT, - GID_WHEEL, 0666, "music%d", scp->unit); - - if (scp->seqdev == NULL || scp->musicdev == NULL) - goto err; - /* - * TODO: Add to list of sequencers this module provides - */ - - ret = - kproc_create - (seq_eventthread, scp, NULL, RFHIGHPID, 0, - "sequencer %02d", scp->unit); - - if (ret) - goto err; - - scp->seqdev->si_drv1 = scp->musicdev->si_drv1 = scp; - - SEQ_DEBUG(2, printf("sequencer %d created scp %p\n", scp->unit, scp)); - - ret = 0; - - mtx_lock(&seqinfo_mtx); - seqs[nseq++] = scp; - mtx_unlock(&seqinfo_mtx); - - goto ok; - -err: - if (scp != NULL) { - if (scp->seqdev != NULL) - destroy_dev(scp->seqdev); - if (scp->musicdev != NULL) - destroy_dev(scp->musicdev); - /* - * TODO: Destroy mutex and cv - */ - if (scp->midis != NULL) - free(scp->midis, M_TEMP); - if (scp->midi_flags != NULL) - free(scp->midi_flags, M_TEMP); - if (scp->out_q.b) - free(scp->out_q.b, M_TEMP); - if (scp->in_q.b) - free(scp->in_q.b, M_TEMP); - free(scp, M_DEVBUF); - } -ok: - return ret; -} - -static int -seq_delunit(int unit) -{ - struct seq_softc *scp = seqs[unit]; - int i; - - //SEQ_DEBUG(4, printf("seq_delunit: %d\n", unit)); - SEQ_DEBUG(1, printf("seq_delunit: 1 \n")); - mtx_lock(&scp->seq_lock); - - scp->playing = 0; - scp->done = 1; - cv_broadcast(&scp->out_cv); - cv_broadcast(&scp->state_cv); - cv_broadcast(&scp->reset_cv); - SEQ_DEBUG(1, printf("seq_delunit: 2 \n")); - cv_wait(&scp->th_cv, &scp->seq_lock); - SEQ_DEBUG(1, printf("seq_delunit: 3.0 \n")); - mtx_unlock(&scp->seq_lock); - SEQ_DEBUG(1, printf("seq_delunit: 3.1 \n")); - - cv_destroy(&scp->state_cv); - SEQ_DEBUG(1, printf("seq_delunit: 4 \n")); - cv_destroy(&scp->empty_cv); - SEQ_DEBUG(1, printf("seq_delunit: 5 \n")); - cv_destroy(&scp->reset_cv); - SEQ_DEBUG(1, printf("seq_delunit: 6 \n")); - cv_destroy(&scp->out_cv); - SEQ_DEBUG(1, printf("seq_delunit: 7 \n")); - cv_destroy(&scp->in_cv); - SEQ_DEBUG(1, printf("seq_delunit: 8 \n")); - cv_destroy(&scp->th_cv); - - SEQ_DEBUG(1, printf("seq_delunit: 10 \n")); - if (scp->seqdev) - destroy_dev(scp->seqdev); - SEQ_DEBUG(1, printf("seq_delunit: 11 \n")); - if (scp->musicdev) - destroy_dev(scp->musicdev); - SEQ_DEBUG(1, printf("seq_delunit: 12 \n")); - scp->seqdev = scp->musicdev = NULL; - if (scp->midis != NULL) - free(scp->midis, M_TEMP); - SEQ_DEBUG(1, printf("seq_delunit: 13 \n")); - if (scp->midi_flags != NULL) - free(scp->midi_flags, M_TEMP); - SEQ_DEBUG(1, printf("seq_delunit: 14 \n")); - free(scp->out_q.b, M_TEMP); - SEQ_DEBUG(1, printf("seq_delunit: 15 \n")); - free(scp->in_q.b, M_TEMP); - - SEQ_DEBUG(1, printf("seq_delunit: 16 \n")); - - mtx_destroy(&scp->seq_lock); - SEQ_DEBUG(1, printf("seq_delunit: 17 \n")); - free(scp, M_DEVBUF); - - mtx_lock(&seqinfo_mtx); - for (i = unit; i < (nseq - 1); i++) - seqs[i] = seqs[i + 1]; - nseq--; - mtx_unlock(&seqinfo_mtx); - - return 0; -} - -int -seq_modevent(module_t mod, int type, void *data) -{ - int retval, r; - - retval = 0; - - switch (type) { - case MOD_LOAD: - mtx_init(&seqinfo_mtx, "seqmod", NULL, 0); - retval = seq_addunit(); - break; - - case MOD_UNLOAD: - while (nseq) { - r = seq_delunit(nseq - 1); - if (r) { - retval = r; - break; - } - } - if (nseq == 0) { - retval = 0; - mtx_destroy(&seqinfo_mtx); - } - break; - - default: - break; - } - - return retval; -} - -static int -seq_fetch_mid(struct seq_softc *scp, int unit, kobj_t *md) -{ - - if (unit > scp->midi_number || unit < 0) - return EINVAL; - - *md = scp->midis[unit]; - - return 0; -} - -int -seq_open(struct cdev *i_dev, int flags, int mode, struct thread *td) -{ - struct seq_softc *scp = i_dev->si_drv1; - int i; - - if (scp == NULL) - return ENXIO; - - SEQ_DEBUG(3, printf("seq_open: scp %p unit %d, flags 0x%x.\n", - scp, scp->unit, flags)); - - /* - * Mark this device busy. - */ - - mtx_lock(&scp->seq_lock); - if (scp->busy) { - mtx_unlock(&scp->seq_lock); - SEQ_DEBUG(2, printf("seq_open: unit %d is busy.\n", scp->unit)); - return EBUSY; - } - scp->fflags = flags; - /* - if ((scp->fflags & O_NONBLOCK) != 0) - scp->flags |= SEQ_F_NBIO; - */ - scp->music = MIDIDEV(i_dev) == SND_DEV_MUSIC; - - /* - * Enumerate the available midi devices - */ - scp->midi_number = 0; - scp->maxunits = midimapper_open(scp->mapper, &scp->mapper_cookie); - - if (scp->maxunits == 0) - SEQ_DEBUG(2, printf("seq_open: no midi devices\n")); - - for (i = 0; i < scp->maxunits; i++) { - scp->midis[scp->midi_number] = - midimapper_fetch_synth(scp->mapper, scp->mapper_cookie, i); - if (scp->midis[scp->midi_number]) { - if (SYNTH_OPEN(scp->midis[scp->midi_number], scp, - scp->fflags) != 0) - scp->midis[scp->midi_number] = NULL; - else { - scp->midi_flags[scp->midi_number] = - SYNTH_QUERY(scp->midis[scp->midi_number]); - scp->midi_number++; - } - } - } - - timer_setvals(scp, 60, 100); - - timer_start(scp); - timer_stop(scp); - /* - * actually, if we're in rdonly mode, we should start the timer - */ - /* - * TODO: Handle recording now - */ - - scp->out_water = MIDIQ_SIZE(scp->out_q) / 2; - - scp->busy = 1; - mtx_unlock(&scp->seq_lock); - - SEQ_DEBUG(2, printf("seq_open: opened, mode %s.\n", - scp->music ? "music" : "sequencer")); - SEQ_DEBUG(2, - printf("Sequencer %d %p opened maxunits %d midi_number %d:\n", - scp->unit, scp, scp->maxunits, scp->midi_number)); - for (i = 0; i < scp->midi_number; i++) - SEQ_DEBUG(3, printf(" midi %d %p\n", i, scp->midis[i])); - - return 0; -} - -/* - * seq_close - */ -int -seq_close(struct cdev *i_dev, int flags, int mode, struct thread *td) -{ - int i; - struct seq_softc *scp = i_dev->si_drv1; - int ret; - - if (scp == NULL) - return ENXIO; - - SEQ_DEBUG(2, printf("seq_close: unit %d.\n", scp->unit)); - - mtx_lock(&scp->seq_lock); - - ret = ENXIO; - if (scp->busy == 0) - goto err; - - seq_reset(scp); - seq_sync(scp); - - for (i = 0; i < scp->midi_number; i++) - if (scp->midis[i]) - SYNTH_CLOSE(scp->midis[i]); - - midimapper_close(scp->mapper, scp->mapper_cookie); - - timer_stop(scp); - - scp->busy = 0; - ret = 0; - -err: - SEQ_DEBUG(3, printf("seq_close: closed ret = %d.\n", ret)); - mtx_unlock(&scp->seq_lock); - return ret; -} - -int -seq_read(struct cdev *i_dev, struct uio *uio, int ioflag) -{ - int retval, used; - struct seq_softc *scp = i_dev->si_drv1; - -#define SEQ_RSIZE 32 - u_char buf[SEQ_RSIZE]; - - if (scp == NULL) - return ENXIO; - - SEQ_DEBUG(7, printf("seq_read: unit %d, resid %zd.\n", - scp->unit, uio->uio_resid)); - - mtx_lock(&scp->seq_lock); - if ((scp->fflags & FREAD) == 0) { - SEQ_DEBUG(2, printf("seq_read: unit %d is not for reading.\n", - scp->unit)); - retval = EIO; - goto err1; - } - /* - * Begin recording. - */ - /* - * if ((scp->flags & SEQ_F_READING) == 0) - */ - /* - * TODO, start recording if not alread - */ - - /* - * I think the semantics are to return as soon - * as possible. - * Second thought, it doens't seem like midimoutain - * expects that at all. - * TODO: Look up in some sort of spec - */ - - while (uio->uio_resid > 0) { - while (MIDIQ_EMPTY(scp->in_q)) { - retval = EWOULDBLOCK; - /* - * I wish I knew which one to care about - */ - - if (scp->fflags & O_NONBLOCK) - goto err1; - if (ioflag & O_NONBLOCK) - goto err1; - - retval = cv_wait_sig(&scp->in_cv, &scp->seq_lock); - if (retval == EINTR) - goto err1; - } - - used = MIN(MIDIQ_LEN(scp->in_q), uio->uio_resid); - used = MIN(used, SEQ_RSIZE); - - SEQ_DEBUG(8, printf("midiread: uiomove cc=%d\n", used)); - MIDIQ_DEQ(scp->in_q, buf, used); - retval = uiomove(buf, used, uio); - if (retval) - goto err1; - } - - retval = 0; -err1: - mtx_unlock(&scp->seq_lock); - SEQ_DEBUG(6, printf("seq_read: ret %d, resid %zd.\n", - retval, uio->uio_resid)); - - return retval; -} - -int -seq_write(struct cdev *i_dev, struct uio *uio, int ioflag) -{ - u_char event[EV_SZ], newevent[EV_SZ], ev_code; - struct seq_softc *scp = i_dev->si_drv1; - int retval; - int used; - - SEQ_DEBUG(7, printf("seq_write: unit %d, resid %zd.\n", - scp->unit, uio->uio_resid)); - - if (scp == NULL) - return ENXIO; - - mtx_lock(&scp->seq_lock); - - if ((scp->fflags & FWRITE) == 0) { - SEQ_DEBUG(2, printf("seq_write: unit %d is not for writing.\n", - scp->unit)); - retval = EIO; - goto err0; - } - while (uio->uio_resid > 0) { - while (MIDIQ_AVAIL(scp->out_q) == 0) { - retval = EWOULDBLOCK; - if (scp->fflags & O_NONBLOCK) - goto err0; - if (ioflag & O_NONBLOCK) - goto err0; - SEQ_DEBUG(8, printf("seq_write cvwait\n")); - - scp->playing = 1; - cv_broadcast(&scp->out_cv); - cv_broadcast(&scp->state_cv); - - retval = cv_wait_sig(&scp->out_cv, &scp->seq_lock); - /* - * We slept, maybe things have changed since last - * dying check - */ - if (retval == EINTR) - goto err0; -#if 0 - /* - * Useless test - */ - if (scp != i_dev->si_drv1) - retval = ENXIO; -#endif - } - - used = MIN(uio->uio_resid, 4); - - SEQ_DEBUG(8, printf("seqout: resid %zd len %jd avail %jd\n", - uio->uio_resid, (intmax_t)MIDIQ_LEN(scp->out_q), - (intmax_t)MIDIQ_AVAIL(scp->out_q))); - - if (used != 4) { - retval = ENXIO; - goto err0; - } - retval = uiomove(event, used, uio); - if (retval) - goto err0; - - ev_code = event[0]; - SEQ_DEBUG(8, printf("seq_write: unit %d, event %s.\n", - scp->unit, midi_cmdname(ev_code, cmdtab_seqevent))); - - /* Have a look at the event code. */ - if (ev_code == SEQ_FULLSIZE) { - - /* - * TODO: restore code for SEQ_FULLSIZE - */ -#if 0 - /* - * A long event, these are the patches/samples for a - * synthesizer. - */ - midiunit = *(u_short *)&event[2]; - mtx_lock(&sd->seq_lock); - ret = lookup_mididev(scp, midiunit, LOOKUP_OPEN, &md); - mtx_unlock(&sd->seq_lock); - if (ret != 0) - return (ret); - - SEQ_DEBUG(printf("seq_write: loading a patch to the unit %d.\n", midiunit)); - - ret = md->synth.loadpatch(md, *(short *)&event[0], buf, - p + 4, count, 0); - return (ret); -#else - /* - * For now, just flush the darn buffer - */ - SEQ_DEBUG(2, - printf("seq_write: SEQ_FULLSIZE flusing buffer.\n")); - while (uio->uio_resid > 0) { - retval = uiomove(event, EV_SZ, uio); - if (retval) - goto err0; - - } - retval = 0; - goto err0; -#endif - } - retval = EINVAL; - if (ev_code >= 128) { - - /* - * Some sort of an extended event. The size is eight - * bytes. scoop extra info. - */ - if (scp->music && ev_code == SEQ_EXTENDED) { - SEQ_DEBUG(2, printf("seq_write: invalid level two event %x.\n", ev_code)); - goto err0; - } - if (uiomove((caddr_t)&event[4], 4, uio)) { - SEQ_DEBUG(2, - printf("seq_write: user memory mangled?\n")); - goto err0; - } - } else { - /* - * Size four event. - */ - if (scp->music) { - SEQ_DEBUG(2, printf("seq_write: four byte event in music mode.\n")); - goto err0; - } - } - if (ev_code == SEQ_MIDIPUTC) { - /* - * TODO: event[2] is unit number to receive char. - * Range check it. - */ - } - if (scp->music) { -#ifdef not_ever_ever - if (event[0] == EV_TIMING && - (event[1] == TMR_START || event[1] == TMR_STOP)) { - /* - * For now, try to make midimoutain work by - * forcing these events to be processed - * immediatly. - */ - seq_processevent(scp, event); - } else - MIDIQ_ENQ(scp->out_q, event, EV_SZ); -#else - MIDIQ_ENQ(scp->out_q, event, EV_SZ); -#endif - } else { - if (seq_convertold(event, newevent) > 0) - MIDIQ_ENQ(scp->out_q, newevent, EV_SZ); -#if 0 - else - goto err0; -#endif - } - - } - - scp->playing = 1; - cv_broadcast(&scp->state_cv); - cv_broadcast(&scp->out_cv); - - retval = 0; - -err0: - SEQ_DEBUG(6, - printf("seq_write done: leftover buffer length %zd retval %d\n", - uio->uio_resid, retval)); - mtx_unlock(&scp->seq_lock); - return retval; -} - -int -seq_ioctl(struct cdev *i_dev, u_long cmd, caddr_t arg, int mode, - struct thread *td) -{ - int midiunit, ret, tmp; - struct seq_softc *scp = i_dev->si_drv1; - struct synth_info *synthinfo; - struct midi_info *midiinfo; - u_char event[EV_SZ]; - u_char newevent[EV_SZ]; - - kobj_t md; - - /* - * struct snd_size *sndsize; - */ - - if (scp == NULL) - return ENXIO; - - SEQ_DEBUG(6, printf("seq_ioctl: unit %d, cmd %s.\n", - scp->unit, midi_cmdname(cmd, cmdtab_seqioctl))); - - ret = 0; - - switch (cmd) { - case SNDCTL_SEQ_GETTIME: - /* - * ioctl needed by libtse - */ - mtx_lock(&scp->seq_lock); - *(int *)arg = timer_now(scp); - mtx_unlock(&scp->seq_lock); - SEQ_DEBUG(6, printf("seq_ioctl: gettime %d.\n", *(int *)arg)); - ret = 0; - break; - case SNDCTL_TMR_METRONOME: - /* fallthrough */ - case SNDCTL_TMR_SOURCE: - /* - * Not implemented - */ - ret = 0; - break; - case SNDCTL_TMR_TEMPO: - event[1] = TMR_TEMPO; - event[4] = *(int *)arg & 0xFF; - event[5] = (*(int *)arg >> 8) & 0xFF; - event[6] = (*(int *)arg >> 16) & 0xFF; - event[7] = (*(int *)arg >> 24) & 0xFF; - goto timerevent; - case SNDCTL_TMR_TIMEBASE: - event[1] = TMR_TIMERBASE; - event[4] = *(int *)arg & 0xFF; - event[5] = (*(int *)arg >> 8) & 0xFF; - event[6] = (*(int *)arg >> 16) & 0xFF; - event[7] = (*(int *)arg >> 24) & 0xFF; - goto timerevent; - case SNDCTL_TMR_START: - event[1] = TMR_START; - goto timerevent; - case SNDCTL_TMR_STOP: - event[1] = TMR_STOP; - goto timerevent; - case SNDCTL_TMR_CONTINUE: - event[1] = TMR_CONTINUE; -timerevent: - event[0] = EV_TIMING; - mtx_lock(&scp->seq_lock); - if (!scp->music) { - ret = EINVAL; - mtx_unlock(&scp->seq_lock); - break; - } - seq_processevent(scp, event); - mtx_unlock(&scp->seq_lock); - break; - case SNDCTL_TMR_SELECT: - SEQ_DEBUG(2, - printf("seq_ioctl: SNDCTL_TMR_SELECT not supported\n")); - ret = EINVAL; - break; - case SNDCTL_SEQ_SYNC: - if (mode == O_RDONLY) { - ret = 0; - break; - } - mtx_lock(&scp->seq_lock); - ret = seq_sync(scp); - mtx_unlock(&scp->seq_lock); - break; - case SNDCTL_SEQ_PANIC: - /* fallthrough */ - case SNDCTL_SEQ_RESET: - /* - * SNDCTL_SEQ_PANIC == SNDCTL_SEQ_RESET - */ - mtx_lock(&scp->seq_lock); - seq_reset(scp); - mtx_unlock(&scp->seq_lock); - ret = 0; - break; - case SNDCTL_SEQ_TESTMIDI: - mtx_lock(&scp->seq_lock); - /* - * TODO: SNDCTL_SEQ_TESTMIDI now means "can I write to the - * device?". - */ - mtx_unlock(&scp->seq_lock); - break; -#if 0 - case SNDCTL_SEQ_GETINCOUNT: - if (mode == O_WRONLY) - *(int *)arg = 0; - else { - mtx_lock(&scp->seq_lock); - *(int *)arg = scp->in_q.rl; - mtx_unlock(&scp->seq_lock); - SEQ_DEBUG(printf("seq_ioctl: incount %d.\n", - *(int *)arg)); - } - ret = 0; - break; - case SNDCTL_SEQ_GETOUTCOUNT: - if (mode == O_RDONLY) - *(int *)arg = 0; - else { - mtx_lock(&scp->seq_lock); - *(int *)arg = scp->out_q.fl; - mtx_unlock(&scp->seq_lock); - SEQ_DEBUG(printf("seq_ioctl: outcount %d.\n", - *(int *)arg)); - } - ret = 0; - break; -#endif - case SNDCTL_SEQ_CTRLRATE: - if (*(int *)arg != 0) { - ret = EINVAL; - break; - } - mtx_lock(&scp->seq_lock); - *(int *)arg = scp->timerbase; - mtx_unlock(&scp->seq_lock); - SEQ_DEBUG(3, printf("seq_ioctl: ctrlrate %d.\n", *(int *)arg)); - ret = 0; - break; - /* - * TODO: ioctl SNDCTL_SEQ_RESETSAMPLES - */ -#if 0 - case SNDCTL_SEQ_RESETSAMPLES: - mtx_lock(&scp->seq_lock); - ret = lookup_mididev(scp, *(int *)arg, LOOKUP_OPEN, &md); - mtx_unlock(&scp->seq_lock); - if (ret != 0) - break; - ret = midi_ioctl(MIDIMKDEV(major(i_dev), *(int *)arg, - SND_DEV_MIDIN), cmd, arg, mode, td); - break; -#endif - case SNDCTL_SEQ_NRSYNTHS: - mtx_lock(&scp->seq_lock); - *(int *)arg = scp->midi_number; - mtx_unlock(&scp->seq_lock); - SEQ_DEBUG(3, printf("seq_ioctl: synths %d.\n", *(int *)arg)); - ret = 0; - break; - case SNDCTL_SEQ_NRMIDIS: - mtx_lock(&scp->seq_lock); - if (scp->music) - *(int *)arg = 0; - else { - /* - * TODO: count the numbder of devices that can WRITERAW - */ - *(int *)arg = scp->midi_number; - } - mtx_unlock(&scp->seq_lock); - SEQ_DEBUG(3, printf("seq_ioctl: midis %d.\n", *(int *)arg)); - ret = 0; - break; - /* - * TODO: ioctl SNDCTL_SYNTH_MEMAVL - */ -#if 0 - case SNDCTL_SYNTH_MEMAVL: - mtx_lock(&scp->seq_lock); - ret = lookup_mididev(scp, *(int *)arg, LOOKUP_OPEN, &md); - mtx_unlock(&scp->seq_lock); - if (ret != 0) - break; - ret = midi_ioctl(MIDIMKDEV(major(i_dev), *(int *)arg, - SND_DEV_MIDIN), cmd, arg, mode, td); - break; -#endif - case SNDCTL_SEQ_OUTOFBAND: - for (ret = 0; ret < EV_SZ; ret++) - event[ret] = (u_char)arg[0]; - - mtx_lock(&scp->seq_lock); - if (scp->music) - ret = seq_processevent(scp, event); - else { - if (seq_convertold(event, newevent) > 0) - ret = seq_processevent(scp, newevent); - else - ret = EINVAL; - } - mtx_unlock(&scp->seq_lock); - break; - case SNDCTL_SYNTH_INFO: - synthinfo = (struct synth_info *)arg; - midiunit = synthinfo->device; - mtx_lock(&scp->seq_lock); - if (seq_fetch_mid(scp, midiunit, &md) == 0) { - bzero(synthinfo, sizeof(*synthinfo)); - synthinfo->name[0] = 'f'; - synthinfo->name[1] = 'a'; - synthinfo->name[2] = 'k'; - synthinfo->name[3] = 'e'; - synthinfo->name[4] = 's'; - synthinfo->name[5] = 'y'; - synthinfo->name[6] = 'n'; - synthinfo->name[7] = 't'; - synthinfo->name[8] = 'h'; - synthinfo->device = midiunit; - synthinfo->synth_type = SYNTH_TYPE_MIDI; - synthinfo->capabilities = scp->midi_flags[midiunit]; - ret = 0; - } else - ret = EINVAL; - mtx_unlock(&scp->seq_lock); - break; - case SNDCTL_MIDI_INFO: - midiinfo = (struct midi_info *)arg; - midiunit = midiinfo->device; - mtx_lock(&scp->seq_lock); - if (seq_fetch_mid(scp, midiunit, &md) == 0) { - bzero(midiinfo, sizeof(*midiinfo)); - midiinfo->name[0] = 'f'; - midiinfo->name[1] = 'a'; - midiinfo->name[2] = 'k'; - midiinfo->name[3] = 'e'; - midiinfo->name[4] = 'm'; - midiinfo->name[5] = 'i'; - midiinfo->name[6] = 'd'; - midiinfo->name[7] = 'i'; - midiinfo->device = midiunit; - midiinfo->capabilities = scp->midi_flags[midiunit]; - /* - * TODO: What devtype? - */ - midiinfo->dev_type = 0x01; - ret = 0; - } else - ret = EINVAL; - mtx_unlock(&scp->seq_lock); - break; - case SNDCTL_SEQ_THRESHOLD: - mtx_lock(&scp->seq_lock); - RANGE(*(int *)arg, 1, MIDIQ_SIZE(scp->out_q) - 1); - scp->out_water = *(int *)arg; - mtx_unlock(&scp->seq_lock); - SEQ_DEBUG(3, printf("seq_ioctl: water %d.\n", *(int *)arg)); - ret = 0; - break; - case SNDCTL_MIDI_PRETIME: - tmp = *(int *)arg; - if (tmp < 0) - tmp = 0; - mtx_lock(&scp->seq_lock); - scp->pre_event_timeout = (hz * tmp) / 10; - *(int *)arg = scp->pre_event_timeout; - mtx_unlock(&scp->seq_lock); - SEQ_DEBUG(3, printf("seq_ioctl: pretime %d.\n", *(int *)arg)); - ret = 0; - break; - case SNDCTL_FM_4OP_ENABLE: - case SNDCTL_PMGR_IFACE: - case SNDCTL_PMGR_ACCESS: - /* - * Patch manager and fm are ded, ded, ded. - */ - /* fallthrough */ - default: - /* - * TODO: Consider ioctl default case. - * Old code used to - * if ((scp->fflags & O_ACCMODE) == FREAD) { - * ret = EIO; - * break; - * } - * Then pass on the ioctl to device 0 - */ - SEQ_DEBUG(2, - printf("seq_ioctl: unsupported IOCTL %ld.\n", cmd)); - ret = EINVAL; - break; - } - - return ret; -} - -int -seq_poll(struct cdev *i_dev, int events, struct thread *td) -{ - int ret, lim; - struct seq_softc *scp = i_dev->si_drv1; - - SEQ_DEBUG(3, printf("seq_poll: unit %d.\n", scp->unit)); - SEQ_DEBUG(1, printf("seq_poll: unit %d.\n", scp->unit)); - - mtx_lock(&scp->seq_lock); - - ret = 0; - - /* Look up the apropriate queue and select it. */ - if ((events & (POLLOUT | POLLWRNORM)) != 0) { - /* Start playing. */ - scp->playing = 1; - cv_broadcast(&scp->state_cv); - cv_broadcast(&scp->out_cv); - - lim = scp->out_water; - - if (MIDIQ_AVAIL(scp->out_q) < lim) - /* No enough space, record select. */ - selrecord(td, &scp->out_sel); - else - /* We can write now. */ - ret |= events & (POLLOUT | POLLWRNORM); - } - if ((events & (POLLIN | POLLRDNORM)) != 0) { - /* TODO: Start recording. */ - - /* Find out the boundary. */ - lim = 1; - if (MIDIQ_LEN(scp->in_q) < lim) - /* No data ready, record select. */ - selrecord(td, &scp->in_sel); - else - /* We can read now. */ - ret |= events & (POLLIN | POLLRDNORM); - } - mtx_unlock(&scp->seq_lock); - - return (ret); -} - -#if 0 -static void -sein_qtr(void *p, void /* mididev_info */ *md) -{ - struct seq_softc *scp; - - scp = (struct seq_softc *)p; - - mtx_lock(&scp->seq_lock); - - /* Restart playing if we have the data to output. */ - if (scp->queueout_pending) - seq_callback(scp, SEQ_CB_START | SEQ_CB_WR); - /* Check the midi device if we are reading. */ - if ((scp->flags & SEQ_F_READING) != 0) - seq_midiinput(scp, md); - - mtx_unlock(&scp->seq_lock); -} - -#endif -/* - * seq_convertold - * Was the old playevent. Use this to convert and old - * style /dev/sequencer event to a /dev/music event - */ -static int -seq_convertold(u_char *event, u_char *out) -{ - int used; - u_char dev, chn, note, vel; - - out[0] = out[1] = out[2] = out[3] = out[4] = out[5] = out[6] = - out[7] = 0; - - dev = 0; - chn = event[1]; - note = event[2]; - vel = event[3]; - - used = 0; - -restart: - /* - * TODO: Debug statement - */ - switch (event[0]) { - case EV_TIMING: - case EV_CHN_VOICE: - case EV_CHN_COMMON: - case EV_SYSEX: - case EV_SEQ_LOCAL: - out[0] = event[0]; - out[1] = event[1]; - out[2] = event[2]; - out[3] = event[3]; - out[4] = event[4]; - out[5] = event[5]; - out[6] = event[6]; - out[7] = event[7]; - used += 8; - break; - case SEQ_NOTEOFF: - out[0] = EV_CHN_VOICE; - out[1] = dev; - out[2] = MIDI_NOTEOFF; - out[3] = chn; - out[4] = note; - out[5] = 255; - used += 4; - break; - - case SEQ_NOTEON: - out[0] = EV_CHN_VOICE; - out[1] = dev; - out[2] = MIDI_NOTEON; - out[3] = chn; - out[4] = note; - out[5] = vel; - used += 4; - break; - - /* - * wait delay = (event[2] << 16) + (event[3] << 8) + event[4] - */ - - case SEQ_PGMCHANGE: - out[0] = EV_CHN_COMMON; - out[1] = dev; - out[2] = MIDI_PGM_CHANGE; - out[3] = chn; - out[4] = note; - out[5] = vel; - used += 4; - break; -/* - out[0] = EV_TIMING; - out[1] = dev; - out[2] = MIDI_PGM_CHANGE; - out[3] = chn; - out[4] = note; - out[5] = vel; - SEQ_DEBUG(4,printf("seq_playevent: synctimer\n")); - break; -*/ - - case SEQ_MIDIPUTC: - SEQ_DEBUG(4, - printf("seq_playevent: put data 0x%02x, unit %d.\n", - event[1], event[2])); - /* - * Pass through to the midi device. - * device = event[2] - * data = event[1] - */ - out[0] = SEQ_MIDIPUTC; - out[1] = dev; - out[2] = chn; - used += 4; - break; -#ifdef notyet - case SEQ_ECHO: - /* - * This isn't handled here yet because I don't know if I can - * just use four bytes events. There might be consequences - * in the _read routing - */ - if (seq_copytoinput(scp, event, 4) == EAGAIN) { - ret = QUEUEFULL; - break; - } - ret = MORE; - break; -#endif - case SEQ_EXTENDED: - switch (event[1]) { - case SEQ_NOTEOFF: - case SEQ_NOTEON: - case SEQ_PGMCHANGE: - event++; - used = 4; - goto restart; - break; - case SEQ_AFTERTOUCH: - /* - * SYNTH_AFTERTOUCH(md, event[3], event[4]) - */ - case SEQ_BALANCE: - /* - * SYNTH_PANNING(md, event[3], (char)event[4]) - */ - case SEQ_CONTROLLER: - /* - * SYNTH_CONTROLLER(md, event[3], event[4], *(short *)&event[5]) - */ - case SEQ_VOLMODE: - /* - * SYNTH_VOLUMEMETHOD(md, event[3]) - */ - default: - SEQ_DEBUG(2, - printf("seq_convertold: SEQ_EXTENDED type %d" - "not handled\n", event[1])); - break; - } - break; - case SEQ_WAIT: - out[0] = EV_TIMING; - out[1] = TMR_WAIT_REL; - out[4] = event[2]; - out[5] = event[3]; - out[6] = event[4]; - - SEQ_DEBUG(5, printf("SEQ_WAIT %d", - event[2] + (event[3] << 8) + (event[4] << 24))); - - used += 4; - break; - - case SEQ_ECHO: - case SEQ_SYNCTIMER: - case SEQ_PRIVATE: - default: - SEQ_DEBUG(2, - printf("seq_convertold: event type %d not handled %d %d %d\n", - event[0], event[1], event[2], event[3])); - break; - } - return used; -} - -/* - * Writting to the sequencer buffer never blocks and drops - * input which cannot be queued - */ -void -seq_copytoinput(struct seq_softc *scp, u_char *event, int len) -{ - - mtx_assert(&scp->seq_lock, MA_OWNED); - - if (MIDIQ_AVAIL(scp->in_q) < len) { - /* - * ENOROOM? EINPUTDROPPED? ETOUGHLUCK? - */ - SEQ_DEBUG(2, printf("seq_copytoinput: queue full\n")); - } else { - MIDIQ_ENQ(scp->in_q, event, len); - selwakeup(&scp->in_sel); - cv_broadcast(&scp->in_cv); - } - -} - -static int -seq_chnvoice(struct seq_softc *scp, kobj_t md, u_char *event) -{ - int ret, voice; - u_char cmd, chn, note, parm; - - ret = 0; - cmd = event[2]; - chn = event[3]; - note = event[4]; - parm = event[5]; - - mtx_assert(&scp->seq_lock, MA_OWNED); - - SEQ_DEBUG(5, printf("seq_chnvoice: unit %d, dev %d, cmd %s," - " chn %d, note %d, parm %d.\n", scp->unit, event[1], - midi_cmdname(cmd, cmdtab_seqcv), chn, note, parm)); - - voice = SYNTH_ALLOC(md, chn, note); - - mtx_unlock(&scp->seq_lock); - - switch (cmd) { - case MIDI_NOTEON: - if (note < 128 || note == 255) { -#if 0 - if (scp->music && chn == 9) { - /* - * This channel is a percussion. The note - * number is the patch number. - */ - /* - mtx_unlock(&scp->seq_lock); - if (SYNTH_SETINSTR(md, voice, 128 + note) - == EAGAIN) { - mtx_lock(&scp->seq_lock); - return (QUEUEFULL); - } - mtx_lock(&scp->seq_lock); - */ - note = 60; /* Middle C. */ - } -#endif - if (scp->music) { - /* - mtx_unlock(&scp->seq_lock); - if (SYNTH_SETUPVOICE(md, voice, chn) - == EAGAIN) { - mtx_lock(&scp->seq_lock); - return (QUEUEFULL); - } - mtx_lock(&scp->seq_lock); - */ - } - SYNTH_STARTNOTE(md, voice, note, parm); - } - break; - case MIDI_NOTEOFF: - SYNTH_KILLNOTE(md, voice, note, parm); - break; - case MIDI_KEY_PRESSURE: - SYNTH_AFTERTOUCH(md, voice, parm); - break; - default: - ret = 1; - SEQ_DEBUG(2, printf("seq_chnvoice event type %d not handled\n", - event[1])); - break; - } - - mtx_lock(&scp->seq_lock); - return ret; -} - -static int -seq_chncommon(struct seq_softc *scp, kobj_t md, u_char *event) -{ - int ret; - u_short w14; - u_char cmd, chn, p1; - - ret = 0; - cmd = event[2]; - chn = event[3]; - p1 = event[4]; - w14 = *(u_short *)&event[6]; - - SEQ_DEBUG(5, printf("seq_chncommon: unit %d, dev %d, cmd %s, chn %d," - " p1 %d, w14 %d.\n", scp->unit, event[1], - midi_cmdname(cmd, cmdtab_seqccmn), chn, p1, w14)); - mtx_unlock(&scp->seq_lock); - switch (cmd) { - case MIDI_PGM_CHANGE: - SEQ_DEBUG(4, printf("seq_chncommon pgmchn chn %d pg %d\n", - chn, p1)); - SYNTH_SETINSTR(md, chn, p1); - break; - case MIDI_CTL_CHANGE: - SEQ_DEBUG(4, printf("seq_chncommon ctlch chn %d pg %d %d\n", - chn, p1, w14)); - SYNTH_CONTROLLER(md, chn, p1, w14); - break; - case MIDI_PITCH_BEND: - if (scp->music) { - /* - * TODO: MIDI_PITCH_BEND - */ -#if 0 - mtx_lock(&md->synth.vc_mtx); - md->synth.chn_info[chn].bender_value = w14; - if (md->midiunit >= 0) { - /* - * Handle all of the notes playing on this - * channel. - */ - key = ((int)chn << 8); - for (i = 0; i < md->synth.alloc.max_voice; i++) - if ((md->synth.alloc.map[i] & 0xff00) == key) { - mtx_unlock(&md->synth.vc_mtx); - mtx_unlock(&scp->seq_lock); - if (md->synth.bender(md, i, w14) == EAGAIN) { - mtx_lock(&scp->seq_lock); - return (QUEUEFULL); - } - mtx_lock(&scp->seq_lock); - } - } else { - mtx_unlock(&md->synth.vc_mtx); - mtx_unlock(&scp->seq_lock); - if (md->synth.bender(md, chn, w14) == EAGAIN) { - mtx_lock(&scp->seq_lock); - return (QUEUEFULL); - } - mtx_lock(&scp->seq_lock); - } -#endif - } else - SYNTH_BENDER(md, chn, w14); - break; - default: - ret = 1; - SEQ_DEBUG(2, - printf("seq_chncommon event type %d not handled.\n", - event[1])); - break; - - } - mtx_lock(&scp->seq_lock); - return ret; -} - -static int -seq_timing(struct seq_softc *scp, u_char *event) -{ - int param; - int ret; - - ret = 0; - param = event[4] + (event[5] << 8) + - (event[6] << 16) + (event[7] << 24); - - SEQ_DEBUG(5, printf("seq_timing: unit %d, cmd %d, param %d.\n", - scp->unit, event[1], param)); - switch (event[1]) { - case TMR_WAIT_REL: - timer_wait(scp, param, 0); - break; - case TMR_WAIT_ABS: - timer_wait(scp, param, 1); - break; - case TMR_START: - timer_start(scp); - cv_broadcast(&scp->reset_cv); - break; - case TMR_STOP: - timer_stop(scp); - /* - * The following cv_broadcast isn't needed since we only - * wait for 0->1 transitions. It probably won't hurt - */ - cv_broadcast(&scp->reset_cv); - break; - case TMR_CONTINUE: - timer_continue(scp); - cv_broadcast(&scp->reset_cv); - break; - case TMR_TEMPO: - if (param < 8) - param = 8; - if (param > 360) - param = 360; - SEQ_DEBUG(4, printf("Timer set tempo %d\n", param)); - timer_setvals(scp, param, scp->timerbase); - break; - case TMR_TIMERBASE: - if (param < 1) - param = 1; - if (param > 1000) - param = 1000; - SEQ_DEBUG(4, printf("Timer set timerbase %d\n", param)); - timer_setvals(scp, scp->tempo, param); - break; - case TMR_ECHO: - /* - * TODO: Consider making 4-byte events for /dev/sequencer - * PRO: Maybe needed by legacy apps - * CON: soundcard.h has been warning for a while many years - * to expect 8 byte events. - */ -#if 0 - if (scp->music) - seq_copytoinput(scp, event, 8); - else { - param = (param << 8 | SEQ_ECHO); - seq_copytoinput(scp, (u_char *)¶m, 4); - } -#else - seq_copytoinput(scp, event, 8); -#endif - break; - default: - SEQ_DEBUG(2, printf("seq_timing event type %d not handled.\n", - event[1])); - ret = 1; - break; - } - return ret; -} - -static int -seq_local(struct seq_softc *scp, u_char *event) -{ - int ret; - - ret = 0; - mtx_assert(&scp->seq_lock, MA_OWNED); - - SEQ_DEBUG(5, printf("seq_local: unit %d, cmd %d\n", scp->unit, - event[1])); - switch (event[1]) { - default: - SEQ_DEBUG(1, printf("seq_local event type %d not handled\n", - event[1])); - ret = 1; - break; - } - return ret; -} - -static int -seq_sysex(struct seq_softc *scp, kobj_t md, u_char *event) -{ - int i, l; - - mtx_assert(&scp->seq_lock, MA_OWNED); - SEQ_DEBUG(5, printf("seq_sysex: unit %d device %d\n", scp->unit, - event[1])); - l = 0; - for (i = 0; i < 6 && event[i + 2] != 0xff; i++) - l = i + 1; - if (l > 0) { - mtx_unlock(&scp->seq_lock); - if (SYNTH_SENDSYSEX(md, &event[2], l) == EAGAIN) { - mtx_lock(&scp->seq_lock); - return 1; - } - mtx_lock(&scp->seq_lock); - } - return 0; -} - -/* - * Reset no longer closes the raw devices nor seq_sync's - * Callers are IOCTL and seq_close - */ -static void -seq_reset(struct seq_softc *scp) -{ - int chn, i; - kobj_t m; - - mtx_assert(&scp->seq_lock, MA_OWNED); - - SEQ_DEBUG(5, printf("seq_reset: unit %d.\n", scp->unit)); - - /* - * Stop reading and writing. - */ - - /* scp->recording = 0; */ - scp->playing = 0; - cv_broadcast(&scp->state_cv); - cv_broadcast(&scp->out_cv); - cv_broadcast(&scp->reset_cv); - - /* - * For now, don't reset the timers. - */ - MIDIQ_CLEAR(scp->in_q); - MIDIQ_CLEAR(scp->out_q); - - for (i = 0; i < scp->midi_number; i++) { - m = scp->midis[i]; - mtx_unlock(&scp->seq_lock); - SYNTH_RESET(m); - for (chn = 0; chn < 16; chn++) { - SYNTH_CONTROLLER(m, chn, 123, 0); - SYNTH_CONTROLLER(m, chn, 121, 0); - SYNTH_BENDER(m, chn, 1 << 13); - } - mtx_lock(&scp->seq_lock); - } -} - -/* - * seq_sync - * *really* flush the output queue - * flush the event queue, then flush the synthsisers. - * Callers are IOCTL and close - */ - -#define SEQ_SYNC_TIMEOUT 8 -static int -seq_sync(struct seq_softc *scp) -{ - int i, rl, sync[16], done; - - mtx_assert(&scp->seq_lock, MA_OWNED); - - SEQ_DEBUG(4, printf("seq_sync: unit %d.\n", scp->unit)); - - /* - * Wait until output queue is empty. Check every so often to see if - * the queue is moving along. If it isn't just abort. - */ - while (!MIDIQ_EMPTY(scp->out_q)) { - - if (!scp->playing) { - scp->playing = 1; - cv_broadcast(&scp->state_cv); - cv_broadcast(&scp->out_cv); - } - rl = MIDIQ_LEN(scp->out_q); - - i = cv_timedwait_sig(&scp->out_cv, - &scp->seq_lock, SEQ_SYNC_TIMEOUT * hz); - - if (i == EINTR || i == ERESTART) { - if (i == EINTR) { - /* - * XXX: I don't know why we stop playing - */ - scp->playing = 0; - cv_broadcast(&scp->out_cv); - } - return i; - } - if (i == EWOULDBLOCK && rl == MIDIQ_LEN(scp->out_q) && - scp->waiting == 0) { - /* - * A queue seems to be stuck up. Give up and clear - * queues. - */ - MIDIQ_CLEAR(scp->out_q); - scp->playing = 0; - cv_broadcast(&scp->state_cv); - cv_broadcast(&scp->out_cv); - cv_broadcast(&scp->reset_cv); - - /* - * TODO: Consider if the raw devices need to be flushed - */ - - SEQ_DEBUG(1, printf("seq_sync queue stuck, aborting\n")); - - return i; - } - } - - scp->playing = 0; - /* - * Since syncing a midi device might block, unlock scp->seq_lock. - */ - - mtx_unlock(&scp->seq_lock); - for (i = 0; i < scp->midi_number; i++) - sync[i] = 1; - - do { - done = 1; - for (i = 0; i < scp->midi_number; i++) - if (sync[i]) { - if (SYNTH_INSYNC(scp->midis[i]) == 0) - sync[i] = 0; - else - done = 0; - } - if (!done) - DELAY(5000); - - } while (!done); - - mtx_lock(&scp->seq_lock); - return 0; -} - -char * -midi_cmdname(int cmd, midi_cmdtab *tab) -{ - while (tab->name != NULL) { - if (cmd == tab->cmd) - return (tab->name); - tab++; - } - - return ("unknown"); -} diff --git a/sys/dev/sound/midi/sequencer.h b/sys/dev/sound/midi/sequencer.h deleted file mode 100644 index 797e9da06d..0000000000 --- a/sys/dev/sound/midi/sequencer.h +++ /dev/null @@ -1,90 +0,0 @@ -/*- - * Copyright (c) 2003 Mathew Kanner - * Copyright (c) 1999 Seigo Tanimura - * All rights reserved. - * - * 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: head/sys/dev/sound/midi/sequencer.h 193640 2009-06-07 19:12:08Z ariff $ - */ - -/* - * Include file for the midi sequence driver. - */ - -#ifndef _SEQUENCER_H_ -#define _SEQUENCER_H_ - - -#define NSEQ_MAX 16 - -/* - * many variables should be reduced to a range. Here define a macro - */ - -#define RANGE(var, low, high) (var) = \ -((var)<(low)?(low) : (var)>(high)?(high) : (var)) - -#ifdef _KERNEL - -void seq_timer(void *arg); - -SYSCTL_DECL(_hw_midi_seq); - -extern int seq_debug; - -#define SEQ_DEBUG(y, x) \ - do { \ - if (seq_debug >= y) { \ - (x); \ - } \ - } while (0) - -SYSCTL_DECL(_hw_midi); - -#endif /* _KERNEL */ - -#define SYNTHPROP_MIDI 1 -#define SYNTHPROP_SYNTH 2 -#define SYNTHPROP_RX 4 -#define SYNTHPROP_TX 8 - -struct _midi_cmdtab { - int cmd; - char *name; -}; -typedef struct _midi_cmdtab midi_cmdtab; -extern midi_cmdtab cmdtab_seqevent[]; -extern midi_cmdtab cmdtab_seqioctl[]; -extern midi_cmdtab cmdtab_timer[]; -extern midi_cmdtab cmdtab_seqcv[]; -extern midi_cmdtab cmdtab_seqccmn[]; - -char *midi_cmdname(int cmd, midi_cmdtab * tab); - -enum { - MORE, - TIMERARMED, - QUEUEFULL -}; - -#endif diff --git a/sys/dev/sound/midi/synth_if.m b/sys/dev/sound/midi/synth_if.m deleted file mode 100644 index faef209c1f..0000000000 --- a/sys/dev/sound/midi/synth_if.m +++ /dev/null @@ -1,313 +0,0 @@ -#- -# Copyright (c) 2003 Mathew Kanner -# All rights reserved. -# -# 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: head/sys/dev/sound/midi/synth_if.m 166971 2007-02-25 13:51:52Z netchild $ -# - -INTERFACE synth; - -#include - -CODE { - -synth_killnote_t nokillnote; -synth_startnote_t nostartnote; -synth_setinstr_t nosetinstr; -synth_hwcontrol_t nohwcontrol; -synth_aftertouch_t noaftertouch; -synth_panning_t nopanning; -synth_controller_t nocontroller; -synth_volumemethod_t novolumemethod; -synth_bender_t nobender; -synth_setupvoice_t nosetupvoice; -synth_sendsysex_t nosendsysex; -synth_allocvoice_t noallocvoice; -synth_writeraw_t nowriteraw; -synth_reset_t noreset; -synth_shortname_t noshortname; -synth_open_t noopen; -synth_close_t noclose; -synth_query_t noquery; -synth_insync_t noinsync; -synth_alloc_t noalloc; - - int - nokillnote(void *_kobj, uint8_t _chn, uint8_t _note, uint8_t _vel) - { - printf("nokillnote\n"); - return 0; - } - - int - noopen(void *_kobj, void *_arg, int mode) - { - printf("noopen\n"); - return 0; - } - - int - noquery(void *_kboj) - { - printf("noquery\n"); - return 0; - } - - int - nostartnote(void *_kb, uint8_t _voice, uint8_t _note, uint8_t _parm) - { - printf("nostartnote\n"); - return 0; - } - - int - nosetinstr(void *_kb, uint8_t _chn, uint16_t _patchno) - { - printf("nosetinstr\n"); - return 0; - } - - int - nohwcontrol(void *_kb, uint8_t *_event) - { - printf("nohwcontrol\n"); - return 0; - } - - int - noaftertouch ( void /* X */ * _kobj, uint8_t _x1, uint8_t _x2) - { - printf("noaftertouch\n"); - return 0; - } - - int - nopanning ( void /* X */ * _kobj, uint8_t _x1, uint8_t _x2) - { - printf("nopanning\n"); - return 0; - } - - int - nocontroller ( void /* X */ * _kobj, uint8_t _x1, uint8_t _x2, uint16_t _x3) - { - printf("nocontroller\n"); - return 0; - } - - int - novolumemethod ( - void /* X */ * _kobj, - uint8_t _x1) - { - printf("novolumemethod\n"); - return 0; - } - - int - nobender ( void /* X */ * _kobj, uint8_t _voice, uint16_t _bend) - { - printf("nobender\n"); - return 0; - } - - int - nosetupvoice ( void /* X */ * _kobj, uint8_t _voice, uint8_t _chn) - { - - printf("nosetupvoice\n"); - return 0; - } - - int - nosendsysex ( void /* X */ * _kobj, void * _buf, size_t _len) - { - printf("nosendsysex\n"); - return 0; - } - - int - noallocvoice ( void /* X */ * _kobj, uint8_t _chn, uint8_t _note, void *_x) - { - printf("noallocvoice\n"); - return 0; - } - - int - nowriteraw ( void /* X */ * _kobjt, uint8_t * _buf, size_t _len) - { - printf("nowriteraw\n"); - return 1; - } - - int - noreset ( void /* X */ * _kobjt) - { - - printf("noreset\n"); - return 0; - } - - char * - noshortname (void /* X */ * _kobjt) - { - printf("noshortname\n"); - return "noshortname"; - } - - int - noclose ( void /* X */ * _kobjt) - { - - printf("noclose\n"); - return 0; - } - - int - noinsync (void /* X */ * _kobjt) - { - - printf("noinsync\n"); - return 0; - } - - int - noalloc ( void /* x */ * _kbojt, uint8_t _chn, uint8_t _note) - { - printf("noalloc\n"); - return 0; - } -} - -METHOD int killnote { - void /* X */ *_kobj; - uint8_t _chan; - uint8_t _note; - uint8_t _vel; -} DEFAULT nokillnote; - -METHOD int startnote { - void /* X */ *_kobj; - uint8_t _voice; - uint8_t _note; - uint8_t _parm; -} DEFAULT nostartnote; - -METHOD int setinstr { - void /* X */ *_kobj; - uint8_t _chn; - uint16_t _patchno; -} DEFAULT nosetinstr; - -METHOD int hwcontrol { - void /* X */ *_kobj; - uint8_t *_event; -} DEFAULT nohwcontrol; - -METHOD int aftertouch { - void /* X */ *_kobj; - uint8_t _x1; - uint8_t _x2; -} DEFAULT noaftertouch; - -METHOD int panning { - void /* X */ *_kobj; - uint8_t _x1; - uint8_t _x2; -} DEFAULT nopanning; - -METHOD int controller { - void /* X */ *_kobj; - uint8_t _x1; - uint8_t _x2; - uint16_t _x3; -} DEFAULT nocontroller; - -METHOD int volumemethod { - void /* X */ *_kobj; - uint8_t _x1; -} DEFAULT novolumemethod; - -METHOD int bender { - void /* X */ *_kobj; - uint8_t _voice; - uint16_t _bend; -} DEFAULT nobender; - -METHOD int setupvoice { - void /* X */ *_kobj; - uint8_t _voice; - uint8_t _chn; -} DEFAULT nosetupvoice; - -METHOD int sendsysex { - void /* X */ *_kobj; - void *_buf; - size_t _len; -} DEFAULT nosendsysex; - -METHOD int allocvoice { - void /* X */ *_kobj; - uint8_t _chn; - uint8_t _note; - void *_x; -} DEFAULT noallocvoice; - -METHOD int writeraw { - void /* X */ *_kobjt; - uint8_t *_buf; - size_t _len; -} DEFAULT nowriteraw; - -METHOD int reset { - void /* X */ *_kobjt; -} DEFAULT noreset; - -METHOD char * shortname { - void /* X */ *_kobjt; -} DEFAULT noshortname; - -METHOD int open { - void /* X */ *_kobjt; - void *_sythn; - int _mode; -} DEFAULT noopen; - -METHOD int close { - void /* X */ *_kobjt; -} DEFAULT noclose; - -METHOD int query { - void /* X */ *_kobjt; -} DEFAULT noquery; - -METHOD int insync { - void /* X */ *_kobjt; -} DEFAULT noinsync; - -METHOD int alloc { - void /* x */ *_kbojt; - uint8_t _chn; - uint8_t _note; -} DEFAULT noalloc; diff --git a/sys/dev/sound/pci/cmi.c b/sys/dev/sound/pci/cmi.c index 4443526501..543133e101 100644 --- a/sys/dev/sound/pci/cmi.c +++ b/sys/dev/sound/pci/cmi.c @@ -54,10 +54,8 @@ #include #include -#include #include "mixer_if.h" -#include "mpufoi_if.h" SND_DECLARE_FILE("$FreeBSD: head/sys/dev/sound/pci/cmi.c 254263 2013-08-12 23:30:01Z scottl $"); @@ -121,13 +119,6 @@ struct sc_info { int spdif_enabled; unsigned int bufsz; struct sc_chinfo pch, rch; - - struct mpu401 *mpu; - mpu401_intr_t *mpu_intr; - struct resource *mpu_reg; - int mpu_regid; - bus_space_tag_t mpu_bt; - bus_space_handle_t mpu_bh; }; /* Channel caps */ @@ -572,9 +563,6 @@ cmi_intr(void *data) } } - if(sc->mpu_intr) { - (sc->mpu_intr)(sc->mpu); - } snd_mtxunlock(sc->lock); return; } @@ -775,75 +763,6 @@ static kobj_method_t cmi_mixer_methods[] = { }; MIXER_DECLARE(cmi_mixer); -/* - * mpu401 functions - */ - -static unsigned char -cmi_mread(struct mpu401 *arg, void *sc, int reg) -{ - unsigned int d; - - d = bus_space_read_1(0,0, 0x330 + reg); - /* printf("cmi_mread: reg %x %x\n",reg, d); - */ - return d; -} - -static void -cmi_mwrite(struct mpu401 *arg, void *sc, int reg, unsigned char b) -{ - - bus_space_write_1(0,0,0x330 + reg , b); -} - -static int -cmi_muninit(struct mpu401 *arg, void *cookie) -{ - struct sc_info *sc = cookie; - - snd_mtxlock(sc->lock); - sc->mpu_intr = 0; - sc->mpu = 0; - snd_mtxunlock(sc->lock); - - return 0; -} - -static kobj_method_t cmi_mpu_methods[] = { - KOBJMETHOD(mpufoi_read, cmi_mread), - KOBJMETHOD(mpufoi_write, cmi_mwrite), - KOBJMETHOD(mpufoi_uninit, cmi_muninit), - KOBJMETHOD_END -}; - -static DEFINE_CLASS(cmi_mpu, cmi_mpu_methods, 0); - -static void -cmi_midiattach(struct sc_info *sc) { -/* - const struct { - int port,bits; - } *p, ports[] = { - {0x330,0}, - {0x320,1}, - {0x310,2}, - {0x300,3}, - {0,0} } ; - Notes, CMPCI_REG_VMPUSEL sets the io port for the mpu. Does - anyone know how to bus_space tag? -*/ - cmi_clr4(sc, CMPCI_REG_FUNC_1, CMPCI_REG_UART_ENABLE); - cmi_clr4(sc, CMPCI_REG_LEGACY_CTRL, - CMPCI_REG_VMPUSEL_MASK << CMPCI_REG_VMPUSEL_SHIFT); - cmi_set4(sc, CMPCI_REG_LEGACY_CTRL, - 0 << CMPCI_REG_VMPUSEL_SHIFT ); - cmi_set4(sc, CMPCI_REG_FUNC_1, CMPCI_REG_UART_ENABLE); - sc->mpu = mpu401_init(&cmi_mpu_class, sc, cmi_intr, &sc->mpu_intr); -} - - - /* ------------------------------------------------------------------------- */ /* Power and reset */ @@ -900,9 +819,6 @@ cmi_uninit(struct sc_info *sc) cmi_clr4(sc, CMPCI_REG_FUNC_0, CMPCI_REG_CH0_ENABLE | CMPCI_REG_CH1_ENABLE); cmi_clr4(sc, CMPCI_REG_FUNC_1, CMPCI_REG_UART_ENABLE); - - if( sc->mpu ) - sc->mpu_intr = 0; } /* ------------------------------------------------------------------------- */ @@ -952,9 +868,6 @@ cmi_attach(device_t dev) sc->st = rman_get_bustag(sc->reg); sc->sh = rman_get_bushandle(sc->reg); - if (0) - cmi_midiattach(sc); - sc->irqid = 0; sc->irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, &sc->irqid, RF_ACTIVE | RF_SHAREABLE); @@ -1035,12 +948,7 @@ cmi_detach(device_t dev) bus_dma_tag_destroy(sc->parent_dmat); bus_teardown_intr(dev, sc->irq, sc->ih); bus_release_resource(dev, SYS_RES_IRQ, sc->irqid, sc->irq); - if(sc->mpu) - mpu401_uninit(sc->mpu); bus_release_resource(dev, SYS_RES_IOPORT, sc->regid, sc->reg); - if (sc->mpu_reg) - bus_release_resource(dev, SYS_RES_IOPORT, sc->mpu_regid, sc->mpu_reg); - snd_mtxfree(sc->lock); free(sc, M_DEVBUF); @@ -1111,5 +1019,4 @@ static driver_t cmi_driver = { DRIVER_MODULE(snd_cmi, pci, cmi_driver, pcm_devclass, 0, 0); MODULE_DEPEND(snd_cmi, sound, SOUND_MINVER, SOUND_PREFVER, SOUND_MAXVER); -MODULE_DEPEND(snd_cmi, midi, 1,1,1); MODULE_VERSION(snd_cmi, 1); diff --git a/sys/dev/sound/pci/emu10k1.c b/sys/dev/sound/pci/emu10k1.c index ce90e075d1..56cd9e93d7 100644 --- a/sys/dev/sound/pci/emu10k1.c +++ b/sys/dev/sound/pci/emu10k1.c @@ -38,9 +38,6 @@ #include #include -#include -#include "mpufoi_if.h" - SND_DECLARE_FILE("$FreeBSD: head/sys/dev/sound/pci/emu10k1.c 267581 2014-06-17 16:07:57Z jhb $"); /* -------------------------------------------------------------------- */ @@ -228,9 +225,6 @@ struct sc_info { struct emu_voice voice[64]; struct sc_pchinfo pch[EMU_MAX_CHANS]; struct sc_rchinfo rch[3]; - struct mpu401 *mpu; - mpu401_intr_t *mpu_intr; - int mputx; }; /* -------------------------------------------------------------------- */ @@ -1156,63 +1150,6 @@ static kobj_method_t emurchan_methods[] = { }; CHANNEL_DECLARE(emurchan); -static unsigned char -emu_mread(struct mpu401 *arg, void *sc, int reg) -{ - unsigned int d; - - d = emu_rd((struct sc_info *)sc, 0x18 + reg, 1); - return d; -} - -static void -emu_mwrite(struct mpu401 *arg, void *sc, int reg, unsigned char b) -{ - - emu_wr((struct sc_info *)sc, 0x18 + reg, b, 1); -} - -static int -emu_muninit(struct mpu401 *arg, void *cookie) -{ - struct sc_info *sc = cookie; - - snd_mtxlock(sc->lock); - sc->mpu_intr = 0; - snd_mtxunlock(sc->lock); - - return 0; -} - -static kobj_method_t emu_mpu_methods[] = { - KOBJMETHOD(mpufoi_read, emu_mread), - KOBJMETHOD(mpufoi_write, emu_mwrite), - KOBJMETHOD(mpufoi_uninit, emu_muninit), - KOBJMETHOD_END -}; - -static DEFINE_CLASS(emu_mpu, emu_mpu_methods, 0); - -static void -emu_intr2(void *p) -{ - struct sc_info *sc = (struct sc_info *)p; - - if (sc->mpu_intr) - (sc->mpu_intr)(sc->mpu); -} - -static void -emu_midiattach(struct sc_info *sc) -{ - int i; - - i = emu_rd(sc, EMU_INTE, 4); - i |= EMU_INTE_MIDIRXENABLE; - emu_wr(sc, EMU_INTE, i, 4); - - sc->mpu = mpu401_init(&emu_mpu_class, sc, emu_intr2, &sc->mpu_intr); -} /* -------------------------------------------------------------------- */ /* The interrupt handler */ @@ -1255,11 +1192,6 @@ emu_intr(void *data) #endif } - if (stat & EMU_IPR_MIDIRECVBUFE) - if (sc->mpu_intr) { - (sc->mpu_intr)(sc->mpu); - ack |= EMU_IPR_MIDIRECVBUFE | EMU_IPR_MIDITRANSBUFE; - } if (stat & ~ack) device_printf(sc->dev, "dodgy irq: %x (harmless)\n", stat & ~ack); @@ -2034,8 +1966,6 @@ emu_uninit(struct sc_info *sc) emu_free(sc, sc->mem.ptb_pages, sc->mem.ptb_map); emu_free(sc, sc->mem.silent_page, sc->mem.silent_map); - if(sc->mpu) - mpu401_uninit(sc->mpu); return 0; } @@ -2121,8 +2051,6 @@ emu_pci_attach(device_t dev) gotmic = (ac97_getcaps(codec) & AC97_CAP_MICCHANNEL) ? 1 : 0; if (mixer_init(dev, ac97_getmixerclass(), codec) == -1) goto bad; - emu_midiattach(sc); - i = 0; sc->irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, &i, RF_ACTIVE | RF_SHAREABLE); diff --git a/sys/dev/sound/pci/emu10kx-midi.c b/sys/dev/sound/pci/emu10kx-midi.c deleted file mode 100644 index 51232146a8..0000000000 --- a/sys/dev/sound/pci/emu10kx-midi.c +++ /dev/null @@ -1,253 +0,0 @@ -/*- - * Copyright (c) 1999 Seigo Tanimura - * Copyright (c) 2003 Mathew Kanner - * Copyright (c) 2003-2006 Yuriy Tsibizov - * All rights reserved - * - * 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: head/sys/dev/sound/pci/emu10kx-midi.c 246128 2013-01-30 18:01:20Z sbz $ - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#ifdef HAVE_KERNEL_OPTION_HEADERS -#include "opt_snd.h" -#endif - -#include -#include - -#include -#include -#include "mpufoi_if.h" - -#include -#include - -struct emu_midi_softc { - struct mtx mtx; - device_t dev; - struct mpu401 *mpu; - mpu401_intr_t *mpu_intr; - struct emu_sc_info *card; - int port; /* I/O port or I/O ptr reg */ - int is_emu10k1; - int fflags; /* File flags */ - int ihandle; /* interrupt manager handle */ -}; - -static uint32_t emu_midi_card_intr(void *p, uint32_t arg); -static devclass_t emu_midi_devclass; - -static unsigned char -emu_mread(struct mpu401 *arg __unused, void *cookie, int reg) -{ - struct emu_midi_softc *sc = cookie; - unsigned int d; - - d = 0; - if (sc->is_emu10k1) - d = emu_rd(sc->card, 0x18 + reg, 1); - else - d = emu_rdptr(sc->card, 0, sc->port + reg); - - return (d); -} - -static void -emu_mwrite(struct mpu401 *arg __unused, void *cookie, int reg, unsigned char b) -{ - struct emu_midi_softc *sc = cookie; - - if (sc->is_emu10k1) - emu_wr(sc->card, 0x18 + reg, b, 1); - else - emu_wrptr(sc->card, 0, sc->port + reg, b); -} - -static int -emu_muninit(struct mpu401 *arg __unused, void *cookie) -{ - struct emu_midi_softc *sc = cookie; - - mtx_lock(&sc->mtx); - sc->mpu_intr = NULL; - mtx_unlock(&sc->mtx); - - return (0); -} - -static kobj_method_t emu_mpu_methods[] = { - KOBJMETHOD(mpufoi_read, emu_mread), - KOBJMETHOD(mpufoi_write, emu_mwrite), - KOBJMETHOD(mpufoi_uninit, emu_muninit), - KOBJMETHOD_END -}; -static DEFINE_CLASS(emu_mpu, emu_mpu_methods, 0); - -static uint32_t -emu_midi_card_intr(void *p, uint32_t intr_status) -{ - struct emu_midi_softc *sc = (struct emu_midi_softc *)p; - if (sc->mpu_intr) - (sc->mpu_intr) (sc->mpu); - if (sc->mpu_intr == NULL) { - /* We should read MIDI event to unlock card after - * interrupt. XXX - check, why this happens. */ - if (bootverbose) - device_printf(sc->dev, "midi interrupt %08x without interrupt handler, force mread!\n", intr_status); - (void)emu_mread((void *)(NULL), sc, 0); - } - return (intr_status); /* Acknowledge everything */ -} - -static void -emu_midi_intr(void *p) -{ - (void)emu_midi_card_intr(p, 0); -} - -static int -emu_midi_probe(device_t dev) -{ - struct emu_midi_softc *scp; - uintptr_t func, r, is_emu10k1; - - r = BUS_READ_IVAR(device_get_parent(dev), dev, 0, &func); - if (func != SCF_MIDI) - return (ENXIO); - - scp = device_get_softc(dev); - bzero(scp, sizeof(*scp)); - r = BUS_READ_IVAR(device_get_parent(dev), dev, EMU_VAR_ISEMU10K1, &is_emu10k1); - scp->is_emu10k1 = is_emu10k1 ? 1 : 0; - - device_set_desc(dev, "EMU10Kx MIDI Interface"); - return (0); -} - -static int -emu_midi_attach(device_t dev) -{ - struct emu_midi_softc * scp; - struct sndcard_func *func; - struct emu_midiinfo *midiinfo; - uint32_t inte_val, ipr_val; - - scp = device_get_softc(dev); - func = device_get_ivars(dev); - - scp->dev = dev; - midiinfo = (struct emu_midiinfo *)func->varinfo; - scp->port = midiinfo->port; - scp->card = midiinfo->card; - - mtx_init(&scp->mtx, device_get_nameunit(dev), "midi softc", MTX_DEF); - - if (scp->is_emu10k1) { - /* SB Live! - only one MIDI device here */ - inte_val = 0; - /* inte_val |= EMU_INTE_MIDITXENABLE;*/ - inte_val |= EMU_INTE_MIDIRXENABLE; - ipr_val = EMU_IPR_MIDITRANSBUFE; - ipr_val |= EMU_IPR_MIDIRECVBUFE; - } else { - if (scp->port == EMU_A_MUDATA1) { - /* EXTERNAL MIDI (AudigyDrive) */ - inte_val = 0; - /* inte_val |= A_EMU_INTE_MIDITXENABLE1;*/ - inte_val |= EMU_INTE_MIDIRXENABLE; - ipr_val = EMU_IPR_MIDITRANSBUFE; - ipr_val |= EMU_IPR_MIDIRECVBUFE; - } else { - /* MIDI hw config port 2 */ - inte_val = 0; - /* inte_val |= A_EMU_INTE_MIDITXENABLE2;*/ - inte_val |= EMU_INTE_A_MIDIRXENABLE2; - ipr_val = EMU_IPR_A_MIDITRANSBUFE2; - ipr_val |= EMU_IPR_A_MIDIRECBUFE2; - } - } - - scp->ihandle = emu_intr_register(scp->card, inte_val, ipr_val, &emu_midi_card_intr, scp); - /* Init the interface. */ - scp->mpu = mpu401_init(&emu_mpu_class, scp, emu_midi_intr, &scp->mpu_intr); - if (scp->mpu == NULL) { - emu_intr_unregister(scp->card, scp->ihandle); - mtx_destroy(&scp->mtx); - return (ENOMEM); - } - /* - * XXX I don't know how to check for Live!Drive / AudigyDrive - * presence. Let's hope that IR enabling code will not harm if - * it is not present. - */ - if (scp->is_emu10k1) - emu_enable_ir(scp->card); - else { - if (scp->port == EMU_A_MUDATA1) - emu_enable_ir(scp->card); - } - - return (0); -} - - -static int -emu_midi_detach(device_t dev) -{ - struct emu_midi_softc *scp; - - scp = device_get_softc(dev); - mpu401_uninit(scp->mpu); - emu_intr_unregister(scp->card, scp->ihandle); - mtx_destroy(&scp->mtx); - return (0); -} - -static device_method_t emu_midi_methods[] = { - DEVMETHOD(device_probe, emu_midi_probe), - DEVMETHOD(device_attach, emu_midi_attach), - DEVMETHOD(device_detach, emu_midi_detach), - - DEVMETHOD_END -}; - -static driver_t emu_midi_driver = { - "midi", - emu_midi_methods, - sizeof(struct emu_midi_softc), -}; -DRIVER_MODULE(snd_emu10kx_midi, emu10kx, emu_midi_driver, emu_midi_devclass, 0, 0); -MODULE_DEPEND(snd_emu10kx_midi, snd_emu10kx, SND_EMU10KX_MINVER, SND_EMU10KX_PREFVER, SND_EMU10KX_MAXVER); -MODULE_DEPEND(snd_emu10kx_midi, sound, SOUND_MINVER, SOUND_PREFVER, SOUND_MAXVER); -MODULE_VERSION(snd_emu10kx_midi, SND_EMU10KX_PREFVER); diff --git a/sys/dev/sound/pcm/Makefile b/sys/dev/sound/pcm/Makefile index 08d37296b8..4e077b4bee 100644 --- a/sys/dev/sound/pcm/Makefile +++ b/sys/dev/sound/pcm/Makefile @@ -2,7 +2,6 @@ .PATH: ${.CURDIR}/../../../dev/sound .PATH: ${.CURDIR}/../../../dev/sound/pcm -.PATH: ${.CURDIR}/../../../dev/sound/midi KMOD= sound SRCS= device_if.h bus_if.h pci_if.h @@ -12,11 +11,8 @@ SRCS+= feeder.c feeder_rate.c feeder_volume.c SRCS+= feeder_chain.c feeder_eq.c feeder_format.c SRCS+= feeder_matrix.c feeder_mixer.c SRCS+= feeder_eq_gen.h feeder_rate_gen.h snd_fxdiv_gen.h -SRCS+= mpu_if.h mpufoi_if.h synth_if.h -SRCS+= mpu_if.c mpufoi_if.c synth_if.c SRCS+= ac97.c ac97_patch.c buffer.c channel.c clone.c dsp.c SRCS+= mixer.c sndstat.c sound.c unit.c vchan.c -SRCS+= midi.c mpu401.c sequencer.c .if !exists(@) feeder_eq_gen.h: @ diff --git a/sys/dev/sound/sound/Makefile b/sys/dev/sound/sound/Makefile index 08d37296b8..4e077b4bee 100644 --- a/sys/dev/sound/sound/Makefile +++ b/sys/dev/sound/sound/Makefile @@ -2,7 +2,6 @@ .PATH: ${.CURDIR}/../../../dev/sound .PATH: ${.CURDIR}/../../../dev/sound/pcm -.PATH: ${.CURDIR}/../../../dev/sound/midi KMOD= sound SRCS= device_if.h bus_if.h pci_if.h @@ -12,11 +11,8 @@ SRCS+= feeder.c feeder_rate.c feeder_volume.c SRCS+= feeder_chain.c feeder_eq.c feeder_format.c SRCS+= feeder_matrix.c feeder_mixer.c SRCS+= feeder_eq_gen.h feeder_rate_gen.h snd_fxdiv_gen.h -SRCS+= mpu_if.h mpufoi_if.h synth_if.h -SRCS+= mpu_if.c mpufoi_if.c synth_if.c SRCS+= ac97.c ac97_patch.c buffer.c channel.c clone.c dsp.c SRCS+= mixer.c sndstat.c sound.c unit.c vchan.c -SRCS+= midi.c mpu401.c sequencer.c .if !exists(@) feeder_eq_gen.h: @