📄 pata_pdc2027x.c
字号:
/* * Promise PATA TX2/TX4/TX2000/133 IDE driver for pdc20268 to pdc20277. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version * 2 of the License, or (at your option) any later version. * * Ported to libata by: * Albert Lee <albertcc@tw.ibm.com> IBM Corporation * * Copyright (C) 1998-2002 Andre Hedrick <andre@linux-ide.org> * Portions Copyright (C) 1999 Promise Technology, Inc. * * Author: Frank Tiernan (frankt@promise.com) * Released under terms of General Public License * * * libata documentation is available via 'make {ps|pdf}docs', * as Documentation/DocBook/libata.* * * Hardware information only available under NDA. * */#include <linux/kernel.h>#include <linux/module.h>#include <linux/pci.h>#include <linux/init.h>#include <linux/blkdev.h>#include <linux/delay.h>#include <linux/device.h>#include <scsi/scsi.h>#include <scsi/scsi_host.h>#include <scsi/scsi_cmnd.h>#include <linux/libata.h>#define DRV_NAME "pata_pdc2027x"#define DRV_VERSION "1.0"#undef PDC_DEBUG#ifdef PDC_DEBUG#define PDPRINTK(fmt, args...) printk(KERN_ERR "%s: " fmt, __func__, ## args)#else#define PDPRINTK(fmt, args...)#endifenum { PDC_MMIO_BAR = 5, PDC_UDMA_100 = 0, PDC_UDMA_133 = 1, PDC_100_MHZ = 100000000, PDC_133_MHZ = 133333333, PDC_SYS_CTL = 0x1100, PDC_ATA_CTL = 0x1104, PDC_GLOBAL_CTL = 0x1108, PDC_CTCR0 = 0x110C, PDC_CTCR1 = 0x1110, PDC_BYTE_COUNT = 0x1120, PDC_PLL_CTL = 0x1202,};static int pdc2027x_init_one(struct pci_dev *pdev, const struct pci_device_id *ent);static int pdc2027x_prereset(struct ata_link *link, unsigned long deadline);static void pdc2027x_set_piomode(struct ata_port *ap, struct ata_device *adev);static void pdc2027x_set_dmamode(struct ata_port *ap, struct ata_device *adev);static int pdc2027x_check_atapi_dma(struct ata_queued_cmd *qc);static unsigned long pdc2027x_mode_filter(struct ata_device *adev, unsigned long mask);static int pdc2027x_cable_detect(struct ata_port *ap);static int pdc2027x_set_mode(struct ata_link *link, struct ata_device **r_failed);/* * ATA Timing Tables based on 133MHz controller clock. * These tables are only used when the controller is in 133MHz clock. * If the controller is in 100MHz clock, the ASIC hardware will * set the timing registers automatically when "set feature" command * is issued to the device. However, if the controller clock is 133MHz, * the following tables must be used. */static struct pdc2027x_pio_timing { u8 value0, value1, value2;} pdc2027x_pio_timing_tbl [] = { { 0xfb, 0x2b, 0xac }, /* PIO mode 0 */ { 0x46, 0x29, 0xa4 }, /* PIO mode 1 */ { 0x23, 0x26, 0x64 }, /* PIO mode 2 */ { 0x27, 0x0d, 0x35 }, /* PIO mode 3, IORDY on, Prefetch off */ { 0x23, 0x09, 0x25 }, /* PIO mode 4, IORDY on, Prefetch off */};static struct pdc2027x_mdma_timing { u8 value0, value1;} pdc2027x_mdma_timing_tbl [] = { { 0xdf, 0x5f }, /* MDMA mode 0 */ { 0x6b, 0x27 }, /* MDMA mode 1 */ { 0x69, 0x25 }, /* MDMA mode 2 */};static struct pdc2027x_udma_timing { u8 value0, value1, value2;} pdc2027x_udma_timing_tbl [] = { { 0x4a, 0x0f, 0xd5 }, /* UDMA mode 0 */ { 0x3a, 0x0a, 0xd0 }, /* UDMA mode 1 */ { 0x2a, 0x07, 0xcd }, /* UDMA mode 2 */ { 0x1a, 0x05, 0xcd }, /* UDMA mode 3 */ { 0x1a, 0x03, 0xcd }, /* UDMA mode 4 */ { 0x1a, 0x02, 0xcb }, /* UDMA mode 5 */ { 0x1a, 0x01, 0xcb }, /* UDMA mode 6 */};static const struct pci_device_id pdc2027x_pci_tbl[] = { { PCI_VDEVICE(PROMISE, PCI_DEVICE_ID_PROMISE_20268), PDC_UDMA_100 }, { PCI_VDEVICE(PROMISE, PCI_DEVICE_ID_PROMISE_20269), PDC_UDMA_133 }, { PCI_VDEVICE(PROMISE, PCI_DEVICE_ID_PROMISE_20270), PDC_UDMA_100 }, { PCI_VDEVICE(PROMISE, PCI_DEVICE_ID_PROMISE_20271), PDC_UDMA_133 }, { PCI_VDEVICE(PROMISE, PCI_DEVICE_ID_PROMISE_20275), PDC_UDMA_133 }, { PCI_VDEVICE(PROMISE, PCI_DEVICE_ID_PROMISE_20276), PDC_UDMA_133 }, { PCI_VDEVICE(PROMISE, PCI_DEVICE_ID_PROMISE_20277), PDC_UDMA_133 }, { } /* terminate list */};static struct pci_driver pdc2027x_pci_driver = { .name = DRV_NAME, .id_table = pdc2027x_pci_tbl, .probe = pdc2027x_init_one, .remove = ata_pci_remove_one,};static struct scsi_host_template pdc2027x_sht = { ATA_BMDMA_SHT(DRV_NAME),};static struct ata_port_operations pdc2027x_pata100_ops = { .inherits = &ata_bmdma_port_ops, .check_atapi_dma = pdc2027x_check_atapi_dma, .cable_detect = pdc2027x_cable_detect, .prereset = pdc2027x_prereset,};static struct ata_port_operations pdc2027x_pata133_ops = { .inherits = &pdc2027x_pata100_ops, .mode_filter = pdc2027x_mode_filter, .set_piomode = pdc2027x_set_piomode, .set_dmamode = pdc2027x_set_dmamode, .set_mode = pdc2027x_set_mode,};static struct ata_port_info pdc2027x_port_info[] = { /* PDC_UDMA_100 */ { .flags = ATA_FLAG_NO_LEGACY | ATA_FLAG_SLAVE_POSS | ATA_FLAG_MMIO, .pio_mask = 0x1f, /* pio0-4 */ .mwdma_mask = 0x07, /* mwdma0-2 */ .udma_mask = ATA_UDMA5, /* udma0-5 */ .port_ops = &pdc2027x_pata100_ops, }, /* PDC_UDMA_133 */ { .flags = ATA_FLAG_NO_LEGACY | ATA_FLAG_SLAVE_POSS | ATA_FLAG_MMIO, .pio_mask = 0x1f, /* pio0-4 */ .mwdma_mask = 0x07, /* mwdma0-2 */ .udma_mask = ATA_UDMA6, /* udma0-6 */ .port_ops = &pdc2027x_pata133_ops, },};MODULE_AUTHOR("Andre Hedrick, Frank Tiernan, Albert Lee");MODULE_DESCRIPTION("libata driver module for Promise PDC20268 to PDC20277");MODULE_LICENSE("GPL");MODULE_VERSION(DRV_VERSION);MODULE_DEVICE_TABLE(pci, pdc2027x_pci_tbl);/** * port_mmio - Get the MMIO address of PDC2027x extended registers * @ap: Port * @offset: offset from mmio base */static inline void __iomem *port_mmio(struct ata_port *ap, unsigned int offset){ return ap->host->iomap[PDC_MMIO_BAR] + ap->port_no * 0x100 + offset;}/** * dev_mmio - Get the MMIO address of PDC2027x extended registers * @ap: Port * @adev: device * @offset: offset from mmio base */static inline void __iomem *dev_mmio(struct ata_port *ap, struct ata_device *adev, unsigned int offset){ u8 adj = (adev->devno) ? 0x08 : 0x00; return port_mmio(ap, offset) + adj;}/** * pdc2027x_pata_cable_detect - Probe host controller cable detect info * @ap: Port for which cable detect info is desired * * Read 80c cable indicator from Promise extended register. * This register is latched when the system is reset. * * LOCKING: * None (inherited from caller). */static int pdc2027x_cable_detect(struct ata_port *ap){ u32 cgcr; /* check cable detect results */ cgcr = ioread32(port_mmio(ap, PDC_GLOBAL_CTL)); if (cgcr & (1 << 26)) goto cbl40; PDPRINTK("No cable or 80-conductor cable on port %d\n", ap->port_no); return ATA_CBL_PATA80;cbl40: printk(KERN_INFO DRV_NAME ": 40-conductor cable detected on port %d\n", ap->port_no); return ATA_CBL_PATA40;}/** * pdc2027x_port_enabled - Check PDC ATA control register to see whether the port is enabled. * @ap: Port to check */static inline int pdc2027x_port_enabled(struct ata_port *ap){ return ioread8(port_mmio(ap, PDC_ATA_CTL)) & 0x02;}/** * pdc2027x_prereset - prereset for PATA host controller * @link: Target link * @deadline: deadline jiffies for the operation * * Probeinit including cable detection. * * LOCKING: * None (inherited from caller). */static int pdc2027x_prereset(struct ata_link *link, unsigned long deadline){ /* Check whether port enabled */ if (!pdc2027x_port_enabled(link->ap)) return -ENOENT; return ata_sff_prereset(link, deadline);}/** * pdc2720x_mode_filter - mode selection filter * @adev: ATA device * @mask: list of modes proposed * * Block UDMA on devices that cause trouble with this controller. */static unsigned long pdc2027x_mode_filter(struct ata_device *adev, unsigned long mask){ unsigned char model_num[ATA_ID_PROD_LEN + 1]; struct ata_device *pair = ata_dev_pair(adev); if (adev->class != ATA_DEV_ATA || adev->devno == 0 || pair == NULL) return ata_bmdma_mode_filter(adev, mask); /* Check for slave of a Maxtor at UDMA6 */ ata_id_c_string(pair->id, model_num, ATA_ID_PROD, ATA_ID_PROD_LEN + 1); /* If the master is a maxtor in UDMA6 then the slave should not use UDMA 6 */ if (strstr(model_num, "Maxtor") == NULL && pair->dma_mode == XFER_UDMA_6) mask &= ~ (1 << (6 + ATA_SHIFT_UDMA)); return ata_bmdma_mode_filter(adev, mask);}/** * pdc2027x_set_piomode - Initialize host controller PATA PIO timings * @ap: Port to configure * @adev: um * @pio: PIO mode, 0 - 4 * * Set PIO mode for device. * * LOCKING: * None (inherited from caller). */static void pdc2027x_set_piomode(struct ata_port *ap, struct ata_device *adev){ unsigned int pio = adev->pio_mode - XFER_PIO_0; u32 ctcr0, ctcr1; PDPRINTK("adev->pio_mode[%X]\n", adev->pio_mode); /* Sanity check */ if (pio > 4) { printk(KERN_ERR DRV_NAME ": Unknown pio mode [%d] ignored\n", pio); return; } /* Set the PIO timing registers using value table for 133MHz */ PDPRINTK("Set pio regs... \n"); ctcr0 = ioread32(dev_mmio(ap, adev, PDC_CTCR0)); ctcr0 &= 0xffff0000; ctcr0 |= pdc2027x_pio_timing_tbl[pio].value0 | (pdc2027x_pio_timing_tbl[pio].value1 << 8); iowrite32(ctcr0, dev_mmio(ap, adev, PDC_CTCR0)); ctcr1 = ioread32(dev_mmio(ap, adev, PDC_CTCR1)); ctcr1 &= 0x00ffffff; ctcr1 |= (pdc2027x_pio_timing_tbl[pio].value2 << 24); iowrite32(ctcr1, dev_mmio(ap, adev, PDC_CTCR1)); PDPRINTK("Set pio regs done\n"); PDPRINTK("Set to pio mode[%u] \n", pio);}/** * pdc2027x_set_dmamode - Initialize host controller PATA UDMA timings * @ap: Port to configure * @adev: um * @udma: udma mode, XFER_UDMA_0 to XFER_UDMA_6 * * Set UDMA mode for device. * * LOCKING: * None (inherited from caller). */static void pdc2027x_set_dmamode(struct ata_port *ap, struct ata_device *adev){ unsigned int dma_mode = adev->dma_mode; u32 ctcr0, ctcr1; if ((dma_mode >= XFER_UDMA_0) && (dma_mode <= XFER_UDMA_6)) { /* Set the UDMA timing registers with value table for 133MHz */ unsigned int udma_mode = dma_mode & 0x07; if (dma_mode == XFER_UDMA_2) { /* * Turn off tHOLD. * If tHOLD is '1', the hardware will add half clock for data hold time. * This code segment seems to be no effect. tHOLD will be overwritten below. */ ctcr1 = ioread32(dev_mmio(ap, adev, PDC_CTCR1)); iowrite32(ctcr1 & ~(1 << 7), dev_mmio(ap, adev, PDC_CTCR1)); } PDPRINTK("Set udma regs... \n"); ctcr1 = ioread32(dev_mmio(ap, adev, PDC_CTCR1)); ctcr1 &= 0xff000000; ctcr1 |= pdc2027x_udma_timing_tbl[udma_mode].value0 | (pdc2027x_udma_timing_tbl[udma_mode].value1 << 8) | (pdc2027x_udma_timing_tbl[udma_mode].value2 << 16); iowrite32(ctcr1, dev_mmio(ap, adev, PDC_CTCR1)); PDPRINTK("Set udma regs done\n"); PDPRINTK("Set to udma mode[%u] \n", udma_mode); } else if ((dma_mode >= XFER_MW_DMA_0) && (dma_mode <= XFER_MW_DMA_2)) { /* Set the MDMA timing registers with value table for 133MHz */ unsigned int mdma_mode = dma_mode & 0x07; PDPRINTK("Set mdma regs... \n"); ctcr0 = ioread32(dev_mmio(ap, adev, PDC_CTCR0)); ctcr0 &= 0x0000ffff; ctcr0 |= (pdc2027x_mdma_timing_tbl[mdma_mode].value0 << 16) | (pdc2027x_mdma_timing_tbl[mdma_mode].value1 << 24); iowrite32(ctcr0, dev_mmio(ap, adev, PDC_CTCR0)); PDPRINTK("Set mdma regs done\n"); PDPRINTK("Set to mdma mode[%u] \n", mdma_mode); } else { printk(KERN_ERR DRV_NAME ": Unknown dma mode [%u] ignored\n", dma_mode); }}/** * pdc2027x_set_mode - Set the timing registers back to correct values. * @link: link to configure
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -