Глава 8. Интерфейс MIDI (MPU401-UART)

Предыдущая  Содержание  Следующая V*D*V

Общие сведения

Многие звуковые карты имеют встроенные интерфейсы MIDI (MPU401-UART). Если звуковая карта поддерживает стандартный интерфейс MPU401-UART, скорее всего, можно использовать ALSA MPU401-UART API. MPU401-UART API определён в <sound/mpu401.h>.

 

Некоторые звуковые чипы имеют похожую, но немного отличающуюся реализацию mpu401. Например, emu10k1 имеет свои собственные процедуры mpu401.

Конструктор

Чтобы создать объект rawmidi, вызовите snd_mpu401_uart_new().

 

struct snd_rawmidi *rmidi;

snd_mpu401_uart_new(card, 0, MPU401_HW_MPU401, port, info_flags,

                    irq, irq_flags, &rmidi);

 

Первым аргументом является указатель карты, а вторым - индекс этого компонента. Можно создать до 8 устройств rawmidi.

 

Третий аргумент - тип оборудования, MPU401_HW_XXX. Если он не какой-то особый, можно использовать MPU401_HW_MPU401.

 

4-м аргументом является адрес порта ввода/вывода. Многие обратно совместимые MPU401 имеют такой порт ввода/вывода, как 0x330. Или он может быть частью его собственной области ввода/вывода PCI. Это зависит от дизайна чипа.

 

Пятый аргумент - битовый флаг для дополнительной информации. Когда вышеупомянутый адрес порта ввода/вывода является частью области ввода/вывода PCI, порт ввода/вывода MPU401 может быть уже выделен (зарезервирован) самим драйвером. В таком случае передайте битовый флаг MPU401_INFO_INTEGRATED и уровень MPU401-UART выделит порты ввода/вывода самостоятельно.

 

Если контроллер поддерживает только поток ввод или вывода MIDI, передайте соответственно битовый флаг MPU401_INFO_INPUT или MPU401_INFO_OUTPUT. В таком случае экземпляр rawmidi создаётся как однопоточный.

 

Битовый флаг MPU401_INFO_MMIO используется для изменения метода доступа к MMIO (через readb и writeb) вместо iob и outb. В этом случае в snd_mpu401_uart_new() необходимо передать отображённый в пространство памяти адрес ввода/вывода.

 

Когда установлен MPU401_INFO_TX_IRQ, выходной поток не контролируется в обработчике прерывания, установленном по умолчанию. Драйвер должен сам вызывать snd_mpu401_uart_interrupt_tx() для начала обработки выходного потока в обработчике прерывания.

 

Обычно, адрес порта соответствует командному порту, а адрес порта + 1 соответствует порту данных. Если это не так, можно изменить поле cport структуры snd_mpu401 вручную позже. Однако, указатель snd_mpu401 функцией snd_mpu401_uart_new() не возвращается явно. Вы должны явно привести rmidi->private_data к типу snd_mpu401,

 

struct snd_mpu401 *mpu;

mpu = rmidi->private_data;

 

и переустановить cport, как требуется:

 

mpu->cport = my_own_control_port;

 

(а как установить порт данных?)

 

Шестой аргумент указывает номер прерывания для UART. Если это прерывание уже выделено, передайте 0 в 7-м аргументе (irq_flags). В противном случае передайте флаги для выделения прерывания (биты SA_XXX) к нему, и прерывание будет зарезервировано уровнем MPU401-UART. Если карта не генерирует прерывания UART, в качестве номера прерывания передайте -1. Тогда для опроса будут вызываться прерывания по таймеру.

Обработчик прерывания

Если прерывание выделено в snd_mpu401_uart_new(), используется закрытый (встроенный) обработчик прерывания, поэтому не придётся ничего делать, кроме создания создания объекта MPU401. В противном случае, необходимо явно вызывать snd_mpu401_uart_interrupt(), если прерывание UART вызывается и управляется в собственном обработчике прерывания.

 

В этом случае в качестве второго аргумента snd_mpu401_uart_interrupt() необходимо передать private_data возвращённого из snd_mpu401_uart_new() объекта rawmidi.

 

snd_mpu401_uart_interrupt(irq, rmidi->private_data, regs);

 

Предыдущая  Содержание  Следующая