I'd be interested in feedback on the effects of the following
particularly on systems that currently fail with libata, and especially
on non-PC systems where the firmware hasn't neccessarily initialized the
disk before Linux takes control

diff -u --new-file --recursive --exclude-from /usr/src/exclude 
linux.vanilla-2.6.22-rc1-mm1/drivers/ata/libata-core.c 
linux-2.6.22-rc1-mm1/drivers/ata/libata-core.c
--- linux.vanilla-2.6.22-rc1-mm1/drivers/ata/libata-core.c      2007-05-18 
16:22:53.000000000 +0100
+++ linux-2.6.22-rc1-mm1/drivers/ata/libata-core.c      2007-05-23 
14:39:00.567356504 +0100
@@ -3099,6 +3109,7 @@
                             unsigned long deadline)
 {
        struct ata_ioports *ioaddr = &ap->ioaddr;
+       int i;
 
        DPRINTK("ata%u: bus reset via SRST\n", ap->print_id);
 
@@ -3120,6 +3131,27 @@
         * Old drivers/ide uses the 2mS rule and then waits for ready
         */
        msleep(150);
+       
+       /* If we issued an SRST then an ATA drive (not ATAPI)
+        * may have changed configuration and be in PIO0 timing. If
+        * we did a hard reset (or are coming from power on) this is
+        * true for ATA or ATAPI. Until we've set a suitable controller
+        * mode we should not touch the bus as we may be talking too fast.
+        */
+
+       for (i = 0; i < ATA_MAX_DEVICES; i++)
+               ap->device[i].pio_mode = XFER_PIO_0;
+
+       /* If the controller has a pio mode setup function then use
+          it to set the chipset to rights. Don't touch the DMA setup
+          as that will be dealt with when revalidating */
+       if (ap->ops->set_piomode) {
+               for (i = 0; i < ATA_MAX_DEVICES; i++) {
+                       if (devmask & (1 << i))
+                               ap->ops->set_piomode(ap, &ap->device[i]);
+               }
+       }
+
 
        /* Before we perform post reset processing we want to see if
         * the bus shows 0xFF because the odd clown forgets the D7
diff -u --new-file --recursive --exclude-from /usr/src/exclude 
linux.vanilla-2.6.22-rc1-mm1/drivers/ata/pata_sis.c 
linux-2.6.22-rc1-mm1/drivers/ata/pata_sis.c
--- linux.vanilla-2.6.22-rc1-mm1/drivers/ata/pata_sis.c 2007-05-18 
16:21:46.000000000 +0100
+++ linux-2.6.22-rc1-mm1/drivers/ata/pata_sis.c 2007-05-23 14:38:11.006890840 
+0100
@@ -73,14 +73,14 @@
 }
 
 /**
- *     sis_port_base           -       return PCI configuration base for dev
+ *     sis_old_port_base               -       return PCI configuration base 
for dev
  *     @adev: device
  *
  *     Returns the base of the PCI configuration registers for this port
  *     number.
  */
 
-static int sis_port_base(struct ata_device *adev)
+static int sis_old_port_base(struct ata_device *adev)
 {
        return  0x40 + (4 * adev->ap->port_no) +  (2 * adev->devno);
 }
@@ -149,6 +149,9 @@
        if (!pci_test_config_bits(pdev, &sis_enable_bits[ap->port_no]))
                return -ENOENT;
 
+       /* Clear the FIFO settings. We can't enable the FIFO until
+          we know we are poking at a disk */
+       pci_write_config_byte(pdev, 0x4B, 0);
        return ata_std_prereset(ap, deadline);
 }
 
