summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authortanimura <tanimura@FreeBSD.org>2002-01-04 01:13:49 +0000
committertanimura <tanimura@FreeBSD.org>2002-01-04 01:13:49 +0000
commitc9a37a6ceaafff4e7bb45214a8cb8bec4cbe1040 (patch)
tree172193f32d3428cba6b1cfe2673b7e848920b3f2
parentbc1c5ca72163809979db46d3d2ea6f9d3ea63a71 (diff)
downloadFreeBSD-src-c9a37a6ceaafff4e7bb45214a8cb8bec4cbe1040.zip
FreeBSD-src-c9a37a6ceaafff4e7bb45214a8cb8bec4cbe1040.tar.gz
- 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.
-rw-r--r--sys/conf/files1
-rw-r--r--sys/dev/sound/isa/emu8000.c19
-rw-r--r--sys/dev/sound/isa/gusmidi.c8
-rw-r--r--sys/dev/sound/isa/mpu.c14
-rw-r--r--sys/dev/sound/isa/opl.c75
-rw-r--r--sys/dev/sound/isa/uartsio.c18
-rw-r--r--sys/dev/sound/midi/midi.c208
-rw-r--r--sys/dev/sound/midi/midi.h100
-rw-r--r--sys/dev/sound/midi/midibuf.c6
-rw-r--r--sys/dev/sound/midi/midisynth.c4
-rw-r--r--sys/dev/sound/midi/sequencer.c751
-rw-r--r--sys/dev/sound/midi/sequencer.h46
-rw-r--r--sys/dev/sound/pci/csamidi.c6
13 files changed, 882 insertions, 374 deletions
diff --git a/sys/conf/files b/sys/conf/files
index d6404a9..77353f8 100644
--- a/sys/conf/files
+++ b/sys/conf/files
@@ -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
diff --git a/sys/dev/sound/isa/emu8000.c b/sys/dev/sound/isa/emu8000.c
index af9e3b2..d17ca3c 100644
--- a/sys/dev/sound/isa/emu8000.c
+++ b/sys/dev/sound/isa/emu8000.c
@@ -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);
}
diff --git a/sys/dev/sound/isa/gusmidi.c b/sys/dev/sound/isa/gusmidi.c
index e5ff9cf..37c99cc 100644
--- a/sys/dev/sound/isa/gusmidi.c
+++ b/sys/dev/sound/isa/gusmidi.c
@@ -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);
}
diff --git a/sys/dev/sound/isa/mpu.c b/sys/dev/sound/isa/mpu.c
index b79a3dd..f66466f 100644
--- a/sys/dev/sound/isa/mpu.c
+++ b/sys/dev/sound/isa/mpu.c
@@ -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 @@ no_irq:
/* 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);
}
diff --git a/sys/dev/sound/isa/opl.c b/sys/dev/sound/isa/opl.c
index 345bebb..6ee4e96 100644
--- a/sys/dev/sound/isa/opl.c
+++ b/sys/dev/sound/isa/opl.c
@@ -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);
diff --git a/sys/dev/sound/isa/uartsio.c b/sys/dev/sound/isa/uartsio.c
index f81f787..6554247 100644
--- a/sys/dev/sound/isa/uartsio.c
+++ b/sys/dev/sound/isa/uartsio.c
@@ -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);
}
diff --git a/sys/dev/sound/midi/midi.c b/sys/dev/sound/midi/midi.c
index 2db4d65..8b6e2a7 100644
--- a/sys/dev/sound/midi/midi.c
+++ b/sys/dev/sound/midi/midi.c
@@ -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");
+}
diff --git a/sys/dev/sound/midi/midi.h b/sys/dev/sound/midi/midi.h
index 9302b56..c048133 100644
--- a/sys/dev/sound/midi/midi.h
+++ b/sys/dev/sound/midi/midi.h
@@ -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.
diff --git a/sys/dev/sound/midi/midibuf.c b/sys/dev/sound/midi/midibuf.c
index 7e75471..d764b68 100644
--- a/sys/dev/sound/midi/midibuf.c
+++ b/sys/dev/sound/midi/midibuf.c
@@ -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. */
diff --git a/sys/dev/sound/midi/midisynth.c b/sys/dev/sound/midi/midisynth.c
index 9f99d35..d370833 100644
--- a/sys/dev/sound/midi/midisynth.c
+++ b/sys/dev/sound/midi/midisynth.c
@@ -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);
}
diff --git a/sys/dev/sound/midi/sequencer.c b/sys/dev/sound/midi/sequencer.c
index 3677c76..7bfb753 100644
--- a/sys/dev/sound/midi/sequencer.c
+++ b/sys/dev/sound/midi/sequencer.c
@@ -36,14 +36,10 @@
#include <dev/sound/midi/midi.h>
#include <dev/sound/midi/sequencer.h>
-#ifndef DDB
-#define DDB(x)
-#endif /* DDB */
-
#define SND_DEV_SEQ 1 /* Sequencer output /dev/sequencer (FM
synthesizer and MIDI output) */
#define SND_DEV_MIDIN 2 /* Raw midi access */
-#define SND_DEV_SEQ2 8 /* /dev/sequencer, level 2 interface */
+#define SND_DEV_MUSIC 8 /* /dev/music, level 2 interface */
#define MIDIDEV_MODE 0x2000
@@ -51,13 +47,6 @@
#define EV_SZ 8
#define IEV_SZ 8
-/* Return value from seq_playevent and the helpers. */
-enum {
- MORE,
- TIMERARMED,
- QUEUEFULL
-};
-
/* Lookup modes */
#define LOOKUP_EXIST (0)
#define LOOKUP_OPEN (1)
@@ -102,36 +91,37 @@ seqdev_info seq_op_desc = {
};
-
/* Here is the parameter structure per a device. */
struct seq_softc {
- seqdev_info *devinfo; /* sequencer device information */
+ seqdev_info *devinfo; /* sequencer device information */
/* Flags (protected by flag_mtx of mididev_info) */
- int fflags; /* Access mode */
- int queueout_pending; /* Pending for the output queue */
+ int fflags; /* Access mode */
+ int queueout_pending; /* Pending for the output queue */
+ int seq_mode; /* Sequencer mode */
/* Timer counters */
- u_long seq_time; /* The beggining time of this sequence */
- u_long prev_event_time; /* The time of the previous event output */
- u_long prev_input_time; /* The time of the previous event input */
- u_long prev_wakeup_time; /* The time of the previous wakeup */
- struct callout timeout_ch; /* Timer callout handler */
- long timer_current; /* Current timer value */
- int timer_running; /* State of timer */
- int pending_timer; /* Timer change operation */
- int pre_event_timeout; /* Time to wait event input */
-
- /* Device list */
- TAILQ_HEAD(,_mididev_info) midi_open; /* Midi devices opened by this sequencer. */
+ u_long seq_time; /* The beggining time of this sequence */
+ u_long prev_event_time; /* The time of the previous event output */
+ u_long prev_input_time; /* The time of the previous event input */
+ u_long prev_wakeup_time; /* The time of the previous wakeup */
+ struct callout timeout_ch; /* Timer callout handler */
+ long timer_current; /* Current timer value */
+ int timer_running; /* State of timer */
+ int pending_timer; /* Timer change operation */
+ int pre_event_timeout; /* Time to wait event input */
+
+ /* Devices */
+ TAILQ_HEAD(,_mididev_info) midi_open; /* Midi devices opened by this sequencer. */
+ timerdev_info *timer; /* A timer device for /dev/music */
/*
* XXX not sure to which category these belong.
* (and some might be no-op)
*/
- int output_threshould; /* Sequence output threshould */
- snd_sync_parm sync_parm; /* AIOSYNC parameter set */
- struct thread *sync_thread; /* AIOSYNCing thread */
+ int output_threshould; /* Sequence output threshould */
+ snd_sync_parm sync_parm; /* AIOSYNC parameter set */
+ struct thread *sync_thread; /* AIOSYNCing thread */
};
typedef struct seq_softc *sc_p;
@@ -160,11 +150,117 @@ static struct cdevsw seq_cdevsw = {
/* flags */ 0,
};
-static TAILQ_HEAD(,_seqdev_info) seq_info;
+
+static TAILQ_HEAD(,_seqdev_info) seq_info;
/* Mutex to protect seq_info and nseq. */
-static struct mtx seqinfo_mtx;
-static u_long nseq; /* total number of sequencers */
-static dev_t seq_alias = NODEV;
+static struct mtx seqinfo_mtx;
+/* total number of sequencers */
+static u_long nseq;
+static dev_t seq_alias = NODEV;
+static dev_t music_alias = NODEV;
+
+SYSCTL_NODE(_hw_midi, OID_AUTO, seq, CTLFLAG_RD, 0, "Midi sequencer");
+
+int seq_debug;
+SYSCTL_INT(_hw_midi_seq, OID_AUTO, debug, CTLFLAG_RW, &seq_debug, 0, "");
+
+static 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_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},
+};
+
+static midi_cmdtab cmdtab_seqcv[] = {
+ {MIDI_NOTEOFF, "MIDI_NOTEOFF"},
+ {MIDI_NOTEON, "MIDI_NOTEON"},
+ {MIDI_KEY_PRESSURE, "MIDI_KEY_PRESSURE"},
+ {-1, NULL},
+};
+
+static 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},
+};
+
/* The followings are the local function. */
static int seq_init(void);
@@ -176,7 +272,6 @@ static u_long seq_gettime(void);
static int seq_requesttimer(sc_p scp, int delay);
static void seq_stoptimer(sc_p scp);
static void seq_midiinput(sc_p scp, mididev_info *md);
-static int seq_copytoinput(sc_p scp, u_char *event, int len);
static int seq_extended(sc_p scp, u_char *event);
static int seq_chnvoice(sc_p scp, u_char *event);
static int seq_findvoice(mididev_info *md, int chn, int note) __unused;
@@ -185,7 +280,6 @@ static int seq_chncommon(sc_p scp, u_char *event);
static int seq_timing(sc_p scp, u_char *event);
static int seq_local(sc_p scp, u_char *event);
static int seq_sysex(sc_p scp, u_char *event);
-static void seq_timer(void *arg);
static int seq_reset(sc_p scp);
static int seq_openmidi(sc_p scp, mididev_info *md, int flags, int mode, struct thread *p);
static int seq_closemidi(sc_p scp, mididev_info *md, int flags, int mode, struct thread *p);
@@ -196,6 +290,7 @@ static seqdev_info *get_seqdev_info(dev_t i_dev, int *unit);
static seqdev_info *get_seqdev_info_unit(int unit);
static seqdev_info *create_seqdev_info_unit(int unit, seqdev_info *seq);
static int lookup_mididev(sc_p scp, int unit, int mode, mididev_info **mdp);
+static int lookup_mididev_midi(sc_p scp, int unit, int mode, mididev_info **mdp);
static void seq_clone(void *arg, char *name, int namelen, dev_t *dev);
/*
@@ -206,7 +301,7 @@ static void seq_clone(void *arg, char *name, int namelen, dev_t *dev);
static int
seq_init(void)
{
- DEB(printf("seq: initing.\n"));
+ SEQ_DEBUG(printf("seq: initing.\n"));
mtx_init(&seqinfo_mtx, "seqinf", MTX_DEF);
TAILQ_INIT(&seq_info);
@@ -214,7 +309,7 @@ seq_init(void)
seq_initunit(0);
EVENTHANDLER_REGISTER(dev_clone, seq_clone, 0, 1000);
- DEB(printf("seq: inited.\n"));
+ SEQ_DEBUG(printf("seq: inited.\n"));
return (0);
}
@@ -224,12 +319,12 @@ seq_initunit(int unit)
{
sc_p scp;
seqdev_info *devinfo;
- dev_t seqdev;
+ dev_t seqdev, musicdev;
/* Allocate the softc. */
scp = malloc(sizeof(*scp), M_DEVBUF, M_WAITOK | M_ZERO);
if (scp == (sc_p)NULL) {
- printf("seq%d: softc allocation failed.\n", unit);
+ printf("seq_initunit: unit %d, softc allocation failed.\n", unit);
return (1);
}
@@ -247,6 +342,7 @@ seq_initunit(int unit)
scp->timer_running = 0;
scp->queueout_pending = 0;
TAILQ_INIT(&scp->midi_open);
+ scp->pending_timer = -1;
scp->devinfo = devinfo = create_seqdev_info_unit(unit, &seq_op_desc);
devinfo->midi_dbuf_in.unit_size = devinfo->midi_dbuf_out.unit_size = EV_SZ;
@@ -256,14 +352,25 @@ seq_initunit(int unit)
seqdev = make_dev(&seq_cdevsw, MIDIMKMINOR(unit, SND_DEV_SEQ),
UID_ROOT, GID_WHEEL, 0666, "sequencer%d", unit);
+ musicdev = make_dev(&seq_cdevsw, MIDIMKMINOR(unit, SND_DEV_MUSIC),
+ UID_ROOT, GID_WHEEL, 0666, "music%d", unit);
+
mtx_lock(&seqinfo_mtx);
if (seq_alias != NODEV) {
destroy_dev(seq_alias);
seq_alias = NODEV;
}
seq_alias = make_dev_alias(seqdev, "sequencer");
+ if (music_alias != NODEV) {
+ destroy_dev(music_alias);
+ music_alias = NODEV;
+ }
+ music_alias = make_dev_alias(musicdev, "music");
mtx_unlock(&seqinfo_mtx);
+ if (timerdev_install() != 0)
+ printf("seq_initunit: timerdev_install failed.\n");
+
return (0);
}
@@ -276,16 +383,16 @@ seq_open(dev_t i_dev, int flags, int mode, struct thread *td)
unit = MIDIUNIT(i_dev);
- DEB(printf("seq%d: opening.\n", unit));
+ SEQ_DEBUG(printf("seq_open: unit %d, flags 0x%x.\n", unit, flags));
if (unit >= NSEQ_MAX) {
- DEB(printf("seq_open: unit %d does not exist.\n", unit));
+ SEQ_DEBUG(printf("seq_open: unit %d does not exist.\n", unit));
return (ENXIO);
}
sd = get_seqdev_info(i_dev, &unit);
if (sd == NULL) {
- DEB(printf("seq_open: unit %d is not configured.\n", unit));
+ SEQ_DEBUG(printf("seq_open: unit %d is not configured.\n", unit));
return (ENXIO);
}
scp = sd->softc;
@@ -294,12 +401,15 @@ seq_open(dev_t i_dev, int flags, int mode, struct thread *td)
mtx_lock(&sd->flagqueue_mtx);
if ((sd->flags & SEQ_F_BUSY) != 0) {
mtx_unlock(&sd->flagqueue_mtx);
- DEB(printf("seq_open: unit %d is busy.\n", unit));
+ SEQ_DEBUG(printf("seq_open: unit %d is busy.\n", unit));
return (EBUSY);
}
+ scp->fflags = flags;
sd->flags |= SEQ_F_BUSY;
sd->flags &= ~(SEQ_F_READING | SEQ_F_WRITING);
- scp->fflags = flags;
+ if ((scp->fflags & O_NONBLOCK) != 0)
+ sd->flags |= SEQ_F_NBIO;
+ scp->seq_mode = MIDIDEV(i_dev);
/* Init the queue. */
midibuf_clear(&sd->midi_dbuf_in);
@@ -311,9 +421,32 @@ seq_open(dev_t i_dev, int flags, int mode, struct thread *td)
scp->prev_input_time = 0;
scp->prev_wakeup_time = scp->seq_time;
+ if (scp->pending_timer != -1) {
+ scp->timer = get_timerdev_info_unit(scp->pending_timer);
+ scp->pending_timer = -1;
+ }
+ if (scp->timer == NULL)
+ scp->timer = get_timerdev_info();
+ if (scp->timer != NULL) {
+ scp->timer->seq = scp;
+ mtx_unlock(&scp->timer->mtx);
+ } else if (scp->seq_mode == SND_DEV_MUSIC) {
+ mtx_unlock(&sd->flagqueue_mtx);
+ printf("seq_open: no timer available.\n");
+ sd->flags &= ~SEQ_F_BUSY;
+ return (ENXIO);
+ }
+
+ if (scp->seq_mode == SND_DEV_MUSIC)
+ scp->timer->open(scp->timer, flags, mode, td);
+
+ /* Begin recording if nonblocking. */
+ if ((sd->flags & (SEQ_F_READING | SEQ_F_NBIO)) == SEQ_F_NBIO && (scp->fflags & FREAD) != 0)
+ sd->callback(sd, SEQ_CB_START | SEQ_CB_RD);
+
mtx_unlock(&sd->flagqueue_mtx);
- DEB(printf("seq%d: opened.\n", unit));
+ SEQ_DEBUG(printf("seq_open: opened, mode %d.\n", scp->seq_mode == SND_DEV_MUSIC ? 2 : 1));
return (0);
}
@@ -325,19 +458,20 @@ seq_close(dev_t i_dev, int flags, int mode, struct thread *td)
sc_p scp;
seqdev_info *sd;
mididev_info *md;
+ timerdev_info *tmd;
unit = MIDIUNIT(i_dev);
- DEB(printf("seq%d: closing.\n", unit));
+ SEQ_DEBUG(printf("seq_close: unit %d.\n", unit));
if (unit >= NSEQ_MAX) {
- DEB(printf("seq_close: unit %d does not exist.\n", unit));
+ SEQ_DEBUG(printf("seq_close: unit %d does not exist.\n", unit));
return (ENXIO);
}
sd = get_seqdev_info(i_dev, &unit);
if (sd == NULL) {
- DEB(printf("seq_close: unit %d is not configured.\n", unit));
+ SEQ_DEBUG(printf("seq_close: unit %d is not configured.\n", unit));
return (ENXIO);
}
scp = sd->softc;
@@ -357,14 +491,24 @@ seq_close(dev_t i_dev, int flags, int mode, struct thread *td)
/* Clean up the midi device. */
TAILQ_FOREACH(md, &scp->midi_open, md_linkseq)
lookup_mididev(scp, md->unit, LOOKUP_CLOSE, NULL);
- mtx_unlock(&sd->flagqueue_mtx);
/* Stop playing and unmark this device busy. */
- mtx_lock(&sd->flagqueue_mtx);
sd->flags &= ~(SEQ_F_BUSY | SEQ_F_READING | SEQ_F_WRITING | SEQ_F_INSYNC);
+
+ if (scp->seq_mode == SND_DEV_MUSIC)
+ scp->timer->close(scp->timer, flags, mode, td);
+
+ if (scp->timer != NULL) {
+ tmd = scp->timer;
+ mtx_lock(&tmd->mtx);
+ scp->timer = NULL;
+ tmd->seq = NULL;
+ mtx_unlock(&tmd->mtx);
+ }
+
mtx_unlock(&sd->flagqueue_mtx);
- DEB(printf("seq%d: closed.\n", unit));
+ SEQ_DEBUG(printf("seq_close: closed.\n"));
return (0);
}
@@ -379,21 +523,21 @@ seq_read(dev_t i_dev, struct uio *buf, int flag)
unit = MIDIUNIT(i_dev);
- /*DEB(printf("seq%d: reading.\n", unit));*/
+ SEQ_DEBUG(printf("seq_read: unit %d, resid %d.\n", unit, buf->uio_resid));
if (unit >= NSEQ_MAX) {
- DEB(printf("seq_read: unit %d does not exist.\n", unit));
+ SEQ_DEBUG(printf("seq_read: unit %d does not exist.\n", unit));
return (ENXIO);
}
sd = get_seqdev_info(i_dev, &unit);
if (sd == NULL) {
- DEB(printf("seq_read: unit %d is not configured.\n", unit));
+ SEQ_DEBUG(printf("seq_read: unit %d is not configured.\n", unit));
return (ENXIO);
}
scp = sd->softc;
if ((scp->fflags & FREAD) == 0) {
- DEB(printf("seq_read: unit %d is not for reading.\n", unit));
+ SEQ_DEBUG(printf("seq_read: unit %d is not for reading.\n", unit));
return (EIO);
}
@@ -413,10 +557,13 @@ seq_read(dev_t i_dev, struct uio *buf, int flag)
/* Have we got the data to read? */
if ((sd->flags & SEQ_F_NBIO) != 0 && sd->midi_dbuf_in.rl == 0)
ret = EAGAIN;
- else
+ else {
+ if ((sd->flags & SEQ_F_NBIO) != 0 && len > sd->midi_dbuf_in.rl)
+ len = sd->midi_dbuf_in.rl;
ret = midibuf_seqread(&sd->midi_dbuf_in, uiobuf, len, &lenr,
sd->callback, sd, SEQ_CB_START | SEQ_CB_RD,
&sd->flagqueue_mtx);
+ }
mtx_unlock(&sd->flagqueue_mtx);
@@ -425,6 +572,8 @@ seq_read(dev_t i_dev, struct uio *buf, int flag)
free(uiobuf, M_DEVBUF);
+ SEQ_DEBUG(printf("seq_read: ret %d, resid %d.\n", ret, buf->uio_resid));
+
return (ret);
}
@@ -439,21 +588,21 @@ seq_write(dev_t i_dev, struct uio *buf, int flag)
unit = MIDIUNIT(i_dev);
- /*DEB(printf("seq%d: writing.\n", unit));*/
+ SEQ_DEBUG(printf("seq_write: unit %d, resid %d.\n", unit, buf->uio_resid));
if (unit >= NSEQ_MAX) {
- DEB(printf("seq_write: unit %d does not exist.\n", unit));
+ SEQ_DEBUG(printf("seq_write: unit %d does not exist.\n", unit));
return (ENXIO);
}
sd = get_seqdev_info(i_dev, &unit);
if (sd == NULL) {
- DEB(printf("seq_write: unit %d is not configured.\n", unit));
+ SEQ_DEBUG(printf("seq_write: unit %d is not configured.\n", unit));
return (ENXIO);
}
scp = sd->softc;
if ((scp->fflags & FWRITE) == 0) {
- DEB(printf("seq_write: unit %d is not for writing.\n", unit));
+ SEQ_DEBUG(printf("seq_write: unit %d is not for writing.\n", unit));
return (EIO);
}
@@ -466,6 +615,7 @@ seq_write(dev_t i_dev, struct uio *buf, int flag)
if (uiomove((caddr_t)event, 4, buf))
printf("seq_write: user memory mangled?\n");
ev_code = event[0];
+ SEQ_DEBUG(printf("seq_write: unit %d, event %s.\n", unit, midi_cmdname(ev_code, cmdtab_seqevent)));
/* Have a look at the event code. */
if (ev_code == SEQ_FULLSIZE) {
@@ -478,7 +628,7 @@ seq_write(dev_t i_dev, struct uio *buf, int flag)
if (ret != 0)
return (ret);
- DEB(printf("seq_write: loading a patch to the unit %d.\n", midiunit));
+ 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);
@@ -487,12 +637,10 @@ seq_write(dev_t i_dev, struct uio *buf, int flag)
if (ev_code >= 128) {
/* Some sort of an extended event. The size is eight bytes. */
-#if notyet
- if (scp->seq_mode == SEQ_2 && ev_code == SEQ_EXTENDED) {
- printf("seq%d: invalid level two event %x.\n", unit, ev_code);
+ if (scp->seq_mode == SND_DEV_MUSIC && ev_code == SEQ_EXTENDED) {
+ printf("seq_write: invalid level two event %x.\n", ev_code);
return (EINVAL);
}
-#endif /* notyet */
ev_size = 8;
if (count < ev_size) {
@@ -501,6 +649,7 @@ seq_write(dev_t i_dev, struct uio *buf, int flag)
if ((sd->flags & SEQ_F_WRITING) == 0)
sd->callback(sd, SEQ_CB_START | SEQ_CB_WR);
mtx_unlock(&sd->flagqueue_mtx);
+ buf->uio_resid += 4;
return (0);
}
@@ -509,25 +658,23 @@ seq_write(dev_t i_dev, struct uio *buf, int flag)
} else {
/* Not an extended event. The size is four bytes. */
-#if notyet
- if (scp->seq_mode == SEQ_2) {
- printf("seq%d: four byte event in level two mode.\n", unit);
+ if (scp->seq_mode == SND_DEV_MUSIC) {
+ printf("seq_write: four byte event in level two mode.\n");
return (EINVAL);
}
-#endif /* notyet */
ev_size = 4;
}
if (ev_code == SEQ_MIDIPUTC) {
/* An event passed to the midi device itself. */
midiunit = event[2];
mtx_lock(&sd->flagqueue_mtx);
- ret = lookup_mididev(scp, midiunit, LOOKUP_OPEN, &md);
+ ret = lookup_mididev_midi(scp, midiunit, LOOKUP_OPEN, &md);
mtx_unlock(&sd->flagqueue_mtx);
if (ret != 0)
return (ret);
}
- /*DEB(printf("seq_write: queueing event %d.\n", event[0]));*/
+ SEQ_DEBUG(printf("seq_write: queueing event %s.\n", midi_cmdname(event[0], cmdtab_seqevent)));
/* Now we queue the event. */
mtx_lock(&sd->flagqueue_mtx);
switch (seq_queue(scp, event)) {
@@ -536,12 +683,18 @@ seq_write(dev_t i_dev, struct uio *buf, int flag)
if ((sd->flags & SEQ_F_WRITING) == 0)
sd->callback(sd, SEQ_CB_START | SEQ_CB_WR);
mtx_unlock(&sd->flagqueue_mtx);
- return (0);
+ buf->uio_resid = count;
+ SEQ_DEBUG(printf("seq_write: resid %d.\n", buf->uio_resid));
+ if (count < countorg)
+ return (0);
+ return (EAGAIN);
case EINTR:
mtx_unlock(&sd->flagqueue_mtx);
+ SEQ_DEBUG(printf("seq_write: resid %d.\n", buf->uio_resid));
return (EINTR);
case ERESTART:
mtx_unlock(&sd->flagqueue_mtx);
+ SEQ_DEBUG(printf("seq_write: resid %d.\n", buf->uio_resid));
return (ERESTART);
}
mtx_unlock(&sd->flagqueue_mtx);
@@ -555,34 +708,35 @@ seq_write(dev_t i_dev, struct uio *buf, int flag)
sd->callback(sd, SEQ_CB_START | SEQ_CB_WR);
mtx_unlock(&sd->flagqueue_mtx);
+ SEQ_DEBUG(printf("seq_write: resid %d.\n", buf->uio_resid));
+
return (0);
}
int
seq_ioctl(dev_t i_dev, u_long cmd, caddr_t arg, int mode, struct thread *td)
{
- int unit, midiunit, ret, tmp, arg2;
+ int unit, midiunit, ret, tmp;
sc_p scp;
seqdev_info *sd;
mididev_info *md;
struct synth_info *synthinfo;
struct midi_info *midiinfo;
struct patmgr_info *patinfo;
- snd_sync_parm *syncparm;
struct seq_event_rec *event;
struct snd_size *sndsize;
unit = MIDIUNIT(i_dev);
- DEB(printf("seq%d: ioctlling, cmd 0x%x.\n", unit, (int)cmd));
+ SEQ_DEBUG(printf("seq_ioctl: unit %d, cmd %s.\n", unit, midi_cmdname(cmd, cmdtab_seqioctl)));
if (unit >= NSEQ_MAX) {
- DEB(printf("seq_ioctl: unit %d does not exist.\n", unit));
+ SEQ_DEBUG(printf("seq_ioctl: unit %d does not exist.\n", unit));
return (ENXIO);
}
sd = get_seqdev_info(i_dev, &unit);
if (sd == NULL) {
- DEB(printf("seq_ioctl: unit %d is not configured.\n", unit));
+ SEQ_DEBUG(printf("seq_ioctl: unit %d is not configured.\n", unit));
return (ENXIO);
}
scp = sd->softc;
@@ -595,11 +749,15 @@ seq_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 be written ? */
+ mtx_lock(&sd->flagqueue_mtx);
*(int *)arg = sd->midi_dbuf_out.fl;
+ mtx_unlock(&sd->flagqueue_mtx);
+ SEQ_DEBUG(printf("seq_ioctl: fl %d.\n", *(int *)arg));
break;
case AIOSSIZE: /* set the current blocksize */
sndsize = (struct snd_size *)arg;
+ SEQ_DEBUG(printf("seq_ioctl: play %d, rec %d.\n", sndsize->play_size, sndsize->rec_size));
mtx_lock(&sd->flagqueue_mtx);
if (sndsize->play_size <= sd->midi_dbuf_out.unit_size && sndsize->rec_size <= sd->midi_dbuf_in.unit_size) {
sd->midi_dbuf_out.blocksize = sd->midi_dbuf_out.unit_size;
@@ -636,6 +794,7 @@ seq_ioctl(dev_t i_dev, u_long cmd, caddr_t arg, int mode, struct thread *td)
sndsize->play_size = sd->midi_dbuf_out.blocksize;
sndsize->rec_size = sd->midi_dbuf_in.blocksize;
mtx_unlock(&sd->flagqueue_mtx);
+ SEQ_DEBUG(printf("seq_ioctl: play %d, rec %d.\n", sndsize->play_size, sndsize->rec_size));
ret = 0;
break;
@@ -650,13 +809,13 @@ seq_ioctl(dev_t i_dev, u_long cmd, caddr_t arg, int mode, struct thread *td)
/* Pass the ioctl to the midi devices. */
TAILQ_FOREACH(md, &scp->midi_open, md_linkseq) {
- if ((md->flags & MIDI_F_WRITING) != 0) {
- arg2 = *(int *)arg;
- midi_ioctl(MIDIMKDEV(major(i_dev), md->unit, SND_DEV_MIDIN), cmd, (caddr_t)&arg2, mode, td);
- }
+ if ((md->flags & MIDI_F_WRITING) != 0)
+ midi_ioctl(MIDIMKDEV(major(i_dev), md->unit, SND_DEV_MIDIN), cmd, (caddr_t)arg, mode, td);
}
+ mtx_lock(&sd->flagqueue_mtx);
*(int *)arg = sd->midi_dbuf_out.rl;
+ mtx_unlock(&sd->flagqueue_mtx);
}
else if (*(int *)arg == AIOSYNC_CAPTURE) {
@@ -667,27 +826,38 @@ seq_ioctl(dev_t i_dev, u_long cmd, caddr_t arg, int mode, struct thread *td)
/* Pass the ioctl to the midi devices. */
TAILQ_FOREACH(md, &scp->midi_open, md_linkseq) {
- if ((md->flags & MIDI_F_WRITING) != 0) {
- arg2 = *(int *)arg;
- midi_ioctl(MIDIMKDEV(major(i_dev), md->unit, SND_DEV_MIDIN), cmd, (caddr_t)&arg2, mode, td);
- }
+ if ((md->flags & MIDI_F_WRITING) != 0)
+ midi_ioctl(MIDIMKDEV(major(i_dev), md->unit, SND_DEV_MIDIN), cmd, (caddr_t)arg, mode, td);
}
+ mtx_lock(&sd->flagqueue_mtx);
*(int *)arg = sd->midi_dbuf_in.rl;
+ mtx_unlock(&sd->flagqueue_mtx);
}
ret = 0;
break;
case AIOSYNC:
- syncparm = (snd_sync_parm *)arg;
- scp->sync_parm = *syncparm;
+ mtx_lock(&sd->flagqueue_mtx);
+ scp->sync_parm = *(snd_sync_parm *)arg;
+ mtx_unlock(&sd->flagqueue_mtx);
/* XXX Should select(2) against us watch the blocksize, or sync_parm? */
ret = 0;
break;
+ case FIONBIO: /* set/clear non-blocking i/o */
+ mtx_lock(&sd->flagqueue_mtx);
+ if (*(int *)arg == 0)
+ sd->flags &= ~SEQ_F_NBIO ;
+ else
+ sd->flags |= SEQ_F_NBIO ;
+ mtx_unlock(&sd->flagqueue_mtx);
+ MIDI_DEBUG(printf("seq_ioctl: arg %d.\n", *(int *)arg));
+ break ;
+
case SNDCTL_TMR_TIMEBASE:
case SNDCTL_TMR_TEMPO:
case SNDCTL_TMR_START:
@@ -695,34 +865,40 @@ seq_ioctl(dev_t i_dev, u_long cmd, caddr_t arg, int mode, struct thread *td)
case SNDCTL_TMR_CONTINUE:
case SNDCTL_TMR_METRONOME:
case SNDCTL_TMR_SOURCE:
-#if notyet
- if (scp->seq_mode != SEQ_2) {
+ mtx_lock(&sd->flagqueue_mtx);
+ if (scp->seq_mode != SND_DEV_MUSIC) {
ret = EINVAL;
+ mtx_unlock(&sd->flagqueue_mtx);
break;
}
- ret = tmr->ioctl(tmr_no, cmd, arg);
-#endif /* notyet */
+ mtx_unlock(&sd->flagqueue_mtx);
+ /* XXX We should adopt am sx to protect scp->timer */
+ ret = scp->timer->ioctl(scp->timer, cmd, arg, mode, td);
break;
case SNDCTL_TMR_SELECT:
-#if notyet
- if (scp->seq_mode != SEQ_2) {
+ mtx_lock(&sd->flagqueue_mtx);
+ if (scp->seq_mode != SND_DEV_MUSIC) {
ret = EINVAL;
+ mtx_unlock(&sd->flagqueue_mtx);
break;
}
-#endif /* notyet */
+ mtx_unlock(&sd->flagqueue_mtx);
scp->pending_timer = *(int *)arg;
- if (scp->pending_timer < 0 || scp->pending_timer >= /*NTIMER*/1) {
+ mtx_lock(&sd->flagqueue_mtx);
+ if (scp->pending_timer < 0) {
scp->pending_timer = -1;
ret = EINVAL;
+ mtx_unlock(&sd->flagqueue_mtx);
break;
}
- *(int *)arg = scp->pending_timer;
+ mtx_unlock(&sd->flagqueue_mtx);
+ SEQ_DEBUG(printf("seq_ioctl: new timer %d.\n", *(int *)arg));
ret = 0;
break;
case SNDCTL_SEQ_PANIC:
- mtx_lock(&scp->devinfo->flagqueue_mtx);
+ mtx_lock(&sd->flagqueue_mtx);
seq_panic(scp);
- mtx_unlock(&scp->devinfo->flagqueue_mtx);
+ mtx_unlock(&sd->flagqueue_mtx);
ret = 0;
break;
case SNDCTL_SEQ_SYNC:
@@ -741,73 +917,91 @@ seq_ioctl(dev_t i_dev, u_long cmd, caddr_t arg, int mode, struct thread *td)
ret = 0;
break;
case SNDCTL_SEQ_TESTMIDI:
- midiunit = *(int *)arg;
mtx_lock(&sd->flagqueue_mtx);
- ret = lookup_mididev(scp, midiunit, LOOKUP_OPEN, &md);
+ ret = lookup_mididev_midi(scp, *(int *)arg, LOOKUP_OPEN, &md);
mtx_unlock(&sd->flagqueue_mtx);
break;
case SNDCTL_SEQ_GETINCOUNT:
if (mode == O_WRONLY)
*(int *)arg = 0;
- else
+ else {
+ mtx_lock(&sd->flagqueue_mtx);
*(int *)arg = sd->midi_dbuf_in.rl;
+ mtx_unlock(&sd->flagqueue_mtx);
+ 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
+ else {
+ mtx_lock(&sd->flagqueue_mtx);
*(int *)arg = sd->midi_dbuf_out.fl;
+ mtx_unlock(&sd->flagqueue_mtx);
+ SEQ_DEBUG(printf("seq_ioctl: outcount %d.\n", *(int *)arg));
+ }
ret = 0;
break;
case SNDCTL_SEQ_CTRLRATE:
-#if notyet
- if (scp->seq_mode != SEQ_2) {
- ret = tmr->ioctl(tmr_no, cmd, arg);
+ mtx_lock(&sd->flagqueue_mtx);
+ if (scp->seq_mode == SND_DEV_MUSIC) {
+ mtx_unlock(&sd->flagqueue_mtx);
+ ret = scp->timer->ioctl(scp->timer, cmd, arg, mode, td);
break;
}
-#endif /* notyet */
+ mtx_unlock(&sd->flagqueue_mtx);
if (*(int *)arg != 0) {
ret = EINVAL;
break;
}
*(int *)arg = hz;
+ SEQ_DEBUG(printf("seq_ioctl: ctrlrate %d.\n", *(int *)arg));
ret = 0;
break;
case SNDCTL_SEQ_RESETSAMPLES:
- midiunit = *(int *)arg;
mtx_lock(&sd->flagqueue_mtx);
- ret = lookup_mididev(scp, midiunit, LOOKUP_OPEN, &md);
+ ret = lookup_mididev(scp, *(int *)arg, LOOKUP_OPEN, &md);
mtx_unlock(&sd->flagqueue_mtx);
if (ret != 0)
break;
- ret = midi_ioctl(MIDIMKDEV(major(i_dev), midiunit, SND_DEV_MIDIN), cmd, arg, mode, td);
+ ret = midi_ioctl(MIDIMKDEV(major(i_dev), *(int *)arg, SND_DEV_MIDIN), cmd, arg, mode, td);
break;
case SNDCTL_SEQ_NRSYNTHS:
- *(int *)arg = mididev_info_number();
+ mtx_lock(&sd->flagqueue_mtx);
+ if (scp->seq_mode == SND_DEV_MUSIC)
+ *(int *)arg = mididev_synth_number() + mididev_midi_number();
+ else
+ *(int *)arg = mididev_synth_number();
+ mtx_unlock(&sd->flagqueue_mtx);
+ SEQ_DEBUG(printf("seq_ioctl: synths %d.\n", *(int *)arg));
ret = 0;
break;
case SNDCTL_SEQ_NRMIDIS:
- *(int *)arg = mididev_info_number();
+ mtx_lock(&sd->flagqueue_mtx);
+ if (scp->seq_mode == SND_DEV_MUSIC)
+ *(int *)arg = 0;
+ else
+ *(int *)arg = mididev_midi_number();
+ mtx_unlock(&sd->flagqueue_mtx);
+ SEQ_DEBUG(printf("seq_ioctl: midis %d.\n", *(int *)arg));
ret = 0;
break;
case SNDCTL_SYNTH_MEMAVL:
- midiunit = *(int *)arg;
mtx_lock(&sd->flagqueue_mtx);
- ret = lookup_mididev(scp, midiunit, LOOKUP_OPEN, &md);
+ ret = lookup_mididev(scp, *(int *)arg, LOOKUP_OPEN, &md);
mtx_unlock(&sd->flagqueue_mtx);
if (ret != 0)
break;
- ret = midi_ioctl(MIDIMKDEV(major(i_dev), midiunit, SND_DEV_MIDIN), cmd, arg, mode, td);
+ ret = midi_ioctl(MIDIMKDEV(major(i_dev), *(int *)arg, SND_DEV_MIDIN), cmd, arg, mode, td);
break;
case SNDCTL_FM_4OP_ENABLE:
- midiunit = *(int *)arg;
mtx_lock(&sd->flagqueue_mtx);
- ret = lookup_mididev(scp, midiunit, LOOKUP_OPEN, &md);
+ ret = lookup_mididev(scp, *(int *)arg, LOOKUP_OPEN, &md);
mtx_unlock(&sd->flagqueue_mtx);
if (ret != 0)
break;
- ret = midi_ioctl(MIDIMKDEV(major(i_dev), midiunit, SND_DEV_MIDIN), cmd, arg, mode, td);
+ ret = midi_ioctl(MIDIMKDEV(major(i_dev), *(int *)arg, SND_DEV_MIDIN), cmd, arg, mode, td);
break;
case SNDCTL_SYNTH_INFO:
synthinfo = (struct synth_info *)arg;
@@ -829,7 +1023,7 @@ seq_ioctl(dev_t i_dev, u_long cmd, caddr_t arg, int mode, struct thread *td)
midiinfo = (struct midi_info *)arg;
midiunit = midiinfo->device;
mtx_lock(&sd->flagqueue_mtx);
- ret = lookup_mididev(scp, midiunit, LOOKUP_OPEN, &md);
+ ret = lookup_mididev_midi(scp, midiunit, LOOKUP_OPEN, &md);
mtx_unlock(&sd->flagqueue_mtx);
if (ret != 0)
break;
@@ -856,21 +1050,26 @@ seq_ioctl(dev_t i_dev, u_long cmd, caddr_t arg, int mode, struct thread *td)
ret = midi_ioctl(MIDIMKDEV(major(i_dev), midiunit, SND_DEV_MIDIN), cmd, arg, mode, td);
break;
case SNDCTL_SEQ_THRESHOLD:
- tmp = *(int *)arg;
- RANGE(tmp, 1, sd->midi_dbuf_out.bufsize - 1);
- scp->output_threshould = tmp;
+ mtx_lock(&sd->flagqueue_mtx);
+ RANGE(*(int *)arg, 1, sd->midi_dbuf_out.bufsize - 1);
+ scp->output_threshould = *(int *)arg;
+ mtx_unlock(&sd->flagqueue_mtx);
+ SEQ_DEBUG(printf("seq_ioctl: threshold %d.\n", *(int *)arg));
ret = 0;
break;
case SNDCTL_MIDI_PRETIME:
tmp = *(int *)arg;
if (tmp < 0)
tmp = 0;
- tmp = (hz * tmp) / 10;
- scp->pre_event_timeout = tmp;
+ mtx_lock(&sd->flagqueue_mtx);
+ scp->pre_event_timeout = (hz * tmp) / 10;
+ *(int *)arg = scp->pre_event_timeout;
+ mtx_unlock(&sd->flagqueue_mtx);
+ SEQ_DEBUG(printf("seq_ioctl: pretime %d.\n", *(int *)arg));
ret = 0;
break;
default:
- if (scp->fflags == O_RDONLY) {
+ if ((scp->fflags & O_ACCMODE) == FREAD) {
ret = EIO;
break;
}
@@ -895,15 +1094,15 @@ seq_poll(dev_t i_dev, int events, struct thread *td)
unit = MIDIUNIT(i_dev);
- DEB(printf("seq%d: polling.\n", unit));
+ SEQ_DEBUG(printf("seq_poll: unit %d.\n", unit));
if (unit >= NSEQ_MAX) {
- DEB(printf("seq_poll: unit %d does not exist.\n", unit));
+ SEQ_DEBUG(printf("seq_poll: unit %d does not exist.\n", unit));
return (ENXIO);
}
sd = get_seqdev_info(i_dev, &unit);
if (sd == NULL) {
- DEB(printf("seq_poll: unit %d is not configured.\n", unit));
+ SEQ_DEBUG(printf("seq_poll: unit %d is not configured.\n", unit));
return (ENXIO);
}
scp = sd->softc;
@@ -981,10 +1180,10 @@ seq_callback(void *d, int reason)
sd = (seqdev_info *)d;
- /*DEB(printf("seq_callback: reason 0x%x.\n", reason));*/
+ SEQ_DEBUG(printf("seq_callback: reason 0x%x.\n", reason));
if (sd == NULL) {
- DEB(printf("seq_callback: device not configured.\n"));
+ SEQ_DEBUG(printf("seq_callback: device not configured.\n"));
return (ENXIO);
}
scp = sd->softc;
@@ -1039,7 +1238,7 @@ seq_queue(sc_p scp, u_char *note)
mtx_assert(&sd->flagqueue_mtx, MA_OWNED);
- /*DEB(printf("seq%d: queueing.\n", unit));*/
+ SEQ_DEBUG(printf("seq_queue: unit %d.\n", unit));
if ((sd->flags & SEQ_F_INSYNC) != 0)
cv_wait(&sd->insync_cv, &sd->flagqueue_mtx);
@@ -1126,9 +1325,12 @@ seq_playevent(sc_p scp, u_char *event)
if (ret != 0)
return (MORE);
+ SEQ_DEBUG(printf("seq_playevent: unit %d, event %s.\n", sd->unit, midi_cmdname(event[0], cmdtab_seqevent)));
+
switch(event[0]) {
case SEQ_NOTEOFF:
mtx_unlock(&sd->flagqueue_mtx);
+ SEQ_DEBUG(printf("seq_playevent: chn %d, note %d, vel %d.\n", event[1], event[2], event[3]));
if (md->synth.killnote(md, event[1], 255, event[3]) == EAGAIN) {
mtx_lock(&sd->flagqueue_mtx);
ret = QUEUEFULL;
@@ -1139,6 +1341,7 @@ seq_playevent(sc_p scp, u_char *event)
break;
case SEQ_NOTEON:
mtx_unlock(&sd->flagqueue_mtx);
+ SEQ_DEBUG(printf("seq_playevent: chn %d, note %d, vel %d, aux %d.\n", event[1], event[2], event[3], event[4]));
if ((event[4] < 128 || event[4] == 255) && md->synth.startnote(md, event[1], event[2], event[3]) == EAGAIN) {
mtx_lock(&sd->flagqueue_mtx);
ret = QUEUEFULL;
@@ -1152,6 +1355,7 @@ seq_playevent(sc_p scp, u_char *event)
/* Extract the delay. */
delay = (long *)event;
*delay = (*delay >> 8) & 0xffffff;
+ SEQ_DEBUG(printf("seq_playevent: delay %ld.\n", *delay));
if (*delay > 0) {
/* Arm the timer. */
sd->flags |= SEQ_F_WRITING;
@@ -1163,6 +1367,7 @@ seq_playevent(sc_p scp, u_char *event)
ret = MORE;
break;
case SEQ_PGMCHANGE:
+ SEQ_DEBUG(printf("seq_playevent: chn %d, instr %d.\n", event[1], event[2]));
mtx_unlock(&sd->flagqueue_mtx);
if (md->synth.setinstr(md, event[1], event[2]) == EAGAIN) {
mtx_lock(&sd->flagqueue_mtx);
@@ -1181,8 +1386,9 @@ seq_playevent(sc_p scp, u_char *event)
ret = MORE;
break;
case SEQ_MIDIPUTC:
+ SEQ_DEBUG(printf("seq_playevent: data 0x%02x, unit %d.\n", event[1], event[2]));
/* Pass through to the midi device. */
- ret = lookup_mididev(scp, event[2], LOOKUP_OPEN, &md);
+ ret = lookup_mididev_midi(scp, event[2], LOOKUP_OPEN, &md);
if (ret != 0) {
ret = MORE;
break;
@@ -1243,12 +1449,13 @@ seq_playevent(sc_p scp, u_char *event)
switch (ret) {
case QUEUEFULL:
- /*DEB(printf("seq_playevent: the queue is full.\n"));*/
+ SEQ_DEBUG(printf("seq_playevent: the queue is full.\n"));
/* The queue was full. Try again on the interrupt by the midi device. */
sd->flags |= SEQ_F_WRITING;
scp->queueout_pending = 1;
break;
case TIMERARMED:
+ SEQ_DEBUG(printf("seq_playevent: armed timer.\n"));
sd->flags |= SEQ_F_WRITING;
/* FALLTHRU */
case MORE:
@@ -1273,7 +1480,7 @@ seq_requesttimer(sc_p scp, int delay)
{
u_long cur_time, rel_base;
- /*DEB(printf("seq%d: requested timer at delay of %d.\n", unit, delay));*/
+ SEQ_DEBUG(printf("seq_requesttimer: unit %d, delay %d.\n", scp->devinfo->unit, delay));
mtx_assert(&scp->devinfo->flagqueue_mtx, MA_OWNED);
@@ -1316,7 +1523,7 @@ seq_requesttimer(sc_p scp, int delay)
static void
seq_stoptimer(sc_p scp)
{
- /*DEB(printf("seq%d: stopping timer.\n", unit));*/
+ SEQ_DEBUG(printf("seq_stoptimer: unit %d.\n", scp->devinfo->unit));
mtx_assert(&scp->devinfo->flagqueue_mtx, MA_OWNED);
@@ -1340,8 +1547,8 @@ seq_midiinput(sc_p scp, mididev_info *md)
unit = sd->unit;
/* Can this midi device interrupt for input? */
- midiunit = md->unit;
- if (lookup_mididev(scp, midiunit, LOOKUP_EXIST, NULL) != 0)
+ midiunit = md->midiunit;
+ if (lookup_mididev_midi(scp, midiunit, LOOKUP_EXIST, NULL) != 0)
return;
if ((md->flags & MIDI_F_READING) != 0 && md->intrarg == sd) {
@@ -1354,6 +1561,7 @@ seq_midiinput(sc_p scp, mididev_info *md)
seq_copytoinput(scp, (u_char *)&tstamp, 4);
scp->prev_input_time = tstamp;
}
+ bzero(event, sizeof(event));
event[0] = SEQ_MIDIPUTC;
event[2] = midiunit;
event[3] = 0;
@@ -1362,17 +1570,26 @@ seq_midiinput(sc_p scp, mididev_info *md)
}
}
-static int
-seq_copytoinput(sc_p scp, u_char *event, int len)
+int
+seq_copytoinput(void *arg, u_char *event, int len)
{
int ret, leni;
+ sc_p scp;
seqdev_info *sd;
+ scp = arg;
sd = scp->devinfo;
mtx_assert(&sd->flagqueue_mtx, MA_OWNED);
+ if (len != 4 && len != 8)
+ return (EINVAL);
+ if (scp->seq_mode == SND_DEV_MUSIC && len != 8)
+ return (EINVAL);
+
ret = midibuf_input_intr(&sd->midi_dbuf_in, event, len, &leni);
+ if (ret == EAGAIN)
+ ret = 0;
return (ret);
}
@@ -1392,9 +1609,12 @@ seq_extended(sc_p scp, u_char *event)
if (lookup_mididev(scp, event[2], LOOKUP_OPEN, &md) != 0)
return (MORE);
+ SEQ_DEBUG(printf("seq_extended: unit %d, event %s, midiunit %d.\n", unit, midi_cmdname(event[1], cmdtab_seqevent), event[2]));
+
switch (event[1]) {
case SEQ_NOTEOFF:
mtx_unlock(&sd->flagqueue_mtx);
+ SEQ_DEBUG(printf("seq_extended: chn %d, note %d, vel %d.\n", event[3], event[4], event[5]));
if (md->synth.killnote(md, event[3], event[4], event[5]) == EAGAIN) {
mtx_lock(&sd->flagqueue_mtx);
return (QUEUEFULL);
@@ -1403,6 +1623,7 @@ seq_extended(sc_p scp, u_char *event)
break;
case SEQ_NOTEON:
mtx_unlock(&sd->flagqueue_mtx);
+ SEQ_DEBUG(printf("seq_extended: chn %d, note %d, vel %d.\n", event[3], event[4], event[5]));
if ((event[4] < 128 || event[4] == 255) && md->synth.startnote(md, event[3], event[4], event[5]) == EAGAIN) {
mtx_lock(&sd->flagqueue_mtx);
return (QUEUEFULL);
@@ -1411,6 +1632,7 @@ seq_extended(sc_p scp, u_char *event)
break;
case SEQ_PGMCHANGE:
mtx_unlock(&sd->flagqueue_mtx);
+ SEQ_DEBUG(printf("seq_extended: chn %d, instr %d.\n", event[3], event[4]));
if (md->synth.setinstr(md, event[3], event[4]) == EAGAIN) {
mtx_lock(&sd->flagqueue_mtx);
return (QUEUEFULL);
@@ -1419,6 +1641,7 @@ seq_extended(sc_p scp, u_char *event)
break;
case SEQ_AFTERTOUCH:
mtx_unlock(&sd->flagqueue_mtx);
+ SEQ_DEBUG(printf("seq_extended: chn %d, press %d.\n", event[3], event[4]));
if (md->synth.aftertouch(md, event[3], event[4]) == EAGAIN) {
mtx_lock(&sd->flagqueue_mtx);
return (QUEUEFULL);
@@ -1427,6 +1650,7 @@ seq_extended(sc_p scp, u_char *event)
break;
case SEQ_BALANCE:
mtx_unlock(&sd->flagqueue_mtx);
+ SEQ_DEBUG(printf("seq_extended: chn %d, pan %d.\n", event[3], event[4]));
if (md->synth.panning(md, event[3], (char)event[4]) == EAGAIN) {
mtx_lock(&sd->flagqueue_mtx);
return (QUEUEFULL);
@@ -1435,6 +1659,7 @@ seq_extended(sc_p scp, u_char *event)
break;
case SEQ_CONTROLLER:
mtx_unlock(&sd->flagqueue_mtx);
+ SEQ_DEBUG(printf("seq_extended: chn %d, ctrlnum %d, val %d.\n", event[3], event[4], *(short *)&event[5]));
if (md->synth.controller(md, event[3], event[4], *(short *)&event[5]) == EAGAIN) {
mtx_lock(&sd->flagqueue_mtx);
return (QUEUEFULL);
@@ -1443,6 +1668,7 @@ seq_extended(sc_p scp, u_char *event)
break;
case SEQ_VOLMODE:
mtx_unlock(&sd->flagqueue_mtx);
+ SEQ_DEBUG(printf("seq_extended: mode %d.\n", event[3]));
if (md->synth.volumemethod != NULL && md->synth.volumemethod(md, event[3]) == EAGAIN) {
mtx_lock(&sd->flagqueue_mtx);
return (QUEUEFULL);
@@ -1476,24 +1702,27 @@ seq_chnvoice(sc_p scp, u_char *event)
if (lookup_mididev(scp, dev, LOOKUP_OPEN, &md) != 0)
return (MORE);
-#if notyet
- if (scp->seq_mode == SEQ_2 && md->synth.allocvoice != NULL)
+ SEQ_DEBUG(printf("seq_chnvoice: unit %d, dev %d, cmd %s, chn %d, note %d, parm %d.\n",
+ sd->unit,
+ dev,
+ midi_cmdname(cmd, cmdtab_seqcv),
+ chn,
+ note,
+ parm));
+
+ if (scp->seq_mode == SND_DEV_MUSIC && md->synth.allocvoice != NULL)
voice = seq_allocvoice(scp, md, chn, note);
-#endif /* notyet */
switch (cmd) {
case MIDI_NOTEON:
if (note < 128 || note == 255) {
-#if notyet
- if (voice == -1 && scp->seq_mode == SEQ_2 && md->synth.allocvoice)
+ if (voice == -1 && scp->seq_mode == SND_DEV_MUSIC && md->synth.allocvoice)
/* This is an internal synthesizer. (FM, GUS, etc) */
if ((voice = seq_allocvoice(scp, md, chn, note)) == EAGAIN)
return (QUEUEFULL);
-#endif /* notyet */
if (voice == -1)
voice = chn;
-#if notyet
- if (scp->seq_mode == SEQ_2 && chn == 9) {
+ if (scp->seq_mode == SND_DEV_MUSIC && chn == 9) {
/* This channel is a percussion. The note number is the patch number. */
mtx_unlock(&sd->flagqueue_mtx);
if (md->synth.setinstr(md, voice, 128 + note) == EAGAIN) {
@@ -1504,7 +1733,7 @@ seq_chnvoice(sc_p scp, u_char *event)
note = 60; /* Middle C. */
}
- if (scp->seq_mode == SEQ_2) {
+ if (scp->seq_mode == SND_DEV_MUSIC) {
mtx_unlock(&sd->flagqueue_mtx);
if (md->synth.setupvoice(md, voice, chn) == EAGAIN) {
mtx_lock(&sd->flagqueue_mtx);
@@ -1512,7 +1741,6 @@ seq_chnvoice(sc_p scp, u_char *event)
}
mtx_lock(&sd->flagqueue_mtx);
}
-#endif /* notyet */
mtx_unlock(&sd->flagqueue_mtx);
if (md->synth.startnote(md, voice, note, parm) == EAGAIN) {
mtx_lock(&sd->flagqueue_mtx);
@@ -1593,7 +1821,7 @@ seq_allocvoice(sc_p scp, mididev_info *md, int chn, int note)
static int
seq_chncommon(sc_p scp, u_char *event)
{
- int unit/*, i, val, key*/;
+ int unit, i, val, key;
u_short w14;
u_char dev, cmd, chn, p1;
seqdev_info *sd;
@@ -1613,21 +1841,29 @@ seq_chncommon(sc_p scp, u_char *event)
if (lookup_mididev(scp, dev, LOOKUP_OPEN, &md) != 0)
return (MORE);
+ SEQ_DEBUG(printf("seq_chnvoice: unit %d, dev %d, cmd %s, chn %d, p1 %d, w14 %d.\n",
+ sd->unit,
+ dev,
+ midi_cmdname(cmd, cmdtab_seqccmn),
+ chn,
+ p1,
+ w14));
+
switch (cmd) {
case MIDI_PGM_CHANGE:
-#if notyet
- if (scp->seq_mode == SEQ_2) {
+ if (scp->seq_mode == SND_DEV_MUSIC) {
mtx_lock(&md->synth.vc_mtx);
md->synth.chn_info[chn].pgm_num = p1;
mtx_unlock(&md->synth.vc_mtx);
mtx_unlock(&sd->flagqueue_mtx);
- if (md->synth.setinstr(md, chn, p1) == EAGAIN) {
- mtx_lock(&sd->flagqueue_mtx);
- return (QUEUEFULL);
+ if (md->midiunit >= 0) {
+ if (md->synth.setinstr(md, chn, p1) == EAGAIN) {
+ mtx_lock(&sd->flagqueue_mtx);
+ return (QUEUEFULL);
+ }
}
mtx_lock(&sd->flagqueue_mtx);
} else {
-#endif /* notyet */
/* For Mode 1. */
mtx_unlock(&sd->flagqueue_mtx);
if (md->synth.setinstr(md, chn, p1) == EAGAIN) {
@@ -1635,44 +1871,50 @@ seq_chncommon(sc_p scp, u_char *event)
return (QUEUEFULL);
}
mtx_lock(&sd->flagqueue_mtx);
-#if notyet
}
-#endif /* notyet */
break;
case MIDI_CTL_CHANGE:
/* mtx_lock(&md->giant); */
-#if notyet
- if (scp->seq_mode == SEQ_2) {
+ if (scp->seq_mode == SND_DEV_MUSIC) {
if (chn < 16 && p1 < 128) {
mtx_lock(&md->synth.vc_mtx);
md->synth.chn_info[chn].controllers[p1] = w14 & 0x7f;
if (p1 < 32)
/* We have set the MSB, clear the LSB. */
md->synth.chn_info[chn].controllers[p1 + 32] = 0;
- val = w14 & 0x7f;
- if (p1 < 64) {
- /* Combine the MSB and the LSB. */
- val = ((md->synth.chn_info[chn].controllers[p1 & ~32] & 0x7f) << 7)
- | (md->synth.chn_info[chn].controllers[p1 | 32] & 0x7f);
- p1 &= ~32;
- }
- /* 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(&sd->flagqueue_mtx);
- if (md->synth.controller(md, i, p1, val) == EAGAIN) {
+ if (md->midiunit >= 0) {
+ val = w14 & 0x7f;
+ if (p1 < 64) {
+ /* Combine the MSB and the LSB. */
+ val = ((md->synth.chn_info[chn].controllers[p1 & ~32] & 0x7f) << 7)
+ | (md->synth.chn_info[chn].controllers[p1 | 32] & 0x7f);
+ p1 &= ~32;
+ }
+ /* 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(&sd->flagqueue_mtx);
+ if (md->synth.controller(md, i, p1, val) == EAGAIN) {
+ mtx_lock(&sd->flagqueue_mtx);
+ return (QUEUEFULL);
+ }
mtx_lock(&sd->flagqueue_mtx);
- return (QUEUEFULL);
+ mtx_lock(&md->synth.vc_mtx);
}
+ mtx_unlock(&md->synth.vc_mtx);
+ } else {
+ mtx_unlock(&md->synth.vc_mtx);
+ mtx_unlock(&sd->flagqueue_mtx);
+ if (md->synth.controller(md, chn, p1, w14) == EAGAIN) {
mtx_lock(&sd->flagqueue_mtx);
- mtx_lock(&md->synth.vc_mtx);
+ return (QUEUEFULL);
}
- mtx_unlock(&md->synth.vc_mtx);
+ mtx_lock(&sd->flagqueue_mtx);
+ }
}
} else {
-#endif /* notyet */
/* For Mode 1. */
mtx_unlock(&sd->flagqueue_mtx);
if (md->synth.controller(md, chn, p1, w14) == EAGAIN) {
@@ -1680,31 +1922,35 @@ seq_chncommon(sc_p scp, u_char *event)
return (QUEUEFULL);
}
mtx_lock(&sd->flagqueue_mtx);
-#if notyet
}
-#endif /* notyet */
break;
case MIDI_PITCH_BEND:
-#if notyet
- if (scp->seq_mode == SEQ_2) {
+ if (scp->seq_mode == SND_DEV_MUSIC) {
mtx_lock(&md->synth.vc_mtx);
md->synth.chn_info[chn].bender_value = w14;
- /* 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(&sd->flagqueue_mtx);
- if (md->synth.bender(md, i, w14) == EAGAIN) {
+ 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(&sd->flagqueue_mtx);
+ if (md->synth.bender(md, i, w14) == EAGAIN) {
+ mtx_lock(&sd->flagqueue_mtx);
+ return (QUEUEFULL);
+ }
mtx_lock(&sd->flagqueue_mtx);
- return (QUEUEFULL);
}
+ } else {
+ mtx_unlock(&md->synth.vc_mtx);
+ mtx_unlock(&sd->flagqueue_mtx);
+ if (md->synth.bender(md, chn, w14) == EAGAIN) {
mtx_lock(&sd->flagqueue_mtx);
- mtx_lock(&md->synth.vc_mtx);
+ return (QUEUEFULL);
}
- mtx_unlock(&md->synth.vc_mtx);
+ mtx_lock(&sd->flagqueue_mtx);
+ }
} else {
-#endif /* notyet */
/* For Mode 1. */
mtx_unlock(&sd->flagqueue_mtx);
if (md->synth.bender(md, chn, w14) == EAGAIN) {
@@ -1712,9 +1958,7 @@ seq_chncommon(sc_p scp, u_char *event)
return (QUEUEFULL);
}
mtx_lock(&sd->flagqueue_mtx);
-#if notyet
}
-#endif /* notyet */
break;
}
@@ -1724,7 +1968,7 @@ seq_chncommon(sc_p scp, u_char *event)
static int
seq_timing(sc_p scp, u_char *event)
{
- int unit/*, ret*/;
+ int unit, ret;
long parm;
seqdev_info *sd;
@@ -1735,10 +1979,17 @@ seq_timing(sc_p scp, u_char *event)
parm = *(long *)&event[4];
-#if notyet
- if (scp->seq_mode == SEQ_2 && (ret = tmr->event(tmr_no, event)) == TIMERARMED)
+ if (scp->seq_mode == SND_DEV_MUSIC) {
+ ret = scp->timer->event(scp->timer, event);
+ if (ret == TIMERARMED)
+ sd->flags |= SEQ_F_WRITING;
return (ret);
-#endif /* notyet */
+ }
+
+ SEQ_DEBUG(printf("seq_timing: unit %d, cmd %s, parm %lu.\n",
+ unit, midi_cmdname(event[1], cmdtab_timer), parm));
+
+ ret = MORE;
switch (event[1]) {
case TMR_WAIT_REL:
parm += scp->prev_event_time;
@@ -1747,7 +1998,7 @@ seq_timing(sc_p scp, u_char *event)
if (parm > 0) {
sd->flags |= SEQ_F_WRITING;
if (seq_requesttimer(scp, parm))
- return (TIMERARMED);
+ ret = TIMERARMED;
}
break;
case TMR_START:
@@ -1763,20 +2014,19 @@ seq_timing(sc_p scp, u_char *event)
case TMR_TEMPO:
break;
case TMR_ECHO:
-#if notyet
- if (scp->seq_mode == SEQ_2)
+ if (scp->seq_mode == SND_DEV_MUSIC)
seq_copytoinput(scp, event, 8);
else {
-#endif /* notyet */
parm = (parm << 8 | SEQ_ECHO);
seq_copytoinput(scp, (u_char *)&parm, 4);
-#if notyet
}
-#endif /* notyet */
break;
}
- return (MORE);
+ SEQ_DEBUG(printf("seq_timing: timer %s.\n",
+ ret == TIMERARMED ? "armed" : "not armed"));
+
+ return (ret);
}
static int
@@ -1831,7 +2081,7 @@ seq_sysex(sc_p scp, u_char *event)
return (MORE);
}
-static void
+void
seq_timer(void *arg)
{
sc_p scp;
@@ -1840,7 +2090,7 @@ seq_timer(void *arg)
scp = arg;
sd = scp->devinfo;
- /*DEB(printf("seq_timer: timer fired.\n"));*/
+ SEQ_DEBUG(printf("seq_timer: unit %d, timer fired.\n", sd->unit));
/* Record the current timestamp. */
mtx_lock(&sd->flagqueue_mtx);
@@ -1855,13 +2105,13 @@ seq_timer(void *arg)
static int
seq_openmidi(sc_p scp, mididev_info *md, int flags, int mode, struct thread *td)
{
- int midiunit, err, insync;
+ int midiunit, err, insync, chn;
mtx_assert(&scp->devinfo->flagqueue_mtx, MA_OWNED);
midiunit = md->unit;
- DEB(printf("seq_openmidi: opening midi unit %d.\n", midiunit));
+ SEQ_DEBUG(printf("seq_openmidi: opening midi unit %d.\n", midiunit));
err = midi_open(MIDIMKDEV(MIDI_CDEV_MAJOR, midiunit, SND_DEV_MIDIN), flags, mode, td);
if (err != 0) {
@@ -1874,6 +2124,13 @@ seq_openmidi(sc_p scp, mididev_info *md, int flags, int mode, struct thread *td)
md->intrarg = scp->devinfo;
mtx_unlock(&md->flagqueue_mtx);
md->synth.sysex_state = 0;
+ if (scp->seq_mode == SND_DEV_MUSIC) {
+ for (chn = 0 ; chn < 16 ; chn++) {
+ md->synth.chn_info[chn].pgm_num = 0;
+ md->synth.reset(md);
+ md->synth.chn_info[chn].bender_value = (1 << 7);
+ }
+ }
mtx_unlock(&md->synth.status_mtx);
insync = 0;
@@ -1898,12 +2155,12 @@ seq_closemidi(sc_p scp, mididev_info *md, int flags, int mode, struct thread *td
mtx_assert(&scp->devinfo->flagqueue_mtx, MA_OWNED);
if (md == NULL || !MIDICONFED(md)) {
- DEB(printf("seq_closemidi: midi device does not exist.\n"));
+ SEQ_DEBUG(printf("seq_closemidi: midi device does not exist.\n"));
return (ENXIO);
}
midiunit = md->unit;
- DEB(printf("seq_closemidi: closing midi unit %d.\n", midiunit));
+ SEQ_DEBUG(printf("seq_closemidi: closing midi unit %d.\n", midiunit));
midi_close(MIDIMKDEV(MIDI_CDEV_MAJOR, midiunit, SND_DEV_MIDIN), flags, mode, td);
mtx_lock(&md->flagqueue_mtx);
@@ -1946,6 +2203,8 @@ seq_reset(sc_p scp)
mtx_assert(&sd->flagqueue_mtx, MA_OWNED);
+ SEQ_DEBUG(printf("seq_reset: unit %d.\n", unit));
+
if ((sd->flags & SEQ_F_INSYNC) != 0)
cv_wait(&sd->insync_cv, &sd->flagqueue_mtx);
@@ -1956,14 +2215,11 @@ seq_reset(sc_p scp)
midibuf_clear(&sd->midi_dbuf_in);
midibuf_clear(&sd->midi_dbuf_out);
-#if notyet
/* Reset the synthesizers. */
TAILQ_FOREACH(md, &scp->midi_open, md_linkseq)
md->synth.reset(md);
-#endif /* notyet */
-#if notyet
- if (scp->seq_mode == SEQ_2) {
+ if (scp->seq_mode == SND_DEV_MUSIC) {
for (chn = 0 ; chn < 16 ; chn++) {
TAILQ_FOREACH(md, &scp->midi_open, md_linkseq) {
if (md->synth.controller(md, chn, 123, 0) == EAGAIN /* All notes off. */
@@ -1973,7 +2229,6 @@ seq_reset(sc_p scp)
}
}
} else {
-#endif /* notyet */
TAILQ_FOREACH(md, &scp->midi_open, md_linkseq) {
for (chn = 0 ; chn < 16 ; chn++) {
c[0] = 0xb0 | (chn & 0x0f);
@@ -1989,9 +2244,7 @@ seq_reset(sc_p scp)
seq_sync(scp);
TAILQ_FOREACH(md, &scp->midi_open, md_linkseq)
lookup_mididev(scp, md->unit, LOOKUP_CLOSE, NULL);
-#if notyet
}
-#endif /* notyet */
return (0);
}
@@ -2008,6 +2261,7 @@ seq_sync(sc_p scp)
mtx_assert(&sd->flagqueue_mtx, MA_OWNED);
+ SEQ_DEBUG(printf("seq_sync: unit %d.\n", sd->unit));
sd->flags |= SEQ_F_INSYNC;
while (sd->midi_dbuf_out.rl >= EV_SZ) {
@@ -2065,7 +2319,7 @@ get_seqdev_info(dev_t i_dev, int *unit)
{
int u;
- if (MIDIDEV(i_dev) != SND_DEV_SEQ && MIDIDEV(i_dev) != SND_DEV_SEQ2)
+ if (MIDIDEV(i_dev) != SND_DEV_SEQ && MIDIDEV(i_dev) != SND_DEV_MUSIC)
return NULL;
u = MIDIUNIT(i_dev);
if (unit)
@@ -2151,7 +2405,52 @@ lookup_mididev(sc_p scp, int unit, int mode, mididev_info **mdp)
mtx_assert(&scp->devinfo->flagqueue_mtx, MA_OWNED);
TAILQ_FOREACH(md, &scp->midi_open, md_linkseq) {
- if (md->unit == unit) {
+ if (scp->seq_mode == SND_DEV_MUSIC ? md->unit == unit : md->synthunit == unit) {
+ *mdp = md;
+ if (mode == LOOKUP_CLOSE)
+ return seq_closemidi(scp, md, scp->fflags, MIDIDEV_MODE, curthread);
+
+ return (md != NULL && MIDICONFED(md)) ? 0 : ENXIO;
+ }
+ }
+
+ if (mode == LOOKUP_OPEN) {
+ if (scp->seq_mode == SND_DEV_MUSIC)
+ md = get_mididev_info_unit(unit);
+ else
+ md = get_mididev_synth_unit(unit);
+ if (md != NULL) {
+ *mdp = md;
+ ret = seq_openmidi(scp, md, scp->fflags, MIDIDEV_MODE, curthread);
+ return ret;
+ }
+ }
+
+ return ENXIO;
+}
+
+/*
+ * Look up a midi device by its midi unit number opened by this sequencer.
+ * If the device is not opened and mode is LOOKUP_OPEN, open the device.
+ */
+static int
+lookup_mididev_midi(sc_p scp, int unit, int mode, mididev_info **mdp)
+{
+ int ret;
+ mididev_info *md;
+
+ if (mdp == NULL)
+ mdp = &md;
+
+ *mdp = NULL;
+
+ if (scp->seq_mode == SND_DEV_MUSIC)
+ return (ENXIO);
+
+ mtx_assert(&scp->devinfo->flagqueue_mtx, MA_OWNED);
+
+ TAILQ_FOREACH(md, &scp->midi_open, md_linkseq) {
+ if (md->midiunit == unit) {
*mdp = md;
if (mode == LOOKUP_CLOSE)
return seq_closemidi(scp, md, scp->fflags, MIDIDEV_MODE, curthread);
@@ -2161,7 +2460,7 @@ lookup_mididev(sc_p scp, int unit, int mode, mididev_info **mdp)
}
if (mode == LOOKUP_OPEN) {
- md = get_mididev_info_unit(unit);
+ md = get_mididev_midi_unit(unit);
if (md != NULL) {
*mdp = md;
ret = seq_openmidi(scp, md, scp->fflags, MIDIDEV_MODE, curthread);
@@ -2178,6 +2477,7 @@ seqopen(dev_t i_dev, int flags, int mode, struct thread *td)
{
switch (MIDIDEV(i_dev)) {
case MIDI_DEV_SEQ:
+ case MIDI_DEV_MUSIC:
return seq_open(i_dev, flags, mode, td);
}
@@ -2189,6 +2489,7 @@ seqclose(dev_t i_dev, int flags, int mode, struct thread *td)
{
switch (MIDIDEV(i_dev)) {
case MIDI_DEV_SEQ:
+ case MIDI_DEV_MUSIC:
return seq_close(i_dev, flags, mode, td);
}
@@ -2200,6 +2501,7 @@ seqread(dev_t i_dev, struct uio * buf, int flag)
{
switch (MIDIDEV(i_dev)) {
case MIDI_DEV_SEQ:
+ case MIDI_DEV_MUSIC:
return seq_read(i_dev, buf, flag);
}
@@ -2211,6 +2513,7 @@ seqwrite(dev_t i_dev, struct uio * buf, int flag)
{
switch (MIDIDEV(i_dev)) {
case MIDI_DEV_SEQ:
+ case MIDI_DEV_MUSIC:
return seq_write(i_dev, buf, flag);
}
@@ -2222,6 +2525,7 @@ seqioctl(dev_t i_dev, u_long cmd, caddr_t arg, int mode, struct thread *td)
{
switch (MIDIDEV(i_dev)) {
case MIDI_DEV_SEQ:
+ case MIDI_DEV_MUSIC:
return seq_ioctl(i_dev, cmd, arg, mode, td);
}
@@ -2233,6 +2537,7 @@ seqpoll(dev_t i_dev, int events, struct thread *td)
{
switch (MIDIDEV(i_dev)) {
case MIDI_DEV_SEQ:
+ case MIDI_DEV_MUSIC:
return seq_poll(i_dev, events, td);
}
diff --git a/sys/dev/sound/midi/sequencer.h b/sys/dev/sound/midi/sequencer.h
index ea75a36..c5db264 100644
--- a/sys/dev/sound/midi/sequencer.h
+++ b/sys/dev/sound/midi/sequencer.h
@@ -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_ */
diff --git a/sys/dev/sound/pci/csamidi.c b/sys/dev/sound/pci/csamidi.c
index ace03d1..a0dd70c 100644
--- a/sys/dev/sound/pci/csamidi.c
+++ b/sys/dev/sound/pci/csamidi.c
@@ -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);
}
OpenPOWER on IntegriCloud