diff options
author | tanimura <tanimura@FreeBSD.org> | 2002-01-04 01:13:49 +0000 |
---|---|---|
committer | tanimura <tanimura@FreeBSD.org> | 2002-01-04 01:13:49 +0000 |
commit | c9a37a6ceaafff4e7bb45214a8cb8bec4cbe1040 (patch) | |
tree | 172193f32d3428cba6b1cfe2673b7e848920b3f2 | |
parent | bc1c5ca72163809979db46d3d2ea6f9d3ea63a71 (diff) | |
download | FreeBSD-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/files | 1 | ||||
-rw-r--r-- | sys/dev/sound/isa/emu8000.c | 19 | ||||
-rw-r--r-- | sys/dev/sound/isa/gusmidi.c | 8 | ||||
-rw-r--r-- | sys/dev/sound/isa/mpu.c | 14 | ||||
-rw-r--r-- | sys/dev/sound/isa/opl.c | 75 | ||||
-rw-r--r-- | sys/dev/sound/isa/uartsio.c | 18 | ||||
-rw-r--r-- | sys/dev/sound/midi/midi.c | 208 | ||||
-rw-r--r-- | sys/dev/sound/midi/midi.h | 100 | ||||
-rw-r--r-- | sys/dev/sound/midi/midibuf.c | 6 | ||||
-rw-r--r-- | sys/dev/sound/midi/midisynth.c | 4 | ||||
-rw-r--r-- | sys/dev/sound/midi/sequencer.c | 751 | ||||
-rw-r--r-- | sys/dev/sound/midi/sequencer.h | 46 | ||||
-rw-r--r-- | sys/dev/sound/pci/csamidi.c | 6 |
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); } |