summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlexandre Ratchov <ratchov@cvs.openbsd.org>2012-03-30 08:18:20 +0000
committerAlexandre Ratchov <ratchov@cvs.openbsd.org>2012-03-30 08:18:20 +0000
commit5dea4f0939f565b7f438e71b0227ea049143f269 (patch)
tree40c06dc60075e2a6fa086379d213d3bd83b822de
parentdea3c9e45ef09b352b75fac87e163b705debf46d (diff)
If the MIDI UART is not ready for output, don't spin at IPL_CLOCK;
just return and make the midi(4) driver retry later. UART buffers are large enough for this, except eap(4) which uses interrupts for output. help from and ok jsg@
-rw-r--r--sys/dev/isa/mpu401.c12
-rw-r--r--sys/dev/isa/sbdsp.c9
-rw-r--r--sys/dev/midi.c66
-rw-r--r--sys/dev/midivar.h3
-rw-r--r--sys/dev/pci/autri.c14
-rw-r--r--sys/dev/pci/eap.c43
-rw-r--r--sys/dev/pci/eapreg.h5
-rw-r--r--sys/dev/pci/envy.c9
-rw-r--r--sys/dev/usb/umidi.c68
-rw-r--r--sys/dev/usb/umidivar.h4
10 files changed, 75 insertions, 158 deletions
diff --git a/sys/dev/isa/mpu401.c b/sys/dev/isa/mpu401.c
index 9e98db5a536..593d0b0fd23 100644
--- a/sys/dev/isa/mpu401.c
+++ b/sys/dev/isa/mpu401.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: mpu401.c,v 1.11 2008/06/26 05:42:16 ray Exp $ */
+/* $OpenBSD: mpu401.c,v 1.12 2012/03/30 08:18:19 ratchov Exp $ */
/* $NetBSD: mpu401.c,v 1.3 1998/11/25 22:17:06 augustss Exp $ */
/*
@@ -208,12 +208,12 @@ mpu_output(v, d)
mpu_readinput(sc);
splx(s);
}
- if (mpu_waitready(sc)) {
- DPRINTF(("mpu_output: not ready\n"));
- return EIO;
- }
+ if (MPU_GETSTATUS(sc->iot, sc->ioh) & MPU_OUTPUT_BUSY)
+ delay(10);
+ if (MPU_GETSTATUS(sc->iot, sc->ioh) & MPU_OUTPUT_BUSY)
+ return 0;
bus_space_write_1(sc->iot, sc->ioh, MPU_DATA, d);
- return 0;
+ return 1;
}
void
diff --git a/sys/dev/isa/sbdsp.c b/sys/dev/isa/sbdsp.c
index 32d63f06567..5c5a507f13c 100644
--- a/sys/dev/isa/sbdsp.c
+++ b/sys/dev/isa/sbdsp.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: sbdsp.c,v 1.31 2010/07/15 03:43:11 jakemsr Exp $ */
+/* $OpenBSD: sbdsp.c,v 1.32 2012/03/30 08:18:19 ratchov Exp $ */
/*
* Copyright (c) 1991-1993 Regents of the University of California.
@@ -2385,10 +2385,9 @@ sbdsp_midi_output(addr, d)
struct sbdsp_softc *sc = addr;
if (sc->sc_model < SB_20 && sbdsp_wdsp(sc, SB_MIDI_WRITE))
- return EIO;
- if (sbdsp_wdsp(sc, d))
- return EIO;
- return 0;
+ return 1;
+ (void)sbdsp_wdsp(sc, d);
+ return 1;
}
void
diff --git a/sys/dev/midi.c b/sys/dev/midi.c
index d0fb2bb9a5c..45d985a0e6e 100644
--- a/sys/dev/midi.c
+++ b/sys/dev/midi.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: midi.c,v 1.26 2011/07/02 22:20:07 nicm Exp $ */
+/* $OpenBSD: midi.c,v 1.27 2012/03/30 08:18:19 ratchov Exp $ */
/*
* Copyright (c) 2003, 2004 Alexandre Ratchov
@@ -232,51 +232,14 @@ void
midi_out_do(struct midi_softc *sc)
{
struct midi_buffer *mb = &sc->outbuf;
- unsigned i;
- int error;
- /*
- * If output interrupts are not supported then we write MIDI_MAXWRITE
- * bytes instead of 1, and then we wait sc->wait
- */
-
- i = sc->props & MIDI_PROP_OUT_INTR ? 1 : MIDI_MAXWRITE;
- while (i != 0) {
- if (mb->used == 0)
+ while (mb->used > 0) {
+ if (!sc->hw_if->output(sc->hw_hdl, mb->data[mb->start]))
break;
- error = sc->hw_if->output(sc->hw_hdl, mb->data[mb->start]);
- /*
- * 0 means that data is being sent, an interrupt will
- * be generated when the interface becomes ready again
- *
- * EINPROGRESS means that data has been queued, but
- * will not be sent immediately and thus will not
- * generate interrupt, in this case we can send
- * another byte. The flush() method can be called
- * to force the transfer.
- *
- * EAGAIN means that data cannot be queued or sent;
- * because the interface isn't ready. An interrupt
- * will be generated once the interface is ready again
- *
- * any other (fatal) error code means that data couldn't
- * be sent and was lost, interrupt will not be generated
- */
- if (error == EINPROGRESS) {
- MIDIBUF_REMOVE(mb, 1);
- if (MIDIBUF_ISEMPTY(mb)) {
- if (sc->hw_if->flush != NULL)
- sc->hw_if->flush(sc->hw_hdl);
- midi_out_stop(sc);
- return;
- }
- } else if (error == 0) {
- MIDIBUF_REMOVE(mb, 1);
- i--;
- } else if (error == EAGAIN) {
- break;
- } else {
- MIDIBUF_INIT(mb);
+ MIDIBUF_REMOVE(mb, 1);
+ if (MIDIBUF_ISEMPTY(mb)) {
+ if (sc->hw_if->flush != NULL)
+ sc->hw_if->flush(sc->hw_hdl);
midi_out_stop(sc);
return;
}
@@ -286,7 +249,7 @@ midi_out_do(struct midi_softc *sc)
if (MIDIBUF_ISEMPTY(mb))
midi_out_stop(sc);
else
- timeout_add(&sc->timeo, sc->wait);
+ timeout_add(&sc->timeo, 1);
}
}
@@ -554,13 +517,11 @@ midiclose(dev_t dev, int fflag, int devtype, struct proc *p)
/*
* some hw_if->close() reset immediately the midi uart
* which flushes the internal buffer of the uart device,
- * so we may lose some (important) data. To avoid this, we sleep 2*wait,
- * which gives the time to the uart to drain its internal buffers.
- *
- * Note: we'd better sleep in the corresponding hw_if->close()
+ * so we may lose some (important) data. To avoid this,
+ * sleep 20ms (around 64 bytes) to give the time to the
+ * uart to drain its internal buffers.
*/
-
- tsleep(&sc->wchan, PWAIT, "mid_cl", 2 * sc->wait);
+ tsleep(&sc->wchan, PWAIT, "mid_cl", hz * MIDI_MAXWRITE / MIDI_RATE);
sc->hw_if->close(sc->hw_hdl);
sc->isopen = 0;
return 0;
@@ -582,9 +543,6 @@ midi_attach(struct midi_softc *sc, struct device *parent)
struct midi_info mi;
sc->isdying = 0;
- sc->wait = (hz * MIDI_MAXWRITE) / MIDI_RATE;
- if (sc->wait == 0)
- sc->wait = 1;
sc->hw_if->getinfo(sc->hw_hdl, &mi);
sc->props = mi.props;
sc->isopen = 0;
diff --git a/sys/dev/midivar.h b/sys/dev/midivar.h
index 427a841391c..e2987e5c3f7 100644
--- a/sys/dev/midivar.h
+++ b/sys/dev/midivar.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: midivar.h,v 1.5 2005/11/21 18:16:38 millert Exp $ */
+/* $OpenBSD: midivar.h,v 1.6 2012/03/30 08:18:19 ratchov Exp $ */
/*
* Copyright (c) 2003, 2004 Alexandre Ratchov
@@ -85,7 +85,6 @@ struct midi_softc {
int props; /* midi hw proprieties */
int rchan;
int wchan;
- unsigned wait; /* see midi_out_do */
struct selinfo rsel;
struct selinfo wsel;
struct proc *async;
diff --git a/sys/dev/pci/autri.c b/sys/dev/pci/autri.c
index 57490580e76..78ba73425a1 100644
--- a/sys/dev/pci/autri.c
+++ b/sys/dev/pci/autri.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: autri.c,v 1.30 2011/07/03 15:47:16 matthew Exp $ */
+/* $OpenBSD: autri.c,v 1.31 2012/03/30 08:18:19 ratchov Exp $ */
/*
* Copyright (c) 2001 SOMEYA Yoshihiko and KUROSAWA Takahiro.
@@ -1612,16 +1612,12 @@ int
autri_midi_output(void *addr, int d)
{
struct autri_softc *sc = addr;
- int x;
- for (x = 0; x != MIDI_BUSY_WAIT; x++) {
- if ((TREAD1(sc, AUTRI_MPUR1) & AUTRI_MIDIOUT_READY) == 0) {
- TWRITE1(sc, AUTRI_MPUR0, d);
- return (0);
- }
- delay(MIDI_BUSY_DELAY);
+ if ((TREAD1(sc, AUTRI_MPUR1) & AUTRI_MIDIOUT_READY) != 0) {
+ TWRITE1(sc, AUTRI_MPUR0, d);
+ return 0;
}
- return (EIO);
+ return 1;
}
void
diff --git a/sys/dev/pci/eap.c b/sys/dev/pci/eap.c
index 21ffa7e7ded..7382cf5fcd5 100644
--- a/sys/dev/pci/eap.c
+++ b/sys/dev/pci/eap.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: eap.c,v 1.43 2011/07/03 15:47:17 matthew Exp $ */
+/* $OpenBSD: eap.c,v 1.44 2012/03/30 08:18:19 ratchov Exp $ */
/* $NetBSD: eap.c,v 1.46 2001/09/03 15:07:37 reinoud Exp $ */
/*
@@ -128,6 +128,7 @@ struct eap_softc {
void (*sc_iintr)(void *, int); /* midi input ready handler */
void (*sc_ointr)(void *); /* midi output ready handler */
void *sc_arg;
+ int sc_uctrl;
struct device *sc_mididev;
#endif
@@ -776,15 +777,22 @@ eap_intr(void *p)
sc->sc_pintr(sc->sc_parg);
}
#if NMIDI > 0
- if ((intr & EAP_I_UART) && sc->sc_iintr != NULL) {
+ if (intr & EAP_I_UART) {
u_int32_t data;
if (EREAD1(sc, EAP_UART_STATUS) & EAP_US_RXINT) {
while (EREAD1(sc, EAP_UART_STATUS) & EAP_US_RXRDY) {
data = EREAD1(sc, EAP_UART_DATA);
- sc->sc_iintr(sc->sc_arg, data);
+ if (sc->sc_iintr)
+ sc->sc_iintr(sc->sc_arg, data);
}
}
+ if (EREAD1(sc, EAP_UART_STATUS) & EAP_US_TXINT) {
+ sc->sc_uctrl &= ~EAP_UC_TXINTEN;
+ EWRITE1(sc, EAP_UART_CONTROL, sc->sc_uctrl);
+ if (sc->sc_ointr)
+ sc->sc_ointr(sc->sc_arg);
+ }
}
#endif
return (1);
@@ -1670,22 +1678,16 @@ eap_midi_open(void *addr, int flags,
void *arg)
{
struct eap_softc *sc = addr;
- u_int32_t uctrl;
sc->sc_iintr = iintr;
sc->sc_ointr = ointr;
sc->sc_arg = arg;
EWRITE4(sc, EAP_ICSC, EREAD4(sc, EAP_ICSC) | EAP_UART_EN);
- uctrl = 0;
+ sc->sc_uctrl = 0;
if (flags & FREAD)
- uctrl |= EAP_UC_RXINTEN;
-#if 0
- /* I don't understand ../midi.c well enough to use output interrupts */
- if (flags & FWRITE)
- uctrl |= EAP_UC_TXINTEN; */
-#endif
- EWRITE1(sc, EAP_UART_CONTROL, uctrl);
+ sc->sc_uctrl |= EAP_UC_RXINTEN;
+ EWRITE1(sc, EAP_UART_CONTROL, sc->sc_uctrl);
return (0);
}
@@ -1707,23 +1709,20 @@ int
eap_midi_output(void *addr, int d)
{
struct eap_softc *sc = addr;
- int x;
- for (x = 0; x != MIDI_BUSY_WAIT; x++) {
- if (EREAD1(sc, EAP_UART_STATUS) & EAP_US_TXRDY) {
- EWRITE1(sc, EAP_UART_DATA, d);
- return (0);
- }
- delay(MIDI_BUSY_DELAY);
- }
- return (EIO);
+ if (!(EREAD1(sc, EAP_UART_STATUS) & EAP_US_TXRDY))
+ return 0;
+ EWRITE1(sc, EAP_UART_DATA, d);
+ sc->sc_uctrl |= EAP_UC_TXINTEN;
+ EWRITE1(sc, EAP_UART_CONTROL, sc->sc_uctrl);
+ return 1;
}
void
eap_midi_getinfo(void *addr, struct midi_info *mi)
{
mi->name = "AudioPCI MIDI UART";
- mi->props = MIDI_PROP_CAN_INPUT;
+ mi->props = MIDI_PROP_CAN_INPUT | MIDI_PROP_OUT_INTR;
}
#endif
diff --git a/sys/dev/pci/eapreg.h b/sys/dev/pci/eapreg.h
index e30502f7c6c..dbc46d45b13 100644
--- a/sys/dev/pci/eapreg.h
+++ b/sys/dev/pci/eapreg.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: eapreg.h,v 1.3 2008/06/26 05:42:17 ray Exp $ */
+/* $OpenBSD: eapreg.h,v 1.4 2012/03/30 08:18:19 ratchov Exp $ */
/* $NetBSD: eapreg.h,v 1.10 2005/02/13 23:58:38 fredb Exp $ */
/*
@@ -263,9 +263,6 @@
#define EAP_RECORD_CLASS 11
#define EAP_INPUT_CLASS 12
-#define MIDI_BUSY_WAIT 100
-#define MIDI_BUSY_DELAY 100 /* Delay when UART is busy */
-
#define EAP_EV1938_A 0x00
#define EAP_ES1371_A 0x02
#define EAP_CT5880_C 0x02
diff --git a/sys/dev/pci/envy.c b/sys/dev/pci/envy.c
index cc7ea390719..86428bfc29b 100644
--- a/sys/dev/pci/envy.c
+++ b/sys/dev/pci/envy.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: envy.c,v 1.50 2011/04/27 07:01:33 ratchov Exp $ */
+/* $OpenBSD: envy.c,v 1.51 2012/03/30 08:18:19 ratchov Exp $ */
/*
* Copyright (c) 2007 Alexandre Ratchov <alex@caoua.org>
*
@@ -2390,10 +2390,13 @@ int
envy_midi_output(void *self, int data)
{
struct envy_softc *sc = (struct envy_softc *)self;
+ int st;
- envy_midi_wait(sc);
+ st = envy_ccs_read(sc, ENVY_CCS_MIDISTAT0);
+ if (st & ENVY_MIDISTAT_OBUSY(sc))
+ return 0;
envy_ccs_write(sc, ENVY_CCS_MIDIDATA0, data);
- return 0;
+ return 1;
}
void
diff --git a/sys/dev/usb/umidi.c b/sys/dev/usb/umidi.c
index c2c4fb0f7a4..73ac99ef278 100644
--- a/sys/dev/usb/umidi.c
+++ b/sys/dev/usb/umidi.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: umidi.c,v 1.32 2011/07/03 15:47:17 matthew Exp $ */
+/* $OpenBSD: umidi.c,v 1.33 2012/03/30 08:18:19 ratchov Exp $ */
/* $NetBSD: umidi.c,v 1.16 2002/07/11 21:14:32 augustss Exp $ */
/*
* Copyright (c) 2001 The NetBSD Foundation, Inc.
@@ -313,7 +313,7 @@ umidi_output(void *addr, int d)
struct umidi_mididev *mididev = addr;
if (!mididev->out_jack || !mididev->opened)
- return EIO;
+ return 1;
return out_jack_output(mididev->out_jack, d);
}
@@ -745,9 +745,7 @@ alloc_all_jacks(struct umidi_softc *sc)
jack->binded = 0;
jack->arg = NULL;
jack->u.out.intr = NULL;
-#ifdef DIAGNOSTIC
- jack->wait = 0;
-#endif
+ jack->intr = 0;
jack->cable_number = i;
jack++;
}
@@ -1165,56 +1163,31 @@ out_jack_output(struct umidi_jack *j, int d)
int s;
if (sc->sc_dying)
- return EIO;
+ return 1;
if (!j->opened)
- return ENODEV;
-
+ return 1;
s = splusb();
- if (ep->used == ep->packetsize) {
-#ifdef DIAGNOSTIC
- if (j->wait == 0) {
- j->wait = 1;
-#endif
+ if (ep->busy) {
+ if (!j->intr) {
SIMPLEQ_INSERT_TAIL(&ep->intrq, j, intrq_entry);
ep->pending++;
-#ifdef DIAGNOSTIC
- } else {
- printf("umidi: (again) %d: already on intrq\n",
- j->cable_number);
- }
-#endif
+ j->intr = 1;
+ }
splx(s);
- return EAGAIN;
+ return 0;
}
-
- if (!out_build_packet(j->cable_number, &j->packet, d,
- ep->buffer + ep->used)) {
+ if (!out_build_packet(j->cable_number, &j->packet, d,
+ ep->buffer + ep->used)) {
splx(s);
- return EINPROGRESS;
+ return 1;
}
ep->used += UMIDI_PACKET_SIZE;
- if (ep->used < ep->packetsize) {
- splx(s);
- return EINPROGRESS;
- }
-#ifdef DIAGNOSTIC
- if (j->wait == 0) {
- j->wait = 1;
-#endif
- SIMPLEQ_INSERT_TAIL(&ep->intrq, j, intrq_entry);
- ep->pending++;
-#ifdef DIAGNOSTIC
- } else {
- printf("umidi: (ok) %d: already on intrq\n",
- j->cable_number);
- }
-#endif
- if (!ep->busy) {
+ if (ep->used == ep->packetsize) {
ep->busy = 1;
start_output_transfer(ep);
}
splx(s);
- return 0;
+ return 1;
}
static void
@@ -1278,6 +1251,7 @@ out_intr(usbd_xfer_handle xfer, usbd_private_handle priv, usbd_status status)
return;
ep->used = 0;
+ ep->busy = 0;
for (pending = ep->pending; pending > 0; pending--) {
j = SIMPLEQ_FIRST(&ep->intrq);
#ifdef DIAGNOSTIC
@@ -1288,18 +1262,10 @@ out_intr(usbd_xfer_handle xfer, usbd_private_handle priv, usbd_status status)
#endif
SIMPLEQ_REMOVE_HEAD(&ep->intrq, intrq_entry);
ep->pending--;
-#ifdef DIAGNOSTIC
- j->wait = 0;
-#endif
+ j->intr = 0;
if (j->opened && j->u.out.intr)
(*j->u.out.intr)(j->arg);
}
-
- if (ep->used == 0) {
- ep->busy = 0;
- } else {
- start_output_transfer(ep);
- }
}
#define UMIDI_VOICELEN(status) (umidi_evlen[((status) >> 4) & 7])
diff --git a/sys/dev/usb/umidivar.h b/sys/dev/usb/umidivar.h
index 04dcce64fd0..0a3f908eb33 100644
--- a/sys/dev/usb/umidivar.h
+++ b/sys/dev/usb/umidivar.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: umidivar.h,v 1.12 2008/06/26 05:42:19 ray Exp $ */
+/* $OpenBSD: umidivar.h,v 1.13 2012/03/30 08:18:19 ratchov Exp $ */
/* $NetBSD: umidivar.h,v 1.5 2002/09/12 21:00:42 augustss Exp $ */
/*
* Copyright (c) 2001 The NetBSD Foundation, Inc.
@@ -69,7 +69,7 @@ struct umidi_jack {
int opened;
SIMPLEQ_ENTRY(umidi_jack) intrq_entry;
#ifdef DIAGNOSTIC
- unsigned wait;
+ unsigned intr;
#endif
union {
struct {