]> git.karo-electronics.de Git - linux-beck.git/commitdiff
Merge branch 'master'
authorJeff Garzik <jeff@garzik.org>
Fri, 17 Mar 2006 00:22:42 +0000 (19:22 -0500)
committerJeff Garzik <jeff@garzik.org>
Fri, 17 Mar 2006 00:22:42 +0000 (19:22 -0500)
24 files changed:
drivers/scsi/Makefile
drivers/scsi/ahci.c
drivers/scsi/ata_piix.c
drivers/scsi/libata-bmdma.c [new file with mode: 0644]
drivers/scsi/libata-core.c
drivers/scsi/libata-scsi.c
drivers/scsi/libata.h
drivers/scsi/pdc_adma.c
drivers/scsi/sata_mv.c
drivers/scsi/sata_nv.c
drivers/scsi/sata_promise.c
drivers/scsi/sata_qstor.c
drivers/scsi/sata_sil.c
drivers/scsi/sata_sil24.c
drivers/scsi/sata_sis.c
drivers/scsi/sata_svw.c
drivers/scsi/sata_sx4.c
drivers/scsi/sata_uli.c
drivers/scsi/sata_via.c
drivers/scsi/sata_vsc.c
drivers/scsi/scsi_error.c
include/linux/ata.h
include/linux/libata.h
include/scsi/scsi_eh.h

index 320e765fa0cd97b873e62b6c805d07c52aab67d1..15dc2e00e1b26a0ab1439e68fddc4d9037d8b8bb 100644 (file)
@@ -163,7 +163,7 @@ ncr53c8xx-flags-$(CONFIG_SCSI_ZALON) \
 CFLAGS_ncr53c8xx.o     := $(ncr53c8xx-flags-y) $(ncr53c8xx-flags-m)
 zalon7xx-objs  := zalon.o ncr53c8xx.o
 NCR_Q720_mod-objs      := NCR_Q720.o ncr53c8xx.o
-libata-objs    := libata-core.o libata-scsi.o
+libata-objs    := libata-core.o libata-scsi.o libata-bmdma.o
 oktagon_esp_mod-objs   := oktagon_esp.o oktagon_io.o
 
 # Files generated that shall be removed upon make clean
index 559ff7aae3f113e4f61e551050c289b73f7fa6d6..e97ab3e6de4d19c847a6546b58c134c99e62f75f 100644 (file)
@@ -66,6 +66,9 @@ enum {
        AHCI_IRQ_ON_SG          = (1 << 31),
        AHCI_CMD_ATAPI          = (1 << 5),
        AHCI_CMD_WRITE          = (1 << 6),
+       AHCI_CMD_PREFETCH       = (1 << 7),
+       AHCI_CMD_RESET          = (1 << 8),
+       AHCI_CMD_CLR_BUSY       = (1 << 10),
 
        RX_FIS_D2H_REG          = 0x40, /* offset of D2H Register FIS data */
 
@@ -85,6 +88,7 @@ enum {
 
        /* HOST_CAP bits */
        HOST_CAP_64             = (1 << 31), /* PCI DAC (64-bit DMA) support */
+       HOST_CAP_CLO            = (1 << 24), /* Command List Override support */
 
        /* registers for each SATA port */
        PORT_LST_ADDR           = 0x00, /* command list DMA addr */
@@ -138,6 +142,7 @@ enum {
        PORT_CMD_LIST_ON        = (1 << 15), /* cmd list DMA engine running */
        PORT_CMD_FIS_ON         = (1 << 14), /* FIS DMA engine running */
        PORT_CMD_FIS_RX         = (1 << 4), /* Enable FIS receive DMA engine */
+       PORT_CMD_CLO            = (1 << 3), /* Command list override */
        PORT_CMD_POWER_ON       = (1 << 2), /* Power up device */
        PORT_CMD_SPIN_UP        = (1 << 1), /* Spin up device */
        PORT_CMD_START          = (1 << 0), /* Enable port DMA engine */
@@ -184,9 +189,9 @@ struct ahci_port_priv {
 static u32 ahci_scr_read (struct ata_port *ap, unsigned int sc_reg);
 static void ahci_scr_write (struct ata_port *ap, unsigned int sc_reg, u32 val);
 static int ahci_init_one (struct pci_dev *pdev, const struct pci_device_id *ent);
-static int ahci_qc_issue(struct ata_queued_cmd *qc);
+static unsigned int ahci_qc_issue(struct ata_queued_cmd *qc);
 static irqreturn_t ahci_interrupt (int irq, void *dev_instance, struct pt_regs *regs);
-static void ahci_phy_reset(struct ata_port *ap);
+static int ahci_probe_reset(struct ata_port *ap, unsigned int *classes);
 static void ahci_irq_clear(struct ata_port *ap);
 static void ahci_eng_timeout(struct ata_port *ap);
 static int ahci_port_start(struct ata_port *ap);
@@ -202,11 +207,11 @@ static struct scsi_host_template ahci_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           = AHCI_MAX_SG,
-       .max_sectors            = ATA_MAX_SECTORS,
        .cmd_per_lun            = ATA_SHT_CMD_PER_LUN,
        .emulated               = ATA_SHT_EMULATED,
        .use_clustering         = AHCI_USE_CLUSTERING,
@@ -225,7 +230,7 @@ static const struct ata_port_operations ahci_ops = {
 
        .tf_read                = ahci_tf_read,
 
-       .phy_reset              = ahci_phy_reset,
+       .probe_reset            = ahci_probe_reset,
 
        .qc_prep                = ahci_qc_prep,
        .qc_issue               = ahci_qc_issue,
@@ -247,8 +252,7 @@ static const struct ata_port_info ahci_port_info[] = {
        {
                .sht            = &ahci_sht,
                .host_flags     = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
-                                 ATA_FLAG_SATA_RESET | ATA_FLAG_MMIO |
-                                 ATA_FLAG_PIO_DMA,
+                                 ATA_FLAG_MMIO | ATA_FLAG_PIO_DMA,
                .pio_mask       = 0x1f, /* pio0-4 */
                .udma_mask      = 0x7f, /* udma0-6 ; FIXME */
                .port_ops       = &ahci_ops,
@@ -450,17 +454,48 @@ static void ahci_scr_write (struct ata_port *ap, unsigned int sc_reg_in,
        writel(val, (void __iomem *) ap->ioaddr.scr_addr + (sc_reg * 4));
 }
 
-static void ahci_phy_reset(struct ata_port *ap)
+static int ahci_stop_engine(struct ata_port *ap)
 {
-       void __iomem *port_mmio = (void __iomem *) ap->ioaddr.cmd_addr;
-       struct ata_taskfile tf;
-       struct ata_device *dev = &ap->device[0];
-       u32 new_tmp, tmp;
+       void __iomem *mmio = ap->host_set->mmio_base;
+       void __iomem *port_mmio = ahci_port_base(mmio, ap->port_no);
+       int work;
+       u32 tmp;
 
-       __sata_phy_reset(ap);
+       tmp = readl(port_mmio + PORT_CMD);
+       tmp &= ~PORT_CMD_START;
+       writel(tmp, port_mmio + PORT_CMD);
 
-       if (ap->flags & ATA_FLAG_PORT_DISABLED)
-               return;
+       /* wait for engine to stop.  TODO: this could be
+        * as long as 500 msec
+        */
+       work = 1000;
+       while (work-- > 0) {
+               tmp = readl(port_mmio + PORT_CMD);
+               if ((tmp & PORT_CMD_LIST_ON) == 0)
+                       return 0;
+               udelay(10);
+       }
+
+       return -EIO;
+}
+
+static void ahci_start_engine(struct ata_port *ap)
+{
+       void __iomem *mmio = ap->host_set->mmio_base;
+       void __iomem *port_mmio = ahci_port_base(mmio, ap->port_no);
+       u32 tmp;
+
+       tmp = readl(port_mmio + PORT_CMD);
+       tmp |= PORT_CMD_START;
+       writel(tmp, port_mmio + PORT_CMD);
+       readl(port_mmio + PORT_CMD); /* flush */
+}
+
+static unsigned int ahci_dev_classify(struct ata_port *ap)
+{
+       void __iomem *port_mmio = (void __iomem *) ap->ioaddr.cmd_addr;
+       struct ata_taskfile tf;
+       u32 tmp;
 
        tmp = readl(port_mmio + PORT_SIG);
        tf.lbah         = (tmp >> 24)   & 0xff;
@@ -468,15 +503,46 @@ static void ahci_phy_reset(struct ata_port *ap)
        tf.lbal         = (tmp >> 8)    & 0xff;
        tf.nsect        = (tmp)         & 0xff;
 
-       dev->class = ata_dev_classify(&tf);
-       if (!ata_dev_present(dev)) {
-               ata_port_disable(ap);
-               return;
-       }
+       return ata_dev_classify(&tf);
+}
+
+static void ahci_fill_cmd_slot(struct ahci_port_priv *pp, u32 opts)
+{
+       pp->cmd_slot[0].opts = cpu_to_le32(opts);
+       pp->cmd_slot[0].status = 0;
+       pp->cmd_slot[0].tbl_addr = cpu_to_le32(pp->cmd_tbl_dma & 0xffffffff);
+       pp->cmd_slot[0].tbl_addr_hi = cpu_to_le32((pp->cmd_tbl_dma >> 16) >> 16);
+}
+
+static int ahci_hardreset(struct ata_port *ap, int verbose, unsigned int *class)
+{
+       int rc;
+
+       DPRINTK("ENTER\n");
+
+       ahci_stop_engine(ap);
+       rc = sata_std_hardreset(ap, verbose, class);
+       ahci_start_engine(ap);
+
+       if (rc == 0)
+               *class = ahci_dev_classify(ap);
+       if (*class == ATA_DEV_UNKNOWN)
+               *class = ATA_DEV_NONE;
+
+       DPRINTK("EXIT, rc=%d, class=%u\n", rc, *class);
+       return rc;
+}
+
+static void ahci_postreset(struct ata_port *ap, unsigned int *class)
+{
+       void __iomem *port_mmio = (void __iomem *) ap->ioaddr.cmd_addr;
+       u32 new_tmp, tmp;
+
+       ata_std_postreset(ap, class);
 
        /* Make sure port's ATAPI bit is set appropriately */
        new_tmp = tmp = readl(port_mmio + PORT_CMD);
-       if (dev->class == ATA_DEV_ATAPI)
+       if (*class == ATA_DEV_ATAPI)
                new_tmp |= PORT_CMD_ATAPI;
        else
                new_tmp &= ~PORT_CMD_ATAPI;
@@ -486,6 +552,12 @@ static void ahci_phy_reset(struct ata_port *ap)
        }
 }
 
+static int ahci_probe_reset(struct ata_port *ap, unsigned int *classes)
+{
+       return ata_drive_probe_reset(ap, NULL, NULL, ahci_hardreset,
+                                    ahci_postreset, classes);
+}
+
 static u8 ahci_check_status(struct ata_port *ap)
 {
        void __iomem *mmio = (void __iomem *) ap->ioaddr.cmd_addr;
@@ -533,42 +605,36 @@ static void ahci_qc_prep(struct ata_queued_cmd *qc)
 {
        struct ata_port *ap = qc->ap;
        struct ahci_port_priv *pp = ap->private_data;
+       int is_atapi = is_atapi_taskfile(&qc->tf);
        u32 opts;
        const u32 cmd_fis_len = 5; /* five dwords */
        unsigned int n_elem;
 
-       /*
-        * Fill in command slot information (currently only one slot,
-        * slot 0, is currently since we don't do queueing)
-        */
-
-       opts = cmd_fis_len;
-       if (qc->tf.flags & ATA_TFLAG_WRITE)
-               opts |= AHCI_CMD_WRITE;
-       if (is_atapi_taskfile(&qc->tf))
-               opts |= AHCI_CMD_ATAPI;
-
-       pp->cmd_slot[0].opts = cpu_to_le32(opts);
-       pp->cmd_slot[0].status = 0;
-       pp->cmd_slot[0].tbl_addr = cpu_to_le32(pp->cmd_tbl_dma & 0xffffffff);
-       pp->cmd_slot[0].tbl_addr_hi = cpu_to_le32((pp->cmd_tbl_dma >> 16) >> 16);
-
        /*
         * Fill in command table information.  First, the header,
         * a SATA Register - Host to Device command FIS.
         */
        ata_tf_to_fis(&qc->tf, pp->cmd_tbl, 0);
-       if (opts & AHCI_CMD_ATAPI) {
+       if (is_atapi) {
                memset(pp->cmd_tbl + AHCI_CMD_TBL_CDB, 0, 32);
-               memcpy(pp->cmd_tbl + AHCI_CMD_TBL_CDB, qc->cdb, ap->cdb_len);
+               memcpy(pp->cmd_tbl + AHCI_CMD_TBL_CDB, qc->cdb,
+                      qc->dev->cdb_len);
        }
 
-       if (!(qc->flags & ATA_QCFLAG_DMAMAP))
-               return;
+       n_elem = 0;
+       if (qc->flags & ATA_QCFLAG_DMAMAP)
+               n_elem = ahci_fill_sg(qc);
 
-       n_elem = ahci_fill_sg(qc);
+       /*
+        * Fill in command slot information.
+        */
+       opts = cmd_fis_len | n_elem << 16;
+       if (qc->tf.flags & ATA_TFLAG_WRITE)
+               opts |= AHCI_CMD_WRITE;
+       if (is_atapi)
+               opts |= AHCI_CMD_ATAPI | AHCI_CMD_PREFETCH;
 
-       pp->cmd_slot[0].opts |= cpu_to_le32(n_elem << 16);
+       ahci_fill_cmd_slot(pp, opts);
 }
 
 static void ahci_restart_port(struct ata_port *ap, u32 irq_stat)
@@ -576,7 +642,6 @@ static void ahci_restart_port(struct ata_port *ap, u32 irq_stat)
        void __iomem *mmio = ap->host_set->mmio_base;
        void __iomem *port_mmio = ahci_port_base(mmio, ap->port_no);
        u32 tmp;
-       int work;
 
        if ((ap->device[0].class != ATA_DEV_ATAPI) ||
            ((irq_stat & PORT_IRQ_TF_ERR) == 0))
@@ -592,20 +657,7 @@ static void ahci_restart_port(struct ata_port *ap, u32 irq_stat)
                        readl(port_mmio + PORT_SCR_ERR));
 
        /* stop DMA */
-       tmp = readl(port_mmio + PORT_CMD);
-       tmp &= ~PORT_CMD_START;
-       writel(tmp, port_mmio + PORT_CMD);
-
-       /* wait for engine to stop.  TODO: this could be
-        * as long as 500 msec
-        */
-       work = 1000;
-       while (work-- > 0) {
-               tmp = readl(port_mmio + PORT_CMD);
-               if ((tmp & PORT_CMD_LIST_ON) == 0)
-                       break;
-               udelay(10);
-       }
+       ahci_stop_engine(ap);
 
        /* clear SATA phy error, if any */
        tmp = readl(port_mmio + PORT_SCR_ERR);
@@ -624,10 +676,7 @@ static void ahci_restart_port(struct ata_port *ap, u32 irq_stat)
        }
 
        /* re-start DMA */
-       tmp = readl(port_mmio + PORT_CMD);
-       tmp |= PORT_CMD_START;
-       writel(tmp, port_mmio + PORT_CMD);
-       readl(port_mmio + PORT_CMD); /* flush */
+       ahci_start_engine(ap);
 }
 
 static void ahci_eng_timeout(struct ata_port *ap)
@@ -642,25 +691,13 @@ static void ahci_eng_timeout(struct ata_port *ap)
 
        spin_lock_irqsave(&host_set->lock, flags);
 
+       ahci_restart_port(ap, readl(port_mmio + PORT_IRQ_STAT));
        qc = ata_qc_from_tag(ap, ap->active_tag);
-       if (!qc) {
-               printk(KERN_ERR "ata%u: BUG: timeout without command\n",
-                      ap->id);
-       } else {
-               ahci_restart_port(ap, readl(port_mmio + PORT_IRQ_STAT));
-
-               /* hack alert!  We cannot use the supplied completion
-                * function from inside the ->eh_strategy_handler() thread.
-                * libata is the only user of ->eh_strategy_handler() in
-                * any kernel, so the default scsi_done() assumes it is
-                * not being called from the SCSI EH.
-                */
-               qc->scsidone = scsi_finish_command;
-               qc->err_mask |= AC_ERR_OTHER;
-               ata_qc_complete(qc);
-       }
+       qc->err_mask |= AC_ERR_TIMEOUT;
 
        spin_unlock_irqrestore(&host_set->lock, flags);
+
+       ata_eh_qc_complete(qc);
 }
 
 static inline int ahci_host_intr(struct ata_port *ap, struct ata_queued_cmd *qc)
@@ -678,7 +715,7 @@ static inline int ahci_host_intr(struct ata_port *ap, struct ata_queued_cmd *qc)
        ci = readl(port_mmio + PORT_CMD_ISSUE);
        if (likely((ci & 0x1) == 0)) {
                if (qc) {
-                       assert(qc->err_mask == 0);
+                       WARN_ON(qc->err_mask);
                        ata_qc_complete(qc);
                        qc = NULL;
                }
@@ -697,7 +734,7 @@ static inline int ahci_host_intr(struct ata_port *ap, struct ata_queued_cmd *qc)
                ahci_restart_port(ap, status);
 
                if (qc) {
-                       qc->err_mask |= AC_ERR_OTHER;
+                       qc->err_mask |= err_mask;
                        ata_qc_complete(qc);
                }
        }
@@ -770,7 +807,7 @@ static irqreturn_t ahci_interrupt (int irq, void *dev_instance, struct pt_regs *
        return IRQ_RETVAL(handled);
 }
 
-static int ahci_qc_issue(struct ata_queued_cmd *qc)
+static unsigned int ahci_qc_issue(struct ata_queued_cmd *qc)
 {
        struct ata_port *ap = qc->ap;
        void __iomem *port_mmio = (void __iomem *) ap->ioaddr.cmd_addr;
index fc3ca051ceed36dd431bcd0dab1dcf29dbc36cd9..9327b62f97de8136a8503bd25a9e8b067119dfa1 100644 (file)
@@ -101,36 +101,54 @@ 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_IGNORE_PCS    = (1 << 25), /* ignore PCS present bits */
+       PIIX_FLAG_SCR           = (1 << 26), /* SCR available */
+       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.
         */
-       PIIX_COMB_PATA_P0       = (1 << 1),
-       PIIX_COMB               = (1 << 2), /* combined mode enabled? */
-
        PIIX_PORT_ENABLED       = (1 << 0),
        PIIX_PORT_PRESENT       = (1 << 4),
 
        PIIX_80C_PRI            = (1 << 5) | (1 << 4),
        PIIX_80C_SEC            = (1 << 7) | (1 << 6),
 
-       ich5_pata               = 0,
-       ich5_sata               = 1,
-       piix4_pata              = 2,
-       ich6_sata               = 3,
-       ich6_sata_ahci          = 4,
+       /* controller IDs */
+       piix4_pata              = 0,
+       ich5_pata               = 1,
+       ich5_sata               = 2,
+       esb_sata                = 3,
+       ich6_sata               = 4,
+       ich6_sata_ahci          = 5,
+       ich6m_sata_ahci         = 6,
+
+       /* constants for mapping table */
+       P0                      = 0,  /* port 0 */
+       P1                      = 1,  /* port 1 */
+       P2                      = 2,  /* port 2 */
+       P3                      = 3,  /* port 3 */
+       IDE                     = -1, /* IDE */
+       NA                      = -2, /* not avaliable */
+       RV                      = -3, /* reserved */
 
        PIIX_AHCI_DEVICE        = 6,
 };
 
+struct piix_map_db {
+       const u32 mask;
+       const int map[][4];
+};
+
 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);
 
@@ -147,19 +165,32 @@ static const struct pci_device_id piix_pci_tbl[] = {
         * list in drivers/pci/quirks.c.
         */
 
+       /* 82801EB (ICH5) */
        { 0x8086, 0x24d1, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich5_sata },
+       /* 82801EB (ICH5) */
        { 0x8086, 0x24df, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich5_sata },
-       { 0x8086, 0x25a3, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich5_sata },
-       { 0x8086, 0x25b0, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich5_sata },
+       /* 6300ESB (ICH5 variant with broken PCS present bits) */
+       { 0x8086, 0x25a3, PCI_ANY_ID, PCI_ANY_ID, 0, 0, esb_sata },
+       /* 6300ESB pretending RAID */
+       { 0x8086, 0x25b0, PCI_ANY_ID, PCI_ANY_ID, 0, 0, esb_sata },
+       /* 82801FB/FW (ICH6/ICH6W) */
        { 0x8086, 0x2651, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich6_sata },
+       /* 82801FR/FRW (ICH6R/ICH6RW) */
        { 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 },
+       /* 82801FBM ICH6M (ICH6R with only port 0 and 2 implemented) */
+       { 0x8086, 0x2653, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich6m_sata_ahci },
+       /* 82801GB/GR/GH (ICH7, identical to ICH6) */
        { 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 },
+       /* 2801GBM/GHM (ICH7M, identical to ICH6M) */
+       { 0x8086, 0x27c4, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich6m_sata_ahci },
+       /* Enterprise Southbridge 2 (where's the datasheet?) */
        { 0x8086, 0x2680, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich6_sata_ahci },
+       /* SATA Controller 1 IDE (ICH8, no datasheet yet) */
        { 0x8086, 0x2820, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich6_sata_ahci },
+       /* SATA Controller 2 IDE (ICH8, ditto) */
        { 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 },
+       /* Mobile SATA Controller IDE (ICH8M, ditto) */
+       { 0x8086, 0x2828, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich6m_sata_ahci },
 
        { }     /* terminate list */
 };
@@ -178,11 +209,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,
@@ -205,7 +236,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,
@@ -233,7 +264,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,
@@ -252,12 +283,62 @@ static const struct ata_port_operations piix_sata_ops = {
        .host_stop              = ata_host_stop,
 };
 
+static struct piix_map_db ich5_map_db = {
+       .mask = 0x7,
+       .map = {
+               /* PM   PS   SM   SS       MAP  */
+               {  P0,  NA,  P1,  NA }, /* 000b */
+               {  P1,  NA,  P0,  NA }, /* 001b */
+               {  RV,  RV,  RV,  RV },
+               {  RV,  RV,  RV,  RV },
+               {  P0,  P1, IDE, IDE }, /* 100b */
+               {  P1,  P0, IDE, IDE }, /* 101b */
+               { IDE, IDE,  P0,  P1 }, /* 110b */
+               { IDE, IDE,  P1,  P0 }, /* 111b */
+       },
+};
+
+static struct piix_map_db ich6_map_db = {
+       .mask = 0x3,
+       .map = {
+               /* PM   PS   SM   SS       MAP */
+               {  P0,  P1,  P2,  P3 }, /* 00b */
+               { IDE, IDE,  P1,  P3 }, /* 01b */
+               {  P0,  P2, IDE, IDE }, /* 10b */
+               {  RV,  RV,  RV,  RV },
+       },
+};
+
+static struct piix_map_db ich6m_map_db = {
+       .mask = 0x3,
+       .map = {
+               /* PM   PS   SM   SS       MAP */
+               {  P0,  P1,  P2,  P3 }, /* 00b */
+               {  RV,  RV,  RV,  RV },
+               {  P0,  P2, IDE, IDE }, /* 10b */
+               {  RV,  RV,  RV,  RV },
+       },
+};
+
 static struct ata_port_info piix_port_info[] = {
+       /* piix4_pata */
+       {
+               .sht            = &piix_sht,
+               .host_flags     = ATA_FLAG_SLAVE_POSS,
+               .pio_mask       = 0x1f, /* pio0-4 */
+#if 0
+               .mwdma_mask     = 0x06, /* mwdma1-2 */
+#else
+               .mwdma_mask     = 0x00, /* mwdma broken */
+#endif
+               .udma_mask      = ATA_UDMA_MASK_40C,
+               .port_ops       = &piix_pata_ops,
+       },
+
        /* 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 */
@@ -271,50 +352,63 @@ 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 */
                .port_ops       = &piix_sata_ops,
+               .private_data   = &ich5_map_db,
        },
 
-       /* piix4_pata */
+       /* i6300esb_sata */
        {
                .sht            = &piix_sht,
-               .host_flags     = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST,
+               .host_flags     = ATA_FLAG_SATA | PIIX_FLAG_COMBINED |
+                                 PIIX_FLAG_CHECKINTR | PIIX_FLAG_IGNORE_PCS,
                .pio_mask       = 0x1f, /* pio0-4 */
-#if 0
-               .mwdma_mask     = 0x06, /* mwdma1-2 */
-#else
-               .mwdma_mask     = 0x00, /* mwdma broken */
-#endif
-               .udma_mask      = ATA_UDMA_MASK_40C,
-               .port_ops       = &piix_pata_ops,
+               .mwdma_mask     = 0x07, /* mwdma0-2 */
+               .udma_mask      = 0x7f, /* udma0-6 */
+               .port_ops       = &piix_sata_ops,
+               .private_data   = &ich5_map_db,
        },
 
        /* ich6_sata */
        {
                .sht            = &piix_sht,
-               .host_flags     = ATA_FLAG_SATA | ATA_FLAG_SRST |
-                                 PIIX_FLAG_COMBINED | PIIX_FLAG_CHECKINTR |
-                                 ATA_FLAG_SLAVE_POSS,
+               .host_flags     = ATA_FLAG_SATA | PIIX_FLAG_COMBINED_ICH6 |
+                                 PIIX_FLAG_CHECKINTR | PIIX_FLAG_SCR,
                .pio_mask       = 0x1f, /* pio0-4 */
                .mwdma_mask     = 0x07, /* mwdma0-2 */
                .udma_mask      = 0x7f, /* udma0-6 */
                .port_ops       = &piix_sata_ops,
+               .private_data   = &ich6_map_db,
        },
 
        /* 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,
+               .host_flags     = ATA_FLAG_SATA | PIIX_FLAG_COMBINED_ICH6 |
+                                 PIIX_FLAG_CHECKINTR | PIIX_FLAG_SCR |
+                                 PIIX_FLAG_AHCI,
+               .pio_mask       = 0x1f, /* pio0-4 */
+               .mwdma_mask     = 0x07, /* mwdma0-2 */
+               .udma_mask      = 0x7f, /* udma0-6 */
+               .port_ops       = &piix_sata_ops,
+               .private_data   = &ich6_map_db,
+       },
+
+       /* ich6m_sata_ahci */
+       {
+               .sht            = &piix_sht,
+               .host_flags     = ATA_FLAG_SATA | PIIX_FLAG_COMBINED_ICH6 |
+                                 PIIX_FLAG_CHECKINTR | PIIX_FLAG_SCR |
+                                 PIIX_FLAG_AHCI,
                .pio_mask       = 0x1f, /* pio0-4 */
                .mwdma_mask     = 0x07, /* mwdma0-2 */
                .udma_mask      = 0x7f, /* udma0-6 */
                .port_ops       = &piix_sata_ops,
+               .private_data   = &ich6m_map_db,
        },
 };
 
@@ -363,102 +457,123 @@ 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);
 }
 
 /**
  *     piix_sata_probe - Probe PCI device for present SATA devices
  *     @ap: Port associated with the PCI device we wish to probe
  *
- *     Reads SATA PCI device's PCI config register Port Configuration
- *     and Status (PCS) to determine port and device availability.
+ *     Reads and configures SATA PCI device's PCI config register
+ *     Port Configuration and Status (PCS) to determine port and
+ *     device availability.
  *
  *     LOCKING:
  *     None (inherited from caller).
  *
  *     RETURNS:
- *     Non-zero if port is enabled, it may or may not have a device
- *     attached in that case (PRESENT bit would only be set if BIOS probe
- *     was done). Zero is returned if port is disabled.
+ *     Mask of avaliable devices on the port.
  */
