162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * pata_rdc - Driver for later RDC PATA controllers 462306a36Sopenharmony_ci * 562306a36Sopenharmony_ci * This is actually a driver for hardware meeting 662306a36Sopenharmony_ci * INCITS 370-2004 (1510D): ATA Host Adapter Standards 762306a36Sopenharmony_ci * 862306a36Sopenharmony_ci * Based on ata_piix. 962306a36Sopenharmony_ci */ 1062306a36Sopenharmony_ci 1162306a36Sopenharmony_ci#include <linux/kernel.h> 1262306a36Sopenharmony_ci#include <linux/module.h> 1362306a36Sopenharmony_ci#include <linux/pci.h> 1462306a36Sopenharmony_ci#include <linux/blkdev.h> 1562306a36Sopenharmony_ci#include <linux/delay.h> 1662306a36Sopenharmony_ci#include <linux/device.h> 1762306a36Sopenharmony_ci#include <linux/gfp.h> 1862306a36Sopenharmony_ci#include <scsi/scsi_host.h> 1962306a36Sopenharmony_ci#include <linux/libata.h> 2062306a36Sopenharmony_ci#include <linux/dmi.h> 2162306a36Sopenharmony_ci 2262306a36Sopenharmony_ci#define DRV_NAME "pata_rdc" 2362306a36Sopenharmony_ci#define DRV_VERSION "0.01" 2462306a36Sopenharmony_ci 2562306a36Sopenharmony_cistruct rdc_host_priv { 2662306a36Sopenharmony_ci u32 saved_iocfg; 2762306a36Sopenharmony_ci}; 2862306a36Sopenharmony_ci 2962306a36Sopenharmony_ci/** 3062306a36Sopenharmony_ci * rdc_pata_cable_detect - Probe host controller cable detect info 3162306a36Sopenharmony_ci * @ap: Port for which cable detect info is desired 3262306a36Sopenharmony_ci * 3362306a36Sopenharmony_ci * Read 80c cable indicator from ATA PCI device's PCI config 3462306a36Sopenharmony_ci * register. This register is normally set by firmware (BIOS). 3562306a36Sopenharmony_ci * 3662306a36Sopenharmony_ci * LOCKING: 3762306a36Sopenharmony_ci * None (inherited from caller). 3862306a36Sopenharmony_ci */ 3962306a36Sopenharmony_ci 4062306a36Sopenharmony_cistatic int rdc_pata_cable_detect(struct ata_port *ap) 4162306a36Sopenharmony_ci{ 4262306a36Sopenharmony_ci struct rdc_host_priv *hpriv = ap->host->private_data; 4362306a36Sopenharmony_ci u8 mask; 4462306a36Sopenharmony_ci 4562306a36Sopenharmony_ci /* check BIOS cable detect results */ 4662306a36Sopenharmony_ci mask = 0x30 << (2 * ap->port_no); 4762306a36Sopenharmony_ci if ((hpriv->saved_iocfg & mask) == 0) 4862306a36Sopenharmony_ci return ATA_CBL_PATA40; 4962306a36Sopenharmony_ci return ATA_CBL_PATA80; 5062306a36Sopenharmony_ci} 5162306a36Sopenharmony_ci 5262306a36Sopenharmony_ci/** 5362306a36Sopenharmony_ci * rdc_pata_prereset - prereset for PATA host controller 5462306a36Sopenharmony_ci * @link: Target link 5562306a36Sopenharmony_ci * @deadline: deadline jiffies for the operation 5662306a36Sopenharmony_ci * 5762306a36Sopenharmony_ci * LOCKING: 5862306a36Sopenharmony_ci * None (inherited from caller). 5962306a36Sopenharmony_ci */ 6062306a36Sopenharmony_cistatic int rdc_pata_prereset(struct ata_link *link, unsigned long deadline) 6162306a36Sopenharmony_ci{ 6262306a36Sopenharmony_ci struct ata_port *ap = link->ap; 6362306a36Sopenharmony_ci struct pci_dev *pdev = to_pci_dev(ap->host->dev); 6462306a36Sopenharmony_ci 6562306a36Sopenharmony_ci static const struct pci_bits rdc_enable_bits[] = { 6662306a36Sopenharmony_ci { 0x41U, 1U, 0x80UL, 0x80UL }, /* port 0 */ 6762306a36Sopenharmony_ci { 0x43U, 1U, 0x80UL, 0x80UL }, /* port 1 */ 6862306a36Sopenharmony_ci }; 6962306a36Sopenharmony_ci 7062306a36Sopenharmony_ci if (!pci_test_config_bits(pdev, &rdc_enable_bits[ap->port_no])) 7162306a36Sopenharmony_ci return -ENOENT; 7262306a36Sopenharmony_ci return ata_sff_prereset(link, deadline); 7362306a36Sopenharmony_ci} 7462306a36Sopenharmony_ci 7562306a36Sopenharmony_cistatic DEFINE_SPINLOCK(rdc_lock); 7662306a36Sopenharmony_ci 7762306a36Sopenharmony_ci/** 7862306a36Sopenharmony_ci * rdc_set_piomode - Initialize host controller PATA PIO timings 7962306a36Sopenharmony_ci * @ap: Port whose timings we are configuring 8062306a36Sopenharmony_ci * @adev: um 8162306a36Sopenharmony_ci * 8262306a36Sopenharmony_ci * Set PIO mode for device, in host controller PCI config space. 8362306a36Sopenharmony_ci * 8462306a36Sopenharmony_ci * LOCKING: 8562306a36Sopenharmony_ci * None (inherited from caller). 8662306a36Sopenharmony_ci */ 8762306a36Sopenharmony_ci 8862306a36Sopenharmony_cistatic void rdc_set_piomode(struct ata_port *ap, struct ata_device *adev) 8962306a36Sopenharmony_ci{ 9062306a36Sopenharmony_ci unsigned int pio = adev->pio_mode - XFER_PIO_0; 9162306a36Sopenharmony_ci struct pci_dev *dev = to_pci_dev(ap->host->dev); 9262306a36Sopenharmony_ci unsigned long flags; 9362306a36Sopenharmony_ci unsigned int is_slave = (adev->devno != 0); 9462306a36Sopenharmony_ci unsigned int master_port= ap->port_no ? 0x42 : 0x40; 9562306a36Sopenharmony_ci unsigned int slave_port = 0x44; 9662306a36Sopenharmony_ci u16 master_data; 9762306a36Sopenharmony_ci u8 slave_data; 9862306a36Sopenharmony_ci u8 udma_enable; 9962306a36Sopenharmony_ci int control = 0; 10062306a36Sopenharmony_ci 10162306a36Sopenharmony_ci static const /* ISP RTC */ 10262306a36Sopenharmony_ci u8 timings[][2] = { { 0, 0 }, 10362306a36Sopenharmony_ci { 0, 0 }, 10462306a36Sopenharmony_ci { 1, 0 }, 10562306a36Sopenharmony_ci { 2, 1 }, 10662306a36Sopenharmony_ci { 2, 3 }, }; 10762306a36Sopenharmony_ci 10862306a36Sopenharmony_ci if (pio >= 2) 10962306a36Sopenharmony_ci control |= 1; /* TIME1 enable */ 11062306a36Sopenharmony_ci if (ata_pio_need_iordy(adev)) 11162306a36Sopenharmony_ci control |= 2; /* IE enable */ 11262306a36Sopenharmony_ci 11362306a36Sopenharmony_ci if (adev->class == ATA_DEV_ATA) 11462306a36Sopenharmony_ci control |= 4; /* PPE enable */ 11562306a36Sopenharmony_ci 11662306a36Sopenharmony_ci spin_lock_irqsave(&rdc_lock, flags); 11762306a36Sopenharmony_ci 11862306a36Sopenharmony_ci /* PIO configuration clears DTE unconditionally. It will be 11962306a36Sopenharmony_ci * programmed in set_dmamode which is guaranteed to be called 12062306a36Sopenharmony_ci * after set_piomode if any DMA mode is available. 12162306a36Sopenharmony_ci */ 12262306a36Sopenharmony_ci pci_read_config_word(dev, master_port, &master_data); 12362306a36Sopenharmony_ci if (is_slave) { 12462306a36Sopenharmony_ci /* clear TIME1|IE1|PPE1|DTE1 */ 12562306a36Sopenharmony_ci master_data &= 0xff0f; 12662306a36Sopenharmony_ci /* Enable SITRE (separate slave timing register) */ 12762306a36Sopenharmony_ci master_data |= 0x4000; 12862306a36Sopenharmony_ci /* enable PPE1, IE1 and TIME1 as needed */ 12962306a36Sopenharmony_ci master_data |= (control << 4); 13062306a36Sopenharmony_ci pci_read_config_byte(dev, slave_port, &slave_data); 13162306a36Sopenharmony_ci slave_data &= (ap->port_no ? 0x0f : 0xf0); 13262306a36Sopenharmony_ci /* Load the timing nibble for this slave */ 13362306a36Sopenharmony_ci slave_data |= ((timings[pio][0] << 2) | timings[pio][1]) 13462306a36Sopenharmony_ci << (ap->port_no ? 4 : 0); 13562306a36Sopenharmony_ci } else { 13662306a36Sopenharmony_ci /* clear ISP|RCT|TIME0|IE0|PPE0|DTE0 */ 13762306a36Sopenharmony_ci master_data &= 0xccf0; 13862306a36Sopenharmony_ci /* Enable PPE, IE and TIME as appropriate */ 13962306a36Sopenharmony_ci master_data |= control; 14062306a36Sopenharmony_ci /* load ISP and RCT */ 14162306a36Sopenharmony_ci master_data |= 14262306a36Sopenharmony_ci (timings[pio][0] << 12) | 14362306a36Sopenharmony_ci (timings[pio][1] << 8); 14462306a36Sopenharmony_ci } 14562306a36Sopenharmony_ci pci_write_config_word(dev, master_port, master_data); 14662306a36Sopenharmony_ci if (is_slave) 14762306a36Sopenharmony_ci pci_write_config_byte(dev, slave_port, slave_data); 14862306a36Sopenharmony_ci 14962306a36Sopenharmony_ci /* Ensure the UDMA bit is off - it will be turned back on if 15062306a36Sopenharmony_ci UDMA is selected */ 15162306a36Sopenharmony_ci 15262306a36Sopenharmony_ci pci_read_config_byte(dev, 0x48, &udma_enable); 15362306a36Sopenharmony_ci udma_enable &= ~(1 << (2 * ap->port_no + adev->devno)); 15462306a36Sopenharmony_ci pci_write_config_byte(dev, 0x48, udma_enable); 15562306a36Sopenharmony_ci 15662306a36Sopenharmony_ci spin_unlock_irqrestore(&rdc_lock, flags); 15762306a36Sopenharmony_ci} 15862306a36Sopenharmony_ci 15962306a36Sopenharmony_ci/** 16062306a36Sopenharmony_ci * rdc_set_dmamode - Initialize host controller PATA PIO timings 16162306a36Sopenharmony_ci * @ap: Port whose timings we are configuring 16262306a36Sopenharmony_ci * @adev: Drive in question 16362306a36Sopenharmony_ci * 16462306a36Sopenharmony_ci * Set UDMA mode for device, in host controller PCI config space. 16562306a36Sopenharmony_ci * 16662306a36Sopenharmony_ci * LOCKING: 16762306a36Sopenharmony_ci * None (inherited from caller). 16862306a36Sopenharmony_ci */ 16962306a36Sopenharmony_ci 17062306a36Sopenharmony_cistatic void rdc_set_dmamode(struct ata_port *ap, struct ata_device *adev) 17162306a36Sopenharmony_ci{ 17262306a36Sopenharmony_ci struct pci_dev *dev = to_pci_dev(ap->host->dev); 17362306a36Sopenharmony_ci unsigned long flags; 17462306a36Sopenharmony_ci u8 master_port = ap->port_no ? 0x42 : 0x40; 17562306a36Sopenharmony_ci u16 master_data; 17662306a36Sopenharmony_ci u8 speed = adev->dma_mode; 17762306a36Sopenharmony_ci int devid = adev->devno + 2 * ap->port_no; 17862306a36Sopenharmony_ci u8 udma_enable = 0; 17962306a36Sopenharmony_ci 18062306a36Sopenharmony_ci static const /* ISP RTC */ 18162306a36Sopenharmony_ci u8 timings[][2] = { { 0, 0 }, 18262306a36Sopenharmony_ci { 0, 0 }, 18362306a36Sopenharmony_ci { 1, 0 }, 18462306a36Sopenharmony_ci { 2, 1 }, 18562306a36Sopenharmony_ci { 2, 3 }, }; 18662306a36Sopenharmony_ci 18762306a36Sopenharmony_ci spin_lock_irqsave(&rdc_lock, flags); 18862306a36Sopenharmony_ci 18962306a36Sopenharmony_ci pci_read_config_word(dev, master_port, &master_data); 19062306a36Sopenharmony_ci pci_read_config_byte(dev, 0x48, &udma_enable); 19162306a36Sopenharmony_ci 19262306a36Sopenharmony_ci if (speed >= XFER_UDMA_0) { 19362306a36Sopenharmony_ci unsigned int udma = adev->dma_mode - XFER_UDMA_0; 19462306a36Sopenharmony_ci u16 udma_timing; 19562306a36Sopenharmony_ci u16 ideconf; 19662306a36Sopenharmony_ci int u_clock, u_speed; 19762306a36Sopenharmony_ci 19862306a36Sopenharmony_ci /* 19962306a36Sopenharmony_ci * UDMA is handled by a combination of clock switching and 20062306a36Sopenharmony_ci * selection of dividers 20162306a36Sopenharmony_ci * 20262306a36Sopenharmony_ci * Handy rule: Odd modes are UDMATIMx 01, even are 02 20362306a36Sopenharmony_ci * except UDMA0 which is 00 20462306a36Sopenharmony_ci */ 20562306a36Sopenharmony_ci u_speed = min(2 - (udma & 1), udma); 20662306a36Sopenharmony_ci if (udma == 5) 20762306a36Sopenharmony_ci u_clock = 0x1000; /* 100Mhz */ 20862306a36Sopenharmony_ci else if (udma > 2) 20962306a36Sopenharmony_ci u_clock = 1; /* 66Mhz */ 21062306a36Sopenharmony_ci else 21162306a36Sopenharmony_ci u_clock = 0; /* 33Mhz */ 21262306a36Sopenharmony_ci 21362306a36Sopenharmony_ci udma_enable |= (1 << devid); 21462306a36Sopenharmony_ci 21562306a36Sopenharmony_ci /* Load the CT/RP selection */ 21662306a36Sopenharmony_ci pci_read_config_word(dev, 0x4A, &udma_timing); 21762306a36Sopenharmony_ci udma_timing &= ~(3 << (4 * devid)); 21862306a36Sopenharmony_ci udma_timing |= u_speed << (4 * devid); 21962306a36Sopenharmony_ci pci_write_config_word(dev, 0x4A, udma_timing); 22062306a36Sopenharmony_ci 22162306a36Sopenharmony_ci /* Select a 33/66/100Mhz clock */ 22262306a36Sopenharmony_ci pci_read_config_word(dev, 0x54, &ideconf); 22362306a36Sopenharmony_ci ideconf &= ~(0x1001 << devid); 22462306a36Sopenharmony_ci ideconf |= u_clock << devid; 22562306a36Sopenharmony_ci pci_write_config_word(dev, 0x54, ideconf); 22662306a36Sopenharmony_ci } else { 22762306a36Sopenharmony_ci /* 22862306a36Sopenharmony_ci * MWDMA is driven by the PIO timings. We must also enable 22962306a36Sopenharmony_ci * IORDY unconditionally along with TIME1. PPE has already 23062306a36Sopenharmony_ci * been set when the PIO timing was set. 23162306a36Sopenharmony_ci */ 23262306a36Sopenharmony_ci unsigned int mwdma = adev->dma_mode - XFER_MW_DMA_0; 23362306a36Sopenharmony_ci unsigned int control; 23462306a36Sopenharmony_ci u8 slave_data; 23562306a36Sopenharmony_ci const unsigned int needed_pio[3] = { 23662306a36Sopenharmony_ci XFER_PIO_0, XFER_PIO_3, XFER_PIO_4 23762306a36Sopenharmony_ci }; 23862306a36Sopenharmony_ci int pio = needed_pio[mwdma] - XFER_PIO_0; 23962306a36Sopenharmony_ci 24062306a36Sopenharmony_ci control = 3; /* IORDY|TIME1 */ 24162306a36Sopenharmony_ci 24262306a36Sopenharmony_ci /* If the drive MWDMA is faster than it can do PIO then 24362306a36Sopenharmony_ci we must force PIO into PIO0 */ 24462306a36Sopenharmony_ci 24562306a36Sopenharmony_ci if (adev->pio_mode < needed_pio[mwdma]) 24662306a36Sopenharmony_ci /* Enable DMA timing only */ 24762306a36Sopenharmony_ci control |= 8; /* PIO cycles in PIO0 */ 24862306a36Sopenharmony_ci 24962306a36Sopenharmony_ci if (adev->devno) { /* Slave */ 25062306a36Sopenharmony_ci master_data &= 0xFF4F; /* Mask out IORDY|TIME1|DMAONLY */ 25162306a36Sopenharmony_ci master_data |= control << 4; 25262306a36Sopenharmony_ci pci_read_config_byte(dev, 0x44, &slave_data); 25362306a36Sopenharmony_ci slave_data &= (ap->port_no ? 0x0f : 0xf0); 25462306a36Sopenharmony_ci /* Load the matching timing */ 25562306a36Sopenharmony_ci slave_data |= ((timings[pio][0] << 2) | timings[pio][1]) << (ap->port_no ? 4 : 0); 25662306a36Sopenharmony_ci pci_write_config_byte(dev, 0x44, slave_data); 25762306a36Sopenharmony_ci } else { /* Master */ 25862306a36Sopenharmony_ci master_data &= 0xCCF4; /* Mask out IORDY|TIME1|DMAONLY 25962306a36Sopenharmony_ci and master timing bits */ 26062306a36Sopenharmony_ci master_data |= control; 26162306a36Sopenharmony_ci master_data |= 26262306a36Sopenharmony_ci (timings[pio][0] << 12) | 26362306a36Sopenharmony_ci (timings[pio][1] << 8); 26462306a36Sopenharmony_ci } 26562306a36Sopenharmony_ci 26662306a36Sopenharmony_ci udma_enable &= ~(1 << devid); 26762306a36Sopenharmony_ci pci_write_config_word(dev, master_port, master_data); 26862306a36Sopenharmony_ci } 26962306a36Sopenharmony_ci pci_write_config_byte(dev, 0x48, udma_enable); 27062306a36Sopenharmony_ci 27162306a36Sopenharmony_ci spin_unlock_irqrestore(&rdc_lock, flags); 27262306a36Sopenharmony_ci} 27362306a36Sopenharmony_ci 27462306a36Sopenharmony_cistatic struct ata_port_operations rdc_pata_ops = { 27562306a36Sopenharmony_ci .inherits = &ata_bmdma32_port_ops, 27662306a36Sopenharmony_ci .cable_detect = rdc_pata_cable_detect, 27762306a36Sopenharmony_ci .set_piomode = rdc_set_piomode, 27862306a36Sopenharmony_ci .set_dmamode = rdc_set_dmamode, 27962306a36Sopenharmony_ci .prereset = rdc_pata_prereset, 28062306a36Sopenharmony_ci}; 28162306a36Sopenharmony_ci 28262306a36Sopenharmony_cistatic const struct ata_port_info rdc_port_info = { 28362306a36Sopenharmony_ci 28462306a36Sopenharmony_ci .flags = ATA_FLAG_SLAVE_POSS, 28562306a36Sopenharmony_ci .pio_mask = ATA_PIO4, 28662306a36Sopenharmony_ci .mwdma_mask = ATA_MWDMA12_ONLY, 28762306a36Sopenharmony_ci .udma_mask = ATA_UDMA5, 28862306a36Sopenharmony_ci .port_ops = &rdc_pata_ops, 28962306a36Sopenharmony_ci}; 29062306a36Sopenharmony_ci 29162306a36Sopenharmony_cistatic const struct scsi_host_template rdc_sht = { 29262306a36Sopenharmony_ci ATA_BMDMA_SHT(DRV_NAME), 29362306a36Sopenharmony_ci}; 29462306a36Sopenharmony_ci 29562306a36Sopenharmony_ci/** 29662306a36Sopenharmony_ci * rdc_init_one - Register PIIX ATA PCI device with kernel services 29762306a36Sopenharmony_ci * @pdev: PCI device to register 29862306a36Sopenharmony_ci * @ent: Entry in rdc_pci_tbl matching with @pdev 29962306a36Sopenharmony_ci * 30062306a36Sopenharmony_ci * Called from kernel PCI layer. We probe for combined mode (sigh), 30162306a36Sopenharmony_ci * and then hand over control to libata, for it to do the rest. 30262306a36Sopenharmony_ci * 30362306a36Sopenharmony_ci * LOCKING: 30462306a36Sopenharmony_ci * Inherited from PCI layer (may sleep). 30562306a36Sopenharmony_ci * 30662306a36Sopenharmony_ci * RETURNS: 30762306a36Sopenharmony_ci * Zero on success, or -ERRNO value. 30862306a36Sopenharmony_ci */ 30962306a36Sopenharmony_ci 31062306a36Sopenharmony_cistatic int rdc_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) 31162306a36Sopenharmony_ci{ 31262306a36Sopenharmony_ci struct device *dev = &pdev->dev; 31362306a36Sopenharmony_ci struct ata_port_info port_info[2]; 31462306a36Sopenharmony_ci const struct ata_port_info *ppi[] = { &port_info[0], &port_info[1] }; 31562306a36Sopenharmony_ci struct ata_host *host; 31662306a36Sopenharmony_ci struct rdc_host_priv *hpriv; 31762306a36Sopenharmony_ci int rc; 31862306a36Sopenharmony_ci 31962306a36Sopenharmony_ci ata_print_version_once(&pdev->dev, DRV_VERSION); 32062306a36Sopenharmony_ci 32162306a36Sopenharmony_ci port_info[0] = rdc_port_info; 32262306a36Sopenharmony_ci port_info[1] = rdc_port_info; 32362306a36Sopenharmony_ci 32462306a36Sopenharmony_ci /* enable device and prepare host */ 32562306a36Sopenharmony_ci rc = pcim_enable_device(pdev); 32662306a36Sopenharmony_ci if (rc) 32762306a36Sopenharmony_ci return rc; 32862306a36Sopenharmony_ci 32962306a36Sopenharmony_ci hpriv = devm_kzalloc(dev, sizeof(*hpriv), GFP_KERNEL); 33062306a36Sopenharmony_ci if (!hpriv) 33162306a36Sopenharmony_ci return -ENOMEM; 33262306a36Sopenharmony_ci 33362306a36Sopenharmony_ci /* Save IOCFG, this will be used for cable detection, quirk 33462306a36Sopenharmony_ci * detection and restoration on detach. 33562306a36Sopenharmony_ci */ 33662306a36Sopenharmony_ci pci_read_config_dword(pdev, 0x54, &hpriv->saved_iocfg); 33762306a36Sopenharmony_ci 33862306a36Sopenharmony_ci rc = ata_pci_bmdma_prepare_host(pdev, ppi, &host); 33962306a36Sopenharmony_ci if (rc) 34062306a36Sopenharmony_ci return rc; 34162306a36Sopenharmony_ci host->private_data = hpriv; 34262306a36Sopenharmony_ci 34362306a36Sopenharmony_ci pci_intx(pdev, 1); 34462306a36Sopenharmony_ci 34562306a36Sopenharmony_ci host->flags |= ATA_HOST_PARALLEL_SCAN; 34662306a36Sopenharmony_ci 34762306a36Sopenharmony_ci pci_set_master(pdev); 34862306a36Sopenharmony_ci return ata_pci_sff_activate_host(host, ata_bmdma_interrupt, &rdc_sht); 34962306a36Sopenharmony_ci} 35062306a36Sopenharmony_ci 35162306a36Sopenharmony_cistatic void rdc_remove_one(struct pci_dev *pdev) 35262306a36Sopenharmony_ci{ 35362306a36Sopenharmony_ci struct ata_host *host = pci_get_drvdata(pdev); 35462306a36Sopenharmony_ci struct rdc_host_priv *hpriv = host->private_data; 35562306a36Sopenharmony_ci 35662306a36Sopenharmony_ci pci_write_config_dword(pdev, 0x54, hpriv->saved_iocfg); 35762306a36Sopenharmony_ci 35862306a36Sopenharmony_ci ata_pci_remove_one(pdev); 35962306a36Sopenharmony_ci} 36062306a36Sopenharmony_ci 36162306a36Sopenharmony_cistatic const struct pci_device_id rdc_pci_tbl[] = { 36262306a36Sopenharmony_ci { PCI_DEVICE(0x17F3, 0x1011), }, 36362306a36Sopenharmony_ci { PCI_DEVICE(0x17F3, 0x1012), }, 36462306a36Sopenharmony_ci { } /* terminate list */ 36562306a36Sopenharmony_ci}; 36662306a36Sopenharmony_ci 36762306a36Sopenharmony_cistatic struct pci_driver rdc_pci_driver = { 36862306a36Sopenharmony_ci .name = DRV_NAME, 36962306a36Sopenharmony_ci .id_table = rdc_pci_tbl, 37062306a36Sopenharmony_ci .probe = rdc_init_one, 37162306a36Sopenharmony_ci .remove = rdc_remove_one, 37262306a36Sopenharmony_ci#ifdef CONFIG_PM_SLEEP 37362306a36Sopenharmony_ci .suspend = ata_pci_device_suspend, 37462306a36Sopenharmony_ci .resume = ata_pci_device_resume, 37562306a36Sopenharmony_ci#endif 37662306a36Sopenharmony_ci}; 37762306a36Sopenharmony_ci 37862306a36Sopenharmony_ci 37962306a36Sopenharmony_cimodule_pci_driver(rdc_pci_driver); 38062306a36Sopenharmony_ci 38162306a36Sopenharmony_ciMODULE_AUTHOR("Alan Cox (based on ata_piix)"); 38262306a36Sopenharmony_ciMODULE_DESCRIPTION("SCSI low-level driver for RDC PATA controllers"); 38362306a36Sopenharmony_ciMODULE_LICENSE("GPL"); 38462306a36Sopenharmony_ciMODULE_DEVICE_TABLE(pci, rdc_pci_tbl); 38562306a36Sopenharmony_ciMODULE_VERSION(DRV_VERSION); 386