Merge branch 'upstream-fixes'
authorJeff Garzik <jgarzik@pobox.com>
Mon, 20 Feb 2006 21:55:56 +0000 (16:55 -0500)
committerJeff Garzik <jgarzik@pobox.com>
Mon, 20 Feb 2006 21:55:56 +0000 (16:55 -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 a800fb51168b0bb64b0540fdb133545ac881e4cf..1c2ab3dede71726c8fe31b698591bbb234c78181 100644 (file)
@@ -66,6 +66,8 @@ enum {
        AHCI_IRQ_ON_SG          = (1 << 31),
        AHCI_CMD_ATAPI          = (1 << 5),
        AHCI_CMD_WRITE          = (1 << 6),
+       AHCI_CMD_RESET          = (1 << 8),
+       AHCI_CMD_CLR_BUSY       = (1 << 10),
 
        RX_FIS_D2H_REG          = 0x40, /* offset of D2H Register FIS data */
 
@@ -85,6 +87,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 +141,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 +188,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 +206,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 +229,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 +251,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 +453,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 +502,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 +551,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 +604,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;
 
-       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 +641,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 +656,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 +675,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 +690,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 +714,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 +733,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);
                }
        }
@@ -776,7 +812,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..c662bf5315142c0b750a348c09eb00dd5fcbc9ff 100644 (file)
@@ -101,9 +101,11 @@ enum {
        ICH5_PCS                = 0x92, /* port control and status */
        PIIX_SCC                = 0x0A, /* sub-class code register */
 
-       PIIX_FLAG_AHCI          = (1 << 28), /* AHCI possible */
-       PIIX_FLAG_CHECKINTR     = (1 << 29), /* make sure PCI INTx enabled */
-       PIIX_FLAG_COMBINED      = (1 << 30), /* combined mode possible */
+       PIIX_FLAG_AHCI          = (1 << 27), /* AHCI possible */
+       PIIX_FLAG_CHECKINTR     = (1 << 28), /* make sure PCI INTx enabled */
+       PIIX_FLAG_COMBINED      = (1 << 29), /* combined mode possible */
+       /* ICH6/7 use different scheme for map value */
+       PIIX_FLAG_COMBINED_ICH6 = PIIX_FLAG_COMBINED | (1 << 30),
 
        /* combined mode.  if set, PATA is channel 0.
         * if clear, PATA is channel 1.
@@ -129,8 +131,8 @@ enum {
 static int piix_init_one (struct pci_dev *pdev,
                                    const struct pci_device_id *ent);
 
-static void piix_pata_phy_reset(struct ata_port *ap);
-static void piix_sata_phy_reset(struct ata_port *ap);
+static int piix_pata_probe_reset(struct ata_port *ap, unsigned int *classes);
+static int piix_sata_probe_reset(struct ata_port *ap, unsigned int *classes);
 static void piix_set_piomode (struct ata_port *ap, struct ata_device *adev);
 static void piix_set_dmamode (struct ata_port *ap, struct ata_device *adev);
 
@@ -178,11 +180,11 @@ static struct scsi_host_template piix_sht = {
        .name                   = DRV_NAME,
        .ioctl                  = ata_scsi_ioctl,
        .queuecommand           = ata_scsi_queuecmd,
+       .eh_timed_out           = ata_scsi_timed_out,
        .eh_strategy_handler    = ata_scsi_error,
        .can_queue              = ATA_DEF_QUEUE,
        .this_id                = ATA_SHT_THIS_ID,
        .sg_tablesize           = LIBATA_MAX_PRD,
-       .max_sectors            = ATA_MAX_SECTORS,
        .cmd_per_lun            = ATA_SHT_CMD_PER_LUN,
        .emulated               = ATA_SHT_EMULATED,
        .use_clustering         = ATA_SHT_USE_CLUSTERING,
@@ -205,7 +207,7 @@ static const struct ata_port_operations piix_pata_ops = {
        .exec_command           = ata_exec_command,
        .dev_select             = ata_std_dev_select,
 
-       .phy_reset              = piix_pata_phy_reset,
+       .probe_reset            = piix_pata_probe_reset,
 
        .bmdma_setup            = ata_bmdma_setup,
        .bmdma_start            = ata_bmdma_start,
@@ -233,7 +235,7 @@ static const struct ata_port_operations piix_sata_ops = {
        .exec_command           = ata_exec_command,
        .dev_select             = ata_std_dev_select,
 
-       .phy_reset              = piix_sata_phy_reset,
+       .probe_reset            = piix_sata_probe_reset,
 
        .bmdma_setup            = ata_bmdma_setup,
        .bmdma_start            = ata_bmdma_start,
@@ -256,8 +258,7 @@ static struct ata_port_info piix_port_info[] = {
        /* ich5_pata */
        {
                .sht            = &piix_sht,
-               .host_flags     = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST |
-                                 PIIX_FLAG_CHECKINTR,
+               .host_flags     = ATA_FLAG_SLAVE_POSS | PIIX_FLAG_CHECKINTR,
                .pio_mask       = 0x1f, /* pio0-4 */
 #if 0
                .mwdma_mask     = 0x06, /* mwdma1-2 */
@@ -271,8 +272,8 @@ static struct ata_port_info piix_port_info[] = {
        /* ich5_sata */
        {
                .sht            = &piix_sht,
-               .host_flags     = ATA_FLAG_SATA | ATA_FLAG_SRST |
-                                 PIIX_FLAG_COMBINED | PIIX_FLAG_CHECKINTR,
+               .host_flags     = ATA_FLAG_SATA | PIIX_FLAG_COMBINED |
+                                 PIIX_FLAG_CHECKINTR,
                .pio_mask       = 0x1f, /* pio0-4 */
                .mwdma_mask     = 0x07, /* mwdma0-2 */
                .udma_mask      = 0x7f, /* udma0-6 */
@@ -282,7 +283,7 @@ static struct ata_port_info piix_port_info[] = {
        /* piix4_pata */
        {
                .sht            = &piix_sht,
-               .host_flags     = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST,
+               .host_flags     = ATA_FLAG_SLAVE_POSS,
                .pio_mask       = 0x1f, /* pio0-4 */
 #if 0
                .mwdma_mask     = 0x06, /* mwdma1-2 */
@@ -296,9 +297,8 @@ static struct ata_port_info piix_port_info[] = {
        /* ich6_sata */
        {
                .sht            = &piix_sht,
-               .host_flags     = ATA_FLAG_SATA | ATA_FLAG_SRST |
-                                 PIIX_FLAG_COMBINED | PIIX_FLAG_CHECKINTR |
-                                 ATA_FLAG_SLAVE_POSS,
+               .host_flags     = ATA_FLAG_SATA | PIIX_FLAG_COMBINED_ICH6 |
+                                 PIIX_FLAG_CHECKINTR | ATA_FLAG_SLAVE_POSS,
                .pio_mask       = 0x1f, /* pio0-4 */
                .mwdma_mask     = 0x07, /* mwdma0-2 */
                .udma_mask      = 0x7f, /* udma0-6 */
@@ -308,9 +308,9 @@ static struct ata_port_info piix_port_info[] = {
        /* 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 | ATA_FLAG_SLAVE_POSS |
+                                 PIIX_FLAG_AHCI,
                .pio_mask       = 0x1f, /* pio0-4 */
                .mwdma_mask     = 0x07, /* mwdma0-2 */
                .udma_mask      = 0x7f, /* udma0-6 */
@@ -363,30 +363,42 @@ cbl40:
 }
 
 /**
- *     piix_pata_phy_reset - Probe specified port on PATA host controller
- *     @ap: Port to probe
+ *     piix_pata_probeinit - probeinit for PATA host controller
+ *     @ap: Target port
  *
- *     Probe PATA phy.
+ *     Probeinit including cable detection.
  *
  *     LOCKING:
  *     None (inherited from caller).
  */
+static void piix_pata_probeinit(struct ata_port *ap)
+{
+       piix_pata_cbl_detect(ap);
+       ata_std_probeinit(ap);
+}
 
-static void piix_pata_phy_reset(struct ata_port *ap)
+/**
+ *     piix_pata_probe_reset - Perform reset on PATA port and classify
+ *     @ap: Port to reset
+ *     @classes: Resulting classes of attached devices
+ *
+ *     Reset PATA phy and classify attached devices.
+ *
+ *     LOCKING:
+ *     None (inherited from caller).
+ */
+static int piix_pata_probe_reset(struct ata_port *ap, unsigned int *classes)
 {
        struct pci_dev *pdev = to_pci_dev(ap->host_set->dev);
 
        if (!pci_test_config_bits(pdev, &piix_enable_bits[ap->hard_port_no])) {
-               ata_port_disable(ap);
                printk(KERN_INFO "ata%u: port disabled. ignoring.\n", ap->id);
-               return;
+               return 0;
        }
 
-       piix_pata_cbl_detect(ap);
-
-       ata_port_probe(ap);
-
-       ata_bus_reset(ap);
+       return ata_drive_probe_reset(ap, piix_pata_probeinit,
+                                    ata_std_softreset, NULL,
+                                    ata_std_postreset, classes);
 }
 
 /**
@@ -411,9 +423,6 @@ static int piix_sata_probe (struct ata_port *ap)
        int orig_mask, mask, i;
        u8 pcs;
 
-       mask = (PIIX_PORT_PRESENT << ap->hard_port_no) |
-              (PIIX_PORT_ENABLED << ap->hard_port_no);
-
        pci_read_config_byte(pdev, ICH5_PCS, &pcs);
        orig_mask = (int) pcs & 0xff;
 
@@ -437,28 +446,25 @@ static int piix_sata_probe (struct ata_port *ap)
 }
 
 /**
- *     piix_sata_phy_reset - Probe specified port on SATA host controller
- *     @ap: Port to probe
+ *     piix_sata_probe_reset - Perform reset on SATA port and classify
+ *     @ap: Port to reset
+ *     @classes: Resulting classes of attached devices
  *
- *     Probe SATA phy.
+ *     Reset SATA phy and classify attached devices.
  *
  *     LOCKING:
  *     None (inherited from caller).
  */
-
-static void piix_sata_phy_reset(struct ata_port *ap)
+static int piix_sata_probe_reset(struct ata_port *ap, unsigned int *classes)
 {
        if (!piix_sata_probe(ap)) {
-               ata_port_disable(ap);
                printk(KERN_INFO "ata%u: SATA port has no device.\n", ap->id);
-               return;
+               return 0;
        }
 
-       ap->cbl = ATA_CBL_SATA;
-
-       ata_port_probe(ap);
-
-       ata_bus_reset(ap);
+       return ata_drive_probe_reset(ap, ata_std_probeinit,
+                                    ata_std_softreset, NULL,
+                                    ata_std_postreset, classes);
 }
 
 /**
@@ -627,6 +633,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
@@ -680,6 +687,7 @@ static int piix_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
        struct ata_port_info *port_info[2];
        unsigned int combined = 0;
        unsigned int pata_chan = 0, sata_chan = 0;
+       unsigned long host_flags;
 
        if (!printed_version++)
                dev_printk(KERN_DEBUG, &pdev->dev,
@@ -692,7 +700,9 @@ static int piix_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
        port_info[0] = &piix_port_info[ent->driver_data];
        port_info[1] = &piix_port_info[ent->driver_data];
 
-       if (port_info[0]->host_flags & PIIX_FLAG_AHCI) {
+       host_flags = port_info[0]->host_flags;
+
+       if (host_flags & PIIX_FLAG_AHCI) {
                u8 tmp;
                pci_read_config_byte(pdev, PIIX_SCC, &tmp);
                if (tmp == PIIX_AHCI_DEVICE) {
@@ -702,16 +712,35 @@ static int piix_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
                }
        }
 
-       if (port_info[0]->host_flags & PIIX_FLAG_COMBINED) {
+       if (host_flags & PIIX_FLAG_COMBINED) {
                u8 tmp;
                pci_read_config_byte(pdev, ICH5_PMR, &tmp);
 
-               if (tmp & PIIX_COMB) {
-                       combined = 1;
-                       if (tmp & PIIX_COMB_PATA_P0)
+               if (host_flags & PIIX_FLAG_COMBINED_ICH6) {
+                       switch (tmp & 0x3) {
+                       case 0:
+                               break;
+                       case 1:
+                               combined = 1;
                                sata_chan = 1;
-                       else
+                               break;
+                       case 2:
+                               combined = 1;
                                pata_chan = 1;
+                               break;
+                       case 3:
+                               dev_printk(KERN_WARNING, &pdev->dev,
+                                          "invalid MAP value %u\n", tmp);
+                               break;
+                       }
+               } else {
+                       if (tmp & PIIX_COMB) {
+                               combined = 1;
+                               if (tmp & PIIX_COMB_PATA_P0)
+                                       sata_chan = 1;
+                               else
+                                       pata_chan = 1;
+                       }
                }
        }
 
@@ -721,7 +750,7 @@ static int piix_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
         * MSI is disabled (and it is disabled, as we don't use
         * message-signalled interrupts currently).
         */
-       if (port_info[0]->host_flags & PIIX_FLAG_CHECKINTR)
+       if (host_flags & PIIX_FLAG_CHECKINTR)
                pci_intx(pdev, 1);
 
        if (combined) {
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 5f1d7580218dde548ccd0d8ba4f71589ed5efcc6..70efde99f65220cb422a5689778587212e9cdcad 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);
@@ -73,7 +71,6 @@ 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_unique_id = 1;
 static struct workqueue_struct *ata_wq;
@@ -87,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
@@ -834,6 +434,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
@@ -846,11 +447,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;
@@ -861,8 +465,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)
@@ -870,22 +474,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
@@ -899,8 +501,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;
 
@@ -918,6 +520,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
@@ -1007,41 +652,41 @@ 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]);
 }
 
 /*
@@ -1073,24 +718,77 @@ static unsigned int ata_pio_modes(const struct ata_device *adev)
           timing API will get this right anyway */
 }
 
-struct ata_exec_internal_arg {
-       unsigned int err_mask;
-       struct ata_taskfile *tf;
-       struct completion *waiting;
-};
+static inline void
+ata_queue_packet_task(struct ata_port *ap)
+{
+       if (!(ap->flags & ATA_FLAG_FLUSH_PIO_TASK))
+               queue_work(ata_wq, &ap->packet_task);
+}
 
-int ata_qc_complete_internal(struct ata_queued_cmd *qc)
+static inline void
+ata_queue_pio_task(struct ata_port *ap)
 {
-       struct ata_exec_internal_arg *arg = qc->private_data;
-       struct completion *waiting = arg->waiting;
+       if (!(ap->flags & ATA_FLAG_FLUSH_PIO_TASK))
+               queue_work(ata_wq, &ap->pio_task);
+}
 
-       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;
-       complete(waiting);
+static inline void
+ata_queue_delayed_pio_task(struct ata_port *ap, unsigned long delay)
+{
+       if (!(ap->flags & ATA_FLAG_FLUSH_PIO_TASK))
+               queue_delayed_work(ata_wq, &ap->pio_task, delay);
+}
 
-       return 0;
+/**
+ *     ata_flush_pio_tasks - Flush pio_task and packet_task
+ *     @ap: the target ata_port
+ *
+ *     After this function completes, pio_task and packet_task are
+ *     guranteed not to be running or scheduled.
+ *
+ *     LOCKING:
+ *     Kernel thread context (may sleep)
+ */
+
+static void ata_flush_pio_tasks(struct ata_port *ap)
+{
+       int tmp = 0;
+       unsigned long flags;
+
+       DPRINTK("ENTER\n");
+
+       spin_lock_irqsave(&ap->host_set->lock, flags);
+       ap->flags |= ATA_FLAG_FLUSH_PIO_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.
+        */
+       tmp |= cancel_delayed_work(&ap->pio_task);
+       tmp |= cancel_delayed_work(&ap->packet_task);
+       if (!tmp) {
+               DPRINTK("flush #2\n");
+               flush_workqueue(ata_wq);
+       }
+
+       spin_lock_irqsave(&ap->host_set->lock, flags);
+       ap->flags &= ~ATA_FLAG_FLUSH_PIO_TASK;
+       spin_unlock_irqrestore(&ap->host_set->lock, flags);
+
+       DPRINTK("EXIT\n");
+}
+
+void ata_qc_complete_internal(struct ata_queued_cmd *qc)
+{
+       struct completion *waiting = qc->private_data;
+
+       qc->ap->ops->tf_read(qc->ap, &qc->tf);
+       complete(waiting);
 }
 
 /**
@@ -1121,7 +819,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);
 
@@ -1135,13 +833,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);
 
@@ -1154,8 +851,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);
@@ -1164,12 +861,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;
 }
 
 /**
@@ -1231,12 +928,11 @@ static void ata_dev_identify(struct ata_port *ap, unsigned int device)
 {
        struct ata_device *dev = &ap->device[device];
        unsigned int major_version;
-       u16 tmp;
        unsigned long xfer_modes;
        unsigned int using_edd;
        struct ata_taskfile tf;
        unsigned int err_mask;
-       int rc;
+       int i, rc;
 
        if (!ata_dev_present(dev)) {
                DPRINTK("ENTER/EXIT (host %u, dev %u) -- nodev\n",
@@ -1244,15 +940,16 @@ static void ata_dev_identify(struct ata_port *ap, unsigned int device)
                return;
        }
 
-       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);
+       WARN_ON(dev->class != ATA_DEV_ATA && dev->class != ATA_DEV_ATAPI &&
+               dev->class != ATA_DEV_NONE);
 
        ata_dev_select(ap, device, 1, 1); /* select device 0/1 */
 
@@ -1324,18 +1021,17 @@ retry:
        if (!xfer_modes)
                xfer_modes = ata_pio_modes(dev);
 
-       ata_dump_id(dev);
+       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_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;
+               major_version = ata_id_major_version(dev->id);
 
                /*
                 * The exact sequence expected by certain pre-ATA4 drives is:
@@ -1346,7 +1042,12 @@ retry:
                 * 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);
+                       err_mask = ata_dev_init_params(ap, dev);
+                       if (err_mask) {
+                               printk(KERN_ERR "ata%u: failed to init "
+                                      "parameters, disabled\n", ap->id);
+                               goto err_out;
+                       }
 
                        /* current CHS translation info (id[53-58]) might be
                         * changed. reread the identify device info.
@@ -1357,12 +1058,8 @@ retry:
                if (ata_id_has_lba(dev->id)) {
                        dev->flags |= ATA_DFLAG_LBA;
 
-                       if (ata_id_has_lba48(dev->id)) {
+                       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);
-                       }
 
                        /* print device info to dmesg */
                        printk(KERN_INFO "ata%u: dev %u ATA-%d, max %s, %Lu sectors:%s\n",
@@ -1378,15 +1075,12 @@ retry:
                        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 */
@@ -1399,7 +1093,7 @@ retry:
 
                }
 
-               ap->host->max_cmd_len = 16;
+               dev->cdb_len = 16;
        }
 
        /* ATAPI-specific feature tests */
@@ -1412,8 +1106,7 @@ retry:
                        printk(KERN_WARNING "ata%u: unsupported CDB len\n", ap->id);
                        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",
@@ -1421,6 +1114,12 @@ retry:
                       ata_mode_string(xfer_modes));
        }
 
