Move libata to drivers/ata.
authorJeff Garzik <jeff@garzik.org>
Thu, 10 Aug 2006 11:31:37 +0000 (07:31 -0400)
committerJeff Garzik <jeff@garzik.org>
Thu, 10 Aug 2006 11:31:37 +0000 (07:31 -0400)
48 files changed:
drivers/Kconfig
drivers/Makefile
drivers/ata/Kconfig [new file with mode: 0644]
drivers/ata/Makefile [new file with mode: 0644]
drivers/ata/ahci.c [new file with mode: 0644]
drivers/ata/ata_piix.c [new file with mode: 0644]
drivers/ata/libata-bmdma.c [new file with mode: 0644]
drivers/ata/libata-core.c [new file with mode: 0644]
drivers/ata/libata-eh.c [new file with mode: 0644]
drivers/ata/libata-scsi.c [new file with mode: 0644]
drivers/ata/libata.h [new file with mode: 0644]
drivers/ata/pdc_adma.c [new file with mode: 0644]
drivers/ata/sata_mv.c [new file with mode: 0644]
drivers/ata/sata_nv.c [new file with mode: 0644]
drivers/ata/sata_promise.c [new file with mode: 0644]
drivers/ata/sata_promise.h [new file with mode: 0644]
drivers/ata/sata_qstor.c [new file with mode: 0644]
drivers/ata/sata_sil.c [new file with mode: 0644]
drivers/ata/sata_sil24.c [new file with mode: 0644]
drivers/ata/sata_sis.c [new file with mode: 0644]
drivers/ata/sata_svw.c [new file with mode: 0644]
drivers/ata/sata_sx4.c [new file with mode: 0644]
drivers/ata/sata_uli.c [new file with mode: 0644]
drivers/ata/sata_via.c [new file with mode: 0644]
drivers/ata/sata_vsc.c [new file with mode: 0644]
drivers/scsi/Kconfig
drivers/scsi/Makefile
drivers/scsi/ahci.c [deleted file]
drivers/scsi/ata_piix.c [deleted file]
drivers/scsi/libata-bmdma.c [deleted file]
drivers/scsi/libata-core.c [deleted file]
drivers/scsi/libata-eh.c [deleted file]
drivers/scsi/libata-scsi.c [deleted file]
drivers/scsi/libata.h [deleted file]
drivers/scsi/pdc_adma.c [deleted file]
drivers/scsi/sata_mv.c [deleted file]
drivers/scsi/sata_nv.c [deleted file]
drivers/scsi/sata_promise.c [deleted file]
drivers/scsi/sata_promise.h [deleted file]
drivers/scsi/sata_qstor.c [deleted file]
drivers/scsi/sata_sil.c [deleted file]
drivers/scsi/sata_sil24.c [deleted file]
drivers/scsi/sata_sis.c [deleted file]
drivers/scsi/sata_svw.c [deleted file]
drivers/scsi/sata_sx4.c [deleted file]
drivers/scsi/sata_uli.c [deleted file]
drivers/scsi/sata_via.c [deleted file]
drivers/scsi/sata_vsc.c [deleted file]

index 8b11ceb..263e86d 100644 (file)
@@ -18,6 +18,8 @@ source "drivers/ide/Kconfig"
 
 source "drivers/scsi/Kconfig"
 
+source "drivers/ata/Kconfig"
+
 source "drivers/cdrom/Kconfig"
 
 source "drivers/md/Kconfig"
index fc2d744..4ac14da 100644 (file)
@@ -34,6 +34,7 @@ obj-$(CONFIG_PPC_PMAC)                += macintosh/
 obj-$(CONFIG_IDE)              += ide/
 obj-$(CONFIG_FC4)              += fc4/
 obj-$(CONFIG_SCSI)             += scsi/
+obj-$(CONFIG_ATA)              += ata/
 obj-$(CONFIG_FUSION)           += message/
 obj-$(CONFIG_IEEE1394)         += ieee1394/
 obj-y                          += cdrom/
diff --git a/drivers/ata/Kconfig b/drivers/ata/Kconfig
new file mode 100644 (file)
index 0000000..95d6b41
--- /dev/null
@@ -0,0 +1,140 @@
+
+config ATA
+       tristate "ATA device support"
+       depends on SCSI
+       ---help---
+         If you want to use a ATA hard disk, ATA tape drive, ATA CD-ROM or
+         any other ATA device under Linux, say Y and make sure that you know
+         the name of your ATA host adapter (the card inside your computer
+         that "speaks" the ATA protocol, also called ATA controller),
+         because you will be asked for it.
+
+config SCSI_SATA_AHCI
+       tristate "AHCI SATA support"
+       depends on ATA && PCI
+       help
+         This option enables support for AHCI Serial ATA.
+
+         If unsure, say N.
+
+config SCSI_SATA_SVW
+       tristate "ServerWorks Frodo / Apple K2 SATA support"
+       depends on ATA && PCI
+       help
+         This option enables support for Broadcom/Serverworks/Apple K2
+         SATA support.
+
+         If unsure, say N.
+
+config SCSI_ATA_PIIX
+       tristate "Intel PIIX/ICH SATA support"
+       depends on ATA && PCI
+       help
+         This option enables support for ICH5/6/7/8 Serial ATA.
+         If PATA support was enabled previously, this enables
+         support for select Intel PIIX/ICH PATA host controllers.
+
+         If unsure, say N.
+
+config SCSI_SATA_MV
+       tristate "Marvell SATA support (HIGHLY EXPERIMENTAL)"
+       depends on ATA && PCI && EXPERIMENTAL
+       help
+         This option enables support for the Marvell Serial ATA family.
+         Currently supports 88SX[56]0[48][01] chips.
+
+         If unsure, say N.
+
+config SCSI_SATA_NV
+       tristate "NVIDIA SATA support"
+       depends on ATA && PCI
+       help
+         This option enables support for NVIDIA Serial ATA.
+
+         If unsure, say N.
+
+config SCSI_PDC_ADMA
+       tristate "Pacific Digital ADMA support"
+       depends on ATA && PCI
+       help
+         This option enables support for Pacific Digital ADMA controllers
+
+         If unsure, say N.
+
+config SCSI_SATA_QSTOR
+       tristate "Pacific Digital SATA QStor support"
+       depends on ATA && PCI
+       help
+         This option enables support for Pacific Digital Serial ATA QStor.
+
+         If unsure, say N.
+
+config SCSI_SATA_PROMISE
+       tristate "Promise SATA TX2/TX4 support"
+       depends on ATA && PCI
+       help
+         This option enables support for Promise Serial ATA TX2/TX4.
+
+         If unsure, say N.
+
+config SCSI_SATA_SX4
+       tristate "Promise SATA SX4 support"
+       depends on ATA && PCI && EXPERIMENTAL
+       help
+         This option enables support for Promise Serial ATA SX4.
+
+         If unsure, say N.
+
+config SCSI_SATA_SIL
+       tristate "Silicon Image SATA support"
+       depends on ATA && PCI
+       help
+         This option enables support for Silicon Image Serial ATA.
+
+         If unsure, say N.
+
+config SCSI_SATA_SIL24
+       tristate "Silicon Image 3124/3132 SATA support"
+       depends on ATA && PCI
+       help
+         This option enables support for Silicon Image 3124/3132 Serial ATA.
+
+         If unsure, say N.
+
+config SCSI_SATA_SIS
+       tristate "SiS 964/180 SATA support"
+       depends on ATA && PCI
+       help
+         This option enables support for SiS Serial ATA 964/180.
+
+         If unsure, say N.
+
+config SCSI_SATA_ULI
+       tristate "ULi Electronics SATA support"
+       depends on ATA && PCI
+       help
+         This option enables support for ULi Electronics SATA.
+
+         If unsure, say N.
+
+config SCSI_SATA_VIA
+       tristate "VIA SATA support"
+       depends on ATA && PCI
+       help
+         This option enables support for VIA Serial ATA.
+
+         If unsure, say N.
+
+config SCSI_SATA_VITESSE
+       tristate "VITESSE VSC-7174 / INTEL 31244 SATA support"
+       depends on ATA && PCI
+       help
+         This option enables support for Vitesse VSC7174 and Intel 31244 Serial ATA.
+
+         If unsure, say N.
+
+config SCSI_SATA_INTEL_COMBINED
+       bool
+       depends on IDE=y && !BLK_DEV_IDE_SATA && (SCSI_SATA_AHCI || SCSI_ATA_PIIX)
+       default y
+
diff --git a/drivers/ata/Makefile b/drivers/ata/Makefile
new file mode 100644 (file)
index 0000000..60bdb7b
--- /dev/null
@@ -0,0 +1,19 @@
+
+obj-$(CONFIG_SCSI_SATA_AHCI)   += libata.o ahci.o
+obj-$(CONFIG_SCSI_SATA_SVW)    += libata.o sata_svw.o
+obj-$(CONFIG_SCSI_ATA_PIIX)    += libata.o ata_piix.o
+obj-$(CONFIG_SCSI_SATA_PROMISE)        += libata.o sata_promise.o
+obj-$(CONFIG_SCSI_SATA_QSTOR)  += libata.o sata_qstor.o
+obj-$(CONFIG_SCSI_SATA_SIL)    += libata.o sata_sil.o
+obj-$(CONFIG_SCSI_SATA_SIL24)  += libata.o sata_sil24.o
+obj-$(CONFIG_SCSI_SATA_VIA)    += libata.o sata_via.o
+obj-$(CONFIG_SCSI_SATA_VITESSE)        += libata.o sata_vsc.o
+obj-$(CONFIG_SCSI_SATA_SIS)    += libata.o sata_sis.o
+obj-$(CONFIG_SCSI_SATA_SX4)    += libata.o sata_sx4.o
+obj-$(CONFIG_SCSI_SATA_NV)     += libata.o sata_nv.o
+obj-$(CONFIG_SCSI_SATA_ULI)    += libata.o sata_uli.o
+obj-$(CONFIG_SCSI_SATA_MV)     += libata.o sata_mv.o
+obj-$(CONFIG_SCSI_PDC_ADMA)    += libata.o pdc_adma.o
+
+libata-objs    := libata-core.o libata-scsi.o libata-bmdma.o libata-eh.o
+
diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c
new file mode 100644 (file)
index 0000000..813031c
--- /dev/null
@@ -0,0 +1,1684 @@
+/*
+ *  ahci.c - AHCI SATA support
+ *
+ *  Maintained by:  Jeff Garzik <jgarzik@pobox.com>
+ *                 Please ALWAYS copy linux-ide@vger.kernel.org
+ *                 on emails.
+ *
+ *  Copyright 2004-2005 Red Hat, Inc.
+ *
+ *
+ *  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.*
+ *
+ * AHCI hardware documentation:
+ * http://www.intel.com/technology/serialata/pdf/rev1_0.pdf
+ * http://www.intel.com/technology/serialata/pdf/rev1_1.pdf
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/pci.h>
+#include <linux/init.h>
+#include <linux/blkdev.h>
+#include <linux/delay.h>
+#include <linux/interrupt.h>
+#include <linux/sched.h>
+#include <linux/dma-mapping.h>
+#include <linux/device.h>
+#include <scsi/scsi_host.h>
+#include <scsi/scsi_cmnd.h>
+#include <linux/libata.h>
+#include <asm/io.h>
+
+#define DRV_NAME       "ahci"
+#define DRV_VERSION    "2.0"
+
+
+enum {
+       AHCI_PCI_BAR            = 5,
+       AHCI_MAX_SG             = 168, /* hardware max is 64K */
+       AHCI_DMA_BOUNDARY       = 0xffffffff,
+       AHCI_USE_CLUSTERING     = 0,
+       AHCI_MAX_CMDS           = 32,
+       AHCI_CMD_SZ             = 32,
+       AHCI_CMD_SLOT_SZ        = AHCI_MAX_CMDS * AHCI_CMD_SZ,
+       AHCI_RX_FIS_SZ          = 256,
+       AHCI_CMD_TBL_CDB        = 0x40,
+       AHCI_CMD_TBL_HDR_SZ     = 0x80,
+       AHCI_CMD_TBL_SZ         = AHCI_CMD_TBL_HDR_SZ + (AHCI_MAX_SG * 16),
+       AHCI_CMD_TBL_AR_SZ      = AHCI_CMD_TBL_SZ * AHCI_MAX_CMDS,
+       AHCI_PORT_PRIV_DMA_SZ   = AHCI_CMD_SLOT_SZ + AHCI_CMD_TBL_AR_SZ +
+                                 AHCI_RX_FIS_SZ,
+       AHCI_IRQ_ON_SG          = (1 << 31),
+       AHCI_CMD_ATAPI          = (1 << 5),
+       AHCI_CMD_WRITE          = (1 << 6),
+       AHCI_CMD_PREFETCH       = (1 << 7),
+       AHCI_CMD_RESET          = (1 << 8),
+       AHCI_CMD_CLR_BUSY       = (1 << 10),
+
+       RX_FIS_D2H_REG          = 0x40, /* offset of D2H Register FIS data */
+       RX_FIS_UNK              = 0x60, /* offset of Unknown FIS data */
+
+       board_ahci              = 0,
+       board_ahci_vt8251       = 1,
+
+       /* global controller registers */
+       HOST_CAP                = 0x00, /* host capabilities */
+       HOST_CTL                = 0x04, /* global host control */
+       HOST_IRQ_STAT           = 0x08, /* interrupt status */
+       HOST_PORTS_IMPL         = 0x0c, /* bitmap of implemented ports */
+       HOST_VERSION            = 0x10, /* AHCI spec. version compliancy */
+
+       /* HOST_CTL bits */
+       HOST_RESET              = (1 << 0),  /* reset controller; self-clear */
+       HOST_IRQ_EN             = (1 << 1),  /* global IRQ enable */
+       HOST_AHCI_EN            = (1 << 31), /* AHCI enabled */
+
+       /* HOST_CAP bits */
+       HOST_CAP_SSC            = (1 << 14), /* Slumber capable */
+       HOST_CAP_CLO            = (1 << 24), /* Command List Override support */
+       HOST_CAP_SSS            = (1 << 27), /* Staggered Spin-up */
+       HOST_CAP_NCQ            = (1 << 30), /* Native Command Queueing */
+       HOST_CAP_64             = (1 << 31), /* PCI DAC (64-bit DMA) support */
+
+       /* registers for each SATA port */
+       PORT_LST_ADDR           = 0x00, /* command list DMA addr */
+       PORT_LST_ADDR_HI        = 0x04, /* command list DMA addr hi */
+       PORT_FIS_ADDR           = 0x08, /* FIS rx buf addr */
+       PORT_FIS_ADDR_HI        = 0x0c, /* FIS rx buf addr hi */
+       PORT_IRQ_STAT           = 0x10, /* interrupt status */
+       PORT_IRQ_MASK           = 0x14, /* interrupt enable/disable mask */
+       PORT_CMD                = 0x18, /* port command */
+       PORT_TFDATA             = 0x20, /* taskfile data */
+       PORT_SIG                = 0x24, /* device TF signature */
+       PORT_CMD_ISSUE          = 0x38, /* command issue */
+       PORT_SCR                = 0x28, /* SATA phy register block */
+       PORT_SCR_STAT           = 0x28, /* SATA phy register: SStatus */
+       PORT_SCR_CTL            = 0x2c, /* SATA phy register: SControl */
+       PORT_SCR_ERR            = 0x30, /* SATA phy register: SError */
+       PORT_SCR_ACT            = 0x34, /* SATA phy register: SActive */
+
+       /* PORT_IRQ_{STAT,MASK} bits */
+       PORT_IRQ_COLD_PRES      = (1 << 31), /* cold presence detect */
+       PORT_IRQ_TF_ERR         = (1 << 30), /* task file error */
+       PORT_IRQ_HBUS_ERR       = (1 << 29), /* host bus fatal error */
+       PORT_IRQ_HBUS_DATA_ERR  = (1 << 28), /* host bus data error */
+       PORT_IRQ_IF_ERR         = (1 << 27), /* interface fatal error */
+       PORT_IRQ_IF_NONFATAL    = (1 << 26), /* interface non-fatal error */
+       PORT_IRQ_OVERFLOW       = (1 << 24), /* xfer exhausted available S/G */
+       PORT_IRQ_BAD_PMP        = (1 << 23), /* incorrect port multiplier */
+
+       PORT_IRQ_PHYRDY         = (1 << 22), /* PhyRdy changed */
+       PORT_IRQ_DEV_ILCK       = (1 << 7), /* device interlock */
+       PORT_IRQ_CONNECT        = (1 << 6), /* port connect change status */
+       PORT_IRQ_SG_DONE        = (1 << 5), /* descriptor processed */
+       PORT_IRQ_UNK_FIS        = (1 << 4), /* unknown FIS rx'd */
+       PORT_IRQ_SDB_FIS        = (1 << 3), /* Set Device Bits FIS rx'd */
+       PORT_IRQ_DMAS_FIS       = (1 << 2), /* DMA Setup FIS rx'd */
+       PORT_IRQ_PIOS_FIS       = (1 << 1), /* PIO Setup FIS rx'd */
+       PORT_IRQ_D2H_REG_FIS    = (1 << 0), /* D2H Register FIS rx'd */
+
+       PORT_IRQ_FREEZE         = PORT_IRQ_HBUS_ERR |
+                                 PORT_IRQ_IF_ERR |
+                                 PORT_IRQ_CONNECT |
+                                 PORT_IRQ_PHYRDY |
+                                 PORT_IRQ_UNK_FIS,
+       PORT_IRQ_ERROR          = PORT_IRQ_FREEZE |
+                                 PORT_IRQ_TF_ERR |
+                                 PORT_IRQ_HBUS_DATA_ERR,
+       DEF_PORT_IRQ            = PORT_IRQ_ERROR | PORT_IRQ_SG_DONE |
+                                 PORT_IRQ_SDB_FIS | PORT_IRQ_DMAS_FIS |
+                                 PORT_IRQ_PIOS_FIS | PORT_IRQ_D2H_REG_FIS,
+
+       /* PORT_CMD bits */
+       PORT_CMD_ATAPI          = (1 << 24), /* Device is ATAPI */
+       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 */
+
+       PORT_CMD_ICC_MASK       = (0xf << 28), /* i/f ICC state mask */
+       PORT_CMD_ICC_ACTIVE     = (0x1 << 28), /* Put i/f in active state */
+       PORT_CMD_ICC_PARTIAL    = (0x2 << 28), /* Put i/f in partial state */
+       PORT_CMD_ICC_SLUMBER    = (0x6 << 28), /* Put i/f in slumber state */
+
+       /* hpriv->flags bits */
+       AHCI_FLAG_MSI           = (1 << 0),
+
+       /* ap->flags bits */
+       AHCI_FLAG_RESET_NEEDS_CLO       = (1 << 24),
+       AHCI_FLAG_NO_NCQ                = (1 << 25),
+};
+
+struct ahci_cmd_hdr {
+       u32                     opts;
+       u32                     status;
+       u32                     tbl_addr;
+       u32                     tbl_addr_hi;
+       u32                     reserved[4];
+};
+
+struct ahci_sg {
+       u32                     addr;
+       u32                     addr_hi;
+       u32                     reserved;
+       u32                     flags_size;
+};
+
+struct ahci_host_priv {
+       unsigned long           flags;
+       u32                     cap;    /* cache of HOST_CAP register */
+       u32                     port_map; /* cache of HOST_PORTS_IMPL reg */
+};
+
+struct ahci_port_priv {
+       struct ahci_cmd_hdr     *cmd_slot;
+       dma_addr_t              cmd_slot_dma;
+       void                    *cmd_tbl;
+       dma_addr_t              cmd_tbl_dma;
+       void                    *rx_fis;
+       dma_addr_t              rx_fis_dma;
+};
+
+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 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_irq_clear(struct ata_port *ap);
+static int ahci_port_start(struct ata_port *ap);
+static void ahci_port_stop(struct ata_port *ap);
+static void ahci_tf_read(struct ata_port *ap, struct ata_taskfile *tf);
+static void ahci_qc_prep(struct ata_queued_cmd *qc);
+static u8 ahci_check_status(struct ata_port *ap);
+static void ahci_freeze(struct ata_port *ap);
+static void ahci_thaw(struct ata_port *ap);
+static void ahci_error_handler(struct ata_port *ap);
+static void ahci_post_internal_cmd(struct ata_queued_cmd *qc);
+static int ahci_port_suspend(struct ata_port *ap, pm_message_t mesg);
+static int ahci_port_resume(struct ata_port *ap);
+static int ahci_pci_device_suspend(struct pci_dev *pdev, pm_message_t mesg);
+static int ahci_pci_device_resume(struct pci_dev *pdev);
+static void ahci_remove_one (struct pci_dev *pdev);
+
+static struct scsi_host_template ahci_sht = {
+       .module                 = THIS_MODULE,
+       .name                   = DRV_NAME,
+       .ioctl                  = ata_scsi_ioctl,
+       .queuecommand           = ata_scsi_queuecmd,
+       .change_queue_depth     = ata_scsi_change_queue_depth,
+       .can_queue              = AHCI_MAX_CMDS - 1,
+       .this_id                = ATA_SHT_THIS_ID,
+       .sg_tablesize           = AHCI_MAX_SG,
+       .cmd_per_lun            = ATA_SHT_CMD_PER_LUN,
+       .emulated               = ATA_SHT_EMULATED,
+       .use_clustering         = AHCI_USE_CLUSTERING,
+       .proc_name              = DRV_NAME,
+       .dma_boundary           = AHCI_DMA_BOUNDARY,
+       .slave_configure        = ata_scsi_slave_config,
+       .slave_destroy          = ata_scsi_slave_destroy,
+       .bios_param             = ata_std_bios_param,
+       .suspend                = ata_scsi_device_suspend,
+       .resume                 = ata_scsi_device_resume,
+};
+
+static const struct ata_port_operations ahci_ops = {
+       .port_disable           = ata_port_disable,
+
+       .check_status           = ahci_check_status,
+       .check_altstatus        = ahci_check_status,
+       .dev_select             = ata_noop_dev_select,
+
+       .tf_read                = ahci_tf_read,
+
+       .qc_prep                = ahci_qc_prep,
+       .qc_issue               = ahci_qc_issue,
+
+       .irq_handler            = ahci_interrupt,
+       .irq_clear              = ahci_irq_clear,
+
+       .scr_read               = ahci_scr_read,
+       .scr_write              = ahci_scr_write,
+
+       .freeze                 = ahci_freeze,
+       .thaw                   = ahci_thaw,
+
+       .error_handler          = ahci_error_handler,
+       .post_internal_cmd      = ahci_post_internal_cmd,
+
+       .port_suspend           = ahci_port_suspend,
+       .port_resume            = ahci_port_resume,
+
+       .port_start             = ahci_port_start,
+       .port_stop              = ahci_port_stop,
+};
+
+static const struct ata_port_info ahci_port_info[] = {
+       /* board_ahci */
+       {
+               .sht            = &ahci_sht,
+               .host_flags     = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
+                                 ATA_FLAG_MMIO | ATA_FLAG_PIO_DMA |
+                                 ATA_FLAG_SKIP_D2H_BSY,
+               .pio_mask       = 0x1f, /* pio0-4 */
+               .udma_mask      = 0x7f, /* udma0-6 ; FIXME */
+               .port_ops       = &ahci_ops,
+       },
+       /* board_ahci_vt8251 */
+       {
+               .sht            = &ahci_sht,
+               .host_flags     = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
+                                 ATA_FLAG_MMIO | ATA_FLAG_PIO_DMA |
+                                 ATA_FLAG_SKIP_D2H_BSY |
+                                 AHCI_FLAG_RESET_NEEDS_CLO | AHCI_FLAG_NO_NCQ,
+               .pio_mask       = 0x1f, /* pio0-4 */
+               .udma_mask      = 0x7f, /* udma0-6 ; FIXME */
+               .port_ops       = &ahci_ops,
+       },
+};
+
+static const struct pci_device_id ahci_pci_tbl[] = {
+       /* Intel */
+       { PCI_VENDOR_ID_INTEL, 0x2652, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+         board_ahci }, /* ICH6 */
+       { PCI_VENDOR_ID_INTEL, 0x2653, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+         board_ahci }, /* ICH6M */
+       { PCI_VENDOR_ID_INTEL, 0x27c1, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+         board_ahci }, /* ICH7 */
+       { PCI_VENDOR_ID_INTEL, 0x27c5, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+         board_ahci }, /* ICH7M */
+       { PCI_VENDOR_ID_INTEL, 0x27c3, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+         board_ahci }, /* ICH7R */
+       { PCI_VENDOR_ID_AL, 0x5288, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+         board_ahci }, /* ULi M5288 */
+       { PCI_VENDOR_ID_INTEL, 0x2681, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+         board_ahci }, /* ESB2 */
+       { PCI_VENDOR_ID_INTEL, 0x2682, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+         board_ahci }, /* ESB2 */
+       { PCI_VENDOR_ID_INTEL, 0x2683, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+         board_ahci }, /* ESB2 */
+       { PCI_VENDOR_ID_INTEL, 0x27c6, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+         board_ahci }, /* ICH7-M DH */
+       { PCI_VENDOR_ID_INTEL, 0x2821, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+         board_ahci }, /* ICH8 */
+       { PCI_VENDOR_ID_INTEL, 0x2822, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+         board_ahci }, /* ICH8 */
+       { PCI_VENDOR_ID_INTEL, 0x2824, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+         board_ahci }, /* ICH8 */
+       { PCI_VENDOR_ID_INTEL, 0x2829, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+         board_ahci }, /* ICH8M */
+       { PCI_VENDOR_ID_INTEL, 0x282a, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+         board_ahci }, /* ICH8M */
+
+       /* JMicron */
+       { 0x197b, 0x2360, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+         board_ahci }, /* JMicron JMB360 */
+       { 0x197b, 0x2361, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+         board_ahci }, /* JMicron JMB361 */
+       { 0x197b, 0x2363, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+         board_ahci }, /* JMicron JMB363 */
+       { 0x197b, 0x2365, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+         board_ahci }, /* JMicron JMB365 */
+       { 0x197b, 0x2366, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+         board_ahci }, /* JMicron JMB366 */
+
+       /* ATI */
+       { PCI_VENDOR_ID_ATI, 0x4380, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+         board_ahci }, /* ATI SB600 non-raid */
+       { PCI_VENDOR_ID_ATI, 0x4381, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+         board_ahci }, /* ATI SB600 raid */
+
+       /* VIA */
+       { PCI_VENDOR_ID_VIA, 0x3349, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+         board_ahci_vt8251 }, /* VIA VT8251 */
+
+       /* NVIDIA */
+       { PCI_VENDOR_ID_NVIDIA, 0x044c, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+         board_ahci },         /* MCP65 */
+       { PCI_VENDOR_ID_NVIDIA, 0x044d, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+         board_ahci },         /* MCP65 */
+       { PCI_VENDOR_ID_NVIDIA, 0x044e, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+         board_ahci },         /* MCP65 */
+       { PCI_VENDOR_ID_NVIDIA, 0x044f, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+         board_ahci },         /* MCP65 */
+
+       /* SiS */
+       { PCI_VENDOR_ID_SI, 0x1184, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+         board_ahci }, /* SiS 966 */
+       { PCI_VENDOR_ID_SI, 0x1185, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+         board_ahci }, /* SiS 966 */
+       { PCI_VENDOR_ID_SI, 0x0186, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+         board_ahci }, /* SiS 968 */
+
+       { }     /* terminate list */
+};
+
+
+static struct pci_driver ahci_pci_driver = {
+       .name                   = DRV_NAME,
+       .id_table               = ahci_pci_tbl,
+       .probe                  = ahci_init_one,
+       .suspend                = ahci_pci_device_suspend,
+       .resume                 = ahci_pci_device_resume,
+       .remove                 = ahci_remove_one,
+};
+
+
+static inline unsigned long ahci_port_base_ul (unsigned long base, unsigned int port)
+{
+       return base + 0x100 + (port * 0x80);
+}
+
+static inline void __iomem *ahci_port_base (void __iomem *base, unsigned int port)
+{
+       return (void __iomem *) ahci_port_base_ul((unsigned long)base, port);
+}
+
+static u32 ahci_scr_read (struct ata_port *ap, unsigned int sc_reg_in)
+{
+       unsigned int sc_reg;
+
+       switch (sc_reg_in) {
+       case SCR_STATUS:        sc_reg = 0; break;
+       case SCR_CONTROL:       sc_reg = 1; break;
+       case SCR_ERROR:         sc_reg = 2; break;
+       case SCR_ACTIVE:        sc_reg = 3; break;
+       default:
+               return 0xffffffffU;
+       }
+
+       return readl((void __iomem *) ap->ioaddr.scr_addr + (sc_reg * 4));
+}
+
+
+static void ahci_scr_write (struct ata_port *ap, unsigned int sc_reg_in,
+                              u32 val)
+{
+       unsigned int sc_reg;
+
+       switch (sc_reg_in) {
+       case SCR_STATUS:        sc_reg = 0; break;
+       case SCR_CONTROL:       sc_reg = 1; break;
+       case SCR_ERROR:         sc_reg = 2; break;
+       case SCR_ACTIVE:        sc_reg = 3; break;
+       default:
+               return;
+       }
+
+       writel(val, (void __iomem *) ap->ioaddr.scr_addr + (sc_reg * 4));
+}
+
+static void ahci_start_engine(void __iomem *port_mmio)
+{
+       u32 tmp;
+
+       /* start DMA */
+       tmp = readl(port_mmio + PORT_CMD);
+       tmp |= PORT_CMD_START;
+       writel(tmp, port_mmio + PORT_CMD);
+       readl(port_mmio + PORT_CMD); /* flush */
+}
+
+static int ahci_stop_engine(void __iomem *port_mmio)
+{
+       u32 tmp;
+
+       tmp = readl(port_mmio + PORT_CMD);
+
+       /* check if the HBA is idle */
+       if ((tmp & (PORT_CMD_START | PORT_CMD_LIST_ON)) == 0)
+               return 0;
+
+       /* setting HBA to idle */
+       tmp &= ~PORT_CMD_START;
+       writel(tmp, port_mmio + PORT_CMD);
+
+       /* wait for engine to stop. This could be as long as 500 msec */
+       tmp = ata_wait_register(port_mmio + PORT_CMD,
+                               PORT_CMD_LIST_ON, PORT_CMD_LIST_ON, 1, 500);
+       if (tmp & PORT_CMD_LIST_ON)
+               return -EIO;
+
+       return 0;
+}
+
+static void ahci_start_fis_rx(void __iomem *port_mmio, u32 cap,
+                             dma_addr_t cmd_slot_dma, dma_addr_t rx_fis_dma)
+{
+       u32 tmp;
+
+       /* set FIS registers */
+       if (cap & HOST_CAP_64)
+               writel((cmd_slot_dma >> 16) >> 16, port_mmio + PORT_LST_ADDR_HI);
+       writel(cmd_slot_dma & 0xffffffff, port_mmio + PORT_LST_ADDR);
+
+       if (cap & HOST_CAP_64)
+               writel((rx_fis_dma >> 16) >> 16, port_mmio + PORT_FIS_ADDR_HI);
+       writel(rx_fis_dma & 0xffffffff, port_mmio + PORT_FIS_ADDR);
+
+       /* enable FIS reception */
+       tmp = readl(port_mmio + PORT_CMD);
+       tmp |= PORT_CMD_FIS_RX;
+       writel(tmp, port_mmio + PORT_CMD);
+
+       /* flush */
+       readl(port_mmio + PORT_CMD);
+}
+
+static int ahci_stop_fis_rx(void __iomem *port_mmio)
+{
+       u32 tmp;
+
+       /* disable FIS reception */
+       tmp = readl(port_mmio + PORT_CMD);
+       tmp &= ~PORT_CMD_FIS_RX;
+       writel(tmp, port_mmio + PORT_CMD);
+
+       /* wait for completion, spec says 500ms, give it 1000 */
+       tmp = ata_wait_register(port_mmio + PORT_CMD, PORT_CMD_FIS_ON,
+                               PORT_CMD_FIS_ON, 10, 1000);
+       if (tmp & PORT_CMD_FIS_ON)
+               return -EBUSY;
+
+       return 0;
+}
+
+static void ahci_power_up(void __iomem *port_mmio, u32 cap)
+{
+       u32 cmd;
+
+       cmd = readl(port_mmio + PORT_CMD) & ~PORT_CMD_ICC_MASK;
+
+       /* spin up device */
+       if (cap & HOST_CAP_SSS) {
+               cmd |= PORT_CMD_SPIN_UP;
+               writel(cmd, port_mmio + PORT_CMD);
+       }
+
+       /* wake up link */
+       writel(cmd | PORT_CMD_ICC_ACTIVE, port_mmio + PORT_CMD);
+}
+
+static void ahci_power_down(void __iomem *port_mmio, u32 cap)
+{
+       u32 cmd, scontrol;
+
+       cmd = readl(port_mmio + PORT_CMD) & ~PORT_CMD_ICC_MASK;
+
+       if (cap & HOST_CAP_SSC) {
+               /* enable transitions to slumber mode */
+               scontrol = readl(port_mmio + PORT_SCR_CTL);
+               if ((scontrol & 0x0f00) > 0x100) {
+                       scontrol &= ~0xf00;
+                       writel(scontrol, port_mmio + PORT_SCR_CTL);
+               }
+
+               /* put device into slumber mode */
+               writel(cmd | PORT_CMD_ICC_SLUMBER, port_mmio + PORT_CMD);
+
+               /* wait for the transition to complete */
+               ata_wait_register(port_mmio + PORT_CMD, PORT_CMD_ICC_SLUMBER,
+                                 PORT_CMD_ICC_SLUMBER, 1, 50);
+       }
+
+       /* put device into listen mode */
+       if (cap & HOST_CAP_SSS) {
+               /* first set PxSCTL.DET to 0 */
+               scontrol = readl(port_mmio + PORT_SCR_CTL);
+               scontrol &= ~0xf;
+               writel(scontrol, port_mmio + PORT_SCR_CTL);
+
+               /* then set PxCMD.SUD to 0 */
+               cmd &= ~PORT_CMD_SPIN_UP;
+               writel(cmd, port_mmio + PORT_CMD);
+       }
+}
+
+static void ahci_init_port(void __iomem *port_mmio, u32 cap,
+                          dma_addr_t cmd_slot_dma, dma_addr_t rx_fis_dma)
+{
+       /* power up */
+       ahci_power_up(port_mmio, cap);
+
+       /* enable FIS reception */
+       ahci_start_fis_rx(port_mmio, cap, cmd_slot_dma, rx_fis_dma);
+
+       /* enable DMA */
+       ahci_start_engine(port_mmio);
+}
+
+static int ahci_deinit_port(void __iomem *port_mmio, u32 cap, const char **emsg)
+{
+       int rc;
+
+       /* disable DMA */
+       rc = ahci_stop_engine(port_mmio);
+       if (rc) {
+               *emsg = "failed to stop engine";
+               return rc;
+       }
+
+       /* disable FIS reception */
+       rc = ahci_stop_fis_rx(port_mmio);
+       if (rc) {
+               *emsg = "failed stop FIS RX";
+               return rc;
+       }
+
+       /* put device into slumber mode */
+       ahci_power_down(port_mmio, cap);
+
+       return 0;
+}
+
+static int ahci_reset_controller(void __iomem *mmio, struct pci_dev *pdev)
+{
+       u32 cap_save, tmp;
+
+       cap_save = readl(mmio + HOST_CAP);
+       cap_save &= ( (1<<28) | (1<<17) );
+       cap_save |= (1 << 27);
+
+       /* global controller reset */
+       tmp = readl(mmio + HOST_CTL);
+       if ((tmp & HOST_RESET) == 0) {
+               writel(tmp | HOST_RESET, mmio + HOST_CTL);
+               readl(mmio + HOST_CTL); /* flush */
+       }
+
+       /* reset must complete within 1 second, or
+        * the hardware should be considered fried.
+        */
+       ssleep(1);
+
+       tmp = readl(mmio + HOST_CTL);
+       if (tmp & HOST_RESET) {
+               dev_printk(KERN_ERR, &pdev->dev,
+                          "controller reset failed (0x%x)\n", tmp);
+               return -EIO;
+       }
+
+       writel(HOST_AHCI_EN, mmio + HOST_CTL);
+       (void) readl(mmio + HOST_CTL);  /* flush */
+       writel(cap_save, mmio + HOST_CAP);
+       writel(0xf, mmio + HOST_PORTS_IMPL);
+       (void) readl(mmio + HOST_PORTS_IMPL);   /* flush */
+
+       if (pdev->vendor == PCI_VENDOR_ID_INTEL) {
+               u16 tmp16;
+
+               /* configure PCS */
+               pci_read_config_word(pdev, 0x92, &tmp16);
+               tmp16 |= 0xf;
+               pci_write_config_word(pdev, 0x92, tmp16);
+       }
+
+       return 0;
+}
+
+static void ahci_init_controller(void __iomem *mmio, struct pci_dev *pdev,
+                                int n_ports, u32 cap)
+{
+       int i, rc;
+       u32 tmp;
+
+       for (i = 0; i < n_ports; i++) {
+               void __iomem *port_mmio = ahci_port_base(mmio, i);
+               const char *emsg = NULL;
+
+#if 0 /* BIOSen initialize this incorrectly */
+               if (!(hpriv->port_map & (1 << i)))
+                       continue;
+#endif
+
+               /* make sure port is not active */
+               rc = ahci_deinit_port(port_mmio, cap, &emsg);
+               if (rc)
+                       dev_printk(KERN_WARNING, &pdev->dev,
+                                  "%s (%d)\n", emsg, rc);
+
+               /* clear SError */
+               tmp = readl(port_mmio + PORT_SCR_ERR);
+               VPRINTK("PORT_SCR_ERR 0x%x\n", tmp);
+               writel(tmp, port_mmio + PORT_SCR_ERR);
+
+               /* clear port IRQ */
+               tmp = readl(port_mmio + PORT_IRQ_STAT);
+               VPRINTK("PORT_IRQ_STAT 0x%x\n", tmp);
+               if (tmp)
+                       writel(tmp, port_mmio + PORT_IRQ_STAT);
+
+               writel(1 << i, mmio + HOST_IRQ_STAT);
+       }
+
+       tmp = readl(mmio + HOST_CTL);
+       VPRINTK("HOST_CTL 0x%x\n", tmp);
+       writel(tmp | HOST_IRQ_EN, mmio + HOST_CTL);
+       tmp = readl(mmio + HOST_CTL);
+       VPRINTK("HOST_CTL 0x%x\n", tmp);
+}
+
+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;
+       tf.lbam         = (tmp >> 16)   & 0xff;
+       tf.lbal         = (tmp >> 8)    & 0xff;
+       tf.nsect        = (tmp)         & 0xff;
+
+       return ata_dev_classify(&tf);
+}
+
+static void ahci_fill_cmd_slot(struct ahci_port_priv *pp, unsigned int tag,
+                              u32 opts)
+{
+       dma_addr_t cmd_tbl_dma;
+
+       cmd_tbl_dma = pp->cmd_tbl_dma + tag * AHCI_CMD_TBL_SZ;
+
+       pp->cmd_slot[tag].opts = cpu_to_le32(opts);
+       pp->cmd_slot[tag].status = 0;
+       pp->cmd_slot[tag].tbl_addr = cpu_to_le32(cmd_tbl_dma & 0xffffffff);
+       pp->cmd_slot[tag].tbl_addr_hi = cpu_to_le32((cmd_tbl_dma >> 16) >> 16);
+}
+
+static int ahci_clo(struct ata_port *ap)
+{
+       void __iomem *port_mmio = (void __iomem *) ap->ioaddr.cmd_addr;
+       struct ahci_host_priv *hpriv = ap->host_set->private_data;
+       u32 tmp;
+
+       if (!(hpriv->cap & HOST_CAP_CLO))
+               return -EOPNOTSUPP;
+
+       tmp = readl(port_mmio + PORT_CMD);
+       tmp |= PORT_CMD_CLO;
+       writel(tmp, port_mmio + PORT_CMD);
+
+       tmp = ata_wait_register(port_mmio + PORT_CMD,
+                               PORT_CMD_CLO, PORT_CMD_CLO, 1, 500);
+       if (tmp & PORT_CMD_CLO)
+               return -EIO;
+
+       return 0;
+}
+
+static int ahci_prereset(struct ata_port *ap)
+{
+       if ((ap->flags & AHCI_FLAG_RESET_NEEDS_CLO) &&
+           (ata_busy_wait(ap, ATA_BUSY, 1000) & ATA_BUSY)) {
+               /* ATA_BUSY hasn't cleared, so send a CLO */
+               ahci_clo(ap);
+       }
+
+       return ata_std_prereset(ap);
+}
+
+static int ahci_softreset(struct ata_port *ap, unsigned int *class)
+{
+       struct ahci_port_priv *pp = ap->private_data;
+       void __iomem *mmio = ap->host_set->mmio_base;
+       void __iomem *port_mmio = ahci_port_base(mmio, ap->port_no);
+       const u32 cmd_fis_len = 5; /* five dwords */
+       const char *reason = NULL;
+       struct ata_taskfile tf;
+       u32 tmp;
+       u8 *fis;
+       int rc;
+
+       DPRINTK("ENTER\n");
+
+       if (ata_port_offline(ap)) {
+               DPRINTK("PHY reports no device\n");
+               *class = ATA_DEV_NONE;
+               return 0;
+       }
+
+       /* prepare for SRST (AHCI-1.1 10.4.1) */
+       rc = ahci_stop_engine(port_mmio);
+       if (rc) {
+               reason = "failed to stop engine";
+               goto fail_restart;
+       }
+
+       /* check BUSY/DRQ, perform Command List Override if necessary */
+       ahci_tf_read(ap, &tf);
+       if (tf.command & (ATA_BUSY | ATA_DRQ)) {
+               rc = ahci_clo(ap);
+
+               if (rc == -EOPNOTSUPP) {
+                       reason = "port busy but CLO unavailable";
+                       goto fail_restart;
+               } else if (rc) {
+                       reason = "port busy but CLO failed";
+                       goto fail_restart;
+               }
+       }
+
+       /* restart engine */
+       ahci_start_engine(port_mmio);
+
+       ata_tf_init(ap->device, &tf);
+       fis = pp->cmd_tbl;
+
+       /* issue the first D2H Register FIS */
+       ahci_fill_cmd_slot(pp, 0,
+                          cmd_fis_len | AHCI_CMD_RESET | AHCI_CMD_CLR_BUSY);
+
+       tf.ctl |= ATA_SRST;
+       ata_tf_to_fis(&tf, fis, 0);
+       fis[1] &= ~(1 << 7);    /* turn off Command FIS bit */
+
+       writel(1, port_mmio + PORT_CMD_ISSUE);
+
+       tmp = ata_wait_register(port_mmio + PORT_CMD_ISSUE, 0x1, 0x1, 1, 500);
+       if (tmp & 0x1) {
+               rc = -EIO;
+               reason = "1st FIS failed";
+               goto fail;
+       }
+
+       /* spec says at least 5us, but be generous and sleep for 1ms */
+       msleep(1);
+
+       /* issue the second D2H Register FIS */
+       ahci_fill_cmd_slot(pp, 0, cmd_fis_len);
+
+       tf.ctl &= ~ATA_SRST;
+       ata_tf_to_fis(&tf, fis, 0);
+       fis[1] &= ~(1 << 7);    /* turn off Command FIS bit */
+
+       writel(1, port_mmio + PORT_CMD_ISSUE);
+       readl(port_mmio + PORT_CMD_ISSUE);      /* flush */
+
+       /* spec mandates ">= 2ms" before checking status.
+        * We wait 150ms, because that was the magic delay used for
+        * ATAPI devices in Hale Landis's ATADRVR, for the period of time
+        * between when the ATA command register is written, and then
+        * status is checked.  Because waiting for "a while" before
+        * checking status is fine, post SRST, we perform this magic
+        * delay here as well.
+        */
+       msleep(150);
+
+       *class = ATA_DEV_NONE;
+       if (ata_port_online(ap)) {
+               if (ata_busy_sleep(ap, ATA_TMOUT_BOOT_QUICK, ATA_TMOUT_BOOT)) {
+                       rc = -EIO;
+                       reason = "device not ready";
+                       goto fail;
+               }
+               *class = ahci_dev_classify(ap);
+       }
+
+       DPRINTK("EXIT, class=%u\n", *class);
+       return 0;
+
+ fail_restart:
+       ahci_start_engine(port_mmio);
+ fail:
+       ata_port_printk(ap, KERN_ERR, "softreset failed (%s)\n", reason);
+       return rc;
+}
+
+static int ahci_hardreset(struct ata_port *ap, unsigned int *class)
+{
+       struct ahci_port_priv *pp = ap->private_data;
+       u8 *d2h_fis = pp->rx_fis + RX_FIS_D2H_REG;
+       struct ata_taskfile tf;
+       void __iomem *mmio = ap->host_set->mmio_base;
+       void __iomem *port_mmio = ahci_port_base(mmio, ap->port_no);
+       int rc;
+
+       DPRINTK("ENTER\n");
+
+       ahci_stop_engine(port_mmio);
+
+       /* clear D2H reception area to properly wait for D2H FIS */
+       ata_tf_init(ap->device, &tf);
+       tf.command = 0xff;
+       ata_tf_to_fis(&tf, d2h_fis, 0);
+
+       rc = sata_std_hardreset(ap, class);
+
+       ahci_start_engine(port_mmio);
+
+       if (rc == 0 && ata_port_online(ap))
+               *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 (*class == ATA_DEV_ATAPI)
+               new_tmp |= PORT_CMD_ATAPI;
+       else
+               new_tmp &= ~PORT_CMD_ATAPI;
+       if (new_tmp != tmp) {
+               writel(new_tmp, port_mmio + PORT_CMD);
+               readl(port_mmio + PORT_CMD); /* flush */
+       }
+}
+
+static u8 ahci_check_status(struct ata_port *ap)
+{
+       void __iomem *mmio = (void __iomem *) ap->ioaddr.cmd_addr;
+
+       return readl(mmio + PORT_TFDATA) & 0xFF;
+}
+
+static void ahci_tf_read(struct ata_port *ap, struct ata_taskfile *tf)
+{
+       struct ahci_port_priv *pp = ap->private_data;
+       u8 *d2h_fis = pp->rx_fis + RX_FIS_D2H_REG;
+
+       ata_tf_from_fis(d2h_fis, tf);
+}
+
+static unsigned int ahci_fill_sg(struct ata_queued_cmd *qc, void *cmd_tbl)
+{
+       struct scatterlist *sg;
+       struct ahci_sg *ahci_sg;
+       unsigned int n_sg = 0;
+
+       VPRINTK("ENTER\n");
+
+       /*
+        * Next, the S/G list.
+        */
+       ahci_sg = cmd_tbl + AHCI_CMD_TBL_HDR_SZ;
+       ata_for_each_sg(sg, qc) {
+               dma_addr_t addr = sg_dma_address(sg);
+               u32 sg_len = sg_dma_len(sg);
+
+               ahci_sg->addr = cpu_to_le32(addr & 0xffffffff);
+               ahci_sg->addr_hi = cpu_to_le32((addr >> 16) >> 16);
+               ahci_sg->flags_size = cpu_to_le32(sg_len - 1);
+
+               ahci_sg++;
+               n_sg++;
+       }
+
+       return n_sg;
+}
+
+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);
+       void *cmd_tbl;
+       u32 opts;
+       const u32 cmd_fis_len = 5; /* five dwords */
+       unsigned int n_elem;
+
+       /*
+        * Fill in command table information.  First, the header,
+        * a SATA Register - Host to Device command FIS.
+        */
+       cmd_tbl = pp->cmd_tbl + qc->tag * AHCI_CMD_TBL_SZ;
+
+       ata_tf_to_fis(&qc->tf, cmd_tbl, 0);
+       if (is_atapi) {
+               memset(cmd_tbl + AHCI_CMD_TBL_CDB, 0, 32);
+               memcpy(cmd_tbl + AHCI_CMD_TBL_CDB, qc->cdb, qc->dev->cdb_len);
+       }
+
+       n_elem = 0;
+       if (qc->flags & ATA_QCFLAG_DMAMAP)
+               n_elem = ahci_fill_sg(qc, cmd_tbl);
+
+       /*
+        * Fill in command slot information.
+        */
+       opts = cmd_fis_len | n_elem << 16;
+       if (qc->tf.flags & ATA_TFLAG_WRITE)
+               opts |= AHCI_CMD_WRITE;
+       if (is_atapi)
+               opts |= AHCI_CMD_ATAPI | AHCI_CMD_PREFETCH;
+
+       ahci_fill_cmd_slot(pp, qc->tag, opts);
+}
+
+static void ahci_error_intr(struct ata_port *ap, u32 irq_stat)
+{
+       struct ahci_port_priv *pp = ap->private_data;
+       struct ata_eh_info *ehi = &ap->eh_info;
+       unsigned int err_mask = 0, action = 0;
+       struct ata_queued_cmd *qc;
+       u32 serror;
+
+       ata_ehi_clear_desc(ehi);
+
+       /* AHCI needs SError cleared; otherwise, it might lock up */
+       serror = ahci_scr_read(ap, SCR_ERROR);
+       ahci_scr_write(ap, SCR_ERROR, serror);
+
+       /* analyze @irq_stat */
+       ata_ehi_push_desc(ehi, "irq_stat 0x%08x", irq_stat);
+
+       if (irq_stat & PORT_IRQ_TF_ERR)
+               err_mask |= AC_ERR_DEV;
+
+       if (irq_stat & (PORT_IRQ_HBUS_ERR | PORT_IRQ_HBUS_DATA_ERR)) {
+               err_mask |= AC_ERR_HOST_BUS;
+               action |= ATA_EH_SOFTRESET;
+       }
+
+       if (irq_stat & PORT_IRQ_IF_ERR) {
+               err_mask |= AC_ERR_ATA_BUS;
+               action |= ATA_EH_SOFTRESET;
+               ata_ehi_push_desc(ehi, ", interface fatal error");
+       }
+
+       if (irq_stat & (PORT_IRQ_CONNECT | PORT_IRQ_PHYRDY)) {
+               ata_ehi_hotplugged(ehi);
+               ata_ehi_push_desc(ehi, ", %s", irq_stat & PORT_IRQ_CONNECT ?
+                       "connection status changed" : "PHY RDY changed");
+       }
+
+       if (irq_stat & PORT_IRQ_UNK_FIS) {
+               u32 *unk = (u32 *)(pp->rx_fis + RX_FIS_UNK);
+
+               err_mask |= AC_ERR_HSM;
+               action |= ATA_EH_SOFTRESET;
+               ata_ehi_push_desc(ehi, ", unknown FIS %08x %08x %08x %08x",
+                                 unk[0], unk[1], unk[2], unk[3]);
+       }
+
+       /* okay, let's hand over to EH */
+       ehi->serror |= serror;
+       ehi->action |= action;
+
+       qc = ata_qc_from_tag(ap, ap->active_tag);
+       if (qc)
+               qc->err_mask |= err_mask;
+       else
+               ehi->err_mask |= err_mask;
+
+       if (irq_stat & PORT_IRQ_FREEZE)
+               ata_port_freeze(ap);
+       else
+               ata_port_abort(ap);
+}
+
+static void ahci_host_intr(struct ata_port *ap)
+{
+       void __iomem *mmio = ap->host_set->mmio_base;
+       void __iomem *port_mmio = ahci_port_base(mmio, ap->port_no);
+       struct ata_eh_info *ehi = &ap->eh_info;
+       u32 status, qc_active;
+       int rc;
+
+       status = readl(port_mmio + PORT_IRQ_STAT);
+       writel(status, port_mmio + PORT_IRQ_STAT);
+
+       if (unlikely(status & PORT_IRQ_ERROR)) {
+               ahci_error_intr(ap, status);
+               return;
+       }
+
+       if (ap->sactive)
+               qc_active = readl(port_mmio + PORT_SCR_ACT);
+       else
+               qc_active = readl(port_mmio + PORT_CMD_ISSUE);
+
+       rc = ata_qc_complete_multiple(ap, qc_active, NULL);
+       if (rc > 0)
+               return;
+       if (rc < 0) {
+               ehi->err_mask |= AC_ERR_HSM;
+               ehi->action |= ATA_EH_SOFTRESET;
+               ata_port_freeze(ap);
+               return;
+       }
+
+       /* hmmm... a spurious interupt */
+
+       /* some devices send D2H reg with I bit set during NCQ command phase */
+       if (ap->sactive && status & PORT_IRQ_D2H_REG_FIS)
+               return;
+
+       /* ignore interim PIO setup fis interrupts */
+       if (ata_tag_valid(ap->active_tag) && (status & PORT_IRQ_PIOS_FIS)) 
+               return;
+
+       if (ata_ratelimit())
+               ata_port_printk(ap, KERN_INFO, "spurious interrupt "
+                               "(irq_stat 0x%x active_tag %d sactive 0x%x)\n",
+                               status, ap->active_tag, ap->sactive);
+}
+
+static void ahci_irq_clear(struct ata_port *ap)
+{
+       /* TODO */
+}
+
+static irqreturn_t ahci_interrupt(int irq, void *dev_instance, struct pt_regs *regs)
+{
+       struct ata_host_set *host_set = dev_instance;
+       struct ahci_host_priv *hpriv;
+       unsigned int i, handled = 0;
+       void __iomem *mmio;
+       u32 irq_stat, irq_ack = 0;
+
+       VPRINTK("ENTER\n");
+
+       hpriv = host_set->private_data;
+       mmio = host_set->mmio_base;
+
+       /* sigh.  0xffffffff is a valid return from h/w */
+       irq_stat = readl(mmio + HOST_IRQ_STAT);
+       irq_stat &= hpriv->port_map;
+       if (!irq_stat)
+               return IRQ_NONE;
+
+        spin_lock(&host_set->lock);
+
+        for (i = 0; i < host_set->n_ports; i++) {
+               struct ata_port *ap;
+
+               if (!(irq_stat & (1 << i)))
+                       continue;
+
+               ap = host_set->ports[i];
+               if (ap) {
+                       ahci_host_intr(ap);
+                       VPRINTK("port %u\n", i);
+               } else {
+                       VPRINTK("port %u (no irq)\n", i);
+                       if (ata_ratelimit())
+                               dev_printk(KERN_WARNING, host_set->dev,
+                                       "interrupt on disabled port %u\n", i);
+               }
+
+               irq_ack |= (1 << i);
+       }
+
+       if (irq_ack) {
+               writel(irq_ack, mmio + HOST_IRQ_STAT);
+               handled = 1;
+       }
+
+       spin_unlock(&host_set->lock);
+
+       VPRINTK("EXIT\n");
+
+       return IRQ_RETVAL(handled);
+}
+
+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;
+
+       if (qc->tf.protocol == ATA_PROT_NCQ)
+               writel(1 << qc->tag, port_mmio + PORT_SCR_ACT);
+       writel(1 << qc->tag, port_mmio + PORT_CMD_ISSUE);
+       readl(port_mmio + PORT_CMD_ISSUE);      /* flush */
+
+       return 0;
+}
+
+static void ahci_freeze(struct ata_port *ap)
+{
+       void __iomem *mmio = ap->host_set->mmio_base;
+       void __iomem *port_mmio = ahci_port_base(mmio, ap->port_no);
+
+       /* turn IRQ off */
+       writel(0, port_mmio + PORT_IRQ_MASK);
+}
+
+static void ahci_thaw(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;
+
+       /* clear IRQ */
+       tmp = readl(port_mmio + PORT_IRQ_STAT);
+       writel(tmp, port_mmio + PORT_IRQ_STAT);
+       writel(1 << ap->id, mmio + HOST_IRQ_STAT);
+
+       /* turn IRQ back on */
+       writel(DEF_PORT_IRQ, port_mmio + PORT_IRQ_MASK);
+}
+
+static void ahci_error_handler(struct ata_port *ap)
+{
+       void __iomem *mmio = ap->host_set->mmio_base;
+       void __iomem *port_mmio = ahci_port_base(mmio, ap->port_no);
+
+       if (!(ap->pflags & ATA_PFLAG_FROZEN)) {
+               /* restart engine */
+               ahci_stop_engine(port_mmio);
+               ahci_start_engine(port_mmio);
+       }
+
+       /* perform recovery */
+       ata_do_eh(ap, ahci_prereset, ahci_softreset, ahci_hardreset,
+                 ahci_postreset);
+}
+
+static void ahci_post_internal_cmd(struct ata_queued_cmd *qc)
+{
+       struct ata_port *ap = qc->ap;
+       void __iomem *mmio = ap->host_set->mmio_base;
+       void __iomem *port_mmio = ahci_port_base(mmio, ap->port_no);
+
+       if (qc->flags & ATA_QCFLAG_FAILED)
+               qc->err_mask |= AC_ERR_OTHER;
+
+       if (qc->err_mask) {
+               /* make DMA engine forget about the failed command */
+               ahci_stop_engine(port_mmio);
+               ahci_start_engine(port_mmio);
+       }
+}
+
+static int ahci_port_suspend(struct ata_port *ap, pm_message_t mesg)
+{
+       struct ahci_host_priv *hpriv = ap->host_set->private_data;
+       struct ahci_port_priv *pp = ap->private_data;
+       void __iomem *mmio = ap->host_set->mmio_base;
+       void __iomem *port_mmio = ahci_port_base(mmio, ap->port_no);
+       const char *emsg = NULL;
+       int rc;
+
+       rc = ahci_deinit_port(port_mmio, hpriv->cap, &emsg);
+       if (rc) {
+               ata_port_printk(ap, KERN_ERR, "%s (%d)\n", emsg, rc);
+               ahci_init_port(port_mmio, hpriv->cap,
+                              pp->cmd_slot_dma, pp->rx_fis_dma);
+       }
+
+       return rc;
+}
+
+static int ahci_port_resume(struct ata_port *ap)
+{
+       struct ahci_port_priv *pp = ap->private_data;
+       struct ahci_host_priv *hpriv = ap->host_set->private_data;
+       void __iomem *mmio = ap->host_set->mmio_base;
+       void __iomem *port_mmio = ahci_port_base(mmio, ap->port_no);
+
+       ahci_init_port(port_mmio, hpriv->cap, pp->cmd_slot_dma, pp->rx_fis_dma);
+
+       return 0;
+}
+
+static int ahci_pci_device_suspend(struct pci_dev *pdev, pm_message_t mesg)
+{
+       struct ata_host_set *host_set = dev_get_drvdata(&pdev->dev);
+       void __iomem *mmio = host_set->mmio_base;
+       u32 ctl;
+
+       if (mesg.event == PM_EVENT_SUSPEND) {
+               /* AHCI spec rev1.1 section 8.3.3:
+                * Software must disable interrupts prior to requesting a
+                * transition of the HBA to D3 state.
+                */
+               ctl = readl(mmio + HOST_CTL);
+               ctl &= ~HOST_IRQ_EN;
+               writel(ctl, mmio + HOST_CTL);
+               readl(mmio + HOST_CTL); /* flush */
+       }
+
+       return ata_pci_device_suspend(pdev, mesg);
+}
+
+static int ahci_pci_device_resume(struct pci_dev *pdev)
+{
+       struct ata_host_set *host_set = dev_get_drvdata(&pdev->dev);
+       struct ahci_host_priv *hpriv = host_set->private_data;
+       void __iomem *mmio = host_set->mmio_base;
+       int rc;
+
+       ata_pci_device_do_resume(pdev);
+
+       if (pdev->dev.power.power_state.event == PM_EVENT_SUSPEND) {
+               rc = ahci_reset_controller(mmio, pdev);
+               if (rc)
+                       return rc;
+
+               ahci_init_controller(mmio, pdev, host_set->n_ports, hpriv->cap);
+       }
+
+       ata_host_set_resume(host_set);
+
+       return 0;
+}
+
+static int ahci_port_start(struct ata_port *ap)
+{
+       struct device *dev = ap->host_set->dev;
+       struct ahci_host_priv *hpriv = ap->host_set->private_data;
+       struct ahci_port_priv *pp;
+       void __iomem *mmio = ap->host_set->mmio_base;
+       void __iomem *port_mmio = ahci_port_base(mmio, ap->port_no);
+       void *mem;
+       dma_addr_t mem_dma;
+       int rc;
+
+       pp = kmalloc(sizeof(*pp), GFP_KERNEL);
+       if (!pp)
+               return -ENOMEM;
+       memset(pp, 0, sizeof(*pp));
+
+       rc = ata_pad_alloc(ap, dev);
+       if (rc) {
+               kfree(pp);
+               return rc;
+       }
+
+       mem = dma_alloc_coherent(dev, AHCI_PORT_PRIV_DMA_SZ, &mem_dma, GFP_KERNEL);
+       if (!mem) {
+               ata_pad_free(ap, dev);
+               kfree(pp);
+               return -ENOMEM;
+       }
+       memset(mem, 0, AHCI_PORT_PRIV_DMA_SZ);
+
+       /*
+        * First item in chunk of DMA memory: 32-slot command table,
+        * 32 bytes each in size
+        */
+       pp->cmd_slot = mem;
+       pp->cmd_slot_dma = mem_dma;
+
+       mem += AHCI_CMD_SLOT_SZ;
+       mem_dma += AHCI_CMD_SLOT_SZ;
+
+       /*
+        * Second item: Received-FIS area
+        */
+       pp->rx_fis = mem;
+       pp->rx_fis_dma = mem_dma;
+
+       mem += AHCI_RX_FIS_SZ;
+       mem_dma += AHCI_RX_FIS_SZ;
+
+       /*
+        * Third item: data area for storing a single command
+        * and its scatter-gather table
+        */
+       pp->cmd_tbl = mem;
+       pp->cmd_tbl_dma = mem_dma;
+
+       ap->private_data = pp;
+
+       /* initialize port */
+       ahci_init_port(port_mmio, hpriv->cap, pp->cmd_slot_dma, pp->rx_fis_dma);
+
+       return 0;
+}
+
+static void ahci_port_stop(struct ata_port *ap)
+{
+       struct device *dev = ap->host_set->dev;
+       struct ahci_host_priv *hpriv = ap->host_set->private_data;
+       struct ahci_port_priv *pp = ap->private_data;
+       void __iomem *mmio = ap->host_set->mmio_base;
+       void __iomem *port_mmio = ahci_port_base(mmio, ap->port_no);
+       const char *emsg = NULL;
+       int rc;
+
+       /* de-initialize port */
+       rc = ahci_deinit_port(port_mmio, hpriv->cap, &emsg);
+       if (rc)
+               ata_port_printk(ap, KERN_WARNING, "%s (%d)\n", emsg, rc);
+
+       ap->private_data = NULL;
+       dma_free_coherent(dev, AHCI_PORT_PRIV_DMA_SZ,
+                         pp->cmd_slot, pp->cmd_slot_dma);
+       ata_pad_free(ap, dev);
+       kfree(pp);
+}
+
+static void ahci_setup_port(struct ata_ioports *port, unsigned long base,
+                           unsigned int port_idx)
+{
+       VPRINTK("ENTER, base==0x%lx, port_idx %u\n", base, port_idx);
+       base = ahci_port_base_ul(base, port_idx);
+       VPRINTK("base now==0x%lx\n", base);
+
+       port->cmd_addr          = base;
+       port->scr_addr          = base + PORT_SCR;
+
+       VPRINTK("EXIT\n");
+}
+
+static int ahci_host_init(struct ata_probe_ent *probe_ent)
+{
+       struct ahci_host_priv *hpriv = probe_ent->private_data;
+       struct pci_dev *pdev = to_pci_dev(probe_ent->dev);
+       void __iomem *mmio = probe_ent->mmio_base;
+       unsigned int i, using_dac;
+       int rc;
+
+       rc = ahci_reset_controller(mmio, pdev);
+       if (rc)
+               return rc;
+
+       hpriv->cap = readl(mmio + HOST_CAP);
+       hpriv->port_map = readl(mmio + HOST_PORTS_IMPL);
+       probe_ent->n_ports = (hpriv->cap & 0x1f) + 1;
+
+       VPRINTK("cap 0x%x  port_map 0x%x  n_ports %d\n",
+               hpriv->cap, hpriv->port_map, probe_ent->n_ports);
+
+       using_dac = hpriv->cap & HOST_CAP_64;
+       if (using_dac &&
+           !pci_set_dma_mask(pdev, DMA_64BIT_MASK)) {
+               rc = pci_set_consistent_dma_mask(pdev, DMA_64BIT_MASK);
+               if (rc) {
+                       rc = pci_set_consistent_dma_mask(pdev, DMA_32BIT_MASK);
+                       if (rc) {
+                               dev_printk(KERN_ERR, &pdev->dev,
+                                          "64-bit DMA enable failed\n");
+                               return rc;
+                       }
+               }
+       } else {
+               rc = pci_set_dma_mask(pdev, DMA_32BIT_MASK);
+               if (rc) {
+                       dev_printk(KERN_ERR, &pdev->dev,
+                                  "32-bit DMA enable failed\n");
+                       return rc;
+               }
+               rc = pci_set_consistent_dma_mask(pdev, DMA_32BIT_MASK);
+               if (rc) {
+                       dev_printk(KERN_ERR, &pdev->dev,
+                                  "32-bit consistent DMA enable failed\n");
+                       return rc;
+               }
+       }
+
+       for (i = 0; i < probe_ent->n_ports; i++)
+               ahci_setup_port(&probe_ent->port[i], (unsigned long) mmio, i);
+
+       ahci_init_controller(mmio, pdev, probe_ent->n_ports, hpriv->cap);
+
+       pci_set_master(pdev);
+
+       return 0;
+}
+
+static void ahci_print_info(struct ata_probe_ent *probe_ent)
+{
+       struct ahci_host_priv *hpriv = probe_ent->private_data;
+       struct pci_dev *pdev = to_pci_dev(probe_ent->dev);
+       void __iomem *mmio = probe_ent->mmio_base;
+       u32 vers, cap, impl, speed;
+       const char *speed_s;
+       u16 cc;
+       const char *scc_s;
+
+       vers = readl(mmio + HOST_VERSION);
+       cap = hpriv->cap;
+       impl = hpriv->port_map;
+
+       speed = (cap >> 20) & 0xf;
+       if (speed == 1)
+               speed_s = "1.5";
+       else if (speed == 2)
+               speed_s = "3";
+       else
+               speed_s = "?";
+
+       pci_read_config_word(pdev, 0x0a, &cc);
+       if (cc == 0x0101)
+               scc_s = "IDE";
+       else if (cc == 0x0106)
+               scc_s = "SATA";
+       else if (cc == 0x0104)
+               scc_s = "RAID";
+       else
+               scc_s = "unknown";
+
+       dev_printk(KERN_INFO, &pdev->dev,
+               "AHCI %02x%02x.%02x%02x "
+               "%u slots %u ports %s Gbps 0x%x impl %s mode\n"
+               ,
+
+               (vers >> 24) & 0xff,
+               (vers >> 16) & 0xff,
+               (vers >> 8) & 0xff,
+               vers & 0xff,
+
+               ((cap >> 8) & 0x1f) + 1,
+               (cap & 0x1f) + 1,
+               speed_s,
+               impl,
+               scc_s);
+
+       dev_printk(KERN_INFO, &pdev->dev,
+               "flags: "
+               "%s%s%s%s%s%s"
+               "%s%s%s%s%s%s%s\n"
+               ,
+
+               cap & (1 << 31) ? "64bit " : "",
+               cap & (1 << 30) ? "ncq " : "",
+               cap & (1 << 28) ? "ilck " : "",
+               cap & (1 << 27) ? "stag " : "",
+               cap & (1 << 26) ? "pm " : "",
+               cap & (1 << 25) ? "led " : "",
+
+               cap & (1 << 24) ? "clo " : "",
+               cap & (1 << 19) ? "nz " : "",
+               cap & (1 << 18) ? "only " : "",
+               cap & (1 << 17) ? "pmp " : "",
+               cap & (1 << 15) ? "pio " : "",
+               cap & (1 << 14) ? "slum " : "",
+               cap & (1 << 13) ? "part " : ""
+               );
+}
+
+static int ahci_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
+{
+       static int printed_version;
+       struct ata_probe_ent *probe_ent = NULL;
+       struct ahci_host_priv *hpriv;
+       unsigned long base;
+       void __iomem *mmio_base;
+       unsigned int board_idx = (unsigned int) ent->driver_data;
+       int have_msi, pci_dev_busy = 0;
+       int rc;
+
+       VPRINTK("ENTER\n");
+
+       WARN_ON(ATA_MAX_QUEUE > AHCI_MAX_CMDS);
+
+       if (!printed_version++)
+               dev_printk(KERN_DEBUG, &pdev->dev, "version " DRV_VERSION "\n");
+
+       /* JMicron-specific fixup: make sure we're in AHCI mode */
+       /* This is protected from races with ata_jmicron by the pci probe
+          locking */
+       if (pdev->vendor == PCI_VENDOR_ID_JMICRON) {
+               /* AHCI enable, AHCI on function 0 */
+               pci_write_config_byte(pdev, 0x41, 0xa1);
+               /* Function 1 is the PATA controller */
+               if (PCI_FUNC(pdev->devfn))
+                       return -ENODEV;
+       }
+
+       rc = pci_enable_device(pdev);
+       if (rc)
+               return rc;
+
+       rc = pci_request_regions(pdev, DRV_NAME);
+       if (rc) {
+               pci_dev_busy = 1;
+               goto err_out;
+       }
+
+       if (pci_enable_msi(pdev) == 0)
+               have_msi = 1;
+       else {
+               pci_intx(pdev, 1);
+               have_msi = 0;
+       }
+
+       probe_ent = kmalloc(sizeof(*probe_ent), GFP_KERNEL);
+       if (probe_ent == NULL) {
+               rc = -ENOMEM;
+               goto err_out_msi;
+       }
+
+       memset(probe_ent, 0, sizeof(*probe_ent));
+       probe_ent->dev = pci_dev_to_dev(pdev);
+       INIT_LIST_HEAD(&probe_ent->node);
+
+       mmio_base = pci_iomap(pdev, AHCI_PCI_BAR, 0);
+       if (mmio_base == NULL) {
+               rc = -ENOMEM;
+               goto err_out_free_ent;
+       }
+       base = (unsigned long) mmio_base;
+
+       hpriv = kmalloc(sizeof(*hpriv), GFP_KERNEL);
+       if (!hpriv) {
+               rc = -ENOMEM;
+               goto err_out_iounmap;
+       }
+       memset(hpriv, 0, sizeof(*hpriv));
+
+       probe_ent->sht          = ahci_port_info[board_idx].sht;
+       probe_ent->host_flags   = ahci_port_info[board_idx].host_flags;
+       probe_ent->pio_mask     = ahci_port_info[board_idx].pio_mask;
+       probe_ent->udma_mask    = ahci_port_info[board_idx].udma_mask;
+       probe_ent->port_ops     = ahci_port_info[board_idx].port_ops;
+
+               probe_ent->irq = pdev->irq;
+               probe_ent->irq_flags = IRQF_SHARED;
+       probe_ent->mmio_base = mmio_base;
+       probe_ent->private_data = hpriv;
+
+       if (have_msi)
+               hpriv->flags |= AHCI_FLAG_MSI;
+
+       /* initialize adapter */
+       rc = ahci_host_init(probe_ent);
+       if (rc)
+               goto err_out_hpriv;
+
+       if (!(probe_ent->host_flags & AHCI_FLAG_NO_NCQ) &&
+           (hpriv->cap & HOST_CAP_NCQ))
+               probe_ent->host_flags |= ATA_FLAG_NCQ;
+
+       ahci_print_info(probe_ent);
+
+       /* FIXME: check ata_device_add return value */
+       ata_device_add(probe_ent);
+       kfree(probe_ent);
+
+       return 0;
+
+err_out_hpriv:
+       kfree(hpriv);
+err_out_iounmap:
+       pci_iounmap(pdev, mmio_base);
+err_out_free_ent:
+       kfree(probe_ent);
+err_out_msi:
+       if (have_msi)
+               pci_disable_msi(pdev);
+       else
+               pci_intx(pdev, 0);
+       pci_release_regions(pdev);
+err_out:
+       if (!pci_dev_busy)
+               pci_disable_device(pdev);
+       return rc;
+}
+
+static void ahci_remove_one (struct pci_dev *pdev)
+{
+       struct device *dev = pci_dev_to_dev(pdev);
+       struct ata_host_set *host_set = dev_get_drvdata(dev);
+       struct ahci_host_priv *hpriv = host_set->private_data;
+       unsigned int i;
+       int have_msi;
+
+       for (i = 0; i < host_set->n_ports; i++)
+               ata_port_detach(host_set->ports[i]);
+
+       have_msi = hpriv->flags & AHCI_FLAG_MSI;
+       free_irq(host_set->irq, host_set);
+
+       for (i = 0; i < host_set->n_ports; i++) {
+               struct ata_port *ap = host_set->ports[i];
+
+               ata_scsi_release(ap->host);
+               scsi_host_put(ap->host);
+       }
+
+       kfree(hpriv);
+       pci_iounmap(pdev, host_set->mmio_base);
+       kfree(host_set);
+
+       if (have_msi)
+               pci_disable_msi(pdev);
+       else
+               pci_intx(pdev, 0);
+       pci_release_regions(pdev);
+       pci_disable_device(pdev);
+       dev_set_drvdata(dev, NULL);
+}
+
+static int __init ahci_init(void)
+{
+       return pci_register_driver(&ahci_pci_driver);
+}
+
+static void __exit ahci_exit(void)
+{
+       pci_unregister_driver(&ahci_pci_driver);
+}
+
+
+MODULE_AUTHOR("Jeff Garzik");
+MODULE_DESCRIPTION("AHCI SATA low-level driver");
+MODULE_LICENSE("GPL");
+MODULE_DEVICE_TABLE(pci, ahci_pci_tbl);
+MODULE_VERSION(DRV_VERSION);
+
+module_init(ahci_init);
+module_exit(ahci_exit);
diff --git a/drivers/ata/ata_piix.c b/drivers/ata/ata_piix.c
new file mode 100644 (file)
index 0000000..46c34fd
--- /dev/null
@@ -0,0 +1,960 @@
+/*
+ *    ata_piix.c - Intel PATA/SATA controllers
+ *
+ *    Maintained by:  Jeff Garzik <jgarzik@pobox.com>
+ *                 Please ALWAYS copy linux-ide@vger.kernel.org
+ *                 on emails.
+ *
+ *
+ *     Copyright 2003-2005 Red Hat Inc
+ *     Copyright 2003-2005 Jeff Garzik
+ *
+ *
+ *     Copyright header from piix.c:
+ *
+ *  Copyright (C) 1998-1999 Andrzej Krzysztofowicz, Author and Maintainer
+ *  Copyright (C) 1998-2000 Andre Hedrick <andre@linux-ide.org>
+ *  Copyright (C) 2003 Red Hat Inc <alan@redhat.com>
+ *
+ *
+ *  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 at http://developer.intel.com/
+ *
+ * Documentation
+ *     Publically available from Intel web site. Errata documentation
+ * is also publically available. As an aide to anyone hacking on this
+ * driver the list of errata that are relevant is below.going back to
+ * PIIX4. Older device documentation is now a bit tricky to find.
+ *
+ * The chipsets all follow very much the same design. The orginal Triton
+ * series chipsets do _not_ support independant device timings, but this
+ * is fixed in Triton II. With the odd mobile exception the chips then
+ * change little except in gaining more modes until SATA arrives. This
+ * driver supports only the chips with independant timing (that is those
+ * with SITRE and the 0x44 timing register). See pata_oldpiix and pata_mpiix
+ * for the early chip drivers.
+ *
+ * Errata of note:
+ *
+ * Unfixable
+ *     PIIX4    errata #9      - Only on ultra obscure hw
+ *     ICH3     errata #13     - Not observed to affect real hw
+ *                               by Intel
+ *
+ * Things we must deal with
+ *     PIIX4   errata #10      - BM IDE hang with non UDMA
+ *                               (must stop/start dma to recover)
+ *     440MX   errata #15      - As PIIX4 errata #10
+ *     PIIX4   errata #15      - Must not read control registers
+ *                               during a PIO transfer
+ *     440MX   errata #13      - As PIIX4 errata #15
+ *     ICH2    errata #21      - DMA mode 0 doesn't work right
+ *     ICH0/1  errata #55      - As ICH2 errata #21
+ *     ICH2    spec c #9       - Extra operations needed to handle
+ *                               drive hotswap [NOT YET SUPPORTED]
+ *     ICH2    spec c #20      - IDE PRD must not cross a 64K boundary
+ *                               and must be dword aligned
+ *     ICH2    spec c #24      - UDMA mode 4,5 t85/86 should be 6ns not 3.3
+ *
+ * Should have been BIOS fixed:
+ *     450NX:  errata #19      - DMA hangs on old 450NX
+ *     450NX:  errata #20      - DMA hangs on old 450NX
+ *     450NX:  errata #25      - Corruption with DMA on old 450NX
+ *     ICH3    errata #15      - IDE deadlock under high load
+ *                               (BIOS must set dev 31 fn 0 bit 23)
+ *     ICH3    errata #18      - Don't use native mode
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/pci.h>
+#include <linux/init.h>
+#include <linux/blkdev.h>
+#include <linux/delay.h>
+#include <linux/device.h>
+#include <scsi/scsi_host.h>
+#include <linux/libata.h>
+
+#define DRV_NAME       "ata_piix"
+#define DRV_VERSION    "2.00"
+
+enum {
+       PIIX_IOCFG              = 0x54, /* IDE I/O configuration register */
+       ICH5_PMR                = 0x90, /* port mapping register */
+       ICH5_PCS                = 0x92, /* port control and status */
+       PIIX_SCC                = 0x0A, /* sub-class code register */
+
+       PIIX_FLAG_IGNORE_PCS    = (1 << 25), /* ignore PCS present bits */
+       PIIX_FLAG_SCR           = (1 << 26), /* SCR available */
+       PIIX_FLAG_AHCI          = (1 << 27), /* AHCI possible */
+       PIIX_FLAG_CHECKINTR     = (1 << 28), /* make sure PCI INTx enabled */
+
+       /* combined mode.  if set, PATA is channel 0.
+        * if clear, PATA is channel 1.
+        */
+       PIIX_PORT_ENABLED       = (1 << 0),
+       PIIX_PORT_PRESENT       = (1 << 4),
+
+       PIIX_80C_PRI            = (1 << 5) | (1 << 4),
+       PIIX_80C_SEC            = (1 << 7) | (1 << 6),
+
+       /* controller IDs */
+       piix4_pata              = 0,
+       ich5_pata               = 1,
+       ich5_sata               = 2,
+       esb_sata                = 3,
+       ich6_sata               = 4,
+       ich6_sata_ahci          = 5,
+       ich6m_sata_ahci         = 6,
+       ich8_sata_ahci          = 7,
+
+       /* constants for mapping table */
+       P0                      = 0,  /* port 0 */
+       P1                      = 1,  /* port 1 */
+       P2                      = 2,  /* port 2 */
+       P3                      = 3,  /* port 3 */
+       IDE                     = -1, /* IDE */
+       NA                      = -2, /* not avaliable */
+       RV                      = -3, /* reserved */
+
+       PIIX_AHCI_DEVICE        = 6,
+};
+
+struct piix_map_db {
+       const u32 mask;
+       const u16 port_enable;
+       const int present_shift;
+       const int map[][4];
+};
+
+struct piix_host_priv {
+       const int *map;
+       const struct piix_map_db *map_db;
+};
+
+static int piix_init_one (struct pci_dev *pdev,
+                                   const struct pci_device_id *ent);
+static void piix_host_stop(struct ata_host_set *host_set);
+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);
+static void piix_pata_error_handler(struct ata_port *ap);
+static void piix_sata_error_handler(struct ata_port *ap);
+
+static unsigned int in_module_init = 1;
+
+static const struct pci_device_id piix_pci_tbl[] = {
+#ifdef ATA_ENABLE_PATA
+       { 0x8086, 0x7111, PCI_ANY_ID, PCI_ANY_ID, 0, 0, piix4_pata },
+       { 0x8086, 0x24db, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich5_pata },
+       { 0x8086, 0x25a2, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich5_pata },
+       { 0x8086, 0x27df, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich5_pata },
+#endif
+
+       /* NOTE: The following PCI ids must be kept in sync with the
+        * list in drivers/pci/quirks.c.
+        */
+
+       /* 82801EB (ICH5) */
+       { 0x8086, 0x24d1, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich5_sata },
+       /* 82801EB (ICH5) */
+       { 0x8086, 0x24df, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich5_sata },
+       /* 6300ESB (ICH5 variant with broken PCS present bits) */
+       { 0x8086, 0x25a3, PCI_ANY_ID, PCI_ANY_ID, 0, 0, esb_sata },
+       /* 6300ESB pretending RAID */
+       { 0x8086, 0x25b0, PCI_ANY_ID, PCI_ANY_ID, 0, 0, esb_sata },
+       /* 82801FB/FW (ICH6/ICH6W) */
+       { 0x8086, 0x2651, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich6_sata },
+       /* 82801FR/FRW (ICH6R/ICH6RW) */
+       { 0x8086, 0x2652, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich6_sata_ahci },
+       /* 82801FBM ICH6M (ICH6R with only port 0 and 2 implemented) */
+       { 0x8086, 0x2653, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich6m_sata_ahci },
+       /* 82801GB/GR/GH (ICH7, identical to ICH6) */
+       { 0x8086, 0x27c0, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich6_sata_ahci },
+       /* 2801GBM/GHM (ICH7M, identical to ICH6M) */
+       { 0x8086, 0x27c4, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich6m_sata_ahci },
+       /* Enterprise Southbridge 2 (where's the datasheet?) */
+       { 0x8086, 0x2680, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich6_sata_ahci },
+       /* SATA Controller 1 IDE (ICH8, no datasheet yet) */
+       { 0x8086, 0x2820, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_sata_ahci },
+       /* SATA Controller 2 IDE (ICH8, ditto) */
+       { 0x8086, 0x2825, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_sata_ahci },
+       /* Mobile SATA Controller IDE (ICH8M, ditto) */
+       { 0x8086, 0x2828, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_sata_ahci },
+
+       { }     /* terminate list */
+};
+
+static struct pci_driver piix_pci_driver = {
+       .name                   = DRV_NAME,
+       .id_table               = piix_pci_tbl,
+       .probe                  = piix_init_one,
+       .remove                 = ata_pci_remove_one,
+       .suspend                = ata_pci_device_suspend,
+       .resume                 = ata_pci_device_resume,
+};
+
+static struct scsi_host_template piix_sht = {
+       .module                 = THIS_MODULE,
+       .name                   = DRV_NAME,
+       .ioctl                  = ata_scsi_ioctl,
+       .queuecommand           = ata_scsi_queuecmd,
+       .can_queue              = ATA_DEF_QUEUE,
+       .this_id                = ATA_SHT_THIS_ID,
+       .sg_tablesize           = LIBATA_MAX_PRD,
+       .cmd_per_lun            = ATA_SHT_CMD_PER_LUN,
+       .emulated               = ATA_SHT_EMULATED,
+       .use_clustering         = ATA_SHT_USE_CLUSTERING,
+       .proc_name              = DRV_NAME,
+       .dma_boundary           = ATA_DMA_BOUNDARY,
+       .slave_configure        = ata_scsi_slave_config,
+       .slave_destroy          = ata_scsi_slave_destroy,
+       .bios_param             = ata_std_bios_param,
+       .resume                 = ata_scsi_device_resume,
+       .suspend                = ata_scsi_device_suspend,
+};
+
+static const struct ata_port_operations piix_pata_ops = {
+       .port_disable           = ata_port_disable,
+       .set_piomode            = piix_set_piomode,
+       .set_dmamode            = piix_set_dmamode,
+       .mode_filter            = ata_pci_default_filter,
+
+       .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,
+
+       .bmdma_setup            = ata_bmdma_setup,
+       .bmdma_start            = ata_bmdma_start,
+       .bmdma_stop             = ata_bmdma_stop,
+       .bmdma_status           = ata_bmdma_status,
+       .qc_prep                = ata_qc_prep,
+       .qc_issue               = ata_qc_issue_prot,
+       .data_xfer              = ata_pio_data_xfer,
+
+       .freeze                 = ata_bmdma_freeze,
+       .thaw                   = ata_bmdma_thaw,
+       .error_handler          = piix_pata_error_handler,
+       .post_internal_cmd      = ata_bmdma_post_internal_cmd,
+
+       .irq_handler            = ata_interrupt,
+       .irq_clear              = ata_bmdma_irq_clear,
+
+       .port_start             = ata_port_start,
+       .port_stop              = ata_port_stop,
+       .host_stop              = piix_host_stop,
+};
+
+static const struct ata_port_operations piix_sata_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,
+
+       .bmdma_setup            = ata_bmdma_setup,
+       .bmdma_start            = ata_bmdma_start,
+       .bmdma_stop             = ata_bmdma_stop,
+       .bmdma_status           = ata_bmdma_status,
+       .qc_prep                = ata_qc_prep,
+       .qc_issue               = ata_qc_issue_prot,
+       .data_xfer              = ata_pio_data_xfer,
+
+       .freeze                 = ata_bmdma_freeze,
+       .thaw                   = ata_bmdma_thaw,
+       .error_handler          = piix_sata_error_handler,
+       .post_internal_cmd      = ata_bmdma_post_internal_cmd,
+
+       .irq_handler            = ata_interrupt,
+       .irq_clear              = ata_bmdma_irq_clear,
+
+       .port_start             = ata_port_start,
+       .port_stop              = ata_port_stop,
+       .host_stop              = piix_host_stop,
+};
+
+static const struct piix_map_db ich5_map_db = {
+       .mask = 0x7,
+       .port_enable = 0x3,
+       .present_shift = 4,
+       .map = {
+               /* PM   PS   SM   SS       MAP  */
+               {  P0,  NA,  P1,  NA }, /* 000b */
+               {  P1,  NA,  P0,  NA }, /* 001b */
+               {  RV,  RV,  RV,  RV },
+               {  RV,  RV,  RV,  RV },
+               {  P0,  P1, IDE, IDE }, /* 100b */
+               {  P1,  P0, IDE, IDE }, /* 101b */
+               { IDE, IDE,  P0,  P1 }, /* 110b */
+               { IDE, IDE,  P1,  P0 }, /* 111b */
+       },
+};
+
+static const struct piix_map_db ich6_map_db = {
+       .mask = 0x3,
+       .port_enable = 0xf,
+       .present_shift = 4,
+       .map = {
+               /* PM   PS   SM   SS       MAP */
+               {  P0,  P2,  P1,  P3 }, /* 00b */
+               { IDE, IDE,  P1,  P3 }, /* 01b */
+               {  P0,  P2, IDE, IDE }, /* 10b */
+               {  RV,  RV,  RV,  RV },
+       },
+};
+
+static const struct piix_map_db ich6m_map_db = {
+       .mask = 0x3,
+       .port_enable = 0x5,
+       .present_shift = 4,
+       .map = {
+               /* PM   PS   SM   SS       MAP */
+               {  P0,  P2,  RV,  RV }, /* 00b */
+               {  RV,  RV,  RV,  RV },
+               {  P0,  P2, IDE, IDE }, /* 10b */
+               {  RV,  RV,  RV,  RV },
+       },
+};
+
+static const struct piix_map_db ich8_map_db = {
+       .mask = 0x3,
+       .port_enable = 0x3,
+       .present_shift = 8,
+       .map = {
+               /* PM   PS   SM   SS       MAP */
+               {  P0,  NA,  P1,  NA }, /* 00b (hardwired) */
+               {  RV,  RV,  RV,  RV },
+               {  RV,  RV,  RV,  RV }, /* 10b (never) */
+               {  RV,  RV,  RV,  RV },
+       },
+};
+
+static const struct piix_map_db *piix_map_db_table[] = {
+       [ich5_sata]             = &ich5_map_db,
+       [esb_sata]              = &ich5_map_db,
+       [ich6_sata]             = &ich6_map_db,
+       [ich6_sata_ahci]        = &ich6_map_db,
+       [ich6m_sata_ahci]       = &ich6m_map_db,
+       [ich8_sata_ahci]        = &ich8_map_db,
+};
+
+static struct ata_port_info piix_port_info[] = {
+       /* piix4_pata */
+       {
+               .sht            = &piix_sht,
+               .host_flags     = ATA_FLAG_SLAVE_POSS,
+               .pio_mask       = 0x1f, /* pio0-4 */
+#if 0
+               .mwdma_mask     = 0x06, /* mwdma1-2 */
+#else
+               .mwdma_mask     = 0x00, /* mwdma broken */
+#endif
+               .udma_mask      = ATA_UDMA_MASK_40C,
+               .port_ops       = &piix_pata_ops,
+       },
+
+       /* ich5_pata */
+       {
+               .sht            = &piix_sht,
+               .host_flags     = ATA_FLAG_SLAVE_POSS | PIIX_FLAG_CHECKINTR,
+               .pio_mask       = 0x1f, /* pio0-4 */
+#if 0
+               .mwdma_mask     = 0x06, /* mwdma1-2 */
+#else
+               .mwdma_mask     = 0x00, /* mwdma broken */
+#endif
+               .udma_mask      = 0x3f, /* udma0-5 */
+               .port_ops       = &piix_pata_ops,
+       },
+
+       /* ich5_sata */
+       {
+               .sht            = &piix_sht,
+               .host_flags     = ATA_FLAG_SATA | PIIX_FLAG_CHECKINTR,
+               .pio_mask       = 0x1f, /* pio0-4 */
+               .mwdma_mask     = 0x07, /* mwdma0-2 */
+               .udma_mask      = 0x7f, /* udma0-6 */
+               .port_ops       = &piix_sata_ops,
+       },
+
+       /* i6300esb_sata */
+       {
+               .sht            = &piix_sht,
+               .host_flags     = ATA_FLAG_SATA |
+                                 PIIX_FLAG_CHECKINTR | PIIX_FLAG_IGNORE_PCS,
+               .pio_mask       = 0x1f, /* pio0-4 */
+               .mwdma_mask     = 0x07, /* mwdma0-2 */
+               .udma_mask      = 0x7f, /* udma0-6 */
+               .port_ops       = &piix_sata_ops,
+       },
+
+       /* ich6_sata */
+       {
+               .sht            = &piix_sht,
+               .host_flags     = ATA_FLAG_SATA |
+                                 PIIX_FLAG_CHECKINTR | PIIX_FLAG_SCR,
+               .pio_mask       = 0x1f, /* pio0-4 */
+               .mwdma_mask     = 0x07, /* mwdma0-2 */
+               .udma_mask      = 0x7f, /* udma0-6 */
+               .port_ops       = &piix_sata_ops,
+       },
+
+       /* ich6_sata_ahci */
+       {
+               .sht            = &piix_sht,
+               .host_flags     = ATA_FLAG_SATA |
+                                 PIIX_FLAG_CHECKINTR | PIIX_FLAG_SCR |
+                                 PIIX_FLAG_AHCI,
+               .pio_mask       = 0x1f, /* pio0-4 */
+               .mwdma_mask     = 0x07, /* mwdma0-2 */
+               .udma_mask      = 0x7f, /* udma0-6 */
+               .port_ops       = &piix_sata_ops,
+       },
+
+       /* ich6m_sata_ahci */
+       {
+               .sht            = &piix_sht,
+               .host_flags     = ATA_FLAG_SATA |
+                                 PIIX_FLAG_CHECKINTR | PIIX_FLAG_SCR |
+                                 PIIX_FLAG_AHCI,
+               .pio_mask       = 0x1f, /* pio0-4 */
+               .mwdma_mask     = 0x07, /* mwdma0-2 */
+               .udma_mask      = 0x7f, /* udma0-6 */
+               .port_ops       = &piix_sata_ops,
+       },
+
+       /* ich8_sata_ahci */
+       {
+               .sht            = &piix_sht,
+               .host_flags     = ATA_FLAG_SATA |
+                                 PIIX_FLAG_CHECKINTR | PIIX_FLAG_SCR |
+                                 PIIX_FLAG_AHCI,
+               .pio_mask       = 0x1f, /* pio0-4 */
+               .mwdma_mask     = 0x07, /* mwdma0-2 */
+               .udma_mask      = 0x7f, /* udma0-6 */
+               .port_ops       = &piix_sata_ops,
+       },
+};
+
+static struct pci_bits piix_enable_bits[] = {
+       { 0x41U, 1U, 0x80UL, 0x80UL },  /* port 0 */
+       { 0x43U, 1U, 0x80UL, 0x80UL },  /* port 1 */
+};
+
+MODULE_AUTHOR("Andre Hedrick, Alan Cox, Andrzej Krzysztofowicz, Jeff Garzik");
+MODULE_DESCRIPTION("SCSI low-level driver for Intel PIIX/ICH ATA controllers");
+MODULE_LICENSE("GPL");
+MODULE_DEVICE_TABLE(pci, piix_pci_tbl);
+MODULE_VERSION(DRV_VERSION);
+
+/**
+ *     piix_pata_cbl_detect - Probe host controller cable detect info
+ *     @ap: Port for which cable detect info is desired
+ *
+ *     Read 80c cable indicator from ATA PCI device's PCI config
+ *     register.  This register is normally set by firmware (BIOS).
+ *
+ *     LOCKING:
+ *     None (inherited from caller).
+ */
+static void piix_pata_cbl_detect(struct ata_port *ap)
+{
+       struct pci_dev *pdev = to_pci_dev(ap->host_set->dev);
+       u8 tmp, mask;
+
+       /* no 80c support in host controller? */
+       if ((ap->udma_mask & ~ATA_UDMA_MASK_40C) == 0)
+               goto cbl40;
+
+       /* check BIOS cable detect results */
+       mask = ap->port_no == 0 ? PIIX_80C_PRI : PIIX_80C_SEC;
+       pci_read_config_byte(pdev, PIIX_IOCFG, &tmp);
+       if ((tmp & mask) == 0)
+               goto cbl40;
+
+       ap->cbl = ATA_CBL_PATA80;
+       return;
+
+cbl40:
+       ap->cbl = ATA_CBL_PATA40;
+       ap->udma_mask &= ATA_UDMA_MASK_40C;
+}
+
+/**
+ *     piix_pata_prereset - prereset for PATA host controller
+ *     @ap: Target port
+ *
+ *     Prereset including cable detection.
+ *
+ *     LOCKING:
+ *     None (inherited from caller).
+ */
+static int piix_pata_prereset(struct ata_port *ap)
+{
+       struct pci_dev *pdev = to_pci_dev(ap->host_set->dev);
+
+       if (!pci_test_config_bits(pdev, &piix_enable_bits[ap->port_no])) {
+               ata_port_printk(ap, KERN_INFO, "port disabled. ignoring.\n");
+               ap->eh_context.i.action &= ~ATA_EH_RESET_MASK;
+               return 0;
+       }
+
+       piix_pata_cbl_detect(ap);
+
+       return ata_std_prereset(ap);
+}
+
+static void piix_pata_error_handler(struct ata_port *ap)
+{
+       ata_bmdma_drive_eh(ap, piix_pata_prereset, ata_std_softreset, NULL,
+                          ata_std_postreset);
+}
+
+/**
+ *     piix_sata_prereset - prereset for SATA host controller
+ *     @ap: Target port
+ *
+ *     Reads and configures SATA PCI device's PCI config register
+ *     Port Configuration and Status (PCS) to determine port and
+ *     device availability.  Return -ENODEV to skip reset if no
+ *     device is present.
+ *
+ *     LOCKING:
+ *     None (inherited from caller).
+ *
+ *     RETURNS:
+ *     0 if device is present, -ENODEV otherwise.
+ */
+static int piix_sata_prereset(struct ata_port *ap)
+{
+       struct pci_dev *pdev = to_pci_dev(ap->host_set->dev);
+       struct piix_host_priv *hpriv = ap->host_set->private_data;
+       const unsigned int *map = hpriv->map;
+       int base = 2 * ap->port_no;
+       unsigned int present = 0;
+       int port, i;
+       u16 pcs;
+
+       pci_read_config_word(pdev, ICH5_PCS, &pcs);
+       DPRINTK("ata%u: ENTER, pcs=0x%x base=%d\n", ap->id, pcs, base);
+
+       for (i = 0; i < 2; i++) {
+               port = map[base + i];
+               if (port < 0)
+                       continue;
+               if ((ap->flags & PIIX_FLAG_IGNORE_PCS) ||
+                   (pcs & 1 << (hpriv->map_db->present_shift + port)))
+                       present = 1;
+       }
+
+       DPRINTK("ata%u: LEAVE, pcs=0x%x present=0x%x\n",
+               ap->id, pcs, present);
+
+       if (!present) {
+               ata_port_printk(ap, KERN_INFO, "SATA port has no device.\n");
+               ap->eh_context.i.action &= ~ATA_EH_RESET_MASK;
+               return 0;
+       }
+
+       return ata_std_prereset(ap);
+}
+
+static void piix_sata_error_handler(struct ata_port *ap)
+{
+       ata_bmdma_drive_eh(ap, piix_sata_prereset, ata_std_softreset, NULL,
+                          ata_std_postreset);
+}
+
+/**
+ *     piix_set_piomode - Initialize host controller PATA PIO timings
+ *     @ap: Port whose timings we are configuring
+ *     @adev: um
+ *
+ *     Set PIO mode for device, in host controller PCI config space.
+ *
+ *     LOCKING:
+ *     None (inherited from caller).
+ */
+
+static void piix_set_piomode (struct ata_port *ap, struct ata_device *adev)
+{
+       unsigned int pio        = adev->pio_mode - XFER_PIO_0;
+       struct pci_dev *dev     = to_pci_dev(ap->host_set->dev);
+       unsigned int is_slave   = (adev->devno != 0);
+       unsigned int master_port= ap->port_no ? 0x42 : 0x40;
+       unsigned int slave_port = 0x44;
+       u16 master_data;
+       u8 slave_data;
+
+       static const     /* ISP  RTC */
+       u8 timings[][2] = { { 0, 0 },
+                           { 0, 0 },
+                           { 1, 0 },
+                           { 2, 1 },
+                           { 2, 3 }, };
+
+       pci_read_config_word(dev, master_port, &master_data);
+       if (is_slave) {
+               master_data |= 0x4000;
+               /* enable PPE, IE and TIME */
+               master_data |= 0x0070;
+               pci_read_config_byte(dev, slave_port, &slave_data);
+               slave_data &= (ap->port_no ? 0x0f : 0xf0);
+               slave_data |=
+                       (timings[pio][0] << 2) |
+                       (timings[pio][1] << (ap->port_no ? 4 : 0));
+       } else {
+               master_data &= 0xccf8;
+               /* enable PPE, IE and TIME */
+               master_data |= 0x0007;
+               master_data |=
+                       (timings[pio][0] << 12) |
+                       (timings[pio][1] << 8);
+       }
+       pci_write_config_word(dev, master_port, master_data);
+       if (is_slave)
+               pci_write_config_byte(dev, slave_port, slave_data);
+}
+
+/**
+ *     piix_set_dmamode - Initialize host controller PATA PIO timings
+ *     @ap: Port whose timings we are configuring
+ *     @adev: um
+ *     @udma: udma mode, 0 - 6
+ *
+ *     Set UDMA mode for device, in host controller PCI config space.
+ *
+ *     LOCKING:
+ *     None (inherited from caller).
+ */
+
+static void piix_set_dmamode (struct ata_port *ap, struct ata_device *adev)
+{
+       unsigned int udma       = adev->dma_mode; /* FIXME: MWDMA too */
+       struct pci_dev *dev     = to_pci_dev(ap->host_set->dev);
+       u8 maslave              = ap->port_no ? 0x42 : 0x40;
+       u8 speed                = udma;
+       unsigned int drive_dn   = (ap->port_no ? 2 : 0) + adev->devno;
+       int a_speed             = 3 << (drive_dn * 4);
+       int u_flag              = 1 << drive_dn;
+       int v_flag              = 0x01 << drive_dn;
+       int w_flag              = 0x10 << drive_dn;
+       int u_speed             = 0;
+       int                     sitre;
+       u16                     reg4042, reg4a;
+       u8                      reg48, reg54, reg55;
+
+       pci_read_config_word(dev, maslave, &reg4042);
+       DPRINTK("reg4042 = 0x%04x\n", reg4042);
+       sitre = (reg4042 & 0x4000) ? 1 : 0;
+       pci_read_config_byte(dev, 0x48, &reg48);
+       pci_read_config_word(dev, 0x4a, &reg4a);
+       pci_read_config_byte(dev, 0x54, &reg54);
+       pci_read_config_byte(dev, 0x55, &reg55);
+
+       switch(speed) {
+               case XFER_UDMA_4:
+               case XFER_UDMA_2:       u_speed = 2 << (drive_dn * 4); break;
+               case XFER_UDMA_6:
+               case XFER_UDMA_5:
+               case XFER_UDMA_3:
+               case XFER_UDMA_1:       u_speed = 1 << (drive_dn * 4); break;
+               case XFER_UDMA_0:       u_speed = 0 << (drive_dn * 4); break;
+               case XFER_MW_DMA_2:
+               case XFER_MW_DMA_1:     break;
+               default:
+                       BUG();
+                       return;
+       }
+
+       if (speed >= XFER_UDMA_0) {
+               if (!(reg48 & u_flag))
+                       pci_write_config_byte(dev, 0x48, reg48 | u_flag);
+               if (speed == XFER_UDMA_5) {
+                       pci_write_config_byte(dev, 0x55, (u8) reg55|w_flag);
+               } else {
+                       pci_write_config_byte(dev, 0x55, (u8) reg55 & ~w_flag);
+               }
+               if ((reg4a & a_speed) != u_speed)
+                       pci_write_config_word(dev, 0x4a, (reg4a & ~a_speed) | u_speed);
+               if (speed > XFER_UDMA_2) {
+                       if (!(reg54 & v_flag))
+                               pci_write_config_byte(dev, 0x54, reg54 | v_flag);
+               } else
+                       pci_write_config_byte(dev, 0x54, reg54 & ~v_flag);
+       } else {
+               if (reg48 & u_flag)
+                       pci_write_config_byte(dev, 0x48, reg48 & ~u_flag);
+               if (reg4a & a_speed)
+                       pci_write_config_word(dev, 0x4a, reg4a & ~a_speed);
+               if (reg54 & v_flag)
+                       pci_write_config_byte(dev, 0x54, reg54 & ~v_flag);
+               if (reg55 & w_flag)
+                       pci_write_config_byte(dev, 0x55, (u8) reg55 & ~w_flag);
+       }
+}
+
+#define AHCI_PCI_BAR 5
+#define AHCI_GLOBAL_CTL 0x04
+#define AHCI_ENABLE (1 << 31)
+static int piix_disable_ahci(struct pci_dev *pdev)
+{
+       void __iomem *mmio;
+       u32 tmp;
+       int rc = 0;
+
+       /* BUG: pci_enable_device has not yet been called.  This
+        * works because this device is usually set up by BIOS.
+        */
+
+       if (!pci_resource_start(pdev, AHCI_PCI_BAR) ||
+           !pci_resource_len(pdev, AHCI_PCI_BAR))
+               return 0;
+
+       mmio = pci_iomap(pdev, AHCI_PCI_BAR, 64);
+       if (!mmio)
+               return -ENOMEM;
+
+       tmp = readl(mmio + AHCI_GLOBAL_CTL);
+       if (tmp & AHCI_ENABLE) {
+               tmp &= ~AHCI_ENABLE;
+               writel(tmp, mmio + AHCI_GLOBAL_CTL);
+
+               tmp = readl(mmio + AHCI_GLOBAL_CTL);
+               if (tmp & AHCI_ENABLE)
+                       rc = -EIO;
+       }
+
+       pci_iounmap(pdev, mmio);
+       return rc;
+}
+
+/**
+ *     piix_check_450nx_errata -       Check for problem 450NX setup
+ *     @ata_dev: the PCI device to check
+ *
+ *     Check for the present of 450NX errata #19 and errata #25. If
+ *     they are found return an error code so we can turn off DMA
+ */
+
+static int __devinit piix_check_450nx_errata(struct pci_dev *ata_dev)
+{
+       struct pci_dev *pdev = NULL;
+       u16 cfg;
+       u8 rev;
+       int no_piix_dma = 0;
+
+       while((pdev = pci_get_device(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82454NX, pdev)) != NULL)
+       {
+               /* Look for 450NX PXB. Check for problem configurations
+                  A PCI quirk checks bit 6 already */
+               pci_read_config_byte(pdev, PCI_REVISION_ID, &rev);
+               pci_read_config_word(pdev, 0x41, &cfg);
+               /* Only on the original revision: IDE DMA can hang */
+               if (rev == 0x00)
+                       no_piix_dma = 1;
+               /* On all revisions below 5 PXB bus lock must be disabled for IDE */
+               else if (cfg & (1<<14) && rev < 5)
+                       no_piix_dma = 2;
+       }
+       if (no_piix_dma)
+               dev_printk(KERN_WARNING, &ata_dev->dev, "450NX errata present, disabling IDE DMA.\n");
+       if (no_piix_dma == 2)
+               dev_printk(KERN_WARNING, &ata_dev->dev, "A BIOS update may resolve this.\n");
+       return no_piix_dma;
+}
+
+static void __devinit piix_init_pcs(struct pci_dev *pdev,
+                                   const struct piix_map_db *map_db)
+{
+       u16 pcs, new_pcs;
+
+       pci_read_config_word(pdev, ICH5_PCS, &pcs);
+
+       new_pcs = pcs | map_db->port_enable;
+
+       if (new_pcs != pcs) {
+               DPRINTK("updating PCS from 0x%x to 0x%x\n", pcs, new_pcs);
+               pci_write_config_word(pdev, ICH5_PCS, new_pcs);
+               msleep(150);
+       }
+}
+
+static void __devinit piix_init_sata_map(struct pci_dev *pdev,
+                                        struct ata_port_info *pinfo,
+                                        const struct piix_map_db *map_db)
+{
+       struct piix_host_priv *hpriv = pinfo[0].private_data;
+       const unsigned int *map;
+       int i, invalid_map = 0;
+       u8 map_value;
+
+       pci_read_config_byte(pdev, ICH5_PMR, &map_value);
+
+       map = map_db->map[map_value & map_db->mask];
+
+       dev_printk(KERN_INFO, &pdev->dev, "MAP [");
+       for (i = 0; i < 4; i++) {
+               switch (map[i]) {
+               case RV:
+                       invalid_map = 1;
+                       printk(" XX");
+                       break;
+
+               case NA:
+                       printk(" --");
+                       break;
+
+               case IDE:
+                       WARN_ON((i & 1) || map[i + 1] != IDE);
+                       pinfo[i / 2] = piix_port_info[ich5_pata];
+                       pinfo[i / 2].private_data = hpriv;
+                       i++;
+                       printk(" IDE IDE");
+                       break;
+
+               default:
+                       printk(" P%d", map[i]);
+                       if (i & 1)
+                               pinfo[i / 2].host_flags |= ATA_FLAG_SLAVE_POSS;
+                       break;
+               }
+       }
+       printk(" ]\n");
+
+       if (invalid_map)
+               dev_printk(KERN_ERR, &pdev->dev,
+                          "invalid MAP value %u\n", map_value);
+
+       hpriv->map = map;
+       hpriv->map_db = map_db;
+}
+
+/**
+ *     piix_init_one - Register PIIX ATA PCI device with kernel services
+ *     @pdev: PCI device to register
+ *     @ent: Entry in piix_pci_tbl matching with @pdev
+ *
+ *     Called from kernel PCI layer.  We probe for combined mode (sigh),
+ *     and then hand over control to libata, for it to do the rest.
+ *
+ *     LOCKING:
+ *     Inherited from PCI layer (may sleep).
+ *
+ *     RETURNS:
+ *     Zero on success, or -ERRNO value.
+ */
+
+static int piix_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
+{
+       static int printed_version;
+       struct ata_port_info port_info[2];
+       struct ata_port_info *ppinfo[2] = { &port_info[0], &port_info[1] };
+       struct piix_host_priv *hpriv;
+       unsigned long host_flags;
+
+       if (!printed_version++)
+               dev_printk(KERN_DEBUG, &pdev->dev,
+                          "version " DRV_VERSION "\n");
+
+       /* no hotplugging support (FIXME) */
+       if (!in_module_init)
+               return -ENODEV;
+
+       hpriv = kzalloc(sizeof(*hpriv), GFP_KERNEL);
+       if (!hpriv)
+               return -ENOMEM;
+
+       port_info[0] = piix_port_info[ent->driver_data];
+       port_info[1] = piix_port_info[ent->driver_data];
+       port_info[0].private_data = hpriv;
+       port_info[1].private_data = hpriv;
+
+       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) {
+                       int rc = piix_disable_ahci(pdev);
+                       if (rc)
+                               return rc;
+               }
+       }
+
+       /* Initialize SATA map */
+       if (host_flags & ATA_FLAG_SATA) {
+               piix_init_sata_map(pdev, port_info,
+                                  piix_map_db_table[ent->driver_data]);
+               piix_init_pcs(pdev, piix_map_db_table[ent->driver_data]);
+       }
+
+       /* On ICH5, some BIOSen disable the interrupt using the
+        * PCI_COMMAND_INTX_DISABLE bit added in PCI 2.3.
+        * On ICH6, this bit has the same effect, but only when
+        * MSI is disabled (and it is disabled, as we don't use
+        * message-signalled interrupts currently).
+        */
+       if (host_flags & PIIX_FLAG_CHECKINTR)
+               pci_intx(pdev, 1);
+
+       if (piix_check_450nx_errata(pdev)) {
+               /* This writes into the master table but it does not
+                  really matter for this errata as we will apply it to
+                  all the PIIX devices on the board */
+               port_info[0].mwdma_mask = 0;
+               port_info[0].udma_mask = 0;
+               port_info[1].mwdma_mask = 0;
+               port_info[1].udma_mask = 0;
+       }
+       return ata_pci_init_one(pdev, ppinfo, 2);
+}
+
+static void piix_host_stop(struct ata_host_set *host_set)
+{
+       ata_host_stop(host_set);
+}
+
+static int __init piix_init(void)
+{
+       int rc;
+
+       DPRINTK("pci_register_driver\n");
+       rc = pci_register_driver(&piix_pci_driver);
+       if (rc)
+               return rc;
+
+       in_module_init = 0;
+
+       DPRINTK("done\n");
+       return 0;
+}
+
+static void __exit piix_exit(void)
+{
+       pci_unregister_driver(&piix_pci_driver);
+}
+
+module_init(piix_init);
+module_exit(piix_exit);
+
diff --git a/drivers/ata/libata-bmdma.c b/drivers/ata/libata-bmdma.c
new file mode 100644 (file)
index 0000000..158f62d
--- /dev/null
@@ -0,0 +1,1109 @@
+/*
+ *  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/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.
+ *
+ *     FIXME: missing write posting for 400nS delay enforcement
+ *
+ *     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);
+}
+
+/**
+ *     ata_bmdma_setup_mmio - Set up PCI IDE BMDMA transaction
+ *     @qc: Info associated with this ATA transaction.
+ *
+ *     LOCKING:
+ *     spin_lock_irqsave(host_set lock)
+ */
+
+static void ata_bmdma_setup_mmio (struct ata_queued_cmd *qc)
+{
+       struct ata_port *ap = qc->ap;
+       unsigned int rw = (qc->tf.flags & ATA_TFLAG_WRITE);
+       u8 dmactl;
+       void __iomem *mmio = (void __iomem *) ap->ioaddr.bmdma_addr;
+
+       /* load PRD table addr. */
+       mb();   /* make sure PRD table writes are visible to controller */
+       writel(ap->prd_dma, mmio + ATA_DMA_TABLE_OFS);
+
+       /* specify data direction, triple-check start bit is clear */
+       dmactl = readb(mmio + ATA_DMA_CMD);
+       dmactl &= ~(ATA_DMA_WR | ATA_DMA_START);
+       if (!rw)
+               dmactl |= ATA_DMA_WR;
+       writeb(dmactl, mmio + ATA_DMA_CMD);
+
+       /* issue r/w command */
+       ap->ops->exec_command(ap, &qc->tf);
+}
+
+/**
+ *     ata_bmdma_start_mmio - Start a PCI IDE BMDMA transaction
+ *     @qc: Info associated with this ATA transaction.
+ *
+ *     LOCKING:
+ *     spin_lock_irqsave(host_set lock)
+ */
+
+static void ata_bmdma_start_mmio (struct ata_queued_cmd *qc)
+{
+       struct ata_port *ap = qc->ap;
+       void __iomem *mmio = (void __iomem *) ap->ioaddr.bmdma_addr;
+       u8 dmactl;
+
+       /* start host DMA transaction */
+       dmactl = readb(mmio + ATA_DMA_CMD);
+       writeb(dmactl | ATA_DMA_START, mmio + ATA_DMA_CMD);
+
+       /* Strictly, one may wish to issue a readb() here, to
+        * flush the mmio write.  However, control also passes
+        * to the hardware at this point, and it will interrupt
+        * us when we are to resume control.  So, in effect,
+        * we don't care when the mmio write flushes.
+        * Further, a read of the DMA status register _immediately_
+        * following the write may not be what certain flaky hardware
+        * is expected, so I think it is best to not add a readb()
+        * without first all the MMIO ATA cards/mobos.
+        * Or maybe I'm just being paranoid.
+        */
+}
+
+/**
+ *     ata_bmdma_setup_pio - Set up PCI IDE BMDMA transaction (PIO)
+ *     @qc: Info associated with this ATA transaction.
+ *
+ *     LOCKING:
+ *     spin_lock_irqsave(host_set lock)
+ */
+
+static void ata_bmdma_setup_pio (struct ata_queued_cmd *qc)
+{
+       struct ata_port *ap = qc->ap;
+       unsigned int rw = (qc->tf.flags & ATA_TFLAG_WRITE);
+       u8 dmactl;
+
+       /* load PRD table addr. */
+       outl(ap->prd_dma, ap->ioaddr.bmdma_addr + ATA_DMA_TABLE_OFS);
+
+       /* specify data direction, triple-check start bit is clear */
+       dmactl = inb(ap->ioaddr.bmdma_addr + ATA_DMA_CMD);
+       dmactl &= ~(ATA_DMA_WR | ATA_DMA_START);
+       if (!rw)
+               dmactl |= ATA_DMA_WR;
+       outb(dmactl, ap->ioaddr.bmdma_addr + ATA_DMA_CMD);
+
+       /* issue r/w command */
+       ap->ops->exec_command(ap, &qc->tf);
+}
+
+/**
+ *     ata_bmdma_start_pio - Start a PCI IDE BMDMA transaction (PIO)
+ *     @qc: Info associated with this ATA transaction.
+ *
+ *     LOCKING:
+ *     spin_lock_irqsave(host_set lock)
+ */
+
+static void ata_bmdma_start_pio (struct ata_queued_cmd *qc)
+{
+       struct ata_port *ap = qc->ap;
+       u8 dmactl;
+
+       /* start host DMA transaction */
+       dmactl = inb(ap->ioaddr.bmdma_addr + ATA_DMA_CMD);
+       outb(dmactl | ATA_DMA_START,
+            ap->ioaddr.bmdma_addr + ATA_DMA_CMD);
+}
+
+
+/**
+ *     ata_bmdma_start - Start a PCI IDE BMDMA transaction
+ *     @qc: Info associated with this ATA transaction.
+ *
+ *     Writes the ATA_DMA_START flag to the DMA command register.
+ *
+ *     May be used as the bmdma_start() entry in ata_port_operations.
+ *
+ *     LOCKING:
+ *     spin_lock_irqsave(host_set lock)
+ */
+void ata_bmdma_start(struct ata_queued_cmd *qc)
+{
+       if (qc->ap->flags & ATA_FLAG_MMIO)
+               ata_bmdma_start_mmio(qc);
+       else
+               ata_bmdma_start_pio(qc);
+}
+
+
+/**
+ *     ata_bmdma_setup - Set up PCI IDE BMDMA transaction
+ *     @qc: Info associated with this ATA transaction.
+ *
+ *     Writes address of PRD table to device's PRD Table Address
+ *     register, sets the DMA control register, and calls
+ *     ops->exec_command() to start the transfer.
+ *
+ *     May be used as the bmdma_setup() entry in ata_port_operations.
+ *
+ *     LOCKING:
+ *     spin_lock_irqsave(host_set lock)
+ */
+void ata_bmdma_setup(struct ata_queued_cmd *qc)
+{
+       if (qc->ap->flags & ATA_FLAG_MMIO)
+               ata_bmdma_setup_mmio(qc);
+       else
+               ata_bmdma_setup_pio(qc);
+}
+
+
+/**
+ *     ata_bmdma_irq_clear - Clear PCI IDE BMDMA interrupt.
+ *     @ap: Port associated with this ATA transaction.
+ *
+ *     Clear interrupt and error flags in DMA status register.
+ *
+ *     May be used as the irq_clear() entry in ata_port_operations.
+ *
+ *     LOCKING:
+ *     spin_lock_irqsave(host_set lock)
+ */
+
+void ata_bmdma_irq_clear(struct ata_port *ap)
+{
+       if (!ap->ioaddr.bmdma_addr)
+               return;
+
+       if (ap->flags & ATA_FLAG_MMIO) {
+               void __iomem *mmio =
+                     ((void __iomem *) ap->ioaddr.bmdma_addr) + ATA_DMA_STATUS;
+               writeb(readb(mmio), mmio);
+       } else {
+               unsigned long addr = ap->ioaddr.bmdma_addr + ATA_DMA_STATUS;
+               outb(inb(addr), addr);
+       }
+}
+
+
+/**
+ *     ata_bmdma_status - Read PCI IDE BMDMA status
+ *     @ap: Port associated with this ATA transaction.
+ *
+ *     Read and return BMDMA status register.
+ *
+ *     May be used as the bmdma_status() entry in ata_port_operations.
+ *
+ *     LOCKING:
+ *     spin_lock_irqsave(host_set lock)
+ */
+
+u8 ata_bmdma_status(struct ata_port *ap)
+{
+       u8 host_stat;
+       if (ap->flags & ATA_FLAG_MMIO) {
+               void __iomem *mmio = (void __iomem *) ap->ioaddr.bmdma_addr;
+               host_stat = readb(mmio + ATA_DMA_STATUS);
+       } else
+               host_stat = inb(ap->ioaddr.bmdma_addr + ATA_DMA_STATUS);
+       return host_stat;
+}
+
+
+/**
+ *     ata_bmdma_stop - Stop PCI IDE BMDMA transfer
+ *     @qc: Command we are ending DMA for
+ *
+ *     Clears the ATA_DMA_START flag in the dma control register
+ *
+ *     May be used as the bmdma_stop() entry in ata_port_operations.
+ *
+ *     LOCKING:
+ *     spin_lock_irqsave(host_set lock)
+ */
+
+void ata_bmdma_stop(struct ata_queued_cmd *qc)
+{
+       struct ata_port *ap = qc->ap;
+       if (ap->flags & ATA_FLAG_MMIO) {
+               void __iomem *mmio = (void __iomem *) ap->ioaddr.bmdma_addr;
+
+               /* clear start/stop bit */
+               writeb(readb(mmio + ATA_DMA_CMD) & ~ATA_DMA_START,
+                       mmio + ATA_DMA_CMD);
+       } else {
+               /* clear start/stop bit */
+               outb(inb(ap->ioaddr.bmdma_addr + ATA_DMA_CMD) & ~ATA_DMA_START,
+                       ap->ioaddr.bmdma_addr + ATA_DMA_CMD);
+       }
+
+       /* one-PIO-cycle guaranteed wait, per spec, for HDMA1:0 transition */
+       ata_altstatus(ap);        /* dummy read */
+}
+
+/**
+ *     ata_bmdma_freeze - Freeze BMDMA controller port
+ *     @ap: port to freeze
+ *
+ *     Freeze BMDMA controller port.
+ *
+ *     LOCKING:
+ *     Inherited from caller.
+ */
+void ata_bmdma_freeze(struct ata_port *ap)
+{
+       struct ata_ioports *ioaddr = &ap->ioaddr;
+
+       ap->ctl |= ATA_NIEN;
+       ap->last_ctl = ap->ctl;
+
+       if (ap->flags & ATA_FLAG_MMIO)
+               writeb(ap->ctl, (void __iomem *)ioaddr->ctl_addr);
+       else
+               outb(ap->ctl, ioaddr->ctl_addr);
+}
+
+/**
+ *     ata_bmdma_thaw - Thaw BMDMA controller port
+ *     @ap: port to thaw
+ *
+ *     Thaw BMDMA controller port.
+ *
+ *     LOCKING:
+ *     Inherited from caller.
+ */
+void ata_bmdma_thaw(struct ata_port *ap)
+{
+       /* clear & re-enable interrupts */
+       ata_chk_status(ap);
+       ap->ops->irq_clear(ap);
+       if (ap->ioaddr.ctl_addr)        /* FIXME: hack. create a hook instead */
+               ata_irq_on(ap);
+}
+
+/**
+ *     ata_bmdma_drive_eh - Perform EH with given methods for BMDMA controller
+ *     @ap: port to handle error for
+ *     @prereset: prereset method (can be NULL)
+ *     @softreset: softreset method (can be NULL)
+ *     @hardreset: hardreset method (can be NULL)
+ *     @postreset: postreset method (can be NULL)
+ *
+ *     Handle error for ATA BMDMA controller.  It can handle both
+ *     PATA and SATA controllers.  Many controllers should be able to
+ *     use this EH as-is or with some added handling before and
+ *     after.
+ *
+ *     This function is intended to be used for constructing
+ *     ->error_handler callback by low level drivers.
+ *
+ *     LOCKING:
+ *     Kernel thread context (may sleep)
+ */
+void ata_bmdma_drive_eh(struct ata_port *ap, ata_prereset_fn_t prereset,
+                       ata_reset_fn_t softreset, ata_reset_fn_t hardreset,
+                       ata_postreset_fn_t postreset)
+{
+       struct ata_eh_context *ehc = &ap->eh_context;
+       struct ata_queued_cmd *qc;
+       unsigned long flags;
+       int thaw = 0;
+
+       qc = __ata_qc_from_tag(ap, ap->active_tag);
+       if (qc && !(qc->flags & ATA_QCFLAG_FAILED))
+               qc = NULL;
+
+       /* reset PIO HSM and stop DMA engine */
+       spin_lock_irqsave(ap->lock, flags);
+
+       ap->hsm_task_state = HSM_ST_IDLE;
+
+       if (qc && (qc->tf.protocol == ATA_PROT_DMA ||
+                  qc->tf.protocol == ATA_PROT_ATAPI_DMA)) {
+               u8 host_stat;
+
+               host_stat = ata_bmdma_status(ap);
+
+               ata_ehi_push_desc(&ehc->i, "BMDMA stat 0x%x", host_stat);
+
+               /* BMDMA controllers indicate host bus error by
+                * setting DMA_ERR bit and timing out.  As it wasn't
+                * really a timeout event, adjust error mask and
+                * cancel frozen state.
+                */
+               if (qc->err_mask == AC_ERR_TIMEOUT && host_stat & ATA_DMA_ERR) {
+                       qc->err_mask = AC_ERR_HOST_BUS;
+                       thaw = 1;
+               }
+
+               ap->ops->bmdma_stop(qc);
+       }
+
+       ata_altstatus(ap);
+       ata_chk_status(ap);
+       ap->ops->irq_clear(ap);
+
+       spin_unlock_irqrestore(ap->lock, flags);
+
+       if (thaw)
+               ata_eh_thaw_port(ap);
+
+       /* PIO and DMA engines have been stopped, perform recovery */
+       ata_do_eh(ap, prereset, softreset, hardreset, postreset);
+}
+
+/**
+ *     ata_bmdma_error_handler - Stock error handler for BMDMA controller
+ *     @ap: port to handle error for
+ *
+ *     Stock error handler for BMDMA controller.
+ *
+ *     LOCKING:
+ *     Kernel thread context (may sleep)
+ */
+void ata_bmdma_error_handler(struct ata_port *ap)
+{
+       ata_reset_fn_t hardreset;
+
+       hardreset = NULL;
+       if (sata_scr_valid(ap))
+               hardreset = sata_std_hardreset;
+
+       ata_bmdma_drive_eh(ap, ata_std_prereset, ata_std_softreset, hardreset,
+                          ata_std_postreset);
+}
+
+/**
+ *     ata_bmdma_post_internal_cmd - Stock post_internal_cmd for
+ *                                   BMDMA controller
+ *     @qc: internal command to clean up
+ *
+ *     LOCKING:
+ *     Kernel thread context (may sleep)
+ */
+void ata_bmdma_post_internal_cmd(struct ata_queued_cmd *qc)
+{
+       ata_bmdma_stop(qc);
+}
+
+#ifdef CONFIG_PCI
+/**
+ *     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;
+       unsigned long bmdma;
+
+       if (!probe_ent)
+               return NULL;
+
+       probe_ent->irq = pdev->irq;
+       probe_ent->irq_flags = IRQF_SHARED;
+       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;
+               bmdma = pci_resource_start(pdev, 4);
+               if (bmdma) {
+                       if (inb(bmdma + 2) & 0x80)
+                               probe_ent->host_set_flags |= ATA_HOST_SIMPLEX;
+                       probe_ent->port[p].bmdma_addr = bmdma;
+               }
+               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;
+               bmdma = pci_resource_start(pdev, 4);
+               if (bmdma) {
+                       bmdma += 8;
+                       if(inb(bmdma + 2) & 0x80)
+                               probe_ent->host_set_flags |= ATA_HOST_SIMPLEX;
+                       probe_ent->port[p].bmdma_addr = bmdma;
+               }
+               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_mask)
+{
+       struct ata_probe_ent *probe_ent;
+       unsigned long bmdma = pci_resource_start(pdev, 4);
+
+       probe_ent = ata_probe_ent_alloc(pci_dev_to_dev(pdev), port[0]);
+       if (!probe_ent)
+               return NULL;
+
+       probe_ent->n_ports = 2;
+       probe_ent->private_data = port[0]->private_data;
+
+       if (port_mask & ATA_PORT_PRIMARY) {
+               probe_ent->irq = 14;
+               probe_ent->port[0].cmd_addr = ATA_PRIMARY_CMD;
+               probe_ent->port[0].altstatus_addr =
+               probe_ent->port[0].ctl_addr = ATA_PRIMARY_CTL;
+               if (bmdma) {
+                       probe_ent->port[0].bmdma_addr = bmdma;
+                       if (inb(bmdma + 2) & 0x80)
+                               probe_ent->host_set_flags |= ATA_HOST_SIMPLEX;
+               }
+               ata_std_ports(&probe_ent->port[0]);
+       } else
+               probe_ent->dummy_port_mask |= ATA_PORT_PRIMARY;
+
+       if (port_mask & ATA_PORT_SECONDARY) {
+               if (probe_ent->irq)
+                       probe_ent->irq2 = 15;
+               else
+                       probe_ent->irq = 15;
+               probe_ent->port[1].cmd_addr = ATA_SECONDARY_CMD;
+               probe_ent->port[1].altstatus_addr =
+               probe_ent->port[1].ctl_addr = ATA_SECONDARY_CTL;
+               if (bmdma) {
+                       probe_ent->port[1].bmdma_addr = bmdma + 8;
+                       if (inb(bmdma + 10) & 0x80)
+                               probe_ent->host_set_flags |= ATA_HOST_SIMPLEX;
+               }
+               ata_std_ports(&probe_ent->port[1]);
+       } else
+               probe_ent->dummy_port_mask |= ATA_PORT_SECONDARY;
+
+       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()
+ *
+ *     ASSUMPTION:
+ *     Nobody makes a single channel controller that appears solely as
+ *     the secondary legacy port on PCI.
+ *
+ *     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;
+       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;
+       }
+
+       if (legacy_mode) {
+               if (!request_region(ATA_PRIMARY_CMD, 8, "libata")) {
+                       struct resource *conflict, res;
+                       res.start = ATA_PRIMARY_CMD;
+                       res.end = ATA_PRIMARY_CMD + 8 - 1;
+                       conflict = ____request_resource(&ioport_resource, &res);
+                       if (!strcmp(conflict->name, "libata"))
+                               legacy_mode |= ATA_PORT_PRIMARY;
+                       else {
+                               disable_dev_on_err = 0;
+                               printk(KERN_WARNING "ata: 0x%0X IDE port busy\n", ATA_PRIMARY_CMD);
+                       }
+               } else
+                       legacy_mode |= ATA_PORT_PRIMARY;
+
+               if (!request_region(ATA_SECONDARY_CMD, 8, "libata")) {
+                       struct resource *conflict, res;
+                       res.start = ATA_SECONDARY_CMD;
+                       res.end = ATA_SECONDARY_CMD + 8 - 1;
+                       conflict = ____request_resource(&ioport_resource, &res);
+                       if (!strcmp(conflict->name, "libata"))
+                               legacy_mode |= ATA_PORT_SECONDARY;
+                       else {
+                               disable_dev_on_err = 0;
+                               printk(KERN_WARNING "ata: 0x%X IDE port busy\n", ATA_SECONDARY_CMD);
+                       }
+               } else
+                       legacy_mode |= ATA_PORT_SECONDARY;
+       }
+
+       /* we have legacy mode, but all ports are unavailable */
+       if (legacy_mode == (1 << 3)) {
+               rc = -EBUSY;
+               goto err_out_regions;
+       }
+
+       /* FIXME: If we get no DMA mask we should fall back to PIO */
+       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) {
+               probe_ent = ata_pci_init_legacy_port(pdev, port, legacy_mode);
+       } 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) {
+               rc = -ENOMEM;
+               goto err_out_regions;
+       }
+
+       pci_set_master(pdev);
+
+       /* FIXME: check ata_device_add return */
+       ata_device_add(probe_ent);
+
+       kfree(probe_ent);
+
+       return 0;
+
+err_out_regions:
+       if (legacy_mode & ATA_PORT_PRIMARY)
+               release_region(ATA_PRIMARY_CMD, 8);
+       if (legacy_mode & ATA_PORT_SECONDARY)
+               release_region(ATA_SECONDARY_CMD, 8);
+       pci_release_regions(pdev);
+err_out:
+       if (disable_dev_on_err)
+               pci_disable_device(pdev);
+       return rc;
+}
+
+/**
+ *     ata_pci_clear_simplex   -       attempt to kick device out of simplex
+ *     @pdev: PCI device
+ *
+ *     Some PCI ATA devices report simplex mode but in fact can be told to
+ *     enter non simplex mode. This implements the neccessary logic to
+ *     perform the task on such devices. Calling it on other devices will
+ *     have -undefined- behaviour.
+ */
+
+int ata_pci_clear_simplex(struct pci_dev *pdev)
+{
+       unsigned long bmdma = pci_resource_start(pdev, 4);
+       u8 simplex;
+
+       if (bmdma == 0)
+               return -ENOENT;
+
+       simplex = inb(bmdma + 0x02);
+       outb(simplex & 0x60, bmdma + 0x02);
+       simplex = inb(bmdma + 0x02);
+       if (simplex & 0x80)
+               return -EOPNOTSUPP;
+       return 0;
+}
+
+unsigned long ata_pci_default_filter(const struct ata_port *ap, struct ata_device *adev, unsigned long xfer_mask)
+{
+       /* Filter out DMA modes if the device has been configured by
+          the BIOS as PIO only */
+
+       if (ap->ioaddr.bmdma_addr == 0)
+               xfer_mask &= ~(ATA_MASK_MWDMA | ATA_MASK_UDMA);
+       return xfer_mask;
+}
+
+#endif /* CONFIG_PCI */
+
diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c
new file mode 100644 (file)
index 0000000..7d786fb
--- /dev/null
@@ -0,0 +1,6097 @@
+/*
+ *  libata-core.c - helper library for ATA
+ *
+ *  Maintained by:  Jeff Garzik <jgarzik@pobox.com>
+ *                 Please ALWAYS copy linux-ide@vger.kernel.org
+ *                 on emails.
+ *
+ *  Copyright 2003-2004 Red Hat, Inc.  All rights reserved.
+ *  Copyright 2003-2004 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/kernel.h>
+#include <linux/module.h>
+#include <linux/pci.h>
+#include <linux/init.h>
+#include <linux/list.h>
+#include <linux/mm.h>
+#include <linux/highmem.h>
+#include <linux/spinlock.h>
+#include <linux/blkdev.h>
+#include <linux/delay.h>
+#include <linux/timer.h>
+#include <linux/interrupt.h>
+#include <linux/completion.h>
+#include <linux/suspend.h>
+#include <linux/workqueue.h>
+#include <linux/jiffies.h>
+#include <linux/scatterlist.h>
+#include <scsi/scsi.h>
+#include <scsi/scsi_cmnd.h>
+#include <scsi/scsi_host.h>
+#include <linux/libata.h>
+#include <asm/io.h>
+#include <asm/semaphore.h>
+#include <asm/byteorder.h>
+
+#include "libata.h"
+
+/* debounce timing parameters in msecs { interval, duration, timeout } */
+const unsigned long sata_deb_timing_normal[]           = {   5,  100, 2000 };
+const unsigned long sata_deb_timing_hotplug[]          = {  25,  500, 2000 };
+const unsigned long sata_deb_timing_long[]             = { 100, 2000, 5000 };
+
+static unsigned int ata_dev_init_params(struct ata_device *dev,
+                                       u16 heads, u16 sectors);
+static unsigned int ata_dev_set_xfermode(struct ata_device *dev);
+static void ata_dev_xfermask(struct ata_device *dev);
+
+static unsigned int ata_unique_id = 1;
+static struct workqueue_struct *ata_wq;
+
+struct workqueue_struct *ata_aux_wq;
+
+int atapi_enabled = 1;
+module_param(atapi_enabled, int, 0444);
+MODULE_PARM_DESC(atapi_enabled, "Enable discovery of ATAPI devices (0=off, 1=on)");
+
+int atapi_dmadir = 0;
+module_param(atapi_dmadir, int, 0444);
+MODULE_PARM_DESC(atapi_dmadir, "Enable ATAPI DMADIR bridge support (0=off, 1=on)");
+
+int libata_fua = 0;
+module_param_named(fua, libata_fua, int, 0444);
+MODULE_PARM_DESC(fua, "FUA support (0=off, 1=on)");
+
+static int ata_probe_timeout = ATA_TMOUT_INTERNAL / HZ;
+module_param(ata_probe_timeout, int, 0444);
+MODULE_PARM_DESC(ata_probe_timeout, "Set ATA probing timeout (seconds)");
+
+MODULE_AUTHOR("Jeff Garzik");
+MODULE_DESCRIPTION("Library module for ATA devices");
+MODULE_LICENSE("GPL");
+MODULE_VERSION(DRV_VERSION);
+
+
+/**
+ *     ata_tf_to_fis - Convert ATA taskfile to SATA FIS structure
+ *     @tf: Taskfile to convert
+ *     @fis: Buffer into which data will output
+ *     @pmp: Port multiplier port
+ *
+ *     Converts a standard ATA taskfile to a Serial ATA
+ *     FIS structure (Register - Host to Device).
+ *
+ *     LOCKING:
+ *     Inherited from caller.
+ */
+
+void ata_tf_to_fis(const struct ata_taskfile *tf, u8 *fis, u8 pmp)
+{
+       fis[0] = 0x27;  /* Register - Host to Device FIS */
+       fis[1] = (pmp & 0xf) | (1 << 7); /* Port multiplier number,
+                                           bit 7 indicates Command FIS */
+       fis[2] = tf->command;
+       fis[3] = tf->feature;
+
+       fis[4] = tf->lbal;
+       fis[5] = tf->lbam;
+       fis[6] = tf->lbah;
+       fis[7] = tf->device;
+
+       fis[8] = tf->hob_lbal;
+       fis[9] = tf->hob_lbam;
+       fis[10] = tf->hob_lbah;
+       fis[11] = tf->hob_feature;
+
+       fis[12] = tf->nsect;
+       fis[13] = tf->hob_nsect;
+       fis[14] = 0;
+       fis[15] = tf->ctl;
+
+       fis[16] = 0;
+       fis[17] = 0;
+       fis[18] = 0;
+       fis[19] = 0;
+}
+
+/**
+ *     ata_tf_from_fis - Convert SATA FIS to ATA taskfile
+ *     @fis: Buffer from which data will be input
+ *     @tf: Taskfile to output
+ *
+ *     Converts a serial ATA FIS structure to a standard ATA taskfile.
+ *
+ *     LOCKING:
+ *     Inherited from caller.
+ */
+
+void ata_tf_from_fis(const u8 *fis, struct ata_taskfile *tf)
+{
+       tf->command     = fis[2];       /* status */
+       tf->feature     = fis[3];       /* error */
+
+       tf->lbal        = fis[4];
+       tf->lbam        = fis[5];
+       tf->lbah        = fis[6];
+       tf->device      = fis[7];
+
+       tf->hob_lbal    = fis[8];
+       tf->hob_lbam    = fis[9];
+       tf->hob_lbah    = fis[10];
+
+       tf->nsect       = fis[12];
+       tf->hob_nsect   = fis[13];
+}
+
+static const u8 ata_rw_cmds[] = {
+       /* pio multi */
+       ATA_CMD_READ_MULTI,
+       ATA_CMD_WRITE_MULTI,
+       ATA_CMD_READ_MULTI_EXT,
+       ATA_CMD_WRITE_MULTI_EXT,
+       0,
+       0,
+       0,
+       ATA_CMD_WRITE_MULTI_FUA_EXT,
+       /* pio */
+       ATA_CMD_PIO_READ,
+       ATA_CMD_PIO_WRITE,
+       ATA_CMD_PIO_READ_EXT,
+       ATA_CMD_PIO_WRITE_EXT,
+       0,
+       0,
+       0,
+       0,
+       /* dma */
+       ATA_CMD_READ,
+       ATA_CMD_WRITE,
+       ATA_CMD_READ_EXT,
+       ATA_CMD_WRITE_EXT,
+       0,
+       0,
+       0,
+       ATA_CMD_WRITE_FUA_EXT
+};
+
+/**
+ *     ata_rwcmd_protocol - set taskfile r/w commands and protocol
+ *     @qc: command to examine and configure
+ *
+ *     Examine the device configuration and tf->flags to calculate
+ *     the proper read/write commands and protocol to use.
+ *
+ *     LOCKING:
+ *     caller.
+ */
+int ata_rwcmd_protocol(struct ata_queued_cmd *qc)
+{
+       struct ata_taskfile *tf = &qc->tf;
+       struct ata_device *dev = qc->dev;
+       u8 cmd;
+
+       int index, fua, lba48, write;
+
+       fua = (tf->flags & ATA_TFLAG_FUA) ? 4 : 0;
+       lba48 = (tf->flags & ATA_TFLAG_LBA48) ? 2 : 0;
+       write = (tf->flags & ATA_TFLAG_WRITE) ? 1 : 0;
+
+       if (dev->flags & ATA_DFLAG_PIO) {
+               tf->protocol = ATA_PROT_PIO;
+               index = dev->multi_count ? 0 : 8;
+       } else if (lba48 && (qc->ap->flags & ATA_FLAG_PIO_LBA48)) {
+               /* Unable to use DMA due to host limitation */
+               tf->protocol = ATA_PROT_PIO;
+               index = dev->multi_count ? 0 : 8;
+       } else {
+               tf->protocol = ATA_PROT_DMA;
+               index = 16;
+       }
+
+       cmd = ata_rw_cmds[index + fua + lba48 + write];
+       if (cmd) {
+               tf->command = cmd;
+               return 0;
+       }
+       return -1;
+}
+
+/**
+ *     ata_pack_xfermask - Pack pio, mwdma and udma masks into xfer_mask
+ *     @pio_mask: pio_mask
+ *     @mwdma_mask: mwdma_mask
+ *     @udma_mask: udma_mask
+ *
+ *     Pack @pio_mask, @mwdma_mask and @udma_mask into a single
+ *     unsigned int xfer_mask.
+ *
+ *     LOCKING:
+ *     None.
+ *
+ *     RETURNS:
+ *     Packed xfer_mask.
+ */
+static unsigned int ata_pack_xfermask(unsigned int pio_mask,
+                                     unsigned int mwdma_mask,
+                                     unsigned int udma_mask)
+{
+       return ((pio_mask << ATA_SHIFT_PIO) & ATA_MASK_PIO) |
+               ((mwdma_mask << ATA_SHIFT_MWDMA) & ATA_MASK_MWDMA) |
+               ((udma_mask << ATA_SHIFT_UDMA) & ATA_MASK_UDMA);
+}
+
+/**
+ *     ata_unpack_xfermask - Unpack xfer_mask into pio, mwdma and udma masks
+ *     @xfer_mask: xfer_mask to unpack
+ *     @pio_mask: resulting pio_mask
+ *     @mwdma_mask: resulting mwdma_mask
+ *     @udma_mask: resulting udma_mask
+ *
+ *     Unpack @xfer_mask into @pio_mask, @mwdma_mask and @udma_mask.
+ *     Any NULL distination masks will be ignored.
+ */
+static void ata_unpack_xfermask(unsigned int xfer_mask,
+                               unsigned int *pio_mask,
+                               unsigned int *mwdma_mask,
+                               unsigned int *udma_mask)
+{
+       if (pio_mask)
+               *pio_mask = (xfer_mask & ATA_MASK_PIO) >> ATA_SHIFT_PIO;
+       if (mwdma_mask)
+               *mwdma_mask = (xfer_mask & ATA_MASK_MWDMA) >> ATA_SHIFT_MWDMA;
+       if (udma_mask)
+               *udma_mask = (xfer_mask & ATA_MASK_UDMA) >> ATA_SHIFT_UDMA;
+}
+
+static const struct ata_xfer_ent {
+       int shift, bits;
+       u8 base;
+} ata_xfer_tbl[] = {
+       { ATA_SHIFT_PIO, ATA_BITS_PIO, XFER_PIO_0 },
+       { ATA_SHIFT_MWDMA, ATA_BITS_MWDMA, XFER_MW_DMA_0 },
+       { ATA_SHIFT_UDMA, ATA_BITS_UDMA, XFER_UDMA_0 },
+       { -1, },
+};
+
+/**
+ *     ata_xfer_mask2mode - Find matching XFER_* for the given xfer_mask
+ *     @xfer_mask: xfer_mask of interest
+ *
+ *     Return matching XFER_* value for @xfer_mask.  Only the highest
+ *     bit of @xfer_mask is considered.
+ *
+ *     LOCKING:
+ *     None.
+ *
+ *     RETURNS:
+ *     Matching XFER_* value, 0 if no match found.
+ */
+static u8 ata_xfer_mask2mode(unsigned int xfer_mask)
+{
+       int highbit = fls(xfer_mask) - 1;
+       const struct ata_xfer_ent *ent;
+
+       for (ent = ata_xfer_tbl; ent->shift >= 0; ent++)
+               if (highbit >= ent->shift && highbit < ent->shift + ent->bits)
+                       return ent->base + highbit - ent->shift;
+       return 0;
+}
+
+/**
+ *     ata_xfer_mode2mask - Find matching xfer_mask for XFER_*
+ *     @xfer_mode: XFER_* of interest
+ *
+ *     Return matching xfer_mask for @xfer_mode.
+ *
+ *     LOCKING:
+ *     None.
+ *
+ *     RETURNS:
+ *     Matching xfer_mask, 0 if no match found.
+ */
+static unsigned int ata_xfer_mode2mask(u8 xfer_mode)
+{
+       const struct ata_xfer_ent *ent;
+
+       for (ent = ata_xfer_tbl; ent->shift >= 0; ent++)
+               if (xfer_mode >= ent->base && xfer_mode < ent->base + ent->bits)
+                       return 1 << (ent->shift + xfer_mode - ent->base);
+       return 0;
+}
+
+/**
+ *     ata_xfer_mode2shift - Find matching xfer_shift for XFER_*
+ *     @xfer_mode: XFER_* of interest
+ *
+ *     Return matching xfer_shift for @xfer_mode.
+ *
+ *     LOCKING:
+ *     None.
+ *
+ *     RETURNS:
+ *     Matching xfer_shift, -1 if no match found.
+ */
+static int ata_xfer_mode2shift(unsigned int xfer_mode)
+{
+       const struct ata_xfer_ent *ent;
+
+       for (ent = ata_xfer_tbl; ent->shift >= 0; ent++)
+               if (xfer_mode >= ent->base && xfer_mode < ent->base + ent->bits)
+                       return ent->shift;
+       return -1;
+}
+
+/**
+ *     ata_mode_string - convert xfer_mask to string
+ *     @xfer_mask: mask of bits supported; only highest bit counts.
+ *
+ *     Determine string which represents the highest speed
+ *     (highest bit in @modemask).
+ *
+ *     LOCKING:
+ *     None.
+ *
+ *     RETURNS:
+ *     Constant C string representing highest speed listed in
+ *     @mode_mask, or the constant C string "<n/a>".
+ */
+static const char *ata_mode_string(unsigned int xfer_mask)
+{
+       static const char * const xfer_mode_str[] = {
+               "PIO0",
+               "PIO1",
+               "PIO2",
+               "PIO3",
+               "PIO4",
+               "MWDMA0",
+               "MWDMA1",
+               "MWDMA2",
+               "UDMA/16",
+               "UDMA/25",
+               "UDMA/33",
+               "UDMA/44",
+               "UDMA/66",
+               "UDMA/100",
+               "UDMA/133",
+               "UDMA7",
+       };
+       int highbit;
+
+       highbit = fls(xfer_mask) - 1;
+       if (highbit >= 0 && highbit < ARRAY_SIZE(xfer_mode_str))
+               return xfer_mode_str[highbit];
+       return "<n/a>";
+}
+
+static const char *sata_spd_string(unsigned int spd)
+{
+       static const char * const spd_str[] = {
+               "1.5 Gbps",
+               "3.0 Gbps",
+       };
+
+       if (spd == 0 || (spd - 1) >= ARRAY_SIZE(spd_str))
+               return "<unknown>";
+       return spd_str[spd - 1];
+}
+
+void ata_dev_disable(struct ata_device *dev)
+{
+       if (ata_dev_enabled(dev) && ata_msg_drv(dev->ap)) {
+               ata_dev_printk(dev, KERN_WARNING, "disabled\n");
+               dev->class++;
+       }
+}
+
+/**
+ *     ata_pio_devchk - PATA device presence detection
+ *     @ap: ATA channel to examine
+ *     @device: Device to examine (starting at zero)
+ *
+ *     This technique was originally described in
+ *     Hale Landis's ATADRVR (www.ata-atapi.com), and
+ *     later found its way into the ATA/ATAPI spec.
+ *
+ *     Write a pattern to the ATA shadow registers,
+ *     and if a device is present, it will respond by
+ *     correctly storing and echoing back the
+ *     ATA shadow register contents.
+ *
+ *     LOCKING:
+ *     caller.
+ */
+
+static unsigned int ata_pio_devchk(struct ata_port *ap,
+                                  unsigned int device)
+{
+       struct ata_ioports *ioaddr = &ap->ioaddr;
+       u8 nsect, lbal;
+
+       ap->ops->dev_select(ap, device);
+
+       outb(0x55, ioaddr->nsect_addr);
+       outb(0xaa, ioaddr->lbal_addr);
+
+       outb(0xaa, ioaddr->nsect_addr);
+       outb(0x55, ioaddr->lbal_addr);
+
+       outb(0x55, ioaddr->nsect_addr);
+       outb(0xaa, ioaddr->lbal_addr);
+
+       nsect = inb(ioaddr->nsect_addr);
+       lbal = inb(ioaddr->lbal_addr);
+
+       if ((nsect == 0x55) && (lbal == 0xaa))
+               return 1;       /* we found a device */
+
+       return 0;               /* nothing found */
+}
+
+/**
+ *     ata_mmio_devchk - PATA device presence detection
+ *     @ap: ATA channel to examine
+ *     @device: Device to examine (starting at zero)
+ *
+ *     This technique was originally described in
+ *     Hale Landis's ATADRVR (www.ata-atapi.com), and
+ *     later found its way into the ATA/ATAPI spec.
+ *
+ *     Write a pattern to the ATA shadow registers,
+ *     and if a device is present, it will respond by
+ *     correctly storing and echoing back the
+ *     ATA shadow register contents.
+ *
+ *     LOCKING:
+ *     caller.
+ */
+
+static unsigned int ata_mmio_devchk(struct ata_port *ap,
+                                   unsigned int device)
+{
+       struct ata_ioports *ioaddr = &ap->ioaddr;
+       u8 nsect, lbal;
+
+       ap->ops->dev_select(ap, device);
+
+       writeb(0x55, (void __iomem *) ioaddr->nsect_addr);
+       writeb(0xaa, (void __iomem *) ioaddr->lbal_addr);
+
+       writeb(0xaa, (void __iomem *) ioaddr->nsect_addr);
+       writeb(0x55, (void __iomem *) ioaddr->lbal_addr);
+
+       writeb(0x55, (void __iomem *) ioaddr->nsect_addr);
+       writeb(0xaa, (void __iomem *) ioaddr->lbal_addr);
+
+       nsect = readb((void __iomem *) ioaddr->nsect_addr);
+       lbal = readb((void __iomem *) ioaddr->lbal_addr);
+
+       if ((nsect == 0x55) && (lbal == 0xaa))
+               return 1;       /* we found a device */
+
+       return 0;               /* nothing found */
+}
+
+/**
+ *     ata_devchk - PATA device presence detection
+ *     @ap: ATA channel to examine
+ *     @device: Device to examine (starting at zero)
+ *
+ *     Dispatch ATA device presence detection, depending
+ *     on whether we are using PIO or MMIO to talk to the
+ *     ATA shadow registers.
+ *
+ *     LOCKING:
+ *     caller.
+ */
+
+static unsigned int ata_devchk(struct ata_port *ap,
+                                   unsigned int device)
+{
+       if (ap->flags & ATA_FLAG_MMIO)
+               return ata_mmio_devchk(ap, device);
+       return ata_pio_devchk(ap, device);
+}
+
+/**
+ *     ata_dev_classify - determine device type based on ATA-spec signature
+ *     @tf: ATA taskfile register set for device to be identified
+ *
+ *     Determine from taskfile register contents whether a device is
+ *     ATA or ATAPI, as per "Signature and persistence" section
+ *     of ATA/PI spec (volume 1, sect 5.14).
+ *
+ *     LOCKING:
+ *     None.
+ *
+ *     RETURNS:
+ *     Device type, %ATA_DEV_ATA, %ATA_DEV_ATAPI, or %ATA_DEV_UNKNOWN
+ *     the event of failure.
+ */
+
+unsigned int ata_dev_classify(const struct ata_taskfile *tf)
+{
+       /* Apple's open source Darwin code hints that some devices only
+        * put a proper signature into the LBA mid/high registers,
+        * So, we only check those.  It's sufficient for uniqueness.
+        */
+
+       if (((tf->lbam == 0) && (tf->lbah == 0)) ||
+           ((tf->lbam == 0x3c) && (tf->lbah == 0xc3))) {
+               DPRINTK("found ATA device by sig\n");
+               return ATA_DEV_ATA;
+       }
+
+       if (((tf->lbam == 0x14) && (tf->lbah == 0xeb)) ||
+           ((tf->lbam == 0x69) && (tf->lbah == 0x96))) {
+               DPRINTK("found ATAPI device by sig\n");
+               return ATA_DEV_ATAPI;
+       }
+
+       DPRINTK("unknown device\n");
+       return ATA_DEV_UNKNOWN;
+}
+
+/**
+ *     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
+ *     shadow registers, indicating the results of device detection
+ *     and diagnostics.
+ *
+ *     Select the ATA device, and read the values from the ATA shadow
+ *     registers.  Then parse according to the Error register value,
+ *     and the spec-defined values examined by ata_dev_classify().
+ *
+ *     LOCKING:
+ *     caller.
+ *
+ *     RETURNS:
+ *     Device type - %ATA_DEV_ATA, %ATA_DEV_ATAPI or %ATA_DEV_NONE.
+ */
+
+static unsigned int
+ata_dev_try_classify(struct ata_port *ap, unsigned int device, u8 *r_err)
+{
+       struct ata_taskfile tf;
+       unsigned int class;
+       u8 err;
+
+       ap->ops->dev_select(ap, device);
+
+       memset(&tf, 0, sizeof(tf));
+
+       ap->ops->tf_read(ap, &tf);
+       err = tf.feature;
+       if (r_err)
+               *r_err = err;
+
+       /* see if device passed diags */
+       if (err == 1)
+               /* do nothing */ ;
+       else if ((device == 0) && (err == 0x81))
+               /* do nothing */ ;
+       else
+               return ATA_DEV_NONE;
+
+       /* determine if device is ATA or ATAPI */
+       class = ata_dev_classify(&tf);
+
+       if (class == ATA_DEV_UNKNOWN)
+               return ATA_DEV_NONE;
+       if ((class == ATA_DEV_ATA) && (ata_chk_status(ap) == 0))
+               return ATA_DEV_NONE;
+       return class;
+}
+
+/**
+ *     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
+ *     @len: length of string to return. must be an even number.
+ *
+ *     The strings in the IDENTIFY DEVICE page are broken up into
+ *     16-bit chunks.  Run through the string, and output each
+ *     8-bit chunk linearly, regardless of platform.
+ *
+ *     LOCKING:
+ *     caller.
+ */
+
+void ata_id_string(const u16 *id, unsigned char *s,
+                  unsigned int ofs, unsigned int len)
+{
+       unsigned int c;
+
+       while (len > 0) {
+               c = id[ofs] >> 8;
+               *s = c;
+               s++;
+
+               c = id[ofs] & 0xff;
+               *s = c;
+               s++;
+
+               ofs++;
+               len -= 2;
+       }
+}
+
+/**
+ *     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
+ *     @ap: ATA channel to manipulate
+ *     @device: ATA device (numbered from zero) to select
+ *
+ *     This function performs no actual function.
+ *
+ *     May be used as the dev_select() entry in ata_port_operations.
+ *
+ *     LOCKING:
+ *     caller.
+ */
+void ata_noop_dev_select (struct ata_port *ap, unsigned int device)
+{
+}
+
+
+/**
+ *     ata_std_dev_select - Select device 0/1 on ATA bus
+ *     @ap: ATA channel to manipulate
+ *     @device: ATA device (numbered from zero) to select
+ *
+ *     Use the method defined in the ATA specification to
+ *     make either device 0, or device 1, active on the
+ *     ATA channel.  Works with both PIO and MMIO.
+ *
+ *     May be used as the dev_select() entry in ata_port_operations.
+ *
+ *     LOCKING:
+ *     caller.
+ */
+
+void ata_std_dev_select (struct ata_port *ap, unsigned int device)
+{
+       u8 tmp;
+
+       if (device == 0)
+               tmp = ATA_DEVICE_OBS;
+       else
+               tmp = ATA_DEVICE_OBS | ATA_DEV1;
+
+       if (ap->flags & ATA_FLAG_MMIO) {
+               writeb(tmp, (void __iomem *) ap->ioaddr.device_addr);
+       } else {
+               outb(tmp, ap->ioaddr.device_addr);
+       }
+       ata_pause(ap);          /* needed; also flushes, for mmio */
+}
+
+/**
+ *     ata_dev_select - Select device 0/1 on ATA bus
+ *     @ap: ATA channel to manipulate
+ *     @device: ATA device (numbered from zero) to select
+ *     @wait: non-zero to wait for Status register BSY bit to clear
+ *     @can_sleep: non-zero if context allows sleeping
+ *
+ *     Use the method defined in the ATA specification to
+ *     make either device 0, or device 1, active on the
+ *     ATA channel.
+ *
+ *     This is a high-level version of ata_std_dev_select(),
+ *     which additionally provides the services of inserting
+ *     the proper pauses and status polling, where needed.
+ *
+ *     LOCKING:
+ *     caller.
+ */
+
+void ata_dev_select(struct ata_port *ap, unsigned int device,
+                          unsigned int wait, unsigned int can_sleep)
+{
+       if (ata_msg_probe(ap))
+               ata_port_printk(ap, KERN_INFO, "ata_dev_select: ENTER, ata%u: "
+                               "device %u, wait %u\n", ap->id, device, wait);
+
+       if (wait)
+               ata_wait_idle(ap);
+
+       ap->ops->dev_select(ap, device);
+
+       if (wait) {
+               if (can_sleep && ap->device[device].class == ATA_DEV_ATAPI)
+                       msleep(150);
+               ata_wait_idle(ap);
+       }
+}
+
+/**
+ *     ata_dump_id - IDENTIFY DEVICE info debugging output
+ *     @id: IDENTIFY DEVICE page to dump
+ *
+ *     Dump selected 16-bit words from the given IDENTIFY DEVICE
+ *     page.
+ *
+ *     LOCKING:
+ *     caller.
+ */
+
+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",
+               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",
+               id[80],
+               id[81],
+               id[82],
+               id[83],
+               id[84]);
+       DPRINTK("88==0x%04x  "
+               "93==0x%04x\n",
+               id[88],
+               id[93]);
+}
+
+/**
+ *     ata_id_xfermask - Compute xfermask from the given IDENTIFY data
+ *     @id: IDENTIFY data to compute xfer mask from
+ *
+ *     Compute the xfermask for this device. This is not as trivial
+ *     as it seems if we must consider early devices correctly.
+ *
+ *     FIXME: pre IDE drive timing (do we care ?).
+ *
+ *     LOCKING:
+ *     None.
+ *
+ *     RETURNS:
+ *     Computed xfermask
+ */
+static unsigned int ata_id_xfermask(const u16 *id)
+{
+       unsigned int pio_mask, mwdma_mask, udma_mask;
+
+       /* Usual case. Word 53 indicates word 64 is valid */
+       if (id[ATA_ID_FIELD_VALID] & (1 << 1)) {
+               pio_mask = id[ATA_ID_PIO_MODES] & 0x03;
+               pio_mask <<= 3;
+               pio_mask |= 0x7;
+       } else {
+               /* If word 64 isn't valid then Word 51 high byte holds
+                * the PIO timing number for the maximum. Turn it into
+                * a mask.
+                */
+               pio_mask = (2 << (id[ATA_ID_OLD_PIO_MODES] & 0xFF)) - 1 ;
+
+               /* But wait.. there's more. Design your standards by
+                * committee and you too can get a free iordy field to
+                * process. However its the speeds not the modes that
+                * are supported... Note drivers using the timing API
+                * will get this right anyway
+                */
+       }
+
+       mwdma_mask = id[ATA_ID_MWDMA_MODES] & 0x07;
+
+       udma_mask = 0;
+       if (id[ATA_ID_FIELD_VALID] & (1 << 2))
+               udma_mask = id[ATA_ID_UDMA_MODES] & 0xff;
+
+       return ata_pack_xfermask(pio_mask, mwdma_mask, udma_mask);
+}
+
+/**
+ *     ata_port_queue_task - Queue port_task
+ *     @ap: The ata_port to queue port_task for
+ *     @fn: workqueue function to be scheduled
+ *     @data: data value to pass to workqueue function
+ *     @delay: delay time for workqueue function
+ *
+ *     Schedule @fn(@data) for execution after @delay jiffies using
+ *     port_task.  There is one port_task per port and it's the
+ *     user(low level driver)'s responsibility to make sure that only
+ *     one task is active at any given time.
+ *
+ *     libata core layer takes care of synchronization between
+ *     port_task and EH.  ata_port_queue_task() may be ignored for EH
+ *     synchronization.
+ *
+ *     LOCKING:
+ *     Inherited from caller.
+ */
+void ata_port_queue_task(struct ata_port *ap, void (*fn)(void *), void *data,
+                        unsigned long delay)
+{
+       int rc;
+
+       if (ap->pflags & ATA_PFLAG_FLUSH_PORT_TASK)
+               return;
+
+       PREPARE_WORK(&ap->port_task, fn, data);
+
+       if (!delay)
+               rc = queue_work(ata_wq, &ap->port_task);
+       else
+               rc = queue_delayed_work(ata_wq, &ap->port_task, delay);
+
+       /* rc == 0 means that another user is using port task */
+       WARN_ON(rc == 0);
+}
+
+/**
+ *     ata_port_flush_task - Flush port_task
+ *     @ap: The ata_port to flush port_task for
+ *
+ *     After this function completes, port_task is guranteed not to
+ *     be running or scheduled.
+ *
+ *     LOCKING:
+ *     Kernel thread context (may sleep)
+ */
+void ata_port_flush_task(struct ata_port *ap)
+{
+       unsigned long flags;
+
+       DPRINTK("ENTER\n");
+
+       spin_lock_irqsave(ap->lock, flags);
+       ap->pflags |= ATA_PFLAG_FLUSH_PORT_TASK;
+       spin_unlock_irqrestore(ap->lock, flags);
+
+       DPRINTK("flush #1\n");
+       flush_workqueue(ata_wq);
+
+       /*
+        * At this point, if a task is running, it's guaranteed to see
+        * the FLUSH flag; thus, it will never queue pio tasks again.
+        * Cancel and flush.
+        */
+       if (!cancel_delayed_work(&ap->port_task)) {
+               if (ata_msg_ctl(ap))
+                       ata_port_printk(ap, KERN_DEBUG, "%s: flush #2\n",
+                                       __FUNCTION__);
+               flush_workqueue(ata_wq);
+       }
+
+       spin_lock_irqsave(ap->lock, flags);
+       ap->pflags &= ~ATA_PFLAG_FLUSH_PORT_TASK;
+       spin_unlock_irqrestore(ap->lock, flags);
+
+       if (ata_msg_ctl(ap))
+               ata_port_printk(ap, KERN_DEBUG, "%s: EXIT\n", __FUNCTION__);
+}
+
+void ata_qc_complete_internal(struct ata_queued_cmd *qc)
+{
+       struct completion *waiting = qc->private_data;
+
+       complete(waiting);
+}
+
+/**
+ *     ata_exec_internal - execute libata internal command
+ *     @dev: Device to which the command is sent
+ *     @tf: Taskfile registers for the command and the result
+ *     @cdb: CDB for packet command
+ *     @dma_dir: Data tranfer direction of the command
+ *     @buf: Data buffer of the command
+ *     @buflen: Length of data buffer
+ *
+ *     Executes libata internal command with timeout.  @tf contains
+ *     command on entry and result on return.  Timeout and error
+ *     conditions are reported via return value.  No recovery action
+ *     is taken after a command times out.  It's caller's duty to
+ *     clean up after timeout.
+ *
+ *     LOCKING:
+ *     None.  Should be called with kernel context, might sleep.
+ *
+ *     RETURNS:
+ *     Zero on success, AC_ERR_* mask on failure
+ */
+unsigned ata_exec_internal(struct ata_device *dev,
+                          struct ata_taskfile *tf, const u8 *cdb,
+                          int dma_dir, void *buf, unsigned int buflen)
+{
+       struct ata_port *ap = dev->ap;
+       u8 command = tf->command;
+       struct ata_queued_cmd *qc;
+       unsigned int tag, preempted_tag;
+       u32 preempted_sactive, preempted_qc_active;
+       DECLARE_COMPLETION_ONSTACK(wait);
+       unsigned long flags;
+       unsigned int err_mask;
+       int rc;
+
+       spin_lock_irqsave(ap->lock, flags);
+
+       /* no internal command while frozen */
+       if (ap->pflags & ATA_PFLAG_FROZEN) {
+               spin_unlock_irqrestore(ap->lock, flags);
+               return AC_ERR_SYSTEM;
+       }
+
+       /* initialize internal qc */
+
+       /* XXX: Tag 0 is used for drivers with legacy EH as some
+        * drivers choke if any other tag is given.  This breaks
+        * ata_tag_internal() test for those drivers.  Don't use new
+        * EH stuff without converting to it.
+        */
+       if (ap->ops->error_handler)
+               tag = ATA_TAG_INTERNAL;
+       else
+               tag = 0;
+
+       if (test_and_set_bit(tag, &ap->qc_allocated))
+               BUG();
+       qc = __ata_qc_from_tag(ap, tag);
+
+       qc->tag = tag;
+       qc->scsicmd = NULL;
+       qc->ap = ap;
+       qc->dev = dev;
+       ata_qc_reinit(qc);
+
+       preempted_tag = ap->active_tag;
+       preempted_sactive = ap->sactive;
+       preempted_qc_active = ap->qc_active;
+       ap->active_tag = ATA_TAG_POISON;
+       ap->sactive = 0;
+       ap->qc_active = 0;
+
+       /* prepare & issue qc */
+       qc->tf = *tf;
+       if (cdb)
+               memcpy(qc->cdb, cdb, ATAPI_CDB_LEN);
+       qc->flags |= ATA_QCFLAG_RESULT_TF;
+       qc->dma_dir = dma_dir;
+       if (dma_dir != DMA_NONE) {
+               ata_sg_init_one(qc, buf, buflen);
+               qc->nsect = buflen / ATA_SECT_SIZE;
+       }
+
+       qc->private_data = &wait;
+       qc->complete_fn = ata_qc_complete_internal;
+
+       ata_qc_issue(qc);
+
+       spin_unlock_irqrestore(ap->lock, flags);
+
+       rc = wait_for_completion_timeout(&wait, ata_probe_timeout);
+
+       ata_port_flush_task(ap);
+
+       if (!rc) {
+               spin_lock_irqsave(ap->lock, flags);
+
+               /* We're racing with irq here.  If we lose, the
+                * following test prevents us from completing the qc
+                * twice.  If we win, the port is frozen and will be
+                * cleaned up by ->post_internal_cmd().
+                */
+               if (qc->flags & ATA_QCFLAG_ACTIVE) {
+                       qc->err_mask |= AC_ERR_TIMEOUT;
+
+                       if (ap->ops->error_handler)
+                               ata_port_freeze(ap);
+                       else
+                               ata_qc_complete(qc);
+
+                       if (ata_msg_warn(ap))
+                               ata_dev_printk(dev, KERN_WARNING,
+                                       "qc timeout (cmd 0x%x)\n", command);
+               }
+
+               spin_unlock_irqrestore(ap->lock, flags);
+       }
+
+       /* do post_internal_cmd */
+       if (ap->ops->post_internal_cmd)
+               ap->ops->post_internal_cmd(qc);
+
+       if (qc->flags & ATA_QCFLAG_FAILED && !qc->err_mask) {
+               if (ata_msg_warn(ap))
+                       ata_dev_printk(dev, KERN_WARNING,
+                               "zero err_mask for failed "
+                               "internal command, assuming AC_ERR_OTHER\n");
+               qc->err_mask |= AC_ERR_OTHER;
+       }
+
+       /* finish up */
+       spin_lock_irqsave(ap->lock, flags);
+
+       *tf = qc->result_tf;
+       err_mask = qc->err_mask;
+
+       ata_qc_free(qc);
+       ap->active_tag = preempted_tag;
+       ap->sactive = preempted_sactive;
+       ap->qc_active = preempted_qc_active;
+
+       /* XXX - Some LLDDs (sata_mv) disable port on command failure.
+        * Until those drivers are fixed, we detect the condition
+        * here, fail the command with AC_ERR_SYSTEM and reenable the
+        * port.
+        *
+        * Note that this doesn't change any behavior as internal
+        * command failure results in disabling the device in the
+        * higher layer for LLDDs without new reset/EH callbacks.
+        *
+        * Kill the following code as soon as those drivers are fixed.
+        */
+       if (ap->flags & ATA_FLAG_DISABLED) {
+               err_mask |= AC_ERR_SYSTEM;
+               ata_port_probe(ap);
+       }
+
+       spin_unlock_irqrestore(ap->lock, flags);
+
+       return err_mask;
+}
+
+/**
+ *     ata_do_simple_cmd - execute simple internal command
+ *     @dev: Device to which the command is sent
+ *     @cmd: Opcode to execute
+ *
+ *     Execute a 'simple' command, that only consists of the opcode
+ *     'cmd' itself, without filling any other registers
+ *
+ *     LOCKING:
+ *     Kernel thread context (may sleep).
+ *
+ *     RETURNS:
+ *     Zero on success, AC_ERR_* mask on failure
+ */
+unsigned int ata_do_simple_cmd(struct ata_device *dev, u8 cmd)
+{
+       struct ata_taskfile tf;
+
+       ata_tf_init(dev, &tf);
+
+       tf.command = cmd;
+       tf.flags |= ATA_TFLAG_DEVICE;
+       tf.protocol = ATA_PROT_NODATA;
+
+       return ata_exec_internal(dev, &tf, NULL, DMA_NONE, NULL, 0);
+}
+
+/**
+ *     ata_pio_need_iordy      -       check if iordy needed
+ *     @adev: ATA device
+ *
+ *     Check if the current speed of the device requires IORDY. Used
+ *     by various controllers for chip configuration.
+ */
+
+unsigned int ata_pio_need_iordy(const struct ata_device *adev)
+{
+       int pio;
+       int speed = adev->pio_mode - XFER_PIO_0;
+
+       if (speed < 2)
+               return 0;
+       if (speed > 2)
+               return 1;
+
+       /* If we have no drive specific rule, then PIO 2 is non IORDY */
+
+       if (adev->id[ATA_ID_FIELD_VALID] & 2) { /* EIDE */
+               pio = adev->id[ATA_ID_EIDE_PIO];
+               /* Is the speed faster than the drive allows non IORDY ? */
+               if (pio) {
+                       /* This is cycle times not frequency - watch the logic! */
+                       if (pio > 240)  /* PIO2 is 240nS per cycle */
+                               return 1;
+                       return 0;
+               }
+       }
+       return 0;
+}
+
+/**
+ *     ata_dev_read_id - Read ID data from the specified device
+ *     @dev: target device
+ *     @p_class: pointer to class of the target device (may be changed)
+ *     @post_reset: is this read ID post-reset?
+ *     @id: buffer to read IDENTIFY data into
+ *
+ *     Read ID data from the specified device.  ATA_CMD_ID_ATA is
+ *     performed on ATA devices and ATA_CMD_ID_ATAPI on ATAPI
+ *     devices.  This function also issues ATA_CMD_INIT_DEV_PARAMS
+ *     for pre-ATA4 drives.
+ *
+ *     LOCKING:
+ *     Kernel thread context (may sleep)
+ *
+ *     RETURNS:
+ *     0 on success, -errno otherwise.
+ */
+int ata_dev_read_id(struct ata_device *dev, unsigned int *p_class,
+                   int post_reset, u16 *id)
+{
+       struct ata_port *ap = dev->ap;
+       unsigned int class = *p_class;
+       struct ata_taskfile tf;
+       unsigned int err_mask = 0;
+       const char *reason;
+       int rc;
+
+       if (ata_msg_ctl(ap))
+               ata_dev_printk(dev, KERN_DEBUG, "%s: ENTER, host %u, dev %u\n",
+                              __FUNCTION__, ap->id, dev->devno);
+
+       ata_dev_select(ap, dev->devno, 1, 1); /* select device 0/1 */
+
+ retry:
+       ata_tf_init(dev, &tf);
+
+       switch (class) {
+       case ATA_DEV_ATA:
+               tf.command = ATA_CMD_ID_ATA;
+               break;
+       case ATA_DEV_ATAPI:
+               tf.command = ATA_CMD_ID_ATAPI;
+               break;
+       default:
+               rc = -ENODEV;
+               reason = "unsupported class";
+               goto err_out;
+       }
+
+       tf.protocol = ATA_PROT_PIO;
+
+       err_mask = ata_exec_internal(dev, &tf, NULL, DMA_FROM_DEVICE,
+                                    id, sizeof(id[0]) * ATA_ID_WORDS);
+       if (err_mask) {
+               rc = -EIO;
+               reason = "I/O error";
+               goto err_out;
+       }
+
+       swap_buf_le16(id, ATA_ID_WORDS);
+
+       /* sanity check */
+       if ((class == ATA_DEV_ATA) != (ata_id_is_ata(id) | ata_id_is_cfa(id))) {
+               rc = -EINVAL;
+               reason = "device reports illegal type";
+               goto err_out;
+       }
+
+       if (post_reset && class == ATA_DEV_ATA) {
+               /*
+                * The exact sequence expected by certain pre-ATA4 drives is:
+                * SRST RESET
+                * IDENTIFY
+                * INITIALIZE DEVICE PARAMETERS
+                * anything else..
+                * Some drives were very specific about that exact sequence.
+                */
+               if (ata_id_major_version(id) < 4 || !ata_id_has_lba(id)) {
+                       err_mask = ata_dev_init_params(dev, id[3], id[6]);
+                       if (err_mask) {
+                               rc = -EIO;
+                               reason = "INIT_DEV_PARAMS failed";
+                               goto err_out;
+                       }
+
+                       /* current CHS translation info (id[53-58]) might be
+                        * changed. reread the identify device info.
+                        */
+                       post_reset = 0;
+                       goto retry;
+               }
+       }
+
+       *p_class = class;
+
+       return 0;
+
+ err_out:
+       if (ata_msg_warn(ap))
+               ata_dev_printk(dev, KERN_WARNING, "failed to IDENTIFY "
+                              "(%s, err_mask=0x%x)\n", reason, err_mask);
+       return rc;
+}
+
+static inline u8 ata_dev_knobble(struct ata_device *dev)
+{
+       return ((dev->ap->cbl == ATA_CBL_SATA) && (!ata_id_is_sata(dev->id)));
+}
+
+static void ata_dev_config_ncq(struct ata_device *dev,
+                              char *desc, size_t desc_sz)
+{
+       struct ata_port *ap = dev->ap;
+       int hdepth = 0, ddepth = ata_id_queue_depth(dev->id);
+
+       if (!ata_id_has_ncq(dev->id)) {
+               desc[0] = '\0';
+               return;
+       }
+
+       if (ap->flags & ATA_FLAG_NCQ) {
+               hdepth = min(ap->host->can_queue, ATA_MAX_QUEUE - 1);
+               dev->flags |= ATA_DFLAG_NCQ;
+       }
+
+       if (hdepth >= ddepth)
+               snprintf(desc, desc_sz, "NCQ (depth %d)", ddepth);
+       else
+               snprintf(desc, desc_sz, "NCQ (depth %d/%d)", hdepth, ddepth);
+}
+
+static void ata_set_port_max_cmd_len(struct ata_port *ap)
+{
+       int i;
+
+       if (ap->host) {
+               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);
+       }
+}
+
+/**
+ *     ata_dev_configure - Configure the specified ATA/ATAPI device
+ *     @dev: Target device to configure
+ *     @print_info: Enable device info printout
+ *
+ *     Configure @dev according to @dev->id.  Generic and low-level
+ *     driver specific fixups are also applied.
+ *
+ *     LOCKING:
+ *     Kernel thread context (may sleep)
+ *
+ *     RETURNS:
+ *     0 on success, -errno otherwise
+ */
+int ata_dev_configure(struct ata_device *dev, int print_info)
+{
+       struct ata_port *ap = dev->ap;
+       const u16 *id = dev->id;
+       unsigned int xfer_mask;
+       int rc;
+
+       if (!ata_dev_enabled(dev) && ata_msg_info(ap)) {
+               ata_dev_printk(dev, KERN_INFO,
+                              "%s: ENTER/EXIT (host %u, dev %u) -- nodev\n",
+                              __FUNCTION__, ap->id, dev->devno);
+               return 0;
+       }
+
+       if (ata_msg_probe(ap))
+               ata_dev_printk(dev, KERN_DEBUG, "%s: ENTER, host %u, dev %u\n",
+                              __FUNCTION__, ap->id, dev->devno);
+
+       /* print device capabilities */
+       if (ata_msg_probe(ap))
+               ata_dev_printk(dev, KERN_DEBUG,
+                              "%s: cfg 49:%04x 82:%04x 83:%04x 84:%04x "
+                              "85:%04x 86:%04x 87:%04x 88:%04x\n",
+                              __FUNCTION__,
+                              id[49], id[82], id[83], id[84],
+                              id[85], id[86], id[87], id[88]);
+
+       /* initialize to-be-configured parameters */
+       dev->flags &= ~ATA_DFLAG_CFG_MASK;
+       dev->max_sectors = 0;
+       dev->cdb_len = 0;
+       dev->n_sectors = 0;
+       dev->cylinders = 0;
+       dev->heads = 0;
+       dev->sectors = 0;
+
+       /*
+        * common ATA, ATAPI feature tests
+        */
+
+       /* find max transfer mode; for printk only */
+       xfer_mask = ata_id_xfermask(id);
+
+       if (ata_msg_probe(ap))
+               ata_dump_id(id);
+
+       /* ATA-specific feature tests */
+       if (dev->class == ATA_DEV_ATA) {
+               dev->n_sectors = ata_id_n_sectors(id);
+
+               if (ata_id_has_lba(id)) {
+                       const char *lba_desc;
+                       char ncq_desc[20];
+
+                       lba_desc = "LBA";
+                       dev->flags |= ATA_DFLAG_LBA;
+                       if (ata_id_has_lba48(id)) {
+                               dev->flags |= ATA_DFLAG_LBA48;
+                               lba_desc = "LBA48";
+                       }
+
+                       /* config NCQ */
+                       ata_dev_config_ncq(dev, ncq_desc, sizeof(ncq_desc));
+
+                       /* print device info to dmesg */
+                       if (ata_msg_drv(ap) && print_info)
+                               ata_dev_printk(dev, KERN_INFO, "ATA-%d, "
+                                       "max %s, %Lu sectors: %s %s\n",
+                                       ata_id_major_version(id),
+                                       ata_mode_string(xfer_mask),
+                                       (unsigned long long)dev->n_sectors,
+                                       lba_desc, ncq_desc);
+               } else {
+                       /* CHS */
+
+                       /* Default translation */
+                       dev->cylinders  = id[1];
+                       dev->heads      = id[3];
+                       dev->sectors    = id[6];
+
+                       if (ata_id_current_chs_valid(id)) {
+                               /* Current CHS translation is valid. */
+                               dev->cylinders = id[54];
+                               dev->heads     = id[55];
+                               dev->sectors   = id[56];
+                       }
+
+                       /* print device info to dmesg */
+                       if (ata_msg_drv(ap) && print_info)
+                               ata_dev_printk(dev, KERN_INFO, "ATA-%d, "
+                                       "max %s, %Lu sectors: CHS %u/%u/%u\n",
+                                       ata_id_major_version(id),
+                                       ata_mode_string(xfer_mask),
+                                       (unsigned long long)dev->n_sectors,
+                                       dev->cylinders, dev->heads,
+                                       dev->sectors);
+               }
+
+               if (dev->id[59] & 0x100) {
+                       dev->multi_count = dev->id[59] & 0xff;
+                       if (ata_msg_drv(ap) && print_info)
+                               ata_dev_printk(dev, KERN_INFO,
+                                       "ata%u: dev %u multi count %u\n",
+                                       ap->id, dev->devno, dev->multi_count);
+               }
+
+               dev->cdb_len = 16;
+       }
+
+       /* ATAPI-specific feature tests */
+       else if (dev->class == ATA_DEV_ATAPI) {
+               char *cdb_intr_string = "";
+
+               rc = atapi_cdb_len(id);
+               if ((rc < 12) || (rc > ATAPI_CDB_LEN)) {
+                       if (ata_msg_warn(ap))
+                               ata_dev_printk(dev, KERN_WARNING,
+                                              "unsupported CDB len\n");
+                       rc = -EINVAL;
+                       goto err_out_nosup;
+               }
+               dev->cdb_len = (unsigned int) rc;
+
+               if (ata_id_cdb_intr(dev->id)) {
+                       dev->flags |= ATA_DFLAG_CDB_INTR;
+                       cdb_intr_string = ", CDB intr";
+               }
+
+               /* print device info to dmesg */
+               if (ata_msg_drv(ap) && print_info)
+                       ata_dev_printk(dev, KERN_INFO, "ATAPI, max %s%s\n",
+                                      ata_mode_string(xfer_mask),
+                                      cdb_intr_string);
+       }
+
+       ata_set_port_max_cmd_len(ap);
+
+       /* limit bridge transfers to udma5, 200 sectors */
+       if (ata_dev_knobble(dev)) {
+               if (ata_msg_drv(ap) && print_info)
+                       ata_dev_printk(dev, KERN_INFO,
+                                      "applying bridge limits\n");
+               dev->udma_mask &= ATA_UDMA5;
+               dev->max_sectors = ATA_MAX_SECTORS;
+       }
+
+       if (ap->ops->dev_config)
+               ap->ops->dev_config(ap, dev);
+
+       if (ata_msg_probe(ap))
+               ata_dev_printk(dev, KERN_DEBUG, "%s: EXIT, drv_stat = 0x%x\n",
+                       __FUNCTION__, ata_chk_status(ap));
+       return 0;
+
+err_out_nosup:
+       if (ata_msg_probe(ap))
+               ata_dev_printk(dev, KERN_DEBUG,
+                              "%s: EXIT, err\n", __FUNCTION__);
+       return rc;
+}
+
+/**
+ *     ata_bus_probe - Reset and probe ATA bus
+ *     @ap: Bus to probe
+ *
+ *     Master ATA bus probing function.  Initiates a hardware-dependent
+ *     bus reset, then attempts to identify any devices found on
+ *     the bus.
+ *
+ *     LOCKING:
+ *     PCI/etc. bus probe sem.
+ *
+ *     RETURNS:
+ *     Zero on success, negative errno otherwise.
+ */
+
+int ata_bus_probe(struct ata_port *ap)
+{
+       unsigned int classes[ATA_MAX_DEVICES];
+       int tries[ATA_MAX_DEVICES];
+       int i, rc, down_xfermask;
+       struct ata_device *dev;
+
+       ata_port_probe(ap);
+
+       for (i = 0; i < ATA_MAX_DEVICES; i++)
+               tries[i] = ATA_PROBE_MAX_TRIES;
+
+ retry:
+       down_xfermask = 0;
+
+       /* reset and determine device classes */
+       ap->ops->phy_reset(ap);
+
+       for (i = 0; i < ATA_MAX_DEVICES; i++) {
+               dev = &ap->device[i];
+
+               if (!(ap->flags & ATA_FLAG_DISABLED) &&
+                   dev->class != ATA_DEV_UNKNOWN)
+                       classes[dev->devno] = dev->class;
+               else
+                       classes[dev->devno] = ATA_DEV_NONE;
+
+               dev->class = ATA_DEV_UNKNOWN;
+       }
+
+       ata_port_probe(ap);
+
+       /* after the reset the device state is PIO 0 and the controller
+          state is undefined. Record the mode */
+
+       for (i = 0; i < ATA_MAX_DEVICES; i++)
+               ap->device[i].pio_mode = XFER_PIO_0;
+
+       /* read IDENTIFY page and configure devices */
+       for (i = 0; i < ATA_MAX_DEVICES; i++) {
+               dev = &ap->device[i];
+
+               if (tries[i])
+                       dev->class = classes[i];
+
+               if (!ata_dev_enabled(dev))
+                       continue;
+
+               rc = ata_dev_read_id(dev, &dev->class, 1, dev->id);
+               if (rc)
+                       goto fail;
+
+               rc = ata_dev_configure(dev, 1);
+               if (rc)
+                       goto fail;
+       }
+
+       /* configure transfer mode */
+       rc = ata_set_mode(ap, &dev);
+       if (rc) {
+               down_xfermask = 1;
+               goto fail;
+       }
+
+       for (i = 0; i < ATA_MAX_DEVICES; i++)
+               if (ata_dev_enabled(&ap->device[i]))
+                       return 0;
+
+       /* no device present, disable port */
+       ata_port_disable(ap);
+       ap->ops->port_disable(ap);
+       return -ENODEV;
+
+ fail:
+       switch (rc) {
+       case -EINVAL:
+       case -ENODEV:
+               tries[dev->devno] = 0;
+               break;
+       case -EIO:
+               sata_down_spd_limit(ap);
+               /* fall through */
+       default:
+               tries[dev->devno]--;
+               if (down_xfermask &&
+                   ata_down_xfermask_limit(dev, tries[dev->devno] == 1))
+                       tries[dev->devno] = 0;
+       }
+
+       if (!tries[dev->devno]) {
+               ata_down_xfermask_limit(dev, 1);
+               ata_dev_disable(dev);
+       }
+
+       goto retry;
+}
+
+/**
+ *     ata_port_probe - Mark port as enabled
+ *     @ap: Port for which we indicate enablement
+ *
+ *     Modify @ap data structure such that the system
+ *     thinks that the entire port is enabled.
+ *
+ *     LOCKING: host_set lock, or some other form of
+ *     serialization.
+ */
+
+void ata_port_probe(struct ata_port *ap)
+{
+       ap->flags &= ~ATA_FLAG_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, scontrol, tmp;
+
+       if (sata_scr_read(ap, SCR_STATUS, &sstatus))
+               return;
+       sata_scr_read(ap, SCR_CONTROL, &scontrol);
+
+       if (ata_port_online(ap)) {
+               tmp = (sstatus >> 4) & 0xf;
+               ata_port_printk(ap, KERN_INFO,
+                               "SATA link up %s (SStatus %X SControl %X)\n",
+                               sata_spd_string(tmp), sstatus, scontrol);
+       } else {
+               ata_port_printk(ap, KERN_INFO,
+                               "SATA link down (SStatus %X SControl %X)\n",
+                               sstatus, scontrol);
+       }
+}
+
+/**
+ *     __sata_phy_reset - Wake/reset a low-level SATA PHY
+ *     @ap: SATA port associated with target SATA PHY.
+ *
+ *     This function issues commands to standard SATA Sxxx
+ *     PHY registers, to wake up the phy (and device), and
+ *     clear any reset condition.
+ *
+ *     LOCKING:
+ *     PCI/etc. bus probe sem.
+ *
+ */
+void __sata_phy_reset(struct ata_port *ap)
+{
+       u32 sstatus;
+       unsigned long timeout = jiffies + (HZ * 5);
+
+       if (ap->flags & ATA_FLAG_SATA_RESET) {
+               /* issue phy wake/reset */
+               sata_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. */
+               mdelay(1);
+       }
+       /* phy wake/clear reset */
+       sata_scr_write_flush(ap, SCR_CONTROL, 0x300);
+
+       /* wait for phy to become ready, if necessary */
+       do {
+               msleep(200);
+               sata_scr_read(ap, SCR_STATUS, &sstatus);
+               if ((sstatus & 0xf) != 1)
+                       break;
+       } while (time_before(jiffies, timeout));
+
+       /* print link status */
+       sata_print_link_status(ap);
+
+       /* TODO: phy layer with polling, timeouts, etc. */
+       if (!ata_port_offline(ap))
+               ata_port_probe(ap);
+       else
+               ata_port_disable(ap);
+
+       if (ap->flags & ATA_FLAG_DISABLED)
+               return;
+
+       if (ata_busy_sleep(ap, ATA_TMOUT_BOOT_QUICK, ATA_TMOUT_BOOT)) {
+               ata_port_disable(ap);
+               return;
+       }
+
+       ap->cbl = ATA_CBL_SATA;
+}
+
+/**
+ *     sata_phy_reset - Reset SATA bus.
+ *     @ap: SATA port associated with target SATA PHY.
+ *
+ *     This function resets the SATA bus, and then probes
+ *     the bus for devices.
+ *
+ *     LOCKING:
+ *     PCI/etc. bus probe sem.
+ *
+ */
+void sata_phy_reset(struct ata_port *ap)
+{
+       __sata_phy_reset(ap);
+       if (ap->flags & ATA_FLAG_DISABLED)
+               return;
+       ata_bus_reset(ap);
+}
+
+/**
+ *     ata_dev_pair            -       return other device on cable
+ *     @adev: device
+ *
+ *     Obtain the other device on the same cable, or if none is
+ *     present NULL is returned
+ */
+
+struct ata_device *ata_dev_pair(struct ata_device *adev)
+{
+       struct ata_port *ap = adev->ap;
+       struct ata_device *pair = &ap->device[1 - adev->devno];
+       if (!ata_dev_enabled(pair))
+               return NULL;
+       return pair;
+}
+
+/**
+ *     ata_port_disable - Disable port.
+ *     @ap: Port to be disabled.
+ *
+ *     Modify @ap data structure such that the system
+ *     thinks that the entire port is disabled, and should
+ *     never attempt to probe or communicate with devices
+ *     on this port.
+ *
+ *     LOCKING: host_set lock, or some other form of
+ *     serialization.
+ */
+
+void ata_port_disable(struct ata_port *ap)
+{
+       ap->device[0].class = ATA_DEV_NONE;
+       ap->device[1].class = ATA_DEV_NONE;
+       ap->flags |= ATA_FLAG_DISABLED;
+}
+
+/**
+ *     sata_down_spd_limit - adjust SATA spd limit downward
+ *     @ap: Port to adjust SATA spd limit for
+ *
+ *     Adjust SATA spd limit of @ap downward.  Note that this
+ *     function only adjusts the limit.  The change must be applied
+ *     using sata_set_spd().
+ *
+ *     LOCKING:
+ *     Inherited from caller.
+ *
+ *     RETURNS:
+ *     0 on success, negative errno on failure
+ */
+int sata_down_spd_limit(struct ata_port *ap)
+{
+       u32 sstatus, spd, mask;
+       int rc, highbit;
+
+       rc = sata_scr_read(ap, SCR_STATUS, &sstatus);
+       if (rc)
+               return rc;
+
+       mask = ap->sata_spd_limit;
+       if (mask <= 1)
+               return -EINVAL;
+       highbit = fls(mask) - 1;
+       mask &= ~(1 << highbit);
+
+       spd = (sstatus >> 4) & 0xf;
+       if (spd <= 1)
+               return -EINVAL;
+       spd--;
+       mask &= (1 << spd) - 1;
+       if (!mask)
+               return -EINVAL;
+
+       ap->sata_spd_limit = mask;
+
+       ata_port_printk(ap, KERN_WARNING, "limiting SATA link speed to %s\n",
+                       sata_spd_string(fls(mask)));
+
+       return 0;
+}
+
+static int __sata_set_spd_needed(struct ata_port *ap, u32 *scontrol)
+{
+       u32 spd, limit;
+
+       if (ap->sata_spd_limit == UINT_MAX)
+               limit = 0;
+       else
+               limit = fls(ap->sata_spd_limit);
+
+       spd = (*scontrol >> 4) & 0xf;
+       *scontrol = (*scontrol & ~0xf0) | ((limit & 0xf) << 4);
+
+       return spd != limit;
+}
+
+/**
+ *     sata_set_spd_needed - is SATA spd configuration needed
+ *     @ap: Port in question
+ *
+ *     Test whether the spd limit in SControl matches
+ *     @ap->sata_spd_limit.  This function is used to determine
+ *     whether hardreset is necessary to apply SATA spd
+ *     configuration.
+ *
+ *     LOCKING:
+ *     Inherited from caller.
+ *
+ *     RETURNS:
+ *     1 if SATA spd configuration is needed, 0 otherwise.
+ */
+int sata_set_spd_needed(struct ata_port *ap)
+{
+       u32 scontrol;
+
+       if (sata_scr_read(ap, SCR_CONTROL, &scontrol))
+               return 0;
+
+       return __sata_set_spd_needed(ap, &scontrol);
+}
+
+/**
+ *     sata_set_spd - set SATA spd according to spd limit
+ *     @ap: Port to set SATA spd for
+ *
+ *     Set SATA spd of @ap according to sata_spd_limit.
+ *
+ *     LOCKING:
+ *     Inherited from caller.
+ *
+ *     RETURNS:
+ *     0 if spd doesn't need to be changed, 1 if spd has been
+ *     changed.  Negative errno if SCR registers are inaccessible.
+ */
+int sata_set_spd(struct ata_port *ap)
+{
+       u32 scontrol;
+       int rc;
+
+       if ((rc = sata_scr_read(ap, SCR_CONTROL, &scontrol)))
+               return rc;
+
+       if (!__sata_set_spd_needed(ap, &scontrol))
+               return 0;
+
+       if ((rc = sata_scr_write(ap, SCR_CONTROL, scontrol)))
+               return rc;
+
+       return 1;
+}
+
+/*
+ * This mode timing computation functionality is ported over from
+ * drivers/ide/ide-timing.h and was originally written by Vojtech Pavlik
+ */
+/*
+ * PIO 0-5, MWDMA 0-2 and UDMA 0-6 timings (in nanoseconds).
+ * These were taken from ATA/ATAPI-6 standard, rev 0a, except
+ * for PIO 5, which is a nonstandard extension and UDMA6, which
+ * is currently supported only by Maxtor drives.
+ */
+
+static const struct ata_timing ata_timing[] = {
+
+       { XFER_UDMA_6,     0,   0,   0,   0,   0,   0,   0,  15 },
+       { XFER_UDMA_5,     0,   0,   0,   0,   0,   0,   0,  20 },
+       { XFER_UDMA_4,     0,   0,   0,   0,   0,   0,   0,  30 },
+       { XFER_UDMA_3,     0,   0,   0,   0,   0,   0,   0,  45 },
+
+       { XFER_UDMA_2,     0,   0,   0,   0,   0,   0,   0,  60 },
+       { XFER_UDMA_1,     0,   0,   0,   0,   0,   0,   0,  80 },
+       { XFER_UDMA_0,     0,   0,   0,   0,   0,   0,   0, 120 },
+
+/*     { XFER_UDMA_SLOW,  0,   0,   0,   0,   0,   0,   0, 150 }, */
+
+       { XFER_MW_DMA_2,  25,   0,   0,   0,  70,  25, 120,   0 },
+       { XFER_MW_DMA_1,  45,   0,   0,   0,  80,  50, 150,   0 },
+       { XFER_MW_DMA_0,  60,   0,   0,   0, 215, 215, 480,   0 },
+
+       { XFER_SW_DMA_2,  60,   0,   0,   0, 120, 120, 240,   0 },
+       { XFER_SW_DMA_1,  90,   0,   0,   0, 240, 240, 480,   0 },
+       { XFER_SW_DMA_0, 120,   0,   0,   0, 480, 480, 960,   0 },
+
+/*     { XFER_PIO_5,     20,  50,  30, 100,  50,  30, 100,   0 }, */
+       { XFER_PIO_4,     25,  70,  25, 120,  70,  25, 120,   0 },
+       { XFER_PIO_3,     30,  80,  70, 180,  80,  70, 180,   0 },
+
+       { XFER_PIO_2,     30, 290,  40, 330, 100,  90, 240,   0 },
+       { XFER_PIO_1,     50, 290,  93, 383, 125, 100, 383,   0 },
+       { XFER_PIO_0,     70, 290, 240, 600, 165, 150, 600,   0 },
+
+/*     { XFER_PIO_SLOW, 120, 290, 240, 960, 290, 240, 960,   0 }, */
+
+       { 0xFF }
+};
+
+#define ENOUGH(v,unit)         (((v)-1)/(unit)+1)
+#define EZ(v,unit)             ((v)?ENOUGH(v,unit):0)
+
+static void ata_timing_quantize(const struct ata_timing *t, struct ata_timing *q, int T, int UT)
+{
+       q->setup   = EZ(t->setup   * 1000,  T);
+       q->act8b   = EZ(t->act8b   * 1000,  T);
+       q->rec8b   = EZ(t->rec8b   * 1000,  T);
+       q->cyc8b   = EZ(t->cyc8b   * 1000,  T);
+       q->active  = EZ(t->active  * 1000,  T);
+       q->recover = EZ(t->recover * 1000,  T);
+       q->cycle   = EZ(t->cycle   * 1000,  T);
+       q->udma    = EZ(t->udma    * 1000, UT);
+}
+
+void ata_timing_merge(const struct ata_timing *a, const struct ata_timing *b,
+                     struct ata_timing *m, unsigned int what)
+{
+       if (what & ATA_TIMING_SETUP  ) m->setup   = max(a->setup,   b->setup);
+       if (what & ATA_TIMING_ACT8B  ) m->act8b   = max(a->act8b,   b->act8b);
+       if (what & ATA_TIMING_REC8B  ) m->rec8b   = max(a->rec8b,   b->rec8b);
+       if (what & ATA_TIMING_CYC8B  ) m->cyc8b   = max(a->cyc8b,   b->cyc8b);
+       if (what & ATA_TIMING_ACTIVE ) m->active  = max(a->active,  b->active);
+       if (what & ATA_TIMING_RECOVER) m->recover = max(a->recover, b->recover);
+       if (what & ATA_TIMING_CYCLE  ) m->cycle   = max(a->cycle,   b->cycle);
+       if (what & ATA_TIMING_UDMA   ) m->udma    = max(a->udma,    b->udma);
+}
+
+static const struct ata_timing* ata_timing_find_mode(unsigned short speed)
+{
+       const struct ata_timing *t;
+
+       for (t = ata_timing; t->mode != speed; t++)
+               if (t->mode == 0xFF)
+                       return NULL;
+       return t;
+}
+
+int ata_timing_compute(struct ata_device *adev, unsigned short speed,
+                      struct ata_timing *t, int T, int UT)
+{
+       const struct ata_timing *s;
+       struct ata_timing p;
+
+       /*
+        * Find the mode.
+        */
+
+       if (!(s = ata_timing_find_mode(speed)))
+               return -EINVAL;
+
+       memcpy(t, s, sizeof(*s));
+
+       /*
+        * If the drive is an EIDE drive, it can tell us it needs extended
+        * PIO/MW_DMA cycle timing.
+        */
+
+       if (adev->id[ATA_ID_FIELD_VALID] & 2) { /* EIDE drive */
+               memset(&p, 0, sizeof(p));
+               if(speed >= XFER_PIO_0 && speed <= XFER_SW_DMA_0) {
+                       if (speed <= XFER_PIO_2) p.cycle = p.cyc8b = adev->id[ATA_ID_EIDE_PIO];
+                                           else p.cycle = p.cyc8b = adev->id[ATA_ID_EIDE_PIO_IORDY];
+               } else if(speed >= XFER_MW_DMA_0 && speed <= XFER_MW_DMA_2) {
+                       p.cycle = adev->id[ATA_ID_EIDE_DMA_MIN];
+               }
+               ata_timing_merge(&p, t, t, ATA_TIMING_CYCLE | ATA_TIMING_CYC8B);
+       }
+
+       /*
+        * Convert the timing to bus clock counts.
+        */
+
+       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.
+        */
+
+       if (speed > XFER_PIO_4) {
+               ata_timing_compute(adev, adev->pio_mode, &p, T, UT);
+               ata_timing_merge(&p, t, t, ATA_TIMING_ALL);
+       }
+
+       /*
+        * Lengthen active & recovery time so that cycle time is correct.
+        */
+
+       if (t->act8b + t->rec8b < t->cyc8b) {
+               t->act8b += (t->cyc8b - (t->act8b + t->rec8b)) / 2;
+               t->rec8b = t->cyc8b - t->act8b;
+       }
+
+       if (t->active + t->recover < t->cycle) {
+               t->active += (t->cycle - (t->active + t->recover)) / 2;
+               t->recover = t->cycle - t->active;
+       }
+
+       return 0;
+}
+
+/**
+ *     ata_down_xfermask_limit - adjust dev xfer masks downward
+ *     @dev: Device to adjust xfer masks
+ *     @force_pio0: Force PIO0
+ *
+ *     Adjust xfer masks of @dev downward.  Note that this function
+ *     does not apply the change.  Invoking ata_set_mode() afterwards
+ *     will apply the limit.
+ *
+ *     LOCKING:
+ *     Inherited from caller.
+ *
+ *     RETURNS:
+ *     0 on success, negative errno on failure
+ */
+int ata_down_xfermask_limit(struct ata_device *dev, int force_pio0)
+{
+       unsigned long xfer_mask;
+       int highbit;
+
+       xfer_mask = ata_pack_xfermask(dev->pio_mask, dev->mwdma_mask,
+                                     dev->udma_mask);
+
+       if (!xfer_mask)
+               goto fail;
+       /* don't gear down to MWDMA from UDMA, go directly to PIO */
+       if (xfer_mask & ATA_MASK_UDMA)
+               xfer_mask &= ~ATA_MASK_MWDMA;
+
+       highbit = fls(xfer_mask) - 1;
+       xfer_mask &= ~(1 << highbit);
+       if (force_pio0)
+               xfer_mask &= 1 << ATA_SHIFT_PIO;
+       if (!xfer_mask)
+               goto fail;
+
+       ata_unpack_xfermask(xfer_mask, &dev->pio_mask, &dev->mwdma_mask,
+                           &dev->udma_mask);
+
+       ata_dev_printk(dev, KERN_WARNING, "limiting speed to %s\n",
+                      ata_mode_string(xfer_mask));
+
+       return 0;
+
+ fail:
+       return -EINVAL;
+}
+
+static int ata_dev_set_mode(struct ata_device *dev)
+{
+       unsigned int err_mask;
+       int rc;
+
+       dev->flags &= ~ATA_DFLAG_PIO;
+       if (dev->xfer_shift == ATA_SHIFT_PIO)
+               dev->flags |= ATA_DFLAG_PIO;
+
+       err_mask = ata_dev_set_xfermode(dev);
+       if (err_mask) {
+               ata_dev_printk(dev, KERN_ERR, "failed to set xfermode "
+                              "(err_mask=0x%x)\n", err_mask);
+               return -EIO;
+       }
+
+       rc = ata_dev_revalidate(dev, 0);
+       if (rc)
+               return rc;
+
+       DPRINTK("xfer_shift=%u, xfer_mode=0x%x\n",
+               dev->xfer_shift, (int)dev->xfer_mode);
+
+       ata_dev_printk(dev, KERN_INFO, "configured for %s\n",
+                      ata_mode_string(ata_xfer_mode2mask(dev->xfer_mode)));
+       return 0;
+}
+
+/**
+ *     ata_set_mode - Program timings and issue SET FEATURES - XFER
+ *     @ap: port on which timings will be programmed
+ *     @r_failed_dev: out paramter for failed device
+ *
+ *     Set ATA device disk transfer mode (PIO3, UDMA6, etc.).  If
+ *     ata_set_mode() fails, pointer to the failing device is
+ *     returned in @r_failed_dev.
+ *
+ *     LOCKING:
+ *     PCI/etc. bus probe sem.
+ *
+ *     RETURNS:
+ *     0 on success, negative errno otherwise
+ */
+int ata_set_mode(struct ata_port *ap, struct ata_device **r_failed_dev)
+{
+       struct ata_device *dev;
+       int i, rc = 0, used_dma = 0, found = 0;
+
+       /* has private set_mode? */
+       if (ap->ops->set_mode) {
+               /* FIXME: make ->set_mode handle no device case and
+                * return error code and failing device on failure.
+                */
+               for (i = 0; i < ATA_MAX_DEVICES; i++) {
+                       if (ata_dev_ready(&ap->device[i])) {
+                               ap->ops->set_mode(ap);
+                               break;
+                       }
+               }
+               return 0;
+       }
+
+       /* step 1: calculate xfer_mask */
+       for (i = 0; i < ATA_MAX_DEVICES; i++) {
+               unsigned int pio_mask, dma_mask;
+
+               dev = &ap->device[i];
+
+               if (!ata_dev_enabled(dev))
+                       continue;
+
+               ata_dev_xfermask(dev);
+
+               pio_mask = ata_pack_xfermask(dev->pio_mask, 0, 0);
+               dma_mask = ata_pack_xfermask(0, dev->mwdma_mask, dev->udma_mask);
+               dev->pio_mode = ata_xfer_mask2mode(pio_mask);
+               dev->dma_mode = ata_xfer_mask2mode(dma_mask);
+
+               found = 1;
+               if (dev->dma_mode)
+                       used_dma = 1;
+       }
+       if (!found)
+               goto out;
+
+       /* step 2: always set host PIO timings */
+       for (i = 0; i < ATA_MAX_DEVICES; i++) {
+               dev = &ap->device[i];
+               if (!ata_dev_enabled(dev))
+                       continue;
+
+               if (!dev->pio_mode) {
+                       ata_dev_printk(dev, KERN_WARNING, "no PIO support\n");
+                       rc = -EINVAL;
+                       goto out;
+               }
+
+               dev->xfer_mode = dev->pio_mode;
+               dev->xfer_shift = ATA_SHIFT_PIO;
+               if (ap->ops->set_piomode)
+                       ap->ops->set_piomode(ap, dev);
+       }
+
+       /* step 3: set host DMA timings */
+       for (i = 0; i < ATA_MAX_DEVICES; i++) {
+               dev = &ap->device[i];
+
+               if (!ata_dev_enabled(dev) || !dev->dma_mode)
+                       continue;
+
+               dev->xfer_mode = dev->dma_mode;
+               dev->xfer_shift = ata_xfer_mode2shift(dev->dma_mode);
+               if (ap->ops->set_dmamode)
+                       ap->ops->set_dmamode(ap, dev);
+       }
+
+       /* step 4: update devices' xfer mode */
+       for (i = 0; i < ATA_MAX_DEVICES; i++) {
+               dev = &ap->device[i];
+
+               /* don't udpate suspended devices' xfer mode */
+               if (!ata_dev_ready(dev))
+                       continue;
+
+               rc = ata_dev_set_mode(dev);
+               if (rc)
+                       goto out;
+       }
+
+       /* Record simplex status. If we selected DMA then the other
+        * host channels are not permitted to do so.
+        */
+       if (used_dma && (ap->host_set->flags & ATA_HOST_SIMPLEX))
+               ap->host_set->simplex_claimed = 1;
+
+       /* step5: chip specific finalisation */
+       if (ap->ops->post_set_mode)
+               ap->ops->post_set_mode(ap);
+
+ out:
+       if (rc)
+               *r_failed_dev = dev;
+       return rc;
+}
+
+/**
+ *     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
+ *     @tmout_pat: impatience timeout
+ *     @tmout: overall timeout
+ *
+ *     Sleep until ATA Status register bit BSY clears,
+ *     or a timeout occurs.
+ *
+ *     LOCKING: None.
+ */
+
+unsigned int ata_busy_sleep (struct ata_port *ap,
+                            unsigned long tmout_pat, unsigned long tmout)
+{
+       unsigned long timer_start, timeout;
+       u8 status;
+
+       status = ata_busy_wait(ap, ATA_BUSY, 300);
+       timer_start = jiffies;
+       timeout = timer_start + tmout_pat;
+       while ((status & ATA_BUSY) && (time_before(jiffies, timeout))) {
+               msleep(50);
+               status = ata_busy_wait(ap, ATA_BUSY, 3);
+       }
+
+       if (status & ATA_BUSY)
+               ata_port_printk(ap, KERN_WARNING,
+                               "port is slow to respond, please be patient\n");
+
+       timeout = timer_start + tmout;
+       while ((status & ATA_BUSY) && (time_before(jiffies, timeout))) {
+               msleep(50);
+               status = ata_chk_status(ap);
+       }
+
+       if (status & ATA_BUSY) {
+               ata_port_printk(ap, KERN_ERR, "port failed to respond "
+                               "(%lu secs)\n", tmout / HZ);
+               return 1;
+       }
+
+       return 0;
+}
+
+static void ata_bus_post_reset(struct ata_port *ap, unsigned int devmask)
+{
+       struct ata_ioports *ioaddr = &ap->ioaddr;
+       unsigned int dev0 = devmask & (1 << 0);
+       unsigned int dev1 = devmask & (1 << 1);
+       unsigned long timeout;
+
+       /* if device 0 was found in ata_devchk, wait for its
+        * BSY bit to clear
+        */
+       if (dev0)
+               ata_busy_sleep(ap, ATA_TMOUT_BOOT_QUICK, ATA_TMOUT_BOOT);
+
+       /* if device 1 was found in ata_devchk, wait for
+        * register access, then wait for BSY to clear
+        */
+       timeout = jiffies + ATA_TMOUT_BOOT;
+       while (dev1) {
+               u8 nsect, lbal;
+
+               ap->ops->dev_select(ap, 1);
+               if (ap->flags & ATA_FLAG_MMIO) {
+                       nsect = readb((void __iomem *) ioaddr->nsect_addr);
+                       lbal = readb((void __iomem *) ioaddr->lbal_addr);
+               } else {
+                       nsect = inb(ioaddr->nsect_addr);
+                       lbal = inb(ioaddr->lbal_addr);
+               }
+               if ((nsect == 1) && (lbal == 1))
+                       break;
+               if (time_after(jiffies, timeout)) {
+                       dev1 = 0;
+                       break;
+               }
+               msleep(50);     /* give drive a breather */
+       }
+       if (dev1)
+               ata_busy_sleep(ap, ATA_TMOUT_BOOT_QUICK, ATA_TMOUT_BOOT);
+
+       /* is all this really necessary? */
+       ap->ops->dev_select(ap, 0);
+       if (dev1)
+               ap->ops->dev_select(ap, 1);
+       if (dev0)
+               ap->ops->dev_select(ap, 0);
+}
+
+static unsigned int ata_bus_softreset(struct ata_port *ap,
+                                     unsigned int devmask)
+{
+       struct ata_ioports *ioaddr = &ap->ioaddr;
+
+       DPRINTK("ata%u: bus reset via SRST\n", ap->id);
+
+       /* software reset.  causes dev0 to be selected */
+       if (ap->flags & ATA_FLAG_MMIO) {
+               writeb(ap->ctl, (void __iomem *) ioaddr->ctl_addr);
+               udelay(20);     /* FIXME: flush */
+               writeb(ap->ctl | ATA_SRST, (void __iomem *) ioaddr->ctl_addr);
+               udelay(20);     /* FIXME: flush */
+               writeb(ap->ctl, (void __iomem *) ioaddr->ctl_addr);
+       } else {
+               outb(ap->ctl, ioaddr->ctl_addr);
+               udelay(10);
+               outb(ap->ctl | ATA_SRST, ioaddr->ctl_addr);
+               udelay(10);
+               outb(ap->ctl, ioaddr->ctl_addr);
+       }
+
+       /* spec mandates ">= 2ms" before checking status.
+        * We wait 150ms, because that was the magic delay used for
+        * ATAPI devices in Hale Landis's ATADRVR, for the period of time
+        * between when the ATA command register is written, and then
+        * status is checked.  Because waiting for "a while" before
+        * checking status is fine, post SRST, we perform this magic
+        * delay here as well.
+        *
+        * Old drivers/ide uses the 2mS rule and then waits for ready
+        */
+       msleep(150);
+
+       /* Before we perform post reset processing we want to see if
+        * the bus shows 0xFF because the odd clown forgets the D7
+        * pulldown resistor.
+        */
+       if (ata_check_status(ap) == 0xFF) {
+               ata_port_printk(ap, KERN_ERR, "SRST failed (status 0xFF)\n");
+               return AC_ERR_OTHER;
+       }
+
+       ata_bus_post_reset(ap, devmask);
+
+       return 0;
+}
+
+/**
+ *     ata_bus_reset - reset host port and associated ATA channel
+ *     @ap: port to reset
+ *
+ *     This is typically the first time we actually start issuing
+ *     commands to the ATA channel.  We wait for BSY to clear, then
+ *     issue EXECUTE DEVICE DIAGNOSTIC command, polling for its
+ *     result.  Determine what devices, if any, are on the channel
+ *     by looking at the device 0/1 error register.  Look at the signature
+ *     stored in each device's taskfile registers, to determine if
+ *     the device is ATA or ATAPI.
+ *
+ *     LOCKING:
+ *     PCI/etc. bus probe sem.
+ *     Obtains host_set lock.
+ *
+ *     SIDE EFFECTS:
+ *     Sets ATA_FLAG_DISABLED if bus reset fails.
+ */
+
+void ata_bus_reset(struct ata_port *ap)
+{
+       struct ata_ioports *ioaddr = &ap->ioaddr;
+       unsigned int slave_possible = ap->flags & ATA_FLAG_SLAVE_POSS;
+       u8 err;
+       unsigned int dev0, dev1 = 0, devmask = 0;
+
+       DPRINTK("ENTER, host %u, port %u\n", ap->id, ap->port_no);
+
+       /* determine if device 0/1 are present */
+       if (ap->flags & ATA_FLAG_SATA_RESET)
+               dev0 = 1;
+       else {
+               dev0 = ata_devchk(ap, 0);
+               if (slave_possible)
+                       dev1 = ata_devchk(ap, 1);
+       }
+
+       if (dev0)
+               devmask |= (1 << 0);
+       if (dev1)
+               devmask |= (1 << 1);
+
+       /* select device 0 again */
+       ap->ops->dev_select(ap, 0);
+
+       /* issue bus reset */
+       if (ap->flags & ATA_FLAG_SRST)
+               if (ata_bus_softreset(ap, devmask))
+                       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:
+       ata_port_printk(ap, KERN_ERR, "disabling port\n");
+       ap->ops->port_disable(ap);
+
+       DPRINTK("EXIT\n");
+}
+
+/**
+ *     sata_phy_debounce - debounce SATA phy status
+ *     @ap: ATA port to debounce SATA phy status for
+ *     @params: timing parameters { interval, duratinon, timeout } in msec
+ *
+ *     Make sure SStatus of @ap reaches stable state, determined by
+ *     holding the same value where DET is not 1 for @duration polled
+ *     every @interval, before @timeout.  Timeout constraints the
+ *     beginning of the stable state.  Because, after hot unplugging,
+ *     DET gets stuck at 1 on some controllers, this functions waits
+ *     until timeout then returns 0 if DET is stable at 1.
+ *
+ *     LOCKING:
+ *     Kernel thread context (may sleep)
+ *
+ *     RETURNS:
+ *     0 on success, -errno on failure.
+ */
+int sata_phy_debounce(struct ata_port *ap, const unsigned long *params)
+{
+       unsigned long interval_msec = params[0];
+       unsigned long duration = params[1] * HZ / 1000;
+       unsigned long timeout = jiffies + params[2] * HZ / 1000;
+       unsigned long last_jiffies;
+       u32 last, cur;
+       int rc;
+
+       if ((rc = sata_scr_read(ap, SCR_STATUS, &cur)))
+               return rc;
+       cur &= 0xf;
+
+       last = cur;
+       last_jiffies = jiffies;
+
+       while (1) {
+               msleep(interval_msec);
+               if ((rc = sata_scr_read(ap, SCR_STATUS, &cur)))
+                       return rc;
+               cur &= 0xf;
+
+               /* DET stable? */
+               if (cur == last) {
+                       if (cur == 1 && time_before(jiffies, timeout))
+                               continue;
+                       if (time_after(jiffies, last_jiffies + duration))
+                               return 0;
+                       continue;
+               }
+
+               /* unstable, start over */
+               last = cur;
+               last_jiffies = jiffies;
+
+               /* check timeout */
+               if (time_after(jiffies, timeout))
+                       return -EBUSY;
+       }
+}
+
+/**
+ *     sata_phy_resume - resume SATA phy
+ *     @ap: ATA port to resume SATA phy for
+ *     @params: timing parameters { interval, duratinon, timeout } in msec
+ *
+ *     Resume SATA phy of @ap and debounce it.
+ *
+ *     LOCKING:
+ *     Kernel thread context (may sleep)
+ *
+ *     RETURNS:
+ *     0 on success, -errno on failure.
+ */
+int sata_phy_resume(struct ata_port *ap, const unsigned long *params)
+{
+       u32 scontrol;
+       int rc;
+
+       if ((rc = sata_scr_read(ap, SCR_CONTROL, &scontrol)))
+               return rc;
+
+       scontrol = (scontrol & 0x0f0) | 0x300;
+
+       if ((rc = sata_scr_write(ap, SCR_CONTROL, scontrol)))
+               return rc;
+
+       /* Some PHYs react badly if SStatus is pounded immediately
+        * after resuming.  Delay 200ms before debouncing.
+        */
+       msleep(200);
+
+       return sata_phy_debounce(ap, params);
+}
+
+static void ata_wait_spinup(struct ata_port *ap)
+{
+       struct ata_eh_context *ehc = &ap->eh_context;
+       unsigned long end, secs;
+       int rc;
+
+       /* first, debounce phy if SATA */
+       if (ap->cbl == ATA_CBL_SATA) {
+               rc = sata_phy_debounce(ap, sata_deb_timing_hotplug);
+
+               /* if debounced successfully and offline, no need to wait */
+               if ((rc == 0 || rc == -EOPNOTSUPP) && ata_port_offline(ap))
+                       return;
+       }
+
+       /* okay, let's give the drive time to spin up */
+       end = ehc->i.hotplug_timestamp + ATA_SPINUP_WAIT * HZ / 1000;
+       secs = ((end - jiffies) + HZ - 1) / HZ;
+
+       if (time_after(jiffies, end))
+               return;
+
+       if (secs > 5)
+               ata_port_printk(ap, KERN_INFO, "waiting for device to spin up "
+                               "(%lu secs)\n", secs);
+
+       schedule_timeout_uninterruptible(end - jiffies);
+}
+
+/**
+ *     ata_std_prereset - prepare for reset
+ *     @ap: ATA port to be reset
+ *
+ *     @ap is about to be reset.  Initialize it.
+ *
+ *     LOCKING:
+ *     Kernel thread context (may sleep)
+ *
+ *     RETURNS:
+ *     0 on success, -errno otherwise.
+ */
+int ata_std_prereset(struct ata_port *ap)
+{
+       struct ata_eh_context *ehc = &ap->eh_context;
+       const unsigned long *timing = sata_ehc_deb_timing(ehc);
+       int rc;
+
+       /* handle link resume & hotplug spinup */
+       if ((ehc->i.flags & ATA_EHI_RESUME_LINK) &&
+           (ap->flags & ATA_FLAG_HRST_TO_RESUME))
+               ehc->i.action |= ATA_EH_HARDRESET;
+
+       if ((ehc->i.flags & ATA_EHI_HOTPLUGGED) &&
+           (ap->flags & ATA_FLAG_SKIP_D2H_BSY))
+               ata_wait_spinup(ap);
+
+       /* if we're about to do hardreset, nothing more to do */
+       if (ehc->i.action & ATA_EH_HARDRESET)
+               return 0;
+
+       /* if SATA, resume phy */
+       if (ap->cbl == ATA_CBL_SATA) {
+               rc = sata_phy_resume(ap, timing);
+               if (rc && rc != -EOPNOTSUPP) {
+                       /* phy resume failed */
+                       ata_port_printk(ap, KERN_WARNING, "failed to resume "
+                                       "link for reset (errno=%d)\n", rc);
+                       return rc;
+               }
+       }
+
+       /* Wait for !BSY if the controller can wait for the first D2H
+        * Reg FIS and we don't know that no device is attached.
+        */
+       if (!(ap->flags & ATA_FLAG_SKIP_D2H_BSY) && !ata_port_offline(ap))
+               ata_busy_sleep(ap, ATA_TMOUT_BOOT_QUICK, ATA_TMOUT_BOOT);
+
+       return 0;
+}
+
+/**
+ *     ata_std_softreset - reset host port via ATA SRST
+ *     @ap: port to reset
+ *     @classes: resulting classes of attached devices
+ *
+ *     Reset host port using ATA SRST.
+ *
+ *     LOCKING:
+ *     Kernel thread context (may sleep)
+ *
+ *     RETURNS:
+ *     0 on success, -errno otherwise.
+ */
+int ata_std_softreset(struct ata_port *ap, 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 (ata_port_offline(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) {
+               ata_port_printk(ap, KERN_ERR, "SRST 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
+ *     @class: resulting class of attached device
+ *
+ *     SATA phy-reset host port using DET bits of SControl register.
+ *
+ *     LOCKING:
+ *     Kernel thread context (may sleep)
+ *
+ *     RETURNS:
+ *     0 on success, -errno otherwise.
+ */
+int sata_std_hardreset(struct ata_port *ap, unsigned int *class)
+{
+       struct ata_eh_context *ehc = &ap->eh_context;
+       const unsigned long *timing = sata_ehc_deb_timing(ehc);
+       u32 scontrol;
+       int rc;
+
+       DPRINTK("ENTER\n");
+
+       if (sata_set_spd_needed(ap)) {
+               /* SATA spec says nothing about how to reconfigure
+                * spd.  To be on the safe side, turn off phy during
+                * reconfiguration.  This works for at least ICH7 AHCI
+                * and Sil3124.
+                */
+               if ((rc = sata_scr_read(ap, SCR_CONTROL, &scontrol)))
+                       return rc;
+
+               scontrol = (scontrol & 0x0f0) | 0x302;
+
+               if ((rc = sata_scr_write(ap, SCR_CONTROL, scontrol)))
+                       return rc;
+
+               sata_set_spd(ap);
+       }
+
+       /* issue phy wake/reset */
+       if ((rc = sata_scr_read(ap, SCR_CONTROL, &scontrol)))
+               return rc;
+
+       scontrol = (scontrol & 0x0f0) | 0x301;
+
+       if ((rc = sata_scr_write_flush(ap, SCR_CONTROL, scontrol)))
+               return rc;
+
+       /* 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, timing);
+
+       /* TODO: phy layer with polling, timeouts, etc. */
+       if (ata_port_offline(ap)) {
+               *class = ATA_DEV_NONE;
+               DPRINTK("EXIT, link offline\n");
+               return 0;
+       }
+
+       if (ata_busy_sleep(ap, ATA_TMOUT_BOOT_QUICK, ATA_TMOUT_BOOT)) {
+               ata_port_printk(ap, KERN_ERR,
+                               "COMRESET failed (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.
+ *
+ *     LOCKING:
+ *     Kernel thread context (may sleep)
+ */
+void ata_std_postreset(struct ata_port *ap, unsigned int *classes)
+{
+       u32 serror;
+
+       DPRINTK("ENTER\n");
+
+       /* print link status */
+       sata_print_link_status(ap);
+
+       /* clear SError */
+       if (sata_scr_read(ap, SCR_ERROR, &serror) == 0)
+               sata_scr_write(ap, SCR_ERROR, serror);
+
+       /* re-enable interrupts */
+       if (!ap->ops->error_handler) {
+               /* FIXME: hack. create a hook instead */
+               if (ap->ioaddr.ctl_addr)
+                       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_dev_same_device - Determine whether new ID matches configured device
+ *     @dev: device to compare against
+ *     @new_class: class of the new device
+ *     @new_id: IDENTIFY page of the new device
+ *
+ *     Compare @new_class and @new_id against @dev and determine
+ *     whether @dev is the device indicated by @new_class and
+ *     @new_id.
+ *
+ *     LOCKING:
+ *     None.
+ *
+ *     RETURNS:
+ *     1 if @dev matches @new_class and @new_id, 0 otherwise.
+ */
+static int ata_dev_same_device(struct ata_device *dev, unsigned int new_class,
+                              const u16 *new_id)
+{
+       const u16 *old_id = dev->id;
+       unsigned char model[2][41], serial[2][21];
+       u64 new_n_sectors;
+
+       if (dev->class != new_class) {
+               ata_dev_printk(dev, KERN_INFO, "class mismatch %d != %d\n",
+                              dev->class, new_class);
+               return 0;
+       }
+
+       ata_id_c_string(old_id, model[0], ATA_ID_PROD_OFS, sizeof(model[0]));
+       ata_id_c_string(new_id, model[1], ATA_ID_PROD_OFS, sizeof(model[1]));
+       ata_id_c_string(old_id, serial[0], ATA_ID_SERNO_OFS, sizeof(serial[0]));
+       ata_id_c_string(new_id, serial[1], ATA_ID_SERNO_OFS, sizeof(serial[1]));
+       new_n_sectors = ata_id_n_sectors(new_id);
+
+       if (strcmp(model[0], model[1])) {
+               ata_dev_printk(dev, KERN_INFO, "model number mismatch "
+                              "'%s' != '%s'\n", model[0], model[1]);
+               return 0;
+       }
+
+       if (strcmp(serial[0], serial[1])) {
+               ata_dev_printk(dev, KERN_INFO, "serial number mismatch "
+                              "'%s' != '%s'\n", serial[0], serial[1]);
+               return 0;
+       }
+
+       if (dev->class == ATA_DEV_ATA && dev->n_sectors != new_n_sectors) {
+               ata_dev_printk(dev, KERN_INFO, "n_sectors mismatch "
+                              "%llu != %llu\n",
+                              (unsigned long long)dev->n_sectors,
+                              (unsigned long long)new_n_sectors);
+               return 0;
+       }
+
+       return 1;
+}
+
+/**
+ *     ata_dev_revalidate - Revalidate ATA device
+ *     @dev: device to revalidate
+ *     @post_reset: is this revalidation after reset?
+ *
+ *     Re-read IDENTIFY page and make sure @dev is still attached to
+ *     the port.
+ *
+ *     LOCKING:
+ *     Kernel thread context (may sleep)
+ *
+ *     RETURNS:
+ *     0 on success, negative errno otherwise
+ */
+int ata_dev_revalidate(struct ata_device *dev, int post_reset)
+{
+       unsigned int class = dev->class;
+       u16 *id = (void *)dev->ap->sector_buf;
+       int rc;
+
+       if (!ata_dev_enabled(dev)) {
+               rc = -ENODEV;
+               goto fail;
+       }
+
+       /* read ID data */
+       rc = ata_dev_read_id(dev, &class, post_reset, id);
+       if (rc)
+               goto fail;
+
+       /* is the device still there? */
+       if (!ata_dev_same_device(dev, class, id)) {
+               rc = -ENODEV;
+               goto fail;
+       }
+
+       memcpy(dev->id, id, sizeof(id[0]) * ATA_ID_WORDS);
+
+       /* configure device according to the new ID */
+       rc = ata_dev_configure(dev, 0);
+       if (rc == 0)
+               return 0;
+
+ fail:
+       ata_dev_printk(dev, KERN_ERR, "revalidation failed (errno=%d)\n", rc);
+       return rc;
+}
+
+static const char * const ata_dma_blacklist [] = {
+       "WDC AC11000H", NULL,
+       "WDC AC22100H", NULL,
+       "WDC AC32500H", NULL,
+       "WDC AC33100H", NULL,
+       "WDC AC31600H", NULL,
+       "WDC AC32100H", "24.09P07",
+       "WDC AC23200L", "21.10N21",
+       "Compaq CRD-8241B",  NULL,
+       "CRD-8400B", NULL,
+       "CRD-8480B", NULL,
+       "CRD-8482B", NULL,
+       "CRD-84", NULL,
+       "SanDisk SDP3B", NULL,
+       "SanDisk SDP3B-64", NULL,
+       "SANYO CD-ROM CRD", NULL,
+       "HITACHI CDR-8", NULL,
+       "HITACHI CDR-8335", NULL,
+       "HITACHI CDR-8435", NULL,
+       "Toshiba CD-ROM XM-6202B", NULL,
+       "TOSHIBA CD-ROM XM-1702BC", NULL,
+       "CD-532E-A", NULL,
+       "E-IDE CD-ROM CR-840", NULL,
+       "CD-ROM Drive/F5A", NULL,
+       "WPI CDD-820", NULL,
+       "SAMSUNG CD-ROM SC-148C", NULL,
+       "SAMSUNG CD-ROM SC", NULL,
+       "SanDisk SDP3B-64", NULL,
+       "ATAPI CD-ROM DRIVE 40X MAXIMUM",NULL,
+       "_NEC DV5800A", NULL,
+       "SAMSUNG CD-ROM SN-124", "N001"
+};
+
+static int ata_strim(char *s, size_t len)
+{
+       len = strnlen(s, len);
+
+       /* ATAPI specifies that empty space is blank-filled; remove blanks */
+       while ((len > 0) && (s[len - 1] == ' ')) {
+               len--;
+               s[len] = 0;
+       }
+       return len;
+}
+
+static int ata_dma_blacklisted(const struct ata_device *dev)
+{
+       unsigned char model_num[40];
+       unsigned char model_rev[16];
+       unsigned int nlen, rlen;
+       int i;
+
+       /* We don't support polling DMA.
+        * DMA blacklist those ATAPI devices with CDB-intr (and use PIO)
+        * if the LLDD handles only interrupts in the HSM_ST_LAST state.
+        */
+       if ((dev->ap->flags & ATA_FLAG_PIO_POLLING) &&
+           (dev->flags & ATA_DFLAG_CDB_INTR))
+               return 1;
+
+       ata_id_string(dev->id, model_num, ATA_ID_PROD_OFS,
+                         sizeof(model_num));
+       ata_id_string(dev->id, model_rev, ATA_ID_FW_REV_OFS,
+                         sizeof(model_rev));
+       nlen = ata_strim(model_num, sizeof(model_num));
+       rlen = ata_strim(model_rev, sizeof(model_rev));
+
+       for (i = 0; i < ARRAY_SIZE(ata_dma_blacklist); i += 2) {
+               if (!strncmp(ata_dma_blacklist[i], model_num, nlen)) {
+                       if (ata_dma_blacklist[i+1] == NULL)
+                               return 1;
+                       if (!strncmp(ata_dma_blacklist[i], model_rev, rlen))
+                               return 1;
+               }
+       }
+       return 0;
+}
+
+/**
+ *     ata_dev_xfermask - Compute supported xfermask of the given device
+ *     @dev: Device to compute xfermask for
+ *
+ *     Compute supported xfermask of @dev and store it in
+ *     dev->*_mask.  This function is responsible for applying all
+ *     known limits including host controller limits, device
+ *     blacklist, etc...
+ *
+ *     LOCKING:
+ *     None.
+ */
+static void ata_dev_xfermask(struct ata_device *dev)
+{
+       struct ata_port *ap = dev->ap;
+       struct ata_host_set *hs = ap->host_set;
+       unsigned long xfer_mask;
+
+       /* controller modes available */
+       xfer_mask = ata_pack_xfermask(ap->pio_mask,
+                                     ap->mwdma_mask, ap->udma_mask);
+
+       /* Apply cable rule here.  Don't apply it early because when
+        * we handle hot plug the cable type can itself change.
+        */
+       if (ap->cbl == ATA_CBL_PATA40)
+               xfer_mask &= ~(0xF8 << ATA_SHIFT_UDMA);
+
+       xfer_mask &= ata_pack_xfermask(dev->pio_mask,
+                                      dev->mwdma_mask, dev->udma_mask);
+       xfer_mask &= ata_id_xfermask(dev->id);
+
+       if (ata_dma_blacklisted(dev)) {
+               xfer_mask &= ~(ATA_MASK_MWDMA | ATA_MASK_UDMA);
+               ata_dev_printk(dev, KERN_WARNING,
+                              "device is on DMA blacklist, disabling DMA\n");
+       }
+
+       if ((hs->flags & ATA_HOST_SIMPLEX) && hs->simplex_claimed) {
+               xfer_mask &= ~(ATA_MASK_MWDMA | ATA_MASK_UDMA);
+               ata_dev_printk(dev, KERN_WARNING, "simplex DMA is claimed by "
+                              "other device, disabling DMA\n");
+       }
+
+       if (ap->ops->mode_filter)
+               xfer_mask = ap->ops->mode_filter(ap, dev, xfer_mask);
+
+       ata_unpack_xfermask(xfer_mask, &dev->pio_mask,
+                           &dev->mwdma_mask, &dev->udma_mask);
+}
+
+/**
+ *     ata_dev_set_xfermode - Issue SET FEATURES - XFER MODE command
+ *     @dev: Device to which command will be sent
+ *
+ *     Issue SET FEATURES - XFER MODE command to device @dev
+ *     on port @ap.
+ *
+ *     LOCKING:
+ *     PCI/etc. bus probe sem.
+ *
+ *     RETURNS:
+ *     0 on success, AC_ERR_* mask otherwise.
+ */
+
+static unsigned int ata_dev_set_xfermode(struct ata_device *dev)
+{
+       struct ata_taskfile tf;
+       unsigned int err_mask;
+
+       /* set up set-features taskfile */
+       DPRINTK("set features - xfer mode\n");
+
+       ata_tf_init(dev, &tf);
+       tf.command = ATA_CMD_SET_FEATURES;
+       tf.feature = SETFEATURES_XFER;
+       tf.flags |= ATA_TFLAG_ISADDR | ATA_TFLAG_DEVICE;
+       tf.protocol = ATA_PROT_NODATA;
+       tf.nsect = dev->xfer_mode;
+
+       err_mask = ata_exec_internal(dev, &tf, NULL, DMA_NONE, NULL, 0);
+
+       DPRINTK("EXIT, err_mask=%x\n", err_mask);
+       return err_mask;
+}
+
+/**
+ *     ata_dev_init_params - Issue INIT DEV PARAMS command
+ *     @dev: Device to which command will be sent
+ *     @heads: Number of heads (taskfile parameter)
+ *     @sectors: Number of sectors (taskfile parameter)
+ *
+ *     LOCKING:
+ *     Kernel thread context (may sleep)
+ *
+ *     RETURNS:
+ *     0 on success, AC_ERR_* mask otherwise.
+ */
+static unsigned int ata_dev_init_params(struct ata_device *dev,
+                                       u16 heads, u16 sectors)
+{
+       struct ata_taskfile tf;
+       unsigned int err_mask;
+
+       /* Number of sectors per track 1-255. Number of heads 1-16 */
+       if (sectors < 1 || sectors > 255 || heads < 1 || heads > 16)
+               return AC_ERR_INVALID;
+
+       /* set up init dev params taskfile */
+       DPRINTK("init dev params \n");
+
+       ata_tf_init(dev, &tf);
+       tf.command = ATA_CMD_INIT_DEV_PARAMS;
+       tf.flags |= ATA_TFLAG_ISADDR | ATA_TFLAG_DEVICE;
+       tf.protocol = ATA_PROT_NODATA;
+       tf.nsect = sectors;
+       tf.device |= (heads - 1) & 0x0f; /* max head = num. of heads - 1 */
+
+       err_mask = ata_exec_internal(dev, &tf, NULL, DMA_NONE, NULL, 0);
+
+       DPRINTK("EXIT, err_mask=%x\n", err_mask);
+       return err_mask;
+}
+
+/**
+ *     ata_sg_clean - Unmap DMA memory associated with command
+ *     @qc: Command containing DMA memory to be released
+ *
+ *     Unmap all mapped DMA memory associated with this command.
+ *
+ *     LOCKING:
+ *     spin_lock_irqsave(host_set lock)
+ */
+
+static void ata_sg_clean(struct ata_queued_cmd *qc)
+{
+       struct ata_port *ap = qc->ap;
+       struct scatterlist *sg = qc->__sg;
+       int dir = qc->dma_dir;
+       void *pad_buf = NULL;
+
+       WARN_ON(!(qc->flags & ATA_QCFLAG_DMAMAP));
+       WARN_ON(sg == NULL);
+
+       if (qc->flags & ATA_QCFLAG_SINGLE)
+               WARN_ON(qc->n_elem > 1);
+
+       VPRINTK("unmapping %u sg elements\n", qc->n_elem);
+
+       /* if we padded the buffer out to 32-bit bound, and data
+        * xfer direction is from-device, we must copy from the
+        * pad buffer back into the supplied buffer
+        */
+       if (qc->pad_len && !(qc->tf.flags & ATA_TFLAG_WRITE))
+               pad_buf = ap->pad + (qc->tag * ATA_DMA_PAD_SZ);
+
+       if (qc->flags & ATA_QCFLAG_SG) {
+               if (qc->n_elem)
+                       dma_unmap_sg(ap->dev, sg, qc->n_elem, dir);
+               /* restore last sg */
+               sg[qc->orig_n_elem - 1].length += qc->pad_len;
+               if (pad_buf) {
+                       struct scatterlist *psg = &qc->pad_sgent;
+                       void *addr = kmap_atomic(psg->page, KM_IRQ0);
+                       memcpy(addr + psg->offset, pad_buf, qc->pad_len);
+                       kunmap_atomic(addr, KM_IRQ0);
+               }
+       } else {
+               if (qc->n_elem)
+                       dma_unmap_single(ap->dev,
+                               sg_dma_address(&sg[0]), sg_dma_len(&sg[0]),
+                               dir);
+               /* restore sg */
+               sg->length += qc->pad_len;
+               if (pad_buf)
+                       memcpy(qc->buf_virt + sg->length - qc->pad_len,
+                              pad_buf, qc->pad_len);
+       }
+
+       qc->flags &= ~ATA_QCFLAG_DMAMAP;
+       qc->__sg = NULL;
+}
+
+/**
+ *     ata_fill_sg - Fill PCI IDE PRD table
+ *     @qc: Metadata associated with taskfile to be transferred
+ *
+ *     Fill PCI IDE PRD (scatter-gather) table with segments
+ *     associated with the current disk command.
+ *
+ *     LOCKING:
+ *     spin_lock_irqsave(host_set lock)
+ *
+ */
+static void ata_fill_sg(struct ata_queued_cmd *qc)
+{
+       struct ata_port *ap = qc->ap;
+       struct scatterlist *sg;
+       unsigned int idx;
+
+       WARN_ON(qc->__sg == NULL);
+       WARN_ON(qc->n_elem == 0 && qc->pad_len == 0);
+
+       idx = 0;
+       ata_for_each_sg(sg, qc) {
+               u32 addr, offset;
+               u32 sg_len, len;
+
+               /* determine if physical DMA addr spans 64K boundary.
+                * Note h/w doesn't support 64-bit, so we unconditionally
+                * truncate dma_addr_t to u32.
+                */
+               addr = (u32) sg_dma_address(sg);
+               sg_len = sg_dma_len(sg);
+
+               while (sg_len) {
+                       offset = addr & 0xffff;
+                       len = sg_len;
+                       if ((offset + sg_len) > 0x10000)
+                               len = 0x10000 - offset;
+
+                       ap->prd[idx].addr = cpu_to_le32(addr);
+                       ap->prd[idx].flags_len = cpu_to_le32(len & 0xffff);
+                       VPRINTK("PRD[%u] = (0x%X, 0x%X)\n", idx, addr, len);
+
+                       idx++;
+                       sg_len -= len;
+                       addr += len;
+               }
+       }
+
+       if (idx)
+               ap->prd[idx - 1].flags_len |= cpu_to_le32(ATA_PRD_EOT);
+}
+/**
+ *     ata_check_atapi_dma - Check whether ATAPI DMA can be supported
+ *     @qc: Metadata associated with taskfile to check
+ *
+ *     Allow low-level driver to filter ATA PACKET commands, returning
+ *     a status indicating whether or not it is OK to use DMA for the
+ *     supplied PACKET command.
+ *
+ *     LOCKING:
+ *     spin_lock_irqsave(host_set lock)
+ *
+ *     RETURNS: 0 when ATAPI DMA can be used
+ *               nonzero otherwise
+ */
+int ata_check_atapi_dma(struct ata_queued_cmd *qc)
+{
+       struct ata_port *ap = qc->ap;
+       int rc = 0; /* Assume ATAPI DMA is OK by default */
+
+       if (ap->ops->check_atapi_dma)
+               rc = ap->ops->check_atapi_dma(qc);
+
+       return rc;
+}
+/**
+ *     ata_qc_prep - Prepare taskfile for submission
+ *     @qc: Metadata associated with taskfile to be prepared
+ *
+ *     Prepare ATA taskfile for submission.
+ *
+ *     LOCKING:
+ *     spin_lock_irqsave(host_set lock)
+ */
+void ata_qc_prep(struct ata_queued_cmd *qc)
+{
+       if (!(qc->flags & ATA_QCFLAG_DMAMAP))
+               return;
+
+       ata_fill_sg(qc);
+}
+
+void ata_noop_qc_prep(struct ata_queued_cmd *qc) { }
+
+/**
+ *     ata_sg_init_one - Associate command with memory buffer
+ *     @qc: Command to be associated
+ *     @buf: Memory buffer
+ *     @buflen: Length of memory buffer, in bytes.
+ *
+ *     Initialize the data-related elements of queued_cmd @qc
+ *     to point to a single memory buffer, @buf of byte length @buflen.
+ *
+ *     LOCKING:
+ *     spin_lock_irqsave(host_set lock)
+ */
+
+void ata_sg_init_one(struct ata_queued_cmd *qc, void *buf, unsigned int buflen)
+{
+       struct scatterlist *sg;
+
+       qc->flags |= ATA_QCFLAG_SINGLE;
+
+       memset(&qc->sgent, 0, sizeof(qc->sgent));
+       qc->__sg = &qc->sgent;
+       qc->n_elem = 1;
+       qc->orig_n_elem = 1;
+       qc->buf_virt = buf;
+       qc->nbytes = buflen;
+
+       sg = qc->__sg;
+       sg_init_one(sg, buf, buflen);
+}
+
+/**
+ *     ata_sg_init - Associate command with scatter-gather table.
+ *     @qc: Command to be associated
+ *     @sg: Scatter-gather table.
+ *     @n_elem: Number of elements in s/g table.
+ *
+ *     Initialize the data-related elements of queued_cmd @qc
+ *     to point to a scatter-gather table @sg, containing @n_elem
+ *     elements.
+ *
+ *     LOCKING:
+ *     spin_lock_irqsave(host_set lock)
+ */
+
+void ata_sg_init(struct ata_queued_cmd *qc, struct scatterlist *sg,
+                unsigned int n_elem)
+{
+       qc->flags |= ATA_QCFLAG_SG;
+       qc->__sg = sg;
+       qc->n_elem = n_elem;
+       qc->orig_n_elem = n_elem;
+}
+
+/**
+ *     ata_sg_setup_one - DMA-map the memory buffer associated with a command.
+ *     @qc: Command with memory buffer to be mapped.
+ *
+ *     DMA-map the memory buffer associated with queued_cmd @qc.
+ *
+ *     LOCKING:
+ *     spin_lock_irqsave(host_set lock)
+ *
+ *     RETURNS:
+ *     Zero on success, negative on error.
+ */
+
+static int ata_sg_setup_one(struct ata_queued_cmd *qc)
+{
+       struct ata_port *ap = qc->ap;
+       int dir = qc->dma_dir;
+       struct scatterlist *sg = qc->__sg;
+       dma_addr_t dma_address;
+       int trim_sg = 0;
+
+       /* we must lengthen transfers to end on a 32-bit boundary */
+       qc->pad_len = sg->length & 3;
+       if (qc->pad_len) {
+               void *pad_buf = ap->pad + (qc->tag * ATA_DMA_PAD_SZ);
+               struct scatterlist *psg = &qc->pad_sgent;
+
+               WARN_ON(qc->dev->class != ATA_DEV_ATAPI);
+
+               memset(pad_buf, 0, ATA_DMA_PAD_SZ);
+
+               if (qc->tf.flags & ATA_TFLAG_WRITE)
+                       memcpy(pad_buf, qc->buf_virt + sg->length - qc->pad_len,
+                              qc->pad_len);
+
+               sg_dma_address(psg) = ap->pad_dma + (qc->tag * ATA_DMA_PAD_SZ);
+               sg_dma_len(psg) = ATA_DMA_PAD_SZ;
+               /* trim sg */
+               sg->length -= qc->pad_len;
+               if (sg->length == 0)
+                       trim_sg = 1;
+
+               DPRINTK("padding done, sg->length=%u pad_len=%u\n",
+                       sg->length, qc->pad_len);
+       }
+
+       if (trim_sg) {
+               qc->n_elem--;
+               goto skip_map;
+       }
+
+       dma_address = dma_map_single(ap->dev, qc->buf_virt,
+                                    sg->length, dir);
+       if (dma_mapping_error(dma_address)) {
+               /* restore sg */
+               sg->length += qc->pad_len;
+               return -1;
+       }
+
+       sg_dma_address(sg) = dma_address;
+       sg_dma_len(sg) = sg->length;
+
+skip_map:
+       DPRINTK("mapped buffer of %d bytes for %s\n", sg_dma_len(sg),
+               qc->tf.flags & ATA_TFLAG_WRITE ? "write" : "read");
+
+       return 0;
+}
+
+/**
+ *     ata_sg_setup - DMA-map the scatter-gather table associated with a command.
+ *     @qc: Command with scatter-gather table to be mapped.
+ *
+ *     DMA-map the scatter-gather table associated with queued_cmd @qc.
+ *
+ *     LOCKING:
+ *     spin_lock_irqsave(host_set lock)
+ *
+ *     RETURNS:
+ *     Zero on success, negative on error.
+ *
+ */
+
+static int ata_sg_setup(struct ata_queued_cmd *qc)
+{
+       struct ata_port *ap = qc->ap;
+       struct scatterlist *sg = qc->__sg;
+       struct scatterlist *lsg = &sg[qc->n_elem - 1];
+       int n_elem, pre_n_elem, dir, trim_sg = 0;
+
+       VPRINTK("ENTER, ata%u\n", ap->id);
+       WARN_ON(!(qc->flags & ATA_QCFLAG_SG));
+
+       /* we must lengthen transfers to end on a 32-bit boundary */
+       qc->pad_len = lsg->length & 3;
+       if (qc->pad_len) {
+               void *pad_buf = ap->pad + (qc->tag * ATA_DMA_PAD_SZ);
+               struct scatterlist *psg = &qc->pad_sgent;
+               unsigned int offset;
+
+               WARN_ON(qc->dev->class != ATA_DEV_ATAPI);
+
+               memset(pad_buf, 0, ATA_DMA_PAD_SZ);
+
+               /*
+                * psg->page/offset are used to copy to-be-written
+                * data in this function or read data in ata_sg_clean.
+                */
+               offset = lsg->offset + lsg->length - qc->pad_len;
+               psg->page = nth_page(lsg->page, offset >> PAGE_SHIFT);
+               psg->offset = offset_in_page(offset);
+
+               if (qc->tf.flags & ATA_TFLAG_WRITE) {
+                       void *addr = kmap_atomic(psg->page, KM_IRQ0);
+                       memcpy(pad_buf, addr + psg->offset, qc->pad_len);
+                       kunmap_atomic(addr, KM_IRQ0);
+               }
+
+               sg_dma_address(psg) = ap->pad_dma + (qc->tag * ATA_DMA_PAD_SZ);
+               sg_dma_len(psg) = ATA_DMA_PAD_SZ;
+               /* trim last sg */
+               lsg->length -= qc->pad_len;
+               if (lsg->length == 0)
+                       trim_sg = 1;
+
+               DPRINTK("padding done, sg[%d].length=%u pad_len=%u\n",
+                       qc->n_elem - 1, lsg->length, qc->pad_len);
+       }
+
+       pre_n_elem = qc->n_elem;
+       if (trim_sg && pre_n_elem)
+               pre_n_elem--;
+
+       if (!pre_n_elem) {
+               n_elem = 0;
+               goto skip_map;
+       }
+
+       dir = qc->dma_dir;
+       n_elem = dma_map_sg(ap->dev, sg, pre_n_elem, dir);
+       if (n_elem < 1) {
+               /* restore last sg */
+               lsg->length += qc->pad_len;
+               return -1;
+       }
+
+       DPRINTK("%d sg elements mapped\n", n_elem);
+
+skip_map:
+       qc->n_elem = n_elem;
+
+       return 0;
+}
+
+/**
+ *     swap_buf_le16 - swap halves of 16-bit words in place
+ *     @buf:  Buffer to swap
+ *     @buf_words:  Number of 16-bit words in buffer.
+ *
+ *     Swap halves of 16-bit words if needed to convert from
+ *     little-endian byte order to native cpu byte order, or
+ *     vice-versa.
+ *
+ *     LOCKING:
+ *     Inherited from caller.
+ */
+void swap_buf_le16(u16 *buf, unsigned int buf_words)
+{
+#ifdef __BIG_ENDIAN
+       unsigned int i;
+
+       for (i = 0; i < buf_words; i++)
+               buf[i] = le16_to_cpu(buf[i]);
+#endif /* __BIG_ENDIAN */
+}
+
+/**
+ *     ata_mmio_data_xfer - Transfer data by MMIO
+ *     @adev: device for this I/O
+ *     @buf: data buffer
+ *     @buflen: buffer length
+ *     @write_data: read/write
+ *
+ *     Transfer data from/to the device data register by MMIO.
+ *
+ *     LOCKING:
+ *     Inherited from caller.
+ */
+
+void ata_mmio_data_xfer(struct ata_device *adev, unsigned char *buf,
+                       unsigned int buflen, int write_data)
+{
+       struct ata_port *ap = adev->ap;
+       unsigned int i;
+       unsigned int words = buflen >> 1;
+       u16 *buf16 = (u16 *) buf;
+       void __iomem *mmio = (void __iomem *)ap->ioaddr.data_addr;
+
+       /* Transfer multiple of 2 bytes */
+       if (write_data) {
+               for (i = 0; i < words; i++)
+                       writew(le16_to_cpu(buf16[i]), mmio);
+       } else {
+               for (i = 0; i < words; i++)
+                       buf16[i] = cpu_to_le16(readw(mmio));
+       }
+
+       /* Transfer trailing 1 byte, if any. */
+       if (unlikely(buflen & 0x01)) {
+               u16 align_buf[1] = { 0 };
+               unsigned char *trailing_buf = buf + buflen - 1;
+
+               if (write_data) {
+                       memcpy(align_buf, trailing_buf, 1);
+                       writew(le16_to_cpu(align_buf[0]), mmio);
+               } else {
+                       align_buf[0] = cpu_to_le16(readw(mmio));
+                       memcpy(trailing_buf, align_buf, 1);
+               }
+       }
+}
+
+/**
+ *     ata_pio_data_xfer - Transfer data by PIO
+ *     @adev: device to target
+ *     @buf: data buffer
+ *     @buflen: buffer length
+ *     @write_data: read/write
+ *
+ *     Transfer data from/to the device data register by PIO.
+ *
+ *     LOCKING:
+ *     Inherited from caller.
+ */
+
+void ata_pio_data_xfer(struct ata_device *adev, unsigned char *buf,
+                      unsigned int buflen, int write_data)
+{
+       struct ata_port *ap = adev->ap;
+       unsigned int words = buflen >> 1;
+
+       /* Transfer multiple of 2 bytes */
+       if (write_data)
+               outsw(ap->ioaddr.data_addr, buf, words);
+       else
+               insw(ap->ioaddr.data_addr, buf, words);
+
+       /* Transfer trailing 1 byte, if any. */
+       if (unlikely(buflen & 0x01)) {
+               u16 align_buf[1] = { 0 };
+               unsigned char *trailing_buf = buf + buflen - 1;
+
+               if (write_data) {
+                       memcpy(align_buf, trailing_buf, 1);
+                       outw(le16_to_cpu(align_buf[0]), ap->ioaddr.data_addr);
+               } else {
+                       align_buf[0] = cpu_to_le16(inw(ap->ioaddr.data_addr));
+                       memcpy(trailing_buf, align_buf, 1);
+               }
+       }
+}
+
+/**
+ *     ata_pio_data_xfer_noirq - Transfer data by PIO
+ *     @adev: device to target
+ *     @buf: data buffer
+ *     @buflen: buffer length
+ *     @write_data: read/write
+ *
+ *     Transfer data from/to the device data register by PIO. Do the
+ *     transfer with interrupts disabled.
+ *
+ *     LOCKING:
+ *     Inherited from caller.
+ */
+
+void ata_pio_data_xfer_noirq(struct ata_device *adev, unsigned char *buf,
+                                   unsigned int buflen, int write_data)
+{
+       unsigned long flags;
+       local_irq_save(flags);
+       ata_pio_data_xfer(adev, buf, buflen, write_data);
+       local_irq_restore(flags);
+}
+
+
+/**
+ *     ata_pio_sector - Transfer ATA_SECT_SIZE (512 bytes) of data.
+ *     @qc: Command on going
+ *
+ *     Transfer ATA_SECT_SIZE of data from/to the ATA device.
+ *
+ *     LOCKING:
+ *     Inherited from caller.
+ */
+
+static void ata_pio_sector(struct ata_queued_cmd *qc)
+{
+       int do_write = (qc->tf.flags & ATA_TFLAG_WRITE);
+       struct scatterlist *sg = qc->__sg;
+       struct ata_port *ap = qc->ap;
+       struct page *page;
+       unsigned int offset;
+       unsigned char *buf;
+
+       if (qc->cursect == (qc->nsect - 1))
+               ap->hsm_task_state = HSM_ST_LAST;
+
+       page = sg[qc->cursg].page;
+       offset = sg[qc->cursg].offset + qc->cursg_ofs * ATA_SECT_SIZE;
+
+       /* get the current page and offset */
+       page = nth_page(page, (offset >> PAGE_SHIFT));
+       offset %= PAGE_SIZE;
+
+       DPRINTK("data %s\n", qc->tf.flags & ATA_TFLAG_WRITE ? "write" : "read");
+
+       if (PageHighMem(page)) {
+               unsigned long flags;
+
+               /* FIXME: use a bounce buffer */
+               local_irq_save(flags);
+               buf = kmap_atomic(page, KM_IRQ0);
+
+               /* do the actual data transfer */
+               ap->ops->data_xfer(qc->dev, buf + offset, ATA_SECT_SIZE, do_write);
+
+               kunmap_atomic(buf, KM_IRQ0);
+               local_irq_restore(flags);
+       } else {
+               buf = page_address(page);
+               ap->ops->data_xfer(qc->dev, buf + offset, ATA_SECT_SIZE, do_write);
+       }
+
+       qc->cursect++;
+       qc->cursg_ofs++;
+
+       if ((qc->cursg_ofs * ATA_SECT_SIZE) == (&sg[qc->cursg])->length) {
+               qc->cursg++;
+               qc->cursg_ofs = 0;
+       }
+}
+
+/**
+ *     ata_pio_sectors - Transfer one or many 512-byte sectors.
+ *     @qc: Command on going
+ *
+ *     Transfer one or many ATA_SECT_SIZE of data from/to the
+ *     ATA device for the DRQ request.
+ *
+ *     LOCKING:
+ *     Inherited from caller.
+ */
+
+static void ata_pio_sectors(struct ata_queued_cmd *qc)
+{
+       if (is_multi_taskfile(&qc->tf)) {
+               /* READ/WRITE MULTIPLE */
+               unsigned int nsect;
+
+               WARN_ON(qc->dev->multi_count == 0);
+
+               nsect = min(qc->nsect - qc->cursect, qc->dev->multi_count);
+               while (nsect--)
+                       ata_pio_sector(qc);
+       } else
+               ata_pio_sector(qc);
+}
+
+/**
+ *     atapi_send_cdb - Write CDB bytes to hardware
+ *     @ap: Port to which ATAPI device is attached.
+ *     @qc: Taskfile currently active
+ *
+ *     When device has indicated its readiness to accept
+ *     a CDB, this function is called.  Send the CDB.
+ *
+ *     LOCKING:
+ *     caller.
+ */
+
+static void atapi_send_cdb(struct ata_port *ap, struct ata_queued_cmd *qc)
+{
+       /* send SCSI cdb */
+       DPRINTK("send cdb\n");
+       WARN_ON(qc->dev->cdb_len < 12);
+
+       ap->ops->data_xfer(qc->dev, qc->cdb, qc->dev->cdb_len, 1);
+       ata_altstatus(ap); /* flush */
+
+       switch (qc->tf.protocol) {
+       case ATA_PROT_ATAPI:
+               ap->hsm_task_state = HSM_ST;
+               break;
+       case ATA_PROT_ATAPI_NODATA:
+               ap->hsm_task_state = HSM_ST_LAST;
+               break;
+       case ATA_PROT_ATAPI_DMA:
+               ap->hsm_task_state = HSM_ST_LAST;
+               /* initiate bmdma */
+               ap->ops->bmdma_start(qc);
+               break;
+       }
+}
+
+/**
+ *     __atapi_pio_bytes - Transfer data from/to the ATAPI device.
+ *     @qc: Command on going
+ *     @bytes: number of bytes
+ *
+ *     Transfer Transfer data from/to the ATAPI device.
+ *
+ *     LOCKING:
+ *     Inherited from caller.
+ *
+ */
+
+static void __atapi_pio_bytes(struct ata_queued_cmd *qc, unsigned int bytes)
+{
+       int do_write = (qc->tf.flags & ATA_TFLAG_WRITE);
+       struct scatterlist *sg = qc->__sg;
+       struct ata_port *ap = qc->ap;
+       struct page *page;
+       unsigned char *buf;
+       unsigned int offset, count;
+
+       if (qc->curbytes + bytes >= qc->nbytes)
+               ap->hsm_task_state = HSM_ST_LAST;
+
+next_sg:
+       if (unlikely(qc->cursg >= qc->n_elem)) {
+               /*
+                * The end of qc->sg is reached and the device expects
+                * more data to transfer. In order not to overrun qc->sg
+                * and fulfill length specified in the byte count register,
+                *    - for read case, discard trailing data from the device
+                *    - for write case, padding zero data to the device
+                */
+               u16 pad_buf[1] = { 0 };
+               unsigned int words = bytes >> 1;
+               unsigned int i;
+
+               if (words) /* warning if bytes > 1 */
+                       ata_dev_printk(qc->dev, KERN_WARNING,
+                                      "%u bytes trailing data\n", bytes);
+
+               for (i = 0; i < words; i++)
+                       ap->ops->data_xfer(qc->dev, (unsigned char*)pad_buf, 2, do_write);
+
+               ap->hsm_task_state = HSM_ST_LAST;
+               return;
+       }
+
+       sg = &qc->__sg[qc->cursg];
+
+       page = sg->page;
+       offset = sg->offset + qc->cursg_ofs;
+
+       /* get the current page and offset */
+       page = nth_page(page, (offset >> PAGE_SHIFT));
+       offset %= PAGE_SIZE;
+
+       /* don't overrun current sg */
+       count = min(sg->length - qc->cursg_ofs, bytes);
+
+       /* don't cross page boundaries */
+       count = min(count, (unsigned int)PAGE_SIZE - offset);
+
+       DPRINTK("data %s\n", qc->tf.flags & ATA_TFLAG_WRITE ? "write" : "read");
+
+       if (PageHighMem(page)) {
+               unsigned long flags;
+
+               /* FIXME: use bounce buffer */
+               local_irq_save(flags);
+               buf = kmap_atomic(page, KM_IRQ0);
+
+               /* do the actual data transfer */
+               ap->ops->data_xfer(qc->dev,  buf + offset, count, do_write);
+
+               kunmap_atomic(buf, KM_IRQ0);
+               local_irq_restore(flags);
+       } else {
+               buf = page_address(page);
+               ap->ops->data_xfer(qc->dev,  buf + offset, count, do_write);
+       }
+
+       bytes -= count;
+       qc->curbytes += count;
+       qc->cursg_ofs += count;
+
+       if (qc->cursg_ofs == sg->length) {
+               qc->cursg++;
+               qc->cursg_ofs = 0;
+       }
+
+       if (bytes)
+               goto next_sg;
+}
+
+/**
+ *     atapi_pio_bytes - Transfer data from/to the ATAPI device.
+ *     @qc: Command on going
+ *
+ *     Transfer Transfer data from/to the ATAPI device.
+ *
+ *     LOCKING:
+ *     Inherited from caller.
+ */
+
+static void atapi_pio_bytes(struct ata_queued_cmd *qc)
+{
+       struct ata_port *ap = qc->ap;
+       struct ata_device *dev = qc->dev;
+       unsigned int ireason, bc_lo, bc_hi, bytes;
+       int i_write, do_write = (qc->tf.flags & ATA_TFLAG_WRITE) ? 1 : 0;
+
+       /* Abuse qc->result_tf for temp storage of intermediate TF
+        * here to save some kernel stack usage.
+        * For normal completion, qc->result_tf is not relevant. For
+        * error, qc->result_tf is later overwritten by ata_qc_complete().
+        * So, the correctness of qc->result_tf is not affected.
+        */
+       ap->ops->tf_read(ap, &qc->result_tf);
+       ireason = qc->result_tf.nsect;
+       bc_lo = qc->result_tf.lbam;
+       bc_hi = qc->result_tf.lbah;
+       bytes = (bc_hi << 8) | bc_lo;
+
+       /* shall be cleared to zero, indicating xfer of data */
+       if (ireason & (1 << 0))
+               goto err_out;
+
+       /* make sure transfer direction matches expected */
+       i_write = ((ireason & (1 << 1)) == 0) ? 1 : 0;
+       if (do_write != i_write)
+               goto err_out;
+
+       VPRINTK("ata%u: xfering %d bytes\n", ap->id, bytes);
+
+       __atapi_pio_bytes(qc, bytes);
+
+       return;
+
+err_out:
+       ata_dev_printk(dev, KERN_INFO, "ATAPI check failed\n");
+       qc->err_mask |= AC_ERR_HSM;
+       ap->hsm_task_state = HSM_ST_ERR;
+}
+
+/**
+ *     ata_hsm_ok_in_wq - Check if the qc can be handled in the workqueue.
+ *     @ap: the target ata_port
+ *     @qc: qc on going
+ *
+ *     RETURNS:
+ *     1 if ok in workqueue, 0 otherwise.
+ */
+
+static inline int ata_hsm_ok_in_wq(struct ata_port *ap, struct ata_queued_cmd *qc)
+{
+       if (qc->tf.flags & ATA_TFLAG_POLLING)
+               return 1;
+
+       if (ap->hsm_task_state == HSM_ST_FIRST) {
+               if (qc->tf.protocol == ATA_PROT_PIO &&
+                   (qc->tf.flags & ATA_TFLAG_WRITE))
+                   return 1;
+
+               if (is_atapi_taskfile(&qc->tf) &&
+                   !(qc->dev->flags & ATA_DFLAG_CDB_INTR))
+                       return 1;
+       }
+
+       return 0;
+}
+
+/**
+ *     ata_hsm_qc_complete - finish a qc running on standard HSM
+ *     @qc: Command to complete
+ *     @in_wq: 1 if called from workqueue, 0 otherwise
+ *
+ *     Finish @qc which is running on standard HSM.
+ *
+ *     LOCKING:
+ *     If @in_wq is zero, spin_lock_irqsave(host_set lock).
+ *     Otherwise, none on entry and grabs host lock.
+ */
+static void ata_hsm_qc_complete(struct ata_queued_cmd *qc, int in_wq)
+{
+       struct ata_port *ap = qc->ap;
+       unsigned long flags;
+
+       if (ap->ops->error_handler) {
+               if (in_wq) {
+                       spin_lock_irqsave(ap->lock, flags);
+
+                       /* EH might have kicked in while host_set lock
+                        * is released.
+                        */
+                       qc = ata_qc_from_tag(ap, qc->tag);
+                       if (qc) {
+                               if (likely(!(qc->err_mask & AC_ERR_HSM))) {
+                                       ata_irq_on(ap);
+                                       ata_qc_complete(qc);
+                               } else
+                                       ata_port_freeze(ap);
+                       }
+
+                       spin_unlock_irqrestore(ap->lock, flags);
+               } else {
+                       if (likely(!(qc->err_mask & AC_ERR_HSM)))
+                               ata_qc_complete(qc);
+                       else
+                               ata_port_freeze(ap);
+               }
+       } else {
+               if (in_wq) {
+                       spin_lock_irqsave(ap->lock, flags);
+                       ata_irq_on(ap);
+                       ata_qc_complete(qc);
+                       spin_unlock_irqrestore(ap->lock, flags);
+               } else
+                       ata_qc_complete(qc);
+       }
+
+       ata_altstatus(ap); /* flush */
+}
+
+/**
+ *     ata_hsm_move - move the HSM to the next state.
+ *     @ap: the target ata_port
+ *     @qc: qc on going
+ *     @status: current device status
+ *     @in_wq: 1 if called from workqueue, 0 otherwise
+ *
+ *     RETURNS:
+ *     1 when poll next status needed, 0 otherwise.
+ */
+int ata_hsm_move(struct ata_port *ap, struct ata_queued_cmd *qc,
+                u8 status, int in_wq)
+{
+       unsigned long flags = 0;
+       int poll_next;
+
+       WARN_ON((qc->flags & ATA_QCFLAG_ACTIVE) == 0);
+
+       /* Make sure ata_qc_issue_prot() does not throw things
+        * like DMA polling into the workqueue. Notice that
+        * in_wq is not equivalent to (qc->tf.flags & ATA_TFLAG_POLLING).
+        */
+       WARN_ON(in_wq != ata_hsm_ok_in_wq(ap, qc));
+
+fsm_start:
+       DPRINTK("ata%u: protocol %d task_state %d (dev_stat 0x%X)\n",
+               ap->id, qc->tf.protocol, ap->hsm_task_state, status);
+
+       switch (ap->hsm_task_state) {
+       case HSM_ST_FIRST:
+               /* Send first data block or PACKET CDB */
+
+               /* If polling, we will stay in the work queue after
+                * sending the data. Otherwise, interrupt handler
+                * takes over after sending the data.
+                */
+               poll_next = (qc->tf.flags & ATA_TFLAG_POLLING);
+
+               /* check device status */
+               if (unlikely((status & ATA_DRQ) == 0)) {
+                       /* handle BSY=0, DRQ=0 as error */
+                       if (likely(status & (ATA_ERR | ATA_DF)))
+                               /* device stops HSM for abort/error */
+                               qc->err_mask |= AC_ERR_DEV;
+                       else
+                               /* HSM violation. Let EH handle this */
+                               qc->err_mask |= AC_ERR_HSM;
+
+                       ap->hsm_task_state = HSM_ST_ERR;
+                       goto fsm_start;
+               }
+
+               /* Device should not ask for data transfer (DRQ=1)
+                * when it finds something wrong.
+                * We ignore DRQ here and stop the HSM by
+                * changing hsm_task_state to HSM_ST_ERR and
+                * let the EH abort the command or reset the device.
+                */
+               if (unlikely(status & (ATA_ERR | ATA_DF))) {
+                       printk(KERN_WARNING "ata%d: DRQ=1 with device error, dev_stat 0x%X\n",
+                              ap->id, status);
+                       qc->err_mask |= AC_ERR_HSM;
+                       ap->hsm_task_state = HSM_ST_ERR;
+                       goto fsm_start;
+               }
+
+               /* Send the CDB (atapi) or the first data block (ata pio out).
+                * During the state transition, interrupt handler shouldn't
+                * be invoked before the data transfer is complete and
+                * hsm_task_state is changed. Hence, the following locking.
+                */
+               if (in_wq)
+                       spin_lock_irqsave(ap->lock, flags);
+
+               if (qc->tf.protocol == ATA_PROT_PIO) {
+                       /* PIO data out protocol.
+                        * send first data block.
+                        */
+
+                       /* ata_pio_sectors() might change the state
+                        * to HSM_ST_LAST. so, the state is changed here
+                        * before ata_pio_sectors().
+                        */
+                       ap->hsm_task_state = HSM_ST;
+                       ata_pio_sectors(qc);
+                       ata_altstatus(ap); /* flush */
+               } else
+                       /* send CDB */
+                       atapi_send_cdb(ap, qc);
+
+               if (in_wq)
+                       spin_unlock_irqrestore(ap->lock, flags);
+
+               /* if polling, ata_pio_task() handles the rest.
+                * otherwise, interrupt handler takes over from here.
+                */
+               break;
+
+       case HSM_ST:
+               /* complete command or read/write the data register */
+               if (qc->tf.protocol == ATA_PROT_ATAPI) {
+                       /* ATAPI PIO protocol */
+                       if ((status & ATA_DRQ) == 0) {
+                               /* No more data to transfer or device error.
+                                * Device error will be tagged in HSM_ST_LAST.
+                                */
+                               ap->hsm_task_state = HSM_ST_LAST;
+                               goto fsm_start;
+                       }
+
+                       /* Device should not ask for data transfer (DRQ=1)
+                        * when it finds something wrong.
+                        * We ignore DRQ here and stop the HSM by
+                        * changing hsm_task_state to HSM_ST_ERR and
+                        * let the EH abort the command or reset the device.
+                        */
+                       if (unlikely(status & (ATA_ERR | ATA_DF))) {
+                               printk(KERN_WARNING "ata%d: DRQ=1 with device error, dev_stat 0x%X\n",
+                                      ap->id, status);
+                               qc->err_mask |= AC_ERR_HSM;
+                               ap->hsm_task_state = HSM_ST_ERR;
+                               goto fsm_start;
+                       }
+
+                       atapi_pio_bytes(qc);
+
+                       if (unlikely(ap->hsm_task_state == HSM_ST_ERR))
+                               /* bad ireason reported by device */
+                               goto fsm_start;
+
+               } else {
+                       /* ATA PIO protocol */
+                       if (unlikely((status & ATA_DRQ) == 0)) {
+                               /* handle BSY=0, DRQ=0 as error */
+                               if (likely(status & (ATA_ERR | ATA_DF)))
+                                       /* device stops HSM for abort/error */
+                                       qc->err_mask |= AC_ERR_DEV;
+                               else
+                                       /* HSM violation. Let EH handle this */
+                                       qc->err_mask |= AC_ERR_HSM;
+
+                               ap->hsm_task_state = HSM_ST_ERR;
+                               goto fsm_start;
+                       }
+
+                       /* For PIO reads, some devices may ask for
+                        * data transfer (DRQ=1) alone with ERR=1.
+                        * We respect DRQ here and transfer one
+                        * block of junk data before changing the
+                        * hsm_task_state to HSM_ST_ERR.
+                        *
+                        * For PIO writes, ERR=1 DRQ=1 doesn't make
+                        * sense since the data block has been
+                        * transferred to the device.
+                        */
+                       if (unlikely(status & (ATA_ERR | ATA_DF))) {
+                               /* data might be corrputed */
+                               qc->err_mask |= AC_ERR_DEV;
+
+                               if (!(qc->tf.flags & ATA_TFLAG_WRITE)) {
+                                       ata_pio_sectors(qc);
+                                       ata_altstatus(ap);
+                                       status = ata_wait_idle(ap);
+                               }
+
+                               if (status & (ATA_BUSY | ATA_DRQ))
+                                       qc->err_mask |= AC_ERR_HSM;
+
+                               /* ata_pio_sectors() might change the
+                                * state to HSM_ST_LAST. so, the state
+                                * is changed after ata_pio_sectors().
+                                */
+                               ap->hsm_task_state = HSM_ST_ERR;
+                               goto fsm_start;
+                       }
+
+                       ata_pio_sectors(qc);
+
+                       if (ap->hsm_task_state == HSM_ST_LAST &&
+                           (!(qc->tf.flags & ATA_TFLAG_WRITE))) {
+                               /* all data read */
+                               ata_altstatus(ap);
+                               status = ata_wait_idle(ap);
+                               goto fsm_start;
+                       }
+               }
+
+               ata_altstatus(ap); /* flush */
+               poll_next = 1;
+               break;
+
+       case HSM_ST_LAST:
+               if (unlikely(!ata_ok(status))) {
+                       qc->err_mask |= __ac_err_mask(status);
+                       ap->hsm_task_state = HSM_ST_ERR;
+                       goto fsm_start;
+               }
+
+               /* no more data to transfer */
+               DPRINTK("ata%u: dev %u command complete, drv_stat 0x%x\n",
+                       ap->id, qc->dev->devno, status);
+
+               WARN_ON(qc->err_mask);
+
+               ap->hsm_task_state = HSM_ST_IDLE;
+
+               /* complete taskfile transaction */
+               ata_hsm_qc_complete(qc, in_wq);
+
+               poll_next = 0;
+               break;
+
+       case HSM_ST_ERR:
+               /* make sure qc->err_mask is available to
+                * know what's wrong and recover
+                */
+               WARN_ON(qc->err_mask == 0);
+
+               ap->hsm_task_state = HSM_ST_IDLE;
+
+               /* complete taskfile transaction */
+               ata_hsm_qc_complete(qc, in_wq);
+
+               poll_next = 0;
+               break;
+       default:
+               poll_next = 0;
+               BUG();
+       }
+
+       return poll_next;
+}
+
+static void ata_pio_task(void *_data)
+{
+       struct ata_queued_cmd *qc = _data;
+       struct ata_port *ap = qc->ap;
+       u8 status;
+       int poll_next;
+
+fsm_start:
+       WARN_ON(ap->hsm_task_state == HSM_ST_IDLE);
+
+       /*
+        * This is purely heuristic.  This is a fast path.
+        * Sometimes when we enter, BSY will be cleared in
+        * a chk-status or two.  If not, the drive is probably seeking
+        * or something.  Snooze for a couple msecs, then
+        * chk-status again.  If still busy, queue delayed work.
+        */
+       status = ata_busy_wait(ap, ATA_BUSY, 5);
+       if (status & ATA_BUSY) {
+               msleep(2);
+               status = ata_busy_wait(ap, ATA_BUSY, 10);
+               if (status & ATA_BUSY) {
+                       ata_port_queue_task(ap, ata_pio_task, qc, ATA_SHORT_PAUSE);
+                       return;
+               }
+       }
+
+       /* move the HSM */
+       poll_next = ata_hsm_move(ap, qc, status, 1);
+
+       /* another command or interrupt handler
+        * may be running at this point.
+        */
+       if (poll_next)
+               goto fsm_start;
+}
+
+/**
+ *     ata_qc_new - Request an available ATA command, for queueing
+ *     @ap: Port associated with device @dev
+ *     @dev: Device from whom we request an available command structure
+ *
+ *     LOCKING:
+ *     None.
+ */
+
+static struct ata_queued_cmd *ata_qc_new(struct ata_port *ap)
+{
+       struct ata_queued_cmd *qc = NULL;
+       unsigned int i;
+
+       /* no command while frozen */
+       if (unlikely(ap->pflags & ATA_PFLAG_FROZEN))
+               return NULL;
+
+       /* the last tag is reserved for internal command. */
+       for (i = 0; i < ATA_MAX_QUEUE - 1; i++)
+               if (!test_and_set_bit(i, &ap->qc_allocated)) {
+                       qc = __ata_qc_from_tag(ap, i);
+                       break;
+               }
+
+       if (qc)
+               qc->tag = i;
+
+       return qc;
+}
+
+/**
+ *     ata_qc_new_init - Request an available ATA command, and initialize it
+ *     @dev: Device from whom we request an available command structure
+ *
+ *     LOCKING:
+ *     None.
+ */
+
+struct ata_queued_cmd *ata_qc_new_init(struct ata_device *dev)
+{
+       struct ata_port *ap = dev->ap;
+       struct ata_queued_cmd *qc;
+
+       qc = ata_qc_new(ap);
+       if (qc) {
+               qc->scsicmd = NULL;
+               qc->ap = ap;
+               qc->dev = dev;
+
+               ata_qc_reinit(qc);
+       }
+
+       return qc;
+}
+
+/**
+ *     ata_qc_free - free unused ata_queued_cmd
+ *     @qc: Command to complete
+ *
+ *     Designed to free unused ata_queued_cmd object
+ *     in case something prevents using it.
+ *
+ *     LOCKING:
+ *     spin_lock_irqsave(host_set lock)
+ */
+void ata_qc_free(struct ata_queued_cmd *qc)
+{
+       struct ata_port *ap = qc->ap;
+       unsigned int tag;
+
+       WARN_ON(qc == NULL);    /* ata_qc_from_tag _might_ return NULL */
+
+       qc->flags = 0;
+       tag = qc->tag;
+       if (likely(ata_tag_valid(tag))) {
+               qc->tag = ATA_TAG_POISON;
+               clear_bit(tag, &ap->qc_allocated);
+       }
+}
+
+void __ata_qc_complete(struct ata_queued_cmd *qc)
+{
+       struct ata_port *ap = qc->ap;
+
+       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);
+
+       /* command should be marked inactive atomically with qc completion */
+       if (qc->tf.protocol == ATA_PROT_NCQ)
+               ap->sactive &= ~(1 << qc->tag);
+       else
+               ap->active_tag = ATA_TAG_POISON;
+
+       /* atapi: mark qc as inactive to prevent the interrupt handler
+        * from completing the command twice later, before the error handler
+        * is called. (when rc != 0 and atapi request sense is needed)
+        */
+       qc->flags &= ~ATA_QCFLAG_ACTIVE;
+       ap->qc_active &= ~(1 << qc->tag);
+
+       /* call completion callback */
+       qc->complete_fn(qc);
+}
+
+/**
+ *     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)
+ */
+void ata_qc_complete(struct ata_queued_cmd *qc)
+{
+       struct ata_port *ap = qc->ap;
+
+       /* XXX: New EH and old EH use different mechanisms to
+        * synchronize EH with regular execution path.
+        *
+        * In new EH, a failed qc is marked with ATA_QCFLAG_FAILED.
+        * Normal execution path is responsible for not accessing a
+        * failed qc.  libata core enforces the rule by returning NULL
+        * from ata_qc_from_tag() for failed qcs.
+        *
+        * Old EH depends on ata_qc_complete() nullifying completion
+        * requests if ATA_QCFLAG_EH_SCHEDULED is set.  Old EH does
+        * not synchronize with interrupt handler.  Only PIO task is
+        * taken care of.
+        */
+       if (ap->ops->error_handler) {
+               WARN_ON(ap->pflags & ATA_PFLAG_FROZEN);
+
+               if (unlikely(qc->err_mask))
+                       qc->flags |= ATA_QCFLAG_FAILED;
+
+               if (unlikely(qc->flags & ATA_QCFLAG_FAILED)) {
+                       if (!ata_tag_internal(qc->tag)) {
+                               /* always fill result TF for failed qc */
+                               ap->ops->tf_read(ap, &qc->result_tf);
+                               ata_qc_schedule_eh(qc);
+                               return;
+                       }
+               }
+
+               /* read result TF if requested */
+               if (qc->flags & ATA_QCFLAG_RESULT_TF)
+                       ap->ops->tf_read(ap, &qc->result_tf);
+
+               __ata_qc_complete(qc);
+       } else {
+               if (qc->flags & ATA_QCFLAG_EH_SCHEDULED)
+                       return;
+
+               /* read result TF if failed or requested */
+               if (qc->err_mask || qc->flags & ATA_QCFLAG_RESULT_TF)
+                       ap->ops->tf_read(ap, &qc->result_tf);
+
+               __ata_qc_complete(qc);
+       }
+}
+
+/**
+ *     ata_qc_complete_multiple - Complete multiple qcs successfully
+ *     @ap: port in question
+ *     @qc_active: new qc_active mask
+ *     @finish_qc: LLDD callback invoked before completing a qc
+ *
+ *     Complete in-flight commands.  This functions is meant to be
+ *     called from low-level driver's interrupt routine to complete
+ *     requests normally.  ap->qc_active and @qc_active is compared
+ *     and commands are completed accordingly.
+ *
+ *     LOCKING:
+ *     spin_lock_irqsave(host_set lock)
+ *
+ *     RETURNS:
+ *     Number of completed commands on success, -errno otherwise.
+ */
+int ata_qc_complete_multiple(struct ata_port *ap, u32 qc_active,
+                            void (*finish_qc)(struct ata_queued_cmd *))
+{
+       int nr_done = 0;
+       u32 done_mask;
+       int i;
+
+       done_mask = ap->qc_active ^ qc_active;
+
+       if (unlikely(done_mask & qc_active)) {
+               ata_port_printk(ap, KERN_ERR, "illegal qc_active transition "
+                               "(%08x->%08x)\n", ap->qc_active, qc_active);
+               return -EINVAL;
+       }
+
+       for (i = 0; i < ATA_MAX_QUEUE; i++) {
+               struct ata_queued_cmd *qc;
+
+               if (!(done_mask & (1 << i)))
+                       continue;
+
+               if ((qc = ata_qc_from_tag(ap, i))) {
+                       if (finish_qc)
+                               finish_qc(qc);
+                       ata_qc_complete(qc);
+                       nr_done++;
+               }
+       }
+
+       return nr_done;
+}
+
+static inline int ata_should_dma_map(struct ata_queued_cmd *qc)
+{
+       struct ata_port *ap = qc->ap;
+
+       switch (qc->tf.protocol) {
+       case ATA_PROT_NCQ:
+       case ATA_PROT_DMA:
+       case ATA_PROT_ATAPI_DMA:
+               return 1;
+
+       case ATA_PROT_ATAPI:
+       case ATA_PROT_PIO:
+               if (ap->flags & ATA_FLAG_PIO_DMA)
+                       return 1;
+
+               /* fall through */
+
+       default:
+               return 0;
+       }
+
+       /* never reached */
+}
+
+/**
+ *     ata_qc_issue - issue taskfile to device
+ *     @qc: command to issue to device
+ *
+ *     Prepare an ATA command to submission to device.
+ *     This includes mapping the data into a DMA-able
+ *     area, filling in the S/G table, and finally
+ *     writing the taskfile to hardware, starting the command.
+ *
+ *     LOCKING:
+ *     spin_lock_irqsave(host_set lock)
+ */
+void ata_qc_issue(struct ata_queued_cmd *qc)
+{
+       struct ata_port *ap = qc->ap;
+
+       /* Make sure only one non-NCQ command is outstanding.  The
+        * check is skipped for old EH because it reuses active qc to
+        * request ATAPI sense.
+        */
+       WARN_ON(ap->ops->error_handler && ata_tag_valid(ap->active_tag));
+
+       if (qc->tf.protocol == ATA_PROT_NCQ) {
+               WARN_ON(ap->sactive & (1 << qc->tag));
+               ap->sactive |= 1 << qc->tag;
+       } else {
+               WARN_ON(ap->sactive);
+               ap->active_tag = qc->tag;
+       }
+
+       qc->flags |= ATA_QCFLAG_ACTIVE;
+       ap->qc_active |= 1 << qc->tag;
+
+       if (ata_should_dma_map(qc)) {
+               if (qc->flags & ATA_QCFLAG_SG) {
+                       if (ata_sg_setup(qc))
+                               goto sg_err;
+               } else if (qc->flags & ATA_QCFLAG_SINGLE) {
+                       if (ata_sg_setup_one(qc))
+                               goto sg_err;
+               }
+       } else {
+               qc->flags &= ~ATA_QCFLAG_DMAMAP;
+       }
+
+       ap->ops->qc_prep(qc);
+
+       qc->err_mask |= ap->ops->qc_issue(qc);
+       if (unlikely(qc->err_mask))
+               goto err;
+       return;
+
+sg_err:
+       qc->flags &= ~ATA_QCFLAG_DMAMAP;
+       qc->err_mask |= AC_ERR_SYSTEM;
+err:
+       ata_qc_complete(qc);
+}
+
+/**
+ *     ata_qc_issue_prot - issue taskfile to device in proto-dependent manner
+ *     @qc: command to issue to device
+ *
+ *     Using various libata functions and hooks, this function
+ *     starts an ATA command.  ATA commands are grouped into
+ *     classes called "protocols", and issuing each type of protocol
+ *     is slightly different.
+ *
+ *     May be used as the qc_issue() entry in ata_port_operations.
+ *
+ *     LOCKING:
+ *     spin_lock_irqsave(host_set lock)
+ *
+ *     RETURNS:
+ *     Zero on success, AC_ERR_* mask on failure
+ */
+
+unsigned int ata_qc_issue_prot(struct ata_queued_cmd *qc)
+{
+       struct ata_port *ap = qc->ap;
+
+       /* Use polling pio if the LLD doesn't handle
+        * interrupt driven pio and atapi CDB interrupt.
+        */
+       if (ap->flags & ATA_FLAG_PIO_POLLING) {
+               switch (qc->tf.protocol) {
+               case ATA_PROT_PIO:
+               case ATA_PROT_ATAPI:
+               case ATA_PROT_ATAPI_NODATA:
+                       qc->tf.flags |= ATA_TFLAG_POLLING;
+                       break;
+               case ATA_PROT_ATAPI_DMA:
+                       if (qc->dev->flags & ATA_DFLAG_CDB_INTR)
+                               /* see ata_dma_blacklisted() */
+                               BUG();
+                       break;
+               default:
+                       break;
+               }
+       }
+
+       /* select the device */
+       ata_dev_select(ap, qc->dev->devno, 1, 0);
+
+       /* start the command */
+       switch (qc->tf.protocol) {
+       case ATA_PROT_NODATA:
+               if (qc->tf.flags & ATA_TFLAG_POLLING)
+                       ata_qc_set_polling(qc);
+
+               ata_tf_to_host(ap, &qc->tf);
+               ap->hsm_task_state = HSM_ST_LAST;
+
+               if (qc->tf.flags & ATA_TFLAG_POLLING)
+                       ata_port_queue_task(ap, ata_pio_task, qc, 0);
+
+               break;
+
+       case ATA_PROT_DMA:
+               WARN_ON(qc->tf.flags & ATA_TFLAG_POLLING);
+
+               ap->ops->tf_load(ap, &qc->tf);   /* load tf registers */
+               ap->ops->bmdma_setup(qc);           /* set up bmdma */
+               ap->ops->bmdma_start(qc);           /* initiate bmdma */
+               ap->hsm_task_state = HSM_ST_LAST;
+               break;
+
+       case ATA_PROT_PIO:
+               if (qc->tf.flags & ATA_TFLAG_POLLING)
+                       ata_qc_set_polling(qc);
+
+               ata_tf_to_host(ap, &qc->tf);
+
+               if (qc->tf.flags & ATA_TFLAG_WRITE) {
+                       /* PIO data out protocol */
+                       ap->hsm_task_state = HSM_ST_FIRST;
+                       ata_port_queue_task(ap, ata_pio_task, qc, 0);
+
+                       /* always send first data block using
+                        * the ata_pio_task() codepath.
+                        */
+               } else {
+                       /* PIO data in protocol */
+                       ap->hsm_task_state = HSM_ST;
+
+                       if (qc->tf.flags & ATA_TFLAG_POLLING)
+                               ata_port_queue_task(ap, ata_pio_task, qc, 0);
+
+                       /* if polling, ata_pio_task() handles the rest.
+                        * otherwise, interrupt handler takes over from here.
+                        */
+               }
+
+               break;
+
+       case ATA_PROT_ATAPI:
+       case ATA_PROT_ATAPI_NODATA:
+               if (qc->tf.flags & ATA_TFLAG_POLLING)
+                       ata_qc_set_polling(qc);
+
+               ata_tf_to_host(ap, &qc->tf);
+
+               ap->hsm_task_state = HSM_ST_FIRST;
+
+               /* send cdb by polling if no cdb interrupt */
+               if ((!(qc->dev->flags & ATA_DFLAG_CDB_INTR)) ||
+                   (qc->tf.flags & ATA_TFLAG_POLLING))
+                       ata_port_queue_task(ap, ata_pio_task, qc, 0);
+               break;
+
+       case ATA_PROT_ATAPI_DMA:
+               WARN_ON(qc->tf.flags & ATA_TFLAG_POLLING);
+
+               ap->ops->tf_load(ap, &qc->tf);   /* load tf registers */
+               ap->ops->bmdma_setup(qc);           /* set up bmdma */
+               ap->hsm_task_state = HSM_ST_FIRST;
+
+               /* send cdb by polling if no cdb interrupt */
+               if (!(qc->dev->flags & ATA_DFLAG_CDB_INTR))
+                       ata_port_queue_task(ap, ata_pio_task, qc, 0);
+               break;
+
+       default:
+               WARN_ON(1);
+               return AC_ERR_SYSTEM;
+       }
+
+       return 0;
+}
+
+/**
+ *     ata_host_intr - Handle host interrupt for given (port, task)
+ *     @ap: Port on which interrupt arrived (possibly...)
+ *     @qc: Taskfile currently active in engine
+ *
+ *     Handle host interrupt for given queued command.  Currently,
+ *     only DMA interrupts are handled.  All other commands are
+ *     handled via polling with interrupts disabled (nIEN bit).
+ *
+ *     LOCKING:
+ *     spin_lock_irqsave(host_set lock)
+ *
+ *     RETURNS:
+ *     One if interrupt was handled, zero if not (shared irq).
+ */
+
+inline unsigned int ata_host_intr (struct ata_port *ap,
+                                  struct ata_queued_cmd *qc)
+{
+       u8 status, host_stat = 0;
+
+       VPRINTK("ata%u: protocol %d task_state %d\n",
+               ap->id, qc->tf.protocol, ap->hsm_task_state);
+
+       /* Check whether we are expecting interrupt in this state */
+       switch (ap->hsm_task_state) {
+       case HSM_ST_FIRST:
+               /* Some pre-ATAPI-4 devices assert INTRQ
+                * at this state when ready to receive CDB.
+                */
+
+               /* Check the ATA_DFLAG_CDB_INTR flag is enough here.
+                * The flag was turned on only for atapi devices.
+                * No need to check is_atapi_taskfile(&qc->tf) again.
+                */
+               if (!(qc->dev->flags & ATA_DFLAG_CDB_INTR))
+                       goto idle_irq;
+               break;
+       case HSM_ST_LAST:
+               if (qc->tf.protocol == ATA_PROT_DMA ||
+                   qc->tf.protocol == ATA_PROT_ATAPI_DMA) {
+                       /* check status of DMA engine */
+                       host_stat = ap->ops->bmdma_status(ap);
+                       VPRINTK("ata%u: host_stat 0x%X\n", ap->id, host_stat);
+
+                       /* if it's not our irq... */
+                       if (!(host_stat & ATA_DMA_INTR))
+                               goto idle_irq;
+
+                       /* before we do anything else, clear DMA-Start bit */
+                       ap->ops->bmdma_stop(qc);
+
+                       if (unlikely(host_stat & ATA_DMA_ERR)) {
+                               /* error when transfering data to/from memory */
+                               qc->err_mask |= AC_ERR_HOST_BUS;
+                               ap->hsm_task_state = HSM_ST_ERR;
+                       }
+               }
+               break;
+       case HSM_ST:
+               break;
+       default:
+               goto idle_irq;
+       }
+
+       /* check altstatus */
+       status = ata_altstatus(ap);
+       if (status & ATA_BUSY)
+               goto idle_irq;
+
+       /* check main status, clearing INTRQ */
+       status = ata_chk_status(ap);
+       if (unlikely(status & ATA_BUSY))
+               goto idle_irq;
+
+       /* ack bmdma irq events */
+       ap->ops->irq_clear(ap);
+
+       ata_hsm_move(ap, qc, status, 0);
+       return 1;       /* irq handled */
+
+idle_irq:
+       ap->stats.idle_irq++;
+
+#ifdef ATA_IRQ_TRAP
+       if ((ap->stats.idle_irq % 1000) == 0) {
+               ata_irq_ack(ap, 0); /* debug trap */
+               ata_port_printk(ap, KERN_WARNING, "irq trap\n");
+               return 1;
+       }
+#endif
+       return 0;       /* irq not handled */
+}
+
+/**
+ *     ata_interrupt - Default ATA host interrupt handler
+ *     @irq: irq line (unused)
+ *     @dev_instance: pointer to our ata_host_set information structure
+ *     @regs: unused
+ *
+ *     Default interrupt handler for PCI IDE devices.  Calls
+ *     ata_host_intr() for each port that is not disabled.
+ *
+ *     LOCKING:
+ *     Obtains host_set lock during operation.
+ *
+ *     RETURNS:
+ *     IRQ_NONE or IRQ_HANDLED.
+ */
+
+irqreturn_t ata_interrupt (int irq, void *dev_instance, struct pt_regs *regs)
+{
+       struct ata_host_set *host_set = dev_instance;
+       unsigned int i;
+       unsigned int handled = 0;
+       unsigned long flags;
+
+       /* TODO: make _irqsave conditional on x86 PCI IDE legacy mode */
+       spin_lock_irqsave(&host_set->lock, flags);
+
+       for (i = 0; i < host_set->n_ports; i++) {
+               struct ata_port *ap;
+
+               ap = host_set->ports[i];
+               if (ap &&
+                   !(ap->flags & ATA_FLAG_DISABLED)) {
+                       struct ata_queued_cmd *qc;
+
+                       qc = ata_qc_from_tag(ap, ap->active_tag);
+                       if (qc && (!(qc->tf.flags & ATA_TFLAG_POLLING)) &&
+                           (qc->flags & ATA_QCFLAG_ACTIVE))
+                               handled |= ata_host_intr(ap, qc);
+               }
+       }
+
+       spin_unlock_irqrestore(&host_set->lock, flags);
+
+       return IRQ_RETVAL(handled);
+}
+
+/**
+ *     sata_scr_valid - test whether SCRs are accessible
+ *     @ap: ATA port to test SCR accessibility for
+ *
+ *     Test whether SCRs are accessible for @ap.
+ *
+ *     LOCKING:
+ *     None.
+ *
+ *     RETURNS:
+ *     1 if SCRs are accessible, 0 otherwise.
+ */
+int sata_scr_valid(struct ata_port *ap)
+{
+       return ap->cbl == ATA_CBL_SATA && ap->ops->scr_read;
+}
+
+/**
+ *     sata_scr_read - read SCR register of the specified port
+ *     @ap: ATA port to read SCR for
+ *     @reg: SCR to read
+ *     @val: Place to store read value
+ *
+ *     Read SCR register @reg of @ap into *@val.  This function is
+ *     guaranteed to succeed if the cable type of the port is SATA
+ *     and the port implements ->scr_read.
+ *
+ *     LOCKING:
+ *     None.
+ *
+ *     RETURNS:
+ *     0 on success, negative errno on failure.
+ */
+int sata_scr_read(struct ata_port *ap, int reg, u32 *val)
+{
+       if (sata_scr_valid(ap)) {
+               *val = ap->ops->scr_read(ap, reg);
+               return 0;
+       }
+       return -EOPNOTSUPP;
+}
+
+/**
+ *     sata_scr_write - write SCR register of the specified port
+ *     @ap: ATA port to write SCR for
+ *     @reg: SCR to write
+ *     @val: value to write
+ *
+ *     Write @val to SCR register @reg of @ap.  This function is
+ *     guaranteed to succeed if the cable type of the port is SATA
+ *     and the port implements ->scr_read.
+ *
+ *     LOCKING:
+ *     None.
+ *
+ *     RETURNS:
+ *     0 on success, negative errno on failure.
+ */
+int sata_scr_write(struct ata_port *ap, int reg, u32 val)
+{
+       if (sata_scr_valid(ap)) {
+               ap->ops->scr_write(ap, reg, val);
+               return 0;
+       }
+       return -EOPNOTSUPP;
+}
+
+/**
+ *     sata_scr_write_flush - write SCR register of the specified port and flush
+ *     @ap: ATA port to write SCR for
+ *     @reg: SCR to write
+ *     @val: value to write
+ *
+ *     This function is identical to sata_scr_write() except that this
+ *     function performs flush after writing to the register.
+ *
+ *     LOCKING:
+ *     None.
+ *
+ *     RETURNS:
+ *     0 on success, negative errno on failure.
+ */
+int sata_scr_write_flush(struct ata_port *ap, int reg, u32 val)
+{
+       if (sata_scr_valid(ap)) {
+               ap->ops->scr_write(ap, reg, val);
+               ap->ops->scr_read(ap, reg);
+               return 0;
+       }
+       return -EOPNOTSUPP;
+}
+
+/**
+ *     ata_port_online - test whether the given port is online
+ *     @ap: ATA port to test
+ *
+ *     Test whether @ap is online.  Note that this function returns 0
+ *     if online status of @ap cannot be obtained, so
+ *     ata_port_online(ap) != !ata_port_offline(ap).
+ *
+ *     LOCKING:
+ *     None.
+ *
+ *     RETURNS:
+ *     1 if the port online status is available and online.
+ */
+int ata_port_online(struct ata_port *ap)
+{
+       u32 sstatus;
+
+       if (!sata_scr_read(ap, SCR_STATUS, &sstatus) && (sstatus & 0xf) == 0x3)
+               return 1;
+       return 0;
+}
+
+/**
+ *     ata_port_offline - test whether the given port is offline
+ *     @ap: ATA port to test
+ *
+ *     Test whether @ap is offline.  Note that this function returns
+ *     0 if offline status of @ap cannot be obtained, so
+ *     ata_port_online(ap) != !ata_port_offline(ap).
+ *
+ *     LOCKING:
+ *     None.
+ *
+ *     RETURNS:
+ *     1 if the port offline status is available and offline.
+ */
+int ata_port_offline(struct ata_port *ap)
+{
+       u32 sstatus;
+
+       if (!sata_scr_read(ap, SCR_STATUS, &sstatus) && (sstatus & 0xf) != 0x3)
+               return 1;
+       return 0;
+}
+
+int ata_flush_cache(struct ata_device *dev)
+{
+       unsigned int err_mask;
+       u8 cmd;
+
+       if (!ata_try_flush_cache(dev))
+               return 0;
+
+       if (ata_id_has_flush_ext(dev->id))
+               cmd = ATA_CMD_FLUSH_EXT;
+       else
+               cmd = ATA_CMD_FLUSH;
+
+       err_mask = ata_do_simple_cmd(dev, cmd);
+       if (err_mask) {
+               ata_dev_printk(dev, KERN_ERR, "failed to flush cache\n");
+               return -EIO;
+       }
+
+       return 0;
+}
+
+static int ata_host_set_request_pm(struct ata_host_set *host_set,
+                                  pm_message_t mesg, unsigned int action,
+                                  unsigned int ehi_flags, int wait)
+{
+       unsigned long flags;
+       int i, rc;
+
+       for (i = 0; i < host_set->n_ports; i++) {
+               struct ata_port *ap = host_set->ports[i];
+
+               /* Previous resume operation might still be in
+                * progress.  Wait for PM_PENDING to clear.
+                */
+               if (ap->pflags & ATA_PFLAG_PM_PENDING) {
+                       ata_port_wait_eh(ap);
+                       WARN_ON(ap->pflags & ATA_PFLAG_PM_PENDING);
+               }
+
+               /* request PM ops to EH */
+               spin_lock_irqsave(ap->lock, flags);
+
+               ap->pm_mesg = mesg;
+               if (wait) {
+                       rc = 0;
+                       ap->pm_result = &rc;
+               }
+
+               ap->pflags |= ATA_PFLAG_PM_PENDING;
+               ap->eh_info.action |= action;
+               ap->eh_info.flags |= ehi_flags;
+
+               ata_port_schedule_eh(ap);
+
+               spin_unlock_irqrestore(ap->lock, flags);
+
+               /* wait and check result */
+               if (wait) {
+                       ata_port_wait_eh(ap);
+                       WARN_ON(ap->pflags & ATA_PFLAG_PM_PENDING);
+                       if (rc)
+                               return rc;
+               }
+       }
+
+       return 0;
+}
+
+/**
+ *     ata_host_set_suspend - suspend host_set
+ *     @host_set: host_set to suspend
+ *     @mesg: PM message
+ *
+ *     Suspend @host_set.  Actual operation is performed by EH.  This
+ *     function requests EH to perform PM operations and waits for EH
+ *     to finish.
+ *
+ *     LOCKING:
+ *     Kernel thread context (may sleep).
+ *
+ *     RETURNS:
+ *     0 on success, -errno on failure.
+ */
+int ata_host_set_suspend(struct ata_host_set *host_set, pm_message_t mesg)
+{
+       int i, j, rc;
+
+       rc = ata_host_set_request_pm(host_set, mesg, 0, ATA_EHI_QUIET, 1);
+       if (rc)
+               goto fail;
+
+       /* EH is quiescent now.  Fail if we have any ready device.
+        * This happens if hotplug occurs between completion of device
+        * suspension and here.
+        */
+       for (i = 0; i < host_set->n_ports; i++) {
+               struct ata_port *ap = host_set->ports[i];
+
+               for (j = 0; j < ATA_MAX_DEVICES; j++) {
+                       struct ata_device *dev = &ap->device[j];
+
+                       if (ata_dev_ready(dev)) {
+                               ata_port_printk(ap, KERN_WARNING,
+                                               "suspend failed, device %d "
+                                               "still active\n", dev->devno);
+                               rc = -EBUSY;
+                               goto fail;
+                       }
+               }
+       }
+
+       host_set->dev->power.power_state = mesg;
+       return 0;
+
+ fail:
+       ata_host_set_resume(host_set);
+       return rc;
+}
+
+/**
+ *     ata_host_set_resume - resume host_set
+ *     @host_set: host_set to resume
+ *
+ *     Resume @host_set.  Actual operation is performed by EH.  This
+ *     function requests EH to perform PM operations and returns.
+ *     Note that all resume operations are performed parallely.
+ *
+ *     LOCKING:
+ *     Kernel thread context (may sleep).
+ */
+void ata_host_set_resume(struct ata_host_set *host_set)
+{
+       ata_host_set_request_pm(host_set, PMSG_ON, ATA_EH_SOFTRESET,
+                               ATA_EHI_NO_AUTOPSY | ATA_EHI_QUIET, 0);
+       host_set->dev->power.power_state = PMSG_ON;
+}
+
+/**
+ *     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->dev;
+       int rc;
+
+       ap->prd = dma_alloc_coherent(dev, ATA_PRD_TBL_SZ, &ap->prd_dma, GFP_KERNEL);
+       if (!ap->prd)
+               return -ENOMEM;
+
+       rc = ata_pad_alloc(ap, dev);
+       if (rc) {
+               dma_free_coherent(dev, ATA_PRD_TBL_SZ, ap->prd, ap->prd_dma);
+               return rc;
+       }
+
+       DPRINTK("prd alloc, virt %p, dma %llx\n", ap->prd, (unsigned long long) ap->prd_dma);
+
+       return 0;
+}
+
+
+/**
+ *     ata_port_stop - Undo ata_port_start()
+ *     @ap: Port to shut down
+ *
+ *     Frees the PRD table.
+ *
+ *     May be used as the port_stop() entry in ata_port_operations.
+ *
+ *     LOCKING:
+ *     Inherited from caller.
+ */
+
+void ata_port_stop (struct ata_port *ap)
+{
+       struct device *dev = ap->dev;
+
+       dma_free_coherent(dev, ATA_PRD_TBL_SZ, ap->prd, ap->prd_dma);
+       ata_pad_free(ap, dev);
+}
+
+void ata_host_stop (struct ata_host_set *host_set)
+{
+       if (host_set->mmio_base)
+               iounmap(host_set->mmio_base);
+}
+
+/**
+ *     ata_dev_init - Initialize an ata_device structure
+ *     @dev: Device structure to initialize
+ *
+ *     Initialize @dev in preparation for probing.
+ *
+ *     LOCKING:
+ *     Inherited from caller.
+ */
+void ata_dev_init(struct ata_device *dev)
+{
+       struct ata_port *ap = dev->ap;
+       unsigned long flags;
+
+       /* SATA spd limit is bound to the first device */
+       ap->sata_spd_limit = ap->hw_sata_spd_limit;
+
+       /* High bits of dev->flags are used to record warm plug
+        * requests which occur asynchronously.  Synchronize using
+        * host_set lock.
+        */
+       spin_lock_irqsave(ap->lock, flags);
+       dev->flags &= ~ATA_DFLAG_INIT_MASK;
+       spin_unlock_irqrestore(ap->lock, flags);
+
+       memset((void *)dev + ATA_DEVICE_CLEAR_OFFSET, 0,
+              sizeof(*dev) - ATA_DEVICE_CLEAR_OFFSET);
+       dev->pio_mask = UINT_MAX;
+       dev->mwdma_mask = UINT_MAX;
+       dev->udma_mask = UINT_MAX;
+}
+
+/**
+ *     ata_port_init - Initialize an ata_port structure
+ *     @ap: Structure to initialize
+ *     @host_set: Collection of hosts to which @ap belongs
+ *     @ent: Probe information provided by low-level driver
+ *     @port_no: Port number associated with this ata_port
+ *
+ *     Initialize a new ata_port structure.
+ *
+ *     LOCKING:
+ *     Inherited from caller.
+ */
+void ata_port_init(struct ata_port *ap, struct ata_host_set *host_set,
+                  const struct ata_probe_ent *ent, unsigned int port_no)
+{
+       unsigned int i;
+
+       ap->lock = &host_set->lock;
+       ap->flags = ATA_FLAG_DISABLED;
+       ap->id = ata_unique_id++;
+       ap->ctl = ATA_DEVCTL_OBS;
+       ap->host_set = host_set;
+       ap->dev = ent->dev;
+       ap->port_no = port_no;
+       ap->pio_mask = ent->pio_mask;
+       ap->mwdma_mask = ent->mwdma_mask;
+       ap->udma_mask = ent->udma_mask;
+       ap->flags |= ent->host_flags;
+       ap->ops = ent->port_ops;
+       ap->hw_sata_spd_limit = UINT_MAX;
+       ap->active_tag = ATA_TAG_POISON;
+       ap->last_ctl = 0xFF;
+
+#if defined(ATA_VERBOSE_DEBUG)
+       /* turn on all debugging levels */
+       ap->msg_enable = 0x00FF;
+#elif defined(ATA_DEBUG)
+       ap->msg_enable = ATA_MSG_DRV | ATA_MSG_INFO | ATA_MSG_CTL | ATA_MSG_WARN | ATA_MSG_ERR;
+#else
+       ap->msg_enable = ATA_MSG_DRV | ATA_MSG_ERR | ATA_MSG_WARN;
+#endif
+
+       INIT_WORK(&ap->port_task, NULL, NULL);
+       INIT_WORK(&ap->hotplug_task, ata_scsi_hotplug, ap);
+       INIT_WORK(&ap->scsi_rescan_task, ata_scsi_dev_rescan, ap);
+       INIT_LIST_HEAD(&ap->eh_done_q);
+       init_waitqueue_head(&ap->eh_wait_q);
+
+       /* set cable type */
+       ap->cbl = ATA_CBL_NONE;
+       if (ap->flags & ATA_FLAG_SATA)
+               ap->cbl = ATA_CBL_SATA;
+
+       for (i = 0; i < ATA_MAX_DEVICES; i++) {
+               struct ata_device *dev = &ap->device[i];
+               dev->ap = ap;
+               dev->devno = i;
+               ata_dev_init(dev);
+       }
+
+#ifdef ATA_IRQ_TRAP
+       ap->stats.unhandled_irq = 1;
+       ap->stats.idle_irq = 1;
+#endif
+
+       memcpy(&ap->ioaddr, &ent->port[port_no], sizeof(struct ata_ioports));
+}
+
+/**
+ *     ata_port_init_shost - Initialize SCSI host associated with ATA port
+ *     @ap: ATA port to initialize SCSI host for
+ *     @shost: SCSI host associated with @ap
+ *
+ *     Initialize SCSI host @shost associated with ATA port @ap.
+ *
+ *     LOCKING:
+ *     Inherited from caller.
+ */
+static void ata_port_init_shost(struct ata_port *ap, struct Scsi_Host *shost)
+{
+       ap->host = shost;
+
+       shost->unique_id = ap->id;
+       shost->max_id = 16;
+       shost->max_lun = 1;
+       shost->max_channel = 1;
+       shost->max_cmd_len = 12;
+}
+
+/**
+ *     ata_port_add - Attach low-level ATA driver to system
+ *     @ent: Information provided by low-level driver
+ *     @host_set: Collections of ports to which we add
+ *     @port_no: Port number associated with this host
+ *
+ *     Attach low-level ATA driver to system.
+ *
+ *     LOCKING:
+ *     PCI/etc. bus probe sem.
+ *
+ *     RETURNS:
+ *     New ata_port on success, for NULL on error.
+ */
+static struct ata_port * ata_port_add(const struct ata_probe_ent *ent,
+                                     struct ata_host_set *host_set,
+                                     unsigned int port_no)
+{
+       struct Scsi_Host *shost;
+       struct ata_port *ap;
+
+       DPRINTK("ENTER\n");
+
+       if (!ent->port_ops->error_handler &&
+           !(ent->host_flags & (ATA_FLAG_SATA_RESET | ATA_FLAG_SRST))) {
+               printk(KERN_ERR "ata%u: no reset mechanism available\n",
+                      port_no);
+               return NULL;
+       }
+
+       shost = scsi_host_alloc(ent->sht, sizeof(struct ata_port));
+       if (!shost)
+               return NULL;
+
+       shost->transportt = &ata_scsi_transport_template;
+
+       ap = ata_shost_to_port(shost);
+
+       ata_port_init(ap, host_set, ent, port_no);
+       ata_port_init_shost(ap, shost);
+
+       return ap;
+}
+
+/**
+ *     ata_sas_host_init - Initialize a host_set struct
+ *     @host_set:      host_set to initialize
+ *     @dev:           device host_set is attached to
+ *     @flags: host_set flags
+ *     @ops:           port_ops
+ *
+ *     LOCKING:
+ *     PCI/etc. bus probe sem.
+ *
+ */
+
+void ata_host_set_init(struct ata_host_set *host_set,
+                      struct device *dev, unsigned long flags,
+                      const struct ata_port_operations *ops)
+{
+       spin_lock_init(&host_set->lock);
+       host_set->dev = dev;
+       host_set->flags = flags;
+       host_set->ops = ops;
+}
+
+/**
+ *     ata_device_add - Register hardware device with ATA and SCSI layers
+ *     @ent: Probe information describing hardware device to be registered
+ *
+ *     This function processes the information provided in the probe
+ *     information struct @ent, allocates the necessary ATA and SCSI
+ *     host information structures, initializes them, and registers
+ *     everything with requisite kernel subsystems.
+ *
+ *     This function requests irqs, probes the ATA bus, and probes
+ *     the SCSI bus.
+ *
+ *     LOCKING:
+ *     PCI/etc. bus probe sem.
+ *
+ *     RETURNS:
+ *     Number of ports registered.  Zero on error (no ports registered).
+ */
+int ata_device_add(const struct ata_probe_ent *ent)
+{
+       unsigned int i;
+       struct device *dev = ent->dev;
+       struct ata_host_set *host_set;
+       int rc;
+
+       DPRINTK("ENTER\n");
+       /* alloc a container for our list of ATA ports (buses) */
+       host_set = kzalloc(sizeof(struct ata_host_set) +
+                          (ent->n_ports * sizeof(void *)), GFP_KERNEL);
+       if (!host_set)
+               return 0;
+
+       ata_host_set_init(host_set, dev, ent->host_set_flags, ent->port_ops);
+       host_set->n_ports = ent->n_ports;
+       host_set->irq = ent->irq;
+       host_set->irq2 = ent->irq2;
+       host_set->mmio_base = ent->mmio_base;
+       host_set->private_data = ent->private_data;
+
+       /* register each port bound to this device */
+       for (i = 0; i < host_set->n_ports; i++) {
+               struct ata_port *ap;
+               unsigned long xfer_mode_mask;
+               int irq_line = ent->irq;
+
+               ap = ata_port_add(ent, host_set, i);
+               if (!ap)
+                       goto err_out;
+
+               host_set->ports[i] = ap;
+
+               /* dummy? */
+               if (ent->dummy_port_mask & (1 << i)) {
+                       ata_port_printk(ap, KERN_INFO, "DUMMY\n");
+                       ap->ops = &ata_dummy_port_ops;
+                       continue;
+               }
+
+               /* start port */
+               rc = ap->ops->port_start(ap);
+               if (rc) {
+                       host_set->ports[i] = NULL;
+                       scsi_host_put(ap->host);
+                       goto err_out;
+               }
+
+               /* Report the secondary IRQ for second channel legacy */
+               if (i == 1 && ent->irq2)
+                       irq_line = ent->irq2;
+
+               xfer_mode_mask =(ap->udma_mask << ATA_SHIFT_UDMA) |
+                               (ap->mwdma_mask << ATA_SHIFT_MWDMA) |
+                               (ap->pio_mask << ATA_SHIFT_PIO);
+
+               /* print per-port info to dmesg */
+               ata_port_printk(ap, KERN_INFO, "%cATA max %s cmd 0x%lX "
+                               "ctl 0x%lX bmdma 0x%lX irq %d\n",
+                               ap->flags & ATA_FLAG_SATA ? 'S' : 'P',
+                               ata_mode_string(xfer_mode_mask),
+                               ap->ioaddr.cmd_addr,
+                               ap->ioaddr.ctl_addr,
+                               ap->ioaddr.bmdma_addr,
+                               irq_line);
+
+               ata_chk_status(ap);
+               host_set->ops->irq_clear(ap);
+               ata_eh_freeze_port(ap); /* freeze port before requesting IRQ */
+       }
+
+       /* obtain irq, that may be shared between channels */
+       rc = request_irq(ent->irq, ent->port_ops->irq_handler, ent->irq_flags,
+                        DRV_NAME, host_set);
+       if (rc) {
+               dev_printk(KERN_ERR, dev, "irq %lu request failed: %d\n",
+                          ent->irq, rc);
+               goto err_out;
+       }
+
+       /* do we have a second IRQ for the other channel, eg legacy mode */
+       if (ent->irq2) {
+               /* We will get weird core code crashes later if this is true
+                  so trap it now */
+               BUG_ON(ent->irq == ent->irq2);
+
+               rc = request_irq(ent->irq2, ent->port_ops->irq_handler, ent->irq_flags,
+                        DRV_NAME, host_set);
+               if (rc) {
+                       dev_printk(KERN_ERR, dev, "irq %lu request failed: %d\n",
+                                  ent->irq2, rc);
+                       goto err_out_free_irq;
+               }
+       }
+
+       /* perform each probe synchronously */
+       DPRINTK("probe begin\n");
+       for (i = 0; i < host_set->n_ports; i++) {
+               struct ata_port *ap = host_set->ports[i];
+               u32 scontrol;
+               int rc;
+
+               /* init sata_spd_limit to the current value */
+               if (sata_scr_read(ap, SCR_CONTROL, &scontrol) == 0) {
+                       int spd = (scontrol >> 4) & 0xf;
+                       ap->hw_sata_spd_limit &= (1 << spd) - 1;
+               }
+               ap->sata_spd_limit = ap->hw_sata_spd_limit;
+
+               rc = scsi_add_host(ap->host, dev);
+               if (rc) {
+                       ata_port_printk(ap, KERN_ERR, "scsi_add_host failed\n");
+                       /* FIXME: do something useful here */
+                       /* FIXME: handle unconditional calls to
+                        * scsi_scan_host and ata_host_remove, below,
+                        * at the very least
+                        */
+               }
+
+               if (ap->ops->error_handler) {
+                       struct ata_eh_info *ehi = &ap->eh_info;
+                       unsigned long flags;
+
+                       ata_port_probe(ap);
+
+                       /* kick EH for boot probing */
+                       spin_lock_irqsave(ap->lock, flags);
+
+                       ehi->probe_mask = (1 << ATA_MAX_DEVICES) - 1;
+                       ehi->action |= ATA_EH_SOFTRESET;
+                       ehi->flags |= ATA_EHI_NO_AUTOPSY | ATA_EHI_QUIET;
+
+                       ap->pflags |= ATA_PFLAG_LOADING;
+                       ata_port_schedule_eh(ap);
+
+                       spin_unlock_irqrestore(ap->lock, flags);
+
+                       /* wait for EH to finish */
+                       ata_port_wait_eh(ap);
+               } else {
+                       DPRINTK("ata%u: bus probe begin\n", ap->id);
+                       rc = ata_bus_probe(ap);
+                       DPRINTK("ata%u: bus probe end\n", ap->id);
+
+                       if (rc) {
+                               /* FIXME: do something useful here?
+                                * Current libata behavior will
+                                * tear down everything when
+                                * the module is removed
+                                * or the h/w is unplugged.
+                                */
+                       }
+               }
+       }
+
+       /* probes are done, now scan each port's disk(s) */
+       DPRINTK("host probe begin\n");
+       for (i = 0; i < host_set->n_ports; i++) {
+               struct ata_port *ap = host_set->ports[i];
+
+               ata_scsi_scan_host(ap);
+       }
+
+       dev_set_drvdata(dev, host_set);
+
+       VPRINTK("EXIT, returning %u\n", ent->n_ports);
+       return ent->n_ports; /* success */
+
+err_out_free_irq:
+       free_irq(ent->irq, host_set);
+err_out:
+       for (i = 0; i < host_set->n_ports; i++) {
+               struct ata_port *ap = host_set->ports[i];
+               if (ap) {
+                       ap->ops->port_stop(ap);
+                       scsi_host_put(ap->host);
+               }
+       }
+
+       kfree(host_set);
+       VPRINTK("EXIT, returning 0\n");
+       return 0;
+}
+
+/**
+ *     ata_port_detach - Detach ATA port in prepration of device removal
+ *     @ap: ATA port to be detached
+ *
+ *     Detach all ATA devices and the associated SCSI devices of @ap;
+ *     then, remove the associated SCSI host.  @ap is guaranteed to
+ *     be quiescent on return from this function.
+ *
+ *     LOCKING:
+ *     Kernel thread context (may sleep).
+ */
+void ata_port_detach(struct ata_port *ap)
+{
+       unsigned long flags;
+       int i;
+
+       if (!ap->ops->error_handler)
+               goto skip_eh;
+
+       /* tell EH we're leaving & flush EH */
+       spin_lock_irqsave(ap->lock, flags);
+       ap->pflags |= ATA_PFLAG_UNLOADING;
+       spin_unlock_irqrestore(ap->lock, flags);
+
+       ata_port_wait_eh(ap);
+
+       /* EH is now guaranteed to see UNLOADING, so no new device
+        * will be attached.  Disable all existing devices.
+        */
+       spin_lock_irqsave(ap->lock, flags);
+
+       for (i = 0; i < ATA_MAX_DEVICES; i++)
+               ata_dev_disable(&ap->device[i]);
+
+       spin_unlock_irqrestore(ap->lock, flags);
+
+       /* Final freeze & EH.  All in-flight commands are aborted.  EH
+        * will be skipped and retrials will be terminated with bad
+        * target.
+        */
+       spin_lock_irqsave(ap->lock, flags);
+       ata_port_freeze(ap);    /* won't be thawed */
+       spin_unlock_irqrestore(ap->lock, flags);
+
+       ata_port_wait_eh(ap);
+
+       /* Flush hotplug task.  The sequence is similar to
+        * ata_port_flush_task().
+        */
+       flush_workqueue(ata_aux_wq);
+       cancel_delayed_work(&ap->hotplug_task);
+       flush_workqueue(ata_aux_wq);
+
+ skip_eh:
+       /* remove the associated SCSI host */
+       scsi_remove_host(ap->host);
+}
+
+/**
+ *     ata_host_set_remove - PCI layer callback for device removal
+ *     @host_set: ATA host set that was removed
+ *
+ *     Unregister all objects associated with this host set. Free those
+ *     objects.
+ *
+ *     LOCKING:
+ *     Inherited from calling layer (may sleep).
+ */
+
+void ata_host_set_remove(struct ata_host_set *host_set)
+{
+       unsigned int i;
+
+       for (i = 0; i < host_set->n_ports; i++)
+               ata_port_detach(host_set->ports[i]);
+
+       free_irq(host_set->irq, host_set);
+       if (host_set->irq2)
+               free_irq(host_set->irq2, host_set);
+
+       for (i = 0; i < host_set->n_ports; i++) {
+               struct ata_port *ap = host_set->ports[i];
+
+               ata_scsi_release(ap->host);
+
+               if ((ap->flags & ATA_FLAG_NO_LEGACY) == 0) {
+                       struct ata_ioports *ioaddr = &ap->ioaddr;
+
+                       /* FIXME: Add -ac IDE pci mods to remove these special cases */
+                       if (ioaddr->cmd_addr == ATA_PRIMARY_CMD)
+                               release_region(ATA_PRIMARY_CMD, 8);
+                       else if (ioaddr->cmd_addr == ATA_SECONDARY_CMD)
+                               release_region(ATA_SECONDARY_CMD, 8);
+               }
+
+               scsi_host_put(ap->host);
+       }
+
+       if (host_set->ops->host_stop)
+               host_set->ops->host_stop(host_set);
+
+       kfree(host_set);
+}
+
+/**
+ *     ata_scsi_release - SCSI layer callback hook for host unload
+ *     @host: libata host to be unloaded
+ *
+ *     Performs all duties necessary to shut down a libata port...
+ *     Kill port kthread, disable port, and release resources.
+ *
+ *     LOCKING:
+ *     Inherited from SCSI layer.
+ *
+ *     RETURNS:
+ *     One.
+ */
+
+int ata_scsi_release(struct Scsi_Host *host)
+{
+       struct ata_port *ap = ata_shost_to_port(host);
+
+       DPRINTK("ENTER\n");
+
+       ap->ops->port_disable(ap);
+       ap->ops->port_stop(ap);
+
+       DPRINTK("EXIT\n");
+       return 1;
+}
+
+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_std_ports - initialize ioaddr with standard port offsets.
+ *     @ioaddr: IO address structure to be initialized
+ *
+ *     Utility function which initializes data_addr, error_addr,
+ *     feature_addr, nsect_addr, lbal_addr, lbam_addr, lbah_addr,
+ *     device_addr, status_addr, and command_addr to standard offsets
+ *     relative to cmd_addr.
+ *
+ *     Does not set ctl_addr, altstatus_addr, bmdma_addr, or scr_addr.
+ */
+
+void ata_std_ports(struct ata_ioports *ioaddr)
+{
+       ioaddr->data_addr = ioaddr->cmd_addr + ATA_REG_DATA;
+       ioaddr->error_addr = ioaddr->cmd_addr + ATA_REG_ERR;
+       ioaddr->feature_addr = ioaddr->cmd_addr + ATA_REG_FEATURE;
+       ioaddr->nsect_addr = ioaddr->cmd_addr + ATA_REG_NSECT;
+       ioaddr->lbal_addr = ioaddr->cmd_addr + ATA_REG_LBAL;
+       ioaddr->lbam_addr = ioaddr->cmd_addr + ATA_REG_LBAM;
+       ioaddr->lbah_addr = ioaddr->cmd_addr + ATA_REG_LBAH;
+       ioaddr->device_addr = ioaddr->cmd_addr + ATA_REG_DEVICE;
+       ioaddr->status_addr = ioaddr->cmd_addr + ATA_REG_STATUS;
+       ioaddr->command_addr = ioaddr->cmd_addr + ATA_REG_CMD;
+}
+
+
+#ifdef CONFIG_PCI
+
+void ata_pci_host_stop (struct ata_host_set *host_set)
+{
+       struct pci_dev *pdev = to_pci_dev(host_set->dev);
+
+       pci_iounmap(pdev, host_set->mmio_base);
+}
+
+/**
+ *     ata_pci_remove_one - PCI layer callback for device removal
+ *     @pdev: PCI device that was removed
+ *
+ *     PCI layer indicates to libata via this hook that
+ *     hot-unplug or module unload event has occurred.
+ *     Handle this by unregistering all objects associated
+ *     with this PCI device.  Free those objects.  Then finally
+ *     release PCI resources and disable device.
+ *
+ *     LOCKING:
+ *     Inherited from PCI layer (may sleep).
+ */
+
+void ata_pci_remove_one (struct pci_dev *pdev)
+{
+       struct device *dev = pci_dev_to_dev(pdev);
+       struct ata_host_set *host_set = dev_get_drvdata(dev);
+
+       ata_host_set_remove(host_set);
+
+       pci_release_regions(pdev);
+       pci_disable_device(pdev);
+       dev_set_drvdata(dev, NULL);
+}
+
+/* move to PCI subsystem */
+int pci_test_config_bits(struct pci_dev *pdev, const struct pci_bits *bits)
+{
+       unsigned long tmp = 0;
+
+       switch (bits->width) {
+       case 1: {
+               u8 tmp8 = 0;
+               pci_read_config_byte(pdev, bits->reg, &tmp8);
+               tmp = tmp8;
+               break;
+       }
+       case 2: {
+               u16 tmp16 = 0;
+               pci_read_config_word(pdev, bits->reg, &tmp16);
+               tmp = tmp16;
+               break;
+       }
+       case 4: {
+               u32 tmp32 = 0;
+               pci_read_config_dword(pdev, bits->reg, &tmp32);
+               tmp = tmp32;
+               break;
+       }
+
+       default:
+               return -EINVAL;
+       }
+
+       tmp &= bits->mask;
+
+       return (tmp == bits->val) ? 1 : 0;
+}
+
+void ata_pci_device_do_suspend(struct pci_dev *pdev, pm_message_t mesg)
+{
+       pci_save_state(pdev);
+
+       if (mesg.event == PM_EVENT_SUSPEND) {
+               pci_disable_device(pdev);
+               pci_set_power_state(pdev, PCI_D3hot);
+       }
+}
+
+void ata_pci_device_do_resume(struct pci_dev *pdev)
+{
+       pci_set_power_state(pdev, PCI_D0);
+       pci_restore_state(pdev);
+       pci_enable_device(pdev);
+       pci_set_master(pdev);
+}
+
+int ata_pci_device_suspend(struct pci_dev *pdev, pm_message_t mesg)
+{
+       struct ata_host_set *host_set = dev_get_drvdata(&pdev->dev);
+       int rc = 0;
+
+       rc = ata_host_set_suspend(host_set, mesg);
+       if (rc)
+               return rc;
+
+       ata_pci_device_do_suspend(pdev, mesg);
+
+       return 0;
+}
+
+int ata_pci_device_resume(struct pci_dev *pdev)
+{
+       struct ata_host_set *host_set = dev_get_drvdata(&pdev->dev);
+
+       ata_pci_device_do_resume(pdev);
+       ata_host_set_resume(host_set);
+       return 0;
+}
+#endif /* CONFIG_PCI */
+
+
+static int __init ata_init(void)
+{
+       ata_probe_timeout *= HZ;
+       ata_wq = create_workqueue("ata");
+       if (!ata_wq)
+               return -ENOMEM;
+
+       ata_aux_wq = create_singlethread_workqueue("ata_aux");
+       if (!ata_aux_wq) {
+               destroy_workqueue(ata_wq);
+               return -ENOMEM;
+       }
+
+       printk(KERN_DEBUG "libata version " DRV_VERSION " loaded.\n");
+       return 0;
+}
+
+static void __exit ata_exit(void)
+{
+       destroy_workqueue(ata_wq);
+       destroy_workqueue(ata_aux_wq);
+}
+
+module_init(ata_init);
+module_exit(ata_exit);
+
+static unsigned long ratelimit_time;
+static DEFINE_SPINLOCK(ata_ratelimit_lock);
+
+int ata_ratelimit(void)
+{
+       int rc;
+       unsigned long flags;
+
+       spin_lock_irqsave(&ata_ratelimit_lock, flags);
+
+       if (time_after(jiffies, ratelimit_time)) {
+               rc = 1;
+               ratelimit_time = jiffies + (HZ/5);
+       } else
+               rc = 0;
+
+       spin_unlock_irqrestore(&ata_ratelimit_lock, flags);
+
+       return rc;
+}
+
+/**
+ *     ata_wait_register - wait until register value changes
+ *     @reg: IO-mapped register
+ *     @mask: Mask to apply to read register value
+ *     @val: Wait condition
+ *     @interval_msec: polling interval in milliseconds
+ *     @timeout_msec: timeout in milliseconds
+ *
+ *     Waiting for some bits of register to change is a common
+ *     operation for ATA controllers.  This function reads 32bit LE
+ *     IO-mapped register @reg and tests for the following condition.
+ *
+ *     (*@reg & mask) != val
+ *
+ *     If the condition is met, it returns; otherwise, the process is
+ *     repeated after @interval_msec until timeout.
+ *
+ *     LOCKING:
+ *     Kernel thread context (may sleep)
+ *
+ *     RETURNS:
+ *     The final register value.
+ */
+u32 ata_wait_register(void __iomem *reg, u32 mask, u32 val,
+                     unsigned long interval_msec,
+                     unsigned long timeout_msec)
+{
+       unsigned long timeout;
+       u32 tmp;
+
+       tmp = ioread32(reg);
+
+       /* Calculate timeout _after_ the first read to make sure
+        * preceding writes reach the controller before starting to
+        * eat away the timeout.
+        */
+       timeout = jiffies + (timeout_msec * HZ) / 1000;
+
+       while ((tmp & mask) == val && time_before(jiffies, timeout)) {
+               msleep(interval_msec);
+               tmp = ioread32(reg);
+       }
+
+       return tmp;
+}
+
+/*
+ * Dummy port_ops
+ */
+static void ata_dummy_noret(struct ata_port *ap)       { }
+static int ata_dummy_ret0(struct ata_port *ap)         { return 0; }
+static void ata_dummy_qc_noret(struct ata_queued_cmd *qc) { }
+
+static u8 ata_dummy_check_status(struct ata_port *ap)
+{
+       return ATA_DRDY;
+}
+
+static unsigned int ata_dummy_qc_issue(struct ata_queued_cmd *qc)
+{
+       return AC_ERR_SYSTEM;
+}
+
+const struct ata_port_operations ata_dummy_port_ops = {
+       .port_disable           = ata_port_disable,
+       .check_status           = ata_dummy_check_status,
+       .check_altstatus        = ata_dummy_check_status,
+       .dev_select             = ata_noop_dev_select,
+       .qc_prep                = ata_noop_qc_prep,
+       .qc_issue               = ata_dummy_qc_issue,
+       .freeze                 = ata_dummy_noret,
+       .thaw                   = ata_dummy_noret,
+       .error_handler          = ata_dummy_noret,
+       .post_internal_cmd      = ata_dummy_qc_noret,
+       .irq_clear              = ata_dummy_noret,
+       .port_start             = ata_dummy_ret0,
+       .port_stop              = ata_dummy_noret,
+};
+
+/*
+ * libata is essentially a library of internal helper functions for
+ * low-level ATA host controller drivers.  As such, the API/ABI is
+ * likely to change as new drivers are added and updated.
+ * Do not depend on ABI/API stability.
+ */
+
+EXPORT_SYMBOL_GPL(sata_deb_timing_normal);
+EXPORT_SYMBOL_GPL(sata_deb_timing_hotplug);
+EXPORT_SYMBOL_GPL(sata_deb_timing_long);
+EXPORT_SYMBOL_GPL(ata_dummy_port_ops);
+EXPORT_SYMBOL_GPL(ata_std_bios_param);
+EXPORT_SYMBOL_GPL(ata_std_ports);
+EXPORT_SYMBOL_GPL(ata_host_set_init);
+EXPORT_SYMBOL_GPL(ata_device_add);
+EXPORT_SYMBOL_GPL(ata_port_detach);
+EXPORT_SYMBOL_GPL(ata_host_set_remove);
+EXPORT_SYMBOL_GPL(ata_sg_init);
+EXPORT_SYMBOL_GPL(ata_sg_init_one);
+EXPORT_SYMBOL_GPL(ata_hsm_move);
+EXPORT_SYMBOL_GPL(ata_qc_complete);
+EXPORT_SYMBOL_GPL(ata_qc_complete_multiple);
+EXPORT_SYMBOL_GPL(ata_qc_issue_prot);
+EXPORT_SYMBOL_GPL(ata_tf_load);
+EXPORT_SYMBOL_GPL(ata_tf_read);
+EXPORT_SYMBOL_GPL(ata_noop_dev_select);
+EXPORT_SYMBOL_GPL(ata_std_dev_select);
+EXPORT_SYMBOL_GPL(ata_tf_to_fis);
+EXPORT_SYMBOL_GPL(ata_tf_from_fis);
+EXPORT_SYMBOL_GPL(ata_check_status);
+EXPORT_SYMBOL_GPL(ata_altstatus);
+EXPORT_SYMBOL_GPL(ata_exec_command);
+EXPORT_SYMBOL_GPL(ata_port_start);
+EXPORT_SYMBOL_GPL(ata_port_stop);
+EXPORT_SYMBOL_GPL(ata_host_stop);
+EXPORT_SYMBOL_GPL(ata_interrupt);
+EXPORT_SYMBOL_GPL(ata_mmio_data_xfer);
+EXPORT_SYMBOL_GPL(ata_pio_data_xfer);
+EXPORT_SYMBOL_GPL(ata_pio_data_xfer_noirq);
+EXPORT_SYMBOL_GPL(ata_qc_prep);
+EXPORT_SYMBOL_GPL(ata_noop_qc_prep);
+EXPORT_SYMBOL_GPL(ata_bmdma_setup);
+EXPORT_SYMBOL_GPL(ata_bmdma_start);
+EXPORT_SYMBOL_GPL(ata_bmdma_irq_clear);
+EXPORT_SYMBOL_GPL(ata_bmdma_status);
+EXPORT_SYMBOL_GPL(ata_bmdma_stop);
+EXPORT_SYMBOL_GPL(ata_bmdma_freeze);
+EXPORT_SYMBOL_GPL(ata_bmdma_thaw);
+EXPORT_SYMBOL_GPL(ata_bmdma_drive_eh);
+EXPORT_SYMBOL_GPL(ata_bmdma_error_handler);
+EXPORT_SYMBOL_GPL(ata_bmdma_post_internal_cmd);
+EXPORT_SYMBOL_GPL(ata_port_probe);
+EXPORT_SYMBOL_GPL(sata_set_spd);
+EXPORT_SYMBOL_GPL(sata_phy_debounce);
+EXPORT_SYMBOL_GPL(sata_phy_resume);
+EXPORT_SYMBOL_GPL(sata_phy_reset);
+EXPORT_SYMBOL_GPL(__sata_phy_reset);
+EXPORT_SYMBOL_GPL(ata_bus_reset);
+EXPORT_SYMBOL_GPL(ata_std_prereset);
+EXPORT_SYMBOL_GPL(ata_std_softreset);
+EXPORT_SYMBOL_GPL(sata_std_hardreset);
+EXPORT_SYMBOL_GPL(ata_std_postreset);
+EXPORT_SYMBOL_GPL(ata_dev_revalidate);
+EXPORT_SYMBOL_GPL(ata_dev_classify);
+EXPORT_SYMBOL_GPL(ata_dev_pair);
+EXPORT_SYMBOL_GPL(ata_port_disable);
+EXPORT_SYMBOL_GPL(ata_ratelimit);
+EXPORT_SYMBOL_GPL(ata_wait_register);
+EXPORT_SYMBOL_GPL(ata_busy_sleep);
+EXPORT_SYMBOL_GPL(ata_port_queue_task);
+EXPORT_SYMBOL_GPL(ata_scsi_ioctl);
+EXPORT_SYMBOL_GPL(ata_scsi_queuecmd);
+EXPORT_SYMBOL_GPL(ata_scsi_slave_config);
+EXPORT_SYMBOL_GPL(ata_scsi_slave_destroy);
+EXPORT_SYMBOL_GPL(ata_scsi_change_queue_depth);
+EXPORT_SYMBOL_GPL(ata_scsi_release);
+EXPORT_SYMBOL_GPL(ata_host_intr);
+EXPORT_SYMBOL_GPL(sata_scr_valid);
+EXPORT_SYMBOL_GPL(sata_scr_read);
+EXPORT_SYMBOL_GPL(sata_scr_write);
+EXPORT_SYMBOL_GPL(sata_scr_write_flush);
+EXPORT_SYMBOL_GPL(ata_port_online);
+EXPORT_SYMBOL_GPL(ata_port_offline);
+EXPORT_SYMBOL_GPL(ata_host_set_suspend);
+EXPORT_SYMBOL_GPL(ata_host_set_resume);
+EXPORT_SYMBOL_GPL(ata_id_string);
+EXPORT_SYMBOL_GPL(ata_id_c_string);
+EXPORT_SYMBOL_GPL(ata_scsi_simulate);
+
+EXPORT_SYMBOL_GPL(ata_pio_need_iordy);
+EXPORT_SYMBOL_GPL(ata_timing_compute);
+EXPORT_SYMBOL_GPL(ata_timing_merge);
+
+#ifdef CONFIG_PCI
+EXPORT_SYMBOL_GPL(pci_test_config_bits);
+EXPORT_SYMBOL_GPL(ata_pci_host_stop);
+EXPORT_SYMBOL_GPL(ata_pci_init_native_mode);
+EXPORT_SYMBOL_GPL(ata_pci_init_one);
+EXPORT_SYMBOL_GPL(ata_pci_remove_one);
+EXPORT_SYMBOL_GPL(ata_pci_device_do_suspend);
+EXPORT_SYMBOL_GPL(ata_pci_device_do_resume);
+EXPORT_SYMBOL_GPL(ata_pci_device_suspend);
+EXPORT_SYMBOL_GPL(ata_pci_device_resume);
+EXPORT_SYMBOL_GPL(ata_pci_default_filter);
+EXPORT_SYMBOL_GPL(ata_pci_clear_simplex);
+#endif /* CONFIG_PCI */
+
+EXPORT_SYMBOL_GPL(ata_scsi_device_suspend);
+EXPORT_SYMBOL_GPL(ata_scsi_device_resume);
+
+EXPORT_SYMBOL_GPL(ata_eng_timeout);
+EXPORT_SYMBOL_GPL(ata_port_schedule_eh);
+EXPORT_SYMBOL_GPL(ata_port_abort);
+EXPORT_SYMBOL_GPL(ata_port_freeze);
+EXPORT_SYMBOL_GPL(ata_eh_freeze_port);
+EXPORT_SYMBOL_GPL(ata_eh_thaw_port);
+EXPORT_SYMBOL_GPL(ata_eh_qc_complete);
+EXPORT_SYMBOL_GPL(ata_eh_qc_retry);
+EXPORT_SYMBOL_GPL(ata_do_eh);
diff --git a/drivers/ata/libata-eh.c b/drivers/ata/libata-eh.c
new file mode 100644 (file)
index 0000000..2c476ee
--- /dev/null
@@ -0,0 +1,2246 @@
+/*
+ *  libata-eh.c - libata error handling
+ *
+ *  Maintained by:  Jeff Garzik <jgarzik@pobox.com>
+ *                 Please ALWAYS copy linux-ide@vger.kernel.org
+ *                 on emails.
+ *
+ *  Copyright 2006 Tejun Heo <htejun@gmail.com>
+ *
+ *
+ *  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 <scsi/scsi.h>
+#include <scsi/scsi_host.h>
+#include <scsi/scsi_eh.h>
+#include <scsi/scsi_device.h>
+#include <scsi/scsi_cmnd.h>
+#include "../scsi/scsi_transport_api.h"
+
+#include <linux/libata.h>
+
+#include "libata.h"
+
+static void __ata_port_freeze(struct ata_port *ap);
+static void ata_eh_finish(struct ata_port *ap);
+static void ata_eh_handle_port_suspend(struct ata_port *ap);
+static void ata_eh_handle_port_resume(struct ata_port *ap);
+
+static void ata_ering_record(struct ata_ering *ering, int is_io,
+                            unsigned int err_mask)
+{
+       struct ata_ering_entry *ent;
+
+       WARN_ON(!err_mask);
+
+       ering->cursor++;
+       ering->cursor %= ATA_ERING_SIZE;
+
+       ent = &ering->ring[ering->cursor];
+       ent->is_io = is_io;
+       ent->err_mask = err_mask;
+       ent->timestamp = get_jiffies_64();
+}
+
+static struct ata_ering_entry * ata_ering_top(struct ata_ering *ering)
+{
+       struct ata_ering_entry *ent = &ering->ring[ering->cursor];
+       if (!ent->err_mask)
+               return NULL;
+       return ent;
+}
+
+static int ata_ering_map(struct ata_ering *ering,
+                        int (*map_fn)(struct ata_ering_entry *, void *),
+                        void *arg)
+{
+       int idx, rc = 0;
+       struct ata_ering_entry *ent;
+
+       idx = ering->cursor;
+       do {
+               ent = &ering->ring[idx];
+               if (!ent->err_mask)
+                       break;
+               rc = map_fn(ent, arg);
+               if (rc)
+                       break;
+               idx = (idx - 1 + ATA_ERING_SIZE) % ATA_ERING_SIZE;
+       } while (idx != ering->cursor);
+
+       return rc;
+}
+
+static unsigned int ata_eh_dev_action(struct ata_device *dev)
+{
+       struct ata_eh_context *ehc = &dev->ap->eh_context;
+
+       return ehc->i.action | ehc->i.dev_action[dev->devno];
+}
+
+static void ata_eh_clear_action(struct ata_device *dev,
+                               struct ata_eh_info *ehi, unsigned int action)
+{
+       int i;
+
+       if (!dev) {
+               ehi->action &= ~action;
+               for (i = 0; i < ATA_MAX_DEVICES; i++)
+                       ehi->dev_action[i] &= ~action;
+       } else {
+               /* doesn't make sense for port-wide EH actions */
+               WARN_ON(!(action & ATA_EH_PERDEV_MASK));
+
+               /* break ehi->action into ehi->dev_action */
+               if (ehi->action & action) {
+                       for (i = 0; i < ATA_MAX_DEVICES; i++)
+                               ehi->dev_action[i] |= ehi->action & action;
+                       ehi->action &= ~action;
+               }
+
+               /* turn off the specified per-dev action */
+               ehi->dev_action[dev->devno] &= ~action;
+       }
+}
+
+/**
+ *     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.
+ *
+ *     TODO: kill this function once old EH is gone.
+ *
+ *     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 = ata_shost_to_port(host);
+       unsigned long flags;
+       struct ata_queued_cmd *qc;
+       enum scsi_eh_timer_return ret;
+
+       DPRINTK("ENTER\n");
+
+       if (ap->ops->error_handler) {
+               ret = EH_NOT_HANDLED;
+               goto out;
+       }
+
+       ret = EH_HANDLED;
+       spin_lock_irqsave(ap->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->lock, flags);
+
+ out:
+       DPRINTK("EXIT, ret=%d\n", ret);
+       return ret;
+}
+
+/**
+ *     ata_scsi_error - SCSI layer error handler callback
+ *     @host: SCSI host on which error occurred
+ *
+ *     Handles SCSI-layer-thrown error events.
+ *
+ *     LOCKING:
+ *     Inherited from SCSI layer (none, can sleep)
+ *
+ *     RETURNS:
+ *     Zero.
+ */
+void ata_scsi_error(struct Scsi_Host *host)
+{
+       struct ata_port *ap = ata_shost_to_port(host);
+       int i, repeat_cnt = ATA_EH_MAX_REPEAT;
+       unsigned long flags;
+
+       DPRINTK("ENTER\n");
+
+       /* synchronize with port task */
+       ata_port_flush_task(ap);
+
+       /* synchronize with host_set lock and sort out timeouts */
+
+       /* For new EH, all qcs are finished in one of three ways -
+        * normal completion, error completion, and SCSI timeout.
+        * Both cmpletions can race against SCSI timeout.  When normal
+        * completion wins, the qc never reaches EH.  When error
+        * completion wins, the qc has ATA_QCFLAG_FAILED set.
+        *
+        * When SCSI timeout wins, things are a bit more complex.
+        * Normal or error completion can occur after the timeout but
+        * before this point.  In such cases, both types of
+        * completions are honored.  A scmd is determined to have
+        * timed out iff its associated qc is active and not failed.
+        */
+       if (ap->ops->error_handler) {
+               struct scsi_cmnd *scmd, *tmp;
+               int nr_timedout = 0;
+
+               spin_lock_irqsave(ap->lock, flags);
+
+               list_for_each_entry_safe(scmd, tmp, &host->eh_cmd_q, eh_entry) {
+                       struct ata_queued_cmd *qc;
+
+                       for (i = 0; i < ATA_MAX_QUEUE; i++) {
+                               qc = __ata_qc_from_tag(ap, i);
+                               if (qc->flags & ATA_QCFLAG_ACTIVE &&
+                                   qc->scsicmd == scmd)
+                                       break;
+                       }
+
+                       if (i < ATA_MAX_QUEUE) {
+                               /* the scmd has an associated qc */
+                               if (!(qc->flags & ATA_QCFLAG_FAILED)) {
+                                       /* which hasn't failed yet, timeout */
+                                       qc->err_mask |= AC_ERR_TIMEOUT;
+                                       qc->flags |= ATA_QCFLAG_FAILED;
+                                       nr_timedout++;
+                               }
+                       } else {
+                               /* Normal completion occurred after
+                                * SCSI timeout but before this point.
+                                * Successfully complete it.
+                                */
+                               scmd->retries = scmd->allowed;
+                               scsi_eh_finish_cmd(scmd, &ap->eh_done_q);
+                       }
+               }
+
+               /* If we have timed out qcs.  They belong to EH from
+                * this point but the state of the controller is
+                * unknown.  Freeze the port to make sure the IRQ
+                * handler doesn't diddle with those qcs.  This must
+                * be done atomically w.r.t. setting QCFLAG_FAILED.
+                */
+               if (nr_timedout)
+                       __ata_port_freeze(ap);
+
+               spin_unlock_irqrestore(ap->lock, flags);
+       } else
+               spin_unlock_wait(ap->lock);
+
+ repeat:
+       /* invoke error handler */
+       if (ap->ops->error_handler) {
+               /* process port resume request */
+               ata_eh_handle_port_resume(ap);
+
+               /* fetch & clear EH info */
+               spin_lock_irqsave(ap->lock, flags);
+
+               memset(&ap->eh_context, 0, sizeof(ap->eh_context));
+               ap->eh_context.i = ap->eh_info;
+               memset(&ap->eh_info, 0, sizeof(ap->eh_info));
+
+               ap->pflags |= ATA_PFLAG_EH_IN_PROGRESS;
+               ap->pflags &= ~ATA_PFLAG_EH_PENDING;
+
+               spin_unlock_irqrestore(ap->lock, flags);
+
+               /* invoke EH, skip if unloading or suspended */
+               if (!(ap->pflags & (ATA_PFLAG_UNLOADING | ATA_PFLAG_SUSPENDED)))
+                       ap->ops->error_handler(ap);
+               else
+                       ata_eh_finish(ap);
+
+               /* process port suspend request */
+               ata_eh_handle_port_suspend(ap);
+
+               /* Exception might have happend after ->error_handler
+                * recovered the port but before this point.  Repeat
+                * EH in such case.
+                */
+               spin_lock_irqsave(ap->lock, flags);
+
+               if (ap->pflags & ATA_PFLAG_EH_PENDING) {
+                       if (--repeat_cnt) {
+                               ata_port_printk(ap, KERN_INFO,
+                                       "EH pending after completion, "
+                                       "repeating EH (cnt=%d)\n", repeat_cnt);
+                               spin_unlock_irqrestore(ap->lock, flags);
+                               goto repeat;
+                       }
+                       ata_port_printk(ap, KERN_ERR, "EH pending after %d "
+                                       "tries, giving up\n", ATA_EH_MAX_REPEAT);
+               }
+
+               /* this run is complete, make sure EH info is clear */
+               memset(&ap->eh_info, 0, sizeof(ap->eh_info));
+
+               /* Clear host_eh_scheduled while holding ap->lock such
+                * that if exception occurs after this point but
+                * before EH completion, SCSI midlayer will
+                * re-initiate EH.
+                */
+               host->host_eh_scheduled = 0;
+
+               spin_unlock_irqrestore(ap->lock, flags);
+       } else {
+               WARN_ON(ata_qc_from_tag(ap, ap->active_tag) == NULL);
+               ap->ops->eng_timeout(ap);
+       }
+
+       /* finish or retry handled scmd's and clean up */
+       WARN_ON(host->host_failed || !list_empty(&host->eh_cmd_q));
+
+       scsi_eh_flush_done_q(&ap->eh_done_q);
+
+       /* clean up */
+       spin_lock_irqsave(ap->lock, flags);
+
+       if (ap->pflags & ATA_PFLAG_LOADING)
+               ap->pflags &= ~ATA_PFLAG_LOADING;
+       else if (ap->pflags & ATA_PFLAG_SCSI_HOTPLUG)
+               queue_work(ata_aux_wq, &ap->hotplug_task);
+
+       if (ap->pflags & ATA_PFLAG_RECOVERED)
+               ata_port_printk(ap, KERN_INFO, "EH complete\n");
+
+       ap->pflags &= ~(ATA_PFLAG_SCSI_HOTPLUG | ATA_PFLAG_RECOVERED);
+
+       /* tell wait_eh that we're done */
+       ap->pflags &= ~ATA_PFLAG_EH_IN_PROGRESS;
+       wake_up_all(&ap->eh_wait_q);
+
+       spin_unlock_irqrestore(ap->lock, flags);
+
+       DPRINTK("EXIT\n");
+}
+
+/**
+ *     ata_port_wait_eh - Wait for the currently pending EH to complete
+ *     @ap: Port to wait EH for
+ *
+ *     Wait until the currently pending EH is complete.
+ *
+ *     LOCKING:
+ *     Kernel thread context (may sleep).
+ */
+void ata_port_wait_eh(struct ata_port *ap)
+{
+       unsigned long flags;
+       DEFINE_WAIT(wait);
+
+ retry:
+       spin_lock_irqsave(ap->lock, flags);
+
+       while (ap->pflags & (ATA_PFLAG_EH_PENDING | ATA_PFLAG_EH_IN_PROGRESS)) {
+               prepare_to_wait(&ap->eh_wait_q, &wait, TASK_UNINTERRUPTIBLE);
+               spin_unlock_irqrestore(ap->lock, flags);
+               schedule();
+               spin_lock_irqsave(ap->lock, flags);
+       }
+       finish_wait(&ap->eh_wait_q, &wait);
+
+       spin_unlock_irqrestore(ap->lock, flags);
+
+       /* make sure SCSI EH is complete */
+       if (scsi_host_in_recovery(ap->host)) {
+               msleep(10);
+               goto retry;
+       }
+}
+
+/**
+ *     ata_qc_timeout - Handle timeout of queued command
+ *     @qc: Command that timed out
+ *
+ *     Some part of the kernel (currently, only the SCSI layer)
+ *     has noticed that the active command on port @ap has not
+ *     completed after a specified length of time.  Handle this
+ *     condition by disabling DMA (if necessary) and completing
+ *     transactions, with error if necessary.
+ *
+ *     This also handles the case of the "lost interrupt", where
+ *     for some reason (possibly hardware bug, possibly driver bug)
+ *     an interrupt was not delivered to the driver, even though the
+ *     transaction completed successfully.
+ *
+ *     TODO: kill this function once old EH is gone.
+ *
+ *     LOCKING:
+ *     Inherited from SCSI layer (none, can sleep)
+ */
+static void ata_qc_timeout(struct ata_queued_cmd *qc)
+{
+       struct ata_port *ap = qc->ap;
+       u8 host_stat = 0, drv_stat;
+       unsigned long flags;
+
+       DPRINTK("ENTER\n");
+
+       ap->hsm_task_state = HSM_ST_IDLE;
+
+       spin_lock_irqsave(ap->lock, flags);
+
+       switch (qc->tf.protocol) {
+
+       case ATA_PROT_DMA:
+       case ATA_PROT_ATAPI_DMA:
+               host_stat = ap->ops->bmdma_status(ap);
+
+               /* before we do anything else, clear DMA-Start bit */
+               ap->ops->bmdma_stop(qc);
+
+               /* fall through */
+
+       default:
+               ata_altstatus(ap);
+               drv_stat = ata_chk_status(ap);
+
+               /* ack bmdma irq events */
+               ap->ops->irq_clear(ap);
+
+               ata_dev_printk(qc->dev, KERN_ERR, "command 0x%x timeout, "
+                              "stat 0x%x host_stat 0x%x\n",
+                              qc->tf.command, drv_stat, host_stat);
+
+               /* complete taskfile transaction */
+               qc->err_mask |= AC_ERR_TIMEOUT;
+               break;
+       }
+
+       spin_unlock_irqrestore(ap->lock, flags);
+
+       ata_eh_qc_complete(qc);
+
+       DPRINTK("EXIT\n");
+}
+
+/**
+ *     ata_eng_timeout - Handle timeout of queued command
+ *     @ap: Port on which timed-out command is active
+ *
+ *     Some part of the kernel (currently, only the SCSI layer)
+ *     has noticed that the active command on port @ap has not
+ *     completed after a specified length of time.  Handle this
+ *     condition by disabling DMA (if necessary) and completing
+ *     transactions, with error if necessary.
+ *
+ *     This also handles the case of the "lost interrupt", where
+ *     for some reason (possibly hardware bug, possibly driver bug)
+ *     an interrupt was not delivered to the driver, even though the
+ *     transaction completed successfully.
+ *
+ *     TODO: kill this function once old EH is gone.
+ *
+ *     LOCKING:
+ *     Inherited from SCSI layer (none, can sleep)
+ */
+void ata_eng_timeout(struct ata_port *ap)
+{
+       DPRINTK("ENTER\n");
+
+       ata_qc_timeout(ata_qc_from_tag(ap, ap->active_tag));
+
+       DPRINTK("EXIT\n");
+}
+
+/**
+ *     ata_qc_schedule_eh - schedule qc for error handling
+ *     @qc: command to schedule error handling for
+ *
+ *     Schedule error handling for @qc.  EH will kick in as soon as
+ *     other commands are drained.
+ *
+ *     LOCKING:
+ *     spin_lock_irqsave(host_set lock)
+ */
+void ata_qc_schedule_eh(struct ata_queued_cmd *qc)
+{
+       struct ata_port *ap = qc->ap;
+
+       WARN_ON(!ap->ops->error_handler);
+
+       qc->flags |= ATA_QCFLAG_FAILED;
+       qc->ap->pflags |= ATA_PFLAG_EH_PENDING;
+
+       /* The following will fail if timeout has already expired.
+        * ata_scsi_error() takes care of such scmds on EH entry.
+        * Note that ATA_QCFLAG_FAILED is unconditionally set after
+        * this function completes.
+        */
+       scsi_req_abort_cmd(qc->scsicmd);
+}
+
+/**
+ *     ata_port_schedule_eh - schedule error handling without a qc
+ *     @ap: ATA port to schedule EH for
+ *
+ *     Schedule error handling for @ap.  EH will kick in as soon as
+ *     all commands are drained.
+ *
+ *     LOCKING:
+ *     spin_lock_irqsave(host_set lock)
+ */
+void ata_port_schedule_eh(struct ata_port *ap)
+{
+       WARN_ON(!ap->ops->error_handler);
+
+       ap->pflags |= ATA_PFLAG_EH_PENDING;
+       scsi_schedule_eh(ap->host);
+
+       DPRINTK("port EH scheduled\n");
+}
+
+/**
+ *     ata_port_abort - abort all qc's on the port
+ *     @ap: ATA port to abort qc's for
+ *
+ *     Abort all active qc's of @ap and schedule EH.
+ *
+ *     LOCKING:
+ *     spin_lock_irqsave(host_set lock)
+ *
+ *     RETURNS:
+ *     Number of aborted qc's.
+ */
+int ata_port_abort(struct ata_port *ap)
+{
+       int tag, nr_aborted = 0;
+
+       WARN_ON(!ap->ops->error_handler);
+
+       for (tag = 0; tag < ATA_MAX_QUEUE; tag++) {
+               struct ata_queued_cmd *qc = ata_qc_from_tag(ap, tag);
+
+               if (qc) {
+                       qc->flags |= ATA_QCFLAG_FAILED;
+                       ata_qc_complete(qc);
+                       nr_aborted++;
+               }
+       }
+
+       if (!nr_aborted)
+               ata_port_schedule_eh(ap);
+
+       return nr_aborted;
+}
+
+/**
+ *     __ata_port_freeze - freeze port
+ *     @ap: ATA port to freeze
+ *
+ *     This function is called when HSM violation or some other
+ *     condition disrupts normal operation of the port.  Frozen port
+ *     is not allowed to perform any operation until the port is
+ *     thawed, which usually follows a successful reset.
+ *
+ *     ap->ops->freeze() callback can be used for freezing the port
+ *     hardware-wise (e.g. mask interrupt and stop DMA engine).  If a
+ *     port cannot be frozen hardware-wise, the interrupt handler
+ *     must ack and clear interrupts unconditionally while the port
+ *     is frozen.
+ *
+ *     LOCKING:
+ *     spin_lock_irqsave(host_set lock)
+ */
+static void __ata_port_freeze(struct ata_port *ap)
+{
+       WARN_ON(!ap->ops->error_handler);
+
+       if (ap->ops->freeze)
+               ap->ops->freeze(ap);
+
+       ap->pflags |= ATA_PFLAG_FROZEN;
+
+       DPRINTK("ata%u port frozen\n", ap->id);
+}
+
+/**
+ *     ata_port_freeze - abort & freeze port
+ *     @ap: ATA port to freeze
+ *
+ *     Abort and freeze @ap.
+ *
+ *     LOCKING:
+ *     spin_lock_irqsave(host_set lock)
+ *
+ *     RETURNS:
+ *     Number of aborted commands.
+ */
+int ata_port_freeze(struct ata_port *ap)
+{
+       int nr_aborted;
+
+       WARN_ON(!ap->ops->error_handler);
+
+       nr_aborted = ata_port_abort(ap);
+       __ata_port_freeze(ap);
+
+       return nr_aborted;
+}
+
+/**
+ *     ata_eh_freeze_port - EH helper to freeze port
+ *     @ap: ATA port to freeze
+ *
+ *     Freeze @ap.
+ *
+ *     LOCKING:
+ *     None.
+ */
+void ata_eh_freeze_port(struct ata_port *ap)
+{
+       unsigned long flags;
+
+       if (!ap->ops->error_handler)
+               return;
+
+       spin_lock_irqsave(ap->lock, flags);
+       __ata_port_freeze(ap);
+       spin_unlock_irqrestore(ap->lock, flags);
+}
+
+/**
+ *     ata_port_thaw_port - EH helper to thaw port
+ *     @ap: ATA port to thaw
+ *
+ *     Thaw frozen port @ap.
+ *
+ *     LOCKING:
+ *     None.
+ */
+void ata_eh_thaw_port(struct ata_port *ap)
+{
+       unsigned long flags;
+
+       if (!ap->ops->error_handler)
+               return;
+
+       spin_lock_irqsave(ap->lock, flags);
+
+       ap->pflags &= ~ATA_PFLAG_FROZEN;
+
+       if (ap->ops->thaw)
+               ap->ops->thaw(ap);
+
+       spin_unlock_irqrestore(ap->lock, flags);
+
+       DPRINTK("ata%u port thawed\n", ap->id);
+}
+
+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->lock, flags);
+       qc->scsidone = ata_eh_scsidone;
+       __ata_qc_complete(qc);
+       WARN_ON(ata_tag_valid(qc->tag));
+       spin_unlock_irqrestore(ap->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.
+ *     scmd->retries is decremented for commands which get retried
+ *     due to unrelated failures (qc->err_mask is zero).
+ */
+void ata_eh_qc_retry(struct ata_queued_cmd *qc)
+{
+       struct scsi_cmnd *scmd = qc->scsicmd;
+       if (!qc->err_mask && scmd->retries)
+               scmd->retries--;
+       __ata_eh_qc_complete(qc);
+}
+
+/**
+ *     ata_eh_detach_dev - detach ATA device
+ *     @dev: ATA device to detach
+ *
+ *     Detach @dev.
+ *
+ *     LOCKING:
+ *     None.
+ */
+static void ata_eh_detach_dev(struct ata_device *dev)
+{
+       struct ata_port *ap = dev->ap;
+       unsigned long flags;
+
+       ata_dev_disable(dev);
+
+       spin_lock_irqsave(ap->lock, flags);
+
+       dev->flags &= ~ATA_DFLAG_DETACH;
+
+       if (ata_scsi_offline_dev(dev)) {
+               dev->flags |= ATA_DFLAG_DETACHED;
+               ap->pflags |= ATA_PFLAG_SCSI_HOTPLUG;
+       }
+
+       /* clear per-dev EH actions */
+       ata_eh_clear_action(dev, &ap->eh_info, ATA_EH_PERDEV_MASK);
+       ata_eh_clear_action(dev, &ap->eh_context.i, ATA_EH_PERDEV_MASK);
+
+       spin_unlock_irqrestore(ap->lock, flags);
+}
+
+/**
+ *     ata_eh_about_to_do - about to perform eh_action
+ *     @ap: target ATA port
+ *     @dev: target ATA dev for per-dev action (can be NULL)
+ *     @action: action about to be performed
+ *
+ *     Called just before performing EH actions to clear related bits
+ *     in @ap->eh_info such that eh actions are not unnecessarily
+ *     repeated.
+ *
+ *     LOCKING:
+ *     None.
+ */
+static void ata_eh_about_to_do(struct ata_port *ap, struct ata_device *dev,
+                              unsigned int action)
+{
+       unsigned long flags;
+       struct ata_eh_info *ehi = &ap->eh_info;
+       struct ata_eh_context *ehc = &ap->eh_context;
+
+       spin_lock_irqsave(ap->lock, flags);
+
+       /* Reset is represented by combination of actions and EHI
+        * flags.  Suck in all related bits before clearing eh_info to
+        * avoid losing requested action.
+        */
+       if (action & ATA_EH_RESET_MASK) {
+               ehc->i.action |= ehi->action & ATA_EH_RESET_MASK;
+               ehc->i.flags |= ehi->flags & ATA_EHI_RESET_MODIFIER_MASK;
+
+               /* make sure all reset actions are cleared & clear EHI flags */
+               action |= ATA_EH_RESET_MASK;
+               ehi->flags &= ~ATA_EHI_RESET_MODIFIER_MASK;
+       }
+
+       ata_eh_clear_action(dev, ehi, action);
+
+       if (!(ehc->i.flags & ATA_EHI_QUIET))
+               ap->pflags |= ATA_PFLAG_RECOVERED;
+
+       spin_unlock_irqrestore(ap->lock, flags);
+}
+
+/**
+ *     ata_eh_done - EH action complete
+ *     @ap: target ATA port
+ *     @dev: target ATA dev for per-dev action (can be NULL)
+ *     @action: action just completed
+ *
+ *     Called right after performing EH actions to clear related bits
+ *     in @ap->eh_context.
+ *
+ *     LOCKING:
+ *     None.
+ */
+static void ata_eh_done(struct ata_port *ap, struct ata_device *dev,
+                       unsigned int action)
+{
+       /* if reset is complete, clear all reset actions & reset modifier */
+       if (action & ATA_EH_RESET_MASK) {
+               action |= ATA_EH_RESET_MASK;
+               ap->eh_context.i.flags &= ~ATA_EHI_RESET_MODIFIER_MASK;
+       }
+
+       ata_eh_clear_action(dev, &ap->eh_context.i, action);
+}
+
+/**
+ *     ata_err_string - convert err_mask to descriptive string
+ *     @err_mask: error mask to convert to string
+ *
+ *     Convert @err_mask to descriptive string.  Errors are
+ *     prioritized according to severity and only the most severe
+ *     error is reported.
+ *
+ *     LOCKING:
+ *     None.
+ *
+ *     RETURNS:
+ *     Descriptive string for @err_mask
+ */
+static const char * ata_err_string(unsigned int err_mask)
+{
+       if (err_mask & AC_ERR_HOST_BUS)
+               return "host bus error";
+       if (err_mask & AC_ERR_ATA_BUS)
+               return "ATA bus error";
+       if (err_mask & AC_ERR_TIMEOUT)
+               return "timeout";
+       if (err_mask & AC_ERR_HSM)
+               return "HSM violation";
+       if (err_mask & AC_ERR_SYSTEM)
+               return "internal error";
+       if (err_mask & AC_ERR_MEDIA)
+               return "media error";
+       if (err_mask & AC_ERR_INVALID)
+               return "invalid argument";
+       if (err_mask & AC_ERR_DEV)
+               return "device error";
+       return "unknown error";
+}
+
+/**
+ *     ata_read_log_page - read a specific log page
+ *     @dev: target device
+ *     @page: page to read
+ *     @buf: buffer to store read page
+ *     @sectors: number of sectors to read
+ *
+ *     Read log page using READ_LOG_EXT command.
+ *
+ *     LOCKING:
+ *     Kernel thread context (may sleep).
+ *
+ *     RETURNS:
+ *     0 on success, AC_ERR_* mask otherwise.
+ */
+static unsigned int ata_read_log_page(struct ata_device *dev,
+                                     u8 page, void *buf, unsigned int sectors)
+{
+       struct ata_taskfile tf;
+       unsigned int err_mask;
+
+       DPRINTK("read log page - page %d\n", page);
+
+       ata_tf_init(dev, &tf);
+       tf.command = ATA_CMD_READ_LOG_EXT;
+       tf.lbal = page;
+       tf.nsect = sectors;
+       tf.hob_nsect = sectors >> 8;
+       tf.flags |= ATA_TFLAG_ISADDR | ATA_TFLAG_LBA48 | ATA_TFLAG_DEVICE;
+       tf.protocol = ATA_PROT_PIO;
+
+       err_mask = ata_exec_internal(dev, &tf, NULL, DMA_FROM_DEVICE,
+                                    buf, sectors * ATA_SECT_SIZE);
+
+       DPRINTK("EXIT, err_mask=%x\n", err_mask);
+       return err_mask;
+}
+
+/**
+ *     ata_eh_read_log_10h - Read log page 10h for NCQ error details
+ *     @dev: Device to read log page 10h from
+ *     @tag: Resulting tag of the failed command
+ *     @tf: Resulting taskfile registers of the failed command
+ *
+ *     Read log page 10h to obtain NCQ error details and clear error
+ *     condition.
+ *
+ *     LOCKING:
+ *     Kernel thread context (may sleep).
+ *
+ *     RETURNS:
+ *     0 on success, -errno otherwise.
+ */
+static int ata_eh_read_log_10h(struct ata_device *dev,
+                              int *tag, struct ata_taskfile *tf)
+{
+       u8 *buf = dev->ap->sector_buf;
+       unsigned int err_mask;
+       u8 csum;
+       int i;
+
+       err_mask = ata_read_log_page(dev, ATA_LOG_SATA_NCQ, buf, 1);
+       if (err_mask)
+               return -EIO;
+
+       csum = 0;
+       for (i = 0; i < ATA_SECT_SIZE; i++)
+               csum += buf[i];
+       if (csum)
+               ata_dev_printk(dev, KERN_WARNING,
+                              "invalid checksum 0x%x on log page 10h\n", csum);
+
+       if (buf[0] & 0x80)
+               return -ENOENT;
+
+       *tag = buf[0] & 0x1f;
+
+       tf->command = buf[2];
+       tf->feature = buf[3];
+       tf->lbal = buf[4];
+       tf->lbam = buf[5];
+       tf->lbah = buf[6];
+       tf->device = buf[7];
+       tf->hob_lbal = buf[8];
+       tf->hob_lbam = buf[9];
+       tf->hob_lbah = buf[10];
+       tf->nsect = buf[12];
+       tf->hob_nsect = buf[13];
+
+       return 0;
+}
+
+/**
+ *     atapi_eh_request_sense - perform ATAPI REQUEST_SENSE
+ *     @dev: device to perform REQUEST_SENSE to
+ *     @sense_buf: result sense data buffer (SCSI_SENSE_BUFFERSIZE bytes long)
+ *
+ *     Perform ATAPI REQUEST_SENSE after the device reported CHECK
+ *     SENSE.  This function is EH helper.
+ *
+ *     LOCKING:
+ *     Kernel thread context (may sleep).
+ *
+ *     RETURNS:
+ *     0 on success, AC_ERR_* mask on failure
+ */
+static unsigned int atapi_eh_request_sense(struct ata_device *dev,
+                                          unsigned char *sense_buf)
+{
+       struct ata_port *ap = dev->ap;
+       struct ata_taskfile tf;
+       u8 cdb[ATAPI_CDB_LEN];
+
+       DPRINTK("ATAPI request sense\n");
+
+       ata_tf_init(dev, &tf);
+
+       /* FIXME: is this needed? */
+       memset(sense_buf, 0, SCSI_SENSE_BUFFERSIZE);
+
+       /* XXX: why tf_read here? */
+       ap->ops->tf_read(ap, &tf);
+
+       /* fill these in, for the case where they are -not- overwritten */
+       sense_buf[0] = 0x70;
+       sense_buf[2] = tf.feature >> 4;
+
+       memset(cdb, 0, ATAPI_CDB_LEN);
+       cdb[0] = REQUEST_SENSE;
+       cdb[4] = SCSI_SENSE_BUFFERSIZE;
+
+       tf.flags |= ATA_TFLAG_ISADDR | ATA_TFLAG_DEVICE;
+       tf.command = ATA_CMD_PACKET;
+
+       /* is it pointless to prefer PIO for "safety reasons"? */
+       if (ap->flags & ATA_FLAG_PIO_DMA) {
+               tf.protocol = ATA_PROT_ATAPI_DMA;
+               tf.feature |= ATAPI_PKT_DMA;
+       } else {
+               tf.protocol = ATA_PROT_ATAPI;
+               tf.lbam = (8 * 1024) & 0xff;
+               tf.lbah = (8 * 1024) >> 8;
+       }
+
+       return ata_exec_internal(dev, &tf, cdb, DMA_FROM_DEVICE,
+                                sense_buf, SCSI_SENSE_BUFFERSIZE);
+}
+
+/**
+ *     ata_eh_analyze_serror - analyze SError for a failed port
+ *     @ap: ATA port to analyze SError for
+ *
+ *     Analyze SError if available and further determine cause of
+ *     failure.
+ *
+ *     LOCKING:
+ *     None.
+ */
+static void ata_eh_analyze_serror(struct ata_port *ap)
+{
+       struct ata_eh_context *ehc = &ap->eh_context;
+       u32 serror = ehc->i.serror;
+       unsigned int err_mask = 0, action = 0;
+
+       if (serror & SERR_PERSISTENT) {
+               err_mask |= AC_ERR_ATA_BUS;
+               action |= ATA_EH_HARDRESET;
+       }
+       if (serror &
+           (SERR_DATA_RECOVERED | SERR_COMM_RECOVERED | SERR_DATA)) {
+               err_mask |= AC_ERR_ATA_BUS;
+               action |= ATA_EH_SOFTRESET;
+       }
+       if (serror & SERR_PROTOCOL) {
+               err_mask |= AC_ERR_HSM;
+               action |= ATA_EH_SOFTRESET;
+       }
+       if (serror & SERR_INTERNAL) {
+               err_mask |= AC_ERR_SYSTEM;
+               action |= ATA_EH_SOFTRESET;
+       }
+       if (serror & (SERR_PHYRDY_CHG | SERR_DEV_XCHG))
+               ata_ehi_hotplugged(&ehc->i);
+
+       ehc->i.err_mask |= err_mask;
+       ehc->i.action |= action;
+}
+
+/**
+ *     ata_eh_analyze_ncq_error - analyze NCQ error
+ *     @ap: ATA port to analyze NCQ error for
+ *
+ *     Read log page 10h, determine the offending qc and acquire
+ *     error status TF.  For NCQ device errors, all LLDDs have to do
+ *     is setting AC_ERR_DEV in ehi->err_mask.  This function takes
+ *     care of the rest.
+ *
+ *     LOCKING:
+ *     Kernel thread context (may sleep).
+ */
+static void ata_eh_analyze_ncq_error(struct ata_port *ap)
+{
+       struct ata_eh_context *ehc = &ap->eh_context;
+       struct ata_device *dev = ap->device;
+       struct ata_queued_cmd *qc;
+       struct ata_taskfile tf;
+       int tag, rc;
+
+       /* if frozen, we can't do much */
+       if (ap->pflags & ATA_PFLAG_FROZEN)
+               return;
+
+       /* is it NCQ device error? */
+       if (!ap->sactive || !(ehc->i.err_mask & AC_ERR_DEV))
+               return;
+
+       /* has LLDD analyzed already? */
+       for (tag = 0; tag < ATA_MAX_QUEUE; tag++) {
+               qc = __ata_qc_from_tag(ap, tag);
+
+               if (!(qc->flags & ATA_QCFLAG_FAILED))
+                       continue;
+
+               if (qc->err_mask)
+                       return;
+       }
+
+       /* okay, this error is ours */
+       rc = ata_eh_read_log_10h(dev, &tag, &tf);
+       if (rc) {
+               ata_port_printk(ap, KERN_ERR, "failed to read log page 10h "
+                               "(errno=%d)\n", rc);
+               return;
+       }
+
+       if (!(ap->sactive & (1 << tag))) {
+               ata_port_printk(ap, KERN_ERR, "log page 10h reported "
+                               "inactive tag %d\n", tag);
+               return;
+       }
+
+       /* we've got the perpetrator, condemn it */
+       qc = __ata_qc_from_tag(ap, tag);
+       memcpy(&qc->result_tf, &tf, sizeof(tf));
+       qc->err_mask |= AC_ERR_DEV;
+       ehc->i.err_mask &= ~AC_ERR_DEV;
+}
+
+/**
+ *     ata_eh_analyze_tf - analyze taskfile of a failed qc
+ *     @qc: qc to analyze
+ *     @tf: Taskfile registers to analyze
+ *
+ *     Analyze taskfile of @qc and further determine cause of
+ *     failure.  This function also requests ATAPI sense data if
+ *     avaliable.
+ *
+ *     LOCKING:
+ *     Kernel thread context (may sleep).
+ *
+ *     RETURNS:
+ *     Determined recovery action
+ */
+static unsigned int ata_eh_analyze_tf(struct ata_queued_cmd *qc,
+                                     const struct ata_taskfile *tf)
+{
+       unsigned int tmp, action = 0;
+       u8 stat = tf->command, err = tf->feature;
+
+       if ((stat & (ATA_BUSY | ATA_DRQ | ATA_DRDY)) != ATA_DRDY) {
+               qc->err_mask |= AC_ERR_HSM;
+               return ATA_EH_SOFTRESET;
+       }
+
+       if (!(qc->err_mask & AC_ERR_DEV))
+               return 0;
+
+       switch (qc->dev->class) {
+       case ATA_DEV_ATA:
+               if (err & ATA_ICRC)
+                       qc->err_mask |= AC_ERR_ATA_BUS;
+               if (err & ATA_UNC)
+                       qc->err_mask |= AC_ERR_MEDIA;
+               if (err & ATA_IDNF)
+                       qc->err_mask |= AC_ERR_INVALID;
+               break;
+
+       case ATA_DEV_ATAPI:
+               tmp = atapi_eh_request_sense(qc->dev,
+                                            qc->scsicmd->sense_buffer);
+               if (!tmp) {
+                       /* ATA_QCFLAG_SENSE_VALID is used to tell
+                        * atapi_qc_complete() that sense data is
+                        * already valid.
+                        *
+                        * TODO: interpret sense data and set
+                        * appropriate err_mask.
+                        */
+                       qc->flags |= ATA_QCFLAG_SENSE_VALID;
+               } else
+                       qc->err_mask |= tmp;
+       }
+
+       if (qc->err_mask & (AC_ERR_HSM | AC_ERR_TIMEOUT | AC_ERR_ATA_BUS))
+               action |= ATA_EH_SOFTRESET;
+
+       return action;
+}
+
+static int ata_eh_categorize_ering_entry(struct ata_ering_entry *ent)
+{
+       if (ent->err_mask & (AC_ERR_ATA_BUS | AC_ERR_TIMEOUT))
+               return 1;
+
+       if (ent->is_io) {
+               if (ent->err_mask & AC_ERR_HSM)
+                       return 1;
+               if ((ent->err_mask &
+                    (AC_ERR_DEV|AC_ERR_MEDIA|AC_ERR_INVALID)) == AC_ERR_DEV)
+                       return 2;
+       }
+
+       return 0;
+}
+
+struct speed_down_needed_arg {
+       u64 since;
+       int nr_errors[3];
+};
+
+static int speed_down_needed_cb(struct ata_ering_entry *ent, void *void_arg)
+{
+       struct speed_down_needed_arg *arg = void_arg;
+
+       if (ent->timestamp < arg->since)
+               return -1;
+
+       arg->nr_errors[ata_eh_categorize_ering_entry(ent)]++;
+       return 0;
+}
+
+/**
+ *     ata_eh_speed_down_needed - Determine wheter speed down is necessary
+ *     @dev: Device of interest
+ *
+ *     This function examines error ring of @dev and determines
+ *     whether speed down is necessary.  Speed down is necessary if
+ *     there have been more than 3 of Cat-1 errors or 10 of Cat-2
+ *     errors during last 15 minutes.
+ *
+ *     Cat-1 errors are ATA_BUS, TIMEOUT for any command and HSM
+ *     violation for known supported commands.
+ *
+ *     Cat-2 errors are unclassified DEV error for known supported
+ *     command.
+ *
+ *     LOCKING:
+ *     Inherited from caller.
+ *
+ *     RETURNS:
+ *     1 if speed down is necessary, 0 otherwise
+ */
+static int ata_eh_speed_down_needed(struct ata_device *dev)
+{
+       const u64 interval = 15LLU * 60 * HZ;
+       static const int err_limits[3] = { -1, 3, 10 };
+       struct speed_down_needed_arg arg;
+       struct ata_ering_entry *ent;
+       int err_cat;
+       u64 j64;
+
+       ent = ata_ering_top(&dev->ering);
+       if (!ent)
+               return 0;
+
+       err_cat = ata_eh_categorize_ering_entry(ent);
+       if (err_cat == 0)
+               return 0;
+
+       memset(&arg, 0, sizeof(arg));
+
+       j64 = get_jiffies_64();
+       if (j64 >= interval)
+               arg.since = j64 - interval;
+       else
+               arg.since = 0;
+
+       ata_ering_map(&dev->ering, speed_down_needed_cb, &arg);
+
+       return arg.nr_errors[err_cat] > err_limits[err_cat];
+}
+
+/**
+ *     ata_eh_speed_down - record error and speed down if necessary
+ *     @dev: Failed device
+ *     @is_io: Did the device fail during normal IO?
+ *     @err_mask: err_mask of the error
+ *
+ *     Record error and examine error history to determine whether
+ *     adjusting transmission speed is necessary.  It also sets
+ *     transmission limits appropriately if such adjustment is
+ *     necessary.
+ *
+ *     LOCKING:
+ *     Kernel thread context (may sleep).
+ *
+ *     RETURNS:
+ *     0 on success, -errno otherwise
+ */
+static int ata_eh_speed_down(struct ata_device *dev, int is_io,
+                            unsigned int err_mask)
+{
+       if (!err_mask)
+               return 0;
+
+       /* record error and determine whether speed down is necessary */
+       ata_ering_record(&dev->ering, is_io, err_mask);
+
+       if (!ata_eh_speed_down_needed(dev))
+               return 0;
+
+       /* speed down SATA link speed if possible */
+       if (sata_down_spd_limit(dev->ap) == 0)
+               return ATA_EH_HARDRESET;
+
+       /* lower transfer mode */
+       if (ata_down_xfermask_limit(dev, 0) == 0)
+               return ATA_EH_SOFTRESET;
+
+       ata_dev_printk(dev, KERN_ERR,
+                      "speed down requested but no transfer mode left\n");
+       return 0;
+}
+
+/**
+ *     ata_eh_autopsy - analyze error and determine recovery action
+ *     @ap: ATA port to perform autopsy on
+ *
+ *     Analyze why @ap failed and determine which recovery action is
+ *     needed.  This function also sets more detailed AC_ERR_* values
+ *     and fills sense data for ATAPI CHECK SENSE.
+ *
+ *     LOCKING:
+ *     Kernel thread context (may sleep).
+ */
+static void ata_eh_autopsy(struct ata_port *ap)
+{
+       struct ata_eh_context *ehc = &ap->eh_context;
+       unsigned int all_err_mask = 0;
+       int tag, is_io = 0;
+       u32 serror;
+       int rc;
+
+       DPRINTK("ENTER\n");
+
+       if (ehc->i.flags & ATA_EHI_NO_AUTOPSY)
+               return;
+
+       /* obtain and analyze SError */
+       rc = sata_scr_read(ap, SCR_ERROR, &serror);
+       if (rc == 0) {
+               ehc->i.serror |= serror;
+               ata_eh_analyze_serror(ap);
+       } else if (rc != -EOPNOTSUPP)
+               ehc->i.action |= ATA_EH_HARDRESET;
+
+       /* analyze NCQ failure */
+       ata_eh_analyze_ncq_error(ap);
+
+       /* any real error trumps AC_ERR_OTHER */
+       if (ehc->i.err_mask & ~AC_ERR_OTHER)
+               ehc->i.err_mask &= ~AC_ERR_OTHER;
+
+       all_err_mask |= ehc->i.err_mask;
+
+       for (tag = 0; tag < ATA_MAX_QUEUE; tag++) {
+               struct ata_queued_cmd *qc = __ata_qc_from_tag(ap, tag);
+
+               if (!(qc->flags & ATA_QCFLAG_FAILED))
+                       continue;
+
+               /* inherit upper level err_mask */
+               qc->err_mask |= ehc->i.err_mask;
+
+               /* analyze TF */
+               ehc->i.action |= ata_eh_analyze_tf(qc, &qc->result_tf);
+
+               /* DEV errors are probably spurious in case of ATA_BUS error */
+               if (qc->err_mask & AC_ERR_ATA_BUS)
+                       qc->err_mask &= ~(AC_ERR_DEV | AC_ERR_MEDIA |
+                                         AC_ERR_INVALID);
+
+               /* any real error trumps unknown error */
+               if (qc->err_mask & ~AC_ERR_OTHER)
+                       qc->err_mask &= ~AC_ERR_OTHER;
+
+               /* SENSE_VALID trumps dev/unknown error and revalidation */
+               if (qc->flags & ATA_QCFLAG_SENSE_VALID) {
+                       qc->err_mask &= ~(AC_ERR_DEV | AC_ERR_OTHER);
+                       ehc->i.action &= ~ATA_EH_REVALIDATE;
+               }
+
+               /* accumulate error info */
+               ehc->i.dev = qc->dev;
+               all_err_mask |= qc->err_mask;
+               if (qc->flags & ATA_QCFLAG_IO)
+                       is_io = 1;
+       }
+
+       /* enforce default EH actions */
+       if (ap->pflags & ATA_PFLAG_FROZEN ||
+           all_err_mask & (AC_ERR_HSM | AC_ERR_TIMEOUT))
+               ehc->i.action |= ATA_EH_SOFTRESET;
+       else if (all_err_mask)
+               ehc->i.action |= ATA_EH_REVALIDATE;
+
+       /* if we have offending qcs and the associated failed device */
+       if (ehc->i.dev) {
+               /* speed down */
+               ehc->i.action |= ata_eh_speed_down(ehc->i.dev, is_io,
+                                                  all_err_mask);
+
+               /* perform per-dev EH action only on the offending device */
+               ehc->i.dev_action[ehc->i.dev->devno] |=
+                       ehc->i.action & ATA_EH_PERDEV_MASK;
+               ehc->i.action &= ~ATA_EH_PERDEV_MASK;
+       }
+
+       DPRINTK("EXIT\n");
+}
+
+/**
+ *     ata_eh_report - report error handling to user
+ *     @ap: ATA port EH is going on
+ *
+ *     Report EH to user.
+ *
+ *     LOCKING:
+ *     None.
+ */
+static void ata_eh_report(struct ata_port *ap)
+{
+       struct ata_eh_context *ehc = &ap->eh_context;
+       const char *frozen, *desc;
+       int tag, nr_failed = 0;
+
+       desc = NULL;
+       if (ehc->i.desc[0] != '\0')
+               desc = ehc->i.desc;
+
+       for (tag = 0; tag < ATA_MAX_QUEUE; tag++) {
+               struct ata_queued_cmd *qc = __ata_qc_from_tag(ap, tag);
+
+               if (!(qc->flags & ATA_QCFLAG_FAILED))
+                       continue;
+               if (qc->flags & ATA_QCFLAG_SENSE_VALID && !qc->err_mask)
+                       continue;
+
+               nr_failed++;
+       }
+
+       if (!nr_failed && !ehc->i.err_mask)
+               return;
+
+       frozen = "";
+       if (ap->pflags & ATA_PFLAG_FROZEN)
+               frozen = " frozen";
+
+       if (ehc->i.dev) {
+               ata_dev_printk(ehc->i.dev, KERN_ERR, "exception Emask 0x%x "
+                              "SAct 0x%x SErr 0x%x action 0x%x%s\n",
+                              ehc->i.err_mask, ap->sactive, ehc->i.serror,
+                              ehc->i.action, frozen);
+               if (desc)
+                       ata_dev_printk(ehc->i.dev, KERN_ERR, "(%s)\n", desc);
+       } else {
+               ata_port_printk(ap, KERN_ERR, "exception Emask 0x%x "
+                               "SAct 0x%x SErr 0x%x action 0x%x%s\n",
+                               ehc->i.err_mask, ap->sactive, ehc->i.serror,
+                               ehc->i.action, frozen);
+               if (desc)
+                       ata_port_printk(ap, KERN_ERR, "(%s)\n", desc);
+       }
+
+       for (tag = 0; tag < ATA_MAX_QUEUE; tag++) {
+               struct ata_queued_cmd *qc = __ata_qc_from_tag(ap, tag);
+
+               if (!(qc->flags & ATA_QCFLAG_FAILED) || !qc->err_mask)
+                       continue;
+
+               ata_dev_printk(qc->dev, KERN_ERR, "tag %d cmd 0x%x "
+                              "Emask 0x%x stat 0x%x err 0x%x (%s)\n",
+                              qc->tag, qc->tf.command, qc->err_mask,
+                              qc->result_tf.command, qc->result_tf.feature,
+                              ata_err_string(qc->err_mask));
+       }
+}
+
+static int ata_do_reset(struct ata_port *ap, ata_reset_fn_t reset,
+                       unsigned int *classes)
+{
+       int i, rc;
+
+       for (i = 0; i < ATA_MAX_DEVICES; i++)
+               classes[i] = ATA_DEV_UNKNOWN;
+
+       rc = reset(ap, classes);
+       if (rc)
+               return rc;
+
+       /* If any class isn't ATA_DEV_UNKNOWN, consider classification
+        * is complete and convert all ATA_DEV_UNKNOWN to
+        * ATA_DEV_NONE.
+        */
+       for (i = 0; i < ATA_MAX_DEVICES; i++)
+               if (classes[i] != ATA_DEV_UNKNOWN)
+                       break;
+
+       if (i < ATA_MAX_DEVICES)
+               for (i = 0; i < ATA_MAX_DEVICES; i++)
+                       if (classes[i] == ATA_DEV_UNKNOWN)
+                               classes[i] = ATA_DEV_NONE;
+
+       return 0;
+}
+
+static int ata_eh_followup_srst_needed(int rc, int classify,
+                                      const unsigned int *classes)
+{
+       if (rc == -EAGAIN)
+               return 1;
+       if (rc != 0)
+               return 0;
+       if (classify && classes[0] == ATA_DEV_UNKNOWN)
+               return 1;
+       return 0;
+}
+
+static int ata_eh_reset(struct ata_port *ap, int classify,
+                       ata_prereset_fn_t prereset, ata_reset_fn_t softreset,
+                       ata_reset_fn_t hardreset, ata_postreset_fn_t postreset)
+{
+       struct ata_eh_context *ehc = &ap->eh_context;
+       unsigned int *classes = ehc->classes;
+       int tries = ATA_EH_RESET_TRIES;
+       int verbose = !(ehc->i.flags & ATA_EHI_QUIET);
+       unsigned int action;
+       ata_reset_fn_t reset;
+       int i, did_followup_srst, rc;
+
+       /* about to reset */
+       ata_eh_about_to_do(ap, NULL, ehc->i.action & ATA_EH_RESET_MASK);
+
+       /* Determine which reset to use and record in ehc->i.action.
+        * prereset() may examine and modify it.
+        */
+       action = ehc->i.action;
+       ehc->i.action &= ~ATA_EH_RESET_MASK;
+       if (softreset && (!hardreset || (!sata_set_spd_needed(ap) &&
+                                        !(action & ATA_EH_HARDRESET))))
+               ehc->i.action |= ATA_EH_SOFTRESET;
+       else
+               ehc->i.action |= ATA_EH_HARDRESET;
+
+       if (prereset) {
+               rc = prereset(ap);
+               if (rc) {
+                       ata_port_printk(ap, KERN_ERR,
+                                       "prereset failed (errno=%d)\n", rc);
+                       return rc;
+               }
+       }
+
+       /* prereset() might have modified ehc->i.action */
+       if (ehc->i.action & ATA_EH_HARDRESET)
+               reset = hardreset;
+       else if (ehc->i.action & ATA_EH_SOFTRESET)
+               reset = softreset;
+       else {
+               /* prereset told us not to reset, bang classes and return */
+               for (i = 0; i < ATA_MAX_DEVICES; i++)
+                       classes[i] = ATA_DEV_NONE;
+               return 0;
+       }
+
+       /* did prereset() screw up?  if so, fix up to avoid oopsing */
+       if (!reset) {
+               ata_port_printk(ap, KERN_ERR, "BUG: prereset() requested "
+                               "invalid reset type\n");
+               if (softreset)
+                       reset = softreset;
+               else
+                       reset = hardreset;
+       }
+
+ retry:
+       /* shut up during boot probing */
+       if (verbose)
+               ata_port_printk(ap, KERN_INFO, "%s resetting port\n",
+                               reset == softreset ? "soft" : "hard");
+
+       /* mark that this EH session started with reset */
+       ehc->i.flags |= ATA_EHI_DID_RESET;
+
+       rc = ata_do_reset(ap, reset, classes);
+
+       did_followup_srst = 0;
+       if (reset == hardreset &&
+           ata_eh_followup_srst_needed(rc, classify, classes)) {
+               /* okay, let's do follow-up softreset */
+               did_followup_srst = 1;
+               reset = softreset;
+
+               if (!reset) {
+                       ata_port_printk(ap, KERN_ERR,
+                                       "follow-up softreset required "
+                                       "but no softreset avaliable\n");
+                       return -EINVAL;
+               }
+
+               ata_eh_about_to_do(ap, NULL, ATA_EH_RESET_MASK);
+               rc = ata_do_reset(ap, reset, classes);
+
+               if (rc == 0 && classify &&
+                   classes[0] == ATA_DEV_UNKNOWN) {
+                       ata_port_printk(ap, KERN_ERR,
+                                       "classification failed\n");
+                       return -EINVAL;
+               }
+       }
+
+       if (rc && --tries) {
+               const char *type;
+
+               if (reset == softreset) {
+                       if (did_followup_srst)
+                               type = "follow-up soft";
+                       else
+                               type = "soft";
+               } else
+                       type = "hard";
+
+               ata_port_printk(ap, KERN_WARNING,
+                               "%sreset failed, retrying in 5 secs\n", type);
+               ssleep(5);
+
+               if (reset == hardreset)
+                       sata_down_spd_limit(ap);
+               if (hardreset)
+                       reset = hardreset;
+               goto retry;
+       }
+
+       if (rc == 0) {
+               /* After the reset, the device state is PIO 0 and the
+                * controller state is undefined.  Record the mode.
+                */
+               for (i = 0; i < ATA_MAX_DEVICES; i++)
+                       ap->device[i].pio_mode = XFER_PIO_0;
+
+               if (postreset)
+                       postreset(ap, classes);
+
+               /* reset successful, schedule revalidation */
+               ata_eh_done(ap, NULL, ehc->i.action & ATA_EH_RESET_MASK);
+               ehc->i.action |= ATA_EH_REVALIDATE;
+       }
+
+       return rc;
+}
+
+static int ata_eh_revalidate_and_attach(struct ata_port *ap,
+                                       struct ata_device **r_failed_dev)
+{
+       struct ata_eh_context *ehc = &ap->eh_context;
+       struct ata_device *dev;
+       unsigned long flags;
+       int i, rc = 0;
+
+       DPRINTK("ENTER\n");
+
+       for (i = 0; i < ATA_MAX_DEVICES; i++) {
+               unsigned int action;
+
+               dev = &ap->device[i];
+               action = ata_eh_dev_action(dev);
+
+               if (action & ATA_EH_REVALIDATE && ata_dev_ready(dev)) {
+                       if (ata_port_offline(ap)) {
+                               rc = -EIO;
+                               break;
+                       }
+
+                       ata_eh_about_to_do(ap, dev, ATA_EH_REVALIDATE);
+                       rc = ata_dev_revalidate(dev,
+                                       ehc->i.flags & ATA_EHI_DID_RESET);
+                       if (rc)
+                               break;
+
+                       ata_eh_done(ap, dev, ATA_EH_REVALIDATE);
+
+                       /* schedule the scsi_rescan_device() here */
+                       queue_work(ata_aux_wq, &(ap->scsi_rescan_task));
+               } else if (dev->class == ATA_DEV_UNKNOWN &&
+                          ehc->tries[dev->devno] &&
+                          ata_class_enabled(ehc->classes[dev->devno])) {
+                       dev->class = ehc->classes[dev->devno];
+
+                       rc = ata_dev_read_id(dev, &dev->class, 1, dev->id);
+                       if (rc == 0)
+                               rc = ata_dev_configure(dev, 1);
+
+                       if (rc) {
+                               dev->class = ATA_DEV_UNKNOWN;
+                               break;
+                       }
+
+                       spin_lock_irqsave(ap->lock, flags);
+                       ap->pflags |= ATA_PFLAG_SCSI_HOTPLUG;
+                       spin_unlock_irqrestore(ap->lock, flags);
+               }
+       }
+
+       if (rc)
+               *r_failed_dev = dev;
+
+       DPRINTK("EXIT\n");
+       return rc;
+}
+
+/**
+ *     ata_eh_suspend - handle suspend EH action
+ *     @ap: target host port
+ *     @r_failed_dev: result parameter to indicate failing device
+ *
+ *     Handle suspend EH action.  Disk devices are spinned down and
+ *     other types of devices are just marked suspended.  Once
+ *     suspended, no EH action to the device is allowed until it is
+ *     resumed.
+ *
+ *     LOCKING:
+ *     Kernel thread context (may sleep).
+ *
+ *     RETURNS:
+ *     0 on success, -errno otherwise
+ */
+static int ata_eh_suspend(struct ata_port *ap, struct ata_device **r_failed_dev)
+{
+       struct ata_device *dev;
+       int i, rc = 0;
+
+       DPRINTK("ENTER\n");
+
+       for (i = 0; i < ATA_MAX_DEVICES; i++) {
+               unsigned long flags;
+               unsigned int action, err_mask;
+
+               dev = &ap->device[i];
+               action = ata_eh_dev_action(dev);
+
+               if (!ata_dev_enabled(dev) || !(action & ATA_EH_SUSPEND))
+                       continue;
+
+               WARN_ON(dev->flags & ATA_DFLAG_SUSPENDED);
+
+               ata_eh_about_to_do(ap, dev, ATA_EH_SUSPEND);
+
+               if (dev->class == ATA_DEV_ATA && !(action & ATA_EH_PM_FREEZE)) {
+                       /* flush cache */
+                       rc = ata_flush_cache(dev);
+                       if (rc)
+                               break;
+
+                       /* spin down */
+                       err_mask = ata_do_simple_cmd(dev, ATA_CMD_STANDBYNOW1);
+                       if (err_mask) {
+                               ata_dev_printk(dev, KERN_ERR, "failed to "
+                                              "spin down (err_mask=0x%x)\n",
+                                              err_mask);
+                               rc = -EIO;
+                               break;
+                       }
+               }
+
+               spin_lock_irqsave(ap->lock, flags);
+               dev->flags |= ATA_DFLAG_SUSPENDED;
+               spin_unlock_irqrestore(ap->lock, flags);
+
+               ata_eh_done(ap, dev, ATA_EH_SUSPEND);
+       }
+
+       if (rc)
+               *r_failed_dev = dev;
+
+       DPRINTK("EXIT\n");
+       return 0;
+}
+
+/**
+ *     ata_eh_prep_resume - prep for resume EH action
+ *     @ap: target host port
+ *
+ *     Clear SUSPENDED in preparation for scheduled resume actions.
+ *     This allows other parts of EH to access the devices being
+ *     resumed.
+ *
+ *     LOCKING:
+ *     Kernel thread context (may sleep).
+ */
+static void ata_eh_prep_resume(struct ata_port *ap)
+{
+       struct ata_device *dev;
+       unsigned long flags;
+       int i;
+
+       DPRINTK("ENTER\n");
+
+       for (i = 0; i < ATA_MAX_DEVICES; i++) {
+               unsigned int action;
+
+               dev = &ap->device[i];
+               action = ata_eh_dev_action(dev);
+
+               if (!ata_dev_enabled(dev) || !(action & ATA_EH_RESUME))
+                       continue;
+
+               spin_lock_irqsave(ap->lock, flags);
+               dev->flags &= ~ATA_DFLAG_SUSPENDED;
+               spin_unlock_irqrestore(ap->lock, flags);
+       }
+
+       DPRINTK("EXIT\n");
+}
+
+/**
+ *     ata_eh_resume - handle resume EH action
+ *     @ap: target host port
+ *     @r_failed_dev: result parameter to indicate failing device
+ *
+ *     Handle resume EH action.  Target devices are already reset and
+ *     revalidated.  Spinning up is the only operation left.
+ *
+ *     LOCKING:
+ *     Kernel thread context (may sleep).
+ *
+ *     RETURNS:
+ *     0 on success, -errno otherwise
+ */
+static int ata_eh_resume(struct ata_port *ap, struct ata_device **r_failed_dev)
+{
+       struct ata_device *dev;
+       int i, rc = 0;
+
+       DPRINTK("ENTER\n");
+
+       for (i = 0; i < ATA_MAX_DEVICES; i++) {
+               unsigned int action, err_mask;
+
+               dev = &ap->device[i];
+               action = ata_eh_dev_action(dev);
+
+               if (!ata_dev_enabled(dev) || !(action & ATA_EH_RESUME))
+                       continue;
+
+               ata_eh_about_to_do(ap, dev, ATA_EH_RESUME);
+
+               if (dev->class == ATA_DEV_ATA && !(action & ATA_EH_PM_FREEZE)) {
+                       err_mask = ata_do_simple_cmd(dev,
+                                                    ATA_CMD_IDLEIMMEDIATE);
+                       if (err_mask) {
+                               ata_dev_printk(dev, KERN_ERR, "failed to "
+                                              "spin up (err_mask=0x%x)\n",
+                                              err_mask);
+                               rc = -EIO;
+                               break;
+                       }
+               }
+
+               ata_eh_done(ap, dev, ATA_EH_RESUME);
+       }
+
+       if (rc)
+               *r_failed_dev = dev;
+
+       DPRINTK("EXIT\n");
+       return 0;
+}
+
+static int ata_port_nr_enabled(struct ata_port *ap)
+{
+       int i, cnt = 0;
+
+       for (i = 0; i < ATA_MAX_DEVICES; i++)
+               if (ata_dev_enabled(&ap->device[i]))
+                       cnt++;
+       return cnt;
+}
+
+static int ata_port_nr_vacant(struct ata_port *ap)
+{
+       int i, cnt = 0;
+
+       for (i = 0; i < ATA_MAX_DEVICES; i++)
+               if (ap->device[i].class == ATA_DEV_UNKNOWN)
+                       cnt++;
+       return cnt;
+}
+
+static int ata_eh_skip_recovery(struct ata_port *ap)
+{
+       struct ata_eh_context *ehc = &ap->eh_context;
+       int i;
+
+       /* skip if all possible devices are suspended */
+       for (i = 0; i < ata_port_max_devices(ap); i++) {
+               struct ata_device *dev = &ap->device[i];
+
+               if (!(dev->flags & ATA_DFLAG_SUSPENDED))
+                       break;
+       }
+
+       if (i == ata_port_max_devices(ap))
+               return 1;
+
+       /* thaw frozen port, resume link and recover failed devices */
+       if ((ap->pflags & ATA_PFLAG_FROZEN) ||
+           (ehc->i.flags & ATA_EHI_RESUME_LINK) || ata_port_nr_enabled(ap))
+               return 0;
+
+       /* skip if class codes for all vacant slots are ATA_DEV_NONE */
+       for (i = 0; i < ATA_MAX_DEVICES; i++) {
+               struct ata_device *dev = &ap->device[i];
+
+               if (dev->class == ATA_DEV_UNKNOWN &&
+                   ehc->classes[dev->devno] != ATA_DEV_NONE)
+                       return 0;
+       }
+
+       return 1;
+}
+
+/**
+ *     ata_eh_recover - recover host port after error
+ *     @ap: host port to recover
+ *     @prereset: prereset method (can be NULL)
+ *     @softreset: softreset method (can be NULL)
+ *     @hardreset: hardreset method (can be NULL)
+ *     @postreset: postreset method (can be NULL)
+ *
+ *     This is the alpha and omega, eum and yang, heart and soul of
+ *     libata exception handling.  On entry, actions required to
+ *     recover the port and hotplug requests are recorded in
+ *     eh_context.  This function executes all the operations with
+ *     appropriate retrials and fallbacks to resurrect failed
+ *     devices, detach goners and greet newcomers.
+ *
+ *     LOCKING:
+ *     Kernel thread context (may sleep).
+ *
+ *     RETURNS:
+ *     0 on success, -errno on failure.
+ */
+static int ata_eh_recover(struct ata_port *ap, ata_prereset_fn_t prereset,
+                         ata_reset_fn_t softreset, ata_reset_fn_t hardreset,
+                         ata_postreset_fn_t postreset)
+{
+       struct ata_eh_context *ehc = &ap->eh_context;
+       struct ata_device *dev;
+       int down_xfermask, i, rc;
+
+       DPRINTK("ENTER\n");
+
+       /* prep for recovery */
+       for (i = 0; i < ATA_MAX_DEVICES; i++) {
+               dev = &ap->device[i];
+
+               ehc->tries[dev->devno] = ATA_EH_DEV_TRIES;
+
+               /* process hotplug request */
+               if (dev->flags & ATA_DFLAG_DETACH)
+                       ata_eh_detach_dev(dev);
+
+               if (!ata_dev_enabled(dev) &&
+                   ((ehc->i.probe_mask & (1 << dev->devno)) &&
+                    !(ehc->did_probe_mask & (1 << dev->devno)))) {
+                       ata_eh_detach_dev(dev);
+                       ata_dev_init(dev);
+                       ehc->did_probe_mask |= (1 << dev->devno);
+                       ehc->i.action |= ATA_EH_SOFTRESET;
+               }
+       }
+
+ retry:
+       down_xfermask = 0;
+       rc = 0;
+
+       /* if UNLOADING, finish immediately */
+       if (ap->pflags & ATA_PFLAG_UNLOADING)
+               goto out;
+
+       /* prep for resume */
+       ata_eh_prep_resume(ap);
+
+       /* skip EH if possible. */
+       if (ata_eh_skip_recovery(ap))
+               ehc->i.action = 0;
+
+       for (i = 0; i < ATA_MAX_DEVICES; i++)
+               ehc->classes[i] = ATA_DEV_UNKNOWN;
+
+       /* reset */
+       if (ehc->i.action & ATA_EH_RESET_MASK) {
+               ata_eh_freeze_port(ap);
+
+               rc = ata_eh_reset(ap, ata_port_nr_vacant(ap), prereset,
+                                 softreset, hardreset, postreset);
+               if (rc) {
+                       ata_port_printk(ap, KERN_ERR,
+                                       "reset failed, giving up\n");
+                       goto out;
+               }
+
+               ata_eh_thaw_port(ap);
+       }
+
+       /* revalidate existing devices and attach new ones */
+       rc = ata_eh_revalidate_and_attach(ap, &dev);
+       if (rc)
+               goto dev_fail;
+
+       /* resume devices */
+       rc = ata_eh_resume(ap, &dev);
+       if (rc)
+               goto dev_fail;
+
+       /* configure transfer mode if the port has been reset */
+       if (ehc->i.flags & ATA_EHI_DID_RESET) {
+               rc = ata_set_mode(ap, &dev);
+               if (rc) {
+                       down_xfermask = 1;
+                       goto dev_fail;
+               }
+       }
+
+       /* suspend devices */
+       rc = ata_eh_suspend(ap, &dev);
+       if (rc)
+               goto dev_fail;
+
+       goto out;
+
+ dev_fail:
+       switch (rc) {
+       case -ENODEV:
+               /* device missing, schedule probing */
+               ehc->i.probe_mask |= (1 << dev->devno);
+       case -EINVAL:
+               ehc->tries[dev->devno] = 0;
+               break;
+       case -EIO:
+               sata_down_spd_limit(ap);
+       default:
+               ehc->tries[dev->devno]--;
+               if (down_xfermask &&
+                   ata_down_xfermask_limit(dev, ehc->tries[dev->devno] == 1))
+                       ehc->tries[dev->devno] = 0;
+       }
+
+       if (ata_dev_enabled(dev) && !ehc->tries[dev->devno]) {
+               /* disable device if it has used up all its chances */
+               ata_dev_disable(dev);
+
+               /* detach if offline */
+               if (ata_port_offline(ap))
+                       ata_eh_detach_dev(dev);
+
+               /* probe if requested */
+               if ((ehc->i.probe_mask & (1 << dev->devno)) &&
+                   !(ehc->did_probe_mask & (1 << dev->devno))) {
+                       ata_eh_detach_dev(dev);
+                       ata_dev_init(dev);
+
+                       ehc->tries[dev->devno] = ATA_EH_DEV_TRIES;
+                       ehc->did_probe_mask |= (1 << dev->devno);
+                       ehc->i.action |= ATA_EH_SOFTRESET;
+               }
+       } else {
+               /* soft didn't work?  be haaaaard */
+               if (ehc->i.flags & ATA_EHI_DID_RESET)
+                       ehc->i.action |= ATA_EH_HARDRESET;
+               else
+                       ehc->i.action |= ATA_EH_SOFTRESET;
+       }
+
+       if (ata_port_nr_enabled(ap)) {
+               ata_port_printk(ap, KERN_WARNING, "failed to recover some "
+                               "devices, retrying in 5 secs\n");
+               ssleep(5);
+       } else {
+               /* no device left, repeat fast */
+               msleep(500);
+       }
+
+       goto retry;
+
+ out:
+       if (rc) {
+               for (i = 0; i < ATA_MAX_DEVICES; i++)
+                       ata_dev_disable(&ap->device[i]);
+       }
+
+       DPRINTK("EXIT, rc=%d\n", rc);
+       return rc;
+}
+
+/**
+ *     ata_eh_finish - finish up EH
+ *     @ap: host port to finish EH for
+ *
+ *     Recovery is complete.  Clean up EH states and retry or finish
+ *     failed qcs.
+ *
+ *     LOCKING:
+ *     None.
+ */
+static void ata_eh_finish(struct ata_port *ap)
+{
+       int tag;
+
+       /* retry or finish qcs */
+       for (tag = 0; tag < ATA_MAX_QUEUE; tag++) {
+               struct ata_queued_cmd *qc = __ata_qc_from_tag(ap, tag);
+
+               if (!(qc->flags & ATA_QCFLAG_FAILED))
+                       continue;
+
+               if (qc->err_mask) {
+                       /* FIXME: Once EH migration is complete,
+                        * generate sense data in this function,
+                        * considering both err_mask and tf.
+                        */
+                       if (qc->err_mask & AC_ERR_INVALID)
+                               ata_eh_qc_complete(qc);
+                       else
+                               ata_eh_qc_retry(qc);
+               } else {
+                       if (qc->flags & ATA_QCFLAG_SENSE_VALID) {
+                               ata_eh_qc_complete(qc);
+                       } else {
+                               /* feed zero TF to sense generation */
+                               memset(&qc->result_tf, 0, sizeof(qc->result_tf));
+                               ata_eh_qc_retry(qc);
+                       }
+               }
+       }
+}
+
+/**
+ *     ata_do_eh - do standard error handling
+ *     @ap: host port to handle error for
+ *     @prereset: prereset method (can be NULL)
+ *     @softreset: softreset method (can be NULL)
+ *     @hardreset: hardreset method (can be NULL)
+ *     @postreset: postreset method (can be NULL)
+ *
+ *     Perform standard error handling sequence.
+ *
+ *     LOCKING:
+ *     Kernel thread context (may sleep).
+ */
+void ata_do_eh(struct ata_port *ap, ata_prereset_fn_t prereset,
+              ata_reset_fn_t softreset, ata_reset_fn_t hardreset,
+              ata_postreset_fn_t postreset)
+{
+       ata_eh_autopsy(ap);
+       ata_eh_report(ap);
+       ata_eh_recover(ap, prereset, softreset, hardreset, postreset);
+       ata_eh_finish(ap);
+}
+
+/**
+ *     ata_eh_handle_port_suspend - perform port suspend operation
+ *     @ap: port to suspend
+ *
+ *     Suspend @ap.
+ *
+ *     LOCKING:
+ *     Kernel thread context (may sleep).
+ */
+static void ata_eh_handle_port_suspend(struct ata_port *ap)
+{
+       unsigned long flags;
+       int rc = 0;
+
+       /* are we suspending? */
+       spin_lock_irqsave(ap->lock, flags);
+       if (!(ap->pflags & ATA_PFLAG_PM_PENDING) ||
+           ap->pm_mesg.event == PM_EVENT_ON) {
+               spin_unlock_irqrestore(ap->lock, flags);
+               return;
+       }
+       spin_unlock_irqrestore(ap->lock, flags);
+
+       WARN_ON(ap->pflags & ATA_PFLAG_SUSPENDED);
+
+       /* suspend */
+       ata_eh_freeze_port(ap);
+
+       if (ap->ops->port_suspend)
+               rc = ap->ops->port_suspend(ap, ap->pm_mesg);
+
+       /* report result */
+       spin_lock_irqsave(ap->lock, flags);
+
+       ap->pflags &= ~ATA_PFLAG_PM_PENDING;
+       if (rc == 0)
+               ap->pflags |= ATA_PFLAG_SUSPENDED;
+       else
+               ata_port_schedule_eh(ap);
+
+       if (ap->pm_result) {
+               *ap->pm_result = rc;
+               ap->pm_result = NULL;
+       }
+
+       spin_unlock_irqrestore(ap->lock, flags);
+
+       return;
+}
+
+/**
+ *     ata_eh_handle_port_resume - perform port resume operation
+ *     @ap: port to resume
+ *
+ *     Resume @ap.
+ *
+ *     This function also waits upto one second until all devices
+ *     hanging off this port requests resume EH action.  This is to
+ *     prevent invoking EH and thus reset multiple times on resume.
+ *
+ *     On DPM resume, where some of devices might not be resumed
+ *     together, this may delay port resume upto one second, but such
+ *     DPM resumes are rare and 1 sec delay isn't too bad.
+ *
+ *     LOCKING:
+ *     Kernel thread context (may sleep).
+ */
+static void ata_eh_handle_port_resume(struct ata_port *ap)
+{
+       unsigned long timeout;
+       unsigned long flags;
+       int i, rc = 0;
+
+       /* are we resuming? */
+       spin_lock_irqsave(ap->lock, flags);
+       if (!(ap->pflags & ATA_PFLAG_PM_PENDING) ||
+           ap->pm_mesg.event != PM_EVENT_ON) {
+               spin_unlock_irqrestore(ap->lock, flags);
+               return;
+       }
+       spin_unlock_irqrestore(ap->lock, flags);
+
+       /* spurious? */
+       if (!(ap->pflags & ATA_PFLAG_SUSPENDED))
+               goto done;
+
+       if (ap->ops->port_resume)
+               rc = ap->ops->port_resume(ap);
+
+       /* give devices time to request EH */
+       timeout = jiffies + HZ; /* 1s max */
+       while (1) {
+               for (i = 0; i < ATA_MAX_DEVICES; i++) {
+                       struct ata_device *dev = &ap->device[i];
+                       unsigned int action = ata_eh_dev_action(dev);
+
+                       if ((dev->flags & ATA_DFLAG_SUSPENDED) &&
+                           !(action & ATA_EH_RESUME))
+                               break;
+               }
+
+               if (i == ATA_MAX_DEVICES || time_after(jiffies, timeout))
+                       break;
+               msleep(10);
+       }
+
+ done:
+       spin_lock_irqsave(ap->lock, flags);
+       ap->pflags &= ~(ATA_PFLAG_PM_PENDING | ATA_PFLAG_SUSPENDED);
+       if (ap->pm_result) {
+               *ap->pm_result = rc;
+               ap->pm_result = NULL;
+       }
+       spin_unlock_irqrestore(ap->lock, flags);
+}
diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c
new file mode 100644 (file)
index 0000000..d168e34
--- /dev/null
@@ -0,0 +1,3322 @@
+/*
+ *  libata-scsi.c - helper library for ATA
+ *
+ *  Maintained by:  Jeff Garzik <jgarzik@pobox.com>
+ *                 Please ALWAYS copy linux-ide@vger.kernel.org
+ *                 on emails.
+ *
+ *  Copyright 2003-2004 Red Hat, Inc.  All rights reserved.
+ *  Copyright 2003-2004 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.t10.org/
+ *  - http://www.t13.org/
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/blkdev.h>
+#include <linux/spinlock.h>
+#include <scsi/scsi.h>
+#include <scsi/scsi_host.h>
+#include <scsi/scsi_cmnd.h>
+#include <scsi/scsi_eh.h>
+#include <scsi/scsi_device.h>
+#include <scsi/scsi_tcq.h>
+#include <scsi/scsi_transport.h>
+#include <linux/libata.h>
+#include <linux/hdreg.h>
+#include <asm/uaccess.h>
+
+#include "libata.h"
+
+#define SECTOR_SIZE    512
+
+typedef unsigned int (*ata_xlat_func_t)(struct ata_queued_cmd *qc, const u8 *scsicmd);
+
+static struct ata_device * __ata_scsi_find_dev(struct ata_port *ap,
+                                       const struct scsi_device *scsidev);
+static struct ata_device * ata_scsi_find_dev(struct ata_port *ap,
+                                           const struct scsi_device *scsidev);
+static int ata_scsi_user_scan(struct Scsi_Host *shost, unsigned int channel,
+                             unsigned int id, unsigned int lun);
+
+
+#define RW_RECOVERY_MPAGE 0x1
+#define RW_RECOVERY_MPAGE_LEN 12
+#define CACHE_MPAGE 0x8
+#define CACHE_MPAGE_LEN 20
+#define CONTROL_MPAGE 0xa
+#define CONTROL_MPAGE_LEN 12
+#define ALL_MPAGES 0x3f
+#define ALL_SUB_MPAGES 0xff
+
+
+static const u8 def_rw_recovery_mpage[] = {
+       RW_RECOVERY_MPAGE,
+       RW_RECOVERY_MPAGE_LEN - 2,
+       (1 << 7) |      /* AWRE, sat-r06 say it shall be 0 */
+           (1 << 6),   /* ARRE (auto read reallocation) */
+       0,              /* read retry count */
+       0, 0, 0, 0,
+       0,              /* write retry count */
+       0, 0, 0
+};
+
+static const u8 def_cache_mpage[CACHE_MPAGE_LEN] = {
+       CACHE_MPAGE,
+       CACHE_MPAGE_LEN - 2,
+       0,              /* contains WCE, needs to be 0 for logic */
+       0, 0, 0, 0, 0, 0, 0, 0, 0,
+       0,              /* contains DRA, needs to be 0 for logic */
+       0, 0, 0, 0, 0, 0, 0
+};
+
+static const u8 def_control_mpage[CONTROL_MPAGE_LEN] = {
+       CONTROL_MPAGE,
+       CONTROL_MPAGE_LEN - 2,
+       2,      /* DSENSE=0, GLTSD=1 */
+       0,      /* [QAM+QERR may be 1, see 05-359r1] */
+       0, 0, 0, 0, 0xff, 0xff,
+       0, 30   /* extended self test time, see 05-359r1 */
+};
+
+/*
+ * libata transport template.  libata doesn't do real transport stuff.
+ * It just needs the eh_timed_out hook.
+ */
+struct scsi_transport_template ata_scsi_transport_template = {
+       .eh_strategy_handler    = ata_scsi_error,
+       .eh_timed_out           = ata_scsi_timed_out,
+       .user_scan              = ata_scsi_user_scan,
+};
+
+
+static void ata_scsi_invalid_field(struct scsi_cmnd *cmd,
+                                  void (*done)(struct scsi_cmnd *))
+{
+       ata_scsi_set_sense(cmd, ILLEGAL_REQUEST, 0x24, 0x0);
+       /* "Invalid field in cbd" */
+       done(cmd);
+}
+
+/**
+ *     ata_std_bios_param - generic bios head/sector/cylinder calculator used by sd.
+ *     @sdev: SCSI device for which BIOS geometry is to be determined
+ *     @bdev: block device associated with @sdev
+ *     @capacity: capacity of SCSI device
+ *     @geom: location to which geometry will be output
+ *
+ *     Generic bios head/sector/cylinder calculator
+ *     used by sd. Most BIOSes nowadays expect a XXX/255/16  (CHS)
+ *     mapping. Some situations may arise where the disk is not
+ *     bootable if this is not used.
+ *
+ *     LOCKING:
+ *     Defined by the SCSI layer.  We don't really care.
+ *
+ *     RETURNS:
+ *     Zero.
+ */
+int ata_std_bios_param(struct scsi_device *sdev, struct block_device *bdev,
+                      sector_t capacity, int geom[])
+{
+       geom[0] = 255;
+       geom[1] = 63;
+       sector_div(capacity, 255*63);
+       geom[2] = capacity;
+
+       return 0;
+}
+
+/**
+ *     ata_cmd_ioctl - Handler for HDIO_DRIVE_CMD ioctl
+ *     @scsidev: Device to which we are issuing command
+ *     @arg: User provided data for issuing command
+ *
+ *     LOCKING:
+ *     Defined by the SCSI layer.  We don't really care.
+ *
+ *     RETURNS:
+ *     Zero on success, negative errno on error.
+ */
+
+int ata_cmd_ioctl(struct scsi_device *scsidev, void __user *arg)
+{
+       int rc = 0;
+       u8 scsi_cmd[MAX_COMMAND_SIZE];
+       u8 args[4], *argbuf = NULL;
+       int argsize = 0;
+       struct scsi_sense_hdr sshdr;
+       enum dma_data_direction data_dir;
+
+       if (arg == NULL)
+               return -EINVAL;
+
+       if (copy_from_user(args, arg, sizeof(args)))
+               return -EFAULT;
+
+       memset(scsi_cmd, 0, sizeof(scsi_cmd));
+
+       if (args[3]) {
+               argsize = SECTOR_SIZE * args[3];
+               argbuf = kmalloc(argsize, GFP_KERNEL);
+               if (argbuf == NULL) {
+                       rc = -ENOMEM;
+                       goto error;
+               }
+
+               scsi_cmd[1]  = (4 << 1); /* PIO Data-in */
+               scsi_cmd[2]  = 0x0e;     /* no off.line or cc, read from dev,
+                                           block count in sector count field */
+               data_dir = DMA_FROM_DEVICE;
+       } else {
+               scsi_cmd[1]  = (3 << 1); /* Non-data */
+               /* scsi_cmd[2] is already 0 -- no off.line, cc, or data xfer */
+               data_dir = DMA_NONE;
+       }
+
+       scsi_cmd[0] = ATA_16;
+
+       scsi_cmd[4] = args[2];
+       if (args[0] == WIN_SMART) { /* hack -- ide driver does this too... */
+               scsi_cmd[6]  = args[3];
+               scsi_cmd[8]  = args[1];
+               scsi_cmd[10] = 0x4f;
+               scsi_cmd[12] = 0xc2;
+       } else {
+               scsi_cmd[6]  = args[1];
+       }
+       scsi_cmd[14] = args[0];
+
+       /* Good values for timeout and retries?  Values below
+          from scsi_ioctl_send_command() for default case... */
+       if (scsi_execute_req(scsidev, scsi_cmd, data_dir, argbuf, argsize,
+                            &sshdr, (10*HZ), 5)) {
+               rc = -EIO;
+               goto error;
+       }
+
+       /* Need code to retrieve data from check condition? */
+
+       if ((argbuf)
+        && copy_to_user(arg + sizeof(args), argbuf, argsize))
+               rc = -EFAULT;
+error:
+       kfree(argbuf);
+       return rc;
+}
+
+/**
+ *     ata_task_ioctl - Handler for HDIO_DRIVE_TASK ioctl
+ *     @scsidev: Device to which we are issuing command
+ *     @arg: User provided data for issuing command
+ *
+ *     LOCKING:
+ *     Defined by the SCSI layer.  We don't really care.
+ *
+ *     RETURNS:
+ *     Zero on success, negative errno on error.
+ */
+int ata_task_ioctl(struct scsi_device *scsidev, void __user *arg)
+{
+       int rc = 0;
+       u8 scsi_cmd[MAX_COMMAND_SIZE];
+       u8 args[7];
+       struct scsi_sense_hdr sshdr;
+
+       if (arg == NULL)
+               return -EINVAL;
+
+       if (copy_from_user(args, arg, sizeof(args)))
+               return -EFAULT;
+
+       memset(scsi_cmd, 0, sizeof(scsi_cmd));
+       scsi_cmd[0]  = ATA_16;
+       scsi_cmd[1]  = (3 << 1); /* Non-data */
+       /* scsi_cmd[2] is already 0 -- no off.line, cc, or data xfer */
+       scsi_cmd[4]  = args[1];
+       scsi_cmd[6]  = args[2];
+       scsi_cmd[8]  = args[3];
+       scsi_cmd[10] = args[4];
+       scsi_cmd[12] = args[5];
+       scsi_cmd[14] = args[0];
+
+       /* Good values for timeout and retries?  Values below
+          from scsi_ioctl_send_command() for default case... */
+       if (scsi_execute_req(scsidev, scsi_cmd, DMA_NONE, NULL, 0, &sshdr,
+                            (10*HZ), 5))
+               rc = -EIO;
+
+       /* Need code to retrieve data from check condition? */
+       return rc;
+}
+
+int ata_scsi_ioctl(struct scsi_device *scsidev, int cmd, void __user *arg)
+{
+       int val = -EINVAL, rc = -EINVAL;
+
+       switch (cmd) {
+       case ATA_IOC_GET_IO32:
+               val = 0;
+               if (copy_to_user(arg, &val, 1))
+                       return -EFAULT;
+               return 0;
+
+       case ATA_IOC_SET_IO32:
+               val = (unsigned long) arg;
+               if (val != 0)
+                       return -EINVAL;
+               return 0;
+
+       case HDIO_DRIVE_CMD:
+               if (!capable(CAP_SYS_ADMIN) || !capable(CAP_SYS_RAWIO))
+                       return -EACCES;
+               return ata_cmd_ioctl(scsidev, arg);
+
+       case HDIO_DRIVE_TASK:
+               if (!capable(CAP_SYS_ADMIN) || !capable(CAP_SYS_RAWIO))
+                       return -EACCES;
+               return ata_task_ioctl(scsidev, arg);
+
+       default:
+               rc = -ENOTTY;
+               break;
+       }
+
+       return rc;
+}
+
+/**
+ *     ata_scsi_qc_new - acquire new ata_queued_cmd reference
+ *     @dev: ATA device to which the new command is attached
+ *     @cmd: SCSI command that originated this ATA command
+ *     @done: SCSI command completion function
+ *
+ *     Obtain a reference to an unused ata_queued_cmd structure,
+ *     which is the basic libata structure representing a single
+ *     ATA command sent to the hardware.
+ *
+ *     If a command was available, fill in the SCSI-specific
+ *     portions of the structure with information on the
+ *     current command.
+ *
+ *     LOCKING:
+ *     spin_lock_irqsave(host_set lock)
+ *
+ *     RETURNS:
+ *     Command allocated, or %NULL if none available.
+ */
+struct ata_queued_cmd *ata_scsi_qc_new(struct ata_device *dev,
+                                      struct scsi_cmnd *cmd,
+                                      void (*done)(struct scsi_cmnd *))
+{
+       struct ata_queued_cmd *qc;
+
+       qc = ata_qc_new_init(dev);
+       if (qc) {
+               qc->scsicmd = cmd;
+               qc->scsidone = done;
+
+               if (cmd->use_sg) {
+                       qc->__sg = (struct scatterlist *) cmd->request_buffer;
+                       qc->n_elem = cmd->use_sg;
+               } else {
+                       qc->__sg = &qc->sgent;
+                       qc->n_elem = 1;
+               }
+       } else {
+               cmd->result = (DID_OK << 16) | (QUEUE_FULL << 1);
+               done(cmd);
+       }
+
+       return qc;
+}
+
+/**
+ *     ata_dump_status - user friendly display of error info
+ *     @id: id of the port in question
+ *     @tf: ptr to filled out taskfile
+ *
+ *     Decode and dump the ATA error/status registers for the user so
+ *     that they have some idea what really happened at the non
+ *     make-believe layer.
+ *
+ *     LOCKING:
+ *     inherited from caller
+ */
+void ata_dump_status(unsigned id, struct ata_taskfile *tf)
+{
+       u8 stat = tf->command, err = tf->feature;
+
+       printk(KERN_WARNING "ata%u: status=0x%02x { ", id, stat);
+       if (stat & ATA_BUSY) {
+               printk("Busy }\n");     /* Data is not valid in this case */
+       } else {
+               if (stat & 0x40)        printk("DriveReady ");
+               if (stat & 0x20)        printk("DeviceFault ");
+               if (stat & 0x10)        printk("SeekComplete ");
+               if (stat & 0x08)        printk("DataRequest ");
+               if (stat & 0x04)        printk("CorrectedError ");
+               if (stat & 0x02)        printk("Index ");
+               if (stat & 0x01)        printk("Error ");
+               printk("}\n");
+
+               if (err) {
+                       printk(KERN_WARNING "ata%u: error=0x%02x { ", id, err);
+                       if (err & 0x04)         printk("DriveStatusError ");
+                       if (err & 0x80) {
+                               if (err & 0x04) printk("BadCRC ");
+                               else            printk("Sector ");
+                       }
+                       if (err & 0x40)         printk("UncorrectableError ");
+                       if (err & 0x10)         printk("SectorIdNotFound ");
+                       if (err & 0x02)         printk("TrackZeroNotFound ");
+                       if (err & 0x01)         printk("AddrMarkNotFound ");
+                       printk("}\n");
+               }
+       }
+}
+
+/**
+ *     ata_scsi_device_suspend - suspend ATA device associated with sdev
+ *     @sdev: the SCSI device to suspend
+ *     @mesg: target power management message
+ *
+ *     Request suspend EH action on the ATA device associated with
+ *     @sdev and wait for the operation to complete.
+ *
+ *     LOCKING:
+ *     Kernel thread context (may sleep).
+ *
+ *     RETURNS:
+ *     0 on success, -errno otherwise.
+ */
+int ata_scsi_device_suspend(struct scsi_device *sdev, pm_message_t mesg)
+{
+       struct ata_port *ap = ata_shost_to_port(sdev->host);
+       struct ata_device *dev = ata_scsi_find_dev(ap, sdev);
+       unsigned long flags;
+       unsigned int action;
+       int rc = 0;
+
+       if (!dev)
+               goto out;
+
+       spin_lock_irqsave(ap->lock, flags);
+
+       /* wait for the previous resume to complete */
+       while (dev->flags & ATA_DFLAG_SUSPENDED) {
+               spin_unlock_irqrestore(ap->lock, flags);
+               ata_port_wait_eh(ap);
+               spin_lock_irqsave(ap->lock, flags);
+       }
+
+       /* if @sdev is already detached, nothing to do */
+       if (sdev->sdev_state == SDEV_OFFLINE ||
+           sdev->sdev_state == SDEV_CANCEL || sdev->sdev_state == SDEV_DEL)
+               goto out_unlock;
+
+       /* request suspend */
+       action = ATA_EH_SUSPEND;
+       if (mesg.event != PM_EVENT_SUSPEND)
+               action |= ATA_EH_PM_FREEZE;
+       ap->eh_info.dev_action[dev->devno] |= action;
+       ap->eh_info.flags |= ATA_EHI_QUIET;
+       ata_port_schedule_eh(ap);
+
+       spin_unlock_irqrestore(ap->lock, flags);
+
+       /* wait for EH to do the job */
+       ata_port_wait_eh(ap);
+
+       spin_lock_irqsave(ap->lock, flags);
+
+       /* If @sdev is still attached but the associated ATA device
+        * isn't suspended, the operation failed.
+        */
+       if (sdev->sdev_state != SDEV_OFFLINE &&
+           sdev->sdev_state != SDEV_CANCEL && sdev->sdev_state != SDEV_DEL &&
+           !(dev->flags & ATA_DFLAG_SUSPENDED))
+               rc = -EIO;
+
+ out_unlock:
+       spin_unlock_irqrestore(ap->lock, flags);
+ out:
+       if (rc == 0)
+               sdev->sdev_gendev.power.power_state = mesg;
+       return rc;
+}
+
+/**
+ *     ata_scsi_device_resume - resume ATA device associated with sdev
+ *     @sdev: the SCSI device to resume
+ *
+ *     Request resume EH action on the ATA device associated with
+ *     @sdev and return immediately.  This enables parallel
+ *     wakeup/spinup of devices.
+ *
+ *     LOCKING:
+ *     Kernel thread context (may sleep).
+ *
+ *     RETURNS:
+ *     0.
+ */
+int ata_scsi_device_resume(struct scsi_device *sdev)
+{
+       struct ata_port *ap = ata_shost_to_port(sdev->host);
+       struct ata_device *dev = ata_scsi_find_dev(ap, sdev);
+       struct ata_eh_info *ehi = &ap->eh_info;
+       unsigned long flags;
+       unsigned int action;
+
+       if (!dev)
+               goto out;
+
+       spin_lock_irqsave(ap->lock, flags);
+
+       /* if @sdev is already detached, nothing to do */
+       if (sdev->sdev_state == SDEV_OFFLINE ||
+           sdev->sdev_state == SDEV_CANCEL || sdev->sdev_state == SDEV_DEL)
+               goto out_unlock;
+
+       /* request resume */
+       action = ATA_EH_RESUME;
+       if (sdev->sdev_gendev.power.power_state.event == PM_EVENT_SUSPEND)
+               __ata_ehi_hotplugged(ehi);
+       else
+               action |= ATA_EH_PM_FREEZE | ATA_EH_SOFTRESET;
+       ehi->dev_action[dev->devno] |= action;
+
+       /* We don't want autopsy and verbose EH messages.  Disable
+        * those if we're the only device on this link.
+        */
+       if (ata_port_max_devices(ap) == 1)
+               ehi->flags |= ATA_EHI_NO_AUTOPSY | ATA_EHI_QUIET;
+
+       ata_port_schedule_eh(ap);
+
+ out_unlock:
+       spin_unlock_irqrestore(ap->lock, flags);
+ out:
+       sdev->sdev_gendev.power.power_state = PMSG_ON;
+       return 0;
+}
+
+/**
+ *     ata_to_sense_error - convert ATA error to SCSI error
+ *     @id: ATA device number
+ *     @drv_stat: value contained in ATA status register
+ *     @drv_err: value contained in ATA error register
+ *     @sk: the sense key we'll fill out
+ *     @asc: the additional sense code we'll fill out
+ *     @ascq: the additional sense code qualifier we'll fill out
+ *     @verbose: be verbose
+ *
+ *     Converts an ATA error into a SCSI error.  Fill out pointers to
+ *     SK, ASC, and ASCQ bytes for later use in fixed or descriptor
+ *     format sense blocks.
+ *
+ *     LOCKING:
+ *     spin_lock_irqsave(host_set lock)
+ */
+void ata_to_sense_error(unsigned id, u8 drv_stat, u8 drv_err, u8 *sk, u8 *asc,
+                       u8 *ascq, int verbose)
+{
+       int i;
+
+       /* Based on the 3ware driver translation table */
+       static const unsigned char sense_table[][4] = {
+               /* BBD|ECC|ID|MAR */
+               {0xd1,          ABORTED_COMMAND, 0x00, 0x00},   // Device busy                  Aborted command
+               /* BBD|ECC|ID */
+               {0xd0,          ABORTED_COMMAND, 0x00, 0x00},   // Device busy                  Aborted command
+               /* ECC|MC|MARK */
+               {0x61,          HARDWARE_ERROR, 0x00, 0x00},    // Device fault                 Hardware error
+               /* ICRC|ABRT */         /* NB: ICRC & !ABRT is BBD */
+               {0x84,          ABORTED_COMMAND, 0x47, 0x00},   // Data CRC error               SCSI parity error
+               /* MC|ID|ABRT|TRK0|MARK */
+               {0x37,          NOT_READY, 0x04, 0x00},         // Unit offline                 Not ready
+               /* MCR|MARK */
+               {0x09,          NOT_READY, 0x04, 0x00},         // Unrecovered disk error       Not ready
+               /*  Bad address mark */
+               {0x01,          MEDIUM_ERROR, 0x13, 0x00},      // Address mark not found       Address mark not found for data field
+               /* TRK0 */
+               {0x02,          HARDWARE_ERROR, 0x00, 0x00},    // Track 0 not found              Hardware error
+               /* Abort & !ICRC */
+               {0x04,          ABORTED_COMMAND, 0x00, 0x00},   // Aborted command              Aborted command
+               /* Media change request */
+               {0x08,          NOT_READY, 0x04, 0x00},         // Media change request   FIXME: faking offline
+               /* SRV */
+               {0x10,          ABORTED_COMMAND, 0x14, 0x00},   // ID not found                 Recorded entity not found
+               /* Media change */
+               {0x08,          NOT_READY, 0x04, 0x00},         // Media change           FIXME: faking offline
+               /* ECC */
+               {0x40,          MEDIUM_ERROR, 0x11, 0x04},      // Uncorrectable ECC error      Unrecovered read error
+               /* BBD - block marked bad */
+               {0x80,          MEDIUM_ERROR, 0x11, 0x04},      // Block marked bad               Medium error, unrecovered read error
+               {0xFF, 0xFF, 0xFF, 0xFF}, // END mark
+       };
+       static const unsigned char stat_table[][4] = {
+               /* Must be first because BUSY means no other bits valid */
+               {0x80,          ABORTED_COMMAND, 0x47, 0x00},   // Busy, fake parity for now
+               {0x20,          HARDWARE_ERROR,  0x00, 0x00},   // Device fault
+               {0x08,          ABORTED_COMMAND, 0x47, 0x00},   // Timed out in xfer, fake parity for now
+               {0x04,          RECOVERED_ERROR, 0x11, 0x00},   // Recovered ECC error    Medium error, recovered
+               {0xFF, 0xFF, 0xFF, 0xFF}, // END mark
+       };
+
+       /*
+        *      Is this an error we can process/parse
+        */
+       if (drv_stat & ATA_BUSY) {
+               drv_err = 0;    /* Ignore the err bits, they're invalid */
+       }
+
+       if (drv_err) {
+               /* Look for drv_err */
+               for (i = 0; sense_table[i][0] != 0xFF; i++) {
+                       /* Look for best matches first */
+                       if ((sense_table[i][0] & drv_err) ==
+                           sense_table[i][0]) {
+                               *sk = sense_table[i][1];
+                               *asc = sense_table[i][2];
+                               *ascq = sense_table[i][3];
+                               goto translate_done;
+                       }
+               }
+               /* No immediate match */
+               if (verbose)
+                       printk(KERN_WARNING "ata%u: no sense translation for "
+                              "error 0x%02x\n", id, drv_err);
+       }
+
+       /* Fall back to interpreting status bits */
+       for (i = 0; stat_table[i][0] != 0xFF; i++) {
+               if (stat_table[i][0] & drv_stat) {
+                       *sk = stat_table[i][1];
+                       *asc = stat_table[i][2];
+                       *ascq = stat_table[i][3];
+                       goto translate_done;
+               }
+       }
+       /* No error?  Undecoded? */
+       if (verbose)
+               printk(KERN_WARNING "ata%u: no sense translation for "
+                      "status: 0x%02x\n", id, drv_stat);
+
+       /* We need a sensible error return here, which is tricky, and one
+          that won't cause people to do things like return a disk wrongly */
+       *sk = ABORTED_COMMAND;
+       *asc = 0x00;
+       *ascq = 0x00;
+
+ translate_done:
+       if (verbose)
+               printk(KERN_ERR "ata%u: translated ATA stat/err 0x%02x/%02x "
+                      "to SCSI SK/ASC/ASCQ 0x%x/%02x/%02x\n",
+                      id, drv_stat, drv_err, *sk, *asc, *ascq);
+       return;
+}
+
+/*
+ *     ata_gen_ata_desc_sense - Generate check condition sense block.
+ *     @qc: Command that completed.
+ *
+ *     This function is specific to the ATA descriptor format sense
+ *     block specified for the ATA pass through commands.  Regardless
+ *     of whether the command errored or not, return a sense
+ *     block. Copy all controller registers into the sense
+ *     block. Clear sense key, ASC & ASCQ if there is no error.
+ *
+ *     LOCKING:
+ *     spin_lock_irqsave(host_set lock)
+ */
+void ata_gen_ata_desc_sense(struct ata_queued_cmd *qc)
+{
+       struct scsi_cmnd *cmd = qc->scsicmd;
+       struct ata_taskfile *tf = &qc->result_tf;
+       unsigned char *sb = cmd->sense_buffer;
+       unsigned char *desc = sb + 8;
+       int verbose = qc->ap->ops->error_handler == NULL;
+
+       memset(sb, 0, SCSI_SENSE_BUFFERSIZE);
+
+       cmd->result = (DRIVER_SENSE << 24) | SAM_STAT_CHECK_CONDITION;
+
+       /*
+        * Use ata_to_sense_error() to map status register bits
+        * onto sense key, asc & ascq.
+        */
+       if (qc->err_mask ||
+           tf->command & (ATA_BUSY | ATA_DF | ATA_ERR | ATA_DRQ)) {
+               ata_to_sense_error(qc->ap->id, tf->command, tf->feature,
+                                  &sb[1], &sb[2], &sb[3], verbose);
+               sb[1] &= 0x0f;
+       }
+
+       /*
+        * Sense data is current and format is descriptor.
+        */
+       sb[0] = 0x72;
+
+       desc[0] = 0x09;
+
+       /*
+        * Set length of additional sense data.
+        * Since we only populate descriptor 0, the total
+        * length is the same (fixed) length as descriptor 0.
+        */
+       desc[1] = sb[7] = 14;
+
+       /*
+        * Copy registers into sense buffer.
+        */
+       desc[2] = 0x00;
+       desc[3] = tf->feature;  /* == error reg */
+       desc[5] = tf->nsect;
+       desc[7] = tf->lbal;
+       desc[9] = tf->lbam;
+       desc[11] = tf->lbah;
+       desc[12] = tf->device;
+       desc[13] = tf->command; /* == status reg */
+
+       /*
+        * Fill in Extend bit, and the high order bytes
+        * if applicable.
+        */
+       if (tf->flags & ATA_TFLAG_LBA48) {
+               desc[2] |= 0x01;
+               desc[4] = tf->hob_nsect;
+               desc[6] = tf->hob_lbal;
+               desc[8] = tf->hob_lbam;
+               desc[10] = tf->hob_lbah;
+       }
+}
+
+/**
+ *     ata_gen_fixed_sense - generate a SCSI fixed sense block
+ *     @qc: Command that we are erroring out
+ *
+ *     Leverage ata_to_sense_error() to give us the codes.  Fit our
+ *     LBA in here if there's room.
+ *
+ *     LOCKING:
+ *     inherited from caller
+ */
+void ata_gen_fixed_sense(struct ata_queued_cmd *qc)
+{
+       struct scsi_cmnd *cmd = qc->scsicmd;
+       struct ata_taskfile *tf = &qc->result_tf;
+       unsigned char *sb = cmd->sense_buffer;
+       int verbose = qc->ap->ops->error_handler == NULL;
+
+       memset(sb, 0, SCSI_SENSE_BUFFERSIZE);
+
+       cmd->result = (DRIVER_SENSE << 24) | SAM_STAT_CHECK_CONDITION;
+
+       /*
+        * Use ata_to_sense_error() to map status register bits
+        * onto sense key, asc & ascq.
+        */
+       if (qc->err_mask ||
+           tf->command & (ATA_BUSY | ATA_DF | ATA_ERR | ATA_DRQ)) {
+               ata_to_sense_error(qc->ap->id, tf->command, tf->feature,
+                                  &sb[2], &sb[12], &sb[13], verbose);
+               sb[2] &= 0x0f;
+       }
+
+       sb[0] = 0x70;
+       sb[7] = 0x0a;
+
+       if (tf->flags & ATA_TFLAG_LBA48) {
+               /* TODO: find solution for LBA48 descriptors */
+       }
+
+       else if (tf->flags & ATA_TFLAG_LBA) {
+               /* A small (28b) LBA will fit in the 32b info field */
+               sb[0] |= 0x80;          /* set valid bit */
+               sb[3] = tf->device & 0x0f;
+               sb[4] = tf->lbah;
+               sb[5] = tf->lbam;
+               sb[6] = tf->lbal;
+       }
+
+       else {
+               /* TODO: C/H/S */
+       }
+}
+
+static void ata_scsi_sdev_config(struct scsi_device *sdev)
+{
+       sdev->use_10_for_rw = 1;
+       sdev->use_10_for_ms = 1;
+}
+
+static void ata_scsi_dev_config(struct scsi_device *sdev,
+                               struct ata_device *dev)
+{
+       unsigned int max_sectors;
+
+       /* 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.
+        */
+       max_sectors = ATA_MAX_SECTORS;
+       if (dev->flags & ATA_DFLAG_LBA48)
+               max_sectors = ATA_MAX_SECTORS_LBA48;
+       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
+        * we need to pad ATAPI transfers using an extra sg.
+        * Decrement max hw segments accordingly.
+        */
+       if (dev->class == ATA_DEV_ATAPI) {
+               request_queue_t *q = sdev->request_queue;
+               blk_queue_max_hw_segments(q, q->max_hw_segments - 1);
+       }
+
+       if (dev->flags & ATA_DFLAG_NCQ) {
+               int depth;
+
+               depth = min(sdev->host->can_queue, ata_id_queue_depth(dev->id));
+               depth = min(ATA_MAX_QUEUE - 1, depth);
+               scsi_adjust_queue_depth(sdev, MSG_SIMPLE_TAG, depth);
+       }
+}
+
+/**
+ *     ata_scsi_slave_config - Set SCSI device attributes
+ *     @sdev: SCSI device to examine
+ *
+ *     This is called before we actually start reading
+ *     and writing to the device, to configure certain
+ *     SCSI mid-layer behaviors.
+ *
+ *     LOCKING:
+ *     Defined by SCSI layer.  We don't really care.
+ */
+
+int ata_scsi_slave_config(struct scsi_device *sdev)
+{
+       struct ata_port *ap = ata_shost_to_port(sdev->host);
+       struct ata_device *dev = __ata_scsi_find_dev(ap, sdev);
+
+       ata_scsi_sdev_config(sdev);
+
+       blk_queue_max_phys_segments(sdev->request_queue, LIBATA_MAX_PRD);
+
+       if (dev)
+               ata_scsi_dev_config(sdev, dev);
+
+       return 0;       /* scsi layer doesn't check return value, sigh */
+}
+
+/**
+ *     ata_scsi_slave_destroy - SCSI device is about to be destroyed
+ *     @sdev: SCSI device to be destroyed
+ *
+ *     @sdev is about to be destroyed for hot/warm unplugging.  If
+ *     this unplugging was initiated by libata as indicated by NULL
+ *     dev->sdev, this function doesn't have to do anything.
+ *     Otherwise, SCSI layer initiated warm-unplug is in progress.
+ *     Clear dev->sdev, schedule the device for ATA detach and invoke
+ *     EH.
+ *
+ *     LOCKING:
+ *     Defined by SCSI layer.  We don't really care.
+ */
+void ata_scsi_slave_destroy(struct scsi_device *sdev)
+{
+       struct ata_port *ap = ata_shost_to_port(sdev->host);
+       unsigned long flags;
+       struct ata_device *dev;
+
+       if (!ap->ops->error_handler)
+               return;
+
+       spin_lock_irqsave(ap->lock, flags);
+       dev = __ata_scsi_find_dev(ap, sdev);
+       if (dev && dev->sdev) {
+               /* SCSI device already in CANCEL state, no need to offline it */
+               dev->sdev = NULL;
+               dev->flags |= ATA_DFLAG_DETACH;
+               ata_port_schedule_eh(ap);
+       }
+       spin_unlock_irqrestore(ap->lock, flags);
+}
+
+/**
+ *     ata_scsi_change_queue_depth - SCSI callback for queue depth config
+ *     @sdev: SCSI device to configure queue depth for
+ *     @queue_depth: new queue depth
+ *
+ *     This is libata standard hostt->change_queue_depth callback.
+ *     SCSI will call into this callback when user tries to set queue
+ *     depth via sysfs.
+ *
+ *     LOCKING:
+ *     SCSI layer (we don't care)
+ *
+ *     RETURNS:
+ *     Newly configured queue depth.
+ */
+int ata_scsi_change_queue_depth(struct scsi_device *sdev, int queue_depth)
+{
+       struct ata_port *ap = ata_shost_to_port(sdev->host);
+       struct ata_device *dev;
+       int max_depth;
+
+       if (queue_depth < 1)
+               return sdev->queue_depth;
+
+       dev = ata_scsi_find_dev(ap, sdev);
+       if (!dev || !ata_dev_enabled(dev))
+               return sdev->queue_depth;
+
+       max_depth = min(sdev->host->can_queue, ata_id_queue_depth(dev->id));
+       max_depth = min(ATA_MAX_QUEUE - 1, max_depth);
+       if (queue_depth > max_depth)
+               queue_depth = max_depth;
+
+       scsi_adjust_queue_depth(sdev, MSG_SIMPLE_TAG, queue_depth);
+       return queue_depth;
+}
+
+/**
+ *     ata_scsi_start_stop_xlat - Translate SCSI START STOP UNIT command
+ *     @qc: Storage for translated ATA taskfile
+ *     @scsicmd: SCSI command to translate
+ *
+ *     Sets up an ATA taskfile to issue STANDBY (to stop) or READ VERIFY
+ *     (to start). Perhaps these commands should be preceded by
+ *     CHECK POWER MODE to see what power mode the device is already in.
+ *     [See SAT revision 5 at www.t10.org]
+ *
+ *     LOCKING:
+ *     spin_lock_irqsave(host_set lock)
+ *
+ *     RETURNS:
+ *     Zero on success, non-zero on error.
+ */
+
+static unsigned int ata_scsi_start_stop_xlat(struct ata_queued_cmd *qc,
+                                            const u8 *scsicmd)
+{
+       struct ata_taskfile *tf = &qc->tf;
+
+       tf->flags |= ATA_TFLAG_DEVICE | ATA_TFLAG_ISADDR;
+       tf->protocol = ATA_PROT_NODATA;
+       if (scsicmd[1] & 0x1) {
+               ;       /* ignore IMMED bit, violates sat-r05 */
+       }
+       if (scsicmd[4] & 0x2)
+               goto invalid_fld;       /* LOEJ bit set not supported */
+       if (((scsicmd[4] >> 4) & 0xf) != 0)
+               goto invalid_fld;       /* power conditions not supported */
+       if (scsicmd[4] & 0x1) {
+               tf->nsect = 1;  /* 1 sector, lba=0 */
+
+               if (qc->dev->flags & ATA_DFLAG_LBA) {
+                       tf->flags |= ATA_TFLAG_LBA;
+
+                       tf->lbah = 0x0;
+                       tf->lbam = 0x0;
+                       tf->lbal = 0x0;
+                       tf->device |= ATA_LBA;
+               } else {
+                       /* CHS */
+                       tf->lbal = 0x1; /* sect */
+                       tf->lbam = 0x0; /* cyl low */
+                       tf->lbah = 0x0; /* cyl high */
+               }
+
+               tf->command = ATA_CMD_VERIFY;   /* READ VERIFY */
+       } else {
+               tf->nsect = 0;  /* time period value (0 implies now) */
+               tf->command = ATA_CMD_STANDBY;
+               /* Consider: ATA STANDBY IMMEDIATE command */
+       }
+       /*
+        * Standby and Idle condition timers could be implemented but that
+        * would require libata to implement the Power condition mode page
+        * and allow the user to change it. Changing mode pages requires
+        * MODE SELECT to be implemented.
+        */
+
+       return 0;
+
+invalid_fld:
+       ata_scsi_set_sense(qc->scsicmd, ILLEGAL_REQUEST, 0x24, 0x0);
+       /* "Invalid field in cbd" */
+       return 1;
+}
+
+
+/**
+ *     ata_scsi_flush_xlat - Translate SCSI SYNCHRONIZE CACHE command
+ *     @qc: Storage for translated ATA taskfile
+ *     @scsicmd: SCSI command to translate (ignored)
+ *
+ *     Sets up an ATA taskfile to issue FLUSH CACHE or
+ *     FLUSH CACHE EXT.
+ *
+ *     LOCKING:
+ *     spin_lock_irqsave(host_set lock)
+ *
+ *     RETURNS:
+ *     Zero on success, non-zero on error.
+ */
+
+static unsigned int ata_scsi_flush_xlat(struct ata_queued_cmd *qc, const u8 *scsicmd)
+{
+       struct ata_taskfile *tf = &qc->tf;
+
+       tf->flags |= ATA_TFLAG_DEVICE;
+       tf->protocol = ATA_PROT_NODATA;
+
+       if ((qc->dev->flags & ATA_DFLAG_LBA48) &&
+           (ata_id_has_flush_ext(qc->dev->id)))
+               tf->command = ATA_CMD_FLUSH_EXT;
+       else
+               tf->command = ATA_CMD_FLUSH;
+
+       return 0;
+}
+
+/**
+ *     scsi_6_lba_len - Get LBA and transfer length
+ *     @scsicmd: SCSI command to translate
+ *
+ *     Calculate LBA and transfer length for 6-byte commands.
+ *
+ *     RETURNS:
+ *     @plba: the LBA
+ *     @plen: the transfer length
+ */
+
+static void scsi_6_lba_len(const u8 *scsicmd, u64 *plba, u32 *plen)
+{
+       u64 lba = 0;
+       u32 len = 0;
+
+       VPRINTK("six-byte command\n");
+
+       lba |= ((u64)scsicmd[2]) << 8;
+       lba |= ((u64)scsicmd[3]);
+
+       len |= ((u32)scsicmd[4]);
+
+       *plba = lba;
+       *plen = len;
+}
+
+/**
+ *     scsi_10_lba_len - Get LBA and transfer length
+ *     @scsicmd: SCSI command to translate
+ *
+ *     Calculate LBA and transfer length for 10-byte commands.
+ *
+ *     RETURNS:
+ *     @plba: the LBA
+ *     @plen: the transfer length
+ */
+
+static void scsi_10_lba_len(const u8 *scsicmd, u64 *plba, u32 *plen)
+{
+       u64 lba = 0;
+       u32 len = 0;
+
+       VPRINTK("ten-byte command\n");
+
+       lba |= ((u64)scsicmd[2]) << 24;
+       lba |= ((u64)scsicmd[3]) << 16;
+       lba |= ((u64)scsicmd[4]) << 8;
+       lba |= ((u64)scsicmd[5]);
+
+       len |= ((u32)scsicmd[7]) << 8;
+       len |= ((u32)scsicmd[8]);
+
+       *plba = lba;
+       *plen = len;
+}
+
+/**
+ *     scsi_16_lba_len - Get LBA and transfer length
+ *     @scsicmd: SCSI command to translate
+ *
+ *     Calculate LBA and transfer length for 16-byte commands.
+ *
+ *     RETURNS:
+ *     @plba: the LBA
+ *     @plen: the transfer length
+ */
+
+static void scsi_16_lba_len(const u8 *scsicmd, u64 *plba, u32 *plen)
+{
+       u64 lba = 0;
+       u32 len = 0;
+
+       VPRINTK("sixteen-byte command\n");
+
+       lba |= ((u64)scsicmd[2]) << 56;
+       lba |= ((u64)scsicmd[3]) << 48;
+       lba |= ((u64)scsicmd[4]) << 40;
+       lba |= ((u64)scsicmd[5]) << 32;
+       lba |= ((u64)scsicmd[6]) << 24;
+       lba |= ((u64)scsicmd[7]) << 16;
+       lba |= ((u64)scsicmd[8]) << 8;
+       lba |= ((u64)scsicmd[9]);
+
+       len |= ((u32)scsicmd[10]) << 24;
+       len |= ((u32)scsicmd[11]) << 16;
+       len |= ((u32)scsicmd[12]) << 8;
+       len |= ((u32)scsicmd[13]);
+
+       *plba = lba;
+       *plen = len;
+}
+
+/**
+ *     ata_scsi_verify_xlat - Translate SCSI VERIFY command into an ATA one
+ *     @qc: Storage for translated ATA taskfile
+ *     @scsicmd: SCSI command to translate
+ *
+ *     Converts SCSI VERIFY command to an ATA READ VERIFY command.
+ *
+ *     LOCKING:
+ *     spin_lock_irqsave(host_set lock)
+ *
+ *     RETURNS:
+ *     Zero on success, non-zero on error.
+ */
+
+static unsigned int ata_scsi_verify_xlat(struct ata_queued_cmd *qc, const u8 *scsicmd)
+{
+       struct ata_taskfile *tf = &qc->tf;
+       struct ata_device *dev = qc->dev;
+       u64 dev_sectors = qc->dev->n_sectors;
+       u64 block;
+       u32 n_block;
+
+       tf->flags |= ATA_TFLAG_ISADDR | ATA_TFLAG_DEVICE;
+       tf->protocol = ATA_PROT_NODATA;
+
+       if (scsicmd[0] == VERIFY)
+               scsi_10_lba_len(scsicmd, &block, &n_block);
+       else if (scsicmd[0] == VERIFY_16)
+               scsi_16_lba_len(scsicmd, &block, &n_block);
+       else
+               goto invalid_fld;
+
+       if (!n_block)
+               goto nothing_to_do;
+       if (block >= dev_sectors)
+               goto out_of_range;
+       if ((block + n_block) > dev_sectors)
+               goto out_of_range;
+
+       if (dev->flags & ATA_DFLAG_LBA) {
+               tf->flags |= ATA_TFLAG_LBA;
+
+               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;
+                       tf->command = ATA_CMD_VERIFY_EXT;
+
+                       tf->hob_nsect = (n_block >> 8) & 0xff;
+
+                       tf->hob_lbah = (block >> 40) & 0xff;
+                       tf->hob_lbam = (block >> 32) & 0xff;
+                       tf->hob_lbal = (block >> 24) & 0xff;
+               } else
+                       /* request too large even for LBA48 */
+                       goto out_of_range;
+
+               tf->nsect = n_block & 0xff;
+
+               tf->lbah = (block >> 16) & 0xff;
+               tf->lbam = (block >> 8) & 0xff;
+               tf->lbal = block & 0xff;
+
+               tf->device |= ATA_LBA;
+       } else {
+               /* CHS */
+               u32 sect, head, cyl, track;
+
+               if (!lba_28_ok(block, n_block))
+                       goto out_of_range;
+
+               /* Convert LBA to CHS */
+               track = (u32)block / dev->sectors;
+               cyl   = track / dev->heads;
+               head  = track % dev->heads;
+               sect  = (u32)block % dev->sectors + 1;
+
+               DPRINTK("block %u track %u cyl %u head %u sect %u\n",
+                       (u32)block, track, cyl, head, sect);
+
+               /* Check whether the converted CHS can fit.
+                  Cylinder: 0-65535
+                  Head: 0-15
+                  Sector: 1-255*/
+               if ((cyl >> 16) || (head >> 4) || (sect >> 8) || (!sect))
+                       goto out_of_range;
+
+               tf->command = ATA_CMD_VERIFY;
+               tf->nsect = n_block & 0xff; /* Sector count 0 means 256 sectors */
+               tf->lbal = sect;
+               tf->lbam = cyl;
+               tf->lbah = cyl >> 8;
+               tf->device |= head;
+       }
+
+       return 0;
+
+invalid_fld:
+       ata_scsi_set_sense(qc->scsicmd, ILLEGAL_REQUEST, 0x24, 0x0);
+       /* "Invalid field in cbd" */
+       return 1;
+
+out_of_range:
+       ata_scsi_set_sense(qc->scsicmd, ILLEGAL_REQUEST, 0x21, 0x0);
+       /* "Logical Block Address out of range" */
+       return 1;
+
+nothing_to_do:
+       qc->scsicmd->result = SAM_STAT_GOOD;
+       return 1;
+}
+
+/**
+ *     ata_scsi_rw_xlat - Translate SCSI r/w command into an ATA one
+ *     @qc: Storage for translated ATA taskfile
+ *     @scsicmd: SCSI command to translate
+ *
+ *     Converts any of six SCSI read/write commands into the
+ *     ATA counterpart, including starting sector (LBA),
+ *     sector count, and taking into account the device's LBA48
+ *     support.
+ *
+ *     Commands %READ_6, %READ_10, %READ_16, %WRITE_6, %WRITE_10, and
+ *     %WRITE_16 are currently supported.
+ *
+ *     LOCKING:
+ *     spin_lock_irqsave(host_set lock)
+ *
+ *     RETURNS:
+ *     Zero on success, non-zero on error.
+ */
+
+static unsigned int ata_scsi_rw_xlat(struct ata_queued_cmd *qc, const u8 *scsicmd)
+{
+       struct ata_taskfile *tf = &qc->tf;
+       struct ata_device *dev = qc->dev;
+       u64 block;
+       u32 n_block;
+
+       qc->flags |= ATA_QCFLAG_IO;
+       tf->flags |= ATA_TFLAG_ISADDR | ATA_TFLAG_DEVICE;
+
+       if (scsicmd[0] == WRITE_10 || scsicmd[0] == WRITE_6 ||
+           scsicmd[0] == WRITE_16)
+               tf->flags |= ATA_TFLAG_WRITE;
+
+       /* Calculate the SCSI LBA, transfer length and FUA. */
+       switch (scsicmd[0]) {
+       case READ_10:
+       case WRITE_10:
+               scsi_10_lba_len(scsicmd, &block, &n_block);
+               if (unlikely(scsicmd[1] & (1 << 3)))
+                       tf->flags |= ATA_TFLAG_FUA;
+               break;
+       case READ_6:
+       case WRITE_6:
+               scsi_6_lba_len(scsicmd, &block, &n_block);
+
+               /* for 6-byte r/w commands, transfer length 0
+                * means 256 blocks of data, not 0 block.
+                */
+               if (!n_block)
+                       n_block = 256;
+               break;
+       case READ_16:
+       case WRITE_16:
+               scsi_16_lba_len(scsicmd, &block, &n_block);
+               if (unlikely(scsicmd[1] & (1 << 3)))
+                       tf->flags |= ATA_TFLAG_FUA;
+               break;
+       default:
+               DPRINTK("no-byte command\n");
+               goto invalid_fld;
+       }
+
+       /* Check and compose ATA command */
+       if (!n_block)
+               /* For 10-byte and 16-byte SCSI R/W commands, transfer
+                * length 0 means transfer 0 block of data.
+                * However, for ATA R/W commands, sector count 0 means
+                * 256 or 65536 sectors, not 0 sectors as in SCSI.
+                *
+                * WARNING: one or two older ATA drives treat 0 as 0...
+                */
+               goto nothing_to_do;
+
+       if ((dev->flags & (ATA_DFLAG_PIO | ATA_DFLAG_NCQ)) == ATA_DFLAG_NCQ) {
+               /* yay, NCQ */
+               if (!lba_48_ok(block, n_block))
+                       goto out_of_range;
+
+               tf->protocol = ATA_PROT_NCQ;
+               tf->flags |= ATA_TFLAG_LBA | ATA_TFLAG_LBA48;
+
+               if (tf->flags & ATA_TFLAG_WRITE)
+                       tf->command = ATA_CMD_FPDMA_WRITE;
+               else
+                       tf->command = ATA_CMD_FPDMA_READ;
+
+               qc->nsect = n_block;
+
+               tf->nsect = qc->tag << 3;
+               tf->hob_feature = (n_block >> 8) & 0xff;
+               tf->feature = n_block & 0xff;
+
+               tf->hob_lbah = (block >> 40) & 0xff;
+               tf->hob_lbam = (block >> 32) & 0xff;
+               tf->hob_lbal = (block >> 24) & 0xff;
+               tf->lbah = (block >> 16) & 0xff;
+               tf->lbam = (block >> 8) & 0xff;
+               tf->lbal = block & 0xff;
+
+               tf->device = 1 << 6;
+               if (tf->flags & ATA_TFLAG_FUA)
+                       tf->device |= 1 << 7;
+       } else if (dev->flags & ATA_DFLAG_LBA) {
+               tf->flags |= ATA_TFLAG_LBA;
+
+               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 */
+                       tf->flags |= ATA_TFLAG_LBA48;
+
+                       tf->hob_nsect = (n_block >> 8) & 0xff;
+
+                       tf->hob_lbah = (block >> 40) & 0xff;
+                       tf->hob_lbam = (block >> 32) & 0xff;
+                       tf->hob_lbal = (block >> 24) & 0xff;
+               } else
+                       /* request too large even for LBA48 */
+                       goto out_of_range;
+
+               if (unlikely(ata_rwcmd_protocol(qc) < 0))
+                       goto invalid_fld;
+
+               qc->nsect = n_block;
+               tf->nsect = n_block & 0xff;
+
+               tf->lbah = (block >> 16) & 0xff;
+               tf->lbam = (block >> 8) & 0xff;
+               tf->lbal = block & 0xff;
+
+               tf->device |= ATA_LBA;
+       } else {
+               /* CHS */
+               u32 sect, head, cyl, track;
+
+               /* The request -may- be too large for CHS addressing. */
+               if (!lba_28_ok(block, n_block))
+                       goto out_of_range;
+
+               if (unlikely(ata_rwcmd_protocol(qc) < 0))
+                       goto invalid_fld;
+
+               /* Convert LBA to CHS */
+               track = (u32)block / dev->sectors;
+               cyl   = track / dev->heads;
+               head  = track % dev->heads;
+               sect  = (u32)block % dev->sectors + 1;
+
+               DPRINTK("block %u track %u cyl %u head %u sect %u\n",
+                       (u32)block, track, cyl, head, sect);
+
+               /* Check whether the converted CHS can fit.
+                  Cylinder: 0-65535
+                  Head: 0-15
+                  Sector: 1-255*/
+               if ((cyl >> 16) || (head >> 4) || (sect >> 8) || (!sect))
+                       goto out_of_range;
+
+               qc->nsect = n_block;
+               tf->nsect = n_block & 0xff; /* Sector count 0 means 256 sectors */
+               tf->lbal = sect;
+               tf->lbam = cyl;
+               tf->lbah = cyl >> 8;
+               tf->device |= head;
+       }
+
+       return 0;
+
+invalid_fld:
+       ata_scsi_set_sense(qc->scsicmd, ILLEGAL_REQUEST, 0x24, 0x0);
+       /* "Invalid field in cbd" */
+       return 1;
+
+out_of_range:
+       ata_scsi_set_sense(qc->scsicmd, ILLEGAL_REQUEST, 0x21, 0x0);
+       /* "Logical Block Address out of range" */
+       return 1;
+
+nothing_to_do:
+       qc->scsicmd->result = SAM_STAT_GOOD;
+       return 1;
+}
+
+static void ata_scsi_qc_complete(struct ata_queued_cmd *qc)
+{
+       struct scsi_cmnd *cmd = qc->scsicmd;
+       u8 *cdb = cmd->cmnd;
+       int need_sense = (qc->err_mask != 0);
+
+       /* We snoop the SET_FEATURES - Write Cache ON/OFF command, and
+        * schedule EH_REVALIDATE operation to update the IDENTIFY DEVICE
+        * cache
+        */
+       if (!need_sense && (qc->tf.command == ATA_CMD_SET_FEATURES) &&
+           ((qc->tf.feature == SETFEATURES_WC_ON) ||
+            (qc->tf.feature == SETFEATURES_WC_OFF))) {
+               qc->ap->eh_info.action |= ATA_EH_REVALIDATE;
+               ata_port_schedule_eh(qc->ap);
+       }
+
+       /* For ATA pass thru (SAT) commands, generate a sense block if
+        * user mandated it or if there's an error.  Note that if we
+        * generate because the user forced us to, a check condition
+        * is generated and the ATA register values are returned
+        * whether the command completed successfully or not. If there
+        * was no error, SK, ASC and ASCQ will all be zero.
+        */
+       if (((cdb[0] == ATA_16) || (cdb[0] == ATA_12)) &&
+           ((cdb[2] & 0x20) || need_sense)) {
+               ata_gen_ata_desc_sense(qc);
+       } else {
+               if (!need_sense) {
+                       cmd->result = SAM_STAT_GOOD;
+               } else {
+                       /* TODO: decide which descriptor format to use
+                        * for 48b LBA devices and call that here
+                        * instead of the fixed desc, which is only
+                        * good for smaller LBA (and maybe CHS?)
+                        * devices.
+                        */
+                       ata_gen_fixed_sense(qc);
+               }
+       }
+
+       if (need_sense && !qc->ap->ops->error_handler)
+               ata_dump_status(qc->ap->id, &qc->result_tf);
+
+       qc->scsidone(cmd);
+
+       ata_qc_free(qc);
+}
+
+/**
+ *     ata_scmd_need_defer - Check whether we need to defer scmd
+ *     @dev: ATA device to which the command is addressed
+ *     @is_io: Is the command IO (and thus possibly NCQ)?
+ *
+ *     NCQ and non-NCQ commands cannot run together.  As upper layer
+ *     only knows the queue depth, we are responsible for maintaining
+ *     exclusion.  This function checks whether a new command can be
+ *     issued to @dev.
+ *
+ *     LOCKING:
+ *     spin_lock_irqsave(host_set lock)
+ *
+ *     RETURNS:
+ *     1 if deferring is needed, 0 otherwise.
+ */
+static int ata_scmd_need_defer(struct ata_device *dev, int is_io)
+{
+       struct ata_port *ap = dev->ap;
+
+       if (!(dev->flags & ATA_DFLAG_NCQ))
+               return 0;
+
+       if (is_io) {
+               if (!ata_tag_valid(ap->active_tag))
+                       return 0;
+       } else {
+               if (!ata_tag_valid(ap->active_tag) && !ap->sactive)
+                       return 0;
+       }
+       return 1;
+}
+
+/**
+ *     ata_scsi_translate - Translate then issue SCSI command to ATA device
+ *     @dev: ATA device to which the command is addressed
+ *     @cmd: SCSI command to execute
+ *     @done: SCSI command completion function
+ *     @xlat_func: Actor which translates @cmd to an ATA taskfile
+ *
+ *     Our ->queuecommand() function has decided that the SCSI
+ *     command issued can be directly translated into an ATA
+ *     command, rather than handled internally.
+ *
+ *     This function sets up an ata_queued_cmd structure for the
+ *     SCSI command, and sends that ata_queued_cmd to the hardware.
+ *
+ *     The xlat_func argument (actor) returns 0 if ready to execute
+ *     ATA command, else 1 to finish translation. If 1 is returned
+ *     then cmd->result (and possibly cmd->sense_buffer) are assumed
+ *     to be set reflecting an error condition or clean (early)
+ *     termination.
+ *
+ *     LOCKING:
+ *     spin_lock_irqsave(host_set lock)
+ *
+ *     RETURNS:
+ *     0 on success, SCSI_ML_QUEUE_DEVICE_BUSY if the command
+ *     needs to be deferred.
+ */
+static int ata_scsi_translate(struct ata_device *dev, struct scsi_cmnd *cmd,
+                             void (*done)(struct scsi_cmnd *),
+                             ata_xlat_func_t xlat_func)
+{
+       struct ata_queued_cmd *qc;
+       u8 *scsicmd = cmd->cmnd;
+       int is_io = xlat_func == ata_scsi_rw_xlat;
+
+       VPRINTK("ENTER\n");
+
+       if (unlikely(ata_scmd_need_defer(dev, is_io)))
+               goto defer;
+
+       qc = ata_scsi_qc_new(dev, cmd, done);
+       if (!qc)
+               goto err_mem;
+
+       /* data is present; dma-map it */
+       if (cmd->sc_data_direction == DMA_FROM_DEVICE ||
+           cmd->sc_data_direction == DMA_TO_DEVICE) {
+               if (unlikely(cmd->request_bufflen < 1)) {
+                       ata_dev_printk(dev, KERN_WARNING,
+                                      "WARNING: zero len r/w req\n");
+                       goto err_did;
+               }
+
+               if (cmd->use_sg)
+                       ata_sg_init(qc, cmd->request_buffer, cmd->use_sg);
+               else
+                       ata_sg_init_one(qc, cmd->request_buffer,
+                                       cmd->request_bufflen);
+
+               qc->dma_dir = cmd->sc_data_direction;
+       }
+
+       qc->complete_fn = ata_scsi_qc_complete;
+
+       if (xlat_func(qc, scsicmd))
+               goto early_finish;
+
+       /* select device, send command to hardware */
+       ata_qc_issue(qc);
+
+       VPRINTK("EXIT\n");
+       return 0;
+
+early_finish:
+        ata_qc_free(qc);
+       done(cmd);
+       DPRINTK("EXIT - early finish (good or error)\n");
+       return 0;
+
+err_did:
+       ata_qc_free(qc);
+err_mem:
+       cmd->result = (DID_ERROR << 16);
+       done(cmd);
+       DPRINTK("EXIT - internal\n");
+       return 0;
+
+defer:
+       DPRINTK("EXIT - defer\n");
+       return SCSI_MLQUEUE_DEVICE_BUSY;
+}
+
+/**
+ *     ata_scsi_rbuf_get - Map response buffer.
+ *     @cmd: SCSI command containing buffer to be mapped.
+ *     @buf_out: Pointer to mapped area.
+ *
+ *     Maps buffer contained within SCSI command @cmd.
+ *
+ *     LOCKING:
+ *     spin_lock_irqsave(host_set lock)
+ *
+ *     RETURNS:
+ *     Length of response buffer.
+ */
+
+static unsigned int ata_scsi_rbuf_get(struct scsi_cmnd *cmd, u8 **buf_out)
+{
+       u8 *buf;
+       unsigned int buflen;
+
+       if (cmd->use_sg) {
+               struct scatterlist *sg;
+
+               sg = (struct scatterlist *) cmd->request_buffer;
+               buf = kmap_atomic(sg->page, KM_USER0) + sg->offset;
+               buflen = sg->length;
+       } else {
+               buf = cmd->request_buffer;
+               buflen = cmd->request_bufflen;
+       }
+
+       *buf_out = buf;
+       return buflen;
+}
+
+/**
+ *     ata_scsi_rbuf_put - Unmap response buffer.
+ *     @cmd: SCSI command containing buffer to be unmapped.
+ *     @buf: buffer to unmap
+ *
+ *     Unmaps response buffer contained within @cmd.
+ *
+ *     LOCKING:
+ *     spin_lock_irqsave(host_set lock)
+ */
+
+static inline void ata_scsi_rbuf_put(struct scsi_cmnd *cmd, u8 *buf)
+{
+       if (cmd->use_sg) {
+               struct scatterlist *sg;
+
+               sg = (struct scatterlist *) cmd->request_buffer;
+               kunmap_atomic(buf - sg->offset, KM_USER0);
+       }
+}
+
+/**
+ *     ata_scsi_rbuf_fill - wrapper for SCSI command simulators
+ *     @args: device IDENTIFY data / SCSI command of interest.
+ *     @actor: Callback hook for desired SCSI command simulator
+ *
+ *     Takes care of the hard work of simulating a SCSI command...
+ *     Mapping the response buffer, calling the command's handler,
+ *     and handling the handler's return value.  This return value
+ *     indicates whether the handler wishes the SCSI command to be
+ *     completed successfully (0), or not (in which case cmd->result
+ *     and sense buffer are assumed to be set).
+ *
+ *     LOCKING:
+ *     spin_lock_irqsave(host_set lock)
+ */
+
+void ata_scsi_rbuf_fill(struct ata_scsi_args *args,
+                       unsigned int (*actor) (struct ata_scsi_args *args,
+                                          u8 *rbuf, unsigned int buflen))
+{
+       u8 *rbuf;
+       unsigned int buflen, rc;
+       struct scsi_cmnd *cmd = args->cmd;
+
+       buflen = ata_scsi_rbuf_get(cmd, &rbuf);
+       memset(rbuf, 0, buflen);
+       rc = actor(args, rbuf, buflen);
+       ata_scsi_rbuf_put(cmd, rbuf);
+
+       if (rc == 0)
+               cmd->result = SAM_STAT_GOOD;
+       args->done(cmd);
+}
+
+/**
+ *     ata_scsiop_inq_std - Simulate INQUIRY command
+ *     @args: device IDENTIFY data / SCSI command of interest.
+ *     @rbuf: Response buffer, to which simulated SCSI cmd output is sent.
+ *     @buflen: Response buffer length.
+ *
+ *     Returns standard device identification data associated
+ *     with non-VPD INQUIRY command output.
+ *
+ *     LOCKING:
+ *     spin_lock_irqsave(host_set lock)
+ */
+
+unsigned int ata_scsiop_inq_std(struct ata_scsi_args *args, u8 *rbuf,
+                              unsigned int buflen)
+{
+       u8 hdr[] = {
+               TYPE_DISK,
+               0,
+               0x5,    /* claim SPC-3 version compatibility */
+               2,
+               95 - 4
+       };
+
+       /* set scsi removeable (RMB) bit per ata bit */
+       if (ata_id_removeable(args->id))
+               hdr[1] |= (1 << 7);
+
+       VPRINTK("ENTER\n");
+
+       memcpy(rbuf, hdr, sizeof(hdr));
+
+       if (buflen > 35) {
+               memcpy(&rbuf[8], "ATA     ", 8);
+               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);
+       }
+
+       if (buflen > 63) {
+               const u8 versions[] = {
+                       0x60,   /* SAM-3 (no version claimed) */
+
+                       0x03,
+                       0x20,   /* SBC-2 (no version claimed) */
+
+                       0x02,
+                       0x60    /* SPC-3 (no version claimed) */
+               };
+
+               memcpy(rbuf + 59, versions, sizeof(versions));
+       }
+
+       return 0;
+}
+
+/**
+ *     ata_scsiop_inq_00 - Simulate INQUIRY VPD page 0, list of pages
+ *     @args: device IDENTIFY data / SCSI command of interest.
+ *     @rbuf: Response buffer, to which simulated SCSI cmd output is sent.
+ *     @buflen: Response buffer length.
+ *
+ *     Returns list of inquiry VPD pages available.
+ *
+ *     LOCKING:
+ *     spin_lock_irqsave(host_set lock)
+ */
+
+unsigned int ata_scsiop_inq_00(struct ata_scsi_args *args, u8 *rbuf,
+                             unsigned int buflen)
+{
+       const u8 pages[] = {
+               0x00,   /* page 0x00, this page */
+               0x80,   /* page 0x80, unit serial no page */
+               0x83    /* page 0x83, device ident page */
+       };
+       rbuf[3] = sizeof(pages);        /* number of supported VPD pages */
+
+       if (buflen > 6)
+               memcpy(rbuf + 4, pages, sizeof(pages));
+
+       return 0;
+}
+
+/**
+ *     ata_scsiop_inq_80 - Simulate INQUIRY VPD page 80, device serial number
+ *     @args: device IDENTIFY data / SCSI command of interest.
+ *     @rbuf: Response buffer, to which simulated SCSI cmd output is sent.
+ *     @buflen: Response buffer length.
+ *
+ *     Returns ATA device serial number.
+ *
+ *     LOCKING:
+ *     spin_lock_irqsave(host_set lock)
+ */
+
+unsigned int ata_scsiop_inq_80(struct ata_scsi_args *args, u8 *rbuf,
+                             unsigned int buflen)
+{
+       const u8 hdr[] = {
+               0,
+               0x80,                   /* this page code */
+               0,
+               ATA_SERNO_LEN,          /* page len */
+       };
+       memcpy(rbuf, hdr, sizeof(hdr));
+
+       if (buflen > (ATA_SERNO_LEN + 4 - 1))
+               ata_id_string(args->id, (unsigned char *) &rbuf[4],
+                             ATA_ID_SERNO_OFS, ATA_SERNO_LEN);
+
+       return 0;
+}
+
+/**
+ *     ata_scsiop_inq_83 - Simulate INQUIRY VPD page 83, device identity
+ *     @args: device IDENTIFY data / SCSI command of interest.
+ *     @rbuf: Response buffer, to which simulated SCSI cmd output is sent.
+ *     @buflen: Response buffer length.
+ *
+ *     Yields two logical unit device identification designators:
+ *      - vendor specific ASCII containing the ATA serial number
+ *      - SAT defined "t10 vendor id based" containing ASCII vendor
+ *        name ("ATA     "), model and serial numbers.
+ *
+ *     LOCKING:
+ *     spin_lock_irqsave(host_set lock)
+ */
+
+unsigned int ata_scsiop_inq_83(struct ata_scsi_args *args, u8 *rbuf,
+                             unsigned int buflen)
+{
+       int num;
+       const int sat_model_serial_desc_len = 68;
+       const int ata_model_byte_len = 40;
+
+       rbuf[1] = 0x83;                 /* this page code */
+       num = 4;
+
+       if (buflen > (ATA_SERNO_LEN + num + 3)) {
+               /* piv=0, assoc=lu, code_set=ACSII, designator=vendor */
+               rbuf[num + 0] = 2;
+               rbuf[num + 3] = ATA_SERNO_LEN;
+               num += 4;
+               ata_id_string(args->id, (unsigned char *) rbuf + num,
+                             ATA_ID_SERNO_OFS, ATA_SERNO_LEN);
+               num += ATA_SERNO_LEN;
+       }
+       if (buflen > (sat_model_serial_desc_len + num + 3)) {
+               /* SAT defined lu model and serial numbers descriptor */
+               /* piv=0, assoc=lu, code_set=ACSII, designator=t10 vendor id */
+               rbuf[num + 0] = 2;
+               rbuf[num + 1] = 1;
+               rbuf[num + 3] = sat_model_serial_desc_len;
+               num += 4;
+               memcpy(rbuf + num, "ATA     ", 8);
+               num += 8;
+               ata_id_string(args->id, (unsigned char *) rbuf + num,
+                             ATA_ID_PROD_OFS, ata_model_byte_len);
+               num += ata_model_byte_len;
+               ata_id_string(args->id, (unsigned char *) rbuf + num,
+                             ATA_ID_SERNO_OFS, ATA_SERNO_LEN);
+               num += ATA_SERNO_LEN;
+       }
+       rbuf[3] = num - 4;    /* page len (assume less than 256 bytes) */
+       return 0;
+}
+
+/**
+ *     ata_scsiop_noop - Command handler that simply returns success.
+ *     @args: device IDENTIFY data / SCSI command of interest.
+ *     @rbuf: Response buffer, to which simulated SCSI cmd output is sent.
+ *     @buflen: Response buffer length.
+ *
+ *     No operation.  Simply returns success to caller, to indicate
+ *     that the caller should successfully complete this SCSI command.
+ *
+ *     LOCKING:
+ *     spin_lock_irqsave(host_set lock)
+ */
+
+unsigned int ata_scsiop_noop(struct ata_scsi_args *args, u8 *rbuf,
+                           unsigned int buflen)
+{
+       VPRINTK("ENTER\n");
+       return 0;
+}
+
+/**
+ *     ata_msense_push - Push data onto MODE SENSE data output buffer
+ *     @ptr_io: (input/output) Location to store more output data
+ *     @last: End of output data buffer
+ *     @buf: Pointer to BLOB being added to output buffer
+ *     @buflen: Length of BLOB
+ *
+ *     Store MODE SENSE data on an output buffer.
+ *
+ *     LOCKING:
+ *     None.
+ */
+
+static void ata_msense_push(u8 **ptr_io, const u8 *last,
+                           const u8 *buf, unsigned int buflen)
+{
+       u8 *ptr = *ptr_io;
+
+       if ((ptr + buflen - 1) > last)
+               return;
+
+       memcpy(ptr, buf, buflen);
+
+       ptr += buflen;
+
+       *ptr_io = ptr;
+}
+
+/**
+ *     ata_msense_caching - Simulate MODE SENSE caching info page
+ *     @id: device IDENTIFY data
+ *     @ptr_io: (input/output) Location to store more output data
+ *     @last: End of output data buffer
+ *
+ *     Generate a caching info page, which conditionally indicates
+ *     write caching to the SCSI layer, depending on device
+ *     capabilities.
+ *
+ *     LOCKING:
+ *     None.
+ */
+
+static unsigned int ata_msense_caching(u16 *id, u8 **ptr_io,
+                                      const u8 *last)
+{
+       u8 page[CACHE_MPAGE_LEN];
+
+       memcpy(page, def_cache_mpage, sizeof(page));
+       if (ata_id_wcache_enabled(id))
+               page[2] |= (1 << 2);    /* write cache enable */
+       if (!ata_id_rahead_enabled(id))
+               page[12] |= (1 << 5);   /* disable read ahead */
+
+       ata_msense_push(ptr_io, last, page, sizeof(page));
+       return sizeof(page);
+}
+
+/**
+ *     ata_msense_ctl_mode - Simulate MODE SENSE control mode page
+ *     @dev: Device associated with this MODE SENSE command
+ *     @ptr_io: (input/output) Location to store more output data
+ *     @last: End of output data buffer
+ *
+ *     Generate a generic MODE SENSE control mode page.
+ *
+ *     LOCKING:
+ *     None.
+ */
+
+static unsigned int ata_msense_ctl_mode(u8 **ptr_io, const u8 *last)
+{
+       ata_msense_push(ptr_io, last, def_control_mpage,
+                       sizeof(def_control_mpage));
+       return sizeof(def_control_mpage);
+}
+
+/**
+ *     ata_msense_rw_recovery - Simulate MODE SENSE r/w error recovery page
+ *     @dev: Device associated with this MODE SENSE command
+ *     @ptr_io: (input/output) Location to store more output data
+ *     @last: End of output data buffer
+ *
+ *     Generate a generic MODE SENSE r/w error recovery page.
+ *
+ *     LOCKING:
+ *     None.
+ */
+
+static unsigned int ata_msense_rw_recovery(u8 **ptr_io, const u8 *last)
+{
+
+       ata_msense_push(ptr_io, last, def_rw_recovery_mpage,
+                       sizeof(def_rw_recovery_mpage));
+       return sizeof(def_rw_recovery_mpage);
+}
+
+/*
+ * We can turn this into a real blacklist if it's needed, for now just
+ * blacklist any Maxtor BANC1G10 revision firmware
+ */
+static int ata_dev_supports_fua(u16 *id)
+{
+       unsigned char model[41], fw[9];
+
+       if (!libata_fua)
+               return 0;
+       if (!ata_id_has_fua(id))
+               return 0;
+
+       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 (strcmp(model, "Maxtor"))
+               return 1;
+       if (strcmp(fw, "BANC1G10"))
+               return 1;
+
+       return 0; /* blacklisted */
+}
+
+/**
+ *     ata_scsiop_mode_sense - Simulate MODE SENSE 6, 10 commands
+ *     @args: device IDENTIFY data / SCSI command of interest.
+ *     @rbuf: Response buffer, to which simulated SCSI cmd output is sent.
+ *     @buflen: Response buffer length.
+ *
+ *     Simulate MODE SENSE commands. Assume this is invoked for direct
+ *     access devices (e.g. disks) only. There should be no block
+ *     descriptor for other device types.
+ *
+ *     LOCKING:
+ *     spin_lock_irqsave(host_set lock)
+ */
+
+unsigned int ata_scsiop_mode_sense(struct ata_scsi_args *args, u8 *rbuf,
+                                 unsigned int buflen)
+{
+       struct ata_device *dev = args->dev;
+       u8 *scsicmd = args->cmd->cmnd, *p, *last;
+       const u8 sat_blk_desc[] = {
+               0, 0, 0, 0,     /* number of blocks: sat unspecified */
+               0,
+               0, 0x2, 0x0     /* block length: 512 bytes */
+       };
+       u8 pg, spg;
+       unsigned int ebd, page_control, six_byte, output_len, alloc_len, minlen;
+       u8 dpofua;
+
+       VPRINTK("ENTER\n");
+
+       six_byte = (scsicmd[0] == MODE_SENSE);
+       ebd = !(scsicmd[1] & 0x8);      /* dbd bit inverted == edb */
+       /*
+        * LLBA bit in msense(10) ignored (compliant)
+        */
+
+       page_control = scsicmd[2] >> 6;
+       switch (page_control) {
+       case 0: /* current */
+               break;  /* supported */
+       case 3: /* saved */
+               goto saving_not_supp;
+       case 1: /* changeable */
+       case 2: /* defaults */
+       default:
+               goto invalid_fld;
+       }
+
+       if (six_byte) {
+               output_len = 4 + (ebd ? 8 : 0);
+               alloc_len = scsicmd[4];
+       } else {
+               output_len = 8 + (ebd ? 8 : 0);
+               alloc_len = (scsicmd[7] << 8) + scsicmd[8];
+       }
+       minlen = (alloc_len < buflen) ? alloc_len : buflen;
+
+       p = rbuf + output_len;
+       last = rbuf + minlen - 1;
+
+       pg = scsicmd[2] & 0x3f;
+       spg = scsicmd[3];
+       /*
+        * No mode subpages supported (yet) but asking for _all_
+        * subpages may be valid
+        */
+       if (spg && (spg != ALL_SUB_MPAGES))
+               goto invalid_fld;
+
+       switch(pg) {
+       case RW_RECOVERY_MPAGE:
+               output_len += ata_msense_rw_recovery(&p, last);
+               break;
+
+       case CACHE_MPAGE:
+               output_len += ata_msense_caching(args->id, &p, last);
+               break;
+
+       case CONTROL_MPAGE: {
+               output_len += ata_msense_ctl_mode(&p, last);
+               break;
+               }
+
+       case ALL_MPAGES:
+               output_len += ata_msense_rw_recovery(&p, last);
+               output_len += ata_msense_caching(args->id, &p, last);
+               output_len += ata_msense_ctl_mode(&p, last);
+               break;
+
+       default:                /* invalid page code */
+               goto invalid_fld;
+       }
+
+       if (minlen < 1)
+               return 0;
+
+       dpofua = 0;
+       if (ata_dev_supports_fua(args->id) && (dev->flags & ATA_DFLAG_LBA48) &&
+           (!(dev->flags & ATA_DFLAG_PIO) || dev->multi_count))
+               dpofua = 1 << 4;
+
+       if (six_byte) {
+               output_len--;
+               rbuf[0] = output_len;
+               if (minlen > 2)
+                       rbuf[2] |= dpofua;
+               if (ebd) {
+                       if (minlen > 3)
+                               rbuf[3] = sizeof(sat_blk_desc);
+                       if (minlen > 11)
+                               memcpy(rbuf + 4, sat_blk_desc,
+                                      sizeof(sat_blk_desc));
+               }
+       } else {
+               output_len -= 2;
+               rbuf[0] = output_len >> 8;
+               if (minlen > 1)
+                       rbuf[1] = output_len;
+               if (minlen > 3)
+                       rbuf[3] |= dpofua;
+               if (ebd) {
+                       if (minlen > 7)
+                               rbuf[7] = sizeof(sat_blk_desc);
+                       if (minlen > 15)
+                               memcpy(rbuf + 8, sat_blk_desc,
+                                      sizeof(sat_blk_desc));
+               }
+       }
+       return 0;
+
+invalid_fld:
+       ata_scsi_set_sense(args->cmd, ILLEGAL_REQUEST, 0x24, 0x0);
+       /* "Invalid field in cbd" */
+       return 1;
+
+saving_not_supp:
+       ata_scsi_set_sense(args->cmd, ILLEGAL_REQUEST, 0x39, 0x0);
+        /* "Saving parameters not supported" */
+       return 1;
+}
+
+/**
+ *     ata_scsiop_read_cap - Simulate READ CAPACITY[ 16] commands
+ *     @args: device IDENTIFY data / SCSI command of interest.
+ *     @rbuf: Response buffer, to which simulated SCSI cmd output is sent.
+ *     @buflen: Response buffer length.
+ *
+ *     Simulate READ CAPACITY commands.
+ *
+ *     LOCKING:
+ *     spin_lock_irqsave(host_set lock)
+ */
+
+unsigned int ata_scsiop_read_cap(struct ata_scsi_args *args, u8 *rbuf,
+                               unsigned int buflen)
+{
+       u64 n_sectors;
+       u32 tmp;
+
+       VPRINTK("ENTER\n");
+
+       if (ata_id_has_lba(args->id)) {
+               if (ata_id_has_lba48(args->id))
+                       n_sectors = ata_id_u64(args->id, 100);
+               else
+                       n_sectors = ata_id_u32(args->id, 60);
+       } else {
+               /* CHS default translation */
+               n_sectors = args->id[1] * args->id[3] * args->id[6];
+
+               if (ata_id_current_chs_valid(args->id))
+                       /* CHS current translation */
+                       n_sectors = ata_id_u32(args->id, 57);
+       }
+
+       n_sectors--;            /* ATA TotalUserSectors - 1 */
+
+       if (args->cmd->cmnd[0] == READ_CAPACITY) {
+               if( n_sectors >= 0xffffffffULL )
+                       tmp = 0xffffffff ;  /* Return max count on overflow */
+               else
+                       tmp = n_sectors ;
+
+               /* sector count, 32-bit */
+               rbuf[0] = tmp >> (8 * 3);
+               rbuf[1] = tmp >> (8 * 2);
+               rbuf[2] = tmp >> (8 * 1);
+               rbuf[3] = tmp;
+
+               /* sector size */
+               tmp = ATA_SECT_SIZE;
+               rbuf[6] = tmp >> 8;
+               rbuf[7] = tmp;
+
+       } else {
+               /* sector count, 64-bit */
+               tmp = n_sectors >> (8 * 4);
+               rbuf[2] = tmp >> (8 * 3);
+               rbuf[3] = tmp >> (8 * 2);
+               rbuf[4] = tmp >> (8 * 1);
+               rbuf[5] = tmp;
+               tmp = n_sectors;
+               rbuf[6] = tmp >> (8 * 3);
+               rbuf[7] = tmp >> (8 * 2);
+               rbuf[8] = tmp >> (8 * 1);
+               rbuf[9] = tmp;
+
+               /* sector size */
+               tmp = ATA_SECT_SIZE;
+               rbuf[12] = tmp >> 8;
+               rbuf[13] = tmp;
+       }
+
+       return 0;
+}
+
+/**
+ *     ata_scsiop_report_luns - Simulate REPORT LUNS command
+ *     @args: device IDENTIFY data / SCSI command of interest.
+ *     @rbuf: Response buffer, to which simulated SCSI cmd output is sent.
+ *     @buflen: Response buffer length.
+ *
+ *     Simulate REPORT LUNS command.
+ *
+ *     LOCKING:
+ *     spin_lock_irqsave(host_set lock)
+ */
+
+unsigned int ata_scsiop_report_luns(struct ata_scsi_args *args, u8 *rbuf,
+                                  unsigned int buflen)
+{
+       VPRINTK("ENTER\n");
+       rbuf[3] = 8;    /* just one lun, LUN 0, size 8 bytes */
+
+       return 0;
+}
+
+/**
+ *     ata_scsi_set_sense - Set SCSI sense data and status
+ *     @cmd: SCSI request to be handled
+ *     @sk: SCSI-defined sense key
+ *     @asc: SCSI-defined additional sense code
+ *     @ascq: SCSI-defined additional sense code qualifier
+ *
+ *     Helper function that builds a valid fixed format, current
+ *     response code and the given sense key (sk), additional sense
+ *     code (asc) and additional sense code qualifier (ascq) with
+ *     a SCSI command status of %SAM_STAT_CHECK_CONDITION and
+ *     DRIVER_SENSE set in the upper bits of scsi_cmnd::result .
+ *
+ *     LOCKING:
+ *     Not required
+ */
+
+void ata_scsi_set_sense(struct scsi_cmnd *cmd, u8 sk, u8 asc, u8 ascq)
+{
+       cmd->result = (DRIVER_SENSE << 24) | SAM_STAT_CHECK_CONDITION;
+
+       cmd->sense_buffer[0] = 0x70;    /* fixed format, current */
+       cmd->sense_buffer[2] = sk;
+       cmd->sense_buffer[7] = 18 - 8;  /* additional sense length */
+       cmd->sense_buffer[12] = asc;
+       cmd->sense_buffer[13] = ascq;
+}
+
+/**
+ *     ata_scsi_badcmd - End a SCSI request with an error
+ *     @cmd: SCSI request to be handled
+ *     @done: SCSI command completion function
+ *     @asc: SCSI-defined additional sense code
+ *     @ascq: SCSI-defined additional sense code qualifier
+ *
+ *     Helper function that completes a SCSI command with
+ *     %SAM_STAT_CHECK_CONDITION, with a sense key %ILLEGAL_REQUEST
+ *     and the specified additional sense codes.
+ *
+ *     LOCKING:
+ *     spin_lock_irqsave(host_set lock)
+ */
+
+void ata_scsi_badcmd(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *), u8 asc, u8 ascq)
+{
+       DPRINTK("ENTER\n");
+       ata_scsi_set_sense(cmd, ILLEGAL_REQUEST, asc, ascq);
+
+       done(cmd);
+}
+
+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
+                * translation of taskfile registers into
+                * a sense descriptors, since that's only
+                * correct for ATA, not ATAPI
+                */
+               ata_gen_ata_desc_sense(qc);
+       }
+
+       qc->scsidone(qc->scsicmd);
+       ata_qc_free(qc);
+}
+
+/* is it pointless to prefer PIO for "safety reasons"? */
+static inline int ata_pio_use_silly(struct ata_port *ap)
+{
+       return (ap->flags & ATA_FLAG_PIO_DMA);
+}
+
+static void atapi_request_sense(struct ata_queued_cmd *qc)
+{
+       struct ata_port *ap = qc->ap;
+       struct scsi_cmnd *cmd = qc->scsicmd;
+
+       DPRINTK("ATAPI request sense\n");
+
+       /* FIXME: is this needed? */
+       memset(cmd->sense_buffer, 0, sizeof(cmd->sense_buffer));
+
+       ap->ops->tf_read(ap, &qc->tf);
+
+       /* fill these in, for the case where they are -not- overwritten */
+       cmd->sense_buffer[0] = 0x70;
+       cmd->sense_buffer[2] = qc->tf.feature >> 4;
+
+       ata_qc_reinit(qc);
+
+       ata_sg_init_one(qc, cmd->sense_buffer, sizeof(cmd->sense_buffer));
+       qc->dma_dir = DMA_FROM_DEVICE;
+
+       memset(&qc->cdb, 0, qc->dev->cdb_len);
+       qc->cdb[0] = REQUEST_SENSE;
+       qc->cdb[4] = SCSI_SENSE_BUFFERSIZE;
+
+       qc->tf.flags |= ATA_TFLAG_ISADDR | ATA_TFLAG_DEVICE;
+       qc->tf.command = ATA_CMD_PACKET;
+
+       if (ata_pio_use_silly(ap)) {
+               qc->tf.protocol = ATA_PROT_ATAPI_DMA;
+               qc->tf.feature |= ATAPI_PKT_DMA;
+       } else {
+               qc->tf.protocol = ATA_PROT_ATAPI;
+               qc->tf.lbam = (8 * 1024) & 0xff;
+               qc->tf.lbah = (8 * 1024) >> 8;
+       }
+       qc->nbytes = SCSI_SENSE_BUFFERSIZE;
+
+       qc->complete_fn = atapi_sense_complete;
+
+       ata_qc_issue(qc);
+
+       DPRINTK("EXIT\n");
+}
+
+static void atapi_qc_complete(struct ata_queued_cmd *qc)
+{
+       struct scsi_cmnd *cmd = qc->scsicmd;
+       unsigned int err_mask = qc->err_mask;
+
+       VPRINTK("ENTER, err_mask 0x%X\n", err_mask);
+
+       /* handle completion from new EH */
+       if (unlikely(qc->ap->ops->error_handler &&
+                    (err_mask || qc->flags & ATA_QCFLAG_SENSE_VALID))) {
+
+               if (!(qc->flags & ATA_QCFLAG_SENSE_VALID)) {
+                       /* FIXME: not quite right; we don't want the
+                        * translation of taskfile registers into a
+                        * sense descriptors, since that's only
+                        * correct for ATA, not ATAPI
+                        */
+                       ata_gen_ata_desc_sense(qc);
+               }
+
+               /* SCSI EH automatically locks door if sdev->locked is
+                * set.  Sometimes door lock request continues to
+                * fail, for example, when no media is present.  This
+                * creates a loop - SCSI EH issues door lock which
+                * fails and gets invoked again to acquire sense data
+                * for the failed command.
+                *
+                * If door lock fails, always clear sdev->locked to
+                * avoid this infinite loop.
+                */
+               if (qc->cdb[0] == ALLOW_MEDIUM_REMOVAL)
+                       qc->dev->sdev->locked = 0;
+
+               qc->scsicmd->result = SAM_STAT_CHECK_CONDITION;
+               qc->scsidone(cmd);
+               ata_qc_free(qc);
+               return;
+       }
+
+       /* successful completion or old EH failure path */
+       if (unlikely(err_mask & AC_ERR_DEV)) {
+               cmd->result = SAM_STAT_CHECK_CONDITION;
+               atapi_request_sense(qc);
+               return;
+       } else if (unlikely(err_mask)) {
+               /* FIXME: not quite right; we don't want the
+                * translation of taskfile registers into
+                * a sense descriptors, since that's only
+                * correct for ATA, not ATAPI
+                */
+               ata_gen_ata_desc_sense(qc);
+       } else {
+               u8 *scsicmd = cmd->cmnd;
+
+               if ((scsicmd[0] == INQUIRY) && ((scsicmd[1] & 0x03) == 0)) {
+                       u8 *buf = NULL;
+                       unsigned int buflen;
+
+                       buflen = ata_scsi_rbuf_get(cmd, &buf);
+
+       /* ATAPI devices typically report zero for their SCSI version,
+        * and sometimes deviate from the spec WRT response data
+        * format.  If SCSI version is reported as zero like normal,
+        * then we make the following fixups:  1) Fake MMC-5 version,
+        * to indicate to the Linux scsi midlayer this is a modern
+        * device.  2) Ensure response data format / ATAPI information
+        * are always correct.
+        */
+                       if (buf[2] == 0) {
+                               buf[2] = 0x5;
+                               buf[3] = 0x32;
+                       }
+
+                       ata_scsi_rbuf_put(cmd, buf);
+               }
+
+               cmd->result = SAM_STAT_GOOD;
+       }
+
+       qc->scsidone(cmd);
+       ata_qc_free(qc);
+}
+/**
+ *     atapi_xlat - Initialize PACKET taskfile
+ *     @qc: command structure to be initialized
+ *     @scsicmd: SCSI CDB associated with this PACKET command
+ *
+ *     LOCKING:
+ *     spin_lock_irqsave(host_set lock)
+ *
+ *     RETURNS:
+ *     Zero on success, non-zero on failure.
+ */
+
+static unsigned int atapi_xlat(struct ata_queued_cmd *qc, const u8 *scsicmd)
+{
+       struct scsi_cmnd *cmd = qc->scsicmd;
+       struct ata_device *dev = qc->dev;
+       int using_pio = (dev->flags & ATA_DFLAG_PIO);
+       int nodata = (cmd->sc_data_direction == DMA_NONE);
+
+       if (!using_pio)
+               /* Check whether ATAPI DMA is safe */
+               if (ata_check_atapi_dma(qc))
+                       using_pio = 1;
+
+       memcpy(&qc->cdb, scsicmd, dev->cdb_len);
+
+       qc->complete_fn = atapi_qc_complete;
+
+       qc->tf.flags |= ATA_TFLAG_ISADDR | ATA_TFLAG_DEVICE;
+       if (cmd->sc_data_direction == DMA_TO_DEVICE) {
+               qc->tf.flags |= ATA_TFLAG_WRITE;
+               DPRINTK("direction: write\n");
+       }
+
+       qc->tf.command = ATA_CMD_PACKET;
+
+       /* no data, or PIO data xfer */
+       if (using_pio || nodata) {
+               if (nodata)
+                       qc->tf.protocol = ATA_PROT_ATAPI_NODATA;
+               else
+                       qc->tf.protocol = ATA_PROT_ATAPI;
+               qc->tf.lbam = (8 * 1024) & 0xff;
+               qc->tf.lbah = (8 * 1024) >> 8;
+       }
+
+       /* DMA data xfer */
+       else {
+               qc->tf.protocol = ATA_PROT_ATAPI_DMA;
+               qc->tf.feature |= ATAPI_PKT_DMA;
+
+               if (atapi_dmadir && (cmd->sc_data_direction != DMA_TO_DEVICE))
+                       /* some SATA bridges need us to indicate data xfer direction */
+                       qc->tf.feature |= ATAPI_DMADIR;
+       }
+
+       qc->nbytes = cmd->request_bufflen;
+
+       return 0;
+}
+
+static struct ata_device * ata_find_dev(struct ata_port *ap, int id)
+{
+       if (likely(id < ATA_MAX_DEVICES))
+               return &ap->device[id];
+       return NULL;
+}
+
+static struct ata_device * __ata_scsi_find_dev(struct ata_port *ap,
+                                       const struct scsi_device *scsidev)
+{
+       /* skip commands not addressed to targets we simulate */
+       if (unlikely(scsidev->channel || scsidev->lun))
+               return NULL;
+
+       return ata_find_dev(ap, scsidev->id);
+}
+
+/**
+ *     ata_scsi_dev_enabled - determine if device is enabled
+ *     @dev: ATA device
+ *
+ *     Determine if commands should be sent to the specified device.
+ *
+ *     LOCKING:
+ *     spin_lock_irqsave(host_set lock)
+ *
+ *     RETURNS:
+ *     0 if commands are not allowed / 1 if commands are allowed
+ */
+
+static int ata_scsi_dev_enabled(struct ata_device *dev)
+{
+       if (unlikely(!ata_dev_enabled(dev)))
+               return 0;
+
+       if (!atapi_enabled || (dev->ap->flags & ATA_FLAG_NO_ATAPI)) {
+               if (unlikely(dev->class == ATA_DEV_ATAPI)) {
+                       ata_dev_printk(dev, KERN_WARNING,
+                                      "WARNING: ATAPI is %s, device ignored.\n",
+                                      atapi_enabled ? "not supported with this driver" : "disabled");
+                       return 0;
+               }
+       }
+
+       return 1;
+}
+
+/**
+ *     ata_scsi_find_dev - lookup ata_device from scsi_cmnd
+ *     @ap: ATA port to which the device is attached
+ *     @scsidev: SCSI device from which we derive the ATA device
+ *
+ *     Given various information provided in struct scsi_cmnd,
+ *     map that onto an ATA bus, and using that mapping
+ *     determine which ata_device is associated with the
+ *     SCSI command to be sent.
+ *
+ *     LOCKING:
+ *     spin_lock_irqsave(host_set lock)
+ *
+ *     RETURNS:
+ *     Associated ATA device, or %NULL if not found.
+ */
+static struct ata_device *
+ata_scsi_find_dev(struct ata_port *ap, const struct scsi_device *scsidev)
+{
+       struct ata_device *dev = __ata_scsi_find_dev(ap, scsidev);
+
+       if (unlikely(!dev || !ata_scsi_dev_enabled(dev)))
+               return NULL;
+
+       return dev;
+}
+
+/*
+ *     ata_scsi_map_proto - Map pass-thru protocol value to taskfile value.
+ *     @byte1: Byte 1 from pass-thru CDB.
+ *
+ *     RETURNS:
+ *     ATA_PROT_UNKNOWN if mapping failed/unimplemented, protocol otherwise.
+ */
+static u8
+ata_scsi_map_proto(u8 byte1)
+{
+       switch((byte1 & 0x1e) >> 1) {
+               case 3:         /* Non-data */
+                       return ATA_PROT_NODATA;
+
+               case 6:         /* DMA */
+                       return ATA_PROT_DMA;
+
+               case 4:         /* PIO Data-in */
+               case 5:         /* PIO Data-out */
+                       return ATA_PROT_PIO;
+
+               case 10:        /* Device Reset */
+               case 0:         /* Hard Reset */
+               case 1:         /* SRST */
+               case 2:         /* Bus Idle */
+               case 7:         /* Packet */
+               case 8:         /* DMA Queued */
+               case 9:         /* Device Diagnostic */
+               case 11:        /* UDMA Data-in */
+               case 12:        /* UDMA Data-Out */
+               case 13:        /* FPDMA */
+               default:        /* Reserved */
+                       break;
+       }
+
+       return ATA_PROT_UNKNOWN;
+}
+
+/**
+ *     ata_scsi_pass_thru - convert ATA pass-thru CDB to taskfile
+ *     @qc: command structure to be initialized
+ *     @scsicmd: SCSI command to convert
+ *
+ *     Handles either 12 or 16-byte versions of the CDB.
+ *
+ *     RETURNS:
+ *     Zero on success, non-zero on failure.
+ */
+static unsigned int
+ata_scsi_pass_thru(struct ata_queued_cmd *qc, const u8 *scsicmd)
+{
+       struct ata_taskfile *tf = &(qc->tf);
+       struct scsi_cmnd *cmd = qc->scsicmd;
+       struct ata_device *dev = qc->dev;
+
+       if ((tf->protocol = ata_scsi_map_proto(scsicmd[1])) == ATA_PROT_UNKNOWN)
+               goto invalid_fld;
+
+       /* We may not issue DMA commands if no DMA mode is set */
+       if (tf->protocol == ATA_PROT_DMA && dev->dma_mode == 0)
+               goto invalid_fld;
+
+       if (scsicmd[1] & 0xe0)
+               /* PIO multi not supported yet */
+               goto invalid_fld;
+
+       /*
+        * 12 and 16 byte CDBs use different offsets to
+        * provide the various register values.
+        */
+       if (scsicmd[0] == ATA_16) {
+               /*
+                * 16-byte CDB - may contain extended commands.
+                *
+                * If that is the case, copy the upper byte register values.
+                */
+               if (scsicmd[1] & 0x01) {
+                       tf->hob_feature = scsicmd[3];
+                       tf->hob_nsect = scsicmd[5];
+                       tf->hob_lbal = scsicmd[7];
+                       tf->hob_lbam = scsicmd[9];
+                       tf->hob_lbah = scsicmd[11];
+                       tf->flags |= ATA_TFLAG_LBA48;
+               } else
+                       tf->flags &= ~ATA_TFLAG_LBA48;
+
+               /*
+                * Always copy low byte, device and command registers.
+                */
+               tf->feature = scsicmd[4];
+               tf->nsect = scsicmd[6];
+               tf->lbal = scsicmd[8];
+               tf->lbam = scsicmd[10];
+               tf->lbah = scsicmd[12];
+               tf->device = scsicmd[13];
+               tf->command = scsicmd[14];
+       } else {
+               /*
+                * 12-byte CDB - incapable of extended commands.
+                */
+               tf->flags &= ~ATA_TFLAG_LBA48;
+
+               tf->feature = scsicmd[3];
+               tf->nsect = scsicmd[4];
+               tf->lbal = scsicmd[5];
+               tf->lbam = scsicmd[6];
+               tf->lbah = scsicmd[7];
+               tf->device = scsicmd[8];
+               tf->command = scsicmd[9];
+       }
+       /*
+        * If slave is possible, enforce correct master/slave bit
+       */
+       if (qc->ap->flags & ATA_FLAG_SLAVE_POSS)
+               tf->device = qc->dev->devno ?
+                       tf->device | ATA_DEV1 : tf->device & ~ATA_DEV1;
+
+       /*
+        * Filter SET_FEATURES - XFER MODE command -- otherwise,
+        * SET_FEATURES - XFER MODE must be preceded/succeeded
+        * by an update to hardware-specific registers for each
+        * controller (i.e. the reason for ->set_piomode(),
+        * ->set_dmamode(), and ->post_set_mode() hooks).
+        */
+       if ((tf->command == ATA_CMD_SET_FEATURES)
+        && (tf->feature == SETFEATURES_XFER))
+               goto invalid_fld;
+
+       /*
+        * Set flags so that all registers will be written,
+        * and pass on write indication (used for PIO/DMA
+        * setup.)
+        */
+       tf->flags |= (ATA_TFLAG_ISADDR | ATA_TFLAG_DEVICE);
+
+       if (cmd->sc_data_direction == DMA_TO_DEVICE)
+               tf->flags |= ATA_TFLAG_WRITE;
+
+       /*
+        * Set transfer length.
+        *
+        * TODO: find out if we need to do more here to
+        *       cover scatter/gather case.
+        */
+       qc->nsect = cmd->request_bufflen / ATA_SECT_SIZE;
+
+       /* request result TF */
+       qc->flags |= ATA_QCFLAG_RESULT_TF;
+
+       return 0;
+
+ invalid_fld:
+       ata_scsi_set_sense(qc->scsicmd, ILLEGAL_REQUEST, 0x24, 0x00);
+       /* "Invalid field in cdb" */
+       return 1;
+}
+
+/**
+ *     ata_get_xlat_func - check if SCSI to ATA translation is possible
+ *     @dev: ATA device
+ *     @cmd: SCSI command opcode to consider
+ *
+ *     Look up the SCSI command given, and determine whether the
+ *     SCSI command is to be translated or simulated.
+ *
+ *     RETURNS:
+ *     Pointer to translation function if possible, %NULL if not.
+ */
+
+static inline ata_xlat_func_t ata_get_xlat_func(struct ata_device *dev, u8 cmd)
+{
+       switch (cmd) {
+       case READ_6:
+       case READ_10:
+       case READ_16:
+
+       case WRITE_6:
+       case WRITE_10:
+       case WRITE_16:
+               return ata_scsi_rw_xlat;
+
+       case SYNCHRONIZE_CACHE:
+               if (ata_try_flush_cache(dev))
+                       return ata_scsi_flush_xlat;
+               break;
+
+       case VERIFY:
+       case VERIFY_16:
+               return ata_scsi_verify_xlat;
+
+       case ATA_12:
+       case ATA_16:
+               return ata_scsi_pass_thru;
+
+       case START_STOP:
+               return ata_scsi_start_stop_xlat;
+       }
+
+       return NULL;
+}
+
+/**
+ *     ata_scsi_dump_cdb - dump SCSI command contents to dmesg
+ *     @ap: ATA port to which the command was being sent
+ *     @cmd: SCSI command to dump
+ *
+ *     Prints the contents of a SCSI command via printk().
+ */
+
+static inline void ata_scsi_dump_cdb(struct ata_port *ap,
+                                    struct scsi_cmnd *cmd)
+{
+#ifdef ATA_DEBUG
+       struct scsi_device *scsidev = cmd->device;
+       u8 *scsicmd = cmd->cmnd;
+
+       DPRINTK("CDB (%u:%d,%d,%d) %02x %02x %02x %02x %02x %02x %02x %02x %02x\n",
+               ap->id,
+               scsidev->channel, scsidev->id, scsidev->lun,
+               scsicmd[0], scsicmd[1], scsicmd[2], scsicmd[3],
+               scsicmd[4], scsicmd[5], scsicmd[6], scsicmd[7],
+               scsicmd[8]);
+#endif
+}
+
+static inline int __ata_scsi_queuecmd(struct scsi_cmnd *cmd,
+                                     void (*done)(struct scsi_cmnd *),
+                                     struct ata_device *dev)
+{
+       int rc = 0;
+
+       if (dev->class == ATA_DEV_ATA) {
+               ata_xlat_func_t xlat_func = ata_get_xlat_func(dev,
+                                                             cmd->cmnd[0]);
+
+               if (xlat_func)
+                       rc = ata_scsi_translate(dev, cmd, done, xlat_func);
+               else
+                       ata_scsi_simulate(dev, cmd, done);
+       } else
+               rc = ata_scsi_translate(dev, cmd, done, atapi_xlat);
+
+       return rc;
+}
+
+/**
+ *     ata_scsi_queuecmd - Issue SCSI cdb to libata-managed device
+ *     @cmd: SCSI command to be sent
+ *     @done: Completion function, called when command is complete
+ *
+ *     In some cases, this function translates SCSI commands into
+ *     ATA taskfiles, and queues the taskfiles to be sent to
+ *     hardware.  In other cases, this function simulates a
+ *     SCSI device by evaluating and responding to certain
+ *     SCSI commands.  This creates the overall effect of
+ *     ATA and ATAPI devices appearing as SCSI devices.
+ *
+ *     LOCKING:
+ *     Releases scsi-layer-held lock, and obtains host_set lock.
+ *
+ *     RETURNS:
+ *     Return value from __ata_scsi_queuecmd() if @cmd can be queued,
+ *     0 otherwise.
+ */
+int ata_scsi_queuecmd(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *))
+{
+       struct ata_port *ap;
+       struct ata_device *dev;
+       struct scsi_device *scsidev = cmd->device;
+       struct Scsi_Host *shost = scsidev->host;
+       int rc = 0;
+
+       ap = ata_shost_to_port(shost);
+
+       spin_unlock(shost->host_lock);
+       spin_lock(ap->lock);
+
+       ata_scsi_dump_cdb(ap, cmd);
+
+       dev = ata_scsi_find_dev(ap, scsidev);
+       if (likely(dev))
+               rc = __ata_scsi_queuecmd(cmd, done, dev);
+       else {
+               cmd->result = (DID_BAD_TARGET << 16);
+               done(cmd);
+       }
+
+       spin_unlock(ap->lock);
+       spin_lock(shost->host_lock);
+       return rc;
+}
+
+/**
+ *     ata_scsi_simulate - simulate SCSI command on ATA device
+ *     @dev: the target device
+ *     @cmd: SCSI command being sent to device.
+ *     @done: SCSI command completion function.
+ *
+ *     Interprets and directly executes a select list of SCSI commands
+ *     that can be handled internally.
+ *
+ *     LOCKING:
+ *     spin_lock_irqsave(host_set lock)
+ */
+
+void ata_scsi_simulate(struct ata_device *dev, struct scsi_cmnd *cmd,
+                     void (*done)(struct scsi_cmnd *))
+{
+       struct ata_scsi_args args;
+       const u8 *scsicmd = cmd->cmnd;
+
+       args.dev = dev;
+       args.id = dev->id;
+       args.cmd = cmd;
+       args.done = done;
+
+       switch(scsicmd[0]) {
+               /* no-op's, complete with success */
+               case SYNCHRONIZE_CACHE:
+               case REZERO_UNIT:
+               case SEEK_6:
+               case SEEK_10:
+               case TEST_UNIT_READY:
+               case FORMAT_UNIT:               /* FIXME: correct? */
+               case SEND_DIAGNOSTIC:           /* FIXME: correct? */
+                       ata_scsi_rbuf_fill(&args, ata_scsiop_noop);
+                       break;
+
+               case INQUIRY:
+                       if (scsicmd[1] & 2)                /* is CmdDt set?  */
+                               ata_scsi_invalid_field(cmd, done);
+                       else if ((scsicmd[1] & 1) == 0)    /* is EVPD clear? */
+                               ata_scsi_rbuf_fill(&args, ata_scsiop_inq_std);
+                       else if (scsicmd[2] == 0x00)
+                               ata_scsi_rbuf_fill(&args, ata_scsiop_inq_00);
+                       else if (scsicmd[2] == 0x80)
+                               ata_scsi_rbuf_fill(&args, ata_scsiop_inq_80);
+                       else if (scsicmd[2] == 0x83)
+                               ata_scsi_rbuf_fill(&args, ata_scsiop_inq_83);
+                       else
+                               ata_scsi_invalid_field(cmd, done);
+                       break;
+
+               case MODE_SENSE:
+               case MODE_SENSE_10:
+                       ata_scsi_rbuf_fill(&args, ata_scsiop_mode_sense);
+                       break;
+
+               case MODE_SELECT:       /* unconditionally return */
+               case MODE_SELECT_10:    /* bad-field-in-cdb */
+                       ata_scsi_invalid_field(cmd, done);
+                       break;
+
+               case READ_CAPACITY:
+                       ata_scsi_rbuf_fill(&args, ata_scsiop_read_cap);
+                       break;
+
+               case SERVICE_ACTION_IN:
+                       if ((scsicmd[1] & 0x1f) == SAI_READ_CAPACITY_16)
+                               ata_scsi_rbuf_fill(&args, ata_scsiop_read_cap);
+                       else
+                               ata_scsi_invalid_field(cmd, done);
+                       break;
+
+               case REPORT_LUNS:
+                       ata_scsi_rbuf_fill(&args, ata_scsiop_report_luns);
+                       break;
+
+               /* mandatory commands we haven't implemented yet */
+               case REQUEST_SENSE:
+
+               /* all other commands */
+               default:
+                       ata_scsi_set_sense(cmd, ILLEGAL_REQUEST, 0x20, 0x0);
+                       /* "Invalid command operation code" */
+                       done(cmd);
+                       break;
+       }
+}
+
+void ata_scsi_scan_host(struct ata_port *ap)
+{
+       unsigned int i;
+
+       if (ap->flags & ATA_FLAG_DISABLED)
+               return;
+
+       for (i = 0; i < ATA_MAX_DEVICES; i++) {
+               struct ata_device *dev = &ap->device[i];
+               struct scsi_device *sdev;
+
+               if (!ata_dev_enabled(dev) || dev->sdev)
+                       continue;
+
+               sdev = __scsi_add_device(ap->host, 0, i, 0, NULL);
+               if (!IS_ERR(sdev)) {
+                       dev->sdev = sdev;
+                       scsi_device_put(sdev);
+               }
+       }
+}
+
+/**
+ *     ata_scsi_offline_dev - offline attached SCSI device
+ *     @dev: ATA device to offline attached SCSI device for
+ *
+ *     This function is called from ata_eh_hotplug() and responsible
+ *     for taking the SCSI device attached to @dev offline.  This
+ *     function is called with host_set lock which protects dev->sdev
+ *     against clearing.
+ *
+ *     LOCKING:
+ *     spin_lock_irqsave(host_set lock)
+ *
+ *     RETURNS:
+ *     1 if attached SCSI device exists, 0 otherwise.
+ */
+int ata_scsi_offline_dev(struct ata_device *dev)
+{
+       if (dev->sdev) {
+               scsi_device_set_state(dev->sdev, SDEV_OFFLINE);
+               return 1;
+       }
+       return 0;
+}
+
+/**
+ *     ata_scsi_remove_dev - remove attached SCSI device
+ *     @dev: ATA device to remove attached SCSI device for
+ *
+ *     This function is called from ata_eh_scsi_hotplug() and
+ *     responsible for removing the SCSI device attached to @dev.
+ *
+ *     LOCKING:
+ *     Kernel thread context (may sleep).
+ */
+static void ata_scsi_remove_dev(struct ata_device *dev)
+{
+       struct ata_port *ap = dev->ap;
+       struct scsi_device *sdev;
+       unsigned long flags;
+
+       /* Alas, we need to grab scan_mutex to ensure SCSI device
+        * state doesn't change underneath us and thus
+        * scsi_device_get() always succeeds.  The mutex locking can
+        * be removed if there is __scsi_device_get() interface which
+        * increments reference counts regardless of device state.
+        */
+       mutex_lock(&ap->host->scan_mutex);
+       spin_lock_irqsave(ap->lock, flags);
+
+       /* clearing dev->sdev is protected by host_set lock */
+       sdev = dev->sdev;
+       dev->sdev = NULL;
+
+       if (sdev) {
+               /* If user initiated unplug races with us, sdev can go
+                * away underneath us after the host_set lock and
+                * scan_mutex are released.  Hold onto it.
+                */
+               if (scsi_device_get(sdev) == 0) {
+                       /* The following ensures the attached sdev is
+                        * offline on return from ata_scsi_offline_dev()
+                        * regardless it wins or loses the race
+                        * against this function.
+                        */
+                       scsi_device_set_state(sdev, SDEV_OFFLINE);
+               } else {
+                       WARN_ON(1);
+                       sdev = NULL;
+               }
+       }
+
+       spin_unlock_irqrestore(ap->lock, flags);
+       mutex_unlock(&ap->host->scan_mutex);
+
+       if (sdev) {
+               ata_dev_printk(dev, KERN_INFO, "detaching (SCSI %s)\n",
+                              sdev->sdev_gendev.bus_id);
+
+               scsi_remove_device(sdev);
+               scsi_device_put(sdev);
+       }
+}
+
+/**
+ *     ata_scsi_hotplug - SCSI part of hotplug
+ *     @data: Pointer to ATA port to perform SCSI hotplug on
+ *
+ *     Perform SCSI part of hotplug.  It's executed from a separate
+ *     workqueue after EH completes.  This is necessary because SCSI
+ *     hot plugging requires working EH and hot unplugging is
+ *     synchronized with hot plugging with a mutex.
+ *
+ *     LOCKING:
+ *     Kernel thread context (may sleep).
+ */
+void ata_scsi_hotplug(void *data)
+{
+       struct ata_port *ap = data;
+       int i;
+
+       if (ap->pflags & ATA_PFLAG_UNLOADING) {
+               DPRINTK("ENTER/EXIT - unloading\n");
+               return;
+       }
+
+       DPRINTK("ENTER\n");
+
+       /* unplug detached devices */
+       for (i = 0; i < ATA_MAX_DEVICES; i++) {
+               struct ata_device *dev = &ap->device[i];
+               unsigned long flags;
+
+               if (!(dev->flags & ATA_DFLAG_DETACHED))
+                       continue;
+
+               spin_lock_irqsave(ap->lock, flags);
+               dev->flags &= ~ATA_DFLAG_DETACHED;
+               spin_unlock_irqrestore(ap->lock, flags);
+
+               ata_scsi_remove_dev(dev);
+       }
+
+       /* scan for new ones */
+       ata_scsi_scan_host(ap);
+
+       /* If we scanned while EH was in progress, scan would have
+        * failed silently.  Requeue if there are enabled but
+        * unattached devices.
+        */
+       for (i = 0; i < ATA_MAX_DEVICES; i++) {
+               struct ata_device *dev = &ap->device[i];
+               if (ata_dev_enabled(dev) && !dev->sdev) {
+                       queue_delayed_work(ata_aux_wq, &ap->hotplug_task, HZ);
+                       break;
+               }
+       }
+
+       DPRINTK("EXIT\n");
+}
+
+/**
+ *     ata_scsi_user_scan - indication for user-initiated bus scan
+ *     @shost: SCSI host to scan
+ *     @channel: Channel to scan
+ *     @id: ID to scan
+ *     @lun: LUN to scan
+ *
+ *     This function is called when user explicitly requests bus
+ *     scan.  Set probe pending flag and invoke EH.
+ *
+ *     LOCKING:
+ *     SCSI layer (we don't care)
+ *
+ *     RETURNS:
+ *     Zero.
+ */
+static int ata_scsi_user_scan(struct Scsi_Host *shost, unsigned int channel,
+                             unsigned int id, unsigned int lun)
+{
+       struct ata_port *ap = ata_shost_to_port(shost);
+       unsigned long flags;
+       int rc = 0;
+
+       if (!ap->ops->error_handler)
+               return -EOPNOTSUPP;
+
+       if ((channel != SCAN_WILD_CARD && channel != 0) ||
+           (lun != SCAN_WILD_CARD && lun != 0))
+               return -EINVAL;
+
+       spin_lock_irqsave(ap->lock, flags);
+
+       if (id == SCAN_WILD_CARD) {
+               ap->eh_info.probe_mask |= (1 << ATA_MAX_DEVICES) - 1;
+               ap->eh_info.action |= ATA_EH_SOFTRESET;
+       } else {
+               struct ata_device *dev = ata_find_dev(ap, id);
+
+               if (dev) {
+                       ap->eh_info.probe_mask |= 1 << dev->devno;
+                       ap->eh_info.action |= ATA_EH_SOFTRESET;
+                       ap->eh_info.flags |= ATA_EHI_RESUME_LINK;
+               } else
+                       rc = -EINVAL;
+       }
+
+       if (rc == 0)
+               ata_port_schedule_eh(ap);
+
+       spin_unlock_irqrestore(ap->lock, flags);
+
+       return rc;
+}
+
+/**
+ *     ata_scsi_dev_rescan - initiate scsi_rescan_device()
+ *     @data: Pointer to ATA port to perform scsi_rescan_device()
+ *
+ *     After ATA pass thru (SAT) commands are executed successfully,
+ *     libata need to propagate the changes to SCSI layer.  This
+ *     function must be executed from ata_aux_wq such that sdev
+ *     attach/detach don't race with rescan.
+ *
+ *     LOCKING:
+ *     Kernel thread context (may sleep).
+ */
+void ata_scsi_dev_rescan(void *data)
+{
+       struct ata_port *ap = data;
+       struct ata_device *dev;
+       unsigned int i;
+
+       for (i = 0; i < ATA_MAX_DEVICES; i++) {
+               dev = &ap->device[i];
+
+               if (ata_dev_enabled(dev) && dev->sdev)
+                       scsi_rescan_device(&(dev->sdev->sdev_gendev));
+       }
+}
+
+/**
+ *     ata_sas_port_alloc - Allocate port for a SAS attached SATA device
+ *     @pdev: PCI device that the scsi device is attached to
+ *     @port_info: Information from low-level host driver
+ *     @host: SCSI host that the scsi device is attached to
+ *
+ *     LOCKING:
+ *     PCI/etc. bus probe sem.
+ *
+ *     RETURNS:
+ *     ata_port pointer on success / NULL on failure.
+ */
+
+struct ata_port *ata_sas_port_alloc(struct ata_host_set *host_set,
+                                   struct ata_port_info *port_info,
+                                   struct Scsi_Host *host)
+{
+       struct ata_port *ap = kzalloc(sizeof(*ap), GFP_KERNEL);
+       struct ata_probe_ent *ent;
+
+       if (!ap)
+               return NULL;
+
+       ent = ata_probe_ent_alloc(host_set->dev, port_info);
+       if (!ent) {
+               kfree(ap);
+               return NULL;
+       }
+
+       ata_port_init(ap, host_set, ent, 0);
+       ap->lock = host->host_lock;
+       kfree(ent);
+       return ap;
+}
+EXPORT_SYMBOL_GPL(ata_sas_port_alloc);
+
+/**
+ *     ata_sas_port_start - Set port up for dma.
+ *     @ap: Port to initialize
+ *
+ *     Called just after data structures for each port are
+ *     initialized.  Allocates DMA pad.
+ *
+ *     May be used as the port_start() entry in ata_port_operations.
+ *
+ *     LOCKING:
+ *     Inherited from caller.
+ */
+int ata_sas_port_start(struct ata_port *ap)
+{
+       return ata_pad_alloc(ap, ap->dev);
+}
+EXPORT_SYMBOL_GPL(ata_sas_port_start);
+
+/**
+ *     ata_port_stop - Undo ata_sas_port_start()
+ *     @ap: Port to shut down
+ *
+ *     Frees the DMA pad.
+ *
+ *     May be used as the port_stop() entry in ata_port_operations.
+ *
+ *     LOCKING:
+ *     Inherited from caller.
+ */
+
+void ata_sas_port_stop(struct ata_port *ap)
+{
+       ata_pad_free(ap, ap->dev);
+}
+EXPORT_SYMBOL_GPL(ata_sas_port_stop);
+
+/**
+ *     ata_sas_port_init - Initialize a SATA device
+ *     @ap: SATA port to initialize
+ *
+ *     LOCKING:
+ *     PCI/etc. bus probe sem.
+ *
+ *     RETURNS:
+ *     Zero on success, non-zero on error.
+ */
+
+int ata_sas_port_init(struct ata_port *ap)
+{
+       int rc = ap->ops->port_start(ap);
+
+       if (!rc)
+               rc = ata_bus_probe(ap);
+
+       return rc;
+}
+EXPORT_SYMBOL_GPL(ata_sas_port_init);
+
+/**
+ *     ata_sas_port_destroy - Destroy a SATA port allocated by ata_sas_port_alloc
+ *     @ap: SATA port to destroy
+ *
+ */
+
+void ata_sas_port_destroy(struct ata_port *ap)
+{
+       ap->ops->port_stop(ap);
+       kfree(ap);
+}
+EXPORT_SYMBOL_GPL(ata_sas_port_destroy);
+
+/**
+ *     ata_sas_slave_configure - Default slave_config routine for libata devices
+ *     @sdev: SCSI device to configure
+ *     @ap: ATA port to which SCSI device is attached
+ *
+ *     RETURNS:
+ *     Zero.
+ */
+
+int ata_sas_slave_configure(struct scsi_device *sdev, struct ata_port *ap)
+{
+       ata_scsi_sdev_config(sdev);
+       ata_scsi_dev_config(sdev, ap->device);
+       return 0;
+}
+EXPORT_SYMBOL_GPL(ata_sas_slave_configure);
+
+/**
+ *     ata_sas_queuecmd - Issue SCSI cdb to libata-managed device
+ *     @cmd: SCSI command to be sent
+ *     @done: Completion function, called when command is complete
+ *     @ap:    ATA port to which the command is being sent
+ *
+ *     RETURNS:
+ *     Zero.
+ */
+
+int ata_sas_queuecmd(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *),
+                    struct ata_port *ap)
+{
+       ata_scsi_dump_cdb(ap, cmd);
+
+       if (likely(ata_scsi_dev_enabled(ap->device)))
+               __ata_scsi_queuecmd(cmd, done, ap->device);
+       else {
+               cmd->result = (DID_BAD_TARGET << 16);
+               done(cmd);
+       }
+       return 0;
+}
+EXPORT_SYMBOL_GPL(ata_sas_queuecmd);
diff --git a/drivers/ata/libata.h b/drivers/ata/libata.h
new file mode 100644 (file)
index 0000000..d4a4f82
--- /dev/null
@@ -0,0 +1,122 @@
+/*
+ *  libata.h - helper library for ATA
+ *
+ *  Copyright 2003-2004 Red Hat, Inc.  All rights reserved.
+ *  Copyright 2003-2004 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.*
+ *
+ */
+
+#ifndef __LIBATA_H__
+#define __LIBATA_H__
+
+#define DRV_NAME       "libata"
+#define DRV_VERSION    "2.00"  /* must be exactly four chars */
+
+struct ata_scsi_args {
+       struct ata_device       *dev;
+       u16                     *id;
+       struct scsi_cmnd        *cmd;
+       void                    (*done)(struct scsi_cmnd *);
+};
+
+/* libata-core.c */
+extern struct workqueue_struct *ata_aux_wq;
+extern int atapi_enabled;
+extern int atapi_dmadir;
+extern int libata_fua;
+extern struct ata_queued_cmd *ata_qc_new_init(struct ata_device *dev);
+extern int ata_rwcmd_protocol(struct ata_queued_cmd *qc);
+extern void ata_dev_disable(struct ata_device *dev);
+extern void ata_port_flush_task(struct ata_port *ap);
+extern unsigned ata_exec_internal(struct ata_device *dev,
+                                 struct ata_taskfile *tf, const u8 *cdb,
+                                 int dma_dir, void *buf, unsigned int buflen);
+extern unsigned int ata_do_simple_cmd(struct ata_device *dev, u8 cmd);
+extern int ata_dev_read_id(struct ata_device *dev, unsigned int *p_class,
+                          int post_reset, u16 *id);
+extern int ata_dev_configure(struct ata_device *dev, int print_info);
+extern int sata_down_spd_limit(struct ata_port *ap);
+extern int sata_set_spd_needed(struct ata_port *ap);
+extern int ata_down_xfermask_limit(struct ata_device *dev, int force_pio0);
+extern int ata_set_mode(struct ata_port *ap, struct ata_device **r_failed_dev);
+extern void ata_qc_free(struct ata_queued_cmd *qc);
+extern void ata_qc_issue(struct ata_queued_cmd *qc);
+extern void __ata_qc_complete(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);
+extern void swap_buf_le16(u16 *buf, unsigned int buf_words);
+extern int ata_flush_cache(struct ata_device *dev);
+extern void ata_dev_init(struct ata_device *dev);
+extern int ata_task_ioctl(struct scsi_device *scsidev, void __user *arg);
+extern int ata_cmd_ioctl(struct scsi_device *scsidev, void __user *arg);
+extern void ata_port_init(struct ata_port *ap, struct ata_host_set *host_set,
+                         const struct ata_probe_ent *ent, unsigned int port_no);
+extern struct ata_probe_ent *ata_probe_ent_alloc(struct device *dev,
+                                                const struct ata_port_info *port);
+
+
+/* libata-scsi.c */
+extern struct scsi_transport_template ata_scsi_transport_template;
+
+extern void ata_scsi_scan_host(struct ata_port *ap);
+extern int ata_scsi_offline_dev(struct ata_device *dev);
+extern void ata_scsi_hotplug(void *data);
+extern unsigned int ata_scsiop_inq_std(struct ata_scsi_args *args, u8 *rbuf,
+                              unsigned int buflen);
+
+extern unsigned int ata_scsiop_inq_00(struct ata_scsi_args *args, u8 *rbuf,
+                             unsigned int buflen);
+
+extern unsigned int ata_scsiop_inq_80(struct ata_scsi_args *args, u8 *rbuf,
+                             unsigned int buflen);
+extern unsigned int ata_scsiop_inq_83(struct ata_scsi_args *args, u8 *rbuf,
+                             unsigned int buflen);
+extern unsigned int ata_scsiop_noop(struct ata_scsi_args *args, u8 *rbuf,
+                           unsigned int buflen);
+extern unsigned int ata_scsiop_sync_cache(struct ata_scsi_args *args, u8 *rbuf,
+                                 unsigned int buflen);
+extern unsigned int ata_scsiop_mode_sense(struct ata_scsi_args *args, u8 *rbuf,
+                                 unsigned int buflen);
+extern unsigned int ata_scsiop_read_cap(struct ata_scsi_args *args, u8 *rbuf,
+                               unsigned int buflen);
+extern unsigned int ata_scsiop_report_luns(struct ata_scsi_args *args, u8 *rbuf,
+                                  unsigned int buflen);
+extern void ata_scsi_badcmd(struct scsi_cmnd *cmd,
+                           void (*done)(struct scsi_cmnd *),
+                           u8 asc, u8 ascq);
+extern void ata_scsi_set_sense(struct scsi_cmnd *cmd,
+                              u8 sk, u8 asc, u8 ascq);
+extern void ata_scsi_rbuf_fill(struct ata_scsi_args *args,
+                        unsigned int (*actor) (struct ata_scsi_args *args,
+                                           u8 *rbuf, unsigned int buflen));
+extern void ata_schedule_scsi_eh(struct Scsi_Host *shost);
+extern void ata_scsi_dev_rescan(void *data);
+extern int ata_bus_probe(struct ata_port *ap);
+
+/* libata-eh.c */
+extern enum scsi_eh_timer_return ata_scsi_timed_out(struct scsi_cmnd *cmd);
+extern void ata_scsi_error(struct Scsi_Host *host);
+extern void ata_port_wait_eh(struct ata_port *ap);
+extern void ata_qc_schedule_eh(struct ata_queued_cmd *qc);
+
+#endif /* __LIBATA_H__ */
diff --git a/drivers/ata/pdc_adma.c b/drivers/ata/pdc_adma.c
new file mode 100644 (file)
index 0000000..61d2aa6
--- /dev/null
@@ -0,0 +1,740 @@
+/*
+ *  pdc_adma.c - Pacific Digital Corporation ADMA
+ *
+ *  Maintained by:  Mark Lord <mlord@pobox.com>
+ *
+ *  Copyright 2005 Mark Lord
+ *
+ *  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.*
+ *
+ *
+ *  Supports ATA disks in single-packet ADMA mode.
+ *  Uses PIO for everything else.
+ *
+ *  TODO:  Use ADMA transfers for ATAPI devices, when possible.
+ *  This requires careful attention to a number of quirks of the chip.
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/pci.h>
+#include <linux/init.h>
+#include <linux/blkdev.h>
+#include <linux/delay.h>
+#include <linux/interrupt.h>
+#include <linux/sched.h>
+#include <linux/device.h>
+#include <scsi/scsi_host.h>
+#include <asm/io.h>
+#include <linux/libata.h>
+
+#define DRV_NAME       "pdc_adma"
+#define DRV_VERSION    "0.04"
+
+/* macro to calculate base address for ATA regs */
+#define ADMA_ATA_REGS(base,port_no)    ((base) + ((port_no) * 0x40))
+
+/* macro to calculate base address for ADMA regs */
+#define ADMA_REGS(base,port_no)        ((base) + 0x80 + ((port_no) * 0x20))
+
+enum {
+       ADMA_PORTS              = 2,
+       ADMA_CPB_BYTES          = 40,
+       ADMA_PRD_BYTES          = LIBATA_MAX_PRD * 16,
+       ADMA_PKT_BYTES          = ADMA_CPB_BYTES + ADMA_PRD_BYTES,
+
+       ADMA_DMA_BOUNDARY       = 0xffffffff,
+
+       /* global register offsets */
+       ADMA_MODE_LOCK          = 0x00c7,
+
+       /* per-channel register offsets */
+       ADMA_CONTROL            = 0x0000, /* ADMA control */
+       ADMA_STATUS             = 0x0002, /* ADMA status */
+       ADMA_CPB_COUNT          = 0x0004, /* CPB count */
+       ADMA_CPB_CURRENT        = 0x000c, /* current CPB address */
+       ADMA_CPB_NEXT           = 0x000c, /* next CPB address */
+       ADMA_CPB_LOOKUP         = 0x0010, /* CPB lookup table */
+       ADMA_FIFO_IN            = 0x0014, /* input FIFO threshold */
+       ADMA_FIFO_OUT           = 0x0016, /* output FIFO threshold */
+
+       /* ADMA_CONTROL register bits */
+       aNIEN                   = (1 << 8), /* irq mask: 1==masked */
+       aGO                     = (1 << 7), /* packet trigger ("Go!") */
+       aRSTADM                 = (1 << 5), /* ADMA logic reset */
+       aPIOMD4                 = 0x0003,   /* PIO mode 4 */
+
+       /* ADMA_STATUS register bits */
+       aPSD                    = (1 << 6),
+       aUIRQ                   = (1 << 4),
+       aPERR                   = (1 << 0),
+
+       /* CPB bits */
+       cDONE                   = (1 << 0),
+       cVLD                    = (1 << 0),
+       cDAT                    = (1 << 2),
+       cIEN                    = (1 << 3),
+
+       /* PRD bits */
+       pORD                    = (1 << 4),
+       pDIRO                   = (1 << 5),
+       pEND                    = (1 << 7),
+
+       /* ATA register flags */
+       rIGN                    = (1 << 5),
+       rEND                    = (1 << 7),
+
+       /* ATA register addresses */
+       ADMA_REGS_CONTROL       = 0x0e,
+       ADMA_REGS_SECTOR_COUNT  = 0x12,
+       ADMA_REGS_LBA_LOW       = 0x13,
+       ADMA_REGS_LBA_MID       = 0x14,
+       ADMA_REGS_LBA_HIGH      = 0x15,
+       ADMA_REGS_DEVICE        = 0x16,
+       ADMA_REGS_COMMAND       = 0x17,
+
+       /* PCI device IDs */
+       board_1841_idx          = 0,    /* ADMA 2-port controller */
+};
+
+typedef enum { adma_state_idle, adma_state_pkt, adma_state_mmio } adma_state_t;
+
+struct adma_port_priv {
+       u8                      *pkt;
+       dma_addr_t              pkt_dma;
+       adma_state_t            state;
+};
+
+static int adma_ata_init_one (struct pci_dev *pdev,
+                               const struct pci_device_id *ent);
+static irqreturn_t adma_intr (int irq, void *dev_instance,
+                               struct pt_regs *regs);
+static int adma_port_start(struct ata_port *ap);
+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 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);
+static void adma_irq_clear(struct ata_port *ap);
+static void adma_eng_timeout(struct ata_port *ap);
+
+static struct scsi_host_template adma_ata_sht = {
+       .module                 = THIS_MODULE,
+       .name                   = DRV_NAME,
+       .ioctl                  = ata_scsi_ioctl,
+       .queuecommand           = ata_scsi_queuecmd,
+       .can_queue              = ATA_DEF_QUEUE,
+       .this_id                = ATA_SHT_THIS_ID,
+       .sg_tablesize           = LIBATA_MAX_PRD,
+       .cmd_per_lun            = ATA_SHT_CMD_PER_LUN,
+       .emulated               = ATA_SHT_EMULATED,
+       .use_clustering         = ENABLE_CLUSTERING,
+       .proc_name              = DRV_NAME,
+       .dma_boundary           = ADMA_DMA_BOUNDARY,
+       .slave_configure        = ata_scsi_slave_config,
+       .slave_destroy          = ata_scsi_slave_destroy,
+       .bios_param             = ata_std_bios_param,
+};
+
+static const struct ata_port_operations adma_ata_ops = {
+       .port_disable           = ata_port_disable,
+       .tf_load                = ata_tf_load,
+       .tf_read                = ata_tf_read,
+       .check_status           = ata_check_status,
+       .check_atapi_dma        = adma_check_atapi_dma,
+       .exec_command           = ata_exec_command,
+       .dev_select             = ata_std_dev_select,
+       .phy_reset              = adma_phy_reset,
+       .qc_prep                = adma_qc_prep,
+       .qc_issue               = adma_qc_issue,
+       .eng_timeout            = adma_eng_timeout,
+       .data_xfer              = ata_mmio_data_xfer,
+       .irq_handler            = adma_intr,
+       .irq_clear              = adma_irq_clear,
+       .port_start             = adma_port_start,
+       .port_stop              = adma_port_stop,
+       .host_stop              = adma_host_stop,
+       .bmdma_stop             = adma_bmdma_stop,
+       .bmdma_status           = adma_bmdma_status,
+};
+
+static struct ata_port_info adma_port_info[] = {
+       /* board_1841_idx */
+       {
+               .sht            = &adma_ata_sht,
+               .host_flags     = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST |
+                                 ATA_FLAG_NO_LEGACY | ATA_FLAG_MMIO |
+                                 ATA_FLAG_PIO_POLLING,
+               .pio_mask       = 0x10, /* pio4 */
+               .udma_mask      = 0x1f, /* udma0-4 */
+               .port_ops       = &adma_ata_ops,
+       },
+};
+
+static const struct pci_device_id adma_ata_pci_tbl[] = {
+       { PCI_VENDOR_ID_PDC, 0x1841, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+         board_1841_idx },
+
+       { }     /* terminate list */
+};
+
+static struct pci_driver adma_ata_pci_driver = {
+       .name                   = DRV_NAME,
+       .id_table               = adma_ata_pci_tbl,
+       .probe                  = adma_ata_init_one,
+       .remove                 = ata_pci_remove_one,
+};
+
+static int adma_check_atapi_dma(struct ata_queued_cmd *qc)
+{
+       return 1;       /* ATAPI DMA not yet supported */
+}
+
+static void adma_bmdma_stop(struct ata_queued_cmd *qc)
+{
+       /* nothing */
+}
+
+static u8 adma_bmdma_status(struct ata_port *ap)
+{
+       return 0;
+}
+
+static void adma_irq_clear(struct ata_port *ap)
+{
+       /* nothing */
+}
+
+static void adma_reset_engine(void __iomem *chan)
+{
+       /* reset ADMA to idle state */
+       writew(aPIOMD4 | aNIEN | aRSTADM, chan + ADMA_CONTROL);
+       udelay(2);
+       writew(aPIOMD4, chan + ADMA_CONTROL);
+       udelay(2);
+}
+
+static void adma_reinit_engine(struct ata_port *ap)
+{
+       struct adma_port_priv *pp = ap->private_data;
+       void __iomem *mmio_base = ap->host_set->mmio_base;
+       void __iomem *chan = ADMA_REGS(mmio_base, ap->port_no);
+
+       /* mask/clear ATA interrupts */
+       writeb(ATA_NIEN, (void __iomem *)ap->ioaddr.ctl_addr);
+       ata_check_status(ap);
+
+       /* reset the ADMA engine */
+       adma_reset_engine(chan);
+
+       /* set in-FIFO threshold to 0x100 */
+       writew(0x100, chan + ADMA_FIFO_IN);
+
+       /* set CPB pointer */
+       writel((u32)pp->pkt_dma, chan + ADMA_CPB_NEXT);
+
+       /* set out-FIFO threshold to 0x100 */
+       writew(0x100, chan + ADMA_FIFO_OUT);
+
+       /* set CPB count */
+       writew(1, chan + ADMA_CPB_COUNT);
+
+       /* read/discard ADMA status */
+       readb(chan + ADMA_STATUS);
+}
+
+static inline void adma_enter_reg_mode(struct ata_port *ap)
+{
+       void __iomem *chan = ADMA_REGS(ap->host_set->mmio_base, ap->port_no);
+
+       writew(aPIOMD4, chan + ADMA_CONTROL);
+       readb(chan + ADMA_STATUS);      /* flush */
+}
+
+static void adma_phy_reset(struct ata_port *ap)
+{
+       struct adma_port_priv *pp = ap->private_data;
+
+       pp->state = adma_state_idle;
+       adma_reinit_engine(ap);
+       ata_port_probe(ap);
+       ata_bus_reset(ap);
+}
+
+static void adma_eng_timeout(struct ata_port *ap)
+{
+       struct adma_port_priv *pp = ap->private_data;
+
+       if (pp->state != adma_state_idle) /* healthy paranoia */
+               pp->state = adma_state_mmio;
+       adma_reinit_engine(ap);
+       ata_eng_timeout(ap);
+}
+
+static int adma_fill_sg(struct ata_queued_cmd *qc)
+{
+       struct scatterlist *sg;
+       struct ata_port *ap = qc->ap;
+       struct adma_port_priv *pp = ap->private_data;
+       u8  *buf = pp->pkt;
+       int i = (2 + buf[3]) * 8;
+       u8 pFLAGS = pORD | ((qc->tf.flags & ATA_TFLAG_WRITE) ? pDIRO : 0);
+
+       ata_for_each_sg(sg, qc) {
+               u32 addr;
+               u32 len;
+
+               addr = (u32)sg_dma_address(sg);
+               *(__le32 *)(buf + i) = cpu_to_le32(addr);
+               i += 4;
+
+               len = sg_dma_len(sg) >> 3;
+               *(__le32 *)(buf + i) = cpu_to_le32(len);
+               i += 4;
+
+               if (ata_sg_is_last(sg, qc))
+                       pFLAGS |= pEND;
+               buf[i++] = pFLAGS;
+               buf[i++] = qc->dev->dma_mode & 0xf;
+               buf[i++] = 0;   /* pPKLW */
+               buf[i++] = 0;   /* reserved */
+
+               *(__le32 *)(buf + i)
+                       = (pFLAGS & pEND) ? 0 : cpu_to_le32(pp->pkt_dma + i + 4);
+               i += 4;
+
+               VPRINTK("PRD[%u] = (0x%lX, 0x%X)\n", i/4,
+                                       (unsigned long)addr, len);
+       }
+       return i;
+}
+
+static void adma_qc_prep(struct ata_queued_cmd *qc)
+{
+       struct adma_port_priv *pp = qc->ap->private_data;
+       u8  *buf = pp->pkt;
+       u32 pkt_dma = (u32)pp->pkt_dma;
+       int i = 0;
+
+       VPRINTK("ENTER\n");
+
+       adma_enter_reg_mode(qc->ap);
+       if (qc->tf.protocol != ATA_PROT_DMA) {
+               ata_qc_prep(qc);
+               return;
+       }
+
+       buf[i++] = 0;   /* Response flags */
+       buf[i++] = 0;   /* reserved */
+       buf[i++] = cVLD | cDAT | cIEN;
+       i++;            /* cLEN, gets filled in below */
+
+       *(__le32 *)(buf+i) = cpu_to_le32(pkt_dma);      /* cNCPB */
+       i += 4;         /* cNCPB */
+       i += 4;         /* cPRD, gets filled in below */
+
+       buf[i++] = 0;   /* reserved */
+       buf[i++] = 0;   /* reserved */
+       buf[i++] = 0;   /* reserved */
+       buf[i++] = 0;   /* reserved */
+
+       /* ATA registers; must be a multiple of 4 */
+       buf[i++] = qc->tf.device;
+       buf[i++] = ADMA_REGS_DEVICE;
+       if ((qc->tf.flags & ATA_TFLAG_LBA48)) {
+               buf[i++] = qc->tf.hob_nsect;
+               buf[i++] = ADMA_REGS_SECTOR_COUNT;
+               buf[i++] = qc->tf.hob_lbal;
+               buf[i++] = ADMA_REGS_LBA_LOW;
+               buf[i++] = qc->tf.hob_lbam;
+               buf[i++] = ADMA_REGS_LBA_MID;
+               buf[i++] = qc->tf.hob_lbah;
+               buf[i++] = ADMA_REGS_LBA_HIGH;
+       }
+       buf[i++] = qc->tf.nsect;
+       buf[i++] = ADMA_REGS_SECTOR_COUNT;
+       buf[i++] = qc->tf.lbal;
+       buf[i++] = ADMA_REGS_LBA_LOW;
+       buf[i++] = qc->tf.lbam;
+       buf[i++] = ADMA_REGS_LBA_MID;
+       buf[i++] = qc->tf.lbah;
+       buf[i++] = ADMA_REGS_LBA_HIGH;
+       buf[i++] = 0;
+       buf[i++] = ADMA_REGS_CONTROL;
+       buf[i++] = rIGN;
+       buf[i++] = 0;
+       buf[i++] = qc->tf.command;
+       buf[i++] = ADMA_REGS_COMMAND | rEND;
+
+       buf[3] = (i >> 3) - 2;                          /* cLEN */
+       *(__le32 *)(buf+8) = cpu_to_le32(pkt_dma + i);  /* cPRD */
+
+       i = adma_fill_sg(qc);
+       wmb();  /* flush PRDs and pkt to memory */
+#if 0
+       /* dump out CPB + PRDs for debug */
+       {
+               int j, len = 0;
+               static char obuf[2048];
+               for (j = 0; j < i; ++j) {
+                       len += sprintf(obuf+len, "%02x ", buf[j]);
+                       if ((j & 7) == 7) {
+                               printk("%s\n", obuf);
+                               len = 0;
+                       }
+               }
+               if (len)
+                       printk("%s\n", obuf);
+       }
+#endif
+}
+
+static inline void adma_packet_start(struct ata_queued_cmd *qc)
+{
+       struct ata_port *ap = qc->ap;
+       void __iomem *chan = ADMA_REGS(ap->host_set->mmio_base, ap->port_no);
+
+       VPRINTK("ENTER, ap %p\n", ap);
+
+       /* fire up the ADMA engine */
+       writew(aPIOMD4 | aGO, chan + ADMA_CONTROL);
+}
+
+static unsigned int adma_qc_issue(struct ata_queued_cmd *qc)
+{
+       struct adma_port_priv *pp = qc->ap->private_data;
+
+       switch (qc->tf.protocol) {
+       case ATA_PROT_DMA:
+               pp->state = adma_state_pkt;
+               adma_packet_start(qc);
+               return 0;
+
+       case ATA_PROT_ATAPI_DMA:
+               BUG();
+               break;
+
+       default:
+               break;
+       }
+
+       pp->state = adma_state_mmio;
+       return ata_qc_issue_prot(qc);
+}
+
+static inline unsigned int adma_intr_pkt(struct ata_host_set *host_set)
+{
+       unsigned int handled = 0, port_no;
+       u8 __iomem *mmio_base = host_set->mmio_base;
+
+       for (port_no = 0; port_no < host_set->n_ports; ++port_no) {
+               struct ata_port *ap = host_set->ports[port_no];
+               struct adma_port_priv *pp;
+               struct ata_queued_cmd *qc;
+               void __iomem *chan = ADMA_REGS(mmio_base, port_no);
+               u8 status = readb(chan + ADMA_STATUS);
+
+               if (status == 0)
+                       continue;
+               handled = 1;
+               adma_enter_reg_mode(ap);
+               if (ap->flags & ATA_FLAG_DISABLED)
+                       continue;
+               pp = ap->private_data;
+               if (!pp || pp->state != adma_state_pkt)
+                       continue;
+               qc = ata_qc_from_tag(ap, ap->active_tag);
+               if (qc && (!(qc->tf.flags & ATA_TFLAG_POLLING))) {
+                       if ((status & (aPERR | aPSD | aUIRQ)))
+                               qc->err_mask |= AC_ERR_OTHER;
+                       else if (pp->pkt[0] != cDONE)
+                               qc->err_mask |= AC_ERR_OTHER;
+
+                       ata_qc_complete(qc);
+               }
+       }
+       return handled;
+}
+
+static inline unsigned int adma_intr_mmio(struct ata_host_set *host_set)
+{
+       unsigned int handled = 0, port_no;
+
+       for (port_no = 0; port_no < host_set->n_ports; ++port_no) {
+               struct ata_port *ap;
+               ap = host_set->ports[port_no];
+               if (ap && (!(ap->flags & ATA_FLAG_DISABLED))) {
+                       struct ata_queued_cmd *qc;
+                       struct adma_port_priv *pp = ap->private_data;
+                       if (!pp || pp->state != adma_state_mmio)
+                               continue;
+                       qc = ata_qc_from_tag(ap, ap->active_tag);
+                       if (qc && (!(qc->tf.flags & ATA_TFLAG_POLLING))) {
+
+                               /* check main status, clearing INTRQ */
+                               u8 status = ata_check_status(ap);
+                               if ((status & ATA_BUSY))
+                                       continue;
+                               DPRINTK("ata%u: protocol %d (dev_stat 0x%X)\n",
+                                       ap->id, qc->tf.protocol, status);
+               
+                               /* complete taskfile transaction */
+                               pp->state = adma_state_idle;
+                               qc->err_mask |= ac_err_mask(status);
+                               ata_qc_complete(qc);
+                               handled = 1;
+                       }
+               }
+       }
+       return handled;
+}
+
+static irqreturn_t adma_intr(int irq, void *dev_instance, struct pt_regs *regs)
+{
+       struct ata_host_set *host_set = dev_instance;
+       unsigned int handled = 0;
+
+       VPRINTK("ENTER\n");
+
+       spin_lock(&host_set->lock);
+       handled  = adma_intr_pkt(host_set) | adma_intr_mmio(host_set);
+       spin_unlock(&host_set->lock);
+
+       VPRINTK("EXIT\n");
+
+       return IRQ_RETVAL(handled);
+}
+
+static void adma_ata_setup_port(struct ata_ioports *port, unsigned long base)
+{
+       port->cmd_addr          =
+       port->data_addr         = base + 0x000;
+       port->error_addr        =
+       port->feature_addr      = base + 0x004;
+       port->nsect_addr        = base + 0x008;
+       port->lbal_addr         = base + 0x00c;
+       port->lbam_addr         = base + 0x010;
+       port->lbah_addr         = base + 0x014;
+       port->device_addr       = base + 0x018;
+       port->status_addr       =
+       port->command_addr      = base + 0x01c;
+       port->altstatus_addr    =
+       port->ctl_addr          = base + 0x038;
+}
+
+static int adma_port_start(struct ata_port *ap)
+{
+       struct device *dev = ap->host_set->dev;
+       struct adma_port_priv *pp;
+       int rc;
+
+       rc = ata_port_start(ap);
+       if (rc)
+               return rc;
+       adma_enter_reg_mode(ap);
+       rc = -ENOMEM;
+       pp = kcalloc(1, sizeof(*pp), GFP_KERNEL);
+       if (!pp)
+               goto err_out;
+       pp->pkt = dma_alloc_coherent(dev, ADMA_PKT_BYTES, &pp->pkt_dma,
+                                                               GFP_KERNEL);
+       if (!pp->pkt)
+               goto err_out_kfree;
+       /* paranoia? */
+       if ((pp->pkt_dma & 7) != 0) {
+               printk("bad alignment for pp->pkt_dma: %08x\n",
+                                               (u32)pp->pkt_dma);
+               dma_free_coherent(dev, ADMA_PKT_BYTES,
+                                               pp->pkt, pp->pkt_dma);
+               goto err_out_kfree;
+       }
+       memset(pp->pkt, 0, ADMA_PKT_BYTES);
+       ap->private_data = pp;
+       adma_reinit_engine(ap);
+       return 0;
+
+err_out_kfree:
+       kfree(pp);
+err_out:
+       ata_port_stop(ap);
+       return rc;
+}
+
+static void adma_port_stop(struct ata_port *ap)
+{
+       struct device *dev = ap->host_set->dev;
+       struct adma_port_priv *pp = ap->private_data;
+
+       adma_reset_engine(ADMA_REGS(ap->host_set->mmio_base, ap->port_no));
+       if (pp != NULL) {
+               ap->private_data = NULL;
+               if (pp->pkt != NULL)
+                       dma_free_coherent(dev, ADMA_PKT_BYTES,
+                                       pp->pkt, pp->pkt_dma);
+               kfree(pp);
+       }
+       ata_port_stop(ap);
+}
+
+static void adma_host_stop(struct ata_host_set *host_set)
+{
+       unsigned int port_no;
+
+       for (port_no = 0; port_no < ADMA_PORTS; ++port_no)
+               adma_reset_engine(ADMA_REGS(host_set->mmio_base, port_no));
+
+       ata_pci_host_stop(host_set);
+}
+
+static void adma_host_init(unsigned int chip_id,
+                               struct ata_probe_ent *probe_ent)
+{
+       unsigned int port_no;
+       void __iomem *mmio_base = probe_ent->mmio_base;
+
+       /* enable/lock aGO operation */
+       writeb(7, mmio_base + ADMA_MODE_LOCK);
+
+       /* reset the ADMA logic */
+       for (port_no = 0; port_no < ADMA_PORTS; ++port_no)
+               adma_reset_engine(ADMA_REGS(mmio_base, port_no));
+}
+
+static int adma_set_dma_masks(struct pci_dev *pdev, void __iomem *mmio_base)
+{
+       int rc;
+
+       rc = pci_set_dma_mask(pdev, DMA_32BIT_MASK);
+       if (rc) {
+               dev_printk(KERN_ERR, &pdev->dev,
+                       "32-bit DMA enable failed\n");
+               return rc;
+       }
+       rc = pci_set_consistent_dma_mask(pdev, DMA_32BIT_MASK);
+       if (rc) {
+               dev_printk(KERN_ERR, &pdev->dev,
+                       "32-bit consistent DMA enable failed\n");
+               return rc;
+       }
+       return 0;
+}
+
+static int adma_ata_init_one(struct pci_dev *pdev,
+                               const struct pci_device_id *ent)
+{
+       static int printed_version;
+       struct ata_probe_ent *probe_ent = NULL;
+       void __iomem *mmio_base;
+       unsigned int board_idx = (unsigned int) ent->driver_data;
+       int rc, port_no;
+
+       if (!printed_version++)
+               dev_printk(KERN_DEBUG, &pdev->dev, "version " DRV_VERSION "\n");
+
+       rc = pci_enable_device(pdev);
+       if (rc)
+               return rc;
+
+       rc = pci_request_regions(pdev, DRV_NAME);
+       if (rc)
+               goto err_out;
+
+       if ((pci_resource_flags(pdev, 4) & IORESOURCE_MEM) == 0) {
+               rc = -ENODEV;
+               goto err_out_regions;
+       }
+
+       mmio_base = pci_iomap(pdev, 4, 0);
+       if (mmio_base == NULL) {
+               rc = -ENOMEM;
+               goto err_out_regions;
+       }
+
+       rc = adma_set_dma_masks(pdev, mmio_base);
+       if (rc)
+               goto err_out_iounmap;
+
+       probe_ent = kcalloc(1, sizeof(*probe_ent), GFP_KERNEL);
+       if (probe_ent == NULL) {
+               rc = -ENOMEM;
+               goto err_out_iounmap;
+       }
+
+       probe_ent->dev = pci_dev_to_dev(pdev);
+       INIT_LIST_HEAD(&probe_ent->node);
+
+       probe_ent->sht          = adma_port_info[board_idx].sht;
+       probe_ent->host_flags   = adma_port_info[board_idx].host_flags;
+       probe_ent->pio_mask     = adma_port_info[board_idx].pio_mask;
+       probe_ent->mwdma_mask   = adma_port_info[board_idx].mwdma_mask;
+       probe_ent->udma_mask    = adma_port_info[board_idx].udma_mask;
+       probe_ent->port_ops     = adma_port_info[board_idx].port_ops;
+
+       probe_ent->irq          = pdev->irq;
+       probe_ent->irq_flags    = IRQF_SHARED;
+       probe_ent->mmio_base    = mmio_base;
+       probe_ent->n_ports      = ADMA_PORTS;
+
+       for (port_no = 0; port_no < probe_ent->n_ports; ++port_no) {
+               adma_ata_setup_port(&probe_ent->port[port_no],
+                       ADMA_ATA_REGS((unsigned long)mmio_base, port_no));
+       }
+
+       pci_set_master(pdev);
+
+       /* initialize adapter */
+       adma_host_init(board_idx, probe_ent);
+
+       rc = ata_device_add(probe_ent);
+       kfree(probe_ent);
+       if (rc != ADMA_PORTS)
+               goto err_out_iounmap;
+       return 0;
+
+err_out_iounmap:
+       pci_iounmap(pdev, mmio_base);
+err_out_regions:
+       pci_release_regions(pdev);
+err_out:
+       pci_disable_device(pdev);
+       return rc;
+}
+
+static int __init adma_ata_init(void)
+{
+       return pci_register_driver(&adma_ata_pci_driver);
+}
+
+static void __exit adma_ata_exit(void)
+{
+       pci_unregister_driver(&adma_ata_pci_driver);
+}
+
+MODULE_AUTHOR("Mark Lord");
+MODULE_DESCRIPTION("Pacific Digital Corporation ADMA low-level driver");
+MODULE_LICENSE("GPL");
+MODULE_DEVICE_TABLE(pci, adma_ata_pci_tbl);
+MODULE_VERSION(DRV_VERSION);
+
+module_init(adma_ata_init);
+module_exit(adma_ata_exit);
diff --git a/drivers/ata/sata_mv.c b/drivers/ata/sata_mv.c
new file mode 100644 (file)
index 0000000..a2915a5
--- /dev/null
@@ -0,0 +1,2468 @@
+/*
+ * sata_mv.c - Marvell SATA support
+ *
+ * Copyright 2005: EMC Corporation, all rights reserved.
+ * Copyright 2005 Red Hat, Inc.  All rights reserved.
+ *
+ * Please ALWAYS copy linux-ide@vger.kernel.org on emails.
+ *
+ * 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; version 2 of the License.
+ *
+ * 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; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/pci.h>
+#include <linux/init.h>
+#include <linux/blkdev.h>
+#include <linux/delay.h>
+#include <linux/interrupt.h>
+#include <linux/sched.h>
+#include <linux/dma-mapping.h>
+#include <linux/device.h>
+#include <scsi/scsi_host.h>
+#include <scsi/scsi_cmnd.h>
+#include <linux/libata.h>
+#include <asm/io.h>
+
+#define DRV_NAME       "sata_mv"
+#define DRV_VERSION    "0.7"
+
+enum {
+       /* BAR's are enumerated in terms of pci_resource_start() terms */
+       MV_PRIMARY_BAR          = 0,    /* offset 0x10: memory space */
+       MV_IO_BAR               = 2,    /* offset 0x18: IO space */
+       MV_MISC_BAR             = 3,    /* offset 0x1c: FLASH, NVRAM, SRAM */
+
+       MV_MAJOR_REG_AREA_SZ    = 0x10000,      /* 64KB */
+       MV_MINOR_REG_AREA_SZ    = 0x2000,       /* 8KB */
+
+       MV_PCI_REG_BASE         = 0,
+       MV_IRQ_COAL_REG_BASE    = 0x18000,      /* 6xxx part only */
+       MV_IRQ_COAL_CAUSE               = (MV_IRQ_COAL_REG_BASE + 0x08),
+       MV_IRQ_COAL_CAUSE_LO            = (MV_IRQ_COAL_REG_BASE + 0x88),
+       MV_IRQ_COAL_CAUSE_HI            = (MV_IRQ_COAL_REG_BASE + 0x8c),
+       MV_IRQ_COAL_THRESHOLD           = (MV_IRQ_COAL_REG_BASE + 0xcc),
+       MV_IRQ_COAL_TIME_THRESHOLD      = (MV_IRQ_COAL_REG_BASE + 0xd0),
+
+       MV_SATAHC0_REG_BASE     = 0x20000,
+       MV_FLASH_CTL            = 0x1046c,
+       MV_GPIO_PORT_CTL        = 0x104f0,
+       MV_RESET_CFG            = 0x180d8,
+
+       MV_PCI_REG_SZ           = MV_MAJOR_REG_AREA_SZ,
+       MV_SATAHC_REG_SZ        = MV_MAJOR_REG_AREA_SZ,
+       MV_SATAHC_ARBTR_REG_SZ  = MV_MINOR_REG_AREA_SZ,         /* arbiter */
+       MV_PORT_REG_SZ          = MV_MINOR_REG_AREA_SZ,
+
+       MV_USE_Q_DEPTH          = ATA_DEF_QUEUE,
+
+       MV_MAX_Q_DEPTH          = 32,
+       MV_MAX_Q_DEPTH_MASK     = MV_MAX_Q_DEPTH - 1,
+
+       /* CRQB needs alignment on a 1KB boundary. Size == 1KB
+        * CRPB needs alignment on a 256B boundary. Size == 256B
+        * SG count of 176 leads to MV_PORT_PRIV_DMA_SZ == 4KB
+        * ePRD (SG) entries need alignment on a 16B boundary. Size == 16B
+        */
+       MV_CRQB_Q_SZ            = (32 * MV_MAX_Q_DEPTH),
+       MV_CRPB_Q_SZ            = (8 * MV_MAX_Q_DEPTH),
+       MV_MAX_SG_CT            = 176,
+       MV_SG_TBL_SZ            = (16 * MV_MAX_SG_CT),
+       MV_PORT_PRIV_DMA_SZ     = (MV_CRQB_Q_SZ + MV_CRPB_Q_SZ + MV_SG_TBL_SZ),
+
+       MV_PORTS_PER_HC         = 4,
+       /* == (port / MV_PORTS_PER_HC) to determine HC from 0-7 port */
+       MV_PORT_HC_SHIFT        = 2,
+       /* == (port % MV_PORTS_PER_HC) to determine hard port from 0-7 port */
+       MV_PORT_MASK            = 3,
+
+       /* Host Flags */
+       MV_FLAG_DUAL_HC         = (1 << 30),  /* two SATA Host Controllers */
+       MV_FLAG_IRQ_COALESCE    = (1 << 29),  /* IRQ coalescing capability */
+       MV_COMMON_FLAGS         = (ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
+                                  ATA_FLAG_SATA_RESET | ATA_FLAG_MMIO |
+                                  ATA_FLAG_NO_ATAPI | ATA_FLAG_PIO_POLLING),
+       MV_6XXX_FLAGS           = MV_FLAG_IRQ_COALESCE,
+
+       CRQB_FLAG_READ          = (1 << 0),
+       CRQB_TAG_SHIFT          = 1,
+       CRQB_CMD_ADDR_SHIFT     = 8,
+       CRQB_CMD_CS             = (0x2 << 11),
+       CRQB_CMD_LAST           = (1 << 15),
+
+       CRPB_FLAG_STATUS_SHIFT  = 8,
+
+       EPRD_FLAG_END_OF_TBL    = (1 << 31),
+
+       /* PCI interface registers */
+
+       PCI_COMMAND_OFS         = 0xc00,
+
+       PCI_MAIN_CMD_STS_OFS    = 0xd30,
+       STOP_PCI_MASTER         = (1 << 2),
+       PCI_MASTER_EMPTY        = (1 << 3),
+       GLOB_SFT_RST            = (1 << 4),
+
+       MV_PCI_MODE             = 0xd00,
+       MV_PCI_EXP_ROM_BAR_CTL  = 0xd2c,
+       MV_PCI_DISC_TIMER       = 0xd04,
+       MV_PCI_MSI_TRIGGER      = 0xc38,
+       MV_PCI_SERR_MASK        = 0xc28,
+       MV_PCI_XBAR_TMOUT       = 0x1d04,
+       MV_PCI_ERR_LOW_ADDRESS  = 0x1d40,
+       MV_PCI_ERR_HIGH_ADDRESS = 0x1d44,
+       MV_PCI_ERR_ATTRIBUTE    = 0x1d48,
+       MV_PCI_ERR_COMMAND      = 0x1d50,
+
+       PCI_IRQ_CAUSE_OFS               = 0x1d58,
+       PCI_IRQ_MASK_OFS                = 0x1d5c,
+       PCI_UNMASK_ALL_IRQS     = 0x7fffff,     /* bits 22-0 */
+
+       HC_MAIN_IRQ_CAUSE_OFS   = 0x1d60,
+       HC_MAIN_IRQ_MASK_OFS    = 0x1d64,
+       PORT0_ERR               = (1 << 0),     /* shift by port # */
+       PORT0_DONE              = (1 << 1),     /* shift by port # */
+       HC0_IRQ_PEND            = 0x1ff,        /* bits 0-8 = HC0's ports */
+       HC_SHIFT                = 9,            /* bits 9-17 = HC1's ports */
+       PCI_ERR                 = (1 << 18),
+       TRAN_LO_DONE            = (1 << 19),    /* 6xxx: IRQ coalescing */
+       TRAN_HI_DONE            = (1 << 20),    /* 6xxx: IRQ coalescing */
+       PORTS_0_7_COAL_DONE     = (1 << 21),    /* 6xxx: IRQ coalescing */
+       GPIO_INT                = (1 << 22),
+       SELF_INT                = (1 << 23),
+       TWSI_INT                = (1 << 24),
+       HC_MAIN_RSVD            = (0x7f << 25), /* bits 31-25 */
+       HC_MAIN_MASKED_IRQS     = (TRAN_LO_DONE | TRAN_HI_DONE |
+                                  PORTS_0_7_COAL_DONE | GPIO_INT | TWSI_INT |
+                                  HC_MAIN_RSVD),
+
+       /* SATAHC registers */
+       HC_CFG_OFS              = 0,
+
+       HC_IRQ_CAUSE_OFS        = 0x14,
+       CRPB_DMA_DONE           = (1 << 0),     /* shift by port # */
+       HC_IRQ_COAL             = (1 << 4),     /* IRQ coalescing */
+       DEV_IRQ                 = (1 << 8),     /* shift by port # */
+
+       /* Shadow block registers */
+       SHD_BLK_OFS             = 0x100,
+       SHD_CTL_AST_OFS         = 0x20,         /* ofs from SHD_BLK_OFS */
+
+       /* SATA registers */
+       SATA_STATUS_OFS         = 0x300,  /* ctrl, err regs follow status */
+       SATA_ACTIVE_OFS         = 0x350,
+       PHY_MODE3               = 0x310,
+       PHY_MODE4               = 0x314,
+       PHY_MODE2               = 0x330,
+       MV5_PHY_MODE            = 0x74,
+       MV5_LT_MODE             = 0x30,
+       MV5_PHY_CTL             = 0x0C,
+       SATA_INTERFACE_CTL      = 0x050,
+
+       MV_M2_PREAMP_MASK       = 0x7e0,
+
+       /* Port registers */
+       EDMA_CFG_OFS            = 0,
+       EDMA_CFG_Q_DEPTH        = 0,                    /* queueing disabled */
+       EDMA_CFG_NCQ            = (1 << 5),
+       EDMA_CFG_NCQ_GO_ON_ERR  = (1 << 14),            /* continue on error */
+       EDMA_CFG_RD_BRST_EXT    = (1 << 11),            /* read burst 512B */
+       EDMA_CFG_WR_BUFF_LEN    = (1 << 13),            /* write buffer 512B */
+
+       EDMA_ERR_IRQ_CAUSE_OFS  = 0x8,
+       EDMA_ERR_IRQ_MASK_OFS   = 0xc,
+       EDMA_ERR_D_PAR          = (1 << 0),
+       EDMA_ERR_PRD_PAR        = (1 << 1),
+       EDMA_ERR_DEV            = (1 << 2),
+       EDMA_ERR_DEV_DCON       = (1 << 3),
+       EDMA_ERR_DEV_CON        = (1 << 4),
+       EDMA_ERR_SERR           = (1 << 5),
+       EDMA_ERR_SELF_DIS       = (1 << 7),
+       EDMA_ERR_BIST_ASYNC     = (1 << 8),
+       EDMA_ERR_CRBQ_PAR       = (1 << 9),
+       EDMA_ERR_CRPB_PAR       = (1 << 10),
+       EDMA_ERR_INTRL_PAR      = (1 << 11),
+       EDMA_ERR_IORDY          = (1 << 12),
+       EDMA_ERR_LNK_CTRL_RX    = (0xf << 13),
+       EDMA_ERR_LNK_CTRL_RX_2  = (1 << 15),
+       EDMA_ERR_LNK_DATA_RX    = (0xf << 17),
+       EDMA_ERR_LNK_CTRL_TX    = (0x1f << 21),
+       EDMA_ERR_LNK_DATA_TX    = (0x1f << 26),
+       EDMA_ERR_TRANS_PROTO    = (1 << 31),
+       EDMA_ERR_FATAL          = (EDMA_ERR_D_PAR | EDMA_ERR_PRD_PAR |
+                                  EDMA_ERR_DEV_DCON | EDMA_ERR_CRBQ_PAR |
+                                  EDMA_ERR_CRPB_PAR | EDMA_ERR_INTRL_PAR |
+                                  EDMA_ERR_IORDY | EDMA_ERR_LNK_CTRL_RX_2 |
+                                  EDMA_ERR_LNK_DATA_RX |
+                                  EDMA_ERR_LNK_DATA_TX |
+                                  EDMA_ERR_TRANS_PROTO),
+
+       EDMA_REQ_Q_BASE_HI_OFS  = 0x10,
+       EDMA_REQ_Q_IN_PTR_OFS   = 0x14,         /* also contains BASE_LO */
+
+       EDMA_REQ_Q_OUT_PTR_OFS  = 0x18,
+       EDMA_REQ_Q_PTR_SHIFT    = 5,
+
+       EDMA_RSP_Q_BASE_HI_OFS  = 0x1c,
+       EDMA_RSP_Q_IN_PTR_OFS   = 0x20,
+       EDMA_RSP_Q_OUT_PTR_OFS  = 0x24,         /* also contains BASE_LO */
+       EDMA_RSP_Q_PTR_SHIFT    = 3,
+
+       EDMA_CMD_OFS            = 0x28,
+       EDMA_EN                 = (1 << 0),
+       EDMA_DS                 = (1 << 1),
+       ATA_RST                 = (1 << 2),
+
+       EDMA_IORDY_TMOUT        = 0x34,
+       EDMA_ARB_CFG            = 0x38,
+
+       /* Host private flags (hp_flags) */
+       MV_HP_FLAG_MSI          = (1 << 0),
+       MV_HP_ERRATA_50XXB0     = (1 << 1),
+       MV_HP_ERRATA_50XXB2     = (1 << 2),
+       MV_HP_ERRATA_60X1B2     = (1 << 3),
+       MV_HP_ERRATA_60X1C0     = (1 << 4),
+       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),
+       MV_PP_FLAG_EDMA_DS_ACT  = (1 << 1),
+};
+
+#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
+        * anything larger than 64KB
+        */
+       MV_DMA_BOUNDARY         = 0xffffU,
+
+       EDMA_REQ_Q_BASE_LO_MASK = 0xfffffc00U,
+
+       EDMA_RSP_Q_BASE_LO_MASK = 0xffffff00U,
+};
+
+enum chip_type {
+       chip_504x,
+       chip_508x,
+       chip_5080,
+       chip_604x,
+       chip_608x,
+       chip_6042,
+       chip_7042,
+};
+
+/* Command ReQuest Block: 32B */
+struct mv_crqb {
+       __le32                  sg_addr;
+       __le32                  sg_addr_hi;
+       __le16                  ctrl_flags;
+       __le16                  ata_cmd[11];
+};
+
+struct mv_crqb_iie {
+       __le32                  addr;
+       __le32                  addr_hi;
+       __le32                  flags;
+       __le32                  len;
+       __le32                  ata_cmd[4];
+};
+
+/* Command ResPonse Block: 8B */
+struct mv_crpb {
+       __le16                  id;
+       __le16                  flags;
+       __le32                  tmstmp;
+};
+
+/* EDMA Physical Region Descriptor (ePRD); A.K.A. SG */
+struct mv_sg {
+       __le32                  addr;
+       __le32                  flags_size;
+       __le32                  addr_hi;
+       __le32                  reserved;
+};
+
+struct mv_port_priv {
+       struct mv_crqb          *crqb;
+       dma_addr_t              crqb_dma;
+       struct mv_crpb          *crpb;
+       dma_addr_t              crpb_dma;
+       struct mv_sg            *sg_tbl;
+       dma_addr_t              sg_tbl_dma;
+       u32                     pp_flags;
+};
+
+struct mv_port_signal {
+       u32                     amps;
+       u32                     pre;
+};
+
+struct mv_host_priv;
+struct mv_hw_ops {
+       void (*phy_errata)(struct mv_host_priv *hpriv, void __iomem *mmio,
+                          unsigned int port);
+       void (*enable_leds)(struct mv_host_priv *hpriv, void __iomem *mmio);
+       void (*read_preamp)(struct mv_host_priv *hpriv, int idx,
+                          void __iomem *mmio);
+       int (*reset_hc)(struct mv_host_priv *hpriv, void __iomem *mmio,
+                       unsigned int n_hc);
+       void (*reset_flash)(struct mv_host_priv *hpriv, void __iomem *mmio);
+       void (*reset_bus)(struct pci_dev *pdev, void __iomem *mmio);
+};
+
+struct mv_host_priv {
+       u32                     hp_flags;
+       struct mv_port_signal   signal[8];
+       const struct mv_hw_ops  *ops;
+};
+
+static void mv_irq_clear(struct ata_port *ap);
+static u32 mv_scr_read(struct ata_port *ap, unsigned int sc_reg_in);
+static void mv_scr_write(struct ata_port *ap, unsigned int sc_reg_in, u32 val);
+static u32 mv5_scr_read(struct ata_port *ap, unsigned int sc_reg_in);
+static void mv5_scr_write(struct ata_port *ap, unsigned int sc_reg_in, u32 val);
+static void mv_phy_reset(struct ata_port *ap);
+static void __mv_phy_reset(struct ata_port *ap, int can_sleep);
+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 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);
+static int mv_init_one(struct pci_dev *pdev, const struct pci_device_id *ent);
+
+static void mv5_phy_errata(struct mv_host_priv *hpriv, void __iomem *mmio,
+                          unsigned int port);
+static void mv5_enable_leds(struct mv_host_priv *hpriv, void __iomem *mmio);
+static void mv5_read_preamp(struct mv_host_priv *hpriv, int idx,
+                          void __iomem *mmio);
+static int mv5_reset_hc(struct mv_host_priv *hpriv, void __iomem *mmio,
+                       unsigned int n_hc);
+static void mv5_reset_flash(struct mv_host_priv *hpriv, void __iomem *mmio);
+static void mv5_reset_bus(struct pci_dev *pdev, void __iomem *mmio);
+
+static void mv6_phy_errata(struct mv_host_priv *hpriv, void __iomem *mmio,
+                          unsigned int port);
+static void mv6_enable_leds(struct mv_host_priv *hpriv, void __iomem *mmio);
+static void mv6_read_preamp(struct mv_host_priv *hpriv, int idx,
+                          void __iomem *mmio);
+static int mv6_reset_hc(struct mv_host_priv *hpriv, void __iomem *mmio,
+                       unsigned int n_hc);
+static void mv6_reset_flash(struct mv_host_priv *hpriv, void __iomem *mmio);
+static void mv_reset_pci_bus(struct pci_dev *pdev, void __iomem *mmio);
+static void mv_channel_reset(struct mv_host_priv *hpriv, void __iomem *mmio,
+                            unsigned int port_no);
+static void mv_stop_and_reset(struct ata_port *ap);
+
+static struct scsi_host_template mv_sht = {
+       .module                 = THIS_MODULE,
+       .name                   = DRV_NAME,
+       .ioctl                  = ata_scsi_ioctl,
+       .queuecommand           = ata_scsi_queuecmd,
+       .can_queue              = MV_USE_Q_DEPTH,
+       .this_id                = ATA_SHT_THIS_ID,
+       .sg_tablesize           = MV_MAX_SG_CT / 2,
+       .cmd_per_lun            = ATA_SHT_CMD_PER_LUN,
+       .emulated               = ATA_SHT_EMULATED,
+       .use_clustering         = ATA_SHT_USE_CLUSTERING,
+       .proc_name              = DRV_NAME,
+       .dma_boundary           = MV_DMA_BOUNDARY,
+       .slave_configure        = ata_scsi_slave_config,
+       .slave_destroy          = ata_scsi_slave_destroy,
+       .bios_param             = ata_std_bios_param,
+};
+
+static const struct ata_port_operations mv5_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,
+       .qc_issue               = mv_qc_issue,
+       .data_xfer              = ata_mmio_data_xfer,
+
+       .eng_timeout            = mv_eng_timeout,
+
+       .irq_handler            = mv_interrupt,
+       .irq_clear              = mv_irq_clear,
+
+       .scr_read               = mv5_scr_read,
+       .scr_write              = mv5_scr_write,
+
+       .port_start             = mv_port_start,
+       .port_stop              = mv_port_stop,
+       .host_stop              = mv_host_stop,
+};
+
+static const struct ata_port_operations mv6_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,
+       .qc_issue               = mv_qc_issue,
+       .data_xfer              = ata_mmio_data_xfer,
+
+       .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_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,
+               .host_flags     = MV_COMMON_FLAGS,
+               .pio_mask       = 0x1f, /* pio0-4 */
+               .udma_mask      = 0x7f, /* udma0-6 */
+               .port_ops       = &mv5_ops,
+       },
+       {  /* chip_508x */
+               .sht            = &mv_sht,
+               .host_flags     = (MV_COMMON_FLAGS | MV_FLAG_DUAL_HC),
+               .pio_mask       = 0x1f, /* pio0-4 */
+               .udma_mask      = 0x7f, /* udma0-6 */
+               .port_ops       = &mv5_ops,
+       },
+       {  /* chip_5080 */
+               .sht            = &mv_sht,
+               .host_flags     = (MV_COMMON_FLAGS | MV_FLAG_DUAL_HC),
+               .pio_mask       = 0x1f, /* pio0-4 */
+               .udma_mask      = 0x7f, /* udma0-6 */
+               .port_ops       = &mv5_ops,
+       },
+       {  /* chip_604x */
+               .sht            = &mv_sht,
+               .host_flags     = (MV_COMMON_FLAGS | MV_6XXX_FLAGS),
+               .pio_mask       = 0x1f, /* pio0-4 */
+               .udma_mask      = 0x7f, /* udma0-6 */
+               .port_ops       = &mv6_ops,
+       },
+       {  /* chip_608x */
+               .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       = &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[] = {
+       {PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x5040), 0, 0, chip_504x},
+       {PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x5041), 0, 0, chip_504x},
+       {PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x5080), 0, 0, chip_5080},
+       {PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x5081), 0, 0, chip_508x},
+
+       {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},
+
+       {PCI_DEVICE(PCI_VENDOR_ID_ADAPTEC2, 0x0241), 0, 0, chip_604x},
+       {}                      /* terminate list */
+};
+
+static struct pci_driver mv_pci_driver = {
+       .name                   = DRV_NAME,
+       .id_table               = mv_pci_tbl,
+       .probe                  = mv_init_one,
+       .remove                 = ata_pci_remove_one,
+};
+
+static const struct mv_hw_ops mv5xxx_ops = {
+       .phy_errata             = mv5_phy_errata,
+       .enable_leds            = mv5_enable_leds,
+       .read_preamp            = mv5_read_preamp,
+       .reset_hc               = mv5_reset_hc,
+       .reset_flash            = mv5_reset_flash,
+       .reset_bus              = mv5_reset_bus,
+};
+
+static const struct mv_hw_ops mv6xxx_ops = {
+       .phy_errata             = mv6_phy_errata,
+       .enable_leds            = mv6_enable_leds,
+       .read_preamp            = mv6_read_preamp,
+       .reset_hc               = mv6_reset_hc,
+       .reset_flash            = mv6_reset_flash,
+       .reset_bus              = mv_reset_pci_bus,
+};
+
+/*
+ * module options
+ */
+static int msi;              /* Use PCI msi; either zero (off, default) or non-zero */
+
+
+/*
+ * Functions
+ */
+
+static inline void writelfl(unsigned long data, void __iomem *addr)
+{
+       writel(data, addr);
+       (void) readl(addr);     /* flush to avoid PCI posted write */
+}
+
+static inline void __iomem *mv_hc_base(void __iomem *base, unsigned int hc)
+{
+       return (base + MV_SATAHC0_REG_BASE + (hc * MV_SATAHC_REG_SZ));
+}
+
+static inline unsigned int mv_hc_from_port(unsigned int port)
+{
+       return port >> MV_PORT_HC_SHIFT;
+}
+
+static inline unsigned int mv_hardport_from_port(unsigned int port)
+{
+       return port & MV_PORT_MASK;
+}
+
+static inline void __iomem *mv_hc_base_from_port(void __iomem *base,
+                                                unsigned int port)
+{
+       return mv_hc_base(base, mv_hc_from_port(port));
+}
+
+static inline void __iomem *mv_port_base(void __iomem *base, unsigned int port)
+{
+       return  mv_hc_base_from_port(base, port) +
+               MV_SATAHC_ARBTR_REG_SZ +
+               (mv_hardport_from_port(port) * MV_PORT_REG_SZ);
+}
+
+static inline void __iomem *mv_ap_base(struct ata_port *ap)
+{
+       return mv_port_base(ap->host_set->mmio_base, ap->port_no);
+}
+
+static inline int mv_get_hc_count(unsigned long host_flags)
+{
+       return ((host_flags & MV_FLAG_DUAL_HC) ? 2 : 1);
+}
+
+static void mv_irq_clear(struct ata_port *ap)
+{
+}
+
+/**
+ *      mv_start_dma - Enable eDMA engine
+ *      @base: port base address
+ *      @pp: port private data
+ *
+ *      Verify the local cache of the eDMA state is accurate with a
+ *      WARN_ON.
+ *
+ *      LOCKING:
+ *      Inherited from caller.
+ */
+static void mv_start_dma(void __iomem *base, struct mv_port_priv *pp)
+{
+       if (!(MV_PP_FLAG_EDMA_EN & pp->pp_flags)) {
+               writelfl(EDMA_EN, base + EDMA_CMD_OFS);
+               pp->pp_flags |= MV_PP_FLAG_EDMA_EN;
+       }
+       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 a
+ *      WARN_ON.
+ *
+ *      LOCKING:
+ *      Inherited from caller.
+ */
+static void mv_stop_dma(struct ata_port *ap)
+{
+       void __iomem *port_mmio = mv_ap_base(ap);
+       struct mv_port_priv *pp = ap->private_data;
+       u32 reg;
+       int i;
+
+       if (MV_PP_FLAG_EDMA_EN & pp->pp_flags) {
+               /* Disable EDMA if active.   The disable bit auto clears.
+                */
+               writelfl(EDMA_DS, port_mmio + EDMA_CMD_OFS);
+               pp->pp_flags &= ~MV_PP_FLAG_EDMA_EN;
+       } else {
+               WARN_ON(EDMA_EN & readl(port_mmio + EDMA_CMD_OFS));
+       }
+
+       /* now properly wait for the eDMA to stop */
+       for (i = 1000; i > 0; i--) {
+               reg = readl(port_mmio + EDMA_CMD_OFS);
+               if (!(EDMA_EN & reg)) {
+                       break;
+               }
+               udelay(100);
+       }
+
+       if (EDMA_EN & reg) {
+               ata_port_printk(ap, KERN_ERR, "Unable to stop eDMA\n");
+               /* FIXME: Consider doing a reset here to recover */
+       }
+}
+
+#ifdef ATA_DEBUG
+static void mv_dump_mem(void __iomem *start, unsigned bytes)
+{
+       int b, w;
+       for (b = 0; b < bytes; ) {
+               DPRINTK("%p: ", start + b);
+               for (w = 0; b < bytes && w < 4; w++) {
+                       printk("%08x ",readl(start + b));
+                       b += sizeof(u32);
+               }
+               printk("\n");
+       }
+}
+#endif
+
+static void mv_dump_pci_cfg(struct pci_dev *pdev, unsigned bytes)
+{
+#ifdef ATA_DEBUG
+       int b, w;
+       u32 dw;
+       for (b = 0; b < bytes; ) {
+               DPRINTK("%02x: ", b);
+               for (w = 0; b < bytes && w < 4; w++) {
+                       (void) pci_read_config_dword(pdev,b,&dw);
+                       printk("%08x ",dw);
+                       b += sizeof(u32);
+               }
+               printk("\n");
+       }
+#endif
+}
+static void mv_dump_all_regs(void __iomem *mmio_base, int port,
+                            struct pci_dev *pdev)
+{
+#ifdef ATA_DEBUG
+       void __iomem *hc_base = mv_hc_base(mmio_base,
+                                          port >> MV_PORT_HC_SHIFT);
+       void __iomem *port_base;
+       int start_port, num_ports, p, start_hc, num_hcs, hc;
+
+       if (0 > port) {
+               start_hc = start_port = 0;
+               num_ports = 8;          /* shld be benign for 4 port devs */
+               num_hcs = 2;
+       } else {
+               start_hc = port >> MV_PORT_HC_SHIFT;
+               start_port = port;
+               num_ports = num_hcs = 1;
+       }
+       DPRINTK("All registers for port(s) %u-%u:\n", start_port,
+               num_ports > 1 ? num_ports - 1 : start_port);
+
+       if (NULL != pdev) {
+               DPRINTK("PCI config space regs:\n");
+               mv_dump_pci_cfg(pdev, 0x68);
+       }
+       DPRINTK("PCI regs:\n");
+       mv_dump_mem(mmio_base+0xc00, 0x3c);
+       mv_dump_mem(mmio_base+0xd00, 0x34);
+       mv_dump_mem(mmio_base+0xf00, 0x4);
+       mv_dump_mem(mmio_base+0x1d00, 0x6c);
+       for (hc = start_hc; hc < start_hc + num_hcs; hc++) {
+               hc_base = mv_hc_base(mmio_base, hc);
+               DPRINTK("HC regs (HC %i):\n", hc);
+               mv_dump_mem(hc_base, 0x1c);
+       }
+       for (p = start_port; p < start_port + num_ports; p++) {
+               port_base = mv_port_base(mmio_base, p);
+               DPRINTK("EDMA regs (port %i):\n",p);
+               mv_dump_mem(port_base, 0x54);
+               DPRINTK("SATA regs (port %i):\n",p);
+               mv_dump_mem(port_base+0x300, 0x60);
+       }
+#endif
+}
+
+static unsigned int mv_scr_offset(unsigned int sc_reg_in)
+{
+       unsigned int ofs;
+
+       switch (sc_reg_in) {
+       case SCR_STATUS:
+       case SCR_CONTROL:
+       case SCR_ERROR:
+               ofs = SATA_STATUS_OFS + (sc_reg_in * sizeof(u32));
+               break;
+       case SCR_ACTIVE:
+               ofs = SATA_ACTIVE_OFS;   /* active is not with the others */
+               break;
+       default:
+               ofs = 0xffffffffU;
+               break;
+       }
+       return ofs;
+}
+
+static u32 mv_scr_read(struct ata_port *ap, unsigned int sc_reg_in)
+{
+       unsigned int ofs = mv_scr_offset(sc_reg_in);
+
+       if (0xffffffffU != ofs) {
+               return readl(mv_ap_base(ap) + ofs);
+       } else {
+               return (u32) ofs;
+       }
+}
+
+static void mv_scr_write(struct ata_port *ap, unsigned int sc_reg_in, u32 val)
+{
+       unsigned int ofs = mv_scr_offset(sc_reg_in);
+
+       if (0xffffffffU != ofs) {
+               writelfl(val, mv_ap_base(ap) + ofs);
+       }
+}
+
+/**
+ *      mv_host_stop - Host specific cleanup/stop routine.
+ *      @host_set: host data structure
+ *
+ *      Disable ints, cleanup host memory, call general purpose
+ *      host_stop.
+ *
+ *      LOCKING:
+ *      Inherited from caller.
+ */
+static void mv_host_stop(struct ata_host_set *host_set)
+{
+       struct mv_host_priv *hpriv = host_set->private_data;
+       struct pci_dev *pdev = to_pci_dev(host_set->dev);
+
+       if (hpriv->hp_flags & MV_HP_FLAG_MSI) {
+               pci_disable_msi(pdev);
+       } else {
+               pci_intx(pdev, 0);
+       }
+       kfree(hpriv);
+       ata_host_stop(host_set);
+}
+
+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
+ *
+ *      Allocate and point to DMA memory, init port private memory,
+ *      zero indices.
+ *
+ *      LOCKING:
+ *      Inherited from caller.
+ */
+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;
+       dma_addr_t mem_dma;
+       int rc = -ENOMEM;
+
+       pp = kmalloc(sizeof(*pp), GFP_KERNEL);
+       if (!pp)
+               goto err_out;
+       memset(pp, 0, sizeof(*pp));
+
+       mem = dma_alloc_coherent(dev, MV_PORT_PRIV_DMA_SZ, &mem_dma,
+                                GFP_KERNEL);
+       if (!mem)
+               goto err_out_pp;
+       memset(mem, 0, MV_PORT_PRIV_DMA_SZ);
+
+       rc = ata_pad_alloc(ap, dev);
+       if (rc)
+               goto err_out_priv;
+
+       /* First item in chunk of DMA memory:
+        * 32-slot command request table (CRQB), 32 bytes each in size
+        */
+       pp->crqb = mem;
+       pp->crqb_dma = mem_dma;
+       mem += MV_CRQB_Q_SZ;
+       mem_dma += MV_CRQB_Q_SZ;
+
+       /* Second item:
+        * 32-slot command response table (CRPB), 8 bytes each in size
+        */
+       pp->crpb = mem;
+       pp->crpb_dma = mem_dma;
+       mem += MV_CRPB_Q_SZ;
+       mem_dma += MV_CRPB_Q_SZ;
+
+       /* Third item:
+        * Table of scatter-gather descriptors (ePRD), 16 bytes each
+        */
+       pp->sg_tbl = mem;
+       pp->sg_tbl_dma = mem_dma;
+
+       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);
+
+       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);
+
+       /* Don't turn on EDMA here...do it before DMA commands only.  Else
+        * we'll be unable to send non-data, PIO, etc due to restricted access
+        * to shadow regs.
+        */
+       ap->private_data = pp;
+       return 0;
+
+err_out_priv:
+       mv_priv_free(pp, dev);
+err_out_pp:
+       kfree(pp);
+err_out:
+       return rc;
+}
+
+/**
+ *      mv_port_stop - Port specific cleanup/stop routine.
+ *      @ap: ATA channel to manipulate
+ *
+ *      Stop DMA, cleanup port memory.
+ *
+ *      LOCKING:
+ *      This routine uses the host_set lock to protect the DMA stop.
+ */
+static void mv_port_stop(struct ata_port *ap)
+{
+       struct device *dev = ap->host_set->dev;
+       struct mv_port_priv *pp = ap->private_data;
+       unsigned long flags;
+
+       spin_lock_irqsave(&ap->host_set->lock, flags);
+       mv_stop_dma(ap);
+       spin_unlock_irqrestore(&ap->host_set->lock, flags);
+
+       ap->private_data = NULL;
+       ata_pad_free(ap, dev);
+       mv_priv_free(pp, dev);
+       kfree(pp);
+}
+
+/**
+ *      mv_fill_sg - Fill out the Marvell ePRD (scatter gather) entries
+ *      @qc: queued command whose SG list to source from
+ *
+ *      Populate the SG list and mark the last entry.
+ *
+ *      LOCKING:
+ *      Inherited from caller.
+ */
+static void mv_fill_sg(struct ata_queued_cmd *qc)
+{
+       struct mv_port_priv *pp = qc->ap->private_data;
+       unsigned int i = 0;
+       struct scatterlist *sg;
+
+       ata_for_each_sg(sg, qc) {
+               dma_addr_t addr;
+               u32 sg_len, len, offset;
+
+               addr = sg_dma_address(sg);
+               sg_len = sg_dma_len(sg);
+
+               while (sg_len) {
+                       offset = addr & MV_DMA_BOUNDARY;
+                       len = sg_len;
+                       if ((offset + sg_len) > 0x10000)
+                               len = 0x10000 - offset;
+
+                       pp->sg_tbl[i].addr = cpu_to_le32(addr & 0xffffffff);
+                       pp->sg_tbl[i].addr_hi = cpu_to_le32((addr >> 16) >> 16);
+                       pp->sg_tbl[i].flags_size = cpu_to_le32(len & 0xffff);
+
+                       sg_len -= len;
+                       addr += len;
+
+                       if (!sg_len && ata_sg_is_last(sg, qc))
+                               pp->sg_tbl[i].flags_size |= cpu_to_le32(EPRD_FLAG_END_OF_TBL);
+
+                       i++;
+               }
+       }
+}
+
+static inline unsigned mv_inc_q_index(unsigned index)
+{
+       return (index + 1) & MV_MAX_Q_DEPTH_MASK;
+}
+
+static inline void mv_crqb_pack_cmd(__le16 *cmdw, u8 data, u8 addr, unsigned last)
+{
+       u16 tmp = data | (addr << CRQB_CMD_ADDR_SHIFT) | CRQB_CMD_CS |
+               (last ? CRQB_CMD_LAST : 0);
+       *cmdw = cpu_to_le16(tmp);
+}
+
+/**
+ *      mv_qc_prep - 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(struct ata_queued_cmd *qc)
+{
+       struct ata_port *ap = qc->ap;
+       struct mv_port_priv *pp = ap->private_data;
+       __le16 *cw;
+       struct ata_taskfile *tf;
+       u16 flags = 0;
+       unsigned in_index;
+
+       if (ATA_PROT_DMA != qc->tf.protocol)
+               return;
+
+       /* Fill in 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;
+
+       /* get current queue index from hardware */
+       in_index = (readl(mv_ap_base(ap) + EDMA_REQ_Q_IN_PTR_OFS)
+                       >> EDMA_REQ_Q_PTR_SHIFT) & MV_MAX_Q_DEPTH_MASK;
+
+       pp->crqb[in_index].sg_addr =
+               cpu_to_le32(pp->sg_tbl_dma & 0xffffffff);
+       pp->crqb[in_index].sg_addr_hi =
+               cpu_to_le32((pp->sg_tbl_dma >> 16) >> 16);
+       pp->crqb[in_index].ctrl_flags = cpu_to_le16(flags);
+
+       cw = &pp->crqb[in_index].ata_cmd[0];
+       tf = &qc->tf;
+
+       /* Sadly, the CRQB cannot accomodate all registers--there are
+        * only 11 bytes...so we must pick and choose required
+        * registers based on the command.  So, we drop feature and
+        * hob_feature for [RW] DMA commands, but they are needed for
+        * NCQ.  NCQ will drop hob_nsect.
+        */
+       switch (tf->command) {
+       case ATA_CMD_READ:
+       case ATA_CMD_READ_EXT:
+       case ATA_CMD_WRITE:
+       case ATA_CMD_WRITE_EXT:
+       case ATA_CMD_WRITE_FUA_EXT:
+               mv_crqb_pack_cmd(cw++, tf->hob_nsect, ATA_REG_NSECT, 0);
+               break;
+#ifdef LIBATA_NCQ              /* FIXME: remove this line when NCQ added */
+       case ATA_CMD_FPDMA_READ:
+       case ATA_CMD_FPDMA_WRITE:
+               mv_crqb_pack_cmd(cw++, tf->hob_feature, ATA_REG_FEATURE, 0);
+               mv_crqb_pack_cmd(cw++, tf->feature, ATA_REG_FEATURE, 0);
+               break;
+#endif                         /* FIXME: remove this line when NCQ added */
+       default:
+               /* The only other commands EDMA supports in non-queued and
+                * non-NCQ mode are: [RW] STREAM DMA and W DMA FUA EXT, none
+                * of which are defined/used by Linux.  If we get here, this
+                * driver needs work.
+                *
+                * FIXME: modify libata to give qc_prep a return value and
+                * return error here.
+                */
+               BUG_ON(tf->command);
+               break;
+       }
+       mv_crqb_pack_cmd(cw++, tf->nsect, ATA_REG_NSECT, 0);
+       mv_crqb_pack_cmd(cw++, tf->hob_lbal, ATA_REG_LBAL, 0);
+       mv_crqb_pack_cmd(cw++, tf->lbal, ATA_REG_LBAL, 0);
+       mv_crqb_pack_cmd(cw++, tf->hob_lbam, ATA_REG_LBAM, 0);
+       mv_crqb_pack_cmd(cw++, tf->lbam, ATA_REG_LBAM, 0);
+       mv_crqb_pack_cmd(cw++, tf->hob_lbah, ATA_REG_LBAH, 0);
+       mv_crqb_pack_cmd(cw++, tf->lbah, ATA_REG_LBAH, 0);
+       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))
+               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;
+       unsigned in_index;
+       u32 flags = 0;
+
+       if (ATA_PROT_DMA != qc->tf.protocol)
+               return;
+
+       /* 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;
+
+       /* get current queue index from hardware */
+       in_index = (readl(mv_ap_base(ap) + EDMA_REQ_Q_IN_PTR_OFS)
+                       >> EDMA_REQ_Q_PTR_SHIFT) & MV_MAX_Q_DEPTH_MASK;
+
+       crqb = (struct mv_crqb_iie *) &pp->crqb[in_index];
+       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);
+}
+
+/**
+ *      mv_qc_issue - Initiate a command to the host
+ *      @qc: queued command to start
+ *
+ *      This routine simply redirects to the general purpose routine
+ *      if command is not DMA.  Else, it sanity checks our local
+ *      caches of the request producer/consumer indices then enables
+ *      DMA and bumps the request producer index.
+ *
+ *      LOCKING:
+ *      Inherited from caller.
+ */
+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;
+       unsigned in_index;
+       u32 in_ptr;
+
+       if (ATA_PROT_DMA != qc->tf.protocol) {
+               /* We're about to send a non-EDMA capable command to the
+                * port.  Turn off EDMA so there won't be problems accessing
+                * shadow block, etc registers.
+                */
+               mv_stop_dma(qc->ap);
+               return ata_qc_issue_prot(qc);
+       }
+
+       in_ptr   = readl(port_mmio + EDMA_REQ_Q_IN_PTR_OFS);
+       in_index = (in_ptr >> EDMA_REQ_Q_PTR_SHIFT) & MV_MAX_Q_DEPTH_MASK;
+
+       /* until we do queuing, the queue should be empty at this point */
+       WARN_ON(in_index != ((readl(port_mmio + EDMA_REQ_Q_OUT_PTR_OFS)
+               >> EDMA_REQ_Q_PTR_SHIFT) & MV_MAX_Q_DEPTH_MASK));
+
+       in_index = mv_inc_q_index(in_index);    /* now incr producer index */
+
+       mv_start_dma(port_mmio, pp);
+
+       /* and write the request in pointer to kick the EDMA to life */
+       in_ptr &= EDMA_REQ_Q_BASE_LO_MASK;
+       in_ptr |= in_index << EDMA_REQ_Q_PTR_SHIFT;
+       writelfl(in_ptr, port_mmio + EDMA_REQ_Q_IN_PTR_OFS);
+
+       return 0;
+}
+
+/**
+ *      mv_get_crpb_status - get status from most recently completed cmd
+ *      @ap: ATA channel to manipulate
+ *
+ *      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 check indices
+ *      are good, grab status, and bump the response consumer index to
+ *      prove that we're up to date.
+ *
+ *      LOCKING:
+ *      Inherited from caller.
+ */
+static u8 mv_get_crpb_status(struct ata_port *ap)
+{
+       void __iomem *port_mmio = mv_ap_base(ap);
+       struct mv_port_priv *pp = ap->private_data;
+       unsigned out_index;
+       u32 out_ptr;
+       u8 ata_status;
+
+       out_ptr   = readl(port_mmio + EDMA_RSP_Q_OUT_PTR_OFS);
+       out_index = (out_ptr >> EDMA_RSP_Q_PTR_SHIFT) & MV_MAX_Q_DEPTH_MASK;
+
+       ata_status = le16_to_cpu(pp->crpb[out_index].flags)
+                                       >> CRPB_FLAG_STATUS_SHIFT;
+
+       /* increment our consumer index... */
+       out_index = mv_inc_q_index(out_index);
+
+       /* and, until we do NCQ, there should only be 1 CRPB waiting */
+       WARN_ON(out_index != ((readl(port_mmio + EDMA_RSP_Q_IN_PTR_OFS)
+               >> EDMA_RSP_Q_PTR_SHIFT) & MV_MAX_Q_DEPTH_MASK));
+
+       /* write out our inc'd consumer index so EDMA knows we're caught up */
+       out_ptr &= EDMA_RSP_Q_BASE_LO_MASK;
+       out_ptr |= out_index << EDMA_RSP_Q_PTR_SHIFT;
+       writelfl(out_ptr, port_mmio + EDMA_RSP_Q_OUT_PTR_OFS);
+
+       /* Return ATA status register for completed CRPB */
+       return ata_status;
+}
+
+/**
+ *      mv_err_intr - Handle error interrupts on the port
+ *      @ap: ATA channel to manipulate
+ *      @reset_allowed: bool: 0 == don't trigger from reset here
+ *
+ *      In most cases, just clear the interrupt and move on.  However,
+ *      some cases require an eDMA reset, which is done right before
+ *      the COMRESET in mv_phy_reset().  The SERR case requires a
+ *      clear of pending errors in the SATA SERROR register.  Finally,
+ *      if the port disabled DMA, update our cached copy to match.
+ *
+ *      LOCKING:
+ *      Inherited from caller.
+ */
+static void mv_err_intr(struct ata_port *ap, int reset_allowed)
+{
+       void __iomem *port_mmio = mv_ap_base(ap);
+       u32 edma_err_cause, serr = 0;
+
+       edma_err_cause = readl(port_mmio + EDMA_ERR_IRQ_CAUSE_OFS);
+
+       if (EDMA_ERR_SERR & edma_err_cause) {
+               sata_scr_read(ap, SCR_ERROR, &serr);
+               sata_scr_write_flush(ap, SCR_ERROR, serr);
+       }
+       if (EDMA_ERR_SELF_DIS & edma_err_cause) {
+               struct mv_port_priv *pp = ap->private_data;
+               pp->pp_flags &= ~MV_PP_FLAG_EDMA_EN;
+       }
+       DPRINTK(KERN_ERR "ata%u: port error; EDMA err cause: 0x%08x "
+               "SERR: 0x%08x\n", ap->id, edma_err_cause, serr);
+
+       /* Clear EDMA now that SERR cleanup done */
+       writelfl(0, port_mmio + EDMA_ERR_IRQ_CAUSE_OFS);
+
+       /* check for fatal here and recover if needed */
+       if (reset_allowed && (EDMA_ERR_FATAL & edma_err_cause))
+               mv_stop_and_reset(ap);
+}
+
+/**
+ *      mv_host_intr - Handle all interrupts on the given host controller
+ *      @host_set: host specific structure
+ *      @relevant: port error bits relevant to this host controller
+ *      @hc: which host controller we're to look at
+ *
+ *      Read then write clear the HC interrupt status then walk each
+ *      port connected to the HC and see if it needs servicing.  Port
+ *      success ints are reported in the HC interrupt status reg, the
+ *      port error ints are reported in the higher level main
+ *      interrupt status register and thus are passed in via the
+ *      'relevant' argument.
+ *
+ *      LOCKING:
+ *      Inherited from caller.
+ */
+static void mv_host_intr(struct ata_host_set *host_set, u32 relevant,
+                        unsigned int hc)
+{
+       void __iomem *mmio = host_set->mmio_base;
+       void __iomem *hc_mmio = mv_hc_base(mmio, hc);
+       struct ata_queued_cmd *qc;
+       u32 hc_irq_cause;
+       int shift, port, port0, hard_port, handled;
+       unsigned int err_mask;
+
+       if (hc == 0) {
+               port0 = 0;
+       } else {
+               port0 = MV_PORTS_PER_HC;
+       }
+
+       /* we'll need the HC success int register in most cases */
+       hc_irq_cause = readl(hc_mmio + HC_IRQ_CAUSE_OFS);
+       if (hc_irq_cause) {
+               writelfl(~hc_irq_cause, hc_mmio + HC_IRQ_CAUSE_OFS);
+       }
+
+       VPRINTK("ENTER, hc%u relevant=0x%08x HC IRQ cause=0x%08x\n",
+               hc,relevant,hc_irq_cause);
+
+       for (port = port0; port < port0 + MV_PORTS_PER_HC; port++) {
+               u8 ata_status = 0;
+               struct ata_port *ap = host_set->ports[port];
+               struct mv_port_priv *pp = ap->private_data;
+
+               hard_port = mv_hardport_from_port(port); /* range 0..3 */
+               handled = 0;    /* ensure ata_status is set if handled++ */
+
+               /* Note that DEV_IRQ might happen spuriously during EDMA,
+                * and should be ignored in such cases.
+                * The cause of this is still under investigation.
+                */
+               if (pp->pp_flags & MV_PP_FLAG_EDMA_EN) {
+                       /* EDMA: check for response queue interrupt */
+                       if ((CRPB_DMA_DONE << hard_port) & hc_irq_cause) {
+                               ata_status = mv_get_crpb_status(ap);
+                               handled = 1;
+                       }
+               } else {
+                       /* PIO: check for device (drive) interrupt */
+                       if ((DEV_IRQ << hard_port) & hc_irq_cause) {
+                               ata_status = readb((void __iomem *)
+                                          ap->ioaddr.status_addr);
+                               handled = 1;
+                               /* ignore spurious intr if drive still BUSY */
+                               if (ata_status & ATA_BUSY) {
+                                       ata_status = 0;
+                                       handled = 0;
+                               }
+                       }
+               }
+
+               if (ap && (ap->flags & ATA_FLAG_DISABLED))
+                       continue;
+
+               err_mask = ac_err_mask(ata_status);
+
+               shift = port << 1;              /* (port * 2) */
+               if (port >= MV_PORTS_PER_HC) {
+                       shift++;        /* skip bit 8 in the HC Main IRQ reg */
+               }
+               if ((PORT0_ERR << shift) & relevant) {
+                       mv_err_intr(ap, 1);
+                       err_mask |= AC_ERR_OTHER;
+                       handled = 1;
+               }
+
+               if (handled) {
+                       qc = ata_qc_from_tag(ap, ap->active_tag);
+                       if (qc && (qc->flags & ATA_QCFLAG_ACTIVE)) {
+                               VPRINTK("port %u IRQ found for qc, "
+                                       "ata_status 0x%x\n", port,ata_status);
+                               /* mark qc status appropriately */
+                               if (!(qc->tf.flags & ATA_TFLAG_POLLING)) {
+                                       qc->err_mask |= err_mask;
+                                       ata_qc_complete(qc);
+                               }
+                       }
+               }
+       }
+       VPRINTK("EXIT\n");
+}
+
+/**
+ *      mv_interrupt -
+ *      @irq: unused
+ *      @dev_instance: private data; in this case the host structure
+ *      @regs: unused
+ *
+ *      Read the read only register to determine if any host
+ *      controllers have pending interrupts.  If so, call lower level
+ *      routine to handle.  Also check for PCI errors which are only
+ *      reported here.
+ *
+ *      LOCKING:
+ *      This routine holds the host_set lock while processing pending
+ *      interrupts.
+ */
+static irqreturn_t mv_interrupt(int irq, void *dev_instance,
+                               struct pt_regs *regs)
+{
+       struct ata_host_set *host_set = dev_instance;
+       unsigned int hc, handled = 0, n_hcs;
+       void __iomem *mmio = host_set->mmio_base;
+       struct mv_host_priv *hpriv;
+       u32 irq_stat;
+
+       irq_stat = readl(mmio + HC_MAIN_IRQ_CAUSE_OFS);
+
+       /* check the cases where we either have nothing pending or have read
+        * a bogus register value which can indicate HW removal or PCI fault
+        */
+       if (!irq_stat || (0xffffffffU == irq_stat)) {
+               return IRQ_NONE;
+       }
+
+       n_hcs = mv_get_hc_count(host_set->ports[0]->flags);
+       spin_lock(&host_set->lock);
+
+       for (hc = 0; hc < n_hcs; hc++) {
+               u32 relevant = irq_stat & (HC0_IRQ_PEND << (hc * HC_SHIFT));
+               if (relevant) {
+                       mv_host_intr(host_set, relevant, hc);
+                       handled++;
+               }
+       }
+
+       hpriv = host_set->private_data;
+       if (IS_60XX(hpriv)) {
+               /* deal with the interrupt coalescing bits */
+               if (irq_stat & (TRAN_LO_DONE | TRAN_HI_DONE | PORTS_0_7_COAL_DONE)) {
+                       writelfl(0, mmio + MV_IRQ_COAL_CAUSE_LO);
+                       writelfl(0, mmio + MV_IRQ_COAL_CAUSE_HI);
+                       writelfl(0, mmio + MV_IRQ_COAL_CAUSE);
+               }
+       }
+
+       if (PCI_ERR & irq_stat) {
+               printk(KERN_ERR DRV_NAME ": PCI ERROR; PCI IRQ cause=0x%08x\n",
+                      readl(mmio + PCI_IRQ_CAUSE_OFS));
+
+               DPRINTK("All regs @ PCI error\n");
+               mv_dump_all_regs(mmio, -1, to_pci_dev(host_set->dev));
+
+               writelfl(0, mmio + PCI_IRQ_CAUSE_OFS);
+               handled++;
+       }
+       spin_unlock(&host_set->lock);
+
+       return IRQ_RETVAL(handled);
+}
+
+static void __iomem *mv5_phy_base(void __iomem *mmio, unsigned int port)
+{
+       void __iomem *hc_mmio = mv_hc_base_from_port(mmio, port);
+       unsigned long ofs = (mv_hardport_from_port(port) + 1) * 0x100UL;
+
+       return hc_mmio + ofs;
+}
+
+static unsigned int mv5_scr_offset(unsigned int sc_reg_in)
+{
+       unsigned int ofs;
+
+       switch (sc_reg_in) {
+       case SCR_STATUS:
+       case SCR_ERROR:
+       case SCR_CONTROL:
+               ofs = sc_reg_in * sizeof(u32);
+               break;
+       default:
+               ofs = 0xffffffffU;
+               break;
+       }
+       return ofs;
+}
+
+static u32 mv5_scr_read(struct ata_port *ap, unsigned int sc_reg_in)
+{
+       void __iomem *mmio = mv5_phy_base(ap->host_set->mmio_base, ap->port_no);
+       unsigned int ofs = mv5_scr_offset(sc_reg_in);
+
+       if (ofs != 0xffffffffU)
+               return readl(mmio + ofs);
+       else
+               return (u32) ofs;
+}
+
+static void mv5_scr_write(struct ata_port *ap, unsigned int sc_reg_in, u32 val)
+{
+       void __iomem *mmio = mv5_phy_base(ap->host_set->mmio_base, ap->port_no);
+       unsigned int ofs = mv5_scr_offset(sc_reg_in);
+
+       if (ofs != 0xffffffffU)
+               writelfl(val, mmio + ofs);
+}
+
+static void mv5_reset_bus(struct pci_dev *pdev, void __iomem *mmio)
+{
+       u8 rev_id;
+       int early_5080;
+
+       pci_read_config_byte(pdev, PCI_REVISION_ID, &rev_id);
+
+       early_5080 = (pdev->device == 0x5080) && (rev_id == 0);
+
+       if (!early_5080) {
+               u32 tmp = readl(mmio + MV_PCI_EXP_ROM_BAR_CTL);
+               tmp |= (1 << 0);
+               writel(tmp, mmio + MV_PCI_EXP_ROM_BAR_CTL);
+       }
+
+       mv_reset_pci_bus(pdev, mmio);
+}
+
+static void mv5_reset_flash(struct mv_host_priv *hpriv, void __iomem *mmio)
+{
+       writel(0x0fcfffff, mmio + MV_FLASH_CTL);
+}
+
+static void mv5_read_preamp(struct mv_host_priv *hpriv, int idx,
+                          void __iomem *mmio)
+{
+       void __iomem *phy_mmio = mv5_phy_base(mmio, idx);
+       u32 tmp;
+
+       tmp = readl(phy_mmio + MV5_PHY_MODE);
+
+       hpriv->signal[idx].pre = tmp & 0x1800;  /* bits 12:11 */
+       hpriv->signal[idx].amps = tmp & 0xe0;   /* bits 7:5 */
+}
+
+static void mv5_enable_leds(struct mv_host_priv *hpriv, void __iomem *mmio)
+{
+       u32 tmp;
+
+       writel(0, mmio + MV_GPIO_PORT_CTL);
+
+       /* FIXME: handle MV_HP_ERRATA_50XXB2 errata */
+
+       tmp = readl(mmio + MV_PCI_EXP_ROM_BAR_CTL);
+       tmp |= ~(1 << 0);
+       writel(tmp, mmio + MV_PCI_EXP_ROM_BAR_CTL);
+}
+
+static void mv5_phy_errata(struct mv_host_priv *hpriv, void __iomem *mmio,
+                          unsigned int port)
+{
+       void __iomem *phy_mmio = mv5_phy_base(mmio, port);
+       const u32 mask = (1<<12) | (1<<11) | (1<<7) | (1<<6) | (1<<5);
+       u32 tmp;
+       int fix_apm_sq = (hpriv->hp_flags & MV_HP_ERRATA_50XXB0);
+
+       if (fix_apm_sq) {
+               tmp = readl(phy_mmio + MV5_LT_MODE);
+               tmp |= (1 << 19);
+               writel(tmp, phy_mmio + MV5_LT_MODE);
+
+               tmp = readl(phy_mmio + MV5_PHY_CTL);
+               tmp &= ~0x3;
+               tmp |= 0x1;
+               writel(tmp, phy_mmio + MV5_PHY_CTL);
+       }
+
+       tmp = readl(phy_mmio + MV5_PHY_MODE);
+       tmp &= ~mask;
+       tmp |= hpriv->signal[port].pre;
+       tmp |= hpriv->signal[port].amps;
+       writel(tmp, phy_mmio + MV5_PHY_MODE);
+}
+
+
+#undef ZERO
+#define ZERO(reg) writel(0, port_mmio + (reg))
+static void mv5_reset_hc_port(struct mv_host_priv *hpriv, void __iomem *mmio,
+                            unsigned int port)
+{
+       void __iomem *port_mmio = mv_port_base(mmio, port);
+
+       writelfl(EDMA_DS, port_mmio + EDMA_CMD_OFS);
+
+       mv_channel_reset(hpriv, mmio, port);
+
+       ZERO(0x028);    /* command */
+       writel(0x11f, port_mmio + EDMA_CFG_OFS);
+       ZERO(0x004);    /* timer */
+       ZERO(0x008);    /* irq err cause */
+       ZERO(0x00c);    /* irq err mask */
+       ZERO(0x010);    /* rq bah */
+       ZERO(0x014);    /* rq inp */
+       ZERO(0x018);    /* rq outp */
+       ZERO(0x01c);    /* respq bah */
+       ZERO(0x024);    /* respq outp */
+       ZERO(0x020);    /* respq inp */
+       ZERO(0x02c);    /* test control */
+       writel(0xbc, port_mmio + EDMA_IORDY_TMOUT);
+}
+#undef ZERO
+
+#define ZERO(reg) writel(0, hc_mmio + (reg))
+static void mv5_reset_one_hc(struct mv_host_priv *hpriv, void __iomem *mmio,
+                       unsigned int hc)
+{
+       void __iomem *hc_mmio = mv_hc_base(mmio, hc);
+       u32 tmp;
+
+       ZERO(0x00c);
+       ZERO(0x010);
+       ZERO(0x014);
+       ZERO(0x018);
+
+       tmp = readl(hc_mmio + 0x20);
+       tmp &= 0x1c1c1c1c;
+       tmp |= 0x03030303;
+       writel(tmp, hc_mmio + 0x20);
+}
+#undef ZERO
+
+static int mv5_reset_hc(struct mv_host_priv *hpriv, void __iomem *mmio,
+                       unsigned int n_hc)
+{
+       unsigned int hc, port;
+
+       for (hc = 0; hc < n_hc; hc++) {
+               for (port = 0; port < MV_PORTS_PER_HC; port++)
+                       mv5_reset_hc_port(hpriv, mmio,
+                                         (hc * MV_PORTS_PER_HC) + port);
+
+               mv5_reset_one_hc(hpriv, mmio, hc);
+       }
+
+       return 0;
+}
+
+#undef ZERO
+#define ZERO(reg) writel(0, mmio + (reg))
+static void mv_reset_pci_bus(struct pci_dev *pdev, void __iomem *mmio)
+{
+       u32 tmp;
+
+       tmp = readl(mmio + MV_PCI_MODE);
+       tmp &= 0xff00ffff;
+       writel(tmp, mmio + MV_PCI_MODE);
+
+       ZERO(MV_PCI_DISC_TIMER);
+       ZERO(MV_PCI_MSI_TRIGGER);
+       writel(0x000100ff, mmio + MV_PCI_XBAR_TMOUT);
+       ZERO(HC_MAIN_IRQ_MASK_OFS);
+       ZERO(MV_PCI_SERR_MASK);
+       ZERO(PCI_IRQ_CAUSE_OFS);
+       ZERO(PCI_IRQ_MASK_OFS);
+       ZERO(MV_PCI_ERR_LOW_ADDRESS);
+       ZERO(MV_PCI_ERR_HIGH_ADDRESS);
+       ZERO(MV_PCI_ERR_ATTRIBUTE);
+       ZERO(MV_PCI_ERR_COMMAND);
+}
+#undef ZERO
+
+static void mv6_reset_flash(struct mv_host_priv *hpriv, void __iomem *mmio)
+{
+       u32 tmp;
+
+       mv5_reset_flash(hpriv, mmio);
+
+       tmp = readl(mmio + MV_GPIO_PORT_CTL);
+       tmp &= 0x3;
+       tmp |= (1 << 5) | (1 << 6);
+       writel(tmp, mmio + MV_GPIO_PORT_CTL);
+}
+
+/**
+ *      mv6_reset_hc - Perform the 6xxx global soft reset
+ *      @mmio: base address of the HBA
+ *
+ *      This routine only applies to 6xxx parts.
+ *
+ *      LOCKING:
+ *      Inherited from caller.
+ */
+static int mv6_reset_hc(struct mv_host_priv *hpriv, void __iomem *mmio,
+                       unsigned int n_hc)
+{
+       void __iomem *reg = mmio + PCI_MAIN_CMD_STS_OFS;
+       int i, rc = 0;
+       u32 t;
+
+       /* Following procedure defined in PCI "main command and status
+        * register" table.
+        */
+       t = readl(reg);
+       writel(t | STOP_PCI_MASTER, reg);
+
+       for (i = 0; i < 1000; i++) {
+               udelay(1);
+               t = readl(reg);
+               if (PCI_MASTER_EMPTY & t) {
+                       break;
+               }
+       }
+       if (!(PCI_MASTER_EMPTY & t)) {
+               printk(KERN_ERR DRV_NAME ": PCI master won't flush\n");
+               rc = 1;
+               goto done;
+       }
+
+       /* set reset */
+       i = 5;
+       do {
+               writel(t | GLOB_SFT_RST, reg);
+               t = readl(reg);
+               udelay(1);
+       } while (!(GLOB_SFT_RST & t) && (i-- > 0));
+
+       if (!(GLOB_SFT_RST & t)) {
+               printk(KERN_ERR DRV_NAME ": can't set global reset\n");
+               rc = 1;
+               goto done;
+       }
+
+       /* clear reset and *reenable the PCI master* (not mentioned in spec) */
+       i = 5;
+       do {
+               writel(t & ~(GLOB_SFT_RST | STOP_PCI_MASTER), reg);
+               t = readl(reg);
+               udelay(1);
+       } while ((GLOB_SFT_RST & t) && (i-- > 0));
+
+       if (GLOB_SFT_RST & t) {
+               printk(KERN_ERR DRV_NAME ": can't clear global reset\n");
+               rc = 1;
+       }
+done:
+       return rc;
+}
+
+static void mv6_read_preamp(struct mv_host_priv *hpriv, int idx,
+                          void __iomem *mmio)
+{
+       void __iomem *port_mmio;
+       u32 tmp;
+
+       tmp = readl(mmio + MV_RESET_CFG);
+       if ((tmp & (1 << 0)) == 0) {
+               hpriv->signal[idx].amps = 0x7 << 8;
+               hpriv->signal[idx].pre = 0x1 << 5;
+               return;
+       }
+
+       port_mmio = mv_port_base(mmio, idx);
+       tmp = readl(port_mmio + PHY_MODE2);
+
+       hpriv->signal[idx].amps = tmp & 0x700;  /* bits 10:8 */
+       hpriv->signal[idx].pre = tmp & 0xe0;    /* bits 7:5 */
+}
+
+static void mv6_enable_leds(struct mv_host_priv *hpriv, void __iomem *mmio)
+{
+       writel(0x00000060, mmio + MV_GPIO_PORT_CTL);
+}
+
+static void mv6_phy_errata(struct mv_host_priv *hpriv, void __iomem *mmio,
+                          unsigned int port)
+{
+       void __iomem *port_mmio = mv_port_base(mmio, port);
+
+       u32 hp_flags = hpriv->hp_flags;
+       int fix_phy_mode2 =
+               hp_flags & (MV_HP_ERRATA_60X1B2 | MV_HP_ERRATA_60X1C0);
+       int fix_phy_mode4 =
+               hp_flags & (MV_HP_ERRATA_60X1B2 | MV_HP_ERRATA_60X1C0);
+       u32 m2, tmp;
+
+       if (fix_phy_mode2) {
+               m2 = readl(port_mmio + PHY_MODE2);
+               m2 &= ~(1 << 16);
+               m2 |= (1 << 31);
+               writel(m2, port_mmio + PHY_MODE2);
+
+               udelay(200);
+
+               m2 = readl(port_mmio + PHY_MODE2);
+               m2 &= ~((1 << 16) | (1 << 31));
+               writel(m2, port_mmio + PHY_MODE2);
+
+               udelay(200);
+       }
+
+       /* who knows what this magic does */
+       tmp = readl(port_mmio + PHY_MODE3);
+       tmp &= ~0x7F800000;
+       tmp |= 0x2A800000;
+       writel(tmp, port_mmio + PHY_MODE3);
+
+       if (fix_phy_mode4) {
+               u32 m4;
+
+               m4 = readl(port_mmio + PHY_MODE4);
+
+               if (hp_flags & MV_HP_ERRATA_60X1B2)
+                       tmp = readl(port_mmio + 0x310);
+
+               m4 = (m4 & ~(1 << 1)) | (1 << 0);
+
+               writel(m4, port_mmio + PHY_MODE4);
+
+               if (hp_flags & MV_HP_ERRATA_60X1B2)
+                       writel(tmp, port_mmio + 0x310);
+       }
+
+       /* Revert values of pre-emphasis and signal amps to the saved ones */
+       m2 = readl(port_mmio + PHY_MODE2);
+
+       m2 &= ~MV_M2_PREAMP_MASK;
+       m2 |= hpriv->signal[port].amps;
+       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);
+}
+
+static void mv_channel_reset(struct mv_host_priv *hpriv, void __iomem *mmio,
+                            unsigned int port_no)
+{
+       void __iomem *port_mmio = mv_port_base(mmio, port_no);
+
+       writelfl(ATA_RST, port_mmio + EDMA_CMD_OFS);
+
+       if (IS_60XX(hpriv)) {
+               u32 ifctl = readl(port_mmio + SATA_INTERFACE_CTL);
+               ifctl |= (1 << 7);              /* enable gen2i speed */
+               ifctl = (ifctl & 0xfff) | 0x9b1000; /* from chip spec */
+               writelfl(ifctl, port_mmio + SATA_INTERFACE_CTL);
+       }
+
+       udelay(25);             /* allow reset propagation */
+
+       /* Spec never mentions clearing the bit.  Marvell's driver does
+        * clear the bit, however.
+        */
+       writelfl(0, port_mmio + EDMA_CMD_OFS);
+
+       hpriv->ops->phy_errata(hpriv, mmio, port_no);
+
+       if (IS_50XX(hpriv))
+               mdelay(1);
+}
+
+static void mv_stop_and_reset(struct ata_port *ap)
+{
+       struct mv_host_priv *hpriv = ap->host_set->private_data;
+       void __iomem *mmio = ap->host_set->mmio_base;
+
+       mv_stop_dma(ap);
+
+       mv_channel_reset(hpriv, mmio, ap->port_no);
+
+       __mv_phy_reset(ap, 0);
+}
+
+static inline void __msleep(unsigned int msec, int can_sleep)
+{
+       if (can_sleep)
+               msleep(msec);
+       else
+               mdelay(msec);
+}
+
+/**
+ *      __mv_phy_reset - Perform eDMA reset followed by COMRESET
+ *      @ap: ATA channel to manipulate
+ *
+ *      Part of this is taken from __sata_phy_reset and modified to
+ *      not sleep since this routine gets called from interrupt level.
+ *
+ *      LOCKING:
+ *      Inherited from caller.  This is coded to safe to call at
+ *      interrupt level, i.e. it does not sleep.
+ */
+static void __mv_phy_reset(struct ata_port *ap, int can_sleep)
+{
+       struct mv_port_priv *pp = ap->private_data;
+       struct mv_host_priv *hpriv = ap->host_set->private_data;
+       void __iomem *port_mmio = mv_ap_base(ap);
+       struct ata_taskfile tf;
+       struct ata_device *dev = &ap->device[0];
+       unsigned long timeout;
+       int retry = 5;
+       u32 sstatus;
+
+       VPRINTK("ENTER, port %u, mmio 0x%p\n", ap->port_no, port_mmio);
+
+       DPRINTK("S-regs after ATA_RST: SStat 0x%08x SErr 0x%08x "
+               "SCtrl 0x%08x\n", mv_scr_read(ap, SCR_STATUS),
+               mv_scr_read(ap, SCR_ERROR), mv_scr_read(ap, SCR_CONTROL));
+
+       /* Issue COMRESET via SControl */
+comreset_retry:
+       sata_scr_write_flush(ap, SCR_CONTROL, 0x301);
+       __msleep(1, can_sleep);
+
+       sata_scr_write_flush(ap, SCR_CONTROL, 0x300);
+       __msleep(20, can_sleep);
+
+       timeout = jiffies + msecs_to_jiffies(200);
+       do {
+               sata_scr_read(ap, SCR_STATUS, &sstatus);
+               sstatus &= 0x3;
+               if ((sstatus == 3) || (sstatus == 0))
+                       break;
+
+               __msleep(1, can_sleep);
+       } while (time_before(jiffies, timeout));
+
+       /* work around errata */
+       if (IS_60XX(hpriv) &&
+           (sstatus != 0x0) && (sstatus != 0x113) && (sstatus != 0x123) &&
+           (retry-- > 0))
+               goto comreset_retry;
+
+       DPRINTK("S-regs after PHY wake: SStat 0x%08x SErr 0x%08x "
+               "SCtrl 0x%08x\n", mv_scr_read(ap, SCR_STATUS),
+               mv_scr_read(ap, SCR_ERROR), mv_scr_read(ap, SCR_CONTROL));
+
+       if (ata_port_online(ap)) {
+               ata_port_probe(ap);
+       } else {
+               sata_scr_read(ap, SCR_STATUS, &sstatus);
+               ata_port_printk(ap, KERN_INFO,
+                               "no device found (phy stat %08x)\n", sstatus);
+               ata_port_disable(ap);
+               return;
+       }
+       ap->cbl = ATA_CBL_SATA;
+
+       /* even after SStatus reflects that device is ready,
+        * it seems to take a while for link to be fully
+        * established (and thus Status no longer 0x80/0x7F),
+        * so we poll a bit for that, here.
+        */
+       retry = 20;
+       while (1) {
+               u8 drv_stat = ata_check_status(ap);
+               if ((drv_stat != 0x80) && (drv_stat != 0x7f))
+                       break;
+               __msleep(500, can_sleep);
+               if (retry-- <= 0)
+                       break;
+       }
+
+       tf.lbah = readb((void __iomem *) ap->ioaddr.lbah_addr);
+       tf.lbam = readb((void __iomem *) ap->ioaddr.lbam_addr);
+       tf.lbal = readb((void __iomem *) ap->ioaddr.lbal_addr);
+       tf.nsect = readb((void __iomem *) ap->ioaddr.nsect_addr);
+
+       dev->class = ata_dev_classify(&tf);
+       if (!ata_dev_enabled(dev)) {
+               VPRINTK("Port disabled post-sig: No device present.\n");
+               ata_port_disable(ap);
+       }
+
+       writelfl(0, port_mmio + EDMA_ERR_IRQ_CAUSE_OFS);
+
+       pp->pp_flags &= ~MV_PP_FLAG_EDMA_EN;
+
+       VPRINTK("EXIT\n");
+}
+
+static void mv_phy_reset(struct ata_port *ap)
+{
+       __mv_phy_reset(ap, 1);
+}
+
+/**
+ *      mv_eng_timeout - Routine called by libata when SCSI times out I/O
+ *      @ap: ATA channel to manipulate
+ *
+ *      Intent is to clear all pending error conditions, reset the
+ *      chip/bus, fail the command, and move on.
+ *
+ *      LOCKING:
+ *      This routine holds the host_set lock while failing the command.
+ */
+static void mv_eng_timeout(struct ata_port *ap)
+{
+       struct ata_queued_cmd *qc;
+       unsigned long flags;
+
+       ata_port_printk(ap, KERN_ERR, "Entering mv_eng_timeout\n");
+       DPRINTK("All regs @ start of eng_timeout\n");
+       mv_dump_all_regs(ap->host_set->mmio_base, ap->port_no,
+                        to_pci_dev(ap->host_set->dev));
+
+       qc = ata_qc_from_tag(ap, ap->active_tag);
+        printk(KERN_ERR "mmio_base %p ap %p qc %p scsi_cmnd %p &cmnd %p\n",
+              ap->host_set->mmio_base, ap, qc, qc->scsicmd,
+              &qc->scsicmd->cmnd);
+
+       spin_lock_irqsave(&ap->host_set->lock, flags);
+       mv_err_intr(ap, 0);
+       mv_stop_and_reset(ap);
+       spin_unlock_irqrestore(&ap->host_set->lock, flags);
+
+       WARN_ON(!(qc->flags & ATA_QCFLAG_ACTIVE));
+       if (qc->flags & ATA_QCFLAG_ACTIVE) {
+               qc->err_mask |= AC_ERR_TIMEOUT;
+               ata_eh_qc_complete(qc);
+       }
+}
+
+/**
+ *      mv_port_init - Perform some early initialization on a single port.
+ *      @port: libata data structure storing shadow register addresses
+ *      @port_mmio: base address of the port
+ *
+ *      Initialize shadow register mmio addresses, clear outstanding
+ *      interrupts on the port, and unmask interrupts for the future
+ *      start of the port.
+ *
+ *      LOCKING:
+ *      Inherited from caller.
+ */
+static void mv_port_init(struct ata_ioports *port,  void __iomem *port_mmio)
+{
+       unsigned long shd_base = (unsigned long) port_mmio + SHD_BLK_OFS;
+       unsigned serr_ofs;
+
+       /* PIO related setup
+        */
+       port->data_addr = shd_base + (sizeof(u32) * ATA_REG_DATA);
+       port->error_addr =
+               port->feature_addr = shd_base + (sizeof(u32) * ATA_REG_ERR);
+       port->nsect_addr = shd_base + (sizeof(u32) * ATA_REG_NSECT);
+       port->lbal_addr = shd_base + (sizeof(u32) * ATA_REG_LBAL);
+       port->lbam_addr = shd_base + (sizeof(u32) * ATA_REG_LBAM);
+       port->lbah_addr = shd_base + (sizeof(u32) * ATA_REG_LBAH);
+       port->device_addr = shd_base + (sizeof(u32) * ATA_REG_DEVICE);
+       port->status_addr =
+               port->command_addr = shd_base + (sizeof(u32) * ATA_REG_STATUS);
+       /* special case: control/altstatus doesn't have ATA_REG_ address */
+       port->altstatus_addr = port->ctl_addr = shd_base + SHD_CTL_AST_OFS;
+
+       /* unused: */
+       port->cmd_addr = port->bmdma_addr = port->scr_addr = 0;
+
+       /* Clear any currently outstanding port interrupt conditions */
+       serr_ofs = mv_scr_offset(SCR_ERROR);
+       writelfl(readl(port_mmio + serr_ofs), port_mmio + serr_ofs);
+       writelfl(0, port_mmio + EDMA_ERR_IRQ_CAUSE_OFS);
+
+       /* unmask all EDMA error interrupts */
+       writelfl(~0, port_mmio + EDMA_ERR_IRQ_MASK_OFS);
+
+       VPRINTK("EDMA cfg=0x%08x EDMA IRQ err cause/mask=0x%08x/0x%08x\n",
+               readl(port_mmio + EDMA_CFG_OFS),
+               readl(port_mmio + EDMA_ERR_IRQ_CAUSE_OFS),
+               readl(port_mmio + EDMA_ERR_IRQ_MASK_OFS));
+}
+
+static int mv_chip_id(struct pci_dev *pdev, struct mv_host_priv *hpriv,
+                     unsigned int board_idx)
+{
+       u8 rev_id;
+       u32 hp_flags = hpriv->hp_flags;
+
+       pci_read_config_byte(pdev, PCI_REVISION_ID, &rev_id);
+
+       switch(board_idx) {
+       case chip_5080:
+               hpriv->ops = &mv5xxx_ops;
+               hp_flags |= MV_HP_50XX;
+
+               switch (rev_id) {
+               case 0x1:
+                       hp_flags |= MV_HP_ERRATA_50XXB0;
+                       break;
+               case 0x3:
+                       hp_flags |= MV_HP_ERRATA_50XXB2;
+                       break;
+               default:
+                       dev_printk(KERN_WARNING, &pdev->dev,
+                          "Applying 50XXB2 workarounds to unknown rev\n");
+                       hp_flags |= MV_HP_ERRATA_50XXB2;
+                       break;
+               }
+               break;
+
+       case chip_504x:
+       case chip_508x:
+               hpriv->ops = &mv5xxx_ops;
+               hp_flags |= MV_HP_50XX;
+
+               switch (rev_id) {
+               case 0x0:
+                       hp_flags |= MV_HP_ERRATA_50XXB0;
+                       break;
+               case 0x3:
+                       hp_flags |= MV_HP_ERRATA_50XXB2;
+                       break;
+               default:
+                       dev_printk(KERN_WARNING, &pdev->dev,
+                          "Applying B2 workarounds to unknown rev\n");
+                       hp_flags |= MV_HP_ERRATA_50XXB2;
+                       break;
+               }
+               break;
+
+       case chip_604x:
+       case chip_608x:
+               hpriv->ops = &mv6xxx_ops;
+
+               switch (rev_id) {
+               case 0x7:
+                       hp_flags |= MV_HP_ERRATA_60X1B2;
+                       break;
+               case 0x9:
+                       hp_flags |= MV_HP_ERRATA_60X1C0;
+                       break;
+               default:
+                       dev_printk(KERN_WARNING, &pdev->dev,
+                                  "Applying B2 workarounds to unknown rev\n");
+                       hp_flags |= MV_HP_ERRATA_60X1B2;
+                       break;
+               }
+               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;
+       }
+
+       hpriv->hp_flags = hp_flags;
+
+       return 0;
+}
+
+/**
+ *      mv_init_host - Perform some early initialization of the host.
+ *     @pdev: host PCI device
+ *      @probe_ent: early data struct representing the host
+ *
+ *      If possible, do an early global reset of the host.  Then do
+ *      our port init and clear/unmask all/relevant host interrupts.
+ *
+ *      LOCKING:
+ *      Inherited from caller.
+ */
+static int mv_init_host(struct pci_dev *pdev, struct ata_probe_ent *probe_ent,
+                       unsigned int board_idx)
+{
+       int rc = 0, n_hc, port, hc;
+       void __iomem *mmio = probe_ent->mmio_base;
+       struct mv_host_priv *hpriv = probe_ent->private_data;
+
+       /* global interrupt mask */
+       writel(0, mmio + HC_MAIN_IRQ_MASK_OFS);
+
+       rc = mv_chip_id(pdev, hpriv, board_idx);
+       if (rc)
+               goto done;
+
+       n_hc = mv_get_hc_count(probe_ent->host_flags);
+       probe_ent->n_ports = MV_PORTS_PER_HC * n_hc;
+
+       for (port = 0; port < probe_ent->n_ports; port++)
+               hpriv->ops->read_preamp(hpriv, port, mmio);
+
+       rc = hpriv->ops->reset_hc(hpriv, mmio, n_hc);
+       if (rc)
+               goto done;
+
+       hpriv->ops->reset_flash(hpriv, mmio);
+       hpriv->ops->reset_bus(pdev, mmio);
+       hpriv->ops->enable_leds(hpriv, mmio);
+
+       for (port = 0; port < probe_ent->n_ports; port++) {
+               if (IS_60XX(hpriv)) {
+                       void __iomem *port_mmio = mv_port_base(mmio, port);
+
+                       u32 ifctl = readl(port_mmio + SATA_INTERFACE_CTL);
+                       ifctl |= (1 << 7);              /* enable gen2i speed */
+                       ifctl = (ifctl & 0xfff) | 0x9b1000; /* from chip spec */
+                       writelfl(ifctl, port_mmio + SATA_INTERFACE_CTL);
+               }
+
+               hpriv->ops->phy_errata(hpriv, mmio, port);
+       }
+
+       for (port = 0; port < probe_ent->n_ports; port++) {
+               void __iomem *port_mmio = mv_port_base(mmio, port);
+               mv_port_init(&probe_ent->port[port], port_mmio);
+       }
+
+       for (hc = 0; hc < n_hc; hc++) {
+               void __iomem *hc_mmio = mv_hc_base(mmio, hc);
+
+               VPRINTK("HC%i: HC config=0x%08x HC IRQ cause "
+                       "(before clear)=0x%08x\n", hc,
+                       readl(hc_mmio + HC_CFG_OFS),
+                       readl(hc_mmio + HC_IRQ_CAUSE_OFS));
+
+               /* Clear any currently outstanding hc interrupt conditions */
+               writelfl(0, hc_mmio + HC_IRQ_CAUSE_OFS);
+       }
+
+       /* Clear any currently outstanding host interrupt conditions */
+       writelfl(0, mmio + PCI_IRQ_CAUSE_OFS);
+
+       /* and unmask interrupt generation for host regs */
+       writelfl(PCI_UNMASK_ALL_IRQS, mmio + PCI_IRQ_MASK_OFS);
+       writelfl(~HC_MAIN_MASKED_IRQS, mmio + HC_MAIN_IRQ_MASK_OFS);
+
+       VPRINTK("HC MAIN IRQ cause/mask=0x%08x/0x%08x "
+               "PCI int cause/mask=0x%08x/0x%08x\n",
+               readl(mmio + HC_MAIN_IRQ_CAUSE_OFS),
+               readl(mmio + HC_MAIN_IRQ_MASK_OFS),
+               readl(mmio + PCI_IRQ_CAUSE_OFS),
+               readl(mmio + PCI_IRQ_MASK_OFS));
+
+done:
+       return rc;
+}
+
+/**
+ *      mv_print_info - Dump key info to kernel log for perusal.
+ *      @probe_ent: early data struct representing the host
+ *
+ *      FIXME: complete this.
+ *
+ *      LOCKING:
+ *      Inherited from caller.
+ */
+static void mv_print_info(struct ata_probe_ent *probe_ent)
+{
+       struct pci_dev *pdev = to_pci_dev(probe_ent->dev);
+       struct mv_host_priv *hpriv = probe_ent->private_data;
+       u8 rev_id, scc;
+       const char *scc_s;
+
+       /* Use this to determine the HW stepping of the chip so we know
+        * what errata to workaround
+        */
+       pci_read_config_byte(pdev, PCI_REVISION_ID, &rev_id);
+
+       pci_read_config_byte(pdev, PCI_CLASS_DEVICE, &scc);
+       if (scc == 0)
+               scc_s = "SCSI";
+       else if (scc == 0x01)
+               scc_s = "RAID";
+       else
+               scc_s = "unknown";
+
+       dev_printk(KERN_INFO, &pdev->dev,
+              "%u slots %u ports %s mode IRQ via %s\n",
+              (unsigned)MV_MAX_Q_DEPTH, probe_ent->n_ports,
+              scc_s, (MV_HP_FLAG_MSI & hpriv->hp_flags) ? "MSI" : "INTx");
+}
+
+/**
+ *      mv_init_one - handle a positive probe of a Marvell host
+ *      @pdev: PCI device found
+ *      @ent: PCI device ID entry for the matched host
+ *
+ *      LOCKING:
+ *      Inherited from caller.
+ */
+static int mv_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
+{
+       static int printed_version = 0;
+       struct ata_probe_ent *probe_ent = NULL;
+       struct mv_host_priv *hpriv;
+       unsigned int board_idx = (unsigned int)ent->driver_data;
+       void __iomem *mmio_base;
+       int pci_dev_busy = 0, rc;
+
+       if (!printed_version++)
+               dev_printk(KERN_INFO, &pdev->dev, "version " DRV_VERSION "\n");
+
+       rc = pci_enable_device(pdev);
+       if (rc) {
+               return rc;
+       }
+       pci_set_master(pdev);
+
+       rc = pci_request_regions(pdev, DRV_NAME);
+       if (rc) {
+               pci_dev_busy = 1;
+               goto err_out;
+       }
+
+       probe_ent = kmalloc(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);
+
+       mmio_base = pci_iomap(pdev, MV_PRIMARY_BAR, 0);
+       if (mmio_base == NULL) {
+               rc = -ENOMEM;
+               goto err_out_free_ent;
+       }
+
+       hpriv = kmalloc(sizeof(*hpriv), GFP_KERNEL);
+       if (!hpriv) {
+               rc = -ENOMEM;
+               goto err_out_iounmap;
+       }
+       memset(hpriv, 0, sizeof(*hpriv));
+
+       probe_ent->sht = mv_port_info[board_idx].sht;
+       probe_ent->host_flags = mv_port_info[board_idx].host_flags;
+       probe_ent->pio_mask = mv_port_info[board_idx].pio_mask;
+       probe_ent->udma_mask = mv_port_info[board_idx].udma_mask;
+       probe_ent->port_ops = mv_port_info[board_idx].port_ops;
+
+       probe_ent->irq = pdev->irq;
+       probe_ent->irq_flags = IRQF_SHARED;
+       probe_ent->mmio_base = mmio_base;
+       probe_ent->private_data = hpriv;
+
+       /* initialize adapter */
+       rc = mv_init_host(pdev, probe_ent, board_idx);
+       if (rc) {
+               goto err_out_hpriv;
+       }
+
+       /* Enable interrupts */
+       if (msi && pci_enable_msi(pdev) == 0) {
+               hpriv->hp_flags |= MV_HP_FLAG_MSI;
+       } else {
+               pci_intx(pdev, 1);
+       }
+
+       mv_dump_pci_cfg(pdev, 0x68);
+       mv_print_info(probe_ent);
+
+       if (ata_device_add(probe_ent) == 0) {
+               rc = -ENODEV;           /* No devices discovered */
+               goto err_out_dev_add;
+       }
+
+       kfree(probe_ent);
+       return 0;
+
+err_out_dev_add:
+       if (MV_HP_FLAG_MSI & hpriv->hp_flags) {
+               pci_disable_msi(pdev);
+       } else {
+               pci_intx(pdev, 0);
+       }
+err_out_hpriv:
+       kfree(hpriv);
+err_out_iounmap:
+       pci_iounmap(pdev, mmio_base);
+err_out_free_ent:
+       kfree(probe_ent);
+err_out_regions:
+       pci_release_regions(pdev);
+err_out:
+       if (!pci_dev_busy) {
+               pci_disable_device(pdev);
+       }
+
+       return rc;
+}
+
+static int __init mv_init(void)
+{
+       return pci_register_driver(&mv_pci_driver);
+}
+
+static void __exit mv_exit(void)
+{
+       pci_unregister_driver(&mv_pci_driver);
+}
+
+MODULE_AUTHOR("Brett Russ");
+MODULE_DESCRIPTION("SCSI low-level driver for Marvell SATA controllers");
+MODULE_LICENSE("GPL");
+MODULE_DEVICE_TABLE(pci, mv_pci_tbl);
+MODULE_VERSION(DRV_VERSION);
+
+module_param(msi, int, 0444);
+MODULE_PARM_DESC(msi, "Enable use of PCI MSI (0=off, 1=on)");
+
+module_init(mv_init);
+module_exit(mv_exit);
diff --git a/drivers/ata/sata_nv.c b/drivers/ata/sata_nv.c
new file mode 100644 (file)
index 0000000..be46df7
--- /dev/null
@@ -0,0 +1,595 @@
+/*
+ *  sata_nv.c - NVIDIA nForce SATA
+ *
+ *  Copyright 2004 NVIDIA Corp.  All rights reserved.
+ *  Copyright 2004 Andrew Chew
+ *
+ *
+ *  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.*
+ *
+ *  No hardware documentation available outside of NVIDIA.
+ *  This driver programs the NVIDIA SATA controller in a similar
+ *  fashion as with other PCI IDE BMDMA controllers, with a few
+ *  NV-specific details such as register offsets, SATA phy location,
+ *  hotplug info, etc.
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/pci.h>
+#include <linux/init.h>
+#include <linux/blkdev.h>
+#include <linux/delay.h>
+#include <linux/interrupt.h>
+#include <linux/device.h>
+#include <scsi/scsi_host.h>
+#include <linux/libata.h>
+
+#define DRV_NAME                       "sata_nv"
+#define DRV_VERSION                    "2.0"
+
+enum {
+       NV_PORTS                        = 2,
+       NV_PIO_MASK                     = 0x1f,
+       NV_MWDMA_MASK                   = 0x07,
+       NV_UDMA_MASK                    = 0x7f,
+       NV_PORT0_SCR_REG_OFFSET         = 0x00,
+       NV_PORT1_SCR_REG_OFFSET         = 0x40,
+
+       /* INT_STATUS/ENABLE */
+       NV_INT_STATUS                   = 0x10,
+       NV_INT_ENABLE                   = 0x11,
+       NV_INT_STATUS_CK804             = 0x440,
+       NV_INT_ENABLE_CK804             = 0x441,
+
+       /* INT_STATUS/ENABLE bits */
+       NV_INT_DEV                      = 0x01,
+       NV_INT_PM                       = 0x02,
+       NV_INT_ADDED                    = 0x04,
+       NV_INT_REMOVED                  = 0x08,
+
+       NV_INT_PORT_SHIFT               = 4,    /* each port occupies 4 bits */
+
+       NV_INT_ALL                      = 0x0f,
+       NV_INT_MASK                     = NV_INT_DEV |
+                                         NV_INT_ADDED | NV_INT_REMOVED,
+
+       /* INT_CONFIG */
+       NV_INT_CONFIG                   = 0x12,
+       NV_INT_CONFIG_METHD             = 0x01, // 0 = INT, 1 = SMI
+
+       // For PCI config register 20
+       NV_MCP_SATA_CFG_20              = 0x50,
+       NV_MCP_SATA_CFG_20_SATA_SPACE_EN = 0x04,
+};
+
+static int nv_init_one (struct pci_dev *pdev, const struct pci_device_id *ent);
+static void nv_ck804_host_stop(struct ata_host_set *host_set);
+static irqreturn_t nv_generic_interrupt(int irq, void *dev_instance,
+                                       struct pt_regs *regs);
+static irqreturn_t nv_nf2_interrupt(int irq, void *dev_instance,
+                                   struct pt_regs *regs);
+static irqreturn_t nv_ck804_interrupt(int irq, void *dev_instance,
+                                     struct pt_regs *regs);
+static u32 nv_scr_read (struct ata_port *ap, unsigned int sc_reg);
+static void nv_scr_write (struct ata_port *ap, unsigned int sc_reg, u32 val);
+
+static void nv_nf2_freeze(struct ata_port *ap);
+static void nv_nf2_thaw(struct ata_port *ap);
+static void nv_ck804_freeze(struct ata_port *ap);
+static void nv_ck804_thaw(struct ata_port *ap);
+static void nv_error_handler(struct ata_port *ap);
+
+enum nv_host_type
+{
+       GENERIC,
+       NFORCE2,
+       NFORCE3 = NFORCE2,      /* NF2 == NF3 as far as sata_nv is concerned */
+       CK804
+};
+
+static const struct pci_device_id nv_pci_tbl[] = {
+       { PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE2S_SATA,
+               PCI_ANY_ID, PCI_ANY_ID, 0, 0, NFORCE2 },
+       { PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE3S_SATA,
+               PCI_ANY_ID, PCI_ANY_ID, 0, 0, NFORCE3 },
+       { PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE3S_SATA2,
+               PCI_ANY_ID, PCI_ANY_ID, 0, 0, NFORCE3 },
+       { PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_CK804_SATA,
+               PCI_ANY_ID, PCI_ANY_ID, 0, 0, CK804 },
+       { PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_CK804_SATA2,
+               PCI_ANY_ID, PCI_ANY_ID, 0, 0, CK804 },
+       { PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP04_SATA,
+               PCI_ANY_ID, PCI_ANY_ID, 0, 0, CK804 },
+       { PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP04_SATA2,
+               PCI_ANY_ID, PCI_ANY_ID, 0, 0, CK804 },
+       { PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP51_SATA,
+               PCI_ANY_ID, PCI_ANY_ID, 0, 0, GENERIC },
+       { PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP51_SATA2,
+               PCI_ANY_ID, PCI_ANY_ID, 0, 0, GENERIC },
+       { PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP55_SATA,
+               PCI_ANY_ID, PCI_ANY_ID, 0, 0, GENERIC },
+       { PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP55_SATA2,
+               PCI_ANY_ID, PCI_ANY_ID, 0, 0, GENERIC },
+       { PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP61_SATA,
+               PCI_ANY_ID, PCI_ANY_ID, 0, 0, GENERIC },
+       { PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP61_SATA2,
+               PCI_ANY_ID, PCI_ANY_ID, 0, 0, GENERIC },
+       { PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP61_SATA3,
+               PCI_ANY_ID, PCI_ANY_ID, 0, 0, GENERIC },
+       { PCI_VENDOR_ID_NVIDIA, 0x045c, PCI_ANY_ID, PCI_ANY_ID, 0, 0, GENERIC },
+       { PCI_VENDOR_ID_NVIDIA, 0x045d, PCI_ANY_ID, PCI_ANY_ID, 0, 0, GENERIC },
+       { PCI_VENDOR_ID_NVIDIA, 0x045e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, GENERIC },
+       { PCI_VENDOR_ID_NVIDIA, 0x045f, PCI_ANY_ID, PCI_ANY_ID, 0, 0, GENERIC },
+       { PCI_VENDOR_ID_NVIDIA, PCI_ANY_ID,
+               PCI_ANY_ID, PCI_ANY_ID,
+               PCI_CLASS_STORAGE_IDE<<8, 0xffff00, GENERIC },
+       { PCI_VENDOR_ID_NVIDIA, PCI_ANY_ID,
+               PCI_ANY_ID, PCI_ANY_ID,
+               PCI_CLASS_STORAGE_RAID<<8, 0xffff00, GENERIC },
+       { 0, } /* terminate list */
+};
+
+static struct pci_driver nv_pci_driver = {
+       .name                   = DRV_NAME,
+       .id_table               = nv_pci_tbl,
+       .probe                  = nv_init_one,
+       .remove                 = ata_pci_remove_one,
+};
+
+static struct scsi_host_template nv_sht = {
+       .module                 = THIS_MODULE,
+       .name                   = DRV_NAME,
+       .ioctl                  = ata_scsi_ioctl,
+       .queuecommand           = ata_scsi_queuecmd,
+       .can_queue              = ATA_DEF_QUEUE,
+       .this_id                = ATA_SHT_THIS_ID,
+       .sg_tablesize           = LIBATA_MAX_PRD,
+       .cmd_per_lun            = ATA_SHT_CMD_PER_LUN,
+       .emulated               = ATA_SHT_EMULATED,
+       .use_clustering         = ATA_SHT_USE_CLUSTERING,
+       .proc_name              = DRV_NAME,
+       .dma_boundary           = ATA_DMA_BOUNDARY,
+       .slave_configure        = ata_scsi_slave_config,
+       .slave_destroy          = ata_scsi_slave_destroy,
+       .bios_param             = ata_std_bios_param,
+};
+
+static const struct ata_port_operations nv_generic_ops = {
+       .port_disable           = ata_port_disable,
+       .tf_load                = ata_tf_load,
+       .tf_read                = ata_tf_read,
+       .exec_command           = ata_exec_command,
+       .check_status           = ata_check_status,
+       .dev_select             = ata_std_dev_select,
+       .bmdma_setup            = ata_bmdma_setup,
+       .bmdma_start            = ata_bmdma_start,
+       .bmdma_stop             = ata_bmdma_stop,
+       .bmdma_status           = ata_bmdma_status,
+       .qc_prep                = ata_qc_prep,
+       .qc_issue               = ata_qc_issue_prot,
+       .freeze                 = ata_bmdma_freeze,
+       .thaw                   = ata_bmdma_thaw,
+       .error_handler          = nv_error_handler,
+       .post_internal_cmd      = ata_bmdma_post_internal_cmd,
+       .data_xfer              = ata_pio_data_xfer,
+       .irq_handler            = nv_generic_interrupt,
+       .irq_clear              = ata_bmdma_irq_clear,
+       .scr_read               = nv_scr_read,
+       .scr_write              = nv_scr_write,
+       .port_start             = ata_port_start,
+       .port_stop              = ata_port_stop,
+       .host_stop              = ata_pci_host_stop,
+};
+
+static const struct ata_port_operations nv_nf2_ops = {
+       .port_disable           = ata_port_disable,
+       .tf_load                = ata_tf_load,
+       .tf_read                = ata_tf_read,
+       .exec_command           = ata_exec_command,
+       .check_status           = ata_check_status,
+       .dev_select             = ata_std_dev_select,
+       .bmdma_setup            = ata_bmdma_setup,
+       .bmdma_start            = ata_bmdma_start,
+       .bmdma_stop             = ata_bmdma_stop,
+       .bmdma_status           = ata_bmdma_status,
+       .qc_prep                = ata_qc_prep,
+       .qc_issue               = ata_qc_issue_prot,
+       .freeze                 = nv_nf2_freeze,
+       .thaw                   = nv_nf2_thaw,
+       .error_handler          = nv_error_handler,
+       .post_internal_cmd      = ata_bmdma_post_internal_cmd,
+       .data_xfer              = ata_pio_data_xfer,
+       .irq_handler            = nv_nf2_interrupt,
+       .irq_clear              = ata_bmdma_irq_clear,
+       .scr_read               = nv_scr_read,
+       .scr_write              = nv_scr_write,
+       .port_start             = ata_port_start,
+       .port_stop              = ata_port_stop,
+       .host_stop              = ata_pci_host_stop,
+};
+
+static const struct ata_port_operations nv_ck804_ops = {
+       .port_disable           = ata_port_disable,
+       .tf_load                = ata_tf_load,
+       .tf_read                = ata_tf_read,
+       .exec_command           = ata_exec_command,
+       .check_status           = ata_check_status,
+       .dev_select             = ata_std_dev_select,
+       .bmdma_setup            = ata_bmdma_setup,
+       .bmdma_start            = ata_bmdma_start,
+       .bmdma_stop             = ata_bmdma_stop,
+       .bmdma_status           = ata_bmdma_status,
+       .qc_prep                = ata_qc_prep,
+       .qc_issue               = ata_qc_issue_prot,
+       .freeze                 = nv_ck804_freeze,
+       .thaw                   = nv_ck804_thaw,
+       .error_handler          = nv_error_handler,
+       .post_internal_cmd      = ata_bmdma_post_internal_cmd,
+       .data_xfer              = ata_pio_data_xfer,
+       .irq_handler            = nv_ck804_interrupt,
+       .irq_clear              = ata_bmdma_irq_clear,
+       .scr_read               = nv_scr_read,
+       .scr_write              = nv_scr_write,
+       .port_start             = ata_port_start,
+       .port_stop              = ata_port_stop,
+       .host_stop              = nv_ck804_host_stop,
+};
+
+static struct ata_port_info nv_port_info[] = {
+       /* generic */
+       {
+               .sht            = &nv_sht,
+               .host_flags     = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY,
+               .pio_mask       = NV_PIO_MASK,
+               .mwdma_mask     = NV_MWDMA_MASK,
+               .udma_mask      = NV_UDMA_MASK,
+               .port_ops       = &nv_generic_ops,
+       },
+       /* nforce2/3 */
+       {
+               .sht            = &nv_sht,
+               .host_flags     = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY,
+               .pio_mask       = NV_PIO_MASK,
+               .mwdma_mask     = NV_MWDMA_MASK,
+               .udma_mask      = NV_UDMA_MASK,
+               .port_ops       = &nv_nf2_ops,
+       },
+       /* ck804 */
+       {
+               .sht            = &nv_sht,
+               .host_flags     = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY,
+               .pio_mask       = NV_PIO_MASK,
+               .mwdma_mask     = NV_MWDMA_MASK,
+               .udma_mask      = NV_UDMA_MASK,
+               .port_ops       = &nv_ck804_ops,
+       },
+};
+
+MODULE_AUTHOR("NVIDIA");
+MODULE_DESCRIPTION("low-level driver for NVIDIA nForce SATA controller");
+MODULE_LICENSE("GPL");
+MODULE_DEVICE_TABLE(pci, nv_pci_tbl);
+MODULE_VERSION(DRV_VERSION);
+
+static irqreturn_t nv_generic_interrupt(int irq, void *dev_instance,
+                                       struct pt_regs *regs)
+{
+       struct ata_host_set *host_set = dev_instance;
+       unsigned int i;
+       unsigned int handled = 0;
+       unsigned long flags;
+
+       spin_lock_irqsave(&host_set->lock, flags);
+
+       for (i = 0; i < host_set->n_ports; i++) {
+               struct ata_port *ap;
+
+               ap = host_set->ports[i];
+               if (ap &&
+                   !(ap->flags & ATA_FLAG_DISABLED)) {
+                       struct ata_queued_cmd *qc;
+
+                       qc = ata_qc_from_tag(ap, ap->active_tag);
+                       if (qc && (!(qc->tf.flags & ATA_TFLAG_POLLING)))
+                               handled += ata_host_intr(ap, qc);
+                       else
+                               // No request pending?  Clear interrupt status
+                               // anyway, in case there's one pending.
+                               ap->ops->check_status(ap);
+               }
+
+       }
+
+       spin_unlock_irqrestore(&host_set->lock, flags);
+
+       return IRQ_RETVAL(handled);
+}
+
+static int nv_host_intr(struct ata_port *ap, u8 irq_stat)
+{
+       struct ata_queued_cmd *qc = ata_qc_from_tag(ap, ap->active_tag);
+       int handled;
+
+       /* freeze if hotplugged */
+       if (unlikely(irq_stat & (NV_INT_ADDED | NV_INT_REMOVED))) {
+               ata_port_freeze(ap);
+               return 1;
+       }
+
+       /* bail out if not our interrupt */
+       if (!(irq_stat & NV_INT_DEV))
+               return 0;
+
+       /* DEV interrupt w/ no active qc? */
+       if (unlikely(!qc || (qc->tf.flags & ATA_TFLAG_POLLING))) {
+               ata_check_status(ap);
+               return 1;
+       }
+
+       /* handle interrupt */
+       handled = ata_host_intr(ap, qc);
+       if (unlikely(!handled)) {
+               /* spurious, clear it */
+               ata_check_status(ap);
+       }
+
+       return 1;
+}
+
+static irqreturn_t nv_do_interrupt(struct ata_host_set *host_set, u8 irq_stat)
+{
+       int i, handled = 0;
+
+       for (i = 0; i < host_set->n_ports; i++) {
+               struct ata_port *ap = host_set->ports[i];
+
+               if (ap && !(ap->flags & ATA_FLAG_DISABLED))
+                       handled += nv_host_intr(ap, irq_stat);
+
+               irq_stat >>= NV_INT_PORT_SHIFT;
+       }
+
+       return IRQ_RETVAL(handled);
+}
+
+static irqreturn_t nv_nf2_interrupt(int irq, void *dev_instance,
+                                   struct pt_regs *regs)
+{
+       struct ata_host_set *host_set = dev_instance;
+       u8 irq_stat;
+       irqreturn_t ret;
+
+       spin_lock(&host_set->lock);
+       irq_stat = inb(host_set->ports[0]->ioaddr.scr_addr + NV_INT_STATUS);
+       ret = nv_do_interrupt(host_set, irq_stat);
+       spin_unlock(&host_set->lock);
+
+       return ret;
+}
+
+static irqreturn_t nv_ck804_interrupt(int irq, void *dev_instance,
+                                     struct pt_regs *regs)
+{
+       struct ata_host_set *host_set = dev_instance;
+       u8 irq_stat;
+       irqreturn_t ret;
+
+       spin_lock(&host_set->lock);
+       irq_stat = readb(host_set->mmio_base + NV_INT_STATUS_CK804);
+       ret = nv_do_interrupt(host_set, irq_stat);
+       spin_unlock(&host_set->lock);
+
+       return ret;
+}
+
+static u32 nv_scr_read (struct ata_port *ap, unsigned int sc_reg)
+{
+       if (sc_reg > SCR_CONTROL)
+               return 0xffffffffU;
+
+       return ioread32((void __iomem *)ap->ioaddr.scr_addr + (sc_reg * 4));
+}
+
+static void nv_scr_write (struct ata_port *ap, unsigned int sc_reg, u32 val)
+{
+       if (sc_reg > SCR_CONTROL)
+               return;
+
+       iowrite32(val, (void __iomem *)ap->ioaddr.scr_addr + (sc_reg * 4));
+}
+
+static void nv_nf2_freeze(struct ata_port *ap)
+{
+       unsigned long scr_addr = ap->host_set->ports[0]->ioaddr.scr_addr;
+       int shift = ap->port_no * NV_INT_PORT_SHIFT;
+       u8 mask;
+
+       mask = inb(scr_addr + NV_INT_ENABLE);
+       mask &= ~(NV_INT_ALL << shift);
+       outb(mask, scr_addr + NV_INT_ENABLE);
+}
+
+static void nv_nf2_thaw(struct ata_port *ap)
+{
+       unsigned long scr_addr = ap->host_set->ports[0]->ioaddr.scr_addr;
+       int shift = ap->port_no * NV_INT_PORT_SHIFT;
+       u8 mask;
+
+       outb(NV_INT_ALL << shift, scr_addr + NV_INT_STATUS);
+
+       mask = inb(scr_addr + NV_INT_ENABLE);
+       mask |= (NV_INT_MASK << shift);
+       outb(mask, scr_addr + NV_INT_ENABLE);
+}
+
+static void nv_ck804_freeze(struct ata_port *ap)
+{
+       void __iomem *mmio_base = ap->host_set->mmio_base;
+       int shift = ap->port_no * NV_INT_PORT_SHIFT;
+       u8 mask;
+
+       mask = readb(mmio_base + NV_INT_ENABLE_CK804);
+       mask &= ~(NV_INT_ALL << shift);
+       writeb(mask, mmio_base + NV_INT_ENABLE_CK804);
+}
+
+static void nv_ck804_thaw(struct ata_port *ap)
+{
+       void __iomem *mmio_base = ap->host_set->mmio_base;
+       int shift = ap->port_no * NV_INT_PORT_SHIFT;
+       u8 mask;
+
+       writeb(NV_INT_ALL << shift, mmio_base + NV_INT_STATUS_CK804);
+
+       mask = readb(mmio_base + NV_INT_ENABLE_CK804);
+       mask |= (NV_INT_MASK << shift);
+       writeb(mask, mmio_base + NV_INT_ENABLE_CK804);
+}
+
+static int nv_hardreset(struct ata_port *ap, unsigned int *class)
+{
+       unsigned int dummy;
+
+       /* SATA hardreset fails to retrieve proper device signature on
+        * some controllers.  Don't classify on hardreset.  For more
+        * info, see http://bugme.osdl.org/show_bug.cgi?id=3352
+        */
+       return sata_std_hardreset(ap, &dummy);
+}
+
+static void nv_error_handler(struct ata_port *ap)
+{
+       ata_bmdma_drive_eh(ap, ata_std_prereset, ata_std_softreset,
+                          nv_hardreset, ata_std_postreset);
+}
+
+static int nv_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
+{
+       static int printed_version = 0;
+       struct ata_port_info *ppi;
+       struct ata_probe_ent *probe_ent;
+       int pci_dev_busy = 0;
+       int rc;
+       u32 bar;
+       unsigned long base;
+
+        // Make sure this is a SATA controller by counting the number of bars
+        // (NVIDIA SATA controllers will always have six bars).  Otherwise,
+        // it's an IDE controller and we ignore it.
+       for (bar=0; bar<6; bar++)
+               if (pci_resource_start(pdev, bar) == 0)
+                       return -ENODEV;
+
+       if (!printed_version++)
+               dev_printk(KERN_DEBUG, &pdev->dev, "version " DRV_VERSION "\n");
+
+       rc = pci_enable_device(pdev);
+       if (rc)
+               goto err_out;
+
+       rc = pci_request_regions(pdev, DRV_NAME);
+       if (rc) {
+               pci_dev_busy = 1;
+               goto err_out_disable;
+       }
+
+       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;
+
+       rc = -ENOMEM;
+
+       ppi = &nv_port_info[ent->driver_data];
+       probe_ent = ata_pci_init_native_mode(pdev, &ppi, ATA_PORT_PRIMARY | ATA_PORT_SECONDARY);
+       if (!probe_ent)
+               goto err_out_regions;
+
+       probe_ent->mmio_base = pci_iomap(pdev, 5, 0);
+       if (!probe_ent->mmio_base) {
+               rc = -EIO;
+               goto err_out_free_ent;
+       }
+
+       base = (unsigned long)probe_ent->mmio_base;
+
+       probe_ent->port[0].scr_addr = base + NV_PORT0_SCR_REG_OFFSET;
+       probe_ent->port[1].scr_addr = base + NV_PORT1_SCR_REG_OFFSET;
+
+       /* enable SATA space for CK804 */
+       if (ent->driver_data == CK804) {
+               u8 regval;
+
+               pci_read_config_byte(pdev, NV_MCP_SATA_CFG_20, &regval);
+               regval |= NV_MCP_SATA_CFG_20_SATA_SPACE_EN;
+               pci_write_config_byte(pdev, NV_MCP_SATA_CFG_20, regval);
+       }
+
+       pci_set_master(pdev);
+
+       rc = ata_device_add(probe_ent);
+       if (rc != NV_PORTS)
+               goto err_out_iounmap;
+
+       kfree(probe_ent);
+
+       return 0;
+
+err_out_iounmap:
+       pci_iounmap(pdev, probe_ent->mmio_base);
+err_out_free_ent:
+       kfree(probe_ent);
+err_out_regions:
+       pci_release_regions(pdev);
+err_out_disable:
+       if (!pci_dev_busy)
+               pci_disable_device(pdev);
+err_out:
+       return rc;
+}
+
+static void nv_ck804_host_stop(struct ata_host_set *host_set)
+{
+       struct pci_dev *pdev = to_pci_dev(host_set->dev);
+       u8 regval;
+
+       /* disable SATA space for CK804 */
+       pci_read_config_byte(pdev, NV_MCP_SATA_CFG_20, &regval);
+       regval &= ~NV_MCP_SATA_CFG_20_SATA_SPACE_EN;
+       pci_write_config_byte(pdev, NV_MCP_SATA_CFG_20, regval);
+
+       ata_pci_host_stop(host_set);
+}
+
+static int __init nv_init(void)
+{
+       return pci_register_driver(&nv_pci_driver);
+}
+
+static void __exit nv_exit(void)
+{
+       pci_unregister_driver(&nv_pci_driver);
+}
+
+module_init(nv_init);
+module_exit(nv_exit);
diff --git a/drivers/ata/sata_promise.c b/drivers/ata/sata_promise.c
new file mode 100644 (file)
index 0000000..a5b3a7d
--- /dev/null
@@ -0,0 +1,844 @@
+/*
+ *  sata_promise.c - Promise SATA
+ *
+ *  Maintained by:  Jeff Garzik <jgarzik@pobox.com>
+ *                 Please ALWAYS copy linux-ide@vger.kernel.org
+ *                 on emails.
+ *
+ *  Copyright 2003-2004 Red Hat, Inc.
+ *
+ *
+ *  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 information only available under NDA.
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/pci.h>
+#include <linux/init.h>
+#include <linux/blkdev.h>
+#include <linux/delay.h>
+#include <linux/interrupt.h>
+#include <linux/sched.h>
+#include <linux/device.h>
+#include <scsi/scsi_host.h>
+#include <scsi/scsi_cmnd.h>
+#include <linux/libata.h>
+#include <asm/io.h>
+#include "sata_promise.h"
+
+#define DRV_NAME       "sata_promise"
+#define DRV_VERSION    "1.04"
+
+
+enum {
+       PDC_PKT_SUBMIT          = 0x40, /* Command packet pointer addr */
+       PDC_INT_SEQMASK         = 0x40, /* Mask of asserted SEQ INTs */
+       PDC_TBG_MODE            = 0x41, /* TBG mode */
+       PDC_FLASH_CTL           = 0x44, /* Flash control register */
+       PDC_PCI_CTL             = 0x48, /* PCI control and status register */
+       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) |
+                                 (1<<8) | (1<<9) | (1<<10),
+
+       board_2037x             = 0,    /* FastTrak S150 TX2plus */
+       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/20575 has PATA */
+
+       PDC_RESET               = (1 << 11), /* HDMA reset */
+
+       PDC_COMMON_FLAGS        = ATA_FLAG_NO_LEGACY | ATA_FLAG_SRST |
+                                 ATA_FLAG_MMIO | ATA_FLAG_NO_ATAPI |
+                                 ATA_FLAG_PIO_POLLING,
+};
+
+
+struct pdc_port_priv {
+       u8                      *pkt;
+       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);
+static irqreturn_t pdc_interrupt (int irq, void *dev_instance, struct pt_regs *regs);
+static void pdc_eng_timeout(struct ata_port *ap);
+static int pdc_port_start(struct ata_port *ap);
+static void pdc_port_stop(struct ata_port *ap);
+static void pdc_pata_phy_reset(struct ata_port *ap);
+static void pdc_sata_phy_reset(struct ata_port *ap);
+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 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 = {
+       .module                 = THIS_MODULE,
+       .name                   = DRV_NAME,
+       .ioctl                  = ata_scsi_ioctl,
+       .queuecommand           = ata_scsi_queuecmd,
+       .can_queue              = ATA_DEF_QUEUE,
+       .this_id                = ATA_SHT_THIS_ID,
+       .sg_tablesize           = LIBATA_MAX_PRD,
+       .cmd_per_lun            = ATA_SHT_CMD_PER_LUN,
+       .emulated               = ATA_SHT_EMULATED,
+       .use_clustering         = ATA_SHT_USE_CLUSTERING,
+       .proc_name              = DRV_NAME,
+       .dma_boundary           = ATA_DMA_BOUNDARY,
+       .slave_configure        = ata_scsi_slave_config,
+       .slave_destroy          = ata_scsi_slave_destroy,
+       .bios_param             = ata_std_bios_param,
+};
+
+static const struct ata_port_operations pdc_sata_ops = {
+       .port_disable           = ata_port_disable,
+       .tf_load                = pdc_tf_load_mmio,
+       .tf_read                = ata_tf_read,
+       .check_status           = ata_check_status,
+       .exec_command           = pdc_exec_command_mmio,
+       .dev_select             = ata_std_dev_select,
+
+       .phy_reset              = pdc_sata_phy_reset,
+
+       .qc_prep                = pdc_qc_prep,
+       .qc_issue               = pdc_qc_issue_prot,
+       .eng_timeout            = pdc_eng_timeout,
+       .data_xfer              = ata_mmio_data_xfer,
+       .irq_handler            = pdc_interrupt,
+       .irq_clear              = pdc_irq_clear,
+
+       .scr_read               = pdc_sata_scr_read,
+       .scr_write              = pdc_sata_scr_write,
+       .port_start             = pdc_port_start,
+       .port_stop              = pdc_port_stop,
+       .host_stop              = pdc_host_stop,
+};
+
+static const struct ata_port_operations pdc_pata_ops = {
+       .port_disable           = ata_port_disable,
+       .tf_load                = pdc_tf_load_mmio,
+       .tf_read                = ata_tf_read,
+       .check_status           = ata_check_status,
+       .exec_command           = pdc_exec_command_mmio,
+       .dev_select             = ata_std_dev_select,
+
+       .phy_reset              = pdc_pata_phy_reset,
+
+       .qc_prep                = pdc_qc_prep,
+       .qc_issue               = pdc_qc_issue_prot,
+       .data_xfer              = ata_mmio_data_xfer,
+       .eng_timeout            = pdc_eng_timeout,
+       .irq_handler            = pdc_interrupt,
+       .irq_clear              = pdc_irq_clear,
+
+       .port_start             = pdc_port_start,
+       .port_stop              = pdc_port_stop,
+       .host_stop              = pdc_host_stop,
+};
+
+static const struct ata_port_info pdc_port_info[] = {
+       /* board_2037x */
+       {
+               .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_20319 */
+       {
+               .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_20619 */
+       {
+               .sht            = &pdc_ata_sht,
+               .host_flags     = PDC_COMMON_FLAGS | ATA_FLAG_SLAVE_POSS,
+               .pio_mask       = 0x1f, /* pio0-4 */
+               .mwdma_mask     = 0x07, /* mwdma0-2 */
+               .udma_mask      = 0x7f, /* udma0-6 ; FIXME */
+               .port_ops       = &pdc_pata_ops,
+       },
+
+       /* board_20771 */
+       {
+               .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_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[] = {
+       { PCI_VENDOR_ID_PROMISE, 0x3371, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+         board_2037x },
+       { PCI_VENDOR_ID_PROMISE, 0x3570, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+         board_2037x },
+       { PCI_VENDOR_ID_PROMISE, 0x3571, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+         board_2037x },
+       { PCI_VENDOR_ID_PROMISE, 0x3373, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+         board_2037x },
+       { PCI_VENDOR_ID_PROMISE, 0x3375, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+         board_2037x },
+       { 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_2057x },
+       { PCI_VENDOR_ID_PROMISE, 0x3d75, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+         board_2057x },
+       { PCI_VENDOR_ID_PROMISE, 0x3d73, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+         board_2037x },
+
+       { PCI_VENDOR_ID_PROMISE, 0x3318, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+         board_20319 },
+       { PCI_VENDOR_ID_PROMISE, 0x3319, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+         board_20319 },
+       { PCI_VENDOR_ID_PROMISE, 0x3515, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+         board_20319 },
+       { PCI_VENDOR_ID_PROMISE, 0x3519, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+         board_20319 },
+       { PCI_VENDOR_ID_PROMISE, 0x3d17, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+         board_20319 },
+       { PCI_VENDOR_ID_PROMISE, 0x3d18, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+         board_40518 },
+
+       { PCI_VENDOR_ID_PROMISE, 0x6629, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+         board_20619 },
+
+/* TODO: remove all associated board_20771 code, as it completely
+ * duplicates board_2037x code, unless reason for separation can be
+ * divined.
+ */
+#if 0
+       { PCI_VENDOR_ID_PROMISE, 0x3570, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+         board_20771 },
+#endif
+
+       { }     /* terminate list */
+};
+
+
+static struct pci_driver pdc_ata_pci_driver = {
+       .name                   = DRV_NAME,
+       .id_table               = pdc_ata_pci_tbl,
+       .probe                  = pdc_ata_init_one,
+       .remove                 = ata_pci_remove_one,
+};
+
+
+static int pdc_port_start(struct ata_port *ap)
+{
+       struct device *dev = ap->host_set->dev;
+       struct pdc_port_priv *pp;
+       int rc;
+
+       rc = ata_port_start(ap);
+       if (rc)
+               return rc;
+
+       pp = kzalloc(sizeof(*pp), GFP_KERNEL);
+       if (!pp) {
+               rc = -ENOMEM;
+               goto err_out;
+       }
+
+       pp->pkt = dma_alloc_coherent(dev, 128, &pp->pkt_dma, GFP_KERNEL);
+       if (!pp->pkt) {
+               rc = -ENOMEM;
+               goto err_out_kfree;
+       }
+
+       ap->private_data = pp;
+
+       return 0;
+
+err_out_kfree:
+       kfree(pp);
+err_out:
+       ata_port_stop(ap);
+       return rc;
+}
+
+
+static void pdc_port_stop(struct ata_port *ap)
+{
+       struct device *dev = ap->host_set->dev;
+       struct pdc_port_priv *pp = ap->private_data;
+
+       ap->private_data = NULL;
+       dma_free_coherent(dev, 128, pp->pkt, pp->pkt_dma);
+       kfree(pp);
+       ata_port_stop(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;
+       unsigned int i;
+       u32 tmp;
+
+       for (i = 11; i > 0; i--) {
+               tmp = readl(mmio);
+               if (tmp & PDC_RESET)
+                       break;
+
+               udelay(100);
+
+               tmp |= PDC_RESET;
+               writel(tmp, mmio);
+       }
+
+       tmp &= ~PDC_RESET;
+       writel(tmp, mmio);
+       readl(mmio);    /* flush */
+}
+
+static void pdc_sata_phy_reset(struct ata_port *ap)
+{
+       pdc_reset_port(ap);
+       sata_phy_reset(ap);
+}
+
+static void pdc_pata_cbl_detect(struct ata_port *ap)
+{
+       u8 tmp;
+       void __iomem *mmio = (void *) ap->ioaddr.cmd_addr + PDC_CTLSTAT + 0x03;
+
+       tmp = readb(mmio);
+
+       if (tmp & 0x01) {
+               ap->cbl = ATA_CBL_PATA40;
+               ap->udma_mask &= ATA_UDMA_MASK_40C;
+       } else
+               ap->cbl = ATA_CBL_PATA80;
+}
+
+static void pdc_pata_phy_reset(struct ata_port *ap)
+{
+       pdc_pata_cbl_detect(ap);
+       pdc_reset_port(ap);
+       ata_port_probe(ap);
+       ata_bus_reset(ap);
+}
+
+static u32 pdc_sata_scr_read (struct ata_port *ap, unsigned int sc_reg)
+{
+       if (sc_reg > SCR_CONTROL)
+               return 0xffffffffU;
+       return readl((void __iomem *) ap->ioaddr.scr_addr + (sc_reg * 4));
+}
+
+
+static void pdc_sata_scr_write (struct ata_port *ap, unsigned int sc_reg,
+                              u32 val)
+{
+       if (sc_reg > SCR_CONTROL)
+               return;
+       writel(val, (void __iomem *) ap->ioaddr.scr_addr + (sc_reg * 4));
+}
+
+static void pdc_qc_prep(struct ata_queued_cmd *qc)
+{
+       struct pdc_port_priv *pp = qc->ap->private_data;
+       unsigned int i;
+
+       VPRINTK("ENTER\n");
+
+       switch (qc->tf.protocol) {
+       case ATA_PROT_DMA:
+               ata_qc_prep(qc);
+               /* fall through */
+
+       case ATA_PROT_NODATA:
+               i = pdc_pkt_header(&qc->tf, qc->ap->prd_dma,
+                                  qc->dev->devno, pp->pkt);
+
+               if (qc->tf.flags & ATA_TFLAG_LBA48)
+                       i = pdc_prep_lba48(&qc->tf, pp->pkt, i);
+               else
+                       i = pdc_prep_lba28(&qc->tf, pp->pkt, i);
+
+               pdc_pkt_footer(&qc->tf, pp->pkt, i);
+               break;
+
+       default:
+               break;
+       }
+}
+
+static void pdc_eng_timeout(struct ata_port *ap)
+{
+       struct ata_host_set *host_set = ap->host_set;
+       u8 drv_stat;
+       struct ata_queued_cmd *qc;
+       unsigned long flags;
+
+       DPRINTK("ENTER\n");
+
+       spin_lock_irqsave(&host_set->lock, flags);
+
+       qc = ata_qc_from_tag(ap, ap->active_tag);
+
+       switch (qc->tf.protocol) {
+       case ATA_PROT_DMA:
+       case ATA_PROT_NODATA:
+               ata_port_printk(ap, KERN_ERR, "command timeout\n");
+               drv_stat = ata_wait_idle(ap);
+               qc->err_mask |= __ac_err_mask(drv_stat);
+               break;
+
+       default:
+               drv_stat = ata_busy_wait(ap, ATA_BUSY | ATA_DRQ, 1000);
+
+               ata_port_printk(ap, KERN_ERR,
+                               "unknown timeout, cmd 0x%x stat 0x%x\n",
+                               qc->tf.command, drv_stat);
+
+               qc->err_mask |= ac_err_mask(drv_stat);
+               break;
+       }
+
+       spin_unlock_irqrestore(&host_set->lock, flags);
+       ata_eh_qc_complete(qc);
+       DPRINTK("EXIT\n");
+}
+
+static inline unsigned int pdc_host_intr( struct ata_port *ap,
+                                          struct ata_queued_cmd *qc)
+{
+       unsigned int handled = 0;
+       u32 tmp;
+       void __iomem *mmio = (void __iomem *) ap->ioaddr.cmd_addr + PDC_GLOBAL_CTL;
+
+       tmp = readl(mmio);
+       if (tmp & PDC_ERR_MASK) {
+               qc->err_mask |= AC_ERR_DEV;
+               pdc_reset_port(ap);
+       }
+
+       switch (qc->tf.protocol) {
+       case ATA_PROT_DMA:
+       case ATA_PROT_NODATA:
+               qc->err_mask |= ac_err_mask(ata_wait_idle(ap));
+               ata_qc_complete(qc);
+               handled = 1;
+               break;
+
+        default:
+               ap->stats.idle_irq++;
+               break;
+        }
+
+       return handled;
+}
+
+static void pdc_irq_clear(struct ata_port *ap)
+{
+       struct ata_host_set *host_set = ap->host_set;
+       void __iomem *mmio = host_set->mmio_base;
+
+       readl(mmio + PDC_INT_SEQMASK);
+}
+
+static irqreturn_t pdc_interrupt (int irq, void *dev_instance, struct pt_regs *regs)
+{
+       struct ata_host_set *host_set = dev_instance;
+       struct ata_port *ap;
+       u32 mask = 0;
+       unsigned int i, tmp;
+       unsigned int handled = 0;
+       void __iomem *mmio_base;
+
+       VPRINTK("ENTER\n");
+
+       if (!host_set || !host_set->mmio_base) {
+               VPRINTK("QUICK EXIT\n");
+               return IRQ_NONE;
+       }
+
+       mmio_base = host_set->mmio_base;
+
+       /* reading should also clear interrupts */
+       mask = readl(mmio_base + PDC_INT_SEQMASK);
+
+       if (mask == 0xffffffff) {
+               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");
+               goto done_irq;
+       }
+
+       writel(mask, mmio_base + PDC_INT_SEQMASK);
+
+       for (i = 0; i < host_set->n_ports; i++) {
+               VPRINTK("port %u\n", i);
+               ap = host_set->ports[i];
+               tmp = mask & (1 << (i + 1));
+               if (tmp && ap &&
+                   !(ap->flags & ATA_FLAG_DISABLED)) {
+                       struct ata_queued_cmd *qc;
+
+                       qc = ata_qc_from_tag(ap, ap->active_tag);
+                       if (qc && (!(qc->tf.flags & ATA_TFLAG_POLLING)))
+                               handled += pdc_host_intr(ap, qc);
+               }
+       }
+
+       VPRINTK("EXIT\n");
+
+done_irq:
+       spin_unlock(&host_set->lock);
+       return IRQ_RETVAL(handled);
+}
+
+static inline void pdc_packet_start(struct ata_queued_cmd *qc)
+{
+       struct ata_port *ap = qc->ap;
+       struct pdc_port_priv *pp = ap->private_data;
+       unsigned int port_no = ap->port_no;
+       u8 seq = (u8) (port_no + 1);
+
+       VPRINTK("ENTER, ap %p\n", ap);
+
+       writel(0x00000001, ap->host_set->mmio_base + (seq * 4));
+       readl(ap->host_set->mmio_base + (seq * 4));     /* flush */
+
+       pp->pkt[2] = seq;
+       wmb();                  /* flush PRD, pkt writes */
+       writel(pp->pkt_dma, (void __iomem *) ap->ioaddr.cmd_addr + PDC_PKT_SUBMIT);
+       readl((void __iomem *) ap->ioaddr.cmd_addr + PDC_PKT_SUBMIT); /* flush */
+}
+
+static unsigned int pdc_qc_issue_prot(struct ata_queued_cmd *qc)
+{
+       switch (qc->tf.protocol) {
+       case ATA_PROT_DMA:
+       case ATA_PROT_NODATA:
+               pdc_packet_start(qc);
+               return 0;
+
+       case ATA_PROT_ATAPI_DMA:
+               BUG();
+               break;
+
+       default:
+               break;
+       }
+
+       return ata_qc_issue_prot(qc);
+}
+
+static void pdc_tf_load_mmio(struct ata_port *ap, const struct ata_taskfile *tf)
+{
+       WARN_ON (tf->protocol == ATA_PROT_DMA ||
+                tf->protocol == ATA_PROT_NODATA);
+       ata_tf_load(ap, tf);
+}
+
+
+static void pdc_exec_command_mmio(struct ata_port *ap, const struct ata_taskfile *tf)
+{
+       WARN_ON (tf->protocol == ATA_PROT_DMA ||
+                tf->protocol == ATA_PROT_NODATA);
+       ata_exec_command(ap, tf);
+}
+
+
+static void pdc_ata_setup_port(struct ata_ioports *port, unsigned long base)
+{
+       port->cmd_addr          = base;
+       port->data_addr         = base;
+       port->feature_addr      =
+       port->error_addr        = base + 0x4;
+       port->nsect_addr        = base + 0x8;
+       port->lbal_addr         = base + 0xc;
+       port->lbam_addr         = base + 0x10;
+       port->lbah_addr         = base + 0x14;
+       port->device_addr       = base + 0x18;
+       port->command_addr      =
+       port->status_addr       = base + 0x1c;
+       port->altstatus_addr    =
+       port->ctl_addr          = base + 0x38;
+}
+
+
+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;
+
+       /*
+        * Except for the hotplug stuff, this is voodoo from the
+        * Promise driver.  Label this entire section
+        * "TODO: figure out why we do this"
+        */
+
+       /* change FIFO_SHD to 8 dwords, enable BMR_BURST */
+       tmp = readl(mmio + PDC_FLASH_CTL);
+       tmp |= 0x12000; /* bit 16 (fifo 8 dw) and 13 (bmr burst?) */
+       writel(tmp, mmio + PDC_FLASH_CTL);
+
+       /* clear plug/unplug flags for all ports */
+       tmp = readl(mmio + hotplug_offset);
+       writel(tmp | 0xff, mmio + hotplug_offset);
+
+       /* mask plug/unplug ints */
+       tmp = readl(mmio + hotplug_offset);
+       writel(tmp | 0xff0000, mmio + hotplug_offset);
+
+       /* reduce TBG clock to 133 Mhz. */
+       tmp = readl(mmio + PDC_TBG_MODE);
+       tmp &= ~0x30000; /* clear bit 17, 16*/
+       tmp |= 0x10000;  /* set bit 17:16 = 0:1 */
+       writel(tmp, mmio + PDC_TBG_MODE);
+
+       readl(mmio + PDC_TBG_MODE);     /* flush */
+       msleep(10);
+
+       /* adjust slew rate control register. */
+       tmp = readl(mmio + PDC_SLEW_CTL);
+       tmp &= 0xFFFFF03F; /* clear bit 11 ~ 6 */
+       tmp  |= 0x00000900; /* set bit 11-9 = 100b , bit 8-6 = 100 */
+       writel(tmp, mmio + PDC_SLEW_CTL);
+}
+
+static int pdc_ata_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
+{
+       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;
+       int pci_dev_busy = 0;
+       int rc;
+
+       if (!printed_version++)
+               dev_printk(KERN_DEBUG, &pdev->dev, "version " DRV_VERSION "\n");
+
+       rc = pci_enable_device(pdev);
+       if (rc)
+               return rc;
+
+       rc = pci_request_regions(pdev, DRV_NAME);
+       if (rc) {
+               pci_dev_busy = 1;
+               goto err_out;
+       }
+
+       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;
+
+       probe_ent = kzalloc(sizeof(*probe_ent), GFP_KERNEL);
+       if (probe_ent == NULL) {
+               rc = -ENOMEM;
+               goto err_out_regions;
+       }
+
+       probe_ent->dev = pci_dev_to_dev(pdev);
+       INIT_LIST_HEAD(&probe_ent->node);
+
+       mmio_base = pci_iomap(pdev, 3, 0);
+       if (mmio_base == NULL) {
+               rc = -ENOMEM;
+               goto err_out_free_ent;
+       }
+       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;
+       probe_ent->mwdma_mask   = pdc_port_info[board_idx].mwdma_mask;
+       probe_ent->udma_mask    = pdc_port_info[board_idx].udma_mask;
+       probe_ent->port_ops     = pdc_port_info[board_idx].port_ops;
+
+               probe_ent->irq = pdev->irq;
+               probe_ent->irq_flags = IRQF_SHARED;
+       probe_ent->mmio_base = mmio_base;
+
+       pdc_ata_setup_port(&probe_ent->port[0], base + 0x200);
+       pdc_ata_setup_port(&probe_ent->port[1], base + 0x280);
+
+       probe_ent->port[0].scr_addr = base + 0x400;
+       probe_ent->port[1].scr_addr = base + 0x500;
+
+       /* 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;
+
+               pdc_ata_setup_port(&probe_ent->port[2], base + 0x300);
+               pdc_ata_setup_port(&probe_ent->port[3], base + 0x380);
+
+               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;
+       case board_20771:
+               probe_ent->n_ports = 2;
+               break;
+       case board_20619:
+               probe_ent->n_ports = 4;
+
+               pdc_ata_setup_port(&probe_ent->port[2], base + 0x300);
+               pdc_ata_setup_port(&probe_ent->port[3], base + 0x380);
+
+               probe_ent->port[2].scr_addr = base + 0x600;
+               probe_ent->port[3].scr_addr = base + 0x700;
+               break;
+       default:
+               BUG();
+               break;
+       }
+
+       pci_set_master(pdev);
+
+       /* initialize adapter */
+       pdc_host_init(board_idx, probe_ent);
+
+       /* FIXME: Need any other frees than hp? */
+       if (!ata_device_add(probe_ent))
+               kfree(hp);
+
+       kfree(probe_ent);
+
+       return 0;
+
+err_out_free_ent:
+       kfree(probe_ent);
+err_out_regions:
+       pci_release_regions(pdev);
+err_out:
+       if (!pci_dev_busy)
+               pci_disable_device(pdev);
+       return rc;
+}
+
+
+static int __init pdc_ata_init(void)
+{
+       return pci_register_driver(&pdc_ata_pci_driver);
+}
+
+
+static void __exit pdc_ata_exit(void)
+{
+       pci_unregister_driver(&pdc_ata_pci_driver);
+}
+
+
+MODULE_AUTHOR("Jeff Garzik");
+MODULE_DESCRIPTION("Promise ATA TX2/TX4/TX4000 low-level driver");
+MODULE_LICENSE("GPL");
+MODULE_DEVICE_TABLE(pci, pdc_ata_pci_tbl);
+MODULE_VERSION(DRV_VERSION);
+
+module_init(pdc_ata_init);
+module_exit(pdc_ata_exit);
diff --git a/drivers/ata/sata_promise.h b/drivers/ata/sata_promise.h
new file mode 100644 (file)
index 0000000..6ee5e19
--- /dev/null
@@ -0,0 +1,157 @@
+/*
+ *  sata_promise.h - Promise SATA common definitions and inline funcs
+ *
+ *  Copyright 2003-2004 Red Hat, Inc.
+ *
+ *
+ *  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.*
+ *
+ */
+
+#ifndef __SATA_PROMISE_H__
+#define __SATA_PROMISE_H__
+
+#include <linux/ata.h>
+
+enum pdc_packet_bits {
+       PDC_PKT_READ            = (1 << 2),
+       PDC_PKT_NODATA          = (1 << 3),
+
+       PDC_PKT_SIZEMASK        = (1 << 7) | (1 << 6) | (1 << 5),
+       PDC_PKT_CLEAR_BSY       = (1 << 4),
+       PDC_PKT_WAIT_DRDY       = (1 << 3) | (1 << 4),
+       PDC_LAST_REG            = (1 << 3),
+
+       PDC_REG_DEVCTL          = (1 << 3) | (1 << 2) | (1 << 1),
+};
+
+static inline unsigned int pdc_pkt_header(struct ata_taskfile *tf,
+                                         dma_addr_t sg_table,
+                                         unsigned int devno, u8 *buf)
+{
+       u8 dev_reg;
+       u32 *buf32 = (u32 *) buf;
+
+       /* set control bits (byte 0), zero delay seq id (byte 3),
+        * and seq id (byte 2)
+        */
+       switch (tf->protocol) {
+       case ATA_PROT_DMA:
+               if (!(tf->flags & ATA_TFLAG_WRITE))
+                       buf32[0] = cpu_to_le32(PDC_PKT_READ);
+               else
+                       buf32[0] = 0;
+               break;
+
+       case ATA_PROT_NODATA:
+               buf32[0] = cpu_to_le32(PDC_PKT_NODATA);
+               break;
+
+       default:
+               BUG();
+               break;
+       }
+
+       buf32[1] = cpu_to_le32(sg_table);       /* S/G table addr */
+       buf32[2] = 0;                           /* no next-packet */
+
+       if (devno == 0)
+               dev_reg = ATA_DEVICE_OBS;
+       else
+               dev_reg = ATA_DEVICE_OBS | ATA_DEV1;
+
+       /* select device */
+       buf[12] = (1 << 5) | PDC_PKT_CLEAR_BSY | ATA_REG_DEVICE;
+       buf[13] = dev_reg;
+
+       /* device control register */
+       buf[14] = (1 << 5) | PDC_REG_DEVCTL;
+       buf[15] = tf->ctl;
+
+       return 16;      /* offset of next byte */
+}
+
+static inline unsigned int pdc_pkt_footer(struct ata_taskfile *tf, u8 *buf,
+                                 unsigned int i)
+{
+       if (tf->flags & ATA_TFLAG_DEVICE) {
+               buf[i++] = (1 << 5) | ATA_REG_DEVICE;
+               buf[i++] = tf->device;
+       }
+
+       /* and finally the command itself; also includes end-of-pkt marker */
+       buf[i++] = (1 << 5) | PDC_LAST_REG | ATA_REG_CMD;
+       buf[i++] = tf->command;
+
+       return i;
+}
+
+static inline unsigned int pdc_prep_lba28(struct ata_taskfile *tf, u8 *buf, unsigned int i)
+{
+       /* the "(1 << 5)" should be read "(count << 5)" */
+
+       /* ATA command block registers */
+       buf[i++] = (1 << 5) | ATA_REG_FEATURE;
+       buf[i++] = tf->feature;
+
+       buf[i++] = (1 << 5) | ATA_REG_NSECT;
+       buf[i++] = tf->nsect;
+
+       buf[i++] = (1 << 5) | ATA_REG_LBAL;
+       buf[i++] = tf->lbal;
+
+       buf[i++] = (1 << 5) | ATA_REG_LBAM;
+       buf[i++] = tf->lbam;
+
+       buf[i++] = (1 << 5) | ATA_REG_LBAH;
+       buf[i++] = tf->lbah;
+
+       return i;
+}
+
+static inline unsigned int pdc_prep_lba48(struct ata_taskfile *tf, u8 *buf, unsigned int i)
+{
+       /* the "(2 << 5)" should be read "(count << 5)" */
+
+       /* ATA command block registers */
+       buf[i++] = (2 << 5) | ATA_REG_FEATURE;
+       buf[i++] = tf->hob_feature;
+       buf[i++] = tf->feature;
+
+       buf[i++] = (2 << 5) | ATA_REG_NSECT;
+       buf[i++] = tf->hob_nsect;
+       buf[i++] = tf->nsect;
+
+       buf[i++] = (2 << 5) | ATA_REG_LBAL;
+       buf[i++] = tf->hob_lbal;
+       buf[i++] = tf->lbal;
+
+       buf[i++] = (2 << 5) | ATA_REG_LBAM;
+       buf[i++] = tf->hob_lbam;
+       buf[i++] = tf->lbam;
+
+       buf[i++] = (2 << 5) | ATA_REG_LBAH;
+       buf[i++] = tf->hob_lbah;
+       buf[i++] = tf->lbah;
+
+       return i;
+}
+
+
+#endif /* __SATA_PROMISE_H__ */
diff --git a/drivers/ata/sata_qstor.c b/drivers/ata/sata_qstor.c
new file mode 100644 (file)
index 0000000..71bd671
--- /dev/null
@@ -0,0 +1,730 @@
+/*
+ *  sata_qstor.c - Pacific Digital Corporation QStor SATA
+ *
+ *  Maintained by:  Mark Lord <mlord@pobox.com>
+ *
+ *  Copyright 2005 Pacific Digital Corporation.
+ *  (OSL/GPL code release authorized by Jalil Fadavi).
+ *
+ *
+ *  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.*
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/pci.h>
+#include <linux/init.h>
+#include <linux/blkdev.h>
+#include <linux/delay.h>
+#include <linux/interrupt.h>
+#include <linux/sched.h>
+#include <linux/device.h>
+#include <scsi/scsi_host.h>
+#include <asm/io.h>
+#include <linux/libata.h>
+
+#define DRV_NAME       "sata_qstor"
+#define DRV_VERSION    "0.06"
+
+enum {
+       QS_PORTS                = 4,
+       QS_MAX_PRD              = LIBATA_MAX_PRD,
+       QS_CPB_ORDER            = 6,
+       QS_CPB_BYTES            = (1 << QS_CPB_ORDER),
+       QS_PRD_BYTES            = QS_MAX_PRD * 16,
+       QS_PKT_BYTES            = QS_CPB_BYTES + QS_PRD_BYTES,
+
+       /* global register offsets */
+       QS_HCF_CNFG3            = 0x0003, /* host configuration offset */
+       QS_HID_HPHY             = 0x0004, /* host physical interface info */
+       QS_HCT_CTRL             = 0x00e4, /* global interrupt mask offset */
+       QS_HST_SFF              = 0x0100, /* host status fifo offset */
+       QS_HVS_SERD3            = 0x0393, /* PHY enable offset */
+
+       /* global control bits */
+       QS_HPHY_64BIT           = (1 << 1), /* 64-bit bus detected */
+       QS_CNFG3_GSRST          = 0x01,     /* global chip reset */
+       QS_SERD3_PHY_ENA        = 0xf0,     /* PHY detection ENAble*/
+
+       /* per-channel register offsets */
+       QS_CCF_CPBA             = 0x0710, /* chan CPB base address */
+       QS_CCF_CSEP             = 0x0718, /* chan CPB separation factor */
+       QS_CFC_HUFT             = 0x0800, /* host upstream fifo threshold */
+       QS_CFC_HDFT             = 0x0804, /* host downstream fifo threshold */
+       QS_CFC_DUFT             = 0x0808, /* dev upstream fifo threshold */
+       QS_CFC_DDFT             = 0x080c, /* dev downstream fifo threshold */
+       QS_CCT_CTR0             = 0x0900, /* chan control-0 offset */
+       QS_CCT_CTR1             = 0x0901, /* chan control-1 offset */
+       QS_CCT_CFF              = 0x0a00, /* chan command fifo offset */
+
+       /* channel control bits */
+       QS_CTR0_REG             = (1 << 1),   /* register mode (vs. pkt mode) */
+       QS_CTR0_CLER            = (1 << 2),   /* clear channel errors */
+       QS_CTR1_RDEV            = (1 << 1),   /* sata phy/comms reset */
+       QS_CTR1_RCHN            = (1 << 4),   /* reset channel logic */
+       QS_CCF_RUN_PKT          = 0x107,      /* RUN a new dma PKT */
+
+       /* pkt sub-field headers */
+       QS_HCB_HDR              = 0x01,   /* Host Control Block header */
+       QS_DCB_HDR              = 0x02,   /* Device Control Block header */
+
+       /* pkt HCB flag bits */
+       QS_HF_DIRO              = (1 << 0),   /* data DIRection Out */
+       QS_HF_DAT               = (1 << 3),   /* DATa pkt */
+       QS_HF_IEN               = (1 << 4),   /* Interrupt ENable */
+       QS_HF_VLD               = (1 << 5),   /* VaLiD pkt */
+
+       /* pkt DCB flag bits */
+       QS_DF_PORD              = (1 << 2),   /* Pio OR Dma */
+       QS_DF_ELBA              = (1 << 3),   /* Extended LBA (lba48) */
+
+       /* PCI device IDs */
+       board_2068_idx          = 0,    /* QStor 4-port SATA/RAID */
+};
+
+enum {
+       QS_DMA_BOUNDARY         = ~0UL
+};
+
+typedef enum { qs_state_idle, qs_state_pkt, qs_state_mmio } qs_state_t;
+
+struct qs_port_priv {
+       u8                      *pkt;
+       dma_addr_t              pkt_dma;
+       qs_state_t              state;
+};
+
+static u32 qs_scr_read (struct ata_port *ap, unsigned int sc_reg);
+static void qs_scr_write (struct ata_port *ap, unsigned int sc_reg, u32 val);
+static int qs_ata_init_one (struct pci_dev *pdev, const struct pci_device_id *ent);
+static irqreturn_t qs_intr (int irq, void *dev_instance, struct pt_regs *regs);
+static int qs_port_start(struct ata_port *ap);
+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 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);
+static void qs_irq_clear(struct ata_port *ap);
+static void qs_eng_timeout(struct ata_port *ap);
+
+static struct scsi_host_template qs_ata_sht = {
+       .module                 = THIS_MODULE,
+       .name                   = DRV_NAME,
+       .ioctl                  = ata_scsi_ioctl,
+       .queuecommand           = ata_scsi_queuecmd,
+       .can_queue              = ATA_DEF_QUEUE,
+       .this_id                = ATA_SHT_THIS_ID,
+       .sg_tablesize           = QS_MAX_PRD,
+       .cmd_per_lun            = ATA_SHT_CMD_PER_LUN,
+       .emulated               = ATA_SHT_EMULATED,
+       //FIXME .use_clustering         = ATA_SHT_USE_CLUSTERING,
+       .use_clustering         = ENABLE_CLUSTERING,
+       .proc_name              = DRV_NAME,
+       .dma_boundary           = QS_DMA_BOUNDARY,
+       .slave_configure        = ata_scsi_slave_config,
+       .slave_destroy          = ata_scsi_slave_destroy,
+       .bios_param             = ata_std_bios_param,
+};
+
+static const struct ata_port_operations qs_ata_ops = {
+       .port_disable           = ata_port_disable,
+       .tf_load                = ata_tf_load,
+       .tf_read                = ata_tf_read,
+       .check_status           = ata_check_status,
+       .check_atapi_dma        = qs_check_atapi_dma,
+       .exec_command           = ata_exec_command,
+       .dev_select             = ata_std_dev_select,
+       .phy_reset              = qs_phy_reset,
+       .qc_prep                = qs_qc_prep,
+       .qc_issue               = qs_qc_issue,
+       .data_xfer              = ata_mmio_data_xfer,
+       .eng_timeout            = qs_eng_timeout,
+       .irq_handler            = qs_intr,
+       .irq_clear              = qs_irq_clear,
+       .scr_read               = qs_scr_read,
+       .scr_write              = qs_scr_write,
+       .port_start             = qs_port_start,
+       .port_stop              = qs_port_stop,
+       .host_stop              = qs_host_stop,
+       .bmdma_stop             = qs_bmdma_stop,
+       .bmdma_status           = qs_bmdma_status,
+};
+
+static const struct ata_port_info qs_port_info[] = {
+       /* board_2068_idx */
+       {
+               .sht            = &qs_ata_sht,
+               .host_flags     = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
+                                 ATA_FLAG_SATA_RESET |
+                                 //FIXME ATA_FLAG_SRST |
+                                 ATA_FLAG_MMIO | ATA_FLAG_PIO_POLLING,
+               .pio_mask       = 0x10, /* pio4 */
+               .udma_mask      = 0x7f, /* udma0-6 */
+               .port_ops       = &qs_ata_ops,
+       },
+};
+
+static const struct pci_device_id qs_ata_pci_tbl[] = {
+       { PCI_VENDOR_ID_PDC, 0x2068, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+         board_2068_idx },
+
+       { }     /* terminate list */
+};
+
+static struct pci_driver qs_ata_pci_driver = {
+       .name                   = DRV_NAME,
+       .id_table               = qs_ata_pci_tbl,
+       .probe                  = qs_ata_init_one,
+       .remove                 = ata_pci_remove_one,
+};
+
+static int qs_check_atapi_dma(struct ata_queued_cmd *qc)
+{
+       return 1;       /* ATAPI DMA not supported */
+}
+
+static void qs_bmdma_stop(struct ata_queued_cmd *qc)
+{
+       /* nothing */
+}
+
+static u8 qs_bmdma_status(struct ata_port *ap)
+{
+       return 0;
+}
+
+static void qs_irq_clear(struct ata_port *ap)
+{
+       /* nothing */
+}
+
+static inline void qs_enter_reg_mode(struct ata_port *ap)
+{
+       u8 __iomem *chan = ap->host_set->mmio_base + (ap->port_no * 0x4000);
+
+       writeb(QS_CTR0_REG, chan + QS_CCT_CTR0);
+       readb(chan + QS_CCT_CTR0);        /* flush */
+}
+
+static inline void qs_reset_channel_logic(struct ata_port *ap)
+{
+       u8 __iomem *chan = ap->host_set->mmio_base + (ap->port_no * 0x4000);
+
+       writeb(QS_CTR1_RCHN, chan + QS_CCT_CTR1);
+       readb(chan + QS_CCT_CTR0);        /* flush */
+       qs_enter_reg_mode(ap);
+}
+
+static void qs_phy_reset(struct ata_port *ap)
+{
+       struct qs_port_priv *pp = ap->private_data;
+
+       pp->state = qs_state_idle;
+       qs_reset_channel_logic(ap);
+       sata_phy_reset(ap);
+}
+
+static void qs_eng_timeout(struct ata_port *ap)
+{
+       struct qs_port_priv *pp = ap->private_data;
+
+       if (pp->state != qs_state_idle) /* healthy paranoia */
+               pp->state = qs_state_mmio;
+       qs_reset_channel_logic(ap);
+       ata_eng_timeout(ap);
+}
+
+static u32 qs_scr_read (struct ata_port *ap, unsigned int sc_reg)
+{
+       if (sc_reg > SCR_CONTROL)
+               return ~0U;
+       return readl((void __iomem *)(ap->ioaddr.scr_addr + (sc_reg * 8)));
+}
+
+static void qs_scr_write (struct ata_port *ap, unsigned int sc_reg, u32 val)
+{
+       if (sc_reg > SCR_CONTROL)
+               return;
+       writel(val, (void __iomem *)(ap->ioaddr.scr_addr + (sc_reg * 8)));
+}
+
+static unsigned int qs_fill_sg(struct ata_queued_cmd *qc)
+{
+       struct scatterlist *sg;
+       struct ata_port *ap = qc->ap;
+       struct qs_port_priv *pp = ap->private_data;
+       unsigned int nelem;
+       u8 *prd = pp->pkt + QS_CPB_BYTES;
+
+       WARN_ON(qc->__sg == NULL);
+       WARN_ON(qc->n_elem == 0 && qc->pad_len == 0);
+
+       nelem = 0;
+       ata_for_each_sg(sg, qc) {
+               u64 addr;
+               u32 len;
+
+               addr = sg_dma_address(sg);
+               *(__le64 *)prd = cpu_to_le64(addr);
+               prd += sizeof(u64);
+
+               len = sg_dma_len(sg);
+               *(__le32 *)prd = cpu_to_le32(len);
+               prd += sizeof(u64);
+
+               VPRINTK("PRD[%u] = (0x%llX, 0x%X)\n", nelem,
+                                       (unsigned long long)addr, len);
+               nelem++;
+       }
+
+       return nelem;
+}
+
+static void qs_qc_prep(struct ata_queued_cmd *qc)
+{
+       struct qs_port_priv *pp = qc->ap->private_data;
+       u8 dflags = QS_DF_PORD, *buf = pp->pkt;
+       u8 hflags = QS_HF_DAT | QS_HF_IEN | QS_HF_VLD;
+       u64 addr;
+       unsigned int nelem;
+
+       VPRINTK("ENTER\n");
+
+       qs_enter_reg_mode(qc->ap);
+       if (qc->tf.protocol != ATA_PROT_DMA) {
+               ata_qc_prep(qc);
+               return;
+       }
+
+       nelem = qs_fill_sg(qc);
+
+       if ((qc->tf.flags & ATA_TFLAG_WRITE))
+               hflags |= QS_HF_DIRO;
+       if ((qc->tf.flags & ATA_TFLAG_LBA48))
+               dflags |= QS_DF_ELBA;
+
+       /* host control block (HCB) */
+       buf[ 0] = QS_HCB_HDR;
+       buf[ 1] = hflags;
+       *(__le32 *)(&buf[ 4]) = cpu_to_le32(qc->nsect * ATA_SECT_SIZE);
+       *(__le32 *)(&buf[ 8]) = cpu_to_le32(nelem);
+       addr = ((u64)pp->pkt_dma) + QS_CPB_BYTES;
+       *(__le64 *)(&buf[16]) = cpu_to_le64(addr);
+
+       /* device control block (DCB) */
+       buf[24] = QS_DCB_HDR;
+       buf[28] = dflags;
+
+       /* frame information structure (FIS) */
+       ata_tf_to_fis(&qc->tf, &buf[32], 0);
+}
+
+static inline void qs_packet_start(struct ata_queued_cmd *qc)
+{
+       struct ata_port *ap = qc->ap;
+       u8 __iomem *chan = ap->host_set->mmio_base + (ap->port_no * 0x4000);
+
+       VPRINTK("ENTER, ap %p\n", ap);
+
+       writeb(QS_CTR0_CLER, chan + QS_CCT_CTR0);
+       wmb();                             /* flush PRDs and pkt to memory */
+       writel(QS_CCF_RUN_PKT, chan + QS_CCT_CFF);
+       readl(chan + QS_CCT_CFF);          /* flush */
+}
+
+static unsigned int qs_qc_issue(struct ata_queued_cmd *qc)
+{
+       struct qs_port_priv *pp = qc->ap->private_data;
+
+       switch (qc->tf.protocol) {
+       case ATA_PROT_DMA:
+
+               pp->state = qs_state_pkt;
+               qs_packet_start(qc);
+               return 0;
+
+       case ATA_PROT_ATAPI_DMA:
+               BUG();
+               break;
+
+       default:
+               break;
+       }
+
+       pp->state = qs_state_mmio;
+       return ata_qc_issue_prot(qc);
+}
+
+static inline unsigned int qs_intr_pkt(struct ata_host_set *host_set)
+{
+       unsigned int handled = 0;
+       u8 sFFE;
+       u8 __iomem *mmio_base = host_set->mmio_base;
+
+       do {
+               u32 sff0 = readl(mmio_base + QS_HST_SFF);
+               u32 sff1 = readl(mmio_base + QS_HST_SFF + 4);
+               u8 sEVLD = (sff1 >> 30) & 0x01; /* valid flag */
+               sFFE  = sff1 >> 31;             /* empty flag */
+
+               if (sEVLD) {
+                       u8 sDST = sff0 >> 16;   /* dev status */
+                       u8 sHST = sff1 & 0x3f;  /* host status */
+                       unsigned int port_no = (sff1 >> 8) & 0x03;
+                       struct ata_port *ap = host_set->ports[port_no];
+
+                       DPRINTK("SFF=%08x%08x: sCHAN=%u sHST=%d sDST=%02x\n",
+                                       sff1, sff0, port_no, sHST, sDST);
+                       handled = 1;
+                       if (ap && !(ap->flags & ATA_FLAG_DISABLED)) {
+                               struct ata_queued_cmd *qc;
+                               struct qs_port_priv *pp = ap->private_data;
+                               if (!pp || pp->state != qs_state_pkt)
+                                       continue;
+                               qc = ata_qc_from_tag(ap, ap->active_tag);
+                               if (qc && (!(qc->tf.flags & ATA_TFLAG_POLLING))) {
+                                       switch (sHST) {
+                                       case 0: /* successful CPB */
+                                       case 3: /* device error */
+                                               pp->state = qs_state_idle;
+                                               qs_enter_reg_mode(qc->ap);
+                                               qc->err_mask |= ac_err_mask(sDST);
+                                               ata_qc_complete(qc);
+                                               break;
+                                       default:
+                                               break;
+                                       }
+                               }
+                       }
+               }
+       } while (!sFFE);
+       return handled;
+}
+
+static inline unsigned int qs_intr_mmio(struct ata_host_set *host_set)
+{
+       unsigned int handled = 0, port_no;
+
+       for (port_no = 0; port_no < host_set->n_ports; ++port_no) {
+               struct ata_port *ap;
+               ap = host_set->ports[port_no];
+               if (ap &&
+                   !(ap->flags & ATA_FLAG_DISABLED)) {
+                       struct ata_queued_cmd *qc;
+                       struct qs_port_priv *pp = ap->private_data;
+                       if (!pp || pp->state != qs_state_mmio)
+                               continue;
+                       qc = ata_qc_from_tag(ap, ap->active_tag);
+                       if (qc && (!(qc->tf.flags & ATA_TFLAG_POLLING))) {
+
+                               /* check main status, clearing INTRQ */
+                               u8 status = ata_check_status(ap);
+                               if ((status & ATA_BUSY))
+                                       continue;
+                               DPRINTK("ata%u: protocol %d (dev_stat 0x%X)\n",
+                                       ap->id, qc->tf.protocol, status);
+
+                               /* complete taskfile transaction */
+                               pp->state = qs_state_idle;
+                               qc->err_mask |= ac_err_mask(status);
+                               ata_qc_complete(qc);
+                               handled = 1;
+                       }
+               }
+       }
+       return handled;
+}
+
+static irqreturn_t qs_intr(int irq, void *dev_instance, struct pt_regs *regs)
+{
+       struct ata_host_set *host_set = dev_instance;
+       unsigned int handled = 0;
+
+       VPRINTK("ENTER\n");
+
+       spin_lock(&host_set->lock);
+       handled  = qs_intr_pkt(host_set) | qs_intr_mmio(host_set);
+       spin_unlock(&host_set->lock);
+
+       VPRINTK("EXIT\n");
+
+       return IRQ_RETVAL(handled);
+}
+
+static void qs_ata_setup_port(struct ata_ioports *port, unsigned long base)
+{
+       port->cmd_addr          =
+       port->data_addr         = base + 0x400;
+       port->error_addr        =
+       port->feature_addr      = base + 0x408; /* hob_feature = 0x409 */
+       port->nsect_addr        = base + 0x410; /* hob_nsect   = 0x411 */
+       port->lbal_addr         = base + 0x418; /* hob_lbal    = 0x419 */
+       port->lbam_addr         = base + 0x420; /* hob_lbam    = 0x421 */
+       port->lbah_addr         = base + 0x428; /* hob_lbah    = 0x429 */
+       port->device_addr       = base + 0x430;
+       port->status_addr       =
+       port->command_addr      = base + 0x438;
+       port->altstatus_addr    =
+       port->ctl_addr          = base + 0x440;
+       port->scr_addr          = base + 0xc00;
+}
+
+static int qs_port_start(struct ata_port *ap)
+{
+       struct device *dev = ap->host_set->dev;
+       struct qs_port_priv *pp;
+       void __iomem *mmio_base = ap->host_set->mmio_base;
+       void __iomem *chan = mmio_base + (ap->port_no * 0x4000);
+       u64 addr;
+       int rc;
+
+       rc = ata_port_start(ap);
+       if (rc)
+               return rc;
+       qs_enter_reg_mode(ap);
+       pp = kzalloc(sizeof(*pp), GFP_KERNEL);
+       if (!pp) {
+               rc = -ENOMEM;
+               goto err_out;
+       }
+       pp->pkt = dma_alloc_coherent(dev, QS_PKT_BYTES, &pp->pkt_dma,
+                                                               GFP_KERNEL);
+       if (!pp->pkt) {
+               rc = -ENOMEM;
+               goto err_out_kfree;
+       }
+       memset(pp->pkt, 0, QS_PKT_BYTES);
+       ap->private_data = pp;
+
+       addr = (u64)pp->pkt_dma;
+       writel((u32) addr,        chan + QS_CCF_CPBA);
+       writel((u32)(addr >> 32), chan + QS_CCF_CPBA + 4);
+       return 0;
+
+err_out_kfree:
+       kfree(pp);
+err_out:
+       ata_port_stop(ap);
+       return rc;
+}
+
+static void qs_port_stop(struct ata_port *ap)
+{
+       struct device *dev = ap->host_set->dev;
+       struct qs_port_priv *pp = ap->private_data;
+
+       if (pp != NULL) {
+               ap->private_data = NULL;
+               if (pp->pkt != NULL)
+                       dma_free_coherent(dev, QS_PKT_BYTES, pp->pkt,
+                                                               pp->pkt_dma);
+               kfree(pp);
+       }
+       ata_port_stop(ap);
+}
+
+static void qs_host_stop(struct ata_host_set *host_set)
+{
+       void __iomem *mmio_base = host_set->mmio_base;
+       struct pci_dev *pdev = to_pci_dev(host_set->dev);
+
+       writeb(0, mmio_base + QS_HCT_CTRL); /* disable host interrupts */
+       writeb(QS_CNFG3_GSRST, mmio_base + QS_HCF_CNFG3); /* global reset */
+
+       pci_iounmap(pdev, mmio_base);
+}
+
+static void qs_host_init(unsigned int chip_id, struct ata_probe_ent *pe)
+{
+       void __iomem *mmio_base = pe->mmio_base;
+       unsigned int port_no;
+
+       writeb(0, mmio_base + QS_HCT_CTRL); /* disable host interrupts */
+       writeb(QS_CNFG3_GSRST, mmio_base + QS_HCF_CNFG3); /* global reset */
+
+       /* reset each channel in turn */
+       for (port_no = 0; port_no < pe->n_ports; ++port_no) {
+               u8 __iomem *chan = mmio_base + (port_no * 0x4000);
+               writeb(QS_CTR1_RDEV|QS_CTR1_RCHN, chan + QS_CCT_CTR1);
+               writeb(QS_CTR0_REG, chan + QS_CCT_CTR0);
+               readb(chan + QS_CCT_CTR0);        /* flush */
+       }
+       writeb(QS_SERD3_PHY_ENA, mmio_base + QS_HVS_SERD3); /* enable phy */
+
+       for (port_no = 0; port_no < pe->n_ports; ++port_no) {
+               u8 __iomem *chan = mmio_base + (port_no * 0x4000);
+               /* set FIFO depths to same settings as Windows driver */
+               writew(32, chan + QS_CFC_HUFT);
+               writew(32, chan + QS_CFC_HDFT);
+               writew(10, chan + QS_CFC_DUFT);
+               writew( 8, chan + QS_CFC_DDFT);
+               /* set CPB size in bytes, as a power of two */
+               writeb(QS_CPB_ORDER,    chan + QS_CCF_CSEP);
+       }
+       writeb(1, mmio_base + QS_HCT_CTRL); /* enable host interrupts */
+}
+
+/*
+ * The QStor understands 64-bit buses, and uses 64-bit fields
+ * for DMA pointers regardless of bus width.  We just have to
+ * make sure our DMA masks are set appropriately for whatever
+ * bridge lies between us and the QStor, and then the DMA mapping
+ * code will ensure we only ever "see" appropriate buffer addresses.
+ * If we're 32-bit limited somewhere, then our 64-bit fields will
+ * just end up with zeros in the upper 32-bits, without any special
+ * logic required outside of this routine (below).
+ */
+static int qs_set_dma_masks(struct pci_dev *pdev, void __iomem *mmio_base)
+{
+       u32 bus_info = readl(mmio_base + QS_HID_HPHY);
+       int rc, have_64bit_bus = (bus_info & QS_HPHY_64BIT);
+
+       if (have_64bit_bus &&
+           !pci_set_dma_mask(pdev, DMA_64BIT_MASK)) {
+               rc = pci_set_consistent_dma_mask(pdev, DMA_64BIT_MASK);
+               if (rc) {
+                       rc = pci_set_consistent_dma_mask(pdev, DMA_32BIT_MASK);
+                       if (rc) {
+                               dev_printk(KERN_ERR, &pdev->dev,
+                                          "64-bit DMA enable failed\n");
+                               return rc;
+                       }
+               }
+       } else {
+               rc = pci_set_dma_mask(pdev, DMA_32BIT_MASK);
+               if (rc) {
+                       dev_printk(KERN_ERR, &pdev->dev,
+                               "32-bit DMA enable failed\n");
+                       return rc;
+               }
+               rc = pci_set_consistent_dma_mask(pdev, DMA_32BIT_MASK);
+               if (rc) {
+                       dev_printk(KERN_ERR, &pdev->dev,
+                               "32-bit consistent DMA enable failed\n");
+                       return rc;
+               }
+       }
+       return 0;
+}
+
+static int qs_ata_init_one(struct pci_dev *pdev,
+                               const struct pci_device_id *ent)
+{
+       static int printed_version;
+       struct ata_probe_ent *probe_ent = NULL;
+       void __iomem *mmio_base;
+       unsigned int board_idx = (unsigned int) ent->driver_data;
+       int rc, port_no;
+
+       if (!printed_version++)
+               dev_printk(KERN_DEBUG, &pdev->dev, "version " DRV_VERSION "\n");
+
+       rc = pci_enable_device(pdev);
+       if (rc)
+               return rc;
+
+       rc = pci_request_regions(pdev, DRV_NAME);
+       if (rc)
+               goto err_out;
+
+       if ((pci_resource_flags(pdev, 4) & IORESOURCE_MEM) == 0) {
+               rc = -ENODEV;
+               goto err_out_regions;
+       }
+
+       mmio_base = pci_iomap(pdev, 4, 0);
+       if (mmio_base == NULL) {
+               rc = -ENOMEM;
+               goto err_out_regions;
+       }
+
+       rc = qs_set_dma_masks(pdev, mmio_base);
+       if (rc)
+               goto err_out_iounmap;
+
+       probe_ent = kmalloc(sizeof(*probe_ent), GFP_KERNEL);
+       if (probe_ent == NULL) {
+               rc = -ENOMEM;
+               goto err_out_iounmap;
+       }
+
+       memset(probe_ent, 0, sizeof(*probe_ent));
+       probe_ent->dev = pci_dev_to_dev(pdev);
+       INIT_LIST_HEAD(&probe_ent->node);
+
+       probe_ent->sht          = qs_port_info[board_idx].sht;
+       probe_ent->host_flags   = qs_port_info[board_idx].host_flags;
+       probe_ent->pio_mask     = qs_port_info[board_idx].pio_mask;
+       probe_ent->mwdma_mask   = qs_port_info[board_idx].mwdma_mask;
+       probe_ent->udma_mask    = qs_port_info[board_idx].udma_mask;
+       probe_ent->port_ops     = qs_port_info[board_idx].port_ops;
+
+       probe_ent->irq          = pdev->irq;
+       probe_ent->irq_flags    = IRQF_SHARED;
+       probe_ent->mmio_base    = mmio_base;
+       probe_ent->n_ports      = QS_PORTS;
+
+       for (port_no = 0; port_no < probe_ent->n_ports; ++port_no) {
+               unsigned long chan = (unsigned long)mmio_base +
+                                                       (port_no * 0x4000);
+               qs_ata_setup_port(&probe_ent->port[port_no], chan);
+       }
+
+       pci_set_master(pdev);
+
+       /* initialize adapter */
+       qs_host_init(board_idx, probe_ent);
+
+       rc = ata_device_add(probe_ent);
+       kfree(probe_ent);
+       if (rc != QS_PORTS)
+               goto err_out_iounmap;
+       return 0;
+
+err_out_iounmap:
+       pci_iounmap(pdev, mmio_base);
+err_out_regions:
+       pci_release_regions(pdev);
+err_out:
+       pci_disable_device(pdev);
+       return rc;
+}
+
+static int __init qs_ata_init(void)
+{
+       return pci_register_driver(&qs_ata_pci_driver);
+}
+
+static void __exit qs_ata_exit(void)
+{
+       pci_unregister_driver(&qs_ata_pci_driver);
+}
+
+MODULE_AUTHOR("Mark Lord");
+MODULE_DESCRIPTION("Pacific Digital Corporation QStor SATA low-level driver");
+MODULE_LICENSE("GPL");
+MODULE_DEVICE_TABLE(pci, qs_ata_pci_tbl);
+MODULE_VERSION(DRV_VERSION);
+
+module_init(qs_ata_init);
+module_exit(qs_ata_exit);
diff --git a/drivers/ata/sata_sil.c b/drivers/ata/sata_sil.c
new file mode 100644 (file)
index 0000000..907faa8
--- /dev/null
@@ -0,0 +1,723 @@
+/*
+ *  sata_sil.c - Silicon Image SATA
+ *
+ *  Maintained by:  Jeff Garzik <jgarzik@pobox.com>
+ *                 Please ALWAYS copy linux-ide@vger.kernel.org
+ *                 on emails.
+ *
+ *  Copyright 2003-2005 Red Hat, Inc.
+ *  Copyright 2003 Benjamin Herrenschmidt
+ *
+ *
+ *  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.*
+ *
+ *  Documentation for SiI 3112:
+ *  http://gkernel.sourceforge.net/specs/sii/3112A_SiI-DS-0095-B2.pdf.bz2
+ *
+ *  Other errata and documentation available under NDA.
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/pci.h>
+#include <linux/init.h>
+#include <linux/blkdev.h>
+#include <linux/delay.h>
+#include <linux/interrupt.h>
+#include <linux/device.h>
+#include <scsi/scsi_host.h>
+#include <linux/libata.h>
+
+#define DRV_NAME       "sata_sil"
+#define DRV_VERSION    "2.0"
+
+enum {
+       /*
+        * host flags
+        */
+       SIL_FLAG_NO_SATA_IRQ    = (1 << 28),
+       SIL_FLAG_RERR_ON_DMA_ACT = (1 << 29),
+       SIL_FLAG_MOD15WRITE     = (1 << 30),
+
+       SIL_DFL_HOST_FLAGS      = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
+                                 ATA_FLAG_MMIO | ATA_FLAG_HRST_TO_RESUME,
+
+       /*
+        * Controller IDs
+        */
+       sil_3112                = 0,
+       sil_3112_no_sata_irq    = 1,
+       sil_3512                = 2,
+       sil_3114                = 3,
+
+       /*
+        * Register offsets
+        */
+       SIL_SYSCFG              = 0x48,
+
+       /*
+        * Register bits
+        */
+       /* SYSCFG */
+       SIL_MASK_IDE0_INT       = (1 << 22),
+       SIL_MASK_IDE1_INT       = (1 << 23),
+       SIL_MASK_IDE2_INT       = (1 << 24),
+       SIL_MASK_IDE3_INT       = (1 << 25),
+       SIL_MASK_2PORT          = SIL_MASK_IDE0_INT | SIL_MASK_IDE1_INT,
+       SIL_MASK_4PORT          = SIL_MASK_2PORT |
+                                 SIL_MASK_IDE2_INT | SIL_MASK_IDE3_INT,
+
+       /* BMDMA/BMDMA2 */
+       SIL_INTR_STEERING       = (1 << 1),
+
+       SIL_DMA_ENABLE          = (1 << 0),  /* DMA run switch */
+       SIL_DMA_RDWR            = (1 << 3),  /* DMA Rd-Wr */
+       SIL_DMA_SATA_IRQ        = (1 << 4),  /* OR of all SATA IRQs */
+       SIL_DMA_ACTIVE          = (1 << 16), /* DMA running */
+       SIL_DMA_ERROR           = (1 << 17), /* PCI bus error */
+       SIL_DMA_COMPLETE        = (1 << 18), /* cmd complete / IRQ pending */
+       SIL_DMA_N_SATA_IRQ      = (1 << 6),  /* SATA_IRQ for the next channel */
+       SIL_DMA_N_ACTIVE        = (1 << 24), /* ACTIVE for the next channel */
+       SIL_DMA_N_ERROR         = (1 << 25), /* ERROR for the next channel */
+       SIL_DMA_N_COMPLETE      = (1 << 26), /* COMPLETE for the next channel */
+
+       /* SIEN */
+       SIL_SIEN_N              = (1 << 16), /* triggered by SError.N */
+
+       /*
+        * Others
+        */
+       SIL_QUIRK_MOD15WRITE    = (1 << 0),
+       SIL_QUIRK_UDMA5MAX      = (1 << 1),
+};
+
+static int sil_init_one (struct pci_dev *pdev, const struct pci_device_id *ent);
+static int sil_pci_device_resume(struct pci_dev *pdev);
+static void sil_dev_config(struct ata_port *ap, struct ata_device *dev);
+static u32 sil_scr_read (struct ata_port *ap, unsigned int sc_reg);
+static void sil_scr_write (struct ata_port *ap, unsigned int sc_reg, u32 val);
+static void sil_post_set_mode (struct ata_port *ap);
+static irqreturn_t sil_interrupt(int irq, void *dev_instance,
+                                struct pt_regs *regs);
+static void sil_freeze(struct ata_port *ap);
+static void sil_thaw(struct ata_port *ap);
+
+
+static const struct pci_device_id sil_pci_tbl[] = {
+       { 0x1095, 0x3112, PCI_ANY_ID, PCI_ANY_ID, 0, 0, sil_3112 },
+       { 0x1095, 0x0240, PCI_ANY_ID, PCI_ANY_ID, 0, 0, sil_3112 },
+       { 0x1095, 0x3512, PCI_ANY_ID, PCI_ANY_ID, 0, 0, sil_3512 },
+       { 0x1095, 0x3114, PCI_ANY_ID, PCI_ANY_ID, 0, 0, sil_3114 },
+       { 0x1002, 0x436e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, sil_3112 },
+       { 0x1002, 0x4379, PCI_ANY_ID, PCI_ANY_ID, 0, 0, sil_3112_no_sata_irq },
+       { 0x1002, 0x437a, PCI_ANY_ID, PCI_ANY_ID, 0, 0, sil_3112_no_sata_irq },
+       { }     /* terminate list */
+};
+
+
+/* TODO firmware versions should be added - eric */
+static const struct sil_drivelist {
+       const char * product;
+       unsigned int quirk;
+} sil_blacklist [] = {
+       { "ST320012AS",         SIL_QUIRK_MOD15WRITE },
+       { "ST330013AS",         SIL_QUIRK_MOD15WRITE },
+       { "ST340017AS",         SIL_QUIRK_MOD15WRITE },
+       { "ST360015AS",         SIL_QUIRK_MOD15WRITE },
+       { "ST380023AS",         SIL_QUIRK_MOD15WRITE },
+       { "ST3120023AS",        SIL_QUIRK_MOD15WRITE },
+       { "ST340014ASL",        SIL_QUIRK_MOD15WRITE },
+       { "ST360014ASL",        SIL_QUIRK_MOD15WRITE },
+       { "ST380011ASL",        SIL_QUIRK_MOD15WRITE },
+       { "ST3120022ASL",       SIL_QUIRK_MOD15WRITE },
+       { "ST3160021ASL",       SIL_QUIRK_MOD15WRITE },
+       { "Maxtor 4D060H3",     SIL_QUIRK_UDMA5MAX },
+       { }
+};
+
+static struct pci_driver sil_pci_driver = {
+       .name                   = DRV_NAME,
+       .id_table               = sil_pci_tbl,
+       .probe                  = sil_init_one,
+       .remove                 = ata_pci_remove_one,
+       .suspend                = ata_pci_device_suspend,
+       .resume                 = sil_pci_device_resume,
+};
+
+static struct scsi_host_template sil_sht = {
+       .module                 = THIS_MODULE,
+       .name                   = DRV_NAME,
+       .ioctl                  = ata_scsi_ioctl,
+       .queuecommand           = ata_scsi_queuecmd,
+       .can_queue              = ATA_DEF_QUEUE,
+       .this_id                = ATA_SHT_THIS_ID,
+       .sg_tablesize           = LIBATA_MAX_PRD,
+       .cmd_per_lun            = ATA_SHT_CMD_PER_LUN,
+       .emulated               = ATA_SHT_EMULATED,
+       .use_clustering         = ATA_SHT_USE_CLUSTERING,
+       .proc_name              = DRV_NAME,
+       .dma_boundary           = ATA_DMA_BOUNDARY,
+       .slave_configure        = ata_scsi_slave_config,
+       .slave_destroy          = ata_scsi_slave_destroy,
+       .bios_param             = ata_std_bios_param,
+       .suspend                = ata_scsi_device_suspend,
+       .resume                 = ata_scsi_device_resume,
+};
+
+static const struct ata_port_operations sil_ops = {
+       .port_disable           = ata_port_disable,
+       .dev_config             = sil_dev_config,
+       .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,
+       .post_set_mode          = sil_post_set_mode,
+       .bmdma_setup            = ata_bmdma_setup,
+       .bmdma_start            = ata_bmdma_start,
+       .bmdma_stop             = ata_bmdma_stop,
+       .bmdma_status           = ata_bmdma_status,
+       .qc_prep                = ata_qc_prep,
+       .qc_issue               = ata_qc_issue_prot,
+       .data_xfer              = ata_mmio_data_xfer,
+       .freeze                 = sil_freeze,
+       .thaw                   = sil_thaw,
+       .error_handler          = ata_bmdma_error_handler,
+       .post_internal_cmd      = ata_bmdma_post_internal_cmd,
+       .irq_handler            = sil_interrupt,
+       .irq_clear              = ata_bmdma_irq_clear,
+       .scr_read               = sil_scr_read,
+       .scr_write              = sil_scr_write,
+       .port_start             = ata_port_start,
+       .port_stop              = ata_port_stop,
+       .host_stop              = ata_pci_host_stop,
+};
+
+static const struct ata_port_info sil_port_info[] = {
+       /* sil_3112 */
+       {
+               .sht            = &sil_sht,
+               .host_flags     = SIL_DFL_HOST_FLAGS | SIL_FLAG_MOD15WRITE,
+               .pio_mask       = 0x1f,                 /* pio0-4 */
+               .mwdma_mask     = 0x07,                 /* mwdma0-2 */
+               .udma_mask      = 0x3f,                 /* udma0-5 */
+               .port_ops       = &sil_ops,
+       },
+       /* sil_3112_no_sata_irq */
+       {
+               .sht            = &sil_sht,
+               .host_flags     = SIL_DFL_HOST_FLAGS | SIL_FLAG_MOD15WRITE |
+                                 SIL_FLAG_NO_SATA_IRQ,
+               .pio_mask       = 0x1f,                 /* pio0-4 */
+               .mwdma_mask     = 0x07,                 /* mwdma0-2 */
+               .udma_mask      = 0x3f,                 /* udma0-5 */
+               .port_ops       = &sil_ops,
+       },
+       /* sil_3512 */
+       {
+               .sht            = &sil_sht,
+               .host_flags     = SIL_DFL_HOST_FLAGS | SIL_FLAG_RERR_ON_DMA_ACT,
+               .pio_mask       = 0x1f,                 /* pio0-4 */
+               .mwdma_mask     = 0x07,                 /* mwdma0-2 */
+               .udma_mask      = 0x3f,                 /* udma0-5 */
+               .port_ops       = &sil_ops,
+       },
+       /* sil_3114 */
+       {
+               .sht            = &sil_sht,
+               .host_flags     = SIL_DFL_HOST_FLAGS | SIL_FLAG_RERR_ON_DMA_ACT,
+               .pio_mask       = 0x1f,                 /* pio0-4 */
+               .mwdma_mask     = 0x07,                 /* mwdma0-2 */
+               .udma_mask      = 0x3f,                 /* udma0-5 */
+               .port_ops       = &sil_ops,
+       },
+};
+
+/* per-port register offsets */
+/* TODO: we can probably calculate rather than use a table */
+static const struct {
+       unsigned long tf;       /* ATA taskfile register block */
+       unsigned long ctl;      /* ATA control/altstatus register block */
+       unsigned long bmdma;    /* DMA register block */
+       unsigned long bmdma2;   /* DMA register block #2 */
+       unsigned long fifo_cfg; /* FIFO Valid Byte Count and Control */
+       unsigned long scr;      /* SATA control register block */
+       unsigned long sien;     /* SATA Interrupt Enable register */
+       unsigned long xfer_mode;/* data transfer mode register */
+       unsigned long sfis_cfg; /* SATA FIS reception config register */
+} sil_port[] = {
+       /* port 0 ... */
+       { 0x80, 0x8A, 0x00, 0x10, 0x40, 0x100, 0x148, 0xb4, 0x14c },
+       { 0xC0, 0xCA, 0x08, 0x18, 0x44, 0x180, 0x1c8, 0xf4, 0x1cc },
+       { 0x280, 0x28A, 0x200, 0x210, 0x240, 0x300, 0x348, 0x2b4, 0x34c },
+       { 0x2C0, 0x2CA, 0x208, 0x218, 0x244, 0x380, 0x3c8, 0x2f4, 0x3cc },
+       /* ... port 3 */
+};
+
+MODULE_AUTHOR("Jeff Garzik");
+MODULE_DESCRIPTION("low-level driver for Silicon Image SATA controller");
+MODULE_LICENSE("GPL");
+MODULE_DEVICE_TABLE(pci, sil_pci_tbl);
+MODULE_VERSION(DRV_VERSION);
+
+static int slow_down = 0;
+module_param(slow_down, int, 0444);
+MODULE_PARM_DESC(slow_down, "Sledgehammer used to work around random problems, by limiting commands to 15 sectors (0=off, 1=on)");
+
+
+static unsigned char sil_get_device_cache_line(struct pci_dev *pdev)
+{
+       u8 cache_line = 0;
+       pci_read_config_byte(pdev, PCI_CACHE_LINE_SIZE, &cache_line);
+       return cache_line;
+}
+
+static void sil_post_set_mode (struct ata_port *ap)
+{
+       struct ata_host_set *host_set = ap->host_set;
+       struct ata_device *dev;
+       void __iomem *addr =
+               host_set->mmio_base + sil_port[ap->port_no].xfer_mode;
+       u32 tmp, dev_mode[2];
+       unsigned int i;
+
+       for (i = 0; i < 2; i++) {
+               dev = &ap->device[i];
+               if (!ata_dev_enabled(dev))
+                       dev_mode[i] = 0;        /* PIO0/1/2 */
+               else if (dev->flags & ATA_DFLAG_PIO)
+                       dev_mode[i] = 1;        /* PIO3/4 */
+               else
+                       dev_mode[i] = 3;        /* UDMA */
+               /* value 2 indicates MDMA */
+       }
+
+       tmp = readl(addr);
+       tmp &= ~((1<<5) | (1<<4) | (1<<1) | (1<<0));
+       tmp |= dev_mode[0];
+       tmp |= (dev_mode[1] << 4);
+       writel(tmp, addr);
+       readl(addr);    /* flush */
+}
+
+static inline unsigned long sil_scr_addr(struct ata_port *ap, unsigned int sc_reg)
+{
+       unsigned long offset = ap->ioaddr.scr_addr;
+
+       switch (sc_reg) {
+       case SCR_STATUS:
+               return offset + 4;
+       case SCR_ERROR:
+               return offset + 8;
+       case SCR_CONTROL:
+               return offset;
+       default:
+               /* do nothing */
+               break;
+       }
+
+       return 0;
+}
+
+static u32 sil_scr_read (struct ata_port *ap, unsigned int sc_reg)
+{
+       void __iomem *mmio = (void __iomem *) sil_scr_addr(ap, sc_reg);
+       if (mmio)
+               return readl(mmio);
+       return 0xffffffffU;
+}
+
+static void sil_scr_write (struct ata_port *ap, unsigned int sc_reg, u32 val)
+{
+       void *mmio = (void __iomem *) sil_scr_addr(ap, sc_reg);
+       if (mmio)
+               writel(val, mmio);
+}
+
+static void sil_host_intr(struct ata_port *ap, u32 bmdma2)
+{
+       struct ata_queued_cmd *qc = ata_qc_from_tag(ap, ap->active_tag);
+       u8 status;
+
+       if (unlikely(bmdma2 & SIL_DMA_SATA_IRQ)) {
+               u32 serror;
+
+               /* SIEN doesn't mask SATA IRQs on some 3112s.  Those
+                * controllers continue to assert IRQ as long as
+                * SError bits are pending.  Clear SError immediately.
+                */
+               serror = sil_scr_read(ap, SCR_ERROR);
+               sil_scr_write(ap, SCR_ERROR, serror);
+
+               /* Trigger hotplug and accumulate SError only if the
+                * port isn't already frozen.  Otherwise, PHY events
+                * during hardreset makes controllers with broken SIEN
+                * repeat probing needlessly.
+                */
+               if (!(ap->pflags & ATA_PFLAG_FROZEN)) {
+                       ata_ehi_hotplugged(&ap->eh_info);
+                       ap->eh_info.serror |= serror;
+               }
+
+               goto freeze;
+       }
+
+       if (unlikely(!qc || qc->tf.ctl & ATA_NIEN))
+               goto freeze;
+
+       /* Check whether we are expecting interrupt in this state */
+       switch (ap->hsm_task_state) {
+       case HSM_ST_FIRST:
+               /* Some pre-ATAPI-4 devices assert INTRQ
+                * at this state when ready to receive CDB.
+                */
+
+               /* Check the ATA_DFLAG_CDB_INTR flag is enough here.
+                * The flag was turned on only for atapi devices.
+                * No need to check is_atapi_taskfile(&qc->tf) again.
+                */
+               if (!(qc->dev->flags & ATA_DFLAG_CDB_INTR))
+                       goto err_hsm;
+               break;
+       case HSM_ST_LAST:
+               if (qc->tf.protocol == ATA_PROT_DMA ||
+                   qc->tf.protocol == ATA_PROT_ATAPI_DMA) {
+                       /* clear DMA-Start bit */
+                       ap->ops->bmdma_stop(qc);
+
+                       if (bmdma2 & SIL_DMA_ERROR) {
+                               qc->err_mask |= AC_ERR_HOST_BUS;
+                               ap->hsm_task_state = HSM_ST_ERR;
+                       }
+               }
+               break;
+       case HSM_ST:
+               break;
+       default:
+               goto err_hsm;
+       }
+
+       /* check main status, clearing INTRQ */
+       status = ata_chk_status(ap);
+       if (unlikely(status & ATA_BUSY))
+               goto err_hsm;
+
+       /* ack bmdma irq events */
+       ata_bmdma_irq_clear(ap);
+
+       /* kick HSM in the ass */
+       ata_hsm_move(ap, qc, status, 0);
+
+       return;
+
+ err_hsm:
+       qc->err_mask |= AC_ERR_HSM;
+ freeze:
+       ata_port_freeze(ap);
+}
+
+static irqreturn_t sil_interrupt(int irq, void *dev_instance,
+                                struct pt_regs *regs)
+{
+       struct ata_host_set *host_set = dev_instance;
+       void __iomem *mmio_base = host_set->mmio_base;
+       int handled = 0;
+       int i;
+
+       spin_lock(&host_set->lock);
+
+       for (i = 0; i < host_set->n_ports; i++) {
+               struct ata_port *ap = host_set->ports[i];
+               u32 bmdma2 = readl(mmio_base + sil_port[ap->port_no].bmdma2);
+
+               if (unlikely(!ap || ap->flags & ATA_FLAG_DISABLED))
+                       continue;
+
+               /* turn off SATA_IRQ if not supported */
+               if (ap->flags & SIL_FLAG_NO_SATA_IRQ)
+                       bmdma2 &= ~SIL_DMA_SATA_IRQ;
+
+               if (bmdma2 == 0xffffffff ||
+                   !(bmdma2 & (SIL_DMA_COMPLETE | SIL_DMA_SATA_IRQ)))
+                       continue;
+
+               sil_host_intr(ap, bmdma2);
+               handled = 1;
+       }
+
+       spin_unlock(&host_set->lock);
+
+       return IRQ_RETVAL(handled);
+}
+
+static void sil_freeze(struct ata_port *ap)
+{
+       void __iomem *mmio_base = ap->host_set->mmio_base;
+       u32 tmp;
+
+       /* global IRQ mask doesn't block SATA IRQ, turn off explicitly */
+       writel(0, mmio_base + sil_port[ap->port_no].sien);
+
+       /* plug IRQ */
+       tmp = readl(mmio_base + SIL_SYSCFG);
+       tmp |= SIL_MASK_IDE0_INT << ap->port_no;
+       writel(tmp, mmio_base + SIL_SYSCFG);
+       readl(mmio_base + SIL_SYSCFG);  /* flush */
+}
+
+static void sil_thaw(struct ata_port *ap)
+{
+       void __iomem *mmio_base = ap->host_set->mmio_base;
+       u32 tmp;
+
+       /* clear IRQ */
+       ata_chk_status(ap);
+       ata_bmdma_irq_clear(ap);
+
+       /* turn on SATA IRQ if supported */
+       if (!(ap->flags & SIL_FLAG_NO_SATA_IRQ))
+               writel(SIL_SIEN_N, mmio_base + sil_port[ap->port_no].sien);
+
+       /* turn on IRQ */
+       tmp = readl(mmio_base + SIL_SYSCFG);
+       tmp &= ~(SIL_MASK_IDE0_INT << ap->port_no);
+       writel(tmp, mmio_base + SIL_SYSCFG);
+}
+
+/**
+ *     sil_dev_config - Apply device/host-specific errata fixups
+ *     @ap: Port containing device to be examined
+ *     @dev: Device to be examined
+ *
+ *     After the IDENTIFY [PACKET] DEVICE step is complete, and a
+ *     device is known to be present, this function is called.
+ *     We apply two errata fixups which are specific to Silicon Image,
+ *     a Seagate and a Maxtor fixup.
+ *
+ *     For certain Seagate devices, we must limit the maximum sectors
+ *     to under 8K.
+ *
+ *     For certain Maxtor devices, we must not program the drive
+ *     beyond udma5.
+ *
+ *     Both fixups are unfairly pessimistic.  As soon as I get more
+ *     information on these errata, I will create a more exhaustive
+ *     list, and apply the fixups to only the specific
+ *     devices/hosts/firmwares that need it.
+ *
+ *     20040111 - Seagate drives affected by the Mod15Write bug are blacklisted
+ *     The Maxtor quirk is in the blacklist, but I'm keeping the original
+ *     pessimistic fix for the following reasons...
+ *     - There seems to be less info on it, only one device gleaned off the
+ *     Windows driver, maybe only one is affected.  More info would be greatly
+ *     appreciated.
+ *     - But then again UDMA5 is hardly anything to complain about
+ */
+static void sil_dev_config(struct ata_port *ap, struct ata_device *dev)
+{
+       unsigned int n, quirks = 0;
+       unsigned char model_num[41];
+
+       ata_id_c_string(dev->id, model_num, ATA_ID_PROD_OFS, sizeof(model_num));
+
+       for (n = 0; sil_blacklist[n].product; n++)
+               if (!strcmp(sil_blacklist[n].product, model_num)) {
+                       quirks = sil_blacklist[n].quirk;
+                       break;
+               }
+
+       /* limit requests to 15 sectors */
+       if (slow_down ||
+           ((ap->flags & SIL_FLAG_MOD15WRITE) &&
+            (quirks & SIL_QUIRK_MOD15WRITE))) {
+               ata_dev_printk(dev, KERN_INFO, "applying Seagate errata fix "
+                              "(mod15write workaround)\n");
+               dev->max_sectors = 15;
+               return;
+       }
+
+       /* limit to udma5 */
+       if (quirks & SIL_QUIRK_UDMA5MAX) {
+               ata_dev_printk(dev, KERN_INFO,
+                              "applying Maxtor errata fix %s\n", model_num);
+               dev->udma_mask &= ATA_UDMA5;
+               return;
+       }
+}
+
+static void sil_init_controller(struct pci_dev *pdev,
+                               int n_ports, unsigned long host_flags,
+                               void __iomem *mmio_base)
+{
+       u8 cls;
+       u32 tmp;
+       int i;
+
+       /* Initialize FIFO PCI bus arbitration */
+       cls = sil_get_device_cache_line(pdev);
+       if (cls) {
+               cls >>= 3;
+               cls++;  /* cls = (line_size/8)+1 */
+               for (i = 0; i < n_ports; i++)
+                       writew(cls << 8 | cls,
+                              mmio_base + sil_port[i].fifo_cfg);
+       } else
+               dev_printk(KERN_WARNING, &pdev->dev,
+                          "cache line size not set.  Driver may not function\n");
+
+       /* Apply R_ERR on DMA activate FIS errata workaround */
+       if (host_flags & SIL_FLAG_RERR_ON_DMA_ACT) {
+               int cnt;
+
+               for (i = 0, cnt = 0; i < n_ports; i++) {
+                       tmp = readl(mmio_base + sil_port[i].sfis_cfg);
+                       if ((tmp & 0x3) != 0x01)
+                               continue;
+                       if (!cnt)
+                               dev_printk(KERN_INFO, &pdev->dev,
+                                          "Applying R_ERR on DMA activate "
+                                          "FIS errata fix\n");
+                       writel(tmp & ~0x3, mmio_base + sil_port[i].sfis_cfg);
+                       cnt++;
+               }
+       }
+
+       if (n_ports == 4) {
+               /* flip the magic "make 4 ports work" bit */
+               tmp = readl(mmio_base + sil_port[2].bmdma);
+               if ((tmp & SIL_INTR_STEERING) == 0)
+                       writel(tmp | SIL_INTR_STEERING,
+                              mmio_base + sil_port[2].bmdma);
+       }
+}
+
+static int sil_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
+{
+       static int printed_version;
+       struct ata_probe_ent *probe_ent = NULL;
+       unsigned long base;
+       void __iomem *mmio_base;
+       int rc;
+       unsigned int i;
+       int pci_dev_busy = 0;
+
+       if (!printed_version++)
+               dev_printk(KERN_DEBUG, &pdev->dev, "version " DRV_VERSION "\n");
+
+       rc = pci_enable_device(pdev);
+       if (rc)
+               return rc;
+
+       rc = pci_request_regions(pdev, DRV_NAME);
+       if (rc) {
+               pci_dev_busy = 1;
+               goto err_out;
+       }
+
+       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;
+
+       probe_ent = kzalloc(sizeof(*probe_ent), GFP_KERNEL);
+       if (probe_ent == NULL) {
+               rc = -ENOMEM;
+               goto err_out_regions;
+       }
+
+       INIT_LIST_HEAD(&probe_ent->node);
+       probe_ent->dev = pci_dev_to_dev(pdev);
+       probe_ent->port_ops = sil_port_info[ent->driver_data].port_ops;
+       probe_ent->sht = sil_port_info[ent->driver_data].sht;
+       probe_ent->n_ports = (ent->driver_data == sil_3114) ? 4 : 2;
+       probe_ent->pio_mask = sil_port_info[ent->driver_data].pio_mask;
+       probe_ent->mwdma_mask = sil_port_info[ent->driver_data].mwdma_mask;
+       probe_ent->udma_mask = sil_port_info[ent->driver_data].udma_mask;
+               probe_ent->irq = pdev->irq;
+               probe_ent->irq_flags = IRQF_SHARED;
+       probe_ent->host_flags = sil_port_info[ent->driver_data].host_flags;
+
+       mmio_base = pci_iomap(pdev, 5, 0);
+       if (mmio_base == NULL) {
+               rc = -ENOMEM;
+               goto err_out_free_ent;
+       }
+
+       probe_ent->mmio_base = mmio_base;
+
+       base = (unsigned long) mmio_base;
+
+       for (i = 0; i < probe_ent->n_ports; i++) {
+               probe_ent->port[i].cmd_addr = base + sil_port[i].tf;
+               probe_ent->port[i].altstatus_addr =
+               probe_ent->port[i].ctl_addr = base + sil_port[i].ctl;
+               probe_ent->port[i].bmdma_addr = base + sil_port[i].bmdma;
+               probe_ent->port[i].scr_addr = base + sil_port[i].scr;
+               ata_std_ports(&probe_ent->port[i]);
+       }
+
+       sil_init_controller(pdev, probe_ent->n_ports, probe_ent->host_flags,
+                           mmio_base);
+
+       pci_set_master(pdev);
+
+       /* FIXME: check ata_device_add return value */
+       ata_device_add(probe_ent);
+       kfree(probe_ent);
+
+       return 0;
+
+err_out_free_ent:
+       kfree(probe_ent);
+err_out_regions:
+       pci_release_regions(pdev);
+err_out:
+       if (!pci_dev_busy)
+               pci_disable_device(pdev);
+       return rc;
+}
+
+static int sil_pci_device_resume(struct pci_dev *pdev)
+{
+       struct ata_host_set *host_set = dev_get_drvdata(&pdev->dev);
+
+       ata_pci_device_do_resume(pdev);
+       sil_init_controller(pdev, host_set->n_ports, host_set->ports[0]->flags,
+                           host_set->mmio_base);
+       ata_host_set_resume(host_set);
+
+       return 0;
+}
+
+static int __init sil_init(void)
+{
+       return pci_register_driver(&sil_pci_driver);
+}
+
+static void __exit sil_exit(void)
+{
+       pci_unregister_driver(&sil_pci_driver);
+}
+
+
+module_init(sil_init);
+module_exit(sil_exit);
diff --git a/drivers/ata/sata_sil24.c b/drivers/ata/sata_sil24.c
new file mode 100644 (file)
index 0000000..3a0161d
--- /dev/null
@@ -0,0 +1,1222 @@
+/*
+ * sata_sil24.c - Driver for Silicon Image 3124/3132 SATA-2 controllers
+ *
+ * Copyright 2005  Tejun Heo
+ *
+ * Based on preview driver from Silicon Image.
+ *
+ * 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.
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/pci.h>
+#include <linux/blkdev.h>
+#include <linux/delay.h>
+#include <linux/interrupt.h>
+#include <linux/dma-mapping.h>
+#include <linux/device.h>
+#include <scsi/scsi_host.h>
+#include <scsi/scsi_cmnd.h>
+#include <linux/libata.h>
+#include <asm/io.h>
+
+#define DRV_NAME       "sata_sil24"
+#define DRV_VERSION    "0.3"
+
+/*
+ * Port request block (PRB) 32 bytes
+ */
+struct sil24_prb {
+       __le16  ctrl;
+       __le16  prot;
+       __le32  rx_cnt;
+       u8      fis[6 * 4];
+};
+
+/*
+ * Scatter gather entry (SGE) 16 bytes
+ */
+struct sil24_sge {
+       __le64  addr;
+       __le32  cnt;
+       __le32  flags;
+};
+
+/*
+ * Port multiplier
+ */
+struct sil24_port_multiplier {
+       __le32  diag;
+       __le32  sactive;
+};
+
+enum {
+       /*
+        * Global controller registers (128 bytes @ BAR0)
+        */
+               /* 32 bit regs */
+       HOST_SLOT_STAT          = 0x00, /* 32 bit slot stat * 4 */
+       HOST_CTRL               = 0x40,
+       HOST_IRQ_STAT           = 0x44,
+       HOST_PHY_CFG            = 0x48,
+       HOST_BIST_CTRL          = 0x50,
+       HOST_BIST_PTRN          = 0x54,
+       HOST_BIST_STAT          = 0x58,
+       HOST_MEM_BIST_STAT      = 0x5c,
+       HOST_FLASH_CMD          = 0x70,
+               /* 8 bit regs */
+       HOST_FLASH_DATA         = 0x74,
+       HOST_TRANSITION_DETECT  = 0x75,
+       HOST_GPIO_CTRL          = 0x76,
+       HOST_I2C_ADDR           = 0x78, /* 32 bit */
+       HOST_I2C_DATA           = 0x7c,
+       HOST_I2C_XFER_CNT       = 0x7e,
+       HOST_I2C_CTRL           = 0x7f,
+
+       /* HOST_SLOT_STAT bits */
+       HOST_SSTAT_ATTN         = (1 << 31),
+
+       /* HOST_CTRL bits */
+       HOST_CTRL_M66EN         = (1 << 16), /* M66EN PCI bus signal */
+       HOST_CTRL_TRDY          = (1 << 17), /* latched PCI TRDY */
+       HOST_CTRL_STOP          = (1 << 18), /* latched PCI STOP */
+       HOST_CTRL_DEVSEL        = (1 << 19), /* latched PCI DEVSEL */
+       HOST_CTRL_REQ64         = (1 << 20), /* latched PCI REQ64 */
+       HOST_CTRL_GLOBAL_RST    = (1 << 31), /* global reset */
+
+       /*
+        * Port registers
+        * (8192 bytes @ +0x0000, +0x2000, +0x4000 and +0x6000 @ BAR2)
+        */
+       PORT_REGS_SIZE          = 0x2000,
+
+       PORT_LRAM               = 0x0000, /* 31 LRAM slots and PM regs */
+       PORT_LRAM_SLOT_SZ       = 0x0080, /* 32 bytes PRB + 2 SGE, ACT... */
+
+       PORT_PM                 = 0x0f80, /* 8 bytes PM * 16 (128 bytes) */
+               /* 32 bit regs */
+       PORT_CTRL_STAT          = 0x1000, /* write: ctrl-set, read: stat */
+       PORT_CTRL_CLR           = 0x1004, /* write: ctrl-clear */
+       PORT_IRQ_STAT           = 0x1008, /* high: status, low: interrupt */
+       PORT_IRQ_ENABLE_SET     = 0x1010, /* write: enable-set */
+       PORT_IRQ_ENABLE_CLR     = 0x1014, /* write: enable-clear */
+       PORT_ACTIVATE_UPPER_ADDR= 0x101c,
+       PORT_EXEC_FIFO          = 0x1020, /* command execution fifo */
+       PORT_CMD_ERR            = 0x1024, /* command error number */
+       PORT_FIS_CFG            = 0x1028,
+       PORT_FIFO_THRES         = 0x102c,
+               /* 16 bit regs */
+       PORT_DECODE_ERR_CNT     = 0x1040,
+       PORT_DECODE_ERR_THRESH  = 0x1042,
+       PORT_CRC_ERR_CNT        = 0x1044,
+       PORT_CRC_ERR_THRESH     = 0x1046,
+       PORT_HSHK_ERR_CNT       = 0x1048,
+       PORT_HSHK_ERR_THRESH    = 0x104a,
+               /* 32 bit regs */
+       PORT_PHY_CFG            = 0x1050,
+       PORT_SLOT_STAT          = 0x1800,
+       PORT_CMD_ACTIVATE       = 0x1c00, /* 64 bit cmd activate * 31 (248 bytes) */
+       PORT_EXEC_DIAG          = 0x1e00, /* 32bit exec diag * 16 (64 bytes, 0-10 used on 3124) */
+       PORT_PSD_DIAG           = 0x1e40, /* 32bit psd diag * 16 (64 bytes, 0-8 used on 3124) */
+       PORT_SCONTROL           = 0x1f00,
+       PORT_SSTATUS            = 0x1f04,
+       PORT_SERROR             = 0x1f08,
+       PORT_SACTIVE            = 0x1f0c,
+
+       /* PORT_CTRL_STAT bits */
+       PORT_CS_PORT_RST        = (1 << 0), /* port reset */
+       PORT_CS_DEV_RST         = (1 << 1), /* device reset */
+       PORT_CS_INIT            = (1 << 2), /* port initialize */
+       PORT_CS_IRQ_WOC         = (1 << 3), /* interrupt write one to clear */
+       PORT_CS_CDB16           = (1 << 5), /* 0=12b cdb, 1=16b cdb */
+       PORT_CS_RESUME          = (1 << 6), /* port resume */
+       PORT_CS_32BIT_ACTV      = (1 << 10), /* 32-bit activation */
+       PORT_CS_PM_EN           = (1 << 13), /* port multiplier enable */
+       PORT_CS_RDY             = (1 << 31), /* port ready to accept commands */
+
+       /* PORT_IRQ_STAT/ENABLE_SET/CLR */
+       /* bits[11:0] are masked */
+       PORT_IRQ_COMPLETE       = (1 << 0), /* command(s) completed */
+       PORT_IRQ_ERROR          = (1 << 1), /* command execution error */
+       PORT_IRQ_PORTRDY_CHG    = (1 << 2), /* port ready change */
+       PORT_IRQ_PWR_CHG        = (1 << 3), /* power management change */
+       PORT_IRQ_PHYRDY_CHG     = (1 << 4), /* PHY ready change */
+       PORT_IRQ_COMWAKE        = (1 << 5), /* COMWAKE received */
+       PORT_IRQ_UNK_FIS        = (1 << 6), /* unknown FIS received */
+       PORT_IRQ_DEV_XCHG       = (1 << 7), /* device exchanged */
+       PORT_IRQ_8B10B          = (1 << 8), /* 8b/10b decode error threshold */
+       PORT_IRQ_CRC            = (1 << 9), /* CRC error threshold */
+       PORT_IRQ_HANDSHAKE      = (1 << 10), /* handshake error threshold */
+       PORT_IRQ_SDB_NOTIFY     = (1 << 11), /* SDB notify received */
+
+       DEF_PORT_IRQ            = PORT_IRQ_COMPLETE | PORT_IRQ_ERROR |
+                                 PORT_IRQ_PHYRDY_CHG | PORT_IRQ_DEV_XCHG |
+                                 PORT_IRQ_UNK_FIS,
+
+       /* bits[27:16] are unmasked (raw) */
+       PORT_IRQ_RAW_SHIFT      = 16,
+       PORT_IRQ_MASKED_MASK    = 0x7ff,
+       PORT_IRQ_RAW_MASK       = (0x7ff << PORT_IRQ_RAW_SHIFT),
+
+       /* ENABLE_SET/CLR specific, intr steering - 2 bit field */
+       PORT_IRQ_STEER_SHIFT    = 30,
+       PORT_IRQ_STEER_MASK     = (3 << PORT_IRQ_STEER_SHIFT),
+
+       /* PORT_CMD_ERR constants */
+       PORT_CERR_DEV           = 1, /* Error bit in D2H Register FIS */
+       PORT_CERR_SDB           = 2, /* Error bit in SDB FIS */
+       PORT_CERR_DATA          = 3, /* Error in data FIS not detected by dev */
+       PORT_CERR_SEND          = 4, /* Initial cmd FIS transmission failure */
+       PORT_CERR_INCONSISTENT  = 5, /* Protocol mismatch */
+       PORT_CERR_DIRECTION     = 6, /* Data direction mismatch */
+       PORT_CERR_UNDERRUN      = 7, /* Ran out of SGEs while writing */
+       PORT_CERR_OVERRUN       = 8, /* Ran out of SGEs while reading */
+       PORT_CERR_PKT_PROT      = 11, /* DIR invalid in 1st PIO setup of ATAPI */
+       PORT_CERR_SGT_BOUNDARY  = 16, /* PLD ecode 00 - SGT not on qword boundary */
+       PORT_CERR_SGT_TGTABRT   = 17, /* PLD ecode 01 - target abort */
+       PORT_CERR_SGT_MSTABRT   = 18, /* PLD ecode 10 - master abort */
+       PORT_CERR_SGT_PCIPERR   = 19, /* PLD ecode 11 - PCI parity err while fetching SGT */
+       PORT_CERR_CMD_BOUNDARY  = 24, /* ctrl[15:13] 001 - PRB not on qword boundary */
+       PORT_CERR_CMD_TGTABRT   = 25, /* ctrl[15:13] 010 - target abort */
+       PORT_CERR_CMD_MSTABRT   = 26, /* ctrl[15:13] 100 - master abort */
+       PORT_CERR_CMD_PCIPERR   = 27, /* ctrl[15:13] 110 - PCI parity err while fetching PRB */
+       PORT_CERR_XFR_UNDEF     = 32, /* PSD ecode 00 - undefined */
+       PORT_CERR_XFR_TGTABRT   = 33, /* PSD ecode 01 - target abort */
+       PORT_CERR_XFR_MSTABRT   = 34, /* PSD ecode 10 - master abort */
+       PORT_CERR_XFR_PCIPERR   = 35, /* PSD ecode 11 - PCI prity err during transfer */
+       PORT_CERR_SENDSERVICE   = 36, /* FIS received while sending service */
+
+       /* bits of PRB control field */
+       PRB_CTRL_PROTOCOL       = (1 << 0), /* override def. ATA protocol */
+       PRB_CTRL_PACKET_READ    = (1 << 4), /* PACKET cmd read */
+       PRB_CTRL_PACKET_WRITE   = (1 << 5), /* PACKET cmd write */
+       PRB_CTRL_NIEN           = (1 << 6), /* Mask completion irq */
+       PRB_CTRL_SRST           = (1 << 7), /* Soft reset request (ign BSY?) */
+
+       /* PRB protocol field */
+       PRB_PROT_PACKET         = (1 << 0),
+       PRB_PROT_TCQ            = (1 << 1),
+       PRB_PROT_NCQ            = (1 << 2),
+       PRB_PROT_READ           = (1 << 3),
+       PRB_PROT_WRITE          = (1 << 4),
+       PRB_PROT_TRANSPARENT    = (1 << 5),
+
+       /*
+        * Other constants
+        */
+       SGE_TRM                 = (1 << 31), /* Last SGE in chain */
+       SGE_LNK                 = (1 << 30), /* linked list
+                                               Points to SGT, not SGE */
+       SGE_DRD                 = (1 << 29), /* discard data read (/dev/null)
+                                               data address ignored */
+
+       SIL24_MAX_CMDS          = 31,
+
+       /* board id */
+       BID_SIL3124             = 0,
+       BID_SIL3132             = 1,
+       BID_SIL3131             = 2,
+
+       /* host flags */
+       SIL24_COMMON_FLAGS      = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
+                                 ATA_FLAG_MMIO | ATA_FLAG_PIO_DMA |
+                                 ATA_FLAG_NCQ | ATA_FLAG_SKIP_D2H_BSY,
+       SIL24_FLAG_PCIX_IRQ_WOC = (1 << 24), /* IRQ loss errata on PCI-X */
+
+       IRQ_STAT_4PORTS         = 0xf,
+};
+
+struct sil24_ata_block {
+       struct sil24_prb prb;
+       struct sil24_sge sge[LIBATA_MAX_PRD];
+};
+
+struct sil24_atapi_block {
+       struct sil24_prb prb;
+       u8 cdb[16];
+       struct sil24_sge sge[LIBATA_MAX_PRD - 1];
+};
+
+union sil24_cmd_block {
+       struct sil24_ata_block ata;
+       struct sil24_atapi_block atapi;
+};
+
+static struct sil24_cerr_info {
+       unsigned int err_mask, action;
+       const char *desc;
+} sil24_cerr_db[] = {
+       [0]                     = { AC_ERR_DEV, ATA_EH_REVALIDATE,
+                                   "device error" },
+       [PORT_CERR_DEV]         = { AC_ERR_DEV, ATA_EH_REVALIDATE,
+                                   "device error via D2H FIS" },
+       [PORT_CERR_SDB]         = { AC_ERR_DEV, ATA_EH_REVALIDATE,
+                                   "device error via SDB FIS" },
+       [PORT_CERR_DATA]        = { AC_ERR_ATA_BUS, ATA_EH_SOFTRESET,
+                                   "error in data FIS" },
+       [PORT_CERR_SEND]        = { AC_ERR_ATA_BUS, ATA_EH_SOFTRESET,
+                                   "failed to transmit command FIS" },
+       [PORT_CERR_INCONSISTENT] = { AC_ERR_HSM, ATA_EH_SOFTRESET,
+                                    "protocol mismatch" },
+       [PORT_CERR_DIRECTION]   = { AC_ERR_HSM, ATA_EH_SOFTRESET,
+                                   "data directon mismatch" },
+       [PORT_CERR_UNDERRUN]    = { AC_ERR_HSM, ATA_EH_SOFTRESET,
+                                   "ran out of SGEs while writing" },
+       [PORT_CERR_OVERRUN]     = { AC_ERR_HSM, ATA_EH_SOFTRESET,
+                                   "ran out of SGEs while reading" },
+       [PORT_CERR_PKT_PROT]    = { AC_ERR_HSM, ATA_EH_SOFTRESET,
+                                   "invalid data directon for ATAPI CDB" },
+       [PORT_CERR_SGT_BOUNDARY] = { AC_ERR_SYSTEM, ATA_EH_SOFTRESET,
+                                    "SGT no on qword boundary" },
+       [PORT_CERR_SGT_TGTABRT] = { AC_ERR_HOST_BUS, ATA_EH_SOFTRESET,
+                                   "PCI target abort while fetching SGT" },
+       [PORT_CERR_SGT_MSTABRT] = { AC_ERR_HOST_BUS, ATA_EH_SOFTRESET,
+                                   "PCI master abort while fetching SGT" },
+       [PORT_CERR_SGT_PCIPERR] = { AC_ERR_HOST_BUS, ATA_EH_SOFTRESET,
+                                   "PCI parity error while fetching SGT" },
+       [PORT_CERR_CMD_BOUNDARY] = { AC_ERR_SYSTEM, ATA_EH_SOFTRESET,
+                                    "PRB not on qword boundary" },
+       [PORT_CERR_CMD_TGTABRT] = { AC_ERR_HOST_BUS, ATA_EH_SOFTRESET,
+                                   "PCI target abort while fetching PRB" },
+       [PORT_CERR_CMD_MSTABRT] = { AC_ERR_HOST_BUS, ATA_EH_SOFTRESET,
+                                   "PCI master abort while fetching PRB" },
+       [PORT_CERR_CMD_PCIPERR] = { AC_ERR_HOST_BUS, ATA_EH_SOFTRESET,
+                                   "PCI parity error while fetching PRB" },
+       [PORT_CERR_XFR_UNDEF]   = { AC_ERR_HOST_BUS, ATA_EH_SOFTRESET,
+                                   "undefined error while transferring data" },
+       [PORT_CERR_XFR_TGTABRT] = { AC_ERR_HOST_BUS, ATA_EH_SOFTRESET,
+                                   "PCI target abort while transferring data" },
+       [PORT_CERR_XFR_MSTABRT] = { AC_ERR_HOST_BUS, ATA_EH_SOFTRESET,
+                                   "PCI master abort while transferring data" },
+       [PORT_CERR_XFR_PCIPERR] = { AC_ERR_HOST_BUS, ATA_EH_SOFTRESET,
+                                   "PCI parity error while transferring data" },
+       [PORT_CERR_SENDSERVICE] = { AC_ERR_HSM, ATA_EH_SOFTRESET,
+                                   "FIS received while sending service FIS" },
+};
+
+/*
+ * ap->private_data
+ *
+ * The preview driver always returned 0 for status.  We emulate it
+ * here from the previous interrupt.
+ */
+struct sil24_port_priv {
+       union sil24_cmd_block *cmd_block;       /* 32 cmd blocks */
+       dma_addr_t cmd_block_dma;               /* DMA base addr for them */
+       struct ata_taskfile tf;                 /* Cached taskfile registers */
+};
+
+/* ap->host_set->private_data */
+struct sil24_host_priv {
+       void __iomem *host_base;        /* global controller control (128 bytes @BAR0) */
+       void __iomem *port_base;        /* port registers (4 * 8192 bytes @BAR2) */
+};
+
+static void sil24_dev_config(struct ata_port *ap, struct ata_device *dev);
+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_qc_prep(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 irqreturn_t sil24_interrupt(int irq, void *dev_instance, struct pt_regs *regs);
+static void sil24_freeze(struct ata_port *ap);
+static void sil24_thaw(struct ata_port *ap);
+static void sil24_error_handler(struct ata_port *ap);
+static void sil24_post_internal_cmd(struct ata_queued_cmd *qc);
+static int sil24_port_start(struct ata_port *ap);
+static void sil24_port_stop(struct ata_port *ap);
+static void sil24_host_stop(struct ata_host_set *host_set);
+static int sil24_init_one(struct pci_dev *pdev, const struct pci_device_id *ent);
+static int sil24_pci_device_resume(struct pci_dev *pdev);
+
+static const struct pci_device_id sil24_pci_tbl[] = {
+       { 0x1095, 0x3124, PCI_ANY_ID, PCI_ANY_ID, 0, 0, BID_SIL3124 },
+       { 0x8086, 0x3124, PCI_ANY_ID, PCI_ANY_ID, 0, 0, BID_SIL3124 },
+       { 0x1095, 0x3132, PCI_ANY_ID, PCI_ANY_ID, 0, 0, BID_SIL3132 },
+       { 0x1095, 0x3131, PCI_ANY_ID, PCI_ANY_ID, 0, 0, BID_SIL3131 },
+       { 0x1095, 0x3531, PCI_ANY_ID, PCI_ANY_ID, 0, 0, BID_SIL3131 },
+       { } /* terminate list */
+};
+
+static struct pci_driver sil24_pci_driver = {
+       .name                   = DRV_NAME,
+       .id_table               = sil24_pci_tbl,
+       .probe                  = sil24_init_one,
+       .remove                 = ata_pci_remove_one, /* safe? */
+       .suspend                = ata_pci_device_suspend,
+       .resume                 = sil24_pci_device_resume,
+};
+
+static struct scsi_host_template sil24_sht = {
+       .module                 = THIS_MODULE,
+       .name                   = DRV_NAME,
+       .ioctl                  = ata_scsi_ioctl,
+       .queuecommand           = ata_scsi_queuecmd,
+       .change_queue_depth     = ata_scsi_change_queue_depth,
+       .can_queue              = SIL24_MAX_CMDS,
+       .this_id                = ATA_SHT_THIS_ID,
+       .sg_tablesize           = LIBATA_MAX_PRD,
+       .cmd_per_lun            = ATA_SHT_CMD_PER_LUN,
+       .emulated               = ATA_SHT_EMULATED,
+       .use_clustering         = ATA_SHT_USE_CLUSTERING,
+       .proc_name              = DRV_NAME,
+       .dma_boundary           = ATA_DMA_BOUNDARY,
+       .slave_configure        = ata_scsi_slave_config,
+       .slave_destroy          = ata_scsi_slave_destroy,
+       .bios_param             = ata_std_bios_param,
+       .suspend                = ata_scsi_device_suspend,
+       .resume                 = ata_scsi_device_resume,
+};
+
+static const struct ata_port_operations sil24_ops = {
+       .port_disable           = ata_port_disable,
+
+       .dev_config             = sil24_dev_config,
+
+       .check_status           = sil24_check_status,
+       .check_altstatus        = sil24_check_status,
+       .dev_select             = ata_noop_dev_select,
+
+       .tf_read                = sil24_tf_read,
+
+       .qc_prep                = sil24_qc_prep,
+       .qc_issue               = sil24_qc_issue,
+
+       .irq_handler            = sil24_interrupt,
+       .irq_clear              = sil24_irq_clear,
+
+       .scr_read               = sil24_scr_read,
+       .scr_write              = sil24_scr_write,
+
+       .freeze                 = sil24_freeze,
+       .thaw                   = sil24_thaw,
+       .error_handler          = sil24_error_handler,
+       .post_internal_cmd      = sil24_post_internal_cmd,
+
+       .port_start             = sil24_port_start,
+       .port_stop              = sil24_port_stop,
+       .host_stop              = sil24_host_stop,
+};
+
+/*
+ * Use bits 30-31 of host_flags to encode available port numbers.
+ * Current maxium is 4.
+ */
+#define SIL24_NPORTS2FLAG(nports)      ((((unsigned)(nports) - 1) & 0x3) << 30)
+#define SIL24_FLAG2NPORTS(flag)                ((((flag) >> 30) & 0x3) + 1)
+
+static struct ata_port_info sil24_port_info[] = {
+       /* sil_3124 */
+       {
+               .sht            = &sil24_sht,
+               .host_flags     = SIL24_COMMON_FLAGS | SIL24_NPORTS2FLAG(4) |
+                                 SIL24_FLAG_PCIX_IRQ_WOC,
+               .pio_mask       = 0x1f,                 /* pio0-4 */
+               .mwdma_mask     = 0x07,                 /* mwdma0-2 */
+               .udma_mask      = 0x3f,                 /* udma0-5 */
+               .port_ops       = &sil24_ops,
+       },
+       /* sil_3132 */
+       {
+               .sht            = &sil24_sht,
+               .host_flags     = SIL24_COMMON_FLAGS | SIL24_NPORTS2FLAG(2),
+               .pio_mask       = 0x1f,                 /* pio0-4 */
+               .mwdma_mask     = 0x07,                 /* mwdma0-2 */
+               .udma_mask      = 0x3f,                 /* udma0-5 */
+               .port_ops       = &sil24_ops,
+       },
+       /* sil_3131/sil_3531 */
+       {
+               .sht            = &sil24_sht,
+               .host_flags     = SIL24_COMMON_FLAGS | SIL24_NPORTS2FLAG(1),
+               .pio_mask       = 0x1f,                 /* pio0-4 */
+               .mwdma_mask     = 0x07,                 /* mwdma0-2 */
+               .udma_mask      = 0x3f,                 /* udma0-5 */
+               .port_ops       = &sil24_ops,
+       },
+};
+
+static int sil24_tag(int tag)
+{
+       if (unlikely(ata_tag_internal(tag)))
+               return 0;
+       return tag;
+}
+
+static void sil24_dev_config(struct ata_port *ap, struct ata_device *dev)
+{
+       void __iomem *port = (void __iomem *)ap->ioaddr.cmd_addr;
+
+       if (dev->cdb_len == 16)
+               writel(PORT_CS_CDB16, port + PORT_CTRL_STAT);
+       else
+               writel(PORT_CS_CDB16, port + PORT_CTRL_CLR);
+}
+
+static inline void sil24_update_tf(struct ata_port *ap)
+{
+       struct sil24_port_priv *pp = ap->private_data;
+       void __iomem *port = (void __iomem *)ap->ioaddr.cmd_addr;
+       struct sil24_prb __iomem *prb = port;
+       u8 fis[6 * 4];
+
+       memcpy_fromio(fis, prb->fis, 6 * 4);
+       ata_tf_from_fis(fis, &pp->tf);
+}
+
+static u8 sil24_check_status(struct ata_port *ap)
+{
+       struct sil24_port_priv *pp = ap->private_data;
+       return pp->tf.command;
+}
+
+static int sil24_scr_map[] = {
+       [SCR_CONTROL]   = 0,
+       [SCR_STATUS]    = 1,
+       [SCR_ERROR]     = 2,
+       [SCR_ACTIVE]    = 3,
+};
+
+static u32 sil24_scr_read(struct ata_port *ap, unsigned sc_reg)
+{
+       void __iomem *scr_addr = (void __iomem *)ap->ioaddr.scr_addr;
+       if (sc_reg < ARRAY_SIZE(sil24_scr_map)) {
+               void __iomem *addr;
+               addr = scr_addr + sil24_scr_map[sc_reg] * 4;
+               return readl(scr_addr + sil24_scr_map[sc_reg] * 4);
+       }
+       return 0xffffffffU;
+}
+
+static void sil24_scr_write(struct ata_port *ap, unsigned sc_reg, u32 val)
+{
+       void __iomem *scr_addr = (void __iomem *)ap->ioaddr.scr_addr;
+       if (sc_reg < ARRAY_SIZE(sil24_scr_map)) {
+               void __iomem *addr;
+               addr = scr_addr + sil24_scr_map[sc_reg] * 4;
+               writel(val, scr_addr + sil24_scr_map[sc_reg] * 4);
+       }
+}
+
+static void sil24_tf_read(struct ata_port *ap, struct ata_taskfile *tf)
+{
+       struct sil24_port_priv *pp = ap->private_data;
+       *tf = pp->tf;
+}
+
+static int sil24_init_port(struct ata_port *ap)
+{
+       void __iomem *port = (void __iomem *)ap->ioaddr.cmd_addr;
+       u32 tmp;
+
+       writel(PORT_CS_INIT, port + PORT_CTRL_STAT);
+       ata_wait_register(port + PORT_CTRL_STAT,
+                         PORT_CS_INIT, PORT_CS_INIT, 10, 100);
+       tmp = ata_wait_register(port + PORT_CTRL_STAT,
+                               PORT_CS_RDY, 0, 10, 100);
+
+       if ((tmp & (PORT_CS_INIT | PORT_CS_RDY)) != PORT_CS_RDY)
+               return -EIO;
+       return 0;
+}
+
+static int sil24_softreset(struct ata_port *ap, unsigned int *class)
+{
+       void __iomem *port = (void __iomem *)ap->ioaddr.cmd_addr;
+       struct sil24_port_priv *pp = ap->private_data;
+       struct sil24_prb *prb = &pp->cmd_block[0].ata.prb;
+       dma_addr_t paddr = pp->cmd_block_dma;
+       u32 mask, irq_stat;
+       const char *reason;
+
+       DPRINTK("ENTER\n");
+
+       if (ata_port_offline(ap)) {
+               DPRINTK("PHY reports no device\n");
+               *class = ATA_DEV_NONE;
+               goto out;
+       }
+
+       /* put the port into known state */
+       if (sil24_init_port(ap)) {
+               reason ="port not ready";
+               goto err;
+       }
+
+       /* do SRST */
+       prb->ctrl = cpu_to_le16(PRB_CTRL_SRST);
+       prb->fis[1] = 0; /* no PM yet */
+
+       writel((u32)paddr, port + PORT_CMD_ACTIVATE);
+       writel((u64)paddr >> 32, port + PORT_CMD_ACTIVATE + 4);
+
+       mask = (PORT_IRQ_COMPLETE | PORT_IRQ_ERROR) << PORT_IRQ_RAW_SHIFT;
+       irq_stat = ata_wait_register(port + PORT_IRQ_STAT, mask, 0x0,
+                                    100, ATA_TMOUT_BOOT / HZ * 1000);
+
+       writel(irq_stat, port + PORT_IRQ_STAT); /* clear IRQs */
+       irq_stat >>= PORT_IRQ_RAW_SHIFT;
+
+       if (!(irq_stat & PORT_IRQ_COMPLETE)) {
+               if (irq_stat & PORT_IRQ_ERROR)
+                       reason = "SRST command error";
+               else
+                       reason = "timeout";
+               goto err;
+       }
+
+       sil24_update_tf(ap);
+       *class = ata_dev_classify(&pp->tf);
+
+       if (*class == ATA_DEV_UNKNOWN)
+               *class = ATA_DEV_NONE;
+
+ out:
+       DPRINTK("EXIT, class=%u\n", *class);
+       return 0;
+
+ err:
+       ata_port_printk(ap, KERN_ERR, "softreset failed (%s)\n", reason);
+       return -EIO;
+}
+
+static int sil24_hardreset(struct ata_port *ap, unsigned int *class)
+{
+       void __iomem *port = (void __iomem *)ap->ioaddr.cmd_addr;
+       const char *reason;
+       int tout_msec, rc;
+       u32 tmp;
+
+       /* sil24 does the right thing(tm) without any protection */
+       sata_set_spd(ap);
+
+       tout_msec = 100;
+       if (ata_port_online(ap))
+               tout_msec = 5000;
+
+       writel(PORT_CS_DEV_RST, port + PORT_CTRL_STAT);
+       tmp = ata_wait_register(port + PORT_CTRL_STAT,
+                               PORT_CS_DEV_RST, PORT_CS_DEV_RST, 10, tout_msec);
+
+       /* SStatus oscillates between zero and valid status after
+        * DEV_RST, debounce it.
+        */
+       rc = sata_phy_debounce(ap, sata_deb_timing_long);
+       if (rc) {
+               reason = "PHY debouncing failed";
+               goto err;
+       }
+
+       if (tmp & PORT_CS_DEV_RST) {
+               if (ata_port_offline(ap))
+                       return 0;
+               reason = "link not ready";
+               goto err;
+       }
+
+       /* Sil24 doesn't store signature FIS after hardreset, so we
+        * can't wait for BSY to clear.  Some devices take a long time
+        * to get ready and those devices will choke if we don't wait
+        * for BSY clearance here.  Tell libata to perform follow-up
+        * softreset.
+        */
+       return -EAGAIN;
+
+ err:
+       ata_port_printk(ap, KERN_ERR, "hardreset failed (%s)\n", reason);
+       return -EIO;
+}
+
+static inline void sil24_fill_sg(struct ata_queued_cmd *qc,
+                                struct sil24_sge *sge)
+{
+       struct scatterlist *sg;
+       unsigned int idx = 0;
+
+       ata_for_each_sg(sg, qc) {
+               sge->addr = cpu_to_le64(sg_dma_address(sg));
+               sge->cnt = cpu_to_le32(sg_dma_len(sg));
+               if (ata_sg_is_last(sg, qc))
+                       sge->flags = cpu_to_le32(SGE_TRM);
+               else
+                       sge->flags = 0;
+
+               sge++;
+               idx++;
+       }
+}
+
+static void sil24_qc_prep(struct ata_queued_cmd *qc)
+{
+       struct ata_port *ap = qc->ap;
+       struct sil24_port_priv *pp = ap->private_data;
+       union sil24_cmd_block *cb;
+       struct sil24_prb *prb;
+       struct sil24_sge *sge;
+       u16 ctrl = 0;
+
+       cb = &pp->cmd_block[sil24_tag(qc->tag)];
+
+       switch (qc->tf.protocol) {
+       case ATA_PROT_PIO:
+       case ATA_PROT_DMA:
+       case ATA_PROT_NCQ:
+       case ATA_PROT_NODATA:
+               prb = &cb->ata.prb;
+               sge = cb->ata.sge;
+               break;
+
+       case ATA_PROT_ATAPI:
+       case ATA_PROT_ATAPI_DMA:
+       case ATA_PROT_ATAPI_NODATA:
+               prb = &cb->atapi.prb;
+               sge = cb->atapi.sge;
+               memset(cb->atapi.cdb, 0, 32);
+               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)
+                               ctrl = PRB_CTRL_PACKET_WRITE;
+                       else
+                               ctrl = PRB_CTRL_PACKET_READ;
+               }
+               break;
+
+       default:
+               prb = NULL;     /* shut up, gcc */
+               sge = NULL;
+               BUG();
+       }
+
+       prb->ctrl = cpu_to_le16(ctrl);
+       ata_tf_to_fis(&qc->tf, prb->fis, 0);
+
+       if (qc->flags & ATA_QCFLAG_DMAMAP)
+               sil24_fill_sg(qc, sge);
+}
+
+static unsigned int sil24_qc_issue(struct ata_queued_cmd *qc)
+{
+       struct ata_port *ap = qc->ap;
+       struct sil24_port_priv *pp = ap->private_data;
+       void __iomem *port = (void __iomem *)ap->ioaddr.cmd_addr;
+       unsigned int tag = sil24_tag(qc->tag);
+       dma_addr_t paddr;
+       void __iomem *activate;
+
+       paddr = pp->cmd_block_dma + tag * sizeof(*pp->cmd_block);
+       activate = port + PORT_CMD_ACTIVATE + tag * 8;
+
+       writel((u32)paddr, activate);
+       writel((u64)paddr >> 32, activate + 4);
+
+       return 0;
+}
+
+static void sil24_irq_clear(struct ata_port *ap)
+{
+       /* unused */
+}
+
+static void sil24_freeze(struct ata_port *ap)
+{
+       void __iomem *port = (void __iomem *)ap->ioaddr.cmd_addr;
+
+       /* Port-wide IRQ mask in HOST_CTRL doesn't really work, clear
+        * PORT_IRQ_ENABLE instead.
+        */
+       writel(0xffff, port + PORT_IRQ_ENABLE_CLR);
+}
+
+static void sil24_thaw(struct ata_port *ap)
+{
+       void __iomem *port = (void __iomem *)ap->ioaddr.cmd_addr;
+       u32 tmp;
+
+       /* clear IRQ */
+       tmp = readl(port + PORT_IRQ_STAT);
+       writel(tmp, port + PORT_IRQ_STAT);
+
+       /* turn IRQ back on */
+       writel(DEF_PORT_IRQ, port + PORT_IRQ_ENABLE_SET);
+}
+
+static void sil24_error_intr(struct ata_port *ap)
+{
+       void __iomem *port = (void __iomem *)ap->ioaddr.cmd_addr;
+       struct ata_eh_info *ehi = &ap->eh_info;
+       int freeze = 0;
+       u32 irq_stat;
+
+       /* on error, we need to clear IRQ explicitly */
+       irq_stat = readl(port + PORT_IRQ_STAT);
+       writel(irq_stat, port + PORT_IRQ_STAT);
+
+       /* first, analyze and record host port events */
+       ata_ehi_clear_desc(ehi);
+
+       ata_ehi_push_desc(ehi, "irq_stat 0x%08x", irq_stat);
+
+       if (irq_stat & (PORT_IRQ_PHYRDY_CHG | PORT_IRQ_DEV_XCHG)) {
+               ata_ehi_hotplugged(ehi);
+               ata_ehi_push_desc(ehi, ", %s",
+                              irq_stat & PORT_IRQ_PHYRDY_CHG ?
+                              "PHY RDY changed" : "device exchanged");
+               freeze = 1;
+       }
+
+       if (irq_stat & PORT_IRQ_UNK_FIS) {
+               ehi->err_mask |= AC_ERR_HSM;
+               ehi->action |= ATA_EH_SOFTRESET;
+               ata_ehi_push_desc(ehi , ", unknown FIS");
+               freeze = 1;
+       }
+
+       /* deal with command error */
+       if (irq_stat & PORT_IRQ_ERROR) {
+               struct sil24_cerr_info *ci = NULL;
+               unsigned int err_mask = 0, action = 0;
+               struct ata_queued_cmd *qc;
+               u32 cerr;
+
+               /* analyze CMD_ERR */
+               cerr = readl(port + PORT_CMD_ERR);
+               if (cerr < ARRAY_SIZE(sil24_cerr_db))
+                       ci = &sil24_cerr_db[cerr];
+
+               if (ci && ci->desc) {
+                       err_mask |= ci->err_mask;
+                       action |= ci->action;
+                       ata_ehi_push_desc(ehi, ", %s", ci->desc);
+               } else {
+                       err_mask |= AC_ERR_OTHER;
+                       action |= ATA_EH_SOFTRESET;
+                       ata_ehi_push_desc(ehi, ", unknown command error %d",
+                                         cerr);
+               }
+
+               /* record error info */
+               qc = ata_qc_from_tag(ap, ap->active_tag);
+               if (qc) {
+                       sil24_update_tf(ap);
+                       qc->err_mask |= err_mask;
+               } else
+                       ehi->err_mask |= err_mask;
+
+               ehi->action |= action;
+       }
+
+       /* freeze or abort */
+       if (freeze)
+               ata_port_freeze(ap);
+       else
+               ata_port_abort(ap);
+}
+
+static void sil24_finish_qc(struct ata_queued_cmd *qc)
+{
+       if (qc->flags & ATA_QCFLAG_RESULT_TF)
+               sil24_update_tf(qc->ap);
+}
+
+static inline void sil24_host_intr(struct ata_port *ap)
+{
+       void __iomem *port = (void __iomem *)ap->ioaddr.cmd_addr;
+       u32 slot_stat, qc_active;
+       int rc;
+
+       slot_stat = readl(port + PORT_SLOT_STAT);
+
+       if (unlikely(slot_stat & HOST_SSTAT_ATTN)) {
+               sil24_error_intr(ap);
+               return;
+       }
+
+       if (ap->flags & SIL24_FLAG_PCIX_IRQ_WOC)
+               writel(PORT_IRQ_COMPLETE, port + PORT_IRQ_STAT);
+
+       qc_active = slot_stat & ~HOST_SSTAT_ATTN;
+       rc = ata_qc_complete_multiple(ap, qc_active, sil24_finish_qc);
+       if (rc > 0)
+               return;
+       if (rc < 0) {
+               struct ata_eh_info *ehi = &ap->eh_info;
+               ehi->err_mask |= AC_ERR_HSM;
+               ehi->action |= ATA_EH_SOFTRESET;
+               ata_port_freeze(ap);
+               return;
+       }
+
+       if (ata_ratelimit())
+               ata_port_printk(ap, KERN_INFO, "spurious interrupt "
+                       "(slot_stat 0x%x active_tag %d sactive 0x%x)\n",
+                       slot_stat, ap->active_tag, ap->sactive);
+}
+
+static irqreturn_t sil24_interrupt(int irq, void *dev_instance, struct pt_regs *regs)
+{
+       struct ata_host_set *host_set = dev_instance;
+       struct sil24_host_priv *hpriv = host_set->private_data;
+       unsigned handled = 0;
+       u32 status;
+       int i;
+
+       status = readl(hpriv->host_base + HOST_IRQ_STAT);
+
+       if (status == 0xffffffff) {
+               printk(KERN_ERR DRV_NAME ": IRQ status == 0xffffffff, "
+                      "PCI fault or device removal?\n");
+               goto out;
+       }
+
+       if (!(status & IRQ_STAT_4PORTS))
+               goto out;
+
+       spin_lock(&host_set->lock);
+
+       for (i = 0; i < host_set->n_ports; i++)
+               if (status & (1 << i)) {
+                       struct ata_port *ap = host_set->ports[i];
+                       if (ap && !(ap->flags & ATA_FLAG_DISABLED)) {
+                               sil24_host_intr(host_set->ports[i]);
+                               handled++;
+                       } else
+                               printk(KERN_ERR DRV_NAME
+                                      ": interrupt from disabled port %d\n", i);
+               }
+
+       spin_unlock(&host_set->lock);
+ out:
+       return IRQ_RETVAL(handled);
+}
+
+static void sil24_error_handler(struct ata_port *ap)
+{
+       struct ata_eh_context *ehc = &ap->eh_context;
+
+       if (sil24_init_port(ap)) {
+               ata_eh_freeze_port(ap);
+               ehc->i.action |= ATA_EH_HARDRESET;
+       }
+
+       /* perform recovery */
+       ata_do_eh(ap, ata_std_prereset, sil24_softreset, sil24_hardreset,
+                 ata_std_postreset);
+}
+
+static void sil24_post_internal_cmd(struct ata_queued_cmd *qc)
+{
+       struct ata_port *ap = qc->ap;
+
+       if (qc->flags & ATA_QCFLAG_FAILED)
+               qc->err_mask |= AC_ERR_OTHER;
+
+       /* make DMA engine forget about the failed command */
+       if (qc->err_mask)
+               sil24_init_port(ap);
+}
+
+static inline void sil24_cblk_free(struct sil24_port_priv *pp, struct device *dev)
+{
+       const size_t cb_size = sizeof(*pp->cmd_block) * SIL24_MAX_CMDS;
+
+       dma_free_coherent(dev, cb_size, pp->cmd_block, pp->cmd_block_dma);
+}
+
+static int sil24_port_start(struct ata_port *ap)
+{
+       struct device *dev = ap->host_set->dev;
+       struct sil24_port_priv *pp;
+       union sil24_cmd_block *cb;
+       size_t cb_size = sizeof(*cb) * SIL24_MAX_CMDS;
+       dma_addr_t cb_dma;
+       int rc = -ENOMEM;
+
+       pp = kzalloc(sizeof(*pp), GFP_KERNEL);
+       if (!pp)
+               goto err_out;
+
+       pp->tf.command = ATA_DRDY;
+
+       cb = dma_alloc_coherent(dev, cb_size, &cb_dma, GFP_KERNEL);
+       if (!cb)
+               goto err_out_pp;
+       memset(cb, 0, cb_size);
+
+       rc = ata_pad_alloc(ap, dev);
+       if (rc)
+               goto err_out_pad;
+
+       pp->cmd_block = cb;
+       pp->cmd_block_dma = cb_dma;
+
+       ap->private_data = pp;
+
+       return 0;
+
+err_out_pad:
+       sil24_cblk_free(pp, dev);
+err_out_pp:
+       kfree(pp);
+err_out:
+       return rc;
+}
+
+static void sil24_port_stop(struct ata_port *ap)
+{
+       struct device *dev = ap->host_set->dev;
+       struct sil24_port_priv *pp = ap->private_data;
+
+       sil24_cblk_free(pp, dev);
+       ata_pad_free(ap, dev);
+       kfree(pp);
+}
+
+static void sil24_host_stop(struct ata_host_set *host_set)
+{
+       struct sil24_host_priv *hpriv = host_set->private_data;
+       struct pci_dev *pdev = to_pci_dev(host_set->dev);
+
+       pci_iounmap(pdev, hpriv->host_base);
+       pci_iounmap(pdev, hpriv->port_base);
+       kfree(hpriv);
+}
+
+static void sil24_init_controller(struct pci_dev *pdev, int n_ports,
+                                 unsigned long host_flags,
+                                 void __iomem *host_base,
+                                 void __iomem *port_base)
+{
+       u32 tmp;
+       int i;
+
+       /* GPIO off */
+       writel(0, host_base + HOST_FLASH_CMD);
+
+       /* clear global reset & mask interrupts during initialization */
+       writel(0, host_base + HOST_CTRL);
+
+       /* init ports */
+       for (i = 0; i < n_ports; i++) {
+               void __iomem *port = port_base + i * PORT_REGS_SIZE;
+
+               /* Initial PHY setting */
+               writel(0x20c, port + PORT_PHY_CFG);
+
+               /* Clear port RST */
+               tmp = readl(port + PORT_CTRL_STAT);
+               if (tmp & PORT_CS_PORT_RST) {
+                       writel(PORT_CS_PORT_RST, port + PORT_CTRL_CLR);
+                       tmp = ata_wait_register(port + PORT_CTRL_STAT,
+                                               PORT_CS_PORT_RST,
+                                               PORT_CS_PORT_RST, 10, 100);
+                       if (tmp & PORT_CS_PORT_RST)
+                               dev_printk(KERN_ERR, &pdev->dev,
+                                          "failed to clear port RST\n");
+               }
+
+               /* Configure IRQ WoC */
+               if (host_flags & SIL24_FLAG_PCIX_IRQ_WOC)
+                       writel(PORT_CS_IRQ_WOC, port + PORT_CTRL_STAT);
+               else
+                       writel(PORT_CS_IRQ_WOC, port + PORT_CTRL_CLR);
+
+               /* Zero error counters. */
+               writel(0x8000, port + PORT_DECODE_ERR_THRESH);
+               writel(0x8000, port + PORT_CRC_ERR_THRESH);
+               writel(0x8000, port + PORT_HSHK_ERR_THRESH);
+               writel(0x0000, port + PORT_DECODE_ERR_CNT);
+               writel(0x0000, port + PORT_CRC_ERR_CNT);
+               writel(0x0000, port + PORT_HSHK_ERR_CNT);
+
+               /* Always use 64bit activation */
+               writel(PORT_CS_32BIT_ACTV, port + PORT_CTRL_CLR);
+
+               /* Clear port multiplier enable and resume bits */
+               writel(PORT_CS_PM_EN | PORT_CS_RESUME, port + PORT_CTRL_CLR);
+       }
+
+       /* Turn on interrupts */
+       writel(IRQ_STAT_4PORTS, host_base + HOST_CTRL);
+}
+
+static int sil24_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
+{
+       static int printed_version = 0;
+       unsigned int board_id = (unsigned int)ent->driver_data;
+       struct ata_port_info *pinfo = &sil24_port_info[board_id];
+       struct ata_probe_ent *probe_ent = NULL;
+       struct sil24_host_priv *hpriv = NULL;
+       void __iomem *host_base = NULL;
+       void __iomem *port_base = NULL;
+       int i, rc;
+       u32 tmp;
+
+       if (!printed_version++)
+               dev_printk(KERN_DEBUG, &pdev->dev, "version " DRV_VERSION "\n");
+
+       rc = pci_enable_device(pdev);
+       if (rc)
+               return rc;
+
+       rc = pci_request_regions(pdev, DRV_NAME);
+       if (rc)
+               goto out_disable;
+
+       rc = -ENOMEM;
+       /* map mmio registers */
+       host_base = pci_iomap(pdev, 0, 0);
+       if (!host_base)
+               goto out_free;
+       port_base = pci_iomap(pdev, 2, 0);
+       if (!port_base)
+               goto out_free;
+
+       /* allocate & init probe_ent and hpriv */
+       probe_ent = kzalloc(sizeof(*probe_ent), GFP_KERNEL);
+       if (!probe_ent)
+               goto out_free;
+
+       hpriv = kzalloc(sizeof(*hpriv), GFP_KERNEL);
+       if (!hpriv)
+               goto out_free;
+
+       probe_ent->dev = pci_dev_to_dev(pdev);
+       INIT_LIST_HEAD(&probe_ent->node);
+
+       probe_ent->sht          = pinfo->sht;
+       probe_ent->host_flags   = pinfo->host_flags;
+       probe_ent->pio_mask     = pinfo->pio_mask;
+       probe_ent->mwdma_mask   = pinfo->mwdma_mask;
+       probe_ent->udma_mask    = pinfo->udma_mask;
+       probe_ent->port_ops     = pinfo->port_ops;
+       probe_ent->n_ports      = SIL24_FLAG2NPORTS(pinfo->host_flags);
+
+       probe_ent->irq = pdev->irq;
+       probe_ent->irq_flags = IRQF_SHARED;
+       probe_ent->private_data = hpriv;
+
+       hpriv->host_base = host_base;
+       hpriv->port_base = port_base;
+
+       /*
+        * Configure the device
+        */
+       if (!pci_set_dma_mask(pdev, DMA_64BIT_MASK)) {
+               rc = pci_set_consistent_dma_mask(pdev, DMA_64BIT_MASK);
+               if (rc) {
+                       rc = pci_set_consistent_dma_mask(pdev, DMA_32BIT_MASK);
+                       if (rc) {
+                               dev_printk(KERN_ERR, &pdev->dev,
+                                          "64-bit DMA enable failed\n");
+                               goto out_free;
+                       }
+               }
+       } else {
+               rc = pci_set_dma_mask(pdev, DMA_32BIT_MASK);
+               if (rc) {
+                       dev_printk(KERN_ERR, &pdev->dev,
+                                  "32-bit DMA enable failed\n");
+                       goto out_free;
+               }
+               rc = pci_set_consistent_dma_mask(pdev, DMA_32BIT_MASK);
+               if (rc) {
+                       dev_printk(KERN_ERR, &pdev->dev,
+                                  "32-bit consistent DMA enable failed\n");
+                       goto out_free;
+               }
+       }
+
+       /* Apply workaround for completion IRQ loss on PCI-X errata */
+       if (probe_ent->host_flags & SIL24_FLAG_PCIX_IRQ_WOC) {
+               tmp = readl(host_base + HOST_CTRL);
+               if (tmp & (HOST_CTRL_TRDY | HOST_CTRL_STOP | HOST_CTRL_DEVSEL))
+                       dev_printk(KERN_INFO, &pdev->dev,
+                                  "Applying completion IRQ loss on PCI-X "
+                                  "errata fix\n");
+               else
+                       probe_ent->host_flags &= ~SIL24_FLAG_PCIX_IRQ_WOC;
+       }
+
+       for (i = 0; i < probe_ent->n_ports; i++) {
+               unsigned long portu =
+                       (unsigned long)port_base + i * PORT_REGS_SIZE;
+
+               probe_ent->port[i].cmd_addr = portu;
+               probe_ent->port[i].scr_addr = portu + PORT_SCONTROL;
+
+               ata_std_ports(&probe_ent->port[i]);
+       }
+
+       sil24_init_controller(pdev, probe_ent->n_ports, probe_ent->host_flags,
+                             host_base, port_base);
+
+       pci_set_master(pdev);
+
+       /* FIXME: check ata_device_add return value */
+       ata_device_add(probe_ent);
+
+       kfree(probe_ent);
+       return 0;
+
+ out_free:
+       if (host_base)
+               pci_iounmap(pdev, host_base);
+       if (port_base)
+               pci_iounmap(pdev, port_base);
+       kfree(probe_ent);
+       kfree(hpriv);
+       pci_release_regions(pdev);
+ out_disable:
+       pci_disable_device(pdev);
+       return rc;
+}
+
+static int sil24_pci_device_resume(struct pci_dev *pdev)
+{
+       struct ata_host_set *host_set = dev_get_drvdata(&pdev->dev);
+       struct sil24_host_priv *hpriv = host_set->private_data;
+
+       ata_pci_device_do_resume(pdev);
+
+       if (pdev->dev.power.power_state.event == PM_EVENT_SUSPEND)
+               writel(HOST_CTRL_GLOBAL_RST, hpriv->host_base + HOST_CTRL);
+
+       sil24_init_controller(pdev, host_set->n_ports,
+                             host_set->ports[0]->flags,
+                             hpriv->host_base, hpriv->port_base);
+
+       ata_host_set_resume(host_set);
+
+       return 0;
+}
+
+static int __init sil24_init(void)
+{
+       return pci_register_driver(&sil24_pci_driver);
+}
+
+static void __exit sil24_exit(void)
+{
+       pci_unregister_driver(&sil24_pci_driver);
+}
+
+MODULE_AUTHOR("Tejun Heo");
+MODULE_DESCRIPTION("Silicon Image 3124/3132 SATA low-level driver");
+MODULE_LICENSE("GPL");
+MODULE_DEVICE_TABLE(pci, sil24_pci_tbl);
+
+module_init(sil24_init);
+module_exit(sil24_exit);
diff --git a/drivers/ata/sata_sis.c b/drivers/ata/sata_sis.c
new file mode 100644 (file)
index 0000000..ac24f66
--- /dev/null
@@ -0,0 +1,347 @@
+/*
+ *  sata_sis.c - Silicon Integrated Systems SATA
+ *
+ *  Maintained by:  Uwe Koziolek
+ *                 Please ALWAYS copy linux-ide@vger.kernel.org
+ *                 on emails.
+ *
+ *  Copyright 2004 Uwe Koziolek
+ *
+ *
+ *  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 under NDA.
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/pci.h>
+#include <linux/init.h>
+#include <linux/blkdev.h>
+#include <linux/delay.h>
+#include <linux/interrupt.h>
+#include <linux/device.h>
+#include <scsi/scsi_host.h>
+#include <linux/libata.h>
+
+#define DRV_NAME       "sata_sis"
+#define DRV_VERSION    "0.6"
+
+enum {
+       sis_180                 = 0,
+       SIS_SCR_PCI_BAR         = 5,
+
+       /* PCI configuration registers */
+       SIS_GENCTL              = 0x54, /* IDE General Control register */
+       SIS_SCR_BASE            = 0xc0, /* sata0 phy SCR registers */
+       SIS180_SATA1_OFS        = 0x10, /* offset from sata0->sata1 phy regs */
+       SIS182_SATA1_OFS        = 0x20, /* offset from sata0->sata1 phy regs */
+       SIS_PMR                 = 0x90, /* port mapping register */
+       SIS_PMR_COMBINED        = 0x30,
+
+       /* random bits */
+       SIS_FLAG_CFGSCR         = (1 << 30), /* host flag: SCRs via PCI cfg */
+
+       GENCTL_IOMAPPED_SCR     = (1 << 26), /* if set, SCRs are in IO space */
+};
+
+static int sis_init_one (struct pci_dev *pdev, const struct pci_device_id *ent);
+static u32 sis_scr_read (struct ata_port *ap, unsigned int sc_reg);
+static void sis_scr_write (struct ata_port *ap, unsigned int sc_reg, u32 val);
+
+static const struct pci_device_id sis_pci_tbl[] = {
+       { PCI_VENDOR_ID_SI, 0x180, PCI_ANY_ID, PCI_ANY_ID, 0, 0, sis_180 },
+       { PCI_VENDOR_ID_SI, 0x181, PCI_ANY_ID, PCI_ANY_ID, 0, 0, sis_180 },
+       { PCI_VENDOR_ID_SI, 0x182, PCI_ANY_ID, PCI_ANY_ID, 0, 0, sis_180 },
+       { }     /* terminate list */
+};
+
+
+static struct pci_driver sis_pci_driver = {
+       .name                   = DRV_NAME,
+       .id_table               = sis_pci_tbl,
+       .probe                  = sis_init_one,
+       .remove                 = ata_pci_remove_one,
+};
+
+static struct scsi_host_template sis_sht = {
+       .module                 = THIS_MODULE,
+       .name                   = DRV_NAME,
+       .ioctl                  = ata_scsi_ioctl,
+       .queuecommand           = ata_scsi_queuecmd,
+       .can_queue              = ATA_DEF_QUEUE,
+       .this_id                = ATA_SHT_THIS_ID,
+       .sg_tablesize           = ATA_MAX_PRD,
+       .cmd_per_lun            = ATA_SHT_CMD_PER_LUN,
+       .emulated               = ATA_SHT_EMULATED,
+       .use_clustering         = ATA_SHT_USE_CLUSTERING,
+       .proc_name              = DRV_NAME,
+       .dma_boundary           = ATA_DMA_BOUNDARY,
+       .slave_configure        = ata_scsi_slave_config,
+       .slave_destroy          = ata_scsi_slave_destroy,
+       .bios_param             = ata_std_bios_param,
+};
+
+static const struct ata_port_operations sis_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,
+       .bmdma_setup            = ata_bmdma_setup,
+       .bmdma_start            = ata_bmdma_start,
+       .bmdma_stop             = ata_bmdma_stop,
+       .bmdma_status           = ata_bmdma_status,
+       .qc_prep                = ata_qc_prep,
+       .qc_issue               = ata_qc_issue_prot,
+       .data_xfer              = ata_pio_data_xfer,
+       .freeze                 = ata_bmdma_freeze,
+       .thaw                   = ata_bmdma_thaw,
+       .error_handler          = ata_bmdma_error_handler,
+       .post_internal_cmd      = ata_bmdma_post_internal_cmd,
+       .irq_handler            = ata_interrupt,
+       .irq_clear              = ata_bmdma_irq_clear,
+       .scr_read               = sis_scr_read,
+       .scr_write              = sis_scr_write,
+       .port_start             = ata_port_start,
+       .port_stop              = ata_port_stop,
+       .host_stop              = ata_host_stop,
+};
+
+static struct ata_port_info sis_port_info = {
+       .sht            = &sis_sht,
+       .host_flags     = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY,
+       .pio_mask       = 0x1f,
+       .mwdma_mask     = 0x7,
+       .udma_mask      = 0x7f,
+       .port_ops       = &sis_ops,
+};
+
+
+MODULE_AUTHOR("Uwe Koziolek");
+MODULE_DESCRIPTION("low-level driver for Silicon Integratad Systems SATA controller");
+MODULE_LICENSE("GPL");
+MODULE_DEVICE_TABLE(pci, sis_pci_tbl);
+MODULE_VERSION(DRV_VERSION);
+
+static unsigned int get_scr_cfg_addr(unsigned int port_no, unsigned int sc_reg, int device)
+{
+       unsigned int addr = SIS_SCR_BASE + (4 * sc_reg);
+
+       if (port_no)  {
+               if (device == 0x182)
+                       addr += SIS182_SATA1_OFS;
+               else
+                       addr += SIS180_SATA1_OFS;
+       }
+
+       return addr;
+}
+
+static u32 sis_scr_cfg_read (struct ata_port *ap, unsigned int sc_reg)
+{
+       struct pci_dev *pdev = to_pci_dev(ap->host_set->dev);
+       unsigned int cfg_addr = get_scr_cfg_addr(ap->port_no, sc_reg, pdev->device);
+       u32 val, val2 = 0;
+       u8 pmr;
+
+       if (sc_reg == SCR_ERROR) /* doesn't exist in PCI cfg space */
+               return 0xffffffff;
+
+       pci_read_config_byte(pdev, SIS_PMR, &pmr);
+
+       pci_read_config_dword(pdev, cfg_addr, &val);
+
+       if ((pdev->device == 0x182) || (pmr & SIS_PMR_COMBINED))
+               pci_read_config_dword(pdev, cfg_addr+0x10, &val2);
+
+       return val|val2;
+}
+
+static void sis_scr_cfg_write (struct ata_port *ap, unsigned int scr, u32 val)
+{
+       struct pci_dev *pdev = to_pci_dev(ap->host_set->dev);
+       unsigned int cfg_addr = get_scr_cfg_addr(ap->port_no, scr, pdev->device);
+       u8 pmr;
+
+       if (scr == SCR_ERROR) /* doesn't exist in PCI cfg space */
+               return;
+
+       pci_read_config_byte(pdev, SIS_PMR, &pmr);
+
+       pci_write_config_dword(pdev, cfg_addr, val);
+
+       if ((pdev->device == 0x182) || (pmr & SIS_PMR_COMBINED))
+               pci_write_config_dword(pdev, cfg_addr+0x10, val);
+}
+
+static u32 sis_scr_read (struct ata_port *ap, unsigned int sc_reg)
+{
+       struct pci_dev *pdev = to_pci_dev(ap->host_set->dev);
+       u32 val, val2 = 0;
+       u8 pmr;
+
+       if (sc_reg > SCR_CONTROL)
+               return 0xffffffffU;
+
+       if (ap->flags & SIS_FLAG_CFGSCR)
+               return sis_scr_cfg_read(ap, sc_reg);
+
+       pci_read_config_byte(pdev, SIS_PMR, &pmr);
+
+       val = inl(ap->ioaddr.scr_addr + (sc_reg * 4));
+
+       if ((pdev->device == 0x182) || (pmr & SIS_PMR_COMBINED))
+               val2 = inl(ap->ioaddr.scr_addr + (sc_reg * 4) + 0x10);
+
+       return val | val2;
+}
+
+static void sis_scr_write (struct ata_port *ap, unsigned int sc_reg, u32 val)
+{
+       struct pci_dev *pdev = to_pci_dev(ap->host_set->dev);
+       u8 pmr;
+
+       if (sc_reg > SCR_CONTROL)
+               return;
+
+       pci_read_config_byte(pdev, SIS_PMR, &pmr);
+
+       if (ap->flags & SIS_FLAG_CFGSCR)
+               sis_scr_cfg_write(ap, sc_reg, val);
+       else {
+               outl(val, ap->ioaddr.scr_addr + (sc_reg * 4));
+               if ((pdev->device == 0x182) || (pmr & SIS_PMR_COMBINED))
+                       outl(val, ap->ioaddr.scr_addr + (sc_reg * 4)+0x10);
+       }
+}
+
+static int sis_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
+{
+       static int printed_version;
+       struct ata_probe_ent *probe_ent = NULL;
+       int rc;
+       u32 genctl;
+       struct ata_port_info *ppi;
+       int pci_dev_busy = 0;
+       u8 pmr;
+       u8 port2_start;
+
+       if (!printed_version++)
+               dev_printk(KERN_INFO, &pdev->dev, "version " DRV_VERSION "\n");
+
+       rc = pci_enable_device(pdev);
+       if (rc)
+               return rc;
+
+       rc = pci_request_regions(pdev, DRV_NAME);
+       if (rc) {
+               pci_dev_busy = 1;
+               goto err_out;
+       }
+
+       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;
+
+       ppi = &sis_port_info;
+       probe_ent = ata_pci_init_native_mode(pdev, &ppi, ATA_PORT_PRIMARY | ATA_PORT_SECONDARY);
+       if (!probe_ent) {
+               rc = -ENOMEM;
+               goto err_out_regions;
+       }
+
+       /* check and see if the SCRs are in IO space or PCI cfg space */
+       pci_read_config_dword(pdev, SIS_GENCTL, &genctl);
+       if ((genctl & GENCTL_IOMAPPED_SCR) == 0)
+               probe_ent->host_flags |= SIS_FLAG_CFGSCR;
+
+       /* if hardware thinks SCRs are in IO space, but there are
+        * no IO resources assigned, change to PCI cfg space.
+        */
+       if ((!(probe_ent->host_flags & SIS_FLAG_CFGSCR)) &&
+           ((pci_resource_start(pdev, SIS_SCR_PCI_BAR) == 0) ||
+            (pci_resource_len(pdev, SIS_SCR_PCI_BAR) < 128))) {
+               genctl &= ~GENCTL_IOMAPPED_SCR;
+               pci_write_config_dword(pdev, SIS_GENCTL, genctl);
+               probe_ent->host_flags |= SIS_FLAG_CFGSCR;
+       }
+
+       pci_read_config_byte(pdev, SIS_PMR, &pmr);
+       if (ent->device != 0x182) {
+               if ((pmr & SIS_PMR_COMBINED) == 0) {
+                       dev_printk(KERN_INFO, &pdev->dev,
+                                  "Detected SiS 180/181 chipset in SATA mode\n");
+                       port2_start = 64;
+               }
+               else {
+                       dev_printk(KERN_INFO, &pdev->dev,
+                                  "Detected SiS 180/181 chipset in combined mode\n");
+                       port2_start=0;
+               }
+       }
+       else {
+               dev_printk(KERN_INFO, &pdev->dev, "Detected SiS 182 chipset\n");
+               port2_start = 0x20;
+       }
+
+       if (!(probe_ent->host_flags & SIS_FLAG_CFGSCR)) {
+               probe_ent->port[0].scr_addr =
+                       pci_resource_start(pdev, SIS_SCR_PCI_BAR);
+               probe_ent->port[1].scr_addr =
+                       pci_resource_start(pdev, SIS_SCR_PCI_BAR) + port2_start;
+       }
+
+       pci_set_master(pdev);
+       pci_intx(pdev, 1);
+
+       /* FIXME: check ata_device_add return value */
+       ata_device_add(probe_ent);
+       kfree(probe_ent);
+
+       return 0;
+
+err_out_regions:
+       pci_release_regions(pdev);
+
+err_out:
+       if (!pci_dev_busy)
+               pci_disable_device(pdev);
+       return rc;
+
+}
+
+static int __init sis_init(void)
+{
+       return pci_register_driver(&sis_pci_driver);
+}
+
+static void __exit sis_exit(void)
+{
+       pci_unregister_driver(&sis_pci_driver);
+}
+
+module_init(sis_init);
+module_exit(sis_exit);
+
diff --git a/drivers/ata/sata_svw.c b/drivers/ata/sata_svw.c
new file mode 100644 (file)
index 0000000..baf259a
--- /dev/null
@@ -0,0 +1,508 @@
+/*
+ *  sata_svw.c - ServerWorks / Apple K2 SATA
+ *
+ *  Maintained by: Benjamin Herrenschmidt <benh@kernel.crashing.org> and
+ *                Jeff Garzik <jgarzik@pobox.com>
+ *                 Please ALWAYS copy linux-ide@vger.kernel.org
+ *                 on emails.
+ *
+ *  Copyright 2003 Benjamin Herrenschmidt <benh@kernel.crashing.org>
+ *
+ *  Bits from Jeff Garzik, Copyright RedHat, Inc.
+ *
+ *  This driver probably works with non-Apple versions of the
+ *  Broadcom chipset...
+ *
+ *
+ *  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 under NDA.
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/pci.h>
+#include <linux/init.h>
+#include <linux/blkdev.h>
+#include <linux/delay.h>
+#include <linux/interrupt.h>
+#include <linux/device.h>
+#include <scsi/scsi_host.h>
+#include <linux/libata.h>
+
+#ifdef CONFIG_PPC_OF
+#include <asm/prom.h>
+#include <asm/pci-bridge.h>
+#endif /* CONFIG_PPC_OF */
+
+#define DRV_NAME       "sata_svw"
+#define DRV_VERSION    "2.0"
+
+enum {
+       /* Taskfile registers offsets */
+       K2_SATA_TF_CMD_OFFSET           = 0x00,
+       K2_SATA_TF_DATA_OFFSET          = 0x00,
+       K2_SATA_TF_ERROR_OFFSET         = 0x04,
+       K2_SATA_TF_NSECT_OFFSET         = 0x08,
+       K2_SATA_TF_LBAL_OFFSET          = 0x0c,
+       K2_SATA_TF_LBAM_OFFSET          = 0x10,
+       K2_SATA_TF_LBAH_OFFSET          = 0x14,
+       K2_SATA_TF_DEVICE_OFFSET        = 0x18,
+       K2_SATA_TF_CMDSTAT_OFFSET       = 0x1c,
+       K2_SATA_TF_CTL_OFFSET           = 0x20,
+
+       /* DMA base */
+       K2_SATA_DMA_CMD_OFFSET          = 0x30,
+
+       /* SCRs base */
+       K2_SATA_SCR_STATUS_OFFSET       = 0x40,
+       K2_SATA_SCR_ERROR_OFFSET        = 0x44,
+       K2_SATA_SCR_CONTROL_OFFSET      = 0x48,
+
+       /* Others */
+       K2_SATA_SICR1_OFFSET            = 0x80,
+       K2_SATA_SICR2_OFFSET            = 0x84,
+       K2_SATA_SIM_OFFSET              = 0x88,
+
+       /* Port stride */
+       K2_SATA_PORT_OFFSET             = 0x100,
+};
+
+static u8 k2_stat_check_status(struct ata_port *ap);
+
+
+static u32 k2_sata_scr_read (struct ata_port *ap, unsigned int sc_reg)
+{
+       if (sc_reg > SCR_CONTROL)
+               return 0xffffffffU;
+       return readl((void *) ap->ioaddr.scr_addr + (sc_reg * 4));
+}
+
+
+static void k2_sata_scr_write (struct ata_port *ap, unsigned int sc_reg,
+                              u32 val)
+{
+       if (sc_reg > SCR_CONTROL)
+               return;
+       writel(val, (void *) ap->ioaddr.scr_addr + (sc_reg * 4));
+}
+
+
+static void k2_sata_tf_load(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, ioaddr->ctl_addr);
+               ap->last_ctl = tf->ctl;
+               ata_wait_idle(ap);
+       }
+       if (is_addr && (tf->flags & ATA_TFLAG_LBA48)) {
+               writew(tf->feature | (((u16)tf->hob_feature) << 8), ioaddr->feature_addr);
+               writew(tf->nsect | (((u16)tf->hob_nsect) << 8), ioaddr->nsect_addr);
+               writew(tf->lbal | (((u16)tf->hob_lbal) << 8), ioaddr->lbal_addr);
+               writew(tf->lbam | (((u16)tf->hob_lbam) << 8), ioaddr->lbam_addr);
+               writew(tf->lbah | (((u16)tf->hob_lbah) << 8), ioaddr->lbah_addr);
+       } else if (is_addr) {
+               writew(tf->feature, ioaddr->feature_addr);
+               writew(tf->nsect, ioaddr->nsect_addr);
+               writew(tf->lbal, ioaddr->lbal_addr);
+               writew(tf->lbam, ioaddr->lbam_addr);
+               writew(tf->lbah, ioaddr->lbah_addr);
+       }
+
+       if (tf->flags & ATA_TFLAG_DEVICE)
+               writeb(tf->device, ioaddr->device_addr);
+
+       ata_wait_idle(ap);
+}
+
+
+static void k2_sata_tf_read(struct ata_port *ap, struct ata_taskfile *tf)
+{
+       struct ata_ioports *ioaddr = &ap->ioaddr;
+       u16 nsect, lbal, lbam, lbah, feature;
+
+       tf->command = k2_stat_check_status(ap);
+       tf->device = readw(ioaddr->device_addr);
+       feature = readw(ioaddr->error_addr);
+       nsect = readw(ioaddr->nsect_addr);
+       lbal = readw(ioaddr->lbal_addr);
+       lbam = readw(ioaddr->lbam_addr);
+       lbah = readw(ioaddr->lbah_addr);
+
+       tf->feature = feature;
+       tf->nsect = nsect;
+       tf->lbal = lbal;
+       tf->lbam = lbam;
+       tf->lbah = lbah;
+
+       if (tf->flags & ATA_TFLAG_LBA48) {
+               tf->hob_feature = feature >> 8;
+               tf->hob_nsect = nsect >> 8;
+               tf->hob_lbal = lbal >> 8;
+               tf->hob_lbam = lbam >> 8;
+               tf->hob_lbah = lbah >> 8;
+        }
+}
+
+/**
+ *     k2_bmdma_setup_mmio - Set up PCI IDE BMDMA transaction (MMIO)
+ *     @qc: Info associated with this ATA transaction.
+ *
+ *     LOCKING:
+ *     spin_lock_irqsave(host_set lock)
+ */
+
+static void k2_bmdma_setup_mmio (struct ata_queued_cmd *qc)
+{
+       struct ata_port *ap = qc->ap;
+       unsigned int rw = (qc->tf.flags & ATA_TFLAG_WRITE);
+       u8 dmactl;
+       void *mmio = (void *) ap->ioaddr.bmdma_addr;
+       /* load PRD table addr. */
+       mb();   /* make sure PRD table writes are visible to controller */
+       writel(ap->prd_dma, mmio + ATA_DMA_TABLE_OFS);
+
+       /* specify data direction, triple-check start bit is clear */
+       dmactl = readb(mmio + ATA_DMA_CMD);
+       dmactl &= ~(ATA_DMA_WR | ATA_DMA_START);
+       if (!rw)
+               dmactl |= ATA_DMA_WR;
+       writeb(dmactl, mmio + ATA_DMA_CMD);
+
+       /* issue r/w command if this is not a ATA DMA command*/
+       if (qc->tf.protocol != ATA_PROT_DMA)
+               ap->ops->exec_command(ap, &qc->tf);
+}
+
+/**
+ *     k2_bmdma_start_mmio - Start a PCI IDE BMDMA transaction (MMIO)
+ *     @qc: Info associated with this ATA transaction.
+ *
+ *     LOCKING:
+ *     spin_lock_irqsave(host_set lock)
+ */
+
+static void k2_bmdma_start_mmio (struct ata_queued_cmd *qc)
+{
+       struct ata_port *ap = qc->ap;
+       void *mmio = (void *) ap->ioaddr.bmdma_addr;
+       u8 dmactl;
+
+       /* start host DMA transaction */
+       dmactl = readb(mmio + ATA_DMA_CMD);
+       writeb(dmactl | ATA_DMA_START, mmio + ATA_DMA_CMD);
+       /* There is a race condition in certain SATA controllers that can
+          be seen when the r/w command is given to the controller before the
+          host DMA is started. On a Read command, the controller would initiate
+          the command to the drive even before it sees the DMA start. When there
+          are very fast drives connected to the controller, or when the data request
+          hits in the drive cache, there is the possibility that the drive returns a part
+          or all of the requested data to the controller before the DMA start is issued.
+          In this case, the controller would become confused as to what to do with the data.
+          In the worst case when all the data is returned back to the controller, the
+          controller could hang. In other cases it could return partial data returning
+          in data corruption. This problem has been seen in PPC systems and can also appear
+          on an system with very fast disks, where the SATA controller is sitting behind a
+          number of bridges, and hence there is significant latency between the r/w command
+          and the start command. */
+       /* issue r/w command if the access is to ATA*/
+       if (qc->tf.protocol == ATA_PROT_DMA)
+               ap->ops->exec_command(ap, &qc->tf);
+}
+
+
+static u8 k2_stat_check_status(struct ata_port *ap)
+{
+               return readl((void *) ap->ioaddr.status_addr);
+}
+
+#ifdef CONFIG_PPC_OF
+/*
+ * k2_sata_proc_info
+ * inout : decides on the direction of the dataflow and the meaning of the
+ *        variables
+ * buffer: If inout==FALSE data is being written to it else read from it
+ * *start: If inout==FALSE start of the valid data in the buffer
+ * offset: If inout==FALSE offset from the beginning of the imaginary file
+ *        from which we start writing into the buffer
+ * length: If inout==FALSE max number of bytes to be written into the buffer
+ *        else number of bytes in the buffer
+ */
+static int k2_sata_proc_info(struct Scsi_Host *shost, char *page, char **start,
+                            off_t offset, int count, int inout)
+{
+       struct ata_port *ap;
+       struct device_node *np;
+       int len, index;
+
+       /* Find  the ata_port */
+       ap = ata_shost_to_port(shost);
+       if (ap == NULL)
+               return 0;
+
+       /* Find the OF node for the PCI device proper */
+       np = pci_device_to_OF_node(to_pci_dev(ap->host_set->dev));
+       if (np == NULL)
+               return 0;
+
+       /* Match it to a port node */
+       index = (ap == ap->host_set->ports[0]) ? 0 : 1;
+       for (np = np->child; np != NULL; np = np->sibling) {
+               u32 *reg = (u32 *)get_property(np, "reg", NULL);
+               if (!reg)
+                       continue;
+               if (index == *reg)
+                       break;
+       }
+       if (np == NULL)
+               return 0;
+
+       len = sprintf(page, "devspec: %s\n", np->full_name);
+
+       return len;
+}
+#endif /* CONFIG_PPC_OF */
+
+
+static struct scsi_host_template k2_sata_sht = {
+       .module                 = THIS_MODULE,
+       .name                   = DRV_NAME,
+       .ioctl                  = ata_scsi_ioctl,
+       .queuecommand           = ata_scsi_queuecmd,
+       .can_queue              = ATA_DEF_QUEUE,
+       .this_id                = ATA_SHT_THIS_ID,
+       .sg_tablesize           = LIBATA_MAX_PRD,
+       .cmd_per_lun            = ATA_SHT_CMD_PER_LUN,
+       .emulated               = ATA_SHT_EMULATED,
+       .use_clustering         = ATA_SHT_USE_CLUSTERING,
+       .proc_name              = DRV_NAME,
+       .dma_boundary           = ATA_DMA_BOUNDARY,
+       .slave_configure        = ata_scsi_slave_config,
+       .slave_destroy          = ata_scsi_slave_destroy,
+#ifdef CONFIG_PPC_OF
+       .proc_info              = k2_sata_proc_info,
+#endif
+       .bios_param             = ata_std_bios_param,
+};
+
+
+static const struct ata_port_operations k2_sata_ops = {
+       .port_disable           = ata_port_disable,
+       .tf_load                = k2_sata_tf_load,
+       .tf_read                = k2_sata_tf_read,
+       .check_status           = k2_stat_check_status,
+       .exec_command           = ata_exec_command,
+       .dev_select             = ata_std_dev_select,
+       .bmdma_setup            = k2_bmdma_setup_mmio,
+       .bmdma_start            = k2_bmdma_start_mmio,
+       .bmdma_stop             = ata_bmdma_stop,
+       .bmdma_status           = ata_bmdma_status,
+       .qc_prep                = ata_qc_prep,
+       .qc_issue               = ata_qc_issue_prot,
+       .data_xfer              = ata_mmio_data_xfer,
+       .freeze                 = ata_bmdma_freeze,
+       .thaw                   = ata_bmdma_thaw,
+       .error_handler          = ata_bmdma_error_handler,
+       .post_internal_cmd      = ata_bmdma_post_internal_cmd,
+       .irq_handler            = ata_interrupt,
+       .irq_clear              = ata_bmdma_irq_clear,
+       .scr_read               = k2_sata_scr_read,
+       .scr_write              = k2_sata_scr_write,
+       .port_start             = ata_port_start,
+       .port_stop              = ata_port_stop,
+       .host_stop              = ata_pci_host_stop,
+};
+
+static void k2_sata_setup_port(struct ata_ioports *port, unsigned long base)
+{
+       port->cmd_addr          = base + K2_SATA_TF_CMD_OFFSET;
+       port->data_addr         = base + K2_SATA_TF_DATA_OFFSET;
+       port->feature_addr      =
+       port->error_addr        = base + K2_SATA_TF_ERROR_OFFSET;
+       port->nsect_addr        = base + K2_SATA_TF_NSECT_OFFSET;
+       port->lbal_addr         = base + K2_SATA_TF_LBAL_OFFSET;
+       port->lbam_addr         = base + K2_SATA_TF_LBAM_OFFSET;
+       port->lbah_addr         = base + K2_SATA_TF_LBAH_OFFSET;
+       port->device_addr       = base + K2_SATA_TF_DEVICE_OFFSET;
+       port->command_addr      =
+       port->status_addr       = base + K2_SATA_TF_CMDSTAT_OFFSET;
+       port->altstatus_addr    =
+       port->ctl_addr          = base + K2_SATA_TF_CTL_OFFSET;
+       port->bmdma_addr        = base + K2_SATA_DMA_CMD_OFFSET;
+       port->scr_addr          = base + K2_SATA_SCR_STATUS_OFFSET;
+}
+
+
+static int k2_sata_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
+{
+       static int printed_version;
+       struct ata_probe_ent *probe_ent = NULL;
+       unsigned long base;
+       void __iomem *mmio_base;
+       int pci_dev_busy = 0;
+       int rc;
+       int i;
+
+       if (!printed_version++)
+               dev_printk(KERN_DEBUG, &pdev->dev, "version " DRV_VERSION "\n");
+
+       /*
+        * If this driver happens to only be useful on Apple's K2, then
+        * we should check that here as it has a normal Serverworks ID
+        */
+       rc = pci_enable_device(pdev);
+       if (rc)
+               return rc;
+       /*
+        * Check if we have resources mapped at all (second function may
+        * have been disabled by firmware)
+        */
+       if (pci_resource_len(pdev, 5) == 0)
+               return -ENODEV;
+
+       /* Request PCI regions */
+       rc = pci_request_regions(pdev, DRV_NAME);
+       if (rc) {
+               pci_dev_busy = 1;
+               goto err_out;
+       }
+
+       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;
+
+       probe_ent = kmalloc(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);
+
+       mmio_base = pci_iomap(pdev, 5, 0);
+       if (mmio_base == NULL) {
+               rc = -ENOMEM;
+               goto err_out_free_ent;
+       }
+       base = (unsigned long) mmio_base;
+
+       /* Clear a magic bit in SCR1 according to Darwin, those help
+        * some funky seagate drives (though so far, those were already
+        * set by the firmware on the machines I had access to)
+        */
+       writel(readl(mmio_base + K2_SATA_SICR1_OFFSET) & ~0x00040000,
+              mmio_base + K2_SATA_SICR1_OFFSET);
+
+       /* Clear SATA error & interrupts we don't use */
+       writel(0xffffffff, mmio_base + K2_SATA_SCR_ERROR_OFFSET);
+       writel(0x0, mmio_base + K2_SATA_SIM_OFFSET);
+
+       probe_ent->sht = &k2_sata_sht;
+       probe_ent->host_flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
+                               ATA_FLAG_MMIO;
+       probe_ent->port_ops = &k2_sata_ops;
+       probe_ent->n_ports = 4;
+       probe_ent->irq = pdev->irq;
+       probe_ent->irq_flags = IRQF_SHARED;
+       probe_ent->mmio_base = mmio_base;
+
+       /* We don't care much about the PIO/UDMA masks, but the core won't like us
+        * if we don't fill these
+        */
+       probe_ent->pio_mask = 0x1f;
+       probe_ent->mwdma_mask = 0x7;
+       probe_ent->udma_mask = 0x7f;
+
+       /* different controllers have different number of ports - currently 4 or 8 */
+       /* All ports are on the same function. Multi-function device is no
+        * longer available. This should not be seen in any system. */
+       for (i = 0; i < ent->driver_data; i++)
+               k2_sata_setup_port(&probe_ent->port[i], base + i * K2_SATA_PORT_OFFSET);
+
+       pci_set_master(pdev);
+
+       /* FIXME: check ata_device_add return value */
+       ata_device_add(probe_ent);
+       kfree(probe_ent);
+
+       return 0;
+
+err_out_free_ent:
+       kfree(probe_ent);
+err_out_regions:
+       pci_release_regions(pdev);
+err_out:
+       if (!pci_dev_busy)
+               pci_disable_device(pdev);
+       return rc;
+}
+
+/* 0x240 is device ID for Apple K2 device
+ * 0x241 is device ID for Serverworks Frodo4
+ * 0x242 is device ID for Serverworks Frodo8
+ * 0x24a is device ID for BCM5785 (aka HT1000) HT southbridge integrated SATA
+ * controller
+ * */
+static const struct pci_device_id k2_sata_pci_tbl[] = {
+       { 0x1166, 0x0240, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 4 },
+       { 0x1166, 0x0241, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 4 },
+       { 0x1166, 0x0242, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 8 },
+       { 0x1166, 0x024a, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 4 },
+       { 0x1166, 0x024b, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 4 },
+       { }
+};
+
+
+static struct pci_driver k2_sata_pci_driver = {
+       .name                   = DRV_NAME,
+       .id_table               = k2_sata_pci_tbl,
+       .probe                  = k2_sata_init_one,
+       .remove                 = ata_pci_remove_one,
+};
+
+
+static int __init k2_sata_init(void)
+{
+       return pci_register_driver(&k2_sata_pci_driver);
+}
+
+
+static void __exit k2_sata_exit(void)
+{
+       pci_unregister_driver(&k2_sata_pci_driver);
+}
+
+
+MODULE_AUTHOR("Benjamin Herrenschmidt");
+MODULE_DESCRIPTION("low-level driver for K2 SATA controller");
+MODULE_LICENSE("GPL");
+MODULE_DEVICE_TABLE(pci, k2_sata_pci_tbl);
+MODULE_VERSION(DRV_VERSION);
+
+module_init(k2_sata_init);
+module_exit(k2_sata_exit);
diff --git a/drivers/ata/sata_sx4.c b/drivers/ata/sata_sx4.c
new file mode 100644 (file)
index 0000000..0da83cb
--- /dev/null
@@ -0,0 +1,1502 @@
+/*
+ *  sata_sx4.c - Promise SATA
+ *
+ *  Maintained by:  Jeff Garzik <jgarzik@pobox.com>
+ *                 Please ALWAYS copy linux-ide@vger.kernel.org
+ *                 on emails.
+ *
+ *  Copyright 2003-2004 Red Hat, Inc.
+ *
+ *
+ *  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 under NDA.
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/pci.h>
+#include <linux/init.h>
+#include <linux/blkdev.h>
+#include <linux/delay.h>
+#include <linux/interrupt.h>
+#include <linux/sched.h>
+#include <linux/device.h>
+#include <scsi/scsi_host.h>
+#include <scsi/scsi_cmnd.h>
+#include <linux/libata.h>
+#include <asm/io.h>
+#include "sata_promise.h"
+
+#define DRV_NAME       "sata_sx4"
+#define DRV_VERSION    "0.9"
+
+
+enum {
+       PDC_PRD_TBL             = 0x44, /* Direct command DMA table addr */
+
+       PDC_PKT_SUBMIT          = 0x40, /* Command packet pointer addr */
+       PDC_HDMA_PKT_SUBMIT     = 0x100, /* Host DMA packet pointer addr */
+       PDC_INT_SEQMASK         = 0x40, /* Mask of asserted SEQ INTs */
+       PDC_HDMA_CTLSTAT        = 0x12C, /* Host DMA control / status */
+
+       PDC_20621_SEQCTL        = 0x400,
+       PDC_20621_SEQMASK       = 0x480,
+       PDC_20621_GENERAL_CTL   = 0x484,
+       PDC_20621_PAGE_SIZE     = (32 * 1024),
+
+       /* chosen, not constant, values; we design our own DIMM mem map */
+       PDC_20621_DIMM_WINDOW   = 0x0C, /* page# for 32K DIMM window */
+       PDC_20621_DIMM_BASE     = 0x00200000,
+       PDC_20621_DIMM_DATA     = (64 * 1024),
+       PDC_DIMM_DATA_STEP      = (256 * 1024),
+       PDC_DIMM_WINDOW_STEP    = (8 * 1024),
+       PDC_DIMM_HOST_PRD       = (6 * 1024),
+       PDC_DIMM_HOST_PKT       = (128 * 0),
+       PDC_DIMM_HPKT_PRD       = (128 * 1),
+       PDC_DIMM_ATA_PKT        = (128 * 2),
+       PDC_DIMM_APKT_PRD       = (128 * 3),
+       PDC_DIMM_HEADER_SZ      = PDC_DIMM_APKT_PRD + 128,
+       PDC_PAGE_WINDOW         = 0x40,
+       PDC_PAGE_DATA           = PDC_PAGE_WINDOW +
+                                 (PDC_20621_DIMM_DATA / PDC_20621_PAGE_SIZE),
+       PDC_PAGE_SET            = PDC_DIMM_DATA_STEP / PDC_20621_PAGE_SIZE,
+
+       PDC_CHIP0_OFS           = 0xC0000, /* offset of chip #0 */
+
+       PDC_20621_ERR_MASK      = (1<<19) | (1<<20) | (1<<21) | (1<<22) |
+                                 (1<<23),
+
+       board_20621             = 0,    /* FastTrak S150 SX4 */
+
+       PDC_RESET               = (1 << 11), /* HDMA reset */
+
+       PDC_MAX_HDMA            = 32,
+       PDC_HDMA_Q_MASK         = (PDC_MAX_HDMA - 1),
+
+       PDC_DIMM0_SPD_DEV_ADDRESS     = 0x50,
+       PDC_DIMM1_SPD_DEV_ADDRESS     = 0x51,
+       PDC_MAX_DIMM_MODULE           = 0x02,
+       PDC_I2C_CONTROL_OFFSET        = 0x48,
+       PDC_I2C_ADDR_DATA_OFFSET      = 0x4C,
+       PDC_DIMM0_CONTROL_OFFSET      = 0x80,
+       PDC_DIMM1_CONTROL_OFFSET      = 0x84,
+       PDC_SDRAM_CONTROL_OFFSET      = 0x88,
+       PDC_I2C_WRITE                 = 0x00000000,
+       PDC_I2C_READ                  = 0x00000040,
+       PDC_I2C_START                 = 0x00000080,
+       PDC_I2C_MASK_INT              = 0x00000020,
+       PDC_I2C_COMPLETE              = 0x00010000,
+       PDC_I2C_NO_ACK                = 0x00100000,
+       PDC_DIMM_SPD_SUBADDRESS_START = 0x00,
+       PDC_DIMM_SPD_SUBADDRESS_END   = 0x7F,
+       PDC_DIMM_SPD_ROW_NUM          = 3,
+       PDC_DIMM_SPD_COLUMN_NUM       = 4,
+       PDC_DIMM_SPD_MODULE_ROW       = 5,
+       PDC_DIMM_SPD_TYPE             = 11,
+       PDC_DIMM_SPD_FRESH_RATE       = 12,
+       PDC_DIMM_SPD_BANK_NUM         = 17,
+       PDC_DIMM_SPD_CAS_LATENCY      = 18,
+       PDC_DIMM_SPD_ATTRIBUTE        = 21,
+       PDC_DIMM_SPD_ROW_PRE_CHARGE   = 27,
+       PDC_DIMM_SPD_ROW_ACTIVE_DELAY = 28,
+       PDC_DIMM_SPD_RAS_CAS_DELAY    = 29,
+       PDC_DIMM_SPD_ACTIVE_PRECHARGE = 30,
+       PDC_DIMM_SPD_SYSTEM_FREQ      = 126,
+       PDC_CTL_STATUS                = 0x08,
+       PDC_DIMM_WINDOW_CTLR          = 0x0C,
+       PDC_TIME_CONTROL              = 0x3C,
+       PDC_TIME_PERIOD               = 0x40,
+       PDC_TIME_COUNTER              = 0x44,
+       PDC_GENERAL_CTLR              = 0x484,
+       PCI_PLL_INIT                  = 0x8A531824,
+       PCI_X_TCOUNT                  = 0xEE1E5CFF
+};
+
+
+struct pdc_port_priv {
+       u8                      dimm_buf[(ATA_PRD_SZ * ATA_MAX_PRD) + 512];
+       u8                      *pkt;
+       dma_addr_t              pkt_dma;
+};
+
+struct pdc_host_priv {
+       void                    __iomem *dimm_mmio;
+
+       unsigned int            doing_hdma;
+       unsigned int            hdma_prod;
+       unsigned int            hdma_cons;
+       struct {
+               struct ata_queued_cmd *qc;
+               unsigned int    seq;
+               unsigned long   pkt_ofs;
+       } hdma[32];
+};
+
+
+static int pdc_sata_init_one (struct pci_dev *pdev, const struct pci_device_id *ent);
+static irqreturn_t pdc20621_interrupt (int irq, void *dev_instance, struct pt_regs *regs);
+static void pdc_eng_timeout(struct ata_port *ap);
+static void pdc_20621_phy_reset (struct ata_port *ap);
+static int pdc_port_start(struct ata_port *ap);
+static void pdc_port_stop(struct ata_port *ap);
+static void pdc20621_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 pdc20621_host_stop(struct ata_host_set *host_set);
+static unsigned int pdc20621_dimm_init(struct ata_probe_ent *pe);
+static int pdc20621_detect_dimm(struct ata_probe_ent *pe);
+static unsigned int pdc20621_i2c_read(struct ata_probe_ent *pe,
+                                     u32 device, u32 subaddr, u32 *pdata);
+static int pdc20621_prog_dimm0(struct ata_probe_ent *pe);
+static unsigned int pdc20621_prog_dimm_global(struct ata_probe_ent *pe);
+#ifdef ATA_VERBOSE_DEBUG
+static void pdc20621_get_from_dimm(struct ata_probe_ent *pe,
+                                  void *psource, u32 offset, u32 size);
+#endif
+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 unsigned int pdc20621_qc_issue_prot(struct ata_queued_cmd *qc);
+
+
+static struct scsi_host_template pdc_sata_sht = {
+       .module                 = THIS_MODULE,
+       .name                   = DRV_NAME,
+       .ioctl                  = ata_scsi_ioctl,
+       .queuecommand           = ata_scsi_queuecmd,
+       .can_queue              = ATA_DEF_QUEUE,
+       .this_id                = ATA_SHT_THIS_ID,
+       .sg_tablesize           = LIBATA_MAX_PRD,
+       .cmd_per_lun            = ATA_SHT_CMD_PER_LUN,
+       .emulated               = ATA_SHT_EMULATED,
+       .use_clustering         = ATA_SHT_USE_CLUSTERING,
+       .proc_name              = DRV_NAME,
+       .dma_boundary           = ATA_DMA_BOUNDARY,
+       .slave_configure        = ata_scsi_slave_config,
+       .slave_destroy          = ata_scsi_slave_destroy,
+       .bios_param             = ata_std_bios_param,
+};
+
+static const struct ata_port_operations pdc_20621_ops = {
+       .port_disable           = ata_port_disable,
+       .tf_load                = pdc_tf_load_mmio,
+       .tf_read                = ata_tf_read,
+       .check_status           = ata_check_status,
+       .exec_command           = pdc_exec_command_mmio,
+       .dev_select             = ata_std_dev_select,
+       .phy_reset              = pdc_20621_phy_reset,
+       .qc_prep                = pdc20621_qc_prep,
+       .qc_issue               = pdc20621_qc_issue_prot,
+       .data_xfer              = ata_mmio_data_xfer,
+       .eng_timeout            = pdc_eng_timeout,
+       .irq_handler            = pdc20621_interrupt,
+       .irq_clear              = pdc20621_irq_clear,
+       .port_start             = pdc_port_start,
+       .port_stop              = pdc_port_stop,
+       .host_stop              = pdc20621_host_stop,
+};
+
+static const struct ata_port_info pdc_port_info[] = {
+       /* board_20621 */
+       {
+               .sht            = &pdc_sata_sht,
+               .host_flags     = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
+                                 ATA_FLAG_SRST | ATA_FLAG_MMIO |
+                                 ATA_FLAG_NO_ATAPI | ATA_FLAG_PIO_POLLING,
+               .pio_mask       = 0x1f, /* pio0-4 */
+               .mwdma_mask     = 0x07, /* mwdma0-2 */
+               .udma_mask      = 0x7f, /* udma0-6 ; FIXME */
+               .port_ops       = &pdc_20621_ops,
+       },
+
+};
+
+static const struct pci_device_id pdc_sata_pci_tbl[] = {
+       { PCI_VENDOR_ID_PROMISE, 0x6622, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+         board_20621 },
+       { }     /* terminate list */
+};
+
+
+static struct pci_driver pdc_sata_pci_driver = {
+       .name                   = DRV_NAME,
+       .id_table               = pdc_sata_pci_tbl,
+       .probe                  = pdc_sata_init_one,
+       .remove                 = ata_pci_remove_one,
+};
+
+
+static void pdc20621_host_stop(struct ata_host_set *host_set)
+{
+       struct pci_dev *pdev = to_pci_dev(host_set->dev);
+       struct pdc_host_priv *hpriv = host_set->private_data;
+       void __iomem *dimm_mmio = hpriv->dimm_mmio;
+
+       pci_iounmap(pdev, dimm_mmio);
+       kfree(hpriv);
+
+       pci_iounmap(pdev, host_set->mmio_base);
+}
+
+static int pdc_port_start(struct ata_port *ap)
+{
+       struct device *dev = ap->host_set->dev;
+       struct pdc_port_priv *pp;
+       int rc;
+
+       rc = ata_port_start(ap);
+       if (rc)
+               return rc;
+
+       pp = kmalloc(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) {
+               rc = -ENOMEM;
+               goto err_out_kfree;
+       }
+
+       ap->private_data = pp;
+
+       return 0;
+
+err_out_kfree:
+       kfree(pp);
+err_out:
+       ata_port_stop(ap);
+       return rc;
+}
+
+
+static void pdc_port_stop(struct ata_port *ap)
+{
+       struct device *dev = ap->host_set->dev;
+       struct pdc_port_priv *pp = ap->private_data;
+
+       ap->private_data = NULL;
+       dma_free_coherent(dev, 128, pp->pkt, pp->pkt_dma);
+       kfree(pp);
+       ata_port_stop(ap);
+}
+
+
+static void pdc_20621_phy_reset (struct ata_port *ap)
+{
+       VPRINTK("ENTER\n");
+        ap->cbl = ATA_CBL_SATA;
+        ata_port_probe(ap);
+        ata_bus_reset(ap);
+}
+
+static inline void pdc20621_ata_sg(struct ata_taskfile *tf, u8 *buf,
+                                          unsigned int portno,
+                                          unsigned int total_len)
+{
+       u32 addr;
+       unsigned int dw = PDC_DIMM_APKT_PRD >> 2;
+       u32 *buf32 = (u32 *) buf;
+
+       /* output ATA packet S/G table */
+       addr = PDC_20621_DIMM_BASE + PDC_20621_DIMM_DATA +
+              (PDC_DIMM_DATA_STEP * portno);
+       VPRINTK("ATA sg addr 0x%x, %d\n", addr, addr);
+       buf32[dw] = cpu_to_le32(addr);
+       buf32[dw + 1] = cpu_to_le32(total_len | ATA_PRD_EOT);
+
+       VPRINTK("ATA PSG @ %x == (0x%x, 0x%x)\n",
+               PDC_20621_DIMM_BASE +
+                      (PDC_DIMM_WINDOW_STEP * portno) +
+                      PDC_DIMM_APKT_PRD,
+               buf32[dw], buf32[dw + 1]);
+}
+
+static inline void pdc20621_host_sg(struct ata_taskfile *tf, u8 *buf,
+                                           unsigned int portno,
+                                           unsigned int total_len)
+{
+       u32 addr;
+       unsigned int dw = PDC_DIMM_HPKT_PRD >> 2;
+       u32 *buf32 = (u32 *) buf;
+
+       /* output Host DMA packet S/G table */
+       addr = PDC_20621_DIMM_BASE + PDC_20621_DIMM_DATA +
+              (PDC_DIMM_DATA_STEP * portno);
+
+       buf32[dw] = cpu_to_le32(addr);
+       buf32[dw + 1] = cpu_to_le32(total_len | ATA_PRD_EOT);
+
+       VPRINTK("HOST PSG @ %x == (0x%x, 0x%x)\n",
+               PDC_20621_DIMM_BASE +
+                      (PDC_DIMM_WINDOW_STEP * portno) +
+                      PDC_DIMM_HPKT_PRD,
+               buf32[dw], buf32[dw + 1]);
+}
+
+static inline unsigned int pdc20621_ata_pkt(struct ata_taskfile *tf,
+                                           unsigned int devno, u8 *buf,
+                                           unsigned int portno)
+{
+       unsigned int i, dw;
+       u32 *buf32 = (u32 *) buf;
+       u8 dev_reg;
+
+       unsigned int dimm_sg = PDC_20621_DIMM_BASE +
+                              (PDC_DIMM_WINDOW_STEP * portno) +
+                              PDC_DIMM_APKT_PRD;
+       VPRINTK("ENTER, dimm_sg == 0x%x, %d\n", dimm_sg, dimm_sg);
+
+       i = PDC_DIMM_ATA_PKT;
+
+       /*
+        * Set up ATA packet
+        */
+       if ((tf->protocol == ATA_PROT_DMA) && (!(tf->flags & ATA_TFLAG_WRITE)))
+               buf[i++] = PDC_PKT_READ;
+       else if (tf->protocol == ATA_PROT_NODATA)
+               buf[i++] = PDC_PKT_NODATA;
+       else
+               buf[i++] = 0;
+       buf[i++] = 0;                   /* reserved */
+       buf[i++] = portno + 1;          /* seq. id */
+       buf[i++] = 0xff;                /* delay seq. id */
+
+       /* dimm dma S/G, and next-pkt */
+       dw = i >> 2;
+       if (tf->protocol == ATA_PROT_NODATA)
+               buf32[dw] = 0;
+       else
+               buf32[dw] = cpu_to_le32(dimm_sg);
+       buf32[dw + 1] = 0;
+       i += 8;
+
+       if (devno == 0)
+               dev_reg = ATA_DEVICE_OBS;
+       else
+               dev_reg = ATA_DEVICE_OBS | ATA_DEV1;
+
+       /* select device */
+       buf[i++] = (1 << 5) | PDC_PKT_CLEAR_BSY | ATA_REG_DEVICE;
+       buf[i++] = dev_reg;
+
+       /* device control register */
+       buf[i++] = (1 << 5) | PDC_REG_DEVCTL;
+       buf[i++] = tf->ctl;
+
+       return i;
+}
+
+static inline void pdc20621_host_pkt(struct ata_taskfile *tf, u8 *buf,
+                                    unsigned int portno)
+{
+       unsigned int dw;
+       u32 tmp, *buf32 = (u32 *) buf;
+
+       unsigned int host_sg = PDC_20621_DIMM_BASE +
+                              (PDC_DIMM_WINDOW_STEP * portno) +
+                              PDC_DIMM_HOST_PRD;
+       unsigned int dimm_sg = PDC_20621_DIMM_BASE +
+                              (PDC_DIMM_WINDOW_STEP * portno) +
+                              PDC_DIMM_HPKT_PRD;
+       VPRINTK("ENTER, dimm_sg == 0x%x, %d\n", dimm_sg, dimm_sg);
+       VPRINTK("host_sg == 0x%x, %d\n", host_sg, host_sg);
+
+       dw = PDC_DIMM_HOST_PKT >> 2;
+
+       /*
+        * Set up Host DMA packet
+        */
+       if ((tf->protocol == ATA_PROT_DMA) && (!(tf->flags & ATA_TFLAG_WRITE)))
+               tmp = PDC_PKT_READ;
+       else
+               tmp = 0;
+       tmp |= ((portno + 1 + 4) << 16);        /* seq. id */
+       tmp |= (0xff << 24);                    /* delay seq. id */
+       buf32[dw + 0] = cpu_to_le32(tmp);
+       buf32[dw + 1] = cpu_to_le32(host_sg);
+       buf32[dw + 2] = cpu_to_le32(dimm_sg);
+       buf32[dw + 3] = 0;
+
+       VPRINTK("HOST PKT @ %x == (0x%x 0x%x 0x%x 0x%x)\n",
+               PDC_20621_DIMM_BASE + (PDC_DIMM_WINDOW_STEP * portno) +
+                       PDC_DIMM_HOST_PKT,
+               buf32[dw + 0],
+               buf32[dw + 1],
+               buf32[dw + 2],
+               buf32[dw + 3]);
+}
+
+static void pdc20621_dma_prep(struct ata_queued_cmd *qc)
+{
+       struct scatterlist *sg;
+       struct ata_port *ap = qc->ap;
+       struct pdc_port_priv *pp = ap->private_data;
+       void __iomem *mmio = ap->host_set->mmio_base;
+       struct pdc_host_priv *hpriv = ap->host_set->private_data;
+       void __iomem *dimm_mmio = hpriv->dimm_mmio;
+       unsigned int portno = ap->port_no;
+       unsigned int i, idx, total_len = 0, sgt_len;
+       u32 *buf = (u32 *) &pp->dimm_buf[PDC_DIMM_HEADER_SZ];
+
+       WARN_ON(!(qc->flags & ATA_QCFLAG_DMAMAP));
+
+       VPRINTK("ata%u: ENTER\n", ap->id);
+
+       /* hard-code chip #0 */
+       mmio += PDC_CHIP0_OFS;
+
+       /*
+        * Build S/G table
+        */
+       idx = 0;
+       ata_for_each_sg(sg, qc) {
+               buf[idx++] = cpu_to_le32(sg_dma_address(sg));
+               buf[idx++] = cpu_to_le32(sg_dma_len(sg));
+               total_len += sg_dma_len(sg);
+       }
+       buf[idx - 1] |= cpu_to_le32(ATA_PRD_EOT);
+       sgt_len = idx * 4;
+
+       /*
+        * Build ATA, host DMA packets
+        */
+       pdc20621_host_sg(&qc->tf, &pp->dimm_buf[0], portno, total_len);
+       pdc20621_host_pkt(&qc->tf, &pp->dimm_buf[0], portno);
+
+       pdc20621_ata_sg(&qc->tf, &pp->dimm_buf[0], portno, total_len);
+       i = pdc20621_ata_pkt(&qc->tf, qc->dev->devno, &pp->dimm_buf[0], portno);
+
+       if (qc->tf.flags & ATA_TFLAG_LBA48)
+               i = pdc_prep_lba48(&qc->tf, &pp->dimm_buf[0], i);
+       else
+               i = pdc_prep_lba28(&qc->tf, &pp->dimm_buf[0], i);
+
+       pdc_pkt_footer(&qc->tf, &pp->dimm_buf[0], i);
+
+       /* copy three S/G tables and two packets to DIMM MMIO window */
+       memcpy_toio(dimm_mmio + (portno * PDC_DIMM_WINDOW_STEP),
+                   &pp->dimm_buf, PDC_DIMM_HEADER_SZ);
+       memcpy_toio(dimm_mmio + (portno * PDC_DIMM_WINDOW_STEP) +
+                   PDC_DIMM_HOST_PRD,
+                   &pp->dimm_buf[PDC_DIMM_HEADER_SZ], sgt_len);
+
+       /* force host FIFO dump */
+       writel(0x00000001, mmio + PDC_20621_GENERAL_CTL);
+
+       readl(dimm_mmio);       /* MMIO PCI posting flush */
+
+       VPRINTK("ata pkt buf ofs %u, prd size %u, mmio copied\n", i, sgt_len);
+}
+
+static void pdc20621_nodata_prep(struct ata_queued_cmd *qc)
+{
+       struct ata_port *ap = qc->ap;
+       struct pdc_port_priv *pp = ap->private_data;
+       void __iomem *mmio = ap->host_set->mmio_base;
+       struct pdc_host_priv *hpriv = ap->host_set->private_data;
+       void __iomem *dimm_mmio = hpriv->dimm_mmio;
+       unsigned int portno = ap->port_no;
+       unsigned int i;
+
+       VPRINTK("ata%u: ENTER\n", ap->id);
+
+       /* hard-code chip #0 */
+       mmio += PDC_CHIP0_OFS;
+
+       i = pdc20621_ata_pkt(&qc->tf, qc->dev->devno, &pp->dimm_buf[0], portno);
+
+       if (qc->tf.flags & ATA_TFLAG_LBA48)
+               i = pdc_prep_lba48(&qc->tf, &pp->dimm_buf[0], i);
+       else
+               i = pdc_prep_lba28(&qc->tf, &pp->dimm_buf[0], i);
+
+       pdc_pkt_footer(&qc->tf, &pp->dimm_buf[0], i);
+
+       /* copy three S/G tables and two packets to DIMM MMIO window */
+       memcpy_toio(dimm_mmio + (portno * PDC_DIMM_WINDOW_STEP),
+                   &pp->dimm_buf, PDC_DIMM_HEADER_SZ);
+
+       /* force host FIFO dump */
+       writel(0x00000001, mmio + PDC_20621_GENERAL_CTL);
+
+       readl(dimm_mmio);       /* MMIO PCI posting flush */
+
+       VPRINTK("ata pkt buf ofs %u, mmio copied\n", i);
+}
+
+static void pdc20621_qc_prep(struct ata_queued_cmd *qc)
+{
+       switch (qc->tf.protocol) {
+       case ATA_PROT_DMA:
+               pdc20621_dma_prep(qc);
+               break;
+       case ATA_PROT_NODATA:
+               pdc20621_nodata_prep(qc);
+               break;
+       default:
+               break;
+       }
+}
+
+static void __pdc20621_push_hdma(struct ata_queued_cmd *qc,
+                                unsigned int seq,
+                                u32 pkt_ofs)
+{
+       struct ata_port *ap = qc->ap;
+       struct ata_host_set *host_set = ap->host_set;
+       void __iomem *mmio = host_set->mmio_base;
+
+       /* hard-code chip #0 */
+       mmio += PDC_CHIP0_OFS;
+
+       writel(0x00000001, mmio + PDC_20621_SEQCTL + (seq * 4));
+       readl(mmio + PDC_20621_SEQCTL + (seq * 4));     /* flush */
+
+       writel(pkt_ofs, mmio + PDC_HDMA_PKT_SUBMIT);
+       readl(mmio + PDC_HDMA_PKT_SUBMIT);      /* flush */
+}
+
+static void pdc20621_push_hdma(struct ata_queued_cmd *qc,
+                               unsigned int seq,
+                               u32 pkt_ofs)
+{
+       struct ata_port *ap = qc->ap;
+       struct pdc_host_priv *pp = ap->host_set->private_data;
+       unsigned int idx = pp->hdma_prod & PDC_HDMA_Q_MASK;
+
+       if (!pp->doing_hdma) {
+               __pdc20621_push_hdma(qc, seq, pkt_ofs);
+               pp->doing_hdma = 1;
+               return;
+       }
+
+       pp->hdma[idx].qc = qc;
+       pp->hdma[idx].seq = seq;
+       pp->hdma[idx].pkt_ofs = pkt_ofs;
+       pp->hdma_prod++;
+}
+
+static void pdc20621_pop_hdma(struct ata_queued_cmd *qc)
+{
+       struct ata_port *ap = qc->ap;
+       struct pdc_host_priv *pp = ap->host_set->private_data;
+       unsigned int idx = pp->hdma_cons & PDC_HDMA_Q_MASK;
+
+       /* if nothing on queue, we're done */
+       if (pp->hdma_prod == pp->hdma_cons) {
+               pp->doing_hdma = 0;
+               return;
+       }
+
+       __pdc20621_push_hdma(pp->hdma[idx].qc, pp->hdma[idx].seq,
+                            pp->hdma[idx].pkt_ofs);
+       pp->hdma_cons++;
+}
+
+#ifdef ATA_VERBOSE_DEBUG
+static void pdc20621_dump_hdma(struct ata_queued_cmd *qc)
+{
+       struct ata_port *ap = qc->ap;
+       unsigned int port_no = ap->port_no;
+       struct pdc_host_priv *hpriv = ap->host_set->private_data;
+       void *dimm_mmio = hpriv->dimm_mmio;
+
+       dimm_mmio += (port_no * PDC_DIMM_WINDOW_STEP);
+       dimm_mmio += PDC_DIMM_HOST_PKT;
+
+       printk(KERN_ERR "HDMA[0] == 0x%08X\n", readl(dimm_mmio));
+       printk(KERN_ERR "HDMA[1] == 0x%08X\n", readl(dimm_mmio + 4));
+       printk(KERN_ERR "HDMA[2] == 0x%08X\n", readl(dimm_mmio + 8));
+       printk(KERN_ERR "HDMA[3] == 0x%08X\n", readl(dimm_mmio + 12));
+}
+#else
+static inline void pdc20621_dump_hdma(struct ata_queued_cmd *qc) { }
+#endif /* ATA_VERBOSE_DEBUG */
+
+static void pdc20621_packet_start(struct ata_queued_cmd *qc)
+{
+       struct ata_port *ap = qc->ap;
+       struct ata_host_set *host_set = ap->host_set;
+       unsigned int port_no = ap->port_no;
+       void __iomem *mmio = host_set->mmio_base;
+       unsigned int rw = (qc->tf.flags & ATA_TFLAG_WRITE);
+       u8 seq = (u8) (port_no + 1);
+       unsigned int port_ofs;
+
+       /* hard-code chip #0 */
+       mmio += PDC_CHIP0_OFS;
+
+       VPRINTK("ata%u: ENTER\n", ap->id);
+
+       wmb();                  /* flush PRD, pkt writes */
+
+       port_ofs = PDC_20621_DIMM_BASE + (PDC_DIMM_WINDOW_STEP * port_no);
+
+       /* if writing, we (1) DMA to DIMM, then (2) do ATA command */
+       if (rw && qc->tf.protocol == ATA_PROT_DMA) {
+               seq += 4;
+
+               pdc20621_dump_hdma(qc);
+               pdc20621_push_hdma(qc, seq, port_ofs + PDC_DIMM_HOST_PKT);
+               VPRINTK("queued ofs 0x%x (%u), seq %u\n",
+                       port_ofs + PDC_DIMM_HOST_PKT,
+                       port_ofs + PDC_DIMM_HOST_PKT,
+                       seq);
+       } else {
+               writel(0x00000001, mmio + PDC_20621_SEQCTL + (seq * 4));
+               readl(mmio + PDC_20621_SEQCTL + (seq * 4));     /* flush */
+
+               writel(port_ofs + PDC_DIMM_ATA_PKT,
+                      (void __iomem *) ap->ioaddr.cmd_addr + PDC_PKT_SUBMIT);
+               readl((void __iomem *) ap->ioaddr.cmd_addr + PDC_PKT_SUBMIT);
+               VPRINTK("submitted ofs 0x%x (%u), seq %u\n",
+                       port_ofs + PDC_DIMM_ATA_PKT,
+                       port_ofs + PDC_DIMM_ATA_PKT,
+                       seq);
+       }
+}
+
+static unsigned int pdc20621_qc_issue_prot(struct ata_queued_cmd *qc)
+{
+       switch (qc->tf.protocol) {
+       case ATA_PROT_DMA:
+       case ATA_PROT_NODATA:
+               pdc20621_packet_start(qc);
+               return 0;
+
+       case ATA_PROT_ATAPI_DMA:
+               BUG();
+               break;
+
+       default:
+               break;
+       }
+
+       return ata_qc_issue_prot(qc);
+}
+
+static inline unsigned int pdc20621_host_intr( struct ata_port *ap,
+                                          struct ata_queued_cmd *qc,
+                                         unsigned int doing_hdma,
+                                         void __iomem *mmio)
+{
+       unsigned int port_no = ap->port_no;
+       unsigned int port_ofs =
+               PDC_20621_DIMM_BASE + (PDC_DIMM_WINDOW_STEP * port_no);
+       u8 status;
+       unsigned int handled = 0;
+
+       VPRINTK("ENTER\n");
+
+       if ((qc->tf.protocol == ATA_PROT_DMA) &&        /* read */
+           (!(qc->tf.flags & ATA_TFLAG_WRITE))) {
+
+               /* step two - DMA from DIMM to host */
+               if (doing_hdma) {
+                       VPRINTK("ata%u: read hdma, 0x%x 0x%x\n", ap->id,
+                               readl(mmio + 0x104), readl(mmio + PDC_HDMA_CTLSTAT));
+                       /* get drive status; clear intr; complete txn */
+                       qc->err_mask |= ac_err_mask(ata_wait_idle(ap));
+                       ata_qc_complete(qc);
+                       pdc20621_pop_hdma(qc);
+               }
+
+               /* step one - exec ATA command */
+               else {
+                       u8 seq = (u8) (port_no + 1 + 4);
+                       VPRINTK("ata%u: read ata, 0x%x 0x%x\n", ap->id,
+                               readl(mmio + 0x104), readl(mmio + PDC_HDMA_CTLSTAT));
+
+                       /* submit hdma pkt */
+                       pdc20621_dump_hdma(qc);
+                       pdc20621_push_hdma(qc, seq,
+                                          port_ofs + PDC_DIMM_HOST_PKT);
+               }
+               handled = 1;
+
+       } else if (qc->tf.protocol == ATA_PROT_DMA) {   /* write */
+
+               /* step one - DMA from host to DIMM */
+               if (doing_hdma) {
+                       u8 seq = (u8) (port_no + 1);
+                       VPRINTK("ata%u: write hdma, 0x%x 0x%x\n", ap->id,
+                               readl(mmio + 0x104), readl(mmio + PDC_HDMA_CTLSTAT));
+
+                       /* submit ata pkt */
+                       writel(0x00000001, mmio + PDC_20621_SEQCTL + (seq * 4));
+                       readl(mmio + PDC_20621_SEQCTL + (seq * 4));
+                       writel(port_ofs + PDC_DIMM_ATA_PKT,
+                              (void __iomem *) ap->ioaddr.cmd_addr + PDC_PKT_SUBMIT);
+                       readl((void __iomem *) ap->ioaddr.cmd_addr + PDC_PKT_SUBMIT);
+               }
+
+               /* step two - execute ATA command */
+               else {
+                       VPRINTK("ata%u: write ata, 0x%x 0x%x\n", ap->id,
+                               readl(mmio + 0x104), readl(mmio + PDC_HDMA_CTLSTAT));
+                       /* get drive status; clear intr; complete txn */
+                       qc->err_mask |= ac_err_mask(ata_wait_idle(ap));
+                       ata_qc_complete(qc);
+                       pdc20621_pop_hdma(qc);
+               }
+               handled = 1;
+
+       /* command completion, but no data xfer */
+       } else if (qc->tf.protocol == ATA_PROT_NODATA) {
+
+               status = ata_busy_wait(ap, ATA_BUSY | ATA_DRQ, 1000);
+               DPRINTK("BUS_NODATA (drv_stat 0x%X)\n", status);
+               qc->err_mask |= ac_err_mask(status);
+               ata_qc_complete(qc);
+               handled = 1;
+
+       } else {
+               ap->stats.idle_irq++;
+       }
+
+       return handled;
+}
+
+static void pdc20621_irq_clear(struct ata_port *ap)
+{
+       struct ata_host_set *host_set = ap->host_set;
+       void __iomem *mmio = host_set->mmio_base;
+
+       mmio += PDC_CHIP0_OFS;
+
+       readl(mmio + PDC_20621_SEQMASK);
+}
+
+static irqreturn_t pdc20621_interrupt (int irq, void *dev_instance, struct pt_regs *regs)
+{
+       struct ata_host_set *host_set = dev_instance;
+       struct ata_port *ap;
+       u32 mask = 0;
+       unsigned int i, tmp, port_no;
+       unsigned int handled = 0;
+       void __iomem *mmio_base;
+
+       VPRINTK("ENTER\n");
+
+       if (!host_set || !host_set->mmio_base) {
+               VPRINTK("QUICK EXIT\n");
+               return IRQ_NONE;
+       }
+
+       mmio_base = host_set->mmio_base;
+
+       /* reading should also clear interrupts */
+       mmio_base += PDC_CHIP0_OFS;
+       mask = readl(mmio_base + PDC_20621_SEQMASK);
+       VPRINTK("mask == 0x%x\n", mask);
+
+       if (mask == 0xffffffff) {
+               VPRINTK("QUICK EXIT 2\n");
+               return IRQ_NONE;
+       }
+       mask &= 0xffff;         /* only 16 tags possible */
+       if (!mask) {
+               VPRINTK("QUICK EXIT 3\n");
+               return IRQ_NONE;
+       }
+
+        spin_lock(&host_set->lock);
+
+        for (i = 1; i < 9; i++) {
+               port_no = i - 1;
+               if (port_no > 3)
+                       port_no -= 4;
+               if (port_no >= host_set->n_ports)
+                       ap = NULL;
+               else
+                       ap = host_set->ports[port_no];
+               tmp = mask & (1 << i);
+               VPRINTK("seq %u, port_no %u, ap %p, tmp %x\n", i, port_no, ap, tmp);
+               if (tmp && ap &&
+                   !(ap->flags & ATA_FLAG_DISABLED)) {
+                       struct ata_queued_cmd *qc;
+
+                       qc = ata_qc_from_tag(ap, ap->active_tag);
+                       if (qc && (!(qc->tf.flags & ATA_TFLAG_POLLING)))
+                               handled += pdc20621_host_intr(ap, qc, (i > 4),
+                                                             mmio_base);
+               }
+       }
+
+        spin_unlock(&host_set->lock);
+
+       VPRINTK("mask == 0x%x\n", mask);
+
+       VPRINTK("EXIT\n");
+
+       return IRQ_RETVAL(handled);
+}
+
+static void pdc_eng_timeout(struct ata_port *ap)
+{
+       u8 drv_stat;
+       struct ata_host_set *host_set = ap->host_set;
+       struct ata_queued_cmd *qc;
+       unsigned long flags;
+
+       DPRINTK("ENTER\n");
+
+       spin_lock_irqsave(&host_set->lock, flags);
+
+       qc = ata_qc_from_tag(ap, ap->active_tag);
+
+       switch (qc->tf.protocol) {
+       case ATA_PROT_DMA:
+       case ATA_PROT_NODATA:
+               ata_port_printk(ap, KERN_ERR, "command timeout\n");
+               qc->err_mask |= __ac_err_mask(ata_wait_idle(ap));
+               break;
+
+       default:
+               drv_stat = ata_busy_wait(ap, ATA_BUSY | ATA_DRQ, 1000);
+
+               ata_port_printk(ap, KERN_ERR,
+                               "unknown timeout, cmd 0x%x stat 0x%x\n",
+                               qc->tf.command, drv_stat);
+
+               qc->err_mask |= ac_err_mask(drv_stat);
+               break;
+       }
+
+       spin_unlock_irqrestore(&host_set->lock, flags);
+       ata_eh_qc_complete(qc);
+       DPRINTK("EXIT\n");
+}
+
+static void pdc_tf_load_mmio(struct ata_port *ap, const struct ata_taskfile *tf)
+{
+       WARN_ON (tf->protocol == ATA_PROT_DMA ||
+                tf->protocol == ATA_PROT_NODATA);
+       ata_tf_load(ap, tf);
+}
+
+
+static void pdc_exec_command_mmio(struct ata_port *ap, const struct ata_taskfile *tf)
+{
+       WARN_ON (tf->protocol == ATA_PROT_DMA ||
+                tf->protocol == ATA_PROT_NODATA);
+       ata_exec_command(ap, tf);
+}
+
+
+static void pdc_sata_setup_port(struct ata_ioports *port, unsigned long base)
+{
+       port->cmd_addr          = base;
+       port->data_addr         = base;
+       port->feature_addr      =
+       port->error_addr        = base + 0x4;
+       port->nsect_addr        = base + 0x8;
+       port->lbal_addr         = base + 0xc;
+       port->lbam_addr         = base + 0x10;
+       port->lbah_addr         = base + 0x14;
+       port->device_addr       = base + 0x18;
+       port->command_addr      =
+       port->status_addr       = base + 0x1c;
+       port->altstatus_addr    =
+       port->ctl_addr          = base + 0x38;
+}
+
+
+#ifdef ATA_VERBOSE_DEBUG
+static void pdc20621_get_from_dimm(struct ata_probe_ent *pe, void *psource,
+                                  u32 offset, u32 size)
+{
+       u32 window_size;
+       u16 idx;
+       u8 page_mask;
+       long dist;
+       void __iomem *mmio = pe->mmio_base;
+       struct pdc_host_priv *hpriv = pe->private_data;
+       void __iomem *dimm_mmio = hpriv->dimm_mmio;
+
+       /* hard-code chip #0 */
+       mmio += PDC_CHIP0_OFS;
+
+       page_mask = 0x00;
+       window_size = 0x2000 * 4; /* 32K byte uchar size */
+       idx = (u16) (offset / window_size);
+
+       writel(0x01, mmio + PDC_GENERAL_CTLR);
+       readl(mmio + PDC_GENERAL_CTLR);
+       writel(((idx) << page_mask), mmio + PDC_DIMM_WINDOW_CTLR);
+       readl(mmio + PDC_DIMM_WINDOW_CTLR);
+
+       offset -= (idx * window_size);
+       idx++;
+       dist = ((long) (window_size - (offset + size))) >= 0 ? size :
+               (long) (window_size - offset);
+       memcpy_fromio((char *) psource, (char *) (dimm_mmio + offset / 4),
+                     dist);
+
+       psource += dist;
+       size -= dist;
+       for (; (long) size >= (long) window_size ;) {
+               writel(0x01, mmio + PDC_GENERAL_CTLR);
+               readl(mmio + PDC_GENERAL_CTLR);
+               writel(((idx) << page_mask), mmio + PDC_DIMM_WINDOW_CTLR);
+               readl(mmio + PDC_DIMM_WINDOW_CTLR);
+               memcpy_fromio((char *) psource, (char *) (dimm_mmio),
+                             window_size / 4);
+               psource += window_size;
+               size -= window_size;
+               idx ++;
+       }
+
+       if (size) {
+               writel(0x01, mmio + PDC_GENERAL_CTLR);
+               readl(mmio + PDC_GENERAL_CTLR);
+               writel(((idx) << page_mask), mmio + PDC_DIMM_WINDOW_CTLR);
+               readl(mmio + PDC_DIMM_WINDOW_CTLR);
+               memcpy_fromio((char *) psource, (char *) (dimm_mmio),
+                             size / 4);
+       }
+}
+#endif
+
+
+static void pdc20621_put_to_dimm(struct ata_probe_ent *pe, void *psource,
+                                u32 offset, u32 size)
+{
+       u32 window_size;
+       u16 idx;
+       u8 page_mask;
+       long dist;
+       void __iomem *mmio = pe->mmio_base;
+       struct pdc_host_priv *hpriv = pe->private_data;
+       void __iomem *dimm_mmio = hpriv->dimm_mmio;
+
+       /* hard-code chip #0 */
+       mmio += PDC_CHIP0_OFS;
+
+       page_mask = 0x00;
+       window_size = 0x2000 * 4;       /* 32K byte uchar size */
+       idx = (u16) (offset / window_size);
+
+       writel(((idx) << page_mask), mmio + PDC_DIMM_WINDOW_CTLR);
+       readl(mmio + PDC_DIMM_WINDOW_CTLR);
+       offset -= (idx * window_size);
+       idx++;
+       dist = ((long)(s32)(window_size - (offset + size))) >= 0 ? size :
+               (long) (window_size - offset);
+       memcpy_toio(dimm_mmio + offset / 4, psource, dist);
+       writel(0x01, mmio + PDC_GENERAL_CTLR);
+       readl(mmio + PDC_GENERAL_CTLR);
+
+       psource += dist;
+       size -= dist;
+       for (; (long) size >= (long) window_size ;) {
+               writel(((idx) << page_mask), mmio + PDC_DIMM_WINDOW_CTLR);
+               readl(mmio + PDC_DIMM_WINDOW_CTLR);
+               memcpy_toio(dimm_mmio, psource, window_size / 4);
+               writel(0x01, mmio + PDC_GENERAL_CTLR);
+               readl(mmio + PDC_GENERAL_CTLR);
+               psource += window_size;
+               size -= window_size;
+               idx ++;
+       }
+
+       if (size) {
+               writel(((idx) << page_mask), mmio + PDC_DIMM_WINDOW_CTLR);
+               readl(mmio + PDC_DIMM_WINDOW_CTLR);
+               memcpy_toio(dimm_mmio, psource, size / 4);
+               writel(0x01, mmio + PDC_GENERAL_CTLR);
+               readl(mmio + PDC_GENERAL_CTLR);
+       }
+}
+
+
+static unsigned int pdc20621_i2c_read(struct ata_probe_ent *pe, u32 device,
+                                     u32 subaddr, u32 *pdata)
+{
+       void __iomem *mmio = pe->mmio_base;
+       u32 i2creg  = 0;
+       u32 status;
+       u32 count =0;
+
+       /* hard-code chip #0 */
+       mmio += PDC_CHIP0_OFS;
+
+       i2creg |= device << 24;
+       i2creg |= subaddr << 16;
+
+       /* Set the device and subaddress */
+       writel(i2creg, mmio + PDC_I2C_ADDR_DATA_OFFSET);
+       readl(mmio + PDC_I2C_ADDR_DATA_OFFSET);
+
+       /* Write Control to perform read operation, mask int */
+       writel(PDC_I2C_READ | PDC_I2C_START | PDC_I2C_MASK_INT,
+              mmio + PDC_I2C_CONTROL_OFFSET);
+
+       for (count = 0; count <= 1000; count ++) {
+               status = readl(mmio + PDC_I2C_CONTROL_OFFSET);
+               if (status & PDC_I2C_COMPLETE) {
+                       status = readl(mmio + PDC_I2C_ADDR_DATA_OFFSET);
+                       break;
+               } else if (count == 1000)
+                       return 0;
+       }
+
+       *pdata = (status >> 8) & 0x000000ff;
+       return 1;
+}
+
+
+static int pdc20621_detect_dimm(struct ata_probe_ent *pe)
+{
+       u32 data=0 ;
+       if (pdc20621_i2c_read(pe, PDC_DIMM0_SPD_DEV_ADDRESS,
+                            PDC_DIMM_SPD_SYSTEM_FREQ, &data)) {
+               if (data == 100)
+                       return 100;
+       } else
+               return 0;
+
+       if (pdc20621_i2c_read(pe, PDC_DIMM0_SPD_DEV_ADDRESS, 9, &data)) {
+               if(data <= 0x75)
+                       return 133;
+       } else
+               return 0;
+
+       return 0;
+}
+
+
+static int pdc20621_prog_dimm0(struct ata_probe_ent *pe)
+{
+       u32 spd0[50];
+       u32 data = 0;
+       int size, i;
+       u8 bdimmsize;
+       void __iomem *mmio = pe->mmio_base;
+       static const struct {
+               unsigned int reg;
+               unsigned int ofs;
+       } pdc_i2c_read_data [] = {
+               { PDC_DIMM_SPD_TYPE, 11 },
+               { PDC_DIMM_SPD_FRESH_RATE, 12 },
+               { PDC_DIMM_SPD_COLUMN_NUM, 4 },
+               { PDC_DIMM_SPD_ATTRIBUTE, 21 },
+               { PDC_DIMM_SPD_ROW_NUM, 3 },
+               { PDC_DIMM_SPD_BANK_NUM, 17 },
+               { PDC_DIMM_SPD_MODULE_ROW, 5 },
+               { PDC_DIMM_SPD_ROW_PRE_CHARGE, 27 },
+               { PDC_DIMM_SPD_ROW_ACTIVE_DELAY, 28 },
+               { PDC_DIMM_SPD_RAS_CAS_DELAY, 29 },
+               { PDC_DIMM_SPD_ACTIVE_PRECHARGE, 30 },
+               { PDC_DIMM_SPD_CAS_LATENCY, 18 },
+       };
+
+       /* hard-code chip #0 */
+       mmio += PDC_CHIP0_OFS;
+
+       for(i=0; i<ARRAY_SIZE(pdc_i2c_read_data); i++)
+               pdc20621_i2c_read(pe, PDC_DIMM0_SPD_DEV_ADDRESS,
+                                 pdc_i2c_read_data[i].reg,
+                                 &spd0[pdc_i2c_read_data[i].ofs]);
+
+       data |= (spd0[4] - 8) | ((spd0[21] != 0) << 3) | ((spd0[3]-11) << 4);
+       data |= ((spd0[17] / 4) << 6) | ((spd0[5] / 2) << 7) |
+               ((((spd0[27] + 9) / 10) - 1) << 8) ;
+       data |= (((((spd0[29] > spd0[28])
+                   ? spd0[29] : spd0[28]) + 9) / 10) - 1) << 10;
+       data |= ((spd0[30] - spd0[29] + 9) / 10 - 2) << 12;
+
+       if (spd0[18] & 0x08)
+               data |= ((0x03) << 14);
+       else if (spd0[18] & 0x04)
+               data |= ((0x02) << 14);
+       else if (spd0[18] & 0x01)
+               data |= ((0x01) << 14);
+       else
+               data |= (0 << 14);
+
+       /*
+          Calculate the size of bDIMMSize (power of 2) and
+          merge the DIMM size by program start/end address.
+       */
+
+       bdimmsize = spd0[4] + (spd0[5] / 2) + spd0[3] + (spd0[17] / 2) + 3;
+       size = (1 << bdimmsize) >> 20;  /* size = xxx(MB) */
+       data |= (((size / 16) - 1) << 16);
+       data |= (0 << 23);
+       data |= 8;
+       writel(data, mmio + PDC_DIMM0_CONTROL_OFFSET);
+       readl(mmio + PDC_DIMM0_CONTROL_OFFSET);
+       return size;
+}
+
+
+static unsigned int pdc20621_prog_dimm_global(struct ata_probe_ent *pe)
+{
+       u32 data, spd0;
+       int error, i;
+       void __iomem *mmio = pe->mmio_base;
+
+       /* hard-code chip #0 */
+       mmio += PDC_CHIP0_OFS;
+
+       /*
+         Set To Default : DIMM Module Global Control Register (0x022259F1)
+         DIMM Arbitration Disable (bit 20)
+         DIMM Data/Control Output Driving Selection (bit12 - bit15)
+         Refresh Enable (bit 17)
+       */
+
+       data = 0x022259F1;
+       writel(data, mmio + PDC_SDRAM_CONTROL_OFFSET);
+       readl(mmio + PDC_SDRAM_CONTROL_OFFSET);
+
+       /* Turn on for ECC */
+       pdc20621_i2c_read(pe, PDC_DIMM0_SPD_DEV_ADDRESS,
+                         PDC_DIMM_SPD_TYPE, &spd0);
+       if (spd0 == 0x02) {
+               data |= (0x01 << 16);
+               writel(data, mmio + PDC_SDRAM_CONTROL_OFFSET);
+               readl(mmio + PDC_SDRAM_CONTROL_OFFSET);
+               printk(KERN_ERR "Local DIMM ECC Enabled\n");
+       }
+
+       /* DIMM Initialization Select/Enable (bit 18/19) */
+       data &= (~(1<<18));
+       data |= (1<<19);
+       writel(data, mmio + PDC_SDRAM_CONTROL_OFFSET);
+
+       error = 1;
+       for (i = 1; i <= 10; i++) {   /* polling ~5 secs */
+               data = readl(mmio + PDC_SDRAM_CONTROL_OFFSET);
+               if (!(data & (1<<19))) {
+                       error = 0;
+                       break;
+               }
+               msleep(i*100);
+       }
+       return error;
+}
+
+
+static unsigned int pdc20621_dimm_init(struct ata_probe_ent *pe)
+{
+       int speed, size, length;
+       u32 addr,spd0,pci_status;
+       u32 tmp=0;
+       u32 time_period=0;
+       u32 tcount=0;
+       u32 ticks=0;
+       u32 clock=0;
+       u32 fparam=0;
+       void __iomem *mmio = pe->mmio_base;
+
+       /* hard-code chip #0 */
+       mmio += PDC_CHIP0_OFS;
+
+       /* Initialize PLL based upon PCI Bus Frequency */
+
+       /* Initialize Time Period Register */
+       writel(0xffffffff, mmio + PDC_TIME_PERIOD);
+       time_period = readl(mmio + PDC_TIME_PERIOD);
+       VPRINTK("Time Period Register (0x40): 0x%x\n", time_period);
+
+       /* Enable timer */
+       writel(0x00001a0, mmio + PDC_TIME_CONTROL);
+       readl(mmio + PDC_TIME_CONTROL);
+
+       /* Wait 3 seconds */
+       msleep(3000);
+
+       /*
+          When timer is enabled, counter is decreased every internal
+          clock cycle.
+       */
+
+       tcount = readl(mmio + PDC_TIME_COUNTER);
+       VPRINTK("Time Counter Register (0x44): 0x%x\n", tcount);
+
+       /*
+          If SX4 is on PCI-X bus, after 3 seconds, the timer counter
+          register should be >= (0xffffffff - 3x10^8).
+       */
+       if(tcount >= PCI_X_TCOUNT) {
+               ticks = (time_period - tcount);
+               VPRINTK("Num counters 0x%x (%d)\n", ticks, ticks);
+
+               clock = (ticks / 300000);
+               VPRINTK("10 * Internal clk = 0x%x (%d)\n", clock, clock);
+
+               clock = (clock * 33);
+               VPRINTK("10 * Internal clk * 33 = 0x%x (%d)\n", clock, clock);
+
+               /* PLL F Param (bit 22:16) */
+               fparam = (1400000 / clock) - 2;
+               VPRINTK("PLL F Param: 0x%x (%d)\n", fparam, fparam);
+
+               /* OD param = 0x2 (bit 31:30), R param = 0x5 (bit 29:25) */
+               pci_status = (0x8a001824 | (fparam << 16));
+       } else
+               pci_status = PCI_PLL_INIT;
+
+       /* Initialize PLL. */
+       VPRINTK("pci_status: 0x%x\n", pci_status);
+       writel(pci_status, mmio + PDC_CTL_STATUS);
+       readl(mmio + PDC_CTL_STATUS);
+
+       /*
+          Read SPD of DIMM by I2C interface,
+          and program the DIMM Module Controller.
+       */
+       if (!(speed = pdc20621_detect_dimm(pe))) {
+               printk(KERN_ERR "Detect Local DIMM Fail\n");
+               return 1;       /* DIMM error */
+       }
+       VPRINTK("Local DIMM Speed = %d\n", speed);
+
+       /* Programming DIMM0 Module Control Register (index_CID0:80h) */
+       size = pdc20621_prog_dimm0(pe);
+       VPRINTK("Local DIMM Size = %dMB\n",size);
+
+       /* Programming DIMM Module Global Control Register (index_CID0:88h) */
+       if (pdc20621_prog_dimm_global(pe)) {
+               printk(KERN_ERR "Programming DIMM Module Global Control Register Fail\n");
+               return 1;
+       }
+
+#ifdef ATA_VERBOSE_DEBUG
+       {
+               u8 test_parttern1[40] = {0x55,0xAA,'P','r','o','m','i','s','e',' ',
+                               'N','o','t',' ','Y','e','t',' ','D','e','f','i','n','e','d',' ',
+                                '1','.','1','0',
+                               '9','8','0','3','1','6','1','2',0,0};
+               u8 test_parttern2[40] = {0};
+
+               pdc20621_put_to_dimm(pe, (void *) test_parttern2, 0x10040, 40);
+               pdc20621_put_to_dimm(pe, (void *) test_parttern2, 0x40, 40);
+
+               pdc20621_put_to_dimm(pe, (void *) test_parttern1, 0x10040, 40);
+               pdc20621_get_from_dimm(pe, (void *) test_parttern2, 0x40, 40);
+               printk(KERN_ERR "%x, %x, %s\n", test_parttern2[0],
+                      test_parttern2[1], &(test_parttern2[2]));
+               pdc20621_get_from_dimm(pe, (void *) test_parttern2, 0x10040,
+                                      40);
+               printk(KERN_ERR "%x, %x, %s\n", test_parttern2[0],
+                      test_parttern2[1], &(test_parttern2[2]));
+
+               pdc20621_put_to_dimm(pe, (void *) test_parttern1, 0x40, 40);
+               pdc20621_get_from_dimm(pe, (void *) test_parttern2, 0x40, 40);
+               printk(KERN_ERR "%x, %x, %s\n", test_parttern2[0],
+                      test_parttern2[1], &(test_parttern2[2]));
+       }
+#endif
+
+       /* ECC initiliazation. */
+
+       pdc20621_i2c_read(pe, PDC_DIMM0_SPD_DEV_ADDRESS,
+                         PDC_DIMM_SPD_TYPE, &spd0);
+       if (spd0 == 0x02) {
+               VPRINTK("Start ECC initialization\n");
+               addr = 0;
+               length = size * 1024 * 1024;
+               while (addr < length) {
+                       pdc20621_put_to_dimm(pe, (void *) &tmp, addr,
+                                            sizeof(u32));
+                       addr += sizeof(u32);
+               }
+               VPRINTK("Finish ECC initialization\n");
+       }
+       return 0;
+}
+
+
+static void pdc_20621_init(struct ata_probe_ent *pe)
+{
+       u32 tmp;
+       void __iomem *mmio = pe->mmio_base;
+
+       /* hard-code chip #0 */
+       mmio += PDC_CHIP0_OFS;
+
+       /*
+        * Select page 0x40 for our 32k DIMM window
+        */
+       tmp = readl(mmio + PDC_20621_DIMM_WINDOW) & 0xffff0000;
+       tmp |= PDC_PAGE_WINDOW; /* page 40h; arbitrarily selected */
+       writel(tmp, mmio + PDC_20621_DIMM_WINDOW);
+
+       /*
+        * Reset Host DMA
+        */
+       tmp = readl(mmio + PDC_HDMA_CTLSTAT);
+       tmp |= PDC_RESET;
+       writel(tmp, mmio + PDC_HDMA_CTLSTAT);
+       readl(mmio + PDC_HDMA_CTLSTAT);         /* flush */
+
+       udelay(10);
+
+       tmp = readl(mmio + PDC_HDMA_CTLSTAT);
+       tmp &= ~PDC_RESET;
+       writel(tmp, mmio + PDC_HDMA_CTLSTAT);
+       readl(mmio + PDC_HDMA_CTLSTAT);         /* flush */
+}
+
+static int pdc_sata_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
+{
+       static int printed_version;
+       struct ata_probe_ent *probe_ent = NULL;
+       unsigned long base;
+       void __iomem *mmio_base;
+       void __iomem *dimm_mmio = NULL;
+       struct pdc_host_priv *hpriv = NULL;
+       unsigned int board_idx = (unsigned int) ent->driver_data;
+       int pci_dev_busy = 0;
+       int rc;
+
+       if (!printed_version++)
+               dev_printk(KERN_DEBUG, &pdev->dev, "version " DRV_VERSION "\n");
+
+       rc = pci_enable_device(pdev);
+       if (rc)
+               return rc;
+
+       rc = pci_request_regions(pdev, DRV_NAME);
+       if (rc) {
+               pci_dev_busy = 1;
+               goto err_out;
+       }
+
+       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;
+
+       probe_ent = kmalloc(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);
+
+       mmio_base = pci_iomap(pdev, 3, 0);
+       if (mmio_base == NULL) {
+               rc = -ENOMEM;
+               goto err_out_free_ent;
+       }
+       base = (unsigned long) mmio_base;
+
+       hpriv = kmalloc(sizeof(*hpriv), GFP_KERNEL);
+       if (!hpriv) {
+               rc = -ENOMEM;
+               goto err_out_iounmap;
+       }
+       memset(hpriv, 0, sizeof(*hpriv));
+
+       dimm_mmio = pci_iomap(pdev, 4, 0);
+       if (!dimm_mmio) {
+               kfree(hpriv);
+               rc = -ENOMEM;
+               goto err_out_iounmap;
+       }
+
+       hpriv->dimm_mmio = dimm_mmio;
+
+       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;
+       probe_ent->mwdma_mask   = pdc_port_info[board_idx].mwdma_mask;
+       probe_ent->udma_mask    = pdc_port_info[board_idx].udma_mask;
+       probe_ent->port_ops     = pdc_port_info[board_idx].port_ops;
+
+               probe_ent->irq = pdev->irq;
+               probe_ent->irq_flags = IRQF_SHARED;
+       probe_ent->mmio_base = mmio_base;
+
+       probe_ent->private_data = hpriv;
+       base += PDC_CHIP0_OFS;
+
+       probe_ent->n_ports = 4;
+       pdc_sata_setup_port(&probe_ent->port[0], base + 0x200);
+       pdc_sata_setup_port(&probe_ent->port[1], base + 0x280);
+       pdc_sata_setup_port(&probe_ent->port[2], base + 0x300);
+       pdc_sata_setup_port(&probe_ent->port[3], base + 0x380);
+
+       pci_set_master(pdev);
+
+       /* initialize adapter */
+       /* initialize local dimm */
+       if (pdc20621_dimm_init(probe_ent)) {
+               rc = -ENOMEM;
+               goto err_out_iounmap_dimm;
+       }
+       pdc_20621_init(probe_ent);
+
+       /* FIXME: check ata_device_add return value */
+       ata_device_add(probe_ent);
+       kfree(probe_ent);
+
+       return 0;
+
+err_out_iounmap_dimm:          /* only get to this label if 20621 */
+       kfree(hpriv);
+       pci_iounmap(pdev, dimm_mmio);
+err_out_iounmap:
+       pci_iounmap(pdev, mmio_base);
+err_out_free_ent:
+       kfree(probe_ent);
+err_out_regions:
+       pci_release_regions(pdev);
+err_out:
+       if (!pci_dev_busy)
+               pci_disable_device(pdev);
+       return rc;
+}
+
+
+static int __init pdc_sata_init(void)
+{
+       return pci_register_driver(&pdc_sata_pci_driver);
+}
+
+
+static void __exit pdc_sata_exit(void)
+{
+       pci_unregister_driver(&pdc_sata_pci_driver);
+}
+
+
+MODULE_AUTHOR("Jeff Garzik");
+MODULE_DESCRIPTION("Promise SATA low-level driver");
+MODULE_LICENSE("GPL");
+MODULE_DEVICE_TABLE(pci, pdc_sata_pci_tbl);
+MODULE_VERSION(DRV_VERSION);
+
+module_init(pdc_sata_init);
+module_exit(pdc_sata_exit);
diff --git a/drivers/ata/sata_uli.c b/drivers/ata/sata_uli.c
new file mode 100644 (file)
index 0000000..654aae2
--- /dev/null
@@ -0,0 +1,300 @@
+/*
+ *  sata_uli.c - ULi Electronics SATA
+ *
+ *
+ *  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 under NDA.
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/pci.h>
+#include <linux/init.h>
+#include <linux/blkdev.h>
+#include <linux/delay.h>
+#include <linux/interrupt.h>
+#include <linux/device.h>
+#include <scsi/scsi_host.h>
+#include <linux/libata.h>
+
+#define DRV_NAME       "sata_uli"
+#define DRV_VERSION    "1.0"
+
+enum {
+       uli_5289                = 0,
+       uli_5287                = 1,
+       uli_5281                = 2,
+
+       uli_max_ports           = 4,
+
+       /* PCI configuration registers */
+       ULI5287_BASE            = 0x90, /* sata0 phy SCR registers */
+       ULI5287_OFFS            = 0x10, /* offset from sata0->sata1 phy regs */
+       ULI5281_BASE            = 0x60, /* sata0 phy SCR  registers */
+       ULI5281_OFFS            = 0x60, /* offset from sata0->sata1 phy regs */
+};
+
+struct uli_priv {
+       unsigned int            scr_cfg_addr[uli_max_ports];
+};
+
+static int uli_init_one (struct pci_dev *pdev, const struct pci_device_id *ent);
+static u32 uli_scr_read (struct ata_port *ap, unsigned int sc_reg);
+static void uli_scr_write (struct ata_port *ap, unsigned int sc_reg, u32 val);
+
+static const struct pci_device_id uli_pci_tbl[] = {
+       { PCI_VENDOR_ID_AL, 0x5289, PCI_ANY_ID, PCI_ANY_ID, 0, 0, uli_5289 },
+       { PCI_VENDOR_ID_AL, 0x5287, PCI_ANY_ID, PCI_ANY_ID, 0, 0, uli_5287 },
+       { PCI_VENDOR_ID_AL, 0x5281, PCI_ANY_ID, PCI_ANY_ID, 0, 0, uli_5281 },
+       { }     /* terminate list */
+};
+
+
+static struct pci_driver uli_pci_driver = {
+       .name                   = DRV_NAME,
+       .id_table               = uli_pci_tbl,
+       .probe                  = uli_init_one,
+       .remove                 = ata_pci_remove_one,
+};
+
+static struct scsi_host_template uli_sht = {
+       .module                 = THIS_MODULE,
+       .name                   = DRV_NAME,
+       .ioctl                  = ata_scsi_ioctl,
+       .queuecommand           = ata_scsi_queuecmd,
+       .can_queue              = ATA_DEF_QUEUE,
+       .this_id                = ATA_SHT_THIS_ID,
+       .sg_tablesize           = LIBATA_MAX_PRD,
+       .cmd_per_lun            = ATA_SHT_CMD_PER_LUN,
+       .emulated               = ATA_SHT_EMULATED,
+       .use_clustering         = ATA_SHT_USE_CLUSTERING,
+       .proc_name              = DRV_NAME,
+       .dma_boundary           = ATA_DMA_BOUNDARY,
+       .slave_configure        = ata_scsi_slave_config,
+       .slave_destroy          = ata_scsi_slave_destroy,
+       .bios_param             = ata_std_bios_param,
+};
+
+static const struct ata_port_operations uli_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,
+
+       .bmdma_setup            = ata_bmdma_setup,
+       .bmdma_start            = ata_bmdma_start,
+       .bmdma_stop             = ata_bmdma_stop,
+       .bmdma_status           = ata_bmdma_status,
+       .qc_prep                = ata_qc_prep,
+       .qc_issue               = ata_qc_issue_prot,
+       .data_xfer              = ata_pio_data_xfer,
+
+       .freeze                 = ata_bmdma_freeze,
+       .thaw                   = ata_bmdma_thaw,
+       .error_handler          = ata_bmdma_error_handler,
+       .post_internal_cmd      = ata_bmdma_post_internal_cmd,
+
+       .irq_handler            = ata_interrupt,
+       .irq_clear              = ata_bmdma_irq_clear,
+
+       .scr_read               = uli_scr_read,
+       .scr_write              = uli_scr_write,
+
+       .port_start             = ata_port_start,
+       .port_stop              = ata_port_stop,
+       .host_stop              = ata_host_stop,
+};
+
+static struct ata_port_info uli_port_info = {
+       .sht            = &uli_sht,
+       .host_flags     = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY,
+       .pio_mask       = 0x1f,         /* pio0-4 */
+       .udma_mask      = 0x7f,         /* udma0-6 */
+       .port_ops       = &uli_ops,
+};
+
+
+MODULE_AUTHOR("Peer Chen");
+MODULE_DESCRIPTION("low-level driver for ULi Electronics SATA controller");
+MODULE_LICENSE("GPL");
+MODULE_DEVICE_TABLE(pci, uli_pci_tbl);
+MODULE_VERSION(DRV_VERSION);
+
+static unsigned int get_scr_cfg_addr(struct ata_port *ap, unsigned int sc_reg)
+{
+       struct uli_priv *hpriv = ap->host_set->private_data;
+       return hpriv->scr_cfg_addr[ap->port_no] + (4 * sc_reg);
+}
+
+static u32 uli_scr_cfg_read (struct ata_port *ap, unsigned int sc_reg)
+{
+       struct pci_dev *pdev = to_pci_dev(ap->host_set->dev);
+       unsigned int cfg_addr = get_scr_cfg_addr(ap, sc_reg);
+       u32 val;
+
+       pci_read_config_dword(pdev, cfg_addr, &val);
+       return val;
+}
+
+static void uli_scr_cfg_write (struct ata_port *ap, unsigned int scr, u32 val)
+{
+       struct pci_dev *pdev = to_pci_dev(ap->host_set->dev);
+       unsigned int cfg_addr = get_scr_cfg_addr(ap, scr);
+
+       pci_write_config_dword(pdev, cfg_addr, val);
+}
+
+static u32 uli_scr_read (struct ata_port *ap, unsigned int sc_reg)
+{
+       if (sc_reg > SCR_CONTROL)
+               return 0xffffffffU;
+
+       return uli_scr_cfg_read(ap, sc_reg);
+}
+
+static void uli_scr_write (struct ata_port *ap, unsigned int sc_reg, u32 val)
+{
+       if (sc_reg > SCR_CONTROL)       //SCR_CONTROL=2, SCR_ERROR=1, SCR_STATUS=0
+               return;
+
+       uli_scr_cfg_write(ap, sc_reg, val);
+}
+
+static int uli_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
+{
+       static int printed_version;
+       struct ata_probe_ent *probe_ent;
+       struct ata_port_info *ppi;
+       int rc;
+       unsigned int board_idx = (unsigned int) ent->driver_data;
+       int pci_dev_busy = 0;
+       struct uli_priv *hpriv;
+
+       if (!printed_version++)
+               dev_printk(KERN_INFO, &pdev->dev, "version " DRV_VERSION "\n");
+
+       rc = pci_enable_device(pdev);
+       if (rc)
+               return rc;
+
+       rc = pci_request_regions(pdev, DRV_NAME);
+       if (rc) {
+               pci_dev_busy = 1;
+               goto err_out;
+       }
+
+       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;
+
+       ppi = &uli_port_info;
+       probe_ent = ata_pci_init_native_mode(pdev, &ppi, ATA_PORT_PRIMARY | ATA_PORT_SECONDARY);
+       if (!probe_ent) {
+               rc = -ENOMEM;
+               goto err_out_regions;
+       }
+
+       hpriv = kzalloc(sizeof(*hpriv), GFP_KERNEL);
+       if (!hpriv) {
+               rc = -ENOMEM;
+               goto err_out_probe_ent;
+       }
+
+       probe_ent->private_data = hpriv;
+
+       switch (board_idx) {
+       case uli_5287:
+               hpriv->scr_cfg_addr[0] = ULI5287_BASE;
+               hpriv->scr_cfg_addr[1] = ULI5287_BASE + ULI5287_OFFS;
+                       probe_ent->n_ports = 4;
+
+                       probe_ent->port[2].cmd_addr = pci_resource_start(pdev, 0) + 8;
+               probe_ent->port[2].altstatus_addr =
+               probe_ent->port[2].ctl_addr =
+                       (pci_resource_start(pdev, 1) | ATA_PCI_CTL_OFS) + 4;
+               probe_ent->port[2].bmdma_addr = pci_resource_start(pdev, 4) + 16;
+               hpriv->scr_cfg_addr[2] = ULI5287_BASE + ULI5287_OFFS*4;
+
+               probe_ent->port[3].cmd_addr = pci_resource_start(pdev, 2) + 8;
+               probe_ent->port[3].altstatus_addr =
+               probe_ent->port[3].ctl_addr =
+                       (pci_resource_start(pdev, 3) | ATA_PCI_CTL_OFS) + 4;
+               probe_ent->port[3].bmdma_addr = pci_resource_start(pdev, 4) + 24;
+               hpriv->scr_cfg_addr[3] = ULI5287_BASE + ULI5287_OFFS*5;
+
+               ata_std_ports(&probe_ent->port[2]);
+               ata_std_ports(&probe_ent->port[3]);
+               break;
+
+       case uli_5289:
+               hpriv->scr_cfg_addr[0] = ULI5287_BASE;
+               hpriv->scr_cfg_addr[1] = ULI5287_BASE + ULI5287_OFFS;
+               break;
+
+       case uli_5281:
+               hpriv->scr_cfg_addr[0] = ULI5281_BASE;
+               hpriv->scr_cfg_addr[1] = ULI5281_BASE + ULI5281_OFFS;
+               break;
+
+       default:
+               BUG();
+               break;
+       }
+
+       pci_set_master(pdev);
+       pci_intx(pdev, 1);
+
+       /* FIXME: check ata_device_add return value */
+       ata_device_add(probe_ent);
+       kfree(probe_ent);
+
+       return 0;
+
+err_out_probe_ent:
+       kfree(probe_ent);
+err_out_regions:
+       pci_release_regions(pdev);
+err_out:
+       if (!pci_dev_busy)
+               pci_disable_device(pdev);
+       return rc;
+
+}
+
+static int __init uli_init(void)
+{
+       return pci_register_driver(&uli_pci_driver);
+}
+
+static void __exit uli_exit(void)
+{
+       pci_unregister_driver(&uli_pci_driver);
+}
+
+
+module_init(uli_init);
+module_exit(uli_exit);
diff --git a/drivers/ata/sata_via.c b/drivers/ata/sata_via.c
new file mode 100644 (file)
index 0000000..0bf1dbe
--- /dev/null
@@ -0,0 +1,394 @@
+/*
+ *  sata_via.c - VIA Serial ATA controllers
+ *
+ *  Maintained by:  Jeff Garzik <jgarzik@pobox.com>
+ *                Please ALWAYS copy linux-ide@vger.kernel.org
+                  on emails.
+ *
+ *  Copyright 2003-2004 Red Hat, Inc.  All rights reserved.
+ *  Copyright 2003-2004 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 under NDA.
+ *
+ *
+ *  To-do list:
+ *  - VT6421 PATA support
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/pci.h>
+#include <linux/init.h>
+#include <linux/blkdev.h>
+#include <linux/delay.h>
+#include <linux/device.h>
+#include <scsi/scsi_host.h>
+#include <linux/libata.h>
+#include <asm/io.h>
+
+#define DRV_NAME       "sata_via"
+#define DRV_VERSION    "2.0"
+
+enum board_ids_enum {
+       vt6420,
+       vt6421,
+};
+
+enum {
+       SATA_CHAN_ENAB          = 0x40, /* SATA channel enable */
+       SATA_INT_GATE           = 0x41, /* SATA interrupt gating */
+       SATA_NATIVE_MODE        = 0x42, /* Native mode enable */
+       SATA_PATA_SHARING       = 0x49, /* PATA/SATA sharing func ctrl */
+
+       PORT0                   = (1 << 1),
+       PORT1                   = (1 << 0),
+       ALL_PORTS               = PORT0 | PORT1,
+       N_PORTS                 = 2,
+
+       NATIVE_MODE_ALL         = (1 << 7) | (1 << 6) | (1 << 5) | (1 << 4),
+
+       SATA_EXT_PHY            = (1 << 6), /* 0==use PATA, 1==ext phy */
+       SATA_2DEV               = (1 << 5), /* SATA is master/slave */
+};
+
+static int svia_init_one (struct pci_dev *pdev, const struct pci_device_id *ent);
+static u32 svia_scr_read (struct ata_port *ap, unsigned int sc_reg);
+static void svia_scr_write (struct ata_port *ap, unsigned int sc_reg, u32 val);
+
+static const struct pci_device_id svia_pci_tbl[] = {
+       { 0x1106, 0x3149, PCI_ANY_ID, PCI_ANY_ID, 0, 0, vt6420 },
+       { 0x1106, 0x3249, PCI_ANY_ID, PCI_ANY_ID, 0, 0, vt6421 },
+
+       { }     /* terminate list */
+};
+
+static struct pci_driver svia_pci_driver = {
+       .name                   = DRV_NAME,
+       .id_table               = svia_pci_tbl,
+       .probe                  = svia_init_one,
+       .remove                 = ata_pci_remove_one,
+};
+
+static struct scsi_host_template svia_sht = {
+       .module                 = THIS_MODULE,
+       .name                   = DRV_NAME,
+       .ioctl                  = ata_scsi_ioctl,
+       .queuecommand           = ata_scsi_queuecmd,
+       .can_queue              = ATA_DEF_QUEUE,
+       .this_id                = ATA_SHT_THIS_ID,
+       .sg_tablesize           = LIBATA_MAX_PRD,
+       .cmd_per_lun            = ATA_SHT_CMD_PER_LUN,
+       .emulated               = ATA_SHT_EMULATED,
+       .use_clustering         = ATA_SHT_USE_CLUSTERING,
+       .proc_name              = DRV_NAME,
+       .dma_boundary           = ATA_DMA_BOUNDARY,
+       .slave_configure        = ata_scsi_slave_config,
+       .slave_destroy          = ata_scsi_slave_destroy,
+       .bios_param             = ata_std_bios_param,
+};
+
+static const struct ata_port_operations svia_sata_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,
+
+       .bmdma_setup            = ata_bmdma_setup,
+       .bmdma_start            = ata_bmdma_start,
+       .bmdma_stop             = ata_bmdma_stop,
+       .bmdma_status           = ata_bmdma_status,
+
+       .qc_prep                = ata_qc_prep,
+       .qc_issue               = ata_qc_issue_prot,
+       .data_xfer              = ata_pio_data_xfer,
+
+       .freeze                 = ata_bmdma_freeze,
+       .thaw                   = ata_bmdma_thaw,
+       .error_handler          = ata_bmdma_error_handler,
+       .post_internal_cmd      = ata_bmdma_post_internal_cmd,
+
+       .irq_handler            = ata_interrupt,
+       .irq_clear              = ata_bmdma_irq_clear,
+
+       .scr_read               = svia_scr_read,
+       .scr_write              = svia_scr_write,
+
+       .port_start             = ata_port_start,
+       .port_stop              = ata_port_stop,
+       .host_stop              = ata_host_stop,
+};
+
+static struct ata_port_info svia_port_info = {
+       .sht            = &svia_sht,
+       .host_flags     = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY,
+       .pio_mask       = 0x1f,
+       .mwdma_mask     = 0x07,
+       .udma_mask      = 0x7f,
+       .port_ops       = &svia_sata_ops,
+};
+
+MODULE_AUTHOR("Jeff Garzik");
+MODULE_DESCRIPTION("SCSI low-level driver for VIA SATA controllers");
+MODULE_LICENSE("GPL");
+MODULE_DEVICE_TABLE(pci, svia_pci_tbl);
+MODULE_VERSION(DRV_VERSION);
+
+static u32 svia_scr_read (struct ata_port *ap, unsigned int sc_reg)
+{
+       if (sc_reg > SCR_CONTROL)
+               return 0xffffffffU;
+       return inl(ap->ioaddr.scr_addr + (4 * sc_reg));
+}
+
+static void svia_scr_write (struct ata_port *ap, unsigned int sc_reg, u32 val)
+{
+       if (sc_reg > SCR_CONTROL)
+               return;
+       outl(val, ap->ioaddr.scr_addr + (4 * sc_reg));
+}
+
+static const unsigned int svia_bar_sizes[] = {
+       8, 4, 8, 4, 16, 256
+};
+
+static const unsigned int vt6421_bar_sizes[] = {
+       16, 16, 16, 16, 32, 128
+};
+
+static unsigned long svia_scr_addr(unsigned long addr, unsigned int port)
+{
+       return addr + (port * 128);
+}
+
+static unsigned long vt6421_scr_addr(unsigned long addr, unsigned int port)
+{
+       return addr + (port * 64);
+}
+
+static void vt6421_init_addrs(struct ata_probe_ent *probe_ent,
+                             struct pci_dev *pdev,
+                             unsigned int port)
+{
+       unsigned long reg_addr = pci_resource_start(pdev, port);
+       unsigned long bmdma_addr = pci_resource_start(pdev, 4) + (port * 8);
+       unsigned long scr_addr;
+
+       probe_ent->port[port].cmd_addr = reg_addr;
+       probe_ent->port[port].altstatus_addr =
+       probe_ent->port[port].ctl_addr = (reg_addr + 8) | ATA_PCI_CTL_OFS;
+       probe_ent->port[port].bmdma_addr = bmdma_addr;
+
+       scr_addr = vt6421_scr_addr(pci_resource_start(pdev, 5), port);
+       probe_ent->port[port].scr_addr = scr_addr;
+
+       ata_std_ports(&probe_ent->port[port]);
+}
+
+static struct ata_probe_ent *vt6420_init_probe_ent(struct pci_dev *pdev)
+{
+       struct ata_probe_ent *probe_ent;
+       struct ata_port_info *ppi = &svia_port_info;
+
+       probe_ent = ata_pci_init_native_mode(pdev, &ppi, ATA_PORT_PRIMARY | ATA_PORT_SECONDARY);
+       if (!probe_ent)
+               return NULL;
+
+       probe_ent->port[0].scr_addr =
+               svia_scr_addr(pci_resource_start(pdev, 5), 0);
+       probe_ent->port[1].scr_addr =
+               svia_scr_addr(pci_resource_start(pdev, 5), 1);
+
+       return probe_ent;
+}
+
+static struct ata_probe_ent *vt6421_init_probe_ent(struct pci_dev *pdev)
+{
+       struct ata_probe_ent *probe_ent;
+       unsigned int i;
+
+       probe_ent = kmalloc(sizeof(*probe_ent), GFP_KERNEL);
+       if (!probe_ent)
+               return NULL;
+
+       memset(probe_ent, 0, sizeof(*probe_ent));
+       probe_ent->dev = pci_dev_to_dev(pdev);
+       INIT_LIST_HEAD(&probe_ent->node);
+
+       probe_ent->sht          = &svia_sht;
+       probe_ent->host_flags   = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY;
+       probe_ent->port_ops     = &svia_sata_ops;
+       probe_ent->n_ports      = N_PORTS;
+       probe_ent->irq          = pdev->irq;
+       probe_ent->irq_flags    = IRQF_SHARED;
+       probe_ent->pio_mask     = 0x1f;
+       probe_ent->mwdma_mask   = 0x07;
+       probe_ent->udma_mask    = 0x7f;
+
+       for (i = 0; i < N_PORTS; i++)
+               vt6421_init_addrs(probe_ent, pdev, i);
+
+       return probe_ent;
+}
+
+static void svia_configure(struct pci_dev *pdev)
+{
+       u8 tmp8;
+
+       pci_read_config_byte(pdev, PCI_INTERRUPT_LINE, &tmp8);
+       dev_printk(KERN_INFO, &pdev->dev, "routed to hard irq line %d\n",
+              (int) (tmp8 & 0xf0) == 0xf0 ? 0 : tmp8 & 0x0f);
+
+       /* make sure SATA channels are enabled */
+       pci_read_config_byte(pdev, SATA_CHAN_ENAB, &tmp8);
+       if ((tmp8 & ALL_PORTS) != ALL_PORTS) {
+               dev_printk(KERN_DEBUG, &pdev->dev,
+                          "enabling SATA channels (0x%x)\n",
+                          (int) tmp8);
+               tmp8 |= ALL_PORTS;
+               pci_write_config_byte(pdev, SATA_CHAN_ENAB, tmp8);
+       }
+
+       /* make sure interrupts for each channel sent to us */
+       pci_read_config_byte(pdev, SATA_INT_GATE, &tmp8);
+       if ((tmp8 & ALL_PORTS) != ALL_PORTS) {
+               dev_printk(KERN_DEBUG, &pdev->dev,
+                          "enabling SATA channel interrupts (0x%x)\n",
+                          (int) tmp8);
+               tmp8 |= ALL_PORTS;
+               pci_write_config_byte(pdev, SATA_INT_GATE, tmp8);
+       }
+
+       /* make sure native mode is enabled */
+       pci_read_config_byte(pdev, SATA_NATIVE_MODE, &tmp8);
+       if ((tmp8 & NATIVE_MODE_ALL) != NATIVE_MODE_ALL) {
+               dev_printk(KERN_DEBUG, &pdev->dev,
+                          "enabling SATA channel native mode (0x%x)\n",
+                          (int) tmp8);
+               tmp8 |= NATIVE_MODE_ALL;
+               pci_write_config_byte(pdev, SATA_NATIVE_MODE, tmp8);
+       }
+}
+
+static int svia_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
+{
+       static int printed_version;
+       unsigned int i;
+       int rc;
+       struct ata_probe_ent *probe_ent;
+       int board_id = (int) ent->driver_data;
+       const int *bar_sizes;
+       int pci_dev_busy = 0;
+       u8 tmp8;
+
+       if (!printed_version++)
+               dev_printk(KERN_DEBUG, &pdev->dev, "version " DRV_VERSION "\n");
+
+       rc = pci_enable_device(pdev);
+       if (rc)
+               return rc;
+
+       rc = pci_request_regions(pdev, DRV_NAME);
+       if (rc) {
+               pci_dev_busy = 1;
+               goto err_out;
+       }
+
+       if (board_id == vt6420) {
+               pci_read_config_byte(pdev, SATA_PATA_SHARING, &tmp8);
+               if (tmp8 & SATA_2DEV) {
+                       dev_printk(KERN_ERR, &pdev->dev,
+                                  "SATA master/slave not supported (0x%x)\n",
+                                  (int) tmp8);
+                       rc = -EIO;
+                       goto err_out_regions;
+               }
+
+               bar_sizes = &svia_bar_sizes[0];
+       } else {
+               bar_sizes = &vt6421_bar_sizes[0];
+       }
+
+       for (i = 0; i < ARRAY_SIZE(svia_bar_sizes); i++)
+               if ((pci_resource_start(pdev, i) == 0) ||
+                   (pci_resource_len(pdev, i) < bar_sizes[i])) {
+                       dev_printk(KERN_ERR, &pdev->dev,
+                               "invalid PCI BAR %u (sz 0x%llx, val 0x%llx)\n",
+                               i,
+                               (unsigned long long)pci_resource_start(pdev, i),
+                               (unsigned long long)pci_resource_len(pdev, i));
+                       rc = -ENODEV;
+                       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 (board_id == vt6420)
+               probe_ent = vt6420_init_probe_ent(pdev);
+       else
+               probe_ent = vt6421_init_probe_ent(pdev);
+
+       if (!probe_ent) {
+               dev_printk(KERN_ERR, &pdev->dev, "out of memory\n");
+               rc = -ENOMEM;
+               goto err_out_regions;
+       }
+
+       svia_configure(pdev);
+
+       pci_set_master(pdev);
+
+       /* FIXME: check ata_device_add return value */
+       ata_device_add(probe_ent);
+       kfree(probe_ent);
+
+       return 0;
+
+err_out_regions:
+       pci_release_regions(pdev);
+err_out:
+       if (!pci_dev_busy)
+               pci_disable_device(pdev);
+       return rc;
+}
+
+static int __init svia_init(void)
+{
+       return pci_register_driver(&svia_pci_driver);
+}
+
+static void __exit svia_exit(void)
+{
+       pci_unregister_driver(&svia_pci_driver);
+}
+
+module_init(svia_init);
+module_exit(svia_exit);
+
diff --git a/drivers/ata/sata_vsc.c b/drivers/ata/sata_vsc.c
new file mode 100644 (file)
index 0000000..4c69a70
--- /dev/null
@@ -0,0 +1,482 @@
+/*
+ *  sata_vsc.c - Vitesse VSC7174 4 port DPA SATA
+ *
+ *  Maintained by:  Jeremy Higdon @ SGI
+ *                 Please ALWAYS copy linux-ide@vger.kernel.org
+ *                 on emails.
+ *
+ *  Copyright 2004 SGI
+ *
+ *  Bits from Jeff Garzik, Copyright RedHat, Inc.
+ *
+ *
+ *  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.*
+ *
+ *  Vitesse hardware documentation presumably available under NDA.
+ *  Intel 31244 (same hardware interface) documentation presumably
+ *  available from http://developer.intel.com/
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/pci.h>
+#include <linux/init.h>
+#include <linux/blkdev.h>
+#include <linux/delay.h>
+#include <linux/interrupt.h>
+#include <linux/dma-mapping.h>
+#include <linux/device.h>
+#include <scsi/scsi_host.h>
+#include <linux/libata.h>
+
+#define DRV_NAME       "sata_vsc"
+#define DRV_VERSION    "2.0"
+
+enum {
+       /* Interrupt register offsets (from chip base address) */
+       VSC_SATA_INT_STAT_OFFSET        = 0x00,
+       VSC_SATA_INT_MASK_OFFSET        = 0x04,
+
+       /* Taskfile registers offsets */
+       VSC_SATA_TF_CMD_OFFSET          = 0x00,
+       VSC_SATA_TF_DATA_OFFSET         = 0x00,
+       VSC_SATA_TF_ERROR_OFFSET        = 0x04,
+       VSC_SATA_TF_FEATURE_OFFSET      = 0x06,
+       VSC_SATA_TF_NSECT_OFFSET        = 0x08,
+       VSC_SATA_TF_LBAL_OFFSET         = 0x0c,
+       VSC_SATA_TF_LBAM_OFFSET         = 0x10,
+       VSC_SATA_TF_LBAH_OFFSET         = 0x14,
+       VSC_SATA_TF_DEVICE_OFFSET       = 0x18,
+       VSC_SATA_TF_STATUS_OFFSET       = 0x1c,
+       VSC_SATA_TF_COMMAND_OFFSET      = 0x1d,
+       VSC_SATA_TF_ALTSTATUS_OFFSET    = 0x28,
+       VSC_SATA_TF_CTL_OFFSET          = 0x29,
+
+       /* DMA base */
+       VSC_SATA_UP_DESCRIPTOR_OFFSET   = 0x64,
+       VSC_SATA_UP_DATA_BUFFER_OFFSET  = 0x6C,
+       VSC_SATA_DMA_CMD_OFFSET         = 0x70,
+
+       /* SCRs base */
+       VSC_SATA_SCR_STATUS_OFFSET      = 0x100,
+       VSC_SATA_SCR_ERROR_OFFSET       = 0x104,
+       VSC_SATA_SCR_CONTROL_OFFSET     = 0x108,
+
+       /* Port stride */
+       VSC_SATA_PORT_OFFSET            = 0x200,
+
+       /* Error interrupt status bit offsets */
+       VSC_SATA_INT_ERROR_CRC          = 0x40,
+       VSC_SATA_INT_ERROR_T            = 0x20,
+       VSC_SATA_INT_ERROR_P            = 0x10,
+       VSC_SATA_INT_ERROR_R            = 0x8,
+       VSC_SATA_INT_ERROR_E            = 0x4,
+       VSC_SATA_INT_ERROR_M            = 0x2,
+       VSC_SATA_INT_PHY_CHANGE         = 0x1,
+       VSC_SATA_INT_ERROR = (VSC_SATA_INT_ERROR_CRC  | VSC_SATA_INT_ERROR_T | \
+                             VSC_SATA_INT_ERROR_P    | VSC_SATA_INT_ERROR_R | \
+                             VSC_SATA_INT_ERROR_E    | VSC_SATA_INT_ERROR_M | \
+                             VSC_SATA_INT_PHY_CHANGE),
+};
+
+
+#define is_vsc_sata_int_err(port_idx, int_status) \
+        (int_status & (VSC_SATA_INT_ERROR << (8 * port_idx)))
+
+
+static u32 vsc_sata_scr_read (struct ata_port *ap, unsigned int sc_reg)
+{
+       if (sc_reg > SCR_CONTROL)
+               return 0xffffffffU;
+       return readl((void __iomem *) ap->ioaddr.scr_addr + (sc_reg * 4));
+}
+
+
+static void vsc_sata_scr_write (struct ata_port *ap, unsigned int sc_reg,
+                              u32 val)
+{
+       if (sc_reg > SCR_CONTROL)
+               return;
+       writel(val, (void __iomem *) ap->ioaddr.scr_addr + (sc_reg * 4));
+}
+
+
+static void vsc_intr_mask_update(struct ata_port *ap, u8 ctl)
+{
+       void __iomem *mask_addr;
+       u8 mask;
+
+       mask_addr = ap->host_set->mmio_base +
+               VSC_SATA_INT_MASK_OFFSET + ap->port_no;
+       mask = readb(mask_addr);
+       if (ctl & ATA_NIEN)
+               mask |= 0x80;
+       else
+               mask &= 0x7F;
+       writeb(mask, mask_addr);
+}
+
+
+static void vsc_sata_tf_load(struct ata_port *ap, const struct ata_taskfile *tf)
+{
+       struct ata_ioports *ioaddr = &ap->ioaddr;
+       unsigned int is_addr = tf->flags & ATA_TFLAG_ISADDR;
+
+       /*
+        * The only thing the ctl register is used for is SRST.
+        * That is not enabled or disabled via tf_load.
+        * However, if ATA_NIEN is changed, then we need to change the interrupt register.
+        */
+       if ((tf->ctl & ATA_NIEN) != (ap->last_ctl & ATA_NIEN)) {
+               ap->last_ctl = tf->ctl;
+               vsc_intr_mask_update(ap, tf->ctl & ATA_NIEN);
+       }
+       if (is_addr && (tf->flags & ATA_TFLAG_LBA48)) {
+               writew(tf->feature | (((u16)tf->hob_feature) << 8), ioaddr->feature_addr);
+               writew(tf->nsect | (((u16)tf->hob_nsect) << 8), ioaddr->nsect_addr);
+               writew(tf->lbal | (((u16)tf->hob_lbal) << 8), ioaddr->lbal_addr);
+               writew(tf->lbam | (((u16)tf->hob_lbam) << 8), ioaddr->lbam_addr);
+               writew(tf->lbah | (((u16)tf->hob_lbah) << 8), ioaddr->lbah_addr);
+       } else if (is_addr) {
+               writew(tf->feature, ioaddr->feature_addr);
+               writew(tf->nsect, ioaddr->nsect_addr);
+               writew(tf->lbal, ioaddr->lbal_addr);
+               writew(tf->lbam, ioaddr->lbam_addr);
+               writew(tf->lbah, ioaddr->lbah_addr);
+       }
+
+       if (tf->flags & ATA_TFLAG_DEVICE)
+               writeb(tf->device, ioaddr->device_addr);
+
+       ata_wait_idle(ap);
+}
+
+
+static void vsc_sata_tf_read(struct ata_port *ap, struct ata_taskfile *tf)
+{
+       struct ata_ioports *ioaddr = &ap->ioaddr;
+       u16 nsect, lbal, lbam, lbah, feature;
+
+       tf->command = ata_check_status(ap);
+       tf->device = readw(ioaddr->device_addr);
+       feature = readw(ioaddr->error_addr);
+       nsect = readw(ioaddr->nsect_addr);
+       lbal = readw(ioaddr->lbal_addr);
+       lbam = readw(ioaddr->lbam_addr);
+       lbah = readw(ioaddr->lbah_addr);
+
+       tf->feature = feature;
+       tf->nsect = nsect;
+       tf->lbal = lbal;
+       tf->lbam = lbam;
+       tf->lbah = lbah;
+
+       if (tf->flags & ATA_TFLAG_LBA48) {
+               tf->hob_feature = feature >> 8;
+               tf->hob_nsect = nsect >> 8;
+               tf->hob_lbal = lbal >> 8;
+               tf->hob_lbam = lbam >> 8;
+               tf->hob_lbah = lbah >> 8;
+        }
+}
+
+
+/*
+ * vsc_sata_interrupt
+ *
+ * Read the interrupt register and process for the devices that have them pending.
+ */
+static irqreturn_t vsc_sata_interrupt (int irq, void *dev_instance,
+                                      struct pt_regs *regs)
+{
+       struct ata_host_set *host_set = dev_instance;
+       unsigned int i;
+       unsigned int handled = 0;
+       u32 int_status;
+
+       spin_lock(&host_set->lock);
+
+       int_status = readl(host_set->mmio_base + VSC_SATA_INT_STAT_OFFSET);
+
+       for (i = 0; i < host_set->n_ports; i++) {
+               if (int_status & ((u32) 0xFF << (8 * i))) {
+                       struct ata_port *ap;
+
+                       ap = host_set->ports[i];
+
+                       if (is_vsc_sata_int_err(i, int_status)) {
+                               u32 err_status;
+                               printk(KERN_DEBUG "%s: ignoring interrupt(s)\n", __FUNCTION__);
+                               err_status = ap ? vsc_sata_scr_read(ap, SCR_ERROR) : 0;
+                               vsc_sata_scr_write(ap, SCR_ERROR, err_status);
+                               handled++;
+                       }
+
+                       if (ap && !(ap->flags & ATA_FLAG_DISABLED)) {
+                               struct ata_queued_cmd *qc;
+
+                               qc = ata_qc_from_tag(ap, ap->active_tag);
+                               if (qc && (!(qc->tf.flags & ATA_TFLAG_POLLING)))
+                                       handled += ata_host_intr(ap, qc);
+                               else if (is_vsc_sata_int_err(i, int_status)) {
+                                       /*
+                                        * On some chips (i.e. Intel 31244), an error
+                                        * interrupt will sneak in at initialization
+                                        * time (phy state changes).  Clearing the SCR
+                                        * error register is not required, but it prevents
+                                        * the phy state change interrupts from recurring
+                                        * later.
+                                        */
+                                       u32 err_status;
+                                       err_status = vsc_sata_scr_read(ap, SCR_ERROR);
+                                       printk(KERN_DEBUG "%s: clearing interrupt, "
+                                              "status %x; sata err status %x\n",
+                                              __FUNCTION__,
+                                              int_status, err_status);
+                                       vsc_sata_scr_write(ap, SCR_ERROR, err_status);
+                                       /* Clear interrupt status */
+                                       ata_chk_status(ap);
+                                       handled++;
+                               }
+                       }
+               }
+       }
+
+       spin_unlock(&host_set->lock);
+
+       return IRQ_RETVAL(handled);
+}
+
+
+static struct scsi_host_template vsc_sata_sht = {
+       .module                 = THIS_MODULE,
+       .name                   = DRV_NAME,
+       .ioctl                  = ata_scsi_ioctl,
+       .queuecommand           = ata_scsi_queuecmd,
+       .can_queue              = ATA_DEF_QUEUE,
+       .this_id                = ATA_SHT_THIS_ID,
+       .sg_tablesize           = LIBATA_MAX_PRD,
+       .cmd_per_lun            = ATA_SHT_CMD_PER_LUN,
+       .emulated               = ATA_SHT_EMULATED,
+       .use_clustering         = ATA_SHT_USE_CLUSTERING,
+       .proc_name              = DRV_NAME,
+       .dma_boundary           = ATA_DMA_BOUNDARY,
+       .slave_configure        = ata_scsi_slave_config,
+       .slave_destroy          = ata_scsi_slave_destroy,
+       .bios_param             = ata_std_bios_param,
+};
+
+
+static const struct ata_port_operations vsc_sata_ops = {
+       .port_disable           = ata_port_disable,
+       .tf_load                = vsc_sata_tf_load,
+       .tf_read                = vsc_sata_tf_read,
+       .exec_command           = ata_exec_command,
+       .check_status           = ata_check_status,
+       .dev_select             = ata_std_dev_select,
+       .bmdma_setup            = ata_bmdma_setup,
+       .bmdma_start            = ata_bmdma_start,
+       .bmdma_stop             = ata_bmdma_stop,
+       .bmdma_status           = ata_bmdma_status,
+       .qc_prep                = ata_qc_prep,
+       .qc_issue               = ata_qc_issue_prot,
+       .data_xfer              = ata_mmio_data_xfer,
+       .freeze                 = ata_bmdma_freeze,
+       .thaw                   = ata_bmdma_thaw,
+       .error_handler          = ata_bmdma_error_handler,
+       .post_internal_cmd      = ata_bmdma_post_internal_cmd,
+       .irq_handler            = vsc_sata_interrupt,
+       .irq_clear              = ata_bmdma_irq_clear,
+       .scr_read               = vsc_sata_scr_read,
+       .scr_write              = vsc_sata_scr_write,
+       .port_start             = ata_port_start,
+       .port_stop              = ata_port_stop,
+       .host_stop              = ata_pci_host_stop,
+};
+
+static void __devinit vsc_sata_setup_port(struct ata_ioports *port, unsigned long base)
+{
+       port->cmd_addr          = base + VSC_SATA_TF_CMD_OFFSET;
+       port->data_addr         = base + VSC_SATA_TF_DATA_OFFSET;
+       port->error_addr        = base + VSC_SATA_TF_ERROR_OFFSET;
+       port->feature_addr      = base + VSC_SATA_TF_FEATURE_OFFSET;
+       port->nsect_addr        = base + VSC_SATA_TF_NSECT_OFFSET;
+       port->lbal_addr         = base + VSC_SATA_TF_LBAL_OFFSET;
+       port->lbam_addr         = base + VSC_SATA_TF_LBAM_OFFSET;
+       port->lbah_addr         = base + VSC_SATA_TF_LBAH_OFFSET;
+       port->device_addr       = base + VSC_SATA_TF_DEVICE_OFFSET;
+       port->status_addr       = base + VSC_SATA_TF_STATUS_OFFSET;
+       port->command_addr      = base + VSC_SATA_TF_COMMAND_OFFSET;
+       port->altstatus_addr    = base + VSC_SATA_TF_ALTSTATUS_OFFSET;
+       port->ctl_addr          = base + VSC_SATA_TF_CTL_OFFSET;
+       port->bmdma_addr        = base + VSC_SATA_DMA_CMD_OFFSET;
+       port->scr_addr          = base + VSC_SATA_SCR_STATUS_OFFSET;
+       writel(0, base + VSC_SATA_UP_DESCRIPTOR_OFFSET);
+       writel(0, base + VSC_SATA_UP_DATA_BUFFER_OFFSET);
+}
+
+
+static int __devinit vsc_sata_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
+{
+       static int printed_version;
+       struct ata_probe_ent *probe_ent = NULL;
+       unsigned long base;
+       int pci_dev_busy = 0;
+       void __iomem *mmio_base;
+       int rc;
+
+       if (!printed_version++)
+               dev_printk(KERN_DEBUG, &pdev->dev, "version " DRV_VERSION "\n");
+
+       rc = pci_enable_device(pdev);
+       if (rc)
+               return rc;
+
+       /*
+        * Check if we have needed resource mapped.
+        */
+       if (pci_resource_len(pdev, 0) == 0) {
+               rc = -ENODEV;
+               goto err_out;
+       }
+
+       rc = pci_request_regions(pdev, DRV_NAME);
+       if (rc) {
+               pci_dev_busy = 1;
+               goto err_out;
+       }
+
+       /*
+        * Use 32 bit DMA mask, because 64 bit address support is poor.
+        */
+       rc = pci_set_dma_mask(pdev, DMA_32BIT_MASK);
+       if (rc)
+               goto err_out_regions;
+       rc = pci_set_consistent_dma_mask(pdev, DMA_32BIT_MASK);
+       if (rc)
+               goto err_out_regions;
+
+       probe_ent = kmalloc(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);
+
+       mmio_base = pci_iomap(pdev, 0, 0);
+       if (mmio_base == NULL) {
+               rc = -ENOMEM;
+               goto err_out_free_ent;
+       }
+       base = (unsigned long) mmio_base;
+
+       /*
+        * Due to a bug in the chip, the default cache line size can't be used
+        */
+       pci_write_config_byte(pdev, PCI_CACHE_LINE_SIZE, 0x80);
+
+       probe_ent->sht = &vsc_sata_sht;
+       probe_ent->host_flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
+                               ATA_FLAG_MMIO;
+       probe_ent->port_ops = &vsc_sata_ops;
+       probe_ent->n_ports = 4;
+       probe_ent->irq = pdev->irq;
+       probe_ent->irq_flags = IRQF_SHARED;
+       probe_ent->mmio_base = mmio_base;
+
+       /* We don't care much about the PIO/UDMA masks, but the core won't like us
+        * if we don't fill these
+        */
+       probe_ent->pio_mask = 0x1f;
+       probe_ent->mwdma_mask = 0x07;
+       probe_ent->udma_mask = 0x7f;
+
+       /* We have 4 ports per PCI function */
+       vsc_sata_setup_port(&probe_ent->port[0], base + 1 * VSC_SATA_PORT_OFFSET);
+       vsc_sata_setup_port(&probe_ent->port[1], base + 2 * VSC_SATA_PORT_OFFSET);
+       vsc_sata_setup_port(&probe_ent->port[2], base + 3 * VSC_SATA_PORT_OFFSET);
+       vsc_sata_setup_port(&probe_ent->port[3], base + 4 * VSC_SATA_PORT_OFFSET);
+
+       pci_set_master(pdev);
+
+       /*
+        * Config offset 0x98 is "Extended Control and Status Register 0"
+        * Default value is (1 << 28).  All bits except bit 28 are reserved in
+        * DPA mode.  If bit 28 is set, LED 0 reflects all ports' activity.
+        * If bit 28 is clear, each port has its own LED.
+        */
+       pci_write_config_dword(pdev, 0x98, 0);
+
+       /* FIXME: check ata_device_add return value */
+       ata_device_add(probe_ent);
+       kfree(probe_ent);
+
+       return 0;
+
+err_out_free_ent:
+       kfree(probe_ent);
+err_out_regions:
+       pci_release_regions(pdev);
+err_out:
+       if (!pci_dev_busy)
+               pci_disable_device(pdev);
+       return rc;
+}
+
+
+static const struct pci_device_id vsc_sata_pci_tbl[] = {
+       { PCI_VENDOR_ID_VITESSE, 0x7174,
+         PCI_ANY_ID, PCI_ANY_ID, 0x10600, 0xFFFFFF, 0 },
+       { PCI_VENDOR_ID_INTEL, 0x3200,
+         PCI_ANY_ID, PCI_ANY_ID, 0x10600, 0xFFFFFF, 0 },
+       { }     /* terminate list */
+};
+
+
+static struct pci_driver vsc_sata_pci_driver = {
+       .name                   = DRV_NAME,
+       .id_table               = vsc_sata_pci_tbl,
+       .probe                  = vsc_sata_init_one,
+       .remove                 = ata_pci_remove_one,
+};
+
+
+static int __init vsc_sata_init(void)
+{
+       return pci_register_driver(&vsc_sata_pci_driver);
+}
+
+
+static void __exit vsc_sata_exit(void)
+{
+       pci_unregister_driver(&vsc_sata_pci_driver);
+}
+
+
+MODULE_AUTHOR("Jeremy Higdon");
+MODULE_DESCRIPTION("low-level driver for Vitesse VSC7174 SATA controller");
+MODULE_LICENSE("GPL");
+MODULE_DEVICE_TABLE(pci, vsc_sata_pci_tbl);
+MODULE_VERSION(DRV_VERSION);
+
+module_init(vsc_sata_init);
+module_exit(vsc_sata_exit);
index 96a81cd..2df4d15 100644 (file)
@@ -471,67 +471,6 @@ config SCSI_IN2000
 
 source "drivers/scsi/megaraid/Kconfig.megaraid"
 
-config SCSI_SATA
-       tristate "Serial ATA (SATA) support"
-       depends on SCSI
-       help
-         This driver family supports Serial ATA host controllers
-         and devices.
-
-         If unsure, say N.
-
-config SCSI_SATA_AHCI
-       tristate "AHCI SATA support"
-       depends on SCSI_SATA && PCI
-       help
-         This option enables support for AHCI Serial ATA.
-
-         If unsure, say N.
-
-config SCSI_SATA_SVW
-       tristate "ServerWorks Frodo / Apple K2 SATA support"
-       depends on SCSI_SATA && PCI
-       help
-         This option enables support for Broadcom/Serverworks/Apple K2
-         SATA support.
-
-         If unsure, say N.
-
-config SCSI_ATA_PIIX
-       tristate "Intel PIIX/ICH SATA support"
-       depends on SCSI_SATA && PCI
-       help
-         This option enables support for ICH5/6/7/8 Serial ATA.
-         If PATA support was enabled previously, this enables
-         support for select Intel PIIX/ICH PATA host controllers.
-
-         If unsure, say N.
-
-config SCSI_SATA_MV
-       tristate "Marvell SATA support (HIGHLY EXPERIMENTAL)"
-       depends on SCSI_SATA && PCI && EXPERIMENTAL
-       help
-         This option enables support for the Marvell Serial ATA family.
-         Currently supports 88SX[56]0[48][01] chips.
-
-         If unsure, say N.
-
-config SCSI_SATA_NV
-       tristate "NVIDIA SATA support"
-       depends on SCSI_SATA && PCI && EXPERIMENTAL
-       help
-         This option enables support for NVIDIA Serial ATA.
-
-         If unsure, say N.
-
-config SCSI_PDC_ADMA
-       tristate "Pacific Digital ADMA support"
-       depends on SCSI_SATA && PCI
-       help
-         This option enables support for Pacific Digital ADMA controllers
-
-         If unsure, say N.
-
 config SCSI_HPTIOP
        tristate "HighPoint RocketRAID 3xxx Controller support"
        depends on SCSI && PCI
@@ -542,83 +481,6 @@ config SCSI_HPTIOP
          To compile this driver as a module, choose M here; the module
          will be called hptiop. If unsure, say N.
 
-config SCSI_SATA_QSTOR
-       tristate "Pacific Digital SATA QStor support"
-       depends on SCSI_SATA && PCI
-       help
-         This option enables support for Pacific Digital Serial ATA QStor.
-
-         If unsure, say N.
-
-config SCSI_SATA_PROMISE
-       tristate "Promise SATA TX2/TX4 support"
-       depends on SCSI_SATA && PCI
-       help
-         This option enables support for Promise Serial ATA TX2/TX4.
-
-         If unsure, say N.
-
-config SCSI_SATA_SX4
-       tristate "Promise SATA SX4 support"
-       depends on SCSI_SATA && PCI && EXPERIMENTAL
-       help
-         This option enables support for Promise Serial ATA SX4.
-
-         If unsure, say N.
-
-config SCSI_SATA_SIL
-       tristate "Silicon Image SATA support"
-       depends on SCSI_SATA && PCI && EXPERIMENTAL
-       help
-         This option enables support for Silicon Image Serial ATA.
-
-         If unsure, say N.
-
-config SCSI_SATA_SIL24
-       tristate "Silicon Image 3124/3132 SATA support"
-       depends on SCSI_SATA && PCI && EXPERIMENTAL
-       help
-         This option enables support for Silicon Image 3124/3132 Serial ATA.
-
-         If unsure, say N.
-
-config SCSI_SATA_SIS
-       tristate "SiS 964/180 SATA support"
-       depends on SCSI_SATA && PCI && EXPERIMENTAL
-       help
-         This option enables support for SiS Serial ATA 964/180.
-
-         If unsure, say N.
-
-config SCSI_SATA_ULI
-       tristate "ULi Electronics SATA support"
-       depends on SCSI_SATA && PCI && EXPERIMENTAL
-       help
-         This option enables support for ULi Electronics SATA.
-
-         If unsure, say N.
-
-config SCSI_SATA_VIA
-       tristate "VIA SATA support"
-       depends on SCSI_SATA && PCI
-       help
-         This option enables support for VIA Serial ATA.
-
-         If unsure, say N.
-
-config SCSI_SATA_VITESSE
-       tristate "VITESSE VSC-7174 / INTEL 31244 SATA support"
-       depends on SCSI_SATA && PCI
-       help
-         This option enables support for Vitesse VSC7174 and Intel 31244 Serial ATA.
-
-         If unsure, say N.
-
-config SCSI_SATA_INTEL_COMBINED
-       bool
-       depends on IDE=y && !BLK_DEV_IDE_SATA && (SCSI_SATA_AHCI || SCSI_ATA_PIIX)
-       default y
-
 config SCSI_BUSLOGIC
        tristate "BusLogic SCSI support"
        depends on (PCI || ISA || MCA) && SCSI && ISA_DMA_API
index ebd0cf0..b678f95 100644 (file)
@@ -122,21 +122,6 @@ obj-$(CONFIG_SCSI_LASI700) += 53c700.o lasi700.o
 obj-$(CONFIG_SCSI_NSP32)       += nsp32.o
 obj-$(CONFIG_SCSI_IPR)         += ipr.o
 obj-$(CONFIG_SCSI_IBMVSCSI)    += ibmvscsi/
-obj-$(CONFIG_SCSI_SATA_AHCI)   += libata.o ahci.o
-obj-$(CONFIG_SCSI_SATA_SVW)    += libata.o sata_svw.o
-obj-$(CONFIG_SCSI_ATA_PIIX)    += libata.o ata_piix.o
-obj-$(CONFIG_SCSI_SATA_PROMISE)        += libata.o sata_promise.o
-obj-$(CONFIG_SCSI_SATA_QSTOR)  += libata.o sata_qstor.o
-obj-$(CONFIG_SCSI_SATA_SIL)    += libata.o sata_sil.o
-obj-$(CONFIG_SCSI_SATA_SIL24)  += libata.o sata_sil24.o
-obj-$(CONFIG_SCSI_SATA_VIA)    += libata.o sata_via.o
-obj-$(CONFIG_SCSI_SATA_VITESSE)        += libata.o sata_vsc.o
-obj-$(CONFIG_SCSI_SATA_SIS)    += libata.o sata_sis.o
-obj-$(CONFIG_SCSI_SATA_SX4)    += libata.o sata_sx4.o
-obj-$(CONFIG_SCSI_SATA_NV)     += libata.o sata_nv.o
-obj-$(CONFIG_SCSI_SATA_ULI)    += libata.o sata_uli.o
-obj-$(CONFIG_SCSI_SATA_MV)     += libata.o sata_mv.o
-obj-$(CONFIG_SCSI_PDC_ADMA)    += libata.o pdc_adma.o
 obj-$(CONFIG_SCSI_HPTIOP)      += hptiop.o
 
 obj-$(CONFIG_ARM)              += arm/
@@ -166,7 +151,6 @@ 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-bmdma.o libata-eh.o
 oktagon_esp_mod-objs   := oktagon_esp.o oktagon_io.o
 
 # Files generated that shall be removed upon make clean
diff --git a/drivers/scsi/ahci.c b/drivers/scsi/ahci.c
deleted file mode 100644 (file)
index 813031c..0000000
+++ /dev/null
@@ -1,1684 +0,0 @@
-/*
- *  ahci.c - AHCI SATA support
- *
- *  Maintained by:  Jeff Garzik <jgarzik@pobox.com>
- *                 Please ALWAYS copy linux-ide@vger.kernel.org
- *                 on emails.
- *
- *  Copyright 2004-2005 Red Hat, Inc.
- *
- *
- *  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.*
- *
- * AHCI hardware documentation:
- * http://www.intel.com/technology/serialata/pdf/rev1_0.pdf
- * http://www.intel.com/technology/serialata/pdf/rev1_1.pdf
- *
- */
-
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/pci.h>
-#include <linux/init.h>
-#include <linux/blkdev.h>
-#include <linux/delay.h>
-#include <linux/interrupt.h>
-#include <linux/sched.h>
-#include <linux/dma-mapping.h>
-#include <linux/device.h>
-#include <scsi/scsi_host.h>
-#include <scsi/scsi_cmnd.h>
-#include <linux/libata.h>
-#include <asm/io.h>
-
-#define DRV_NAME       "ahci"
-#define DRV_VERSION    "2.0"
-
-
-enum {
-       AHCI_PCI_BAR            = 5,
-       AHCI_MAX_SG             = 168, /* hardware max is 64K */
-       AHCI_DMA_BOUNDARY       = 0xffffffff,
-       AHCI_USE_CLUSTERING     = 0,
-       AHCI_MAX_CMDS           = 32,
-       AHCI_CMD_SZ             = 32,
-       AHCI_CMD_SLOT_SZ        = AHCI_MAX_CMDS * AHCI_CMD_SZ,
-       AHCI_RX_FIS_SZ          = 256,
-       AHCI_CMD_TBL_CDB        = 0x40,
-       AHCI_CMD_TBL_HDR_SZ     = 0x80,
-       AHCI_CMD_TBL_SZ         = AHCI_CMD_TBL_HDR_SZ + (AHCI_MAX_SG * 16),
-       AHCI_CMD_TBL_AR_SZ      = AHCI_CMD_TBL_SZ * AHCI_MAX_CMDS,
-       AHCI_PORT_PRIV_DMA_SZ   = AHCI_CMD_SLOT_SZ + AHCI_CMD_TBL_AR_SZ +
-                                 AHCI_RX_FIS_SZ,
-       AHCI_IRQ_ON_SG          = (1 << 31),
-       AHCI_CMD_ATAPI          = (1 << 5),
-       AHCI_CMD_WRITE          = (1 << 6),
-       AHCI_CMD_PREFETCH       = (1 << 7),
-       AHCI_CMD_RESET          = (1 << 8),
-       AHCI_CMD_CLR_BUSY       = (1 << 10),
-
-       RX_FIS_D2H_REG          = 0x40, /* offset of D2H Register FIS data */
-       RX_FIS_UNK              = 0x60, /* offset of Unknown FIS data */
-
-       board_ahci              = 0,
-       board_ahci_vt8251       = 1,
-
-       /* global controller registers */
-       HOST_CAP                = 0x00, /* host capabilities */
-       HOST_CTL                = 0x04, /* global host control */
-       HOST_IRQ_STAT           = 0x08, /* interrupt status */
-       HOST_PORTS_IMPL         = 0x0c, /* bitmap of implemented ports */
-       HOST_VERSION            = 0x10, /* AHCI spec. version compliancy */
-
-       /* HOST_CTL bits */
-       HOST_RESET              = (1 << 0),  /* reset controller; self-clear */
-       HOST_IRQ_EN             = (1 << 1),  /* global IRQ enable */
-       HOST_AHCI_EN            = (1 << 31), /* AHCI enabled */
-
-       /* HOST_CAP bits */
-       HOST_CAP_SSC            = (1 << 14), /* Slumber capable */
-       HOST_CAP_CLO            = (1 << 24), /* Command List Override support */
-       HOST_CAP_SSS            = (1 << 27), /* Staggered Spin-up */
-       HOST_CAP_NCQ            = (1 << 30), /* Native Command Queueing */
-       HOST_CAP_64             = (1 << 31), /* PCI DAC (64-bit DMA) support */
-
-       /* registers for each SATA port */
-       PORT_LST_ADDR           = 0x00, /* command list DMA addr */
-       PORT_LST_ADDR_HI        = 0x04, /* command list DMA addr hi */
-       PORT_FIS_ADDR           = 0x08, /* FIS rx buf addr */
-       PORT_FIS_ADDR_HI        = 0x0c, /* FIS rx buf addr hi */
-       PORT_IRQ_STAT           = 0x10, /* interrupt status */
-       PORT_IRQ_MASK           = 0x14, /* interrupt enable/disable mask */
-       PORT_CMD                = 0x18, /* port command */
-       PORT_TFDATA             = 0x20, /* taskfile data */
-       PORT_SIG                = 0x24, /* device TF signature */
-       PORT_CMD_ISSUE          = 0x38, /* command issue */
-       PORT_SCR                = 0x28, /* SATA phy register block */
-       PORT_SCR_STAT           = 0x28, /* SATA phy register: SStatus */
-       PORT_SCR_CTL            = 0x2c, /* SATA phy register: SControl */
-       PORT_SCR_ERR            = 0x30, /* SATA phy register: SError */
-       PORT_SCR_ACT            = 0x34, /* SATA phy register: SActive */
-
-       /* PORT_IRQ_{STAT,MASK} bits */
-       PORT_IRQ_COLD_PRES      = (1 << 31), /* cold presence detect */
-       PORT_IRQ_TF_ERR         = (1 << 30), /* task file error */
-       PORT_IRQ_HBUS_ERR       = (1 << 29), /* host bus fatal error */
-       PORT_IRQ_HBUS_DATA_ERR  = (1 << 28), /* host bus data error */
-       PORT_IRQ_IF_ERR         = (1 << 27), /* interface fatal error */
-       PORT_IRQ_IF_NONFATAL    = (1 << 26), /* interface non-fatal error */
-       PORT_IRQ_OVERFLOW       = (1 << 24), /* xfer exhausted available S/G */
-       PORT_IRQ_BAD_PMP        = (1 << 23), /* incorrect port multiplier */
-
-       PORT_IRQ_PHYRDY         = (1 << 22), /* PhyRdy changed */
-       PORT_IRQ_DEV_ILCK       = (1 << 7), /* device interlock */
-       PORT_IRQ_CONNECT        = (1 << 6), /* port connect change status */
-       PORT_IRQ_SG_DONE        = (1 << 5), /* descriptor processed */
-       PORT_IRQ_UNK_FIS        = (1 << 4), /* unknown FIS rx'd */
-       PORT_IRQ_SDB_FIS        = (1 << 3), /* Set Device Bits FIS rx'd */
-       PORT_IRQ_DMAS_FIS       = (1 << 2), /* DMA Setup FIS rx'd */
-       PORT_IRQ_PIOS_FIS       = (1 << 1), /* PIO Setup FIS rx'd */
-       PORT_IRQ_D2H_REG_FIS    = (1 << 0), /* D2H Register FIS rx'd */
-
-       PORT_IRQ_FREEZE         = PORT_IRQ_HBUS_ERR |
-                                 PORT_IRQ_IF_ERR |
-                                 PORT_IRQ_CONNECT |
-                                 PORT_IRQ_PHYRDY |
-                                 PORT_IRQ_UNK_FIS,
-       PORT_IRQ_ERROR          = PORT_IRQ_FREEZE |
-                                 PORT_IRQ_TF_ERR |
-                                 PORT_IRQ_HBUS_DATA_ERR,
-       DEF_PORT_IRQ            = PORT_IRQ_ERROR | PORT_IRQ_SG_DONE |
-                                 PORT_IRQ_SDB_FIS | PORT_IRQ_DMAS_FIS |
-                                 PORT_IRQ_PIOS_FIS | PORT_IRQ_D2H_REG_FIS,
-
-       /* PORT_CMD bits */
-       PORT_CMD_ATAPI          = (1 << 24), /* Device is ATAPI */
-       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 */
-
-       PORT_CMD_ICC_MASK       = (0xf << 28), /* i/f ICC state mask */
-       PORT_CMD_ICC_ACTIVE     = (0x1 << 28), /* Put i/f in active state */
-       PORT_CMD_ICC_PARTIAL    = (0x2 << 28), /* Put i/f in partial state */
-       PORT_CMD_ICC_SLUMBER    = (0x6 << 28), /* Put i/f in slumber state */
-
-       /* hpriv->flags bits */
-       AHCI_FLAG_MSI           = (1 << 0),
-
-       /* ap->flags bits */
-       AHCI_FLAG_RESET_NEEDS_CLO       = (1 << 24),
-       AHCI_FLAG_NO_NCQ                = (1 << 25),
-};
-
-struct ahci_cmd_hdr {
-       u32                     opts;
-       u32                     status;
-       u32                     tbl_addr;
-       u32                     tbl_addr_hi;
-       u32                     reserved[4];
-};
-
-struct ahci_sg {
-       u32                     addr;
-       u32                     addr_hi;
-       u32                     reserved;
-       u32                     flags_size;
-};
-
-struct ahci_host_priv {
-       unsigned long           flags;
-       u32                     cap;    /* cache of HOST_CAP register */
-       u32                     port_map; /* cache of HOST_PORTS_IMPL reg */
-};
-
-struct ahci_port_priv {
-       struct ahci_cmd_hdr     *cmd_slot;
-       dma_addr_t              cmd_slot_dma;
-       void                    *cmd_tbl;
-       dma_addr_t              cmd_tbl_dma;
-       void                    *rx_fis;
-       dma_addr_t              rx_fis_dma;
-};
-
-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 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_irq_clear(struct ata_port *ap);
-static int ahci_port_start(struct ata_port *ap);
-static void ahci_port_stop(struct ata_port *ap);
-static void ahci_tf_read(struct ata_port *ap, struct ata_taskfile *tf);
-static void ahci_qc_prep(struct ata_queued_cmd *qc);
-static u8 ahci_check_status(struct ata_port *ap);
-static void ahci_freeze(struct ata_port *ap);
-static void ahci_thaw(struct ata_port *ap);
-static void ahci_error_handler(struct ata_port *ap);
-static void ahci_post_internal_cmd(struct ata_queued_cmd *qc);
-static int ahci_port_suspend(struct ata_port *ap, pm_message_t mesg);
-static int ahci_port_resume(struct ata_port *ap);
-static int ahci_pci_device_suspend(struct pci_dev *pdev, pm_message_t mesg);
-static int ahci_pci_device_resume(struct pci_dev *pdev);
-static void ahci_remove_one (struct pci_dev *pdev);
-
-static struct scsi_host_template ahci_sht = {
-       .module                 = THIS_MODULE,
-       .name                   = DRV_NAME,
-       .ioctl                  = ata_scsi_ioctl,
-       .queuecommand           = ata_scsi_queuecmd,
-       .change_queue_depth     = ata_scsi_change_queue_depth,
-       .can_queue              = AHCI_MAX_CMDS - 1,
-       .this_id                = ATA_SHT_THIS_ID,
-       .sg_tablesize           = AHCI_MAX_SG,
-       .cmd_per_lun            = ATA_SHT_CMD_PER_LUN,
-       .emulated               = ATA_SHT_EMULATED,
-       .use_clustering         = AHCI_USE_CLUSTERING,
-       .proc_name              = DRV_NAME,
-       .dma_boundary           = AHCI_DMA_BOUNDARY,
-       .slave_configure        = ata_scsi_slave_config,
-       .slave_destroy          = ata_scsi_slave_destroy,
-       .bios_param             = ata_std_bios_param,
-       .suspend                = ata_scsi_device_suspend,
-       .resume                 = ata_scsi_device_resume,
-};
-
-static const struct ata_port_operations ahci_ops = {
-       .port_disable           = ata_port_disable,
-
-       .check_status           = ahci_check_status,
-       .check_altstatus        = ahci_check_status,
-       .dev_select             = ata_noop_dev_select,
-
-       .tf_read                = ahci_tf_read,
-
-       .qc_prep                = ahci_qc_prep,
-       .qc_issue               = ahci_qc_issue,
-
-       .irq_handler            = ahci_interrupt,
-       .irq_clear              = ahci_irq_clear,
-
-       .scr_read               = ahci_scr_read,
-       .scr_write              = ahci_scr_write,
-
-       .freeze                 = ahci_freeze,
-       .thaw                   = ahci_thaw,
-
-       .error_handler          = ahci_error_handler,
-       .post_internal_cmd      = ahci_post_internal_cmd,
-
-       .port_suspend           = ahci_port_suspend,
-       .port_resume            = ahci_port_resume,
-
-       .port_start             = ahci_port_start,
-       .port_stop              = ahci_port_stop,
-};
-
-static const struct ata_port_info ahci_port_info[] = {
-       /* board_ahci */
-       {
-               .sht            = &ahci_sht,
-               .host_flags     = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
-                                 ATA_FLAG_MMIO | ATA_FLAG_PIO_DMA |
-                                 ATA_FLAG_SKIP_D2H_BSY,
-               .pio_mask       = 0x1f, /* pio0-4 */
-               .udma_mask      = 0x7f, /* udma0-6 ; FIXME */
-               .port_ops       = &ahci_ops,
-       },
-       /* board_ahci_vt8251 */
-       {
-               .sht            = &ahci_sht,
-               .host_flags     = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
-                                 ATA_FLAG_MMIO | ATA_FLAG_PIO_DMA |
-                                 ATA_FLAG_SKIP_D2H_BSY |
-                                 AHCI_FLAG_RESET_NEEDS_CLO | AHCI_FLAG_NO_NCQ,
-               .pio_mask       = 0x1f, /* pio0-4 */
-               .udma_mask      = 0x7f, /* udma0-6 ; FIXME */
-               .port_ops       = &ahci_ops,
-       },
-};
-
-static const struct pci_device_id ahci_pci_tbl[] = {
-       /* Intel */
-       { PCI_VENDOR_ID_INTEL, 0x2652, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-         board_ahci }, /* ICH6 */
-       { PCI_VENDOR_ID_INTEL, 0x2653, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-         board_ahci }, /* ICH6M */
-       { PCI_VENDOR_ID_INTEL, 0x27c1, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-         board_ahci }, /* ICH7 */
-       { PCI_VENDOR_ID_INTEL, 0x27c5, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-         board_ahci }, /* ICH7M */
-       { PCI_VENDOR_ID_INTEL, 0x27c3, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-         board_ahci }, /* ICH7R */
-       { PCI_VENDOR_ID_AL, 0x5288, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-         board_ahci }, /* ULi M5288 */
-       { PCI_VENDOR_ID_INTEL, 0x2681, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-         board_ahci }, /* ESB2 */
-       { PCI_VENDOR_ID_INTEL, 0x2682, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-         board_ahci }, /* ESB2 */
-       { PCI_VENDOR_ID_INTEL, 0x2683, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-         board_ahci }, /* ESB2 */
-       { PCI_VENDOR_ID_INTEL, 0x27c6, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-         board_ahci }, /* ICH7-M DH */
-       { PCI_VENDOR_ID_INTEL, 0x2821, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-         board_ahci }, /* ICH8 */
-       { PCI_VENDOR_ID_INTEL, 0x2822, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-         board_ahci }, /* ICH8 */
-       { PCI_VENDOR_ID_INTEL, 0x2824, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-         board_ahci }, /* ICH8 */
-       { PCI_VENDOR_ID_INTEL, 0x2829, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-         board_ahci }, /* ICH8M */
-       { PCI_VENDOR_ID_INTEL, 0x282a, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-         board_ahci }, /* ICH8M */
-
-       /* JMicron */
-       { 0x197b, 0x2360, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-         board_ahci }, /* JMicron JMB360 */
-       { 0x197b, 0x2361, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-         board_ahci }, /* JMicron JMB361 */
-       { 0x197b, 0x2363, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-         board_ahci }, /* JMicron JMB363 */
-       { 0x197b, 0x2365, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-         board_ahci }, /* JMicron JMB365 */
-       { 0x197b, 0x2366, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-         board_ahci }, /* JMicron JMB366 */
-
-       /* ATI */
-       { PCI_VENDOR_ID_ATI, 0x4380, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-         board_ahci }, /* ATI SB600 non-raid */
-       { PCI_VENDOR_ID_ATI, 0x4381, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-         board_ahci }, /* ATI SB600 raid */
-
-       /* VIA */
-       { PCI_VENDOR_ID_VIA, 0x3349, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-         board_ahci_vt8251 }, /* VIA VT8251 */
-
-       /* NVIDIA */
-       { PCI_VENDOR_ID_NVIDIA, 0x044c, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-         board_ahci },         /* MCP65 */
-       { PCI_VENDOR_ID_NVIDIA, 0x044d, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-         board_ahci },         /* MCP65 */
-       { PCI_VENDOR_ID_NVIDIA, 0x044e, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-         board_ahci },         /* MCP65 */
-       { PCI_VENDOR_ID_NVIDIA, 0x044f, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-         board_ahci },         /* MCP65 */
-
-       /* SiS */
-       { PCI_VENDOR_ID_SI, 0x1184, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-         board_ahci }, /* SiS 966 */
-       { PCI_VENDOR_ID_SI, 0x1185, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-         board_ahci }, /* SiS 966 */
-       { PCI_VENDOR_ID_SI, 0x0186, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-         board_ahci }, /* SiS 968 */
-
-       { }     /* terminate list */
-};
-
-
-static struct pci_driver ahci_pci_driver = {
-       .name                   = DRV_NAME,
-       .id_table               = ahci_pci_tbl,
-       .probe                  = ahci_init_one,
-       .suspend                = ahci_pci_device_suspend,
-       .resume                 = ahci_pci_device_resume,
-       .remove                 = ahci_remove_one,
-};
-
-
-static inline unsigned long ahci_port_base_ul (unsigned long base, unsigned int port)
-{
-       return base + 0x100 + (port * 0x80);
-}
-
-static inline void __iomem *ahci_port_base (void __iomem *base, unsigned int port)
-{
-       return (void __iomem *) ahci_port_base_ul((unsigned long)base, port);
-}
-
-static u32 ahci_scr_read (struct ata_port *ap, unsigned int sc_reg_in)
-{
-       unsigned int sc_reg;
-
-       switch (sc_reg_in) {
-       case SCR_STATUS:        sc_reg = 0; break;
-       case SCR_CONTROL:       sc_reg = 1; break;
-       case SCR_ERROR:         sc_reg = 2; break;
-       case SCR_ACTIVE:        sc_reg = 3; break;
-       default:
-               return 0xffffffffU;
-       }
-
-       return readl((void __iomem *) ap->ioaddr.scr_addr + (sc_reg * 4));
-}
-
-
-static void ahci_scr_write (struct ata_port *ap, unsigned int sc_reg_in,
-                              u32 val)
-{
-       unsigned int sc_reg;
-
-       switch (sc_reg_in) {
-       case SCR_STATUS:        sc_reg = 0; break;
-       case SCR_CONTROL:       sc_reg = 1; break;
-       case SCR_ERROR:         sc_reg = 2; break;
-       case SCR_ACTIVE:        sc_reg = 3; break;
-       default:
-               return;
-       }
-
-       writel(val, (void __iomem *) ap->ioaddr.scr_addr + (sc_reg * 4));
-}
-
-static void ahci_start_engine(void __iomem *port_mmio)
-{
-       u32 tmp;
-
-       /* start DMA */
-       tmp = readl(port_mmio + PORT_CMD);
-       tmp |= PORT_CMD_START;
-       writel(tmp, port_mmio + PORT_CMD);
-       readl(port_mmio + PORT_CMD); /* flush */
-}
-
-static int ahci_stop_engine(void __iomem *port_mmio)
-{
-       u32 tmp;
-
-       tmp = readl(port_mmio + PORT_CMD);
-
-       /* check if the HBA is idle */
-       if ((tmp & (PORT_CMD_START | PORT_CMD_LIST_ON)) == 0)
-               return 0;
-
-       /* setting HBA to idle */
-       tmp &= ~PORT_CMD_START;
-       writel(tmp, port_mmio + PORT_CMD);
-
-       /* wait for engine to stop. This could be as long as 500 msec */
-       tmp = ata_wait_register(port_mmio + PORT_CMD,
-                               PORT_CMD_LIST_ON, PORT_CMD_LIST_ON, 1, 500);
-       if (tmp & PORT_CMD_LIST_ON)
-               return -EIO;
-
-       return 0;
-}
-
-static void ahci_start_fis_rx(void __iomem *port_mmio, u32 cap,
-                             dma_addr_t cmd_slot_dma, dma_addr_t rx_fis_dma)
-{
-       u32 tmp;
-
-       /* set FIS registers */
-       if (cap & HOST_CAP_64)
-               writel((cmd_slot_dma >> 16) >> 16, port_mmio + PORT_LST_ADDR_HI);
-       writel(cmd_slot_dma & 0xffffffff, port_mmio + PORT_LST_ADDR);
-
-       if (cap & HOST_CAP_64)
-               writel((rx_fis_dma >> 16) >> 16, port_mmio + PORT_FIS_ADDR_HI);
-       writel(rx_fis_dma & 0xffffffff, port_mmio + PORT_FIS_ADDR);
-
-       /* enable FIS reception */
-       tmp = readl(port_mmio + PORT_CMD);
-       tmp |= PORT_CMD_FIS_RX;
-       writel(tmp, port_mmio + PORT_CMD);
-
-       /* flush */
-       readl(port_mmio + PORT_CMD);
-}
-
-static int ahci_stop_fis_rx(void __iomem *port_mmio)
-{
-       u32 tmp;
-
-       /* disable FIS reception */
-       tmp = readl(port_mmio + PORT_CMD);
-       tmp &= ~PORT_CMD_FIS_RX;
-       writel(tmp, port_mmio + PORT_CMD);
-
-       /* wait for completion, spec says 500ms, give it 1000 */
-       tmp = ata_wait_register(port_mmio + PORT_CMD, PORT_CMD_FIS_ON,
-                               PORT_CMD_FIS_ON, 10, 1000);
-       if (tmp & PORT_CMD_FIS_ON)
-               return -EBUSY;
-
-       return 0;
-}
-
-static void ahci_power_up(void __iomem *port_mmio, u32 cap)
-{
-       u32 cmd;
-
-       cmd = readl(port_mmio + PORT_CMD) & ~PORT_CMD_ICC_MASK;
-
-       /* spin up device */
-       if (cap & HOST_CAP_SSS) {
-               cmd |= PORT_CMD_SPIN_UP;
-               writel(cmd, port_mmio + PORT_CMD);
-       }
-
-       /* wake up link */
-       writel(cmd | PORT_CMD_ICC_ACTIVE, port_mmio + PORT_CMD);
-}
-
-static void ahci_power_down(void __iomem *port_mmio, u32 cap)
-{
-       u32 cmd, scontrol;
-
-       cmd = readl(port_mmio + PORT_CMD) & ~PORT_CMD_ICC_MASK;
-
-       if (cap & HOST_CAP_SSC) {
-               /* enable transitions to slumber mode */
-               scontrol = readl(port_mmio + PORT_SCR_CTL);
-               if ((scontrol & 0x0f00) > 0x100) {
-                       scontrol &= ~0xf00;
-                       writel(scontrol, port_mmio + PORT_SCR_CTL);
-               }
-
-               /* put device into slumber mode */
-               writel(cmd | PORT_CMD_ICC_SLUMBER, port_mmio + PORT_CMD);
-
-               /* wait for the transition to complete */
-               ata_wait_register(port_mmio + PORT_CMD, PORT_CMD_ICC_SLUMBER,
-                                 PORT_CMD_ICC_SLUMBER, 1, 50);
-       }
-
-       /* put device into listen mode */
-       if (cap & HOST_CAP_SSS) {
-               /* first set PxSCTL.DET to 0 */
-               scontrol = readl(port_mmio + PORT_SCR_CTL);
-               scontrol &= ~0xf;
-               writel(scontrol, port_mmio + PORT_SCR_CTL);
-
-               /* then set PxCMD.SUD to 0 */
-               cmd &= ~PORT_CMD_SPIN_UP;
-               writel(cmd, port_mmio + PORT_CMD);
-       }
-}
-
-static void ahci_init_port(void __iomem *port_mmio, u32 cap,
-                          dma_addr_t cmd_slot_dma, dma_addr_t rx_fis_dma)
-{
-       /* power up */
-       ahci_power_up(port_mmio, cap);
-
-       /* enable FIS reception */
-       ahci_start_fis_rx(port_mmio, cap, cmd_slot_dma, rx_fis_dma);
-
-       /* enable DMA */
-       ahci_start_engine(port_mmio);
-}
-
-static int ahci_deinit_port(void __iomem *port_mmio, u32 cap, const char **emsg)
-{
-       int rc;
-
-       /* disable DMA */
-       rc = ahci_stop_engine(port_mmio);
-       if (rc) {
-               *emsg = "failed to stop engine";
-               return rc;
-       }
-
-       /* disable FIS reception */
-       rc = ahci_stop_fis_rx(port_mmio);
-       if (rc) {
-               *emsg = "failed stop FIS RX";
-               return rc;
-       }
-
-       /* put device into slumber mode */
-       ahci_power_down(port_mmio, cap);
-
-       return 0;
-}
-
-static int ahci_reset_controller(void __iomem *mmio, struct pci_dev *pdev)
-{
-       u32 cap_save, tmp;
-
-       cap_save = readl(mmio + HOST_CAP);
-       cap_save &= ( (1<<28) | (1<<17) );
-       cap_save |= (1 << 27);
-
-       /* global controller reset */
-       tmp = readl(mmio + HOST_CTL);
-       if ((tmp & HOST_RESET) == 0) {
-               writel(tmp | HOST_RESET, mmio + HOST_CTL);
-               readl(mmio + HOST_CTL); /* flush */
-       }
-
-       /* reset must complete within 1 second, or
-        * the hardware should be considered fried.
-        */
-       ssleep(1);
-
-       tmp = readl(mmio + HOST_CTL);
-       if (tmp & HOST_RESET) {
-               dev_printk(KERN_ERR, &pdev->dev,
-                          "controller reset failed (0x%x)\n", tmp);
-               return -EIO;
-       }
-
-       writel(HOST_AHCI_EN, mmio + HOST_CTL);
-       (void) readl(mmio + HOST_CTL);  /* flush */
-       writel(cap_save, mmio + HOST_CAP);
-       writel(0xf, mmio + HOST_PORTS_IMPL);
-       (void) readl(mmio + HOST_PORTS_IMPL);   /* flush */
-
-       if (pdev->vendor == PCI_VENDOR_ID_INTEL) {
-               u16 tmp16;
-
-               /* configure PCS */
-               pci_read_config_word(pdev, 0x92, &tmp16);
-               tmp16 |= 0xf;
-               pci_write_config_word(pdev, 0x92, tmp16);
-       }
-
-       return 0;
-}
-
-static void ahci_init_controller(void __iomem *mmio, struct pci_dev *pdev,
-                                int n_ports, u32 cap)
-{
-       int i, rc;
-       u32 tmp;
-
-       for (i = 0; i < n_ports; i++) {
-               void __iomem *port_mmio = ahci_port_base(mmio, i);
-               const char *emsg = NULL;
-
-#if 0 /* BIOSen initialize this incorrectly */
-               if (!(hpriv->port_map & (1 << i)))
-                       continue;
-#endif
-
-               /* make sure port is not active */
-               rc = ahci_deinit_port(port_mmio, cap, &emsg);
-               if (rc)
-                       dev_printk(KERN_WARNING, &pdev->dev,
-                                  "%s (%d)\n", emsg, rc);
-
-               /* clear SError */
-               tmp = readl(port_mmio + PORT_SCR_ERR);
-               VPRINTK("PORT_SCR_ERR 0x%x\n", tmp);
-               writel(tmp, port_mmio + PORT_SCR_ERR);
-
-               /* clear port IRQ */
-               tmp = readl(port_mmio + PORT_IRQ_STAT);
-               VPRINTK("PORT_IRQ_STAT 0x%x\n", tmp);
-               if (tmp)
-                       writel(tmp, port_mmio + PORT_IRQ_STAT);
-
-               writel(1 << i, mmio + HOST_IRQ_STAT);
-       }
-
-       tmp = readl(mmio + HOST_CTL);
-       VPRINTK("HOST_CTL 0x%x\n", tmp);
-       writel(tmp | HOST_IRQ_EN, mmio + HOST_CTL);
-       tmp = readl(mmio + HOST_CTL);
-       VPRINTK("HOST_CTL 0x%x\n", tmp);
-}
-
-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;
-       tf.lbam         = (tmp >> 16)   & 0xff;
-       tf.lbal         = (tmp >> 8)    & 0xff;
-       tf.nsect        = (tmp)         & 0xff;
-
-       return ata_dev_classify(&tf);
-}
-
-static void ahci_fill_cmd_slot(struct ahci_port_priv *pp, unsigned int tag,
-                              u32 opts)
-{
-       dma_addr_t cmd_tbl_dma;
-
-       cmd_tbl_dma = pp->cmd_tbl_dma + tag * AHCI_CMD_TBL_SZ;
-
-       pp->cmd_slot[tag].opts = cpu_to_le32(opts);
-       pp->cmd_slot[tag].status = 0;
-       pp->cmd_slot[tag].tbl_addr = cpu_to_le32(cmd_tbl_dma & 0xffffffff);
-       pp->cmd_slot[tag].tbl_addr_hi = cpu_to_le32((cmd_tbl_dma >> 16) >> 16);
-}
-
-static int ahci_clo(struct ata_port *ap)
-{
-       void __iomem *port_mmio = (void __iomem *) ap->ioaddr.cmd_addr;
-       struct ahci_host_priv *hpriv = ap->host_set->private_data;
-       u32 tmp;
-
-       if (!(hpriv->cap & HOST_CAP_CLO))
-               return -EOPNOTSUPP;
-
-       tmp = readl(port_mmio + PORT_CMD);
-       tmp |= PORT_CMD_CLO;
-       writel(tmp, port_mmio + PORT_CMD);
-
-       tmp = ata_wait_register(port_mmio + PORT_CMD,
-                               PORT_CMD_CLO, PORT_CMD_CLO, 1, 500);
-       if (tmp & PORT_CMD_CLO)
-               return -EIO;
-
-       return 0;
-}
-
-static int ahci_prereset(struct ata_port *ap)
-{
-       if ((ap->flags & AHCI_FLAG_RESET_NEEDS_CLO) &&
-           (ata_busy_wait(ap, ATA_BUSY, 1000) & ATA_BUSY)) {
-               /* ATA_BUSY hasn't cleared, so send a CLO */
-               ahci_clo(ap);
-       }
-
-       return ata_std_prereset(ap);
-}
-
-static int ahci_softreset(struct ata_port *ap, unsigned int *class)
-{
-       struct ahci_port_priv *pp = ap->private_data;
-       void __iomem *mmio = ap->host_set->mmio_base;
-       void __iomem *port_mmio = ahci_port_base(mmio, ap->port_no);
-       const u32 cmd_fis_len = 5; /* five dwords */
-       const char *reason = NULL;
-       struct ata_taskfile tf;
-       u32 tmp;
-       u8 *fis;
-       int rc;
-
-       DPRINTK("ENTER\n");
-
-       if (ata_port_offline(ap)) {
-               DPRINTK("PHY reports no device\n");
-               *class = ATA_DEV_NONE;
-               return 0;
-       }
-
-       /* prepare for SRST (AHCI-1.1 10.4.1) */
-       rc = ahci_stop_engine(port_mmio);
-       if (rc) {
-               reason = "failed to stop engine";
-               goto fail_restart;
-       }
-
-       /* check BUSY/DRQ, perform Command List Override if necessary */
-       ahci_tf_read(ap, &tf);
-       if (tf.command & (ATA_BUSY | ATA_DRQ)) {
-               rc = ahci_clo(ap);
-
-               if (rc == -EOPNOTSUPP) {
-                       reason = "port busy but CLO unavailable";
-                       goto fail_restart;
-               } else if (rc) {
-                       reason = "port busy but CLO failed";
-                       goto fail_restart;
-               }
-       }
-
-       /* restart engine */
-       ahci_start_engine(port_mmio);
-
-       ata_tf_init(ap->device, &tf);
-       fis = pp->cmd_tbl;
-
-       /* issue the first D2H Register FIS */
-       ahci_fill_cmd_slot(pp, 0,
-                          cmd_fis_len | AHCI_CMD_RESET | AHCI_CMD_CLR_BUSY);
-
-       tf.ctl |= ATA_SRST;
-       ata_tf_to_fis(&tf, fis, 0);
-       fis[1] &= ~(1 << 7);    /* turn off Command FIS bit */
-
-       writel(1, port_mmio + PORT_CMD_ISSUE);
-
-       tmp = ata_wait_register(port_mmio + PORT_CMD_ISSUE, 0x1, 0x1, 1, 500);
-       if (tmp & 0x1) {
-               rc = -EIO;
-               reason = "1st FIS failed";
-               goto fail;
-       }
-
-       /* spec says at least 5us, but be generous and sleep for 1ms */
-       msleep(1);
-
-       /* issue the second D2H Register FIS */
-       ahci_fill_cmd_slot(pp, 0, cmd_fis_len);
-
-       tf.ctl &= ~ATA_SRST;
-       ata_tf_to_fis(&tf, fis, 0);
-       fis[1] &= ~(1 << 7);    /* turn off Command FIS bit */
-
-       writel(1, port_mmio + PORT_CMD_ISSUE);
-       readl(port_mmio + PORT_CMD_ISSUE);      /* flush */
-
-       /* spec mandates ">= 2ms" before checking status.
-        * We wait 150ms, because that was the magic delay used for
-        * ATAPI devices in Hale Landis's ATADRVR, for the period of time
-        * between when the ATA command register is written, and then
-        * status is checked.  Because waiting for "a while" before
-        * checking status is fine, post SRST, we perform this magic
-        * delay here as well.
-        */
-       msleep(150);
-
-       *class = ATA_DEV_NONE;
-       if (ata_port_online(ap)) {
-               if (ata_busy_sleep(ap, ATA_TMOUT_BOOT_QUICK, ATA_TMOUT_BOOT)) {
-                       rc = -EIO;
-                       reason = "device not ready";
-                       goto fail;
-               }
-               *class = ahci_dev_classify(ap);
-       }
-
-       DPRINTK("EXIT, class=%u\n", *class);
-       return 0;
-
- fail_restart:
-       ahci_start_engine(port_mmio);
- fail:
-       ata_port_printk(ap, KERN_ERR, "softreset failed (%s)\n", reason);
-       return rc;
-}
-
-static int ahci_hardreset(struct ata_port *ap, unsigned int *class)
-{
-       struct ahci_port_priv *pp = ap->private_data;
-       u8 *d2h_fis = pp->rx_fis + RX_FIS_D2H_REG;
-       struct ata_taskfile tf;
-       void __iomem *mmio = ap->host_set->mmio_base;
-       void __iomem *port_mmio = ahci_port_base(mmio, ap->port_no);
-       int rc;
-
-       DPRINTK("ENTER\n");
-
-       ahci_stop_engine(port_mmio);
-
-       /* clear D2H reception area to properly wait for D2H FIS */
-       ata_tf_init(ap->device, &tf);
-       tf.command = 0xff;
-       ata_tf_to_fis(&tf, d2h_fis, 0);
-
-       rc = sata_std_hardreset(ap, class);
-
-       ahci_start_engine(port_mmio);
-
-       if (rc == 0 && ata_port_online(ap))
-               *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 (*class == ATA_DEV_ATAPI)
-               new_tmp |= PORT_CMD_ATAPI;
-       else
-               new_tmp &= ~PORT_CMD_ATAPI;
-       if (new_tmp != tmp) {
-               writel(new_tmp, port_mmio + PORT_CMD);
-               readl(port_mmio + PORT_CMD); /* flush */
-       }
-}
-
-static u8 ahci_check_status(struct ata_port *ap)
-{
-       void __iomem *mmio = (void __iomem *) ap->ioaddr.cmd_addr;
-
-       return readl(mmio + PORT_TFDATA) & 0xFF;
-}
-
-static void ahci_tf_read(struct ata_port *ap, struct ata_taskfile *tf)
-{
-       struct ahci_port_priv *pp = ap->private_data;
-       u8 *d2h_fis = pp->rx_fis + RX_FIS_D2H_REG;
-
-       ata_tf_from_fis(d2h_fis, tf);
-}
-
-static unsigned int ahci_fill_sg(struct ata_queued_cmd *qc, void *cmd_tbl)
-{
-       struct scatterlist *sg;
-       struct ahci_sg *ahci_sg;
-       unsigned int n_sg = 0;
-
-       VPRINTK("ENTER\n");
-
-       /*
-        * Next, the S/G list.
-        */
-       ahci_sg = cmd_tbl + AHCI_CMD_TBL_HDR_SZ;
-       ata_for_each_sg(sg, qc) {
-               dma_addr_t addr = sg_dma_address(sg);
-               u32 sg_len = sg_dma_len(sg);
-
-               ahci_sg->addr = cpu_to_le32(addr & 0xffffffff);
-               ahci_sg->addr_hi = cpu_to_le32((addr >> 16) >> 16);
-               ahci_sg->flags_size = cpu_to_le32(sg_len - 1);
-
-               ahci_sg++;
-               n_sg++;
-       }
-
-       return n_sg;
-}
-
-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);
-       void *cmd_tbl;
-       u32 opts;
-       const u32 cmd_fis_len = 5; /* five dwords */
-       unsigned int n_elem;
-
-       /*
-        * Fill in command table information.  First, the header,
-        * a SATA Register - Host to Device command FIS.
-        */
-       cmd_tbl = pp->cmd_tbl + qc->tag * AHCI_CMD_TBL_SZ;
-
-       ata_tf_to_fis(&qc->tf, cmd_tbl, 0);
-       if (is_atapi) {
-               memset(cmd_tbl + AHCI_CMD_TBL_CDB, 0, 32);
-               memcpy(cmd_tbl + AHCI_CMD_TBL_CDB, qc->cdb, qc->dev->cdb_len);
-       }
-
-       n_elem = 0;
-       if (qc->flags & ATA_QCFLAG_DMAMAP)
-               n_elem = ahci_fill_sg(qc, cmd_tbl);
-
-       /*
-        * Fill in command slot information.
-        */
-       opts = cmd_fis_len | n_elem << 16;
-       if (qc->tf.flags & ATA_TFLAG_WRITE)
-               opts |= AHCI_CMD_WRITE;
-       if (is_atapi)
-               opts |= AHCI_CMD_ATAPI | AHCI_CMD_PREFETCH;
-
-       ahci_fill_cmd_slot(pp, qc->tag, opts);
-}
-
-static void ahci_error_intr(struct ata_port *ap, u32 irq_stat)
-{
-       struct ahci_port_priv *pp = ap->private_data;
-       struct ata_eh_info *ehi = &ap->eh_info;
-       unsigned int err_mask = 0, action = 0;
-       struct ata_queued_cmd *qc;
-       u32 serror;
-
-       ata_ehi_clear_desc(ehi);
-
-       /* AHCI needs SError cleared; otherwise, it might lock up */
-       serror = ahci_scr_read(ap, SCR_ERROR);
-       ahci_scr_write(ap, SCR_ERROR, serror);
-
-       /* analyze @irq_stat */
-       ata_ehi_push_desc(ehi, "irq_stat 0x%08x", irq_stat);
-
-       if (irq_stat & PORT_IRQ_TF_ERR)
-               err_mask |= AC_ERR_DEV;
-
-       if (irq_stat & (PORT_IRQ_HBUS_ERR | PORT_IRQ_HBUS_DATA_ERR)) {
-               err_mask |= AC_ERR_HOST_BUS;
-               action |= ATA_EH_SOFTRESET;
-       }
-
-       if (irq_stat & PORT_IRQ_IF_ERR) {
-               err_mask |= AC_ERR_ATA_BUS;
-               action |= ATA_EH_SOFTRESET;
-               ata_ehi_push_desc(ehi, ", interface fatal error");
-       }
-
-       if (irq_stat & (PORT_IRQ_CONNECT | PORT_IRQ_PHYRDY)) {
-               ata_ehi_hotplugged(ehi);
-               ata_ehi_push_desc(ehi, ", %s", irq_stat & PORT_IRQ_CONNECT ?
-                       "connection status changed" : "PHY RDY changed");
-       }
-
-       if (irq_stat & PORT_IRQ_UNK_FIS) {
-               u32 *unk = (u32 *)(pp->rx_fis + RX_FIS_UNK);
-
-               err_mask |= AC_ERR_HSM;
-               action |= ATA_EH_SOFTRESET;
-               ata_ehi_push_desc(ehi, ", unknown FIS %08x %08x %08x %08x",
-                                 unk[0], unk[1], unk[2], unk[3]);
-       }
-
-       /* okay, let's hand over to EH */
-       ehi->serror |= serror;
-       ehi->action |= action;
-
-       qc = ata_qc_from_tag(ap, ap->active_tag);
-       if (qc)
-               qc->err_mask |= err_mask;
-       else
-               ehi->err_mask |= err_mask;
-
-       if (irq_stat & PORT_IRQ_FREEZE)
-               ata_port_freeze(ap);
-       else
-               ata_port_abort(ap);
-}
-
-static void ahci_host_intr(struct ata_port *ap)
-{
-       void __iomem *mmio = ap->host_set->mmio_base;
-       void __iomem *port_mmio = ahci_port_base(mmio, ap->port_no);
-       struct ata_eh_info *ehi = &ap->eh_info;
-       u32 status, qc_active;
-       int rc;
-
-       status = readl(port_mmio + PORT_IRQ_STAT);
-       writel(status, port_mmio + PORT_IRQ_STAT);
-
-       if (unlikely(status & PORT_IRQ_ERROR)) {
-               ahci_error_intr(ap, status);
-               return;
-       }
-
-       if (ap->sactive)
-               qc_active = readl(port_mmio + PORT_SCR_ACT);
-       else
-               qc_active = readl(port_mmio + PORT_CMD_ISSUE);
-
-       rc = ata_qc_complete_multiple(ap, qc_active, NULL);
-       if (rc > 0)
-               return;
-       if (rc < 0) {
-               ehi->err_mask |= AC_ERR_HSM;
-               ehi->action |= ATA_EH_SOFTRESET;
-               ata_port_freeze(ap);
-               return;
-       }
-
-       /* hmmm... a spurious interupt */
-
-       /* some devices send D2H reg with I bit set during NCQ command phase */
-       if (ap->sactive && status & PORT_IRQ_D2H_REG_FIS)
-               return;
-
-       /* ignore interim PIO setup fis interrupts */
-       if (ata_tag_valid(ap->active_tag) && (status & PORT_IRQ_PIOS_FIS)) 
-               return;
-
-       if (ata_ratelimit())
-               ata_port_printk(ap, KERN_INFO, "spurious interrupt "
-                               "(irq_stat 0x%x active_tag %d sactive 0x%x)\n",
-                               status, ap->active_tag, ap->sactive);
-}
-
-static void ahci_irq_clear(struct ata_port *ap)
-{
-       /* TODO */
-}
-
-static irqreturn_t ahci_interrupt(int irq, void *dev_instance, struct pt_regs *regs)
-{
-       struct ata_host_set *host_set = dev_instance;
-       struct ahci_host_priv *hpriv;
-       unsigned int i, handled = 0;
-       void __iomem *mmio;
-       u32 irq_stat, irq_ack = 0;
-
-       VPRINTK("ENTER\n");
-
-       hpriv = host_set->private_data;
-       mmio = host_set->mmio_base;
-
-       /* sigh.  0xffffffff is a valid return from h/w */
-       irq_stat = readl(mmio + HOST_IRQ_STAT);
-       irq_stat &= hpriv->port_map;
-       if (!irq_stat)
-               return IRQ_NONE;
-
-        spin_lock(&host_set->lock);
-
-        for (i = 0; i < host_set->n_ports; i++) {
-               struct ata_port *ap;
-
-               if (!(irq_stat & (1 << i)))
-                       continue;
-
-               ap = host_set->ports[i];
-               if (ap) {
-                       ahci_host_intr(ap);
-                       VPRINTK("port %u\n", i);
-               } else {
-                       VPRINTK("port %u (no irq)\n", i);
-                       if (ata_ratelimit())
-                               dev_printk(KERN_WARNING, host_set->dev,
-                                       "interrupt on disabled port %u\n", i);
-               }
-
-               irq_ack |= (1 << i);
-       }
-
-       if (irq_ack) {
-               writel(irq_ack, mmio + HOST_IRQ_STAT);
-               handled = 1;
-       }
-
-       spin_unlock(&host_set->lock);
-
-       VPRINTK("EXIT\n");
-
-       return IRQ_RETVAL(handled);
-}
-
-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;
-
-       if (qc->tf.protocol == ATA_PROT_NCQ)
-               writel(1 << qc->tag, port_mmio + PORT_SCR_ACT);
-       writel(1 << qc->tag, port_mmio + PORT_CMD_ISSUE);
-       readl(port_mmio + PORT_CMD_ISSUE);      /* flush */
-
-       return 0;
-}
-
-static void ahci_freeze(struct ata_port *ap)
-{
-       void __iomem *mmio = ap->host_set->mmio_base;
-       void __iomem *port_mmio = ahci_port_base(mmio, ap->port_no);
-
-       /* turn IRQ off */
-       writel(0, port_mmio + PORT_IRQ_MASK);
-}
-
-static void ahci_thaw(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;
-
-       /* clear IRQ */
-       tmp = readl(port_mmio + PORT_IRQ_STAT);
-       writel(tmp, port_mmio + PORT_IRQ_STAT);
-       writel(1 << ap->id, mmio + HOST_IRQ_STAT);
-
-       /* turn IRQ back on */
-       writel(DEF_PORT_IRQ, port_mmio + PORT_IRQ_MASK);
-}
-
-static void ahci_error_handler(struct ata_port *ap)
-{
-       void __iomem *mmio = ap->host_set->mmio_base;
-       void __iomem *port_mmio = ahci_port_base(mmio, ap->port_no);
-
-       if (!(ap->pflags & ATA_PFLAG_FROZEN)) {
-               /* restart engine */
-               ahci_stop_engine(port_mmio);
-               ahci_start_engine(port_mmio);
-       }
-
-       /* perform recovery */
-       ata_do_eh(ap, ahci_prereset, ahci_softreset, ahci_hardreset,
-                 ahci_postreset);
-}
-
-static void ahci_post_internal_cmd(struct ata_queued_cmd *qc)
-{
-       struct ata_port *ap = qc->ap;
-       void __iomem *mmio = ap->host_set->mmio_base;
-       void __iomem *port_mmio = ahci_port_base(mmio, ap->port_no);
-
-       if (qc->flags & ATA_QCFLAG_FAILED)
-               qc->err_mask |= AC_ERR_OTHER;
-
-       if (qc->err_mask) {
-               /* make DMA engine forget about the failed command */
-               ahci_stop_engine(port_mmio);
-               ahci_start_engine(port_mmio);
-       }
-}
-
-static int ahci_port_suspend(struct ata_port *ap, pm_message_t mesg)
-{
-       struct ahci_host_priv *hpriv = ap->host_set->private_data;
-       struct ahci_port_priv *pp = ap->private_data;
-       void __iomem *mmio = ap->host_set->mmio_base;
-       void __iomem *port_mmio = ahci_port_base(mmio, ap->port_no);
-       const char *emsg = NULL;
-       int rc;
-
-       rc = ahci_deinit_port(port_mmio, hpriv->cap, &emsg);
-       if (rc) {
-               ata_port_printk(ap, KERN_ERR, "%s (%d)\n", emsg, rc);
-               ahci_init_port(port_mmio, hpriv->cap,
-                              pp->cmd_slot_dma, pp->rx_fis_dma);
-       }
-
-       return rc;
-}
-
-static int ahci_port_resume(struct ata_port *ap)
-{
-       struct ahci_port_priv *pp = ap->private_data;
-       struct ahci_host_priv *hpriv = ap->host_set->private_data;
-       void __iomem *mmio = ap->host_set->mmio_base;
-       void __iomem *port_mmio = ahci_port_base(mmio, ap->port_no);
-
-       ahci_init_port(port_mmio, hpriv->cap, pp->cmd_slot_dma, pp->rx_fis_dma);
-
-       return 0;
-}
-
-static int ahci_pci_device_suspend(struct pci_dev *pdev, pm_message_t mesg)
-{
-       struct ata_host_set *host_set = dev_get_drvdata(&pdev->dev);
-       void __iomem *mmio = host_set->mmio_base;
-       u32 ctl;
-
-       if (mesg.event == PM_EVENT_SUSPEND) {
-               /* AHCI spec rev1.1 section 8.3.3:
-                * Software must disable interrupts prior to requesting a
-                * transition of the HBA to D3 state.
-                */
-               ctl = readl(mmio + HOST_CTL);
-               ctl &= ~HOST_IRQ_EN;
-               writel(ctl, mmio + HOST_CTL);
-               readl(mmio + HOST_CTL); /* flush */
-       }
-
-       return ata_pci_device_suspend(pdev, mesg);
-}
-
-static int ahci_pci_device_resume(struct pci_dev *pdev)
-{
-       struct ata_host_set *host_set = dev_get_drvdata(&pdev->dev);
-       struct ahci_host_priv *hpriv = host_set->private_data;
-       void __iomem *mmio = host_set->mmio_base;
-       int rc;
-
-       ata_pci_device_do_resume(pdev);
-
-       if (pdev->dev.power.power_state.event == PM_EVENT_SUSPEND) {
-               rc = ahci_reset_controller(mmio, pdev);
-               if (rc)
-                       return rc;
-
-               ahci_init_controller(mmio, pdev, host_set->n_ports, hpriv->cap);
-       }
-
-       ata_host_set_resume(host_set);
-
-       return 0;
-}
-
-static int ahci_port_start(struct ata_port *ap)
-{
-       struct device *dev = ap->host_set->dev;
-       struct ahci_host_priv *hpriv = ap->host_set->private_data;
-       struct ahci_port_priv *pp;
-       void __iomem *mmio = ap->host_set->mmio_base;
-       void __iomem *port_mmio = ahci_port_base(mmio, ap->port_no);
-       void *mem;
-       dma_addr_t mem_dma;
-       int rc;
-
-       pp = kmalloc(sizeof(*pp), GFP_KERNEL);
-       if (!pp)
-               return -ENOMEM;
-       memset(pp, 0, sizeof(*pp));
-
-       rc = ata_pad_alloc(ap, dev);
-       if (rc) {
-               kfree(pp);
-               return rc;
-       }
-
-       mem = dma_alloc_coherent(dev, AHCI_PORT_PRIV_DMA_SZ, &mem_dma, GFP_KERNEL);
-       if (!mem) {
-               ata_pad_free(ap, dev);
-               kfree(pp);
-               return -ENOMEM;
-       }
-       memset(mem, 0, AHCI_PORT_PRIV_DMA_SZ);
-
-       /*
-        * First item in chunk of DMA memory: 32-slot command table,
-        * 32 bytes each in size
-        */
-       pp->cmd_slot = mem;
-       pp->cmd_slot_dma = mem_dma;
-
-       mem += AHCI_CMD_SLOT_SZ;
-       mem_dma += AHCI_CMD_SLOT_SZ;
-
-       /*
-        * Second item: Received-FIS area
-        */
-       pp->rx_fis = mem;
-       pp->rx_fis_dma = mem_dma;
-
-       mem += AHCI_RX_FIS_SZ;
-       mem_dma += AHCI_RX_FIS_SZ;
-
-       /*
-        * Third item: data area for storing a single command
-        * and its scatter-gather table
-        */
-       pp->cmd_tbl = mem;
-       pp->cmd_tbl_dma = mem_dma;
-
-       ap->private_data = pp;
-
-       /* initialize port */
-       ahci_init_port(port_mmio, hpriv->cap, pp->cmd_slot_dma, pp->rx_fis_dma);
-
-       return 0;
-}
-
-static void ahci_port_stop(struct ata_port *ap)
-{
-       struct device *dev = ap->host_set->dev;
-       struct ahci_host_priv *hpriv = ap->host_set->private_data;
-       struct ahci_port_priv *pp = ap->private_data;
-       void __iomem *mmio = ap->host_set->mmio_base;
-       void __iomem *port_mmio = ahci_port_base(mmio, ap->port_no);
-       const char *emsg = NULL;
-       int rc;
-
-       /* de-initialize port */
-       rc = ahci_deinit_port(port_mmio, hpriv->cap, &emsg);
-       if (rc)
-               ata_port_printk(ap, KERN_WARNING, "%s (%d)\n", emsg, rc);
-
-       ap->private_data = NULL;
-       dma_free_coherent(dev, AHCI_PORT_PRIV_DMA_SZ,
-                         pp->cmd_slot, pp->cmd_slot_dma);
-       ata_pad_free(ap, dev);
-       kfree(pp);
-}
-
-static void ahci_setup_port(struct ata_ioports *port, unsigned long base,
-                           unsigned int port_idx)
-{
-       VPRINTK("ENTER, base==0x%lx, port_idx %u\n", base, port_idx);
-       base = ahci_port_base_ul(base, port_idx);
-       VPRINTK("base now==0x%lx\n", base);
-
-       port->cmd_addr          = base;
-       port->scr_addr          = base + PORT_SCR;
-
-       VPRINTK("EXIT\n");
-}
-
-static int ahci_host_init(struct ata_probe_ent *probe_ent)
-{
-       struct ahci_host_priv *hpriv = probe_ent->private_data;
-       struct pci_dev *pdev = to_pci_dev(probe_ent->dev);
-       void __iomem *mmio = probe_ent->mmio_base;
-       unsigned int i, using_dac;
-       int rc;
-
-       rc = ahci_reset_controller(mmio, pdev);
-       if (rc)
-               return rc;
-
-       hpriv->cap = readl(mmio + HOST_CAP);
-       hpriv->port_map = readl(mmio + HOST_PORTS_IMPL);
-       probe_ent->n_ports = (hpriv->cap & 0x1f) + 1;
-
-       VPRINTK("cap 0x%x  port_map 0x%x  n_ports %d\n",
-               hpriv->cap, hpriv->port_map, probe_ent->n_ports);
-
-       using_dac = hpriv->cap & HOST_CAP_64;
-       if (using_dac &&
-           !pci_set_dma_mask(pdev, DMA_64BIT_MASK)) {
-               rc = pci_set_consistent_dma_mask(pdev, DMA_64BIT_MASK);
-               if (rc) {
-                       rc = pci_set_consistent_dma_mask(pdev, DMA_32BIT_MASK);
-                       if (rc) {
-                               dev_printk(KERN_ERR, &pdev->dev,
-                                          "64-bit DMA enable failed\n");
-                               return rc;
-                       }
-               }
-       } else {
-               rc = pci_set_dma_mask(pdev, DMA_32BIT_MASK);
-               if (rc) {
-                       dev_printk(KERN_ERR, &pdev->dev,
-                                  "32-bit DMA enable failed\n");
-                       return rc;
-               }
-               rc = pci_set_consistent_dma_mask(pdev, DMA_32BIT_MASK);
-               if (rc) {
-                       dev_printk(KERN_ERR, &pdev->dev,
-                                  "32-bit consistent DMA enable failed\n");
-                       return rc;
-               }
-       }
-
-       for (i = 0; i < probe_ent->n_ports; i++)
-               ahci_setup_port(&probe_ent->port[i], (unsigned long) mmio, i);
-
-       ahci_init_controller(mmio, pdev, probe_ent->n_ports, hpriv->cap);
-
-       pci_set_master(pdev);
-
-       return 0;
-}
-
-static void ahci_print_info(struct ata_probe_ent *probe_ent)
-{
-       struct ahci_host_priv *hpriv = probe_ent->private_data;
-       struct pci_dev *pdev = to_pci_dev(probe_ent->dev);
-       void __iomem *mmio = probe_ent->mmio_base;
-       u32 vers, cap, impl, speed;
-       const char *speed_s;
-       u16 cc;
-       const char *scc_s;
-
-       vers = readl(mmio + HOST_VERSION);
-       cap = hpriv->cap;
-       impl = hpriv->port_map;
-
-       speed = (cap >> 20) & 0xf;
-       if (speed == 1)
-               speed_s = "1.5";
-       else if (speed == 2)
-               speed_s = "3";
-       else
-               speed_s = "?";
-
-       pci_read_config_word(pdev, 0x0a, &cc);
-       if (cc == 0x0101)
-               scc_s = "IDE";
-       else if (cc == 0x0106)
-               scc_s = "SATA";
-       else if (cc == 0x0104)
-               scc_s = "RAID";
-       else
-               scc_s = "unknown";
-
-       dev_printk(KERN_INFO, &pdev->dev,
-               "AHCI %02x%02x.%02x%02x "
-               "%u slots %u ports %s Gbps 0x%x impl %s mode\n"
-               ,
-
-               (vers >> 24) & 0xff,
-               (vers >> 16) & 0xff,
-               (vers >> 8) & 0xff,
-               vers & 0xff,
-
-               ((cap >> 8) & 0x1f) + 1,
-               (cap & 0x1f) + 1,
-               speed_s,
-               impl,
-               scc_s);
-
-       dev_printk(KERN_INFO, &pdev->dev,
-               "flags: "
-               "%s%s%s%s%s%s"
-               "%s%s%s%s%s%s%s\n"
-               ,
-
-               cap & (1 << 31) ? "64bit " : "",
-               cap & (1 << 30) ? "ncq " : "",
-               cap & (1 << 28) ? "ilck " : "",
-               cap & (1 << 27) ? "stag " : "",
-               cap & (1 << 26) ? "pm " : "",
-               cap & (1 << 25) ? "led " : "",
-
-               cap & (1 << 24) ? "clo " : "",
-               cap & (1 << 19) ? "nz " : "",
-               cap & (1 << 18) ? "only " : "",
-               cap & (1 << 17) ? "pmp " : "",
-               cap & (1 << 15) ? "pio " : "",
-               cap & (1 << 14) ? "slum " : "",
-               cap & (1 << 13) ? "part " : ""
-               );
-}
-
-static int ahci_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
-{
-       static int printed_version;
-       struct ata_probe_ent *probe_ent = NULL;
-       struct ahci_host_priv *hpriv;
-       unsigned long base;
-       void __iomem *mmio_base;
-       unsigned int board_idx = (unsigned int) ent->driver_data;
-       int have_msi, pci_dev_busy = 0;
-       int rc;
-
-       VPRINTK("ENTER\n");
-
-       WARN_ON(ATA_MAX_QUEUE > AHCI_MAX_CMDS);
-
-       if (!printed_version++)
-               dev_printk(KERN_DEBUG, &pdev->dev, "version " DRV_VERSION "\n");
-
-       /* JMicron-specific fixup: make sure we're in AHCI mode */
-       /* This is protected from races with ata_jmicron by the pci probe
-          locking */
-       if (pdev->vendor == PCI_VENDOR_ID_JMICRON) {
-               /* AHCI enable, AHCI on function 0 */
-               pci_write_config_byte(pdev, 0x41, 0xa1);
-               /* Function 1 is the PATA controller */
-               if (PCI_FUNC(pdev->devfn))
-                       return -ENODEV;
-       }
-
-       rc = pci_enable_device(pdev);
-       if (rc)
-               return rc;
-
-       rc = pci_request_regions(pdev, DRV_NAME);
-       if (rc) {
-               pci_dev_busy = 1;
-               goto err_out;
-       }
-
-       if (pci_enable_msi(pdev) == 0)
-               have_msi = 1;
-       else {
-               pci_intx(pdev, 1);
-               have_msi = 0;
-       }
-
-       probe_ent = kmalloc(sizeof(*probe_ent), GFP_KERNEL);
-       if (probe_ent == NULL) {
-               rc = -ENOMEM;
-               goto err_out_msi;
-       }
-
-       memset(probe_ent, 0, sizeof(*probe_ent));
-       probe_ent->dev = pci_dev_to_dev(pdev);
-       INIT_LIST_HEAD(&probe_ent->node);
-
-       mmio_base = pci_iomap(pdev, AHCI_PCI_BAR, 0);
-       if (mmio_base == NULL) {
-               rc = -ENOMEM;
-               goto err_out_free_ent;
-       }
-       base = (unsigned long) mmio_base;
-
-       hpriv = kmalloc(sizeof(*hpriv), GFP_KERNEL);
-       if (!hpriv) {
-               rc = -ENOMEM;
-               goto err_out_iounmap;
-       }
-       memset(hpriv, 0, sizeof(*hpriv));
-
-       probe_ent->sht          = ahci_port_info[board_idx].sht;
-       probe_ent->host_flags   = ahci_port_info[board_idx].host_flags;
-       probe_ent->pio_mask     = ahci_port_info[board_idx].pio_mask;
-       probe_ent->udma_mask    = ahci_port_info[board_idx].udma_mask;
-       probe_ent->port_ops     = ahci_port_info[board_idx].port_ops;
-
-               probe_ent->irq = pdev->irq;
-               probe_ent->irq_flags = IRQF_SHARED;
-       probe_ent->mmio_base = mmio_base;
-       probe_ent->private_data = hpriv;
-
-       if (have_msi)
-               hpriv->flags |= AHCI_FLAG_MSI;
-
-       /* initialize adapter */
-       rc = ahci_host_init(probe_ent);
-       if (rc)
-               goto err_out_hpriv;
-
-       if (!(probe_ent->host_flags & AHCI_FLAG_NO_NCQ) &&
-           (hpriv->cap & HOST_CAP_NCQ))
-               probe_ent->host_flags |= ATA_FLAG_NCQ;
-
-       ahci_print_info(probe_ent);
-
-       /* FIXME: check ata_device_add return value */
-       ata_device_add(probe_ent);
-       kfree(probe_ent);
-
-       return 0;
-
-err_out_hpriv:
-       kfree(hpriv);
-err_out_iounmap:
-       pci_iounmap(pdev, mmio_base);
-err_out_free_ent:
-       kfree(probe_ent);
-err_out_msi:
-       if (have_msi)
-               pci_disable_msi(pdev);
-       else
-               pci_intx(pdev, 0);
-       pci_release_regions(pdev);
-err_out:
-       if (!pci_dev_busy)
-               pci_disable_device(pdev);
-       return rc;
-}
-
-static void ahci_remove_one (struct pci_dev *pdev)
-{
-       struct device *dev = pci_dev_to_dev(pdev);
-       struct ata_host_set *host_set = dev_get_drvdata(dev);
-       struct ahci_host_priv *hpriv = host_set->private_data;
-       unsigned int i;
-       int have_msi;
-
-       for (i = 0; i < host_set->n_ports; i++)
-               ata_port_detach(host_set->ports[i]);
-
-       have_msi = hpriv->flags & AHCI_FLAG_MSI;
-       free_irq(host_set->irq, host_set);
-
-       for (i = 0; i < host_set->n_ports; i++) {
-               struct ata_port *ap = host_set->ports[i];
-
-               ata_scsi_release(ap->host);
-               scsi_host_put(ap->host);
-       }
-
-       kfree(hpriv);
-       pci_iounmap(pdev, host_set->mmio_base);
-       kfree(host_set);
-
-       if (have_msi)
-               pci_disable_msi(pdev);
-       else
-               pci_intx(pdev, 0);
-       pci_release_regions(pdev);
-       pci_disable_device(pdev);
-       dev_set_drvdata(dev, NULL);
-}
-
-static int __init ahci_init(void)
-{
-       return pci_register_driver(&ahci_pci_driver);
-}
-
-static void __exit ahci_exit(void)
-{
-       pci_unregister_driver(&ahci_pci_driver);
-}
-
-
-MODULE_AUTHOR("Jeff Garzik");
-MODULE_DESCRIPTION("AHCI SATA low-level driver");
-MODULE_LICENSE("GPL");
-MODULE_DEVICE_TABLE(pci, ahci_pci_tbl);
-MODULE_VERSION(DRV_VERSION);
-
-module_init(ahci_init);
-module_exit(ahci_exit);
diff --git a/drivers/scsi/ata_piix.c b/drivers/scsi/ata_piix.c
deleted file mode 100644 (file)
index 46c34fd..0000000
+++ /dev/null
@@ -1,960 +0,0 @@
-/*
- *    ata_piix.c - Intel PATA/SATA controllers
- *
- *    Maintained by:  Jeff Garzik <jgarzik@pobox.com>
- *                 Please ALWAYS copy linux-ide@vger.kernel.org
- *                 on emails.
- *
- *
- *     Copyright 2003-2005 Red Hat Inc
- *     Copyright 2003-2005 Jeff Garzik
- *
- *
- *     Copyright header from piix.c:
- *
- *  Copyright (C) 1998-1999 Andrzej Krzysztofowicz, Author and Maintainer
- *  Copyright (C) 1998-2000 Andre Hedrick <andre@linux-ide.org>
- *  Copyright (C) 2003 Red Hat Inc <alan@redhat.com>
- *
- *
- *  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 at http://developer.intel.com/
- *
- * Documentation
- *     Publically available from Intel web site. Errata documentation
- * is also publically available. As an aide to anyone hacking on this
- * driver the list of errata that are relevant is below.going back to
- * PIIX4. Older device documentation is now a bit tricky to find.
- *
- * The chipsets all follow very much the same design. The orginal Triton
- * series chipsets do _not_ support independant device timings, but this
- * is fixed in Triton II. With the odd mobile exception the chips then
- * change little except in gaining more modes until SATA arrives. This
- * driver supports only the chips with independant timing (that is those
- * with SITRE and the 0x44 timing register). See pata_oldpiix and pata_mpiix
- * for the early chip drivers.
- *
- * Errata of note:
- *
- * Unfixable
- *     PIIX4    errata #9      - Only on ultra obscure hw
- *     ICH3     errata #13     - Not observed to affect real hw
- *                               by Intel
- *
- * Things we must deal with
- *     PIIX4   errata #10      - BM IDE hang with non UDMA
- *                               (must stop/start dma to recover)
- *     440MX   errata #15      - As PIIX4 errata #10
- *     PIIX4   errata #15      - Must not read control registers
- *                               during a PIO transfer
- *     440MX   errata #13      - As PIIX4 errata #15
- *     ICH2    errata #21      - DMA mode 0 doesn't work right
- *     ICH0/1  errata #55      - As ICH2 errata #21
- *     ICH2    spec c #9       - Extra operations needed to handle
- *                               drive hotswap [NOT YET SUPPORTED]
- *     ICH2    spec c #20      - IDE PRD must not cross a 64K boundary
- *                               and must be dword aligned
- *     ICH2    spec c #24      - UDMA mode 4,5 t85/86 should be 6ns not 3.3
- *
- * Should have been BIOS fixed:
- *     450NX:  errata #19      - DMA hangs on old 450NX
- *     450NX:  errata #20      - DMA hangs on old 450NX
- *     450NX:  errata #25      - Corruption with DMA on old 450NX
- *     ICH3    errata #15      - IDE deadlock under high load
- *                               (BIOS must set dev 31 fn 0 bit 23)
- *     ICH3    errata #18      - Don't use native mode
- */
-
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/pci.h>
-#include <linux/init.h>
-#include <linux/blkdev.h>
-#include <linux/delay.h>
-#include <linux/device.h>
-#include <scsi/scsi_host.h>
-#include <linux/libata.h>
-
-#define DRV_NAME       "ata_piix"
-#define DRV_VERSION    "2.00"
-
-enum {
-       PIIX_IOCFG              = 0x54, /* IDE I/O configuration register */
-       ICH5_PMR                = 0x90, /* port mapping register */
-       ICH5_PCS                = 0x92, /* port control and status */
-       PIIX_SCC                = 0x0A, /* sub-class code register */
-
-       PIIX_FLAG_IGNORE_PCS    = (1 << 25), /* ignore PCS present bits */
-       PIIX_FLAG_SCR           = (1 << 26), /* SCR available */
-       PIIX_FLAG_AHCI          = (1 << 27), /* AHCI possible */
-       PIIX_FLAG_CHECKINTR     = (1 << 28), /* make sure PCI INTx enabled */
-
-       /* combined mode.  if set, PATA is channel 0.
-        * if clear, PATA is channel 1.
-        */
-       PIIX_PORT_ENABLED       = (1 << 0),
-       PIIX_PORT_PRESENT       = (1 << 4),
-
-       PIIX_80C_PRI            = (1 << 5) | (1 << 4),
-       PIIX_80C_SEC            = (1 << 7) | (1 << 6),
-
-       /* controller IDs */
-       piix4_pata              = 0,
-       ich5_pata               = 1,
-       ich5_sata               = 2,
-       esb_sata                = 3,
-       ich6_sata               = 4,
-       ich6_sata_ahci          = 5,
-       ich6m_sata_ahci         = 6,
-       ich8_sata_ahci          = 7,
-
-       /* constants for mapping table */
-       P0                      = 0,  /* port 0 */
-       P1                      = 1,  /* port 1 */
-       P2                      = 2,  /* port 2 */
-       P3                      = 3,  /* port 3 */
-       IDE                     = -1, /* IDE */
-       NA                      = -2, /* not avaliable */
-       RV                      = -3, /* reserved */
-
-       PIIX_AHCI_DEVICE        = 6,
-};
-
-struct piix_map_db {
-       const u32 mask;
-       const u16 port_enable;
-       const int present_shift;
-       const int map[][4];
-};
-
-struct piix_host_priv {
-       const int *map;
-       const struct piix_map_db *map_db;
-};
-
-static int piix_init_one (struct pci_dev *pdev,
-                                   const struct pci_device_id *ent);
-static void piix_host_stop(struct ata_host_set *host_set);
-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);
-static void piix_pata_error_handler(struct ata_port *ap);
-static void piix_sata_error_handler(struct ata_port *ap);
-
-static unsigned int in_module_init = 1;
-
-static const struct pci_device_id piix_pci_tbl[] = {
-#ifdef ATA_ENABLE_PATA
-       { 0x8086, 0x7111, PCI_ANY_ID, PCI_ANY_ID, 0, 0, piix4_pata },
-       { 0x8086, 0x24db, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich5_pata },
-       { 0x8086, 0x25a2, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich5_pata },
-       { 0x8086, 0x27df, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich5_pata },
-#endif
-
-       /* NOTE: The following PCI ids must be kept in sync with the
-        * list in drivers/pci/quirks.c.
-        */
-
-       /* 82801EB (ICH5) */
-       { 0x8086, 0x24d1, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich5_sata },
-       /* 82801EB (ICH5) */
-       { 0x8086, 0x24df, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich5_sata },
-       /* 6300ESB (ICH5 variant with broken PCS present bits) */
-       { 0x8086, 0x25a3, PCI_ANY_ID, PCI_ANY_ID, 0, 0, esb_sata },
-       /* 6300ESB pretending RAID */
-       { 0x8086, 0x25b0, PCI_ANY_ID, PCI_ANY_ID, 0, 0, esb_sata },
-       /* 82801FB/FW (ICH6/ICH6W) */
-       { 0x8086, 0x2651, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich6_sata },
-       /* 82801FR/FRW (ICH6R/ICH6RW) */
-       { 0x8086, 0x2652, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich6_sata_ahci },
-       /* 82801FBM ICH6M (ICH6R with only port 0 and 2 implemented) */
-       { 0x8086, 0x2653, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich6m_sata_ahci },
-       /* 82801GB/GR/GH (ICH7, identical to ICH6) */
-       { 0x8086, 0x27c0, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich6_sata_ahci },
-       /* 2801GBM/GHM (ICH7M, identical to ICH6M) */
-       { 0x8086, 0x27c4, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich6m_sata_ahci },
-       /* Enterprise Southbridge 2 (where's the datasheet?) */
-       { 0x8086, 0x2680, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich6_sata_ahci },
-       /* SATA Controller 1 IDE (ICH8, no datasheet yet) */
-       { 0x8086, 0x2820, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_sata_ahci },
-       /* SATA Controller 2 IDE (ICH8, ditto) */
-       { 0x8086, 0x2825, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_sata_ahci },
-       /* Mobile SATA Controller IDE (ICH8M, ditto) */
-       { 0x8086, 0x2828, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_sata_ahci },
-
-       { }     /* terminate list */
-};
-
-static struct pci_driver piix_pci_driver = {
-       .name                   = DRV_NAME,
-       .id_table               = piix_pci_tbl,
-       .probe                  = piix_init_one,
-       .remove                 = ata_pci_remove_one,
-       .suspend                = ata_pci_device_suspend,
-       .resume                 = ata_pci_device_resume,
-};
-
-static struct scsi_host_template piix_sht = {
-       .module                 = THIS_MODULE,
-       .name                   = DRV_NAME,
-       .ioctl                  = ata_scsi_ioctl,
-       .queuecommand           = ata_scsi_queuecmd,
-       .can_queue              = ATA_DEF_QUEUE,
-       .this_id                = ATA_SHT_THIS_ID,
-       .sg_tablesize           = LIBATA_MAX_PRD,
-       .cmd_per_lun            = ATA_SHT_CMD_PER_LUN,
-       .emulated               = ATA_SHT_EMULATED,
-       .use_clustering         = ATA_SHT_USE_CLUSTERING,
-       .proc_name              = DRV_NAME,
-       .dma_boundary           = ATA_DMA_BOUNDARY,
-       .slave_configure        = ata_scsi_slave_config,
-       .slave_destroy          = ata_scsi_slave_destroy,
-       .bios_param             = ata_std_bios_param,
-       .resume                 = ata_scsi_device_resume,
-       .suspend                = ata_scsi_device_suspend,
-};
-
-static const struct ata_port_operations piix_pata_ops = {
-       .port_disable           = ata_port_disable,
-       .set_piomode            = piix_set_piomode,
-       .set_dmamode            = piix_set_dmamode,
-       .mode_filter            = ata_pci_default_filter,
-
-       .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,
-
-       .bmdma_setup            = ata_bmdma_setup,
-       .bmdma_start            = ata_bmdma_start,
-       .bmdma_stop             = ata_bmdma_stop,
-       .bmdma_status           = ata_bmdma_status,
-       .qc_prep                = ata_qc_prep,
-       .qc_issue               = ata_qc_issue_prot,
-       .data_xfer              = ata_pio_data_xfer,
-
-       .freeze                 = ata_bmdma_freeze,
-       .thaw                   = ata_bmdma_thaw,
-       .error_handler          = piix_pata_error_handler,
-       .post_internal_cmd      = ata_bmdma_post_internal_cmd,
-
-       .irq_handler            = ata_interrupt,
-       .irq_clear              = ata_bmdma_irq_clear,
-
-       .port_start             = ata_port_start,
-       .port_stop              = ata_port_stop,
-       .host_stop              = piix_host_stop,
-};
-
-static const struct ata_port_operations piix_sata_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,
-
-       .bmdma_setup            = ata_bmdma_setup,
-       .bmdma_start            = ata_bmdma_start,
-       .bmdma_stop             = ata_bmdma_stop,
-       .bmdma_status           = ata_bmdma_status,
-       .qc_prep                = ata_qc_prep,
-       .qc_issue               = ata_qc_issue_prot,
-       .data_xfer              = ata_pio_data_xfer,
-
-       .freeze                 = ata_bmdma_freeze,
-       .thaw                   = ata_bmdma_thaw,
-       .error_handler          = piix_sata_error_handler,
-       .post_internal_cmd      = ata_bmdma_post_internal_cmd,
-
-       .irq_handler            = ata_interrupt,
-       .irq_clear              = ata_bmdma_irq_clear,
-
-       .port_start             = ata_port_start,
-       .port_stop              = ata_port_stop,
-       .host_stop              = piix_host_stop,
-};
-
-static const struct piix_map_db ich5_map_db = {
-       .mask = 0x7,
-       .port_enable = 0x3,
-       .present_shift = 4,
-       .map = {
-               /* PM   PS   SM   SS       MAP  */
-               {  P0,  NA,  P1,  NA }, /* 000b */
-               {  P1,  NA,  P0,  NA }, /* 001b */
-               {  RV,  RV,  RV,  RV },
-               {  RV,  RV,  RV,  RV },
-               {  P0,  P1, IDE, IDE }, /* 100b */
-               {  P1,  P0, IDE, IDE }, /* 101b */
-               { IDE, IDE,  P0,  P1 }, /* 110b */
-               { IDE, IDE,  P1,  P0 }, /* 111b */
-       },
-};
-
-static const struct piix_map_db ich6_map_db = {
-       .mask = 0x3,
-       .port_enable = 0xf,
-       .present_shift = 4,
-       .map = {
-               /* PM   PS   SM   SS       MAP */
-               {  P0,  P2,  P1,  P3 }, /* 00b */
-               { IDE, IDE,  P1,  P3 }, /* 01b */
-               {  P0,  P2, IDE, IDE }, /* 10b */
-               {  RV,  RV,  RV,  RV },
-       },
-};
-
-static const struct piix_map_db ich6m_map_db = {
-       .mask = 0x3,
-       .port_enable = 0x5,
-       .present_shift = 4,
-       .map = {
-               /* PM   PS   SM   SS       MAP */
-               {  P0,  P2,  RV,  RV }, /* 00b */
-               {  RV,  RV,  RV,  RV },
-               {  P0,  P2, IDE, IDE }, /* 10b */
-               {  RV,  RV,  RV,  RV },
-       },
-};
-
-static const struct piix_map_db ich8_map_db = {
-       .mask = 0x3,
-       .port_enable = 0x3,
-       .present_shift = 8,
-       .map = {
-               /* PM   PS   SM   SS       MAP */
-               {  P0,  NA,  P1,  NA }, /* 00b (hardwired) */
-               {  RV,  RV,  RV,  RV },
-               {  RV,  RV,  RV,  RV }, /* 10b (never) */
-               {  RV,  RV,  RV,  RV },
-       },
-};
-
-static const struct piix_map_db *piix_map_db_table[] = {
-       [ich5_sata]             = &ich5_map_db,
-       [esb_sata]              = &ich5_map_db,
-       [ich6_sata]             = &ich6_map_db,
-       [ich6_sata_ahci]        = &ich6_map_db,
-       [ich6m_sata_ahci]       = &ich6m_map_db,
-       [ich8_sata_ahci]        = &ich8_map_db,
-};
-
-static struct ata_port_info piix_port_info[] = {
-       /* piix4_pata */
-       {
-               .sht            = &piix_sht,
-               .host_flags     = ATA_FLAG_SLAVE_POSS,
-               .pio_mask       = 0x1f, /* pio0-4 */
-#if 0
-               .mwdma_mask     = 0x06, /* mwdma1-2 */
-#else
-               .mwdma_mask     = 0x00, /* mwdma broken */
-#endif
-               .udma_mask      = ATA_UDMA_MASK_40C,
-               .port_ops       = &piix_pata_ops,
-       },
-
-       /* ich5_pata */
-       {
-               .sht            = &piix_sht,
-               .host_flags     = ATA_FLAG_SLAVE_POSS | PIIX_FLAG_CHECKINTR,
-               .pio_mask       = 0x1f, /* pio0-4 */
-#if 0
-               .mwdma_mask     = 0x06, /* mwdma1-2 */
-#else
-               .mwdma_mask     = 0x00, /* mwdma broken */
-#endif
-               .udma_mask      = 0x3f, /* udma0-5 */
-               .port_ops       = &piix_pata_ops,
-       },
-
-       /* ich5_sata */
-       {
-               .sht            = &piix_sht,
-               .host_flags     = ATA_FLAG_SATA | PIIX_FLAG_CHECKINTR,
-               .pio_mask       = 0x1f, /* pio0-4 */
-               .mwdma_mask     = 0x07, /* mwdma0-2 */
-               .udma_mask      = 0x7f, /* udma0-6 */
-               .port_ops       = &piix_sata_ops,
-       },
-
-       /* i6300esb_sata */
-       {
-               .sht            = &piix_sht,
-               .host_flags     = ATA_FLAG_SATA |
-                                 PIIX_FLAG_CHECKINTR | PIIX_FLAG_IGNORE_PCS,
-               .pio_mask       = 0x1f, /* pio0-4 */
-               .mwdma_mask     = 0x07, /* mwdma0-2 */
-               .udma_mask      = 0x7f, /* udma0-6 */
-               .port_ops       = &piix_sata_ops,
-       },
-
-       /* ich6_sata */
-       {
-               .sht            = &piix_sht,
-               .host_flags     = ATA_FLAG_SATA |
-                                 PIIX_FLAG_CHECKINTR | PIIX_FLAG_SCR,
-               .pio_mask       = 0x1f, /* pio0-4 */
-               .mwdma_mask     = 0x07, /* mwdma0-2 */
-               .udma_mask      = 0x7f, /* udma0-6 */
-               .port_ops       = &piix_sata_ops,
-       },
-
-       /* ich6_sata_ahci */
-       {
-               .sht            = &piix_sht,
-               .host_flags     = ATA_FLAG_SATA |
-                                 PIIX_FLAG_CHECKINTR | PIIX_FLAG_SCR |
-                                 PIIX_FLAG_AHCI,
-               .pio_mask       = 0x1f, /* pio0-4 */
-               .mwdma_mask     = 0x07, /* mwdma0-2 */
-               .udma_mask      = 0x7f, /* udma0-6 */
-               .port_ops       = &piix_sata_ops,
-       },
-
-       /* ich6m_sata_ahci */
-       {
-               .sht            = &piix_sht,
-               .host_flags     = ATA_FLAG_SATA |
-                                 PIIX_FLAG_CHECKINTR | PIIX_FLAG_SCR |
-                                 PIIX_FLAG_AHCI,
-               .pio_mask       = 0x1f, /* pio0-4 */
-               .mwdma_mask     = 0x07, /* mwdma0-2 */
-               .udma_mask      = 0x7f, /* udma0-6 */
-               .port_ops       = &piix_sata_ops,
-       },
-
-       /* ich8_sata_ahci */
-       {
-               .sht            = &piix_sht,
-               .host_flags     = ATA_FLAG_SATA |
-                                 PIIX_FLAG_CHECKINTR | PIIX_FLAG_SCR |
-                                 PIIX_FLAG_AHCI,
-               .pio_mask       = 0x1f, /* pio0-4 */
-               .mwdma_mask     = 0x07, /* mwdma0-2 */
-               .udma_mask      = 0x7f, /* udma0-6 */
-               .port_ops       = &piix_sata_ops,
-       },
-};
-
-static struct pci_bits piix_enable_bits[] = {
-       { 0x41U, 1U, 0x80UL, 0x80UL },  /* port 0 */
-       { 0x43U, 1U, 0x80UL, 0x80UL },  /* port 1 */
-};
-
-MODULE_AUTHOR("Andre Hedrick, Alan Cox, Andrzej Krzysztofowicz, Jeff Garzik");
-MODULE_DESCRIPTION("SCSI low-level driver for Intel PIIX/ICH ATA controllers");
-MODULE_LICENSE("GPL");
-MODULE_DEVICE_TABLE(pci, piix_pci_tbl);
-MODULE_VERSION(DRV_VERSION);
-
-/**
- *     piix_pata_cbl_detect - Probe host controller cable detect info
- *     @ap: Port for which cable detect info is desired
- *
- *     Read 80c cable indicator from ATA PCI device's PCI config
- *     register.  This register is normally set by firmware (BIOS).
- *
- *     LOCKING:
- *     None (inherited from caller).
- */
-static void piix_pata_cbl_detect(struct ata_port *ap)
-{
-       struct pci_dev *pdev = to_pci_dev(ap->host_set->dev);
-       u8 tmp, mask;
-
-       /* no 80c support in host controller? */
-       if ((ap->udma_mask & ~ATA_UDMA_MASK_40C) == 0)
-               goto cbl40;
-
-       /* check BIOS cable detect results */
-       mask = ap->port_no == 0 ? PIIX_80C_PRI : PIIX_80C_SEC;
-       pci_read_config_byte(pdev, PIIX_IOCFG, &tmp);
-       if ((tmp & mask) == 0)
-               goto cbl40;
-
-       ap->cbl = ATA_CBL_PATA80;
-       return;
-
-cbl40:
-       ap->cbl = ATA_CBL_PATA40;
-       ap->udma_mask &= ATA_UDMA_MASK_40C;
-}
-
-/**
- *     piix_pata_prereset - prereset for PATA host controller
- *     @ap: Target port
- *
- *     Prereset including cable detection.
- *
- *     LOCKING:
- *     None (inherited from caller).
- */
-static int piix_pata_prereset(struct ata_port *ap)
-{
-       struct pci_dev *pdev = to_pci_dev(ap->host_set->dev);
-
-       if (!pci_test_config_bits(pdev, &piix_enable_bits[ap->port_no])) {
-               ata_port_printk(ap, KERN_INFO, "port disabled. ignoring.\n");
-               ap->eh_context.i.action &= ~ATA_EH_RESET_MASK;
-               return 0;
-       }
-
-       piix_pata_cbl_detect(ap);
-
-       return ata_std_prereset(ap);
-}
-
-static void piix_pata_error_handler(struct ata_port *ap)
-{
-       ata_bmdma_drive_eh(ap, piix_pata_prereset, ata_std_softreset, NULL,
-                          ata_std_postreset);
-}
-
-/**
- *     piix_sata_prereset - prereset for SATA host controller
- *     @ap: Target port
- *
- *     Reads and configures SATA PCI device's PCI config register
- *     Port Configuration and Status (PCS) to determine port and
- *     device availability.  Return -ENODEV to skip reset if no
- *     device is present.
- *
- *     LOCKING:
- *     None (inherited from caller).
- *
- *     RETURNS:
- *     0 if device is present, -ENODEV otherwise.
- */
-static int piix_sata_prereset(struct ata_port *ap)
-{
-       struct pci_dev *pdev = to_pci_dev(ap->host_set->dev);
-       struct piix_host_priv *hpriv = ap->host_set->private_data;
-       const unsigned int *map = hpriv->map;
-       int base = 2 * ap->port_no;
-       unsigned int present = 0;
-       int port, i;
-       u16 pcs;
-
-       pci_read_config_word(pdev, ICH5_PCS, &pcs);
-       DPRINTK("ata%u: ENTER, pcs=0x%x base=%d\n", ap->id, pcs, base);
-
-       for (i = 0; i < 2; i++) {
-               port = map[base + i];
-               if (port < 0)
-                       continue;
-               if ((ap->flags & PIIX_FLAG_IGNORE_PCS) ||
-                   (pcs & 1 << (hpriv->map_db->present_shift + port)))
-                       present = 1;
-       }
-
-       DPRINTK("ata%u: LEAVE, pcs=0x%x present=0x%x\n",
-               ap->id, pcs, present);
-
-       if (!present) {
-               ata_port_printk(ap, KERN_INFO, "SATA port has no device.\n");
-               ap->eh_context.i.action &= ~ATA_EH_RESET_MASK;
-               return 0;
-       }
-
-       return ata_std_prereset(ap);
-}
-
-static void piix_sata_error_handler(struct ata_port *ap)
-{
-       ata_bmdma_drive_eh(ap, piix_sata_prereset, ata_std_softreset, NULL,
-                          ata_std_postreset);
-}
-
-/**
- *     piix_set_piomode - Initialize host controller PATA PIO timings
- *     @ap: Port whose timings we are configuring
- *     @adev: um
- *
- *     Set PIO mode for device, in host controller PCI config space.
- *
- *     LOCKING:
- *     None (inherited from caller).
- */
-
-static void piix_set_piomode (struct ata_port *ap, struct ata_device *adev)
-{
-       unsigned int pio        = adev->pio_mode - XFER_PIO_0;
-       struct pci_dev *dev     = to_pci_dev(ap->host_set->dev);
-       unsigned int is_slave   = (adev->devno != 0);
-       unsigned int master_port= ap->port_no ? 0x42 : 0x40;
-       unsigned int slave_port = 0x44;
-       u16 master_data;
-       u8 slave_data;
-
-       static const     /* ISP  RTC */
-       u8 timings[][2] = { { 0, 0 },
-                           { 0, 0 },
-                           { 1, 0 },
-                           { 2, 1 },
-                           { 2, 3 }, };
-
-       pci_read_config_word(dev, master_port, &master_data);
-       if (is_slave) {
-               master_data |= 0x4000;
-               /* enable PPE, IE and TIME */
-               master_data |= 0x0070;
-               pci_read_config_byte(dev, slave_port, &slave_data);
-               slave_data &= (ap->port_no ? 0x0f : 0xf0);
-               slave_data |=
-                       (timings[pio][0] << 2) |
-                       (timings[pio][1] << (ap->port_no ? 4 : 0));
-       } else {
-               master_data &= 0xccf8;
-               /* enable PPE, IE and TIME */
-               master_data |= 0x0007;
-               master_data |=
-                       (timings[pio][0] << 12) |
-                       (timings[pio][1] << 8);
-       }
-       pci_write_config_word(dev, master_port, master_data);
-       if (is_slave)
-               pci_write_config_byte(dev, slave_port, slave_data);
-}
-
-/**
- *     piix_set_dmamode - Initialize host controller PATA PIO timings
- *     @ap: Port whose timings we are configuring
- *     @adev: um
- *     @udma: udma mode, 0 - 6
- *
- *     Set UDMA mode for device, in host controller PCI config space.
- *
- *     LOCKING:
- *     None (inherited from caller).
- */
-
-static void piix_set_dmamode (struct ata_port *ap, struct ata_device *adev)
-{
-       unsigned int udma       = adev->dma_mode; /* FIXME: MWDMA too */
-       struct pci_dev *dev     = to_pci_dev(ap->host_set->dev);
-       u8 maslave              = ap->port_no ? 0x42 : 0x40;
-       u8 speed                = udma;
-       unsigned int drive_dn   = (ap->port_no ? 2 : 0) + adev->devno;
-       int a_speed             = 3 << (drive_dn * 4);
-       int u_flag              = 1 << drive_dn;
-       int v_flag              = 0x01 << drive_dn;
-       int w_flag              = 0x10 << drive_dn;
-       int u_speed             = 0;
-       int                     sitre;
-       u16                     reg4042, reg4a;
-       u8                      reg48, reg54, reg55;
-
-       pci_read_config_word(dev, maslave, &reg4042);
-       DPRINTK("reg4042 = 0x%04x\n", reg4042);
-       sitre = (reg4042 & 0x4000) ? 1 : 0;
-       pci_read_config_byte(dev, 0x48, &reg48);
-       pci_read_config_word(dev, 0x4a, &reg4a);
-       pci_read_config_byte(dev, 0x54, &reg54);
-       pci_read_config_byte(dev, 0x55, &reg55);
-
-       switch(speed) {
-               case XFER_UDMA_4:
-               case XFER_UDMA_2:       u_speed = 2 << (drive_dn * 4); break;
-               case XFER_UDMA_6:
-               case XFER_UDMA_5:
-               case XFER_UDMA_3:
-               case XFER_UDMA_1:       u_speed = 1 << (drive_dn * 4); break;
-               case XFER_UDMA_0:       u_speed = 0 << (drive_dn * 4); break;
-               case XFER_MW_DMA_2:
-               case XFER_MW_DMA_1:     break;
-               default:
-                       BUG();
-                       return;
-       }
-
-       if (speed >= XFER_UDMA_0) {
-               if (!(reg48 & u_flag))
-                       pci_write_config_byte(dev, 0x48, reg48 | u_flag);
-               if (speed == XFER_UDMA_5) {
-                       pci_write_config_byte(dev, 0x55, (u8) reg55|w_flag);
-               } else {
-                       pci_write_config_byte(dev, 0x55, (u8) reg55 & ~w_flag);
-               }
-               if ((reg4a & a_speed) != u_speed)
-                       pci_write_config_word(dev, 0x4a, (reg4a & ~a_speed) | u_speed);
-               if (speed > XFER_UDMA_2) {
-                       if (!(reg54 & v_flag))
-                               pci_write_config_byte(dev, 0x54, reg54 | v_flag);
-               } else
-                       pci_write_config_byte(dev, 0x54, reg54 & ~v_flag);
-       } else {
-               if (reg48 & u_flag)
-                       pci_write_config_byte(dev, 0x48, reg48 & ~u_flag);
-               if (reg4a & a_speed)
-                       pci_write_config_word(dev, 0x4a, reg4a & ~a_speed);
-               if (reg54 & v_flag)
-                       pci_write_config_byte(dev, 0x54, reg54 & ~v_flag);
-               if (reg55 & w_flag)
-                       pci_write_config_byte(dev, 0x55, (u8) reg55 & ~w_flag);
-       }
-}
-
-#define AHCI_PCI_BAR 5
-#define AHCI_GLOBAL_CTL 0x04
-#define AHCI_ENABLE (1 << 31)
-static int piix_disable_ahci(struct pci_dev *pdev)
-{
-       void __iomem *mmio;
-       u32 tmp;
-       int rc = 0;
-
-       /* BUG: pci_enable_device has not yet been called.  This
-        * works because this device is usually set up by BIOS.
-        */
-
-       if (!pci_resource_start(pdev, AHCI_PCI_BAR) ||
-           !pci_resource_len(pdev, AHCI_PCI_BAR))
-               return 0;
-
-       mmio = pci_iomap(pdev, AHCI_PCI_BAR, 64);
-       if (!mmio)
-               return -ENOMEM;
-
-       tmp = readl(mmio + AHCI_GLOBAL_CTL);
-       if (tmp & AHCI_ENABLE) {
-               tmp &= ~AHCI_ENABLE;
-               writel(tmp, mmio + AHCI_GLOBAL_CTL);
-
-               tmp = readl(mmio + AHCI_GLOBAL_CTL);
-               if (tmp & AHCI_ENABLE)
-                       rc = -EIO;
-       }
-
-       pci_iounmap(pdev, mmio);
-       return rc;
-}
-
-/**
- *     piix_check_450nx_errata -       Check for problem 450NX setup
- *     @ata_dev: the PCI device to check
- *
- *     Check for the present of 450NX errata #19 and errata #25. If
- *     they are found return an error code so we can turn off DMA
- */
-
-static int __devinit piix_check_450nx_errata(struct pci_dev *ata_dev)
-{
-       struct pci_dev *pdev = NULL;
-       u16 cfg;
-       u8 rev;
-       int no_piix_dma = 0;
-
-       while((pdev = pci_get_device(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82454NX, pdev)) != NULL)
-       {
-               /* Look for 450NX PXB. Check for problem configurations
-                  A PCI quirk checks bit 6 already */
-               pci_read_config_byte(pdev, PCI_REVISION_ID, &rev);
-               pci_read_config_word(pdev, 0x41, &cfg);
-               /* Only on the original revision: IDE DMA can hang */
-               if (rev == 0x00)
-                       no_piix_dma = 1;
-               /* On all revisions below 5 PXB bus lock must be disabled for IDE */
-               else if (cfg & (1<<14) && rev < 5)
-                       no_piix_dma = 2;
-       }
-       if (no_piix_dma)
-               dev_printk(KERN_WARNING, &ata_dev->dev, "450NX errata present, disabling IDE DMA.\n");
-       if (no_piix_dma == 2)
-               dev_printk(KERN_WARNING, &ata_dev->dev, "A BIOS update may resolve this.\n");
-       return no_piix_dma;
-}
-
-static void __devinit piix_init_pcs(struct pci_dev *pdev,
-                                   const struct piix_map_db *map_db)
-{
-       u16 pcs, new_pcs;
-
-       pci_read_config_word(pdev, ICH5_PCS, &pcs);
-
-       new_pcs = pcs | map_db->port_enable;
-
-       if (new_pcs != pcs) {
-               DPRINTK("updating PCS from 0x%x to 0x%x\n", pcs, new_pcs);
-               pci_write_config_word(pdev, ICH5_PCS, new_pcs);
-               msleep(150);
-       }
-}
-
-static void __devinit piix_init_sata_map(struct pci_dev *pdev,
-                                        struct ata_port_info *pinfo,
-                                        const struct piix_map_db *map_db)
-{
-       struct piix_host_priv *hpriv = pinfo[0].private_data;
-       const unsigned int *map;
-       int i, invalid_map = 0;
-       u8 map_value;
-
-       pci_read_config_byte(pdev, ICH5_PMR, &map_value);
-
-       map = map_db->map[map_value & map_db->mask];
-
-       dev_printk(KERN_INFO, &pdev->dev, "MAP [");
-       for (i = 0; i < 4; i++) {
-               switch (map[i]) {
-               case RV:
-                       invalid_map = 1;
-                       printk(" XX");
-                       break;
-
-               case NA:
-                       printk(" --");
-                       break;
-
-               case IDE:
-                       WARN_ON((i & 1) || map[i + 1] != IDE);
-                       pinfo[i / 2] = piix_port_info[ich5_pata];
-                       pinfo[i / 2].private_data = hpriv;
-                       i++;
-                       printk(" IDE IDE");
-                       break;
-
-               default:
-                       printk(" P%d", map[i]);
-                       if (i & 1)
-                               pinfo[i / 2].host_flags |= ATA_FLAG_SLAVE_POSS;
-                       break;
-               }
-       }
-       printk(" ]\n");
-
-       if (invalid_map)
-               dev_printk(KERN_ERR, &pdev->dev,
-                          "invalid MAP value %u\n", map_value);
-
-       hpriv->map = map;
-       hpriv->map_db = map_db;
-}
-
-/**
- *     piix_init_one - Register PIIX ATA PCI device with kernel services
- *     @pdev: PCI device to register
- *     @ent: Entry in piix_pci_tbl matching with @pdev
- *
- *     Called from kernel PCI layer.  We probe for combined mode (sigh),
- *     and then hand over control to libata, for it to do the rest.
- *
- *     LOCKING:
- *     Inherited from PCI layer (may sleep).
- *
- *     RETURNS:
- *     Zero on success, or -ERRNO value.
- */
-
-static int piix_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
-{
-       static int printed_version;
-       struct ata_port_info port_info[2];
-       struct ata_port_info *ppinfo[2] = { &port_info[0], &port_info[1] };
-       struct piix_host_priv *hpriv;
-       unsigned long host_flags;
-
-       if (!printed_version++)
-               dev_printk(KERN_DEBUG, &pdev->dev,
-                          "version " DRV_VERSION "\n");
-
-       /* no hotplugging support (FIXME) */
-       if (!in_module_init)
-               return -ENODEV;
-
-       hpriv = kzalloc(sizeof(*hpriv), GFP_KERNEL);
-       if (!hpriv)
-               return -ENOMEM;
-
-       port_info[0] = piix_port_info[ent->driver_data];
-       port_info[1] = piix_port_info[ent->driver_data];
-       port_info[0].private_data = hpriv;
-       port_info[1].private_data = hpriv;
-
-       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) {
-                       int rc = piix_disable_ahci(pdev);
-                       if (rc)
-                               return rc;
-               }
-       }
-
-       /* Initialize SATA map */
-       if (host_flags & ATA_FLAG_SATA) {
-               piix_init_sata_map(pdev, port_info,
-                                  piix_map_db_table[ent->driver_data]);
-               piix_init_pcs(pdev, piix_map_db_table[ent->driver_data]);
-       }
-
-       /* On ICH5, some BIOSen disable the interrupt using the
-        * PCI_COMMAND_INTX_DISABLE bit added in PCI 2.3.
-        * On ICH6, this bit has the same effect, but only when
-        * MSI is disabled (and it is disabled, as we don't use
-        * message-signalled interrupts currently).
-        */
-       if (host_flags & PIIX_FLAG_CHECKINTR)
-               pci_intx(pdev, 1);
-
-       if (piix_check_450nx_errata(pdev)) {
-               /* This writes into the master table but it does not
-                  really matter for this errata as we will apply it to
-                  all the PIIX devices on the board */
-               port_info[0].mwdma_mask = 0;
-               port_info[0].udma_mask = 0;
-               port_info[1].mwdma_mask = 0;
-               port_info[1].udma_mask = 0;
-       }
-       return ata_pci_init_one(pdev, ppinfo, 2);
-}
-
-static void piix_host_stop(struct ata_host_set *host_set)
-{
-       ata_host_stop(host_set);
-}
-
-static int __init piix_init(void)
-{
-       int rc;
-
-       DPRINTK("pci_register_driver\n");
-       rc = pci_register_driver(&piix_pci_driver);
-       if (rc)
-               return rc;
-
-       in_module_init = 0;
-
-       DPRINTK("done\n");
-       return 0;
-}
-
-static void __exit piix_exit(void)
-{
-       pci_unregister_driver(&piix_pci_driver);
-}
-
-module_init(piix_init);
-module_exit(piix_exit);
-
diff --git a/drivers/scsi/libata-bmdma.c b/drivers/scsi/libata-bmdma.c
deleted file mode 100644 (file)
index 158f62d..0000000
+++ /dev/null
@@ -1,1109 +0,0 @@
-/*
- *  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/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.
- *
- *     FIXME: missing write posting for 400nS delay enforcement
- *
- *     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);
-}
-
-/**
- *     ata_bmdma_setup_mmio - Set up PCI IDE BMDMA transaction
- *     @qc: Info associated with this ATA transaction.
- *
- *     LOCKING:
- *     spin_lock_irqsave(host_set lock)
- */
-
-static void ata_bmdma_setup_mmio (struct ata_queued_cmd *qc)
-{
-       struct ata_port *ap = qc->ap;
-       unsigned int rw = (qc->tf.flags & ATA_TFLAG_WRITE);
-       u8 dmactl;
-       void __iomem *mmio = (void __iomem *) ap->ioaddr.bmdma_addr;
-
-       /* load PRD table addr. */
-       mb();   /* make sure PRD table writes are visible to controller */
-       writel(ap->prd_dma, mmio + ATA_DMA_TABLE_OFS);
-
-       /* specify data direction, triple-check start bit is clear */
-       dmactl = readb(mmio + ATA_DMA_CMD);
-       dmactl &= ~(ATA_DMA_WR | ATA_DMA_START);
-       if (!rw)
-               dmactl |= ATA_DMA_WR;
-       writeb(dmactl, mmio + ATA_DMA_CMD);
-
-       /* issue r/w command */
-       ap->ops->exec_command(ap, &qc->tf);
-}
-
-/**
- *     ata_bmdma_start_mmio - Start a PCI IDE BMDMA transaction
- *     @qc: Info associated with this ATA transaction.
- *
- *     LOCKING:
- *     spin_lock_irqsave(host_set lock)
- */
-
-static void ata_bmdma_start_mmio (struct ata_queued_cmd *qc)
-{
-       struct ata_port *ap = qc->ap;
-       void __iomem *mmio = (void __iomem *) ap->ioaddr.bmdma_addr;
-       u8 dmactl;
-
-       /* start host DMA transaction */
-       dmactl = readb(mmio + ATA_DMA_CMD);
-       writeb(dmactl | ATA_DMA_START, mmio + ATA_DMA_CMD);
-
-       /* Strictly, one may wish to issue a readb() here, to
-        * flush the mmio write.  However, control also passes
-        * to the hardware at this point, and it will interrupt
-        * us when we are to resume control.  So, in effect,
-        * we don't care when the mmio write flushes.
-        * Further, a read of the DMA status register _immediately_
-        * following the write may not be what certain flaky hardware
-        * is expected, so I think it is best to not add a readb()
-        * without first all the MMIO ATA cards/mobos.
-        * Or maybe I'm just being paranoid.
-        */
-}
-
-/**
- *     ata_bmdma_setup_pio - Set up PCI IDE BMDMA transaction (PIO)
- *     @qc: Info associated with this ATA transaction.
- *
- *     LOCKING:
- *     spin_lock_irqsave(host_set lock)
- */
-
-static void ata_bmdma_setup_pio (struct ata_queued_cmd *qc)
-{
-       struct ata_port *ap = qc->ap;
-       unsigned int rw = (qc->tf.flags & ATA_TFLAG_WRITE);
-       u8 dmactl;
-
-       /* load PRD table addr. */
-       outl(ap->prd_dma, ap->ioaddr.bmdma_addr + ATA_DMA_TABLE_OFS);
-
-       /* specify data direction, triple-check start bit is clear */
-       dmactl = inb(ap->ioaddr.bmdma_addr + ATA_DMA_CMD);
-       dmactl &= ~(ATA_DMA_WR | ATA_DMA_START);
-       if (!rw)
-               dmactl |= ATA_DMA_WR;
-       outb(dmactl, ap->ioaddr.bmdma_addr + ATA_DMA_CMD);
-
-       /* issue r/w command */
-       ap->ops->exec_command(ap, &qc->tf);
-}
-
-/**
- *     ata_bmdma_start_pio - Start a PCI IDE BMDMA transaction (PIO)
- *     @qc: Info associated with this ATA transaction.
- *
- *     LOCKING:
- *     spin_lock_irqsave(host_set lock)
- */
-
-static void ata_bmdma_start_pio (struct ata_queued_cmd *qc)
-{
-       struct ata_port *ap = qc->ap;
-       u8 dmactl;
-
-       /* start host DMA transaction */
-       dmactl = inb(ap->ioaddr.bmdma_addr + ATA_DMA_CMD);
-       outb(dmactl | ATA_DMA_START,
-            ap->ioaddr.bmdma_addr + ATA_DMA_CMD);
-}
-
-
-/**
- *     ata_bmdma_start - Start a PCI IDE BMDMA transaction
- *     @qc: Info associated with this ATA transaction.
- *
- *     Writes the ATA_DMA_START flag to the DMA command register.
- *
- *     May be used as the bmdma_start() entry in ata_port_operations.
- *
- *     LOCKING:
- *     spin_lock_irqsave(host_set lock)
- */
-void ata_bmdma_start(struct ata_queued_cmd *qc)
-{
-       if (qc->ap->flags & ATA_FLAG_MMIO)
-               ata_bmdma_start_mmio(qc);
-       else
-               ata_bmdma_start_pio(qc);
-}
-
-
-/**
- *     ata_bmdma_setup - Set up PCI IDE BMDMA transaction
- *     @qc: Info associated with this ATA transaction.
- *
- *     Writes address of PRD table to device's PRD Table Address
- *     register, sets the DMA control register, and calls
- *     ops->exec_command() to start the transfer.
- *
- *     May be used as the bmdma_setup() entry in ata_port_operations.
- *
- *     LOCKING:
- *     spin_lock_irqsave(host_set lock)
- */
-void ata_bmdma_setup(struct ata_queued_cmd *qc)
-{
-       if (qc->ap->flags & ATA_FLAG_MMIO)
-               ata_bmdma_setup_mmio(qc);
-       else
-               ata_bmdma_setup_pio(qc);
-}
-
-
-/**
- *     ata_bmdma_irq_clear - Clear PCI IDE BMDMA interrupt.
- *     @ap: Port associated with this ATA transaction.
- *
- *     Clear interrupt and error flags in DMA status register.
- *
- *     May be used as the irq_clear() entry in ata_port_operations.
- *
- *     LOCKING:
- *     spin_lock_irqsave(host_set lock)
- */
-
-void ata_bmdma_irq_clear(struct ata_port *ap)
-{
-       if (!ap->ioaddr.bmdma_addr)
-               return;
-
-       if (ap->flags & ATA_FLAG_MMIO) {
-               void __iomem *mmio =
-                     ((void __iomem *) ap->ioaddr.bmdma_addr) + ATA_DMA_STATUS;
-               writeb(readb(mmio), mmio);
-       } else {
-               unsigned long addr = ap->ioaddr.bmdma_addr + ATA_DMA_STATUS;
-               outb(inb(addr), addr);
-       }
-}
-
-
-/**
- *     ata_bmdma_status - Read PCI IDE BMDMA status
- *     @ap: Port associated with this ATA transaction.
- *
- *     Read and return BMDMA status register.
- *
- *     May be used as the bmdma_status() entry in ata_port_operations.
- *
- *     LOCKING:
- *     spin_lock_irqsave(host_set lock)
- */
-
-u8 ata_bmdma_status(struct ata_port *ap)
-{
-       u8 host_stat;
-       if (ap->flags & ATA_FLAG_MMIO) {
-               void __iomem *mmio = (void __iomem *) ap->ioaddr.bmdma_addr;
-               host_stat = readb(mmio + ATA_DMA_STATUS);
-       } else
-               host_stat = inb(ap->ioaddr.bmdma_addr + ATA_DMA_STATUS);
-       return host_stat;
-}
-
-
-/**
- *     ata_bmdma_stop - Stop PCI IDE BMDMA transfer
- *     @qc: Command we are ending DMA for
- *
- *     Clears the ATA_DMA_START flag in the dma control register
- *
- *     May be used as the bmdma_stop() entry in ata_port_operations.
- *
- *     LOCKING:
- *     spin_lock_irqsave(host_set lock)
- */
-
-void ata_bmdma_stop(struct ata_queued_cmd *qc)
-{
-       struct ata_port *ap = qc->ap;
-       if (ap->flags & ATA_FLAG_MMIO) {
-               void __iomem *mmio = (void __iomem *) ap->ioaddr.bmdma_addr;
-
-               /* clear start/stop bit */
-               writeb(readb(mmio + ATA_DMA_CMD) & ~ATA_DMA_START,
-                       mmio + ATA_DMA_CMD);
-       } else {
-               /* clear start/stop bit */
-               outb(inb(ap->ioaddr.bmdma_addr + ATA_DMA_CMD) & ~ATA_DMA_START,
-                       ap->ioaddr.bmdma_addr + ATA_DMA_CMD);
-       }
-
-       /* one-PIO-cycle guaranteed wait, per spec, for HDMA1:0 transition */
-       ata_altstatus(ap);        /* dummy read */
-}
-
-/**
- *     ata_bmdma_freeze - Freeze BMDMA controller port
- *     @ap: port to freeze
- *
- *     Freeze BMDMA controller port.
- *
- *     LOCKING:
- *     Inherited from caller.
- */
-void ata_bmdma_freeze(struct ata_port *ap)
-{
-       struct ata_ioports *ioaddr = &ap->ioaddr;
-
-       ap->ctl |= ATA_NIEN;
-       ap->last_ctl = ap->ctl;
-
-       if (ap->flags & ATA_FLAG_MMIO)
-               writeb(ap->ctl, (void __iomem *)ioaddr->ctl_addr);
-       else
-               outb(ap->ctl, ioaddr->ctl_addr);
-}
-
-/**
- *     ata_bmdma_thaw - Thaw BMDMA controller port
- *     @ap: port to thaw
- *
- *     Thaw BMDMA controller port.
- *
- *     LOCKING:
- *     Inherited from caller.
- */
-void ata_bmdma_thaw(struct ata_port *ap)
-{
-       /* clear & re-enable interrupts */
-       ata_chk_status(ap);
-       ap->ops->irq_clear(ap);
-       if (ap->ioaddr.ctl_addr)        /* FIXME: hack. create a hook instead */
-               ata_irq_on(ap);
-}
-
-/**
- *     ata_bmdma_drive_eh - Perform EH with given methods for BMDMA controller
- *     @ap: port to handle error for
- *     @prereset: prereset method (can be NULL)
- *     @softreset: softreset method (can be NULL)
- *     @hardreset: hardreset method (can be NULL)
- *     @postreset: postreset method (can be NULL)
- *
- *     Handle error for ATA BMDMA controller.  It can handle both
- *     PATA and SATA controllers.  Many controllers should be able to
- *     use this EH as-is or with some added handling before and
- *     after.
- *
- *     This function is intended to be used for constructing
- *     ->error_handler callback by low level drivers.
- *
- *     LOCKING:
- *     Kernel thread context (may sleep)
- */
-void ata_bmdma_drive_eh(struct ata_port *ap, ata_prereset_fn_t prereset,
-                       ata_reset_fn_t softreset, ata_reset_fn_t hardreset,
-                       ata_postreset_fn_t postreset)
-{
-       struct ata_eh_context *ehc = &ap->eh_context;
-       struct ata_queued_cmd *qc;
-       unsigned long flags;
-       int thaw = 0;
-
-       qc = __ata_qc_from_tag(ap, ap->active_tag);
-       if (qc && !(qc->flags & ATA_QCFLAG_FAILED))
-               qc = NULL;
-
-       /* reset PIO HSM and stop DMA engine */
-       spin_lock_irqsave(ap->lock, flags);
-
-       ap->hsm_task_state = HSM_ST_IDLE;
-
-       if (qc && (qc->tf.protocol == ATA_PROT_DMA ||
-                  qc->tf.protocol == ATA_PROT_ATAPI_DMA)) {
-               u8 host_stat;
-
-               host_stat = ata_bmdma_status(ap);
-
-               ata_ehi_push_desc(&ehc->i, "BMDMA stat 0x%x", host_stat);
-
-               /* BMDMA controllers indicate host bus error by
-                * setting DMA_ERR bit and timing out.  As it wasn't
-                * really a timeout event, adjust error mask and
-                * cancel frozen state.
-                */
-               if (qc->err_mask == AC_ERR_TIMEOUT && host_stat & ATA_DMA_ERR) {
-                       qc->err_mask = AC_ERR_HOST_BUS;
-                       thaw = 1;
-               }
-
-               ap->ops->bmdma_stop(qc);
-       }
-
-       ata_altstatus(ap);
-       ata_chk_status(ap);
-       ap->ops->irq_clear(ap);
-
-       spin_unlock_irqrestore(ap->lock, flags);
-
-       if (thaw)
-               ata_eh_thaw_port(ap);
-
-       /* PIO and DMA engines have been stopped, perform recovery */
-       ata_do_eh(ap, prereset, softreset, hardreset, postreset);
-}
-
-/**
- *     ata_bmdma_error_handler - Stock error handler for BMDMA controller
- *     @ap: port to handle error for
- *
- *     Stock error handler for BMDMA controller.
- *
- *     LOCKING:
- *     Kernel thread context (may sleep)
- */
-void ata_bmdma_error_handler(struct ata_port *ap)
-{
-       ata_reset_fn_t hardreset;
-
-       hardreset = NULL;
-       if (sata_scr_valid(ap))
-               hardreset = sata_std_hardreset;
-
-       ata_bmdma_drive_eh(ap, ata_std_prereset, ata_std_softreset, hardreset,
-                          ata_std_postreset);
-}
-
-/**
- *     ata_bmdma_post_internal_cmd - Stock post_internal_cmd for
- *                                   BMDMA controller
- *     @qc: internal command to clean up
- *
- *     LOCKING:
- *     Kernel thread context (may sleep)
- */
-void ata_bmdma_post_internal_cmd(struct ata_queued_cmd *qc)
-{
-       ata_bmdma_stop(qc);
-}
-
-#ifdef CONFIG_PCI
-/**
- *     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;
-       unsigned long bmdma;
-
-       if (!probe_ent)
-               return NULL;
-
-       probe_ent->irq = pdev->irq;
-       probe_ent->irq_flags = IRQF_SHARED;
-       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;
-               bmdma = pci_resource_start(pdev, 4);
-               if (bmdma) {
-                       if (inb(bmdma + 2) & 0x80)
-                               probe_ent->host_set_flags |= ATA_HOST_SIMPLEX;
-                       probe_ent->port[p].bmdma_addr = bmdma;
-               }
-               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;
-               bmdma = pci_resource_start(pdev, 4);
-               if (bmdma) {
-                       bmdma += 8;
-                       if(inb(bmdma + 2) & 0x80)
-                               probe_ent->host_set_flags |= ATA_HOST_SIMPLEX;
-                       probe_ent->port[p].bmdma_addr = bmdma;
-               }
-               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_mask)
-{
-       struct ata_probe_ent *probe_ent;
-       unsigned long bmdma = pci_resource_start(pdev, 4);
-
-       probe_ent = ata_probe_ent_alloc(pci_dev_to_dev(pdev), port[0]);
-       if (!probe_ent)
-               return NULL;
-
-       probe_ent->n_ports = 2;
-       probe_ent->private_data = port[0]->private_data;
-
-       if (port_mask & ATA_PORT_PRIMARY) {
-               probe_ent->irq = 14;
-               probe_ent->port[0].cmd_addr = ATA_PRIMARY_CMD;
-               probe_ent->port[0].altstatus_addr =
-               probe_ent->port[0].ctl_addr = ATA_PRIMARY_CTL;
-               if (bmdma) {
-                       probe_ent->port[0].bmdma_addr = bmdma;
-                       if (inb(bmdma + 2) & 0x80)
-                               probe_ent->host_set_flags |= ATA_HOST_SIMPLEX;
-               }
-               ata_std_ports(&probe_ent->port[0]);
-       } else
-               probe_ent->dummy_port_mask |= ATA_PORT_PRIMARY;
-
-       if (port_mask & ATA_PORT_SECONDARY) {
-               if (probe_ent->irq)
-                       probe_ent->irq2 = 15;
-               else
-                       probe_ent->irq = 15;
-               probe_ent->port[1].cmd_addr = ATA_SECONDARY_CMD;
-               probe_ent->port[1].altstatus_addr =
-               probe_ent->port[1].ctl_addr = ATA_SECONDARY_CTL;
-               if (bmdma) {
-                       probe_ent->port[1].bmdma_addr = bmdma + 8;
-                       if (inb(bmdma + 10) & 0x80)
-                               probe_ent->host_set_flags |= ATA_HOST_SIMPLEX;
-               }
-               ata_std_ports(&probe_ent->port[1]);
-       } else
-               probe_ent->dummy_port_mask |= ATA_PORT_SECONDARY;
-
-       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()
- *
- *     ASSUMPTION:
- *     Nobody makes a single channel controller that appears solely as
- *     the secondary legacy port on PCI.
- *
- *     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;
-       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;
-       }
-
-       if (legacy_mode) {
-               if (!request_region(ATA_PRIMARY_CMD, 8, "libata")) {
-                       struct resource *conflict, res;
-                       res.start = ATA_PRIMARY_CMD;
-                       res.end = ATA_PRIMARY_CMD + 8 - 1;
-                       conflict = ____request_resource(&ioport_resource, &res);
-                       if (!strcmp(conflict->name, "libata"))
-                               legacy_mode |= ATA_PORT_PRIMARY;
-                       else {
-                               disable_dev_on_err = 0;
-                               printk(KERN_WARNING "ata: 0x%0X IDE port busy\n", ATA_PRIMARY_CMD);
-                       }
-               } else
-                       legacy_mode |= ATA_PORT_PRIMARY;
-
-               if (!request_region(ATA_SECONDARY_CMD, 8, "libata")) {
-                       struct resource *conflict, res;
-                       res.start = ATA_SECONDARY_CMD;
-                       res.end = ATA_SECONDARY_CMD + 8 - 1;
-                       conflict = ____request_resource(&ioport_resource, &res);
-                       if (!strcmp(conflict->name, "libata"))
-                               legacy_mode |= ATA_PORT_SECONDARY;
-                       else {
-                               disable_dev_on_err = 0;
-                               printk(KERN_WARNING "ata: 0x%X IDE port busy\n", ATA_SECONDARY_CMD);
-                       }
-               } else
-                       legacy_mode |= ATA_PORT_SECONDARY;
-       }
-
-       /* we have legacy mode, but all ports are unavailable */
-       if (legacy_mode == (1 << 3)) {
-               rc = -EBUSY;
-               goto err_out_regions;
-       }
-
-       /* FIXME: If we get no DMA mask we should fall back to PIO */
-       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) {
-               probe_ent = ata_pci_init_legacy_port(pdev, port, legacy_mode);
-       } 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) {
-               rc = -ENOMEM;
-               goto err_out_regions;
-       }
-
-       pci_set_master(pdev);
-
-       /* FIXME: check ata_device_add return */
-       ata_device_add(probe_ent);
-
-       kfree(probe_ent);
-
-       return 0;
-
-err_out_regions:
-       if (legacy_mode & ATA_PORT_PRIMARY)
-               release_region(ATA_PRIMARY_CMD, 8);
-       if (legacy_mode & ATA_PORT_SECONDARY)
-               release_region(ATA_SECONDARY_CMD, 8);
-       pci_release_regions(pdev);
-err_out:
-       if (disable_dev_on_err)
-               pci_disable_device(pdev);
-       return rc;
-}
-
-/**
- *     ata_pci_clear_simplex   -       attempt to kick device out of simplex
- *     @pdev: PCI device
- *
- *     Some PCI ATA devices report simplex mode but in fact can be told to
- *     enter non simplex mode. This implements the neccessary logic to
- *     perform the task on such devices. Calling it on other devices will
- *     have -undefined- behaviour.
- */
-
-int ata_pci_clear_simplex(struct pci_dev *pdev)
-{
-       unsigned long bmdma = pci_resource_start(pdev, 4);
-       u8 simplex;
-
-       if (bmdma == 0)
-               return -ENOENT;
-
-       simplex = inb(bmdma + 0x02);
-       outb(simplex & 0x60, bmdma + 0x02);
-       simplex = inb(bmdma + 0x02);
-       if (simplex & 0x80)
-               return -EOPNOTSUPP;
-       return 0;
-}
-
-unsigned long ata_pci_default_filter(const struct ata_port *ap, struct ata_device *adev, unsigned long xfer_mask)
-{
-       /* Filter out DMA modes if the device has been configured by
-          the BIOS as PIO only */
-
-       if (ap->ioaddr.bmdma_addr == 0)
-               xfer_mask &= ~(ATA_MASK_MWDMA | ATA_MASK_UDMA);
-       return xfer_mask;
-}
-
-#endif /* CONFIG_PCI */
-
diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c
deleted file mode 100644 (file)
index 3f963f2..0000000
+++ /dev/null
@@ -1,6098 +0,0 @@
-/*
- *  libata-core.c - helper library for ATA
- *
- *  Maintained by:  Jeff Garzik <jgarzik@pobox.com>
- *                 Please ALWAYS copy linux-ide@vger.kernel.org
- *                 on emails.
- *
- *  Copyright 2003-2004 Red Hat, Inc.  All rights reserved.
- *  Copyright 2003-2004 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/kernel.h>
-#include <linux/module.h>
-#include <linux/pci.h>
-#include <linux/init.h>
-#include <linux/list.h>
-#include <linux/mm.h>
-#include <linux/highmem.h>
-#include <linux/spinlock.h>
-#include <linux/blkdev.h>
-#include <linux/delay.h>
-#include <linux/timer.h>
-#include <linux/interrupt.h>
-#include <linux/completion.h>
-#include <linux/suspend.h>
-#include <linux/workqueue.h>
-#include <linux/jiffies.h>
-#include <linux/scatterlist.h>
-#include <scsi/scsi.h>
-#include "scsi_priv.h"
-#include <scsi/scsi_cmnd.h>
-#include <scsi/scsi_host.h>
-#include <linux/libata.h>
-#include <asm/io.h>
-#include <asm/semaphore.h>
-#include <asm/byteorder.h>
-
-#include "libata.h"
-
-/* debounce timing parameters in msecs { interval, duration, timeout } */
-const unsigned long sata_deb_timing_normal[]           = {   5,  100, 2000 };
-const unsigned long sata_deb_timing_hotplug[]          = {  25,  500, 2000 };
-const unsigned long sata_deb_timing_long[]             = { 100, 2000, 5000 };
-
-static unsigned int ata_dev_init_params(struct ata_device *dev,
-                                       u16 heads, u16 sectors);
-static unsigned int ata_dev_set_xfermode(struct ata_device *dev);
-static void ata_dev_xfermask(struct ata_device *dev);
-
-static unsigned int ata_unique_id = 1;
-static struct workqueue_struct *ata_wq;
-
-struct workqueue_struct *ata_aux_wq;
-
-int atapi_enabled = 1;
-module_param(atapi_enabled, int, 0444);
-MODULE_PARM_DESC(atapi_enabled, "Enable discovery of ATAPI devices (0=off, 1=on)");
-
-int atapi_dmadir = 0;
-module_param(atapi_dmadir, int, 0444);
-MODULE_PARM_DESC(atapi_dmadir, "Enable ATAPI DMADIR bridge support (0=off, 1=on)");
-
-int libata_fua = 0;
-module_param_named(fua, libata_fua, int, 0444);
-MODULE_PARM_DESC(fua, "FUA support (0=off, 1=on)");
-
-static int ata_probe_timeout = ATA_TMOUT_INTERNAL / HZ;
-module_param(ata_probe_timeout, int, 0444);
-MODULE_PARM_DESC(ata_probe_timeout, "Set ATA probing timeout (seconds)");
-
-MODULE_AUTHOR("Jeff Garzik");
-MODULE_DESCRIPTION("Library module for ATA devices");
-MODULE_LICENSE("GPL");
-MODULE_VERSION(DRV_VERSION);
-
-
-/**
- *     ata_tf_to_fis - Convert ATA taskfile to SATA FIS structure
- *     @tf: Taskfile to convert
- *     @fis: Buffer into which data will output
- *     @pmp: Port multiplier port
- *
- *     Converts a standard ATA taskfile to a Serial ATA
- *     FIS structure (Register - Host to Device).
- *
- *     LOCKING:
- *     Inherited from caller.
- */
-
-void ata_tf_to_fis(const struct ata_taskfile *tf, u8 *fis, u8 pmp)
-{
-       fis[0] = 0x27;  /* Register - Host to Device FIS */
-       fis[1] = (pmp & 0xf) | (1 << 7); /* Port multiplier number,
-                                           bit 7 indicates Command FIS */
-       fis[2] = tf->command;
-       fis[3] = tf->feature;
-
-       fis[4] = tf->lbal;
-       fis[5] = tf->lbam;
-       fis[6] = tf->lbah;
-       fis[7] = tf->device;
-
-       fis[8] = tf->hob_lbal;
-       fis[9] = tf->hob_lbam;
-       fis[10] = tf->hob_lbah;
-       fis[11] = tf->hob_feature;
-
-       fis[12] = tf->nsect;
-       fis[13] = tf->hob_nsect;
-       fis[14] = 0;
-       fis[15] = tf->ctl;
-
-       fis[16] = 0;
-       fis[17] = 0;
-       fis[18] = 0;
-       fis[19] = 0;
-}
-
-/**
- *     ata_tf_from_fis - Convert SATA FIS to ATA taskfile
- *     @fis: Buffer from which data will be input
- *     @tf: Taskfile to output
- *
- *     Converts a serial ATA FIS structure to a standard ATA taskfile.
- *
- *     LOCKING:
- *     Inherited from caller.
- */
-
-void ata_tf_from_fis(const u8 *fis, struct ata_taskfile *tf)
-{
-       tf->command     = fis[2];       /* status */
-       tf->feature     = fis[3];       /* error */
-
-       tf->lbal        = fis[4];
-       tf->lbam        = fis[5];
-       tf->lbah        = fis[6];
-       tf->device      = fis[7];
-
-       tf->hob_lbal    = fis[8];
-       tf->hob_lbam    = fis[9];
-       tf->hob_lbah    = fis[10];
-
-       tf->nsect       = fis[12];
-       tf->hob_nsect   = fis[13];
-}
-
-static const u8 ata_rw_cmds[] = {
-       /* pio multi */
-       ATA_CMD_READ_MULTI,
-       ATA_CMD_WRITE_MULTI,
-       ATA_CMD_READ_MULTI_EXT,
-       ATA_CMD_WRITE_MULTI_EXT,
-       0,
-       0,
-       0,
-       ATA_CMD_WRITE_MULTI_FUA_EXT,
-       /* pio */
-       ATA_CMD_PIO_READ,
-       ATA_CMD_PIO_WRITE,
-       ATA_CMD_PIO_READ_EXT,
-       ATA_CMD_PIO_WRITE_EXT,
-       0,
-       0,
-       0,
-       0,
-       /* dma */
-       ATA_CMD_READ,
-       ATA_CMD_WRITE,
-       ATA_CMD_READ_EXT,
-       ATA_CMD_WRITE_EXT,
-       0,
-       0,
-       0,
-       ATA_CMD_WRITE_FUA_EXT
-};
-
-/**
- *     ata_rwcmd_protocol - set taskfile r/w commands and protocol
- *     @qc: command to examine and configure
- *
- *     Examine the device configuration and tf->flags to calculate
- *     the proper read/write commands and protocol to use.
- *
- *     LOCKING:
- *     caller.
- */
-int ata_rwcmd_protocol(struct ata_queued_cmd *qc)
-{
-       struct ata_taskfile *tf = &qc->tf;
-       struct ata_device *dev = qc->dev;
-       u8 cmd;
-
-       int index, fua, lba48, write;
-
-       fua = (tf->flags & ATA_TFLAG_FUA) ? 4 : 0;
-       lba48 = (tf->flags & ATA_TFLAG_LBA48) ? 2 : 0;
-       write = (tf->flags & ATA_TFLAG_WRITE) ? 1 : 0;
-
-       if (dev->flags & ATA_DFLAG_PIO) {
-               tf->protocol = ATA_PROT_PIO;
-               index = dev->multi_count ? 0 : 8;
-       } else if (lba48 && (qc->ap->flags & ATA_FLAG_PIO_LBA48)) {
-               /* Unable to use DMA due to host limitation */
-               tf->protocol = ATA_PROT_PIO;
-               index = dev->multi_count ? 0 : 8;
-       } else {
-               tf->protocol = ATA_PROT_DMA;
-               index = 16;
-       }
-
-       cmd = ata_rw_cmds[index + fua + lba48 + write];
-       if (cmd) {
-               tf->command = cmd;
-               return 0;
-       }
-       return -1;
-}
-
-/**
- *     ata_pack_xfermask - Pack pio, mwdma and udma masks into xfer_mask
- *     @pio_mask: pio_mask
- *     @mwdma_mask: mwdma_mask
- *     @udma_mask: udma_mask
- *
- *     Pack @pio_mask, @mwdma_mask and @udma_mask into a single
- *     unsigned int xfer_mask.
- *
- *     LOCKING:
- *     None.
- *
- *     RETURNS:
- *     Packed xfer_mask.
- */
-static unsigned int ata_pack_xfermask(unsigned int pio_mask,
-                                     unsigned int mwdma_mask,
-                                     unsigned int udma_mask)
-{
-       return ((pio_mask << ATA_SHIFT_PIO) & ATA_MASK_PIO) |
-               ((mwdma_mask << ATA_SHIFT_MWDMA) & ATA_MASK_MWDMA) |
-               ((udma_mask << ATA_SHIFT_UDMA) & ATA_MASK_UDMA);
-}
-
-/**
- *     ata_unpack_xfermask - Unpack xfer_mask into pio, mwdma and udma masks
- *     @xfer_mask: xfer_mask to unpack
- *     @pio_mask: resulting pio_mask
- *     @mwdma_mask: resulting mwdma_mask
- *     @udma_mask: resulting udma_mask
- *
- *     Unpack @xfer_mask into @pio_mask, @mwdma_mask and @udma_mask.
- *     Any NULL distination masks will be ignored.
- */
-static void ata_unpack_xfermask(unsigned int xfer_mask,
-                               unsigned int *pio_mask,
-                               unsigned int *mwdma_mask,
-                               unsigned int *udma_mask)
-{
-       if (pio_mask)
-               *pio_mask = (xfer_mask & ATA_MASK_PIO) >> ATA_SHIFT_PIO;
-       if (mwdma_mask)
-               *mwdma_mask = (xfer_mask & ATA_MASK_MWDMA) >> ATA_SHIFT_MWDMA;
-       if (udma_mask)
-               *udma_mask = (xfer_mask & ATA_MASK_UDMA) >> ATA_SHIFT_UDMA;
-}
-
-static const struct ata_xfer_ent {
-       int shift, bits;
-       u8 base;
-} ata_xfer_tbl[] = {
-       { ATA_SHIFT_PIO, ATA_BITS_PIO, XFER_PIO_0 },
-       { ATA_SHIFT_MWDMA, ATA_BITS_MWDMA, XFER_MW_DMA_0 },
-       { ATA_SHIFT_UDMA, ATA_BITS_UDMA, XFER_UDMA_0 },
-       { -1, },
-};
-
-/**
- *     ata_xfer_mask2mode - Find matching XFER_* for the given xfer_mask
- *     @xfer_mask: xfer_mask of interest
- *
- *     Return matching XFER_* value for @xfer_mask.  Only the highest
- *     bit of @xfer_mask is considered.
- *
- *     LOCKING:
- *     None.
- *
- *     RETURNS:
- *     Matching XFER_* value, 0 if no match found.
- */
-static u8 ata_xfer_mask2mode(unsigned int xfer_mask)
-{
-       int highbit = fls(xfer_mask) - 1;
-       const struct ata_xfer_ent *ent;
-
-       for (ent = ata_xfer_tbl; ent->shift >= 0; ent++)
-               if (highbit >= ent->shift && highbit < ent->shift + ent->bits)
-                       return ent->base + highbit - ent->shift;
-       return 0;
-}
-
-/**
- *     ata_xfer_mode2mask - Find matching xfer_mask for XFER_*
- *     @xfer_mode: XFER_* of interest
- *
- *     Return matching xfer_mask for @xfer_mode.
- *
- *     LOCKING:
- *     None.
- *
- *     RETURNS:
- *     Matching xfer_mask, 0 if no match found.
- */
-static unsigned int ata_xfer_mode2mask(u8 xfer_mode)
-{
-       const struct ata_xfer_ent *ent;
-
-       for (ent = ata_xfer_tbl; ent->shift >= 0; ent++)
-               if (xfer_mode >= ent->base && xfer_mode < ent->base + ent->bits)
-                       return 1 << (ent->shift + xfer_mode - ent->base);
-       return 0;
-}
-
-/**
- *     ata_xfer_mode2shift - Find matching xfer_shift for XFER_*
- *     @xfer_mode: XFER_* of interest
- *
- *     Return matching xfer_shift for @xfer_mode.
- *
- *     LOCKING:
- *     None.
- *
- *     RETURNS:
- *     Matching xfer_shift, -1 if no match found.
- */
-static int ata_xfer_mode2shift(unsigned int xfer_mode)
-{
-       const struct ata_xfer_ent *ent;
-
-       for (ent = ata_xfer_tbl; ent->shift >= 0; ent++)
-               if (xfer_mode >= ent->base && xfer_mode < ent->base + ent->bits)
-                       return ent->shift;
-       return -1;
-}
-
-/**
- *     ata_mode_string - convert xfer_mask to string
- *     @xfer_mask: mask of bits supported; only highest bit counts.
- *
- *     Determine string which represents the highest speed
- *     (highest bit in @modemask).
- *
- *     LOCKING:
- *     None.
- *
- *     RETURNS:
- *     Constant C string representing highest speed listed in
- *     @mode_mask, or the constant C string "<n/a>".
- */
-static const char *ata_mode_string(unsigned int xfer_mask)
-{
-       static const char * const xfer_mode_str[] = {
-               "PIO0",
-               "PIO1",
-               "PIO2",
-               "PIO3",
-               "PIO4",
-               "MWDMA0",
-               "MWDMA1",
-               "MWDMA2",
-               "UDMA/16",
-               "UDMA/25",
-               "UDMA/33",
-               "UDMA/44",
-               "UDMA/66",
-               "UDMA/100",
-               "UDMA/133",
-               "UDMA7",
-       };
-       int highbit;
-
-       highbit = fls(xfer_mask) - 1;
-       if (highbit >= 0 && highbit < ARRAY_SIZE(xfer_mode_str))
-               return xfer_mode_str[highbit];
-       return "<n/a>";
-}
-
-static const char *sata_spd_string(unsigned int spd)
-{
-       static const char * const spd_str[] = {
-               "1.5 Gbps",
-               "3.0 Gbps",
-       };
-
-       if (spd == 0 || (spd - 1) >= ARRAY_SIZE(spd_str))
-               return "<unknown>";
-       return spd_str[spd - 1];
-}
-
-void ata_dev_disable(struct ata_device *dev)
-{
-       if (ata_dev_enabled(dev) && ata_msg_drv(dev->ap)) {
-               ata_dev_printk(dev, KERN_WARNING, "disabled\n");
-               dev->class++;
-       }
-}
-
-/**
- *     ata_pio_devchk - PATA device presence detection
- *     @ap: ATA channel to examine
- *     @device: Device to examine (starting at zero)
- *
- *     This technique was originally described in
- *     Hale Landis's ATADRVR (www.ata-atapi.com), and
- *     later found its way into the ATA/ATAPI spec.
- *
- *     Write a pattern to the ATA shadow registers,
- *     and if a device is present, it will respond by
- *     correctly storing and echoing back the
- *     ATA shadow register contents.
- *
- *     LOCKING:
- *     caller.
- */
-
-static unsigned int ata_pio_devchk(struct ata_port *ap,
-                                  unsigned int device)
-{
-       struct ata_ioports *ioaddr = &ap->ioaddr;
-       u8 nsect, lbal;
-
-       ap->ops->dev_select(ap, device);
-
-       outb(0x55, ioaddr->nsect_addr);
-       outb(0xaa, ioaddr->lbal_addr);
-
-       outb(0xaa, ioaddr->nsect_addr);
-       outb(0x55, ioaddr->lbal_addr);
-
-       outb(0x55, ioaddr->nsect_addr);
-       outb(0xaa, ioaddr->lbal_addr);
-
-       nsect = inb(ioaddr->nsect_addr);
-       lbal = inb(ioaddr->lbal_addr);
-
-       if ((nsect == 0x55) && (lbal == 0xaa))
-               return 1;       /* we found a device */
-
-       return 0;               /* nothing found */
-}
-
-/**
- *     ata_mmio_devchk - PATA device presence detection
- *     @ap: ATA channel to examine
- *     @device: Device to examine (starting at zero)
- *
- *     This technique was originally described in
- *     Hale Landis's ATADRVR (www.ata-atapi.com), and
- *     later found its way into the ATA/ATAPI spec.
- *
- *     Write a pattern to the ATA shadow registers,
- *     and if a device is present, it will respond by
- *     correctly storing and echoing back the
- *     ATA shadow register contents.
- *
- *     LOCKING:
- *     caller.
- */
-
-static unsigned int ata_mmio_devchk(struct ata_port *ap,
-                                   unsigned int device)
-{
-       struct ata_ioports *ioaddr = &ap->ioaddr;
-       u8 nsect, lbal;
-
-       ap->ops->dev_select(ap, device);
-
-       writeb(0x55, (void __iomem *) ioaddr->nsect_addr);
-       writeb(0xaa, (void __iomem *) ioaddr->lbal_addr);
-
-       writeb(0xaa, (void __iomem *) ioaddr->nsect_addr);
-       writeb(0x55, (void __iomem *) ioaddr->lbal_addr);
-
-       writeb(0x55, (void __iomem *) ioaddr->nsect_addr);
-       writeb(0xaa, (void __iomem *) ioaddr->lbal_addr);
-
-       nsect = readb((void __iomem *) ioaddr->nsect_addr);
-       lbal = readb((void __iomem *) ioaddr->lbal_addr);
-
-       if ((nsect == 0x55) && (lbal == 0xaa))
-               return 1;       /* we found a device */
-
-       return 0;               /* nothing found */
-}
-
-/**
- *     ata_devchk - PATA device presence detection
- *     @ap: ATA channel to examine
- *     @device: Device to examine (starting at zero)
- *
- *     Dispatch ATA device presence detection, depending
- *     on whether we are using PIO or MMIO to talk to the
- *     ATA shadow registers.
- *
- *     LOCKING:
- *     caller.
- */
-
-static unsigned int ata_devchk(struct ata_port *ap,
-                                   unsigned int device)
-{
-       if (ap->flags & ATA_FLAG_MMIO)
-               return ata_mmio_devchk(ap, device);
-       return ata_pio_devchk(ap, device);
-}
-
-/**
- *     ata_dev_classify - determine device type based on ATA-spec signature
- *     @tf: ATA taskfile register set for device to be identified
- *
- *     Determine from taskfile register contents whether a device is
- *     ATA or ATAPI, as per "Signature and persistence" section
- *     of ATA/PI spec (volume 1, sect 5.14).
- *
- *     LOCKING:
- *     None.
- *
- *     RETURNS:
- *     Device type, %ATA_DEV_ATA, %ATA_DEV_ATAPI, or %ATA_DEV_UNKNOWN
- *     the event of failure.
- */
-
-unsigned int ata_dev_classify(const struct ata_taskfile *tf)
-{
-       /* Apple's open source Darwin code hints that some devices only
-        * put a proper signature into the LBA mid/high registers,
-        * So, we only check those.  It's sufficient for uniqueness.
-        */
-
-       if (((tf->lbam == 0) && (tf->lbah == 0)) ||
-           ((tf->lbam == 0x3c) && (tf->lbah == 0xc3))) {
-               DPRINTK("found ATA device by sig\n");
-               return ATA_DEV_ATA;
-       }
-
-       if (((tf->lbam == 0x14) && (tf->lbah == 0xeb)) ||
-           ((tf->lbam == 0x69) && (tf->lbah == 0x96))) {
-               DPRINTK("found ATAPI device by sig\n");
-               return ATA_DEV_ATAPI;
-       }
-
-       DPRINTK("unknown device\n");
-       return ATA_DEV_UNKNOWN;
-}
-
-/**
- *     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
- *     shadow registers, indicating the results of device detection
- *     and diagnostics.
- *
- *     Select the ATA device, and read the values from the ATA shadow
- *     registers.  Then parse according to the Error register value,
- *     and the spec-defined values examined by ata_dev_classify().
- *
- *     LOCKING:
- *     caller.
- *
- *     RETURNS:
- *     Device type - %ATA_DEV_ATA, %ATA_DEV_ATAPI or %ATA_DEV_NONE.
- */
-
-static unsigned int
-ata_dev_try_classify(struct ata_port *ap, unsigned int device, u8 *r_err)
-{
-       struct ata_taskfile tf;
-       unsigned int class;
-       u8 err;
-
-       ap->ops->dev_select(ap, device);
-
-       memset(&tf, 0, sizeof(tf));
-
-       ap->ops->tf_read(ap, &tf);
-       err = tf.feature;
-       if (r_err)
-               *r_err = err;
-
-       /* see if device passed diags */
-       if (err == 1)
-               /* do nothing */ ;
-       else if ((device == 0) && (err == 0x81))
-               /* do nothing */ ;
-       else
-               return ATA_DEV_NONE;
-
-       /* determine if device is ATA or ATAPI */
-       class = ata_dev_classify(&tf);
-
-       if (class == ATA_DEV_UNKNOWN)
-               return ATA_DEV_NONE;
-       if ((class == ATA_DEV_ATA) && (ata_chk_status(ap) == 0))
-               return ATA_DEV_NONE;
-       return class;
-}
-
-/**
- *     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
- *     @len: length of string to return. must be an even number.
- *
- *     The strings in the IDENTIFY DEVICE page are broken up into
- *     16-bit chunks.  Run through the string, and output each
- *     8-bit chunk linearly, regardless of platform.
- *
- *     LOCKING:
- *     caller.
- */
-
-void ata_id_string(const u16 *id, unsigned char *s,
-                  unsigned int ofs, unsigned int len)
-{
-       unsigned int c;
-
-       while (len > 0) {
-               c = id[ofs] >> 8;
-               *s = c;
-               s++;
-
-               c = id[ofs] & 0xff;
-               *s = c;
-               s++;
-
-               ofs++;
-               len -= 2;
-       }
-}
-
-/**
- *     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
- *     @ap: ATA channel to manipulate
- *     @device: ATA device (numbered from zero) to select
- *
- *     This function performs no actual function.
- *
- *     May be used as the dev_select() entry in ata_port_operations.
- *
- *     LOCKING:
- *     caller.
- */
-void ata_noop_dev_select (struct ata_port *ap, unsigned int device)
-{
-}
-
-
-/**
- *     ata_std_dev_select - Select device 0/1 on ATA bus
- *     @ap: ATA channel to manipulate
- *     @device: ATA device (numbered from zero) to select
- *
- *     Use the method defined in the ATA specification to
- *     make either device 0, or device 1, active on the
- *     ATA channel.  Works with both PIO and MMIO.
- *
- *     May be used as the dev_select() entry in ata_port_operations.
- *
- *     LOCKING:
- *     caller.
- */
-
-void ata_std_dev_select (struct ata_port *ap, unsigned int device)
-{
-       u8 tmp;
-
-       if (device == 0)
-               tmp = ATA_DEVICE_OBS;
-       else
-               tmp = ATA_DEVICE_OBS | ATA_DEV1;
-
-       if (ap->flags & ATA_FLAG_MMIO) {
-               writeb(tmp, (void __iomem *) ap->ioaddr.device_addr);
-       } else {
-               outb(tmp, ap->ioaddr.device_addr);
-       }
-       ata_pause(ap);          /* needed; also flushes, for mmio */
-}
-
-/**
- *     ata_dev_select - Select device 0/1 on ATA bus
- *     @ap: ATA channel to manipulate
- *     @device: ATA device (numbered from zero) to select
- *     @wait: non-zero to wait for Status register BSY bit to clear
- *     @can_sleep: non-zero if context allows sleeping
- *
- *     Use the method defined in the ATA specification to
- *     make either device 0, or device 1, active on the
- *     ATA channel.
- *
- *     This is a high-level version of ata_std_dev_select(),
- *     which additionally provides the services of inserting
- *     the proper pauses and status polling, where needed.
- *
- *     LOCKING:
- *     caller.
- */
-
-void ata_dev_select(struct ata_port *ap, unsigned int device,
-                          unsigned int wait, unsigned int can_sleep)
-{
-       if (ata_msg_probe(ap))
-               ata_port_printk(ap, KERN_INFO, "ata_dev_select: ENTER, ata%u: "
-                               "device %u, wait %u\n", ap->id, device, wait);
-
-       if (wait)
-               ata_wait_idle(ap);
-
-       ap->ops->dev_select(ap, device);
-
-       if (wait) {
-               if (can_sleep && ap->device[device].class == ATA_DEV_ATAPI)
-                       msleep(150);
-               ata_wait_idle(ap);
-       }
-}
-
-/**
- *     ata_dump_id - IDENTIFY DEVICE info debugging output
- *     @id: IDENTIFY DEVICE page to dump
- *
- *     Dump selected 16-bit words from the given IDENTIFY DEVICE
- *     page.
- *
- *     LOCKING:
- *     caller.
- */
-
-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",
-               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",
-               id[80],
-               id[81],
-               id[82],
-               id[83],
-               id[84]);
-       DPRINTK("88==0x%04x  "
-               "93==0x%04x\n",
-               id[88],
-               id[93]);
-}
-
-/**
- *     ata_id_xfermask - Compute xfermask from the given IDENTIFY data
- *     @id: IDENTIFY data to compute xfer mask from
- *
- *     Compute the xfermask for this device. This is not as trivial
- *     as it seems if we must consider early devices correctly.
- *
- *     FIXME: pre IDE drive timing (do we care ?).
- *
- *     LOCKING:
- *     None.
- *
- *     RETURNS:
- *     Computed xfermask
- */
-static unsigned int ata_id_xfermask(const u16 *id)
-{
-       unsigned int pio_mask, mwdma_mask, udma_mask;
-
-       /* Usual case. Word 53 indicates word 64 is valid */
-       if (id[ATA_ID_FIELD_VALID] & (1 << 1)) {
-               pio_mask = id[ATA_ID_PIO_MODES] & 0x03;
-               pio_mask <<= 3;
-               pio_mask |= 0x7;
-       } else {
-               /* If word 64 isn't valid then Word 51 high byte holds
-                * the PIO timing number for the maximum. Turn it into
-                * a mask.
-                */
-               pio_mask = (2 << (id[ATA_ID_OLD_PIO_MODES] & 0xFF)) - 1 ;
-
-               /* But wait.. there's more. Design your standards by
-                * committee and you too can get a free iordy field to
-                * process. However its the speeds not the modes that
-                * are supported... Note drivers using the timing API
-                * will get this right anyway
-                */
-       }
-
-       mwdma_mask = id[ATA_ID_MWDMA_MODES] & 0x07;
-
-       udma_mask = 0;
-       if (id[ATA_ID_FIELD_VALID] & (1 << 2))
-               udma_mask = id[ATA_ID_UDMA_MODES] & 0xff;
-
-       return ata_pack_xfermask(pio_mask, mwdma_mask, udma_mask);
-}
-
-/**
- *     ata_port_queue_task - Queue port_task
- *     @ap: The ata_port to queue port_task for
- *     @fn: workqueue function to be scheduled
- *     @data: data value to pass to workqueue function
- *     @delay: delay time for workqueue function
- *
- *     Schedule @fn(@data) for execution after @delay jiffies using
- *     port_task.  There is one port_task per port and it's the
- *     user(low level driver)'s responsibility to make sure that only
- *     one task is active at any given time.
- *
- *     libata core layer takes care of synchronization between
- *     port_task and EH.  ata_port_queue_task() may be ignored for EH
- *     synchronization.
- *
- *     LOCKING:
- *     Inherited from caller.
- */
-void ata_port_queue_task(struct ata_port *ap, void (*fn)(void *), void *data,
-                        unsigned long delay)
-{
-       int rc;
-
-       if (ap->pflags & ATA_PFLAG_FLUSH_PORT_TASK)
-               return;
-
-       PREPARE_WORK(&ap->port_task, fn, data);
-
-       if (!delay)
-               rc = queue_work(ata_wq, &ap->port_task);
-       else
-               rc = queue_delayed_work(ata_wq, &ap->port_task, delay);
-
-       /* rc == 0 means that another user is using port task */
-       WARN_ON(rc == 0);
-}
-
-/**
- *     ata_port_flush_task - Flush port_task
- *     @ap: The ata_port to flush port_task for
- *
- *     After this function completes, port_task is guranteed not to
- *     be running or scheduled.
- *
- *     LOCKING:
- *     Kernel thread context (may sleep)
- */
-void ata_port_flush_task(struct ata_port *ap)
-{
-       unsigned long flags;
-
-       DPRINTK("ENTER\n");
-
-       spin_lock_irqsave(ap->lock, flags);
-       ap->pflags |= ATA_PFLAG_FLUSH_PORT_TASK;
-       spin_unlock_irqrestore(ap->lock, flags);
-
-       DPRINTK("flush #1\n");
-       flush_workqueue(ata_wq);
-
-       /*
-        * At this point, if a task is running, it's guaranteed to see
-        * the FLUSH flag; thus, it will never queue pio tasks again.
-        * Cancel and flush.
-        */
-       if (!cancel_delayed_work(&ap->port_task)) {
-               if (ata_msg_ctl(ap))
-                       ata_port_printk(ap, KERN_DEBUG, "%s: flush #2\n",
-                                       __FUNCTION__);
-               flush_workqueue(ata_wq);
-       }
-
-       spin_lock_irqsave(ap->lock, flags);
-       ap->pflags &= ~ATA_PFLAG_FLUSH_PORT_TASK;
-       spin_unlock_irqrestore(ap->lock, flags);
-
-       if (ata_msg_ctl(ap))
-               ata_port_printk(ap, KERN_DEBUG, "%s: EXIT\n", __FUNCTION__);
-}
-
-void ata_qc_complete_internal(struct ata_queued_cmd *qc)
-{
-       struct completion *waiting = qc->private_data;
-
-       complete(waiting);
-}
-
-/**
- *     ata_exec_internal - execute libata internal command
- *     @dev: Device to which the command is sent
- *     @tf: Taskfile registers for the command and the result
- *     @cdb: CDB for packet command
- *     @dma_dir: Data tranfer direction of the command
- *     @buf: Data buffer of the command
- *     @buflen: Length of data buffer
- *
- *     Executes libata internal command with timeout.  @tf contains
- *     command on entry and result on return.  Timeout and error
- *     conditions are reported via return value.  No recovery action
- *     is taken after a command times out.  It's caller's duty to
- *     clean up after timeout.
- *
- *     LOCKING:
- *     None.  Should be called with kernel context, might sleep.
- *
- *     RETURNS:
- *     Zero on success, AC_ERR_* mask on failure
- */
-unsigned ata_exec_internal(struct ata_device *dev,
-                          struct ata_taskfile *tf, const u8 *cdb,
-                          int dma_dir, void *buf, unsigned int buflen)
-{
-       struct ata_port *ap = dev->ap;
-       u8 command = tf->command;
-       struct ata_queued_cmd *qc;
-       unsigned int tag, preempted_tag;
-       u32 preempted_sactive, preempted_qc_active;
-       DECLARE_COMPLETION_ONSTACK(wait);
-       unsigned long flags;
-       unsigned int err_mask;
-       int rc;
-
-       spin_lock_irqsave(ap->lock, flags);
-
-       /* no internal command while frozen */
-       if (ap->pflags & ATA_PFLAG_FROZEN) {
-               spin_unlock_irqrestore(ap->lock, flags);
-               return AC_ERR_SYSTEM;
-       }
-
-       /* initialize internal qc */
-
-       /* XXX: Tag 0 is used for drivers with legacy EH as some
-        * drivers choke if any other tag is given.  This breaks
-        * ata_tag_internal() test for those drivers.  Don't use new
-        * EH stuff without converting to it.
-        */
-       if (ap->ops->error_handler)
-               tag = ATA_TAG_INTERNAL;
-       else
-               tag = 0;
-
-       if (test_and_set_bit(tag, &ap->qc_allocated))
-               BUG();
-       qc = __ata_qc_from_tag(ap, tag);
-
-       qc->tag = tag;
-       qc->scsicmd = NULL;
-       qc->ap = ap;
-       qc->dev = dev;
-       ata_qc_reinit(qc);
-
-       preempted_tag = ap->active_tag;
-       preempted_sactive = ap->sactive;
-       preempted_qc_active = ap->qc_active;
-       ap->active_tag = ATA_TAG_POISON;
-       ap->sactive = 0;
-       ap->qc_active = 0;
-
-       /* prepare & issue qc */
-       qc->tf = *tf;
-       if (cdb)
-               memcpy(qc->cdb, cdb, ATAPI_CDB_LEN);
-       qc->flags |= ATA_QCFLAG_RESULT_TF;
-       qc->dma_dir = dma_dir;
-       if (dma_dir != DMA_NONE) {
-               ata_sg_init_one(qc, buf, buflen);
-               qc->nsect = buflen / ATA_SECT_SIZE;
-       }
-
-       qc->private_data = &wait;
-       qc->complete_fn = ata_qc_complete_internal;
-
-       ata_qc_issue(qc);
-
-       spin_unlock_irqrestore(ap->lock, flags);
-
-       rc = wait_for_completion_timeout(&wait, ata_probe_timeout);
-
-       ata_port_flush_task(ap);
-
-       if (!rc) {
-               spin_lock_irqsave(ap->lock, flags);
-
-               /* We're racing with irq here.  If we lose, the
-                * following test prevents us from completing the qc
-                * twice.  If we win, the port is frozen and will be
-                * cleaned up by ->post_internal_cmd().
-                */
-               if (qc->flags & ATA_QCFLAG_ACTIVE) {
-                       qc->err_mask |= AC_ERR_TIMEOUT;
-
-                       if (ap->ops->error_handler)
-                               ata_port_freeze(ap);
-                       else
-                               ata_qc_complete(qc);
-
-                       if (ata_msg_warn(ap))
-                               ata_dev_printk(dev, KERN_WARNING,
-                                       "qc timeout (cmd 0x%x)\n", command);
-               }
-
-               spin_unlock_irqrestore(ap->lock, flags);
-       }
-
-       /* do post_internal_cmd */
-       if (ap->ops->post_internal_cmd)
-               ap->ops->post_internal_cmd(qc);
-
-       if (qc->flags & ATA_QCFLAG_FAILED && !qc->err_mask) {
-               if (ata_msg_warn(ap))
-                       ata_dev_printk(dev, KERN_WARNING,
-                               "zero err_mask for failed "
-                               "internal command, assuming AC_ERR_OTHER\n");
-               qc->err_mask |= AC_ERR_OTHER;
-       }
-
-       /* finish up */
-       spin_lock_irqsave(ap->lock, flags);
-
-       *tf = qc->result_tf;
-       err_mask = qc->err_mask;
-
-       ata_qc_free(qc);
-       ap->active_tag = preempted_tag;
-       ap->sactive = preempted_sactive;
-       ap->qc_active = preempted_qc_active;
-
-       /* XXX - Some LLDDs (sata_mv) disable port on command failure.
-        * Until those drivers are fixed, we detect the condition
-        * here, fail the command with AC_ERR_SYSTEM and reenable the
-        * port.
-        *
-        * Note that this doesn't change any behavior as internal
-        * command failure results in disabling the device in the
-        * higher layer for LLDDs without new reset/EH callbacks.
-        *
-        * Kill the following code as soon as those drivers are fixed.
-        */
-       if (ap->flags & ATA_FLAG_DISABLED) {
-               err_mask |= AC_ERR_SYSTEM;
-               ata_port_probe(ap);
-       }
-
-       spin_unlock_irqrestore(ap->lock, flags);
-
-       return err_mask;
-}
-
-/**
- *     ata_do_simple_cmd - execute simple internal command
- *     @dev: Device to which the command is sent
- *     @cmd: Opcode to execute
- *
- *     Execute a 'simple' command, that only consists of the opcode
- *     'cmd' itself, without filling any other registers
- *
- *     LOCKING:
- *     Kernel thread context (may sleep).
- *
- *     RETURNS:
- *     Zero on success, AC_ERR_* mask on failure
- */
-unsigned int ata_do_simple_cmd(struct ata_device *dev, u8 cmd)
-{
-       struct ata_taskfile tf;
-
-       ata_tf_init(dev, &tf);
-
-       tf.command = cmd;
-       tf.flags |= ATA_TFLAG_DEVICE;
-       tf.protocol = ATA_PROT_NODATA;
-
-       return ata_exec_internal(dev, &tf, NULL, DMA_NONE, NULL, 0);
-}
-
-/**
- *     ata_pio_need_iordy      -       check if iordy needed
- *     @adev: ATA device
- *
- *     Check if the current speed of the device requires IORDY. Used
- *     by various controllers for chip configuration.
- */
-
-unsigned int ata_pio_need_iordy(const struct ata_device *adev)
-{
-       int pio;
-       int speed = adev->pio_mode - XFER_PIO_0;
-
-       if (speed < 2)
-               return 0;
-       if (speed > 2)
-               return 1;
-
-       /* If we have no drive specific rule, then PIO 2 is non IORDY */
-
-       if (adev->id[ATA_ID_FIELD_VALID] & 2) { /* EIDE */
-               pio = adev->id[ATA_ID_EIDE_PIO];
-               /* Is the speed faster than the drive allows non IORDY ? */
-               if (pio) {
-                       /* This is cycle times not frequency - watch the logic! */
-                       if (pio > 240)  /* PIO2 is 240nS per cycle */
-                               return 1;
-                       return 0;
-               }
-       }
-       return 0;
-}
-
-/**
- *     ata_dev_read_id - Read ID data from the specified device
- *     @dev: target device
- *     @p_class: pointer to class of the target device (may be changed)
- *     @post_reset: is this read ID post-reset?
- *     @id: buffer to read IDENTIFY data into
- *
- *     Read ID data from the specified device.  ATA_CMD_ID_ATA is
- *     performed on ATA devices and ATA_CMD_ID_ATAPI on ATAPI
- *     devices.  This function also issues ATA_CMD_INIT_DEV_PARAMS
- *     for pre-ATA4 drives.
- *
- *     LOCKING:
- *     Kernel thread context (may sleep)
- *
- *     RETURNS:
- *     0 on success, -errno otherwise.
- */
-int ata_dev_read_id(struct ata_device *dev, unsigned int *p_class,
-                   int post_reset, u16 *id)
-{
-       struct ata_port *ap = dev->ap;
-       unsigned int class = *p_class;
-       struct ata_taskfile tf;
-       unsigned int err_mask = 0;
-       const char *reason;
-       int rc;
-
-       if (ata_msg_ctl(ap))
-               ata_dev_printk(dev, KERN_DEBUG, "%s: ENTER, host %u, dev %u\n",
-                              __FUNCTION__, ap->id, dev->devno);
-
-       ata_dev_select(ap, dev->devno, 1, 1); /* select device 0/1 */
-
- retry:
-       ata_tf_init(dev, &tf);
-
-       switch (class) {
-       case ATA_DEV_ATA:
-               tf.command = ATA_CMD_ID_ATA;
-               break;
-       case ATA_DEV_ATAPI:
-               tf.command = ATA_CMD_ID_ATAPI;
-               break;
-       default:
-               rc = -ENODEV;
-               reason = "unsupported class";
-               goto err_out;
-       }
-
-       tf.protocol = ATA_PROT_PIO;
-
-       err_mask = ata_exec_internal(dev, &tf, NULL, DMA_FROM_DEVICE,
-                                    id, sizeof(id[0]) * ATA_ID_WORDS);
-       if (err_mask) {
-               rc = -EIO;
-               reason = "I/O error";
-               goto err_out;
-       }
-
-       swap_buf_le16(id, ATA_ID_WORDS);
-
-       /* sanity check */
-       if ((class == ATA_DEV_ATA) != (ata_id_is_ata(id) | ata_id_is_cfa(id))) {
-               rc = -EINVAL;
-               reason = "device reports illegal type";
-               goto err_out;
-       }
-
-       if (post_reset && class == ATA_DEV_ATA) {
-               /*
-                * The exact sequence expected by certain pre-ATA4 drives is:
-                * SRST RESET
-                * IDENTIFY
-                * INITIALIZE DEVICE PARAMETERS
-                * anything else..
-                * Some drives were very specific about that exact sequence.
-                */
-               if (ata_id_major_version(id) < 4 || !ata_id_has_lba(id)) {
-                       err_mask = ata_dev_init_params(dev, id[3], id[6]);
-                       if (err_mask) {
-                               rc = -EIO;
-                               reason = "INIT_DEV_PARAMS failed";
-                               goto err_out;
-                       }
-
-                       /* current CHS translation info (id[53-58]) might be
-                        * changed. reread the identify device info.
-                        */
-                       post_reset = 0;
-                       goto retry;
-               }
-       }
-
-       *p_class = class;
-
-       return 0;
-
- err_out:
-       if (ata_msg_warn(ap))
-               ata_dev_printk(dev, KERN_WARNING, "failed to IDENTIFY "
-                              "(%s, err_mask=0x%x)\n", reason, err_mask);
-       return rc;
-}
-
-static inline u8 ata_dev_knobble(struct ata_device *dev)
-{
-       return ((dev->ap->cbl == ATA_CBL_SATA) && (!ata_id_is_sata(dev->id)));
-}
-
-static void ata_dev_config_ncq(struct ata_device *dev,
-                              char *desc, size_t desc_sz)
-{
-       struct ata_port *ap = dev->ap;
-       int hdepth = 0, ddepth = ata_id_queue_depth(dev->id);
-
-       if (!ata_id_has_ncq(dev->id)) {
-               desc[0] = '\0';
-               return;
-       }
-
-       if (ap->flags & ATA_FLAG_NCQ) {
-               hdepth = min(ap->host->can_queue, ATA_MAX_QUEUE - 1);
-               dev->flags |= ATA_DFLAG_NCQ;
-       }
-
-       if (hdepth >= ddepth)
-               snprintf(desc, desc_sz, "NCQ (depth %d)", ddepth);
-       else
-               snprintf(desc, desc_sz, "NCQ (depth %d/%d)", hdepth, ddepth);
-}
-
-static void ata_set_port_max_cmd_len(struct ata_port *ap)
-{
-       int i;
-
-       if (ap->host) {
-               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);
-       }
-}
-
-/**
- *     ata_dev_configure - Configure the specified ATA/ATAPI device
- *     @dev: Target device to configure
- *     @print_info: Enable device info printout
- *
- *     Configure @dev according to @dev->id.  Generic and low-level
- *     driver specific fixups are also applied.
- *
- *     LOCKING:
- *     Kernel thread context (may sleep)
- *
- *     RETURNS:
- *     0 on success, -errno otherwise
- */
-int ata_dev_configure(struct ata_device *dev, int print_info)
-{
-       struct ata_port *ap = dev->ap;
-       const u16 *id = dev->id;
-       unsigned int xfer_mask;
-       int rc;
-
-       if (!ata_dev_enabled(dev) && ata_msg_info(ap)) {
-               ata_dev_printk(dev, KERN_INFO,
-                              "%s: ENTER/EXIT (host %u, dev %u) -- nodev\n",
-                              __FUNCTION__, ap->id, dev->devno);
-               return 0;
-       }
-
-       if (ata_msg_probe(ap))
-               ata_dev_printk(dev, KERN_DEBUG, "%s: ENTER, host %u, dev %u\n",
-                              __FUNCTION__, ap->id, dev->devno);
-
-       /* print device capabilities */
-       if (ata_msg_probe(ap))
-               ata_dev_printk(dev, KERN_DEBUG,
-                              "%s: cfg 49:%04x 82:%04x 83:%04x 84:%04x "
-                              "85:%04x 86:%04x 87:%04x 88:%04x\n",
-                              __FUNCTION__,
-                              id[49], id[82], id[83], id[84],
-                              id[85], id[86], id[87], id[88]);
-
-       /* initialize to-be-configured parameters */
-       dev->flags &= ~ATA_DFLAG_CFG_MASK;
-       dev->max_sectors = 0;
-       dev->cdb_len = 0;
-       dev->n_sectors = 0;
-       dev->cylinders = 0;
-       dev->heads = 0;
-       dev->sectors = 0;
-
-       /*
-        * common ATA, ATAPI feature tests
-        */
-
-       /* find max transfer mode; for printk only */
-       xfer_mask = ata_id_xfermask(id);
-
-       if (ata_msg_probe(ap))
-               ata_dump_id(id);
-
-       /* ATA-specific feature tests */
-       if (dev->class == ATA_DEV_ATA) {
-               dev->n_sectors = ata_id_n_sectors(id);
-
-               if (ata_id_has_lba(id)) {
-                       const char *lba_desc;
-                       char ncq_desc[20];
-
-                       lba_desc = "LBA";
-                       dev->flags |= ATA_DFLAG_LBA;
-                       if (ata_id_has_lba48(id)) {
-                               dev->flags |= ATA_DFLAG_LBA48;
-                               lba_desc = "LBA48";
-                       }
-
-                       /* config NCQ */
-                       ata_dev_config_ncq(dev, ncq_desc, sizeof(ncq_desc));
-
-                       /* print device info to dmesg */
-                       if (ata_msg_drv(ap) && print_info)
-                               ata_dev_printk(dev, KERN_INFO, "ATA-%d, "
-                                       "max %s, %Lu sectors: %s %s\n",
-                                       ata_id_major_version(id),
-                                       ata_mode_string(xfer_mask),
-                                       (unsigned long long)dev->n_sectors,
-                                       lba_desc, ncq_desc);
-               } else {
-                       /* CHS */
-
-                       /* Default translation */
-                       dev->cylinders  = id[1];
-                       dev->heads      = id[3];
-                       dev->sectors    = id[6];
-
-                       if (ata_id_current_chs_valid(id)) {
-                               /* Current CHS translation is valid. */
-                               dev->cylinders = id[54];
-                               dev->heads     = id[55];
-                               dev->sectors   = id[56];
-                       }
-
-                       /* print device info to dmesg */
-                       if (ata_msg_drv(ap) && print_info)
-                               ata_dev_printk(dev, KERN_INFO, "ATA-%d, "
-                                       "max %s, %Lu sectors: CHS %u/%u/%u\n",
-                                       ata_id_major_version(id),
-                                       ata_mode_string(xfer_mask),
-                                       (unsigned long long)dev->n_sectors,
-                                       dev->cylinders, dev->heads,
-                                       dev->sectors);
-               }
-
-               if (dev->id[59] & 0x100) {
-                       dev->multi_count = dev->id[59] & 0xff;
-                       if (ata_msg_drv(ap) && print_info)
-                               ata_dev_printk(dev, KERN_INFO,
-                                       "ata%u: dev %u multi count %u\n",
-                                       ap->id, dev->devno, dev->multi_count);
-               }
-
-               dev->cdb_len = 16;
-       }
-
-       /* ATAPI-specific feature tests */
-       else if (dev->class == ATA_DEV_ATAPI) {
-               char *cdb_intr_string = "";
-
-               rc = atapi_cdb_len(id);
-               if ((rc < 12) || (rc > ATAPI_CDB_LEN)) {
-                       if (ata_msg_warn(ap))
-                               ata_dev_printk(dev, KERN_WARNING,
-                                              "unsupported CDB len\n");
-                       rc = -EINVAL;
-                       goto err_out_nosup;
-               }
-               dev->cdb_len = (unsigned int) rc;
-
-               if (ata_id_cdb_intr(dev->id)) {
-                       dev->flags |= ATA_DFLAG_CDB_INTR;
-                       cdb_intr_string = ", CDB intr";
-               }
-
-               /* print device info to dmesg */
-               if (ata_msg_drv(ap) && print_info)
-                       ata_dev_printk(dev, KERN_INFO, "ATAPI, max %s%s\n",
-                                      ata_mode_string(xfer_mask),
-                                      cdb_intr_string);
-       }
-
-       ata_set_port_max_cmd_len(ap);
-
-       /* limit bridge transfers to udma5, 200 sectors */
-       if (ata_dev_knobble(dev)) {
-               if (ata_msg_drv(ap) && print_info)
-                       ata_dev_printk(dev, KERN_INFO,
-                                      "applying bridge limits\n");
-               dev->udma_mask &= ATA_UDMA5;
-               dev->max_sectors = ATA_MAX_SECTORS;
-       }
-
-       if (ap->ops->dev_config)
-               ap->ops->dev_config(ap, dev);
-
-       if (ata_msg_probe(ap))
-               ata_dev_printk(dev, KERN_DEBUG, "%s: EXIT, drv_stat = 0x%x\n",
-                       __FUNCTION__, ata_chk_status(ap));
-       return 0;
-
-err_out_nosup:
-       if (ata_msg_probe(ap))
-               ata_dev_printk(dev, KERN_DEBUG,
-                              "%s: EXIT, err\n", __FUNCTION__);
-       return rc;
-}
-
-/**
- *     ata_bus_probe - Reset and probe ATA bus
- *     @ap: Bus to probe
- *
- *     Master ATA bus probing function.  Initiates a hardware-dependent
- *     bus reset, then attempts to identify any devices found on
- *     the bus.
- *
- *     LOCKING:
- *     PCI/etc. bus probe sem.
- *
- *     RETURNS:
- *     Zero on success, negative errno otherwise.
- */
-
-int ata_bus_probe(struct ata_port *ap)
-{
-       unsigned int classes[ATA_MAX_DEVICES];
-       int tries[ATA_MAX_DEVICES];
-       int i, rc, down_xfermask;
-       struct ata_device *dev;
-
-       ata_port_probe(ap);
-
-       for (i = 0; i < ATA_MAX_DEVICES; i++)
-               tries[i] = ATA_PROBE_MAX_TRIES;
-
- retry:
-       down_xfermask = 0;
-
-       /* reset and determine device classes */
-       ap->ops->phy_reset(ap);
-
-       for (i = 0; i < ATA_MAX_DEVICES; i++) {
-               dev = &ap->device[i];
-
-               if (!(ap->flags & ATA_FLAG_DISABLED) &&
-                   dev->class != ATA_DEV_UNKNOWN)
-                       classes[dev->devno] = dev->class;
-               else
-                       classes[dev->devno] = ATA_DEV_NONE;
-
-               dev->class = ATA_DEV_UNKNOWN;
-       }
-
-       ata_port_probe(ap);
-
-       /* after the reset the device state is PIO 0 and the controller
-          state is undefined. Record the mode */
-
-       for (i = 0; i < ATA_MAX_DEVICES; i++)
-               ap->device[i].pio_mode = XFER_PIO_0;
-
-       /* read IDENTIFY page and configure devices */
-       for (i = 0; i < ATA_MAX_DEVICES; i++) {
-               dev = &ap->device[i];
-
-               if (tries[i])
-                       dev->class = classes[i];
-
-               if (!ata_dev_enabled(dev))
-                       continue;
-
-               rc = ata_dev_read_id(dev, &dev->class, 1, dev->id);
-               if (rc)
-                       goto fail;
-
-               rc = ata_dev_configure(dev, 1);
-               if (rc)
-                       goto fail;
-       }
-
-       /* configure transfer mode */
-       rc = ata_set_mode(ap, &dev);
-       if (rc) {
-               down_xfermask = 1;
-               goto fail;
-       }
-
-       for (i = 0; i < ATA_MAX_DEVICES; i++)
-               if (ata_dev_enabled(&ap->device[i]))
-                       return 0;
-
-       /* no device present, disable port */
-       ata_port_disable(ap);
-       ap->ops->port_disable(ap);
-       return -ENODEV;
-
- fail:
-       switch (rc) {
-       case -EINVAL:
-       case -ENODEV:
-               tries[dev->devno] = 0;
-               break;
-       case -EIO:
-               sata_down_spd_limit(ap);
-               /* fall through */
-       default:
-               tries[dev->devno]--;
-               if (down_xfermask &&
-                   ata_down_xfermask_limit(dev, tries[dev->devno] == 1))
-                       tries[dev->devno] = 0;
-       }
-
-       if (!tries[dev->devno]) {
-               ata_down_xfermask_limit(dev, 1);
-               ata_dev_disable(dev);
-       }
-
-       goto retry;
-}
-
-/**
- *     ata_port_probe - Mark port as enabled
- *     @ap: Port for which we indicate enablement
- *
- *     Modify @ap data structure such that the system
- *     thinks that the entire port is enabled.
- *
- *     LOCKING: host_set lock, or some other form of
- *     serialization.
- */
-
-void ata_port_probe(struct ata_port *ap)
-{
-       ap->flags &= ~ATA_FLAG_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, scontrol, tmp;
-
-       if (sata_scr_read(ap, SCR_STATUS, &sstatus))
-               return;
-       sata_scr_read(ap, SCR_CONTROL, &scontrol);
-
-       if (ata_port_online(ap)) {
-               tmp = (sstatus >> 4) & 0xf;
-               ata_port_printk(ap, KERN_INFO,
-                               "SATA link up %s (SStatus %X SControl %X)\n",
-                               sata_spd_string(tmp), sstatus, scontrol);
-       } else {
-               ata_port_printk(ap, KERN_INFO,
-                               "SATA link down (SStatus %X SControl %X)\n",
-                               sstatus, scontrol);
-       }
-}
-
-/**
- *     __sata_phy_reset - Wake/reset a low-level SATA PHY
- *     @ap: SATA port associated with target SATA PHY.
- *
- *     This function issues commands to standard SATA Sxxx
- *     PHY registers, to wake up the phy (and device), and
- *     clear any reset condition.
- *
- *     LOCKING:
- *     PCI/etc. bus probe sem.
- *
- */
-void __sata_phy_reset(struct ata_port *ap)
-{
-       u32 sstatus;
-       unsigned long timeout = jiffies + (HZ * 5);
-
-       if (ap->flags & ATA_FLAG_SATA_RESET) {
-               /* issue phy wake/reset */
-               sata_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. */
-               mdelay(1);
-       }
-       /* phy wake/clear reset */
-       sata_scr_write_flush(ap, SCR_CONTROL, 0x300);
-
-       /* wait for phy to become ready, if necessary */
-       do {
-               msleep(200);
-               sata_scr_read(ap, SCR_STATUS, &sstatus);
-               if ((sstatus & 0xf) != 1)
-                       break;
-       } while (time_before(jiffies, timeout));
-
-       /* print link status */
-       sata_print_link_status(ap);
-
-       /* TODO: phy layer with polling, timeouts, etc. */
-       if (!ata_port_offline(ap))
-               ata_port_probe(ap);
-       else
-               ata_port_disable(ap);
-
-       if (ap->flags & ATA_FLAG_DISABLED)
-               return;
-
-       if (ata_busy_sleep(ap, ATA_TMOUT_BOOT_QUICK, ATA_TMOUT_BOOT)) {
-               ata_port_disable(ap);
-               return;
-       }
-
-       ap->cbl = ATA_CBL_SATA;
-}
-
-/**
- *     sata_phy_reset - Reset SATA bus.
- *     @ap: SATA port associated with target SATA PHY.
- *
- *     This function resets the SATA bus, and then probes
- *     the bus for devices.
- *
- *     LOCKING:
- *     PCI/etc. bus probe sem.
- *
- */
-void sata_phy_reset(struct ata_port *ap)
-{
-       __sata_phy_reset(ap);
-       if (ap->flags & ATA_FLAG_DISABLED)
-               return;
-       ata_bus_reset(ap);
-}
-
-/**
- *     ata_dev_pair            -       return other device on cable
- *     @adev: device
- *
- *     Obtain the other device on the same cable, or if none is
- *     present NULL is returned
- */
-
-struct ata_device *ata_dev_pair(struct ata_device *adev)
-{
-       struct ata_port *ap = adev->ap;
-       struct ata_device *pair = &ap->device[1 - adev->devno];
-       if (!ata_dev_enabled(pair))
-               return NULL;
-       return pair;
-}
-
-/**
- *     ata_port_disable - Disable port.
- *     @ap: Port to be disabled.
- *
- *     Modify @ap data structure such that the system
- *     thinks that the entire port is disabled, and should
- *     never attempt to probe or communicate with devices
- *     on this port.
- *
- *     LOCKING: host_set lock, or some other form of
- *     serialization.
- */
-
-void ata_port_disable(struct ata_port *ap)
-{
-       ap->device[0].class = ATA_DEV_NONE;
-       ap->device[1].class = ATA_DEV_NONE;
-       ap->flags |= ATA_FLAG_DISABLED;
-}
-
-/**
- *     sata_down_spd_limit - adjust SATA spd limit downward
- *     @ap: Port to adjust SATA spd limit for
- *
- *     Adjust SATA spd limit of @ap downward.  Note that this
- *     function only adjusts the limit.  The change must be applied
- *     using sata_set_spd().
- *
- *     LOCKING:
- *     Inherited from caller.
- *
- *     RETURNS:
- *     0 on success, negative errno on failure
- */
-int sata_down_spd_limit(struct ata_port *ap)
-{
-       u32 sstatus, spd, mask;
-       int rc, highbit;
-
-       rc = sata_scr_read(ap, SCR_STATUS, &sstatus);
-       if (rc)
-               return rc;
-
-       mask = ap->sata_spd_limit;
-       if (mask <= 1)
-               return -EINVAL;
-       highbit = fls(mask) - 1;
-       mask &= ~(1 << highbit);
-
-       spd = (sstatus >> 4) & 0xf;
-       if (spd <= 1)
-               return -EINVAL;
-       spd--;
-       mask &= (1 << spd) - 1;
-       if (!mask)
-               return -EINVAL;
-
-       ap->sata_spd_limit = mask;
-
-       ata_port_printk(ap, KERN_WARNING, "limiting SATA link speed to %s\n",
-                       sata_spd_string(fls(mask)));
-
-       return 0;
-}
-
-static int __sata_set_spd_needed(struct ata_port *ap, u32 *scontrol)
-{
-       u32 spd, limit;
-
-       if (ap->sata_spd_limit == UINT_MAX)
-               limit = 0;
-       else
-               limit = fls(ap->sata_spd_limit);
-
-       spd = (*scontrol >> 4) & 0xf;
-       *scontrol = (*scontrol & ~0xf0) | ((limit & 0xf) << 4);
-
-       return spd != limit;
-}
-
-/**
- *     sata_set_spd_needed - is SATA spd configuration needed
- *     @ap: Port in question
- *
- *     Test whether the spd limit in SControl matches
- *     @ap->sata_spd_limit.  This function is used to determine
- *     whether hardreset is necessary to apply SATA spd
- *     configuration.
- *
- *     LOCKING:
- *     Inherited from caller.
- *
- *     RETURNS:
- *     1 if SATA spd configuration is needed, 0 otherwise.
- */
-int sata_set_spd_needed(struct ata_port *ap)
-{
-       u32 scontrol;
-
-       if (sata_scr_read(ap, SCR_CONTROL, &scontrol))
-               return 0;
-
-       return __sata_set_spd_needed(ap, &scontrol);
-}
-
-/**
- *     sata_set_spd - set SATA spd according to spd limit
- *     @ap: Port to set SATA spd for
- *
- *     Set SATA spd of @ap according to sata_spd_limit.
- *
- *     LOCKING:
- *     Inherited from caller.
- *
- *     RETURNS:
- *     0 if spd doesn't need to be changed, 1 if spd has been
- *     changed.  Negative errno if SCR registers are inaccessible.
- */
-int sata_set_spd(struct ata_port *ap)
-{
-       u32 scontrol;
-       int rc;
-
-       if ((rc = sata_scr_read(ap, SCR_CONTROL, &scontrol)))
-               return rc;
-
-       if (!__sata_set_spd_needed(ap, &scontrol))
-               return 0;
-
-       if ((rc = sata_scr_write(ap, SCR_CONTROL, scontrol)))
-               return rc;
-
-       return 1;
-}
-
-/*
- * This mode timing computation functionality is ported over from
- * drivers/ide/ide-timing.h and was originally written by Vojtech Pavlik
- */
-/*
- * PIO 0-5, MWDMA 0-2 and UDMA 0-6 timings (in nanoseconds).
- * These were taken from ATA/ATAPI-6 standard, rev 0a, except
- * for PIO 5, which is a nonstandard extension and UDMA6, which
- * is currently supported only by Maxtor drives.
- */
-
-static const struct ata_timing ata_timing[] = {
-
-       { XFER_UDMA_6,     0,   0,   0,   0,   0,   0,   0,  15 },
-       { XFER_UDMA_5,     0,   0,   0,   0,   0,   0,   0,  20 },
-       { XFER_UDMA_4,     0,   0,   0,   0,   0,   0,   0,  30 },
-       { XFER_UDMA_3,     0,   0,   0,   0,   0,   0,   0,  45 },
-
-       { XFER_UDMA_2,     0,   0,   0,   0,   0,   0,   0,  60 },
-       { XFER_UDMA_1,     0,   0,   0,   0,   0,   0,   0,  80 },
-       { XFER_UDMA_0,     0,   0,   0,   0,   0,   0,   0, 120 },
-
-/*     { XFER_UDMA_SLOW,  0,   0,   0,   0,   0,   0,   0, 150 }, */
-
-       { XFER_MW_DMA_2,  25,   0,   0,   0,  70,  25, 120,   0 },
-       { XFER_MW_DMA_1,  45,   0,   0,   0,  80,  50, 150,   0 },
-       { XFER_MW_DMA_0,  60,   0,   0,   0, 215, 215, 480,   0 },
-
-       { XFER_SW_DMA_2,  60,   0,   0,   0, 120, 120, 240,   0 },
-       { XFER_SW_DMA_1,  90,   0,   0,   0, 240, 240, 480,   0 },
-       { XFER_SW_DMA_0, 120,   0,   0,   0, 480, 480, 960,   0 },
-
-/*     { XFER_PIO_5,     20,  50,  30, 100,  50,  30, 100,   0 }, */
-       { XFER_PIO_4,     25,  70,  25, 120,  70,  25, 120,   0 },
-       { XFER_PIO_3,     30,  80,  70, 180,  80,  70, 180,   0 },
-
-       { XFER_PIO_2,     30, 290,  40, 330, 100,  90, 240,   0 },
-       { XFER_PIO_1,     50, 290,  93, 383, 125, 100, 383,   0 },
-       { XFER_PIO_0,     70, 290, 240, 600, 165, 150, 600,   0 },
-
-/*     { XFER_PIO_SLOW, 120, 290, 240, 960, 290, 240, 960,   0 }, */
-
-       { 0xFF }
-};
-
-#define ENOUGH(v,unit)         (((v)-1)/(unit)+1)
-#define EZ(v,unit)             ((v)?ENOUGH(v,unit):0)
-
-static void ata_timing_quantize(const struct ata_timing *t, struct ata_timing *q, int T, int UT)
-{
-       q->setup   = EZ(t->setup   * 1000,  T);
-       q->act8b   = EZ(t->act8b   * 1000,  T);
-       q->rec8b   = EZ(t->rec8b   * 1000,  T);
-       q->cyc8b   = EZ(t->cyc8b   * 1000,  T);
-       q->active  = EZ(t->active  * 1000,  T);
-       q->recover = EZ(t->recover * 1000,  T);
-       q->cycle   = EZ(t->cycle   * 1000,  T);
-       q->udma    = EZ(t->udma    * 1000, UT);
-}
-
-void ata_timing_merge(const struct ata_timing *a, const struct ata_timing *b,
-                     struct ata_timing *m, unsigned int what)
-{
-       if (what & ATA_TIMING_SETUP  ) m->setup   = max(a->setup,   b->setup);
-       if (what & ATA_TIMING_ACT8B  ) m->act8b   = max(a->act8b,   b->act8b);
-       if (what & ATA_TIMING_REC8B  ) m->rec8b   = max(a->rec8b,   b->rec8b);
-       if (what & ATA_TIMING_CYC8B  ) m->cyc8b   = max(a->cyc8b,   b->cyc8b);
-       if (what & ATA_TIMING_ACTIVE ) m->active  = max(a->active,  b->active);
-       if (what & ATA_TIMING_RECOVER) m->recover = max(a->recover, b->recover);
-       if (what & ATA_TIMING_CYCLE  ) m->cycle   = max(a->cycle,   b->cycle);
-       if (what & ATA_TIMING_UDMA   ) m->udma    = max(a->udma,    b->udma);
-}
-
-static const struct ata_timing* ata_timing_find_mode(unsigned short speed)
-{
-       const struct ata_timing *t;
-
-       for (t = ata_timing; t->mode != speed; t++)
-               if (t->mode == 0xFF)
-                       return NULL;
-       return t;
-}
-
-int ata_timing_compute(struct ata_device *adev, unsigned short speed,
-                      struct ata_timing *t, int T, int UT)
-{
-       const struct ata_timing *s;
-       struct ata_timing p;
-
-       /*
-        * Find the mode.
-        */
-
-       if (!(s = ata_timing_find_mode(speed)))
-               return -EINVAL;
-
-       memcpy(t, s, sizeof(*s));
-
-       /*
-        * If the drive is an EIDE drive, it can tell us it needs extended
-        * PIO/MW_DMA cycle timing.
-        */
-
-       if (adev->id[ATA_ID_FIELD_VALID] & 2) { /* EIDE drive */
-               memset(&p, 0, sizeof(p));
-               if(speed >= XFER_PIO_0 && speed <= XFER_SW_DMA_0) {
-                       if (speed <= XFER_PIO_2) p.cycle = p.cyc8b = adev->id[ATA_ID_EIDE_PIO];
-                                           else p.cycle = p.cyc8b = adev->id[ATA_ID_EIDE_PIO_IORDY];
-               } else if(speed >= XFER_MW_DMA_0 && speed <= XFER_MW_DMA_2) {
-                       p.cycle = adev->id[ATA_ID_EIDE_DMA_MIN];
-               }
-               ata_timing_merge(&p, t, t, ATA_TIMING_CYCLE | ATA_TIMING_CYC8B);
-       }
-
-       /*
-        * Convert the timing to bus clock counts.
-        */
-
-       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.
-        */
-
-       if (speed > XFER_PIO_4) {
-               ata_timing_compute(adev, adev->pio_mode, &p, T, UT);
-               ata_timing_merge(&p, t, t, ATA_TIMING_ALL);
-       }
-
-       /*
-        * Lengthen active & recovery time so that cycle time is correct.
-        */
-
-       if (t->act8b + t->rec8b < t->cyc8b) {
-               t->act8b += (t->cyc8b - (t->act8b + t->rec8b)) / 2;
-               t->rec8b = t->cyc8b - t->act8b;
-       }
-
-       if (t->active + t->recover < t->cycle) {
-               t->active += (t->cycle - (t->active + t->recover)) / 2;
-               t->recover = t->cycle - t->active;
-       }
-
-       return 0;
-}
-
-/**
- *     ata_down_xfermask_limit - adjust dev xfer masks downward
- *     @dev: Device to adjust xfer masks
- *     @force_pio0: Force PIO0
- *
- *     Adjust xfer masks of @dev downward.  Note that this function
- *     does not apply the change.  Invoking ata_set_mode() afterwards
- *     will apply the limit.
- *
- *     LOCKING:
- *     Inherited from caller.
- *
- *     RETURNS:
- *     0 on success, negative errno on failure
- */
-int ata_down_xfermask_limit(struct ata_device *dev, int force_pio0)
-{
-       unsigned long xfer_mask;
-       int highbit;
-
-       xfer_mask = ata_pack_xfermask(dev->pio_mask, dev->mwdma_mask,
-                                     dev->udma_mask);
-
-       if (!xfer_mask)
-               goto fail;
-       /* don't gear down to MWDMA from UDMA, go directly to PIO */
-       if (xfer_mask & ATA_MASK_UDMA)
-               xfer_mask &= ~ATA_MASK_MWDMA;
-
-       highbit = fls(xfer_mask) - 1;
-       xfer_mask &= ~(1 << highbit);
-       if (force_pio0)
-               xfer_mask &= 1 << ATA_SHIFT_PIO;
-       if (!xfer_mask)
-               goto fail;
-
-       ata_unpack_xfermask(xfer_mask, &dev->pio_mask, &dev->mwdma_mask,
-                           &dev->udma_mask);
-
-       ata_dev_printk(dev, KERN_WARNING, "limiting speed to %s\n",
-                      ata_mode_string(xfer_mask));
-
-       return 0;
-
- fail:
-       return -EINVAL;
-}
-
-static int ata_dev_set_mode(struct ata_device *dev)
-{
-       unsigned int err_mask;
-       int rc;
-
-       dev->flags &= ~ATA_DFLAG_PIO;
-       if (dev->xfer_shift == ATA_SHIFT_PIO)
-               dev->flags |= ATA_DFLAG_PIO;
-
-       err_mask = ata_dev_set_xfermode(dev);
-       if (err_mask) {
-               ata_dev_printk(dev, KERN_ERR, "failed to set xfermode "
-                              "(err_mask=0x%x)\n", err_mask);
-               return -EIO;
-       }
-
-       rc = ata_dev_revalidate(dev, 0);
-       if (rc)
-               return rc;
-
-       DPRINTK("xfer_shift=%u, xfer_mode=0x%x\n",
-               dev->xfer_shift, (int)dev->xfer_mode);
-
-       ata_dev_printk(dev, KERN_INFO, "configured for %s\n",
-                      ata_mode_string(ata_xfer_mode2mask(dev->xfer_mode)));
-       return 0;
-}
-
-/**
- *     ata_set_mode - Program timings and issue SET FEATURES - XFER
- *     @ap: port on which timings will be programmed
- *     @r_failed_dev: out paramter for failed device
- *
- *     Set ATA device disk transfer mode (PIO3, UDMA6, etc.).  If
- *     ata_set_mode() fails, pointer to the failing device is
- *     returned in @r_failed_dev.
- *
- *     LOCKING:
- *     PCI/etc. bus probe sem.
- *
- *     RETURNS:
- *     0 on success, negative errno otherwise
- */
-int ata_set_mode(struct ata_port *ap, struct ata_device **r_failed_dev)
-{
-       struct ata_device *dev;
-       int i, rc = 0, used_dma = 0, found = 0;
-
-       /* has private set_mode? */
-       if (ap->ops->set_mode) {
-               /* FIXME: make ->set_mode handle no device case and
-                * return error code and failing device on failure.
-                */
-               for (i = 0; i < ATA_MAX_DEVICES; i++) {
-                       if (ata_dev_ready(&ap->device[i])) {
-                               ap->ops->set_mode(ap);
-                               break;
-                       }
-               }
-               return 0;
-       }
-
-       /* step 1: calculate xfer_mask */
-       for (i = 0; i < ATA_MAX_DEVICES; i++) {
-               unsigned int pio_mask, dma_mask;
-
-               dev = &ap->device[i];
-
-               if (!ata_dev_enabled(dev))
-                       continue;
-
-               ata_dev_xfermask(dev);
-
-               pio_mask = ata_pack_xfermask(dev->pio_mask, 0, 0);
-               dma_mask = ata_pack_xfermask(0, dev->mwdma_mask, dev->udma_mask);
-               dev->pio_mode = ata_xfer_mask2mode(pio_mask);
-               dev->dma_mode = ata_xfer_mask2mode(dma_mask);
-
-               found = 1;
-               if (dev->dma_mode)
-                       used_dma = 1;
-       }
-       if (!found)
-               goto out;
-
-       /* step 2: always set host PIO timings */
-       for (i = 0; i < ATA_MAX_DEVICES; i++) {
-               dev = &ap->device[i];
-               if (!ata_dev_enabled(dev))
-                       continue;
-
-               if (!dev->pio_mode) {
-                       ata_dev_printk(dev, KERN_WARNING, "no PIO support\n");
-                       rc = -EINVAL;
-                       goto out;
-               }
-
-               dev->xfer_mode = dev->pio_mode;
-               dev->xfer_shift = ATA_SHIFT_PIO;
-               if (ap->ops->set_piomode)
-                       ap->ops->set_piomode(ap, dev);
-       }
-
-       /* step 3: set host DMA timings */
-       for (i = 0; i < ATA_MAX_DEVICES; i++) {
-               dev = &ap->device[i];
-
-               if (!ata_dev_enabled(dev) || !dev->dma_mode)
-                       continue;
-
-               dev->xfer_mode = dev->dma_mode;
-               dev->xfer_shift = ata_xfer_mode2shift(dev->dma_mode);
-               if (ap->ops->set_dmamode)
-                       ap->ops->set_dmamode(ap, dev);
-       }
-
-       /* step 4: update devices' xfer mode */
-       for (i = 0; i < ATA_MAX_DEVICES; i++) {
-               dev = &ap->device[i];
-
-               /* don't udpate suspended devices' xfer mode */
-               if (!ata_dev_ready(dev))
-                       continue;
-
-               rc = ata_dev_set_mode(dev);
-               if (rc)
-                       goto out;
-       }
-
-       /* Record simplex status. If we selected DMA then the other
-        * host channels are not permitted to do so.
-        */
-       if (used_dma && (ap->host_set->flags & ATA_HOST_SIMPLEX))
-               ap->host_set->simplex_claimed = 1;
-
-       /* step5: chip specific finalisation */
-       if (ap->ops->post_set_mode)
-               ap->ops->post_set_mode(ap);
-
- out:
-       if (rc)
-               *r_failed_dev = dev;
-       return rc;
-}
-
-/**
- *     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
- *     @tmout_pat: impatience timeout
- *     @tmout: overall timeout
- *
- *     Sleep until ATA Status register bit BSY clears,
- *     or a timeout occurs.
- *
- *     LOCKING: None.
- */
-
-unsigned int ata_busy_sleep (struct ata_port *ap,
-                            unsigned long tmout_pat, unsigned long tmout)
-{
-       unsigned long timer_start, timeout;
-       u8 status;
-
-       status = ata_busy_wait(ap, ATA_BUSY, 300);
-       timer_start = jiffies;
-       timeout = timer_start + tmout_pat;
-       while ((status & ATA_BUSY) && (time_before(jiffies, timeout))) {
-               msleep(50);
-               status = ata_busy_wait(ap, ATA_BUSY, 3);
-       }
-
-       if (status & ATA_BUSY)
-               ata_port_printk(ap, KERN_WARNING,
-                               "port is slow to respond, please be patient\n");
-
-       timeout = timer_start + tmout;
-       while ((status & ATA_BUSY) && (time_before(jiffies, timeout))) {
-               msleep(50);
-               status = ata_chk_status(ap);
-       }
-
-       if (status & ATA_BUSY) {
-               ata_port_printk(ap, KERN_ERR, "port failed to respond "
-                               "(%lu secs)\n", tmout / HZ);
-               return 1;
-       }
-
-       return 0;
-}
-
-static void ata_bus_post_reset(struct ata_port *ap, unsigned int devmask)
-{
-       struct ata_ioports *ioaddr = &ap->ioaddr;
-       unsigned int dev0 = devmask & (1 << 0);
-       unsigned int dev1 = devmask & (1 << 1);
-       unsigned long timeout;
-
-       /* if device 0 was found in ata_devchk, wait for its
-        * BSY bit to clear
-        */
-       if (dev0)
-               ata_busy_sleep(ap, ATA_TMOUT_BOOT_QUICK, ATA_TMOUT_BOOT);
-
-       /* if device 1 was found in ata_devchk, wait for
-        * register access, then wait for BSY to clear
-        */
-       timeout = jiffies + ATA_TMOUT_BOOT;
-       while (dev1) {
-               u8 nsect, lbal;
-
-               ap->ops->dev_select(ap, 1);
-               if (ap->flags & ATA_FLAG_MMIO) {
-                       nsect = readb((void __iomem *) ioaddr->nsect_addr);
-                       lbal = readb((void __iomem *) ioaddr->lbal_addr);
-               } else {
-                       nsect = inb(ioaddr->nsect_addr);
-                       lbal = inb(ioaddr->lbal_addr);
-               }
-               if ((nsect == 1) && (lbal == 1))
-                       break;
-               if (time_after(jiffies, timeout)) {
-                       dev1 = 0;
-                       break;
-               }
-               msleep(50);     /* give drive a breather */
-       }
-       if (dev1)
-               ata_busy_sleep(ap, ATA_TMOUT_BOOT_QUICK, ATA_TMOUT_BOOT);
-
-       /* is all this really necessary? */
-       ap->ops->dev_select(ap, 0);
-       if (dev1)
-               ap->ops->dev_select(ap, 1);
-       if (dev0)
-               ap->ops->dev_select(ap, 0);
-}
-
-static unsigned int ata_bus_softreset(struct ata_port *ap,
-                                     unsigned int devmask)
-{
-       struct ata_ioports *ioaddr = &ap->ioaddr;
-
-       DPRINTK("ata%u: bus reset via SRST\n", ap->id);
-
-       /* software reset.  causes dev0 to be selected */
-       if (ap->flags & ATA_FLAG_MMIO) {
-               writeb(ap->ctl, (void __iomem *) ioaddr->ctl_addr);
-               udelay(20);     /* FIXME: flush */
-               writeb(ap->ctl | ATA_SRST, (void __iomem *) ioaddr->ctl_addr);
-               udelay(20);     /* FIXME: flush */
-               writeb(ap->ctl, (void __iomem *) ioaddr->ctl_addr);
-       } else {
-               outb(ap->ctl, ioaddr->ctl_addr);
-               udelay(10);
-               outb(ap->ctl | ATA_SRST, ioaddr->ctl_addr);
-               udelay(10);
-               outb(ap->ctl, ioaddr->ctl_addr);
-       }
-
-       /* spec mandates ">= 2ms" before checking status.
-        * We wait 150ms, because that was the magic delay used for
-        * ATAPI devices in Hale Landis's ATADRVR, for the period of time
-        * between when the ATA command register is written, and then
-        * status is checked.  Because waiting for "a while" before
-        * checking status is fine, post SRST, we perform this magic
-        * delay here as well.
-        *
-        * Old drivers/ide uses the 2mS rule and then waits for ready
-        */
-       msleep(150);
-
-       /* Before we perform post reset processing we want to see if
-        * the bus shows 0xFF because the odd clown forgets the D7
-        * pulldown resistor.
-        */
-       if (ata_check_status(ap) == 0xFF) {
-               ata_port_printk(ap, KERN_ERR, "SRST failed (status 0xFF)\n");
-               return AC_ERR_OTHER;
-       }
-
-       ata_bus_post_reset(ap, devmask);
-
-       return 0;
-}
-
-/**
- *     ata_bus_reset - reset host port and associated ATA channel
- *     @ap: port to reset
- *
- *     This is typically the first time we actually start issuing
- *     commands to the ATA channel.  We wait for BSY to clear, then
- *     issue EXECUTE DEVICE DIAGNOSTIC command, polling for its
- *     result.  Determine what devices, if any, are on the channel
- *     by looking at the device 0/1 error register.  Look at the signature
- *     stored in each device's taskfile registers, to determine if
- *     the device is ATA or ATAPI.
- *
- *     LOCKING:
- *     PCI/etc. bus probe sem.
- *     Obtains host_set lock.
- *
- *     SIDE EFFECTS:
- *     Sets ATA_FLAG_DISABLED if bus reset fails.
- */
-
-void ata_bus_reset(struct ata_port *ap)
-{
-       struct ata_ioports *ioaddr = &ap->ioaddr;
-       unsigned int slave_possible = ap->flags & ATA_FLAG_SLAVE_POSS;
-       u8 err;
-       unsigned int dev0, dev1 = 0, devmask = 0;
-
-       DPRINTK("ENTER, host %u, port %u\n", ap->id, ap->port_no);
-
-       /* determine if device 0/1 are present */
-       if (ap->flags & ATA_FLAG_SATA_RESET)
-               dev0 = 1;
-       else {
-               dev0 = ata_devchk(ap, 0);
-               if (slave_possible)
-                       dev1 = ata_devchk(ap, 1);
-       }
-
-       if (dev0)
-               devmask |= (1 << 0);
-       if (dev1)
-               devmask |= (1 << 1);
-
-       /* select device 0 again */
-       ap->ops->dev_select(ap, 0);
-
-       /* issue bus reset */
-       if (ap->flags & ATA_FLAG_SRST)
-               if (ata_bus_softreset(ap, devmask))
-                       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:
-       ata_port_printk(ap, KERN_ERR, "disabling port\n");
-       ap->ops->port_disable(ap);
-
-       DPRINTK("EXIT\n");
-}
-
-/**
- *     sata_phy_debounce - debounce SATA phy status
- *     @ap: ATA port to debounce SATA phy status for
- *     @params: timing parameters { interval, duratinon, timeout } in msec
- *
- *     Make sure SStatus of @ap reaches stable state, determined by
- *     holding the same value where DET is not 1 for @duration polled
- *     every @interval, before @timeout.  Timeout constraints the
- *     beginning of the stable state.  Because, after hot unplugging,
- *     DET gets stuck at 1 on some controllers, this functions waits
- *     until timeout then returns 0 if DET is stable at 1.
- *
- *     LOCKING:
- *     Kernel thread context (may sleep)
- *
- *     RETURNS:
- *     0 on success, -errno on failure.
- */
-int sata_phy_debounce(struct ata_port *ap, const unsigned long *params)
-{
-       unsigned long interval_msec = params[0];
-       unsigned long duration = params[1] * HZ / 1000;
-       unsigned long timeout = jiffies + params[2] * HZ / 1000;
-       unsigned long last_jiffies;
-       u32 last, cur;
-       int rc;
-
-       if ((rc = sata_scr_read(ap, SCR_STATUS, &cur)))
-               return rc;
-       cur &= 0xf;
-
-       last = cur;
-       last_jiffies = jiffies;
-
-       while (1) {
-               msleep(interval_msec);
-               if ((rc = sata_scr_read(ap, SCR_STATUS, &cur)))
-                       return rc;
-               cur &= 0xf;
-
-               /* DET stable? */
-               if (cur == last) {
-                       if (cur == 1 && time_before(jiffies, timeout))
-                               continue;
-                       if (time_after(jiffies, last_jiffies + duration))
-                               return 0;
-                       continue;
-               }
-
-               /* unstable, start over */
-               last = cur;
-               last_jiffies = jiffies;
-
-               /* check timeout */
-               if (time_after(jiffies, timeout))
-                       return -EBUSY;
-       }
-}
-
-/**
- *     sata_phy_resume - resume SATA phy
- *     @ap: ATA port to resume SATA phy for
- *     @params: timing parameters { interval, duratinon, timeout } in msec
- *
- *     Resume SATA phy of @ap and debounce it.
- *
- *     LOCKING:
- *     Kernel thread context (may sleep)
- *
- *     RETURNS:
- *     0 on success, -errno on failure.
- */
-int sata_phy_resume(struct ata_port *ap, const unsigned long *params)
-{
-       u32 scontrol;
-       int rc;
-
-       if ((rc = sata_scr_read(ap, SCR_CONTROL, &scontrol)))
-               return rc;
-
-       scontrol = (scontrol & 0x0f0) | 0x300;
-
-       if ((rc = sata_scr_write(ap, SCR_CONTROL, scontrol)))
-               return rc;
-
-       /* Some PHYs react badly if SStatus is pounded immediately
-        * after resuming.  Delay 200ms before debouncing.
-        */
-       msleep(200);
-
-       return sata_phy_debounce(ap, params);
-}
-
-static void ata_wait_spinup(struct ata_port *ap)
-{
-       struct ata_eh_context *ehc = &ap->eh_context;
-       unsigned long end, secs;
-       int rc;
-
-       /* first, debounce phy if SATA */
-       if (ap->cbl == ATA_CBL_SATA) {
-               rc = sata_phy_debounce(ap, sata_deb_timing_hotplug);
-
-               /* if debounced successfully and offline, no need to wait */
-               if ((rc == 0 || rc == -EOPNOTSUPP) && ata_port_offline(ap))
-                       return;
-       }
-
-       /* okay, let's give the drive time to spin up */
-       end = ehc->i.hotplug_timestamp + ATA_SPINUP_WAIT * HZ / 1000;
-       secs = ((end - jiffies) + HZ - 1) / HZ;
-
-       if (time_after(jiffies, end))
-               return;
-
-       if (secs > 5)
-               ata_port_printk(ap, KERN_INFO, "waiting for device to spin up "
-                               "(%lu secs)\n", secs);
-
-       schedule_timeout_uninterruptible(end - jiffies);
-}
-
-/**
- *     ata_std_prereset - prepare for reset
- *     @ap: ATA port to be reset
- *
- *     @ap is about to be reset.  Initialize it.
- *
- *     LOCKING:
- *     Kernel thread context (may sleep)
- *
- *     RETURNS:
- *     0 on success, -errno otherwise.
- */
-int ata_std_prereset(struct ata_port *ap)
-{
-       struct ata_eh_context *ehc = &ap->eh_context;
-       const unsigned long *timing = sata_ehc_deb_timing(ehc);
-       int rc;
-
-       /* handle link resume & hotplug spinup */
-       if ((ehc->i.flags & ATA_EHI_RESUME_LINK) &&
-           (ap->flags & ATA_FLAG_HRST_TO_RESUME))
-               ehc->i.action |= ATA_EH_HARDRESET;
-
-       if ((ehc->i.flags & ATA_EHI_HOTPLUGGED) &&
-           (ap->flags & ATA_FLAG_SKIP_D2H_BSY))
-               ata_wait_spinup(ap);
-
-       /* if we're about to do hardreset, nothing more to do */
-       if (ehc->i.action & ATA_EH_HARDRESET)
-               return 0;
-
-       /* if SATA, resume phy */
-       if (ap->cbl == ATA_CBL_SATA) {
-               rc = sata_phy_resume(ap, timing);
-               if (rc && rc != -EOPNOTSUPP) {
-                       /* phy resume failed */
-                       ata_port_printk(ap, KERN_WARNING, "failed to resume "
-                                       "link for reset (errno=%d)\n", rc);
-                       return rc;
-               }
-       }
-
-       /* Wait for !BSY if the controller can wait for the first D2H
-        * Reg FIS and we don't know that no device is attached.
-        */
-       if (!(ap->flags & ATA_FLAG_SKIP_D2H_BSY) && !ata_port_offline(ap))
-               ata_busy_sleep(ap, ATA_TMOUT_BOOT_QUICK, ATA_TMOUT_BOOT);
-
-       return 0;
-}
-
-/**
- *     ata_std_softreset - reset host port via ATA SRST
- *     @ap: port to reset
- *     @classes: resulting classes of attached devices
- *
- *     Reset host port using ATA SRST.
- *
- *     LOCKING:
- *     Kernel thread context (may sleep)
- *
- *     RETURNS:
- *     0 on success, -errno otherwise.
- */
-int ata_std_softreset(struct ata_port *ap, 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 (ata_port_offline(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) {
-               ata_port_printk(ap, KERN_ERR, "SRST 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
- *     @class: resulting class of attached device
- *
- *     SATA phy-reset host port using DET bits of SControl register.
- *
- *     LOCKING:
- *     Kernel thread context (may sleep)
- *
- *     RETURNS:
- *     0 on success, -errno otherwise.
- */
-int sata_std_hardreset(struct ata_port *ap, unsigned int *class)
-{
-       struct ata_eh_context *ehc = &ap->eh_context;
-       const unsigned long *timing = sata_ehc_deb_timing(ehc);
-       u32 scontrol;
-       int rc;
-
-       DPRINTK("ENTER\n");
-
-       if (sata_set_spd_needed(ap)) {
-               /* SATA spec says nothing about how to reconfigure
-                * spd.  To be on the safe side, turn off phy during
-                * reconfiguration.  This works for at least ICH7 AHCI
-                * and Sil3124.
-                */
-               if ((rc = sata_scr_read(ap, SCR_CONTROL, &scontrol)))
-                       return rc;
-
-               scontrol = (scontrol & 0x0f0) | 0x302;
-
-               if ((rc = sata_scr_write(ap, SCR_CONTROL, scontrol)))
-                       return rc;
-
-               sata_set_spd(ap);
-       }
-
-       /* issue phy wake/reset */
-       if ((rc = sata_scr_read(ap, SCR_CONTROL, &scontrol)))
-               return rc;
-
-       scontrol = (scontrol & 0x0f0) | 0x301;
-
-       if ((rc = sata_scr_write_flush(ap, SCR_CONTROL, scontrol)))
-               return rc;
-
-       /* 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, timing);
-
-       /* TODO: phy layer with polling, timeouts, etc. */
-       if (ata_port_offline(ap)) {
-               *class = ATA_DEV_NONE;
-               DPRINTK("EXIT, link offline\n");
-               return 0;
-       }
-
-       if (ata_busy_sleep(ap, ATA_TMOUT_BOOT_QUICK, ATA_TMOUT_BOOT)) {
-               ata_port_printk(ap, KERN_ERR,
-                               "COMRESET failed (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.
- *
- *     LOCKING:
- *     Kernel thread context (may sleep)
- */
-void ata_std_postreset(struct ata_port *ap, unsigned int *classes)
-{
-       u32 serror;
-
-       DPRINTK("ENTER\n");
-
-       /* print link status */
-       sata_print_link_status(ap);
-
-       /* clear SError */
-       if (sata_scr_read(ap, SCR_ERROR, &serror) == 0)
-               sata_scr_write(ap, SCR_ERROR, serror);
-
-       /* re-enable interrupts */
-       if (!ap->ops->error_handler) {
-               /* FIXME: hack. create a hook instead */
-               if (ap->ioaddr.ctl_addr)
-                       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_dev_same_device - Determine whether new ID matches configured device
- *     @dev: device to compare against
- *     @new_class: class of the new device
- *     @new_id: IDENTIFY page of the new device
- *
- *     Compare @new_class and @new_id against @dev and determine
- *     whether @dev is the device indicated by @new_class and
- *     @new_id.
- *
- *     LOCKING:
- *     None.
- *
- *     RETURNS:
- *     1 if @dev matches @new_class and @new_id, 0 otherwise.
- */
-static int ata_dev_same_device(struct ata_device *dev, unsigned int new_class,
-                              const u16 *new_id)
-{
-       const u16 *old_id = dev->id;
-       unsigned char model[2][41], serial[2][21];
-       u64 new_n_sectors;
-
-       if (dev->class != new_class) {
-               ata_dev_printk(dev, KERN_INFO, "class mismatch %d != %d\n",
-                              dev->class, new_class);
-               return 0;
-       }
-
-       ata_id_c_string(old_id, model[0], ATA_ID_PROD_OFS, sizeof(model[0]));
-       ata_id_c_string(new_id, model[1], ATA_ID_PROD_OFS, sizeof(model[1]));
-       ata_id_c_string(old_id, serial[0], ATA_ID_SERNO_OFS, sizeof(serial[0]));
-       ata_id_c_string(new_id, serial[1], ATA_ID_SERNO_OFS, sizeof(serial[1]));
-       new_n_sectors = ata_id_n_sectors(new_id);
-
-       if (strcmp(model[0], model[1])) {
-               ata_dev_printk(dev, KERN_INFO, "model number mismatch "
-                              "'%s' != '%s'\n", model[0], model[1]);
-               return 0;
-       }
-
-       if (strcmp(serial[0], serial[1])) {
-               ata_dev_printk(dev, KERN_INFO, "serial number mismatch "
-                              "'%s' != '%s'\n", serial[0], serial[1]);
-               return 0;
-       }
-
-       if (dev->class == ATA_DEV_ATA && dev->n_sectors != new_n_sectors) {
-               ata_dev_printk(dev, KERN_INFO, "n_sectors mismatch "
-                              "%llu != %llu\n",
-                              (unsigned long long)dev->n_sectors,
-                              (unsigned long long)new_n_sectors);
-               return 0;
-       }
-
-       return 1;
-}
-
-/**
- *     ata_dev_revalidate - Revalidate ATA device
- *     @dev: device to revalidate
- *     @post_reset: is this revalidation after reset?
- *
- *     Re-read IDENTIFY page and make sure @dev is still attached to
- *     the port.
- *
- *     LOCKING:
- *     Kernel thread context (may sleep)
- *
- *     RETURNS:
- *     0 on success, negative errno otherwise
- */
-int ata_dev_revalidate(struct ata_device *dev, int post_reset)
-{
-       unsigned int class = dev->class;
-       u16 *id = (void *)dev->ap->sector_buf;
-       int rc;
-
-       if (!ata_dev_enabled(dev)) {
-               rc = -ENODEV;
-               goto fail;
-       }
-
-       /* read ID data */
-       rc = ata_dev_read_id(dev, &class, post_reset, id);
-       if (rc)
-               goto fail;
-
-       /* is the device still there? */
-       if (!ata_dev_same_device(dev, class, id)) {
-               rc = -ENODEV;
-               goto fail;
-       }
-
-       memcpy(dev->id, id, sizeof(id[0]) * ATA_ID_WORDS);
-
-       /* configure device according to the new ID */
-       rc = ata_dev_configure(dev, 0);
-       if (rc == 0)
-               return 0;
-
- fail:
-       ata_dev_printk(dev, KERN_ERR, "revalidation failed (errno=%d)\n", rc);
-       return rc;
-}
-
-static const char * const ata_dma_blacklist [] = {
-       "WDC AC11000H", NULL,
-       "WDC AC22100H", NULL,
-       "WDC AC32500H", NULL,
-       "WDC AC33100H", NULL,
-       "WDC AC31600H", NULL,
-       "WDC AC32100H", "24.09P07",
-       "WDC AC23200L", "21.10N21",
-       "Compaq CRD-8241B",  NULL,
-       "CRD-8400B", NULL,
-       "CRD-8480B", NULL,
-       "CRD-8482B", NULL,
-       "CRD-84", NULL,
-       "SanDisk SDP3B", NULL,
-       "SanDisk SDP3B-64", NULL,
-       "SANYO CD-ROM CRD", NULL,
-       "HITACHI CDR-8", NULL,
-       "HITACHI CDR-8335", NULL,
-       "HITACHI CDR-8435", NULL,
-       "Toshiba CD-ROM XM-6202B", NULL,
-       "TOSHIBA CD-ROM XM-1702BC", NULL,
-       "CD-532E-A", NULL,
-       "E-IDE CD-ROM CR-840", NULL,
-       "CD-ROM Drive/F5A", NULL,
-       "WPI CDD-820", NULL,
-       "SAMSUNG CD-ROM SC-148C", NULL,
-       "SAMSUNG CD-ROM SC", NULL,
-       "SanDisk SDP3B-64", NULL,
-       "ATAPI CD-ROM DRIVE 40X MAXIMUM",NULL,
-       "_NEC DV5800A", NULL,
-       "SAMSUNG CD-ROM SN-124", "N001"
-};
-
-static int ata_strim(char *s, size_t len)
-{
-       len = strnlen(s, len);
-
-       /* ATAPI specifies that empty space is blank-filled; remove blanks */
-       while ((len > 0) && (s[len - 1] == ' ')) {
-               len--;
-               s[len] = 0;
-       }
-       return len;
-}
-
-static int ata_dma_blacklisted(const struct ata_device *dev)
-{
-       unsigned char model_num[40];
-       unsigned char model_rev[16];
-       unsigned int nlen, rlen;
-       int i;
-
-       /* We don't support polling DMA.
-        * DMA blacklist those ATAPI devices with CDB-intr (and use PIO)
-        * if the LLDD handles only interrupts in the HSM_ST_LAST state.
-        */
-       if ((dev->ap->flags & ATA_FLAG_PIO_POLLING) &&
-           (dev->flags & ATA_DFLAG_CDB_INTR))
-               return 1;
-
-       ata_id_string(dev->id, model_num, ATA_ID_PROD_OFS,
-                         sizeof(model_num));
-       ata_id_string(dev->id, model_rev, ATA_ID_FW_REV_OFS,
-                         sizeof(model_rev));
-       nlen = ata_strim(model_num, sizeof(model_num));
-       rlen = ata_strim(model_rev, sizeof(model_rev));
-
-       for (i = 0; i < ARRAY_SIZE(ata_dma_blacklist); i += 2) {
-               if (!strncmp(ata_dma_blacklist[i], model_num, nlen)) {
-                       if (ata_dma_blacklist[i+1] == NULL)
-                               return 1;
-                       if (!strncmp(ata_dma_blacklist[i], model_rev, rlen))
-                               return 1;
-               }
-       }
-       return 0;
-}
-
-/**
- *     ata_dev_xfermask - Compute supported xfermask of the given device
- *     @dev: Device to compute xfermask for
- *
- *     Compute supported xfermask of @dev and store it in
- *     dev->*_mask.  This function is responsible for applying all
- *     known limits including host controller limits, device
- *     blacklist, etc...
- *
- *     LOCKING:
- *     None.
- */
-static void ata_dev_xfermask(struct ata_device *dev)
-{
-       struct ata_port *ap = dev->ap;
-       struct ata_host_set *hs = ap->host_set;
-       unsigned long xfer_mask;
-
-       /* controller modes available */
-       xfer_mask = ata_pack_xfermask(ap->pio_mask,
-                                     ap->mwdma_mask, ap->udma_mask);
-
-       /* Apply cable rule here.  Don't apply it early because when
-        * we handle hot plug the cable type can itself change.
-        */
-       if (ap->cbl == ATA_CBL_PATA40)
-               xfer_mask &= ~(0xF8 << ATA_SHIFT_UDMA);
-
-       xfer_mask &= ata_pack_xfermask(dev->pio_mask,
-                                      dev->mwdma_mask, dev->udma_mask);
-       xfer_mask &= ata_id_xfermask(dev->id);
-
-       if (ata_dma_blacklisted(dev)) {
-               xfer_mask &= ~(ATA_MASK_MWDMA | ATA_MASK_UDMA);
-               ata_dev_printk(dev, KERN_WARNING,
-                              "device is on DMA blacklist, disabling DMA\n");
-       }
-
-       if ((hs->flags & ATA_HOST_SIMPLEX) && hs->simplex_claimed) {
-               xfer_mask &= ~(ATA_MASK_MWDMA | ATA_MASK_UDMA);
-               ata_dev_printk(dev, KERN_WARNING, "simplex DMA is claimed by "
-                              "other device, disabling DMA\n");
-       }
-
-       if (ap->ops->mode_filter)
-               xfer_mask = ap->ops->mode_filter(ap, dev, xfer_mask);
-
-       ata_unpack_xfermask(xfer_mask, &dev->pio_mask,
-                           &dev->mwdma_mask, &dev->udma_mask);
-}
-
-/**
- *     ata_dev_set_xfermode - Issue SET FEATURES - XFER MODE command
- *     @dev: Device to which command will be sent
- *
- *     Issue SET FEATURES - XFER MODE command to device @dev
- *     on port @ap.
- *
- *     LOCKING:
- *     PCI/etc. bus probe sem.
- *
- *     RETURNS:
- *     0 on success, AC_ERR_* mask otherwise.
- */
-
-static unsigned int ata_dev_set_xfermode(struct ata_device *dev)
-{
-       struct ata_taskfile tf;
-       unsigned int err_mask;
-
-       /* set up set-features taskfile */
-       DPRINTK("set features - xfer mode\n");
-
-       ata_tf_init(dev, &tf);
-       tf.command = ATA_CMD_SET_FEATURES;
-       tf.feature = SETFEATURES_XFER;
-       tf.flags |= ATA_TFLAG_ISADDR | ATA_TFLAG_DEVICE;
-       tf.protocol = ATA_PROT_NODATA;
-       tf.nsect = dev->xfer_mode;
-
-       err_mask = ata_exec_internal(dev, &tf, NULL, DMA_NONE, NULL, 0);
-
-       DPRINTK("EXIT, err_mask=%x\n", err_mask);
-       return err_mask;
-}
-
-/**
- *     ata_dev_init_params - Issue INIT DEV PARAMS command
- *     @dev: Device to which command will be sent
- *     @heads: Number of heads (taskfile parameter)
- *     @sectors: Number of sectors (taskfile parameter)
- *
- *     LOCKING:
- *     Kernel thread context (may sleep)
- *
- *     RETURNS:
- *     0 on success, AC_ERR_* mask otherwise.
- */
-static unsigned int ata_dev_init_params(struct ata_device *dev,
-                                       u16 heads, u16 sectors)
-{
-       struct ata_taskfile tf;
-       unsigned int err_mask;
-
-       /* Number of sectors per track 1-255. Number of heads 1-16 */
-       if (sectors < 1 || sectors > 255 || heads < 1 || heads > 16)
-               return AC_ERR_INVALID;
-
-       /* set up init dev params taskfile */
-       DPRINTK("init dev params \n");
-
-       ata_tf_init(dev, &tf);
-       tf.command = ATA_CMD_INIT_DEV_PARAMS;
-       tf.flags |= ATA_TFLAG_ISADDR | ATA_TFLAG_DEVICE;
-       tf.protocol = ATA_PROT_NODATA;
-       tf.nsect = sectors;
-       tf.device |= (heads - 1) & 0x0f; /* max head = num. of heads - 1 */
-
-       err_mask = ata_exec_internal(dev, &tf, NULL, DMA_NONE, NULL, 0);
-
-       DPRINTK("EXIT, err_mask=%x\n", err_mask);
-       return err_mask;
-}
-
-/**
- *     ata_sg_clean - Unmap DMA memory associated with command
- *     @qc: Command containing DMA memory to be released
- *
- *     Unmap all mapped DMA memory associated with this command.
- *
- *     LOCKING:
- *     spin_lock_irqsave(host_set lock)
- */
-
-static void ata_sg_clean(struct ata_queued_cmd *qc)
-{
-       struct ata_port *ap = qc->ap;
-       struct scatterlist *sg = qc->__sg;
-       int dir = qc->dma_dir;
-       void *pad_buf = NULL;
-
-       WARN_ON(!(qc->flags & ATA_QCFLAG_DMAMAP));
-       WARN_ON(sg == NULL);
-
-       if (qc->flags & ATA_QCFLAG_SINGLE)
-               WARN_ON(qc->n_elem > 1);
-
-       VPRINTK("unmapping %u sg elements\n", qc->n_elem);
-
-       /* if we padded the buffer out to 32-bit bound, and data
-        * xfer direction is from-device, we must copy from the
-        * pad buffer back into the supplied buffer
-        */
-       if (qc->pad_len && !(qc->tf.flags & ATA_TFLAG_WRITE))
-               pad_buf = ap->pad + (qc->tag * ATA_DMA_PAD_SZ);
-
-       if (qc->flags & ATA_QCFLAG_SG) {
-               if (qc->n_elem)
-                       dma_unmap_sg(ap->dev, sg, qc->n_elem, dir);
-               /* restore last sg */
-               sg[qc->orig_n_elem - 1].length += qc->pad_len;
-               if (pad_buf) {
-                       struct scatterlist *psg = &qc->pad_sgent;
-                       void *addr = kmap_atomic(psg->page, KM_IRQ0);
-                       memcpy(addr + psg->offset, pad_buf, qc->pad_len);
-                       kunmap_atomic(addr, KM_IRQ0);
-               }
-       } else {
-               if (qc->n_elem)
-                       dma_unmap_single(ap->dev,
-                               sg_dma_address(&sg[0]), sg_dma_len(&sg[0]),
-                               dir);
-               /* restore sg */
-               sg->length += qc->pad_len;
-               if (pad_buf)
-                       memcpy(qc->buf_virt + sg->length - qc->pad_len,
-                              pad_buf, qc->pad_len);
-       }
-
-       qc->flags &= ~ATA_QCFLAG_DMAMAP;
-       qc->__sg = NULL;
-}
-
-/**
- *     ata_fill_sg - Fill PCI IDE PRD table
- *     @qc: Metadata associated with taskfile to be transferred
- *
- *     Fill PCI IDE PRD (scatter-gather) table with segments
- *     associated with the current disk command.
- *
- *     LOCKING:
- *     spin_lock_irqsave(host_set lock)
- *
- */
-static void ata_fill_sg(struct ata_queued_cmd *qc)
-{
-       struct ata_port *ap = qc->ap;
-       struct scatterlist *sg;
-       unsigned int idx;
-
-       WARN_ON(qc->__sg == NULL);
-       WARN_ON(qc->n_elem == 0 && qc->pad_len == 0);
-
-       idx = 0;
-       ata_for_each_sg(sg, qc) {
-               u32 addr, offset;
-               u32 sg_len, len;
-
-               /* determine if physical DMA addr spans 64K boundary.
-                * Note h/w doesn't support 64-bit, so we unconditionally
-                * truncate dma_addr_t to u32.
-                */
-               addr = (u32) sg_dma_address(sg);
-               sg_len = sg_dma_len(sg);
-
-               while (sg_len) {
-                       offset = addr & 0xffff;
-                       len = sg_len;
-                       if ((offset + sg_len) > 0x10000)
-                               len = 0x10000 - offset;
-
-                       ap->prd[idx].addr = cpu_to_le32(addr);
-                       ap->prd[idx].flags_len = cpu_to_le32(len & 0xffff);
-                       VPRINTK("PRD[%u] = (0x%X, 0x%X)\n", idx, addr, len);
-
-                       idx++;
-                       sg_len -= len;
-                       addr += len;
-               }
-       }
-
-       if (idx)
-               ap->prd[idx - 1].flags_len |= cpu_to_le32(ATA_PRD_EOT);
-}
-/**
- *     ata_check_atapi_dma - Check whether ATAPI DMA can be supported
- *     @qc: Metadata associated with taskfile to check
- *
- *     Allow low-level driver to filter ATA PACKET commands, returning
- *     a status indicating whether or not it is OK to use DMA for the
- *     supplied PACKET command.
- *
- *     LOCKING:
- *     spin_lock_irqsave(host_set lock)
- *
- *     RETURNS: 0 when ATAPI DMA can be used
- *               nonzero otherwise
- */
-int ata_check_atapi_dma(struct ata_queued_cmd *qc)
-{
-       struct ata_port *ap = qc->ap;
-       int rc = 0; /* Assume ATAPI DMA is OK by default */
-
-       if (ap->ops->check_atapi_dma)
-               rc = ap->ops->check_atapi_dma(qc);
-
-       return rc;
-}
-/**
- *     ata_qc_prep - Prepare taskfile for submission
- *     @qc: Metadata associated with taskfile to be prepared
- *
- *     Prepare ATA taskfile for submission.
- *
- *     LOCKING:
- *     spin_lock_irqsave(host_set lock)
- */
-void ata_qc_prep(struct ata_queued_cmd *qc)
-{
-       if (!(qc->flags & ATA_QCFLAG_DMAMAP))
-               return;
-
-       ata_fill_sg(qc);
-}
-
-void ata_noop_qc_prep(struct ata_queued_cmd *qc) { }
-
-/**
- *     ata_sg_init_one - Associate command with memory buffer
- *     @qc: Command to be associated
- *     @buf: Memory buffer
- *     @buflen: Length of memory buffer, in bytes.
- *
- *     Initialize the data-related elements of queued_cmd @qc
- *     to point to a single memory buffer, @buf of byte length @buflen.
- *
- *     LOCKING:
- *     spin_lock_irqsave(host_set lock)
- */
-
-void ata_sg_init_one(struct ata_queued_cmd *qc, void *buf, unsigned int buflen)
-{
-       struct scatterlist *sg;
-
-       qc->flags |= ATA_QCFLAG_SINGLE;
-
-       memset(&qc->sgent, 0, sizeof(qc->sgent));
-       qc->__sg = &qc->sgent;
-       qc->n_elem = 1;
-       qc->orig_n_elem = 1;
-       qc->buf_virt = buf;
-       qc->nbytes = buflen;
-
-       sg = qc->__sg;
-       sg_init_one(sg, buf, buflen);
-}
-
-/**
- *     ata_sg_init - Associate command with scatter-gather table.
- *     @qc: Command to be associated
- *     @sg: Scatter-gather table.
- *     @n_elem: Number of elements in s/g table.
- *
- *     Initialize the data-related elements of queued_cmd @qc
- *     to point to a scatter-gather table @sg, containing @n_elem
- *     elements.
- *
- *     LOCKING:
- *     spin_lock_irqsave(host_set lock)
- */
-
-void ata_sg_init(struct ata_queued_cmd *qc, struct scatterlist *sg,
-                unsigned int n_elem)
-{
-       qc->flags |= ATA_QCFLAG_SG;
-       qc->__sg = sg;
-       qc->n_elem = n_elem;
-       qc->orig_n_elem = n_elem;
-}
-
-/**
- *     ata_sg_setup_one - DMA-map the memory buffer associated with a command.
- *     @qc: Command with memory buffer to be mapped.
- *
- *     DMA-map the memory buffer associated with queued_cmd @qc.
- *
- *     LOCKING:
- *     spin_lock_irqsave(host_set lock)
- *
- *     RETURNS:
- *     Zero on success, negative on error.
- */
-
-static int ata_sg_setup_one(struct ata_queued_cmd *qc)
-{
-       struct ata_port *ap = qc->ap;
-       int dir = qc->dma_dir;
-       struct scatterlist *sg = qc->__sg;
-       dma_addr_t dma_address;
-       int trim_sg = 0;
-
-       /* we must lengthen transfers to end on a 32-bit boundary */
-       qc->pad_len = sg->length & 3;
-       if (qc->pad_len) {
-               void *pad_buf = ap->pad + (qc->tag * ATA_DMA_PAD_SZ);
-               struct scatterlist *psg = &qc->pad_sgent;
-
-               WARN_ON(qc->dev->class != ATA_DEV_ATAPI);
-
-               memset(pad_buf, 0, ATA_DMA_PAD_SZ);
-
-               if (qc->tf.flags & ATA_TFLAG_WRITE)
-                       memcpy(pad_buf, qc->buf_virt + sg->length - qc->pad_len,
-                              qc->pad_len);
-
-               sg_dma_address(psg) = ap->pad_dma + (qc->tag * ATA_DMA_PAD_SZ);
-               sg_dma_len(psg) = ATA_DMA_PAD_SZ;
-               /* trim sg */
-               sg->length -= qc->pad_len;
-               if (sg->length == 0)
-                       trim_sg = 1;
-
-               DPRINTK("padding done, sg->length=%u pad_len=%u\n",
-                       sg->length, qc->pad_len);
-       }
-
-       if (trim_sg) {
-               qc->n_elem--;
-               goto skip_map;
-       }
-
-       dma_address = dma_map_single(ap->dev, qc->buf_virt,
-                                    sg->length, dir);
-       if (dma_mapping_error(dma_address)) {
-               /* restore sg */
-               sg->length += qc->pad_len;
-               return -1;
-       }
-
-       sg_dma_address(sg) = dma_address;
-       sg_dma_len(sg) = sg->length;
-
-skip_map:
-       DPRINTK("mapped buffer of %d bytes for %s\n", sg_dma_len(sg),
-               qc->tf.flags & ATA_TFLAG_WRITE ? "write" : "read");
-
-       return 0;
-}
-
-/**
- *     ata_sg_setup - DMA-map the scatter-gather table associated with a command.
- *     @qc: Command with scatter-gather table to be mapped.
- *
- *     DMA-map the scatter-gather table associated with queued_cmd @qc.
- *
- *     LOCKING:
- *     spin_lock_irqsave(host_set lock)
- *
- *     RETURNS:
- *     Zero on success, negative on error.
- *
- */
-
-static int ata_sg_setup(struct ata_queued_cmd *qc)
-{
-       struct ata_port *ap = qc->ap;
-       struct scatterlist *sg = qc->__sg;
-       struct scatterlist *lsg = &sg[qc->n_elem - 1];
-       int n_elem, pre_n_elem, dir, trim_sg = 0;
-
-       VPRINTK("ENTER, ata%u\n", ap->id);
-       WARN_ON(!(qc->flags & ATA_QCFLAG_SG));
-
-       /* we must lengthen transfers to end on a 32-bit boundary */
-       qc->pad_len = lsg->length & 3;
-       if (qc->pad_len) {
-               void *pad_buf = ap->pad + (qc->tag * ATA_DMA_PAD_SZ);
-               struct scatterlist *psg = &qc->pad_sgent;
-               unsigned int offset;
-
-               WARN_ON(qc->dev->class != ATA_DEV_ATAPI);
-
-               memset(pad_buf, 0, ATA_DMA_PAD_SZ);
-
-               /*
-                * psg->page/offset are used to copy to-be-written
-                * data in this function or read data in ata_sg_clean.
-                */
-               offset = lsg->offset + lsg->length - qc->pad_len;
-               psg->page = nth_page(lsg->page, offset >> PAGE_SHIFT);
-               psg->offset = offset_in_page(offset);
-
-               if (qc->tf.flags & ATA_TFLAG_WRITE) {
-                       void *addr = kmap_atomic(psg->page, KM_IRQ0);
-                       memcpy(pad_buf, addr + psg->offset, qc->pad_len);
-                       kunmap_atomic(addr, KM_IRQ0);
-               }
-
-               sg_dma_address(psg) = ap->pad_dma + (qc->tag * ATA_DMA_PAD_SZ);
-               sg_dma_len(psg) = ATA_DMA_PAD_SZ;
-               /* trim last sg */
-               lsg->length -= qc->pad_len;
-               if (lsg->length == 0)
-                       trim_sg = 1;
-
-               DPRINTK("padding done, sg[%d].length=%u pad_len=%u\n",
-                       qc->n_elem - 1, lsg->length, qc->pad_len);
-       }
-
-       pre_n_elem = qc->n_elem;
-       if (trim_sg && pre_n_elem)
-               pre_n_elem--;
-
-       if (!pre_n_elem) {
-               n_elem = 0;
-               goto skip_map;
-       }
-
-       dir = qc->dma_dir;
-       n_elem = dma_map_sg(ap->dev, sg, pre_n_elem, dir);
-       if (n_elem < 1) {
-               /* restore last sg */
-               lsg->length += qc->pad_len;
-               return -1;
-       }
-
-       DPRINTK("%d sg elements mapped\n", n_elem);
-
-skip_map:
-       qc->n_elem = n_elem;
-
-       return 0;
-}
-
-/**
- *     swap_buf_le16 - swap halves of 16-bit words in place
- *     @buf:  Buffer to swap
- *     @buf_words:  Number of 16-bit words in buffer.
- *
- *     Swap halves of 16-bit words if needed to convert from
- *     little-endian byte order to native cpu byte order, or
- *     vice-versa.
- *
- *     LOCKING:
- *     Inherited from caller.
- */
-void swap_buf_le16(u16 *buf, unsigned int buf_words)
-{
-#ifdef __BIG_ENDIAN
-       unsigned int i;
-
-       for (i = 0; i < buf_words; i++)
-               buf[i] = le16_to_cpu(buf[i]);
-#endif /* __BIG_ENDIAN */
-}
-
-/**
- *     ata_mmio_data_xfer - Transfer data by MMIO
- *     @adev: device for this I/O
- *     @buf: data buffer
- *     @buflen: buffer length
- *     @write_data: read/write
- *
- *     Transfer data from/to the device data register by MMIO.
- *
- *     LOCKING:
- *     Inherited from caller.
- */
-
-void ata_mmio_data_xfer(struct ata_device *adev, unsigned char *buf,
-                       unsigned int buflen, int write_data)
-{
-       struct ata_port *ap = adev->ap;
-       unsigned int i;
-       unsigned int words = buflen >> 1;
-       u16 *buf16 = (u16 *) buf;
-       void __iomem *mmio = (void __iomem *)ap->ioaddr.data_addr;
-
-       /* Transfer multiple of 2 bytes */
-       if (write_data) {
-               for (i = 0; i < words; i++)
-                       writew(le16_to_cpu(buf16[i]), mmio);
-       } else {
-               for (i = 0; i < words; i++)
-                       buf16[i] = cpu_to_le16(readw(mmio));
-       }
-
-       /* Transfer trailing 1 byte, if any. */
-       if (unlikely(buflen & 0x01)) {
-               u16 align_buf[1] = { 0 };
-               unsigned char *trailing_buf = buf + buflen - 1;
-
-               if (write_data) {
-                       memcpy(align_buf, trailing_buf, 1);
-                       writew(le16_to_cpu(align_buf[0]), mmio);
-               } else {
-                       align_buf[0] = cpu_to_le16(readw(mmio));
-                       memcpy(trailing_buf, align_buf, 1);
-               }
-       }
-}
-
-/**
- *     ata_pio_data_xfer - Transfer data by PIO
- *     @adev: device to target
- *     @buf: data buffer
- *     @buflen: buffer length
- *     @write_data: read/write
- *
- *     Transfer data from/to the device data register by PIO.
- *
- *     LOCKING:
- *     Inherited from caller.
- */
-
-void ata_pio_data_xfer(struct ata_device *adev, unsigned char *buf,
-                      unsigned int buflen, int write_data)
-{
-       struct ata_port *ap = adev->ap;
-       unsigned int words = buflen >> 1;
-
-       /* Transfer multiple of 2 bytes */
-       if (write_data)
-               outsw(ap->ioaddr.data_addr, buf, words);
-       else
-               insw(ap->ioaddr.data_addr, buf, words);
-
-       /* Transfer trailing 1 byte, if any. */
-       if (unlikely(buflen & 0x01)) {
-               u16 align_buf[1] = { 0 };
-               unsigned char *trailing_buf = buf + buflen - 1;
-
-               if (write_data) {
-                       memcpy(align_buf, trailing_buf, 1);
-                       outw(le16_to_cpu(align_buf[0]), ap->ioaddr.data_addr);
-               } else {
-                       align_buf[0] = cpu_to_le16(inw(ap->ioaddr.data_addr));
-                       memcpy(trailing_buf, align_buf, 1);
-               }
-       }
-}
-
-/**
- *     ata_pio_data_xfer_noirq - Transfer data by PIO
- *     @adev: device to target
- *     @buf: data buffer
- *     @buflen: buffer length
- *     @write_data: read/write
- *
- *     Transfer data from/to the device data register by PIO. Do the
- *     transfer with interrupts disabled.
- *
- *     LOCKING:
- *     Inherited from caller.
- */
-
-void ata_pio_data_xfer_noirq(struct ata_device *adev, unsigned char *buf,
-                                   unsigned int buflen, int write_data)
-{
-       unsigned long flags;
-       local_irq_save(flags);
-       ata_pio_data_xfer(adev, buf, buflen, write_data);
-       local_irq_restore(flags);
-}
-
-
-/**
- *     ata_pio_sector - Transfer ATA_SECT_SIZE (512 bytes) of data.
- *     @qc: Command on going
- *
- *     Transfer ATA_SECT_SIZE of data from/to the ATA device.
- *
- *     LOCKING:
- *     Inherited from caller.
- */
-
-static void ata_pio_sector(struct ata_queued_cmd *qc)
-{
-       int do_write = (qc->tf.flags & ATA_TFLAG_WRITE);
-       struct scatterlist *sg = qc->__sg;
-       struct ata_port *ap = qc->ap;
-       struct page *page;
-       unsigned int offset;
-       unsigned char *buf;
-
-       if (qc->cursect == (qc->nsect - 1))
-               ap->hsm_task_state = HSM_ST_LAST;
-
-       page = sg[qc->cursg].page;
-       offset = sg[qc->cursg].offset + qc->cursg_ofs * ATA_SECT_SIZE;
-
-       /* get the current page and offset */
-       page = nth_page(page, (offset >> PAGE_SHIFT));
-       offset %= PAGE_SIZE;
-
-       DPRINTK("data %s\n", qc->tf.flags & ATA_TFLAG_WRITE ? "write" : "read");
-
-       if (PageHighMem(page)) {
-               unsigned long flags;
-
-               /* FIXME: use a bounce buffer */
-               local_irq_save(flags);
-               buf = kmap_atomic(page, KM_IRQ0);
-
-               /* do the actual data transfer */
-               ap->ops->data_xfer(qc->dev, buf + offset, ATA_SECT_SIZE, do_write);
-
-               kunmap_atomic(buf, KM_IRQ0);
-               local_irq_restore(flags);
-       } else {
-               buf = page_address(page);
-               ap->ops->data_xfer(qc->dev, buf + offset, ATA_SECT_SIZE, do_write);
-       }
-
-       qc->cursect++;
-       qc->cursg_ofs++;
-
-       if ((qc->cursg_ofs * ATA_SECT_SIZE) == (&sg[qc->cursg])->length) {
-               qc->cursg++;
-               qc->cursg_ofs = 0;
-       }
-}
-
-/**
- *     ata_pio_sectors - Transfer one or many 512-byte sectors.
- *     @qc: Command on going
- *
- *     Transfer one or many ATA_SECT_SIZE of data from/to the
- *     ATA device for the DRQ request.
- *
- *     LOCKING:
- *     Inherited from caller.
- */
-
-static void ata_pio_sectors(struct ata_queued_cmd *qc)
-{
-       if (is_multi_taskfile(&qc->tf)) {
-               /* READ/WRITE MULTIPLE */
-               unsigned int nsect;
-
-               WARN_ON(qc->dev->multi_count == 0);
-
-               nsect = min(qc->nsect - qc->cursect, qc->dev->multi_count);
-               while (nsect--)
-                       ata_pio_sector(qc);
-       } else
-               ata_pio_sector(qc);
-}
-
-/**
- *     atapi_send_cdb - Write CDB bytes to hardware
- *     @ap: Port to which ATAPI device is attached.
- *     @qc: Taskfile currently active
- *
- *     When device has indicated its readiness to accept
- *     a CDB, this function is called.  Send the CDB.
- *
- *     LOCKING:
- *     caller.
- */
-
-static void atapi_send_cdb(struct ata_port *ap, struct ata_queued_cmd *qc)
-{
-       /* send SCSI cdb */
-       DPRINTK("send cdb\n");
-       WARN_ON(qc->dev->cdb_len < 12);
-
-       ap->ops->data_xfer(qc->dev, qc->cdb, qc->dev->cdb_len, 1);
-       ata_altstatus(ap); /* flush */
-
-       switch (qc->tf.protocol) {
-       case ATA_PROT_ATAPI:
-               ap->hsm_task_state = HSM_ST;
-               break;
-       case ATA_PROT_ATAPI_NODATA:
-               ap->hsm_task_state = HSM_ST_LAST;
-               break;
-       case ATA_PROT_ATAPI_DMA:
-               ap->hsm_task_state = HSM_ST_LAST;
-               /* initiate bmdma */
-               ap->ops->bmdma_start(qc);
-               break;
-       }
-}
-
-/**
- *     __atapi_pio_bytes - Transfer data from/to the ATAPI device.
- *     @qc: Command on going
- *     @bytes: number of bytes
- *
- *     Transfer Transfer data from/to the ATAPI device.
- *
- *     LOCKING:
- *     Inherited from caller.
- *
- */
-
-static void __atapi_pio_bytes(struct ata_queued_cmd *qc, unsigned int bytes)
-{
-       int do_write = (qc->tf.flags & ATA_TFLAG_WRITE);
-       struct scatterlist *sg = qc->__sg;
-       struct ata_port *ap = qc->ap;
-       struct page *page;
-       unsigned char *buf;
-       unsigned int offset, count;
-
-       if (qc->curbytes + bytes >= qc->nbytes)
-               ap->hsm_task_state = HSM_ST_LAST;
-
-next_sg:
-       if (unlikely(qc->cursg >= qc->n_elem)) {
-               /*
-                * The end of qc->sg is reached and the device expects
-                * more data to transfer. In order not to overrun qc->sg
-                * and fulfill length specified in the byte count register,
-                *    - for read case, discard trailing data from the device
-                *    - for write case, padding zero data to the device
-                */
-               u16 pad_buf[1] = { 0 };
-               unsigned int words = bytes >> 1;
-               unsigned int i;
-
-               if (words) /* warning if bytes > 1 */
-                       ata_dev_printk(qc->dev, KERN_WARNING,
-                                      "%u bytes trailing data\n", bytes);
-
-               for (i = 0; i < words; i++)
-                       ap->ops->data_xfer(qc->dev, (unsigned char*)pad_buf, 2, do_write);
-
-               ap->hsm_task_state = HSM_ST_LAST;
-               return;
-       }
-
-       sg = &qc->__sg[qc->cursg];
-
-       page = sg->page;
-       offset = sg->offset + qc->cursg_ofs;
-
-       /* get the current page and offset */
-       page = nth_page(page, (offset >> PAGE_SHIFT));
-       offset %= PAGE_SIZE;
-
-       /* don't overrun current sg */
-       count = min(sg->length - qc->cursg_ofs, bytes);
-
-       /* don't cross page boundaries */
-       count = min(count, (unsigned int)PAGE_SIZE - offset);
-
-       DPRINTK("data %s\n", qc->tf.flags & ATA_TFLAG_WRITE ? "write" : "read");
-
-       if (PageHighMem(page)) {
-               unsigned long flags;
-
-               /* FIXME: use bounce buffer */
-               local_irq_save(flags);
-               buf = kmap_atomic(page, KM_IRQ0);
-
-               /* do the actual data transfer */
-               ap->ops->data_xfer(qc->dev,  buf + offset, count, do_write);
-
-               kunmap_atomic(buf, KM_IRQ0);
-               local_irq_restore(flags);
-       } else {
-               buf = page_address(page);
-               ap->ops->data_xfer(qc->dev,  buf + offset, count, do_write);
-       }
-
-       bytes -= count;
-       qc->curbytes += count;
-       qc->cursg_ofs += count;
-
-       if (qc->cursg_ofs == sg->length) {
-               qc->cursg++;
-               qc->cursg_ofs = 0;
-       }
-
-       if (bytes)
-               goto next_sg;
-}
-
-/**
- *     atapi_pio_bytes - Transfer data from/to the ATAPI device.
- *     @qc: Command on going
- *
- *     Transfer Transfer data from/to the ATAPI device.
- *
- *     LOCKING:
- *     Inherited from caller.
- */
-
-static void atapi_pio_bytes(struct ata_queued_cmd *qc)
-{
-       struct ata_port *ap = qc->ap;
-       struct ata_device *dev = qc->dev;
-       unsigned int ireason, bc_lo, bc_hi, bytes;
-       int i_write, do_write = (qc->tf.flags & ATA_TFLAG_WRITE) ? 1 : 0;
-
-       /* Abuse qc->result_tf for temp storage of intermediate TF
-        * here to save some kernel stack usage.
-        * For normal completion, qc->result_tf is not relevant. For
-        * error, qc->result_tf is later overwritten by ata_qc_complete().
-        * So, the correctness of qc->result_tf is not affected.
-        */
-       ap->ops->tf_read(ap, &qc->result_tf);
-       ireason = qc->result_tf.nsect;
-       bc_lo = qc->result_tf.lbam;
-       bc_hi = qc->result_tf.lbah;
-       bytes = (bc_hi << 8) | bc_lo;
-
-       /* shall be cleared to zero, indicating xfer of data */
-       if (ireason & (1 << 0))
-               goto err_out;
-
-       /* make sure transfer direction matches expected */
-       i_write = ((ireason & (1 << 1)) == 0) ? 1 : 0;
-       if (do_write != i_write)
-               goto err_out;
-
-       VPRINTK("ata%u: xfering %d bytes\n", ap->id, bytes);
-
-       __atapi_pio_bytes(qc, bytes);
-
-       return;
-
-err_out:
-       ata_dev_printk(dev, KERN_INFO, "ATAPI check failed\n");
-       qc->err_mask |= AC_ERR_HSM;
-       ap->hsm_task_state = HSM_ST_ERR;
-}
-
-/**
- *     ata_hsm_ok_in_wq - Check if the qc can be handled in the workqueue.
- *     @ap: the target ata_port
- *     @qc: qc on going
- *
- *     RETURNS:
- *     1 if ok in workqueue, 0 otherwise.
- */
-
-static inline int ata_hsm_ok_in_wq(struct ata_port *ap, struct ata_queued_cmd *qc)
-{
-       if (qc->tf.flags & ATA_TFLAG_POLLING)
-               return 1;
-
-       if (ap->hsm_task_state == HSM_ST_FIRST) {
-               if (qc->tf.protocol == ATA_PROT_PIO &&
-                   (qc->tf.flags & ATA_TFLAG_WRITE))
-                   return 1;
-
-               if (is_atapi_taskfile(&qc->tf) &&
-                   !(qc->dev->flags & ATA_DFLAG_CDB_INTR))
-                       return 1;
-       }
-
-       return 0;
-}
-
-/**
- *     ata_hsm_qc_complete - finish a qc running on standard HSM
- *     @qc: Command to complete
- *     @in_wq: 1 if called from workqueue, 0 otherwise
- *
- *     Finish @qc which is running on standard HSM.
- *
- *     LOCKING:
- *     If @in_wq is zero, spin_lock_irqsave(host_set lock).
- *     Otherwise, none on entry and grabs host lock.
- */
-static void ata_hsm_qc_complete(struct ata_queued_cmd *qc, int in_wq)
-{
-       struct ata_port *ap = qc->ap;
-       unsigned long flags;
-
-       if (ap->ops->error_handler) {
-               if (in_wq) {
-                       spin_lock_irqsave(ap->lock, flags);
-
-                       /* EH might have kicked in while host_set lock
-                        * is released.
-                        */
-                       qc = ata_qc_from_tag(ap, qc->tag);
-                       if (qc) {
-                               if (likely(!(qc->err_mask & AC_ERR_HSM))) {
-                                       ata_irq_on(ap);
-                                       ata_qc_complete(qc);
-                               } else
-                                       ata_port_freeze(ap);
-                       }
-
-                       spin_unlock_irqrestore(ap->lock, flags);
-               } else {
-                       if (likely(!(qc->err_mask & AC_ERR_HSM)))
-                               ata_qc_complete(qc);
-                       else
-                               ata_port_freeze(ap);
-               }
-       } else {
-               if (in_wq) {
-                       spin_lock_irqsave(ap->lock, flags);
-                       ata_irq_on(ap);
-                       ata_qc_complete(qc);
-                       spin_unlock_irqrestore(ap->lock, flags);
-               } else
-                       ata_qc_complete(qc);
-       }
-
-       ata_altstatus(ap); /* flush */
-}
-
-/**
- *     ata_hsm_move - move the HSM to the next state.
- *     @ap: the target ata_port
- *     @qc: qc on going
- *     @status: current device status
- *     @in_wq: 1 if called from workqueue, 0 otherwise
- *
- *     RETURNS:
- *     1 when poll next status needed, 0 otherwise.
- */
-int ata_hsm_move(struct ata_port *ap, struct ata_queued_cmd *qc,
-                u8 status, int in_wq)
-{
-       unsigned long flags = 0;
-       int poll_next;
-
-       WARN_ON((qc->flags & ATA_QCFLAG_ACTIVE) == 0);
-
-       /* Make sure ata_qc_issue_prot() does not throw things
-        * like DMA polling into the workqueue. Notice that
-        * in_wq is not equivalent to (qc->tf.flags & ATA_TFLAG_POLLING).
-        */
-       WARN_ON(in_wq != ata_hsm_ok_in_wq(ap, qc));
-
-fsm_start:
-       DPRINTK("ata%u: protocol %d task_state %d (dev_stat 0x%X)\n",
-               ap->id, qc->tf.protocol, ap->hsm_task_state, status);
-
-       switch (ap->hsm_task_state) {
-       case HSM_ST_FIRST:
-               /* Send first data block or PACKET CDB */
-
-               /* If polling, we will stay in the work queue after
-                * sending the data. Otherwise, interrupt handler
-                * takes over after sending the data.
-                */
-               poll_next = (qc->tf.flags & ATA_TFLAG_POLLING);
-
-               /* check device status */
-               if (unlikely((status & ATA_DRQ) == 0)) {
-                       /* handle BSY=0, DRQ=0 as error */
-                       if (likely(status & (ATA_ERR | ATA_DF)))
-                               /* device stops HSM for abort/error */
-                               qc->err_mask |= AC_ERR_DEV;
-                       else
-                               /* HSM violation. Let EH handle this */
-                               qc->err_mask |= AC_ERR_HSM;
-
-                       ap->hsm_task_state = HSM_ST_ERR;
-                       goto fsm_start;
-               }
-
-               /* Device should not ask for data transfer (DRQ=1)
-                * when it finds something wrong.
-                * We ignore DRQ here and stop the HSM by
-                * changing hsm_task_state to HSM_ST_ERR and
-                * let the EH abort the command or reset the device.
-                */
-               if (unlikely(status & (ATA_ERR | ATA_DF))) {
-                       printk(KERN_WARNING "ata%d: DRQ=1 with device error, dev_stat 0x%X\n",
-                              ap->id, status);
-                       qc->err_mask |= AC_ERR_HSM;
-                       ap->hsm_task_state = HSM_ST_ERR;
-                       goto fsm_start;
-               }
-
-               /* Send the CDB (atapi) or the first data block (ata pio out).
-                * During the state transition, interrupt handler shouldn't
-                * be invoked before the data transfer is complete and
-                * hsm_task_state is changed. Hence, the following locking.
-                */
-               if (in_wq)
-                       spin_lock_irqsave(ap->lock, flags);
-
-               if (qc->tf.protocol == ATA_PROT_PIO) {
-                       /* PIO data out protocol.
-                        * send first data block.
-                        */
-
-                       /* ata_pio_sectors() might change the state
-                        * to HSM_ST_LAST. so, the state is changed here
-                        * before ata_pio_sectors().
-                        */
-                       ap->hsm_task_state = HSM_ST;
-                       ata_pio_sectors(qc);
-                       ata_altstatus(ap); /* flush */
-               } else
-                       /* send CDB */
-                       atapi_send_cdb(ap, qc);
-
-               if (in_wq)
-                       spin_unlock_irqrestore(ap->lock, flags);
-
-               /* if polling, ata_pio_task() handles the rest.
-                * otherwise, interrupt handler takes over from here.
-                */
-               break;
-
-       case HSM_ST:
-               /* complete command or read/write the data register */
-               if (qc->tf.protocol == ATA_PROT_ATAPI) {
-                       /* ATAPI PIO protocol */
-                       if ((status & ATA_DRQ) == 0) {
-                               /* No more data to transfer or device error.
-                                * Device error will be tagged in HSM_ST_LAST.
-                                */
-                               ap->hsm_task_state = HSM_ST_LAST;
-                               goto fsm_start;
-                       }
-
-                       /* Device should not ask for data transfer (DRQ=1)
-                        * when it finds something wrong.
-                        * We ignore DRQ here and stop the HSM by
-                        * changing hsm_task_state to HSM_ST_ERR and
-                        * let the EH abort the command or reset the device.
-                        */
-                       if (unlikely(status & (ATA_ERR | ATA_DF))) {
-                               printk(KERN_WARNING "ata%d: DRQ=1 with device error, dev_stat 0x%X\n",
-                                      ap->id, status);
-                               qc->err_mask |= AC_ERR_HSM;
-                               ap->hsm_task_state = HSM_ST_ERR;
-                               goto fsm_start;
-                       }
-
-                       atapi_pio_bytes(qc);
-
-                       if (unlikely(ap->hsm_task_state == HSM_ST_ERR))
-                               /* bad ireason reported by device */
-                               goto fsm_start;
-
-               } else {
-                       /* ATA PIO protocol */
-                       if (unlikely((status & ATA_DRQ) == 0)) {
-                               /* handle BSY=0, DRQ=0 as error */
-                               if (likely(status & (ATA_ERR | ATA_DF)))
-                                       /* device stops HSM for abort/error */
-                                       qc->err_mask |= AC_ERR_DEV;
-                               else
-                                       /* HSM violation. Let EH handle this */
-                                       qc->err_mask |= AC_ERR_HSM;
-
-                               ap->hsm_task_state = HSM_ST_ERR;
-                               goto fsm_start;
-                       }
-
-                       /* For PIO reads, some devices may ask for
-                        * data transfer (DRQ=1) alone with ERR=1.
-                        * We respect DRQ here and transfer one
-                        * block of junk data before changing the
-                        * hsm_task_state to HSM_ST_ERR.
-                        *
-                        * For PIO writes, ERR=1 DRQ=1 doesn't make
-                        * sense since the data block has been
-                        * transferred to the device.
-                        */
-                       if (unlikely(status & (ATA_ERR | ATA_DF))) {
-                               /* data might be corrputed */
-                               qc->err_mask |= AC_ERR_DEV;
-
-                               if (!(qc->tf.flags & ATA_TFLAG_WRITE)) {
-                                       ata_pio_sectors(qc);
-                                       ata_altstatus(ap);
-                                       status = ata_wait_idle(ap);
-                               }
-
-                               if (status & (ATA_BUSY | ATA_DRQ))
-                                       qc->err_mask |= AC_ERR_HSM;
-
-                               /* ata_pio_sectors() might change the
-                                * state to HSM_ST_LAST. so, the state
-                                * is changed after ata_pio_sectors().
-                                */
-                               ap->hsm_task_state = HSM_ST_ERR;
-                               goto fsm_start;
-                       }
-
-                       ata_pio_sectors(qc);
-
-                       if (ap->hsm_task_state == HSM_ST_LAST &&
-                           (!(qc->tf.flags & ATA_TFLAG_WRITE))) {
-                               /* all data read */
-                               ata_altstatus(ap);
-                               status = ata_wait_idle(ap);
-                               goto fsm_start;
-                       }
-               }
-
-               ata_altstatus(ap); /* flush */
-               poll_next = 1;
-               break;
-
-       case HSM_ST_LAST:
-               if (unlikely(!ata_ok(status))) {
-                       qc->err_mask |= __ac_err_mask(status);
-                       ap->hsm_task_state = HSM_ST_ERR;
-                       goto fsm_start;
-               }
-
-               /* no more data to transfer */
-               DPRINTK("ata%u: dev %u command complete, drv_stat 0x%x\n",
-                       ap->id, qc->dev->devno, status);
-
-               WARN_ON(qc->err_mask);
-
-               ap->hsm_task_state = HSM_ST_IDLE;
-
-               /* complete taskfile transaction */
-               ata_hsm_qc_complete(qc, in_wq);
-
-               poll_next = 0;
-               break;
-
-       case HSM_ST_ERR:
-               /* make sure qc->err_mask is available to
-                * know what's wrong and recover
-                */
-               WARN_ON(qc->err_mask == 0);
-
-               ap->hsm_task_state = HSM_ST_IDLE;
-
-               /* complete taskfile transaction */
-               ata_hsm_qc_complete(qc, in_wq);
-
-               poll_next = 0;
-               break;
-       default:
-               poll_next = 0;
-               BUG();
-       }
-
-       return poll_next;
-}
-
-static void ata_pio_task(void *_data)
-{
-       struct ata_queued_cmd *qc = _data;
-       struct ata_port *ap = qc->ap;
-       u8 status;
-       int poll_next;
-
-fsm_start:
-       WARN_ON(ap->hsm_task_state == HSM_ST_IDLE);
-
-       /*
-        * This is purely heuristic.  This is a fast path.
-        * Sometimes when we enter, BSY will be cleared in
-        * a chk-status or two.  If not, the drive is probably seeking
-        * or something.  Snooze for a couple msecs, then
-        * chk-status again.  If still busy, queue delayed work.
-        */
-       status = ata_busy_wait(ap, ATA_BUSY, 5);
-       if (status & ATA_BUSY) {
-               msleep(2);
-               status = ata_busy_wait(ap, ATA_BUSY, 10);
-               if (status & ATA_BUSY) {
-                       ata_port_queue_task(ap, ata_pio_task, qc, ATA_SHORT_PAUSE);
-                       return;
-               }
-       }
-
-       /* move the HSM */
-       poll_next = ata_hsm_move(ap, qc, status, 1);
-
-       /* another command or interrupt handler
-        * may be running at this point.
-        */
-       if (poll_next)
-               goto fsm_start;
-}
-
-/**
- *     ata_qc_new - Request an available ATA command, for queueing
- *     @ap: Port associated with device @dev
- *     @dev: Device from whom we request an available command structure
- *
- *     LOCKING:
- *     None.
- */
-
-static struct ata_queued_cmd *ata_qc_new(struct ata_port *ap)
-{
-       struct ata_queued_cmd *qc = NULL;
-       unsigned int i;
-
-       /* no command while frozen */
-       if (unlikely(ap->pflags & ATA_PFLAG_FROZEN))
-               return NULL;
-
-       /* the last tag is reserved for internal command. */
-       for (i = 0; i < ATA_MAX_QUEUE - 1; i++)
-               if (!test_and_set_bit(i, &ap->qc_allocated)) {
-                       qc = __ata_qc_from_tag(ap, i);
-                       break;
-               }
-
-       if (qc)
-               qc->tag = i;
-
-       return qc;
-}
-
-/**
- *     ata_qc_new_init - Request an available ATA command, and initialize it
- *     @dev: Device from whom we request an available command structure
- *
- *     LOCKING:
- *     None.
- */
-
-struct ata_queued_cmd *ata_qc_new_init(struct ata_device *dev)
-{
-       struct ata_port *ap = dev->ap;
-       struct ata_queued_cmd *qc;
-
-       qc = ata_qc_new(ap);
-       if (qc) {
-               qc->scsicmd = NULL;
-               qc->ap = ap;
-               qc->dev = dev;
-
-               ata_qc_reinit(qc);
-       }
-
-       return qc;
-}
-
-/**
- *     ata_qc_free - free unused ata_queued_cmd
- *     @qc: Command to complete
- *
- *     Designed to free unused ata_queued_cmd object
- *     in case something prevents using it.
- *
- *     LOCKING:
- *     spin_lock_irqsave(host_set lock)
- */
-void ata_qc_free(struct ata_queued_cmd *qc)
-{
-       struct ata_port *ap = qc->ap;
-       unsigned int tag;
-
-       WARN_ON(qc == NULL);    /* ata_qc_from_tag _might_ return NULL */
-
-       qc->flags = 0;
-       tag = qc->tag;
-       if (likely(ata_tag_valid(tag))) {
-               qc->tag = ATA_TAG_POISON;
-               clear_bit(tag, &ap->qc_allocated);
-       }
-}
-
-void __ata_qc_complete(struct ata_queued_cmd *qc)
-{
-       struct ata_port *ap = qc->ap;
-
-       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);
-
-       /* command should be marked inactive atomically with qc completion */
-       if (qc->tf.protocol == ATA_PROT_NCQ)
-               ap->sactive &= ~(1 << qc->tag);
-       else
-               ap->active_tag = ATA_TAG_POISON;
-
-       /* atapi: mark qc as inactive to prevent the interrupt handler
-        * from completing the command twice later, before the error handler
-        * is called. (when rc != 0 and atapi request sense is needed)
-        */
-       qc->flags &= ~ATA_QCFLAG_ACTIVE;
-       ap->qc_active &= ~(1 << qc->tag);
-
-       /* call completion callback */
-       qc->complete_fn(qc);
-}
-
-/**
- *     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)
- */
-void ata_qc_complete(struct ata_queued_cmd *qc)
-{
-       struct ata_port *ap = qc->ap;
-
-       /* XXX: New EH and old EH use different mechanisms to
-        * synchronize EH with regular execution path.
-        *
-        * In new EH, a failed qc is marked with ATA_QCFLAG_FAILED.
-        * Normal execution path is responsible for not accessing a
-        * failed qc.  libata core enforces the rule by returning NULL
-        * from ata_qc_from_tag() for failed qcs.
-        *
-        * Old EH depends on ata_qc_complete() nullifying completion
-        * requests if ATA_QCFLAG_EH_SCHEDULED is set.  Old EH does
-        * not synchronize with interrupt handler.  Only PIO task is
-        * taken care of.
-        */
-       if (ap->ops->error_handler) {
-               WARN_ON(ap->pflags & ATA_PFLAG_FROZEN);
-
-               if (unlikely(qc->err_mask))
-                       qc->flags |= ATA_QCFLAG_FAILED;
-
-               if (unlikely(qc->flags & ATA_QCFLAG_FAILED)) {
-                       if (!ata_tag_internal(qc->tag)) {
-                               /* always fill result TF for failed qc */
-                               ap->ops->tf_read(ap, &qc->result_tf);
-                               ata_qc_schedule_eh(qc);
-                               return;
-                       }
-               }
-
-               /* read result TF if requested */
-               if (qc->flags & ATA_QCFLAG_RESULT_TF)
-                       ap->ops->tf_read(ap, &qc->result_tf);
-
-               __ata_qc_complete(qc);
-       } else {
-               if (qc->flags & ATA_QCFLAG_EH_SCHEDULED)
-                       return;
-
-               /* read result TF if failed or requested */
-               if (qc->err_mask || qc->flags & ATA_QCFLAG_RESULT_TF)
-                       ap->ops->tf_read(ap, &qc->result_tf);
-
-               __ata_qc_complete(qc);
-       }
-}
-
-/**
- *     ata_qc_complete_multiple - Complete multiple qcs successfully
- *     @ap: port in question
- *     @qc_active: new qc_active mask
- *     @finish_qc: LLDD callback invoked before completing a qc
- *
- *     Complete in-flight commands.  This functions is meant to be
- *     called from low-level driver's interrupt routine to complete
- *     requests normally.  ap->qc_active and @qc_active is compared
- *     and commands are completed accordingly.
- *
- *     LOCKING:
- *     spin_lock_irqsave(host_set lock)
- *
- *     RETURNS:
- *     Number of completed commands on success, -errno otherwise.
- */
-int ata_qc_complete_multiple(struct ata_port *ap, u32 qc_active,
-                            void (*finish_qc)(struct ata_queued_cmd *))
-{
-       int nr_done = 0;
-       u32 done_mask;
-       int i;
-
-       done_mask = ap->qc_active ^ qc_active;
-
-       if (unlikely(done_mask & qc_active)) {
-               ata_port_printk(ap, KERN_ERR, "illegal qc_active transition "
-                               "(%08x->%08x)\n", ap->qc_active, qc_active);
-               return -EINVAL;
-       }
-
-       for (i = 0; i < ATA_MAX_QUEUE; i++) {
-               struct ata_queued_cmd *qc;
-
-               if (!(done_mask & (1 << i)))
-                       continue;
-
-               if ((qc = ata_qc_from_tag(ap, i))) {
-                       if (finish_qc)
-                               finish_qc(qc);
-                       ata_qc_complete(qc);
-                       nr_done++;
-               }
-       }
-
-       return nr_done;
-}
-
-static inline int ata_should_dma_map(struct ata_queued_cmd *qc)
-{
-       struct ata_port *ap = qc->ap;
-
-       switch (qc->tf.protocol) {
-       case ATA_PROT_NCQ:
-       case ATA_PROT_DMA:
-       case ATA_PROT_ATAPI_DMA:
-               return 1;
-
-       case ATA_PROT_ATAPI:
-       case ATA_PROT_PIO:
-               if (ap->flags & ATA_FLAG_PIO_DMA)
-                       return 1;
-
-               /* fall through */
-
-       default:
-               return 0;
-       }
-
-       /* never reached */
-}
-
-/**
- *     ata_qc_issue - issue taskfile to device
- *     @qc: command to issue to device
- *
- *     Prepare an ATA command to submission to device.
- *     This includes mapping the data into a DMA-able
- *     area, filling in the S/G table, and finally
- *     writing the taskfile to hardware, starting the command.
- *
- *     LOCKING:
- *     spin_lock_irqsave(host_set lock)
- */
-void ata_qc_issue(struct ata_queued_cmd *qc)
-{
-       struct ata_port *ap = qc->ap;
-
-       /* Make sure only one non-NCQ command is outstanding.  The
-        * check is skipped for old EH because it reuses active qc to
-        * request ATAPI sense.
-        */
-       WARN_ON(ap->ops->error_handler && ata_tag_valid(ap->active_tag));
-
-       if (qc->tf.protocol == ATA_PROT_NCQ) {
-               WARN_ON(ap->sactive & (1 << qc->tag));
-               ap->sactive |= 1 << qc->tag;
-       } else {
-               WARN_ON(ap->sactive);
-               ap->active_tag = qc->tag;
-       }
-
-       qc->flags |= ATA_QCFLAG_ACTIVE;
-       ap->qc_active |= 1 << qc->tag;
-
-       if (ata_should_dma_map(qc)) {
-               if (qc->flags & ATA_QCFLAG_SG) {
-                       if (ata_sg_setup(qc))
-                               goto sg_err;
-               } else if (qc->flags & ATA_QCFLAG_SINGLE) {
-                       if (ata_sg_setup_one(qc))
-                               goto sg_err;
-               }
-       } else {
-               qc->flags &= ~ATA_QCFLAG_DMAMAP;
-       }
-
-       ap->ops->qc_prep(qc);
-
-       qc->err_mask |= ap->ops->qc_issue(qc);
-       if (unlikely(qc->err_mask))
-               goto err;
-       return;
-
-sg_err:
-       qc->flags &= ~ATA_QCFLAG_DMAMAP;
-       qc->err_mask |= AC_ERR_SYSTEM;
-err:
-       ata_qc_complete(qc);
-}
-
-/**
- *     ata_qc_issue_prot - issue taskfile to device in proto-dependent manner
- *     @qc: command to issue to device
- *
- *     Using various libata functions and hooks, this function
- *     starts an ATA command.  ATA commands are grouped into
- *     classes called "protocols", and issuing each type of protocol
- *     is slightly different.
- *
- *     May be used as the qc_issue() entry in ata_port_operations.
- *
- *     LOCKING:
- *     spin_lock_irqsave(host_set lock)
- *
- *     RETURNS:
- *     Zero on success, AC_ERR_* mask on failure
- */
-
-unsigned int ata_qc_issue_prot(struct ata_queued_cmd *qc)
-{
-       struct ata_port *ap = qc->ap;
-
-       /* Use polling pio if the LLD doesn't handle
-        * interrupt driven pio and atapi CDB interrupt.
-        */
-       if (ap->flags & ATA_FLAG_PIO_POLLING) {
-               switch (qc->tf.protocol) {
-               case ATA_PROT_PIO:
-               case ATA_PROT_ATAPI:
-               case ATA_PROT_ATAPI_NODATA:
-                       qc->tf.flags |= ATA_TFLAG_POLLING;
-                       break;
-               case ATA_PROT_ATAPI_DMA:
-                       if (qc->dev->flags & ATA_DFLAG_CDB_INTR)
-                               /* see ata_dma_blacklisted() */
-                               BUG();
-                       break;
-               default:
-                       break;
-               }
-       }
-
-       /* select the device */
-       ata_dev_select(ap, qc->dev->devno, 1, 0);
-
-       /* start the command */
-       switch (qc->tf.protocol) {
-       case ATA_PROT_NODATA:
-               if (qc->tf.flags & ATA_TFLAG_POLLING)
-                       ata_qc_set_polling(qc);
-
-               ata_tf_to_host(ap, &qc->tf);
-               ap->hsm_task_state = HSM_ST_LAST;
-
-               if (qc->tf.flags & ATA_TFLAG_POLLING)
-                       ata_port_queue_task(ap, ata_pio_task, qc, 0);
-
-               break;
-
-       case ATA_PROT_DMA:
-               WARN_ON(qc->tf.flags & ATA_TFLAG_POLLING);
-
-               ap->ops->tf_load(ap, &qc->tf);   /* load tf registers */
-               ap->ops->bmdma_setup(qc);           /* set up bmdma */
-               ap->ops->bmdma_start(qc);           /* initiate bmdma */
-               ap->hsm_task_state = HSM_ST_LAST;
-               break;
-
-       case ATA_PROT_PIO:
-               if (qc->tf.flags & ATA_TFLAG_POLLING)
-                       ata_qc_set_polling(qc);
-
-               ata_tf_to_host(ap, &qc->tf);
-
-               if (qc->tf.flags & ATA_TFLAG_WRITE) {
-                       /* PIO data out protocol */
-                       ap->hsm_task_state = HSM_ST_FIRST;
-                       ata_port_queue_task(ap, ata_pio_task, qc, 0);
-
-                       /* always send first data block using
-                        * the ata_pio_task() codepath.
-                        */
-               } else {
-                       /* PIO data in protocol */
-                       ap->hsm_task_state = HSM_ST;
-
-                       if (qc->tf.flags & ATA_TFLAG_POLLING)
-                               ata_port_queue_task(ap, ata_pio_task, qc, 0);
-
-                       /* if polling, ata_pio_task() handles the rest.
-                        * otherwise, interrupt handler takes over from here.
-                        */
-               }
-
-               break;
-
-       case ATA_PROT_ATAPI:
-       case ATA_PROT_ATAPI_NODATA:
-               if (qc->tf.flags & ATA_TFLAG_POLLING)
-                       ata_qc_set_polling(qc);
-
-               ata_tf_to_host(ap, &qc->tf);
-
-               ap->hsm_task_state = HSM_ST_FIRST;
-
-               /* send cdb by polling if no cdb interrupt */
-               if ((!(qc->dev->flags & ATA_DFLAG_CDB_INTR)) ||
-                   (qc->tf.flags & ATA_TFLAG_POLLING))
-                       ata_port_queue_task(ap, ata_pio_task, qc, 0);
-               break;
-
-       case ATA_PROT_ATAPI_DMA:
-               WARN_ON(qc->tf.flags & ATA_TFLAG_POLLING);
-
-               ap->ops->tf_load(ap, &qc->tf);   /* load tf registers */
-               ap->ops->bmdma_setup(qc);           /* set up bmdma */
-               ap->hsm_task_state = HSM_ST_FIRST;
-
-               /* send cdb by polling if no cdb interrupt */
-               if (!(qc->dev->flags & ATA_DFLAG_CDB_INTR))
-                       ata_port_queue_task(ap, ata_pio_task, qc, 0);
-               break;
-
-       default:
-               WARN_ON(1);
-               return AC_ERR_SYSTEM;
-       }
-
-       return 0;
-}
-
-/**
- *     ata_host_intr - Handle host interrupt for given (port, task)
- *     @ap: Port on which interrupt arrived (possibly...)
- *     @qc: Taskfile currently active in engine
- *
- *     Handle host interrupt for given queued command.  Currently,
- *     only DMA interrupts are handled.  All other commands are
- *     handled via polling with interrupts disabled (nIEN bit).
- *
- *     LOCKING:
- *     spin_lock_irqsave(host_set lock)
- *
- *     RETURNS:
- *     One if interrupt was handled, zero if not (shared irq).
- */
-
-inline unsigned int ata_host_intr (struct ata_port *ap,
-                                  struct ata_queued_cmd *qc)
-{
-       u8 status, host_stat = 0;
-
-       VPRINTK("ata%u: protocol %d task_state %d\n",
-               ap->id, qc->tf.protocol, ap->hsm_task_state);
-
-       /* Check whether we are expecting interrupt in this state */
-       switch (ap->hsm_task_state) {
-       case HSM_ST_FIRST:
-               /* Some pre-ATAPI-4 devices assert INTRQ
-                * at this state when ready to receive CDB.
-                */
-
-               /* Check the ATA_DFLAG_CDB_INTR flag is enough here.
-                * The flag was turned on only for atapi devices.
-                * No need to check is_atapi_taskfile(&qc->tf) again.
-                */
-               if (!(qc->dev->flags & ATA_DFLAG_CDB_INTR))
-                       goto idle_irq;
-               break;
-       case HSM_ST_LAST:
-               if (qc->tf.protocol == ATA_PROT_DMA ||
-                   qc->tf.protocol == ATA_PROT_ATAPI_DMA) {
-                       /* check status of DMA engine */
-                       host_stat = ap->ops->bmdma_status(ap);
-                       VPRINTK("ata%u: host_stat 0x%X\n", ap->id, host_stat);
-
-                       /* if it's not our irq... */
-                       if (!(host_stat & ATA_DMA_INTR))
-                               goto idle_irq;
-
-                       /* before we do anything else, clear DMA-Start bit */
-                       ap->ops->bmdma_stop(qc);
-
-                       if (unlikely(host_stat & ATA_DMA_ERR)) {
-                               /* error when transfering data to/from memory */
-                               qc->err_mask |= AC_ERR_HOST_BUS;
-                               ap->hsm_task_state = HSM_ST_ERR;
-                       }
-               }
-               break;
-       case HSM_ST:
-               break;
-       default:
-               goto idle_irq;
-       }
-
-       /* check altstatus */
-       status = ata_altstatus(ap);
-       if (status & ATA_BUSY)
-               goto idle_irq;
-
-       /* check main status, clearing INTRQ */
-       status = ata_chk_status(ap);
-       if (unlikely(status & ATA_BUSY))
-               goto idle_irq;
-
-       /* ack bmdma irq events */
-       ap->ops->irq_clear(ap);
-
-       ata_hsm_move(ap, qc, status, 0);
-       return 1;       /* irq handled */
-
-idle_irq:
-       ap->stats.idle_irq++;
-
-#ifdef ATA_IRQ_TRAP
-       if ((ap->stats.idle_irq % 1000) == 0) {
-               ata_irq_ack(ap, 0); /* debug trap */
-               ata_port_printk(ap, KERN_WARNING, "irq trap\n");
-               return 1;
-       }
-#endif
-       return 0;       /* irq not handled */
-}
-
-/**
- *     ata_interrupt - Default ATA host interrupt handler
- *     @irq: irq line (unused)
- *     @dev_instance: pointer to our ata_host_set information structure
- *     @regs: unused
- *
- *     Default interrupt handler for PCI IDE devices.  Calls
- *     ata_host_intr() for each port that is not disabled.
- *
- *     LOCKING:
- *     Obtains host_set lock during operation.
- *
- *     RETURNS:
- *     IRQ_NONE or IRQ_HANDLED.
- */
-
-irqreturn_t ata_interrupt (int irq, void *dev_instance, struct pt_regs *regs)
-{
-       struct ata_host_set *host_set = dev_instance;
-       unsigned int i;
-       unsigned int handled = 0;
-       unsigned long flags;
-
-       /* TODO: make _irqsave conditional on x86 PCI IDE legacy mode */
-       spin_lock_irqsave(&host_set->lock, flags);
-
-       for (i = 0; i < host_set->n_ports; i++) {
-               struct ata_port *ap;
-
-               ap = host_set->ports[i];
-               if (ap &&
-                   !(ap->flags & ATA_FLAG_DISABLED)) {
-                       struct ata_queued_cmd *qc;
-
-                       qc = ata_qc_from_tag(ap, ap->active_tag);
-                       if (qc && (!(qc->tf.flags & ATA_TFLAG_POLLING)) &&
-                           (qc->flags & ATA_QCFLAG_ACTIVE))
-                               handled |= ata_host_intr(ap, qc);
-               }
-       }
-
-       spin_unlock_irqrestore(&host_set->lock, flags);
-
-       return IRQ_RETVAL(handled);
-}
-
-/**
- *     sata_scr_valid - test whether SCRs are accessible
- *     @ap: ATA port to test SCR accessibility for
- *
- *     Test whether SCRs are accessible for @ap.
- *
- *     LOCKING:
- *     None.
- *
- *     RETURNS:
- *     1 if SCRs are accessible, 0 otherwise.
- */
-int sata_scr_valid(struct ata_port *ap)
-{
-       return ap->cbl == ATA_CBL_SATA && ap->ops->scr_read;
-}
-
-/**
- *     sata_scr_read - read SCR register of the specified port
- *     @ap: ATA port to read SCR for
- *     @reg: SCR to read
- *     @val: Place to store read value
- *
- *     Read SCR register @reg of @ap into *@val.  This function is
- *     guaranteed to succeed if the cable type of the port is SATA
- *     and the port implements ->scr_read.
- *
- *     LOCKING:
- *     None.
- *
- *     RETURNS:
- *     0 on success, negative errno on failure.
- */
-int sata_scr_read(struct ata_port *ap, int reg, u32 *val)
-{
-       if (sata_scr_valid(ap)) {
-               *val = ap->ops->scr_read(ap, reg);
-               return 0;
-       }
-       return -EOPNOTSUPP;
-}
-
-/**
- *     sata_scr_write - write SCR register of the specified port
- *     @ap: ATA port to write SCR for
- *     @reg: SCR to write
- *     @val: value to write
- *
- *     Write @val to SCR register @reg of @ap.  This function is
- *     guaranteed to succeed if the cable type of the port is SATA
- *     and the port implements ->scr_read.
- *
- *     LOCKING:
- *     None.
- *
- *     RETURNS:
- *     0 on success, negative errno on failure.
- */
-int sata_scr_write(struct ata_port *ap, int reg, u32 val)
-{
-       if (sata_scr_valid(ap)) {
-               ap->ops->scr_write(ap, reg, val);
-               return 0;
-       }
-       return -EOPNOTSUPP;
-}
-
-/**
- *     sata_scr_write_flush - write SCR register of the specified port and flush
- *     @ap: ATA port to write SCR for
- *     @reg: SCR to write
- *     @val: value to write
- *
- *     This function is identical to sata_scr_write() except that this
- *     function performs flush after writing to the register.
- *
- *     LOCKING:
- *     None.
- *
- *     RETURNS:
- *     0 on success, negative errno on failure.
- */
-int sata_scr_write_flush(struct ata_port *ap, int reg, u32 val)
-{
-       if (sata_scr_valid(ap)) {
-               ap->ops->scr_write(ap, reg, val);
-               ap->ops->scr_read(ap, reg);
-               return 0;
-       }
-       return -EOPNOTSUPP;
-}
-
-/**
- *     ata_port_online - test whether the given port is online
- *     @ap: ATA port to test
- *
- *     Test whether @ap is online.  Note that this function returns 0
- *     if online status of @ap cannot be obtained, so
- *     ata_port_online(ap) != !ata_port_offline(ap).
- *
- *     LOCKING:
- *     None.
- *
- *     RETURNS:
- *     1 if the port online status is available and online.
- */
-int ata_port_online(struct ata_port *ap)
-{
-       u32 sstatus;
-
-       if (!sata_scr_read(ap, SCR_STATUS, &sstatus) && (sstatus & 0xf) == 0x3)
-               return 1;
-       return 0;
-}
-
-/**
- *     ata_port_offline - test whether the given port is offline
- *     @ap: ATA port to test
- *
- *     Test whether @ap is offline.  Note that this function returns
- *     0 if offline status of @ap cannot be obtained, so
- *     ata_port_online(ap) != !ata_port_offline(ap).
- *
- *     LOCKING:
- *     None.
- *
- *     RETURNS:
- *     1 if the port offline status is available and offline.
- */
-int ata_port_offline(struct ata_port *ap)
-{
-       u32 sstatus;
-
-       if (!sata_scr_read(ap, SCR_STATUS, &sstatus) && (sstatus & 0xf) != 0x3)
-               return 1;
-       return 0;
-}
-
-int ata_flush_cache(struct ata_device *dev)
-{
-       unsigned int err_mask;
-       u8 cmd;
-
-       if (!ata_try_flush_cache(dev))
-               return 0;
-
-       if (ata_id_has_flush_ext(dev->id))
-               cmd = ATA_CMD_FLUSH_EXT;
-       else
-               cmd = ATA_CMD_FLUSH;
-
-       err_mask = ata_do_simple_cmd(dev, cmd);
-       if (err_mask) {
-               ata_dev_printk(dev, KERN_ERR, "failed to flush cache\n");
-               return -EIO;
-       }
-
-       return 0;
-}
-
-static int ata_host_set_request_pm(struct ata_host_set *host_set,
-                                  pm_message_t mesg, unsigned int action,
-                                  unsigned int ehi_flags, int wait)
-{
-       unsigned long flags;
-       int i, rc;
-
-       for (i = 0; i < host_set->n_ports; i++) {
-               struct ata_port *ap = host_set->ports[i];
-
-               /* Previous resume operation might still be in
-                * progress.  Wait for PM_PENDING to clear.
-                */
-               if (ap->pflags & ATA_PFLAG_PM_PENDING) {
-                       ata_port_wait_eh(ap);
-                       WARN_ON(ap->pflags & ATA_PFLAG_PM_PENDING);
-               }
-
-               /* request PM ops to EH */
-               spin_lock_irqsave(ap->lock, flags);
-
-               ap->pm_mesg = mesg;
-               if (wait) {
-                       rc = 0;
-                       ap->pm_result = &rc;
-               }
-
-               ap->pflags |= ATA_PFLAG_PM_PENDING;
-               ap->eh_info.action |= action;
-               ap->eh_info.flags |= ehi_flags;
-
-               ata_port_schedule_eh(ap);
-
-               spin_unlock_irqrestore(ap->lock, flags);
-
-               /* wait and check result */
-               if (wait) {
-                       ata_port_wait_eh(ap);
-                       WARN_ON(ap->pflags & ATA_PFLAG_PM_PENDING);
-                       if (rc)
-                               return rc;
-               }
-       }
-
-       return 0;
-}
-
-/**
- *     ata_host_set_suspend - suspend host_set
- *     @host_set: host_set to suspend
- *     @mesg: PM message
- *
- *     Suspend @host_set.  Actual operation is performed by EH.  This
- *     function requests EH to perform PM operations and waits for EH
- *     to finish.
- *
- *     LOCKING:
- *     Kernel thread context (may sleep).
- *
- *     RETURNS:
- *     0 on success, -errno on failure.
- */
-int ata_host_set_suspend(struct ata_host_set *host_set, pm_message_t mesg)
-{
-       int i, j, rc;
-
-       rc = ata_host_set_request_pm(host_set, mesg, 0, ATA_EHI_QUIET, 1);
-       if (rc)
-               goto fail;
-
-       /* EH is quiescent now.  Fail if we have any ready device.
-        * This happens if hotplug occurs between completion of device
-        * suspension and here.
-        */
-       for (i = 0; i < host_set->n_ports; i++) {
-               struct ata_port *ap = host_set->ports[i];
-
-               for (j = 0; j < ATA_MAX_DEVICES; j++) {
-                       struct ata_device *dev = &ap->device[j];
-
-                       if (ata_dev_ready(dev)) {
-                               ata_port_printk(ap, KERN_WARNING,
-                                               "suspend failed, device %d "
-                                               "still active\n", dev->devno);
-                               rc = -EBUSY;
-                               goto fail;
-                       }
-               }
-       }
-
-       host_set->dev->power.power_state = mesg;
-       return 0;
-
- fail:
-       ata_host_set_resume(host_set);
-       return rc;
-}
-
-/**
- *     ata_host_set_resume - resume host_set
- *     @host_set: host_set to resume
- *
- *     Resume @host_set.  Actual operation is performed by EH.  This
- *     function requests EH to perform PM operations and returns.
- *     Note that all resume operations are performed parallely.
- *
- *     LOCKING:
- *     Kernel thread context (may sleep).
- */
-void ata_host_set_resume(struct ata_host_set *host_set)
-{
-       ata_host_set_request_pm(host_set, PMSG_ON, ATA_EH_SOFTRESET,
-                               ATA_EHI_NO_AUTOPSY | ATA_EHI_QUIET, 0);
-       host_set->dev->power.power_state = PMSG_ON;
-}
-
-/**
- *     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->dev;
-       int rc;
-
-       ap->prd = dma_alloc_coherent(dev, ATA_PRD_TBL_SZ, &ap->prd_dma, GFP_KERNEL);
-       if (!ap->prd)
-               return -ENOMEM;
-
-       rc = ata_pad_alloc(ap, dev);
-       if (rc) {
-               dma_free_coherent(dev, ATA_PRD_TBL_SZ, ap->prd, ap->prd_dma);
-               return rc;
-       }
-
-       DPRINTK("prd alloc, virt %p, dma %llx\n", ap->prd, (unsigned long long) ap->prd_dma);
-
-       return 0;
-}
-
-
-/**
- *     ata_port_stop - Undo ata_port_start()
- *     @ap: Port to shut down
- *
- *     Frees the PRD table.
- *
- *     May be used as the port_stop() entry in ata_port_operations.
- *
- *     LOCKING:
- *     Inherited from caller.
- */
-
-void ata_port_stop (struct ata_port *ap)
-{
-       struct device *dev = ap->dev;
-
-       dma_free_coherent(dev, ATA_PRD_TBL_SZ, ap->prd, ap->prd_dma);
-       ata_pad_free(ap, dev);
-}
-
-void ata_host_stop (struct ata_host_set *host_set)
-{
-       if (host_set->mmio_base)
-               iounmap(host_set->mmio_base);
-}
-
-/**
- *     ata_dev_init - Initialize an ata_device structure
- *     @dev: Device structure to initialize
- *
- *     Initialize @dev in preparation for probing.
- *
- *     LOCKING:
- *     Inherited from caller.
- */
-void ata_dev_init(struct ata_device *dev)
-{
-       struct ata_port *ap = dev->ap;
-       unsigned long flags;
-
-       /* SATA spd limit is bound to the first device */
-       ap->sata_spd_limit = ap->hw_sata_spd_limit;
-
-       /* High bits of dev->flags are used to record warm plug
-        * requests which occur asynchronously.  Synchronize using
-        * host_set lock.
-        */
-       spin_lock_irqsave(ap->lock, flags);
-       dev->flags &= ~ATA_DFLAG_INIT_MASK;
-       spin_unlock_irqrestore(ap->lock, flags);
-
-       memset((void *)dev + ATA_DEVICE_CLEAR_OFFSET, 0,
-              sizeof(*dev) - ATA_DEVICE_CLEAR_OFFSET);
-       dev->pio_mask = UINT_MAX;
-       dev->mwdma_mask = UINT_MAX;
-       dev->udma_mask = UINT_MAX;
-}
-
-/**
- *     ata_port_init - Initialize an ata_port structure
- *     @ap: Structure to initialize
- *     @host_set: Collection of hosts to which @ap belongs
- *     @ent: Probe information provided by low-level driver
- *     @port_no: Port number associated with this ata_port
- *
- *     Initialize a new ata_port structure.
- *
- *     LOCKING:
- *     Inherited from caller.
- */
-void ata_port_init(struct ata_port *ap, struct ata_host_set *host_set,
-                  const struct ata_probe_ent *ent, unsigned int port_no)
-{
-       unsigned int i;
-
-       ap->lock = &host_set->lock;
-       ap->flags = ATA_FLAG_DISABLED;
-       ap->id = ata_unique_id++;
-       ap->ctl = ATA_DEVCTL_OBS;
-       ap->host_set = host_set;
-       ap->dev = ent->dev;
-       ap->port_no = port_no;
-       ap->pio_mask = ent->pio_mask;
-       ap->mwdma_mask = ent->mwdma_mask;
-       ap->udma_mask = ent->udma_mask;
-       ap->flags |= ent->host_flags;
-       ap->ops = ent->port_ops;
-       ap->hw_sata_spd_limit = UINT_MAX;
-       ap->active_tag = ATA_TAG_POISON;
-       ap->last_ctl = 0xFF;
-
-#if defined(ATA_VERBOSE_DEBUG)
-       /* turn on all debugging levels */
-       ap->msg_enable = 0x00FF;
-#elif defined(ATA_DEBUG)
-       ap->msg_enable = ATA_MSG_DRV | ATA_MSG_INFO | ATA_MSG_CTL | ATA_MSG_WARN | ATA_MSG_ERR;
-#else
-       ap->msg_enable = ATA_MSG_DRV | ATA_MSG_ERR | ATA_MSG_WARN;
-#endif
-
-       INIT_WORK(&ap->port_task, NULL, NULL);
-       INIT_WORK(&ap->hotplug_task, ata_scsi_hotplug, ap);
-       INIT_WORK(&ap->scsi_rescan_task, ata_scsi_dev_rescan, ap);
-       INIT_LIST_HEAD(&ap->eh_done_q);
-       init_waitqueue_head(&ap->eh_wait_q);
-
-       /* set cable type */
-       ap->cbl = ATA_CBL_NONE;
-       if (ap->flags & ATA_FLAG_SATA)
-               ap->cbl = ATA_CBL_SATA;
-
-       for (i = 0; i < ATA_MAX_DEVICES; i++) {
-               struct ata_device *dev = &ap->device[i];
-               dev->ap = ap;
-               dev->devno = i;
-               ata_dev_init(dev);
-       }
-
-#ifdef ATA_IRQ_TRAP
-       ap->stats.unhandled_irq = 1;
-       ap->stats.idle_irq = 1;
-#endif
-
-       memcpy(&ap->ioaddr, &ent->port[port_no], sizeof(struct ata_ioports));
-}
-
-/**
- *     ata_port_init_shost - Initialize SCSI host associated with ATA port
- *     @ap: ATA port to initialize SCSI host for
- *     @shost: SCSI host associated with @ap
- *
- *     Initialize SCSI host @shost associated with ATA port @ap.
- *
- *     LOCKING:
- *     Inherited from caller.
- */
-static void ata_port_init_shost(struct ata_port *ap, struct Scsi_Host *shost)
-{
-       ap->host = shost;
-
-       shost->unique_id = ap->id;
-       shost->max_id = 16;
-       shost->max_lun = 1;
-       shost->max_channel = 1;
-       shost->max_cmd_len = 12;
-}
-
-/**
- *     ata_port_add - Attach low-level ATA driver to system
- *     @ent: Information provided by low-level driver
- *     @host_set: Collections of ports to which we add
- *     @port_no: Port number associated with this host
- *
- *     Attach low-level ATA driver to system.
- *
- *     LOCKING:
- *     PCI/etc. bus probe sem.
- *
- *     RETURNS:
- *     New ata_port on success, for NULL on error.
- */
-static struct ata_port * ata_port_add(const struct ata_probe_ent *ent,
-                                     struct ata_host_set *host_set,
-                                     unsigned int port_no)
-{
-       struct Scsi_Host *shost;
-       struct ata_port *ap;
-
-       DPRINTK("ENTER\n");
-
-       if (!ent->port_ops->error_handler &&
-           !(ent->host_flags & (ATA_FLAG_SATA_RESET | ATA_FLAG_SRST))) {
-               printk(KERN_ERR "ata%u: no reset mechanism available\n",
-                      port_no);
-               return NULL;
-       }
-
-       shost = scsi_host_alloc(ent->sht, sizeof(struct ata_port));
-       if (!shost)
-               return NULL;
-
-       shost->transportt = &ata_scsi_transport_template;
-
-       ap = ata_shost_to_port(shost);
-
-       ata_port_init(ap, host_set, ent, port_no);
-       ata_port_init_shost(ap, shost);
-
-       return ap;
-}
-
-/**
- *     ata_sas_host_init - Initialize a host_set struct
- *     @host_set:      host_set to initialize
- *     @dev:           device host_set is attached to
- *     @flags: host_set flags
- *     @ops:           port_ops
- *
- *     LOCKING:
- *     PCI/etc. bus probe sem.
- *
- */
-
-void ata_host_set_init(struct ata_host_set *host_set,
-                      struct device *dev, unsigned long flags,
-                      const struct ata_port_operations *ops)
-{
-       spin_lock_init(&host_set->lock);
-       host_set->dev = dev;
-       host_set->flags = flags;
-       host_set->ops = ops;
-}
-
-/**
- *     ata_device_add - Register hardware device with ATA and SCSI layers
- *     @ent: Probe information describing hardware device to be registered
- *
- *     This function processes the information provided in the probe
- *     information struct @ent, allocates the necessary ATA and SCSI
- *     host information structures, initializes them, and registers
- *     everything with requisite kernel subsystems.
- *
- *     This function requests irqs, probes the ATA bus, and probes
- *     the SCSI bus.
- *
- *     LOCKING:
- *     PCI/etc. bus probe sem.
- *
- *     RETURNS:
- *     Number of ports registered.  Zero on error (no ports registered).
- */
-int ata_device_add(const struct ata_probe_ent *ent)
-{
-       unsigned int i;
-       struct device *dev = ent->dev;
-       struct ata_host_set *host_set;
-       int rc;
-
-       DPRINTK("ENTER\n");
-       /* alloc a container for our list of ATA ports (buses) */
-       host_set = kzalloc(sizeof(struct ata_host_set) +
-                          (ent->n_ports * sizeof(void *)), GFP_KERNEL);
-       if (!host_set)
-               return 0;
-
-       ata_host_set_init(host_set, dev, ent->host_set_flags, ent->port_ops);
-       host_set->n_ports = ent->n_ports;
-       host_set->irq = ent->irq;
-       host_set->irq2 = ent->irq2;
-       host_set->mmio_base = ent->mmio_base;
-       host_set->private_data = ent->private_data;
-
-       /* register each port bound to this device */
-       for (i = 0; i < host_set->n_ports; i++) {
-               struct ata_port *ap;
-               unsigned long xfer_mode_mask;
-               int irq_line = ent->irq;
-
-               ap = ata_port_add(ent, host_set, i);
-               if (!ap)
-                       goto err_out;
-
-               host_set->ports[i] = ap;
-
-               /* dummy? */
-               if (ent->dummy_port_mask & (1 << i)) {
-                       ata_port_printk(ap, KERN_INFO, "DUMMY\n");
-                       ap->ops = &ata_dummy_port_ops;
-                       continue;
-               }
-
-               /* start port */
-               rc = ap->ops->port_start(ap);
-               if (rc) {
-                       host_set->ports[i] = NULL;
-                       scsi_host_put(ap->host);
-                       goto err_out;
-               }
-
-               /* Report the secondary IRQ for second channel legacy */
-               if (i == 1 && ent->irq2)
-                       irq_line = ent->irq2;
-
-               xfer_mode_mask =(ap->udma_mask << ATA_SHIFT_UDMA) |
-                               (ap->mwdma_mask << ATA_SHIFT_MWDMA) |
-                               (ap->pio_mask << ATA_SHIFT_PIO);
-
-               /* print per-port info to dmesg */
-               ata_port_printk(ap, KERN_INFO, "%cATA max %s cmd 0x%lX "
-                               "ctl 0x%lX bmdma 0x%lX irq %d\n",
-                               ap->flags & ATA_FLAG_SATA ? 'S' : 'P',
-                               ata_mode_string(xfer_mode_mask),
-                               ap->ioaddr.cmd_addr,
-                               ap->ioaddr.ctl_addr,
-                               ap->ioaddr.bmdma_addr,
-                               irq_line);
-
-               ata_chk_status(ap);
-               host_set->ops->irq_clear(ap);
-               ata_eh_freeze_port(ap); /* freeze port before requesting IRQ */
-       }
-
-       /* obtain irq, that may be shared between channels */
-       rc = request_irq(ent->irq, ent->port_ops->irq_handler, ent->irq_flags,
-                        DRV_NAME, host_set);
-       if (rc) {
-               dev_printk(KERN_ERR, dev, "irq %lu request failed: %d\n",
-                          ent->irq, rc);
-               goto err_out;
-       }
-
-       /* do we have a second IRQ for the other channel, eg legacy mode */
-       if (ent->irq2) {
-               /* We will get weird core code crashes later if this is true
-                  so trap it now */
-               BUG_ON(ent->irq == ent->irq2);
-
-               rc = request_irq(ent->irq2, ent->port_ops->irq_handler, ent->irq_flags,
-                        DRV_NAME, host_set);
-               if (rc) {
-                       dev_printk(KERN_ERR, dev, "irq %lu request failed: %d\n",
-                                  ent->irq2, rc);
-                       goto err_out_free_irq;
-               }
-       }
-
-       /* perform each probe synchronously */
-       DPRINTK("probe begin\n");
-       for (i = 0; i < host_set->n_ports; i++) {
-               struct ata_port *ap = host_set->ports[i];
-               u32 scontrol;
-               int rc;
-
-               /* init sata_spd_limit to the current value */
-               if (sata_scr_read(ap, SCR_CONTROL, &scontrol) == 0) {
-                       int spd = (scontrol >> 4) & 0xf;
-                       ap->hw_sata_spd_limit &= (1 << spd) - 1;
-               }
-               ap->sata_spd_limit = ap->hw_sata_spd_limit;
-
-               rc = scsi_add_host(ap->host, dev);
-               if (rc) {
-                       ata_port_printk(ap, KERN_ERR, "scsi_add_host failed\n");
-                       /* FIXME: do something useful here */
-                       /* FIXME: handle unconditional calls to
-                        * scsi_scan_host and ata_host_remove, below,
-                        * at the very least
-                        */
-               }
-
-               if (ap->ops->error_handler) {
-                       struct ata_eh_info *ehi = &ap->eh_info;
-                       unsigned long flags;
-
-                       ata_port_probe(ap);
-
-                       /* kick EH for boot probing */
-                       spin_lock_irqsave(ap->lock, flags);
-
-                       ehi->probe_mask = (1 << ATA_MAX_DEVICES) - 1;
-                       ehi->action |= ATA_EH_SOFTRESET;
-                       ehi->flags |= ATA_EHI_NO_AUTOPSY | ATA_EHI_QUIET;
-
-                       ap->pflags |= ATA_PFLAG_LOADING;
-                       ata_port_schedule_eh(ap);
-
-                       spin_unlock_irqrestore(ap->lock, flags);
-
-                       /* wait for EH to finish */
-                       ata_port_wait_eh(ap);
-               } else {
-                       DPRINTK("ata%u: bus probe begin\n", ap->id);
-                       rc = ata_bus_probe(ap);
-                       DPRINTK("ata%u: bus probe end\n", ap->id);
-
-                       if (rc) {
-                               /* FIXME: do something useful here?
-                                * Current libata behavior will
-                                * tear down everything when
-                                * the module is removed
-                                * or the h/w is unplugged.
-                                */
-                       }
-               }
-       }
-
-       /* probes are done, now scan each port's disk(s) */
-       DPRINTK("host probe begin\n");
-       for (i = 0; i < host_set->n_ports; i++) {
-               struct ata_port *ap = host_set->ports[i];
-
-               ata_scsi_scan_host(ap);
-       }
-
-       dev_set_drvdata(dev, host_set);
-
-       VPRINTK("EXIT, returning %u\n", ent->n_ports);
-       return ent->n_ports; /* success */
-
-err_out_free_irq:
-       free_irq(ent->irq, host_set);
-err_out:
-       for (i = 0; i < host_set->n_ports; i++) {
-               struct ata_port *ap = host_set->ports[i];
-               if (ap) {
-                       ap->ops->port_stop(ap);
-                       scsi_host_put(ap->host);
-               }
-       }
-
-       kfree(host_set);
-       VPRINTK("EXIT, returning 0\n");
-       return 0;
-}
-
-/**
- *     ata_port_detach - Detach ATA port in prepration of device removal
- *     @ap: ATA port to be detached
- *
- *     Detach all ATA devices and the associated SCSI devices of @ap;
- *     then, remove the associated SCSI host.  @ap is guaranteed to
- *     be quiescent on return from this function.
- *
- *     LOCKING:
- *     Kernel thread context (may sleep).
- */
-void ata_port_detach(struct ata_port *ap)
-{
-       unsigned long flags;
-       int i;
-
-       if (!ap->ops->error_handler)
-               goto skip_eh;
-
-       /* tell EH we're leaving & flush EH */
-       spin_lock_irqsave(ap->lock, flags);
-       ap->pflags |= ATA_PFLAG_UNLOADING;
-       spin_unlock_irqrestore(ap->lock, flags);
-
-       ata_port_wait_eh(ap);
-
-       /* EH is now guaranteed to see UNLOADING, so no new device
-        * will be attached.  Disable all existing devices.
-        */
-       spin_lock_irqsave(ap->lock, flags);
-
-       for (i = 0; i < ATA_MAX_DEVICES; i++)
-               ata_dev_disable(&ap->device[i]);
-
-       spin_unlock_irqrestore(ap->lock, flags);
-
-       /* Final freeze & EH.  All in-flight commands are aborted.  EH
-        * will be skipped and retrials will be terminated with bad
-        * target.
-        */
-       spin_lock_irqsave(ap->lock, flags);
-       ata_port_freeze(ap);    /* won't be thawed */
-       spin_unlock_irqrestore(ap->lock, flags);
-
-       ata_port_wait_eh(ap);
-
-       /* Flush hotplug task.  The sequence is similar to
-        * ata_port_flush_task().
-        */
-       flush_workqueue(ata_aux_wq);
-       cancel_delayed_work(&ap->hotplug_task);
-       flush_workqueue(ata_aux_wq);
-
- skip_eh:
-       /* remove the associated SCSI host */
-       scsi_remove_host(ap->host);
-}
-
-/**
- *     ata_host_set_remove - PCI layer callback for device removal
- *     @host_set: ATA host set that was removed
- *
- *     Unregister all objects associated with this host set. Free those
- *     objects.
- *
- *     LOCKING:
- *     Inherited from calling layer (may sleep).
- */
-
-void ata_host_set_remove(struct ata_host_set *host_set)
-{
-       unsigned int i;
-
-       for (i = 0; i < host_set->n_ports; i++)
-               ata_port_detach(host_set->ports[i]);
-
-       free_irq(host_set->irq, host_set);
-       if (host_set->irq2)
-               free_irq(host_set->irq2, host_set);
-
-       for (i = 0; i < host_set->n_ports; i++) {
-               struct ata_port *ap = host_set->ports[i];
-
-               ata_scsi_release(ap->host);
-
-               if ((ap->flags & ATA_FLAG_NO_LEGACY) == 0) {
-                       struct ata_ioports *ioaddr = &ap->ioaddr;
-
-                       /* FIXME: Add -ac IDE pci mods to remove these special cases */
-                       if (ioaddr->cmd_addr == ATA_PRIMARY_CMD)
-                               release_region(ATA_PRIMARY_CMD, 8);
-                       else if (ioaddr->cmd_addr == ATA_SECONDARY_CMD)
-                               release_region(ATA_SECONDARY_CMD, 8);
-               }
-
-               scsi_host_put(ap->host);
-       }
-
-       if (host_set->ops->host_stop)
-               host_set->ops->host_stop(host_set);
-
-       kfree(host_set);
-}
-
-/**
- *     ata_scsi_release - SCSI layer callback hook for host unload
- *     @host: libata host to be unloaded
- *
- *     Performs all duties necessary to shut down a libata port...
- *     Kill port kthread, disable port, and release resources.
- *
- *     LOCKING:
- *     Inherited from SCSI layer.
- *
- *     RETURNS:
- *     One.
- */
-
-int ata_scsi_release(struct Scsi_Host *host)
-{
-       struct ata_port *ap = ata_shost_to_port(host);
-
-       DPRINTK("ENTER\n");
-
-       ap->ops->port_disable(ap);
-       ap->ops->port_stop(ap);
-
-       DPRINTK("EXIT\n");
-       return 1;
-}
-
-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_std_ports - initialize ioaddr with standard port offsets.
- *     @ioaddr: IO address structure to be initialized
- *
- *     Utility function which initializes data_addr, error_addr,
- *     feature_addr, nsect_addr, lbal_addr, lbam_addr, lbah_addr,
- *     device_addr, status_addr, and command_addr to standard offsets
- *     relative to cmd_addr.
- *
- *     Does not set ctl_addr, altstatus_addr, bmdma_addr, or scr_addr.
- */
-
-void ata_std_ports(struct ata_ioports *ioaddr)
-{
-       ioaddr->data_addr = ioaddr->cmd_addr + ATA_REG_DATA;
-       ioaddr->error_addr = ioaddr->cmd_addr + ATA_REG_ERR;
-       ioaddr->feature_addr = ioaddr->cmd_addr + ATA_REG_FEATURE;
-       ioaddr->nsect_addr = ioaddr->cmd_addr + ATA_REG_NSECT;
-       ioaddr->lbal_addr = ioaddr->cmd_addr + ATA_REG_LBAL;
-       ioaddr->lbam_addr = ioaddr->cmd_addr + ATA_REG_LBAM;
-       ioaddr->lbah_addr = ioaddr->cmd_addr + ATA_REG_LBAH;
-       ioaddr->device_addr = ioaddr->cmd_addr + ATA_REG_DEVICE;
-       ioaddr->status_addr = ioaddr->cmd_addr + ATA_REG_STATUS;
-       ioaddr->command_addr = ioaddr->cmd_addr + ATA_REG_CMD;
-}
-
-
-#ifdef CONFIG_PCI
-
-void ata_pci_host_stop (struct ata_host_set *host_set)
-{
-       struct pci_dev *pdev = to_pci_dev(host_set->dev);
-
-       pci_iounmap(pdev, host_set->mmio_base);
-}
-
-/**
- *     ata_pci_remove_one - PCI layer callback for device removal
- *     @pdev: PCI device that was removed
- *
- *     PCI layer indicates to libata via this hook that
- *     hot-unplug or module unload event has occurred.
- *     Handle this by unregistering all objects associated
- *     with this PCI device.  Free those objects.  Then finally
- *     release PCI resources and disable device.
- *
- *     LOCKING:
- *     Inherited from PCI layer (may sleep).
- */
-
-void ata_pci_remove_one (struct pci_dev *pdev)
-{
-       struct device *dev = pci_dev_to_dev(pdev);
-       struct ata_host_set *host_set = dev_get_drvdata(dev);
-
-       ata_host_set_remove(host_set);
-
-       pci_release_regions(pdev);
-       pci_disable_device(pdev);
-       dev_set_drvdata(dev, NULL);
-}
-
-/* move to PCI subsystem */
-int pci_test_config_bits(struct pci_dev *pdev, const struct pci_bits *bits)
-{
-       unsigned long tmp = 0;
-
-       switch (bits->width) {
-       case 1: {
-               u8 tmp8 = 0;
-               pci_read_config_byte(pdev, bits->reg, &tmp8);
-               tmp = tmp8;
-               break;
-       }
-       case 2: {
-               u16 tmp16 = 0;
-               pci_read_config_word(pdev, bits->reg, &tmp16);
-               tmp = tmp16;
-               break;
-       }
-       case 4: {
-               u32 tmp32 = 0;
-               pci_read_config_dword(pdev, bits->reg, &tmp32);
-               tmp = tmp32;
-               break;
-       }
-
-       default:
-               return -EINVAL;
-       }
-
-       tmp &= bits->mask;
-
-       return (tmp == bits->val) ? 1 : 0;
-}
-
-void ata_pci_device_do_suspend(struct pci_dev *pdev, pm_message_t mesg)
-{
-       pci_save_state(pdev);
-
-       if (mesg.event == PM_EVENT_SUSPEND) {
-               pci_disable_device(pdev);
-               pci_set_power_state(pdev, PCI_D3hot);
-       }
-}
-
-void ata_pci_device_do_resume(struct pci_dev *pdev)
-{
-       pci_set_power_state(pdev, PCI_D0);
-       pci_restore_state(pdev);
-       pci_enable_device(pdev);
-       pci_set_master(pdev);
-}
-
-int ata_pci_device_suspend(struct pci_dev *pdev, pm_message_t mesg)
-{
-       struct ata_host_set *host_set = dev_get_drvdata(&pdev->dev);
-       int rc = 0;
-
-       rc = ata_host_set_suspend(host_set, mesg);
-       if (rc)
-               return rc;
-
-       ata_pci_device_do_suspend(pdev, mesg);
-
-       return 0;
-}
-
-int ata_pci_device_resume(struct pci_dev *pdev)
-{
-       struct ata_host_set *host_set = dev_get_drvdata(&pdev->dev);
-
-       ata_pci_device_do_resume(pdev);
-       ata_host_set_resume(host_set);
-       return 0;
-}
-#endif /* CONFIG_PCI */
-
-
-static int __init ata_init(void)
-{
-       ata_probe_timeout *= HZ;
-       ata_wq = create_workqueue("ata");
-       if (!ata_wq)
-               return -ENOMEM;
-
-       ata_aux_wq = create_singlethread_workqueue("ata_aux");
-       if (!ata_aux_wq) {
-               destroy_workqueue(ata_wq);
-               return -ENOMEM;
-       }
-
-       printk(KERN_DEBUG "libata version " DRV_VERSION " loaded.\n");
-       return 0;
-}
-
-static void __exit ata_exit(void)
-{
-       destroy_workqueue(ata_wq);
-       destroy_workqueue(ata_aux_wq);
-}
-
-module_init(ata_init);
-module_exit(ata_exit);
-
-static unsigned long ratelimit_time;
-static DEFINE_SPINLOCK(ata_ratelimit_lock);
-
-int ata_ratelimit(void)
-{
-       int rc;
-       unsigned long flags;
-
-       spin_lock_irqsave(&ata_ratelimit_lock, flags);
-
-       if (time_after(jiffies, ratelimit_time)) {
-               rc = 1;
-               ratelimit_time = jiffies + (HZ/5);
-       } else
-               rc = 0;
-
-       spin_unlock_irqrestore(&ata_ratelimit_lock, flags);
-
-       return rc;
-}
-
-/**
- *     ata_wait_register - wait until register value changes
- *     @reg: IO-mapped register
- *     @mask: Mask to apply to read register value
- *     @val: Wait condition
- *     @interval_msec: polling interval in milliseconds
- *     @timeout_msec: timeout in milliseconds
- *
- *     Waiting for some bits of register to change is a common
- *     operation for ATA controllers.  This function reads 32bit LE
- *     IO-mapped register @reg and tests for the following condition.
- *
- *     (*@reg & mask) != val
- *
- *     If the condition is met, it returns; otherwise, the process is
- *     repeated after @interval_msec until timeout.
- *
- *     LOCKING:
- *     Kernel thread context (may sleep)
- *
- *     RETURNS:
- *     The final register value.
- */
-u32 ata_wait_register(void __iomem *reg, u32 mask, u32 val,
-                     unsigned long interval_msec,
-                     unsigned long timeout_msec)
-{
-       unsigned long timeout;
-       u32 tmp;
-
-       tmp = ioread32(reg);
-
-       /* Calculate timeout _after_ the first read to make sure
-        * preceding writes reach the controller before starting to
-        * eat away the timeout.
-        */
-       timeout = jiffies + (timeout_msec * HZ) / 1000;
-
-       while ((tmp & mask) == val && time_before(jiffies, timeout)) {
-               msleep(interval_msec);
-               tmp = ioread32(reg);
-       }
-
-       return tmp;
-}
-
-/*
- * Dummy port_ops
- */
-static void ata_dummy_noret(struct ata_port *ap)       { }
-static int ata_dummy_ret0(struct ata_port *ap)         { return 0; }
-static void ata_dummy_qc_noret(struct ata_queued_cmd *qc) { }
-
-static u8 ata_dummy_check_status(struct ata_port *ap)
-{
-       return ATA_DRDY;
-}
-
-static unsigned int ata_dummy_qc_issue(struct ata_queued_cmd *qc)
-{
-       return AC_ERR_SYSTEM;
-}
-
-const struct ata_port_operations ata_dummy_port_ops = {
-       .port_disable           = ata_port_disable,
-       .check_status           = ata_dummy_check_status,
-       .check_altstatus        = ata_dummy_check_status,
-       .dev_select             = ata_noop_dev_select,
-       .qc_prep                = ata_noop_qc_prep,
-       .qc_issue               = ata_dummy_qc_issue,
-       .freeze                 = ata_dummy_noret,
-       .thaw                   = ata_dummy_noret,
-       .error_handler          = ata_dummy_noret,
-       .post_internal_cmd      = ata_dummy_qc_noret,
-       .irq_clear              = ata_dummy_noret,
-       .port_start             = ata_dummy_ret0,
-       .port_stop              = ata_dummy_noret,
-};
-
-/*
- * libata is essentially a library of internal helper functions for
- * low-level ATA host controller drivers.  As such, the API/ABI is
- * likely to change as new drivers are added and updated.
- * Do not depend on ABI/API stability.
- */
-
-EXPORT_SYMBOL_GPL(sata_deb_timing_normal);
-EXPORT_SYMBOL_GPL(sata_deb_timing_hotplug);
-EXPORT_SYMBOL_GPL(sata_deb_timing_long);
-EXPORT_SYMBOL_GPL(ata_dummy_port_ops);
-EXPORT_SYMBOL_GPL(ata_std_bios_param);
-EXPORT_SYMBOL_GPL(ata_std_ports);
-EXPORT_SYMBOL_GPL(ata_host_set_init);
-EXPORT_SYMBOL_GPL(ata_device_add);
-EXPORT_SYMBOL_GPL(ata_port_detach);
-EXPORT_SYMBOL_GPL(ata_host_set_remove);
-EXPORT_SYMBOL_GPL(ata_sg_init);
-EXPORT_SYMBOL_GPL(ata_sg_init_one);
-EXPORT_SYMBOL_GPL(ata_hsm_move);
-EXPORT_SYMBOL_GPL(ata_qc_complete);
-EXPORT_SYMBOL_GPL(ata_qc_complete_multiple);
-EXPORT_SYMBOL_GPL(ata_qc_issue_prot);
-EXPORT_SYMBOL_GPL(ata_tf_load);
-EXPORT_SYMBOL_GPL(ata_tf_read);
-EXPORT_SYMBOL_GPL(ata_noop_dev_select);
-EXPORT_SYMBOL_GPL(ata_std_dev_select);
-EXPORT_SYMBOL_GPL(ata_tf_to_fis);
-EXPORT_SYMBOL_GPL(ata_tf_from_fis);
-EXPORT_SYMBOL_GPL(ata_check_status);
-EXPORT_SYMBOL_GPL(ata_altstatus);
-EXPORT_SYMBOL_GPL(ata_exec_command);
-EXPORT_SYMBOL_GPL(ata_port_start);
-EXPORT_SYMBOL_GPL(ata_port_stop);
-EXPORT_SYMBOL_GPL(ata_host_stop);
-EXPORT_SYMBOL_GPL(ata_interrupt);
-EXPORT_SYMBOL_GPL(ata_mmio_data_xfer);
-EXPORT_SYMBOL_GPL(ata_pio_data_xfer);
-EXPORT_SYMBOL_GPL(ata_pio_data_xfer_noirq);
-EXPORT_SYMBOL_GPL(ata_qc_prep);
-EXPORT_SYMBOL_GPL(ata_noop_qc_prep);
-EXPORT_SYMBOL_GPL(ata_bmdma_setup);
-EXPORT_SYMBOL_GPL(ata_bmdma_start);
-EXPORT_SYMBOL_GPL(ata_bmdma_irq_clear);
-EXPORT_SYMBOL_GPL(ata_bmdma_status);
-EXPORT_SYMBOL_GPL(ata_bmdma_stop);
-EXPORT_SYMBOL_GPL(ata_bmdma_freeze);
-EXPORT_SYMBOL_GPL(ata_bmdma_thaw);
-EXPORT_SYMBOL_GPL(ata_bmdma_drive_eh);
-EXPORT_SYMBOL_GPL(ata_bmdma_error_handler);
-EXPORT_SYMBOL_GPL(ata_bmdma_post_internal_cmd);
-EXPORT_SYMBOL_GPL(ata_port_probe);
-EXPORT_SYMBOL_GPL(sata_set_spd);
-EXPORT_SYMBOL_GPL(sata_phy_debounce);
-EXPORT_SYMBOL_GPL(sata_phy_resume);
-EXPORT_SYMBOL_GPL(sata_phy_reset);
-EXPORT_SYMBOL_GPL(__sata_phy_reset);
-EXPORT_SYMBOL_GPL(ata_bus_reset);
-EXPORT_SYMBOL_GPL(ata_std_prereset);
-EXPORT_SYMBOL_GPL(ata_std_softreset);
-EXPORT_SYMBOL_GPL(sata_std_hardreset);
-EXPORT_SYMBOL_GPL(ata_std_postreset);
-EXPORT_SYMBOL_GPL(ata_dev_revalidate);
-EXPORT_SYMBOL_GPL(ata_dev_classify);
-EXPORT_SYMBOL_GPL(ata_dev_pair);
-EXPORT_SYMBOL_GPL(ata_port_disable);
-EXPORT_SYMBOL_GPL(ata_ratelimit);
-EXPORT_SYMBOL_GPL(ata_wait_register);
-EXPORT_SYMBOL_GPL(ata_busy_sleep);
-EXPORT_SYMBOL_GPL(ata_port_queue_task);
-EXPORT_SYMBOL_GPL(ata_scsi_ioctl);
-EXPORT_SYMBOL_GPL(ata_scsi_queuecmd);
-EXPORT_SYMBOL_GPL(ata_scsi_slave_config);
-EXPORT_SYMBOL_GPL(ata_scsi_slave_destroy);
-EXPORT_SYMBOL_GPL(ata_scsi_change_queue_depth);
-EXPORT_SYMBOL_GPL(ata_scsi_release);
-EXPORT_SYMBOL_GPL(ata_host_intr);
-EXPORT_SYMBOL_GPL(sata_scr_valid);
-EXPORT_SYMBOL_GPL(sata_scr_read);
-EXPORT_SYMBOL_GPL(sata_scr_write);
-EXPORT_SYMBOL_GPL(sata_scr_write_flush);
-EXPORT_SYMBOL_GPL(ata_port_online);
-EXPORT_SYMBOL_GPL(ata_port_offline);
-EXPORT_SYMBOL_GPL(ata_host_set_suspend);
-EXPORT_SYMBOL_GPL(ata_host_set_resume);
-EXPORT_SYMBOL_GPL(ata_id_string);
-EXPORT_SYMBOL_GPL(ata_id_c_string);
-EXPORT_SYMBOL_GPL(ata_scsi_simulate);
-
-EXPORT_SYMBOL_GPL(ata_pio_need_iordy);
-EXPORT_SYMBOL_GPL(ata_timing_compute);
-EXPORT_SYMBOL_GPL(ata_timing_merge);
-
-#ifdef CONFIG_PCI
-EXPORT_SYMBOL_GPL(pci_test_config_bits);
-EXPORT_SYMBOL_GPL(ata_pci_host_stop);
-EXPORT_SYMBOL_GPL(ata_pci_init_native_mode);
-EXPORT_SYMBOL_GPL(ata_pci_init_one);
-EXPORT_SYMBOL_GPL(ata_pci_remove_one);
-EXPORT_SYMBOL_GPL(ata_pci_device_do_suspend);
-EXPORT_SYMBOL_GPL(ata_pci_device_do_resume);
-EXPORT_SYMBOL_GPL(ata_pci_device_suspend);
-EXPORT_SYMBOL_GPL(ata_pci_device_resume);
-EXPORT_SYMBOL_GPL(ata_pci_default_filter);
-EXPORT_SYMBOL_GPL(ata_pci_clear_simplex);
-#endif /* CONFIG_PCI */
-
-EXPORT_SYMBOL_GPL(ata_scsi_device_suspend);
-EXPORT_SYMBOL_GPL(ata_scsi_device_resume);
-
-EXPORT_SYMBOL_GPL(ata_eng_timeout);
-EXPORT_SYMBOL_GPL(ata_port_schedule_eh);
-EXPORT_SYMBOL_GPL(ata_port_abort);
-EXPORT_SYMBOL_GPL(ata_port_freeze);
-EXPORT_SYMBOL_GPL(ata_eh_freeze_port);
-EXPORT_SYMBOL_GPL(ata_eh_thaw_port);
-EXPORT_SYMBOL_GPL(ata_eh_qc_complete);
-EXPORT_SYMBOL_GPL(ata_eh_qc_retry);
-EXPORT_SYMBOL_GPL(ata_do_eh);
diff --git a/drivers/scsi/libata-eh.c b/drivers/scsi/libata-eh.c
deleted file mode 100644 (file)
index 29f5934..0000000
+++ /dev/null
@@ -1,2246 +0,0 @@
-/*
- *  libata-eh.c - libata error handling
- *
- *  Maintained by:  Jeff Garzik <jgarzik@pobox.com>
- *                 Please ALWAYS copy linux-ide@vger.kernel.org
- *                 on emails.
- *
- *  Copyright 2006 Tejun Heo <htejun@gmail.com>
- *
- *
- *  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 <scsi/scsi.h>
-#include <scsi/scsi_host.h>
-#include <scsi/scsi_eh.h>
-#include <scsi/scsi_device.h>
-#include <scsi/scsi_cmnd.h>
-#include "scsi_transport_api.h"
-
-#include <linux/libata.h>
-
-#include "libata.h"
-
-static void __ata_port_freeze(struct ata_port *ap);
-static void ata_eh_finish(struct ata_port *ap);
-static void ata_eh_handle_port_suspend(struct ata_port *ap);
-static void ata_eh_handle_port_resume(struct ata_port *ap);
-
-static void ata_ering_record(struct ata_ering *ering, int is_io,
-                            unsigned int err_mask)
-{
-       struct ata_ering_entry *ent;
-
-       WARN_ON(!err_mask);
-
-       ering->cursor++;
-       ering->cursor %= ATA_ERING_SIZE;
-
-       ent = &ering->ring[ering->cursor];
-       ent->is_io = is_io;
-       ent->err_mask = err_mask;
-       ent->timestamp = get_jiffies_64();
-}
-
-static struct ata_ering_entry * ata_ering_top(struct ata_ering *ering)
-{
-       struct ata_ering_entry *ent = &ering->ring[ering->cursor];
-       if (!ent->err_mask)
-               return NULL;
-       return ent;
-}
-
-static int ata_ering_map(struct ata_ering *ering,
-                        int (*map_fn)(struct ata_ering_entry *, void *),
-                        void *arg)
-{
-       int idx, rc = 0;
-       struct ata_ering_entry *ent;
-
-       idx = ering->cursor;
-       do {
-               ent = &ering->ring[idx];
-               if (!ent->err_mask)
-                       break;
-               rc = map_fn(ent, arg);
-               if (rc)
-                       break;
-               idx = (idx - 1 + ATA_ERING_SIZE) % ATA_ERING_SIZE;
-       } while (idx != ering->cursor);
-
-       return rc;
-}
-
-static unsigned int ata_eh_dev_action(struct ata_device *dev)
-{
-       struct ata_eh_context *ehc = &dev->ap->eh_context;
-
-       return ehc->i.action | ehc->i.dev_action[dev->devno];
-}
-
-static void ata_eh_clear_action(struct ata_device *dev,
-                               struct ata_eh_info *ehi, unsigned int action)
-{
-       int i;
-
-       if (!dev) {
-               ehi->action &= ~action;
-               for (i = 0; i < ATA_MAX_DEVICES; i++)
-                       ehi->dev_action[i] &= ~action;
-       } else {
-               /* doesn't make sense for port-wide EH actions */
-               WARN_ON(!(action & ATA_EH_PERDEV_MASK));
-
-               /* break ehi->action into ehi->dev_action */
-               if (ehi->action & action) {
-                       for (i = 0; i < ATA_MAX_DEVICES; i++)
-                               ehi->dev_action[i] |= ehi->action & action;
-                       ehi->action &= ~action;
-               }
-
-               /* turn off the specified per-dev action */
-               ehi->dev_action[dev->devno] &= ~action;
-       }
-}
-
-/**
- *     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.
- *
- *     TODO: kill this function once old EH is gone.
- *
- *     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 = ata_shost_to_port(host);
-       unsigned long flags;
-       struct ata_queued_cmd *qc;
-       enum scsi_eh_timer_return ret;
-
-       DPRINTK("ENTER\n");
-
-       if (ap->ops->error_handler) {
-               ret = EH_NOT_HANDLED;
-               goto out;
-       }
-
-       ret = EH_HANDLED;
-       spin_lock_irqsave(ap->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->lock, flags);
-
- out:
-       DPRINTK("EXIT, ret=%d\n", ret);
-       return ret;
-}
-
-/**
- *     ata_scsi_error - SCSI layer error handler callback
- *     @host: SCSI host on which error occurred
- *
- *     Handles SCSI-layer-thrown error events.
- *
- *     LOCKING:
- *     Inherited from SCSI layer (none, can sleep)
- *
- *     RETURNS:
- *     Zero.
- */
-void ata_scsi_error(struct Scsi_Host *host)
-{
-       struct ata_port *ap = ata_shost_to_port(host);
-       int i, repeat_cnt = ATA_EH_MAX_REPEAT;
-       unsigned long flags;
-
-       DPRINTK("ENTER\n");
-
-       /* synchronize with port task */
-       ata_port_flush_task(ap);
-
-       /* synchronize with host_set lock and sort out timeouts */
-
-       /* For new EH, all qcs are finished in one of three ways -
-        * normal completion, error completion, and SCSI timeout.
-        * Both cmpletions can race against SCSI timeout.  When normal
-        * completion wins, the qc never reaches EH.  When error
-        * completion wins, the qc has ATA_QCFLAG_FAILED set.
-        *
-        * When SCSI timeout wins, things are a bit more complex.
-        * Normal or error completion can occur after the timeout but
-        * before this point.  In such cases, both types of
-        * completions are honored.  A scmd is determined to have
-        * timed out iff its associated qc is active and not failed.
-        */
-       if (ap->ops->error_handler) {
-               struct scsi_cmnd *scmd, *tmp;
-               int nr_timedout = 0;
-
-               spin_lock_irqsave(ap->lock, flags);
-
-               list_for_each_entry_safe(scmd, tmp, &host->eh_cmd_q, eh_entry) {
-                       struct ata_queued_cmd *qc;
-
-                       for (i = 0; i < ATA_MAX_QUEUE; i++) {
-                               qc = __ata_qc_from_tag(ap, i);
-                               if (qc->flags & ATA_QCFLAG_ACTIVE &&
-                                   qc->scsicmd == scmd)
-                                       break;
-                       }
-
-                       if (i < ATA_MAX_QUEUE) {
-                               /* the scmd has an associated qc */
-                               if (!(qc->flags & ATA_QCFLAG_FAILED)) {
-                                       /* which hasn't failed yet, timeout */
-                                       qc->err_mask |= AC_ERR_TIMEOUT;
-                                       qc->flags |= ATA_QCFLAG_FAILED;
-                                       nr_timedout++;
-                               }
-                       } else {
-                               /* Normal completion occurred after
-                                * SCSI timeout but before this point.
-                                * Successfully complete it.
-                                */
-                               scmd->retries = scmd->allowed;
-                               scsi_eh_finish_cmd(scmd, &ap->eh_done_q);
-                       }
-               }
-
-               /* If we have timed out qcs.  They belong to EH from
-                * this point but the state of the controller is
-                * unknown.  Freeze the port to make sure the IRQ
-                * handler doesn't diddle with those qcs.  This must
-                * be done atomically w.r.t. setting QCFLAG_FAILED.
-                */
-               if (nr_timedout)
-                       __ata_port_freeze(ap);
-
-               spin_unlock_irqrestore(ap->lock, flags);
-       } else
-               spin_unlock_wait(ap->lock);
-
- repeat:
-       /* invoke error handler */
-       if (ap->ops->error_handler) {
-               /* process port resume request */
-               ata_eh_handle_port_resume(ap);
-
-               /* fetch & clear EH info */
-               spin_lock_irqsave(ap->lock, flags);
-
-               memset(&ap->eh_context, 0, sizeof(ap->eh_context));
-               ap->eh_context.i = ap->eh_info;
-               memset(&ap->eh_info, 0, sizeof(ap->eh_info));
-
-               ap->pflags |= ATA_PFLAG_EH_IN_PROGRESS;
-               ap->pflags &= ~ATA_PFLAG_EH_PENDING;
-
-               spin_unlock_irqrestore(ap->lock, flags);
-
-               /* invoke EH, skip if unloading or suspended */
-               if (!(ap->pflags & (ATA_PFLAG_UNLOADING | ATA_PFLAG_SUSPENDED)))
-                       ap->ops->error_handler(ap);
-               else
-                       ata_eh_finish(ap);
-
-               /* process port suspend request */
-               ata_eh_handle_port_suspend(ap);
-
-               /* Exception might have happend after ->error_handler
-                * recovered the port but before this point.  Repeat
-                * EH in such case.
-                */
-               spin_lock_irqsave(ap->lock, flags);
-
-               if (ap->pflags & ATA_PFLAG_EH_PENDING) {
-                       if (--repeat_cnt) {
-                               ata_port_printk(ap, KERN_INFO,
-                                       "EH pending after completion, "
-                                       "repeating EH (cnt=%d)\n", repeat_cnt);
-                               spin_unlock_irqrestore(ap->lock, flags);
-                               goto repeat;
-                       }
-                       ata_port_printk(ap, KERN_ERR, "EH pending after %d "
-                                       "tries, giving up\n", ATA_EH_MAX_REPEAT);
-               }
-
-               /* this run is complete, make sure EH info is clear */
-               memset(&ap->eh_info, 0, sizeof(ap->eh_info));
-
-               /* Clear host_eh_scheduled while holding ap->lock such
-                * that if exception occurs after this point but
-                * before EH completion, SCSI midlayer will
-                * re-initiate EH.
-                */
-               host->host_eh_scheduled = 0;
-
-               spin_unlock_irqrestore(ap->lock, flags);
-       } else {
-               WARN_ON(ata_qc_from_tag(ap, ap->active_tag) == NULL);
-               ap->ops->eng_timeout(ap);
-       }
-
-       /* finish or retry handled scmd's and clean up */
-       WARN_ON(host->host_failed || !list_empty(&host->eh_cmd_q));
-
-       scsi_eh_flush_done_q(&ap->eh_done_q);
-
-       /* clean up */
-       spin_lock_irqsave(ap->lock, flags);
-
-       if (ap->pflags & ATA_PFLAG_LOADING)
-               ap->pflags &= ~ATA_PFLAG_LOADING;
-       else if (ap->pflags & ATA_PFLAG_SCSI_HOTPLUG)
-               queue_work(ata_aux_wq, &ap->hotplug_task);
-
-       if (ap->pflags & ATA_PFLAG_RECOVERED)
-               ata_port_printk(ap, KERN_INFO, "EH complete\n");
-
-       ap->pflags &= ~(ATA_PFLAG_SCSI_HOTPLUG | ATA_PFLAG_RECOVERED);
-
-       /* tell wait_eh that we're done */
-       ap->pflags &= ~ATA_PFLAG_EH_IN_PROGRESS;
-       wake_up_all(&ap->eh_wait_q);
-
-       spin_unlock_irqrestore(ap->lock, flags);
-
-       DPRINTK("EXIT\n");
-}
-
-/**
- *     ata_port_wait_eh - Wait for the currently pending EH to complete
- *     @ap: Port to wait EH for
- *
- *     Wait until the currently pending EH is complete.
- *
- *     LOCKING:
- *     Kernel thread context (may sleep).
- */
-void ata_port_wait_eh(struct ata_port *ap)
-{
-       unsigned long flags;
-       DEFINE_WAIT(wait);
-
- retry:
-       spin_lock_irqsave(ap->lock, flags);
-
-       while (ap->pflags & (ATA_PFLAG_EH_PENDING | ATA_PFLAG_EH_IN_PROGRESS)) {
-               prepare_to_wait(&ap->eh_wait_q, &wait, TASK_UNINTERRUPTIBLE);
-               spin_unlock_irqrestore(ap->lock, flags);
-               schedule();
-               spin_lock_irqsave(ap->lock, flags);
-       }
-       finish_wait(&ap->eh_wait_q, &wait);
-
-       spin_unlock_irqrestore(ap->lock, flags);
-
-       /* make sure SCSI EH is complete */
-       if (scsi_host_in_recovery(ap->host)) {
-               msleep(10);
-               goto retry;
-       }
-}
-
-/**
- *     ata_qc_timeout - Handle timeout of queued command
- *     @qc: Command that timed out
- *
- *     Some part of the kernel (currently, only the SCSI layer)
- *     has noticed that the active command on port @ap has not
- *     completed after a specified length of time.  Handle this
- *     condition by disabling DMA (if necessary) and completing
- *     transactions, with error if necessary.
- *
- *     This also handles the case of the "lost interrupt", where
- *     for some reason (possibly hardware bug, possibly driver bug)
- *     an interrupt was not delivered to the driver, even though the
- *     transaction completed successfully.
- *
- *     TODO: kill this function once old EH is gone.
- *
- *     LOCKING:
- *     Inherited from SCSI layer (none, can sleep)
- */
-static void ata_qc_timeout(struct ata_queued_cmd *qc)
-{
-       struct ata_port *ap = qc->ap;
-       u8 host_stat = 0, drv_stat;
-       unsigned long flags;
-
-       DPRINTK("ENTER\n");
-
-       ap->hsm_task_state = HSM_ST_IDLE;
-
-       spin_lock_irqsave(ap->lock, flags);
-
-       switch (qc->tf.protocol) {
-
-       case ATA_PROT_DMA:
-       case ATA_PROT_ATAPI_DMA:
-               host_stat = ap->ops->bmdma_status(ap);
-
-               /* before we do anything else, clear DMA-Start bit */
-               ap->ops->bmdma_stop(qc);
-
-               /* fall through */
-
-       default:
-               ata_altstatus(ap);
-               drv_stat = ata_chk_status(ap);
-
-               /* ack bmdma irq events */
-               ap->ops->irq_clear(ap);
-
-               ata_dev_printk(qc->dev, KERN_ERR, "command 0x%x timeout, "
-                              "stat 0x%x host_stat 0x%x\n",
-                              qc->tf.command, drv_stat, host_stat);
-
-               /* complete taskfile transaction */
-               qc->err_mask |= AC_ERR_TIMEOUT;
-               break;
-       }
-
-       spin_unlock_irqrestore(ap->lock, flags);
-
-       ata_eh_qc_complete(qc);
-
-       DPRINTK("EXIT\n");
-}
-
-/**
- *     ata_eng_timeout - Handle timeout of queued command
- *     @ap: Port on which timed-out command is active
- *
- *     Some part of the kernel (currently, only the SCSI layer)
- *     has noticed that the active command on port @ap has not
- *     completed after a specified length of time.  Handle this
- *     condition by disabling DMA (if necessary) and completing
- *     transactions, with error if necessary.
- *
- *     This also handles the case of the "lost interrupt", where
- *     for some reason (possibly hardware bug, possibly driver bug)
- *     an interrupt was not delivered to the driver, even though the
- *     transaction completed successfully.
- *
- *     TODO: kill this function once old EH is gone.
- *
- *     LOCKING:
- *     Inherited from SCSI layer (none, can sleep)
- */
-void ata_eng_timeout(struct ata_port *ap)
-{
-       DPRINTK("ENTER\n");
-
-       ata_qc_timeout(ata_qc_from_tag(ap, ap->active_tag));
-
-       DPRINTK("EXIT\n");
-}
-
-/**
- *     ata_qc_schedule_eh - schedule qc for error handling
- *     @qc: command to schedule error handling for
- *
- *     Schedule error handling for @qc.  EH will kick in as soon as
- *     other commands are drained.
- *
- *     LOCKING:
- *     spin_lock_irqsave(host_set lock)
- */
-void ata_qc_schedule_eh(struct ata_queued_cmd *qc)
-{
-       struct ata_port *ap = qc->ap;
-
-       WARN_ON(!ap->ops->error_handler);
-
-       qc->flags |= ATA_QCFLAG_FAILED;
-       qc->ap->pflags |= ATA_PFLAG_EH_PENDING;
-
-       /* The following will fail if timeout has already expired.
-        * ata_scsi_error() takes care of such scmds on EH entry.
-        * Note that ATA_QCFLAG_FAILED is unconditionally set after
-        * this function completes.
-        */
-       scsi_req_abort_cmd(qc->scsicmd);
-}
-
-/**
- *     ata_port_schedule_eh - schedule error handling without a qc
- *     @ap: ATA port to schedule EH for
- *
- *     Schedule error handling for @ap.  EH will kick in as soon as
- *     all commands are drained.
- *
- *     LOCKING:
- *     spin_lock_irqsave(host_set lock)
- */
-void ata_port_schedule_eh(struct ata_port *ap)
-{
-       WARN_ON(!ap->ops->error_handler);
-
-       ap->pflags |= ATA_PFLAG_EH_PENDING;
-       scsi_schedule_eh(ap->host);
-
-       DPRINTK("port EH scheduled\n");
-}
-
-/**
- *     ata_port_abort - abort all qc's on the port
- *     @ap: ATA port to abort qc's for
- *
- *     Abort all active qc's of @ap and schedule EH.
- *
- *     LOCKING:
- *     spin_lock_irqsave(host_set lock)
- *
- *     RETURNS:
- *     Number of aborted qc's.
- */
-int ata_port_abort(struct ata_port *ap)
-{
-       int tag, nr_aborted = 0;
-
-       WARN_ON(!ap->ops->error_handler);
-
-       for (tag = 0; tag < ATA_MAX_QUEUE; tag++) {
-               struct ata_queued_cmd *qc = ata_qc_from_tag(ap, tag);
-
-               if (qc) {
-                       qc->flags |= ATA_QCFLAG_FAILED;
-                       ata_qc_complete(qc);
-                       nr_aborted++;
-               }
-       }
-
-       if (!nr_aborted)
-               ata_port_schedule_eh(ap);
-
-       return nr_aborted;
-}
-
-/**
- *     __ata_port_freeze - freeze port
- *     @ap: ATA port to freeze
- *
- *     This function is called when HSM violation or some other
- *     condition disrupts normal operation of the port.  Frozen port
- *     is not allowed to perform any operation until the port is
- *     thawed, which usually follows a successful reset.
- *
- *     ap->ops->freeze() callback can be used for freezing the port
- *     hardware-wise (e.g. mask interrupt and stop DMA engine).  If a
- *     port cannot be frozen hardware-wise, the interrupt handler
- *     must ack and clear interrupts unconditionally while the port
- *     is frozen.
- *
- *     LOCKING:
- *     spin_lock_irqsave(host_set lock)
- */
-static void __ata_port_freeze(struct ata_port *ap)
-{
-       WARN_ON(!ap->ops->error_handler);
-
-       if (ap->ops->freeze)
-               ap->ops->freeze(ap);
-
-       ap->pflags |= ATA_PFLAG_FROZEN;
-
-       DPRINTK("ata%u port frozen\n", ap->id);
-}
-
-/**
- *     ata_port_freeze - abort & freeze port
- *     @ap: ATA port to freeze
- *
- *     Abort and freeze @ap.
- *
- *     LOCKING:
- *     spin_lock_irqsave(host_set lock)
- *
- *     RETURNS:
- *     Number of aborted commands.
- */
-int ata_port_freeze(struct ata_port *ap)
-{
-       int nr_aborted;
-
-       WARN_ON(!ap->ops->error_handler);
-
-       nr_aborted = ata_port_abort(ap);
-       __ata_port_freeze(ap);
-
-       return nr_aborted;
-}
-
-/**
- *     ata_eh_freeze_port - EH helper to freeze port
- *     @ap: ATA port to freeze
- *
- *     Freeze @ap.
- *
- *     LOCKING:
- *     None.
- */
-void ata_eh_freeze_port(struct ata_port *ap)
-{
-       unsigned long flags;
-
-       if (!ap->ops->error_handler)
-               return;
-
-       spin_lock_irqsave(ap->lock, flags);
-       __ata_port_freeze(ap);
-       spin_unlock_irqrestore(ap->lock, flags);
-}
-
-/**
- *     ata_port_thaw_port - EH helper to thaw port
- *     @ap: ATA port to thaw
- *
- *     Thaw frozen port @ap.
- *
- *     LOCKING:
- *     None.
- */
-void ata_eh_thaw_port(struct ata_port *ap)
-{
-       unsigned long flags;
-
-       if (!ap->ops->error_handler)
-               return;
-
-       spin_lock_irqsave(ap->lock, flags);
-
-       ap->pflags &= ~ATA_PFLAG_FROZEN;
-
-       if (ap->ops->thaw)
-               ap->ops->thaw(ap);
-
-       spin_unlock_irqrestore(ap->lock, flags);
-
-       DPRINTK("ata%u port thawed\n", ap->id);
-}
-
-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->lock, flags);
-       qc->scsidone = ata_eh_scsidone;
-       __ata_qc_complete(qc);
-       WARN_ON(ata_tag_valid(qc->tag));
-       spin_unlock_irqrestore(ap->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.
- *     scmd->retries is decremented for commands which get retried
- *     due to unrelated failures (qc->err_mask is zero).
- */
-void ata_eh_qc_retry(struct ata_queued_cmd *qc)
-{
-       struct scsi_cmnd *scmd = qc->scsicmd;
-       if (!qc->err_mask && scmd->retries)
-               scmd->retries--;
-       __ata_eh_qc_complete(qc);
-}
-
-/**
- *     ata_eh_detach_dev - detach ATA device
- *     @dev: ATA device to detach
- *
- *     Detach @dev.
- *
- *     LOCKING:
- *     None.
- */
-static void ata_eh_detach_dev(struct ata_device *dev)
-{
-       struct ata_port *ap = dev->ap;
-       unsigned long flags;
-
-       ata_dev_disable(dev);
-
-       spin_lock_irqsave(ap->lock, flags);
-
-       dev->flags &= ~ATA_DFLAG_DETACH;
-
-       if (ata_scsi_offline_dev(dev)) {
-               dev->flags |= ATA_DFLAG_DETACHED;
-               ap->pflags |= ATA_PFLAG_SCSI_HOTPLUG;
-       }
-
-       /* clear per-dev EH actions */
-       ata_eh_clear_action(dev, &ap->eh_info, ATA_EH_PERDEV_MASK);
-       ata_eh_clear_action(dev, &ap->eh_context.i, ATA_EH_PERDEV_MASK);
-
-       spin_unlock_irqrestore(ap->lock, flags);
-}
-
-/**
- *     ata_eh_about_to_do - about to perform eh_action
- *     @ap: target ATA port
- *     @dev: target ATA dev for per-dev action (can be NULL)
- *     @action: action about to be performed
- *
- *     Called just before performing EH actions to clear related bits
- *     in @ap->eh_info such that eh actions are not unnecessarily
- *     repeated.
- *
- *     LOCKING:
- *     None.
- */
-static void ata_eh_about_to_do(struct ata_port *ap, struct ata_device *dev,
-                              unsigned int action)
-{
-       unsigned long flags;
-       struct ata_eh_info *ehi = &ap->eh_info;
-       struct ata_eh_context *ehc = &ap->eh_context;
-
-       spin_lock_irqsave(ap->lock, flags);
-
-       /* Reset is represented by combination of actions and EHI
-        * flags.  Suck in all related bits before clearing eh_info to
-        * avoid losing requested action.
-        */
-       if (action & ATA_EH_RESET_MASK) {
-               ehc->i.action |= ehi->action & ATA_EH_RESET_MASK;
-               ehc->i.flags |= ehi->flags & ATA_EHI_RESET_MODIFIER_MASK;
-
-               /* make sure all reset actions are cleared & clear EHI flags */
-               action |= ATA_EH_RESET_MASK;
-               ehi->flags &= ~ATA_EHI_RESET_MODIFIER_MASK;
-       }
-
-       ata_eh_clear_action(dev, ehi, action);
-
-       if (!(ehc->i.flags & ATA_EHI_QUIET))
-               ap->pflags |= ATA_PFLAG_RECOVERED;
-
-       spin_unlock_irqrestore(ap->lock, flags);
-}
-
-/**
- *     ata_eh_done - EH action complete
- *     @ap: target ATA port
- *     @dev: target ATA dev for per-dev action (can be NULL)
- *     @action: action just completed
- *
- *     Called right after performing EH actions to clear related bits
- *     in @ap->eh_context.
- *
- *     LOCKING:
- *     None.
- */
-static void ata_eh_done(struct ata_port *ap, struct ata_device *dev,
-                       unsigned int action)
-{
-       /* if reset is complete, clear all reset actions & reset modifier */
-       if (action & ATA_EH_RESET_MASK) {
-               action |= ATA_EH_RESET_MASK;
-               ap->eh_context.i.flags &= ~ATA_EHI_RESET_MODIFIER_MASK;
-       }
-
-       ata_eh_clear_action(dev, &ap->eh_context.i, action);
-}
-
-/**
- *     ata_err_string - convert err_mask to descriptive string
- *     @err_mask: error mask to convert to string
- *
- *     Convert @err_mask to descriptive string.  Errors are
- *     prioritized according to severity and only the most severe
- *     error is reported.
- *
- *     LOCKING:
- *     None.
- *
- *     RETURNS:
- *     Descriptive string for @err_mask
- */
-static const char * ata_err_string(unsigned int err_mask)
-{
-       if (err_mask & AC_ERR_HOST_BUS)
-               return "host bus error";
-       if (err_mask & AC_ERR_ATA_BUS)
-               return "ATA bus error";
-       if (err_mask & AC_ERR_TIMEOUT)
-               return "timeout";
-       if (err_mask & AC_ERR_HSM)
-               return "HSM violation";
-       if (err_mask & AC_ERR_SYSTEM)
-               return "internal error";
-       if (err_mask & AC_ERR_MEDIA)
-               return "media error";
-       if (err_mask & AC_ERR_INVALID)
-               return "invalid argument";
-       if (err_mask & AC_ERR_DEV)
-               return "device error";
-       return "unknown error";
-}
-
-/**
- *     ata_read_log_page - read a specific log page
- *     @dev: target device
- *     @page: page to read
- *     @buf: buffer to store read page
- *     @sectors: number of sectors to read
- *
- *     Read log page using READ_LOG_EXT command.
- *
- *     LOCKING:
- *     Kernel thread context (may sleep).
- *
- *     RETURNS:
- *     0 on success, AC_ERR_* mask otherwise.
- */
-static unsigned int ata_read_log_page(struct ata_device *dev,
-                                     u8 page, void *buf, unsigned int sectors)
-{
-       struct ata_taskfile tf;
-       unsigned int err_mask;
-
-       DPRINTK("read log page - page %d\n", page);
-
-       ata_tf_init(dev, &tf);
-       tf.command = ATA_CMD_READ_LOG_EXT;
-       tf.lbal = page;
-       tf.nsect = sectors;
-       tf.hob_nsect = sectors >> 8;
-       tf.flags |= ATA_TFLAG_ISADDR | ATA_TFLAG_LBA48 | ATA_TFLAG_DEVICE;
-       tf.protocol = ATA_PROT_PIO;
-
-       err_mask = ata_exec_internal(dev, &tf, NULL, DMA_FROM_DEVICE,
-                                    buf, sectors * ATA_SECT_SIZE);
-
-       DPRINTK("EXIT, err_mask=%x\n", err_mask);
-       return err_mask;
-}
-
-/**
- *     ata_eh_read_log_10h - Read log page 10h for NCQ error details
- *     @dev: Device to read log page 10h from
- *     @tag: Resulting tag of the failed command
- *     @tf: Resulting taskfile registers of the failed command
- *
- *     Read log page 10h to obtain NCQ error details and clear error
- *     condition.
- *
- *     LOCKING:
- *     Kernel thread context (may sleep).
- *
- *     RETURNS:
- *     0 on success, -errno otherwise.
- */
-static int ata_eh_read_log_10h(struct ata_device *dev,
-                              int *tag, struct ata_taskfile *tf)
-{
-       u8 *buf = dev->ap->sector_buf;
-       unsigned int err_mask;
-       u8 csum;
-       int i;
-
-       err_mask = ata_read_log_page(dev, ATA_LOG_SATA_NCQ, buf, 1);
-       if (err_mask)
-               return -EIO;
-
-       csum = 0;
-       for (i = 0; i < ATA_SECT_SIZE; i++)
-               csum += buf[i];
-       if (csum)
-               ata_dev_printk(dev, KERN_WARNING,
-                              "invalid checksum 0x%x on log page 10h\n", csum);
-
-       if (buf[0] & 0x80)
-               return -ENOENT;
-
-       *tag = buf[0] & 0x1f;
-
-       tf->command = buf[2];
-       tf->feature = buf[3];
-       tf->lbal = buf[4];
-       tf->lbam = buf[5];
-       tf->lbah = buf[6];
-       tf->device = buf[7];
-       tf->hob_lbal = buf[8];
-       tf->hob_lbam = buf[9];
-       tf->hob_lbah = buf[10];
-       tf->nsect = buf[12];
-       tf->hob_nsect = buf[13];
-
-       return 0;
-}
-
-/**
- *     atapi_eh_request_sense - perform ATAPI REQUEST_SENSE
- *     @dev: device to perform REQUEST_SENSE to
- *     @sense_buf: result sense data buffer (SCSI_SENSE_BUFFERSIZE bytes long)
- *
- *     Perform ATAPI REQUEST_SENSE after the device reported CHECK
- *     SENSE.  This function is EH helper.
- *
- *     LOCKING:
- *     Kernel thread context (may sleep).
- *
- *     RETURNS:
- *     0 on success, AC_ERR_* mask on failure
- */
-static unsigned int atapi_eh_request_sense(struct ata_device *dev,
-                                          unsigned char *sense_buf)
-{
-       struct ata_port *ap = dev->ap;
-       struct ata_taskfile tf;
-       u8 cdb[ATAPI_CDB_LEN];
-
-       DPRINTK("ATAPI request sense\n");
-
-       ata_tf_init(dev, &tf);
-
-       /* FIXME: is this needed? */
-       memset(sense_buf, 0, SCSI_SENSE_BUFFERSIZE);
-
-       /* XXX: why tf_read here? */
-       ap->ops->tf_read(ap, &tf);
-
-       /* fill these in, for the case where they are -not- overwritten */
-       sense_buf[0] = 0x70;
-       sense_buf[2] = tf.feature >> 4;
-
-       memset(cdb, 0, ATAPI_CDB_LEN);
-       cdb[0] = REQUEST_SENSE;
-       cdb[4] = SCSI_SENSE_BUFFERSIZE;
-
-       tf.flags |= ATA_TFLAG_ISADDR | ATA_TFLAG_DEVICE;
-       tf.command = ATA_CMD_PACKET;
-
-       /* is it pointless to prefer PIO for "safety reasons"? */
-       if (ap->flags & ATA_FLAG_PIO_DMA) {
-               tf.protocol = ATA_PROT_ATAPI_DMA;
-               tf.feature |= ATAPI_PKT_DMA;
-       } else {
-               tf.protocol = ATA_PROT_ATAPI;
-               tf.lbam = (8 * 1024) & 0xff;
-               tf.lbah = (8 * 1024) >> 8;
-       }
-
-       return ata_exec_internal(dev, &tf, cdb, DMA_FROM_DEVICE,
-                                sense_buf, SCSI_SENSE_BUFFERSIZE);
-}
-
-/**
- *     ata_eh_analyze_serror - analyze SError for a failed port
- *     @ap: ATA port to analyze SError for
- *
- *     Analyze SError if available and further determine cause of
- *     failure.
- *
- *     LOCKING:
- *     None.
- */
-static void ata_eh_analyze_serror(struct ata_port *ap)
-{
-       struct ata_eh_context *ehc = &ap->eh_context;
-       u32 serror = ehc->i.serror;
-       unsigned int err_mask = 0, action = 0;
-
-       if (serror & SERR_PERSISTENT) {
-               err_mask |= AC_ERR_ATA_BUS;
-               action |= ATA_EH_HARDRESET;
-       }
-       if (serror &
-           (SERR_DATA_RECOVERED | SERR_COMM_RECOVERED | SERR_DATA)) {
-               err_mask |= AC_ERR_ATA_BUS;
-               action |= ATA_EH_SOFTRESET;
-       }
-       if (serror & SERR_PROTOCOL) {
-               err_mask |= AC_ERR_HSM;
-               action |= ATA_EH_SOFTRESET;
-       }
-       if (serror & SERR_INTERNAL) {
-               err_mask |= AC_ERR_SYSTEM;
-               action |= ATA_EH_SOFTRESET;
-       }
-       if (serror & (SERR_PHYRDY_CHG | SERR_DEV_XCHG))
-               ata_ehi_hotplugged(&ehc->i);
-
-       ehc->i.err_mask |= err_mask;
-       ehc->i.action |= action;
-}
-
-/**
- *     ata_eh_analyze_ncq_error - analyze NCQ error
- *     @ap: ATA port to analyze NCQ error for
- *
- *     Read log page 10h, determine the offending qc and acquire
- *     error status TF.  For NCQ device errors, all LLDDs have to do
- *     is setting AC_ERR_DEV in ehi->err_mask.  This function takes
- *     care of the rest.
- *
- *     LOCKING:
- *     Kernel thread context (may sleep).
- */
-static void ata_eh_analyze_ncq_error(struct ata_port *ap)
-{
-       struct ata_eh_context *ehc = &ap->eh_context;
-       struct ata_device *dev = ap->device;
-       struct ata_queued_cmd *qc;
-       struct ata_taskfile tf;
-       int tag, rc;
-
-       /* if frozen, we can't do much */
-       if (ap->pflags & ATA_PFLAG_FROZEN)
-               return;
-
-       /* is it NCQ device error? */
-       if (!ap->sactive || !(ehc->i.err_mask & AC_ERR_DEV))
-               return;
-
-       /* has LLDD analyzed already? */
-       for (tag = 0; tag < ATA_MAX_QUEUE; tag++) {
-               qc = __ata_qc_from_tag(ap, tag);
-
-               if (!(qc->flags & ATA_QCFLAG_FAILED))
-                       continue;
-
-               if (qc->err_mask)
-                       return;
-       }
-
-       /* okay, this error is ours */
-       rc = ata_eh_read_log_10h(dev, &tag, &tf);
-       if (rc) {
-               ata_port_printk(ap, KERN_ERR, "failed to read log page 10h "
-                               "(errno=%d)\n", rc);
-               return;
-       }
-
-       if (!(ap->sactive & (1 << tag))) {
-               ata_port_printk(ap, KERN_ERR, "log page 10h reported "
-                               "inactive tag %d\n", tag);
-               return;
-       }
-
-       /* we've got the perpetrator, condemn it */
-       qc = __ata_qc_from_tag(ap, tag);
-       memcpy(&qc->result_tf, &tf, sizeof(tf));
-       qc->err_mask |= AC_ERR_DEV;
-       ehc->i.err_mask &= ~AC_ERR_DEV;
-}
-
-/**
- *     ata_eh_analyze_tf - analyze taskfile of a failed qc
- *     @qc: qc to analyze
- *     @tf: Taskfile registers to analyze
- *
- *     Analyze taskfile of @qc and further determine cause of
- *     failure.  This function also requests ATAPI sense data if
- *     avaliable.
- *
- *     LOCKING:
- *     Kernel thread context (may sleep).
- *
- *     RETURNS:
- *     Determined recovery action
- */
-static unsigned int ata_eh_analyze_tf(struct ata_queued_cmd *qc,
-                                     const struct ata_taskfile *tf)
-{
-       unsigned int tmp, action = 0;
-       u8 stat = tf->command, err = tf->feature;
-
-       if ((stat & (ATA_BUSY | ATA_DRQ | ATA_DRDY)) != ATA_DRDY) {
-               qc->err_mask |= AC_ERR_HSM;
-               return ATA_EH_SOFTRESET;
-       }
-
-       if (!(qc->err_mask & AC_ERR_DEV))
-               return 0;
-
-       switch (qc->dev->class) {
-       case ATA_DEV_ATA:
-               if (err & ATA_ICRC)
-                       qc->err_mask |= AC_ERR_ATA_BUS;
-               if (err & ATA_UNC)
-                       qc->err_mask |= AC_ERR_MEDIA;
-               if (err & ATA_IDNF)
-                       qc->err_mask |= AC_ERR_INVALID;
-               break;
-
-       case ATA_DEV_ATAPI:
-               tmp = atapi_eh_request_sense(qc->dev,
-                                            qc->scsicmd->sense_buffer);
-               if (!tmp) {
-                       /* ATA_QCFLAG_SENSE_VALID is used to tell
-                        * atapi_qc_complete() that sense data is
-                        * already valid.
-                        *
-                        * TODO: interpret sense data and set
-                        * appropriate err_mask.
-                        */
-                       qc->flags |= ATA_QCFLAG_SENSE_VALID;
-               } else
-                       qc->err_mask |= tmp;
-       }
-
-       if (qc->err_mask & (AC_ERR_HSM | AC_ERR_TIMEOUT | AC_ERR_ATA_BUS))
-               action |= ATA_EH_SOFTRESET;
-
-       return action;
-}
-
-static int ata_eh_categorize_ering_entry(struct ata_ering_entry *ent)
-{
-       if (ent->err_mask & (AC_ERR_ATA_BUS | AC_ERR_TIMEOUT))
-               return 1;
-
-       if (ent->is_io) {
-               if (ent->err_mask & AC_ERR_HSM)
-                       return 1;
-               if ((ent->err_mask &
-                    (AC_ERR_DEV|AC_ERR_MEDIA|AC_ERR_INVALID)) == AC_ERR_DEV)
-                       return 2;
-       }
-
-       return 0;
-}
-
-struct speed_down_needed_arg {
-       u64 since;
-       int nr_errors[3];
-};
-
-static int speed_down_needed_cb(struct ata_ering_entry *ent, void *void_arg)
-{
-       struct speed_down_needed_arg *arg = void_arg;
-
-       if (ent->timestamp < arg->since)
-               return -1;
-
-       arg->nr_errors[ata_eh_categorize_ering_entry(ent)]++;
-       return 0;
-}
-
-/**
- *     ata_eh_speed_down_needed - Determine wheter speed down is necessary
- *     @dev: Device of interest
- *
- *     This function examines error ring of @dev and determines
- *     whether speed down is necessary.  Speed down is necessary if
- *     there have been more than 3 of Cat-1 errors or 10 of Cat-2
- *     errors during last 15 minutes.
- *
- *     Cat-1 errors are ATA_BUS, TIMEOUT for any command and HSM
- *     violation for known supported commands.
- *
- *     Cat-2 errors are unclassified DEV error for known supported
- *     command.
- *
- *     LOCKING:
- *     Inherited from caller.
- *
- *     RETURNS:
- *     1 if speed down is necessary, 0 otherwise
- */
-static int ata_eh_speed_down_needed(struct ata_device *dev)
-{
-       const u64 interval = 15LLU * 60 * HZ;
-       static const int err_limits[3] = { -1, 3, 10 };
-       struct speed_down_needed_arg arg;
-       struct ata_ering_entry *ent;
-       int err_cat;
-       u64 j64;
-
-       ent = ata_ering_top(&dev->ering);
-       if (!ent)
-               return 0;
-
-       err_cat = ata_eh_categorize_ering_entry(ent);
-       if (err_cat == 0)
-               return 0;
-
-       memset(&arg, 0, sizeof(arg));
-
-       j64 = get_jiffies_64();
-       if (j64 >= interval)
-               arg.since = j64 - interval;
-       else
-               arg.since = 0;
-
-       ata_ering_map(&dev->ering, speed_down_needed_cb, &arg);
-
-       return arg.nr_errors[err_cat] > err_limits[err_cat];
-}
-
-/**
- *     ata_eh_speed_down - record error and speed down if necessary
- *     @dev: Failed device
- *     @is_io: Did the device fail during normal IO?
- *     @err_mask: err_mask of the error
- *
- *     Record error and examine error history to determine whether
- *     adjusting transmission speed is necessary.  It also sets
- *     transmission limits appropriately if such adjustment is
- *     necessary.
- *
- *     LOCKING:
- *     Kernel thread context (may sleep).
- *
- *     RETURNS:
- *     0 on success, -errno otherwise
- */
-static int ata_eh_speed_down(struct ata_device *dev, int is_io,
-                            unsigned int err_mask)
-{
-       if (!err_mask)
-               return 0;
-
-       /* record error and determine whether speed down is necessary */
-       ata_ering_record(&dev->ering, is_io, err_mask);
-
-       if (!ata_eh_speed_down_needed(dev))
-               return 0;
-
-       /* speed down SATA link speed if possible */
-       if (sata_down_spd_limit(dev->ap) == 0)
-               return ATA_EH_HARDRESET;
-
-       /* lower transfer mode */
-       if (ata_down_xfermask_limit(dev, 0) == 0)
-               return ATA_EH_SOFTRESET;
-
-       ata_dev_printk(dev, KERN_ERR,
-                      "speed down requested but no transfer mode left\n");
-       return 0;
-}
-
-/**
- *     ata_eh_autopsy - analyze error and determine recovery action
- *     @ap: ATA port to perform autopsy on
- *
- *     Analyze why @ap failed and determine which recovery action is
- *     needed.  This function also sets more detailed AC_ERR_* values
- *     and fills sense data for ATAPI CHECK SENSE.
- *
- *     LOCKING:
- *     Kernel thread context (may sleep).
- */
-static void ata_eh_autopsy(struct ata_port *ap)
-{
-       struct ata_eh_context *ehc = &ap->eh_context;
-       unsigned int all_err_mask = 0;
-       int tag, is_io = 0;
-       u32 serror;
-       int rc;
-
-       DPRINTK("ENTER\n");
-
-       if (ehc->i.flags & ATA_EHI_NO_AUTOPSY)
-               return;
-
-       /* obtain and analyze SError */
-       rc = sata_scr_read(ap, SCR_ERROR, &serror);
-       if (rc == 0) {
-               ehc->i.serror |= serror;
-               ata_eh_analyze_serror(ap);
-       } else if (rc != -EOPNOTSUPP)
-               ehc->i.action |= ATA_EH_HARDRESET;
-
-       /* analyze NCQ failure */
-       ata_eh_analyze_ncq_error(ap);
-
-       /* any real error trumps AC_ERR_OTHER */
-       if (ehc->i.err_mask & ~AC_ERR_OTHER)
-               ehc->i.err_mask &= ~AC_ERR_OTHER;
-
-       all_err_mask |= ehc->i.err_mask;
-
-       for (tag = 0; tag < ATA_MAX_QUEUE; tag++) {
-               struct ata_queued_cmd *qc = __ata_qc_from_tag(ap, tag);
-
-               if (!(qc->flags & ATA_QCFLAG_FAILED))
-                       continue;
-
-               /* inherit upper level err_mask */
-               qc->err_mask |= ehc->i.err_mask;
-
-               /* analyze TF */
-               ehc->i.action |= ata_eh_analyze_tf(qc, &qc->result_tf);
-
-               /* DEV errors are probably spurious in case of ATA_BUS error */
-               if (qc->err_mask & AC_ERR_ATA_BUS)
-                       qc->err_mask &= ~(AC_ERR_DEV | AC_ERR_MEDIA |
-                                         AC_ERR_INVALID);
-
-               /* any real error trumps unknown error */
-               if (qc->err_mask & ~AC_ERR_OTHER)
-                       qc->err_mask &= ~AC_ERR_OTHER;
-
-               /* SENSE_VALID trumps dev/unknown error and revalidation */
-               if (qc->flags & ATA_QCFLAG_SENSE_VALID) {
-                       qc->err_mask &= ~(AC_ERR_DEV | AC_ERR_OTHER);
-                       ehc->i.action &= ~ATA_EH_REVALIDATE;
-               }
-
-               /* accumulate error info */
-               ehc->i.dev = qc->dev;
-               all_err_mask |= qc->err_mask;
-               if (qc->flags & ATA_QCFLAG_IO)
-                       is_io = 1;
-       }
-
-       /* enforce default EH actions */
-       if (ap->pflags & ATA_PFLAG_FROZEN ||
-           all_err_mask & (AC_ERR_HSM | AC_ERR_TIMEOUT))
-               ehc->i.action |= ATA_EH_SOFTRESET;
-       else if (all_err_mask)
-               ehc->i.action |= ATA_EH_REVALIDATE;
-
-       /* if we have offending qcs and the associated failed device */
-       if (ehc->i.dev) {
-               /* speed down */
-               ehc->i.action |= ata_eh_speed_down(ehc->i.dev, is_io,
-                                                  all_err_mask);
-
-               /* perform per-dev EH action only on the offending device */
-               ehc->i.dev_action[ehc->i.dev->devno] |=
-                       ehc->i.action & ATA_EH_PERDEV_MASK;
-               ehc->i.action &= ~ATA_EH_PERDEV_MASK;
-       }
-
-       DPRINTK("EXIT\n");
-}
-
-/**
- *     ata_eh_report - report error handling to user
- *     @ap: ATA port EH is going on
- *
- *     Report EH to user.
- *
- *     LOCKING:
- *     None.
- */
-static void ata_eh_report(struct ata_port *ap)
-{
-       struct ata_eh_context *ehc = &ap->eh_context;
-       const char *frozen, *desc;
-       int tag, nr_failed = 0;
-
-       desc = NULL;
-       if (ehc->i.desc[0] != '\0')
-               desc = ehc->i.desc;
-
-       for (tag = 0; tag < ATA_MAX_QUEUE; tag++) {
-               struct ata_queued_cmd *qc = __ata_qc_from_tag(ap, tag);
-
-               if (!(qc->flags & ATA_QCFLAG_FAILED))
-                       continue;
-               if (qc->flags & ATA_QCFLAG_SENSE_VALID && !qc->err_mask)
-                       continue;
-
-               nr_failed++;
-       }
-
-       if (!nr_failed && !ehc->i.err_mask)
-               return;
-
-       frozen = "";
-       if (ap->pflags & ATA_PFLAG_FROZEN)
-               frozen = " frozen";
-
-       if (ehc->i.dev) {
-               ata_dev_printk(ehc->i.dev, KERN_ERR, "exception Emask 0x%x "
-                              "SAct 0x%x SErr 0x%x action 0x%x%s\n",
-                              ehc->i.err_mask, ap->sactive, ehc->i.serror,
-                              ehc->i.action, frozen);
-               if (desc)
-                       ata_dev_printk(ehc->i.dev, KERN_ERR, "(%s)\n", desc);
-       } else {
-               ata_port_printk(ap, KERN_ERR, "exception Emask 0x%x "
-                               "SAct 0x%x SErr 0x%x action 0x%x%s\n",
-                               ehc->i.err_mask, ap->sactive, ehc->i.serror,
-                               ehc->i.action, frozen);
-               if (desc)
-                       ata_port_printk(ap, KERN_ERR, "(%s)\n", desc);
-       }
-
-       for (tag = 0; tag < ATA_MAX_QUEUE; tag++) {
-               struct ata_queued_cmd *qc = __ata_qc_from_tag(ap, tag);
-
-               if (!(qc->flags & ATA_QCFLAG_FAILED) || !qc->err_mask)
-                       continue;
-
-               ata_dev_printk(qc->dev, KERN_ERR, "tag %d cmd 0x%x "
-                              "Emask 0x%x stat 0x%x err 0x%x (%s)\n",
-                              qc->tag, qc->tf.command, qc->err_mask,
-                              qc->result_tf.command, qc->result_tf.feature,
-                              ata_err_string(qc->err_mask));
-       }
-}
-
-static int ata_do_reset(struct ata_port *ap, ata_reset_fn_t reset,
-                       unsigned int *classes)
-{
-       int i, rc;
-
-       for (i = 0; i < ATA_MAX_DEVICES; i++)
-               classes[i] = ATA_DEV_UNKNOWN;
-
-       rc = reset(ap, classes);
-       if (rc)
-               return rc;
-
-       /* If any class isn't ATA_DEV_UNKNOWN, consider classification
-        * is complete and convert all ATA_DEV_UNKNOWN to
-        * ATA_DEV_NONE.
-        */
-       for (i = 0; i < ATA_MAX_DEVICES; i++)
-               if (classes[i] != ATA_DEV_UNKNOWN)
-                       break;
-
-       if (i < ATA_MAX_DEVICES)
-               for (i = 0; i < ATA_MAX_DEVICES; i++)
-                       if (classes[i] == ATA_DEV_UNKNOWN)
-                               classes[i] = ATA_DEV_NONE;
-
-       return 0;
-}
-
-static int ata_eh_followup_srst_needed(int rc, int classify,
-                                      const unsigned int *classes)
-{
-       if (rc == -EAGAIN)
-               return 1;
-       if (rc != 0)
-               return 0;
-       if (classify && classes[0] == ATA_DEV_UNKNOWN)
-               return 1;
-       return 0;
-}
-
-static int ata_eh_reset(struct ata_port *ap, int classify,
-                       ata_prereset_fn_t prereset, ata_reset_fn_t softreset,
-                       ata_reset_fn_t hardreset, ata_postreset_fn_t postreset)
-{
-       struct ata_eh_context *ehc = &ap->eh_context;
-       unsigned int *classes = ehc->classes;
-       int tries = ATA_EH_RESET_TRIES;
-       int verbose = !(ehc->i.flags & ATA_EHI_QUIET);
-       unsigned int action;
-       ata_reset_fn_t reset;
-       int i, did_followup_srst, rc;
-
-       /* about to reset */
-       ata_eh_about_to_do(ap, NULL, ehc->i.action & ATA_EH_RESET_MASK);
-
-       /* Determine which reset to use and record in ehc->i.action.
-        * prereset() may examine and modify it.
-        */
-       action = ehc->i.action;
-       ehc->i.action &= ~ATA_EH_RESET_MASK;
-       if (softreset && (!hardreset || (!sata_set_spd_needed(ap) &&
-                                        !(action & ATA_EH_HARDRESET))))
-               ehc->i.action |= ATA_EH_SOFTRESET;
-       else
-               ehc->i.action |= ATA_EH_HARDRESET;
-
-       if (prereset) {
-               rc = prereset(ap);
-               if (rc) {
-                       ata_port_printk(ap, KERN_ERR,
-                                       "prereset failed (errno=%d)\n", rc);
-                       return rc;
-               }
-       }
-
-       /* prereset() might have modified ehc->i.action */
-       if (ehc->i.action & ATA_EH_HARDRESET)
-               reset = hardreset;
-       else if (ehc->i.action & ATA_EH_SOFTRESET)
-               reset = softreset;
-       else {
-               /* prereset told us not to reset, bang classes and return */
-               for (i = 0; i < ATA_MAX_DEVICES; i++)
-                       classes[i] = ATA_DEV_NONE;
-               return 0;
-       }
-
-       /* did prereset() screw up?  if so, fix up to avoid oopsing */
-       if (!reset) {
-               ata_port_printk(ap, KERN_ERR, "BUG: prereset() requested "
-                               "invalid reset type\n");
-               if (softreset)
-                       reset = softreset;
-               else
-                       reset = hardreset;
-       }
-
- retry:
-       /* shut up during boot probing */
-       if (verbose)
-               ata_port_printk(ap, KERN_INFO, "%s resetting port\n",
-                               reset == softreset ? "soft" : "hard");
-
-       /* mark that this EH session started with reset */
-       ehc->i.flags |= ATA_EHI_DID_RESET;
-
-       rc = ata_do_reset(ap, reset, classes);
-
-       did_followup_srst = 0;
-       if (reset == hardreset &&
-           ata_eh_followup_srst_needed(rc, classify, classes)) {
-               /* okay, let's do follow-up softreset */
-               did_followup_srst = 1;
-               reset = softreset;
-
-               if (!reset) {
-                       ata_port_printk(ap, KERN_ERR,
-                                       "follow-up softreset required "
-                                       "but no softreset avaliable\n");
-                       return -EINVAL;
-               }
-
-               ata_eh_about_to_do(ap, NULL, ATA_EH_RESET_MASK);
-               rc = ata_do_reset(ap, reset, classes);
-
-               if (rc == 0 && classify &&
-                   classes[0] == ATA_DEV_UNKNOWN) {
-                       ata_port_printk(ap, KERN_ERR,
-                                       "classification failed\n");
-                       return -EINVAL;
-               }
-       }
-
-       if (rc && --tries) {
-               const char *type;
-
-               if (reset == softreset) {
-                       if (did_followup_srst)
-                               type = "follow-up soft";
-                       else
-                               type = "soft";
-               } else
-                       type = "hard";
-
-               ata_port_printk(ap, KERN_WARNING,
-                               "%sreset failed, retrying in 5 secs\n", type);
-               ssleep(5);
-
-               if (reset == hardreset)
-                       sata_down_spd_limit(ap);
-               if (hardreset)
-                       reset = hardreset;
-               goto retry;
-       }
-
-       if (rc == 0) {
-               /* After the reset, the device state is PIO 0 and the
-                * controller state is undefined.  Record the mode.
-                */
-               for (i = 0; i < ATA_MAX_DEVICES; i++)
-                       ap->device[i].pio_mode = XFER_PIO_0;
-
-               if (postreset)
-                       postreset(ap, classes);
-
-               /* reset successful, schedule revalidation */
-               ata_eh_done(ap, NULL, ehc->i.action & ATA_EH_RESET_MASK);
-               ehc->i.action |= ATA_EH_REVALIDATE;
-       }
-
-       return rc;
-}
-
-static int ata_eh_revalidate_and_attach(struct ata_port *ap,
-                                       struct ata_device **r_failed_dev)
-{
-       struct ata_eh_context *ehc = &ap->eh_context;
-       struct ata_device *dev;
-       unsigned long flags;
-       int i, rc = 0;
-
-       DPRINTK("ENTER\n");
-
-       for (i = 0; i < ATA_MAX_DEVICES; i++) {
-               unsigned int action;
-
-               dev = &ap->device[i];
-               action = ata_eh_dev_action(dev);
-
-               if (action & ATA_EH_REVALIDATE && ata_dev_ready(dev)) {
-                       if (ata_port_offline(ap)) {
-                               rc = -EIO;
-                               break;
-                       }
-
-                       ata_eh_about_to_do(ap, dev, ATA_EH_REVALIDATE);
-                       rc = ata_dev_revalidate(dev,
-                                       ehc->i.flags & ATA_EHI_DID_RESET);
-                       if (rc)
-                               break;
-
-                       ata_eh_done(ap, dev, ATA_EH_REVALIDATE);
-
-                       /* schedule the scsi_rescan_device() here */
-                       queue_work(ata_aux_wq, &(ap->scsi_rescan_task));
-               } else if (dev->class == ATA_DEV_UNKNOWN &&
-                          ehc->tries[dev->devno] &&
-                          ata_class_enabled(ehc->classes[dev->devno])) {
-                       dev->class = ehc->classes[dev->devno];
-
-                       rc = ata_dev_read_id(dev, &dev->class, 1, dev->id);
-                       if (rc == 0)
-                               rc = ata_dev_configure(dev, 1);
-
-                       if (rc) {
-                               dev->class = ATA_DEV_UNKNOWN;
-                               break;
-                       }
-
-                       spin_lock_irqsave(ap->lock, flags);
-                       ap->pflags |= ATA_PFLAG_SCSI_HOTPLUG;
-                       spin_unlock_irqrestore(ap->lock, flags);
-               }
-       }
-
-       if (rc)
-               *r_failed_dev = dev;
-
-       DPRINTK("EXIT\n");
-       return rc;
-}
-
-/**
- *     ata_eh_suspend - handle suspend EH action
- *     @ap: target host port
- *     @r_failed_dev: result parameter to indicate failing device
- *
- *     Handle suspend EH action.  Disk devices are spinned down and
- *     other types of devices are just marked suspended.  Once
- *     suspended, no EH action to the device is allowed until it is
- *     resumed.
- *
- *     LOCKING:
- *     Kernel thread context (may sleep).
- *
- *     RETURNS:
- *     0 on success, -errno otherwise
- */
-static int ata_eh_suspend(struct ata_port *ap, struct ata_device **r_failed_dev)
-{
-       struct ata_device *dev;
-       int i, rc = 0;
-
-       DPRINTK("ENTER\n");
-
-       for (i = 0; i < ATA_MAX_DEVICES; i++) {
-               unsigned long flags;
-               unsigned int action, err_mask;
-
-               dev = &ap->device[i];
-               action = ata_eh_dev_action(dev);
-
-               if (!ata_dev_enabled(dev) || !(action & ATA_EH_SUSPEND))
-                       continue;
-
-               WARN_ON(dev->flags & ATA_DFLAG_SUSPENDED);
-
-               ata_eh_about_to_do(ap, dev, ATA_EH_SUSPEND);
-
-               if (dev->class == ATA_DEV_ATA && !(action & ATA_EH_PM_FREEZE)) {
-                       /* flush cache */
-                       rc = ata_flush_cache(dev);
-                       if (rc)
-                               break;
-
-                       /* spin down */
-                       err_mask = ata_do_simple_cmd(dev, ATA_CMD_STANDBYNOW1);
-                       if (err_mask) {
-                               ata_dev_printk(dev, KERN_ERR, "failed to "
-                                              "spin down (err_mask=0x%x)\n",
-                                              err_mask);
-                               rc = -EIO;
-                               break;
-                       }
-               }
-
-               spin_lock_irqsave(ap->lock, flags);
-               dev->flags |= ATA_DFLAG_SUSPENDED;
-               spin_unlock_irqrestore(ap->lock, flags);
-
-               ata_eh_done(ap, dev, ATA_EH_SUSPEND);
-       }
-
-       if (rc)
-               *r_failed_dev = dev;
-
-       DPRINTK("EXIT\n");
-       return 0;
-}
-
-/**
- *     ata_eh_prep_resume - prep for resume EH action
- *     @ap: target host port
- *
- *     Clear SUSPENDED in preparation for scheduled resume actions.
- *     This allows other parts of EH to access the devices being
- *     resumed.
- *
- *     LOCKING:
- *     Kernel thread context (may sleep).
- */
-static void ata_eh_prep_resume(struct ata_port *ap)
-{
-       struct ata_device *dev;
-       unsigned long flags;
-       int i;
-
-       DPRINTK("ENTER\n");
-
-       for (i = 0; i < ATA_MAX_DEVICES; i++) {
-               unsigned int action;
-
-               dev = &ap->device[i];
-               action = ata_eh_dev_action(dev);
-
-               if (!ata_dev_enabled(dev) || !(action & ATA_EH_RESUME))
-                       continue;
-
-               spin_lock_irqsave(ap->lock, flags);
-               dev->flags &= ~ATA_DFLAG_SUSPENDED;
-               spin_unlock_irqrestore(ap->lock, flags);
-       }
-
-       DPRINTK("EXIT\n");
-}
-
-/**
- *     ata_eh_resume - handle resume EH action
- *     @ap: target host port
- *     @r_failed_dev: result parameter to indicate failing device
- *
- *     Handle resume EH action.  Target devices are already reset and
- *     revalidated.  Spinning up is the only operation left.
- *
- *     LOCKING:
- *     Kernel thread context (may sleep).
- *
- *     RETURNS:
- *     0 on success, -errno otherwise
- */
-static int ata_eh_resume(struct ata_port *ap, struct ata_device **r_failed_dev)
-{
-       struct ata_device *dev;
-       int i, rc = 0;
-
-       DPRINTK("ENTER\n");
-
-       for (i = 0; i < ATA_MAX_DEVICES; i++) {
-               unsigned int action, err_mask;
-
-               dev = &ap->device[i];
-               action = ata_eh_dev_action(dev);
-
-               if (!ata_dev_enabled(dev) || !(action & ATA_EH_RESUME))
-                       continue;
-
-               ata_eh_about_to_do(ap, dev, ATA_EH_RESUME);
-
-               if (dev->class == ATA_DEV_ATA && !(action & ATA_EH_PM_FREEZE)) {
-                       err_mask = ata_do_simple_cmd(dev,
-                                                    ATA_CMD_IDLEIMMEDIATE);
-                       if (err_mask) {
-                               ata_dev_printk(dev, KERN_ERR, "failed to "
-                                              "spin up (err_mask=0x%x)\n",
-                                              err_mask);
-                               rc = -EIO;
-                               break;
-                       }
-               }
-
-               ata_eh_done(ap, dev, ATA_EH_RESUME);
-       }
-
-       if (rc)
-               *r_failed_dev = dev;
-
-       DPRINTK("EXIT\n");
-       return 0;
-}
-
-static int ata_port_nr_enabled(struct ata_port *ap)
-{
-       int i, cnt = 0;
-
-       for (i = 0; i < ATA_MAX_DEVICES; i++)
-               if (ata_dev_enabled(&ap->device[i]))
-                       cnt++;
-       return cnt;
-}
-
-static int ata_port_nr_vacant(struct ata_port *ap)
-{
-       int i, cnt = 0;
-
-       for (i = 0; i < ATA_MAX_DEVICES; i++)
-               if (ap->device[i].class == ATA_DEV_UNKNOWN)
-                       cnt++;
-       return cnt;
-}
-
-static int ata_eh_skip_recovery(struct ata_port *ap)
-{
-       struct ata_eh_context *ehc = &ap->eh_context;
-       int i;
-
-       /* skip if all possible devices are suspended */
-       for (i = 0; i < ata_port_max_devices(ap); i++) {
-               struct ata_device *dev = &ap->device[i];
-
-               if (!(dev->flags & ATA_DFLAG_SUSPENDED))
-                       break;
-       }
-
-       if (i == ata_port_max_devices(ap))
-               return 1;
-
-       /* thaw frozen port, resume link and recover failed devices */
-       if ((ap->pflags & ATA_PFLAG_FROZEN) ||
-           (ehc->i.flags & ATA_EHI_RESUME_LINK) || ata_port_nr_enabled(ap))
-               return 0;
-
-       /* skip if class codes for all vacant slots are ATA_DEV_NONE */
-       for (i = 0; i < ATA_MAX_DEVICES; i++) {
-               struct ata_device *dev = &ap->device[i];
-
-               if (dev->class == ATA_DEV_UNKNOWN &&
-                   ehc->classes[dev->devno] != ATA_DEV_NONE)
-                       return 0;
-       }
-
-       return 1;
-}
-
-/**
- *     ata_eh_recover - recover host port after error
- *     @ap: host port to recover
- *     @prereset: prereset method (can be NULL)
- *     @softreset: softreset method (can be NULL)
- *     @hardreset: hardreset method (can be NULL)
- *     @postreset: postreset method (can be NULL)
- *
- *     This is the alpha and omega, eum and yang, heart and soul of
- *     libata exception handling.  On entry, actions required to
- *     recover the port and hotplug requests are recorded in
- *     eh_context.  This function executes all the operations with
- *     appropriate retrials and fallbacks to resurrect failed
- *     devices, detach goners and greet newcomers.
- *
- *     LOCKING:
- *     Kernel thread context (may sleep).
- *
- *     RETURNS:
- *     0 on success, -errno on failure.
- */
-static int ata_eh_recover(struct ata_port *ap, ata_prereset_fn_t prereset,
-                         ata_reset_fn_t softreset, ata_reset_fn_t hardreset,
-                         ata_postreset_fn_t postreset)
-{
-       struct ata_eh_context *ehc = &ap->eh_context;
-       struct ata_device *dev;
-       int down_xfermask, i, rc;
-
-       DPRINTK("ENTER\n");
-
-       /* prep for recovery */
-       for (i = 0; i < ATA_MAX_DEVICES; i++) {
-               dev = &ap->device[i];
-
-               ehc->tries[dev->devno] = ATA_EH_DEV_TRIES;
-
-               /* process hotplug request */
-               if (dev->flags & ATA_DFLAG_DETACH)
-                       ata_eh_detach_dev(dev);
-
-               if (!ata_dev_enabled(dev) &&
-                   ((ehc->i.probe_mask & (1 << dev->devno)) &&
-                    !(ehc->did_probe_mask & (1 << dev->devno)))) {
-                       ata_eh_detach_dev(dev);
-                       ata_dev_init(dev);
-                       ehc->did_probe_mask |= (1 << dev->devno);
-                       ehc->i.action |= ATA_EH_SOFTRESET;
-               }
-       }
-
- retry:
-       down_xfermask = 0;
-       rc = 0;
-
-       /* if UNLOADING, finish immediately */
-       if (ap->pflags & ATA_PFLAG_UNLOADING)
-               goto out;
-
-       /* prep for resume */
-       ata_eh_prep_resume(ap);
-
-       /* skip EH if possible. */
-       if (ata_eh_skip_recovery(ap))
-               ehc->i.action = 0;
-
-       for (i = 0; i < ATA_MAX_DEVICES; i++)
-               ehc->classes[i] = ATA_DEV_UNKNOWN;
-
-       /* reset */
-       if (ehc->i.action & ATA_EH_RESET_MASK) {
-               ata_eh_freeze_port(ap);
-
-               rc = ata_eh_reset(ap, ata_port_nr_vacant(ap), prereset,
-                                 softreset, hardreset, postreset);
-               if (rc) {
-                       ata_port_printk(ap, KERN_ERR,
-                                       "reset failed, giving up\n");
-                       goto out;
-               }
-
-               ata_eh_thaw_port(ap);
-       }
-
-       /* revalidate existing devices and attach new ones */
-       rc = ata_eh_revalidate_and_attach(ap, &dev);
-       if (rc)
-               goto dev_fail;
-
-       /* resume devices */
-       rc = ata_eh_resume(ap, &dev);
-       if (rc)
-               goto dev_fail;
-
-       /* configure transfer mode if the port has been reset */
-       if (ehc->i.flags & ATA_EHI_DID_RESET) {
-               rc = ata_set_mode(ap, &dev);
-               if (rc) {
-                       down_xfermask = 1;
-                       goto dev_fail;
-               }
-       }
-
-       /* suspend devices */
-       rc = ata_eh_suspend(ap, &dev);
-       if (rc)
-               goto dev_fail;
-
-       goto out;
-
- dev_fail:
-       switch (rc) {
-       case -ENODEV:
-               /* device missing, schedule probing */
-               ehc->i.probe_mask |= (1 << dev->devno);
-       case -EINVAL:
-               ehc->tries[dev->devno] = 0;
-               break;
-       case -EIO:
-               sata_down_spd_limit(ap);
-       default:
-               ehc->tries[dev->devno]--;
-               if (down_xfermask &&
-                   ata_down_xfermask_limit(dev, ehc->tries[dev->devno] == 1))
-                       ehc->tries[dev->devno] = 0;
-       }
-
-       if (ata_dev_enabled(dev) && !ehc->tries[dev->devno]) {
-               /* disable device if it has used up all its chances */
-               ata_dev_disable(dev);
-
-               /* detach if offline */
-               if (ata_port_offline(ap))
-                       ata_eh_detach_dev(dev);
-
-               /* probe if requested */
-               if ((ehc->i.probe_mask & (1 << dev->devno)) &&
-                   !(ehc->did_probe_mask & (1 << dev->devno))) {
-                       ata_eh_detach_dev(dev);
-                       ata_dev_init(dev);
-
-                       ehc->tries[dev->devno] = ATA_EH_DEV_TRIES;
-                       ehc->did_probe_mask |= (1 << dev->devno);
-                       ehc->i.action |= ATA_EH_SOFTRESET;
-               }
-       } else {
-               /* soft didn't work?  be haaaaard */
-               if (ehc->i.flags & ATA_EHI_DID_RESET)
-                       ehc->i.action |= ATA_EH_HARDRESET;
-               else
-                       ehc->i.action |= ATA_EH_SOFTRESET;
-       }
-
-       if (ata_port_nr_enabled(ap)) {
-               ata_port_printk(ap, KERN_WARNING, "failed to recover some "
-                               "devices, retrying in 5 secs\n");
-               ssleep(5);
-       } else {
-               /* no device left, repeat fast */
-               msleep(500);
-       }
-
-       goto retry;
-
- out:
-       if (rc) {
-               for (i = 0; i < ATA_MAX_DEVICES; i++)
-                       ata_dev_disable(&ap->device[i]);
-       }
-
-       DPRINTK("EXIT, rc=%d\n", rc);
-       return rc;
-}
-
-/**
- *     ata_eh_finish - finish up EH
- *     @ap: host port to finish EH for
- *
- *     Recovery is complete.  Clean up EH states and retry or finish
- *     failed qcs.
- *
- *     LOCKING:
- *     None.
- */
-static void ata_eh_finish(struct ata_port *ap)
-{
-       int tag;
-
-       /* retry or finish qcs */
-       for (tag = 0; tag < ATA_MAX_QUEUE; tag++) {
-               struct ata_queued_cmd *qc = __ata_qc_from_tag(ap, tag);
-
-               if (!(qc->flags & ATA_QCFLAG_FAILED))
-                       continue;
-
-               if (qc->err_mask) {
-                       /* FIXME: Once EH migration is complete,
-                        * generate sense data in this function,
-                        * considering both err_mask and tf.
-                        */
-                       if (qc->err_mask & AC_ERR_INVALID)
-                               ata_eh_qc_complete(qc);
-                       else
-                               ata_eh_qc_retry(qc);
-               } else {
-                       if (qc->flags & ATA_QCFLAG_SENSE_VALID) {
-                               ata_eh_qc_complete(qc);
-                       } else {
-                               /* feed zero TF to sense generation */
-                               memset(&qc->result_tf, 0, sizeof(qc->result_tf));
-                               ata_eh_qc_retry(qc);
-                       }
-               }
-       }
-}
-
-/**
- *     ata_do_eh - do standard error handling
- *     @ap: host port to handle error for
- *     @prereset: prereset method (can be NULL)
- *     @softreset: softreset method (can be NULL)
- *     @hardreset: hardreset method (can be NULL)
- *     @postreset: postreset method (can be NULL)
- *
- *     Perform standard error handling sequence.
- *
- *     LOCKING:
- *     Kernel thread context (may sleep).
- */
-void ata_do_eh(struct ata_port *ap, ata_prereset_fn_t prereset,
-              ata_reset_fn_t softreset, ata_reset_fn_t hardreset,
-              ata_postreset_fn_t postreset)
-{
-       ata_eh_autopsy(ap);
-       ata_eh_report(ap);
-       ata_eh_recover(ap, prereset, softreset, hardreset, postreset);
-       ata_eh_finish(ap);
-}
-
-/**
- *     ata_eh_handle_port_suspend - perform port suspend operation
- *     @ap: port to suspend
- *
- *     Suspend @ap.
- *
- *     LOCKING:
- *     Kernel thread context (may sleep).
- */
-static void ata_eh_handle_port_suspend(struct ata_port *ap)
-{
-       unsigned long flags;
-       int rc = 0;
-
-       /* are we suspending? */
-       spin_lock_irqsave(ap->lock, flags);
-       if (!(ap->pflags & ATA_PFLAG_PM_PENDING) ||
-           ap->pm_mesg.event == PM_EVENT_ON) {
-               spin_unlock_irqrestore(ap->lock, flags);
-               return;
-       }
-       spin_unlock_irqrestore(ap->lock, flags);
-
-       WARN_ON(ap->pflags & ATA_PFLAG_SUSPENDED);
-
-       /* suspend */
-       ata_eh_freeze_port(ap);
-
-       if (ap->ops->port_suspend)
-               rc = ap->ops->port_suspend(ap, ap->pm_mesg);
-
-       /* report result */
-       spin_lock_irqsave(ap->lock, flags);
-
-       ap->pflags &= ~ATA_PFLAG_PM_PENDING;
-       if (rc == 0)
-               ap->pflags |= ATA_PFLAG_SUSPENDED;
-       else
-               ata_port_schedule_eh(ap);
-
-       if (ap->pm_result) {
-               *ap->pm_result = rc;
-               ap->pm_result = NULL;
-       }
-
-       spin_unlock_irqrestore(ap->lock, flags);
-
-       return;
-}
-
-/**
- *     ata_eh_handle_port_resume - perform port resume operation
- *     @ap: port to resume
- *
- *     Resume @ap.
- *
- *     This function also waits upto one second until all devices
- *     hanging off this port requests resume EH action.  This is to
- *     prevent invoking EH and thus reset multiple times on resume.
- *
- *     On DPM resume, where some of devices might not be resumed
- *     together, this may delay port resume upto one second, but such
- *     DPM resumes are rare and 1 sec delay isn't too bad.
- *
- *     LOCKING:
- *     Kernel thread context (may sleep).
- */
-static void ata_eh_handle_port_resume(struct ata_port *ap)
-{
-       unsigned long timeout;
-       unsigned long flags;
-       int i, rc = 0;
-
-       /* are we resuming? */
-       spin_lock_irqsave(ap->lock, flags);
-       if (!(ap->pflags & ATA_PFLAG_PM_PENDING) ||
-           ap->pm_mesg.event != PM_EVENT_ON) {
-               spin_unlock_irqrestore(ap->lock, flags);
-               return;
-       }
-       spin_unlock_irqrestore(ap->lock, flags);
-
-       /* spurious? */
-       if (!(ap->pflags & ATA_PFLAG_SUSPENDED))
-               goto done;
-
-       if (ap->ops->port_resume)
-               rc = ap->ops->port_resume(ap);
-
-       /* give devices time to request EH */
-       timeout = jiffies + HZ; /* 1s max */
-       while (1) {
-               for (i = 0; i < ATA_MAX_DEVICES; i++) {
-                       struct ata_device *dev = &ap->device[i];
-                       unsigned int action = ata_eh_dev_action(dev);
-
-                       if ((dev->flags & ATA_DFLAG_SUSPENDED) &&
-                           !(action & ATA_EH_RESUME))
-                               break;
-               }
-
-               if (i == ATA_MAX_DEVICES || time_after(jiffies, timeout))
-                       break;
-               msleep(10);
-       }
-
- done:
-       spin_lock_irqsave(ap->lock, flags);
-       ap->pflags &= ~(ATA_PFLAG_PM_PENDING | ATA_PFLAG_SUSPENDED);
-       if (ap->pm_result) {
-               *ap->pm_result = rc;
-               ap->pm_result = NULL;
-       }
-       spin_unlock_irqrestore(ap->lock, flags);
-}
diff --git a/drivers/scsi/libata-scsi.c b/drivers/scsi/libata-scsi.c
deleted file mode 100644 (file)
index d168e34..0000000
+++ /dev/null
@@ -1,3322 +0,0 @@
-/*
- *  libata-scsi.c - helper library for ATA
- *
- *  Maintained by:  Jeff Garzik <jgarzik@pobox.com>
- *                 Please ALWAYS copy linux-ide@vger.kernel.org
- *                 on emails.
- *
- *  Copyright 2003-2004 Red Hat, Inc.  All rights reserved.
- *  Copyright 2003-2004 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.t10.org/
- *  - http://www.t13.org/
- *
- */
-
-#include <linux/kernel.h>
-#include <linux/blkdev.h>
-#include <linux/spinlock.h>
-#include <scsi/scsi.h>
-#include <scsi/scsi_host.h>
-#include <scsi/scsi_cmnd.h>
-#include <scsi/scsi_eh.h>
-#include <scsi/scsi_device.h>
-#include <scsi/scsi_tcq.h>
-#include <scsi/scsi_transport.h>
-#include <linux/libata.h>
-#include <linux/hdreg.h>
-#include <asm/uaccess.h>
-
-#include "libata.h"
-
-#define SECTOR_SIZE    512
-
-typedef unsigned int (*ata_xlat_func_t)(struct ata_queued_cmd *qc, const u8 *scsicmd);
-
-static struct ata_device * __ata_scsi_find_dev(struct ata_port *ap,
-                                       const struct scsi_device *scsidev);
-static struct ata_device * ata_scsi_find_dev(struct ata_port *ap,
-                                           const struct scsi_device *scsidev);
-static int ata_scsi_user_scan(struct Scsi_Host *shost, unsigned int channel,
-                             unsigned int id, unsigned int lun);
-
-
-#define RW_RECOVERY_MPAGE 0x1
-#define RW_RECOVERY_MPAGE_LEN 12
-#define CACHE_MPAGE 0x8
-#define CACHE_MPAGE_LEN 20
-#define CONTROL_MPAGE 0xa
-#define CONTROL_MPAGE_LEN 12
-#define ALL_MPAGES 0x3f
-#define ALL_SUB_MPAGES 0xff
-
-
-static const u8 def_rw_recovery_mpage[] = {
-       RW_RECOVERY_MPAGE,
-       RW_RECOVERY_MPAGE_LEN - 2,
-       (1 << 7) |      /* AWRE, sat-r06 say it shall be 0 */
-           (1 << 6),   /* ARRE (auto read reallocation) */
-       0,              /* read retry count */
-       0, 0, 0, 0,
-       0,              /* write retry count */
-       0, 0, 0
-};
-
-static const u8 def_cache_mpage[CACHE_MPAGE_LEN] = {
-       CACHE_MPAGE,
-       CACHE_MPAGE_LEN - 2,
-       0,              /* contains WCE, needs to be 0 for logic */
-       0, 0, 0, 0, 0, 0, 0, 0, 0,
-       0,              /* contains DRA, needs to be 0 for logic */
-       0, 0, 0, 0, 0, 0, 0
-};
-
-static const u8 def_control_mpage[CONTROL_MPAGE_LEN] = {
-       CONTROL_MPAGE,
-       CONTROL_MPAGE_LEN - 2,
-       2,      /* DSENSE=0, GLTSD=1 */
-       0,      /* [QAM+QERR may be 1, see 05-359r1] */
-       0, 0, 0, 0, 0xff, 0xff,
-       0, 30   /* extended self test time, see 05-359r1 */
-};
-
-/*
- * libata transport template.  libata doesn't do real transport stuff.
- * It just needs the eh_timed_out hook.
- */
-struct scsi_transport_template ata_scsi_transport_template = {
-       .eh_strategy_handler    = ata_scsi_error,
-       .eh_timed_out           = ata_scsi_timed_out,
-       .user_scan              = ata_scsi_user_scan,
-};
-
-
-static void ata_scsi_invalid_field(struct scsi_cmnd *cmd,
-                                  void (*done)(struct scsi_cmnd *))
-{
-       ata_scsi_set_sense(cmd, ILLEGAL_REQUEST, 0x24, 0x0);
-       /* "Invalid field in cbd" */
-       done(cmd);
-}
-
-/**
- *     ata_std_bios_param - generic bios head/sector/cylinder calculator used by sd.
- *     @sdev: SCSI device for which BIOS geometry is to be determined
- *     @bdev: block device associated with @sdev
- *     @capacity: capacity of SCSI device
- *     @geom: location to which geometry will be output
- *
- *     Generic bios head/sector/cylinder calculator
- *     used by sd. Most BIOSes nowadays expect a XXX/255/16  (CHS)
- *     mapping. Some situations may arise where the disk is not
- *     bootable if this is not used.
- *
- *     LOCKING:
- *     Defined by the SCSI layer.  We don't really care.
- *
- *     RETURNS:
- *     Zero.
- */
-int ata_std_bios_param(struct scsi_device *sdev, struct block_device *bdev,
-                      sector_t capacity, int geom[])
-{
-       geom[0] = 255;
-       geom[1] = 63;
-       sector_div(capacity, 255*63);
-       geom[2] = capacity;
-
-       return 0;
-}
-
-/**
- *     ata_cmd_ioctl - Handler for HDIO_DRIVE_CMD ioctl
- *     @scsidev: Device to which we are issuing command
- *     @arg: User provided data for issuing command
- *
- *     LOCKING:
- *     Defined by the SCSI layer.  We don't really care.
- *
- *     RETURNS:
- *     Zero on success, negative errno on error.
- */
-
-int ata_cmd_ioctl(struct scsi_device *scsidev, void __user *arg)
-{
-       int rc = 0;
-       u8 scsi_cmd[MAX_COMMAND_SIZE];
-       u8 args[4], *argbuf = NULL;
-       int argsize = 0;
-       struct scsi_sense_hdr sshdr;
-       enum dma_data_direction data_dir;
-
-       if (arg == NULL)
-               return -EINVAL;
-
-       if (copy_from_user(args, arg, sizeof(args)))
-               return -EFAULT;
-
-       memset(scsi_cmd, 0, sizeof(scsi_cmd));
-
-       if (args[3]) {
-               argsize = SECTOR_SIZE * args[3];
-               argbuf = kmalloc(argsize, GFP_KERNEL);
-               if (argbuf == NULL) {
-                       rc = -ENOMEM;
-                       goto error;
-               }
-
-               scsi_cmd[1]  = (4 << 1); /* PIO Data-in */
-               scsi_cmd[2]  = 0x0e;     /* no off.line or cc, read from dev,
-                                           block count in sector count field */
-               data_dir = DMA_FROM_DEVICE;
-       } else {
-               scsi_cmd[1]  = (3 << 1); /* Non-data */
-               /* scsi_cmd[2] is already 0 -- no off.line, cc, or data xfer */
-               data_dir = DMA_NONE;
-       }
-
-       scsi_cmd[0] = ATA_16;
-
-       scsi_cmd[4] = args[2];
-       if (args[0] == WIN_SMART) { /* hack -- ide driver does this too... */
-               scsi_cmd[6]  = args[3];
-               scsi_cmd[8]  = args[1];
-               scsi_cmd[10] = 0x4f;
-               scsi_cmd[12] = 0xc2;
-       } else {
-               scsi_cmd[6]  = args[1];
-       }
-       scsi_cmd[14] = args[0];
-
-       /* Good values for timeout and retries?  Values below
-          from scsi_ioctl_send_command() for default case... */
-       if (scsi_execute_req(scsidev, scsi_cmd, data_dir, argbuf, argsize,
-                            &sshdr, (10*HZ), 5)) {
-               rc = -EIO;
-               goto error;
-       }
-
-       /* Need code to retrieve data from check condition? */
-
-       if ((argbuf)
-        && copy_to_user(arg + sizeof(args), argbuf, argsize))
-               rc = -EFAULT;
-error:
-       kfree(argbuf);
-       return rc;
-}
-
-/**
- *     ata_task_ioctl - Handler for HDIO_DRIVE_TASK ioctl
- *     @scsidev: Device to which we are issuing command
- *     @arg: User provided data for issuing command
- *
- *     LOCKING:
- *     Defined by the SCSI layer.  We don't really care.
- *
- *     RETURNS:
- *     Zero on success, negative errno on error.
- */
-int ata_task_ioctl(struct scsi_device *scsidev, void __user *arg)
-{
-       int rc = 0;
-       u8 scsi_cmd[MAX_COMMAND_SIZE];
-       u8 args[7];
-       struct scsi_sense_hdr sshdr;
-
-       if (arg == NULL)
-               return -EINVAL;
-
-       if (copy_from_user(args, arg, sizeof(args)))
-               return -EFAULT;
-
-       memset(scsi_cmd, 0, sizeof(scsi_cmd));
-       scsi_cmd[0]  = ATA_16;
-       scsi_cmd[1]  = (3 << 1); /* Non-data */
-       /* scsi_cmd[2] is already 0 -- no off.line, cc, or data xfer */
-       scsi_cmd[4]  = args[1];
-       scsi_cmd[6]  = args[2];
-       scsi_cmd[8]  = args[3];
-       scsi_cmd[10] = args[4];
-       scsi_cmd[12] = args[5];
-       scsi_cmd[14] = args[0];
-
-       /* Good values for timeout and retries?  Values below
-          from scsi_ioctl_send_command() for default case... */
-       if (scsi_execute_req(scsidev, scsi_cmd, DMA_NONE, NULL, 0, &sshdr,
-                            (10*HZ), 5))
-               rc = -EIO;
-
-       /* Need code to retrieve data from check condition? */
-       return rc;
-}
-
-int ata_scsi_ioctl(struct scsi_device *scsidev, int cmd, void __user *arg)
-{
-       int val = -EINVAL, rc = -EINVAL;
-
-       switch (cmd) {
-       case ATA_IOC_GET_IO32:
-               val = 0;
-               if (copy_to_user(arg, &val, 1))
-                       return -EFAULT;
-               return 0;
-
-       case ATA_IOC_SET_IO32:
-               val = (unsigned long) arg;
-               if (val != 0)
-                       return -EINVAL;
-               return 0;
-
-       case HDIO_DRIVE_CMD:
-               if (!capable(CAP_SYS_ADMIN) || !capable(CAP_SYS_RAWIO))
-                       return -EACCES;
-               return ata_cmd_ioctl(scsidev, arg);
-
-       case HDIO_DRIVE_TASK:
-               if (!capable(CAP_SYS_ADMIN) || !capable(CAP_SYS_RAWIO))
-                       return -EACCES;
-               return ata_task_ioctl(scsidev, arg);
-
-       default:
-               rc = -ENOTTY;
-               break;
-       }
-
-       return rc;
-}
-
-/**
- *     ata_scsi_qc_new - acquire new ata_queued_cmd reference
- *     @dev: ATA device to which the new command is attached
- *     @cmd: SCSI command that originated this ATA command
- *     @done: SCSI command completion function
- *
- *     Obtain a reference to an unused ata_queued_cmd structure,
- *     which is the basic libata structure representing a single
- *     ATA command sent to the hardware.
- *
- *     If a command was available, fill in the SCSI-specific
- *     portions of the structure with information on the
- *     current command.
- *
- *     LOCKING:
- *     spin_lock_irqsave(host_set lock)
- *
- *     RETURNS:
- *     Command allocated, or %NULL if none available.
- */
-struct ata_queued_cmd *ata_scsi_qc_new(struct ata_device *dev,
-                                      struct scsi_cmnd *cmd,
-                                      void (*done)(struct scsi_cmnd *))
-{
-       struct ata_queued_cmd *qc;
-
-       qc = ata_qc_new_init(dev);
-       if (qc) {
-               qc->scsicmd = cmd;
-               qc->scsidone = done;
-
-               if (cmd->use_sg) {
-                       qc->__sg = (struct scatterlist *) cmd->request_buffer;
-                       qc->n_elem = cmd->use_sg;
-               } else {
-                       qc->__sg = &qc->sgent;
-                       qc->n_elem = 1;
-               }
-       } else {
-               cmd->result = (DID_OK << 16) | (QUEUE_FULL << 1);
-               done(cmd);
-       }
-
-       return qc;
-}
-
-/**
- *     ata_dump_status - user friendly display of error info
- *     @id: id of the port in question
- *     @tf: ptr to filled out taskfile
- *
- *     Decode and dump the ATA error/status registers for the user so
- *     that they have some idea what really happened at the non
- *     make-believe layer.
- *
- *     LOCKING:
- *     inherited from caller
- */
-void ata_dump_status(unsigned id, struct ata_taskfile *tf)
-{
-       u8 stat = tf->command, err = tf->feature;
-
-       printk(KERN_WARNING "ata%u: status=0x%02x { ", id, stat);
-       if (stat & ATA_BUSY) {
-               printk("Busy }\n");     /* Data is not valid in this case */
-       } else {
-               if (stat & 0x40)        printk("DriveReady ");
-               if (stat & 0x20)        printk("DeviceFault ");
-               if (stat & 0x10)        printk("SeekComplete ");
-               if (stat & 0x08)        printk("DataRequest ");
-               if (stat & 0x04)        printk("CorrectedError ");
-               if (stat & 0x02)        printk("Index ");
-               if (stat & 0x01)        printk("Error ");
-               printk("}\n");
-
-               if (err) {
-                       printk(KERN_WARNING "ata%u: error=0x%02x { ", id, err);
-                       if (err & 0x04)         printk("DriveStatusError ");
-                       if (err & 0x80) {
-                               if (err & 0x04) printk("BadCRC ");
-                               else            printk("Sector ");
-                       }
-                       if (err & 0x40)         printk("UncorrectableError ");
-                       if (err & 0x10)         printk("SectorIdNotFound ");
-                       if (err & 0x02)         printk("TrackZeroNotFound ");
-                       if (err & 0x01)         printk("AddrMarkNotFound ");
-                       printk("}\n");
-               }
-       }
-}
-
-/**
- *     ata_scsi_device_suspend - suspend ATA device associated with sdev
- *     @sdev: the SCSI device to suspend
- *     @mesg: target power management message
- *
- *     Request suspend EH action on the ATA device associated with
- *     @sdev and wait for the operation to complete.
- *
- *     LOCKING:
- *     Kernel thread context (may sleep).
- *
- *     RETURNS:
- *     0 on success, -errno otherwise.
- */
-int ata_scsi_device_suspend(struct scsi_device *sdev, pm_message_t mesg)
-{
-       struct ata_port *ap = ata_shost_to_port(sdev->host);
-       struct ata_device *dev = ata_scsi_find_dev(ap, sdev);
-       unsigned long flags;
-       unsigned int action;
-       int rc = 0;
-
-       if (!dev)
-               goto out;
-
-       spin_lock_irqsave(ap->lock, flags);
-
-       /* wait for the previous resume to complete */
-       while (dev->flags & ATA_DFLAG_SUSPENDED) {
-               spin_unlock_irqrestore(ap->lock, flags);
-               ata_port_wait_eh(ap);
-               spin_lock_irqsave(ap->lock, flags);
-       }
-
-       /* if @sdev is already detached, nothing to do */
-       if (sdev->sdev_state == SDEV_OFFLINE ||
-           sdev->sdev_state == SDEV_CANCEL || sdev->sdev_state == SDEV_DEL)
-               goto out_unlock;
-
-       /* request suspend */
-       action = ATA_EH_SUSPEND;
-       if (mesg.event != PM_EVENT_SUSPEND)
-               action |= ATA_EH_PM_FREEZE;
-       ap->eh_info.dev_action[dev->devno] |= action;
-       ap->eh_info.flags |= ATA_EHI_QUIET;
-       ata_port_schedule_eh(ap);
-
-       spin_unlock_irqrestore(ap->lock, flags);
-
-       /* wait for EH to do the job */
-       ata_port_wait_eh(ap);
-
-       spin_lock_irqsave(ap->lock, flags);
-
-       /* If @sdev is still attached but the associated ATA device
-        * isn't suspended, the operation failed.
-        */
-       if (sdev->sdev_state != SDEV_OFFLINE &&
-           sdev->sdev_state != SDEV_CANCEL && sdev->sdev_state != SDEV_DEL &&
-           !(dev->flags & ATA_DFLAG_SUSPENDED))
-               rc = -EIO;
-
- out_unlock:
-       spin_unlock_irqrestore(ap->lock, flags);
- out:
-       if (rc == 0)
-               sdev->sdev_gendev.power.power_state = mesg;
-       return rc;
-}
-
-/**
- *     ata_scsi_device_resume - resume ATA device associated with sdev
- *     @sdev: the SCSI device to resume
- *
- *     Request resume EH action on the ATA device associated with
- *     @sdev and return immediately.  This enables parallel
- *     wakeup/spinup of devices.
- *
- *     LOCKING:
- *     Kernel thread context (may sleep).
- *
- *     RETURNS:
- *     0.
- */
-int ata_scsi_device_resume(struct scsi_device *sdev)
-{
-       struct ata_port *ap = ata_shost_to_port(sdev->host);
-       struct ata_device *dev = ata_scsi_find_dev(ap, sdev);
-       struct ata_eh_info *ehi = &ap->eh_info;
-       unsigned long flags;
-       unsigned int action;
-
-       if (!dev)
-               goto out;
-
-       spin_lock_irqsave(ap->lock, flags);
-
-       /* if @sdev is already detached, nothing to do */
-       if (sdev->sdev_state == SDEV_OFFLINE ||
-           sdev->sdev_state == SDEV_CANCEL || sdev->sdev_state == SDEV_DEL)
-               goto out_unlock;
-
-       /* request resume */
-       action = ATA_EH_RESUME;
-       if (sdev->sdev_gendev.power.power_state.event == PM_EVENT_SUSPEND)
-               __ata_ehi_hotplugged(ehi);
-       else
-               action |= ATA_EH_PM_FREEZE | ATA_EH_SOFTRESET;
-       ehi->dev_action[dev->devno] |= action;
-
-       /* We don't want autopsy and verbose EH messages.  Disable
-        * those if we're the only device on this link.
-        */
-       if (ata_port_max_devices(ap) == 1)
-               ehi->flags |= ATA_EHI_NO_AUTOPSY | ATA_EHI_QUIET;
-
-       ata_port_schedule_eh(ap);
-
- out_unlock:
-       spin_unlock_irqrestore(ap->lock, flags);
- out:
-       sdev->sdev_gendev.power.power_state = PMSG_ON;
-       return 0;
-}
-
-/**
- *     ata_to_sense_error - convert ATA error to SCSI error
- *     @id: ATA device number
- *     @drv_stat: value contained in ATA status register
- *     @drv_err: value contained in ATA error register
- *     @sk: the sense key we'll fill out
- *     @asc: the additional sense code we'll fill out
- *     @ascq: the additional sense code qualifier we'll fill out
- *     @verbose: be verbose
- *
- *     Converts an ATA error into a SCSI error.  Fill out pointers to
- *     SK, ASC, and ASCQ bytes for later use in fixed or descriptor
- *     format sense blocks.
- *
- *     LOCKING:
- *     spin_lock_irqsave(host_set lock)
- */
-void ata_to_sense_error(unsigned id, u8 drv_stat, u8 drv_err, u8 *sk, u8 *asc,
-                       u8 *ascq, int verbose)
-{
-       int i;
-
-       /* Based on the 3ware driver translation table */
-       static const unsigned char sense_table[][4] = {
-               /* BBD|ECC|ID|MAR */
-               {0xd1,          ABORTED_COMMAND, 0x00, 0x00},   // Device busy                  Aborted command
-               /* BBD|ECC|ID */
-               {0xd0,          ABORTED_COMMAND, 0x00, 0x00},   // Device busy                  Aborted command
-               /* ECC|MC|MARK */
-               {0x61,          HARDWARE_ERROR, 0x00, 0x00},    // Device fault                 Hardware error
-               /* ICRC|ABRT */         /* NB: ICRC & !ABRT is BBD */
-               {0x84,          ABORTED_COMMAND, 0x47, 0x00},   // Data CRC error               SCSI parity error
-               /* MC|ID|ABRT|TRK0|MARK */
-               {0x37,          NOT_READY, 0x04, 0x00},         // Unit offline                 Not ready
-               /* MCR|MARK */
-               {0x09,          NOT_READY, 0x04, 0x00},         // Unrecovered disk error       Not ready
-               /*  Bad address mark */
-               {0x01,          MEDIUM_ERROR, 0x13, 0x00},      // Address mark not found       Address mark not found for data field
-               /* TRK0 */
-               {0x02,          HARDWARE_ERROR, 0x00, 0x00},    // Track 0 not found              Hardware error
-               /* Abort & !ICRC */
-               {0x04,          ABORTED_COMMAND, 0x00, 0x00},   // Aborted command              Aborted command
-               /* Media change request */
-               {0x08,          NOT_READY, 0x04, 0x00},         // Media change request   FIXME: faking offline
-               /* SRV */
-               {0x10,          ABORTED_COMMAND, 0x14, 0x00},   // ID not found                 Recorded entity not found
-               /* Media change */
-               {0x08,          NOT_READY, 0x04, 0x00},         // Media change           FIXME: faking offline
-               /* ECC */
-               {0x40,          MEDIUM_ERROR, 0x11, 0x04},      // Uncorrectable ECC error      Unrecovered read error
-               /* BBD - block marked bad */
-               {0x80,          MEDIUM_ERROR, 0x11, 0x04},      // Block marked bad               Medium error, unrecovered read error
-               {0xFF, 0xFF, 0xFF, 0xFF}, // END mark
-       };
-       static const unsigned char stat_table[][4] = {
-               /* Must be first because BUSY means no other bits valid */
-               {0x80,          ABORTED_COMMAND, 0x47, 0x00},   // Busy, fake parity for now
-               {0x20,          HARDWARE_ERROR,  0x00, 0x00},   // Device fault
-               {0x08,          ABORTED_COMMAND, 0x47, 0x00},   // Timed out in xfer, fake parity for now
-               {0x04,          RECOVERED_ERROR, 0x11, 0x00},   // Recovered ECC error    Medium error, recovered
-               {0xFF, 0xFF, 0xFF, 0xFF}, // END mark
-       };
-
-       /*
-        *      Is this an error we can process/parse
-        */
-       if (drv_stat & ATA_BUSY) {
-               drv_err = 0;    /* Ignore the err bits, they're invalid */
-       }
-
-       if (drv_err) {
-               /* Look for drv_err */
-               for (i = 0; sense_table[i][0] != 0xFF; i++) {
-                       /* Look for best matches first */
-                       if ((sense_table[i][0] & drv_err) ==
-                           sense_table[i][0]) {
-                               *sk = sense_table[i][1];
-                               *asc = sense_table[i][2];
-                               *ascq = sense_table[i][3];
-                               goto translate_done;
-                       }
-               }
-               /* No immediate match */
-               if (verbose)
-                       printk(KERN_WARNING "ata%u: no sense translation for "
-                              "error 0x%02x\n", id, drv_err);
-       }
-
-       /* Fall back to interpreting status bits */
-       for (i = 0; stat_table[i][0] != 0xFF; i++) {
-               if (stat_table[i][0] & drv_stat) {
-                       *sk = stat_table[i][1];
-                       *asc = stat_table[i][2];
-                       *ascq = stat_table[i][3];
-                       goto translate_done;
-               }
-       }
-       /* No error?  Undecoded? */
-       if (verbose)
-               printk(KERN_WARNING "ata%u: no sense translation for "
-                      "status: 0x%02x\n", id, drv_stat);
-
-       /* We need a sensible error return here, which is tricky, and one
-          that won't cause people to do things like return a disk wrongly */
-       *sk = ABORTED_COMMAND;
-       *asc = 0x00;
-       *ascq = 0x00;
-
- translate_done:
-       if (verbose)
-               printk(KERN_ERR "ata%u: translated ATA stat/err 0x%02x/%02x "
-                      "to SCSI SK/ASC/ASCQ 0x%x/%02x/%02x\n",
-                      id, drv_stat, drv_err, *sk, *asc, *ascq);
-       return;
-}
-
-/*
- *     ata_gen_ata_desc_sense - Generate check condition sense block.
- *     @qc: Command that completed.
- *
- *     This function is specific to the ATA descriptor format sense
- *     block specified for the ATA pass through commands.  Regardless
- *     of whether the command errored or not, return a sense
- *     block. Copy all controller registers into the sense
- *     block. Clear sense key, ASC & ASCQ if there is no error.
- *
- *     LOCKING:
- *     spin_lock_irqsave(host_set lock)
- */
-void ata_gen_ata_desc_sense(struct ata_queued_cmd *qc)
-{
-       struct scsi_cmnd *cmd = qc->scsicmd;
-       struct ata_taskfile *tf = &qc->result_tf;
-       unsigned char *sb = cmd->sense_buffer;
-       unsigned char *desc = sb + 8;
-       int verbose = qc->ap->ops->error_handler == NULL;
-
-       memset(sb, 0, SCSI_SENSE_BUFFERSIZE);
-
-       cmd->result = (DRIVER_SENSE << 24) | SAM_STAT_CHECK_CONDITION;
-
-       /*
-        * Use ata_to_sense_error() to map status register bits
-        * onto sense key, asc & ascq.
-        */
-       if (qc->err_mask ||
-           tf->command & (ATA_BUSY | ATA_DF | ATA_ERR | ATA_DRQ)) {
-               ata_to_sense_error(qc->ap->id, tf->command, tf->feature,
-                                  &sb[1], &sb[2], &sb[3], verbose);
-               sb[1] &= 0x0f;
-       }
-
-       /*
-        * Sense data is current and format is descriptor.
-        */
-       sb[0] = 0x72;
-
-       desc[0] = 0x09;
-
-       /*
-        * Set length of additional sense data.
-        * Since we only populate descriptor 0, the total
-        * length is the same (fixed) length as descriptor 0.
-        */
-       desc[1] = sb[7] = 14;
-
-       /*
-        * Copy registers into sense buffer.
-        */
-       desc[2] = 0x00;
-       desc[3] = tf->feature;  /* == error reg */
-       desc[5] = tf->nsect;
-       desc[7] = tf->lbal;
-       desc[9] = tf->lbam;
-       desc[11] = tf->lbah;
-       desc[12] = tf->device;
-       desc[13] = tf->command; /* == status reg */
-
-       /*
-        * Fill in Extend bit, and the high order bytes
-        * if applicable.
-        */
-       if (tf->flags & ATA_TFLAG_LBA48) {
-               desc[2] |= 0x01;
-               desc[4] = tf->hob_nsect;
-               desc[6] = tf->hob_lbal;
-               desc[8] = tf->hob_lbam;
-               desc[10] = tf->hob_lbah;
-       }
-}
-
-/**
- *     ata_gen_fixed_sense - generate a SCSI fixed sense block
- *     @qc: Command that we are erroring out
- *
- *     Leverage ata_to_sense_error() to give us the codes.  Fit our
- *     LBA in here if there's room.
- *
- *     LOCKING:
- *     inherited from caller
- */
-void ata_gen_fixed_sense(struct ata_queued_cmd *qc)
-{
-       struct scsi_cmnd *cmd = qc->scsicmd;
-       struct ata_taskfile *tf = &qc->result_tf;
-       unsigned char *sb = cmd->sense_buffer;
-       int verbose = qc->ap->ops->error_handler == NULL;
-
-       memset(sb, 0, SCSI_SENSE_BUFFERSIZE);
-
-       cmd->result = (DRIVER_SENSE << 24) | SAM_STAT_CHECK_CONDITION;
-
-       /*
-        * Use ata_to_sense_error() to map status register bits
-        * onto sense key, asc & ascq.
-        */
-       if (qc->err_mask ||
-           tf->command & (ATA_BUSY | ATA_DF | ATA_ERR | ATA_DRQ)) {
-               ata_to_sense_error(qc->ap->id, tf->command, tf->feature,
-                                  &sb[2], &sb[12], &sb[13], verbose);
-               sb[2] &= 0x0f;
-       }
-
-       sb[0] = 0x70;
-       sb[7] = 0x0a;
-
-       if (tf->flags & ATA_TFLAG_LBA48) {
-               /* TODO: find solution for LBA48 descriptors */
-       }
-
-       else if (tf->flags & ATA_TFLAG_LBA) {
-               /* A small (28b) LBA will fit in the 32b info field */
-               sb[0] |= 0x80;          /* set valid bit */
-               sb[3] = tf->device & 0x0f;
-               sb[4] = tf->lbah;
-               sb[5] = tf->lbam;
-               sb[6] = tf->lbal;
-       }
-
-       else {
-               /* TODO: C/H/S */
-       }
-}
-
-static void ata_scsi_sdev_config(struct scsi_device *sdev)
-{
-       sdev->use_10_for_rw = 1;
-       sdev->use_10_for_ms = 1;
-}
-
-static void ata_scsi_dev_config(struct scsi_device *sdev,
-                               struct ata_device *dev)
-{
-       unsigned int max_sectors;
-
-       /* 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.
-        */
-       max_sectors = ATA_MAX_SECTORS;
-       if (dev->flags & ATA_DFLAG_LBA48)
-               max_sectors = ATA_MAX_SECTORS_LBA48;
-       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
-        * we need to pad ATAPI transfers using an extra sg.
-        * Decrement max hw segments accordingly.
-        */
-       if (dev->class == ATA_DEV_ATAPI) {
-               request_queue_t *q = sdev->request_queue;
-               blk_queue_max_hw_segments(q, q->max_hw_segments - 1);
-       }
-
-       if (dev->flags & ATA_DFLAG_NCQ) {
-               int depth;
-
-               depth = min(sdev->host->can_queue, ata_id_queue_depth(dev->id));
-               depth = min(ATA_MAX_QUEUE - 1, depth);
-               scsi_adjust_queue_depth(sdev, MSG_SIMPLE_TAG, depth);
-       }
-}
-
-/**
- *     ata_scsi_slave_config - Set SCSI device attributes
- *     @sdev: SCSI device to examine
- *
- *     This is called before we actually start reading
- *     and writing to the device, to configure certain
- *     SCSI mid-layer behaviors.
- *
- *     LOCKING:
- *     Defined by SCSI layer.  We don't really care.
- */
-
-int ata_scsi_slave_config(struct scsi_device *sdev)
-{
-       struct ata_port *ap = ata_shost_to_port(sdev->host);
-       struct ata_device *dev = __ata_scsi_find_dev(ap, sdev);
-
-       ata_scsi_sdev_config(sdev);
-
-       blk_queue_max_phys_segments(sdev->request_queue, LIBATA_MAX_PRD);
-
-       if (dev)
-               ata_scsi_dev_config(sdev, dev);
-
-       return 0;       /* scsi layer doesn't check return value, sigh */
-}
-
-/**
- *     ata_scsi_slave_destroy - SCSI device is about to be destroyed
- *     @sdev: SCSI device to be destroyed
- *
- *     @sdev is about to be destroyed for hot/warm unplugging.  If
- *     this unplugging was initiated by libata as indicated by NULL
- *     dev->sdev, this function doesn't have to do anything.
- *     Otherwise, SCSI layer initiated warm-unplug is in progress.
- *     Clear dev->sdev, schedule the device for ATA detach and invoke
- *     EH.
- *
- *     LOCKING:
- *     Defined by SCSI layer.  We don't really care.
- */
-void ata_scsi_slave_destroy(struct scsi_device *sdev)
-{
-       struct ata_port *ap = ata_shost_to_port(sdev->host);
-       unsigned long flags;
-       struct ata_device *dev;
-
-       if (!ap->ops->error_handler)
-               return;
-
-       spin_lock_irqsave(ap->lock, flags);
-       dev = __ata_scsi_find_dev(ap, sdev);
-       if (dev && dev->sdev) {
-               /* SCSI device already in CANCEL state, no need to offline it */
-               dev->sdev = NULL;
-               dev->flags |= ATA_DFLAG_DETACH;
-               ata_port_schedule_eh(ap);
-       }
-       spin_unlock_irqrestore(ap->lock, flags);
-}
-
-/**
- *     ata_scsi_change_queue_depth - SCSI callback for queue depth config
- *     @sdev: SCSI device to configure queue depth for
- *     @queue_depth: new queue depth
- *
- *     This is libata standard hostt->change_queue_depth callback.
- *     SCSI will call into this callback when user tries to set queue
- *     depth via sysfs.
- *
- *     LOCKING:
- *     SCSI layer (we don't care)
- *
- *     RETURNS:
- *     Newly configured queue depth.
- */
-int ata_scsi_change_queue_depth(struct scsi_device *sdev, int queue_depth)
-{
-       struct ata_port *ap = ata_shost_to_port(sdev->host);
-       struct ata_device *dev;
-       int max_depth;
-
-       if (queue_depth < 1)
-               return sdev->queue_depth;
-
-       dev = ata_scsi_find_dev(ap, sdev);
-       if (!dev || !ata_dev_enabled(dev))
-               return sdev->queue_depth;
-
-       max_depth = min(sdev->host->can_queue, ata_id_queue_depth(dev->id));
-       max_depth = min(ATA_MAX_QUEUE - 1, max_depth);
-       if (queue_depth > max_depth)
-               queue_depth = max_depth;
-
-       scsi_adjust_queue_depth(sdev, MSG_SIMPLE_TAG, queue_depth);
-       return queue_depth;
-}
-
-/**
- *     ata_scsi_start_stop_xlat - Translate SCSI START STOP UNIT command
- *     @qc: Storage for translated ATA taskfile
- *     @scsicmd: SCSI command to translate
- *
- *     Sets up an ATA taskfile to issue STANDBY (to stop) or READ VERIFY
- *     (to start). Perhaps these commands should be preceded by
- *     CHECK POWER MODE to see what power mode the device is already in.
- *     [See SAT revision 5 at www.t10.org]
- *
- *     LOCKING:
- *     spin_lock_irqsave(host_set lock)
- *
- *     RETURNS:
- *     Zero on success, non-zero on error.
- */
-
-static unsigned int ata_scsi_start_stop_xlat(struct ata_queued_cmd *qc,
-                                            const u8 *scsicmd)
-{
-       struct ata_taskfile *tf = &qc->tf;
-
-       tf->flags |= ATA_TFLAG_DEVICE | ATA_TFLAG_ISADDR;
-       tf->protocol = ATA_PROT_NODATA;
-       if (scsicmd[1] & 0x1) {
-               ;       /* ignore IMMED bit, violates sat-r05 */
-       }
-       if (scsicmd[4] & 0x2)
-               goto invalid_fld;       /* LOEJ bit set not supported */
-       if (((scsicmd[4] >> 4) & 0xf) != 0)
-               goto invalid_fld;       /* power conditions not supported */
-       if (scsicmd[4] & 0x1) {
-               tf->nsect = 1;  /* 1 sector, lba=0 */
-
-               if (qc->dev->flags & ATA_DFLAG_LBA) {
-                       tf->flags |= ATA_TFLAG_LBA;
-
-                       tf->lbah = 0x0;
-                       tf->lbam = 0x0;
-                       tf->lbal = 0x0;
-                       tf->device |= ATA_LBA;
-               } else {
-                       /* CHS */
-                       tf->lbal = 0x1; /* sect */
-                       tf->lbam = 0x0; /* cyl low */
-                       tf->lbah = 0x0; /* cyl high */
-               }
-
-               tf->command = ATA_CMD_VERIFY;   /* READ VERIFY */
-       } else {
-               tf->nsect = 0;  /* time period value (0 implies now) */
-               tf->command = ATA_CMD_STANDBY;
-               /* Consider: ATA STANDBY IMMEDIATE command */
-       }
-       /*
-        * Standby and Idle condition timers could be implemented but that
-        * would require libata to implement the Power condition mode page
-        * and allow the user to change it. Changing mode pages requires
-        * MODE SELECT to be implemented.
-        */
-
-       return 0;
-
-invalid_fld:
-       ata_scsi_set_sense(qc->scsicmd, ILLEGAL_REQUEST, 0x24, 0x0);
-       /* "Invalid field in cbd" */
-       return 1;
-}
-
-
-/**
- *     ata_scsi_flush_xlat - Translate SCSI SYNCHRONIZE CACHE command
- *     @qc: Storage for translated ATA taskfile
- *     @scsicmd: SCSI command to translate (ignored)
- *
- *     Sets up an ATA taskfile to issue FLUSH CACHE or
- *     FLUSH CACHE EXT.
- *
- *     LOCKING:
- *     spin_lock_irqsave(host_set lock)
- *
- *     RETURNS:
- *     Zero on success, non-zero on error.
- */
-
-static unsigned int ata_scsi_flush_xlat(struct ata_queued_cmd *qc, const u8 *scsicmd)
-{
-       struct ata_taskfile *tf = &qc->tf;
-
-       tf->flags |= ATA_TFLAG_DEVICE;
-       tf->protocol = ATA_PROT_NODATA;
-
-       if ((qc->dev->flags & ATA_DFLAG_LBA48) &&
-           (ata_id_has_flush_ext(qc->dev->id)))
-               tf->command = ATA_CMD_FLUSH_EXT;
-       else
-               tf->command = ATA_CMD_FLUSH;
-
-       return 0;
-}
-
-/**
- *     scsi_6_lba_len - Get LBA and transfer length
- *     @scsicmd: SCSI command to translate
- *
- *     Calculate LBA and transfer length for 6-byte commands.
- *
- *     RETURNS:
- *     @plba: the LBA
- *     @plen: the transfer length
- */
-
-static void scsi_6_lba_len(const u8 *scsicmd, u64 *plba, u32 *plen)
-{
-       u64 lba = 0;
-       u32 len = 0;
-
-       VPRINTK("six-byte command\n");
-
-       lba |= ((u64)scsicmd[2]) << 8;
-       lba |= ((u64)scsicmd[3]);
-
-       len |= ((u32)scsicmd[4]);
-
-       *plba = lba;
-       *plen = len;
-}
-
-/**
- *     scsi_10_lba_len - Get LBA and transfer length
- *     @scsicmd: SCSI command to translate
- *
- *     Calculate LBA and transfer length for 10-byte commands.
- *
- *     RETURNS:
- *     @plba: the LBA
- *     @plen: the transfer length
- */
-
-static void scsi_10_lba_len(const u8 *scsicmd, u64 *plba, u32 *plen)
-{
-       u64 lba = 0;
-       u32 len = 0;
-
-       VPRINTK("ten-byte command\n");
-
-       lba |= ((u64)scsicmd[2]) << 24;
-       lba |= ((u64)scsicmd[3]) << 16;
-       lba |= ((u64)scsicmd[4]) << 8;
-       lba |= ((u64)scsicmd[5]);
-
-       len |= ((u32)scsicmd[7]) << 8;
-       len |= ((u32)scsicmd[8]);
-
-       *plba = lba;
-       *plen = len;
-}
-
-/**
- *     scsi_16_lba_len - Get LBA and transfer length
- *     @scsicmd: SCSI command to translate
- *
- *     Calculate LBA and transfer length for 16-byte commands.
- *
- *     RETURNS:
- *     @plba: the LBA
- *     @plen: the transfer length
- */
-
-static void scsi_16_lba_len(const u8 *scsicmd, u64 *plba, u32 *plen)
-{
-       u64 lba = 0;
-       u32 len = 0;
-
-       VPRINTK("sixteen-byte command\n");
-
-       lba |= ((u64)scsicmd[2]) << 56;
-       lba |= ((u64)scsicmd[3]) << 48;
-       lba |= ((u64)scsicmd[4]) << 40;
-       lba |= ((u64)scsicmd[5]) << 32;
-       lba |= ((u64)scsicmd[6]) << 24;
-       lba |= ((u64)scsicmd[7]) << 16;
-       lba |= ((u64)scsicmd[8]) << 8;
-       lba |= ((u64)scsicmd[9]);
-
-       len |= ((u32)scsicmd[10]) << 24;
-       len |= ((u32)scsicmd[11]) << 16;
-       len |= ((u32)scsicmd[12]) << 8;
-       len |= ((u32)scsicmd[13]);
-
-       *plba = lba;
-       *plen = len;
-}
-
-/**
- *     ata_scsi_verify_xlat - Translate SCSI VERIFY command into an ATA one
- *     @qc: Storage for translated ATA taskfile
- *     @scsicmd: SCSI command to translate
- *
- *     Converts SCSI VERIFY command to an ATA READ VERIFY command.
- *
- *     LOCKING:
- *     spin_lock_irqsave(host_set lock)
- *
- *     RETURNS:
- *     Zero on success, non-zero on error.
- */
-
-static unsigned int ata_scsi_verify_xlat(struct ata_queued_cmd *qc, const u8 *scsicmd)
-{
-       struct ata_taskfile *tf = &qc->tf;
-       struct ata_device *dev = qc->dev;
-       u64 dev_sectors = qc->dev->n_sectors;
-       u64 block;
-       u32 n_block;
-
-       tf->flags |= ATA_TFLAG_ISADDR | ATA_TFLAG_DEVICE;
-       tf->protocol = ATA_PROT_NODATA;
-
-       if (scsicmd[0] == VERIFY)
-               scsi_10_lba_len(scsicmd, &block, &n_block);
-       else if (scsicmd[0] == VERIFY_16)
-               scsi_16_lba_len(scsicmd, &block, &n_block);
-       else
-               goto invalid_fld;
-
-       if (!n_block)
-               goto nothing_to_do;
-       if (block >= dev_sectors)
-               goto out_of_range;
-       if ((block + n_block) > dev_sectors)
-               goto out_of_range;
-
-       if (dev->flags & ATA_DFLAG_LBA) {
-               tf->flags |= ATA_TFLAG_LBA;
-
-               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;
-                       tf->command = ATA_CMD_VERIFY_EXT;
-
-                       tf->hob_nsect = (n_block >> 8) & 0xff;
-
-                       tf->hob_lbah = (block >> 40) & 0xff;
-                       tf->hob_lbam = (block >> 32) & 0xff;
-                       tf->hob_lbal = (block >> 24) & 0xff;
-               } else
-                       /* request too large even for LBA48 */
-                       goto out_of_range;
-
-               tf->nsect = n_block & 0xff;
-
-               tf->lbah = (block >> 16) & 0xff;
-               tf->lbam = (block >> 8) & 0xff;
-               tf->lbal = block & 0xff;
-
-               tf->device |= ATA_LBA;
-       } else {
-               /* CHS */
-               u32 sect, head, cyl, track;
-
-               if (!lba_28_ok(block, n_block))
-                       goto out_of_range;
-
-               /* Convert LBA to CHS */
-               track = (u32)block / dev->sectors;
-               cyl   = track / dev->heads;
-               head  = track % dev->heads;
-               sect  = (u32)block % dev->sectors + 1;
-
-               DPRINTK("block %u track %u cyl %u head %u sect %u\n",
-                       (u32)block, track, cyl, head, sect);
-
-               /* Check whether the converted CHS can fit.
-                  Cylinder: 0-65535
-                  Head: 0-15
-                  Sector: 1-255*/
-               if ((cyl >> 16) || (head >> 4) || (sect >> 8) || (!sect))
-                       goto out_of_range;
-
-               tf->command = ATA_CMD_VERIFY;
-               tf->nsect = n_block & 0xff; /* Sector count 0 means 256 sectors */
-               tf->lbal = sect;
-               tf->lbam = cyl;
-               tf->lbah = cyl >> 8;
-               tf->device |= head;
-       }
-
-       return 0;
-
-invalid_fld:
-       ata_scsi_set_sense(qc->scsicmd, ILLEGAL_REQUEST, 0x24, 0x0);
-       /* "Invalid field in cbd" */
-       return 1;
-
-out_of_range:
-       ata_scsi_set_sense(qc->scsicmd, ILLEGAL_REQUEST, 0x21, 0x0);
-       /* "Logical Block Address out of range" */
-       return 1;
-
-nothing_to_do:
-       qc->scsicmd->result = SAM_STAT_GOOD;
-       return 1;
-}
-
-/**
- *     ata_scsi_rw_xlat - Translate SCSI r/w command into an ATA one
- *     @qc: Storage for translated ATA taskfile
- *     @scsicmd: SCSI command to translate
- *
- *     Converts any of six SCSI read/write commands into the
- *     ATA counterpart, including starting sector (LBA),
- *     sector count, and taking into account the device's LBA48
- *     support.
- *
- *     Commands %READ_6, %READ_10, %READ_16, %WRITE_6, %WRITE_10, and
- *     %WRITE_16 are currently supported.
- *
- *     LOCKING:
- *     spin_lock_irqsave(host_set lock)
- *
- *     RETURNS:
- *     Zero on success, non-zero on error.
- */
-
-static unsigned int ata_scsi_rw_xlat(struct ata_queued_cmd *qc, const u8 *scsicmd)
-{
-       struct ata_taskfile *tf = &qc->tf;
-       struct ata_device *dev = qc->dev;
-       u64 block;
-       u32 n_block;
-
-       qc->flags |= ATA_QCFLAG_IO;
-       tf->flags |= ATA_TFLAG_ISADDR | ATA_TFLAG_DEVICE;
-
-       if (scsicmd[0] == WRITE_10 || scsicmd[0] == WRITE_6 ||
-           scsicmd[0] == WRITE_16)
-               tf->flags |= ATA_TFLAG_WRITE;
-
-       /* Calculate the SCSI LBA, transfer length and FUA. */
-       switch (scsicmd[0]) {
-       case READ_10:
-       case WRITE_10:
-               scsi_10_lba_len(scsicmd, &block, &n_block);
-               if (unlikely(scsicmd[1] & (1 << 3)))
-                       tf->flags |= ATA_TFLAG_FUA;
-               break;
-       case READ_6:
-       case WRITE_6:
-               scsi_6_lba_len(scsicmd, &block, &n_block);
-
-               /* for 6-byte r/w commands, transfer length 0
-                * means 256 blocks of data, not 0 block.
-                */
-               if (!n_block)
-                       n_block = 256;
-               break;
-       case READ_16:
-       case WRITE_16:
-               scsi_16_lba_len(scsicmd, &block, &n_block);
-               if (unlikely(scsicmd[1] & (1 << 3)))
-                       tf->flags |= ATA_TFLAG_FUA;
-               break;
-       default:
-               DPRINTK("no-byte command\n");
-               goto invalid_fld;
-       }
-
-       /* Check and compose ATA command */
-       if (!n_block)
-               /* For 10-byte and 16-byte SCSI R/W commands, transfer
-                * length 0 means transfer 0 block of data.
-                * However, for ATA R/W commands, sector count 0 means
-                * 256 or 65536 sectors, not 0 sectors as in SCSI.
-                *
-                * WARNING: one or two older ATA drives treat 0 as 0...
-                */
-               goto nothing_to_do;
-
-       if ((dev->flags & (ATA_DFLAG_PIO | ATA_DFLAG_NCQ)) == ATA_DFLAG_NCQ) {
-               /* yay, NCQ */
-               if (!lba_48_ok(block, n_block))
-                       goto out_of_range;
-
-               tf->protocol = ATA_PROT_NCQ;
-               tf->flags |= ATA_TFLAG_LBA | ATA_TFLAG_LBA48;
-
-               if (tf->flags & ATA_TFLAG_WRITE)
-                       tf->command = ATA_CMD_FPDMA_WRITE;
-               else
-                       tf->command = ATA_CMD_FPDMA_READ;
-
-               qc->nsect = n_block;
-
-               tf->nsect = qc->tag << 3;
-               tf->hob_feature = (n_block >> 8) & 0xff;
-               tf->feature = n_block & 0xff;
-
-               tf->hob_lbah = (block >> 40) & 0xff;
-               tf->hob_lbam = (block >> 32) & 0xff;
-               tf->hob_lbal = (block >> 24) & 0xff;
-               tf->lbah = (block >> 16) & 0xff;
-               tf->lbam = (block >> 8) & 0xff;
-               tf->lbal = block & 0xff;
-
-               tf->device = 1 << 6;
-               if (tf->flags & ATA_TFLAG_FUA)
-                       tf->device |= 1 << 7;
-       } else if (dev->flags & ATA_DFLAG_LBA) {
-               tf->flags |= ATA_TFLAG_LBA;
-
-               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 */
-                       tf->flags |= ATA_TFLAG_LBA48;
-
-                       tf->hob_nsect = (n_block >> 8) & 0xff;
-
-                       tf->hob_lbah = (block >> 40) & 0xff;
-                       tf->hob_lbam = (block >> 32) & 0xff;
-                       tf->hob_lbal = (block >> 24) & 0xff;
-               } else
-                       /* request too large even for LBA48 */
-                       goto out_of_range;
-
-               if (unlikely(ata_rwcmd_protocol(qc) < 0))
-                       goto invalid_fld;
-
-               qc->nsect = n_block;
-               tf->nsect = n_block & 0xff;
-
-               tf->lbah = (block >> 16) & 0xff;
-               tf->lbam = (block >> 8) & 0xff;
-               tf->lbal = block & 0xff;
-
-               tf->device |= ATA_LBA;
-       } else {
-               /* CHS */
-               u32 sect, head, cyl, track;
-
-               /* The request -may- be too large for CHS addressing. */
-               if (!lba_28_ok(block, n_block))
-                       goto out_of_range;
-
-               if (unlikely(ata_rwcmd_protocol(qc) < 0))
-                       goto invalid_fld;
-
-               /* Convert LBA to CHS */
-               track = (u32)block / dev->sectors;
-               cyl   = track / dev->heads;
-               head  = track % dev->heads;
-               sect  = (u32)block % dev->sectors + 1;
-
-               DPRINTK("block %u track %u cyl %u head %u sect %u\n",
-                       (u32)block, track, cyl, head, sect);
-
-               /* Check whether the converted CHS can fit.
-                  Cylinder: 0-65535
-                  Head: 0-15
-                  Sector: 1-255*/
-               if ((cyl >> 16) || (head >> 4) || (sect >> 8) || (!sect))
-                       goto out_of_range;
-
-               qc->nsect = n_block;
-               tf->nsect = n_block & 0xff; /* Sector count 0 means 256 sectors */
-               tf->lbal = sect;
-               tf->lbam = cyl;
-               tf->lbah = cyl >> 8;
-               tf->device |= head;
-       }
-
-       return 0;
-
-invalid_fld:
-       ata_scsi_set_sense(qc->scsicmd, ILLEGAL_REQUEST, 0x24, 0x0);
-       /* "Invalid field in cbd" */
-       return 1;
-
-out_of_range:
-       ata_scsi_set_sense(qc->scsicmd, ILLEGAL_REQUEST, 0x21, 0x0);
-       /* "Logical Block Address out of range" */
-       return 1;
-
-nothing_to_do:
-       qc->scsicmd->result = SAM_STAT_GOOD;
-       return 1;
-}
-
-static void ata_scsi_qc_complete(struct ata_queued_cmd *qc)
-{
-       struct scsi_cmnd *cmd = qc->scsicmd;
-       u8 *cdb = cmd->cmnd;
-       int need_sense = (qc->err_mask != 0);
-
-       /* We snoop the SET_FEATURES - Write Cache ON/OFF command, and
-        * schedule EH_REVALIDATE operation to update the IDENTIFY DEVICE
-        * cache
-        */
-       if (!need_sense && (qc->tf.command == ATA_CMD_SET_FEATURES) &&
-           ((qc->tf.feature == SETFEATURES_WC_ON) ||
-            (qc->tf.feature == SETFEATURES_WC_OFF))) {
-               qc->ap->eh_info.action |= ATA_EH_REVALIDATE;
-               ata_port_schedule_eh(qc->ap);
-       }
-
-       /* For ATA pass thru (SAT) commands, generate a sense block if
-        * user mandated it or if there's an error.  Note that if we
-        * generate because the user forced us to, a check condition
-        * is generated and the ATA register values are returned
-        * whether the command completed successfully or not. If there
-        * was no error, SK, ASC and ASCQ will all be zero.
-        */
-       if (((cdb[0] == ATA_16) || (cdb[0] == ATA_12)) &&
-           ((cdb[2] & 0x20) || need_sense)) {
-               ata_gen_ata_desc_sense(qc);
-       } else {
-               if (!need_sense) {
-                       cmd->result = SAM_STAT_GOOD;
-               } else {
-                       /* TODO: decide which descriptor format to use
-                        * for 48b LBA devices and call that here
-                        * instead of the fixed desc, which is only
-                        * good for smaller LBA (and maybe CHS?)
-                        * devices.
-                        */
-                       ata_gen_fixed_sense(qc);
-               }
-       }
-
-       if (need_sense && !qc->ap->ops->error_handler)
-               ata_dump_status(qc->ap->id, &qc->result_tf);
-
-       qc->scsidone(cmd);
-
-       ata_qc_free(qc);
-}
-
-/**
- *     ata_scmd_need_defer - Check whether we need to defer scmd
- *     @dev: ATA device to which the command is addressed
- *     @is_io: Is the command IO (and thus possibly NCQ)?
- *
- *     NCQ and non-NCQ commands cannot run together.  As upper layer
- *     only knows the queue depth, we are responsible for maintaining
- *     exclusion.  This function checks whether a new command can be
- *     issued to @dev.
- *
- *     LOCKING:
- *     spin_lock_irqsave(host_set lock)
- *
- *     RETURNS:
- *     1 if deferring is needed, 0 otherwise.
- */
-static int ata_scmd_need_defer(struct ata_device *dev, int is_io)
-{
-       struct ata_port *ap = dev->ap;
-
-       if (!(dev->flags & ATA_DFLAG_NCQ))
-               return 0;
-
-       if (is_io) {
-               if (!ata_tag_valid(ap->active_tag))
-                       return 0;
-       } else {
-               if (!ata_tag_valid(ap->active_tag) && !ap->sactive)
-                       return 0;
-       }
-       return 1;
-}
-
-/**
- *     ata_scsi_translate - Translate then issue SCSI command to ATA device
- *     @dev: ATA device to which the command is addressed
- *     @cmd: SCSI command to execute
- *     @done: SCSI command completion function
- *     @xlat_func: Actor which translates @cmd to an ATA taskfile
- *
- *     Our ->queuecommand() function has decided that the SCSI
- *     command issued can be directly translated into an ATA
- *     command, rather than handled internally.
- *
- *     This function sets up an ata_queued_cmd structure for the
- *     SCSI command, and sends that ata_queued_cmd to the hardware.
- *
- *     The xlat_func argument (actor) returns 0 if ready to execute
- *     ATA command, else 1 to finish translation. If 1 is returned
- *     then cmd->result (and possibly cmd->sense_buffer) are assumed
- *     to be set reflecting an error condition or clean (early)
- *     termination.
- *
- *     LOCKING:
- *     spin_lock_irqsave(host_set lock)
- *
- *     RETURNS:
- *     0 on success, SCSI_ML_QUEUE_DEVICE_BUSY if the command
- *     needs to be deferred.
- */
-static int ata_scsi_translate(struct ata_device *dev, struct scsi_cmnd *cmd,
-                             void (*done)(struct scsi_cmnd *),
-                             ata_xlat_func_t xlat_func)
-{
-       struct ata_queued_cmd *qc;
-       u8 *scsicmd = cmd->cmnd;
-       int is_io = xlat_func == ata_scsi_rw_xlat;
-
-       VPRINTK("ENTER\n");
-
-       if (unlikely(ata_scmd_need_defer(dev, is_io)))
-               goto defer;
-
-       qc = ata_scsi_qc_new(dev, cmd, done);
-       if (!qc)
-               goto err_mem;
-
-       /* data is present; dma-map it */
-       if (cmd->sc_data_direction == DMA_FROM_DEVICE ||
-           cmd->sc_data_direction == DMA_TO_DEVICE) {
-               if (unlikely(cmd->request_bufflen < 1)) {
-                       ata_dev_printk(dev, KERN_WARNING,
-                                      "WARNING: zero len r/w req\n");
-                       goto err_did;
-               }
-
-               if (cmd->use_sg)
-                       ata_sg_init(qc, cmd->request_buffer, cmd->use_sg);
-               else
-                       ata_sg_init_one(qc, cmd->request_buffer,
-                                       cmd->request_bufflen);
-
-               qc->dma_dir = cmd->sc_data_direction;
-       }
-
-       qc->complete_fn = ata_scsi_qc_complete;
-
-       if (xlat_func(qc, scsicmd))
-               goto early_finish;
-
-       /* select device, send command to hardware */
-       ata_qc_issue(qc);
-
-       VPRINTK("EXIT\n");
-       return 0;
-
-early_finish:
-        ata_qc_free(qc);
-       done(cmd);
-       DPRINTK("EXIT - early finish (good or error)\n");
-       return 0;
-
-err_did:
-       ata_qc_free(qc);
-err_mem:
-       cmd->result = (DID_ERROR << 16);
-       done(cmd);
-       DPRINTK("EXIT - internal\n");
-       return 0;
-
-defer:
-       DPRINTK("EXIT - defer\n");
-       return SCSI_MLQUEUE_DEVICE_BUSY;
-}
-
-/**
- *     ata_scsi_rbuf_get - Map response buffer.
- *     @cmd: SCSI command containing buffer to be mapped.
- *     @buf_out: Pointer to mapped area.
- *
- *     Maps buffer contained within SCSI command @cmd.
- *
- *     LOCKING:
- *     spin_lock_irqsave(host_set lock)
- *
- *     RETURNS:
- *     Length of response buffer.
- */
-
-static unsigned int ata_scsi_rbuf_get(struct scsi_cmnd *cmd, u8 **buf_out)
-{
-       u8 *buf;
-       unsigned int buflen;
-
-       if (cmd->use_sg) {
-               struct scatterlist *sg;
-
-               sg = (struct scatterlist *) cmd->request_buffer;
-               buf = kmap_atomic(sg->page, KM_USER0) + sg->offset;
-               buflen = sg->length;
-       } else {
-               buf = cmd->request_buffer;
-               buflen = cmd->request_bufflen;
-       }
-
-       *buf_out = buf;
-       return buflen;
-}
-
-/**
- *     ata_scsi_rbuf_put - Unmap response buffer.
- *     @cmd: SCSI command containing buffer to be unmapped.
- *     @buf: buffer to unmap
- *
- *     Unmaps response buffer contained within @cmd.
- *
- *     LOCKING:
- *     spin_lock_irqsave(host_set lock)
- */
-
-static inline void ata_scsi_rbuf_put(struct scsi_cmnd *cmd, u8 *buf)
-{
-       if (cmd->use_sg) {
-               struct scatterlist *sg;
-
-               sg = (struct scatterlist *) cmd->request_buffer;
-               kunmap_atomic(buf - sg->offset, KM_USER0);
-       }
-}
-
-/**
- *     ata_scsi_rbuf_fill - wrapper for SCSI command simulators
- *     @args: device IDENTIFY data / SCSI command of interest.
- *     @actor: Callback hook for desired SCSI command simulator
- *
- *     Takes care of the hard work of simulating a SCSI command...
- *     Mapping the response buffer, calling the command's handler,
- *     and handling the handler's return value.  This return value
- *     indicates whether the handler wishes the SCSI command to be
- *     completed successfully (0), or not (in which case cmd->result
- *     and sense buffer are assumed to be set).
- *
- *     LOCKING:
- *     spin_lock_irqsave(host_set lock)
- */
-
-void ata_scsi_rbuf_fill(struct ata_scsi_args *args,
-                       unsigned int (*actor) (struct ata_scsi_args *args,
-                                          u8 *rbuf, unsigned int buflen))
-{
-       u8 *rbuf;
-       unsigned int buflen, rc;
-       struct scsi_cmnd *cmd = args->cmd;
-
-       buflen = ata_scsi_rbuf_get(cmd, &rbuf);
-       memset(rbuf, 0, buflen);
-       rc = actor(args, rbuf, buflen);
-       ata_scsi_rbuf_put(cmd, rbuf);
-
-       if (rc == 0)
-               cmd->result = SAM_STAT_GOOD;
-       args->done(cmd);
-}
-
-/**
- *     ata_scsiop_inq_std - Simulate INQUIRY command
- *     @args: device IDENTIFY data / SCSI command of interest.
- *     @rbuf: Response buffer, to which simulated SCSI cmd output is sent.
- *     @buflen: Response buffer length.
- *
- *     Returns standard device identification data associated
- *     with non-VPD INQUIRY command output.
- *
- *     LOCKING:
- *     spin_lock_irqsave(host_set lock)
- */
-
-unsigned int ata_scsiop_inq_std(struct ata_scsi_args *args, u8 *rbuf,
-                              unsigned int buflen)
-{
-       u8 hdr[] = {
-               TYPE_DISK,
-               0,
-               0x5,    /* claim SPC-3 version compatibility */
-               2,
-               95 - 4
-       };
-
-       /* set scsi removeable (RMB) bit per ata bit */
-       if (ata_id_removeable(args->id))
-               hdr[1] |= (1 << 7);
-
-       VPRINTK("ENTER\n");
-
-       memcpy(rbuf, hdr, sizeof(hdr));
-
-       if (buflen > 35) {
-               memcpy(&rbuf[8], "ATA     ", 8);
-               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);
-       }
-
-       if (buflen > 63) {
-               const u8 versions[] = {
-                       0x60,   /* SAM-3 (no version claimed) */
-
-                       0x03,
-                       0x20,   /* SBC-2 (no version claimed) */
-
-                       0x02,
-                       0x60    /* SPC-3 (no version claimed) */
-               };
-
-               memcpy(rbuf + 59, versions, sizeof(versions));
-       }
-
-       return 0;
-}
-
-/**
- *     ata_scsiop_inq_00 - Simulate INQUIRY VPD page 0, list of pages
- *     @args: device IDENTIFY data / SCSI command of interest.
- *     @rbuf: Response buffer, to which simulated SCSI cmd output is sent.
- *     @buflen: Response buffer length.
- *
- *     Returns list of inquiry VPD pages available.
- *
- *     LOCKING:
- *     spin_lock_irqsave(host_set lock)
- */
-
-unsigned int ata_scsiop_inq_00(struct ata_scsi_args *args, u8 *rbuf,
-                             unsigned int buflen)
-{
-       const u8 pages[] = {
-               0x00,   /* page 0x00, this page */
-               0x80,   /* page 0x80, unit serial no page */
-               0x83    /* page 0x83, device ident page */
-       };
-       rbuf[3] = sizeof(pages);        /* number of supported VPD pages */
-
-       if (buflen > 6)
-               memcpy(rbuf + 4, pages, sizeof(pages));
-
-       return 0;
-}
-
-/**
- *     ata_scsiop_inq_80 - Simulate INQUIRY VPD page 80, device serial number
- *     @args: device IDENTIFY data / SCSI command of interest.
- *     @rbuf: Response buffer, to which simulated SCSI cmd output is sent.
- *     @buflen: Response buffer length.
- *
- *     Returns ATA device serial number.
- *
- *     LOCKING:
- *     spin_lock_irqsave(host_set lock)
- */
-
-unsigned int ata_scsiop_inq_80(struct ata_scsi_args *args, u8 *rbuf,
-                             unsigned int buflen)
-{
-       const u8 hdr[] = {
-               0,
-               0x80,                   /* this page code */
-               0,
-               ATA_SERNO_LEN,          /* page len */
-       };
-       memcpy(rbuf, hdr, sizeof(hdr));
-
-       if (buflen > (ATA_SERNO_LEN + 4 - 1))
-               ata_id_string(args->id, (unsigned char *) &rbuf[4],
-                             ATA_ID_SERNO_OFS, ATA_SERNO_LEN);
-
-       return 0;
-}
-
-/**
- *     ata_scsiop_inq_83 - Simulate INQUIRY VPD page 83, device identity
- *     @args: device IDENTIFY data / SCSI command of interest.
- *     @rbuf: Response buffer, to which simulated SCSI cmd output is sent.
- *     @buflen: Response buffer length.
- *
- *     Yields two logical unit device identification designators:
- *      - vendor specific ASCII containing the ATA serial number
- *      - SAT defined "t10 vendor id based" containing ASCII vendor
- *        name ("ATA     "), model and serial numbers.
- *
- *     LOCKING:
- *     spin_lock_irqsave(host_set lock)
- */
-
-unsigned int ata_scsiop_inq_83(struct ata_scsi_args *args, u8 *rbuf,
-                             unsigned int buflen)
-{
-       int num;
-       const int sat_model_serial_desc_len = 68;
-       const int ata_model_byte_len = 40;
-
-       rbuf[1] = 0x83;                 /* this page code */
-       num = 4;
-
-       if (buflen > (ATA_SERNO_LEN + num + 3)) {
-               /* piv=0, assoc=lu, code_set=ACSII, designator=vendor */
-               rbuf[num + 0] = 2;
-               rbuf[num + 3] = ATA_SERNO_LEN;
-               num += 4;
-               ata_id_string(args->id, (unsigned char *) rbuf + num,
-                             ATA_ID_SERNO_OFS, ATA_SERNO_LEN);
-               num += ATA_SERNO_LEN;
-       }
-       if (buflen > (sat_model_serial_desc_len + num + 3)) {
-               /* SAT defined lu model and serial numbers descriptor */
-               /* piv=0, assoc=lu, code_set=ACSII, designator=t10 vendor id */
-               rbuf[num + 0] = 2;
-               rbuf[num + 1] = 1;
-               rbuf[num + 3] = sat_model_serial_desc_len;
-               num += 4;
-               memcpy(rbuf + num, "ATA     ", 8);
-               num += 8;
-               ata_id_string(args->id, (unsigned char *) rbuf + num,
-                             ATA_ID_PROD_OFS, ata_model_byte_len);
-               num += ata_model_byte_len;
-               ata_id_string(args->id, (unsigned char *) rbuf + num,
-                             ATA_ID_SERNO_OFS, ATA_SERNO_LEN);
-               num += ATA_SERNO_LEN;
-       }
-       rbuf[3] = num - 4;    /* page len (assume less than 256 bytes) */
-       return 0;
-}
-
-/**
- *     ata_scsiop_noop - Command handler that simply returns success.
- *     @args: device IDENTIFY data / SCSI command of interest.
- *     @rbuf: Response buffer, to which simulated SCSI cmd output is sent.
- *     @buflen: Response buffer length.
- *
- *     No operation.  Simply returns success to caller, to indicate
- *     that the caller should successfully complete this SCSI command.
- *
- *     LOCKING:
- *     spin_lock_irqsave(host_set lock)
- */
-
-unsigned int ata_scsiop_noop(struct ata_scsi_args *args, u8 *rbuf,
-                           unsigned int buflen)
-{
-       VPRINTK("ENTER\n");
-       return 0;
-}
-
-/**
- *     ata_msense_push - Push data onto MODE SENSE data output buffer
- *     @ptr_io: (input/output) Location to store more output data
- *     @last: End of output data buffer
- *     @buf: Pointer to BLOB being added to output buffer
- *     @buflen: Length of BLOB
- *
- *     Store MODE SENSE data on an output buffer.
- *
- *     LOCKING:
- *     None.
- */
-
-static void ata_msense_push(u8 **ptr_io, const u8 *last,
-                           const u8 *buf, unsigned int buflen)
-{
-       u8 *ptr = *ptr_io;
-
-       if ((ptr + buflen - 1) > last)
-               return;
-
-       memcpy(ptr, buf, buflen);
-
-       ptr += buflen;
-
-       *ptr_io = ptr;
-}
-
-/**
- *     ata_msense_caching - Simulate MODE SENSE caching info page
- *     @id: device IDENTIFY data
- *     @ptr_io: (input/output) Location to store more output data
- *     @last: End of output data buffer
- *
- *     Generate a caching info page, which conditionally indicates
- *     write caching to the SCSI layer, depending on device
- *     capabilities.
- *
- *     LOCKING:
- *     None.
- */
-
-static unsigned int ata_msense_caching(u16 *id, u8 **ptr_io,
-                                      const u8 *last)
-{
-       u8 page[CACHE_MPAGE_LEN];
-
-       memcpy(page, def_cache_mpage, sizeof(page));
-       if (ata_id_wcache_enabled(id))
-               page[2] |= (1 << 2);    /* write cache enable */
-       if (!ata_id_rahead_enabled(id))
-               page[12] |= (1 << 5);   /* disable read ahead */
-
-       ata_msense_push(ptr_io, last, page, sizeof(page));
-       return sizeof(page);
-}
-
-/**
- *     ata_msense_ctl_mode - Simulate MODE SENSE control mode page
- *     @dev: Device associated with this MODE SENSE command
- *     @ptr_io: (input/output) Location to store more output data
- *     @last: End of output data buffer
- *
- *     Generate a generic MODE SENSE control mode page.
- *
- *     LOCKING:
- *     None.
- */
-
-static unsigned int ata_msense_ctl_mode(u8 **ptr_io, const u8 *last)
-{
-       ata_msense_push(ptr_io, last, def_control_mpage,
-                       sizeof(def_control_mpage));
-       return sizeof(def_control_mpage);
-}
-
-/**
- *     ata_msense_rw_recovery - Simulate MODE SENSE r/w error recovery page
- *     @dev: Device associated with this MODE SENSE command
- *     @ptr_io: (input/output) Location to store more output data
- *     @last: End of output data buffer
- *
- *     Generate a generic MODE SENSE r/w error recovery page.
- *
- *     LOCKING:
- *     None.
- */
-
-static unsigned int ata_msense_rw_recovery(u8 **ptr_io, const u8 *last)
-{
-
-       ata_msense_push(ptr_io, last, def_rw_recovery_mpage,
-                       sizeof(def_rw_recovery_mpage));
-       return sizeof(def_rw_recovery_mpage);
-}
-
-/*
- * We can turn this into a real blacklist if it's needed, for now just
- * blacklist any Maxtor BANC1G10 revision firmware
- */
-static int ata_dev_supports_fua(u16 *id)
-{
-       unsigned char model[41], fw[9];
-
-       if (!libata_fua)
-               return 0;
-       if (!ata_id_has_fua(id))
-               return 0;
-
-       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 (strcmp(model, "Maxtor"))
-               return 1;
-       if (strcmp(fw, "BANC1G10"))
-               return 1;
-
-       return 0; /* blacklisted */
-}
-
-/**
- *     ata_scsiop_mode_sense - Simulate MODE SENSE 6, 10 commands
- *     @args: device IDENTIFY data / SCSI command of interest.
- *     @rbuf: Response buffer, to which simulated SCSI cmd output is sent.
- *     @buflen: Response buffer length.
- *
- *     Simulate MODE SENSE commands. Assume this is invoked for direct
- *     access devices (e.g. disks) only. There should be no block
- *     descriptor for other device types.
- *
- *     LOCKING:
- *     spin_lock_irqsave(host_set lock)
- */
-
-unsigned int ata_scsiop_mode_sense(struct ata_scsi_args *args, u8 *rbuf,
-                                 unsigned int buflen)
-{
-       struct ata_device *dev = args->dev;
-       u8 *scsicmd = args->cmd->cmnd, *p, *last;
-       const u8 sat_blk_desc[] = {
-               0, 0, 0, 0,     /* number of blocks: sat unspecified */
-               0,
-               0, 0x2, 0x0     /* block length: 512 bytes */
-       };
-       u8 pg, spg;
-       unsigned int ebd, page_control, six_byte, output_len, alloc_len, minlen;
-       u8 dpofua;
-
-       VPRINTK("ENTER\n");
-
-       six_byte = (scsicmd[0] == MODE_SENSE);
-       ebd = !(scsicmd[1] & 0x8);      /* dbd bit inverted == edb */
-       /*
-        * LLBA bit in msense(10) ignored (compliant)
-        */
-
-       page_control = scsicmd[2] >> 6;
-       switch (page_control) {
-       case 0: /* current */
-               break;  /* supported */
-       case 3: /* saved */
-               goto saving_not_supp;
-       case 1: /* changeable */
-       case 2: /* defaults */
-       default:
-               goto invalid_fld;
-       }
-
-       if (six_byte) {
-               output_len = 4 + (ebd ? 8 : 0);
-               alloc_len = scsicmd[4];
-       } else {
-               output_len = 8 + (ebd ? 8 : 0);
-               alloc_len = (scsicmd[7] << 8) + scsicmd[8];
-       }
-       minlen = (alloc_len < buflen) ? alloc_len : buflen;
-
-       p = rbuf + output_len;
-       last = rbuf + minlen - 1;
-
-       pg = scsicmd[2] & 0x3f;
-       spg = scsicmd[3];
-       /*
-        * No mode subpages supported (yet) but asking for _all_
-        * subpages may be valid
-        */
-       if (spg && (spg != ALL_SUB_MPAGES))
-               goto invalid_fld;
-
-       switch(pg) {
-       case RW_RECOVERY_MPAGE:
-               output_len += ata_msense_rw_recovery(&p, last);
-               break;
-
-       case CACHE_MPAGE:
-               output_len += ata_msense_caching(args->id, &p, last);
-               break;
-
-       case CONTROL_MPAGE: {
-               output_len += ata_msense_ctl_mode(&p, last);
-               break;
-               }
-
-       case ALL_MPAGES:
-               output_len += ata_msense_rw_recovery(&p, last);
-               output_len += ata_msense_caching(args->id, &p, last);
-               output_len += ata_msense_ctl_mode(&p, last);
-               break;
-
-       default:                /* invalid page code */
-               goto invalid_fld;
-       }
-
-       if (minlen < 1)
-               return 0;
-
-       dpofua = 0;
-       if (ata_dev_supports_fua(args->id) && (dev->flags & ATA_DFLAG_LBA48) &&
-           (!(dev->flags & ATA_DFLAG_PIO) || dev->multi_count))
-               dpofua = 1 << 4;
-
-       if (six_byte) {
-               output_len--;
-               rbuf[0] = output_len;
-               if (minlen > 2)
-                       rbuf[2] |= dpofua;
-               if (ebd) {
-                       if (minlen > 3)
-                               rbuf[3] = sizeof(sat_blk_desc);
-                       if (minlen > 11)
-                               memcpy(rbuf + 4, sat_blk_desc,
-                                      sizeof(sat_blk_desc));
-               }
-       } else {
-               output_len -= 2;
-               rbuf[0] = output_len >> 8;
-               if (minlen > 1)
-                       rbuf[1] = output_len;
-               if (minlen > 3)
-                       rbuf[3] |= dpofua;
-               if (ebd) {
-                       if (minlen > 7)
-                               rbuf[7] = sizeof(sat_blk_desc);
-                       if (minlen > 15)
-                               memcpy(rbuf + 8, sat_blk_desc,
-                                      sizeof(sat_blk_desc));
-               }
-       }
-       return 0;
-
-invalid_fld:
-       ata_scsi_set_sense(args->cmd, ILLEGAL_REQUEST, 0x24, 0x0);
-       /* "Invalid field in cbd" */
-       return 1;
-
-saving_not_supp:
-       ata_scsi_set_sense(args->cmd, ILLEGAL_REQUEST, 0x39, 0x0);
-        /* "Saving parameters not supported" */
-       return 1;
-}
-
-/**
- *     ata_scsiop_read_cap - Simulate READ CAPACITY[ 16] commands
- *     @args: device IDENTIFY data / SCSI command of interest.
- *     @rbuf: Response buffer, to which simulated SCSI cmd output is sent.
- *     @buflen: Response buffer length.
- *
- *     Simulate READ CAPACITY commands.
- *
- *     LOCKING:
- *     spin_lock_irqsave(host_set lock)
- */
-
-unsigned int ata_scsiop_read_cap(struct ata_scsi_args *args, u8 *rbuf,
-                               unsigned int buflen)
-{
-       u64 n_sectors;
-       u32 tmp;
-
-       VPRINTK("ENTER\n");
-
-       if (ata_id_has_lba(args->id)) {
-               if (ata_id_has_lba48(args->id))
-                       n_sectors = ata_id_u64(args->id, 100);
-               else
-                       n_sectors = ata_id_u32(args->id, 60);
-       } else {
-               /* CHS default translation */
-               n_sectors = args->id[1] * args->id[3] * args->id[6];
-
-               if (ata_id_current_chs_valid(args->id))
-                       /* CHS current translation */
-                       n_sectors = ata_id_u32(args->id, 57);
-       }
-
-       n_sectors--;            /* ATA TotalUserSectors - 1 */
-
-       if (args->cmd->cmnd[0] == READ_CAPACITY) {
-               if( n_sectors >= 0xffffffffULL )
-                       tmp = 0xffffffff ;  /* Return max count on overflow */
-               else
-                       tmp = n_sectors ;
-
-               /* sector count, 32-bit */
-               rbuf[0] = tmp >> (8 * 3);
-               rbuf[1] = tmp >> (8 * 2);
-               rbuf[2] = tmp >> (8 * 1);
-               rbuf[3] = tmp;
-
-               /* sector size */
-               tmp = ATA_SECT_SIZE;
-               rbuf[6] = tmp >> 8;
-               rbuf[7] = tmp;
-
-       } else {
-               /* sector count, 64-bit */
-               tmp = n_sectors >> (8 * 4);
-               rbuf[2] = tmp >> (8 * 3);
-               rbuf[3] = tmp >> (8 * 2);
-               rbuf[4] = tmp >> (8 * 1);
-               rbuf[5] = tmp;
-               tmp = n_sectors;
-               rbuf[6] = tmp >> (8 * 3);
-               rbuf[7] = tmp >> (8 * 2);
-               rbuf[8] = tmp >> (8 * 1);
-               rbuf[9] = tmp;
-
-               /* sector size */
-               tmp = ATA_SECT_SIZE;
-               rbuf[12] = tmp >> 8;
-               rbuf[13] = tmp;
-       }
-
-       return 0;
-}
-
-/**
- *     ata_scsiop_report_luns - Simulate REPORT LUNS command
- *     @args: device IDENTIFY data / SCSI command of interest.
- *     @rbuf: Response buffer, to which simulated SCSI cmd output is sent.
- *     @buflen: Response buffer length.
- *
- *     Simulate REPORT LUNS command.
- *
- *     LOCKING:
- *     spin_lock_irqsave(host_set lock)
- */
-
-unsigned int ata_scsiop_report_luns(struct ata_scsi_args *args, u8 *rbuf,
-                                  unsigned int buflen)
-{
-       VPRINTK("ENTER\n");
-       rbuf[3] = 8;    /* just one lun, LUN 0, size 8 bytes */
-
-       return 0;
-}
-
-/**
- *     ata_scsi_set_sense - Set SCSI sense data and status
- *     @cmd: SCSI request to be handled
- *     @sk: SCSI-defined sense key
- *     @asc: SCSI-defined additional sense code
- *     @ascq: SCSI-defined additional sense code qualifier
- *
- *     Helper function that builds a valid fixed format, current
- *     response code and the given sense key (sk), additional sense
- *     code (asc) and additional sense code qualifier (ascq) with
- *     a SCSI command status of %SAM_STAT_CHECK_CONDITION and
- *     DRIVER_SENSE set in the upper bits of scsi_cmnd::result .
- *
- *     LOCKING:
- *     Not required
- */
-
-void ata_scsi_set_sense(struct scsi_cmnd *cmd, u8 sk, u8 asc, u8 ascq)
-{
-       cmd->result = (DRIVER_SENSE << 24) | SAM_STAT_CHECK_CONDITION;
-
-       cmd->sense_buffer[0] = 0x70;    /* fixed format, current */
-       cmd->sense_buffer[2] = sk;
-       cmd->sense_buffer[7] = 18 - 8;  /* additional sense length */
-       cmd->sense_buffer[12] = asc;
-       cmd->sense_buffer[13] = ascq;
-}
-
-/**
- *     ata_scsi_badcmd - End a SCSI request with an error
- *     @cmd: SCSI request to be handled
- *     @done: SCSI command completion function
- *     @asc: SCSI-defined additional sense code
- *     @ascq: SCSI-defined additional sense code qualifier
- *
- *     Helper function that completes a SCSI command with
- *     %SAM_STAT_CHECK_CONDITION, with a sense key %ILLEGAL_REQUEST
- *     and the specified additional sense codes.
- *
- *     LOCKING:
- *     spin_lock_irqsave(host_set lock)
- */
-
-void ata_scsi_badcmd(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *), u8 asc, u8 ascq)
-{
-       DPRINTK("ENTER\n");
-       ata_scsi_set_sense(cmd, ILLEGAL_REQUEST, asc, ascq);
-
-       done(cmd);
-}
-
-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
-                * translation of taskfile registers into
-                * a sense descriptors, since that's only
-                * correct for ATA, not ATAPI
-                */
-               ata_gen_ata_desc_sense(qc);
-       }
-
-       qc->scsidone(qc->scsicmd);
-       ata_qc_free(qc);
-}
-
-/* is it pointless to prefer PIO for "safety reasons"? */
-static inline int ata_pio_use_silly(struct ata_port *ap)
-{
-       return (ap->flags & ATA_FLAG_PIO_DMA);
-}
-
-static void atapi_request_sense(struct ata_queued_cmd *qc)
-{
-       struct ata_port *ap = qc->ap;
-       struct scsi_cmnd *cmd = qc->scsicmd;
-
-       DPRINTK("ATAPI request sense\n");
-
-       /* FIXME: is this needed? */
-       memset(cmd->sense_buffer, 0, sizeof(cmd->sense_buffer));
-
-       ap->ops->tf_read(ap, &qc->tf);
-
-       /* fill these in, for the case where they are -not- overwritten */
-       cmd->sense_buffer[0] = 0x70;
-       cmd->sense_buffer[2] = qc->tf.feature >> 4;
-
-       ata_qc_reinit(qc);
-
-       ata_sg_init_one(qc, cmd->sense_buffer, sizeof(cmd->sense_buffer));
-       qc->dma_dir = DMA_FROM_DEVICE;
-
-       memset(&qc->cdb, 0, qc->dev->cdb_len);
-       qc->cdb[0] = REQUEST_SENSE;
-       qc->cdb[4] = SCSI_SENSE_BUFFERSIZE;
-
-       qc->tf.flags |= ATA_TFLAG_ISADDR | ATA_TFLAG_DEVICE;
-       qc->tf.command = ATA_CMD_PACKET;
-
-       if (ata_pio_use_silly(ap)) {
-               qc->tf.protocol = ATA_PROT_ATAPI_DMA;
-               qc->tf.feature |= ATAPI_PKT_DMA;
-       } else {
-               qc->tf.protocol = ATA_PROT_ATAPI;
-               qc->tf.lbam = (8 * 1024) & 0xff;
-               qc->tf.lbah = (8 * 1024) >> 8;
-       }
-       qc->nbytes = SCSI_SENSE_BUFFERSIZE;
-
-       qc->complete_fn = atapi_sense_complete;
-
-       ata_qc_issue(qc);
-
-       DPRINTK("EXIT\n");
-}
-
-static void atapi_qc_complete(struct ata_queued_cmd *qc)
-{
-       struct scsi_cmnd *cmd = qc->scsicmd;
-       unsigned int err_mask = qc->err_mask;
-
-       VPRINTK("ENTER, err_mask 0x%X\n", err_mask);
-
-       /* handle completion from new EH */
-       if (unlikely(qc->ap->ops->error_handler &&
-                    (err_mask || qc->flags & ATA_QCFLAG_SENSE_VALID))) {
-
-               if (!(qc->flags & ATA_QCFLAG_SENSE_VALID)) {
-                       /* FIXME: not quite right; we don't want the
-                        * translation of taskfile registers into a
-                        * sense descriptors, since that's only
-                        * correct for ATA, not ATAPI
-                        */
-                       ata_gen_ata_desc_sense(qc);
-               }
-
-               /* SCSI EH automatically locks door if sdev->locked is
-                * set.  Sometimes door lock request continues to
-                * fail, for example, when no media is present.  This
-                * creates a loop - SCSI EH issues door lock which
-                * fails and gets invoked again to acquire sense data
-                * for the failed command.
-                *
-                * If door lock fails, always clear sdev->locked to
-                * avoid this infinite loop.
-                */
-               if (qc->cdb[0] == ALLOW_MEDIUM_REMOVAL)
-                       qc->dev->sdev->locked = 0;
-
-               qc->scsicmd->result = SAM_STAT_CHECK_CONDITION;
-               qc->scsidone(cmd);
-               ata_qc_free(qc);
-               return;
-       }
-
-       /* successful completion or old EH failure path */
-       if (unlikely(err_mask & AC_ERR_DEV)) {
-               cmd->result = SAM_STAT_CHECK_CONDITION;
-               atapi_request_sense(qc);
-               return;
-       } else if (unlikely(err_mask)) {
-               /* FIXME: not quite right; we don't want the
-                * translation of taskfile registers into
-                * a sense descriptors, since that's only
-                * correct for ATA, not ATAPI
-                */
-               ata_gen_ata_desc_sense(qc);
-       } else {
-               u8 *scsicmd = cmd->cmnd;
-
-               if ((scsicmd[0] == INQUIRY) && ((scsicmd[1] & 0x03) == 0)) {
-                       u8 *buf = NULL;
-                       unsigned int buflen;
-
-                       buflen = ata_scsi_rbuf_get(cmd, &buf);
-
-       /* ATAPI devices typically report zero for their SCSI version,
-        * and sometimes deviate from the spec WRT response data
-        * format.  If SCSI version is reported as zero like normal,
-        * then we make the following fixups:  1) Fake MMC-5 version,
-        * to indicate to the Linux scsi midlayer this is a modern
-        * device.  2) Ensure response data format / ATAPI information
-        * are always correct.
-        */
-                       if (buf[2] == 0) {
-                               buf[2] = 0x5;
-                               buf[3] = 0x32;
-                       }
-
-                       ata_scsi_rbuf_put(cmd, buf);
-               }
-
-               cmd->result = SAM_STAT_GOOD;
-       }
-
-       qc->scsidone(cmd);
-       ata_qc_free(qc);
-}
-/**
- *     atapi_xlat - Initialize PACKET taskfile
- *     @qc: command structure to be initialized
- *     @scsicmd: SCSI CDB associated with this PACKET command
- *
- *     LOCKING:
- *     spin_lock_irqsave(host_set lock)
- *
- *     RETURNS:
- *     Zero on success, non-zero on failure.
- */
-
-static unsigned int atapi_xlat(struct ata_queued_cmd *qc, const u8 *scsicmd)
-{
-       struct scsi_cmnd *cmd = qc->scsicmd;
-       struct ata_device *dev = qc->dev;
-       int using_pio = (dev->flags & ATA_DFLAG_PIO);
-       int nodata = (cmd->sc_data_direction == DMA_NONE);
-
-       if (!using_pio)
-               /* Check whether ATAPI DMA is safe */
-               if (ata_check_atapi_dma(qc))
-                       using_pio = 1;
-
-       memcpy(&qc->cdb, scsicmd, dev->cdb_len);
-
-       qc->complete_fn = atapi_qc_complete;
-
-       qc->tf.flags |= ATA_TFLAG_ISADDR | ATA_TFLAG_DEVICE;
-       if (cmd->sc_data_direction == DMA_TO_DEVICE) {
-               qc->tf.flags |= ATA_TFLAG_WRITE;
-               DPRINTK("direction: write\n");
-       }
-
-       qc->tf.command = ATA_CMD_PACKET;
-
-       /* no data, or PIO data xfer */
-       if (using_pio || nodata) {
-               if (nodata)
-                       qc->tf.protocol = ATA_PROT_ATAPI_NODATA;
-               else
-                       qc->tf.protocol = ATA_PROT_ATAPI;
-               qc->tf.lbam = (8 * 1024) & 0xff;
-               qc->tf.lbah = (8 * 1024) >> 8;
-       }
-
-       /* DMA data xfer */
-       else {
-               qc->tf.protocol = ATA_PROT_ATAPI_DMA;
-               qc->tf.feature |= ATAPI_PKT_DMA;
-
-               if (atapi_dmadir && (cmd->sc_data_direction != DMA_TO_DEVICE))
-                       /* some SATA bridges need us to indicate data xfer direction */
-                       qc->tf.feature |= ATAPI_DMADIR;
-       }
-
-       qc->nbytes = cmd->request_bufflen;
-
-       return 0;
-}
-
-static struct ata_device * ata_find_dev(struct ata_port *ap, int id)
-{
-       if (likely(id < ATA_MAX_DEVICES))
-               return &ap->device[id];
-       return NULL;
-}
-
-static struct ata_device * __ata_scsi_find_dev(struct ata_port *ap,
-                                       const struct scsi_device *scsidev)
-{
-       /* skip commands not addressed to targets we simulate */
-       if (unlikely(scsidev->channel || scsidev->lun))
-               return NULL;
-
-       return ata_find_dev(ap, scsidev->id);
-}
-
-/**
- *     ata_scsi_dev_enabled - determine if device is enabled
- *     @dev: ATA device
- *
- *     Determine if commands should be sent to the specified device.
- *
- *     LOCKING:
- *     spin_lock_irqsave(host_set lock)
- *
- *     RETURNS:
- *     0 if commands are not allowed / 1 if commands are allowed
- */
-
-static int ata_scsi_dev_enabled(struct ata_device *dev)
-{
-       if (unlikely(!ata_dev_enabled(dev)))
-               return 0;
-
-       if (!atapi_enabled || (dev->ap->flags & ATA_FLAG_NO_ATAPI)) {
-               if (unlikely(dev->class == ATA_DEV_ATAPI)) {
-                       ata_dev_printk(dev, KERN_WARNING,
-                                      "WARNING: ATAPI is %s, device ignored.\n",
-                                      atapi_enabled ? "not supported with this driver" : "disabled");
-                       return 0;
-               }
-       }
-
-       return 1;
-}
-
-/**
- *     ata_scsi_find_dev - lookup ata_device from scsi_cmnd
- *     @ap: ATA port to which the device is attached
- *     @scsidev: SCSI device from which we derive the ATA device
- *
- *     Given various information provided in struct scsi_cmnd,
- *     map that onto an ATA bus, and using that mapping
- *     determine which ata_device is associated with the
- *     SCSI command to be sent.
- *
- *     LOCKING:
- *     spin_lock_irqsave(host_set lock)
- *
- *     RETURNS:
- *     Associated ATA device, or %NULL if not found.
- */
-static struct ata_device *
-ata_scsi_find_dev(struct ata_port *ap, const struct scsi_device *scsidev)
-{
-       struct ata_device *dev = __ata_scsi_find_dev(ap, scsidev);
-
-       if (unlikely(!dev || !ata_scsi_dev_enabled(dev)))
-               return NULL;
-
-       return dev;
-}
-
-/*
- *     ata_scsi_map_proto - Map pass-thru protocol value to taskfile value.
- *     @byte1: Byte 1 from pass-thru CDB.
- *
- *     RETURNS:
- *     ATA_PROT_UNKNOWN if mapping failed/unimplemented, protocol otherwise.
- */
-static u8
-ata_scsi_map_proto(u8 byte1)
-{
-       switch((byte1 & 0x1e) >> 1) {
-               case 3:         /* Non-data */
-                       return ATA_PROT_NODATA;
-
-               case 6:         /* DMA */
-                       return ATA_PROT_DMA;
-
-               case 4:         /* PIO Data-in */
-               case 5:         /* PIO Data-out */
-                       return ATA_PROT_PIO;
-
-               case 10:        /* Device Reset */
-               case 0:         /* Hard Reset */
-               case 1:         /* SRST */
-               case 2:         /* Bus Idle */
-               case 7:         /* Packet */
-               case 8:         /* DMA Queued */
-               case 9:         /* Device Diagnostic */
-               case 11:        /* UDMA Data-in */
-               case 12:        /* UDMA Data-Out */
-               case 13:        /* FPDMA */
-               default:        /* Reserved */
-                       break;
-       }
-
-       return ATA_PROT_UNKNOWN;
-}
-
-/**
- *     ata_scsi_pass_thru - convert ATA pass-thru CDB to taskfile
- *     @qc: command structure to be initialized
- *     @scsicmd: SCSI command to convert
- *
- *     Handles either 12 or 16-byte versions of the CDB.
- *
- *     RETURNS:
- *     Zero on success, non-zero on failure.
- */
-static unsigned int
-ata_scsi_pass_thru(struct ata_queued_cmd *qc, const u8 *scsicmd)
-{
-       struct ata_taskfile *tf = &(qc->tf);
-       struct scsi_cmnd *cmd = qc->scsicmd;
-       struct ata_device *dev = qc->dev;
-
-       if ((tf->protocol = ata_scsi_map_proto(scsicmd[1])) == ATA_PROT_UNKNOWN)
-               goto invalid_fld;
-
-       /* We may not issue DMA commands if no DMA mode is set */
-       if (tf->protocol == ATA_PROT_DMA && dev->dma_mode == 0)
-               goto invalid_fld;
-
-       if (scsicmd[1] & 0xe0)
-               /* PIO multi not supported yet */
-               goto invalid_fld;
-
-       /*
-        * 12 and 16 byte CDBs use different offsets to
-        * provide the various register values.
-        */
-       if (scsicmd[0] == ATA_16) {
-               /*
-                * 16-byte CDB - may contain extended commands.
-                *
-                * If that is the case, copy the upper byte register values.
-                */
-               if (scsicmd[1] & 0x01) {
-                       tf->hob_feature = scsicmd[3];
-                       tf->hob_nsect = scsicmd[5];
-                       tf->hob_lbal = scsicmd[7];
-                       tf->hob_lbam = scsicmd[9];
-                       tf->hob_lbah = scsicmd[11];
-                       tf->flags |= ATA_TFLAG_LBA48;
-               } else
-                       tf->flags &= ~ATA_TFLAG_LBA48;
-
-               /*
-                * Always copy low byte, device and command registers.
-                */
-               tf->feature = scsicmd[4];
-               tf->nsect = scsicmd[6];
-               tf->lbal = scsicmd[8];
-               tf->lbam = scsicmd[10];
-               tf->lbah = scsicmd[12];
-               tf->device = scsicmd[13];
-               tf->command = scsicmd[14];
-       } else {
-               /*
-                * 12-byte CDB - incapable of extended commands.
-                */
-               tf->flags &= ~ATA_TFLAG_LBA48;
-
-               tf->feature = scsicmd[3];
-               tf->nsect = scsicmd[4];
-               tf->lbal = scsicmd[5];
-               tf->lbam = scsicmd[6];
-               tf->lbah = scsicmd[7];
-               tf->device = scsicmd[8];
-               tf->command = scsicmd[9];
-       }
-       /*
-        * If slave is possible, enforce correct master/slave bit
-       */
-       if (qc->ap->flags & ATA_FLAG_SLAVE_POSS)
-               tf->device = qc->dev->devno ?
-                       tf->device | ATA_DEV1 : tf->device & ~ATA_DEV1;
-
-       /*
-        * Filter SET_FEATURES - XFER MODE command -- otherwise,
-        * SET_FEATURES - XFER MODE must be preceded/succeeded
-        * by an update to hardware-specific registers for each
-        * controller (i.e. the reason for ->set_piomode(),
-        * ->set_dmamode(), and ->post_set_mode() hooks).
-        */
-       if ((tf->command == ATA_CMD_SET_FEATURES)
-        && (tf->feature == SETFEATURES_XFER))
-               goto invalid_fld;
-
-       /*
-        * Set flags so that all registers will be written,
-        * and pass on write indication (used for PIO/DMA
-        * setup.)
-        */
-       tf->flags |= (ATA_TFLAG_ISADDR | ATA_TFLAG_DEVICE);
-
-       if (cmd->sc_data_direction == DMA_TO_DEVICE)
-               tf->flags |= ATA_TFLAG_WRITE;
-
-       /*
-        * Set transfer length.
-        *
-        * TODO: find out if we need to do more here to
-        *       cover scatter/gather case.
-        */
-       qc->nsect = cmd->request_bufflen / ATA_SECT_SIZE;
-
-       /* request result TF */
-       qc->flags |= ATA_QCFLAG_RESULT_TF;
-
-       return 0;
-
- invalid_fld:
-       ata_scsi_set_sense(qc->scsicmd, ILLEGAL_REQUEST, 0x24, 0x00);
-       /* "Invalid field in cdb" */
-       return 1;
-}
-
-/**
- *     ata_get_xlat_func - check if SCSI to ATA translation is possible
- *     @dev: ATA device
- *     @cmd: SCSI command opcode to consider
- *
- *     Look up the SCSI command given, and determine whether the
- *     SCSI command is to be translated or simulated.
- *
- *     RETURNS:
- *     Pointer to translation function if possible, %NULL if not.
- */
-
-static inline ata_xlat_func_t ata_get_xlat_func(struct ata_device *dev, u8 cmd)
-{
-       switch (cmd) {
-       case READ_6:
-       case READ_10:
-       case READ_16:
-
-       case WRITE_6:
-       case WRITE_10:
-       case WRITE_16:
-               return ata_scsi_rw_xlat;
-
-       case SYNCHRONIZE_CACHE:
-               if (ata_try_flush_cache(dev))
-                       return ata_scsi_flush_xlat;
-               break;
-
-       case VERIFY:
-       case VERIFY_16:
-               return ata_scsi_verify_xlat;
-
-       case ATA_12:
-       case ATA_16:
-               return ata_scsi_pass_thru;
-
-       case START_STOP:
-               return ata_scsi_start_stop_xlat;
-       }
-
-       return NULL;
-}
-
-/**
- *     ata_scsi_dump_cdb - dump SCSI command contents to dmesg
- *     @ap: ATA port to which the command was being sent
- *     @cmd: SCSI command to dump
- *
- *     Prints the contents of a SCSI command via printk().
- */
-
-static inline void ata_scsi_dump_cdb(struct ata_port *ap,
-                                    struct scsi_cmnd *cmd)
-{
-#ifdef ATA_DEBUG
-       struct scsi_device *scsidev = cmd->device;
-       u8 *scsicmd = cmd->cmnd;
-
-       DPRINTK("CDB (%u:%d,%d,%d) %02x %02x %02x %02x %02x %02x %02x %02x %02x\n",
-               ap->id,
-               scsidev->channel, scsidev->id, scsidev->lun,
-               scsicmd[0], scsicmd[1], scsicmd[2], scsicmd[3],
-               scsicmd[4], scsicmd[5], scsicmd[6], scsicmd[7],
-               scsicmd[8]);
-#endif
-}
-
-static inline int __ata_scsi_queuecmd(struct scsi_cmnd *cmd,
-                                     void (*done)(struct scsi_cmnd *),
-                                     struct ata_device *dev)
-{
-       int rc = 0;
-
-       if (dev->class == ATA_DEV_ATA) {
-               ata_xlat_func_t xlat_func = ata_get_xlat_func(dev,
-                                                             cmd->cmnd[0]);
-
-               if (xlat_func)
-                       rc = ata_scsi_translate(dev, cmd, done, xlat_func);
-               else
-                       ata_scsi_simulate(dev, cmd, done);
-       } else
-               rc = ata_scsi_translate(dev, cmd, done, atapi_xlat);
-
-       return rc;
-}
-
-/**
- *     ata_scsi_queuecmd - Issue SCSI cdb to libata-managed device
- *     @cmd: SCSI command to be sent
- *     @done: Completion function, called when command is complete
- *
- *     In some cases, this function translates SCSI commands into
- *     ATA taskfiles, and queues the taskfiles to be sent to
- *     hardware.  In other cases, this function simulates a
- *     SCSI device by evaluating and responding to certain
- *     SCSI commands.  This creates the overall effect of
- *     ATA and ATAPI devices appearing as SCSI devices.
- *
- *     LOCKING:
- *     Releases scsi-layer-held lock, and obtains host_set lock.
- *
- *     RETURNS:
- *     Return value from __ata_scsi_queuecmd() if @cmd can be queued,
- *     0 otherwise.
- */
-int ata_scsi_queuecmd(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *))
-{
-       struct ata_port *ap;
-       struct ata_device *dev;
-       struct scsi_device *scsidev = cmd->device;
-       struct Scsi_Host *shost = scsidev->host;
-       int rc = 0;
-
-       ap = ata_shost_to_port(shost);
-
-       spin_unlock(shost->host_lock);
-       spin_lock(ap->lock);
-
-       ata_scsi_dump_cdb(ap, cmd);
-
-       dev = ata_scsi_find_dev(ap, scsidev);
-       if (likely(dev))
-               rc = __ata_scsi_queuecmd(cmd, done, dev);
-       else {
-               cmd->result = (DID_BAD_TARGET << 16);
-               done(cmd);
-       }
-
-       spin_unlock(ap->lock);
-       spin_lock(shost->host_lock);
-       return rc;
-}
-
-/**
- *     ata_scsi_simulate - simulate SCSI command on ATA device
- *     @dev: the target device
- *     @cmd: SCSI command being sent to device.
- *     @done: SCSI command completion function.
- *
- *     Interprets and directly executes a select list of SCSI commands
- *     that can be handled internally.
- *
- *     LOCKING:
- *     spin_lock_irqsave(host_set lock)
- */
-
-void ata_scsi_simulate(struct ata_device *dev, struct scsi_cmnd *cmd,
-                     void (*done)(struct scsi_cmnd *))
-{
-       struct ata_scsi_args args;
-       const u8 *scsicmd = cmd->cmnd;
-
-       args.dev = dev;
-       args.id = dev->id;
-       args.cmd = cmd;
-       args.done = done;
-
-       switch(scsicmd[0]) {
-               /* no-op's, complete with success */
-               case SYNCHRONIZE_CACHE:
-               case REZERO_UNIT:
-               case SEEK_6:
-               case SEEK_10:
-               case TEST_UNIT_READY:
-               case FORMAT_UNIT:               /* FIXME: correct? */
-               case SEND_DIAGNOSTIC:           /* FIXME: correct? */
-                       ata_scsi_rbuf_fill(&args, ata_scsiop_noop);
-                       break;
-
-               case INQUIRY:
-                       if (scsicmd[1] & 2)                /* is CmdDt set?  */
-                               ata_scsi_invalid_field(cmd, done);
-                       else if ((scsicmd[1] & 1) == 0)    /* is EVPD clear? */
-                               ata_scsi_rbuf_fill(&args, ata_scsiop_inq_std);
-                       else if (scsicmd[2] == 0x00)
-                               ata_scsi_rbuf_fill(&args, ata_scsiop_inq_00);
-                       else if (scsicmd[2] == 0x80)
-                               ata_scsi_rbuf_fill(&args, ata_scsiop_inq_80);
-                       else if (scsicmd[2] == 0x83)
-                               ata_scsi_rbuf_fill(&args, ata_scsiop_inq_83);
-                       else
-                               ata_scsi_invalid_field(cmd, done);
-                       break;
-
-               case MODE_SENSE:
-               case MODE_SENSE_10:
-                       ata_scsi_rbuf_fill(&args, ata_scsiop_mode_sense);
-                       break;
-
-               case MODE_SELECT:       /* unconditionally return */
-               case MODE_SELECT_10:    /* bad-field-in-cdb */
-                       ata_scsi_invalid_field(cmd, done);
-                       break;
-
-               case READ_CAPACITY:
-                       ata_scsi_rbuf_fill(&args, ata_scsiop_read_cap);
-                       break;
-
-               case SERVICE_ACTION_IN:
-                       if ((scsicmd[1] & 0x1f) == SAI_READ_CAPACITY_16)
-                               ata_scsi_rbuf_fill(&args, ata_scsiop_read_cap);
-                       else
-                               ata_scsi_invalid_field(cmd, done);
-                       break;
-
-               case REPORT_LUNS:
-                       ata_scsi_rbuf_fill(&args, ata_scsiop_report_luns);
-                       break;
-
-               /* mandatory commands we haven't implemented yet */
-               case REQUEST_SENSE:
-
-               /* all other commands */
-               default:
-                       ata_scsi_set_sense(cmd, ILLEGAL_REQUEST, 0x20, 0x0);
-                       /* "Invalid command operation code" */
-                       done(cmd);
-                       break;
-       }
-}
-
-void ata_scsi_scan_host(struct ata_port *ap)
-{
-       unsigned int i;
-
-       if (ap->flags & ATA_FLAG_DISABLED)
-               return;
-
-       for (i = 0; i < ATA_MAX_DEVICES; i++) {
-               struct ata_device *dev = &ap->device[i];
-               struct scsi_device *sdev;
-
-               if (!ata_dev_enabled(dev) || dev->sdev)
-                       continue;
-
-               sdev = __scsi_add_device(ap->host, 0, i, 0, NULL);
-               if (!IS_ERR(sdev)) {
-                       dev->sdev = sdev;
-                       scsi_device_put(sdev);
-               }
-       }
-}
-
-/**
- *     ata_scsi_offline_dev - offline attached SCSI device
- *     @dev: ATA device to offline attached SCSI device for
- *
- *     This function is called from ata_eh_hotplug() and responsible
- *     for taking the SCSI device attached to @dev offline.  This
- *     function is called with host_set lock which protects dev->sdev
- *     against clearing.
- *
- *     LOCKING:
- *     spin_lock_irqsave(host_set lock)
- *
- *     RETURNS:
- *     1 if attached SCSI device exists, 0 otherwise.
- */
-int ata_scsi_offline_dev(struct ata_device *dev)
-{
-       if (dev->sdev) {
-               scsi_device_set_state(dev->sdev, SDEV_OFFLINE);
-               return 1;
-       }
-       return 0;
-}
-
-/**
- *     ata_scsi_remove_dev - remove attached SCSI device
- *     @dev: ATA device to remove attached SCSI device for
- *
- *     This function is called from ata_eh_scsi_hotplug() and
- *     responsible for removing the SCSI device attached to @dev.
- *
- *     LOCKING:
- *     Kernel thread context (may sleep).
- */
-static void ata_scsi_remove_dev(struct ata_device *dev)
-{
-       struct ata_port *ap = dev->ap;
-       struct scsi_device *sdev;
-       unsigned long flags;
-
-       /* Alas, we need to grab scan_mutex to ensure SCSI device
-        * state doesn't change underneath us and thus
-        * scsi_device_get() always succeeds.  The mutex locking can
-        * be removed if there is __scsi_device_get() interface which
-        * increments reference counts regardless of device state.
-        */
-       mutex_lock(&ap->host->scan_mutex);
-       spin_lock_irqsave(ap->lock, flags);
-
-       /* clearing dev->sdev is protected by host_set lock */
-       sdev = dev->sdev;
-       dev->sdev = NULL;
-
-       if (sdev) {
-               /* If user initiated unplug races with us, sdev can go
-                * away underneath us after the host_set lock and
-                * scan_mutex are released.  Hold onto it.
-                */
-               if (scsi_device_get(sdev) == 0) {
-                       /* The following ensures the attached sdev is
-                        * offline on return from ata_scsi_offline_dev()
-                        * regardless it wins or loses the race
-                        * against this function.
-                        */
-                       scsi_device_set_state(sdev, SDEV_OFFLINE);
-               } else {
-                       WARN_ON(1);
-                       sdev = NULL;
-               }
-       }
-
-       spin_unlock_irqrestore(ap->lock, flags);
-       mutex_unlock(&ap->host->scan_mutex);
-
-       if (sdev) {
-               ata_dev_printk(dev, KERN_INFO, "detaching (SCSI %s)\n",
-                              sdev->sdev_gendev.bus_id);
-
-               scsi_remove_device(sdev);
-               scsi_device_put(sdev);
-       }
-}
-
-/**
- *     ata_scsi_hotplug - SCSI part of hotplug
- *     @data: Pointer to ATA port to perform SCSI hotplug on
- *
- *     Perform SCSI part of hotplug.  It's executed from a separate
- *     workqueue after EH completes.  This is necessary because SCSI
- *     hot plugging requires working EH and hot unplugging is
- *     synchronized with hot plugging with a mutex.
- *
- *     LOCKING:
- *     Kernel thread context (may sleep).
- */
-void ata_scsi_hotplug(void *data)
-{
-       struct ata_port *ap = data;
-       int i;
-
-       if (ap->pflags & ATA_PFLAG_UNLOADING) {
-               DPRINTK("ENTER/EXIT - unloading\n");
-               return;
-       }
-
-       DPRINTK("ENTER\n");
-
-       /* unplug detached devices */
-       for (i = 0; i < ATA_MAX_DEVICES; i++) {
-               struct ata_device *dev = &ap->device[i];
-               unsigned long flags;
-
-               if (!(dev->flags & ATA_DFLAG_DETACHED))
-                       continue;
-
-               spin_lock_irqsave(ap->lock, flags);
-               dev->flags &= ~ATA_DFLAG_DETACHED;
-               spin_unlock_irqrestore(ap->lock, flags);
-
-               ata_scsi_remove_dev(dev);
-       }
-
-       /* scan for new ones */
-       ata_scsi_scan_host(ap);
-
-       /* If we scanned while EH was in progress, scan would have
-        * failed silently.  Requeue if there are enabled but
-        * unattached devices.
-        */
-       for (i = 0; i < ATA_MAX_DEVICES; i++) {
-               struct ata_device *dev = &ap->device[i];
-               if (ata_dev_enabled(dev) && !dev->sdev) {
-                       queue_delayed_work(ata_aux_wq, &ap->hotplug_task, HZ);
-                       break;
-               }
-       }
-
-       DPRINTK("EXIT\n");
-}
-
-/**
- *     ata_scsi_user_scan - indication for user-initiated bus scan
- *     @shost: SCSI host to scan
- *     @channel: Channel to scan
- *     @id: ID to scan
- *     @lun: LUN to scan
- *
- *     This function is called when user explicitly requests bus
- *     scan.  Set probe pending flag and invoke EH.
- *
- *     LOCKING:
- *     SCSI layer (we don't care)
- *
- *     RETURNS:
- *     Zero.
- */
-static int ata_scsi_user_scan(struct Scsi_Host *shost, unsigned int channel,
-                             unsigned int id, unsigned int lun)
-{
-       struct ata_port *ap = ata_shost_to_port(shost);
-       unsigned long flags;
-       int rc = 0;
-
-       if (!ap->ops->error_handler)
-               return -EOPNOTSUPP;
-
-       if ((channel != SCAN_WILD_CARD && channel != 0) ||
-           (lun != SCAN_WILD_CARD && lun != 0))
-               return -EINVAL;
-
-       spin_lock_irqsave(ap->lock, flags);
-
-       if (id == SCAN_WILD_CARD) {
-               ap->eh_info.probe_mask |= (1 << ATA_MAX_DEVICES) - 1;
-               ap->eh_info.action |= ATA_EH_SOFTRESET;
-       } else {
-               struct ata_device *dev = ata_find_dev(ap, id);
-
-               if (dev) {
-                       ap->eh_info.probe_mask |= 1 << dev->devno;
-                       ap->eh_info.action |= ATA_EH_SOFTRESET;
-                       ap->eh_info.flags |= ATA_EHI_RESUME_LINK;
-               } else
-                       rc = -EINVAL;
-       }
-
-       if (rc == 0)
-               ata_port_schedule_eh(ap);
-
-       spin_unlock_irqrestore(ap->lock, flags);
-
-       return rc;
-}
-
-/**
- *     ata_scsi_dev_rescan - initiate scsi_rescan_device()
- *     @data: Pointer to ATA port to perform scsi_rescan_device()
- *
- *     After ATA pass thru (SAT) commands are executed successfully,
- *     libata need to propagate the changes to SCSI layer.  This
- *     function must be executed from ata_aux_wq such that sdev
- *     attach/detach don't race with rescan.
- *
- *     LOCKING:
- *     Kernel thread context (may sleep).
- */
-void ata_scsi_dev_rescan(void *data)
-{
-       struct ata_port *ap = data;
-       struct ata_device *dev;
-       unsigned int i;
-
-       for (i = 0; i < ATA_MAX_DEVICES; i++) {
-               dev = &ap->device[i];
-
-               if (ata_dev_enabled(dev) && dev->sdev)
-                       scsi_rescan_device(&(dev->sdev->sdev_gendev));
-       }
-}
-
-/**
- *     ata_sas_port_alloc - Allocate port for a SAS attached SATA device
- *     @pdev: PCI device that the scsi device is attached to
- *     @port_info: Information from low-level host driver
- *     @host: SCSI host that the scsi device is attached to
- *
- *     LOCKING:
- *     PCI/etc. bus probe sem.
- *
- *     RETURNS:
- *     ata_port pointer on success / NULL on failure.
- */
-
-struct ata_port *ata_sas_port_alloc(struct ata_host_set *host_set,
-                                   struct ata_port_info *port_info,
-                                   struct Scsi_Host *host)
-{
-       struct ata_port *ap = kzalloc(sizeof(*ap), GFP_KERNEL);
-       struct ata_probe_ent *ent;
-
-       if (!ap)
-               return NULL;
-
-       ent = ata_probe_ent_alloc(host_set->dev, port_info);
-       if (!ent) {
-               kfree(ap);
-               return NULL;
-       }
-
-       ata_port_init(ap, host_set, ent, 0);
-       ap->lock = host->host_lock;
-       kfree(ent);
-       return ap;
-}
-EXPORT_SYMBOL_GPL(ata_sas_port_alloc);
-
-/**
- *     ata_sas_port_start - Set port up for dma.
- *     @ap: Port to initialize
- *
- *     Called just after data structures for each port are
- *     initialized.  Allocates DMA pad.
- *
- *     May be used as the port_start() entry in ata_port_operations.
- *
- *     LOCKING:
- *     Inherited from caller.
- */
-int ata_sas_port_start(struct ata_port *ap)
-{
-       return ata_pad_alloc(ap, ap->dev);
-}
-EXPORT_SYMBOL_GPL(ata_sas_port_start);
-
-/**
- *     ata_port_stop - Undo ata_sas_port_start()
- *     @ap: Port to shut down
- *
- *     Frees the DMA pad.
- *
- *     May be used as the port_stop() entry in ata_port_operations.
- *
- *     LOCKING:
- *     Inherited from caller.
- */
-
-void ata_sas_port_stop(struct ata_port *ap)
-{
-       ata_pad_free(ap, ap->dev);
-}
-EXPORT_SYMBOL_GPL(ata_sas_port_stop);
-
-/**
- *     ata_sas_port_init - Initialize a SATA device
- *     @ap: SATA port to initialize
- *
- *     LOCKING:
- *     PCI/etc. bus probe sem.
- *
- *     RETURNS:
- *     Zero on success, non-zero on error.
- */
-
-int ata_sas_port_init(struct ata_port *ap)
-{
-       int rc = ap->ops->port_start(ap);
-
-       if (!rc)
-               rc = ata_bus_probe(ap);
-
-       return rc;
-}
-EXPORT_SYMBOL_GPL(ata_sas_port_init);
-
-/**
- *     ata_sas_port_destroy - Destroy a SATA port allocated by ata_sas_port_alloc
- *     @ap: SATA port to destroy
- *
- */
-
-void ata_sas_port_destroy(struct ata_port *ap)
-{
-       ap->ops->port_stop(ap);
-       kfree(ap);
-}
-EXPORT_SYMBOL_GPL(ata_sas_port_destroy);
-
-/**
- *     ata_sas_slave_configure - Default slave_config routine for libata devices
- *     @sdev: SCSI device to configure
- *     @ap: ATA port to which SCSI device is attached
- *
- *     RETURNS:
- *     Zero.
- */
-
-int ata_sas_slave_configure(struct scsi_device *sdev, struct ata_port *ap)
-{
-       ata_scsi_sdev_config(sdev);
-       ata_scsi_dev_config(sdev, ap->device);
-       return 0;
-}
-EXPORT_SYMBOL_GPL(ata_sas_slave_configure);
-
-/**
- *     ata_sas_queuecmd - Issue SCSI cdb to libata-managed device
- *     @cmd: SCSI command to be sent
- *     @done: Completion function, called when command is complete
- *     @ap:    ATA port to which the command is being sent
- *
- *     RETURNS:
- *     Zero.
- */
-
-int ata_sas_queuecmd(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *),
-                    struct ata_port *ap)
-{
-       ata_scsi_dump_cdb(ap, cmd);
-
-       if (likely(ata_scsi_dev_enabled(ap->device)))
-               __ata_scsi_queuecmd(cmd, done, ap->device);
-       else {
-               cmd->result = (DID_BAD_TARGET << 16);
-               done(cmd);
-       }
-       return 0;
-}
-EXPORT_SYMBOL_GPL(ata_sas_queuecmd);
diff --git a/drivers/scsi/libata.h b/drivers/scsi/libata.h
deleted file mode 100644 (file)
index d4a4f82..0000000
+++ /dev/null
@@ -1,122 +0,0 @@
-/*
- *  libata.h - helper library for ATA
- *
- *  Copyright 2003-2004 Red Hat, Inc.  All rights reserved.
- *  Copyright 2003-2004 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.*
- *
- */
-
-#ifndef __LIBATA_H__
-#define __LIBATA_H__
-
-#define DRV_NAME       "libata"
-#define DRV_VERSION    "2.00"  /* must be exactly four chars */
-
-struct ata_scsi_args {
-       struct ata_device       *dev;
-       u16                     *id;
-       struct scsi_cmnd        *cmd;
-       void                    (*done)(struct scsi_cmnd *);
-};
-
-/* libata-core.c */
-extern struct workqueue_struct *ata_aux_wq;
-extern int atapi_enabled;
-extern int atapi_dmadir;
-extern int libata_fua;
-extern struct ata_queued_cmd *ata_qc_new_init(struct ata_device *dev);
-extern int ata_rwcmd_protocol(struct ata_queued_cmd *qc);
-extern void ata_dev_disable(struct ata_device *dev);
-extern void ata_port_flush_task(struct ata_port *ap);
-extern unsigned ata_exec_internal(struct ata_device *dev,
-                                 struct ata_taskfile *tf, const u8 *cdb,
-                                 int dma_dir, void *buf, unsigned int buflen);
-extern unsigned int ata_do_simple_cmd(struct ata_device *dev, u8 cmd);
-extern int ata_dev_read_id(struct ata_device *dev, unsigned int *p_class,
-                          int post_reset, u16 *id);
-extern int ata_dev_configure(struct ata_device *dev, int print_info);
-extern int sata_down_spd_limit(struct ata_port *ap);
-extern int sata_set_spd_needed(struct ata_port *ap);
-extern int ata_down_xfermask_limit(struct ata_device *dev, int force_pio0);
-extern int ata_set_mode(struct ata_port *ap, struct ata_device **r_failed_dev);
-extern void ata_qc_free(struct ata_queued_cmd *qc);
-extern void ata_qc_issue(struct ata_queued_cmd *qc);
-extern void __ata_qc_complete(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);
-extern void swap_buf_le16(u16 *buf, unsigned int buf_words);
-extern int ata_flush_cache(struct ata_device *dev);
-extern void ata_dev_init(struct ata_device *dev);
-extern int ata_task_ioctl(struct scsi_device *scsidev, void __user *arg);
-extern int ata_cmd_ioctl(struct scsi_device *scsidev, void __user *arg);
-extern void ata_port_init(struct ata_port *ap, struct ata_host_set *host_set,
-                         const struct ata_probe_ent *ent, unsigned int port_no);
-extern struct ata_probe_ent *ata_probe_ent_alloc(struct device *dev,
-                                                const struct ata_port_info *port);
-
-
-/* libata-scsi.c */
-extern struct scsi_transport_template ata_scsi_transport_template;
-
-extern void ata_scsi_scan_host(struct ata_port *ap);
-extern int ata_scsi_offline_dev(struct ata_device *dev);
-extern void ata_scsi_hotplug(void *data);
-extern unsigned int ata_scsiop_inq_std(struct ata_scsi_args *args, u8 *rbuf,
-                              unsigned int buflen);
-
-extern unsigned int ata_scsiop_inq_00(struct ata_scsi_args *args, u8 *rbuf,
-                             unsigned int buflen);
-
-extern unsigned int ata_scsiop_inq_80(struct ata_scsi_args *args, u8 *rbuf,
-                             unsigned int buflen);
-extern unsigned int ata_scsiop_inq_83(struct ata_scsi_args *args, u8 *rbuf,
-                             unsigned int buflen);
-extern unsigned int ata_scsiop_noop(struct ata_scsi_args *args, u8 *rbuf,
-                           unsigned int buflen);
-extern unsigned int ata_scsiop_sync_cache(struct ata_scsi_args *args, u8 *rbuf,
-                                 unsigned int buflen);
-extern unsigned int ata_scsiop_mode_sense(struct ata_scsi_args *args, u8 *rbuf,
-                                 unsigned int buflen);
-extern unsigned int ata_scsiop_read_cap(struct ata_scsi_args *args, u8 *rbuf,
-                               unsigned int buflen);
-extern unsigned int ata_scsiop_report_luns(struct ata_scsi_args *args, u8 *rbuf,
-                                  unsigned int buflen);
-extern void ata_scsi_badcmd(struct scsi_cmnd *cmd,
-                           void (*done)(struct scsi_cmnd *),
-                           u8 asc, u8 ascq);
-extern void ata_scsi_set_sense(struct scsi_cmnd *cmd,
-                              u8 sk, u8 asc, u8 ascq);
-extern void ata_scsi_rbuf_fill(struct ata_scsi_args *args,
-                        unsigned int (*actor) (struct ata_scsi_args *args,
-                                           u8 *rbuf, unsigned int buflen));
-extern void ata_schedule_scsi_eh(struct Scsi_Host *shost);
-extern void ata_scsi_dev_rescan(void *data);
-extern int ata_bus_probe(struct ata_port *ap);
-
-/* libata-eh.c */
-extern enum scsi_eh_timer_return ata_scsi_timed_out(struct scsi_cmnd *cmd);
-extern void ata_scsi_error(struct Scsi_Host *host);
-extern void ata_port_wait_eh(struct ata_port *ap);
-extern void ata_qc_schedule_eh(struct ata_queued_cmd *qc);
-
-#endif /* __LIBATA_H__ */
diff --git a/drivers/scsi/pdc_adma.c b/drivers/scsi/pdc_adma.c
deleted file mode 100644 (file)
index 61d2aa6..0000000
+++ /dev/null
@@ -1,740 +0,0 @@
-/*
- *  pdc_adma.c - Pacific Digital Corporation ADMA
- *
- *  Maintained by:  Mark Lord <mlord@pobox.com>
- *
- *  Copyright 2005 Mark Lord
- *
- *  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.*
- *
- *
- *  Supports ATA disks in single-packet ADMA mode.
- *  Uses PIO for everything else.
- *
- *  TODO:  Use ADMA transfers for ATAPI devices, when possible.
- *  This requires careful attention to a number of quirks of the chip.
- *
- */
-
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/pci.h>
-#include <linux/init.h>
-#include <linux/blkdev.h>
-#include <linux/delay.h>
-#include <linux/interrupt.h>
-#include <linux/sched.h>
-#include <linux/device.h>
-#include <scsi/scsi_host.h>
-#include <asm/io.h>
-#include <linux/libata.h>
-
-#define DRV_NAME       "pdc_adma"
-#define DRV_VERSION    "0.04"
-
-/* macro to calculate base address for ATA regs */
-#define ADMA_ATA_REGS(base,port_no)    ((base) + ((port_no) * 0x40))
-
-/* macro to calculate base address for ADMA regs */
-#define ADMA_REGS(base,port_no)        ((base) + 0x80 + ((port_no) * 0x20))
-
-enum {
-       ADMA_PORTS              = 2,
-       ADMA_CPB_BYTES          = 40,
-       ADMA_PRD_BYTES          = LIBATA_MAX_PRD * 16,
-       ADMA_PKT_BYTES          = ADMA_CPB_BYTES + ADMA_PRD_BYTES,
-
-       ADMA_DMA_BOUNDARY       = 0xffffffff,
-
-       /* global register offsets */
-       ADMA_MODE_LOCK          = 0x00c7,
-
-       /* per-channel register offsets */
-       ADMA_CONTROL            = 0x0000, /* ADMA control */
-       ADMA_STATUS             = 0x0002, /* ADMA status */
-       ADMA_CPB_COUNT          = 0x0004, /* CPB count */
-       ADMA_CPB_CURRENT        = 0x000c, /* current CPB address */
-       ADMA_CPB_NEXT           = 0x000c, /* next CPB address */
-       ADMA_CPB_LOOKUP         = 0x0010, /* CPB lookup table */
-       ADMA_FIFO_IN            = 0x0014, /* input FIFO threshold */
-       ADMA_FIFO_OUT           = 0x0016, /* output FIFO threshold */
-
-       /* ADMA_CONTROL register bits */
-       aNIEN                   = (1 << 8), /* irq mask: 1==masked */
-       aGO                     = (1 << 7), /* packet trigger ("Go!") */
-       aRSTADM                 = (1 << 5), /* ADMA logic reset */
-       aPIOMD4                 = 0x0003,   /* PIO mode 4 */
-
-       /* ADMA_STATUS register bits */
-       aPSD                    = (1 << 6),
-       aUIRQ                   = (1 << 4),
-       aPERR                   = (1 << 0),
-
-       /* CPB bits */
-       cDONE                   = (1 << 0),
-       cVLD                    = (1 << 0),
-       cDAT                    = (1 << 2),
-       cIEN                    = (1 << 3),
-
-       /* PRD bits */
-       pORD                    = (1 << 4),
-       pDIRO                   = (1 << 5),
-       pEND                    = (1 << 7),
-
-       /* ATA register flags */
-       rIGN                    = (1 << 5),
-       rEND                    = (1 << 7),
-
-       /* ATA register addresses */
-       ADMA_REGS_CONTROL       = 0x0e,
-       ADMA_REGS_SECTOR_COUNT  = 0x12,
-       ADMA_REGS_LBA_LOW       = 0x13,
-       ADMA_REGS_LBA_MID       = 0x14,
-       ADMA_REGS_LBA_HIGH      = 0x15,
-       ADMA_REGS_DEVICE        = 0x16,
-       ADMA_REGS_COMMAND       = 0x17,
-
-       /* PCI device IDs */
-       board_1841_idx          = 0,    /* ADMA 2-port controller */
-};
-
-typedef enum { adma_state_idle, adma_state_pkt, adma_state_mmio } adma_state_t;
-
-struct adma_port_priv {
-       u8                      *pkt;
-       dma_addr_t              pkt_dma;
-       adma_state_t            state;
-};
-
-static int adma_ata_init_one (struct pci_dev *pdev,
-                               const struct pci_device_id *ent);
-static irqreturn_t adma_intr (int irq, void *dev_instance,
-                               struct pt_regs *regs);
-static int adma_port_start(struct ata_port *ap);
-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 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);
-static void adma_irq_clear(struct ata_port *ap);
-static void adma_eng_timeout(struct ata_port *ap);
-
-static struct scsi_host_template adma_ata_sht = {
-       .module                 = THIS_MODULE,
-       .name                   = DRV_NAME,
-       .ioctl                  = ata_scsi_ioctl,
-       .queuecommand           = ata_scsi_queuecmd,
-       .can_queue              = ATA_DEF_QUEUE,
-       .this_id                = ATA_SHT_THIS_ID,
-       .sg_tablesize           = LIBATA_MAX_PRD,
-       .cmd_per_lun            = ATA_SHT_CMD_PER_LUN,
-       .emulated               = ATA_SHT_EMULATED,
-       .use_clustering         = ENABLE_CLUSTERING,
-       .proc_name              = DRV_NAME,
-       .dma_boundary           = ADMA_DMA_BOUNDARY,
-       .slave_configure        = ata_scsi_slave_config,
-       .slave_destroy          = ata_scsi_slave_destroy,
-       .bios_param             = ata_std_bios_param,
-};
-
-static const struct ata_port_operations adma_ata_ops = {
-       .port_disable           = ata_port_disable,
-       .tf_load                = ata_tf_load,
-       .tf_read                = ata_tf_read,
-       .check_status           = ata_check_status,
-       .check_atapi_dma        = adma_check_atapi_dma,
-       .exec_command           = ata_exec_command,
-       .dev_select             = ata_std_dev_select,
-       .phy_reset              = adma_phy_reset,
-       .qc_prep                = adma_qc_prep,
-       .qc_issue               = adma_qc_issue,
-       .eng_timeout            = adma_eng_timeout,
-       .data_xfer              = ata_mmio_data_xfer,
-       .irq_handler            = adma_intr,
-       .irq_clear              = adma_irq_clear,
-       .port_start             = adma_port_start,
-       .port_stop              = adma_port_stop,
-       .host_stop              = adma_host_stop,
-       .bmdma_stop             = adma_bmdma_stop,
-       .bmdma_status           = adma_bmdma_status,
-};
-
-static struct ata_port_info adma_port_info[] = {
-       /* board_1841_idx */
-       {
-               .sht            = &adma_ata_sht,
-               .host_flags     = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST |
-                                 ATA_FLAG_NO_LEGACY | ATA_FLAG_MMIO |
-                                 ATA_FLAG_PIO_POLLING,
-               .pio_mask       = 0x10, /* pio4 */
-               .udma_mask      = 0x1f, /* udma0-4 */
-               .port_ops       = &adma_ata_ops,
-       },
-};
-
-static const struct pci_device_id adma_ata_pci_tbl[] = {
-       { PCI_VENDOR_ID_PDC, 0x1841, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-         board_1841_idx },
-
-       { }     /* terminate list */
-};
-
-static struct pci_driver adma_ata_pci_driver = {
-       .name                   = DRV_NAME,
-       .id_table               = adma_ata_pci_tbl,
-       .probe                  = adma_ata_init_one,
-       .remove                 = ata_pci_remove_one,
-};
-
-static int adma_check_atapi_dma(struct ata_queued_cmd *qc)
-{
-       return 1;       /* ATAPI DMA not yet supported */
-}
-
-static void adma_bmdma_stop(struct ata_queued_cmd *qc)
-{
-       /* nothing */
-}
-
-static u8 adma_bmdma_status(struct ata_port *ap)
-{
-       return 0;
-}
-
-static void adma_irq_clear(struct ata_port *ap)
-{
-       /* nothing */
-}
-
-static void adma_reset_engine(void __iomem *chan)
-{
-       /* reset ADMA to idle state */
-       writew(aPIOMD4 | aNIEN | aRSTADM, chan + ADMA_CONTROL);
-       udelay(2);
-       writew(aPIOMD4, chan + ADMA_CONTROL);
-       udelay(2);
-}
-
-static void adma_reinit_engine(struct ata_port *ap)
-{
-       struct adma_port_priv *pp = ap->private_data;
-       void __iomem *mmio_base = ap->host_set->mmio_base;
-       void __iomem *chan = ADMA_REGS(mmio_base, ap->port_no);
-
-       /* mask/clear ATA interrupts */
-       writeb(ATA_NIEN, (void __iomem *)ap->ioaddr.ctl_addr);
-       ata_check_status(ap);
-
-       /* reset the ADMA engine */
-       adma_reset_engine(chan);
-
-       /* set in-FIFO threshold to 0x100 */
-       writew(0x100, chan + ADMA_FIFO_IN);
-
-       /* set CPB pointer */
-       writel((u32)pp->pkt_dma, chan + ADMA_CPB_NEXT);
-
-       /* set out-FIFO threshold to 0x100 */
-       writew(0x100, chan + ADMA_FIFO_OUT);
-
-       /* set CPB count */
-       writew(1, chan + ADMA_CPB_COUNT);
-
-       /* read/discard ADMA status */
-       readb(chan + ADMA_STATUS);
-}
-
-static inline void adma_enter_reg_mode(struct ata_port *ap)
-{
-       void __iomem *chan = ADMA_REGS(ap->host_set->mmio_base, ap->port_no);
-
-       writew(aPIOMD4, chan + ADMA_CONTROL);
-       readb(chan + ADMA_STATUS);      /* flush */
-}
-
-static void adma_phy_reset(struct ata_port *ap)
-{
-       struct adma_port_priv *pp = ap->private_data;
-
-       pp->state = adma_state_idle;
-       adma_reinit_engine(ap);
-       ata_port_probe(ap);
-       ata_bus_reset(ap);
-}
-
-static void adma_eng_timeout(struct ata_port *ap)
-{
-       struct adma_port_priv *pp = ap->private_data;
-
-       if (pp->state != adma_state_idle) /* healthy paranoia */
-               pp->state = adma_state_mmio;
-       adma_reinit_engine(ap);
-       ata_eng_timeout(ap);
-}
-
-static int adma_fill_sg(struct ata_queued_cmd *qc)
-{
-       struct scatterlist *sg;
-       struct ata_port *ap = qc->ap;
-       struct adma_port_priv *pp = ap->private_data;
-       u8  *buf = pp->pkt;
-       int i = (2 + buf[3]) * 8;
-       u8 pFLAGS = pORD | ((qc->tf.flags & ATA_TFLAG_WRITE) ? pDIRO : 0);
-
-       ata_for_each_sg(sg, qc) {
-               u32 addr;
-               u32 len;
-
-               addr = (u32)sg_dma_address(sg);
-               *(__le32 *)(buf + i) = cpu_to_le32(addr);
-               i += 4;
-
-               len = sg_dma_len(sg) >> 3;
-               *(__le32 *)(buf + i) = cpu_to_le32(len);
-               i += 4;
-
-               if (ata_sg_is_last(sg, qc))
-                       pFLAGS |= pEND;
-               buf[i++] = pFLAGS;
-               buf[i++] = qc->dev->dma_mode & 0xf;
-               buf[i++] = 0;   /* pPKLW */
-               buf[i++] = 0;   /* reserved */
-
-               *(__le32 *)(buf + i)
-                       = (pFLAGS & pEND) ? 0 : cpu_to_le32(pp->pkt_dma + i + 4);
-               i += 4;
-
-               VPRINTK("PRD[%u] = (0x%lX, 0x%X)\n", i/4,
-                                       (unsigned long)addr, len);
-       }
-       return i;
-}
-
-static void adma_qc_prep(struct ata_queued_cmd *qc)
-{
-       struct adma_port_priv *pp = qc->ap->private_data;
-       u8  *buf = pp->pkt;
-       u32 pkt_dma = (u32)pp->pkt_dma;
-       int i = 0;
-
-       VPRINTK("ENTER\n");
-
-       adma_enter_reg_mode(qc->ap);
-       if (qc->tf.protocol != ATA_PROT_DMA) {
-               ata_qc_prep(qc);
-               return;
-       }
-
-       buf[i++] = 0;   /* Response flags */
-       buf[i++] = 0;   /* reserved */
-       buf[i++] = cVLD | cDAT | cIEN;
-       i++;            /* cLEN, gets filled in below */
-
-       *(__le32 *)(buf+i) = cpu_to_le32(pkt_dma);      /* cNCPB */
-       i += 4;         /* cNCPB */
-       i += 4;         /* cPRD, gets filled in below */
-
-       buf[i++] = 0;   /* reserved */
-       buf[i++] = 0;   /* reserved */
-       buf[i++] = 0;   /* reserved */
-       buf[i++] = 0;   /* reserved */
-
-       /* ATA registers; must be a multiple of 4 */
-       buf[i++] = qc->tf.device;
-       buf[i++] = ADMA_REGS_DEVICE;
-       if ((qc->tf.flags & ATA_TFLAG_LBA48)) {
-               buf[i++] = qc->tf.hob_nsect;
-               buf[i++] = ADMA_REGS_SECTOR_COUNT;
-               buf[i++] = qc->tf.hob_lbal;
-               buf[i++] = ADMA_REGS_LBA_LOW;
-               buf[i++] = qc->tf.hob_lbam;
-               buf[i++] = ADMA_REGS_LBA_MID;
-               buf[i++] = qc->tf.hob_lbah;
-               buf[i++] = ADMA_REGS_LBA_HIGH;
-       }
-       buf[i++] = qc->tf.nsect;
-       buf[i++] = ADMA_REGS_SECTOR_COUNT;
-       buf[i++] = qc->tf.lbal;
-       buf[i++] = ADMA_REGS_LBA_LOW;
-       buf[i++] = qc->tf.lbam;
-       buf[i++] = ADMA_REGS_LBA_MID;
-       buf[i++] = qc->tf.lbah;
-       buf[i++] = ADMA_REGS_LBA_HIGH;
-       buf[i++] = 0;
-       buf[i++] = ADMA_REGS_CONTROL;
-       buf[i++] = rIGN;
-       buf[i++] = 0;
-       buf[i++] = qc->tf.command;
-       buf[i++] = ADMA_REGS_COMMAND | rEND;
-
-       buf[3] = (i >> 3) - 2;                          /* cLEN */
-       *(__le32 *)(buf+8) = cpu_to_le32(pkt_dma + i);  /* cPRD */
-
-       i = adma_fill_sg(qc);
-       wmb();  /* flush PRDs and pkt to memory */
-#if 0
-       /* dump out CPB + PRDs for debug */
-       {
-               int j, len = 0;
-               static char obuf[2048];
-               for (j = 0; j < i; ++j) {
-                       len += sprintf(obuf+len, "%02x ", buf[j]);
-                       if ((j & 7) == 7) {
-                               printk("%s\n", obuf);
-                               len = 0;
-                       }
-               }
-               if (len)
-                       printk("%s\n", obuf);
-       }
-#endif
-}
-
-static inline void adma_packet_start(struct ata_queued_cmd *qc)
-{
-       struct ata_port *ap = qc->ap;
-       void __iomem *chan = ADMA_REGS(ap->host_set->mmio_base, ap->port_no);
-
-       VPRINTK("ENTER, ap %p\n", ap);
-
-       /* fire up the ADMA engine */
-       writew(aPIOMD4 | aGO, chan + ADMA_CONTROL);
-}
-
-static unsigned int adma_qc_issue(struct ata_queued_cmd *qc)
-{
-       struct adma_port_priv *pp = qc->ap->private_data;
-
-       switch (qc->tf.protocol) {
-       case ATA_PROT_DMA:
-               pp->state = adma_state_pkt;
-               adma_packet_start(qc);
-               return 0;
-
-       case ATA_PROT_ATAPI_DMA:
-               BUG();
-               break;
-
-       default:
-               break;
-       }
-
-       pp->state = adma_state_mmio;
-       return ata_qc_issue_prot(qc);
-}
-
-static inline unsigned int adma_intr_pkt(struct ata_host_set *host_set)
-{
-       unsigned int handled = 0, port_no;
-       u8 __iomem *mmio_base = host_set->mmio_base;
-
-       for (port_no = 0; port_no < host_set->n_ports; ++port_no) {
-               struct ata_port *ap = host_set->ports[port_no];
-               struct adma_port_priv *pp;
-               struct ata_queued_cmd *qc;
-               void __iomem *chan = ADMA_REGS(mmio_base, port_no);
-               u8 status = readb(chan + ADMA_STATUS);
-
-               if (status == 0)
-                       continue;
-               handled = 1;
-               adma_enter_reg_mode(ap);
-               if (ap->flags & ATA_FLAG_DISABLED)
-                       continue;
-               pp = ap->private_data;
-               if (!pp || pp->state != adma_state_pkt)
-                       continue;
-               qc = ata_qc_from_tag(ap, ap->active_tag);
-               if (qc && (!(qc->tf.flags & ATA_TFLAG_POLLING))) {
-                       if ((status & (aPERR | aPSD | aUIRQ)))
-                               qc->err_mask |= AC_ERR_OTHER;
-                       else if (pp->pkt[0] != cDONE)
-                               qc->err_mask |= AC_ERR_OTHER;
-
-                       ata_qc_complete(qc);
-               }
-       }
-       return handled;
-}
-
-static inline unsigned int adma_intr_mmio(struct ata_host_set *host_set)
-{
-       unsigned int handled = 0, port_no;
-
-       for (port_no = 0; port_no < host_set->n_ports; ++port_no) {
-               struct ata_port *ap;
-               ap = host_set->ports[port_no];
-               if (ap && (!(ap->flags & ATA_FLAG_DISABLED))) {
-                       struct ata_queued_cmd *qc;
-                       struct adma_port_priv *pp = ap->private_data;
-                       if (!pp || pp->state != adma_state_mmio)
-                               continue;
-                       qc = ata_qc_from_tag(ap, ap->active_tag);
-                       if (qc && (!(qc->tf.flags & ATA_TFLAG_POLLING))) {
-
-                               /* check main status, clearing INTRQ */
-                               u8 status = ata_check_status(ap);
-                               if ((status & ATA_BUSY))
-                                       continue;
-                               DPRINTK("ata%u: protocol %d (dev_stat 0x%X)\n",
-                                       ap->id, qc->tf.protocol, status);
-               
-                               /* complete taskfile transaction */
-                               pp->state = adma_state_idle;
-                               qc->err_mask |= ac_err_mask(status);
-                               ata_qc_complete(qc);
-                               handled = 1;
-                       }
-               }
-       }
-       return handled;
-}
-
-static irqreturn_t adma_intr(int irq, void *dev_instance, struct pt_regs *regs)
-{
-       struct ata_host_set *host_set = dev_instance;
-       unsigned int handled = 0;
-
-       VPRINTK("ENTER\n");
-
-       spin_lock(&host_set->lock);
-       handled  = adma_intr_pkt(host_set) | adma_intr_mmio(host_set);
-       spin_unlock(&host_set->lock);
-
-       VPRINTK("EXIT\n");
-
-       return IRQ_RETVAL(handled);
-}
-
-static void adma_ata_setup_port(struct ata_ioports *port, unsigned long base)
-{
-       port->cmd_addr          =
-       port->data_addr         = base + 0x000;
-       port->error_addr        =
-       port->feature_addr      = base + 0x004;
-       port->nsect_addr        = base + 0x008;
-       port->lbal_addr         = base + 0x00c;
-       port->lbam_addr         = base + 0x010;
-       port->lbah_addr         = base + 0x014;
-       port->device_addr       = base + 0x018;
-       port->status_addr       =
-       port->command_addr      = base + 0x01c;
-       port->altstatus_addr    =
-       port->ctl_addr          = base + 0x038;
-}
-
-static int adma_port_start(struct ata_port *ap)
-{
-       struct device *dev = ap->host_set->dev;
-       struct adma_port_priv *pp;
-       int rc;
-
-       rc = ata_port_start(ap);
-       if (rc)
-               return rc;
-       adma_enter_reg_mode(ap);
-       rc = -ENOMEM;
-       pp = kcalloc(1, sizeof(*pp), GFP_KERNEL);
-       if (!pp)
-               goto err_out;
-       pp->pkt = dma_alloc_coherent(dev, ADMA_PKT_BYTES, &pp->pkt_dma,
-                                                               GFP_KERNEL);
-       if (!pp->pkt)
-               goto err_out_kfree;
-       /* paranoia? */
-       if ((pp->pkt_dma & 7) != 0) {
-               printk("bad alignment for pp->pkt_dma: %08x\n",
-                                               (u32)pp->pkt_dma);
-               dma_free_coherent(dev, ADMA_PKT_BYTES,
-                                               pp->pkt, pp->pkt_dma);
-               goto err_out_kfree;
-       }
-       memset(pp->pkt, 0, ADMA_PKT_BYTES);
-       ap->private_data = pp;
-       adma_reinit_engine(ap);
-       return 0;
-
-err_out_kfree:
-       kfree(pp);
-err_out:
-       ata_port_stop(ap);
-       return rc;
-}
-
-static void adma_port_stop(struct ata_port *ap)
-{
-       struct device *dev = ap->host_set->dev;
-       struct adma_port_priv *pp = ap->private_data;
-
-       adma_reset_engine(ADMA_REGS(ap->host_set->mmio_base, ap->port_no));
-       if (pp != NULL) {
-               ap->private_data = NULL;
-               if (pp->pkt != NULL)
-                       dma_free_coherent(dev, ADMA_PKT_BYTES,
-                                       pp->pkt, pp->pkt_dma);
-               kfree(pp);
-       }
-       ata_port_stop(ap);
-}
-
-static void adma_host_stop(struct ata_host_set *host_set)
-{
-       unsigned int port_no;
-
-       for (port_no = 0; port_no < ADMA_PORTS; ++port_no)
-               adma_reset_engine(ADMA_REGS(host_set->mmio_base, port_no));
-
-       ata_pci_host_stop(host_set);
-}
-
-static void adma_host_init(unsigned int chip_id,
-                               struct ata_probe_ent *probe_ent)
-{
-       unsigned int port_no;
-       void __iomem *mmio_base = probe_ent->mmio_base;
-
-       /* enable/lock aGO operation */
-       writeb(7, mmio_base + ADMA_MODE_LOCK);
-
-       /* reset the ADMA logic */
-       for (port_no = 0; port_no < ADMA_PORTS; ++port_no)
-               adma_reset_engine(ADMA_REGS(mmio_base, port_no));
-}
-
-static int adma_set_dma_masks(struct pci_dev *pdev, void __iomem *mmio_base)
-{
-       int rc;
-
-       rc = pci_set_dma_mask(pdev, DMA_32BIT_MASK);
-       if (rc) {
-               dev_printk(KERN_ERR, &pdev->dev,
-                       "32-bit DMA enable failed\n");
-               return rc;
-       }
-       rc = pci_set_consistent_dma_mask(pdev, DMA_32BIT_MASK);
-       if (rc) {
-               dev_printk(KERN_ERR, &pdev->dev,
-                       "32-bit consistent DMA enable failed\n");
-               return rc;
-       }
-       return 0;
-}
-
-static int adma_ata_init_one(struct pci_dev *pdev,
-                               const struct pci_device_id *ent)
-{
-       static int printed_version;
-       struct ata_probe_ent *probe_ent = NULL;
-       void __iomem *mmio_base;
-       unsigned int board_idx = (unsigned int) ent->driver_data;
-       int rc, port_no;
-
-       if (!printed_version++)
-               dev_printk(KERN_DEBUG, &pdev->dev, "version " DRV_VERSION "\n");
-
-       rc = pci_enable_device(pdev);
-       if (rc)
-               return rc;
-
-       rc = pci_request_regions(pdev, DRV_NAME);
-       if (rc)
-               goto err_out;
-
-       if ((pci_resource_flags(pdev, 4) & IORESOURCE_MEM) == 0) {
-               rc = -ENODEV;
-               goto err_out_regions;
-       }
-
-       mmio_base = pci_iomap(pdev, 4, 0);
-       if (mmio_base == NULL) {
-               rc = -ENOMEM;
-               goto err_out_regions;
-       }
-
-       rc = adma_set_dma_masks(pdev, mmio_base);
-       if (rc)
-               goto err_out_iounmap;
-
-       probe_ent = kcalloc(1, sizeof(*probe_ent), GFP_KERNEL);
-       if (probe_ent == NULL) {
-               rc = -ENOMEM;
-               goto err_out_iounmap;
-       }
-
-       probe_ent->dev = pci_dev_to_dev(pdev);
-       INIT_LIST_HEAD(&probe_ent->node);
-
-       probe_ent->sht          = adma_port_info[board_idx].sht;
-       probe_ent->host_flags   = adma_port_info[board_idx].host_flags;
-       probe_ent->pio_mask     = adma_port_info[board_idx].pio_mask;
-       probe_ent->mwdma_mask   = adma_port_info[board_idx].mwdma_mask;
-       probe_ent->udma_mask    = adma_port_info[board_idx].udma_mask;
-       probe_ent->port_ops     = adma_port_info[board_idx].port_ops;
-
-       probe_ent->irq          = pdev->irq;
-       probe_ent->irq_flags    = IRQF_SHARED;
-       probe_ent->mmio_base    = mmio_base;
-       probe_ent->n_ports      = ADMA_PORTS;
-
-       for (port_no = 0; port_no < probe_ent->n_ports; ++port_no) {
-               adma_ata_setup_port(&probe_ent->port[port_no],
-                       ADMA_ATA_REGS((unsigned long)mmio_base, port_no));
-       }
-
-       pci_set_master(pdev);
-
-       /* initialize adapter */
-       adma_host_init(board_idx, probe_ent);
-
-       rc = ata_device_add(probe_ent);
-       kfree(probe_ent);
-       if (rc != ADMA_PORTS)
-               goto err_out_iounmap;
-       return 0;
-
-err_out_iounmap:
-       pci_iounmap(pdev, mmio_base);
-err_out_regions:
-       pci_release_regions(pdev);
-err_out:
-       pci_disable_device(pdev);
-       return rc;
-}
-
-static int __init adma_ata_init(void)
-{
-       return pci_register_driver(&adma_ata_pci_driver);
-}
-
-static void __exit adma_ata_exit(void)
-{
-       pci_unregister_driver(&adma_ata_pci_driver);
-}
-
-MODULE_AUTHOR("Mark Lord");
-MODULE_DESCRIPTION("Pacific Digital Corporation ADMA low-level driver");
-MODULE_LICENSE("GPL");
-MODULE_DEVICE_TABLE(pci, adma_ata_pci_tbl);
-MODULE_VERSION(DRV_VERSION);
-
-module_init(adma_ata_init);
-module_exit(adma_ata_exit);
diff --git a/drivers/scsi/sata_mv.c b/drivers/scsi/sata_mv.c
deleted file mode 100644 (file)
index a2915a5..0000000
+++ /dev/null
@@ -1,2468 +0,0 @@
-/*
- * sata_mv.c - Marvell SATA support
- *
- * Copyright 2005: EMC Corporation, all rights reserved.
- * Copyright 2005 Red Hat, Inc.  All rights reserved.
- *
- * Please ALWAYS copy linux-ide@vger.kernel.org on emails.
- *
- * 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; version 2 of the License.
- *
- * 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; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- *
- */
-
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/pci.h>
-#include <linux/init.h>
-#include <linux/blkdev.h>
-#include <linux/delay.h>
-#include <linux/interrupt.h>
-#include <linux/sched.h>
-#include <linux/dma-mapping.h>
-#include <linux/device.h>
-#include <scsi/scsi_host.h>
-#include <scsi/scsi_cmnd.h>
-#include <linux/libata.h>
-#include <asm/io.h>
-
-#define DRV_NAME       "sata_mv"
-#define DRV_VERSION    "0.7"
-
-enum {
-       /* BAR's are enumerated in terms of pci_resource_start() terms */
-       MV_PRIMARY_BAR          = 0,    /* offset 0x10: memory space */
-       MV_IO_BAR               = 2,    /* offset 0x18: IO space */
-       MV_MISC_BAR             = 3,    /* offset 0x1c: FLASH, NVRAM, SRAM */
-
-       MV_MAJOR_REG_AREA_SZ    = 0x10000,      /* 64KB */
-       MV_MINOR_REG_AREA_SZ    = 0x2000,       /* 8KB */
-
-       MV_PCI_REG_BASE         = 0,
-       MV_IRQ_COAL_REG_BASE    = 0x18000,      /* 6xxx part only */
-       MV_IRQ_COAL_CAUSE               = (MV_IRQ_COAL_REG_BASE + 0x08),
-       MV_IRQ_COAL_CAUSE_LO            = (MV_IRQ_COAL_REG_BASE + 0x88),
-       MV_IRQ_COAL_CAUSE_HI            = (MV_IRQ_COAL_REG_BASE + 0x8c),
-       MV_IRQ_COAL_THRESHOLD           = (MV_IRQ_COAL_REG_BASE + 0xcc),
-       MV_IRQ_COAL_TIME_THRESHOLD      = (MV_IRQ_COAL_REG_BASE + 0xd0),
-
-       MV_SATAHC0_REG_BASE     = 0x20000,
-       MV_FLASH_CTL            = 0x1046c,
-       MV_GPIO_PORT_CTL        = 0x104f0,
-       MV_RESET_CFG            = 0x180d8,
-
-       MV_PCI_REG_SZ           = MV_MAJOR_REG_AREA_SZ,
-       MV_SATAHC_REG_SZ        = MV_MAJOR_REG_AREA_SZ,
-       MV_SATAHC_ARBTR_REG_SZ  = MV_MINOR_REG_AREA_SZ,         /* arbiter */
-       MV_PORT_REG_SZ          = MV_MINOR_REG_AREA_SZ,
-
-       MV_USE_Q_DEPTH          = ATA_DEF_QUEUE,
-
-       MV_MAX_Q_DEPTH          = 32,
-       MV_MAX_Q_DEPTH_MASK     = MV_MAX_Q_DEPTH - 1,
-
-       /* CRQB needs alignment on a 1KB boundary. Size == 1KB
-        * CRPB needs alignment on a 256B boundary. Size == 256B
-        * SG count of 176 leads to MV_PORT_PRIV_DMA_SZ == 4KB
-        * ePRD (SG) entries need alignment on a 16B boundary. Size == 16B
-        */
-       MV_CRQB_Q_SZ            = (32 * MV_MAX_Q_DEPTH),
-       MV_CRPB_Q_SZ            = (8 * MV_MAX_Q_DEPTH),
-       MV_MAX_SG_CT            = 176,
-       MV_SG_TBL_SZ            = (16 * MV_MAX_SG_CT),
-       MV_PORT_PRIV_DMA_SZ     = (MV_CRQB_Q_SZ + MV_CRPB_Q_SZ + MV_SG_TBL_SZ),
-
-       MV_PORTS_PER_HC         = 4,
-       /* == (port / MV_PORTS_PER_HC) to determine HC from 0-7 port */
-       MV_PORT_HC_SHIFT        = 2,
-       /* == (port % MV_PORTS_PER_HC) to determine hard port from 0-7 port */
-       MV_PORT_MASK            = 3,
-
-       /* Host Flags */
-       MV_FLAG_DUAL_HC         = (1 << 30),  /* two SATA Host Controllers */
-       MV_FLAG_IRQ_COALESCE    = (1 << 29),  /* IRQ coalescing capability */
-       MV_COMMON_FLAGS         = (ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
-                                  ATA_FLAG_SATA_RESET | ATA_FLAG_MMIO |
-                                  ATA_FLAG_NO_ATAPI | ATA_FLAG_PIO_POLLING),
-       MV_6XXX_FLAGS           = MV_FLAG_IRQ_COALESCE,
-
-       CRQB_FLAG_READ          = (1 << 0),
-       CRQB_TAG_SHIFT          = 1,
-       CRQB_CMD_ADDR_SHIFT     = 8,
-       CRQB_CMD_CS             = (0x2 << 11),
-       CRQB_CMD_LAST           = (1 << 15),
-
-       CRPB_FLAG_STATUS_SHIFT  = 8,
-
-       EPRD_FLAG_END_OF_TBL    = (1 << 31),
-
-       /* PCI interface registers */
-
-       PCI_COMMAND_OFS         = 0xc00,
-
-       PCI_MAIN_CMD_STS_OFS    = 0xd30,
-       STOP_PCI_MASTER         = (1 << 2),
-       PCI_MASTER_EMPTY        = (1 << 3),
-       GLOB_SFT_RST            = (1 << 4),
-
-       MV_PCI_MODE             = 0xd00,
-       MV_PCI_EXP_ROM_BAR_CTL  = 0xd2c,
-       MV_PCI_DISC_TIMER       = 0xd04,
-       MV_PCI_MSI_TRIGGER      = 0xc38,
-       MV_PCI_SERR_MASK        = 0xc28,
-       MV_PCI_XBAR_TMOUT       = 0x1d04,
-       MV_PCI_ERR_LOW_ADDRESS  = 0x1d40,
-       MV_PCI_ERR_HIGH_ADDRESS = 0x1d44,
-       MV_PCI_ERR_ATTRIBUTE    = 0x1d48,
-       MV_PCI_ERR_COMMAND      = 0x1d50,
-
-       PCI_IRQ_CAUSE_OFS               = 0x1d58,
-       PCI_IRQ_MASK_OFS                = 0x1d5c,
-       PCI_UNMASK_ALL_IRQS     = 0x7fffff,     /* bits 22-0 */
-
-       HC_MAIN_IRQ_CAUSE_OFS   = 0x1d60,
-       HC_MAIN_IRQ_MASK_OFS    = 0x1d64,
-       PORT0_ERR               = (1 << 0),     /* shift by port # */
-       PORT0_DONE              = (1 << 1),     /* shift by port # */
-       HC0_IRQ_PEND            = 0x1ff,        /* bits 0-8 = HC0's ports */
-       HC_SHIFT                = 9,            /* bits 9-17 = HC1's ports */
-       PCI_ERR                 = (1 << 18),
-       TRAN_LO_DONE            = (1 << 19),    /* 6xxx: IRQ coalescing */
-       TRAN_HI_DONE            = (1 << 20),    /* 6xxx: IRQ coalescing */
-       PORTS_0_7_COAL_DONE     = (1 << 21),    /* 6xxx: IRQ coalescing */
-       GPIO_INT                = (1 << 22),
-       SELF_INT                = (1 << 23),
-       TWSI_INT                = (1 << 24),
-       HC_MAIN_RSVD            = (0x7f << 25), /* bits 31-25 */
-       HC_MAIN_MASKED_IRQS     = (TRAN_LO_DONE | TRAN_HI_DONE |
-                                  PORTS_0_7_COAL_DONE | GPIO_INT | TWSI_INT |
-                                  HC_MAIN_RSVD),
-
-       /* SATAHC registers */
-       HC_CFG_OFS              = 0,
-
-       HC_IRQ_CAUSE_OFS        = 0x14,
-       CRPB_DMA_DONE           = (1 << 0),     /* shift by port # */
-       HC_IRQ_COAL             = (1 << 4),     /* IRQ coalescing */
-       DEV_IRQ                 = (1 << 8),     /* shift by port # */
-
-       /* Shadow block registers */
-       SHD_BLK_OFS             = 0x100,
-       SHD_CTL_AST_OFS         = 0x20,         /* ofs from SHD_BLK_OFS */
-
-       /* SATA registers */
-       SATA_STATUS_OFS         = 0x300,  /* ctrl, err regs follow status */
-       SATA_ACTIVE_OFS         = 0x350,
-       PHY_MODE3               = 0x310,
-       PHY_MODE4               = 0x314,
-       PHY_MODE2               = 0x330,
-       MV5_PHY_MODE            = 0x74,
-       MV5_LT_MODE             = 0x30,
-       MV5_PHY_CTL             = 0x0C,
-       SATA_INTERFACE_CTL      = 0x050,
-
-       MV_M2_PREAMP_MASK       = 0x7e0,
-
-       /* Port registers */
-       EDMA_CFG_OFS            = 0,
-       EDMA_CFG_Q_DEPTH        = 0,                    /* queueing disabled */
-       EDMA_CFG_NCQ            = (1 << 5),
-       EDMA_CFG_NCQ_GO_ON_ERR  = (1 << 14),            /* continue on error */
-       EDMA_CFG_RD_BRST_EXT    = (1 << 11),            /* read burst 512B */
-       EDMA_CFG_WR_BUFF_LEN    = (1 << 13),            /* write buffer 512B */
-
-       EDMA_ERR_IRQ_CAUSE_OFS  = 0x8,
-       EDMA_ERR_IRQ_MASK_OFS   = 0xc,
-       EDMA_ERR_D_PAR          = (1 << 0),
-       EDMA_ERR_PRD_PAR        = (1 << 1),
-       EDMA_ERR_DEV            = (1 << 2),
-       EDMA_ERR_DEV_DCON       = (1 << 3),
-       EDMA_ERR_DEV_CON        = (1 << 4),
-       EDMA_ERR_SERR           = (1 << 5),
-       EDMA_ERR_SELF_DIS       = (1 << 7),
-       EDMA_ERR_BIST_ASYNC     = (1 << 8),
-       EDMA_ERR_CRBQ_PAR       = (1 << 9),
-       EDMA_ERR_CRPB_PAR       = (1 << 10),
-       EDMA_ERR_INTRL_PAR      = (1 << 11),
-       EDMA_ERR_IORDY          = (1 << 12),
-       EDMA_ERR_LNK_CTRL_RX    = (0xf << 13),
-       EDMA_ERR_LNK_CTRL_RX_2  = (1 << 15),
-       EDMA_ERR_LNK_DATA_RX    = (0xf << 17),
-       EDMA_ERR_LNK_CTRL_TX    = (0x1f << 21),
-       EDMA_ERR_LNK_DATA_TX    = (0x1f << 26),
-       EDMA_ERR_TRANS_PROTO    = (1 << 31),
-       EDMA_ERR_FATAL          = (EDMA_ERR_D_PAR | EDMA_ERR_PRD_PAR |
-                                  EDMA_ERR_DEV_DCON | EDMA_ERR_CRBQ_PAR |
-                                  EDMA_ERR_CRPB_PAR | EDMA_ERR_INTRL_PAR |
-                                  EDMA_ERR_IORDY | EDMA_ERR_LNK_CTRL_RX_2 |
-                                  EDMA_ERR_LNK_DATA_RX |
-                                  EDMA_ERR_LNK_DATA_TX |
-                                  EDMA_ERR_TRANS_PROTO),
-
-       EDMA_REQ_Q_BASE_HI_OFS  = 0x10,
-       EDMA_REQ_Q_IN_PTR_OFS   = 0x14,         /* also contains BASE_LO */
-
-       EDMA_REQ_Q_OUT_PTR_OFS  = 0x18,
-       EDMA_REQ_Q_PTR_SHIFT    = 5,
-
-       EDMA_RSP_Q_BASE_HI_OFS  = 0x1c,
-       EDMA_RSP_Q_IN_PTR_OFS   = 0x20,
-       EDMA_RSP_Q_OUT_PTR_OFS  = 0x24,         /* also contains BASE_LO */
-       EDMA_RSP_Q_PTR_SHIFT    = 3,
-
-       EDMA_CMD_OFS            = 0x28,
-       EDMA_EN                 = (1 << 0),
-       EDMA_DS                 = (1 << 1),
-       ATA_RST                 = (1 << 2),
-
-       EDMA_IORDY_TMOUT        = 0x34,
-       EDMA_ARB_CFG            = 0x38,
-
-       /* Host private flags (hp_flags) */
-       MV_HP_FLAG_MSI          = (1 << 0),
-       MV_HP_ERRATA_50XXB0     = (1 << 1),
-       MV_HP_ERRATA_50XXB2     = (1 << 2),
-       MV_HP_ERRATA_60X1B2     = (1 << 3),
-       MV_HP_ERRATA_60X1C0     = (1 << 4),
-       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),
-       MV_PP_FLAG_EDMA_DS_ACT  = (1 << 1),
-};
-
-#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
-        * anything larger than 64KB
-        */
-       MV_DMA_BOUNDARY         = 0xffffU,
-
-       EDMA_REQ_Q_BASE_LO_MASK = 0xfffffc00U,
-
-       EDMA_RSP_Q_BASE_LO_MASK = 0xffffff00U,
-};
-
-enum chip_type {
-       chip_504x,
-       chip_508x,
-       chip_5080,
-       chip_604x,
-       chip_608x,
-       chip_6042,
-       chip_7042,
-};
-
-/* Command ReQuest Block: 32B */
-struct mv_crqb {
-       __le32                  sg_addr;
-       __le32                  sg_addr_hi;
-       __le16                  ctrl_flags;
-       __le16                  ata_cmd[11];
-};
-
-struct mv_crqb_iie {
-       __le32                  addr;
-       __le32                  addr_hi;
-       __le32                  flags;
-       __le32                  len;
-       __le32                  ata_cmd[4];
-};
-
-/* Command ResPonse Block: 8B */
-struct mv_crpb {
-       __le16                  id;
-       __le16                  flags;
-       __le32                  tmstmp;
-};
-
-/* EDMA Physical Region Descriptor (ePRD); A.K.A. SG */
-struct mv_sg {
-       __le32                  addr;
-       __le32                  flags_size;
-       __le32                  addr_hi;
-       __le32                  reserved;
-};
-
-struct mv_port_priv {
-       struct mv_crqb          *crqb;
-       dma_addr_t              crqb_dma;
-       struct mv_crpb          *crpb;
-       dma_addr_t              crpb_dma;
-       struct mv_sg            *sg_tbl;
-       dma_addr_t              sg_tbl_dma;
-       u32                     pp_flags;
-};
-
-struct mv_port_signal {
-       u32                     amps;
-       u32                     pre;
-};
-
-struct mv_host_priv;
-struct mv_hw_ops {
-       void (*phy_errata)(struct mv_host_priv *hpriv, void __iomem *mmio,
-                          unsigned int port);
-       void (*enable_leds)(struct mv_host_priv *hpriv, void __iomem *mmio);
-       void (*read_preamp)(struct mv_host_priv *hpriv, int idx,
-                          void __iomem *mmio);
-       int (*reset_hc)(struct mv_host_priv *hpriv, void __iomem *mmio,
-                       unsigned int n_hc);
-       void (*reset_flash)(struct mv_host_priv *hpriv, void __iomem *mmio);
-       void (*reset_bus)(struct pci_dev *pdev, void __iomem *mmio);
-};
-
-struct mv_host_priv {
-       u32                     hp_flags;
-       struct mv_port_signal   signal[8];
-       const struct mv_hw_ops  *ops;
-};
-
-static void mv_irq_clear(struct ata_port *ap);
-static u32 mv_scr_read(struct ata_port *ap, unsigned int sc_reg_in);
-static void mv_scr_write(struct ata_port *ap, unsigned int sc_reg_in, u32 val);
-static u32 mv5_scr_read(struct ata_port *ap, unsigned int sc_reg_in);
-static void mv5_scr_write(struct ata_port *ap, unsigned int sc_reg_in, u32 val);
-static void mv_phy_reset(struct ata_port *ap);
-static void __mv_phy_reset(struct ata_port *ap, int can_sleep);
-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 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);
-static int mv_init_one(struct pci_dev *pdev, const struct pci_device_id *ent);
-
-static void mv5_phy_errata(struct mv_host_priv *hpriv, void __iomem *mmio,
-                          unsigned int port);
-static void mv5_enable_leds(struct mv_host_priv *hpriv, void __iomem *mmio);
-static void mv5_read_preamp(struct mv_host_priv *hpriv, int idx,
-                          void __iomem *mmio);
-static int mv5_reset_hc(struct mv_host_priv *hpriv, void __iomem *mmio,
-                       unsigned int n_hc);
-static void mv5_reset_flash(struct mv_host_priv *hpriv, void __iomem *mmio);
-static void mv5_reset_bus(struct pci_dev *pdev, void __iomem *mmio);
-
-static void mv6_phy_errata(struct mv_host_priv *hpriv, void __iomem *mmio,
-                          unsigned int port);
-static void mv6_enable_leds(struct mv_host_priv *hpriv, void __iomem *mmio);
-static void mv6_read_preamp(struct mv_host_priv *hpriv, int idx,
-                          void __iomem *mmio);
-static int mv6_reset_hc(struct mv_host_priv *hpriv, void __iomem *mmio,
-                       unsigned int n_hc);
-static void mv6_reset_flash(struct mv_host_priv *hpriv, void __iomem *mmio);
-static void mv_reset_pci_bus(struct pci_dev *pdev, void __iomem *mmio);
-static void mv_channel_reset(struct mv_host_priv *hpriv, void __iomem *mmio,
-                            unsigned int port_no);
-static void mv_stop_and_reset(struct ata_port *ap);
-
-static struct scsi_host_template mv_sht = {
-       .module                 = THIS_MODULE,
-       .name                   = DRV_NAME,
-       .ioctl                  = ata_scsi_ioctl,
-       .queuecommand           = ata_scsi_queuecmd,
-       .can_queue              = MV_USE_Q_DEPTH,
-       .this_id                = ATA_SHT_THIS_ID,
-       .sg_tablesize           = MV_MAX_SG_CT / 2,
-       .cmd_per_lun            = ATA_SHT_CMD_PER_LUN,
-       .emulated               = ATA_SHT_EMULATED,
-       .use_clustering         = ATA_SHT_USE_CLUSTERING,
-       .proc_name              = DRV_NAME,
-       .dma_boundary           = MV_DMA_BOUNDARY,
-       .slave_configure        = ata_scsi_slave_config,
-       .slave_destroy          = ata_scsi_slave_destroy,
-       .bios_param             = ata_std_bios_param,
-};
-
-static const struct ata_port_operations mv5_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,
-       .qc_issue               = mv_qc_issue,
-       .data_xfer              = ata_mmio_data_xfer,
-
-       .eng_timeout            = mv_eng_timeout,
-
-       .irq_handler            = mv_interrupt,
-       .irq_clear              = mv_irq_clear,
-
-       .scr_read               = mv5_scr_read,
-       .scr_write              = mv5_scr_write,
-
-       .port_start             = mv_port_start,
-       .port_stop              = mv_port_stop,
-       .host_stop              = mv_host_stop,
-};
-
-static const struct ata_port_operations mv6_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,
-       .qc_issue               = mv_qc_issue,
-       .data_xfer              = ata_mmio_data_xfer,
-
-       .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_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,
-               .host_flags     = MV_COMMON_FLAGS,
-               .pio_mask       = 0x1f, /* pio0-4 */
-               .udma_mask      = 0x7f, /* udma0-6 */
-               .port_ops       = &mv5_ops,
-       },
-       {  /* chip_508x */
-               .sht            = &mv_sht,
-               .host_flags     = (MV_COMMON_FLAGS | MV_FLAG_DUAL_HC),
-               .pio_mask       = 0x1f, /* pio0-4 */
-               .udma_mask      = 0x7f, /* udma0-6 */
-               .port_ops       = &mv5_ops,
-       },
-       {  /* chip_5080 */
-               .sht            = &mv_sht,
-               .host_flags     = (MV_COMMON_FLAGS | MV_FLAG_DUAL_HC),
-               .pio_mask       = 0x1f, /* pio0-4 */
-               .udma_mask      = 0x7f, /* udma0-6 */
-               .port_ops       = &mv5_ops,
-       },
-       {  /* chip_604x */
-               .sht            = &mv_sht,
-               .host_flags     = (MV_COMMON_FLAGS | MV_6XXX_FLAGS),
-               .pio_mask       = 0x1f, /* pio0-4 */
-               .udma_mask      = 0x7f, /* udma0-6 */
-               .port_ops       = &mv6_ops,
-       },
-       {  /* chip_608x */
-               .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       = &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[] = {
-       {PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x5040), 0, 0, chip_504x},
-       {PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x5041), 0, 0, chip_504x},
-       {PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x5080), 0, 0, chip_5080},
-       {PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x5081), 0, 0, chip_508x},
-
-       {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},
-
-       {PCI_DEVICE(PCI_VENDOR_ID_ADAPTEC2, 0x0241), 0, 0, chip_604x},
-       {}                      /* terminate list */
-};
-
-static struct pci_driver mv_pci_driver = {
-       .name                   = DRV_NAME,
-       .id_table               = mv_pci_tbl,
-       .probe                  = mv_init_one,
-       .remove                 = ata_pci_remove_one,
-};
-
-static const struct mv_hw_ops mv5xxx_ops = {
-       .phy_errata             = mv5_phy_errata,
-       .enable_leds            = mv5_enable_leds,
-       .read_preamp            = mv5_read_preamp,
-       .reset_hc               = mv5_reset_hc,
-       .reset_flash            = mv5_reset_flash,
-       .reset_bus              = mv5_reset_bus,
-};
-
-static const struct mv_hw_ops mv6xxx_ops = {
-       .phy_errata             = mv6_phy_errata,
-       .enable_leds            = mv6_enable_leds,
-       .read_preamp            = mv6_read_preamp,
-       .reset_hc               = mv6_reset_hc,
-       .reset_flash            = mv6_reset_flash,
-       .reset_bus              = mv_reset_pci_bus,
-};
-
-/*
- * module options
- */
-static int msi;              /* Use PCI msi; either zero (off, default) or non-zero */
-
-
-/*
- * Functions
- */
-
-static inline void writelfl(unsigned long data, void __iomem *addr)
-{
-       writel(data, addr);
-       (void) readl(addr);     /* flush to avoid PCI posted write */
-}
-
-static inline void __iomem *mv_hc_base(void __iomem *base, unsigned int hc)
-{
-       return (base + MV_SATAHC0_REG_BASE + (hc * MV_SATAHC_REG_SZ));
-}
-
-static inline unsigned int mv_hc_from_port(unsigned int port)
-{
-       return port >> MV_PORT_HC_SHIFT;
-}
-
-static inline unsigned int mv_hardport_from_port(unsigned int port)
-{
-       return port & MV_PORT_MASK;
-}
-
-static inline void __iomem *mv_hc_base_from_port(void __iomem *base,
-                                                unsigned int port)
-{
-       return mv_hc_base(base, mv_hc_from_port(port));
-}
-
-static inline void __iomem *mv_port_base(void __iomem *base, unsigned int port)
-{
-       return  mv_hc_base_from_port(base, port) +
-               MV_SATAHC_ARBTR_REG_SZ +
-               (mv_hardport_from_port(port) * MV_PORT_REG_SZ);
-}
-
-static inline void __iomem *mv_ap_base(struct ata_port *ap)
-{
-       return mv_port_base(ap->host_set->mmio_base, ap->port_no);
-}
-
-static inline int mv_get_hc_count(unsigned long host_flags)
-{
-       return ((host_flags & MV_FLAG_DUAL_HC) ? 2 : 1);
-}
-
-static void mv_irq_clear(struct ata_port *ap)
-{
-}
-
-/**
- *      mv_start_dma - Enable eDMA engine
- *      @base: port base address
- *      @pp: port private data
- *
- *      Verify the local cache of the eDMA state is accurate with a
- *      WARN_ON.
- *
- *      LOCKING:
- *      Inherited from caller.
- */
-static void mv_start_dma(void __iomem *base, struct mv_port_priv *pp)
-{
-       if (!(MV_PP_FLAG_EDMA_EN & pp->pp_flags)) {
-               writelfl(EDMA_EN, base + EDMA_CMD_OFS);
-               pp->pp_flags |= MV_PP_FLAG_EDMA_EN;
-       }
-       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 a
- *      WARN_ON.
- *
- *      LOCKING:
- *      Inherited from caller.
- */
-static void mv_stop_dma(struct ata_port *ap)
-{
-       void __iomem *port_mmio = mv_ap_base(ap);
-       struct mv_port_priv *pp = ap->private_data;
-       u32 reg;
-       int i;
-
-       if (MV_PP_FLAG_EDMA_EN & pp->pp_flags) {
-               /* Disable EDMA if active.   The disable bit auto clears.
-                */
-               writelfl(EDMA_DS, port_mmio + EDMA_CMD_OFS);
-               pp->pp_flags &= ~MV_PP_FLAG_EDMA_EN;
-       } else {
-               WARN_ON(EDMA_EN & readl(port_mmio + EDMA_CMD_OFS));
-       }
-
-       /* now properly wait for the eDMA to stop */
-       for (i = 1000; i > 0; i--) {
-               reg = readl(port_mmio + EDMA_CMD_OFS);
-               if (!(EDMA_EN & reg)) {
-                       break;
-               }
-               udelay(100);
-       }
-
-       if (EDMA_EN & reg) {
-               ata_port_printk(ap, KERN_ERR, "Unable to stop eDMA\n");
-               /* FIXME: Consider doing a reset here to recover */
-       }
-}
-
-#ifdef ATA_DEBUG
-static void mv_dump_mem(void __iomem *start, unsigned bytes)
-{
-       int b, w;
-       for (b = 0; b < bytes; ) {
-               DPRINTK("%p: ", start + b);
-               for (w = 0; b < bytes && w < 4; w++) {
-                       printk("%08x ",readl(start + b));
-                       b += sizeof(u32);
-               }
-               printk("\n");
-       }
-}
-#endif
-
-static void mv_dump_pci_cfg(struct pci_dev *pdev, unsigned bytes)
-{
-#ifdef ATA_DEBUG
-       int b, w;
-       u32 dw;
-       for (b = 0; b < bytes; ) {
-               DPRINTK("%02x: ", b);
-               for (w = 0; b < bytes && w < 4; w++) {
-                       (void) pci_read_config_dword(pdev,b,&dw);
-                       printk("%08x ",dw);
-                       b += sizeof(u32);
-               }
-               printk("\n");
-       }
-#endif
-}
-static void mv_dump_all_regs(void __iomem *mmio_base, int port,
-                            struct pci_dev *pdev)
-{
-#ifdef ATA_DEBUG
-       void __iomem *hc_base = mv_hc_base(mmio_base,
-                                          port >> MV_PORT_HC_SHIFT);
-       void __iomem *port_base;
-       int start_port, num_ports, p, start_hc, num_hcs, hc;
-
-       if (0 > port) {
-               start_hc = start_port = 0;
-               num_ports = 8;          /* shld be benign for 4 port devs */
-               num_hcs = 2;
-       } else {
-               start_hc = port >> MV_PORT_HC_SHIFT;
-               start_port = port;
-               num_ports = num_hcs = 1;
-       }
-       DPRINTK("All registers for port(s) %u-%u:\n", start_port,
-               num_ports > 1 ? num_ports - 1 : start_port);
-
-       if (NULL != pdev) {
-               DPRINTK("PCI config space regs:\n");
-               mv_dump_pci_cfg(pdev, 0x68);
-       }
-       DPRINTK("PCI regs:\n");
-       mv_dump_mem(mmio_base+0xc00, 0x3c);
-       mv_dump_mem(mmio_base+0xd00, 0x34);
-       mv_dump_mem(mmio_base+0xf00, 0x4);
-       mv_dump_mem(mmio_base+0x1d00, 0x6c);
-       for (hc = start_hc; hc < start_hc + num_hcs; hc++) {
-               hc_base = mv_hc_base(mmio_base, hc);
-               DPRINTK("HC regs (HC %i):\n", hc);
-               mv_dump_mem(hc_base, 0x1c);
-       }
-       for (p = start_port; p < start_port + num_ports; p++) {
-               port_base = mv_port_base(mmio_base, p);
-               DPRINTK("EDMA regs (port %i):\n",p);
-               mv_dump_mem(port_base, 0x54);
-               DPRINTK("SATA regs (port %i):\n",p);
-               mv_dump_mem(port_base+0x300, 0x60);
-       }
-#endif
-}
-
-static unsigned int mv_scr_offset(unsigned int sc_reg_in)
-{
-       unsigned int ofs;
-
-       switch (sc_reg_in) {
-       case SCR_STATUS:
-       case SCR_CONTROL:
-       case SCR_ERROR:
-               ofs = SATA_STATUS_OFS + (sc_reg_in * sizeof(u32));
-               break;
-       case SCR_ACTIVE:
-               ofs = SATA_ACTIVE_OFS;   /* active is not with the others */
-               break;
-       default:
-               ofs = 0xffffffffU;
-               break;
-       }
-       return ofs;
-}
-
-static u32 mv_scr_read(struct ata_port *ap, unsigned int sc_reg_in)
-{
-       unsigned int ofs = mv_scr_offset(sc_reg_in);
-
-       if (0xffffffffU != ofs) {
-               return readl(mv_ap_base(ap) + ofs);
-       } else {
-               return (u32) ofs;
-       }
-}
-
-static void mv_scr_write(struct ata_port *ap, unsigned int sc_reg_in, u32 val)
-{
-       unsigned int ofs = mv_scr_offset(sc_reg_in);
-
-       if (0xffffffffU != ofs) {
-               writelfl(val, mv_ap_base(ap) + ofs);
-       }
-}
-
-/**
- *      mv_host_stop - Host specific cleanup/stop routine.
- *      @host_set: host data structure
- *
- *      Disable ints, cleanup host memory, call general purpose
- *      host_stop.
- *
- *      LOCKING:
- *      Inherited from caller.
- */
-static void mv_host_stop(struct ata_host_set *host_set)
-{
-       struct mv_host_priv *hpriv = host_set->private_data;
-       struct pci_dev *pdev = to_pci_dev(host_set->dev);
-
-       if (hpriv->hp_flags & MV_HP_FLAG_MSI) {
-               pci_disable_msi(pdev);
-       } else {
-               pci_intx(pdev, 0);
-       }
-       kfree(hpriv);
-       ata_host_stop(host_set);
-}
-
-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
- *
- *      Allocate and point to DMA memory, init port private memory,
- *      zero indices.
- *
- *      LOCKING:
- *      Inherited from caller.
- */
-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;
-       dma_addr_t mem_dma;
-       int rc = -ENOMEM;
-
-       pp = kmalloc(sizeof(*pp), GFP_KERNEL);
-       if (!pp)
-               goto err_out;
-       memset(pp, 0, sizeof(*pp));
-
-       mem = dma_alloc_coherent(dev, MV_PORT_PRIV_DMA_SZ, &mem_dma,
-                                GFP_KERNEL);
-       if (!mem)
-               goto err_out_pp;
-       memset(mem, 0, MV_PORT_PRIV_DMA_SZ);
-
-       rc = ata_pad_alloc(ap, dev);
-       if (rc)
-               goto err_out_priv;
-
-       /* First item in chunk of DMA memory:
-        * 32-slot command request table (CRQB), 32 bytes each in size
-        */
-       pp->crqb = mem;
-       pp->crqb_dma = mem_dma;
-       mem += MV_CRQB_Q_SZ;
-       mem_dma += MV_CRQB_Q_SZ;
-
-       /* Second item:
-        * 32-slot command response table (CRPB), 8 bytes each in size
-        */
-       pp->crpb = mem;
-       pp->crpb_dma = mem_dma;
-       mem += MV_CRPB_Q_SZ;
-       mem_dma += MV_CRPB_Q_SZ;
-
-       /* Third item:
-        * Table of scatter-gather descriptors (ePRD), 16 bytes each
-        */
-       pp->sg_tbl = mem;
-       pp->sg_tbl_dma = mem_dma;
-
-       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);
-
-       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);
-
-       /* Don't turn on EDMA here...do it before DMA commands only.  Else
-        * we'll be unable to send non-data, PIO, etc due to restricted access
-        * to shadow regs.
-        */
-       ap->private_data = pp;
-       return 0;
-
-err_out_priv:
-       mv_priv_free(pp, dev);
-err_out_pp:
-       kfree(pp);
-err_out:
-       return rc;
-}
-
-/**
- *      mv_port_stop - Port specific cleanup/stop routine.
- *      @ap: ATA channel to manipulate
- *
- *      Stop DMA, cleanup port memory.
- *
- *      LOCKING:
- *      This routine uses the host_set lock to protect the DMA stop.
- */
-static void mv_port_stop(struct ata_port *ap)
-{
-       struct device *dev = ap->host_set->dev;
-       struct mv_port_priv *pp = ap->private_data;
-       unsigned long flags;
-
-       spin_lock_irqsave(&ap->host_set->lock, flags);
-       mv_stop_dma(ap);
-       spin_unlock_irqrestore(&ap->host_set->lock, flags);
-
-       ap->private_data = NULL;
-       ata_pad_free(ap, dev);
-       mv_priv_free(pp, dev);
-       kfree(pp);
-}
-
-/**
- *      mv_fill_sg - Fill out the Marvell ePRD (scatter gather) entries
- *      @qc: queued command whose SG list to source from
- *
- *      Populate the SG list and mark the last entry.
- *
- *      LOCKING:
- *      Inherited from caller.
- */
-static void mv_fill_sg(struct ata_queued_cmd *qc)
-{
-       struct mv_port_priv *pp = qc->ap->private_data;
-       unsigned int i = 0;
-       struct scatterlist *sg;
-
-       ata_for_each_sg(sg, qc) {
-               dma_addr_t addr;
-               u32 sg_len, len, offset;
-
-               addr = sg_dma_address(sg);
-               sg_len = sg_dma_len(sg);
-
-               while (sg_len) {
-                       offset = addr & MV_DMA_BOUNDARY;
-                       len = sg_len;
-                       if ((offset + sg_len) > 0x10000)
-                               len = 0x10000 - offset;
-
-                       pp->sg_tbl[i].addr = cpu_to_le32(addr & 0xffffffff);
-                       pp->sg_tbl[i].addr_hi = cpu_to_le32((addr >> 16) >> 16);
-                       pp->sg_tbl[i].flags_size = cpu_to_le32(len & 0xffff);
-
-                       sg_len -= len;
-                       addr += len;
-
-                       if (!sg_len && ata_sg_is_last(sg, qc))
-                               pp->sg_tbl[i].flags_size |= cpu_to_le32(EPRD_FLAG_END_OF_TBL);
-
-                       i++;
-               }
-       }
-}
-
-static inline unsigned mv_inc_q_index(unsigned index)
-{
-       return (index + 1) & MV_MAX_Q_DEPTH_MASK;
-}
-
-static inline void mv_crqb_pack_cmd(__le16 *cmdw, u8 data, u8 addr, unsigned last)
-{
-       u16 tmp = data | (addr << CRQB_CMD_ADDR_SHIFT) | CRQB_CMD_CS |
-               (last ? CRQB_CMD_LAST : 0);
-       *cmdw = cpu_to_le16(tmp);
-}
-
-/**
- *      mv_qc_prep - 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(struct ata_queued_cmd *qc)
-{
-       struct ata_port *ap = qc->ap;
-       struct mv_port_priv *pp = ap->private_data;
-       __le16 *cw;
-       struct ata_taskfile *tf;
-       u16 flags = 0;
-       unsigned in_index;
-
-       if (ATA_PROT_DMA != qc->tf.protocol)
-               return;
-
-       /* Fill in 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;
-
-       /* get current queue index from hardware */
-       in_index = (readl(mv_ap_base(ap) + EDMA_REQ_Q_IN_PTR_OFS)
-                       >> EDMA_REQ_Q_PTR_SHIFT) & MV_MAX_Q_DEPTH_MASK;
-
-       pp->crqb[in_index].sg_addr =
-               cpu_to_le32(pp->sg_tbl_dma & 0xffffffff);
-       pp->crqb[in_index].sg_addr_hi =
-               cpu_to_le32((pp->sg_tbl_dma >> 16) >> 16);
-       pp->crqb[in_index].ctrl_flags = cpu_to_le16(flags);
-
-       cw = &pp->crqb[in_index].ata_cmd[0];
-       tf = &qc->tf;
-
-       /* Sadly, the CRQB cannot accomodate all registers--there are
-        * only 11 bytes...so we must pick and choose required
-        * registers based on the command.  So, we drop feature and
-        * hob_feature for [RW] DMA commands, but they are needed for
-        * NCQ.  NCQ will drop hob_nsect.
-        */
-       switch (tf->command) {
-       case ATA_CMD_READ:
-       case ATA_CMD_READ_EXT:
-       case ATA_CMD_WRITE:
-       case ATA_CMD_WRITE_EXT:
-       case ATA_CMD_WRITE_FUA_EXT:
-               mv_crqb_pack_cmd(cw++, tf->hob_nsect, ATA_REG_NSECT, 0);
-               break;
-#ifdef LIBATA_NCQ              /* FIXME: remove this line when NCQ added */
-       case ATA_CMD_FPDMA_READ:
-       case ATA_CMD_FPDMA_WRITE:
-               mv_crqb_pack_cmd(cw++, tf->hob_feature, ATA_REG_FEATURE, 0);
-               mv_crqb_pack_cmd(cw++, tf->feature, ATA_REG_FEATURE, 0);
-               break;
-#endif                         /* FIXME: remove this line when NCQ added */
-       default:
-               /* The only other commands EDMA supports in non-queued and
-                * non-NCQ mode are: [RW] STREAM DMA and W DMA FUA EXT, none
-                * of which are defined/used by Linux.  If we get here, this
-                * driver needs work.
-                *
-                * FIXME: modify libata to give qc_prep a return value and
-                * return error here.
-                */
-               BUG_ON(tf->command);
-               break;
-       }
-       mv_crqb_pack_cmd(cw++, tf->nsect, ATA_REG_NSECT, 0);
-       mv_crqb_pack_cmd(cw++, tf->hob_lbal, ATA_REG_LBAL, 0);
-       mv_crqb_pack_cmd(cw++, tf->lbal, ATA_REG_LBAL, 0);
-       mv_crqb_pack_cmd(cw++, tf->hob_lbam, ATA_REG_LBAM, 0);
-       mv_crqb_pack_cmd(cw++, tf->lbam, ATA_REG_LBAM, 0);
-       mv_crqb_pack_cmd(cw++, tf->hob_lbah, ATA_REG_LBAH, 0);
-       mv_crqb_pack_cmd(cw++, tf->lbah, ATA_REG_LBAH, 0);
-       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))
-               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;
-       unsigned in_index;
-       u32 flags = 0;
-
-       if (ATA_PROT_DMA != qc->tf.protocol)
-               return;
-
-       /* 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;
-
-       /* get current queue index from hardware */
-       in_index = (readl(mv_ap_base(ap) + EDMA_REQ_Q_IN_PTR_OFS)
-                       >> EDMA_REQ_Q_PTR_SHIFT) & MV_MAX_Q_DEPTH_MASK;
-
-       crqb = (struct mv_crqb_iie *) &pp->crqb[in_index];
-       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);
-}
-
-/**
- *      mv_qc_issue - Initiate a command to the host
- *      @qc: queued command to start
- *
- *      This routine simply redirects to the general purpose routine
- *      if command is not DMA.  Else, it sanity checks our local
- *      caches of the request producer/consumer indices then enables
- *      DMA and bumps the request producer index.
- *
- *      LOCKING:
- *      Inherited from caller.
- */
-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;
-       unsigned in_index;
-       u32 in_ptr;
-
-       if (ATA_PROT_DMA != qc->tf.protocol) {
-               /* We're about to send a non-EDMA capable command to the
-                * port.  Turn off EDMA so there won't be problems accessing
-                * shadow block, etc registers.
-                */
-               mv_stop_dma(qc->ap);
-               return ata_qc_issue_prot(qc);
-       }
-
-       in_ptr   = readl(port_mmio + EDMA_REQ_Q_IN_PTR_OFS);
-       in_index = (in_ptr >> EDMA_REQ_Q_PTR_SHIFT) & MV_MAX_Q_DEPTH_MASK;
-
-       /* until we do queuing, the queue should be empty at this point */
-       WARN_ON(in_index != ((readl(port_mmio + EDMA_REQ_Q_OUT_PTR_OFS)
-               >> EDMA_REQ_Q_PTR_SHIFT) & MV_MAX_Q_DEPTH_MASK));
-
-       in_index = mv_inc_q_index(in_index);    /* now incr producer index */
-
-       mv_start_dma(port_mmio, pp);
-
-       /* and write the request in pointer to kick the EDMA to life */
-       in_ptr &= EDMA_REQ_Q_BASE_LO_MASK;
-       in_ptr |= in_index << EDMA_REQ_Q_PTR_SHIFT;
-       writelfl(in_ptr, port_mmio + EDMA_REQ_Q_IN_PTR_OFS);
-
-       return 0;
-}
-
-/**
- *      mv_get_crpb_status - get status from most recently completed cmd
- *      @ap: ATA channel to manipulate
- *
- *      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 check indices
- *      are good, grab status, and bump the response consumer index to
- *      prove that we're up to date.
- *
- *      LOCKING:
- *      Inherited from caller.
- */
-static u8 mv_get_crpb_status(struct ata_port *ap)
-{
-       void __iomem *port_mmio = mv_ap_base(ap);
-       struct mv_port_priv *pp = ap->private_data;
-       unsigned out_index;
-       u32 out_ptr;
-       u8 ata_status;
-
-       out_ptr   = readl(port_mmio + EDMA_RSP_Q_OUT_PTR_OFS);
-       out_index = (out_ptr >> EDMA_RSP_Q_PTR_SHIFT) & MV_MAX_Q_DEPTH_MASK;
-
-       ata_status = le16_to_cpu(pp->crpb[out_index].flags)
-                                       >> CRPB_FLAG_STATUS_SHIFT;
-
-       /* increment our consumer index... */
-       out_index = mv_inc_q_index(out_index);
-
-       /* and, until we do NCQ, there should only be 1 CRPB waiting */
-       WARN_ON(out_index != ((readl(port_mmio + EDMA_RSP_Q_IN_PTR_OFS)
-               >> EDMA_RSP_Q_PTR_SHIFT) & MV_MAX_Q_DEPTH_MASK));
-
-       /* write out our inc'd consumer index so EDMA knows we're caught up */
-       out_ptr &= EDMA_RSP_Q_BASE_LO_MASK;
-       out_ptr |= out_index << EDMA_RSP_Q_PTR_SHIFT;
-       writelfl(out_ptr, port_mmio + EDMA_RSP_Q_OUT_PTR_OFS);
-
-       /* Return ATA status register for completed CRPB */
-       return ata_status;
-}
-
-/**
- *      mv_err_intr - Handle error interrupts on the port
- *      @ap: ATA channel to manipulate
- *      @reset_allowed: bool: 0 == don't trigger from reset here
- *
- *      In most cases, just clear the interrupt and move on.  However,
- *      some cases require an eDMA reset, which is done right before
- *      the COMRESET in mv_phy_reset().  The SERR case requires a
- *      clear of pending errors in the SATA SERROR register.  Finally,
- *      if the port disabled DMA, update our cached copy to match.
- *
- *      LOCKING:
- *      Inherited from caller.
- */
-static void mv_err_intr(struct ata_port *ap, int reset_allowed)
-{
-       void __iomem *port_mmio = mv_ap_base(ap);
-       u32 edma_err_cause, serr = 0;
-
-       edma_err_cause = readl(port_mmio + EDMA_ERR_IRQ_CAUSE_OFS);
-
-       if (EDMA_ERR_SERR & edma_err_cause) {
-               sata_scr_read(ap, SCR_ERROR, &serr);
-               sata_scr_write_flush(ap, SCR_ERROR, serr);
-       }
-       if (EDMA_ERR_SELF_DIS & edma_err_cause) {
-               struct mv_port_priv *pp = ap->private_data;
-               pp->pp_flags &= ~MV_PP_FLAG_EDMA_EN;
-       }
-       DPRINTK(KERN_ERR "ata%u: port error; EDMA err cause: 0x%08x "
-               "SERR: 0x%08x\n", ap->id, edma_err_cause, serr);
-
-       /* Clear EDMA now that SERR cleanup done */
-       writelfl(0, port_mmio + EDMA_ERR_IRQ_CAUSE_OFS);
-
-       /* check for fatal here and recover if needed */
-       if (reset_allowed && (EDMA_ERR_FATAL & edma_err_cause))
-               mv_stop_and_reset(ap);
-}
-
-/**
- *      mv_host_intr - Handle all interrupts on the given host controller
- *      @host_set: host specific structure
- *      @relevant: port error bits relevant to this host controller
- *      @hc: which host controller we're to look at
- *
- *      Read then write clear the HC interrupt status then walk each
- *      port connected to the HC and see if it needs servicing.  Port
- *      success ints are reported in the HC interrupt status reg, the
- *      port error ints are reported in the higher level main
- *      interrupt status register and thus are passed in via the
- *      'relevant' argument.
- *
- *      LOCKING:
- *      Inherited from caller.
- */
-static void mv_host_intr(struct ata_host_set *host_set, u32 relevant,
-                        unsigned int hc)
-{
-       void __iomem *mmio = host_set->mmio_base;
-       void __iomem *hc_mmio = mv_hc_base(mmio, hc);
-       struct ata_queued_cmd *qc;
-       u32 hc_irq_cause;
-       int shift, port, port0, hard_port, handled;
-       unsigned int err_mask;
-
-       if (hc == 0) {
-               port0 = 0;
-       } else {
-               port0 = MV_PORTS_PER_HC;
-       }
-
-       /* we'll need the HC success int register in most cases */
-       hc_irq_cause = readl(hc_mmio + HC_IRQ_CAUSE_OFS);
-       if (hc_irq_cause) {
-               writelfl(~hc_irq_cause, hc_mmio + HC_IRQ_CAUSE_OFS);
-       }
-
-       VPRINTK("ENTER, hc%u relevant=0x%08x HC IRQ cause=0x%08x\n",
-               hc,relevant,hc_irq_cause);
-
-       for (port = port0; port < port0 + MV_PORTS_PER_HC; port++) {
-               u8 ata_status = 0;
-               struct ata_port *ap = host_set->ports[port];
-               struct mv_port_priv *pp = ap->private_data;
-
-               hard_port = mv_hardport_from_port(port); /* range 0..3 */
-               handled = 0;    /* ensure ata_status is set if handled++ */
-
-               /* Note that DEV_IRQ might happen spuriously during EDMA,
-                * and should be ignored in such cases.
-                * The cause of this is still under investigation.
-                */
-               if (pp->pp_flags & MV_PP_FLAG_EDMA_EN) {
-                       /* EDMA: check for response queue interrupt */
-                       if ((CRPB_DMA_DONE << hard_port) & hc_irq_cause) {
-                               ata_status = mv_get_crpb_status(ap);
-                               handled = 1;
-                       }
-               } else {
-                       /* PIO: check for device (drive) interrupt */
-                       if ((DEV_IRQ << hard_port) & hc_irq_cause) {
-                               ata_status = readb((void __iomem *)
-                                          ap->ioaddr.status_addr);
-                               handled = 1;
-                               /* ignore spurious intr if drive still BUSY */
-                               if (ata_status & ATA_BUSY) {
-                                       ata_status = 0;
-                                       handled = 0;
-                               }
-                       }
-               }
-
-               if (ap && (ap->flags & ATA_FLAG_DISABLED))
-                       continue;
-
-               err_mask = ac_err_mask(ata_status);
-
-               shift = port << 1;              /* (port * 2) */
-               if (port >= MV_PORTS_PER_HC) {
-                       shift++;        /* skip bit 8 in the HC Main IRQ reg */
-               }
-               if ((PORT0_ERR << shift) & relevant) {
-                       mv_err_intr(ap, 1);
-                       err_mask |= AC_ERR_OTHER;
-                       handled = 1;
-               }
-
-               if (handled) {
-                       qc = ata_qc_from_tag(ap, ap->active_tag);
-                       if (qc && (qc->flags & ATA_QCFLAG_ACTIVE)) {
-                               VPRINTK("port %u IRQ found for qc, "
-                                       "ata_status 0x%x\n", port,ata_status);
-                               /* mark qc status appropriately */
-                               if (!(qc->tf.flags & ATA_TFLAG_POLLING)) {
-                                       qc->err_mask |= err_mask;
-                                       ata_qc_complete(qc);
-                               }
-                       }
-               }
-       }
-       VPRINTK("EXIT\n");
-}
-
-/**
- *      mv_interrupt -
- *      @irq: unused
- *      @dev_instance: private data; in this case the host structure
- *      @regs: unused
- *
- *      Read the read only register to determine if any host
- *      controllers have pending interrupts.  If so, call lower level
- *      routine to handle.  Also check for PCI errors which are only
- *      reported here.
- *
- *      LOCKING:
- *      This routine holds the host_set lock while processing pending
- *      interrupts.
- */
-static irqreturn_t mv_interrupt(int irq, void *dev_instance,
-                               struct pt_regs *regs)
-{
-       struct ata_host_set *host_set = dev_instance;
-       unsigned int hc, handled = 0, n_hcs;
-       void __iomem *mmio = host_set->mmio_base;
-       struct mv_host_priv *hpriv;
-       u32 irq_stat;
-
-       irq_stat = readl(mmio + HC_MAIN_IRQ_CAUSE_OFS);
-
-       /* check the cases where we either have nothing pending or have read
-        * a bogus register value which can indicate HW removal or PCI fault
-        */
-       if (!irq_stat || (0xffffffffU == irq_stat)) {
-               return IRQ_NONE;
-       }
-
-       n_hcs = mv_get_hc_count(host_set->ports[0]->flags);
-       spin_lock(&host_set->lock);
-
-       for (hc = 0; hc < n_hcs; hc++) {
-               u32 relevant = irq_stat & (HC0_IRQ_PEND << (hc * HC_SHIFT));
-               if (relevant) {
-                       mv_host_intr(host_set, relevant, hc);
-                       handled++;
-               }
-       }
-
-       hpriv = host_set->private_data;
-       if (IS_60XX(hpriv)) {
-               /* deal with the interrupt coalescing bits */
-               if (irq_stat & (TRAN_LO_DONE | TRAN_HI_DONE | PORTS_0_7_COAL_DONE)) {
-                       writelfl(0, mmio + MV_IRQ_COAL_CAUSE_LO);
-                       writelfl(0, mmio + MV_IRQ_COAL_CAUSE_HI);
-                       writelfl(0, mmio + MV_IRQ_COAL_CAUSE);
-               }
-       }
-
-       if (PCI_ERR & irq_stat) {
-               printk(KERN_ERR DRV_NAME ": PCI ERROR; PCI IRQ cause=0x%08x\n",
-                      readl(mmio + PCI_IRQ_CAUSE_OFS));
-
-               DPRINTK("All regs @ PCI error\n");
-               mv_dump_all_regs(mmio, -1, to_pci_dev(host_set->dev));
-
-               writelfl(0, mmio + PCI_IRQ_CAUSE_OFS);
-               handled++;
-       }
-       spin_unlock(&host_set->lock);
-
-       return IRQ_RETVAL(handled);
-}
-
-static void __iomem *mv5_phy_base(void __iomem *mmio, unsigned int port)
-{
-       void __iomem *hc_mmio = mv_hc_base_from_port(mmio, port);
-       unsigned long ofs = (mv_hardport_from_port(port) + 1) * 0x100UL;
-
-       return hc_mmio + ofs;
-}
-
-static unsigned int mv5_scr_offset(unsigned int sc_reg_in)
-{
-       unsigned int ofs;
-
-       switch (sc_reg_in) {
-       case SCR_STATUS:
-       case SCR_ERROR:
-       case SCR_CONTROL:
-               ofs = sc_reg_in * sizeof(u32);
-               break;
-       default:
-               ofs = 0xffffffffU;
-               break;
-       }
-       return ofs;
-}
-
-static u32 mv5_scr_read(struct ata_port *ap, unsigned int sc_reg_in)
-{
-       void __iomem *mmio = mv5_phy_base(ap->host_set->mmio_base, ap->port_no);
-       unsigned int ofs = mv5_scr_offset(sc_reg_in);
-
-       if (ofs != 0xffffffffU)
-               return readl(mmio + ofs);
-       else
-               return (u32) ofs;
-}
-
-static void mv5_scr_write(struct ata_port *ap, unsigned int sc_reg_in, u32 val)
-{
-       void __iomem *mmio = mv5_phy_base(ap->host_set->mmio_base, ap->port_no);
-       unsigned int ofs = mv5_scr_offset(sc_reg_in);
-
-       if (ofs != 0xffffffffU)
-               writelfl(val, mmio + ofs);
-}
-
-static void mv5_reset_bus(struct pci_dev *pdev, void __iomem *mmio)
-{
-       u8 rev_id;
-       int early_5080;
-
-       pci_read_config_byte(pdev, PCI_REVISION_ID, &rev_id);
-
-       early_5080 = (pdev->device == 0x5080) && (rev_id == 0);
-
-       if (!early_5080) {
-               u32 tmp = readl(mmio + MV_PCI_EXP_ROM_BAR_CTL);
-               tmp |= (1 << 0);
-               writel(tmp, mmio + MV_PCI_EXP_ROM_BAR_CTL);
-       }
-
-       mv_reset_pci_bus(pdev, mmio);
-}
-
-static void mv5_reset_flash(struct mv_host_priv *hpriv, void __iomem *mmio)
-{
-       writel(0x0fcfffff, mmio + MV_FLASH_CTL);
-}
-
-static void mv5_read_preamp(struct mv_host_priv *hpriv, int idx,
-                          void __iomem *mmio)
-{
-       void __iomem *phy_mmio = mv5_phy_base(mmio, idx);
-       u32 tmp;
-
-       tmp = readl(phy_mmio + MV5_PHY_MODE);
-
-       hpriv->signal[idx].pre = tmp & 0x1800;  /* bits 12:11 */
-       hpriv->signal[idx].amps = tmp & 0xe0;   /* bits 7:5 */
-}
-
-static void mv5_enable_leds(struct mv_host_priv *hpriv, void __iomem *mmio)
-{
-       u32 tmp;
-
-       writel(0, mmio + MV_GPIO_PORT_CTL);
-
-       /* FIXME: handle MV_HP_ERRATA_50XXB2 errata */
-
-       tmp = readl(mmio + MV_PCI_EXP_ROM_BAR_CTL);
-       tmp |= ~(1 << 0);
-       writel(tmp, mmio + MV_PCI_EXP_ROM_BAR_CTL);
-}
-
-static void mv5_phy_errata(struct mv_host_priv *hpriv, void __iomem *mmio,
-                          unsigned int port)
-{
-       void __iomem *phy_mmio = mv5_phy_base(mmio, port);
-       const u32 mask = (1<<12) | (1<<11) | (1<<7) | (1<<6) | (1<<5);
-       u32 tmp;
-       int fix_apm_sq = (hpriv->hp_flags & MV_HP_ERRATA_50XXB0);
-
-       if (fix_apm_sq) {
-               tmp = readl(phy_mmio + MV5_LT_MODE);
-               tmp |= (1 << 19);
-               writel(tmp, phy_mmio + MV5_LT_MODE);
-
-               tmp = readl(phy_mmio + MV5_PHY_CTL);
-               tmp &= ~0x3;
-               tmp |= 0x1;
-               writel(tmp, phy_mmio + MV5_PHY_CTL);
-       }
-
-       tmp = readl(phy_mmio + MV5_PHY_MODE);
-       tmp &= ~mask;
-       tmp |= hpriv->signal[port].pre;
-       tmp |= hpriv->signal[port].amps;
-       writel(tmp, phy_mmio + MV5_PHY_MODE);
-}
-
-
-#undef ZERO
-#define ZERO(reg) writel(0, port_mmio + (reg))
-static void mv5_reset_hc_port(struct mv_host_priv *hpriv, void __iomem *mmio,
-                            unsigned int port)
-{
-       void __iomem *port_mmio = mv_port_base(mmio, port);
-
-       writelfl(EDMA_DS, port_mmio + EDMA_CMD_OFS);
-
-       mv_channel_reset(hpriv, mmio, port);
-
-       ZERO(0x028);    /* command */
-       writel(0x11f, port_mmio + EDMA_CFG_OFS);
-       ZERO(0x004);    /* timer */
-       ZERO(0x008);    /* irq err cause */
-       ZERO(0x00c);    /* irq err mask */
-       ZERO(0x010);    /* rq bah */
-       ZERO(0x014);    /* rq inp */
-       ZERO(0x018);    /* rq outp */
-       ZERO(0x01c);    /* respq bah */
-       ZERO(0x024);    /* respq outp */
-       ZERO(0x020);    /* respq inp */
-       ZERO(0x02c);    /* test control */
-       writel(0xbc, port_mmio + EDMA_IORDY_TMOUT);
-}
-#undef ZERO
-
-#define ZERO(reg) writel(0, hc_mmio + (reg))
-static void mv5_reset_one_hc(struct mv_host_priv *hpriv, void __iomem *mmio,
-                       unsigned int hc)
-{
-       void __iomem *hc_mmio = mv_hc_base(mmio, hc);
-       u32 tmp;
-
-       ZERO(0x00c);
-       ZERO(0x010);
-       ZERO(0x014);
-       ZERO(0x018);
-
-       tmp = readl(hc_mmio + 0x20);
-       tmp &= 0x1c1c1c1c;
-       tmp |= 0x03030303;
-       writel(tmp, hc_mmio + 0x20);
-}
-#undef ZERO
-
-static int mv5_reset_hc(struct mv_host_priv *hpriv, void __iomem *mmio,
-                       unsigned int n_hc)
-{
-       unsigned int hc, port;
-
-       for (hc = 0; hc < n_hc; hc++) {
-               for (port = 0; port < MV_PORTS_PER_HC; port++)
-                       mv5_reset_hc_port(hpriv, mmio,
-                                         (hc * MV_PORTS_PER_HC) + port);
-
-               mv5_reset_one_hc(hpriv, mmio, hc);
-       }
-
-       return 0;
-}
-
-#undef ZERO
-#define ZERO(reg) writel(0, mmio + (reg))
-static void mv_reset_pci_bus(struct pci_dev *pdev, void __iomem *mmio)
-{
-       u32 tmp;
-
-       tmp = readl(mmio + MV_PCI_MODE);
-       tmp &= 0xff00ffff;
-       writel(tmp, mmio + MV_PCI_MODE);
-
-       ZERO(MV_PCI_DISC_TIMER);
-       ZERO(MV_PCI_MSI_TRIGGER);
-       writel(0x000100ff, mmio + MV_PCI_XBAR_TMOUT);
-       ZERO(HC_MAIN_IRQ_MASK_OFS);
-       ZERO(MV_PCI_SERR_MASK);
-       ZERO(PCI_IRQ_CAUSE_OFS);
-       ZERO(PCI_IRQ_MASK_OFS);
-       ZERO(MV_PCI_ERR_LOW_ADDRESS);
-       ZERO(MV_PCI_ERR_HIGH_ADDRESS);
-       ZERO(MV_PCI_ERR_ATTRIBUTE);
-       ZERO(MV_PCI_ERR_COMMAND);
-}
-#undef ZERO
-
-static void mv6_reset_flash(struct mv_host_priv *hpriv, void __iomem *mmio)
-{
-       u32 tmp;
-
-       mv5_reset_flash(hpriv, mmio);
-
-       tmp = readl(mmio + MV_GPIO_PORT_CTL);
-       tmp &= 0x3;
-       tmp |= (1 << 5) | (1 << 6);
-       writel(tmp, mmio + MV_GPIO_PORT_CTL);
-}
-
-/**
- *      mv6_reset_hc - Perform the 6xxx global soft reset
- *      @mmio: base address of the HBA
- *
- *      This routine only applies to 6xxx parts.
- *
- *      LOCKING:
- *      Inherited from caller.
- */
-static int mv6_reset_hc(struct mv_host_priv *hpriv, void __iomem *mmio,
-                       unsigned int n_hc)
-{
-       void __iomem *reg = mmio + PCI_MAIN_CMD_STS_OFS;
-       int i, rc = 0;
-       u32 t;
-
-       /* Following procedure defined in PCI "main command and status
-        * register" table.
-        */
-       t = readl(reg);
-       writel(t | STOP_PCI_MASTER, reg);
-
-       for (i = 0; i < 1000; i++) {
-               udelay(1);
-               t = readl(reg);
-               if (PCI_MASTER_EMPTY & t) {
-                       break;
-               }
-       }
-       if (!(PCI_MASTER_EMPTY & t)) {
-               printk(KERN_ERR DRV_NAME ": PCI master won't flush\n");
-               rc = 1;
-               goto done;
-       }
-
-       /* set reset */
-       i = 5;
-       do {
-               writel(t | GLOB_SFT_RST, reg);
-               t = readl(reg);
-               udelay(1);
-       } while (!(GLOB_SFT_RST & t) && (i-- > 0));
-
-       if (!(GLOB_SFT_RST & t)) {
-               printk(KERN_ERR DRV_NAME ": can't set global reset\n");
-               rc = 1;
-               goto done;
-       }
-
-       /* clear reset and *reenable the PCI master* (not mentioned in spec) */
-       i = 5;
-       do {
-               writel(t & ~(GLOB_SFT_RST | STOP_PCI_MASTER), reg);
-               t = readl(reg);
-               udelay(1);
-       } while ((GLOB_SFT_RST & t) && (i-- > 0));
-
-       if (GLOB_SFT_RST & t) {
-               printk(KERN_ERR DRV_NAME ": can't clear global reset\n");
-               rc = 1;
-       }
-done:
-       return rc;
-}
-
-static void mv6_read_preamp(struct mv_host_priv *hpriv, int idx,
-                          void __iomem *mmio)
-{
-       void __iomem *port_mmio;
-       u32 tmp;
-
-       tmp = readl(mmio + MV_RESET_CFG);
-       if ((tmp & (1 << 0)) == 0) {
-               hpriv->signal[idx].amps = 0x7 << 8;
-               hpriv->signal[idx].pre = 0x1 << 5;
-               return;
-       }
-
-       port_mmio = mv_port_base(mmio, idx);
-       tmp = readl(port_mmio + PHY_MODE2);
-
-       hpriv->signal[idx].amps = tmp & 0x700;  /* bits 10:8 */
-       hpriv->signal[idx].pre = tmp & 0xe0;    /* bits 7:5 */
-}
-
-static void mv6_enable_leds(struct mv_host_priv *hpriv, void __iomem *mmio)
-{
-       writel(0x00000060, mmio + MV_GPIO_PORT_CTL);
-}
-
-static void mv6_phy_errata(struct mv_host_priv *hpriv, void __iomem *mmio,
-                          unsigned int port)
-{
-       void __iomem *port_mmio = mv_port_base(mmio, port);
-
-       u32 hp_flags = hpriv->hp_flags;
-       int fix_phy_mode2 =
-               hp_flags & (MV_HP_ERRATA_60X1B2 | MV_HP_ERRATA_60X1C0);
-       int fix_phy_mode4 =
-               hp_flags & (MV_HP_ERRATA_60X1B2 | MV_HP_ERRATA_60X1C0);
-       u32 m2, tmp;
-
-       if (fix_phy_mode2) {
-               m2 = readl(port_mmio + PHY_MODE2);
-               m2 &= ~(1 << 16);
-               m2 |= (1 << 31);
-               writel(m2, port_mmio + PHY_MODE2);
-
-               udelay(200);
-
-               m2 = readl(port_mmio + PHY_MODE2);
-               m2 &= ~((1 << 16) | (1 << 31));
-               writel(m2, port_mmio + PHY_MODE2);
-
-               udelay(200);
-       }
-
-       /* who knows what this magic does */
-       tmp = readl(port_mmio + PHY_MODE3);
-       tmp &= ~0x7F800000;
-       tmp |= 0x2A800000;
-       writel(tmp, port_mmio + PHY_MODE3);
-
-       if (fix_phy_mode4) {
-               u32 m4;
-
-               m4 = readl(port_mmio + PHY_MODE4);
-
-               if (hp_flags & MV_HP_ERRATA_60X1B2)
-                       tmp = readl(port_mmio + 0x310);
-
-               m4 = (m4 & ~(1 << 1)) | (1 << 0);
-
-               writel(m4, port_mmio + PHY_MODE4);
-
-               if (hp_flags & MV_HP_ERRATA_60X1B2)
-                       writel(tmp, port_mmio + 0x310);
-       }
-
-       /* Revert values of pre-emphasis and signal amps to the saved ones */
-       m2 = readl(port_mmio + PHY_MODE2);
-
-       m2 &= ~MV_M2_PREAMP_MASK;
-       m2 |= hpriv->signal[port].amps;
-       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);
-}
-
-static void mv_channel_reset(struct mv_host_priv *hpriv, void __iomem *mmio,
-                            unsigned int port_no)
-{
-       void __iomem *port_mmio = mv_port_base(mmio, port_no);
-
-       writelfl(ATA_RST, port_mmio + EDMA_CMD_OFS);
-
-       if (IS_60XX(hpriv)) {
-               u32 ifctl = readl(port_mmio + SATA_INTERFACE_CTL);
-               ifctl |= (1 << 7);              /* enable gen2i speed */
-               ifctl = (ifctl & 0xfff) | 0x9b1000; /* from chip spec */
-               writelfl(ifctl, port_mmio + SATA_INTERFACE_CTL);
-       }
-
-       udelay(25);             /* allow reset propagation */
-
-       /* Spec never mentions clearing the bit.  Marvell's driver does
-        * clear the bit, however.
-        */
-       writelfl(0, port_mmio + EDMA_CMD_OFS);
-
-       hpriv->ops->phy_errata(hpriv, mmio, port_no);
-
-       if (IS_50XX(hpriv))
-               mdelay(1);
-}
-
-static void mv_stop_and_reset(struct ata_port *ap)
-{
-       struct mv_host_priv *hpriv = ap->host_set->private_data;
-       void __iomem *mmio = ap->host_set->mmio_base;
-
-       mv_stop_dma(ap);
-
-       mv_channel_reset(hpriv, mmio, ap->port_no);
-
-       __mv_phy_reset(ap, 0);
-}
-
-static inline void __msleep(unsigned int msec, int can_sleep)
-{
-       if (can_sleep)
-               msleep(msec);
-       else
-               mdelay(msec);
-}
-
-/**
- *      __mv_phy_reset - Perform eDMA reset followed by COMRESET
- *      @ap: ATA channel to manipulate
- *
- *      Part of this is taken from __sata_phy_reset and modified to
- *      not sleep since this routine gets called from interrupt level.
- *
- *      LOCKING:
- *      Inherited from caller.  This is coded to safe to call at
- *      interrupt level, i.e. it does not sleep.
- */
-static void __mv_phy_reset(struct ata_port *ap, int can_sleep)
-{
-       struct mv_port_priv *pp = ap->private_data;
-       struct mv_host_priv *hpriv = ap->host_set->private_data;
-       void __iomem *port_mmio = mv_ap_base(ap);
-       struct ata_taskfile tf;
-       struct ata_device *dev = &ap->device[0];
-       unsigned long timeout;
-       int retry = 5;
-       u32 sstatus;
-
-       VPRINTK("ENTER, port %u, mmio 0x%p\n", ap->port_no, port_mmio);
-
-       DPRINTK("S-regs after ATA_RST: SStat 0x%08x SErr 0x%08x "
-               "SCtrl 0x%08x\n", mv_scr_read(ap, SCR_STATUS),
-               mv_scr_read(ap, SCR_ERROR), mv_scr_read(ap, SCR_CONTROL));
-
-       /* Issue COMRESET via SControl */
-comreset_retry:
-       sata_scr_write_flush(ap, SCR_CONTROL, 0x301);
-       __msleep(1, can_sleep);
-
-       sata_scr_write_flush(ap, SCR_CONTROL, 0x300);
-       __msleep(20, can_sleep);
-
-       timeout = jiffies + msecs_to_jiffies(200);
-       do {
-               sata_scr_read(ap, SCR_STATUS, &sstatus);
-               sstatus &= 0x3;
-               if ((sstatus == 3) || (sstatus == 0))
-                       break;
-
-               __msleep(1, can_sleep);
-       } while (time_before(jiffies, timeout));
-
-       /* work around errata */
-       if (IS_60XX(hpriv) &&
-           (sstatus != 0x0) && (sstatus != 0x113) && (sstatus != 0x123) &&
-           (retry-- > 0))
-               goto comreset_retry;
-
-       DPRINTK("S-regs after PHY wake: SStat 0x%08x SErr 0x%08x "
-               "SCtrl 0x%08x\n", mv_scr_read(ap, SCR_STATUS),
-               mv_scr_read(ap, SCR_ERROR), mv_scr_read(ap, SCR_CONTROL));
-
-       if (ata_port_online(ap)) {
-               ata_port_probe(ap);
-       } else {
-               sata_scr_read(ap, SCR_STATUS, &sstatus);
-               ata_port_printk(ap, KERN_INFO,
-                               "no device found (phy stat %08x)\n", sstatus);
-               ata_port_disable(ap);
-               return;
-       }
-       ap->cbl = ATA_CBL_SATA;
-
-       /* even after SStatus reflects that device is ready,
-        * it seems to take a while for link to be fully
-        * established (and thus Status no longer 0x80/0x7F),
-        * so we poll a bit for that, here.
-        */
-       retry = 20;
-       while (1) {
-               u8 drv_stat = ata_check_status(ap);
-               if ((drv_stat != 0x80) && (drv_stat != 0x7f))
-                       break;
-               __msleep(500, can_sleep);
-               if (retry-- <= 0)
-                       break;
-       }
-
-       tf.lbah = readb((void __iomem *) ap->ioaddr.lbah_addr);
-       tf.lbam = readb((void __iomem *) ap->ioaddr.lbam_addr);
-       tf.lbal = readb((void __iomem *) ap->ioaddr.lbal_addr);
-       tf.nsect = readb((void __iomem *) ap->ioaddr.nsect_addr);
-
-       dev->class = ata_dev_classify(&tf);
-       if (!ata_dev_enabled(dev)) {
-               VPRINTK("Port disabled post-sig: No device present.\n");
-               ata_port_disable(ap);
-       }
-
-       writelfl(0, port_mmio + EDMA_ERR_IRQ_CAUSE_OFS);
-
-       pp->pp_flags &= ~MV_PP_FLAG_EDMA_EN;
-
-       VPRINTK("EXIT\n");
-}
-
-static void mv_phy_reset(struct ata_port *ap)
-{
-       __mv_phy_reset(ap, 1);
-}
-
-/**
- *      mv_eng_timeout - Routine called by libata when SCSI times out I/O
- *      @ap: ATA channel to manipulate
- *
- *      Intent is to clear all pending error conditions, reset the
- *      chip/bus, fail the command, and move on.
- *
- *      LOCKING:
- *      This routine holds the host_set lock while failing the command.
- */
-static void mv_eng_timeout(struct ata_port *ap)
-{
-       struct ata_queued_cmd *qc;
-       unsigned long flags;
-
-       ata_port_printk(ap, KERN_ERR, "Entering mv_eng_timeout\n");
-       DPRINTK("All regs @ start of eng_timeout\n");
-       mv_dump_all_regs(ap->host_set->mmio_base, ap->port_no,
-                        to_pci_dev(ap->host_set->dev));
-
-       qc = ata_qc_from_tag(ap, ap->active_tag);
-        printk(KERN_ERR "mmio_base %p ap %p qc %p scsi_cmnd %p &cmnd %p\n",
-              ap->host_set->mmio_base, ap, qc, qc->scsicmd,
-              &qc->scsicmd->cmnd);
-
-       spin_lock_irqsave(&ap->host_set->lock, flags);
-       mv_err_intr(ap, 0);
-       mv_stop_and_reset(ap);
-       spin_unlock_irqrestore(&ap->host_set->lock, flags);
-
-       WARN_ON(!(qc->flags & ATA_QCFLAG_ACTIVE));
-       if (qc->flags & ATA_QCFLAG_ACTIVE) {
-               qc->err_mask |= AC_ERR_TIMEOUT;
-               ata_eh_qc_complete(qc);
-       }
-}
-
-/**
- *      mv_port_init - Perform some early initialization on a single port.
- *      @port: libata data structure storing shadow register addresses
- *      @port_mmio: base address of the port
- *
- *      Initialize shadow register mmio addresses, clear outstanding
- *      interrupts on the port, and unmask interrupts for the future
- *      start of the port.
- *
- *      LOCKING:
- *      Inherited from caller.
- */
-static void mv_port_init(struct ata_ioports *port,  void __iomem *port_mmio)
-{
-       unsigned long shd_base = (unsigned long) port_mmio + SHD_BLK_OFS;
-       unsigned serr_ofs;
-
-       /* PIO related setup
-        */
-       port->data_addr = shd_base + (sizeof(u32) * ATA_REG_DATA);
-       port->error_addr =
-               port->feature_addr = shd_base + (sizeof(u32) * ATA_REG_ERR);
-       port->nsect_addr = shd_base + (sizeof(u32) * ATA_REG_NSECT);
-       port->lbal_addr = shd_base + (sizeof(u32) * ATA_REG_LBAL);
-       port->lbam_addr = shd_base + (sizeof(u32) * ATA_REG_LBAM);
-       port->lbah_addr = shd_base + (sizeof(u32) * ATA_REG_LBAH);
-       port->device_addr = shd_base + (sizeof(u32) * ATA_REG_DEVICE);
-       port->status_addr =
-               port->command_addr = shd_base + (sizeof(u32) * ATA_REG_STATUS);
-       /* special case: control/altstatus doesn't have ATA_REG_ address */
-       port->altstatus_addr = port->ctl_addr = shd_base + SHD_CTL_AST_OFS;
-
-       /* unused: */
-       port->cmd_addr = port->bmdma_addr = port->scr_addr = 0;
-
-       /* Clear any currently outstanding port interrupt conditions */
-       serr_ofs = mv_scr_offset(SCR_ERROR);
-       writelfl(readl(port_mmio + serr_ofs), port_mmio + serr_ofs);
-       writelfl(0, port_mmio + EDMA_ERR_IRQ_CAUSE_OFS);
-
-       /* unmask all EDMA error interrupts */
-       writelfl(~0, port_mmio + EDMA_ERR_IRQ_MASK_OFS);
-
-       VPRINTK("EDMA cfg=0x%08x EDMA IRQ err cause/mask=0x%08x/0x%08x\n",
-               readl(port_mmio + EDMA_CFG_OFS),
-               readl(port_mmio + EDMA_ERR_IRQ_CAUSE_OFS),
-               readl(port_mmio + EDMA_ERR_IRQ_MASK_OFS));
-}
-
-static int mv_chip_id(struct pci_dev *pdev, struct mv_host_priv *hpriv,
-                     unsigned int board_idx)
-{
-       u8 rev_id;
-       u32 hp_flags = hpriv->hp_flags;
-
-       pci_read_config_byte(pdev, PCI_REVISION_ID, &rev_id);
-
-       switch(board_idx) {
-       case chip_5080:
-               hpriv->ops = &mv5xxx_ops;
-               hp_flags |= MV_HP_50XX;
-
-               switch (rev_id) {
-               case 0x1:
-                       hp_flags |= MV_HP_ERRATA_50XXB0;
-                       break;
-               case 0x3:
-                       hp_flags |= MV_HP_ERRATA_50XXB2;
-                       break;
-               default:
-                       dev_printk(KERN_WARNING, &pdev->dev,
-                          "Applying 50XXB2 workarounds to unknown rev\n");
-                       hp_flags |= MV_HP_ERRATA_50XXB2;
-                       break;
-               }
-               break;
-
-       case chip_504x:
-       case chip_508x:
-               hpriv->ops = &mv5xxx_ops;
-               hp_flags |= MV_HP_50XX;
-
-               switch (rev_id) {
-               case 0x0:
-                       hp_flags |= MV_HP_ERRATA_50XXB0;
-                       break;
-               case 0x3:
-                       hp_flags |= MV_HP_ERRATA_50XXB2;
-                       break;
-               default:
-                       dev_printk(KERN_WARNING, &pdev->dev,
-                          "Applying B2 workarounds to unknown rev\n");
-                       hp_flags |= MV_HP_ERRATA_50XXB2;
-                       break;
-               }
-               break;
-
-       case chip_604x:
-       case chip_608x:
-               hpriv->ops = &mv6xxx_ops;
-
-               switch (rev_id) {
-               case 0x7:
-                       hp_flags |= MV_HP_ERRATA_60X1B2;
-                       break;
-               case 0x9:
-                       hp_flags |= MV_HP_ERRATA_60X1C0;
-                       break;
-               default:
-                       dev_printk(KERN_WARNING, &pdev->dev,
-                                  "Applying B2 workarounds to unknown rev\n");
-                       hp_flags |= MV_HP_ERRATA_60X1B2;
-                       break;
-               }
-               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;
-       }
-
-       hpriv->hp_flags = hp_flags;
-
-       return 0;
-}
-
-/**
- *      mv_init_host - Perform some early initialization of the host.
- *     @pdev: host PCI device
- *      @probe_ent: early data struct representing the host
- *
- *      If possible, do an early global reset of the host.  Then do
- *      our port init and clear/unmask all/relevant host interrupts.
- *
- *      LOCKING:
- *      Inherited from caller.
- */
-static int mv_init_host(struct pci_dev *pdev, struct ata_probe_ent *probe_ent,
-                       unsigned int board_idx)
-{
-       int rc = 0, n_hc, port, hc;
-       void __iomem *mmio = probe_ent->mmio_base;
-       struct mv_host_priv *hpriv = probe_ent->private_data;
-
-       /* global interrupt mask */
-       writel(0, mmio + HC_MAIN_IRQ_MASK_OFS);
-
-       rc = mv_chip_id(pdev, hpriv, board_idx);
-       if (rc)
-               goto done;
-
-       n_hc = mv_get_hc_count(probe_ent->host_flags);
-       probe_ent->n_ports = MV_PORTS_PER_HC * n_hc;
-
-       for (port = 0; port < probe_ent->n_ports; port++)
-               hpriv->ops->read_preamp(hpriv, port, mmio);
-
-       rc = hpriv->ops->reset_hc(hpriv, mmio, n_hc);
-       if (rc)
-               goto done;
-
-       hpriv->ops->reset_flash(hpriv, mmio);
-       hpriv->ops->reset_bus(pdev, mmio);
-       hpriv->ops->enable_leds(hpriv, mmio);
-
-       for (port = 0; port < probe_ent->n_ports; port++) {
-               if (IS_60XX(hpriv)) {
-                       void __iomem *port_mmio = mv_port_base(mmio, port);
-
-                       u32 ifctl = readl(port_mmio + SATA_INTERFACE_CTL);
-                       ifctl |= (1 << 7);              /* enable gen2i speed */
-                       ifctl = (ifctl & 0xfff) | 0x9b1000; /* from chip spec */
-                       writelfl(ifctl, port_mmio + SATA_INTERFACE_CTL);
-               }
-
-               hpriv->ops->phy_errata(hpriv, mmio, port);
-       }
-
-       for (port = 0; port < probe_ent->n_ports; port++) {
-               void __iomem *port_mmio = mv_port_base(mmio, port);
-               mv_port_init(&probe_ent->port[port], port_mmio);
-       }
-
-       for (hc = 0; hc < n_hc; hc++) {
-               void __iomem *hc_mmio = mv_hc_base(mmio, hc);
-
-               VPRINTK("HC%i: HC config=0x%08x HC IRQ cause "
-                       "(before clear)=0x%08x\n", hc,
-                       readl(hc_mmio + HC_CFG_OFS),
-                       readl(hc_mmio + HC_IRQ_CAUSE_OFS));
-
-               /* Clear any currently outstanding hc interrupt conditions */
-               writelfl(0, hc_mmio + HC_IRQ_CAUSE_OFS);
-       }
-
-       /* Clear any currently outstanding host interrupt conditions */
-       writelfl(0, mmio + PCI_IRQ_CAUSE_OFS);
-
-       /* and unmask interrupt generation for host regs */
-       writelfl(PCI_UNMASK_ALL_IRQS, mmio + PCI_IRQ_MASK_OFS);
-       writelfl(~HC_MAIN_MASKED_IRQS, mmio + HC_MAIN_IRQ_MASK_OFS);
-
-       VPRINTK("HC MAIN IRQ cause/mask=0x%08x/0x%08x "
-               "PCI int cause/mask=0x%08x/0x%08x\n",
-               readl(mmio + HC_MAIN_IRQ_CAUSE_OFS),
-               readl(mmio + HC_MAIN_IRQ_MASK_OFS),
-               readl(mmio + PCI_IRQ_CAUSE_OFS),
-               readl(mmio + PCI_IRQ_MASK_OFS));
-
-done:
-       return rc;
-}
-
-/**
- *      mv_print_info - Dump key info to kernel log for perusal.
- *      @probe_ent: early data struct representing the host
- *
- *      FIXME: complete this.
- *
- *      LOCKING:
- *      Inherited from caller.
- */
-static void mv_print_info(struct ata_probe_ent *probe_ent)
-{
-       struct pci_dev *pdev = to_pci_dev(probe_ent->dev);
-       struct mv_host_priv *hpriv = probe_ent->private_data;
-       u8 rev_id, scc;
-       const char *scc_s;
-
-       /* Use this to determine the HW stepping of the chip so we know
-        * what errata to workaround
-        */
-       pci_read_config_byte(pdev, PCI_REVISION_ID, &rev_id);
-
-       pci_read_config_byte(pdev, PCI_CLASS_DEVICE, &scc);
-       if (scc == 0)
-               scc_s = "SCSI";
-       else if (scc == 0x01)
-               scc_s = "RAID";
-       else
-               scc_s = "unknown";
-
-       dev_printk(KERN_INFO, &pdev->dev,
-              "%u slots %u ports %s mode IRQ via %s\n",
-              (unsigned)MV_MAX_Q_DEPTH, probe_ent->n_ports,
-              scc_s, (MV_HP_FLAG_MSI & hpriv->hp_flags) ? "MSI" : "INTx");
-}
-
-/**
- *      mv_init_one - handle a positive probe of a Marvell host
- *      @pdev: PCI device found
- *      @ent: PCI device ID entry for the matched host
- *
- *      LOCKING:
- *      Inherited from caller.
- */
-static int mv_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
-{
-       static int printed_version = 0;
-       struct ata_probe_ent *probe_ent = NULL;
-       struct mv_host_priv *hpriv;
-       unsigned int board_idx = (unsigned int)ent->driver_data;
-       void __iomem *mmio_base;
-       int pci_dev_busy = 0, rc;
-
-       if (!printed_version++)
-               dev_printk(KERN_INFO, &pdev->dev, "version " DRV_VERSION "\n");
-
-       rc = pci_enable_device(pdev);
-       if (rc) {
-               return rc;
-       }
-       pci_set_master(pdev);
-
-       rc = pci_request_regions(pdev, DRV_NAME);
-       if (rc) {
-               pci_dev_busy = 1;
-               goto err_out;
-       }
-
-       probe_ent = kmalloc(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);
-
-       mmio_base = pci_iomap(pdev, MV_PRIMARY_BAR, 0);
-       if (mmio_base == NULL) {
-               rc = -ENOMEM;
-               goto err_out_free_ent;
-       }
-
-       hpriv = kmalloc(sizeof(*hpriv), GFP_KERNEL);
-       if (!hpriv) {
-               rc = -ENOMEM;
-               goto err_out_iounmap;
-       }
-       memset(hpriv, 0, sizeof(*hpriv));
-
-       probe_ent->sht = mv_port_info[board_idx].sht;
-       probe_ent->host_flags = mv_port_info[board_idx].host_flags;
-       probe_ent->pio_mask = mv_port_info[board_idx].pio_mask;
-       probe_ent->udma_mask = mv_port_info[board_idx].udma_mask;
-       probe_ent->port_ops = mv_port_info[board_idx].port_ops;
-
-       probe_ent->irq = pdev->irq;
-       probe_ent->irq_flags = IRQF_SHARED;
-       probe_ent->mmio_base = mmio_base;
-       probe_ent->private_data = hpriv;
-
-       /* initialize adapter */
-       rc = mv_init_host(pdev, probe_ent, board_idx);
-       if (rc) {
-               goto err_out_hpriv;
-       }
-
-       /* Enable interrupts */
-       if (msi && pci_enable_msi(pdev) == 0) {
-               hpriv->hp_flags |= MV_HP_FLAG_MSI;
-       } else {
-               pci_intx(pdev, 1);
-       }
-
-       mv_dump_pci_cfg(pdev, 0x68);
-       mv_print_info(probe_ent);
-
-       if (ata_device_add(probe_ent) == 0) {
-               rc = -ENODEV;           /* No devices discovered */
-               goto err_out_dev_add;
-       }
-
-       kfree(probe_ent);
-       return 0;
-
-err_out_dev_add:
-       if (MV_HP_FLAG_MSI & hpriv->hp_flags) {
-               pci_disable_msi(pdev);
-       } else {
-               pci_intx(pdev, 0);
-       }
-err_out_hpriv:
-       kfree(hpriv);
-err_out_iounmap:
-       pci_iounmap(pdev, mmio_base);
-err_out_free_ent:
-       kfree(probe_ent);
-err_out_regions:
-       pci_release_regions(pdev);
-err_out:
-       if (!pci_dev_busy) {
-               pci_disable_device(pdev);
-       }
-
-       return rc;
-}
-
-static int __init mv_init(void)
-{
-       return pci_register_driver(&mv_pci_driver);
-}
-
-static void __exit mv_exit(void)
-{
-       pci_unregister_driver(&mv_pci_driver);
-}
-
-MODULE_AUTHOR("Brett Russ");
-MODULE_DESCRIPTION("SCSI low-level driver for Marvell SATA controllers");
-MODULE_LICENSE("GPL");
-MODULE_DEVICE_TABLE(pci, mv_pci_tbl);
-MODULE_VERSION(DRV_VERSION);
-
-module_param(msi, int, 0444);
-MODULE_PARM_DESC(msi, "Enable use of PCI MSI (0=off, 1=on)");
-
-module_init(mv_init);
-module_exit(mv_exit);
diff --git a/drivers/scsi/sata_nv.c b/drivers/scsi/sata_nv.c
deleted file mode 100644 (file)
index be46df7..0000000
+++ /dev/null
@@ -1,595 +0,0 @@
-/*
- *  sata_nv.c - NVIDIA nForce SATA
- *
- *  Copyright 2004 NVIDIA Corp.  All rights reserved.
- *  Copyright 2004 Andrew Chew
- *
- *
- *  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.*
- *
- *  No hardware documentation available outside of NVIDIA.
- *  This driver programs the NVIDIA SATA controller in a similar
- *  fashion as with other PCI IDE BMDMA controllers, with a few
- *  NV-specific details such as register offsets, SATA phy location,
- *  hotplug info, etc.
- *
- */
-
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/pci.h>
-#include <linux/init.h>
-#include <linux/blkdev.h>
-#include <linux/delay.h>
-#include <linux/interrupt.h>
-#include <linux/device.h>
-#include <scsi/scsi_host.h>
-#include <linux/libata.h>
-
-#define DRV_NAME                       "sata_nv"
-#define DRV_VERSION                    "2.0"
-
-enum {
-       NV_PORTS                        = 2,
-       NV_PIO_MASK                     = 0x1f,
-       NV_MWDMA_MASK                   = 0x07,
-       NV_UDMA_MASK                    = 0x7f,
-       NV_PORT0_SCR_REG_OFFSET         = 0x00,
-       NV_PORT1_SCR_REG_OFFSET         = 0x40,
-
-       /* INT_STATUS/ENABLE */
-       NV_INT_STATUS                   = 0x10,
-       NV_INT_ENABLE                   = 0x11,
-       NV_INT_STATUS_CK804             = 0x440,
-       NV_INT_ENABLE_CK804             = 0x441,
-
-       /* INT_STATUS/ENABLE bits */
-       NV_INT_DEV                      = 0x01,
-       NV_INT_PM                       = 0x02,
-       NV_INT_ADDED                    = 0x04,
-       NV_INT_REMOVED                  = 0x08,
-
-       NV_INT_PORT_SHIFT               = 4,    /* each port occupies 4 bits */
-
-       NV_INT_ALL                      = 0x0f,
-       NV_INT_MASK                     = NV_INT_DEV |
-                                         NV_INT_ADDED | NV_INT_REMOVED,
-
-       /* INT_CONFIG */
-       NV_INT_CONFIG                   = 0x12,
-       NV_INT_CONFIG_METHD             = 0x01, // 0 = INT, 1 = SMI
-
-       // For PCI config register 20
-       NV_MCP_SATA_CFG_20              = 0x50,
-       NV_MCP_SATA_CFG_20_SATA_SPACE_EN = 0x04,
-};
-
-static int nv_init_one (struct pci_dev *pdev, const struct pci_device_id *ent);
-static void nv_ck804_host_stop(struct ata_host_set *host_set);
-static irqreturn_t nv_generic_interrupt(int irq, void *dev_instance,
-                                       struct pt_regs *regs);
-static irqreturn_t nv_nf2_interrupt(int irq, void *dev_instance,
-                                   struct pt_regs *regs);
-static irqreturn_t nv_ck804_interrupt(int irq, void *dev_instance,
-                                     struct pt_regs *regs);
-static u32 nv_scr_read (struct ata_port *ap, unsigned int sc_reg);
-static void nv_scr_write (struct ata_port *ap, unsigned int sc_reg, u32 val);
-
-static void nv_nf2_freeze(struct ata_port *ap);
-static void nv_nf2_thaw(struct ata_port *ap);
-static void nv_ck804_freeze(struct ata_port *ap);
-static void nv_ck804_thaw(struct ata_port *ap);
-static void nv_error_handler(struct ata_port *ap);
-
-enum nv_host_type
-{
-       GENERIC,
-       NFORCE2,
-       NFORCE3 = NFORCE2,      /* NF2 == NF3 as far as sata_nv is concerned */
-       CK804
-};
-
-static const struct pci_device_id nv_pci_tbl[] = {
-       { PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE2S_SATA,
-               PCI_ANY_ID, PCI_ANY_ID, 0, 0, NFORCE2 },
-       { PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE3S_SATA,
-               PCI_ANY_ID, PCI_ANY_ID, 0, 0, NFORCE3 },
-       { PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE3S_SATA2,
-               PCI_ANY_ID, PCI_ANY_ID, 0, 0, NFORCE3 },
-       { PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_CK804_SATA,
-               PCI_ANY_ID, PCI_ANY_ID, 0, 0, CK804 },
-       { PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_CK804_SATA2,
-               PCI_ANY_ID, PCI_ANY_ID, 0, 0, CK804 },
-       { PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP04_SATA,
-               PCI_ANY_ID, PCI_ANY_ID, 0, 0, CK804 },
-       { PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP04_SATA2,
-               PCI_ANY_ID, PCI_ANY_ID, 0, 0, CK804 },
-       { PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP51_SATA,
-               PCI_ANY_ID, PCI_ANY_ID, 0, 0, GENERIC },
-       { PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP51_SATA2,
-               PCI_ANY_ID, PCI_ANY_ID, 0, 0, GENERIC },
-       { PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP55_SATA,
-               PCI_ANY_ID, PCI_ANY_ID, 0, 0, GENERIC },
-       { PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP55_SATA2,
-               PCI_ANY_ID, PCI_ANY_ID, 0, 0, GENERIC },
-       { PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP61_SATA,
-               PCI_ANY_ID, PCI_ANY_ID, 0, 0, GENERIC },
-       { PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP61_SATA2,
-               PCI_ANY_ID, PCI_ANY_ID, 0, 0, GENERIC },
-       { PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP61_SATA3,
-               PCI_ANY_ID, PCI_ANY_ID, 0, 0, GENERIC },
-       { PCI_VENDOR_ID_NVIDIA, 0x045c, PCI_ANY_ID, PCI_ANY_ID, 0, 0, GENERIC },
-       { PCI_VENDOR_ID_NVIDIA, 0x045d, PCI_ANY_ID, PCI_ANY_ID, 0, 0, GENERIC },
-       { PCI_VENDOR_ID_NVIDIA, 0x045e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, GENERIC },
-       { PCI_VENDOR_ID_NVIDIA, 0x045f, PCI_ANY_ID, PCI_ANY_ID, 0, 0, GENERIC },
-       { PCI_VENDOR_ID_NVIDIA, PCI_ANY_ID,
-               PCI_ANY_ID, PCI_ANY_ID,
-               PCI_CLASS_STORAGE_IDE<<8, 0xffff00, GENERIC },
-       { PCI_VENDOR_ID_NVIDIA, PCI_ANY_ID,
-               PCI_ANY_ID, PCI_ANY_ID,
-               PCI_CLASS_STORAGE_RAID<<8, 0xffff00, GENERIC },
-       { 0, } /* terminate list */
-};
-
-static struct pci_driver nv_pci_driver = {
-       .name                   = DRV_NAME,
-       .id_table               = nv_pci_tbl,
-       .probe                  = nv_init_one,
-       .remove                 = ata_pci_remove_one,
-};
-
-static struct scsi_host_template nv_sht = {
-       .module                 = THIS_MODULE,
-       .name                   = DRV_NAME,
-       .ioctl                  = ata_scsi_ioctl,
-       .queuecommand           = ata_scsi_queuecmd,
-       .can_queue              = ATA_DEF_QUEUE,
-       .this_id                = ATA_SHT_THIS_ID,
-       .sg_tablesize           = LIBATA_MAX_PRD,
-       .cmd_per_lun            = ATA_SHT_CMD_PER_LUN,
-       .emulated               = ATA_SHT_EMULATED,
-       .use_clustering         = ATA_SHT_USE_CLUSTERING,
-       .proc_name              = DRV_NAME,
-       .dma_boundary           = ATA_DMA_BOUNDARY,
-       .slave_configure        = ata_scsi_slave_config,
-       .slave_destroy          = ata_scsi_slave_destroy,
-       .bios_param             = ata_std_bios_param,
-};
-
-static const struct ata_port_operations nv_generic_ops = {
-       .port_disable           = ata_port_disable,
-       .tf_load                = ata_tf_load,
-       .tf_read                = ata_tf_read,
-       .exec_command           = ata_exec_command,
-       .check_status           = ata_check_status,
-       .dev_select             = ata_std_dev_select,
-       .bmdma_setup            = ata_bmdma_setup,
-       .bmdma_start            = ata_bmdma_start,
-       .bmdma_stop             = ata_bmdma_stop,
-       .bmdma_status           = ata_bmdma_status,
-       .qc_prep                = ata_qc_prep,
-       .qc_issue               = ata_qc_issue_prot,
-       .freeze                 = ata_bmdma_freeze,
-       .thaw                   = ata_bmdma_thaw,
-       .error_handler          = nv_error_handler,
-       .post_internal_cmd      = ata_bmdma_post_internal_cmd,
-       .data_xfer              = ata_pio_data_xfer,
-       .irq_handler            = nv_generic_interrupt,
-       .irq_clear              = ata_bmdma_irq_clear,
-       .scr_read               = nv_scr_read,
-       .scr_write              = nv_scr_write,
-       .port_start             = ata_port_start,
-       .port_stop              = ata_port_stop,
-       .host_stop              = ata_pci_host_stop,
-};
-
-static const struct ata_port_operations nv_nf2_ops = {
-       .port_disable           = ata_port_disable,
-       .tf_load                = ata_tf_load,
-       .tf_read                = ata_tf_read,
-       .exec_command           = ata_exec_command,
-       .check_status           = ata_check_status,
-       .dev_select             = ata_std_dev_select,
-       .bmdma_setup            = ata_bmdma_setup,
-       .bmdma_start            = ata_bmdma_start,
-       .bmdma_stop             = ata_bmdma_stop,
-       .bmdma_status           = ata_bmdma_status,
-       .qc_prep                = ata_qc_prep,
-       .qc_issue               = ata_qc_issue_prot,
-       .freeze                 = nv_nf2_freeze,
-       .thaw                   = nv_nf2_thaw,
-       .error_handler          = nv_error_handler,
-       .post_internal_cmd      = ata_bmdma_post_internal_cmd,
-       .data_xfer              = ata_pio_data_xfer,
-       .irq_handler            = nv_nf2_interrupt,
-       .irq_clear              = ata_bmdma_irq_clear,
-       .scr_read               = nv_scr_read,
-       .scr_write              = nv_scr_write,
-       .port_start             = ata_port_start,
-       .port_stop              = ata_port_stop,
-       .host_stop              = ata_pci_host_stop,
-};
-
-static const struct ata_port_operations nv_ck804_ops = {
-       .port_disable           = ata_port_disable,
-       .tf_load                = ata_tf_load,
-       .tf_read                = ata_tf_read,
-       .exec_command           = ata_exec_command,
-       .check_status           = ata_check_status,
-       .dev_select             = ata_std_dev_select,
-       .bmdma_setup            = ata_bmdma_setup,
-       .bmdma_start            = ata_bmdma_start,
-       .bmdma_stop             = ata_bmdma_stop,
-       .bmdma_status           = ata_bmdma_status,
-       .qc_prep                = ata_qc_prep,
-       .qc_issue               = ata_qc_issue_prot,
-       .freeze                 = nv_ck804_freeze,
-       .thaw                   = nv_ck804_thaw,
-       .error_handler          = nv_error_handler,
-       .post_internal_cmd      = ata_bmdma_post_internal_cmd,
-       .data_xfer              = ata_pio_data_xfer,
-       .irq_handler            = nv_ck804_interrupt,
-       .irq_clear              = ata_bmdma_irq_clear,
-       .scr_read               = nv_scr_read,
-       .scr_write              = nv_scr_write,
-       .port_start             = ata_port_start,
-       .port_stop              = ata_port_stop,
-       .host_stop              = nv_ck804_host_stop,
-};
-
-static struct ata_port_info nv_port_info[] = {
-       /* generic */
-       {
-               .sht            = &nv_sht,
-               .host_flags     = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY,
-               .pio_mask       = NV_PIO_MASK,
-               .mwdma_mask     = NV_MWDMA_MASK,
-               .udma_mask      = NV_UDMA_MASK,
-               .port_ops       = &nv_generic_ops,
-       },
-       /* nforce2/3 */
-       {
-               .sht            = &nv_sht,
-               .host_flags     = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY,
-               .pio_mask       = NV_PIO_MASK,
-               .mwdma_mask     = NV_MWDMA_MASK,
-               .udma_mask      = NV_UDMA_MASK,
-               .port_ops       = &nv_nf2_ops,
-       },
-       /* ck804 */
-       {
-               .sht            = &nv_sht,
-               .host_flags     = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY,
-               .pio_mask       = NV_PIO_MASK,
-               .mwdma_mask     = NV_MWDMA_MASK,
-               .udma_mask      = NV_UDMA_MASK,
-               .port_ops       = &nv_ck804_ops,
-       },
-};
-
-MODULE_AUTHOR("NVIDIA");
-MODULE_DESCRIPTION("low-level driver for NVIDIA nForce SATA controller");
-MODULE_LICENSE("GPL");
-MODULE_DEVICE_TABLE(pci, nv_pci_tbl);
-MODULE_VERSION(DRV_VERSION);
-
-static irqreturn_t nv_generic_interrupt(int irq, void *dev_instance,
-                                       struct pt_regs *regs)
-{
-       struct ata_host_set *host_set = dev_instance;
-       unsigned int i;
-       unsigned int handled = 0;
-       unsigned long flags;
-
-       spin_lock_irqsave(&host_set->lock, flags);
-
-       for (i = 0; i < host_set->n_ports; i++) {
-               struct ata_port *ap;
-
-               ap = host_set->ports[i];
-               if (ap &&
-                   !(ap->flags & ATA_FLAG_DISABLED)) {
-                       struct ata_queued_cmd *qc;
-
-                       qc = ata_qc_from_tag(ap, ap->active_tag);
-                       if (qc && (!(qc->tf.flags & ATA_TFLAG_POLLING)))
-                               handled += ata_host_intr(ap, qc);
-                       else
-                               // No request pending?  Clear interrupt status
-                               // anyway, in case there's one pending.
-                               ap->ops->check_status(ap);
-               }
-
-       }
-
-       spin_unlock_irqrestore(&host_set->lock, flags);
-
-       return IRQ_RETVAL(handled);
-}
-
-static int nv_host_intr(struct ata_port *ap, u8 irq_stat)
-{
-       struct ata_queued_cmd *qc = ata_qc_from_tag(ap, ap->active_tag);
-       int handled;
-
-       /* freeze if hotplugged */
-       if (unlikely(irq_stat & (NV_INT_ADDED | NV_INT_REMOVED))) {
-               ata_port_freeze(ap);
-               return 1;
-       }
-
-       /* bail out if not our interrupt */
-       if (!(irq_stat & NV_INT_DEV))
-               return 0;
-
-       /* DEV interrupt w/ no active qc? */
-       if (unlikely(!qc || (qc->tf.flags & ATA_TFLAG_POLLING))) {
-               ata_check_status(ap);
-               return 1;
-       }
-
-       /* handle interrupt */
-       handled = ata_host_intr(ap, qc);
-       if (unlikely(!handled)) {
-               /* spurious, clear it */
-               ata_check_status(ap);
-       }
-
-       return 1;
-}
-
-static irqreturn_t nv_do_interrupt(struct ata_host_set *host_set, u8 irq_stat)
-{
-       int i, handled = 0;
-
-       for (i = 0; i < host_set->n_ports; i++) {
-               struct ata_port *ap = host_set->ports[i];
-
-               if (ap && !(ap->flags & ATA_FLAG_DISABLED))
-                       handled += nv_host_intr(ap, irq_stat);
-
-               irq_stat >>= NV_INT_PORT_SHIFT;
-       }
-
-       return IRQ_RETVAL(handled);
-}
-
-static irqreturn_t nv_nf2_interrupt(int irq, void *dev_instance,
-                                   struct pt_regs *regs)
-{
-       struct ata_host_set *host_set = dev_instance;
-       u8 irq_stat;
-       irqreturn_t ret;
-
-       spin_lock(&host_set->lock);
-       irq_stat = inb(host_set->ports[0]->ioaddr.scr_addr + NV_INT_STATUS);
-       ret = nv_do_interrupt(host_set, irq_stat);
-       spin_unlock(&host_set->lock);
-
-       return ret;
-}
-
-static irqreturn_t nv_ck804_interrupt(int irq, void *dev_instance,
-                                     struct pt_regs *regs)
-{
-       struct ata_host_set *host_set = dev_instance;
-       u8 irq_stat;
-       irqreturn_t ret;
-
-       spin_lock(&host_set->lock);
-       irq_stat = readb(host_set->mmio_base + NV_INT_STATUS_CK804);
-       ret = nv_do_interrupt(host_set, irq_stat);
-       spin_unlock(&host_set->lock);
-
-       return ret;
-}
-
-static u32 nv_scr_read (struct ata_port *ap, unsigned int sc_reg)
-{
-       if (sc_reg > SCR_CONTROL)
-               return 0xffffffffU;
-
-       return ioread32((void __iomem *)ap->ioaddr.scr_addr + (sc_reg * 4));
-}
-
-static void nv_scr_write (struct ata_port *ap, unsigned int sc_reg, u32 val)
-{
-       if (sc_reg > SCR_CONTROL)
-               return;
-
-       iowrite32(val, (void __iomem *)ap->ioaddr.scr_addr + (sc_reg * 4));
-}
-
-static void nv_nf2_freeze(struct ata_port *ap)
-{
-       unsigned long scr_addr = ap->host_set->ports[0]->ioaddr.scr_addr;
-       int shift = ap->port_no * NV_INT_PORT_SHIFT;
-       u8 mask;
-
-       mask = inb(scr_addr + NV_INT_ENABLE);
-       mask &= ~(NV_INT_ALL << shift);
-       outb(mask, scr_addr + NV_INT_ENABLE);
-}
-
-static void nv_nf2_thaw(struct ata_port *ap)
-{
-       unsigned long scr_addr = ap->host_set->ports[0]->ioaddr.scr_addr;
-       int shift = ap->port_no * NV_INT_PORT_SHIFT;
-       u8 mask;
-
-       outb(NV_INT_ALL << shift, scr_addr + NV_INT_STATUS);
-
-       mask = inb(scr_addr + NV_INT_ENABLE);
-       mask |= (NV_INT_MASK << shift);
-       outb(mask, scr_addr + NV_INT_ENABLE);
-}
-
-static void nv_ck804_freeze(struct ata_port *ap)
-{
-       void __iomem *mmio_base = ap->host_set->mmio_base;
-       int shift = ap->port_no * NV_INT_PORT_SHIFT;
-       u8 mask;
-
-       mask = readb(mmio_base + NV_INT_ENABLE_CK804);
-       mask &= ~(NV_INT_ALL << shift);
-       writeb(mask, mmio_base + NV_INT_ENABLE_CK804);
-}
-
-static void nv_ck804_thaw(struct ata_port *ap)
-{
-       void __iomem *mmio_base = ap->host_set->mmio_base;
-       int shift = ap->port_no * NV_INT_PORT_SHIFT;
-       u8 mask;
-
-       writeb(NV_INT_ALL << shift, mmio_base + NV_INT_STATUS_CK804);
-
-       mask = readb(mmio_base + NV_INT_ENABLE_CK804);
-       mask |= (NV_INT_MASK << shift);
-       writeb(mask, mmio_base + NV_INT_ENABLE_CK804);
-}
-
-static int nv_hardreset(struct ata_port *ap, unsigned int *class)
-{
-       unsigned int dummy;
-
-       /* SATA hardreset fails to retrieve proper device signature on
-        * some controllers.  Don't classify on hardreset.  For more
-        * info, see http://bugme.osdl.org/show_bug.cgi?id=3352
-        */
-       return sata_std_hardreset(ap, &dummy);
-}
-
-static void nv_error_handler(struct ata_port *ap)
-{
-       ata_bmdma_drive_eh(ap, ata_std_prereset, ata_std_softreset,
-                          nv_hardreset, ata_std_postreset);
-}
-
-static int nv_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
-{
-       static int printed_version = 0;
-       struct ata_port_info *ppi;
-       struct ata_probe_ent *probe_ent;
-       int pci_dev_busy = 0;
-       int rc;
-       u32 bar;
-       unsigned long base;
-
-        // Make sure this is a SATA controller by counting the number of bars
-        // (NVIDIA SATA controllers will always have six bars).  Otherwise,
-        // it's an IDE controller and we ignore it.
-       for (bar=0; bar<6; bar++)
-               if (pci_resource_start(pdev, bar) == 0)
-                       return -ENODEV;
-
-       if (!printed_version++)
-               dev_printk(KERN_DEBUG, &pdev->dev, "version " DRV_VERSION "\n");
-
-       rc = pci_enable_device(pdev);
-       if (rc)
-               goto err_out;
-
-       rc = pci_request_regions(pdev, DRV_NAME);
-       if (rc) {
-               pci_dev_busy = 1;
-               goto err_out_disable;
-       }
-
-       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;
-
-       rc = -ENOMEM;
-
-       ppi = &nv_port_info[ent->driver_data];
-       probe_ent = ata_pci_init_native_mode(pdev, &ppi, ATA_PORT_PRIMARY | ATA_PORT_SECONDARY);
-       if (!probe_ent)
-               goto err_out_regions;
-
-       probe_ent->mmio_base = pci_iomap(pdev, 5, 0);
-       if (!probe_ent->mmio_base) {
-               rc = -EIO;
-               goto err_out_free_ent;
-       }
-
-       base = (unsigned long)probe_ent->mmio_base;
-
-       probe_ent->port[0].scr_addr = base + NV_PORT0_SCR_REG_OFFSET;
-       probe_ent->port[1].scr_addr = base + NV_PORT1_SCR_REG_OFFSET;
-
-       /* enable SATA space for CK804 */
-       if (ent->driver_data == CK804) {
-               u8 regval;
-
-               pci_read_config_byte(pdev, NV_MCP_SATA_CFG_20, &regval);
-               regval |= NV_MCP_SATA_CFG_20_SATA_SPACE_EN;
-               pci_write_config_byte(pdev, NV_MCP_SATA_CFG_20, regval);
-       }
-
-       pci_set_master(pdev);
-
-       rc = ata_device_add(probe_ent);
-       if (rc != NV_PORTS)
-               goto err_out_iounmap;
-
-       kfree(probe_ent);
-
-       return 0;
-
-err_out_iounmap:
-       pci_iounmap(pdev, probe_ent->mmio_base);
-err_out_free_ent:
-       kfree(probe_ent);
-err_out_regions:
-       pci_release_regions(pdev);
-err_out_disable:
-       if (!pci_dev_busy)
-               pci_disable_device(pdev);
-err_out:
-       return rc;
-}
-
-static void nv_ck804_host_stop(struct ata_host_set *host_set)
-{
-       struct pci_dev *pdev = to_pci_dev(host_set->dev);
-       u8 regval;
-
-       /* disable SATA space for CK804 */
-       pci_read_config_byte(pdev, NV_MCP_SATA_CFG_20, &regval);
-       regval &= ~NV_MCP_SATA_CFG_20_SATA_SPACE_EN;
-       pci_write_config_byte(pdev, NV_MCP_SATA_CFG_20, regval);
-
-       ata_pci_host_stop(host_set);
-}
-
-static int __init nv_init(void)
-{
-       return pci_register_driver(&nv_pci_driver);
-}
-
-static void __exit nv_exit(void)
-{
-       pci_unregister_driver(&nv_pci_driver);
-}
-
-module_init(nv_init);
-module_exit(nv_exit);
diff --git a/drivers/scsi/sata_promise.c b/drivers/scsi/sata_promise.c
deleted file mode 100644 (file)
index a5b3a7d..0000000
+++ /dev/null
@@ -1,844 +0,0 @@
-/*
- *  sata_promise.c - Promise SATA
- *
- *  Maintained by:  Jeff Garzik <jgarzik@pobox.com>
- *                 Please ALWAYS copy linux-ide@vger.kernel.org
- *                 on emails.
- *
- *  Copyright 2003-2004 Red Hat, Inc.
- *
- *
- *  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 information only available under NDA.
- *
- */
-
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/pci.h>
-#include <linux/init.h>
-#include <linux/blkdev.h>
-#include <linux/delay.h>
-#include <linux/interrupt.h>
-#include <linux/sched.h>
-#include <linux/device.h>
-#include <scsi/scsi_host.h>
-#include <scsi/scsi_cmnd.h>
-#include <linux/libata.h>
-#include <asm/io.h>
-#include "sata_promise.h"
-
-#define DRV_NAME       "sata_promise"
-#define DRV_VERSION    "1.04"
-
-
-enum {
-       PDC_PKT_SUBMIT          = 0x40, /* Command packet pointer addr */
-       PDC_INT_SEQMASK         = 0x40, /* Mask of asserted SEQ INTs */
-       PDC_TBG_MODE            = 0x41, /* TBG mode */
-       PDC_FLASH_CTL           = 0x44, /* Flash control register */
-       PDC_PCI_CTL             = 0x48, /* PCI control and status register */
-       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) |
-                                 (1<<8) | (1<<9) | (1<<10),
-
-       board_2037x             = 0,    /* FastTrak S150 TX2plus */
-       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/20575 has PATA */
-
-       PDC_RESET               = (1 << 11), /* HDMA reset */
-
-       PDC_COMMON_FLAGS        = ATA_FLAG_NO_LEGACY | ATA_FLAG_SRST |
-                                 ATA_FLAG_MMIO | ATA_FLAG_NO_ATAPI |
-                                 ATA_FLAG_PIO_POLLING,
-};
-
-
-struct pdc_port_priv {
-       u8                      *pkt;
-       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);
-static irqreturn_t pdc_interrupt (int irq, void *dev_instance, struct pt_regs *regs);
-static void pdc_eng_timeout(struct ata_port *ap);
-static int pdc_port_start(struct ata_port *ap);
-static void pdc_port_stop(struct ata_port *ap);
-static void pdc_pata_phy_reset(struct ata_port *ap);
-static void pdc_sata_phy_reset(struct ata_port *ap);
-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 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 = {
-       .module                 = THIS_MODULE,
-       .name                   = DRV_NAME,
-       .ioctl                  = ata_scsi_ioctl,
-       .queuecommand           = ata_scsi_queuecmd,
-       .can_queue              = ATA_DEF_QUEUE,
-       .this_id                = ATA_SHT_THIS_ID,
-       .sg_tablesize           = LIBATA_MAX_PRD,
-       .cmd_per_lun            = ATA_SHT_CMD_PER_LUN,
-       .emulated               = ATA_SHT_EMULATED,
-       .use_clustering         = ATA_SHT_USE_CLUSTERING,
-       .proc_name              = DRV_NAME,
-       .dma_boundary           = ATA_DMA_BOUNDARY,
-       .slave_configure        = ata_scsi_slave_config,
-       .slave_destroy          = ata_scsi_slave_destroy,
-       .bios_param             = ata_std_bios_param,
-};
-
-static const struct ata_port_operations pdc_sata_ops = {
-       .port_disable           = ata_port_disable,
-       .tf_load                = pdc_tf_load_mmio,
-       .tf_read                = ata_tf_read,
-       .check_status           = ata_check_status,
-       .exec_command           = pdc_exec_command_mmio,
-       .dev_select             = ata_std_dev_select,
-
-       .phy_reset              = pdc_sata_phy_reset,
-
-       .qc_prep                = pdc_qc_prep,
-       .qc_issue               = pdc_qc_issue_prot,
-       .eng_timeout            = pdc_eng_timeout,
-       .data_xfer              = ata_mmio_data_xfer,
-       .irq_handler            = pdc_interrupt,
-       .irq_clear              = pdc_irq_clear,
-
-       .scr_read               = pdc_sata_scr_read,
-       .scr_write              = pdc_sata_scr_write,
-       .port_start             = pdc_port_start,
-       .port_stop              = pdc_port_stop,
-       .host_stop              = pdc_host_stop,
-};
-
-static const struct ata_port_operations pdc_pata_ops = {
-       .port_disable           = ata_port_disable,
-       .tf_load                = pdc_tf_load_mmio,
-       .tf_read                = ata_tf_read,
-       .check_status           = ata_check_status,
-       .exec_command           = pdc_exec_command_mmio,
-       .dev_select             = ata_std_dev_select,
-
-       .phy_reset              = pdc_pata_phy_reset,
-
-       .qc_prep                = pdc_qc_prep,
-       .qc_issue               = pdc_qc_issue_prot,
-       .data_xfer              = ata_mmio_data_xfer,
-       .eng_timeout            = pdc_eng_timeout,
-       .irq_handler            = pdc_interrupt,
-       .irq_clear              = pdc_irq_clear,
-
-       .port_start             = pdc_port_start,
-       .port_stop              = pdc_port_stop,
-       .host_stop              = pdc_host_stop,
-};
-
-static const struct ata_port_info pdc_port_info[] = {
-       /* board_2037x */
-       {
-               .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_20319 */
-       {
-               .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_20619 */
-       {
-               .sht            = &pdc_ata_sht,
-               .host_flags     = PDC_COMMON_FLAGS | ATA_FLAG_SLAVE_POSS,
-               .pio_mask       = 0x1f, /* pio0-4 */
-               .mwdma_mask     = 0x07, /* mwdma0-2 */
-               .udma_mask      = 0x7f, /* udma0-6 ; FIXME */
-               .port_ops       = &pdc_pata_ops,
-       },
-
-       /* board_20771 */
-       {
-               .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_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[] = {
-       { PCI_VENDOR_ID_PROMISE, 0x3371, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-         board_2037x },
-       { PCI_VENDOR_ID_PROMISE, 0x3570, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-         board_2037x },
-       { PCI_VENDOR_ID_PROMISE, 0x3571, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-         board_2037x },
-       { PCI_VENDOR_ID_PROMISE, 0x3373, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-         board_2037x },
-       { PCI_VENDOR_ID_PROMISE, 0x3375, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-         board_2037x },
-       { 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_2057x },
-       { PCI_VENDOR_ID_PROMISE, 0x3d75, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-         board_2057x },
-       { PCI_VENDOR_ID_PROMISE, 0x3d73, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-         board_2037x },
-
-       { PCI_VENDOR_ID_PROMISE, 0x3318, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-         board_20319 },
-       { PCI_VENDOR_ID_PROMISE, 0x3319, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-         board_20319 },
-       { PCI_VENDOR_ID_PROMISE, 0x3515, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-         board_20319 },
-       { PCI_VENDOR_ID_PROMISE, 0x3519, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-         board_20319 },
-       { PCI_VENDOR_ID_PROMISE, 0x3d17, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-         board_20319 },
-       { PCI_VENDOR_ID_PROMISE, 0x3d18, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-         board_40518 },
-
-       { PCI_VENDOR_ID_PROMISE, 0x6629, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-         board_20619 },
-
-/* TODO: remove all associated board_20771 code, as it completely
- * duplicates board_2037x code, unless reason for separation can be
- * divined.
- */
-#if 0
-       { PCI_VENDOR_ID_PROMISE, 0x3570, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-         board_20771 },
-#endif
-
-       { }     /* terminate list */
-};
-
-
-static struct pci_driver pdc_ata_pci_driver = {
-       .name                   = DRV_NAME,
-       .id_table               = pdc_ata_pci_tbl,
-       .probe                  = pdc_ata_init_one,
-       .remove                 = ata_pci_remove_one,
-};
-
-
-static int pdc_port_start(struct ata_port *ap)
-{
-       struct device *dev = ap->host_set->dev;
-       struct pdc_port_priv *pp;
-       int rc;
-
-       rc = ata_port_start(ap);
-       if (rc)
-               return rc;
-
-       pp = kzalloc(sizeof(*pp), GFP_KERNEL);
-       if (!pp) {
-               rc = -ENOMEM;
-               goto err_out;
-       }
-
-       pp->pkt = dma_alloc_coherent(dev, 128, &pp->pkt_dma, GFP_KERNEL);
-       if (!pp->pkt) {
-               rc = -ENOMEM;
-               goto err_out_kfree;
-       }
-
-       ap->private_data = pp;
-
-       return 0;
-
-err_out_kfree:
-       kfree(pp);
-err_out:
-       ata_port_stop(ap);
-       return rc;
-}
-
-
-static void pdc_port_stop(struct ata_port *ap)
-{
-       struct device *dev = ap->host_set->dev;
-       struct pdc_port_priv *pp = ap->private_data;
-
-       ap->private_data = NULL;
-       dma_free_coherent(dev, 128, pp->pkt, pp->pkt_dma);
-       kfree(pp);
-       ata_port_stop(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;
-       unsigned int i;
-       u32 tmp;
-
-       for (i = 11; i > 0; i--) {
-               tmp = readl(mmio);
-               if (tmp & PDC_RESET)
-                       break;
-
-               udelay(100);
-
-               tmp |= PDC_RESET;
-               writel(tmp, mmio);
-       }
-
-       tmp &= ~PDC_RESET;
-       writel(tmp, mmio);
-       readl(mmio);    /* flush */
-}
-
-static void pdc_sata_phy_reset(struct ata_port *ap)
-{
-       pdc_reset_port(ap);
-       sata_phy_reset(ap);
-}
-
-static void pdc_pata_cbl_detect(struct ata_port *ap)
-{
-       u8 tmp;
-       void __iomem *mmio = (void *) ap->ioaddr.cmd_addr + PDC_CTLSTAT + 0x03;
-
-       tmp = readb(mmio);
-
-       if (tmp & 0x01) {
-               ap->cbl = ATA_CBL_PATA40;
-               ap->udma_mask &= ATA_UDMA_MASK_40C;
-       } else
-               ap->cbl = ATA_CBL_PATA80;
-}
-
-static void pdc_pata_phy_reset(struct ata_port *ap)
-{
-       pdc_pata_cbl_detect(ap);
-       pdc_reset_port(ap);
-       ata_port_probe(ap);
-       ata_bus_reset(ap);
-}
-
-static u32 pdc_sata_scr_read (struct ata_port *ap, unsigned int sc_reg)
-{
-       if (sc_reg > SCR_CONTROL)
-               return 0xffffffffU;
-       return readl((void __iomem *) ap->ioaddr.scr_addr + (sc_reg * 4));
-}
-
-
-static void pdc_sata_scr_write (struct ata_port *ap, unsigned int sc_reg,
-                              u32 val)
-{
-       if (sc_reg > SCR_CONTROL)
-               return;
-       writel(val, (void __iomem *) ap->ioaddr.scr_addr + (sc_reg * 4));
-}
-
-static void pdc_qc_prep(struct ata_queued_cmd *qc)
-{
-       struct pdc_port_priv *pp = qc->ap->private_data;
-       unsigned int i;
-
-       VPRINTK("ENTER\n");
-
-       switch (qc->tf.protocol) {
-       case ATA_PROT_DMA:
-               ata_qc_prep(qc);
-               /* fall through */
-
-       case ATA_PROT_NODATA:
-               i = pdc_pkt_header(&qc->tf, qc->ap->prd_dma,
-                                  qc->dev->devno, pp->pkt);
-
-               if (qc->tf.flags & ATA_TFLAG_LBA48)
-                       i = pdc_prep_lba48(&qc->tf, pp->pkt, i);
-               else
-                       i = pdc_prep_lba28(&qc->tf, pp->pkt, i);
-
-               pdc_pkt_footer(&qc->tf, pp->pkt, i);
-               break;
-
-       default:
-               break;
-       }
-}
-
-static void pdc_eng_timeout(struct ata_port *ap)
-{
-       struct ata_host_set *host_set = ap->host_set;
-       u8 drv_stat;
-       struct ata_queued_cmd *qc;
-       unsigned long flags;
-
-       DPRINTK("ENTER\n");
-
-       spin_lock_irqsave(&host_set->lock, flags);
-
-       qc = ata_qc_from_tag(ap, ap->active_tag);
-
-       switch (qc->tf.protocol) {
-       case ATA_PROT_DMA:
-       case ATA_PROT_NODATA:
-               ata_port_printk(ap, KERN_ERR, "command timeout\n");
-               drv_stat = ata_wait_idle(ap);
-               qc->err_mask |= __ac_err_mask(drv_stat);
-               break;
-
-       default:
-               drv_stat = ata_busy_wait(ap, ATA_BUSY | ATA_DRQ, 1000);
-
-               ata_port_printk(ap, KERN_ERR,
-                               "unknown timeout, cmd 0x%x stat 0x%x\n",
-                               qc->tf.command, drv_stat);
-
-               qc->err_mask |= ac_err_mask(drv_stat);
-               break;
-       }
-
-       spin_unlock_irqrestore(&host_set->lock, flags);
-       ata_eh_qc_complete(qc);
-       DPRINTK("EXIT\n");
-}
-
-static inline unsigned int pdc_host_intr( struct ata_port *ap,
-                                          struct ata_queued_cmd *qc)
-{
-       unsigned int handled = 0;
-       u32 tmp;
-       void __iomem *mmio = (void __iomem *) ap->ioaddr.cmd_addr + PDC_GLOBAL_CTL;
-
-       tmp = readl(mmio);
-       if (tmp & PDC_ERR_MASK) {
-               qc->err_mask |= AC_ERR_DEV;
-               pdc_reset_port(ap);
-       }
-
-       switch (qc->tf.protocol) {
-       case ATA_PROT_DMA:
-       case ATA_PROT_NODATA:
-               qc->err_mask |= ac_err_mask(ata_wait_idle(ap));
-               ata_qc_complete(qc);
-               handled = 1;
-               break;
-
-        default:
-               ap->stats.idle_irq++;
-               break;
-        }
-
-       return handled;
-}
-
-static void pdc_irq_clear(struct ata_port *ap)
-{
-       struct ata_host_set *host_set = ap->host_set;
-       void __iomem *mmio = host_set->mmio_base;
-
-       readl(mmio + PDC_INT_SEQMASK);
-}
-
-static irqreturn_t pdc_interrupt (int irq, void *dev_instance, struct pt_regs *regs)
-{
-       struct ata_host_set *host_set = dev_instance;
-       struct ata_port *ap;
-       u32 mask = 0;
-       unsigned int i, tmp;
-       unsigned int handled = 0;
-       void __iomem *mmio_base;
-
-       VPRINTK("ENTER\n");
-
-       if (!host_set || !host_set->mmio_base) {
-               VPRINTK("QUICK EXIT\n");
-               return IRQ_NONE;
-       }
-
-       mmio_base = host_set->mmio_base;
-
-       /* reading should also clear interrupts */
-       mask = readl(mmio_base + PDC_INT_SEQMASK);
-
-       if (mask == 0xffffffff) {
-               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");
-               goto done_irq;
-       }
-
-       writel(mask, mmio_base + PDC_INT_SEQMASK);
-
-       for (i = 0; i < host_set->n_ports; i++) {
-               VPRINTK("port %u\n", i);
-               ap = host_set->ports[i];
-               tmp = mask & (1 << (i + 1));
-               if (tmp && ap &&
-                   !(ap->flags & ATA_FLAG_DISABLED)) {
-                       struct ata_queued_cmd *qc;
-
-                       qc = ata_qc_from_tag(ap, ap->active_tag);
-                       if (qc && (!(qc->tf.flags & ATA_TFLAG_POLLING)))
-                               handled += pdc_host_intr(ap, qc);
-               }
-       }
-
-       VPRINTK("EXIT\n");
-
-done_irq:
-       spin_unlock(&host_set->lock);
-       return IRQ_RETVAL(handled);
-}
-
-static inline void pdc_packet_start(struct ata_queued_cmd *qc)
-{
-       struct ata_port *ap = qc->ap;
-       struct pdc_port_priv *pp = ap->private_data;
-       unsigned int port_no = ap->port_no;
-       u8 seq = (u8) (port_no + 1);
-
-       VPRINTK("ENTER, ap %p\n", ap);
-
-       writel(0x00000001, ap->host_set->mmio_base + (seq * 4));
-       readl(ap->host_set->mmio_base + (seq * 4));     /* flush */
-
-       pp->pkt[2] = seq;
-       wmb();                  /* flush PRD, pkt writes */
-       writel(pp->pkt_dma, (void __iomem *) ap->ioaddr.cmd_addr + PDC_PKT_SUBMIT);
-       readl((void __iomem *) ap->ioaddr.cmd_addr + PDC_PKT_SUBMIT); /* flush */
-}
-
-static unsigned int pdc_qc_issue_prot(struct ata_queued_cmd *qc)
-{
-       switch (qc->tf.protocol) {
-       case ATA_PROT_DMA:
-       case ATA_PROT_NODATA:
-               pdc_packet_start(qc);
-               return 0;
-
-       case ATA_PROT_ATAPI_DMA:
-               BUG();
-               break;
-
-       default:
-               break;
-       }
-
-       return ata_qc_issue_prot(qc);
-}
-
-static void pdc_tf_load_mmio(struct ata_port *ap, const struct ata_taskfile *tf)
-{
-       WARN_ON (tf->protocol == ATA_PROT_DMA ||
-                tf->protocol == ATA_PROT_NODATA);
-       ata_tf_load(ap, tf);
-}
-
-
-static void pdc_exec_command_mmio(struct ata_port *ap, const struct ata_taskfile *tf)
-{
-       WARN_ON (tf->protocol == ATA_PROT_DMA ||
-                tf->protocol == ATA_PROT_NODATA);
-       ata_exec_command(ap, tf);
-}
-
-
-static void pdc_ata_setup_port(struct ata_ioports *port, unsigned long base)
-{
-       port->cmd_addr          = base;
-       port->data_addr         = base;
-       port->feature_addr      =
-       port->error_addr        = base + 0x4;
-       port->nsect_addr        = base + 0x8;
-       port->lbal_addr         = base + 0xc;
-       port->lbam_addr         = base + 0x10;
-       port->lbah_addr         = base + 0x14;
-       port->device_addr       = base + 0x18;
-       port->command_addr      =
-       port->status_addr       = base + 0x1c;
-       port->altstatus_addr    =
-       port->ctl_addr          = base + 0x38;
-}
-
-
-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;
-
-       /*
-        * Except for the hotplug stuff, this is voodoo from the
-        * Promise driver.  Label this entire section
-        * "TODO: figure out why we do this"
-        */
-
-       /* change FIFO_SHD to 8 dwords, enable BMR_BURST */
-       tmp = readl(mmio + PDC_FLASH_CTL);
-       tmp |= 0x12000; /* bit 16 (fifo 8 dw) and 13 (bmr burst?) */
-       writel(tmp, mmio + PDC_FLASH_CTL);
-
-       /* clear plug/unplug flags for all ports */
-       tmp = readl(mmio + hotplug_offset);
-       writel(tmp | 0xff, mmio + hotplug_offset);
-
-       /* mask plug/unplug ints */
-       tmp = readl(mmio + hotplug_offset);
-       writel(tmp | 0xff0000, mmio + hotplug_offset);
-
-       /* reduce TBG clock to 133 Mhz. */
-       tmp = readl(mmio + PDC_TBG_MODE);
-       tmp &= ~0x30000; /* clear bit 17, 16*/
-       tmp |= 0x10000;  /* set bit 17:16 = 0:1 */
-       writel(tmp, mmio + PDC_TBG_MODE);
-
-       readl(mmio + PDC_TBG_MODE);     /* flush */
-       msleep(10);
-
-       /* adjust slew rate control register. */
-       tmp = readl(mmio + PDC_SLEW_CTL);
-       tmp &= 0xFFFFF03F; /* clear bit 11 ~ 6 */
-       tmp  |= 0x00000900; /* set bit 11-9 = 100b , bit 8-6 = 100 */
-       writel(tmp, mmio + PDC_SLEW_CTL);
-}
-
-static int pdc_ata_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
-{
-       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;
-       int pci_dev_busy = 0;
-       int rc;
-
-       if (!printed_version++)
-               dev_printk(KERN_DEBUG, &pdev->dev, "version " DRV_VERSION "\n");
-
-       rc = pci_enable_device(pdev);
-       if (rc)
-               return rc;
-
-       rc = pci_request_regions(pdev, DRV_NAME);
-       if (rc) {
-               pci_dev_busy = 1;
-               goto err_out;
-       }
-
-       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;
-
-       probe_ent = kzalloc(sizeof(*probe_ent), GFP_KERNEL);
-       if (probe_ent == NULL) {
-               rc = -ENOMEM;
-               goto err_out_regions;
-       }
-
-       probe_ent->dev = pci_dev_to_dev(pdev);
-       INIT_LIST_HEAD(&probe_ent->node);
-
-       mmio_base = pci_iomap(pdev, 3, 0);
-       if (mmio_base == NULL) {
-               rc = -ENOMEM;
-               goto err_out_free_ent;
-       }
-       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;
-       probe_ent->mwdma_mask   = pdc_port_info[board_idx].mwdma_mask;
-       probe_ent->udma_mask    = pdc_port_info[board_idx].udma_mask;
-       probe_ent->port_ops     = pdc_port_info[board_idx].port_ops;
-
-               probe_ent->irq = pdev->irq;
-               probe_ent->irq_flags = IRQF_SHARED;
-       probe_ent->mmio_base = mmio_base;
-
-       pdc_ata_setup_port(&probe_ent->port[0], base + 0x200);
-       pdc_ata_setup_port(&probe_ent->port[1], base + 0x280);
-
-       probe_ent->port[0].scr_addr = base + 0x400;
-       probe_ent->port[1].scr_addr = base + 0x500;
-
-       /* 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;
-
-               pdc_ata_setup_port(&probe_ent->port[2], base + 0x300);
-               pdc_ata_setup_port(&probe_ent->port[3], base + 0x380);
-
-               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;
-       case board_20771:
-               probe_ent->n_ports = 2;
-               break;
-       case board_20619:
-               probe_ent->n_ports = 4;
-
-               pdc_ata_setup_port(&probe_ent->port[2], base + 0x300);
-               pdc_ata_setup_port(&probe_ent->port[3], base + 0x380);
-
-               probe_ent->port[2].scr_addr = base + 0x600;
-               probe_ent->port[3].scr_addr = base + 0x700;
-               break;
-       default:
-               BUG();
-               break;
-       }
-
-       pci_set_master(pdev);
-
-       /* initialize adapter */
-       pdc_host_init(board_idx, probe_ent);
-
-       /* FIXME: Need any other frees than hp? */
-       if (!ata_device_add(probe_ent))
-               kfree(hp);
-
-       kfree(probe_ent);
-
-       return 0;
-
-err_out_free_ent:
-       kfree(probe_ent);
-err_out_regions:
-       pci_release_regions(pdev);
-err_out:
-       if (!pci_dev_busy)
-               pci_disable_device(pdev);
-       return rc;
-}
-
-
-static int __init pdc_ata_init(void)
-{
-       return pci_register_driver(&pdc_ata_pci_driver);
-}
-
-
-static void __exit pdc_ata_exit(void)
-{
-       pci_unregister_driver(&pdc_ata_pci_driver);
-}
-
-
-MODULE_AUTHOR("Jeff Garzik");
-MODULE_DESCRIPTION("Promise ATA TX2/TX4/TX4000 low-level driver");
-MODULE_LICENSE("GPL");
-MODULE_DEVICE_TABLE(pci, pdc_ata_pci_tbl);
-MODULE_VERSION(DRV_VERSION);
-
-module_init(pdc_ata_init);
-module_exit(pdc_ata_exit);
diff --git a/drivers/scsi/sata_promise.h b/drivers/scsi/sata_promise.h
deleted file mode 100644 (file)
index 6ee5e19..0000000
+++ /dev/null
@@ -1,157 +0,0 @@
-/*
- *  sata_promise.h - Promise SATA common definitions and inline funcs
- *
- *  Copyright 2003-2004 Red Hat, Inc.
- *
- *
- *  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.*
- *
- */
-
-#ifndef __SATA_PROMISE_H__
-#define __SATA_PROMISE_H__
-
-#include <linux/ata.h>
-
-enum pdc_packet_bits {
-       PDC_PKT_READ            = (1 << 2),
-       PDC_PKT_NODATA          = (1 << 3),
-
-       PDC_PKT_SIZEMASK        = (1 << 7) | (1 << 6) | (1 << 5),
-       PDC_PKT_CLEAR_BSY       = (1 << 4),
-       PDC_PKT_WAIT_DRDY       = (1 << 3) | (1 << 4),
-       PDC_LAST_REG            = (1 << 3),
-
-       PDC_REG_DEVCTL          = (1 << 3) | (1 << 2) | (1 << 1),
-};
-
-static inline unsigned int pdc_pkt_header(struct ata_taskfile *tf,
-                                         dma_addr_t sg_table,
-                                         unsigned int devno, u8 *buf)
-{
-       u8 dev_reg;
-       u32 *buf32 = (u32 *) buf;
-
-       /* set control bits (byte 0), zero delay seq id (byte 3),
-        * and seq id (byte 2)
-        */
-       switch (tf->protocol) {
-       case ATA_PROT_DMA:
-               if (!(tf->flags & ATA_TFLAG_WRITE))
-                       buf32[0] = cpu_to_le32(PDC_PKT_READ);
-               else
-                       buf32[0] = 0;
-               break;
-
-       case ATA_PROT_NODATA:
-               buf32[0] = cpu_to_le32(PDC_PKT_NODATA);
-               break;
-
-       default:
-               BUG();
-               break;
-       }
-
-       buf32[1] = cpu_to_le32(sg_table);       /* S/G table addr */
-       buf32[2] = 0;                           /* no next-packet */
-
-       if (devno == 0)
-               dev_reg = ATA_DEVICE_OBS;
-       else
-               dev_reg = ATA_DEVICE_OBS | ATA_DEV1;
-
-       /* select device */
-       buf[12] = (1 << 5) | PDC_PKT_CLEAR_BSY | ATA_REG_DEVICE;
-       buf[13] = dev_reg;
-
-       /* device control register */
-       buf[14] = (1 << 5) | PDC_REG_DEVCTL;
-       buf[15] = tf->ctl;
-
-       return 16;      /* offset of next byte */
-}
-
-static inline unsigned int pdc_pkt_footer(struct ata_taskfile *tf, u8 *buf,
-                                 unsigned int i)
-{
-       if (tf->flags & ATA_TFLAG_DEVICE) {
-               buf[i++] = (1 << 5) | ATA_REG_DEVICE;
-               buf[i++] = tf->device;
-       }
-
-       /* and finally the command itself; also includes end-of-pkt marker */
-       buf[i++] = (1 << 5) | PDC_LAST_REG | ATA_REG_CMD;
-       buf[i++] = tf->command;
-
-       return i;
-}
-
-static inline unsigned int pdc_prep_lba28(struct ata_taskfile *tf, u8 *buf, unsigned int i)
-{
-       /* the "(1 << 5)" should be read "(count << 5)" */
-
-       /* ATA command block registers */
-       buf[i++] = (1 << 5) | ATA_REG_FEATURE;
-       buf[i++] = tf->feature;
-
-       buf[i++] = (1 << 5) | ATA_REG_NSECT;
-       buf[i++] = tf->nsect;
-
-       buf[i++] = (1 << 5) | ATA_REG_LBAL;
-       buf[i++] = tf->lbal;
-
-       buf[i++] = (1 << 5) | ATA_REG_LBAM;
-       buf[i++] = tf->lbam;
-
-       buf[i++] = (1 << 5) | ATA_REG_LBAH;
-       buf[i++] = tf->lbah;
-
-       return i;
-}
-
-static inline unsigned int pdc_prep_lba48(struct ata_taskfile *tf, u8 *buf, unsigned int i)
-{
-       /* the "(2 << 5)" should be read "(count << 5)" */
-
-       /* ATA command block registers */
-       buf[i++] = (2 << 5) | ATA_REG_FEATURE;
-       buf[i++] = tf->hob_feature;
-       buf[i++] = tf->feature;
-
-       buf[i++] = (2 << 5) | ATA_REG_NSECT;
-       buf[i++] = tf->hob_nsect;
-       buf[i++] = tf->nsect;
-
-       buf[i++] = (2 << 5) | ATA_REG_LBAL;
-       buf[i++] = tf->hob_lbal;
-       buf[i++] = tf->lbal;
-
-       buf[i++] = (2 << 5) | ATA_REG_LBAM;
-       buf[i++] = tf->hob_lbam;
-       buf[i++] = tf->lbam;
-
-       buf[i++] = (2 << 5) | ATA_REG_LBAH;
-       buf[i++] = tf->hob_lbah;
-       buf[i++] = tf->lbah;
-
-       return i;
-}
-
-
-#endif /* __SATA_PROMISE_H__ */
diff --git a/drivers/scsi/sata_qstor.c b/drivers/scsi/sata_qstor.c
deleted file mode 100644 (file)
index 71bd671..0000000
+++ /dev/null
@@ -1,730 +0,0 @@
-/*
- *  sata_qstor.c - Pacific Digital Corporation QStor SATA
- *
- *  Maintained by:  Mark Lord <mlord@pobox.com>
- *
- *  Copyright 2005 Pacific Digital Corporation.
- *  (OSL/GPL code release authorized by Jalil Fadavi).
- *
- *
- *  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.*
- *
- */
-
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/pci.h>
-#include <linux/init.h>
-#include <linux/blkdev.h>
-#include <linux/delay.h>
-#include <linux/interrupt.h>
-#include <linux/sched.h>
-#include <linux/device.h>
-#include <scsi/scsi_host.h>
-#include <asm/io.h>
-#include <linux/libata.h>
-
-#define DRV_NAME       "sata_qstor"
-#define DRV_VERSION    "0.06"
-
-enum {
-       QS_PORTS                = 4,
-       QS_MAX_PRD              = LIBATA_MAX_PRD,
-       QS_CPB_ORDER            = 6,
-       QS_CPB_BYTES            = (1 << QS_CPB_ORDER),
-       QS_PRD_BYTES            = QS_MAX_PRD * 16,
-       QS_PKT_BYTES            = QS_CPB_BYTES + QS_PRD_BYTES,
-
-       /* global register offsets */
-       QS_HCF_CNFG3            = 0x0003, /* host configuration offset */
-       QS_HID_HPHY             = 0x0004, /* host physical interface info */
-       QS_HCT_CTRL             = 0x00e4, /* global interrupt mask offset */
-       QS_HST_SFF              = 0x0100, /* host status fifo offset */
-       QS_HVS_SERD3            = 0x0393, /* PHY enable offset */
-
-       /* global control bits */
-       QS_HPHY_64BIT           = (1 << 1), /* 64-bit bus detected */
-       QS_CNFG3_GSRST          = 0x01,     /* global chip reset */
-       QS_SERD3_PHY_ENA        = 0xf0,     /* PHY detection ENAble*/
-
-       /* per-channel register offsets */
-       QS_CCF_CPBA             = 0x0710, /* chan CPB base address */
-       QS_CCF_CSEP             = 0x0718, /* chan CPB separation factor */
-       QS_CFC_HUFT             = 0x0800, /* host upstream fifo threshold */
-       QS_CFC_HDFT             = 0x0804, /* host downstream fifo threshold */
-       QS_CFC_DUFT             = 0x0808, /* dev upstream fifo threshold */
-       QS_CFC_DDFT             = 0x080c, /* dev downstream fifo threshold */
-       QS_CCT_CTR0             = 0x0900, /* chan control-0 offset */
-       QS_CCT_CTR1             = 0x0901, /* chan control-1 offset */
-       QS_CCT_CFF              = 0x0a00, /* chan command fifo offset */
-
-       /* channel control bits */
-       QS_CTR0_REG             = (1 << 1),   /* register mode (vs. pkt mode) */
-       QS_CTR0_CLER            = (1 << 2),   /* clear channel errors */
-       QS_CTR1_RDEV            = (1 << 1),   /* sata phy/comms reset */
-       QS_CTR1_RCHN            = (1 << 4),   /* reset channel logic */
-       QS_CCF_RUN_PKT          = 0x107,      /* RUN a new dma PKT */
-
-       /* pkt sub-field headers */
-       QS_HCB_HDR              = 0x01,   /* Host Control Block header */
-       QS_DCB_HDR              = 0x02,   /* Device Control Block header */
-
-       /* pkt HCB flag bits */
-       QS_HF_DIRO              = (1 << 0),   /* data DIRection Out */
-       QS_HF_DAT               = (1 << 3),   /* DATa pkt */
-       QS_HF_IEN               = (1 << 4),   /* Interrupt ENable */
-       QS_HF_VLD               = (1 << 5),   /* VaLiD pkt */
-
-       /* pkt DCB flag bits */
-       QS_DF_PORD              = (1 << 2),   /* Pio OR Dma */
-       QS_DF_ELBA              = (1 << 3),   /* Extended LBA (lba48) */
-
-       /* PCI device IDs */
-       board_2068_idx          = 0,    /* QStor 4-port SATA/RAID */
-};
-
-enum {
-       QS_DMA_BOUNDARY         = ~0UL
-};
-
-typedef enum { qs_state_idle, qs_state_pkt, qs_state_mmio } qs_state_t;
-
-struct qs_port_priv {
-       u8                      *pkt;
-       dma_addr_t              pkt_dma;
-       qs_state_t              state;
-};
-
-static u32 qs_scr_read (struct ata_port *ap, unsigned int sc_reg);
-static void qs_scr_write (struct ata_port *ap, unsigned int sc_reg, u32 val);
-static int qs_ata_init_one (struct pci_dev *pdev, const struct pci_device_id *ent);
-static irqreturn_t qs_intr (int irq, void *dev_instance, struct pt_regs *regs);
-static int qs_port_start(struct ata_port *ap);
-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 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);
-static void qs_irq_clear(struct ata_port *ap);
-static void qs_eng_timeout(struct ata_port *ap);
-
-static struct scsi_host_template qs_ata_sht = {
-       .module                 = THIS_MODULE,
-       .name                   = DRV_NAME,
-       .ioctl                  = ata_scsi_ioctl,
-       .queuecommand           = ata_scsi_queuecmd,
-       .can_queue              = ATA_DEF_QUEUE,
-       .this_id                = ATA_SHT_THIS_ID,
-       .sg_tablesize           = QS_MAX_PRD,
-       .cmd_per_lun            = ATA_SHT_CMD_PER_LUN,
-       .emulated               = ATA_SHT_EMULATED,
-       //FIXME .use_clustering         = ATA_SHT_USE_CLUSTERING,
-       .use_clustering         = ENABLE_CLUSTERING,
-       .proc_name              = DRV_NAME,
-       .dma_boundary           = QS_DMA_BOUNDARY,
-       .slave_configure        = ata_scsi_slave_config,
-       .slave_destroy          = ata_scsi_slave_destroy,
-       .bios_param             = ata_std_bios_param,
-};
-
-static const struct ata_port_operations qs_ata_ops = {
-       .port_disable           = ata_port_disable,
-       .tf_load                = ata_tf_load,
-       .tf_read                = ata_tf_read,
-       .check_status           = ata_check_status,
-       .check_atapi_dma        = qs_check_atapi_dma,
-       .exec_command           = ata_exec_command,
-       .dev_select             = ata_std_dev_select,
-       .phy_reset              = qs_phy_reset,
-       .qc_prep                = qs_qc_prep,
-       .qc_issue               = qs_qc_issue,
-       .data_xfer              = ata_mmio_data_xfer,
-       .eng_timeout            = qs_eng_timeout,
-       .irq_handler            = qs_intr,
-       .irq_clear              = qs_irq_clear,
-       .scr_read               = qs_scr_read,
-       .scr_write              = qs_scr_write,
-       .port_start             = qs_port_start,
-       .port_stop              = qs_port_stop,
-       .host_stop              = qs_host_stop,
-       .bmdma_stop             = qs_bmdma_stop,
-       .bmdma_status           = qs_bmdma_status,
-};
-
-static const struct ata_port_info qs_port_info[] = {
-       /* board_2068_idx */
-       {
-               .sht            = &qs_ata_sht,
-               .host_flags     = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
-                                 ATA_FLAG_SATA_RESET |
-                                 //FIXME ATA_FLAG_SRST |
-                                 ATA_FLAG_MMIO | ATA_FLAG_PIO_POLLING,
-               .pio_mask       = 0x10, /* pio4 */
-               .udma_mask      = 0x7f, /* udma0-6 */
-               .port_ops       = &qs_ata_ops,
-       },
-};
-
-static const struct pci_device_id qs_ata_pci_tbl[] = {
-       { PCI_VENDOR_ID_PDC, 0x2068, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-         board_2068_idx },
-
-       { }     /* terminate list */
-};
-
-static struct pci_driver qs_ata_pci_driver = {
-       .name                   = DRV_NAME,
-       .id_table               = qs_ata_pci_tbl,
-       .probe                  = qs_ata_init_one,
-       .remove                 = ata_pci_remove_one,
-};
-
-static int qs_check_atapi_dma(struct ata_queued_cmd *qc)
-{
-       return 1;       /* ATAPI DMA not supported */
-}
-
-static void qs_bmdma_stop(struct ata_queued_cmd *qc)
-{
-       /* nothing */
-}
-
-static u8 qs_bmdma_status(struct ata_port *ap)
-{
-       return 0;
-}
-
-static void qs_irq_clear(struct ata_port *ap)
-{
-       /* nothing */
-}
-
-static inline void qs_enter_reg_mode(struct ata_port *ap)
-{
-       u8 __iomem *chan = ap->host_set->mmio_base + (ap->port_no * 0x4000);
-
-       writeb(QS_CTR0_REG, chan + QS_CCT_CTR0);
-       readb(chan + QS_CCT_CTR0);        /* flush */
-}
-
-static inline void qs_reset_channel_logic(struct ata_port *ap)
-{
-       u8 __iomem *chan = ap->host_set->mmio_base + (ap->port_no * 0x4000);
-
-       writeb(QS_CTR1_RCHN, chan + QS_CCT_CTR1);
-       readb(chan + QS_CCT_CTR0);        /* flush */
-       qs_enter_reg_mode(ap);
-}
-
-static void qs_phy_reset(struct ata_port *ap)
-{
-       struct qs_port_priv *pp = ap->private_data;
-
-       pp->state = qs_state_idle;
-       qs_reset_channel_logic(ap);
-       sata_phy_reset(ap);
-}
-
-static void qs_eng_timeout(struct ata_port *ap)
-{
-       struct qs_port_priv *pp = ap->private_data;
-
-       if (pp->state != qs_state_idle) /* healthy paranoia */
-               pp->state = qs_state_mmio;
-       qs_reset_channel_logic(ap);
-       ata_eng_timeout(ap);
-}
-
-static u32 qs_scr_read (struct ata_port *ap, unsigned int sc_reg)
-{
-       if (sc_reg > SCR_CONTROL)
-               return ~0U;
-       return readl((void __iomem *)(ap->ioaddr.scr_addr + (sc_reg * 8)));
-}
-
-static void qs_scr_write (struct ata_port *ap, unsigned int sc_reg, u32 val)
-{
-       if (sc_reg > SCR_CONTROL)
-               return;
-       writel(val, (void __iomem *)(ap->ioaddr.scr_addr + (sc_reg * 8)));
-}
-
-static unsigned int qs_fill_sg(struct ata_queued_cmd *qc)
-{
-       struct scatterlist *sg;
-       struct ata_port *ap = qc->ap;
-       struct qs_port_priv *pp = ap->private_data;
-       unsigned int nelem;
-       u8 *prd = pp->pkt + QS_CPB_BYTES;
-
-       WARN_ON(qc->__sg == NULL);
-       WARN_ON(qc->n_elem == 0 && qc->pad_len == 0);
-
-       nelem = 0;
-       ata_for_each_sg(sg, qc) {
-               u64 addr;
-               u32 len;
-
-               addr = sg_dma_address(sg);
-               *(__le64 *)prd = cpu_to_le64(addr);
-               prd += sizeof(u64);
-
-               len = sg_dma_len(sg);
-               *(__le32 *)prd = cpu_to_le32(len);
-               prd += sizeof(u64);
-
-               VPRINTK("PRD[%u] = (0x%llX, 0x%X)\n", nelem,
-                                       (unsigned long long)addr, len);
-               nelem++;
-       }
-
-       return nelem;
-}
-
-static void qs_qc_prep(struct ata_queued_cmd *qc)
-{
-       struct qs_port_priv *pp = qc->ap->private_data;
-       u8 dflags = QS_DF_PORD, *buf = pp->pkt;
-       u8 hflags = QS_HF_DAT | QS_HF_IEN | QS_HF_VLD;
-       u64 addr;
-       unsigned int nelem;
-
-       VPRINTK("ENTER\n");
-
-       qs_enter_reg_mode(qc->ap);
-       if (qc->tf.protocol != ATA_PROT_DMA) {
-               ata_qc_prep(qc);
-               return;
-       }
-
-       nelem = qs_fill_sg(qc);
-
-       if ((qc->tf.flags & ATA_TFLAG_WRITE))
-               hflags |= QS_HF_DIRO;
-       if ((qc->tf.flags & ATA_TFLAG_LBA48))
-               dflags |= QS_DF_ELBA;
-
-       /* host control block (HCB) */
-       buf[ 0] = QS_HCB_HDR;
-       buf[ 1] = hflags;
-       *(__le32 *)(&buf[ 4]) = cpu_to_le32(qc->nsect * ATA_SECT_SIZE);
-       *(__le32 *)(&buf[ 8]) = cpu_to_le32(nelem);
-       addr = ((u64)pp->pkt_dma) + QS_CPB_BYTES;
-       *(__le64 *)(&buf[16]) = cpu_to_le64(addr);
-
-       /* device control block (DCB) */
-       buf[24] = QS_DCB_HDR;
-       buf[28] = dflags;
-
-       /* frame information structure (FIS) */
-       ata_tf_to_fis(&qc->tf, &buf[32], 0);
-}
-
-static inline void qs_packet_start(struct ata_queued_cmd *qc)
-{
-       struct ata_port *ap = qc->ap;
-       u8 __iomem *chan = ap->host_set->mmio_base + (ap->port_no * 0x4000);
-
-       VPRINTK("ENTER, ap %p\n", ap);
-
-       writeb(QS_CTR0_CLER, chan + QS_CCT_CTR0);
-       wmb();                             /* flush PRDs and pkt to memory */
-       writel(QS_CCF_RUN_PKT, chan + QS_CCT_CFF);
-       readl(chan + QS_CCT_CFF);          /* flush */
-}
-
-static unsigned int qs_qc_issue(struct ata_queued_cmd *qc)
-{
-       struct qs_port_priv *pp = qc->ap->private_data;
-
-       switch (qc->tf.protocol) {
-       case ATA_PROT_DMA:
-
-               pp->state = qs_state_pkt;
-               qs_packet_start(qc);
-               return 0;
-
-       case ATA_PROT_ATAPI_DMA:
-               BUG();
-               break;
-
-       default:
-               break;
-       }
-
-       pp->state = qs_state_mmio;
-       return ata_qc_issue_prot(qc);
-}
-
-static inline unsigned int qs_intr_pkt(struct ata_host_set *host_set)
-{
-       unsigned int handled = 0;
-       u8 sFFE;
-       u8 __iomem *mmio_base = host_set->mmio_base;
-
-       do {
-               u32 sff0 = readl(mmio_base + QS_HST_SFF);
-               u32 sff1 = readl(mmio_base + QS_HST_SFF + 4);
-               u8 sEVLD = (sff1 >> 30) & 0x01; /* valid flag */
-               sFFE  = sff1 >> 31;             /* empty flag */
-
-               if (sEVLD) {
-                       u8 sDST = sff0 >> 16;   /* dev status */
-                       u8 sHST = sff1 & 0x3f;  /* host status */
-                       unsigned int port_no = (sff1 >> 8) & 0x03;
-                       struct ata_port *ap = host_set->ports[port_no];
-
-                       DPRINTK("SFF=%08x%08x: sCHAN=%u sHST=%d sDST=%02x\n",
-                                       sff1, sff0, port_no, sHST, sDST);
-                       handled = 1;
-                       if (ap && !(ap->flags & ATA_FLAG_DISABLED)) {
-                               struct ata_queued_cmd *qc;
-                               struct qs_port_priv *pp = ap->private_data;
-                               if (!pp || pp->state != qs_state_pkt)
-                                       continue;
-                               qc = ata_qc_from_tag(ap, ap->active_tag);
-                               if (qc && (!(qc->tf.flags & ATA_TFLAG_POLLING))) {
-                                       switch (sHST) {
-                                       case 0: /* successful CPB */
-                                       case 3: /* device error */
-                                               pp->state = qs_state_idle;
-                                               qs_enter_reg_mode(qc->ap);
-                                               qc->err_mask |= ac_err_mask(sDST);
-                                               ata_qc_complete(qc);
-                                               break;
-                                       default:
-                                               break;
-                                       }
-                               }
-                       }
-               }
-       } while (!sFFE);
-       return handled;
-}
-
-static inline unsigned int qs_intr_mmio(struct ata_host_set *host_set)
-{
-       unsigned int handled = 0, port_no;
-
-       for (port_no = 0; port_no < host_set->n_ports; ++port_no) {
-               struct ata_port *ap;
-               ap = host_set->ports[port_no];
-               if (ap &&
-                   !(ap->flags & ATA_FLAG_DISABLED)) {
-                       struct ata_queued_cmd *qc;
-                       struct qs_port_priv *pp = ap->private_data;
-                       if (!pp || pp->state != qs_state_mmio)
-                               continue;
-                       qc = ata_qc_from_tag(ap, ap->active_tag);
-                       if (qc && (!(qc->tf.flags & ATA_TFLAG_POLLING))) {
-
-                               /* check main status, clearing INTRQ */
-                               u8 status = ata_check_status(ap);
-                               if ((status & ATA_BUSY))
-                                       continue;
-                               DPRINTK("ata%u: protocol %d (dev_stat 0x%X)\n",
-                                       ap->id, qc->tf.protocol, status);
-
-                               /* complete taskfile transaction */
-                               pp->state = qs_state_idle;
-                               qc->err_mask |= ac_err_mask(status);
-                               ata_qc_complete(qc);
-                               handled = 1;
-                       }
-               }
-       }
-       return handled;
-}
-
-static irqreturn_t qs_intr(int irq, void *dev_instance, struct pt_regs *regs)
-{
-       struct ata_host_set *host_set = dev_instance;
-       unsigned int handled = 0;
-
-       VPRINTK("ENTER\n");
-
-       spin_lock(&host_set->lock);
-       handled  = qs_intr_pkt(host_set) | qs_intr_mmio(host_set);
-       spin_unlock(&host_set->lock);
-
-       VPRINTK("EXIT\n");
-
-       return IRQ_RETVAL(handled);
-}
-
-static void qs_ata_setup_port(struct ata_ioports *port, unsigned long base)
-{
-       port->cmd_addr          =
-       port->data_addr         = base + 0x400;
-       port->error_addr        =
-       port->feature_addr      = base + 0x408; /* hob_feature = 0x409 */
-       port->nsect_addr        = base + 0x410; /* hob_nsect   = 0x411 */
-       port->lbal_addr         = base + 0x418; /* hob_lbal    = 0x419 */
-       port->lbam_addr         = base + 0x420; /* hob_lbam    = 0x421 */
-       port->lbah_addr         = base + 0x428; /* hob_lbah    = 0x429 */
-       port->device_addr       = base + 0x430;
-       port->status_addr       =
-       port->command_addr      = base + 0x438;
-       port->altstatus_addr    =
-       port->ctl_addr          = base + 0x440;
-       port->scr_addr          = base + 0xc00;
-}
-
-static int qs_port_start(struct ata_port *ap)
-{
-       struct device *dev = ap->host_set->dev;
-       struct qs_port_priv *pp;
-       void __iomem *mmio_base = ap->host_set->mmio_base;
-       void __iomem *chan = mmio_base + (ap->port_no * 0x4000);
-       u64 addr;
-       int rc;
-
-       rc = ata_port_start(ap);
-       if (rc)
-               return rc;
-       qs_enter_reg_mode(ap);
-       pp = kzalloc(sizeof(*pp), GFP_KERNEL);
-       if (!pp) {
-               rc = -ENOMEM;
-               goto err_out;
-       }
-       pp->pkt = dma_alloc_coherent(dev, QS_PKT_BYTES, &pp->pkt_dma,
-                                                               GFP_KERNEL);
-       if (!pp->pkt) {
-               rc = -ENOMEM;
-               goto err_out_kfree;
-       }
-       memset(pp->pkt, 0, QS_PKT_BYTES);
-       ap->private_data = pp;
-
-       addr = (u64)pp->pkt_dma;
-       writel((u32) addr,        chan + QS_CCF_CPBA);
-       writel((u32)(addr >> 32), chan + QS_CCF_CPBA + 4);
-       return 0;
-
-err_out_kfree:
-       kfree(pp);
-err_out:
-       ata_port_stop(ap);
-       return rc;
-}
-
-static void qs_port_stop(struct ata_port *ap)
-{
-       struct device *dev = ap->host_set->dev;
-       struct qs_port_priv *pp = ap->private_data;
-
-       if (pp != NULL) {
-               ap->private_data = NULL;
-               if (pp->pkt != NULL)
-                       dma_free_coherent(dev, QS_PKT_BYTES, pp->pkt,
-                                                               pp->pkt_dma);
-               kfree(pp);
-       }
-       ata_port_stop(ap);
-}
-
-static void qs_host_stop(struct ata_host_set *host_set)
-{
-       void __iomem *mmio_base = host_set->mmio_base;
-       struct pci_dev *pdev = to_pci_dev(host_set->dev);
-
-       writeb(0, mmio_base + QS_HCT_CTRL); /* disable host interrupts */
-       writeb(QS_CNFG3_GSRST, mmio_base + QS_HCF_CNFG3); /* global reset */
-
-       pci_iounmap(pdev, mmio_base);
-}
-
-static void qs_host_init(unsigned int chip_id, struct ata_probe_ent *pe)
-{
-       void __iomem *mmio_base = pe->mmio_base;
-       unsigned int port_no;
-
-       writeb(0, mmio_base + QS_HCT_CTRL); /* disable host interrupts */
-       writeb(QS_CNFG3_GSRST, mmio_base + QS_HCF_CNFG3); /* global reset */
-
-       /* reset each channel in turn */
-       for (port_no = 0; port_no < pe->n_ports; ++port_no) {
-               u8 __iomem *chan = mmio_base + (port_no * 0x4000);
-               writeb(QS_CTR1_RDEV|QS_CTR1_RCHN, chan + QS_CCT_CTR1);
-               writeb(QS_CTR0_REG, chan + QS_CCT_CTR0);
-               readb(chan + QS_CCT_CTR0);        /* flush */
-       }
-       writeb(QS_SERD3_PHY_ENA, mmio_base + QS_HVS_SERD3); /* enable phy */
-
-       for (port_no = 0; port_no < pe->n_ports; ++port_no) {
-               u8 __iomem *chan = mmio_base + (port_no * 0x4000);
-               /* set FIFO depths to same settings as Windows driver */
-               writew(32, chan + QS_CFC_HUFT);
-               writew(32, chan + QS_CFC_HDFT);
-               writew(10, chan + QS_CFC_DUFT);
-               writew( 8, chan + QS_CFC_DDFT);
-               /* set CPB size in bytes, as a power of two */
-               writeb(QS_CPB_ORDER,    chan + QS_CCF_CSEP);
-       }
-       writeb(1, mmio_base + QS_HCT_CTRL); /* enable host interrupts */
-}
-
-/*
- * The QStor understands 64-bit buses, and uses 64-bit fields
- * for DMA pointers regardless of bus width.  We just have to
- * make sure our DMA masks are set appropriately for whatever
- * bridge lies between us and the QStor, and then the DMA mapping
- * code will ensure we only ever "see" appropriate buffer addresses.
- * If we're 32-bit limited somewhere, then our 64-bit fields will
- * just end up with zeros in the upper 32-bits, without any special
- * logic required outside of this routine (below).
- */
-static int qs_set_dma_masks(struct pci_dev *pdev, void __iomem *mmio_base)
-{
-       u32 bus_info = readl(mmio_base + QS_HID_HPHY);
-       int rc, have_64bit_bus = (bus_info & QS_HPHY_64BIT);
-
-       if (have_64bit_bus &&
-           !pci_set_dma_mask(pdev, DMA_64BIT_MASK)) {
-               rc = pci_set_consistent_dma_mask(pdev, DMA_64BIT_MASK);
-               if (rc) {
-                       rc = pci_set_consistent_dma_mask(pdev, DMA_32BIT_MASK);
-                       if (rc) {
-                               dev_printk(KERN_ERR, &pdev->dev,
-                                          "64-bit DMA enable failed\n");
-                               return rc;
-                       }
-               }
-       } else {
-               rc = pci_set_dma_mask(pdev, DMA_32BIT_MASK);
-               if (rc) {
-                       dev_printk(KERN_ERR, &pdev->dev,
-                               "32-bit DMA enable failed\n");
-                       return rc;
-               }
-               rc = pci_set_consistent_dma_mask(pdev, DMA_32BIT_MASK);
-               if (rc) {
-                       dev_printk(KERN_ERR, &pdev->dev,
-                               "32-bit consistent DMA enable failed\n");
-                       return rc;
-               }
-       }
-       return 0;
-}
-
-static int qs_ata_init_one(struct pci_dev *pdev,
-                               const struct pci_device_id *ent)
-{
-       static int printed_version;
-       struct ata_probe_ent *probe_ent = NULL;
-       void __iomem *mmio_base;
-       unsigned int board_idx = (unsigned int) ent->driver_data;
-       int rc, port_no;
-
-       if (!printed_version++)
-               dev_printk(KERN_DEBUG, &pdev->dev, "version " DRV_VERSION "\n");
-
-       rc = pci_enable_device(pdev);
-       if (rc)
-               return rc;
-
-       rc = pci_request_regions(pdev, DRV_NAME);
-       if (rc)
-               goto err_out;
-
-       if ((pci_resource_flags(pdev, 4) & IORESOURCE_MEM) == 0) {
-               rc = -ENODEV;
-               goto err_out_regions;
-       }
-
-       mmio_base = pci_iomap(pdev, 4, 0);
-       if (mmio_base == NULL) {
-               rc = -ENOMEM;
-               goto err_out_regions;
-       }
-
-       rc = qs_set_dma_masks(pdev, mmio_base);
-       if (rc)
-               goto err_out_iounmap;
-
-       probe_ent = kmalloc(sizeof(*probe_ent), GFP_KERNEL);
-       if (probe_ent == NULL) {
-               rc = -ENOMEM;
-               goto err_out_iounmap;
-       }
-
-       memset(probe_ent, 0, sizeof(*probe_ent));
-       probe_ent->dev = pci_dev_to_dev(pdev);
-       INIT_LIST_HEAD(&probe_ent->node);
-
-       probe_ent->sht          = qs_port_info[board_idx].sht;
-       probe_ent->host_flags   = qs_port_info[board_idx].host_flags;
-       probe_ent->pio_mask     = qs_port_info[board_idx].pio_mask;
-       probe_ent->mwdma_mask   = qs_port_info[board_idx].mwdma_mask;
-       probe_ent->udma_mask    = qs_port_info[board_idx].udma_mask;
-       probe_ent->port_ops     = qs_port_info[board_idx].port_ops;
-
-       probe_ent->irq          = pdev->irq;
-       probe_ent->irq_flags    = IRQF_SHARED;
-       probe_ent->mmio_base    = mmio_base;
-       probe_ent->n_ports      = QS_PORTS;
-
-       for (port_no = 0; port_no < probe_ent->n_ports; ++port_no) {
-               unsigned long chan = (unsigned long)mmio_base +
-                                                       (port_no * 0x4000);
-               qs_ata_setup_port(&probe_ent->port[port_no], chan);
-       }
-
-       pci_set_master(pdev);
-
-       /* initialize adapter */
-       qs_host_init(board_idx, probe_ent);
-
-       rc = ata_device_add(probe_ent);
-       kfree(probe_ent);
-       if (rc != QS_PORTS)
-               goto err_out_iounmap;
-       return 0;
-
-err_out_iounmap:
-       pci_iounmap(pdev, mmio_base);
-err_out_regions:
-       pci_release_regions(pdev);
-err_out:
-       pci_disable_device(pdev);
-       return rc;
-}
-
-static int __init qs_ata_init(void)
-{
-       return pci_register_driver(&qs_ata_pci_driver);
-}
-
-static void __exit qs_ata_exit(void)
-{
-       pci_unregister_driver(&qs_ata_pci_driver);
-}
-
-MODULE_AUTHOR("Mark Lord");
-MODULE_DESCRIPTION("Pacific Digital Corporation QStor SATA low-level driver");
-MODULE_LICENSE("GPL");
-MODULE_DEVICE_TABLE(pci, qs_ata_pci_tbl);
-MODULE_VERSION(DRV_VERSION);
-
-module_init(qs_ata_init);
-module_exit(qs_ata_exit);
diff --git a/drivers/scsi/sata_sil.c b/drivers/scsi/sata_sil.c
deleted file mode 100644 (file)
index 907faa8..0000000
+++ /dev/null
@@ -1,723 +0,0 @@
-/*
- *  sata_sil.c - Silicon Image SATA
- *
- *  Maintained by:  Jeff Garzik <jgarzik@pobox.com>
- *                 Please ALWAYS copy linux-ide@vger.kernel.org
- *                 on emails.
- *
- *  Copyright 2003-2005 Red Hat, Inc.
- *  Copyright 2003 Benjamin Herrenschmidt
- *
- *
- *  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.*
- *
- *  Documentation for SiI 3112:
- *  http://gkernel.sourceforge.net/specs/sii/3112A_SiI-DS-0095-B2.pdf.bz2
- *
- *  Other errata and documentation available under NDA.
- *
- */
-
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/pci.h>
-#include <linux/init.h>
-#include <linux/blkdev.h>
-#include <linux/delay.h>
-#include <linux/interrupt.h>
-#include <linux/device.h>
-#include <scsi/scsi_host.h>
-#include <linux/libata.h>
-
-#define DRV_NAME       "sata_sil"
-#define DRV_VERSION    "2.0"
-
-enum {
-       /*
-        * host flags
-        */
-       SIL_FLAG_NO_SATA_IRQ    = (1 << 28),
-       SIL_FLAG_RERR_ON_DMA_ACT = (1 << 29),
-       SIL_FLAG_MOD15WRITE     = (1 << 30),
-
-       SIL_DFL_HOST_FLAGS      = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
-                                 ATA_FLAG_MMIO | ATA_FLAG_HRST_TO_RESUME,
-
-       /*
-        * Controller IDs
-        */
-       sil_3112                = 0,
-       sil_3112_no_sata_irq    = 1,
-       sil_3512                = 2,
-       sil_3114                = 3,
-
-       /*
-        * Register offsets
-        */
-       SIL_SYSCFG              = 0x48,
-
-       /*
-        * Register bits
-        */
-       /* SYSCFG */
-       SIL_MASK_IDE0_INT       = (1 << 22),
-       SIL_MASK_IDE1_INT       = (1 << 23),
-       SIL_MASK_IDE2_INT       = (1 << 24),
-       SIL_MASK_IDE3_INT       = (1 << 25),
-       SIL_MASK_2PORT          = SIL_MASK_IDE0_INT | SIL_MASK_IDE1_INT,
-       SIL_MASK_4PORT          = SIL_MASK_2PORT |
-                                 SIL_MASK_IDE2_INT | SIL_MASK_IDE3_INT,
-
-       /* BMDMA/BMDMA2 */
-       SIL_INTR_STEERING       = (1 << 1),
-
-       SIL_DMA_ENABLE          = (1 << 0),  /* DMA run switch */
-       SIL_DMA_RDWR            = (1 << 3),  /* DMA Rd-Wr */
-       SIL_DMA_SATA_IRQ        = (1 << 4),  /* OR of all SATA IRQs */
-       SIL_DMA_ACTIVE          = (1 << 16), /* DMA running */
-       SIL_DMA_ERROR           = (1 << 17), /* PCI bus error */
-       SIL_DMA_COMPLETE        = (1 << 18), /* cmd complete / IRQ pending */
-       SIL_DMA_N_SATA_IRQ      = (1 << 6),  /* SATA_IRQ for the next channel */
-       SIL_DMA_N_ACTIVE        = (1 << 24), /* ACTIVE for the next channel */
-       SIL_DMA_N_ERROR         = (1 << 25), /* ERROR for the next channel */
-       SIL_DMA_N_COMPLETE      = (1 << 26), /* COMPLETE for the next channel */
-
-       /* SIEN */
-       SIL_SIEN_N              = (1 << 16), /* triggered by SError.N */
-
-       /*
-        * Others
-        */
-       SIL_QUIRK_MOD15WRITE    = (1 << 0),
-       SIL_QUIRK_UDMA5MAX      = (1 << 1),
-};
-
-static int sil_init_one (struct pci_dev *pdev, const struct pci_device_id *ent);
-static int sil_pci_device_resume(struct pci_dev *pdev);
-static void sil_dev_config(struct ata_port *ap, struct ata_device *dev);
-static u32 sil_scr_read (struct ata_port *ap, unsigned int sc_reg);
-static void sil_scr_write (struct ata_port *ap, unsigned int sc_reg, u32 val);
-static void sil_post_set_mode (struct ata_port *ap);
-static irqreturn_t sil_interrupt(int irq, void *dev_instance,
-                                struct pt_regs *regs);
-static void sil_freeze(struct ata_port *ap);
-static void sil_thaw(struct ata_port *ap);
-
-
-static const struct pci_device_id sil_pci_tbl[] = {
-       { 0x1095, 0x3112, PCI_ANY_ID, PCI_ANY_ID, 0, 0, sil_3112 },
-       { 0x1095, 0x0240, PCI_ANY_ID, PCI_ANY_ID, 0, 0, sil_3112 },
-       { 0x1095, 0x3512, PCI_ANY_ID, PCI_ANY_ID, 0, 0, sil_3512 },
-       { 0x1095, 0x3114, PCI_ANY_ID, PCI_ANY_ID, 0, 0, sil_3114 },
-       { 0x1002, 0x436e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, sil_3112 },
-       { 0x1002, 0x4379, PCI_ANY_ID, PCI_ANY_ID, 0, 0, sil_3112_no_sata_irq },
-       { 0x1002, 0x437a, PCI_ANY_ID, PCI_ANY_ID, 0, 0, sil_3112_no_sata_irq },
-       { }     /* terminate list */
-};
-
-
-/* TODO firmware versions should be added - eric */
-static const struct sil_drivelist {
-       const char * product;
-       unsigned int quirk;
-} sil_blacklist [] = {
-       { "ST320012AS",         SIL_QUIRK_MOD15WRITE },
-       { "ST330013AS",         SIL_QUIRK_MOD15WRITE },
-       { "ST340017AS",         SIL_QUIRK_MOD15WRITE },
-       { "ST360015AS",         SIL_QUIRK_MOD15WRITE },
-       { "ST380023AS",         SIL_QUIRK_MOD15WRITE },
-       { "ST3120023AS",        SIL_QUIRK_MOD15WRITE },
-       { "ST340014ASL",        SIL_QUIRK_MOD15WRITE },
-       { "ST360014ASL",        SIL_QUIRK_MOD15WRITE },
-       { "ST380011ASL",        SIL_QUIRK_MOD15WRITE },
-       { "ST3120022ASL",       SIL_QUIRK_MOD15WRITE },
-       { "ST3160021ASL",       SIL_QUIRK_MOD15WRITE },
-       { "Maxtor 4D060H3",     SIL_QUIRK_UDMA5MAX },
-       { }
-};
-
-static struct pci_driver sil_pci_driver = {
-       .name                   = DRV_NAME,
-       .id_table               = sil_pci_tbl,
-       .probe                  = sil_init_one,
-       .remove                 = ata_pci_remove_one,
-       .suspend                = ata_pci_device_suspend,
-       .resume                 = sil_pci_device_resume,
-};
-
-static struct scsi_host_template sil_sht = {
-       .module                 = THIS_MODULE,
-       .name                   = DRV_NAME,
-       .ioctl                  = ata_scsi_ioctl,
-       .queuecommand           = ata_scsi_queuecmd,
-       .can_queue              = ATA_DEF_QUEUE,
-       .this_id                = ATA_SHT_THIS_ID,
-       .sg_tablesize           = LIBATA_MAX_PRD,
-       .cmd_per_lun            = ATA_SHT_CMD_PER_LUN,
-       .emulated               = ATA_SHT_EMULATED,
-       .use_clustering         = ATA_SHT_USE_CLUSTERING,
-       .proc_name              = DRV_NAME,
-       .dma_boundary           = ATA_DMA_BOUNDARY,
-       .slave_configure        = ata_scsi_slave_config,
-       .slave_destroy          = ata_scsi_slave_destroy,
-       .bios_param             = ata_std_bios_param,
-       .suspend                = ata_scsi_device_suspend,
-       .resume                 = ata_scsi_device_resume,
-};
-
-static const struct ata_port_operations sil_ops = {
-       .port_disable           = ata_port_disable,
-       .dev_config             = sil_dev_config,
-       .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,
-       .post_set_mode          = sil_post_set_mode,
-       .bmdma_setup            = ata_bmdma_setup,
-       .bmdma_start            = ata_bmdma_start,
-       .bmdma_stop             = ata_bmdma_stop,
-       .bmdma_status           = ata_bmdma_status,
-       .qc_prep                = ata_qc_prep,
-       .qc_issue               = ata_qc_issue_prot,
-       .data_xfer              = ata_mmio_data_xfer,
-       .freeze                 = sil_freeze,
-       .thaw                   = sil_thaw,
-       .error_handler          = ata_bmdma_error_handler,
-       .post_internal_cmd      = ata_bmdma_post_internal_cmd,
-       .irq_handler            = sil_interrupt,
-       .irq_clear              = ata_bmdma_irq_clear,
-       .scr_read               = sil_scr_read,
-       .scr_write              = sil_scr_write,
-       .port_start             = ata_port_start,
-       .port_stop              = ata_port_stop,
-       .host_stop              = ata_pci_host_stop,
-};
-
-static const struct ata_port_info sil_port_info[] = {
-       /* sil_3112 */
-       {
-               .sht            = &sil_sht,
-               .host_flags     = SIL_DFL_HOST_FLAGS | SIL_FLAG_MOD15WRITE,
-               .pio_mask       = 0x1f,                 /* pio0-4 */
-               .mwdma_mask     = 0x07,                 /* mwdma0-2 */
-               .udma_mask      = 0x3f,                 /* udma0-5 */
-               .port_ops       = &sil_ops,
-       },
-       /* sil_3112_no_sata_irq */
-       {
-               .sht            = &sil_sht,
-               .host_flags     = SIL_DFL_HOST_FLAGS | SIL_FLAG_MOD15WRITE |
-                                 SIL_FLAG_NO_SATA_IRQ,
-               .pio_mask       = 0x1f,                 /* pio0-4 */
-               .mwdma_mask     = 0x07,                 /* mwdma0-2 */
-               .udma_mask      = 0x3f,                 /* udma0-5 */
-               .port_ops       = &sil_ops,
-       },
-       /* sil_3512 */
-       {
-               .sht            = &sil_sht,
-               .host_flags     = SIL_DFL_HOST_FLAGS | SIL_FLAG_RERR_ON_DMA_ACT,
-               .pio_mask       = 0x1f,                 /* pio0-4 */
-               .mwdma_mask     = 0x07,                 /* mwdma0-2 */
-               .udma_mask      = 0x3f,                 /* udma0-5 */
-               .port_ops       = &sil_ops,
-       },
-       /* sil_3114 */
-       {
-               .sht            = &sil_sht,
-               .host_flags     = SIL_DFL_HOST_FLAGS | SIL_FLAG_RERR_ON_DMA_ACT,
-               .pio_mask       = 0x1f,                 /* pio0-4 */
-               .mwdma_mask     = 0x07,                 /* mwdma0-2 */
-               .udma_mask      = 0x3f,                 /* udma0-5 */
-               .port_ops       = &sil_ops,
-       },
-};
-
-/* per-port register offsets */
-/* TODO: we can probably calculate rather than use a table */
-static const struct {
-       unsigned long tf;       /* ATA taskfile register block */
-       unsigned long ctl;      /* ATA control/altstatus register block */
-       unsigned long bmdma;    /* DMA register block */
-       unsigned long bmdma2;   /* DMA register block #2 */
-       unsigned long fifo_cfg; /* FIFO Valid Byte Count and Control */
-       unsigned long scr;      /* SATA control register block */
-       unsigned long sien;     /* SATA Interrupt Enable register */
-       unsigned long xfer_mode;/* data transfer mode register */
-       unsigned long sfis_cfg; /* SATA FIS reception config register */
-} sil_port[] = {
-       /* port 0 ... */
-       { 0x80, 0x8A, 0x00, 0x10, 0x40, 0x100, 0x148, 0xb4, 0x14c },
-       { 0xC0, 0xCA, 0x08, 0x18, 0x44, 0x180, 0x1c8, 0xf4, 0x1cc },
-       { 0x280, 0x28A, 0x200, 0x210, 0x240, 0x300, 0x348, 0x2b4, 0x34c },
-       { 0x2C0, 0x2CA, 0x208, 0x218, 0x244, 0x380, 0x3c8, 0x2f4, 0x3cc },
-       /* ... port 3 */
-};
-
-MODULE_AUTHOR("Jeff Garzik");
-MODULE_DESCRIPTION("low-level driver for Silicon Image SATA controller");
-MODULE_LICENSE("GPL");
-MODULE_DEVICE_TABLE(pci, sil_pci_tbl);
-MODULE_VERSION(DRV_VERSION);
-
-static int slow_down = 0;
-module_param(slow_down, int, 0444);
-MODULE_PARM_DESC(slow_down, "Sledgehammer used to work around random problems, by limiting commands to 15 sectors (0=off, 1=on)");
-
-
-static unsigned char sil_get_device_cache_line(struct pci_dev *pdev)
-{
-       u8 cache_line = 0;
-       pci_read_config_byte(pdev, PCI_CACHE_LINE_SIZE, &cache_line);
-       return cache_line;
-}
-
-static void sil_post_set_mode (struct ata_port *ap)
-{
-       struct ata_host_set *host_set = ap->host_set;
-       struct ata_device *dev;
-       void __iomem *addr =
-               host_set->mmio_base + sil_port[ap->port_no].xfer_mode;
-       u32 tmp, dev_mode[2];
-       unsigned int i;
-
-       for (i = 0; i < 2; i++) {
-               dev = &ap->device[i];
-               if (!ata_dev_enabled(dev))
-                       dev_mode[i] = 0;        /* PIO0/1/2 */
-               else if (dev->flags & ATA_DFLAG_PIO)
-                       dev_mode[i] = 1;        /* PIO3/4 */
-               else
-                       dev_mode[i] = 3;        /* UDMA */
-               /* value 2 indicates MDMA */
-       }
-
-       tmp = readl(addr);
-       tmp &= ~((1<<5) | (1<<4) | (1<<1) | (1<<0));
-       tmp |= dev_mode[0];
-       tmp |= (dev_mode[1] << 4);
-       writel(tmp, addr);
-       readl(addr);    /* flush */
-}
-
-static inline unsigned long sil_scr_addr(struct ata_port *ap, unsigned int sc_reg)
-{
-       unsigned long offset = ap->ioaddr.scr_addr;
-
-       switch (sc_reg) {
-       case SCR_STATUS:
-               return offset + 4;
-       case SCR_ERROR:
-               return offset + 8;
-       case SCR_CONTROL:
-               return offset;
-       default:
-               /* do nothing */
-               break;
-       }
-
-       return 0;
-}
-
-static u32 sil_scr_read (struct ata_port *ap, unsigned int sc_reg)
-{
-       void __iomem *mmio = (void __iomem *) sil_scr_addr(ap, sc_reg);
-       if (mmio)
-               return readl(mmio);
-       return 0xffffffffU;
-}
-
-static void sil_scr_write (struct ata_port *ap, unsigned int sc_reg, u32 val)
-{
-       void *mmio = (void __iomem *) sil_scr_addr(ap, sc_reg);
-       if (mmio)
-               writel(val, mmio);
-}
-
-static void sil_host_intr(struct ata_port *ap, u32 bmdma2)
-{
-       struct ata_queued_cmd *qc = ata_qc_from_tag(ap, ap->active_tag);
-       u8 status;
-
-       if (unlikely(bmdma2 & SIL_DMA_SATA_IRQ)) {
-               u32 serror;
-
-               /* SIEN doesn't mask SATA IRQs on some 3112s.  Those
-                * controllers continue to assert IRQ as long as
-                * SError bits are pending.  Clear SError immediately.
-                */
-               serror = sil_scr_read(ap, SCR_ERROR);
-               sil_scr_write(ap, SCR_ERROR, serror);
-
-               /* Trigger hotplug and accumulate SError only if the
-                * port isn't already frozen.  Otherwise, PHY events
-                * during hardreset makes controllers with broken SIEN
-                * repeat probing needlessly.
-                */
-               if (!(ap->pflags & ATA_PFLAG_FROZEN)) {
-                       ata_ehi_hotplugged(&ap->eh_info);
-                       ap->eh_info.serror |= serror;
-               }
-
-               goto freeze;
-       }
-
-       if (unlikely(!qc || qc->tf.ctl & ATA_NIEN))
-               goto freeze;
-
-       /* Check whether we are expecting interrupt in this state */
-       switch (ap->hsm_task_state) {
-       case HSM_ST_FIRST:
-               /* Some pre-ATAPI-4 devices assert INTRQ
-                * at this state when ready to receive CDB.
-                */
-
-               /* Check the ATA_DFLAG_CDB_INTR flag is enough here.
-                * The flag was turned on only for atapi devices.
-                * No need to check is_atapi_taskfile(&qc->tf) again.
-                */
-               if (!(qc->dev->flags & ATA_DFLAG_CDB_INTR))
-                       goto err_hsm;
-               break;
-       case HSM_ST_LAST:
-               if (qc->tf.protocol == ATA_PROT_DMA ||
-                   qc->tf.protocol == ATA_PROT_ATAPI_DMA) {
-                       /* clear DMA-Start bit */
-                       ap->ops->bmdma_stop(qc);
-
-                       if (bmdma2 & SIL_DMA_ERROR) {
-                               qc->err_mask |= AC_ERR_HOST_BUS;
-                               ap->hsm_task_state = HSM_ST_ERR;
-                       }
-               }
-               break;
-       case HSM_ST:
-               break;
-       default:
-               goto err_hsm;
-       }
-
-       /* check main status, clearing INTRQ */
-       status = ata_chk_status(ap);
-       if (unlikely(status & ATA_BUSY))
-               goto err_hsm;
-
-       /* ack bmdma irq events */
-       ata_bmdma_irq_clear(ap);
-
-       /* kick HSM in the ass */
-       ata_hsm_move(ap, qc, status, 0);
-
-       return;
-
- err_hsm:
-       qc->err_mask |= AC_ERR_HSM;
- freeze:
-       ata_port_freeze(ap);
-}
-
-static irqreturn_t sil_interrupt(int irq, void *dev_instance,
-                                struct pt_regs *regs)
-{
-       struct ata_host_set *host_set = dev_instance;
-       void __iomem *mmio_base = host_set->mmio_base;
-       int handled = 0;
-       int i;
-
-       spin_lock(&host_set->lock);
-
-       for (i = 0; i < host_set->n_ports; i++) {
-               struct ata_port *ap = host_set->ports[i];
-               u32 bmdma2 = readl(mmio_base + sil_port[ap->port_no].bmdma2);
-
-               if (unlikely(!ap || ap->flags & ATA_FLAG_DISABLED))
-                       continue;
-
-               /* turn off SATA_IRQ if not supported */
-               if (ap->flags & SIL_FLAG_NO_SATA_IRQ)
-                       bmdma2 &= ~SIL_DMA_SATA_IRQ;
-
-               if (bmdma2 == 0xffffffff ||
-                   !(bmdma2 & (SIL_DMA_COMPLETE | SIL_DMA_SATA_IRQ)))
-                       continue;
-
-               sil_host_intr(ap, bmdma2);
-               handled = 1;
-       }
-
-       spin_unlock(&host_set->lock);
-
-       return IRQ_RETVAL(handled);
-}
-
-static void sil_freeze(struct ata_port *ap)
-{
-       void __iomem *mmio_base = ap->host_set->mmio_base;
-       u32 tmp;
-
-       /* global IRQ mask doesn't block SATA IRQ, turn off explicitly */
-       writel(0, mmio_base + sil_port[ap->port_no].sien);
-
-       /* plug IRQ */
-       tmp = readl(mmio_base + SIL_SYSCFG);
-       tmp |= SIL_MASK_IDE0_INT << ap->port_no;
-       writel(tmp, mmio_base + SIL_SYSCFG);
-       readl(mmio_base + SIL_SYSCFG);  /* flush */
-}
-
-static void sil_thaw(struct ata_port *ap)
-{
-       void __iomem *mmio_base = ap->host_set->mmio_base;
-       u32 tmp;
-
-       /* clear IRQ */
-       ata_chk_status(ap);
-       ata_bmdma_irq_clear(ap);
-
-       /* turn on SATA IRQ if supported */
-       if (!(ap->flags & SIL_FLAG_NO_SATA_IRQ))
-               writel(SIL_SIEN_N, mmio_base + sil_port[ap->port_no].sien);
-
-       /* turn on IRQ */
-       tmp = readl(mmio_base + SIL_SYSCFG);
-       tmp &= ~(SIL_MASK_IDE0_INT << ap->port_no);
-       writel(tmp, mmio_base + SIL_SYSCFG);
-}
-
-/**
- *     sil_dev_config - Apply device/host-specific errata fixups
- *     @ap: Port containing device to be examined
- *     @dev: Device to be examined
- *
- *     After the IDENTIFY [PACKET] DEVICE step is complete, and a
- *     device is known to be present, this function is called.
- *     We apply two errata fixups which are specific to Silicon Image,
- *     a Seagate and a Maxtor fixup.
- *
- *     For certain Seagate devices, we must limit the maximum sectors
- *     to under 8K.
- *
- *     For certain Maxtor devices, we must not program the drive
- *     beyond udma5.
- *
- *     Both fixups are unfairly pessimistic.  As soon as I get more
- *     information on these errata, I will create a more exhaustive
- *     list, and apply the fixups to only the specific
- *     devices/hosts/firmwares that need it.
- *
- *     20040111 - Seagate drives affected by the Mod15Write bug are blacklisted
- *     The Maxtor quirk is in the blacklist, but I'm keeping the original
- *     pessimistic fix for the following reasons...
- *     - There seems to be less info on it, only one device gleaned off the
- *     Windows driver, maybe only one is affected.  More info would be greatly
- *     appreciated.
- *     - But then again UDMA5 is hardly anything to complain about
- */
-static void sil_dev_config(struct ata_port *ap, struct ata_device *dev)
-{
-       unsigned int n, quirks = 0;
-       unsigned char model_num[41];
-
-       ata_id_c_string(dev->id, model_num, ATA_ID_PROD_OFS, sizeof(model_num));
-
-       for (n = 0; sil_blacklist[n].product; n++)
-               if (!strcmp(sil_blacklist[n].product, model_num)) {
-                       quirks = sil_blacklist[n].quirk;
-                       break;
-               }
-
-       /* limit requests to 15 sectors */
-       if (slow_down ||
-           ((ap->flags & SIL_FLAG_MOD15WRITE) &&
-            (quirks & SIL_QUIRK_MOD15WRITE))) {
-               ata_dev_printk(dev, KERN_INFO, "applying Seagate errata fix "
-                              "(mod15write workaround)\n");
-               dev->max_sectors = 15;
-               return;
-       }
-
-       /* limit to udma5 */
-       if (quirks & SIL_QUIRK_UDMA5MAX) {
-               ata_dev_printk(dev, KERN_INFO,
-                              "applying Maxtor errata fix %s\n", model_num);
-               dev->udma_mask &= ATA_UDMA5;
-               return;
-       }
-}
-
-static void sil_init_controller(struct pci_dev *pdev,
-                               int n_ports, unsigned long host_flags,
-                               void __iomem *mmio_base)
-{
-       u8 cls;
-       u32 tmp;
-       int i;
-
-       /* Initialize FIFO PCI bus arbitration */
-       cls = sil_get_device_cache_line(pdev);
-       if (cls) {
-               cls >>= 3;
-               cls++;  /* cls = (line_size/8)+1 */
-               for (i = 0; i < n_ports; i++)
-                       writew(cls << 8 | cls,
-                              mmio_base + sil_port[i].fifo_cfg);
-       } else
-               dev_printk(KERN_WARNING, &pdev->dev,
-                          "cache line size not set.  Driver may not function\n");
-
-       /* Apply R_ERR on DMA activate FIS errata workaround */
-       if (host_flags & SIL_FLAG_RERR_ON_DMA_ACT) {
-               int cnt;
-
-               for (i = 0, cnt = 0; i < n_ports; i++) {
-                       tmp = readl(mmio_base + sil_port[i].sfis_cfg);
-                       if ((tmp & 0x3) != 0x01)
-                               continue;
-                       if (!cnt)
-                               dev_printk(KERN_INFO, &pdev->dev,
-                                          "Applying R_ERR on DMA activate "
-                                          "FIS errata fix\n");
-                       writel(tmp & ~0x3, mmio_base + sil_port[i].sfis_cfg);
-                       cnt++;
-               }
-       }
-
-       if (n_ports == 4) {
-               /* flip the magic "make 4 ports work" bit */
-               tmp = readl(mmio_base + sil_port[2].bmdma);
-               if ((tmp & SIL_INTR_STEERING) == 0)
-                       writel(tmp | SIL_INTR_STEERING,
-                              mmio_base + sil_port[2].bmdma);
-       }
-}
-
-static int sil_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
-{
-       static int printed_version;
-       struct ata_probe_ent *probe_ent = NULL;
-       unsigned long base;
-       void __iomem *mmio_base;
-       int rc;
-       unsigned int i;
-       int pci_dev_busy = 0;
-
-       if (!printed_version++)
-               dev_printk(KERN_DEBUG, &pdev->dev, "version " DRV_VERSION "\n");
-
-       rc = pci_enable_device(pdev);
-       if (rc)
-               return rc;
-
-       rc = pci_request_regions(pdev, DRV_NAME);
-       if (rc) {
-               pci_dev_busy = 1;
-               goto err_out;
-       }
-
-       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;
-
-       probe_ent = kzalloc(sizeof(*probe_ent), GFP_KERNEL);
-       if (probe_ent == NULL) {
-               rc = -ENOMEM;
-               goto err_out_regions;
-       }
-
-       INIT_LIST_HEAD(&probe_ent->node);
-       probe_ent->dev = pci_dev_to_dev(pdev);
-       probe_ent->port_ops = sil_port_info[ent->driver_data].port_ops;
-       probe_ent->sht = sil_port_info[ent->driver_data].sht;
-       probe_ent->n_ports = (ent->driver_data == sil_3114) ? 4 : 2;
-       probe_ent->pio_mask = sil_port_info[ent->driver_data].pio_mask;
-       probe_ent->mwdma_mask = sil_port_info[ent->driver_data].mwdma_mask;
-       probe_ent->udma_mask = sil_port_info[ent->driver_data].udma_mask;
-               probe_ent->irq = pdev->irq;
-               probe_ent->irq_flags = IRQF_SHARED;
-       probe_ent->host_flags = sil_port_info[ent->driver_data].host_flags;
-
-       mmio_base = pci_iomap(pdev, 5, 0);
-       if (mmio_base == NULL) {
-               rc = -ENOMEM;
-               goto err_out_free_ent;
-       }
-
-       probe_ent->mmio_base = mmio_base;
-
-       base = (unsigned long) mmio_base;
-
-       for (i = 0; i < probe_ent->n_ports; i++) {
-               probe_ent->port[i].cmd_addr = base + sil_port[i].tf;
-               probe_ent->port[i].altstatus_addr =
-               probe_ent->port[i].ctl_addr = base + sil_port[i].ctl;
-               probe_ent->port[i].bmdma_addr = base + sil_port[i].bmdma;
-               probe_ent->port[i].scr_addr = base + sil_port[i].scr;
-               ata_std_ports(&probe_ent->port[i]);
-       }
-
-       sil_init_controller(pdev, probe_ent->n_ports, probe_ent->host_flags,
-                           mmio_base);
-
-       pci_set_master(pdev);
-
-       /* FIXME: check ata_device_add return value */
-       ata_device_add(probe_ent);
-       kfree(probe_ent);
-
-       return 0;
-
-err_out_free_ent:
-       kfree(probe_ent);
-err_out_regions:
-       pci_release_regions(pdev);
-err_out:
-       if (!pci_dev_busy)
-               pci_disable_device(pdev);
-       return rc;
-}
-
-static int sil_pci_device_resume(struct pci_dev *pdev)
-{
-       struct ata_host_set *host_set = dev_get_drvdata(&pdev->dev);
-
-       ata_pci_device_do_resume(pdev);
-       sil_init_controller(pdev, host_set->n_ports, host_set->ports[0]->flags,
-                           host_set->mmio_base);
-       ata_host_set_resume(host_set);
-
-       return 0;
-}
-
-static int __init sil_init(void)
-{
-       return pci_register_driver(&sil_pci_driver);
-}
-
-static void __exit sil_exit(void)
-{
-       pci_unregister_driver(&sil_pci_driver);
-}
-
-
-module_init(sil_init);
-module_exit(sil_exit);
diff --git a/drivers/scsi/sata_sil24.c b/drivers/scsi/sata_sil24.c
deleted file mode 100644 (file)
index 3a0161d..0000000
+++ /dev/null
@@ -1,1222 +0,0 @@
-/*
- * sata_sil24.c - Driver for Silicon Image 3124/3132 SATA-2 controllers
- *
- * Copyright 2005  Tejun Heo
- *
- * Based on preview driver from Silicon Image.
- *
- * 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.
- *
- */
-
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/pci.h>
-#include <linux/blkdev.h>
-#include <linux/delay.h>
-#include <linux/interrupt.h>
-#include <linux/dma-mapping.h>
-#include <linux/device.h>
-#include <scsi/scsi_host.h>
-#include <scsi/scsi_cmnd.h>
-#include <linux/libata.h>
-#include <asm/io.h>
-
-#define DRV_NAME       "sata_sil24"
-#define DRV_VERSION    "0.3"
-
-/*
- * Port request block (PRB) 32 bytes
- */
-struct sil24_prb {
-       __le16  ctrl;
-       __le16  prot;
-       __le32  rx_cnt;
-       u8      fis[6 * 4];
-};
-
-/*
- * Scatter gather entry (SGE) 16 bytes
- */
-struct sil24_sge {
-       __le64  addr;
-       __le32  cnt;
-       __le32  flags;
-};
-
-/*
- * Port multiplier
- */
-struct sil24_port_multiplier {
-       __le32  diag;
-       __le32  sactive;
-};
-
-enum {
-       /*
-        * Global controller registers (128 bytes @ BAR0)
-        */
-               /* 32 bit regs */
-       HOST_SLOT_STAT          = 0x00, /* 32 bit slot stat * 4 */
-       HOST_CTRL               = 0x40,
-       HOST_IRQ_STAT           = 0x44,
-       HOST_PHY_CFG            = 0x48,
-       HOST_BIST_CTRL          = 0x50,
-       HOST_BIST_PTRN          = 0x54,
-       HOST_BIST_STAT          = 0x58,
-       HOST_MEM_BIST_STAT      = 0x5c,
-       HOST_FLASH_CMD          = 0x70,
-               /* 8 bit regs */
-       HOST_FLASH_DATA         = 0x74,
-       HOST_TRANSITION_DETECT  = 0x75,
-       HOST_GPIO_CTRL          = 0x76,
-       HOST_I2C_ADDR           = 0x78, /* 32 bit */
-       HOST_I2C_DATA           = 0x7c,
-       HOST_I2C_XFER_CNT       = 0x7e,
-       HOST_I2C_CTRL           = 0x7f,
-
-       /* HOST_SLOT_STAT bits */
-       HOST_SSTAT_ATTN         = (1 << 31),
-
-       /* HOST_CTRL bits */
-       HOST_CTRL_M66EN         = (1 << 16), /* M66EN PCI bus signal */
-       HOST_CTRL_TRDY          = (1 << 17), /* latched PCI TRDY */
-       HOST_CTRL_STOP          = (1 << 18), /* latched PCI STOP */
-       HOST_CTRL_DEVSEL        = (1 << 19), /* latched PCI DEVSEL */
-       HOST_CTRL_REQ64         = (1 << 20), /* latched PCI REQ64 */
-       HOST_CTRL_GLOBAL_RST    = (1 << 31), /* global reset */
-
-       /*
-        * Port registers
-        * (8192 bytes @ +0x0000, +0x2000, +0x4000 and +0x6000 @ BAR2)
-        */
-       PORT_REGS_SIZE          = 0x2000,
-
-       PORT_LRAM               = 0x0000, /* 31 LRAM slots and PM regs */
-       PORT_LRAM_SLOT_SZ       = 0x0080, /* 32 bytes PRB + 2 SGE, ACT... */
-
-       PORT_PM                 = 0x0f80, /* 8 bytes PM * 16 (128 bytes) */
-               /* 32 bit regs */
-       PORT_CTRL_STAT          = 0x1000, /* write: ctrl-set, read: stat */
-       PORT_CTRL_CLR           = 0x1004, /* write: ctrl-clear */
-       PORT_IRQ_STAT           = 0x1008, /* high: status, low: interrupt */
-       PORT_IRQ_ENABLE_SET     = 0x1010, /* write: enable-set */
-       PORT_IRQ_ENABLE_CLR     = 0x1014, /* write: enable-clear */
-       PORT_ACTIVATE_UPPER_ADDR= 0x101c,
-       PORT_EXEC_FIFO          = 0x1020, /* command execution fifo */
-       PORT_CMD_ERR            = 0x1024, /* command error number */
-       PORT_FIS_CFG            = 0x1028,
-       PORT_FIFO_THRES         = 0x102c,
-               /* 16 bit regs */
-       PORT_DECODE_ERR_CNT     = 0x1040,
-       PORT_DECODE_ERR_THRESH  = 0x1042,
-       PORT_CRC_ERR_CNT        = 0x1044,
-       PORT_CRC_ERR_THRESH     = 0x1046,
-       PORT_HSHK_ERR_CNT       = 0x1048,
-       PORT_HSHK_ERR_THRESH    = 0x104a,
-               /* 32 bit regs */
-       PORT_PHY_CFG            = 0x1050,
-       PORT_SLOT_STAT          = 0x1800,
-       PORT_CMD_ACTIVATE       = 0x1c00, /* 64 bit cmd activate * 31 (248 bytes) */
-       PORT_EXEC_DIAG          = 0x1e00, /* 32bit exec diag * 16 (64 bytes, 0-10 used on 3124) */
-       PORT_PSD_DIAG           = 0x1e40, /* 32bit psd diag * 16 (64 bytes, 0-8 used on 3124) */
-       PORT_SCONTROL           = 0x1f00,
-       PORT_SSTATUS            = 0x1f04,
-       PORT_SERROR             = 0x1f08,
-       PORT_SACTIVE            = 0x1f0c,
-
-       /* PORT_CTRL_STAT bits */
-       PORT_CS_PORT_RST        = (1 << 0), /* port reset */
-       PORT_CS_DEV_RST         = (1 << 1), /* device reset */
-       PORT_CS_INIT            = (1 << 2), /* port initialize */
-       PORT_CS_IRQ_WOC         = (1 << 3), /* interrupt write one to clear */
-       PORT_CS_CDB16           = (1 << 5), /* 0=12b cdb, 1=16b cdb */
-       PORT_CS_RESUME          = (1 << 6), /* port resume */
-       PORT_CS_32BIT_ACTV      = (1 << 10), /* 32-bit activation */
-       PORT_CS_PM_EN           = (1 << 13), /* port multiplier enable */
-       PORT_CS_RDY             = (1 << 31), /* port ready to accept commands */
-
-       /* PORT_IRQ_STAT/ENABLE_SET/CLR */
-       /* bits[11:0] are masked */
-       PORT_IRQ_COMPLETE       = (1 << 0), /* command(s) completed */
-       PORT_IRQ_ERROR          = (1 << 1), /* command execution error */
-       PORT_IRQ_PORTRDY_CHG    = (1 << 2), /* port ready change */
-       PORT_IRQ_PWR_CHG        = (1 << 3), /* power management change */
-       PORT_IRQ_PHYRDY_CHG     = (1 << 4), /* PHY ready change */
-       PORT_IRQ_COMWAKE        = (1 << 5), /* COMWAKE received */
-       PORT_IRQ_UNK_FIS        = (1 << 6), /* unknown FIS received */
-       PORT_IRQ_DEV_XCHG       = (1 << 7), /* device exchanged */
-       PORT_IRQ_8B10B          = (1 << 8), /* 8b/10b decode error threshold */
-       PORT_IRQ_CRC            = (1 << 9), /* CRC error threshold */
-       PORT_IRQ_HANDSHAKE      = (1 << 10), /* handshake error threshold */
-       PORT_IRQ_SDB_NOTIFY     = (1 << 11), /* SDB notify received */
-
-       DEF_PORT_IRQ            = PORT_IRQ_COMPLETE | PORT_IRQ_ERROR |
-                                 PORT_IRQ_PHYRDY_CHG | PORT_IRQ_DEV_XCHG |
-                                 PORT_IRQ_UNK_FIS,
-
-       /* bits[27:16] are unmasked (raw) */
-       PORT_IRQ_RAW_SHIFT      = 16,
-       PORT_IRQ_MASKED_MASK    = 0x7ff,
-       PORT_IRQ_RAW_MASK       = (0x7ff << PORT_IRQ_RAW_SHIFT),
-
-       /* ENABLE_SET/CLR specific, intr steering - 2 bit field */
-       PORT_IRQ_STEER_SHIFT    = 30,
-       PORT_IRQ_STEER_MASK     = (3 << PORT_IRQ_STEER_SHIFT),
-
-       /* PORT_CMD_ERR constants */
-       PORT_CERR_DEV           = 1, /* Error bit in D2H Register FIS */
-       PORT_CERR_SDB           = 2, /* Error bit in SDB FIS */
-       PORT_CERR_DATA          = 3, /* Error in data FIS not detected by dev */
-       PORT_CERR_SEND          = 4, /* Initial cmd FIS transmission failure */
-       PORT_CERR_INCONSISTENT  = 5, /* Protocol mismatch */
-       PORT_CERR_DIRECTION     = 6, /* Data direction mismatch */
-       PORT_CERR_UNDERRUN      = 7, /* Ran out of SGEs while writing */
-       PORT_CERR_OVERRUN       = 8, /* Ran out of SGEs while reading */
-       PORT_CERR_PKT_PROT      = 11, /* DIR invalid in 1st PIO setup of ATAPI */
-       PORT_CERR_SGT_BOUNDARY  = 16, /* PLD ecode 00 - SGT not on qword boundary */
-       PORT_CERR_SGT_TGTABRT   = 17, /* PLD ecode 01 - target abort */
-       PORT_CERR_SGT_MSTABRT   = 18, /* PLD ecode 10 - master abort */
-       PORT_CERR_SGT_PCIPERR   = 19, /* PLD ecode 11 - PCI parity err while fetching SGT */
-       PORT_CERR_CMD_BOUNDARY  = 24, /* ctrl[15:13] 001 - PRB not on qword boundary */
-       PORT_CERR_CMD_TGTABRT   = 25, /* ctrl[15:13] 010 - target abort */
-       PORT_CERR_CMD_MSTABRT   = 26, /* ctrl[15:13] 100 - master abort */
-       PORT_CERR_CMD_PCIPERR   = 27, /* ctrl[15:13] 110 - PCI parity err while fetching PRB */
-       PORT_CERR_XFR_UNDEF     = 32, /* PSD ecode 00 - undefined */
-       PORT_CERR_XFR_TGTABRT   = 33, /* PSD ecode 01 - target abort */
-       PORT_CERR_XFR_MSTABRT   = 34, /* PSD ecode 10 - master abort */
-       PORT_CERR_XFR_PCIPERR   = 35, /* PSD ecode 11 - PCI prity err during transfer */
-       PORT_CERR_SENDSERVICE   = 36, /* FIS received while sending service */
-
-       /* bits of PRB control field */
-       PRB_CTRL_PROTOCOL       = (1 << 0), /* override def. ATA protocol */
-       PRB_CTRL_PACKET_READ    = (1 << 4), /* PACKET cmd read */
-       PRB_CTRL_PACKET_WRITE   = (1 << 5), /* PACKET cmd write */
-       PRB_CTRL_NIEN           = (1 << 6), /* Mask completion irq */
-       PRB_CTRL_SRST           = (1 << 7), /* Soft reset request (ign BSY?) */
-
-       /* PRB protocol field */
-       PRB_PROT_PACKET         = (1 << 0),
-       PRB_PROT_TCQ            = (1 << 1),
-       PRB_PROT_NCQ            = (1 << 2),
-       PRB_PROT_READ           = (1 << 3),
-       PRB_PROT_WRITE          = (1 << 4),
-       PRB_PROT_TRANSPARENT    = (1 << 5),
-
-       /*
-        * Other constants
-        */
-       SGE_TRM                 = (1 << 31), /* Last SGE in chain */
-       SGE_LNK                 = (1 << 30), /* linked list
-                                               Points to SGT, not SGE */
-       SGE_DRD                 = (1 << 29), /* discard data read (/dev/null)
-                                               data address ignored */
-
-       SIL24_MAX_CMDS          = 31,
-
-       /* board id */
-       BID_SIL3124             = 0,
-       BID_SIL3132             = 1,
-       BID_SIL3131             = 2,
-
-       /* host flags */
-       SIL24_COMMON_FLAGS      = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
-                                 ATA_FLAG_MMIO | ATA_FLAG_PIO_DMA |
-                                 ATA_FLAG_NCQ | ATA_FLAG_SKIP_D2H_BSY,
-       SIL24_FLAG_PCIX_IRQ_WOC = (1 << 24), /* IRQ loss errata on PCI-X */
-
-       IRQ_STAT_4PORTS         = 0xf,
-};
-
-struct sil24_ata_block {
-       struct sil24_prb prb;
-       struct sil24_sge sge[LIBATA_MAX_PRD];
-};
-
-struct sil24_atapi_block {
-       struct sil24_prb prb;
-       u8 cdb[16];
-       struct sil24_sge sge[LIBATA_MAX_PRD - 1];
-};
-
-union sil24_cmd_block {
-       struct sil24_ata_block ata;
-       struct sil24_atapi_block atapi;
-};
-
-static struct sil24_cerr_info {
-       unsigned int err_mask, action;
-       const char *desc;
-} sil24_cerr_db[] = {
-       [0]                     = { AC_ERR_DEV, ATA_EH_REVALIDATE,
-                                   "device error" },
-       [PORT_CERR_DEV]         = { AC_ERR_DEV, ATA_EH_REVALIDATE,
-                                   "device error via D2H FIS" },
-       [PORT_CERR_SDB]         = { AC_ERR_DEV, ATA_EH_REVALIDATE,
-                                   "device error via SDB FIS" },
-       [PORT_CERR_DATA]        = { AC_ERR_ATA_BUS, ATA_EH_SOFTRESET,
-                                   "error in data FIS" },
-       [PORT_CERR_SEND]        = { AC_ERR_ATA_BUS, ATA_EH_SOFTRESET,
-                                   "failed to transmit command FIS" },
-       [PORT_CERR_INCONSISTENT] = { AC_ERR_HSM, ATA_EH_SOFTRESET,
-                                    "protocol mismatch" },
-       [PORT_CERR_DIRECTION]   = { AC_ERR_HSM, ATA_EH_SOFTRESET,
-                                   "data directon mismatch" },
-       [PORT_CERR_UNDERRUN]    = { AC_ERR_HSM, ATA_EH_SOFTRESET,
-                                   "ran out of SGEs while writing" },
-       [PORT_CERR_OVERRUN]     = { AC_ERR_HSM, ATA_EH_SOFTRESET,
-                                   "ran out of SGEs while reading" },
-       [PORT_CERR_PKT_PROT]    = { AC_ERR_HSM, ATA_EH_SOFTRESET,
-                                   "invalid data directon for ATAPI CDB" },
-       [PORT_CERR_SGT_BOUNDARY] = { AC_ERR_SYSTEM, ATA_EH_SOFTRESET,
-                                    "SGT no on qword boundary" },
-       [PORT_CERR_SGT_TGTABRT] = { AC_ERR_HOST_BUS, ATA_EH_SOFTRESET,
-                                   "PCI target abort while fetching SGT" },
-       [PORT_CERR_SGT_MSTABRT] = { AC_ERR_HOST_BUS, ATA_EH_SOFTRESET,
-                                   "PCI master abort while fetching SGT" },
-       [PORT_CERR_SGT_PCIPERR] = { AC_ERR_HOST_BUS, ATA_EH_SOFTRESET,
-                                   "PCI parity error while fetching SGT" },
-       [PORT_CERR_CMD_BOUNDARY] = { AC_ERR_SYSTEM, ATA_EH_SOFTRESET,
-                                    "PRB not on qword boundary" },
-       [PORT_CERR_CMD_TGTABRT] = { AC_ERR_HOST_BUS, ATA_EH_SOFTRESET,
-                                   "PCI target abort while fetching PRB" },
-       [PORT_CERR_CMD_MSTABRT] = { AC_ERR_HOST_BUS, ATA_EH_SOFTRESET,
-                                   "PCI master abort while fetching PRB" },
-       [PORT_CERR_CMD_PCIPERR] = { AC_ERR_HOST_BUS, ATA_EH_SOFTRESET,
-                                   "PCI parity error while fetching PRB" },
-       [PORT_CERR_XFR_UNDEF]   = { AC_ERR_HOST_BUS, ATA_EH_SOFTRESET,
-                                   "undefined error while transferring data" },
-       [PORT_CERR_XFR_TGTABRT] = { AC_ERR_HOST_BUS, ATA_EH_SOFTRESET,
-                                   "PCI target abort while transferring data" },
-       [PORT_CERR_XFR_MSTABRT] = { AC_ERR_HOST_BUS, ATA_EH_SOFTRESET,
-                                   "PCI master abort while transferring data" },
-       [PORT_CERR_XFR_PCIPERR] = { AC_ERR_HOST_BUS, ATA_EH_SOFTRESET,
-                                   "PCI parity error while transferring data" },
-       [PORT_CERR_SENDSERVICE] = { AC_ERR_HSM, ATA_EH_SOFTRESET,
-                                   "FIS received while sending service FIS" },
-};
-
-/*
- * ap->private_data
- *
- * The preview driver always returned 0 for status.  We emulate it
- * here from the previous interrupt.
- */
-struct sil24_port_priv {
-       union sil24_cmd_block *cmd_block;       /* 32 cmd blocks */
-       dma_addr_t cmd_block_dma;               /* DMA base addr for them */
-       struct ata_taskfile tf;                 /* Cached taskfile registers */
-};
-
-/* ap->host_set->private_data */
-struct sil24_host_priv {
-       void __iomem *host_base;        /* global controller control (128 bytes @BAR0) */
-       void __iomem *port_base;        /* port registers (4 * 8192 bytes @BAR2) */
-};
-
-static void sil24_dev_config(struct ata_port *ap, struct ata_device *dev);
-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_qc_prep(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 irqreturn_t sil24_interrupt(int irq, void *dev_instance, struct pt_regs *regs);
-static void sil24_freeze(struct ata_port *ap);
-static void sil24_thaw(struct ata_port *ap);
-static void sil24_error_handler(struct ata_port *ap);
-static void sil24_post_internal_cmd(struct ata_queued_cmd *qc);
-static int sil24_port_start(struct ata_port *ap);
-static void sil24_port_stop(struct ata_port *ap);
-static void sil24_host_stop(struct ata_host_set *host_set);
-static int sil24_init_one(struct pci_dev *pdev, const struct pci_device_id *ent);
-static int sil24_pci_device_resume(struct pci_dev *pdev);
-
-static const struct pci_device_id sil24_pci_tbl[] = {
-       { 0x1095, 0x3124, PCI_ANY_ID, PCI_ANY_ID, 0, 0, BID_SIL3124 },
-       { 0x8086, 0x3124, PCI_ANY_ID, PCI_ANY_ID, 0, 0, BID_SIL3124 },
-       { 0x1095, 0x3132, PCI_ANY_ID, PCI_ANY_ID, 0, 0, BID_SIL3132 },
-       { 0x1095, 0x3131, PCI_ANY_ID, PCI_ANY_ID, 0, 0, BID_SIL3131 },
-       { 0x1095, 0x3531, PCI_ANY_ID, PCI_ANY_ID, 0, 0, BID_SIL3131 },
-       { } /* terminate list */
-};
-
-static struct pci_driver sil24_pci_driver = {
-       .name                   = DRV_NAME,
-       .id_table               = sil24_pci_tbl,
-       .probe                  = sil24_init_one,
-       .remove                 = ata_pci_remove_one, /* safe? */
-       .suspend                = ata_pci_device_suspend,
-       .resume                 = sil24_pci_device_resume,
-};
-
-static struct scsi_host_template sil24_sht = {
-       .module                 = THIS_MODULE,
-       .name                   = DRV_NAME,
-       .ioctl                  = ata_scsi_ioctl,
-       .queuecommand           = ata_scsi_queuecmd,
-       .change_queue_depth     = ata_scsi_change_queue_depth,
-       .can_queue              = SIL24_MAX_CMDS,
-       .this_id                = ATA_SHT_THIS_ID,
-       .sg_tablesize           = LIBATA_MAX_PRD,
-       .cmd_per_lun            = ATA_SHT_CMD_PER_LUN,
-       .emulated               = ATA_SHT_EMULATED,
-       .use_clustering         = ATA_SHT_USE_CLUSTERING,
-       .proc_name              = DRV_NAME,
-       .dma_boundary           = ATA_DMA_BOUNDARY,
-       .slave_configure        = ata_scsi_slave_config,
-       .slave_destroy          = ata_scsi_slave_destroy,
-       .bios_param             = ata_std_bios_param,
-       .suspend                = ata_scsi_device_suspend,
-       .resume                 = ata_scsi_device_resume,
-};
-
-static const struct ata_port_operations sil24_ops = {
-       .port_disable           = ata_port_disable,
-
-       .dev_config             = sil24_dev_config,
-
-       .check_status           = sil24_check_status,
-       .check_altstatus        = sil24_check_status,
-       .dev_select             = ata_noop_dev_select,
-
-       .tf_read                = sil24_tf_read,
-
-       .qc_prep                = sil24_qc_prep,
-       .qc_issue               = sil24_qc_issue,
-
-       .irq_handler            = sil24_interrupt,
-       .irq_clear              = sil24_irq_clear,
-
-       .scr_read               = sil24_scr_read,
-       .scr_write              = sil24_scr_write,
-
-       .freeze                 = sil24_freeze,
-       .thaw                   = sil24_thaw,
-       .error_handler          = sil24_error_handler,
-       .post_internal_cmd      = sil24_post_internal_cmd,
-
-       .port_start             = sil24_port_start,
-       .port_stop              = sil24_port_stop,
-       .host_stop              = sil24_host_stop,
-};
-
-/*
- * Use bits 30-31 of host_flags to encode available port numbers.
- * Current maxium is 4.
- */
-#define SIL24_NPORTS2FLAG(nports)      ((((unsigned)(nports) - 1) & 0x3) << 30)
-#define SIL24_FLAG2NPORTS(flag)                ((((flag) >> 30) & 0x3) + 1)
-
-static struct ata_port_info sil24_port_info[] = {
-       /* sil_3124 */
-       {
-               .sht            = &sil24_sht,
-               .host_flags     = SIL24_COMMON_FLAGS | SIL24_NPORTS2FLAG(4) |
-                                 SIL24_FLAG_PCIX_IRQ_WOC,
-               .pio_mask       = 0x1f,                 /* pio0-4 */
-               .mwdma_mask     = 0x07,                 /* mwdma0-2 */
-               .udma_mask      = 0x3f,                 /* udma0-5 */
-               .port_ops       = &sil24_ops,
-       },
-       /* sil_3132 */
-       {
-               .sht            = &sil24_sht,
-               .host_flags     = SIL24_COMMON_FLAGS | SIL24_NPORTS2FLAG(2),
-               .pio_mask       = 0x1f,                 /* pio0-4 */
-               .mwdma_mask     = 0x07,                 /* mwdma0-2 */
-               .udma_mask      = 0x3f,                 /* udma0-5 */
-               .port_ops       = &sil24_ops,
-       },
-       /* sil_3131/sil_3531 */
-       {
-               .sht            = &sil24_sht,
-               .host_flags     = SIL24_COMMON_FLAGS | SIL24_NPORTS2FLAG(1),
-               .pio_mask       = 0x1f,                 /* pio0-4 */
-               .mwdma_mask     = 0x07,                 /* mwdma0-2 */
-               .udma_mask      = 0x3f,                 /* udma0-5 */
-               .port_ops       = &sil24_ops,
-       },
-};
-
-static int sil24_tag(int tag)
-{
-       if (unlikely(ata_tag_internal(tag)))
-               return 0;
-       return tag;
-}
-
-static void sil24_dev_config(struct ata_port *ap, struct ata_device *dev)
-{
-       void __iomem *port = (void __iomem *)ap->ioaddr.cmd_addr;
-
-       if (dev->cdb_len == 16)
-               writel(PORT_CS_CDB16, port + PORT_CTRL_STAT);
-       else
-               writel(PORT_CS_CDB16, port + PORT_CTRL_CLR);
-}
-
-static inline void sil24_update_tf(struct ata_port *ap)
-{
-       struct sil24_port_priv *pp = ap->private_data;
-       void __iomem *port = (void __iomem *)ap->ioaddr.cmd_addr;
-       struct sil24_prb __iomem *prb = port;
-       u8 fis[6 * 4];
-
-       memcpy_fromio(fis, prb->fis, 6 * 4);
-       ata_tf_from_fis(fis, &pp->tf);
-}
-
-static u8 sil24_check_status(struct ata_port *ap)
-{
-       struct sil24_port_priv *pp = ap->private_data;
-       return pp->tf.command;
-}
-
-static int sil24_scr_map[] = {
-       [SCR_CONTROL]   = 0,
-       [SCR_STATUS]    = 1,
-       [SCR_ERROR]     = 2,
-       [SCR_ACTIVE]    = 3,
-};
-
-static u32 sil24_scr_read(struct ata_port *ap, unsigned sc_reg)
-{
-       void __iomem *scr_addr = (void __iomem *)ap->ioaddr.scr_addr;
-       if (sc_reg < ARRAY_SIZE(sil24_scr_map)) {
-               void __iomem *addr;
-               addr = scr_addr + sil24_scr_map[sc_reg] * 4;
-               return readl(scr_addr + sil24_scr_map[sc_reg] * 4);
-       }
-       return 0xffffffffU;
-}
-
-static void sil24_scr_write(struct ata_port *ap, unsigned sc_reg, u32 val)
-{
-       void __iomem *scr_addr = (void __iomem *)ap->ioaddr.scr_addr;
-       if (sc_reg < ARRAY_SIZE(sil24_scr_map)) {
-               void __iomem *addr;
-               addr = scr_addr + sil24_scr_map[sc_reg] * 4;
-               writel(val, scr_addr + sil24_scr_map[sc_reg] * 4);
-       }
-}
-
-static void sil24_tf_read(struct ata_port *ap, struct ata_taskfile *tf)
-{
-       struct sil24_port_priv *pp = ap->private_data;
-       *tf = pp->tf;
-}
-
-static int sil24_init_port(struct ata_port *ap)
-{
-       void __iomem *port = (void __iomem *)ap->ioaddr.cmd_addr;
-       u32 tmp;
-
-       writel(PORT_CS_INIT, port + PORT_CTRL_STAT);
-       ata_wait_register(port + PORT_CTRL_STAT,
-                         PORT_CS_INIT, PORT_CS_INIT, 10, 100);
-       tmp = ata_wait_register(port + PORT_CTRL_STAT,
-                               PORT_CS_RDY, 0, 10, 100);
-
-       if ((tmp & (PORT_CS_INIT | PORT_CS_RDY)) != PORT_CS_RDY)
-               return -EIO;
-       return 0;
-}
-
-static int sil24_softreset(struct ata_port *ap, unsigned int *class)
-{
-       void __iomem *port = (void __iomem *)ap->ioaddr.cmd_addr;
-       struct sil24_port_priv *pp = ap->private_data;
-       struct sil24_prb *prb = &pp->cmd_block[0].ata.prb;
-       dma_addr_t paddr = pp->cmd_block_dma;
-       u32 mask, irq_stat;
-       const char *reason;
-
-       DPRINTK("ENTER\n");
-
-       if (ata_port_offline(ap)) {
-               DPRINTK("PHY reports no device\n");
-               *class = ATA_DEV_NONE;
-               goto out;
-       }
-
-       /* put the port into known state */
-       if (sil24_init_port(ap)) {
-               reason ="port not ready";
-               goto err;
-       }
-
-       /* do SRST */
-       prb->ctrl = cpu_to_le16(PRB_CTRL_SRST);
-       prb->fis[1] = 0; /* no PM yet */
-
-       writel((u32)paddr, port + PORT_CMD_ACTIVATE);
-       writel((u64)paddr >> 32, port + PORT_CMD_ACTIVATE + 4);
-
-       mask = (PORT_IRQ_COMPLETE | PORT_IRQ_ERROR) << PORT_IRQ_RAW_SHIFT;
-       irq_stat = ata_wait_register(port + PORT_IRQ_STAT, mask, 0x0,
-                                    100, ATA_TMOUT_BOOT / HZ * 1000);
-
-       writel(irq_stat, port + PORT_IRQ_STAT); /* clear IRQs */
-       irq_stat >>= PORT_IRQ_RAW_SHIFT;
-
-       if (!(irq_stat & PORT_IRQ_COMPLETE)) {
-               if (irq_stat & PORT_IRQ_ERROR)
-                       reason = "SRST command error";
-               else
-                       reason = "timeout";
-               goto err;
-       }
-
-       sil24_update_tf(ap);
-       *class = ata_dev_classify(&pp->tf);
-
-       if (*class == ATA_DEV_UNKNOWN)
-               *class = ATA_DEV_NONE;
-
- out:
-       DPRINTK("EXIT, class=%u\n", *class);
-       return 0;
-
- err:
-       ata_port_printk(ap, KERN_ERR, "softreset failed (%s)\n", reason);
-       return -EIO;
-}
-
-static int sil24_hardreset(struct ata_port *ap, unsigned int *class)
-{
-       void __iomem *port = (void __iomem *)ap->ioaddr.cmd_addr;
-       const char *reason;
-       int tout_msec, rc;
-       u32 tmp;
-
-       /* sil24 does the right thing(tm) without any protection */
-       sata_set_spd(ap);
-
-       tout_msec = 100;
-       if (ata_port_online(ap))
-               tout_msec = 5000;
-
-       writel(PORT_CS_DEV_RST, port + PORT_CTRL_STAT);
-       tmp = ata_wait_register(port + PORT_CTRL_STAT,
-                               PORT_CS_DEV_RST, PORT_CS_DEV_RST, 10, tout_msec);
-
-       /* SStatus oscillates between zero and valid status after
-        * DEV_RST, debounce it.
-        */
-       rc = sata_phy_debounce(ap, sata_deb_timing_long);
-       if (rc) {
-               reason = "PHY debouncing failed";
-               goto err;
-       }
-
-       if (tmp & PORT_CS_DEV_RST) {
-               if (ata_port_offline(ap))
-                       return 0;
-               reason = "link not ready";
-               goto err;
-       }
-
-       /* Sil24 doesn't store signature FIS after hardreset, so we
-        * can't wait for BSY to clear.  Some devices take a long time
-        * to get ready and those devices will choke if we don't wait
-        * for BSY clearance here.  Tell libata to perform follow-up
-        * softreset.
-        */
-       return -EAGAIN;
-
- err:
-       ata_port_printk(ap, KERN_ERR, "hardreset failed (%s)\n", reason);
-       return -EIO;
-}
-
-static inline void sil24_fill_sg(struct ata_queued_cmd *qc,
-                                struct sil24_sge *sge)
-{
-       struct scatterlist *sg;
-       unsigned int idx = 0;
-
-       ata_for_each_sg(sg, qc) {
-               sge->addr = cpu_to_le64(sg_dma_address(sg));
-               sge->cnt = cpu_to_le32(sg_dma_len(sg));
-               if (ata_sg_is_last(sg, qc))
-                       sge->flags = cpu_to_le32(SGE_TRM);
-               else
-                       sge->flags = 0;
-
-               sge++;
-               idx++;
-       }
-}
-
-static void sil24_qc_prep(struct ata_queued_cmd *qc)
-{
-       struct ata_port *ap = qc->ap;
-       struct sil24_port_priv *pp = ap->private_data;
-       union sil24_cmd_block *cb;
-       struct sil24_prb *prb;
-       struct sil24_sge *sge;
-       u16 ctrl = 0;
-
-       cb = &pp->cmd_block[sil24_tag(qc->tag)];
-
-       switch (qc->tf.protocol) {
-       case ATA_PROT_PIO:
-       case ATA_PROT_DMA:
-       case ATA_PROT_NCQ:
-       case ATA_PROT_NODATA:
-               prb = &cb->ata.prb;
-               sge = cb->ata.sge;
-               break;
-
-       case ATA_PROT_ATAPI:
-       case ATA_PROT_ATAPI_DMA:
-       case ATA_PROT_ATAPI_NODATA:
-               prb = &cb->atapi.prb;
-               sge = cb->atapi.sge;
-               memset(cb->atapi.cdb, 0, 32);
-               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)
-                               ctrl = PRB_CTRL_PACKET_WRITE;
-                       else
-                               ctrl = PRB_CTRL_PACKET_READ;
-               }
-               break;
-
-       default:
-               prb = NULL;     /* shut up, gcc */
-               sge = NULL;
-               BUG();
-       }
-
-       prb->ctrl = cpu_to_le16(ctrl);
-       ata_tf_to_fis(&qc->tf, prb->fis, 0);
-
-       if (qc->flags & ATA_QCFLAG_DMAMAP)
-               sil24_fill_sg(qc, sge);
-}
-
-static unsigned int sil24_qc_issue(struct ata_queued_cmd *qc)
-{
-       struct ata_port *ap = qc->ap;
-       struct sil24_port_priv *pp = ap->private_data;
-       void __iomem *port = (void __iomem *)ap->ioaddr.cmd_addr;
-       unsigned int tag = sil24_tag(qc->tag);
-       dma_addr_t paddr;
-       void __iomem *activate;
-
-       paddr = pp->cmd_block_dma + tag * sizeof(*pp->cmd_block);
-       activate = port + PORT_CMD_ACTIVATE + tag * 8;
-
-       writel((u32)paddr, activate);
-       writel((u64)paddr >> 32, activate + 4);
-
-       return 0;
-}
-
-static void sil24_irq_clear(struct ata_port *ap)
-{
-       /* unused */
-}
-
-static void sil24_freeze(struct ata_port *ap)
-{
-       void __iomem *port = (void __iomem *)ap->ioaddr.cmd_addr;
-
-       /* Port-wide IRQ mask in HOST_CTRL doesn't really work, clear
-        * PORT_IRQ_ENABLE instead.
-        */
-       writel(0xffff, port + PORT_IRQ_ENABLE_CLR);
-}
-
-static void sil24_thaw(struct ata_port *ap)
-{
-       void __iomem *port = (void __iomem *)ap->ioaddr.cmd_addr;
-       u32 tmp;
-
-       /* clear IRQ */
-       tmp = readl(port + PORT_IRQ_STAT);
-       writel(tmp, port + PORT_IRQ_STAT);
-
-       /* turn IRQ back on */
-       writel(DEF_PORT_IRQ, port + PORT_IRQ_ENABLE_SET);
-}
-
-static void sil24_error_intr(struct ata_port *ap)
-{
-       void __iomem *port = (void __iomem *)ap->ioaddr.cmd_addr;
-       struct ata_eh_info *ehi = &ap->eh_info;
-       int freeze = 0;
-       u32 irq_stat;
-
-       /* on error, we need to clear IRQ explicitly */
-       irq_stat = readl(port + PORT_IRQ_STAT);
-       writel(irq_stat, port + PORT_IRQ_STAT);
-
-       /* first, analyze and record host port events */
-       ata_ehi_clear_desc(ehi);
-
-       ata_ehi_push_desc(ehi, "irq_stat 0x%08x", irq_stat);
-
-       if (irq_stat & (PORT_IRQ_PHYRDY_CHG | PORT_IRQ_DEV_XCHG)) {
-               ata_ehi_hotplugged(ehi);
-               ata_ehi_push_desc(ehi, ", %s",
-                              irq_stat & PORT_IRQ_PHYRDY_CHG ?
-                              "PHY RDY changed" : "device exchanged");
-               freeze = 1;
-       }
-
-       if (irq_stat & PORT_IRQ_UNK_FIS) {
-               ehi->err_mask |= AC_ERR_HSM;
-               ehi->action |= ATA_EH_SOFTRESET;
-               ata_ehi_push_desc(ehi , ", unknown FIS");
-               freeze = 1;
-       }
-
-       /* deal with command error */
-       if (irq_stat & PORT_IRQ_ERROR) {
-               struct sil24_cerr_info *ci = NULL;
-               unsigned int err_mask = 0, action = 0;
-               struct ata_queued_cmd *qc;
-               u32 cerr;
-
-               /* analyze CMD_ERR */
-               cerr = readl(port + PORT_CMD_ERR);
-               if (cerr < ARRAY_SIZE(sil24_cerr_db))
-                       ci = &sil24_cerr_db[cerr];
-
-               if (ci && ci->desc) {
-                       err_mask |= ci->err_mask;
-                       action |= ci->action;
-                       ata_ehi_push_desc(ehi, ", %s", ci->desc);
-               } else {
-                       err_mask |= AC_ERR_OTHER;
-                       action |= ATA_EH_SOFTRESET;
-                       ata_ehi_push_desc(ehi, ", unknown command error %d",
-                                         cerr);
-               }
-
-               /* record error info */
-               qc = ata_qc_from_tag(ap, ap->active_tag);
-               if (qc) {
-                       sil24_update_tf(ap);
-                       qc->err_mask |= err_mask;
-               } else
-                       ehi->err_mask |= err_mask;
-
-               ehi->action |= action;
-       }
-
-       /* freeze or abort */
-       if (freeze)
-               ata_port_freeze(ap);
-       else
-               ata_port_abort(ap);
-}
-
-static void sil24_finish_qc(struct ata_queued_cmd *qc)
-{
-       if (qc->flags & ATA_QCFLAG_RESULT_TF)
-               sil24_update_tf(qc->ap);
-}
-
-static inline void sil24_host_intr(struct ata_port *ap)
-{
-       void __iomem *port = (void __iomem *)ap->ioaddr.cmd_addr;
-       u32 slot_stat, qc_active;
-       int rc;
-
-       slot_stat = readl(port + PORT_SLOT_STAT);
-
-       if (unlikely(slot_stat & HOST_SSTAT_ATTN)) {
-               sil24_error_intr(ap);
-               return;
-       }
-
-       if (ap->flags & SIL24_FLAG_PCIX_IRQ_WOC)
-               writel(PORT_IRQ_COMPLETE, port + PORT_IRQ_STAT);
-
-       qc_active = slot_stat & ~HOST_SSTAT_ATTN;
-       rc = ata_qc_complete_multiple(ap, qc_active, sil24_finish_qc);
-       if (rc > 0)
-               return;
-       if (rc < 0) {
-               struct ata_eh_info *ehi = &ap->eh_info;
-               ehi->err_mask |= AC_ERR_HSM;
-               ehi->action |= ATA_EH_SOFTRESET;
-               ata_port_freeze(ap);
-               return;
-       }
-
-       if (ata_ratelimit())
-               ata_port_printk(ap, KERN_INFO, "spurious interrupt "
-                       "(slot_stat 0x%x active_tag %d sactive 0x%x)\n",
-                       slot_stat, ap->active_tag, ap->sactive);
-}
-
-static irqreturn_t sil24_interrupt(int irq, void *dev_instance, struct pt_regs *regs)
-{
-       struct ata_host_set *host_set = dev_instance;
-       struct sil24_host_priv *hpriv = host_set->private_data;
-       unsigned handled = 0;
-       u32 status;
-       int i;
-
-       status = readl(hpriv->host_base + HOST_IRQ_STAT);
-
-       if (status == 0xffffffff) {
-               printk(KERN_ERR DRV_NAME ": IRQ status == 0xffffffff, "
-                      "PCI fault or device removal?\n");
-               goto out;
-       }
-
-       if (!(status & IRQ_STAT_4PORTS))
-               goto out;
-
-       spin_lock(&host_set->lock);
-
-       for (i = 0; i < host_set->n_ports; i++)
-               if (status & (1 << i)) {
-                       struct ata_port *ap = host_set->ports[i];
-                       if (ap && !(ap->flags & ATA_FLAG_DISABLED)) {
-                               sil24_host_intr(host_set->ports[i]);
-                               handled++;
-                       } else
-                               printk(KERN_ERR DRV_NAME
-                                      ": interrupt from disabled port %d\n", i);
-               }
-
-       spin_unlock(&host_set->lock);
- out:
-       return IRQ_RETVAL(handled);
-}
-
-static void sil24_error_handler(struct ata_port *ap)
-{
-       struct ata_eh_context *ehc = &ap->eh_context;
-
-       if (sil24_init_port(ap)) {
-               ata_eh_freeze_port(ap);
-               ehc->i.action |= ATA_EH_HARDRESET;
-       }
-
-       /* perform recovery */
-       ata_do_eh(ap, ata_std_prereset, sil24_softreset, sil24_hardreset,
-                 ata_std_postreset);
-}
-
-static void sil24_post_internal_cmd(struct ata_queued_cmd *qc)
-{
-       struct ata_port *ap = qc->ap;
-
-       if (qc->flags & ATA_QCFLAG_FAILED)
-               qc->err_mask |= AC_ERR_OTHER;
-
-       /* make DMA engine forget about the failed command */
-       if (qc->err_mask)
-               sil24_init_port(ap);
-}
-
-static inline void sil24_cblk_free(struct sil24_port_priv *pp, struct device *dev)
-{
-       const size_t cb_size = sizeof(*pp->cmd_block) * SIL24_MAX_CMDS;
-
-       dma_free_coherent(dev, cb_size, pp->cmd_block, pp->cmd_block_dma);
-}
-
-static int sil24_port_start(struct ata_port *ap)
-{
-       struct device *dev = ap->host_set->dev;
-       struct sil24_port_priv *pp;
-       union sil24_cmd_block *cb;
-       size_t cb_size = sizeof(*cb) * SIL24_MAX_CMDS;
-       dma_addr_t cb_dma;
-       int rc = -ENOMEM;
-
-       pp = kzalloc(sizeof(*pp), GFP_KERNEL);
-       if (!pp)
-               goto err_out;
-
-       pp->tf.command = ATA_DRDY;
-
-       cb = dma_alloc_coherent(dev, cb_size, &cb_dma, GFP_KERNEL);
-       if (!cb)
-               goto err_out_pp;
-       memset(cb, 0, cb_size);
-
-       rc = ata_pad_alloc(ap, dev);
-       if (rc)
-               goto err_out_pad;
-
-       pp->cmd_block = cb;
-       pp->cmd_block_dma = cb_dma;
-
-       ap->private_data = pp;
-
-       return 0;
-
-err_out_pad:
-       sil24_cblk_free(pp, dev);
-err_out_pp:
-       kfree(pp);
-err_out:
-       return rc;
-}
-
-static void sil24_port_stop(struct ata_port *ap)
-{
-       struct device *dev = ap->host_set->dev;
-       struct sil24_port_priv *pp = ap->private_data;
-
-       sil24_cblk_free(pp, dev);
-       ata_pad_free(ap, dev);
-       kfree(pp);
-}
-
-static void sil24_host_stop(struct ata_host_set *host_set)
-{
-       struct sil24_host_priv *hpriv = host_set->private_data;
-       struct pci_dev *pdev = to_pci_dev(host_set->dev);
-
-       pci_iounmap(pdev, hpriv->host_base);
-       pci_iounmap(pdev, hpriv->port_base);
-       kfree(hpriv);
-}
-
-static void sil24_init_controller(struct pci_dev *pdev, int n_ports,
-                                 unsigned long host_flags,
-                                 void __iomem *host_base,
-                                 void __iomem *port_base)
-{
-       u32 tmp;
-       int i;
-
-       /* GPIO off */
-       writel(0, host_base + HOST_FLASH_CMD);
-
-       /* clear global reset & mask interrupts during initialization */
-       writel(0, host_base + HOST_CTRL);
-
-       /* init ports */
-       for (i = 0; i < n_ports; i++) {
-               void __iomem *port = port_base + i * PORT_REGS_SIZE;
-
-               /* Initial PHY setting */
-               writel(0x20c, port + PORT_PHY_CFG);
-
-               /* Clear port RST */
-               tmp = readl(port + PORT_CTRL_STAT);
-               if (tmp & PORT_CS_PORT_RST) {
-                       writel(PORT_CS_PORT_RST, port + PORT_CTRL_CLR);
-                       tmp = ata_wait_register(port + PORT_CTRL_STAT,
-                                               PORT_CS_PORT_RST,
-                                               PORT_CS_PORT_RST, 10, 100);
-                       if (tmp & PORT_CS_PORT_RST)
-                               dev_printk(KERN_ERR, &pdev->dev,
-                                          "failed to clear port RST\n");
-               }
-
-               /* Configure IRQ WoC */
-               if (host_flags & SIL24_FLAG_PCIX_IRQ_WOC)
-                       writel(PORT_CS_IRQ_WOC, port + PORT_CTRL_STAT);
-               else
-                       writel(PORT_CS_IRQ_WOC, port + PORT_CTRL_CLR);
-
-               /* Zero error counters. */
-               writel(0x8000, port + PORT_DECODE_ERR_THRESH);
-               writel(0x8000, port + PORT_CRC_ERR_THRESH);
-               writel(0x8000, port + PORT_HSHK_ERR_THRESH);
-               writel(0x0000, port + PORT_DECODE_ERR_CNT);
-               writel(0x0000, port + PORT_CRC_ERR_CNT);
-               writel(0x0000, port + PORT_HSHK_ERR_CNT);
-
-               /* Always use 64bit activation */
-               writel(PORT_CS_32BIT_ACTV, port + PORT_CTRL_CLR);
-
-               /* Clear port multiplier enable and resume bits */
-               writel(PORT_CS_PM_EN | PORT_CS_RESUME, port + PORT_CTRL_CLR);
-       }
-
-       /* Turn on interrupts */
-       writel(IRQ_STAT_4PORTS, host_base + HOST_CTRL);
-}
-
-static int sil24_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
-{
-       static int printed_version = 0;
-       unsigned int board_id = (unsigned int)ent->driver_data;
-       struct ata_port_info *pinfo = &sil24_port_info[board_id];
-       struct ata_probe_ent *probe_ent = NULL;
-       struct sil24_host_priv *hpriv = NULL;
-       void __iomem *host_base = NULL;
-       void __iomem *port_base = NULL;
-       int i, rc;
-       u32 tmp;
-
-       if (!printed_version++)
-               dev_printk(KERN_DEBUG, &pdev->dev, "version " DRV_VERSION "\n");
-
-       rc = pci_enable_device(pdev);
-       if (rc)
-               return rc;
-
-       rc = pci_request_regions(pdev, DRV_NAME);
-       if (rc)
-               goto out_disable;
-
-       rc = -ENOMEM;
-       /* map mmio registers */
-       host_base = pci_iomap(pdev, 0, 0);
-       if (!host_base)
-               goto out_free;
-       port_base = pci_iomap(pdev, 2, 0);
-       if (!port_base)
-               goto out_free;
-
-       /* allocate & init probe_ent and hpriv */
-       probe_ent = kzalloc(sizeof(*probe_ent), GFP_KERNEL);
-       if (!probe_ent)
-               goto out_free;
-
-       hpriv = kzalloc(sizeof(*hpriv), GFP_KERNEL);
-       if (!hpriv)
-               goto out_free;
-
-       probe_ent->dev = pci_dev_to_dev(pdev);
-       INIT_LIST_HEAD(&probe_ent->node);
-
-       probe_ent->sht          = pinfo->sht;
-       probe_ent->host_flags   = pinfo->host_flags;
-       probe_ent->pio_mask     = pinfo->pio_mask;
-       probe_ent->mwdma_mask   = pinfo->mwdma_mask;
-       probe_ent->udma_mask    = pinfo->udma_mask;
-       probe_ent->port_ops     = pinfo->port_ops;
-       probe_ent->n_ports      = SIL24_FLAG2NPORTS(pinfo->host_flags);
-
-       probe_ent->irq = pdev->irq;
-       probe_ent->irq_flags = IRQF_SHARED;
-       probe_ent->private_data = hpriv;
-
-       hpriv->host_base = host_base;
-       hpriv->port_base = port_base;
-
-       /*
-        * Configure the device
-        */
-       if (!pci_set_dma_mask(pdev, DMA_64BIT_MASK)) {
-               rc = pci_set_consistent_dma_mask(pdev, DMA_64BIT_MASK);
-               if (rc) {
-                       rc = pci_set_consistent_dma_mask(pdev, DMA_32BIT_MASK);
-                       if (rc) {
-                               dev_printk(KERN_ERR, &pdev->dev,
-                                          "64-bit DMA enable failed\n");
-                               goto out_free;
-                       }
-               }
-       } else {
-               rc = pci_set_dma_mask(pdev, DMA_32BIT_MASK);
-               if (rc) {
-                       dev_printk(KERN_ERR, &pdev->dev,
-                                  "32-bit DMA enable failed\n");
-                       goto out_free;
-               }
-               rc = pci_set_consistent_dma_mask(pdev, DMA_32BIT_MASK);
-               if (rc) {
-                       dev_printk(KERN_ERR, &pdev->dev,
-                                  "32-bit consistent DMA enable failed\n");
-                       goto out_free;
-               }
-       }
-
-       /* Apply workaround for completion IRQ loss on PCI-X errata */
-       if (probe_ent->host_flags & SIL24_FLAG_PCIX_IRQ_WOC) {
-               tmp = readl(host_base + HOST_CTRL);
-               if (tmp & (HOST_CTRL_TRDY | HOST_CTRL_STOP | HOST_CTRL_DEVSEL))
-                       dev_printk(KERN_INFO, &pdev->dev,
-                                  "Applying completion IRQ loss on PCI-X "
-                                  "errata fix\n");
-               else
-                       probe_ent->host_flags &= ~SIL24_FLAG_PCIX_IRQ_WOC;
-       }
-
-       for (i = 0; i < probe_ent->n_ports; i++) {
-               unsigned long portu =
-                       (unsigned long)port_base + i * PORT_REGS_SIZE;
-
-               probe_ent->port[i].cmd_addr = portu;
-               probe_ent->port[i].scr_addr = portu + PORT_SCONTROL;
-
-               ata_std_ports(&probe_ent->port[i]);
-       }
-
-       sil24_init_controller(pdev, probe_ent->n_ports, probe_ent->host_flags,
-                             host_base, port_base);
-
-       pci_set_master(pdev);
-
-       /* FIXME: check ata_device_add return value */
-       ata_device_add(probe_ent);
-
-       kfree(probe_ent);
-       return 0;
-
- out_free:
-       if (host_base)
-               pci_iounmap(pdev, host_base);
-       if (port_base)
-               pci_iounmap(pdev, port_base);
-       kfree(probe_ent);
-       kfree(hpriv);
-       pci_release_regions(pdev);
- out_disable:
-       pci_disable_device(pdev);
-       return rc;
-}
-
-static int sil24_pci_device_resume(struct pci_dev *pdev)
-{
-       struct ata_host_set *host_set = dev_get_drvdata(&pdev->dev);
-       struct sil24_host_priv *hpriv = host_set->private_data;
-
-       ata_pci_device_do_resume(pdev);
-
-       if (pdev->dev.power.power_state.event == PM_EVENT_SUSPEND)
-               writel(HOST_CTRL_GLOBAL_RST, hpriv->host_base + HOST_CTRL);
-
-       sil24_init_controller(pdev, host_set->n_ports,
-                             host_set->ports[0]->flags,
-                             hpriv->host_base, hpriv->port_base);
-
-       ata_host_set_resume(host_set);
-
-       return 0;
-}
-
-static int __init sil24_init(void)
-{
-       return pci_register_driver(&sil24_pci_driver);
-}
-
-static void __exit sil24_exit(void)
-{
-       pci_unregister_driver(&sil24_pci_driver);
-}
-
-MODULE_AUTHOR("Tejun Heo");
-MODULE_DESCRIPTION("Silicon Image 3124/3132 SATA low-level driver");
-MODULE_LICENSE("GPL");
-MODULE_DEVICE_TABLE(pci, sil24_pci_tbl);
-
-module_init(sil24_init);
-module_exit(sil24_exit);
diff --git a/drivers/scsi/sata_sis.c b/drivers/scsi/sata_sis.c
deleted file mode 100644 (file)
index ac24f66..0000000
+++ /dev/null
@@ -1,347 +0,0 @@
-/*
- *  sata_sis.c - Silicon Integrated Systems SATA
- *
- *  Maintained by:  Uwe Koziolek
- *                 Please ALWAYS copy linux-ide@vger.kernel.org
- *                 on emails.
- *
- *  Copyright 2004 Uwe Koziolek
- *
- *
- *  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 under NDA.
- *
- */
-
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/pci.h>
-#include <linux/init.h>
-#include <linux/blkdev.h>
-#include <linux/delay.h>
-#include <linux/interrupt.h>
-#include <linux/device.h>
-#include <scsi/scsi_host.h>
-#include <linux/libata.h>
-
-#define DRV_NAME       "sata_sis"
-#define DRV_VERSION    "0.6"
-
-enum {
-       sis_180                 = 0,
-       SIS_SCR_PCI_BAR         = 5,
-
-       /* PCI configuration registers */
-       SIS_GENCTL              = 0x54, /* IDE General Control register */
-       SIS_SCR_BASE            = 0xc0, /* sata0 phy SCR registers */
-       SIS180_SATA1_OFS        = 0x10, /* offset from sata0->sata1 phy regs */
-       SIS182_SATA1_OFS        = 0x20, /* offset from sata0->sata1 phy regs */
-       SIS_PMR                 = 0x90, /* port mapping register */
-       SIS_PMR_COMBINED        = 0x30,
-
-       /* random bits */
-       SIS_FLAG_CFGSCR         = (1 << 30), /* host flag: SCRs via PCI cfg */
-
-       GENCTL_IOMAPPED_SCR     = (1 << 26), /* if set, SCRs are in IO space */
-};
-
-static int sis_init_one (struct pci_dev *pdev, const struct pci_device_id *ent);
-static u32 sis_scr_read (struct ata_port *ap, unsigned int sc_reg);
-static void sis_scr_write (struct ata_port *ap, unsigned int sc_reg, u32 val);
-
-static const struct pci_device_id sis_pci_tbl[] = {
-       { PCI_VENDOR_ID_SI, 0x180, PCI_ANY_ID, PCI_ANY_ID, 0, 0, sis_180 },
-       { PCI_VENDOR_ID_SI, 0x181, PCI_ANY_ID, PCI_ANY_ID, 0, 0, sis_180 },
-       { PCI_VENDOR_ID_SI, 0x182, PCI_ANY_ID, PCI_ANY_ID, 0, 0, sis_180 },
-       { }     /* terminate list */
-};
-
-
-static struct pci_driver sis_pci_driver = {
-       .name                   = DRV_NAME,
-       .id_table               = sis_pci_tbl,
-       .probe                  = sis_init_one,
-       .remove                 = ata_pci_remove_one,
-};
-
-static struct scsi_host_template sis_sht = {
-       .module                 = THIS_MODULE,
-       .name                   = DRV_NAME,
-       .ioctl                  = ata_scsi_ioctl,
-       .queuecommand           = ata_scsi_queuecmd,
-       .can_queue              = ATA_DEF_QUEUE,
-       .this_id                = ATA_SHT_THIS_ID,
-       .sg_tablesize           = ATA_MAX_PRD,
-       .cmd_per_lun            = ATA_SHT_CMD_PER_LUN,
-       .emulated               = ATA_SHT_EMULATED,
-       .use_clustering         = ATA_SHT_USE_CLUSTERING,
-       .proc_name              = DRV_NAME,
-       .dma_boundary           = ATA_DMA_BOUNDARY,
-       .slave_configure        = ata_scsi_slave_config,
-       .slave_destroy          = ata_scsi_slave_destroy,
-       .bios_param             = ata_std_bios_param,
-};
-
-static const struct ata_port_operations sis_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,
-       .bmdma_setup            = ata_bmdma_setup,
-       .bmdma_start            = ata_bmdma_start,
-       .bmdma_stop             = ata_bmdma_stop,
-       .bmdma_status           = ata_bmdma_status,
-       .qc_prep                = ata_qc_prep,
-       .qc_issue               = ata_qc_issue_prot,
-       .data_xfer              = ata_pio_data_xfer,
-       .freeze                 = ata_bmdma_freeze,
-       .thaw                   = ata_bmdma_thaw,
-       .error_handler          = ata_bmdma_error_handler,
-       .post_internal_cmd      = ata_bmdma_post_internal_cmd,
-       .irq_handler            = ata_interrupt,
-       .irq_clear              = ata_bmdma_irq_clear,
-       .scr_read               = sis_scr_read,
-       .scr_write              = sis_scr_write,
-       .port_start             = ata_port_start,
-       .port_stop              = ata_port_stop,
-       .host_stop              = ata_host_stop,
-};
-
-static struct ata_port_info sis_port_info = {
-       .sht            = &sis_sht,
-       .host_flags     = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY,
-       .pio_mask       = 0x1f,
-       .mwdma_mask     = 0x7,
-       .udma_mask      = 0x7f,
-       .port_ops       = &sis_ops,
-};
-
-
-MODULE_AUTHOR("Uwe Koziolek");
-MODULE_DESCRIPTION("low-level driver for Silicon Integratad Systems SATA controller");
-MODULE_LICENSE("GPL");
-MODULE_DEVICE_TABLE(pci, sis_pci_tbl);
-MODULE_VERSION(DRV_VERSION);
-
-static unsigned int get_scr_cfg_addr(unsigned int port_no, unsigned int sc_reg, int device)
-{
-       unsigned int addr = SIS_SCR_BASE + (4 * sc_reg);
-
-       if (port_no)  {
-               if (device == 0x182)
-                       addr += SIS182_SATA1_OFS;
-               else
-                       addr += SIS180_SATA1_OFS;
-       }
-
-       return addr;
-}
-
-static u32 sis_scr_cfg_read (struct ata_port *ap, unsigned int sc_reg)
-{
-       struct pci_dev *pdev = to_pci_dev(ap->host_set->dev);
-       unsigned int cfg_addr = get_scr_cfg_addr(ap->port_no, sc_reg, pdev->device);
-       u32 val, val2 = 0;
-       u8 pmr;
-
-       if (sc_reg == SCR_ERROR) /* doesn't exist in PCI cfg space */
-               return 0xffffffff;
-
-       pci_read_config_byte(pdev, SIS_PMR, &pmr);
-
-       pci_read_config_dword(pdev, cfg_addr, &val);
-
-       if ((pdev->device == 0x182) || (pmr & SIS_PMR_COMBINED))
-               pci_read_config_dword(pdev, cfg_addr+0x10, &val2);
-
-       return val|val2;
-}
-
-static void sis_scr_cfg_write (struct ata_port *ap, unsigned int scr, u32 val)
-{
-       struct pci_dev *pdev = to_pci_dev(ap->host_set->dev);
-       unsigned int cfg_addr = get_scr_cfg_addr(ap->port_no, scr, pdev->device);
-       u8 pmr;
-
-       if (scr == SCR_ERROR) /* doesn't exist in PCI cfg space */
-               return;
-
-       pci_read_config_byte(pdev, SIS_PMR, &pmr);
-
-       pci_write_config_dword(pdev, cfg_addr, val);
-
-       if ((pdev->device == 0x182) || (pmr & SIS_PMR_COMBINED))
-               pci_write_config_dword(pdev, cfg_addr+0x10, val);
-}
-
-static u32 sis_scr_read (struct ata_port *ap, unsigned int sc_reg)
-{
-       struct pci_dev *pdev = to_pci_dev(ap->host_set->dev);
-       u32 val, val2 = 0;
-       u8 pmr;
-
-       if (sc_reg > SCR_CONTROL)
-               return 0xffffffffU;
-
-       if (ap->flags & SIS_FLAG_CFGSCR)
-               return sis_scr_cfg_read(ap, sc_reg);
-
-       pci_read_config_byte(pdev, SIS_PMR, &pmr);
-
-       val = inl(ap->ioaddr.scr_addr + (sc_reg * 4));
-
-       if ((pdev->device == 0x182) || (pmr & SIS_PMR_COMBINED))
-               val2 = inl(ap->ioaddr.scr_addr + (sc_reg * 4) + 0x10);
-
-       return val | val2;
-}
-
-static void sis_scr_write (struct ata_port *ap, unsigned int sc_reg, u32 val)
-{
-       struct pci_dev *pdev = to_pci_dev(ap->host_set->dev);
-       u8 pmr;
-
-       if (sc_reg > SCR_CONTROL)
-               return;
-
-       pci_read_config_byte(pdev, SIS_PMR, &pmr);
-
-       if (ap->flags & SIS_FLAG_CFGSCR)
-               sis_scr_cfg_write(ap, sc_reg, val);
-       else {
-               outl(val, ap->ioaddr.scr_addr + (sc_reg * 4));
-               if ((pdev->device == 0x182) || (pmr & SIS_PMR_COMBINED))
-                       outl(val, ap->ioaddr.scr_addr + (sc_reg * 4)+0x10);
-       }
-}
-
-static int sis_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
-{
-       static int printed_version;
-       struct ata_probe_ent *probe_ent = NULL;
-       int rc;
-       u32 genctl;
-       struct ata_port_info *ppi;
-       int pci_dev_busy = 0;
-       u8 pmr;
-       u8 port2_start;
-
-       if (!printed_version++)
-               dev_printk(KERN_INFO, &pdev->dev, "version " DRV_VERSION "\n");
-
-       rc = pci_enable_device(pdev);
-       if (rc)
-               return rc;
-
-       rc = pci_request_regions(pdev, DRV_NAME);
-       if (rc) {
-               pci_dev_busy = 1;
-               goto err_out;
-       }
-
-       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;
-
-       ppi = &sis_port_info;
-       probe_ent = ata_pci_init_native_mode(pdev, &ppi, ATA_PORT_PRIMARY | ATA_PORT_SECONDARY);
-       if (!probe_ent) {
-               rc = -ENOMEM;
-               goto err_out_regions;
-       }
-
-       /* check and see if the SCRs are in IO space or PCI cfg space */
-       pci_read_config_dword(pdev, SIS_GENCTL, &genctl);
-       if ((genctl & GENCTL_IOMAPPED_SCR) == 0)
-               probe_ent->host_flags |= SIS_FLAG_CFGSCR;
-
-       /* if hardware thinks SCRs are in IO space, but there are
-        * no IO resources assigned, change to PCI cfg space.
-        */
-       if ((!(probe_ent->host_flags & SIS_FLAG_CFGSCR)) &&
-           ((pci_resource_start(pdev, SIS_SCR_PCI_BAR) == 0) ||
-            (pci_resource_len(pdev, SIS_SCR_PCI_BAR) < 128))) {
-               genctl &= ~GENCTL_IOMAPPED_SCR;
-               pci_write_config_dword(pdev, SIS_GENCTL, genctl);
-               probe_ent->host_flags |= SIS_FLAG_CFGSCR;
-       }
-
-       pci_read_config_byte(pdev, SIS_PMR, &pmr);
-       if (ent->device != 0x182) {
-               if ((pmr & SIS_PMR_COMBINED) == 0) {
-                       dev_printk(KERN_INFO, &pdev->dev,
-                                  "Detected SiS 180/181 chipset in SATA mode\n");
-                       port2_start = 64;
-               }
-               else {
-                       dev_printk(KERN_INFO, &pdev->dev,
-                                  "Detected SiS 180/181 chipset in combined mode\n");
-                       port2_start=0;
-               }
-       }
-       else {
-               dev_printk(KERN_INFO, &pdev->dev, "Detected SiS 182 chipset\n");
-               port2_start = 0x20;
-       }
-
-       if (!(probe_ent->host_flags & SIS_FLAG_CFGSCR)) {
-               probe_ent->port[0].scr_addr =
-                       pci_resource_start(pdev, SIS_SCR_PCI_BAR);
-               probe_ent->port[1].scr_addr =
-                       pci_resource_start(pdev, SIS_SCR_PCI_BAR) + port2_start;
-       }
-
-       pci_set_master(pdev);
-       pci_intx(pdev, 1);
-
-       /* FIXME: check ata_device_add return value */
-       ata_device_add(probe_ent);
-       kfree(probe_ent);
-
-       return 0;
-
-err_out_regions:
-       pci_release_regions(pdev);
-
-err_out:
-       if (!pci_dev_busy)
-               pci_disable_device(pdev);
-       return rc;
-
-}
-
-static int __init sis_init(void)
-{
-       return pci_register_driver(&sis_pci_driver);
-}
-
-static void __exit sis_exit(void)
-{
-       pci_unregister_driver(&sis_pci_driver);
-}
-
-module_init(sis_init);
-module_exit(sis_exit);
-
diff --git a/drivers/scsi/sata_svw.c b/drivers/scsi/sata_svw.c
deleted file mode 100644 (file)
index baf259a..0000000
+++ /dev/null
@@ -1,508 +0,0 @@
-/*
- *  sata_svw.c - ServerWorks / Apple K2 SATA
- *
- *  Maintained by: Benjamin Herrenschmidt <benh@kernel.crashing.org> and
- *                Jeff Garzik <jgarzik@pobox.com>
- *                 Please ALWAYS copy linux-ide@vger.kernel.org
- *                 on emails.
- *
- *  Copyright 2003 Benjamin Herrenschmidt <benh@kernel.crashing.org>
- *
- *  Bits from Jeff Garzik, Copyright RedHat, Inc.
- *
- *  This driver probably works with non-Apple versions of the
- *  Broadcom chipset...
- *
- *
- *  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 under NDA.
- *
- */
-
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/pci.h>
-#include <linux/init.h>
-#include <linux/blkdev.h>
-#include <linux/delay.h>
-#include <linux/interrupt.h>
-#include <linux/device.h>
-#include <scsi/scsi_host.h>
-#include <linux/libata.h>
-
-#ifdef CONFIG_PPC_OF
-#include <asm/prom.h>
-#include <asm/pci-bridge.h>
-#endif /* CONFIG_PPC_OF */
-
-#define DRV_NAME       "sata_svw"
-#define DRV_VERSION    "2.0"
-
-enum {
-       /* Taskfile registers offsets */
-       K2_SATA_TF_CMD_OFFSET           = 0x00,
-       K2_SATA_TF_DATA_OFFSET          = 0x00,
-       K2_SATA_TF_ERROR_OFFSET         = 0x04,
-       K2_SATA_TF_NSECT_OFFSET         = 0x08,
-       K2_SATA_TF_LBAL_OFFSET          = 0x0c,
-       K2_SATA_TF_LBAM_OFFSET          = 0x10,
-       K2_SATA_TF_LBAH_OFFSET          = 0x14,
-       K2_SATA_TF_DEVICE_OFFSET        = 0x18,
-       K2_SATA_TF_CMDSTAT_OFFSET       = 0x1c,
-       K2_SATA_TF_CTL_OFFSET           = 0x20,
-
-       /* DMA base */
-       K2_SATA_DMA_CMD_OFFSET          = 0x30,
-
-       /* SCRs base */
-       K2_SATA_SCR_STATUS_OFFSET       = 0x40,
-       K2_SATA_SCR_ERROR_OFFSET        = 0x44,
-       K2_SATA_SCR_CONTROL_OFFSET      = 0x48,
-
-       /* Others */
-       K2_SATA_SICR1_OFFSET            = 0x80,
-       K2_SATA_SICR2_OFFSET            = 0x84,
-       K2_SATA_SIM_OFFSET              = 0x88,
-
-       /* Port stride */
-       K2_SATA_PORT_OFFSET             = 0x100,
-};
-
-static u8 k2_stat_check_status(struct ata_port *ap);
-
-
-static u32 k2_sata_scr_read (struct ata_port *ap, unsigned int sc_reg)
-{
-       if (sc_reg > SCR_CONTROL)
-               return 0xffffffffU;
-       return readl((void *) ap->ioaddr.scr_addr + (sc_reg * 4));
-}
-
-
-static void k2_sata_scr_write (struct ata_port *ap, unsigned int sc_reg,
-                              u32 val)
-{
-       if (sc_reg > SCR_CONTROL)
-               return;
-       writel(val, (void *) ap->ioaddr.scr_addr + (sc_reg * 4));
-}
-
-
-static void k2_sata_tf_load(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, ioaddr->ctl_addr);
-               ap->last_ctl = tf->ctl;
-               ata_wait_idle(ap);
-       }
-       if (is_addr && (tf->flags & ATA_TFLAG_LBA48)) {
-               writew(tf->feature | (((u16)tf->hob_feature) << 8), ioaddr->feature_addr);
-               writew(tf->nsect | (((u16)tf->hob_nsect) << 8), ioaddr->nsect_addr);
-               writew(tf->lbal | (((u16)tf->hob_lbal) << 8), ioaddr->lbal_addr);
-               writew(tf->lbam | (((u16)tf->hob_lbam) << 8), ioaddr->lbam_addr);
-               writew(tf->lbah | (((u16)tf->hob_lbah) << 8), ioaddr->lbah_addr);
-       } else if (is_addr) {
-               writew(tf->feature, ioaddr->feature_addr);
-               writew(tf->nsect, ioaddr->nsect_addr);
-               writew(tf->lbal, ioaddr->lbal_addr);
-               writew(tf->lbam, ioaddr->lbam_addr);
-               writew(tf->lbah, ioaddr->lbah_addr);
-       }
-
-       if (tf->flags & ATA_TFLAG_DEVICE)
-               writeb(tf->device, ioaddr->device_addr);
-
-       ata_wait_idle(ap);
-}
-
-
-static void k2_sata_tf_read(struct ata_port *ap, struct ata_taskfile *tf)
-{
-       struct ata_ioports *ioaddr = &ap->ioaddr;
-       u16 nsect, lbal, lbam, lbah, feature;
-
-       tf->command = k2_stat_check_status(ap);
-       tf->device = readw(ioaddr->device_addr);
-       feature = readw(ioaddr->error_addr);
-       nsect = readw(ioaddr->nsect_addr);
-       lbal = readw(ioaddr->lbal_addr);
-       lbam = readw(ioaddr->lbam_addr);
-       lbah = readw(ioaddr->lbah_addr);
-
-       tf->feature = feature;
-       tf->nsect = nsect;
-       tf->lbal = lbal;
-       tf->lbam = lbam;
-       tf->lbah = lbah;
-
-       if (tf->flags & ATA_TFLAG_LBA48) {
-               tf->hob_feature = feature >> 8;
-               tf->hob_nsect = nsect >> 8;
-               tf->hob_lbal = lbal >> 8;
-               tf->hob_lbam = lbam >> 8;
-               tf->hob_lbah = lbah >> 8;
-        }
-}
-
-/**
- *     k2_bmdma_setup_mmio - Set up PCI IDE BMDMA transaction (MMIO)
- *     @qc: Info associated with this ATA transaction.
- *
- *     LOCKING:
- *     spin_lock_irqsave(host_set lock)
- */
-
-static void k2_bmdma_setup_mmio (struct ata_queued_cmd *qc)
-{
-       struct ata_port *ap = qc->ap;
-       unsigned int rw = (qc->tf.flags & ATA_TFLAG_WRITE);
-       u8 dmactl;
-       void *mmio = (void *) ap->ioaddr.bmdma_addr;
-       /* load PRD table addr. */
-       mb();   /* make sure PRD table writes are visible to controller */
-       writel(ap->prd_dma, mmio + ATA_DMA_TABLE_OFS);
-
-       /* specify data direction, triple-check start bit is clear */
-       dmactl = readb(mmio + ATA_DMA_CMD);
-       dmactl &= ~(ATA_DMA_WR | ATA_DMA_START);
-       if (!rw)
-               dmactl |= ATA_DMA_WR;
-       writeb(dmactl, mmio + ATA_DMA_CMD);
-
-       /* issue r/w command if this is not a ATA DMA command*/
-       if (qc->tf.protocol != ATA_PROT_DMA)
-               ap->ops->exec_command(ap, &qc->tf);
-}
-
-/**
- *     k2_bmdma_start_mmio - Start a PCI IDE BMDMA transaction (MMIO)
- *     @qc: Info associated with this ATA transaction.
- *
- *     LOCKING:
- *     spin_lock_irqsave(host_set lock)
- */
-
-static void k2_bmdma_start_mmio (struct ata_queued_cmd *qc)
-{
-       struct ata_port *ap = qc->ap;
-       void *mmio = (void *) ap->ioaddr.bmdma_addr;
-       u8 dmactl;
-
-       /* start host DMA transaction */
-       dmactl = readb(mmio + ATA_DMA_CMD);
-       writeb(dmactl | ATA_DMA_START, mmio + ATA_DMA_CMD);
-       /* There is a race condition in certain SATA controllers that can
-          be seen when the r/w command is given to the controller before the
-          host DMA is started. On a Read command, the controller would initiate
-          the command to the drive even before it sees the DMA start. When there
-          are very fast drives connected to the controller, or when the data request
-          hits in the drive cache, there is the possibility that the drive returns a part
-          or all of the requested data to the controller before the DMA start is issued.
-          In this case, the controller would become confused as to what to do with the data.
-          In the worst case when all the data is returned back to the controller, the
-          controller could hang. In other cases it could return partial data returning
-          in data corruption. This problem has been seen in PPC systems and can also appear
-          on an system with very fast disks, where the SATA controller is sitting behind a
-          number of bridges, and hence there is significant latency between the r/w command
-          and the start command. */
-       /* issue r/w command if the access is to ATA*/
-       if (qc->tf.protocol == ATA_PROT_DMA)
-               ap->ops->exec_command(ap, &qc->tf);
-}
-
-
-static u8 k2_stat_check_status(struct ata_port *ap)
-{
-               return readl((void *) ap->ioaddr.status_addr);
-}
-
-#ifdef CONFIG_PPC_OF
-/*
- * k2_sata_proc_info
- * inout : decides on the direction of the dataflow and the meaning of the
- *        variables
- * buffer: If inout==FALSE data is being written to it else read from it
- * *start: If inout==FALSE start of the valid data in the buffer
- * offset: If inout==FALSE offset from the beginning of the imaginary file
- *        from which we start writing into the buffer
- * length: If inout==FALSE max number of bytes to be written into the buffer
- *        else number of bytes in the buffer
- */
-static int k2_sata_proc_info(struct Scsi_Host *shost, char *page, char **start,
-                            off_t offset, int count, int inout)
-{
-       struct ata_port *ap;
-       struct device_node *np;
-       int len, index;
-
-       /* Find  the ata_port */
-       ap = ata_shost_to_port(shost);
-       if (ap == NULL)
-               return 0;
-
-       /* Find the OF node for the PCI device proper */
-       np = pci_device_to_OF_node(to_pci_dev(ap->host_set->dev));
-       if (np == NULL)
-               return 0;
-
-       /* Match it to a port node */
-       index = (ap == ap->host_set->ports[0]) ? 0 : 1;
-       for (np = np->child; np != NULL; np = np->sibling) {
-               u32 *reg = (u32 *)get_property(np, "reg", NULL);
-               if (!reg)
-                       continue;
-               if (index == *reg)
-                       break;
-       }
-       if (np == NULL)
-               return 0;
-
-       len = sprintf(page, "devspec: %s\n", np->full_name);
-
-       return len;
-}
-#endif /* CONFIG_PPC_OF */
-
-
-static struct scsi_host_template k2_sata_sht = {
-       .module                 = THIS_MODULE,
-       .name                   = DRV_NAME,
-       .ioctl                  = ata_scsi_ioctl,
-       .queuecommand           = ata_scsi_queuecmd,
-       .can_queue              = ATA_DEF_QUEUE,
-       .this_id                = ATA_SHT_THIS_ID,
-       .sg_tablesize           = LIBATA_MAX_PRD,
-       .cmd_per_lun            = ATA_SHT_CMD_PER_LUN,
-       .emulated               = ATA_SHT_EMULATED,
-       .use_clustering         = ATA_SHT_USE_CLUSTERING,
-       .proc_name              = DRV_NAME,
-       .dma_boundary           = ATA_DMA_BOUNDARY,
-       .slave_configure        = ata_scsi_slave_config,
-       .slave_destroy          = ata_scsi_slave_destroy,
-#ifdef CONFIG_PPC_OF
-       .proc_info              = k2_sata_proc_info,
-#endif
-       .bios_param             = ata_std_bios_param,
-};
-
-
-static const struct ata_port_operations k2_sata_ops = {
-       .port_disable           = ata_port_disable,
-       .tf_load                = k2_sata_tf_load,
-       .tf_read                = k2_sata_tf_read,
-       .check_status           = k2_stat_check_status,
-       .exec_command           = ata_exec_command,
-       .dev_select             = ata_std_dev_select,
-       .bmdma_setup            = k2_bmdma_setup_mmio,
-       .bmdma_start            = k2_bmdma_start_mmio,
-       .bmdma_stop             = ata_bmdma_stop,
-       .bmdma_status           = ata_bmdma_status,
-       .qc_prep                = ata_qc_prep,
-       .qc_issue               = ata_qc_issue_prot,
-       .data_xfer              = ata_mmio_data_xfer,
-       .freeze                 = ata_bmdma_freeze,
-       .thaw                   = ata_bmdma_thaw,
-       .error_handler          = ata_bmdma_error_handler,
-       .post_internal_cmd      = ata_bmdma_post_internal_cmd,
-       .irq_handler            = ata_interrupt,
-       .irq_clear              = ata_bmdma_irq_clear,
-       .scr_read               = k2_sata_scr_read,
-       .scr_write              = k2_sata_scr_write,
-       .port_start             = ata_port_start,
-       .port_stop              = ata_port_stop,
-       .host_stop              = ata_pci_host_stop,
-};
-
-static void k2_sata_setup_port(struct ata_ioports *port, unsigned long base)
-{
-       port->cmd_addr          = base + K2_SATA_TF_CMD_OFFSET;
-       port->data_addr         = base + K2_SATA_TF_DATA_OFFSET;
-       port->feature_addr      =
-       port->error_addr        = base + K2_SATA_TF_ERROR_OFFSET;
-       port->nsect_addr        = base + K2_SATA_TF_NSECT_OFFSET;
-       port->lbal_addr         = base + K2_SATA_TF_LBAL_OFFSET;
-       port->lbam_addr         = base + K2_SATA_TF_LBAM_OFFSET;
-       port->lbah_addr         = base + K2_SATA_TF_LBAH_OFFSET;
-       port->device_addr       = base + K2_SATA_TF_DEVICE_OFFSET;
-       port->command_addr      =
-       port->status_addr       = base + K2_SATA_TF_CMDSTAT_OFFSET;
-       port->altstatus_addr    =
-       port->ctl_addr          = base + K2_SATA_TF_CTL_OFFSET;
-       port->bmdma_addr        = base + K2_SATA_DMA_CMD_OFFSET;
-       port->scr_addr          = base + K2_SATA_SCR_STATUS_OFFSET;
-}
-
-
-static int k2_sata_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
-{
-       static int printed_version;
-       struct ata_probe_ent *probe_ent = NULL;
-       unsigned long base;
-       void __iomem *mmio_base;
-       int pci_dev_busy = 0;
-       int rc;
-       int i;
-
-       if (!printed_version++)
-               dev_printk(KERN_DEBUG, &pdev->dev, "version " DRV_VERSION "\n");
-
-       /*
-        * If this driver happens to only be useful on Apple's K2, then
-        * we should check that here as it has a normal Serverworks ID
-        */
-       rc = pci_enable_device(pdev);
-       if (rc)
-               return rc;
-       /*
-        * Check if we have resources mapped at all (second function may
-        * have been disabled by firmware)
-        */
-       if (pci_resource_len(pdev, 5) == 0)
-               return -ENODEV;
-
-       /* Request PCI regions */
-       rc = pci_request_regions(pdev, DRV_NAME);
-       if (rc) {
-               pci_dev_busy = 1;
-               goto err_out;
-       }
-
-       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;
-
-       probe_ent = kmalloc(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);
-
-       mmio_base = pci_iomap(pdev, 5, 0);
-       if (mmio_base == NULL) {
-               rc = -ENOMEM;
-               goto err_out_free_ent;
-       }
-       base = (unsigned long) mmio_base;
-
-       /* Clear a magic bit in SCR1 according to Darwin, those help
-        * some funky seagate drives (though so far, those were already
-        * set by the firmware on the machines I had access to)
-        */
-       writel(readl(mmio_base + K2_SATA_SICR1_OFFSET) & ~0x00040000,
-              mmio_base + K2_SATA_SICR1_OFFSET);
-
-       /* Clear SATA error & interrupts we don't use */
-       writel(0xffffffff, mmio_base + K2_SATA_SCR_ERROR_OFFSET);
-       writel(0x0, mmio_base + K2_SATA_SIM_OFFSET);
-
-       probe_ent->sht = &k2_sata_sht;
-       probe_ent->host_flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
-                               ATA_FLAG_MMIO;
-       probe_ent->port_ops = &k2_sata_ops;
-       probe_ent->n_ports = 4;
-       probe_ent->irq = pdev->irq;
-       probe_ent->irq_flags = IRQF_SHARED;
-       probe_ent->mmio_base = mmio_base;
-
-       /* We don't care much about the PIO/UDMA masks, but the core won't like us
-        * if we don't fill these
-        */
-       probe_ent->pio_mask = 0x1f;
-       probe_ent->mwdma_mask = 0x7;
-       probe_ent->udma_mask = 0x7f;
-
-       /* different controllers have different number of ports - currently 4 or 8 */
-       /* All ports are on the same function. Multi-function device is no
-        * longer available. This should not be seen in any system. */
-       for (i = 0; i < ent->driver_data; i++)
-               k2_sata_setup_port(&probe_ent->port[i], base + i * K2_SATA_PORT_OFFSET);
-
-       pci_set_master(pdev);
-
-       /* FIXME: check ata_device_add return value */
-       ata_device_add(probe_ent);
-       kfree(probe_ent);
-
-       return 0;
-
-err_out_free_ent:
-       kfree(probe_ent);
-err_out_regions:
-       pci_release_regions(pdev);
-err_out:
-       if (!pci_dev_busy)
-               pci_disable_device(pdev);
-       return rc;
-}
-
-/* 0x240 is device ID for Apple K2 device
- * 0x241 is device ID for Serverworks Frodo4
- * 0x242 is device ID for Serverworks Frodo8
- * 0x24a is device ID for BCM5785 (aka HT1000) HT southbridge integrated SATA
- * controller
- * */
-static const struct pci_device_id k2_sata_pci_tbl[] = {
-       { 0x1166, 0x0240, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 4 },
-       { 0x1166, 0x0241, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 4 },
-       { 0x1166, 0x0242, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 8 },
-       { 0x1166, 0x024a, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 4 },
-       { 0x1166, 0x024b, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 4 },
-       { }
-};
-
-
-static struct pci_driver k2_sata_pci_driver = {
-       .name                   = DRV_NAME,
-       .id_table               = k2_sata_pci_tbl,
-       .probe                  = k2_sata_init_one,
-       .remove                 = ata_pci_remove_one,
-};
-
-
-static int __init k2_sata_init(void)
-{
-       return pci_register_driver(&k2_sata_pci_driver);
-}
-
-
-static void __exit k2_sata_exit(void)
-{
-       pci_unregister_driver(&k2_sata_pci_driver);
-}
-
-
-MODULE_AUTHOR("Benjamin Herrenschmidt");
-MODULE_DESCRIPTION("low-level driver for K2 SATA controller");
-MODULE_LICENSE("GPL");
-MODULE_DEVICE_TABLE(pci, k2_sata_pci_tbl);
-MODULE_VERSION(DRV_VERSION);
-
-module_init(k2_sata_init);
-module_exit(k2_sata_exit);
diff --git a/drivers/scsi/sata_sx4.c b/drivers/scsi/sata_sx4.c
deleted file mode 100644 (file)
index 0da83cb..0000000
+++ /dev/null
@@ -1,1502 +0,0 @@
-/*
- *  sata_sx4.c - Promise SATA
- *
- *  Maintained by:  Jeff Garzik <jgarzik@pobox.com>
- *                 Please ALWAYS copy linux-ide@vger.kernel.org
- *                 on emails.
- *
- *  Copyright 2003-2004 Red Hat, Inc.
- *
- *
- *  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 under NDA.
- *
- */
-
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/pci.h>
-#include <linux/init.h>
-#include <linux/blkdev.h>
-#include <linux/delay.h>
-#include <linux/interrupt.h>
-#include <linux/sched.h>
-#include <linux/device.h>
-#include <scsi/scsi_host.h>
-#include <scsi/scsi_cmnd.h>
-#include <linux/libata.h>
-#include <asm/io.h>
-#include "sata_promise.h"
-
-#define DRV_NAME       "sata_sx4"
-#define DRV_VERSION    "0.9"
-
-
-enum {
-       PDC_PRD_TBL             = 0x44, /* Direct command DMA table addr */
-
-       PDC_PKT_SUBMIT          = 0x40, /* Command packet pointer addr */
-       PDC_HDMA_PKT_SUBMIT     = 0x100, /* Host DMA packet pointer addr */
-       PDC_INT_SEQMASK         = 0x40, /* Mask of asserted SEQ INTs */
-       PDC_HDMA_CTLSTAT        = 0x12C, /* Host DMA control / status */
-
-       PDC_20621_SEQCTL        = 0x400,
-       PDC_20621_SEQMASK       = 0x480,
-       PDC_20621_GENERAL_CTL   = 0x484,
-       PDC_20621_PAGE_SIZE     = (32 * 1024),
-
-       /* chosen, not constant, values; we design our own DIMM mem map */
-       PDC_20621_DIMM_WINDOW   = 0x0C, /* page# for 32K DIMM window */
-       PDC_20621_DIMM_BASE     = 0x00200000,
-       PDC_20621_DIMM_DATA     = (64 * 1024),
-       PDC_DIMM_DATA_STEP      = (256 * 1024),
-       PDC_DIMM_WINDOW_STEP    = (8 * 1024),
-       PDC_DIMM_HOST_PRD       = (6 * 1024),
-       PDC_DIMM_HOST_PKT       = (128 * 0),
-       PDC_DIMM_HPKT_PRD       = (128 * 1),
-       PDC_DIMM_ATA_PKT        = (128 * 2),
-       PDC_DIMM_APKT_PRD       = (128 * 3),
-       PDC_DIMM_HEADER_SZ      = PDC_DIMM_APKT_PRD + 128,
-       PDC_PAGE_WINDOW         = 0x40,
-       PDC_PAGE_DATA           = PDC_PAGE_WINDOW +
-                                 (PDC_20621_DIMM_DATA / PDC_20621_PAGE_SIZE),
-       PDC_PAGE_SET            = PDC_DIMM_DATA_STEP / PDC_20621_PAGE_SIZE,
-
-       PDC_CHIP0_OFS           = 0xC0000, /* offset of chip #0 */
-
-       PDC_20621_ERR_MASK      = (1<<19) | (1<<20) | (1<<21) | (1<<22) |
-                                 (1<<23),
-
-       board_20621             = 0,    /* FastTrak S150 SX4 */
-
-       PDC_RESET               = (1 << 11), /* HDMA reset */
-
-       PDC_MAX_HDMA            = 32,
-       PDC_HDMA_Q_MASK         = (PDC_MAX_HDMA - 1),
-
-       PDC_DIMM0_SPD_DEV_ADDRESS     = 0x50,
-       PDC_DIMM1_SPD_DEV_ADDRESS     = 0x51,
-       PDC_MAX_DIMM_MODULE           = 0x02,
-       PDC_I2C_CONTROL_OFFSET        = 0x48,
-       PDC_I2C_ADDR_DATA_OFFSET      = 0x4C,
-       PDC_DIMM0_CONTROL_OFFSET      = 0x80,
-       PDC_DIMM1_CONTROL_OFFSET      = 0x84,
-       PDC_SDRAM_CONTROL_OFFSET      = 0x88,
-       PDC_I2C_WRITE                 = 0x00000000,
-       PDC_I2C_READ                  = 0x00000040,
-       PDC_I2C_START                 = 0x00000080,
-       PDC_I2C_MASK_INT              = 0x00000020,
-       PDC_I2C_COMPLETE              = 0x00010000,
-       PDC_I2C_NO_ACK                = 0x00100000,
-       PDC_DIMM_SPD_SUBADDRESS_START = 0x00,
-       PDC_DIMM_SPD_SUBADDRESS_END   = 0x7F,
-       PDC_DIMM_SPD_ROW_NUM          = 3,
-       PDC_DIMM_SPD_COLUMN_NUM       = 4,
-       PDC_DIMM_SPD_MODULE_ROW       = 5,
-       PDC_DIMM_SPD_TYPE             = 11,
-       PDC_DIMM_SPD_FRESH_RATE       = 12,
-       PDC_DIMM_SPD_BANK_NUM         = 17,
-       PDC_DIMM_SPD_CAS_LATENCY      = 18,
-       PDC_DIMM_SPD_ATTRIBUTE        = 21,
-       PDC_DIMM_SPD_ROW_PRE_CHARGE   = 27,
-       PDC_DIMM_SPD_ROW_ACTIVE_DELAY = 28,
-       PDC_DIMM_SPD_RAS_CAS_DELAY    = 29,
-       PDC_DIMM_SPD_ACTIVE_PRECHARGE = 30,
-       PDC_DIMM_SPD_SYSTEM_FREQ      = 126,
-       PDC_CTL_STATUS                = 0x08,
-       PDC_DIMM_WINDOW_CTLR          = 0x0C,
-       PDC_TIME_CONTROL              = 0x3C,
-       PDC_TIME_PERIOD               = 0x40,
-       PDC_TIME_COUNTER              = 0x44,
-       PDC_GENERAL_CTLR              = 0x484,
-       PCI_PLL_INIT                  = 0x8A531824,
-       PCI_X_TCOUNT                  = 0xEE1E5CFF
-};
-
-
-struct pdc_port_priv {
-       u8                      dimm_buf[(ATA_PRD_SZ * ATA_MAX_PRD) + 512];
-       u8                      *pkt;
-       dma_addr_t              pkt_dma;
-};
-
-struct pdc_host_priv {
-       void                    __iomem *dimm_mmio;
-
-       unsigned int            doing_hdma;
-       unsigned int            hdma_prod;
-       unsigned int            hdma_cons;
-       struct {
-               struct ata_queued_cmd *qc;
-               unsigned int    seq;
-               unsigned long   pkt_ofs;
-       } hdma[32];
-};
-
-
-static int pdc_sata_init_one (struct pci_dev *pdev, const struct pci_device_id *ent);
-static irqreturn_t pdc20621_interrupt (int irq, void *dev_instance, struct pt_regs *regs);
-static void pdc_eng_timeout(struct ata_port *ap);
-static void pdc_20621_phy_reset (struct ata_port *ap);
-static int pdc_port_start(struct ata_port *ap);
-static void pdc_port_stop(struct ata_port *ap);
-static void pdc20621_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 pdc20621_host_stop(struct ata_host_set *host_set);
-static unsigned int pdc20621_dimm_init(struct ata_probe_ent *pe);
-static int pdc20621_detect_dimm(struct ata_probe_ent *pe);
-static unsigned int pdc20621_i2c_read(struct ata_probe_ent *pe,
-                                     u32 device, u32 subaddr, u32 *pdata);
-static int pdc20621_prog_dimm0(struct ata_probe_ent *pe);
-static unsigned int pdc20621_prog_dimm_global(struct ata_probe_ent *pe);
-#ifdef ATA_VERBOSE_DEBUG
-static void pdc20621_get_from_dimm(struct ata_probe_ent *pe,
-                                  void *psource, u32 offset, u32 size);
-#endif
-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 unsigned int pdc20621_qc_issue_prot(struct ata_queued_cmd *qc);
-
-
-static struct scsi_host_template pdc_sata_sht = {
-       .module                 = THIS_MODULE,
-       .name                   = DRV_NAME,
-       .ioctl                  = ata_scsi_ioctl,
-       .queuecommand           = ata_scsi_queuecmd,
-       .can_queue              = ATA_DEF_QUEUE,
-       .this_id                = ATA_SHT_THIS_ID,
-       .sg_tablesize           = LIBATA_MAX_PRD,
-       .cmd_per_lun            = ATA_SHT_CMD_PER_LUN,
-       .emulated               = ATA_SHT_EMULATED,
-       .use_clustering         = ATA_SHT_USE_CLUSTERING,
-       .proc_name              = DRV_NAME,
-       .dma_boundary           = ATA_DMA_BOUNDARY,
-       .slave_configure        = ata_scsi_slave_config,
-       .slave_destroy          = ata_scsi_slave_destroy,
-       .bios_param             = ata_std_bios_param,
-};
-
-static const struct ata_port_operations pdc_20621_ops = {
-       .port_disable           = ata_port_disable,
-       .tf_load                = pdc_tf_load_mmio,
-       .tf_read                = ata_tf_read,
-       .check_status           = ata_check_status,
-       .exec_command           = pdc_exec_command_mmio,
-       .dev_select             = ata_std_dev_select,
-       .phy_reset              = pdc_20621_phy_reset,
-       .qc_prep                = pdc20621_qc_prep,
-       .qc_issue               = pdc20621_qc_issue_prot,
-       .data_xfer              = ata_mmio_data_xfer,
-       .eng_timeout            = pdc_eng_timeout,
-       .irq_handler            = pdc20621_interrupt,
-       .irq_clear              = pdc20621_irq_clear,
-       .port_start             = pdc_port_start,
-       .port_stop              = pdc_port_stop,
-       .host_stop              = pdc20621_host_stop,
-};
-
-static const struct ata_port_info pdc_port_info[] = {
-       /* board_20621 */
-       {
-               .sht            = &pdc_sata_sht,
-               .host_flags     = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
-                                 ATA_FLAG_SRST | ATA_FLAG_MMIO |
-                                 ATA_FLAG_NO_ATAPI | ATA_FLAG_PIO_POLLING,
-               .pio_mask       = 0x1f, /* pio0-4 */
-               .mwdma_mask     = 0x07, /* mwdma0-2 */
-               .udma_mask      = 0x7f, /* udma0-6 ; FIXME */
-               .port_ops       = &pdc_20621_ops,
-       },
-
-};
-
-static const struct pci_device_id pdc_sata_pci_tbl[] = {
-       { PCI_VENDOR_ID_PROMISE, 0x6622, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-         board_20621 },
-       { }     /* terminate list */
-};
-
-
-static struct pci_driver pdc_sata_pci_driver = {
-       .name                   = DRV_NAME,
-       .id_table               = pdc_sata_pci_tbl,
-       .probe                  = pdc_sata_init_one,
-       .remove                 = ata_pci_remove_one,
-};
-
-
-static void pdc20621_host_stop(struct ata_host_set *host_set)
-{
-       struct pci_dev *pdev = to_pci_dev(host_set->dev);
-       struct pdc_host_priv *hpriv = host_set->private_data;
-       void __iomem *dimm_mmio = hpriv->dimm_mmio;
-
-       pci_iounmap(pdev, dimm_mmio);
-       kfree(hpriv);
-
-       pci_iounmap(pdev, host_set->mmio_base);
-}
-
-static int pdc_port_start(struct ata_port *ap)
-{
-       struct device *dev = ap->host_set->dev;
-       struct pdc_port_priv *pp;
-       int rc;
-
-       rc = ata_port_start(ap);
-       if (rc)
-               return rc;
-
-       pp = kmalloc(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) {
-               rc = -ENOMEM;
-               goto err_out_kfree;
-       }
-
-       ap->private_data = pp;
-
-       return 0;
-
-err_out_kfree:
-       kfree(pp);
-err_out:
-       ata_port_stop(ap);
-       return rc;
-}
-
-
-static void pdc_port_stop(struct ata_port *ap)
-{
-       struct device *dev = ap->host_set->dev;
-       struct pdc_port_priv *pp = ap->private_data;
-
-       ap->private_data = NULL;
-       dma_free_coherent(dev, 128, pp->pkt, pp->pkt_dma);
-       kfree(pp);
-       ata_port_stop(ap);
-}
-
-
-static void pdc_20621_phy_reset (struct ata_port *ap)
-{
-       VPRINTK("ENTER\n");
-        ap->cbl = ATA_CBL_SATA;
-        ata_port_probe(ap);
-        ata_bus_reset(ap);
-}
-
-static inline void pdc20621_ata_sg(struct ata_taskfile *tf, u8 *buf,
-                                          unsigned int portno,
-                                          unsigned int total_len)
-{
-       u32 addr;
-       unsigned int dw = PDC_DIMM_APKT_PRD >> 2;
-       u32 *buf32 = (u32 *) buf;
-
-       /* output ATA packet S/G table */
-       addr = PDC_20621_DIMM_BASE + PDC_20621_DIMM_DATA +
-              (PDC_DIMM_DATA_STEP * portno);
-       VPRINTK("ATA sg addr 0x%x, %d\n", addr, addr);
-       buf32[dw] = cpu_to_le32(addr);
-       buf32[dw + 1] = cpu_to_le32(total_len | ATA_PRD_EOT);
-
-       VPRINTK("ATA PSG @ %x == (0x%x, 0x%x)\n",
-               PDC_20621_DIMM_BASE +
-                      (PDC_DIMM_WINDOW_STEP * portno) +
-                      PDC_DIMM_APKT_PRD,
-               buf32[dw], buf32[dw + 1]);
-}
-
-static inline void pdc20621_host_sg(struct ata_taskfile *tf, u8 *buf,
-                                           unsigned int portno,
-                                           unsigned int total_len)
-{
-       u32 addr;
-       unsigned int dw = PDC_DIMM_HPKT_PRD >> 2;
-       u32 *buf32 = (u32 *) buf;
-
-       /* output Host DMA packet S/G table */
-       addr = PDC_20621_DIMM_BASE + PDC_20621_DIMM_DATA +
-              (PDC_DIMM_DATA_STEP * portno);
-
-       buf32[dw] = cpu_to_le32(addr);
-       buf32[dw + 1] = cpu_to_le32(total_len | ATA_PRD_EOT);
-
-       VPRINTK("HOST PSG @ %x == (0x%x, 0x%x)\n",
-               PDC_20621_DIMM_BASE +
-                      (PDC_DIMM_WINDOW_STEP * portno) +
-                      PDC_DIMM_HPKT_PRD,
-               buf32[dw], buf32[dw + 1]);
-}
-
-static inline unsigned int pdc20621_ata_pkt(struct ata_taskfile *tf,
-                                           unsigned int devno, u8 *buf,
-                                           unsigned int portno)
-{
-       unsigned int i, dw;
-       u32 *buf32 = (u32 *) buf;
-       u8 dev_reg;
-
-       unsigned int dimm_sg = PDC_20621_DIMM_BASE +
-                              (PDC_DIMM_WINDOW_STEP * portno) +
-                              PDC_DIMM_APKT_PRD;
-       VPRINTK("ENTER, dimm_sg == 0x%x, %d\n", dimm_sg, dimm_sg);
-
-       i = PDC_DIMM_ATA_PKT;
-
-       /*
-        * Set up ATA packet
-        */
-       if ((tf->protocol == ATA_PROT_DMA) && (!(tf->flags & ATA_TFLAG_WRITE)))
-               buf[i++] = PDC_PKT_READ;
-       else if (tf->protocol == ATA_PROT_NODATA)
-               buf[i++] = PDC_PKT_NODATA;
-       else
-               buf[i++] = 0;
-       buf[i++] = 0;                   /* reserved */
-       buf[i++] = portno + 1;          /* seq. id */
-       buf[i++] = 0xff;                /* delay seq. id */
-
-       /* dimm dma S/G, and next-pkt */
-       dw = i >> 2;
-       if (tf->protocol == ATA_PROT_NODATA)
-               buf32[dw] = 0;
-       else
-               buf32[dw] = cpu_to_le32(dimm_sg);
-       buf32[dw + 1] = 0;
-       i += 8;
-
-       if (devno == 0)
-               dev_reg = ATA_DEVICE_OBS;
-       else
-               dev_reg = ATA_DEVICE_OBS | ATA_DEV1;
-
-       /* select device */
-       buf[i++] = (1 << 5) | PDC_PKT_CLEAR_BSY | ATA_REG_DEVICE;
-       buf[i++] = dev_reg;
-
-       /* device control register */
-       buf[i++] = (1 << 5) | PDC_REG_DEVCTL;
-       buf[i++] = tf->ctl;
-
-       return i;
-}
-
-static inline void pdc20621_host_pkt(struct ata_taskfile *tf, u8 *buf,
-                                    unsigned int portno)
-{
-       unsigned int dw;
-       u32 tmp, *buf32 = (u32 *) buf;
-
-       unsigned int host_sg = PDC_20621_DIMM_BASE +
-                              (PDC_DIMM_WINDOW_STEP * portno) +
-                              PDC_DIMM_HOST_PRD;
-       unsigned int dimm_sg = PDC_20621_DIMM_BASE +
-                              (PDC_DIMM_WINDOW_STEP * portno) +
-                              PDC_DIMM_HPKT_PRD;
-       VPRINTK("ENTER, dimm_sg == 0x%x, %d\n", dimm_sg, dimm_sg);
-       VPRINTK("host_sg == 0x%x, %d\n", host_sg, host_sg);
-
-       dw = PDC_DIMM_HOST_PKT >> 2;
-
-       /*
-        * Set up Host DMA packet
-        */
-       if ((tf->protocol == ATA_PROT_DMA) && (!(tf->flags & ATA_TFLAG_WRITE)))
-               tmp = PDC_PKT_READ;
-       else
-               tmp = 0;
-       tmp |= ((portno + 1 + 4) << 16);        /* seq. id */
-       tmp |= (0xff << 24);                    /* delay seq. id */
-       buf32[dw + 0] = cpu_to_le32(tmp);
-       buf32[dw + 1] = cpu_to_le32(host_sg);
-       buf32[dw + 2] = cpu_to_le32(dimm_sg);
-       buf32[dw + 3] = 0;
-
-       VPRINTK("HOST PKT @ %x == (0x%x 0x%x 0x%x 0x%x)\n",
-               PDC_20621_DIMM_BASE + (PDC_DIMM_WINDOW_STEP * portno) +
-                       PDC_DIMM_HOST_PKT,
-               buf32[dw + 0],
-               buf32[dw + 1],
-               buf32[dw + 2],
-               buf32[dw + 3]);
-}
-
-static void pdc20621_dma_prep(struct ata_queued_cmd *qc)
-{
-       struct scatterlist *sg;
-       struct ata_port *ap = qc->ap;
-       struct pdc_port_priv *pp = ap->private_data;
-       void __iomem *mmio = ap->host_set->mmio_base;
-       struct pdc_host_priv *hpriv = ap->host_set->private_data;
-       void __iomem *dimm_mmio = hpriv->dimm_mmio;
-       unsigned int portno = ap->port_no;
-       unsigned int i, idx, total_len = 0, sgt_len;
-       u32 *buf = (u32 *) &pp->dimm_buf[PDC_DIMM_HEADER_SZ];
-
-       WARN_ON(!(qc->flags & ATA_QCFLAG_DMAMAP));
-
-       VPRINTK("ata%u: ENTER\n", ap->id);
-
-       /* hard-code chip #0 */
-       mmio += PDC_CHIP0_OFS;
-
-       /*
-        * Build S/G table
-        */
-       idx = 0;
-       ata_for_each_sg(sg, qc) {
-               buf[idx++] = cpu_to_le32(sg_dma_address(sg));
-               buf[idx++] = cpu_to_le32(sg_dma_len(sg));
-               total_len += sg_dma_len(sg);
-       }
-       buf[idx - 1] |= cpu_to_le32(ATA_PRD_EOT);
-       sgt_len = idx * 4;
-
-       /*
-        * Build ATA, host DMA packets
-        */
-       pdc20621_host_sg(&qc->tf, &pp->dimm_buf[0], portno, total_len);
-       pdc20621_host_pkt(&qc->tf, &pp->dimm_buf[0], portno);
-
-       pdc20621_ata_sg(&qc->tf, &pp->dimm_buf[0], portno, total_len);
-       i = pdc20621_ata_pkt(&qc->tf, qc->dev->devno, &pp->dimm_buf[0], portno);
-
-       if (qc->tf.flags & ATA_TFLAG_LBA48)
-               i = pdc_prep_lba48(&qc->tf, &pp->dimm_buf[0], i);
-       else
-               i = pdc_prep_lba28(&qc->tf, &pp->dimm_buf[0], i);
-
-       pdc_pkt_footer(&qc->tf, &pp->dimm_buf[0], i);
-
-       /* copy three S/G tables and two packets to DIMM MMIO window */
-       memcpy_toio(dimm_mmio + (portno * PDC_DIMM_WINDOW_STEP),
-                   &pp->dimm_buf, PDC_DIMM_HEADER_SZ);
-       memcpy_toio(dimm_mmio + (portno * PDC_DIMM_WINDOW_STEP) +
-                   PDC_DIMM_HOST_PRD,
-                   &pp->dimm_buf[PDC_DIMM_HEADER_SZ], sgt_len);
-
-       /* force host FIFO dump */
-       writel(0x00000001, mmio + PDC_20621_GENERAL_CTL);
-
-       readl(dimm_mmio);       /* MMIO PCI posting flush */
-
-       VPRINTK("ata pkt buf ofs %u, prd size %u, mmio copied\n", i, sgt_len);
-}
-
-static void pdc20621_nodata_prep(struct ata_queued_cmd *qc)
-{
-       struct ata_port *ap = qc->ap;
-       struct pdc_port_priv *pp = ap->private_data;
-       void __iomem *mmio = ap->host_set->mmio_base;
-       struct pdc_host_priv *hpriv = ap->host_set->private_data;
-       void __iomem *dimm_mmio = hpriv->dimm_mmio;
-       unsigned int portno = ap->port_no;
-       unsigned int i;
-
-       VPRINTK("ata%u: ENTER\n", ap->id);
-
-       /* hard-code chip #0 */
-       mmio += PDC_CHIP0_OFS;
-
-       i = pdc20621_ata_pkt(&qc->tf, qc->dev->devno, &pp->dimm_buf[0], portno);
-
-       if (qc->tf.flags & ATA_TFLAG_LBA48)
-               i = pdc_prep_lba48(&qc->tf, &pp->dimm_buf[0], i);
-       else
-               i = pdc_prep_lba28(&qc->tf, &pp->dimm_buf[0], i);
-
-       pdc_pkt_footer(&qc->tf, &pp->dimm_buf[0], i);
-
-       /* copy three S/G tables and two packets to DIMM MMIO window */
-       memcpy_toio(dimm_mmio + (portno * PDC_DIMM_WINDOW_STEP),
-                   &pp->dimm_buf, PDC_DIMM_HEADER_SZ);
-
-       /* force host FIFO dump */
-       writel(0x00000001, mmio + PDC_20621_GENERAL_CTL);
-
-       readl(dimm_mmio);       /* MMIO PCI posting flush */
-
-       VPRINTK("ata pkt buf ofs %u, mmio copied\n", i);
-}
-
-static void pdc20621_qc_prep(struct ata_queued_cmd *qc)
-{
-       switch (qc->tf.protocol) {
-       case ATA_PROT_DMA:
-               pdc20621_dma_prep(qc);
-               break;
-       case ATA_PROT_NODATA:
-               pdc20621_nodata_prep(qc);
-               break;
-       default:
-               break;
-       }
-}
-
-static void __pdc20621_push_hdma(struct ata_queued_cmd *qc,
-                                unsigned int seq,
-                                u32 pkt_ofs)
-{
-       struct ata_port *ap = qc->ap;
-       struct ata_host_set *host_set = ap->host_set;
-       void __iomem *mmio = host_set->mmio_base;
-
-       /* hard-code chip #0 */
-       mmio += PDC_CHIP0_OFS;
-
-       writel(0x00000001, mmio + PDC_20621_SEQCTL + (seq * 4));
-       readl(mmio + PDC_20621_SEQCTL + (seq * 4));     /* flush */
-
-       writel(pkt_ofs, mmio + PDC_HDMA_PKT_SUBMIT);
-       readl(mmio + PDC_HDMA_PKT_SUBMIT);      /* flush */
-}
-
-static void pdc20621_push_hdma(struct ata_queued_cmd *qc,
-                               unsigned int seq,
-                               u32 pkt_ofs)
-{
-       struct ata_port *ap = qc->ap;
-       struct pdc_host_priv *pp = ap->host_set->private_data;
-       unsigned int idx = pp->hdma_prod & PDC_HDMA_Q_MASK;
-
-       if (!pp->doing_hdma) {
-               __pdc20621_push_hdma(qc, seq, pkt_ofs);
-               pp->doing_hdma = 1;
-               return;
-       }
-
-       pp->hdma[idx].qc = qc;
-       pp->hdma[idx].seq = seq;
-       pp->hdma[idx].pkt_ofs = pkt_ofs;
-       pp->hdma_prod++;
-}
-
-static void pdc20621_pop_hdma(struct ata_queued_cmd *qc)
-{
-       struct ata_port *ap = qc->ap;
-       struct pdc_host_priv *pp = ap->host_set->private_data;
-       unsigned int idx = pp->hdma_cons & PDC_HDMA_Q_MASK;
-
-       /* if nothing on queue, we're done */
-       if (pp->hdma_prod == pp->hdma_cons) {
-               pp->doing_hdma = 0;
-               return;
-       }
-
-       __pdc20621_push_hdma(pp->hdma[idx].qc, pp->hdma[idx].seq,
-                            pp->hdma[idx].pkt_ofs);
-       pp->hdma_cons++;
-}
-
-#ifdef ATA_VERBOSE_DEBUG
-static void pdc20621_dump_hdma(struct ata_queued_cmd *qc)
-{
-       struct ata_port *ap = qc->ap;
-       unsigned int port_no = ap->port_no;
-       struct pdc_host_priv *hpriv = ap->host_set->private_data;
-       void *dimm_mmio = hpriv->dimm_mmio;
-
-       dimm_mmio += (port_no * PDC_DIMM_WINDOW_STEP);
-       dimm_mmio += PDC_DIMM_HOST_PKT;
-
-       printk(KERN_ERR "HDMA[0] == 0x%08X\n", readl(dimm_mmio));
-       printk(KERN_ERR "HDMA[1] == 0x%08X\n", readl(dimm_mmio + 4));
-       printk(KERN_ERR "HDMA[2] == 0x%08X\n", readl(dimm_mmio + 8));
-       printk(KERN_ERR "HDMA[3] == 0x%08X\n", readl(dimm_mmio + 12));
-}
-#else
-static inline void pdc20621_dump_hdma(struct ata_queued_cmd *qc) { }
-#endif /* ATA_VERBOSE_DEBUG */
-
-static void pdc20621_packet_start(struct ata_queued_cmd *qc)
-{
-       struct ata_port *ap = qc->ap;
-       struct ata_host_set *host_set = ap->host_set;
-       unsigned int port_no = ap->port_no;
-       void __iomem *mmio = host_set->mmio_base;
-       unsigned int rw = (qc->tf.flags & ATA_TFLAG_WRITE);
-       u8 seq = (u8) (port_no + 1);
-       unsigned int port_ofs;
-
-       /* hard-code chip #0 */
-       mmio += PDC_CHIP0_OFS;
-
-       VPRINTK("ata%u: ENTER\n", ap->id);
-
-       wmb();                  /* flush PRD, pkt writes */
-
-       port_ofs = PDC_20621_DIMM_BASE + (PDC_DIMM_WINDOW_STEP * port_no);
-
-       /* if writing, we (1) DMA to DIMM, then (2) do ATA command */
-       if (rw && qc->tf.protocol == ATA_PROT_DMA) {
-               seq += 4;
-
-               pdc20621_dump_hdma(qc);
-               pdc20621_push_hdma(qc, seq, port_ofs + PDC_DIMM_HOST_PKT);
-               VPRINTK("queued ofs 0x%x (%u), seq %u\n",
-                       port_ofs + PDC_DIMM_HOST_PKT,
-                       port_ofs + PDC_DIMM_HOST_PKT,
-                       seq);
-       } else {
-               writel(0x00000001, mmio + PDC_20621_SEQCTL + (seq * 4));
-               readl(mmio + PDC_20621_SEQCTL + (seq * 4));     /* flush */
-
-               writel(port_ofs + PDC_DIMM_ATA_PKT,
-                      (void __iomem *) ap->ioaddr.cmd_addr + PDC_PKT_SUBMIT);
-               readl((void __iomem *) ap->ioaddr.cmd_addr + PDC_PKT_SUBMIT);
-               VPRINTK("submitted ofs 0x%x (%u), seq %u\n",
-                       port_ofs + PDC_DIMM_ATA_PKT,
-                       port_ofs + PDC_DIMM_ATA_PKT,
-                       seq);
-       }
-}
-
-static unsigned int pdc20621_qc_issue_prot(struct ata_queued_cmd *qc)
-{
-       switch (qc->tf.protocol) {
-       case ATA_PROT_DMA:
-       case ATA_PROT_NODATA:
-               pdc20621_packet_start(qc);
-               return 0;
-
-       case ATA_PROT_ATAPI_DMA:
-               BUG();
-               break;
-
-       default:
-               break;
-       }
-
-       return ata_qc_issue_prot(qc);
-}
-
-static inline unsigned int pdc20621_host_intr( struct ata_port *ap,
-                                          struct ata_queued_cmd *qc,
-                                         unsigned int doing_hdma,
-                                         void __iomem *mmio)
-{
-       unsigned int port_no = ap->port_no;
-       unsigned int port_ofs =
-               PDC_20621_DIMM_BASE + (PDC_DIMM_WINDOW_STEP * port_no);
-       u8 status;
-       unsigned int handled = 0;
-
-       VPRINTK("ENTER\n");
-
-       if ((qc->tf.protocol == ATA_PROT_DMA) &&        /* read */
-           (!(qc->tf.flags & ATA_TFLAG_WRITE))) {
-
-               /* step two - DMA from DIMM to host */
-               if (doing_hdma) {
-                       VPRINTK("ata%u: read hdma, 0x%x 0x%x\n", ap->id,
-                               readl(mmio + 0x104), readl(mmio + PDC_HDMA_CTLSTAT));
-                       /* get drive status; clear intr; complete txn */
-                       qc->err_mask |= ac_err_mask(ata_wait_idle(ap));
-                       ata_qc_complete(qc);
-                       pdc20621_pop_hdma(qc);
-               }
-
-               /* step one - exec ATA command */
-               else {
-                       u8 seq = (u8) (port_no + 1 + 4);
-                       VPRINTK("ata%u: read ata, 0x%x 0x%x\n", ap->id,
-                               readl(mmio + 0x104), readl(mmio + PDC_HDMA_CTLSTAT));
-
-                       /* submit hdma pkt */
-                       pdc20621_dump_hdma(qc);
-                       pdc20621_push_hdma(qc, seq,
-                                          port_ofs + PDC_DIMM_HOST_PKT);
-               }
-               handled = 1;
-
-       } else if (qc->tf.protocol == ATA_PROT_DMA) {   /* write */
-
-               /* step one - DMA from host to DIMM */
-               if (doing_hdma) {
-                       u8 seq = (u8) (port_no + 1);
-                       VPRINTK("ata%u: write hdma, 0x%x 0x%x\n", ap->id,
-                               readl(mmio + 0x104), readl(mmio + PDC_HDMA_CTLSTAT));
-
-                       /* submit ata pkt */
-                       writel(0x00000001, mmio + PDC_20621_SEQCTL + (seq * 4));
-                       readl(mmio + PDC_20621_SEQCTL + (seq * 4));
-                       writel(port_ofs + PDC_DIMM_ATA_PKT,
-                              (void __iomem *) ap->ioaddr.cmd_addr + PDC_PKT_SUBMIT);
-                       readl((void __iomem *) ap->ioaddr.cmd_addr + PDC_PKT_SUBMIT);
-               }
-
-               /* step two - execute ATA command */
-               else {
-                       VPRINTK("ata%u: write ata, 0x%x 0x%x\n", ap->id,
-                               readl(mmio + 0x104), readl(mmio + PDC_HDMA_CTLSTAT));
-                       /* get drive status; clear intr; complete txn */
-                       qc->err_mask |= ac_err_mask(ata_wait_idle(ap));
-                       ata_qc_complete(qc);
-                       pdc20621_pop_hdma(qc);
-               }
-               handled = 1;
-
-       /* command completion, but no data xfer */
-       } else if (qc->tf.protocol == ATA_PROT_NODATA) {
-
-               status = ata_busy_wait(ap, ATA_BUSY | ATA_DRQ, 1000);
-               DPRINTK("BUS_NODATA (drv_stat 0x%X)\n", status);
-               qc->err_mask |= ac_err_mask(status);
-               ata_qc_complete(qc);
-               handled = 1;
-
-       } else {
-               ap->stats.idle_irq++;
-       }
-
-       return handled;
-}
-
-static void pdc20621_irq_clear(struct ata_port *ap)
-{
-       struct ata_host_set *host_set = ap->host_set;
-       void __iomem *mmio = host_set->mmio_base;
-
-       mmio += PDC_CHIP0_OFS;
-
-       readl(mmio + PDC_20621_SEQMASK);
-}
-
-static irqreturn_t pdc20621_interrupt (int irq, void *dev_instance, struct pt_regs *regs)
-{
-       struct ata_host_set *host_set = dev_instance;
-       struct ata_port *ap;
-       u32 mask = 0;
-       unsigned int i, tmp, port_no;
-       unsigned int handled = 0;
-       void __iomem *mmio_base;
-
-       VPRINTK("ENTER\n");
-
-       if (!host_set || !host_set->mmio_base) {
-               VPRINTK("QUICK EXIT\n");
-               return IRQ_NONE;
-       }
-
-       mmio_base = host_set->mmio_base;
-
-       /* reading should also clear interrupts */
-       mmio_base += PDC_CHIP0_OFS;
-       mask = readl(mmio_base + PDC_20621_SEQMASK);
-       VPRINTK("mask == 0x%x\n", mask);
-
-       if (mask == 0xffffffff) {
-               VPRINTK("QUICK EXIT 2\n");
-               return IRQ_NONE;
-       }
-       mask &= 0xffff;         /* only 16 tags possible */
-       if (!mask) {
-               VPRINTK("QUICK EXIT 3\n");
-               return IRQ_NONE;
-       }
-
-        spin_lock(&host_set->lock);
-
-        for (i = 1; i < 9; i++) {
-               port_no = i - 1;
-               if (port_no > 3)
-                       port_no -= 4;
-               if (port_no >= host_set->n_ports)
-                       ap = NULL;
-               else
-                       ap = host_set->ports[port_no];
-               tmp = mask & (1 << i);
-               VPRINTK("seq %u, port_no %u, ap %p, tmp %x\n", i, port_no, ap, tmp);
-               if (tmp && ap &&
-                   !(ap->flags & ATA_FLAG_DISABLED)) {
-                       struct ata_queued_cmd *qc;
-
-                       qc = ata_qc_from_tag(ap, ap->active_tag);
-                       if (qc && (!(qc->tf.flags & ATA_TFLAG_POLLING)))
-                               handled += pdc20621_host_intr(ap, qc, (i > 4),
-                                                             mmio_base);
-               }
-       }
-
-        spin_unlock(&host_set->lock);
-
-       VPRINTK("mask == 0x%x\n", mask);
-
-       VPRINTK("EXIT\n");
-
-       return IRQ_RETVAL(handled);
-}
-
-static void pdc_eng_timeout(struct ata_port *ap)
-{
-       u8 drv_stat;
-       struct ata_host_set *host_set = ap->host_set;
-       struct ata_queued_cmd *qc;
-       unsigned long flags;
-
-       DPRINTK("ENTER\n");
-
-       spin_lock_irqsave(&host_set->lock, flags);
-
-       qc = ata_qc_from_tag(ap, ap->active_tag);
-
-       switch (qc->tf.protocol) {
-       case ATA_PROT_DMA:
-       case ATA_PROT_NODATA:
-               ata_port_printk(ap, KERN_ERR, "command timeout\n");
-               qc->err_mask |= __ac_err_mask(ata_wait_idle(ap));
-               break;
-
-       default:
-               drv_stat = ata_busy_wait(ap, ATA_BUSY | ATA_DRQ, 1000);
-
-               ata_port_printk(ap, KERN_ERR,
-                               "unknown timeout, cmd 0x%x stat 0x%x\n",
-                               qc->tf.command, drv_stat);
-
-               qc->err_mask |= ac_err_mask(drv_stat);
-               break;
-       }
-
-       spin_unlock_irqrestore(&host_set->lock, flags);
-       ata_eh_qc_complete(qc);
-       DPRINTK("EXIT\n");
-}
-
-static void pdc_tf_load_mmio(struct ata_port *ap, const struct ata_taskfile *tf)
-{
-       WARN_ON (tf->protocol == ATA_PROT_DMA ||
-                tf->protocol == ATA_PROT_NODATA);
-       ata_tf_load(ap, tf);
-}
-
-
-static void pdc_exec_command_mmio(struct ata_port *ap, const struct ata_taskfile *tf)
-{
-       WARN_ON (tf->protocol == ATA_PROT_DMA ||
-                tf->protocol == ATA_PROT_NODATA);
-       ata_exec_command(ap, tf);
-}
-
-
-static void pdc_sata_setup_port(struct ata_ioports *port, unsigned long base)
-{
-       port->cmd_addr          = base;
-       port->data_addr         = base;
-       port->feature_addr      =
-       port->error_addr        = base + 0x4;
-       port->nsect_addr        = base + 0x8;
-       port->lbal_addr         = base + 0xc;
-       port->lbam_addr         = base + 0x10;
-       port->lbah_addr         = base + 0x14;
-       port->device_addr       = base + 0x18;
-       port->command_addr      =
-       port->status_addr       = base + 0x1c;
-       port->altstatus_addr    =
-       port->ctl_addr          = base + 0x38;
-}
-
-
-#ifdef ATA_VERBOSE_DEBUG
-static void pdc20621_get_from_dimm(struct ata_probe_ent *pe, void *psource,
-                                  u32 offset, u32 size)
-{
-       u32 window_size;
-       u16 idx;
-       u8 page_mask;
-       long dist;
-       void __iomem *mmio = pe->mmio_base;
-       struct pdc_host_priv *hpriv = pe->private_data;
-       void __iomem *dimm_mmio = hpriv->dimm_mmio;
-
-       /* hard-code chip #0 */
-       mmio += PDC_CHIP0_OFS;
-
-       page_mask = 0x00;
-       window_size = 0x2000 * 4; /* 32K byte uchar size */
-       idx = (u16) (offset / window_size);
-
-       writel(0x01, mmio + PDC_GENERAL_CTLR);
-       readl(mmio + PDC_GENERAL_CTLR);
-       writel(((idx) << page_mask), mmio + PDC_DIMM_WINDOW_CTLR);
-       readl(mmio + PDC_DIMM_WINDOW_CTLR);
-
-       offset -= (idx * window_size);
-       idx++;
-       dist = ((long) (window_size - (offset + size))) >= 0 ? size :
-               (long) (window_size - offset);
-       memcpy_fromio((char *) psource, (char *) (dimm_mmio + offset / 4),
-                     dist);
-
-       psource += dist;
-       size -= dist;
-       for (; (long) size >= (long) window_size ;) {
-               writel(0x01, mmio + PDC_GENERAL_CTLR);
-               readl(mmio + PDC_GENERAL_CTLR);
-               writel(((idx) << page_mask), mmio + PDC_DIMM_WINDOW_CTLR);
-               readl(mmio + PDC_DIMM_WINDOW_CTLR);
-               memcpy_fromio((char *) psource, (char *) (dimm_mmio),
-                             window_size / 4);
-               psource += window_size;
-               size -= window_size;
-               idx ++;
-       }
-
-       if (size) {
-               writel(0x01, mmio + PDC_GENERAL_CTLR);
-               readl(mmio + PDC_GENERAL_CTLR);
-               writel(((idx) << page_mask), mmio + PDC_DIMM_WINDOW_CTLR);
-               readl(mmio + PDC_DIMM_WINDOW_CTLR);
-               memcpy_fromio((char *) psource, (char *) (dimm_mmio),
-                             size / 4);
-       }
-}
-#endif
-
-
-static void pdc20621_put_to_dimm(struct ata_probe_ent *pe, void *psource,
-                                u32 offset, u32 size)
-{
-       u32 window_size;
-       u16 idx;
-       u8 page_mask;
-       long dist;
-       void __iomem *mmio = pe->mmio_base;
-       struct pdc_host_priv *hpriv = pe->private_data;
-       void __iomem *dimm_mmio = hpriv->dimm_mmio;
-
-       /* hard-code chip #0 */
-       mmio += PDC_CHIP0_OFS;
-
-       page_mask = 0x00;
-       window_size = 0x2000 * 4;       /* 32K byte uchar size */
-       idx = (u16) (offset / window_size);
-
-       writel(((idx) << page_mask), mmio + PDC_DIMM_WINDOW_CTLR);
-       readl(mmio + PDC_DIMM_WINDOW_CTLR);
-       offset -= (idx * window_size);
-       idx++;
-       dist = ((long)(s32)(window_size - (offset + size))) >= 0 ? size :
-               (long) (window_size - offset);
-       memcpy_toio(dimm_mmio + offset / 4, psource, dist);
-       writel(0x01, mmio + PDC_GENERAL_CTLR);
-       readl(mmio + PDC_GENERAL_CTLR);
-
-       psource += dist;
-       size -= dist;
-       for (; (long) size >= (long) window_size ;) {
-               writel(((idx) << page_mask), mmio + PDC_DIMM_WINDOW_CTLR);
-               readl(mmio + PDC_DIMM_WINDOW_CTLR);
-               memcpy_toio(dimm_mmio, psource, window_size / 4);
-               writel(0x01, mmio + PDC_GENERAL_CTLR);
-               readl(mmio + PDC_GENERAL_CTLR);
-               psource += window_size;
-               size -= window_size;
-               idx ++;
-       }
-
-       if (size) {
-               writel(((idx) << page_mask), mmio + PDC_DIMM_WINDOW_CTLR);
-               readl(mmio + PDC_DIMM_WINDOW_CTLR);
-               memcpy_toio(dimm_mmio, psource, size / 4);
-               writel(0x01, mmio + PDC_GENERAL_CTLR);
-               readl(mmio + PDC_GENERAL_CTLR);
-       }
-}
-
-
-static unsigned int pdc20621_i2c_read(struct ata_probe_ent *pe, u32 device,
-                                     u32 subaddr, u32 *pdata)
-{
-       void __iomem *mmio = pe->mmio_base;
-       u32 i2creg  = 0;
-       u32 status;
-       u32 count =0;
-
-       /* hard-code chip #0 */
-       mmio += PDC_CHIP0_OFS;
-
-       i2creg |= device << 24;
-       i2creg |= subaddr << 16;
-
-       /* Set the device and subaddress */
-       writel(i2creg, mmio + PDC_I2C_ADDR_DATA_OFFSET);
-       readl(mmio + PDC_I2C_ADDR_DATA_OFFSET);
-
-       /* Write Control to perform read operation, mask int */
-       writel(PDC_I2C_READ | PDC_I2C_START | PDC_I2C_MASK_INT,
-              mmio + PDC_I2C_CONTROL_OFFSET);
-
-       for (count = 0; count <= 1000; count ++) {
-               status = readl(mmio + PDC_I2C_CONTROL_OFFSET);
-               if (status & PDC_I2C_COMPLETE) {
-                       status = readl(mmio + PDC_I2C_ADDR_DATA_OFFSET);
-                       break;
-               } else if (count == 1000)
-                       return 0;
-       }
-
-       *pdata = (status >> 8) & 0x000000ff;
-       return 1;
-}
-
-
-static int pdc20621_detect_dimm(struct ata_probe_ent *pe)
-{
-       u32 data=0 ;
-       if (pdc20621_i2c_read(pe, PDC_DIMM0_SPD_DEV_ADDRESS,
-                            PDC_DIMM_SPD_SYSTEM_FREQ, &data)) {
-               if (data == 100)
-                       return 100;
-       } else
-               return 0;
-
-       if (pdc20621_i2c_read(pe, PDC_DIMM0_SPD_DEV_ADDRESS, 9, &data)) {
-               if(data <= 0x75)
-                       return 133;
-       } else
-               return 0;
-
-       return 0;
-}
-
-
-static int pdc20621_prog_dimm0(struct ata_probe_ent *pe)
-{
-       u32 spd0[50];
-       u32 data = 0;
-       int size, i;
-       u8 bdimmsize;
-       void __iomem *mmio = pe->mmio_base;
-       static const struct {
-               unsigned int reg;
-               unsigned int ofs;
-       } pdc_i2c_read_data [] = {
-               { PDC_DIMM_SPD_TYPE, 11 },
-               { PDC_DIMM_SPD_FRESH_RATE, 12 },
-               { PDC_DIMM_SPD_COLUMN_NUM, 4 },
-               { PDC_DIMM_SPD_ATTRIBUTE, 21 },
-               { PDC_DIMM_SPD_ROW_NUM, 3 },
-               { PDC_DIMM_SPD_BANK_NUM, 17 },
-               { PDC_DIMM_SPD_MODULE_ROW, 5 },
-               { PDC_DIMM_SPD_ROW_PRE_CHARGE, 27 },
-               { PDC_DIMM_SPD_ROW_ACTIVE_DELAY, 28 },
-               { PDC_DIMM_SPD_RAS_CAS_DELAY, 29 },
-               { PDC_DIMM_SPD_ACTIVE_PRECHARGE, 30 },
-               { PDC_DIMM_SPD_CAS_LATENCY, 18 },
-       };
-
-       /* hard-code chip #0 */
-       mmio += PDC_CHIP0_OFS;
-
-       for(i=0; i<ARRAY_SIZE(pdc_i2c_read_data); i++)
-               pdc20621_i2c_read(pe, PDC_DIMM0_SPD_DEV_ADDRESS,
-                                 pdc_i2c_read_data[i].reg,
-                                 &spd0[pdc_i2c_read_data[i].ofs]);
-
-       data |= (spd0[4] - 8) | ((spd0[21] != 0) << 3) | ((spd0[3]-11) << 4);
-       data |= ((spd0[17] / 4) << 6) | ((spd0[5] / 2) << 7) |
-               ((((spd0[27] + 9) / 10) - 1) << 8) ;
-       data |= (((((spd0[29] > spd0[28])
-                   ? spd0[29] : spd0[28]) + 9) / 10) - 1) << 10;
-       data |= ((spd0[30] - spd0[29] + 9) / 10 - 2) << 12;
-
-       if (spd0[18] & 0x08)
-               data |= ((0x03) << 14);
-       else if (spd0[18] & 0x04)
-               data |= ((0x02) << 14);
-       else if (spd0[18] & 0x01)
-               data |= ((0x01) << 14);
-       else
-               data |= (0 << 14);
-
-       /*
-          Calculate the size of bDIMMSize (power of 2) and
-          merge the DIMM size by program start/end address.
-       */
-
-       bdimmsize = spd0[4] + (spd0[5] / 2) + spd0[3] + (spd0[17] / 2) + 3;
-       size = (1 << bdimmsize) >> 20;  /* size = xxx(MB) */
-       data |= (((size / 16) - 1) << 16);
-       data |= (0 << 23);
-       data |= 8;
-       writel(data, mmio + PDC_DIMM0_CONTROL_OFFSET);
-       readl(mmio + PDC_DIMM0_CONTROL_OFFSET);
-       return size;
-}
-
-
-static unsigned int pdc20621_prog_dimm_global(struct ata_probe_ent *pe)
-{
-       u32 data, spd0;
-       int error, i;
-       void __iomem *mmio = pe->mmio_base;
-
-       /* hard-code chip #0 */
-       mmio += PDC_CHIP0_OFS;
-
-       /*
-         Set To Default : DIMM Module Global Control Register (0x022259F1)
-         DIMM Arbitration Disable (bit 20)
-         DIMM Data/Control Output Driving Selection (bit12 - bit15)
-         Refresh Enable (bit 17)
-       */
-
-       data = 0x022259F1;
-       writel(data, mmio + PDC_SDRAM_CONTROL_OFFSET);
-       readl(mmio + PDC_SDRAM_CONTROL_OFFSET);
-
-       /* Turn on for ECC */
-       pdc20621_i2c_read(pe, PDC_DIMM0_SPD_DEV_ADDRESS,
-                         PDC_DIMM_SPD_TYPE, &spd0);
-       if (spd0 == 0x02) {
-               data |= (0x01 << 16);
-               writel(data, mmio + PDC_SDRAM_CONTROL_OFFSET);
-               readl(mmio + PDC_SDRAM_CONTROL_OFFSET);
-               printk(KERN_ERR "Local DIMM ECC Enabled\n");
-       }
-
-       /* DIMM Initialization Select/Enable (bit 18/19) */
-       data &= (~(1<<18));
-       data |= (1<<19);
-       writel(data, mmio + PDC_SDRAM_CONTROL_OFFSET);
-
-       error = 1;
-       for (i = 1; i <= 10; i++) {   /* polling ~5 secs */
-               data = readl(mmio + PDC_SDRAM_CONTROL_OFFSET);
-               if (!(data & (1<<19))) {
-                       error = 0;
-                       break;
-               }
-               msleep(i*100);
-       }
-       return error;
-}
-
-
-static unsigned int pdc20621_dimm_init(struct ata_probe_ent *pe)
-{
-       int speed, size, length;
-       u32 addr,spd0,pci_status;
-       u32 tmp=0;
-       u32 time_period=0;
-       u32 tcount=0;
-       u32 ticks=0;
-       u32 clock=0;
-       u32 fparam=0;
-       void __iomem *mmio = pe->mmio_base;
-
-       /* hard-code chip #0 */
-       mmio += PDC_CHIP0_OFS;
-
-       /* Initialize PLL based upon PCI Bus Frequency */
-
-       /* Initialize Time Period Register */
-       writel(0xffffffff, mmio + PDC_TIME_PERIOD);
-       time_period = readl(mmio + PDC_TIME_PERIOD);
-       VPRINTK("Time Period Register (0x40): 0x%x\n", time_period);
-
-       /* Enable timer */
-       writel(0x00001a0, mmio + PDC_TIME_CONTROL);
-       readl(mmio + PDC_TIME_CONTROL);
-
-       /* Wait 3 seconds */
-       msleep(3000);
-
-       /*
-          When timer is enabled, counter is decreased every internal
-          clock cycle.
-       */
-
-       tcount = readl(mmio + PDC_TIME_COUNTER);
-       VPRINTK("Time Counter Register (0x44): 0x%x\n", tcount);
-
-       /*
-          If SX4 is on PCI-X bus, after 3 seconds, the timer counter
-          register should be >= (0xffffffff - 3x10^8).
-       */
-       if(tcount >= PCI_X_TCOUNT) {
-               ticks = (time_period - tcount);
-               VPRINTK("Num counters 0x%x (%d)\n", ticks, ticks);
-
-               clock = (ticks / 300000);
-               VPRINTK("10 * Internal clk = 0x%x (%d)\n", clock, clock);
-
-               clock = (clock * 33);
-               VPRINTK("10 * Internal clk * 33 = 0x%x (%d)\n", clock, clock);
-
-               /* PLL F Param (bit 22:16) */
-               fparam = (1400000 / clock) - 2;
-               VPRINTK("PLL F Param: 0x%x (%d)\n", fparam, fparam);
-
-               /* OD param = 0x2 (bit 31:30), R param = 0x5 (bit 29:25) */
-               pci_status = (0x8a001824 | (fparam << 16));
-       } else
-               pci_status = PCI_PLL_INIT;
-
-       /* Initialize PLL. */
-       VPRINTK("pci_status: 0x%x\n", pci_status);
-       writel(pci_status, mmio + PDC_CTL_STATUS);
-       readl(mmio + PDC_CTL_STATUS);
-
-       /*
-          Read SPD of DIMM by I2C interface,
-          and program the DIMM Module Controller.
-       */
-       if (!(speed = pdc20621_detect_dimm(pe))) {
-               printk(KERN_ERR "Detect Local DIMM Fail\n");
-               return 1;       /* DIMM error */
-       }
-       VPRINTK("Local DIMM Speed = %d\n", speed);
-
-       /* Programming DIMM0 Module Control Register (index_CID0:80h) */
-       size = pdc20621_prog_dimm0(pe);
-       VPRINTK("Local DIMM Size = %dMB\n",size);
-
-       /* Programming DIMM Module Global Control Register (index_CID0:88h) */
-       if (pdc20621_prog_dimm_global(pe)) {
-               printk(KERN_ERR "Programming DIMM Module Global Control Register Fail\n");
-               return 1;
-       }
-
-#ifdef ATA_VERBOSE_DEBUG
-       {
-               u8 test_parttern1[40] = {0x55,0xAA,'P','r','o','m','i','s','e',' ',
-                               'N','o','t',' ','Y','e','t',' ','D','e','f','i','n','e','d',' ',
-                                '1','.','1','0',
-                               '9','8','0','3','1','6','1','2',0,0};
-               u8 test_parttern2[40] = {0};
-
-               pdc20621_put_to_dimm(pe, (void *) test_parttern2, 0x10040, 40);
-               pdc20621_put_to_dimm(pe, (void *) test_parttern2, 0x40, 40);
-
-               pdc20621_put_to_dimm(pe, (void *) test_parttern1, 0x10040, 40);
-               pdc20621_get_from_dimm(pe, (void *) test_parttern2, 0x40, 40);
-               printk(KERN_ERR "%x, %x, %s\n", test_parttern2[0],
-                      test_parttern2[1], &(test_parttern2[2]));
-               pdc20621_get_from_dimm(pe, (void *) test_parttern2, 0x10040,
-                                      40);
-               printk(KERN_ERR "%x, %x, %s\n", test_parttern2[0],
-                      test_parttern2[1], &(test_parttern2[2]));
-
-               pdc20621_put_to_dimm(pe, (void *) test_parttern1, 0x40, 40);
-               pdc20621_get_from_dimm(pe, (void *) test_parttern2, 0x40, 40);
-               printk(KERN_ERR "%x, %x, %s\n", test_parttern2[0],
-                      test_parttern2[1], &(test_parttern2[2]));
-       }
-#endif
-
-       /* ECC initiliazation. */
-
-       pdc20621_i2c_read(pe, PDC_DIMM0_SPD_DEV_ADDRESS,
-                         PDC_DIMM_SPD_TYPE, &spd0);
-       if (spd0 == 0x02) {
-               VPRINTK("Start ECC initialization\n");
-               addr = 0;
-               length = size * 1024 * 1024;
-               while (addr < length) {
-                       pdc20621_put_to_dimm(pe, (void *) &tmp, addr,
-                                            sizeof(u32));
-                       addr += sizeof(u32);
-               }
-               VPRINTK("Finish ECC initialization\n");
-       }
-       return 0;
-}
-
-
-static void pdc_20621_init(struct ata_probe_ent *pe)
-{
-       u32 tmp;
-       void __iomem *mmio = pe->mmio_base;
-
-       /* hard-code chip #0 */
-       mmio += PDC_CHIP0_OFS;
-
-       /*
-        * Select page 0x40 for our 32k DIMM window
-        */
-       tmp = readl(mmio + PDC_20621_DIMM_WINDOW) & 0xffff0000;
-       tmp |= PDC_PAGE_WINDOW; /* page 40h; arbitrarily selected */
-       writel(tmp, mmio + PDC_20621_DIMM_WINDOW);
-
-       /*
-        * Reset Host DMA
-        */
-       tmp = readl(mmio + PDC_HDMA_CTLSTAT);
-       tmp |= PDC_RESET;
-       writel(tmp, mmio + PDC_HDMA_CTLSTAT);
-       readl(mmio + PDC_HDMA_CTLSTAT);         /* flush */
-
-       udelay(10);
-
-       tmp = readl(mmio + PDC_HDMA_CTLSTAT);
-       tmp &= ~PDC_RESET;
-       writel(tmp, mmio + PDC_HDMA_CTLSTAT);
-       readl(mmio + PDC_HDMA_CTLSTAT);         /* flush */
-}
-
-static int pdc_sata_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
-{
-       static int printed_version;
-       struct ata_probe_ent *probe_ent = NULL;
-       unsigned long base;
-       void __iomem *mmio_base;
-       void __iomem *dimm_mmio = NULL;
-       struct pdc_host_priv *hpriv = NULL;
-       unsigned int board_idx = (unsigned int) ent->driver_data;
-       int pci_dev_busy = 0;
-       int rc;
-
-       if (!printed_version++)
-               dev_printk(KERN_DEBUG, &pdev->dev, "version " DRV_VERSION "\n");
-
-       rc = pci_enable_device(pdev);
-       if (rc)
-               return rc;
-
-       rc = pci_request_regions(pdev, DRV_NAME);
-       if (rc) {
-               pci_dev_busy = 1;
-               goto err_out;
-       }
-
-       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;
-
-       probe_ent = kmalloc(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);
-
-       mmio_base = pci_iomap(pdev, 3, 0);
-       if (mmio_base == NULL) {
-               rc = -ENOMEM;
-               goto err_out_free_ent;
-       }
-       base = (unsigned long) mmio_base;
-
-       hpriv = kmalloc(sizeof(*hpriv), GFP_KERNEL);
-       if (!hpriv) {
-               rc = -ENOMEM;
-               goto err_out_iounmap;
-       }
-       memset(hpriv, 0, sizeof(*hpriv));
-
-       dimm_mmio = pci_iomap(pdev, 4, 0);
-       if (!dimm_mmio) {
-               kfree(hpriv);
-               rc = -ENOMEM;
-               goto err_out_iounmap;
-       }
-
-       hpriv->dimm_mmio = dimm_mmio;
-
-       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;
-       probe_ent->mwdma_mask   = pdc_port_info[board_idx].mwdma_mask;
-       probe_ent->udma_mask    = pdc_port_info[board_idx].udma_mask;
-       probe_ent->port_ops     = pdc_port_info[board_idx].port_ops;
-
-               probe_ent->irq = pdev->irq;
-               probe_ent->irq_flags = IRQF_SHARED;
-       probe_ent->mmio_base = mmio_base;
-
-       probe_ent->private_data = hpriv;
-       base += PDC_CHIP0_OFS;
-
-       probe_ent->n_ports = 4;
-       pdc_sata_setup_port(&probe_ent->port[0], base + 0x200);
-       pdc_sata_setup_port(&probe_ent->port[1], base + 0x280);
-       pdc_sata_setup_port(&probe_ent->port[2], base + 0x300);
-       pdc_sata_setup_port(&probe_ent->port[3], base + 0x380);
-
-       pci_set_master(pdev);
-
-       /* initialize adapter */
-       /* initialize local dimm */
-       if (pdc20621_dimm_init(probe_ent)) {
-               rc = -ENOMEM;
-               goto err_out_iounmap_dimm;
-       }
-       pdc_20621_init(probe_ent);
-
-       /* FIXME: check ata_device_add return value */
-       ata_device_add(probe_ent);
-       kfree(probe_ent);
-
-       return 0;
-
-err_out_iounmap_dimm:          /* only get to this label if 20621 */
-       kfree(hpriv);
-       pci_iounmap(pdev, dimm_mmio);
-err_out_iounmap:
-       pci_iounmap(pdev, mmio_base);
-err_out_free_ent:
-       kfree(probe_ent);
-err_out_regions:
-       pci_release_regions(pdev);
-err_out:
-       if (!pci_dev_busy)
-               pci_disable_device(pdev);
-       return rc;
-}
-
-
-static int __init pdc_sata_init(void)
-{
-       return pci_register_driver(&pdc_sata_pci_driver);
-}
-
-
-static void __exit pdc_sata_exit(void)
-{
-       pci_unregister_driver(&pdc_sata_pci_driver);
-}
-
-
-MODULE_AUTHOR("Jeff Garzik");
-MODULE_DESCRIPTION("Promise SATA low-level driver");
-MODULE_LICENSE("GPL");
-MODULE_DEVICE_TABLE(pci, pdc_sata_pci_tbl);
-MODULE_VERSION(DRV_VERSION);
-
-module_init(pdc_sata_init);
-module_exit(pdc_sata_exit);
diff --git a/drivers/scsi/sata_uli.c b/drivers/scsi/sata_uli.c
deleted file mode 100644 (file)
index 654aae2..0000000
+++ /dev/null
@@ -1,300 +0,0 @@
-/*
- *  sata_uli.c - ULi Electronics SATA
- *
- *
- *  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 under NDA.
- *
- */
-
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/pci.h>
-#include <linux/init.h>
-#include <linux/blkdev.h>
-#include <linux/delay.h>
-#include <linux/interrupt.h>
-#include <linux/device.h>
-#include <scsi/scsi_host.h>
-#include <linux/libata.h>
-
-#define DRV_NAME       "sata_uli"
-#define DRV_VERSION    "1.0"
-
-enum {
-       uli_5289                = 0,
-       uli_5287                = 1,
-       uli_5281                = 2,
-
-       uli_max_ports           = 4,
-
-       /* PCI configuration registers */
-       ULI5287_BASE            = 0x90, /* sata0 phy SCR registers */
-       ULI5287_OFFS            = 0x10, /* offset from sata0->sata1 phy regs */
-       ULI5281_BASE            = 0x60, /* sata0 phy SCR  registers */
-       ULI5281_OFFS            = 0x60, /* offset from sata0->sata1 phy regs */
-};
-
-struct uli_priv {
-       unsigned int            scr_cfg_addr[uli_max_ports];
-};
-
-static int uli_init_one (struct pci_dev *pdev, const struct pci_device_id *ent);
-static u32 uli_scr_read (struct ata_port *ap, unsigned int sc_reg);
-static void uli_scr_write (struct ata_port *ap, unsigned int sc_reg, u32 val);
-
-static const struct pci_device_id uli_pci_tbl[] = {
-       { PCI_VENDOR_ID_AL, 0x5289, PCI_ANY_ID, PCI_ANY_ID, 0, 0, uli_5289 },
-       { PCI_VENDOR_ID_AL, 0x5287, PCI_ANY_ID, PCI_ANY_ID, 0, 0, uli_5287 },
-       { PCI_VENDOR_ID_AL, 0x5281, PCI_ANY_ID, PCI_ANY_ID, 0, 0, uli_5281 },
-       { }     /* terminate list */
-};
-
-
-static struct pci_driver uli_pci_driver = {
-       .name                   = DRV_NAME,
-       .id_table               = uli_pci_tbl,
-       .probe                  = uli_init_one,
-       .remove                 = ata_pci_remove_one,
-};
-
-static struct scsi_host_template uli_sht = {
-       .module                 = THIS_MODULE,
-       .name                   = DRV_NAME,
-       .ioctl                  = ata_scsi_ioctl,
-       .queuecommand           = ata_scsi_queuecmd,
-       .can_queue              = ATA_DEF_QUEUE,
-       .this_id                = ATA_SHT_THIS_ID,
-       .sg_tablesize           = LIBATA_MAX_PRD,
-       .cmd_per_lun            = ATA_SHT_CMD_PER_LUN,
-       .emulated               = ATA_SHT_EMULATED,
-       .use_clustering         = ATA_SHT_USE_CLUSTERING,
-       .proc_name              = DRV_NAME,
-       .dma_boundary           = ATA_DMA_BOUNDARY,
-       .slave_configure        = ata_scsi_slave_config,
-       .slave_destroy          = ata_scsi_slave_destroy,
-       .bios_param             = ata_std_bios_param,
-};
-
-static const struct ata_port_operations uli_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,
-
-       .bmdma_setup            = ata_bmdma_setup,
-       .bmdma_start            = ata_bmdma_start,
-       .bmdma_stop             = ata_bmdma_stop,
-       .bmdma_status           = ata_bmdma_status,
-       .qc_prep                = ata_qc_prep,
-       .qc_issue               = ata_qc_issue_prot,
-       .data_xfer              = ata_pio_data_xfer,
-
-       .freeze                 = ata_bmdma_freeze,
-       .thaw                   = ata_bmdma_thaw,
-       .error_handler          = ata_bmdma_error_handler,
-       .post_internal_cmd      = ata_bmdma_post_internal_cmd,
-
-       .irq_handler            = ata_interrupt,
-       .irq_clear              = ata_bmdma_irq_clear,
-
-       .scr_read               = uli_scr_read,
-       .scr_write              = uli_scr_write,
-
-       .port_start             = ata_port_start,
-       .port_stop              = ata_port_stop,
-       .host_stop              = ata_host_stop,
-};
-
-static struct ata_port_info uli_port_info = {
-       .sht            = &uli_sht,
-       .host_flags     = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY,
-       .pio_mask       = 0x1f,         /* pio0-4 */
-       .udma_mask      = 0x7f,         /* udma0-6 */
-       .port_ops       = &uli_ops,
-};
-
-
-MODULE_AUTHOR("Peer Chen");
-MODULE_DESCRIPTION("low-level driver for ULi Electronics SATA controller");
-MODULE_LICENSE("GPL");
-MODULE_DEVICE_TABLE(pci, uli_pci_tbl);
-MODULE_VERSION(DRV_VERSION);
-
-static unsigned int get_scr_cfg_addr(struct ata_port *ap, unsigned int sc_reg)
-{
-       struct uli_priv *hpriv = ap->host_set->private_data;
-       return hpriv->scr_cfg_addr[ap->port_no] + (4 * sc_reg);
-}
-
-static u32 uli_scr_cfg_read (struct ata_port *ap, unsigned int sc_reg)
-{
-       struct pci_dev *pdev = to_pci_dev(ap->host_set->dev);
-       unsigned int cfg_addr = get_scr_cfg_addr(ap, sc_reg);
-       u32 val;
-
-       pci_read_config_dword(pdev, cfg_addr, &val);
-       return val;
-}
-
-static void uli_scr_cfg_write (struct ata_port *ap, unsigned int scr, u32 val)
-{
-       struct pci_dev *pdev = to_pci_dev(ap->host_set->dev);
-       unsigned int cfg_addr = get_scr_cfg_addr(ap, scr);
-
-       pci_write_config_dword(pdev, cfg_addr, val);
-}
-
-static u32 uli_scr_read (struct ata_port *ap, unsigned int sc_reg)
-{
-       if (sc_reg > SCR_CONTROL)
-               return 0xffffffffU;
-
-       return uli_scr_cfg_read(ap, sc_reg);
-}
-
-static void uli_scr_write (struct ata_port *ap, unsigned int sc_reg, u32 val)
-{
-       if (sc_reg > SCR_CONTROL)       //SCR_CONTROL=2, SCR_ERROR=1, SCR_STATUS=0
-               return;
-
-       uli_scr_cfg_write(ap, sc_reg, val);
-}
-
-static int uli_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
-{
-       static int printed_version;
-       struct ata_probe_ent *probe_ent;
-       struct ata_port_info *ppi;
-       int rc;
-       unsigned int board_idx = (unsigned int) ent->driver_data;
-       int pci_dev_busy = 0;
-       struct uli_priv *hpriv;
-
-       if (!printed_version++)
-               dev_printk(KERN_INFO, &pdev->dev, "version " DRV_VERSION "\n");
-
-       rc = pci_enable_device(pdev);
-       if (rc)
-               return rc;
-
-       rc = pci_request_regions(pdev, DRV_NAME);
-       if (rc) {
-               pci_dev_busy = 1;
-               goto err_out;
-       }
-
-       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;
-
-       ppi = &uli_port_info;
-       probe_ent = ata_pci_init_native_mode(pdev, &ppi, ATA_PORT_PRIMARY | ATA_PORT_SECONDARY);
-       if (!probe_ent) {
-               rc = -ENOMEM;
-               goto err_out_regions;
-       }
-
-       hpriv = kzalloc(sizeof(*hpriv), GFP_KERNEL);
-       if (!hpriv) {
-               rc = -ENOMEM;
-               goto err_out_probe_ent;
-       }
-
-       probe_ent->private_data = hpriv;
-
-       switch (board_idx) {
-       case uli_5287:
-               hpriv->scr_cfg_addr[0] = ULI5287_BASE;
-               hpriv->scr_cfg_addr[1] = ULI5287_BASE + ULI5287_OFFS;
-                       probe_ent->n_ports = 4;
-
-                       probe_ent->port[2].cmd_addr = pci_resource_start(pdev, 0) + 8;
-               probe_ent->port[2].altstatus_addr =
-               probe_ent->port[2].ctl_addr =
-                       (pci_resource_start(pdev, 1) | ATA_PCI_CTL_OFS) + 4;
-               probe_ent->port[2].bmdma_addr = pci_resource_start(pdev, 4) + 16;
-               hpriv->scr_cfg_addr[2] = ULI5287_BASE + ULI5287_OFFS*4;
-
-               probe_ent->port[3].cmd_addr = pci_resource_start(pdev, 2) + 8;
-               probe_ent->port[3].altstatus_addr =
-               probe_ent->port[3].ctl_addr =
-                       (pci_resource_start(pdev, 3) | ATA_PCI_CTL_OFS) + 4;
-               probe_ent->port[3].bmdma_addr = pci_resource_start(pdev, 4) + 24;
-               hpriv->scr_cfg_addr[3] = ULI5287_BASE + ULI5287_OFFS*5;
-
-               ata_std_ports(&probe_ent->port[2]);
-               ata_std_ports(&probe_ent->port[3]);
-               break;
-
-       case uli_5289:
-               hpriv->scr_cfg_addr[0] = ULI5287_BASE;
-               hpriv->scr_cfg_addr[1] = ULI5287_BASE + ULI5287_OFFS;
-               break;
-
-       case uli_5281:
-               hpriv->scr_cfg_addr[0] = ULI5281_BASE;
-               hpriv->scr_cfg_addr[1] = ULI5281_BASE + ULI5281_OFFS;
-               break;
-
-       default:
-               BUG();
-               break;
-       }
-
-       pci_set_master(pdev);
-       pci_intx(pdev, 1);
-
-       /* FIXME: check ata_device_add return value */
-       ata_device_add(probe_ent);
-       kfree(probe_ent);
-
-       return 0;
-
-err_out_probe_ent:
-       kfree(probe_ent);
-err_out_regions:
-       pci_release_regions(pdev);
-err_out:
-       if (!pci_dev_busy)
-               pci_disable_device(pdev);
-       return rc;
-
-}
-
-static int __init uli_init(void)
-{
-       return pci_register_driver(&uli_pci_driver);
-}
-
-static void __exit uli_exit(void)
-{
-       pci_unregister_driver(&uli_pci_driver);
-}
-
-
-module_init(uli_init);
-module_exit(uli_exit);
diff --git a/drivers/scsi/sata_via.c b/drivers/scsi/sata_via.c
deleted file mode 100644 (file)
index 0bf1dbe..0000000
+++ /dev/null
@@ -1,394 +0,0 @@
-/*
- *  sata_via.c - VIA Serial ATA controllers
- *
- *  Maintained by:  Jeff Garzik <jgarzik@pobox.com>
- *                Please ALWAYS copy linux-ide@vger.kernel.org
-                  on emails.
- *
- *  Copyright 2003-2004 Red Hat, Inc.  All rights reserved.
- *  Copyright 2003-2004 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 under NDA.
- *
- *
- *  To-do list:
- *  - VT6421 PATA support
- *
- */
-
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/pci.h>
-#include <linux/init.h>
-#include <linux/blkdev.h>
-#include <linux/delay.h>
-#include <linux/device.h>
-#include <scsi/scsi_host.h>
-#include <linux/libata.h>
-#include <asm/io.h>
-
-#define DRV_NAME       "sata_via"
-#define DRV_VERSION    "2.0"
-
-enum board_ids_enum {
-       vt6420,
-       vt6421,
-};
-
-enum {
-       SATA_CHAN_ENAB          = 0x40, /* SATA channel enable */
-       SATA_INT_GATE           = 0x41, /* SATA interrupt gating */
-       SATA_NATIVE_MODE        = 0x42, /* Native mode enable */
-       SATA_PATA_SHARING       = 0x49, /* PATA/SATA sharing func ctrl */
-
-       PORT0                   = (1 << 1),
-       PORT1                   = (1 << 0),
-       ALL_PORTS               = PORT0 | PORT1,
-       N_PORTS                 = 2,
-
-       NATIVE_MODE_ALL         = (1 << 7) | (1 << 6) | (1 << 5) | (1 << 4),
-
-       SATA_EXT_PHY            = (1 << 6), /* 0==use PATA, 1==ext phy */
-       SATA_2DEV               = (1 << 5), /* SATA is master/slave */
-};
-
-static int svia_init_one (struct pci_dev *pdev, const struct pci_device_id *ent);
-static u32 svia_scr_read (struct ata_port *ap, unsigned int sc_reg);
-static void svia_scr_write (struct ata_port *ap, unsigned int sc_reg, u32 val);
-
-static const struct pci_device_id svia_pci_tbl[] = {
-       { 0x1106, 0x3149, PCI_ANY_ID, PCI_ANY_ID, 0, 0, vt6420 },
-       { 0x1106, 0x3249, PCI_ANY_ID, PCI_ANY_ID, 0, 0, vt6421 },
-
-       { }     /* terminate list */
-};
-
-static struct pci_driver svia_pci_driver = {
-       .name                   = DRV_NAME,
-       .id_table               = svia_pci_tbl,
-       .probe                  = svia_init_one,
-       .remove                 = ata_pci_remove_one,
-};
-
-static struct scsi_host_template svia_sht = {
-       .module                 = THIS_MODULE,
-       .name                   = DRV_NAME,
-       .ioctl                  = ata_scsi_ioctl,
-       .queuecommand           = ata_scsi_queuecmd,
-       .can_queue              = ATA_DEF_QUEUE,
-       .this_id                = ATA_SHT_THIS_ID,
-       .sg_tablesize           = LIBATA_MAX_PRD,
-       .cmd_per_lun            = ATA_SHT_CMD_PER_LUN,
-       .emulated               = ATA_SHT_EMULATED,
-       .use_clustering         = ATA_SHT_USE_CLUSTERING,
-       .proc_name              = DRV_NAME,
-       .dma_boundary           = ATA_DMA_BOUNDARY,
-       .slave_configure        = ata_scsi_slave_config,
-       .slave_destroy          = ata_scsi_slave_destroy,
-       .bios_param             = ata_std_bios_param,
-};
-
-static const struct ata_port_operations svia_sata_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,
-
-       .bmdma_setup            = ata_bmdma_setup,
-       .bmdma_start            = ata_bmdma_start,
-       .bmdma_stop             = ata_bmdma_stop,
-       .bmdma_status           = ata_bmdma_status,
-
-       .qc_prep                = ata_qc_prep,
-       .qc_issue               = ata_qc_issue_prot,
-       .data_xfer              = ata_pio_data_xfer,
-
-       .freeze                 = ata_bmdma_freeze,
-       .thaw                   = ata_bmdma_thaw,
-       .error_handler          = ata_bmdma_error_handler,
-       .post_internal_cmd      = ata_bmdma_post_internal_cmd,
-
-       .irq_handler            = ata_interrupt,
-       .irq_clear              = ata_bmdma_irq_clear,
-
-       .scr_read               = svia_scr_read,
-       .scr_write              = svia_scr_write,
-
-       .port_start             = ata_port_start,
-       .port_stop              = ata_port_stop,
-       .host_stop              = ata_host_stop,
-};
-
-static struct ata_port_info svia_port_info = {
-       .sht            = &svia_sht,
-       .host_flags     = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY,
-       .pio_mask       = 0x1f,
-       .mwdma_mask     = 0x07,
-       .udma_mask      = 0x7f,
-       .port_ops       = &svia_sata_ops,
-};
-
-MODULE_AUTHOR("Jeff Garzik");
-MODULE_DESCRIPTION("SCSI low-level driver for VIA SATA controllers");
-MODULE_LICENSE("GPL");
-MODULE_DEVICE_TABLE(pci, svia_pci_tbl);
-MODULE_VERSION(DRV_VERSION);
-
-static u32 svia_scr_read (struct ata_port *ap, unsigned int sc_reg)
-{
-       if (sc_reg > SCR_CONTROL)
-               return 0xffffffffU;
-       return inl(ap->ioaddr.scr_addr + (4 * sc_reg));
-}
-
-static void svia_scr_write (struct ata_port *ap, unsigned int sc_reg, u32 val)
-{
-       if (sc_reg > SCR_CONTROL)
-               return;
-       outl(val, ap->ioaddr.scr_addr + (4 * sc_reg));
-}
-
-static const unsigned int svia_bar_sizes[] = {
-       8, 4, 8, 4, 16, 256
-};
-
-static const unsigned int vt6421_bar_sizes[] = {
-       16, 16, 16, 16, 32, 128
-};
-
-static unsigned long svia_scr_addr(unsigned long addr, unsigned int port)
-{
-       return addr + (port * 128);
-}
-
-static unsigned long vt6421_scr_addr(unsigned long addr, unsigned int port)
-{
-       return addr + (port * 64);
-}
-
-static void vt6421_init_addrs(struct ata_probe_ent *probe_ent,
-                             struct pci_dev *pdev,
-                             unsigned int port)
-{
-       unsigned long reg_addr = pci_resource_start(pdev, port);
-       unsigned long bmdma_addr = pci_resource_start(pdev, 4) + (port * 8);
-       unsigned long scr_addr;
-
-       probe_ent->port[port].cmd_addr = reg_addr;
-       probe_ent->port[port].altstatus_addr =
-       probe_ent->port[port].ctl_addr = (reg_addr + 8) | ATA_PCI_CTL_OFS;
-       probe_ent->port[port].bmdma_addr = bmdma_addr;
-
-       scr_addr = vt6421_scr_addr(pci_resource_start(pdev, 5), port);
-       probe_ent->port[port].scr_addr = scr_addr;
-
-       ata_std_ports(&probe_ent->port[port]);
-}
-
-static struct ata_probe_ent *vt6420_init_probe_ent(struct pci_dev *pdev)
-{
-       struct ata_probe_ent *probe_ent;
-       struct ata_port_info *ppi = &svia_port_info;
-
-       probe_ent = ata_pci_init_native_mode(pdev, &ppi, ATA_PORT_PRIMARY | ATA_PORT_SECONDARY);
-       if (!probe_ent)
-               return NULL;
-
-       probe_ent->port[0].scr_addr =
-               svia_scr_addr(pci_resource_start(pdev, 5), 0);
-       probe_ent->port[1].scr_addr =
-               svia_scr_addr(pci_resource_start(pdev, 5), 1);
-
-       return probe_ent;
-}
-
-static struct ata_probe_ent *vt6421_init_probe_ent(struct pci_dev *pdev)
-{
-       struct ata_probe_ent *probe_ent;
-       unsigned int i;
-
-       probe_ent = kmalloc(sizeof(*probe_ent), GFP_KERNEL);
-       if (!probe_ent)
-               return NULL;
-
-       memset(probe_ent, 0, sizeof(*probe_ent));
-       probe_ent->dev = pci_dev_to_dev(pdev);
-       INIT_LIST_HEAD(&probe_ent->node);
-
-       probe_ent->sht          = &svia_sht;
-       probe_ent->host_flags   = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY;
-       probe_ent->port_ops     = &svia_sata_ops;
-       probe_ent->n_ports      = N_PORTS;
-       probe_ent->irq          = pdev->irq;
-       probe_ent->irq_flags    = IRQF_SHARED;
-       probe_ent->pio_mask     = 0x1f;
-       probe_ent->mwdma_mask   = 0x07;
-       probe_ent->udma_mask    = 0x7f;
-
-       for (i = 0; i < N_PORTS; i++)
-               vt6421_init_addrs(probe_ent, pdev, i);
-
-       return probe_ent;
-}
-
-static void svia_configure(struct pci_dev *pdev)
-{
-       u8 tmp8;
-
-       pci_read_config_byte(pdev, PCI_INTERRUPT_LINE, &tmp8);
-       dev_printk(KERN_INFO, &pdev->dev, "routed to hard irq line %d\n",
-              (int) (tmp8 & 0xf0) == 0xf0 ? 0 : tmp8 & 0x0f);
-
-       /* make sure SATA channels are enabled */
-       pci_read_config_byte(pdev, SATA_CHAN_ENAB, &tmp8);
-       if ((tmp8 & ALL_PORTS) != ALL_PORTS) {
-               dev_printk(KERN_DEBUG, &pdev->dev,
-                          "enabling SATA channels (0x%x)\n",
-                          (int) tmp8);
-               tmp8 |= ALL_PORTS;
-               pci_write_config_byte(pdev, SATA_CHAN_ENAB, tmp8);
-       }
-
-       /* make sure interrupts for each channel sent to us */
-       pci_read_config_byte(pdev, SATA_INT_GATE, &tmp8);
-       if ((tmp8 & ALL_PORTS) != ALL_PORTS) {
-               dev_printk(KERN_DEBUG, &pdev->dev,
-                          "enabling SATA channel interrupts (0x%x)\n",
-                          (int) tmp8);
-               tmp8 |= ALL_PORTS;
-               pci_write_config_byte(pdev, SATA_INT_GATE, tmp8);
-       }
-
-       /* make sure native mode is enabled */
-       pci_read_config_byte(pdev, SATA_NATIVE_MODE, &tmp8);
-       if ((tmp8 & NATIVE_MODE_ALL) != NATIVE_MODE_ALL) {
-               dev_printk(KERN_DEBUG, &pdev->dev,
-                          "enabling SATA channel native mode (0x%x)\n",
-                          (int) tmp8);
-               tmp8 |= NATIVE_MODE_ALL;
-               pci_write_config_byte(pdev, SATA_NATIVE_MODE, tmp8);
-       }
-}
-
-static int svia_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
-{
-       static int printed_version;
-       unsigned int i;
-       int rc;
-       struct ata_probe_ent *probe_ent;
-       int board_id = (int) ent->driver_data;
-       const int *bar_sizes;
-       int pci_dev_busy = 0;
-       u8 tmp8;
-
-       if (!printed_version++)
-               dev_printk(KERN_DEBUG, &pdev->dev, "version " DRV_VERSION "\n");
-
-       rc = pci_enable_device(pdev);
-       if (rc)
-               return rc;
-
-       rc = pci_request_regions(pdev, DRV_NAME);
-       if (rc) {
-               pci_dev_busy = 1;
-               goto err_out;
-       }
-
-       if (board_id == vt6420) {
-               pci_read_config_byte(pdev, SATA_PATA_SHARING, &tmp8);
-               if (tmp8 & SATA_2DEV) {
-                       dev_printk(KERN_ERR, &pdev->dev,
-                                  "SATA master/slave not supported (0x%x)\n",
-                                  (int) tmp8);
-                       rc = -EIO;
-                       goto err_out_regions;
-               }
-
-               bar_sizes = &svia_bar_sizes[0];
-       } else {
-               bar_sizes = &vt6421_bar_sizes[0];
-       }
-
-       for (i = 0; i < ARRAY_SIZE(svia_bar_sizes); i++)
-               if ((pci_resource_start(pdev, i) == 0) ||
-                   (pci_resource_len(pdev, i) < bar_sizes[i])) {
-                       dev_printk(KERN_ERR, &pdev->dev,
-                               "invalid PCI BAR %u (sz 0x%llx, val 0x%llx)\n",
-                               i,
-                               (unsigned long long)pci_resource_start(pdev, i),
-                               (unsigned long long)pci_resource_len(pdev, i));
-                       rc = -ENODEV;
-                       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 (board_id == vt6420)
-               probe_ent = vt6420_init_probe_ent(pdev);
-       else
-               probe_ent = vt6421_init_probe_ent(pdev);
-
-       if (!probe_ent) {
-               dev_printk(KERN_ERR, &pdev->dev, "out of memory\n");
-               rc = -ENOMEM;
-               goto err_out_regions;
-       }
-
-       svia_configure(pdev);
-
-       pci_set_master(pdev);
-
-       /* FIXME: check ata_device_add return value */
-       ata_device_add(probe_ent);
-       kfree(probe_ent);
-
-       return 0;
-
-err_out_regions:
-       pci_release_regions(pdev);
-err_out:
-       if (!pci_dev_busy)
-               pci_disable_device(pdev);
-       return rc;
-}
-
-static int __init svia_init(void)
-{
-       return pci_register_driver(&svia_pci_driver);
-}
-
-static void __exit svia_exit(void)
-{
-       pci_unregister_driver(&svia_pci_driver);
-}
-
-module_init(svia_init);
-module_exit(svia_exit);
-
diff --git a/drivers/scsi/sata_vsc.c b/drivers/scsi/sata_vsc.c
deleted file mode 100644 (file)
index 4c69a70..0000000
+++ /dev/null
@@ -1,482 +0,0 @@
-/*
- *  sata_vsc.c - Vitesse VSC7174 4 port DPA SATA
- *
- *  Maintained by:  Jeremy Higdon @ SGI
- *                 Please ALWAYS copy linux-ide@vger.kernel.org
- *                 on emails.
- *
- *  Copyright 2004 SGI
- *
- *  Bits from Jeff Garzik, Copyright RedHat, Inc.
- *
- *
- *  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.*
- *
- *  Vitesse hardware documentation presumably available under NDA.
- *  Intel 31244 (same hardware interface) documentation presumably
- *  available from http://developer.intel.com/
- *
- */
-
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/pci.h>
-#include <linux/init.h>
-#include <linux/blkdev.h>
-#include <linux/delay.h>
-#include <linux/interrupt.h>
-#include <linux/dma-mapping.h>
-#include <linux/device.h>
-#include <scsi/scsi_host.h>
-#include <linux/libata.h>
-
-#define DRV_NAME       "sata_vsc"
-#define DRV_VERSION    "2.0"
-
-enum {
-       /* Interrupt register offsets (from chip base address) */
-       VSC_SATA_INT_STAT_OFFSET        = 0x00,
-       VSC_SATA_INT_MASK_OFFSET        = 0x04,
-
-       /* Taskfile registers offsets */
-       VSC_SATA_TF_CMD_OFFSET          = 0x00,
-       VSC_SATA_TF_DATA_OFFSET         = 0x00,
-       VSC_SATA_TF_ERROR_OFFSET        = 0x04,
-       VSC_SATA_TF_FEATURE_OFFSET      = 0x06,
-       VSC_SATA_TF_NSECT_OFFSET        = 0x08,
-       VSC_SATA_TF_LBAL_OFFSET         = 0x0c,
-       VSC_SATA_TF_LBAM_OFFSET         = 0x10,
-       VSC_SATA_TF_LBAH_OFFSET         = 0x14,
-       VSC_SATA_TF_DEVICE_OFFSET       = 0x18,
-       VSC_SATA_TF_STATUS_OFFSET       = 0x1c,
-       VSC_SATA_TF_COMMAND_OFFSET      = 0x1d,
-       VSC_SATA_TF_ALTSTATUS_OFFSET    = 0x28,
-       VSC_SATA_TF_CTL_OFFSET          = 0x29,
-
-       /* DMA base */
-       VSC_SATA_UP_DESCRIPTOR_OFFSET   = 0x64,
-       VSC_SATA_UP_DATA_BUFFER_OFFSET  = 0x6C,
-       VSC_SATA_DMA_CMD_OFFSET         = 0x70,
-
-       /* SCRs base */
-       VSC_SATA_SCR_STATUS_OFFSET      = 0x100,
-       VSC_SATA_SCR_ERROR_OFFSET       = 0x104,
-       VSC_SATA_SCR_CONTROL_OFFSET     = 0x108,
-
-       /* Port stride */
-       VSC_SATA_PORT_OFFSET            = 0x200,
-
-       /* Error interrupt status bit offsets */
-       VSC_SATA_INT_ERROR_CRC          = 0x40,
-       VSC_SATA_INT_ERROR_T            = 0x20,
-       VSC_SATA_INT_ERROR_P            = 0x10,
-       VSC_SATA_INT_ERROR_R            = 0x8,
-       VSC_SATA_INT_ERROR_E            = 0x4,
-       VSC_SATA_INT_ERROR_M            = 0x2,
-       VSC_SATA_INT_PHY_CHANGE         = 0x1,
-       VSC_SATA_INT_ERROR = (VSC_SATA_INT_ERROR_CRC  | VSC_SATA_INT_ERROR_T | \
-                             VSC_SATA_INT_ERROR_P    | VSC_SATA_INT_ERROR_R | \
-                             VSC_SATA_INT_ERROR_E    | VSC_SATA_INT_ERROR_M | \
-                             VSC_SATA_INT_PHY_CHANGE),
-};
-
-
-#define is_vsc_sata_int_err(port_idx, int_status) \
-        (int_status & (VSC_SATA_INT_ERROR << (8 * port_idx)))
-
-
-static u32 vsc_sata_scr_read (struct ata_port *ap, unsigned int sc_reg)
-{
-       if (sc_reg > SCR_CONTROL)
-               return 0xffffffffU;
-       return readl((void __iomem *) ap->ioaddr.scr_addr + (sc_reg * 4));
-}
-
-
-static void vsc_sata_scr_write (struct ata_port *ap, unsigned int sc_reg,
-                              u32 val)
-{
-       if (sc_reg > SCR_CONTROL)
-               return;
-       writel(val, (void __iomem *) ap->ioaddr.scr_addr + (sc_reg * 4));
-}
-
-
-static void vsc_intr_mask_update(struct ata_port *ap, u8 ctl)
-{
-       void __iomem *mask_addr;
-       u8 mask;
-
-       mask_addr = ap->host_set->mmio_base +
-               VSC_SATA_INT_MASK_OFFSET + ap->port_no;
-       mask = readb(mask_addr);
-       if (ctl & ATA_NIEN)
-               mask |= 0x80;
-       else
-               mask &= 0x7F;
-       writeb(mask, mask_addr);
-}
-
-
-static void vsc_sata_tf_load(struct ata_port *ap, const struct ata_taskfile *tf)
-{
-       struct ata_ioports *ioaddr = &ap->ioaddr;
-       unsigned int is_addr = tf->flags & ATA_TFLAG_ISADDR;
-
-       /*
-        * The only thing the ctl register is used for is SRST.
-        * That is not enabled or disabled via tf_load.
-        * However, if ATA_NIEN is changed, then we need to change the interrupt register.
-        */
-       if ((tf->ctl & ATA_NIEN) != (ap->last_ctl & ATA_NIEN)) {
-               ap->last_ctl = tf->ctl;
-               vsc_intr_mask_update(ap, tf->ctl & ATA_NIEN);
-       }
-       if (is_addr && (tf->flags & ATA_TFLAG_LBA48)) {
-               writew(tf->feature | (((u16)tf->hob_feature) << 8), ioaddr->feature_addr);
-               writew(tf->nsect | (((u16)tf->hob_nsect) << 8), ioaddr->nsect_addr);
-               writew(tf->lbal | (((u16)tf->hob_lbal) << 8), ioaddr->lbal_addr);
-               writew(tf->lbam | (((u16)tf->hob_lbam) << 8), ioaddr->lbam_addr);
-               writew(tf->lbah | (((u16)tf->hob_lbah) << 8), ioaddr->lbah_addr);
-       } else if (is_addr) {
-               writew(tf->feature, ioaddr->feature_addr);
-               writew(tf->nsect, ioaddr->nsect_addr);
-               writew(tf->lbal, ioaddr->lbal_addr);
-               writew(tf->lbam, ioaddr->lbam_addr);
-               writew(tf->lbah, ioaddr->lbah_addr);
-       }
-
-       if (tf->flags & ATA_TFLAG_DEVICE)
-               writeb(tf->device, ioaddr->device_addr);
-
-       ata_wait_idle(ap);
-}
-
-
-static void vsc_sata_tf_read(struct ata_port *ap, struct ata_taskfile *tf)
-{
-       struct ata_ioports *ioaddr = &ap->ioaddr;
-       u16 nsect, lbal, lbam, lbah, feature;
-
-       tf->command = ata_check_status(ap);
-       tf->device = readw(ioaddr->device_addr);
-       feature = readw(ioaddr->error_addr);
-       nsect = readw(ioaddr->nsect_addr);
-       lbal = readw(ioaddr->lbal_addr);
-       lbam = readw(ioaddr->lbam_addr);
-       lbah = readw(ioaddr->lbah_addr);
-
-       tf->feature = feature;
-       tf->nsect = nsect;
-       tf->lbal = lbal;
-       tf->lbam = lbam;
-       tf->lbah = lbah;
-
-       if (tf->flags & ATA_TFLAG_LBA48) {
-               tf->hob_feature = feature >> 8;
-               tf->hob_nsect = nsect >> 8;
-               tf->hob_lbal = lbal >> 8;
-               tf->hob_lbam = lbam >> 8;
-               tf->hob_lbah = lbah >> 8;
-        }
-}
-
-
-/*
- * vsc_sata_interrupt
- *
- * Read the interrupt register and process for the devices that have them pending.
- */
-static irqreturn_t vsc_sata_interrupt (int irq, void *dev_instance,
-                                      struct pt_regs *regs)
-{
-       struct ata_host_set *host_set = dev_instance;
-       unsigned int i;
-       unsigned int handled = 0;
-       u32 int_status;
-
-       spin_lock(&host_set->lock);
-
-       int_status = readl(host_set->mmio_base + VSC_SATA_INT_STAT_OFFSET);
-
-       for (i = 0; i < host_set->n_ports; i++) {
-               if (int_status & ((u32) 0xFF << (8 * i))) {
-                       struct ata_port *ap;
-
-                       ap = host_set->ports[i];
-
-                       if (is_vsc_sata_int_err(i, int_status)) {
-                               u32 err_status;
-                               printk(KERN_DEBUG "%s: ignoring interrupt(s)\n", __FUNCTION__);
-                               err_status = ap ? vsc_sata_scr_read(ap, SCR_ERROR) : 0;
-                               vsc_sata_scr_write(ap, SCR_ERROR, err_status);
-                               handled++;
-                       }
-
-                       if (ap && !(ap->flags & ATA_FLAG_DISABLED)) {
-                               struct ata_queued_cmd *qc;
-
-                               qc = ata_qc_from_tag(ap, ap->active_tag);
-                               if (qc && (!(qc->tf.flags & ATA_TFLAG_POLLING)))
-                                       handled += ata_host_intr(ap, qc);
-                               else if (is_vsc_sata_int_err(i, int_status)) {
-                                       /*
-                                        * On some chips (i.e. Intel 31244), an error
-                                        * interrupt will sneak in at initialization
-                                        * time (phy state changes).  Clearing the SCR
-                                        * error register is not required, but it prevents
-                                        * the phy state change interrupts from recurring
-                                        * later.
-                                        */
-                                       u32 err_status;
-                                       err_status = vsc_sata_scr_read(ap, SCR_ERROR);
-                                       printk(KERN_DEBUG "%s: clearing interrupt, "
-                                              "status %x; sata err status %x\n",
-                                              __FUNCTION__,
-                                              int_status, err_status);
-                                       vsc_sata_scr_write(ap, SCR_ERROR, err_status);
-                                       /* Clear interrupt status */
-                                       ata_chk_status(ap);
-                                       handled++;
-                               }
-                       }
-               }
-       }
-
-       spin_unlock(&host_set->lock);
-
-       return IRQ_RETVAL(handled);
-}
-
-
-static struct scsi_host_template vsc_sata_sht = {
-       .module                 = THIS_MODULE,
-       .name                   = DRV_NAME,
-       .ioctl                  = ata_scsi_ioctl,
-       .queuecommand           = ata_scsi_queuecmd,
-       .can_queue              = ATA_DEF_QUEUE,
-       .this_id                = ATA_SHT_THIS_ID,
-       .sg_tablesize           = LIBATA_MAX_PRD,
-       .cmd_per_lun            = ATA_SHT_CMD_PER_LUN,
-       .emulated               = ATA_SHT_EMULATED,
-       .use_clustering         = ATA_SHT_USE_CLUSTERING,
-       .proc_name              = DRV_NAME,
-       .dma_boundary           = ATA_DMA_BOUNDARY,
-       .slave_configure        = ata_scsi_slave_config,
-       .slave_destroy          = ata_scsi_slave_destroy,
-       .bios_param             = ata_std_bios_param,
-};
-
-
-static const struct ata_port_operations vsc_sata_ops = {
-       .port_disable           = ata_port_disable,
-       .tf_load                = vsc_sata_tf_load,
-       .tf_read                = vsc_sata_tf_read,
-       .exec_command           = ata_exec_command,
-       .check_status           = ata_check_status,
-       .dev_select             = ata_std_dev_select,
-       .bmdma_setup            = ata_bmdma_setup,
-       .bmdma_start            = ata_bmdma_start,
-       .bmdma_stop             = ata_bmdma_stop,
-       .bmdma_status           = ata_bmdma_status,
-       .qc_prep                = ata_qc_prep,
-       .qc_issue               = ata_qc_issue_prot,
-       .data_xfer              = ata_mmio_data_xfer,
-       .freeze                 = ata_bmdma_freeze,
-       .thaw                   = ata_bmdma_thaw,
-       .error_handler          = ata_bmdma_error_handler,
-       .post_internal_cmd      = ata_bmdma_post_internal_cmd,
-       .irq_handler            = vsc_sata_interrupt,
-       .irq_clear              = ata_bmdma_irq_clear,
-       .scr_read               = vsc_sata_scr_read,
-       .scr_write              = vsc_sata_scr_write,
-       .port_start             = ata_port_start,
-       .port_stop              = ata_port_stop,
-       .host_stop              = ata_pci_host_stop,
-};
-
-static void __devinit vsc_sata_setup_port(struct ata_ioports *port, unsigned long base)
-{
-       port->cmd_addr          = base + VSC_SATA_TF_CMD_OFFSET;
-       port->data_addr         = base + VSC_SATA_TF_DATA_OFFSET;
-       port->error_addr        = base + VSC_SATA_TF_ERROR_OFFSET;
-       port->feature_addr      = base + VSC_SATA_TF_FEATURE_OFFSET;
-       port->nsect_addr        = base + VSC_SATA_TF_NSECT_OFFSET;
-       port->lbal_addr         = base + VSC_SATA_TF_LBAL_OFFSET;
-       port->lbam_addr         = base + VSC_SATA_TF_LBAM_OFFSET;
-       port->lbah_addr         = base + VSC_SATA_TF_LBAH_OFFSET;
-       port->device_addr       = base + VSC_SATA_TF_DEVICE_OFFSET;
-       port->status_addr       = base + VSC_SATA_TF_STATUS_OFFSET;
-       port->command_addr      = base + VSC_SATA_TF_COMMAND_OFFSET;
-       port->altstatus_addr    = base + VSC_SATA_TF_ALTSTATUS_OFFSET;
-       port->ctl_addr          = base + VSC_SATA_TF_CTL_OFFSET;
-       port->bmdma_addr        = base + VSC_SATA_DMA_CMD_OFFSET;
-       port->scr_addr          = base + VSC_SATA_SCR_STATUS_OFFSET;
-       writel(0, base + VSC_SATA_UP_DESCRIPTOR_OFFSET);
-       writel(0, base + VSC_SATA_UP_DATA_BUFFER_OFFSET);
-}
-
-
-static int __devinit vsc_sata_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
-{
-       static int printed_version;
-       struct ata_probe_ent *probe_ent = NULL;
-       unsigned long base;
-       int pci_dev_busy = 0;
-       void __iomem *mmio_base;
-       int rc;
-
-       if (!printed_version++)
-               dev_printk(KERN_DEBUG, &pdev->dev, "version " DRV_VERSION "\n");
-
-       rc = pci_enable_device(pdev);
-       if (rc)
-               return rc;
-
-       /*
-        * Check if we have needed resource mapped.
-        */
-       if (pci_resource_len(pdev, 0) == 0) {
-               rc = -ENODEV;
-               goto err_out;
-       }
-
-       rc = pci_request_regions(pdev, DRV_NAME);
-       if (rc) {
-               pci_dev_busy = 1;
-               goto err_out;
-       }
-
-       /*
-        * Use 32 bit DMA mask, because 64 bit address support is poor.
-        */
-       rc = pci_set_dma_mask(pdev, DMA_32BIT_MASK);
-       if (rc)
-               goto err_out_regions;
-       rc = pci_set_consistent_dma_mask(pdev, DMA_32BIT_MASK);
-       if (rc)
-               goto err_out_regions;
-
-       probe_ent = kmalloc(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);
-
-       mmio_base = pci_iomap(pdev, 0, 0);
-       if (mmio_base == NULL) {
-               rc = -ENOMEM;
-               goto err_out_free_ent;
-       }
-       base = (unsigned long) mmio_base;
-
-       /*
-        * Due to a bug in the chip, the default cache line size can't be used
-        */
-       pci_write_config_byte(pdev, PCI_CACHE_LINE_SIZE, 0x80);
-
-       probe_ent->sht = &vsc_sata_sht;
-       probe_ent->host_flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
-                               ATA_FLAG_MMIO;
-       probe_ent->port_ops = &vsc_sata_ops;
-       probe_ent->n_ports = 4;
-       probe_ent->irq = pdev->irq;
-       probe_ent->irq_flags = IRQF_SHARED;
-       probe_ent->mmio_base = mmio_base;
-
-       /* We don't care much about the PIO/UDMA masks, but the core won't like us
-        * if we don't fill these
-        */
-       probe_ent->pio_mask = 0x1f;
-       probe_ent->mwdma_mask = 0x07;
-       probe_ent->udma_mask = 0x7f;
-
-       /* We have 4 ports per PCI function */
-       vsc_sata_setup_port(&probe_ent->port[0], base + 1 * VSC_SATA_PORT_OFFSET);
-       vsc_sata_setup_port(&probe_ent->port[1], base + 2 * VSC_SATA_PORT_OFFSET);
-       vsc_sata_setup_port(&probe_ent->port[2], base + 3 * VSC_SATA_PORT_OFFSET);
-       vsc_sata_setup_port(&probe_ent->port[3], base + 4 * VSC_SATA_PORT_OFFSET);
-
-       pci_set_master(pdev);
-
-       /*
-        * Config offset 0x98 is "Extended Control and Status Register 0"
-        * Default value is (1 << 28).  All bits except bit 28 are reserved in
-        * DPA mode.  If bit 28 is set, LED 0 reflects all ports' activity.
-        * If bit 28 is clear, each port has its own LED.
-        */
-       pci_write_config_dword(pdev, 0x98, 0);
-
-       /* FIXME: check ata_device_add return value */
-       ata_device_add(probe_ent);
-       kfree(probe_ent);
-
-       return 0;
-
-err_out_free_ent:
-       kfree(probe_ent);
-err_out_regions:
-       pci_release_regions(pdev);
-err_out:
-       if (!pci_dev_busy)
-               pci_disable_device(pdev);
-       return rc;
-}
-
-
-static const struct pci_device_id vsc_sata_pci_tbl[] = {
-       { PCI_VENDOR_ID_VITESSE, 0x7174,
-         PCI_ANY_ID, PCI_ANY_ID, 0x10600, 0xFFFFFF, 0 },
-       { PCI_VENDOR_ID_INTEL, 0x3200,
-         PCI_ANY_ID, PCI_ANY_ID, 0x10600, 0xFFFFFF, 0 },
-       { }     /* terminate list */
-};
-
-
-static struct pci_driver vsc_sata_pci_driver = {
-       .name                   = DRV_NAME,
-       .id_table               = vsc_sata_pci_tbl,
-       .probe                  = vsc_sata_init_one,
-       .remove                 = ata_pci_remove_one,
-};
-
-
-static int __init vsc_sata_init(void)
-{
-       return pci_register_driver(&vsc_sata_pci_driver);
-}
-
-
-static void __exit vsc_sata_exit(void)
-{
-       pci_unregister_driver(&vsc_sata_pci_driver);
-}
-
-
-MODULE_AUTHOR("Jeremy Higdon");
-MODULE_DESCRIPTION("low-level driver for Vitesse VSC7174 SATA controller");
-MODULE_LICENSE("GPL");
-MODULE_DEVICE_TABLE(pci, vsc_sata_pci_tbl);
-MODULE_VERSION(DRV_VERSION);
-
-module_init(vsc_sata_init);
-module_exit(vsc_sata_exit);