sound/isa/sb/sb8_midi.c

Source file repositories/reference/linux-study-clean/sound/isa/sb/sb8_midi.c

File Facts

System
Linux kernel
Corpus path
sound/isa/sb/sb8_midi.c
Extension
.c
Size
6708 bytes
Lines
244
Domain
Driver Families
Bucket
sound/isa
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 (inb(SBP(chip, DATA_AVAIL)) & 0x80) {
			byte = inb(SBP(chip, READ));
			if (chip->open & SB_OPEN_MIDI_INPUT_TRIGGER) {
				snd_rawmidi_receive(chip->midi_substream_input, &byte, 1);
			}
		}
	}
	return IRQ_HANDLED;
}

static int snd_sb8dsp_midi_input_open(struct snd_rawmidi_substream *substream)
{
	struct snd_sb *chip;
	unsigned int valid_open_flags;

	chip = substream->rmidi->private_data;
	valid_open_flags = chip->hardware >= SB_HW_20
		? SB_OPEN_MIDI_OUTPUT | SB_OPEN_MIDI_OUTPUT_TRIGGER : 0;
	scoped_guard(spinlock_irqsave, &chip->open_lock) {
		if (chip->open & ~valid_open_flags)
			return -EAGAIN;
		chip->open |= SB_OPEN_MIDI_INPUT;
		chip->midi_substream_input = substream;
		if (chip->open & SB_OPEN_MIDI_OUTPUT)
			return 0;
	}
	snd_sbdsp_reset(chip);		/* reset DSP */
	if (chip->hardware >= SB_HW_20)
		snd_sbdsp_command(chip, SB_DSP_MIDI_UART_IRQ);
	return 0;
}

static int snd_sb8dsp_midi_output_open(struct snd_rawmidi_substream *substream)
{
	struct snd_sb *chip;
	unsigned int valid_open_flags;

	chip = substream->rmidi->private_data;
	valid_open_flags = chip->hardware >= SB_HW_20
		? SB_OPEN_MIDI_INPUT | SB_OPEN_MIDI_INPUT_TRIGGER : 0;
	scoped_guard(spinlock_irqsave, &chip->open_lock) {
		if (chip->open & ~valid_open_flags)
			return -EAGAIN;
		chip->open |= SB_OPEN_MIDI_OUTPUT;
		chip->midi_substream_output = substream;
		if (chip->open & SB_OPEN_MIDI_INPUT)
			return 0;
	}
	snd_sbdsp_reset(chip);		/* reset DSP */
	if (chip->hardware >= SB_HW_20)
		snd_sbdsp_command(chip, SB_DSP_MIDI_UART_IRQ);
	return 0;
}

static int snd_sb8dsp_midi_input_close(struct snd_rawmidi_substream *substream)
{
	struct snd_sb *chip;

	chip = substream->rmidi->private_data;
	scoped_guard(spinlock_irqsave, &chip->open_lock) {
		chip->open &= ~(SB_OPEN_MIDI_INPUT | SB_OPEN_MIDI_INPUT_TRIGGER);
		chip->midi_substream_input = NULL;
		if (chip->open & SB_OPEN_MIDI_OUTPUT)
			return 0;
	}
	snd_sbdsp_reset(chip);		/* reset DSP */
	return 0;
}

static int snd_sb8dsp_midi_output_close(struct snd_rawmidi_substream *substream)
{
	struct snd_sb *chip;

	chip = substream->rmidi->private_data;
	timer_delete_sync(&chip->midi_timer);
	scoped_guard(spinlock_irqsave, &chip->open_lock) {
		chip->open &= ~(SB_OPEN_MIDI_OUTPUT | SB_OPEN_MIDI_OUTPUT_TRIGGER);
		chip->midi_substream_output = NULL;
		if (chip->open & SB_OPEN_MIDI_INPUT)
			return 0;
	}
	snd_sbdsp_reset(chip);		/* reset DSP */
	return 0;
}

static void snd_sb8dsp_midi_input_trigger(struct snd_rawmidi_substream *substream, int up)
{
	struct snd_sb *chip;

	chip = substream->rmidi->private_data;

Annotation

Implementation Notes