- Provide toggles to show debug messages. Set new sysctl variables

hw.midi.debug and hw.midi.seq.debug to 1 to enable debug log.

- Make debug messages human-frendly.

- Implement /dev/music.

- Add a timer engine required by /dev/music.

- Fix nonblocking I/O.

- Fix the numbering of midi and synth devices.
This commit is contained in:
Seigo Tanimura 2002-01-04 01:13:49 +00:00
parent 233beff278
commit 995231304d
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=88869
13 changed files with 884 additions and 376 deletions

View file

@ -503,6 +503,7 @@ dev/sound/midi/midi.c optional midi
dev/sound/midi/midibuf.c optional midi
dev/sound/midi/midisynth.c optional midi
dev/sound/midi/sequencer.c optional seq midi
dev/sound/midi/timer.c optional seq midi
dev/sound/pci/als4000.c optional pcm pci
dev/sound/pci/cmi.c optional pcm pci
dev/sound/pci/cs4281.c optional pcm pci

View file

@ -548,7 +548,7 @@ emu_probe(device_t dev)
device_set_desc(dev, "EMU8000 Wavetable Synth");
bzero(scp, sizeof(*scp));
DEB(printf("emu%d: probing.\n", unit));
MIDI_DEBUG(printf("emu%d: probing.\n", unit));
if (emu_allocres(scp, dev)) {
emu_releaseres(scp, dev);
@ -565,7 +565,7 @@ emu_probe(device_t dev)
return (ENXIO);
}
DEB(printf("emu%d: probed.\n", unit));
MIDI_DEBUG(printf("emu%d: probed.\n", unit));
return (0);
}
@ -582,7 +582,7 @@ emu_attach(device_t dev)
unit = device_get_unit(dev);
scp = device_get_softc(dev);
DEB(printf("emu%d: attaching.\n", unit));
MIDI_DEBUG(printf("emu%d: attaching.\n", unit));
if (emu_allocres(scp, dev)) {
emu_releaseres(scp, dev);
@ -731,7 +731,7 @@ emu_attach(device_t dev)
midiinit(devinfo, dev);
DEB(printf("emu%d: attached.\n", unit));
MIDI_DEBUG(printf("emu%d: attached.\n", unit));
return (0);
}
@ -765,11 +765,11 @@ emu_ioctl(dev_t i_dev, u_long cmd, caddr_t arg, int mode, struct thread *td)
unit = MIDIUNIT(i_dev);
DEB(printf("emu%d: ioctlling, cmd 0x%x.\n", unit, (int)cmd));
MIDI_DEBUG(printf("emu_ioctl: unit %d, cmd %s.\n", unit, midi_cmdname(cmd, cmdtab_midiioctl)));
devinfo = get_mididev_info(i_dev, &unit);
if (devinfo == NULL) {
DEB(printf("emu_ioctl: unit %d is not configured.\n", unit));
MIDI_DEBUG(printf("emu_ioctl: unit %d is not configured.\n", unit));
return (ENXIO);
}
scp = devinfo->softc;
@ -793,7 +793,8 @@ emu_ioctl(dev_t i_dev, u_long cmd, caddr_t arg, int mode, struct thread *td)
return (0);
break;
case SNDCTL_SYNTH_MEMAVL:
return 0x7fffffff;
*(int *)arg = 0x7fffffff;
return (0);
break;
default:
return (ENOSYS);
@ -828,7 +829,7 @@ emu_readraw(mididev_info *md, u_char *buf, int len, int *lenr, int nonblock)
unit = md->unit;
scp = md->softc;
if ((md->fflags & FREAD) == 0) {
DEB(printf("emu_readraw: unit %d is not for reading.\n", unit));
MIDI_DEBUG(printf("emu_readraw: unit %d is not for reading.\n", unit));
return (EIO);
}
@ -852,7 +853,7 @@ emu_writeraw(mididev_info *md, u_char *buf, int len, int *lenw, int nonblock)
unit = md->unit;
scp = md->softc;
if ((md->fflags & FWRITE) == 0) {
DEB(printf("emu_writeraw: unit %d is not for writing.\n", unit));
MIDI_DEBUG(printf("emu_writeraw: unit %d is not for writing.\n", unit));
return (EIO);
}

View file

@ -224,7 +224,7 @@ gusmidi_open(dev_t i_dev, int flags, int mode, struct thread *td)
devinfo = get_mididev_info(i_dev, &unit);
if (devinfo == NULL) {
DEB(printf("gusmidi_open: unit %d is not configured.\n", unit));
MIDI_DEBUG(printf("gusmidi_open: unit %d is not configured.\n", unit));
return (ENXIO);
}
scp = devinfo->softc;
@ -252,9 +252,11 @@ gusmidi_ioctl(dev_t i_dev, u_long cmd, caddr_t arg, int mode, struct thread *td)
unit = MIDIUNIT(i_dev);
MIDI_DEBUG(printf("gusmidi_ioctl: unit %d, cmd %s.\n", unit, midi_cmdname(cmd, cmdtab_midiioctl)));
devinfo = get_mididev_info(i_dev, &unit);
if (devinfo == NULL) {
DEB(printf("gusmidi_ioctl: unit %d is not configured.\n", unit));
MIDI_DEBUG(printf("gusmidi_ioctl: unit %d is not configured.\n", unit));
return (ENXIO);
}
scp = devinfo->softc;
@ -353,7 +355,7 @@ gusmidi_callback(void *di, int reason)
mtx_assert(&d->flagqueue_mtx, MA_OWNED);
if (d == NULL) {
DEB(printf("gusmidi_callback: device not configured.\n"));
MIDI_DEBUG(printf("gusmidi_callback: device not configured.\n"));
return (ENXIO);
}

