diff --git a/Documentation/DocBook/libata.tmpl b/Documentation/DocBook/libata.tmpl
index e97c32314541..065e8dc23e3a 100644
--- a/Documentation/DocBook/libata.tmpl
+++ b/Documentation/DocBook/libata.tmpl
@@ -868,18 +868,18 @@ and other resources, etc.
libata Library
-!Edrivers/scsi/libata-core.c
+!Edrivers/ata/libata-core.c
libata Core Internals
-!Idrivers/scsi/libata-core.c
+!Idrivers/ata/libata-core.c
libata SCSI translation/emulation
-!Edrivers/scsi/libata-scsi.c
-!Idrivers/scsi/libata-scsi.c
+!Edrivers/ata/libata-scsi.c
+!Idrivers/ata/libata-scsi.c
@@ -1600,12 +1600,12 @@ and other resources, etc.
ata_piix Internals
-!Idrivers/scsi/ata_piix.c
+!Idrivers/ata/ata_piix.c
sata_sil Internals
-!Idrivers/scsi/sata_sil.c
+!Idrivers/ata/sata_sil.c
diff --git a/drivers/Kconfig b/drivers/Kconfig
index 8b11cebe65df..263e86ddc1a4 100644
--- a/drivers/Kconfig
+++ b/drivers/Kconfig
@@ -18,6 +18,8 @@ source "drivers/ide/Kconfig"
source "drivers/scsi/Kconfig"
+source "drivers/ata/Kconfig"
+
source "drivers/cdrom/Kconfig"
source "drivers/md/Kconfig"
diff --git a/drivers/Makefile b/drivers/Makefile
index fc2d744a4e4a..4ac14dab3079 100644
--- a/drivers/Makefile
+++ b/drivers/Makefile
@@ -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
index 000000000000..5a8bdac5f5e8
--- /dev/null
+++ b/drivers/ata/Kconfig
@@ -0,0 +1,484 @@
+#
+# SATA/PATA driver configuration
+#
+
+menu "Serial ATA (prod) and Parallel ATA (experimental) drivers"
+
+config ATA
+ tristate "ATA device support"
+ select 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.
+
+if ATA
+
+config SATA_AHCI
+ tristate "AHCI SATA support"
+ depends on PCI
+ help
+ This option enables support for AHCI Serial ATA.
+
+ If unsure, say N.
+
+config SATA_SVW
+ tristate "ServerWorks Frodo / Apple K2 SATA support"
+ depends on PCI
+ help
+ This option enables support for Broadcom/Serverworks/Apple K2
+ SATA support.
+
+ If unsure, say N.
+
+config ATA_PIIX
+ tristate "Intel PIIX/ICH SATA support"
+ depends on 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 SATA_MV
+ tristate "Marvell SATA support (HIGHLY EXPERIMENTAL)"
+ depends on 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 SATA_NV
+ tristate "NVIDIA SATA support"
+ depends on PCI
+ help
+ This option enables support for NVIDIA Serial ATA.
+
+ If unsure, say N.
+
+config PDC_ADMA
+ tristate "Pacific Digital ADMA support"
+ depends on PCI
+ help
+ This option enables support for Pacific Digital ADMA controllers
+
+ If unsure, say N.
+
+config SATA_QSTOR
+ tristate "Pacific Digital SATA QStor support"
+ depends on PCI
+ help
+ This option enables support for Pacific Digital Serial ATA QStor.
+
+ If unsure, say N.
+
+config SATA_PROMISE
+ tristate "Promise SATA TX2/TX4 support"
+ depends on PCI
+ help
+ This option enables support for Promise Serial ATA TX2/TX4.
+
+ If unsure, say N.
+
+config SATA_SX4
+ tristate "Promise SATA SX4 support"
+ depends on PCI && EXPERIMENTAL
+ help
+ This option enables support for Promise Serial ATA SX4.
+
+ If unsure, say N.
+
+config SATA_SIL
+ tristate "Silicon Image SATA support"
+ depends on PCI
+ help
+ This option enables support for Silicon Image Serial ATA.
+
+ If unsure, say N.
+
+config SATA_SIL24
+ tristate "Silicon Image 3124/3132 SATA support"
+ depends on PCI
+ help
+ This option enables support for Silicon Image 3124/3132 Serial ATA.
+
+ If unsure, say N.
+
+config SATA_SIS
+ tristate "SiS 964/180 SATA support"
+ depends on PCI
+ help
+ This option enables support for SiS Serial ATA 964/180.
+
+ If unsure, say N.
+
+config SATA_ULI
+ tristate "ULi Electronics SATA support"
+ depends on PCI
+ help
+ This option enables support for ULi Electronics SATA.
+
+ If unsure, say N.
+
+config SATA_VIA
+ tristate "VIA SATA support"
+ depends on PCI
+ help
+ This option enables support for VIA Serial ATA.
+
+ If unsure, say N.
+
+config SATA_VITESSE
+ tristate "VITESSE VSC-7174 / INTEL 31244 SATA support"
+ depends on PCI
+ help
+ This option enables support for Vitesse VSC7174 and Intel 31244 Serial ATA.
+
+ If unsure, say N.
+
+config SATA_INTEL_COMBINED
+ bool
+ depends on IDE=y && !BLK_DEV_IDE_SATA && (SATA_AHCI || ATA_PIIX)
+ default y
+
+config PATA_ALI
+ tristate "ALi PATA support (Experimental)"
+ depends on PCI && EXPERIMENTAL
+ help
+ This option enables support for the ALi ATA interfaces
+ found on the many ALi chipsets.
+
+ If unsure, say N.
+
+config PATA_AMD
+ tristate "AMD/NVidia PATA support (Experimental)"
+ depends on PCI
+ help
+ This option enables support for the AMD and NVidia PATA
+ interfaces found on the chipsets for Athlon/Athlon64.
+
+ If unsure, say N.
+
+config PATA_ARTOP
+ tristate "ARTOP 6210/6260 PATA support (Experimental)"
+ depends on PCI && EXPERIMENTAL
+ help
+ This option enables support for ARTOP PATA controllers.
+
+ If unsure, say N.
+
+config PATA_ATIIXP
+ tristate "ATI PATA support (Experimental)"
+ depends on PCI && EXPERIMENTAL
+ help
+ This option enables support for the ATI ATA interfaces
+ found on the many ATI chipsets.
+
+ If unsure, say N.
+
+config PATA_CMD64X
+ tristate "CMD64x PATA support (Very Experimental)"
+ depends on PCI&& EXPERIMENTAL
+ help
+ This option enables support for the CMD64x series chips
+ except for the CMD640.
+
+ If unsure, say N.
+
+config PATA_CS5520
+ tristate "CS5510/5520 PATA support"
+ depends on PCI
+ help
+ This option enables support for the Cyrix 5510/5520
+ companion chip used with the MediaGX/Geode processor family.
+
+ If unsure, say N.
+
+config PATA_CS5530
+ tristate "CS5530 PATA support (Experimental)"
+ depends on PCI && EXPERIMENTAL
+ help
+ This option enables support for the Cyrix/NatSemi/AMD CS5530
+ companion chip used with the MediaGX/Geode processor family.
+
+ If unsure, say N.
+
+config PATA_CS5535
+ tristate "CS5535 PATA support (Experimental)"
+ depends on PCI && X86 && !X86_64 && EXPERIMENTAL
+ help
+ This option enables support for the NatSemi/AMD CS5535
+ companion chip used with the Geode processor family.
+
+ If unsure, say N.
+
+config PATA_CYPRESS
+ tristate "Cypress CY82C693 PATA support (Very Experimental)"
+ depends on PCI && EXPERIMENTAL
+ help
+ This option enables support for the Cypress/Contaq CY82C693
+ chipset found in some Alpha systems
+
+ If unsure, say N.
+
+config PATA_EFAR
+ tristate "EFAR SLC90E66 support"
+ depends on PCI
+ help
+ This option enables support for the EFAR SLC90E66
+ IDE controller found on some older machines.
+
+ If unsure, say N.
+
+config ATA_GENERIC
+ tristate "Generic ATA support"
+ depends on PCI
+ help
+ This option enables support for generic BIOS configured
+ ATA controllers via the new ATA layer
+
+ If unsure, say N.
+
+config PATA_HPT366
+ tristate "HPT 366/368 PATA support (Very Experimental)"
+ depends on PCI && EXPERIMENTAL
+ help
+ This option enables support for the HPT 366 and 368
+ PATA controllers via the new ATA layer.
+
+ If unsure, say N.
+
+config PATA_HPT37X
+ tristate "HPT 370/370A/371/372/374/302 PATA support (Very Experimental)"
+ depends on PCI && EXPERIMENTAL
+ help
+ This option enables support for the majority of the later HPT
+ PATA controllers via the new ATA layer.
+
+ If unsure, say N.
+
+config PATA_HPT3X2N
+ tristate "HPT 372N/302N PATA support (Very Experimental)"
+ depends on PCI && EXPERIMENTAL
+ help
+ This option enables support for the N variant HPT PATA
+ controllers via the new ATA layer
+
+ If unsure, say N.
+
+config PATA_HPT3X3
+ tristate "HPT 343/363 PATA support (Experimental)"
+ depends on PCI
+ help
+ This option enables support for the HPT 343/363
+ PATA controllers via the new ATA layer
+
+ If unsure, say N.
+
+config PATA_ISAPNP
+ tristate "ISA Plug and Play PATA support (Very Experimental)"
+ depends on EXPERIMENTAL && ISAPNP
+ help
+ This option enables support for ISA plug & play ATA
+ controllers such as those found on old soundcards.
+
+ If unsure, say N.
+
+config PATA_IT821X
+ tristate "IT821x PATA support (Experimental)"
+ depends on PCI && EXPERIMENTAL
+ help
+ This option enables support for the ITE 8211 and 8212
+ PATA controllers via the new ATA layer, including RAID
+ mode.
+
+ If unsure, say N.
+
+config PATA_JMICRON
+ tristate "JMicron PATA support"
+ depends on PCI
+ help
+ Enable support for the JMicron IDE controller, via the new
+ ATA layer.
+
+ If unsure, say N.
+
+config PATA_LEGACY
+ tristate "Legacy ISA PATA support (Experimental)"
+ depends on PCI && EXPERIMENTAL
+ help
+ This option enables support for ISA/VLB bus legacy PATA
+ ports and allows them to be accessed via the new ATA layer.
+
+ If unsure, say N.
+
+config PATA_TRIFLEX
+ tristate "Compaq Triflex PATA support"
+ depends on PCI
+ help
+ Enable support for the Compaq 'Triflex' IDE controller as found
+ on many Compaq Pentium-Pro systems, via the new ATA layer.
+
+ If unsure, say N.
+
+config PATA_MPIIX
+ tristate "Intel PATA MPIIX support"
+ depends on PCI
+ help
+ This option enables support for MPIIX PATA support.
+
+ If unsure, say N.
+
+config PATA_OLDPIIX
+ tristate "Intel PATA old PIIX support (Experimental)"
+ depends on PCI && EXPERIMENTAL
+ help
+ This option enables support for old(?) PIIX PATA support.
+
+ If unsure, say N.
+
+config PATA_NETCELL
+ tristate "NETCELL Revolution RAID support"
+ depends on PCI
+ help
+ This option enables support for the Netcell Revolution RAID
+ PATA controller.
+
+ If unsure, say N.
+
+config PATA_NS87410
+ tristate "Nat Semi NS87410 PATA support (Experimental)"
+ depends on PCI && EXPERIMENTAL
+ help
+ This option enables support for the National Semiconductor
+ NS87410 PCI-IDE controller.
+
+ If unsure, say N.
+
+config PATA_OPTI
+ tristate "OPTI621/6215 PATA support (Very Experimental)"
+ depends on PCI && EXPERIMENTAL
+ help
+ This option enables full PIO support for the early Opti ATA
+ controllers found on some old motherboards.
+
+ If unsure, say N.
+
+config PATA_OPTIDMA
+ tristate "OPTI FireStar PATA support (Veyr Experimental)"
+ depends on PCI && EXPERIMENTAL
+ help
+ This option enables DMA/PIO support for the later OPTi
+ controllers found on some old motherboards and in some
+ latops
+
+ If unsure, say N.
+
+config PATA_PCMCIA
+ tristate "PCMCIA PATA support"
+ depends on PCMCIA
+ help
+ This option enables support for PCMCIA ATA interfaces, including
+ compact flash card adapters via the new ATA layer.
+
+ If unsure, say N.
+
+config PATA_PDC_OLD
+ tristate "Older Promise PATA controller support (Very Experimental)"
+ depends on PCI && EXPERIMENTAL
+ help
+ This option enables support for the Promise 20246, 20262, 20263,
+ 20265 and 20267 adapters.
+
+ If unsure, say N.
+
+config PATA_QDI
+ tristate "QDI VLB PATA support"
+ help
+ Support for QDI 6500 and 6580 PATA controllers on VESA local bus.
+
+config PATA_RADISYS
+ tristate "RADISYS 82600 PATA support (Very experimental)"
+ depends on PCI && EXPERIMENTAL
+ help
+ This option enables support for the RADISYS 82600
+ PATA controllers via the new ATA layer
+
+ If unsure, say N.
+
+config PATA_RZ1000
+ tristate "PC Tech RZ1000 PATA support"
+ depends on PCI
+ help
+ This option enables basic support for the PC Tech RZ1000/1
+ PATA controllers via the new ATA layer
+
+ If unsure, say N.
+
+config PATA_SC1200
+ tristate "SC1200 PATA support (Raving Lunatic)"
+ depends on PCI && EXPERIMENTAL
+ help
+ This option enables support for the NatSemi/AMD SC1200 SoC
+ companion chip used with the Geode processor family.
+
+ If unsure, say N.
+
+config PATA_SERVERWORKS
+ tristate "SERVERWORKS OSB4/CSB5/CSB6/HT1000 PATA support (Experimental)"
+ depends on PCI && EXPERIMENTAL
+ help
+ This option enables support for the Serverworks OSB4/CSB5/CSB6 and
+ HT1000 PATA controllers, via the new ATA layer.
+
+ If unsure, say N.
+
+config PATA_PDC2027X
+ tristate "Promise PATA 2027x support"
+ depends on PCI
+ help
+ This option enables support for Promise PATA pdc20268 to pdc20277 host adapters.
+
+ If unsure, say N.
+
+config PATA_SIL680
+ tristate "CMD / Silicon Image 680 PATA support"
+ depends on PCI
+ help
+ This option enables support for CMD / Silicon Image 680 PATA.
+
+ If unsure, say N.
+
+config PATA_SIS
+ tristate "SiS PATA support (Experimental)"
+ depends on PCI && EXPERIMENTAL
+ help
+ This option enables support for SiS PATA controllers
+
+ If unsure, say N.
+
+config PATA_VIA
+ tristate "VIA PATA support"
+ depends on PCI
+ help
+ This option enables support for the VIA PATA interfaces
+ found on the many VIA chipsets.
+
+ If unsure, say N.
+
+config PATA_WINBOND
+ tristate "Winbond SL82C105 PATA support"
+ depends on PCI
+ help
+ This option enables support for SL82C105 PATA devices found in the
+ Netwinder and some other systems
+
+ If unsure, say N.
+
+endif
+endmenu
+
diff --git a/drivers/ata/Makefile b/drivers/ata/Makefile
new file mode 100644
index 000000000000..72243a677f9b
--- /dev/null
+++ b/drivers/ata/Makefile
@@ -0,0 +1,62 @@
+
+obj-$(CONFIG_ATA) += libata.o
+
+obj-$(CONFIG_SATA_AHCI) += ahci.o
+obj-$(CONFIG_SATA_SVW) += sata_svw.o
+obj-$(CONFIG_ATA_PIIX) += ata_piix.o
+obj-$(CONFIG_SATA_PROMISE) += sata_promise.o
+obj-$(CONFIG_SATA_QSTOR) += sata_qstor.o
+obj-$(CONFIG_SATA_SIL) += sata_sil.o
+obj-$(CONFIG_SATA_SIL24) += sata_sil24.o
+obj-$(CONFIG_SATA_VIA) += sata_via.o
+obj-$(CONFIG_SATA_VITESSE) += sata_vsc.o
+obj-$(CONFIG_SATA_SIS) += sata_sis.o
+obj-$(CONFIG_SATA_SX4) += sata_sx4.o
+obj-$(CONFIG_SATA_NV) += sata_nv.o
+obj-$(CONFIG_SATA_ULI) += sata_uli.o
+obj-$(CONFIG_SATA_MV) += sata_mv.o
+obj-$(CONFIG_PDC_ADMA) += pdc_adma.o
+
+obj-$(CONFIG_PATA_ALI) += pata_ali.o
+obj-$(CONFIG_PATA_AMD) += pata_amd.o
+obj-$(CONFIG_PATA_ARTOP) += pata_artop.o
+obj-$(CONFIG_PATA_ATIIXP) += pata_atiixp.o
+obj-$(CONFIG_PATA_CMD64X) += pata_cmd64x.o
+obj-$(CONFIG_PATA_CS5520) += pata_cs5520.o
+obj-$(CONFIG_PATA_CS5530) += pata_cs5530.o
+obj-$(CONFIG_PATA_CS5535) += pata_cs5535.o
+obj-$(CONFIG_PATA_CYPRESS) += pata_cypress.o
+obj-$(CONFIG_PATA_EFAR) += pata_efar.o
+obj-$(CONFIG_PATA_HPT366) += pata_hpt366.o
+obj-$(CONFIG_PATA_HPT37X) += pata_hpt37x.o
+obj-$(CONFIG_PATA_HPT3X2N) += pata_hpt3x2n.o
+obj-$(CONFIG_PATA_HPT3X3) += pata_hpt3x3.o
+obj-$(CONFIG_PATA_ISAPNP) += pata_isapnp.o
+obj-$(CONFIG_PATA_IT821X) += pata_it821x.o
+obj-$(CONFIG_PATA_JMICRON) += pata_jmicron.o
+obj-$(CONFIG_PATA_NETCELL) += pata_netcell.o
+obj-$(CONFIG_PATA_NS87410) += pata_ns87410.o
+obj-$(CONFIG_PATA_OPTI) += pata_opti.o
+obj-$(CONFIG_PATA_OPTIDMA) += pata_optidma.o
+obj-$(CONFIG_PATA_MPIIX) += pata_mpiix.o
+obj-$(CONFIG_PATA_OLDPIIX) += pata_oldpiix.o
+obj-$(CONFIG_PATA_PCMCIA) += pata_pcmcia.o
+obj-$(CONFIG_PATA_PDC2027X) += pata_pdc2027x.o
+obj-$(CONFIG_PATA_PDC_OLD) += pata_pdc202xx_old.o
+obj-$(CONFIG_PATA_QDI) += pata_qdi.o
+obj-$(CONFIG_PATA_RADISYS) += pata_radisys.o
+obj-$(CONFIG_PATA_RZ1000) += pata_rz1000.o
+obj-$(CONFIG_PATA_SC1200) += pata_sc1200.o
+obj-$(CONFIG_PATA_SERVERWORKS) += pata_serverworks.o
+obj-$(CONFIG_PATA_SIL680) += pata_sil680.o
+obj-$(CONFIG_PATA_VIA) += pata_via.o
+obj-$(CONFIG_PATA_WINBOND) += pata_sl82c105.o
+obj-$(CONFIG_PATA_SIS) += pata_sis.o
+obj-$(CONFIG_PATA_TRIFLEX) += pata_triflex.o
+# Should be last but one libata driver
+obj-$(CONFIG_ATA_GENERIC) += ata_generic.o
+# Should be last libata driver
+obj-$(CONFIG_PATA_LEGACY) += pata_legacy.o
+
+libata-objs := libata-core.o libata-scsi.o libata-sff.o libata-eh.o
+
diff --git a/drivers/scsi/ahci.c b/drivers/ata/ahci.c
similarity index 79%
rename from drivers/scsi/ahci.c
rename to drivers/ata/ahci.c
index 904c25fb4ba4..1aabc81d82f1 100644
--- a/drivers/scsi/ahci.c
+++ b/drivers/ata/ahci.c
@@ -92,7 +92,9 @@ enum {
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 */
@@ -155,6 +157,7 @@ enum {
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 */
@@ -212,6 +215,10 @@ 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 = {
@@ -231,6 +238,8 @@ static struct scsi_host_template ahci_sht = {
.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 = {
@@ -257,6 +266,9 @@ static const struct ata_port_operations ahci_ops = {
.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,
};
@@ -265,7 +277,7 @@ static const struct ata_port_info ahci_port_info[] = {
/* board_ahci */
{
.sht = &ahci_sht,
- .host_flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
+ .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 */
@@ -275,7 +287,7 @@ static const struct ata_port_info ahci_port_info[] = {
/* board_ahci_vt8251 */
{
.sht = &ahci_sht,
- .host_flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
+ .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,
@@ -350,6 +362,14 @@ static const struct pci_device_id ahci_pci_tbl[] = {
{ 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 */
};
@@ -358,6 +378,8 @@ 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,
};
@@ -372,108 +394,6 @@ static inline void __iomem *ahci_port_base (void __iomem *base, unsigned int por
return (void __iomem *) ahci_port_base_ul((unsigned long)base, port);
}
-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;
-
- if (hpriv->cap & HOST_CAP_64)
- writel((pp->cmd_slot_dma >> 16) >> 16, port_mmio + PORT_LST_ADDR_HI);
- writel(pp->cmd_slot_dma & 0xffffffff, port_mmio + PORT_LST_ADDR);
- readl(port_mmio + PORT_LST_ADDR); /* flush */
-
- if (hpriv->cap & HOST_CAP_64)
- writel((pp->rx_fis_dma >> 16) >> 16, port_mmio + PORT_FIS_ADDR_HI);
- writel(pp->rx_fis_dma & 0xffffffff, port_mmio + PORT_FIS_ADDR);
- readl(port_mmio + PORT_FIS_ADDR); /* flush */
-
- writel(PORT_CMD_ICC_ACTIVE | PORT_CMD_FIS_RX |
- PORT_CMD_POWER_ON | PORT_CMD_SPIN_UP |
- PORT_CMD_START, port_mmio + PORT_CMD);
- readl(port_mmio + PORT_CMD); /* flush */
-
- return 0;
-}
-
-
-static void ahci_port_stop(struct ata_port *ap)
-{
- struct device *dev = ap->host_set->dev;
- 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);
- u32 tmp;
-
- tmp = readl(port_mmio + PORT_CMD);
- tmp &= ~(PORT_CMD_START | PORT_CMD_FIS_RX);
- writel(tmp, port_mmio + PORT_CMD);
- readl(port_mmio + PORT_CMD); /* flush */
-
- /* spec says 500 msecs for each PORT_CMD_{START,FIS_RX} bit, so
- * this is slightly incorrect.
- */
- msleep(500);
-
- 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 u32 ahci_scr_read (struct ata_port *ap, unsigned int sc_reg_in)
{
unsigned int sc_reg;
@@ -508,43 +428,256 @@ static void ahci_scr_write (struct ata_port *ap, unsigned int sc_reg_in,
writel(val, (void __iomem *) ap->ioaddr.scr_addr + (sc_reg * 4));
}
-static int ahci_stop_engine(struct ata_port *ap)
+static void ahci_start_engine(void __iomem *port_mmio)
{
- void __iomem *mmio = ap->host_set->mmio_base;
- void __iomem *port_mmio = ahci_port_base(mmio, ap->port_no);
- int work;
- u32 tmp;
-
- tmp = readl(port_mmio + PORT_CMD);
- tmp &= ~PORT_CMD_START;
- writel(tmp, port_mmio + PORT_CMD);
-
- /* wait for engine to stop. TODO: this could be
- * as long as 500 msec
- */
- work = 1000;
- while (work-- > 0) {
- tmp = readl(port_mmio + PORT_CMD);
- if ((tmp & PORT_CMD_LIST_ON) == 0)
- return 0;
- udelay(10);
- }
-
- return -EIO;
-}
-
-static void ahci_start_engine(struct ata_port *ap)
-{
- void __iomem *mmio = ap->host_set->mmio_base;
- void __iomem *port_mmio = ahci_port_base(mmio, ap->port_no);
u32 tmp;
+ /* 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;
@@ -576,7 +709,7 @@ static void ahci_fill_cmd_slot(struct ahci_port_priv *pp, unsigned int tag,
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;
+ struct ahci_host_priv *hpriv = ap->host->private_data;
u32 tmp;
if (!(hpriv->cap & HOST_CAP_CLO))
@@ -608,7 +741,7 @@ static int ahci_prereset(struct ata_port *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 *mmio = ap->host->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;
@@ -626,7 +759,7 @@ static int ahci_softreset(struct ata_port *ap, unsigned int *class)
}
/* prepare for SRST (AHCI-1.1 10.4.1) */
- rc = ahci_stop_engine(ap);
+ rc = ahci_stop_engine(port_mmio);
if (rc) {
reason = "failed to stop engine";
goto fail_restart;
@@ -647,7 +780,7 @@ static int ahci_softreset(struct ata_port *ap, unsigned int *class)
}
/* restart engine */
- ahci_start_engine(ap);
+ ahci_start_engine(port_mmio);
ata_tf_init(ap->device, &tf);
fis = pp->cmd_tbl;
@@ -706,7 +839,7 @@ static int ahci_softreset(struct ata_port *ap, unsigned int *class)
return 0;
fail_restart:
- ahci_start_engine(ap);
+ ahci_start_engine(port_mmio);
fail:
ata_port_printk(ap, KERN_ERR, "softreset failed (%s)\n", reason);
return rc;
@@ -717,11 +850,13 @@ 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->mmio_base;
+ void __iomem *port_mmio = ahci_port_base(mmio, ap->port_no);
int rc;
DPRINTK("ENTER\n");
- ahci_stop_engine(ap);
+ ahci_stop_engine(port_mmio);
/* clear D2H reception area to properly wait for D2H FIS */
ata_tf_init(ap->device, &tf);
@@ -730,7 +865,7 @@ static int ahci_hardreset(struct ata_port *ap, unsigned int *class)
rc = sata_std_hardreset(ap, class);
- ahci_start_engine(ap);
+ ahci_start_engine(port_mmio);
if (rc == 0 && ata_port_online(ap))
*class = ahci_dev_classify(ap);
@@ -904,7 +1039,7 @@ static void ahci_error_intr(struct ata_port *ap, u32 irq_stat)
static void ahci_host_intr(struct ata_port *ap)
{
- void __iomem *mmio = ap->host_set->mmio_base;
+ void __iomem *mmio = ap->host->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;
@@ -940,7 +1075,7 @@ static void ahci_host_intr(struct ata_port *ap)
return;
/* ignore interim PIO setup fis interrupts */
- if (ata_tag_valid(ap->active_tag) && (status & PORT_IRQ_PIOS_FIS))
+ if (ata_tag_valid(ap->active_tag) && (status & PORT_IRQ_PIOS_FIS))
return;
if (ata_ratelimit())
@@ -956,7 +1091,7 @@ static void ahci_irq_clear(struct ata_port *ap)
static irqreturn_t ahci_interrupt(int irq, void *dev_instance, struct pt_regs *regs)
{
- struct ata_host_set *host_set = dev_instance;
+ struct ata_host *host = dev_instance;
struct ahci_host_priv *hpriv;
unsigned int i, handled = 0;
void __iomem *mmio;
@@ -964,8 +1099,8 @@ static irqreturn_t ahci_interrupt(int irq, void *dev_instance, struct pt_regs *r
VPRINTK("ENTER\n");
- hpriv = host_set->private_data;
- mmio = host_set->mmio_base;
+ hpriv = host->private_data;
+ mmio = host->mmio_base;
/* sigh. 0xffffffff is a valid return from h/w */
irq_stat = readl(mmio + HOST_IRQ_STAT);
@@ -973,22 +1108,22 @@ static irqreturn_t ahci_interrupt(int irq, void *dev_instance, struct pt_regs *r
if (!irq_stat)
return IRQ_NONE;
- spin_lock(&host_set->lock);
+ spin_lock(&host->lock);
- for (i = 0; i < host_set->n_ports; i++) {
+ for (i = 0; i < host->n_ports; i++) {
struct ata_port *ap;
if (!(irq_stat & (1 << i)))
continue;
- ap = host_set->ports[i];
+ ap = host->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,
+ dev_printk(KERN_WARNING, host->dev,
"interrupt on disabled port %u\n", i);
}
@@ -1000,7 +1135,7 @@ static irqreturn_t ahci_interrupt(int irq, void *dev_instance, struct pt_regs *r
handled = 1;
}
- spin_unlock(&host_set->lock);
+ spin_unlock(&host->lock);
VPRINTK("EXIT\n");
@@ -1022,7 +1157,7 @@ static unsigned int ahci_qc_issue(struct ata_queued_cmd *qc)
static void ahci_freeze(struct ata_port *ap)
{
- void __iomem *mmio = ap->host_set->mmio_base;
+ void __iomem *mmio = ap->host->mmio_base;
void __iomem *port_mmio = ahci_port_base(mmio, ap->port_no);
/* turn IRQ off */
@@ -1031,7 +1166,7 @@ static void ahci_freeze(struct ata_port *ap)
static void ahci_thaw(struct ata_port *ap)
{
- void __iomem *mmio = ap->host_set->mmio_base;
+ void __iomem *mmio = ap->host->mmio_base;
void __iomem *port_mmio = ahci_port_base(mmio, ap->port_no);
u32 tmp;
@@ -1046,10 +1181,13 @@ static void ahci_thaw(struct ata_port *ap)
static void ahci_error_handler(struct ata_port *ap)
{
+ void __iomem *mmio = ap->host->mmio_base;
+ void __iomem *port_mmio = ahci_port_base(mmio, ap->port_no);
+
if (!(ap->pflags & ATA_PFLAG_FROZEN)) {
/* restart engine */
- ahci_stop_engine(ap);
- ahci_start_engine(ap);
+ ahci_stop_engine(port_mmio);
+ ahci_start_engine(port_mmio);
}
/* perform recovery */
@@ -1060,17 +1198,178 @@ static void ahci_error_handler(struct ata_port *ap)
static void ahci_post_internal_cmd(struct ata_queued_cmd *qc)
{
struct ata_port *ap = qc->ap;
+ void __iomem *mmio = ap->host->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(ap);
- ahci_start_engine(ap);
+ 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->private_data;
+ struct ahci_port_priv *pp = ap->private_data;
+ void __iomem *mmio = ap->host->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->private_data;
+ void __iomem *mmio = ap->host->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 *host = dev_get_drvdata(&pdev->dev);
+ void __iomem *mmio = host->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 *host = dev_get_drvdata(&pdev->dev);
+ struct ahci_host_priv *hpriv = host->private_data;
+ void __iomem *mmio = host->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->n_ports, hpriv->cap);
+ }
+
+ ata_host_resume(host);
+
+ return 0;
+}
+
+static int ahci_port_start(struct ata_port *ap)
+{
+ struct device *dev = ap->host->dev;
+ struct ahci_host_priv *hpriv = ap->host->private_data;
+ struct ahci_port_priv *pp;
+ void __iomem *mmio = ap->host->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->dev;
+ struct ahci_host_priv *hpriv = ap->host->private_data;
+ struct ahci_port_priv *pp = ap->private_data;
+ void __iomem *mmio = ap->host->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)
{
@@ -1089,47 +1388,12 @@ 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;
- u32 tmp, cap_save;
- unsigned int i, j, using_dac;
+ unsigned int i, using_dac;
int rc;
- void __iomem *port_mmio;
- 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;
-
- pci_read_config_word(pdev, 0x92, &tmp16);
- tmp16 |= 0xf;
- pci_write_config_word(pdev, 0x92, tmp16);
- }
+ rc = ahci_reset_controller(mmio, pdev);
+ if (rc)
+ return rc;
hpriv->cap = readl(mmio + HOST_CAP);
hpriv->port_map = readl(mmio + HOST_PORTS_IMPL);
@@ -1165,63 +1429,10 @@ static int ahci_host_init(struct ata_probe_ent *probe_ent)
}
}
- for (i = 0; i < probe_ent->n_ports; i++) {
-#if 0 /* BIOSen initialize this incorrectly */
- if (!(hpriv->port_map & (1 << i)))
- continue;
-#endif
+ for (i = 0; i < probe_ent->n_ports; i++)
+ ahci_setup_port(&probe_ent->port[i], (unsigned long) mmio, i);
- port_mmio = ahci_port_base(mmio, i);
- VPRINTK("mmio %p port_mmio %p\n", mmio, port_mmio);
-
- ahci_setup_port(&probe_ent->port[i],
- (unsigned long) mmio, i);
-
- /* make sure port is not active */
- tmp = readl(port_mmio + PORT_CMD);
- VPRINTK("PORT_CMD 0x%x\n", tmp);
- if (tmp & (PORT_CMD_LIST_ON | PORT_CMD_FIS_ON |
- PORT_CMD_FIS_RX | PORT_CMD_START)) {
- tmp &= ~(PORT_CMD_LIST_ON | PORT_CMD_FIS_ON |
- PORT_CMD_FIS_RX | PORT_CMD_START);
- writel(tmp, port_mmio + PORT_CMD);
- readl(port_mmio + PORT_CMD); /* flush */
-
- /* spec says 500 msecs for each bit, so
- * this is slightly incorrect.
- */
- msleep(500);
- }
-
- writel(PORT_CMD_SPIN_UP, port_mmio + PORT_CMD);
-
- j = 0;
- while (j < 100) {
- msleep(10);
- tmp = readl(port_mmio + PORT_SCR_STAT);
- if ((tmp & 0xf) == 0x3)
- break;
- j++;
- }
-
- tmp = readl(port_mmio + PORT_SCR_ERR);
- VPRINTK("PORT_SCR_ERR 0x%x\n", tmp);
- writel(tmp, port_mmio + PORT_SCR_ERR);
-
- /* ack any pending irq events for this port */
- 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);
+ ahci_init_controller(mmio, pdev, probe_ent->n_ports, hpriv->cap);
pci_set_master(pdev);
@@ -1370,7 +1581,7 @@ static int ahci_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
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->port_flags = ahci_port_info[board_idx].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;
@@ -1388,9 +1599,9 @@ static int ahci_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
if (rc)
goto err_out_hpriv;
- if (!(probe_ent->host_flags & AHCI_FLAG_NO_NCQ) &&
+ if (!(probe_ent->port_flags & AHCI_FLAG_NO_NCQ) &&
(hpriv->cap & HOST_CAP_NCQ))
- probe_ent->host_flags |= ATA_FLAG_NCQ;
+ probe_ent->port_flags |= ATA_FLAG_NCQ;
ahci_print_info(probe_ent);
@@ -1421,27 +1632,27 @@ err_out:
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;
+ struct ata_host *host = dev_get_drvdata(dev);
+ struct ahci_host_priv *hpriv = host->private_data;
unsigned int i;
int have_msi;
- for (i = 0; i < host_set->n_ports; i++)
- ata_port_detach(host_set->ports[i]);
+ for (i = 0; i < host->n_ports; i++)
+ ata_port_detach(host->ports[i]);
have_msi = hpriv->flags & AHCI_FLAG_MSI;
- free_irq(host_set->irq, host_set);
+ free_irq(host->irq, host);
- for (i = 0; i < host_set->n_ports; i++) {
- struct ata_port *ap = host_set->ports[i];
+ for (i = 0; i < host->n_ports; i++) {
+ struct ata_port *ap = host->ports[i];
- ata_scsi_release(ap->host);
- scsi_host_put(ap->host);
+ ata_scsi_release(ap->scsi_host);
+ scsi_host_put(ap->scsi_host);
}
kfree(hpriv);
- pci_iounmap(pdev, host_set->mmio_base);
- kfree(host_set);
+ pci_iounmap(pdev, host->mmio_base);
+ kfree(host);
if (have_msi)
pci_disable_msi(pdev);
@@ -1454,7 +1665,7 @@ static void ahci_remove_one (struct pci_dev *pdev)
static int __init ahci_init(void)
{
- return pci_module_init(&ahci_pci_driver);
+ return pci_register_driver(&ahci_pci_driver);
}
static void __exit ahci_exit(void)
diff --git a/drivers/ata/ata_generic.c b/drivers/ata/ata_generic.c
new file mode 100644
index 000000000000..1d1c30a2fcd0
--- /dev/null
+++ b/drivers/ata/ata_generic.c
@@ -0,0 +1,252 @@
+/*
+ * ata_generic.c - Generic PATA/SATA controller driver.
+ * Copyright 2005 Red Hat Inc , all rights reserved.
+ *
+ * Elements from ide/pci/generic.c
+ * Copyright (C) 2001-2002 Andre Hedrick
+ * Portions (C) Copyright 2002 Red Hat Inc
+ *
+ * May be copied or modified under the terms of the GNU General Public License
+ *
+ * Driver for PCI IDE interfaces implementing the standard bus mastering
+ * interface functionality. This assumes the BIOS did the drive set up and
+ * tuning for us. By default we do not grab all IDE class devices as they
+ * may have other drivers or need fixups to avoid problems. Instead we keep
+ * a default list of stuff without documentation/driver that appears to
+ * work.
+ */
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#define DRV_NAME "ata_generic"
+#define DRV_VERSION "0.2.6"
+
+/*
+ * A generic parallel ATA driver using libata
+ */
+
+/**
+ * generic_pre_reset - probe begin
+ * @ap: ATA port
+ *
+ * Set up cable type and use generic probe init
+ */
+
+static int generic_pre_reset(struct ata_port *ap)
+{
+ ap->cbl = ATA_CBL_PATA80;
+ return ata_std_prereset(ap);
+}
+
+
+/**
+ * generic_error_handler - Probe specified port on PATA host controller
+ * @ap: Port to probe
+ * @classes:
+ *
+ * LOCKING:
+ * None (inherited from caller).
+ */
+
+
+static void generic_error_handler(struct ata_port *ap)
+{
+ ata_bmdma_drive_eh(ap, generic_pre_reset, ata_std_softreset, NULL, ata_std_postreset);
+}
+
+/**
+ * generic_set_mode - mode setting
+ * @ap: interface to set up
+ *
+ * Use a non standard set_mode function. We don't want to be tuned.
+ * The BIOS configured everything. Our job is not to fiddle. We
+ * read the dma enabled bits from the PCI configuration of the device
+ * and respect them.
+ */
+
+static void generic_set_mode(struct ata_port *ap)
+{
+ int dma_enabled = 0;
+ int i;
+
+ /* Bits 5 and 6 indicate if DMA is active on master/slave */
+ if (ap->ioaddr.bmdma_addr)
+ dma_enabled = inb(ap->ioaddr.bmdma_addr + ATA_DMA_CMD);
+
+ for (i = 0; i < ATA_MAX_DEVICES; i++) {
+ struct ata_device *dev = &ap->device[i];
+ if (ata_dev_enabled(dev)) {
+ /* We don't really care */
+ dev->pio_mode = XFER_PIO_0;
+ dev->dma_mode = XFER_MW_DMA_0;
+ /* We do need the right mode information for DMA or PIO
+ and this comes from the current configuration flags */
+ if (dma_enabled & (1 << (5 + i))) {
+ dev->xfer_mode = XFER_MW_DMA_0;
+ dev->xfer_shift = ATA_SHIFT_MWDMA;
+ dev->flags &= ~ATA_DFLAG_PIO;
+ } else {
+ dev->xfer_mode = XFER_PIO_0;
+ dev->xfer_shift = ATA_SHIFT_PIO;
+ dev->flags |= ATA_DFLAG_PIO;
+ }
+ }
+ }
+}
+
+static struct scsi_host_template generic_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,
+ .max_sectors = ATA_MAX_SECTORS,
+ .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,
+ .bios_param = ata_std_bios_param,
+};
+
+static struct ata_port_operations generic_port_ops = {
+ .set_mode = generic_set_mode,
+
+ .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,
+
+ .data_xfer = ata_pio_data_xfer,
+
+ .freeze = ata_bmdma_freeze,
+ .thaw = ata_bmdma_thaw,
+ .error_handler = generic_error_handler,
+ .post_internal_cmd = ata_bmdma_post_internal_cmd,
+
+ .qc_prep = ata_qc_prep,
+ .qc_issue = ata_qc_issue_prot,
+ .eng_timeout = ata_eng_timeout,
+ .irq_handler = ata_interrupt,
+ .irq_clear = ata_bmdma_irq_clear,
+
+ .port_start = ata_port_start,
+ .port_stop = ata_port_stop,
+ .host_stop = ata_host_stop
+};
+
+static int all_generic_ide; /* Set to claim all devices */
+
+/**
+ * ata_generic_init - attach generic IDE
+ * @dev: PCI device found
+ * @id: match entry
+ *
+ * Called each time a matching IDE interface is found. We check if the
+ * interface is one we wish to claim and if so we perform any chip
+ * specific hacks then let the ATA layer do the heavy lifting.
+ */
+
+static int ata_generic_init_one(struct pci_dev *dev, const struct pci_device_id *id)
+{
+ u16 command;
+ static struct ata_port_info info = {
+ .sht = &generic_sht,
+ .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST,
+ .pio_mask = 0x1f,
+ .mwdma_mask = 0x07,
+ .udma_mask = 0x3f,
+ .port_ops = &generic_port_ops
+ };
+ static struct ata_port_info *port_info[2] = { &info, &info };
+
+ /* Don't use the generic entry unless instructed to do so */
+ if (id->driver_data == 1 && all_generic_ide == 0)
+ return -ENODEV;
+
+ /* Devices that need care */
+ if (dev->vendor == PCI_VENDOR_ID_UMC &&
+ dev->device == PCI_DEVICE_ID_UMC_UM8886A &&
+ (!(PCI_FUNC(dev->devfn) & 1)))
+ return -ENODEV;
+
+ if (dev->vendor == PCI_VENDOR_ID_OPTI &&
+ dev->device == PCI_DEVICE_ID_OPTI_82C558 &&
+ (!(PCI_FUNC(dev->devfn) & 1)))
+ return -ENODEV;
+
+ /* Don't re-enable devices in generic mode or we will break some
+ motherboards with disabled and unused IDE controllers */
+ pci_read_config_word(dev, PCI_COMMAND, &command);
+ if (!(command & PCI_COMMAND_IO))
+ return -ENODEV;
+
+ if (dev->vendor == PCI_VENDOR_ID_AL)
+ ata_pci_clear_simplex(dev);
+
+ return ata_pci_init_one(dev, port_info, 2);
+}
+
+static struct pci_device_id ata_generic[] = {
+ { PCI_DEVICE(PCI_VENDOR_ID_PCTECH, PCI_DEVICE_ID_PCTECH_SAMURAI_IDE), },
+ { PCI_DEVICE(PCI_VENDOR_ID_HOLTEK, PCI_DEVICE_ID_HOLTEK_6565), },
+ { PCI_DEVICE(PCI_VENDOR_ID_UMC, PCI_DEVICE_ID_UMC_UM8673F), },
+ { PCI_DEVICE(PCI_VENDOR_ID_UMC, PCI_DEVICE_ID_UMC_UM8886A), },
+ { PCI_DEVICE(PCI_VENDOR_ID_UMC, PCI_DEVICE_ID_UMC_UM8886BF), },
+ { PCI_DEVICE(PCI_VENDOR_ID_HINT, PCI_DEVICE_ID_HINT_VXPROII_IDE), },
+ { PCI_DEVICE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C561), },
+ { PCI_DEVICE(PCI_VENDOR_ID_OPTI, PCI_DEVICE_ID_OPTI_82C558), },
+ { PCI_DEVICE(PCI_VENDOR_ID_TOSHIBA,PCI_DEVICE_ID_TOSHIBA_PICCOLO), },
+ { PCI_DEVICE(PCI_VENDOR_ID_TOSHIBA,PCI_DEVICE_ID_TOSHIBA_PICCOLO_1), },
+ { PCI_DEVICE(PCI_VENDOR_ID_TOSHIBA,PCI_DEVICE_ID_TOSHIBA_PICCOLO_2), },
+ /* Must come last. If you add entries adjust this table appropriately */
+ { PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_STORAGE_IDE << 8, 0xFFFFFF00UL, 1},
+ { 0, },
+};
+
+static struct pci_driver ata_generic_pci_driver = {
+ .name = DRV_NAME,
+ .id_table = ata_generic,
+ .probe = ata_generic_init_one,
+ .remove = ata_pci_remove_one
+};
+
+static int __init ata_generic_init(void)
+{
+ return pci_module_init(&ata_generic_pci_driver);
+}
+
+
+static void __exit ata_generic_exit(void)
+{
+ pci_unregister_driver(&ata_generic_pci_driver);
+}
+
+
+MODULE_AUTHOR("Alan Cox");
+MODULE_DESCRIPTION("low-level driver for generic ATA");
+MODULE_LICENSE("GPL");
+MODULE_DEVICE_TABLE(pci, ata_generic);
+MODULE_VERSION(DRV_VERSION);
+
+module_init(ata_generic_init);
+module_exit(ata_generic_exit);
+
+module_param(all_generic_ide, int, 0);
diff --git a/drivers/scsi/ata_piix.c b/drivers/ata/ata_piix.c
similarity index 67%
rename from drivers/scsi/ata_piix.c
rename to drivers/ata/ata_piix.c
index a9bb3cb7e89b..ab2ecccf7798 100644
--- a/drivers/scsi/ata_piix.c
+++ b/drivers/ata/ata_piix.c
@@ -93,7 +93,7 @@
#include
#define DRV_NAME "ata_piix"
-#define DRV_VERSION "2.00"
+#define DRV_VERSION "2.00ac6"
enum {
PIIX_IOCFG = 0x54, /* IDE I/O configuration register */
@@ -116,15 +116,18 @@ enum {
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,
- ich7m_sata_ahci = 7,
- ich8_sata_ahci = 8,
+ piix_pata_33 = 0, /* PIIX3 or 4 at 33Mhz */
+ ich_pata_33 = 1, /* ICH up to UDMA 33 only */
+ ich_pata_66 = 2, /* ICH up to 66 Mhz */
+ ich_pata_100 = 3, /* ICH up to UDMA 100 */
+ ich_pata_133 = 4, /* ICH up to UDMA 133 */
+ ich5_sata = 5,
+ esb_sata = 6,
+ ich6_sata = 7,
+ ich6_sata_ahci = 8,
+ ich6m_sata_ahci = 9,
+ ich7m_sata_ahci = 10,
+ ich8_sata_ahci = 11,
/* constants for mapping table */
P0 = 0, /* port 0 */
@@ -152,20 +155,55 @@ struct piix_host_priv {
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_host_stop(struct ata_host *host);
+static void piix_pata_error_handler(struct ata_port *ap);
+static void ich_pata_error_handler(struct ata_port *ap);
+static void piix_sata_error_handler(struct ata_port *ap);
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 void ich_set_dmamode (struct ata_port *ap, struct ata_device *adev);
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 },
+ /* Intel PIIX4 for the 430TX/440BX/MX chipset: UDMA 33 */
+ /* Also PIIX4E (fn3 rev 2) and PIIX4M (fn3 rev 3) */
+ { 0x8086, 0x7111, PCI_ANY_ID, PCI_ANY_ID, 0, 0, piix_pata_33 },
+ { 0x8086, 0x24db, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich_pata_100 },
+ { 0x8086, 0x25a2, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich_pata_100 },
+ /* Intel PIIX4 */
+ { 0x8086, 0x7199, PCI_ANY_ID, PCI_ANY_ID, 0, 0, piix_pata_33 },
+ /* Intel PIIX4 */
+ { 0x8086, 0x7601, PCI_ANY_ID, PCI_ANY_ID, 0, 0, piix_pata_33 },
+ /* Intel PIIX */
+ { 0x8086, 0x84CA, PCI_ANY_ID, PCI_ANY_ID, 0, 0, piix_pata_33 },
+ /* Intel ICH (i810, i815, i840) UDMA 66*/
+ { 0x8086, 0x2411, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich_pata_66 },
+ /* Intel ICH0 : UDMA 33*/
+ { 0x8086, 0x2421, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich_pata_33 },
+ /* Intel ICH2M */
+ { 0x8086, 0x244A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich_pata_100 },
+ /* Intel ICH2 (i810E2, i845, 850, 860) UDMA 100 */
+ { 0x8086, 0x244B, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich_pata_100 },
+ /* Intel ICH3M */
+ { 0x8086, 0x248A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich_pata_100 },
+ /* Intel ICH3 (E7500/1) UDMA 100 */
+ { 0x8086, 0x248B, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich_pata_100 },
+ /* Intel ICH4 (i845GV, i845E, i852, i855) UDMA 100 */
+ { 0x8086, 0x24CA, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich_pata_100 },
+ { 0x8086, 0x24CB, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich_pata_100 },
+ /* Intel ICH5 */
+ { 0x8086, 0x24DB, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich_pata_133 },
+ /* C-ICH (i810E2) */
+ { 0x8086, 0x245B, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich_pata_100 },
+ /* ESB (855GME/875P + 6300ESB) UDMA 100 */
+ { 0x8086, 0x25A2, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich_pata_100 },
+ /* ICH6 (and 6) (i915) UDMA 100 */
+ { 0x8086, 0x266F, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich_pata_100 },
+ /* ICH7/7-R (i945, i975) UDMA 100*/
+ { 0x8086, 0x27DF, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich_pata_133 },
+ { 0x8086, 0x269E, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich_pata_100 },
#endif
/* NOTE: The following PCI ids must be kept in sync with the
@@ -264,6 +302,39 @@ static const struct ata_port_operations piix_pata_ops = {
.host_stop = piix_host_stop,
};
+static const struct ata_port_operations ich_pata_ops = {
+ .port_disable = ata_port_disable,
+ .set_piomode = piix_set_piomode,
+ .set_dmamode = ich_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 = ich_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 = ata_host_stop,
+};
+
static const struct ata_port_operations piix_sata_ops = {
.port_disable = ata_port_disable,
@@ -379,38 +450,59 @@ static const struct piix_map_db *piix_map_db_table[] = {
};
static struct ata_port_info piix_port_info[] = {
- /* piix4_pata */
+ /* piix_pata_33: 0: PIIX3 or 4 at 33MHz */
{
.sht = &piix_sht,
- .host_flags = ATA_FLAG_SLAVE_POSS,
+ .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST,
.pio_mask = 0x1f, /* pio0-4 */
-#if 0
- .mwdma_mask = 0x06, /* mwdma1-2 */
-#else
- .mwdma_mask = 0x00, /* mwdma broken */
-#endif
+ .mwdma_mask = 0x06, /* mwdma1-2 ?? CHECK 0 should be ok but slow */
.udma_mask = ATA_UDMA_MASK_40C,
.port_ops = &piix_pata_ops,
},
- /* ich5_pata */
+ /* ich_pata_33: 1 ICH0 - ICH at 33Mhz*/
{
.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,
+ .flags = ATA_FLAG_SRST | ATA_FLAG_SLAVE_POSS,
+ .pio_mask = 0x1f, /* pio 0-4 */
+ .mwdma_mask = 0x06, /* Check: maybe 0x07 */
+ .udma_mask = ATA_UDMA2, /* UDMA33 */
+ .port_ops = &ich_pata_ops,
+ },
+ /* ich_pata_66: 2 ICH controllers up to 66MHz */
+ {
+ .sht = &piix_sht,
+ .flags = ATA_FLAG_SRST | ATA_FLAG_SLAVE_POSS,
+ .pio_mask = 0x1f, /* pio 0-4 */
+ .mwdma_mask = 0x06, /* MWDMA0 is broken on chip */
+ .udma_mask = ATA_UDMA4,
+ .port_ops = &ich_pata_ops,
},
- /* ich5_sata */
+ /* ich_pata_100: 3 */
{
.sht = &piix_sht,
- .host_flags = ATA_FLAG_SATA | PIIX_FLAG_CHECKINTR |
+ .flags = ATA_FLAG_SRST | ATA_FLAG_SLAVE_POSS | PIIX_FLAG_CHECKINTR,
+ .pio_mask = 0x1f, /* pio0-4 */
+ .mwdma_mask = 0x06, /* mwdma1-2 */
+ .udma_mask = ATA_UDMA5, /* udma0-5 */
+ .port_ops = &ich_pata_ops,
+ },
+
+ /* ich_pata_133: 4 ICH with full UDMA6 */
+ {
+ .sht = &piix_sht,
+ .flags = ATA_FLAG_SRST | ATA_FLAG_SLAVE_POSS | PIIX_FLAG_CHECKINTR,
+ .pio_mask = 0x1f, /* pio 0-4 */
+ .mwdma_mask = 0x06, /* Check: maybe 0x07 */
+ .udma_mask = ATA_UDMA6, /* UDMA133 */
+ .port_ops = &ich_pata_ops,
+ },
+
+ /* ich5_sata: 5 */
+ {
+ .sht = &piix_sht,
+ .flags = ATA_FLAG_SATA | PIIX_FLAG_CHECKINTR |
PIIX_FLAG_IGNORE_PCS,
.pio_mask = 0x1f, /* pio0-4 */
.mwdma_mask = 0x07, /* mwdma0-2 */
@@ -418,10 +510,10 @@ static struct ata_port_info piix_port_info[] = {
.port_ops = &piix_sata_ops,
},
- /* i6300esb_sata */
+ /* i6300esb_sata: 6 */
{
.sht = &piix_sht,
- .host_flags = ATA_FLAG_SATA |
+ .flags = ATA_FLAG_SATA |
PIIX_FLAG_CHECKINTR | PIIX_FLAG_IGNORE_PCS,
.pio_mask = 0x1f, /* pio0-4 */
.mwdma_mask = 0x07, /* mwdma0-2 */
@@ -429,10 +521,10 @@ static struct ata_port_info piix_port_info[] = {
.port_ops = &piix_sata_ops,
},
- /* ich6_sata */
+ /* ich6_sata: 7 */
{
.sht = &piix_sht,
- .host_flags = ATA_FLAG_SATA |
+ .flags = ATA_FLAG_SATA |
PIIX_FLAG_CHECKINTR | PIIX_FLAG_SCR,
.pio_mask = 0x1f, /* pio0-4 */
.mwdma_mask = 0x07, /* mwdma0-2 */
@@ -440,10 +532,10 @@ static struct ata_port_info piix_port_info[] = {
.port_ops = &piix_sata_ops,
},
- /* ich6_sata_ahci */
+ /* ich6_sata_ahci: 8 */
{
.sht = &piix_sht,
- .host_flags = ATA_FLAG_SATA |
+ .flags = ATA_FLAG_SATA |
PIIX_FLAG_CHECKINTR | PIIX_FLAG_SCR |
PIIX_FLAG_AHCI,
.pio_mask = 0x1f, /* pio0-4 */
@@ -452,10 +544,10 @@ static struct ata_port_info piix_port_info[] = {
.port_ops = &piix_sata_ops,
},
- /* ich6m_sata_ahci */
+ /* ich6m_sata_ahci: 9 */
{
.sht = &piix_sht,
- .host_flags = ATA_FLAG_SATA |
+ .flags = ATA_FLAG_SATA |
PIIX_FLAG_CHECKINTR | PIIX_FLAG_SCR |
PIIX_FLAG_AHCI,
.pio_mask = 0x1f, /* pio0-4 */
@@ -464,10 +556,10 @@ static struct ata_port_info piix_port_info[] = {
.port_ops = &piix_sata_ops,
},
- /* ich7m_sata_ahci */
+ /* ich7m_sata_ahci: 10 */
{
.sht = &piix_sht,
- .host_flags = ATA_FLAG_SATA |
+ .flags = ATA_FLAG_SATA |
PIIX_FLAG_CHECKINTR | PIIX_FLAG_SCR |
PIIX_FLAG_AHCI,
.pio_mask = 0x1f, /* pio0-4 */
@@ -476,10 +568,10 @@ static struct ata_port_info piix_port_info[] = {
.port_ops = &piix_sata_ops,
},
- /* ich8_sata_ahci */
+ /* ich8_sata_ahci: 11 */
{
.sht = &piix_sht,
- .host_flags = ATA_FLAG_SATA |
+ .flags = ATA_FLAG_SATA |
PIIX_FLAG_CHECKINTR | PIIX_FLAG_SCR |
PIIX_FLAG_AHCI,
.pio_mask = 0x1f, /* pio0-4 */
@@ -487,6 +579,7 @@ static struct ata_port_info piix_port_info[] = {
.udma_mask = 0x7f, /* udma0-6 */
.port_ops = &piix_sata_ops,
},
+
};
static struct pci_bits piix_enable_bits[] = {
@@ -515,9 +608,10 @@ MODULE_PARM_DESC(force_pcs, "force honoring or ignoring PCS to work around "
* LOCKING:
* None (inherited from caller).
*/
-static void piix_pata_cbl_detect(struct ata_port *ap)
+
+static void ich_pata_cbl_detect(struct ata_port *ap)
{
- struct pci_dev *pdev = to_pci_dev(ap->host_set->dev);
+ struct pci_dev *pdev = to_pci_dev(ap->host->dev);
u8 tmp, mask;
/* no 80c support in host controller? */
@@ -525,7 +619,7 @@ static void piix_pata_cbl_detect(struct ata_port *ap)
goto cbl40;
/* check BIOS cable detect results */
- mask = ap->hard_port_no == 0 ? PIIX_80C_PRI : PIIX_80C_SEC;
+ 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;
@@ -535,30 +629,26 @@ static void piix_pata_cbl_detect(struct ata_port *ap)
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);
+ struct pci_dev *pdev = to_pci_dev(ap->host->dev);
- if (!pci_test_config_bits(pdev, &piix_enable_bits[ap->hard_port_no])) {
+ 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);
-
+ ap->cbl = ATA_CBL_PATA40;
return ata_std_prereset(ap);
}
@@ -568,6 +658,36 @@ static void piix_pata_error_handler(struct ata_port *ap)
ata_std_postreset);
}
+
+/**
+ * ich_pata_prereset - prereset for PATA host controller
+ * @ap: Target port
+ *
+ *
+ * LOCKING:
+ * None (inherited from caller).
+ */
+static int ich_pata_prereset(struct ata_port *ap)
+{
+ struct pci_dev *pdev = to_pci_dev(ap->host->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;
+ }
+
+ ich_pata_cbl_detect(ap);
+
+ return ata_std_prereset(ap);
+}
+
+static void ich_pata_error_handler(struct ata_port *ap)
+{
+ ata_bmdma_drive_eh(ap, ich_pata_prereset, ata_std_softreset, NULL,
+ ata_std_postreset);
+}
+
/**
* piix_sata_present_mask - determine present mask for SATA host controller
* @ap: Target port
@@ -583,10 +703,10 @@ static void piix_pata_error_handler(struct ata_port *ap)
*/
static unsigned int piix_sata_present_mask(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;
+ struct pci_dev *pdev = to_pci_dev(ap->host->dev);
+ struct piix_host_priv *hpriv = ap->host->private_data;
const unsigned int *map = hpriv->map;
- int base = 2 * ap->hard_port_no;
+ int base = 2 * ap->port_no;
unsigned int present_mask = 0;
int port, i;
u16 pcs;
@@ -663,12 +783,90 @@ static void piix_sata_error_handler(struct ata_port *ap)
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);
+ struct pci_dev *dev = to_pci_dev(ap->host->dev);
unsigned int is_slave = (adev->devno != 0);
- unsigned int master_port= ap->hard_port_no ? 0x42 : 0x40;
+ unsigned int master_port= ap->port_no ? 0x42 : 0x40;
unsigned int slave_port = 0x44;
u16 master_data;
u8 slave_data;
+ u8 udma_enable;
+ int control = 0;
+
+ /*
+ * See Intel Document 298600-004 for the timing programing rules
+ * for ICH controllers.
+ */
+
+ static const /* ISP RTC */
+ u8 timings[][2] = { { 0, 0 },
+ { 0, 0 },
+ { 1, 0 },
+ { 2, 1 },
+ { 2, 3 }, };
+
+ if (pio >= 2)
+ control |= 1; /* TIME1 enable */
+ if (ata_pio_need_iordy(adev))
+ control |= 2; /* IE enable */
+
+ /* Intel specifies that the PPE functionality is for disk only */
+ if (adev->class == ATA_DEV_ATA)
+ control |= 4; /* PPE enable */
+
+ pci_read_config_word(dev, master_port, &master_data);
+ if (is_slave) {
+ /* Enable SITRE (seperate slave timing register) */
+ master_data |= 0x4000;
+ /* enable PPE1, IE1 and TIME1 as needed */
+ master_data |= (control << 4);
+ pci_read_config_byte(dev, slave_port, &slave_data);
+ slave_data &= (ap->port_no ? 0x0f : 0xf0);
+ /* Load the timing nibble for this slave */
+ slave_data |= ((timings[pio][0] << 2) | timings[pio][1]) << (ap->port_no ? 4 : 0);
+ } else {
+ /* Master keeps the bits in a different format */
+ master_data &= 0xccf8;
+ /* Enable PPE, IE and TIME as appropriate */
+ master_data |= control;
+ 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);
+
+ /* Ensure the UDMA bit is off - it will be turned back on if
+ UDMA is selected */
+
+ if (ap->udma_mask) {
+ pci_read_config_byte(dev, 0x48, &udma_enable);
+ udma_enable &= ~(1 << (2 * ap->port_no + adev->devno));
+ pci_write_config_byte(dev, 0x48, udma_enable);
+ }
+}
+
+/**
+ * do_pata_set_dmamode - Initialize host controller PATA PIO timings
+ * @ap: Port whose timings we are configuring
+ * @adev: Drive in question
+ * @udma: udma mode, 0 - 6
+ * @is_ich: set if the chip is an ICH device
+ *
+ * Set UDMA mode for device, in host controller PCI config space.
+ *
+ * LOCKING:
+ * None (inherited from caller).
+ */
+
+static void do_pata_set_dmamode (struct ata_port *ap, struct ata_device *adev, int isich)
+{
+ struct pci_dev *dev = to_pci_dev(ap->host->dev);
+ u8 master_port = ap->port_no ? 0x42 : 0x40;
+ u16 master_data;
+ u8 speed = adev->dma_mode;
+ int devid = adev->devno + 2 * ap->port_no;
+ u8 udma_enable;
static const /* ISP RTC */
u8 timings[][2] = { { 0, 0 },
@@ -678,35 +876,99 @@ static void piix_set_piomode (struct ata_port *ap, struct ata_device *adev)
{ 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->hard_port_no ? 0x0f : 0xf0);
- slave_data |=
- (timings[pio][0] << 2) |
- (timings[pio][1] << (ap->hard_port_no ? 4 : 0));
+ pci_read_config_byte(dev, 0x48, &udma_enable);
+
+ if (speed >= XFER_UDMA_0) {
+ unsigned int udma = adev->dma_mode - XFER_UDMA_0;
+ u16 udma_timing;
+ u16 ideconf;
+ int u_clock, u_speed;
+
+ /*
+ * UDMA is handled by a combination of clock switching and
+ * selection of dividers
+ *
+ * Handy rule: Odd modes are UDMATIMx 01, even are 02
+ * except UDMA0 which is 00
+ */
+ u_speed = min(2 - (udma & 1), udma);
+ if (udma == 5)
+ u_clock = 0x1000; /* 100Mhz */
+ else if (udma > 2)
+ u_clock = 1; /* 66Mhz */
+ else
+ u_clock = 0; /* 33Mhz */
+
+ udma_enable |= (1 << devid);
+
+ /* Load the CT/RP selection */
+ pci_read_config_word(dev, 0x4A, &udma_timing);
+ udma_timing &= ~(3 << (4 * devid));
+ udma_timing |= u_speed << (4 * devid);
+ pci_write_config_word(dev, 0x4A, udma_timing);
+
+ if (isich) {
+ /* Select a 33/66/100Mhz clock */
+ pci_read_config_word(dev, 0x54, &ideconf);
+ ideconf &= ~(0x1001 << devid);
+ ideconf |= u_clock << devid;
+ /* For ICH or later we should set bit 10 for better
+ performance (WR_PingPong_En) */
+ pci_write_config_word(dev, 0x54, ideconf);
+ }
} else {
- master_data &= 0xccf8;
- /* enable PPE, IE and TIME */
- master_data |= 0x0007;
- master_data |=
- (timings[pio][0] << 12) |
- (timings[pio][1] << 8);
+ /*
+ * MWDMA is driven by the PIO timings. We must also enable
+ * IORDY unconditionally along with TIME1. PPE has already
+ * been set when the PIO timing was set.
+ */
+ unsigned int mwdma = adev->dma_mode - XFER_MW_DMA_0;
+ unsigned int control;
+ u8 slave_data;
+ const unsigned int needed_pio[3] = {
+ XFER_PIO_0, XFER_PIO_3, XFER_PIO_4
+ };
+ int pio = needed_pio[mwdma] - XFER_PIO_0;
+
+ control = 3; /* IORDY|TIME1 */
+
+ /* If the drive MWDMA is faster than it can do PIO then
+ we must force PIO into PIO0 */
+
+ if (adev->pio_mode < needed_pio[mwdma])
+ /* Enable DMA timing only */
+ control |= 8; /* PIO cycles in PIO0 */
+
+ if (adev->devno) { /* Slave */
+ master_data &= 0xFF4F; /* Mask out IORDY|TIME1|DMAONLY */
+ master_data |= control << 4;
+ pci_read_config_byte(dev, 0x44, &slave_data);
+ slave_data &= (0x0F + 0xE1 * ap->port_no);
+ /* Load the matching timing */
+ slave_data |= ((timings[pio][0] << 2) | timings[pio][1]) << (ap->port_no ? 4 : 0);
+ pci_write_config_byte(dev, 0x44, slave_data);
+ } else { /* Master */
+ master_data &= 0xCCF4; /* Mask out IORDY|TIME1|DMAONLY
+ and master timing bits */
+ master_data |= control;
+ master_data |=
+ (timings[pio][0] << 12) |
+ (timings[pio][1] << 8);
+ }
+ udma_enable &= ~(1 << devid);
+ pci_write_config_word(dev, master_port, master_data);
}
- pci_write_config_word(dev, master_port, master_data);
- if (is_slave)
- pci_write_config_byte(dev, slave_port, slave_data);
+ /* Don't scribble on 0x48 if the controller does not support UDMA */
+ if (ap->udma_mask)
+ pci_write_config_byte(dev, 0x48, udma_enable);
}
/**
- * piix_set_dmamode - Initialize host controller PATA PIO timings
+ * piix_set_dmamode - Initialize host controller PATA DMA 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.
+ * Set MW/UDMA mode for device, in host controller PCI config space.
*
* LOCKING:
* None (inherited from caller).
@@ -714,68 +976,23 @@ 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)
{
- unsigned int udma = adev->dma_mode; /* FIXME: MWDMA too */
- struct pci_dev *dev = to_pci_dev(ap->host_set->dev);
- u8 maslave = ap->hard_port_no ? 0x42 : 0x40;
- u8 speed = udma;
- unsigned int drive_dn = (ap->hard_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;
+ do_pata_set_dmamode(ap, adev, 0);
+}
- pci_read_config_word(dev, maslave, ®4042);
- DPRINTK("reg4042 = 0x%04x\n", reg4042);
- sitre = (reg4042 & 0x4000) ? 1 : 0;
- pci_read_config_byte(dev, 0x48, ®48);
- pci_read_config_word(dev, 0x4a, ®4a);
- pci_read_config_byte(dev, 0x54, ®54);
- pci_read_config_byte(dev, 0x55, ®55);
+/**
+ * ich_set_dmamode - Initialize host controller PATA DMA timings
+ * @ap: Port whose timings we are configuring
+ * @adev: um
+ *
+ * Set MW/UDMA mode for device, in host controller PCI config space.
+ *
+ * LOCKING:
+ * None (inherited from caller).
+ */
- 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);
- }
+static void ich_set_dmamode (struct ata_port *ap, struct ata_device *adev)
+{
+ do_pata_set_dmamode(ap, adev, 1);
}
#define AHCI_PCI_BAR 5
@@ -867,13 +1084,13 @@ static void __devinit piix_init_pcs(struct pci_dev *pdev,
if (force_pcs == 1) {
dev_printk(KERN_INFO, &pdev->dev,
"force ignoring PCS (0x%x)\n", new_pcs);
- pinfo[0].host_flags |= PIIX_FLAG_IGNORE_PCS;
- pinfo[1].host_flags |= PIIX_FLAG_IGNORE_PCS;
+ pinfo[0].flags |= PIIX_FLAG_IGNORE_PCS;
+ pinfo[1].flags |= PIIX_FLAG_IGNORE_PCS;
} else if (force_pcs == 2) {
dev_printk(KERN_INFO, &pdev->dev,
"force honoring PCS (0x%x)\n", new_pcs);
- pinfo[0].host_flags &= ~PIIX_FLAG_IGNORE_PCS;
- pinfo[1].host_flags &= ~PIIX_FLAG_IGNORE_PCS;
+ pinfo[0].flags &= ~PIIX_FLAG_IGNORE_PCS;
+ pinfo[1].flags &= ~PIIX_FLAG_IGNORE_PCS;
}
}
@@ -904,7 +1121,7 @@ static void __devinit piix_init_sata_map(struct pci_dev *pdev,
case IDE:
WARN_ON((i & 1) || map[i + 1] != IDE);
- pinfo[i / 2] = piix_port_info[ich5_pata];
+ pinfo[i / 2] = piix_port_info[ich_pata_100];
pinfo[i / 2].private_data = hpriv;
i++;
printk(" IDE IDE");
@@ -913,7 +1130,7 @@ static void __devinit piix_init_sata_map(struct pci_dev *pdev,
default:
printk(" P%d", map[i]);
if (i & 1)
- pinfo[i / 2].host_flags |= ATA_FLAG_SLAVE_POSS;
+ pinfo[i / 2].flags |= ATA_FLAG_SLAVE_POSS;
break;
}
}
@@ -948,7 +1165,7 @@ static int piix_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
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;
+ unsigned long port_flags;
if (!printed_version++)
dev_printk(KERN_DEBUG, &pdev->dev,
@@ -967,9 +1184,9 @@ static int piix_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
port_info[0].private_data = hpriv;
port_info[1].private_data = hpriv;
- host_flags = port_info[0].host_flags;
+ port_flags = port_info[0].flags;
- if (host_flags & PIIX_FLAG_AHCI) {
+ if (port_flags & PIIX_FLAG_AHCI) {
u8 tmp;
pci_read_config_byte(pdev, PIIX_SCC, &tmp);
if (tmp == PIIX_AHCI_DEVICE) {
@@ -980,7 +1197,7 @@ static int piix_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
}
/* Initialize SATA map */
- if (host_flags & ATA_FLAG_SATA) {
+ if (port_flags & ATA_FLAG_SATA) {
piix_init_sata_map(pdev, port_info,
piix_map_db_table[ent->driver_data]);
piix_init_pcs(pdev, port_info,
@@ -993,7 +1210,7 @@ static int piix_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
* MSI is disabled (and it is disabled, as we don't use
* message-signalled interrupts currently).
*/
- if (host_flags & PIIX_FLAG_CHECKINTR)
+ if (port_flags & PIIX_FLAG_CHECKINTR)
pci_intx(pdev, 1);
if (piix_check_450nx_errata(pdev)) {
@@ -1008,19 +1225,21 @@ static int piix_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
return ata_pci_init_one(pdev, ppinfo, 2);
}
-static void piix_host_stop(struct ata_host_set *host_set)
+static void piix_host_stop(struct ata_host *host)
{
- if (host_set->next == NULL)
- kfree(host_set->private_data);
- ata_host_stop(host_set);
+ struct piix_host_priv *hpriv = host->private_data;
+
+ ata_host_stop(host);
+
+ kfree(hpriv);
}
static int __init piix_init(void)
{
int rc;
- DPRINTK("pci_module_init\n");
- rc = pci_module_init(&piix_pci_driver);
+ DPRINTK("pci_register_driver\n");
+ rc = pci_register_driver(&piix_pci_driver);
if (rc)
return rc;
@@ -1037,4 +1256,3 @@ static void __exit piix_exit(void)
module_init(piix_init);
module_exit(piix_exit);
-
diff --git a/drivers/scsi/libata-core.c b/drivers/ata/libata-core.c
similarity index 92%
rename from drivers/scsi/libata-core.c
rename to drivers/ata/libata-core.c
index 427b73a3886a..753b0152afd1 100644
--- a/drivers/scsi/libata-core.c
+++ b/drivers/ata/libata-core.c
@@ -50,7 +50,6 @@
#include
#include
#include
-#include "scsi_priv.h"
#include
#include
#include
@@ -387,9 +386,13 @@ static const char *ata_mode_string(unsigned int xfer_mask)
"PIO2",
"PIO3",
"PIO4",
+ "PIO5",
+ "PIO6",
"MWDMA0",
"MWDMA1",
"MWDMA2",
+ "MWDMA3",
+ "MWDMA4",
"UDMA/16",
"UDMA/25",
"UDMA/33",
@@ -613,8 +616,11 @@ ata_dev_try_classify(struct ata_port *ap, unsigned int device, u8 *r_err)
if (r_err)
*r_err = err;
- /* see if device passed diags */
- if (err == 1)
+ /* see if device passed diags: if master then continue and warn later */
+ if (err == 0 && device == 0)
+ /* diagnostic fail : do nothing _YET_ */
+ ap->device[device].horkage |= ATA_HORKAGE_DIAGNOSTIC;
+ else if (err == 1)
/* do nothing */ ;
else if ((device == 0) && (err == 0x81))
/* do nothing */ ;
@@ -876,6 +882,23 @@ static unsigned int ata_id_xfermask(const u16 *id)
mwdma_mask = id[ATA_ID_MWDMA_MODES] & 0x07;
+ if (ata_id_is_cfa(id)) {
+ /*
+ * Process compact flash extended modes
+ */
+ int pio = id[163] & 0x7;
+ int dma = (id[163] >> 3) & 7;
+
+ if (pio)
+ pio_mask |= (1 << 5);
+ if (pio > 1)
+ pio_mask |= (1 << 6);
+ if (dma)
+ mwdma_mask |= (1 << 3);
+ if (dma > 1)
+ mwdma_mask |= (1 << 4);
+ }
+
udma_mask = 0;
if (id[ATA_ID_FIELD_VALID] & (1 << 2))
udma_mask = id[ATA_ID_UDMA_MODES] & 0xff;
@@ -1320,7 +1343,7 @@ static void ata_dev_config_ncq(struct ata_device *dev,
}
if (ap->flags & ATA_FLAG_NCQ) {
- hdepth = min(ap->host->can_queue, ATA_MAX_QUEUE - 1);
+ hdepth = min(ap->scsi_host->can_queue, ATA_MAX_QUEUE - 1);
dev->flags |= ATA_DFLAG_NCQ;
}
@@ -1334,12 +1357,13 @@ static void ata_set_port_max_cmd_len(struct ata_port *ap)
{
int i;
- if (ap->host) {
- ap->host->max_cmd_len = 0;
+ if (ap->scsi_host) {
+ unsigned int 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);
+ len = max(len, ap->device[i].cdb_len);
+
+ ap->scsi_host->max_cmd_len = len;
}
}
@@ -1362,6 +1386,7 @@ 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;
+ char revbuf[7]; /* XYZ-99\0 */
int rc;
if (!ata_dev_enabled(dev) && ata_msg_info(ap)) {
@@ -1405,6 +1430,15 @@ int ata_dev_configure(struct ata_device *dev, int print_info)
/* ATA-specific feature tests */
if (dev->class == ATA_DEV_ATA) {
+ if (ata_id_is_cfa(id)) {
+ if (id[162] & 1) /* CPRM may make this media unusable */
+ ata_dev_printk(dev, KERN_WARNING, "ata%u: device %u supports DRM functions and may not be fully accessable.\n",
+ ap->id, dev->devno);
+ snprintf(revbuf, 7, "CFA");
+ }
+ else
+ snprintf(revbuf, 7, "ATA-%d", ata_id_major_version(id));
+
dev->n_sectors = ata_id_n_sectors(id);
if (ata_id_has_lba(id)) {
@@ -1423,9 +1457,9 @@ int ata_dev_configure(struct ata_device *dev, int print_info)
/* print device info to dmesg */
if (ata_msg_drv(ap) && print_info)
- ata_dev_printk(dev, KERN_INFO, "ATA-%d, "
+ ata_dev_printk(dev, KERN_INFO, "%s, "
"max %s, %Lu sectors: %s %s\n",
- ata_id_major_version(id),
+ revbuf,
ata_mode_string(xfer_mask),
(unsigned long long)dev->n_sectors,
lba_desc, ncq_desc);
@@ -1446,9 +1480,9 @@ int ata_dev_configure(struct ata_device *dev, int print_info)
/* print device info to dmesg */
if (ata_msg_drv(ap) && print_info)
- ata_dev_printk(dev, KERN_INFO, "ATA-%d, "
+ ata_dev_printk(dev, KERN_INFO, "%s, "
"max %s, %Lu sectors: CHS %u/%u/%u\n",
- ata_id_major_version(id),
+ revbuf,
ata_mode_string(xfer_mask),
(unsigned long long)dev->n_sectors,
dev->cylinders, dev->heads,
@@ -1492,6 +1526,18 @@ int ata_dev_configure(struct ata_device *dev, int print_info)
cdb_intr_string);
}
+ if (dev->horkage & ATA_HORKAGE_DIAGNOSTIC) {
+ /* Let the user know. We don't want to disallow opens for
+ rescue purposes, or in case the vendor is just a blithering
+ idiot */
+ if (print_info) {
+ ata_dev_printk(dev, KERN_WARNING,
+"Drive reports diagnostics failure. This may indicate a drive\n");
+ ata_dev_printk(dev, KERN_WARNING,
+"fault or invalid emulation. Contact drive vendor for information.\n");
+ }
+ }
+
ata_set_port_max_cmd_len(ap);
/* limit bridge transfers to udma5, 200 sectors */
@@ -1533,7 +1579,7 @@ err_out_nosup:
* Zero on success, negative errno otherwise.
*/
-static int ata_bus_probe(struct ata_port *ap)
+int ata_bus_probe(struct ata_port *ap)
{
unsigned int classes[ATA_MAX_DEVICES];
int tries[ATA_MAX_DEVICES];
@@ -1637,7 +1683,7 @@ static int ata_bus_probe(struct ata_port *ap)
* Modify @ap data structure such that the system
* thinks that the entire port is enabled.
*
- * LOCKING: host_set lock, or some other form of
+ * LOCKING: host lock, or some other form of
* serialization.
*/
@@ -1775,7 +1821,7 @@ struct ata_device *ata_dev_pair(struct ata_device *adev)
* never attempt to probe or communicate with devices
* on this port.
*
- * LOCKING: host_set lock, or some other form of
+ * LOCKING: host lock, or some other form of
* serialization.
*/
@@ -1906,10 +1952,11 @@ int sata_set_spd(struct ata_port *ap)
* 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).
+ * PIO 0-4, 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.
+ * for UDMA6, which is currently supported only by Maxtor drives.
+ *
+ * For PIO 5/6 MWDMA 3/4 see the CFA specification 3.0.
*/
static const struct ata_timing ata_timing[] = {
@@ -1919,6 +1966,8 @@ static const struct ata_timing ata_timing[] = {
{ XFER_UDMA_4, 0, 0, 0, 0, 0, 0, 0, 30 },
{ XFER_UDMA_3, 0, 0, 0, 0, 0, 0, 0, 45 },
+ { XFER_MW_DMA_4, 25, 0, 0, 0, 55, 20, 80, 0 },
+ { XFER_MW_DMA_3, 25, 0, 0, 0, 65, 25, 100, 0 },
{ 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 },
@@ -1933,7 +1982,8 @@ static const struct ata_timing ata_timing[] = {
{ 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_6, 10, 55, 20, 80, 55, 20, 80, 0 },
+ { XFER_PIO_5, 15, 65, 25, 100, 65, 25, 100, 0 },
{ XFER_PIO_4, 25, 70, 25, 120, 70, 25, 120, 0 },
{ XFER_PIO_3, 30, 80, 70, 180, 80, 70, 180, 0 },
@@ -2229,8 +2279,8 @@ int ata_set_mode(struct ata_port *ap, struct ata_device **r_failed_dev)
/* 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;
+ if (used_dma && (ap->host->flags & ATA_HOST_SIMPLEX))
+ ap->host->simplex_claimed = 1;
/* step5: chip specific finalisation */
if (ap->ops->post_set_mode)
@@ -2252,7 +2302,7 @@ int ata_set_mode(struct ata_port *ap, struct ata_device **r_failed_dev)
* other threads.
*
* LOCKING:
- * spin_lock_irqsave(host_set lock)
+ * spin_lock_irqsave(host lock)
*/
static inline void ata_tf_to_host(struct ata_port *ap,
@@ -2416,7 +2466,7 @@ static unsigned int ata_bus_softreset(struct ata_port *ap,
*
* LOCKING:
* PCI/etc. bus probe sem.
- * Obtains host_set lock.
+ * Obtains host lock.
*
* SIDE EFFECTS:
* Sets ATA_FLAG_DISABLED if bus reset fails.
@@ -3045,20 +3095,16 @@ static int ata_dma_blacklisted(const struct ata_device *dev)
* known limits including host controller limits, device
* blacklist, etc...
*
- * FIXME: The current implementation limits all transfer modes to
- * the fastest of the lowested device on the port. This is not
- * required on most controllers.
- *
* 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;
+ struct ata_host *host = ap->host;
unsigned long xfer_mask;
- int i;
+ /* controller modes available */
xfer_mask = ata_pack_xfermask(ap->pio_mask,
ap->mwdma_mask, ap->udma_mask);
@@ -3068,34 +3114,31 @@ static void ata_dev_xfermask(struct ata_device *dev)
if (ap->cbl == ATA_CBL_PATA40)
xfer_mask &= ~(0xF8 << ATA_SHIFT_UDMA);
- /* FIXME: Use port-wide xfermask for now */
- for (i = 0; i < ATA_MAX_DEVICES; i++) {
- struct ata_device *d = &ap->device[i];
+ xfer_mask &= ata_pack_xfermask(dev->pio_mask,
+ dev->mwdma_mask, dev->udma_mask);
+ xfer_mask &= ata_id_xfermask(dev->id);
- if (ata_dev_absent(d))
- continue;
-
- if (ata_dev_disabled(d)) {
- /* to avoid violating device selection timing */
- xfer_mask &= ata_pack_xfermask(d->pio_mask,
- UINT_MAX, UINT_MAX);
- continue;
- }
-
- xfer_mask &= ata_pack_xfermask(d->pio_mask,
- d->mwdma_mask, d->udma_mask);
- xfer_mask &= ata_id_xfermask(d->id);
- if (ata_dma_blacklisted(d))
- xfer_mask &= ~(ATA_MASK_MWDMA | ATA_MASK_UDMA);
+ /*
+ * CFA Advanced TrueIDE timings are not allowed on a shared
+ * cable
+ */
+ if (ata_dev_pair(dev)) {
+ /* No PIO5 or PIO6 */
+ xfer_mask &= ~(0x03 << (ATA_SHIFT_PIO + 5));
+ /* No MWDMA3 or MWDMA 4 */
+ xfer_mask &= ~(0x03 << (ATA_SHIFT_MWDMA + 3));
}
- if (ata_dma_blacklisted(dev))
+ 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) {
- if (hs->simplex_claimed)
- xfer_mask &= ~(ATA_MASK_MWDMA | ATA_MASK_UDMA);
+ if ((host->flags & ATA_HOST_SIMPLEX) && host->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)
@@ -3185,7 +3228,7 @@ static unsigned int ata_dev_init_params(struct ata_device *dev,
* Unmap all mapped DMA memory associated with this command.
*
* LOCKING:
- * spin_lock_irqsave(host_set lock)
+ * spin_lock_irqsave(host lock)
*/
static void ata_sg_clean(struct ata_queued_cmd *qc)
@@ -3245,7 +3288,7 @@ static void ata_sg_clean(struct ata_queued_cmd *qc)
* associated with the current disk command.
*
* LOCKING:
- * spin_lock_irqsave(host_set lock)
+ * spin_lock_irqsave(host lock)
*
*/
static void ata_fill_sg(struct ata_queued_cmd *qc)
@@ -3297,7 +3340,7 @@ static void ata_fill_sg(struct ata_queued_cmd *qc)
* supplied PACKET command.
*
* LOCKING:
- * spin_lock_irqsave(host_set lock)
+ * spin_lock_irqsave(host lock)
*
* RETURNS: 0 when ATAPI DMA can be used
* nonzero otherwise
@@ -3319,7 +3362,7 @@ int ata_check_atapi_dma(struct ata_queued_cmd *qc)
* Prepare ATA taskfile for submission.
*
* LOCKING:
- * spin_lock_irqsave(host_set lock)
+ * spin_lock_irqsave(host lock)
*/
void ata_qc_prep(struct ata_queued_cmd *qc)
{
@@ -3341,7 +3384,7 @@ void ata_noop_qc_prep(struct ata_queued_cmd *qc) { }
* to point to a single memory buffer, @buf of byte length @buflen.
*
* LOCKING:
- * spin_lock_irqsave(host_set lock)
+ * spin_lock_irqsave(host lock)
*/
void ata_sg_init_one(struct ata_queued_cmd *qc, void *buf, unsigned int buflen)
@@ -3372,7 +3415,7 @@ void ata_sg_init_one(struct ata_queued_cmd *qc, void *buf, unsigned int buflen)
* elements.
*
* LOCKING:
- * spin_lock_irqsave(host_set lock)
+ * spin_lock_irqsave(host lock)
*/
void ata_sg_init(struct ata_queued_cmd *qc, struct scatterlist *sg,
@@ -3391,7 +3434,7 @@ void ata_sg_init(struct ata_queued_cmd *qc, struct scatterlist *sg,
* DMA-map the memory buffer associated with queued_cmd @qc.
*
* LOCKING:
- * spin_lock_irqsave(host_set lock)
+ * spin_lock_irqsave(host lock)
*
* RETURNS:
* Zero on success, negative on error.
@@ -3460,7 +3503,7 @@ skip_map:
* DMA-map the scatter-gather table associated with queued_cmd @qc.
*
* LOCKING:
- * spin_lock_irqsave(host_set lock)
+ * spin_lock_irqsave(host lock)
*
* RETURNS:
* Zero on success, negative on error.
@@ -3969,7 +4012,7 @@ static inline int ata_hsm_ok_in_wq(struct ata_port *ap, struct ata_queued_cmd *q
* Finish @qc which is running on standard HSM.
*
* LOCKING:
- * If @in_wq is zero, spin_lock_irqsave(host_set lock).
+ * If @in_wq is zero, spin_lock_irqsave(host lock).
* Otherwise, none on entry and grabs host lock.
*/
static void ata_hsm_qc_complete(struct ata_queued_cmd *qc, int in_wq)
@@ -3981,8 +4024,8 @@ static void ata_hsm_qc_complete(struct ata_queued_cmd *qc, int in_wq)
if (in_wq) {
spin_lock_irqsave(ap->lock, flags);
- /* EH might have kicked in while host_set lock
- * is released.
+ /* EH might have kicked in while host lock is
+ * released.
*/
qc = ata_qc_from_tag(ap, qc->tag);
if (qc) {
@@ -4347,7 +4390,7 @@ struct ata_queued_cmd *ata_qc_new_init(struct ata_device *dev)
* in case something prevents using it.
*
* LOCKING:
- * spin_lock_irqsave(host_set lock)
+ * spin_lock_irqsave(host lock)
*/
void ata_qc_free(struct ata_queued_cmd *qc)
{
@@ -4400,7 +4443,7 @@ void __ata_qc_complete(struct ata_queued_cmd *qc)
* command has completed, with either an ok or not-ok status.
*
* LOCKING:
- * spin_lock_irqsave(host_set lock)
+ * spin_lock_irqsave(host lock)
*/
void ata_qc_complete(struct ata_queued_cmd *qc)
{
@@ -4463,7 +4506,7 @@ void ata_qc_complete(struct ata_queued_cmd *qc)
* and commands are completed accordingly.
*
* LOCKING:
- * spin_lock_irqsave(host_set lock)
+ * spin_lock_irqsave(host lock)
*
* RETURNS:
* Number of completed commands on success, -errno otherwise.
@@ -4534,7 +4577,7 @@ static inline int ata_should_dma_map(struct ata_queued_cmd *qc)
* writing the taskfile to hardware, starting the command.
*
* LOCKING:
- * spin_lock_irqsave(host_set lock)
+ * spin_lock_irqsave(host lock)
*/
void ata_qc_issue(struct ata_queued_cmd *qc)
{
@@ -4595,7 +4638,7 @@ err:
* May be used as the qc_issue() entry in ata_port_operations.
*
* LOCKING:
- * spin_lock_irqsave(host_set lock)
+ * spin_lock_irqsave(host lock)
*
* RETURNS:
* Zero on success, AC_ERR_* mask on failure
@@ -4724,7 +4767,7 @@ unsigned int ata_qc_issue_prot(struct ata_queued_cmd *qc)
* handled via polling with interrupts disabled (nIEN bit).
*
* LOCKING:
- * spin_lock_irqsave(host_set lock)
+ * spin_lock_irqsave(host lock)
*
* RETURNS:
* One if interrupt was handled, zero if not (shared irq).
@@ -4811,14 +4854,14 @@ idle_irq:
/**
* ata_interrupt - Default ATA host interrupt handler
* @irq: irq line (unused)
- * @dev_instance: pointer to our ata_host_set information structure
+ * @dev_instance: pointer to our ata_host 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.
+ * Obtains host lock during operation.
*
* RETURNS:
* IRQ_NONE or IRQ_HANDLED.
@@ -4826,18 +4869,18 @@ idle_irq:
irqreturn_t ata_interrupt (int irq, void *dev_instance, struct pt_regs *regs)
{
- struct ata_host_set *host_set = dev_instance;
+ struct ata_host *host = 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);
+ spin_lock_irqsave(&host->lock, flags);
- for (i = 0; i < host_set->n_ports; i++) {
+ for (i = 0; i < host->n_ports; i++) {
struct ata_port *ap;
- ap = host_set->ports[i];
+ ap = host->ports[i];
if (ap &&
!(ap->flags & ATA_FLAG_DISABLED)) {
struct ata_queued_cmd *qc;
@@ -4849,7 +4892,7 @@ irqreturn_t ata_interrupt (int irq, void *dev_instance, struct pt_regs *regs)
}
}
- spin_unlock_irqrestore(&host_set->lock, flags);
+ spin_unlock_irqrestore(&host->lock, flags);
return IRQ_RETVAL(handled);
}
@@ -5014,15 +5057,15 @@ int ata_flush_cache(struct ata_device *dev)
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)
+static int ata_host_request_pm(struct ata_host *host, 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];
+ for (i = 0; i < host->n_ports; i++) {
+ struct ata_port *ap = host->ports[i];
/* Previous resume operation might still be in
* progress. Wait for PM_PENDING to clear.
@@ -5062,11 +5105,11 @@ static int ata_host_set_request_pm(struct ata_host_set *host_set,
}
/**
- * ata_host_set_suspend - suspend host_set
- * @host_set: host_set to suspend
+ * ata_host_suspend - suspend host
+ * @host: host to suspend
* @mesg: PM message
*
- * Suspend @host_set. Actual operation is performed by EH. This
+ * Suspend @host. Actual operation is performed by EH. This
* function requests EH to perform PM operations and waits for EH
* to finish.
*
@@ -5076,11 +5119,11 @@ static int ata_host_set_request_pm(struct ata_host_set *host_set,
* RETURNS:
* 0 on success, -errno on failure.
*/
-int ata_host_set_suspend(struct ata_host_set *host_set, pm_message_t mesg)
+int ata_host_suspend(struct ata_host *host, pm_message_t mesg)
{
int i, j, rc;
- rc = ata_host_set_request_pm(host_set, mesg, 0, ATA_EHI_QUIET, 1);
+ rc = ata_host_request_pm(host, mesg, 0, ATA_EHI_QUIET, 1);
if (rc)
goto fail;
@@ -5088,8 +5131,8 @@ int ata_host_set_suspend(struct ata_host_set *host_set, pm_message_t mesg)
* 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 (i = 0; i < host->n_ports; i++) {
+ struct ata_port *ap = host->ports[i];
for (j = 0; j < ATA_MAX_DEVICES; j++) {
struct ata_device *dev = &ap->device[j];
@@ -5104,30 +5147,30 @@ int ata_host_set_suspend(struct ata_host_set *host_set, pm_message_t mesg)
}
}
- host_set->dev->power.power_state = mesg;
+ host->dev->power.power_state = mesg;
return 0;
fail:
- ata_host_set_resume(host_set);
+ ata_host_resume(host);
return rc;
}
/**
- * ata_host_set_resume - resume host_set
- * @host_set: host_set to resume
+ * ata_host_resume - resume host
+ * @host: host to resume
*
- * Resume @host_set. Actual operation is performed by EH. This
+ * Resume @host. 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)
+void ata_host_resume(struct ata_host *host)
{
- 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_host_request_pm(host, PMSG_ON, ATA_EH_SOFTRESET,
+ ATA_EHI_NO_AUTOPSY | ATA_EHI_QUIET, 0);
+ host->dev->power.power_state = PMSG_ON;
}
/**
@@ -5184,10 +5227,10 @@ void ata_port_stop (struct ata_port *ap)
ata_pad_free(ap, dev);
}
-void ata_host_stop (struct ata_host_set *host_set)
+void ata_host_stop (struct ata_host *host)
{
- if (host_set->mmio_base)
- iounmap(host_set->mmio_base);
+ if (host->mmio_base)
+ iounmap(host->mmio_base);
}
/**
@@ -5209,7 +5252,7 @@ void ata_dev_init(struct ata_device *dev)
/* High bits of dev->flags are used to record warm plug
* requests which occur asynchronously. Synchronize using
- * host_set lock.
+ * host lock.
*/
spin_lock_irqsave(ap->lock, flags);
dev->flags &= ~ATA_DFLAG_INIT_MASK;
@@ -5223,46 +5266,42 @@ void ata_dev_init(struct ata_device *dev)
}
/**
- * ata_host_init - Initialize an ata_port structure
+ * ata_port_init - Initialize an ata_port structure
* @ap: Structure to initialize
- * @host: associated SCSI mid-layer structure
- * @host_set: Collection of hosts to which @ap belongs
+ * @host: 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, and its associated
- * scsi_host.
+ * Initialize a new ata_port structure.
*
* LOCKING:
* Inherited from caller.
*/
-static void ata_host_init(struct ata_port *ap, struct Scsi_Host *host,
- struct ata_host_set *host_set,
- const struct ata_probe_ent *ent, unsigned int port_no)
+void ata_port_init(struct ata_port *ap, struct ata_host *host,
+ const struct ata_probe_ent *ent, unsigned int port_no)
{
unsigned int i;
- host->max_id = 16;
- host->max_lun = 1;
- host->max_channel = 1;
- host->unique_id = ata_unique_id++;
- host->max_cmd_len = 12;
-
- ap->lock = &host_set->lock;
+ ap->lock = &host->lock;
ap->flags = ATA_FLAG_DISABLED;
- ap->id = host->unique_id;
- ap->host = host;
+ ap->id = ata_unique_id++;
ap->ctl = ATA_DEVCTL_OBS;
- ap->host_set = host_set;
+ ap->host = host;
ap->dev = ent->dev;
ap->port_no = port_no;
- ap->hard_port_no =
- ent->legacy_mode ? ent->hard_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;
+ if (port_no == 1 && ent->pinfo2) {
+ ap->pio_mask = ent->pinfo2->pio_mask;
+ ap->mwdma_mask = ent->pinfo2->mwdma_mask;
+ ap->udma_mask = ent->pinfo2->udma_mask;
+ ap->flags |= ent->pinfo2->flags;
+ ap->ops = ent->pinfo2->port_ops;
+ } else {
+ ap->pio_mask = ent->pio_mask;
+ ap->mwdma_mask = ent->mwdma_mask;
+ ap->udma_mask = ent->udma_mask;
+ ap->flags |= ent->port_flags;
+ ap->ops = ent->port_ops;
+ }
ap->hw_sata_spd_limit = UINT_MAX;
ap->active_tag = ATA_TAG_POISON;
ap->last_ctl = 0xFF;
@@ -5303,9 +5342,30 @@ static void ata_host_init(struct ata_port *ap, struct Scsi_Host *host,
}
/**
- * ata_host_add - Attach low-level ATA driver to system
+ * 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->scsi_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
+ * @host: Collections of ports to which we add
* @port_no: Port number associated with this host
*
* Attach low-level ATA driver to system.
@@ -5316,43 +5376,55 @@ static void ata_host_init(struct ata_port *ap, struct Scsi_Host *host,
* RETURNS:
* New ata_port on success, for NULL on error.
*/
-
-static struct ata_port * ata_host_add(const struct ata_probe_ent *ent,
- struct ata_host_set *host_set,
+static struct ata_port * ata_port_add(const struct ata_probe_ent *ent,
+ struct ata_host *host,
unsigned int port_no)
{
- struct Scsi_Host *host;
+ struct Scsi_Host *shost;
struct ata_port *ap;
- int rc;
DPRINTK("ENTER\n");
if (!ent->port_ops->error_handler &&
- !(ent->host_flags & (ATA_FLAG_SATA_RESET | ATA_FLAG_SRST))) {
+ !(ent->port_flags & (ATA_FLAG_SATA_RESET | ATA_FLAG_SRST))) {
printk(KERN_ERR "ata%u: no reset mechanism available\n",
port_no);
return NULL;
}
- host = scsi_host_alloc(ent->sht, sizeof(struct ata_port));
- if (!host)
+ shost = scsi_host_alloc(ent->sht, sizeof(struct ata_port));
+ if (!shost)
return NULL;
- host->transportt = &ata_scsi_transport_template;
+ shost->transportt = &ata_scsi_transport_template;
- ap = ata_shost_to_port(host);
+ ap = ata_shost_to_port(shost);
- ata_host_init(ap, host, host_set, ent, port_no);
-
- rc = ap->ops->port_start(ap);
- if (rc)
- goto err_out;
+ ata_port_init(ap, host, ent, port_no);
+ ata_port_init_shost(ap, shost);
return ap;
+}
-err_out:
- scsi_host_put(host);
- return NULL;
+/**
+ * ata_sas_host_init - Initialize a host struct
+ * @host: host to initialize
+ * @dev: device host is attached to
+ * @flags: host flags
+ * @ops: port_ops
+ *
+ * LOCKING:
+ * PCI/etc. bus probe sem.
+ *
+ */
+
+void ata_host_init(struct ata_host *host, struct device *dev,
+ unsigned long flags, const struct ata_port_operations *ops)
+{
+ spin_lock_init(&host->lock);
+ host->dev = dev;
+ host->flags = flags;
+ host->ops = ops;
}
/**
@@ -5375,78 +5447,106 @@ err_out:
*/
int ata_device_add(const struct ata_probe_ent *ent)
{
- unsigned int count = 0, i;
+ unsigned int i;
struct device *dev = ent->dev;
- struct ata_host_set *host_set;
+ struct ata_host *host;
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)
+ host = kzalloc(sizeof(struct ata_host) +
+ (ent->n_ports * sizeof(void *)), GFP_KERNEL);
+ if (!host)
return 0;
- spin_lock_init(&host_set->lock);
- host_set->dev = dev;
- host_set->n_ports = ent->n_ports;
- host_set->irq = ent->irq;
- host_set->mmio_base = ent->mmio_base;
- host_set->private_data = ent->private_data;
- host_set->ops = ent->port_ops;
- host_set->flags = ent->host_set_flags;
+ ata_host_init(host, dev, ent->_host_flags, ent->port_ops);
+ host->n_ports = ent->n_ports;
+ host->irq = ent->irq;
+ host->irq2 = ent->irq2;
+ host->mmio_base = ent->mmio_base;
+ host->private_data = ent->private_data;
/* register each port bound to this device */
- for (i = 0; i < ent->n_ports; i++) {
+ for (i = 0; i < host->n_ports; i++) {
struct ata_port *ap;
unsigned long xfer_mode_mask;
+ int irq_line = ent->irq;
- ap = ata_host_add(ent, host_set, i);
+ ap = ata_port_add(ent, host, i);
if (!ap)
goto err_out;
- host_set->ports[i] = ap;
+ host->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->ports[i] = NULL;
+ scsi_host_put(ap->scsi_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 %lu\n",
+ "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,
- ent->irq);
+ irq_line);
ata_chk_status(ap);
- host_set->ops->irq_clear(ap);
+ host->ops->irq_clear(ap);
ata_eh_freeze_port(ap); /* freeze port before requesting IRQ */
- count++;
}
- if (!count)
- goto err_free_ret;
-
- /* obtain irq, that is shared between channels */
+ /* 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);
+ DRV_NAME, host);
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);
+ 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 < count; i++) {
- struct ata_port *ap;
+ for (i = 0; i < host->n_ports; i++) {
+ struct ata_port *ap = host->ports[i];
u32 scontrol;
int rc;
- ap = host_set->ports[i];
-
/* init sata_spd_limit to the current value */
if (sata_scr_read(ap, SCR_CONTROL, &scontrol) == 0) {
int spd = (scontrol >> 4) & 0xf;
@@ -5454,7 +5554,7 @@ int ata_device_add(const struct ata_probe_ent *ent)
}
ap->sata_spd_limit = ap->hw_sata_spd_limit;
- rc = scsi_add_host(ap->host, dev);
+ rc = scsi_add_host(ap->scsi_host, dev);
if (rc) {
ata_port_printk(ap, KERN_ERR, "scsi_add_host failed\n");
/* FIXME: do something useful here */
@@ -5502,27 +5602,29 @@ int ata_device_add(const struct ata_probe_ent *ent)
/* probes are done, now scan each port's disk(s) */
DPRINTK("host probe begin\n");
- for (i = 0; i < count; i++) {
- struct ata_port *ap = host_set->ports[i];
+ for (i = 0; i < host->n_ports; i++) {
+ struct ata_port *ap = host->ports[i];
ata_scsi_scan_host(ap);
}
- dev_set_drvdata(dev, host_set);
+ dev_set_drvdata(dev, host);
VPRINTK("EXIT, returning %u\n", ent->n_ports);
return ent->n_ports; /* success */
+err_out_free_irq:
+ free_irq(ent->irq, host);
err_out:
- for (i = 0; i < count; i++) {
- struct ata_port *ap = host_set->ports[i];
+ for (i = 0; i < host->n_ports; i++) {
+ struct ata_port *ap = host->ports[i];
if (ap) {
ap->ops->port_stop(ap);
- scsi_host_put(ap->host);
+ scsi_host_put(ap->scsi_host);
}
}
-err_free_ret:
- kfree(host_set);
+
+ kfree(host);
VPRINTK("EXIT, returning 0\n");
return 0;
}
@@ -5582,12 +5684,12 @@ void ata_port_detach(struct ata_port *ap)
skip_eh:
/* remove the associated SCSI host */
- scsi_remove_host(ap->host);
+ scsi_remove_host(ap->scsi_host);
}
/**
- * ata_host_set_remove - PCI layer callback for device removal
- * @host_set: ATA host set that was removed
+ * ata_host_remove - PCI layer callback for device removal
+ * @host: ATA host set that was removed
*
* Unregister all objects associated with this host set. Free those
* objects.
@@ -5596,36 +5698,39 @@ void ata_port_detach(struct ata_port *ap)
* Inherited from calling layer (may sleep).
*/
-void ata_host_set_remove(struct ata_host_set *host_set)
+void ata_host_remove(struct ata_host *host)
{
unsigned int i;
- for (i = 0; i < host_set->n_ports; i++)
- ata_port_detach(host_set->ports[i]);
+ for (i = 0; i < host->n_ports; i++)
+ ata_port_detach(host->ports[i]);
- free_irq(host_set->irq, host_set);
+ free_irq(host->irq, host);
+ if (host->irq2)
+ free_irq(host->irq2, host);
- for (i = 0; i < host_set->n_ports; i++) {
- struct ata_port *ap = host_set->ports[i];
+ for (i = 0; i < host->n_ports; i++) {
+ struct ata_port *ap = host->ports[i];
- ata_scsi_release(ap->host);
+ ata_scsi_release(ap->scsi_host);
if ((ap->flags & ATA_FLAG_NO_LEGACY) == 0) {
struct ata_ioports *ioaddr = &ap->ioaddr;
- if (ioaddr->cmd_addr == 0x1f0)
- release_region(0x1f0, 8);
- else if (ioaddr->cmd_addr == 0x170)
- release_region(0x170, 8);
+ /* 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);
+ scsi_host_put(ap->scsi_host);
}
- if (host_set->ops->host_stop)
- host_set->ops->host_stop(host_set);
+ if (host->ops->host_stop)
+ host->ops->host_stop(host);
- kfree(host_set);
+ kfree(host);
}
/**
@@ -5642,9 +5747,9 @@ void ata_host_set_remove(struct ata_host_set *host_set)
* One.
*/
-int ata_scsi_release(struct Scsi_Host *host)
+int ata_scsi_release(struct Scsi_Host *shost)
{
- struct ata_port *ap = ata_shost_to_port(host);
+ struct ata_port *ap = ata_shost_to_port(shost);
DPRINTK("ENTER\n");
@@ -5655,6 +5760,31 @@ int ata_scsi_release(struct Scsi_Host *host)
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->port_flags = port->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
@@ -5684,11 +5814,11 @@ void ata_std_ports(struct ata_ioports *ioaddr)
#ifdef CONFIG_PCI
-void ata_pci_host_stop (struct ata_host_set *host_set)
+void ata_pci_host_stop (struct ata_host *host)
{
- struct pci_dev *pdev = to_pci_dev(host_set->dev);
+ struct pci_dev *pdev = to_pci_dev(host->dev);
- pci_iounmap(pdev, host_set->mmio_base);
+ pci_iounmap(pdev, host->mmio_base);
}
/**
@@ -5708,12 +5838,9 @@ void ata_pci_host_stop (struct ata_host_set *host_set)
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);
- struct ata_host_set *host_set2 = host_set->next;
+ struct ata_host *host = dev_get_drvdata(dev);
- ata_host_set_remove(host_set);
- if (host_set2)
- ata_host_set_remove(host_set2);
+ ata_host_remove(host);
pci_release_regions(pdev);
pci_disable_device(pdev);
@@ -5754,11 +5881,11 @@ int pci_test_config_bits(struct pci_dev *pdev, const struct pci_bits *bits)
return (tmp == bits->val) ? 1 : 0;
}
-void ata_pci_device_do_suspend(struct pci_dev *pdev, pm_message_t state)
+void ata_pci_device_do_suspend(struct pci_dev *pdev, pm_message_t mesg)
{
pci_save_state(pdev);
- if (state.event == PM_EVENT_SUSPEND) {
+ if (mesg.event == PM_EVENT_SUSPEND) {
pci_disable_device(pdev);
pci_set_power_state(pdev, PCI_D3hot);
}
@@ -5772,37 +5899,26 @@ void ata_pci_device_do_resume(struct pci_dev *pdev)
pci_set_master(pdev);
}
-int ata_pci_device_suspend(struct pci_dev *pdev, pm_message_t state)
+int ata_pci_device_suspend(struct pci_dev *pdev, pm_message_t mesg)
{
- struct ata_host_set *host_set = dev_get_drvdata(&pdev->dev);
+ struct ata_host *host = dev_get_drvdata(&pdev->dev);
int rc = 0;
- rc = ata_host_set_suspend(host_set, state);
+ rc = ata_host_suspend(host, mesg);
if (rc)
return rc;
- if (host_set->next) {
- rc = ata_host_set_suspend(host_set->next, state);
- if (rc) {
- ata_host_set_resume(host_set);
- return rc;
- }
- }
-
- ata_pci_device_do_suspend(pdev, state);
+ 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);
+ struct ata_host *host = dev_get_drvdata(&pdev->dev);
ata_pci_device_do_resume(pdev);
- ata_host_set_resume(host_set);
- if (host_set->next)
- ata_host_set_resume(host_set->next);
-
+ ata_host_resume(host);
return 0;
}
#endif /* CONFIG_PCI */
@@ -5901,6 +6017,39 @@ u32 ata_wait_register(void __iomem *reg, u32 mask, u32 val,
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
@@ -5911,11 +6060,13 @@ u32 ata_wait_register(void __iomem *reg, u32 mask, u32 val,
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_init);
EXPORT_SYMBOL_GPL(ata_device_add);
EXPORT_SYMBOL_GPL(ata_port_detach);
-EXPORT_SYMBOL_GPL(ata_host_set_remove);
+EXPORT_SYMBOL_GPL(ata_host_remove);
EXPORT_SYMBOL_GPL(ata_sg_init);
EXPORT_SYMBOL_GPL(ata_sg_init_one);
EXPORT_SYMBOL_GPL(ata_hsm_move);
@@ -5982,8 +6133,8 @@ 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_host_suspend);
+EXPORT_SYMBOL_GPL(ata_host_resume);
EXPORT_SYMBOL_GPL(ata_id_string);
EXPORT_SYMBOL_GPL(ata_id_c_string);
EXPORT_SYMBOL_GPL(ata_scsi_simulate);
diff --git a/drivers/scsi/libata-eh.c b/drivers/ata/libata-eh.c
similarity index 99%
rename from drivers/scsi/libata-eh.c
rename to drivers/ata/libata-eh.c
index 2c34af99627d..3fa80f09f2ae 100644
--- a/drivers/scsi/libata-eh.c
+++ b/drivers/ata/libata-eh.c
@@ -38,7 +38,7 @@
#include
#include
#include
-#include "scsi_transport_api.h"
+#include "../scsi/scsi_transport_api.h"
#include
@@ -199,7 +199,7 @@ void ata_scsi_error(struct Scsi_Host *host)
/* synchronize with port task */
ata_port_flush_task(ap);
- /* synchronize with host_set lock and sort out timeouts */
+ /* synchronize with host lock and sort out timeouts */
/* For new EH, all qcs are finished in one of three ways -
* normal completion, error completion, and SCSI timeout.
@@ -376,7 +376,7 @@ void ata_port_wait_eh(struct ata_port *ap)
spin_unlock_irqrestore(ap->lock, flags);
/* make sure SCSI EH is complete */
- if (scsi_host_in_recovery(ap->host)) {
+ if (scsi_host_in_recovery(ap->scsi_host)) {
msleep(10);
goto retry;
}
@@ -485,7 +485,7 @@ void ata_eng_timeout(struct ata_port *ap)
* other commands are drained.
*
* LOCKING:
- * spin_lock_irqsave(host_set lock)
+ * spin_lock_irqsave(host lock)
*/
void ata_qc_schedule_eh(struct ata_queued_cmd *qc)
{
@@ -512,14 +512,14 @@ void ata_qc_schedule_eh(struct ata_queued_cmd *qc)
* all commands are drained.
*
* LOCKING:
- * spin_lock_irqsave(host_set lock)
+ * spin_lock_irqsave(host 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);
+ scsi_schedule_eh(ap->scsi_host);
DPRINTK("port EH scheduled\n");
}
@@ -531,7 +531,7 @@ void ata_port_schedule_eh(struct ata_port *ap)
* Abort all active qc's of @ap and schedule EH.
*
* LOCKING:
- * spin_lock_irqsave(host_set lock)
+ * spin_lock_irqsave(host lock)
*
* RETURNS:
* Number of aborted qc's.
@@ -574,7 +574,7 @@ int ata_port_abort(struct ata_port *ap)
* is frozen.
*
* LOCKING:
- * spin_lock_irqsave(host_set lock)
+ * spin_lock_irqsave(host lock)
*/
static void __ata_port_freeze(struct ata_port *ap)
{
@@ -595,7 +595,7 @@ static void __ata_port_freeze(struct ata_port *ap)
* Abort and freeze @ap.
*
* LOCKING:
- * spin_lock_irqsave(host_set lock)
+ * spin_lock_irqsave(host lock)
*
* RETURNS:
* Number of aborted commands.
diff --git a/drivers/scsi/libata-scsi.c b/drivers/ata/libata-scsi.c
similarity index 94%
rename from drivers/scsi/libata-scsi.c
rename to drivers/ata/libata-scsi.c
index e92c31d698ff..3986ec8741b4 100644
--- a/drivers/scsi/libata-scsi.c
+++ b/drivers/ata/libata-scsi.c
@@ -321,7 +321,7 @@ int ata_scsi_ioctl(struct scsi_device *scsidev, int cmd, void __user *arg)
* current command.
*
* LOCKING:
- * spin_lock_irqsave(host_set lock)
+ * spin_lock_irqsave(host lock)
*
* RETURNS:
* Command allocated, or %NULL if none available.
@@ -400,7 +400,7 @@ void ata_dump_status(unsigned id, struct ata_taskfile *tf)
/**
* ata_scsi_device_suspend - suspend ATA device associated with sdev
* @sdev: the SCSI device to suspend
- * @state: target power management state
+ * @mesg: target power management message
*
* Request suspend EH action on the ATA device associated with
* @sdev and wait for the operation to complete.
@@ -411,7 +411,7 @@ void ata_dump_status(unsigned id, struct ata_taskfile *tf)
* RETURNS:
* 0 on success, -errno otherwise.
*/
-int ata_scsi_device_suspend(struct scsi_device *sdev, pm_message_t state)
+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);
@@ -438,7 +438,7 @@ int ata_scsi_device_suspend(struct scsi_device *sdev, pm_message_t state)
/* request suspend */
action = ATA_EH_SUSPEND;
- if (state.event != PM_EVENT_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;
@@ -463,7 +463,7 @@ int ata_scsi_device_suspend(struct scsi_device *sdev, pm_message_t state)
spin_unlock_irqrestore(ap->lock, flags);
out:
if (rc == 0)
- sdev->sdev_gendev.power.power_state = state;
+ sdev->sdev_gendev.power.power_state = mesg;
return rc;
}
@@ -537,7 +537,7 @@ int ata_scsi_device_resume(struct scsi_device *sdev)
* format sense blocks.
*
* LOCKING:
- * spin_lock_irqsave(host_set lock)
+ * spin_lock_irqsave(host lock)
*/
void ata_to_sense_error(unsigned id, u8 drv_stat, u8 drv_err, u8 *sk, u8 *asc,
u8 *ascq, int verbose)
@@ -649,7 +649,7 @@ void ata_to_sense_error(unsigned id, u8 drv_stat, u8 drv_err, u8 *sk, u8 *asc,
* block. Clear sense key, ASC & ASCQ if there is no error.
*
* LOCKING:
- * spin_lock_irqsave(host_set lock)
+ * spin_lock_irqsave(host lock)
*/
void ata_gen_ata_desc_sense(struct ata_queued_cmd *qc)
{
@@ -918,7 +918,7 @@ int ata_scsi_change_queue_depth(struct scsi_device *sdev, int queue_depth)
* [See SAT revision 5 at www.t10.org]
*
* LOCKING:
- * spin_lock_irqsave(host_set lock)
+ * spin_lock_irqsave(host lock)
*
* RETURNS:
* Zero on success, non-zero on error.
@@ -986,7 +986,7 @@ invalid_fld:
* FLUSH CACHE EXT.
*
* LOCKING:
- * spin_lock_irqsave(host_set lock)
+ * spin_lock_irqsave(host lock)
*
* RETURNS:
* Zero on success, non-zero on error.
@@ -1109,7 +1109,7 @@ static void scsi_16_lba_len(const u8 *scsicmd, u64 *plba, u32 *plen)
* Converts SCSI VERIFY command to an ATA READ VERIFY command.
*
* LOCKING:
- * spin_lock_irqsave(host_set lock)
+ * spin_lock_irqsave(host lock)
*
* RETURNS:
* Zero on success, non-zero on error.
@@ -1233,7 +1233,7 @@ nothing_to_do:
* %WRITE_16 are currently supported.
*
* LOCKING:
- * spin_lock_irqsave(host_set lock)
+ * spin_lock_irqsave(host lock)
*
* RETURNS:
* Zero on success, non-zero on error.
@@ -1467,7 +1467,7 @@ static void ata_scsi_qc_complete(struct ata_queued_cmd *qc)
* issued to @dev.
*
* LOCKING:
- * spin_lock_irqsave(host_set lock)
+ * spin_lock_irqsave(host lock)
*
* RETURNS:
* 1 if deferring is needed, 0 otherwise.
@@ -1510,7 +1510,7 @@ static int ata_scmd_need_defer(struct ata_device *dev, int is_io)
* termination.
*
* LOCKING:
- * spin_lock_irqsave(host_set lock)
+ * spin_lock_irqsave(host lock)
*
* RETURNS:
* 0 on success, SCSI_ML_QUEUE_DEVICE_BUSY if the command
@@ -1589,7 +1589,7 @@ defer:
* Maps buffer contained within SCSI command @cmd.
*
* LOCKING:
- * spin_lock_irqsave(host_set lock)
+ * spin_lock_irqsave(host lock)
*
* RETURNS:
* Length of response buffer.
@@ -1623,7 +1623,7 @@ static unsigned int ata_scsi_rbuf_get(struct scsi_cmnd *cmd, u8 **buf_out)
* Unmaps response buffer contained within @cmd.
*
* LOCKING:
- * spin_lock_irqsave(host_set lock)
+ * spin_lock_irqsave(host lock)
*/
static inline void ata_scsi_rbuf_put(struct scsi_cmnd *cmd, u8 *buf)
@@ -1649,7 +1649,7 @@ static inline void ata_scsi_rbuf_put(struct scsi_cmnd *cmd, u8 *buf)
* and sense buffer are assumed to be set).
*
* LOCKING:
- * spin_lock_irqsave(host_set lock)
+ * spin_lock_irqsave(host lock)
*/
void ata_scsi_rbuf_fill(struct ata_scsi_args *args,
@@ -1680,7 +1680,7 @@ void ata_scsi_rbuf_fill(struct ata_scsi_args *args,
* with non-VPD INQUIRY command output.
*
* LOCKING:
- * spin_lock_irqsave(host_set lock)
+ * spin_lock_irqsave(host lock)
*/
unsigned int ata_scsiop_inq_std(struct ata_scsi_args *args, u8 *rbuf,
@@ -1736,7 +1736,7 @@ unsigned int ata_scsiop_inq_std(struct ata_scsi_args *args, u8 *rbuf,
* Returns list of inquiry VPD pages available.
*
* LOCKING:
- * spin_lock_irqsave(host_set lock)
+ * spin_lock_irqsave(host lock)
*/
unsigned int ata_scsiop_inq_00(struct ata_scsi_args *args, u8 *rbuf,
@@ -1764,7 +1764,7 @@ unsigned int ata_scsiop_inq_00(struct ata_scsi_args *args, u8 *rbuf,
* Returns ATA device serial number.
*
* LOCKING:
- * spin_lock_irqsave(host_set lock)
+ * spin_lock_irqsave(host lock)
*/
unsigned int ata_scsiop_inq_80(struct ata_scsi_args *args, u8 *rbuf,
@@ -1797,7 +1797,7 @@ unsigned int ata_scsiop_inq_80(struct ata_scsi_args *args, u8 *rbuf,
* name ("ATA "), model and serial numbers.
*
* LOCKING:
- * spin_lock_irqsave(host_set lock)
+ * spin_lock_irqsave(host lock)
*/
unsigned int ata_scsiop_inq_83(struct ata_scsi_args *args, u8 *rbuf,
@@ -1849,7 +1849,7 @@ unsigned int ata_scsiop_inq_83(struct ata_scsi_args *args, u8 *rbuf,
* that the caller should successfully complete this SCSI command.
*
* LOCKING:
- * spin_lock_irqsave(host_set lock)
+ * spin_lock_irqsave(host lock)
*/
unsigned int ata_scsiop_noop(struct ata_scsi_args *args, u8 *rbuf,
@@ -1990,7 +1990,7 @@ static int ata_dev_supports_fua(u16 *id)
* descriptor for other device types.
*
* LOCKING:
- * spin_lock_irqsave(host_set lock)
+ * spin_lock_irqsave(host lock)
*/
unsigned int ata_scsiop_mode_sense(struct ata_scsi_args *args, u8 *rbuf,
@@ -2129,7 +2129,7 @@ saving_not_supp:
* Simulate READ CAPACITY commands.
*
* LOCKING:
- * spin_lock_irqsave(host_set lock)
+ * spin_lock_irqsave(host lock)
*/
unsigned int ata_scsiop_read_cap(struct ata_scsi_args *args, u8 *rbuf,
@@ -2204,7 +2204,7 @@ unsigned int ata_scsiop_read_cap(struct ata_scsi_args *args, u8 *rbuf,
* Simulate REPORT LUNS command.
*
* LOCKING:
- * spin_lock_irqsave(host_set lock)
+ * spin_lock_irqsave(host lock)
*/
unsigned int ata_scsiop_report_luns(struct ata_scsi_args *args, u8 *rbuf,
@@ -2256,7 +2256,7 @@ void ata_scsi_set_sense(struct scsi_cmnd *cmd, u8 sk, u8 asc, u8 ascq)
* and the specified additional sense codes.
*
* LOCKING:
- * spin_lock_irqsave(host_set lock)
+ * spin_lock_irqsave(host lock)
*/
void ata_scsi_badcmd(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *), u8 asc, u8 ascq)
@@ -2421,7 +2421,7 @@ static void atapi_qc_complete(struct ata_queued_cmd *qc)
* @scsicmd: SCSI CDB associated with this PACKET command
*
* LOCKING:
- * spin_lock_irqsave(host_set lock)
+ * spin_lock_irqsave(host lock)
*
* RETURNS:
* Zero on success, non-zero on failure.
@@ -2500,7 +2500,7 @@ static struct ata_device * __ata_scsi_find_dev(struct ata_port *ap,
* Determine if commands should be sent to the specified device.
*
* LOCKING:
- * spin_lock_irqsave(host_set lock)
+ * spin_lock_irqsave(host lock)
*
* RETURNS:
* 0 if commands are not allowed / 1 if commands are allowed
@@ -2534,7 +2534,7 @@ static int ata_scsi_dev_enabled(struct ata_device *dev)
* SCSI command to be sent.
*
* LOCKING:
- * spin_lock_irqsave(host_set lock)
+ * spin_lock_irqsave(host lock)
*
* RETURNS:
* Associated ATA device, or %NULL if not found.
@@ -2808,7 +2808,7 @@ static inline int __ata_scsi_queuecmd(struct scsi_cmnd *cmd,
* ATA and ATAPI devices appearing as SCSI devices.
*
* LOCKING:
- * Releases scsi-layer-held lock, and obtains host_set lock.
+ * Releases scsi-layer-held lock, and obtains host lock.
*
* RETURNS:
* Return value from __ata_scsi_queuecmd() if @cmd can be queued,
@@ -2852,7 +2852,7 @@ int ata_scsi_queuecmd(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *))
* that can be handled internally.
*
* LOCKING:
- * spin_lock_irqsave(host_set lock)
+ * spin_lock_irqsave(host lock)
*/
void ata_scsi_simulate(struct ata_device *dev, struct scsi_cmnd *cmd,
@@ -2944,7 +2944,7 @@ void ata_scsi_scan_host(struct ata_port *ap)
if (!ata_dev_enabled(dev) || dev->sdev)
continue;
- sdev = __scsi_add_device(ap->host, 0, i, 0, NULL);
+ sdev = __scsi_add_device(ap->scsi_host, 0, i, 0, NULL);
if (!IS_ERR(sdev)) {
dev->sdev = sdev;
scsi_device_put(sdev);
@@ -2958,11 +2958,11 @@ void ata_scsi_scan_host(struct ata_port *ap)
*
* 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
+ * function is called with host lock which protects dev->sdev
* against clearing.
*
* LOCKING:
- * spin_lock_irqsave(host_set lock)
+ * spin_lock_irqsave(host lock)
*
* RETURNS:
* 1 if attached SCSI device exists, 0 otherwise.
@@ -2998,16 +2998,16 @@ static void ata_scsi_remove_dev(struct ata_device *dev)
* be removed if there is __scsi_device_get() interface which
* increments reference counts regardless of device state.
*/
- mutex_lock(&ap->host->scan_mutex);
+ mutex_lock(&ap->scsi_host->scan_mutex);
spin_lock_irqsave(ap->lock, flags);
- /* clearing dev->sdev is protected by host_set lock */
+ /* clearing dev->sdev is protected by host 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
+ * away underneath us after the host lock and
* scan_mutex are released. Hold onto it.
*/
if (scsi_device_get(sdev) == 0) {
@@ -3024,7 +3024,7 @@ static void ata_scsi_remove_dev(struct ata_device *dev)
}
spin_unlock_irqrestore(ap->lock, flags);
- mutex_unlock(&ap->host->scan_mutex);
+ mutex_unlock(&ap->scsi_host->scan_mutex);
if (sdev) {
ata_dev_printk(dev, KERN_INFO, "detaching (SCSI %s)\n",
@@ -3171,3 +3171,152 @@ void ata_scsi_dev_rescan(void *data)
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
+ * @shost: 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 *host,
+ struct ata_port_info *port_info,
+ struct Scsi_Host *shost)
+{
+ struct ata_port *ap = kzalloc(sizeof(*ap), GFP_KERNEL);
+ struct ata_probe_ent *ent;
+
+ if (!ap)
+ return NULL;
+
+ ent = ata_probe_ent_alloc(host->dev, port_info);
+ if (!ent) {
+ kfree(ap);
+ return NULL;
+ }
+
+ ata_port_init(ap, host, ent, 0);
+ ap->lock = shost->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-bmdma.c b/drivers/ata/libata-sff.c
similarity index 89%
rename from drivers/scsi/libata-bmdma.c
rename to drivers/ata/libata-sff.c
index 9ce221f25954..688bb55e197a 100644
--- a/drivers/scsi/libata-bmdma.c
+++ b/drivers/ata/libata-sff.c
@@ -193,7 +193,7 @@ void ata_tf_load(struct ata_port *ap, const struct ata_taskfile *tf)
* synchronization with interrupt handler / other threads.
*
* LOCKING:
- * spin_lock_irqsave(host_set lock)
+ * spin_lock_irqsave(host lock)
*/
static void ata_exec_command_pio(struct ata_port *ap, const struct ata_taskfile *tf)
@@ -216,7 +216,7 @@ static void ata_exec_command_pio(struct ata_port *ap, const struct ata_taskfile
* FIXME: missing write posting for 400nS delay enforcement
*
* LOCKING:
- * spin_lock_irqsave(host_set lock)
+ * spin_lock_irqsave(host lock)
*/
static void ata_exec_command_mmio(struct ata_port *ap, const struct ata_taskfile *tf)
@@ -237,7 +237,7 @@ static void ata_exec_command_mmio(struct ata_port *ap, const struct ata_taskfile
* synchronization with interrupt handler / other threads.
*
* LOCKING:
- * spin_lock_irqsave(host_set lock)
+ * spin_lock_irqsave(host lock)
*/
void ata_exec_command(struct ata_port *ap, const struct ata_taskfile *tf)
{
@@ -422,7 +422,7 @@ u8 ata_altstatus(struct ata_port *ap)
* @qc: Info associated with this ATA transaction.
*
* LOCKING:
- * spin_lock_irqsave(host_set lock)
+ * spin_lock_irqsave(host lock)
*/
static void ata_bmdma_setup_mmio (struct ata_queued_cmd *qc)
@@ -452,7 +452,7 @@ static void ata_bmdma_setup_mmio (struct ata_queued_cmd *qc)
* @qc: Info associated with this ATA transaction.
*
* LOCKING:
- * spin_lock_irqsave(host_set lock)
+ * spin_lock_irqsave(host lock)
*/
static void ata_bmdma_start_mmio (struct ata_queued_cmd *qc)
@@ -483,7 +483,7 @@ static void ata_bmdma_start_mmio (struct ata_queued_cmd *qc)
* @qc: Info associated with this ATA transaction.
*
* LOCKING:
- * spin_lock_irqsave(host_set lock)
+ * spin_lock_irqsave(host lock)
*/
static void ata_bmdma_setup_pio (struct ata_queued_cmd *qc)
@@ -511,7 +511,7 @@ static void ata_bmdma_setup_pio (struct ata_queued_cmd *qc)
* @qc: Info associated with this ATA transaction.
*
* LOCKING:
- * spin_lock_irqsave(host_set lock)
+ * spin_lock_irqsave(host lock)
*/
static void ata_bmdma_start_pio (struct ata_queued_cmd *qc)
@@ -535,7 +535,7 @@ static void ata_bmdma_start_pio (struct ata_queued_cmd *qc)
* May be used as the bmdma_start() entry in ata_port_operations.
*
* LOCKING:
- * spin_lock_irqsave(host_set lock)
+ * spin_lock_irqsave(host lock)
*/
void ata_bmdma_start(struct ata_queued_cmd *qc)
{
@@ -557,7 +557,7 @@ void ata_bmdma_start(struct ata_queued_cmd *qc)
* May be used as the bmdma_setup() entry in ata_port_operations.
*
* LOCKING:
- * spin_lock_irqsave(host_set lock)
+ * spin_lock_irqsave(host lock)
*/
void ata_bmdma_setup(struct ata_queued_cmd *qc)
{
@@ -577,7 +577,7 @@ void ata_bmdma_setup(struct ata_queued_cmd *qc)
* May be used as the irq_clear() entry in ata_port_operations.
*
* LOCKING:
- * spin_lock_irqsave(host_set lock)
+ * spin_lock_irqsave(host lock)
*/
void ata_bmdma_irq_clear(struct ata_port *ap)
@@ -605,7 +605,7 @@ void ata_bmdma_irq_clear(struct ata_port *ap)
* May be used as the bmdma_status() entry in ata_port_operations.
*
* LOCKING:
- * spin_lock_irqsave(host_set lock)
+ * spin_lock_irqsave(host lock)
*/
u8 ata_bmdma_status(struct ata_port *ap)
@@ -629,7 +629,7 @@ u8 ata_bmdma_status(struct ata_port *ap)
* May be used as the bmdma_stop() entry in ata_port_operations.
*
* LOCKING:
- * spin_lock_irqsave(host_set lock)
+ * spin_lock_irqsave(host lock)
*/
void ata_bmdma_stop(struct ata_queued_cmd *qc)
@@ -797,32 +797,6 @@ void ata_bmdma_post_internal_cmd(struct ata_queued_cmd *qc)
}
#ifdef CONFIG_PCI
-static struct ata_probe_ent *
-ata_probe_ent_alloc(struct device *dev, const struct ata_port_info *port)
-{
- struct ata_probe_ent *probe_ent;
-
- probe_ent = kzalloc(sizeof(*probe_ent), GFP_KERNEL);
- if (!probe_ent) {
- printk(KERN_ERR DRV_NAME "(%s): out of memory\n",
- kobject_name(&(dev->kobj)));
- return NULL;
- }
-
- INIT_LIST_HEAD(&probe_ent->node);
- probe_ent->dev = dev;
-
- probe_ent->sht = port->sht;
- probe_ent->host_flags = port->host_flags;
- probe_ent->pio_mask = port->pio_mask;
- probe_ent->mwdma_mask = port->mwdma_mask;
- probe_ent->udma_mask = port->udma_mask;
- probe_ent->port_ops = port->port_ops;
-
- return probe_ent;
-}
-
-
/**
* ata_pci_init_native_mode - Initialize native-mode driver
* @pdev: pci device to be initialized
@@ -864,7 +838,7 @@ ata_pci_init_native_mode(struct pci_dev *pdev, struct ata_port_info **port, int
bmdma = pci_resource_start(pdev, 4);
if (bmdma) {
if (inb(bmdma + 2) & 0x80)
- probe_ent->host_set_flags |= ATA_HOST_SIMPLEX;
+ probe_ent->_host_flags |= ATA_HOST_SIMPLEX;
probe_ent->port[p].bmdma_addr = bmdma;
}
ata_std_ports(&probe_ent->port[p]);
@@ -880,10 +854,11 @@ ata_pci_init_native_mode(struct pci_dev *pdev, struct ata_port_info **port, int
if (bmdma) {
bmdma += 8;
if(inb(bmdma + 2) & 0x80)
- probe_ent->host_set_flags |= ATA_HOST_SIMPLEX;
+ probe_ent->_host_flags |= ATA_HOST_SIMPLEX;
probe_ent->port[p].bmdma_addr = bmdma;
}
ata_std_ports(&probe_ent->port[p]);
+ probe_ent->pinfo2 = port[1];
p++;
}
@@ -893,44 +868,49 @@ ata_pci_init_native_mode(struct pci_dev *pdev, struct ata_port_info **port, int
static struct ata_probe_ent *ata_pci_init_legacy_port(struct pci_dev *pdev,
- struct ata_port_info *port, int port_num)
+ struct ata_port_info **port, int port_mask)
{
struct ata_probe_ent *probe_ent;
- unsigned long bmdma;
+ unsigned long bmdma = pci_resource_start(pdev, 4);
- probe_ent = ata_probe_ent_alloc(pci_dev_to_dev(pdev), port);
+ probe_ent = ata_probe_ent_alloc(pci_dev_to_dev(pdev), port[0]);
if (!probe_ent)
return NULL;
- probe_ent->legacy_mode = 1;
- probe_ent->n_ports = 1;
- probe_ent->hard_port_no = port_num;
- probe_ent->private_data = port->private_data;
+ probe_ent->n_ports = 2;
+ probe_ent->private_data = port[0]->private_data;
- switch(port_num)
- {
- case 0:
- probe_ent->irq = 14;
- probe_ent->port[0].cmd_addr = 0x1f0;
- probe_ent->port[0].altstatus_addr =
- probe_ent->port[0].ctl_addr = 0x3f6;
- break;
- case 1:
+ 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_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[0].cmd_addr = 0x170;
- probe_ent->port[0].altstatus_addr =
- probe_ent->port[0].ctl_addr = 0x376;
- break;
- }
-
- bmdma = pci_resource_start(pdev, 4);
- if (bmdma != 0) {
- bmdma += 8 * port_num;
- 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]);
+ 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_flags |= ATA_HOST_SIMPLEX;
+ }
+ ata_std_ports(&probe_ent->port[1]);
+ probe_ent->pinfo2 = port[1];
+ } else
+ probe_ent->dummy_port_mask |= ATA_PORT_SECONDARY;
return probe_ent;
}
@@ -950,6 +930,10 @@ static struct ata_probe_ent *ata_pci_init_legacy_port(struct pci_dev *pdev,
* 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).
*
@@ -960,7 +944,7 @@ static struct ata_probe_ent *ata_pci_init_legacy_port(struct pci_dev *pdev,
int ata_pci_init_one (struct pci_dev *pdev, struct ata_port_info **port_info,
unsigned int n_ports)
{
- struct ata_probe_ent *probe_ent = NULL, *probe_ent2 = NULL;
+ struct ata_probe_ent *probe_ent = NULL;
struct ata_port_info *port[2];
u8 tmp8, mask;
unsigned int legacy_mode = 0;
@@ -975,7 +959,7 @@ int ata_pci_init_one (struct pci_dev *pdev, struct ata_port_info **port_info,
else
port[1] = port[0];
- if ((port[0]->host_flags & ATA_FLAG_NO_LEGACY) == 0
+ if ((port[0]->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);
@@ -1009,35 +993,44 @@ int ata_pci_init_one (struct pci_dev *pdev, struct ata_port_info **port_info,
goto err_out;
}
- /* FIXME: Should use platform specific mappers for legacy port ranges */
if (legacy_mode) {
- if (!request_region(0x1f0, 8, "libata")) {
+ if (!request_region(ATA_PRIMARY_CMD, 8, "libata")) {
struct resource *conflict, res;
- res.start = 0x1f0;
- res.end = 0x1f0 + 8 - 1;
+ res.start = ATA_PRIMARY_CMD;
+ res.end = ATA_PRIMARY_CMD + 8 - 1;
conflict = ____request_resource(&ioport_resource, &res);
+ while (conflict->child)
+ conflict = ____request_resource(conflict, &res);
if (!strcmp(conflict->name, "libata"))
- legacy_mode |= (1 << 0);
+ legacy_mode |= ATA_PORT_PRIMARY;
else {
disable_dev_on_err = 0;
- printk(KERN_WARNING "ata: 0x1f0 IDE port busy\n");
+ printk(KERN_WARNING "ata: 0x%0X IDE port busy\n" \
+ "ata: conflict with %s\n",
+ ATA_PRIMARY_CMD,
+ conflict->name);
}
} else
- legacy_mode |= (1 << 0);
+ legacy_mode |= ATA_PORT_PRIMARY;
- if (!request_region(0x170, 8, "libata")) {
+ if (!request_region(ATA_SECONDARY_CMD, 8, "libata")) {
struct resource *conflict, res;
- res.start = 0x170;
- res.end = 0x170 + 8 - 1;
+ res.start = ATA_SECONDARY_CMD;
+ res.end = ATA_SECONDARY_CMD + 8 - 1;
conflict = ____request_resource(&ioport_resource, &res);
+ while (conflict->child)
+ conflict = ____request_resource(conflict, &res);
if (!strcmp(conflict->name, "libata"))
- legacy_mode |= (1 << 1);
+ legacy_mode |= ATA_PORT_SECONDARY;
else {
disable_dev_on_err = 0;
- printk(KERN_WARNING "ata: 0x170 IDE port busy\n");
+ printk(KERN_WARNING "ata: 0x%X IDE port busy\n" \
+ "ata: conflict with %s\n",
+ ATA_SECONDARY_CMD,
+ conflict->name);
}
} else
- legacy_mode |= (1 << 1);
+ legacy_mode |= ATA_PORT_SECONDARY;
}
/* we have legacy mode, but all ports are unavailable */
@@ -1055,17 +1048,14 @@ int ata_pci_init_one (struct pci_dev *pdev, struct ata_port_info **port_info,
goto err_out_regions;
if (legacy_mode) {
- if (legacy_mode & (1 << 0))
- probe_ent = ata_pci_init_legacy_port(pdev, port[0], 0);
- if (legacy_mode & (1 << 1))
- probe_ent2 = ata_pci_init_legacy_port(pdev, port[1], 1);
+ 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 && !probe_ent2) {
+ if (!probe_ent) {
rc = -ENOMEM;
goto err_out_regions;
}
@@ -1073,35 +1063,17 @@ int ata_pci_init_one (struct pci_dev *pdev, struct ata_port_info **port_info,
pci_set_master(pdev);
/* FIXME: check ata_device_add return */
- if (legacy_mode) {
- struct device *dev = &pdev->dev;
- struct ata_host_set *host_set = NULL;
-
- if (legacy_mode & (1 << 0)) {
- ata_device_add(probe_ent);
- host_set = dev_get_drvdata(dev);
- }
-
- if (legacy_mode & (1 << 1)) {
- ata_device_add(probe_ent2);
- if (host_set) {
- host_set->next = dev_get_drvdata(dev);
- dev_set_drvdata(dev, host_set);
- }
- }
- } else
- ata_device_add(probe_ent);
+ ata_device_add(probe_ent);
kfree(probe_ent);
- kfree(probe_ent2);
return 0;
err_out_regions:
- if (legacy_mode & (1 << 0))
- release_region(0x1f0, 8);
- if (legacy_mode & (1 << 1))
- release_region(0x170, 8);
+ 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)
diff --git a/drivers/scsi/libata.h b/drivers/ata/libata.h
similarity index 94%
rename from drivers/scsi/libata.h
rename to drivers/ata/libata.h
index c325679d9b54..a5ecb71390a9 100644
--- a/drivers/scsi/libata.h
+++ b/drivers/ata/libata.h
@@ -69,6 +69,10 @@ 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 *host,
+ 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 */
@@ -107,6 +111,7 @@ extern void ata_scsi_rbuf_fill(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);
diff --git a/drivers/ata/pata_ali.c b/drivers/ata/pata_ali.c
new file mode 100644
index 000000000000..8448ee6e0eed
--- /dev/null
+++ b/drivers/ata/pata_ali.c
@@ -0,0 +1,679 @@
+/*
+ * pata_ali.c - ALI 15x3 PATA for new ATA layer
+ * (C) 2005 Red Hat Inc
+ * Alan Cox
+ *
+ * based in part upon
+ * linux/drivers/ide/pci/alim15x3.c Version 0.17 2003/01/02
+ *
+ * Copyright (C) 1998-2000 Michel Aubry, Maintainer
+ * Copyright (C) 1998-2000 Andrzej Krzysztofowicz, Maintainer
+ * Copyright (C) 1999-2000 CJ, cjtsai@ali.com.tw, Maintainer
+ *
+ * Copyright (C) 1998-2000 Andre Hedrick (andre@linux-ide.org)
+ * May be copied or modified under the terms of the GNU General Public License
+ * Copyright (C) 2002 Alan Cox
+ * ALi (now ULi M5228) support by Clear Zhang
+ *
+ * Documentation
+ * Chipset documentation available under NDA only
+ *
+ * TODO/CHECK
+ * Cannot have ATAPI on both master & slave for rev < c2 (???) but
+ * otherwise should do atapi DMA.
+ */
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#define DRV_NAME "pata_ali"
+#define DRV_VERSION "0.6.5"
+
+/*
+ * Cable special cases
+ */
+
+static struct dmi_system_id cable_dmi_table[] = {
+ {
+ .ident = "HP Pavilion N5430",
+ .matches = {
+ DMI_MATCH(DMI_BOARD_VENDOR, "Hewlett-Packard"),
+ DMI_MATCH(DMI_BOARD_NAME, "OmniBook N32N-736"),
+ },
+ },
+ { }
+};
+
+static int ali_cable_override(struct pci_dev *pdev)
+{
+ /* Fujitsu P2000 */
+ if (pdev->subsystem_vendor == 0x10CF && pdev->subsystem_device == 0x10AF)
+ return 1;
+ /* Systems by DMI */
+ if (dmi_check_system(cable_dmi_table))
+ return 1;
+ return 0;
+}
+
+/**
+ * ali_c2_cable_detect - cable detection
+ * @ap: ATA port
+ *
+ * Perform cable detection for C2 and later revisions
+ */
+
+static int ali_c2_cable_detect(struct ata_port *ap)
+{
+ struct pci_dev *pdev = to_pci_dev(ap->host->dev);
+ u8 ata66;
+
+ /* Certain laptops use short but suitable cables and don't
+ implement the detect logic */
+
+ if (ali_cable_override(pdev))
+ return ATA_CBL_PATA80;
+
+ /* Host view cable detect 0x4A bit 0 primary bit 1 secondary
+ Bit set for 40 pin */
+ pci_read_config_byte(pdev, 0x4A, &ata66);
+ if (ata66 & (1 << ap->port_no))
+ return ATA_CBL_PATA40;
+ else
+ return ATA_CBL_PATA80;
+}
+
+/**
+ * ali_early_error_handler - reset for eary chip
+ * @ap: ATA port
+ *
+ * Handle the reset callback for the later chips with cable detect
+ */
+
+static int ali_c2_pre_reset(struct ata_port *ap)
+{
+ ap->cbl = ali_c2_cable_detect(ap);
+ return ata_std_prereset(ap);
+}
+
+static void ali_c2_error_handler(struct ata_port *ap)
+{
+ ata_bmdma_drive_eh(ap, ali_c2_pre_reset,
+ ata_std_softreset, NULL,
+ ata_std_postreset);
+}
+
+/**
+ * ali_early_cable_detect - cable detection
+ * @ap: ATA port
+ *
+ * Perform cable detection for older chipsets. This turns out to be
+ * rather easy to implement
+ */
+
+static int ali_early_cable_detect(struct ata_port *ap)
+{
+ return ATA_CBL_PATA40;
+}
+
+/**
+ * ali_early_probe_init - reset for early chip
+ * @ap: ATA port
+ *
+ * Handle the reset callback for the early (pre cable detect) chips.
+ */
+
+static int ali_early_pre_reset(struct ata_port *ap)
+{
+ ap->cbl = ali_early_cable_detect(ap);
+ return ata_std_prereset(ap);
+}
+
+static void ali_early_error_handler(struct ata_port *ap)
+{
+ return ata_bmdma_drive_eh(ap, ali_early_pre_reset,
+ ata_std_softreset, NULL,
+ ata_std_postreset);
+}
+
+/**
+ * ali_20_filter - filter for earlier ALI DMA
+ * @ap: ALi ATA port
+ * @adev: attached device
+ *
+ * Ensure that we do not do DMA on CD devices. We may be able to
+ * fix that later on. Also ensure we do not do UDMA on WDC drives
+ */
+
+static unsigned long ali_20_filter(const struct ata_port *ap, struct ata_device *adev, unsigned long mask)
+{
+ char model_num[40];
+ /* No DMA on anything but a disk for now */
+ if (adev->class != ATA_DEV_ATA)
+ mask &= ~(ATA_MASK_MWDMA | ATA_MASK_UDMA);
+ ata_id_string(adev->id, model_num, ATA_ID_PROD_OFS, sizeof(model_num));
+ if (strstr(model_num, "WDC"))
+ return mask &= ~ATA_MASK_UDMA;
+ return ata_pci_default_filter(ap, adev, mask);
+}
+
+/**
+ * ali_fifo_control - FIFO manager
+ * @ap: ALi channel to control
+ * @adev: device for FIFO control
+ * @on: 0 for off 1 for on
+ *
+ * Enable or disable the FIFO on a given device. Because of the way the
+ * ALi FIFO works it provides a boost on ATA disk but can be confused by
+ * ATAPI and we must therefore manage it.
+ */
+
+static void ali_fifo_control(struct ata_port *ap, struct ata_device *adev, int on)
+{
+ struct pci_dev *pdev = to_pci_dev(ap->host->dev);
+ int pio_fifo = 0x54 + ap->port_no;
+ u8 fifo;
+ int shift = 4 * adev->devno;
+
+ /* ATA - FIFO on set nibble to 0x05, ATAPI - FIFO off, set nibble to
+ 0x00. Not all the docs agree but the behaviour we now use is the
+ one stated in the BIOS Programming Guide */
+
+ pci_read_config_byte(pdev, pio_fifo, &fifo);
+ fifo &= ~(0x0F << shift);
+ if (on)
+ fifo |= (on << shift);
+ pci_write_config_byte(pdev, pio_fifo, fifo);
+}
+
+/**
+ * ali_program_modes - load mode registers
+ * @ap: ALi channel to load
+ * @adev: Device the timing is for
+ * @cmd: Command timing
+ * @data: Data timing
+ * @ultra: UDMA timing or zero for off
+ *
+ * Loads the timing registers for cmd/data and disable UDMA if
+ * ultra is zero. If ultra is set then load and enable the UDMA
+ * timing but do not touch the command/data timing.
+ */
+
+static void ali_program_modes(struct ata_port *ap, struct ata_device *adev, struct ata_timing *t, u8 ultra)
+{
+ struct pci_dev *pdev = to_pci_dev(ap->host->dev);
+ int cas = 0x58 + 4 * ap->port_no; /* Command timing */
+ int cbt = 0x59 + 4 * ap->port_no; /* Command timing */
+ int drwt = 0x5A + 4 * ap->port_no + adev->devno; /* R/W timing */
+ int udmat = 0x56 + ap->port_no; /* UDMA timing */
+ int shift = 4 * adev->devno;
+ u8 udma;
+
+ if (t != NULL) {
+ t->setup = FIT(t->setup, 1, 8) & 7;
+ t->act8b = FIT(t->act8b, 1, 8) & 7;
+ t->rec8b = FIT(t->rec8b, 1, 16) & 15;
+ t->active = FIT(t->active, 1, 8) & 7;
+ t->recover = FIT(t->recover, 1, 16) & 15;
+
+ pci_write_config_byte(pdev, cas, t->setup);
+ pci_write_config_byte(pdev, cbt, (t->act8b << 4) | t->rec8b);
+ pci_write_config_byte(pdev, drwt, (t->active << 4) | t->recover);
+ }
+
+ /* Set up the UDMA enable */
+ pci_read_config_byte(pdev, udmat, &udma);
+ udma &= ~(0x0F << shift);
+ udma |= ultra << shift;
+ pci_write_config_byte(pdev, udmat, udma);
+}
+
+/**
+ * ali_set_piomode - set initial PIO mode data
+ * @ap: ATA interface
+ * @adev: ATA device
+ *
+ * Program the ALi registers for PIO mode. FIXME: add timings for
+ * PIO5.
+ */
+
+static void ali_set_piomode(struct ata_port *ap, struct ata_device *adev)
+{
+ struct ata_device *pair = ata_dev_pair(adev);
+ struct ata_timing t;
+ unsigned long T = 1000000000 / 33333; /* PCI clock based */
+
+ ata_timing_compute(adev, adev->pio_mode, &t, T, 1);
+ if (pair) {
+ struct ata_timing p;
+ ata_timing_compute(pair, pair->pio_mode, &p, T, 1);
+ ata_timing_merge(&p, &t, &t, ATA_TIMING_SETUP|ATA_TIMING_8BIT);
+ if (pair->dma_mode) {
+ ata_timing_compute(pair, pair->dma_mode, &p, T, 1);
+ ata_timing_merge(&p, &t, &t, ATA_TIMING_SETUP|ATA_TIMING_8BIT);
+ }
+ }
+
+ /* PIO FIFO is only permitted on ATA disk */
+ if (adev->class != ATA_DEV_ATA)
+ ali_fifo_control(ap, adev, 0x00);
+ ali_program_modes(ap, adev, &t, 0);
+ if (adev->class == ATA_DEV_ATA)
+ ali_fifo_control(ap, adev, 0x05);
+
+}
+
+/**
+ * ali_set_dmamode - set initial DMA mode data
+ * @ap: ATA interface
+ * @adev: ATA device
+ *
+ * FIXME: MWDMA timings
+ */
+
+static void ali_set_dmamode(struct ata_port *ap, struct ata_device *adev)
+{
+ static u8 udma_timing[7] = { 0xC, 0xB, 0xA, 0x9, 0x8, 0xF, 0xD };
+ struct ata_device *pair = ata_dev_pair(adev);
+ struct ata_timing t;
+ unsigned long T = 1000000000 / 33333; /* PCI clock based */
+ struct pci_dev *pdev = to_pci_dev(ap->host->dev);
+
+
+ if (adev->class == ATA_DEV_ATA)
+ ali_fifo_control(ap, adev, 0x08);
+
+ if (adev->dma_mode >= XFER_UDMA_0) {
+ ali_program_modes(ap, adev, NULL, udma_timing[adev->dma_mode - XFER_UDMA_0]);
+ if (adev->dma_mode >= XFER_UDMA_3) {
+ u8 reg4b;
+ pci_read_config_byte(pdev, 0x4B, ®4b);
+ reg4b |= 1;
+ pci_write_config_byte(pdev, 0x4B, reg4b);
+ }
+ } else {
+ ata_timing_compute(adev, adev->dma_mode, &t, T, 1);
+ if (pair) {
+ struct ata_timing p;
+ ata_timing_compute(pair, pair->pio_mode, &p, T, 1);
+ ata_timing_merge(&p, &t, &t, ATA_TIMING_SETUP|ATA_TIMING_8BIT);
+ if (pair->dma_mode) {
+ ata_timing_compute(pair, pair->dma_mode, &p, T, 1);
+ ata_timing_merge(&p, &t, &t, ATA_TIMING_SETUP|ATA_TIMING_8BIT);
+ }
+ }
+ ali_program_modes(ap, adev, &t, 0);
+ }
+}
+
+/**
+ * ali_lock_sectors - Keep older devices to 255 sector mode
+ * @ap: ATA port
+ * @adev: Device
+ *
+ * Called during the bus probe for each device that is found. We use
+ * this call to lock the sector count of the device to 255 or less on
+ * older ALi controllers. If we didn't do this then large I/O's would
+ * require LBA48 commands which the older ALi requires are issued by
+ * slower PIO methods
+ */
+
+static void ali_lock_sectors(struct ata_port *ap, struct ata_device *adev)
+{
+ adev->max_sectors = 255;
+}
+
+static struct scsi_host_template ali_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,
+ /* Keep LBA28 counts so large I/O's don't turn LBA48 and PIO
+ with older controllers. Not locked so will grow on C5 or later */
+ .max_sectors = 255,
+ .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,
+ .bios_param = ata_std_bios_param,
+};
+
+/*
+ * Port operations for PIO only ALi
+ */
+
+static struct ata_port_operations ali_early_port_ops = {
+ .port_disable = ata_port_disable,
+ .set_piomode = ali_set_piomode,
+ .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,
+
+ .freeze = ata_bmdma_freeze,
+ .thaw = ata_bmdma_thaw,
+ .error_handler = ali_early_error_handler,
+ .post_internal_cmd = ata_bmdma_post_internal_cmd,
+
+ .qc_prep = ata_qc_prep,
+ .qc_issue = ata_qc_issue_prot,
+ .eng_timeout = ata_eng_timeout,
+ .data_xfer = ata_pio_data_xfer,
+
+ .irq_handler = ata_interrupt,
+ .irq_clear = ata_bmdma_irq_clear,
+
+ .port_start = ata_port_start,
+ .port_stop = ata_port_stop,
+ .host_stop = ata_host_stop
+};
+
+/*
+ * Port operations for DMA capable ALi without cable
+ * detect
+ */
+static struct ata_port_operations ali_20_port_ops = {
+ .port_disable = ata_port_disable,
+
+ .set_piomode = ali_set_piomode,
+ .set_dmamode = ali_set_dmamode,
+ .mode_filter = ali_20_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,
+ .dev_config = ali_lock_sectors,
+
+ .freeze = ata_bmdma_freeze,
+ .thaw = ata_bmdma_thaw,
+ .error_handler = ali_early_error_handler,
+ .post_internal_cmd = ata_bmdma_post_internal_cmd,
+
+ .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,
+ .eng_timeout = ata_eng_timeout,
+ .data_xfer = ata_pio_data_xfer,
+
+ .irq_handler = ata_interrupt,
+ .irq_clear = ata_bmdma_irq_clear,
+
+ .port_start = ata_port_start,
+ .port_stop = ata_port_stop,
+ .host_stop = ata_host_stop
+};
+
+/*
+ * Port operations for DMA capable ALi with cable detect
+ */
+static struct ata_port_operations ali_c2_port_ops = {
+ .port_disable = ata_port_disable,
+ .set_piomode = ali_set_piomode,
+ .set_dmamode = ali_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,
+ .dev_config = ali_lock_sectors,
+
+ .freeze = ata_bmdma_freeze,
+ .thaw = ata_bmdma_thaw,
+ .error_handler = ali_c2_error_handler,
+ .post_internal_cmd = ata_bmdma_post_internal_cmd,
+
+ .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,
+ .eng_timeout = ata_eng_timeout,
+ .data_xfer = ata_pio_data_xfer,
+
+ .irq_handler = ata_interrupt,
+ .irq_clear = ata_bmdma_irq_clear,
+
+ .port_start = ata_port_start,
+ .port_stop = ata_port_stop,
+ .host_stop = ata_host_stop
+};
+
+/*
+ * Port operations for DMA capable ALi with cable detect and LBA48
+ */
+static struct ata_port_operations ali_c5_port_ops = {
+ .port_disable = ata_port_disable,
+ .set_piomode = ali_set_piomode,
+ .set_dmamode = ali_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,
+
+ .freeze = ata_bmdma_freeze,
+ .thaw = ata_bmdma_thaw,
+ .error_handler = ali_c2_error_handler,
+ .post_internal_cmd = ata_bmdma_post_internal_cmd,
+
+ .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,
+ .eng_timeout = ata_eng_timeout,
+ .data_xfer = ata_pio_data_xfer,
+
+ .irq_handler = ata_interrupt,
+ .irq_clear = ata_bmdma_irq_clear,
+
+ .port_start = ata_port_start,
+ .port_stop = ata_port_stop,
+ .host_stop = ata_host_stop
+};
+
+/**
+ * ali_init_one - discovery callback
+ * @pdev: PCI device ID
+ * @id: PCI table info
+ *
+ * An ALi IDE interface has been discovered. Figure out what revision
+ * and perform configuration work before handing it to the ATA layer
+ */
+
+static int ali_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
+{
+ static struct ata_port_info info_early = {
+ .sht = &ali_sht,
+ .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST,
+ .pio_mask = 0x1f,
+ .port_ops = &ali_early_port_ops
+ };
+ /* Revision 0x20 added DMA */
+ static struct ata_port_info info_20 = {
+ .sht = &ali_sht,
+ .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST | ATA_FLAG_PIO_LBA48,
+ .pio_mask = 0x1f,
+ .mwdma_mask = 0x07,
+ .port_ops = &ali_20_port_ops
+ };
+ /* Revision 0x20 with support logic added UDMA */
+ static struct ata_port_info info_20_udma = {
+ .sht = &ali_sht,
+ .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST | ATA_FLAG_PIO_LBA48,
+ .pio_mask = 0x1f,
+ .mwdma_mask = 0x07,
+ .udma_mask = 0x07, /* UDMA33 */
+ .port_ops = &ali_20_port_ops
+ };
+ /* Revision 0xC2 adds UDMA66 */
+ static struct ata_port_info info_c2 = {
+ .sht = &ali_sht,
+ .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST | ATA_FLAG_PIO_LBA48,
+ .pio_mask = 0x1f,
+ .mwdma_mask = 0x07,
+ .udma_mask = 0x1f,
+ .port_ops = &ali_c2_port_ops
+ };
+ /* Revision 0xC3 is UDMA100 */
+ static struct ata_port_info info_c3 = {
+ .sht = &ali_sht,
+ .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST | ATA_FLAG_PIO_LBA48,
+ .pio_mask = 0x1f,
+ .mwdma_mask = 0x07,
+ .udma_mask = 0x3f,
+ .port_ops = &ali_c2_port_ops
+ };
+ /* Revision 0xC4 is UDMA133 */
+ static struct ata_port_info info_c4 = {
+ .sht = &ali_sht,
+ .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST | ATA_FLAG_PIO_LBA48,
+ .pio_mask = 0x1f,
+ .mwdma_mask = 0x07,
+ .udma_mask = 0x7f,
+ .port_ops = &ali_c2_port_ops
+ };
+ /* Revision 0xC5 is UDMA133 with LBA48 DMA */
+ static struct ata_port_info info_c5 = {
+ .sht = &ali_sht,
+ .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST,
+ .pio_mask = 0x1f,
+ .mwdma_mask = 0x07,
+ .udma_mask = 0x7f,
+ .port_ops = &ali_c5_port_ops
+ };
+
+ static struct ata_port_info *port_info[2];
+ u8 rev, tmp;
+ struct pci_dev *north, *isa_bridge;
+
+ pci_read_config_byte(pdev, PCI_REVISION_ID, &rev);
+
+ /*
+ * The chipset revision selects the driver operations and
+ * mode data.
+ */
+
+ if (rev < 0x20) {
+ port_info[0] = port_info[1] = &info_early;
+ } else if (rev < 0xC2) {
+ /* 1543-E/F, 1543C-C, 1543C-D, 1543C-E */
+ pci_read_config_byte(pdev, 0x4B, &tmp);
+ /* Clear CD-ROM DMA write bit */
+ tmp &= 0x7F;
+ pci_write_config_byte(pdev, 0x4B, tmp);
+ port_info[0] = port_info[1] = &info_20;
+ } else if (rev == 0xC2) {
+ port_info[0] = port_info[1] = &info_c2;
+ } else if (rev == 0xC3) {
+ port_info[0] = port_info[1] = &info_c3;
+ } else if (rev == 0xC4) {
+ port_info[0] = port_info[1] = &info_c4;
+ } else
+ port_info[0] = port_info[1] = &info_c5;
+
+ if (rev >= 0xC2) {
+ /* Enable cable detection logic */
+ pci_read_config_byte(pdev, 0x4B, &tmp);
+ pci_write_config_byte(pdev, 0x4B, tmp | 0x08);
+ }
+
+ north = pci_get_slot(pdev->bus, PCI_DEVFN(0,0));
+ isa_bridge = pci_get_device(PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M1533, NULL);
+
+ if (north && north->vendor == PCI_VENDOR_ID_AL) {
+ /* Configure the ALi bridge logic. For non ALi rely on BIOS.
+ Set the south bridge enable bit */
+ pci_read_config_byte(isa_bridge, 0x79, &tmp);
+ if (rev == 0xC2)
+ pci_write_config_byte(isa_bridge, 0x79, tmp | 0x04);
+ else if (rev > 0xC2)
+ pci_write_config_byte(isa_bridge, 0x79, tmp | 0x02);
+ }
+
+ if (rev >= 0x20) {
+ if (rev < 0xC2) {
+ /* Are we paired with a UDMA capable chip */
+ pci_read_config_byte(isa_bridge, 0x5E, &tmp);
+ if ((tmp & 0x1E) == 0x12)
+ port_info[0] = port_info[1] = &info_20_udma;
+ }
+ /*
+ * CD_ROM DMA on (0x53 bit 0). Enable this even if we want
+ * to use PIO. 0x53 bit 1 (rev 20 only) - enable FIFO control
+ * via 0x54/55.
+ */
+ pci_read_config_byte(pdev, 0x53, &tmp);
+ if (rev <= 0x20)
+ tmp &= ~0x02;
+ if (rev == 0xc7)
+ tmp |= 0x03;
+ else
+ tmp |= 0x01; /* CD_ROM enable for DMA */
+ pci_write_config_byte(pdev, 0x53, tmp);
+ }
+
+ pci_dev_put(isa_bridge);
+ pci_dev_put(north);
+
+ ata_pci_clear_simplex(pdev);
+ return ata_pci_init_one(pdev, port_info, 2);
+}
+
+static struct pci_device_id ali[] = {
+ { PCI_DEVICE(PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M5228), },
+ { PCI_DEVICE(PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M5229), },
+ { 0, },
+};
+
+static struct pci_driver ali_pci_driver = {
+ .name = DRV_NAME,
+ .id_table = ali,
+ .probe = ali_init_one,
+ .remove = ata_pci_remove_one
+};
+
+static int __init ali_init(void)
+{
+ return pci_register_driver(&ali_pci_driver);
+}
+
+
+static void __exit ali_exit(void)
+{
+ pci_unregister_driver(&ali_pci_driver);
+}
+
+
+MODULE_AUTHOR("Alan Cox");
+MODULE_DESCRIPTION("low-level driver for ALi PATA");
+MODULE_LICENSE("GPL");
+MODULE_DEVICE_TABLE(pci, ali);
+MODULE_VERSION(DRV_VERSION);
+
+module_init(ali_init);
+module_exit(ali_exit);
diff --git a/drivers/ata/pata_amd.c b/drivers/ata/pata_amd.c
new file mode 100644
index 000000000000..3293cf9a7eb5
--- /dev/null
+++ b/drivers/ata/pata_amd.c
@@ -0,0 +1,718 @@
+/*
+ * pata_amd.c - AMD PATA for new ATA layer
+ * (C) 2005-2006 Red Hat Inc
+ * Alan Cox
+ *
+ * Based on pata-sil680. Errata information is taken from data sheets
+ * and the amd74xx.c driver by Vojtech Pavlik. Nvidia SATA devices are
+ * claimed by sata-nv.c.
+ *
+ * TODO:
+ * Variable system clock when/if it makes sense
+ * Power management on ports
+ *
+ *
+ * Documentation publically available.
+ */
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#define DRV_NAME "pata_amd"
+#define DRV_VERSION "0.2.3"
+
+/**
+ * timing_setup - shared timing computation and load
+ * @ap: ATA port being set up
+ * @adev: drive being configured
+ * @offset: port offset
+ * @speed: target speed
+ * @clock: clock multiplier (number of times 33MHz for this part)
+ *
+ * Perform the actual timing set up for Nvidia or AMD PATA devices.
+ * The actual devices vary so they all call into this helper function
+ * providing the clock multipler and offset (because AMD and Nvidia put
+ * the ports at different locations).
+ */
+
+static void timing_setup(struct ata_port *ap, struct ata_device *adev, int offset, int speed, int clock)
+{
+ static const unsigned char amd_cyc2udma[] = {
+ 6, 6, 5, 4, 0, 1, 1, 2, 2, 3, 3, 3, 3, 3, 3, 7
+ };
+
+ struct pci_dev *pdev = to_pci_dev(ap->host->dev);
+ struct ata_device *peer = ata_dev_pair(adev);
+ int dn = ap->port_no * 2 + adev->devno;
+ struct ata_timing at, apeer;
+ int T, UT;
+ const int amd_clock = 33333; /* KHz. */
+ u8 t;
+
+ T = 1000000000 / amd_clock;
+ UT = T / min_t(int, max_t(int, clock, 1), 2);
+
+ if (ata_timing_compute(adev, speed, &at, T, UT) < 0) {
+ dev_printk(KERN_ERR, &pdev->dev, "unknown mode %d.\n", speed);
+ return;
+ }
+
+ if (peer) {
+ /* This may be over conservative */
+ if (peer->dma_mode) {
+ ata_timing_compute(peer, peer->dma_mode, &apeer, T, UT);
+ ata_timing_merge(&apeer, &at, &at, ATA_TIMING_8BIT);
+ }
+ ata_timing_compute(peer, peer->pio_mode, &apeer, T, UT);
+ ata_timing_merge(&apeer, &at, &at, ATA_TIMING_8BIT);
+ }
+
+ if (speed == XFER_UDMA_5 && amd_clock <= 33333) at.udma = 1;
+ if (speed == XFER_UDMA_6 && amd_clock <= 33333) at.udma = 15;
+
+ /*
+ * Now do the setup work
+ */
+
+ /* Configure the address set up timing */
+ pci_read_config_byte(pdev, offset + 0x0C, &t);
+ t = (t & ~(3 << ((3 - dn) << 1))) | ((FIT(at.setup, 1, 4) - 1) << ((3 - dn) << 1));
+ pci_write_config_byte(pdev, offset + 0x0C , t);
+
+ /* Configure the 8bit I/O timing */
+ pci_write_config_byte(pdev, offset + 0x0E + (1 - (dn >> 1)),
+ ((FIT(at.act8b, 1, 16) - 1) << 4) | (FIT(at.rec8b, 1, 16) - 1));
+
+ /* Drive timing */
+ pci_write_config_byte(pdev, offset + 0x08 + (3 - dn),
+ ((FIT(at.active, 1, 16) - 1) << 4) | (FIT(at.recover, 1, 16) - 1));
+
+ switch (clock) {
+ case 1:
+ t = at.udma ? (0xc0 | (FIT(at.udma, 2, 5) - 2)) : 0x03;
+ break;
+
+ case 2:
+ t = at.udma ? (0xc0 | amd_cyc2udma[FIT(at.udma, 2, 10)]) : 0x03;
+ break;
+
+ case 3:
+ t = at.udma ? (0xc0 | amd_cyc2udma[FIT(at.udma, 1, 10)]) : 0x03;
+ break;
+
+ case 4:
+ t = at.udma ? (0xc0 | amd_cyc2udma[FIT(at.udma, 1, 15)]) : 0x03;
+ break;
+
+ default:
+ return;
+ }
+
+ /* UDMA timing */
+ pci_write_config_byte(pdev, offset + 0x10 + (3 - dn), t);
+}
+
+/**
+ * amd_probe_init - cable detection
+ * @ap: ATA port
+ *
+ * Perform cable detection. The BIOS stores this in PCI config
+ * space for us.
+ */
+
+static int amd_pre_reset(struct ata_port *ap)
+{
+ static const u32 bitmask[2] = {0x03, 0xC0};
+ static const struct pci_bits amd_enable_bits[] = {
+ { 0x40, 1, 0x02, 0x02 },
+ { 0x40, 1, 0x01, 0x01 }
+ };
+
+ struct pci_dev *pdev = to_pci_dev(ap->host->dev);
+ u8 ata66;
+
+ if (!pci_test_config_bits(pdev, &amd_enable_bits[ap->port_no])) {
+ ata_port_disable(ap);
+ printk(KERN_INFO "ata%u: port disabled. ignoring.\n", ap->id);
+ return 0;
+ }
+
+ pci_read_config_byte(pdev, 0x42, &ata66);
+ if (ata66 & bitmask[ap->port_no])
+ ap->cbl = ATA_CBL_PATA80;
+ else
+ ap->cbl = ATA_CBL_PATA40;
+ return ata_std_prereset(ap);
+
+}
+
+static void amd_error_handler(struct ata_port *ap)
+{
+ return ata_bmdma_drive_eh(ap, amd_pre_reset,
+ ata_std_softreset, NULL,
+ ata_std_postreset);
+}
+
+static int amd_early_pre_reset(struct ata_port *ap)
+{
+ struct pci_dev *pdev = to_pci_dev(ap->host->dev);
+ static struct pci_bits amd_enable_bits[] = {
+ { 0x40, 1, 0x02, 0x02 },
+ { 0x40, 1, 0x01, 0x01 }
+ };
+
+ if (!pci_test_config_bits(pdev, &amd_enable_bits[ap->port_no])) {
+ ata_port_disable(ap);
+ printk(KERN_INFO "ata%u: port disabled. ignoring.\n", ap->id);
+ return 0;
+ }
+ /* No host side cable detection */
+ ap->cbl = ATA_CBL_PATA80;
+ return ata_std_prereset(ap);
+
+}
+
+static void amd_early_error_handler(struct ata_port *ap)
+{
+ ata_bmdma_drive_eh(ap, amd_early_pre_reset,
+ ata_std_softreset, NULL,
+ ata_std_postreset);
+}
+
+/**
+ * amd33_set_piomode - set initial PIO mode data
+ * @ap: ATA interface
+ * @adev: ATA device
+ *
+ * Program the AMD registers for PIO mode.
+ */
+
+static void amd33_set_piomode(struct ata_port *ap, struct ata_device *adev)
+{
+ timing_setup(ap, adev, 0x40, adev->pio_mode, 1);
+}
+
+static void amd66_set_piomode(struct ata_port *ap, struct ata_device *adev)
+{
+ timing_setup(ap, adev, 0x40, adev->pio_mode, 2);
+}
+
+static void amd100_set_piomode(struct ata_port *ap, struct ata_device *adev)
+{
+ timing_setup(ap, adev, 0x40, adev->pio_mode, 3);
+}
+
+static void amd133_set_piomode(struct ata_port *ap, struct ata_device *adev)
+{
+ timing_setup(ap, adev, 0x40, adev->pio_mode, 4);
+}
+
+/**
+ * amd33_set_dmamode - set initial DMA mode data
+ * @ap: ATA interface
+ * @adev: ATA device
+ *
+ * Program the MWDMA/UDMA modes for the AMD and Nvidia
+ * chipset.
+ */
+
+static void amd33_set_dmamode(struct ata_port *ap, struct ata_device *adev)
+{
+ timing_setup(ap, adev, 0x40, adev->dma_mode, 1);
+}
+
+static void amd66_set_dmamode(struct ata_port *ap, struct ata_device *adev)
+{
+ timing_setup(ap, adev, 0x40, adev->dma_mode, 2);
+}
+
+static void amd100_set_dmamode(struct ata_port *ap, struct ata_device *adev)
+{
+ timing_setup(ap, adev, 0x40, adev->dma_mode, 3);
+}
+
+static void amd133_set_dmamode(struct ata_port *ap, struct ata_device *adev)
+{
+ timing_setup(ap, adev, 0x40, adev->dma_mode, 4);
+}
+
+
+/**
+ * nv_probe_init - cable detection
+ * @ap: ATA port
+ *
+ * Perform cable detection. The BIOS stores this in PCI config
+ * space for us.
+ */
+
+static int nv_pre_reset(struct ata_port *ap) {
+ static const u8 bitmask[2] = {0x03, 0xC0};
+ static const struct pci_bits nv_enable_bits[] = {
+ { 0x50, 1, 0x02, 0x02 },
+ { 0x50, 1, 0x01, 0x01 }
+ };
+
+ struct pci_dev *pdev = to_pci_dev(ap->host->dev);
+ u8 ata66;
+ u16 udma;
+
+ if (!pci_test_config_bits(pdev, &nv_enable_bits[ap->port_no])) {
+ ata_port_disable(ap);
+ printk(KERN_INFO "ata%u: port disabled. ignoring.\n", ap->id);
+ return 0;
+ }
+
+
+ pci_read_config_byte(pdev, 0x52, &ata66);
+ if (ata66 & bitmask[ap->port_no])
+ ap->cbl = ATA_CBL_PATA80;
+ else
+ ap->cbl = ATA_CBL_PATA40;
+
+ /* We now have to double check because the Nvidia boxes BIOS
+ doesn't always set the cable bits but does set mode bits */
+
+ pci_read_config_word(pdev, 0x62 - 2 * ap->port_no, &udma);
+ if ((udma & 0xC4) == 0xC4 || (udma & 0xC400) == 0xC400)
+ ap->cbl = ATA_CBL_PATA80;
+ return ata_std_prereset(ap);
+}
+
+static void nv_error_handler(struct ata_port *ap)
+{
+ ata_bmdma_drive_eh(ap, nv_pre_reset,
+ ata_std_softreset, NULL,
+ ata_std_postreset);
+}
+/**
+ * nv100_set_piomode - set initial PIO mode data
+ * @ap: ATA interface
+ * @adev: ATA device
+ *
+ * Program the AMD registers for PIO mode.
+ */
+
+static void nv100_set_piomode(struct ata_port *ap, struct ata_device *adev)
+{
+ timing_setup(ap, adev, 0x50, adev->pio_mode, 3);
+}
+
+static void nv133_set_piomode(struct ata_port *ap, struct ata_device *adev)
+{
+ timing_setup(ap, adev, 0x50, adev->pio_mode, 4);
+}
+
+/**
+ * nv100_set_dmamode - set initial DMA mode data
+ * @ap: ATA interface
+ * @adev: ATA device
+ *
+ * Program the MWDMA/UDMA modes for the AMD and Nvidia
+ * chipset.
+ */
+
+static void nv100_set_dmamode(struct ata_port *ap, struct ata_device *adev)
+{
+ timing_setup(ap, adev, 0x50, adev->dma_mode, 3);
+}
+
+static void nv133_set_dmamode(struct ata_port *ap, struct ata_device *adev)
+{
+ timing_setup(ap, adev, 0x50, adev->dma_mode, 4);
+}
+
+static struct scsi_host_template amd_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,
+ .max_sectors = ATA_MAX_SECTORS,
+ .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,
+ .bios_param = ata_std_bios_param,
+};
+
+static struct ata_port_operations amd33_port_ops = {
+ .port_disable = ata_port_disable,
+ .set_piomode = amd33_set_piomode,
+ .set_dmamode = amd33_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,
+
+ .freeze = ata_bmdma_freeze,
+ .thaw = ata_bmdma_thaw,
+ .error_handler = amd_early_error_handler,
+ .post_internal_cmd = ata_bmdma_post_internal_cmd,
+
+ .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,
+ .eng_timeout = ata_eng_timeout,
+ .data_xfer = ata_pio_data_xfer,
+
+ .irq_handler = ata_interrupt,
+ .irq_clear = ata_bmdma_irq_clear,
+
+ .port_start = ata_port_start,
+ .port_stop = ata_port_stop,
+ .host_stop = ata_host_stop
+};
+
+static struct ata_port_operations amd66_port_ops = {
+ .port_disable = ata_port_disable,
+ .set_piomode = amd66_set_piomode,
+ .set_dmamode = amd66_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,
+
+ .freeze = ata_bmdma_freeze,
+ .thaw = ata_bmdma_thaw,
+ .error_handler = amd_early_error_handler,
+ .post_internal_cmd = ata_bmdma_post_internal_cmd,
+
+ .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,
+ .eng_timeout = ata_eng_timeout,
+ .data_xfer = ata_pio_data_xfer,
+
+ .irq_handler = ata_interrupt,
+ .irq_clear = ata_bmdma_irq_clear,
+
+ .port_start = ata_port_start,
+ .port_stop = ata_port_stop,
+ .host_stop = ata_host_stop
+};
+
+static struct ata_port_operations amd100_port_ops = {
+ .port_disable = ata_port_disable,
+ .set_piomode = amd100_set_piomode,
+ .set_dmamode = amd100_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,
+
+ .freeze = ata_bmdma_freeze,
+ .thaw = ata_bmdma_thaw,
+ .error_handler = amd_error_handler,
+ .post_internal_cmd = ata_bmdma_post_internal_cmd,
+
+ .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,
+ .eng_timeout = ata_eng_timeout,
+ .data_xfer = ata_pio_data_xfer,
+
+ .irq_handler = ata_interrupt,
+ .irq_clear = ata_bmdma_irq_clear,
+
+ .port_start = ata_port_start,
+ .port_stop = ata_port_stop,
+ .host_stop = ata_host_stop
+};
+
+static struct ata_port_operations amd133_port_ops = {
+ .port_disable = ata_port_disable,
+ .set_piomode = amd133_set_piomode,
+ .set_dmamode = amd133_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,
+
+ .freeze = ata_bmdma_freeze,
+ .thaw = ata_bmdma_thaw,
+ .error_handler = amd_error_handler,
+ .post_internal_cmd = ata_bmdma_post_internal_cmd,
+
+ .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,
+ .eng_timeout = ata_eng_timeout,
+ .data_xfer = ata_pio_data_xfer,
+
+ .irq_handler = ata_interrupt,
+ .irq_clear = ata_bmdma_irq_clear,
+
+ .port_start = ata_port_start,
+ .port_stop = ata_port_stop,
+ .host_stop = ata_host_stop
+};
+
+static struct ata_port_operations nv100_port_ops = {
+ .port_disable = ata_port_disable,
+ .set_piomode = nv100_set_piomode,
+ .set_dmamode = nv100_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,
+
+ .freeze = ata_bmdma_freeze,
+ .thaw = ata_bmdma_thaw,
+ .error_handler = nv_error_handler,
+ .post_internal_cmd = ata_bmdma_post_internal_cmd,
+
+ .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,
+ .eng_timeout = ata_eng_timeout,
+ .data_xfer = ata_pio_data_xfer,
+
+ .irq_handler = ata_interrupt,
+ .irq_clear = ata_bmdma_irq_clear,
+
+ .port_start = ata_port_start,
+ .port_stop = ata_port_stop,
+ .host_stop = ata_host_stop
+};
+
+static struct ata_port_operations nv133_port_ops = {
+ .port_disable = ata_port_disable,
+ .set_piomode = nv133_set_piomode,
+ .set_dmamode = nv133_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,
+
+ .freeze = ata_bmdma_freeze,
+ .thaw = ata_bmdma_thaw,
+ .error_handler = nv_error_handler,
+ .post_internal_cmd = ata_bmdma_post_internal_cmd,
+
+ .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,
+ .eng_timeout = ata_eng_timeout,
+ .data_xfer = ata_pio_data_xfer,
+
+ .irq_handler = ata_interrupt,
+ .irq_clear = ata_bmdma_irq_clear,
+
+ .port_start = ata_port_start,
+ .port_stop = ata_port_stop,
+ .host_stop = ata_host_stop
+};
+
+static int amd_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
+{
+ static struct ata_port_info info[10] = {
+ { /* 0: AMD 7401 */
+ .sht = &amd_sht,
+ .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST,
+ .pio_mask = 0x1f,
+ .mwdma_mask = 0x07, /* No SWDMA */
+ .udma_mask = 0x07, /* UDMA 33 */
+ .port_ops = &amd33_port_ops
+ },
+ { /* 1: Early AMD7409 - no swdma */
+ .sht = &amd_sht,
+ .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST,
+ .pio_mask = 0x1f,
+ .mwdma_mask = 0x07,
+ .udma_mask = 0x1f, /* UDMA 66 */
+ .port_ops = &amd66_port_ops
+ },
+ { /* 2: AMD 7409, no swdma errata */
+ .sht = &amd_sht,
+ .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST,
+ .pio_mask = 0x1f,
+ .mwdma_mask = 0x07,
+ .udma_mask = 0x1f, /* UDMA 66 */
+ .port_ops = &amd66_port_ops
+ },
+ { /* 3: AMD 7411 */
+ .sht = &amd_sht,
+ .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST,
+ .pio_mask = 0x1f,
+ .mwdma_mask = 0x07,
+ .udma_mask = 0x3f, /* UDMA 100 */
+ .port_ops = &amd100_port_ops
+ },
+ { /* 4: AMD 7441 */
+ .sht = &amd_sht,
+ .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST,
+ .pio_mask = 0x1f,
+ .mwdma_mask = 0x07,
+ .udma_mask = 0x3f, /* UDMA 100 */
+ .port_ops = &amd100_port_ops
+ },
+ { /* 5: AMD 8111*/
+ .sht = &amd_sht,
+ .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST,
+ .pio_mask = 0x1f,
+ .mwdma_mask = 0x07,
+ .udma_mask = 0x7f, /* UDMA 133, no swdma */
+ .port_ops = &amd133_port_ops
+ },
+ { /* 6: AMD 8111 UDMA 100 (Serenade) */
+ .sht = &amd_sht,
+ .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST,
+ .pio_mask = 0x1f,
+ .mwdma_mask = 0x07,
+ .udma_mask = 0x3f, /* UDMA 100, no swdma */
+ .port_ops = &amd133_port_ops
+ },
+ { /* 7: Nvidia Nforce */
+ .sht = &amd_sht,
+ .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST,
+ .pio_mask = 0x1f,
+ .mwdma_mask = 0x07,
+ .udma_mask = 0x3f, /* UDMA 100 */
+ .port_ops = &nv100_port_ops
+ },
+ { /* 8: Nvidia Nforce2 and later */
+ .sht = &amd_sht,
+ .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST,
+ .pio_mask = 0x1f,
+ .mwdma_mask = 0x07,
+ .udma_mask = 0x7f, /* UDMA 133, no swdma */
+ .port_ops = &nv133_port_ops
+ },
+ { /* 9: AMD CS5536 (Geode companion) */
+ .sht = &amd_sht,
+ .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST,
+ .pio_mask = 0x1f,
+ .mwdma_mask = 0x07,
+ .udma_mask = 0x3f, /* UDMA 100 */
+ .port_ops = &amd100_port_ops
+ }
+ };
+ static struct ata_port_info *port_info[2];
+ static int printed_version;
+ int type = id->driver_data;
+ u8 rev;
+ u8 fifo;
+
+ if (!printed_version++)
+ dev_printk(KERN_DEBUG, &pdev->dev, "version " DRV_VERSION "\n");
+
+ pci_read_config_byte(pdev, PCI_REVISION_ID, &rev);
+ pci_read_config_byte(pdev, 0x41, &fifo);
+
+ /* Check for AMD7409 without swdma errata and if found adjust type */
+ if (type == 1 && rev > 0x7)
+ type = 2;
+
+ /* Check for AMD7411 */
+ if (type == 3)
+ /* FIFO is broken */
+ pci_write_config_byte(pdev, 0x41, fifo & 0x0F);
+ else
+ pci_write_config_byte(pdev, 0x41, fifo | 0xF0);
+
+ /* Serenade ? */
+ if (type == 5 && pdev->subsystem_vendor == PCI_VENDOR_ID_AMD &&
+ pdev->subsystem_device == PCI_DEVICE_ID_AMD_SERENADE)
+ type = 6; /* UDMA 100 only */
+
+ if (type < 3)
+ ata_pci_clear_simplex(pdev);
+
+ /* And fire it up */
+
+ port_info[0] = port_info[1] = &info[type];
+ return ata_pci_init_one(pdev, port_info, 2);
+}
+
+static const struct pci_device_id amd[] = {
+ { PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_COBRA_7401, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
+ { PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_VIPER_7409, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 1 },
+ { PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_VIPER_7411, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 3 },
+ { PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_OPUS_7441, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 4 },
+ { PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_8111_IDE, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 5 },
+ { PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_IDE, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 7 },
+ { PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE2_IDE, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 8 },
+ { PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE2S_IDE, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 8 },
+ { PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE3_IDE, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 8 },
+ { PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE3S_IDE, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 8 },
+ { PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_CK804_IDE, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 8 },
+ { PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP04_IDE, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 8 },
+ { PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP51_IDE, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 8 },
+ { PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP55_IDE, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 8 },
+ { PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP61_IDE, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 8 },
+ { PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_CS5536_IDE, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 9 },
+ { 0, },
+};
+
+static struct pci_driver amd_pci_driver = {
+ .name = DRV_NAME,
+ .id_table = amd,
+ .probe = amd_init_one,
+ .remove = ata_pci_remove_one
+};
+
+static int __init amd_init(void)
+{
+ return pci_register_driver(&amd_pci_driver);
+}
+
+static void __exit amd_exit(void)
+{
+ pci_unregister_driver(&amd_pci_driver);
+}
+
+
+MODULE_AUTHOR("Alan Cox");
+MODULE_DESCRIPTION("low-level driver for AMD PATA IDE");
+MODULE_LICENSE("GPL");
+MODULE_DEVICE_TABLE(pci, amd);
+MODULE_VERSION(DRV_VERSION);
+
+module_init(amd_init);
+module_exit(amd_exit);
diff --git a/drivers/ata/pata_artop.c b/drivers/ata/pata_artop.c
new file mode 100644
index 000000000000..d6ef3bf1bac7
--- /dev/null
+++ b/drivers/ata/pata_artop.c
@@ -0,0 +1,518 @@
+/*
+ * pata_artop.c - ARTOP ATA controller driver
+ *
+ * (C) 2006 Red Hat
+ *
+ * Based in part on drivers/ide/pci/aec62xx.c
+ * Copyright (C) 1999-2002 Andre Hedrick
+ * 865/865R fixes for Macintosh card version from a patch to the old
+ * driver by Thibaut VARENE
+ * When setting the PCI latency we must set 0x80 or higher for burst
+ * performance Alessandro Zummo
+ *
+ * TODO
+ * 850 serialization once the core supports it
+ * Investigate no_dsc on 850R
+ * Clock detect
+ */
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#define DRV_NAME "pata_artop"
+#define DRV_VERSION "0.4.1"
+
+/*
+ * The ARTOP has 33 Mhz and "over clocked" timing tables. Until we
+ * get PCI bus speed functionality we leave this as 0. Its a variable
+ * for when we get the functionality and also for folks wanting to
+ * test stuff.
+ */
+
+static int clock = 0;
+
+static int artop6210_pre_reset(struct ata_port *ap)
+{
+ struct pci_dev *pdev = to_pci_dev(ap->host->dev);
+ const struct pci_bits artop_enable_bits[] = {
+ { 0x4AU, 1U, 0x02UL, 0x02UL }, /* port 0 */
+ { 0x4AU, 1U, 0x04UL, 0x04UL }, /* port 1 */
+ };
+
+ if (!pci_test_config_bits(pdev, &artop_enable_bits[ap->port_no])) {
+ ata_port_disable(ap);
+ printk(KERN_INFO "ata%u: port disabled. ignoring.\n", ap->id);
+ return 0;
+ }
+ ap->cbl = ATA_CBL_PATA40;
+ return ata_std_prereset(ap);
+}
+
+/**
+ * artop6210_error_handler - Probe specified port on PATA host controller
+ * @ap: Port to probe
+ *
+ * LOCKING:
+ * None (inherited from caller).
+ */
+
+static void artop6210_error_handler(struct ata_port *ap)
+{
+ ata_bmdma_drive_eh(ap, artop6210_pre_reset,
+ ata_std_softreset, NULL,
+ ata_std_postreset);
+}
+
+/**
+ * artop6260_pre_reset - check for 40/80 pin
+ * @ap: Port
+ *
+ * The ARTOP hardware reports the cable detect bits in register 0x49.
+ * Nothing complicated needed here.
+ */
+
+static int artop6260_pre_reset(struct ata_port *ap)
+{
+ static const struct pci_bits artop_enable_bits[] = {
+ { 0x4AU, 1U, 0x02UL, 0x02UL }, /* port 0 */
+ { 0x4AU, 1U, 0x04UL, 0x04UL }, /* port 1 */
+ };
+
+ struct pci_dev *pdev = to_pci_dev(ap->host->dev);
+ u8 tmp;
+
+ /* Odd numbered device ids are the units with enable bits (the -R cards) */
+ if (pdev->device % 1 && !pci_test_config_bits(pdev, &artop_enable_bits[ap->port_no])) {
+ ata_port_disable(ap);
+ printk(KERN_INFO "ata%u: port disabled. ignoring.\n", ap->id);
+ return 0;
+ }
+ pci_read_config_byte(pdev, 0x49, &tmp);
+ if (tmp & (1 >> ap->port_no))
+ ap->cbl = ATA_CBL_PATA40;
+ else
+ ap->cbl = ATA_CBL_PATA80;
+ return ata_std_prereset(ap);
+}
+
+/**
+ * artop6260_error_handler - Probe specified port on PATA host controller
+ * @ap: Port to probe
+ *
+ * LOCKING:
+ * None (inherited from caller).
+ */
+
+static void artop6260_error_handler(struct ata_port *ap)
+{
+ ata_bmdma_drive_eh(ap, artop6260_pre_reset,
+ ata_std_softreset, NULL,
+ ata_std_postreset);
+}
+
+/**
+ * artop6210_load_piomode - Load a set of PATA PIO timings
+ * @ap: Port whose timings we are configuring
+ * @adev: Device
+ * @pio: PIO mode
+ *
+ * Set PIO mode for device, in host controller PCI config space. This
+ * is used both to set PIO timings in PIO mode and also to set the
+ * matching PIO clocking for UDMA, as well as the MWDMA timings.
+ *
+ * LOCKING:
+ * None (inherited from caller).
+ */
+
+static void artop6210_load_piomode(struct ata_port *ap, struct ata_device *adev, unsigned int pio)
+{
+ struct pci_dev *pdev = to_pci_dev(ap->host->dev);
+ int dn = adev->devno + 2 * ap->port_no;
+ const u16 timing[2][5] = {
+ { 0x0000, 0x000A, 0x0008, 0x0303, 0x0301 },
+ { 0x0700, 0x070A, 0x0708, 0x0403, 0x0401 }
+
+ };
+ /* Load the PIO timing active/recovery bits */
+ pci_write_config_word(pdev, 0x40 + 2 * dn, timing[clock][pio]);
+}
+
+/**
+ * artop6210_set_piomode - Initialize host controller PATA PIO timings
+ * @ap: Port whose timings we are configuring
+ * @adev: Device we are configuring
+ *
+ * Set PIO mode for device, in host controller PCI config space. For
+ * ARTOP we must also clear the UDMA bits if we are not doing UDMA. In
+ * the event UDMA is used the later call to set_dmamode will set the
+ * bits as required.
+ *
+ * LOCKING:
+ * None (inherited from caller).
+ */
+
+static void artop6210_set_piomode(struct ata_port *ap, struct ata_device *adev)
+{
+ struct pci_dev *pdev = to_pci_dev(ap->host->dev);
+ int dn = adev->devno + 2 * ap->port_no;
+ u8 ultra;
+
+ artop6210_load_piomode(ap, adev, adev->pio_mode - XFER_PIO_0);
+
+ /* Clear the UDMA mode bits (set_dmamode will redo this if needed) */
+ pci_read_config_byte(pdev, 0x54, &ultra);
+ ultra &= ~(3 << (2 * dn));
+ pci_write_config_byte(pdev, 0x54, ultra);
+}
+
+/**
+ * artop6260_load_piomode - Initialize host controller PATA PIO timings
+ * @ap: Port whose timings we are configuring
+ * @adev: Device we are configuring
+ * @pio: PIO mode
+ *
+ * Set PIO mode for device, in host controller PCI config space. The
+ * ARTOP6260 and relatives store the timing data differently.
+ *
+ * LOCKING:
+ * None (inherited from caller).
+ */
+
+static void artop6260_load_piomode (struct ata_port *ap, struct ata_device *adev, unsigned int pio)
+{
+ struct pci_dev *pdev = to_pci_dev(ap->host->dev);
+ int dn = adev->devno + 2 * ap->port_no;
+ const u8 timing[2][5] = {
+ { 0x00, 0x0A, 0x08, 0x33, 0x31 },
+ { 0x70, 0x7A, 0x78, 0x43, 0x41 }
+
+ };
+ /* Load the PIO timing active/recovery bits */
+ pci_write_config_byte(pdev, 0x40 + dn, timing[clock][pio]);
+}
+
+/**
+ * artop6260_set_piomode - Initialize host controller PATA PIO timings
+ * @ap: Port whose timings we are configuring
+ * @adev: Device we are configuring
+ *
+ * Set PIO mode for device, in host controller PCI config space. For
+ * ARTOP we must also clear the UDMA bits if we are not doing UDMA. In
+ * the event UDMA is used the later call to set_dmamode will set the
+ * bits as required.
+ *
+ * LOCKING:
+ * None (inherited from caller).
+ */
+
+static void artop6260_set_piomode(struct ata_port *ap, struct ata_device *adev)
+{
+ struct pci_dev *pdev = to_pci_dev(ap->host->dev);
+ u8 ultra;
+
+ artop6260_load_piomode(ap, adev, adev->pio_mode - XFER_PIO_0);
+
+ /* Clear the UDMA mode bits (set_dmamode will redo this if needed) */
+ pci_read_config_byte(pdev, 0x44 + ap->port_no, &ultra);
+ ultra &= ~(7 << (4 * adev->devno)); /* One nibble per drive */
+ pci_write_config_byte(pdev, 0x44 + ap->port_no, ultra);
+}
+
+/**
+ * artop6210_set_dmamode - Initialize host controller PATA PIO timings
+ * @ap: Port whose timings we are configuring
+ * @adev: um
+ *
+ * Set DMA mode for device, in host controller PCI config space.
+ *
+ * LOCKING:
+ * None (inherited from caller).
+ */
+
+static void artop6210_set_dmamode (struct ata_port *ap, struct ata_device *adev)
+{
+ unsigned int pio;
+ struct pci_dev *pdev = to_pci_dev(ap->host->dev);
+ int dn = adev->devno + 2 * ap->port_no;
+ u8 ultra;
+
+ if (adev->dma_mode == XFER_MW_DMA_0)
+ pio = 1;
+ else
+ pio = 4;
+
+ /* Load the PIO timing active/recovery bits */
+ artop6210_load_piomode(ap, adev, pio);
+
+ pci_read_config_byte(pdev, 0x54, &ultra);
+ ultra &= ~(3 << (2 * dn));
+
+ /* Add ultra DMA bits if in UDMA mode */
+ if (adev->dma_mode >= XFER_UDMA_0) {
+ u8 mode = (adev->dma_mode - XFER_UDMA_0) + 1 - clock;
+ if (mode == 0)
+ mode = 1;
+ ultra |= (mode << (2 * dn));
+ }
+ pci_write_config_byte(pdev, 0x54, ultra);
+}
+
+/**
+ * artop6260_set_dmamode - Initialize host controller PATA PIO timings
+ * @ap: Port whose timings we are configuring
+ * @adev: Device we are configuring
+ *
+ * Set DMA mode for device, in host controller PCI config space. The
+ * ARTOP6260 and relatives store the timing data differently.
+ *
+ * LOCKING:
+ * None (inherited from caller).
+ */
+
+static void artop6260_set_dmamode (struct ata_port *ap, struct ata_device *adev)
+{
+ unsigned int pio = adev->pio_mode - XFER_PIO_0;
+ struct pci_dev *pdev = to_pci_dev(ap->host->dev);
+ u8 ultra;
+
+ if (adev->dma_mode == XFER_MW_DMA_0)
+ pio = 1;
+ else
+ pio = 4;
+
+ /* Load the PIO timing active/recovery bits */
+ artop6260_load_piomode(ap, adev, pio);
+
+ /* Add ultra DMA bits if in UDMA mode */
+ pci_read_config_byte(pdev, 0x44 + ap->port_no, &ultra);
+ ultra &= ~(7 << (4 * adev->devno)); /* One nibble per drive */
+ if (adev->dma_mode >= XFER_UDMA_0) {
+ u8 mode = adev->dma_mode - XFER_UDMA_0 + 1 - clock;
+ if (mode == 0)
+ mode = 1;
+ ultra |= (mode << (4 * adev->devno));
+ }
+ pci_write_config_byte(pdev, 0x44 + ap->port_no, ultra);
+}
+
+static struct scsi_host_template artop_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,
+ .max_sectors = ATA_MAX_SECTORS,
+ .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,
+ .bios_param = ata_std_bios_param,
+};
+
+static const struct ata_port_operations artop6210_ops = {
+ .port_disable = ata_port_disable,
+ .set_piomode = artop6210_set_piomode,
+ .set_dmamode = artop6210_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,
+
+ .freeze = ata_bmdma_freeze,
+ .thaw = ata_bmdma_thaw,
+ .error_handler = artop6210_error_handler,
+ .post_internal_cmd = ata_bmdma_post_internal_cmd,
+
+ .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,
+ .eng_timeout = ata_eng_timeout,
+ .data_xfer = ata_pio_data_xfer,
+
+ .irq_handler = ata_interrupt,
+ .irq_clear = ata_bmdma_irq_clear,
+
+ .port_start = ata_port_start,
+ .port_stop = ata_port_stop,
+ .host_stop = ata_host_stop,
+};
+
+static const struct ata_port_operations artop6260_ops = {
+ .port_disable = ata_port_disable,
+ .set_piomode = artop6260_set_piomode,
+ .set_dmamode = artop6260_set_dmamode,
+
+ .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,
+
+ .freeze = ata_bmdma_freeze,
+ .thaw = ata_bmdma_thaw,
+ .error_handler = artop6260_error_handler,
+ .post_internal_cmd = ata_bmdma_post_internal_cmd,
+
+ .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,
+
+ .eng_timeout = ata_eng_timeout,
+
+ .irq_handler = ata_interrupt,
+ .irq_clear = ata_bmdma_irq_clear,
+
+ .port_start = ata_port_start,
+ .port_stop = ata_port_stop,
+ .host_stop = ata_host_stop,
+};
+
+
+/**
+ * artop_init_one - Register ARTOP ATA PCI device with kernel services
+ * @pdev: PCI device to register
+ * @ent: Entry in artop_pci_tbl matching with @pdev
+ *
+ * Called from kernel PCI layer.
+ *
+ * LOCKING:
+ * Inherited from PCI layer (may sleep).
+ *
+ * RETURNS:
+ * Zero on success, or -ERRNO value.
+ */
+
+static int artop_init_one (struct pci_dev *pdev, const struct pci_device_id *id)
+{
+ static int printed_version;
+ static struct ata_port_info info_6210 = {
+ .sht = &artop_sht,
+ .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST,
+ .pio_mask = 0x1f, /* pio0-4 */
+ .mwdma_mask = 0x07, /* mwdma0-2 */
+ .udma_mask = ATA_UDMA2,
+ .port_ops = &artop6210_ops,
+ };
+ static struct ata_port_info info_626x = {
+ .sht = &artop_sht,
+ .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST,
+ .pio_mask = 0x1f, /* pio0-4 */
+ .mwdma_mask = 0x07, /* mwdma0-2 */
+ .udma_mask = ATA_UDMA4,
+ .port_ops = &artop6260_ops,
+ };
+ static struct ata_port_info info_626x_fast = {
+ .sht = &artop_sht,
+ .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST,
+ .pio_mask = 0x1f, /* pio0-4 */
+ .mwdma_mask = 0x07, /* mwdma0-2 */
+ .udma_mask = ATA_UDMA5,
+ .port_ops = &artop6260_ops,
+ };
+ struct ata_port_info *port_info[2];
+ struct ata_port_info *info;
+ int ports = 2;
+
+ if (!printed_version++)
+ dev_printk(KERN_DEBUG, &pdev->dev,
+ "version " DRV_VERSION "\n");
+
+ if (id->driver_data == 0) { /* 6210 variant */
+ info = &info_6210;
+ /* BIOS may have left us in UDMA, clear it before libata probe */
+ pci_write_config_byte(pdev, 0x54, 0);
+ /* For the moment (also lacks dsc) */
+ printk(KERN_WARNING "ARTOP 6210 requires serialize functionality not yet supported by libata.\n");
+ printk(KERN_WARNING "Secondary ATA ports will not be activated.\n");
+ ports = 1;
+ }
+ else if (id->driver_data == 1) /* 6260 */
+ info = &info_626x;
+ else if (id->driver_data == 2) { /* 6260 or 6260 + fast */
+ unsigned long io = pci_resource_start(pdev, 4);
+ u8 reg;
+
+ info = &info_626x;
+ if (inb(io) & 0x10)
+ info = &info_626x_fast;
+ /* Mac systems come up with some registers not set as we
+ will need them */
+
+ /* Clear reset & test bits */
+ pci_read_config_byte(pdev, 0x49, ®);
+ pci_write_config_byte(pdev, 0x49, reg & ~ 0x30);
+
+ /* PCI latency must be > 0x80 for burst mode, tweak it
+ * if required.
+ */
+ pci_read_config_byte(pdev, PCI_LATENCY_TIMER, ®);
+ if (reg <= 0x80)
+ pci_write_config_byte(pdev, PCI_LATENCY_TIMER, 0x90);
+
+ /* Enable IRQ output and burst mode */
+ pci_read_config_byte(pdev, 0x4a, ®);
+ pci_write_config_byte(pdev, 0x4a, (reg & ~0x01) | 0x80);
+
+ }
+ port_info[0] = port_info[1] = info;
+ return ata_pci_init_one(pdev, port_info, ports);
+}
+
+static const struct pci_device_id artop_pci_tbl[] = {
+ { 0x1191, 0x0005, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+ { 0x1191, 0x0006, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 1},
+ { 0x1191, 0x0007, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 1},
+ { 0x1191, 0x0008, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 2},
+ { 0x1191, 0x0009, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 2},
+ { } /* terminate list */
+};
+
+static struct pci_driver artop_pci_driver = {
+ .name = DRV_NAME,
+ .id_table = artop_pci_tbl,
+ .probe = artop_init_one,
+ .remove = ata_pci_remove_one,
+};
+
+static int __init artop_init(void)
+{
+ return pci_register_driver(&artop_pci_driver);
+}
+
+static void __exit artop_exit(void)
+{
+ pci_unregister_driver(&artop_pci_driver);
+}
+
+
+module_init(artop_init);
+module_exit(artop_exit);
+
+MODULE_AUTHOR("Alan Cox");
+MODULE_DESCRIPTION("SCSI low-level driver for ARTOP PATA");
+MODULE_LICENSE("GPL");
+MODULE_DEVICE_TABLE(pci, artop_pci_tbl);
+MODULE_VERSION(DRV_VERSION);
+
diff --git a/drivers/ata/pata_atiixp.c b/drivers/ata/pata_atiixp.c
new file mode 100644
index 000000000000..3f78a1e54a75
--- /dev/null
+++ b/drivers/ata/pata_atiixp.c
@@ -0,0 +1,306 @@
+/*
+ * pata_atiixp.c - ATI PATA for new ATA layer
+ * (C) 2005 Red Hat Inc
+ * Alan Cox
+ *
+ * Based on
+ *
+ * linux/drivers/ide/pci/atiixp.c Version 0.01-bart2 Feb. 26, 2004
+ *
+ * Copyright (C) 2003 ATI Inc.
+ * Copyright (C) 2004 Bartlomiej Zolnierkiewicz
+ *
+ */
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#define DRV_NAME "pata_atiixp"
+#define DRV_VERSION "0.4.2"
+
+enum {
+ ATIIXP_IDE_PIO_TIMING = 0x40,
+ ATIIXP_IDE_MWDMA_TIMING = 0x44,
+ ATIIXP_IDE_PIO_CONTROL = 0x48,
+ ATIIXP_IDE_PIO_MODE = 0x4a,
+ ATIIXP_IDE_UDMA_CONTROL = 0x54,
+ ATIIXP_IDE_UDMA_MODE = 0x56
+};
+
+static int atiixp_pre_reset(struct ata_port *ap)
+{
+ struct pci_dev *pdev = to_pci_dev(ap->host->dev);
+ static struct pci_bits atiixp_enable_bits[] = {
+ { 0x48, 1, 0x01, 0x00 },
+ { 0x48, 1, 0x08, 0x00 }
+ };
+
+ if (!pci_test_config_bits(pdev, &atiixp_enable_bits[ap->port_no])) {
+ ata_port_disable(ap);
+ printk(KERN_INFO "ata%u: port disabled. ignoring.\n", ap->id);
+ return 0;
+ }
+ ap->cbl = ATA_CBL_PATA80;
+ return ata_std_prereset(ap);
+}
+
+static void atiixp_error_handler(struct ata_port *ap)
+{
+ ata_bmdma_drive_eh(ap, atiixp_pre_reset, ata_std_softreset, NULL, ata_std_postreset);
+}
+
+/**
+ * atiixp_set_pio_timing - set initial PIO mode data
+ * @ap: ATA interface
+ * @adev: ATA device
+ *
+ * Called by both the pio and dma setup functions to set the controller
+ * timings for PIO transfers. We must load both the mode number and
+ * timing values into the controller.
+ */
+
+static void atiixp_set_pio_timing(struct ata_port *ap, struct ata_device *adev, int pio)
+{
+ static u8 pio_timings[5] = { 0x5D, 0x47, 0x34, 0x22, 0x20 };
+
+ struct pci_dev *pdev = to_pci_dev(ap->host->dev);
+ int dn = 2 * ap->port_no + adev->devno;
+
+ /* Check this is correct - the order is odd in both drivers */
+ int timing_shift = (16 * ap->port_no) + 8 * (adev->devno ^ 1);
+ u16 pio_mode_data, pio_timing_data;
+
+ pci_read_config_word(pdev, ATIIXP_IDE_PIO_MODE, &pio_mode_data);
+ pio_mode_data &= ~(0x7 << (4 * dn));
+ pio_mode_data |= pio << (4 * dn);
+ pci_write_config_word(pdev, ATIIXP_IDE_PIO_MODE, pio_mode_data);
+
+ pci_read_config_word(pdev, ATIIXP_IDE_PIO_TIMING, &pio_timing_data);
+ pio_mode_data &= ~(0xFF << timing_shift);
+ pio_mode_data |= (pio_timings[pio] << timing_shift);
+ pci_write_config_word(pdev, ATIIXP_IDE_PIO_TIMING, pio_timing_data);
+}
+
+/**
+ * atiixp_set_piomode - set initial PIO mode data
+ * @ap: ATA interface
+ * @adev: ATA device
+ *
+ * Called to do the PIO mode setup. We use a shared helper for this
+ * as the DMA setup must also adjust the PIO timing information.
+ */
+
+static void atiixp_set_piomode(struct ata_port *ap, struct ata_device *adev)
+{
+ atiixp_set_pio_timing(ap, adev, adev->pio_mode - XFER_PIO_0);
+}
+
+/**
+ * atiixp_set_dmamode - set initial DMA mode data
+ * @ap: ATA interface
+ * @adev: ATA device
+ *
+ * Called to do the DMA mode setup. We use timing tables for most
+ * modes but must tune an appropriate PIO mode to match.
+ */
+
+static void atiixp_set_dmamode(struct ata_port *ap, struct ata_device *adev)
+{
+ static u8 mwdma_timings[5] = { 0x77, 0x21, 0x20 };
+
+ struct pci_dev *pdev = to_pci_dev(ap->host->dev);
+ int dma = adev->dma_mode;
+ int dn = 2 * ap->port_no + adev->devno;
+ int wanted_pio;
+
+ if (adev->dma_mode >= XFER_UDMA_0) {
+ u16 udma_mode_data;
+
+ dma -= XFER_UDMA_0;
+
+ pci_read_config_word(pdev, ATIIXP_IDE_UDMA_MODE, &udma_mode_data);
+ udma_mode_data &= ~(0x7 << (4 * dn));
+ udma_mode_data |= dma << (4 * dn);
+ pci_write_config_word(pdev, ATIIXP_IDE_UDMA_MODE, udma_mode_data);
+ } else {
+ u16 mwdma_timing_data;
+ /* Check this is correct - the order is odd in both drivers */
+ int timing_shift = (16 * ap->port_no) + 8 * (adev->devno ^ 1);
+
+ dma -= XFER_MW_DMA_0;
+
+ pci_read_config_word(pdev, ATIIXP_IDE_MWDMA_TIMING, &mwdma_timing_data);
+ mwdma_timing_data &= ~(0xFF << timing_shift);
+ mwdma_timing_data |= (mwdma_timings[dma] << timing_shift);
+ pci_write_config_word(pdev, ATIIXP_IDE_MWDMA_TIMING, mwdma_timing_data);
+ }
+ /*
+ * We must now look at the PIO mode situation. We may need to
+ * adjust the PIO mode to keep the timings acceptable
+ */
+ if (adev->dma_mode >= XFER_MW_DMA_2)
+ wanted_pio = 4;
+ else if (adev->dma_mode == XFER_MW_DMA_1)
+ wanted_pio = 3;
+ else if (adev->dma_mode == XFER_MW_DMA_0)
+ wanted_pio = 0;
+ else BUG();
+
+ if (adev->pio_mode != wanted_pio)
+ atiixp_set_pio_timing(ap, adev, wanted_pio);
+}
+
+/**
+ * atiixp_bmdma_start - DMA start callback
+ * @qc: Command in progress
+ *
+ * When DMA begins we need to ensure that the UDMA control
+ * register for the channel is correctly set.
+ */
+
+static void atiixp_bmdma_start(struct ata_queued_cmd *qc)
+{
+ struct ata_port *ap = qc->ap;
+ struct ata_device *adev = qc->dev;
+
+ struct pci_dev *pdev = to_pci_dev(ap->host->dev);
+ int dn = (2 * ap->port_no) + adev->devno;
+ u16 tmp16;
+
+ pci_read_config_word(pdev, ATIIXP_IDE_UDMA_CONTROL, &tmp16);
+ if (adev->dma_mode >= XFER_UDMA_0)
+ tmp16 |= (1 << dn);
+ else
+ tmp16 &= ~(1 << dn);
+ pci_write_config_word(pdev, ATIIXP_IDE_UDMA_CONTROL, tmp16);
+ ata_bmdma_start(qc);
+}
+
+/**
+ * atiixp_dma_stop - DMA stop callback
+ * @qc: Command in progress
+ *
+ * DMA has completed. Clear the UDMA flag as the next operations will
+ * be PIO ones not UDMA data transfer.
+ */
+
+static void atiixp_bmdma_stop(struct ata_queued_cmd *qc)
+{
+ struct ata_port *ap = qc->ap;
+ struct pci_dev *pdev = to_pci_dev(ap->host->dev);
+ int dn = (2 * ap->port_no) + qc->dev->devno;
+ u16 tmp16;
+
+ pci_read_config_word(pdev, ATIIXP_IDE_UDMA_CONTROL, &tmp16);
+ tmp16 &= ~(1 << dn);
+ pci_write_config_word(pdev, ATIIXP_IDE_UDMA_CONTROL, tmp16);
+ ata_bmdma_stop(qc);
+}
+
+static struct scsi_host_template atiixp_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,
+ .max_sectors = ATA_MAX_SECTORS,
+ .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,
+ .bios_param = ata_std_bios_param,
+};
+
+static struct ata_port_operations atiixp_port_ops = {
+ .port_disable = ata_port_disable,
+ .set_piomode = atiixp_set_piomode,
+ .set_dmamode = atiixp_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,
+
+ .freeze = ata_bmdma_freeze,
+ .thaw = ata_bmdma_thaw,
+ .error_handler = atiixp_error_handler,
+ .post_internal_cmd = ata_bmdma_post_internal_cmd,
+
+ .bmdma_setup = ata_bmdma_setup,
+ .bmdma_start = atiixp_bmdma_start,
+ .bmdma_stop = atiixp_bmdma_stop,
+ .bmdma_status = ata_bmdma_status,
+
+ .qc_prep = ata_qc_prep,
+ .qc_issue = ata_qc_issue_prot,
+ .eng_timeout = ata_eng_timeout,
+ .data_xfer = ata_pio_data_xfer,
+
+ .irq_handler = ata_interrupt,
+ .irq_clear = ata_bmdma_irq_clear,
+
+ .port_start = ata_port_start,
+ .port_stop = ata_port_stop,
+ .host_stop = ata_host_stop
+};
+
+static int atiixp_init_one(struct pci_dev *dev, const struct pci_device_id *id)
+{
+ static struct ata_port_info info = {
+ .sht = &atiixp_sht,
+ .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST,
+ .pio_mask = 0x1f,
+ .mwdma_mask = 0x06, /* No MWDMA0 support */
+ .udma_mask = 0x3F,
+ .port_ops = &atiixp_port_ops
+ };
+ static struct ata_port_info *port_info[2] = { &info, &info };
+ return ata_pci_init_one(dev, port_info, 2);
+}
+
+static struct pci_device_id atiixp[] = {
+ { PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_IXP200_IDE), },
+ { PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_IXP300_IDE), },
+ { PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_IXP400_IDE), },
+ { PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_IXP600_IDE), },
+ { 0, },
+};
+
+static struct pci_driver atiixp_pci_driver = {
+ .name = DRV_NAME,
+ .id_table = atiixp,
+ .probe = atiixp_init_one,
+ .remove = ata_pci_remove_one
+};
+
+static int __init atiixp_init(void)
+{
+ return pci_register_driver(&atiixp_pci_driver);
+}
+
+
+static void __exit atiixp_exit(void)
+{
+ pci_unregister_driver(&atiixp_pci_driver);
+}
+
+
+MODULE_AUTHOR("Alan Cox");
+MODULE_DESCRIPTION("low-level driver for ATI IXP200/300/400");
+MODULE_LICENSE("GPL");
+MODULE_DEVICE_TABLE(pci, atiixp);
+MODULE_VERSION(DRV_VERSION);
+
+module_init(atiixp_init);
+module_exit(atiixp_exit);
diff --git a/drivers/ata/pata_cmd64x.c b/drivers/ata/pata_cmd64x.c
new file mode 100644
index 000000000000..abf1bb7bd322
--- /dev/null
+++ b/drivers/ata/pata_cmd64x.c
@@ -0,0 +1,505 @@
+/*
+ * pata_cmd64x.c - ATI PATA for new ATA layer
+ * (C) 2005 Red Hat Inc
+ * Alan Cox
+ *
+ * Based upon
+ * linux/drivers/ide/pci/cmd64x.c Version 1.30 Sept 10, 2002
+ *
+ * cmd64x.c: Enable interrupts at initialization time on Ultra/PCI machines.
+ * Note, this driver is not used at all on other systems because
+ * there the "BIOS" has done all of the following already.
+ * Due to massive hardware bugs, UltraDMA is only supported
+ * on the 646U2 and not on the 646U.
+ *
+ * Copyright (C) 1998 Eddie C. Dost (ecd@skynet.be)
+ * Copyright (C) 1998 David S. Miller (davem@redhat.com)
+ *
+ * Copyright (C) 1999-2002 Andre Hedrick
+ *
+ * TODO
+ * Testing work
+ */
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#define DRV_NAME "pata_cmd64x"
+#define DRV_VERSION "0.2.1"
+
+/*
+ * CMD64x specific registers definition.
+ */
+
+enum {
+ CFR = 0x50,
+ CFR_INTR_CH0 = 0x02,
+ CNTRL = 0x51,
+ CNTRL_DIS_RA0 = 0x40,
+ CNTRL_DIS_RA1 = 0x80,
+ CNTRL_ENA_2ND = 0x08,
+ CMDTIM = 0x52,
+ ARTTIM0 = 0x53,
+ DRWTIM0 = 0x54,
+ ARTTIM1 = 0x55,
+ DRWTIM1 = 0x56,
+ ARTTIM23 = 0x57,
+ ARTTIM23_DIS_RA2 = 0x04,
+ ARTTIM23_DIS_RA3 = 0x08,
+ ARTTIM23_INTR_CH1 = 0x10,
+ ARTTIM2 = 0x57,
+ ARTTIM3 = 0x57,
+ DRWTIM23 = 0x58,
+ DRWTIM2 = 0x58,
+ BRST = 0x59,
+ DRWTIM3 = 0x5b,
+ BMIDECR0 = 0x70,
+ MRDMODE = 0x71,
+ MRDMODE_INTR_CH0 = 0x04,
+ MRDMODE_INTR_CH1 = 0x08,
+ MRDMODE_BLK_CH0 = 0x10,
+ MRDMODE_BLK_CH1 = 0x20,
+ BMIDESR0 = 0x72,
+ UDIDETCR0 = 0x73,
+ DTPR0 = 0x74,
+ BMIDECR1 = 0x78,
+ BMIDECSR = 0x79,
+ BMIDESR1 = 0x7A,
+ UDIDETCR1 = 0x7B,
+ DTPR1 = 0x7C
+};
+
+static int cmd64x_pre_reset(struct ata_port *ap)
+{
+ ap->cbl = ATA_CBL_PATA40;
+ return ata_std_prereset(ap);
+}
+
+static int cmd648_pre_reset(struct ata_port *ap)
+{
+ struct pci_dev *pdev = to_pci_dev(ap->host->dev);
+ u8 r;
+
+ /* Check cable detect bits */
+ pci_read_config_byte(pdev, BMIDECSR, &r);
+ if (r & (1 << ap->port_no))
+ ap->cbl = ATA_CBL_PATA80;
+ else
+ ap->cbl = ATA_CBL_PATA40;
+
+ return ata_std_prereset(ap);
+}
+
+static void cmd64x_error_handler(struct ata_port *ap)
+{
+ return ata_bmdma_drive_eh(ap, cmd64x_pre_reset, ata_std_softreset, NULL, ata_std_postreset);
+}
+
+static void cmd648_error_handler(struct ata_port *ap)
+{
+ ata_bmdma_drive_eh(ap, cmd648_pre_reset, ata_std_softreset, NULL, ata_std_postreset);
+}
+
+/**
+ * cmd64x_set_piomode - set initial PIO mode data
+ * @ap: ATA interface
+ * @adev: ATA device
+ *
+ * Called to do the PIO mode setup.
+ */
+
+static void cmd64x_set_piomode(struct ata_port *ap, struct ata_device *adev)
+{
+ struct pci_dev *pdev = to_pci_dev(ap->host->dev);
+ struct ata_timing t;
+ const unsigned long T = 1000000 / 33;
+ const u8 setup_data[] = { 0x40, 0x40, 0x40, 0x80, 0x00 };
+
+ u8 reg;
+
+ /* Port layout is not logical so use a table */
+ const u8 arttim_port[2][2] = {
+ { ARTTIM0, ARTTIM1 },
+ { ARTTIM23, ARTTIM23 }
+ };
+ const u8 drwtim_port[2][2] = {
+ { DRWTIM0, DRWTIM1 },
+ { DRWTIM2, DRWTIM3 }
+ };
+
+ int arttim = arttim_port[ap->port_no][adev->devno];
+ int drwtim = drwtim_port[ap->port_no][adev->devno];
+
+
+ if (ata_timing_compute(adev, adev->pio_mode, &t, T, 0) < 0) {
+ printk(KERN_ERR DRV_NAME ": mode computation failed.\n");
+ return;
+ }
+ if (ap->port_no) {
+ /* Slave has shared address setup */
+ struct ata_device *pair = ata_dev_pair(adev);
+
+ if (pair) {
+ struct ata_timing tp;
+ ata_timing_compute(pair, pair->pio_mode, &tp, T, 0);
+ ata_timing_merge(&t, &tp, &t, ATA_TIMING_SETUP);
+ }
+ }
+
+ printk(KERN_DEBUG DRV_NAME ": active %d recovery %d setup %d.\n",
+ t.active, t.recover, t.setup);
+ if (t.recover > 16) {
+ t.active += t.recover - 16;
+ t.recover = 16;
+ }
+ if (t.active > 16)
+ t.active = 16;
+
+ /* Now convert the clocks into values we can actually stuff into
+ the chip */
+
+ if (t.recover > 1)
+ t.recover--;
+ else
+ t.recover = 15;
+
+ if (t.setup > 4)
+ t.setup = 0xC0;
+ else
+ t.setup = setup_data[t.setup];
+
+ t.active &= 0x0F; /* 0 = 16 */
+
+ /* Load setup timing */
+ pci_read_config_byte(pdev, arttim, ®);
+ reg &= 0x3F;
+ reg |= t.setup;
+ pci_write_config_byte(pdev, arttim, reg);
+
+ /* Load active/recovery */
+ pci_write_config_byte(pdev, drwtim, (t.active << 4) | t.recover);
+}
+
+/**
+ * cmd64x_set_dmamode - set initial DMA mode data
+ * @ap: ATA interface
+ * @adev: ATA device
+ *
+ * Called to do the DMA mode setup.
+ */
+
+static void cmd64x_set_dmamode(struct ata_port *ap, struct ata_device *adev)
+{
+ static const u8 udma_data[] = {
+ 0x31, 0x21, 0x11, 0x25, 0x15, 0x05
+ };
+ static const u8 mwdma_data[] = {
+ 0x30, 0x20, 0x10
+ };
+
+ struct pci_dev *pdev = to_pci_dev(ap->host->dev);
+ u8 regU, regD;
+
+ int pciU = UDIDETCR0 + 8 * ap->port_no;
+ int pciD = BMIDESR0 + 8 * ap->port_no;
+ int shift = 2 * adev->devno;
+
+ pci_read_config_byte(pdev, pciD, ®D);
+ pci_read_config_byte(pdev, pciU, ®U);
+
+ regD &= ~(0x20 << shift);
+ regU &= ~(0x35 << shift);
+
+ if (adev->dma_mode >= XFER_UDMA_0)
+ regU |= udma_data[adev->dma_mode - XFER_UDMA_0] << shift;
+ else
+ regD |= mwdma_data[adev->dma_mode - XFER_MW_DMA_0] << shift;
+
+ regD |= 0x20 << adev->devno;
+
+ pci_write_config_byte(pdev, pciU, regU);
+ pci_write_config_byte(pdev, pciD, regD);
+}
+
+/**
+ * cmd648_dma_stop - DMA stop callback
+ * @qc: Command in progress
+ *
+ * DMA has completed.
+ */
+
+static void cmd648_bmdma_stop(struct ata_queued_cmd *qc)
+{
+ struct ata_port *ap = qc->ap;
+ struct pci_dev *pdev = to_pci_dev(ap->host->dev);
+ u8 dma_intr;
+ int dma_reg = ap->port_no ? ARTTIM23_INTR_CH1 : CFR_INTR_CH0;
+ int dma_mask = ap->port_no ? ARTTIM2 : CFR;
+
+ ata_bmdma_stop(qc);
+
+ pci_read_config_byte(pdev, dma_reg, &dma_intr);
+ pci_write_config_byte(pdev, dma_reg, dma_intr | dma_mask);
+}
+
+/**
+ * cmd646r1_dma_stop - DMA stop callback
+ * @qc: Command in progress
+ *
+ * Stub for now while investigating the r1 quirk in the old driver.
+ */
+
+static void cmd646r1_bmdma_stop(struct ata_queued_cmd *qc)
+{
+ ata_bmdma_stop(qc);
+}
+
+static struct scsi_host_template cmd64x_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,
+ .max_sectors = ATA_MAX_SECTORS,
+ .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,
+ .bios_param = ata_std_bios_param,
+};
+
+static struct ata_port_operations cmd64x_port_ops = {
+ .port_disable = ata_port_disable,
+ .set_piomode = cmd64x_set_piomode,
+ .set_dmamode = cmd64x_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,
+
+ .freeze = ata_bmdma_freeze,
+ .thaw = ata_bmdma_thaw,
+ .error_handler = cmd64x_error_handler,
+ .post_internal_cmd = ata_bmdma_post_internal_cmd,
+
+ .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,
+ .eng_timeout = ata_eng_timeout,
+ .data_xfer = ata_pio_data_xfer,
+
+ .irq_handler = ata_interrupt,
+ .irq_clear = ata_bmdma_irq_clear,
+
+ .port_start = ata_port_start,
+ .port_stop = ata_port_stop,
+ .host_stop = ata_host_stop
+};
+
+static struct ata_port_operations cmd646r1_port_ops = {
+ .port_disable = ata_port_disable,
+ .set_piomode = cmd64x_set_piomode,
+ .set_dmamode = cmd64x_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,
+
+ .freeze = ata_bmdma_freeze,
+ .thaw = ata_bmdma_thaw,
+ .error_handler = cmd64x_error_handler,
+ .post_internal_cmd = ata_bmdma_post_internal_cmd,
+
+ .bmdma_setup = ata_bmdma_setup,
+ .bmdma_start = ata_bmdma_start,
+ .bmdma_stop = cmd646r1_bmdma_stop,
+ .bmdma_status = ata_bmdma_status,
+
+ .qc_prep = ata_qc_prep,
+ .qc_issue = ata_qc_issue_prot,
+ .eng_timeout = ata_eng_timeout,
+ .data_xfer = ata_pio_data_xfer,
+
+ .irq_handler = ata_interrupt,
+ .irq_clear = ata_bmdma_irq_clear,
+
+ .port_start = ata_port_start,
+ .port_stop = ata_port_stop,
+ .host_stop = ata_host_stop
+};
+
+static struct ata_port_operations cmd648_port_ops = {
+ .port_disable = ata_port_disable,
+ .set_piomode = cmd64x_set_piomode,
+ .set_dmamode = cmd64x_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,
+
+ .freeze = ata_bmdma_freeze,
+ .thaw = ata_bmdma_thaw,
+ .error_handler = cmd648_error_handler,
+ .post_internal_cmd = ata_bmdma_post_internal_cmd,
+
+ .bmdma_setup = ata_bmdma_setup,
+ .bmdma_start = ata_bmdma_start,
+ .bmdma_stop = cmd648_bmdma_stop,
+ .bmdma_status = ata_bmdma_status,
+
+ .qc_prep = ata_qc_prep,
+ .qc_issue = ata_qc_issue_prot,
+ .eng_timeout = ata_eng_timeout,
+ .data_xfer = ata_pio_data_xfer,
+
+ .irq_handler = ata_interrupt,
+ .irq_clear = ata_bmdma_irq_clear,
+
+ .port_start = ata_port_start,
+ .port_stop = ata_port_stop,
+ .host_stop = ata_host_stop
+};
+
+static int cmd64x_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
+{
+ u32 class_rev;
+
+ static struct ata_port_info cmd_info[6] = {
+ { /* CMD 643 - no UDMA */
+ .sht = &cmd64x_sht,
+ .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST,
+ .pio_mask = 0x1f,
+ .mwdma_mask = 0x07,
+ .port_ops = &cmd64x_port_ops
+ },
+ { /* CMD 646 with broken UDMA */
+ .sht = &cmd64x_sht,
+ .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST,
+ .pio_mask = 0x1f,
+ .mwdma_mask = 0x07,
+ .port_ops = &cmd64x_port_ops
+ },
+ { /* CMD 646 with working UDMA */
+ .sht = &cmd64x_sht,
+ .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST,
+ .pio_mask = 0x1f,
+ .mwdma_mask = 0x07,
+ .udma_mask = ATA_UDMA1,
+ .port_ops = &cmd64x_port_ops
+ },
+ { /* CMD 646 rev 1 */
+ .sht = &cmd64x_sht,
+ .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST,
+ .pio_mask = 0x1f,
+ .mwdma_mask = 0x07,
+ .port_ops = &cmd646r1_port_ops
+ },
+ { /* CMD 648 */
+ .sht = &cmd64x_sht,
+ .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST,
+ .pio_mask = 0x1f,
+ .mwdma_mask = 0x07,
+ .udma_mask = ATA_UDMA2,
+ .port_ops = &cmd648_port_ops
+ },
+ { /* CMD 649 */
+ .sht = &cmd64x_sht,
+ .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST,
+ .pio_mask = 0x1f,
+ .mwdma_mask = 0x07,
+ .udma_mask = ATA_UDMA3,
+ .port_ops = &cmd648_port_ops
+ }
+ };
+ static struct ata_port_info *port_info[2], *info;
+ u8 mrdmode;
+
+ info = &cmd_info[id->driver_data];
+
+ pci_read_config_dword(pdev, PCI_CLASS_REVISION, &class_rev);
+ class_rev &= 0xFF;
+
+ if (id->driver_data == 0) /* 643 */
+ ata_pci_clear_simplex(pdev);
+
+ if (pdev->device == PCI_DEVICE_ID_CMD_646) {
+ /* Does UDMA work ? */
+ if (class_rev > 4)
+ info = &cmd_info[2];
+ /* Early rev with other problems ? */
+ else if (class_rev == 1)
+ info = &cmd_info[3];
+ }
+
+ pci_write_config_byte(pdev, PCI_LATENCY_TIMER, 64);
+ pci_read_config_byte(pdev, MRDMODE, &mrdmode);
+ mrdmode &= ~ 0x30; /* IRQ set up */
+ mrdmode |= 0x02; /* Memory read line enable */
+ pci_write_config_byte(pdev, MRDMODE, mrdmode);
+
+ /* Force PIO 0 here.. */
+
+ /* PPC specific fixup copied from old driver */
+#ifdef CONFIG_PPC
+ pci_write_config_byte(pdev, UDIDETCR0, 0xF0);
+#endif
+
+ port_info[0] = port_info[1] = info;
+ return ata_pci_init_one(pdev, port_info, 2);
+}
+
+static struct pci_device_id cmd64x[] = {
+ { PCI_VENDOR_ID_CMD, PCI_DEVICE_ID_CMD_643, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+ { PCI_VENDOR_ID_CMD, PCI_DEVICE_ID_CMD_646, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 1},
+ { PCI_VENDOR_ID_CMD, PCI_DEVICE_ID_CMD_648, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 4},
+ { PCI_VENDOR_ID_CMD, PCI_DEVICE_ID_CMD_649, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 5},
+ { 0, },
+};
+
+static struct pci_driver cmd64x_pci_driver = {
+ .name = DRV_NAME,
+ .id_table = cmd64x,
+ .probe = cmd64x_init_one,
+ .remove = ata_pci_remove_one
+};
+
+static int __init cmd64x_init(void)
+{
+ return pci_register_driver(&cmd64x_pci_driver);
+}
+
+
+static void __exit cmd64x_exit(void)
+{
+ pci_unregister_driver(&cmd64x_pci_driver);
+}
+
+
+MODULE_AUTHOR("Alan Cox");
+MODULE_DESCRIPTION("low-level driver for CMD64x series PATA controllers");
+MODULE_LICENSE("GPL");
+MODULE_DEVICE_TABLE(pci, cmd64x);
+MODULE_VERSION(DRV_VERSION);
+
+module_init(cmd64x_init);
+module_exit(cmd64x_exit);
diff --git a/drivers/ata/pata_cs5520.c b/drivers/ata/pata_cs5520.c
new file mode 100644
index 000000000000..792ce4828510
--- /dev/null
+++ b/drivers/ata/pata_cs5520.c
@@ -0,0 +1,336 @@
+/*
+ * IDE tuning and bus mastering support for the CS5510/CS5520
+ * chipsets
+ *
+ * The CS5510/CS5520 are slightly unusual devices. Unlike the
+ * typical IDE controllers they do bus mastering with the drive in
+ * PIO mode and smarter silicon.
+ *
+ * The practical upshot of this is that we must always tune the
+ * drive for the right PIO mode. We must also ignore all the blacklists
+ * and the drive bus mastering DMA information. Also to confuse matters
+ * further we can do DMA on PIO only drives.
+ *
+ * DMA on the 5510 also requires we disable_hlt() during DMA on early
+ * revisions.
+ *
+ * *** This driver is strictly experimental ***
+ *
+ * (c) Copyright Red Hat Inc 2002
+ *
+ * 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.
+ *
+ * Documentation:
+ * Not publically available.
+ */
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#define DRV_NAME "pata_cs5520"
+#define DRV_VERSION "0.6.2"
+
+struct pio_clocks
+{
+ int address;
+ int assert;
+ int recovery;
+};
+
+static const struct pio_clocks cs5520_pio_clocks[]={
+ {3, 6, 11},
+ {2, 5, 6},
+ {1, 4, 3},
+ {1, 3, 2},
+ {1, 2, 1}
+};
+
+/**
+ * cs5520_set_timings - program PIO timings
+ * @ap: ATA port
+ * @adev: ATA device
+ *
+ * Program the PIO mode timings for the controller according to the pio
+ * clocking table.
+ */
+
+static void cs5520_set_timings(struct ata_port *ap, struct ata_device *adev, int pio)
+{
+ struct pci_dev *pdev = to_pci_dev(ap->host->dev);
+ int slave = adev->devno;
+
+ pio -= XFER_PIO_0;
+
+ /* Channel command timing */
+ pci_write_config_byte(pdev, 0x62 + ap->port_no,
+ (cs5520_pio_clocks[pio].recovery << 4) |
+ (cs5520_pio_clocks[pio].assert));
+ /* FIXME: should these use address ? */
+ /* Read command timing */
+ pci_write_config_byte(pdev, 0x64 + 4*ap->port_no + slave,
+ (cs5520_pio_clocks[pio].recovery << 4) |
+ (cs5520_pio_clocks[pio].assert));
+ /* Write command timing */
+ pci_write_config_byte(pdev, 0x66 + 4*ap->port_no + slave,
+ (cs5520_pio_clocks[pio].recovery << 4) |
+ (cs5520_pio_clocks[pio].assert));
+}
+
+/**
+ * cs5520_enable_dma - turn on DMA bits
+ *
+ * Turn on the DMA bits for this disk. Needed because the BIOS probably
+ * has not done the work for us. Belongs in the core SATA code.
+ */
+
+static void cs5520_enable_dma(struct ata_port *ap, struct ata_device *adev)
+{
+ /* Set the DMA enable/disable flag */
+ u8 reg = inb(ap->ioaddr.bmdma_addr + 0x02);
+ reg |= 1<<(adev->devno + 5);
+ outb(reg, ap->ioaddr.bmdma_addr + 0x02);
+}
+
+/**
+ * cs5520_set_dmamode - program DMA timings
+ * @ap: ATA port
+ * @adev: ATA device
+ *
+ * Program the DMA mode timings for the controller according to the pio
+ * clocking table. Note that this device sets the DMA timings to PIO
+ * mode values. This may seem bizarre but the 5520 architecture talks
+ * PIO mode to the disk and DMA mode to the controller so the underlying
+ * transfers are PIO timed.
+ */
+
+static void cs5520_set_dmamode(struct ata_port *ap, struct ata_device *adev)
+{
+ static const int dma_xlate[3] = { XFER_PIO_0, XFER_PIO_3, XFER_PIO_4 };
+ cs5520_set_timings(ap, adev, dma_xlate[adev->dma_mode]);
+ cs5520_enable_dma(ap, adev);
+}
+
+/**
+ * cs5520_set_piomode - program PIO timings
+ * @ap: ATA port
+ * @adev: ATA device
+ *
+ * Program the PIO mode timings for the controller according to the pio
+ * clocking table. We know pio_mode will equal dma_mode because of the
+ * CS5520 architecture. At least once we turned DMA on and wrote a
+ * mode setter.
+ */
+
+static void cs5520_set_piomode(struct ata_port *ap, struct ata_device *adev)
+{
+ cs5520_set_timings(ap, adev, adev->pio_mode);
+}
+
+
+static int cs5520_pre_reset(struct ata_port *ap)
+{
+ ap->cbl = ATA_CBL_PATA40;
+ return ata_std_prereset(ap);
+}
+
+static void cs5520_error_handler(struct ata_port *ap)
+{
+ return ata_bmdma_drive_eh(ap, cs5520_pre_reset, ata_std_softreset, NULL, ata_std_postreset);
+}
+
+static struct scsi_host_template cs5520_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,
+ .max_sectors = ATA_MAX_SECTORS,
+ .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,
+ .bios_param = ata_std_bios_param,
+};
+
+static struct ata_port_operations cs5520_port_ops = {
+ .port_disable = ata_port_disable,
+ .set_piomode = cs5520_set_piomode,
+ .set_dmamode = cs5520_set_dmamode,
+
+ .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,
+
+ .freeze = ata_bmdma_freeze,
+ .thaw = ata_bmdma_thaw,
+ .error_handler = cs5520_error_handler,
+ .post_internal_cmd = ata_bmdma_post_internal_cmd,
+
+ .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,
+
+ .eng_timeout = ata_eng_timeout,
+
+ .irq_handler = ata_interrupt,
+ .irq_clear = ata_bmdma_irq_clear,
+
+ .port_start = ata_port_start,
+ .port_stop = ata_port_stop,
+ .host_stop = ata_host_stop,
+};
+
+static int __devinit cs5520_init_one(struct pci_dev *dev, const struct pci_device_id *id)
+{
+ u8 pcicfg;
+ static struct ata_probe_ent probe[2];
+ int ports = 0;
+
+ /* IDE port enable bits */
+ pci_read_config_byte(dev, 0x60, &pcicfg);
+
+ /* Check if the ATA ports are enabled */
+ if ((pcicfg & 3) == 0)
+ return -ENODEV;
+
+ if ((pcicfg & 0x40) == 0) {
+ printk(KERN_WARNING DRV_NAME ": DMA mode disabled. Enabling.\n");
+ pci_write_config_byte(dev, 0x60, pcicfg | 0x40);
+ }
+
+ /* Perform set up for DMA */
+ if (pci_enable_device_bars(dev, 1<<2)) {
+ printk(KERN_ERR DRV_NAME ": unable to configure BAR2.\n");
+ return -ENODEV;
+ }
+ pci_set_master(dev);
+ if (pci_set_dma_mask(dev, DMA_32BIT_MASK)) {
+ printk(KERN_ERR DRV_NAME ": unable to configure DMA mask.\n");
+ return -ENODEV;
+ }
+ if (pci_set_consistent_dma_mask(dev, DMA_32BIT_MASK)) {
+ printk(KERN_ERR DRV_NAME ": unable to configure consistent DMA mask.\n");
+ return -ENODEV;
+ }
+
+ /* We have to do our own plumbing as the PCI setup for this
+ chipset is non-standard so we can't punt to the libata code */
+
+ INIT_LIST_HEAD(&probe[0].node);
+ probe[0].dev = pci_dev_to_dev(dev);
+ probe[0].port_ops = &cs5520_port_ops;
+ probe[0].sht = &cs5520_sht;
+ probe[0].pio_mask = 0x1F;
+ probe[0].mwdma_mask = id->driver_data;
+ probe[0].irq = 14;
+ probe[0].irq_flags = 0;
+ probe[0].port_flags = ATA_FLAG_SLAVE_POSS|ATA_FLAG_SRST;
+ probe[0].n_ports = 1;
+ probe[0].port[0].cmd_addr = 0x1F0;
+ probe[0].port[0].ctl_addr = 0x3F6;
+ probe[0].port[0].altstatus_addr = 0x3F6;
+ probe[0].port[0].bmdma_addr = pci_resource_start(dev, 2);
+
+ /* The secondary lurks at different addresses but is otherwise
+ the same beastie */
+
+ probe[1] = probe[0];
+ INIT_LIST_HEAD(&probe[1].node);
+ probe[1].irq = 15;
+ probe[1].port[0].cmd_addr = 0x170;
+ probe[1].port[0].ctl_addr = 0x376;
+ probe[1].port[0].altstatus_addr = 0x376;
+ probe[1].port[0].bmdma_addr = pci_resource_start(dev, 2) + 8;
+
+ /* Let libata fill in the port details */
+ ata_std_ports(&probe[0].port[0]);
+ ata_std_ports(&probe[1].port[0]);
+
+ /* Now add the ports that are active */
+ if (pcicfg & 1)
+ ports += ata_device_add(&probe[0]);
+ if (pcicfg & 2)
+ ports += ata_device_add(&probe[1]);
+ if (ports)
+ return 0;
+ return -ENODEV;
+}
+
+/**
+ * cs5520_remove_one - device unload
+ * @pdev: PCI device being removed
+ *
+ * Handle an unplug/unload event for a PCI device. Unload the
+ * PCI driver but do not use the default handler as we manage
+ * resources ourself and *MUST NOT* disable the device as it has
+ * other functions.
+ */
+
+static void __devexit cs5520_remove_one(struct pci_dev *pdev)
+{
+ struct device *dev = pci_dev_to_dev(pdev);
+ struct ata_host *host = dev_get_drvdata(dev);
+
+ ata_host_remove(host);
+ dev_set_drvdata(dev, NULL);
+}
+
+/* For now keep DMA off. We can set it for all but A rev CS5510 once the
+ core ATA code can handle it */
+
+static struct pci_device_id pata_cs5520[] = {
+ { PCI_DEVICE(PCI_VENDOR_ID_CYRIX, PCI_DEVICE_ID_CYRIX_5510), },
+ { PCI_DEVICE(PCI_VENDOR_ID_CYRIX, PCI_DEVICE_ID_CYRIX_5520), },
+ { 0, },
+};
+
+static struct pci_driver cs5520_pci_driver = {
+ .name = DRV_NAME,
+ .id_table = pata_cs5520,
+ .probe = cs5520_init_one,
+ .remove = cs5520_remove_one
+};
+
+
+static int __init cs5520_init(void)
+{
+ return pci_register_driver(&cs5520_pci_driver);
+}
+
+static void __exit cs5520_exit(void)
+{
+ pci_unregister_driver(&cs5520_pci_driver);
+}
+
+MODULE_AUTHOR("Alan Cox");
+MODULE_DESCRIPTION("low-level driver for Cyrix CS5510/5520");
+MODULE_LICENSE("GPL");
+MODULE_DEVICE_TABLE(pci, pata_cs5520);
+MODULE_VERSION(DRV_VERSION);
+
+module_init(cs5520_init);
+module_exit(cs5520_exit);
+
diff --git a/drivers/ata/pata_cs5530.c b/drivers/ata/pata_cs5530.c
new file mode 100644
index 000000000000..f3d8a3bc1e78
--- /dev/null
+++ b/drivers/ata/pata_cs5530.c
@@ -0,0 +1,387 @@
+/*
+ * pata-cs5530.c - CS5530 PATA for new ATA layer
+ * (C) 2005 Red Hat Inc
+ * Alan Cox
+ *
+ * based upon cs5530.c by Mark Lord.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * 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
+ *
+ * Loosely based on the piix & svwks drivers.
+ *
+ * Documentation:
+ * Available from AMD web site.
+ */
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#define DRV_NAME "pata_cs5530"
+#define DRV_VERSION "0.6"
+
+/**
+ * cs5530_set_piomode - PIO setup
+ * @ap: ATA interface
+ * @adev: device on the interface
+ *
+ * Set our PIO requirements. This is fairly simple on the CS5530
+ * chips.
+ */
+
+static void cs5530_set_piomode(struct ata_port *ap, struct ata_device *adev)
+{
+ static const unsigned int cs5530_pio_timings[2][5] = {
+ {0x00009172, 0x00012171, 0x00020080, 0x00032010, 0x00040010},
+ {0xd1329172, 0x71212171, 0x30200080, 0x20102010, 0x00100010}
+ };
+ unsigned long base = ( ap->ioaddr.bmdma_addr & ~0x0F) + 0x20 + 0x10 * ap->port_no;
+ u32 tuning;
+ int format;
+
+ /* Find out which table to use */
+ tuning = inl(base + 0x04);
+ format = (tuning & 0x80000000UL) ? 1 : 0;
+
+ /* Now load the right timing register */
+ if (adev->devno)
+ base += 0x08;
+
+ outl(cs5530_pio_timings[format][adev->pio_mode - XFER_PIO_0], base);
+}
+
+/**
+ * cs5530_set_dmamode - DMA timing setup
+ * @ap: ATA interface
+ * @adev: Device being configured
+ *
+ * We cannot mix MWDMA and UDMA without reloading timings each switch
+ * master to slave. We track the last DMA setup in order to minimise
+ * reloads.
+ */
+
+static void cs5530_set_dmamode(struct ata_port *ap, struct ata_device *adev)
+{
+ unsigned long base = ( ap->ioaddr.bmdma_addr & ~0x0F) + 0x20 + 0x10 * ap->port_no;
+ u32 tuning, timing = 0;
+ u8 reg;
+
+ /* Find out which table to use */
+ tuning = inl(base + 0x04);
+
+ switch(adev->dma_mode) {
+ case XFER_UDMA_0:
+ timing = 0x00921250;break;
+ case XFER_UDMA_1:
+ timing = 0x00911140;break;
+ case XFER_UDMA_2:
+ timing = 0x00911030;break;
+ case XFER_MW_DMA_0:
+ timing = 0x00077771;break;
+ case XFER_MW_DMA_1:
+ timing = 0x00012121;break;
+ case XFER_MW_DMA_2:
+ timing = 0x00002020;break;
+ default:
+ BUG();
+ }
+ /* Merge in the PIO format bit */
+ timing |= (tuning & 0x80000000UL);
+ if (adev->devno == 0) /* Master */
+ outl(timing, base + 0x04);
+ else {
+ if (timing & 0x00100000)
+ tuning |= 0x00100000; /* UDMA for both */
+ else
+ tuning &= ~0x00100000; /* MWDMA for both */
+ outl(tuning, base + 0x04);
+ outl(timing, base + 0x0C);
+ }
+
+ /* Set the DMA capable bit in the BMDMA area */
+ reg = inb(ap->ioaddr.bmdma_addr + ATA_DMA_STATUS);
+ reg |= (1 << (5 + adev->devno));
+ outb(reg, ap->ioaddr.bmdma_addr + ATA_DMA_STATUS);
+
+ /* Remember the last DMA setup we did */
+
+ ap->private_data = adev;
+}
+
+/**
+ * cs5530_qc_issue_prot - command issue
+ * @qc: command pending
+ *
+ * Called when the libata layer is about to issue a command. We wrap
+ * this interface so that we can load the correct ATA timings if
+ * neccessary. Specifically we have a problem that there is only
+ * one MWDMA/UDMA bit.
+ */
+
+static unsigned int cs5530_qc_issue_prot(struct ata_queued_cmd *qc)
+{
+ struct ata_port *ap = qc->ap;
+ struct ata_device *adev = qc->dev;
+ struct ata_device *prev = ap->private_data;
+
+ /* See if the DMA settings could be wrong */
+ if (adev->dma_mode != 0 && adev != prev && prev != NULL) {
+ /* Maybe, but do the channels match MWDMA/UDMA ? */
+ if ((adev->dma_mode >= XFER_UDMA_0 && prev->dma_mode < XFER_UDMA_0) ||
+ (adev->dma_mode < XFER_UDMA_0 && prev->dma_mode >= XFER_UDMA_0))
+ /* Switch the mode bits */
+ cs5530_set_dmamode(ap, adev);
+ }
+
+ return ata_qc_issue_prot(qc);
+}
+
+static int cs5530_pre_reset(struct ata_port *ap)
+{
+ ap->cbl = ATA_CBL_PATA40;
+ return ata_std_prereset(ap);
+}
+
+static void cs5530_error_handler(struct ata_port *ap)
+{
+ return ata_bmdma_drive_eh(ap, cs5530_pre_reset, ata_std_softreset, NULL, ata_std_postreset);
+}
+
+
+static struct scsi_host_template cs5530_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,
+ .max_sectors = ATA_MAX_SECTORS,
+ .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,
+ .bios_param = ata_std_bios_param,
+};
+
+static struct ata_port_operations cs5530_port_ops = {
+ .port_disable = ata_port_disable,
+ .set_piomode = cs5530_set_piomode,
+ .set_dmamode = cs5530_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,
+
+ .freeze = ata_bmdma_freeze,
+ .thaw = ata_bmdma_thaw,
+ .error_handler = cs5530_error_handler,
+ .post_internal_cmd = ata_bmdma_post_internal_cmd,
+
+ .qc_prep = ata_qc_prep,
+ .qc_issue = cs5530_qc_issue_prot,
+ .eng_timeout = ata_eng_timeout,
+ .data_xfer = ata_pio_data_xfer,
+
+ .irq_handler = ata_interrupt,
+ .irq_clear = ata_bmdma_irq_clear,
+
+ .port_start = ata_port_start,
+ .port_stop = ata_port_stop,
+ .host_stop = ata_host_stop
+};
+
+static struct dmi_system_id palmax_dmi_table[] = {
+ {
+ .ident = "Palmax PD1100",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "Cyrix"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "Caddis"),
+ },
+ },
+ { }
+};
+
+static int cs5530_is_palmax(void)
+{
+ if (dmi_check_system(palmax_dmi_table)) {
+ printk(KERN_INFO "Palmax PD1100: Disabling DMA on docking port.\n");
+ return 1;
+ }
+ return 0;
+}
+
+/**
+ * cs5530_init_one - Initialise a CS5530
+ * @dev: PCI device
+ * @id: Entry in match table
+ *
+ * Install a driver for the newly found CS5530 companion chip. Most of
+ * this is just housekeeping. We have to set the chip up correctly and
+ * turn off various bits of emulation magic.
+ */
+
+static int cs5530_init_one(struct pci_dev *dev, const struct pci_device_id *id)
+{
+ int compiler_warning_pointless_fix;
+ struct pci_dev *master_0 = NULL, *cs5530_0 = NULL;
+ static struct ata_port_info info = {
+ .sht = &cs5530_sht,
+ .flags = ATA_FLAG_SLAVE_POSS|ATA_FLAG_SRST,
+ .pio_mask = 0x1f,
+ .mwdma_mask = 0x07,
+ .udma_mask = 0x07,
+ .port_ops = &cs5530_port_ops
+ };
+ /* The docking connector doesn't do UDMA, and it seems not MWDMA */
+ static struct ata_port_info info_palmax_secondary = {
+ .sht = &cs5530_sht,
+ .flags = ATA_FLAG_SLAVE_POSS|ATA_FLAG_SRST,
+ .pio_mask = 0x1f,
+ .port_ops = &cs5530_port_ops
+ };
+ static struct ata_port_info *port_info[2] = { &info, &info };
+
+ dev = NULL;
+ while ((dev = pci_get_device(PCI_VENDOR_ID_CYRIX, PCI_ANY_ID, dev)) != NULL) {
+ switch (dev->device) {
+ case PCI_DEVICE_ID_CYRIX_PCI_MASTER:
+ master_0 = pci_dev_get(dev);
+ break;
+ case PCI_DEVICE_ID_CYRIX_5530_LEGACY:
+ cs5530_0 = pci_dev_get(dev);
+ break;
+ }
+ }
+ if (!master_0) {
+ printk(KERN_ERR DRV_NAME ": unable to locate PCI MASTER function\n");
+ goto fail_put;
+ }
+ if (!cs5530_0) {
+ printk(KERN_ERR DRV_NAME ": unable to locate CS5530 LEGACY function\n");
+ goto fail_put;
+ }
+
+ pci_set_master(cs5530_0);
+ compiler_warning_pointless_fix = pci_set_mwi(cs5530_0);
+
+ /*
+ * Set PCI CacheLineSize to 16-bytes:
+ * --> Write 0x04 into 8-bit PCI CACHELINESIZE reg of function 0 of the cs5530
+ *
+ * Note: This value is constant because the 5530 is only a Geode companion
+ */
+
+ pci_write_config_byte(cs5530_0, PCI_CACHE_LINE_SIZE, 0x04);
+
+ /*
+ * Disable trapping of UDMA register accesses (Win98 hack):
+ * --> Write 0x5006 into 16-bit reg at offset 0xd0 of function 0 of the cs5530
+ */
+
+ pci_write_config_word(cs5530_0, 0xd0, 0x5006);
+
+ /*
+ * Bit-1 at 0x40 enables MemoryWriteAndInvalidate on internal X-bus:
+ * The other settings are what is necessary to get the register
+ * into a sane state for IDE DMA operation.
+ */
+
+ pci_write_config_byte(master_0, 0x40, 0x1e);
+
+ /*
+ * Set max PCI burst size (16-bytes seems to work best):
+ * 16bytes: set bit-1 at 0x41 (reg value of 0x16)
+ * all others: clear bit-1 at 0x41, and do:
+ * 128bytes: OR 0x00 at 0x41
+ * 256bytes: OR 0x04 at 0x41
+ * 512bytes: OR 0x08 at 0x41
+ * 1024bytes: OR 0x0c at 0x41
+ */
+
+ pci_write_config_byte(master_0, 0x41, 0x14);
+
+ /*
+ * These settings are necessary to get the chip
+ * into a sane state for IDE DMA operation.
+ */
+
+ pci_write_config_byte(master_0, 0x42, 0x00);
+ pci_write_config_byte(master_0, 0x43, 0xc1);
+
+ pci_dev_put(master_0);
+ pci_dev_put(cs5530_0);
+
+ if (cs5530_is_palmax())
+ port_info[1] = &info_palmax_secondary;
+
+ /* Now kick off ATA set up */
+ return ata_pci_init_one(dev, port_info, 2);
+
+fail_put:
+ if (master_0)
+ pci_dev_put(master_0);
+ if (cs5530_0)
+ pci_dev_put(cs5530_0);
+ return -ENODEV;
+}
+
+static struct pci_device_id cs5530[] = {
+ { PCI_DEVICE(PCI_VENDOR_ID_CYRIX, PCI_DEVICE_ID_CYRIX_5530_IDE), },
+ { 0, },
+};
+
+static struct pci_driver cs5530_pci_driver = {
+ .name = DRV_NAME,
+ .id_table = cs5530,
+ .probe = cs5530_init_one,
+ .remove = ata_pci_remove_one
+};
+
+static int __init cs5530_init(void)
+{
+ return pci_register_driver(&cs5530_pci_driver);
+}
+
+
+static void __exit cs5530_exit(void)
+{
+ pci_unregister_driver(&cs5530_pci_driver);
+}
+
+
+MODULE_AUTHOR("Alan Cox");
+MODULE_DESCRIPTION("low-level driver for the Cyrix/NS/AMD 5530");
+MODULE_LICENSE("GPL");
+MODULE_DEVICE_TABLE(pci, cs5530);
+MODULE_VERSION(DRV_VERSION);
+
+module_init(cs5530_init);
+module_exit(cs5530_exit);
diff --git a/drivers/ata/pata_cs5535.c b/drivers/ata/pata_cs5535.c
new file mode 100644
index 000000000000..69d6b4258724
--- /dev/null
+++ b/drivers/ata/pata_cs5535.c
@@ -0,0 +1,291 @@
+/*
+ * pata-cs5535.c - CS5535 PATA for new ATA layer
+ * (C) 2005-2006 Red Hat Inc
+ * Alan Cox
+ *
+ * based upon cs5535.c from AMD as cleaned up and
+ * made readable and Linux style by Wolfgang Zuleger
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * 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
+ *
+ * Loosely based on the piix & svwks drivers.
+ *
+ * Documentation:
+ * Available from AMD web site.
+ * TODO
+ * Review errata to see if serializing is neccessary
+ */
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#define DRV_NAME "cs5535"
+#define DRV_VERSION "0.2.10"
+
+/*
+ * The Geode (Aka Athlon GX now) uses an internal MSR based
+ * bus system for control. Demented but there you go.
+ */
+
+#define MSR_ATAC_BASE 0x51300000
+#define ATAC_GLD_MSR_CAP (MSR_ATAC_BASE+0)
+#define ATAC_GLD_MSR_CONFIG (MSR_ATAC_BASE+0x01)
+#define ATAC_GLD_MSR_SMI (MSR_ATAC_BASE+0x02)
+#define ATAC_GLD_MSR_ERROR (MSR_ATAC_BASE+0x03)
+#define ATAC_GLD_MSR_PM (MSR_ATAC_BASE+0x04)
+#define ATAC_GLD_MSR_DIAG (MSR_ATAC_BASE+0x05)
+#define ATAC_IO_BAR (MSR_ATAC_BASE+0x08)
+#define ATAC_RESET (MSR_ATAC_BASE+0x10)
+#define ATAC_CH0D0_PIO (MSR_ATAC_BASE+0x20)
+#define ATAC_CH0D0_DMA (MSR_ATAC_BASE+0x21)
+#define ATAC_CH0D1_PIO (MSR_ATAC_BASE+0x22)
+#define ATAC_CH0D1_DMA (MSR_ATAC_BASE+0x23)
+#define ATAC_PCI_ABRTERR (MSR_ATAC_BASE+0x24)
+
+#define ATAC_BM0_CMD_PRIM 0x00
+#define ATAC_BM0_STS_PRIM 0x02
+#define ATAC_BM0_PRD 0x04
+
+#define CS5535_CABLE_DETECT 0x48
+
+#define CS5535_BAD_PIO(timings) ( (timings&~0x80000000UL)==0x00009172 )
+
+/**
+ * cs5535_pre_reset - detect cable type
+ * @ap: Port to detect on
+ *
+ * Perform cable detection for ATA66 capable cable. Return a libata
+ * cable type.
+ */
+
+static int cs5535_pre_reset(struct ata_port *ap)
+{
+ u8 cable;
+ struct pci_dev *pdev = to_pci_dev(ap->host->dev);
+
+ pci_read_config_byte(pdev, CS5535_CABLE_DETECT, &cable);
+ if (cable & 1)
+ ap->cbl = ATA_CBL_PATA80;
+ else
+ ap->cbl = ATA_CBL_PATA40;
+ return ata_std_prereset(ap);
+}
+
+/**
+ * cs5535_error_handler - reset/probe
+ * @ap: Port to reset
+ *
+ * Reset and configure a port
+ */
+
+static void cs5535_error_handler(struct ata_port *ap)
+{
+ ata_bmdma_drive_eh(ap, cs5535_pre_reset, ata_std_softreset, NULL, ata_std_postreset);
+}
+
+/**
+ * cs5535_set_piomode - PIO setup
+ * @ap: ATA interface
+ * @adev: device on the interface
+ *
+ * Set our PIO requirements. The CS5535 is pretty clean about all this
+ */
+
+static void cs5535_set_piomode(struct ata_port *ap, struct ata_device *adev)
+{
+ static const u16 pio_timings[5] = {
+ 0xF7F4, 0x53F3, 0x13F1, 0x5131, 0x1131
+ };
+ static const u16 pio_cmd_timings[5] = {
+ 0xF7F4, 0x53F3, 0x13F1, 0x5131, 0x1131
+ };
+ u32 reg, dummy;
+ struct ata_device *pair = ata_dev_pair(adev);
+
+ int mode = adev->pio_mode - XFER_PIO_0;
+ int cmdmode = mode;
+
+ /* Command timing has to be for the lowest of the pair of devices */
+ if (pair) {
+ int pairmode = pair->pio_mode - XFER_PIO_0;
+ cmdmode = min(mode, pairmode);
+ /* Write the other drive timing register if it changed */
+ if (cmdmode < pairmode)
+ wrmsr(ATAC_CH0D0_PIO + 2 * pair->devno,
+ pio_cmd_timings[cmdmode] << 16 | pio_timings[pairmode], 0);
+ }
+ /* Write the drive timing register */
+ wrmsr(ATAC_CH0D0_PIO + 2 * adev->devno,
+ pio_cmd_timings[cmdmode] << 16 | pio_timings[mode], 0);
+
+ /* Set the PIO "format 1" bit in the DMA timing register */
+ rdmsr(ATAC_CH0D0_DMA + 2 * adev->devno, reg, dummy);
+ wrmsr(ATAC_CH0D0_DMA + 2 * adev->devno, reg | 0x80000000UL, 0);
+}
+
+/**
+ * cs5535_set_dmamode - DMA timing setup
+ * @ap: ATA interface
+ * @adev: Device being configured
+ *
+ */
+
+static void cs5535_set_dmamode(struct ata_port *ap, struct ata_device *adev)
+{
+ static const u32 udma_timings[5] = {
+ 0x7F7436A1, 0x7F733481, 0x7F723261, 0x7F713161, 0x7F703061
+ };
+ static const u32 mwdma_timings[3] = {
+ 0x7F0FFFF3, 0x7F035352, 0x7F024241
+ };
+ u32 reg, dummy;
+ int mode = adev->dma_mode;
+
+ rdmsr(ATAC_CH0D0_DMA + 2 * adev->devno, reg, dummy);
+ reg &= 0x80000000UL;
+ if (mode >= XFER_UDMA_0)
+ reg |= udma_timings[mode - XFER_UDMA_0];
+ else
+ reg |= mwdma_timings[mode - XFER_MW_DMA_0];
+ wrmsr(ATAC_CH0D0_DMA + 2 * adev->devno, reg, 0);
+}
+
+static struct scsi_host_template cs5535_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,
+ .max_sectors = ATA_MAX_SECTORS,
+ .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,
+ .bios_param = ata_std_bios_param,
+};
+
+static struct ata_port_operations cs5535_port_ops = {
+ .port_disable = ata_port_disable,
+ .set_piomode = cs5535_set_piomode,
+ .set_dmamode = cs5535_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,
+
+ .freeze = ata_bmdma_freeze,
+ .thaw = ata_bmdma_thaw,
+ .error_handler = cs5535_error_handler,
+ .post_internal_cmd = ata_bmdma_post_internal_cmd,
+
+ .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,
+ .eng_timeout = ata_eng_timeout,
+ .data_xfer = ata_pio_data_xfer,
+
+ .irq_handler = ata_interrupt,
+ .irq_clear = ata_bmdma_irq_clear,
+
+ .port_start = ata_port_start,
+ .port_stop = ata_port_stop,
+ .host_stop = ata_host_stop
+};
+
+/**
+ * cs5535_init_one - Initialise a CS5530
+ * @dev: PCI device
+ * @id: Entry in match table
+ *
+ * Install a driver for the newly found CS5530 companion chip. Most of
+ * this is just housekeeping. We have to set the chip up correctly and
+ * turn off various bits of emulation magic.
+ */
+
+static int cs5535_init_one(struct pci_dev *dev, const struct pci_device_id *id)
+{
+ static struct ata_port_info info = {
+ .sht = &cs5535_sht,
+ .flags = ATA_FLAG_SLAVE_POSS|ATA_FLAG_SRST,
+ .pio_mask = 0x1f,
+ .mwdma_mask = 0x07,
+ .udma_mask = 0x1f,
+ .port_ops = &cs5535_port_ops
+ };
+ struct ata_port_info *ports[1] = { &info };
+
+ u32 timings, dummy;
+
+ /* Check the BIOS set the initial timing clock. If not set the
+ timings for PIO0 */
+ rdmsr(ATAC_CH0D0_PIO, timings, dummy);
+ if (CS5535_BAD_PIO(timings))
+ wrmsr(ATAC_CH0D0_PIO, 0xF7F4F7F4UL, 0);
+ rdmsr(ATAC_CH0D1_PIO, timings, dummy);
+ if (CS5535_BAD_PIO(timings))
+ wrmsr(ATAC_CH0D1_PIO, 0xF7F4F7F4UL, 0);
+ return ata_pci_init_one(dev, ports, 1);
+}
+
+static struct pci_device_id cs5535[] = {
+ { PCI_DEVICE(PCI_VENDOR_ID_NS, 0x002D), },
+ { 0, },
+};
+
+static struct pci_driver cs5535_pci_driver = {
+ .name = DRV_NAME,
+ .id_table = cs5535,
+ .probe = cs5535_init_one,
+ .remove = ata_pci_remove_one
+};
+
+static int __init cs5535_init(void)
+{
+ return pci_register_driver(&cs5535_pci_driver);
+}
+
+
+static void __exit cs5535_exit(void)
+{
+ pci_unregister_driver(&cs5535_pci_driver);
+}
+
+
+MODULE_AUTHOR("Alan Cox, Jens Altmann, Wolfgan Zuleger, Alexander Kiausch");
+MODULE_DESCRIPTION("low-level driver for the NS/AMD 5530");
+MODULE_LICENSE("GPL");
+MODULE_DEVICE_TABLE(pci, cs5535);
+MODULE_VERSION(DRV_VERSION);
+
+module_init(cs5535_init);
+module_exit(cs5535_exit);
diff --git a/drivers/ata/pata_cypress.c b/drivers/ata/pata_cypress.c
new file mode 100644
index 000000000000..fd55474e0d15
--- /dev/null
+++ b/drivers/ata/pata_cypress.c
@@ -0,0 +1,227 @@
+/*
+ * pata_cypress.c - Cypress PATA for new ATA layer
+ * (C) 2006 Red Hat Inc
+ * Alan Cox
+ *
+ * Based heavily on
+ * linux/drivers/ide/pci/cy82c693.c Version 0.40 Sep. 10, 2002
+ *
+ */
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#define DRV_NAME "pata_cypress"
+#define DRV_VERSION "0.1.2"
+
+/* here are the offset definitions for the registers */
+
+enum {
+ CY82_IDE_CMDREG = 0x04,
+ CY82_IDE_ADDRSETUP = 0x48,
+ CY82_IDE_MASTER_IOR = 0x4C,
+ CY82_IDE_MASTER_IOW = 0x4D,
+ CY82_IDE_SLAVE_IOR = 0x4E,
+ CY82_IDE_SLAVE_IOW = 0x4F,
+ CY82_IDE_MASTER_8BIT = 0x50,
+ CY82_IDE_SLAVE_8BIT = 0x51,
+
+ CY82_INDEX_PORT = 0x22,
+ CY82_DATA_PORT = 0x23,
+
+ CY82_INDEX_CTRLREG1 = 0x01,
+ CY82_INDEX_CHANNEL0 = 0x30,
+ CY82_INDEX_CHANNEL1 = 0x31,
+ CY82_INDEX_TIMEOUT = 0x32
+};
+
+static int cy82c693_pre_reset(struct ata_port *ap)
+{
+ ap->cbl = ATA_CBL_PATA40;
+ return ata_std_prereset(ap);
+}
+
+static void cy82c693_error_handler(struct ata_port *ap)
+{
+ ata_bmdma_drive_eh(ap, cy82c693_pre_reset, ata_std_softreset, NULL, ata_std_postreset);
+}
+
+/**
+ * cy82c693_set_piomode - set initial PIO mode data
+ * @ap: ATA interface
+ * @adev: ATA device
+ *
+ * Called to do the PIO mode setup.
+ */
+
+static void cy82c693_set_piomode(struct ata_port *ap, struct ata_device *adev)
+{
+ struct pci_dev *pdev = to_pci_dev(ap->host->dev);
+ struct ata_timing t;
+ const unsigned long T = 1000000 / 33;
+ short time_16, time_8;
+ u32 addr;
+
+ if (ata_timing_compute(adev, adev->pio_mode, &t, T, 1) < 0) {
+ printk(KERN_ERR DRV_NAME ": mome computation failed.\n");
+ return;
+ }
+
+ time_16 = FIT(t.recover, 0, 15) | (FIT(t.active, 0, 15) << 4);
+ time_8 = FIT(t.act8b, 0, 15) | (FIT(t.rec8b, 0, 15) << 4);
+
+ if (adev->devno == 0) {
+ pci_read_config_dword(pdev, CY82_IDE_ADDRSETUP, &addr);
+
+ addr &= ~0x0F; /* Mask bits */
+ addr |= FIT(t.setup, 0, 15);
+
+ pci_write_config_dword(pdev, CY82_IDE_ADDRSETUP, addr);
+ pci_write_config_byte(pdev, CY82_IDE_MASTER_IOR, time_16);
+ pci_write_config_byte(pdev, CY82_IDE_MASTER_IOW, time_16);
+ pci_write_config_byte(pdev, CY82_IDE_MASTER_8BIT, time_8);
+ } else {
+ pci_read_config_dword(pdev, CY82_IDE_ADDRSETUP, &addr);
+
+ addr &= ~0xF0; /* Mask bits */
+ addr |= (FIT(t.setup, 0, 15) << 4);
+
+ pci_write_config_dword(pdev, CY82_IDE_ADDRSETUP, addr);
+ pci_write_config_byte(pdev, CY82_IDE_SLAVE_IOR, time_16);
+ pci_write_config_byte(pdev, CY82_IDE_SLAVE_IOW, time_16);
+ pci_write_config_byte(pdev, CY82_IDE_SLAVE_8BIT, time_8);
+ }
+}
+
+/**
+ * cy82c693_set_dmamode - set initial DMA mode data
+ * @ap: ATA interface
+ * @adev: ATA device
+ *
+ * Called to do the DMA mode setup.
+ */
+
+static void cy82c693_set_dmamode(struct ata_port *ap, struct ata_device *adev)
+{
+ int reg = CY82_INDEX_CHANNEL0 + ap->port_no;
+
+ /* Be afraid, be very afraid. Magic registers in low I/O space */
+ outb(reg, 0x22);
+ outb(adev->dma_mode - XFER_MW_DMA_0, 0x23);
+
+ /* 0x50 gives the best behaviour on the Alpha's using this chip */
+ outb(CY82_INDEX_TIMEOUT, 0x22);
+ outb(0x50, 0x23);
+}
+
+static struct scsi_host_template cy82c693_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,
+ .max_sectors = ATA_MAX_SECTORS,
+ .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,
+ .bios_param = ata_std_bios_param,
+};
+
+static struct ata_port_operations cy82c693_port_ops = {
+ .port_disable = ata_port_disable,
+ .set_piomode = cy82c693_set_piomode,
+ .set_dmamode = cy82c693_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,
+
+ .freeze = ata_bmdma_freeze,
+ .thaw = ata_bmdma_thaw,
+ .error_handler = cy82c693_error_handler,
+ .post_internal_cmd = ata_bmdma_post_internal_cmd,
+
+ .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,
+ .eng_timeout = ata_eng_timeout,
+ .data_xfer = ata_pio_data_xfer,
+
+ .irq_handler = ata_interrupt,
+ .irq_clear = ata_bmdma_irq_clear,
+
+ .port_start = ata_port_start,
+ .port_stop = ata_port_stop,
+ .host_stop = ata_host_stop
+};
+
+static int cy82c693_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
+{
+ static struct ata_port_info info = {
+ .sht = &cy82c693_sht,
+ .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST,
+ .pio_mask = 0x1f,
+ .mwdma_mask = 0x07,
+ .port_ops = &cy82c693_port_ops
+ };
+ static struct ata_port_info *port_info[1] = { &info };
+
+ /* Devfn 1 is the ATA primary. The secondary is magic and on devfn2. For the
+ moment we don't handle the secondary. FIXME */
+
+ if (PCI_FUNC(pdev->devfn) != 1)
+ return -ENODEV;
+
+ return ata_pci_init_one(pdev, port_info, 1);
+}
+
+static struct pci_device_id cy82c693[] = {
+ { PCI_VENDOR_ID_CONTAQ, PCI_DEVICE_ID_CONTAQ_82C693, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+ { 0, },
+};
+
+static struct pci_driver cy82c693_pci_driver = {
+ .name = DRV_NAME,
+ .id_table = cy82c693,
+ .probe = cy82c693_init_one,
+ .remove = ata_pci_remove_one
+};
+
+static int __init cy82c693_init(void)
+{
+ return pci_register_driver(&cy82c693_pci_driver);
+}
+
+
+static void __exit cy82c693_exit(void)
+{
+ pci_unregister_driver(&cy82c693_pci_driver);
+}
+
+
+MODULE_AUTHOR("Alan Cox");
+MODULE_DESCRIPTION("low-level driver for the CY82C693 PATA controller");
+MODULE_LICENSE("GPL");
+MODULE_DEVICE_TABLE(pci, cy82c693);
+MODULE_VERSION(DRV_VERSION);
+
+module_init(cy82c693_init);
+module_exit(cy82c693_exit);
diff --git a/drivers/ata/pata_efar.c b/drivers/ata/pata_efar.c
new file mode 100644
index 000000000000..c30bc181304f
--- /dev/null
+++ b/drivers/ata/pata_efar.c
@@ -0,0 +1,342 @@
+/*
+ * pata_efar.c - EFAR PIIX clone controller driver
+ *
+ * (C) 2005 Red Hat
+ *
+ * Some parts based on ata_piix.c by Jeff Garzik and others.
+ *
+ * The EFAR is a PIIX4 clone with UDMA66 support. Unlike the later
+ * Intel ICH controllers the EFAR widened the UDMA mode register bits
+ * and doesn't require the funky clock selection.
+ */
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#define DRV_NAME "pata_efar"
+#define DRV_VERSION "0.4.1"
+
+/**
+ * efar_pre_reset - check for 40/80 pin
+ * @ap: Port
+ *
+ * Perform cable detection for the EFAR ATA interface. This is
+ * different to the PIIX arrangement
+ */
+
+static int efar_pre_reset(struct ata_port *ap)
+{
+ static const struct pci_bits efar_enable_bits[] = {
+ { 0x41U, 1U, 0x80UL, 0x80UL }, /* port 0 */
+ { 0x43U, 1U, 0x80UL, 0x80UL }, /* port 1 */
+ };
+
+ struct pci_dev *pdev = to_pci_dev(ap->host->dev);
+ u8 tmp;
+
+ if (!pci_test_config_bits(pdev, &efar_enable_bits[ap->port_no])) {
+ ata_port_disable(ap);
+ printk(KERN_INFO "ata%u: port disabled. ignoring.\n", ap->id);
+ return 0;
+ }
+ pci_read_config_byte(pdev, 0x47, &tmp);
+ if (tmp & (2 >> ap->port_no))
+ ap->cbl = ATA_CBL_PATA40;
+ else
+ ap->cbl = ATA_CBL_PATA80;
+ return ata_std_prereset(ap);
+}
+
+/**
+ * efar_probe_reset - Probe specified port on PATA host controller
+ * @ap: Port to probe
+ *
+ * LOCKING:
+ * None (inherited from caller).
+ */
+
+static void efar_error_handler(struct ata_port *ap)
+{
+ ata_bmdma_drive_eh(ap, efar_pre_reset, ata_std_softreset, NULL, ata_std_postreset);
+}
+
+/**
+ * efar_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 efar_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->dev);
+ unsigned int idetm_port= ap->port_no ? 0x42 : 0x40;
+ u16 idetm_data;
+ int control = 0;
+
+ /*
+ * See Intel Document 298600-004 for the timing programing rules
+ * for PIIX/ICH. The EFAR is a clone so very similar
+ */
+
+ static const /* ISP RTC */
+ u8 timings[][2] = { { 0, 0 },
+ { 0, 0 },
+ { 1, 0 },
+ { 2, 1 },
+ { 2, 3 }, };
+
+ if (pio > 2)
+ control |= 1; /* TIME1 enable */
+ if (ata_pio_need_iordy(adev)) /* PIO 3/4 require IORDY */
+ control |= 2; /* IE enable */
+ /* Intel specifies that the PPE functionality is for disk only */
+ if (adev->class == ATA_DEV_ATA)
+ control |= 4; /* PPE enable */
+
+ pci_read_config_word(dev, idetm_port, &idetm_data);
+
+ /* Enable PPE, IE and TIME as appropriate */
+
+ if (adev->devno == 0) {
+ idetm_data &= 0xCCF0;
+ idetm_data |= control;
+ idetm_data |= (timings[pio][0] << 12) |
+ (timings[pio][1] << 8);
+ } else {
+ int shift = 4 * ap->port_no;
+ u8 slave_data;
+
+ idetm_data &= 0xCC0F;
+ idetm_data |= (control << 4);
+
+ /* Slave timing in seperate register */
+ pci_read_config_byte(dev, 0x44, &slave_data);
+ slave_data &= 0x0F << shift;
+ slave_data |= ((timings[pio][0] << 2) | timings[pio][1]) << shift;
+ pci_write_config_byte(dev, 0x44, slave_data);
+ }
+
+ idetm_data |= 0x4000; /* Ensure SITRE is enabled */
+ pci_write_config_word(dev, idetm_port, idetm_data);
+}
+
+/**
+ * efar_set_dmamode - Initialize host controller PATA DMA timings
+ * @ap: Port whose timings we are configuring
+ * @adev: Device to program
+ *
+ * Set UDMA/MWDMA mode for device, in host controller PCI config space.
+ *
+ * LOCKING:
+ * None (inherited from caller).
+ */
+
+static void efar_set_dmamode (struct ata_port *ap, struct ata_device *adev)
+{
+ struct pci_dev *dev = to_pci_dev(ap->host->dev);
+ u8 master_port = ap->port_no ? 0x42 : 0x40;
+ u16 master_data;
+ u8 speed = adev->dma_mode;
+ int devid = adev->devno + 2 * ap->port_no;
+ u8 udma_enable;
+
+ 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);
+ pci_read_config_byte(dev, 0x48, &udma_enable);
+
+ if (speed >= XFER_UDMA_0) {
+ unsigned int udma = adev->dma_mode - XFER_UDMA_0;
+ u16 udma_timing;
+
+ udma_enable |= (1 << devid);
+
+ /* Load the UDMA mode number */
+ pci_read_config_word(dev, 0x4A, &udma_timing);
+ udma_timing &= ~(7 << (4 * devid));
+ udma_timing |= udma << (4 * devid);
+ pci_write_config_word(dev, 0x4A, udma_timing);
+ } else {
+ /*
+ * MWDMA is driven by the PIO timings. We must also enable
+ * IORDY unconditionally along with TIME1. PPE has already
+ * been set when the PIO timing was set.
+ */
+ unsigned int mwdma = adev->dma_mode - XFER_MW_DMA_0;
+ unsigned int control;
+ u8 slave_data;
+ const unsigned int needed_pio[3] = {
+ XFER_PIO_0, XFER_PIO_3, XFER_PIO_4
+ };
+ int pio = needed_pio[mwdma] - XFER_PIO_0;
+
+ control = 3; /* IORDY|TIME1 */
+
+ /* If the drive MWDMA is faster than it can do PIO then
+ we must force PIO into PIO0 */
+
+ if (adev->pio_mode < needed_pio[mwdma])
+ /* Enable DMA timing only */
+ control |= 8; /* PIO cycles in PIO0 */
+
+ if (adev->devno) { /* Slave */
+ master_data &= 0xFF4F; /* Mask out IORDY|TIME1|DMAONLY */
+ master_data |= control << 4;
+ pci_read_config_byte(dev, 0x44, &slave_data);
+ slave_data &= (0x0F + 0xE1 * ap->port_no);
+ /* Load the matching timing */
+ slave_data |= ((timings[pio][0] << 2) | timings[pio][1]) << (ap->port_no ? 4 : 0);
+ pci_write_config_byte(dev, 0x44, slave_data);
+ } else { /* Master */
+ master_data &= 0xCCF4; /* Mask out IORDY|TIME1|DMAONLY
+ and master timing bits */
+ master_data |= control;
+ master_data |=
+ (timings[pio][0] << 12) |
+ (timings[pio][1] << 8);
+ }
+ udma_enable &= ~(1 << devid);
+ pci_write_config_word(dev, master_port, master_data);
+ }
+ pci_write_config_byte(dev, 0x48, udma_enable);
+}
+
+static struct scsi_host_template efar_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,
+ .max_sectors = ATA_MAX_SECTORS,
+ .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,
+ .bios_param = ata_std_bios_param,
+};
+
+static const struct ata_port_operations efar_ops = {
+ .port_disable = ata_port_disable,
+ .set_piomode = efar_set_piomode,
+ .set_dmamode = efar_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,
+
+ .freeze = ata_bmdma_freeze,
+ .thaw = ata_bmdma_thaw,
+ .error_handler = efar_error_handler,
+ .post_internal_cmd = ata_bmdma_post_internal_cmd,
+
+ .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,
+
+ .eng_timeout = ata_eng_timeout,
+
+ .irq_handler = ata_interrupt,
+ .irq_clear = ata_bmdma_irq_clear,
+
+ .port_start = ata_port_start,
+ .port_stop = ata_port_stop,
+ .host_stop = ata_host_stop,
+};
+
+
+/**
+ * efar_init_one - Register EFAR ATA PCI device with kernel services
+ * @pdev: PCI device to register
+ * @ent: Entry in efar_pci_tbl matching with @pdev
+ *
+ * Called from kernel PCI layer.
+ *
+ * LOCKING:
+ * Inherited from PCI layer (may sleep).
+ *
+ * RETURNS:
+ * Zero on success, or -ERRNO value.
+ */
+
+static int efar_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
+{
+ static int printed_version;
+ static struct ata_port_info info = {
+ .sht = &efar_sht,
+ .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST,
+ .pio_mask = 0x1f, /* pio0-4 */
+ .mwdma_mask = 0x07, /* mwdma1-2 */
+ .udma_mask = 0x0f, /* UDMA 66 */
+ .port_ops = &efar_ops,
+ };
+ static struct ata_port_info *port_info[2] = { &info, &info };
+
+ if (!printed_version++)
+ dev_printk(KERN_DEBUG, &pdev->dev,
+ "version " DRV_VERSION "\n");
+
+ return ata_pci_init_one(pdev, port_info, 2);
+}
+
+static const struct pci_device_id efar_pci_tbl[] = {
+ { 0x1055, 0x9130, PCI_ANY_ID, PCI_ANY_ID, },
+ { } /* terminate list */
+};
+
+static struct pci_driver efar_pci_driver = {
+ .name = DRV_NAME,
+ .id_table = efar_pci_tbl,
+ .probe = efar_init_one,
+ .remove = ata_pci_remove_one,
+};
+
+static int __init efar_init(void)
+{
+ return pci_register_driver(&efar_pci_driver);
+}
+
+static void __exit efar_exit(void)
+{
+ pci_unregister_driver(&efar_pci_driver);
+}
+
+
+module_init(efar_init);
+module_exit(efar_exit);
+
+MODULE_AUTHOR("Alan Cox");
+MODULE_DESCRIPTION("SCSI low-level driver for EFAR PIIX clones");
+MODULE_LICENSE("GPL");
+MODULE_DEVICE_TABLE(pci, efar_pci_tbl);
+MODULE_VERSION(DRV_VERSION);
+
diff --git a/drivers/ata/pata_hpt366.c b/drivers/ata/pata_hpt366.c
new file mode 100644
index 000000000000..94bb1dfc3f19
--- /dev/null
+++ b/drivers/ata/pata_hpt366.c
@@ -0,0 +1,478 @@
+/*
+ * Libata driver for the highpoint 366 and 368 UDMA66 ATA controllers.
+ *
+ * This driver is heavily based upon:
+ *
+ * linux/drivers/ide/pci/hpt366.c Version 0.36 April 25, 2003
+ *
+ * Copyright (C) 1999-2003 Andre Hedrick
+ * Portions Copyright (C) 2001 Sun Microsystems, Inc.
+ * Portions Copyright (C) 2003 Red Hat Inc
+ *
+ *
+ * TODO
+ * Maybe PLL mode
+ * Look into engine reset on timeout errors. Should not be
+ * required.
+ */
+
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#define DRV_NAME "pata_hpt366"
+#define DRV_VERSION "0.5"
+
+struct hpt_clock {
+ u8 xfer_speed;
+ u32 timing;
+};
+
+/* key for bus clock timings
+ * bit
+ * 0:3 data_high_time. inactive time of DIOW_/DIOR_ for PIO and MW
+ * DMA. cycles = value + 1
+ * 4:8 data_low_time. active time of DIOW_/DIOR_ for PIO and MW
+ * DMA. cycles = value + 1
+ * 9:12 cmd_high_time. inactive time of DIOW_/DIOR_ during task file
+ * register access.
+ * 13:17 cmd_low_time. active time of DIOW_/DIOR_ during task file
+ * register access.
+ * 18:21 udma_cycle_time. clock freq and clock cycles for UDMA xfer.
+ * during task file register access.
+ * 22:24 pre_high_time. time to initialize 1st cycle for PIO and MW DMA
+ * xfer.
+ * 25:27 cmd_pre_high_time. time to initialize 1st PIO cycle for task
+ * register access.
+ * 28 UDMA enable
+ * 29 DMA enable
+ * 30 PIO_MST enable. if set, the chip is in bus master mode during
+ * PIO.
+ * 31 FIFO enable.
+ */
+
+static const struct hpt_clock hpt366_40[] = {
+ { XFER_UDMA_4, 0x900fd943 },
+ { XFER_UDMA_3, 0x900ad943 },
+ { XFER_UDMA_2, 0x900bd943 },
+ { XFER_UDMA_1, 0x9008d943 },
+ { XFER_UDMA_0, 0x9008d943 },
+
+ { XFER_MW_DMA_2, 0xa008d943 },
+ { XFER_MW_DMA_1, 0xa010d955 },
+ { XFER_MW_DMA_0, 0xa010d9fc },
+
+ { XFER_PIO_4, 0xc008d963 },
+ { XFER_PIO_3, 0xc010d974 },
+ { XFER_PIO_2, 0xc010d997 },
+ { XFER_PIO_1, 0xc010d9c7 },
+ { XFER_PIO_0, 0xc018d9d9 },
+ { 0, 0x0120d9d9 }
+};
+
+static const struct hpt_clock hpt366_33[] = {
+ { XFER_UDMA_4, 0x90c9a731 },
+ { XFER_UDMA_3, 0x90cfa731 },
+ { XFER_UDMA_2, 0x90caa731 },
+ { XFER_UDMA_1, 0x90cba731 },
+ { XFER_UDMA_0, 0x90c8a731 },
+
+ { XFER_MW_DMA_2, 0xa0c8a731 },
+ { XFER_MW_DMA_1, 0xa0c8a732 }, /* 0xa0c8a733 */
+ { XFER_MW_DMA_0, 0xa0c8a797 },
+
+ { XFER_PIO_4, 0xc0c8a731 },
+ { XFER_PIO_3, 0xc0c8a742 },
+ { XFER_PIO_2, 0xc0d0a753 },
+ { XFER_PIO_1, 0xc0d0a7a3 }, /* 0xc0d0a793 */
+ { XFER_PIO_0, 0xc0d0a7aa }, /* 0xc0d0a7a7 */
+ { 0, 0x0120a7a7 }
+};
+
+static const struct hpt_clock hpt366_25[] = {
+ { XFER_UDMA_4, 0x90c98521 },
+ { XFER_UDMA_3, 0x90cf8521 },
+ { XFER_UDMA_2, 0x90cf8521 },
+ { XFER_UDMA_1, 0x90cb8521 },
+ { XFER_UDMA_0, 0x90cb8521 },
+
+ { XFER_MW_DMA_2, 0xa0ca8521 },
+ { XFER_MW_DMA_1, 0xa0ca8532 },
+ { XFER_MW_DMA_0, 0xa0ca8575 },
+
+ { XFER_PIO_4, 0xc0ca8521 },
+ { XFER_PIO_3, 0xc0ca8532 },
+ { XFER_PIO_2, 0xc0ca8542 },
+ { XFER_PIO_1, 0xc0d08572 },
+ { XFER_PIO_0, 0xc0d08585 },
+ { 0, 0x01208585 }
+};
+
+static const char *bad_ata33[] = {
+ "Maxtor 92720U8", "Maxtor 92040U6", "Maxtor 91360U4", "Maxtor 91020U3", "Maxtor 90845U3", "Maxtor 90650U2",
+ "Maxtor 91360D8", "Maxtor 91190D7", "Maxtor 91020D6", "Maxtor 90845D5", "Maxtor 90680D4", "Maxtor 90510D3", "Maxtor 90340D2",
+ "Maxtor 91152D8", "Maxtor 91008D7", "Maxtor 90845D6", "Maxtor 90840D6", "Maxtor 90720D5", "Maxtor 90648D5", "Maxtor 90576D4",
+ "Maxtor 90510D4",
+ "Maxtor 90432D3", "Maxtor 90288D2", "Maxtor 90256D2",
+ "Maxtor 91000D8", "Maxtor 90910D8", "Maxtor 90875D7", "Maxtor 90840D7", "Maxtor 90750D6", "Maxtor 90625D5", "Maxtor 90500D4",
+ "Maxtor 91728D8", "Maxtor 91512D7", "Maxtor 91303D6", "Maxtor 91080D5", "Maxtor 90845D4", "Maxtor 90680D4", "Maxtor 90648D3", "Maxtor 90432D2",
+ NULL
+};
+
+static const char *bad_ata66_4[] = {
+ "IBM-DTLA-307075",
+ "IBM-DTLA-307060",
+ "IBM-DTLA-307045",
+ "IBM-DTLA-307030",
+ "IBM-DTLA-307020",
+ "IBM-DTLA-307015",
+ "IBM-DTLA-305040",
+ "IBM-DTLA-305030",
+ "IBM-DTLA-305020",
+ "IC35L010AVER07-0",
+ "IC35L020AVER07-0",
+ "IC35L030AVER07-0",
+ "IC35L040AVER07-0",
+ "IC35L060AVER07-0",
+ "WDC AC310200R",
+ NULL
+};
+
+static const char *bad_ata66_3[] = {
+ "WDC AC310200R",
+ NULL
+};
+
+static int hpt_dma_blacklisted(const struct ata_device *dev, char *modestr, const char *list[])
+{
+ unsigned char model_num[40];
+ char *s;
+ unsigned int len;
+ int i = 0;
+
+ ata_id_string(dev->id, model_num, ATA_ID_PROD_OFS, sizeof(model_num));
+ s = &model_num[0];
+ len = strnlen(s, sizeof(model_num));
+
+ /* ATAPI specifies that empty space is blank-filled; remove blanks */
+ while ((len > 0) && (s[len - 1] == ' ')) {
+ len--;
+ s[len] = 0;
+ }
+
+ while(list[i] != NULL) {
+ if (!strncmp(list[i], s, len)) {
+ printk(KERN_WARNING DRV_NAME ": %s is not supported for %s.\n",
+ modestr, list[i]);
+ return 1;
+ }
+ i++;
+ }
+ return 0;
+}
+
+/**
+ * hpt366_filter - mode selection filter
+ * @ap: ATA interface
+ * @adev: ATA device
+ *
+ * Block UDMA on devices that cause trouble with this controller.
+ */
+
+static unsigned long hpt366_filter(const struct ata_port *ap, struct ata_device *adev, unsigned long mask)
+{
+ if (adev->class == ATA_DEV_ATA) {
+ if (hpt_dma_blacklisted(adev, "UDMA", bad_ata33))
+ mask &= ~ATA_MASK_UDMA;
+ if (hpt_dma_blacklisted(adev, "UDMA3", bad_ata66_3))
+ mask &= ~(0x07 << ATA_SHIFT_UDMA);
+ if (hpt_dma_blacklisted(adev, "UDMA4", bad_ata66_4))
+ mask &= ~(0x0F << ATA_SHIFT_UDMA);
+ }
+ return ata_pci_default_filter(ap, adev, mask);
+}
+
+/**
+ * hpt36x_find_mode - reset the hpt36x bus
+ * @ap: ATA port
+ * @speed: transfer mode
+ *
+ * Return the 32bit register programming information for this channel
+ * that matches the speed provided.
+ */
+
+static u32 hpt36x_find_mode(struct ata_port *ap, int speed)
+{
+ struct hpt_clock *clocks = ap->host->private_data;
+
+ while(clocks->xfer_speed) {
+ if (clocks->xfer_speed == speed)
+ return clocks->timing;
+ clocks++;
+ }
+ BUG();
+ return 0xffffffffU; /* silence compiler warning */
+}
+
+static int hpt36x_pre_reset(struct ata_port *ap)
+{
+ u8 ata66;
+ struct pci_dev *pdev = to_pci_dev(ap->host->dev);
+
+ pci_read_config_byte(pdev, 0x5A, &ata66);
+ if (ata66 & (1 << ap->port_no))
+ ap->cbl = ATA_CBL_PATA40;
+ else
+ ap->cbl = ATA_CBL_PATA80;
+ return ata_std_prereset(ap);
+}
+
+/**
+ * hpt36x_error_handler - reset the hpt36x bus
+ * @ap: ATA port to reset
+ *
+ * Perform the reset handling for the 366/368
+ */
+
+static void hpt36x_error_handler(struct ata_port *ap)
+{
+ ata_bmdma_drive_eh(ap, hpt36x_pre_reset, ata_std_softreset, NULL, ata_std_postreset);
+}
+
+/**
+ * hpt366_set_piomode - PIO setup
+ * @ap: ATA interface
+ * @adev: device on the interface
+ *
+ * Perform PIO mode setup.
+ */
+
+static void hpt366_set_piomode(struct ata_port *ap, struct ata_device *adev)
+{
+ struct pci_dev *pdev = to_pci_dev(ap->host->dev);
+ u32 addr1, addr2;
+ u32 reg;
+ u32 mode;
+ u8 fast;
+
+ addr1 = 0x40 + 4 * (adev->devno + 2 * ap->port_no);
+ addr2 = 0x51 + 4 * ap->port_no;
+
+ /* Fast interrupt prediction disable, hold off interrupt disable */
+ pci_read_config_byte(pdev, addr2, &fast);
+ if (fast & 0x80) {
+ fast &= ~0x80;
+ pci_write_config_byte(pdev, addr2, fast);
+ }
+
+ pci_read_config_dword(pdev, addr1, ®);
+ mode = hpt36x_find_mode(ap, adev->pio_mode);
+ mode &= ~0x8000000; /* No FIFO in PIO */
+ mode &= ~0x30070000; /* Leave config bits alone */
+ reg &= 0x30070000; /* Strip timing bits */
+ pci_write_config_dword(pdev, addr1, reg | mode);
+}
+
+/**
+ * hpt366_set_dmamode - DMA timing setup
+ * @ap: ATA interface
+ * @adev: Device being configured
+ *
+ * Set up the channel for MWDMA or UDMA modes. Much the same as with
+ * PIO, load the mode number and then set MWDMA or UDMA flag.
+ */
+
+static void hpt366_set_dmamode(struct ata_port *ap, struct ata_device *adev)
+{
+ struct pci_dev *pdev = to_pci_dev(ap->host->dev);
+ u32 addr1, addr2;
+ u32 reg;
+ u32 mode;
+ u8 fast;
+
+ addr1 = 0x40 + 4 * (adev->devno + 2 * ap->port_no);
+ addr2 = 0x51 + 4 * ap->port_no;
+
+ /* Fast interrupt prediction disable, hold off interrupt disable */
+ pci_read_config_byte(pdev, addr2, &fast);
+ if (fast & 0x80) {
+ fast &= ~0x80;
+ pci_write_config_byte(pdev, addr2, fast);
+ }
+
+ pci_read_config_dword(pdev, addr1, ®);
+ mode = hpt36x_find_mode(ap, adev->dma_mode);
+ mode |= 0x8000000; /* FIFO in MWDMA or UDMA */
+ mode &= ~0xC0000000; /* Leave config bits alone */
+ reg &= 0xC0000000; /* Strip timing bits */
+ pci_write_config_dword(pdev, addr1, reg | mode);
+}
+
+static struct scsi_host_template hpt36x_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,
+ .max_sectors = ATA_MAX_SECTORS,
+ .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,
+ .bios_param = ata_std_bios_param,
+};
+
+/*
+ * Configuration for HPT366/68
+ */
+
+static struct ata_port_operations hpt366_port_ops = {
+ .port_disable = ata_port_disable,
+ .set_piomode = hpt366_set_piomode,
+ .set_dmamode = hpt366_set_dmamode,
+ .mode_filter = hpt366_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,
+
+ .freeze = ata_bmdma_freeze,
+ .thaw = ata_bmdma_thaw,
+ .error_handler = hpt36x_error_handler,
+ .post_internal_cmd = ata_bmdma_post_internal_cmd,
+
+ .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,
+ .eng_timeout = ata_eng_timeout,
+ .data_xfer = ata_pio_data_xfer,
+
+ .irq_handler = ata_interrupt,
+ .irq_clear = ata_bmdma_irq_clear,
+
+ .port_start = ata_port_start,
+ .port_stop = ata_port_stop,
+ .host_stop = ata_host_stop
+};
+
+/**
+ * hpt36x_init_one - Initialise an HPT366/368
+ * @dev: PCI device
+ * @id: Entry in match table
+ *
+ * Initialise an HPT36x device. There are some interesting complications
+ * here. Firstly the chip may report 366 and be one of several variants.
+ * Secondly all the timings depend on the clock for the chip which we must
+ * detect and look up
+ *
+ * This is the known chip mappings. It may be missing a couple of later
+ * releases.
+ *
+ * Chip version PCI Rev Notes
+ * HPT366 4 (HPT366) 0 UDMA66
+ * HPT366 4 (HPT366) 1 UDMA66
+ * HPT368 4 (HPT366) 2 UDMA66
+ * HPT37x/30x 4 (HPT366) 3+ Other driver
+ *
+ */
+
+static int hpt36x_init_one(struct pci_dev *dev, const struct pci_device_id *id)
+{
+ static struct ata_port_info info_hpt366 = {
+ .sht = &hpt36x_sht,
+ .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST,
+ .pio_mask = 0x1f,
+ .mwdma_mask = 0x07,
+ .udma_mask = 0x1f,
+ .port_ops = &hpt366_port_ops
+ };
+ struct ata_port_info *port_info[2] = {&info_hpt366, &info_hpt366};
+
+ u32 class_rev;
+ u32 reg1;
+ u8 drive_fast;
+
+ pci_read_config_dword(dev, PCI_CLASS_REVISION, &class_rev);
+ class_rev &= 0xFF;
+
+ /* May be a later chip in disguise. Check */
+ /* Newer chips are not in the HPT36x driver. Ignore them */
+ if (class_rev > 2)
+ return -ENODEV;
+
+ pci_write_config_byte(dev, PCI_CACHE_LINE_SIZE, (L1_CACHE_BYTES / 4));
+ pci_write_config_byte(dev, PCI_LATENCY_TIMER, 0x78);
+ pci_write_config_byte(dev, PCI_MIN_GNT, 0x08);
+ pci_write_config_byte(dev, PCI_MAX_LAT, 0x08);
+
+ pci_read_config_byte(dev, 0x51, &drive_fast);
+ if (drive_fast & 0x80)
+ pci_write_config_byte(dev, 0x51, drive_fast & ~0x80);
+
+ pci_read_config_dword(dev, 0x40, ®1);
+
+ /* PCI clocking determines the ATA timing values to use */
+ /* info_hpt366 is safe against re-entry so we can scribble on it */
+ switch(reg1 & 0x700) {
+ case 5:
+ info_hpt366.private_data = &hpt366_40;
+ break;
+ case 9:
+ info_hpt366.private_data = &hpt366_25;
+ break;
+ default:
+ info_hpt366.private_data = &hpt366_33;
+ break;
+ }
+ /* Now kick off ATA set up */
+ return ata_pci_init_one(dev, port_info, 2);
+}
+
+static struct pci_device_id hpt36x[] = {
+ { PCI_DEVICE(PCI_VENDOR_ID_TTI, PCI_DEVICE_ID_TTI_HPT366), },
+ { 0, },
+};
+
+static struct pci_driver hpt36x_pci_driver = {
+ .name = DRV_NAME,
+ .id_table = hpt36x,
+ .probe = hpt36x_init_one,
+ .remove = ata_pci_remove_one
+};
+
+static int __init hpt36x_init(void)
+{
+ return pci_register_driver(&hpt36x_pci_driver);
+}
+
+
+static void __exit hpt36x_exit(void)
+{
+ pci_unregister_driver(&hpt36x_pci_driver);
+}
+
+
+MODULE_AUTHOR("Alan Cox");
+MODULE_DESCRIPTION("low-level driver for the Highpoint HPT366/368");
+MODULE_LICENSE("GPL");
+MODULE_DEVICE_TABLE(pci, hpt36x);
+MODULE_VERSION(DRV_VERSION);
+
+module_init(hpt36x_init);
+module_exit(hpt36x_exit);
diff --git a/drivers/ata/pata_hpt37x.c b/drivers/ata/pata_hpt37x.c
new file mode 100644
index 000000000000..532a7928f803
--- /dev/null
+++ b/drivers/ata/pata_hpt37x.c
@@ -0,0 +1,1257 @@
+/*
+ * Libata driver for the highpoint 37x and 30x UDMA66 ATA controllers.
+ *
+ * This driver is heavily based upon:
+ *
+ * linux/drivers/ide/pci/hpt366.c Version 0.36 April 25, 2003
+ *
+ * Copyright (C) 1999-2003 Andre Hedrick
+ * Portions Copyright (C) 2001 Sun Microsystems, Inc.
+ * Portions Copyright (C) 2003 Red Hat Inc
+ *
+ * TODO
+ * PLL mode
+ * Look into engine reset on timeout errors. Should not be
+ * required.
+ */
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#define DRV_NAME "pata_hpt37x"
+#define DRV_VERSION "0.5"
+
+struct hpt_clock {
+ u8 xfer_speed;
+ u32 timing;
+};
+
+struct hpt_chip {
+ const char *name;
+ unsigned int base;
+ struct hpt_clock const *clocks[4];
+};
+
+/* key for bus clock timings
+ * bit
+ * 0:3 data_high_time. inactive time of DIOW_/DIOR_ for PIO and MW
+ * DMA. cycles = value + 1
+ * 4:8 data_low_time. active time of DIOW_/DIOR_ for PIO and MW
+ * DMA. cycles = value + 1
+ * 9:12 cmd_high_time. inactive time of DIOW_/DIOR_ during task file
+ * register access.
+ * 13:17 cmd_low_time. active time of DIOW_/DIOR_ during task file
+ * register access.
+ * 18:21 udma_cycle_time. clock freq and clock cycles for UDMA xfer.
+ * during task file register access.
+ * 22:24 pre_high_time. time to initialize 1st cycle for PIO and MW DMA
+ * xfer.
+ * 25:27 cmd_pre_high_time. time to initialize 1st PIO cycle for task
+ * register access.
+ * 28 UDMA enable
+ * 29 DMA enable
+ * 30 PIO_MST enable. if set, the chip is in bus master mode during
+ * PIO.
+ * 31 FIFO enable.
+ */
+
+/* from highpoint documentation. these are old values */
+static const struct hpt_clock hpt370_timings_33[] = {
+/* { XFER_UDMA_5, 0x1A85F442, 0x16454e31 }, */
+ { XFER_UDMA_5, 0x16454e31 },
+ { XFER_UDMA_4, 0x16454e31 },
+ { XFER_UDMA_3, 0x166d4e31 },
+ { XFER_UDMA_2, 0x16494e31 },
+ { XFER_UDMA_1, 0x164d4e31 },
+ { XFER_UDMA_0, 0x16514e31 },
+
+ { XFER_MW_DMA_2, 0x26514e21 },
+ { XFER_MW_DMA_1, 0x26514e33 },
+ { XFER_MW_DMA_0, 0x26514e97 },
+
+ { XFER_PIO_4, 0x06514e21 },
+ { XFER_PIO_3, 0x06514e22 },
+ { XFER_PIO_2, 0x06514e33 },
+ { XFER_PIO_1, 0x06914e43 },
+ { XFER_PIO_0, 0x06914e57 },
+ { 0, 0x06514e57 }
+};
+
+static const struct hpt_clock hpt370_timings_66[] = {
+ { XFER_UDMA_5, 0x14846231 },
+ { XFER_UDMA_4, 0x14886231 },
+ { XFER_UDMA_3, 0x148c6231 },
+ { XFER_UDMA_2, 0x148c6231 },
+ { XFER_UDMA_1, 0x14906231 },
+ { XFER_UDMA_0, 0x14986231 },
+
+ { XFER_MW_DMA_2, 0x26514e21 },
+ { XFER_MW_DMA_1, 0x26514e33 },
+ { XFER_MW_DMA_0, 0x26514e97 },
+
+ { XFER_PIO_4, 0x06514e21 },
+ { XFER_PIO_3, 0x06514e22 },
+ { XFER_PIO_2, 0x06514e33 },
+ { XFER_PIO_1, 0x06914e43 },
+ { XFER_PIO_0, 0x06914e57 },
+ { 0, 0x06514e57 }
+};
+
+/* these are the current (4 sep 2001) timings from highpoint */
+static const struct hpt_clock hpt370a_timings_33[] = {
+ { XFER_UDMA_5, 0x12446231 },
+ { XFER_UDMA_4, 0x12446231 },
+ { XFER_UDMA_3, 0x126c6231 },
+ { XFER_UDMA_2, 0x12486231 },
+ { XFER_UDMA_1, 0x124c6233 },
+ { XFER_UDMA_0, 0x12506297 },
+
+ { XFER_MW_DMA_2, 0x22406c31 },
+ { XFER_MW_DMA_1, 0x22406c33 },
+ { XFER_MW_DMA_0, 0x22406c97 },
+
+ { XFER_PIO_4, 0x06414e31 },
+ { XFER_PIO_3, 0x06414e42 },
+ { XFER_PIO_2, 0x06414e53 },
+ { XFER_PIO_1, 0x06814e93 },
+ { XFER_PIO_0, 0x06814ea7 },
+ { 0, 0x06814ea7 }
+};
+
+/* 2x 33MHz timings */
+static const struct hpt_clock hpt370a_timings_66[] = {
+ { XFER_UDMA_5, 0x1488e673 },
+ { XFER_UDMA_4, 0x1488e673 },
+ { XFER_UDMA_3, 0x1498e673 },
+ { XFER_UDMA_2, 0x1490e673 },
+ { XFER_UDMA_1, 0x1498e677 },
+ { XFER_UDMA_0, 0x14a0e73f },
+
+ { XFER_MW_DMA_2, 0x2480fa73 },
+ { XFER_MW_DMA_1, 0x2480fa77 },
+ { XFER_MW_DMA_0, 0x2480fb3f },
+
+ { XFER_PIO_4, 0x0c82be73 },
+ { XFER_PIO_3, 0x0c82be95 },
+ { XFER_PIO_2, 0x0c82beb7 },
+ { XFER_PIO_1, 0x0d02bf37 },
+ { XFER_PIO_0, 0x0d02bf5f },
+ { 0, 0x0d02bf5f }
+};
+
+static const struct hpt_clock hpt370a_timings_50[] = {
+ { XFER_UDMA_5, 0x12848242 },
+ { XFER_UDMA_4, 0x12ac8242 },
+ { XFER_UDMA_3, 0x128c8242 },
+ { XFER_UDMA_2, 0x120c8242 },
+ { XFER_UDMA_1, 0x12148254 },
+ { XFER_UDMA_0, 0x121882ea },
+
+ { XFER_MW_DMA_2, 0x22808242 },
+ { XFER_MW_DMA_1, 0x22808254 },
+ { XFER_MW_DMA_0, 0x228082ea },
+
+ { XFER_PIO_4, 0x0a81f442 },
+ { XFER_PIO_3, 0x0a81f443 },
+ { XFER_PIO_2, 0x0a81f454 },
+ { XFER_PIO_1, 0x0ac1f465 },
+ { XFER_PIO_0, 0x0ac1f48a },
+ { 0, 0x0ac1f48a }
+};
+
+static const struct hpt_clock hpt372_timings_33[] = {
+ { XFER_UDMA_6, 0x1c81dc62 },
+ { XFER_UDMA_5, 0x1c6ddc62 },
+ { XFER_UDMA_4, 0x1c8ddc62 },
+ { XFER_UDMA_3, 0x1c8edc62 }, /* checkme */
+ { XFER_UDMA_2, 0x1c91dc62 },
+ { XFER_UDMA_1, 0x1c9adc62 }, /* checkme */
+ { XFER_UDMA_0, 0x1c82dc62 }, /* checkme */
+
+ { XFER_MW_DMA_2, 0x2c829262 },
+ { XFER_MW_DMA_1, 0x2c829266 }, /* checkme */
+ { XFER_MW_DMA_0, 0x2c82922e }, /* checkme */
+
+ { XFER_PIO_4, 0x0c829c62 },
+ { XFER_PIO_3, 0x0c829c84 },
+ { XFER_PIO_2, 0x0c829ca6 },
+ { XFER_PIO_1, 0x0d029d26 },
+ { XFER_PIO_0, 0x0d029d5e },
+ { 0, 0x0d029d5e }
+};
+
+static const struct hpt_clock hpt372_timings_50[] = {
+ { XFER_UDMA_5, 0x12848242 },
+ { XFER_UDMA_4, 0x12ac8242 },
+ { XFER_UDMA_3, 0x128c8242 },
+ { XFER_UDMA_2, 0x120c8242 },
+ { XFER_UDMA_1, 0x12148254 },
+ { XFER_UDMA_0, 0x121882ea },
+
+ { XFER_MW_DMA_2, 0x22808242 },
+ { XFER_MW_DMA_1, 0x22808254 },
+ { XFER_MW_DMA_0, 0x228082ea },
+
+ { XFER_PIO_4, 0x0a81f442 },
+ { XFER_PIO_3, 0x0a81f443 },
+ { XFER_PIO_2, 0x0a81f454 },
+ { XFER_PIO_1, 0x0ac1f465 },
+ { XFER_PIO_0, 0x0ac1f48a },
+ { 0, 0x0a81f443 }
+};
+
+static const struct hpt_clock hpt372_timings_66[] = {
+ { XFER_UDMA_6, 0x1c869c62 },
+ { XFER_UDMA_5, 0x1cae9c62 },
+ { XFER_UDMA_4, 0x1c8a9c62 },
+ { XFER_UDMA_3, 0x1c8e9c62 },
+ { XFER_UDMA_2, 0x1c929c62 },
+ { XFER_UDMA_1, 0x1c9a9c62 },
+ { XFER_UDMA_0, 0x1c829c62 },
+
+ { XFER_MW_DMA_2, 0x2c829c62 },
+ { XFER_MW_DMA_1, 0x2c829c66 },
+ { XFER_MW_DMA_0, 0x2c829d2e },
+
+ { XFER_PIO_4, 0x0c829c62 },
+ { XFER_PIO_3, 0x0c829c84 },
+ { XFER_PIO_2, 0x0c829ca6 },
+ { XFER_PIO_1, 0x0d029d26 },
+ { XFER_PIO_0, 0x0d029d5e },
+ { 0, 0x0d029d26 }
+};
+
+static const struct hpt_clock hpt374_timings_33[] = {
+ { XFER_UDMA_6, 0x12808242 },
+ { XFER_UDMA_5, 0x12848242 },
+ { XFER_UDMA_4, 0x12ac8242 },
+ { XFER_UDMA_3, 0x128c8242 },
+ { XFER_UDMA_2, 0x120c8242 },
+ { XFER_UDMA_1, 0x12148254 },
+ { XFER_UDMA_0, 0x121882ea },
+
+ { XFER_MW_DMA_2, 0x22808242 },
+ { XFER_MW_DMA_1, 0x22808254 },
+ { XFER_MW_DMA_0, 0x228082ea },
+
+ { XFER_PIO_4, 0x0a81f442 },
+ { XFER_PIO_3, 0x0a81f443 },
+ { XFER_PIO_2, 0x0a81f454 },
+ { XFER_PIO_1, 0x0ac1f465 },
+ { XFER_PIO_0, 0x0ac1f48a },
+ { 0, 0x06814e93 }
+};
+
+static const struct hpt_chip hpt370 = {
+ "HPT370",
+ 48,
+ {
+ hpt370_timings_33,
+ NULL,
+ NULL,
+ hpt370_timings_66
+ }
+};
+
+static const struct hpt_chip hpt370a = {
+ "HPT370A",
+ 48,
+ {
+ hpt370a_timings_33,
+ NULL,
+ hpt370a_timings_50,
+ hpt370a_timings_66
+ }
+};
+
+static const struct hpt_chip hpt372 = {
+ "HPT372",
+ 55,
+ {
+ hpt372_timings_33,
+ NULL,
+ hpt372_timings_50,
+ hpt372_timings_66
+ }
+};
+
+static const struct hpt_chip hpt302 = {
+ "HPT302",
+ 66,
+ {
+ hpt372_timings_33,
+ NULL,
+ hpt372_timings_50,
+ hpt372_timings_66
+ }
+};
+
+static const struct hpt_chip hpt371 = {
+ "HPT371",
+ 66,
+ {
+ hpt372_timings_33,
+ NULL,
+ hpt372_timings_50,
+ hpt372_timings_66
+ }
+};
+
+static const struct hpt_chip hpt372a = {
+ "HPT372A",
+ 66,
+ {
+ hpt372_timings_33,
+ NULL,
+ hpt372_timings_50,
+ hpt372_timings_66
+ }
+};
+
+static const struct hpt_chip hpt374 = {
+ "HPT374",
+ 48,
+ {
+ hpt374_timings_33,
+ NULL,
+ NULL,
+ NULL
+ }
+};
+
+/**
+ * hpt37x_find_mode - reset the hpt37x bus
+ * @ap: ATA port
+ * @speed: transfer mode
+ *
+ * Return the 32bit register programming information for this channel
+ * that matches the speed provided.
+ */
+
+static u32 hpt37x_find_mode(struct ata_port *ap, int speed)
+{
+ struct hpt_clock *clocks = ap->host->private_data;
+
+ while(clocks->xfer_speed) {
+ if (clocks->xfer_speed == speed)
+ return clocks->timing;
+ clocks++;
+ }
+ BUG();
+ return 0xffffffffU; /* silence compiler warning */
+}
+
+static int hpt_dma_blacklisted(const struct ata_device *dev, char *modestr, const char *list[])
+{
+ unsigned char model_num[40];
+ char *s;
+ unsigned int len;
+ int i = 0;
+
+ ata_id_string(dev->id, model_num, ATA_ID_PROD_OFS,
+ sizeof(model_num));
+ s = &model_num[0];
+ len = strnlen(s, sizeof(model_num));
+
+ /* ATAPI specifies that empty space is blank-filled; remove blanks */
+ while ((len > 0) && (s[len - 1] == ' ')) {
+ len--;
+ s[len] = 0;
+ }
+
+ while(list[i] != NULL) {
+ if (!strncmp(list[i], s, len)) {
+ printk(KERN_WARNING DRV_NAME ": %s is not supported for %s.\n",
+ modestr, list[i]);
+ return 1;
+ }
+ i++;
+ }
+ return 0;
+}
+
+static const char *bad_ata33[] = {
+ "Maxtor 92720U8", "Maxtor 92040U6", "Maxtor 91360U4", "Maxtor 91020U3", "Maxtor 90845U3", "Maxtor 90650U2",
+ "Maxtor 91360D8", "Maxtor 91190D7", "Maxtor 91020D6", "Maxtor 90845D5", "Maxtor 90680D4", "Maxtor 90510D3", "Maxtor 90340D2",
+ "Maxtor 91152D8", "Maxtor 91008D7", "Maxtor 90845D6", "Maxtor 90840D6", "Maxtor 90720D5", "Maxtor 90648D5", "Maxtor 90576D4",
+ "Maxtor 90510D4",
+ "Maxtor 90432D3", "Maxtor 90288D2", "Maxtor 90256D2",
+ "Maxtor 91000D8", "Maxtor 90910D8", "Maxtor 90875D7", "Maxtor 90840D7", "Maxtor 90750D6", "Maxtor 90625D5", "Maxtor 90500D4",
+ "Maxtor 91728D8", "Maxtor 91512D7", "Maxtor 91303D6", "Maxtor 91080D5", "Maxtor 90845D4", "Maxtor 90680D4", "Maxtor 90648D3", "Maxtor 90432D2",
+ NULL
+};
+
+static const char *bad_ata100_5[] = {
+ "IBM-DTLA-307075",
+ "IBM-DTLA-307060",
+ "IBM-DTLA-307045",
+ "IBM-DTLA-307030",
+ "IBM-DTLA-307020",
+ "IBM-DTLA-307015",
+ "IBM-DTLA-305040",
+ "IBM-DTLA-305030",
+ "IBM-DTLA-305020",
+ "IC35L010AVER07-0",
+ "IC35L020AVER07-0",
+ "IC35L030AVER07-0",
+ "IC35L040AVER07-0",
+ "IC35L060AVER07-0",
+ "WDC AC310200R",
+ NULL
+};
+
+/**
+ * hpt370_filter - mode selection filter
+ * @ap: ATA interface
+ * @adev: ATA device
+ *
+ * Block UDMA on devices that cause trouble with this controller.
+ */
+
+static unsigned long hpt370_filter(const struct ata_port *ap, struct ata_device *adev, unsigned long mask)
+{
+ if (adev->class != ATA_DEV_ATA) {
+ if (hpt_dma_blacklisted(adev, "UDMA", bad_ata33))
+ mask &= ~ATA_MASK_UDMA;
+ if (hpt_dma_blacklisted(adev, "UDMA100", bad_ata100_5))
+ mask &= ~(0x1F << ATA_SHIFT_UDMA);
+ }
+ return ata_pci_default_filter(ap, adev, mask);
+}
+
+/**
+ * hpt370a_filter - mode selection filter
+ * @ap: ATA interface
+ * @adev: ATA device
+ *
+ * Block UDMA on devices that cause trouble with this controller.
+ */
+
+static unsigned long hpt370a_filter(const struct ata_port *ap, struct ata_device *adev, unsigned long mask)
+{
+ if (adev->class != ATA_DEV_ATA) {
+ if (hpt_dma_blacklisted(adev, "UDMA100", bad_ata100_5))
+ mask &= ~ (0x1F << ATA_SHIFT_UDMA);
+ }
+ return ata_pci_default_filter(ap, adev, mask);
+}
+
+/**
+ * hpt37x_pre_reset - reset the hpt37x bus
+ * @ap: ATA port to reset
+ *
+ * Perform the initial reset handling for the 370/372 and 374 func 0
+ */
+
+static int hpt37x_pre_reset(struct ata_port *ap)
+{
+ u8 scr2, ata66;
+ struct pci_dev *pdev = to_pci_dev(ap->host->dev);
+
+ pci_read_config_byte(pdev, 0x5B, &scr2);
+ pci_write_config_byte(pdev, 0x5B, scr2 & ~0x01);
+ /* Cable register now active */
+ pci_read_config_byte(pdev, 0x5A, &ata66);
+ /* Restore state */
+ pci_write_config_byte(pdev, 0x5B, scr2);
+
+ if (ata66 & (1 << ap->port_no))
+ ap->cbl = ATA_CBL_PATA40;
+ else
+ ap->cbl = ATA_CBL_PATA80;
+
+ /* Reset the state machine */
+ pci_write_config_byte(pdev, 0x50, 0x37);
+ pci_write_config_byte(pdev, 0x54, 0x37);
+ udelay(100);
+
+ return ata_std_prereset(ap);
+}
+
+/**
+ * hpt37x_error_handler - reset the hpt374
+ * @ap: ATA port to reset
+ *
+ * Perform probe for HPT37x, except for HPT374 channel 2
+ */
+
+static void hpt37x_error_handler(struct ata_port *ap)
+{
+ ata_bmdma_drive_eh(ap, hpt37x_pre_reset, ata_std_softreset, NULL, ata_std_postreset);
+}
+
+static int hpt374_pre_reset(struct ata_port *ap)
+{
+ u16 mcr3, mcr6;
+ u8 ata66;
+
+ struct pci_dev *pdev = to_pci_dev(ap->host->dev);
+ /* Do the extra channel work */
+ pci_read_config_word(pdev, 0x52, &mcr3);
+ pci_read_config_word(pdev, 0x56, &mcr6);
+ /* Set bit 15 of 0x52 to enable TCBLID as input
+ Set bit 15 of 0x56 to enable FCBLID as input
+ */
+ pci_write_config_word(pdev, 0x52, mcr3 | 0x8000);
+ pci_write_config_word(pdev, 0x56, mcr6 | 0x8000);
+ pci_read_config_byte(pdev, 0x5A, &ata66);
+ /* Reset TCBLID/FCBLID to output */
+ pci_write_config_word(pdev, 0x52, mcr3);
+ pci_write_config_word(pdev, 0x56, mcr6);
+
+ if (ata66 & (1 << ap->port_no))
+ ap->cbl = ATA_CBL_PATA40;
+ else
+ ap->cbl = ATA_CBL_PATA80;
+
+ /* Reset the state machine */
+ pci_write_config_byte(pdev, 0x50, 0x37);
+ pci_write_config_byte(pdev, 0x54, 0x37);
+ udelay(100);
+
+ return ata_std_prereset(ap);
+}
+
+/**
+ * hpt374_error_handler - reset the hpt374
+ * @classes:
+ *
+ * The 374 cable detect is a little different due to the extra
+ * channels. The function 0 channels work like usual but function 1
+ * is special
+ */
+
+static void hpt374_error_handler(struct ata_port *ap)
+{
+ struct pci_dev *pdev = to_pci_dev(ap->host->dev);
+
+ if (!(PCI_FUNC(pdev->devfn) & 1))
+ hpt37x_error_handler(ap);
+ else
+ ata_bmdma_drive_eh(ap, hpt374_pre_reset, ata_std_softreset, NULL, ata_std_postreset);
+}
+
+/**
+ * hpt370_set_piomode - PIO setup
+ * @ap: ATA interface
+ * @adev: device on the interface
+ *
+ * Perform PIO mode setup.
+ */
+
+static void hpt370_set_piomode(struct ata_port *ap, struct ata_device *adev)
+{
+ struct pci_dev *pdev = to_pci_dev(ap->host->dev);
+ u32 addr1, addr2;
+ u32 reg;
+ u32 mode;
+ u8 fast;
+
+ addr1 = 0x40 + 4 * (adev->devno + 2 * ap->port_no);
+ addr2 = 0x51 + 4 * ap->port_no;
+
+ /* Fast interrupt prediction disable, hold off interrupt disable */
+ pci_read_config_byte(pdev, addr2, &fast);
+ fast &= ~0x02;
+ fast |= 0x01;
+ pci_write_config_byte(pdev, addr2, fast);
+
+ pci_read_config_dword(pdev, addr1, ®);
+ mode = hpt37x_find_mode(ap, adev->pio_mode);
+ mode &= ~0x8000000; /* No FIFO in PIO */
+ mode &= ~0x30070000; /* Leave config bits alone */
+ reg &= 0x30070000; /* Strip timing bits */
+ pci_write_config_dword(pdev, addr1, reg | mode);
+}
+
+/**
+ * hpt370_set_dmamode - DMA timing setup
+ * @ap: ATA interface
+ * @adev: Device being configured
+ *
+ * Set up the channel for MWDMA or UDMA modes. Much the same as with
+ * PIO, load the mode number and then set MWDMA or UDMA flag.
+ */
+
+static void hpt370_set_dmamode(struct ata_port *ap, struct ata_device *adev)
+{
+ struct pci_dev *pdev = to_pci_dev(ap->host->dev);
+ u32 addr1, addr2;
+ u32 reg;
+ u32 mode;
+ u8 fast;
+
+ addr1 = 0x40 + 4 * (adev->devno + 2 * ap->port_no);
+ addr2 = 0x51 + 4 * ap->port_no;
+
+ /* Fast interrupt prediction disable, hold off interrupt disable */
+ pci_read_config_byte(pdev, addr2, &fast);
+ fast &= ~0x02;
+ fast |= 0x01;
+ pci_write_config_byte(pdev, addr2, fast);
+
+ pci_read_config_dword(pdev, addr1, ®);
+ mode = hpt37x_find_mode(ap, adev->dma_mode);
+ mode |= 0x8000000; /* FIFO in MWDMA or UDMA */
+ mode &= ~0xC0000000; /* Leave config bits alone */
+ reg &= 0xC0000000; /* Strip timing bits */
+ pci_write_config_dword(pdev, addr1, reg | mode);
+}
+
+/**
+ * hpt370_bmdma_start - DMA engine begin
+ * @qc: ATA command
+ *
+ * The 370 and 370A want us to reset the DMA engine each time we
+ * use it. The 372 and later are fine.
+ */
+
+static void hpt370_bmdma_start(struct ata_queued_cmd *qc)
+{
+ struct ata_port *ap = qc->ap;
+ struct pci_dev *pdev = to_pci_dev(ap->host->dev);
+ pci_write_config_byte(pdev, 0x50 + 4 * ap->port_no, 0x37);
+ udelay(10);
+ ata_bmdma_start(qc);
+}
+
+/**
+ * hpt370_bmdma_end - DMA engine stop
+ * @qc: ATA command
+ *
+ * Work around the HPT370 DMA engine.
+ */
+
+static void hpt370_bmdma_stop(struct ata_queued_cmd *qc)
+{
+ struct ata_port *ap = qc->ap;
+ struct pci_dev *pdev = to_pci_dev(ap->host->dev);
+ u8 dma_stat = inb(ap->ioaddr.bmdma_addr + 2);
+ u8 dma_cmd;
+ unsigned long bmdma = ap->ioaddr.bmdma_addr;
+
+ if (dma_stat & 0x01) {
+ udelay(20);
+ dma_stat = inb(bmdma + 2);
+ }
+ if (dma_stat & 0x01) {
+ /* Clear the engine */
+ pci_write_config_byte(pdev, 0x50 + 4 * ap->port_no, 0x37);
+ udelay(10);
+ /* Stop DMA */
+ dma_cmd = inb(bmdma );
+ outb(dma_cmd & 0xFE, bmdma);
+ /* Clear Error */
+ dma_stat = inb(bmdma + 2);
+ outb(dma_stat | 0x06 , bmdma + 2);
+ /* Clear the engine */
+ pci_write_config_byte(pdev, 0x50 + 4 * ap->port_no, 0x37);
+ udelay(10);
+ }
+ ata_bmdma_stop(qc);
+}
+
+/**
+ * hpt372_set_piomode - PIO setup
+ * @ap: ATA interface
+ * @adev: device on the interface
+ *
+ * Perform PIO mode setup.
+ */
+
+static void hpt372_set_piomode(struct ata_port *ap, struct ata_device *adev)
+{
+ struct pci_dev *pdev = to_pci_dev(ap->host->dev);
+ u32 addr1, addr2;
+ u32 reg;
+ u32 mode;
+ u8 fast;
+
+ addr1 = 0x40 + 4 * (adev->devno + 2 * ap->port_no);
+ addr2 = 0x51 + 4 * ap->port_no;
+
+ /* Fast interrupt prediction disable, hold off interrupt disable */
+ pci_read_config_byte(pdev, addr2, &fast);
+ fast &= ~0x07;
+ pci_write_config_byte(pdev, addr2, fast);
+
+ pci_read_config_dword(pdev, addr1, ®);
+ mode = hpt37x_find_mode(ap, adev->pio_mode);
+
+ printk("Find mode for %d reports %X\n", adev->pio_mode, mode);
+ mode &= ~0x80000000; /* No FIFO in PIO */
+ mode &= ~0x30070000; /* Leave config bits alone */
+ reg &= 0x30070000; /* Strip timing bits */
+ pci_write_config_dword(pdev, addr1, reg | mode);
+}
+
+/**
+ * hpt372_set_dmamode - DMA timing setup
+ * @ap: ATA interface
+ * @adev: Device being configured
+ *
+ * Set up the channel for MWDMA or UDMA modes. Much the same as with
+ * PIO, load the mode number and then set MWDMA or UDMA flag.
+ */
+
+static void hpt372_set_dmamode(struct ata_port *ap, struct ata_device *adev)
+{
+ struct pci_dev *pdev = to_pci_dev(ap->host->dev);
+ u32 addr1, addr2;
+ u32 reg;
+ u32 mode;
+ u8 fast;
+
+ addr1 = 0x40 + 4 * (adev->devno + 2 * ap->port_no);
+ addr2 = 0x51 + 4 * ap->port_no;
+
+ /* Fast interrupt prediction disable, hold off interrupt disable */
+ pci_read_config_byte(pdev, addr2, &fast);
+ fast &= ~0x07;
+ pci_write_config_byte(pdev, addr2, fast);
+
+ pci_read_config_dword(pdev, addr1, ®);
+ mode = hpt37x_find_mode(ap, adev->dma_mode);
+ printk("Find mode for DMA %d reports %X\n", adev->dma_mode, mode);
+ mode &= ~0xC0000000; /* Leave config bits alone */
+ mode |= 0x80000000; /* FIFO in MWDMA or UDMA */
+ reg &= 0xC0000000; /* Strip timing bits */
+ pci_write_config_dword(pdev, addr1, reg | mode);
+}
+
+/**
+ * hpt37x_bmdma_end - DMA engine stop
+ * @qc: ATA command
+ *
+ * Clean up after the HPT372 and later DMA engine
+ */
+
+static void hpt37x_bmdma_stop(struct ata_queued_cmd *qc)
+{
+ struct ata_port *ap = qc->ap;
+ struct pci_dev *pdev = to_pci_dev(ap->host->dev);
+ int mscreg = 0x50 + 2 * ap->port_no;
+ u8 bwsr_stat, msc_stat;
+
+ pci_read_config_byte(pdev, 0x6A, &bwsr_stat);
+ pci_read_config_byte(pdev, mscreg, &msc_stat);
+ if (bwsr_stat & (1 << ap->port_no))
+ pci_write_config_byte(pdev, mscreg, msc_stat | 0x30);
+ ata_bmdma_stop(qc);
+}
+
+
+static struct scsi_host_template hpt37x_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,
+ .max_sectors = ATA_MAX_SECTORS,
+ .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,
+ .bios_param = ata_std_bios_param,
+};
+
+/*
+ * Configuration for HPT370
+ */
+
+static struct ata_port_operations hpt370_port_ops = {
+ .port_disable = ata_port_disable,
+ .set_piomode = hpt370_set_piomode,
+ .set_dmamode = hpt370_set_dmamode,
+ .mode_filter = hpt370_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,
+
+ .freeze = ata_bmdma_freeze,
+ .thaw = ata_bmdma_thaw,
+ .error_handler = hpt37x_error_handler,
+ .post_internal_cmd = ata_bmdma_post_internal_cmd,
+
+ .bmdma_setup = ata_bmdma_setup,
+ .bmdma_start = hpt370_bmdma_start,
+ .bmdma_stop = hpt370_bmdma_stop,
+ .bmdma_status = ata_bmdma_status,
+
+ .qc_prep = ata_qc_prep,
+ .qc_issue = ata_qc_issue_prot,
+ .eng_timeout = ata_eng_timeout,
+ .data_xfer = ata_pio_data_xfer,
+
+ .irq_handler = ata_interrupt,
+ .irq_clear = ata_bmdma_irq_clear,
+
+ .port_start = ata_port_start,
+ .port_stop = ata_port_stop,
+ .host_stop = ata_host_stop
+};
+
+/*
+ * Configuration for HPT370A. Close to 370 but less filters
+ */
+
+static struct ata_port_operations hpt370a_port_ops = {
+ .port_disable = ata_port_disable,
+ .set_piomode = hpt370_set_piomode,
+ .set_dmamode = hpt370_set_dmamode,
+ .mode_filter = hpt370a_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,
+
+ .freeze = ata_bmdma_freeze,
+ .thaw = ata_bmdma_thaw,
+ .error_handler = hpt37x_error_handler,
+ .post_internal_cmd = ata_bmdma_post_internal_cmd,
+
+ .bmdma_setup = ata_bmdma_setup,
+ .bmdma_start = hpt370_bmdma_start,
+ .bmdma_stop = hpt370_bmdma_stop,
+ .bmdma_status = ata_bmdma_status,
+
+ .qc_prep = ata_qc_prep,
+ .qc_issue = ata_qc_issue_prot,
+ .eng_timeout = ata_eng_timeout,
+ .data_xfer = ata_pio_data_xfer,
+
+ .irq_handler = ata_interrupt,
+ .irq_clear = ata_bmdma_irq_clear,
+
+ .port_start = ata_port_start,
+ .port_stop = ata_port_stop,
+ .host_stop = ata_host_stop
+};
+
+/*
+ * Configuration for HPT372, HPT371, HPT302. Slightly different PIO
+ * and DMA mode setting functionality.
+ */
+
+static struct ata_port_operations hpt372_port_ops = {
+ .port_disable = ata_port_disable,
+ .set_piomode = hpt372_set_piomode,
+ .set_dmamode = hpt372_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,
+
+ .freeze = ata_bmdma_freeze,
+ .thaw = ata_bmdma_thaw,
+ .error_handler = hpt37x_error_handler,
+ .post_internal_cmd = ata_bmdma_post_internal_cmd,
+
+ .bmdma_setup = ata_bmdma_setup,
+ .bmdma_start = ata_bmdma_start,
+ .bmdma_stop = hpt37x_bmdma_stop,
+ .bmdma_status = ata_bmdma_status,
+
+ .qc_prep = ata_qc_prep,
+ .qc_issue = ata_qc_issue_prot,
+ .eng_timeout = ata_eng_timeout,
+ .data_xfer = ata_pio_data_xfer,
+
+ .irq_handler = ata_interrupt,
+ .irq_clear = ata_bmdma_irq_clear,
+
+ .port_start = ata_port_start,
+ .port_stop = ata_port_stop,
+ .host_stop = ata_host_stop
+};
+
+/*
+ * Configuration for HPT374. Mode setting works like 372 and friends
+ * but we have a different cable detection procedure.
+ */
+
+static struct ata_port_operations hpt374_port_ops = {
+ .port_disable = ata_port_disable,
+ .set_piomode = hpt372_set_piomode,
+ .set_dmamode = hpt372_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,
+
+ .freeze = ata_bmdma_freeze,
+ .thaw = ata_bmdma_thaw,
+ .error_handler = hpt374_error_handler,
+ .post_internal_cmd = ata_bmdma_post_internal_cmd,
+
+ .bmdma_setup = ata_bmdma_setup,
+ .bmdma_start = ata_bmdma_start,
+ .bmdma_stop = hpt37x_bmdma_stop,
+ .bmdma_status = ata_bmdma_status,
+
+ .qc_prep = ata_qc_prep,
+ .qc_issue = ata_qc_issue_prot,
+ .eng_timeout = ata_eng_timeout,
+ .data_xfer = ata_pio_data_xfer,
+
+ .irq_handler = ata_interrupt,
+ .irq_clear = ata_bmdma_irq_clear,
+
+ .port_start = ata_port_start,
+ .port_stop = ata_port_stop,
+ .host_stop = ata_host_stop
+};
+
+/**
+ * htp37x_clock_slot - Turn timing to PC clock entry
+ * @freq: Reported frequency timing
+ * @base: Base timing
+ *
+ * Turn the timing data intoa clock slot (0 for 33, 1 for 40, 2 for 50
+ * and 3 for 66Mhz)
+ */
+
+static int hpt37x_clock_slot(unsigned int freq, unsigned int base)
+{
+ unsigned int f = (base * freq) / 192; /* Mhz */
+ if (f < 40)
+ return 0; /* 33Mhz slot */
+ if (f < 45)
+ return 1; /* 40Mhz slot */
+ if (f < 55)
+ return 2; /* 50Mhz slot */
+ return 3; /* 60Mhz slot */
+}
+
+/**
+ * hpt37x_calibrate_dpll - Calibrate the DPLL loop
+ * @dev: PCI device
+ *
+ * Perform a calibration cycle on the HPT37x DPLL. Returns 1 if this
+ * succeeds
+ */
+
+static int hpt37x_calibrate_dpll(struct pci_dev *dev)
+{
+ u8 reg5b;
+ u32 reg5c;
+ int tries;
+
+ for(tries = 0; tries < 0x5000; tries++) {
+ udelay(50);
+ pci_read_config_byte(dev, 0x5b, ®5b);
+ if (reg5b & 0x80) {
+ /* See if it stays set */
+ for(tries = 0; tries < 0x1000; tries ++) {
+ pci_read_config_byte(dev, 0x5b, ®5b);
+ /* Failed ? */
+ if ((reg5b & 0x80) == 0)
+ return 0;
+ }
+ /* Turn off tuning, we have the DPLL set */
+ pci_read_config_dword(dev, 0x5c, ®5c);
+ pci_write_config_dword(dev, 0x5c, reg5c & ~ 0x100);
+ return 1;
+ }
+ }
+ /* Never went stable */
+ return 0;
+}
+/**
+ * hpt37x_init_one - Initialise an HPT37X/302
+ * @dev: PCI device
+ * @id: Entry in match table
+ *
+ * Initialise an HPT37x device. There are some interesting complications
+ * here. Firstly the chip may report 366 and be one of several variants.
+ * Secondly all the timings depend on the clock for the chip which we must
+ * detect and look up
+ *
+ * This is the known chip mappings. It may be missing a couple of later
+ * releases.
+ *
+ * Chip version PCI Rev Notes
+ * HPT366 4 (HPT366) 0 Other driver
+ * HPT366 4 (HPT366) 1 Other driver
+ * HPT368 4 (HPT366) 2 Other driver
+ * HPT370 4 (HPT366) 3 UDMA100
+ * HPT370A 4 (HPT366) 4 UDMA100
+ * HPT372 4 (HPT366) 5 UDMA133 (1)
+ * HPT372N 4 (HPT366) 6 Other driver
+ * HPT372A 5 (HPT372) 1 UDMA133 (1)
+ * HPT372N 5 (HPT372) 2 Other driver
+ * HPT302 6 (HPT302) 1 UDMA133
+ * HPT302N 6 (HPT302) 2 Other driver
+ * HPT371 7 (HPT371) * UDMA133
+ * HPT374 8 (HPT374) * UDMA133 4 channel
+ * HPT372N 9 (HPT372N) * Other driver
+ *
+ * (1) UDMA133 support depends on the bus clock
+ */
+
+static int hpt37x_init_one(struct pci_dev *dev, const struct pci_device_id *id)
+{
+ /* HPT370 - UDMA100 */
+ static struct ata_port_info info_hpt370 = {
+ .sht = &hpt37x_sht,
+ .flags = ATA_FLAG_SLAVE_POSS|ATA_FLAG_SRST,
+ .pio_mask = 0x1f,
+ .mwdma_mask = 0x07,
+ .udma_mask = 0x3f,
+ .port_ops = &hpt370_port_ops
+ };
+ /* HPT370A - UDMA100 */
+ static struct ata_port_info info_hpt370a = {
+ .sht = &hpt37x_sht,
+ .flags = ATA_FLAG_SLAVE_POSS|ATA_FLAG_SRST,
+ .pio_mask = 0x1f,
+ .mwdma_mask = 0x07,
+ .udma_mask = 0x3f,
+ .port_ops = &hpt370a_port_ops
+ };
+ /* HPT371, 372 and friends - UDMA133 */
+ static struct ata_port_info info_hpt372 = {
+ .sht = &hpt37x_sht,
+ .flags = ATA_FLAG_SLAVE_POSS|ATA_FLAG_SRST,
+ .pio_mask = 0x1f,
+ .mwdma_mask = 0x07,
+ .udma_mask = 0x7f,
+ .port_ops = &hpt372_port_ops
+ };
+ /* HPT371, 372 and friends - UDMA100 at 50MHz clock */
+ static struct ata_port_info info_hpt372_50 = {
+ .sht = &hpt37x_sht,
+ .flags = ATA_FLAG_SLAVE_POSS|ATA_FLAG_SRST,
+ .pio_mask = 0x1f,
+ .mwdma_mask = 0x07,
+ .udma_mask = 0x3f,
+ .port_ops = &hpt372_port_ops
+ };
+ /* HPT374 - UDMA133 */
+ static struct ata_port_info info_hpt374 = {
+ .sht = &hpt37x_sht,
+ .flags = ATA_FLAG_SLAVE_POSS|ATA_FLAG_SRST,
+ .pio_mask = 0x1f,
+ .mwdma_mask = 0x07,
+ .udma_mask = 0x7f,
+ .port_ops = &hpt374_port_ops
+ };
+
+ static const int MHz[4] = { 33, 40, 50, 66 };
+
+ struct ata_port_info *port_info[2];
+ struct ata_port_info *port;
+
+ u8 irqmask;
+ u32 class_rev;
+ u32 freq;
+
+ const struct hpt_chip *chip_table;
+ int clock_slot;
+
+ pci_read_config_dword(dev, PCI_CLASS_REVISION, &class_rev);
+ class_rev &= 0xFF;
+
+ if (dev->device == PCI_DEVICE_ID_TTI_HPT366) {
+ /* May be a later chip in disguise. Check */
+ /* Older chips are in the HPT366 driver. Ignore them */
+ if (class_rev < 3)
+ return -ENODEV;
+ /* N series chips have their own driver. Ignore */
+ if (class_rev == 6)
+ return -ENODEV;
+
+ switch(class_rev) {
+ case 3:
+ port = &info_hpt370;
+ chip_table = &hpt370;
+ break;
+ case 4:
+ port = &info_hpt370a;
+ chip_table = &hpt370a;
+ break;
+ case 5:
+ port = &info_hpt372;
+ chip_table = &hpt372;
+ break;
+ default:
+ printk(KERN_ERR "pata_hpt37x: Unknown HPT366 subtype please report (%d).\n", class_rev);
+ return -ENODEV;
+ }
+ } else {
+ switch(dev->device) {
+ case PCI_DEVICE_ID_TTI_HPT372:
+ /* 372N if rev >= 2*/
+ if (class_rev >= 2)
+ return -ENODEV;
+ port = &info_hpt372;
+ chip_table = &hpt372a;
+ break;
+ case PCI_DEVICE_ID_TTI_HPT302:
+ /* 302N if rev > 1 */
+ if (class_rev > 1)
+ return -ENODEV;
+ port = &info_hpt372;
+ /* Check this */
+ chip_table = &hpt302;
+ break;
+ case PCI_DEVICE_ID_TTI_HPT371:
+ port = &info_hpt372;
+ chip_table = &hpt371;
+ break;
+ case PCI_DEVICE_ID_TTI_HPT374:
+ chip_table = &hpt374;
+ port = &info_hpt374;
+ break;
+ default:
+ printk(KERN_ERR "pata_hpt37x: PCI table is bogus please report (%d).\n", dev->device);
+ return -ENODEV;
+ }
+ }
+ /* Ok so this is a chip we support */
+
+ pci_write_config_byte(dev, PCI_CACHE_LINE_SIZE, (L1_CACHE_BYTES / 4));
+ pci_write_config_byte(dev, PCI_LATENCY_TIMER, 0x78);
+ pci_write_config_byte(dev, PCI_MIN_GNT, 0x08);
+ pci_write_config_byte(dev, PCI_MAX_LAT, 0x08);
+
+ pci_read_config_byte(dev, 0x5A, &irqmask);
+ irqmask &= ~0x10;
+ pci_write_config_byte(dev, 0x5a, irqmask);
+
+ /*
+ * default to pci clock. make sure MA15/16 are set to output
+ * to prevent drives having problems with 40-pin cables. Needed
+ * for some drives such as IBM-DTLA which will not enter ready
+ * state on reset when PDIAG is a input.
+ */
+
+ pci_write_config_byte(dev, 0x5b, 0x23);
+
+ pci_read_config_dword(dev, 0x70, &freq);
+ if ((freq >> 12) != 0xABCDE) {
+ int i;
+ u8 sr;
+ u32 total = 0;
+
+ printk(KERN_WARNING "pata_hpt37x: BIOS has not set timing clocks.\n");
+
+ /* This is the process the HPT371 BIOS is reported to use */
+ for(i = 0; i < 128; i++) {
+ pci_read_config_byte(dev, 0x78, &sr);
+ total += sr;
+ udelay(15);
+ }
+ freq = total / 128;
+ }
+ freq &= 0x1FF;
+
+ /*
+ * Turn the frequency check into a band and then find a timing
+ * table to match it.
+ */
+
+ clock_slot = hpt37x_clock_slot(freq, chip_table->base);
+ if (chip_table->clocks[clock_slot] == NULL) {
+ /*
+ * We need to try PLL mode instead
+ */
+ unsigned int f_low = (MHz[clock_slot] * chip_table->base) / 192;
+ unsigned int f_high = f_low + 2;
+ int adjust;
+
+ for(adjust = 0; adjust < 8; adjust++) {
+ if (hpt37x_calibrate_dpll(dev))
+ break;
+ /* See if it'll settle at a fractionally different clock */
+ if ((adjust & 3) == 3) {
+ f_low --;
+ f_high ++;
+ }
+ pci_write_config_dword(dev, 0x5C, (f_high << 16) | f_low);
+ }
+ if (adjust == 8) {
+ printk(KERN_WARNING "hpt37x: DPLL did not stabilize.\n");
+ return -ENODEV;
+ }
+ /* Check if this works for all cases */
+ port->private_data = (void *)hpt370_timings_66;
+
+ printk(KERN_INFO "hpt37x: Bus clock %dMHz, using DPLL.\n", MHz[clock_slot]);
+ } else {
+ port->private_data = (void *)chip_table->clocks[clock_slot];
+ /*
+ * Perform a final fixup. The 371 and 372 clock determines
+ * if UDMA133 is available.
+ */
+
+ if (clock_slot == 2 && chip_table == &hpt372) { /* 50Mhz */
+ printk(KERN_WARNING "pata_hpt37x: No UDMA133 support available with 50MHz bus clock.\n");
+ if (port == &info_hpt372)
+ port = &info_hpt372_50;
+ else BUG();
+ }
+ printk(KERN_INFO "hpt37x: %s: Bus clock %dMHz.\n", chip_table->name, MHz[clock_slot]);
+ }
+ port_info[0] = port_info[1] = port;
+ /* Now kick off ATA set up */
+ return ata_pci_init_one(dev, port_info, 2);
+}
+
+static struct pci_device_id hpt37x[] = {
+ { PCI_DEVICE(PCI_VENDOR_ID_TTI, PCI_DEVICE_ID_TTI_HPT366), },
+ { PCI_DEVICE(PCI_VENDOR_ID_TTI, PCI_DEVICE_ID_TTI_HPT371), },
+ { PCI_DEVICE(PCI_VENDOR_ID_TTI, PCI_DEVICE_ID_TTI_HPT372), },
+ { PCI_DEVICE(PCI_VENDOR_ID_TTI, PCI_DEVICE_ID_TTI_HPT374), },
+ { PCI_DEVICE(PCI_VENDOR_ID_TTI, PCI_DEVICE_ID_TTI_HPT302), },
+ { 0, },
+};
+
+static struct pci_driver hpt37x_pci_driver = {
+ .name = DRV_NAME,
+ .id_table = hpt37x,
+ .probe = hpt37x_init_one,
+ .remove = ata_pci_remove_one
+};
+
+static int __init hpt37x_init(void)
+{
+ return pci_register_driver(&hpt37x_pci_driver);
+}
+
+
+static void __exit hpt37x_exit(void)
+{
+ pci_unregister_driver(&hpt37x_pci_driver);
+}
+
+
+MODULE_AUTHOR("Alan Cox");
+MODULE_DESCRIPTION("low-level driver for the Highpoint HPT37x/30x");
+MODULE_LICENSE("GPL");
+MODULE_DEVICE_TABLE(pci, hpt37x);
+MODULE_VERSION(DRV_VERSION);
+
+module_init(hpt37x_init);
+module_exit(hpt37x_exit);
diff --git a/drivers/ata/pata_hpt3x2n.c b/drivers/ata/pata_hpt3x2n.c
new file mode 100644
index 000000000000..06c8db079b91
--- /dev/null
+++ b/drivers/ata/pata_hpt3x2n.c
@@ -0,0 +1,597 @@
+/*
+ * Libata driver for the highpoint 372N and 302N UDMA66 ATA controllers.
+ *
+ * This driver is heavily based upon:
+ *
+ * linux/drivers/ide/pci/hpt366.c Version 0.36 April 25, 2003
+ *
+ * Copyright (C) 1999-2003 Andre Hedrick
+ * Portions Copyright (C) 2001 Sun Microsystems, Inc.
+ * Portions Copyright (C) 2003 Red Hat Inc
+ *
+ *
+ * TODO
+ * 371N
+ * Work out best PLL policy
+ */
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#define DRV_NAME "pata_hpt3x2n"
+#define DRV_VERSION "0.3"
+
+enum {
+ HPT_PCI_FAST = (1 << 31),
+ PCI66 = (1 << 1),
+ USE_DPLL = (1 << 0)
+};
+
+struct hpt_clock {
+ u8 xfer_speed;
+ u32 timing;
+};
+
+struct hpt_chip {
+ const char *name;
+ struct hpt_clock *clocks[3];
+};
+
+/* key for bus clock timings
+ * bit
+ * 0:3 data_high_time. inactive time of DIOW_/DIOR_ for PIO and MW
+ * DMA. cycles = value + 1
+ * 4:8 data_low_time. active time of DIOW_/DIOR_ for PIO and MW
+ * DMA. cycles = value + 1
+ * 9:12 cmd_high_time. inactive time of DIOW_/DIOR_ during task file
+ * register access.
+ * 13:17 cmd_low_time. active time of DIOW_/DIOR_ during task file
+ * register access.
+ * 18:21 udma_cycle_time. clock freq and clock cycles for UDMA xfer.
+ * during task file register access.
+ * 22:24 pre_high_time. time to initialize 1st cycle for PIO and MW DMA
+ * xfer.
+ * 25:27 cmd_pre_high_time. time to initialize 1st PIO cycle for task
+ * register access.
+ * 28 UDMA enable
+ * 29 DMA enable
+ * 30 PIO_MST enable. if set, the chip is in bus master mode during
+ * PIO.
+ * 31 FIFO enable.
+ */
+
+/* 66MHz DPLL clocks */
+
+static struct hpt_clock hpt3x2n_clocks[] = {
+ { XFER_UDMA_7, 0x1c869c62 },
+ { XFER_UDMA_6, 0x1c869c62 },
+ { XFER_UDMA_5, 0x1c8a9c62 },
+ { XFER_UDMA_4, 0x1c8a9c62 },
+ { XFER_UDMA_3, 0x1c8e9c62 },
+ { XFER_UDMA_2, 0x1c929c62 },
+ { XFER_UDMA_1, 0x1c9a9c62 },
+ { XFER_UDMA_0, 0x1c829c62 },
+
+ { XFER_MW_DMA_2, 0x2c829c62 },
+ { XFER_MW_DMA_1, 0x2c829c66 },
+ { XFER_MW_DMA_0, 0x2c829d2c },
+
+ { XFER_PIO_4, 0x0c829c62 },
+ { XFER_PIO_3, 0x0c829c84 },
+ { XFER_PIO_2, 0x0c829ca6 },
+ { XFER_PIO_1, 0x0d029d26 },
+ { XFER_PIO_0, 0x0d029d5e },
+ { 0, 0x0d029d5e }
+};
+
+/**
+ * hpt3x2n_find_mode - reset the hpt3x2n bus
+ * @ap: ATA port
+ * @speed: transfer mode
+ *
+ * Return the 32bit register programming information for this channel
+ * that matches the speed provided. For the moment the clocks table
+ * is hard coded but easy to change. This will be needed if we use
+ * different DPLLs
+ */
+
+static u32 hpt3x2n_find_mode(struct ata_port *ap, int speed)
+{
+ struct hpt_clock *clocks = hpt3x2n_clocks;
+
+ while(clocks->xfer_speed) {
+ if (clocks->xfer_speed == speed)
+ return clocks->timing;
+ clocks++;
+ }
+ BUG();
+ return 0xffffffffU; /* silence compiler warning */
+}
+
+/**
+ * hpt3x2n_pre_reset - reset the hpt3x2n bus
+ * @ap: ATA port to reset
+ *
+ * Perform the initial reset handling for the 3x2n series controllers.
+ * Reset the hardware and state machine, obtain the cable type.
+ */
+
+static int hpt3xn_pre_reset(struct ata_port *ap)
+{
+ u8 scr2, ata66;
+ struct pci_dev *pdev = to_pci_dev(ap->host->dev);
+
+ pci_read_config_byte(pdev, 0x5B, &scr2);
+ pci_write_config_byte(pdev, 0x5B, scr2 & ~0x01);
+ /* Cable register now active */
+ pci_read_config_byte(pdev, 0x5A, &ata66);
+ /* Restore state */
+ pci_write_config_byte(pdev, 0x5B, scr2);
+
+ if (ata66 & (1 << ap->port_no))
+ ap->cbl = ATA_CBL_PATA40;
+ else
+ ap->cbl = ATA_CBL_PATA80;
+
+ /* Reset the state machine */
+ pci_write_config_byte(pdev, 0x50, 0x37);
+ pci_write_config_byte(pdev, 0x54, 0x37);
+ udelay(100);
+
+ return ata_std_prereset(ap);
+}
+
+/**
+ * hpt3x2n_error_handler - probe the hpt3x2n bus
+ * @ap: ATA port to reset
+ *
+ * Perform the probe reset handling for the 3x2N
+ */
+
+static void hpt3x2n_error_handler(struct ata_port *ap)
+{
+ ata_bmdma_drive_eh(ap, hpt3xn_pre_reset, ata_std_softreset, NULL, ata_std_postreset);
+}
+
+/**
+ * hpt3x2n_set_piomode - PIO setup
+ * @ap: ATA interface
+ * @adev: device on the interface
+ *
+ * Perform PIO mode setup.
+ */
+
+static void hpt3x2n_set_piomode(struct ata_port *ap, struct ata_device *adev)
+{
+ struct pci_dev *pdev = to_pci_dev(ap->host->dev);
+ u32 addr1, addr2;
+ u32 reg;
+ u32 mode;
+ u8 fast;
+
+ addr1 = 0x40 + 4 * (adev->devno + 2 * ap->port_no);
+ addr2 = 0x51 + 4 * ap->port_no;
+
+ /* Fast interrupt prediction disable, hold off interrupt disable */
+ pci_read_config_byte(pdev, addr2, &fast);
+ fast &= ~0x07;
+ pci_write_config_byte(pdev, addr2, fast);
+
+ pci_read_config_dword(pdev, addr1, ®);
+ mode = hpt3x2n_find_mode(ap, adev->pio_mode);
+ mode &= ~0x8000000; /* No FIFO in PIO */
+ mode &= ~0x30070000; /* Leave config bits alone */
+ reg &= 0x30070000; /* Strip timing bits */
+ pci_write_config_dword(pdev, addr1, reg | mode);
+}
+
+/**
+ * hpt3x2n_set_dmamode - DMA timing setup
+ * @ap: ATA interface
+ * @adev: Device being configured
+ *
+ * Set up the channel for MWDMA or UDMA modes. Much the same as with
+ * PIO, load the mode number and then set MWDMA or UDMA flag.
+ */
+
+static void hpt3x2n_set_dmamode(struct ata_port *ap, struct ata_device *adev)
+{
+ struct pci_dev *pdev = to_pci_dev(ap->host->dev);
+ u32 addr1, addr2;
+ u32 reg;
+ u32 mode;
+ u8 fast;
+
+ addr1 = 0x40 + 4 * (adev->devno + 2 * ap->port_no);
+ addr2 = 0x51 + 4 * ap->port_no;
+
+ /* Fast interrupt prediction disable, hold off interrupt disable */
+ pci_read_config_byte(pdev, addr2, &fast);
+ fast &= ~0x07;
+ pci_write_config_byte(pdev, addr2, fast);
+
+ pci_read_config_dword(pdev, addr1, ®);
+ mode = hpt3x2n_find_mode(ap, adev->dma_mode);
+ mode |= 0x8000000; /* FIFO in MWDMA or UDMA */
+ mode &= ~0xC0000000; /* Leave config bits alone */
+ reg &= 0xC0000000; /* Strip timing bits */
+ pci_write_config_dword(pdev, addr1, reg | mode);
+}
+
+/**
+ * hpt3x2n_bmdma_end - DMA engine stop
+ * @qc: ATA command
+ *
+ * Clean up after the HPT3x2n and later DMA engine
+ */
+
+static void hpt3x2n_bmdma_stop(struct ata_queued_cmd *qc)
+{
+ struct ata_port *ap = qc->ap;
+ struct pci_dev *pdev = to_pci_dev(ap->host->dev);
+ int mscreg = 0x50 + 2 * ap->port_no;
+ u8 bwsr_stat, msc_stat;
+
+ pci_read_config_byte(pdev, 0x6A, &bwsr_stat);
+ pci_read_config_byte(pdev, mscreg, &msc_stat);
+ if (bwsr_stat & (1 << ap->port_no))
+ pci_write_config_byte(pdev, mscreg, msc_stat | 0x30);
+ ata_bmdma_stop(qc);
+}
+
+/**
+ * hpt3x2n_set_clock - clock control
+ * @ap: ATA port
+ * @source: 0x21 or 0x23 for PLL or PCI sourced clock
+ *
+ * Switch the ATA bus clock between the PLL and PCI clock sources
+ * while correctly isolating the bus and resetting internal logic
+ *
+ * We must use the DPLL for
+ * - writing
+ * - second channel UDMA7 (SATA ports) or higher
+ * - 66MHz PCI
+ *
+ * or we will underclock the device and get reduced performance.
+ */
+
+static void hpt3x2n_set_clock(struct ata_port *ap, int source)
+{
+ unsigned long bmdma = ap->ioaddr.bmdma_addr;
+
+ /* Tristate the bus */
+ outb(0x80, bmdma+0x73);
+ outb(0x80, bmdma+0x77);
+
+ /* Switch clock and reset channels */
+ outb(source, bmdma+0x7B);
+ outb(0xC0, bmdma+0x79);
+
+ /* Reset state machines */
+ outb(0x37, bmdma+0x70);
+ outb(0x37, bmdma+0x74);
+
+ /* Complete reset */
+ outb(0x00, bmdma+0x79);
+
+ /* Reconnect channels to bus */
+ outb(0x00, bmdma+0x73);
+ outb(0x00, bmdma+0x77);
+}
+
+/* Check if our partner interface is busy */
+
+static int hpt3x2n_pair_idle(struct ata_port *ap)
+{
+ struct ata_host *host = ap->host;
+ struct ata_port *pair = host->ports[ap->port_no ^ 1];
+
+ if (pair->hsm_task_state == HSM_ST_IDLE)
+ return 1;
+ return 0;
+}
+
+static int hpt3x2n_use_dpll(struct ata_port *ap, int reading)
+{
+ long flags = (long)ap->host->private_data;
+ /* See if we should use the DPLL */
+ if (reading == 0)
+ return USE_DPLL; /* Needed for write */
+ if (flags & PCI66)
+ return USE_DPLL; /* Needed at 66Mhz */
+ return 0;
+}
+
+static unsigned int hpt3x2n_qc_issue_prot(struct ata_queued_cmd *qc)
+{
+ struct ata_taskfile *tf = &qc->tf;
+ struct ata_port *ap = qc->ap;
+ int flags = (long)ap->host->private_data;
+
+ if (hpt3x2n_pair_idle(ap)) {
+ int dpll = hpt3x2n_use_dpll(ap, (tf->flags & ATA_TFLAG_WRITE));
+ if ((flags & USE_DPLL) != dpll) {
+ if (dpll == 1)
+ hpt3x2n_set_clock(ap, 0x21);
+ else
+ hpt3x2n_set_clock(ap, 0x23);
+ }
+ }
+ return ata_qc_issue_prot(qc);
+}
+
+static struct scsi_host_template hpt3x2n_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,
+ .max_sectors = ATA_MAX_SECTORS,
+ .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,
+ .bios_param = ata_std_bios_param,
+};
+
+/*
+ * Configuration for HPT3x2n.
+ */
+
+static struct ata_port_operations hpt3x2n_port_ops = {
+ .port_disable = ata_port_disable,
+ .set_piomode = hpt3x2n_set_piomode,
+ .set_dmamode = hpt3x2n_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,
+
+ .freeze = ata_bmdma_freeze,
+ .thaw = ata_bmdma_thaw,
+ .error_handler = hpt3x2n_error_handler,
+ .post_internal_cmd = ata_bmdma_post_internal_cmd,
+
+ .bmdma_setup = ata_bmdma_setup,
+ .bmdma_start = ata_bmdma_start,
+ .bmdma_stop = hpt3x2n_bmdma_stop,
+ .bmdma_status = ata_bmdma_status,
+
+ .qc_prep = ata_qc_prep,
+ .qc_issue = hpt3x2n_qc_issue_prot,
+ .eng_timeout = ata_eng_timeout,
+ .data_xfer = ata_pio_data_xfer,
+
+ .irq_handler = ata_interrupt,
+ .irq_clear = ata_bmdma_irq_clear,
+
+ .port_start = ata_port_start,
+ .port_stop = ata_port_stop,
+ .host_stop = ata_host_stop
+};
+
+/**
+ * hpt3xn_calibrate_dpll - Calibrate the DPLL loop
+ * @dev: PCI device
+ *
+ * Perform a calibration cycle on the HPT3xN DPLL. Returns 1 if this
+ * succeeds
+ */
+
+static int hpt3xn_calibrate_dpll(struct pci_dev *dev)
+{
+ u8 reg5b;
+ u32 reg5c;
+ int tries;
+
+ for(tries = 0; tries < 0x5000; tries++) {
+ udelay(50);
+ pci_read_config_byte(dev, 0x5b, ®5b);
+ if (reg5b & 0x80) {
+ /* See if it stays set */
+ for(tries = 0; tries < 0x1000; tries ++) {
+ pci_read_config_byte(dev, 0x5b, ®5b);
+ /* Failed ? */
+ if ((reg5b & 0x80) == 0)
+ return 0;
+ }
+ /* Turn off tuning, we have the DPLL set */
+ pci_read_config_dword(dev, 0x5c, ®5c);
+ pci_write_config_dword(dev, 0x5c, reg5c & ~ 0x100);
+ return 1;
+ }
+ }
+ /* Never went stable */
+ return 0;
+}
+
+static int hpt3x2n_pci_clock(struct pci_dev *pdev)
+{
+ unsigned long freq;
+ u32 fcnt;
+
+ pci_read_config_dword(pdev, 0x70/*CHECKME*/, &fcnt);
+ if ((fcnt >> 12) != 0xABCDE) {
+ printk(KERN_WARNING "hpt3xn: BIOS clock data not set.\n");
+ return 33; /* Not BIOS set */
+ }
+ fcnt &= 0x1FF;
+
+ freq = (fcnt * 77) / 192;
+
+ /* Clamp to bands */
+ if (freq < 40)
+ return 33;
+ if (freq < 45)
+ return 40;
+ if (freq < 55)
+ return 50;
+ return 66;
+}
+
+/**
+ * hpt3x2n_init_one - Initialise an HPT37X/302
+ * @dev: PCI device
+ * @id: Entry in match table
+ *
+ * Initialise an HPT3x2n device. There are some interesting complications
+ * here. Firstly the chip may report 366 and be one of several variants.
+ * Secondly all the timings depend on the clock for the chip which we must
+ * detect and look up
+ *
+ * This is the known chip mappings. It may be missing a couple of later
+ * releases.
+ *
+ * Chip version PCI Rev Notes
+ * HPT372 4 (HPT366) 5 Other driver
+ * HPT372N 4 (HPT366) 6 UDMA133
+ * HPT372 5 (HPT372) 1 Other driver
+ * HPT372N 5 (HPT372) 2 UDMA133
+ * HPT302 6 (HPT302) * Other driver
+ * HPT302N 6 (HPT302) > 1 UDMA133
+ * HPT371 7 (HPT371) * Other driver
+ * HPT371N 7 (HPT371) > 1 UDMA133
+ * HPT374 8 (HPT374) * Other driver
+ * HPT372N 9 (HPT372N) * UDMA133
+ *
+ * (1) UDMA133 support depends on the bus clock
+ *
+ * To pin down HPT371N
+ */
+
+static int hpt3x2n_init_one(struct pci_dev *dev, const struct pci_device_id *id)
+{
+ /* HPT372N and friends - UDMA133 */
+ static struct ata_port_info info = {
+ .sht = &hpt3x2n_sht,
+ .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST,
+ .pio_mask = 0x1f,
+ .mwdma_mask = 0x07,
+ .udma_mask = 0x7f,
+ .port_ops = &hpt3x2n_port_ops
+ };
+ struct ata_port_info *port_info[2];
+ struct ata_port_info *port = &info;
+
+ u8 irqmask;
+ u32 class_rev;
+
+ unsigned int pci_mhz;
+ unsigned int f_low, f_high;
+ int adjust;
+
+ pci_read_config_dword(dev, PCI_CLASS_REVISION, &class_rev);
+ class_rev &= 0xFF;
+
+ switch(dev->device) {
+ case PCI_DEVICE_ID_TTI_HPT366:
+ if (class_rev < 6)
+ return -ENODEV;
+ break;
+ case PCI_DEVICE_ID_TTI_HPT372:
+ /* 372N if rev >= 1*/
+ if (class_rev == 0)
+ return -ENODEV;
+ break;
+ case PCI_DEVICE_ID_TTI_HPT302:
+ if (class_rev < 2)
+ return -ENODEV;
+ break;
+ case PCI_DEVICE_ID_TTI_HPT372N:
+ break;
+ default:
+ printk(KERN_ERR "pata_hpt3x2n: PCI table is bogus please report (%d).\n", dev->device);
+ return -ENODEV;
+ }
+
+ /* Ok so this is a chip we support */
+
+ pci_write_config_byte(dev, PCI_CACHE_LINE_SIZE, (L1_CACHE_BYTES / 4));
+ pci_write_config_byte(dev, PCI_LATENCY_TIMER, 0x78);
+ pci_write_config_byte(dev, PCI_MIN_GNT, 0x08);
+ pci_write_config_byte(dev, PCI_MAX_LAT, 0x08);
+
+ pci_read_config_byte(dev, 0x5A, &irqmask);
+ irqmask &= ~0x10;
+ pci_write_config_byte(dev, 0x5a, irqmask);
+
+ /* Tune the PLL. HPT recommend using 75 for SATA, 66 for UDMA133 or
+ 50 for UDMA100. Right now we always use 66 */
+
+ pci_mhz = hpt3x2n_pci_clock(dev);
+
+ f_low = (pci_mhz * 48) / 66; /* PCI Mhz for 66Mhz DPLL */
+ f_high = f_low + 2; /* Tolerance */
+
+ pci_write_config_dword(dev, 0x5C, (f_high << 16) | f_low | 0x100);
+ /* PLL clock */
+ pci_write_config_byte(dev, 0x5B, 0x21);
+
+ /* Unlike the 37x we don't try jiggling the frequency */
+ for(adjust = 0; adjust < 8; adjust++) {
+ if (hpt3xn_calibrate_dpll(dev))
+ break;
+ pci_write_config_dword(dev, 0x5C, (f_high << 16) | f_low);
+ }
+ if (adjust == 8)
+ printk(KERN_WARNING "hpt3xn: DPLL did not stabilize.\n");
+
+ /* Set our private data up. We only need a few flags so we use
+ it directly */
+ port->private_data = NULL;
+ if (pci_mhz > 60)
+ port->private_data = (void *)PCI66;
+
+ /* Now kick off ATA set up */
+ port_info[0] = port_info[1] = port;
+ return ata_pci_init_one(dev, port_info, 2);
+}
+
+static struct pci_device_id hpt3x2n[] = {
+ { PCI_DEVICE(PCI_VENDOR_ID_TTI, PCI_DEVICE_ID_TTI_HPT366), },
+ { PCI_DEVICE(PCI_VENDOR_ID_TTI, PCI_DEVICE_ID_TTI_HPT372), },
+ { PCI_DEVICE(PCI_VENDOR_ID_TTI, PCI_DEVICE_ID_TTI_HPT302), },
+ { PCI_DEVICE(PCI_VENDOR_ID_TTI, PCI_DEVICE_ID_TTI_HPT372N), },
+ { 0, },
+};
+
+static struct pci_driver hpt3x2n_pci_driver = {
+ .name = DRV_NAME,
+ .id_table = hpt3x2n,
+ .probe = hpt3x2n_init_one,
+ .remove = ata_pci_remove_one
+};
+
+static int __init hpt3x2n_init(void)
+{
+ return pci_register_driver(&hpt3x2n_pci_driver);
+}
+
+
+static void __exit hpt3x2n_exit(void)
+{
+ pci_unregister_driver(&hpt3x2n_pci_driver);
+}
+
+
+MODULE_AUTHOR("Alan Cox");
+MODULE_DESCRIPTION("low-level driver for the Highpoint HPT3x2n/30x");
+MODULE_LICENSE("GPL");
+MODULE_DEVICE_TABLE(pci, hpt3x2n);
+MODULE_VERSION(DRV_VERSION);
+
+module_init(hpt3x2n_init);
+module_exit(hpt3x2n_exit);
diff --git a/drivers/ata/pata_hpt3x3.c b/drivers/ata/pata_hpt3x3.c
new file mode 100644
index 000000000000..152770133ab1
--- /dev/null
+++ b/drivers/ata/pata_hpt3x3.c
@@ -0,0 +1,226 @@
+/*
+ * pata_hpt3x3 - HPT3x3 driver
+ * (c) Copyright 2005-2006 Red Hat
+ *
+ * Was pata_hpt34x but the naming was confusing as it supported the
+ * 343 and 363 so it has been renamed.
+ *
+ * Based on:
+ * linux/drivers/ide/pci/hpt34x.c Version 0.40 Sept 10, 2002
+ * Copyright (C) 1998-2000 Andre Hedrick
+ *
+ * May be copied or modified under the terms of the GNU General Public
+ * License
+ */
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#define DRV_NAME "pata_hpt3x3"
+#define DRV_VERSION "0.4.1"
+
+static int hpt3x3_probe_init(struct ata_port *ap)
+{
+ ap->cbl = ATA_CBL_PATA40;
+ return ata_std_prereset(ap);
+}
+
+/**
+ * hpt3x3_probe_reset - reset the hpt3x3 bus
+ * @ap: ATA port to reset
+ *
+ * Perform the housekeeping when doing an ATA bus reeset. We just
+ * need to force the cable type.
+ */
+
+static void hpt3x3_error_handler(struct ata_port *ap)
+{
+ return ata_bmdma_drive_eh(ap, hpt3x3_probe_init, ata_std_softreset, NULL, ata_std_postreset);
+}
+
+/**
+ * hpt3x3_set_piomode - PIO setup
+ * @ap: ATA interface
+ * @adev: device on the interface
+ *
+ * Set our PIO requirements. This is fairly simple on the HPT3x3 as
+ * all we have to do is clear the MWDMA and UDMA bits then load the
+ * mode number.
+ */
+
+static void hpt3x3_set_piomode(struct ata_port *ap, struct ata_device *adev)
+{
+ struct pci_dev *pdev = to_pci_dev(ap->host->dev);
+ u32 r1, r2;
+ int dn = 2 * ap->port_no + adev->devno;
+
+ pci_read_config_dword(pdev, 0x44, &r1);
+ pci_read_config_dword(pdev, 0x48, &r2);
+ /* Load the PIO timing number */
+ r1 &= ~(7 << (3 * dn));
+ r1 |= (adev->pio_mode - XFER_PIO_0) << (3 * dn);
+ r2 &= ~(0x11 << dn); /* Clear MWDMA and UDMA bits */
+
+ pci_write_config_dword(pdev, 0x44, r1);
+ pci_write_config_dword(pdev, 0x48, r2);
+}
+
+/**
+ * hpt3x3_set_dmamode - DMA timing setup
+ * @ap: ATA interface
+ * @adev: Device being configured
+ *
+ * Set up the channel for MWDMA or UDMA modes. Much the same as with
+ * PIO, load the mode number and then set MWDMA or UDMA flag.
+ */
+
+static void hpt3x3_set_dmamode(struct ata_port *ap, struct ata_device *adev)
+{
+ struct pci_dev *pdev = to_pci_dev(ap->host->dev);
+ u32 r1, r2;
+ int dn = 2 * ap->port_no + adev->devno;
+ int mode_num = adev->dma_mode & 0x0F;
+
+ pci_read_config_dword(pdev, 0x44, &r1);
+ pci_read_config_dword(pdev, 0x48, &r2);
+ /* Load the timing number */
+ r1 &= ~(7 << (3 * dn));
+ r1 |= (mode_num << (3 * dn));
+ r2 &= ~(0x11 << dn); /* Clear MWDMA and UDMA bits */
+
+ if (adev->dma_mode >= XFER_UDMA_0)
+ r2 |= 0x01 << dn; /* Ultra mode */
+ else
+ r2 |= 0x10 << dn; /* MWDMA */
+
+ pci_write_config_dword(pdev, 0x44, r1);
+ pci_write_config_dword(pdev, 0x48, r2);
+}
+
+static struct scsi_host_template hpt3x3_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,
+ .max_sectors = ATA_MAX_SECTORS,
+ .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,
+ .bios_param = ata_std_bios_param,
+};
+
+static struct ata_port_operations hpt3x3_port_ops = {
+ .port_disable = ata_port_disable,
+ .set_piomode = hpt3x3_set_piomode,
+ .set_dmamode = hpt3x3_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,
+
+ .freeze = ata_bmdma_freeze,
+ .thaw = ata_bmdma_thaw,
+ .error_handler = hpt3x3_error_handler,
+ .post_internal_cmd = ata_bmdma_post_internal_cmd,
+
+ .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,
+ .eng_timeout = ata_eng_timeout,
+ .data_xfer = ata_pio_data_xfer,
+
+ .irq_handler = ata_interrupt,
+ .irq_clear = ata_bmdma_irq_clear,
+
+ .port_start = ata_port_start,
+ .port_stop = ata_port_stop,
+ .host_stop = ata_host_stop
+};
+
+/**
+ * hpt3x3_init_one - Initialise an HPT343/363
+ * @dev: PCI device
+ * @id: Entry in match table
+ *
+ * Perform basic initialisation. The chip has a quirk that it won't
+ * function unless it is at XX00. The old ATA driver touched this up
+ * but we leave it for pci quirks to do properly.
+ */
+
+static int hpt3x3_init_one(struct pci_dev *dev, const struct pci_device_id *id)
+{
+ static struct ata_port_info info = {
+ .sht = &hpt3x3_sht,
+ .flags = ATA_FLAG_SLAVE_POSS|ATA_FLAG_SRST,
+ .pio_mask = 0x1f,
+ .mwdma_mask = 0x07,
+ .udma_mask = 0x07,
+ .port_ops = &hpt3x3_port_ops
+ };
+ static struct ata_port_info *port_info[2] = { &info, &info };
+ u16 cmd;
+
+ /* Initialize the board */
+ pci_write_config_word(dev, 0x80, 0x00);
+ /* Check if it is a 343 or a 363. 363 has COMMAND_MEMORY set */
+ pci_read_config_word(dev, PCI_COMMAND, &cmd);
+ if (cmd & PCI_COMMAND_MEMORY)
+ pci_write_config_byte(dev, PCI_LATENCY_TIMER, 0xF0);
+ else
+ pci_write_config_byte(dev, PCI_LATENCY_TIMER, 0x20);
+
+ /* Now kick off ATA set up */
+ return ata_pci_init_one(dev, port_info, 2);
+}
+
+static struct pci_device_id hpt3x3[] = {
+ { PCI_DEVICE(PCI_VENDOR_ID_TTI, PCI_DEVICE_ID_TTI_HPT343), },
+ { 0, },
+};
+
+static struct pci_driver hpt3x3_pci_driver = {
+ .name = DRV_NAME,
+ .id_table = hpt3x3,
+ .probe = hpt3x3_init_one,
+ .remove = ata_pci_remove_one
+};
+
+static int __init hpt3x3_init(void)
+{
+ return pci_register_driver(&hpt3x3_pci_driver);
+}
+
+
+static void __exit hpt3x3_exit(void)
+{
+ pci_unregister_driver(&hpt3x3_pci_driver);
+}
+
+
+MODULE_AUTHOR("Alan Cox");
+MODULE_DESCRIPTION("low-level driver for the Highpoint HPT343/363");
+MODULE_LICENSE("GPL");
+MODULE_DEVICE_TABLE(pci, hpt3x3);
+MODULE_VERSION(DRV_VERSION);
+
+module_init(hpt3x3_init);
+module_exit(hpt3x3_exit);
diff --git a/drivers/ata/pata_isapnp.c b/drivers/ata/pata_isapnp.c
new file mode 100644
index 000000000000..73948c8b7270
--- /dev/null
+++ b/drivers/ata/pata_isapnp.c
@@ -0,0 +1,156 @@
+
+/*
+ * pata-isapnp.c - ISA PnP PATA controller driver.
+ * Copyright 2005/2006 Red Hat Inc , all rights reserved.
+ *
+ * Based in part on ide-pnp.c by Andrey Panin
+ */
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#define DRV_NAME "pata_isapnp"
+#define DRV_VERSION "0.1.5"
+
+static struct scsi_host_template isapnp_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,
+ .max_sectors = ATA_MAX_SECTORS,
+ .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,
+ .bios_param = ata_std_bios_param,
+};
+
+static struct ata_port_operations isapnp_port_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,
+
+ .freeze = ata_bmdma_freeze,
+ .thaw = ata_bmdma_thaw,
+ .error_handler = ata_bmdma_error_handler,
+ .post_internal_cmd = ata_bmdma_post_internal_cmd,
+
+ .qc_prep = ata_qc_prep,
+ .qc_issue = ata_qc_issue_prot,
+ .eng_timeout = ata_eng_timeout,
+ .data_xfer = ata_pio_data_xfer,
+
+ .irq_handler = ata_interrupt,
+ .irq_clear = ata_bmdma_irq_clear,
+
+ .port_start = ata_port_start,
+ .port_stop = ata_port_stop,
+ .host_stop = ata_host_stop
+};
+
+/**
+ * isapnp_init_one - attach an isapnp interface
+ * @idev: PnP device
+ * @dev_id: matching detect line
+ *
+ * Register an ISA bus IDE interface. Such interfaces are PIO 0 and
+ * non shared IRQ.
+ */
+
+static int isapnp_init_one(struct pnp_dev *idev, const struct pnp_device_id *dev_id)
+{
+ struct ata_probe_ent ae;
+
+ if (pnp_port_valid(idev, 0) == 0)
+ return -ENODEV;
+
+ /* FIXME: Should selected polled PIO here not fail */
+ if (pnp_irq_valid(idev, 0) == 0)
+ return -ENODEV;
+
+ memset(&ae, 0, sizeof(struct ata_probe_ent));
+ INIT_LIST_HEAD(&ae.node);
+ ae.dev = &idev->dev;
+ ae.port_ops = &isapnp_port_ops;
+ ae.sht = &isapnp_sht;
+ ae.n_ports = 1;
+ ae.pio_mask = 1; /* ISA so PIO 0 cycles */
+ ae.irq = pnp_irq(idev, 0);
+ ae.irq_flags = 0;
+ ae.port_flags = ATA_FLAG_SLAVE_POSS;
+ ae.port[0].cmd_addr = pnp_port_start(idev, 0);
+
+ if (pnp_port_valid(idev, 1) == 0) {
+ ae.port[0].altstatus_addr = pnp_port_start(idev, 1);
+ ae.port[0].ctl_addr = pnp_port_start(idev, 1);
+ ae.port_flags |= ATA_FLAG_SRST;
+ }
+ ata_std_ports(&ae.port[0]);
+
+ if (ata_device_add(&ae) == 0)
+ return -ENODEV;
+ return 0;
+}
+
+/**
+ * isapnp_remove_one - unplug an isapnp interface
+ * @idev: PnP device
+ *
+ * Remove a previously configured PnP ATA port. Called only on module
+ * unload events as the core does not currently deal with ISAPnP docking.
+ */
+
+static void isapnp_remove_one(struct pnp_dev *idev)
+{
+ struct device *dev = &idev->dev;
+ struct ata_host *host = dev_get_drvdata(dev);
+
+ ata_host_remove(host);
+ dev_set_drvdata(dev, NULL);
+}
+
+static struct pnp_device_id isapnp_devices[] = {
+ /* Generic ESDI/IDE/ATA compatible hard disk controller */
+ {.id = "PNP0600", .driver_data = 0},
+ {.id = ""}
+};
+
+static struct pnp_driver isapnp_driver = {
+ .name = DRV_NAME,
+ .id_table = isapnp_devices,
+ .probe = isapnp_init_one,
+ .remove = isapnp_remove_one,
+};
+
+static int __init isapnp_init(void)
+{
+ return pnp_register_driver(&isapnp_driver);
+}
+
+static void __exit isapnp_exit(void)
+{
+ pnp_unregister_driver(&isapnp_driver);
+}
+
+MODULE_AUTHOR("Alan Cox");
+MODULE_DESCRIPTION("low-level driver for ISA PnP ATA");
+MODULE_LICENSE("GPL");
+MODULE_VERSION(DRV_VERSION);
+
+module_init(isapnp_init);
+module_exit(isapnp_exit);
diff --git a/drivers/ata/pata_it821x.c b/drivers/ata/pata_it821x.c
new file mode 100644
index 000000000000..af39097d8081
--- /dev/null
+++ b/drivers/ata/pata_it821x.c
@@ -0,0 +1,847 @@
+/*
+ * ata-it821x.c - IT821x PATA for new ATA layer
+ * (C) 2005 Red Hat Inc
+ * Alan Cox
+ *
+ * based upon
+ *
+ * it821x.c
+ *
+ * linux/drivers/ide/pci/it821x.c Version 0.09 December 2004
+ *
+ * Copyright (C) 2004 Red Hat
+ *
+ * May be copied or modified under the terms of the GNU General Public License
+ * Based in part on the ITE vendor provided SCSI driver.
+ *
+ * Documentation available from
+ * http://www.ite.com.tw/pc/IT8212F_V04.pdf
+ * Some other documents are NDA.
+ *
+ * The ITE8212 isn't exactly a standard IDE controller. It has two
+ * modes. In pass through mode then it is an IDE controller. In its smart
+ * mode its actually quite a capable hardware raid controller disguised
+ * as an IDE controller. Smart mode only understands DMA read/write and
+ * identify, none of the fancier commands apply. The IT8211 is identical
+ * in other respects but lacks the raid mode.
+ *
+ * Errata:
+ * o Rev 0x10 also requires master/slave hold the same DMA timings and
+ * cannot do ATAPI MWDMA.
+ * o The identify data for raid volumes lacks CHS info (technically ok)
+ * but also fails to set the LBA28 and other bits. We fix these in
+ * the IDE probe quirk code.
+ * o If you write LBA48 sized I/O's (ie > 256 sector) in smart mode
+ * raid then the controller firmware dies
+ * o Smart mode without RAID doesn't clear all the necessary identify
+ * bits to reduce the command set to the one used
+ *
+ * This has a few impacts on the driver
+ * - In pass through mode we do all the work you would expect
+ * - In smart mode the clocking set up is done by the controller generally
+ * but we must watch the other limits and filter.
+ * - There are a few extra vendor commands that actually talk to the
+ * controller but only work PIO with no IRQ.
+ *
+ * Vendor areas of the identify block in smart mode are used for the
+ * timing and policy set up. Each HDD in raid mode also has a serial
+ * block on the disk. The hardware extra commands are get/set chip status,
+ * rebuild, get rebuild status.
+ *
+ * In Linux the driver supports pass through mode as if the device was
+ * just another IDE controller. If the smart mode is running then
+ * volumes are managed by the controller firmware and each IDE "disk"
+ * is a raid volume. Even more cute - the controller can do automated
+ * hotplug and rebuild.
+ *
+ * The pass through controller itself is a little demented. It has a
+ * flaw that it has a single set of PIO/MWDMA timings per channel so
+ * non UDMA devices restrict each others performance. It also has a
+ * single clock source per channel so mixed UDMA100/133 performance
+ * isn't perfect and we have to pick a clock. Thankfully none of this
+ * matters in smart mode. ATAPI DMA is not currently supported.
+ *
+ * It seems the smart mode is a win for RAID1/RAID10 but otherwise not.
+ *
+ * TODO
+ * - ATAPI and other speed filtering
+ * - Command filter in smart mode
+ * - RAID configuration ioctls
+ */
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+
+#define DRV_NAME "pata_it821x"
+#define DRV_VERSION "0.3.2"
+
+struct it821x_dev
+{
+ unsigned int smart:1, /* Are we in smart raid mode */
+ timing10:1; /* Rev 0x10 */
+ u8 clock_mode; /* 0, ATA_50 or ATA_66 */
+ u8 want[2][2]; /* Mode/Pri log for master slave */
+ /* We need these for switching the clock when DMA goes on/off
+ The high byte is the 66Mhz timing */
+ u16 pio[2]; /* Cached PIO values */
+ u16 mwdma[2]; /* Cached MWDMA values */
+ u16 udma[2]; /* Cached UDMA values (per drive) */
+ u16 last_device; /* Master or slave loaded ? */
+};
+
+#define ATA_66 0
+#define ATA_50 1
+#define ATA_ANY 2
+
+#define UDMA_OFF 0
+#define MWDMA_OFF 0
+
+/*
+ * We allow users to force the card into non raid mode without
+ * flashing the alternative BIOS. This is also neccessary right now
+ * for embedded platforms that cannot run a PC BIOS but are using this
+ * device.
+ */
+
+static int it8212_noraid;
+
+/**
+ * it821x_pre_reset - probe
+ * @ap: ATA port
+ *
+ * Set the cable type
+ */
+
+static int it821x_pre_reset(struct ata_port *ap)
+{
+ ap->cbl = ATA_CBL_PATA80;
+ return ata_std_prereset(ap);
+}
+
+/**
+ * it821x_error_handler - probe/reset
+ * @ap: ATA port
+ *
+ * Set the cable type and trigger a probe
+ */
+
+static void it821x_error_handler(struct ata_port *ap)
+{
+ return ata_bmdma_drive_eh(ap, it821x_pre_reset, ata_std_softreset, NULL, ata_std_postreset);
+}
+
+/**
+ * it821x_program - program the PIO/MWDMA registers
+ * @ap: ATA port
+ * @adev: Device to program
+ * @timing: Timing value (66Mhz in top 8bits, 50 in the low 8)
+ *
+ * Program the PIO/MWDMA timing for this channel according to the
+ * current clock. These share the same register so are managed by
+ * the DMA start/stop sequence as with the old driver.
+ */
+
+static void it821x_program(struct ata_port *ap, struct ata_device *adev, u16 timing)
+{
+ struct pci_dev *pdev = to_pci_dev(ap->host->dev);
+ struct it821x_dev *itdev = ap->private_data;
+ int channel = ap->port_no;
+ u8 conf;
+
+ /* Program PIO/MWDMA timing bits */
+ if (itdev->clock_mode == ATA_66)
+ conf = timing >> 8;
+ else
+ conf = timing & 0xFF;
+ pci_write_config_byte(pdev, 0x54 + 4 * channel, conf);
+}
+
+
+/**
+ * it821x_program_udma - program the UDMA registers
+ * @ap: ATA port
+ * @adev: ATA device to update
+ * @timing: Timing bits. Top 8 are for 66Mhz bottom for 50Mhz
+ *
+ * Program the UDMA timing for this drive according to the
+ * current clock. Handles the dual clocks and also knows about
+ * the errata on the 0x10 revision. The UDMA errata is partly handled
+ * here and partly in start_dma.
+ */
+
+static void it821x_program_udma(struct ata_port *ap, struct ata_device *adev, u16 timing)
+{
+ struct it821x_dev *itdev = ap->private_data;
+ struct pci_dev *pdev = to_pci_dev(ap->host->dev);
+ int channel = ap->port_no;
+ int unit = adev->devno;
+ u8 conf;
+
+ /* Program UDMA timing bits */
+ if (itdev->clock_mode == ATA_66)
+ conf = timing >> 8;
+ else
+ conf = timing & 0xFF;
+ if (itdev->timing10 == 0)
+ pci_write_config_byte(pdev, 0x56 + 4 * channel + unit, conf);
+ else {
+ /* Early revision must be programmed for both together */
+ pci_write_config_byte(pdev, 0x56 + 4 * channel, conf);
+ pci_write_config_byte(pdev, 0x56 + 4 * channel + 1, conf);
+ }
+}
+
+/**
+ * it821x_clock_strategy
+ * @ap: ATA interface
+ * @adev: ATA device being updated
+ *
+ * Select between the 50 and 66Mhz base clocks to get the best
+ * results for this interface.
+ */
+
+static void it821x_clock_strategy(struct ata_port *ap, struct ata_device *adev)
+{
+ struct pci_dev *pdev = to_pci_dev(ap->host->dev);
+ struct it821x_dev *itdev = ap->private_data;
+ u8 unit = adev->devno;
+ struct ata_device *pair = ata_dev_pair(adev);
+
+ int clock, altclock;
+ u8 v;
+ int sel = 0;
+
+ /* Look for the most wanted clocking */
+ if (itdev->want[0][0] > itdev->want[1][0]) {
+ clock = itdev->want[0][1];
+ altclock = itdev->want[1][1];
+ } else {
+ clock = itdev->want[1][1];
+ altclock = itdev->want[0][1];
+ }
+
+ /* Master doesn't care does the slave ? */
+ if (clock == ATA_ANY)
+ clock = altclock;
+
+ /* Nobody cares - keep the same clock */
+ if (clock == ATA_ANY)
+ return;
+ /* No change */
+ if (clock == itdev->clock_mode)
+ return;
+
+ /* Load this into the controller */
+ if (clock == ATA_66)
+ itdev->clock_mode = ATA_66;
+ else {
+ itdev->clock_mode = ATA_50;
+ sel = 1;
+ }
+ pci_read_config_byte(pdev, 0x50, &v);
+ v &= ~(1 << (1 + ap->port_no));
+ v |= sel << (1 + ap->port_no);
+ pci_write_config_byte(pdev, 0x50, v);
+
+ /*
+ * Reprogram the UDMA/PIO of the pair drive for the switch
+ * MWDMA will be dealt with by the dma switcher
+ */
+ if (pair && itdev->udma[1-unit] != UDMA_OFF) {
+ it821x_program_udma(ap, pair, itdev->udma[1-unit]);
+ it821x_program(ap, pair, itdev->pio[1-unit]);
+ }
+ /*
+ * Reprogram the UDMA/PIO of our drive for the switch.
+ * MWDMA will be dealt with by the dma switcher
+ */
+ if (itdev->udma[unit] != UDMA_OFF) {
+ it821x_program_udma(ap, adev, itdev->udma[unit]);
+ it821x_program(ap, adev, itdev->pio[unit]);
+ }
+}
+
+/**
+ * it821x_passthru_set_piomode - set PIO mode data
+ * @ap: ATA interface
+ * @adev: ATA device
+ *
+ * Configure for PIO mode. This is complicated as the register is
+ * shared by PIO and MWDMA and for both channels.
+ */
+
+static void it821x_passthru_set_piomode(struct ata_port *ap, struct ata_device *adev)
+{
+ /* Spec says 89 ref driver uses 88 */
+ static const u16 pio[] = { 0xAA88, 0xA382, 0xA181, 0x3332, 0x3121 };
+ static const u8 pio_want[] = { ATA_66, ATA_66, ATA_66, ATA_66, ATA_ANY };
+
+ struct it821x_dev *itdev = ap->private_data;
+ int unit = adev->devno;
+ int mode_wanted = adev->pio_mode - XFER_PIO_0;
+
+ /* We prefer 66Mhz clock for PIO 0-3, don't care for PIO4 */
+ itdev->want[unit][1] = pio_want[mode_wanted];
+ itdev->want[unit][0] = 1; /* PIO is lowest priority */
+ itdev->pio[unit] = pio[mode_wanted];
+ it821x_clock_strategy(ap, adev);
+ it821x_program(ap, adev, itdev->pio[unit]);
+}
+
+/**
+ * it821x_passthru_set_dmamode - set initial DMA mode data
+ * @ap: ATA interface
+ * @adev: ATA device
+ *
+ * Set up the DMA modes. The actions taken depend heavily on the mode
+ * to use. If UDMA is used as is hopefully the usual case then the
+ * timing register is private and we need only consider the clock. If
+ * we are using MWDMA then we have to manage the setting ourself as
+ * we switch devices and mode.
+ */
+
+static void it821x_passthru_set_dmamode(struct ata_port *ap, struct ata_device *adev)
+{
+ static const u16 dma[] = { 0x8866, 0x3222, 0x3121 };
+ static const u8 mwdma_want[] = { ATA_ANY, ATA_66, ATA_ANY };
+ static const u16 udma[] = { 0x4433, 0x4231, 0x3121, 0x2121, 0x1111, 0x2211, 0x1111 };
+ static const u8 udma_want[] = { ATA_ANY, ATA_50, ATA_ANY, ATA_66, ATA_66, ATA_50, ATA_66 };
+
+ struct pci_dev *pdev = to_pci_dev(ap->host->dev);
+ struct it821x_dev *itdev = ap->private_data;
+ int channel = ap->port_no;
+ int unit = adev->devno;
+ u8 conf;
+
+ if (adev->dma_mode >= XFER_UDMA_0) {
+ int mode_wanted = adev->dma_mode - XFER_UDMA_0;
+
+ itdev->want[unit][1] = udma_want[mode_wanted];
+ itdev->want[unit][0] = 3; /* UDMA is high priority */
+ itdev->mwdma[unit] = MWDMA_OFF;
+ itdev->udma[unit] = udma[mode_wanted];
+ if (mode_wanted >= 5)
+ itdev->udma[unit] |= 0x8080; /* UDMA 5/6 select on */
+
+ /* UDMA on. Again revision 0x10 must do the pair */
+ pci_read_config_byte(pdev, 0x50, &conf);
+ if (itdev->timing10)
+ conf &= channel ? 0x9F: 0xE7;
+ else
+ conf &= ~ (1 << (3 + 2 * channel + unit));
+ pci_write_config_byte(pdev, 0x50, conf);
+ it821x_clock_strategy(ap, adev);
+ it821x_program_udma(ap, adev, itdev->udma[unit]);
+ } else {
+ int mode_wanted = adev->dma_mode - XFER_MW_DMA_0;
+
+ itdev->want[unit][1] = mwdma_want[mode_wanted];
+ itdev->want[unit][0] = 2; /* MWDMA is low priority */
+ itdev->mwdma[unit] = dma[mode_wanted];
+ itdev->udma[unit] = UDMA_OFF;
+
+ /* UDMA bits off - Revision 0x10 do them in pairs */
+ pci_read_config_byte(pdev, 0x50, &conf);
+ if (itdev->timing10)
+ conf |= channel ? 0x60: 0x18;
+ else
+ conf |= 1 << (3 + 2 * channel + unit);
+ pci_write_config_byte(pdev, 0x50, conf);
+ it821x_clock_strategy(ap, adev);
+ }
+}
+
+/**
+ * it821x_passthru_dma_start - DMA start callback
+ * @qc: Command in progress
+ *
+ * Usually drivers set the DMA timing at the point the set_dmamode call
+ * is made. IT821x however requires we load new timings on the
+ * transitions in some cases.
+ */
+
+static void it821x_passthru_bmdma_start(struct ata_queued_cmd *qc)
+{
+ struct ata_port *ap = qc->ap;
+ struct ata_device *adev = qc->dev;
+ struct it821x_dev *itdev = ap->private_data;
+ int unit = adev->devno;
+
+ if (itdev->mwdma[unit] != MWDMA_OFF)
+ it821x_program(ap, adev, itdev->mwdma[unit]);
+ else if (itdev->udma[unit] != UDMA_OFF && itdev->timing10)
+ it821x_program_udma(ap, adev, itdev->udma[unit]);
+ ata_bmdma_start(qc);
+}
+
+/**
+ * it821x_passthru_dma_stop - DMA stop callback
+ * @qc: ATA command
+ *
+ * We loaded new timings in dma_start, as a result we need to restore
+ * the PIO timings in dma_stop so that the next command issue gets the
+ * right clock values.
+ */
+
+static void it821x_passthru_bmdma_stop(struct ata_queued_cmd *qc)
+{
+ struct ata_port *ap = qc->ap;
+ struct ata_device *adev = qc->dev;
+ struct it821x_dev *itdev = ap->private_data;
+ int unit = adev->devno;
+
+ ata_bmdma_stop(qc);
+ if (itdev->mwdma[unit] != MWDMA_OFF)
+ it821x_program(ap, adev, itdev->pio[unit]);
+}
+
+
+/**
+ * it821x_passthru_dev_select - Select master/slave
+ * @ap: ATA port
+ * @device: Device number (not pointer)
+ *
+ * Device selection hook. If neccessary perform clock switching
+ */
+
+static void it821x_passthru_dev_select(struct ata_port *ap,
+ unsigned int device)
+{
+ struct it821x_dev *itdev = ap->private_data;
+ if (itdev && device != itdev->last_device) {
+ struct ata_device *adev = &ap->device[device];
+ it821x_program(ap, adev, itdev->pio[adev->devno]);
+ itdev->last_device = device;
+ }
+ ata_std_dev_select(ap, device);
+}
+
+/**
+ * it821x_smart_qc_issue_prot - wrap qc issue prot
+ * @qc: command
+ *
+ * Wrap the command issue sequence for the IT821x. We need to
+ * perform out own device selection timing loads before the
+ * usual happenings kick off
+ */
+
+static unsigned int it821x_smart_qc_issue_prot(struct ata_queued_cmd *qc)
+{
+ switch(qc->tf.command)
+ {
+ /* Commands the firmware supports */
+ case ATA_CMD_READ:
+ case ATA_CMD_READ_EXT:
+ case ATA_CMD_WRITE:
+ case ATA_CMD_WRITE_EXT:
+ case ATA_CMD_PIO_READ:
+ case ATA_CMD_PIO_READ_EXT:
+ case ATA_CMD_PIO_WRITE:
+ case ATA_CMD_PIO_WRITE_EXT:
+ case ATA_CMD_READ_MULTI:
+ case ATA_CMD_READ_MULTI_EXT:
+ case ATA_CMD_WRITE_MULTI:
+ case ATA_CMD_WRITE_MULTI_EXT:
+ case ATA_CMD_ID_ATA:
+ /* Arguably should just no-op this one */
+ case ATA_CMD_SET_FEATURES:
+ return ata_qc_issue_prot(qc);
+ }
+ printk(KERN_DEBUG "it821x: can't process command 0x%02X\n", qc->tf.command);
+ return AC_ERR_INVALID;
+}
+
+/**
+ * it821x_passthru_qc_issue_prot - wrap qc issue prot
+ * @qc: command
+ *
+ * Wrap the command issue sequence for the IT821x. We need to
+ * perform out own device selection timing loads before the
+ * usual happenings kick off
+ */
+
+static unsigned int it821x_passthru_qc_issue_prot(struct ata_queued_cmd *qc)
+{
+ it821x_passthru_dev_select(qc->ap, qc->dev->devno);
+ return ata_qc_issue_prot(qc);
+}
+
+/**
+ * it821x_smart_set_mode - mode setting
+ * @ap: interface to set up
+ *
+ * Use a non standard set_mode function. We don't want to be tuned.
+ * The BIOS configured everything. Our job is not to fiddle. We
+ * read the dma enabled bits from the PCI configuration of the device
+ * and respect them.
+ */
+
+static void it821x_smart_set_mode(struct ata_port *ap)
+{
+ int dma_enabled = 0;
+ int i;
+
+ /* Bits 5 and 6 indicate if DMA is active on master/slave */
+ /* It is possible that BMDMA isn't allocated */
+ if (ap->ioaddr.bmdma_addr)
+ dma_enabled = inb(ap->ioaddr.bmdma_addr + ATA_DMA_CMD);
+
+ for (i = 0; i < ATA_MAX_DEVICES; i++) {
+ struct ata_device *dev = &ap->device[i];
+ if (ata_dev_enabled(dev)) {
+ /* We don't really care */
+ dev->pio_mode = XFER_PIO_0;
+ dev->dma_mode = XFER_MW_DMA_0;
+ /* We do need the right mode information for DMA or PIO
+ and this comes from the current configuration flags */
+ if (dma_enabled & (1 << (5 + i))) {
+ dev->xfer_mode = XFER_MW_DMA_0;
+ dev->xfer_shift = ATA_SHIFT_MWDMA;
+ dev->flags &= ~ATA_DFLAG_PIO;
+ } else {
+ dev->xfer_mode = XFER_PIO_0;
+ dev->xfer_shift = ATA_SHIFT_PIO;
+ dev->flags |= ATA_DFLAG_PIO;
+ }
+ }
+ }
+}
+
+/**
+ * it821x_dev_config - Called each device identify
+ * @ap: ATA port
+ * @adev: Device that has just been identified
+ *
+ * Perform the initial setup needed for each device that is chip
+ * special. In our case we need to lock the sector count to avoid
+ * blowing the brains out of the firmware with large LBA48 requests
+ *
+ * FIXME: When FUA appears we need to block FUA too. And SMART and
+ * basically we need to filter commands for this chip.
+ */
+
+static void it821x_dev_config(struct ata_port *ap, struct ata_device *adev)
+{
+ unsigned char model_num[40];
+ char *s;
+ unsigned int len;
+
+ /* This block ought to be a library routine as it is in several
+ drivers now */
+
+ ata_id_string(adev->id, model_num, ATA_ID_PROD_OFS,
+ sizeof(model_num));
+ s = &model_num[0];
+ len = strnlen(s, sizeof(model_num));
+
+ /* ATAPI specifies that empty space is blank-filled; remove blanks */
+ while ((len > 0) && (s[len - 1] == ' ')) {
+ len--;
+ s[len] = 0;
+ }
+
+ if (adev->max_sectors > 255)
+ adev->max_sectors = 255;
+
+ if (strstr(model_num, "Integrated Technology Express")) {
+ /* RAID mode */
+ printk(KERN_INFO "IT821x %sRAID%d volume",
+ adev->id[147]?"Bootable ":"",
+ adev->id[129]);
+ if (adev->id[129] != 1)
+ printk("(%dK stripe)", adev->id[146]);
+ printk(".\n");
+ }
+}
+
+
+/**
+ * it821x_check_atapi_dma - ATAPI DMA handler
+ * @qc: Command we are about to issue
+ *
+ * Decide if this ATAPI command can be issued by DMA on this
+ * controller. Return 0 if it can be.
+ */
+
+static int it821x_check_atapi_dma(struct ata_queued_cmd *qc)
+{
+ struct ata_port *ap = qc->ap;
+ struct it821x_dev *itdev = ap->private_data;
+
+ /* No ATAPI DMA in smart mode */
+ if (itdev->smart)
+ return -EOPNOTSUPP;
+ /* No ATAPI DMA on rev 10 */
+ if (itdev->timing10)
+ return -EOPNOTSUPP;
+ /* Cool */
+ return 0;
+}
+
+
+/**
+ * it821x_port_start - port setup
+ * @ap: ATA port being set up
+ *
+ * The it821x needs to maintain private data structures and also to
+ * use the standard PCI interface which lacks support for this
+ * functionality. We instead set up the private data on the port
+ * start hook, and tear it down on port stop
+ */
+
+static int it821x_port_start(struct ata_port *ap)
+{
+ struct pci_dev *pdev = to_pci_dev(ap->host->dev);
+ struct it821x_dev *itdev;
+ u8 conf;
+
+ int ret = ata_port_start(ap);
+ if (ret < 0)
+ return ret;
+
+ ap->private_data = kmalloc(sizeof(struct it821x_dev), GFP_KERNEL);
+ if (ap->private_data == NULL) {
+ ata_port_stop(ap);
+ return -ENOMEM;
+ }
+
+ itdev = ap->private_data;
+ memset(itdev, 0, sizeof(struct it821x_dev));
+
+ pci_read_config_byte(pdev, 0x50, &conf);
+
+ if (conf & 1) {
+ itdev->smart = 1;
+ /* Long I/O's although allowed in LBA48 space cause the
+ onboard firmware to enter the twighlight zone */
+ /* No ATAPI DMA in this mode either */
+ }
+ /* Pull the current clocks from 0x50 */
+ if (conf & (1 << (1 + ap->port_no)))
+ itdev->clock_mode = ATA_50;
+ else
+ itdev->clock_mode = ATA_66;
+
+ itdev->want[0][1] = ATA_ANY;
+ itdev->want[1][1] = ATA_ANY;
+ itdev->last_device = -1;
+
+ pci_read_config_byte(pdev, PCI_REVISION_ID, &conf);
+ if (conf == 0x10) {
+ itdev->timing10 = 1;
+ /* Need to disable ATAPI DMA for this case */
+ if (!itdev->smart)
+ printk(KERN_WARNING DRV_NAME": Revision 0x10, workarounds activated.\n");
+ }
+
+ return 0;
+}
+
+/**
+ * it821x_port_stop - port shutdown
+ * @ap: ATA port being removed
+ *
+ * Release the private objects we added in it821x_port_start
+ */
+
+static void it821x_port_stop(struct ata_port *ap) {
+ kfree(ap->private_data);
+ ap->private_data = NULL; /* We want an OOPS if we reuse this
+ too late! */
+ ata_port_stop(ap);
+}
+
+static struct scsi_host_template it821x_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,
+ /* 255 sectors to begin with. This is locked in smart mode but not
+ in pass through */
+ .max_sectors = 255,
+ .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,
+ .bios_param = ata_std_bios_param,
+};
+
+static struct ata_port_operations it821x_smart_port_ops = {
+ .set_mode = it821x_smart_set_mode,
+ .port_disable = ata_port_disable,
+ .tf_load = ata_tf_load,
+ .tf_read = ata_tf_read,
+ .mode_filter = ata_pci_default_filter,
+
+ .check_status = ata_check_status,
+ .check_atapi_dma= it821x_check_atapi_dma,
+ .exec_command = ata_exec_command,
+ .dev_select = ata_std_dev_select,
+ .dev_config = it821x_dev_config,
+
+ .freeze = ata_bmdma_freeze,
+ .thaw = ata_bmdma_thaw,
+ .error_handler = it821x_error_handler,
+ .post_internal_cmd = ata_bmdma_post_internal_cmd,
+
+ .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 = it821x_smart_qc_issue_prot,
+ .eng_timeout = ata_eng_timeout,
+ .data_xfer = ata_pio_data_xfer,
+
+ .irq_handler = ata_interrupt,
+ .irq_clear = ata_bmdma_irq_clear,
+
+ .port_start = it821x_port_start,
+ .port_stop = it821x_port_stop,
+ .host_stop = ata_host_stop
+};
+
+static struct ata_port_operations it821x_passthru_port_ops = {
+ .port_disable = ata_port_disable,
+ .set_piomode = it821x_passthru_set_piomode,
+ .set_dmamode = it821x_passthru_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,
+ .check_atapi_dma= it821x_check_atapi_dma,
+ .dev_select = it821x_passthru_dev_select,
+
+ .freeze = ata_bmdma_freeze,
+ .thaw = ata_bmdma_thaw,
+ .error_handler = it821x_error_handler,
+ .post_internal_cmd = ata_bmdma_post_internal_cmd,
+
+ .bmdma_setup = ata_bmdma_setup,
+ .bmdma_start = it821x_passthru_bmdma_start,
+ .bmdma_stop = it821x_passthru_bmdma_stop,
+ .bmdma_status = ata_bmdma_status,
+
+ .qc_prep = ata_qc_prep,
+ .qc_issue = it821x_passthru_qc_issue_prot,
+ .eng_timeout = ata_eng_timeout,
+ .data_xfer = ata_pio_data_xfer,
+
+ .irq_clear = ata_bmdma_irq_clear,
+ .irq_handler = ata_interrupt,
+
+ .port_start = it821x_port_start,
+ .port_stop = it821x_port_stop,
+ .host_stop = ata_host_stop
+};
+
+static void __devinit it821x_disable_raid(struct pci_dev *pdev)
+{
+ /* Reset local CPU, and set BIOS not ready */
+ pci_write_config_byte(pdev, 0x5E, 0x01);
+
+ /* Set to bypass mode, and reset PCI bus */
+ pci_write_config_byte(pdev, 0x50, 0x00);
+ pci_write_config_word(pdev, PCI_COMMAND,
+ PCI_COMMAND_PARITY | PCI_COMMAND_IO |
+ PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER);
+ pci_write_config_word(pdev, 0x40, 0xA0F3);
+
+ pci_write_config_dword(pdev,0x4C, 0x02040204);
+ pci_write_config_byte(pdev, 0x42, 0x36);
+ pci_write_config_byte(pdev, PCI_LATENCY_TIMER, 0x20);
+}
+
+
+static int it821x_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
+{
+ u8 conf;
+
+ static struct ata_port_info info_smart = {
+ .sht = &it821x_sht,
+ .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST,
+ .pio_mask = 0x1f,
+ .mwdma_mask = 0x07,
+ .port_ops = &it821x_smart_port_ops
+ };
+ static struct ata_port_info info_passthru = {
+ .sht = &it821x_sht,
+ .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST,
+ .pio_mask = 0x1f,
+ .mwdma_mask = 0x07,
+ .udma_mask = 0x7f,
+ .port_ops = &it821x_passthru_port_ops
+ };
+ static struct ata_port_info *port_info[2];
+
+ static char *mode[2] = { "pass through", "smart" };
+
+ /* Force the card into bypass mode if so requested */
+ if (it8212_noraid) {
+ printk(KERN_INFO DRV_NAME ": forcing bypass mode.\n");
+ it821x_disable_raid(pdev);
+ }
+ pci_read_config_byte(pdev, 0x50, &conf);
+ conf &= 1;
+
+ printk(KERN_INFO DRV_NAME ": controller in %s mode.\n", mode[conf]);
+ if (conf == 0)
+ port_info[0] = port_info[1] = &info_passthru;
+ else
+ port_info[0] = port_info[1] = &info_smart;
+
+ return ata_pci_init_one(pdev, port_info, 2);
+}
+
+static struct pci_device_id it821x[] = {
+ { PCI_DEVICE(PCI_VENDOR_ID_ITE, PCI_DEVICE_ID_ITE_8211), },
+ { PCI_DEVICE(PCI_VENDOR_ID_ITE, PCI_DEVICE_ID_ITE_8212), },
+ { 0, },
+};
+
+static struct pci_driver it821x_pci_driver = {
+ .name = DRV_NAME,
+ .id_table = it821x,
+ .probe = it821x_init_one,
+ .remove = ata_pci_remove_one
+};
+
+static int __init it821x_init(void)
+{
+ return pci_register_driver(&it821x_pci_driver);
+}
+
+
+static void __exit it821x_exit(void)
+{
+ pci_unregister_driver(&it821x_pci_driver);
+}
+
+
+MODULE_AUTHOR("Alan Cox");
+MODULE_DESCRIPTION("low-level driver for the IT8211/IT8212 IDE RAID controller");
+MODULE_LICENSE("GPL");
+MODULE_DEVICE_TABLE(pci, it821x);
+MODULE_VERSION(DRV_VERSION);
+
+
+module_param_named(noraid, it8212_noraid, int, S_IRUGO);
+MODULE_PARM_DESC(it8212_noraid, "Force card into bypass mode");
+
+module_init(it821x_init);
+module_exit(it821x_exit);
diff --git a/drivers/ata/pata_jmicron.c b/drivers/ata/pata_jmicron.c
new file mode 100644
index 000000000000..6832a643a9eb
--- /dev/null
+++ b/drivers/ata/pata_jmicron.c
@@ -0,0 +1,266 @@
+/*
+ * pata_jmicron.c - JMicron ATA driver for non AHCI mode. This drives the
+ * PATA port of the controller. The SATA ports are
+ * driven by AHCI in the usual configuration although
+ * this driver can handle other setups if we need it.
+ *
+ * (c) 2006 Red Hat
+ */
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#define DRV_NAME "pata_jmicron"
+#define DRV_VERSION "0.1.2"
+
+typedef enum {
+ PORT_PATA0 = 0,
+ PORT_PATA1 = 1,
+ PORT_SATA = 2,
+} port_type;
+
+/**
+ * jmicron_pre_reset - check for 40/80 pin
+ * @ap: Port
+ *
+ * Perform the PATA port setup we need.
+
+ * On the Jmicron 361/363 there is a single PATA port that can be mapped
+ * either as primary or secondary (or neither). We don't do any policy
+ * and setup here. We assume that has been done by init_one and the
+ * BIOS.
+ */
+
+static int jmicron_pre_reset(struct ata_port *ap)
+{
+ struct pci_dev *pdev = to_pci_dev(ap->host->dev);
+ u32 control;
+ u32 control5;
+ int port_mask = 1<< (4 * ap->port_no);
+ int port = ap->port_no;
+ port_type port_map[2];
+
+ /* Check if our port is enabled */
+ pci_read_config_dword(pdev, 0x40, &control);
+ if ((control & port_mask) == 0)
+ return 0;
+
+ /* There are two basic mappings. One has the two SATA ports merged
+ as master/slave and the secondary as PATA, the other has only the
+ SATA port mapped */
+ if (control & (1 << 23)) {
+ port_map[0] = PORT_SATA;
+ port_map[1] = PORT_PATA0;
+ } else {
+ port_map[0] = PORT_SATA;
+ port_map[1] = PORT_SATA;
+ }
+
+ /* The 365/366 may have this bit set to map the second PATA port
+ as the internal primary channel */
+ pci_read_config_dword(pdev, 0x80, &control5);
+ if (control5 & (1<<24))
+ port_map[0] = PORT_PATA1;
+
+ /* The two ports may then be logically swapped by the firmware */
+ if (control & (1 << 22))
+ port = port ^ 1;
+
+ /*
+ * Now we know which physical port we are talking about we can
+ * actually do our cable checking etc. Thankfully we don't need
+ * to do the plumbing for other cases.
+ */
+ switch (port_map[port])
+ {
+ case PORT_PATA0:
+ if (control & (1 << 5))
+ return 0;
+ if (control & (1 << 3)) /* 40/80 pin primary */
+ ap->cbl = ATA_CBL_PATA40;
+ else
+ ap->cbl = ATA_CBL_PATA80;
+ break;
+ case PORT_PATA1:
+ /* Bit 21 is set if the port is enabled */
+ if ((control5 & (1 << 21)) == 0)
+ return 0;
+ if (control5 & (1 << 19)) /* 40/80 pin secondary */
+ ap->cbl = ATA_CBL_PATA40;
+ else
+ ap->cbl = ATA_CBL_PATA80;
+ break;
+ case PORT_SATA:
+ ap->cbl = ATA_CBL_SATA;
+ break;
+ }
+ return ata_std_prereset(ap);
+}
+
+/**
+ * jmicron_error_handler - Setup and error handler
+ * @ap: Port to handle
+ *
+ * LOCKING:
+ * None (inherited from caller).
+ */
+
+static void jmicron_error_handler(struct ata_port *ap)
+{
+ return ata_bmdma_drive_eh(ap, jmicron_pre_reset, ata_std_softreset, NULL, ata_std_postreset);
+}
+
+/* No PIO or DMA methods needed for this device */
+
+static struct scsi_host_template jmicron_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,
+ /* Special handling needed if you have sector or LBA48 limits */
+ .max_sectors = ATA_MAX_SECTORS,
+ .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,
+ /* Use standard CHS mapping rules */
+ .bios_param = ata_std_bios_param,
+};
+
+static const struct ata_port_operations jmicron_ops = {
+ .port_disable = ata_port_disable,
+
+ /* Task file is PCI ATA format, use helpers */
+ .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,
+
+ .freeze = ata_bmdma_freeze,
+ .thaw = ata_bmdma_thaw,
+ .error_handler = jmicron_error_handler,
+ .post_internal_cmd = ata_bmdma_post_internal_cmd,
+
+ /* BMDMA handling is PCI ATA format, use helpers */
+ .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,
+
+ /* Timeout handling. Special recovery hooks here */
+ .eng_timeout = ata_eng_timeout,
+ .irq_handler = ata_interrupt,
+ .irq_clear = ata_bmdma_irq_clear,
+
+ /* Generic PATA PCI ATA helpers */
+ .port_start = ata_port_start,
+ .port_stop = ata_port_stop,
+ .host_stop = ata_host_stop,
+};
+
+
+/**
+ * jmicron_init_one - Register Jmicron ATA PCI device with kernel services
+ * @pdev: PCI device to register
+ * @ent: Entry in jmicron_pci_tbl matching with @pdev
+ *
+ * Called from kernel PCI layer.
+ *
+ * LOCKING:
+ * Inherited from PCI layer (may sleep).
+ *
+ * RETURNS:
+ * Zero on success, or -ERRNO value.
+ */
+
+static int jmicron_init_one (struct pci_dev *pdev, const struct pci_device_id *id)
+{
+ static struct ata_port_info info = {
+ .sht = &jmicron_sht,
+ .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST,
+
+ .pio_mask = 0x1f,
+ .mwdma_mask = 0x07,
+ .udma_mask = 0x3f,
+
+ .port_ops = &jmicron_ops,
+ };
+ struct ata_port_info *port_info[2] = { &info, &info };
+
+ u32 reg;
+
+ if (id->driver_data != 368) {
+ /* Put the controller into AHCI mode in case the AHCI driver
+ has not yet been loaded. This can be done with either
+ function present */
+
+ /* FIXME: We may want a way to override this in future */
+ pci_write_config_byte(pdev, 0x41, 0xa1);
+ }
+
+ /* PATA controller is fn 1, AHCI is fn 0 */
+ if (PCI_FUNC(pdev->devfn) != 1)
+ return -ENODEV;
+
+ if ( id->driver_data == 365 || id->driver_data == 366) {
+ /* The 365/66 have two PATA channels, redirect the second */
+ pci_read_config_dword(pdev, 0x80, ®);
+ reg |= (1 << 24); /* IDE1 to PATA IDE secondary */
+ pci_write_config_dword(pdev, 0x80, reg);
+ }
+
+ return ata_pci_init_one(pdev, port_info, 2);
+}
+
+static const struct pci_device_id jmicron_pci_tbl[] = {
+ { PCI_DEVICE(PCI_VENDOR_ID_JMICRON, PCI_DEVICE_ID_JMICRON_JMB361), 361},
+ { PCI_DEVICE(PCI_VENDOR_ID_JMICRON, PCI_DEVICE_ID_JMICRON_JMB363), 363},
+ { PCI_DEVICE(PCI_VENDOR_ID_JMICRON, PCI_DEVICE_ID_JMICRON_JMB365), 365},
+ { PCI_DEVICE(PCI_VENDOR_ID_JMICRON, PCI_DEVICE_ID_JMICRON_JMB366), 366},
+ { PCI_DEVICE(PCI_VENDOR_ID_JMICRON, PCI_DEVICE_ID_JMICRON_JMB368), 368},
+ { } /* terminate list */
+};
+
+static struct pci_driver jmicron_pci_driver = {
+ .name = DRV_NAME,
+ .id_table = jmicron_pci_tbl,
+ .probe = jmicron_init_one,
+ .remove = ata_pci_remove_one,
+};
+
+static int __init jmicron_init(void)
+{
+ return pci_register_driver(&jmicron_pci_driver);
+}
+
+static void __exit jmicron_exit(void)
+{
+ pci_unregister_driver(&jmicron_pci_driver);
+}
+
+module_init(jmicron_init);
+module_exit(jmicron_exit);
+
+MODULE_AUTHOR("Alan Cox");
+MODULE_DESCRIPTION("SCSI low-level driver for Jmicron PATA ports");
+MODULE_LICENSE("GPL");
+MODULE_DEVICE_TABLE(pci, jmicron_pci_tbl);
+MODULE_VERSION(DRV_VERSION);
+
diff --git a/drivers/ata/pata_legacy.c b/drivers/ata/pata_legacy.c
new file mode 100644
index 000000000000..ad37c220bb2c
--- /dev/null
+++ b/drivers/ata/pata_legacy.c
@@ -0,0 +1,949 @@
+/*
+ * pata-legacy.c - Legacy port PATA/SATA controller driver.
+ * Copyright 2005/2006 Red Hat , all rights reserved.
+ *
+ * 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.
+ *
+ * An ATA driver for the legacy ATA ports.
+ *
+ * Data Sources:
+ * Opti 82C465/82C611 support: Data sheets at opti-inc.com
+ * HT6560 series:
+ * Promise 20230/20620:
+ * http://www.ryston.cz/petr/vlb/pdc20230b.html
+ * http://www.ryston.cz/petr/vlb/pdc20230c.html
+ * http://www.ryston.cz/petr/vlb/pdc20630.html
+ *
+ * Unsupported but docs exist:
+ * Appian/Adaptec AIC25VL01/Cirrus Logic PD7220
+ * Winbond W83759A
+ *
+ * This driver handles legacy (that is "ISA/VLB side") IDE ports found
+ * on PC class systems. There are three hybrid devices that are exceptions
+ * The Cyrix 5510/5520 where a pre SFF ATA device is on the bridge and
+ * the MPIIX where the tuning is PCI side but the IDE is "ISA side".
+ *
+ * Specific support is included for the ht6560a/ht6560b/opti82c611a/
+ * opti82c465mv/promise 20230c/20630
+ *
+ * Use the autospeed and pio_mask options with:
+ * Appian ADI/2 aka CLPD7220 or AIC25VL01.
+ * Use the jumpers, autospeed and set pio_mask to the mode on the jumpers with
+ * Goldstar GM82C711, PIC-1288A-125, UMC 82C871F, Winbond W83759,
+ * Winbond W83759A, Promise PDC20230-B
+ *
+ * For now use autospeed and pio_mask as above with the W83759A. This may
+ * change.
+ *
+ * TODO
+ * Merge existing pata_qdi driver
+ *
+ */
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#define DRV_NAME "pata_legacy"
+#define DRV_VERSION "0.5.3"
+
+#define NR_HOST 6
+
+static int legacy_port[NR_HOST] = { 0x1f0, 0x170, 0x1e8, 0x168, 0x1e0, 0x160 };
+static int legacy_irq[NR_HOST] = { 15, 14, 11, 10, 8, 12 };
+
+struct legacy_data {
+ unsigned long timing;
+ u8 clock[2];
+ u8 last;
+ int fast;
+ struct platform_device *platform_dev;
+
+};
+
+static struct legacy_data legacy_data[NR_HOST];
+static struct ata_host *legacy_host[NR_HOST];
+static int nr_legacy_host;
+
+
+static int probe_all; /* Set to check all ISA port ranges */
+static int ht6560a; /* HT 6560A on primary 1, secondary 2, both 3 */
+static int ht6560b; /* HT 6560A on primary 1, secondary 2, both 3 */
+static int opti82c611a; /* Opti82c611A on primary 1, secondary 2, both 3 */
+static int opti82c46x; /* Opti 82c465MV present (pri/sec autodetect) */
+static int autospeed; /* Chip present which snoops speed changes */
+static int pio_mask = 0x1F; /* PIO range for autospeed devices */
+
+/**
+ * legacy_set_mode - mode setting
+ * @ap: IDE interface
+ *
+ * Use a non standard set_mode function. We don't want to be tuned.
+ *
+ * The BIOS configured everything. Our job is not to fiddle. Just use
+ * whatever PIO the hardware is using and leave it at that. When we
+ * get some kind of nice user driven API for control then we can
+ * expand on this as per hdparm in the base kernel.
+ */
+
+static void legacy_set_mode(struct ata_port *ap)
+{
+ int i;
+
+ for (i = 0; i < ATA_MAX_DEVICES; i++) {
+ struct ata_device *dev = &ap->device[i];
+ if (ata_dev_enabled(dev)) {
+ dev->pio_mode = XFER_PIO_0;
+ dev->xfer_mode = XFER_PIO_0;
+ dev->xfer_shift = ATA_SHIFT_PIO;
+ dev->flags |= ATA_DFLAG_PIO;
+ }
+ }
+}
+
+static struct scsi_host_template legacy_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,
+ .max_sectors = ATA_MAX_SECTORS,
+ .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,
+ .bios_param = ata_std_bios_param,
+};
+
+/*
+ * These ops are used if the user indicates the hardware
+ * snoops the commands to decide on the mode and handles the
+ * mode selection "magically" itself. Several legacy controllers
+ * do this. The mode range can be set if it is not 0x1F by setting
+ * pio_mask as well.
+ */
+
+static struct ata_port_operations simple_port_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,
+
+ .freeze = ata_bmdma_freeze,
+ .thaw = ata_bmdma_thaw,
+ .error_handler = ata_bmdma_error_handler,
+ .post_internal_cmd = ata_bmdma_post_internal_cmd,
+
+ .qc_prep = ata_qc_prep,
+ .qc_issue = ata_qc_issue_prot,
+ .eng_timeout = ata_eng_timeout,
+ .data_xfer = ata_pio_data_xfer_noirq,
+
+ .irq_handler = ata_interrupt,
+ .irq_clear = ata_bmdma_irq_clear,
+
+ .port_start = ata_port_start,
+ .port_stop = ata_port_stop,
+ .host_stop = ata_host_stop
+};
+
+static struct ata_port_operations legacy_port_ops = {
+ .set_mode = legacy_set_mode,
+
+ .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,
+
+ .error_handler = ata_bmdma_error_handler,
+
+ .qc_prep = ata_qc_prep,
+ .qc_issue = ata_qc_issue_prot,
+ .eng_timeout = ata_eng_timeout,
+ .data_xfer = ata_pio_data_xfer_noirq,
+
+ .irq_handler = ata_interrupt,
+ .irq_clear = ata_bmdma_irq_clear,
+
+ .port_start = ata_port_start,
+ .port_stop = ata_port_stop,
+ .host_stop = ata_host_stop
+};
+
+/*
+ * Promise 20230C and 20620 support
+ *
+ * This controller supports PIO0 to PIO2. We set PIO timings conservatively to
+ * allow for 50MHz Vesa Local Bus. The 20620 DMA support is weird being DMA to
+ * controller and PIO'd to the host and not supported.
+ */
+
+static void pdc20230_set_piomode(struct ata_port *ap, struct ata_device *adev)
+{
+ int tries = 5;
+ int pio = adev->pio_mode - XFER_PIO_0;
+ u8 rt;
+ unsigned long flags;
+
+ /* Safe as UP only. Force I/Os to occur together */
+
+ local_irq_save(flags);
+
+ /* Unlock the control interface */
+ do
+ {
+ inb(0x1F5);
+ outb(inb(0x1F2) | 0x80, 0x1F2);
+ inb(0x1F2);
+ inb(0x3F6);
+ inb(0x3F6);
+ inb(0x1F2);
+ inb(0x1F2);
+ }
+ while((inb(0x1F2) & 0x80) && --tries);
+
+ local_irq_restore(flags);
+
+ outb(inb(0x1F4) & 0x07, 0x1F4);
+
+ rt = inb(0x1F3);
+ rt &= 0x07 << (3 * adev->devno);
+ if (pio)
+ rt |= (1 + 3 * pio) << (3 * adev->devno);
+
+ udelay(100);
+ outb(inb(0x1F2) | 0x01, 0x1F2);
+ udelay(100);
+ inb(0x1F5);
+
+}
+
+static void pdc_data_xfer_vlb(struct ata_device *adev, unsigned char *buf, unsigned int buflen, int write_data)
+{
+ struct ata_port *ap = adev->ap;
+ int slop = buflen & 3;
+ unsigned long flags;
+
+ if (ata_id_has_dword_io(adev->id)) {
+ local_irq_save(flags);
+
+ /* Perform the 32bit I/O synchronization sequence */
+ inb(ap->ioaddr.nsect_addr);
+ inb(ap->ioaddr.nsect_addr);
+ inb(ap->ioaddr.nsect_addr);
+
+ /* Now the data */
+
+ if (write_data)
+ outsl(ap->ioaddr.data_addr, buf, buflen >> 2);
+ else
+ insl(ap->ioaddr.data_addr, buf, buflen >> 2);
+
+ if (unlikely(slop)) {
+ u32 pad;
+ if (write_data) {
+ memcpy(&pad, buf + buflen - slop, slop);
+ outl(le32_to_cpu(pad), ap->ioaddr.data_addr);
+ } else {
+ pad = cpu_to_le16(inl(ap->ioaddr.data_addr));
+ memcpy(buf + buflen - slop, &pad, slop);
+ }
+ }
+ local_irq_restore(flags);
+ }
+ else
+ ata_pio_data_xfer_noirq(adev, buf, buflen, write_data);
+}
+
+static struct ata_port_operations pdc20230_port_ops = {
+ .set_piomode = pdc20230_set_piomode,
+
+ .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,
+
+ .error_handler = ata_bmdma_error_handler,
+
+ .qc_prep = ata_qc_prep,
+ .qc_issue = ata_qc_issue_prot,
+ .eng_timeout = ata_eng_timeout,
+ .data_xfer = pdc_data_xfer_vlb,
+
+ .irq_handler = ata_interrupt,
+ .irq_clear = ata_bmdma_irq_clear,
+
+ .port_start = ata_port_start,
+ .port_stop = ata_port_stop,
+ .host_stop = ata_host_stop
+};
+
+/*
+ * Holtek 6560A support
+ *
+ * This controller supports PIO0 to PIO2 (no IORDY even though higher timings
+ * can be loaded).
+ */
+
+static void ht6560a_set_piomode(struct ata_port *ap, struct ata_device *adev)
+{
+ u8 active, recover;
+ struct ata_timing t;
+
+ /* Get the timing data in cycles. For now play safe at 50Mhz */
+ ata_timing_compute(adev, adev->pio_mode, &t, 20000, 1000);
+
+ active = FIT(t.active, 2, 15);
+ recover = FIT(t.recover, 4, 15);
+
+ inb(0x3E6);
+ inb(0x3E6);
+ inb(0x3E6);
+ inb(0x3E6);
+
+ outb(recover << 4 | active, ap->ioaddr.device_addr);
+ inb(ap->ioaddr.status_addr);
+}
+
+static struct ata_port_operations ht6560a_port_ops = {
+ .set_piomode = ht6560a_set_piomode,
+
+ .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,
+
+ .error_handler = ata_bmdma_error_handler,
+
+ .qc_prep = ata_qc_prep,
+ .qc_issue = ata_qc_issue_prot,
+ .eng_timeout = ata_eng_timeout,
+ .data_xfer = ata_pio_data_xfer, /* Check vlb/noirq */
+
+ .irq_handler = ata_interrupt,
+ .irq_clear = ata_bmdma_irq_clear,
+
+ .port_start = ata_port_start,
+ .port_stop = ata_port_stop,
+ .host_stop = ata_host_stop
+};
+
+/*
+ * Holtek 6560B support
+ *
+ * This controller supports PIO0 to PIO4. We honour the BIOS/jumper FIFO setting
+ * unless we see an ATAPI device in which case we force it off.
+ *
+ * FIXME: need to implement 2nd channel support.
+ */
+
+static void ht6560b_set_piomode(struct ata_port *ap, struct ata_device *adev)
+{
+ u8 active, recover;
+ struct ata_timing t;
+
+ /* Get the timing data in cycles. For now play safe at 50Mhz */
+ ata_timing_compute(adev, adev->pio_mode, &t, 20000, 1000);
+
+ active = FIT(t.active, 2, 15);
+ recover = FIT(t.recover, 2, 16);
+ recover &= 0x15;
+
+ inb(0x3E6);
+ inb(0x3E6);
+ inb(0x3E6);
+ inb(0x3E6);
+
+ outb(recover << 4 | active, ap->ioaddr.device_addr);
+
+ if (adev->class != ATA_DEV_ATA) {
+ u8 rconf = inb(0x3E6);
+ if (rconf & 0x24) {
+ rconf &= ~ 0x24;
+ outb(rconf, 0x3E6);
+ }
+ }
+ inb(ap->ioaddr.status_addr);
+}
+
+static struct ata_port_operations ht6560b_port_ops = {
+ .set_piomode = ht6560b_set_piomode,
+
+ .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,
+
+ .error_handler = ata_bmdma_error_handler,
+
+ .qc_prep = ata_qc_prep,
+ .qc_issue = ata_qc_issue_prot,
+ .eng_timeout = ata_eng_timeout,
+ .data_xfer = ata_pio_data_xfer, /* FIXME: Check 32bit and noirq */
+
+ .irq_handler = ata_interrupt,
+ .irq_clear = ata_bmdma_irq_clear,
+
+ .port_start = ata_port_start,
+ .port_stop = ata_port_stop,
+ .host_stop = ata_host_stop
+};
+
+/*
+ * Opti core chipset helpers
+ */
+
+/**
+ * opti_syscfg - read OPTI chipset configuration
+ * @reg: Configuration register to read
+ *
+ * Returns the value of an OPTI system board configuration register.
+ */
+
+static u8 opti_syscfg(u8 reg)
+{
+ unsigned long flags;
+ u8 r;
+
+ /* Uniprocessor chipset and must force cycles adjancent */
+ local_irq_save(flags);
+ outb(reg, 0x22);
+ r = inb(0x24);
+ local_irq_restore(flags);
+ return r;
+}
+
+/*
+ * Opti 82C611A
+ *
+ * This controller supports PIO0 to PIO3.
+ */
+
+static void opti82c611a_set_piomode(struct ata_port *ap, struct ata_device *adev)
+{
+ u8 active, recover, setup;
+ struct ata_timing t;
+ struct ata_device *pair = ata_dev_pair(adev);
+ int clock;
+ int khz[4] = { 50000, 40000, 33000, 25000 };
+ u8 rc;
+
+ /* Enter configuration mode */
+ inw(ap->ioaddr.error_addr);
+ inw(ap->ioaddr.error_addr);
+ outb(3, ap->ioaddr.nsect_addr);
+
+ /* Read VLB clock strapping */
+ clock = 1000000000 / khz[inb(ap->ioaddr.lbah_addr) & 0x03];
+
+ /* Get the timing data in cycles */
+ ata_timing_compute(adev, adev->pio_mode, &t, clock, 1000);
+
+ /* Setup timing is shared */
+ if (pair) {
+ struct ata_timing tp;
+ ata_timing_compute(pair, pair->pio_mode, &tp, clock, 1000);
+
+ ata_timing_merge(&t, &tp, &t, ATA_TIMING_SETUP);
+ }
+
+ active = FIT(t.active, 2, 17) - 2;
+ recover = FIT(t.recover, 1, 16) - 1;
+ setup = FIT(t.setup, 1, 4) - 1;
+
+ /* Select the right timing bank for write timing */
+ rc = inb(ap->ioaddr.lbal_addr);
+ rc &= 0x7F;
+ rc |= (adev->devno << 7);
+ outb(rc, ap->ioaddr.lbal_addr);
+
+ /* Write the timings */
+ outb(active << 4 | recover, ap->ioaddr.error_addr);
+
+ /* Select the right bank for read timings, also
+ load the shared timings for address */
+ rc = inb(ap->ioaddr.device_addr);
+ rc &= 0xC0;
+ rc |= adev->devno; /* Index select */
+ rc |= (setup << 4) | 0x04;
+ outb(rc, ap->ioaddr.device_addr);
+
+ /* Load the read timings */
+ outb(active << 4 | recover, ap->ioaddr.data_addr);
+
+ /* Ensure the timing register mode is right */
+ rc = inb (ap->ioaddr.lbal_addr);
+ rc &= 0x73;
+ rc |= 0x84;
+ outb(rc, ap->ioaddr.lbal_addr);
+
+ /* Exit command mode */
+ outb(0x83, ap->ioaddr.nsect_addr);
+}
+
+
+static struct ata_port_operations opti82c611a_port_ops = {
+ .set_piomode = opti82c611a_set_piomode,
+
+ .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,
+
+ .error_handler = ata_bmdma_error_handler,
+
+ .qc_prep = ata_qc_prep,
+ .qc_issue = ata_qc_issue_prot,
+ .eng_timeout = ata_eng_timeout,
+ .data_xfer = ata_pio_data_xfer,
+
+ .irq_handler = ata_interrupt,
+ .irq_clear = ata_bmdma_irq_clear,
+
+ .port_start = ata_port_start,
+ .port_stop = ata_port_stop,
+ .host_stop = ata_host_stop
+};
+
+/*
+ * Opti 82C465MV
+ *
+ * This controller supports PIO0 to PIO3. Unlike the 611A the MVB
+ * version is dual channel but doesn't have a lot of unique registers.
+ */
+
+static void opti82c46x_set_piomode(struct ata_port *ap, struct ata_device *adev)
+{
+ u8 active, recover, setup;
+ struct ata_timing t;
+ struct ata_device *pair = ata_dev_pair(adev);
+ int clock;
+ int khz[4] = { 50000, 40000, 33000, 25000 };
+ u8 rc;
+ u8 sysclk;
+
+ /* Get the clock */
+ sysclk = opti_syscfg(0xAC) & 0xC0; /* BIOS set */
+
+ /* Enter configuration mode */
+ inw(ap->ioaddr.error_addr);
+ inw(ap->ioaddr.error_addr);
+ outb(3, ap->ioaddr.nsect_addr);
+
+ /* Read VLB clock strapping */
+ clock = 1000000000 / khz[sysclk];
+
+ /* Get the timing data in cycles */
+ ata_timing_compute(adev, adev->pio_mode, &t, clock, 1000);
+
+ /* Setup timing is shared */
+ if (pair) {
+ struct ata_timing tp;
+ ata_timing_compute(pair, pair->pio_mode, &tp, clock, 1000);
+
+ ata_timing_merge(&t, &tp, &t, ATA_TIMING_SETUP);
+ }
+
+ active = FIT(t.active, 2, 17) - 2;
+ recover = FIT(t.recover, 1, 16) - 1;
+ setup = FIT(t.setup, 1, 4) - 1;
+
+ /* Select the right timing bank for write timing */
+ rc = inb(ap->ioaddr.lbal_addr);
+ rc &= 0x7F;
+ rc |= (adev->devno << 7);
+ outb(rc, ap->ioaddr.lbal_addr);
+
+ /* Write the timings */
+ outb(active << 4 | recover, ap->ioaddr.error_addr);
+
+ /* Select the right bank for read timings, also
+ load the shared timings for address */
+ rc = inb(ap->ioaddr.device_addr);
+ rc &= 0xC0;
+ rc |= adev->devno; /* Index select */
+ rc |= (setup << 4) | 0x04;
+ outb(rc, ap->ioaddr.device_addr);
+
+ /* Load the read timings */
+ outb(active << 4 | recover, ap->ioaddr.data_addr);
+
+ /* Ensure the timing register mode is right */
+ rc = inb (ap->ioaddr.lbal_addr);
+ rc &= 0x73;
+ rc |= 0x84;
+ outb(rc, ap->ioaddr.lbal_addr);
+
+ /* Exit command mode */
+ outb(0x83, ap->ioaddr.nsect_addr);
+
+ /* We need to know this for quad device on the MVB */
+ ap->host->private_data = ap;
+}
+
+/**
+ * opt82c465mv_qc_issue_prot - command issue
+ * @qc: command pending
+ *
+ * Called when the libata layer is about to issue a command. We wrap
+ * this interface so that we can load the correct ATA timings. The
+ * MVB has a single set of timing registers and these are shared
+ * across channels. As there are two registers we really ought to
+ * track the last two used values as a sort of register window. For
+ * now we just reload on a channel switch. On the single channel
+ * setup this condition never fires so we do nothing extra.
+ *
+ * FIXME: dual channel needs ->serialize support
+ */
+
+static unsigned int opti82c46x_qc_issue_prot(struct ata_queued_cmd *qc)
+{
+ struct ata_port *ap = qc->ap;
+ struct ata_device *adev = qc->dev;
+
+ /* If timings are set and for the wrong channel (2nd test is
+ due to a libata shortcoming and will eventually go I hope) */
+ if (ap->host->private_data != ap->host
+ && ap->host->private_data != NULL)
+ opti82c46x_set_piomode(ap, adev);
+
+ return ata_qc_issue_prot(qc);
+}
+
+static struct ata_port_operations opti82c46x_port_ops = {
+ .set_piomode = opti82c46x_set_piomode,
+
+ .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,
+
+ .error_handler = ata_bmdma_error_handler,
+
+ .qc_prep = ata_qc_prep,
+ .qc_issue = opti82c46x_qc_issue_prot,
+ .eng_timeout = ata_eng_timeout,
+ .data_xfer = ata_pio_data_xfer,
+
+ .irq_handler = ata_interrupt,
+ .irq_clear = ata_bmdma_irq_clear,
+
+ .port_start = ata_port_start,
+ .port_stop = ata_port_stop,
+ .host_stop = ata_host_stop
+};
+
+
+/**
+ * legacy_init_one - attach a legacy interface
+ * @port: port number
+ * @io: I/O port start
+ * @ctrl: control port
+ * @irq: interrupt line
+ *
+ * Register an ISA bus IDE interface. Such interfaces are PIO and we
+ * assume do not support IRQ sharing.
+ */
+
+static __init int legacy_init_one(int port, unsigned long io, unsigned long ctrl, int irq)
+{
+ struct legacy_data *ld = &legacy_data[nr_legacy_host];
+ struct ata_probe_ent ae;
+ struct platform_device *pdev;
+ int ret = -EBUSY;
+ struct ata_port_operations *ops = &legacy_port_ops;
+ int pio_modes = pio_mask;
+ u32 mask = (1 << port);
+
+ if (request_region(io, 8, "pata_legacy") == NULL)
+ return -EBUSY;
+ if (request_region(ctrl, 1, "pata_legacy") == NULL)
+ goto fail_io;
+
+ pdev = platform_device_register_simple(DRV_NAME, nr_legacy_host, NULL, 0);
+ if (pdev == NULL)
+ goto fail_dev;
+
+ if (ht6560a & mask) {
+ ops = &ht6560a_port_ops;
+ pio_modes = 0x07;
+ }
+ if (ht6560b & mask) {
+ ops = &ht6560b_port_ops;
+ pio_modes = 0x1F;
+ }
+ if (opti82c611a & mask) {
+ ops = &opti82c611a_port_ops;
+ pio_modes = 0x0F;
+ }
+ if (opti82c46x & mask) {
+ ops = &opti82c46x_port_ops;
+ pio_modes = 0x0F;
+ }
+
+ /* Probe for automatically detectable controllers */
+
+ if (io == 0x1F0 && ops == &legacy_port_ops) {
+ unsigned long flags;
+
+ local_irq_save(flags);
+
+ /* Probes */
+ inb(0x1F5);
+ outb(inb(0x1F2) | 0x80, 0x1F2);
+ inb(0x1F2);
+ inb(0x3F6);
+ inb(0x3F6);
+ inb(0x1F2);
+ inb(0x1F2);
+
+ if ((inb(0x1F2) & 0x80) == 0) {
+ /* PDC20230c or 20630 ? */
+ printk(KERN_INFO "PDC20230-C/20630 VLB ATA controller detected.\n");
+ pio_modes = 0x07;
+ ops = &pdc20230_port_ops;
+ udelay(100);
+ inb(0x1F5);
+ } else {
+ outb(0x55, 0x1F2);
+ inb(0x1F2);
+ inb(0x1F2);
+ if (inb(0x1F2) == 0x00) {
+ printk(KERN_INFO "PDC20230-B VLB ATA controller detected.\n");
+ }
+ }
+ local_irq_restore(flags);
+ }
+
+
+ /* Chip does mode setting by command snooping */
+ if (ops == &legacy_port_ops && (autospeed & mask))
+ ops = &simple_port_ops;
+ memset(&ae, 0, sizeof(struct ata_probe_ent));
+ INIT_LIST_HEAD(&ae.node);
+ ae.dev = &pdev->dev;
+ ae.port_ops = ops;
+ ae.sht = &legacy_sht;
+ ae.n_ports = 1;
+ ae.pio_mask = pio_modes;
+ ae.irq = irq;
+ ae.irq_flags = 0;
+ ae.port_flags = ATA_FLAG_SLAVE_POSS|ATA_FLAG_SRST;
+ ae.port[0].cmd_addr = io;
+ ae.port[0].altstatus_addr = ctrl;
+ ae.port[0].ctl_addr = ctrl;
+ ata_std_ports(&ae.port[0]);
+ ae.private_data = ld;
+
+ ret = ata_device_add(&ae);
+ if (ret == 0) {
+ ret = -ENODEV;
+ goto fail;
+ }
+ legacy_host[nr_legacy_host++] = dev_get_drvdata(&pdev->dev);
+ ld->platform_dev = pdev;
+ return 0;
+
+fail:
+ platform_device_unregister(pdev);
+fail_dev:
+ release_region(ctrl, 1);
+fail_io:
+ release_region(io, 8);
+ return ret;
+}
+
+/**
+ * legacy_check_special_cases - ATA special cases
+ * @p: PCI device to check
+ * @master: set this if we find an ATA master
+ * @master: set this if we find an ATA secondary
+ *
+ * A small number of vendors implemented early PCI ATA interfaces on bridge logic
+ * without the ATA interface being PCI visible. Where we have a matching PCI driver
+ * we must skip the relevant device here. If we don't know about it then the legacy
+ * driver is the right driver anyway.
+ */
+
+static void legacy_check_special_cases(struct pci_dev *p, int *primary, int *secondary)
+{
+ /* Cyrix CS5510 pre SFF MWDMA ATA on the bridge */
+ if (p->vendor == 0x1078 && p->device == 0x0000) {
+ *primary = *secondary = 1;
+ return;
+ }
+ /* Cyrix CS5520 pre SFF MWDMA ATA on the bridge */
+ if (p->vendor == 0x1078 && p->device == 0x0002) {
+ *primary = *secondary = 1;
+ return;
+ }
+ /* Intel MPIIX - PIO ATA on non PCI side of bridge */
+ if (p->vendor == 0x8086 && p->device == 0x1234) {
+ u16 r;
+ pci_read_config_word(p, 0x6C, &r);
+ if (r & 0x8000) { /* ATA port enabled */
+ if (r & 0x4000)
+ *secondary = 1;
+ else
+ *primary = 1;
+ }
+ return;
+ }
+}
+
+
+/**
+ * legacy_init - attach legacy interfaces
+ *
+ * Attach legacy IDE interfaces by scanning the usual IRQ/port suspects.
+ * Right now we do not scan the ide0 and ide1 address but should do so
+ * for non PCI systems or systems with no PCI IDE legacy mode devices.
+ * If you fix that note there are special cases to consider like VLB
+ * drivers and CS5510/20.
+ */
+
+static __init int legacy_init(void)
+{
+ int i;
+ int ct = 0;
+ int primary = 0;
+ int secondary = 0;
+ int last_port = NR_HOST;
+
+ struct pci_dev *p = NULL;
+
+ for_each_pci_dev(p) {
+ int r;
+ /* Check for any overlap of the system ATA mappings. Native mode controllers
+ stuck on these addresses or some devices in 'raid' mode won't be found by
+ the storage class test */
+ for (r = 0; r < 6; r++) {
+ if (pci_resource_start(p, r) == 0x1f0)
+ primary = 1;
+ if (pci_resource_start(p, r) == 0x170)
+ secondary = 1;
+ }
+ /* Check for special cases */
+ legacy_check_special_cases(p, &primary, &secondary);
+
+ /* If PCI bus is present then don't probe for tertiary legacy ports */
+ if (probe_all == 0)
+ last_port = 2;
+ }
+
+ /* If an OPTI 82C46X is present find out where the channels are */
+ if (opti82c46x) {
+ static const char *optis[4] = {
+ "3/463MV", "5MV",
+ "5MVA", "5MVB"
+ };
+ u8 chans = 1;
+ u8 ctrl = (opti_syscfg(0x30) & 0xC0) >> 6;
+
+ opti82c46x = 3; /* Assume master and slave first */
+ printk(KERN_INFO DRV_NAME ": Opti 82C46%s chipset support.\n", optis[ctrl]);
+ if (ctrl == 3)
+ chans = (opti_syscfg(0x3F) & 0x20) ? 2 : 1;
+ ctrl = opti_syscfg(0xAC);
+ /* Check enabled and this port is the 465MV port. On the
+ MVB we may have two channels */
+ if (ctrl & 8) {
+ if (ctrl & 4)
+ opti82c46x = 2; /* Slave */
+ else
+ opti82c46x = 1; /* Master */
+ if (chans == 2)
+ opti82c46x = 3; /* Master and Slave */
+ } /* Slave only */
+ else if (chans == 1)
+ opti82c46x = 1;
+ }
+
+ for (i = 0; i < last_port; i++) {
+ /* Skip primary if we have seen a PCI one */
+ if (i == 0 && primary == 1)
+ continue;
+ /* Skip secondary if we have seen a PCI one */
+ if (i == 1 && secondary == 1)
+ continue;
+ if (legacy_init_one(i, legacy_port[i],
+ legacy_port[i] + 0x0206,
+ legacy_irq[i]) == 0)
+ ct++;
+ }
+ if (ct != 0)
+ return 0;
+ return -ENODEV;
+}
+
+static __exit void legacy_exit(void)
+{
+ int i;
+
+ for (i = 0; i < nr_legacy_host; i++) {
+ struct legacy_data *ld = &legacy_data[i];
+ struct ata_port *ap =legacy_host[i]->ports[0];
+ unsigned long io = ap->ioaddr.cmd_addr;
+ unsigned long ctrl = ap->ioaddr.ctl_addr;
+ ata_host_remove(legacy_host[i]);
+ platform_device_unregister(ld->platform_dev);
+ if (ld->timing)
+ release_region(ld->timing, 2);
+ release_region(io, 8);
+ release_region(ctrl, 1);
+ }
+}
+
+MODULE_AUTHOR("Alan Cox");
+MODULE_DESCRIPTION("low-level driver for legacy ATA");
+MODULE_LICENSE("GPL");
+MODULE_VERSION(DRV_VERSION);
+
+module_param(probe_all, int, 0);
+module_param(autospeed, int, 0);
+module_param(ht6560a, int, 0);
+module_param(ht6560b, int, 0);
+module_param(opti82c611a, int, 0);
+module_param(opti82c46x, int, 0);
+module_param(pio_mask, int, 0);
+
+module_init(legacy_init);
+module_exit(legacy_exit);
+
diff --git a/drivers/ata/pata_mpiix.c b/drivers/ata/pata_mpiix.c
new file mode 100644
index 000000000000..1958c4ed09a8
--- /dev/null
+++ b/drivers/ata/pata_mpiix.c
@@ -0,0 +1,313 @@
+/*
+ * pata_mpiix.c - Intel MPIIX PATA for new ATA layer
+ * (C) 2005-2006 Red Hat Inc
+ * Alan Cox
+ *
+ * The MPIIX is different enough to the PIIX4 and friends that we give it
+ * a separate driver. The old ide/pci code handles this by just not tuning
+ * MPIIX at all.
+ *
+ * The MPIIX also differs in another important way from the majority of PIIX
+ * devices. The chip is a bridge (pardon the pun) between the old world of
+ * ISA IDE and PCI IDE. Although the ATA timings are PCI configured the actual
+ * IDE controller is not decoded in PCI space and the chip does not claim to
+ * be IDE class PCI. This requires slightly non-standard probe logic compared
+ * with PCI IDE and also that we do not disable the device when our driver is
+ * unloaded (as it has many other functions).
+ *
+ * The driver conciously keeps this logic internally to avoid pushing quirky
+ * PATA history into the clean libata layer.
+ *
+ * Thinkpad specific note: If you boot an MPIIX using thinkpad with a PCMCIA
+ * hard disk present this driver will not detect it. This is not a bug. In this
+ * configuration the secondary port of the MPIIX is disabled and the addresses
+ * are decoded by the PCMCIA bridge and therefore are for a generic IDE driver
+ * to operate.
+ */
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#define DRV_NAME "pata_mpiix"
+#define DRV_VERSION "0.7.1"
+
+enum {
+ IDETIM = 0x6C, /* IDE control register */
+ IORDY = (1 << 1),
+ PPE = (1 << 2),
+ FTIM = (1 << 0),
+ ENABLED = (1 << 15),
+ SECONDARY = (1 << 14)
+};
+
+static int mpiix_pre_reset(struct ata_port *ap)
+{
+ struct pci_dev *pdev = to_pci_dev(ap->host->dev);
+ static const struct pci_bits mpiix_enable_bits[] = {
+ { 0x6D, 1, 0x80, 0x80 },
+ { 0x6F, 1, 0x80, 0x80 }
+ };
+
+ if (!pci_test_config_bits(pdev, &mpiix_enable_bits[ap->port_no])) {
+ ata_port_disable(ap);
+ printk(KERN_INFO "ata%u: port disabled. ignoring.\n", ap->id);
+ return 0;
+ }
+ ap->cbl = ATA_CBL_PATA40;
+ return ata_std_prereset(ap);
+}
+
+/**
+ * mpiix_error_handler - probe reset
+ * @ap: ATA port
+ *
+ * Perform the ATA probe and bus reset sequence plus specific handling
+ * for this hardware. The MPIIX has the enable bits in a different place
+ * to PIIX4 and friends. As a pure PIO device it has no cable detect
+ */
+
+static void mpiix_error_handler(struct ata_port *ap)
+{
+ ata_bmdma_drive_eh(ap, mpiix_pre_reset, ata_std_softreset, NULL, ata_std_postreset);
+}
+
+/**
+ * mpiix_set_piomode - set initial PIO mode data
+ * @ap: ATA interface
+ * @adev: ATA device
+ *
+ * Called to do the PIO mode setup. The MPIIX allows us to program the
+ * IORDY sample point (2-5 clocks), recovery 1-4 clocks and whether
+ * prefetching or iordy are used.
+ *
+ * This would get very ugly because we can only program timing for one
+ * device at a time, the other gets PIO0. Fortunately libata calls
+ * our qc_issue_prot command before a command is issued so we can
+ * flip the timings back and forth to reduce the pain.
+ */
+
+static void mpiix_set_piomode(struct ata_port *ap, struct ata_device *adev)
+{
+ int control = 0;
+ int pio = adev->pio_mode - XFER_PIO_0;
+ struct pci_dev *pdev = to_pci_dev(ap->host->dev);
+ u16 idetim;
+ static const /* ISP RTC */
+ u8 timings[][2] = { { 0, 0 },
+ { 0, 0 },
+ { 1, 0 },
+ { 2, 1 },
+ { 2, 3 }, };
+
+ pci_read_config_word(pdev, IDETIM, &idetim);
+ /* Mask the IORDY/TIME/PPE0 bank for this device */
+ if (adev->class == ATA_DEV_ATA)
+ control |= PPE; /* PPE enable for disk */
+ if (ata_pio_need_iordy(adev))
+ control |= IORDY; /* IORDY */
+ if (pio > 0)
+ control |= FTIM; /* This drive is on the fast timing bank */
+
+ /* Mask out timing and clear both TIME bank selects */
+ idetim &= 0xCCEE;
+ idetim &= ~(0x07 << (2 * adev->devno));
+ idetim |= (control << (2 * adev->devno));
+
+ idetim |= (timings[pio][0] << 12) | (timings[pio][1] << 8);
+ pci_write_config_word(pdev, IDETIM, idetim);
+
+ /* We use ap->private_data as a pointer to the device currently
+ loaded for timing */
+ ap->private_data = adev;
+}
+
+/**
+ * mpiix_qc_issue_prot - command issue
+ * @qc: command pending
+ *
+ * Called when the libata layer is about to issue a command. We wrap
+ * this interface so that we can load the correct ATA timings if
+ * neccessary. Our logic also clears TIME0/TIME1 for the other device so
+ * that, even if we get this wrong, cycles to the other device will
+ * be made PIO0.
+ */
+
+static unsigned int mpiix_qc_issue_prot(struct ata_queued_cmd *qc)
+{
+ struct ata_port *ap = qc->ap;
+ struct ata_device *adev = qc->dev;
+
+ /* If modes have been configured and the channel data is not loaded
+ then load it. We have to check if pio_mode is set as the core code
+ does not set adev->pio_mode to XFER_PIO_0 while probing as would be
+ logical */
+
+ if (adev->pio_mode && adev != ap->private_data)
+ mpiix_set_piomode(ap, adev);
+
+ return ata_qc_issue_prot(qc);
+}
+
+static struct scsi_host_template mpiix_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,
+ .max_sectors = ATA_MAX_SECTORS,
+ .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,
+ .bios_param = ata_std_bios_param,
+};
+
+static struct ata_port_operations mpiix_port_ops = {
+ .port_disable = ata_port_disable,
+ .set_piomode = mpiix_set_piomode,
+
+ .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,
+
+ .freeze = ata_bmdma_freeze,
+ .thaw = ata_bmdma_thaw,
+ .error_handler = mpiix_error_handler,
+ .post_internal_cmd = ata_bmdma_post_internal_cmd,
+
+ .qc_prep = ata_qc_prep,
+ .qc_issue = mpiix_qc_issue_prot,
+ .data_xfer = ata_pio_data_xfer,
+
+ .irq_handler = ata_interrupt,
+ .irq_clear = ata_bmdma_irq_clear,
+
+ .port_start = ata_port_start,
+ .port_stop = ata_port_stop,
+ .host_stop = ata_host_stop
+};
+
+static int mpiix_init_one(struct pci_dev *dev, const struct pci_device_id *id)
+{
+ /* Single threaded by the PCI probe logic */
+ static struct ata_probe_ent probe[2];
+ static int printed_version;
+ u16 idetim;
+ int enabled;
+
+ if (!printed_version++)
+ dev_printk(KERN_DEBUG, &dev->dev, "version " DRV_VERSION "\n");
+
+ /* MPIIX has many functions which can be turned on or off according
+ to other devices present. Make sure IDE is enabled before we try
+ and use it */
+
+ pci_read_config_word(dev, IDETIM, &idetim);
+ if (!(idetim & ENABLED))
+ return -ENODEV;
+
+ /* We do our own plumbing to avoid leaking special cases for whacko
+ ancient hardware into the core code. There are two issues to
+ worry about. #1 The chip is a bridge so if in legacy mode and
+ without BARs set fools the setup. #2 If you pci_disable_device
+ the MPIIX your box goes castors up */
+
+ INIT_LIST_HEAD(&probe[0].node);
+ probe[0].dev = pci_dev_to_dev(dev);
+ probe[0].port_ops = &mpiix_port_ops;
+ probe[0].sht = &mpiix_sht;
+ probe[0].pio_mask = 0x1F;
+ probe[0].irq = 14;
+ probe[0].irq_flags = SA_SHIRQ;
+ probe[0].port_flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST;
+ probe[0].n_ports = 1;
+ probe[0].port[0].cmd_addr = 0x1F0;
+ probe[0].port[0].ctl_addr = 0x3F6;
+ probe[0].port[0].altstatus_addr = 0x3F6;
+
+ /* The secondary lurks at different addresses but is otherwise
+ the same beastie */
+
+ INIT_LIST_HEAD(&probe[1].node);
+ probe[1] = probe[0];
+ probe[1].irq = 15;
+ probe[1].port[0].cmd_addr = 0x170;
+ probe[1].port[0].ctl_addr = 0x376;
+ probe[1].port[0].altstatus_addr = 0x376;
+
+ /* Let libata fill in the port details */
+ ata_std_ports(&probe[0].port[0]);
+ ata_std_ports(&probe[1].port[0]);
+
+ /* Now add the port that is active */
+ enabled = (idetim & SECONDARY) ? 1 : 0;
+
+ if (ata_device_add(&probe[enabled]))
+ return 0;
+ return -ENODEV;
+}
+
+/**
+ * mpiix_remove_one - device unload
+ * @pdev: PCI device being removed
+ *
+ * Handle an unplug/unload event for a PCI device. Unload the
+ * PCI driver but do not use the default handler as we *MUST NOT*
+ * disable the device as it has other functions.
+ */
+
+static void __devexit mpiix_remove_one(struct pci_dev *pdev)
+{
+ struct device *dev = pci_dev_to_dev(pdev);
+ struct ata_host *host = dev_get_drvdata(dev);
+
+ ata_host_remove(host);
+ dev_set_drvdata(dev, NULL);
+}
+
+
+
+static const struct pci_device_id mpiix[] = {
+ { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371MX), },
+ { 0, },
+};
+
+static struct pci_driver mpiix_pci_driver = {
+ .name = DRV_NAME,
+ .id_table = mpiix,
+ .probe = mpiix_init_one,
+ .remove = mpiix_remove_one
+};
+
+static int __init mpiix_init(void)
+{
+ return pci_register_driver(&mpiix_pci_driver);
+}
+
+
+static void __exit mpiix_exit(void)
+{
+ pci_unregister_driver(&mpiix_pci_driver);
+}
+
+
+MODULE_AUTHOR("Alan Cox");
+MODULE_DESCRIPTION("low-level driver for Intel MPIIX");
+MODULE_LICENSE("GPL");
+MODULE_DEVICE_TABLE(pci, mpiix);
+MODULE_VERSION(DRV_VERSION);
+
+module_init(mpiix_init);
+module_exit(mpiix_exit);
diff --git a/drivers/ata/pata_netcell.c b/drivers/ata/pata_netcell.c
new file mode 100644
index 000000000000..16cb254cb973
--- /dev/null
+++ b/drivers/ata/pata_netcell.c
@@ -0,0 +1,175 @@
+/*
+ * pata_netcell.c - Netcell PATA driver
+ *
+ * (c) 2006 Red Hat
+ */
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#define DRV_NAME "pata_netcell"
+#define DRV_VERSION "0.1.5"
+
+/**
+ * netcell_probe_init - check for 40/80 pin
+ * @ap: Port
+ *
+ * Cables are handled by the RAID controller. Report 80 pin.
+ */
+
+static int netcell_pre_reset(struct ata_port *ap)
+{
+ ap->cbl = ATA_CBL_PATA80;
+ return ata_std_prereset(ap);
+}
+
+/**
+ * netcell_probe_reset - Probe specified port on PATA host controller
+ * @ap: Port to probe
+ *
+ * LOCKING:
+ * None (inherited from caller).
+ */
+
+static void netcell_error_handler(struct ata_port *ap)
+{
+ return ata_bmdma_drive_eh(ap, netcell_pre_reset, ata_std_softreset, NULL, ata_std_postreset);
+}
+
+/* No PIO or DMA methods needed for this device */
+
+static struct scsi_host_template netcell_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,
+ /* Special handling needed if you have sector or LBA48 limits */
+ .max_sectors = ATA_MAX_SECTORS,
+ .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,
+ /* Use standard CHS mapping rules */
+ .bios_param = ata_std_bios_param,
+};
+
+static const struct ata_port_operations netcell_ops = {
+ .port_disable = ata_port_disable,
+
+ /* Task file is PCI ATA format, use helpers */
+ .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,
+
+ .freeze = ata_bmdma_freeze,
+ .thaw = ata_bmdma_thaw,
+ .error_handler = netcell_error_handler,
+ .post_internal_cmd = ata_bmdma_post_internal_cmd,
+
+ /* BMDMA handling is PCI ATA format, use helpers */
+ .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,
+
+ /* Timeout handling. Special recovery hooks here */
+ .eng_timeout = ata_eng_timeout,
+ .irq_handler = ata_interrupt,
+ .irq_clear = ata_bmdma_irq_clear,
+
+ /* Generic PATA PCI ATA helpers */
+ .port_start = ata_port_start,
+ .port_stop = ata_port_stop,
+ .host_stop = ata_host_stop,
+};
+
+
+/**
+ * netcell_init_one - Register Netcell ATA PCI device with kernel services
+ * @pdev: PCI device to register
+ * @ent: Entry in netcell_pci_tbl matching with @pdev
+ *
+ * Called from kernel PCI layer.
+ *
+ * LOCKING:
+ * Inherited from PCI layer (may sleep).
+ *
+ * RETURNS:
+ * Zero on success, or -ERRNO value.
+ */
+
+static int netcell_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
+{
+ static int printed_version;
+ static struct ata_port_info info = {
+ .sht = &netcell_sht,
+ .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST,
+ /* Actually we don't really care about these as the
+ firmware deals with it */
+ .pio_mask = 0x1f, /* pio0-4 */
+ .mwdma_mask = 0x07, /* mwdma0-2 */
+ .udma_mask = 0x3f, /* UDMA 133 */
+ .port_ops = &netcell_ops,
+ };
+ static struct ata_port_info *port_info[2] = { &info, &info };
+
+ if (!printed_version++)
+ dev_printk(KERN_DEBUG, &pdev->dev,
+ "version " DRV_VERSION "\n");
+
+ /* Any chip specific setup/optimisation/messages here */
+ ata_pci_clear_simplex(pdev);
+
+ /* And let the library code do the work */
+ return ata_pci_init_one(pdev, port_info, 2);
+}
+
+static const struct pci_device_id netcell_pci_tbl[] = {
+ { PCI_DEVICE(PCI_VENDOR_ID_NETCELL, PCI_DEVICE_ID_REVOLUTION), },
+ { } /* terminate list */
+};
+
+static struct pci_driver netcell_pci_driver = {
+ .name = DRV_NAME,
+ .id_table = netcell_pci_tbl,
+ .probe = netcell_init_one,
+ .remove = ata_pci_remove_one,
+};
+
+static int __init netcell_init(void)
+{
+ return pci_register_driver(&netcell_pci_driver);
+}
+
+static void __exit netcell_exit(void)
+{
+ pci_unregister_driver(&netcell_pci_driver);
+}
+
+module_init(netcell_init);
+module_exit(netcell_exit);
+
+MODULE_AUTHOR("Alan Cox");
+MODULE_DESCRIPTION("SCSI low-level driver for Netcell PATA RAID");
+MODULE_LICENSE("GPL");
+MODULE_DEVICE_TABLE(pci, netcell_pci_tbl);
+MODULE_VERSION(DRV_VERSION);
+
diff --git a/drivers/ata/pata_ns87410.c b/drivers/ata/pata_ns87410.c
new file mode 100644
index 000000000000..93d6646d2954
--- /dev/null
+++ b/drivers/ata/pata_ns87410.c
@@ -0,0 +1,236 @@
+/*
+ * pata_ns87410.c - National Semiconductor 87410 PATA for new ATA layer
+ * (C) 2006 Red Hat Inc
+ * Alan Cox
+ *
+ * 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.
+ */
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#define DRV_NAME "pata_ns87410"
+#define DRV_VERSION "0.4.2"
+
+/**
+ * ns87410_pre_reset - probe begin
+ * @ap: ATA port
+ *
+ * Set up cable type and use generic probe init
+ */
+
+static int ns87410_pre_reset(struct ata_port *ap)
+{
+ struct pci_dev *pdev = to_pci_dev(ap->host->dev);
+ static const struct pci_bits ns87410_enable_bits[] = {
+ { 0x43, 1, 0x08, 0x08 },
+ { 0x47, 1, 0x08, 0x08 }
+ };
+
+ if (!pci_test_config_bits(pdev, &ns87410_enable_bits[ap->port_no])) {
+ ata_port_disable(ap);
+ printk(KERN_INFO "ata%u: port disabled. ignoring.\n", ap->id);
+ return 0;
+ }
+ ap->cbl = ATA_CBL_PATA40;
+ return ata_std_prereset(ap);
+}
+
+/**
+ * ns87410_error_handler - probe reset
+ * @ap: ATA port
+ *
+ * Perform the ATA probe and bus reset sequence plus specific handling
+ * for this hardware. The MPIIX has the enable bits in a different place
+ * to PIIX4 and friends. As a pure PIO device it has no cable detect
+ */
+
+static void ns87410_error_handler(struct ata_port *ap)
+{
+ ata_bmdma_drive_eh(ap, ns87410_pre_reset, ata_std_softreset, NULL, ata_std_postreset);
+}
+
+/**
+ * ns87410_set_piomode - set initial PIO mode data
+ * @ap: ATA interface
+ * @adev: ATA device
+ *
+ * Program timing data. This is kept per channel not per device,
+ * and only affects the data port.
+ */
+
+static void ns87410_set_piomode(struct ata_port *ap, struct ata_device *adev)
+{
+ struct pci_dev *pdev = to_pci_dev(ap->host->dev);
+ int port = 0x40 + 4 * ap->port_no;
+ u8 idetcr, idefr;
+ struct ata_timing at;
+
+ static const u8 activebits[15] = {
+ 0, 1, 2, 3, 4,
+ 5, 5, 6, 6, 6,
+ 6, 7, 7, 7, 7
+ };
+
+ static const u8 recoverbits[12] = {
+ 0, 1, 2, 3, 4, 5, 6, 6, 7, 7, 7, 7
+ };
+
+ pci_read_config_byte(pdev, port + 3, &idefr);
+
+ if (ata_pio_need_iordy(adev))
+ idefr |= 0x04; /* IORDY enable */
+ else
+ idefr &= ~0x04;
+
+ if (ata_timing_compute(adev, adev->pio_mode, &at, 30303, 1) < 0) {
+ dev_printk(KERN_ERR, &pdev->dev, "unknown mode %d.\n", adev->pio_mode);
+ return;
+ }
+
+ at.active = FIT(at.active, 2, 16) - 2;
+ at.setup = FIT(at.setup, 1, 4) - 1;
+ at.recover = FIT(at.recover, 1, 12) - 1;
+
+ idetcr = (at.setup << 6) | (recoverbits[at.recover] << 3) | activebits[at.active];
+
+ pci_write_config_byte(pdev, port, idetcr);
+ pci_write_config_byte(pdev, port + 3, idefr);
+ /* We use ap->private_data as a pointer to the device currently
+ loaded for timing */
+ ap->private_data = adev;
+}
+
+/**
+ * ns87410_qc_issue_prot - command issue
+ * @qc: command pending
+ *
+ * Called when the libata layer is about to issue a command. We wrap
+ * this interface so that we can load the correct ATA timings if
+ * neccessary.
+ */
+
+static unsigned int ns87410_qc_issue_prot(struct ata_queued_cmd *qc)
+{
+ struct ata_port *ap = qc->ap;
+ struct ata_device *adev = qc->dev;
+
+ /* If modes have been configured and the channel data is not loaded
+ then load it. We have to check if pio_mode is set as the core code
+ does not set adev->pio_mode to XFER_PIO_0 while probing as would be
+ logical */
+
+ if (adev->pio_mode && adev != ap->private_data)
+ ns87410_set_piomode(ap, adev);
+
+ return ata_qc_issue_prot(qc);
+}
+
+static struct scsi_host_template ns87410_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,
+ .max_sectors = ATA_MAX_SECTORS,
+ .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,
+ .bios_param = ata_std_bios_param,
+};
+
+static struct ata_port_operations ns87410_port_ops = {
+ .port_disable = ata_port_disable,
+ .set_piomode = ns87410_set_piomode,
+
+ .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,
+
+ .freeze = ata_bmdma_freeze,
+ .thaw = ata_bmdma_thaw,
+ .error_handler = ns87410_error_handler,
+ .post_internal_cmd = ata_bmdma_post_internal_cmd,
+
+ .qc_prep = ata_qc_prep,
+ .qc_issue = ns87410_qc_issue_prot,
+ .eng_timeout = ata_eng_timeout,
+ .data_xfer = ata_pio_data_xfer,
+
+ .irq_handler = ata_interrupt,
+ .irq_clear = ata_bmdma_irq_clear,
+
+ .port_start = ata_port_start,
+ .port_stop = ata_port_stop,
+ .host_stop = ata_host_stop
+};
+
+static int ns87410_init_one(struct pci_dev *dev, const struct pci_device_id *id)
+{
+ static struct ata_port_info info = {
+ .sht = &ns87410_sht,
+ .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST,
+ .pio_mask = 0x0F,
+ .port_ops = &ns87410_port_ops
+ };
+ static struct ata_port_info *port_info[2] = {&info, &info};
+ return ata_pci_init_one(dev, port_info, 2);
+}
+
+static const struct pci_device_id ns87410[] = {
+ { PCI_DEVICE(PCI_VENDOR_ID_NS, PCI_DEVICE_ID_NS_87410), },
+ { 0, },
+};
+
+static struct pci_driver ns87410_pci_driver = {
+ .name = DRV_NAME,
+ .id_table = ns87410,
+ .probe = ns87410_init_one,
+ .remove = ata_pci_remove_one
+};
+
+static int __init ns87410_init(void)
+{
+ return pci_register_driver(&ns87410_pci_driver);
+}
+
+
+static void __exit ns87410_exit(void)
+{
+ pci_unregister_driver(&ns87410_pci_driver);
+}
+
+
+MODULE_AUTHOR("Alan Cox");
+MODULE_DESCRIPTION("low-level driver for Nat Semi 87410");
+MODULE_LICENSE("GPL");
+MODULE_DEVICE_TABLE(pci, ns87410);
+MODULE_VERSION(DRV_VERSION);
+
+module_init(ns87410_init);
+module_exit(ns87410_exit);
diff --git a/drivers/ata/pata_oldpiix.c b/drivers/ata/pata_oldpiix.c
new file mode 100644
index 000000000000..04c618a2664b
--- /dev/null
+++ b/drivers/ata/pata_oldpiix.c
@@ -0,0 +1,339 @@
+/*
+ * pata_oldpiix.c - Intel PATA/SATA controllers
+ *
+ * (C) 2005 Red Hat
+ *
+ * Some parts based on ata_piix.c by Jeff Garzik and others.
+ *
+ * Early PIIX differs significantly from the later PIIX as it lacks
+ * SITRE and the slave timing registers. This means that you have to
+ * set timing per channel, or be clever. Libata tells us whenever it
+ * does drive selection and we use this to reload the timings.
+ *
+ * Because of these behaviour differences PIIX gets its own driver module.
+ */
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#define DRV_NAME "pata_oldpiix"
+#define DRV_VERSION "0.5.1"
+
+/**
+ * oldpiix_pre_reset - probe begin
+ * @ap: ATA port
+ *
+ * Set up cable type and use generic probe init
+ */
+
+static int oldpiix_pre_reset(struct ata_port *ap)
+{
+ struct pci_dev *pdev = to_pci_dev(ap->host->dev);
+ static const struct pci_bits oldpiix_enable_bits[] = {
+ { 0x41U, 1U, 0x80UL, 0x80UL }, /* port 0 */
+ { 0x43U, 1U, 0x80UL, 0x80UL }, /* port 1 */
+ };
+
+ if (!pci_test_config_bits(pdev, &oldpiix_enable_bits[ap->port_no])) {
+ ata_port_disable(ap);
+ printk(KERN_INFO "ata%u: port disabled. ignoring.\n", ap->id);
+ return 0;
+ }
+ ap->cbl = ATA_CBL_PATA40;
+ return ata_std_prereset(ap);
+}
+
+/**
+ * oldpiix_pata_error_handler - Probe specified port on PATA host controller
+ * @ap: Port to probe
+ * @classes:
+ *
+ * LOCKING:
+ * None (inherited from caller).
+ */
+
+static void oldpiix_pata_error_handler(struct ata_port *ap)
+{
+ ata_bmdma_drive_eh(ap, oldpiix_pre_reset, ata_std_softreset, NULL, ata_std_postreset);
+}
+
+/**
+ * oldpiix_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 oldpiix_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->dev);
+ unsigned int idetm_port= ap->port_no ? 0x42 : 0x40;
+ u16 idetm_data;
+ int control = 0;
+
+ /*
+ * See Intel Document 298600-004 for the timing programing rules
+ * for PIIX/ICH. Note that the early PIIX does not have the slave
+ * timing port at 0x44.
+ */
+
+ static const /* ISP RTC */
+ u8 timings[][2] = { { 0, 0 },
+ { 0, 0 },
+ { 1, 0 },
+ { 2, 1 },
+ { 2, 3 }, };
+
+ if (pio > 2)
+ control |= 1; /* TIME1 enable */
+ if (ata_pio_need_iordy(adev))
+ control |= 2; /* IE IORDY */
+
+ /* Intel specifies that the PPE functionality is for disk only */
+ if (adev->class == ATA_DEV_ATA)
+ control |= 4; /* PPE enable */
+
+ pci_read_config_word(dev, idetm_port, &idetm_data);
+
+ /* Enable PPE, IE and TIME as appropriate. Clear the other
+ drive timing bits */
+ if (adev->devno == 0) {
+ idetm_data &= 0xCCE0;
+ idetm_data |= control;
+ } else {
+ idetm_data &= 0xCC0E;
+ idetm_data |= (control << 4);
+ }
+ idetm_data |= (timings[pio][0] << 12) |
+ (timings[pio][1] << 8);
+ pci_write_config_word(dev, idetm_port, idetm_data);
+
+ /* Track which port is configured */
+ ap->private_data = adev;
+}
+
+/**
+ * oldpiix_set_dmamode - Initialize host controller PATA DMA timings
+ * @ap: Port whose timings we are configuring
+ * @adev: Device to program
+ * @isich: True if the device is an ICH and has IOCFG registers
+ *
+ * Set MWDMA mode for device, in host controller PCI config space.
+ *
+ * LOCKING:
+ * None (inherited from caller).
+ */
+
+static void oldpiix_set_dmamode (struct ata_port *ap, struct ata_device *adev)
+{
+ struct pci_dev *dev = to_pci_dev(ap->host->dev);
+ u8 idetm_port = ap->port_no ? 0x42 : 0x40;
+ u16 idetm_data;
+
+ static const /* ISP RTC */
+ u8 timings[][2] = { { 0, 0 },
+ { 0, 0 },
+ { 1, 0 },
+ { 2, 1 },
+ { 2, 3 }, };
+
+ /*
+ * MWDMA is driven by the PIO timings. We must also enable
+ * IORDY unconditionally along with TIME1. PPE has already
+ * been set when the PIO timing was set.
+ */
+
+ unsigned int mwdma = adev->dma_mode - XFER_MW_DMA_0;
+ unsigned int control;
+ const unsigned int needed_pio[3] = {
+ XFER_PIO_0, XFER_PIO_3, XFER_PIO_4
+ };
+ int pio = needed_pio[mwdma] - XFER_PIO_0;
+
+ pci_read_config_word(dev, idetm_port, &idetm_data);
+
+ control = 3; /* IORDY|TIME0 */
+ /* Intel specifies that the PPE functionality is for disk only */
+ if (adev->class == ATA_DEV_ATA)
+ control |= 4; /* PPE enable */
+
+ /* If the drive MWDMA is faster than it can do PIO then
+ we must force PIO into PIO0 */
+
+ if (adev->pio_mode < needed_pio[mwdma])
+ /* Enable DMA timing only */
+ control |= 8; /* PIO cycles in PIO0 */
+
+ /* Mask out the relevant control and timing bits we will load. Also
+ clear the other drive TIME register as a precaution */
+ if (adev->devno == 0) {
+ idetm_data &= 0xCCE0;
+ idetm_data |= control;
+ } else {
+ idetm_data &= 0xCC0E;
+ idetm_data |= (control << 4);
+ }
+ idetm_data |= (timings[pio][0] << 12) | (timings[pio][1] << 8);
+ pci_write_config_word(dev, idetm_port, idetm_data);
+
+ /* Track which port is configured */
+ ap->private_data = adev;
+}
+
+/**
+ * oldpiix_qc_issue_prot - command issue
+ * @qc: command pending
+ *
+ * Called when the libata layer is about to issue a command. We wrap
+ * this interface so that we can load the correct ATA timings if
+ * neccessary. Our logic also clears TIME0/TIME1 for the other device so
+ * that, even if we get this wrong, cycles to the other device will
+ * be made PIO0.
+ */
+
+static unsigned int oldpiix_qc_issue_prot(struct ata_queued_cmd *qc)
+{
+ struct ata_port *ap = qc->ap;
+ struct ata_device *adev = qc->dev;
+
+ if (adev != ap->private_data) {
+ if (adev->dma_mode)
+ oldpiix_set_dmamode(ap, adev);
+ else if (adev->pio_mode)
+ oldpiix_set_piomode(ap, adev);
+ }
+ return ata_qc_issue_prot(qc);
+}
+
+
+static struct scsi_host_template oldpiix_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,
+ .max_sectors = ATA_MAX_SECTORS,
+ .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,
+ .bios_param = ata_std_bios_param,
+};
+
+static const struct ata_port_operations oldpiix_pata_ops = {
+ .port_disable = ata_port_disable,
+ .set_piomode = oldpiix_set_piomode,
+ .set_dmamode = oldpiix_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,
+
+ .freeze = ata_bmdma_freeze,
+ .thaw = ata_bmdma_thaw,
+ .error_handler = oldpiix_pata_error_handler,
+ .post_internal_cmd = ata_bmdma_post_internal_cmd,
+
+ .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 = oldpiix_qc_issue_prot,
+ .data_xfer = ata_pio_data_xfer,
+
+ .irq_handler = ata_interrupt,
+ .irq_clear = ata_bmdma_irq_clear,
+
+ .port_start = ata_port_start,
+ .port_stop = ata_port_stop,
+ .host_stop = ata_host_stop,
+};
+
+
+/**
+ * oldpiix_init_one - Register PIIX ATA PCI device with kernel services
+ * @pdev: PCI device to register
+ * @ent: Entry in oldpiix_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 oldpiix_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
+{
+ static int printed_version;
+ static struct ata_port_info info = {
+ .sht = &oldpiix_sht,
+ .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST,
+ .pio_mask = 0x1f, /* pio0-4 */
+ .mwdma_mask = 0x07, /* mwdma1-2 */
+ .port_ops = &oldpiix_pata_ops,
+ };
+ static struct ata_port_info *port_info[2] = { &info, &info };
+
+ if (!printed_version++)
+ dev_printk(KERN_DEBUG, &pdev->dev,
+ "version " DRV_VERSION "\n");
+
+ return ata_pci_init_one(pdev, port_info, 2);
+}
+
+static const struct pci_device_id oldpiix_pci_tbl[] = {
+ { PCI_DEVICE(0x8086, 0x1230), },
+ { } /* terminate list */
+};
+
+static struct pci_driver oldpiix_pci_driver = {
+ .name = DRV_NAME,
+ .id_table = oldpiix_pci_tbl,
+ .probe = oldpiix_init_one,
+ .remove = ata_pci_remove_one,
+};
+
+static int __init oldpiix_init(void)
+{
+ return pci_register_driver(&oldpiix_pci_driver);
+}
+
+static void __exit oldpiix_exit(void)
+{
+ pci_unregister_driver(&oldpiix_pci_driver);
+}
+
+
+module_init(oldpiix_init);
+module_exit(oldpiix_exit);
+
+MODULE_AUTHOR("Alan Cox");
+MODULE_DESCRIPTION("SCSI low-level driver for early PIIX series controllers");
+MODULE_LICENSE("GPL");
+MODULE_DEVICE_TABLE(pci, oldpiix_pci_tbl);
+MODULE_VERSION(DRV_VERSION);
+
diff --git a/drivers/ata/pata_opti.c b/drivers/ata/pata_opti.c
new file mode 100644
index 000000000000..c3d01325e0e2
--- /dev/null
+++ b/drivers/ata/pata_opti.c
@@ -0,0 +1,292 @@
+/*
+ * pata_opti.c - ATI PATA for new ATA layer
+ * (C) 2005 Red Hat Inc
+ * Alan Cox
+ *
+ * Based on
+ * linux/drivers/ide/pci/opti621.c Version 0.7 Sept 10, 2002
+ *
+ * Copyright (C) 1996-1998 Linus Torvalds & authors (see below)
+ *
+ * Authors:
+ * Jaromir Koutek ,
+ * Jan Harkes ,
+ * Mark Lord
+ * Some parts of code are from ali14xx.c and from rz1000.c.
+ *
+ * Also consulted the FreeBSD prototype driver by Kevin Day to try
+ * and resolve some confusions. Further documentation can be found in
+ * Ralf Brown's interrupt list
+ *
+ * If you have other variants of the Opti range (Viper/Vendetta) please
+ * try this driver with those PCI idents and report back. For the later
+ * chips see the pata_optidma driver
+ *
+ */
+
+#include
+#include
+#include