sound/pci/emu10k1/emumpu401.c

Source file repositories/reference/linux-study-clean/sound/pci/emu10k1/emumpu401.c

File Facts

System
Linux kernel
Corpus path
sound/pci/emu10k1/emumpu401.c
Extension
.c
Size
9978 bytes
Lines
364
Domain
Driver Families
Bucket
sound/pci
Inferred role
Driver Families: implementation source
Status
source implementation candidate

Why This File Exists

Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.

Dependency Surface

Detected Declarations

Annotated Snippet

if ((status & midi->ipr_rx) && mpu401_input_avail(emu, midi)) {
			if (!(midi->midi_mode & EMU10K1_MIDI_MODE_INPUT)) {
				mpu401_clear_rx(emu, midi);
			} else {
				byte = mpu401_read_data(emu, midi);
				if (midi->substream_input)
					snd_rawmidi_receive(midi->substream_input, &byte, 1);
			}
		}
	}

	scoped_guard(spinlock, &midi->output_lock) {
		if ((status & midi->ipr_tx) && mpu401_output_ready(emu, midi)) {
			if (midi->substream_output &&
			    snd_rawmidi_transmit(midi->substream_output, &byte, 1) == 1) {
				mpu401_write_data(emu, midi, byte);
			} else {
				snd_emu10k1_intr_disable(emu, midi->tx_enable);
			}
		}
	}
}

static void snd_emu10k1_midi_interrupt(struct snd_emu10k1 *emu, unsigned int status)
{
	do_emu10k1_midi_interrupt(emu, &emu->midi, status);
}

static void snd_emu10k1_midi_interrupt2(struct snd_emu10k1 *emu, unsigned int status)
{
	do_emu10k1_midi_interrupt(emu, &emu->midi2, status);
}

static int snd_emu10k1_midi_cmd(struct snd_emu10k1 * emu, struct snd_emu10k1_midi *midi, unsigned char cmd, int ack)
{
	int timeout, ok;

	scoped_guard(spinlock_irq, &midi->input_lock) {
		mpu401_write_data(emu, midi, 0x00);
		/* mpu401_clear_rx(emu, midi); */

		mpu401_write_cmd(emu, midi, cmd);
		if (ack) {
			ok = 0;
			timeout = 10000;
			while (!ok && timeout-- > 0) {
				if (mpu401_input_avail(emu, midi)) {
					if (mpu401_read_data(emu, midi) == MPU401_ACK)
						ok = 1;
				}
			}
			if (!ok && mpu401_read_data(emu, midi) == MPU401_ACK)
				ok = 1;
		} else {
			ok = 1;
		}
	}
	if (!ok) {
		dev_err(emu->card->dev,
			"midi_cmd: 0x%x failed at 0x%lx (status = 0x%x, data = 0x%x)!!!\n",
			   cmd, emu->port,
			   mpu401_read_stat(emu, midi),
			   mpu401_read_data(emu, midi));
		return 1;
	}
	return 0;
}

static int snd_emu10k1_midi_input_open(struct snd_rawmidi_substream *substream)
{
	struct snd_emu10k1 *emu;
	struct snd_emu10k1_midi *midi = (struct snd_emu10k1_midi *)substream->rmidi->private_data;

	emu = midi->emu;
	if (snd_BUG_ON(!emu))
		return -ENXIO;
	scoped_guard(spinlock_irq, &midi->open_lock) {
		midi->midi_mode |= EMU10K1_MIDI_MODE_INPUT;
		midi->substream_input = substream;
		if (midi->midi_mode & EMU10K1_MIDI_MODE_OUTPUT)
			return 0;
	}
	if (snd_emu10k1_midi_cmd(emu, midi, MPU401_RESET, 1))
		return -EIO;
	if (snd_emu10k1_midi_cmd(emu, midi, MPU401_ENTER_UART, 1))
		return -EIO;
	return 0;
}

static int snd_emu10k1_midi_output_open(struct snd_rawmidi_substream *substream)

Annotation

Implementation Notes