+       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);
+
        DPRINTK("EXIT, drv_stat = 0x%x\n", ata_chk_status(ap));
        return;
 
@@ -1433,30 +1132,28 @@ err_out:
 }
 
 
-static inline u8 ata_dev_knobble(const struct ata_port *ap)
+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(ap->device->id)));
+       return ((ap->cbl == ATA_CBL_SATA) && (!ata_id_is_sata(dev->id)));
 }
 
 /**
- *     ata_dev_config - Run device specific handlers and check for
- *                      SATA->PATA bridges
- *     @ap: Bus
- *     @i:  Device
+ * ata_dev_config - Run device specific handlers & check for SATA->PATA bridges
+ * @ap: Bus
+ * @i:  Device
  *
- *     LOCKING:
+ * LOCKING:
  */
 
 void ata_dev_config(struct ata_port *ap, unsigned int i)
 {
        /* limit bridge transfers to udma5, 200 sectors */
-       if (ata_dev_knobble(ap)) {
+       if (ata_dev_knobble(ap, &ap->device[i])) {
                printk(KERN_INFO "ata%u(%u): applying bridge limits\n",
-                       ap->id, ap->device->devno);
+                      ap->id, i);
                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;
+               ap->device[i].max_sectors = ATA_MAX_SECTORS;
        }
 
        if (ap->ops->dev_config)
@@ -1482,7 +1179,27 @@ static int ata_bus_probe(struct ata_port *ap)
 {
        unsigned int i, found = 0;
 
-       ap->ops->phy_reset(ap);
+       if (ap->ops->probe_reset) {
+               unsigned int classes[ATA_MAX_DEVICES];
+               int rc;
+
+               ata_port_probe(ap);
+
+               rc = ap->ops->probe_reset(ap, classes);
+               if (rc == 0) {
+                       for (i = 0; i < ATA_MAX_DEVICES; i++) {
+                               if (classes[i] == ATA_DEV_UNKNOWN)
+                                       classes[i] = ATA_DEV_NONE;
+                               ap->device[i].class = classes[i];
+                       }
+               } else {
+                       printk(KERN_ERR "ata%u: probe reset failed, "
+                              "disabling port\n", ap->id);
+                       ata_port_disable(ap);
+               }
+       } else
+               ap->ops->phy_reset(ap);
+
        if (ap->flags & ATA_FLAG_PORT_DISABLED)
                goto err_out;
 
@@ -1525,6 +1242,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.
@@ -1559,27 +1311,14 @@ void __sata_phy_reset(struct ata_port *ap)
                        break;
        } while (time_before(jiffies, timeout));
 
-       /* TODO: phy layer with polling, timeouts, etc. */
-       sstatus = scr_read(ap, SCR_STATUS);
-       if (sata_dev_present(ap)) {
-               const char *speed;
-               u32 tmp;
+       /* print link status */
+       sata_print_link_status(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);
+       /* TODO: phy layer with polling, timeouts, etc. */
+       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;
@@ -1752,9 +1491,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) {
@@ -1763,7 +1502,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) {
@@ -1882,7 +1621,6 @@ 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)
 {
@@ -1921,6 +1659,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
@@ -1931,12 +1689,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;
@@ -2137,59 +1893,387 @@ void ata_bus_reset(struct ata_port *ap)
        /* 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);
-       }
+       /* 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)
-               goto err_out;
+               return rc;
 
-       /*
-        * determine by signature whether we have ATA or ATAPI devices
+       /* If any class isn't ATA_DEV_UNKNOWN, consider classification
+        * is complete and convert all ATA_DEV_UNKNOWN to
+        * ATA_DEV_NONE.
         */
-       err = ata_dev_try_classify(ap, 0);
-       if ((slave_possible) && (err != 0x81))
-               ata_dev_try_classify(ap, 1);
+       for (i = 0; i < ATA_MAX_DEVICES; i++)
+               if (classes[i] != ATA_DEV_UNKNOWN)
+                       break;
 
-       /* re-enable interrupts */
-       if (ap->ioaddr.ctl_addr)        /* FIXME: hack. create a hook instead */
-               ata_irq_on(ap);
+       if (i < ATA_MAX_DEVICES)
+               for (i = 0; i < ATA_MAX_DEVICES; i++)
+                       if (classes[i] == ATA_DEV_UNKNOWN)
+                               classes[i] = ATA_DEV_NONE;
 
-       /* 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 (postreset)
+               postreset(ap, classes);
 
-       /* 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;
+       return classes[0] != ATA_DEV_UNKNOWN ? 0 : -ENODEV;
+}
 
-       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);
+/**
+ *     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;
        }
 
-       DPRINTK("EXIT\n");
-       return;
+       if (!hardreset)
+               return rc;
 
-err_out:
-       printk(KERN_ERR "ata%u: disabling port\n", ap->id);
-       ap->ops->port_disable(ap);
+       rc = do_probe_reset(ap, hardreset, postreset, classes);
+       if (rc == 0 || rc != -ENODEV)
+               return rc;
 
-       DPRINTK("EXIT\n");
+       if (softreset)
+               rc = do_probe_reset(ap, softreset, postreset, classes);
+
+       return rc;
 }
 
 static void ata_pr_blacklisted(const struct ata_port *ap,
@@ -2233,24 +2317,13 @@ 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;
@@ -2264,7 +2337,7 @@ static unsigned int ata_get_mode_mask(const struct ata_port *ap, int shift)
        master = &ap->device[0];
        slave = &ap->device[1];
 
-       assert (ata_dev_present(master) || ata_dev_present(slave));
+       WARN_ON(!ata_dev_present(master) && !ata_dev_present(slave));
 
        if (shift == ATA_SHIFT_UDMA) {
                mask = ap->udma_mask;
@@ -2446,7 +2519,7 @@ static void ata_dev_reread_id(struct ata_port *ap, struct ata_device *dev)
 
        swap_buf_le16(dev->id, ATA_ID_WORDS);
 
-       ata_dump_id(dev);
+       ata_dump_id(dev->id);
 
        DPRINTK("EXIT\n");
 
@@ -2462,17 +2535,23 @@ err_out:
  *     @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");
@@ -2484,13 +2563,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;
 }
 
 /**
@@ -2510,11 +2586,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);
 
@@ -2569,8 +2645,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) {
@@ -2723,7 +2799,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);
 
@@ -2787,7 +2863,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;
@@ -2796,7 +2872,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);
 
@@ -2872,7 +2948,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:
@@ -2890,7 +2966,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:
@@ -2911,7 +2987,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;
                }
@@ -2958,7 +3034,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)) {
@@ -2969,7 +3045,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 */
@@ -2979,7 +3055,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.
  *
@@ -3289,7 +3365,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;
 }
 
@@ -3326,7 +3402,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)) {
@@ -3347,7 +3423,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;
                }
