18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * Copyright (C) 1998-2002 Andre Hedrick <andre@linux-ide.org> 48c2ecf20Sopenharmony_ci * Copyright (C) 2006-2007, 2009 MontaVista Software, Inc. 58c2ecf20Sopenharmony_ci * Copyright (C) 2007-2010 Bartlomiej Zolnierkiewicz 68c2ecf20Sopenharmony_ci * 78c2ecf20Sopenharmony_ci * Portions Copyright (C) 1999 Promise Technology, Inc. 88c2ecf20Sopenharmony_ci * Author: Frank Tiernan (frankt@promise.com) 98c2ecf20Sopenharmony_ci * Released under terms of General Public License 108c2ecf20Sopenharmony_ci */ 118c2ecf20Sopenharmony_ci 128c2ecf20Sopenharmony_ci#include <linux/types.h> 138c2ecf20Sopenharmony_ci#include <linux/module.h> 148c2ecf20Sopenharmony_ci#include <linux/kernel.h> 158c2ecf20Sopenharmony_ci#include <linux/delay.h> 168c2ecf20Sopenharmony_ci#include <linux/blkdev.h> 178c2ecf20Sopenharmony_ci#include <linux/pci.h> 188c2ecf20Sopenharmony_ci#include <linux/init.h> 198c2ecf20Sopenharmony_ci#include <linux/ide.h> 208c2ecf20Sopenharmony_ci 218c2ecf20Sopenharmony_ci#include <asm/io.h> 228c2ecf20Sopenharmony_ci 238c2ecf20Sopenharmony_ci#define DRV_NAME "pdc202xx_old" 248c2ecf20Sopenharmony_ci 258c2ecf20Sopenharmony_cistatic void pdc202xx_set_mode(ide_hwif_t *hwif, ide_drive_t *drive) 268c2ecf20Sopenharmony_ci{ 278c2ecf20Sopenharmony_ci struct pci_dev *dev = to_pci_dev(hwif->dev); 288c2ecf20Sopenharmony_ci u8 drive_pci = 0x60 + (drive->dn << 2); 298c2ecf20Sopenharmony_ci const u8 speed = drive->dma_mode; 308c2ecf20Sopenharmony_ci 318c2ecf20Sopenharmony_ci u8 AP = 0, BP = 0, CP = 0; 328c2ecf20Sopenharmony_ci u8 TA = 0, TB = 0, TC = 0; 338c2ecf20Sopenharmony_ci 348c2ecf20Sopenharmony_ci pci_read_config_byte(dev, drive_pci, &AP); 358c2ecf20Sopenharmony_ci pci_read_config_byte(dev, drive_pci + 1, &BP); 368c2ecf20Sopenharmony_ci pci_read_config_byte(dev, drive_pci + 2, &CP); 378c2ecf20Sopenharmony_ci 388c2ecf20Sopenharmony_ci switch(speed) { 398c2ecf20Sopenharmony_ci case XFER_UDMA_5: 408c2ecf20Sopenharmony_ci case XFER_UDMA_4: TB = 0x20; TC = 0x01; break; 418c2ecf20Sopenharmony_ci case XFER_UDMA_2: TB = 0x20; TC = 0x01; break; 428c2ecf20Sopenharmony_ci case XFER_UDMA_3: 438c2ecf20Sopenharmony_ci case XFER_UDMA_1: TB = 0x40; TC = 0x02; break; 448c2ecf20Sopenharmony_ci case XFER_UDMA_0: 458c2ecf20Sopenharmony_ci case XFER_MW_DMA_2: TB = 0x60; TC = 0x03; break; 468c2ecf20Sopenharmony_ci case XFER_MW_DMA_1: TB = 0x60; TC = 0x04; break; 478c2ecf20Sopenharmony_ci case XFER_MW_DMA_0: TB = 0xE0; TC = 0x0F; break; 488c2ecf20Sopenharmony_ci case XFER_PIO_4: TA = 0x01; TB = 0x04; break; 498c2ecf20Sopenharmony_ci case XFER_PIO_3: TA = 0x02; TB = 0x06; break; 508c2ecf20Sopenharmony_ci case XFER_PIO_2: TA = 0x03; TB = 0x08; break; 518c2ecf20Sopenharmony_ci case XFER_PIO_1: TA = 0x05; TB = 0x0C; break; 528c2ecf20Sopenharmony_ci case XFER_PIO_0: 538c2ecf20Sopenharmony_ci default: TA = 0x09; TB = 0x13; break; 548c2ecf20Sopenharmony_ci } 558c2ecf20Sopenharmony_ci 568c2ecf20Sopenharmony_ci if (speed < XFER_SW_DMA_0) { 578c2ecf20Sopenharmony_ci /* 588c2ecf20Sopenharmony_ci * preserve SYNC_INT / ERDDY_EN bits while clearing 598c2ecf20Sopenharmony_ci * Prefetch_EN / IORDY_EN / PA[3:0] bits of register A 608c2ecf20Sopenharmony_ci */ 618c2ecf20Sopenharmony_ci AP &= ~0x3f; 628c2ecf20Sopenharmony_ci if (ide_pio_need_iordy(drive, speed - XFER_PIO_0)) 638c2ecf20Sopenharmony_ci AP |= 0x20; /* set IORDY_EN bit */ 648c2ecf20Sopenharmony_ci if (drive->media == ide_disk) 658c2ecf20Sopenharmony_ci AP |= 0x10; /* set Prefetch_EN bit */ 668c2ecf20Sopenharmony_ci /* clear PB[4:0] bits of register B */ 678c2ecf20Sopenharmony_ci BP &= ~0x1f; 688c2ecf20Sopenharmony_ci pci_write_config_byte(dev, drive_pci, AP | TA); 698c2ecf20Sopenharmony_ci pci_write_config_byte(dev, drive_pci + 1, BP | TB); 708c2ecf20Sopenharmony_ci } else { 718c2ecf20Sopenharmony_ci /* clear MB[2:0] bits of register B */ 728c2ecf20Sopenharmony_ci BP &= ~0xe0; 738c2ecf20Sopenharmony_ci /* clear MC[3:0] bits of register C */ 748c2ecf20Sopenharmony_ci CP &= ~0x0f; 758c2ecf20Sopenharmony_ci pci_write_config_byte(dev, drive_pci + 1, BP | TB); 768c2ecf20Sopenharmony_ci pci_write_config_byte(dev, drive_pci + 2, CP | TC); 778c2ecf20Sopenharmony_ci } 788c2ecf20Sopenharmony_ci} 798c2ecf20Sopenharmony_ci 808c2ecf20Sopenharmony_cistatic void pdc202xx_set_pio_mode(ide_hwif_t *hwif, ide_drive_t *drive) 818c2ecf20Sopenharmony_ci{ 828c2ecf20Sopenharmony_ci drive->dma_mode = drive->pio_mode; 838c2ecf20Sopenharmony_ci pdc202xx_set_mode(hwif, drive); 848c2ecf20Sopenharmony_ci} 858c2ecf20Sopenharmony_ci 868c2ecf20Sopenharmony_cistatic int pdc202xx_test_irq(ide_hwif_t *hwif) 878c2ecf20Sopenharmony_ci{ 888c2ecf20Sopenharmony_ci struct pci_dev *dev = to_pci_dev(hwif->dev); 898c2ecf20Sopenharmony_ci unsigned long high_16 = pci_resource_start(dev, 4); 908c2ecf20Sopenharmony_ci u8 sc1d = inb(high_16 + 0x1d); 918c2ecf20Sopenharmony_ci 928c2ecf20Sopenharmony_ci if (hwif->channel) { 938c2ecf20Sopenharmony_ci /* 948c2ecf20Sopenharmony_ci * bit 7: error, bit 6: interrupting, 958c2ecf20Sopenharmony_ci * bit 5: FIFO full, bit 4: FIFO empty 968c2ecf20Sopenharmony_ci */ 978c2ecf20Sopenharmony_ci return (sc1d & 0x40) ? 1 : 0; 988c2ecf20Sopenharmony_ci } else { 998c2ecf20Sopenharmony_ci /* 1008c2ecf20Sopenharmony_ci * bit 3: error, bit 2: interrupting, 1018c2ecf20Sopenharmony_ci * bit 1: FIFO full, bit 0: FIFO empty 1028c2ecf20Sopenharmony_ci */ 1038c2ecf20Sopenharmony_ci return (sc1d & 0x04) ? 1 : 0; 1048c2ecf20Sopenharmony_ci } 1058c2ecf20Sopenharmony_ci} 1068c2ecf20Sopenharmony_ci 1078c2ecf20Sopenharmony_cistatic u8 pdc2026x_cable_detect(ide_hwif_t *hwif) 1088c2ecf20Sopenharmony_ci{ 1098c2ecf20Sopenharmony_ci struct pci_dev *dev = to_pci_dev(hwif->dev); 1108c2ecf20Sopenharmony_ci u16 CIS, mask = hwif->channel ? (1 << 11) : (1 << 10); 1118c2ecf20Sopenharmony_ci 1128c2ecf20Sopenharmony_ci pci_read_config_word(dev, 0x50, &CIS); 1138c2ecf20Sopenharmony_ci 1148c2ecf20Sopenharmony_ci return (CIS & mask) ? ATA_CBL_PATA40 : ATA_CBL_PATA80; 1158c2ecf20Sopenharmony_ci} 1168c2ecf20Sopenharmony_ci 1178c2ecf20Sopenharmony_ci/* 1188c2ecf20Sopenharmony_ci * Set the control register to use the 66MHz system 1198c2ecf20Sopenharmony_ci * clock for UDMA 3/4/5 mode operation when necessary. 1208c2ecf20Sopenharmony_ci * 1218c2ecf20Sopenharmony_ci * FIXME: this register is shared by both channels, some locking is needed 1228c2ecf20Sopenharmony_ci * 1238c2ecf20Sopenharmony_ci * It may also be possible to leave the 66MHz clock on 1248c2ecf20Sopenharmony_ci * and readjust the timing parameters. 1258c2ecf20Sopenharmony_ci */ 1268c2ecf20Sopenharmony_cistatic void pdc_old_enable_66MHz_clock(ide_hwif_t *hwif) 1278c2ecf20Sopenharmony_ci{ 1288c2ecf20Sopenharmony_ci unsigned long clock_reg = hwif->extra_base + 0x01; 1298c2ecf20Sopenharmony_ci u8 clock = inb(clock_reg); 1308c2ecf20Sopenharmony_ci 1318c2ecf20Sopenharmony_ci outb(clock | (hwif->channel ? 0x08 : 0x02), clock_reg); 1328c2ecf20Sopenharmony_ci} 1338c2ecf20Sopenharmony_ci 1348c2ecf20Sopenharmony_cistatic void pdc_old_disable_66MHz_clock(ide_hwif_t *hwif) 1358c2ecf20Sopenharmony_ci{ 1368c2ecf20Sopenharmony_ci unsigned long clock_reg = hwif->extra_base + 0x01; 1378c2ecf20Sopenharmony_ci u8 clock = inb(clock_reg); 1388c2ecf20Sopenharmony_ci 1398c2ecf20Sopenharmony_ci outb(clock & ~(hwif->channel ? 0x08 : 0x02), clock_reg); 1408c2ecf20Sopenharmony_ci} 1418c2ecf20Sopenharmony_ci 1428c2ecf20Sopenharmony_cistatic void pdc2026x_init_hwif(ide_hwif_t *hwif) 1438c2ecf20Sopenharmony_ci{ 1448c2ecf20Sopenharmony_ci pdc_old_disable_66MHz_clock(hwif); 1458c2ecf20Sopenharmony_ci} 1468c2ecf20Sopenharmony_ci 1478c2ecf20Sopenharmony_cistatic void pdc202xx_dma_start(ide_drive_t *drive) 1488c2ecf20Sopenharmony_ci{ 1498c2ecf20Sopenharmony_ci if (drive->current_speed > XFER_UDMA_2) 1508c2ecf20Sopenharmony_ci pdc_old_enable_66MHz_clock(drive->hwif); 1518c2ecf20Sopenharmony_ci if (drive->media != ide_disk || (drive->dev_flags & IDE_DFLAG_LBA48)) { 1528c2ecf20Sopenharmony_ci ide_hwif_t *hwif = drive->hwif; 1538c2ecf20Sopenharmony_ci struct request *rq = hwif->rq; 1548c2ecf20Sopenharmony_ci unsigned long high_16 = hwif->extra_base - 16; 1558c2ecf20Sopenharmony_ci unsigned long atapi_reg = high_16 + (hwif->channel ? 0x24 : 0x20); 1568c2ecf20Sopenharmony_ci u32 word_count = 0; 1578c2ecf20Sopenharmony_ci u8 clock = inb(high_16 + 0x11); 1588c2ecf20Sopenharmony_ci 1598c2ecf20Sopenharmony_ci outb(clock | (hwif->channel ? 0x08 : 0x02), high_16 + 0x11); 1608c2ecf20Sopenharmony_ci word_count = (blk_rq_sectors(rq) << 8); 1618c2ecf20Sopenharmony_ci word_count = (rq_data_dir(rq) == READ) ? 1628c2ecf20Sopenharmony_ci word_count | 0x05000000 : 1638c2ecf20Sopenharmony_ci word_count | 0x06000000; 1648c2ecf20Sopenharmony_ci outl(word_count, atapi_reg); 1658c2ecf20Sopenharmony_ci } 1668c2ecf20Sopenharmony_ci ide_dma_start(drive); 1678c2ecf20Sopenharmony_ci} 1688c2ecf20Sopenharmony_ci 1698c2ecf20Sopenharmony_cistatic int pdc202xx_dma_end(ide_drive_t *drive) 1708c2ecf20Sopenharmony_ci{ 1718c2ecf20Sopenharmony_ci if (drive->media != ide_disk || (drive->dev_flags & IDE_DFLAG_LBA48)) { 1728c2ecf20Sopenharmony_ci ide_hwif_t *hwif = drive->hwif; 1738c2ecf20Sopenharmony_ci unsigned long high_16 = hwif->extra_base - 16; 1748c2ecf20Sopenharmony_ci unsigned long atapi_reg = high_16 + (hwif->channel ? 0x24 : 0x20); 1758c2ecf20Sopenharmony_ci u8 clock = 0; 1768c2ecf20Sopenharmony_ci 1778c2ecf20Sopenharmony_ci outl(0, atapi_reg); /* zero out extra */ 1788c2ecf20Sopenharmony_ci clock = inb(high_16 + 0x11); 1798c2ecf20Sopenharmony_ci outb(clock & ~(hwif->channel ? 0x08:0x02), high_16 + 0x11); 1808c2ecf20Sopenharmony_ci } 1818c2ecf20Sopenharmony_ci if (drive->current_speed > XFER_UDMA_2) 1828c2ecf20Sopenharmony_ci pdc_old_disable_66MHz_clock(drive->hwif); 1838c2ecf20Sopenharmony_ci return ide_dma_end(drive); 1848c2ecf20Sopenharmony_ci} 1858c2ecf20Sopenharmony_ci 1868c2ecf20Sopenharmony_cistatic int init_chipset_pdc202xx(struct pci_dev *dev) 1878c2ecf20Sopenharmony_ci{ 1888c2ecf20Sopenharmony_ci unsigned long dmabase = pci_resource_start(dev, 4); 1898c2ecf20Sopenharmony_ci u8 udma_speed_flag = 0, primary_mode = 0, secondary_mode = 0; 1908c2ecf20Sopenharmony_ci 1918c2ecf20Sopenharmony_ci if (dmabase == 0) 1928c2ecf20Sopenharmony_ci goto out; 1938c2ecf20Sopenharmony_ci 1948c2ecf20Sopenharmony_ci udma_speed_flag = inb(dmabase | 0x1f); 1958c2ecf20Sopenharmony_ci primary_mode = inb(dmabase | 0x1a); 1968c2ecf20Sopenharmony_ci secondary_mode = inb(dmabase | 0x1b); 1978c2ecf20Sopenharmony_ci printk(KERN_INFO "%s: (U)DMA Burst Bit %sABLED " \ 1988c2ecf20Sopenharmony_ci "Primary %s Mode " \ 1998c2ecf20Sopenharmony_ci "Secondary %s Mode.\n", pci_name(dev), 2008c2ecf20Sopenharmony_ci (udma_speed_flag & 1) ? "EN" : "DIS", 2018c2ecf20Sopenharmony_ci (primary_mode & 1) ? "MASTER" : "PCI", 2028c2ecf20Sopenharmony_ci (secondary_mode & 1) ? "MASTER" : "PCI" ); 2038c2ecf20Sopenharmony_ci 2048c2ecf20Sopenharmony_ci if (!(udma_speed_flag & 1)) { 2058c2ecf20Sopenharmony_ci printk(KERN_INFO "%s: FORCING BURST BIT 0x%02x->0x%02x ", 2068c2ecf20Sopenharmony_ci pci_name(dev), udma_speed_flag, 2078c2ecf20Sopenharmony_ci (udma_speed_flag|1)); 2088c2ecf20Sopenharmony_ci outb(udma_speed_flag | 1, dmabase | 0x1f); 2098c2ecf20Sopenharmony_ci printk("%sACTIVE\n", (inb(dmabase | 0x1f) & 1) ? "" : "IN"); 2108c2ecf20Sopenharmony_ci } 2118c2ecf20Sopenharmony_ciout: 2128c2ecf20Sopenharmony_ci return 0; 2138c2ecf20Sopenharmony_ci} 2148c2ecf20Sopenharmony_ci 2158c2ecf20Sopenharmony_cistatic void pdc202ata4_fixup_irq(struct pci_dev *dev, const char *name) 2168c2ecf20Sopenharmony_ci{ 2178c2ecf20Sopenharmony_ci if ((dev->class >> 8) != PCI_CLASS_STORAGE_IDE) { 2188c2ecf20Sopenharmony_ci u8 irq = 0, irq2 = 0; 2198c2ecf20Sopenharmony_ci pci_read_config_byte(dev, PCI_INTERRUPT_LINE, &irq); 2208c2ecf20Sopenharmony_ci /* 0xbc */ 2218c2ecf20Sopenharmony_ci pci_read_config_byte(dev, (PCI_INTERRUPT_LINE)|0x80, &irq2); 2228c2ecf20Sopenharmony_ci if (irq != irq2) { 2238c2ecf20Sopenharmony_ci pci_write_config_byte(dev, 2248c2ecf20Sopenharmony_ci (PCI_INTERRUPT_LINE)|0x80, irq); /* 0xbc */ 2258c2ecf20Sopenharmony_ci printk(KERN_INFO "%s %s: PCI config space interrupt " 2268c2ecf20Sopenharmony_ci "mirror fixed\n", name, pci_name(dev)); 2278c2ecf20Sopenharmony_ci } 2288c2ecf20Sopenharmony_ci } 2298c2ecf20Sopenharmony_ci} 2308c2ecf20Sopenharmony_ci 2318c2ecf20Sopenharmony_ci#define IDE_HFLAGS_PDC202XX \ 2328c2ecf20Sopenharmony_ci (IDE_HFLAG_ERROR_STOPS_FIFO | \ 2338c2ecf20Sopenharmony_ci IDE_HFLAG_OFF_BOARD) 2348c2ecf20Sopenharmony_ci 2358c2ecf20Sopenharmony_cistatic const struct ide_port_ops pdc20246_port_ops = { 2368c2ecf20Sopenharmony_ci .set_pio_mode = pdc202xx_set_pio_mode, 2378c2ecf20Sopenharmony_ci .set_dma_mode = pdc202xx_set_mode, 2388c2ecf20Sopenharmony_ci .test_irq = pdc202xx_test_irq, 2398c2ecf20Sopenharmony_ci}; 2408c2ecf20Sopenharmony_ci 2418c2ecf20Sopenharmony_cistatic const struct ide_port_ops pdc2026x_port_ops = { 2428c2ecf20Sopenharmony_ci .set_pio_mode = pdc202xx_set_pio_mode, 2438c2ecf20Sopenharmony_ci .set_dma_mode = pdc202xx_set_mode, 2448c2ecf20Sopenharmony_ci .test_irq = pdc202xx_test_irq, 2458c2ecf20Sopenharmony_ci .cable_detect = pdc2026x_cable_detect, 2468c2ecf20Sopenharmony_ci}; 2478c2ecf20Sopenharmony_ci 2488c2ecf20Sopenharmony_cistatic const struct ide_dma_ops pdc2026x_dma_ops = { 2498c2ecf20Sopenharmony_ci .dma_host_set = ide_dma_host_set, 2508c2ecf20Sopenharmony_ci .dma_setup = ide_dma_setup, 2518c2ecf20Sopenharmony_ci .dma_start = pdc202xx_dma_start, 2528c2ecf20Sopenharmony_ci .dma_end = pdc202xx_dma_end, 2538c2ecf20Sopenharmony_ci .dma_test_irq = ide_dma_test_irq, 2548c2ecf20Sopenharmony_ci .dma_lost_irq = ide_dma_lost_irq, 2558c2ecf20Sopenharmony_ci .dma_timer_expiry = ide_dma_sff_timer_expiry, 2568c2ecf20Sopenharmony_ci .dma_sff_read_status = ide_dma_sff_read_status, 2578c2ecf20Sopenharmony_ci}; 2588c2ecf20Sopenharmony_ci 2598c2ecf20Sopenharmony_ci#define DECLARE_PDC2026X_DEV(udma, sectors) \ 2608c2ecf20Sopenharmony_ci { \ 2618c2ecf20Sopenharmony_ci .name = DRV_NAME, \ 2628c2ecf20Sopenharmony_ci .init_chipset = init_chipset_pdc202xx, \ 2638c2ecf20Sopenharmony_ci .init_hwif = pdc2026x_init_hwif, \ 2648c2ecf20Sopenharmony_ci .port_ops = &pdc2026x_port_ops, \ 2658c2ecf20Sopenharmony_ci .dma_ops = &pdc2026x_dma_ops, \ 2668c2ecf20Sopenharmony_ci .host_flags = IDE_HFLAGS_PDC202XX, \ 2678c2ecf20Sopenharmony_ci .pio_mask = ATA_PIO4, \ 2688c2ecf20Sopenharmony_ci .mwdma_mask = ATA_MWDMA2, \ 2698c2ecf20Sopenharmony_ci .udma_mask = udma, \ 2708c2ecf20Sopenharmony_ci .max_sectors = sectors, \ 2718c2ecf20Sopenharmony_ci } 2728c2ecf20Sopenharmony_ci 2738c2ecf20Sopenharmony_cistatic const struct ide_port_info pdc202xx_chipsets[] = { 2748c2ecf20Sopenharmony_ci { /* 0: PDC20246 */ 2758c2ecf20Sopenharmony_ci .name = DRV_NAME, 2768c2ecf20Sopenharmony_ci .init_chipset = init_chipset_pdc202xx, 2778c2ecf20Sopenharmony_ci .port_ops = &pdc20246_port_ops, 2788c2ecf20Sopenharmony_ci .dma_ops = &sff_dma_ops, 2798c2ecf20Sopenharmony_ci .host_flags = IDE_HFLAGS_PDC202XX, 2808c2ecf20Sopenharmony_ci .pio_mask = ATA_PIO4, 2818c2ecf20Sopenharmony_ci .mwdma_mask = ATA_MWDMA2, 2828c2ecf20Sopenharmony_ci .udma_mask = ATA_UDMA2, 2838c2ecf20Sopenharmony_ci }, 2848c2ecf20Sopenharmony_ci 2858c2ecf20Sopenharmony_ci /* 1: PDC2026{2,3} */ 2868c2ecf20Sopenharmony_ci DECLARE_PDC2026X_DEV(ATA_UDMA4, 0), 2878c2ecf20Sopenharmony_ci /* 2: PDC2026{5,7}: UDMA5, limit LBA48 requests to 256 sectors */ 2888c2ecf20Sopenharmony_ci DECLARE_PDC2026X_DEV(ATA_UDMA5, 256), 2898c2ecf20Sopenharmony_ci}; 2908c2ecf20Sopenharmony_ci 2918c2ecf20Sopenharmony_ci/** 2928c2ecf20Sopenharmony_ci * pdc202xx_init_one - called when a PDC202xx is found 2938c2ecf20Sopenharmony_ci * @dev: the pdc202xx device 2948c2ecf20Sopenharmony_ci * @id: the matching pci id 2958c2ecf20Sopenharmony_ci * 2968c2ecf20Sopenharmony_ci * Called when the PCI registration layer (or the IDE initialization) 2978c2ecf20Sopenharmony_ci * finds a device matching our IDE device tables. 2988c2ecf20Sopenharmony_ci */ 2998c2ecf20Sopenharmony_ci 3008c2ecf20Sopenharmony_cistatic int pdc202xx_init_one(struct pci_dev *dev, 3018c2ecf20Sopenharmony_ci const struct pci_device_id *id) 3028c2ecf20Sopenharmony_ci{ 3038c2ecf20Sopenharmony_ci const struct ide_port_info *d; 3048c2ecf20Sopenharmony_ci u8 idx = id->driver_data; 3058c2ecf20Sopenharmony_ci 3068c2ecf20Sopenharmony_ci d = &pdc202xx_chipsets[idx]; 3078c2ecf20Sopenharmony_ci 3088c2ecf20Sopenharmony_ci if (idx < 2) 3098c2ecf20Sopenharmony_ci pdc202ata4_fixup_irq(dev, d->name); 3108c2ecf20Sopenharmony_ci 3118c2ecf20Sopenharmony_ci if (dev->vendor == PCI_DEVICE_ID_PROMISE_20265) { 3128c2ecf20Sopenharmony_ci struct pci_dev *bridge = dev->bus->self; 3138c2ecf20Sopenharmony_ci 3148c2ecf20Sopenharmony_ci if (bridge && 3158c2ecf20Sopenharmony_ci bridge->vendor == PCI_VENDOR_ID_INTEL && 3168c2ecf20Sopenharmony_ci (bridge->device == PCI_DEVICE_ID_INTEL_I960 || 3178c2ecf20Sopenharmony_ci bridge->device == PCI_DEVICE_ID_INTEL_I960RM)) { 3188c2ecf20Sopenharmony_ci printk(KERN_INFO DRV_NAME " %s: skipping Promise " 3198c2ecf20Sopenharmony_ci "PDC20265 attached to I2O RAID controller\n", 3208c2ecf20Sopenharmony_ci pci_name(dev)); 3218c2ecf20Sopenharmony_ci return -ENODEV; 3228c2ecf20Sopenharmony_ci } 3238c2ecf20Sopenharmony_ci } 3248c2ecf20Sopenharmony_ci 3258c2ecf20Sopenharmony_ci return ide_pci_init_one(dev, d, NULL); 3268c2ecf20Sopenharmony_ci} 3278c2ecf20Sopenharmony_ci 3288c2ecf20Sopenharmony_cistatic const struct pci_device_id pdc202xx_pci_tbl[] = { 3298c2ecf20Sopenharmony_ci { PCI_VDEVICE(PROMISE, PCI_DEVICE_ID_PROMISE_20246), 0 }, 3308c2ecf20Sopenharmony_ci { PCI_VDEVICE(PROMISE, PCI_DEVICE_ID_PROMISE_20262), 1 }, 3318c2ecf20Sopenharmony_ci { PCI_VDEVICE(PROMISE, PCI_DEVICE_ID_PROMISE_20263), 1 }, 3328c2ecf20Sopenharmony_ci { PCI_VDEVICE(PROMISE, PCI_DEVICE_ID_PROMISE_20265), 2 }, 3338c2ecf20Sopenharmony_ci { PCI_VDEVICE(PROMISE, PCI_DEVICE_ID_PROMISE_20267), 2 }, 3348c2ecf20Sopenharmony_ci { 0, }, 3358c2ecf20Sopenharmony_ci}; 3368c2ecf20Sopenharmony_ciMODULE_DEVICE_TABLE(pci, pdc202xx_pci_tbl); 3378c2ecf20Sopenharmony_ci 3388c2ecf20Sopenharmony_cistatic struct pci_driver pdc202xx_pci_driver = { 3398c2ecf20Sopenharmony_ci .name = "Promise_Old_IDE", 3408c2ecf20Sopenharmony_ci .id_table = pdc202xx_pci_tbl, 3418c2ecf20Sopenharmony_ci .probe = pdc202xx_init_one, 3428c2ecf20Sopenharmony_ci .remove = ide_pci_remove, 3438c2ecf20Sopenharmony_ci .suspend = ide_pci_suspend, 3448c2ecf20Sopenharmony_ci .resume = ide_pci_resume, 3458c2ecf20Sopenharmony_ci}; 3468c2ecf20Sopenharmony_ci 3478c2ecf20Sopenharmony_cistatic int __init pdc202xx_ide_init(void) 3488c2ecf20Sopenharmony_ci{ 3498c2ecf20Sopenharmony_ci return ide_pci_register_driver(&pdc202xx_pci_driver); 3508c2ecf20Sopenharmony_ci} 3518c2ecf20Sopenharmony_ci 3528c2ecf20Sopenharmony_cistatic void __exit pdc202xx_ide_exit(void) 3538c2ecf20Sopenharmony_ci{ 3548c2ecf20Sopenharmony_ci pci_unregister_driver(&pdc202xx_pci_driver); 3558c2ecf20Sopenharmony_ci} 3568c2ecf20Sopenharmony_ci 3578c2ecf20Sopenharmony_cimodule_init(pdc202xx_ide_init); 3588c2ecf20Sopenharmony_cimodule_exit(pdc202xx_ide_exit); 3598c2ecf20Sopenharmony_ci 3608c2ecf20Sopenharmony_ciMODULE_AUTHOR("Andre Hedrick, Frank Tiernan, Bartlomiej Zolnierkiewicz"); 3618c2ecf20Sopenharmony_ciMODULE_DESCRIPTION("PCI driver module for older Promise IDE"); 3628c2ecf20Sopenharmony_ciMODULE_LICENSE("GPL"); 363