summaryrefslogtreecommitdiffstats
path: root/sys/dev/sound/midi/midi.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/dev/sound/midi/midi.c')
-rw-r--r--sys/dev/sound/midi/midi.c1054
1 files changed, 0 insertions, 1054 deletions
diff --git a/sys/dev/sound/midi/midi.c b/sys/dev/sound/midi/midi.c
deleted file mode 100644
index a9d0184..0000000
--- a/sys/dev/sound/midi/midi.c
+++ /dev/null
@@ -1,1054 +0,0 @@
-/*
- * Main midi driver for FreeBSD. This file provides the main
- * entry points for probe/attach and all i/o demultiplexing, including
- * default routines for generic devices.
- *
- * (C) 1999 Seigo Tanimura
- *
- * Redistribution and use in source and binary forms, with or
- * without modification, are permitted provided that the following
- * conditions are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following
- * disclaimer in the documentation and/or other materials provided
- * with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS
- * IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
- * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
- * AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
- * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- *
- * For each card type a template "mididev_info" structure contains
- * all the relevant parameters, both for configuration and runtime.
- *
- * In this file we build tables of pointers to the descriptors for
- * the various supported cards. The generic probe routine scans
- * the table(s) looking for a matching entry, then invokes the
- * board-specific probe routine. If successful, a pointer to the
- * correct mididev_info is stored in mididev_last_probed, for subsequent
- * use in the attach routine. The generic attach routine copies
- * the template to a permanent descriptor (midi_info and
- * friends), initializes all generic parameters, and calls the
- * board-specific attach routine.
- *
- * On device calls, the generic routines do the checks on unit and
- * device parameters, then call the board-specific routines if
- * available, or try to perform the task using the default code.
- *
- * $FreeBSD$
- *
- */
-
-#include <dev/sound/midi/midi.h>
-
-static devclass_t midi_devclass;
-
-static d_open_t midiopen;
-static d_close_t midiclose;
-static d_ioctl_t midiioctl;
-static d_read_t midiread;
-static d_write_t midiwrite;
-static d_poll_t midipoll;
-
-/* These functions are local. */
-static d_open_t midistat_open;
-static d_close_t midistat_close;
-static d_read_t midistat_read;
-static int midi_initstatus(char *buf, int size);
-static int midi_readstatus(char *buf, int *ptr, struct uio *uio);
-
-#define CDEV_MAJOR MIDI_CDEV_MAJOR
-static struct cdevsw midi_cdevsw = {
- .d_version = D_VERSION,
- .d_flags = D_NEEDGIANT,
- .d_open = midiopen,
- .d_close = midiclose,
- .d_read = midiread,
- .d_write = midiwrite,
- .d_ioctl = midiioctl,
- .d_poll = midipoll,
- .d_name = "midi",
- .d_maj = CDEV_MAJOR,
-};
-
-/*
- * descriptors for active devices. also used as the public softc
- * of a device.
- */
-static TAILQ_HEAD(,_mididev_info) midi_info;
-static int nmidi, nsynth;
-/* Mutex to protect midi_info, nmidi and nsynth. */
-static struct mtx midiinfo_mtx;
-static int midiinfo_mtx_init;
-
-/* These make the buffer for /dev/midistat */
-static int midistatbusy;
-static char midistatbuf[4096];
-static int midistatptr;
-
-SYSCTL_NODE(_hw, OID_AUTO, midi, CTLFLAG_RD, 0, "Midi driver");
-
-int midi_debug;
-SYSCTL_INT(_hw_midi, OID_AUTO, debug, CTLFLAG_RW, &midi_debug, 0, "");
-
-midi_cmdtab cmdtab_midiioctl[] = {
- {SNDCTL_MIDI_PRETIME, "SNDCTL_MIDI_PRETIME"},
- {SNDCTL_MIDI_MPUMODE, "SNDCTL_MIDI_MPUMODE"},
- {SNDCTL_MIDI_MPUCMD, "SNDCTL_MIDI_MPUCMD"},
- {SNDCTL_SYNTH_INFO, "SNDCTL_SYNTH_INFO"},
- {SNDCTL_MIDI_INFO, "SNDCTL_MIDI_INFO"},
- {SNDCTL_SYNTH_MEMAVL, "SNDCTL_SYNTH_MEMAVL"},
- {SNDCTL_FM_LOAD_INSTR, "SNDCTL_FM_LOAD_INSTR"},
- {SNDCTL_FM_4OP_ENABLE, "SNDCTL_FM_4OP_ENABLE"},
- {MIOSPASSTHRU, "MIOSPASSTHRU"},
- {MIOGPASSTHRU, "MIOGPASSTHRU"},
- {AIONWRITE, "AIONWRITE"},
- {AIOGSIZE, "AIOGSIZE"},
- {AIOSSIZE, "AIOSSIZE"},
- {AIOGFMT, "AIOGFMT"},
- {AIOSFMT, "AIOSFMT"},
- {AIOGMIX, "AIOGMIX"},
- {AIOSMIX, "AIOSMIX"},
- {AIOSTOP, "AIOSTOP"},
- {AIOSYNC, "AIOSYNC"},
- {AIOGCAP, "AIOGCAP"},
- {-1, NULL},
-};
-
-/*
- * This is the generic init routine.
- * Must be called after device-specific init.
- */
-int
-midiinit(mididev_info *d, device_t dev)
-{
- int unit;
-
- /*
- * initialize standard parameters for the device. This can be
- * overridden by device-specific configurations but better do
- * here the generic things.
- */
-
- MIDI_DEBUG(printf("midiinit: unit %d.\n", d->unit));
-
- unit = d->unit;
- d->softc = device_get_softc(dev);
- d->dev = dev;
- d->magic = MAGIC(d->unit); /* debugging... */
- d->flags = 0;
- d->fflags = 0;
- d->midi_dbuf_in.unit_size = 1;
- d->midi_dbuf_out.unit_size = 1;
- d->midi_dbuf_passthru.unit_size = 1;
-
- mtx_unlock(&d->flagqueue_mtx);
-
- if (midi_devclass == NULL) {
- midi_devclass = device_get_devclass(dev);
- make_dev(&midi_cdevsw, MIDIMKMINOR(0, MIDI_DEV_STATUS),
- UID_ROOT, GID_WHEEL, 0444, "midistat");
- }
- make_dev(&midi_cdevsw, MIDIMKMINOR(unit, MIDI_DEV_MIDIN),
- UID_ROOT, GID_WHEEL, 0666, "midi%d", unit);
-
- return 0 ;
-}
-
-/*
- * a small utility function which, given a device number, returns
- * a pointer to the associated mididev_info struct, and sets the unit
- * number.
- */
-mididev_info *
-get_mididev_info(dev_t i_dev, int *unit)
-{
- int u;
-
- if (MIDIDEV(i_dev) != MIDI_DEV_MIDIN)
- return NULL;
- u = MIDIUNIT(i_dev);
- if (unit)
- *unit = u;
-
- return get_mididev_info_unit(u);
-}
-
-/*
- * a small utility function which, given a unit number, returns
- * a pointer to the associated mididev_info struct.
- */
-mididev_info *
-get_mididev_info_unit(int unit)
-{
- mididev_info *md;
-
- /* XXX */
- if (!midiinfo_mtx_init) {
- midiinfo_mtx_init = 1;
- mtx_init(&midiinfo_mtx, "midinf", NULL, MTX_DEF);
- TAILQ_INIT(&midi_info);
- }
-
- mtx_lock(&midiinfo_mtx);
- TAILQ_FOREACH(md, &midi_info, md_link) {
- if (md->unit == unit)
- break;
- }
- mtx_unlock(&midiinfo_mtx);
-
- return md;
-}
-
-/*
- * a small utility function which, given a unit number, returns
- * a pointer to the associated mididev_info struct with MDT_MIDI.
- */
-mididev_info *
-get_mididev_midi_unit(int unit)
-{
- mididev_info *md;
-
- /* XXX */
- if (!midiinfo_mtx_init) {
- midiinfo_mtx_init = 1;
- mtx_init(&midiinfo_mtx, "midinf", NULL, MTX_DEF);
- TAILQ_INIT(&midi_info);
- }
-
- mtx_lock(&midiinfo_mtx);
- TAILQ_FOREACH(md, &midi_info, md_link) {
- if (md->midiunit == unit)
- break;
- }
- mtx_unlock(&midiinfo_mtx);
-
- return md;
-}
-
-/*
- * a small utility function which, given a unit number, returns
- * a pointer to the associated mididev_info struct with MDT_SYNTH.
- */
-mididev_info *
-get_mididev_synth_unit(int unit)
-{
- mididev_info *md;
-
- /* XXX */
- if (!midiinfo_mtx_init) {
- midiinfo_mtx_init = 1;
- mtx_init(&midiinfo_mtx, "midinf", NULL, MTX_DEF);
- TAILQ_INIT(&midi_info);
- }
-
- mtx_lock(&midiinfo_mtx);
- TAILQ_FOREACH(md, &midi_info, md_link) {
- if (md->synthunit == unit)
- break;
- }
- mtx_unlock(&midiinfo_mtx);
-
- return md;
-}
-
-/* Create a new midi device info structure. */
-/* TODO: lock md, then exit. */
-mididev_info *
-create_mididev_info_unit(int type, mididev_info *mdinf, synthdev_info *syninf)
-{
- int unit;
- mididev_info *md, *mdnew;
-
- /* XXX */
- if (!midiinfo_mtx_init) {
- midiinfo_mtx_init = 1;
- mtx_init(&midiinfo_mtx, "midinf", NULL, MTX_DEF);
- TAILQ_INIT(&midi_info);
- }
-
- /* As malloc(9) might block, allocate mididev_info now. */
- mdnew = malloc(sizeof(mididev_info), M_DEVBUF, M_WAITOK | M_ZERO);
- if (mdnew == NULL)
- return NULL;
- bcopy(mdinf, mdnew, sizeof(mididev_info));
- bcopy(syninf, &mdnew->synth, sizeof(synthdev_info));
- midibuf_init(&mdnew->midi_dbuf_in);
- midibuf_init(&mdnew->midi_dbuf_out);
- midibuf_init(&mdnew->midi_dbuf_passthru);
- mtx_init(&mdnew->flagqueue_mtx, "midflq", NULL, MTX_DEF);
- mtx_init(&mdnew->synth.vc_mtx, "synsvc", NULL, MTX_DEF);
- mtx_init(&mdnew->synth.status_mtx, "synsst", NULL, MTX_DEF);
-
- mtx_lock(&midiinfo_mtx);
-
- switch (type) {
- case MDT_MIDI:
- mdnew->midiunit = nmidi;
- mdnew->synthunit = nmidi;
- nmidi++;
- break;
- case MDT_SYNTH:
- mdnew->midiunit = -1;
- mdnew->synthunit = nsynth;
- nsynth++;
- break;
- default:
- mtx_unlock(&midiinfo_mtx);
- midibuf_destroy(&mdnew->midi_dbuf_in);
- midibuf_destroy(&mdnew->midi_dbuf_out);
- midibuf_destroy(&mdnew->midi_dbuf_passthru);
- mtx_destroy(&mdnew->flagqueue_mtx);
- mtx_destroy(&mdnew->synth.vc_mtx);
- mtx_destroy(&mdnew->synth.status_mtx);
- free(mdnew, M_DEVBUF);
- panic("unsupported device type");
- return NULL;
- }
- mdnew->mdtype = type;
-
- for (unit = 0 ; ; unit++) {
- TAILQ_FOREACH(md, &midi_info, md_link) {
- if (md->unit == unit)
- break;
- }
- if (md == NULL)
- break;
- }
-
- mdnew->unit = unit;
- mtx_lock(&mdnew->flagqueue_mtx);
- TAILQ_INSERT_TAIL(&midi_info, mdnew, md_link);
-
- mtx_unlock(&midiinfo_mtx);
-
- return mdnew;
-}
-
-/* Return the number of configured devices. */
-int
-mididev_info_number(void)
-{
- return nmidi + nsynth;
-}
-
-/* Return the number of configured midi devices. */
-int
-mididev_midi_number(void)
-{
- return nmidi;
-}
-
-/* Return the number of configured synth devices. */
-int
-mididev_synth_number(void)
-{
- return nsynth;
-}
-
-/*
- * here are the switches for the main functions. The switches do
- * all necessary checks on the device number to make sure
- * that the device is configured. They also provide some default
- * functionalities so that device-specific drivers have to deal
- * only with special cases.
- */
-
-static int
-midiopen(dev_t i_dev, int flags, int mode, struct thread *td)
-{
- int ret;
-
- switch (MIDIDEV(i_dev)) {
- case MIDI_DEV_MIDIN:
- ret = midi_open(i_dev, flags, mode, td);
- break;
- case MIDI_DEV_STATUS:
- ret = midistat_open(i_dev, flags, mode, td);
- break;
- default:
- ret = ENXIO;
- break;
- }
-
- return (ret);
-}
-
-static int
-midiclose(dev_t i_dev, int flags, int mode, struct thread *td)
-{
- int ret;
-
- switch (MIDIDEV(i_dev)) {
- case MIDI_DEV_MIDIN:
- ret = midi_close(i_dev, flags, mode, td);
- break;
- case MIDI_DEV_STATUS:
- ret = midistat_close(i_dev, flags, mode, td);
- break;
- default:
- ret = ENXIO;
- break;
- }
-
- return (ret);
-}
-
-static int
-midiread(dev_t i_dev, struct uio * buf, int flag)
-{
- int ret;
-
- switch (MIDIDEV(i_dev)) {
- case MIDI_DEV_MIDIN:
- ret = midi_read(i_dev, buf, flag);
- break;
- case MIDI_DEV_STATUS:
- ret = midistat_read(i_dev, buf, flag);
- break;
- default:
- ret = ENXIO;
- break;
- }
-
- return (ret);
-}
-
-static int
-midiwrite(dev_t i_dev, struct uio * buf, int flag)
-{
- int ret;
-
- switch (MIDIDEV(i_dev)) {
- case MIDI_DEV_MIDIN:
- ret = midi_write(i_dev, buf, flag);
- break;
- default:
- ret = ENXIO;
- break;
- }
-
- return (ret);
-}
-
-static int
-midiioctl(dev_t i_dev, u_long cmd, caddr_t arg, int mode, struct thread *td)
-{
- int ret;
-
- switch (MIDIDEV(i_dev)) {
- case MIDI_DEV_MIDIN:
- ret = midi_ioctl(i_dev, cmd, arg, mode, td);
- break;
- default:
- ret = ENXIO;
- break;
- }
-
- return (ret);
-}
-
-static int
-midipoll(dev_t i_dev, int events, struct thread *td)
-{
- int ret;
-
- switch (MIDIDEV(i_dev)) {
- case MIDI_DEV_MIDIN:
- ret = midi_poll(i_dev, events, td);
- break;
- default:
- ret = ENXIO;
- break;
- }
-
- return (ret);
-}
-
-/*
- * Followings are the generic methods in midi drivers.
- */
-
-int
-midi_open(dev_t i_dev, int flags, int mode, struct thread *td)
-{
- int dev, unit, ret;
- mididev_info *d;
-
- dev = minor(i_dev);
- d = get_mididev_info(i_dev, &unit);
-
- MIDI_DEBUG(printf("midi_open: unit %d, flags 0x%x.\n", unit, flags));
-
- if (d == NULL)
- return (ENXIO);
-
- /* Mark this device busy. */
- mtx_lock(&d->flagqueue_mtx);
- device_busy(d->dev);
- if ((d->flags & MIDI_F_BUSY) != 0) {
- mtx_unlock(&d->flagqueue_mtx);
- printf("midi_open: unit %d is busy.\n", unit);
- return (EBUSY);
- }
- d->fflags = flags;
- d->flags |= MIDI_F_BUSY;
- d->flags &= ~(MIDI_F_READING | MIDI_F_WRITING);
- if ((d->fflags & O_NONBLOCK) != 0)
- d->flags |= MIDI_F_NBIO;
-
- /* Init the queue. */
- if ((flags & FREAD) != 0)
- midibuf_clear(&d->midi_dbuf_in);
- if ((flags & FWRITE) != 0) {
- midibuf_clear(&d->midi_dbuf_out);
- midibuf_clear(&d->midi_dbuf_passthru);
- }
-
- mtx_unlock(&d->flagqueue_mtx);
-
- if (d->open == NULL)
- ret = 0;
- else
- ret = d->open(i_dev, flags, mode, td);
-
- mtx_lock(&d->flagqueue_mtx);
-
- /* Begin recording if nonblocking. */
- if ((d->flags & (MIDI_F_READING | MIDI_F_NBIO)) == MIDI_F_NBIO && (d->fflags & FREAD) != 0)
- d->callback(d, MIDI_CB_START | MIDI_CB_RD);
-
- mtx_unlock(&d->flagqueue_mtx);
-
- MIDI_DEBUG(printf("midi_open: opened.\n"));
-
- return (ret);
-}
-
-int
-midi_close(dev_t i_dev, int flags, int mode, struct thread *td)
-{
- int dev, unit, ret;
- mididev_info *d;
-
- dev = minor(i_dev);
- d = get_mididev_info(i_dev, &unit);
-
- MIDI_DEBUG(printf("midi_close: unit %d.\n", unit));
-
- if (d == NULL)
- return (ENXIO);
-
- mtx_lock(&d->flagqueue_mtx);
-
- /* Stop recording and playing. */
- if ((d->flags & MIDI_F_READING) != 0)
- d->callback(d, MIDI_CB_ABORT | MIDI_CB_RD);
- if ((d->flags & MIDI_F_WRITING) != 0)
- d->callback(d, MIDI_CB_ABORT | MIDI_CB_WR);
-
- /* Clear the queues. */
- if ((d->fflags & FREAD) != 0)
- midibuf_clear(&d->midi_dbuf_in);
- if ((d->fflags & FWRITE) != 0) {
- midibuf_clear(&d->midi_dbuf_out);
- midibuf_clear(&d->midi_dbuf_passthru);
- }
-
- /* Stop playing and unmark this device busy. */
- d->flags &= ~MIDI_F_BUSY;
- d->fflags = 0;
-
- device_unbusy(d->dev);
-
- mtx_unlock(&d->flagqueue_mtx);
-
- if (d->close == NULL)
- ret = 0;
- else
- ret = d->close(i_dev, flags, mode, td);
-
- MIDI_DEBUG(printf("midi_close: closed.\n"));
-
- return (ret);
-}
-
-int
-midi_read(dev_t i_dev, struct uio * buf, int flag)
-{
- int dev, unit, len, lenr, ret;
- mididev_info *d ;
- u_char *uiobuf;
-
- dev = minor(i_dev);
-
- d = get_mididev_info(i_dev, &unit);
- MIDI_DEBUG(printf("midi_read: unit %d, resid %d.\n", unit, buf->uio_resid));
-
- if (d == NULL)
- return (ENXIO);
-
- ret = 0;
-
- len = buf->uio_resid;
- lenr = 0;
-
- uiobuf = (u_char *)malloc(len, M_DEVBUF, M_WAITOK | M_ZERO);
- if (uiobuf == NULL)
- return (ENOMEM);
-
- mtx_lock(&d->flagqueue_mtx);
-
- /* Begin recording. */
- d->callback(d, MIDI_CB_START | MIDI_CB_RD);
-
- /* Have we got the data to read? */
- if ((d->flags & MIDI_F_NBIO) != 0 && d->midi_dbuf_in.rl == 0)
- ret = EAGAIN;
- else {
- if ((d->flags & MIDI_F_NBIO) != 0 && len > d->midi_dbuf_in.rl)
- len = d->midi_dbuf_in.rl;
- ret = midibuf_seqread(&d->midi_dbuf_in, uiobuf, len, &lenr,
- d->callback, d, MIDI_CB_START | MIDI_CB_RD,
- &d->flagqueue_mtx);
- }
-
- mtx_unlock(&d->flagqueue_mtx);
-
- if (lenr > 0)
- ret = uiomove(uiobuf, lenr, buf);
-
- free(uiobuf, M_DEVBUF);
-
- MIDI_DEBUG(printf("midi_read: ret %d, resid %d.\n", ret, buf->uio_resid));
-
- return (ret);
-}
-
-int
-midi_write(dev_t i_dev, struct uio * buf, int flag)
-{
- int dev, unit, len, len2, lenw, ret;
- mididev_info *d;
- u_char *uiobuf;
-
- dev = minor(i_dev);
- d = get_mididev_info(i_dev, &unit);
-
- MIDI_DEBUG(printf("midi_write: unit %d.\n", unit));
-
- if (d == NULL)
- return (ENXIO);
-
- ret = 0;
-
- len = buf->uio_resid;
- lenw = 0;
-
- uiobuf = (u_char *)malloc(len, M_DEVBUF, M_WAITOK | M_ZERO);
- if (uiobuf == NULL)
- return (ENOMEM);
-
- ret = uiomove(uiobuf, len, buf);
- if (ret != 0) {
- free(uiobuf, M_DEVBUF);
- return (ret);
- }
-
- mtx_lock(&d->flagqueue_mtx);
-
- /* Have we got the data to write? */
- if ((d->flags & MIDI_F_NBIO) != 0 && d->midi_dbuf_out.fl == 0) {
- /* Begin playing. */
- d->callback(d, MIDI_CB_START | MIDI_CB_WR);
- ret = EAGAIN;
- } else {
- len2 = len;
- if ((d->flags & MIDI_F_NBIO) != 0 && len2 > d->midi_dbuf_out.fl)
- len2 = d->midi_dbuf_out.fl;
- ret = midibuf_seqwrite(&d->midi_dbuf_out, uiobuf, len2, &lenw,
- d->callback, d, MIDI_CB_START | MIDI_CB_WR,
- &d->flagqueue_mtx);
- }
-
- mtx_unlock(&d->flagqueue_mtx);
-
- free(uiobuf, M_DEVBUF);
- buf->uio_resid = len - lenw;
-
- return (ret);
-}
-
-/*
- * generic midi ioctl. Functions of the default driver can be
- * overridden by the device-specific ioctl call.
- * If a device-specific call returns ENOSYS (Function not implemented),
- * the default driver is called. Otherwise, the returned value
- * is passed up.
- *
- * The default handler, for many parameters, sets the value in the
- * descriptor, sets MIDI_F_INIT, and calls the callback function with
- * reason INIT. If successful, the callback returns 1 and the caller
- * can update the parameter.
- */
-
-int
-midi_ioctl(dev_t i_dev, u_long cmd, caddr_t arg, int mode, struct thread *td)
-{
- int ret = ENOSYS, dev, unit;
- mididev_info *d;
- struct snd_size *sndsize;
- snd_sync_parm *sp;
-
- dev = minor(i_dev);
- d = get_mididev_info(i_dev, &unit);
-
- if (d == NULL)
- return (ENXIO);
-
- if (d->ioctl)
- ret = d->ioctl(i_dev, cmd, arg, mode, td);
- if (ret != ENOSYS)
- return ret;
-
- /*
- * pass control to the default ioctl handler. Set ret to 0 now.
- */
- ret = 0;
-
- MIDI_DEBUG(printf("midi_ioctl: unit %d, cmd %s.\n", unit, midi_cmdname(cmd, cmdtab_midiioctl)));
-
- /*
- * all routines are called with int. blocked. Make sure that
- * ints are re-enabled when calling slow or blocking functions!
- */
- switch(cmd) {
-
- /*
- * we start with the new ioctl interface.
- */
- case AIONWRITE: /* how many bytes can write ? */
- mtx_lock(&d->flagqueue_mtx);
- *(int *)arg = d->midi_dbuf_out.fl;
- mtx_unlock(&d->flagqueue_mtx);
- MIDI_DEBUG(printf("midi_ioctl: fl %d.\n", *(int *)arg));
- break;
-
- case AIOSSIZE: /* set the current blocksize */
- sndsize = (struct snd_size *)arg;
- MIDI_DEBUG(printf("midi_ioctl: play %d, rec %d.\n", sndsize->play_size, sndsize->rec_size));
- mtx_lock(&d->flagqueue_mtx);
- if (sndsize->play_size <= d->midi_dbuf_out.unit_size && sndsize->rec_size <= d->midi_dbuf_in.unit_size) {
- d->midi_dbuf_out.blocksize = d->midi_dbuf_out.unit_size;
- d->midi_dbuf_in.blocksize = d->midi_dbuf_in.unit_size;
- sndsize->play_size = d->midi_dbuf_out.blocksize;
- sndsize->rec_size = d->midi_dbuf_in.blocksize;
- d->flags &= ~MIDI_F_HAS_SIZE;
- mtx_unlock(&d->flagqueue_mtx);
- }
- else {
- if (sndsize->play_size > d->midi_dbuf_out.bufsize / 4)
- sndsize->play_size = d->midi_dbuf_out.bufsize / 4;
- if (sndsize->rec_size > d->midi_dbuf_in.bufsize / 4)
- sndsize->rec_size = d->midi_dbuf_in.bufsize / 4;
- /* Round up the size to the multiple of EV_SZ. */
- d->midi_dbuf_out.blocksize =
- ((sndsize->play_size + d->midi_dbuf_out.unit_size - 1)
- / d->midi_dbuf_out.unit_size) * d->midi_dbuf_out.unit_size;
- d->midi_dbuf_in.blocksize =
- ((sndsize->rec_size + d->midi_dbuf_in.unit_size - 1)
- / d->midi_dbuf_in.unit_size) * d->midi_dbuf_in.unit_size;
- sndsize->play_size = d->midi_dbuf_out.blocksize;
- sndsize->rec_size = d->midi_dbuf_in.blocksize;
- d->flags |= MIDI_F_HAS_SIZE;
- mtx_unlock(&d->flagqueue_mtx);
- }
-
- ret = 0;
- break;
-
- case AIOGSIZE: /* get the current blocksize */
- sndsize = (struct snd_size *)arg;
- mtx_lock(&d->flagqueue_mtx);
- sndsize->play_size = d->midi_dbuf_out.blocksize;
- sndsize->rec_size = d->midi_dbuf_in.blocksize;
- mtx_unlock(&d->flagqueue_mtx);
- MIDI_DEBUG(printf("midi_ioctl: play %d, rec %d.\n", sndsize->play_size, sndsize->rec_size));
-
- ret = 0;
- break;
-
- case AIOSTOP:
- mtx_lock(&d->flagqueue_mtx);
- if (*(int *)arg == AIOSYNC_PLAY) /* play */
- *(int *)arg = d->callback(d, MIDI_CB_STOP | MIDI_CB_WR);
- else if (*(int *)arg == AIOSYNC_CAPTURE)
- *(int *)arg = d->callback(d, MIDI_CB_STOP | MIDI_CB_RD);
- else {
- MIDI_DEBUG(printf("midi_ioctl: bad channel 0x%x.\n", *(int *)arg));
- *(int *)arg = 0 ;
- }
- mtx_unlock(&d->flagqueue_mtx);
- break ;
-
- case AIOSYNC:
- sp = (snd_sync_parm *)arg;
- MIDI_DEBUG(printf("midi_ioctl: unimplemented, chan 0x%03lx pos %lu.\n",
- sp->chan,
- sp->pos));
- break;
- /*
- * here follow the standard ioctls (filio.h etc.)
- */
- case FIONREAD: /* get # bytes to read */
- mtx_lock(&d->flagqueue_mtx);
- *(int *)arg = d->midi_dbuf_in.rl;
- mtx_unlock(&d->flagqueue_mtx);
- MIDI_DEBUG(printf("midi_ioctl: rl %d.\n", *(int *)arg));
- break;
-
- case FIOASYNC: /*set/clear async i/o */
- MIDI_DEBUG(printf("FIOASYNC\n"));
- break;
-
- case FIONBIO: /* set/clear non-blocking i/o */
- mtx_lock(&d->flagqueue_mtx);
- if (*(int *)arg == 0)
- d->flags &= ~MIDI_F_NBIO ;
- else
- d->flags |= MIDI_F_NBIO ;
- mtx_unlock(&d->flagqueue_mtx);
- MIDI_DEBUG(printf("midi_ioctl: arg %d.\n", *(int *)arg));
- break ;
-
- case MIOSPASSTHRU: /* set/clear passthru */
- mtx_lock(&d->flagqueue_mtx);
- if (*(int *)arg == 0)
- d->flags &= ~MIDI_F_PASSTHRU ;
- else
- d->flags |= MIDI_F_PASSTHRU ;
-
- /* Init the queue. */
- midibuf_clear(&d->midi_dbuf_passthru);
-
- mtx_unlock(&d->flagqueue_mtx);
- MIDI_DEBUG(printf("midi_ioctl: passthru %d.\n", *(int *)arg));
-
- /* FALLTHROUGH */
- case MIOGPASSTHRU: /* get passthru */
- mtx_lock(&d->flagqueue_mtx);
- if ((d->flags & MIDI_F_PASSTHRU) != 0)
- *(int *)arg = 1;
- else
- *(int *)arg = 0;
- mtx_unlock(&d->flagqueue_mtx);
- MIDI_DEBUG(printf("midi_ioctl: passthru %d.\n", *(int *)arg));
- break;
-
- default:
- MIDI_DEBUG(printf("midi_ioctl: default ioctl midi%d subdev %d fn 0x%08lx fail\n",
- unit, dev & 0xf, cmd));
- ret = EINVAL;
- break ;
- }
- return ret ;
-}
-
-int
-midi_poll(dev_t i_dev, int events, struct thread *td)
-{
- int unit, dev, ret, lim;
- mididev_info *d;
-
- dev = minor(i_dev);
- d = get_mididev_info(i_dev, &unit);
-
- MIDI_DEBUG(printf("midi_poll: unit %d.\n", unit));
-
- if (d == NULL)
- return (ENXIO);
-
- ret = 0;
-
- mtx_lock(&d->flagqueue_mtx);
-
- /* Look up the apropriate queue and select it. */
- if ((events & (POLLOUT | POLLWRNORM)) != 0) {
- /* Start playing. */
- d->callback(d, MIDI_CB_START | MIDI_CB_WR);
-
- /* Find out the boundary. */
- if ((d->flags & MIDI_F_HAS_SIZE) != 0)
- lim = d->midi_dbuf_out.blocksize;
- else
- lim = d->midi_dbuf_out.unit_size;
- if (d->midi_dbuf_out.fl < lim)
- /* No enough space, record select. */
- selrecord(td, &d->midi_dbuf_out.sel);
- else
- /* We can write now. */
- ret |= events & (POLLOUT | POLLWRNORM);
- }
- if ((events & (POLLIN | POLLRDNORM)) != 0) {
- /* Start recording. */
- d->callback(d, MIDI_CB_START | MIDI_CB_RD);
-
- /* Find out the boundary. */
- if ((d->flags & MIDI_F_HAS_SIZE) != 0)
- lim = d->midi_dbuf_in.blocksize;
- else
- lim = d->midi_dbuf_in.unit_size;
- if (d->midi_dbuf_in.rl < lim)
- /* No data ready, record select. */
- selrecord(td, &d->midi_dbuf_in.sel);
- else
- /* We can write now. */
- ret |= events & (POLLIN | POLLRDNORM);
- }
-
- mtx_unlock(&d->flagqueue_mtx);
-
- return (ret);
-}
-
-void
-midi_intr(mididev_info *d)
-{
- if (d->intr != NULL)
- d->intr(d->intrarg, d);
-}
-
-/* Flush the output queue. */
-#define MIDI_SYNC_TIMEOUT 1
-int
-midi_sync(mididev_info *d)
-{
- int i, rl;
-
- mtx_assert(&d->flagqueue_mtx, MA_OWNED);
-
- MIDI_DEBUG(printf("midi_sync: unit %d.\n", d->unit));
-
- while (d->midi_dbuf_out.rl > 0) {
- if ((d->flags & MIDI_F_WRITING) == 0)
- d->callback(d, MIDI_CB_START | MIDI_CB_WR);
- rl = d->midi_dbuf_out.rl;
- i = cv_timedwait_sig(&d->midi_dbuf_out.cv_out,
- &d->flagqueue_mtx,
- (d->midi_dbuf_out.bufsize * 10 * hz / 38400)
- + MIDI_SYNC_TIMEOUT * hz);
- if (i == EINTR || i == ERESTART) {
- if (i == EINTR)
- d->callback(d, MIDI_CB_STOP | MIDI_CB_WR);
- return (i);
- }
- if (i == EWOULDBLOCK && rl == d->midi_dbuf_out.rl) {
- /* A queue seems to be stuck up. Give up and clear the queue. */
- d->callback(d, MIDI_CB_STOP | MIDI_CB_WR);
- midibuf_clear(&d->midi_dbuf_out);
- return (0);
- }
- }
-
- return 0;
-}
-
-/*
- * These handle the status message of the midi drivers.
- */
-
-int
-midistat_open(dev_t i_dev, int flags, int mode, struct thread *td)
-{
- if (midistatbusy)
- return (EBUSY);
-
- bzero(midistatbuf, sizeof(midistatbuf));
- midistatptr = 0;
- if (midi_initstatus(midistatbuf, sizeof(midistatbuf) - 1))
- return (ENOMEM);
-
- midistatbusy = 1;
-
- return (0);
-}
-
-int
-midistat_close(dev_t i_dev, int flags, int mode, struct thread *td)
-{
- midistatbusy = 0;
-
- return (0);
-}
-
-int
-midistat_read(dev_t i_dev, struct uio * buf, int flag)
-{
- return midi_readstatus(midistatbuf, &midistatptr, buf);
-}
-
-/*
- * finally, some "libraries"
- */
-
-/* Inits the buffer for /dev/midistat. */
-static int
-midi_initstatus(char *buf, int size)
-{
- int i, p;
- device_t dev;
- mididev_info *md;
-
- p = 0;
- p += snprintf(buf, size, "FreeBSD Midi Driver (newmidi) %s %s\nInstalled devices:\n", __DATE__, __TIME__);
- for (i = 0 ; i < mididev_info_number() ; i++) {
- md = get_mididev_info_unit(i);
- if (!MIDICONFED(md))
- continue;
- dev = devclass_get_device(midi_devclass, i);
- if (p < size)
- p += snprintf(&buf[p], size - p, "midi%d: <%s> %s\n", i, device_get_desc(dev), md->midistat);
- else
- return (1);
- }
-
- return (0);
-}
-
-/* Reads the status message. */
-static int
-midi_readstatus(char *buf, int *ptr, struct uio *uio)
-{
- int len;
-
- len = min(uio->uio_resid, strlen(&buf[*ptr]));
- if (len > 0) {
- uiomove(&buf[*ptr], len, uio);
- *ptr += len;
- }
-
- return (0);
-}
-
-char
-*midi_cmdname(int cmd, midi_cmdtab *tab)
-{
- while (tab->name != NULL) {
- if (cmd == tab->cmd)
- return (tab->name);
- tab++;
- }
-
- return ("unknown");
-}
OpenPOWER on IntegriCloud