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

📄 icside.c

📁 linux-2.6.15.6
💻 C
📖 第 1 页 / 共 2 页
字号:
	set_dma_sg(hwif->hw.dma, hwif->sg_table, hwif->sg_nents);	set_dma_mode(hwif->hw.dma, dma_mode);	drive->waiting_for_dma = 1;	return 0;}static void icside_dma_exec_cmd(ide_drive_t *drive, u8 cmd){	/* issue cmd to drive */	ide_execute_command(drive, cmd, ide_dma_intr, 2 * WAIT_CMD, NULL);}static int icside_dma_test_irq(ide_drive_t *drive){	ide_hwif_t *hwif = HWIF(drive);	struct icside_state *state = hwif->hwif_data;	return readb(state->irq_port +		     (hwif->channel ?			ICS_ARCIN_V6_INTRSTAT_2 :			ICS_ARCIN_V6_INTRSTAT_1)) & 1;}static int icside_dma_timeout(ide_drive_t *drive){	printk(KERN_ERR "%s: DMA timeout occurred: ", drive->name);	if (icside_dma_test_irq(drive))		return 0;	ide_dump_status(drive, "DMA timeout",		HWIF(drive)->INB(IDE_STATUS_REG));	return icside_dma_end(drive);}static int icside_dma_lostirq(ide_drive_t *drive){	printk(KERN_ERR "%s: IRQ lost\n", drive->name);	return 1;}static void icside_dma_init(ide_hwif_t *hwif){	int autodma = 0;#ifdef CONFIG_IDEDMA_ICS_AUTO	autodma = 1;#endif	printk("    %s: SG-DMA", hwif->name);	hwif->atapi_dma		= 1;	hwif->mwdma_mask	= 7; /* MW0..2 */	hwif->swdma_mask	= 7; /* SW0..2 */	hwif->dmatable_cpu	= NULL;	hwif->dmatable_dma	= 0;	hwif->speedproc		= icside_set_speed;	hwif->autodma		= autodma;	hwif->ide_dma_check	= icside_dma_check;	hwif->ide_dma_host_off	= icside_dma_host_off;	hwif->ide_dma_off_quietly = icside_dma_off_quietly;	hwif->ide_dma_host_on	= icside_dma_host_on;	hwif->ide_dma_on	= icside_dma_on;	hwif->dma_setup		= icside_dma_setup;	hwif->dma_exec_cmd	= icside_dma_exec_cmd;	hwif->dma_start		= icside_dma_start;	hwif->ide_dma_end	= icside_dma_end;	hwif->ide_dma_test_irq	= icside_dma_test_irq;	hwif->ide_dma_timeout	= icside_dma_timeout;	hwif->ide_dma_lostirq	= icside_dma_lostirq;	hwif->drives[0].autodma = hwif->autodma;	hwif->drives[1].autodma = hwif->autodma;	printk(" capable%s\n", hwif->autodma ? ", auto-enable" : "");}#else#define icside_dma_init(hwif)	(0)#endifstatic ide_hwif_t *icside_find_hwif(unsigned long dataport){	ide_hwif_t *hwif;	int index;	for (index = 0; index < MAX_HWIFS; ++index) {		hwif = &ide_hwifs[index];		if (hwif->io_ports[IDE_DATA_OFFSET] == dataport)			goto found;	}	for (index = 0; index < MAX_HWIFS; ++index) {		hwif = &ide_hwifs[index];		if (!hwif->io_ports[IDE_DATA_OFFSET])			goto found;	}	hwif = NULL;found:	return hwif;}static ide_hwif_t *icside_setup(void __iomem *base, struct cardinfo *info, struct expansion_card *ec){	unsigned long port = (unsigned long)base + info->dataoffset;	ide_hwif_t *hwif;	hwif = icside_find_hwif(port);	if (hwif) {		int i;		memset(&hwif->hw, 0, sizeof(hw_regs_t));		/*		 * Ensure we're using MMIO		 */		default_hwif_mmiops(hwif);		hwif->mmio = 2;		for (i = IDE_DATA_OFFSET; i <= IDE_STATUS_OFFSET; i++) {			hwif->hw.io_ports[i] = port;			hwif->io_ports[i] = port;			port += 1 << info->stepping;		}		hwif->hw.io_ports[IDE_CONTROL_OFFSET] = (unsigned long)base + info->ctrloffset;		hwif->io_ports[IDE_CONTROL_OFFSET] = (unsigned long)base + info->ctrloffset;		hwif->hw.irq  = ec->irq;		hwif->irq     = ec->irq;		hwif->noprobe = 0;		hwif->chipset = ide_acorn;		hwif->gendev.parent = &ec->dev;	}	return hwif;}static int __initicside_register_v5(struct icside_state *state, struct expansion_card *ec){	ide_hwif_t *hwif;	void __iomem *base;	base = ioremap(ecard_resource_start(ec, ECARD_RES_MEMC),		       ecard_resource_len(ec, ECARD_RES_MEMC));	if (!base)		return -ENOMEM;	state->irq_port = base;	ec->irqaddr  = base + ICS_ARCIN_V5_INTRSTAT;	ec->irqmask  = 1;	ec->irq_data = state;	ec->ops      = &icside_ops_arcin_v5;	/*	 * Be on the safe side - disable interrupts	 */	icside_irqdisable_arcin_v5(ec, 0);	hwif = icside_setup(base, &icside_cardinfo_v5, ec);	if (!hwif) {		iounmap(base);		return -ENODEV;	}	state->hwif[0] = hwif;	probe_hwif_init(hwif);	create_proc_ide_interfaces();	return 0;}static int __initicside_register_v6(struct icside_state *state, struct expansion_card *ec){	ide_hwif_t *hwif, *mate;	void __iomem *ioc_base, *easi_base;	unsigned int sel = 0;	int ret;	ioc_base = ioremap(ecard_resource_start(ec, ECARD_RES_IOCFAST),			   ecard_resource_len(ec, ECARD_RES_IOCFAST));	if (!ioc_base) {		ret = -ENOMEM;		goto out;	}	easi_base = ioc_base;	if (ecard_resource_flags(ec, ECARD_RES_EASI)) {		easi_base = ioremap(ecard_resource_start(ec, ECARD_RES_EASI),				    ecard_resource_len(ec, ECARD_RES_EASI));		if (!easi_base) {			ret = -ENOMEM;			goto unmap_slot;		}		/*		 * Enable access to the EASI region.		 */		sel = 1 << 5;	}	writeb(sel, ioc_base);	ec->irq_data      = state;	ec->ops           = &icside_ops_arcin_v6;	state->irq_port   = easi_base;	state->ioc_base   = ioc_base;	/*	 * Be on the safe side - disable interrupts	 */	icside_irqdisable_arcin_v6(ec, 0);	/*	 * Find and register the interfaces.	 */	hwif = icside_setup(easi_base, &icside_cardinfo_v6_1, ec);	mate = icside_setup(easi_base, &icside_cardinfo_v6_2, ec);	if (!hwif || !mate) {		ret = -ENODEV;		goto unmap_port;	}	state->hwif[0]    = hwif;	state->hwif[1]    = mate;	hwif->maskproc    = icside_maskproc;	hwif->channel     = 0;	hwif->hwif_data   = state;	hwif->mate        = mate;	hwif->serialized  = 1;	hwif->config_data = (unsigned long)ioc_base;	hwif->select_data = sel;	hwif->hw.dma      = ec->dma;	mate->maskproc    = icside_maskproc;	mate->channel     = 1;	mate->hwif_data   = state;	mate->mate        = hwif;	mate->serialized  = 1;	mate->config_data = (unsigned long)ioc_base;	mate->select_data = sel | 1;	mate->hw.dma      = ec->dma;	if (ec->dma != NO_DMA && !request_dma(ec->dma, hwif->name)) {		icside_dma_init(hwif);		icside_dma_init(mate);	}	probe_hwif_init(hwif);	probe_hwif_init(mate);	create_proc_ide_interfaces();	return 0; unmap_port:	if (easi_base != ioc_base)		iounmap(easi_base); unmap_slot:	iounmap(ioc_base); out:	return ret;}static int __deviniticside_probe(struct expansion_card *ec, const struct ecard_id *id){	struct icside_state *state;	void __iomem *idmem;	int ret;	ret = ecard_request_resources(ec);	if (ret)		goto out;	state = kmalloc(sizeof(struct icside_state), GFP_KERNEL);	if (!state) {		ret = -ENOMEM;		goto release;	}	memset(state, 0, sizeof(state));	state->type	= ICS_TYPE_NOTYPE;	state->dev	= &ec->dev;	idmem = ioremap(ecard_resource_start(ec, ECARD_RES_IOCFAST),			ecard_resource_len(ec, ECARD_RES_IOCFAST));	if (idmem) {		unsigned int type;		type = readb(idmem + ICS_IDENT_OFFSET) & 1;		type |= (readb(idmem + ICS_IDENT_OFFSET + 4) & 1) << 1;		type |= (readb(idmem + ICS_IDENT_OFFSET + 8) & 1) << 2;		type |= (readb(idmem + ICS_IDENT_OFFSET + 12) & 1) << 3;		iounmap(idmem);		state->type = type;	}	switch (state->type) {	case ICS_TYPE_A3IN:		dev_warn(&ec->dev, "A3IN unsupported\n");		ret = -ENODEV;		break;	case ICS_TYPE_A3USER:		dev_warn(&ec->dev, "A3USER unsupported\n");		ret = -ENODEV;		break;	case ICS_TYPE_V5:		ret = icside_register_v5(state, ec);		break;	case ICS_TYPE_V6:		ret = icside_register_v6(state, ec);		break;	default:		dev_warn(&ec->dev, "unknown interface type\n");		ret = -ENODEV;		break;	}	if (ret == 0) {		ecard_set_drvdata(ec, state);		goto out;	}	kfree(state); release:	ecard_release_resources(ec); out:	return ret;}static void __devexit icside_remove(struct expansion_card *ec){	struct icside_state *state = ecard_get_drvdata(ec);	switch (state->type) {	case ICS_TYPE_V5:		/* FIXME: tell IDE to stop using the interface */		/* Disable interrupts */		icside_irqdisable_arcin_v5(ec, 0);		break;	case ICS_TYPE_V6:		/* FIXME: tell IDE to stop using the interface */		if (ec->dma != NO_DMA)			free_dma(ec->dma);		/* Disable interrupts */		icside_irqdisable_arcin_v6(ec, 0);		/* Reset the ROM pointer/EASI selection */		writeb(0, state->ioc_base);		break;	}	ecard_set_drvdata(ec, NULL);	ec->ops = NULL;	ec->irq_data = NULL;	if (state->ioc_base)		iounmap(state->ioc_base);	if (state->ioc_base != state->irq_port)		iounmap(state->irq_port);	kfree(state);	ecard_release_resources(ec);}static void icside_shutdown(struct expansion_card *ec){	struct icside_state *state = ecard_get_drvdata(ec);	unsigned long flags;	/*	 * Disable interrupts from this card.  We need to do	 * this before disabling EASI since we may be accessing	 * this register via that region.	 */	local_irq_save(flags);	ec->ops->irqdisable(ec, 0);	local_irq_restore(flags);	/*	 * Reset the ROM pointer so that we can read the ROM	 * after a soft reboot.  This also disables access to	 * the IDE taskfile via the EASI region.	 */	if (state->ioc_base)		writeb(0, state->ioc_base);}static const struct ecard_id icside_ids[] = {	{ MANU_ICS,  PROD_ICS_IDE  },	{ MANU_ICS2, PROD_ICS2_IDE },	{ 0xffff, 0xffff }};static struct ecard_driver icside_driver = {	.probe		= icside_probe,	.remove		= __devexit_p(icside_remove),	.shutdown	= icside_shutdown,	.id_table	= icside_ids,	.drv = {		.name	= "icside",	},};static int __init icside_init(void){	return ecard_register_driver(&icside_driver);}MODULE_AUTHOR("Russell King <rmk@arm.linux.org.uk>");MODULE_LICENSE("GPL");MODULE_DESCRIPTION("ICS IDE driver");module_init(icside_init);

⌨️ 快捷键说明

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