[PATCH] ata_piix: convert sata to new reset mechanism
[sfrench/cifs-2.6.git] / drivers / scsi / ata_piix.c
index 333d69dd84ef5ad0febfefeb07a30e7153288a72..c662bf5315142c0b750a348c09eb00dd5fcbc9ff 100644 (file)
  *
  *  Hardware documentation available at http://developer.intel.com/
  *
+ * Documentation
+ *     Publically available from Intel web site. Errata documentation
+ * is also publically available. As an aide to anyone hacking on this
+ * driver the list of errata that are relevant is below.going back to
+ * PIIX4. Older device documentation is now a bit tricky to find.
+ *
+ * The chipsets all follow very much the same design. The orginal Triton
+ * series chipsets do _not_ support independant device timings, but this
+ * is fixed in Triton II. With the odd mobile exception the chips then
+ * change little except in gaining more modes until SATA arrives. This
+ * driver supports only the chips with independant timing (that is those
+ * with SITRE and the 0x44 timing register). See pata_oldpiix and pata_mpiix
+ * for the early chip drivers.
+ *
+ * Errata of note:
+ *
+ * Unfixable
+ *     PIIX4    errata #9      - Only on ultra obscure hw
+ *     ICH3     errata #13     - Not observed to affect real hw
+ *                               by Intel
+ *
+ * Things we must deal with
+ *     PIIX4   errata #10      - BM IDE hang with non UDMA
+ *                               (must stop/start dma to recover)
+ *     440MX   errata #15      - As PIIX4 errata #10
+ *     PIIX4   errata #15      - Must not read control registers
+ *                               during a PIO transfer
+ *     440MX   errata #13      - As PIIX4 errata #15
+ *     ICH2    errata #21      - DMA mode 0 doesn't work right
+ *     ICH0/1  errata #55      - As ICH2 errata #21
+ *     ICH2    spec c #9       - Extra operations needed to handle
+ *                               drive hotswap [NOT YET SUPPORTED]
+ *     ICH2    spec c #20      - IDE PRD must not cross a 64K boundary
+ *                               and must be dword aligned
+ *     ICH2    spec c #24      - UDMA mode 4,5 t85/86 should be 6ns not 3.3
+ *
+ * Should have been BIOS fixed:
+ *     450NX:  errata #19      - DMA hangs on old 450NX
+ *     450NX:  errata #20      - DMA hangs on old 450NX
+ *     450NX:  errata #25      - Corruption with DMA on old 450NX
+ *     ICH3    errata #15      - IDE deadlock under high load
+ *                               (BIOS must set dev 31 fn 0 bit 23)
+ *     ICH3    errata #18      - Don't use native mode
  */
 
 #include <linux/kernel.h>
