Index: linux-2.6.16/drivers/scsi/libata-core.c =================================================================== --- linux-2.6.16.orig/drivers/scsi/libata-core.c 2006-06-18 15:23:49.000000000 +0200 +++ linux-2.6.16/drivers/scsi/libata-core.c 2006-06-18 20:57:13.000000000 +0200 @@ -4706,6 +4706,7 @@ struct ata_queued_cmd *qc) { u8 status, host_stat = 0; + int i; VPRINTK("ata%u: protocol %d task_state %d\n", ap->id, qc->tf.protocol, ap->hsm_task_state); @@ -4752,9 +4753,25 @@ } /* check altstatus */ - status = ata_altstatus(ap); - if (status & ATA_BUSY) - goto idle_irq; + if (qc->tf.command == ATA_CMD_SET_FEATURES && + qc->tf.feature == SETFEATURES_XFER) { + /* With some configurations (PATA VIA and CDR-6S48), the + * ata_altstatus take some times (~ 3us) to become not busy. + * Without this quirk, it is impossible to set the xfer mode. + */ + for (i = 0; ata_altstatus(ap) & ATA_BUSY; i++) { + if (i > 10) + goto idle_irq; + udelay(1); + } + + if (i) + ata_port_printk(ap, KERN_WARNING, "ata_altstatus take %dus\n", i); + } else { + status = ata_altstatus(ap); + if (status & ATA_BUSY) + goto idle_irq; + } /* check main status, clearing INTRQ */ status = ata_chk_status(ap);