diff options
author | Alexandre Ratchov <ratchov@cvs.openbsd.org> | 2012-03-30 08:18:20 +0000 |
---|---|---|
committer | Alexandre Ratchov <ratchov@cvs.openbsd.org> | 2012-03-30 08:18:20 +0000 |
commit | 5dea4f0939f565b7f438e71b0227ea049143f269 (patch) | |
tree | 40c06dc60075e2a6fa086379d213d3bd83b822de | |
parent | dea3c9e45ef09b352b75fac87e163b705debf46d (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.c | 12 | ||||
-rw-r--r-- | sys/dev/isa/sbdsp.c | 9 | ||||
-rw-r--r-- | sys/dev/midi.c | 66 | ||||
-rw-r--r-- | sys/dev/midivar.h | 3 | ||||
-rw-r--r-- | sys/dev/pci/autri.c | 14 | ||||
-rw-r--r-- | sys/dev/pci/eap.c | 43 | ||||
-rw-r--r-- | sys/dev/pci/eapreg.h | 5 | ||||
-rw-r--r-- | sys/dev/pci/envy.c | 9 | ||||
-rw-r--r-- | sys/dev/usb/umidi.c | 68 | ||||
-rw-r--r-- | sys/dev/usb/umidivar.h | 4 |
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 { |