11da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 21da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Copyright (C) 1998-2002 Andre Hedrick <andre@linux-ide.org> 3669165daad2ec839df85b8c5f7bc155e76a2f404Sergei Shtylyov * Copyright (C) 2006-2007, 2009 MontaVista Software, Inc. 4a337c2272731d538827153b32f547ef7c131a4cbBartlomiej Zolnierkiewicz * Copyright (C) 2007-2010 Bartlomiej Zolnierkiewicz 51da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 61da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Portions Copyright (C) 1999 Promise Technology, Inc. 71da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Author: Frank Tiernan (frankt@promise.com) 81da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Released under terms of General Public License 91da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/types.h> 121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/module.h> 131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/kernel.h> 141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/delay.h> 151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/blkdev.h> 161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/pci.h> 171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/init.h> 181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/ide.h> 191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/io.h> 211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 22ced3ec8aa7d0fa3300187ee47c144a22ccfc974eBartlomiej Zolnierkiewicz#define DRV_NAME "pdc202xx_old" 23ced3ec8aa7d0fa3300187ee47c144a22ccfc974eBartlomiej Zolnierkiewicz 248776168ca2151850164af1de5565d01f7b8b2c53Bartlomiej Zolnierkiewiczstatic void pdc202xx_set_mode(ide_hwif_t *hwif, ide_drive_t *drive) 251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 2636501650ec45b1db308c3b51886044863be2d762Bartlomiej Zolnierkiewicz struct pci_dev *dev = to_pci_dev(hwif->dev); 271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u8 drive_pci = 0x60 + (drive->dn << 2); 288776168ca2151850164af1de5565d01f7b8b2c53Bartlomiej Zolnierkiewicz const u8 speed = drive->dma_mode; 291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 304fce3164b84d5b014acbf5a3f57eb3650e154f5bBartlomiej Zolnierkiewicz u8 AP = 0, BP = 0, CP = 0; 311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u8 TA = 0, TB = 0, TC = 0; 321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 334fce3164b84d5b014acbf5a3f57eb3650e154f5bBartlomiej Zolnierkiewicz pci_read_config_byte(dev, drive_pci, &AP); 344fce3164b84d5b014acbf5a3f57eb3650e154f5bBartlomiej Zolnierkiewicz pci_read_config_byte(dev, drive_pci + 1, &BP); 354fce3164b84d5b014acbf5a3f57eb3650e154f5bBartlomiej Zolnierkiewicz pci_read_config_byte(dev, drive_pci + 2, &CP); 361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds switch(speed) { 381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case XFER_UDMA_5: 391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case XFER_UDMA_4: TB = 0x20; TC = 0x01; break; 401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case XFER_UDMA_2: TB = 0x20; TC = 0x01; break; 411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case XFER_UDMA_3: 421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case XFER_UDMA_1: TB = 0x40; TC = 0x02; break; 431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case XFER_UDMA_0: 441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case XFER_MW_DMA_2: TB = 0x60; TC = 0x03; break; 451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case XFER_MW_DMA_1: TB = 0x60; TC = 0x04; break; 464fce3164b84d5b014acbf5a3f57eb3650e154f5bBartlomiej Zolnierkiewicz case XFER_MW_DMA_0: TB = 0xE0; TC = 0x0F; break; 471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case XFER_PIO_4: TA = 0x01; TB = 0x04; break; 481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case XFER_PIO_3: TA = 0x02; TB = 0x06; break; 491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case XFER_PIO_2: TA = 0x03; TB = 0x08; break; 501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case XFER_PIO_1: TA = 0x05; TB = 0x0C; break; 511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case XFER_PIO_0: 521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds default: TA = 0x09; TB = 0x13; break; 531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (speed < XFER_SW_DMA_0) { 564fce3164b84d5b014acbf5a3f57eb3650e154f5bBartlomiej Zolnierkiewicz /* 574fce3164b84d5b014acbf5a3f57eb3650e154f5bBartlomiej Zolnierkiewicz * preserve SYNC_INT / ERDDY_EN bits while clearing 584fce3164b84d5b014acbf5a3f57eb3650e154f5bBartlomiej Zolnierkiewicz * Prefetch_EN / IORDY_EN / PA[3:0] bits of register A 594fce3164b84d5b014acbf5a3f57eb3650e154f5bBartlomiej Zolnierkiewicz */ 604fce3164b84d5b014acbf5a3f57eb3650e154f5bBartlomiej Zolnierkiewicz AP &= ~0x3f; 61c9ef59ff01b6bd1c7360a64fcc8556a1193c2ed0Bartlomiej Zolnierkiewicz if (ide_pio_need_iordy(drive, speed - XFER_PIO_0)) 624fce3164b84d5b014acbf5a3f57eb3650e154f5bBartlomiej Zolnierkiewicz AP |= 0x20; /* set IORDY_EN bit */ 634fce3164b84d5b014acbf5a3f57eb3650e154f5bBartlomiej Zolnierkiewicz if (drive->media == ide_disk) 644fce3164b84d5b014acbf5a3f57eb3650e154f5bBartlomiej Zolnierkiewicz AP |= 0x10; /* set Prefetch_EN bit */ 654fce3164b84d5b014acbf5a3f57eb3650e154f5bBartlomiej Zolnierkiewicz /* clear PB[4:0] bits of register B */ 664fce3164b84d5b014acbf5a3f57eb3650e154f5bBartlomiej Zolnierkiewicz BP &= ~0x1f; 674fce3164b84d5b014acbf5a3f57eb3650e154f5bBartlomiej Zolnierkiewicz pci_write_config_byte(dev, drive_pci, AP | TA); 684fce3164b84d5b014acbf5a3f57eb3650e154f5bBartlomiej Zolnierkiewicz pci_write_config_byte(dev, drive_pci + 1, BP | TB); 691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else { 704fce3164b84d5b014acbf5a3f57eb3650e154f5bBartlomiej Zolnierkiewicz /* clear MB[2:0] bits of register B */ 714fce3164b84d5b014acbf5a3f57eb3650e154f5bBartlomiej Zolnierkiewicz BP &= ~0xe0; 724fce3164b84d5b014acbf5a3f57eb3650e154f5bBartlomiej Zolnierkiewicz /* clear MC[3:0] bits of register C */ 734fce3164b84d5b014acbf5a3f57eb3650e154f5bBartlomiej Zolnierkiewicz CP &= ~0x0f; 744fce3164b84d5b014acbf5a3f57eb3650e154f5bBartlomiej Zolnierkiewicz pci_write_config_byte(dev, drive_pci + 1, BP | TB); 754fce3164b84d5b014acbf5a3f57eb3650e154f5bBartlomiej Zolnierkiewicz pci_write_config_byte(dev, drive_pci + 2, CP | TC); 761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 79e085b3cae85af47eb0a3eda3186bd898310fb322Bartlomiej Zolnierkiewiczstatic void pdc202xx_set_pio_mode(ide_hwif_t *hwif, ide_drive_t *drive) 801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 818776168ca2151850164af1de5565d01f7b8b2c53Bartlomiej Zolnierkiewicz drive->dma_mode = drive->pio_mode; 828776168ca2151850164af1de5565d01f7b8b2c53Bartlomiej Zolnierkiewicz pdc202xx_set_mode(hwif, drive); 831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 85e0321fbe6d34b4bb514fb6daff9e0859e5d76001Sergei Shtylyovstatic int pdc202xx_test_irq(ide_hwif_t *hwif) 86e0321fbe6d34b4bb514fb6daff9e0859e5d76001Sergei Shtylyov{ 87e0321fbe6d34b4bb514fb6daff9e0859e5d76001Sergei Shtylyov struct pci_dev *dev = to_pci_dev(hwif->dev); 88e0321fbe6d34b4bb514fb6daff9e0859e5d76001Sergei Shtylyov unsigned long high_16 = pci_resource_start(dev, 4); 89e0321fbe6d34b4bb514fb6daff9e0859e5d76001Sergei Shtylyov u8 sc1d = inb(high_16 + 0x1d); 90e0321fbe6d34b4bb514fb6daff9e0859e5d76001Sergei Shtylyov 91e0321fbe6d34b4bb514fb6daff9e0859e5d76001Sergei Shtylyov if (hwif->channel) { 92e0321fbe6d34b4bb514fb6daff9e0859e5d76001Sergei Shtylyov /* 93e0321fbe6d34b4bb514fb6daff9e0859e5d76001Sergei Shtylyov * bit 7: error, bit 6: interrupting, 94e0321fbe6d34b4bb514fb6daff9e0859e5d76001Sergei Shtylyov * bit 5: FIFO full, bit 4: FIFO empty 95e0321fbe6d34b4bb514fb6daff9e0859e5d76001Sergei Shtylyov */ 96f693be4d8a00431b53a59d74aefdb3f7ae92f662Sergei Shtylyov return (sc1d & 0x40) ? 1 : 0; 97e0321fbe6d34b4bb514fb6daff9e0859e5d76001Sergei Shtylyov } else { 98e0321fbe6d34b4bb514fb6daff9e0859e5d76001Sergei Shtylyov /* 99e0321fbe6d34b4bb514fb6daff9e0859e5d76001Sergei Shtylyov * bit 3: error, bit 2: interrupting, 100e0321fbe6d34b4bb514fb6daff9e0859e5d76001Sergei Shtylyov * bit 1: FIFO full, bit 0: FIFO empty 101e0321fbe6d34b4bb514fb6daff9e0859e5d76001Sergei Shtylyov */ 102f693be4d8a00431b53a59d74aefdb3f7ae92f662Sergei Shtylyov return (sc1d & 0x04) ? 1 : 0; 103e0321fbe6d34b4bb514fb6daff9e0859e5d76001Sergei Shtylyov } 104e0321fbe6d34b4bb514fb6daff9e0859e5d76001Sergei Shtylyov} 105e0321fbe6d34b4bb514fb6daff9e0859e5d76001Sergei Shtylyov 106f454cbe8cd38b6d447e74ddaf012017fea42717eBartlomiej Zolnierkiewiczstatic u8 pdc2026x_cable_detect(ide_hwif_t *hwif) 1071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 10836501650ec45b1db308c3b51886044863be2d762Bartlomiej Zolnierkiewicz struct pci_dev *dev = to_pci_dev(hwif->dev); 1091bee4d1dce2d76bcf0bf9565298c62666de0fa1dAlan Cox u16 CIS, mask = hwif->channel ? (1 << 11) : (1 << 10); 11049521f97ccd3c2bf6e71a91cea8fe65d170fa4fbBartlomiej Zolnierkiewicz 11136501650ec45b1db308c3b51886044863be2d762Bartlomiej Zolnierkiewicz pci_read_config_word(dev, 0x50, &CIS); 11249521f97ccd3c2bf6e71a91cea8fe65d170fa4fbBartlomiej Zolnierkiewicz 11349521f97ccd3c2bf6e71a91cea8fe65d170fa4fbBartlomiej Zolnierkiewicz return (CIS & mask) ? ATA_CBL_PATA40 : ATA_CBL_PATA80; 1141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 1171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Set the control register to use the 66MHz system 1181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * clock for UDMA 3/4/5 mode operation when necessary. 1191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 1204fce3164b84d5b014acbf5a3f57eb3650e154f5bBartlomiej Zolnierkiewicz * FIXME: this register is shared by both channels, some locking is needed 1214fce3164b84d5b014acbf5a3f57eb3650e154f5bBartlomiej Zolnierkiewicz * 1221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * It may also be possible to leave the 66MHz clock on 1231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * and readjust the timing parameters. 1241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 1251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void pdc_old_enable_66MHz_clock(ide_hwif_t *hwif) 1261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1271c029fd658baa2442e8e51dc9c819301cad95777Bartlomiej Zolnierkiewicz unsigned long clock_reg = hwif->extra_base + 0x01; 1280ecdca26e556eae9668ce6de9554757dddb942efBartlomiej Zolnierkiewicz u8 clock = inb(clock_reg); 1291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1300ecdca26e556eae9668ce6de9554757dddb942efBartlomiej Zolnierkiewicz outb(clock | (hwif->channel ? 0x08 : 0x02), clock_reg); 1311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void pdc_old_disable_66MHz_clock(ide_hwif_t *hwif) 1341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1351c029fd658baa2442e8e51dc9c819301cad95777Bartlomiej Zolnierkiewicz unsigned long clock_reg = hwif->extra_base + 0x01; 1360ecdca26e556eae9668ce6de9554757dddb942efBartlomiej Zolnierkiewicz u8 clock = inb(clock_reg); 1371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1380ecdca26e556eae9668ce6de9554757dddb942efBartlomiej Zolnierkiewicz outb(clock & ~(hwif->channel ? 0x08 : 0x02), clock_reg); 1391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 141a337c2272731d538827153b32f547ef7c131a4cbBartlomiej Zolnierkiewiczstatic void pdc2026x_init_hwif(ide_hwif_t *hwif) 142a337c2272731d538827153b32f547ef7c131a4cbBartlomiej Zolnierkiewicz{ 143a337c2272731d538827153b32f547ef7c131a4cbBartlomiej Zolnierkiewicz pdc_old_disable_66MHz_clock(hwif); 144a337c2272731d538827153b32f547ef7c131a4cbBartlomiej Zolnierkiewicz} 145a337c2272731d538827153b32f547ef7c131a4cbBartlomiej Zolnierkiewicz 1465e37bdc081a980dd0d669e6387bcf15ca9666f81Bartlomiej Zolnierkiewiczstatic void pdc202xx_dma_start(ide_drive_t *drive) 1471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (drive->current_speed > XFER_UDMA_2) 1491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds pdc_old_enable_66MHz_clock(drive->hwif); 15097100fc816badbbc162644cfde7ad39ae9211fb4Bartlomiej Zolnierkiewicz if (drive->media != ide_disk || (drive->dev_flags & IDE_DFLAG_LBA48)) { 151898ec223fea2a2df88035e58dbf50f493577e225Bartlomiej Zolnierkiewicz ide_hwif_t *hwif = drive->hwif; 152b65fac32cfe3b2f98cd472fef400bd1c1340de23Bartlomiej Zolnierkiewicz struct request *rq = hwif->rq; 1531c029fd658baa2442e8e51dc9c819301cad95777Bartlomiej Zolnierkiewicz unsigned long high_16 = hwif->extra_base - 16; 1541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned long atapi_reg = high_16 + (hwif->channel ? 0x24 : 0x20); 1551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u32 word_count = 0; 1560ecdca26e556eae9668ce6de9554757dddb942efBartlomiej Zolnierkiewicz u8 clock = inb(high_16 + 0x11); 1571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1580ecdca26e556eae9668ce6de9554757dddb942efBartlomiej Zolnierkiewicz outb(clock | (hwif->channel ? 0x08 : 0x02), high_16 + 0x11); 1599780e2dd8254351f6cbe11304849126b51dbd561Tejun Heo word_count = (blk_rq_sectors(rq) << 8); 1601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds word_count = (rq_data_dir(rq) == READ) ? 1611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds word_count | 0x05000000 : 1621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds word_count | 0x06000000; 1630ecdca26e556eae9668ce6de9554757dddb942efBartlomiej Zolnierkiewicz outl(word_count, atapi_reg); 1641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ide_dma_start(drive); 1661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1685e37bdc081a980dd0d669e6387bcf15ca9666f81Bartlomiej Zolnierkiewiczstatic int pdc202xx_dma_end(ide_drive_t *drive) 1691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 17097100fc816badbbc162644cfde7ad39ae9211fb4Bartlomiej Zolnierkiewicz if (drive->media != ide_disk || (drive->dev_flags & IDE_DFLAG_LBA48)) { 171898ec223fea2a2df88035e58dbf50f493577e225Bartlomiej Zolnierkiewicz ide_hwif_t *hwif = drive->hwif; 1721c029fd658baa2442e8e51dc9c819301cad95777Bartlomiej Zolnierkiewicz unsigned long high_16 = hwif->extra_base - 16; 1731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned long atapi_reg = high_16 + (hwif->channel ? 0x24 : 0x20); 1741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u8 clock = 0; 1751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1760ecdca26e556eae9668ce6de9554757dddb942efBartlomiej Zolnierkiewicz outl(0, atapi_reg); /* zero out extra */ 1770ecdca26e556eae9668ce6de9554757dddb942efBartlomiej Zolnierkiewicz clock = inb(high_16 + 0x11); 1780ecdca26e556eae9668ce6de9554757dddb942efBartlomiej Zolnierkiewicz outb(clock & ~(hwif->channel ? 0x08:0x02), high_16 + 0x11); 1791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (drive->current_speed > XFER_UDMA_2) 1811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds pdc_old_disable_66MHz_clock(drive->hwif); 182653bcf5292a9ac4ffc07315198f0ef995e0646a8Bartlomiej Zolnierkiewicz return ide_dma_end(drive); 1831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1852ed0ef543ae3f3ea4f8bd0433fb1fed22625a309Bartlomiej Zolnierkiewiczstatic int init_chipset_pdc202xx(struct pci_dev *dev) 1861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 18773369d2a15cfe7dceae89a9e70e3d442e4c21576Bartlomiej Zolnierkiewicz unsigned long dmabase = pci_resource_start(dev, 4); 1881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u8 udma_speed_flag = 0, primary_mode = 0, secondary_mode = 0; 1891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 19073369d2a15cfe7dceae89a9e70e3d442e4c21576Bartlomiej Zolnierkiewicz if (dmabase == 0) 19173369d2a15cfe7dceae89a9e70e3d442e4c21576Bartlomiej Zolnierkiewicz goto out; 1921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1930ecdca26e556eae9668ce6de9554757dddb942efBartlomiej Zolnierkiewicz udma_speed_flag = inb(dmabase | 0x1f); 1940ecdca26e556eae9668ce6de9554757dddb942efBartlomiej Zolnierkiewicz primary_mode = inb(dmabase | 0x1a); 1950ecdca26e556eae9668ce6de9554757dddb942efBartlomiej Zolnierkiewicz secondary_mode = inb(dmabase | 0x1b); 1961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk(KERN_INFO "%s: (U)DMA Burst Bit %sABLED " \ 1971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "Primary %s Mode " \ 1985e59c236846df444860ffc8b852117f9ff65c101Bartlomiej Zolnierkiewicz "Secondary %s Mode.\n", pci_name(dev), 1991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds (udma_speed_flag & 1) ? "EN" : "DIS", 2001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds (primary_mode & 1) ? "MASTER" : "PCI", 2011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds (secondary_mode & 1) ? "MASTER" : "PCI" ); 2021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!(udma_speed_flag & 1)) { 2041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk(KERN_INFO "%s: FORCING BURST BIT 0x%02x->0x%02x ", 2055e59c236846df444860ffc8b852117f9ff65c101Bartlomiej Zolnierkiewicz pci_name(dev), udma_speed_flag, 2061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds (udma_speed_flag|1)); 2070ecdca26e556eae9668ce6de9554757dddb942efBartlomiej Zolnierkiewicz outb(udma_speed_flag | 1, dmabase | 0x1f); 2080ecdca26e556eae9668ce6de9554757dddb942efBartlomiej Zolnierkiewicz printk("%sACTIVE\n", (inb(dmabase | 0x1f) & 1) ? "" : "IN"); 2091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 21073369d2a15cfe7dceae89a9e70e3d442e4c21576Bartlomiej Zolnierkiewiczout: 2112ed0ef543ae3f3ea4f8bd0433fb1fed22625a309Bartlomiej Zolnierkiewicz return 0; 2121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 2131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 21497f84baa030c9e2d235e26e4a96fe7e294049cb0Bartlomiej Zolnierkiewiczstatic void __devinit pdc202ata4_fixup_irq(struct pci_dev *dev, 21597f84baa030c9e2d235e26e4a96fe7e294049cb0Bartlomiej Zolnierkiewicz const char *name) 2161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 2171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if ((dev->class >> 8) != PCI_CLASS_STORAGE_IDE) { 2181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u8 irq = 0, irq2 = 0; 2191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds pci_read_config_byte(dev, PCI_INTERRUPT_LINE, &irq); 2201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 0xbc */ 2211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds pci_read_config_byte(dev, (PCI_INTERRUPT_LINE)|0x80, &irq2); 2221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (irq != irq2) { 2231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds pci_write_config_byte(dev, 2241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds (PCI_INTERRUPT_LINE)|0x80, irq); /* 0xbc */ 22528cfd8af52a9ed4e5bd1751ea6bc0b8c870f68ecBartlomiej Zolnierkiewicz printk(KERN_INFO "%s %s: PCI config space interrupt " 22628cfd8af52a9ed4e5bd1751ea6bc0b8c870f68ecBartlomiej Zolnierkiewicz "mirror fixed\n", name, pci_name(dev)); 2271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 2301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2314db90a145292327b95b03f6dcd3352327235cc36Bartlomiej Zolnierkiewicz#define IDE_HFLAGS_PDC202XX \ 2324db90a145292327b95b03f6dcd3352327235cc36Bartlomiej Zolnierkiewicz (IDE_HFLAG_ERROR_STOPS_FIFO | \ 2334db90a145292327b95b03f6dcd3352327235cc36Bartlomiej Zolnierkiewicz IDE_HFLAG_OFF_BOARD) 2344db90a145292327b95b03f6dcd3352327235cc36Bartlomiej Zolnierkiewicz 235ac95beedf8bc97b24f9540d4da9952f07221c023Bartlomiej Zolnierkiewiczstatic const struct ide_port_ops pdc20246_port_ops = { 236ac95beedf8bc97b24f9540d4da9952f07221c023Bartlomiej Zolnierkiewicz .set_pio_mode = pdc202xx_set_pio_mode, 237ac95beedf8bc97b24f9540d4da9952f07221c023Bartlomiej Zolnierkiewicz .set_dma_mode = pdc202xx_set_mode, 238e0321fbe6d34b4bb514fb6daff9e0859e5d76001Sergei Shtylyov .test_irq = pdc202xx_test_irq, 239ac95beedf8bc97b24f9540d4da9952f07221c023Bartlomiej Zolnierkiewicz}; 240ac95beedf8bc97b24f9540d4da9952f07221c023Bartlomiej Zolnierkiewicz 241ac95beedf8bc97b24f9540d4da9952f07221c023Bartlomiej Zolnierkiewiczstatic const struct ide_port_ops pdc2026x_port_ops = { 242ac95beedf8bc97b24f9540d4da9952f07221c023Bartlomiej Zolnierkiewicz .set_pio_mode = pdc202xx_set_pio_mode, 243ac95beedf8bc97b24f9540d4da9952f07221c023Bartlomiej Zolnierkiewicz .set_dma_mode = pdc202xx_set_mode, 24463e7cf910542383591318941cb62a246ac191cfeSergei Shtylyov .test_irq = pdc202xx_test_irq, 245ac95beedf8bc97b24f9540d4da9952f07221c023Bartlomiej Zolnierkiewicz .cable_detect = pdc2026x_cable_detect, 246ac95beedf8bc97b24f9540d4da9952f07221c023Bartlomiej Zolnierkiewicz}; 247ac95beedf8bc97b24f9540d4da9952f07221c023Bartlomiej Zolnierkiewicz 248f37afdaca711838b50ecd89b9c15fc745270d77cBartlomiej Zolnierkiewiczstatic const struct ide_dma_ops pdc2026x_dma_ops = { 249f37afdaca711838b50ecd89b9c15fc745270d77cBartlomiej Zolnierkiewicz .dma_host_set = ide_dma_host_set, 250f37afdaca711838b50ecd89b9c15fc745270d77cBartlomiej Zolnierkiewicz .dma_setup = ide_dma_setup, 2515e37bdc081a980dd0d669e6387bcf15ca9666f81Bartlomiej Zolnierkiewicz .dma_start = pdc202xx_dma_start, 2525e37bdc081a980dd0d669e6387bcf15ca9666f81Bartlomiej Zolnierkiewicz .dma_end = pdc202xx_dma_end, 25372b9304f04d0724a25251e9e9041aa95f89c15ddSergei Shtylyov .dma_test_irq = ide_dma_test_irq, 2541221e241e3a6f1ff5b0de03d58d871f7c995781bSergei Shtylyov .dma_lost_irq = ide_dma_lost_irq, 25522117d6eaac50d366d9013c88318a869ea4d8739Bartlomiej Zolnierkiewicz .dma_timer_expiry = ide_dma_sff_timer_expiry, 256592b5315219881c6c0af4785f96456ad2043193aSergei Shtylyov .dma_sff_read_status = ide_dma_sff_read_status, 2575e37bdc081a980dd0d669e6387bcf15ca9666f81Bartlomiej Zolnierkiewicz}; 2585e37bdc081a980dd0d669e6387bcf15ca9666f81Bartlomiej Zolnierkiewicz 2596b4924962c49655494d2c8e9d3faab0e349a3062Bartlomiej Zolnierkiewicz#define DECLARE_PDC2026X_DEV(udma, sectors) \ 2605ef8cb5d9262678d3020a9395afb96592bffe069Bartlomiej Zolnierkiewicz { \ 261ced3ec8aa7d0fa3300187ee47c144a22ccfc974eBartlomiej Zolnierkiewicz .name = DRV_NAME, \ 2625ef8cb5d9262678d3020a9395afb96592bffe069Bartlomiej Zolnierkiewicz .init_chipset = init_chipset_pdc202xx, \ 263a337c2272731d538827153b32f547ef7c131a4cbBartlomiej Zolnierkiewicz .init_hwif = pdc2026x_init_hwif, \ 264ac95beedf8bc97b24f9540d4da9952f07221c023Bartlomiej Zolnierkiewicz .port_ops = &pdc2026x_port_ops, \ 2655e37bdc081a980dd0d669e6387bcf15ca9666f81Bartlomiej Zolnierkiewicz .dma_ops = &pdc2026x_dma_ops, \ 2666b4924962c49655494d2c8e9d3faab0e349a3062Bartlomiej Zolnierkiewicz .host_flags = IDE_HFLAGS_PDC202XX, \ 2675ef8cb5d9262678d3020a9395afb96592bffe069Bartlomiej Zolnierkiewicz .pio_mask = ATA_PIO4, \ 2685ef8cb5d9262678d3020a9395afb96592bffe069Bartlomiej Zolnierkiewicz .mwdma_mask = ATA_MWDMA2, \ 2695ef8cb5d9262678d3020a9395afb96592bffe069Bartlomiej Zolnierkiewicz .udma_mask = udma, \ 2706b4924962c49655494d2c8e9d3faab0e349a3062Bartlomiej Zolnierkiewicz .max_sectors = sectors, \ 2715ef8cb5d9262678d3020a9395afb96592bffe069Bartlomiej Zolnierkiewicz } 2725ef8cb5d9262678d3020a9395afb96592bffe069Bartlomiej Zolnierkiewicz 2738562043606430185cad26d085d46adcc7ad67fd1Bartlomiej Zolnierkiewiczstatic const struct ide_port_info pdc202xx_chipsets[] __devinitdata = { 274ced3ec8aa7d0fa3300187ee47c144a22ccfc974eBartlomiej Zolnierkiewicz { /* 0: PDC20246 */ 275ced3ec8aa7d0fa3300187ee47c144a22ccfc974eBartlomiej Zolnierkiewicz .name = DRV_NAME, 2761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .init_chipset = init_chipset_pdc202xx, 277ac95beedf8bc97b24f9540d4da9952f07221c023Bartlomiej Zolnierkiewicz .port_ops = &pdc20246_port_ops, 27872b9304f04d0724a25251e9e9041aa95f89c15ddSergei Shtylyov .dma_ops = &sff_dma_ops, 2794db90a145292327b95b03f6dcd3352327235cc36Bartlomiej Zolnierkiewicz .host_flags = IDE_HFLAGS_PDC202XX, 2804099d14322149c7a467e4997b87be4ba8eb78697Bartlomiej Zolnierkiewicz .pio_mask = ATA_PIO4, 2815f8b6c34854a966fe5eb7241fde0419d47d5d408Bartlomiej Zolnierkiewicz .mwdma_mask = ATA_MWDMA2, 2825f8b6c34854a966fe5eb7241fde0419d47d5d408Bartlomiej Zolnierkiewicz .udma_mask = ATA_UDMA2, 2835ef8cb5d9262678d3020a9395afb96592bffe069Bartlomiej Zolnierkiewicz }, 2845ef8cb5d9262678d3020a9395afb96592bffe069Bartlomiej Zolnierkiewicz 285ced3ec8aa7d0fa3300187ee47c144a22ccfc974eBartlomiej Zolnierkiewicz /* 1: PDC2026{2,3} */ 286ced3ec8aa7d0fa3300187ee47c144a22ccfc974eBartlomiej Zolnierkiewicz DECLARE_PDC2026X_DEV(ATA_UDMA4, 0), 2876b4924962c49655494d2c8e9d3faab0e349a3062Bartlomiej Zolnierkiewicz /* 2: PDC2026{5,7}: UDMA5, limit LBA48 requests to 256 sectors */ 2886b4924962c49655494d2c8e9d3faab0e349a3062Bartlomiej Zolnierkiewicz DECLARE_PDC2026X_DEV(ATA_UDMA5, 256), 2891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 2901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/** 2921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * pdc202xx_init_one - called when a PDC202xx is found 2931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @dev: the pdc202xx device 2941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @id: the matching pci id 2951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 2961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Called when the PCI registration layer (or the IDE initialization) 2971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * finds a device matching our IDE device tables. 2981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 2991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int __devinit pdc202xx_init_one(struct pci_dev *dev, const struct pci_device_id *id) 3011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 3028562043606430185cad26d085d46adcc7ad67fd1Bartlomiej Zolnierkiewicz const struct ide_port_info *d; 30397f84baa030c9e2d235e26e4a96fe7e294049cb0Bartlomiej Zolnierkiewicz u8 idx = id->driver_data; 30497f84baa030c9e2d235e26e4a96fe7e294049cb0Bartlomiej Zolnierkiewicz 30597f84baa030c9e2d235e26e4a96fe7e294049cb0Bartlomiej Zolnierkiewicz d = &pdc202xx_chipsets[idx]; 30697f84baa030c9e2d235e26e4a96fe7e294049cb0Bartlomiej Zolnierkiewicz 307ced3ec8aa7d0fa3300187ee47c144a22ccfc974eBartlomiej Zolnierkiewicz if (idx < 2) 30897f84baa030c9e2d235e26e4a96fe7e294049cb0Bartlomiej Zolnierkiewicz pdc202ata4_fixup_irq(dev, d->name); 30997f84baa030c9e2d235e26e4a96fe7e294049cb0Bartlomiej Zolnierkiewicz 310ced3ec8aa7d0fa3300187ee47c144a22ccfc974eBartlomiej Zolnierkiewicz if (dev->vendor == PCI_DEVICE_ID_PROMISE_20265) { 31197f84baa030c9e2d235e26e4a96fe7e294049cb0Bartlomiej Zolnierkiewicz struct pci_dev *bridge = dev->bus->self; 3121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 31397f84baa030c9e2d235e26e4a96fe7e294049cb0Bartlomiej Zolnierkiewicz if (bridge && 31497f84baa030c9e2d235e26e4a96fe7e294049cb0Bartlomiej Zolnierkiewicz bridge->vendor == PCI_VENDOR_ID_INTEL && 31597f84baa030c9e2d235e26e4a96fe7e294049cb0Bartlomiej Zolnierkiewicz (bridge->device == PCI_DEVICE_ID_INTEL_I960 || 31697f84baa030c9e2d235e26e4a96fe7e294049cb0Bartlomiej Zolnierkiewicz bridge->device == PCI_DEVICE_ID_INTEL_I960RM)) { 317ced3ec8aa7d0fa3300187ee47c144a22ccfc974eBartlomiej Zolnierkiewicz printk(KERN_INFO DRV_NAME " %s: skipping Promise " 31828cfd8af52a9ed4e5bd1751ea6bc0b8c870f68ecBartlomiej Zolnierkiewicz "PDC20265 attached to I2O RAID controller\n", 31928cfd8af52a9ed4e5bd1751ea6bc0b8c870f68ecBartlomiej Zolnierkiewicz pci_name(dev)); 32097f84baa030c9e2d235e26e4a96fe7e294049cb0Bartlomiej Zolnierkiewicz return -ENODEV; 32197f84baa030c9e2d235e26e4a96fe7e294049cb0Bartlomiej Zolnierkiewicz } 32297f84baa030c9e2d235e26e4a96fe7e294049cb0Bartlomiej Zolnierkiewicz } 32397f84baa030c9e2d235e26e4a96fe7e294049cb0Bartlomiej Zolnierkiewicz 3246cdf6eb357c2681596b7b1672b92396ba82333d4Bartlomiej Zolnierkiewicz return ide_pci_init_one(dev, d, NULL); 3251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 3261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3279cbcc5e3c5d2d0355fed22d00762fd764c81a383Bartlomiej Zolnierkiewiczstatic const struct pci_device_id pdc202xx_pci_tbl[] = { 3289cbcc5e3c5d2d0355fed22d00762fd764c81a383Bartlomiej Zolnierkiewicz { PCI_VDEVICE(PROMISE, PCI_DEVICE_ID_PROMISE_20246), 0 }, 3299cbcc5e3c5d2d0355fed22d00762fd764c81a383Bartlomiej Zolnierkiewicz { PCI_VDEVICE(PROMISE, PCI_DEVICE_ID_PROMISE_20262), 1 }, 330ced3ec8aa7d0fa3300187ee47c144a22ccfc974eBartlomiej Zolnierkiewicz { PCI_VDEVICE(PROMISE, PCI_DEVICE_ID_PROMISE_20263), 1 }, 331ced3ec8aa7d0fa3300187ee47c144a22ccfc974eBartlomiej Zolnierkiewicz { PCI_VDEVICE(PROMISE, PCI_DEVICE_ID_PROMISE_20265), 2 }, 332ced3ec8aa7d0fa3300187ee47c144a22ccfc974eBartlomiej Zolnierkiewicz { PCI_VDEVICE(PROMISE, PCI_DEVICE_ID_PROMISE_20267), 2 }, 3331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { 0, }, 3341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 3351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_DEVICE_TABLE(pci, pdc202xx_pci_tbl); 3361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 337a9ab09e26055a76295548ca36ec00de2f4367d32Bartlomiej Zolnierkiewiczstatic struct pci_driver pdc202xx_pci_driver = { 3381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .name = "Promise_Old_IDE", 3391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .id_table = pdc202xx_pci_tbl, 3401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .probe = pdc202xx_init_one, 341574a1c24b63fdb584935b4924a38b451eeb0880eBartlomiej Zolnierkiewicz .remove = ide_pci_remove, 342feb22b7f8e62b1b987a3a1dbad95af767a1df832Bartlomiej Zolnierkiewicz .suspend = ide_pci_suspend, 343feb22b7f8e62b1b987a3a1dbad95af767a1df832Bartlomiej Zolnierkiewicz .resume = ide_pci_resume, 3441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 3451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 34682ab1eeceba6705cd5a8815c48eb03af1dada744Bartlomiej Zolnierkiewiczstatic int __init pdc202xx_ide_init(void) 3471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 348a9ab09e26055a76295548ca36ec00de2f4367d32Bartlomiej Zolnierkiewicz return ide_pci_register_driver(&pdc202xx_pci_driver); 3491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 3501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 351574a1c24b63fdb584935b4924a38b451eeb0880eBartlomiej Zolnierkiewiczstatic void __exit pdc202xx_ide_exit(void) 352574a1c24b63fdb584935b4924a38b451eeb0880eBartlomiej Zolnierkiewicz{ 353a9ab09e26055a76295548ca36ec00de2f4367d32Bartlomiej Zolnierkiewicz pci_unregister_driver(&pdc202xx_pci_driver); 354574a1c24b63fdb584935b4924a38b451eeb0880eBartlomiej Zolnierkiewicz} 355574a1c24b63fdb584935b4924a38b451eeb0880eBartlomiej Zolnierkiewicz 3561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmodule_init(pdc202xx_ide_init); 357574a1c24b63fdb584935b4924a38b451eeb0880eBartlomiej Zolnierkiewiczmodule_exit(pdc202xx_ide_exit); 3581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 359a337c2272731d538827153b32f547ef7c131a4cbBartlomiej ZolnierkiewiczMODULE_AUTHOR("Andre Hedrick, Frank Tiernan, Bartlomiej Zolnierkiewicz"); 3601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_DESCRIPTION("PCI driver module for older Promise IDE"); 3611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_LICENSE("GPL"); 362