@@ -211,7 +214,7 @@
 static void sis_old_set_piomode (struct ata_port *ap, struct ata_device *adev)
 {
        struct pci_dev *pdev    = to_pci_dev(ap->host->dev);
-       int port = sis_port_base(adev);
+       int port = sis_old_port_base(adev);
        u8 t1, t2;
        int speed = adev->pio_mode - XFER_PIO_0;
 
@@ -248,7 +251,7 @@
 static void sis_100_set_piomode (struct ata_port *ap, struct ata_device *adev)
 {
        struct pci_dev *pdev    = to_pci_dev(ap->host->dev);
-       int port = sis_port_base(adev);
+       int port = sis_old_port_base(adev);
        int speed = adev->pio_mode - XFER_PIO_0;
 
        const u8 actrec[] = { 0x00, 0x67, 0x44, 0x33, 0x31 };
@@ -328,7 +331,7 @@
 {
        struct pci_dev *pdev    = to_pci_dev(ap->host->dev);
        int speed = adev->dma_mode - XFER_MW_DMA_0;
-       int drive_pci = sis_port_base(adev);
+       int drive_pci = sis_old_port_base(adev);
        u16 timing;
 
        const u16 mwdma_bits[] = { 0x707, 0x202, 0x202 };
@@ -367,7 +370,7 @@
 {
        struct pci_dev *pdev    = to_pci_dev(ap->host->dev);
        int speed = adev->dma_mode - XFER_MW_DMA_0;
-       int drive_pci = sis_port_base(adev);
+       int drive_pci = sis_old_port_base(adev);
        u16 timing;
 
        const u16 mwdma_bits[] = { 0x707, 0x202, 0x202 };
@@ -378,12 +381,12 @@
        if (adev->dma_mode < XFER_UDMA_0) {
                /* bits 3-0 hold recovery timing bits 8-10 active timing and
                   the higer bits are dependant on the device, bit 15 udma */
-               timing &= ~ 0x870F;
+               timing &= ~0x870F;
                timing |= mwdma_bits[speed];
        } else {
                /* Bit 15 is UDMA on/off, bit 12-14 are cycle time */
                speed = adev->dma_mode - XFER_UDMA_0;
-               timing &= ~0x6000;
+               timing &= ~0xF000;
                timing |= udma_bits[speed];
        }
        pci_write_config_word(pdev, drive_pci, timing);
@@ -405,22 +408,22 @@
 {
        struct pci_dev *pdev    = to_pci_dev(ap->host->dev);
        int speed = adev->dma_mode - XFER_MW_DMA_0;
-       int drive_pci = sis_port_base(adev);
-       u16 timing;
+       int drive_pci = sis_old_port_base(adev);
+       u8 timing;
 
-       const u16 udma_bits[]  = { 0x8B00, 0x8700, 0x8500, 0x8300, 0x8200, 
0x8100};
+       const u16 udma_bits[]  = { 0x8B, 0x87, 0x85, 0x83, 0x82, 0x81};
 
-       pci_read_config_word(pdev, drive_pci, &timing);
+       pci_read_config_byte(pdev, drive_pci + 1, &timing);
 
        if (adev->dma_mode < XFER_UDMA_0) {
                /* NOT SUPPORTED YET: NEED DATA SHEET. DITTO IN OLD DRIVER */
        } else {
-               /* Bit 15 is UDMA on/off, bit 12-14 are cycle time */
+               /* Bit 7 is UDMA on/off, bit 0-3 are cycle time */
                speed = adev->dma_mode - XFER_UDMA_0;
-               timing &= ~0x0F00;
+               timing &= ~0x8F;
                timing |= udma_bits[speed];
        }
-       pci_write_config_word(pdev, drive_pci, timing);
+       pci_write_config_byte(pdev, drive_pci + 1, timing);
 }
 
 /**
@@ -440,22 +443,22 @@
 {
        struct pci_dev *pdev    = to_pci_dev(ap->host->dev);
        int speed = adev->dma_mode - XFER_MW_DMA_0;
-       int drive_pci = sis_port_base(adev);
-       u16 timing;
-
-       static const u16 udma_bits[]  = { 0x8F00, 0x8A00, 0x8700, 0x8500, 
0x8300, 0x8200, 0x8100};
+       int drive_pci = sis_old_port_base(adev);
+       u8 timing;
+       /* Low 4 bits are timing */
+       static const u8 udma_bits[]  = { 0x8F, 0x8A, 0x87, 0x85, 0x83, 0x82, 
0x81};
 
-       pci_read_config_word(pdev, drive_pci, &timing);
+       pci_read_config_byte(pdev, drive_pci + 1, &timing);
 
        if (adev->dma_mode < XFER_UDMA_0) {
                /* NOT SUPPORTED YET: NEED DATA SHEET. DITTO IN OLD DRIVER */
        } else {
-               /* Bit 15 is UDMA on/off, bit 12-14 are cycle time */
+               /* Bit 7 is UDMA on/off, bit 0-3 are cycle time */
                speed = adev->dma_mode - XFER_UDMA_0;
-               timing &= ~0x0F00;
+               timing &= ~0x8F;
                timing |= udma_bits[speed];
        }
-       pci_write_config_word(pdev, drive_pci, timing);
+       pci_write_config_byte(pdev, drive_pci + 1, timing);
 }
 
 /**
-
To unsubscribe from this list: send the line "unsubscribe linux-ide" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to