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

📄 sata_promise.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
/* *  sata_promise.c - Promise SATA * *  Maintained by:  Jeff Garzik <jgarzik@pobox.com> *		    Mikael Pettersson <mikpe@it.uu.se> *  		    Please ALWAYS copy linux-ide@vger.kernel.org *		    on emails. * *  Copyright 2003-2004 Red Hat, Inc. * * *  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, or (at your option) *  any later version. * *  This program is distributed in the hope that it will be useful, *  but WITHOUT ANY WARRANTY; without even the implied warranty of *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the *  GNU General Public License for more details. * *  You should have received a copy of the GNU General Public License *  along with this program; see the file COPYING.  If not, write to *  the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. * * *  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/interrupt.h>#include <linux/device.h>#include <scsi/scsi.h>#include <scsi/scsi_host.h>#include <scsi/scsi_cmnd.h>#include <linux/libata.h>#include "sata_promise.h"#define DRV_NAME	"sata_promise"#define DRV_VERSION	"2.11"enum {	PDC_MAX_PORTS		= 4,	PDC_MMIO_BAR		= 3,	PDC_MAX_PRD		= LIBATA_MAX_PRD - 1, /* -1 for ASIC PRD bug workaround */	/* register offsets */	PDC_FEATURE		= 0x04, /* Feature/Error reg (per port) */	PDC_SECTOR_COUNT	= 0x08, /* Sector count reg (per port) */	PDC_SECTOR_NUMBER	= 0x0C, /* Sector number reg (per port) */	PDC_CYLINDER_LOW	= 0x10, /* Cylinder low reg (per port) */	PDC_CYLINDER_HIGH	= 0x14, /* Cylinder high reg (per port) */	PDC_DEVICE		= 0x18, /* Device/Head reg (per port) */	PDC_COMMAND		= 0x1C, /* Command/status reg (per port) */	PDC_ALTSTATUS		= 0x38, /* Alternate-status/device-control reg (per port) */	PDC_PKT_SUBMIT		= 0x40, /* Command packet pointer addr */	PDC_INT_SEQMASK		= 0x40,	/* Mask of asserted SEQ INTs */	PDC_FLASH_CTL		= 0x44, /* Flash control register */	PDC_GLOBAL_CTL		= 0x48, /* Global control/status (per port) */	PDC_CTLSTAT		= 0x60,	/* IDE control and status (per port) */	PDC_SATA_PLUG_CSR	= 0x6C, /* SATA Plug control/status reg */	PDC2_SATA_PLUG_CSR	= 0x60, /* SATAII Plug control/status reg */	PDC_TBG_MODE		= 0x41C, /* TBG mode (not SATAII) */	PDC_SLEW_CTL		= 0x470, /* slew rate control reg (not SATAII) */	/* PDC_GLOBAL_CTL bit definitions */	PDC_PH_ERR		= (1 <<  8), /* PCI error while loading packet */	PDC_SH_ERR		= (1 <<  9), /* PCI error while loading S/G table */	PDC_DH_ERR		= (1 << 10), /* PCI error while loading data */	PDC2_HTO_ERR		= (1 << 12), /* host bus timeout */	PDC2_ATA_HBA_ERR	= (1 << 13), /* error during SATA DATA FIS transmission */	PDC2_ATA_DMA_CNT_ERR	= (1 << 14), /* DMA DATA FIS size differs from S/G count */	PDC_OVERRUN_ERR		= (1 << 19), /* S/G byte count larger than HD requires */	PDC_UNDERRUN_ERR	= (1 << 20), /* S/G byte count less than HD requires */	PDC_DRIVE_ERR		= (1 << 21), /* drive error */	PDC_PCI_SYS_ERR		= (1 << 22), /* PCI system error */	PDC1_PCI_PARITY_ERR	= (1 << 23), /* PCI parity error (from SATA150 driver) */	PDC1_ERR_MASK		= PDC1_PCI_PARITY_ERR,	PDC2_ERR_MASK		= PDC2_HTO_ERR | PDC2_ATA_HBA_ERR |				  PDC2_ATA_DMA_CNT_ERR,	PDC_ERR_MASK		= PDC_PH_ERR | PDC_SH_ERR | PDC_DH_ERR |				  PDC_OVERRUN_ERR | PDC_UNDERRUN_ERR |				  PDC_DRIVE_ERR | PDC_PCI_SYS_ERR |				  PDC1_ERR_MASK | PDC2_ERR_MASK,	board_2037x		= 0,	/* FastTrak S150 TX2plus */	board_2037x_pata	= 1,	/* FastTrak S150 TX2plus PATA port */	board_20319		= 2,	/* FastTrak S150 TX4 */	board_20619		= 3,	/* FastTrak TX4000 */	board_2057x		= 4,	/* SATAII150 Tx2plus */	board_2057x_pata	= 5,	/* SATAII150 Tx2plus PATA port */	board_40518		= 6,	/* SATAII150 Tx4 */	PDC_HAS_PATA		= (1 << 1), /* PDC20375/20575 has PATA */	/* Sequence counter control registers bit definitions */	PDC_SEQCNTRL_INT_MASK	= (1 << 5), /* Sequence Interrupt Mask */	/* Feature register values */	PDC_FEATURE_ATAPI_PIO	= 0x00, /* ATAPI data xfer by PIO */	PDC_FEATURE_ATAPI_DMA	= 0x01, /* ATAPI data xfer by DMA */	/* Device/Head register values */	PDC_DEVICE_SATA		= 0xE0, /* Device/Head value for SATA devices */	/* PDC_CTLSTAT bit definitions */	PDC_DMA_ENABLE		= (1 << 7),	PDC_IRQ_DISABLE		= (1 << 10),	PDC_RESET		= (1 << 11), /* HDMA reset */	PDC_COMMON_FLAGS	= ATA_FLAG_NO_LEGACY |				  ATA_FLAG_MMIO |				  ATA_FLAG_PIO_POLLING,	/* ap->flags bits */	PDC_FLAG_GEN_II		= (1 << 24),	PDC_FLAG_SATA_PATA	= (1 << 25), /* supports SATA + PATA */	PDC_FLAG_4_PORTS	= (1 << 26), /* 4 ports */};struct pdc_port_priv {	u8			*pkt;	dma_addr_t		pkt_dma;};static int pdc_sata_scr_read(struct ata_port *ap, unsigned int sc_reg, u32 *val);static int pdc_sata_scr_write(struct ata_port *ap, unsigned int sc_reg, u32 val);static int pdc_ata_init_one (struct pci_dev *pdev, const struct pci_device_id *ent);static int pdc_common_port_start(struct ata_port *ap);static int pdc_sata_port_start(struct ata_port *ap);static void pdc_qc_prep(struct ata_queued_cmd *qc);static void pdc_tf_load_mmio(struct ata_port *ap, const struct ata_taskfile *tf);static void pdc_exec_command_mmio(struct ata_port *ap, const struct ata_taskfile *tf);static int pdc_check_atapi_dma(struct ata_queued_cmd *qc);static int pdc_old_sata_check_atapi_dma(struct ata_queued_cmd *qc);static void pdc_irq_clear(struct ata_port *ap);static unsigned int pdc_qc_issue_prot(struct ata_queued_cmd *qc);static void pdc_freeze(struct ata_port *ap);static void pdc_thaw(struct ata_port *ap);static void pdc_pata_error_handler(struct ata_port *ap);static void pdc_sata_error_handler(struct ata_port *ap);static void pdc_post_internal_cmd(struct ata_queued_cmd *qc);static int pdc_pata_cable_detect(struct ata_port *ap);static int pdc_sata_cable_detect(struct ata_port *ap);static struct scsi_host_template pdc_ata_sht = {	.module			= THIS_MODULE,	.name			= DRV_NAME,	.ioctl			= ata_scsi_ioctl,	.queuecommand		= ata_scsi_queuecmd,	.can_queue		= ATA_DEF_QUEUE,	.this_id		= ATA_SHT_THIS_ID,	.sg_tablesize		= PDC_MAX_PRD,	.cmd_per_lun		= ATA_SHT_CMD_PER_LUN,	.emulated		= ATA_SHT_EMULATED,	.use_clustering		= ATA_SHT_USE_CLUSTERING,	.proc_name		= DRV_NAME,	.dma_boundary		= ATA_DMA_BOUNDARY,	.slave_configure	= ata_scsi_slave_config,	.slave_destroy		= ata_scsi_slave_destroy,	.bios_param		= ata_std_bios_param,};static const struct ata_port_operations pdc_sata_ops = {	.tf_load		= pdc_tf_load_mmio,	.tf_read		= ata_tf_read,	.check_status		= ata_check_status,	.exec_command		= pdc_exec_command_mmio,	.dev_select		= ata_std_dev_select,	.check_atapi_dma	= pdc_check_atapi_dma,	.qc_prep		= pdc_qc_prep,	.qc_issue		= pdc_qc_issue_prot,	.freeze			= pdc_freeze,	.thaw			= pdc_thaw,	.error_handler		= pdc_sata_error_handler,	.post_internal_cmd	= pdc_post_internal_cmd,	.cable_detect		= pdc_sata_cable_detect,	.data_xfer		= ata_data_xfer,	.irq_clear		= pdc_irq_clear,	.irq_on			= ata_irq_on,	.scr_read		= pdc_sata_scr_read,	.scr_write		= pdc_sata_scr_write,	.port_start		= pdc_sata_port_start,};/* First-generation chips need a more restrictive ->check_atapi_dma op */static const struct ata_port_operations pdc_old_sata_ops = {	.tf_load		= pdc_tf_load_mmio,	.tf_read		= ata_tf_read,	.check_status		= ata_check_status,	.exec_command		= pdc_exec_command_mmio,	.dev_select		= ata_std_dev_select,	.check_atapi_dma	= pdc_old_sata_check_atapi_dma,	.qc_prep		= pdc_qc_prep,	.qc_issue		= pdc_qc_issue_prot,	.freeze			= pdc_freeze,	.thaw			= pdc_thaw,	.error_handler		= pdc_sata_error_handler,	.post_internal_cmd	= pdc_post_internal_cmd,	.cable_detect		= pdc_sata_cable_detect,	.data_xfer		= ata_data_xfer,	.irq_clear		= pdc_irq_clear,	.irq_on			= ata_irq_on,	.scr_read		= pdc_sata_scr_read,	.scr_write		= pdc_sata_scr_write,	.port_start		= pdc_sata_port_start,};static const struct ata_port_operations pdc_pata_ops = {	.tf_load		= pdc_tf_load_mmio,	.tf_read		= ata_tf_read,	.check_status		= ata_check_status,	.exec_command		= pdc_exec_command_mmio,	.dev_select		= ata_std_dev_select,	.check_atapi_dma	= pdc_check_atapi_dma,	.qc_prep		= pdc_qc_prep,	.qc_issue		= pdc_qc_issue_prot,	.freeze			= pdc_freeze,	.thaw			= pdc_thaw,	.error_handler		= pdc_pata_error_handler,	.post_internal_cmd	= pdc_post_internal_cmd,	.cable_detect		= pdc_pata_cable_detect,	.data_xfer		= ata_data_xfer,	.irq_clear		= pdc_irq_clear,	.irq_on			= ata_irq_on,	.port_start		= pdc_common_port_start,};static const struct ata_port_info pdc_port_info[] = {	[board_2037x] =	{		.flags		= PDC_COMMON_FLAGS | ATA_FLAG_SATA |				  PDC_FLAG_SATA_PATA,		.pio_mask	= 0x1f, /* pio0-4 */		.mwdma_mask	= 0x07, /* mwdma0-2 */		.udma_mask	= ATA_UDMA6,		.port_ops	= &pdc_old_sata_ops,	},	[board_2037x_pata] =	{		.flags		= PDC_COMMON_FLAGS | ATA_FLAG_SLAVE_POSS,		.pio_mask	= 0x1f, /* pio0-4 */		.mwdma_mask	= 0x07, /* mwdma0-2 */		.udma_mask	= ATA_UDMA6,		.port_ops	= &pdc_pata_ops,	},	[board_20319] =	{		.flags		= PDC_COMMON_FLAGS | ATA_FLAG_SATA |				  PDC_FLAG_4_PORTS,		.pio_mask	= 0x1f, /* pio0-4 */		.mwdma_mask	= 0x07, /* mwdma0-2 */		.udma_mask	= ATA_UDMA6,		.port_ops	= &pdc_old_sata_ops,	},	[board_20619] =	{		.flags		= PDC_COMMON_FLAGS | ATA_FLAG_SLAVE_POSS |				  PDC_FLAG_4_PORTS,		.pio_mask	= 0x1f, /* pio0-4 */		.mwdma_mask	= 0x07, /* mwdma0-2 */		.udma_mask	= ATA_UDMA6,		.port_ops	= &pdc_pata_ops,	},	[board_2057x] =	{		.flags		= PDC_COMMON_FLAGS | ATA_FLAG_SATA |				  PDC_FLAG_GEN_II | PDC_FLAG_SATA_PATA,		.pio_mask	= 0x1f, /* pio0-4 */		.mwdma_mask	= 0x07, /* mwdma0-2 */		.udma_mask	= ATA_UDMA6,		.port_ops	= &pdc_sata_ops,	},	[board_2057x_pata] =	{		.flags		= PDC_COMMON_FLAGS | ATA_FLAG_SLAVE_POSS |				  PDC_FLAG_GEN_II,		.pio_mask	= 0x1f, /* pio0-4 */		.mwdma_mask	= 0x07, /* mwdma0-2 */		.udma_mask	= ATA_UDMA6,		.port_ops	= &pdc_pata_ops,	},	[board_40518] =	{		.flags		= PDC_COMMON_FLAGS | ATA_FLAG_SATA |				  PDC_FLAG_GEN_II | PDC_FLAG_4_PORTS,		.pio_mask	= 0x1f, /* pio0-4 */		.mwdma_mask	= 0x07, /* mwdma0-2 */		.udma_mask	= ATA_UDMA6,		.port_ops	= &pdc_sata_ops,	},};static const struct pci_device_id pdc_ata_pci_tbl[] = {	{ PCI_VDEVICE(PROMISE, 0x3371), board_2037x },	{ PCI_VDEVICE(PROMISE, 0x3373), board_2037x },	{ PCI_VDEVICE(PROMISE, 0x3375), board_2037x },	{ PCI_VDEVICE(PROMISE, 0x3376), board_2037x },	{ PCI_VDEVICE(PROMISE, 0x3570), board_2057x },	{ PCI_VDEVICE(PROMISE, 0x3571), board_2057x },	{ PCI_VDEVICE(PROMISE, 0x3574), board_2057x },	{ PCI_VDEVICE(PROMISE, 0x3577), board_2057x },	{ PCI_VDEVICE(PROMISE, 0x3d73), board_2057x },	{ PCI_VDEVICE(PROMISE, 0x3d75), board_2057x },	{ PCI_VDEVICE(PROMISE, 0x3318), board_20319 },	{ PCI_VDEVICE(PROMISE, 0x3319), board_20319 },	{ PCI_VDEVICE(PROMISE, 0x3515), board_40518 },	{ PCI_VDEVICE(PROMISE, 0x3519), board_40518 },	{ PCI_VDEVICE(PROMISE, 0x3d17), board_40518 },	{ PCI_VDEVICE(PROMISE, 0x3d18), board_40518 },	{ PCI_VDEVICE(PROMISE, 0x6629), board_20619 },	{ }	/* terminate list */};static struct pci_driver pdc_ata_pci_driver = {	.name			= DRV_NAME,	.id_table		= pdc_ata_pci_tbl,	.probe			= pdc_ata_init_one,	.remove			= ata_pci_remove_one,};static int pdc_common_port_start(struct ata_port *ap){	struct device *dev = ap->host->dev;	struct pdc_port_priv *pp;	int rc;	rc = ata_port_start(ap);	if (rc)		return rc;	pp = devm_kzalloc(dev, sizeof(*pp), GFP_KERNEL);	if (!pp)		return -ENOMEM;	pp->pkt = dmam_alloc_coherent(dev, 128, &pp->pkt_dma, GFP_KERNEL);	if (!pp->pkt)		return -ENOMEM;	ap->private_data = pp;	return 0;}static int pdc_sata_port_start(struct ata_port *ap){	int rc;	rc = pdc_common_port_start(ap);	if (rc)		return rc;	/* fix up PHYMODE4 align timing */	if (ap->flags & PDC_FLAG_GEN_II) {		void __iomem *mmio = ap->ioaddr.scr_addr;		unsigned int tmp;		tmp = readl(mmio + 0x014);		tmp = (tmp & ~3) | 1;	/* set bits 1:0 = 0:1 */		writel(tmp, mmio + 0x014);	}	return 0;}static void pdc_reset_port(struct ata_port *ap){	void __iomem *mmio = ap->ioaddr.cmd_addr + PDC_CTLSTAT;	unsigned int i;	u32 tmp;	for (i = 11; i > 0; i--) {		tmp = readl(mmio);		if (tmp & PDC_RESET)			break;		udelay(100);		tmp |= PDC_RESET;		writel(tmp, mmio);	}	tmp &= ~PDC_RESET;	writel(tmp, mmio);	readl(mmio);	/* flush */}static int pdc_pata_cable_detect(struct ata_port *ap){	u8 tmp;	void __iomem *mmio = ap->ioaddr.cmd_addr + PDC_CTLSTAT + 0x03;	tmp = readb(mmio);	if (tmp & 0x01)		return ATA_CBL_PATA40;	return ATA_CBL_PATA80;}static int pdc_sata_cable_detect(struct ata_port *ap){	return ATA_CBL_SATA;}static int pdc_sata_scr_read(struct ata_port *ap, unsigned int sc_reg, u32 *val){	if (sc_reg > SCR_CONTROL)		return -EINVAL;	*val = readl(ap->ioaddr.scr_addr + (sc_reg * 4));	return 0;}static int pdc_sata_scr_write(struct ata_port *ap, unsigned int sc_reg, u32 val){	if (sc_reg > SCR_CONTROL)		return -EINVAL;	writel(val, ap->ioaddr.scr_addr + (sc_reg * 4));	return 0;}static void pdc_atapi_pkt(struct ata_queued_cmd *qc){	struct ata_port *ap = qc->ap;	dma_addr_t sg_table = ap->prd_dma;	unsigned int cdb_len = qc->dev->cdb_len;	u8 *cdb = qc->cdb;	struct pdc_port_priv *pp = ap->private_data;	u8 *buf = pp->pkt;	u32 *buf32 = (u32 *) buf;	unsigned int dev_sel, feature, nbytes;	/* set control bits (byte 0), zero delay seq id (byte 3),	 * and seq id (byte 2)	 */	switch (qc->tf.protocol) {	case ATA_PROT_ATAPI_DMA:		if (!(qc->tf.flags & ATA_TFLAG_WRITE))			buf32[0] = cpu_to_le32(PDC_PKT_READ);		else			buf32[0] = 0;		break;	case ATA_PROT_ATAPI_NODATA:		buf32[0] = cpu_to_le32(PDC_PKT_NODATA);		break;	default:		BUG();		break;	}	buf32[1] = cpu_to_le32(sg_table);	/* S/G table addr */	buf32[2] = 0;				/* no next-packet */	/* select drive */	if (sata_scr_valid(&ap->link)) {		dev_sel = PDC_DEVICE_SATA;	} else {		dev_sel = ATA_DEVICE_OBS;		if (qc->dev->devno != 0)			dev_sel |= ATA_DEV1;	}	buf[12] = (1 << 5) | ATA_REG_DEVICE;	buf[13] = dev_sel;	buf[14] = (1 << 5) | ATA_REG_DEVICE | PDC_PKT_CLEAR_BSY;	buf[15] = dev_sel; /* once more, waiting for BSY to clear */	buf[16] = (1 << 5) | ATA_REG_NSECT;	buf[17] = 0x00;	buf[18] = (1 << 5) | ATA_REG_LBAL;	buf[19] = 0x00;	/* set feature and byte counter registers */	if (qc->tf.protocol != ATA_PROT_ATAPI_DMA) {		feature = PDC_FEATURE_ATAPI_PIO;		/* set byte counter register to real transfer byte count */		nbytes = qc->nbytes;		if (nbytes > 0xffff)			nbytes = 0xffff;	} else {		feature = PDC_FEATURE_ATAPI_DMA;		/* set byte counter register to 0 */		nbytes = 0;	}	buf[20] = (1 << 5) | ATA_REG_FEATURE;	buf[21] = feature;	buf[22] = (1 << 5) | ATA_REG_BYTEL;	buf[23] = nbytes & 0xFF;	buf[24] = (1 << 5) | ATA_REG_BYTEH;	buf[25] = (nbytes >> 8) & 0xFF;	/* send ATAPI packet command 0xA0 */	buf[26] = (1 << 5) | ATA_REG_CMD;	buf[27] = ATA_CMD_PACKET;	/* select drive and check DRQ */	buf[28] = (1 << 5) | ATA_REG_DEVICE | PDC_PKT_WAIT_DRDY;	buf[29] = dev_sel;	/* we can represent cdb lengths 2/4/6/8/10/12/14/16 */	BUG_ON(cdb_len & ~0x1E);	/* append the CDB as the final part */	buf[30] = (((cdb_len >> 1) & 7) << 5) | ATA_REG_DATA | PDC_LAST_REG;	memcpy(buf+31, cdb, cdb_len);}/** *	pdc_fill_sg - Fill PCI IDE PRD table *	@qc: Metadata associated with taskfile to be transferred * *	Fill PCI IDE PRD (scatter-gather) table with segments *	associated with the current disk command. *	Make sure hardware does not choke on it. * *	LOCKING: *	spin_lock_irqsave(host lock) * */static void pdc_fill_sg(struct ata_queued_cmd *qc){	struct ata_port *ap = qc->ap;	struct scatterlist *sg;	unsigned int idx;	const u32 SG_COUNT_ASIC_BUG = 41*4;	if (!(qc->flags & ATA_QCFLAG_DMAMAP))		return;	WARN_ON(qc->__sg == NULL);	WARN_ON(qc->n_elem == 0 && qc->pad_len == 0);	idx = 0;	ata_for_each_sg(sg, qc) {		u32 addr, offset;		u32 sg_len, len;		/* determine if physical DMA addr spans 64K boundary.		 * Note h/w doesn't support 64-bit, so we unconditionally		 * truncate dma_addr_t to u32.		 */		addr = (u32) sg_dma_address(sg);		sg_len = sg_dma_len(sg);		while (sg_len) {			offset = addr & 0xffff;			len = sg_len;			if ((offset + sg_len) > 0x10000)				len = 0x10000 - offset;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -