- Do not uiomove with a mutex locked.

- Move from msleep/wakeup to condvar.

- Return either zero or a positive errno value from a function.
  Return additional result via references.

- Unify the typedef of callback functions.
This commit is contained in:
Seigo Tanimura 2002-01-01 17:36:26 +00:00
parent d6811c6851
commit 05331bc6d4
15 changed files with 391 additions and 429 deletions

View File

@ -803,21 +803,28 @@ emu_ioctl(dev_t i_dev, u_long cmd, caddr_t arg, int mode, struct thread *td)
}
static int
emu_callback(mididev_info *devinfo, int reason)
emu_callback(void *d, int reason)
{
mididev_info *devinfo;
devinfo = (mididev_info *)d;
mtx_assert(&devinfo->flagqueue_mtx, MA_OWNED);
return (0);
}
static int
emu_readraw(mididev_info *md, u_char *buf, int len, int nonblock)
emu_readraw(mididev_info *md, u_char *buf, int len, int *lenr, int nonblock)
{
sc_p scp;
int unit;
if (md == NULL)
return (ENXIO);
if (lenr == NULL)
return (EINVAL);
unit = md->unit;
scp = md->softc;
if ((md->fflags & FREAD) == 0) {
@ -826,17 +833,22 @@ emu_readraw(mididev_info *md, u_char *buf, int len, int nonblock)
}
/* NOP. */
*lenr = 0;
return (0);
}
static int
emu_writeraw(mididev_info *md, u_char *buf, int len, int nonblock)
emu_writeraw(mididev_info *md, u_char *buf, int len, int *lenw, int nonblock)
{
sc_p scp;
int unit;
if (md == NULL)
return (ENXIO);
if (lenw == NULL)
return (EINVAL);
unit = md->unit;
scp = md->softc;
if ((md->fflags & FWRITE) == 0) {
@ -845,6 +857,8 @@ emu_writeraw(mididev_info *md, u_char *buf, int len, int nonblock)
}
/* NOP. */
*lenw = 0;
return (0);
}

View File