@@ -3361,7 +3437,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);
@@ -3369,7 +3445,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;
 
@@ -3410,7 +3486,7 @@ fsm_start:
        }
 
        if (timeout)
-               queue_delayed_work(ata_wq, &ap->pio_task, timeout);
+               ata_queue_delayed_pio_task(ap, timeout);
        else if (!qc_completed)
                goto fsm_start;
 }
@@ -3443,15 +3519,10 @@ static void ata_qc_timeout(struct ata_queued_cmd *qc)
 
        DPRINTK("ENTER\n");
 
-       spin_lock_irqsave(&host_set->lock, flags);
+       ata_flush_pio_tasks(ap);
+       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) {
 
@@ -3476,12 +3547,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");
 }
 
@@ -3506,20 +3578,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");
 }
 
@@ -3575,21 +3637,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
@@ -3602,29 +3649,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);
@@ -3636,17 +3679,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)
@@ -3686,20 +3719,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;
@@ -3712,8 +3745,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;
 }
 
 
@@ -3732,10 +3766,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;
 
@@ -3756,31 +3790,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_queue_pio_task(ap);
                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_queue_packet_task(ap);
                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_queue_packet_task(ap);
                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_queue_packet_task(ap);
                break;
 
        default:
                WARN_ON(1);
-               return -1;
+               return AC_ERR_SYSTEM;
        }
 
        return 0;
