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 } } _______________________________________________ Alsa-devel mailing list Alsa-devel@xxxxxxxxxxxxxxxx http://mailman.alsa-project.org/mailman/listinfo/alsa-devel