@@ -58,9 +101,11 @@ enum {
        ICH5_PCS                = 0x92, /* port control and status */
        PIIX_SCC                = 0x0A, /* sub-class code register */
 
-       PIIX_FLAG_AHCI          = (1 << 28), /* AHCI possible */
-       PIIX_FLAG_CHECKINTR     = (1 << 29), /* make sure PCI INTx enabled */
-       PIIX_FLAG_COMBINED      = (1 << 30), /* combined mode possible */
+       PIIX_FLAG_AHCI          = (1 << 27), /* AHCI possible */
+       PIIX_FLAG_CHECKINTR     = (1 << 28), /* make sure PCI INTx enabled */
+       PIIX_FLAG_COMBINED      = (1 << 29), /* combined mode possible */
+       /* ICH6/7 use different scheme for map value */
+       PIIX_FLAG_COMBINED_ICH6 = PIIX_FLAG_COMBINED | (1 << 30),
 
        /* combined mode.  if set, PATA is channel 0.
         * if clear, PATA is channel 1.
@@ -78,9 +123,7 @@ enum {
        ich5_sata               = 1,
        piix4_pata              = 2,
        ich6_sata               = 3,
-       ich6_sata_rm            = 4,
-       ich7_sata               = 5,
-       esb2_sata               = 6,
+       ich6_sata_ahci          = 4,
 
        PIIX_AHCI_DEVICE        = 6,
 };
@@ -88,8 +131,8 @@ enum {
 static int piix_init_one (struct pci_dev *pdev,
                                    const struct pci_device_id *ent);
 
-static void piix_pata_phy_reset(struct ata_port *ap);
-static void piix_sata_phy_reset(struct ata_port *ap);
+static int piix_pata_probe_reset(struct ata_port *ap, unsigned int *classes);
+static int piix_sata_probe_reset(struct ata_port *ap, unsigned int *classes);
 static void piix_set_piomode (struct ata_port *ap, struct ata_device *adev);
 static void piix_set_dmamode (struct ata_port *ap, struct ata_device *adev);
 
@@ -111,11 +154,14 @@ static const struct pci_device_id piix_pci_tbl[] = {
        { 0x8086, 0x25a3, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich5_sata },
        { 0x8086, 0x25b0, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich5_sata },
        { 0x8086, 0x2651, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich6_sata },
-       { 0x8086, 0x2652, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich6_sata_rm },
-       { 0x8086, 0x2653, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich6_sata_rm },
-       { 0x8086, 0x27c0, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich7_sata },
-       { 0x8086, 0x27c4, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich7_sata },
-       { 0x8086, 0x2680, PCI_ANY_ID, PCI_ANY_ID, 0, 0, esb2_sata },
+       { 0x8086, 0x2652, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich6_sata_ahci },
+       { 0x8086, 0x2653, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich6_sata_ahci },
+       { 0x8086, 0x27c0, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich6_sata_ahci },
+       { 0x8086, 0x27c4, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich6_sata_ahci },
+       { 0x8086, 0x2680, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich6_sata_ahci },
+       { 0x8086, 0x2820, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich6_sata_ahci },
+       { 0x8086, 0x2825, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich6_sata_ahci },
+       { 0x8086, 0x2828, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich6_sata_ahci },
 
        { }     /* terminate list */
 };