@@ -4164,26 +4198,26 @@ static void atapi_packet_task(void *_data)
        u8 status;
 
        qc = ata_qc_from_tag(ap, ap->active_tag);
-       assert(qc != NULL);
-       assert(qc->flags & ATA_QCFLAG_ACTIVE);
+       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_ATA_BUS;
+               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_ATA_BUS;
+               qc->err_mask |= AC_ERR_HSM;
                goto err_out;
        }
 
        /* send SCSI cdb */
        DPRINTK("send cdb\n");
-       assert(ap->cdb_len >= 12);
+       WARN_ON(qc->dev->cdb_len < 12);
 
        if (qc->tf.protocol == ATA_PROT_ATAPI_DMA ||
            qc->tf.protocol == ATA_PROT_ATAPI_NODATA) {
@@ -4197,16 +4231,16 @@ static void atapi_packet_task(void *_data)
                 */
                spin_lock_irqsave(&ap->host_set->lock, flags);
                ap->flags &= ~ATA_FLAG_NOINTR;
-               ata_data_xfer(ap, qc->cdb, ap->cdb_len, 1);
+               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, ap->cdb_len, 1);
+               ata_data_xfer(ap, qc->cdb, qc->dev->cdb_len, 1);
 
                /* PIO commands are handled by polling */
                ap->hsm_task_state = HSM_ST;