-static int piix_sata_probe (struct ata_port *ap)
+static unsigned int piix_sata_probe (struct ata_port *ap)
 {
        struct pci_dev *pdev = to_pci_dev(ap->host_set->dev);
-       int combined = (ap->flags & ATA_FLAG_SLAVE_POSS);
-       int orig_mask, mask, i;
+       const unsigned int *map = ap->host_set->private_data;
+       int base = 2 * ap->hard_port_no;
+       unsigned int present_mask = 0;
+       int port, 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;
-
-       /* TODO: this is vaguely wrong for ICH6 combined mode,
-        * where only two of the four SATA ports are mapped
-        * onto a single ATA channel.  It is also vaguely inaccurate
-        * for ICH5, which has only two ports.  However, this is ok,
-        * as further device presence detection code will handle
-        * any false positives produced here.
-        */
+       DPRINTK("ata%u: ENTER, pcs=0x%x base=%d\n", ap->id, pcs, base);
 
-       for (i = 0; i < 4; i++) {
-               mask = (PIIX_PORT_ENABLED << i);
+       /* enable all ports on this ap and wait for them to settle */
+       for (i = 0; i < 2; i++) {
+               port = map[base + i];
+               if (port >= 0)
+                       pcs |= 1 << port;
+       }
+
+       pci_write_config_byte(pdev, ICH5_PCS, pcs);
+       msleep(100);
 
-               if ((orig_mask & mask) == mask)
-                       if (combined || (i == ap->hard_port_no))
-                               return 1;
+       /* let's see which devices are present */
+       pci_read_config_byte(pdev, ICH5_PCS, &pcs);
+
+       for (i = 0; i < 2; i++) {
+               port = map[base + i];
+               if (port < 0)
+                       continue;
+               if (ap->flags & PIIX_FLAG_IGNORE_PCS || pcs & 1 << (4 + port))
+                       present_mask |= 1 << i;
+               else
+                       pcs &= ~(1 << port);
        }
 
-       return 0;
+       /* disable offline ports on non-AHCI controllers */
+       if (!(ap->flags & PIIX_FLAG_AHCI))
+               pci_write_config_byte(pdev, ICH5_PCS, pcs);
+
+       DPRINTK("ata%u: LEAVE, pcs=0x%x present_mask=0x%x\n",
+               ap->id, pcs, present_mask);
+
+       return present_mask;
 }
 
 /**
- *     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);
 }
 
 /**
@@ -627,6 +742,7 @@ static int piix_disable_ahci(struct pci_dev *pdev)
 
 /**
  *     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
@@ -659,6 +775,54 @@ static int __devinit piix_check_450nx_errata(struct pci_dev *ata_dev)
        return no_piix_dma;
 }              
 
+static void __devinit piix_init_sata_map(struct pci_dev *pdev,
+                                        struct ata_port_info *pinfo)
+{
+       struct piix_map_db *map_db = pinfo[0].private_data;
+       const unsigned int *map;
+       int i, invalid_map = 0;
+       u8 map_value;
+
+       pci_read_config_byte(pdev, ICH5_PMR, &map_value);
+
+       map = map_db->map[map_value & map_db->mask];
+
+       dev_printk(KERN_INFO, &pdev->dev, "MAP [");
+       for (i = 0; i < 4; i++) {
+               switch (map[i]) {
+               case RV:
+                       invalid_map = 1;
+                       printk(" XX");
+                       break;
+
+               case NA:
+                       printk(" --");
+                       break;
+
+               case IDE:
+                       WARN_ON((i & 1) || map[i + 1] != IDE);
+                       pinfo[i / 2] = piix_port_info[ich5_pata];
+                       i++;
+                       printk(" IDE IDE");
+                       break;
+
+               default:
+                       printk(" P%d", map[i]);
+                       if (i & 1)
+                               pinfo[i / 2].host_flags |= ATA_FLAG_SLAVE_POSS;
+                       break;
+               }
+       }
+       printk(" ]\n");
+
+       if (invalid_map)
+               dev_printk(KERN_ERR, &pdev->dev,
+                          "invalid MAP value %u\n", map_value);
+
+       pinfo[0].private_data = (void *)map;
+       pinfo[1].private_data = (void *)map;
+}
+
 /**
  *     piix_init_one - Register PIIX ATA PCI device with kernel services
  *     @pdev: PCI device to register
@@ -677,9 +841,9 @@ static int __devinit piix_check_450nx_errata(struct pci_dev *ata_dev)
 static int piix_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
 {
        static int printed_version;
-       struct ata_port_info *port_info[2];
-       unsigned int combined = 0;
-       unsigned int pata_chan = 0, sata_chan = 0;
+       struct ata_port_info port_info[2];
+       struct ata_port_info *ppinfo[2] = { &port_info[0], &port_info[1] };
+       unsigned long host_flags;
 
        if (!printed_version++)
                dev_printk(KERN_DEBUG, &pdev->dev,
@@ -689,10 +853,12 @@ static int piix_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
        if (!in_module_init)
                return -ENODEV;
 
-       port_info[0] = &piix_port_info[ent->driver_data];
-       port_info[1] = &piix_port_info[ent->driver_data];
+       port_info[0] = piix_port_info[ent->driver_data];
+       port_info[1] = piix_port_info[ent->driver_data];
+
+       host_flags = port_info[0].host_flags;
 
-       if (port_info[0]->host_flags & PIIX_FLAG_AHCI) {
+       if (host_flags & PIIX_FLAG_AHCI) {
                u8 tmp;
                pci_read_config_byte(pdev, PIIX_SCC, &tmp);
                if (tmp == PIIX_AHCI_DEVICE) {
@@ -702,18 +868,9 @@ static int piix_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
                }
        }
 
-       if (port_info[0]->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)
-                               sata_chan = 1;
-                       else
-                               pata_chan = 1;
-               }
-       }
+       /* Initialize SATA map */
+       if (host_flags & ATA_FLAG_SATA)
+               piix_init_sata_map(pdev, port_info);
 
        /* On ICH5, some BIOSen disable the interrupt using the
         * PCI_COMMAND_INTX_DISABLE bit added in PCI 2.3.
@@ -721,28 +878,19 @@ 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) {
-               port_info[sata_chan] = &piix_port_info[ent->driver_data];
-               port_info[sata_chan]->host_flags |= ATA_FLAG_SLAVE_POSS;
-               port_info[pata_chan] = &piix_port_info[ich5_pata];
-
-               dev_printk(KERN_WARNING, &pdev->dev,
-                          "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;
+               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);
+       return ata_pci_init_one(pdev, ppinfo, 2);
 }
 
 static int __init piix_init(void)
diff --git a/drivers/scsi/libata-bmdma.c b/drivers/scsi/libata-bmdma.c
new file mode 100644 (file)
index 0000000..a93336a
--- /dev/null
@@ -0,0 +1,703 @@
+/*
+ *  libata-bmdma.c - helper library for PCI IDE BMDMA
+ *
+ *  Maintained by:  Jeff Garzik <jgarzik@pobox.com>
+ *                 Please ALWAYS copy linux-ide@vger.kernel.org
+ *                 on emails.
+ *
+ *  Copyright 2003-2006 Red Hat, Inc.  All rights reserved.
+ *  Copyright 2003-2006 Jeff Garzik
+ *
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2, or (at your option)
+ *  any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; see the file COPYING.  If not, write to
+ *  the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ *
+ *  libata documentation is available via 'make {ps|pdf}docs',
+ *  as Documentation/DocBook/libata.*
+ *
+ *  Hardware documentation available from http://www.t13.org/ and
+ *  http://www.sata-io.org/
+ *
+ */
+
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/pci.h>
+#include <linux/libata.h>
+
+#include "libata.h"
+
+/**
+ *     ata_tf_load_pio - send taskfile registers to host controller
+ *     @ap: Port to which output is sent
+ *     @tf: ATA taskfile register set
+ *
+ *     Outputs ATA taskfile to standard ATA host controller.
+ *
+ *     LOCKING:
+ *     Inherited from caller.
+ */
+
+static void ata_tf_load_pio(struct ata_port *ap, const struct ata_taskfile *tf)
+{
+       struct ata_ioports *ioaddr = &ap->ioaddr;
+       unsigned int is_addr = tf->flags & ATA_TFLAG_ISADDR;
+
+       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->feature_addr);
+               outb(tf->hob_nsect, ioaddr->nsect_addr);
+               outb(tf->hob_lbal, ioaddr->lbal_addr);
+               outb(tf->hob_lbam, ioaddr->lbam_addr);
+               outb(tf->hob_lbah, ioaddr->lbah_addr);
+               VPRINTK("hob: feat 0x%X nsect 0x%X, lba 0x%X 0x%X 0x%X\n",
+                       tf->hob_feature,
+                       tf->hob_nsect,
+                       tf->hob_lbal,
+                       tf->hob_lbam,
+                       tf->hob_lbah);
+       }
+
+       if (is_addr) {
+               outb(tf->feature, ioaddr->feature_addr);
+               outb(tf->nsect, ioaddr->nsect_addr);
+               outb(tf->lbal, ioaddr->lbal_addr);
+               outb(tf->lbam, ioaddr->lbam_addr);
+               outb(tf->lbah, ioaddr->lbah_addr);
+               VPRINTK("feat 0x%X nsect 0x%X lba 0x%X 0x%X 0x%X\n",
+                       tf->feature,
+                       tf->nsect,
+                       tf->lbal,
+                       tf->lbam,
+                       tf->lbah);
+       }
+
+       if (tf->flags & ATA_TFLAG_DEVICE) {
+               outb(tf->device, ioaddr->device_addr);
+               VPRINTK("device 0x%X\n", tf->device);
+       }
+
+       ata_wait_idle(ap);
+}
+
+/**
+ *     ata_tf_load_mmio - send taskfile registers to host controller
+ *     @ap: Port to which output is sent
+ *     @tf: ATA taskfile register set
+ *
+ *     Outputs ATA taskfile to standard ATA host controller using MMIO.
+ *
+ *     LOCKING:
+ *     Inherited from caller.
+ */
+
+static void ata_tf_load_mmio(struct ata_port *ap, const struct ata_taskfile *tf)
+{
+       struct ata_ioports *ioaddr = &ap->ioaddr;
+       unsigned int is_addr = tf->flags & ATA_TFLAG_ISADDR;
+
+       if (tf->ctl != ap->last_ctl) {
+               writeb(tf->ctl, (void __iomem *) 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 __iomem *) ioaddr->feature_addr);
+               writeb(tf->hob_nsect, (void __iomem *) ioaddr->nsect_addr);
+               writeb(tf->hob_lbal, (void __iomem *) ioaddr->lbal_addr);
+               writeb(tf->hob_lbam, (void __iomem *) ioaddr->lbam_addr);
+               writeb(tf->hob_lbah, (void __iomem *) ioaddr->lbah_addr);
+               VPRINTK("hob: feat 0x%X nsect 0x%X, lba 0x%X 0x%X 0x%X\n",
+                       tf->hob_feature,
+                       tf->hob_nsect,
+                       tf->hob_lbal,
+                       tf->hob_lbam,
+                       tf->hob_lbah);
+       }
+
+       if (is_addr) {
+               writeb(tf->feature, (void __iomem *) ioaddr->feature_addr);
+               writeb(tf->nsect, (void __iomem *) ioaddr->nsect_addr);
+               writeb(tf->lbal, (void __iomem *) ioaddr->lbal_addr);
+               writeb(tf->lbam, (void __iomem *) ioaddr->lbam_addr);
+               writeb(tf->lbah, (void __iomem *) ioaddr->lbah_addr);
+               VPRINTK("feat 0x%X nsect 0x%X lba 0x%X 0x%X 0x%X\n",
+                       tf->feature,
+                       tf->nsect,
+                       tf->lbal,
+                       tf->lbam,
+                       tf->lbah);
+       }
+
+       if (tf->flags & ATA_TFLAG_DEVICE) {
+               writeb(tf->device, (void __iomem *) ioaddr->device_addr);
+               VPRINTK("device 0x%X\n", tf->device);
+       }
+
+       ata_wait_idle(ap);
+}
+
+
+/**
+ *     ata_tf_load - send taskfile registers to host controller
+ *     @ap: Port to which output is sent
+ *     @tf: ATA taskfile register set
+ *
+ *     Outputs ATA taskfile to standard ATA host controller using MMIO
+ *     or PIO as indicated by the ATA_FLAG_MMIO flag.
+ *     Writes the control, feature, nsect, lbal, lbam, and lbah registers.
+ *     Optionally (ATA_TFLAG_LBA48) writes hob_feature, hob_nsect,
+ *     hob_lbal, hob_lbam, and hob_lbah.
+ *
+ *     This function waits for idle (!BUSY and !DRQ) after writing
+ *     registers.  If the control register has a new value, this
+ *     function also waits for idle after writing control and before
+ *     writing the remaining registers.
+ *
+ *     May be used as the tf_load() entry in ata_port_operations.
+ *
+ *     LOCKING:
+ *     Inherited from caller.
+ */
+void ata_tf_load(struct ata_port *ap, const struct ata_taskfile *tf)
+{
+       if (ap->flags & ATA_FLAG_MMIO)
+               ata_tf_load_mmio(ap, tf);
+       else
+               ata_tf_load_pio(ap, tf);
+}
+
+/**
+ *     ata_exec_command_pio - issue ATA command to host controller
+ *     @ap: port to which command is being issued
+ *     @tf: ATA taskfile register set
+ *
+ *     Issues PIO write to ATA command register, with proper
+ *     synchronization with interrupt handler / other threads.
+ *
+ *     LOCKING:
+ *     spin_lock_irqsave(host_set lock)
+ */
+
+static void ata_exec_command_pio(struct ata_port *ap, const struct ata_taskfile *tf)
+{
+       DPRINTK("ata%u: cmd 0x%X\n", ap->id, tf->command);
+
+               outb(tf->command, ap->ioaddr.command_addr);
+       ata_pause(ap);
+}
+
+
+/**
+ *     ata_exec_command_mmio - issue ATA command to host controller
+ *     @ap: port to which command is being issued
+ *     @tf: ATA taskfile register set
+ *
+ *     Issues MMIO write to ATA command register, with proper
+ *     synchronization with interrupt handler / other threads.
+ *
+ *     LOCKING:
+ *     spin_lock_irqsave(host_set lock)
+ */
+
+static void ata_exec_command_mmio(struct ata_port *ap, const struct ata_taskfile *tf)
+{
+       DPRINTK("ata%u: cmd 0x%X\n", ap->id, tf->command);
+
+               writeb(tf->command, (void __iomem *) ap->ioaddr.command_addr);
+       ata_pause(ap);
+}
+
+
+/**
+ *     ata_exec_command - issue ATA command to host controller
+ *     @ap: port to which command is being issued
+ *     @tf: ATA taskfile register set
+ *
+ *     Issues PIO/MMIO write to ATA command register, with proper
+ *     synchronization with interrupt handler / other threads.
+ *
+ *     LOCKING:
+ *     spin_lock_irqsave(host_set lock)
+ */
+void ata_exec_command(struct ata_port *ap, const struct ata_taskfile *tf)
+{
+       if (ap->flags & ATA_FLAG_MMIO)
+               ata_exec_command_mmio(ap, tf);
+       else
+               ata_exec_command_pio(ap, tf);
+}
+
+/**
+ *     ata_tf_read_pio - input device's ATA taskfile shadow registers
+ *     @ap: Port from which input is read
+ *     @tf: ATA taskfile register set for storing input
+ *
+ *     Reads ATA taskfile registers for currently-selected device
+ *     into @tf.
+ *
+ *     LOCKING:
+ *     Inherited from caller.
+ */
+
+static void ata_tf_read_pio(struct ata_port *ap, struct ata_taskfile *tf)
+{
+       struct ata_ioports *ioaddr = &ap->ioaddr;
+
+       tf->command = ata_check_status(ap);
+       tf->feature = inb(ioaddr->error_addr);
+       tf->nsect = inb(ioaddr->nsect_addr);
+       tf->lbal = inb(ioaddr->lbal_addr);
+       tf->lbam = inb(ioaddr->lbam_addr);
+       tf->lbah = inb(ioaddr->lbah_addr);
+       tf->device = inb(ioaddr->device_addr);
+
+       if (tf->flags & ATA_TFLAG_LBA48) {
+               outb(tf->ctl | ATA_HOB, ioaddr->ctl_addr);
+               tf->hob_feature = inb(ioaddr->error_addr);
+               tf->hob_nsect = inb(ioaddr->nsect_addr);
+               tf->hob_lbal = inb(ioaddr->lbal_addr);
+               tf->hob_lbam = inb(ioaddr->lbam_addr);
+               tf->hob_lbah = inb(ioaddr->lbah_addr);
+       }
+}
+
+/**
+ *     ata_tf_read_mmio - input device's ATA taskfile shadow registers
+ *     @ap: Port from which input is read
+ *     @tf: ATA taskfile register set for storing input
+ *
+ *     Reads ATA taskfile registers for currently-selected device
+ *     into @tf via MMIO.
+ *
+ *     LOCKING:
+ *     Inherited from caller.
+ */
+
+static void ata_tf_read_mmio(struct ata_port *ap, struct ata_taskfile *tf)
+{
+       struct ata_ioports *ioaddr = &ap->ioaddr;
+
+       tf->command = ata_check_status(ap);
+       tf->feature = readb((void __iomem *)ioaddr->error_addr);
+       tf->nsect = readb((void __iomem *)ioaddr->nsect_addr);
+       tf->lbal = readb((void __iomem *)ioaddr->lbal_addr);
+       tf->lbam = readb((void __iomem *)ioaddr->lbam_addr);
+       tf->lbah = readb((void __iomem *)ioaddr->lbah_addr);
+       tf->device = readb((void __iomem *)ioaddr->device_addr);
+
+       if (tf->flags & ATA_TFLAG_LBA48) {
+               writeb(tf->ctl | ATA_HOB, (void __iomem *) ap->ioaddr.ctl_addr);
+               tf->hob_feature = readb((void __iomem *)ioaddr->error_addr);
+               tf->hob_nsect = readb((void __iomem *)ioaddr->nsect_addr);
+               tf->hob_lbal = readb((void __iomem *)ioaddr->lbal_addr);
+               tf->hob_lbam = readb((void __iomem *)ioaddr->lbam_addr);
+               tf->hob_lbah = readb((void __iomem *)ioaddr->lbah_addr);
+       }
+}
+
+
+/**
+ *     ata_tf_read - input device's ATA taskfile shadow registers
+ *     @ap: Port from which input is read
+ *     @tf: ATA taskfile register set for storing input
+ *
+ *     Reads ATA taskfile registers for currently-selected device
+ *     into @tf.
+ *
+ *     Reads nsect, lbal, lbam, lbah, and device.  If ATA_TFLAG_LBA48
+ *     is set, also reads the hob registers.
+ *
+ *     May be used as the tf_read() entry in ata_port_operations.
+ *
+ *     LOCKING:
+ *     Inherited from caller.
+ */
+void ata_tf_read(struct ata_port *ap, struct ata_taskfile *tf)
+{
+       if (ap->flags & ATA_FLAG_MMIO)
+               ata_tf_read_mmio(ap, tf);
+       else
+               ata_tf_read_pio(ap, tf);
+}
+
+/**
+ *     ata_check_status_pio - Read device status reg & clear interrupt
+ *     @ap: port where the device is
+ *
+ *     Reads ATA taskfile status register for currently-selected device
+ *     and return its value. This also clears pending interrupts
+ *      from this device
+ *
+ *     LOCKING:
+ *     Inherited from caller.
+ */
+static u8 ata_check_status_pio(struct ata_port *ap)
+{
+       return inb(ap->ioaddr.status_addr);
+}
+
+/**
+ *     ata_check_status_mmio - Read device status reg & clear interrupt
+ *     @ap: port where the device is
+ *
+ *     Reads ATA taskfile status register for currently-selected device
+ *     via MMIO and return its value. This also clears pending interrupts
+ *      from this device
+ *
+ *     LOCKING:
+ *     Inherited from caller.
+ */
+static u8 ata_check_status_mmio(struct ata_port *ap)
+{
+               return readb((void __iomem *) ap->ioaddr.status_addr);
+}
+
+
+/**
+ *     ata_check_status - Read device status reg & clear interrupt
+ *     @ap: port where the device is
+ *
+ *     Reads ATA taskfile status register for currently-selected device
+ *     and return its value. This also clears pending interrupts
+ *      from this device
+ *
+ *     May be used as the check_status() entry in ata_port_operations.
+ *
+ *     LOCKING:
+ *     Inherited from caller.
+ */
+u8 ata_check_status(struct ata_port *ap)
+{
+       if (ap->flags & ATA_FLAG_MMIO)
+               return ata_check_status_mmio(ap);
+       return ata_check_status_pio(ap);
+}
+
+
+/**
+ *     ata_altstatus - Read device alternate status reg
+ *     @ap: port where the device is
+ *
+ *     Reads ATA taskfile alternate status register for
+ *     currently-selected device and return its value.
+ *
+ *     Note: may NOT be used as the check_altstatus() entry in
+ *     ata_port_operations.
+ *
+ *     LOCKING:
+ *     Inherited from caller.
+ */
+u8 ata_altstatus(struct ata_port *ap)
+{
+       if (ap->ops->check_altstatus)
+               return ap->ops->check_altstatus(ap);
+
+       if (ap->flags & ATA_FLAG_MMIO)
+               return readb((void __iomem *)ap->ioaddr.altstatus_addr);
+       return inb(ap->ioaddr.altstatus_addr);
+}
+
+#ifdef CONFIG_PCI
+static struct ata_probe_ent *
+ata_probe_ent_alloc(struct device *dev, const struct ata_port_info *port)
+{
+       struct ata_probe_ent *probe_ent;
+
+       probe_ent = kzalloc(sizeof(*probe_ent), GFP_KERNEL);
+       if (!probe_ent) {
+               printk(KERN_ERR DRV_NAME "(%s): out of memory\n",
+                      kobject_name(&(dev->kobj)));
+               return NULL;
+       }
+
+       INIT_LIST_HEAD(&probe_ent->node);
+       probe_ent->dev = dev;
+
+       probe_ent->sht = port->sht;
+       probe_ent->host_flags = port->host_flags;
+       probe_ent->pio_mask = port->pio_mask;
+       probe_ent->mwdma_mask = port->mwdma_mask;
+       probe_ent->udma_mask = port->udma_mask;
+       probe_ent->port_ops = port->port_ops;
+
+       return probe_ent;
+}
+
+
+/**
+ *     ata_pci_init_native_mode - Initialize native-mode driver
+ *     @pdev:  pci device to be initialized
+ *     @port:  array[2] of pointers to port info structures.
+ *     @ports: bitmap of ports present
+ *
+ *     Utility function which allocates and initializes an
+ *     ata_probe_ent structure for a standard dual-port
+ *     PIO-based IDE controller.  The returned ata_probe_ent
+ *     structure can be passed to ata_device_add().  The returned
+ *     ata_probe_ent structure should then be freed with kfree().
+ *
+ *     The caller need only pass the address of the primary port, the
+ *     secondary will be deduced automatically. If the device has non
+ *     standard secondary port mappings this function can be called twice,
+ *     once for each interface.
+ */
+
+struct ata_probe_ent *
+ata_pci_init_native_mode(struct pci_dev *pdev, struct ata_port_info **port, int ports)
+{
+       struct ata_probe_ent *probe_ent =
+               ata_probe_ent_alloc(pci_dev_to_dev(pdev), port[0]);
+       int p = 0;
+
+       if (!probe_ent)
+               return NULL;
+
+       probe_ent->irq = pdev->irq;
+       probe_ent->irq_flags = SA_SHIRQ;
+       probe_ent->private_data = port[0]->private_data;
+
+       if (ports & ATA_PORT_PRIMARY) {
+               probe_ent->port[p].cmd_addr = pci_resource_start(pdev, 0);
+               probe_ent->port[p].altstatus_addr =
+               probe_ent->port[p].ctl_addr =
+                       pci_resource_start(pdev, 1) | ATA_PCI_CTL_OFS;
+               probe_ent->port[p].bmdma_addr = pci_resource_start(pdev, 4);
+               ata_std_ports(&probe_ent->port[p]);
+               p++;
+       }
+
+       if (ports & ATA_PORT_SECONDARY) {
+               probe_ent->port[p].cmd_addr = pci_resource_start(pdev, 2);
+               probe_ent->port[p].altstatus_addr =
+               probe_ent->port[p].ctl_addr =
+                       pci_resource_start(pdev, 3) | ATA_PCI_CTL_OFS;
+               probe_ent->port[p].bmdma_addr = pci_resource_start(pdev, 4) + 8;
+               ata_std_ports(&probe_ent->port[p]);
+               p++;
+       }
+
+       probe_ent->n_ports = p;
+       return probe_ent;
+}
+
+
+static struct ata_probe_ent *ata_pci_init_legacy_port(struct pci_dev *pdev,
+                               struct ata_port_info *port, int port_num)
+{
+       struct ata_probe_ent *probe_ent;
+
+       probe_ent = ata_probe_ent_alloc(pci_dev_to_dev(pdev), port);
+       if (!probe_ent)
+               return NULL;
+
+       probe_ent->legacy_mode = 1;
+       probe_ent->n_ports = 1;
+       probe_ent->hard_port_no = port_num;
+       probe_ent->private_data = port->private_data;
+
+       switch(port_num)
+       {
+               case 0:
+                       probe_ent->irq = 14;
+                       probe_ent->port[0].cmd_addr = 0x1f0;
+                       probe_ent->port[0].altstatus_addr =
+                       probe_ent->port[0].ctl_addr = 0x3f6;
+                       break;
+               case 1:
+                       probe_ent->irq = 15;
+                       probe_ent->port[0].cmd_addr = 0x170;
+                       probe_ent->port[0].altstatus_addr =
+                       probe_ent->port[0].ctl_addr = 0x376;
+                       break;
+       }
+
+       probe_ent->port[0].bmdma_addr =
+               pci_resource_start(pdev, 4) + 8 * port_num;
+       ata_std_ports(&probe_ent->port[0]);
+
+       return probe_ent;
+}
+
+
+/**
+ *     ata_pci_init_one - Initialize/register PCI IDE host controller
+ *     @pdev: Controller to be initialized
+ *     @port_info: Information from low-level host driver
+ *     @n_ports: Number of ports attached to host controller
+ *
+ *     This is a helper function which can be called from a driver's
+ *     xxx_init_one() probe function if the hardware uses traditional
+ *     IDE taskfile registers.
+ *
+ *     This function calls pci_enable_device(), reserves its register
+ *     regions, sets the dma mask, enables bus master mode, and calls
+ *     ata_device_add()
+ *
+ *     LOCKING:
+ *     Inherited from PCI layer (may sleep).
+ *
+ *     RETURNS:
+ *     Zero on success, negative on errno-based value on error.
+ */
+
+int ata_pci_init_one (struct pci_dev *pdev, struct ata_port_info **port_info,
+                     unsigned int n_ports)
+{
+       struct ata_probe_ent *probe_ent = NULL, *probe_ent2 = NULL;
+       struct ata_port_info *port[2];
+       u8 tmp8, mask;
+       unsigned int legacy_mode = 0;
+       int disable_dev_on_err = 1;
+       int rc;
+
+       DPRINTK("ENTER\n");
+
+       port[0] = port_info[0];
+       if (n_ports > 1)
+               port[1] = port_info[1];
+       else
+               port[1] = port[0];
+
+       if ((port[0]->host_flags & ATA_FLAG_NO_LEGACY) == 0
+           && (pdev->class >> 8) == PCI_CLASS_STORAGE_IDE) {
+               /* TODO: What if one channel is in native mode ... */
+               pci_read_config_byte(pdev, PCI_CLASS_PROG, &tmp8);
+               mask = (1 << 2) | (1 << 0);
+               if ((tmp8 & mask) != mask)
+                       legacy_mode = (1 << 3);
+       }
+
+       /* FIXME... */
+       if ((!legacy_mode) && (n_ports > 2)) {
+               printk(KERN_ERR "ata: BUG: native mode, n_ports > 2\n");
+               n_ports = 2;
+               /* For now */
+       }
+
+       /* FIXME: Really for ATA it isn't safe because the device may be
+          multi-purpose and we want to leave it alone if it was already
+          enabled. Secondly for shared use as Arjan says we want refcounting
+
+          Checking dev->is_enabled is insufficient as this is not set at
+          boot for the primary video which is BIOS enabled
+         */
+
+       rc = pci_enable_device(pdev);
+       if (rc)
+               return rc;
+
+       rc = pci_request_regions(pdev, DRV_NAME);
+       if (rc) {
+               disable_dev_on_err = 0;
+               goto err_out;
+       }
+
+       /* FIXME: Should use platform specific mappers for legacy port ranges */
+       if (legacy_mode) {
+               if (!request_region(0x1f0, 8, "libata")) {
+                       struct resource *conflict, res;
+                       res.start = 0x1f0;
+                       res.end = 0x1f0 + 8 - 1;
+                       conflict = ____request_resource(&ioport_resource, &res);
+                       if (!strcmp(conflict->name, "libata"))
+                               legacy_mode |= (1 << 0);
+                       else {
+                               disable_dev_on_err = 0;
+                               printk(KERN_WARNING "ata: 0x1f0 IDE port busy\n");
+                       }
+               } else
+                       legacy_mode |= (1 << 0);
+
+               if (!request_region(0x170, 8, "libata")) {
+                       struct resource *conflict, res;
+                       res.start = 0x170;
+                       res.end = 0x170 + 8 - 1;
+                       conflict = ____request_resource(&ioport_resource, &res);
+                       if (!strcmp(conflict->name, "libata"))
+                               legacy_mode |= (1 << 1);
+                       else {
+                               disable_dev_on_err = 0;
+                               printk(KERN_WARNING "ata: 0x170 IDE port busy\n");
+                       }
+               } else
+                       legacy_mode |= (1 << 1);
+       }
+
+       /* we have legacy mode, but all ports are unavailable */
+       if (legacy_mode == (1 << 3)) {
+               rc = -EBUSY;
+               goto err_out_regions;
+       }
+
+       rc = pci_set_dma_mask(pdev, ATA_DMA_MASK);
+       if (rc)
+               goto err_out_regions;
+       rc = pci_set_consistent_dma_mask(pdev, ATA_DMA_MASK);
+       if (rc)
+               goto err_out_regions;
+
+       if (legacy_mode) {
+               if (legacy_mode & (1 << 0))
+                       probe_ent = ata_pci_init_legacy_port(pdev, port[0], 0);
+               if (legacy_mode & (1 << 1))
+                       probe_ent2 = ata_pci_init_legacy_port(pdev, port[1], 1);
+       } else {
+               if (n_ports == 2)
+                       probe_ent = ata_pci_init_native_mode(pdev, port, ATA_PORT_PRIMARY | ATA_PORT_SECONDARY);
+               else
+                       probe_ent = ata_pci_init_native_mode(pdev, port, ATA_PORT_PRIMARY);
+       }
+       if (!probe_ent && !probe_ent2) {
+               rc = -ENOMEM;
+               goto err_out_regions;
+       }
+
+       pci_set_master(pdev);
+
+       /* FIXME: check ata_device_add return */
+       if (legacy_mode) {
+               if (legacy_mode & (1 << 0))
+                       ata_device_add(probe_ent);
+               if (legacy_mode & (1 << 1))
+                       ata_device_add(probe_ent2);
+       } else
+               ata_device_add(probe_ent);
+
+       kfree(probe_ent);
+       kfree(probe_ent2);
+
+       return 0;
+
+err_out_regions:
+       if (legacy_mode & (1 << 0))
+               release_region(0x1f0, 8);
+       if (legacy_mode & (1 << 1))
+               release_region(0x170, 8);
+       pci_release_regions(pdev);
+err_out:
+       if (disable_dev_on_err)
+               pci_disable_device(pdev);
+       return rc;
+}
+
+#endif /* CONFIG_PCI */
+
index 4f91b0dc572bb5b1aea66a6aed56df874808eac8..439b6db138024b3a1edb0baa8d7d3b47715d4f45 100644 (file)
 
 #include "libata.h"
 
-static unsigned int ata_busy_sleep (struct ata_port *ap,
-                                   unsigned long tmout_pat,
-                                   unsigned long tmout);
-static void ata_dev_reread_id(struct ata_port *ap, struct ata_device *dev);
-static void ata_dev_init_params(struct ata_port *ap, struct ata_device *dev);
+static unsigned int ata_dev_init_params(struct ata_port *ap,
+                                       struct ata_device *dev);
 static void ata_set_mode(struct ata_port *ap);
 static void ata_dev_set_xfermode(struct ata_port *ap, struct ata_device *dev);
-static unsigned int ata_get_mode_mask(const struct ata_port *ap, int shift);
-static int fgb(u32 bitmap);
-static int ata_choose_xfer_mode(const struct ata_port *ap,
-                               u8 *xfer_mode_out,
-                               unsigned int *xfer_shift_out);
-static void __ata_qc_complete(struct ata_queued_cmd *qc);
+static unsigned int ata_dev_xfermask(struct ata_port *ap,
+                                    struct ata_device *dev);
 
 static unsigned int ata_unique_id = 1;
 static struct workqueue_struct *ata_wq;
 
-int atapi_enabled = 0;
+int atapi_enabled = 1;
 module_param(atapi_enabled, int, 0444);
 MODULE_PARM_DESC(atapi_enabled, "Enable discovery of ATAPI devices (0=off, 1=on)");
 
@@ -91,403 +84,6 @@ MODULE_DESCRIPTION("Library module for ATA devices");
 MODULE_LICENSE("GPL");
 MODULE_VERSION(DRV_VERSION);
 
-/**
- *     ata_tf_load_pio - send taskfile registers to host controller
- *     @ap: Port to which output is sent
- *     @tf: ATA taskfile register set
- *
- *     Outputs ATA taskfile to standard ATA host controller.
- *
- *     LOCKING:
- *     Inherited from caller.
- */
-
-static void ata_tf_load_pio(struct ata_port *ap, const struct ata_taskfile *tf)
-{
-       struct ata_ioports *ioaddr = &ap->ioaddr;
-       unsigned int is_addr = tf->flags & ATA_TFLAG_ISADDR;
-
-       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->feature_addr);
-               outb(tf->hob_nsect, ioaddr->nsect_addr);
-               outb(tf->hob_lbal, ioaddr->lbal_addr);
-               outb(tf->hob_lbam, ioaddr->lbam_addr);
-               outb(tf->hob_lbah, ioaddr->lbah_addr);
-               VPRINTK("hob: feat 0x%X nsect 0x%X, lba 0x%X 0x%X 0x%X\n",
-                       tf->hob_feature,
-                       tf->hob_nsect,
-                       tf->hob_lbal,
-                       tf->hob_lbam,
-                       tf->hob_lbah);
-       }
-
-       if (is_addr) {
-               outb(tf->feature, ioaddr->feature_addr);
-               outb(tf->nsect, ioaddr->nsect_addr);
-               outb(tf->lbal, ioaddr->lbal_addr);
-               outb(tf->lbam, ioaddr->lbam_addr);
-               outb(tf->lbah, ioaddr->lbah_addr);
-               VPRINTK("feat 0x%X nsect 0x%X lba 0x%X 0x%X 0x%X\n",
-                       tf->feature,
-                       tf->nsect,
-                       tf->lbal,
-                       tf->lbam,
-                       tf->lbah);
-       }
-
-       if (tf->flags & ATA_TFLAG_DEVICE) {
-               outb(tf->device, ioaddr->device_addr);
-               VPRINTK("device 0x%X\n", tf->device);
-       }
-
-       ata_wait_idle(ap);
-}
-
-/**
- *     ata_tf_load_mmio - send taskfile registers to host controller
- *     @ap: Port to which output is sent
- *     @tf: ATA taskfile register set
- *
- *     Outputs ATA taskfile to standard ATA host controller using MMIO.
- *
- *     LOCKING:
- *     Inherited from caller.
- */
-
-static void ata_tf_load_mmio(struct ata_port *ap, const struct ata_taskfile *tf)
-{
-       struct ata_ioports *ioaddr = &ap->ioaddr;
-       unsigned int is_addr = tf->flags & ATA_TFLAG_ISADDR;
-
-       if (tf->ctl != ap->last_ctl) {
-               writeb(tf->ctl, (void __iomem *) 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 __iomem *) ioaddr->feature_addr);
-               writeb(tf->hob_nsect, (void __iomem *) ioaddr->nsect_addr);
-               writeb(tf->hob_lbal, (void __iomem *) ioaddr->lbal_addr);
-               writeb(tf->hob_lbam, (void __iomem *) ioaddr->lbam_addr);
-               writeb(tf->hob_lbah, (void __iomem *) ioaddr->lbah_addr);
-               VPRINTK("hob: feat 0x%X nsect 0x%X, lba 0x%X 0x%X 0x%X\n",
-                       tf->hob_feature,
-                       tf->hob_nsect,
-                       tf->hob_lbal,
-                       tf->hob_lbam,
-                       tf->hob_lbah);
-       }
-
-       if (is_addr) {
-               writeb(tf->feature, (void __iomem *) ioaddr->feature_addr);
-               writeb(tf->nsect, (void __iomem *) ioaddr->nsect_addr);
-               writeb(tf->lbal, (void __iomem *) ioaddr->lbal_addr);
-               writeb(tf->lbam, (void __iomem *) ioaddr->lbam_addr);
-               writeb(tf->lbah, (void __iomem *) ioaddr->lbah_addr);
-               VPRINTK("feat 0x%X nsect 0x%X lba 0x%X 0x%X 0x%X\n",
-                       tf->feature,
-                       tf->nsect,
-                       tf->lbal,
-                       tf->lbam,
-                       tf->lbah);
-       }
-
-       if (tf->flags & ATA_TFLAG_DEVICE) {
-               writeb(tf->device, (void __iomem *) ioaddr->device_addr);
-               VPRINTK("device 0x%X\n", tf->device);
-       }
-
-       ata_wait_idle(ap);
-}
-
-
-/**
- *     ata_tf_load - send taskfile registers to host controller
- *     @ap: Port to which output is sent
- *     @tf: ATA taskfile register set
- *
- *     Outputs ATA taskfile to standard ATA host controller using MMIO
- *     or PIO as indicated by the ATA_FLAG_MMIO flag.
- *     Writes the control, feature, nsect, lbal, lbam, and lbah registers.
- *     Optionally (ATA_TFLAG_LBA48) writes hob_feature, hob_nsect,
- *     hob_lbal, hob_lbam, and hob_lbah.
- *
- *     This function waits for idle (!BUSY and !DRQ) after writing
- *     registers.  If the control register has a new value, this
- *     function also waits for idle after writing control and before
- *     writing the remaining registers.
- *
- *     May be used as the tf_load() entry in ata_port_operations.
- *
- *     LOCKING:
- *     Inherited from caller.
- */
-void ata_tf_load(struct ata_port *ap, const struct ata_taskfile *tf)
-{
-       if (ap->flags & ATA_FLAG_MMIO)
-               ata_tf_load_mmio(ap, tf);
-       else
-               ata_tf_load_pio(ap, tf);
-}
-
-/**
- *     ata_exec_command_pio - issue ATA command to host controller
- *     @ap: port to which command is being issued
- *     @tf: ATA taskfile register set
- *
- *     Issues PIO write to ATA command register, with proper
- *     synchronization with interrupt handler / other threads.
- *
- *     LOCKING:
- *     spin_lock_irqsave(host_set lock)
- */
-
-static void ata_exec_command_pio(struct ata_port *ap, const struct ata_taskfile *tf)
-{
-       DPRINTK("ata%u: cmd 0x%X\n", ap->id, tf->command);
-
-               outb(tf->command, ap->ioaddr.command_addr);
-       ata_pause(ap);
-}
-
-
-/**
- *     ata_exec_command_mmio - issue ATA command to host controller
- *     @ap: port to which command is being issued
- *     @tf: ATA taskfile register set
- *
- *     Issues MMIO write to ATA command register, with proper
- *     synchronization with interrupt handler / other threads.
- *
- *     LOCKING:
- *     spin_lock_irqsave(host_set lock)
- */
-
-static void ata_exec_command_mmio(struct ata_port *ap, const struct ata_taskfile *tf)
-{
-       DPRINTK("ata%u: cmd 0x%X\n", ap->id, tf->command);
-
-               writeb(tf->command, (void __iomem *) ap->ioaddr.command_addr);
-       ata_pause(ap);
-}
-
-
-/**
- *     ata_exec_command - issue ATA command to host controller
- *     @ap: port to which command is being issued
- *     @tf: ATA taskfile register set
- *
- *     Issues PIO/MMIO write to ATA command register, with proper
- *     synchronization with interrupt handler / other threads.
- *
- *     LOCKING:
- *     spin_lock_irqsave(host_set lock)
- */
-void ata_exec_command(struct ata_port *ap, const struct ata_taskfile *tf)
-{
-       if (ap->flags & ATA_FLAG_MMIO)
-               ata_exec_command_mmio(ap, tf);
-       else
-               ata_exec_command_pio(ap, tf);
-}
-
-/**
- *     ata_tf_to_host - issue ATA taskfile to host controller
- *     @ap: port to which command is being issued
- *     @tf: ATA taskfile register set
- *
- *     Issues ATA taskfile register set to ATA host controller,
- *     with proper synchronization with interrupt handler and
- *     other threads.
- *
- *     LOCKING:
- *     spin_lock_irqsave(host_set lock)
- */
-
-static inline void ata_tf_to_host(struct ata_port *ap,
-                                 const struct ata_taskfile *tf)
-{
-       ap->ops->tf_load(ap, tf);
-       ap->ops->exec_command(ap, tf);
-}
-
-/**
- *     ata_tf_read_pio - input device's ATA taskfile shadow registers
- *     @ap: Port from which input is read
- *     @tf: ATA taskfile register set for storing input
- *
- *     Reads ATA taskfile registers for currently-selected device
- *     into @tf.
- *
- *     LOCKING:
- *     Inherited from caller.
- */
-
-static void ata_tf_read_pio(struct ata_port *ap, struct ata_taskfile *tf)
-{
-       struct ata_ioports *ioaddr = &ap->ioaddr;
-
-       tf->command = ata_check_status(ap);
-       tf->feature = inb(ioaddr->error_addr);
-       tf->nsect = inb(ioaddr->nsect_addr);
-       tf->lbal = inb(ioaddr->lbal_addr);
-       tf->lbam = inb(ioaddr->lbam_addr);
-       tf->lbah = inb(ioaddr->lbah_addr);
-       tf->device = inb(ioaddr->device_addr);
-
-       if (tf->flags & ATA_TFLAG_LBA48) {
-               outb(tf->ctl | ATA_HOB, ioaddr->ctl_addr);
-               tf->hob_feature = inb(ioaddr->error_addr);
-               tf->hob_nsect = inb(ioaddr->nsect_addr);
-               tf->hob_lbal = inb(ioaddr->lbal_addr);
-               tf->hob_lbam = inb(ioaddr->lbam_addr);
-               tf->hob_lbah = inb(ioaddr->lbah_addr);
-       }
-}
-
-/**
- *     ata_tf_read_mmio - input device's ATA taskfile shadow registers
- *     @ap: Port from which input is read
- *     @tf: ATA taskfile register set for storing input
- *
- *     Reads ATA taskfile registers for currently-selected device
- *     into @tf via MMIO.
- *
- *     LOCKING:
- *     Inherited from caller.
- */
-
-static void ata_tf_read_mmio(struct ata_port *ap, struct ata_taskfile *tf)
-{
-       struct ata_ioports *ioaddr = &ap->ioaddr;
-
-       tf->command = ata_check_status(ap);
-       tf->feature = readb((void __iomem *)ioaddr->error_addr);
-       tf->nsect = readb((void __iomem *)ioaddr->nsect_addr);
-       tf->lbal = readb((void __iomem *)ioaddr->lbal_addr);
-       tf->lbam = readb((void __iomem *)ioaddr->lbam_addr);
-       tf->lbah = readb((void __iomem *)ioaddr->lbah_addr);
-       tf->device = readb((void __iomem *)ioaddr->device_addr);
-
-       if (tf->flags & ATA_TFLAG_LBA48) {
-               writeb(tf->ctl | ATA_HOB, (void __iomem *) ap->ioaddr.ctl_addr);
-               tf->hob_feature = readb((void __iomem *)ioaddr->error_addr);
-               tf->hob_nsect = readb((void __iomem *)ioaddr->nsect_addr);
-               tf->hob_lbal = readb((void __iomem *)ioaddr->lbal_addr);
-               tf->hob_lbam = readb((void __iomem *)ioaddr->lbam_addr);
-               tf->hob_lbah = readb((void __iomem *)ioaddr->lbah_addr);
-       }
-}
-
-
-/**
- *     ata_tf_read - input device's ATA taskfile shadow registers
- *     @ap: Port from which input is read
- *     @tf: ATA taskfile register set for storing input
- *
- *     Reads ATA taskfile registers for currently-selected device
- *     into @tf.
- *
- *     Reads nsect, lbal, lbam, lbah, and device.  If ATA_TFLAG_LBA48
- *     is set, also reads the hob registers.
- *
- *     May be used as the tf_read() entry in ata_port_operations.
- *
- *     LOCKING:
- *     Inherited from caller.
- */
-void ata_tf_read(struct ata_port *ap, struct ata_taskfile *tf)
-{
-       if (ap->flags & ATA_FLAG_MMIO)
-               ata_tf_read_mmio(ap, tf);
-       else
-               ata_tf_read_pio(ap, tf);
-}
-
-/**
- *     ata_check_status_pio - Read device status reg & clear interrupt
- *     @ap: port where the device is
- *
- *     Reads ATA taskfile status register for currently-selected device
- *     and return its value. This also clears pending interrupts
- *      from this device
- *
- *     LOCKING:
- *     Inherited from caller.
- */
-static u8 ata_check_status_pio(struct ata_port *ap)
-{
-       return inb(ap->ioaddr.status_addr);
-}
-
-/**
- *     ata_check_status_mmio - Read device status reg & clear interrupt
- *     @ap: port where the device is
- *
- *     Reads ATA taskfile status register for currently-selected device
- *     via MMIO and return its value. This also clears pending interrupts
- *      from this device
- *
- *     LOCKING:
- *     Inherited from caller.
- */
-static u8 ata_check_status_mmio(struct ata_port *ap)
-{
-               return readb((void __iomem *) ap->ioaddr.status_addr);
-}
-
-
-/**
- *     ata_check_status - Read device status reg & clear interrupt
- *     @ap: port where the device is
- *
- *     Reads ATA taskfile status register for currently-selected device
- *     and return its value. This also clears pending interrupts
- *      from this device
- *
- *     May be used as the check_status() entry in ata_port_operations.
- *
- *     LOCKING:
- *     Inherited from caller.
- */
-u8 ata_check_status(struct ata_port *ap)
-{
-       if (ap->flags & ATA_FLAG_MMIO)
-               return ata_check_status_mmio(ap);
-       return ata_check_status_pio(ap);
-}
-
-
-/**
- *     ata_altstatus - Read device alternate status reg
- *     @ap: port where the device is
- *
- *     Reads ATA taskfile alternate status register for
- *     currently-selected device and return its value.
- *
- *     Note: may NOT be used as the check_altstatus() entry in
- *     ata_port_operations.
- *
- *     LOCKING:
- *     Inherited from caller.
- */
-u8 ata_altstatus(struct ata_port *ap)
-{
-       if (ap->ops->check_altstatus)
-               return ap->ops->check_altstatus(ap);
-
-       if (ap->flags & ATA_FLAG_MMIO)
-               return readb((void __iomem *)ap->ioaddr.altstatus_addr);
-       return inb(ap->ioaddr.altstatus_addr);
-}
-
 
 /**
  *     ata_tf_to_fis - Convert ATA taskfile to SATA FIS structure
@@ -632,58 +228,148 @@ int ata_rwcmd_protocol(struct ata_queued_cmd *qc)
        return -1;
 }
 
-static const char * const xfer_mode_str[] = {
-       "UDMA/16",
-       "UDMA/25",
-       "UDMA/33",
-       "UDMA/44",
-       "UDMA/66",
-       "UDMA/100",
-       "UDMA/133",
-       "UDMA7",
-       "MWDMA0",
-       "MWDMA1",
-       "MWDMA2",
-       "PIO0",
-       "PIO1",
-       "PIO2",
-       "PIO3",
-       "PIO4",
+/**
+ *     ata_pack_xfermask - Pack pio, mwdma and udma masks into xfer_mask
+ *     @pio_mask: pio_mask
+ *     @mwdma_mask: mwdma_mask
+ *     @udma_mask: udma_mask
+ *
+ *     Pack @pio_mask, @mwdma_mask and @udma_mask into a single
+ *     unsigned int xfer_mask.
+ *
+ *     LOCKING:
+ *     None.
+ *
+ *     RETURNS:
+ *     Packed xfer_mask.
+ */
+static unsigned int ata_pack_xfermask(unsigned int pio_mask,
+                                     unsigned int mwdma_mask,
+                                     unsigned int udma_mask)
+{
+       return ((pio_mask << ATA_SHIFT_PIO) & ATA_MASK_PIO) |
+               ((mwdma_mask << ATA_SHIFT_MWDMA) & ATA_MASK_MWDMA) |
+               ((udma_mask << ATA_SHIFT_UDMA) & ATA_MASK_UDMA);
+}
+
+static const struct ata_xfer_ent {
+       unsigned int shift, bits;
+       u8 base;
+} ata_xfer_tbl[] = {
+       { ATA_SHIFT_PIO, ATA_BITS_PIO, XFER_PIO_0 },
+       { ATA_SHIFT_MWDMA, ATA_BITS_MWDMA, XFER_MW_DMA_0 },
+       { ATA_SHIFT_UDMA, ATA_BITS_UDMA, XFER_UDMA_0 },
+       { -1, },
 };
 
 /**
- *     ata_udma_string - convert UDMA bit offset to string
- *     @mask: mask of bits supported; only highest bit counts.
+ *     ata_xfer_mask2mode - Find matching XFER_* for the given xfer_mask
+ *     @xfer_mask: xfer_mask of interest
  *
- *     Determine string which represents the highest speed
- *     (highest bit in @udma_mask).
+ *     Return matching XFER_* value for @xfer_mask.  Only the highest
+ *     bit of @xfer_mask is considered.
  *
  *     LOCKING:
  *     None.
  *
  *     RETURNS:
- *     Constant C string representing highest speed listed in
- *     @udma_mask, or the constant C string "<n/a>".
+ *     Matching XFER_* value, 0 if no match found.
+ */
+static u8 ata_xfer_mask2mode(unsigned int xfer_mask)
+{
+       int highbit = fls(xfer_mask) - 1;
+       const struct ata_xfer_ent *ent;
+
+       for (ent = ata_xfer_tbl; ent->shift >= 0; ent++)
+               if (highbit >= ent->shift && highbit < ent->shift + ent->bits)
+                       return ent->base + highbit - ent->shift;
+       return 0;
+}
+
+/**
+ *     ata_xfer_mode2mask - Find matching xfer_mask for XFER_*
+ *     @xfer_mode: XFER_* of interest
+ *
+ *     Return matching xfer_mask for @xfer_mode.
+ *
+ *     LOCKING:
+ *     None.
+ *
+ *     RETURNS:
+ *     Matching xfer_mask, 0 if no match found.
  */