@@ -125,6 +171,8 @@ static struct pci_driver piix_pci_driver = {
        .id_table               = piix_pci_tbl,
        .probe                  = piix_init_one,
        .remove                 = ata_pci_remove_one,
+       .suspend                = ata_pci_device_suspend,
+       .resume                 = ata_pci_device_resume,
 };
 
 static struct scsi_host_template piix_sht = {
@@ -132,11 +180,11 @@ static struct scsi_host_template piix_sht = {
        .name                   = DRV_NAME,
        .ioctl                  = ata_scsi_ioctl,
        .queuecommand           = ata_scsi_queuecmd,
+       .eh_timed_out           = ata_scsi_timed_out,
        .eh_strategy_handler    = ata_scsi_error,
        .can_queue              = ATA_DEF_QUEUE,
        .this_id                = ATA_SHT_THIS_ID,
        .sg_tablesize           = LIBATA_MAX_PRD,
-       .max_sectors            = ATA_MAX_SECTORS,
        .cmd_per_lun            = ATA_SHT_CMD_PER_LUN,
        .emulated               = ATA_SHT_EMULATED,
        .use_clustering         = ATA_SHT_USE_CLUSTERING,
@@ -144,7 +192,8 @@ static struct scsi_host_template piix_sht = {
        .dma_boundary           = ATA_DMA_BOUNDARY,
        .slave_configure        = ata_scsi_slave_config,
        .bios_param             = ata_std_bios_param,
-       .ordered_flush          = 1,
+       .resume                 = ata_scsi_device_resume,
+       .suspend                = ata_scsi_device_suspend,
 };
 
 static const struct ata_port_operations piix_pata_ops = {
@@ -158,7 +207,7 @@ static const struct ata_port_operations piix_pata_ops = {
        .exec_command           = ata_exec_command,
        .dev_select             = ata_std_dev_select,
 
-       .phy_reset              = piix_pata_phy_reset,
+       .probe_reset            = piix_pata_probe_reset,
 
        .bmdma_setup            = ata_bmdma_setup,
        .bmdma_start            = ata_bmdma_start,
@@ -186,7 +235,7 @@ static const struct ata_port_operations piix_sata_ops = {
        .exec_command           = ata_exec_command,
        .dev_select             = ata_std_dev_select,
 
-       .phy_reset              = piix_sata_phy_reset,
+       .probe_reset            = piix_sata_probe_reset,
 
        .bmdma_setup            = ata_bmdma_setup,
        .bmdma_start            = ata_bmdma_start,
@@ -209,8 +258,7 @@ static struct ata_port_info piix_port_info[] = {
        /* ich5_pata */
        {
                .sht            = &piix_sht,
-               .host_flags     = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST |
-                                 PIIX_FLAG_CHECKINTR,
+               .host_flags     = ATA_FLAG_SLAVE_POSS | PIIX_FLAG_CHECKINTR,
                .pio_mask       = 0x1f, /* pio0-4 */
 #if 0
                .mwdma_mask     = 0x06, /* mwdma1-2 */
@@ -224,8 +272,8 @@ static struct ata_port_info piix_port_info[] = {
        /* ich5_sata */
        {
                .sht            = &piix_sht,
-               .host_flags     = ATA_FLAG_SATA | ATA_FLAG_SRST |
-                                 PIIX_FLAG_COMBINED | PIIX_FLAG_CHECKINTR,
+               .host_flags     = ATA_FLAG_SATA | PIIX_FLAG_COMBINED |
+                                 PIIX_FLAG_CHECKINTR,
                .pio_mask       = 0x1f, /* pio0-4 */
                .mwdma_mask     = 0x07, /* mwdma0-2 */
                .udma_mask      = 0x7f, /* udma0-6 */
@@ -235,7 +283,7 @@ static struct ata_port_info piix_port_info[] = {
        /* piix4_pata */
        {
                .sht            = &piix_sht,
-               .host_flags     = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST,
+               .host_flags     = ATA_FLAG_SLAVE_POSS,
                .pio_mask       = 0x1f, /* pio0-4 */
 #if 0
                .mwdma_mask     = 0x06, /* mwdma1-2 */
@@ -249,45 +297,20 @@ static struct ata_port_info piix_port_info[] = {
        /* ich6_sata */
        {
                .sht            = &piix_sht,
-               .host_flags     = ATA_FLAG_SATA | ATA_FLAG_SRST |
-                                 PIIX_FLAG_COMBINED | PIIX_FLAG_CHECKINTR |
-                                 ATA_FLAG_SLAVE_POSS,
-               .pio_mask       = 0x1f, /* pio0-4 */
-               .mwdma_mask     = 0x07, /* mwdma0-2 */
-               .udma_mask      = 0x7f, /* udma0-6 */
-               .port_ops       = &piix_sata_ops,
-       },
-
-       /* ich6_sata_rm */
-       {
-               .sht            = &piix_sht,
-               .host_flags     = ATA_FLAG_SATA | ATA_FLAG_SRST |
-                                 PIIX_FLAG_COMBINED | PIIX_FLAG_CHECKINTR |
-                                 ATA_FLAG_SLAVE_POSS | PIIX_FLAG_AHCI,
+               .host_flags     = ATA_FLAG_SATA | PIIX_FLAG_COMBINED_ICH6 |
+                                 PIIX_FLAG_CHECKINTR | ATA_FLAG_SLAVE_POSS,
                .pio_mask       = 0x1f, /* pio0-4 */
                .mwdma_mask     = 0x07, /* mwdma0-2 */
                .udma_mask      = 0x7f, /* udma0-6 */
                .port_ops       = &piix_sata_ops,
        },
 
-       /* ich7_sata */
+       /* ich6_sata_ahci */
        {
                .sht            = &piix_sht,
-               .host_flags     = ATA_FLAG_SATA | ATA_FLAG_SRST |
-                                 PIIX_FLAG_COMBINED | PIIX_FLAG_CHECKINTR |
-                                 ATA_FLAG_SLAVE_POSS | PIIX_FLAG_AHCI,
-               .pio_mask       = 0x1f, /* pio0-4 */
-               .mwdma_mask     = 0x07, /* mwdma0-2 */
-               .udma_mask      = 0x7f, /* udma0-6 */
-               .port_ops       = &piix_sata_ops,
-       },
-
-       /* esb2_sata */
-       {
-               .sht            = &piix_sht,
-               .host_flags     = ATA_FLAG_SATA | ATA_FLAG_SRST |
-                                 PIIX_FLAG_COMBINED | PIIX_FLAG_CHECKINTR |
-                                 ATA_FLAG_SLAVE_POSS | PIIX_FLAG_AHCI,
+               .host_flags     = ATA_FLAG_SATA | PIIX_FLAG_COMBINED_ICH6 |
+                                 PIIX_FLAG_CHECKINTR | ATA_FLAG_SLAVE_POSS |
+                                 PIIX_FLAG_AHCI,
                .pio_mask       = 0x1f, /* pio0-4 */
                .mwdma_mask     = 0x07, /* mwdma0-2 */
                .udma_mask      = 0x7f, /* udma0-6 */
@@ -340,30 +363,42 @@ cbl40:
 }
 
 /**
- *     piix_pata_phy_reset - Probe specified port on PATA host controller
- *     @ap: Port to probe
+ *     piix_pata_probeinit - probeinit for PATA host controller
+ *     @ap: Target port
  *
- *     Probe PATA phy.
+ *     Probeinit including cable detection.
  *
  *     LOCKING:
  *     None (inherited from caller).
  */
+static void piix_pata_probeinit(struct ata_port *ap)
+{
+       piix_pata_cbl_detect(ap);
+       ata_std_probeinit(ap);
+}
 
-static void piix_pata_phy_reset(struct ata_port *ap)
+/**
+ *     piix_pata_probe_reset - Perform reset on PATA port and classify
+ *     @ap: Port to reset
+ *     @classes: Resulting classes of attached devices
+ *
+ *     Reset PATA phy and classify attached devices.
+ *
+ *     LOCKING:
+ *     None (inherited from caller).
+ */
+static int piix_pata_probe_reset(struct ata_port *ap, unsigned int *classes)
 {
        struct pci_dev *pdev = to_pci_dev(ap->host_set->dev);
 
        if (!pci_test_config_bits(pdev, &piix_enable_bits[ap->hard_port_no])) {
-               ata_port_disable(ap);
                printk(KERN_INFO "ata%u: port disabled. ignoring.\n", ap->id);
-               return;
+               return 0;
        }
 
-       piix_pata_cbl_detect(ap);
-
-       ata_port_probe(ap);
-
-       ata_bus_reset(ap);
+       return ata_drive_probe_reset(ap, piix_pata_probeinit,
+                                    ata_std_softreset, NULL,
+                                    ata_std_postreset, classes);
 }
 
 /**
@@ -388,9 +423,6 @@ static int piix_sata_probe (struct ata_port *ap)
        int orig_mask, mask, i;
        u8 pcs;
 
-       mask = (PIIX_PORT_PRESENT << ap->hard_port_no) |
-              (PIIX_PORT_ENABLED << ap->hard_port_no);
-
        pci_read_config_byte(pdev, ICH5_PCS, &pcs);
        orig_mask = (int) pcs & 0xff;
 
@@ -414,28 +446,25 @@ static int piix_sata_probe (struct ata_port *ap)
 }
 
 /**
- *     piix_sata_phy_reset - Probe specified port on SATA host controller
- *     @ap: Port to probe
+ *     piix_sata_probe_reset - Perform reset on SATA port and classify
+ *     @ap: Port to reset
+ *     @classes: Resulting classes of attached devices
  *
- *     Probe SATA phy.
+ *     Reset SATA phy and classify attached devices.
  *
  *     LOCKING:
  *     None (inherited from caller).
  */
-
-static void piix_sata_phy_reset(struct ata_port *ap)
+static int piix_sata_probe_reset(struct ata_port *ap, unsigned int *classes)
 {
        if (!piix_sata_probe(ap)) {
-               ata_port_disable(ap);
                printk(KERN_INFO "ata%u: SATA port has no device.\n", ap->id);
-               return;
+               return 0;
        }
 
-       ap->cbl = ATA_CBL_SATA;
-
-       ata_port_probe(ap);
-
-       ata_bus_reset(ap);
+       return ata_drive_probe_reset(ap, ata_std_probeinit,
+                                    ata_std_softreset, NULL,
+                                    ata_std_postreset, classes);
 }
 
 /**
@@ -602,6 +631,41 @@ static int piix_disable_ahci(struct pci_dev *pdev)
        return rc;
 }
 
+/**
+ *     piix_check_450nx_errata -       Check for problem 450NX setup
+ *     @ata_dev: the PCI device to check
+ *     
+ *     Check for the present of 450NX errata #19 and errata #25. If
+ *     they are found return an error code so we can turn off DMA
+ */
+
+static int __devinit piix_check_450nx_errata(struct pci_dev *ata_dev)
+{
+       struct pci_dev *pdev = NULL;
+       u16 cfg;
+       u8 rev;
+       int no_piix_dma = 0;
+       
+       while((pdev = pci_get_device(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82454NX, pdev)) != NULL)
+       {
+               /* Look for 450NX PXB. Check for problem configurations
+                  A PCI quirk checks bit 6 already */
+               pci_read_config_byte(pdev, PCI_REVISION_ID, &rev);
+               pci_read_config_word(pdev, 0x41, &cfg);
+               /* Only on the original revision: IDE DMA can hang */
+               if(rev == 0x00)
+                       no_piix_dma = 1;
+               /* On all revisions below 5 PXB bus lock must be disabled for IDE */
+               else if(cfg & (1<<14) && rev < 5)
+                       no_piix_dma = 2;
+       }
+       if(no_piix_dma)
+               dev_printk(KERN_WARNING, &ata_dev->dev, "450NX errata present, disabling IDE DMA.\n");
+       if(no_piix_dma == 2)
+               dev_printk(KERN_WARNING, &ata_dev->dev, "A BIOS update may resolve this.\n");
+       return no_piix_dma;
+}              
+
 /**
  *     piix_init_one - Register PIIX ATA PCI device with kernel services
  *     @pdev: PCI device to register
@@ -623,6 +687,7 @@ static int piix_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
        struct ata_port_info *port_info[2];
        unsigned int combined = 0;
        unsigned int pata_chan = 0, sata_chan = 0;
+       unsigned long host_flags;
 
        if (!printed_version++)
                dev_printk(KERN_DEBUG, &pdev->dev,
@@ -635,7 +700,9 @@ static int piix_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
        port_info[0] = &piix_port_info[ent->driver_data];
        port_info[1] = &piix_port_info[ent->driver_data];
 
-       if (port_info[0]->host_flags & PIIX_FLAG_AHCI) {
+       host_flags = port_info[0]->host_flags;
+
+       if (host_flags & PIIX_FLAG_AHCI) {
                u8 tmp;
                pci_read_config_byte(pdev, PIIX_SCC, &tmp);
                if (tmp == PIIX_AHCI_DEVICE) {
@@ -645,16 +712,35 @@ static int piix_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
                }
        }
 
-       if (port_info[0]->host_flags & PIIX_FLAG_COMBINED) {
+       if (host_flags & PIIX_FLAG_COMBINED) {
                u8 tmp;
                pci_read_config_byte(pdev, ICH5_PMR, &tmp);
 
-               if (tmp & PIIX_COMB) {
-                       combined = 1;
-                       if (tmp & PIIX_COMB_PATA_P0)
+               if (host_flags & PIIX_FLAG_COMBINED_ICH6) {
+                       switch (tmp & 0x3) {
+                       case 0:
+                               break;
+                       case 1:
+                               combined = 1;
                                sata_chan = 1;
-                       else
+                               break;
+                       case 2:
+                               combined = 1;
                                pata_chan = 1;
+                               break;
+                       case 3:
+                               dev_printk(KERN_WARNING, &pdev->dev,
+                                          "invalid MAP value %u\n", tmp);
+                               break;
+                       }
+               } else {
+                       if (tmp & PIIX_COMB) {
+                               combined = 1;
+                               if (tmp & PIIX_COMB_PATA_P0)
+                                       sata_chan = 1;
+                               else
+                                       pata_chan = 1;
+                       }
                }
        }
 
@@ -664,7 +750,7 @@ static int piix_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
         * MSI is disabled (and it is disabled, as we don't use
         * message-signalled interrupts currently).
         */
-       if (port_info[0]->host_flags & PIIX_FLAG_CHECKINTR)
+       if (host_flags & PIIX_FLAG_CHECKINTR)
                pci_intx(pdev, 1);
 
        if (combined) {
@@ -676,7 +762,15 @@ static int piix_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
                           "combined mode detected (p=%u, s=%u)\n",
                           pata_chan, sata_chan);
        }
-
+       if (piix_check_450nx_errata(pdev)) {
+               /* This writes into the master table but it does not
+                  really matter for this errata as we will apply it to
+                  all the PIIX devices on the board */
+               port_info[0]->mwdma_mask = 0;
+               port_info[0]->udma_mask = 0;
+               port_info[1]->mwdma_mask = 0;
+               port_info[1]->udma_mask = 0;
+       }
        return ata_pci_init_one(pdev, port_info, 2);
 }