Subject: Re: /dev/music weirdness
To: Gavan Fantom <gavan@coolfactor.org>
From: Bill Studenmund <wrstuden@zembu.com>
List: tech-kern
Date: 01/26/2001 16:57:27
On Fri, 26 Jan 2001, Gavan Fantom wrote:

> On Fri, 26 Jan 2001, Gavan Fantom wrote:
> 
> I had a peek at sequencer.c, which prompted me to have a bit more of a
> play. The problem disappears on putting a sleep(1) between
> ioctl(SEQUENCER_SYNC) and close().
> 
> So, a timing issue. After close() on /dev/music, seq_drain() waits until
> the sequencer has done its business and then calls midiclose() on each
> midi device... this is then supposed to wait until everything is finished
> on that MIDI port (and does appear to have code to do so), and then calls
> close() on the driver (in this case, eap), which just turns things off in
> the UART.

I think the problem is that the delay in midiclose() only waits for the
last bit of data to be sent TO the UART, not for the UART to actually send
said data.

> So, either I've missed something, or the card does some funny business
> which needs an extra command to flush things out before it's closed.

No, I think what needs to happen is that we actually need to let the UART
_finish_ flushing things before we turn it off. :-)

I'd suggest adding a delay loop to eap_midi_close. Off the cuff, something
like:

void
eap_midi_clsoe(addr)
	void *addr;
{
	struct eap_softc *sc = addr;
	int x;

	for (x = 0; x != MIDI_BUSY_WAIT; x++) {
		if (EREAD1(sc, EAP_UART_STATUS) & EAP_US_TXRDY)
			break;
		delay(MIDI_BUSY_DELAY);
	}

	EWRITE1(sc, EAP_UART_CONTROL, 0);
	EWRITE4(sc, EAP_ICSC, EREAD4(sc, EAP_ICSC) & ~EAP_UART_EN);

	sc->sc_iintr = 0;
	sc->sc_ointr = 0;
}

Take care,

Bill