]> git.hungrycats.org Git - linux/commitdiff
[libata] Fix flush of Device Control register to device
authorBenjamin Herrenschmidt <benh@kernel.crashing.org>
Mon, 24 Nov 2003 06:19:35 +0000 (01:19 -0500)
committerJeff Garzik <jgarzik@redhat.com>
Mon, 24 Nov 2003 06:19:35 +0000 (01:19 -0500)
Also add some ServerWorks-specific tweaks.

drivers/scsi/libata-core.c
drivers/scsi/sata_svw.c
include/linux/libata.h

index 4906684e1f02588a26d9f4b1dc7a8d8136baf64b..b92d67726018fd96d571e976127df0dcfadde680 100644 (file)
@@ -133,7 +133,11 @@ void ata_tf_load_pio(struct ata_port *ap, struct ata_taskfile *tf)
        struct ata_ioports *ioaddr = &ap->ioaddr;
        unsigned int is_addr = tf->flags & ATA_TFLAG_ISADDR;
 
-       outb(tf->ctl, ioaddr->ctl_addr);
+       if (tf->ctl != ap->last_ctl) {
+               outb(tf->ctl, ioaddr->ctl_addr);
+               ap->last_ctl = tf->ctl;
+               ata_wait_idle(ap);
+       }
 
        if (is_addr && (tf->flags & ATA_TFLAG_LBA48)) {
                outb(tf->hob_feature, ioaddr->error_addr);
@@ -187,7 +191,11 @@ void ata_tf_load_mmio(struct ata_port *ap, struct ata_taskfile *tf)
        struct ata_ioports *ioaddr = &ap->ioaddr;
        unsigned int is_addr = tf->flags & ATA_TFLAG_ISADDR;
 
-       writeb(tf->ctl, ap->ioaddr.ctl_addr);
+       if (tf->ctl != ap->last_ctl) {
+               writeb(tf->ctl, ap->ioaddr.ctl_addr);
+               ap->last_ctl = tf->ctl;
+               ata_wait_idle(ap);
+       }
 
        if (is_addr && (tf->flags & ATA_TFLAG_LBA48)) {
                writeb(tf->hob_feature, (void *) ioaddr->error_addr);
@@ -1281,9 +1289,9 @@ static unsigned int ata_bus_softreset(struct ata_port *ap,
        /* software reset.  causes dev0 to be selected */
        if (ap->flags & ATA_FLAG_MMIO) {
                writeb(ap->ctl, ioaddr->ctl_addr);
-               udelay(10);     /* FIXME: flush */
+               udelay(20);     /* FIXME: flush */
                writeb(ap->ctl | ATA_SRST, ioaddr->ctl_addr);
-               udelay(10);     /* FIXME: flush */
+               udelay(20);     /* FIXME: flush */
                writeb(ap->ctl, ioaddr->ctl_addr);
        } else {
                outb(ap->ctl, ioaddr->ctl_addr);
@@ -2755,6 +2763,7 @@ static void ata_host_init(struct ata_port *ap, struct Scsi_Host *host,
        ap->cbl = ATA_CBL_NONE;
        ap->device[0].flags = ATA_DFLAG_MASTER;
        ap->active_tag = ATA_TAG_POISON;
+       ap->last_ctl = 0xFF;
 
        /* ata_engine init */
        ap->eng.flags = 0;
index 5053074195f7b14f85acb77fbfebfe1e48ededc2..756367807b6a3e843165fe01c0d0e34397808674 100644 (file)
@@ -69,8 +69,11 @@ static void k2_sata_tf_load(struct ata_port *ap, struct ata_taskfile *tf)
        struct ata_ioports *ioaddr = &ap->ioaddr;
        unsigned int is_addr = tf->flags & ATA_TFLAG_ISADDR;
 
-       writeb(tf->ctl, ioaddr->ctl_addr);
-
+       if (tf->ctl != ap->last_ctl) {
+               writeb(tf->ctl, ioaddr->ctl_addr);
+               ap->last_ctl = tf->ctl;
+               ata_wait_idle(ap);
+       }
        if (is_addr && (tf->flags & ATA_TFLAG_LBA48)) {
                writew(tf->feature | (((u16)tf->hob_feature) << 8), ioaddr->error_addr);
                writew(tf->nsect | (((u16)tf->hob_nsect) << 8), ioaddr->nsect_addr);
@@ -311,13 +314,24 @@ static int k2_sata_init_one (struct pci_dev *pdev, const struct pci_device_id *e
                rc = -ENODEV;
                goto err_out_unmap;
        }
+
+       /* Clear a magic bit in SCR1 according to Darwin, those help
+        * some funky seagate drives (though so far, those were already
+        * set by the firmware on the machines I had access to
+        */
+       writel(readl(mmio_base + 0x80) & ~0x00040000, mmio_base + 0x80);
+
+       /* Clear SATA error & interrupts we don't use */
+       writel(0xffffffff, mmio_base + 0x44);
+       writel(0x0, mmio_base + 0x88);
+
        probe_ent->sht = &k2_sata_sht;
-       probe_ent->host_flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
-                               ATA_FLAG_SRST | ATA_FLAG_MMIO;
+       probe_ent->host_flags = ATA_FLAG_SATA | ATA_FLAG_SATA_RESET |
+                               ATA_FLAG_NO_LEGACY | ATA_FLAG_MMIO;
        probe_ent->port_ops = &k2_sata_ops;
-               probe_ent->n_ports = 2;
-               probe_ent->irq = pdev->irq;
-               probe_ent->irq_flags = SA_SHIRQ;
+       probe_ent->n_ports = 2;
+       probe_ent->irq = pdev->irq;
+       probe_ent->irq_flags = SA_SHIRQ;
        probe_ent->mmio_base = mmio_base;
 
        /*
index e34b31950dd67d27429d24227631788b246c0841..feabeae1cfc09ae1421f28700834b39c9ecdebcd 100644 (file)
@@ -310,6 +310,7 @@ struct ata_port {
        struct ata_ioports      ioaddr; /* ATA cmd/ctl/dma register blocks */
 
        u8                      ctl;    /* cache of ATA control register */
+       u8                      last_ctl;       /* Cache last written value */
        unsigned int            bus_state;
        unsigned int            port_state;
        unsigned int            pio_mask;
@@ -522,12 +523,12 @@ static inline u8 ata_irq_on(struct ata_port *ap)
        struct ata_ioports *ioaddr = &ap->ioaddr;
 
        ap->ctl &= ~ATA_NIEN;
+       ap->last_ctl = ap->ctl;
 
        if (ap->flags & ATA_FLAG_MMIO)
                writeb(ap->ctl, ioaddr->ctl_addr);
        else
                outb(ap->ctl, ioaddr->ctl_addr);
-
        return ata_wait_idle(ap);
 }