View file

@ -249,7 +249,7 @@ mpu_probe2(device_t dev)
if (scp->io == NULL)
return (ENXIO);
DEB(printf("mpu%d: probing.\n", unit));
MIDI_DEBUG(printf("mpu%d: probing.\n", unit));
/* Reset the interface. */
if (mpu_resetmode(scp) != 0 || mpu_waitack(scp) != 0) {
@ -320,7 +320,7 @@ mpu_probe2(device_t dev)
/* We have found the irq. */
scp->irq_val = ffs(~irqp0 & irqp1) - 1;
DEB(printf("mpu%d: probed.\n", unit));
MIDI_DEBUG(printf("mpu%d: probed.\n", unit));
return (0);
}
@ -356,7 +356,7 @@ mpu_attach(device_t dev)
scp = device_get_softc(dev);
DEB(printf("mpu: attaching.\n"));
MIDI_DEBUG(printf("mpu: attaching.\n"));
mtx_init(&scp->mtx, "mpumid", MTX_DEF);
@ -387,7 +387,7 @@ mpu_attach(device_t dev)
bus_setup_intr(dev, scp->irq, INTR_TYPE_AV, mpu_intr, scp,
&scp->ih);
DEB(printf("mpu: attached.\n"));
MIDI_DEBUG(printf("mpu: attached.\n"));
return (0);
}
@ -417,9 +417,11 @@ mpu_ioctl(dev_t i_dev, u_long cmd, caddr_t arg, int mode, struct thread *td)
unit = MIDIUNIT(i_dev);
MIDI_DEBUG(printf("mpu_ioctl: unit %d, cmd %s.\n", unit, midi_cmdname(cmd, cmdtab_midiioctl)));
devinfo = get_mididev_info(i_dev, &unit);
if (devinfo == NULL) {
DEB(printf("mpu_ioctl: unit %d is not configured.\n", unit));
MIDI_DEBUG(printf("mpu_ioctl: unit %d is not configured.\n", unit));
return (ENXIO);
}
scp = devinfo->softc;
@ -497,7 +499,7 @@ mpu_callback(void *di, int reason)
mtx_assert(&d->flagqueue_mtx, MA_OWNED);
if (d == NULL) {
DEB(printf("mpu_callback: device not configured.\n"));
MIDI_DEBUG(printf("mpu_callback: device not configured.\n"));
return (ENXIO);
}

View file