-               queue_work(ata_wq, &ap->pio_task);
+               ata_queue_pio_task(ap);
        }
 
        return;
@@ -4216,19 +4250,6 @@ err_out:
 }
 
 
-/**
- *     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,
  * without filling any other registers
@@ -4280,6 +4301,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
@@ -4302,10 +4325,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)
 {
@@ -4319,6 +4343,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;
@@ -4434,6 +4471,7 @@ static void ata_host_init(struct ata_port *ap, struct Scsi_Host *host,
 
        INIT_WORK(&ap->packet_task, atapi_packet_task, ap);
        INIT_WORK(&ap->pio_task, ata_pio_task, ap);
+       INIT_LIST_HEAD(&ap->eh_done_q);
 
        for (i = 0; i < ATA_MAX_DEVICES; i++)
                ap->device[i].devno = i;
@@ -4575,9 +4613,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?
@@ -4601,7 +4639,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];
 
@@ -4723,32 +4761,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
 
@@ -4759,256 +4771,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
@@ -5139,7 +4901,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);
@@ -5165,18 +4927,29 @@ 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_port_disable);
 EXPORT_SYMBOL_GPL(ata_ratelimit);
+EXPORT_SYMBOL_GPL(ata_busy_sleep);
 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_id_string);
+EXPORT_SYMBOL_GPL(ata_id_c_string);
 EXPORT_SYMBOL_GPL(ata_dev_config);
 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 07b1e7cc61dfcbc0ab5ce762be6d83ecb4f1f1db..538784e65cdc02977f9c424edd19011935dbb9f9 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,82 @@ 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);
+
        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 +1085,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 +1102,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 +1117,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 +1237,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 +1252,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 +1272,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 +1319,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 +1356,7 @@ static int ata_scsi_qc_complete(struct ata_queued_cmd *qc)
 
        qc->scsidone(cmd);
 
-       return 0;
+       ata_qc_free(qc);
 }
 
 /**
@@ -1328,8 +1422,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 +1567,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 +1642,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;
 }
@@ -1711,15 +1806,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 */
@@ -2013,7 +2105,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
@@ -2024,7 +2116,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"? */
@@ -2054,7 +2146,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;
 
