[alsa-devel] ICE 1724 MIDI support still broken?
Hello ALSA team,
We have a user with an ESI Juli@ whose Linux box hangs when any MIDI application starts up. I read that MIDI support is broken generally on ICE 1724 cards; is this still the case in recent driver releases?
If so, is there any interest in fixing this long-standing issue? The user has indicated that his box would be available by ssh for any tests required.
Cheers!
Daniel
At Thu, 19 Apr 2007 16:15:26 +0100, Daniel James wrote:
Hello ALSA team,
We have a user with an ESI Juli@ whose Linux box hangs when any MIDI application starts up. I read that MIDI support is broken generally on ICE 1724 cards; is this still the case in recent driver releases?
If so, is there any interest in fixing this long-standing issue? The user has indicated that his box would be available by ssh for any tests required.
Well, Juli is hard to fix right now from my side because of lack of hardware information. Maybe Jaroslav can do better because he apparently had contact with ESI.
Takashi
At Mon, 23 Apr 2007 12:16:11 +0200, 私 wrote:
At Thu, 19 Apr 2007 16:15:26 +0100, Daniel James wrote:
Hello ALSA team,
We have a user with an ESI Juli@ whose Linux box hangs when any MIDI application starts up. I read that MIDI support is broken generally on ICE 1724 cards; is this still the case in recent driver releases?
If so, is there any interest in fixing this long-standing issue? The user has indicated that his box would be available by ssh for any tests required.
Well, Juli is hard to fix right now from my side because of lack of hardware information. Maybe Jaroslav can do better because he apparently had contact with ESI.
I took a bit look at specs and tried to hack. The below is a revised patch just for fixing possible problems blindly. It extends mpu401_uart API, too. Give it a spin if you'd like.
The irq handler has a check of possible endless loops, so it shouldn't hang up so immediately. Check the kernel log.
If you get a message like "cmd: 0x3f failed at ...", try to uncomment MPU401_INFO_NO_ACK in the argument of snd_mpu401_uart_new() in ice1724.c.
You can try also set watermarks by commenting out the block around line ice1724.c:2465 (/* for testing */) in the case of endless irq loops.
The patch is against HG version, and I won't debug any older version.
Takashi
diff -r f73f5a4fa439 drivers/mpu401/mpu401_uart.c --- a/drivers/mpu401/mpu401_uart.c Tue Apr 24 12:27:36 2007 +0200 +++ b/drivers/mpu401/mpu401_uart.c Tue Apr 24 14:45:24 2007 +0200 @@ -50,12 +50,10 @@ static void snd_mpu401_uart_output_write
*/
-#define snd_mpu401_input_avail(mpu) (!(mpu->read(mpu, MPU401C(mpu)) & 0x80)) -#define snd_mpu401_output_ready(mpu) (!(mpu->read(mpu, MPU401C(mpu)) & 0x40)) - -#define MPU401_RESET 0xff -#define MPU401_ENTER_UART 0x3f -#define MPU401_ACK 0xfe +#define snd_mpu401_input_avail(mpu) \ + (!(mpu->read(mpu, MPU401C(mpu)) & MPU401_RX_EMPTY)) +#define snd_mpu401_output_ready(mpu) \ + (!(mpu->read(mpu, MPU401C(mpu)) & MPU401_TX_FULL))
/* Build in lowlevel io */ static void mpu401_write_port(struct snd_mpu401 *mpu, unsigned char data, @@ -242,7 +240,7 @@ static int snd_mpu401_uart_cmd(struct sn #endif } mpu->write(mpu, cmd, MPU401C(mpu)); - if (ack) { + if (ack && !(mpu->info_flags & MPU401_INFO_NO_ACK)) { ok = 0; timeout = 10000; while (!ok && timeout-- > 0) { diff -r f73f5a4fa439 include/mpu401.h --- a/include/mpu401.h Tue Apr 24 12:27:36 2007 +0200 +++ b/include/mpu401.h Tue Apr 24 14:44:55 2007 +0200 @@ -51,6 +51,7 @@ #define MPU401_INFO_MMIO (1 << 3) /* MMIO access */ #define MPU401_INFO_TX_IRQ (1 << 4) /* independent TX irq */ #define MPU401_INFO_UART_ONLY (1 << 5) /* No ENTER_UART cmd needed */ +#define MPU401_INFO_NO_ACK (1 << 6) /* No ACK cmd needed */
#define MPU401_MODE_BIT_INPUT 0 #define MPU401_MODE_BIT_OUTPUT 1 @@ -104,6 +105,21 @@ struct snd_mpu401 { #define MPU401D(mpu) (mpu)->port
/* + * control register bits + */ +/* read MPU401C() */ +#define MPU401_RX_EMPTY 0x80 +#define MPU401_TX_FULL 0x40 + +/* write MPU401C() */ +#define MPU401_RESET 0xff +#define MPU401_ENTER_UART 0x3f + +/* read MPU401D() */ +#define MPU401_ACK 0xfe + + +/*
*/
diff -r f73f5a4fa439 pci/ice1712/ice1724.c --- a/pci/ice1712/ice1724.c Tue Apr 24 12:27:36 2007 +0200 +++ b/pci/ice1712/ice1724.c Tue Apr 24 14:52:07 2007 +0200 @@ -216,6 +216,32 @@ static unsigned int snd_vt1724_get_gpio_ }
/* + * MPU401 accessor + */ +static unsigned char snd_vt1724_mpu401_read(struct snd_mpu401 *mpu, + unsigned long addr) +{ + /* fix status bits to the standard position */ + /* only RX_EMPTY and TX_FULL are checked */ + if (addr == MPU401C(mpu)) + return (inb(addr) & 0x0c) << 4; + else + return inb(addr); +} + +static void snd_vt1724_mpu401_write(struct snd_mpu401 *mpu, + unsigned char data, unsigned long addr) +{ + if (addr == MPU401C(mpu)) { + if (data == MPU401_ENTER_UART) + outb(0x01, addr); + /* what else? */ + } else + outb(data, addr); +} + + +/* * Interrupt handler */
@@ -224,23 +250,44 @@ static irqreturn_t snd_vt1724_interrupt( struct snd_ice1712 *ice = dev_id; unsigned char status; int handled = 0; +#ifdef CONFIG_SND_DEBUG + int timeout = 0; +#endif
while (1) { status = inb(ICEREG1724(ice, IRQSTAT)); + status &= VT1724_IRQ_MPU_RX|VT1724_IRQ_MPU_TX|VT1724_IRQ_MTPCM; if (status == 0) break; - +#ifdef CONFIG_SND_DEBUG + if (++timeout > 10) { + printk(KERN_ERR + "ice1724: Too long irq loop, status = 0x%x\n", + status); + break; + } +#endif handled = 1; - /* these should probably be separated at some point, - * but as we don't currently have MPU support on the board - * I will leave it - */ - if ((status & VT1724_IRQ_MPU_RX)||(status & VT1724_IRQ_MPU_TX)) { + if (status & VT1724_IRQ_MPU_TX) { if (ice->rmidi[0]) - snd_mpu401_uart_interrupt(irq, ice->rmidi[0]->private_data); - outb(status & (VT1724_IRQ_MPU_RX|VT1724_IRQ_MPU_TX), ICEREG1724(ice, IRQSTAT)); - status &= ~(VT1724_IRQ_MPU_RX|VT1724_IRQ_MPU_TX); + snd_mpu401_uart_interrupt_tx(irq, + ice->rmidi[0]->private_data); + else /* disable TX to be sure */ + outb(inb(ICEREG1724(ice, IRQMASK)) | + VT1724_IRQ_MPU_RX, + ICEREG1724(ice, IRQMASK)); } + if (status & VT1724_IRQ_MPU_RX) { + if (ice->rmidi[0]) + snd_mpu401_uart_interrupt(irq, + ice->rmidi[0]->private_data); + else /* disable RX to be sure */ + outb(inb(ICEREG1724(ice, IRQMASK)) | + VT1724_IRQ_MPU_RX, + ICEREG1724(ice, IRQMASK)); + } + /* ack MPU irq */ + outb(status, ICEREG1724(ice, IRQSTAT)); if (status & VT1724_IRQ_MTPCM) { /* * Multi-track PCM @@ -2276,10 +2323,7 @@ static int __devinit snd_vt1724_create(s }
/* unmask used interrupts */ - if (! (ice->eeprom.data[ICE_EEP2_SYSCONF] & VT1724_CFG_MPU401)) - mask = VT1724_IRQ_MPU_RX | VT1724_IRQ_MPU_TX; - else - mask = 0; + mask = VT1724_IRQ_MPU_RX | VT1724_IRQ_MPU_TX; outb(mask, ICEREG1724(ice, IRQMASK)); /* don't handle FIFO overrun/underruns (just yet), * since they cause machine lockups @@ -2400,14 +2444,30 @@ static int __devinit snd_vt1724_probe(st
if (! c->no_mpu401) { if (ice->eeprom.data[ICE_EEP2_SYSCONF] & VT1724_CFG_MPU401) { + struct snd_mpu401 *mpu; if ((err = snd_mpu401_uart_new(card, 0, MPU401_HW_ICE1712, ICEREG1724(ice, MPU_CTRL), - MPU401_INFO_INTEGRATED, + (MPU401_INFO_INTEGRATED | + /*MPU401_INFO_NO_ACK |*/ + MPU401_INFO_TX_IRQ), ice->irq, 0, &ice->rmidi[0])) < 0) { snd_card_free(card); return err; } + mpu = ice->rmidi[0]->private_data; + mpu->read = snd_vt1724_mpu401_read; + mpu->write = snd_vt1724_mpu401_write; + /* unmask MPU RX/TX irqs */ + outb(inb(ICEREG1724(ice, IRQMASK)) & + ~(VT1724_IRQ_MPU_RX | VT1724_IRQ_MPU_TX), + ICEREG1724(ice, IRQMASK)); +#if 0 /* for testing */ + /* set watermarks */ + outb(VT1724_MPU_RX_FIFO | 0x1, + ICEREG1724(ice, MPU_FIFO_WM)); + outb(0x1, ICEREG1724(ice, MPU_FIFO_WM)); +#endif } }
participants (2)
-
Daniel James
-
Takashi Iwai