@ -289,7 +289,7 @@ gusmidi_intr(void *arg)
sc_p scp;
u_char c;
mididev_info *devinfo;
int stat, did_something;
int stat, did_something, leni;
scp = (sc_p)arg;
devinfo = scp->devinfo;
@ -308,13 +308,13 @@ gusmidi_intr(void *arg)
(!(devinfo->flags & MIDI_F_BUSY) ||
!(devinfo->fflags & FWRITE))) {
midibuf_input_intr(&devinfo->midi_dbuf_passthru,
&c, sizeof c);
&c, sizeof c, &leni);
devinfo->callback(devinfo,
MIDI_CB_START | MIDI_CB_WR);
}
if ((devinfo->flags & MIDI_F_READING) && c != 0xfe) {
midibuf_input_intr(&devinfo->midi_dbuf_in,
&c, sizeof c);
&c, sizeof c, &leni);
}
did_something = 1;
} else
@ -342,10 +342,13 @@ gusmidi_intr(void *arg)
}
static int
gusmidi_callback(mididev_info *d, int reason)
gusmidi_callback(void *di, int reason)
{
int unit;
sc_p scp;
mididev_info *d;
d = (mididev_info *)di;
mtx_assert(&d->flagqueue_mtx, MA_OWNED);
@ -424,6 +427,7 @@ gusmidi_xmit(sc_p scp)
register mididev_info *devinfo;
register midi_dbuf *dbuf;
u_char c;
int leno;
devinfo = scp->devinfo;
@ -450,7 +454,7 @@ gusmidi_xmit(sc_p scp)
mtx_lock(&scp->mtx);
if (gusmidi_readport(scp, PORT_ST) & MIDIST_TXDONE) {
/* Send the data. */
midibuf_output_intr(dbuf, &c, sizeof(c));
midibuf_output_intr(dbuf, &c, sizeof(c), &leno);
gusmidi_writeport(scp, PORT_TX, c);
/* We are playing now. */
} else {

View File

@ -148,7 +148,7 @@ static int mpu_uartmode(sc_p scp);
static int mpu_waitack(sc_p scp);
static int mpu_status(sc_p scp);
static int mpu_command(sc_p scp, u_int8_t value);
static int mpu_readdata(sc_p scp);
static int mpu_readdata(sc_p scp, u_int8_t *value);
static int mpu_writedata(sc_p scp, u_int8_t value);
static u_int mpu_readport(sc_p scp, int off);
static void mpu_writeport(sc_p scp, int off, u_int8_t value);
@ -454,6 +454,7 @@ mpu_intr(void *arg)
sc_p scp;
u_char c;
mididev_info *devinfo;
int leni;
scp = (sc_p)arg;
devinfo = scp->devinfo;
@ -464,16 +465,16 @@ mpu_intr(void *arg)
/* Read the received data. */
while ((mpu_status(scp) & MPU_INPUTBUSY) == 0) {
/* Receive the data. */
c = mpu_readdata(scp);
mpu_readdata(scp, &c);
mtx_unlock(&scp->mtx);
/* Queue into the passthru buffer and start transmitting if we can. */
if ((devinfo->flags & MIDI_F_PASSTHRU) != 0 && ((devinfo->flags & MIDI_F_BUSY) == 0 || (devinfo->fflags & FWRITE) == 0)) {
midibuf_input_intr(&devinfo->midi_dbuf_passthru, &c, sizeof(c));
midibuf_input_intr(&devinfo->midi_dbuf_passthru, &c, sizeof(c), &leni);
devinfo->callback(devinfo, MIDI_CB_START | MIDI_CB_WR);
}
/* Queue if we are reading. Discard an active sensing. */
if ((devinfo->flags & MIDI_F_READING) != 0 && c != 0xfe) {
midibuf_input_intr(&devinfo->midi_dbuf_in, &c, sizeof(c));
midibuf_input_intr(&devinfo->midi_dbuf_in, &c, sizeof(c), &leni);
}
mtx_lock(&scp->mtx);
}
@ -485,10 +486,13 @@ mpu_intr(void *arg)
}
static int
mpu_callback(mididev_info *d, int reason)
mpu_callback(void *di, int reason)
{
int unit;
sc_p scp;
mididev_info *d;
d = (mididev_info *)di;
mtx_assert(&d->flagqueue_mtx, MA_OWNED);
@ -553,6 +557,7 @@ mpu_xmit(sc_p scp)
register mididev_info *devinfo;
register midi_dbuf *dbuf;
u_char c;
int leno;
devinfo = scp->devinfo;
@ -573,7 +578,7 @@ mpu_xmit(sc_p scp)
/* XXX Wait until we can write the data. */
if ((mpu_status(scp) & MPU_OUTPUTBUSY) == 0) {
/* Send the data. */
midibuf_output_intr(dbuf, &c, sizeof(c));
midibuf_output_intr(dbuf, &c, sizeof(c), &leno);
mpu_writedata(scp, c);
/* We are playing now. */
devinfo->flags |= MIDI_F_WRITING;
@ -639,12 +644,12 @@ mpu_uartmode(sc_p scp)
static int
mpu_waitack(sc_p scp)
{
int i, resp;
int i;
u_int8_t resp;
resp = 0;
for (i = 0 ; i < MPU_TRYDATA ; i++) {
resp = mpu_readdata(scp);
if (resp >= 0)
if (mpu_readdata(scp, &resp) == 0)
break;
}
if (resp != MPU_ACK)
@ -680,17 +685,22 @@ mpu_command(sc_p scp, u_int8_t value)
/* Reads a byte of data. */
static int
mpu_readdata(sc_p scp)
mpu_readdata(sc_p scp, u_int8_t *value)
{
u_int status;
if (value == NULL)
return (EINVAL);
/* Is the interface ready to write? */
status = mpu_status(scp);
if ((status & MPU_INPUTBUSY) != 0)
/* The interface is busy. */
return (-EAGAIN);
return (EAGAIN);
return (int)mpu_readport(scp, MPU_DATAPORT) & 0xff;
*value = (u_int8_t)(mpu_readport(scp, MPU_DATAPORT) & 0xff);
return (0);
}
/* Writes a byte of data. */

View File

@ -907,10 +907,13 @@ opl_ioctl(dev_t i_dev, u_long cmd, caddr_t arg, int mode, struct thread *td)
}
static int
opl_callback(mididev_info *devinfo, int reason)
opl_callback(void *d, int reason)
{
int unit;
sc_p scp;
mididev_info *devinfo;
devinfo = (mididev_info *)d;
mtx_assert(&devinfo->flagqueue_mtx, MA_OWNED);
@ -948,13 +951,16 @@ opl_callback(mididev_info *devinfo, int reason)
}
static int
opl_readraw(mididev_info *md, u_char *buf, int len, int nonblock)
opl_readraw(mididev_info *md, u_char *buf, int len, int *lenr, int nonblock)
{
sc_p scp;
int unit;
if (md == NULL)
return (ENXIO);
if (lenr == NULL)
return (EINVAL);
unit = md->unit;
scp = md->softc;
if ((md->fflags & FREAD) == 0) {
@ -963,17 +969,22 @@ opl_readraw(mididev_info *md, u_char *buf, int len, int nonblock)
}
/* NOP. */
*lenr = 0;
return (0);
}
static int
opl_writeraw(mididev_info *md, u_char *buf, int len, int nonblock)
opl_writeraw(mididev_info *md, u_char *buf, int len, int *lenw, int nonblock)
{
sc_p scp;
int unit;
if (md == NULL)
return (ENXIO);
if (lenw == NULL)
return (EINVAL);
unit = md->unit;
scp = md->softc;
if ((md->fflags & FWRITE) == 0) {
@ -982,6 +993,8 @@ opl_writeraw(mididev_info *md, u_char *buf, int len, int nonblock)
}
/* NOP. */
*lenw = 0;
return (0);
}

View File

@ -320,10 +320,13 @@ uartsio_intr(void *arg)
}
static int
uartsio_callback(mididev_info *d, int reason)
uartsio_callback(void *di, int reason)
{
int unit;
sc_p scp;
mididev_info *d;
d = (mididev_info *)di;
mtx_assert(&d->flagqueue_mtx, MA_OWNED);
@ -386,7 +389,7 @@ uartsio_xmit(sc_p scp)
{
mididev_info *devinfo;
midi_dbuf *dbuf;
int lsr, msr, iir, i, txsize;
int lsr, msr, iir, i, txsize, leni, leno;
u_char c[TX_FIFO_SIZE];
devinfo = scp->devinfo;
@ -406,12 +409,12 @@ uartsio_xmit(sc_p scp)
mtx_unlock(&scp->mtx);
/* Queue into the passthru buffer and start transmitting if we can. */
if ((devinfo->flags & MIDI_F_PASSTHRU) != 0 && ((devinfo->flags & MIDI_F_BUSY) == 0 || (devinfo->fflags & FWRITE) == 0)) {
midibuf_input_intr(&devinfo->midi_dbuf_passthru, &c[0], sizeof(c[0]));
midibuf_input_intr(&devinfo->midi_dbuf_passthru, &c[0], sizeof(c[0]), &leni);
devinfo->flags |= MIDI_F_WRITING;
}
/* Queue if we are reading. Discard an active sensing. */
if ((devinfo->flags & MIDI_F_READING) != 0 && c[0] != 0xfe)
midibuf_input_intr(&devinfo->midi_dbuf_in, &c[0], sizeof(c[0]));
midibuf_input_intr(&devinfo->midi_dbuf_in, &c[0], sizeof(c[0]), &leni);
mtx_lock(&scp->mtx);
}
}
@ -440,7 +443,7 @@ uartsio_xmit(sc_p scp)
txsize = scp->tx_size;
if (dbuf->rl < txsize)
txsize = dbuf->rl;
midibuf_output_intr(dbuf, c, txsize);
midibuf_output_intr(dbuf, c, txsize, &leno);
for (i = 0 ; i < txsize ; i++)
uartsio_writeport(scp, com_data, c[i]);
/* We are playing now. */

View File

@ -476,8 +476,9 @@ midi_close(dev_t i_dev, int flags, int mode, struct thread *td)
int
midi_read(dev_t i_dev, struct uio * buf, int flag)
{
int dev, unit, len, ret;
int dev, unit, len, lenr, ret;
mididev_info *d ;
u_char *uiobuf;
dev = minor(i_dev);
@ -489,35 +490,42 @@ midi_read(dev_t i_dev, struct uio * buf, int flag)
ret = 0;
len = buf->uio_resid;
lenr = 0;
uiobuf = (u_char *)malloc(len, M_DEVBUF, M_WAITOK | M_ZERO);
if (uiobuf == NULL)
return (ENOMEM);
mtx_lock(&d->flagqueue_mtx);
/* Begin recording. */
d->callback(d, MIDI_CB_START | MIDI_CB_RD);
len = 0;
/* Have we got the data to read? */
if ((d->flags & MIDI_F_NBIO) != 0 && d->midi_dbuf_in.rl == 0)
ret = EAGAIN;
else {
len = buf->uio_resid;
ret = midibuf_uioread(&d->midi_dbuf_in, buf, len, &d->flagqueue_mtx);
if (ret < 0)
ret = -ret;
else
ret = 0;
}
else
ret = midibuf_seqread(&d->midi_dbuf_in, uiobuf, len, &lenr,
d->callback, d, MIDI_CB_START | MIDI_CB_RD,
&d->flagqueue_mtx);
mtx_unlock(&d->flagqueue_mtx);
if (lenr > 0)
ret = uiomove(uiobuf, lenr, buf);
free(uiobuf, M_DEVBUF);
return (ret);
}
int
midi_write(dev_t i_dev, struct uio * buf, int flag)
{
int dev, unit, len, ret;
int dev, unit, len, len2, lenw, ret;
mididev_info *d;
u_char *uiobuf;
dev = minor(i_dev);
d = get_mididev_info(i_dev, &unit);
@ -529,6 +537,19 @@ midi_write(dev_t i_dev, struct uio * buf, int flag)
ret = 0;
len = buf->uio_resid;
lenw = 0;
uiobuf = (u_char *)malloc(len, M_DEVBUF, M_WAITOK | M_ZERO);
if (uiobuf == NULL)
return (ENOMEM);
ret = uiomove(uiobuf, len, buf);
if (ret != 0) {
free(uiobuf, M_DEVBUF);
return (ret);
}
mtx_lock(&d->flagqueue_mtx);
/* Have we got the data to write? */
@ -537,22 +558,19 @@ midi_write(dev_t i_dev, struct uio * buf, int flag)
d->callback(d, MIDI_CB_START | MIDI_CB_WR);
ret = EAGAIN;
} else {
len = buf->uio_resid;
if (len > d->midi_dbuf_out.fl &&
(d->flags & MIDI_F_NBIO))
len = d->midi_dbuf_out.fl;
ret = midibuf_uiowrite(&d->midi_dbuf_out, buf, len, &d->flagqueue_mtx);
if (ret < 0)
ret = -ret;
else {
/* Begin playing. */
d->callback(d, MIDI_CB_START | MIDI_CB_WR);
ret = 0;
}
len2 = len;
if ((d->flags & MIDI_F_NBIO) != 0 && len2 > d->midi_dbuf_out.fl)
len2 = d->midi_dbuf_out.fl;
ret = midibuf_seqwrite(&d->midi_dbuf_out, uiobuf, len2, &lenw,
d->callback, d, MIDI_CB_START | MIDI_CB_WR,
&d->flagqueue_mtx);
}
mtx_unlock(&d->flagqueue_mtx);
free(uiobuf, M_DEVBUF);
buf->uio_resid = len - lenw;
return (ret);
}
@ -789,7 +807,10 @@ midi_sync(mididev_info *d)
if ((d->flags & MIDI_F_WRITING) == 0)
d->callback(d, MIDI_CB_START | MIDI_CB_WR);
rl = d->midi_dbuf_out.rl;
i = msleep(&d->midi_dbuf_out.tsleep_out, &d->flagqueue_mtx, PRIBIO | PCATCH, "midsnc", (d->midi_dbuf_out.bufsize * 10 * hz / 38400) + MIDI_SYNC_TIMEOUT * hz);
i = cv_timedwait_sig(&d->midi_dbuf_out.cv_out,
&d->flagqueue_mtx,
(d->midi_dbuf_out.bufsize * 10 * hz / 38400)
+ MIDI_SYNC_TIMEOUT * hz);
if (i == EINTR || i == ERESTART) {
if (i == EINTR)
d->callback(d, MIDI_CB_STOP | MIDI_CB_WR);

View File

@ -67,6 +67,7 @@
#include <sys/mman.h>
#include <sys/poll.h>
#include <sys/mutex.h>
#include <sys/condvar.h>
#include <dev/sound/midi/miditypes.h>
#include <dev/sound/midi/midibuf.h>

View File

@ -42,11 +42,9 @@
#define SPACE_AVAIL(dbuf) ((dbuf)->fl)
static void queuerawdata(midi_dbuf *dbuf, char *data, int len);
static void queueuiodata(midi_dbuf *dbuf, struct uio *buf, int len);
static void dequeuerawdata(midi_dbuf *dbuf, char *data, int len);
static void undequeuerawdata(midi_dbuf *dbuf, char *data, int len);
static void copyrawdata(midi_dbuf *dbuf, char *data, int len);
static void dequeueuiodata(midi_dbuf *dbuf, struct uio *buf, int len);
static void copyrawdata(midi_dbuf *dbuf, int offset, char *data, int len);
static void deleterawdata(midi_dbuf *dbuf, int len);
/*
* Here are the functions to interact to the midi device drivers.
@ -56,9 +54,11 @@ static void dequeueuiodata(midi_dbuf *dbuf, struct uio *buf, int len);
int
midibuf_init(midi_dbuf *dbuf)
{
if (dbuf->buf != NULL)
free(dbuf->buf, M_DEVBUF);
dbuf->buf = malloc(MIDI_BUFFSIZE, M_DEVBUF, M_WAITOK | M_ZERO);
if (dbuf->buf == NULL) {
dbuf->buf = malloc(MIDI_BUFFSIZE, M_DEVBUF, M_WAITOK | M_ZERO);
cv_init(&dbuf->cv_in, "midi queue in");
cv_init(&dbuf->cv_out, "midi queue out");
}
return (midibuf_clear(dbuf));
}
@ -66,8 +66,11 @@ midibuf_init(midi_dbuf *dbuf)
int
midibuf_destroy(midi_dbuf *dbuf)
{
if (dbuf->buf != NULL)
if (dbuf->buf != NULL) {
free(dbuf->buf, M_DEVBUF);
cv_destroy(&dbuf->cv_in);
cv_destroy(&dbuf->cv_out);
}
return (0);
}
@ -94,15 +97,21 @@ midibuf_clear(midi_dbuf *dbuf)
/* The sequencer calls this function to queue data. */
int
midibuf_seqwrite(midi_dbuf *dbuf, u_char* data, int len, struct mtx *m)
midibuf_seqwrite(midi_dbuf *dbuf, u_char* data, int len, int *lenw, midi_callback_t *cb, void *d, int reason, struct mtx *m)
{
int i, lwrt, lwritten;
int i, lwrt;
if (m != NULL)
mtx_assert(m, MA_OWNED);
if (lenw == NULL)
return (EINVAL);
*lenw = 0;
/* Is this a real queue? */
if (dbuf == (midi_dbuf *)NULL)
return (0);
return (EINVAL);
lwritten = 0;
/* Write down every single byte. */
while (len > 0) {
/* Find out the number of bytes to write. */
@ -113,131 +122,103 @@ midibuf_seqwrite(midi_dbuf *dbuf, u_char* data, int len, struct mtx *m)
/* We can write some now. Queue the data. */
queuerawdata(dbuf, data, lwrt);
lwritten += lwrt;
*lenw += lwrt;
len -= lwrt;
data += lwrt;
if (cb != NULL)
(*cb)(d, reason);
}
/* Have we got still more data to write? */
if (len > 0) {
/* Yes, sleep until we have enough space. */
i = msleep((void *)&dbuf->tsleep_out, m, PRIBIO | PCATCH, "mbsqwt", 0);
/* Sleep until we have enough space. */
i = cv_wait_sig(&dbuf->cv_out, m);
if (i == EINTR || i == ERESTART)
return (-i);
return (i);
}
}
return (lwritten);
}
/* sndwrite calls this function to queue data. */
int
midibuf_uiowrite(midi_dbuf *dbuf, struct uio *buf, int len, struct mtx *m)
{
int i, lwrt, lwritten;
/* Is this a real queue? */
if (dbuf == (midi_dbuf *)NULL)
return (0);
lwritten = 0;
/* Write down every single byte. */
while (len > 0) {
/* Find out the number of bytes to write. */
lwrt = SPACE_AVAIL(dbuf);
if (lwrt > len)
lwrt = len;
if (lwrt > 0) {
/* We can write some now. Queue the data. */
queueuiodata(dbuf, buf, lwrt);
lwritten += lwrt;
len -= lwrt;
}
/* Have we got still more data to write? */
if (len > 0) {
/* Yes, sleep until we have enough space. */
i = msleep(&dbuf->tsleep_out, m, PRIBIO | PCATCH, "mbuiwt", 0);
if (i == EINTR || i == ERESTART)
return (-i);
}
}
return (lwritten);
return (0);
}
int
midibuf_output_intr(midi_dbuf *dbuf, u_char *data, int len)
midibuf_output_intr(midi_dbuf *dbuf, u_char *data, int len, int *leno)
{
int lrd;
if (leno == NULL)
return (EINVAL);
*leno = 0;
/* Is this a real queue? */
if (dbuf == (midi_dbuf *)NULL)
return (0);
return (EINVAL);
/* Have we got any data in the queue? */
if ((lrd = DATA_AVAIL(dbuf)) == 0)
return (0);
*leno = DATA_AVAIL(dbuf);
if (*leno == 0)
return (EAGAIN);
/* Dequeue the data. */
if (lrd > len)
lrd = len;
dequeuerawdata(dbuf, data, lrd);
if (*leno > len)
*leno = len;
dequeuerawdata(dbuf, data, *leno);
return (lrd);
return (0);
}
int
midibuf_input_intr(midi_dbuf *dbuf, u_char *data, int len)
midibuf_input_intr(midi_dbuf *dbuf, u_char *data, int len, int *leni)
{
int lwritten;
if (leni == NULL)
return (EINVAL);
*leni = 0;
/* Is this a real queue? */
if (dbuf == (midi_dbuf *)NULL)
return (0);
lwritten = 0;
return (EINVAL);
/* Have we got any data to write? */
if (len == 0)
return (0);
/* Can we write now? */
if (SPACE_AVAIL(dbuf) < len)
return (-EAGAIN);
return (EAGAIN);
/* We can write some now. Queue the data. */
queuerawdata(dbuf, data, len);
lwritten = len;
*leni = len;
/* Have we managed to write the whole data? */
if (lwritten < len)
printf("midibuf_input_intr: queue did not have enough space, discarded %d bytes out of %d bytes.\n", len - lwritten, len);
return (lwritten);
return (0);
}
/* The sequencer calls this function to dequeue data. */
int
midibuf_seqread(midi_dbuf *dbuf, u_char* data, int len, struct mtx *m)
midibuf_seqread(midi_dbuf *dbuf, u_char* data, int len, int *lenr, midi_callback_t *cb, void *d, int reason, struct mtx *m)
{
int i, lrd, lread;
int i, lrd;
if (m != NULL)
mtx_assert(m, MA_OWNED);
if (lenr == NULL)
return (EINVAL);
*lenr = 0;
/* Is this a real queue? */
if (dbuf == (midi_dbuf *)NULL)
return (0);
return (EINVAL);
lread = 0;
/* Write down every single byte. */
while (len > 0) {
if (cb != NULL)
(*cb)(d, reason);
/* Have we got data to read? */
if ((lrd = DATA_AVAIL(dbuf)) == 0) {
/* No, sleep until we have data ready to read. */
i = msleep(&dbuf->tsleep_in, m, PRIBIO | PCATCH, "mbsqrd", 0);
/* Sleep until we have data ready to read. */
i = cv_wait_sig(&dbuf->cv_in, m);
if (i == EINTR || i == ERESTART)
return (-i);
if (i == EWOULDBLOCK)
continue;
return (i);
/* Find out the number of bytes to read. */
lrd = DATA_AVAIL(dbuf);
}
@ -248,76 +229,43 @@ midibuf_seqread(midi_dbuf *dbuf, u_char* data, int len, struct mtx *m)
/* We can read some data now. Dequeue the data. */
dequeuerawdata(dbuf, data, lrd);
lread += lrd;
*lenr += lrd;
len -= lrd;
data += lrd;
}
}
return (lread);
}
/* The sequencer calls this function to undo dequeued data. */
int
midibuf_sequnread(midi_dbuf *dbuf, u_char* data, int len, struct mtx *m)
{
int i, lrd, lunread;
/* Is this a real queue? */
if (dbuf == (midi_dbuf *)NULL)
return (0);
lunread = 0;
/* Write down every single byte. */
while (len > 0) {
/* Have we got data to read? */
if ((lrd = SPACE_AVAIL(dbuf)) == 0) {
/* No, sleep until we have data ready to read. */
i = msleep(&dbuf->tsleep_in, m, PRIBIO | PCATCH, "mbsqur", 0);
if (i == EINTR || i == ERESTART)
return (-i);
if (i == EWOULDBLOCK)
continue;
/* Find out the number of bytes to unread. */
lrd = SPACE_AVAIL(dbuf);
}
if (lrd > len)
lrd = len;
if (lrd > 0) {
/* We can read some data now. Dequeue the data. */
undequeuerawdata(dbuf, data, lrd);
lunread += lrd;
len -= lrd;
data += lrd;
}
}
return (lunread);
return (0);
}
/* The sequencer calls this function to copy data without dequeueing. */
int
midibuf_seqcopy(midi_dbuf *dbuf, u_char* data, int len, struct mtx *m)
midibuf_seqcopy(midi_dbuf *dbuf, u_char* data, int len, int *lenc, midi_callback_t *cb, void *d, int reason, struct mtx *m)
{
int i, lrd, lread;
int i, lrd;
if (m != NULL)
mtx_assert(m, MA_OWNED);
if (lenc == NULL)
return (EINVAL);
*lenc = 0;
/* Is this a real queue? */
if (dbuf == (midi_dbuf *)NULL)
return (0);
return (EINVAL);
lread = 0;
/* Write down every single byte. */
while (len > 0) {
if (cb != NULL)
(*cb)(d, reason);
/* Have we got data to read? */
if ((lrd = DATA_AVAIL(dbuf)) == 0) {
/* No, sleep until we have data ready to read. */
i = msleep(&dbuf->tsleep_in, m, PRIBIO | PCATCH, "mbsqrd", 0);
/* Sleep until we have data ready to read. */
i = cv_wait_sig(&dbuf->cv_in, m);
if (i == EINTR || i == ERESTART)
return (-i);
if (i == EWOULDBLOCK)
continue;
return (i);
/* Find out the number of bytes to read. */
lrd = DATA_AVAIL(dbuf);
}
@ -326,37 +274,48 @@ midibuf_seqcopy(midi_dbuf *dbuf, u_char* data, int len, struct mtx *m)
lrd = len;
if (lrd > 0) {
/* We can read some data now. Copy the data. */
copyrawdata(dbuf, data, lrd);
copyrawdata(dbuf, *lenc, data, lrd);
lread += lrd;
*lenc += lrd;
len -= lrd;
data += lrd;
}
}
return (lread);
return (0);
}
/* sndread calls this function to dequeue data. */
/*
* The sequencer calls this function to delete the data
* that the sequencer has already read.
*/
int
midibuf_uioread(midi_dbuf *dbuf, struct uio *buf, int len, struct mtx *m)
midibuf_seqdelete(midi_dbuf *dbuf, int len, int *lenr, midi_callback_t *cb, void *d, int reason, struct mtx *m)
{
int i, lrd, lread;
int i, lrd;
if (m != NULL)
mtx_assert(m, MA_OWNED);
if (lenr == NULL)
return (EINVAL);
*lenr = 0;
/* Is this a real queue? */
if (dbuf == (midi_dbuf *)NULL)
return (0);
return (EINVAL);
/* Write down every single byte. */
while (len > 0) {
if (cb != NULL)
(*cb)(d, reason);
lread = 0;
while (len > 0 && lread == 0) {
/* Have we got data to read? */
if ((lrd = DATA_AVAIL(dbuf)) == 0) {
/* No, sleep until we have data ready to read. */
i = msleep(&dbuf->tsleep_in, m, PRIBIO | PCATCH, "mbuird", 0);
/* Sleep until we have data ready to read. */
i = cv_wait_sig(&dbuf->cv_in, m);
if (i == EINTR || i == ERESTART)
return (-i);
if (i == EWOULDBLOCK)
continue;
return (i);
/* Find out the number of bytes to read. */
lrd = DATA_AVAIL(dbuf);
}
@ -364,15 +323,15 @@ midibuf_uioread(midi_dbuf *dbuf, struct uio *buf, int len, struct mtx *m)
if (lrd > len)
lrd = len;
if (lrd > 0) {
/* We can read some data now. Dequeue the data. */
dequeueuiodata(dbuf, buf, lrd);
/* We can read some data now. Delete the data. */
deleterawdata(dbuf, lrd);
lread += lrd;
*lenr += lrd;
len -= lrd;
}
}
return (lread);
return (0);
}
/*
@ -385,11 +344,11 @@ queuerawdata(midi_dbuf *dbuf, char *data, int len)
/* dbuf->fp might wrap around dbuf->bufsize. */
if (dbuf->bufsize - dbuf->fp < len) {
/* The new data wraps, copy them twice. */
memcpy(dbuf->buf + dbuf->fp, data, dbuf->bufsize - dbuf->fp);
memcpy(dbuf->buf, data + dbuf->bufsize - dbuf->fp, len - (dbuf->bufsize - dbuf->fp));
bcopy(data, dbuf->buf + dbuf->fp, dbuf->bufsize - dbuf->fp);
bcopy(data + dbuf->bufsize - dbuf->fp, dbuf->buf, len - (dbuf->bufsize - dbuf->fp));
} else
/* The new data do not wrap, once is enough. */
memcpy(dbuf->buf + dbuf->fp, data, len);
bcopy(data, dbuf->buf + dbuf->fp, len);
/* Adjust the pointer and the length counters. */
dbuf->fp = (dbuf->fp + len) % dbuf->bufsize;
@ -397,30 +356,7 @@ queuerawdata(midi_dbuf *dbuf, char *data, int len)
dbuf->rl += len;
/* Wake up the processes sleeping on input data. */
wakeup(&dbuf->tsleep_in);
if (dbuf->sel.si_pid && dbuf->rl >= dbuf->blocksize)
selwakeup(&dbuf->sel);
}
static void
queueuiodata(midi_dbuf *dbuf, struct uio *buf, int len)
{
/* dbuf->fp might wrap around dbuf->bufsize. */
if (dbuf->bufsize - dbuf->fp < len) {
/* The new data wraps, copy them twice. */
uiomove((caddr_t)(dbuf->buf + dbuf->fp), dbuf->bufsize - dbuf->fp, buf);
uiomove((caddr_t)(dbuf->buf), len - (dbuf->bufsize - dbuf->fp), buf);
} else
/* The new data do not wrap, once is enough. */
uiomove((caddr_t)(dbuf->buf + dbuf->fp), len, buf);
/* Adjust the pointer and the length counters. */
dbuf->fp = (dbuf->fp + len) % dbuf->bufsize;
dbuf->fl -= len;
dbuf->rl += len;
/* Wake up the processes sleeping on queueing. */
wakeup(&dbuf->tsleep_in);
cv_broadcast(&dbuf->cv_in);
if (dbuf->sel.si_pid && dbuf->rl >= dbuf->blocksize)
selwakeup(&dbuf->sel);
}
@ -429,73 +365,39 @@ static void
dequeuerawdata(midi_dbuf *dbuf, char *data, int len)
{
/* Copy the data. */
copyrawdata(dbuf, data, len);
copyrawdata(dbuf, 0, data, len);
/* Adjust the pointer and the length counters. */
dbuf->rp = (dbuf->rp + len) % dbuf->bufsize;
dbuf->rl -= len;
dbuf->fl += len;
/* Wake up the processes sleeping on queueing. */
wakeup(&dbuf->tsleep_out);
if (dbuf->sel.si_pid && dbuf->fl >= dbuf->blocksize)
selwakeup(&dbuf->sel);
}
/* Undo the last dequeue. */
static void
undequeuerawdata(midi_dbuf *dbuf, char *data, int len)
{
/* Copy the data. */
if (dbuf->rp < len) {
memcpy(dbuf->buf, data + (len - dbuf->rp), dbuf->rp);
memcpy(dbuf->buf + (dbuf->bufsize - (len - dbuf->rp)), data, len - dbuf->rp);
} else
memcpy(dbuf->buf + (dbuf->rp - len), data, len);
/* Adjust the pointer and the length counters. */
dbuf->rp = (dbuf->rp - len + dbuf->bufsize) % dbuf->bufsize;
dbuf->rl += len;
dbuf->fl -= len;
/* Wake up the processes sleeping on queueing. */
wakeup(&dbuf->tsleep_in);
if (dbuf->sel.si_pid && dbuf->rl >= dbuf->blocksize)
selwakeup(&dbuf->sel);
/* Delete the data. */
deleterawdata(dbuf, len);
}
static void
copyrawdata(midi_dbuf *dbuf, char *data, int len)
copyrawdata(midi_dbuf *dbuf, int offset, char *data, int len)
{
int rp;
rp = (dbuf->rp + offset) % dbuf->bufsize;
/* dbuf->rp might wrap around dbuf->bufsize. */
if (dbuf->bufsize - dbuf->rp < len) {
if (dbuf->bufsize - rp < len) {
/* The data to be read wraps, copy them twice. */
memcpy(data, dbuf->buf + dbuf->rp, dbuf->bufsize - dbuf->rp);
memcpy(data + dbuf->bufsize - dbuf->rp, dbuf->buf, len - (dbuf->bufsize - dbuf->rp));
bcopy(dbuf->buf + rp, data, dbuf->bufsize - rp);
bcopy(dbuf->buf, data + dbuf->bufsize - rp, len - (dbuf->bufsize - rp));
} else
/* The new data do not wrap, once is enough. */
memcpy(data, dbuf->buf + dbuf->rp, len);
bcopy(dbuf->buf + rp, data, len);
}
static void
dequeueuiodata(midi_dbuf *dbuf, struct uio *buf, int len)
deleterawdata(midi_dbuf *dbuf, int len)
{
/* dbuf->rp might wrap around dbuf->bufsize. */
if (dbuf->bufsize - dbuf->rp < len) {
/* The new data wraps, copy them twice. */
uiomove((caddr_t)(dbuf->buf + dbuf->rp), dbuf->bufsize - dbuf->rp, buf);
uiomove((caddr_t)(dbuf->buf), len - (dbuf->bufsize - dbuf->rp), buf);
} else
/* The new data do not wrap, once is enough. */
uiomove((caddr_t)(dbuf->buf + dbuf->rp), len, buf);
/* Adjust the pointer and the length counters. */
dbuf->rp = (dbuf->rp + len) % dbuf->bufsize;
dbuf->rl -= len;
dbuf->fl += len;
/* Wake up the processes sleeping on queueing. */
wakeup(&dbuf->tsleep_out);
cv_broadcast(&dbuf->cv_out);
if (dbuf->sel.si_pid && dbuf->fl >= dbuf->blocksize)
selwakeup(&dbuf->sel);
}

View File

@ -38,17 +38,17 @@
typedef struct _midi_dbuf {
char *buf;
int bufsize ;
volatile int rp, fp; /* pointers to the ready and free area */
volatile int dl; /* transfer size */
volatile int rl, fl; /* length of ready and free areas. */
volatile int rp, fp; /* pointers to the ready and free area */
volatile int dl; /* transfer size */
volatile int rl, fl; /* length of ready and free areas. */
int int_count;
int chan; /* dma channel */
int unit_size ; /* unit size */
int chan; /* dma channel */
int unit_size ; /* unit size */
struct selinfo sel;
u_long total; /* total bytes processed */
u_long prev_total; /* copy of the above when GETxPTR called */
int tsleep_in, tsleep_out; /* pillows to tsleep on */
int blocksize; /* block size */
u_long total; /* total bytes processed */
u_long prev_total; /* copy of the above when GETxPTR called */
struct cv cv_in, cv_out; /* condvars */
int blocksize; /* block size */
} midi_dbuf ;
/*
@ -57,11 +57,9 @@ typedef struct _midi_dbuf {
int midibuf_init(midi_dbuf *dbuf);
int midibuf_destroy(midi_dbuf *dbuf);
int midibuf_clear(midi_dbuf *dbuf);
int midibuf_seqwrite(midi_dbuf *dbuf, u_char* data, int len, struct mtx *m);
int midibuf_uiowrite(midi_dbuf *dbuf, struct uio *buf, int len, struct mtx *m);
int midibuf_output_intr(midi_dbuf *dbuf, u_char *data, int len);
int midibuf_input_intr(midi_dbuf *dbuf, u_char *data, int len);
int midibuf_seqread(midi_dbuf *dbuf, u_char* data, int len, struct mtx *m);
int midibuf_sequnread(midi_dbuf *dbuf, u_char* data, int len, struct mtx *m);
int midibuf_seqcopy(midi_dbuf *dbuf, u_char* data, int len, struct mtx *m);
int midibuf_uioread(midi_dbuf *dbuf, struct uio *buf, int len, struct mtx *m);
int midibuf_seqwrite(midi_dbuf *dbuf, u_char* data, int len, int *lenw, midi_callback_t *cb, void *d, int reason, struct mtx *m);
int midibuf_output_intr(midi_dbuf *dbuf, u_char *data, int len, int *leno);
int midibuf_input_intr(midi_dbuf *dbuf, u_char *data, int len, int *leni);
int midibuf_seqread(midi_dbuf *dbuf, u_char* data, int len, int *lenr, midi_callback_t *cb, void *d, int reason, struct mtx *m);
int midibuf_seqcopy(midi_dbuf *dbuf, u_char* data, int len, int *lenc, midi_callback_t *cb, void *d, int reason, struct mtx *m);
int midibuf_seqdelete(midi_dbuf *dbuf, int len, int *lend, midi_callback_t *cb, void *d, int reason, struct mtx *m);

View File

@ -101,13 +101,13 @@ static int synth_leavesysex(mididev_info *md);
/*
* Here are the main functions to interact to the midi sequencer.
* These are called from the sequencer functions in sys/i386/isa/snd/sequencer.c.
* These are called from the sequencer functions in sequencer.c.
*/
static int
synth_killnote(mididev_info *md, int chn, int note, int vel)
{
int unit;
int unit, lenw;
synthdev_info *sd;
u_char c[3];
@ -132,16 +132,14 @@ synth_killnote(mididev_info *md, int chn, int note, int vel)
if (synth_prefixcmd(md, c[0]))
return (0);
if (md->synth.writeraw(md, c, 3, 1) == EAGAIN)
return EAGAIN;
return (0);
return (md->synth.writeraw(md, c, 3, &lenw, 1));
}
static int
synth_setinstr(mididev_info *md, int chn, int instr)
{
int unit;
int unit, lenw;
synthdev_info *sd;
u_char c[2];
@ -156,16 +154,14 @@ synth_setinstr(mididev_info *md, int chn, int instr)
c[0] = 0xc0 | (chn & 0x0f); /* Progamme change. */
c[1] = (u_char)instr;
if (md->synth.writeraw(md, c, 3, 1) == EAGAIN)
return (EAGAIN);
return (0);
return (md->synth.writeraw(md, c, 3, &lenw, 1));
}
static int
synth_startnote(mididev_info *md, int chn, int note, int vel)
{
int unit;
int unit, lenw;
synthdev_info *sd;
u_char c[3];
@ -183,10 +179,8 @@ synth_startnote(mididev_info *md, int chn, int note, int vel)
c[2] = (u_char)vel;
if (synth_prefixcmd(md, c[0]))
return (0);
if (md->synth.writeraw(md, c, 3, 1) == EAGAIN)
return (EAGAIN);
return (0);
return (md->synth.writeraw(md, c, 3, &lenw, 1));
}
static int
@ -208,7 +202,7 @@ synth_loadpatch(mididev_info *md, int format, struct uio *buf, int offs, int cou
{
struct sysex_info sysex;
synthdev_info *sd;
int unit, i, eox_seen, first_byte, left, src_offs, hdr_size;
int unit, i, eox_seen, first_byte, left, src_offs, hdr_size, lenw;
u_char c[count];
unit = md->unit;
@ -254,7 +248,7 @@ synth_loadpatch(mididev_info *md, int format, struct uio *buf, int offs, int cou
return (EINVAL);
}
if (!first_byte && (c[i] & 0x80) != 0) {
md->synth.writeraw(md, c, i + 1, 0);
md->synth.writeraw(md, c, i + 1, &lenw, 0);
return (0);
}
first_byte = 0;
@ -262,7 +256,7 @@ synth_loadpatch(mididev_info *md, int format, struct uio *buf, int offs, int cou
if (!eox_seen) {
c[0] = 0xf7;
md->synth.writeraw(md, c, 1, 0);
md->synth.writeraw(md, c, 1, &lenw, 0);
}
return (0);
@ -278,7 +272,7 @@ synth_panning(mididev_info *md, int chn, int pan)
static int
synth_aftertouch(mididev_info *md, int chn, int press)
{
int unit;
int unit, lenw;
synthdev_info *sd;
u_char c[2];
@ -294,16 +288,14 @@ synth_aftertouch(mididev_info *md, int chn, int press)
c[1] = (u_char)press;
if (synth_prefixcmd(md, c[0]))
return (0);
if (md->synth.writeraw(md, c, 2, 1) == EAGAIN)
return (EAGAIN);
return (0);
return (md->synth.writeraw(md, c, 2, &lenw, 1));
}
static int
synth_controller(mididev_info *md, int chn, int ctrlnum, int val)
{
int unit;
int unit, lenw;
synthdev_info *sd;
u_char c[3];
@ -319,10 +311,8 @@ synth_controller(mididev_info *md, int chn, int ctrlnum, int val)
c[1] = (u_char)ctrlnum;
if (synth_prefixcmd(md, c[0]))
return (0);
if (md->synth.writeraw(md, c, 3, 1) == EAGAIN)
return (EAGAIN);
return (0);
return (md->synth.writeraw(md, c, 3, &lenw, 1));
}
static int
@ -334,7 +324,7 @@ synth_patchmgr(mididev_info *md, struct patmgr_info *rec)
static int
synth_bender(mididev_info *md, int chn, int val)
{
int unit;
int unit, lenw;
synthdev_info *sd;
u_char c[3];
@ -351,10 +341,8 @@ synth_bender(mididev_info *md, int chn, int val)
c[2] = (u_char)(val >> 7) & 0x7f;
if (synth_prefixcmd(md, c[0]))
return (0);
if (md->synth.writeraw(md, c, 3, 1) == EAGAIN)
return (EAGAIN);
return (0);
return (md->synth.writeraw(md, c, 3, &lenw, 1));
}
static int
@ -374,7 +362,7 @@ synth_setupvoice(mididev_info *md, int voice, int chn)
static int
synth_sendsysex(mididev_info *md, u_char *sysex, int len)
{
int unit, i;
int unit, i, lenw;
synthdev_info *sd;
u_char c[len];
@ -417,10 +405,8 @@ synth_sendsysex(mididev_info *md, u_char *sysex, int len)
break;
}
mtx_unlock(&sd->status_mtx);
if (md->synth.writeraw(md, c, i, 1) == EAGAIN)
return (EAGAIN);
return (0);
return (md->synth.writeraw(md, c, i, &lenw, 1));
}
static int
@ -438,16 +424,20 @@ synth_volumemethod(mididev_info *md, int mode)
}
static int
synth_readraw(mididev_info *md, u_char *buf, int len, int nonblock)
synth_readraw(mididev_info *md, u_char *buf, int len, int *lenr, int nonblock)
{
int unit, ret;
if (md == NULL)
return (ENXIO);
if (lenr == NULL)
return (EINVAL);
*lenr = 0;
unit = md->unit;
if ((md->fflags & FREAD) == 0) {
DEB(printf("mpu_readraw: unit %d is not for reading.\n", unit));
DEB(printf("synth_readraw: unit %d is not for reading.\n", unit));
return (EIO);
}
@ -465,26 +455,26 @@ synth_readraw(mididev_info *md, u_char *buf, int len, int nonblock)
}
}
ret = midibuf_seqread(&md->midi_dbuf_in, buf, len, &md->flagqueue_mtx);
ret = midibuf_seqread(&md->midi_dbuf_in, buf, len, lenr,
md->callback, md, MIDI_CB_START | MIDI_CB_RD,
&md->flagqueue_mtx);
mtx_unlock(&md->flagqueue_mtx);
if (ret < 0)
ret = -ret;
else
ret = 0;
return (ret);
}
static int
synth_writeraw(mididev_info *md, u_char *buf, int len, int nonblock)
synth_writeraw(mididev_info *md, u_char *buf, int len, int *lenw, int nonblock)
{
int unit, ret;
if (md == NULL)
return (ENXIO);
if (lenw == NULL)
return (EINVAL);
*lenw = 0;
unit = md->unit;
if ((md->fflags & FWRITE) == 0) {
@ -501,15 +491,13 @@ synth_writeraw(mididev_info *md, u_char *buf, int len, int nonblock)
return (EAGAIN);
}
ret = midibuf_seqwrite(&md->midi_dbuf_out, buf, len, &md->flagqueue_mtx);
ret = midibuf_seqwrite(&md->midi_dbuf_out, buf, len, lenw,
md->callback, md, MIDI_CB_START | MIDI_CB_WR,
&md->flagqueue_mtx);
if (ret < 0)
ret = -ret;
else {
if (ret == 0)
/* Begin playing. */
md->callback(md, MIDI_CB_START | MIDI_CB_WR);
ret = 0;
}
mtx_unlock(&md->flagqueue_mtx);
@ -523,7 +511,7 @@ synth_writeraw(mididev_info *md, u_char *buf, int len, int nonblock)
static int
synth_leavesysex(mididev_info *md)
{
int unit;
int unit, lenw;
synthdev_info *sd;
u_char c;
@ -539,8 +527,6 @@ synth_leavesysex(mididev_info *md)
sd->sysex_state = 0;
mtx_unlock(&sd->status_mtx);
c = 0xf7;
if (md->synth.writeraw(md, &c, sizeof(c), 1) == EAGAIN)
return (EAGAIN);
return (0);
return (md->synth.writeraw(md, &c, sizeof(c), &lenw, 1));
}

View File

@ -64,8 +64,8 @@ typedef int (mdsy_setupvoice_t)(mididev_info *md, int voice, int chn);
typedef int (mdsy_sendsysex_t)(mididev_info *md, u_char *sysex, int len);
typedef int (mdsy_prefixcmd_t)(mididev_info *md, int status);
typedef int (mdsy_volumemethod_t)(mididev_info *md, int mode);
typedef int (mdsy_readraw_t)(mididev_info *md, u_char *buf, int len, int nonblock);
typedef int (mdsy_writeraw_t)(mididev_info *md, u_char *buf, int len, int nonblock);
typedef int (mdsy_readraw_t)(mididev_info *md, u_char *buf, int len, int *lenr, int nonblock);
typedef int (mdsy_writeraw_t)(mididev_info *md, u_char *buf, int len, int *lenw, int nonblock);
/*
* The order of mutex lock (from the first to the last)

View File

@ -30,5 +30,5 @@
typedef struct _mididev_info mididev_info;
typedef int (midi_callback_t)(mididev_info *d, int reason);
typedef int (midi_callback_t)(void *d, int reason);
typedef void (midi_intr_t)(void *p, mididev_info *md);

View File

@ -69,7 +69,7 @@ enum {
*/
static midi_intr_t seq_intr;
static seq_callback_t seq_callback;
static midi_callback_t seq_callback;
/* These are the entries to the sequencer driver. */
static d_open_t seq_open;
@ -372,9 +372,10 @@ seq_close(dev_t i_dev, int flags, int mode, struct thread *td)
int
seq_read(dev_t i_dev, struct uio *buf, int flag)
{
int unit, ret, len;
int unit, ret, len, lenr;
sc_p scp;
seqdev_info *sd;
u_char *uiobuf;
unit = MIDIUNIT(i_dev);
@ -396,27 +397,34 @@ seq_read(dev_t i_dev, struct uio *buf, int flag)
return (EIO);
}
len = buf->uio_resid;
lenr = 0;
uiobuf = (u_char *)malloc(len, M_DEVBUF, M_WAITOK | M_ZERO);
if (uiobuf == NULL)
return (ENOMEM);
mtx_lock(&sd->flagqueue_mtx);
/* Begin recording. */
if ((sd->flags & SEQ_F_READING) == 0)
sd->callback(sd, SEQ_CB_START | SEQ_CB_RD);
len = 0;
/* Have we got the data to read? */
if ((sd->flags & SEQ_F_NBIO) != 0 && sd->midi_dbuf_in.rl == 0)
ret = EAGAIN;
else {
len = buf->uio_resid;
ret = midibuf_uioread(&sd->midi_dbuf_in, buf, len, &sd->flagqueue_mtx);
if (ret < 0)
ret = -ret;
else
ret = 0;
}
else
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);
if (ret == 0 && lenr > 0)
ret = uiomove(uiobuf, lenr, buf);
free(uiobuf, M_DEVBUF);
return (ret);
}
@ -965,10 +973,13 @@ seq_intr(void *p, mididev_info *md)
}
static int
seq_callback(seqdev_info *sd, int reason)
seq_callback(void *d, int reason)
{
int unit;
sc_p scp;
seqdev_info *sd;
sd = (seqdev_info *)d;
/*DEB(printf("seq_callback: reason 0x%x.\n", reason));*/
@ -1020,7 +1031,7 @@ seq_callback(seqdev_info *sd, int reason)
static int
seq_queue(sc_p scp, u_char *note)
{
int unit, err;
int unit, err, lenw;
seqdev_info *sd;
sd = scp->devinfo;
@ -1030,10 +1041,8 @@ seq_queue(sc_p scp, u_char *note)
/*DEB(printf("seq%d: queueing.\n", unit));*/
if ((sd->flags & SEQ_F_INSYNC) != 0) {
if ((sd->flags & SEQ_F_INSYNC) != 0)
cv_wait(&sd->insync_cv, &sd->flagqueue_mtx);
cv_signal(&sd->insync_cv);
}
if (sd->midi_dbuf_out.fl < EV_SZ) {
/* We have no space. Start playing if not yet. */
@ -1042,26 +1051,14 @@ seq_queue(sc_p scp, u_char *note)
if ((sd->flags & SEQ_F_NBIO) != 0 && sd->midi_dbuf_out.fl < EV_SZ)
/* We would block. */
return (EAGAIN);
else {
while (sd->midi_dbuf_out.fl < EV_SZ) {
/* We have no space. Good night. */
err = msleep(&sd->midi_dbuf_out.tsleep_out, &sd->flagqueue_mtx, PRIBIO | PCATCH, "seqque", 0);
if (err == EINTR || err == ERESTART) {
if (err == EINTR)
sd->callback(sd, SEQ_CB_STOP | SEQ_CB_WR);
return (err);
}
}
}
}
/* We now have enough space to write. */
err = midibuf_seqwrite(&sd->midi_dbuf_out, note, EV_SZ, &sd->flagqueue_mtx);
/* Write to the queue. */
err = midibuf_seqwrite(&sd->midi_dbuf_out, note, EV_SZ, &lenw,
sd->callback, sd, SEQ_CB_START | SEQ_CB_WR,
&sd->flagqueue_mtx);
if (err < 0)
err = -err;
else {
err = 0;
if (err == 0) {
/* Start playing if we have some data in the queue. */
if (sd->midi_dbuf_out.rl >= EV_SZ && ((sd->flags & SEQ_F_WRITING) == 0))
sd->callback(sd, SEQ_CB_START | SEQ_CB_WR);
@ -1073,7 +1070,7 @@ seq_queue(sc_p scp, u_char *note)
static void
seq_startplay(sc_p scp)
{
int unit;
int unit, lenr;
u_char event[EV_SZ];
seqdev_info *sd;
@ -1082,19 +1079,28 @@ seq_startplay(sc_p scp)
mtx_assert(&sd->flagqueue_mtx, MA_OWNED);
sd->flags |= SEQ_F_WRITING;
/* Dequeue the events to play. */
while (sd->midi_dbuf_out.rl >= EV_SZ) {
midibuf_seqread(&sd->midi_dbuf_out, event, EV_SZ, &sd->flagqueue_mtx);
midibuf_seqcopy(&sd->midi_dbuf_out, event, EV_SZ, &lenr,
NULL, NULL, 0,
&sd->flagqueue_mtx);
switch (seq_playevent(scp, event)) {
case TIMERARMED:
midibuf_seqdelete(&sd->midi_dbuf_out, EV_SZ, &lenr,
NULL, NULL, 0,
&sd->flagqueue_mtx);
return;
case QUEUEFULL:
/* We cannot play any further. */
midibuf_sequnread(&sd->midi_dbuf_out, event, EV_SZ, &sd->flagqueue_mtx);
return;
case MORE:
midibuf_seqdelete(&sd->midi_dbuf_out, EV_SZ, &lenr,
NULL, NULL, 0,
&sd->flagqueue_mtx);
break;
}
}
@ -1106,7 +1112,7 @@ seq_startplay(sc_p scp)
static int
seq_playevent(sc_p scp, u_char *event)
{
int unit, ret;
int unit, ret, lenw;
long *delay;
seqdev_info *sd;
mididev_info *md;
@ -1182,14 +1188,12 @@ seq_playevent(sc_p scp, u_char *event)
break;
}
mtx_unlock(&sd->flagqueue_mtx);
if (md->synth.writeraw(md, &event[1], sizeof(event[1]), 1) == EAGAIN) {
mtx_lock(&sd->flagqueue_mtx);
if (md->synth.writeraw(md, &event[1], sizeof(event[1]), &lenw, 1) == EAGAIN)
/* The queue was full. Try again later. */
ret = QUEUEFULL;
break;
}
else
ret = MORE;
mtx_lock(&sd->flagqueue_mtx);
ret = MORE;
break;
case SEQ_ECHO:
/* Echo this event back. */
@ -1325,7 +1329,7 @@ seq_stoptimer(sc_p scp)
static void
seq_midiinput(sc_p scp, mididev_info *md)
{
int unit, midiunit;
int unit, midiunit, lenr;
u_long tstamp;
u_char event[4];
seqdev_info *sd;
@ -1342,7 +1346,7 @@ seq_midiinput(sc_p scp, mididev_info *md)
if ((md->flags & MIDI_F_READING) != 0 && md->intrarg == sd) {
/* Read the input data. */
while (md->synth.readraw(md, &event[1], sizeof(event[1]), 1) == 0) {
while (md->synth.readraw(md, &event[1], sizeof(event[1]), &lenr, 1) == 0) {
tstamp = seq_gettime() - scp->seq_time;
if (tstamp != scp->prev_input_time) {
/* Insert a wait between events. */
@ -1361,16 +1365,16 @@ seq_midiinput(sc_p scp, mididev_info *md)
static int
seq_copytoinput(sc_p scp, u_char *event, int len)
{
int ret, leni;
seqdev_info *sd;
sd = scp->devinfo;
mtx_assert(&sd->flagqueue_mtx, MA_OWNED);
if (midibuf_input_intr(&sd->midi_dbuf_in, event, len) == -EAGAIN)
return (EAGAIN);
ret = midibuf_input_intr(&sd->midi_dbuf_in, event, len, &leni);
return (0);
return (ret);
}
static int
@ -1482,7 +1486,7 @@ seq_chnvoice(sc_p scp, u_char *event)
#if notyet
if (voice == -1 && scp->seq_mode == SEQ_2 && md->synth.allocvoice)
/* This is an internal synthesizer. (FM, GUS, etc) */
if ((voice = seq_allocvoice(scp, md, chn, note)) == -EAGAIN)
if ((voice = seq_allocvoice(scp, md, chn, note)) == EAGAIN)
return (QUEUEFULL);
#endif /* notyet */
if (voice == -1)
@ -1572,9 +1576,9 @@ seq_allocvoice(sc_p scp, mididev_info *md, int chn, int note)
key = (chn << 8) | (note + 1);
mtx_unlock(&scp->devinfo->flagqueue_mtx);
if ((voice = md->synth.allocvoice(md, chn, note, &md->synth.alloc)) == -EAGAIN) {
if ((voice = md->synth.allocvoice(md, chn, note, &md->synth.alloc)) == EAGAIN) {
mtx_lock(&scp->devinfo->flagqueue_mtx);
return (-EAGAIN);
return (EAGAIN);
}
mtx_lock(&scp->devinfo->flagqueue_mtx);
@ -1737,9 +1741,9 @@ seq_timing(sc_p scp, u_char *event)
#endif /* notyet */
switch (event[1]) {
case TMR_WAIT_REL:
parm += scp->prev_event_time;
/* FALLTHRU */
case TMR_WAIT_ABS:
if (event[1] == TMR_WAIT_REL)
parm += scp->prev_event_time;
if (parm > 0) {
sd->flags |= SEQ_F_WRITING;
if (seq_requesttimer(scp, parm))
@ -1881,7 +1885,7 @@ seq_openmidi(sc_p scp, mididev_info *md, int flags, int mode, struct thread *td)
TAILQ_INSERT_TAIL(&scp->midi_open, md, md_linkseq);
if (insync)
cv_signal(&scp->devinfo->insync_cv);
cv_broadcast(&scp->devinfo->insync_cv);
return (0);
}
@ -1916,7 +1920,7 @@ seq_closemidi(sc_p scp, mididev_info *md, int flags, int mode, struct thread *td
TAILQ_REMOVE(&scp->midi_open, md, md_linkseq);
if (insync)
cv_signal(&scp->devinfo->insync_cv);
cv_broadcast(&scp->devinfo->insync_cv);
return (0);
}
@ -1932,7 +1936,7 @@ seq_panic(sc_p scp)
static int
seq_reset(sc_p scp)
{
int unit, chn;
int unit, chn, lenw;
seqdev_info *sd;
mididev_info *md;
u_char c[3];
@ -1942,10 +1946,8 @@ seq_reset(sc_p scp)
mtx_assert(&sd->flagqueue_mtx, MA_OWNED);
if ((sd->flags & SEQ_F_INSYNC) != 0) {
if ((sd->flags & SEQ_F_INSYNC) != 0)
cv_wait(&sd->insync_cv, &sd->flagqueue_mtx);
cv_signal(&sd->insync_cv);
}
/* Stop reading and writing. */
sd->callback(sd, SEQ_CB_ABORT | SEQ_CB_RD | SEQ_CB_WR);
@ -1977,11 +1979,11 @@ seq_reset(sc_p scp)
c[0] = 0xb0 | (chn & 0x0f);
c[1] = (u_char)0x78; /* All sound off */
c[2] = (u_char)0;
md->synth.writeraw(md, c, 3, 0);
md->synth.writeraw(md, c, 3, &lenw, 0);
c[1] = (u_char)0x7b; /* All note off */
md->synth.writeraw(md, c, 3, 0);
md->synth.writeraw(md, c, 3, &lenw, 0);
c[1] = (u_char)0x79; /* Reset all controller */
md->synth.writeraw(md, c, 3, 0);
md->synth.writeraw(md, c, 3, &lenw, 0);
}
}
seq_sync(scp);
@ -2012,7 +2014,7 @@ seq_sync(sc_p scp)
if ((sd->flags & SEQ_F_WRITING) == 0)
sd->callback(sd, SEQ_CB_START | SEQ_CB_WR);
rl = sd->midi_dbuf_out.rl;
i = msleep(&sd->midi_dbuf_out.tsleep_out, &sd->flagqueue_mtx, PRIBIO | PCATCH, "seqsnc", SEQ_SYNC_TIMEOUT * hz);
i = cv_timedwait_sig(&sd->midi_dbuf_out.cv_out, &sd->flagqueue_mtx, SEQ_SYNC_TIMEOUT * hz);
if (i == EINTR || i == ERESTART) {
if (i == EINTR)
sd->callback(sd, SEQ_CB_STOP | SEQ_CB_WR);
@ -2048,7 +2050,7 @@ seq_sync(sc_p scp)
mtx_lock(&sd->flagqueue_mtx);
sd->flags &= ~SEQ_F_INSYNC;
cv_signal(&sd->insync_cv);
cv_broadcast(&sd->insync_cv);
return (0);
}

View File

@ -68,8 +68,6 @@
typedef struct _seqdev_info seqdev_info;
typedef int (seq_callback_t)(seqdev_info *sd, int reason);
/*
* The order of mutex lock (from the first to the last)
*
@ -101,7 +99,7 @@ struct _seqdev_info {
d_write_t *write;
d_ioctl_t *ioctl;
d_poll_t *poll;
seq_callback_t *callback;
midi_callback_t *callback;
/*
* combinations of the following flags are used as second argument in
@ -234,7 +232,7 @@ struct _seqdev_info {
/*
* finally, all default parameters
*/
#define SEQ_BUFFSIZE (4 * 1024) /* XXX */
#define SEQ_BUFFSIZE (1024) /* XXX */
/*
* some macros for debugging purposes

View File

@ -113,7 +113,7 @@ static void csamidi_xmit(sc_p scp);
static int csamidi_reset(sc_p scp);
static int csamidi_status(sc_p scp);
static int csamidi_command(sc_p scp, u_int32_t value);
static int csamidi_readdata(sc_p scp);
static int csamidi_readdata(sc_p scp, u_int8_t *value);
static int csamidi_writedata(sc_p scp, u_int32_t value);
static u_int32_t csamidi_readio(sc_p scp, u_long offset);
static void csamidi_writeio(sc_p scp, u_long offset, u_int32_t data);
@ -261,6 +261,7 @@ csamidi_intr(void *arg)
sc_p scp;
u_char c;
mididev_info *devinfo;
int leni;
scp = (sc_p)arg;
devinfo = scp->devinfo;
@ -271,17 +272,17 @@ csamidi_intr(void *arg)
/* Read the received data. */
while ((csamidi_status(scp) & MIDSR_RBE) == 0) {
/* Receive the data. */
c = (u_char)csamidi_readdata(scp);
csamidi_readdata(scp, &c);
mtx_unlock(&scp->mtx);
/* Queue into the passthru buffer and start transmitting if we can. */
if ((devinfo->flags & MIDI_F_PASSTHRU) != 0 && ((devinfo->flags & MIDI_F_BUSY) == 0 || (devinfo->fflags & FWRITE) == 0)) {
midibuf_input_intr(&devinfo->midi_dbuf_passthru, &c, sizeof(c));
midibuf_input_intr(&devinfo->midi_dbuf_passthru, &c, sizeof(c), &leni);
devinfo->callback(devinfo, MIDI_CB_START | MIDI_CB_WR);
}
/* Queue if we are reading. Discard an active sensing. */
if ((devinfo->flags & MIDI_F_READING) != 0 && c != 0xfe) {
midibuf_input_intr(&devinfo->midi_dbuf_in, &c, sizeof(c));
midibuf_input_intr(&devinfo->midi_dbuf_in, &c, sizeof(c), &leni);
}
mtx_lock(&scp->mtx);
}
@ -298,10 +299,13 @@ csamidi_intr(void *arg)
}
static int
csamidi_callback(mididev_info *d, int reason)
csamidi_callback(void *di, int reason)
{
int unit;
sc_p scp;
mididev_info *d;
d = (mididev_info *)di;
mtx_assert(&d->flagqueue_mtx, MA_OWNED);
@ -366,6 +370,7 @@ csamidi_xmit(sc_p scp)
register mididev_info *devinfo;
register midi_dbuf *dbuf;
u_char c;
int leno;
devinfo = scp->devinfo;
@ -391,7 +396,7 @@ csamidi_xmit(sc_p scp)
break;
}
/* Send the data. */
midibuf_output_intr(dbuf, &c, sizeof(c));
midibuf_output_intr(dbuf, &c, sizeof(c), &leno);
csamidi_writedata(scp, c);
/* We are playing now. */
devinfo->flags |= MIDI_F_WRITING;
@ -452,17 +457,22 @@ csamidi_command(sc_p scp, u_int32_t value)
/* Reads a byte of data. */
static int
csamidi_readdata(sc_p scp)
csamidi_readdata(sc_p scp, u_int8_t *value)
{
u_int status;
if (value == NULL)
return (EINVAL);
/* Is the interface ready to read? */
status = csamidi_status(scp);
if ((status & MIDSR_RBE) != 0)
/* The interface is busy. */
return (-EAGAIN);
return (EAGAIN);
return (int)csamidi_readio(scp, BA0_MIDRP) & 0xff;
*value = (u_int8_t)(csamidi_readio(scp, BA0_MIDRP) & 0xff);
return (0);
}
/* Writes a byte of data. */