Staging: add pata_rdc driver
authorKevin Huang <Kevin.Huang@rdc.com.tw>
Mon, 1 Jun 2009 03:43:20 +0000 (11:43 +0800)
committerGreg Kroah-Hartman <gregkh@suse.de>
Fri, 19 Jun 2009 18:00:56 +0000 (11:00 -0700)
This is our IDE Source code. This is base on kernel 2.6.28.  pata_rdc.h
and pata_rdc.c

From: Kevin Huang <Kevin.Huang@rdc.com.tw>
Cc: Tomy Wang <Tomy.Wang@rdc.com.tw>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
drivers/staging/pata_rdc/pata_rdc.c [new file with mode: 0644]
drivers/staging/pata_rdc/pata_rdc.h [new file with mode: 0644]

diff --git a/drivers/staging/pata_rdc/pata_rdc.c b/drivers/staging/pata_rdc/pata_rdc.c
new file mode 100644 (file)
index 0000000..657e997
--- /dev/null
@@ -0,0 +1,1403 @@
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/module.h>
+
+#include <linux/pci.h>
+#include <linux/device.h>
+
+#include <scsi/scsi_host.h>
+#include <linux/libata.h>
+
+#include "pata_rdc.h"
+
+//#define DBGPRINTF
+
+#ifdef DBGPRINTF
+
+    #define dbgprintf(format, arg...) printk(KERN_INFO format, ## arg)
+
+#else
+
+    #define dbgprintf(...)
+
+#endif
+
+// Driver Info.
+
+#define DRIVER_NAME         "pata_rdc"  // sata_rdc for SATA
+#define DRIVER_VERSION      "2.6.28"    // based on kernel version.
+                                        // because each kernel main version has its libata, we follow kernel to determine the last libata version.
+
+
+static const struct pci_device_id rdc_pata_id_table[] = {
+    { 0x17F3, 0x1011, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RDC_17F31011},
+    { 0x17F3, 0x1012, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RDC_17F31012},
+    { }    /* terminate list */
+};
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("this version author is RDC");    // replace "RDC" with the last maintainer.
+MODULE_DESCRIPTION("RDC PCI IDE Driver");
+MODULE_DEVICE_TABLE(pci, rdc_pata_id_table);
+MODULE_VERSION(DRIVER_VERSION);
+
+// a pci driver
+static struct pci_driver rdc_pata_driver = {
+    .name           = DRIVER_NAME,
+    .id_table       = rdc_pata_id_table,
+    .probe          = rdc_init_one,
+    .remove         = ata_pci_remove_one,
+#ifdef CONFIG_PM
+    .suspend        = ata_pci_device_suspend,
+    .resume         = ata_pci_device_resume,
+#endif
+};
+
+static unsigned int in_module_init = 1; // hotplugging check???
+static int __init pata_rdc_init(void)
+{
+    int rc;
+
+    dbgprintf("pata_rdc_init\n");
+    rc = pci_register_driver(&rdc_pata_driver);
+    if (rc)
+    {
+        dbgprintf("pata_rdc_init faile\n");
+        return rc;
+    }
+
+    in_module_init = 0;
+
+    return 0;
+}
+
+static void __exit pata_rdc_exit(void)
+{
+    dbgprintf("pata_rdc_exit\n");
+    pci_unregister_driver(&rdc_pata_driver);
+}
+
+module_init(pata_rdc_init);
+module_exit(pata_rdc_exit);
+
+// ata device data
+
+static struct pci_bits ATA_Decode_Enable_Bits[] = { // see ATA Host Adapters Standards.
+    { 0x41U, 1U, 0x80UL, 0x80UL },    /* port (Channel) 0 */
+    { 0x43U, 1U, 0x80UL, 0x80UL },    /* port (Channel) 1 */
+};
+
+static struct scsi_host_template rdc_pata_sht = {    // pata host template
+    ATA_BMDMA_SHT(DRIVER_NAME),
+};
+
+static const struct ata_port_operations rdc_pata_ops = {
+    .inherits           = &ata_bmdma_port_ops,
+
+    .port_start         = rdc_pata_port_start,
+    .port_stop          = rdc_pata_port_stop,
+    .prereset           = rdc_pata_prereset,
+    .cable_detect       = rdc_pata_cable_detect,
+    .set_piomode        = rdc_pata_set_piomode,
+    .set_dmamode        = rdc_pata_set_dmamode,
+
+};
+
+static struct ata_port_info rdc_pata_port_info[] = {
+    [RDC_17F31011] =
+    {
+        .flags          = ATA_FLAG_SLAVE_POSS,
+        .pio_mask       = 0x1f,    /* pio0-4 */
+        .mwdma_mask     = 0x07, /* mwdma0-2 */
+        .udma_mask      = ATA_UDMA5, /* udma0-5 */
+        .port_ops       = &rdc_pata_ops,
+    },
+
+    [RDC_17F31012] =
+    {
+        .flags          = ATA_FLAG_SLAVE_POSS,
+        .pio_mask       = 0x1f,    /* pio0-4 */
+        .mwdma_mask     = 0x07, /* mwdma0-2 */
+        .udma_mask      = ATA_UDMA5, /* udma0-5 */
+        .port_ops       = &rdc_pata_ops,
+    },
+
+
+};
+
+
+
+
+// callback function for pci_driver
+
+/**
+ *    Register ATA PCI device with kernel services
+ *    @pdev: PCI device to register
+ *    @ent: Entry in sch_pci_tbl matching with @pdev
+ *
+ *    LOCKING:
+ *    Inherited from PCI layer (may sleep).
+ *
+ *    RETURNS:
+ *    Zero on success, or -ERRNO value.
+ */
+static int __devinit rdc_init_one(
+    struct pci_dev *pdev,
+    const struct pci_device_id *ent
+    )
+{
+    //struct device *dev = &pdev->dev;
+    struct ata_port_info port_info[2];
+    struct ata_port_info *ppinfo[] = { &port_info[0], &port_info[1] };
+
+    int rc;
+
+    dbgprintf("rdc_init_one\n");
+
+    /* no hotplugging support (FIXME) */ // why???
+    if (!in_module_init)
+    {
+        dbgprintf("rdc_init_one in_module_init == 0 failed \n");
+        return -ENODEV;
+    }
+    port_info[0] = rdc_pata_port_info[ent->driver_data];
+    port_info[1] = rdc_pata_port_info[ent->driver_data];
+
+    /* enable device and prepare host */
+    rc = pci_enable_device(pdev);
+    if (rc)
+    {
+        dbgprintf("rdc_init_one pci_enable_device failed \n");
+        return rc;
+    }
+    /* initialize controller */
+
+    pci_intx(pdev, 1);  // enable interrupt
+
+    return ata_pci_init_one(pdev, ppinfo);
+}
+
+// callback function for ata_port
+
+/**
+ *    Set port up for dma.
+ *    @ap: Port to initialize
+ *
+ *    Called just after data structures for each port are
+ *    initialized.  Allocates space for PRD table if the device
+ *    is DMA capable SFF.
+
+    Some drivers also use this entry point as a chance to allocate driverprivate
+    memory for ap->private_data.
+
+ *
+ *    May be used as the port_start() entry in ata_port_operations.
+ *
+ *    LOCKING:
+ *    Inherited from caller.
+ */
+static int rdc_pata_port_start(
+    struct ata_port *ap
+    )
+{
+    uint    Channel;
+
+    Channel = ap->port_no;
+    dbgprintf("rdc_pata_port_start Channel: %u \n", Channel);
+    if (ap->ioaddr.bmdma_addr)
+    {
+        return ata_port_start(ap);
+    }
+    else
+    {
+        dbgprintf("rdc_pata_port_start return 0 !!!\n");
+        return 0;
+    }
+}
+
+static void rdc_pata_port_stop(
+    struct ata_port *ap
+    )
+{
+    uint    Channel;
+
+    Channel = ap->port_no;
+
+    dbgprintf("rdc_pata_port_stop Channel: %u \n", Channel);
+}
+
+/**
+ *    prereset for PATA host controller
+ *    @link: Target link
+ *    @deadline: deadline jiffies for the operation
+ *
+ *    LOCKING:
+ *    None (inherited from caller).
+ */
+static int rdc_pata_prereset(
+    struct ata_link *link,
+    unsigned long deadline
+    )
+{
+    struct pci_dev *pdev;
+    struct ata_port *ap;
+
+    uint    Channel;
+
+    dbgprintf("rdc_pata_prereset\n");
+
+    ap = link->ap;
+    pdev = to_pci_dev(ap->host->dev);
+
+    Channel = ap->port_no;
+
+    // test ATA Decode Enable Bits, should be enable.
+    if (!pci_test_config_bits(pdev, &ATA_Decode_Enable_Bits[Channel]))
+    {
+        dbgprintf("rdc_pata_prereset Channel: %u, Decode Disable\n", Channel);
+        return -ENOENT;
+    }
+    else
+    {
+        dbgprintf("rdc_pata_prereset Channel: %u, Decode Enable\n", Channel);
+        return ata_std_prereset(link, deadline);
+    }
+}
+
+/**
+ *    Probe host controller cable detect info
+ *    @ap: Port for which cable detect info is desired
+ *
+ *    Read cable indicator from ATA PCI device's PCI config
+ *    register.  This register is normally set by firmware (BIOS).
+ *
+ *    LOCKING:
+ *    None (inherited from caller).
+ */
+
+static int rdc_pata_cable_detect(
+    struct ata_port *ap
+    )
+{
+    struct pci_dev *pdev;
+
+    uint    Channel;
+
+    uint    Mask;
+    u32     u32Value;
+
+    dbgprintf("rdc_pata_cable_detect\n");
+
+    pdev = to_pci_dev(ap->host->dev);
+
+    Channel = ap->port_no;
+
+    if (Channel == 0)
+    {
+        Mask = ATAConfiguration_IDEIOConfiguration_PrimaryDeviceCable80Report;
+    }
+    else
+    {
+        Mask = ATAConfiguration_IDEIOConfiguration_SecondaryDeviceCable80Report;
+    }
+
+    /* check BIOS cable detect results */
+    pci_read_config_dword(pdev, ATAConfiguration_ID_IDEIOConfiguration + ATAConfiguration_PCIOffset, &u32Value);
+
+    if ((u32Value & Mask) == 0)
+    {
+        dbgprintf("rdc_pata_cable_detect Channel: %u, PATA40 \n", Channel);
+        return ATA_CBL_PATA40;
+    }
+    else
+    {
+        dbgprintf("rdc_pata_cable_detect Channel: %u, PATA80 \n", Channel);
+        return ATA_CBL_PATA80;
+    }
+}
+
+/**
+ *    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 rdc_pata_set_piomode(
+    struct ata_port *ap,
+    struct ata_device *adev
+    )
+{
+    struct pci_dev *pdev;
+
+    uint    Channel;
+    uint    DeviceID;
+
+    uint    PIOTimingMode;
+    uint    PrefetchPostingEnable;
+
+    dbgprintf("rdc_pata_set_piomode\n");
+
+    pdev    = to_pci_dev(ap->host->dev);
+
+    Channel = ap->port_no;
+    DeviceID = adev->devno;
+    PIOTimingMode = adev->pio_mode - XFER_PIO_0;  // piomode = 0, 1, 2, 3... ; adev->pio_mode = XFER_PIO_0, XFER_PIO_1, XFER_PIO_2, XFER_PIO_3...
+
+    if (adev->class == ATA_DEV_ATA)
+    {
+        PrefetchPostingEnable = TRUE;
+    }
+    else
+    {   // ATAPI, CD DVD Rom
+        PrefetchPostingEnable = FALSE;
+    }
+
+    /* PIO configuration clears DTE unconditionally.  It will be
+     * programmed in set_dmamode which is guaranteed to be called
+     * after set_piomode if any DMA mode is available.
+     */
+
+     /* Ensure the UDMA bit is off - it will be turned back on if
+       UDMA is selected */
+
+    if (Channel == 0)
+    {
+        ATAHostAdapter_SetPrimaryPIO(
+            pdev,
+            DeviceID,
+            PIOTimingMode,
+            TRUE,//DMAEnable,
+            PrefetchPostingEnable
+            );
+
+        ATAHostAdapter_SetPrimaryUDMA(
+            pdev,
+            DeviceID,
+            FALSE,//UDMAEnable,
+            UDMA0
+            );
+    }
+    else
+    {
+        ATAHostAdapter_SetSecondaryPIO(
+            pdev,
+            DeviceID,
+            PIOTimingMode,
+            TRUE,//DMAEnable,
+            PrefetchPostingEnable
+            );
+
+        ATAHostAdapter_SetSecondaryUDMA(
+            pdev,
+            DeviceID,
+            FALSE,//UDMAEnable,
+            UDMA0
+            );
+    }
+    dbgprintf("rdc_pata_set_piomode Channel: %u, DeviceID: %u, PIO: %d \n", Channel, DeviceID, PIOTimingMode);
+}
+
+/**
+ *    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).
+ */
+
+static void rdc_pata_set_dmamode(
+    struct ata_port *ap,
+    struct ata_device *adev
+    )
+{
+    struct pci_dev *pdev;
+
+    uint    Channel;
+    uint    DeviceID;
+
+    uint    PIOTimingMode;
+    uint    PrefetchPostingEnable;
+    uint    DMATimingMode;
+    uint    UDMAEnable;
+
+    dbgprintf("rdc_pata_set_dmamode\n");
+
+    pdev    = to_pci_dev(ap->host->dev);
+
+    Channel = ap->port_no;
+    DeviceID = adev->devno;
+    PIOTimingMode = adev->pio_mode - XFER_PIO_0;  // piomode = 0, 1, 2, 3... ; adev->pio_mode = XFER_PIO_0, XFER_PIO_1, XFER_PIO_2, XFER_PIO_3...
+    DMATimingMode = adev->dma_mode; // UDMA or MDMA
+
+    if (adev->class == ATA_DEV_ATA)
+    {
+        PrefetchPostingEnable = TRUE;
+    }
+    else
+    {   // ATAPI, CD DVD Rom
+        PrefetchPostingEnable = FALSE;
+    }
+
+    if (ap->udma_mask == 0)
+    {   // ata_port dont support udma. depend on hardware spec.
+        UDMAEnable = FALSE;
+    }
+    else
+    {
+        UDMAEnable = TRUE;
+    }
+
+    /*if (ap->mdma_mask == 0)
+    {
+    }*/
+
+    if (Channel == 0)
+    {
+        if (DMATimingMode >= XFER_UDMA_0)
+        {   // UDMA
+            ATAHostAdapter_SetPrimaryPIO(
+                pdev,
+                DeviceID,
+                PIOTimingMode,
+                TRUE,//DMAEnable,
+                PrefetchPostingEnable
+                );
+
+            ATAHostAdapter_SetPrimaryUDMA(
+                pdev,
+                DeviceID,
+                UDMAEnable,
+                DMATimingMode - XFER_UDMA_0
+                );
+            dbgprintf("rdc_pata_set_dmamode Channel: %u, DeviceID: %u, UDMA: %u \n", Channel, DeviceID, (uint)(DMATimingMode - XFER_UDMA_0));
+        }
+        else
+        {   // MDMA
+            ATAHostAdapter_SetPrimaryPIO(
+                pdev,
+                DeviceID,
+                (DMATimingMode - XFER_MW_DMA_0) + PIO2, // MDMA0 = PIO2
+                TRUE,//DMAEnable,
+                PrefetchPostingEnable
+                );
+
+            ATAHostAdapter_SetPrimaryUDMA(
+                pdev,
+                DeviceID,
+                FALSE,//UDMAEnable,
+                UDMA0
+                );
+            dbgprintf("rdc_pata_set_dmamode Channel: %u, DeviceID: %u, MDMA: %u \n", Channel, DeviceID, (uint)(DMATimingMode - XFER_MW_DMA_0));
+        }
+    }
+    else
+    {
+        if (DMATimingMode >= XFER_UDMA_0)
+        {   // UDMA
+            ATAHostAdapter_SetSecondaryPIO(
+                pdev,
+                DeviceID,
+                PIOTimingMode,
+                TRUE,//DMAEnable,
+                PrefetchPostingEnable
+                );
+
+            ATAHostAdapter_SetSecondaryUDMA(
+                pdev,
+                DeviceID,
+                UDMAEnable,
+                DMATimingMode - XFER_UDMA_0
+                );
+            dbgprintf("rdc_pata_set_dmamode Channel: %u, DeviceID: %u, UDMA: %u \n", Channel, DeviceID, (uint)(DMATimingMode - XFER_UDMA_0));
+        }
+        else
+        {   // MDMA
+            ATAHostAdapter_SetSecondaryPIO(
+                pdev,
+                DeviceID,
+                (DMATimingMode - XFER_MW_DMA_0) + PIO2, // MDMA0 = PIO2
+                TRUE,//DMAEnable,
+                PrefetchPostingEnable
+                );
+
+            ATAHostAdapter_SetSecondaryUDMA(
+                pdev,
+                DeviceID,
+                FALSE,//UDMAEnable,
+                UDMA0
+                );
+            dbgprintf("rdc_pata_set_dmamode Channel: %u, DeviceID: %u, MDMA: %u \n", Channel, DeviceID, (uint)(DMATimingMode - XFER_MW_DMA_0));
+        }
+    }
+}
+
+// modified PCIDeviceIO code.
+
+static uint
+PCIDeviceIO_ReadPCIConfiguration(
+    struct pci_dev *pdev,
+    uint           Offset,
+    uint           Length,
+    void*          pBuffer
+    )
+{
+    uint    funcresult;
+
+    unchar* pchar;
+
+    uint   i;
+
+    funcresult = TRUE;
+
+    pchar = pBuffer;
+
+    for (i = 0; i < Length; i++)
+    {
+        pci_read_config_byte(pdev, Offset, pchar);
+        Offset++;
+        pchar++;
+    }
+
+    funcresult = TRUE;
+
+    goto funcexit;
+funcexit:
+
+    return funcresult;
+}
+
+static uint
+PCIDeviceIO_WritePCIConfiguration(
+    struct pci_dev *pdev,
+    uint           Offset,
+    uint           Length,
+    void*          pBuffer
+    )
+{
+    uint    funcresult;
+
+    unchar* pchar;
+
+    uint   i;
+
+    funcresult = TRUE;
+
+    pchar = pBuffer;
+
+    for (i = 0; i < Length; i++)
+    {
+        pci_write_config_byte(pdev, Offset, *pchar);
+        Offset++;
+        pchar++;
+    }
+
+    funcresult = TRUE;
+
+    goto funcexit;
+funcexit:
+
+    return funcresult;
+}
+
+
+// modified ATAHostAdapter code.
+
+static uint
+ATAHostAdapter_SetPrimaryPIO(
+    struct pci_dev *pdev,
+    uint                DeviceID,
+    uint                PIOTimingMode,
+    uint                DMAEnable,
+    uint                PrefetchPostingEnable
+    )
+{
+    uint    funcresult;
+
+    uint    result;
+
+    uint    ATATimingRegister;
+    uint    Device1TimingRegister;
+
+    funcresult = TRUE;
+
+    ATATimingRegister = 0;
+    Device1TimingRegister = 0;
+
+    result = PCIDeviceIO_ReadPCIConfiguration(
+        pdev,
+        ATAConfiguration_ID_PrimaryTiming + ATAConfiguration_PCIOffset,
+        ATAConfiguration_ID_PrimaryTiming_Size,
+        &ATATimingRegister
+        );
+    if (result == FALSE)
+    {
+        funcresult = FALSE;
+        goto funcexit;
+    }
+
+    result = PCIDeviceIO_ReadPCIConfiguration(
+        pdev,
+        ATAConfiguration_ID_Device1Timing + ATAConfiguration_PCIOffset,
+        ATAConfiguration_ID_Device1Timing_Size,
+        &Device1TimingRegister
+        );
+    if (result == FALSE)
+    {
+        funcresult = FALSE;
+        goto funcexit;
+    }
+
+    ATATimingRegister |= ATAConfiguration_PrimaryTiming_Device1TimingRegisterEnable;
+
+    switch(DeviceID)
+    {
+        case 0:
+            {
+                // mask clear
+                ATATimingRegister &= ~(ATAConfiguration_PrimaryTiming_Device0FastTimingEnable
+                    | ATAConfiguration_PrimaryTiming_Device0IORDYSampleModeEnable
+                    | ATAConfiguration_PrimaryTiming_Device0PrefetchandPostingEnable
+                    | ATAConfiguration_PrimaryTiming_Device0DMATimingEnable
+                    | ATAConfiguration_PrimaryTiming_Device0RecoveryMode
+                    | ATAConfiguration_PrimaryTiming_Device0IORDYSampleMode
+                    );
+
+                if (PIOTimingMode > PIO0)
+                {
+                    ATATimingRegister |= ATAConfiguration_PrimaryTiming_Device0FastTimingEnable;
+                }
+
+                if (PIOTimingMode >= PIO3)
+                {
+                    ATATimingRegister |= ATAConfiguration_PrimaryTiming_Device0IORDYSampleModeEnable;
+                }
+
+                if (PIOTimingMode >= PIO2 && PrefetchPostingEnable == TRUE)
+                {
+                    ATATimingRegister |= ATAConfiguration_PrimaryTiming_Device0PrefetchandPostingEnable;
+                }
+
+                if (DMAEnable == TRUE
+                    && PIOTimingMode >= PIO2)
+                {
+                    ATATimingRegister |= ATAConfiguration_PrimaryTiming_Device0DMATimingEnable;
+                }
+
+                if (PIOTimingMode <= PIO2)
+                {
+                    ATATimingRegister |= ATAConfiguration_PrimaryTiming_Device0RecoveryMode_0;
+                }
+                else if (PIOTimingMode == PIO3)
+                {
+                    ATATimingRegister |= ATAConfiguration_PrimaryTiming_Device0RecoveryMode_1;
+                }
+                else if (PIOTimingMode == PIO4)
+                {
+                    ATATimingRegister |= ATAConfiguration_PrimaryTiming_Device0RecoveryMode_3;
+                }
+
+                if (PIOTimingMode <= PIO1)
+                {
+                    ATATimingRegister |= ATAConfiguration_PrimaryTiming_Device0IORDYSampleMode_0;
+                }
+                else if (PIOTimingMode == PIO2)
+                {
+                    ATATimingRegister |= ATAConfiguration_PrimaryTiming_Device0IORDYSampleMode_1;
+                }
+                else if (PIOTimingMode <= PIO4)
+                {
+                    ATATimingRegister |= ATAConfiguration_PrimaryTiming_Device0IORDYSampleMode_2;
+                }
+            }
+            break;
+        case 1:
+            {
+                ATATimingRegister &= ~(ATAConfiguration_PrimaryTiming_Device1FastTimingEnable
+                    | ATAConfiguration_PrimaryTiming_Device1IORDYSampleModeEnable
+                    | ATAConfiguration_PrimaryTiming_Device1PrefetchandPostingEnable
+                    | ATAConfiguration_PrimaryTiming_Device1DMATimingEnable
+                    );
+
+                if (PIOTimingMode > PIO0)
+                {
+                    ATATimingRegister |= ATAConfiguration_PrimaryTiming_Device1FastTimingEnable;
+                }
+
+                if (PIOTimingMode >= PIO3)
+                {
+                    ATATimingRegister |= ATAConfiguration_PrimaryTiming_Device1IORDYSampleModeEnable;
+                }
+
+                if (PIOTimingMode >= PIO2 && PrefetchPostingEnable == TRUE)
+                {
+                    ATATimingRegister |= ATAConfiguration_PrimaryTiming_Device1PrefetchandPostingEnable;
+                }
+
+                if (DMAEnable == TRUE
+                    && PIOTimingMode >= PIO2)
+                {
+                    ATATimingRegister |= ATAConfiguration_PrimaryTiming_Device1DMATimingEnable;
+                }
+
+                Device1TimingRegister &= ~(ATAConfiguration_Device1Timing_PrimaryRecoveryMode | ATAConfiguration_Device1Timing_PrimaryIORDYSampleMode);
+
+                if (PIOTimingMode <= PIO2)
+                {
+                    Device1TimingRegister |= ATAConfiguration_Device1Timing_PrimaryRecoveryMode_0;
+                }
+                else if (PIOTimingMode == PIO3)
+                {
+                    Device1TimingRegister |= ATAConfiguration_Device1Timing_PrimaryRecoveryMode_1;
+                }
+                else if (PIOTimingMode == PIO4)
+                {
+                    Device1TimingRegister |= ATAConfiguration_Device1Timing_PrimaryRecoveryMode_3;
+                }
+
+                if (PIOTimingMode <= PIO1)
+                {
+                    Device1TimingRegister |= ATAConfiguration_Device1Timing_PrimaryIORDYSampleMode_0;
+                }
+                else if (PIOTimingMode == PIO2)
+                {
+                    Device1TimingRegister |= ATAConfiguration_Device1Timing_PrimaryIORDYSampleMode_1;
+                }
+                else if (PIOTimingMode <= PIO4)
+                {
+                    Device1TimingRegister |= ATAConfiguration_Device1Timing_PrimaryIORDYSampleMode_2;
+                }
+            }
+            break;
+        default:
+            {
+                funcresult = FALSE;
+                goto funcexit;
+            }
+            break;
+    }
+
+    result = PCIDeviceIO_WritePCIConfiguration(
+        pdev,
+        ATAConfiguration_ID_PrimaryTiming + ATAConfiguration_PCIOffset,
+        ATAConfiguration_ID_PrimaryTiming_Size,
+        &ATATimingRegister
+        );
+    if (result == FALSE)
+    {
+        funcresult = FALSE;
+        goto funcexit;
+    }
+
+    result = PCIDeviceIO_WritePCIConfiguration(
+        pdev,
+        ATAConfiguration_ID_Device1Timing + ATAConfiguration_PCIOffset,
+        ATAConfiguration_ID_Device1Timing_Size,
+        &Device1TimingRegister
+        );
+    if (result == FALSE)
+    {
+        funcresult = FALSE;
+        goto funcexit;
+    }
+
+    goto funcexit;
+funcexit:
+
+    return funcresult;
+}
+
+static uint
+ATAHostAdapter_SetSecondaryPIO(
+    struct pci_dev *pdev,
+    uint                DeviceID,
+    uint                PIOTimingMode,
+    uint                DMAEnable,
+    uint                PrefetchPostingEnable
+    )
+{
+    uint    funcresult;
+
+    uint    result;
+
+    uint    ATATimingRegister;
+    uint    Device1TimingRegister;
+
+    funcresult = TRUE;
+
+    ATATimingRegister = 0;
+    Device1TimingRegister = 0;
+
+    result = PCIDeviceIO_ReadPCIConfiguration(
+        pdev,
+        ATAConfiguration_ID_SecondaryTiming + ATAConfiguration_PCIOffset,
+        ATAConfiguration_ID_SecondaryTiming_Size,
+        &ATATimingRegister
+        );
+    if (result == FALSE)
+    {
+        funcresult = FALSE;
+        goto funcexit;
+    }
+
+    result = PCIDeviceIO_ReadPCIConfiguration(
+        pdev,
+        ATAConfiguration_ID_Device1Timing + ATAConfiguration_PCIOffset,
+        ATAConfiguration_ID_Device1Timing_Size,
+        &Device1TimingRegister
+        );
+    if (result == FALSE)
+    {
+        funcresult = FALSE;
+        goto funcexit;
+    }
+
+    ATATimingRegister |= ATAConfiguration_PrimaryTiming_Device1TimingRegisterEnable;
+
+    switch(DeviceID)
+    {
+        case 0:
+            {
+                // mask clear
+                ATATimingRegister &= ~(ATAConfiguration_PrimaryTiming_Device0FastTimingEnable
+                    | ATAConfiguration_PrimaryTiming_Device0IORDYSampleModeEnable
+                    | ATAConfiguration_PrimaryTiming_Device0PrefetchandPostingEnable
+                    | ATAConfiguration_PrimaryTiming_Device0DMATimingEnable
+                    | ATAConfiguration_PrimaryTiming_Device0RecoveryMode
+                    | ATAConfiguration_PrimaryTiming_Device0IORDYSampleMode
+                    );
+
+                if (PIOTimingMode > PIO0)
+                {
+                    ATATimingRegister |= ATAConfiguration_PrimaryTiming_Device0FastTimingEnable;
+                }
+
+                if (PIOTimingMode >= PIO3)
+                {
+                    ATATimingRegister |= ATAConfiguration_PrimaryTiming_Device0IORDYSampleModeEnable;
+                }
+
+                if (PIOTimingMode >= PIO2 && PrefetchPostingEnable == TRUE)
+                {
+                    ATATimingRegister |= ATAConfiguration_PrimaryTiming_Device0PrefetchandPostingEnable;
+                }
+
+                if (DMAEnable == TRUE
+                    && PIOTimingMode >= PIO2)
+                {
+                    ATATimingRegister |= ATAConfiguration_PrimaryTiming_Device0DMATimingEnable;
+                }
+
+                if (PIOTimingMode <= PIO2)
+                {
+                    ATATimingRegister |= ATAConfiguration_PrimaryTiming_Device0RecoveryMode_0;
+                }
+                else if (PIOTimingMode == PIO3)
+                {
+                    ATATimingRegister |= ATAConfiguration_PrimaryTiming_Device0RecoveryMode_1;
+                }
+                else if (PIOTimingMode == PIO4)
+                {
+                    ATATimingRegister |= ATAConfiguration_PrimaryTiming_Device0RecoveryMode_3;
+                }
+
+                if (PIOTimingMode <= PIO1)
+                {
+                    ATATimingRegister |= ATAConfiguration_PrimaryTiming_Device0IORDYSampleMode_0;
+                }
+                else if (PIOTimingMode == PIO2)
+                {
+                    ATATimingRegister |= ATAConfiguration_PrimaryTiming_Device0IORDYSampleMode_1;
+                }
+                else if (PIOTimingMode <= PIO4)
+                {
+                    ATATimingRegister |= ATAConfiguration_PrimaryTiming_Device0IORDYSampleMode_2;
+                }
+            }
+            break;
+        case 1:
+            {
+                ATATimingRegister &= ~(ATAConfiguration_PrimaryTiming_Device1FastTimingEnable
+                    | ATAConfiguration_PrimaryTiming_Device1IORDYSampleModeEnable
+                    | ATAConfiguration_PrimaryTiming_Device1PrefetchandPostingEnable
+                    | ATAConfiguration_PrimaryTiming_Device1DMATimingEnable
+                    );
+
+                if (PIOTimingMode > PIO0)
+                {
+                    ATATimingRegister |= ATAConfiguration_PrimaryTiming_Device1FastTimingEnable;
+                }
+
+                if (PIOTimingMode >= PIO3)
+                {
+                    ATATimingRegister |= ATAConfiguration_PrimaryTiming_Device1IORDYSampleModeEnable;
+                }
+
+                if (PIOTimingMode >= PIO2 && PrefetchPostingEnable == TRUE)
+                {
+                    ATATimingRegister |= ATAConfiguration_PrimaryTiming_Device1PrefetchandPostingEnable;
+                }
+
+                if (DMAEnable == TRUE
+                    && PIOTimingMode >= PIO2)
+                {
+                    ATATimingRegister |= ATAConfiguration_PrimaryTiming_Device1DMATimingEnable;
+                }
+
+                Device1TimingRegister &= ~(ATAConfiguration_Device1Timing_SecondaryRecoveryMode | ATAConfiguration_Device1Timing_SecondaryIORDYSampleMode);
+
+                if (PIOTimingMode <= PIO2)
+                {
+                    Device1TimingRegister |= ATAConfiguration_Device1Timing_SecondaryRecoveryMode_0;
+                }
+                else if (PIOTimingMode == PIO3)
+                {
+                    Device1TimingRegister |= ATAConfiguration_Device1Timing_SecondaryRecoveryMode_1;
+                }
+                else if (PIOTimingMode == PIO4)
+                {
+                    Device1TimingRegister |= ATAConfiguration_Device1Timing_SecondaryRecoveryMode_3;
+                }
+
+                if (PIOTimingMode <= PIO1)
+                {
+                    Device1TimingRegister |= ATAConfiguration_Device1Timing_SecondaryIORDYSampleMode_0;
+                }
+                else if (PIOTimingMode == PIO2)
+                {
+                    Device1TimingRegister |= ATAConfiguration_Device1Timing_SecondaryIORDYSampleMode_1;
+                }
+                else if (PIOTimingMode <= PIO4)
+                {
+                    Device1TimingRegister |= ATAConfiguration_Device1Timing_SecondaryIORDYSampleMode_2;
+                }
+            }
+            break;
+        default:
+            {
+                funcresult = FALSE;
+                goto funcexit;
+            }
+            break;
+    }
+
+    result = PCIDeviceIO_WritePCIConfiguration(
+        pdev,
+        ATAConfiguration_ID_SecondaryTiming + ATAConfiguration_PCIOffset,
+        ATAConfiguration_ID_SecondaryTiming_Size,
+        &ATATimingRegister
+        );
+    if (result == FALSE)
+    {
+        funcresult = FALSE;
+        goto funcexit;
+    }
+
+    result = PCIDeviceIO_WritePCIConfiguration(
+        pdev,
+        ATAConfiguration_ID_Device1Timing + ATAConfiguration_PCIOffset,
+        ATAConfiguration_ID_Device1Timing_Size,
+        &Device1TimingRegister
+        );
+    if (result == FALSE)
+    {
+        funcresult = FALSE;
+        goto funcexit;
+    }
+
+    goto funcexit;
+funcexit:
+
+    return funcresult;
+}
+
+static uint
+ATAHostAdapter_SetPrimaryUDMA(
+    struct pci_dev *pdev,
+    uint                DeviceID,
+    uint                UDMAEnable,
+    uint                UDMATimingMode
+    )
+{
+    uint    funcresult;
+
+    uint    result;
+
+    uint    UDMAControlRegister;
+    uint    UDMATimingRegister;
+    ulong   IDEIOConfigurationRegister;
+
+    funcresult = TRUE;
+
+    UDMAControlRegister = 0;
+    UDMATimingRegister = 0;
+    IDEIOConfigurationRegister = 0;
+
+    result = PCIDeviceIO_ReadPCIConfiguration(
+        pdev,
+        ATAConfiguration_ID_UDMAControl + ATAConfiguration_PCIOffset,
+        ATAConfiguration_ID_UDMAControl_Size,
+        &UDMAControlRegister
+        );
+    if (result == FALSE)
+    {
+        funcresult = FALSE;
+        goto funcexit;
+    }
+
+    result = PCIDeviceIO_ReadPCIConfiguration(
+        pdev,
+        ATAConfiguration_ID_UDMATiming + ATAConfiguration_PCIOffset,
+        ATAConfiguration_ID_UDMATiming_Size,
+        &UDMATimingRegister
+        );
+    if (result == FALSE)
+    {
+        funcresult = FALSE;
+        goto funcexit;
+    }
+
+    result = PCIDeviceIO_ReadPCIConfiguration(
+        pdev,
+        ATAConfiguration_ID_IDEIOConfiguration + ATAConfiguration_PCIOffset,
+        ATAConfiguration_ID_IDEIOConfiguration_Size,
+        &IDEIOConfigurationRegister
+        );
+    if (result == FALSE)
+    {
+        funcresult = FALSE;
+        goto funcexit;
+    }
+
+    //Rom Code will determine the device cable type and ATA 100.
+    //IDEIOConfigurationRegister |= ATAConfiguration_IDEIOConfiguration_DeviceCable80Report;
+    //IDEIOConfigurationRegister |= ATAConfiguration_IDEIOConfiguration_ATA100IsSupported;
+
+    switch(DeviceID)
+    {
+        case 0:
+            {
+                UDMAControlRegister &= ~(ATAConfiguration_UDMAControl_PrimaryDevice0UDMAModeEnable);
+                if (UDMAEnable == TRUE)
+                {
+                    UDMAControlRegister |= ATAConfiguration_UDMAControl_PrimaryDevice0UDMAModeEnable;
+                }
+
+                IDEIOConfigurationRegister &= ~(ATAConfiguration_IDEIOConfiguration_PrimaryDevice066MhzEnable
+                    | ATAConfiguration_IDEIOConfiguration_PrimaryDevice0100MhzEnable
+                    );
+
+                if (UDMATimingMode >= UDMA5)
+                {
+                    IDEIOConfigurationRegister |= ATAConfiguration_IDEIOConfiguration_PrimaryDevice0100MhzEnable;
+                }
+                else if (UDMATimingMode >= UDMA3)
+                {
+                    IDEIOConfigurationRegister |= ATAConfiguration_IDEIOConfiguration_PrimaryDevice066MhzEnable;
+                }
+
+                // if 80 cable report
+
+                UDMATimingRegister &= ~(ATAConfiguration_UDMATiming_PrimaryDevice0CycleTime);
+
+                if (UDMATimingMode == UDMA0)
+                {
+                    UDMATimingRegister |= ATAConfiguration_UDMATiming_PrimaryDevice0CycleTime_0;
+                }
+                else if (UDMATimingMode == UDMA1 || UDMATimingMode == UDMA3 || UDMATimingMode == UDMA5)
+                {
+                    UDMATimingRegister |= ATAConfiguration_UDMATiming_PrimaryDevice0CycleTime_1;
+                }
+                else if (UDMATimingMode == UDMA2 || UDMATimingMode == UDMA4)
+                {
+                    UDMATimingRegister |= ATAConfiguration_UDMATiming_PrimaryDevice0CycleTime_2;
+                }
+            }
+            break;
+        case 1:
+            {
+                UDMAControlRegister &= ~(ATAConfiguration_UDMAControl_PrimaryDevice1UDMAModeEnable);
+                if (UDMAEnable == TRUE)
+                {
+                    UDMAControlRegister |= ATAConfiguration_UDMAControl_PrimaryDevice1UDMAModeEnable;
+                }
+
+                IDEIOConfigurationRegister &= ~(ATAConfiguration_IDEIOConfiguration_PrimaryDevice166MhzEnable
+                    | ATAConfiguration_IDEIOConfiguration_PrimaryDevice1100MhzEnable
+                    );
+
+                if (UDMATimingMode >= UDMA5)
+                {
+                    IDEIOConfigurationRegister |= ATAConfiguration_IDEIOConfiguration_PrimaryDevice1100MhzEnable;
+                }
+                else if (UDMATimingMode >= UDMA3)
+                {
+                    IDEIOConfigurationRegister |= ATAConfiguration_IDEIOConfiguration_PrimaryDevice166MhzEnable;
+                }
+
+                // if 80 cable report
+
+                UDMATimingRegister &= ~(ATAConfiguration_UDMATiming_PrimaryDevice1CycleTime);
+
+                if (UDMATimingMode == UDMA0)
+                {
+                    UDMATimingRegister |= ATAConfiguration_UDMATiming_PrimaryDevice1CycleTime_0;
+                }
+                else if (UDMATimingMode == UDMA1 || UDMATimingMode == UDMA3 || UDMATimingMode == UDMA5)
+                {
+                    UDMATimingRegister |= ATAConfiguration_UDMATiming_PrimaryDevice1CycleTime_1;
+                }
+                else if (UDMATimingMode == UDMA2 || UDMATimingMode == UDMA4)
+                {
+                    UDMATimingRegister |= ATAConfiguration_UDMATiming_PrimaryDevice1CycleTime_2;
+                }
+            }
+            break;
+        default:
+            {
+                funcresult = FALSE;
+                goto funcexit;
+            }
+            break;
+    }
+
+    result = PCIDeviceIO_WritePCIConfiguration(
+        pdev,
+        ATAConfiguration_ID_UDMAControl + ATAConfiguration_PCIOffset,
+        ATAConfiguration_ID_UDMAControl_Size,
+        &UDMAControlRegister
+        );
+    if (result == FALSE)
+    {
+        funcresult = FALSE;
+        goto funcexit;
+    }
+
+    result = PCIDeviceIO_WritePCIConfiguration(
+        pdev,
+        ATAConfiguration_ID_UDMATiming + ATAConfiguration_PCIOffset,
+        ATAConfiguration_ID_UDMATiming_Size,
+        &UDMATimingRegister
+        );
+    if (result == FALSE)
+    {
+        funcresult = FALSE;
+        goto funcexit;
+    }
+
+    result = PCIDeviceIO_WritePCIConfiguration(
+        pdev,
+        ATAConfiguration_ID_IDEIOConfiguration + ATAConfiguration_PCIOffset,
+        ATAConfiguration_ID_IDEIOConfiguration_Size,
+        &IDEIOConfigurationRegister
+        );
+    if (result == FALSE)
+    {
+        funcresult = FALSE;
+        goto funcexit;
+    }
+
+    goto funcexit;
+funcexit:
+
+    return funcresult;
+}
+
+static uint
+ATAHostAdapter_SetSecondaryUDMA(
+    struct pci_dev *pdev,
+    uint                DeviceID,
+    uint                UDMAEnable,
+    uint                UDMATimingMode
+    )
+{
+    uint    funcresult;
+
+    uint    result;
+
+    uint    UDMAControlRegister;
+    uint    UDMATimingRegister;
+    ulong   IDEIOConfigurationRegister;
+
+    funcresult = TRUE;
+
+    UDMAControlRegister = 0;
+    UDMATimingRegister = 0;
+    IDEIOConfigurationRegister = 0;
+
+    result = PCIDeviceIO_ReadPCIConfiguration(
+        pdev,
+        ATAConfiguration_ID_UDMAControl + ATAConfiguration_PCIOffset,
+        ATAConfiguration_ID_UDMAControl_Size,
+        &UDMAControlRegister
+        );
+    if (result == FALSE)
+    {
+        funcresult = FALSE;
+        goto funcexit;
+    }
+
+    result = PCIDeviceIO_ReadPCIConfiguration(
+        pdev,
+        ATAConfiguration_ID_UDMATiming + ATAConfiguration_PCIOffset,
+        ATAConfiguration_ID_UDMATiming_Size,
+        &UDMATimingRegister
+        );
+    if (result == FALSE)
+    {
+        funcresult = FALSE;
+        goto funcexit;
+    }
+
+    result = PCIDeviceIO_ReadPCIConfiguration(
+        pdev,
+        ATAConfiguration_ID_IDEIOConfiguration + ATAConfiguration_PCIOffset,
+        ATAConfiguration_ID_IDEIOConfiguration_Size,
+        &IDEIOConfigurationRegister
+        );
+    if (result == FALSE)
+    {
+        funcresult = FALSE;
+        goto funcexit;
+    }
+
+    //Rom Code will determine the device cable type and ATA 100.
+    //IDEIOConfigurationRegister |= ATAConfiguration_IDEIOConfiguration_DeviceCable80Report;
+    //IDEIOConfigurationRegister |= ATAConfiguration_IDEIOConfiguration_ATA100IsSupported;
+
+    switch(DeviceID)
+    {
+        case 0:
+            {
+                UDMAControlRegister &= ~(ATAConfiguration_UDMAControl_SecondaryDevice0UDMAModeEnable);
+                if (UDMAEnable == TRUE)
+                {
+                    UDMAControlRegister |= ATAConfiguration_UDMAControl_SecondaryDevice0UDMAModeEnable;
+                }
+
+                IDEIOConfigurationRegister &= ~(ATAConfiguration_IDEIOConfiguration_SecondaryDevice066MhzEnable
+                    | ATAConfiguration_IDEIOConfiguration_SecondaryDevice0100MhzEnable
+                    );
+
+                if (UDMATimingMode >= UDMA5)
+                {
+                    IDEIOConfigurationRegister |= ATAConfiguration_IDEIOConfiguration_SecondaryDevice0100MhzEnable;
+                }
+                else if (UDMATimingMode >= UDMA3)
+                {
+                    IDEIOConfigurationRegister |= ATAConfiguration_IDEIOConfiguration_SecondaryDevice066MhzEnable;
+                }
+
+                // if 80 cable report
+
+                UDMATimingRegister &= ~(ATAConfiguration_UDMATiming_SecondaryDevice0CycleTime);
+
+                if (UDMATimingMode == UDMA0)
+                {
+                    UDMATimingRegister |= ATAConfiguration_UDMATiming_SecondaryDevice0CycleTime_0;
+                }
+                else if (UDMATimingMode == UDMA1 || UDMATimingMode == UDMA3 || UDMATimingMode == UDMA5)
+                {
+                    UDMATimingRegister |= ATAConfiguration_UDMATiming_SecondaryDevice0CycleTime_1;
+                }
+                else if (UDMATimingMode == UDMA2 || UDMATimingMode == UDMA4)
+                {
+                    UDMATimingRegister |= ATAConfiguration_UDMATiming_SecondaryDevice0CycleTime_2;
+                }
+            }
+            break;
+        case 1:
+            {
+                UDMAControlRegister &= ~(ATAConfiguration_UDMAControl_SecondaryDevice1UDMAModeEnable);
+                if (UDMAEnable == TRUE)
+                {
+                    UDMAControlRegister |= ATAConfiguration_UDMAControl_SecondaryDevice1UDMAModeEnable;
+                }
+
+                IDEIOConfigurationRegister &= ~(ATAConfiguration_IDEIOConfiguration_SecondaryDevice166MhzEnable
+                    | ATAConfiguration_IDEIOConfiguration_SecondaryDevice1100MhzEnable
+                    );
+
+                if (UDMATimingMode >= UDMA5)
+                {
+                    IDEIOConfigurationRegister |= ATAConfiguration_IDEIOConfiguration_SecondaryDevice1100MhzEnable;
+                }
+                else if (UDMATimingMode >= UDMA3)
+                {
+                    IDEIOConfigurationRegister |= ATAConfiguration_IDEIOConfiguration_SecondaryDevice166MhzEnable;
+                }
+
+                // if 80 cable report
+
+                UDMATimingRegister &= ~(ATAConfiguration_UDMATiming_SecondaryDevice1CycleTime);
+
+                if (UDMATimingMode == UDMA0)
+                {
+                    UDMATimingRegister |= ATAConfiguration_UDMATiming_SecondaryDevice1CycleTime_0;
+                }
+                else if (UDMATimingMode == UDMA1 || UDMATimingMode == UDMA3 || UDMATimingMode == UDMA5)
+                {
+                    UDMATimingRegister |= ATAConfiguration_UDMATiming_SecondaryDevice1CycleTime_1;
+                }
+                else if (UDMATimingMode == UDMA2 || UDMATimingMode == UDMA4)
+                {
+                    UDMATimingRegister |= ATAConfiguration_UDMATiming_SecondaryDevice1CycleTime_2;
+                }
+            }
+            break;
+        default:
+            {
+                funcresult = FALSE;
+                goto funcexit;
+            }
+            break;
+    }
+
+    result = PCIDeviceIO_WritePCIConfiguration(
+        pdev,
+        ATAConfiguration_ID_UDMAControl + ATAConfiguration_PCIOffset,
+        ATAConfiguration_ID_UDMAControl_Size,
+        &UDMAControlRegister
+        );
+    if (result == FALSE)
+    {
+        funcresult = FALSE;
+        goto funcexit;
+    }
+
+    result = PCIDeviceIO_WritePCIConfiguration(
+        pdev,
+        ATAConfiguration_ID_UDMATiming + ATAConfiguration_PCIOffset,
+        ATAConfiguration_ID_UDMATiming_Size,
+        &UDMATimingRegister
+        );
+    if (result == FALSE)
+    {
+        funcresult = FALSE;
+        goto funcexit;
+    }
+
+    result = PCIDeviceIO_WritePCIConfiguration(
+        pdev,
+        ATAConfiguration_ID_IDEIOConfiguration + ATAConfiguration_PCIOffset,
+        ATAConfiguration_ID_IDEIOConfiguration_Size,
+        &IDEIOConfigurationRegister
+        );
+    if (result == FALSE)
+    {
+        funcresult = FALSE;
+        goto funcexit;
+    }
+
+    goto funcexit;
+funcexit:
+
+    return funcresult;
+}
diff --git a/drivers/staging/pata_rdc/pata_rdc.h b/drivers/staging/pata_rdc/pata_rdc.h
new file mode 100644 (file)
index 0000000..af1d79e
--- /dev/null
@@ -0,0 +1,237 @@
+#ifndef pata_rdc_H
+#define pata_rdc_H
+
+#ifndef TRUE
+#define TRUE  1
+#endif
+
+#ifndef FALSE
+#define FALSE 0
+#endif
+
+// ATA Configuration Register ID offset address size
+#define ATAConfiguration_PCIOffset                  0x40
+#define ATAConfiguration_ID_PrimaryTiming           0x00
+#define ATAConfiguration_ID_SecondaryTiming         0x02
+#define ATAConfiguration_ID_Device1Timing           0x04
+#define ATAConfiguration_ID_UDMAControl             0x08
+#define ATAConfiguration_ID_UDMATiming              0x0A
+#define ATAConfiguration_ID_IDEIOConfiguration      0x14
+
+#define ATAConfiguration_ID_PrimaryTiming_Size         2
+#define ATAConfiguration_ID_SecondaryTiming_Size       2
+#define ATAConfiguration_ID_Device1Timing_Size         1
+#define ATAConfiguration_ID_UDMAControl_Size           1
+#define ATAConfiguration_ID_UDMATiming_Size            2
+#define ATAConfiguration_ID_IDEIOConfiguration_Size    4
+
+// ATA Configuration Register bit define
+#define ATAConfiguration_PrimaryTiming_Device0FastTimingEnable          0x0001
+#define ATAConfiguration_PrimaryTiming_Device0IORDYSampleModeEnable     0x0002  // PIO 3 or greater
+#define ATAConfiguration_PrimaryTiming_Device0PrefetchandPostingEnable  0x0004  // PIO 2 or greater
+#define ATAConfiguration_PrimaryTiming_Device0DMATimingEnable           0x0008
+#define ATAConfiguration_PrimaryTiming_Device1FastTimingEnable          0x0010
+#define ATAConfiguration_PrimaryTiming_Device1IORDYSampleModeEnable     0x0020  // PIO 3 or greater
+#define ATAConfiguration_PrimaryTiming_Device1PrefetchandPostingEnable  0x0040  // PIO 2 or greater
+#define ATAConfiguration_PrimaryTiming_Device1DMATimingEnable           0x0080
+#define ATAConfiguration_PrimaryTiming_Device0RecoveryMode              0x0300
+#define ATAConfiguration_PrimaryTiming_Device0RecoveryMode_0            0x0000  // PIO 0, PIO 2, MDMA 0
+#define ATAConfiguration_PrimaryTiming_Device0RecoveryMode_1            0x0100  // PIO 3, MDMA 1
+#define ATAConfiguration_PrimaryTiming_Device0RecoveryMode_2            0x0200  // X
+#define ATAConfiguration_PrimaryTiming_Device0RecoveryMode_3            0x0300  // PIO 4, MDMA 2
+#define ATAConfiguration_PrimaryTiming_Device0IORDYSampleMode           0x3000
+#define ATAConfiguration_PrimaryTiming_Device0IORDYSampleMode_0         0x0000  // PIO 0
+#define ATAConfiguration_PrimaryTiming_Device0IORDYSampleMode_1         0x1000  // PIO 2, MDMA 0
+#define ATAConfiguration_PrimaryTiming_Device0IORDYSampleMode_2         0x2000  // PIO 3, PIO 4, MDMA 1, MDMA 2
+#define ATAConfiguration_PrimaryTiming_Device0IORDYSampleMode_3         0x3000  // X
+#define ATAConfiguration_PrimaryTiming_Device1TimingRegisterEnable      0x4000
+#define ATAConfiguration_PrimaryTiming_IDEDecodeEnable                  0x8000
+
+#define ATAConfiguration_Device1Timing_PrimaryRecoveryMode              0x0003
+#define ATAConfiguration_Device1Timing_PrimaryRecoveryMode_0            0x0000
+#define ATAConfiguration_Device1Timing_PrimaryRecoveryMode_1            0x0001
+#define ATAConfiguration_Device1Timing_PrimaryRecoveryMode_2            0x0002
+#define ATAConfiguration_Device1Timing_PrimaryRecoveryMode_3            0x0003
+#define ATAConfiguration_Device1Timing_PrimaryIORDYSampleMode           0x000C
+#define ATAConfiguration_Device1Timing_PrimaryIORDYSampleMode_0         0x0000
+#define ATAConfiguration_Device1Timing_PrimaryIORDYSampleMode_1         0x0004
+#define ATAConfiguration_Device1Timing_PrimaryIORDYSampleMode_2         0x0008
+#define ATAConfiguration_Device1Timing_PrimaryIORDYSampleMode_3         0x000C
+#define ATAConfiguration_Device1Timing_SecondaryRecoveryMode            0x0030
+#define ATAConfiguration_Device1Timing_SecondaryRecoveryMode_0          0x0000
+#define ATAConfiguration_Device1Timing_SecondaryRecoveryMode_1          0x0010
+#define ATAConfiguration_Device1Timing_SecondaryRecoveryMode_2          0x0020
+#define ATAConfiguration_Device1Timing_SecondaryRecoveryMode_3          0x0030
+#define ATAConfiguration_Device1Timing_SecondaryIORDYSampleMode         0x00C0
+#define ATAConfiguration_Device1Timing_SecondaryIORDYSampleMode_0       0x0000
+#define ATAConfiguration_Device1Timing_SecondaryIORDYSampleMode_1       0x0040
+#define ATAConfiguration_Device1Timing_SecondaryIORDYSampleMode_2       0x0080
+#define ATAConfiguration_Device1Timing_SecondaryIORDYSampleMode_3       0x00C0
+
+#define ATAConfiguration_UDMAControl_PrimaryDevice0UDMAModeEnable       0x0001
+#define ATAConfiguration_UDMAControl_PrimaryDevice1UDMAModeEnable       0x0002
+#define ATAConfiguration_UDMAControl_SecondaryDevice0UDMAModeEnable     0x0004
+#define ATAConfiguration_UDMAControl_SecondaryDevice1UDMAModeEnable     0x0008
+
+#define ATAConfiguration_UDMATiming_PrimaryDevice0CycleTime             0x0003
+#define ATAConfiguration_UDMATiming_PrimaryDevice0CycleTime_0           0x0000  // UDMA 0
+#define ATAConfiguration_UDMATiming_PrimaryDevice0CycleTime_1           0x0001  // UDMA 1, UDMA 3, UDMA 5
+#define ATAConfiguration_UDMATiming_PrimaryDevice0CycleTime_2           0x0002  // UDMA 2, UDMA 4
+#define ATAConfiguration_UDMATiming_PrimaryDevice0CycleTime_3           0x0003  // X
+#define ATAConfiguration_UDMATiming_PrimaryDevice1CycleTime             0x0030
+#define ATAConfiguration_UDMATiming_PrimaryDevice1CycleTime_0           0x0000  // UDMA 0
+#define ATAConfiguration_UDMATiming_PrimaryDevice1CycleTime_1           0x0010  // UDMA 1, UDMA 3, UDMA 5
+#define ATAConfiguration_UDMATiming_PrimaryDevice1CycleTime_2           0x0020  // UDMA 2, UDMA 4
+#define ATAConfiguration_UDMATiming_PrimaryDevice1CycleTime_3           0x0030  // X
+#define ATAConfiguration_UDMATiming_SecondaryDevice0CycleTime           0x0300
+#define ATAConfiguration_UDMATiming_SecondaryDevice0CycleTime_0         0x0000  // UDMA 0
+#define ATAConfiguration_UDMATiming_SecondaryDevice0CycleTime_1         0x0100  // UDMA 1, UDMA 3, UDMA 5
+#define ATAConfiguration_UDMATiming_SecondaryDevice0CycleTime_2         0x0200  // UDMA 2, UDMA 4
+#define ATAConfiguration_UDMATiming_SecondaryDevice0CycleTime_3         0x0300  // X
+#define ATAConfiguration_UDMATiming_SecondaryDevice1CycleTime           0x3000
+#define ATAConfiguration_UDMATiming_SecondaryDevice1CycleTime_0         0x0000  // UDMA 0
+#define ATAConfiguration_UDMATiming_SecondaryDevice1CycleTime_1         0x1000  // UDMA 1, UDMA 3, UDMA 5
+#define ATAConfiguration_UDMATiming_SecondaryDevice1CycleTime_2         0x2000  // UDMA 2, UDMA 4
+#define ATAConfiguration_UDMATiming_SecondaryDevice1CycleTime_3         0x3000  // X
+
+#define ATAConfiguration_IDEIOConfiguration_PrimaryDevice066MhzEnable       0x00000001  // UDMA 3, UDMA 4
+#define ATAConfiguration_IDEIOConfiguration_PrimaryDevice166MhzEnable       0x00000002
+#define ATAConfiguration_IDEIOConfiguration_SecondaryDevice066MhzEnable     0x00000004
+#define ATAConfiguration_IDEIOConfiguration_SecondaryDevice166MhzEnable     0x00000008
+#define ATAConfiguration_IDEIOConfiguration_DeviceCable80Report             0x000000F0
+#define ATAConfiguration_IDEIOConfiguration_PrimaryDeviceCable80Report      0x00000030
+#define ATAConfiguration_IDEIOConfiguration_PrimaryDevice0Cable80Report     0x00000010  // UDMA 3, UDMA 4, UDMA 5
+#define ATAConfiguration_IDEIOConfiguration_PrimaryDevice1Cable80Report     0x00000020
+#define ATAConfiguration_IDEIOConfiguration_SecondaryDeviceCable80Report    0x000000C0
+#define ATAConfiguration_IDEIOConfiguration_SecondaryDevice0Cable80Report   0x00000040
+#define ATAConfiguration_IDEIOConfiguration_SecondaryDevice1Cable80Report   0x00000080
+#define ATAConfiguration_IDEIOConfiguration_PrimaryDevice0100MhzEnable      0x00001000  // UDMA 5
+#define ATAConfiguration_IDEIOConfiguration_PrimaryDevice1100MhzEnable      0x00002000
+#define ATAConfiguration_IDEIOConfiguration_SecondaryDevice0100MhzEnable    0x00004000
+#define ATAConfiguration_IDEIOConfiguration_SecondaryDevice1100MhzEnable    0x00008000
+#define ATAConfiguration_IDEIOConfiguration_ATA100IsSupported               0x00F00000
+
+enum _PIOTimingMode
+{
+    PIO0 = 0,
+    PIO1,
+    PIO2,   // MDMA 0
+    PIO3,   // MDMA 1
+    PIO4    // MDMA 2
+};
+
+enum _DMATimingMode
+{
+    MDMA0 = 0,
+    MDMA1,
+    MDMA2
+};
+
+enum _UDMATimingMode
+{
+    UDMA0 = 0,
+    UDMA1,
+    UDMA2,
+    UDMA3,
+    UDMA4,
+    UDMA5
+};
+
+
+enum rdc_controller_ids {
+       /* controller IDs */
+       RDC_17F31011,
+       RDC_17F31012
+};
+
+// callback function for driver
+
+static int __devinit rdc_init_one(
+    struct pci_dev *pdev,
+    const struct pci_device_id *ent
+    );
+
+// callback function for ata_port
+
+static int rdc_pata_port_start(
+    struct ata_port *ap
+    );
+
+static void rdc_pata_port_stop(
+    struct ata_port *ap
+    );
+
+static int rdc_pata_prereset(
+    struct ata_link *link,
+    unsigned long deadline
+    );
+
+static int rdc_pata_cable_detect(
+    struct ata_port *ap
+    );
+
+static void rdc_pata_set_piomode(
+    struct ata_port *ap,
+    struct ata_device *adev
+    );
+
+static void rdc_pata_set_dmamode(
+    struct ata_port *ap,
+    struct ata_device *adev
+    );
+
+// modified PCIDeviceIO code.
+
+static uint
+PCIDeviceIO_ReadPCIConfiguration(
+    struct pci_dev *pdev,
+    uint           Offset,
+    uint           Length,
+    void*          pBuffer
+    );
+
+static uint
+PCIDeviceIO_WritePCIConfiguration(
+    struct pci_dev *pdev,
+    uint           Offset,
+    uint           Length,
+    void*          pBuffer
+    );
+
+// modify ATAHostAdapter code
+
+static uint
+ATAHostAdapter_SetPrimaryPIO(
+    struct pci_dev *pdev,
+    uint                DeviceID,
+    uint                PIOTimingMode,
+    uint                DMAEnable,
+    uint                PrefetchPostingEnable
+    );
+
+static uint
+ATAHostAdapter_SetSecondaryPIO(
+    struct pci_dev *pdev,
+    uint                DeviceID,
+    uint                PIOTimingMode,
+    uint                DMAEnable,
+    uint                PrefetchPostingEnable
+    );
+
+static uint
+ATAHostAdapter_SetPrimaryUDMA(
+    struct pci_dev *pdev,
+    uint                DeviceID,
+    uint                UDMAEnable,
+    uint                UDMATimingMode
+    );
+
+static uint
+ATAHostAdapter_SetSecondaryUDMA(
+    struct pci_dev *pdev,
+    uint                DeviceID,
+    uint                UDMAEnable,
+    uint                UDMATimingMode
+    );
+
+#endif