sata_promise.c

来自「Linux Kernel 2.6.9 for OMAP1710」· C语言 代码 · 共 667 行 · 第 1/2 页

C
667
字号
/* *  sata_promise.c - Promise SATA * *  Maintained by:  Jeff Garzik <jgarzik@pobox.com> *  		    Please ALWAYS copy linux-ide@vger.kernel.org *		    on emails. * *  Copyright 2003-2004 Red Hat, Inc. * *  The contents of this file are subject to the Open *  Software License version 1.1 that can be found at *  http://www.opensource.org/licenses/osl-1.1.txt and is included herein *  by reference. * *  Alternatively, the contents of this file may be used under the terms *  of the GNU General Public License version 2 (the "GPL") as distributed *  in the kernel source COPYING file, in which case the provisions of *  the GPL are applicable instead of the above.  If you wish to allow *  the use of your version of this file only under the terms of the *  GPL and not to allow others to use your version of this file under *  the OSL, indicate your decision by deleting the provisions above and *  replace them with the notice and other provisions required by the GPL. *  If you do not delete the provisions above, a recipient may use your *  version of this file under either the OSL or the GPL. * */#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/sched.h>#include "scsi.h"#include <scsi/scsi_host.h>#include <linux/libata.h>#include <asm/io.h>#include "sata_promise.h"#define DRV_NAME	"sata_promise"#define DRV_VERSION	"1.00"enum {	PDC_PKT_SUBMIT		= 0x40, /* Command packet pointer addr */	PDC_INT_SEQMASK		= 0x40,	/* Mask of asserted SEQ INTs */	PDC_TBG_MODE		= 0x41,	/* TBG mode */	PDC_FLASH_CTL		= 0x44, /* Flash control register */	PDC_PCI_CTL		= 0x48, /* PCI control and status 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 */	PDC_SLEW_CTL		= 0x470, /* slew rate control reg */	PDC_ERR_MASK		= (1<<19) | (1<<20) | (1<<21) | (1<<22) |				  (1<<8) | (1<<9) | (1<<10),	board_2037x		= 0,	/* FastTrak S150 TX2plus */	board_20319		= 1,	/* FastTrak S150 TX4 */	PDC_HAS_PATA		= (1 << 1), /* PDC20375 has PATA */	PDC_RESET		= (1 << 11), /* HDMA reset */};struct pdc_port_priv {	u8			*pkt;	dma_addr_t		pkt_dma;};static u32 pdc_sata_scr_read (struct ata_port *ap, unsigned int sc_reg);static void pdc_sata_scr_write (struct ata_port *ap, unsigned int sc_reg, u32 val);static int pdc_sata_init_one (struct pci_dev *pdev, const struct pci_device_id *ent);static irqreturn_t pdc_interrupt (int irq, void *dev_instance, struct pt_regs *regs);static void pdc_eng_timeout(struct ata_port *ap);static int pdc_port_start(struct ata_port *ap);static void pdc_port_stop(struct ata_port *ap);static void pdc_phy_reset(struct ata_port *ap);static void pdc_qc_prep(struct ata_queued_cmd *qc);static void pdc_tf_load_mmio(struct ata_port *ap, struct ata_taskfile *tf);static void pdc_exec_command_mmio(struct ata_port *ap, struct ata_taskfile *tf);static void pdc_irq_clear(struct ata_port *ap);static int pdc_qc_issue_prot(struct ata_queued_cmd *qc);static Scsi_Host_Template pdc_sata_sht = {	.module			= THIS_MODULE,	.name			= DRV_NAME,	.ioctl			= ata_scsi_ioctl,	.queuecommand		= ata_scsi_queuecmd,	.eh_strategy_handler	= ata_scsi_error,	.can_queue		= ATA_DEF_QUEUE,	.this_id		= ATA_SHT_THIS_ID,	.sg_tablesize		= LIBATA_MAX_PRD,	.max_sectors		= ATA_MAX_SECTORS,	.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,	.bios_param		= ata_std_bios_param,};static struct ata_port_operations pdc_sata_ops = {	.port_disable		= ata_port_disable,	.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,	.phy_reset		= pdc_phy_reset,	.qc_prep		= pdc_qc_prep,	.qc_issue		= pdc_qc_issue_prot,	.eng_timeout		= pdc_eng_timeout,	.irq_handler		= pdc_interrupt,	.irq_clear		= pdc_irq_clear,	.scr_read		= pdc_sata_scr_read,	.scr_write		= pdc_sata_scr_write,	.port_start		= pdc_port_start,	.port_stop		= pdc_port_stop,};static struct ata_port_info pdc_port_info[] = {	/* board_2037x */	{		.sht		= &pdc_sata_sht,		.host_flags	= ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |				  ATA_FLAG_SRST | ATA_FLAG_MMIO,		.pio_mask	= 0x1f, /* pio0-4 */		.mwdma_mask	= 0x07, /* mwdma0-2 */		.udma_mask	= 0x7f, /* udma0-6 ; FIXME */		.port_ops	= &pdc_sata_ops,	},	/* board_20319 */	{		.sht		= &pdc_sata_sht,		.host_flags	= ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |				  ATA_FLAG_SRST | ATA_FLAG_MMIO,		.pio_mask	= 0x1f, /* pio0-4 */		.mwdma_mask	= 0x07, /* mwdma0-2 */		.udma_mask	= 0x7f, /* udma0-6 ; FIXME */		.port_ops	= &pdc_sata_ops,	},};static struct pci_device_id pdc_sata_pci_tbl[] = {	{ PCI_VENDOR_ID_PROMISE, 0x3371, PCI_ANY_ID, PCI_ANY_ID, 0, 0,	  board_2037x },	{ PCI_VENDOR_ID_PROMISE, 0x3373, PCI_ANY_ID, PCI_ANY_ID, 0, 0,	  board_2037x },	{ PCI_VENDOR_ID_PROMISE, 0x3375, PCI_ANY_ID, PCI_ANY_ID, 0, 0,	  board_2037x },	{ PCI_VENDOR_ID_PROMISE, 0x3376, PCI_ANY_ID, PCI_ANY_ID, 0, 0,	  board_2037x },	{ PCI_VENDOR_ID_PROMISE, 0x3318, PCI_ANY_ID, PCI_ANY_ID, 0, 0,	  board_20319 },	{ PCI_VENDOR_ID_PROMISE, 0x3319, PCI_ANY_ID, PCI_ANY_ID, 0, 0,	  board_20319 },	{ }	/* terminate list */};static struct pci_driver pdc_sata_pci_driver = {	.name			= DRV_NAME,	.id_table		= pdc_sata_pci_tbl,	.probe			= pdc_sata_init_one,	.remove			= ata_pci_remove_one,};static int pdc_port_start(struct ata_port *ap){	struct pci_dev *pdev = ap->host_set->pdev;	struct pdc_port_priv *pp;	int rc;	rc = ata_port_start(ap);	if (rc)		return rc;	pp = kmalloc(sizeof(*pp), GFP_KERNEL);	if (!pp) {		rc = -ENOMEM;		goto err_out;	}	memset(pp, 0, sizeof(*pp));	pp->pkt = pci_alloc_consistent(pdev, 128, &pp->pkt_dma);	if (!pp->pkt) {		rc = -ENOMEM;		goto err_out_kfree;	}	ap->private_data = pp;	return 0;err_out_kfree:	kfree(pp);err_out:	ata_port_stop(ap);	return rc;}static void pdc_port_stop(struct ata_port *ap){	struct pci_dev *pdev = ap->host_set->pdev;	struct pdc_port_priv *pp = ap->private_data;	ap->private_data = NULL;	pci_free_consistent(pdev, 128, pp->pkt, pp->pkt_dma);	kfree(pp);	ata_port_stop(ap);}static void pdc_reset_port(struct ata_port *ap){	void *mmio = (void *) 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 void pdc_phy_reset(struct ata_port *ap){	pdc_reset_port(ap);	sata_phy_reset(ap);}static u32 pdc_sata_scr_read (struct ata_port *ap, unsigned int sc_reg){	if (sc_reg > SCR_CONTROL)		return 0xffffffffU;	return readl((void *) ap->ioaddr.scr_addr + (sc_reg * 4));}static void pdc_sata_scr_write (struct ata_port *ap, unsigned int sc_reg,			       u32 val){	if (sc_reg > SCR_CONTROL)		return;	writel(val, (void *) ap->ioaddr.scr_addr + (sc_reg * 4));}static void pdc_qc_prep(struct ata_queued_cmd *qc){	struct pdc_port_priv *pp = qc->ap->private_data;	unsigned int i;	VPRINTK("ENTER\n");	switch (qc->tf.protocol) {	case ATA_PROT_DMA:		ata_qc_prep(qc);		/* fall through */	case ATA_PROT_NODATA:		i = pdc_pkt_header(&qc->tf, qc->ap->prd_dma,				   qc->dev->devno, pp->pkt);		if (qc->tf.flags & ATA_TFLAG_LBA48)			i = pdc_prep_lba48(&qc->tf, pp->pkt, i);		else			i = pdc_prep_lba28(&qc->tf, pp->pkt, i);		pdc_pkt_footer(&qc->tf, pp->pkt, i);		break;	default:		break;	}}static void pdc_eng_timeout(struct ata_port *ap){	u8 drv_stat;	struct ata_queued_cmd *qc;	DPRINTK("ENTER\n");	qc = ata_qc_from_tag(ap, ap->active_tag);	if (!qc) {		printk(KERN_ERR "ata%u: BUG: timeout without command\n",		       ap->id);		goto out;	}	/* hack alert!  We cannot use the supplied completion	 * function from inside the ->eh_strategy_handler() thread.	 * libata is the only user of ->eh_strategy_handler() in	 * any kernel, so the default scsi_done() assumes it is	 * not being called from the SCSI EH.	 */	qc->scsidone = scsi_finish_command;	switch (qc->tf.protocol) {	case ATA_PROT_DMA:	case ATA_PROT_NODATA:		printk(KERN_ERR "ata%u: command timeout\n", ap->id);		ata_qc_complete(qc, ata_wait_idle(ap) | ATA_ERR);		break;	default:		drv_stat = ata_busy_wait(ap, ATA_BUSY | ATA_DRQ, 1000);		printk(KERN_ERR "ata%u: unknown timeout, cmd 0x%x stat 0x%x\n",		       ap->id, qc->tf.command, drv_stat);		ata_qc_complete(qc, drv_stat);		break;	}out:

⌨️ 快捷键说明

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