⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 pata_pdc2027x.c

📁 This file was based on: drivers/ata/pata_ixp4xx_cf.c
💻 C
📖 第 1 页 / 共 2 页
字号:
/* *  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 + -