@@ -2073,15 +2165,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;
@@ -2091,7 +2182,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))
@@ -2131,7 +2222,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
@@ -2157,7 +2248,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;
 
@@ -2517,7 +2608,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 e03ce48b7b4b633c8752319470cdb56105054659..9d76923a22536eeb850427757fed3d794b0c270a 100644 (file)
@@ -45,7 +45,7 @@ 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_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..ba2b7a0983dbfc3f40e946050541152669a05441 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 },
 
@@ -232,7 +260,7 @@ static const struct pci_device_id pdc_ata_pci_tbl[] = {
        { 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 +289,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 +325,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 +431,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 +438,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 +447,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 +517,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 +542,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 +567,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 +623,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 +639,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 +666,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 +697,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 +713,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 +742,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 +755,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 +784,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 17f74d3c10e7c76ff4ef97846c61baa72bb9f4b4..e14ed4ebbeed8632fe6be6ca4157a280d930797e 100644 (file)
@@ -135,11 +135,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,
@@ -157,7 +157,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,
@@ -180,7 +180,7 @@ static const struct ata_port_info sil_port_info[] = {
        {
                .sht            = &sil_sht,
                .host_flags     = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
-                                 ATA_FLAG_SRST | ATA_FLAG_MMIO,
+                                 ATA_FLAG_MMIO,
                .pio_mask       = 0x1f,                 /* pio0-4 */
                .mwdma_mask     = 0x07,                 /* mwdma0-2 */
                .udma_mask      = 0x3f,                 /* udma0-5 */
@@ -189,8 +189,7 @@ static const struct ata_port_info sil_port_info[] = {
        {
                .sht            = &sil_sht,
                .host_flags     = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
-                                 ATA_FLAG_SRST | ATA_FLAG_MMIO |
-                                 SIL_FLAG_MOD15WRITE,
+                                 ATA_FLAG_MMIO | SIL_FLAG_MOD15WRITE,
                .pio_mask       = 0x1f,                 /* pio0-4 */
                .mwdma_mask     = 0x07,                 /* mwdma0-2 */
                .udma_mask      = 0x3f,                 /* udma0-5 */
@@ -199,7 +198,7 @@ static const struct ata_port_info sil_port_info[] = {
        {
                .sht            = &sil_sht,
                .host_flags     = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
-                                 ATA_FLAG_SRST | ATA_FLAG_MMIO,
+                                 ATA_FLAG_MMIO,
                .pio_mask       = 0x1f,                 /* pio0-4 */
                .mwdma_mask     = 0x07,                 /* mwdma0-2 */
                .udma_mask      = 0x3f,                 /* udma0-5 */
@@ -337,22 +336,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;
                }
@@ -363,16 +352,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;
        }
index 923130185a9e417c4570c04fe88298ce265fe102..a0e35a2621569ad2cec6f4e9cac9f54627e56710 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);
@@ -280,11 +280,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 +305,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 +335,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 +346,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 +357,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 +370,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,7 +427,8 @@ 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;
@@ -436,6 +437,8 @@ static int sil24_issue_SRST(struct ata_port *ap)
        u32 irq_enable, irq_stat;
        int cnt;
 
+       DPRINTK("ENTER\n");
+
        /* temporarily turn off IRQs during SRST */
        irq_enable = readl(port + PORT_IRQ_ENABLE_SET);
        writel(irq_enable, port + PORT_IRQ_ENABLE_CLR);
@@ -465,30 +468,36 @@ static int sil24_issue_SRST(struct ata_port *ap)
        /* restore IRQs */
        writel(irq_enable, port + PORT_IRQ_ENABLE_SET);
 
-       if (!(irq_stat & PORT_IRQ_COMPLETE))
-               return -1;
+       if (sata_dev_present(ap)) {
+               if (!(irq_stat & PORT_IRQ_COMPLETE)) {
+                       DPRINTK("EXIT, srst failed\n");
+                       return -EIO;
+               }
 
-       /* update TF */
-       sil24_update_tf(ap);
+               sil24_update_tf(ap);
+               *class = ata_dev_classify(&pp->tf);
+       }
+       if (*class == ATA_DEV_UNKNOWN)
+               *class = ATA_DEV_NONE;
+
+       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;
-
-       __sata_phy_reset(ap);
-       if (ap->flags & ATA_FLAG_PORT_DISABLED)
-               return;
+       unsigned int dummy_class;
 
-       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 +542,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 +566,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 +647,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);
 }
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 5cc97b721661471b38a57346a6bebb759fc9ec10..50f8057be75de1b5aae4b0eba0a5a7c565b1e385 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..66b6847225df10bdead7a9f02bef8e710d1d1b52 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_PIO_TASK = (1 << 15), /* Flush PIO 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 */
@@ -189,10 +215,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 +233,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;
@@ -313,6 +347,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 +378,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];
 
@@ -359,6 +394,9 @@ struct ata_port {
        unsigned int            hsm_task_state;
        unsigned long           pio_task_timeout;
 
+       u32                     msg_enable;
+       struct list_head        eh_done_q;
+
        void                    *private_data;
 };
 
@@ -378,7 +416,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 +427,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 +475,16 @@ 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 void ata_port_disable(struct ata_port *);
 extern void ata_std_ports(struct ata_ioports *ioaddr);
 #ifdef CONFIG_PCI
@@ -449,7 +499,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 +510,9 @@ 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);
 
 /*
  * Default driver ops implementations
@@ -470,26 +526,29 @@ 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_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_dev_config(struct ata_port *ap, unsigned int i);
 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,
@@ -657,9 +716,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 +760,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 +828,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 +847,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 +887,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 *);