]> www.pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - drivers/ata/ata_piix.c
ATA: remove excess kernel-doc notation
[linux-2.6-omap-h63xx.git] / drivers / ata / ata_piix.c
index e6b4606e36b68a51448d73b755aab75d91e0fa80..8e37be19bbf520b1b8e9d8409d9874846ee868f4 100644 (file)
@@ -14,7 +14,7 @@
  *
  *  Copyright (C) 1998-1999 Andrzej Krzysztofowicz, Author and Maintainer
  *  Copyright (C) 1998-2000 Andre Hedrick <andre@linux-ide.org>
- *  Copyright (C) 2003 Red Hat Inc <alan@redhat.com>
+ *  Copyright (C) 2003 Red Hat Inc
  *
  *
  *  This program is free software; you can redistribute it and/or modify
@@ -165,8 +165,10 @@ static void piix_set_dmamode(struct ata_port *ap, struct ata_device *adev);
 static void ich_set_dmamode(struct ata_port *ap, struct ata_device *adev);
 static int ich_pata_cable_detect(struct ata_port *ap);
 static u8 piix_vmw_bmdma_status(struct ata_port *ap);
-static int piix_sidpr_scr_read(struct ata_port *ap, unsigned int reg, u32 *val);
-static int piix_sidpr_scr_write(struct ata_port *ap, unsigned int reg, u32 val);
+static int piix_sidpr_scr_read(struct ata_link *link,
+                              unsigned int reg, u32 *val);
+static int piix_sidpr_scr_write(struct ata_link *link,
+                               unsigned int reg, u32 val);
 #ifdef CONFIG_PM
 static int piix_pci_device_suspend(struct pci_dev *pdev, pm_message_t mesg);
 static int piix_pci_device_resume(struct pci_dev *pdev);
@@ -278,12 +280,15 @@ static const struct pci_device_id piix_pci_tbl[] = {
        /* SATA Controller IDE (PCH) */
        { 0x8086, 0x3b20, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_sata },
        /* SATA Controller IDE (PCH) */
+       { 0x8086, 0x3b21, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_2port_sata },
+       /* SATA Controller IDE (PCH) */
        { 0x8086, 0x3b26, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_2port_sata },
        /* SATA Controller IDE (PCH) */
+       { 0x8086, 0x3b28, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_sata },
+       /* SATA Controller IDE (PCH) */
        { 0x8086, 0x3b2d, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_2port_sata },
        /* SATA Controller IDE (PCH) */
        { 0x8086, 0x3b2e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_sata },
-
        { }     /* terminate list */
 };
 