@ -548,13 +548,13 @@ opl_probe(device_t dev)
device_set_desc(dev, opl_op_desc.name);
bzero(scp, sizeof(*scp));
DEB(printf("opl%d: probing.\n", unit));
MIDI_DEBUG(printf("opl%d: probing.\n", unit));
scp->io_rid = 0;
scp->io = bus_alloc_resource(dev, SYS_RES_IOPORT, &scp->io_rid, 0, ~0, 4, RF_ACTIVE);
if (opl_allocres(scp, dev)) {
/* We try the defaults in opl_defaultiobase. */
DEB(printf("opl%d: port is omitted, trying the defaults.\n", unit));
MIDI_DEBUG(printf("opl%d: port is omitted, trying the defaults.\n", unit));
for (i = 0 ; i < sizeof(opl_defaultiobase) / sizeof(*opl_defaultiobase) ; i++) {
scp->io_rid = 0;
scp->io = bus_alloc_resource(dev, SYS_RES_IOPORT, &scp->io_rid, opl_defaultiobase[i], opl_defaultiobase[i] + 1, 4, RF_ACTIVE);
@ -574,7 +574,7 @@ opl_probe(device_t dev)
/* We now have some kind of OPL. */
DEB(printf("opl%d: probed.\n", unit));
MIDI_DEBUG(printf("opl%d: probed.\n", unit));
return (0);
}
@ -645,7 +645,7 @@ opl_attach(device_t dev)
scp = device_get_softc(dev);
DEB(printf("opl: attaching.\n"));
MIDI_DEBUG(printf("opl: attaching.\n"));
/* Fill the softc for this unit. */
scp->dev = dev;
@ -751,8 +751,8 @@ opl_attach(device_t dev)
midiinit(devinfo, dev);
DEB(printf("opl: attached.\n"));
DEB(printf("opl: the chip is OPL%d.\n", scp->model));
MIDI_DEBUG(printf("opl: attached.\n"));
MIDI_DEBUG(printf("opl: the chip is OPL%d.\n", scp->model));
return (0);
}
@ -772,11 +772,11 @@ opl_open(dev_t i_dev, int flags, int mode, struct thread *td)
unit = MIDIUNIT(i_dev);
DEB(printf("opl%d: opening.\n", unit));
MIDI_DEBUG(printf("opl%d: opening.\n", unit));
devinfo = get_mididev_info(i_dev, &unit);
if (devinfo == NULL) {
DEB(printf("opl_open: unit %d is not configured.\n", unit));
MIDI_DEBUG(printf("opl_open: unit %d is not configured.\n", unit));
return (ENXIO);
}
scp = devinfo->softc;
@ -799,7 +799,7 @@ opl_open(dev_t i_dev, int flags, int mode, struct thread *td)
mtx_unlock(&scp->mtx);
}
DEB(printf("opl%d: opened.\n", unit));
MIDI_DEBUG(printf("opl%d: opened.\n", unit));
return (0);
}
@ -813,11 +813,11 @@ opl_close(dev_t i_dev, int flags, int mode, struct thread *td)
unit = MIDIUNIT(i_dev);
DEB(printf("opl%d: closing.\n", unit));
MIDI_DEBUG(printf("opl%d: closing.\n", unit));
devinfo = get_mididev_info(i_dev, &unit);
if (devinfo == NULL) {
DEB(printf("opl_close: unit %d is not configured.\n", unit));
MIDI_DEBUG(printf("opl_close: unit %d is not configured.\n", unit));
return (ENXIO);
}
scp = devinfo->softc;
@ -832,7 +832,7 @@ opl_close(dev_t i_dev, int flags, int mode, struct thread *td)
/* Stop the OPL. */
opl_reset(scp->devinfo);
DEB(printf("opl%d: closed.\n", unit));
MIDI_DEBUG(printf("opl%d: closed.\n", unit));
return (0);
}
@ -845,15 +845,15 @@ opl_ioctl(dev_t i_dev, u_long cmd, caddr_t arg, int mode, struct thread *td)
int unit;
struct synth_info *synthinfo;
struct midi_info *midiinfo;
struct sbi_instrument ins;
struct sbi_instrument *ins;
unit = MIDIUNIT(i_dev);
DEB(printf("opl%d: ioctlling, cmd 0x%x.\n", unit, (int)cmd));
MIDI_DEBUG(printf("opl_ioctl: unit %d, cmd %s.\n", unit, midi_cmdname(cmd, cmdtab_midiioctl)));
devinfo = get_mididev_info(i_dev, &unit);
if (devinfo == NULL) {
DEB(printf("opl_ioctl: unit %d is not configured.\n", unit));
MIDI_DEBUG(printf("opl_ioctl: unit %d is not configured.\n", unit));
return (ENXIO);
}
scp = devinfo->softc;
@ -880,19 +880,20 @@ opl_ioctl(dev_t i_dev, u_long cmd, caddr_t arg, int mode, struct thread *td)
return (0);
break;
case SNDCTL_FM_LOAD_INSTR:
bcopy(arg, &ins, sizeof(ins));
if (ins.channel < 0 || ins.channel >= SBFM_MAXINSTR) {
printf("opl_ioctl: Instrument number %d is not valid.\n", ins.channel);
ins = (struct sbi_instrument *)arg;
if (ins->channel < 0 || ins->channel >= SBFM_MAXINSTR) {
printf("opl_ioctl: Instrument number %d is not valid.\n", ins->channel);
return (EINVAL);
}
#if notyet
pmgr_inform(scp, PM_E_PATCH_LOADED, inc.channel, 0, 0, 0);
pmgr_inform(scp, PM_E_PATCH_LOADED, inc->channel, 0, 0, 0);
#endif /* notyet */
opl_storeinstr(scp, ins.channel, &ins);
opl_storeinstr(scp, ins->channel, ins);
return (0);
break;
case SNDCTL_SYNTH_MEMAVL:
return 0x7fffffff;
*(int *)arg = 0x7fffffff;
return (0);
break;
case SNDCTL_FM_4OP_ENABLE:
if (scp->model >= MODEL_OPL3)
@ -918,14 +919,14 @@ opl_callback(void *d, int reason)
mtx_assert(&devinfo->flagqueue_mtx, MA_OWNED);
if (devinfo == NULL) {
DEB(printf("opl_callback: device not configured.\n"));
MIDI_DEBUG(printf("opl_callback: device not configured.\n"));
return (ENXIO);
}
unit = devinfo->unit;
scp = devinfo->softc;
DEB(printf("opl%d: callback, reason 0x%x.\n", unit, reason));
MIDI_DEBUG(printf("opl%d: callback, reason 0x%x.\n", unit, reason));
switch (reason & MIDI_CB_REASON_MASK) {
case MIDI_CB_START:
@ -964,7 +965,7 @@ opl_readraw(mididev_info *md, u_char *buf, int len, int *lenr, int nonblock)
unit = md->unit;
scp = md->softc;
if ((md->fflags & FREAD) == 0) {
DEB(printf("opl_readraw: unit %d is not for reading.\n", unit));
MIDI_DEBUG(printf("opl_readraw: unit %d is not for reading.\n", unit));
return (EIO);
}
@ -988,7 +989,7 @@ opl_writeraw(mididev_info *md, u_char *buf, int len, int *lenw, int nonblock)
unit = md->unit;
scp = md->softc;
if ((md->fflags & FWRITE) == 0) {
DEB(printf("opl_writeraw: unit %d is not for writing.\n", unit));
MIDI_DEBUG(printf("opl_writeraw: unit %d is not for writing.\n", unit));
return (EIO);
}
@ -1010,7 +1011,7 @@ opl_killnote(mididev_info *md, int voice, int note, int vel)
scp = md->softc;
unit = md->unit;
DEB(printf("opl%d: killing a note, voice %d, note %d, vel %d.\n", unit, voice, note, vel));
MIDI_DEBUG(printf("opl%d: killing a note, voice %d, note %d, vel %d.\n", unit, voice, note, vel));
if (voice < 0 || voice >= md->synth.alloc.max_voice)
return (0);
@ -1048,7 +1049,7 @@ opl_setinstr(mididev_info *md, int voice, int instr_no)
scp = md->softc;
unit = md->unit;
DEB(printf("opl%d: setting an instrument, voice %d, instr_no %d.\n", unit, voice, instr_no));
MIDI_DEBUG(printf("opl%d: setting an instrument, voice %d, instr_no %d.\n", unit, voice, instr_no));
if (voice < 0 || voice >= md->synth.alloc.max_voice || instr_no < 0 || instr_no >= SBFM_MAXINSTR)
@ -1073,7 +1074,7 @@ opl_startnote(mididev_info *md, int voice, int note, int volume)
scp = md->softc;
unit = md->unit;
DEB(printf("opl%d: starting a note, voice %d, note %d, volume %d.\n", unit, voice, note, volume));
MIDI_DEBUG(printf("opl%d: starting a note, voice %d, note %d, volume %d.\n", unit, voice, note, volume));
if (voice < 0 || voice >= md->synth.alloc.max_voice)
return (0);
@ -1192,7 +1193,7 @@ opl_reset(mididev_info *md)
scp = md->softc;
unit = md->unit;
DEB(printf("opl%d: resetting.\n", unit));
MIDI_DEBUG(printf("opl%d: resetting.\n", unit));
mtx_lock(&md->synth.vc_mtx);
mtx_lock(&scp->mtx);
@ -1297,7 +1298,7 @@ opl_aftertouch(mididev_info *md, int voice, int press)
scp = md->softc;
unit = md->unit;
DEB(printf("opl%d: setting the aftertouch, voice %d, press %d.\n", unit, voice, press));
MIDI_DEBUG(printf("opl%d: setting the aftertouch, voice %d, press %d.\n", unit, voice, press));
if (voice < 0 || voice >= md->synth.alloc.max_voice)
return (0);
@ -1356,7 +1357,7 @@ opl_bendpitch(sc_p scp, int voice, int value)
md = scp->devinfo;
unit = md->unit;
DEB(printf("opl%d: setting the pitch bend, voice %d, value %d.\n", unit, voice, value));
MIDI_DEBUG(printf("opl%d: setting the pitch bend, voice %d, value %d.\n", unit, voice, value));
mtx_lock(&scp->mtx);
@ -1396,7 +1397,7 @@ opl_controller(mididev_info *md, int voice, int ctrlnum, int val)
scp = md->softc;
unit = md->unit;
DEB(printf("opl%d: setting the controller, voice %d, ctrlnum %d, val %d.\n", unit, voice, ctrlnum, val));
MIDI_DEBUG(printf("opl%d: setting the controller, voice %d, ctrlnum %d, val %d.\n", unit, voice, ctrlnum, val));
if (voice < 0 || voice >= md->synth.alloc.max_voice)
return (0);
@ -1448,7 +1449,7 @@ opl_allocvoice(mididev_info *md, int chn, int note, struct voice_alloc_info *all
scp = md->softc;
DEB(printf("opl%d: allocating a voice, chn %d, note %d.\n", unit, chn, note));
MIDI_DEBUG(printf("opl%d: allocating a voice, chn %d, note %d.\n", md->unit, chn, note));
best_time = 0x7fffffff;
@ -1515,7 +1516,7 @@ opl_setupvoice(mididev_info *md, int voice, int chn)
scp = md->softc;
DEB(printf("opl%d: setting up a voice, voice %d, chn %d.\n", unit, voice, chn));
MIDI_DEBUG(printf("opl%d: setting up a voice, voice %d, chn %d.\n", md->unit, voice, chn));
mtx_lock(&md->synth.vc_mtx);
@ -1563,7 +1564,7 @@ opl_command(sc_p scp, int ch, int addr, u_int val)
{
int model;
DEB(printf("opl%d: sending a command, iobase 0x%x, addr 0x%x, val 0x%x.\n", unit, iobase, addr, val));
MIDI_DEBUG(printf("opl%d: sending a command, addr 0x%x, val 0x%x.\n", scp->devinfo->unit, addr, val));
model = scp->model;
@ -1590,7 +1591,7 @@ opl_command(sc_p scp, int ch, int addr, u_int val)
static int
opl_status(sc_p scp)
{
DEB(printf("opl%d: reading the status.\n", unit));
MIDI_DEBUG(printf("opl%d: reading the status.\n", scp->devinfo->unit));
return bus_space_read_1(rman_get_bustag(scp->io), rman_get_bushandle(scp->io), 0);
}
@ -1606,7 +1607,7 @@ opl_enter4opmode(sc_p scp)
devinfo = scp->devinfo;
DEB(printf("opl%d: entering 4 OP mode.\n", unit));
MIDI_DEBUG(printf("opl%d: entering 4 OP mode.\n", devinfo->unit));
/* Connect all possible 4 OP voice operators. */
mtx_lock(&devinfo->synth.vc_mtx);

View file

@ -172,7 +172,7 @@ uartsio_probe(device_t dev)
if (scp->io == NULL)
return (ENXIO);
DEB(printf("uartsio%d: probing.\n", unit));
MIDI_DEBUG(printf("uartsio%d: probing.\n", unit));
/* Read the IER. The upper four bits should all be zero. */
c = uartsio_readport(scp, com_ier);
@ -190,7 +190,7 @@ uartsio_probe(device_t dev)
/* XXX Do we need a loopback test? */
DEB(printf("uartsio%d: probed.\n", unit));
MIDI_DEBUG(printf("uartsio%d: probed.\n", unit));
return (0);
}
@ -203,7 +203,7 @@ uartsio_attach(device_t dev)
scp = device_get_softc(dev);
DEB(printf("uartsio: attaching.\n"));
MIDI_DEBUG(printf("uartsio: attaching.\n"));
/* Allocate resources. */
if (uartsio_allocres(scp, dev)) {
@ -216,11 +216,11 @@ uartsio_attach(device_t dev)
if ((uartsio_readport(scp, com_iir) & IIR_FIFO_MASK) == FIFO_RX_HIGH) {
scp->has_fifo = 1;
scp->tx_size = TX_FIFO_SIZE;
DEB(printf("uartsio: uart is 16550A, tx size is %d bytes.\n", scp->tx_size));
MIDI_DEBUG(printf("uartsio: uart is 16550A, tx size is %d bytes.\n", scp->tx_size));
} else {
scp->has_fifo = 0;
scp->tx_size = 1;
DEB(printf("uartsio: uart is not 16550A.\n"));
MIDI_DEBUG(printf("uartsio: uart is not 16550A.\n"));
}
/* Configure the uart. */
@ -255,7 +255,7 @@ uartsio_attach(device_t dev)
/* Now we can handle the interrupts. */
bus_setup_intr(dev, scp->irq, INTR_TYPE_AV, uartsio_intr, scp, &scp->ih);
DEB(printf("uartsio: attached.\n"));
MIDI_DEBUG(printf("uartsio: attached.\n"));
return (0);
}
@ -271,9 +271,11 @@ uartsio_ioctl(dev_t i_dev, u_long cmd, caddr_t arg, int mode, struct thread *td)
unit = MIDIUNIT(i_dev);
MIDI_DEBUG(printf("uartsio_ioctl: unit %d, cmd %s.\n", unit, midi_cmdname(cmd, cmdtab_midiioctl)));
devinfo = get_mididev_info(i_dev, &unit);
if (devinfo == NULL) {
DEB(printf("uartsio_ioctl: unit %d is not configured.\n", unit));
MIDI_DEBUG(printf("uartsio_ioctl: unit %d is not configured.\n", unit));
return (ENXIO);
}
scp = devinfo->softc;
@ -331,7 +333,7 @@ uartsio_callback(void *di, int reason)
mtx_assert(&d->flagqueue_mtx, MA_OWNED);
if (d == NULL) {
DEB(printf("uartsio_callback: device not configured.\n"));
MIDI_DEBUG(printf("uartsio_callback: device not configured.\n"));
return (ENXIO);
}

View file

@ -89,16 +89,45 @@ static struct cdevsw midi_cdevsw = {
* descriptors for active devices. also used as the public softc
* of a device.
*/
static TAILQ_HEAD(,_mididev_info) midi_info;
static int nmidi, nsynth;
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;
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;
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.
@ -115,6 +144,8 @@ midiinit(mididev_info *d, device_t dev)
* 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;
@ -183,6 +214,58 @@ get_mididev_info_unit(int unit)
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", 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", 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 *
@ -213,12 +296,15 @@ create_mididev_info_unit(int type, mididev_info *mdinf, synthdev_info *syninf)
mtx_lock(&midiinfo_mtx);
/* XXX midi_info is still static. */
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:
@ -233,6 +319,7 @@ create_mididev_info_unit(int type, mididev_info *mdinf, synthdev_info *syninf)
panic("unsupported device type");
return NULL;
}
mdnew->mdtype = type;
for (unit = 0 ; ; unit++) {
TAILQ_FOREACH(md, &midi_info, md_link) {
@ -259,6 +346,20 @@ 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
@ -391,8 +492,7 @@ midi_open(dev_t i_dev, int flags, int mode, struct thread *td)
dev = minor(i_dev);
d = get_mididev_info(i_dev, &unit);
DEB(printf("open midi%d subdev %d flags 0x%08x mode 0x%08x\n",
unit, dev & 0xf, flags, mode));
MIDI_DEBUG(printf("midi_open: unit %d, flags 0x%x.\n", unit, flags));
if (d == NULL)
return (ENXIO);
@ -402,12 +502,14 @@ midi_open(dev_t i_dev, int flags, int mode, struct thread *td)
device_busy(d->dev);
if ((d->flags & MIDI_F_BUSY) != 0) {
mtx_unlock(&d->flagqueue_mtx);
DEB(printf("opl_open: unit %d is busy.\n", unit));
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);
d->fflags = flags;
if ((d->fflags & O_NONBLOCK) != 0)
d->flags |= MIDI_F_NBIO;
/* Init the queue. */
if ((flags & FREAD) != 0)
@ -424,6 +526,16 @@ midi_open(dev_t i_dev, int flags, int mode, struct thread *td)
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);
}
@ -436,7 +548,7 @@ midi_close(dev_t i_dev, int flags, int mode, struct thread *td)
dev = minor(i_dev);
d = get_mididev_info(i_dev, &unit);
DEB(printf("close midi%d subdev %d\n", unit, dev & 0xf));
MIDI_DEBUG(printf("midi_close: unit %d.\n", unit));
if (d == NULL)
return (ENXIO);
@ -470,6 +582,8 @@ midi_close(dev_t i_dev, int flags, int mode, struct thread *td)
else
ret = d->close(i_dev, flags, mode, td);
MIDI_DEBUG(printf("midi_close: closed.\n"));
return (ret);
}
@ -483,7 +597,7 @@ midi_read(dev_t i_dev, struct uio * buf, int flag)
dev = minor(i_dev);
d = get_mididev_info(i_dev, &unit);
DEB(printf("read midi%d subdev %d flag 0x%08x\n", unit, dev & 0xf, flag));
MIDI_DEBUG(printf("midi_read: unit %d, resid %d.\n", unit, buf->uio_resid));
if (d == NULL)
return (ENXIO);
@ -505,10 +619,13 @@ midi_read(dev_t i_dev, struct uio * buf, int flag)
/* Have we got the data to read? */
if ((d->flags & MIDI_F_NBIO) != 0 && d->midi_dbuf_in.rl == 0)
ret = EAGAIN;
else
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);
@ -517,6 +634,8 @@ midi_read(dev_t i_dev, struct uio * buf, int flag)
free(uiobuf, M_DEVBUF);
MIDI_DEBUG(printf("midi_read: ret %d, resid %d.\n", ret, buf->uio_resid));
return (ret);
}
@ -530,7 +649,7 @@ midi_write(dev_t i_dev, struct uio * buf, int flag)
dev = minor(i_dev);
d = get_mididev_info(i_dev, &unit);
DEB(printf("write midi%d subdev %d flag 0x%08x\n", unit, dev & 0xf, flag));
MIDI_DEBUG(printf("midi_write: unit %d.\n", unit));
if (d == NULL)
return (ENXIO);
@ -593,6 +712,7 @@ 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);
@ -610,6 +730,8 @@ midi_ioctl(dev_t i_dev, u_long cmd, caddr_t arg, int mode, struct thread *td)
*/
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!
@ -620,11 +742,15 @@ midi_ioctl(dev_t i_dev, u_long cmd, caddr_t arg, int mode, struct thread *td)
* 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;
@ -661,6 +787,7 @@ midi_ioctl(dev_t i_dev, u_long cmd, caddr_t arg, int mode, struct thread *td)
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;
@ -672,40 +799,45 @@ midi_ioctl(dev_t i_dev, u_long cmd, caddr_t arg, int mode, struct thread *td)
else if (*(int *)arg == AIOSYNC_CAPTURE)
*(int *)arg = d->callback(d, MIDI_CB_STOP | MIDI_CB_RD);
else {
DEB(printf("AIOSTOP: bad channel 0x%x\n", *(int *)arg));
MIDI_DEBUG(printf("midi_ioctl: bad channel 0x%x.\n", *(int *)arg));
*(int *)arg = 0 ;
}
mtx_unlock(&d->flagqueue_mtx);
break ;
case AIOSYNC:
DEB(printf("AIOSYNC chan 0x%03lx pos %lu unimplemented\n",
((snd_sync_parm *)arg)->chan,
((snd_sync_parm *)arg)->pos));
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 */
DEB( printf("FIOASYNC\n") ; )
MIDI_DEBUG(printf("FIOASYNC\n"));
break;
case FIONBIO: /* set/clear non-blocking i/o */
mtx_lock(&d->flagqueue_mtx);
if ( *(int *)arg == 0 )
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 )
if (*(int *)arg == 0)
d->flags &= ~MIDI_F_PASSTHRU ;
else
d->flags |= MIDI_F_PASSTHRU ;
@ -714,18 +846,22 @@ midi_ioctl(dev_t i_dev, u_long cmd, caddr_t arg, int mode, struct thread *td)
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;
*(int *)arg = 1;
else
(int *)arg = 0;
break ;
*(int *)arg = 0;
mtx_unlock(&d->flagqueue_mtx);
MIDI_DEBUG(printf("midi_ioctl: passthru %d.\n", *(int *)arg));
break;
default:
DEB(printf("default ioctl midi%d subdev %d fn 0x%08x fail\n",
unit, dev & 0xf, cmd));
MIDI_DEBUG(printf("midi_ioctl: default ioctl midi%d subdev %d fn 0x%08lx fail\n",
unit, dev & 0xf, cmd));
ret = EINVAL;
break ;
}
@ -741,6 +877,8 @@ midi_poll(dev_t i_dev, int events, struct thread *td)
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);
@ -803,6 +941,8 @@ midi_sync(mididev_info *d)
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);
@ -903,3 +1043,15 @@ midi_readstatus(char *buf, int *ptr, struct uio *uio)
return (0);
}
char
*midi_cmdname(int cmd, midi_cmdtab *tab)
{
while (tab->name != NULL) {
if (cmd == tab->cmd)
return (tab->name);
tab++;
}
return ("unknown");
}

