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

📄 icside.c

📁 ep9315平台下硬盘驱动的源码
💻 C
📖 第 1 页 / 共 2 页
字号:
}/* * dma_intr() is the handler for disk read/write DMA interrupts */static ide_startstop_t icside_dmaintr(ide_drive_t *drive){	unsigned int stat;	int dma_stat;	dma_stat = icside_dma_end(drive);	stat = HWIF(drive)->INB(IDE_STATUS_REG);	if (OK_STAT(stat, DRIVE_READY, drive->bad_wstat | DRQ_STAT)) {		if (!dma_stat) {			struct request *rq = HWGROUP(drive)->rq;			int i;			for (i = rq->nr_sectors; i > 0; ) {				i -= rq->current_nr_sectors;				DRIVER(drive)->end_request(drive, 1);			}			return ide_stopped;		}		printk(KERN_ERR "%s: bad DMA status (dma_stat=%x)\n",		       drive->name, dma_stat);	}	return DRIVER(drive)->error(drive, __FUNCTION__, stat);}static inticside_dma_common(ide_drive_t *drive, struct request *rq,		  unsigned int dma_mode){	ide_hwif_t *hwif = HWIF(drive);	/*	 * We can not enable DMA on both channels.	 */	BUG_ON(hwif->sg_dma_active);	BUG_ON(dma_channel_active(hwif->hw.dma));	ide_build_sglist(drive, rq);	/*	 * Ensure that we have the right interrupt routed.	 */	icside_maskproc(drive, 0);	/*	 * Route the DMA signals to the correct interface.	 */	outb(hwif->select_data, hwif->config_data);	/*	 * Select the correct timing for this drive.	 */	set_dma_speed(hwif->hw.dma, drive->drive_data);	/*	 * Tell the DMA engine about the SG table and	 * data direction.	 */	set_dma_sg(hwif->hw.dma, hwif->sg_table, hwif->sg_nents);	set_dma_mode(hwif->hw.dma, dma_mode);	return 0;}static int icside_dma_read(ide_drive_t *drive){	struct request *rq = HWGROUP(drive)->rq;	task_ioreg_t cmd;	if (icside_dma_common(drive, rq, DMA_MODE_READ))		return 1;	drive->waiting_for_dma = 1;	if (drive->media != ide_disk)		return 0;	/*	 * FIX ME to use only ACB ide_task_t args Struct	 */#if 0	{		ide_task_t *args = rq->special;		cmd = args->tfRegister[IDE_COMMAND_OFFSET];	}#else	if (rq->cmd == IDE_DRIVE_TASKFILE) {		ide_task_t *args = rq->special;		cmd = args->tfRegister[IDE_COMMAND_OFFSET];	} else if (drive->addressing == 1) {		cmd = WIN_READDMA_EXT;	} else {		cmd = WIN_READDMA;	}#endif	ide_execute_command(drive, cmd, icside_dmaintr, 2*WAIT_CMD, NULL);	return icside_dma_begin(drive);}static int icside_dma_write(ide_drive_t *drive){	struct request *rq = HWGROUP(drive)->rq;	task_ioreg_t cmd;	if (icside_dma_common(drive, rq, DMA_MODE_WRITE))		return 1;	drive->waiting_for_dma = 1;	if (drive->media != ide_disk)		return 0;	/*	 * FIX ME to use only ACB ide_task_t args Struct	 */#if 0	{		ide_task_t *args = rq->special;		cmd = args->tfRegister[IDE_COMMAND_OFFSET];	}#else	if (rq->cmd == IDE_DRIVE_TASKFILE) {		ide_task_t *args = rq->special;		cmd = args->tfRegister[IDE_COMMAND_OFFSET];	} else if (drive->addressing == 1) {		cmd = WIN_WRITEDMA_EXT;	} else {		cmd = WIN_WRITEDMA;	}#endif	ide_execute_command(drive, cmd, icside_dmaintr, 2*WAIT_CMD, NULL);	return icside_dma_begin(drive);}static int icside_dma_test_irq(ide_drive_t *drive){	ide_hwif_t *hwif = HWIF(drive);	struct icside_state *state = hwif->hwif_data;	return inb(state->irq_port +		   (hwif->channel ?			ICS_ARCIN_V6_INTRSTAT_2 :			ICS_ARCIN_V6_INTRSTAT_1)) & 1;}static int icside_dma_verbose(ide_drive_t *drive){	printk(", %s (peak %dMB/s)",		ide_xfer_verbose(drive->current_speed),		2000 / drive->drive_data);	return 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 int 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->sg_table = kmalloc(sizeof(struct scatterlist) * NR_ENTRIES,				 GFP_KERNEL);	if (!hwif->sg_table)		goto failed;	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_off	= icside_dma_off;	hwif->ide_dma_host_on	= icside_dma_host_on;	hwif->ide_dma_on	= icside_dma_on;	hwif->ide_dma_read	= icside_dma_read;	hwif->ide_dma_write	= icside_dma_write;	hwif->ide_dma_count	= icside_dma_count;	hwif->ide_dma_begin	= icside_dma_begin;	hwif->ide_dma_end	= icside_dma_end;	hwif->ide_dma_test_irq	= icside_dma_test_irq;	hwif->ide_dma_verbose	= icside_dma_verbose;	hwif->ide_dma_timeout	= icside_dma_timeout;	hwif->ide_dma_lostirq	= icside_dma_lostirq;	printk(" capable%s\n", hwif->autodma ? ", auto-enable" : "");	return 1;failed:	printk(" disabled, unable to allocate DMA table\n");	return 0;}static void icside_dma_exit(ide_hwif_t *hwif){	if (hwif->sg_table) {		kfree(hwif->sg_table);		hwif->sg_table = NULL;	}}#else#define icside_dma_init(hwif)	(0)#define icside_dma_exit(hwif)	do { } while (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] == (ide_ioreg_t)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(unsigned long base, struct cardinfo *info, struct expansion_card *ec){	unsigned long port = base + info->dataoffset;	ide_hwif_t *hwif;	hwif = icside_find_hwif(base);	if (hwif) {		int i;		memset(&hwif->hw, 0, sizeof(hw_regs_t));		for (i = IDE_DATA_OFFSET; i <= IDE_STATUS_OFFSET; i++) {			hwif->hw.io_ports[i] = (ide_ioreg_t)port;			hwif->io_ports[i] = (ide_ioreg_t)port;			port += 1 << info->stepping;		}		hwif->hw.io_ports[IDE_CONTROL_OFFSET] = base + info->ctrloffset;		hwif->io_ports[IDE_CONTROL_OFFSET] = base + info->ctrloffset;		hwif->hw.irq  = ec->irq;		hwif->irq     = ec->irq;		hwif->hw.dma  = NO_DMA;		hwif->noprobe = 0;		hwif->chipset = ide_acorn;	}	return hwif;}static int __initicside_register_v5(struct icside_state *state, struct expansion_card *ec){	unsigned long slot_port;	ide_hwif_t *hwif;	slot_port = ecard_address(ec, ECARD_MEMC, 0);	state->irq_port = slot_port;	ec->irqaddr  = (unsigned char *)ioaddr(slot_port + ICS_ARCIN_V5_INTRSTAT);	ec->irqmask  = 1;	ec->irq_data = state;	ec->ops      = &icside_ops_arcin_v5;	/*	 * Be on the safe side - disable interrupts	 */	inb(slot_port + ICS_ARCIN_V5_INTROFFSET);	hwif = icside_setup(slot_port, &icside_cardinfo_v5, ec);	state->hwif[0] = hwif;	return hwif ? 0 : -ENODEV;}static int __initicside_register_v6(struct icside_state *state, struct expansion_card *ec){	unsigned long slot_port, port;	ide_hwif_t *hwif, *mate;	unsigned int sel = 0;	slot_port = ecard_address(ec, ECARD_IOC, ECARD_FAST);	port      = ecard_address(ec, ECARD_EASI, ECARD_FAST);	if (port == 0)		port = slot_port;	else		sel = 1 << 5;	outb(sel, slot_port);	/*	 * Be on the safe side - disable interrupts	 */	inb(port + ICS_ARCIN_V6_INTROFFSET_1);	inb(port + ICS_ARCIN_V6_INTROFFSET_2);	/*	 * Find and register the interfaces.	 */	hwif = icside_setup(port, &icside_cardinfo_v6_1, ec);	mate = icside_setup(port, &icside_cardinfo_v6_2, ec);	if (!hwif || !mate)		return -ENODEV;	state->irq_port   = port;	state->slot_port  = slot_port;	state->hwif[0]    = hwif;	state->hwif[1]    = mate;	ec->irq_data      = state;	ec->ops           = &icside_ops_arcin_v6;	hwif->maskproc    = icside_maskproc;	hwif->channel     = 0;	hwif->hwif_data   = state;	hwif->mate        = mate;	hwif->serialized  = 1;	hwif->config_data = slot_port;	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 = slot_port;	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);	}	return 0;}static int __init icside_probe(struct expansion_card *ec, const struct ecard_id *id){	struct icside_state *state;	int ret;	state = kmalloc(sizeof(struct icside_state), GFP_KERNEL);	if (!state) {		ret = -ENOMEM;		goto out;	}	memset(state, 0, sizeof(struct icside_state));	state->type	= ICS_TYPE_NOTYPE;	{		unsigned int addr = ecard_address (ec, ECARD_IOC, ECARD_FAST) + ICS_IDENT_OFFSET;		unsigned int type;		type = inb(addr) & 1;		type |= (inb(addr + 1) & 1) << 1;		type |= (inb(addr + 2) & 1) << 2;		type |= (inb(addr + 3) & 1) << 3;		state->type = type;	}	switch (state->type) {	case ICS_TYPE_A3IN:		printk(KERN_WARNING "icside: A3IN unsupported\n");		ret = -ENODEV;		break;	case ICS_TYPE_A3USER:		printk(KERN_WARNING "icside: 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:		printk(KERN_WARNING "icside: unknown interface type\n");		ret = -ENODEV;		break;	}	if (ret == 0) {		ecard_set_drvdata(ec, state);	} else {		kfree(state);	} 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 */		inb(state->slot_port + ICS_ARCIN_V5_INTROFFSET);		break;	case ICS_TYPE_V6:		/* FIXME: tell IDE to stop using the interface */		icside_dma_exit(state->hwif[1]);		icside_dma_exit(state->hwif[0]);		if (ec->dma != NO_DMA)			free_dma(ec->dma);		/* Disable interrupts */		inb(state->irq_port + ICS_ARCIN_V6_INTROFFSET_1);		inb(state->irq_port + ICS_ARCIN_V6_INTROFFSET_2);		/* Reset the ROM pointer/EASI selection */		outb(0, state->slot_port);		break;	}	ecard_set_drvdata(ec, NULL);	ec->ops = NULL;	ec->irq_data = NULL;	kfree(state);}static void icside_shutdown(struct expansion_card *ec){	struct icside_state *state = ecard_get_drvdata(ec);	switch (state->type) {	case ICS_TYPE_V5:		/* Disable interrupts */		inb(state->slot_port + ICS_ARCIN_V5_INTROFFSET);		break;	case ICS_TYPE_V6:		/* Disable interrupts */		inb(state->irq_port + ICS_ARCIN_V6_INTROFFSET_1);		inb(state->irq_port + ICS_ARCIN_V6_INTROFFSET_2);		/* Reset the ROM pointer/EASI selection */		outb(0, state->slot_port);		break;	}}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,};int __init icside_init(void){	return ecard_register_driver(&icside_driver);}

⌨️ 快捷键说明

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