@@ -582,6 +587,7 @@ static const struct ich_laptop ich_laptop[] = {
        { 0x27DF, 0x1025, 0x0110 },     /* ICH7 on Acer 3682WLMi */
        { 0x27DF, 0x1043, 0x1267 },     /* ICH7 on Asus W5F */
        { 0x27DF, 0x103C, 0x30A1 },     /* ICH7 on HP Compaq nc2400 */
+       { 0x27DF, 0x1071, 0xD221 },     /* ICH7 on Hercules EC-900 */
        { 0x24CA, 0x1025, 0x0061 },     /* ICH4 on ACER Aspire 2023WLMi */
        { 0x24CA, 0x1025, 0x003d },     /* ICH4 on ACER TM290 */
        { 0x266F, 0x1025, 0x0066 },     /* ICH6 on ACER Aspire 1694WLMi */
@@ -732,7 +738,6 @@ static void piix_set_piomode(struct ata_port *ap, struct ata_device *adev)
  *     do_pata_set_dmamode - Initialize host controller PATA PIO timings
  *     @ap: Port whose timings we are configuring
  *     @adev: Drive in question
- *     @udma: udma mode, 0 - 6
  *     @isich: set if the chip is an ICH device
  *
  *     Set UDMA mode for device, in host controller PCI config space.
@@ -885,23 +890,9 @@ static void ich_set_dmamode(struct ata_port *ap, struct ata_device *adev)
  * Serial ATA Index/Data Pair Superset Registers access
  *
  * Beginning from ICH8, there's a sane way to access SCRs using index
- * and data register pair located at BAR5.  This creates an
- * interesting problem of mapping two SCRs to one port.
- *
- * Although they have separate SCRs, the master and slave aren't
- * independent enough to be treated as separate links - e.g. softreset
- * resets both.  Also, there's no protocol defined for hard resetting
- * singled device sharing the virtual port (no defined way to acquire
- * device signature).  This is worked around by merging the SCR values
- * into one sensible value and requesting follow-up SRST after
- * hardreset.
- *
- * SCR merging is perfomed in nibbles which is the unit contents in
- * SCRs are organized.  If two values are equal, the value is used.
- * When they differ, merge table which lists precedence of possible
- * values is consulted and the first match or the last entry when
- * nothing matches is used.  When there's no merge table for the
- * specific nibble, value from the first port is used.
+ * and data register pair located at BAR5 which means that we have
+ * separate SCRs for master and slave.  This is handled using libata
+ * slave_link facility.
  */
 static const int piix_sidx_map[] = {
        [SCR_STATUS]    = 0,
@@ -909,120 +900,38 @@ static const int piix_sidx_map[] = {
        [SCR_CONTROL]   = 1,
 };
 
-static void piix_sidpr_sel(struct ata_device *dev, unsigned int reg)
+static void piix_sidpr_sel(struct ata_link *link, unsigned int reg)
 {
-       struct ata_port *ap = dev->link->ap;
+       struct ata_port *ap = link->ap;
        struct piix_host_priv *hpriv = ap->host->private_data;
 
-       iowrite32(((ap->port_no * 2 + dev->devno) << 8) | piix_sidx_map[reg],
+       iowrite32(((ap->port_no * 2 + link->pmp) << 8) | piix_sidx_map[reg],
                  hpriv->sidpr + PIIX_SIDPR_IDX);
 }
 
-static int piix_sidpr_read(struct ata_device *dev, unsigned int reg)
-{
-       struct piix_host_priv *hpriv = dev->link->ap->host->private_data;
-
-       piix_sidpr_sel(dev, reg);
-       return ioread32(hpriv->sidpr + PIIX_SIDPR_DATA);
-}
-
-static void piix_sidpr_write(struct ata_device *dev, unsigned int reg, u32 val)
-{
-       struct piix_host_priv *hpriv = dev->link->ap->host->private_data;
-
-       piix_sidpr_sel(dev, reg);
-       iowrite32(val, hpriv->sidpr + PIIX_SIDPR_DATA);
-}
-
-static u32 piix_merge_scr(u32 val0, u32 val1, const int * const *merge_tbl)
-{
-       u32 val = 0;
-       int i, mi;
-
-       for (i = 0, mi = 0; i < 32 / 4; i++) {
-               u8 c0 = (val0 >> (i * 4)) & 0xf;
-               u8 c1 = (val1 >> (i * 4)) & 0xf;
-               u8 merged = c0;
-               const int *cur;
-
-               /* if no merge preference, assume the first value */
-               cur = merge_tbl[mi];
-               if (!cur)
-                       goto done;
-               mi++;
-
-               /* if two values equal, use it */
-               if (c0 == c1)
-                       goto done;
-
-               /* choose the first match or the last from the merge table */
-               while (*cur != -1) {
-                       if (c0 == *cur || c1 == *cur)
-                               break;
-                       cur++;
-               }
-               if (*cur == -1)
-                       cur--;
-               merged = *cur;
-       done:
-               val |= merged << (i * 4);
-       }
-
-       return val;
-}
-
-static int piix_sidpr_scr_read(struct ata_port *ap, unsigned int reg, u32 *val)
+static int piix_sidpr_scr_read(struct ata_link *link,
+                              unsigned int reg, u32 *val)
 {
-       const int * const sstatus_merge_tbl[] = {
-               /* DET */ (const int []){ 1, 3, 0, 4, 3, -1 },
-               /* SPD */ (const int []){ 2, 1, 0, -1 },
-               /* IPM */ (const int []){ 6, 2, 1, 0, -1 },
-               NULL,
-       };
-       const int * const scontrol_merge_tbl[] = {
-               /* DET */ (const int []){ 1, 0, 4, 0, -1 },
-               /* SPD */ (const int []){ 0, 2, 1, 0, -1 },
-               /* IPM */ (const int []){ 0, 1, 2, 3, 0, -1 },
-               NULL,
-       };
-       u32 v0, v1;
+       struct piix_host_priv *hpriv = link->ap->host->private_data;
 
        if (reg >= ARRAY_SIZE(piix_sidx_map))
                return -EINVAL;
 
-       if (!(ap->flags & ATA_FLAG_SLAVE_POSS)) {
-               *val = piix_sidpr_read(&ap->link.device[0], reg);
-               return 0;
-       }
-
-       v0 = piix_sidpr_read(&ap->link.device[0], reg);
-       v1 = piix_sidpr_read(&ap->link.device[1], reg);
-
-       switch (reg) {
-       case SCR_STATUS:
-               *val = piix_merge_scr(v0, v1, sstatus_merge_tbl);
-               break;
-       case SCR_ERROR:
-               *val = v0 | v1;
-               break;
-       case SCR_CONTROL:
-               *val = piix_merge_scr(v0, v1, scontrol_merge_tbl);
-               break;
-       }
-
+       piix_sidpr_sel(link, reg);
+       *val = ioread32(hpriv->sidpr + PIIX_SIDPR_DATA);
        return 0;
 }
 
-static int piix_sidpr_scr_write(struct ata_port *ap, unsigned int reg, u32 val)
+static int piix_sidpr_scr_write(struct ata_link *link,
+                               unsigned int reg, u32 val)
 {
+       struct piix_host_priv *hpriv = link->ap->host->private_data;
+
        if (reg >= ARRAY_SIZE(piix_sidx_map))
                return -EINVAL;
 
-       piix_sidpr_write(&ap->link.device[0], reg, val);
-
-       if (ap->flags & ATA_FLAG_SLAVE_POSS)
-               piix_sidpr_write(&ap->link.device[1], reg, val);
-
+       piix_sidpr_sel(link, reg);
+       iowrite32(val, hpriv->sidpr + PIIX_SIDPR_DATA);
        return 0;
 }
 
@@ -1363,28 +1272,28 @@ static const int *__devinit piix_init_sata_map(struct pci_dev *pdev,
        return map;
 }
 
-static void __devinit piix_init_sidpr(struct ata_host *host)
+static int __devinit piix_init_sidpr(struct ata_host *host)
 {
        struct pci_dev *pdev = to_pci_dev(host->dev);
        struct piix_host_priv *hpriv = host->private_data;
-       struct ata_device *dev0 = &host->ports[0]->link.device[0];
+       struct ata_link *link0 = &host->ports[0]->link;
        u32 scontrol;
-       int i;
+       int i, rc;
 
        /* check for availability */
        for (i = 0; i < 4; i++)
                if (hpriv->map[i] == IDE)
-                       return;
+                       return 0;
 
        if (!(host->ports[0]->flags & PIIX_FLAG_SIDPR))
-               return;
+               return 0;
 
        if (pci_resource_start(pdev, PIIX_SIDPR_BAR) == 0 ||
            pci_resource_len(pdev, PIIX_SIDPR_BAR) != PIIX_SIDPR_LEN)
-               return;
+               return 0;
 
        if (pcim_iomap_regions(pdev, 1 << PIIX_SIDPR_BAR, DRV_NAME))
-               return;
+               return 0;
 
        hpriv->sidpr = pcim_iomap_table(pdev)[PIIX_SIDPR_BAR];
 
@@ -1392,7 +1301,7 @@ static void __devinit piix_init_sidpr(struct ata_host *host)
         * Give it a test drive by inhibiting power save modes which
         * we'll do anyway.
         */
-       scontrol = piix_sidpr_read(dev0, SCR_CONTROL);
+       piix_sidpr_scr_read(link0, SCR_CONTROL, &scontrol);
 
        /* if IPM is already 3, SCR access is probably working.  Don't
         * un-inhibit power save modes as BIOS might have inhibited
@@ -1400,18 +1309,30 @@ static void __devinit piix_init_sidpr(struct ata_host *host)
         */
        if ((scontrol & 0xf00) != 0x300) {
                scontrol |= 0x300;
-               piix_sidpr_write(dev0, SCR_CONTROL, scontrol);
-               scontrol = piix_sidpr_read(dev0, SCR_CONTROL);
+               piix_sidpr_scr_write(link0, SCR_CONTROL, scontrol);
+               piix_sidpr_scr_read(link0, SCR_CONTROL, &scontrol);
 
                if ((scontrol & 0xf00) != 0x300) {
                        dev_printk(KERN_INFO, host->dev, "SCR access via "
                                   "SIDPR is available but doesn't work\n");
-                       return;
+                       return 0;
                }
        }
 
-       host->ports[0]->ops = &piix_sidpr_sata_ops;
-       host->ports[1]->ops = &piix_sidpr_sata_ops;
+       /* okay, SCRs available, set ops and ask libata for slave_link */
+       for (i = 0; i < 2; i++) {
+               struct ata_port *ap = host->ports[i];
+
+               ap->ops = &piix_sidpr_sata_ops;
+
+               if (ap->flags & ATA_FLAG_SLAVE_POSS) {
+                       rc = ata_slave_link_init(ap);
+                       if (rc)
+                               return rc;
+               }
+       }
+
+       return 0;
 }
 
 static void piix_iocfg_bit18_quirk(struct pci_dev *pdev)
@@ -1521,7 +1442,9 @@ static int __devinit piix_init_one(struct pci_dev *pdev,
        /* initialize controller */
        if (port_flags & ATA_FLAG_SATA) {
                piix_init_pcs(host, piix_map_db_table[ent->driver_data]);
-               piix_init_sidpr(host);
+               rc = piix_init_sidpr(host);
+               if (rc)
+                       return rc;
        }
 
        /* apply IOCFG bit18 quirk */