+static unsigned int ata_xfer_mode2mask(u8 xfer_mode)
+{
+       const struct ata_xfer_ent *ent;
+
+       for (ent = ata_xfer_tbl; ent->shift >= 0; ent++)
+               if (xfer_mode >= ent->base && xfer_mode < ent->base + ent->bits)
+                       return 1 << (ent->shift + xfer_mode - ent->base);
+       return 0;
+}
 
-static const char *ata_mode_string(unsigned int mask)
+/**
+ *     ata_xfer_mode2shift - Find matching xfer_shift for XFER_*
+ *     @xfer_mode: XFER_* of interest
+ *
+ *     Return matching xfer_shift for @xfer_mode.
+ *
+ *     LOCKING:
+ *     None.
+ *
+ *     RETURNS:
+ *     Matching xfer_shift, -1 if no match found.
+ */
+static int ata_xfer_mode2shift(unsigned int xfer_mode)
 {
-       int i;
+       const struct ata_xfer_ent *ent;
 
-       for (i = 7; i >= 0; i--)
-               if (mask & (1 << i))
-                       goto out;
-       for (i = ATA_SHIFT_MWDMA + 2; i >= ATA_SHIFT_MWDMA; i--)
-               if (mask & (1 << i))
-                       goto out;
-       for (i = ATA_SHIFT_PIO + 4; i >= ATA_SHIFT_PIO; i--)
-               if (mask & (1 << i))
-                       goto out;
+       for (ent = ata_xfer_tbl; ent->shift >= 0; ent++)
+               if (xfer_mode >= ent->base && xfer_mode < ent->base + ent->bits)
+                       return ent->shift;
+       return -1;
+}
 
+/**
+ *     ata_mode_string - convert xfer_mask to string
+ *     @xfer_mask: mask of bits supported; only highest bit counts.
+ *
+ *     Determine string which represents the highest speed
+ *     (highest bit in @modemask).
+ *
+ *     LOCKING:
+ *     None.
+ *
+ *     RETURNS:
+ *     Constant C string representing highest speed listed in
+ *     @mode_mask, or the constant C string "<n/a>".
+ */
+static const char *ata_mode_string(unsigned int xfer_mask)
+{
+       static const char * const xfer_mode_str[] = {
+               "PIO0",
+               "PIO1",
+               "PIO2",
+               "PIO3",
+               "PIO4",
+               "MWDMA0",
+               "MWDMA1",
+               "MWDMA2",
+               "UDMA/16",
+               "UDMA/25",
+               "UDMA/33",
+               "UDMA/44",
+               "UDMA/66",
+               "UDMA/100",
+               "UDMA/133",
+               "UDMA7",
+       };
+       int highbit;
+
+       highbit = fls(xfer_mask) - 1;
+       if (highbit >= 0 && highbit < ARRAY_SIZE(xfer_mode_str))
+               return xfer_mode_str[highbit];
        return "<n/a>";
-
-out:
-       return xfer_mode_str[i];
 }
 
 /**
@@ -838,6 +524,7 @@ unsigned int ata_dev_classify(const struct ata_taskfile *tf)
  *     ata_dev_try_classify - Parse returned ATA device signature
  *     @ap: ATA channel to examine
  *     @device: Device to examine (starting at zero)
+ *     @r_err: Value of error register on completion
  *
  *     After an event -- SRST, E.D.D., or SATA COMRESET -- occurs,
  *     an ATA/ATAPI-defined set of values is placed in the ATA
@@ -850,11 +537,14 @@ unsigned int ata_dev_classify(const struct ata_taskfile *tf)
  *
  *     LOCKING:
  *     caller.
+ *
+ *     RETURNS:
+ *     Device type - %ATA_DEV_ATA, %ATA_DEV_ATAPI or %ATA_DEV_NONE.
  */
 
-static u8 ata_dev_try_classify(struct ata_port *ap, unsigned int device)
+static unsigned int
+ata_dev_try_classify(struct ata_port *ap, unsigned int device, u8 *r_err)
 {
-       struct ata_device *dev = &ap->device[device];
        struct ata_taskfile tf;
        unsigned int class;
        u8 err;
@@ -865,8 +555,8 @@ static u8 ata_dev_try_classify(struct ata_port *ap, unsigned int device)
 
        ap->ops->tf_read(ap, &tf);
        err = tf.feature;
-
-       dev->class = ATA_DEV_NONE;
+       if (r_err)
+               *r_err = err;
 
        /* see if device passed diags */
        if (err == 1)
@@ -874,22 +564,20 @@ static u8 ata_dev_try_classify(struct ata_port *ap, unsigned int device)
        else if ((device == 0) && (err == 0x81))
                /* do nothing */ ;
        else
-               return err;
+               return ATA_DEV_NONE;
 
-       /* determine if device if ATA or ATAPI */
+       /* determine if device is ATA or ATAPI */
        class = ata_dev_classify(&tf);
+
        if (class == ATA_DEV_UNKNOWN)
-               return err;
+               return ATA_DEV_NONE;
        if ((class == ATA_DEV_ATA) && (ata_chk_status(ap) == 0))
-               return err;
-
-       dev->class = class;
-
-       return err;
+               return ATA_DEV_NONE;
+       return class;
 }
 
 /**
- *     ata_dev_id_string - Convert IDENTIFY DEVICE page into string
+ *     ata_id_string - Convert IDENTIFY DEVICE page into string
  *     @id: IDENTIFY DEVICE results we will examine
  *     @s: string into which data is output
  *     @ofs: offset into identify device page
@@ -903,8 +591,8 @@ static u8 ata_dev_try_classify(struct ata_port *ap, unsigned int device)
  *     caller.
  */
 
-void ata_dev_id_string(const u16 *id, unsigned char *s,
-                      unsigned int ofs, unsigned int len)
+void ata_id_string(const u16 *id, unsigned char *s,
+                  unsigned int ofs, unsigned int len)
 {
        unsigned int c;
 
@@ -922,6 +610,49 @@ void ata_dev_id_string(const u16 *id, unsigned char *s,
        }
 }
 
+/**
+ *     ata_id_c_string - Convert IDENTIFY DEVICE page into C string
+ *     @id: IDENTIFY DEVICE results we will examine
+ *     @s: string into which data is output
+ *     @ofs: offset into identify device page
+ *     @len: length of string to return. must be an odd number.
+ *
+ *     This function is identical to ata_id_string except that it
+ *     trims trailing spaces and terminates the resulting string with
+ *     null.  @len must be actual maximum length (even number) + 1.
+ *
+ *     LOCKING:
+ *     caller.
+ */
+void ata_id_c_string(const u16 *id, unsigned char *s,
+                    unsigned int ofs, unsigned int len)
+{
+       unsigned char *p;
+
+       WARN_ON(!(len & 1));
+
+       ata_id_string(id, s, ofs, len - 1);
+
+       p = s + strnlen(s, len - 1);
+       while (p > s && p[-1] == ' ')
+               p--;
+       *p = '\0';
+}
+
+static u64 ata_id_n_sectors(const u16 *id)
+{
+       if (ata_id_has_lba(id)) {
+               if (ata_id_has_lba48(id))
+                       return ata_id_u64(id, 100);
+               else
+                       return ata_id_u32(id, 60);
+       } else {
+               if (ata_id_current_chs_valid(id))
+                       return ata_id_u32(id, 57);
+               else
+                       return id[1] * id[3] * id[6];
+       }
+}
 
 /**
  *     ata_noop_dev_select - Select device 0/1 on ATA bus
@@ -1011,90 +742,172 @@ void ata_dev_select(struct ata_port *ap, unsigned int device,
 
 /**
  *     ata_dump_id - IDENTIFY DEVICE info debugging output
- *     @dev: Device whose IDENTIFY DEVICE page we will dump
+ *     @id: IDENTIFY DEVICE page to dump
  *
- *     Dump selected 16-bit words from a detected device's
- *     IDENTIFY PAGE page.
+ *     Dump selected 16-bit words from the given IDENTIFY DEVICE
+ *     page.
  *
  *     LOCKING:
  *     caller.
  */
 
-static inline void ata_dump_id(const struct ata_device *dev)
+static inline void ata_dump_id(const u16 *id)
 {
        DPRINTK("49==0x%04x  "
                "53==0x%04x  "
                "63==0x%04x  "
                "64==0x%04x  "
                "75==0x%04x  \n",
-               dev->id[49],
-               dev->id[53],
-               dev->id[63],
-               dev->id[64],
-               dev->id[75]);
+               id[49],
+               id[53],
+               id[63],
+               id[64],
+               id[75]);
        DPRINTK("80==0x%04x  "
                "81==0x%04x  "
                "82==0x%04x  "
                "83==0x%04x  "
                "84==0x%04x  \n",
-               dev->id[80],
-               dev->id[81],
-               dev->id[82],
-               dev->id[83],
-               dev->id[84]);
+               id[80],
+               id[81],
+               id[82],
+               id[83],
+               id[84]);
        DPRINTK("88==0x%04x  "
                "93==0x%04x\n",
-               dev->id[88],
-               dev->id[93]);
+               id[88],
+               id[93]);
 }
 
-/*
- *     Compute the PIO modes available for this device. This is not as
- *     trivial as it seems if we must consider early devices correctly.
+/**
+ *     ata_id_xfermask - Compute xfermask from the given IDENTIFY data
+ *     @id: IDENTIFY data to compute xfer mask from
+ *
+ *     Compute the xfermask for this device. This is not as trivial
+ *     as it seems if we must consider early devices correctly.
+ *
+ *     FIXME: pre IDE drive timing (do we care ?).
  *
- *     FIXME: pre IDE drive timing (do we care ?). 
+ *     LOCKING:
+ *     None.
+ *
+ *     RETURNS:
+ *     Computed xfermask
  */