View file

@ -45,6 +45,7 @@
#include <sys/fcntl.h>
#include <sys/tty.h>
#include <sys/proc.h>
#include <sys/sysctl.h>
#include <sys/kernel.h> /* for DATA_SET */
@ -98,14 +99,14 @@ struct _mididev_info {
* the first part of the descriptor is filled up from a
* template.
*/
char name[64];
char name[64];
int type;
int type;
d_open_t *open;
d_close_t *close;
d_ioctl_t *ioctl;
midi_callback_t *callback;
d_open_t *open;
d_close_t *close;
d_ioctl_t *ioctl;
midi_callback_t *callback;
/*
* combinations of the following flags are used as second argument in
@ -137,20 +138,23 @@ struct _mididev_info {
* not in the common structure.
*/
int unit; /* unit number of the device */
void *softc; /* softc for the device */
device_t dev; /* device_t for the device */
int unit; /* unit number of the device */
int midiunit; /* unit number for midi devices */
int synthunit; /* unit number for synth devices */
int mdtype; /* MDT_MIDI or MDT_SYNTH */
void *softc; /* softc for the device */
device_t dev; /* device_t for the device */
int bd_id ; /* used to hold board-id info, eg. sb version,
* mss codec type, etc. etc.
*/
int bd_id; /* used to hold board-id info, eg. sb version,
* mss codec type, etc. etc.
*/
struct mtx flagqueue_mtx; /* Mutex to protect flags and queues */
struct mtx flagqueue_mtx; /* Mutex to protect flags and queues */
/* Queues */
midi_dbuf midi_dbuf_in; /* midi input event/message queue */
midi_dbuf midi_dbuf_out; /* midi output event/message queue */
midi_dbuf midi_dbuf_passthru; /* midi passthru event/message queue */
midi_dbuf midi_dbuf_in; /* midi input event/message queue */
midi_dbuf midi_dbuf_out; /* midi output event/message queue */
midi_dbuf midi_dbuf_passthru; /* midi passthru event/message queue */
/*
* these parameters describe the operation of the board.
@ -158,8 +162,8 @@ struct _mididev_info {
*/
/* Flags */
volatile u_long flags ; /* 32 bits, used for various purposes. */
int fflags; /* file flag */
volatile u_long flags; /* 32 bits, used for various purposes. */
int fflags; /* file flag */
/*
* we have separate flags for read and write, although in some
@ -210,29 +214,29 @@ struct _mididev_info {
*/
#define MIDI_F_INIT 0x4000 /* changed parameters. need init */
int play_blocksize, rec_blocksize; /* blocksize for io and dma ops */
int play_blocksize, rec_blocksize; /* blocksize for io and dma ops */
#define mwsel midi_dbuf_out.sel
#define mrsel midi_dbuf_in.sel
u_long interrupts; /* counter of interrupts */
u_long magic;
u_long nterrupts; /* counter of interrupts */
u_long magic;
#define MAGIC(unit) ( 0xa4d10de0 + unit )
void *device_data ; /* just in case it is needed...*/
void *device_data ; /* just in case it is needed...*/
midi_intr_t *intr; /* interrupt handler of the upper layer (ie sequencer) */
midi_intr_t *intr; /* interrupt handler of the upper layer (ie sequencer) */
void *intrarg; /* argument to interrupt handler */
/* The following is the interface from a midi sequencer to a midi device. */
synthdev_info synth;
synthdev_info synth;
/* This is the status message to display via /dev/midistat */
char midistat[128];
char midistat[128];
/* The tailq entry of the next midi device. */
TAILQ_ENTRY(_mididev_info) md_link;
TAILQ_ENTRY(_mididev_info) md_link;
/* The tailq entry of the next midi device opened by a sequencer. */
TAILQ_ENTRY(_mididev_info) md_linkseq;
TAILQ_ENTRY(_mididev_info) md_linkseq;
} ;
/*
@ -267,17 +271,7 @@ struct _mididev_info {
*/
#define MIDI_BUFFSIZE (1024) /* XXX */
/*
* some macros for debugging purposes
* DDB/DEB to enable/disable debugging stuff
* BVDDB to enable debugging when bootverbose
*/
#define DDB(x) x /* XXX */
#define BVDDB(x) if (bootverbose) x
#ifndef DEB
#define DEB(x)
#endif
#ifdef _KERNEL
/* This is the generic midi drvier initializer. */
int midiinit(mididev_info *d, device_t dev);
@ -285,8 +279,12 @@ struct _mididev_info {
/* This provides an access to the mididev_info. */
mididev_info *get_mididev_info(dev_t i_dev, int *unit);
mididev_info *get_mididev_info_unit(int unit);
mididev_info *get_mididev_midi_unit(int unit);
mididev_info *get_mididev_synth_unit(int unit);
mididev_info *create_mididev_info_unit(int type, mididev_info *mdinf, synthdev_info *syninf);
int mididev_info_number(void);
int mididev_midi_number(void);
int mididev_synth_number(void);
#define MDT_MIDI (0)
#define MDT_SYNTH (1)
@ -299,10 +297,32 @@ struct _mididev_info {
d_poll_t midi_poll;
/* Common interrupt handler */
void midi_intr(mididev_info *);
void midi_intr(mididev_info *);
/* Sync output */
int midi_sync(mididev_info *);
int midi_sync(mididev_info *);
struct _midi_cmdtab {
int cmd;
char * name;
};
typedef struct _midi_cmdtab midi_cmdtab;
char *midi_cmdname(int cmd, midi_cmdtab *tab);
SYSCTL_DECL(_hw_midi);
extern int midi_debug;
#define MIDI_DEBUG(x) \
do { \
if (midi_debug) { \
(x); \
} \
} while(0)
extern midi_cmdtab cmdtab_midiioctl[];
#endif /* _KERNEL */
/*
* Minor numbers for the midi driver.

View file

@ -125,11 +125,11 @@ midibuf_seqwrite(midi_dbuf *dbuf, u_char* data, int len, int *lenw, midi_callbac
*lenw += lwrt;
len -= lwrt;
data += lwrt;
if (cb != NULL)
(*cb)(d, reason);
}
if (cb != NULL)
(*cb)(d, reason);
/* Have we got still more data to write? */
if (len > 0) {
/* Sleep until we have enough space. */

View file

@ -437,7 +437,7 @@ synth_readraw(mididev_info *md, u_char *buf, int len, int *lenr, int nonblock)
unit = md->unit;
if ((md->fflags & FREAD) == 0) {
DEB(printf("synth_readraw: unit %d is not for reading.\n", unit));
MIDI_DEBUG(printf("synth_readraw: unit %d is not for reading.\n", unit));
return (EIO);
}
@ -478,7 +478,7 @@ synth_writeraw(mididev_info *md, u_char *buf, int len, int *lenw, int nonblock)
unit = md->unit;
if ((md->fflags & FWRITE) == 0) {
DEB(printf("synth_writeraw: unit %d is not for writing.\n", unit));
MIDI_DEBUG(printf("synth_writeraw: unit %d is not for writing.\n", unit));
return (EIO);
}

File diff suppressed because it is too large Load diff

View file

@ -57,6 +57,8 @@
#include <machine/clock.h> /* for DELAY */
#include <sys/soundcard.h>
#include <dev/sound/midi/timer.h>
#define SEQ_CDEV_MAJOR MIDI_CDEV_MAJOR
/*
@ -66,6 +68,13 @@
#include <sys/poll.h>
#define d_select_t d_poll_t
/* Return value from seq_playevent and timer event handers. */
enum {
MORE,
TIMERARMED,
QUEUEFULL
};
typedef struct _seqdev_info seqdev_info;
/*
@ -214,7 +223,7 @@ struct _seqdev_info {
/* The tailq entry of the next sequencer device. */
TAILQ_ENTRY(_seqdev_info) sd_link;
} ;
};
/*
@ -234,19 +243,30 @@ struct _seqdev_info {
*/
#define SEQ_BUFFSIZE (1024) /* XXX */
/*
* some macros for debugging purposes
* DDB/DEB to enable/disable debugging stuff
* BVDDB to enable debugging when bootverbose
*/
#define DDB(x) x /* XXX */
#define BVDDB(x) if (bootverbose) x
#ifndef DEB
#define DEB(x)
#endif
#define MIDI_DEV_SEQ 1 /* Sequencer output /dev/sequencer (FM
synthesizer and MIDI output) */
#define MIDI_DEV_MUSIC 8 /* Sequencer output /dev/music (FM
synthesizer and MIDI output) */
#ifdef _KERNEL
extern midi_cmdtab cmdtab_seqioctl[];
extern midi_cmdtab cmdtab_timer[];
void seq_timer(void *arg);
int seq_copytoinput(void *arg, u_char *event, int len);
SYSCTL_DECL(_hw_midi_seq);
extern int seq_debug;
#define SEQ_DEBUG(x) \
do { \
if (seq_debug) { \
(x); \
} \
} while(0)
#endif /* _KERNEL */
#endif /* _SEQUENCER_H_ */

View file

@ -224,9 +224,11 @@ csamidi_ioctl(dev_t i_dev, u_long cmd, caddr_t arg, int mode, struct thread *td)
unit = MIDIUNIT(i_dev);
MIDI_DEBUG(printf("csamidi_ioctl: unit %d, cmd %s.\n", unit, midi_cmdname(cmd, cmdtab_midiioctl)));
devinfo = get_mididev_info(i_dev, &unit);
if (devinfo == NULL) {
DEB(printf("csamidi_ioctl: unit %d is not configured.\n", unit));
MIDI_DEBUG(printf("csamidi_ioctl: unit %d is not configured.\n", unit));
return (ENXIO);
}
scp = devinfo->softc;
@ -310,7 +312,7 @@ csamidi_callback(void *di, int reason)
mtx_assert(&d->flagqueue_mtx, MA_OWNED);
if (d == NULL) {
DEB(printf("csamidi_callback: device not configured.\n"));
MIDI_DEBUG(printf("csamidi_callback: device not configured.\n"));
return (ENXIO);
}