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

📄 sata_inic162x.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
static void inic_freeze(struct ata_port *ap){	void __iomem *port_base = inic_port_base(ap);	__inic_set_pirq_mask(ap, PIRQ_MASK_FREEZE);	ata_chk_status(ap);	writeb(0xff, port_base + PORT_IRQ_STAT);	readb(port_base + PORT_IRQ_STAT); /* flush */}static void inic_thaw(struct ata_port *ap){	void __iomem *port_base = inic_port_base(ap);	ata_chk_status(ap);	writeb(0xff, port_base + PORT_IRQ_STAT);	__inic_set_pirq_mask(ap, PIRQ_MASK_OTHER);	readb(port_base + PORT_IRQ_STAT); /* flush */}/* * SRST and SControl hardreset don't give valid signature on this * controller.  Only controller specific hardreset mechanism works. */static int inic_hardreset(struct ata_link *link, unsigned int *class,			  unsigned long deadline){	struct ata_port *ap = link->ap;	void __iomem *port_base = inic_port_base(ap);	void __iomem *idma_ctl = port_base + PORT_IDMA_CTL;	const unsigned long *timing = sata_ehc_deb_timing(&link->eh_context);	u16 val;	int rc;	/* hammer it into sane state */	inic_reset_port(port_base);	val = readw(idma_ctl);	writew(val | IDMA_CTL_RST_ATA, idma_ctl);	readw(idma_ctl);	/* flush */	msleep(1);	writew(val & ~IDMA_CTL_RST_ATA, idma_ctl);	rc = sata_link_resume(link, timing, deadline);	if (rc) {		ata_link_printk(link, KERN_WARNING, "failed to resume "				"link after reset (errno=%d)\n", rc);		return rc;	}	*class = ATA_DEV_NONE;	if (ata_link_online(link)) {		struct ata_taskfile tf;		/* wait a while before checking status */		ata_wait_after_reset(ap, deadline);		rc = ata_wait_ready(ap, deadline);		/* link occupied, -ENODEV too is an error */		if (rc) {			ata_link_printk(link, KERN_WARNING, "device not ready "					"after hardreset (errno=%d)\n", rc);			return rc;		}		ata_tf_read(ap, &tf);		*class = ata_dev_classify(&tf);		if (*class == ATA_DEV_UNKNOWN)			*class = ATA_DEV_NONE;	}	return 0;}static void inic_error_handler(struct ata_port *ap){	void __iomem *port_base = inic_port_base(ap);	struct inic_port_priv *pp = ap->private_data;	unsigned long flags;	/* reset PIO HSM and stop DMA engine */	inic_reset_port(port_base);	spin_lock_irqsave(ap->lock, flags);	ap->hsm_task_state = HSM_ST_IDLE;	writeb(pp->dfl_prdctl, port_base + PORT_PRD_CTL);	spin_unlock_irqrestore(ap->lock, flags);	/* PIO and DMA engines have been stopped, perform recovery */	ata_do_eh(ap, ata_std_prereset, NULL, inic_hardreset,		  ata_std_postreset);}static void inic_post_internal_cmd(struct ata_queued_cmd *qc){	/* make DMA engine forget about the failed command */	if (qc->flags & ATA_QCFLAG_FAILED)		inic_reset_port(inic_port_base(qc->ap));}static void inic_dev_config(struct ata_device *dev){	/* inic can only handle upto LBA28 max sectors */	if (dev->max_sectors > ATA_MAX_SECTORS)		dev->max_sectors = ATA_MAX_SECTORS;	if (dev->n_sectors >= 1 << 28) {		ata_dev_printk(dev, KERN_ERR,	"ERROR: This driver doesn't support LBA48 yet and may cause\n"	"                data corruption on such devices.  Disabling.\n");		ata_dev_disable(dev);	}}static void init_port(struct ata_port *ap){	void __iomem *port_base = inic_port_base(ap);	/* Setup PRD address */	writel(ap->prd_dma, port_base + PORT_PRD_ADDR);}static int inic_port_resume(struct ata_port *ap){	init_port(ap);	return 0;}static int inic_port_start(struct ata_port *ap){	void __iomem *port_base = inic_port_base(ap);	struct inic_port_priv *pp;	u8 tmp;	int rc;	/* alloc and initialize private data */	pp = devm_kzalloc(ap->host->dev, sizeof(*pp), GFP_KERNEL);	if (!pp)		return -ENOMEM;	ap->private_data = pp;	/* default PRD_CTL value, DMAEN, WR and START off */	tmp = readb(port_base + PORT_PRD_CTL);	tmp &= ~(PRD_CTL_DMAEN | PRD_CTL_WR | PRD_CTL_START);	pp->dfl_prdctl = tmp;	/* Alloc resources */	rc = ata_port_start(ap);	if (rc) {		kfree(pp);		return rc;	}	init_port(ap);	return 0;}static struct ata_port_operations inic_port_ops = {	.tf_load		= ata_tf_load,	.tf_read		= ata_tf_read,	.check_status		= ata_check_status,	.exec_command		= ata_exec_command,	.dev_select		= ata_std_dev_select,	.scr_read		= inic_scr_read,	.scr_write		= inic_scr_write,	.bmdma_setup		= inic_bmdma_setup,	.bmdma_start		= inic_bmdma_start,	.bmdma_stop		= inic_bmdma_stop,	.bmdma_status		= inic_bmdma_status,	.irq_clear		= inic_irq_clear,	.irq_on			= ata_irq_on,	.qc_prep	 	= ata_qc_prep,	.qc_issue		= inic_qc_issue,	.data_xfer		= ata_data_xfer,	.freeze			= inic_freeze,	.thaw			= inic_thaw,	.error_handler		= inic_error_handler,	.post_internal_cmd	= inic_post_internal_cmd,	.dev_config		= inic_dev_config,	.port_resume		= inic_port_resume,	.port_start		= inic_port_start,};static struct ata_port_info inic_port_info = {	/* For some reason, ATA_PROT_ATAPI is broken on this	 * controller, and no, PIO_POLLING does't fix it.  It somehow	 * manages to report the wrong ireason and ignoring ireason	 * results in machine lock up.  Tell libata to always prefer	 * DMA.	 */	.flags			= ATA_FLAG_SATA | ATA_FLAG_PIO_DMA,	.pio_mask		= 0x1f,	/* pio0-4 */	.mwdma_mask		= 0x07, /* mwdma0-2 */	.udma_mask		= ATA_UDMA6,	.port_ops		= &inic_port_ops};static int init_controller(void __iomem *mmio_base, u16 hctl){	int i;	u16 val;	hctl &= ~HCTL_KNOWN_BITS;	/* Soft reset whole controller.  Spec says reset duration is 3	 * PCI clocks, be generous and give it 10ms.	 */	writew(hctl | HCTL_SOFTRST, mmio_base + HOST_CTL);	readw(mmio_base + HOST_CTL); /* flush */	for (i = 0; i < 10; i++) {		msleep(1);		val = readw(mmio_base + HOST_CTL);		if (!(val & HCTL_SOFTRST))			break;	}	if (val & HCTL_SOFTRST)		return -EIO;	/* mask all interrupts and reset ports */	for (i = 0; i < NR_PORTS; i++) {		void __iomem *port_base = mmio_base + i * PORT_SIZE;		writeb(0xff, port_base + PORT_IRQ_MASK);		inic_reset_port(port_base);	}	/* port IRQ is masked now, unmask global IRQ */	writew(hctl & ~HCTL_IRQOFF, mmio_base + HOST_CTL);	val = readw(mmio_base + HOST_IRQ_MASK);	val &= ~(HIRQ_PORT0 | HIRQ_PORT1);	writew(val, mmio_base + HOST_IRQ_MASK);	return 0;}#ifdef CONFIG_PMstatic int inic_pci_device_resume(struct pci_dev *pdev){	struct ata_host *host = dev_get_drvdata(&pdev->dev);	struct inic_host_priv *hpriv = host->private_data;	void __iomem *mmio_base = host->iomap[MMIO_BAR];	int rc;	rc = ata_pci_device_do_resume(pdev);	if (rc)		return rc;	if (pdev->dev.power.power_state.event == PM_EVENT_SUSPEND) {		rc = init_controller(mmio_base, hpriv->cached_hctl);		if (rc)			return rc;	}	ata_host_resume(host);	return 0;}#endifstatic int inic_init_one(struct pci_dev *pdev, const struct pci_device_id *ent){	static int printed_version;	const struct ata_port_info *ppi[] = { &inic_port_info, NULL };	struct ata_host *host;	struct inic_host_priv *hpriv;	void __iomem * const *iomap;	int i, rc;	if (!printed_version++)		dev_printk(KERN_DEBUG, &pdev->dev, "version " DRV_VERSION "\n");	/* alloc host */	host = ata_host_alloc_pinfo(&pdev->dev, ppi, NR_PORTS);	hpriv = devm_kzalloc(&pdev->dev, sizeof(*hpriv), GFP_KERNEL);	if (!host || !hpriv)		return -ENOMEM;	host->private_data = hpriv;	/* acquire resources and fill host */	rc = pcim_enable_device(pdev);	if (rc)		return rc;	rc = pcim_iomap_regions(pdev, 0x3f, DRV_NAME);	if (rc)		return rc;	host->iomap = iomap = pcim_iomap_table(pdev);	for (i = 0; i < NR_PORTS; i++) {		struct ata_port *ap = host->ports[i];		struct ata_ioports *port = &ap->ioaddr;		unsigned int offset = i * PORT_SIZE;		port->cmd_addr = iomap[2 * i];		port->altstatus_addr =		port->ctl_addr = (void __iomem *)			((unsigned long)iomap[2 * i + 1] | ATA_PCI_CTL_OFS);		port->scr_addr = iomap[MMIO_BAR] + offset + PORT_SCR;		ata_std_ports(port);		ata_port_pbar_desc(ap, MMIO_BAR, -1, "mmio");		ata_port_pbar_desc(ap, MMIO_BAR, offset, "port");		ata_port_desc(ap, "cmd 0x%llx ctl 0x%llx",		  (unsigned long long)pci_resource_start(pdev, 2 * i),		  (unsigned long long)pci_resource_start(pdev, (2 * i + 1)) |				      ATA_PCI_CTL_OFS);	}	hpriv->cached_hctl = readw(iomap[MMIO_BAR] + HOST_CTL);	/* Set dma_mask.  This devices doesn't support 64bit addressing. */	rc = pci_set_dma_mask(pdev, DMA_32BIT_MASK);	if (rc) {		dev_printk(KERN_ERR, &pdev->dev,			   "32-bit DMA enable failed\n");		return rc;	}	rc = pci_set_consistent_dma_mask(pdev, DMA_32BIT_MASK);	if (rc) {		dev_printk(KERN_ERR, &pdev->dev,			   "32-bit consistent DMA enable failed\n");		return rc;	}	rc = init_controller(iomap[MMIO_BAR], hpriv->cached_hctl);	if (rc) {		dev_printk(KERN_ERR, &pdev->dev,			   "failed to initialize controller\n");		return rc;	}	pci_set_master(pdev);	return ata_host_activate(host, pdev->irq, inic_interrupt, IRQF_SHARED,				 &inic_sht);}static const struct pci_device_id inic_pci_tbl[] = {	{ PCI_VDEVICE(INIT, 0x1622), },	{ },};static struct pci_driver inic_pci_driver = {	.name 		= DRV_NAME,	.id_table	= inic_pci_tbl,#ifdef CONFIG_PM	.suspend	= ata_pci_device_suspend,	.resume		= inic_pci_device_resume,#endif	.probe 		= inic_init_one,	.remove		= ata_pci_remove_one,};static int __init inic_init(void){	return pci_register_driver(&inic_pci_driver);}static void __exit inic_exit(void){	pci_unregister_driver(&inic_pci_driver);}MODULE_AUTHOR("Tejun Heo");MODULE_DESCRIPTION("low-level driver for Initio 162x SATA");MODULE_LICENSE("GPL v2");MODULE_DEVICE_TABLE(pci, inic_pci_tbl);MODULE_VERSION(DRV_VERSION);module_init(inic_init);module_exit(inic_exit);

⌨️ 快捷键说明

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