-
-static unsigned int ata_pio_modes(const struct ata_device *adev)
+static unsigned int ata_id_xfermask(const u16 *id)
 {
-       u16 modes;
+       unsigned int pio_mask, mwdma_mask, udma_mask;
 
        /* Usual case. Word 53 indicates word 64 is valid */
-       if (adev->id[ATA_ID_FIELD_VALID] & (1 << 1)) {
-               modes = adev->id[ATA_ID_PIO_MODES] & 0x03;
-               modes <<= 3;
-               modes |= 0x7;
-               return modes;
+       if (id[ATA_ID_FIELD_VALID] & (1 << 1)) {
+               pio_mask = id[ATA_ID_PIO_MODES] & 0x03;
+               pio_mask <<= 3;
+               pio_mask |= 0x7;
+       } else {
+               /* If word 64 isn't valid then Word 51 high byte holds
+                * the PIO timing number for the maximum. Turn it into
+                * a mask.
+                */
+               pio_mask = (2 << (id[ATA_ID_OLD_PIO_MODES] & 0xFF)) - 1 ;
+
+               /* But wait.. there's more. Design your standards by
+                * committee and you too can get a free iordy field to
+                * process. However its the speeds not the modes that
+                * are supported... Note drivers using the timing API
+                * will get this right anyway
+                */
        }
 
-       /* If word 64 isn't valid then Word 51 high byte holds the PIO timing
-          number for the maximum. Turn it into a mask and return it */
-       modes = (2 << ((adev->id[ATA_ID_OLD_PIO_MODES] >> 8) & 0xFF)) - 1 ;
-       return modes;
-       /* But wait.. there's more. Design your standards by committee and
-          you too can get a free iordy field to process. However its the 
-          speeds not the modes that are supported... Note drivers using the
-          timing API will get this right anyway */
+       mwdma_mask = id[ATA_ID_MWDMA_MODES] & 0x07;
+
+       udma_mask = 0;
+       if (id[ATA_ID_FIELD_VALID] & (1 << 2))
+               udma_mask = id[ATA_ID_UDMA_MODES] & 0xff;
+
+       return ata_pack_xfermask(pio_mask, mwdma_mask, udma_mask);
 }
 
-struct ata_exec_internal_arg {
-       unsigned int err_mask;
-       struct ata_taskfile *tf;
-       struct completion *waiting;
-};
+/**
+ *     ata_port_queue_task - Queue port_task
+ *     @ap: The ata_port to queue port_task for
+ *
+ *     Schedule @fn(@data) for execution after @delay jiffies using
+ *     port_task.  There is one port_task per port and it's the
+ *     user(low level driver)'s responsibility to make sure that only
+ *     one task is active at any given time.
+ *
+ *     libata core layer takes care of synchronization between
+ *     port_task and EH.  ata_port_queue_task() may be ignored for EH
+ *     synchronization.
+ *
+ *     LOCKING:
+ *     Inherited from caller.
+ */
+void ata_port_queue_task(struct ata_port *ap, void (*fn)(void *), void *data,
+                        unsigned long delay)
+{
+       int rc;
+
+       if (ap->flags & ATA_FLAG_FLUSH_PORT_TASK)
+               return;
+
+       PREPARE_WORK(&ap->port_task, fn, data);
+
+       if (!delay)
+               rc = queue_work(ata_wq, &ap->port_task);
+       else
+               rc = queue_delayed_work(ata_wq, &ap->port_task, delay);
+
+       /* rc == 0 means that another user is using port task */
+       WARN_ON(rc == 0);
+}
+
+/**
+ *     ata_port_flush_task - Flush port_task
+ *     @ap: The ata_port to flush port_task for
+ *
+ *     After this function completes, port_task is guranteed not to
+ *     be running or scheduled.
+ *
+ *     LOCKING:
+ *     Kernel thread context (may sleep)
+ */
+void ata_port_flush_task(struct ata_port *ap)
+{
+       unsigned long flags;
+
+       DPRINTK("ENTER\n");
+
+       spin_lock_irqsave(&ap->host_set->lock, flags);
+       ap->flags |= ATA_FLAG_FLUSH_PORT_TASK;
+       spin_unlock_irqrestore(&ap->host_set->lock, flags);
+
+       DPRINTK("flush #1\n");
+       flush_workqueue(ata_wq);
+
+       /*
+        * At this point, if a task is running, it's guaranteed to see
+        * the FLUSH flag; thus, it will never queue pio tasks again.
+        * Cancel and flush.
+        */
+       if (!cancel_delayed_work(&ap->port_task)) {
+               DPRINTK("flush #2\n");
+               flush_workqueue(ata_wq);
+       }
 
-int ata_qc_complete_internal(struct ata_queued_cmd *qc)
+       spin_lock_irqsave(&ap->host_set->lock, flags);
+       ap->flags &= ~ATA_FLAG_FLUSH_PORT_TASK;
+       spin_unlock_irqrestore(&ap->host_set->lock, flags);
+
+       DPRINTK("EXIT\n");
+}
+
+void ata_qc_complete_internal(struct ata_queued_cmd *qc)
 {
-       struct ata_exec_internal_arg *arg = qc->private_data;
-       struct completion *waiting = arg->waiting;
+       struct completion *waiting = qc->private_data;
 
-       if (!(qc->err_mask & ~AC_ERR_DEV))
-               qc->ap->ops->tf_read(qc->ap, arg->tf);
-       arg->err_mask = qc->err_mask;
-       arg->waiting = NULL;
+       qc->ap->ops->tf_read(qc->ap, &qc->tf);
        complete(waiting);
-
-       return 0;
 }
 
 /**
@@ -1125,7 +938,7 @@ ata_exec_internal(struct ata_port *ap, struct ata_device *dev,
        struct ata_queued_cmd *qc;
        DECLARE_COMPLETION(wait);
        unsigned long flags;
-       struct ata_exec_internal_arg arg;
+       unsigned int err_mask;
 
        spin_lock_irqsave(&ap->host_set->lock, flags);
 
@@ -1139,13 +952,12 @@ ata_exec_internal(struct ata_port *ap, struct ata_device *dev,
                qc->nsect = buflen / ATA_SECT_SIZE;
        }
 
-       arg.waiting = &wait;
-       arg.tf = tf;
-       qc->private_data = &arg;
+       qc->private_data = &wait;
        qc->complete_fn = ata_qc_complete_internal;
 
-       if (ata_qc_issue(qc))
-               goto issue_fail;
+       qc->err_mask = ata_qc_issue(qc);
+       if (qc->err_mask)
+               ata_qc_complete(qc);
 
        spin_unlock_irqrestore(&ap->host_set->lock, flags);
 
@@ -1158,8 +970,8 @@ ata_exec_internal(struct ata_port *ap, struct ata_device *dev,
                 * before the caller cleans up, it will result in a
                 * spurious interrupt.  We can live with that.
                 */
-               if (arg.waiting) {
-                       qc->err_mask = AC_ERR_OTHER;
+               if (qc->flags & ATA_QCFLAG_ACTIVE) {
+                       qc->err_mask = AC_ERR_TIMEOUT;
                        ata_qc_complete(qc);
                        printk(KERN_WARNING "ata%u: qc timeout (cmd 0x%x)\n",
                               ap->id, command);
@@ -1168,12 +980,12 @@ ata_exec_internal(struct ata_port *ap, struct ata_device *dev,
                spin_unlock_irqrestore(&ap->host_set->lock, flags);
        }
 
-       return arg.err_mask;
+       *tf = qc->tf;
+       err_mask = qc->err_mask;
 
- issue_fail:
        ata_qc_free(qc);
-       spin_unlock_irqrestore(&ap->host_set->lock, flags);
-       return AC_ERR_OTHER;
+
+       return err_mask;
 }
 
 /**
@@ -1210,73 +1022,78 @@ unsigned int ata_pio_need_iordy(const struct ata_device *adev)
 }
 
 /**
- *     ata_dev_identify - obtain IDENTIFY x DEVICE page
- *     @ap: port on which device we wish to probe resides
- *     @device: device bus address, starting at zero
- *
- *     Following bus reset, we issue the IDENTIFY [PACKET] DEVICE
- *     command, and read back the 512-byte device information page.
- *     The device information page is fed to us via the standard
- *     PIO-IN protocol, but we hand-code it here. (TODO: investigate
- *     using standard PIO-IN paths)
- *
- *     After reading the device information page, we use several
- *     bits of information from it to initialize data structures
- *     that will be used during the lifetime of the ata_device.
- *     Other data from the info page is used to disqualify certain
- *     older ATA devices we do not wish to support.
+ *     ata_dev_read_id - Read ID data from the specified device
+ *     @ap: port on which target device resides
+ *     @dev: target device
+ *     @p_class: pointer to class of the target device (may be changed)
+ *     @post_reset: is this read ID post-reset?
+ *     @p_id: read IDENTIFY page (newly allocated)
+ *
+ *     Read ID data from the specified device.  ATA_CMD_ID_ATA is
+ *     performed on ATA devices and ATA_CMD_ID_ATAPI on ATAPI
+ *     devices.  This function also takes care of EDD signature
+ *     misreporting (to be removed once EDD support is gone) and
+ *     issues ATA_CMD_INIT_DEV_PARAMS for pre-ATA4 drives.
  *
  *     LOCKING:
- *     Inherited from caller.  Some functions called by this function
- *     obtain the host_set lock.
+ *     Kernel thread context (may sleep)
+ *
+ *     RETURNS:
+ *     0 on success, -errno otherwise.
  */
-
-static void ata_dev_identify(struct ata_port *ap, unsigned int device)
+static int ata_dev_read_id(struct ata_port *ap, struct ata_device *dev,
+                          unsigned int *p_class, int post_reset, u16 **p_id)
 {
-       struct ata_device *dev = &ap->device[device];
-       unsigned int major_version;
-       u16 tmp;
-       unsigned long xfer_modes;
+       unsigned int class = *p_class;
        unsigned int using_edd;
        struct ata_taskfile tf;
-       unsigned int err_mask;
+       unsigned int err_mask = 0;
+       u16 *id;
+       const char *reason;
        int rc;
 
-       if (!ata_dev_present(dev)) {
-               DPRINTK("ENTER/EXIT (host %u, dev %u) -- nodev\n",
-                       ap->id, device);
-               return;
-       }
+       DPRINTK("ENTER, host %u, dev %u\n", ap->id, dev->devno);
 
-       if (ap->flags & (ATA_FLAG_SRST | ATA_FLAG_SATA_RESET))
+       if (ap->ops->probe_reset ||
+           ap->flags & (ATA_FLAG_SRST | ATA_FLAG_SATA_RESET))
                using_edd = 0;
        else
                using_edd = 1;
 
-       DPRINTK("ENTER, host %u, dev %u\n", ap->id, device);
-
-       assert (dev->class == ATA_DEV_ATA || dev->class == ATA_DEV_ATAPI ||
-               dev->class == ATA_DEV_NONE);
+       ata_dev_select(ap, dev->devno, 1, 1); /* select device 0/1 */
 
-       ata_dev_select(ap, device, 1, 1); /* select device 0/1 */
+       id = kmalloc(sizeof(id[0]) * ATA_ID_WORDS, GFP_KERNEL);
+       if (id == NULL) {
+               rc = -ENOMEM;
+               reason = "out of memory";
+               goto err_out;
+       }
 
-retry:
-       ata_tf_init(ap, &tf, device);
+ retry:
+       ata_tf_init(ap, &tf, dev->devno);
 
-       if (dev->class == ATA_DEV_ATA) {
+       switch (class) {
+       case ATA_DEV_ATA:
                tf.command = ATA_CMD_ID_ATA;
-               DPRINTK("do ATA identify\n");
-       } else {
+               break;
+       case ATA_DEV_ATAPI:
                tf.command = ATA_CMD_ID_ATAPI;
-               DPRINTK("do ATAPI identify\n");
+               break;
+       default:
+               rc = -ENODEV;
+               reason = "unsupported class";
+               goto err_out;
        }
 
        tf.protocol = ATA_PROT_PIO;
 
        err_mask = ata_exec_internal(ap, dev, &tf, DMA_FROM_DEVICE,
-                                    dev->id, sizeof(dev->id));
+                                    id, sizeof(id[0]) * ATA_ID_WORDS);
 
        if (err_mask) {
+               rc = -EIO;
+               reason = "I/O error";
+
                if (err_mask & ~AC_ERR_DEV)
                        goto err_out;
 
@@ -1291,56 +1108,32 @@ retry:
                 * ATA software reset (SRST, the default) does not appear
                 * to have this problem.
                 */
-               if ((using_edd) && (dev->class == ATA_DEV_ATA)) {
+               if ((using_edd) && (class == ATA_DEV_ATA)) {
                        u8 err = tf.feature;
                        if (err & ATA_ABORTED) {
-                               dev->class = ATA_DEV_ATAPI;
+                               class = ATA_DEV_ATAPI;
                                goto retry;
                        }
                }
                goto err_out;
        }
 
-       swap_buf_le16(dev->id, ATA_ID_WORDS);
+       swap_buf_le16(id, ATA_ID_WORDS);
 
        /* print device capabilities */
        printk(KERN_DEBUG "ata%u: dev %u cfg "
               "49:%04x 82:%04x 83:%04x 84:%04x 85:%04x 86:%04x 87:%04x 88:%04x\n",
-              ap->id, device, dev->id[49],
-              dev->id[82], dev->id[83], dev->id[84],
-              dev->id[85], dev->id[86], dev->id[87],
-              dev->id[88]);
-
-       /*
-        * common ATA, ATAPI feature tests
-        */
+              ap->id, dev->devno,
+              id[49], id[82], id[83], id[84], id[85], id[86], id[87], id[88]);
 
-       /* we require DMA support (bits 8 of word 49) */
-       if (!ata_id_has_dma(dev->id)) {
-               printk(KERN_DEBUG "ata%u: no dma\n", ap->id);
-               goto err_out_nosup;
+       /* sanity check */
+       if ((class == ATA_DEV_ATA) != ata_id_is_ata(id)) {
+               rc = -EINVAL;
+               reason = "device reports illegal type";
+               goto err_out;
        }
 
-       /* quick-n-dirty find max transfer mode; for printk only */
-       xfer_modes = dev->id[ATA_ID_UDMA_MODES];
-       if (!xfer_modes)
-               xfer_modes = (dev->id[ATA_ID_MWDMA_MODES]) << ATA_SHIFT_MWDMA;
-       if (!xfer_modes)
-               xfer_modes = ata_pio_modes(dev);
-
-       ata_dump_id(dev);
-
-       /* ATA-specific feature tests */
-       if (dev->class == ATA_DEV_ATA) {
-               if (!ata_id_is_ata(dev->id))    /* sanity check */
-                       goto err_out_nosup;
-
-               /* get major version */
-               tmp = dev->id[ATA_ID_MAJOR_VER];
-               for (major_version = 14; major_version >= 1; major_version--)
-                       if (tmp & (1 << major_version))
-                               break;
-
+       if (post_reset && class == ATA_DEV_ATA) {
                /*
                 * The exact sequence expected by certain pre-ATA4 drives is:
                 * SRST RESET
@@ -1349,122 +1142,187 @@ retry:
                 * anything else..
                 * Some drives were very specific about that exact sequence.
                 */
-               if (major_version < 4 || (!ata_id_has_lba(dev->id))) {
-                       ata_dev_init_params(ap, dev);
+               if (ata_id_major_version(id) < 4 || !ata_id_has_lba(id)) {
+                       err_mask = ata_dev_init_params(ap, dev);
+                       if (err_mask) {
+                               rc = -EIO;
+                               reason = "INIT_DEV_PARAMS failed";
+                               goto err_out;
+                       }
 
                        /* current CHS translation info (id[53-58]) might be
                         * changed. reread the identify device info.
                         */
-                       ata_dev_reread_id(ap, dev);
+                       post_reset = 0;
+                       goto retry;
                }
+       }
+
+       *p_class = class;
+       *p_id = id;
+       return 0;
+
+ err_out:
+       printk(KERN_WARNING "ata%u: dev %u failed to IDENTIFY (%s)\n",
+              ap->id, dev->devno, reason);
+       kfree(id);
+       return rc;
+}
+
+static inline u8 ata_dev_knobble(const struct ata_port *ap,
+                                struct ata_device *dev)
+{
+       return ((ap->cbl == ATA_CBL_SATA) && (!ata_id_is_sata(dev->id)));
+}
+
+/**
+ *     ata_dev_configure - Configure the specified ATA/ATAPI device
+ *     @ap: Port on which target device resides
+ *     @dev: Target device to configure
+ *     @print_info: Enable device info printout
+ *
+ *     Configure @dev according to @dev->id.  Generic and low-level
+ *     driver specific fixups are also applied.
+ *
+ *     LOCKING:
+ *     Kernel thread context (may sleep)
+ *
+ *     RETURNS:
+ *     0 on success, -errno otherwise
+ */
+static int ata_dev_configure(struct ata_port *ap, struct ata_device *dev,
+                            int print_info)
+{
+       unsigned int xfer_mask;
+       int i, rc;
+
+       if (!ata_dev_present(dev)) {
+               DPRINTK("ENTER/EXIT (host %u, dev %u) -- nodev\n",
+                       ap->id, dev->devno);
+               return 0;
+       }
+
+       DPRINTK("ENTER, host %u, dev %u\n", ap->id, dev->devno);
+
+       /* initialize to-be-configured parameters */
+       dev->flags = 0;
+       dev->max_sectors = 0;
+       dev->cdb_len = 0;
+       dev->n_sectors = 0;
+       dev->cylinders = 0;
+       dev->heads = 0;
+       dev->sectors = 0;
+
+       /*
+        * common ATA, ATAPI feature tests
+        */
+
+       /* we require DMA support (bits 8 of word 49) */
+       if (!ata_id_has_dma(dev->id)) {
+               printk(KERN_DEBUG "ata%u: no dma\n", ap->id);
+               rc = -EINVAL;
+               goto err_out_nosup;
+       }
+
+       /* find max transfer mode; for printk only */
+       xfer_mask = ata_id_xfermask(dev->id);
+
+       ata_dump_id(dev->id);
+
+       /* ATA-specific feature tests */
+       if (dev->class == ATA_DEV_ATA) {
+               dev->n_sectors = ata_id_n_sectors(dev->id);
 
                if (ata_id_has_lba(dev->id)) {
-                       dev->flags |= ATA_DFLAG_LBA;
+                       const char *lba_desc;
 
+                       lba_desc = "LBA";
+                       dev->flags |= ATA_DFLAG_LBA;
                        if (ata_id_has_lba48(dev->id)) {
                                dev->flags |= ATA_DFLAG_LBA48;
-                               dev->n_sectors = ata_id_u64(dev->id, 100);
-                       } else {
-                               dev->n_sectors = ata_id_u32(dev->id, 60);
+                               lba_desc = "LBA48";
                        }
 
                        /* print device info to dmesg */
-                       printk(KERN_INFO "ata%u: dev %u ATA-%d, max %s, %Lu sectors:%s\n",
-                              ap->id, device,
-                              major_version,
-                              ata_mode_string(xfer_modes),
-                              (unsigned long long)dev->n_sectors,
-                              dev->flags & ATA_DFLAG_LBA48 ? " LBA48" : " LBA");
-               } else { 
+                       if (print_info)
+                               printk(KERN_INFO "ata%u: dev %u ATA-%d, "
+                                      "max %s, %Lu sectors: %s\n",
+                                      ap->id, dev->devno,
+                                      ata_id_major_version(dev->id),
+                                      ata_mode_string(xfer_mask),
+                                      (unsigned long long)dev->n_sectors,
+                                      lba_desc);
+               } else {
                        /* CHS */
 
                        /* Default translation */
                        dev->cylinders  = dev->id[1];
                        dev->heads      = dev->id[3];
                        dev->sectors    = dev->id[6];
-                       dev->n_sectors  = dev->cylinders * dev->heads * dev->sectors;
 
                        if (ata_id_current_chs_valid(dev->id)) {
                                /* Current CHS translation is valid. */
                                dev->cylinders = dev->id[54];
                                dev->heads     = dev->id[55];
                                dev->sectors   = dev->id[56];
-                               
-                               dev->n_sectors = ata_id_u32(dev->id, 57);
                        }
 
                        /* print device info to dmesg */
-                       printk(KERN_INFO "ata%u: dev %u ATA-%d, max %s, %Lu sectors: CHS %d/%d/%d\n",
-                              ap->id, device,
-                              major_version,
-                              ata_mode_string(xfer_modes),
-                              (unsigned long long)dev->n_sectors,
-                              (int)dev->cylinders, (int)dev->heads, (int)dev->sectors);
-
+                       if (print_info)
+                               printk(KERN_INFO "ata%u: dev %u ATA-%d, "
+                                      "max %s, %Lu sectors: CHS %u/%u/%u\n",
+                                      ap->id, dev->devno,
+                                      ata_id_major_version(dev->id),
+                                      ata_mode_string(xfer_mask),
+                                      (unsigned long long)dev->n_sectors,
+                                      dev->cylinders, dev->heads, dev->sectors);
                }
 
-               ap->host->max_cmd_len = 16;
+               dev->cdb_len = 16;
        }
 
        /* ATAPI-specific feature tests */
        else if (dev->class == ATA_DEV_ATAPI) {
-               if (ata_id_is_ata(dev->id))             /* sanity check */
-                       goto err_out_nosup;
-
                rc = atapi_cdb_len(dev->id);
                if ((rc < 12) || (rc > ATAPI_CDB_LEN)) {
                        printk(KERN_WARNING "ata%u: unsupported CDB len\n", ap->id);
+                       rc = -EINVAL;
                        goto err_out_nosup;
                }
-               ap->cdb_len = (unsigned int) rc;
-               ap->host->max_cmd_len = (unsigned char) ap->cdb_len;
+               dev->cdb_len = (unsigned int) rc;
 
                /* print device info to dmesg */
-               printk(KERN_INFO "ata%u: dev %u ATAPI, max %s\n",
-                      ap->id, device,
-                      ata_mode_string(xfer_modes));
+               if (print_info)
+                       printk(KERN_INFO "ata%u: dev %u ATAPI, max %s\n",
+                              ap->id, dev->devno, ata_mode_string(xfer_mask));
        }
 
-       DPRINTK("EXIT, drv_stat = 0x%x\n", ata_chk_status(ap));
-       return;
-
-err_out_nosup:
-       printk(KERN_WARNING "ata%u: dev %u not supported, ignoring\n",
-              ap->id, device);
-err_out:
-       dev->class++;   /* converts ATA_DEV_xxx into ATA_DEV_xxx_UNSUP */
-       DPRINTK("EXIT, err\n");
-}
-
-
-static inline u8 ata_dev_knobble(const struct ata_port *ap)
-{
-       return ((ap->cbl == ATA_CBL_SATA) && (!ata_id_is_sata(ap->device->id)));
-}
-
-/**
- *     ata_dev_config - Run device specific handlers and check for
- *                      SATA->PATA bridges
- *     @ap: Bus
- *     @i:  Device
- *
- *     LOCKING:
- */
+       ap->host->max_cmd_len = 0;
+       for (i = 0; i < ATA_MAX_DEVICES; i++)
+               ap->host->max_cmd_len = max_t(unsigned int,
+                                             ap->host->max_cmd_len,
+                                             ap->device[i].cdb_len);
 
-void ata_dev_config(struct ata_port *ap, unsigned int i)
-{
        /* limit bridge transfers to udma5, 200 sectors */
-       if (ata_dev_knobble(ap)) {
-               printk(KERN_INFO "ata%u(%u): applying bridge limits\n",
-                       ap->id, ap->device->devno);
+       if (ata_dev_knobble(ap, dev)) {
+               if (print_info)
+                       printk(KERN_INFO "ata%u(%u): applying bridge limits\n",
+                              ap->id, dev->devno);
                ap->udma_mask &= ATA_UDMA5;
-               ap->host->max_sectors = ATA_MAX_SECTORS;
-               ap->host->hostt->max_sectors = ATA_MAX_SECTORS;
-               ap->device[i].flags |= ATA_DFLAG_LOCK_SECTORS;
+               dev->max_sectors = ATA_MAX_SECTORS;
        }
 
        if (ap->ops->dev_config)
-               ap->ops->dev_config(ap, &ap->device[i]);
+               ap->ops->dev_config(ap, dev);
+
+       DPRINTK("EXIT, drv_stat = 0x%x\n", ata_chk_status(ap));
+       return 0;
+
+err_out_nosup:
+       printk(KERN_WARNING "ata%u: dev %u not supported, ignoring\n",
+              ap->id, dev->devno);
+       DPRINTK("EXIT, err\n");
+       return rc;
 }
 
 /**
@@ -1484,21 +1342,59 @@ void ata_dev_config(struct ata_port *ap, unsigned int i)
 
 static int ata_bus_probe(struct ata_port *ap)
 {
-       unsigned int i, found = 0;
+       unsigned int classes[ATA_MAX_DEVICES];
+       unsigned int i, rc, found = 0;
 
-       ap->ops->phy_reset(ap);
-       if (ap->flags & ATA_FLAG_PORT_DISABLED)
-               goto err_out;
+       ata_port_probe(ap);
+
+       /* reset and determine device classes */
+       for (i = 0; i < ATA_MAX_DEVICES; i++)
+               classes[i] = ATA_DEV_UNKNOWN;
 
+       if (ap->ops->probe_reset) {
+               rc = ap->ops->probe_reset(ap, classes);
+               if (rc) {
+                       printk("ata%u: reset failed (errno=%d)\n", ap->id, rc);
+                       return rc;
+               }
+       } else {
+               ap->ops->phy_reset(ap);
+
+               if (!(ap->flags & ATA_FLAG_PORT_DISABLED))
+                       for (i = 0; i < ATA_MAX_DEVICES; i++)
+                               classes[i] = ap->device[i].class;
+
+               ata_port_probe(ap);
+       }
+
+       for (i = 0; i < ATA_MAX_DEVICES; i++)
+               if (classes[i] == ATA_DEV_UNKNOWN)
+                       classes[i] = ATA_DEV_NONE;
+
+       /* read IDENTIFY page and configure devices */
        for (i = 0; i < ATA_MAX_DEVICES; i++) {
-               ata_dev_identify(ap, i);
-               if (ata_dev_present(&ap->device[i])) {
-                       found = 1;
-                       ata_dev_config(ap,i);
+               struct ata_device *dev = &ap->device[i];
+
+               dev->class = classes[i];
+
+               if (!ata_dev_present(dev))
+                       continue;
+
+               WARN_ON(dev->id != NULL);
+               if (ata_dev_read_id(ap, dev, &dev->class, 1, &dev->id)) {
+                       dev->class = ATA_DEV_NONE;
+                       continue;
+               }
+
+               if (ata_dev_configure(ap, dev, 1)) {
+                       dev->class++;   /* disable device */
+                       continue;
                }
+
+               found = 1;
        }
 
-       if ((!found) || (ap->flags & ATA_FLAG_PORT_DISABLED))
+       if (!found)
                goto err_out_disable;
 
        ata_set_mode(ap);
@@ -1509,7 +1405,6 @@ static int ata_bus_probe(struct ata_port *ap)
 
 err_out_disable:
        ap->ops->port_disable(ap);
-err_out:
        return -1;
 }
 
@@ -1529,6 +1424,41 @@ void ata_port_probe(struct ata_port *ap)
        ap->flags &= ~ATA_FLAG_PORT_DISABLED;
 }
 
+/**
+ *     sata_print_link_status - Print SATA link status
+ *     @ap: SATA port to printk link status about
+ *
+ *     This function prints link speed and status of a SATA link.
+ *
+ *     LOCKING:
+ *     None.
+ */
+static void sata_print_link_status(struct ata_port *ap)
+{
+       u32 sstatus, tmp;
+       const char *speed;
+
+       if (!ap->ops->scr_read)
+               return;
+
+       sstatus = scr_read(ap, SCR_STATUS);
+
+       if (sata_dev_present(ap)) {
+               tmp = (sstatus >> 4) & 0xf;
+               if (tmp & (1 << 0))
+                       speed = "1.5";
+               else if (tmp & (1 << 1))
+                       speed = "3.0";
+               else
+                       speed = "<unknown>";
+               printk(KERN_INFO "ata%u: SATA link up %s Gbps (SStatus %X)\n",
+                      ap->id, speed, sstatus);
+       } else {
+               printk(KERN_INFO "ata%u: SATA link down (SStatus %X)\n",
+                      ap->id, sstatus);
+       }
+}
+
 /**
  *     __sata_phy_reset - Wake/reset a low-level SATA PHY
  *     @ap: SATA port associated with target SATA PHY.
@@ -1563,27 +1493,14 @@ void __sata_phy_reset(struct ata_port *ap)
                        break;
        } while (time_before(jiffies, timeout));
 
+       /* print link status */
+       sata_print_link_status(ap);
+
        /* TODO: phy layer with polling, timeouts, etc. */
-       sstatus = scr_read(ap, SCR_STATUS);
-       if (sata_dev_present(ap)) {
-               const char *speed;
-               u32 tmp;
-
-               tmp = (sstatus >> 4) & 0xf;
-               if (tmp & (1 << 0))
-                       speed = "1.5";
-               else if (tmp & (1 << 1))
-                       speed = "3.0";
-               else
-                       speed = "<unknown>";
-               printk(KERN_INFO "ata%u: SATA link up %s Gbps (SStatus %X)\n",
-                      ap->id, speed, sstatus);
+       if (sata_dev_present(ap))
                ata_port_probe(ap);
-       } else {
-               printk(KERN_INFO "ata%u: SATA link down (SStatus %X)\n",
-                      ap->id, sstatus);
+       else
                ata_port_disable(ap);
-       }
 
        if (ap->flags & ATA_FLAG_PORT_DISABLED)
                return;
@@ -1756,9 +1673,9 @@ int ata_timing_compute(struct ata_device *adev, unsigned short speed,
        ata_timing_quantize(t, t, T, UT);
 
        /*
-        * Even in DMA/UDMA modes we still use PIO access for IDENTIFY, S.M.A.R.T
-        * and some other commands. We have to ensure that the DMA cycle timing is
-        * slower/equal than the fastest PIO timing.
+        * Even in DMA/UDMA modes we still use PIO access for IDENTIFY,
+        * S.M.A.R.T * and some other commands. We have to ensure that the
+        * DMA cycle timing is slower/equal than the fastest PIO timing.
         */
 
        if (speed > XFER_PIO_4) {
@@ -1767,7 +1684,7 @@ int ata_timing_compute(struct ata_device *adev, unsigned short speed,
        }
 
        /*
-        * Lenghten active & recovery time so that cycle time is correct.
+        * Lengthen active & recovery time so that cycle time is correct.
         */
 
        if (t->act8b + t->rec8b < t->cyc8b) {
@@ -1783,31 +1700,8 @@ int ata_timing_compute(struct ata_device *adev, unsigned short speed,
        return 0;
 }
 
-static const struct {
-       unsigned int shift;
-       u8 base;
-} xfer_mode_classes[] = {
-       { ATA_SHIFT_UDMA,       XFER_UDMA_0 },
-       { ATA_SHIFT_MWDMA,      XFER_MW_DMA_0 },
-       { ATA_SHIFT_PIO,        XFER_PIO_0 },
-};
-
-static u8 base_from_shift(unsigned int shift)
-{
-       int i;
-
-       for (i = 0; i < ARRAY_SIZE(xfer_mode_classes); i++)
-               if (xfer_mode_classes[i].shift == shift)
-                       return xfer_mode_classes[i].base;
-
-       return 0xff;
-}
-
 static void ata_dev_set_mode(struct ata_port *ap, struct ata_device *dev)
 {
-       int ofs, idx;
-       u8 base;
-
        if (!ata_dev_present(dev) || (ap->flags & ATA_FLAG_PORT_DISABLED))
                return;
 
@@ -1816,65 +1710,58 @@ static void ata_dev_set_mode(struct ata_port *ap, struct ata_device *dev)
 
        ata_dev_set_xfermode(ap, dev);
 
-       base = base_from_shift(dev->xfer_shift);
-       ofs = dev->xfer_mode - base;
-       idx = ofs + dev->xfer_shift;
-       WARN_ON(idx >= ARRAY_SIZE(xfer_mode_str));
+       if (ata_dev_revalidate(ap, dev, 0)) {
+               printk(KERN_ERR "ata%u: failed to revalidate after set "
+                      "xfermode, disabled\n", ap->id);
+               ata_port_disable(ap);
+       }
 
-       DPRINTK("idx=%d xfer_shift=%u, xfer_mode=0x%x, base=0x%x, offset=%d\n",
-               idx, dev->xfer_shift, (int)dev->xfer_mode, (int)base, ofs);
+       DPRINTK("xfer_shift=%u, xfer_mode=0x%x\n",
+               dev->xfer_shift, (int)dev->xfer_mode);
 
        printk(KERN_INFO "ata%u: dev %u configured for %s\n",
-               ap->id, dev->devno, xfer_mode_str[idx]);
+              ap->id, dev->devno,
+              ata_mode_string(ata_xfer_mode2mask(dev->xfer_mode)));
 }
 
 static int ata_host_set_pio(struct ata_port *ap)
 {
-       unsigned int mask;
-       int x, i;
-       u8 base, xfer_mode;
-
-       mask = ata_get_mode_mask(ap, ATA_SHIFT_PIO);
-       x = fgb(mask);
-       if (x < 0) {
-               printk(KERN_WARNING "ata%u: no PIO support\n", ap->id);
-               return -1;
-       }
-
-       base = base_from_shift(ATA_SHIFT_PIO);
-       xfer_mode = base + x;
-
-       DPRINTK("base 0x%x xfer_mode 0x%x mask 0x%x x %d\n",
-               (int)base, (int)xfer_mode, mask, x);
+       int i;
 
        for (i = 0; i < ATA_MAX_DEVICES; i++) {
                struct ata_device *dev = &ap->device[i];
-               if (ata_dev_present(dev)) {
-                       dev->pio_mode = xfer_mode;
-                       dev->xfer_mode = xfer_mode;
-                       dev->xfer_shift = ATA_SHIFT_PIO;
-                       if (ap->ops->set_piomode)
-                               ap->ops->set_piomode(ap, dev);
+
+               if (!ata_dev_present(dev))
+                       continue;
+
+               if (!dev->pio_mode) {
+                       printk(KERN_WARNING "ata%u: no PIO support\n", ap->id);
+                       return -1;
                }
+
+               dev->xfer_mode = dev->pio_mode;
+               dev->xfer_shift = ATA_SHIFT_PIO;
+               if (ap->ops->set_piomode)
+                       ap->ops->set_piomode(ap, dev);
        }
 
        return 0;
 }
 
-static void ata_host_set_dma(struct ata_port *ap, u8 xfer_mode,
-                           unsigned int xfer_shift)
+static void ata_host_set_dma(struct ata_port *ap)
 {
        int i;
 
        for (i = 0; i < ATA_MAX_DEVICES; i++) {
                struct ata_device *dev = &ap->device[i];
-               if (ata_dev_present(dev)) {
-                       dev->dma_mode = xfer_mode;
-                       dev->xfer_mode = xfer_mode;
-                       dev->xfer_shift = xfer_shift;
-                       if (ap->ops->set_dmamode)
-                               ap->ops->set_dmamode(ap, dev);
-               }
+
+               if (!ata_dev_present(dev) || !dev->dma_mode)
+                       continue;
+
+               dev->xfer_mode = dev->dma_mode;
+               dev->xfer_shift = ata_xfer_mode2shift(dev->dma_mode);
+               if (ap->ops->set_dmamode)
+                       ap->ops->set_dmamode(ap, dev);
        }
 }
 
@@ -1886,32 +1773,37 @@ static void ata_host_set_dma(struct ata_port *ap, u8 xfer_mode,
  *
  *     LOCKING:
  *     PCI/etc. bus probe sem.
- *
  */
 static void ata_set_mode(struct ata_port *ap)
 {
-       unsigned int xfer_shift;
-       u8 xfer_mode;
-       int rc;
+       int i, rc;
 
-       /* step 1: always set host PIO timings */
-       rc = ata_host_set_pio(ap);
-       if (rc)
-               goto err_out;
+       /* step 1: calculate xfer_mask */
+       for (i = 0; i < ATA_MAX_DEVICES; i++) {
+               struct ata_device *dev = &ap->device[i];
+               unsigned int xfer_mask;
+
+               if (!ata_dev_present(dev))
+                       continue;
 
-       /* step 2: choose the best data xfer mode */
-       xfer_mode = xfer_shift = 0;
-       rc = ata_choose_xfer_mode(ap, &xfer_mode, &xfer_shift);
+               xfer_mask = ata_dev_xfermask(ap, dev);
+
+               dev->pio_mode = ata_xfer_mask2mode(xfer_mask & ATA_MASK_PIO);
+               dev->dma_mode = ata_xfer_mask2mode(xfer_mask & (ATA_MASK_MWDMA |
+                                                               ATA_MASK_UDMA));
+       }
+
+       /* step 2: always set host PIO timings */
+       rc = ata_host_set_pio(ap);
        if (rc)
                goto err_out;
 
-       /* step 3: if that xfer mode isn't PIO, set host DMA timings */
-       if (xfer_shift != ATA_SHIFT_PIO)
-               ata_host_set_dma(ap, xfer_mode, xfer_shift);
+       /* step 3: set host DMA timings */
+       ata_host_set_dma(ap);
 
        /* step 4: update devices' xfer mode */
-       ata_dev_set_mode(ap, &ap->device[0]);
-       ata_dev_set_mode(ap, &ap->device[1]);
+       for (i = 0; i < ATA_MAX_DEVICES; i++)
+               ata_dev_set_mode(ap, &ap->device[i]);
 
        if (ap->flags & ATA_FLAG_PORT_DISABLED)
                return;
@@ -1925,6 +1817,26 @@ err_out:
        ata_port_disable(ap);
 }
 
+/**
+ *     ata_tf_to_host - issue ATA taskfile to host controller
+ *     @ap: port to which command is being issued
+ *     @tf: ATA taskfile register set
+ *
+ *     Issues ATA taskfile register set to ATA host controller,
+ *     with proper synchronization with interrupt handler and
+ *     other threads.
+ *
+ *     LOCKING:
+ *     spin_lock_irqsave(host_set lock)
+ */
+
+static inline void ata_tf_to_host(struct ata_port *ap,
+                                 const struct ata_taskfile *tf)
+{
+       ap->ops->tf_load(ap, tf);
+       ap->ops->exec_command(ap, tf);
+}
+
 /**
  *     ata_busy_sleep - sleep until BSY clears, or timeout
  *     @ap: port containing status register to be polled
@@ -1935,12 +1847,10 @@ err_out:
  *     or a timeout occurs.
  *
  *     LOCKING: None.
- *
  */
 
-static unsigned int ata_busy_sleep (struct ata_port *ap,
-                                   unsigned long tmout_pat,
-                                   unsigned long tmout)
+unsigned int ata_busy_sleep (struct ata_port *ap,
+                            unsigned long tmout_pat, unsigned long tmout)
 {
        unsigned long timer_start, timeout;
        u8 status;
@@ -2090,117 +2000,552 @@ static unsigned int ata_bus_softreset(struct ata_port *ap,
         */
        msleep(150);
 
-       ata_bus_post_reset(ap, devmask);
+       ata_bus_post_reset(ap, devmask);
+
+       return 0;
+}
+
+/**
+ *     ata_bus_reset - reset host port and associated ATA channel
+ *     @ap: port to reset
+ *
+ *     This is typically the first time we actually start issuing
+ *     commands to the ATA channel.  We wait for BSY to clear, then
+ *     issue EXECUTE DEVICE DIAGNOSTIC command, polling for its
+ *     result.  Determine what devices, if any, are on the channel
+ *     by looking at the device 0/1 error register.  Look at the signature
+ *     stored in each device's taskfile registers, to determine if
+ *     the device is ATA or ATAPI.
+ *
+ *     LOCKING:
+ *     PCI/etc. bus probe sem.
+ *     Obtains host_set lock.
+ *
+ *     SIDE EFFECTS:
+ *     Sets ATA_FLAG_PORT_DISABLED if bus reset fails.
+ */
+
+void ata_bus_reset(struct ata_port *ap)
+{
+       struct ata_ioports *ioaddr = &ap->ioaddr;
+       unsigned int slave_possible = ap->flags & ATA_FLAG_SLAVE_POSS;
+       u8 err;
+       unsigned int dev0, dev1 = 0, rc = 0, devmask = 0;
+
+       DPRINTK("ENTER, host %u, port %u\n", ap->id, ap->port_no);
+
+       /* determine if device 0/1 are present */
+       if (ap->flags & ATA_FLAG_SATA_RESET)
+               dev0 = 1;
+       else {
+               dev0 = ata_devchk(ap, 0);
+               if (slave_possible)
+                       dev1 = ata_devchk(ap, 1);
+       }
+
+       if (dev0)
+               devmask |= (1 << 0);
+       if (dev1)
+               devmask |= (1 << 1);
+
+       /* select device 0 again */
+       ap->ops->dev_select(ap, 0);
+
+       /* issue bus reset */
+       if (ap->flags & ATA_FLAG_SRST)
+               rc = ata_bus_softreset(ap, devmask);
+       else if ((ap->flags & ATA_FLAG_SATA_RESET) == 0) {
+               /* set up device control */
+               if (ap->flags & ATA_FLAG_MMIO)
+                       writeb(ap->ctl, (void __iomem *) ioaddr->ctl_addr);
+               else
+                       outb(ap->ctl, ioaddr->ctl_addr);
+               rc = ata_bus_edd(ap);
+       }
+
+       if (rc)
+               goto err_out;
+
+       /*
+        * determine by signature whether we have ATA or ATAPI devices
+        */
+       ap->device[0].class = ata_dev_try_classify(ap, 0, &err);
+       if ((slave_possible) && (err != 0x81))
+               ap->device[1].class = ata_dev_try_classify(ap, 1, &err);
+
+       /* re-enable interrupts */
+       if (ap->ioaddr.ctl_addr)        /* FIXME: hack. create a hook instead */
+               ata_irq_on(ap);
+
+       /* is double-select really necessary? */
+       if (ap->device[1].class != ATA_DEV_NONE)
+               ap->ops->dev_select(ap, 1);
+       if (ap->device[0].class != ATA_DEV_NONE)
+               ap->ops->dev_select(ap, 0);
+
+       /* if no devices were detected, disable this port */
+       if ((ap->device[0].class == ATA_DEV_NONE) &&
+           (ap->device[1].class == ATA_DEV_NONE))
+               goto err_out;
+
+       if (ap->flags & (ATA_FLAG_SATA_RESET | ATA_FLAG_SRST)) {
+               /* set up device control for ATA_FLAG_SATA_RESET */
+               if (ap->flags & ATA_FLAG_MMIO)
+                       writeb(ap->ctl, (void __iomem *) ioaddr->ctl_addr);
+               else
+                       outb(ap->ctl, ioaddr->ctl_addr);
+       }
+
+       DPRINTK("EXIT\n");
+       return;
+
+err_out:
+       printk(KERN_ERR "ata%u: disabling port\n", ap->id);
+       ap->ops->port_disable(ap);
+
+       DPRINTK("EXIT\n");
+}
+
+static int sata_phy_resume(struct ata_port *ap)
+{
+       unsigned long timeout = jiffies + (HZ * 5);
+       u32 sstatus;
+
+       scr_write_flush(ap, SCR_CONTROL, 0x300);
+
+       /* Wait for phy to become ready, if necessary. */
+       do {
+               msleep(200);
+               sstatus = scr_read(ap, SCR_STATUS);
+               if ((sstatus & 0xf) != 1)
+                       return 0;
+       } while (time_before(jiffies, timeout));
+
+       return -1;
+}
+
+/**
+ *     ata_std_probeinit - initialize probing
+ *     @ap: port to be probed
+ *
+ *     @ap is about to be probed.  Initialize it.  This function is
+ *     to be used as standard callback for ata_drive_probe_reset().
+ *
+ *     NOTE!!! Do not use this function as probeinit if a low level
+ *     driver implements only hardreset.  Just pass NULL as probeinit
+ *     in that case.  Using this function is probably okay but doing
+ *     so makes reset sequence different from the original
+ *     ->phy_reset implementation and Jeff nervous.  :-P
+ */
+extern void ata_std_probeinit(struct ata_port *ap)
+{
+       if (ap->flags & ATA_FLAG_SATA && ap->ops->scr_read) {
+               sata_phy_resume(ap);
+               if (sata_dev_present(ap))
+                       ata_busy_sleep(ap, ATA_TMOUT_BOOT_QUICK, ATA_TMOUT_BOOT);
+       }
+}
+
+/**
+ *     ata_std_softreset - reset host port via ATA SRST
+ *     @ap: port to reset
+ *     @verbose: fail verbosely
+ *     @classes: resulting classes of attached devices
+ *
+ *     Reset host port using ATA SRST.  This function is to be used
+ *     as standard callback for ata_drive_*_reset() functions.
+ *
+ *     LOCKING:
+ *     Kernel thread context (may sleep)
+ *
+ *     RETURNS:
+ *     0 on success, -errno otherwise.
+ */
+int ata_std_softreset(struct ata_port *ap, int verbose, unsigned int *classes)
+{
+       unsigned int slave_possible = ap->flags & ATA_FLAG_SLAVE_POSS;
+       unsigned int devmask = 0, err_mask;
+       u8 err;
+
+       DPRINTK("ENTER\n");
+
+       if (ap->ops->scr_read && !sata_dev_present(ap)) {
+               classes[0] = ATA_DEV_NONE;
+               goto out;
+       }
+
+       /* determine if device 0/1 are present */
+       if (ata_devchk(ap, 0))
+               devmask |= (1 << 0);
+       if (slave_possible && ata_devchk(ap, 1))
+               devmask |= (1 << 1);
+
+       /* select device 0 again */
+       ap->ops->dev_select(ap, 0);
+
+       /* issue bus reset */
+       DPRINTK("about to softreset, devmask=%x\n", devmask);
+       err_mask = ata_bus_softreset(ap, devmask);
+       if (err_mask) {
+               if (verbose)
+                       printk(KERN_ERR "ata%u: SRST failed (err_mask=0x%x)\n",
+                              ap->id, err_mask);
+               else
+                       DPRINTK("EXIT, softreset failed (err_mask=0x%x)\n",
+                               err_mask);
+               return -EIO;
+       }
+
+       /* determine by signature whether we have ATA or ATAPI devices */
+       classes[0] = ata_dev_try_classify(ap, 0, &err);
+       if (slave_possible && err != 0x81)
+               classes[1] = ata_dev_try_classify(ap, 1, &err);
+
+ out:
+       DPRINTK("EXIT, classes[0]=%u [1]=%u\n", classes[0], classes[1]);
+       return 0;
+}
+
+/**
+ *     sata_std_hardreset - reset host port via SATA phy reset
+ *     @ap: port to reset
+ *     @verbose: fail verbosely
+ *     @class: resulting class of attached device
+ *
+ *     SATA phy-reset host port using DET bits of SControl register.
+ *     This function is to be used as standard callback for
+ *     ata_drive_*_reset().
+ *
+ *     LOCKING:
+ *     Kernel thread context (may sleep)
+ *
+ *     RETURNS:
+ *     0 on success, -errno otherwise.
+ */
+int sata_std_hardreset(struct ata_port *ap, int verbose, unsigned int *class)
+{
+       DPRINTK("ENTER\n");
+
+       /* Issue phy wake/reset */
+       scr_write_flush(ap, SCR_CONTROL, 0x301);
+
+       /*
+        * Couldn't find anything in SATA I/II specs, but AHCI-1.1
+        * 10.4.2 says at least 1 ms.
+        */
+       msleep(1);
+
+       /* Bring phy back */
+       sata_phy_resume(ap);
+
+       /* TODO: phy layer with polling, timeouts, etc. */
+       if (!sata_dev_present(ap)) {
+               *class = ATA_DEV_NONE;
+               DPRINTK("EXIT, link offline\n");
+               return 0;
+       }
+
+       if (ata_busy_sleep(ap, ATA_TMOUT_BOOT_QUICK, ATA_TMOUT_BOOT)) {
+               if (verbose)
+                       printk(KERN_ERR "ata%u: COMRESET failed "
+                              "(device not ready)\n", ap->id);
+               else
+                       DPRINTK("EXIT, device not ready\n");
+               return -EIO;
+       }
+
+       ap->ops->dev_select(ap, 0);     /* probably unnecessary */
+
+       *class = ata_dev_try_classify(ap, 0, NULL);
+
+       DPRINTK("EXIT, class=%u\n", *class);
+       return 0;
+}
+
+/**
+ *     ata_std_postreset - standard postreset callback
+ *     @ap: the target ata_port
+ *     @classes: classes of attached devices
+ *
+ *     This function is invoked after a successful reset.  Note that
+ *     the device might have been reset more than once using
+ *     different reset methods before postreset is invoked.
+ *
+ *     This function is to be used as standard callback for
+ *     ata_drive_*_reset().
+ *
+ *     LOCKING:
+ *     Kernel thread context (may sleep)
+ */
+void ata_std_postreset(struct ata_port *ap, unsigned int *classes)
+{
+       DPRINTK("ENTER\n");
+
+       /* set cable type if it isn't already set */
+       if (ap->cbl == ATA_CBL_NONE && ap->flags & ATA_FLAG_SATA)
+               ap->cbl = ATA_CBL_SATA;
+
+       /* print link status */
+       if (ap->cbl == ATA_CBL_SATA)
+               sata_print_link_status(ap);
+
+       /* re-enable interrupts */
+       if (ap->ioaddr.ctl_addr)        /* FIXME: hack. create a hook instead */
+               ata_irq_on(ap);
+
+       /* is double-select really necessary? */
+       if (classes[0] != ATA_DEV_NONE)
+               ap->ops->dev_select(ap, 1);
+       if (classes[1] != ATA_DEV_NONE)
+               ap->ops->dev_select(ap, 0);
+
+       /* bail out if no device is present */
+       if (classes[0] == ATA_DEV_NONE && classes[1] == ATA_DEV_NONE) {
+               DPRINTK("EXIT, no device\n");
+               return;
+       }
+
+       /* set up device control */
+       if (ap->ioaddr.ctl_addr) {
+               if (ap->flags & ATA_FLAG_MMIO)
+                       writeb(ap->ctl, (void __iomem *) ap->ioaddr.ctl_addr);
+               else
+                       outb(ap->ctl, ap->ioaddr.ctl_addr);
+       }
+
+       DPRINTK("EXIT\n");
+}
+
+/**
+ *     ata_std_probe_reset - standard probe reset method
+ *     @ap: prot to perform probe-reset
+ *     @classes: resulting classes of attached devices
+ *
+ *     The stock off-the-shelf ->probe_reset method.
+ *
+ *     LOCKING:
+ *     Kernel thread context (may sleep)
+ *
+ *     RETURNS:
+ *     0 on success, -errno otherwise.
+ */
+int ata_std_probe_reset(struct ata_port *ap, unsigned int *classes)
+{
+       ata_reset_fn_t hardreset;
+
+       hardreset = NULL;
+       if (ap->flags & ATA_FLAG_SATA && ap->ops->scr_read)
+               hardreset = sata_std_hardreset;
+
+       return ata_drive_probe_reset(ap, ata_std_probeinit,
+                                    ata_std_softreset, hardreset,
+                                    ata_std_postreset, classes);
+}
+
+static int do_probe_reset(struct ata_port *ap, ata_reset_fn_t reset,
+                         ata_postreset_fn_t postreset,
+                         unsigned int *classes)
+{
+       int i, rc;
+
+       for (i = 0; i < ATA_MAX_DEVICES; i++)
+               classes[i] = ATA_DEV_UNKNOWN;
+
+       rc = reset(ap, 0, classes);
+       if (rc)
+               return rc;
+
+       /* If any class isn't ATA_DEV_UNKNOWN, consider classification
+        * is complete and convert all ATA_DEV_UNKNOWN to
+        * ATA_DEV_NONE.
+        */
+       for (i = 0; i < ATA_MAX_DEVICES; i++)
+               if (classes[i] != ATA_DEV_UNKNOWN)
+                       break;
+
+       if (i < ATA_MAX_DEVICES)
+               for (i = 0; i < ATA_MAX_DEVICES; i++)
+                       if (classes[i] == ATA_DEV_UNKNOWN)
+                               classes[i] = ATA_DEV_NONE;
+
+       if (postreset)
+               postreset(ap, classes);
+
+       return classes[0] != ATA_DEV_UNKNOWN ? 0 : -ENODEV;
+}
+
+/**
+ *     ata_drive_probe_reset - Perform probe reset with given methods
+ *     @ap: port to reset
+ *     @probeinit: probeinit method (can be NULL)
+ *     @softreset: softreset method (can be NULL)
+ *     @hardreset: hardreset method (can be NULL)
+ *     @postreset: postreset method (can be NULL)
+ *     @classes: resulting classes of attached devices
+ *
+ *     Reset the specified port and classify attached devices using
+ *     given methods.  This function prefers softreset but tries all
+ *     possible reset sequences to reset and classify devices.  This
+ *     function is intended to be used for constructing ->probe_reset
+ *     callback by low level drivers.
+ *
+ *     Reset methods should follow the following rules.
+ *
+ *     - Return 0 on sucess, -errno on failure.
+ *     - If classification is supported, fill classes[] with
+ *       recognized class codes.
+ *     - If classification is not supported, leave classes[] alone.
+ *     - If verbose is non-zero, print error message on failure;
+ *       otherwise, shut up.
+ *
+ *     LOCKING:
+ *     Kernel thread context (may sleep)
+ *
+ *     RETURNS:
+ *     0 on success, -EINVAL if no reset method is avaliable, -ENODEV
+ *     if classification fails, and any error code from reset
+ *     methods.
+ */
+int ata_drive_probe_reset(struct ata_port *ap, ata_probeinit_fn_t probeinit,
+                         ata_reset_fn_t softreset, ata_reset_fn_t hardreset,
+                         ata_postreset_fn_t postreset, unsigned int *classes)
+{
+       int rc = -EINVAL;
+
+       if (probeinit)
+               probeinit(ap);
+
+       if (softreset) {
+               rc = do_probe_reset(ap, softreset, postreset, classes);
+               if (rc == 0)
+                       return 0;
+       }
+
+       if (!hardreset)
+               return rc;
+
+       rc = do_probe_reset(ap, hardreset, postreset, classes);
+       if (rc == 0 || rc != -ENODEV)
+               return rc;
 
-       return 0;
+       if (softreset)
+               rc = do_probe_reset(ap, softreset, postreset, classes);
+
+       return rc;
 }
 
 /**
- *     ata_bus_reset - reset host port and associated ATA channel
- *     @ap: port to reset
+ *     ata_dev_same_device - Determine whether new ID matches configured device
+ *     @ap: port on which the device to compare against resides
+ *     @dev: device to compare against
+ *     @new_class: class of the new device
+ *     @new_id: IDENTIFY page of the new device
  *
- *     This is typically the first time we actually start issuing
- *     commands to the ATA channel.  We wait for BSY to clear, then
- *     issue EXECUTE DEVICE DIAGNOSTIC command, polling for its
- *     result.  Determine what devices, if any, are on the channel
- *     by looking at the device 0/1 error register.  Look at the signature
- *     stored in each device's taskfile registers, to determine if
- *     the device is ATA or ATAPI.
+ *     Compare @new_class and @new_id against @dev and determine
+ *     whether @dev is the device indicated by @new_class and
+ *     @new_id.
  *
  *     LOCKING:
- *     PCI/etc. bus probe sem.
- *     Obtains host_set lock.
+ *     None.
  *
- *     SIDE EFFECTS:
- *     Sets ATA_FLAG_PORT_DISABLED if bus reset fails.
+ *     RETURNS:
+ *     1 if @dev matches @new_class and @new_id, 0 otherwise.
  */
-
-void ata_bus_reset(struct ata_port *ap)
+static int ata_dev_same_device(struct ata_port *ap, struct ata_device *dev,
+                              unsigned int new_class, const u16 *new_id)
 {
-       struct ata_ioports *ioaddr = &ap->ioaddr;
-       unsigned int slave_possible = ap->flags & ATA_FLAG_SLAVE_POSS;
-       u8 err;
-       unsigned int dev0, dev1 = 0, rc = 0, devmask = 0;
-
-       DPRINTK("ENTER, host %u, port %u\n", ap->id, ap->port_no);
+       const u16 *old_id = dev->id;
+       unsigned char model[2][41], serial[2][21];
+       u64 new_n_sectors;
 
-       /* determine if device 0/1 are present */
-       if (ap->flags & ATA_FLAG_SATA_RESET)
-               dev0 = 1;
-       else {
-               dev0 = ata_devchk(ap, 0);
-               if (slave_possible)
-                       dev1 = ata_devchk(ap, 1);
+       if (dev->class != new_class) {
+               printk(KERN_INFO
+                      "ata%u: dev %u class mismatch %d != %d\n",
+                      ap->id, dev->devno, dev->class, new_class);
+               return 0;
        }
 
-       if (dev0)
-               devmask |= (1 << 0);
-       if (dev1)
-               devmask |= (1 << 1);
+       ata_id_c_string(old_id, model[0], ATA_ID_PROD_OFS, sizeof(model[0]));
+       ata_id_c_string(new_id, model[1], ATA_ID_PROD_OFS, sizeof(model[1]));
+       ata_id_c_string(old_id, serial[0], ATA_ID_SERNO_OFS, sizeof(serial[0]));
+       ata_id_c_string(new_id, serial[1], ATA_ID_SERNO_OFS, sizeof(serial[1]));
+       new_n_sectors = ata_id_n_sectors(new_id);
 
-       /* select device 0 again */
-       ap->ops->dev_select(ap, 0);
+       if (strcmp(model[0], model[1])) {
+               printk(KERN_INFO
+                      "ata%u: dev %u model number mismatch '%s' != '%s'\n",
+                      ap->id, dev->devno, model[0], model[1]);
+               return 0;
+       }
 
-       /* issue bus reset */
-       if (ap->flags & ATA_FLAG_SRST)
-               rc = ata_bus_softreset(ap, devmask);
-       else if ((ap->flags & ATA_FLAG_SATA_RESET) == 0) {
-               /* set up device control */
-               if (ap->flags & ATA_FLAG_MMIO)
-                       writeb(ap->ctl, (void __iomem *) ioaddr->ctl_addr);
-               else
-                       outb(ap->ctl, ioaddr->ctl_addr);
-               rc = ata_bus_edd(ap);
+       if (strcmp(serial[0], serial[1])) {
+               printk(KERN_INFO
+                      "ata%u: dev %u serial number mismatch '%s' != '%s'\n",
+                      ap->id, dev->devno, serial[0], serial[1]);
+               return 0;
        }
 
-       if (rc)
-               goto err_out;
+       if (dev->class == ATA_DEV_ATA && dev->n_sectors != new_n_sectors) {
+               printk(KERN_INFO
+                      "ata%u: dev %u n_sectors mismatch %llu != %llu\n",
+                      ap->id, dev->devno, (unsigned long long)dev->n_sectors,
+                      (unsigned long long)new_n_sectors);
+               return 0;
+       }
 
-       /*
-        * determine by signature whether we have ATA or ATAPI devices
-        */
-       err = ata_dev_try_classify(ap, 0);
-       if ((slave_possible) && (err != 0x81))
-               ata_dev_try_classify(ap, 1);
+       return 1;
+}
 
-       /* re-enable interrupts */
-       if (ap->ioaddr.ctl_addr)        /* FIXME: hack. create a hook instead */
-               ata_irq_on(ap);
+/**
+ *     ata_dev_revalidate - Revalidate ATA device
+ *     @ap: port on which the device to revalidate resides
+ *     @dev: device to revalidate
+ *     @post_reset: is this revalidation after reset?
+ *
+ *     Re-read IDENTIFY page and make sure @dev is still attached to
+ *     the port.
+ *
+ *     LOCKING:
+ *     Kernel thread context (may sleep)
+ *
+ *     RETURNS:
+ *     0 on success, negative errno otherwise
+ */
+int ata_dev_revalidate(struct ata_port *ap, struct ata_device *dev,
+                      int post_reset)
+{
+       unsigned int class;
+       u16 *id;
+       int rc;
 
-       /* is double-select really necessary? */
-       if (ap->device[1].class != ATA_DEV_NONE)
-               ap->ops->dev_select(ap, 1);
-       if (ap->device[0].class != ATA_DEV_NONE)
-               ap->ops->dev_select(ap, 0);
+       if (!ata_dev_present(dev))
+               return -ENODEV;
 
-       /* if no devices were detected, disable this port */
-       if ((ap->device[0].class == ATA_DEV_NONE) &&
-           (ap->device[1].class == ATA_DEV_NONE))
-               goto err_out;
+       class = dev->class;
+       id = NULL;
 
-       if (ap->flags & (ATA_FLAG_SATA_RESET | ATA_FLAG_SRST)) {
-               /* set up device control for ATA_FLAG_SATA_RESET */
-               if (ap->flags & ATA_FLAG_MMIO)
-                       writeb(ap->ctl, (void __iomem *) ioaddr->ctl_addr);
-               else
-                       outb(ap->ctl, ioaddr->ctl_addr);
-       }
+       /* allocate & read ID data */
+       rc = ata_dev_read_id(ap, dev, &class, post_reset, &id);
+       if (rc)
+               goto fail;
 
-       DPRINTK("EXIT\n");
-       return;
+       /* is the device still there? */
+       if (!ata_dev_same_device(ap, dev, class, id)) {
+               rc = -ENODEV;
+               goto fail;
+       }
 
-err_out:
-       printk(KERN_ERR "ata%u: disabling port\n", ap->id);
-       ap->ops->port_disable(ap);
+       kfree(dev->id);
+       dev->id = id;
 
-       DPRINTK("EXIT\n");
-}
+       /* configure device according to the new ID */
+       return ata_dev_configure(ap, dev, 0);
 
-static void ata_pr_blacklisted(const struct ata_port *ap,
-                              const struct ata_device *dev)
-{
-       printk(KERN_WARNING "ata%u: dev %u is on DMA blacklist, disabling DMA\n",
-               ap->id, dev->devno);
+ fail:
+       printk(KERN_ERR "ata%u: dev %u revalidation failed (errno=%d)\n",
+              ap->id, dev->devno, rc);
+       kfree(id);
+       return rc;
 }
 
 static const char * const ata_dma_blacklist [] = {
@@ -2237,151 +2582,57 @@ static const char * const ata_dma_blacklist [] = {
 
 static int ata_dma_blacklisted(const struct ata_device *dev)
 {
-       unsigned char model_num[40];
-       char *s;
-       unsigned int len;
+       unsigned char model_num[41];
        int i;
 
-       ata_dev_id_string(dev->id, model_num, ATA_ID_PROD_OFS,
-                         sizeof(model_num));
-       s = &model_num[0];
-       len = strnlen(s, sizeof(model_num));
-
-       /* ATAPI specifies that empty space is blank-filled; remove blanks */
-       while ((len > 0) && (s[len - 1] == ' ')) {
-               len--;
-               s[len] = 0;
-       }
+       ata_id_c_string(dev->id, model_num, ATA_ID_PROD_OFS, sizeof(model_num));
 
        for (i = 0; i < ARRAY_SIZE(ata_dma_blacklist); i++)
-               if (!strncmp(ata_dma_blacklist[i], s, len))
+               if (!strcmp(ata_dma_blacklist[i], model_num))
                        return 1;
 
        return 0;
 }
 
-static unsigned int ata_get_mode_mask(const struct ata_port *ap, int shift)
-{
-       const struct ata_device *master, *slave;
-       unsigned int mask;
-
-       master = &ap->device[0];
-       slave = &ap->device[1];
-
-       assert (ata_dev_present(master) || ata_dev_present(slave));
-
-       if (shift == ATA_SHIFT_UDMA) {
-               mask = ap->udma_mask;
-               if (ata_dev_present(master)) {
-                       mask &= (master->id[ATA_ID_UDMA_MODES] & 0xff);
-                       if (ata_dma_blacklisted(master)) {
-                               mask = 0;
-                               ata_pr_blacklisted(ap, master);
-                       }
-               }
-               if (ata_dev_present(slave)) {
-                       mask &= (slave->id[ATA_ID_UDMA_MODES] & 0xff);
-                       if (ata_dma_blacklisted(slave)) {
-                               mask = 0;
-                               ata_pr_blacklisted(ap, slave);
-                       }
-               }
-       }
-       else if (shift == ATA_SHIFT_MWDMA) {
-               mask = ap->mwdma_mask;
-               if (ata_dev_present(master)) {
-                       mask &= (master->id[ATA_ID_MWDMA_MODES] & 0x07);
-                       if (ata_dma_blacklisted(master)) {
-                               mask = 0;
-                               ata_pr_blacklisted(ap, master);
-                       }
-               }
-               if (ata_dev_present(slave)) {
-                       mask &= (slave->id[ATA_ID_MWDMA_MODES] & 0x07);
-                       if (ata_dma_blacklisted(slave)) {
-                               mask = 0;
-                               ata_pr_blacklisted(ap, slave);
-                       }
-               }
-       }
-       else if (shift == ATA_SHIFT_PIO) {
-               mask = ap->pio_mask;
-               if (ata_dev_present(master)) {
-                       /* spec doesn't return explicit support for
-                        * PIO0-2, so we fake it
-                        */
-                       u16 tmp_mode = master->id[ATA_ID_PIO_MODES] & 0x03;
-                       tmp_mode <<= 3;
-                       tmp_mode |= 0x7;
-                       mask &= tmp_mode;
-               }
-               if (ata_dev_present(slave)) {
-                       /* spec doesn't return explicit support for
-                        * PIO0-2, so we fake it
-                        */
-                       u16 tmp_mode = slave->id[ATA_ID_PIO_MODES] & 0x03;
-                       tmp_mode <<= 3;
-                       tmp_mode |= 0x7;
-                       mask &= tmp_mode;
-               }
-       }
-       else {
-               mask = 0xffffffff; /* shut up compiler warning */
-               BUG();
-       }
-
-       return mask;
-}
-
-/* find greatest bit */
-static int fgb(u32 bitmap)
-{
-       unsigned int i;
-       int x = -1;
-
-       for (i = 0; i < 32; i++)
-               if (bitmap & (1 << i))
-                       x = i;
-
-       return x;
-}
-
 /**
- *     ata_choose_xfer_mode - attempt to find best transfer mode
- *     @ap: Port for which an xfer mode will be selected
- *     @xfer_mode_out: (output) SET FEATURES - XFER MODE code
- *     @xfer_shift_out: (output) bit shift that selects this mode
+ *     ata_dev_xfermask - Compute supported xfermask of the given device
+ *     @ap: Port on which the device to compute xfermask for resides
+ *     @dev: Device to compute xfermask for
  *
- *     Based on host and device capabilities, determine the
- *     maximum transfer mode that is amenable to all.
+ *     Compute supported xfermask of @dev.  This function is
+ *     responsible for applying all known limits including host
+ *     controller limits, device blacklist, etc...
  *
  *     LOCKING:
- *     PCI/etc. bus probe sem.
+ *     None.
  *
  *     RETURNS:
- *     Zero on success, negative on error.
+ *     Computed xfermask.
  */
-
-static int ata_choose_xfer_mode(const struct ata_port *ap,
-                               u8 *xfer_mode_out,
-                               unsigned int *xfer_shift_out)
+static unsigned int ata_dev_xfermask(struct ata_port *ap,
+                                    struct ata_device *dev)
 {
-       unsigned int mask, shift;
-       int x, i;
+       unsigned long xfer_mask;
+       int i;
 
-       for (i = 0; i < ARRAY_SIZE(xfer_mode_classes); i++) {
-               shift = xfer_mode_classes[i].shift;
-               mask = ata_get_mode_mask(ap, shift);
+       xfer_mask = ata_pack_xfermask(ap->pio_mask, ap->mwdma_mask,
+                                     ap->udma_mask);
 
-               x = fgb(mask);
-               if (x >= 0) {
-                       *xfer_mode_out = xfer_mode_classes[i].base + x;
-                       *xfer_shift_out = shift;
-                       return 0;
-               }
+       /* use port-wide xfermask for now */
+       for (i = 0; i < ATA_MAX_DEVICES; i++) {
+               struct ata_device *d = &ap->device[i];
+               if (!ata_dev_present(d))
+                       continue;
+               xfer_mask &= ata_id_xfermask(d->id);
+               if (ata_dma_blacklisted(d))
+                       xfer_mask &= ~(ATA_MASK_MWDMA | ATA_MASK_UDMA);
        }
 
-       return -1;
+       if (ata_dma_blacklisted(dev))
+               printk(KERN_WARNING "ata%u: dev %u is on DMA blacklist, "
+                      "disabling DMA\n", ap->id, dev->devno);
+
+       return xfer_mask;
 }
 
 /**
@@ -2419,64 +2670,29 @@ static void ata_dev_set_xfermode(struct ata_port *ap, struct ata_device *dev)
        DPRINTK("EXIT\n");
 }
 
-/**
- *     ata_dev_reread_id - Reread the device identify device info
- *     @ap: port where the device is
- *     @dev: device to reread the identify device info
- *
- *     LOCKING:
- */
-
-static void ata_dev_reread_id(struct ata_port *ap, struct ata_device *dev)
-{
-       struct ata_taskfile tf;
-
-       ata_tf_init(ap, &tf, dev->devno);
-
-       if (dev->class == ATA_DEV_ATA) {
-               tf.command = ATA_CMD_ID_ATA;
-               DPRINTK("do ATA identify\n");
-       } else {
-               tf.command = ATA_CMD_ID_ATAPI;
-               DPRINTK("do ATAPI identify\n");
-       }
-
-       tf.flags |= ATA_TFLAG_DEVICE;
-       tf.protocol = ATA_PROT_PIO;
-
-       if (ata_exec_internal(ap, dev, &tf, DMA_FROM_DEVICE,
-                             dev->id, sizeof(dev->id)))
-               goto err_out;
-
-       swap_buf_le16(dev->id, ATA_ID_WORDS);
-
-       ata_dump_id(dev);
-
-       DPRINTK("EXIT\n");
-
-       return;
-err_out:
-       printk(KERN_ERR "ata%u: failed to reread ID, disabled\n", ap->id);
-       ata_port_disable(ap);
-}
-
 /**
  *     ata_dev_init_params - Issue INIT DEV PARAMS command
  *     @ap: Port associated with device @dev
  *     @dev: Device to which command will be sent
  *
  *     LOCKING:
+ *     Kernel thread context (may sleep)
+ *
+ *     RETURNS:
+ *     0 on success, AC_ERR_* mask otherwise.
  */
 
-static void ata_dev_init_params(struct ata_port *ap, struct ata_device *dev)
+static unsigned int ata_dev_init_params(struct ata_port *ap,
+                                       struct ata_device *dev)
 {
        struct ata_taskfile tf;
+       unsigned int err_mask;
        u16 sectors = dev->id[6];
        u16 heads   = dev->id[3];
 
        /* Number of sectors per track 1-255. Number of heads 1-16 */
        if (sectors < 1 || sectors > 255 || heads < 1 || heads > 16)
-               return;
+               return 0;
 
        /* set up init dev params taskfile */
        DPRINTK("init dev params \n");
@@ -2488,13 +2704,10 @@ static void ata_dev_init_params(struct ata_port *ap, struct ata_device *dev)
        tf.nsect = sectors;
        tf.device |= (heads - 1) & 0x0f; /* max head = num. of heads - 1 */
 
-       if (ata_exec_internal(ap, dev, &tf, DMA_NONE, NULL, 0)) {
-               printk(KERN_ERR "ata%u: failed to init parameters, disabled\n",
-                      ap->id);
-               ata_port_disable(ap);
-       }
+       err_mask = ata_exec_internal(ap, dev, &tf, DMA_NONE, NULL, 0);
 
-       DPRINTK("EXIT\n");
+       DPRINTK("EXIT, err_mask=%x\n", err_mask);
+       return err_mask;
 }
 
 /**
@@ -2514,11 +2727,11 @@ static void ata_sg_clean(struct ata_queued_cmd *qc)
        int dir = qc->dma_dir;
        void *pad_buf = NULL;
 
-       assert(qc->flags & ATA_QCFLAG_DMAMAP);
-       assert(sg != NULL);
+       WARN_ON(!(qc->flags & ATA_QCFLAG_DMAMAP));
+       WARN_ON(sg == NULL);
 
        if (qc->flags & ATA_QCFLAG_SINGLE)
-               assert(qc->n_elem <= 1);
+               WARN_ON(qc->n_elem > 1);
 
        VPRINTK("unmapping %u sg elements\n", qc->n_elem);
 
@@ -2573,8 +2786,8 @@ static void ata_fill_sg(struct ata_queued_cmd *qc)
        struct scatterlist *sg;
        unsigned int idx;
 
-       assert(qc->__sg != NULL);
-       assert(qc->n_elem > 0 || qc->pad_len > 0);
+       WARN_ON(qc->__sg == NULL);
+       WARN_ON(qc->n_elem == 0 && qc->pad_len == 0);
 
        idx = 0;
        ata_for_each_sg(sg, qc) {
@@ -2727,7 +2940,7 @@ static int ata_sg_setup_one(struct ata_queued_cmd *qc)
                void *pad_buf = ap->pad + (qc->tag * ATA_DMA_PAD_SZ);
                struct scatterlist *psg = &qc->pad_sgent;
 
-               assert(qc->dev->class == ATA_DEV_ATAPI);
+               WARN_ON(qc->dev->class != ATA_DEV_ATAPI);
 
                memset(pad_buf, 0, ATA_DMA_PAD_SZ);
 
@@ -2791,7 +3004,7 @@ static int ata_sg_setup(struct ata_queued_cmd *qc)
        int n_elem, pre_n_elem, dir, trim_sg = 0;
 
        VPRINTK("ENTER, ata%u\n", ap->id);
-       assert(qc->flags & ATA_QCFLAG_SG);
+       WARN_ON(!(qc->flags & ATA_QCFLAG_SG));
 
        /* we must lengthen transfers to end on a 32-bit boundary */
        qc->pad_len = lsg->length & 3;
@@ -2800,7 +3013,7 @@ static int ata_sg_setup(struct ata_queued_cmd *qc)
                struct scatterlist *psg = &qc->pad_sgent;
                unsigned int offset;
 
-               assert(qc->dev->class == ATA_DEV_ATAPI);
+               WARN_ON(qc->dev->class != ATA_DEV_ATAPI);
 
                memset(pad_buf, 0, ATA_DMA_PAD_SZ);
 
@@ -2876,7 +3089,7 @@ void ata_poll_qc_complete(struct ata_queued_cmd *qc)
 }
 
 /**
- *     ata_pio_poll -
+ *     ata_pio_poll - poll using PIO, depending on current state
  *     @ap: the target ata_port
  *
  *     LOCKING:
@@ -2894,7 +3107,7 @@ static unsigned long ata_pio_poll(struct ata_port *ap)
        unsigned int reg_state = HSM_ST_UNKNOWN;
 
        qc = ata_qc_from_tag(ap, ap->active_tag);
-       assert(qc != NULL);
+       WARN_ON(qc == NULL);
 
        switch (ap->hsm_task_state) {
        case HSM_ST:
@@ -2915,7 +3128,7 @@ static unsigned long ata_pio_poll(struct ata_port *ap)
        status = ata_chk_status(ap);
        if (status & ATA_BUSY) {
                if (time_after(jiffies, ap->pio_task_timeout)) {
-                       qc->err_mask |= AC_ERR_ATA_BUS;
+                       qc->err_mask |= AC_ERR_TIMEOUT;
                        ap->hsm_task_state = HSM_ST_TMOUT;
                        return 0;
                }
@@ -2962,7 +3175,7 @@ static int ata_pio_complete (struct ata_port *ap)
        }
 
        qc = ata_qc_from_tag(ap, ap->active_tag);
-       assert(qc != NULL);
+       WARN_ON(qc == NULL);
 
        drv_stat = ata_wait_idle(ap);
        if (!ata_ok(drv_stat)) {
@@ -2973,7 +3186,7 @@ static int ata_pio_complete (struct ata_port *ap)
 
        ap->hsm_task_state = HSM_ST_IDLE;
 
-       assert(qc->err_mask == 0);
+       WARN_ON(qc->err_mask);
        ata_poll_qc_complete(qc);
 
        /* another command may start at this point */
@@ -2983,7 +3196,7 @@ static int ata_pio_complete (struct ata_port *ap)
 
 
 /**
- *     swap_buf_le16 - swap halves of 16-words in place
+ *     swap_buf_le16 - swap halves of 16-bit words in place
  *     @buf:  Buffer to swap
  *     @buf_words:  Number of 16-bit words in buffer.
  *
@@ -3293,7 +3506,7 @@ static void atapi_pio_bytes(struct ata_queued_cmd *qc)
 err_out:
        printk(KERN_INFO "ata%u: dev %u: ATAPI check failed\n",
              ap->id, dev->devno);
-       qc->err_mask |= AC_ERR_ATA_BUS;
+       qc->err_mask |= AC_ERR_HSM;
        ap->hsm_task_state = HSM_ST_ERR;
 }
 
@@ -3330,7 +3543,7 @@ static void ata_pio_block(struct ata_port *ap)
        }
 
        qc = ata_qc_from_tag(ap, ap->active_tag);
-       assert(qc != NULL);
+       WARN_ON(qc == NULL);
 
        /* check error */
        if (status & (ATA_ERR | ATA_DF)) {
@@ -3351,7 +3564,7 @@ static void ata_pio_block(struct ata_port *ap)
        } else {
                /* handle BSY=0, DRQ=0 as error */
                if ((status & ATA_DRQ) == 0) {
-                       qc->err_mask |= AC_ERR_ATA_BUS;
+                       qc->err_mask |= AC_ERR_HSM;
                        ap->hsm_task_state = HSM_ST_ERR;
                        return;
                }
@@ -3365,7 +3578,7 @@ static void ata_pio_error(struct ata_port *ap)
        struct ata_queued_cmd *qc;
 
        qc = ata_qc_from_tag(ap, ap->active_tag);
-       assert(qc != NULL);
+       WARN_ON(qc == NULL);
 
        if (qc->tf.command != ATA_CMD_PACKET)
                printk(KERN_WARNING "ata%u: PIO error\n", ap->id);
@@ -3373,7 +3586,7 @@ static void ata_pio_error(struct ata_port *ap)
        /* make sure qc->err_mask is available to 
         * know what's wrong and recover
         */
-       assert(qc->err_mask);
+       WARN_ON(qc->err_mask == 0);
 
        ap->hsm_task_state = HSM_ST_IDLE;
 
@@ -3407,16 +3620,88 @@ fsm_start:
                timeout = ata_pio_poll(ap);
                break;
 
-       case HSM_ST_TMOUT:
-       case HSM_ST_ERR:
-               ata_pio_error(ap);
-               return;
+       case HSM_ST_TMOUT:
+       case HSM_ST_ERR:
+               ata_pio_error(ap);
+               return;
+       }
+
+       if (timeout)
+               ata_port_queue_task(ap, ata_pio_task, ap, timeout);
+       else if (!qc_completed)
+               goto fsm_start;
+}
+
+/**
+ *     atapi_packet_task - Write CDB bytes to hardware
+ *     @_data: Port to which ATAPI device is attached.
+ *
+ *     When device has indicated its readiness to accept
+ *     a CDB, this function is called.  Send the CDB.
+ *     If DMA is to be performed, exit immediately.
+ *     Otherwise, we are in polling mode, so poll
+ *     status under operation succeeds or fails.
+ *
+ *     LOCKING:
+ *     Kernel thread context (may sleep)
+ */
+
+static void atapi_packet_task(void *_data)
+{
+       struct ata_port *ap = _data;
+       struct ata_queued_cmd *qc;
+       u8 status;
+
+       qc = ata_qc_from_tag(ap, ap->active_tag);
+       WARN_ON(qc == NULL);
+       WARN_ON(!(qc->flags & ATA_QCFLAG_ACTIVE));
+
+       /* sleep-wait for BSY to clear */
+       DPRINTK("busy wait\n");
+       if (ata_busy_sleep(ap, ATA_TMOUT_CDB_QUICK, ATA_TMOUT_CDB)) {
+               qc->err_mask |= AC_ERR_TIMEOUT;
+               goto err_out;
+       }
+
+       /* make sure DRQ is set */
+       status = ata_chk_status(ap);
+       if ((status & (ATA_BUSY | ATA_DRQ)) != ATA_DRQ) {
+               qc->err_mask |= AC_ERR_HSM;
+               goto err_out;
+       }
+
+       /* send SCSI cdb */
+       DPRINTK("send cdb\n");
+       WARN_ON(qc->dev->cdb_len < 12);
+
+       if (qc->tf.protocol == ATA_PROT_ATAPI_DMA ||
+           qc->tf.protocol == ATA_PROT_ATAPI_NODATA) {
+               unsigned long flags;
+
+               /* Once we're done issuing command and kicking bmdma,
+                * irq handler takes over.  To not lose irq, we need
+                * to clear NOINTR flag before sending cdb, but
+                * interrupt handler shouldn't be invoked before we're
+                * finished.  Hence, the following locking.
+                */
+               spin_lock_irqsave(&ap->host_set->lock, flags);
+               ap->flags &= ~ATA_FLAG_NOINTR;
+               ata_data_xfer(ap, qc->cdb, qc->dev->cdb_len, 1);
+               if (qc->tf.protocol == ATA_PROT_ATAPI_DMA)
+                       ap->ops->bmdma_start(qc);       /* initiate bmdma */
+               spin_unlock_irqrestore(&ap->host_set->lock, flags);
+       } else {
+               ata_data_xfer(ap, qc->cdb, qc->dev->cdb_len, 1);
+
+               /* PIO commands are handled by polling */
+               ap->hsm_task_state = HSM_ST;
+               ata_port_queue_task(ap, ata_pio_task, ap, 0);
        }
 
-       if (timeout)
-               queue_delayed_work(ata_wq, &ap->pio_task, timeout);
-       else if (!qc_completed)
-               goto fsm_start;
+       return;
+
+err_out:
+       ata_poll_qc_complete(qc);
 }
 
 /**
@@ -3447,15 +3732,9 @@ static void ata_qc_timeout(struct ata_queued_cmd *qc)
 
        DPRINTK("ENTER\n");
 
-       spin_lock_irqsave(&host_set->lock, flags);
+       ap->hsm_task_state = HSM_ST_IDLE;
 
-       /* hack alert!  We cannot use the supplied completion
-        * function from inside the ->eh_strategy_handler() thread.
-        * libata is the only user of ->eh_strategy_handler() in
-        * any kernel, so the default scsi_done() assumes it is
-        * not being called from the SCSI EH.
-        */
-       qc->scsidone = scsi_finish_command;
+       spin_lock_irqsave(&host_set->lock, flags);
 
        switch (qc->tf.protocol) {
 
@@ -3480,12 +3759,13 @@ static void ata_qc_timeout(struct ata_queued_cmd *qc)
 
                /* complete taskfile transaction */
                qc->err_mask |= ac_err_mask(drv_stat);
-               ata_qc_complete(qc);
                break;
        }
 
        spin_unlock_irqrestore(&host_set->lock, flags);
 
+       ata_eh_qc_complete(qc);
+
        DPRINTK("EXIT\n");
 }
 
@@ -3510,20 +3790,10 @@ static void ata_qc_timeout(struct ata_queued_cmd *qc)
 
 void ata_eng_timeout(struct ata_port *ap)
 {
-       struct ata_queued_cmd *qc;
-
        DPRINTK("ENTER\n");
 
-       qc = ata_qc_from_tag(ap, ap->active_tag);
-       if (qc)
-               ata_qc_timeout(qc);
-       else {
-               printk(KERN_ERR "ata%u: BUG: timeout without command\n",
-                      ap->id);
-               goto out;
-       }
+       ata_qc_timeout(ata_qc_from_tag(ap, ap->active_tag));
 
-out:
        DPRINTK("EXIT\n");
 }
 
@@ -3579,21 +3849,6 @@ struct ata_queued_cmd *ata_qc_new_init(struct ata_port *ap,
        return qc;
 }
 
-static void __ata_qc_complete(struct ata_queued_cmd *qc)
-{
-       struct ata_port *ap = qc->ap;
-       unsigned int tag;
-
-       qc->flags = 0;
-       tag = qc->tag;
-       if (likely(ata_tag_valid(tag))) {
-               if (tag == ap->active_tag)
-                       ap->active_tag = ATA_TAG_POISON;
-               qc->tag = ATA_TAG_POISON;
-               clear_bit(tag, &ap->qactive);
-       }
-}
-
 /**
  *     ata_qc_free - free unused ata_queued_cmd
  *     @qc: Command to complete
@@ -3606,29 +3861,25 @@ static void __ata_qc_complete(struct ata_queued_cmd *qc)
  */
 void ata_qc_free(struct ata_queued_cmd *qc)
 {
-       assert(qc != NULL);     /* ata_qc_from_tag _might_ return NULL */
+       struct ata_port *ap = qc->ap;
+       unsigned int tag;
 
-       __ata_qc_complete(qc);
-}
+       WARN_ON(qc == NULL);    /* ata_qc_from_tag _might_ return NULL */
 
-/**
- *     ata_qc_complete - Complete an active ATA command
- *     @qc: Command to complete
- *     @err_mask: ATA Status register contents
- *
- *     Indicate to the mid and upper layers that an ATA
- *     command has completed, with either an ok or not-ok status.
- *
- *     LOCKING:
- *     spin_lock_irqsave(host_set lock)
- */
+       qc->flags = 0;
+       tag = qc->tag;
+       if (likely(ata_tag_valid(tag))) {
+               if (tag == ap->active_tag)
+                       ap->active_tag = ATA_TAG_POISON;
+               qc->tag = ATA_TAG_POISON;
+               clear_bit(tag, &ap->qactive);
+       }
+}
 
-void ata_qc_complete(struct ata_queued_cmd *qc)
+void __ata_qc_complete(struct ata_queued_cmd *qc)
 {
-       int rc;
-
-       assert(qc != NULL);     /* ata_qc_from_tag _might_ return NULL */
-       assert(qc->flags & ATA_QCFLAG_ACTIVE);
+       WARN_ON(qc == NULL);    /* ata_qc_from_tag _might_ return NULL */
+       WARN_ON(!(qc->flags & ATA_QCFLAG_ACTIVE));
 
        if (likely(qc->flags & ATA_QCFLAG_DMAMAP))
                ata_sg_clean(qc);
@@ -3640,17 +3891,7 @@ void ata_qc_complete(struct ata_queued_cmd *qc)
        qc->flags &= ~ATA_QCFLAG_ACTIVE;
 
        /* call completion callback */
-       rc = qc->complete_fn(qc);
-
-       /* if callback indicates not to complete command (non-zero),
-        * return immediately
-        */
-       if (rc != 0)
-               return;
-
-       __ata_qc_complete(qc);
-
-       VPRINTK("EXIT\n");
+       qc->complete_fn(qc);
 }
 
 static inline int ata_should_dma_map(struct ata_queued_cmd *qc)
@@ -3690,20 +3931,20 @@ static inline int ata_should_dma_map(struct ata_queued_cmd *qc)
  *     spin_lock_irqsave(host_set lock)
  *
  *     RETURNS:
- *     Zero on success, negative on error.
+ *     Zero on success, AC_ERR_* mask on failure
  */
 
-int ata_qc_issue(struct ata_queued_cmd *qc)
+unsigned int ata_qc_issue(struct ata_queued_cmd *qc)
 {
        struct ata_port *ap = qc->ap;
 
        if (ata_should_dma_map(qc)) {
                if (qc->flags & ATA_QCFLAG_SG) {
                        if (ata_sg_setup(qc))
-                               goto err_out;
+                               goto sg_err;
                } else if (qc->flags & ATA_QCFLAG_SINGLE) {
                        if (ata_sg_setup_one(qc))
-                               goto err_out;
+                               goto sg_err;
                }
        } else {
                qc->flags &= ~ATA_QCFLAG_DMAMAP;
@@ -3716,8 +3957,9 @@ int ata_qc_issue(struct ata_queued_cmd *qc)
 
        return ap->ops->qc_issue(qc);
 
-err_out:
-       return -1;
+sg_err:
+       qc->flags &= ~ATA_QCFLAG_DMAMAP;
+       return AC_ERR_SYSTEM;
 }
 
 
@@ -3736,10 +3978,10 @@ err_out:
  *     spin_lock_irqsave(host_set lock)
  *
  *     RETURNS:
- *     Zero on success, negative on error.
+ *     Zero on success, AC_ERR_* mask on failure
  */
 
-int ata_qc_issue_prot(struct ata_queued_cmd *qc)
+unsigned int ata_qc_issue_prot(struct ata_queued_cmd *qc)
 {
        struct ata_port *ap = qc->ap;
 
@@ -3760,31 +4002,31 @@ int ata_qc_issue_prot(struct ata_queued_cmd *qc)
                ata_qc_set_polling(qc);
                ata_tf_to_host(ap, &qc->tf);
                ap->hsm_task_state = HSM_ST;
-               queue_work(ata_wq, &ap->pio_task);
+               ata_port_queue_task(ap, ata_pio_task, ap, 0);
                break;
 
        case ATA_PROT_ATAPI:
                ata_qc_set_polling(qc);
                ata_tf_to_host(ap, &qc->tf);
-               queue_work(ata_wq, &ap->packet_task);
+               ata_port_queue_task(ap, atapi_packet_task, ap, 0);
                break;
 
        case ATA_PROT_ATAPI_NODATA:
                ap->flags |= ATA_FLAG_NOINTR;
                ata_tf_to_host(ap, &qc->tf);
-               queue_work(ata_wq, &ap->packet_task);
+               ata_port_queue_task(ap, atapi_packet_task, ap, 0);
                break;
 
        case ATA_PROT_ATAPI_DMA:
                ap->flags |= ATA_FLAG_NOINTR;
                ap->ops->tf_load(ap, &qc->tf);   /* load tf registers */
                ap->ops->bmdma_setup(qc);           /* set up bmdma */
-               queue_work(ata_wq, &ap->packet_task);
+               ata_port_queue_task(ap, atapi_packet_task, ap, 0);
                break;
 
        default:
                WARN_ON(1);
-               return -1;
+               return AC_ERR_SYSTEM;
        }
 
        return 0;
@@ -4147,91 +4389,6 @@ irqreturn_t ata_interrupt (int irq, void *dev_instance, struct pt_regs *regs)
        return IRQ_RETVAL(handled);
 }
 
-/**
- *     atapi_packet_task - Write CDB bytes to hardware
- *     @_data: Port to which ATAPI device is attached.
- *
- *     When device has indicated its readiness to accept
- *     a CDB, this function is called.  Send the CDB.
- *     If DMA is to be performed, exit immediately.
- *     Otherwise, we are in polling mode, so poll
- *     status under operation succeeds or fails.
- *
- *     LOCKING:
- *     Kernel thread context (may sleep)
- */
-
-static void atapi_packet_task(void *_data)
-{
-       struct ata_port *ap = _data;
-       struct ata_queued_cmd *qc;
-       u8 status;
-
-       qc = ata_qc_from_tag(ap, ap->active_tag);
-       assert(qc != NULL);
-       assert(qc->flags & ATA_QCFLAG_ACTIVE);
-
-       /* sleep-wait for BSY to clear */
-       DPRINTK("busy wait\n");
-       if (ata_busy_sleep(ap, ATA_TMOUT_CDB_QUICK, ATA_TMOUT_CDB)) {
-               qc->err_mask |= AC_ERR_ATA_BUS;
-               goto err_out;
-       }
-
-       /* make sure DRQ is set */
-       status = ata_chk_status(ap);
-       if ((status & (ATA_BUSY | ATA_DRQ)) != ATA_DRQ) {
-               qc->err_mask |= AC_ERR_ATA_BUS;
-               goto err_out;
-       }
-
-       /* send SCSI cdb */
-       DPRINTK("send cdb\n");
-       assert(ap->cdb_len >= 12);
-
-       if (qc->tf.protocol == ATA_PROT_ATAPI_DMA ||
-           qc->tf.protocol == ATA_PROT_ATAPI_NODATA) {
-               unsigned long flags;
-
-               /* Once we're done issuing command and kicking bmdma,
-                * irq handler takes over.  To not lose irq, we need
-                * to clear NOINTR flag before sending cdb, but
-                * interrupt handler shouldn't be invoked before we're
-                * finished.  Hence, the following locking.
-                */
-               spin_lock_irqsave(&ap->host_set->lock, flags);
-               ap->flags &= ~ATA_FLAG_NOINTR;
-               ata_data_xfer(ap, qc->cdb, ap->cdb_len, 1);
-               if (qc->tf.protocol == ATA_PROT_ATAPI_DMA)
-                       ap->ops->bmdma_start(qc);       /* initiate bmdma */
-               spin_unlock_irqrestore(&ap->host_set->lock, flags);
-       } else {
-               ata_data_xfer(ap, qc->cdb, ap->cdb_len, 1);
-
-               /* PIO commands are handled by polling */
-               ap->hsm_task_state = HSM_ST;
-               queue_work(ata_wq, &ap->pio_task);
-       }
-
-       return;
-
-err_out:
-       ata_poll_qc_complete(qc);
-}
-
-
-/**
- *     ata_port_start - Set port up for dma.
- *     @ap: Port to initialize
- *
- *     Called just after data structures for each port are
- *     initialized.  Allocates space for PRD table.
- *
- *     May be used as the port_start() entry in ata_port_operations.
- *
- *     LOCKING:
- *     Inherited from caller.
- */
 
 /*
  * Execute a 'simple' command, that only consists of the opcode 'cmd' itself,
@@ -4284,6 +4441,8 @@ static int ata_start_drive(struct ata_port *ap, struct ata_device *dev)
 
 /**
  *     ata_device_resume - wakeup a previously suspended devices
+ *     @ap: port the device is connected to
+ *     @dev: the device to resume
  *
  *     Kick the drive back into action, by sending it an idle immediate
  *     command and making sure its transfer mode matches between drive
@@ -4306,10 +4465,11 @@ int ata_device_resume(struct ata_port *ap, struct ata_device *dev)
 
 /**
  *     ata_device_suspend - prepare a device for suspend
+ *     @ap: port the device is connected to
+ *     @dev: the device to suspend
  *
  *     Flush the cache on the drive, if appropriate, then issue a
  *     standbynow command.
- *
  */
 int ata_device_suspend(struct ata_port *ap, struct ata_device *dev)
 {
@@ -4323,6 +4483,19 @@ int ata_device_suspend(struct ata_port *ap, struct ata_device *dev)
        return 0;
 }
 
+/**
+ *     ata_port_start - Set port up for dma.
+ *     @ap: Port to initialize
+ *
+ *     Called just after data structures for each port are
+ *     initialized.  Allocates space for PRD table.
+ *
+ *     May be used as the port_start() entry in ata_port_operations.
+ *
+ *     LOCKING:
+ *     Inherited from caller.
+ */
+
 int ata_port_start (struct ata_port *ap)
 {
        struct device *dev = ap->host_set->dev;
@@ -4436,8 +4609,8 @@ static void ata_host_init(struct ata_port *ap, struct Scsi_Host *host,
        ap->active_tag = ATA_TAG_POISON;
        ap->last_ctl = 0xFF;
 
-       INIT_WORK(&ap->packet_task, atapi_packet_task, ap);
-       INIT_WORK(&ap->pio_task, ata_pio_task, ap);
+       INIT_WORK(&ap->port_task, NULL, NULL);
+       INIT_LIST_HEAD(&ap->eh_done_q);
 
        for (i = 0; i < ATA_MAX_DEVICES; i++)
                ap->device[i].devno = i;
@@ -4579,9 +4752,9 @@ int ata_device_add(const struct ata_probe_ent *ent)
 
                ap = host_set->ports[i];
 
-               DPRINTK("ata%u: probe begin\n", ap->id);
+               DPRINTK("ata%u: bus probe begin\n", ap->id);
                rc = ata_bus_probe(ap);
-               DPRINTK("ata%u: probe end\n", ap->id);
+               DPRINTK("ata%u: bus probe end\n", ap->id);
 
                if (rc) {
                        /* FIXME: do something useful here?
@@ -4605,7 +4778,7 @@ int ata_device_add(const struct ata_probe_ent *ent)
        }
 
        /* probes are done, now scan each port's disk(s) */
-       DPRINTK("probe begin\n");
+       DPRINTK("host probe begin\n");
        for (i = 0; i < count; i++) {
                struct ata_port *ap = host_set->ports[i];
 
@@ -4691,11 +4864,14 @@ void ata_host_set_remove(struct ata_host_set *host_set)
 int ata_scsi_release(struct Scsi_Host *host)
 {
        struct ata_port *ap = (struct ata_port *) &host->hostdata[0];
+       int i;
 
        DPRINTK("ENTER\n");
 
        ap->ops->port_disable(ap);
        ata_host_remove(ap, 0);
+       for (i = 0; i < ATA_MAX_DEVICES; i++)
+               kfree(ap->device[i].id);
 
        DPRINTK("EXIT\n");
        return 1;
@@ -4727,32 +4903,6 @@ void ata_std_ports(struct ata_ioports *ioaddr)
        ioaddr->command_addr = ioaddr->cmd_addr + ATA_REG_CMD;
 }
 
-static struct ata_probe_ent *
-ata_probe_ent_alloc(struct device *dev, const struct ata_port_info *port)
-{
-       struct ata_probe_ent *probe_ent;
-
-       probe_ent = kzalloc(sizeof(*probe_ent), GFP_KERNEL);
-       if (!probe_ent) {
-               printk(KERN_ERR DRV_NAME "(%s): out of memory\n",
-                      kobject_name(&(dev->kobj)));
-               return NULL;
-       }
-
-       INIT_LIST_HEAD(&probe_ent->node);
-       probe_ent->dev = dev;
-
-       probe_ent->sht = port->sht;
-       probe_ent->host_flags = port->host_flags;
-       probe_ent->pio_mask = port->pio_mask;
-       probe_ent->mwdma_mask = port->mwdma_mask;
-       probe_ent->udma_mask = port->udma_mask;
-       probe_ent->port_ops = port->port_ops;
-
-       return probe_ent;
-}
-
-
 
 #ifdef CONFIG_PCI
 
@@ -4763,256 +4913,6 @@ void ata_pci_host_stop (struct ata_host_set *host_set)
        pci_iounmap(pdev, host_set->mmio_base);
 }
 
-/**
- *     ata_pci_init_native_mode - Initialize native-mode driver
- *     @pdev:  pci device to be initialized
- *     @port:  array[2] of pointers to port info structures.
- *     @ports: bitmap of ports present
- *
- *     Utility function which allocates and initializes an
- *     ata_probe_ent structure for a standard dual-port
- *     PIO-based IDE controller.  The returned ata_probe_ent
- *     structure can be passed to ata_device_add().  The returned
- *     ata_probe_ent structure should then be freed with kfree().
- *
- *     The caller need only pass the address of the primary port, the
- *     secondary will be deduced automatically. If the device has non
- *     standard secondary port mappings this function can be called twice,
- *     once for each interface.
- */
-
-struct ata_probe_ent *
-ata_pci_init_native_mode(struct pci_dev *pdev, struct ata_port_info **port, int ports)
-{
-       struct ata_probe_ent *probe_ent =
-               ata_probe_ent_alloc(pci_dev_to_dev(pdev), port[0]);
-       int p = 0;
-
-       if (!probe_ent)
-               return NULL;
-
-       probe_ent->irq = pdev->irq;
-       probe_ent->irq_flags = SA_SHIRQ;
-       probe_ent->private_data = port[0]->private_data;
-
-       if (ports & ATA_PORT_PRIMARY) {
-               probe_ent->port[p].cmd_addr = pci_resource_start(pdev, 0);
-               probe_ent->port[p].altstatus_addr =
-               probe_ent->port[p].ctl_addr =
-                       pci_resource_start(pdev, 1) | ATA_PCI_CTL_OFS;
-               probe_ent->port[p].bmdma_addr = pci_resource_start(pdev, 4);
-               ata_std_ports(&probe_ent->port[p]);
-               p++;
-       }
-
-       if (ports & ATA_PORT_SECONDARY) {
-               probe_ent->port[p].cmd_addr = pci_resource_start(pdev, 2);
-               probe_ent->port[p].altstatus_addr =
-               probe_ent->port[p].ctl_addr =
-                       pci_resource_start(pdev, 3) | ATA_PCI_CTL_OFS;
-               probe_ent->port[p].bmdma_addr = pci_resource_start(pdev, 4) + 8;
-               ata_std_ports(&probe_ent->port[p]);
-               p++;
-       }
-
-       probe_ent->n_ports = p;
-       return probe_ent;
-}
-
-static struct ata_probe_ent *ata_pci_init_legacy_port(struct pci_dev *pdev, struct ata_port_info *port, int port_num)
-{
-       struct ata_probe_ent *probe_ent;
-
-       probe_ent = ata_probe_ent_alloc(pci_dev_to_dev(pdev), port);
-       if (!probe_ent)
-               return NULL;
-
-       probe_ent->legacy_mode = 1;
-       probe_ent->n_ports = 1;
-       probe_ent->hard_port_no = port_num;
-       probe_ent->private_data = port->private_data;
-
-       switch(port_num)
-       {
-               case 0:
-                       probe_ent->irq = 14;
-                       probe_ent->port[0].cmd_addr = 0x1f0;
-                       probe_ent->port[0].altstatus_addr =
-                       probe_ent->port[0].ctl_addr = 0x3f6;
-                       break;
-               case 1:
-                       probe_ent->irq = 15;
-                       probe_ent->port[0].cmd_addr = 0x170;
-                       probe_ent->port[0].altstatus_addr =
-                       probe_ent->port[0].ctl_addr = 0x376;
-                       break;
-       }
-       probe_ent->port[0].bmdma_addr = pci_resource_start(pdev, 4) + 8 * port_num;
-       ata_std_ports(&probe_ent->port[0]);
-       return probe_ent;
-}
-
-/**
- *     ata_pci_init_one - Initialize/register PCI IDE host controller
- *     @pdev: Controller to be initialized
- *     @port_info: Information from low-level host driver
- *     @n_ports: Number of ports attached to host controller
- *
- *     This is a helper function which can be called from a driver's
- *     xxx_init_one() probe function if the hardware uses traditional
- *     IDE taskfile registers.
- *
- *     This function calls pci_enable_device(), reserves its register
- *     regions, sets the dma mask, enables bus master mode, and calls
- *     ata_device_add()
- *
- *     LOCKING:
- *     Inherited from PCI layer (may sleep).
- *
- *     RETURNS:
- *     Zero on success, negative on errno-based value on error.
- */
-
-int ata_pci_init_one (struct pci_dev *pdev, struct ata_port_info **port_info,
-                     unsigned int n_ports)
-{
-       struct ata_probe_ent *probe_ent = NULL, *probe_ent2 = NULL;
-       struct ata_port_info *port[2];
-       u8 tmp8, mask;
-       unsigned int legacy_mode = 0;
-       int disable_dev_on_err = 1;
-       int rc;
-
-       DPRINTK("ENTER\n");
-
-       port[0] = port_info[0];
-       if (n_ports > 1)
-               port[1] = port_info[1];
-       else
-               port[1] = port[0];
-
-       if ((port[0]->host_flags & ATA_FLAG_NO_LEGACY) == 0
-           && (pdev->class >> 8) == PCI_CLASS_STORAGE_IDE) {
-               /* TODO: What if one channel is in native mode ... */
-               pci_read_config_byte(pdev, PCI_CLASS_PROG, &tmp8);
-               mask = (1 << 2) | (1 << 0);
-               if ((tmp8 & mask) != mask)
-                       legacy_mode = (1 << 3);
-       }
-
-       /* FIXME... */
-       if ((!legacy_mode) && (n_ports > 2)) {
-               printk(KERN_ERR "ata: BUG: native mode, n_ports > 2\n");
-               n_ports = 2;
-               /* For now */
-       }
-
-       /* FIXME: Really for ATA it isn't safe because the device may be
-          multi-purpose and we want to leave it alone if it was already
-          enabled. Secondly for shared use as Arjan says we want refcounting
-          
-          Checking dev->is_enabled is insufficient as this is not set at
-          boot for the primary video which is BIOS enabled
-         */
-         
-       rc = pci_enable_device(pdev);
-       if (rc)
-               return rc;
-
-       rc = pci_request_regions(pdev, DRV_NAME);
-       if (rc) {
-               disable_dev_on_err = 0;
-               goto err_out;
-       }
-
-       /* FIXME: Should use platform specific mappers for legacy port ranges */
-       if (legacy_mode) {
-               if (!request_region(0x1f0, 8, "libata")) {
-                       struct resource *conflict, res;
-                       res.start = 0x1f0;
-                       res.end = 0x1f0 + 8 - 1;
-                       conflict = ____request_resource(&ioport_resource, &res);
-                       if (!strcmp(conflict->name, "libata"))
-                               legacy_mode |= (1 << 0);
-                       else {
-                               disable_dev_on_err = 0;
-                               printk(KERN_WARNING "ata: 0x1f0 IDE port busy\n");
-                       }
-               } else
-                       legacy_mode |= (1 << 0);
-
-               if (!request_region(0x170, 8, "libata")) {
-                       struct resource *conflict, res;
-                       res.start = 0x170;
-                       res.end = 0x170 + 8 - 1;
-                       conflict = ____request_resource(&ioport_resource, &res);
-                       if (!strcmp(conflict->name, "libata"))
-                               legacy_mode |= (1 << 1);
-                       else {
-                               disable_dev_on_err = 0;
-                               printk(KERN_WARNING "ata: 0x170 IDE port busy\n");
-                       }
-               } else
-                       legacy_mode |= (1 << 1);
-       }
-
-       /* we have legacy mode, but all ports are unavailable */
-       if (legacy_mode == (1 << 3)) {
-               rc = -EBUSY;
-               goto err_out_regions;
-       }
-
-       rc = pci_set_dma_mask(pdev, ATA_DMA_MASK);
-       if (rc)
-               goto err_out_regions;
-       rc = pci_set_consistent_dma_mask(pdev, ATA_DMA_MASK);
-       if (rc)
-               goto err_out_regions;
-
-       if (legacy_mode) {
-               if (legacy_mode & (1 << 0))
-                       probe_ent = ata_pci_init_legacy_port(pdev, port[0], 0);
-               if (legacy_mode & (1 << 1))
-                       probe_ent2 = ata_pci_init_legacy_port(pdev, port[1], 1);
-       } else {
-               if (n_ports == 2)
-                       probe_ent = ata_pci_init_native_mode(pdev, port, ATA_PORT_PRIMARY | ATA_PORT_SECONDARY);
-               else
-                       probe_ent = ata_pci_init_native_mode(pdev, port, ATA_PORT_PRIMARY);
-       }
-       if (!probe_ent && !probe_ent2) {
-               rc = -ENOMEM;
-               goto err_out_regions;
-       }
-
-       pci_set_master(pdev);
-
-       /* FIXME: check ata_device_add return */
-       if (legacy_mode) {
-               if (legacy_mode & (1 << 0))
-                       ata_device_add(probe_ent);
-               if (legacy_mode & (1 << 1))
-                       ata_device_add(probe_ent2);
-       } else
-               ata_device_add(probe_ent);
-
-       kfree(probe_ent);
-       kfree(probe_ent2);
-
-       return 0;
-
-err_out_regions:
-       if (legacy_mode & (1 << 0))
-               release_region(0x1f0, 8);
-       if (legacy_mode & (1 << 1))
-               release_region(0x170, 8);
-       pci_release_regions(pdev);
-err_out:
-       if (disable_dev_on_err)
-               pci_disable_device(pdev);
-       return rc;
-}
-
 /**
  *     ata_pci_remove_one - PCI layer callback for device removal
  *     @pdev: PCI device that was removed
@@ -5143,7 +5043,7 @@ EXPORT_SYMBOL_GPL(ata_device_add);
 EXPORT_SYMBOL_GPL(ata_host_set_remove);
 EXPORT_SYMBOL_GPL(ata_sg_init);
 EXPORT_SYMBOL_GPL(ata_sg_init_one);
-EXPORT_SYMBOL_GPL(ata_qc_complete);
+EXPORT_SYMBOL_GPL(__ata_qc_complete);
 EXPORT_SYMBOL_GPL(ata_qc_issue_prot);
 EXPORT_SYMBOL_GPL(ata_eng_timeout);
 EXPORT_SYMBOL_GPL(ata_tf_load);
@@ -5169,18 +5069,30 @@ EXPORT_SYMBOL_GPL(ata_port_probe);
 EXPORT_SYMBOL_GPL(sata_phy_reset);
 EXPORT_SYMBOL_GPL(__sata_phy_reset);
 EXPORT_SYMBOL_GPL(ata_bus_reset);
+EXPORT_SYMBOL_GPL(ata_std_probeinit);
+EXPORT_SYMBOL_GPL(ata_std_softreset);
+EXPORT_SYMBOL_GPL(sata_std_hardreset);
+EXPORT_SYMBOL_GPL(ata_std_postreset);
+EXPORT_SYMBOL_GPL(ata_std_probe_reset);
+EXPORT_SYMBOL_GPL(ata_drive_probe_reset);
+EXPORT_SYMBOL_GPL(ata_dev_revalidate);
 EXPORT_SYMBOL_GPL(ata_port_disable);
 EXPORT_SYMBOL_GPL(ata_ratelimit);
+EXPORT_SYMBOL_GPL(ata_busy_sleep);
+EXPORT_SYMBOL_GPL(ata_port_queue_task);
 EXPORT_SYMBOL_GPL(ata_scsi_ioctl);
 EXPORT_SYMBOL_GPL(ata_scsi_queuecmd);
+EXPORT_SYMBOL_GPL(ata_scsi_timed_out);
 EXPORT_SYMBOL_GPL(ata_scsi_error);
 EXPORT_SYMBOL_GPL(ata_scsi_slave_config);
 EXPORT_SYMBOL_GPL(ata_scsi_release);
 EXPORT_SYMBOL_GPL(ata_host_intr);
 EXPORT_SYMBOL_GPL(ata_dev_classify);
-EXPORT_SYMBOL_GPL(ata_dev_id_string);
-EXPORT_SYMBOL_GPL(ata_dev_config);
+EXPORT_SYMBOL_GPL(ata_id_string);
+EXPORT_SYMBOL_GPL(ata_id_c_string);
 EXPORT_SYMBOL_GPL(ata_scsi_simulate);
+EXPORT_SYMBOL_GPL(ata_eh_qc_complete);
+EXPORT_SYMBOL_GPL(ata_eh_qc_retry);
 
 EXPORT_SYMBOL_GPL(ata_pio_need_iordy);
 EXPORT_SYMBOL_GPL(ata_timing_compute);
index 59503c9ccac9ff794a66d29c358f4d98c4b33ed0..ccedb4536977af454a6c95a613fefc4a292d3e83 100644 (file)
@@ -151,7 +151,7 @@ int ata_cmd_ioctl(struct scsi_device *scsidev, void __user *arg)
        struct scsi_sense_hdr sshdr;
        enum dma_data_direction data_dir;
 
-       if (NULL == (void *)arg)
+       if (arg == NULL)
                return -EINVAL;
 
        if (copy_from_user(args, arg, sizeof(args)))
@@ -201,7 +201,7 @@ int ata_cmd_ioctl(struct scsi_device *scsidev, void __user *arg)
        /* Need code to retrieve data from check condition? */
 
        if ((argbuf)
-        && copy_to_user((void *)(arg + sizeof(args)), argbuf, argsize))
+        && copy_to_user(arg + sizeof(args), argbuf, argsize))
                rc = -EFAULT;
 error:
        if (argbuf)
@@ -228,7 +228,7 @@ int ata_task_ioctl(struct scsi_device *scsidev, void __user *arg)
        u8 args[7];
        struct scsi_sense_hdr sshdr;
 
-       if (NULL == (void *)arg)
+       if (arg == NULL)
                return -EINVAL;
 
        if (copy_from_user(args, arg, sizeof(args)))
@@ -553,7 +553,7 @@ void ata_gen_ata_desc_sense(struct ata_queued_cmd *qc)
        /*
         * Read the controller registers.
         */
-       assert(NULL != qc->ap->ops->tf_read);
+       WARN_ON(qc->ap->ops->tf_read == NULL);
        qc->ap->ops->tf_read(qc->ap, tf);
 
        /*
@@ -628,7 +628,7 @@ void ata_gen_fixed_sense(struct ata_queued_cmd *qc)
        /*
         * Read the controller registers.
         */
-       assert(NULL != qc->ap->ops->tf_read);
+       WARN_ON(qc->ap->ops->tf_read == NULL);
        qc->ap->ops->tf_read(qc->ap, tf);
 
        /*
@@ -684,23 +684,23 @@ int ata_scsi_slave_config(struct scsi_device *sdev)
        if (sdev->id < ATA_MAX_DEVICES) {
                struct ata_port *ap;
                struct ata_device *dev;
+               unsigned int max_sectors;
 
                ap = (struct ata_port *) &sdev->host->hostdata[0];
                dev = &ap->device[sdev->id];
 
-               /* TODO: 1024 is an arbitrary number, not the
+               /* TODO: 2048 is an arbitrary number, not the
                 * hardware maximum.  This should be increased to
                 * 65534 when Jens Axboe's patch for dynamically
                 * determining max_sectors is merged.
                 */
-               if ((dev->flags & ATA_DFLAG_LBA48) &&
-                   ((dev->flags & ATA_DFLAG_LOCK_SECTORS) == 0)) {
-                       /*
-                        * do not overwrite sdev->host->max_sectors, since
-                        * other drives on this host may not support LBA48
-                        */
-                       blk_queue_max_sectors(sdev->request_queue, 2048);
-               }
+               max_sectors = ATA_MAX_SECTORS;
+               if (dev->flags & ATA_DFLAG_LBA48)
+                       max_sectors = 2048;
+               if (dev->max_sectors)
+                       max_sectors = dev->max_sectors;
+
+               blk_queue_max_sectors(sdev->request_queue, max_sectors);
 
                /*
                 * SATA DMA transfers must be multiples of 4 byte, so
@@ -716,6 +716,47 @@ int ata_scsi_slave_config(struct scsi_device *sdev)
        return 0;       /* scsi layer doesn't check return value, sigh */
 }
 
+/**
+ *     ata_scsi_timed_out - SCSI layer time out callback
+ *     @cmd: timed out SCSI command
+ *
+ *     Handles SCSI layer timeout.  We race with normal completion of
+ *     the qc for @cmd.  If the qc is already gone, we lose and let
+ *     the scsi command finish (EH_HANDLED).  Otherwise, the qc has
+ *     timed out and EH should be invoked.  Prevent ata_qc_complete()
+ *     from finishing it by setting EH_SCHEDULED and return
+ *     EH_NOT_HANDLED.
+ *
+ *     LOCKING:
+ *     Called from timer context
+ *
+ *     RETURNS:
+ *     EH_HANDLED or EH_NOT_HANDLED
+ */
+enum scsi_eh_timer_return ata_scsi_timed_out(struct scsi_cmnd *cmd)
+{
+       struct Scsi_Host *host = cmd->device->host;
+       struct ata_port *ap = (struct ata_port *) &host->hostdata[0];
+       unsigned long flags;
+       struct ata_queued_cmd *qc;
+       enum scsi_eh_timer_return ret = EH_HANDLED;
+
+       DPRINTK("ENTER\n");
+
+       spin_lock_irqsave(&ap->host_set->lock, flags);
+       qc = ata_qc_from_tag(ap, ap->active_tag);
+       if (qc) {
+               WARN_ON(qc->scsicmd != cmd);
+               qc->flags |= ATA_QCFLAG_EH_SCHEDULED;
+               qc->err_mask |= AC_ERR_TIMEOUT;
+               ret = EH_NOT_HANDLED;
+       }
+       spin_unlock_irqrestore(&ap->host_set->lock, flags);
+
+       DPRINTK("EXIT, ret=%d\n", ret);
+       return ret;
+}
+
 /**
  *     ata_scsi_error - SCSI layer error handler callback
  *     @host: SCSI host on which error occurred
@@ -732,23 +773,84 @@ int ata_scsi_slave_config(struct scsi_device *sdev)
 int ata_scsi_error(struct Scsi_Host *host)
 {
        struct ata_port *ap;
+       unsigned long flags;
 
        DPRINTK("ENTER\n");
 
        ap = (struct ata_port *) &host->hostdata[0];
+
+       spin_lock_irqsave(&ap->host_set->lock, flags);
+       WARN_ON(ap->flags & ATA_FLAG_IN_EH);
+       ap->flags |= ATA_FLAG_IN_EH;
+       WARN_ON(ata_qc_from_tag(ap, ap->active_tag) == NULL);
+       spin_unlock_irqrestore(&ap->host_set->lock, flags);
+
+       ata_port_flush_task(ap);
+
        ap->ops->eng_timeout(ap);
 
-       /* TODO: this is per-command; when queueing is supported
-        * this code will either change or move to a more
-        * appropriate place
-        */
-       host->host_failed--;
-       INIT_LIST_HEAD(&host->eh_cmd_q);
+       WARN_ON(host->host_failed || !list_empty(&host->eh_cmd_q));
+
+       scsi_eh_flush_done_q(&ap->eh_done_q);
+
+       spin_lock_irqsave(&ap->host_set->lock, flags);
+       ap->flags &= ~ATA_FLAG_IN_EH;
+       spin_unlock_irqrestore(&ap->host_set->lock, flags);
 
        DPRINTK("EXIT\n");
        return 0;
 }
 
+static void ata_eh_scsidone(struct scsi_cmnd *scmd)
+{
+       /* nada */
+}
+
+static void __ata_eh_qc_complete(struct ata_queued_cmd *qc)
+{
+       struct ata_port *ap = qc->ap;
+       struct scsi_cmnd *scmd = qc->scsicmd;
+       unsigned long flags;
+
+       spin_lock_irqsave(&ap->host_set->lock, flags);
+       qc->scsidone = ata_eh_scsidone;
+       __ata_qc_complete(qc);
+       WARN_ON(ata_tag_valid(qc->tag));
+       spin_unlock_irqrestore(&ap->host_set->lock, flags);
+
+       scsi_eh_finish_cmd(scmd, &ap->eh_done_q);
+}
+
+/**
+ *     ata_eh_qc_complete - Complete an active ATA command from EH
+ *     @qc: Command to complete
+ *
+ *     Indicate to the mid and upper layers that an ATA command has
+ *     completed.  To be used from EH.
+ */
+void ata_eh_qc_complete(struct ata_queued_cmd *qc)
+{
+       struct scsi_cmnd *scmd = qc->scsicmd;
+       scmd->retries = scmd->allowed;
+       __ata_eh_qc_complete(qc);
+}
+
+/**
+ *     ata_eh_qc_retry - Tell midlayer to retry an ATA command after EH
+ *     @qc: Command to retry
+ *
+ *     Indicate to the mid and upper layers that an ATA command
+ *     should be retried.  To be used from EH.
+ *
+ *     SCSI midlayer limits the number of retries to scmd->allowed.
+ *     This function might need to adjust scmd->retries for commands
+ *     which get retried due to unrelated NCQ failures.
+ */
+void ata_eh_qc_retry(struct ata_queued_cmd *qc)
+{
+       __ata_eh_qc_complete(qc);
+}
+
 /**
  *     ata_scsi_start_stop_xlat - Translate SCSI START STOP UNIT command
  *     @qc: Storage for translated ATA taskfile
@@ -985,9 +1087,13 @@ static unsigned int ata_scsi_verify_xlat(struct ata_queued_cmd *qc, const u8 *sc
        if (dev->flags & ATA_DFLAG_LBA) {
                tf->flags |= ATA_TFLAG_LBA;
 
-               if (dev->flags & ATA_DFLAG_LBA48) {
-                       if (n_block > (64 * 1024))
-                               goto invalid_fld;
+               if (lba_28_ok(block, n_block)) {
+                       /* use LBA28 */
+                       tf->command = ATA_CMD_VERIFY;
+                       tf->device |= (block >> 24) & 0xf;
+               } else if (lba_48_ok(block, n_block)) {
+                       if (!(dev->flags & ATA_DFLAG_LBA48))
+                               goto out_of_range;
 
                        /* use LBA48 */
                        tf->flags |= ATA_TFLAG_LBA48;
@@ -998,15 +1104,9 @@ static unsigned int ata_scsi_verify_xlat(struct ata_queued_cmd *qc, const u8 *sc
                        tf->hob_lbah = (block >> 40) & 0xff;
                        tf->hob_lbam = (block >> 32) & 0xff;
                        tf->hob_lbal = (block >> 24) & 0xff;
-               } else {
-                       if (n_block > 256)
-                               goto invalid_fld;
-
-                       /* use LBA28 */
-                       tf->command = ATA_CMD_VERIFY;
-
-                       tf->device |= (block >> 24) & 0xf;
-               }
+               } else
+                       /* request too large even for LBA48 */
+                       goto out_of_range;
 
                tf->nsect = n_block & 0xff;
 
@@ -1019,8 +1119,8 @@ static unsigned int ata_scsi_verify_xlat(struct ata_queued_cmd *qc, const u8 *sc
                /* CHS */
                u32 sect, head, cyl, track;
 
-               if (n_block > 256)
-                       goto invalid_fld;
+               if (!lba_28_ok(block, n_block))
+                       goto out_of_range;
 
                /* Convert LBA to CHS */
                track = (u32)block / dev->sectors;
@@ -1139,9 +1239,11 @@ static unsigned int ata_scsi_rw_xlat(struct ata_queued_cmd *qc, const u8 *scsicm
        if (dev->flags & ATA_DFLAG_LBA) {
                tf->flags |= ATA_TFLAG_LBA;
 
-               if (dev->flags & ATA_DFLAG_LBA48) {
-                       /* The request -may- be too large for LBA48. */
-                       if ((block >> 48) || (n_block > 65536))
+               if (lba_28_ok(block, n_block)) {
+                       /* use LBA28 */
+                       tf->device |= (block >> 24) & 0xf;
+               } else if (lba_48_ok(block, n_block)) {
+                       if (!(dev->flags & ATA_DFLAG_LBA48))
                                goto out_of_range;
 
                        /* use LBA48 */
@@ -1152,15 +1254,9 @@ static unsigned int ata_scsi_rw_xlat(struct ata_queued_cmd *qc, const u8 *scsicm
                        tf->hob_lbah = (block >> 40) & 0xff;
                        tf->hob_lbam = (block >> 32) & 0xff;
                        tf->hob_lbal = (block >> 24) & 0xff;
-               } else { 
-                       /* use LBA28 */
-
-                       /* The request -may- be too large for LBA28. */
-                       if ((block >> 28) || (n_block > 256))
-                               goto out_of_range;
-
-                       tf->device |= (block >> 24) & 0xf;
-               }
+               } else
+                       /* request too large even for LBA48 */
+                       goto out_of_range;
 
                if (unlikely(ata_rwcmd_protocol(qc) < 0))
                        goto invalid_fld;
@@ -1178,7 +1274,7 @@ static unsigned int ata_scsi_rw_xlat(struct ata_queued_cmd *qc, const u8 *scsicm
                u32 sect, head, cyl, track;
 
                /* The request -may- be too large for CHS addressing. */
-               if ((block >> 28) || (n_block > 256))
+               if (!lba_28_ok(block, n_block))
                        goto out_of_range;
 
                if (unlikely(ata_rwcmd_protocol(qc) < 0))
@@ -1225,7 +1321,7 @@ nothing_to_do:
        return 1;
 }
 
-static int ata_scsi_qc_complete(struct ata_queued_cmd *qc)
+static void ata_scsi_qc_complete(struct ata_queued_cmd *qc)
 {
        struct scsi_cmnd *cmd = qc->scsicmd;
        u8 *cdb = cmd->cmnd;
@@ -1262,7 +1358,7 @@ static int ata_scsi_qc_complete(struct ata_queued_cmd *qc)
 
        qc->scsidone(cmd);
 
-       return 0;
+       ata_qc_free(qc);
 }
 
 /**
@@ -1328,8 +1424,9 @@ static void ata_scsi_translate(struct ata_port *ap, struct ata_device *dev,
                goto early_finish;
 
        /* select device, send command to hardware */
-       if (ata_qc_issue(qc))
-               goto err_did;
+       qc->err_mask = ata_qc_issue(qc);
+       if (qc->err_mask)
+               ata_qc_complete(qc);
 
        VPRINTK("EXIT\n");
        return;
@@ -1472,8 +1569,8 @@ unsigned int ata_scsiop_inq_std(struct ata_scsi_args *args, u8 *rbuf,
 
        if (buflen > 35) {
                memcpy(&rbuf[8], "ATA     ", 8);
-               ata_dev_id_string(args->id, &rbuf[16], ATA_ID_PROD_OFS, 16);
-               ata_dev_id_string(args->id, &rbuf[32], ATA_ID_FW_REV_OFS, 4);
+               ata_id_string(args->id, &rbuf[16], ATA_ID_PROD_OFS, 16);
+               ata_id_string(args->id, &rbuf[32], ATA_ID_FW_REV_OFS, 4);
                if (rbuf[32] == 0 || rbuf[32] == ' ')
                        memcpy(&rbuf[32], "n/a ", 4);
        }
@@ -1547,8 +1644,8 @@ unsigned int ata_scsiop_inq_80(struct ata_scsi_args *args, u8 *rbuf,
        memcpy(rbuf, hdr, sizeof(hdr));
 
        if (buflen > (ATA_SERNO_LEN + 4 - 1))
-               ata_dev_id_string(args->id, (unsigned char *) &rbuf[4],
-                                 ATA_ID_SERNO_OFS, ATA_SERNO_LEN);
+               ata_id_string(args->id, (unsigned char *) &rbuf[4],
+                             ATA_ID_SERNO_OFS, ATA_SERNO_LEN);
 
        return 0;
 }
@@ -1713,15 +1810,12 @@ static int ata_dev_supports_fua(u16 *id)
        if (!ata_id_has_fua(id))
                return 0;
 
-       model[40] = '\0';
-       fw[8] = '\0';
-
-       ata_dev_id_string(id, model, ATA_ID_PROD_OFS, sizeof(model) - 1);
-       ata_dev_id_string(id, fw, ATA_ID_FW_REV_OFS, sizeof(fw) - 1);
+       ata_id_c_string(id, model, ATA_ID_PROD_OFS, sizeof(model));
+       ata_id_c_string(id, fw, ATA_ID_FW_REV_OFS, sizeof(fw));
 
-       if (strncmp(model, "Maxtor", 6))
+       if (strcmp(model, "Maxtor"))
                return 1;
-       if (strncmp(fw, "BANC1G10", 8))
+       if (strcmp(fw, "BANC1G10"))
                return 1;
 
        return 0; /* blacklisted */
@@ -2015,7 +2109,7 @@ void ata_scsi_badcmd(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *), u8
        done(cmd);
 }
 
-static int atapi_sense_complete(struct ata_queued_cmd *qc)
+static void atapi_sense_complete(struct ata_queued_cmd *qc)
 {
        if (qc->err_mask && ((qc->err_mask & AC_ERR_DEV) == 0))
                /* FIXME: not quite right; we don't want the
@@ -2026,7 +2120,7 @@ static int atapi_sense_complete(struct ata_queued_cmd *qc)
                ata_gen_ata_desc_sense(qc);
 
        qc->scsidone(qc->scsicmd);
-       return 0;
+       ata_qc_free(qc);
 }
 
 /* is it pointless to prefer PIO for "safety reasons"? */
@@ -2056,7 +2150,7 @@ static void atapi_request_sense(struct ata_queued_cmd *qc)
        ata_sg_init_one(qc, cmd->sense_buffer, sizeof(cmd->sense_buffer));
        qc->dma_dir = DMA_FROM_DEVICE;
 
-       memset(&qc->cdb, 0, ap->cdb_len);
+       memset(&qc->cdb, 0, qc->dev->cdb_len);
        qc->cdb[0] = REQUEST_SENSE;
        qc->cdb[4] = SCSI_SENSE_BUFFERSIZE;
 
@@ -2075,15 +2169,14 @@ static void atapi_request_sense(struct ata_queued_cmd *qc)
 
        qc->complete_fn = atapi_sense_complete;
 
-       if (ata_qc_issue(qc)) {
-               qc->err_mask |= AC_ERR_OTHER;
+       qc->err_mask = ata_qc_issue(qc);
+       if (qc->err_mask)
                ata_qc_complete(qc);
-       }
 
        DPRINTK("EXIT\n");
 }
 
-static int atapi_qc_complete(struct ata_queued_cmd *qc)
+static void atapi_qc_complete(struct ata_queued_cmd *qc)
 {
        struct scsi_cmnd *cmd = qc->scsicmd;
        unsigned int err_mask = qc->err_mask;
@@ -2093,7 +2186,7 @@ static int atapi_qc_complete(struct ata_queued_cmd *qc)
        if (unlikely(err_mask & AC_ERR_DEV)) {
                cmd->result = SAM_STAT_CHECK_CONDITION;
                atapi_request_sense(qc);
-               return 1;
+               return;
        }
 
        else if (unlikely(err_mask))
@@ -2133,7 +2226,7 @@ static int atapi_qc_complete(struct ata_queued_cmd *qc)
        }
 
        qc->scsidone(cmd);
-       return 0;
+       ata_qc_free(qc);
 }
 /**
  *     atapi_xlat - Initialize PACKET taskfile
@@ -2159,7 +2252,7 @@ static unsigned int atapi_xlat(struct ata_queued_cmd *qc, const u8 *scsicmd)
                if (ata_check_atapi_dma(qc))
                        using_pio = 1;
 
-       memcpy(&qc->cdb, scsicmd, qc->ap->cdb_len);
+       memcpy(&qc->cdb, scsicmd, dev->cdb_len);
 
        qc->complete_fn = atapi_qc_complete;
 
@@ -2519,7 +2612,8 @@ out_unlock:
 
 /**
  *     ata_scsi_simulate - simulate SCSI command on ATA device
- *     @id: current IDENTIFY data for target device.
+ *     @ap: port the device is connected to
+ *     @dev: the target device
  *     @cmd: SCSI command being sent to device.
  *     @done: SCSI command completion function.
  *
index fddaf479a5440ff08c12d6e22c49f9e373814731..f4c48c91b63d643635ee8e7779a61c76c0f5b5a4 100644 (file)
@@ -45,8 +45,9 @@ extern int libata_fua;
 extern struct ata_queued_cmd *ata_qc_new_init(struct ata_port *ap,
                                      struct ata_device *dev);
 extern int ata_rwcmd_protocol(struct ata_queued_cmd *qc);
+extern void ata_port_flush_task(struct ata_port *ap);
 extern void ata_qc_free(struct ata_queued_cmd *qc);
-extern int ata_qc_issue(struct ata_queued_cmd *qc);
+extern unsigned int ata_qc_issue(struct ata_queued_cmd *qc);
 extern int ata_check_atapi_dma(struct ata_queued_cmd *qc);
 extern void ata_dev_select(struct ata_port *ap, unsigned int device,
                            unsigned int wait, unsigned int can_sleep);
index e8df0c9ec1e646992c5e3354d04868da4dba2d3f..5f33cc932e70dfb20dca425183238cdb406820d7 100644 (file)
@@ -131,7 +131,7 @@ static void adma_host_stop(struct ata_host_set *host_set);
 static void adma_port_stop(struct ata_port *ap);
 static void adma_phy_reset(struct ata_port *ap);
 static void adma_qc_prep(struct ata_queued_cmd *qc);
-static int adma_qc_issue(struct ata_queued_cmd *qc);
+static unsigned int adma_qc_issue(struct ata_queued_cmd *qc);
 static int adma_check_atapi_dma(struct ata_queued_cmd *qc);
 static void adma_bmdma_stop(struct ata_queued_cmd *qc);
 static u8 adma_bmdma_status(struct ata_port *ap);
@@ -143,11 +143,11 @@ static struct scsi_host_template adma_ata_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         = ENABLE_CLUSTERING,
@@ -419,7 +419,7 @@ static inline void adma_packet_start(struct ata_queued_cmd *qc)
        writew(aPIOMD4 | aGO, chan + ADMA_CONTROL);
 }
 
-static int adma_qc_issue(struct ata_queued_cmd *qc)
+static unsigned int adma_qc_issue(struct ata_queued_cmd *qc)
 {
        struct adma_port_priv *pp = qc->ap->private_data;
 
index 2770005324b4bac76781154ffe6543ecda049a82..aceaf56999a55156a6dc4824174daaaedbc6a481 100644 (file)
@@ -37,7 +37,7 @@
 #include <asm/io.h>
 
 #define DRV_NAME       "sata_mv"
-#define DRV_VERSION    "0.5"
+#define DRV_VERSION    "0.6"
 
 enum {
        /* BAR's are enumerated in terms of pci_resource_start() terms */
@@ -228,7 +228,9 @@ enum {
        MV_HP_ERRATA_50XXB2     = (1 << 2),
        MV_HP_ERRATA_60X1B2     = (1 << 3),
        MV_HP_ERRATA_60X1C0     = (1 << 4),
-       MV_HP_50XX              = (1 << 5),
+       MV_HP_ERRATA_XX42A0     = (1 << 5),
+       MV_HP_50XX              = (1 << 6),
+       MV_HP_GEN_IIE           = (1 << 7),
 
        /* Port private flags (pp_flags) */
        MV_PP_FLAG_EDMA_EN      = (1 << 0),
@@ -237,6 +239,9 @@ enum {
 
 #define IS_50XX(hpriv) ((hpriv)->hp_flags & MV_HP_50XX)
 #define IS_60XX(hpriv) (((hpriv)->hp_flags & MV_HP_50XX) == 0)
+#define IS_GEN_I(hpriv) IS_50XX(hpriv)
+#define IS_GEN_II(hpriv) IS_60XX(hpriv)
+#define IS_GEN_IIE(hpriv) ((hpriv)->hp_flags & MV_HP_GEN_IIE)
 
 enum {
        /* Our DMA boundary is determined by an ePRD being unable to handle
@@ -255,6 +260,8 @@ enum chip_type {
        chip_5080,
        chip_604x,
        chip_608x,
+       chip_6042,
+       chip_7042,
 };
 
 /* Command ReQuest Block: 32B */
@@ -265,6 +272,14 @@ struct mv_crqb {
        u16                     ata_cmd[11];
 };
 
+struct mv_crqb_iie {
+       u32                     addr;
+       u32                     addr_hi;
+       u32                     flags;
+       u32                     len;
+       u32                     ata_cmd[4];
+};
+
 /* Command ResPonse Block: 8B */
 struct mv_crpb {
        u16                     id;
@@ -328,7 +343,8 @@ static void mv_host_stop(struct ata_host_set *host_set);
 static int mv_port_start(struct ata_port *ap);
 static void mv_port_stop(struct ata_port *ap);
 static void mv_qc_prep(struct ata_queued_cmd *qc);
-static int mv_qc_issue(struct ata_queued_cmd *qc);
+static void mv_qc_prep_iie(struct ata_queued_cmd *qc);
+static unsigned int mv_qc_issue(struct ata_queued_cmd *qc);
 static irqreturn_t mv_interrupt(int irq, void *dev_instance,
                                struct pt_regs *regs);
 static void mv_eng_timeout(struct ata_port *ap);
@@ -362,11 +378,11 @@ static struct scsi_host_template mv_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              = MV_USE_Q_DEPTH,
        .this_id                = ATA_SHT_THIS_ID,
        .sg_tablesize           = MV_MAX_SG_CT / 2,
-       .max_sectors            = ATA_MAX_SECTORS,
        .cmd_per_lun            = ATA_SHT_CMD_PER_LUN,
        .emulated               = ATA_SHT_EMULATED,
        .use_clustering         = ATA_SHT_USE_CLUSTERING,
@@ -430,6 +446,33 @@ static const struct ata_port_operations mv6_ops = {
        .host_stop              = mv_host_stop,
 };
 
+static const struct ata_port_operations mv_iie_ops = {
+       .port_disable           = ata_port_disable,
+
+       .tf_load                = ata_tf_load,
+       .tf_read                = ata_tf_read,
+       .check_status           = ata_check_status,
+       .exec_command           = ata_exec_command,
+       .dev_select             = ata_std_dev_select,
+
+       .phy_reset              = mv_phy_reset,
+
+       .qc_prep                = mv_qc_prep_iie,
+       .qc_issue               = mv_qc_issue,
+
+       .eng_timeout            = mv_eng_timeout,
+
+       .irq_handler            = mv_interrupt,
+       .irq_clear              = mv_irq_clear,
+
+       .scr_read               = mv_scr_read,
+       .scr_write              = mv_scr_write,
+
+       .port_start             = mv_port_start,
+       .port_stop              = mv_port_stop,
+       .host_stop              = mv_host_stop,
+};
+
 static const struct ata_port_info mv_port_info[] = {
        {  /* chip_504x */
                .sht            = &mv_sht,
@@ -467,6 +510,21 @@ static const struct ata_port_info mv_port_info[] = {
                .udma_mask      = 0x7f, /* udma0-6 */
                .port_ops       = &mv6_ops,
        },
+       {  /* chip_6042 */
+               .sht            = &mv_sht,
+               .host_flags     = (MV_COMMON_FLAGS | MV_6XXX_FLAGS),
+               .pio_mask       = 0x1f, /* pio0-4 */
+               .udma_mask      = 0x7f, /* udma0-6 */
+               .port_ops       = &mv_iie_ops,
+       },
+       {  /* chip_7042 */
+               .sht            = &mv_sht,
+               .host_flags     = (MV_COMMON_FLAGS | MV_6XXX_FLAGS |
+                                  MV_FLAG_DUAL_HC),
+               .pio_mask       = 0x1f, /* pio0-4 */
+               .udma_mask      = 0x7f, /* udma0-6 */
+               .port_ops       = &mv_iie_ops,
+       },
 };
 
 static const struct pci_device_id mv_pci_tbl[] = {
@@ -477,6 +535,7 @@ static const struct pci_device_id mv_pci_tbl[] = {
 
        {PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x6040), 0, 0, chip_604x},
        {PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x6041), 0, 0, chip_604x},
+       {PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x6042), 0, 0, chip_6042},
        {PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x6080), 0, 0, chip_608x},
        {PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x6081), 0, 0, chip_608x},
 
@@ -572,8 +631,8 @@ static void mv_irq_clear(struct ata_port *ap)
  *      @base: port base address
  *      @pp: port private data
  *
- *      Verify the local cache of the eDMA state is accurate with an
- *      assert.
+ *      Verify the local cache of the eDMA state is accurate with a
+ *      WARN_ON.
  *
  *      LOCKING:
  *      Inherited from caller.
@@ -584,15 +643,15 @@ static void mv_start_dma(void __iomem *base, struct mv_port_priv *pp)
                writelfl(EDMA_EN, base + EDMA_CMD_OFS);
                pp->pp_flags |= MV_PP_FLAG_EDMA_EN;
        }
-       assert(EDMA_EN & readl(base + EDMA_CMD_OFS));
+       WARN_ON(!(EDMA_EN & readl(base + EDMA_CMD_OFS)));
 }
 
 /**
  *      mv_stop_dma - Disable eDMA engine
  *      @ap: ATA channel to manipulate
  *
- *      Verify the local cache of the eDMA state is accurate with an
- *      assert.
+ *      Verify the local cache of the eDMA state is accurate with a
+ *      WARN_ON.
  *
  *      LOCKING:
  *      Inherited from caller.
@@ -610,7 +669,7 @@ static void mv_stop_dma(struct ata_port *ap)
                writelfl(EDMA_DS, port_mmio + EDMA_CMD_OFS);
                pp->pp_flags &= ~MV_PP_FLAG_EDMA_EN;
        } else {
-               assert(!(EDMA_EN & readl(port_mmio + EDMA_CMD_OFS)));
+               WARN_ON(EDMA_EN & readl(port_mmio + EDMA_CMD_OFS));
        }
 
        /* now properly wait for the eDMA to stop */
@@ -773,6 +832,33 @@ static inline void mv_priv_free(struct mv_port_priv *pp, struct device *dev)
        dma_free_coherent(dev, MV_PORT_PRIV_DMA_SZ, pp->crpb, pp->crpb_dma);
 }
 
+static void mv_edma_cfg(struct mv_host_priv *hpriv, void __iomem *port_mmio)
+{
+       u32 cfg = readl(port_mmio + EDMA_CFG_OFS);
+
+       /* set up non-NCQ EDMA configuration */
+       cfg &= ~0x1f;           /* clear queue depth */
+       cfg &= ~EDMA_CFG_NCQ;   /* clear NCQ mode */
+       cfg &= ~(1 << 9);       /* disable equeue */
+
+       if (IS_GEN_I(hpriv))
+               cfg |= (1 << 8);        /* enab config burst size mask */
+
+       else if (IS_GEN_II(hpriv))
+               cfg |= EDMA_CFG_RD_BRST_EXT | EDMA_CFG_WR_BUFF_LEN;
+
+       else if (IS_GEN_IIE(hpriv)) {
+               cfg |= (1 << 23);       /* dis RX PM port mask */
+               cfg &= ~(1 << 16);      /* dis FIS-based switching (for now) */
+               cfg &= ~(1 << 19);      /* dis 128-entry queue (for now?) */
+               cfg |= (1 << 18);       /* enab early completion */
+               cfg |= (1 << 17);       /* enab host q cache */
+               cfg |= (1 << 22);       /* enab cutthrough */
+       }
+
+       writelfl(cfg, port_mmio + EDMA_CFG_OFS);
+}
+
 /**
  *      mv_port_start - Port specific init/start routine.
  *      @ap: ATA channel to manipulate
@@ -786,6 +872,7 @@ static inline void mv_priv_free(struct mv_port_priv *pp, struct device *dev)
 static int mv_port_start(struct ata_port *ap)
 {
        struct device *dev = ap->host_set->dev;
+       struct mv_host_priv *hpriv = ap->host_set->private_data;
        struct mv_port_priv *pp;
        void __iomem *port_mmio = mv_ap_base(ap);
        void *mem;
@@ -829,17 +916,26 @@ static int mv_port_start(struct ata_port *ap)
        pp->sg_tbl = mem;
        pp->sg_tbl_dma = mem_dma;
 
-       writelfl(EDMA_CFG_Q_DEPTH | EDMA_CFG_RD_BRST_EXT |
-                EDMA_CFG_WR_BUFF_LEN, port_mmio + EDMA_CFG_OFS);
+       mv_edma_cfg(hpriv, port_mmio);
 
        writel((pp->crqb_dma >> 16) >> 16, port_mmio + EDMA_REQ_Q_BASE_HI_OFS);
        writelfl(pp->crqb_dma & EDMA_REQ_Q_BASE_LO_MASK,
                 port_mmio + EDMA_REQ_Q_IN_PTR_OFS);
 
-       writelfl(0, port_mmio + EDMA_REQ_Q_OUT_PTR_OFS);
-       writelfl(0, port_mmio + EDMA_RSP_Q_IN_PTR_OFS);
+       if (hpriv->hp_flags & MV_HP_ERRATA_XX42A0)
+               writelfl(pp->crqb_dma & 0xffffffff,
+                        port_mmio + EDMA_REQ_Q_OUT_PTR_OFS);
+       else
+               writelfl(0, port_mmio + EDMA_REQ_Q_OUT_PTR_OFS);
 
        writel((pp->crpb_dma >> 16) >> 16, port_mmio + EDMA_RSP_Q_BASE_HI_OFS);
+
+       if (hpriv->hp_flags & MV_HP_ERRATA_XX42A0)
+               writelfl(pp->crpb_dma & 0xffffffff,
+                        port_mmio + EDMA_RSP_Q_IN_PTR_OFS);
+       else
+               writelfl(0, port_mmio + EDMA_RSP_Q_IN_PTR_OFS);
+
        writelfl(pp->crpb_dma & EDMA_RSP_Q_BASE_LO_MASK,
                 port_mmio + EDMA_RSP_Q_OUT_PTR_OFS);
 
@@ -960,21 +1056,19 @@ static void mv_qc_prep(struct ata_queued_cmd *qc)
        struct ata_taskfile *tf;
        u16 flags = 0;
 
-       if (ATA_PROT_DMA != qc->tf.protocol) {
+       if (ATA_PROT_DMA != qc->tf.protocol)
                return;
-       }
 
        /* the req producer index should be the same as we remember it */
-       assert(((readl(mv_ap_base(qc->ap) + EDMA_REQ_Q_IN_PTR_OFS) >>
-                EDMA_REQ_Q_PTR_SHIFT) & MV_MAX_Q_DEPTH_MASK) ==
-              pp->req_producer);
+       WARN_ON(((readl(mv_ap_base(qc->ap) + EDMA_REQ_Q_IN_PTR_OFS) >>
+                 EDMA_REQ_Q_PTR_SHIFT) & MV_MAX_Q_DEPTH_MASK) !=
+               pp->req_producer);
 
        /* Fill in command request block
         */
-       if (!(qc->tf.flags & ATA_TFLAG_WRITE)) {
+       if (!(qc->tf.flags & ATA_TFLAG_WRITE))
                flags |= CRQB_FLAG_READ;
-       }
-       assert(MV_MAX_Q_DEPTH > qc->tag);
+       WARN_ON(MV_MAX_Q_DEPTH <= qc->tag);
        flags |= qc->tag << CRQB_TAG_SHIFT;
 
        pp->crqb[pp->req_producer].sg_addr =
@@ -1029,9 +1123,76 @@ static void mv_qc_prep(struct ata_queued_cmd *qc)
        mv_crqb_pack_cmd(cw++, tf->device, ATA_REG_DEVICE, 0);
        mv_crqb_pack_cmd(cw++, tf->command, ATA_REG_CMD, 1);    /* last */
 
-       if (!(qc->flags & ATA_QCFLAG_DMAMAP)) {
+       if (!(qc->flags & ATA_QCFLAG_DMAMAP))
+               return;
+       mv_fill_sg(qc);
+}
+
+/**
+ *      mv_qc_prep_iie - Host specific command preparation.
+ *      @qc: queued command to prepare
+ *
+ *      This routine simply redirects to the general purpose routine
+ *      if command is not DMA.  Else, it handles prep of the CRQB
+ *      (command request block), does some sanity checking, and calls
+ *      the SG load routine.
+ *
+ *      LOCKING:
+ *      Inherited from caller.
+ */
+static void mv_qc_prep_iie(struct ata_queued_cmd *qc)
+{
+       struct ata_port *ap = qc->ap;
+       struct mv_port_priv *pp = ap->private_data;
+       struct mv_crqb_iie *crqb;
+       struct ata_taskfile *tf;
+       u32 flags = 0;
+
+       if (ATA_PROT_DMA != qc->tf.protocol)
+               return;
+
+       /* the req producer index should be the same as we remember it */
+       WARN_ON(((readl(mv_ap_base(qc->ap) + EDMA_REQ_Q_IN_PTR_OFS) >>
+                 EDMA_REQ_Q_PTR_SHIFT) & MV_MAX_Q_DEPTH_MASK) !=
+               pp->req_producer);
+
+       /* Fill in Gen IIE command request block
+        */
+       if (!(qc->tf.flags & ATA_TFLAG_WRITE))
+               flags |= CRQB_FLAG_READ;
+
+       WARN_ON(MV_MAX_Q_DEPTH <= qc->tag);
+       flags |= qc->tag << CRQB_TAG_SHIFT;
+
+       crqb = (struct mv_crqb_iie *) &pp->crqb[pp->req_producer];
+       crqb->addr = cpu_to_le32(pp->sg_tbl_dma & 0xffffffff);
+       crqb->addr_hi = cpu_to_le32((pp->sg_tbl_dma >> 16) >> 16);
+       crqb->flags = cpu_to_le32(flags);
+
+       tf = &qc->tf;
+       crqb->ata_cmd[0] = cpu_to_le32(
+                       (tf->command << 16) |
+                       (tf->feature << 24)
+               );
+       crqb->ata_cmd[1] = cpu_to_le32(
+                       (tf->lbal << 0) |
+                       (tf->lbam << 8) |
+                       (tf->lbah << 16) |
+                       (tf->device << 24)
+               );
+       crqb->ata_cmd[2] = cpu_to_le32(
+                       (tf->hob_lbal << 0) |
+                       (tf->hob_lbam << 8) |
+                       (tf->hob_lbah << 16) |
+                       (tf->hob_feature << 24)
+               );
+       crqb->ata_cmd[3] = cpu_to_le32(
+                       (tf->nsect << 0) |
+                       (tf->hob_nsect << 8)
+               );
+
+       if (!(qc->flags & ATA_QCFLAG_DMAMAP))
                return;
-       }
        mv_fill_sg(qc);
 }
 
@@ -1047,7 +1208,7 @@ static void mv_qc_prep(struct ata_queued_cmd *qc)
  *      LOCKING:
  *      Inherited from caller.
  */
-static int mv_qc_issue(struct ata_queued_cmd *qc)
+static unsigned int mv_qc_issue(struct ata_queued_cmd *qc)
 {
        void __iomem *port_mmio = mv_ap_base(qc->ap);
        struct mv_port_priv *pp = qc->ap->private_data;
@@ -1065,12 +1226,12 @@ static int mv_qc_issue(struct ata_queued_cmd *qc)
        in_ptr = readl(port_mmio + EDMA_REQ_Q_IN_PTR_OFS);
 
        /* the req producer index should be the same as we remember it */
-       assert(((in_ptr >> EDMA_REQ_Q_PTR_SHIFT) & MV_MAX_Q_DEPTH_MASK) ==
-              pp->req_producer);
+       WARN_ON(((in_ptr >> EDMA_REQ_Q_PTR_SHIFT) & MV_MAX_Q_DEPTH_MASK) !=
+               pp->req_producer);
        /* until we do queuing, the queue should be empty at this point */
-       assert(((in_ptr >> EDMA_REQ_Q_PTR_SHIFT) & MV_MAX_Q_DEPTH_MASK) ==
-              ((readl(port_mmio + EDMA_REQ_Q_OUT_PTR_OFS) >>
-                EDMA_REQ_Q_PTR_SHIFT) & MV_MAX_Q_DEPTH_MASK));
+       WARN_ON(((in_ptr >> EDMA_REQ_Q_PTR_SHIFT) & MV_MAX_Q_DEPTH_MASK) !=
+               ((readl(port_mmio + EDMA_REQ_Q_OUT_PTR_OFS) >>
+                 EDMA_REQ_Q_PTR_SHIFT) & MV_MAX_Q_DEPTH_MASK));
 
        mv_inc_q_index(&pp->req_producer);      /* now incr producer index */
 
@@ -1090,7 +1251,7 @@ static int mv_qc_issue(struct ata_queued_cmd *qc)
  *
  *      This routine is for use when the port is in DMA mode, when it
  *      will be using the CRPB (command response block) method of
- *      returning command completion information.  We assert indices
+ *      returning command completion information.  We check indices
  *      are good, grab status, and bump the response consumer index to
  *      prove that we're up to date.
  *
@@ -1106,16 +1267,16 @@ static u8 mv_get_crpb_status(struct ata_port *ap)
        out_ptr = readl(port_mmio + EDMA_RSP_Q_OUT_PTR_OFS);
 
        /* the response consumer index should be the same as we remember it */
-       assert(((out_ptr >> EDMA_RSP_Q_PTR_SHIFT) & MV_MAX_Q_DEPTH_MASK) ==
-              pp->rsp_consumer);
+       WARN_ON(((out_ptr >> EDMA_RSP_Q_PTR_SHIFT) & MV_MAX_Q_DEPTH_MASK) !=
+               pp->rsp_consumer);
 
        /* increment our consumer index... */
        pp->rsp_consumer = mv_inc_q_index(&pp->rsp_consumer);
 
        /* and, until we do NCQ, there should only be 1 CRPB waiting */
-       assert(((readl(port_mmio + EDMA_RSP_Q_IN_PTR_OFS) >>
-                EDMA_RSP_Q_PTR_SHIFT) & MV_MAX_Q_DEPTH_MASK) ==
-              pp->rsp_consumer);
+       WARN_ON(((readl(port_mmio + EDMA_RSP_Q_IN_PTR_OFS) >>
+                 EDMA_RSP_Q_PTR_SHIFT) & MV_MAX_Q_DEPTH_MASK) !=
+               pp->rsp_consumer);
 
        /* write out our inc'd consumer index so EDMA knows we're caught up */
        out_ptr &= EDMA_RSP_Q_BASE_LO_MASK;
@@ -1681,6 +1842,12 @@ static void mv6_phy_errata(struct mv_host_priv *hpriv, void __iomem *mmio,
        m2 |= hpriv->signal[port].pre;
        m2 &= ~(1 << 16);
 
+       /* according to mvSata 3.6.1, some IIE values are fixed */
+       if (IS_GEN_IIE(hpriv)) {
+               m2 &= ~0xC30FF01F;
+               m2 |= 0x0000900F;
+       }
+
        writel(m2, port_mmio + PHY_MODE2);
 }
 
@@ -1846,7 +2013,6 @@ static void mv_phy_reset(struct ata_port *ap)
 static void mv_eng_timeout(struct ata_port *ap)
 {
        struct ata_queued_cmd *qc;
-       unsigned long flags;
 
        printk(KERN_ERR "ata%u: Entering mv_eng_timeout\n",ap->id);
        DPRINTK("All regs @ start of eng_timeout\n");
@@ -1861,22 +2027,8 @@ static void mv_eng_timeout(struct ata_port *ap)
        mv_err_intr(ap);
        mv_stop_and_reset(ap);
 
-       if (!qc) {
-               printk(KERN_ERR "ata%u: BUG: timeout without command\n",
-                      ap->id);
-       } else {
-               /* hack alert!  We cannot use the supplied completion
-                * function from inside the ->eh_strategy_handler() thread.
-                * libata is the only user of ->eh_strategy_handler() in
-                * any kernel, so the default scsi_done() assumes it is
-                * not being called from the SCSI EH.
-                */
-               spin_lock_irqsave(&ap->host_set->lock, flags);
-               qc->scsidone = scsi_finish_command;
-               qc->err_mask |= AC_ERR_OTHER;
-               ata_qc_complete(qc);
-               spin_unlock_irqrestore(&ap->host_set->lock, flags);
-       }
+       qc->err_mask |= AC_ERR_TIMEOUT;
+       ata_eh_qc_complete(qc);
 }
 
 /**
@@ -1995,6 +2147,27 @@ static int mv_chip_id(struct pci_dev *pdev, struct mv_host_priv *hpriv,
                }
                break;
 
+       case chip_7042:
+       case chip_6042:
+               hpriv->ops = &mv6xxx_ops;
+
+               hp_flags |= MV_HP_GEN_IIE;
+
+               switch (rev_id) {
+               case 0x0:
+                       hp_flags |= MV_HP_ERRATA_XX42A0;
+                       break;
+               case 0x1:
+                       hp_flags |= MV_HP_ERRATA_60X1C0;
+                       break;
+               default:
+                       dev_printk(KERN_WARNING, &pdev->dev,
+                          "Applying 60X1C0 workarounds to unknown rev\n");
+                       hp_flags |= MV_HP_ERRATA_60X1C0;
+                       break;
+               }
+               break;
+
        default:
                printk(KERN_ERR DRV_NAME ": BUG: invalid board index %u\n", board_idx);
                return 1;
index bbbb55eeb73a521d52797bf9da858fbad7040911..caffadc2e0aed630b6ceeac6d3f6802c85cae33e 100644 (file)
@@ -229,11 +229,11 @@ static struct scsi_host_template nv_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,
index b0b0a69b3563c67a896f83517ae3b609a30aa011..84cb3940ad8821a2f96aa861c131353472b7f72d 100644 (file)
@@ -46,7 +46,7 @@
 #include "sata_promise.h"
 
 #define DRV_NAME       "sata_promise"
-#define DRV_VERSION    "1.03"
+#define DRV_VERSION    "1.04"
 
 
 enum {
@@ -58,6 +58,7 @@ enum {
        PDC_GLOBAL_CTL          = 0x48, /* Global control/status (per port) */
        PDC_CTLSTAT             = 0x60, /* IDE control and status (per port) */
        PDC_SATA_PLUG_CSR       = 0x6C, /* SATA Plug control/status reg */
+       PDC2_SATA_PLUG_CSR      = 0x60, /* SATAII Plug control/status reg */
        PDC_SLEW_CTL            = 0x470, /* slew rate control reg */
 
        PDC_ERR_MASK            = (1<<19) | (1<<20) | (1<<21) | (1<<22) |
@@ -67,8 +68,10 @@ enum {
        board_20319             = 1,    /* FastTrak S150 TX4 */
        board_20619             = 2,    /* FastTrak TX4000 */
        board_20771             = 3,    /* FastTrak TX2300 */
+       board_2057x             = 4,    /* SATAII150 Tx2plus */
+       board_40518             = 5,    /* SATAII150 Tx4 */
 
-       PDC_HAS_PATA            = (1 << 1), /* PDC20375 has PATA */
+       PDC_HAS_PATA            = (1 << 1), /* PDC20375/20575 has PATA */
 
        PDC_RESET               = (1 << 11), /* HDMA reset */
 
@@ -82,6 +85,10 @@ struct pdc_port_priv {
        dma_addr_t              pkt_dma;
 };
 
+struct pdc_host_priv {
+       int                     hotplug_offset;
+};
+
 static u32 pdc_sata_scr_read (struct ata_port *ap, unsigned int sc_reg);
 static void pdc_sata_scr_write (struct ata_port *ap, unsigned int sc_reg, u32 val);
 static int pdc_ata_init_one (struct pci_dev *pdev, const struct pci_device_id *ent);
@@ -95,7 +102,8 @@ static void pdc_qc_prep(struct ata_queued_cmd *qc);
 static void pdc_tf_load_mmio(struct ata_port *ap, const struct ata_taskfile *tf);
 static void pdc_exec_command_mmio(struct ata_port *ap, const struct ata_taskfile *tf);
 static void pdc_irq_clear(struct ata_port *ap);
-static int pdc_qc_issue_prot(struct ata_queued_cmd *qc);
+static unsigned int pdc_qc_issue_prot(struct ata_queued_cmd *qc);
+static void pdc_host_stop(struct ata_host_set *host_set);
 
 
 static struct scsi_host_template pdc_ata_sht = {
@@ -103,11 +111,11 @@ static struct scsi_host_template pdc_ata_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,
@@ -137,7 +145,7 @@ static const struct ata_port_operations pdc_sata_ops = {
        .scr_write              = pdc_sata_scr_write,
        .port_start             = pdc_port_start,
        .port_stop              = pdc_port_stop,
-       .host_stop              = ata_pci_host_stop,
+       .host_stop              = pdc_host_stop,
 };
 
 static const struct ata_port_operations pdc_pata_ops = {
@@ -158,7 +166,7 @@ static const struct ata_port_operations pdc_pata_ops = {
 
        .port_start             = pdc_port_start,
        .port_stop              = pdc_port_stop,
-       .host_stop              = ata_pci_host_stop,
+       .host_stop              = pdc_host_stop,
 };
 
 static const struct ata_port_info pdc_port_info[] = {
@@ -201,6 +209,26 @@ static const struct ata_port_info pdc_port_info[] = {
                .udma_mask      = 0x7f, /* udma0-6 ; FIXME */
                .port_ops       = &pdc_sata_ops,
        },
+
+       /* board_2057x */
+       {
+               .sht            = &pdc_ata_sht,
+               .host_flags     = PDC_COMMON_FLAGS | ATA_FLAG_SATA,
+               .pio_mask       = 0x1f, /* pio0-4 */
+               .mwdma_mask     = 0x07, /* mwdma0-2 */
+               .udma_mask      = 0x7f, /* udma0-6 ; FIXME */
+               .port_ops       = &pdc_sata_ops,
+       },
+
+       /* board_40518 */
+       {
+               .sht            = &pdc_ata_sht,
+               .host_flags     = PDC_COMMON_FLAGS | ATA_FLAG_SATA,
+               .pio_mask       = 0x1f, /* pio0-4 */
+               .mwdma_mask     = 0x07, /* mwdma0-2 */
+               .udma_mask      = 0x7f, /* udma0-6 ; FIXME */
+               .port_ops       = &pdc_sata_ops,
+       },
 };
 
 static const struct pci_device_id pdc_ata_pci_tbl[] = {
@@ -217,9 +245,9 @@ static const struct pci_device_id pdc_ata_pci_tbl[] = {
        { PCI_VENDOR_ID_PROMISE, 0x3376, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
          board_2037x },
        { PCI_VENDOR_ID_PROMISE, 0x3574, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-         board_2037x },
+         board_2057x },
        { PCI_VENDOR_ID_PROMISE, 0x3d75, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-         board_2037x },
+         board_2057x },
        { PCI_VENDOR_ID_PROMISE, 0x3d73, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
          board_2037x },
 
@@ -227,12 +255,14 @@ static const struct pci_device_id pdc_ata_pci_tbl[] = {
          board_20319 },
        { PCI_VENDOR_ID_PROMISE, 0x3319, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
          board_20319 },
+       { PCI_VENDOR_ID_PROMISE, 0x3515, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+         board_20319 },
        { PCI_VENDOR_ID_PROMISE, 0x3519, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
          board_20319 },
        { PCI_VENDOR_ID_PROMISE, 0x3d17, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
          board_20319 },
        { PCI_VENDOR_ID_PROMISE, 0x3d18, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-         board_20319 },
+         board_40518 },
 
        { PCI_VENDOR_ID_PROMISE, 0x6629, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
          board_20619 },
@@ -261,12 +291,11 @@ static int pdc_port_start(struct ata_port *ap)
        if (rc)
                return rc;
 
-       pp = kmalloc(sizeof(*pp), GFP_KERNEL);
+       pp = kzalloc(sizeof(*pp), GFP_KERNEL);
        if (!pp) {
                rc = -ENOMEM;
                goto err_out;
        }
-       memset(pp, 0, sizeof(*pp));
 
        pp->pkt = dma_alloc_coherent(dev, 128, &pp->pkt_dma, GFP_KERNEL);
        if (!pp->pkt) {
@@ -298,6 +327,16 @@ static void pdc_port_stop(struct ata_port *ap)
 }
 
 
+static void pdc_host_stop(struct ata_host_set *host_set)
+{
+       struct pdc_host_priv *hp = host_set->private_data;
+
+       ata_pci_host_stop(host_set);
+
+       kfree(hp);
+}
+
+
 static void pdc_reset_port(struct ata_port *ap)
 {
        void __iomem *mmio = (void __iomem *) ap->ioaddr.cmd_addr + PDC_CTLSTAT;
@@ -394,19 +433,6 @@ static void pdc_eng_timeout(struct ata_port *ap)
        spin_lock_irqsave(&host_set->lock, flags);
 
        qc = ata_qc_from_tag(ap, ap->active_tag);
-       if (!qc) {
-               printk(KERN_ERR "ata%u: BUG: timeout without command\n",
-                      ap->id);
-               goto out;
-       }
-
-       /* hack alert!  We cannot use the supplied completion
-        * function from inside the ->eh_strategy_handler() thread.
-        * libata is the only user of ->eh_strategy_handler() in
-        * any kernel, so the default scsi_done() assumes it is
-        * not being called from the SCSI EH.
-        */
-       qc->scsidone = scsi_finish_command;
 
        switch (qc->tf.protocol) {
        case ATA_PROT_DMA:
@@ -414,7 +440,6 @@ static void pdc_eng_timeout(struct ata_port *ap)
                printk(KERN_ERR "ata%u: command timeout\n", ap->id);
                drv_stat = ata_wait_idle(ap);
                qc->err_mask |= __ac_err_mask(drv_stat);
-               ata_qc_complete(qc);
                break;
 
        default:
@@ -424,12 +449,11 @@ static void pdc_eng_timeout(struct ata_port *ap)
                       ap->id, qc->tf.command, drv_stat);
 
                qc->err_mask |= ac_err_mask(drv_stat);
-               ata_qc_complete(qc);
                break;
        }
 
-out:
        spin_unlock_irqrestore(&host_set->lock, flags);
+       ata_eh_qc_complete(qc);
        DPRINTK("EXIT\n");
 }
 
@@ -495,14 +519,15 @@ static irqreturn_t pdc_interrupt (int irq, void *dev_instance, struct pt_regs *r
                VPRINTK("QUICK EXIT 2\n");
                return IRQ_NONE;
        }
+
+       spin_lock(&host_set->lock);
+
        mask &= 0xffff;         /* only 16 tags possible */
        if (!mask) {
                VPRINTK("QUICK EXIT 3\n");
-               return IRQ_NONE;
+               goto done_irq;
        }
 
-       spin_lock(&host_set->lock);
-
        writel(mask, mmio_base + PDC_INT_SEQMASK);
 
        for (i = 0; i < host_set->n_ports; i++) {
@@ -519,10 +544,10 @@ static irqreturn_t pdc_interrupt (int irq, void *dev_instance, struct pt_regs *r
                }
        }
 
-        spin_unlock(&host_set->lock);
-
        VPRINTK("EXIT\n");
 
+done_irq:
+       spin_unlock(&host_set->lock);
        return IRQ_RETVAL(handled);
 }
 
@@ -544,7 +569,7 @@ static inline void pdc_packet_start(struct ata_queued_cmd *qc)
        readl((void __iomem *) ap->ioaddr.cmd_addr + PDC_PKT_SUBMIT); /* flush */
 }
 
-static int pdc_qc_issue_prot(struct ata_queued_cmd *qc)
+static unsigned int pdc_qc_issue_prot(struct ata_queued_cmd *qc)
 {
        switch (qc->tf.protocol) {
        case ATA_PROT_DMA:
@@ -600,6 +625,8 @@ static void pdc_ata_setup_port(struct ata_ioports *port, unsigned long base)
 static void pdc_host_init(unsigned int chip_id, struct ata_probe_ent *pe)
 {
        void __iomem *mmio = pe->mmio_base;
+       struct pdc_host_priv *hp = pe->private_data;
+       int hotplug_offset = hp->hotplug_offset;
        u32 tmp;
 
        /*
@@ -614,12 +641,12 @@ static void pdc_host_init(unsigned int chip_id, struct ata_probe_ent *pe)
        writel(tmp, mmio + PDC_FLASH_CTL);
 
        /* clear plug/unplug flags for all ports */
-       tmp = readl(mmio + PDC_SATA_PLUG_CSR);
-       writel(tmp | 0xff, mmio + PDC_SATA_PLUG_CSR);
+       tmp = readl(mmio + hotplug_offset);
+       writel(tmp | 0xff, mmio + hotplug_offset);
 
        /* mask plug/unplug ints */
-       tmp = readl(mmio + PDC_SATA_PLUG_CSR);
-       writel(tmp | 0xff0000, mmio + PDC_SATA_PLUG_CSR);
+       tmp = readl(mmio + hotplug_offset);
+       writel(tmp | 0xff0000, mmio + hotplug_offset);
 
        /* reduce TBG clock to 133 Mhz. */
        tmp = readl(mmio + PDC_TBG_MODE);
@@ -641,6 +668,7 @@ static int pdc_ata_init_one (struct pci_dev *pdev, const struct pci_device_id *e
 {
        static int printed_version;
        struct ata_probe_ent *probe_ent = NULL;
+       struct pdc_host_priv *hp;
        unsigned long base;
        void __iomem *mmio_base;
        unsigned int board_idx = (unsigned int) ent->driver_data;
@@ -671,13 +699,12 @@ static int pdc_ata_init_one (struct pci_dev *pdev, const struct pci_device_id *e
        if (rc)
                goto err_out_regions;
 
-       probe_ent = kmalloc(sizeof(*probe_ent), GFP_KERNEL);
+       probe_ent = kzalloc(sizeof(*probe_ent), GFP_KERNEL);
        if (probe_ent == NULL) {
                rc = -ENOMEM;
                goto err_out_regions;
        }
 
-       memset(probe_ent, 0, sizeof(*probe_ent));
        probe_ent->dev = pci_dev_to_dev(pdev);
        INIT_LIST_HEAD(&probe_ent->node);
 
@@ -688,6 +715,16 @@ static int pdc_ata_init_one (struct pci_dev *pdev, const struct pci_device_id *e
        }
        base = (unsigned long) mmio_base;
 
+       hp = kzalloc(sizeof(*hp), GFP_KERNEL);
+       if (hp == NULL) {
+               rc = -ENOMEM;
+               goto err_out_free_ent;
+       }
+
+       /* Set default hotplug offset */
+       hp->hotplug_offset = PDC_SATA_PLUG_CSR;
+       probe_ent->private_data = hp;
+
        probe_ent->sht          = pdc_port_info[board_idx].sht;
        probe_ent->host_flags   = pdc_port_info[board_idx].host_flags;
        probe_ent->pio_mask     = pdc_port_info[board_idx].pio_mask;
@@ -707,6 +744,10 @@ static int pdc_ata_init_one (struct pci_dev *pdev, const struct pci_device_id *e
 
        /* notice 4-port boards */
        switch (board_idx) {
+       case board_40518:
+               /* Override hotplug offset for SATAII150 */
+               hp->hotplug_offset = PDC2_SATA_PLUG_CSR;
+               /* Fall through */
        case board_20319:
                        probe_ent->n_ports = 4;
 
@@ -716,6 +757,10 @@ static int pdc_ata_init_one (struct pci_dev *pdev, const struct pci_device_id *e
                probe_ent->port[2].scr_addr = base + 0x600;
                probe_ent->port[3].scr_addr = base + 0x700;
                break;
+       case board_2057x:
+               /* Override hotplug offset for SATAII150 */
+               hp->hotplug_offset = PDC2_SATA_PLUG_CSR;
+               /* Fall through */
        case board_2037x:
                probe_ent->n_ports = 2;
                break;
@@ -741,8 +786,10 @@ static int pdc_ata_init_one (struct pci_dev *pdev, const struct pci_device_id *e
        /* initialize adapter */
        pdc_host_init(board_idx, probe_ent);
 
-       /* FIXME: check ata_device_add return value */
-       ata_device_add(probe_ent);
+       /* FIXME: Need any other frees than hp? */
+       if (!ata_device_add(probe_ent))
+               kfree(hp);
+
        kfree(probe_ent);
 
        return 0;
index 80480f0fb2b82abf2ebdcbe156abd994d9b9ff27..9602f43a298e1a2c7290e461ff00d7f6dcf479ef 100644 (file)
@@ -120,7 +120,7 @@ static void qs_host_stop(struct ata_host_set *host_set);
 static void qs_port_stop(struct ata_port *ap);
 static void qs_phy_reset(struct ata_port *ap);
 static void qs_qc_prep(struct ata_queued_cmd *qc);
-static int qs_qc_issue(struct ata_queued_cmd *qc);
+static unsigned int qs_qc_issue(struct ata_queued_cmd *qc);
 static int qs_check_atapi_dma(struct ata_queued_cmd *qc);
 static void qs_bmdma_stop(struct ata_queued_cmd *qc);
 static u8 qs_bmdma_status(struct ata_port *ap);
@@ -132,11 +132,11 @@ static struct scsi_host_template qs_ata_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           = QS_MAX_PRD,
-       .max_sectors            = ATA_MAX_SECTORS,
        .cmd_per_lun            = ATA_SHT_CMD_PER_LUN,
        .emulated               = ATA_SHT_EMULATED,
        //FIXME .use_clustering         = ATA_SHT_USE_CLUSTERING,
@@ -276,8 +276,8 @@ static unsigned int qs_fill_sg(struct ata_queued_cmd *qc)
        unsigned int nelem;
        u8 *prd = pp->pkt + QS_CPB_BYTES;
 
-       assert(qc->__sg != NULL);
-       assert(qc->n_elem > 0 || qc->pad_len > 0);
+       WARN_ON(qc->__sg == NULL);
+       WARN_ON(qc->n_elem == 0 && qc->pad_len == 0);
 
        nelem = 0;
        ata_for_each_sg(sg, qc) {
@@ -352,7 +352,7 @@ static inline void qs_packet_start(struct ata_queued_cmd *qc)
        readl(chan + QS_CCT_CFF);          /* flush */
 }
 
-static int qs_qc_issue(struct ata_queued_cmd *qc)
+static unsigned int qs_qc_issue(struct ata_queued_cmd *qc)
 {
        struct qs_port_priv *pp = qc->ap->private_data;
 
index 9face3c6aa2144fccaaea7ef8d5754076201c0a0..4f2a67ed39d87bd765b3e69ddfbbe59a158ea909 100644 (file)
 #define DRV_VERSION    "0.9"
 
 enum {
+       /*
+        * host flags
+        */
        SIL_FLAG_RERR_ON_DMA_ACT = (1 << 29),
        SIL_FLAG_MOD15WRITE     = (1 << 30),
+       SIL_DFL_HOST_FLAGS      = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
+                                 ATA_FLAG_MMIO,
 
+       /*
+        * Controller IDs
+        */
        sil_3112                = 0,
-       sil_3112_m15w           = 1,
-       sil_3512                = 2,
-       sil_3114                = 3,
-
-       SIL_FIFO_R0             = 0x40,
-       SIL_FIFO_W0             = 0x41,
-       SIL_FIFO_R1             = 0x44,
-       SIL_FIFO_W1             = 0x45,
-       SIL_FIFO_R2             = 0x240,
-       SIL_FIFO_W2             = 0x241,
-       SIL_FIFO_R3             = 0x244,
-       SIL_FIFO_W3             = 0x245,
+       sil_3512                = 1,
+       sil_3114                = 2,
 
+       /*
+        * Register offsets
+        */
        SIL_SYSCFG              = 0x48,
+
+       /*
+        * Register bits
+        */
+       /* SYSCFG */
        SIL_MASK_IDE0_INT       = (1 << 22),
        SIL_MASK_IDE1_INT       = (1 << 23),
        SIL_MASK_IDE2_INT       = (1 << 24),
@@ -75,9 +81,12 @@ enum {
        SIL_MASK_4PORT          = SIL_MASK_2PORT |
                                  SIL_MASK_IDE2_INT | SIL_MASK_IDE3_INT,
 
-       SIL_IDE2_BMDMA          = 0x200,
-
+       /* BMDMA/BMDMA2 */
        SIL_INTR_STEERING       = (1 << 1),
+
+       /*
+        * Others
+        */
        SIL_QUIRK_MOD15WRITE    = (1 << 0),
        SIL_QUIRK_UDMA5MAX      = (1 << 1),
 };
@@ -90,13 +99,13 @@ static void sil_post_set_mode (struct ata_port *ap);
 
 
 static const struct pci_device_id sil_pci_tbl[] = {
-       { 0x1095, 0x3112, PCI_ANY_ID, PCI_ANY_ID, 0, 0, sil_3112_m15w },
-       { 0x1095, 0x0240, PCI_ANY_ID, PCI_ANY_ID, 0, 0, sil_3112_m15w },
+       { 0x1095, 0x3112, PCI_ANY_ID, PCI_ANY_ID, 0, 0, sil_3112 },
+       { 0x1095, 0x0240, PCI_ANY_ID, PCI_ANY_ID, 0, 0, sil_3112 },
        { 0x1095, 0x3512, PCI_ANY_ID, PCI_ANY_ID, 0, 0, sil_3512 },
        { 0x1095, 0x3114, PCI_ANY_ID, PCI_ANY_ID, 0, 0, sil_3114 },
-       { 0x1002, 0x436e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, sil_3112_m15w },
-       { 0x1002, 0x4379, PCI_ANY_ID, PCI_ANY_ID, 0, 0, sil_3112_m15w },
-       { 0x1002, 0x437a, PCI_ANY_ID, PCI_ANY_ID, 0, 0, sil_3112_m15w },
+       { 0x1002, 0x436e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, sil_3112 },
+       { 0x1002, 0x4379, PCI_ANY_ID, PCI_ANY_ID, 0, 0, sil_3112 },
+       { 0x1002, 0x437a, PCI_ANY_ID, PCI_ANY_ID, 0, 0, sil_3112 },
        { }     /* terminate list */
 };
 
@@ -137,11 +146,11 @@ static struct scsi_host_template sil_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,
@@ -159,7 +168,7 @@ static const struct ata_port_operations sil_ops = {
        .check_status           = ata_check_status,
        .exec_command           = ata_exec_command,
        .dev_select             = ata_std_dev_select,
-       .phy_reset              = sata_phy_reset,
+       .probe_reset            = ata_std_probe_reset,
        .post_set_mode          = sil_post_set_mode,
        .bmdma_setup            = ata_bmdma_setup,
        .bmdma_start            = ata_bmdma_start,
@@ -181,19 +190,7 @@ static const struct ata_port_info sil_port_info[] = {
        /* sil_3112 */
        {
                .sht            = &sil_sht,
-               .host_flags     = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
-                                 ATA_FLAG_SRST | ATA_FLAG_MMIO,
-               .pio_mask       = 0x1f,                 /* pio0-4 */
-               .mwdma_mask     = 0x07,                 /* mwdma0-2 */
-               .udma_mask      = 0x3f,                 /* udma0-5 */
-               .port_ops       = &sil_ops,
-       },
-       /* sil_3112_15w - keep it sync'd w/ sil_3112 */
-       {
-               .sht            = &sil_sht,
-               .host_flags     = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
-                                 ATA_FLAG_SRST | ATA_FLAG_MMIO |
-                                 SIL_FLAG_MOD15WRITE,
+               .host_flags     = SIL_DFL_HOST_FLAGS | SIL_FLAG_MOD15WRITE,
                .pio_mask       = 0x1f,                 /* pio0-4 */
                .mwdma_mask     = 0x07,                 /* mwdma0-2 */
                .udma_mask      = 0x3f,                 /* udma0-5 */
@@ -202,9 +199,7 @@ static const struct ata_port_info sil_port_info[] = {
        /* sil_3512 */
        {
                .sht            = &sil_sht,
-               .host_flags     = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
-                                 ATA_FLAG_SRST | ATA_FLAG_MMIO |
-                                 SIL_FLAG_RERR_ON_DMA_ACT,
+               .host_flags     = SIL_DFL_HOST_FLAGS | SIL_FLAG_RERR_ON_DMA_ACT,
                .pio_mask       = 0x1f,                 /* pio0-4 */
                .mwdma_mask     = 0x07,                 /* mwdma0-2 */
                .udma_mask      = 0x3f,                 /* udma0-5 */
@@ -213,9 +208,7 @@ static const struct ata_port_info sil_port_info[] = {
        /* sil_3114 */
        {
                .sht            = &sil_sht,
-               .host_flags     = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
-                                 ATA_FLAG_SRST | ATA_FLAG_MMIO |
-                                 SIL_FLAG_RERR_ON_DMA_ACT,
+               .host_flags     = SIL_DFL_HOST_FLAGS | SIL_FLAG_RERR_ON_DMA_ACT,
                .pio_mask       = 0x1f,                 /* pio0-4 */
                .mwdma_mask     = 0x07,                 /* mwdma0-2 */
                .udma_mask      = 0x3f,                 /* udma0-5 */
@@ -229,16 +222,17 @@ static const struct {
        unsigned long tf;       /* ATA taskfile register block */
        unsigned long ctl;      /* ATA control/altstatus register block */
        unsigned long bmdma;    /* DMA register block */
+       unsigned long fifo_cfg; /* FIFO Valid Byte Count and Control */
        unsigned long scr;      /* SATA control register block */
        unsigned long sien;     /* SATA Interrupt Enable register */
        unsigned long xfer_mode;/* data transfer mode register */
        unsigned long sfis_cfg; /* SATA FIS reception config register */
 } sil_port[] = {
        /* port 0 ... */
-       { 0x80, 0x8A, 0x00, 0x100, 0x148, 0xb4, 0x14c },
-       { 0xC0, 0xCA, 0x08, 0x180, 0x1c8, 0xf4, 0x1cc },
-       { 0x280, 0x28A, 0x200, 0x300, 0x348, 0x2b4, 0x34c },
-       { 0x2C0, 0x2CA, 0x208, 0x380, 0x3c8, 0x2f4, 0x3cc },
+       { 0x80, 0x8A, 0x00, 0x40, 0x100, 0x148, 0xb4, 0x14c },
+       { 0xC0, 0xCA, 0x08, 0x44, 0x180, 0x1c8, 0xf4, 0x1cc },
+       { 0x280, 0x28A, 0x200, 0x240, 0x300, 0x348, 0x2b4, 0x34c },
+       { 0x2C0, 0x2CA, 0x208, 0x244, 0x380, 0x3c8, 0x2f4, 0x3cc },
        /* ... port 3 */
 };
 
@@ -354,22 +348,12 @@ static void sil_scr_write (struct ata_port *ap, unsigned int sc_reg, u32 val)
 static void sil_dev_config(struct ata_port *ap, struct ata_device *dev)
 {
        unsigned int n, quirks = 0;
-       unsigned char model_num[40];
-       const char *s;
-       unsigned int len;
+       unsigned char model_num[41];
 
-       ata_dev_id_string(dev->id, model_num, ATA_ID_PROD_OFS,
-                         sizeof(model_num));
-       s = &model_num[0];
-       len = strnlen(s, sizeof(model_num));
-
-       /* ATAPI specifies that empty space is blank-filled; remove blanks */
-       while ((len > 0) && (s[len - 1] == ' '))
-               len--;
+       ata_id_c_string(dev->id, model_num, ATA_ID_PROD_OFS, sizeof(model_num));
 
        for (n = 0; sil_blacklist[n].product; n++)
-               if (!memcmp(sil_blacklist[n].product, s,
-                           strlen(sil_blacklist[n].product))) {
+               if (!strcmp(sil_blacklist[n].product, model_num)) {
                        quirks = sil_blacklist[n].quirk;
                        break;
                }
@@ -380,16 +364,14 @@ static void sil_dev_config(struct ata_port *ap, struct ata_device *dev)
             (quirks & SIL_QUIRK_MOD15WRITE))) {
                printk(KERN_INFO "ata%u(%u): applying Seagate errata fix (mod15write workaround)\n",
                       ap->id, dev->devno);
-               ap->host->max_sectors = 15;
-               ap->host->hostt->max_sectors = 15;
-               dev->flags |= ATA_DFLAG_LOCK_SECTORS;
+               dev->max_sectors = 15;
                return;
        }
 
        /* limit to udma5 */
        if (quirks & SIL_QUIRK_UDMA5MAX) {
                printk(KERN_INFO "ata%u(%u): applying Maxtor errata fix %s\n",
-                      ap->id, dev->devno, s);
+                      ap->id, dev->devno, model_num);
                ap->udma_mask &= ATA_UDMA5;
                return;
        }
@@ -431,13 +413,12 @@ static int sil_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
        if (rc)
                goto err_out_regions;
 
-       probe_ent = kmalloc(sizeof(*probe_ent), GFP_KERNEL);
+       probe_ent = kzalloc(sizeof(*probe_ent), GFP_KERNEL);
        if (probe_ent == NULL) {
                rc = -ENOMEM;
                goto err_out_regions;
        }
 
-       memset(probe_ent, 0, sizeof(*probe_ent));
        INIT_LIST_HEAD(&probe_ent->node);
        probe_ent->dev = pci_dev_to_dev(pdev);
        probe_ent->port_ops = sil_port_info[ent->driver_data].port_ops;
@@ -474,19 +455,12 @@ static int sil_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
        if (cls) {
                cls >>= 3;
                cls++;  /* cls = (line_size/8)+1 */
-               writeb(cls, mmio_base + SIL_FIFO_R0);
-               writeb(cls, mmio_base + SIL_FIFO_W0);
-               writeb(cls, mmio_base + SIL_FIFO_R1);
-               writeb(cls, mmio_base + SIL_FIFO_W1);
-               if (ent->driver_data == sil_3114) {
-                       writeb(cls, mmio_base + SIL_FIFO_R2);
-                       writeb(cls, mmio_base + SIL_FIFO_W2);
-                       writeb(cls, mmio_base + SIL_FIFO_R3);
-                       writeb(cls, mmio_base + SIL_FIFO_W3);
-               }
+               for (i = 0; i < probe_ent->n_ports; i++)
+                       writew(cls << 8 | cls,
+                              mmio_base + sil_port[i].fifo_cfg);
        } else
                dev_printk(KERN_WARNING, &pdev->dev,
-                        "cache line size not set.  Driver may not function\n");
+                          "cache line size not set.  Driver may not function\n");
 
        /* Apply R_ERR on DMA activate FIS errata workaround */
        if (probe_ent->host_flags & SIL_FLAG_RERR_ON_DMA_ACT) {
@@ -509,10 +483,10 @@ static int sil_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
                irq_mask = SIL_MASK_4PORT;
 
                /* flip the magic "make 4 ports work" bit */
-               tmp = readl(mmio_base + SIL_IDE2_BMDMA);
+               tmp = readl(mmio_base + sil_port[2].bmdma);
                if ((tmp & SIL_INTR_STEERING) == 0)
                        writel(tmp | SIL_INTR_STEERING,
-                              mmio_base + SIL_IDE2_BMDMA);
+                              mmio_base + sil_port[2].bmdma);
 
        } else {
                irq_mask = SIL_MASK_2PORT;
index 923130185a9e417c4570c04fe88298ce265fe102..9a53a5ed38c5ae10ce28e59c1bd729c4b94c5731 100644 (file)
@@ -249,9 +249,9 @@ static u8 sil24_check_status(struct ata_port *ap);
 static u32 sil24_scr_read(struct ata_port *ap, unsigned sc_reg);
 static void sil24_scr_write(struct ata_port *ap, unsigned sc_reg, u32 val);
 static void sil24_tf_read(struct ata_port *ap, struct ata_taskfile *tf);
-static void sil24_phy_reset(struct ata_port *ap);
+static int sil24_probe_reset(struct ata_port *ap, unsigned int *classes);
 static void sil24_qc_prep(struct ata_queued_cmd *qc);
-static int sil24_qc_issue(struct ata_queued_cmd *qc);
+static unsigned int sil24_qc_issue(struct ata_queued_cmd *qc);
 static void sil24_irq_clear(struct ata_port *ap);
 static void sil24_eng_timeout(struct ata_port *ap);
 static irqreturn_t sil24_interrupt(int irq, void *dev_instance, struct pt_regs *regs);
@@ -262,6 +262,7 @@ static int sil24_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
 
 static const struct pci_device_id sil24_pci_tbl[] = {
        { 0x1095, 0x3124, PCI_ANY_ID, PCI_ANY_ID, 0, 0, BID_SIL3124 },
+       { 0x8086, 0x3124, PCI_ANY_ID, PCI_ANY_ID, 0, 0, BID_SIL3124 },
        { 0x1095, 0x3132, PCI_ANY_ID, PCI_ANY_ID, 0, 0, BID_SIL3132 },
        { 0x1095, 0x3131, PCI_ANY_ID, PCI_ANY_ID, 0, 0, BID_SIL3131 },
        { 0x1095, 0x3531, PCI_ANY_ID, PCI_ANY_ID, 0, 0, BID_SIL3131 },
@@ -280,11 +281,11 @@ static struct scsi_host_template sil24_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,
@@ -305,7 +306,7 @@ static const struct ata_port_operations sil24_ops = {
 
        .tf_read                = sil24_tf_read,
 
-       .phy_reset              = sil24_phy_reset,
+       .probe_reset            = sil24_probe_reset,
 
        .qc_prep                = sil24_qc_prep,
        .qc_issue               = sil24_qc_issue,
@@ -335,8 +336,8 @@ static struct ata_port_info sil24_port_info[] = {
        {
                .sht            = &sil24_sht,
                .host_flags     = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
-                                 ATA_FLAG_SRST | ATA_FLAG_MMIO |
-                                 ATA_FLAG_PIO_DMA | SIL24_NPORTS2FLAG(4),
+                                 ATA_FLAG_MMIO | ATA_FLAG_PIO_DMA |
+                                 SIL24_NPORTS2FLAG(4),
                .pio_mask       = 0x1f,                 /* pio0-4 */
                .mwdma_mask     = 0x07,                 /* mwdma0-2 */
                .udma_mask      = 0x3f,                 /* udma0-5 */
@@ -346,8 +347,8 @@ static struct ata_port_info sil24_port_info[] = {
        {
                .sht            = &sil24_sht,
                .host_flags     = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
-                                 ATA_FLAG_SRST | ATA_FLAG_MMIO |
-                                 ATA_FLAG_PIO_DMA | SIL24_NPORTS2FLAG(2),
+                                 ATA_FLAG_MMIO | ATA_FLAG_PIO_DMA |
+                                 SIL24_NPORTS2FLAG(2),
                .pio_mask       = 0x1f,                 /* pio0-4 */
                .mwdma_mask     = 0x07,                 /* mwdma0-2 */
                .udma_mask      = 0x3f,                 /* udma0-5 */
@@ -357,8 +358,8 @@ static struct ata_port_info sil24_port_info[] = {
        {
                .sht            = &sil24_sht,
                .host_flags     = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
-                                 ATA_FLAG_SRST | ATA_FLAG_MMIO |
-                                 ATA_FLAG_PIO_DMA | SIL24_NPORTS2FLAG(1),
+                                 ATA_FLAG_MMIO | ATA_FLAG_PIO_DMA |
+                                 SIL24_NPORTS2FLAG(1),
                .pio_mask       = 0x1f,                 /* pio0-4 */
                .mwdma_mask     = 0x07,                 /* mwdma0-2 */
                .udma_mask      = 0x3f,                 /* udma0-5 */
@@ -370,7 +371,7 @@ static void sil24_dev_config(struct ata_port *ap, struct ata_device *dev)
 {
        void __iomem *port = (void __iomem *)ap->ioaddr.cmd_addr;
 
-       if (ap->cdb_len == 16)
+       if (dev->cdb_len == 16)
                writel(PORT_CS_CDB16, port + PORT_CTRL_STAT);
        else
                writel(PORT_CS_CDB16, port + PORT_CTRL_CLR);
@@ -427,14 +428,23 @@ static void sil24_tf_read(struct ata_port *ap, struct ata_taskfile *tf)
        *tf = pp->tf;
 }
 
-static int sil24_issue_SRST(struct ata_port *ap)
+static int sil24_softreset(struct ata_port *ap, int verbose,
+                          unsigned int *class)
 {
        void __iomem *port = (void __iomem *)ap->ioaddr.cmd_addr;
        struct sil24_port_priv *pp = ap->private_data;
        struct sil24_prb *prb = &pp->cmd_block[0].ata.prb;
        dma_addr_t paddr = pp->cmd_block_dma;
+       unsigned long timeout = jiffies + ATA_TMOUT_BOOT * HZ;
        u32 irq_enable, irq_stat;
-       int cnt;
+
+       DPRINTK("ENTER\n");
+
+       if (!sata_dev_present(ap)) {
+               DPRINTK("PHY reports no device\n");
+               *class = ATA_DEV_NONE;
+               goto out;
+       }
 
        /* temporarily turn off IRQs during SRST */
        irq_enable = readl(port + PORT_IRQ_ENABLE_SET);
@@ -451,7 +461,7 @@ static int sil24_issue_SRST(struct ata_port *ap)
 
        writel((u32)paddr, port + PORT_CMD_ACTIVATE);
 
-       for (cnt = 0; cnt < 100; cnt++) {
+       do {
                irq_stat = readl(port + PORT_IRQ_STAT);
                writel(irq_stat, port + PORT_IRQ_STAT);         /* clear irq */
 
@@ -459,36 +469,42 @@ static int sil24_issue_SRST(struct ata_port *ap)
                if (irq_stat & (PORT_IRQ_COMPLETE | PORT_IRQ_ERROR))
                        break;
 
-               msleep(1);
-       }
+               msleep(100);
+       } while (time_before(jiffies, timeout));
 
        /* restore IRQs */
        writel(irq_enable, port + PORT_IRQ_ENABLE_SET);
 
-       if (!(irq_stat & PORT_IRQ_COMPLETE))
-               return -1;
+       if (!(irq_stat & PORT_IRQ_COMPLETE)) {
+               DPRINTK("EXIT, srst failed\n");
+               return -EIO;
+       }
 
-       /* update TF */
        sil24_update_tf(ap);
+       *class = ata_dev_classify(&pp->tf);
+
+       if (*class == ATA_DEV_UNKNOWN)
+               *class = ATA_DEV_NONE;
+
+ out:
+       DPRINTK("EXIT, class=%u\n", *class);
        return 0;
 }
 
-static void sil24_phy_reset(struct ata_port *ap)
+static int sil24_hardreset(struct ata_port *ap, int verbose,
+                          unsigned int *class)
 {
-       struct sil24_port_priv *pp = ap->private_data;
+       unsigned int dummy_class;
 
-       __sata_phy_reset(ap);
-       if (ap->flags & ATA_FLAG_PORT_DISABLED)
-               return;
-
-       if (sil24_issue_SRST(ap) < 0) {
-               printk(KERN_ERR DRV_NAME
-                      " ata%u: SRST failed, disabling port\n", ap->id);
-               ap->ops->port_disable(ap);
-               return;
-       }
+       /* sil24 doesn't report device signature after hard reset */
+       return sata_std_hardreset(ap, verbose, &dummy_class);
+}
 
-       ap->device->class = ata_dev_classify(&pp->tf);
+static int sil24_probe_reset(struct ata_port *ap, unsigned int *classes)
+{
+       return ata_drive_probe_reset(ap, ata_std_probeinit,
+                                    sil24_softreset, sil24_hardreset,
+                                    ata_std_postreset, classes);
 }
 
 static inline void sil24_fill_sg(struct ata_queued_cmd *qc,
@@ -533,7 +549,7 @@ static void sil24_qc_prep(struct ata_queued_cmd *qc)
                prb = &cb->atapi.prb;
                sge = cb->atapi.sge;
                memset(cb->atapi.cdb, 0, 32);
-               memcpy(cb->atapi.cdb, qc->cdb, ap->cdb_len);
+               memcpy(cb->atapi.cdb, qc->cdb, qc->dev->cdb_len);
 
                if (qc->tf.protocol != ATA_PROT_ATAPI_NODATA) {
                        if (qc->tf.flags & ATA_TFLAG_WRITE)
@@ -557,7 +573,7 @@ static void sil24_qc_prep(struct ata_queued_cmd *qc)
                sil24_fill_sg(qc, sge);
 }
 
-static int sil24_qc_issue(struct ata_queued_cmd *qc)
+static unsigned int sil24_qc_issue(struct ata_queued_cmd *qc)
 {
        struct ata_port *ap = qc->ap;
        void __iomem *port = (void __iomem *)ap->ioaddr.cmd_addr;
@@ -638,23 +654,10 @@ static void sil24_eng_timeout(struct ata_port *ap)
        struct ata_queued_cmd *qc;
 
        qc = ata_qc_from_tag(ap, ap->active_tag);
-       if (!qc) {
-               printk(KERN_ERR "ata%u: BUG: timeout without command\n",
-                      ap->id);
-               return;
-       }
 
-       /*
-        * hack alert!  We cannot use the supplied completion
-        * function from inside the ->eh_strategy_handler() thread.
-        * libata is the only user of ->eh_strategy_handler() in
-        * any kernel, so the default scsi_done() assumes it is
-        * not being called from the SCSI EH.
-        */
        printk(KERN_ERR "ata%u: command timeout\n", ap->id);
-       qc->scsidone = scsi_finish_command;
-       qc->err_mask |= AC_ERR_OTHER;
-       ata_qc_complete(qc);
+       qc->err_mask |= AC_ERR_TIMEOUT;
+       ata_eh_qc_complete(qc);
 
        sil24_reset_controller(ap);
 }
@@ -895,6 +898,7 @@ static int sil24_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
        probe_ent->sht          = pinfo->sht;
        probe_ent->host_flags   = pinfo->host_flags;
        probe_ent->pio_mask     = pinfo->pio_mask;
+       probe_ent->mwdma_mask   = pinfo->mwdma_mask;
        probe_ent->udma_mask    = pinfo->udma_mask;
        probe_ent->port_ops     = pinfo->port_ops;
        probe_ent->n_ports      = SIL24_FLAG2NPORTS(pinfo->host_flags);
index 2df8c5632ac367a6e7b022efa0facb6874a5bb91..7fd45f86de99b575f4a863837b2aaca9c882ee9b 100644 (file)
@@ -87,11 +87,11 @@ static struct scsi_host_template sis_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           = ATA_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,
index d8472563fde860cc0789f982bc896ab9104ba38e..4aaccd53e7367efc5069cec701f7c4da39df3be0 100644 (file)
@@ -288,11 +288,11 @@ static struct scsi_host_template k2_sata_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,
index bc87c16c80d2b2377a6ff1ddabaf396d84d428f4..9f8a76815402bd831717ec7f4b8b6da944f456c8 100644 (file)
@@ -174,7 +174,7 @@ static void pdc20621_get_from_dimm(struct ata_probe_ent *pe,
 static void pdc20621_put_to_dimm(struct ata_probe_ent *pe,
                                 void *psource, u32 offset, u32 size);
 static void pdc20621_irq_clear(struct ata_port *ap);
-static int pdc20621_qc_issue_prot(struct ata_queued_cmd *qc);
+static unsigned int pdc20621_qc_issue_prot(struct ata_queued_cmd *qc);
 
 
 static struct scsi_host_template pdc_sata_sht = {
@@ -182,11 +182,11 @@ static struct scsi_host_template pdc_sata_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,
@@ -460,7 +460,7 @@ static void pdc20621_dma_prep(struct ata_queued_cmd *qc)
        unsigned int i, idx, total_len = 0, sgt_len;
        u32 *buf = (u32 *) &pp->dimm_buf[PDC_DIMM_HEADER_SZ];
 
-       assert(qc->flags & ATA_QCFLAG_DMAMAP);
+       WARN_ON(!(qc->flags & ATA_QCFLAG_DMAMAP));
 
        VPRINTK("ata%u: ENTER\n", ap->id);
 
@@ -678,7 +678,7 @@ static void pdc20621_packet_start(struct ata_queued_cmd *qc)
        }
 }
 
-static int pdc20621_qc_issue_prot(struct ata_queued_cmd *qc)
+static unsigned int pdc20621_qc_issue_prot(struct ata_queued_cmd *qc)
 {
        switch (qc->tf.protocol) {
        case ATA_PROT_DMA:
@@ -866,26 +866,12 @@ static void pdc_eng_timeout(struct ata_port *ap)
        spin_lock_irqsave(&host_set->lock, flags);
 
        qc = ata_qc_from_tag(ap, ap->active_tag);
-       if (!qc) {
-               printk(KERN_ERR "ata%u: BUG: timeout without command\n",
-                      ap->id);
-               goto out;
-       }
-
-       /* hack alert!  We cannot use the supplied completion
-        * function from inside the ->eh_strategy_handler() thread.
-        * libata is the only user of ->eh_strategy_handler() in
-        * any kernel, so the default scsi_done() assumes it is
-        * not being called from the SCSI EH.
-        */
-       qc->scsidone = scsi_finish_command;
 
        switch (qc->tf.protocol) {
        case ATA_PROT_DMA:
        case ATA_PROT_NODATA:
                printk(KERN_ERR "ata%u: command timeout\n", ap->id);
                qc->err_mask |= __ac_err_mask(ata_wait_idle(ap));
-               ata_qc_complete(qc);
                break;
 
        default:
@@ -895,12 +881,11 @@ static void pdc_eng_timeout(struct ata_port *ap)
                       ap->id, qc->tf.command, drv_stat);
 
                qc->err_mask |= ac_err_mask(drv_stat);
-               ata_qc_complete(qc);
                break;
        }
 
-out:
        spin_unlock_irqrestore(&host_set->lock, flags);
+       ata_eh_qc_complete(qc);
        DPRINTK("EXIT\n");
 }
 
index 9635ca7009770b823adbc79f0fa944acf70f0186..37a487b7d655a1696a4ef2c74b011db3c16d0454 100644 (file)
@@ -75,11 +75,11 @@ static struct scsi_host_template uli_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,
index 6d5b0a794cfdf056e9abcf4272cca7709b9cba2a..ff65a0b0457fa8cc914332d5392e81eef7037d63 100644 (file)
@@ -94,11 +94,11 @@ static struct scsi_host_template svia_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,
index e484e8db68105f346ad38aa49247334caf5eb6d3..b574379a7a82168542cbd6914dea268148c4fd76 100644 (file)
@@ -251,11 +251,11 @@ static struct scsi_host_template vsc_sata_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,
index ff82ccfbb106b528539e112168a1aba8d250294c..5d169a2881b98dd2accf752cc784551c7f598473 100644 (file)
@@ -584,8 +584,7 @@ static int scsi_request_sense(struct scsi_cmnd *scmd)
  *    keep a list of pending commands for final completion, and once we
  *    are ready to leave error handling we handle completion for real.
  **/
-static void scsi_eh_finish_cmd(struct scsi_cmnd *scmd,
-                              struct list_head *done_q)
+void scsi_eh_finish_cmd(struct scsi_cmnd *scmd, struct list_head *done_q)
 {
        scmd->device->host->host_failed--;
        scmd->eh_eflags = 0;
@@ -597,6 +596,7 @@ static void scsi_eh_finish_cmd(struct scsi_cmnd *scmd,
        scsi_setup_cmd_retry(scmd);
        list_move_tail(&scmd->eh_entry, done_q);
 }
+EXPORT_SYMBOL(scsi_eh_finish_cmd);
 
 /**
  * scsi_eh_get_sense - Get device sense data.
@@ -1425,7 +1425,7 @@ static void scsi_eh_ready_devs(struct Scsi_Host *shost,
  * @done_q:    list_head of processed commands.
  *
  **/
-static void scsi_eh_flush_done_q(struct list_head *done_q)
+void scsi_eh_flush_done_q(struct list_head *done_q)
 {
        struct scsi_cmnd *scmd, *next;
 
@@ -1454,6 +1454,7 @@ static void scsi_eh_flush_done_q(struct list_head *done_q)
                }
        }
 }
+EXPORT_SYMBOL(scsi_eh_flush_done_q);
 
 /**
  * scsi_unjam_host - Attempt to fix a host which has a cmd that failed.
index 94f77cce27fa10d634b7ffdbeb415d31613833b5..b02a16c435e78b6da13376238bb345aa2ac4ab12 100644 (file)
@@ -267,6 +267,16 @@ struct ata_taskfile {
          ((u64) (id)[(n) + 1] << 16) | \
          ((u64) (id)[(n) + 0]) )
 
+static inline unsigned int ata_id_major_version(const u16 *id)
+{
+       unsigned int mver;
+
+       for (mver = 14; mver >= 1; mver--)
+               if (id[ATA_ID_MAJOR_VER] & (1 << mver))
+                       break;
+       return mver;
+}
+
 static inline int ata_id_current_chs_valid(const u16 *id)
 {
        /* For ATA-1 devices, if the INITIALIZE DEVICE PARAMETERS command 
@@ -302,4 +312,16 @@ static inline int ata_ok(u8 status)
                        == ATA_DRDY);
 }
 
+static inline int lba_28_ok(u64 block, u32 n_block)
+{
+       /* check the ending block number */
+       return ((block + n_block - 1) < ((u64)1 << 28)) && (n_block <= 256);
+}
+
+static inline int lba_48_ok(u64 block, u32 n_block)
+{
+       /* check the ending block number */
+       return ((block + n_block - 1) < ((u64)1 << 48)) && (n_block <= 65536);
+}
+
 #endif /* __LINUX_ATA_H__ */
index c91be5e64ededd7f59831bddf7bfba2b080d2db5..239408ecfddfb2d7dda2ef22d728a0c85d4c5d64 100644 (file)
@@ -35,7 +35,8 @@
 #include <linux/workqueue.h>
 
 /*
- * compile-time options
+ * compile-time options: to be removed as soon as all the drivers are
+ * converted to the new debugging mechanism
  */
 #undef ATA_DEBUG               /* debugging output */
 #undef ATA_VERBOSE_DEBUG       /* yet more debugging output */
 
 #define BPRINTK(fmt, args...) if (ap->flags & ATA_FLAG_DEBUGMSG) printk(KERN_ERR "%s: " fmt, __FUNCTION__, ## args)
 
-#ifdef ATA_NDEBUG
-#define assert(expr)
-#else
-#define assert(expr) \
-        if(unlikely(!(expr))) {                                   \
-        printk(KERN_ERR "Assertion failed! %s,%s,%s,line=%d\n", \
-        #expr,__FILE__,__FUNCTION__,__LINE__);          \
-        }
-#endif
+/* NEW: debug levels */
+#define HAVE_LIBATA_MSG 1
+
+enum {
+       ATA_MSG_DRV     = 0x0001,
+       ATA_MSG_INFO    = 0x0002,
+       ATA_MSG_PROBE   = 0x0004,
+       ATA_MSG_WARN    = 0x0008,
+       ATA_MSG_MALLOC  = 0x0010,
+       ATA_MSG_CTL     = 0x0020,
+       ATA_MSG_INTR    = 0x0040,
+       ATA_MSG_ERR     = 0x0080,
+};
+
+#define ata_msg_drv(p)    ((p)->msg_enable & ATA_MSG_DRV)
+#define ata_msg_info(p)   ((p)->msg_enable & ATA_MSG_INFO)
+#define ata_msg_probe(p)  ((p)->msg_enable & ATA_MSG_PROBE)
+#define ata_msg_warn(p)   ((p)->msg_enable & ATA_MSG_WARN)
+#define ata_msg_malloc(p) ((p)->msg_enable & ATA_MSG_MALLOC)
+#define ata_msg_ctl(p)    ((p)->msg_enable & ATA_MSG_CTL)
+#define ata_msg_intr(p)   ((p)->msg_enable & ATA_MSG_INTR)
+#define ata_msg_err(p)    ((p)->msg_enable & ATA_MSG_ERR)
+
+static inline u32 ata_msg_init(int dval, int default_msg_enable_bits)
+{
+       if (dval < 0 || dval >= (sizeof(u32) * 8))
+               return default_msg_enable_bits; /* should be 0x1 - only driver info msgs */
+       if (!dval)
+               return 0;
+       return (1 << dval) - 1;
+}
 
 /* defines only for the constants which don't work well as enums */
 #define ATA_TAG_POISON         0xfafbfcfdU
@@ -99,8 +122,7 @@ enum {
        /* struct ata_device stuff */
        ATA_DFLAG_LBA48         = (1 << 0), /* device supports LBA48 */
        ATA_DFLAG_PIO           = (1 << 1), /* device currently in PIO mode */
-       ATA_DFLAG_LOCK_SECTORS  = (1 << 2), /* don't adjust max_sectors */
-       ATA_DFLAG_LBA           = (1 << 3), /* device supports LBA */
+       ATA_DFLAG_LBA           = (1 << 2), /* device supports LBA */
 
        ATA_DEV_UNKNOWN         = 0,    /* unknown device */
        ATA_DEV_ATA             = 1,    /* ATA device */
@@ -115,9 +137,9 @@ enum {
        ATA_FLAG_PORT_DISABLED  = (1 << 2), /* port is disabled, ignore it */
        ATA_FLAG_SATA           = (1 << 3),
        ATA_FLAG_NO_LEGACY      = (1 << 4), /* no legacy mode check */
-       ATA_FLAG_SRST           = (1 << 5), /* use ATA SRST, not E.D.D. */
+       ATA_FLAG_SRST           = (1 << 5), /* (obsolete) use ATA SRST, not E.D.D. */
        ATA_FLAG_MMIO           = (1 << 6), /* use MMIO, not PIO */
-       ATA_FLAG_SATA_RESET     = (1 << 7), /* use COMRESET */
+       ATA_FLAG_SATA_RESET     = (1 << 7), /* (obsolete) use COMRESET */
        ATA_FLAG_PIO_DMA        = (1 << 8), /* PIO cmds via DMA */
        ATA_FLAG_NOINTR         = (1 << 9), /* FIXME: Remove this once
                                             * proper HSM is in place. */
@@ -129,10 +151,14 @@ enum {
        ATA_FLAG_PIO_LBA48      = (1 << 13), /* Host DMA engine is LBA28 only */
        ATA_FLAG_IRQ_MASK       = (1 << 14), /* Mask IRQ in PIO xfers */
 
+       ATA_FLAG_FLUSH_PORT_TASK = (1 << 15), /* Flush port task */
+       ATA_FLAG_IN_EH          = (1 << 16), /* EH in progress */
+
        ATA_QCFLAG_ACTIVE       = (1 << 1), /* cmd not yet ack'd to scsi lyer */
        ATA_QCFLAG_SG           = (1 << 3), /* have s/g table? */
        ATA_QCFLAG_SINGLE       = (1 << 4), /* no s/g, just a single buffer */
        ATA_QCFLAG_DMAMAP       = ATA_QCFLAG_SG | ATA_QCFLAG_SINGLE,
+       ATA_QCFLAG_EH_SCHEDULED = (1 << 5), /* EH scheduled */
 
        /* various lengths of time */
        ATA_TMOUT_EDD           = 5 * HZ,       /* heuristic */
@@ -162,11 +188,19 @@ enum {
        PORT_DISABLED           = 2,
 
        /* encoding various smaller bitmaps into a single
-        * unsigned long bitmap
+        * unsigned int bitmap
         */
-       ATA_SHIFT_UDMA          = 0,
-       ATA_SHIFT_MWDMA         = 8,
-       ATA_SHIFT_PIO           = 11,
+       ATA_BITS_PIO            = 5,
+       ATA_BITS_MWDMA          = 3,
+       ATA_BITS_UDMA           = 8,
+
+       ATA_SHIFT_PIO           = 0,
+       ATA_SHIFT_MWDMA         = ATA_SHIFT_PIO + ATA_BITS_PIO,
+       ATA_SHIFT_UDMA          = ATA_SHIFT_MWDMA + ATA_BITS_MWDMA,
+
+       ATA_MASK_PIO            = ((1 << ATA_BITS_PIO) - 1) << ATA_SHIFT_PIO,
+       ATA_MASK_MWDMA          = ((1 << ATA_BITS_MWDMA) - 1) << ATA_SHIFT_MWDMA,
+       ATA_MASK_UDMA           = ((1 << ATA_BITS_UDMA) - 1) << ATA_SHIFT_UDMA,
 
        /* size of buffer to pad xfers ending on unaligned boundaries */
        ATA_DMA_PAD_SZ          = 4,
@@ -189,10 +223,15 @@ enum hsm_task_states {
 };
 
 enum ata_completion_errors {
-       AC_ERR_OTHER            = (1 << 0),
-       AC_ERR_DEV              = (1 << 1),
-       AC_ERR_ATA_BUS          = (1 << 2),
-       AC_ERR_HOST_BUS         = (1 << 3),
+       AC_ERR_DEV              = (1 << 0), /* device reported error */
+       AC_ERR_HSM              = (1 << 1), /* host state machine violation */
+       AC_ERR_TIMEOUT          = (1 << 2), /* timeout */
+       AC_ERR_MEDIA            = (1 << 3), /* media error */
+       AC_ERR_ATA_BUS          = (1 << 4), /* ATA bus error */
+       AC_ERR_HOST_BUS         = (1 << 5), /* host bus error */
+       AC_ERR_SYSTEM           = (1 << 6), /* system error */
+       AC_ERR_INVALID          = (1 << 7), /* invalid argument */
+       AC_ERR_OTHER            = (1 << 8), /* unknown */
 };
 
 /* forward declarations */
@@ -202,7 +241,10 @@ struct ata_port;
 struct ata_queued_cmd;
 
 /* typedefs */
-typedef int (*ata_qc_cb_t) (struct ata_queued_cmd *qc);
+typedef void (*ata_qc_cb_t) (struct ata_queued_cmd *qc);
+typedef void (*ata_probeinit_fn_t)(struct ata_port *);
+typedef int (*ata_reset_fn_t)(struct ata_port *, int, unsigned int *);
+typedef void (*ata_postreset_fn_t)(struct ata_port *ap, unsigned int *);
 
 struct ata_ioports {
        unsigned long           cmd_addr;
@@ -305,7 +347,7 @@ struct ata_device {
        unsigned long           flags;          /* ATA_DFLAG_xxx */
        unsigned int            class;          /* ATA_DEV_xxx */
        unsigned int            devno;          /* 0 or 1 */
-       u16                     id[ATA_ID_WORDS]; /* IDENTIFY xxx DEVICE data */
+       u16                     *id;            /* IDENTIFY xxx DEVICE data */
        u8                      pio_mode;
        u8                      dma_mode;
        u8                      xfer_mode;
@@ -313,6 +355,8 @@ struct ata_device {
 
        unsigned int            multi_count;    /* sectors count for
                                                   READ/WRITE MULTIPLE */
+       unsigned int            max_sectors;    /* per-device max sectors */
+       unsigned int            cdb_len;
 
        /* for CHS addressing */
        u16                     cylinders;      /* Number of cylinders */
@@ -342,7 +386,6 @@ struct ata_port {
        unsigned int            mwdma_mask;
        unsigned int            udma_mask;
        unsigned int            cbl;    /* cable type; ATA_CBL_xxx */
-       unsigned int            cdb_len;
 
        struct ata_device       device[ATA_MAX_DEVICES];
 
@@ -353,12 +396,14 @@ struct ata_port {
        struct ata_host_stats   stats;
        struct ata_host_set     *host_set;
 
-       struct work_struct      packet_task;
+       struct work_struct      port_task;
 
-       struct work_struct      pio_task;
        unsigned int            hsm_task_state;
        unsigned long           pio_task_timeout;
 
+       u32                     msg_enable;
+       struct list_head        eh_done_q;
+
        void                    *private_data;
 };
 
@@ -378,7 +423,9 @@ struct ata_port_operations {
        u8   (*check_altstatus)(struct ata_port *ap);
        void (*dev_select)(struct ata_port *ap, unsigned int device);
 
-       void (*phy_reset) (struct ata_port *ap);
+       void (*phy_reset) (struct ata_port *ap); /* obsolete */
+       int (*probe_reset) (struct ata_port *ap, unsigned int *classes);
+
        void (*post_set_mode) (struct ata_port *ap);
 
        int (*check_atapi_dma) (struct ata_queued_cmd *qc);
@@ -387,7 +434,7 @@ struct ata_port_operations {
        void (*bmdma_start) (struct ata_queued_cmd *qc);
 
        void (*qc_prep) (struct ata_queued_cmd *qc);
-       int (*qc_issue) (struct ata_queued_cmd *qc);
+       unsigned int (*qc_issue) (struct ata_queued_cmd *qc);
 
        void (*eng_timeout) (struct ata_port *ap);
 
@@ -435,6 +482,18 @@ extern void ata_port_probe(struct ata_port *);
 extern void __sata_phy_reset(struct ata_port *ap);
 extern void sata_phy_reset(struct ata_port *ap);
 extern void ata_bus_reset(struct ata_port *ap);
+extern int ata_drive_probe_reset(struct ata_port *ap,
+                       ata_probeinit_fn_t probeinit,
+                       ata_reset_fn_t softreset, ata_reset_fn_t hardreset,
+                       ata_postreset_fn_t postreset, unsigned int *classes);
+extern void ata_std_probeinit(struct ata_port *ap);
+extern int ata_std_softreset(struct ata_port *ap, int verbose,
+                            unsigned int *classes);
+extern int sata_std_hardreset(struct ata_port *ap, int verbose,
+                             unsigned int *class);
+extern void ata_std_postreset(struct ata_port *ap, unsigned int *classes);
+extern int ata_dev_revalidate(struct ata_port *ap, struct ata_device *dev,
+                             int post_reset);
 extern void ata_port_disable(struct ata_port *);
 extern void ata_std_ports(struct ata_ioports *ioaddr);
 #ifdef CONFIG_PCI
@@ -449,7 +508,10 @@ extern void ata_host_set_remove(struct ata_host_set *host_set);
 extern int ata_scsi_detect(struct scsi_host_template *sht);
 extern int ata_scsi_ioctl(struct scsi_device *dev, int cmd, void __user *arg);
 extern int ata_scsi_queuecmd(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *));
+extern enum scsi_eh_timer_return ata_scsi_timed_out(struct scsi_cmnd *cmd);
 extern int ata_scsi_error(struct Scsi_Host *host);
+extern void ata_eh_qc_complete(struct ata_queued_cmd *qc);
+extern void ata_eh_qc_retry(struct ata_queued_cmd *qc);
 extern int ata_scsi_release(struct Scsi_Host *host);
 extern unsigned int ata_host_intr(struct ata_port *ap, struct ata_queued_cmd *qc);
 extern int ata_scsi_device_resume(struct scsi_device *);
@@ -457,6 +519,11 @@ extern int ata_scsi_device_suspend(struct scsi_device *);
 extern int ata_device_resume(struct ata_port *, struct ata_device *);
 extern int ata_device_suspend(struct ata_port *, struct ata_device *);
 extern int ata_ratelimit(void);
+extern unsigned int ata_busy_sleep(struct ata_port *ap,
+                                  unsigned long timeout_pat,
+                                  unsigned long timeout);
+extern void ata_port_queue_task(struct ata_port *ap, void (*fn)(void *),
+                               void *data, unsigned long delay);
 
 /*
  * Default driver ops implementations
@@ -470,26 +537,28 @@ extern void ata_std_dev_select (struct ata_port *ap, unsigned int device);
 extern u8 ata_check_status(struct ata_port *ap);
 extern u8 ata_altstatus(struct ata_port *ap);
 extern void ata_exec_command(struct ata_port *ap, const struct ata_taskfile *tf);
+extern int ata_std_probe_reset(struct ata_port *ap, unsigned int *classes);
 extern int ata_port_start (struct ata_port *ap);
 extern void ata_port_stop (struct ata_port *ap);
 extern void ata_host_stop (struct ata_host_set *host_set);
 extern irqreturn_t ata_interrupt (int irq, void *dev_instance, struct pt_regs *regs);
 extern void ata_qc_prep(struct ata_queued_cmd *qc);
-extern int ata_qc_issue_prot(struct ata_queued_cmd *qc);
+extern unsigned int ata_qc_issue_prot(struct ata_queued_cmd *qc);
 extern void ata_sg_init_one(struct ata_queued_cmd *qc, void *buf,
                unsigned int buflen);
 extern void ata_sg_init(struct ata_queued_cmd *qc, struct scatterlist *sg,
                 unsigned int n_elem);
 extern unsigned int ata_dev_classify(const struct ata_taskfile *tf);
-extern void ata_dev_id_string(const u16 *id, unsigned char *s,
-                             unsigned int ofs, unsigned int len);
-extern void ata_dev_config(struct ata_port *ap, unsigned int i);
+extern void ata_id_string(const u16 *id, unsigned char *s,
+                         unsigned int ofs, unsigned int len);
+extern void ata_id_c_string(const u16 *id, unsigned char *s,
+                           unsigned int ofs, unsigned int len);
 extern void ata_bmdma_setup (struct ata_queued_cmd *qc);
 extern void ata_bmdma_start (struct ata_queued_cmd *qc);
 extern void ata_bmdma_stop(struct ata_queued_cmd *qc);
 extern u8   ata_bmdma_status(struct ata_port *ap);
 extern void ata_bmdma_irq_clear(struct ata_port *ap);
-extern void ata_qc_complete(struct ata_queued_cmd *qc);
+extern void __ata_qc_complete(struct ata_queued_cmd *qc);
 extern void ata_eng_timeout(struct ata_port *ap);
 extern void ata_scsi_simulate(struct ata_port *ap, struct ata_device *dev,
                              struct scsi_cmnd *cmd,
@@ -586,10 +655,14 @@ static inline unsigned int ata_tag_valid(unsigned int tag)
        return (tag < ATA_MAX_QUEUE) ? 1 : 0;
 }
 
+static inline unsigned int ata_class_present(unsigned int class)
+{
+       return class == ATA_DEV_ATA || class == ATA_DEV_ATAPI;
+}
+
 static inline unsigned int ata_dev_present(const struct ata_device *dev)
 {
-       return ((dev->class == ATA_DEV_ATA) ||
-               (dev->class == ATA_DEV_ATAPI));
+       return ata_class_present(dev->class);
 }
 
 static inline u8 ata_chk_status(struct ata_port *ap)
@@ -657,9 +730,9 @@ static inline u8 ata_wait_idle(struct ata_port *ap)
 
        if (status & (ATA_BUSY | ATA_DRQ)) {
                unsigned long l = ap->ioaddr.status_addr;
-               printk(KERN_WARNING
-                      "ATA: abnormal status 0x%X on port 0x%lX\n",
-                      status, l);
+               if (ata_msg_warn(ap))
+                       printk(KERN_WARNING "ATA: abnormal status 0x%X on port 0x%lX\n",
+                               status, l);
        }
 
        return status;
@@ -701,6 +774,24 @@ static inline void ata_qc_reinit(struct ata_queued_cmd *qc)
        ata_tf_init(qc->ap, &qc->tf, qc->dev->devno);
 }
 
+/**
+ *     ata_qc_complete - Complete an active ATA command
+ *     @qc: Command to complete
+ *     @err_mask: ATA Status register contents
+ *
+ *     Indicate to the mid and upper layers that an ATA
+ *     command has completed, with either an ok or not-ok status.
+ *
+ *     LOCKING:
+ *     spin_lock_irqsave(host_set lock)
+ */
+static inline void ata_qc_complete(struct ata_queued_cmd *qc)
+{
+       if (unlikely(qc->flags & ATA_QCFLAG_EH_SCHEDULED))
+               return;
+
+       __ata_qc_complete(qc);
+}
 
 /**
  *     ata_irq_on - Enable interrupts on a port.
@@ -751,7 +842,8 @@ static inline u8 ata_irq_ack(struct ata_port *ap, unsigned int chk_drq)
 
        status = ata_busy_wait(ap, bits, 1000);
        if (status & bits)
-               DPRINTK("abnormal status 0x%X\n", status);
+               if (ata_msg_err(ap))
+                       printk(KERN_ERR "abnormal status 0x%X\n", status);
 
        /* get controller status; clear intr, err bits */
        if (ap->flags & ATA_FLAG_MMIO) {
@@ -769,8 +861,10 @@ static inline u8 ata_irq_ack(struct ata_port *ap, unsigned int chk_drq)
                post_stat = inb(ap->ioaddr.bmdma_addr + ATA_DMA_STATUS);
        }
 
-       VPRINTK("irq ack: host_stat 0x%X, new host_stat 0x%X, drv_stat 0x%X\n",
-               host_stat, post_stat, status);
+       if (ata_msg_intr(ap))
+               printk(KERN_INFO "%s: irq ack: host_stat 0x%X, new host_stat 0x%X, drv_stat 0x%X\n",
+                       __FUNCTION__,
+                       host_stat, post_stat, status);
 
        return status;
 }
@@ -807,7 +901,7 @@ static inline int ata_try_flush_cache(const struct ata_device *dev)
 static inline unsigned int ac_err_mask(u8 status)
 {
        if (status & ATA_BUSY)
-               return AC_ERR_ATA_BUS;
+               return AC_ERR_HSM;
        if (status & (ATA_ERR | ATA_DF))
                return AC_ERR_DEV;
        return 0;
index fabd879c2f2e13e44f41a08083241fc6a20a6914..d160880b2a8798f18d3c0772ef84281e9d0bb6bc 100644 (file)
@@ -35,6 +35,9 @@ static inline int scsi_sense_valid(struct scsi_sense_hdr *sshdr)
 }
 
 
+extern void scsi_eh_finish_cmd(struct scsi_cmnd *scmd,
+                              struct list_head *done_q);
+extern void scsi_eh_flush_done_q(struct list_head *done_q);
 extern void scsi_report_bus_reset(struct Scsi_Host *, int);
 extern void scsi_report_device_reset(struct Scsi_Host *, int, int);
 extern int scsi_block_when_processing_errors(struct scsi_device *);