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

📄 ide-dma.c

📁 2410的硬盘块设备源码
💻 C
📖 第 1 页 / 共 2 页
字号:
#ifdef CONFIG_BLK_DEV_IDEDMA_PCI/** *	__ide_dma_host_on	-	Enable DMA on a host *	@drive: drive to enable for DMA * *	Enable DMA on an IDE controller following generic bus mastering *	IDE controller behaviour */ int __ide_dma_host_on (ide_drive_t *drive){	if (drive->using_dma) {		ide_hwif_t *hwif	= HWIF(drive);		u8 unit			= (drive->select.b.unit & 0x01);		u8 dma_stat		= hwif->INB(hwif->dma_status);		hwif->OUTB((dma_stat|(1<<(5+unit))), hwif->dma_status);		return 0;	}	return 1;}EXPORT_SYMBOL(__ide_dma_host_on);/** *	__ide_dma_on		-	Enable DMA on a device *	@drive: drive to enable DMA on * *	Enable IDE DMA for a device on this IDE controller. */ int __ide_dma_on (ide_drive_t *drive){	/* consult the list of known "bad" drives */	if (__ide_dma_bad_drive(drive))		return 1;	drive->using_dma = 1;	ide_toggle_bounce(drive, 1);	if (HWIF(drive)->ide_dma_host_on(drive))		return 1;	return 0;}EXPORT_SYMBOL(__ide_dma_on);/** *	__ide_dma_check		-	check DMA setup *	@drive: drive to check * *	Don't use - due for extermination */ int __ide_dma_check (ide_drive_t *drive){	return config_drive_for_dma(drive);}EXPORT_SYMBOL(__ide_dma_check);/** *	ide_dma_setup	-	begin a DMA phase *	@drive: target device * *	Build an IDE DMA PRD (IDE speak for scatter gather table) *	and then set up the DMA transfer registers for a device *	that follows generic IDE PCI DMA behaviour. Controllers can *	override this function if they need to * *	Returns 0 on success. If a PIO fallback is required then 1 *	is returned.  */int ide_dma_setup(ide_drive_t *drive){	ide_hwif_t *hwif = drive->hwif;	struct request *rq = HWGROUP(drive)->rq;	unsigned int reading;	u8 dma_stat;	if (rq_data_dir(rq))		reading = 0;	else		reading = 1 << 3;	/* fall back to pio! */	if (!ide_build_dmatable(drive, rq)) {		ide_map_sg(drive, rq);		return 1;	}	/* PRD table */	hwif->OUTL(hwif->dmatable_dma, hwif->dma_prdtable);	/* specify r/w */	hwif->OUTB(reading, hwif->dma_command);	/* read dma_status for INTR & ERROR flags */	dma_stat = hwif->INB(hwif->dma_status);	/* clear INTR & ERROR flags */	hwif->OUTB(dma_stat|6, hwif->dma_status);	drive->waiting_for_dma = 1;	return 0;}EXPORT_SYMBOL_GPL(ide_dma_setup);static void ide_dma_exec_cmd(ide_drive_t *drive, u8 command){	/* issue cmd to drive */	ide_execute_command(drive, command, &ide_dma_intr, 2*WAIT_CMD, dma_timer_expiry);}void ide_dma_start(ide_drive_t *drive){	ide_hwif_t *hwif	= HWIF(drive);	u8 dma_cmd		= hwif->INB(hwif->dma_command);	/* Note that this is done *after* the cmd has	 * been issued to the drive, as per the BM-IDE spec.	 * The Promise Ultra33 doesn't work correctly when	 * we do this part before issuing the drive cmd.	 */	/* start DMA */	hwif->OUTB(dma_cmd|1, hwif->dma_command);	hwif->dma = 1;	wmb();}EXPORT_SYMBOL_GPL(ide_dma_start);/* returns 1 on error, 0 otherwise */int __ide_dma_end (ide_drive_t *drive){	ide_hwif_t *hwif	= HWIF(drive);	u8 dma_stat = 0, dma_cmd = 0;	drive->waiting_for_dma = 0;	/* get dma_command mode */	dma_cmd = hwif->INB(hwif->dma_command);	/* stop DMA */	hwif->OUTB(dma_cmd&~1, hwif->dma_command);	/* get DMA status */	dma_stat = hwif->INB(hwif->dma_status);	/* clear the INTR & ERROR bits */	hwif->OUTB(dma_stat|6, hwif->dma_status);	/* purge DMA mappings */	ide_destroy_dmatable(drive);	/* verify good DMA status */	hwif->dma = 0;	wmb();	return (dma_stat & 7) != 4 ? (0x10 | dma_stat) : 0;}EXPORT_SYMBOL(__ide_dma_end);/* returns 1 if dma irq issued, 0 otherwise */static int __ide_dma_test_irq(ide_drive_t *drive){	ide_hwif_t *hwif	= HWIF(drive);	u8 dma_stat		= hwif->INB(hwif->dma_status);#if 0  /* do not set unless you know what you are doing */	if (dma_stat & 4) {		u8 stat = hwif->INB(IDE_STATUS_REG);		hwif->OUTB(hwif->dma_status, dma_stat & 0xE4);	}#endif	/* return 1 if INTR asserted */	if ((dma_stat & 4) == 4)		return 1;	if (!drive->waiting_for_dma)		printk(KERN_WARNING "%s: (%s) called while not waiting\n",			drive->name, __FUNCTION__);	return 0;}#endif /* CONFIG_BLK_DEV_IDEDMA_PCI */int __ide_dma_bad_drive (ide_drive_t *drive){	struct hd_driveid *id = drive->id;	int blacklist = in_drive_list(id, drive_blacklist);	if (blacklist) {		printk(KERN_WARNING "%s: Disabling (U)DMA for %s (blacklisted)\n",				    drive->name, id->model);		return blacklist;	}	return 0;}EXPORT_SYMBOL(__ide_dma_bad_drive);int __ide_dma_good_drive (ide_drive_t *drive){	struct hd_driveid *id = drive->id;	return in_drive_list(id, drive_whitelist);}EXPORT_SYMBOL(__ide_dma_good_drive);int ide_use_dma(ide_drive_t *drive){	struct hd_driveid *id = drive->id;	ide_hwif_t *hwif = drive->hwif;	/* consult the list of known "bad" drives */	if (__ide_dma_bad_drive(drive))		return 0;	/* capable of UltraDMA modes */	if (id->field_valid & 4) {		if (hwif->ultra_mask & id->dma_ultra)			return 1;	}	/* capable of regular DMA modes */	if (id->field_valid & 2) {		if (hwif->mwdma_mask & id->dma_mword)			return 1;		if (hwif->swdma_mask & id->dma_1word)			return 1;	}	/* consult the list of known "good" drives */	if (__ide_dma_good_drive(drive) && id->eide_dma_time < 150)		return 1;	return 0;}EXPORT_SYMBOL_GPL(ide_use_dma);void ide_dma_verbose(ide_drive_t *drive){	struct hd_driveid *id	= drive->id;	ide_hwif_t *hwif	= HWIF(drive);	if (id->field_valid & 4) {		if ((id->dma_ultra >> 8) && (id->dma_mword >> 8))			goto bug_dma_off;		if (id->dma_ultra & ((id->dma_ultra >> 8) & hwif->ultra_mask)) {			if (((id->dma_ultra >> 11) & 0x1F) &&			    eighty_ninty_three(drive)) {				if ((id->dma_ultra >> 15) & 1) {					printk(", UDMA(mode 7)");				} else if ((id->dma_ultra >> 14) & 1) {					printk(", UDMA(133)");				} else if ((id->dma_ultra >> 13) & 1) {					printk(", UDMA(100)");				} else if ((id->dma_ultra >> 12) & 1) {					printk(", UDMA(66)");				} else if ((id->dma_ultra >> 11) & 1) {					printk(", UDMA(44)");				} else					goto mode_two;			} else {		mode_two:				if ((id->dma_ultra >> 10) & 1) {					printk(", UDMA(33)");				} else if ((id->dma_ultra >> 9) & 1) {					printk(", UDMA(25)");				} else if ((id->dma_ultra >> 8) & 1) {					printk(", UDMA(16)");				}			}		} else {			printk(", (U)DMA");	/* Can be BIOS-enabled! */		}	} else if (id->field_valid & 2) {		if ((id->dma_mword >> 8) && (id->dma_1word >> 8))			goto bug_dma_off;		printk(", DMA");	} else if (id->field_valid & 1) {		printk(", BUG");	}	return;bug_dma_off:	printk(", BUG DMA OFF");	hwif->ide_dma_off_quietly(drive);	return;}EXPORT_SYMBOL(ide_dma_verbose);#ifdef CONFIG_BLK_DEV_IDEDMA_PCIint __ide_dma_lostirq (ide_drive_t *drive){	printk("%s: DMA interrupt recovery\n", drive->name);	return 1;}EXPORT_SYMBOL(__ide_dma_lostirq);int __ide_dma_timeout (ide_drive_t *drive){	printk(KERN_ERR "%s: timeout waiting for DMA\n", drive->name);	if (HWIF(drive)->ide_dma_test_irq(drive))		return 0;	return HWIF(drive)->ide_dma_end(drive);}EXPORT_SYMBOL(__ide_dma_timeout);/* * Needed for allowing full modular support of ide-driver */static int ide_release_dma_engine(ide_hwif_t *hwif){	if (hwif->dmatable_cpu) {		pci_free_consistent(hwif->pci_dev,				    PRD_ENTRIES * PRD_BYTES,				    hwif->dmatable_cpu,				    hwif->dmatable_dma);		hwif->dmatable_cpu = NULL;	}	return 1;}static int ide_release_iomio_dma(ide_hwif_t *hwif){	if ((hwif->dma_extra) && (hwif->channel == 0))		release_region((hwif->dma_base + 16), hwif->dma_extra);	release_region(hwif->dma_base, 8);	if (hwif->dma_base2)		release_region(hwif->dma_base, 8);	return 1;}/* * Needed for allowing full modular support of ide-driver */int ide_release_dma (ide_hwif_t *hwif){	if (hwif->mmio == 2)		return 1;	if (hwif->chipset == ide_etrax100)		return 1;	ide_release_dma_engine(hwif);	return ide_release_iomio_dma(hwif);}static int ide_allocate_dma_engine(ide_hwif_t *hwif){	hwif->dmatable_cpu = pci_alloc_consistent(hwif->pci_dev,						  PRD_ENTRIES * PRD_BYTES,						  &hwif->dmatable_dma);	if (hwif->dmatable_cpu)		return 0;	printk(KERN_ERR "%s: -- Error, unable to allocate%s DMA table(s).\n",			hwif->cds->name, !hwif->dmatable_cpu ? " CPU" : "");	ide_release_dma_engine(hwif);	return 1;}static int ide_mapped_mmio_dma(ide_hwif_t *hwif, unsigned long base, unsigned int ports){	printk(KERN_INFO "    %s: MMIO-DMA ", hwif->name);	hwif->dma_base = base;	if (hwif->cds->extra && hwif->channel == 0)		hwif->dma_extra = hwif->cds->extra;	if(hwif->mate)		hwif->dma_master = (hwif->channel) ? hwif->mate->dma_base : base;	else		hwif->dma_master = base;	return 0;}static int ide_iomio_dma(ide_hwif_t *hwif, unsigned long base, unsigned int ports){	printk(KERN_INFO "    %s: BM-DMA at 0x%04lx-0x%04lx",		hwif->name, base, base + ports - 1);	if (!request_region(base, ports, hwif->name)) {		printk(" -- Error, ports in use.\n");		return 1;	}	hwif->dma_base = base;	if ((hwif->cds->extra) && (hwif->channel == 0)) {		request_region(base+16, hwif->cds->extra, hwif->cds->name);		hwif->dma_extra = hwif->cds->extra;	}		if(hwif->mate)		hwif->dma_master = (hwif->channel) ? hwif->mate->dma_base : base;	else		hwif->dma_master = base;	if (hwif->dma_base2) {		if (!request_region(hwif->dma_base2, ports, hwif->name))		{			printk(" -- Error, secondary ports in use.\n");			release_region(base, ports);			return 1;		}	}	return 0;}static int ide_dma_iobase(ide_hwif_t *hwif, unsigned long base, unsigned int ports){	if (hwif->mmio == 2)		return ide_mapped_mmio_dma(hwif, base,ports);	BUG_ON(hwif->mmio == 1);	return ide_iomio_dma(hwif, base, ports);}/* * This can be called for a dynamically installed interface. Don't __init it */void ide_setup_dma (ide_hwif_t *hwif, unsigned long dma_base, unsigned int num_ports){	if (ide_dma_iobase(hwif, dma_base, num_ports))		return;	if (ide_allocate_dma_engine(hwif)) {		ide_release_dma(hwif);		return;	}	if (!(hwif->dma_command))		hwif->dma_command	= hwif->dma_base;	if (!(hwif->dma_vendor1))		hwif->dma_vendor1	= (hwif->dma_base + 1);	if (!(hwif->dma_status))		hwif->dma_status	= (hwif->dma_base + 2);	if (!(hwif->dma_vendor3))		hwif->dma_vendor3	= (hwif->dma_base + 3);	if (!(hwif->dma_prdtable))		hwif->dma_prdtable	= (hwif->dma_base + 4);	if (!hwif->ide_dma_off_quietly)		hwif->ide_dma_off_quietly = &__ide_dma_off_quietly;	if (!hwif->ide_dma_host_off)		hwif->ide_dma_host_off = &__ide_dma_host_off;	if (!hwif->ide_dma_on)		hwif->ide_dma_on = &__ide_dma_on;	if (!hwif->ide_dma_host_on)		hwif->ide_dma_host_on = &__ide_dma_host_on;	if (!hwif->ide_dma_check)		hwif->ide_dma_check = &__ide_dma_check;	if (!hwif->dma_setup)		hwif->dma_setup = &ide_dma_setup;	if (!hwif->dma_exec_cmd)		hwif->dma_exec_cmd = &ide_dma_exec_cmd;	if (!hwif->dma_start)		hwif->dma_start = &ide_dma_start;	if (!hwif->ide_dma_end)		hwif->ide_dma_end = &__ide_dma_end;	if (!hwif->ide_dma_test_irq)		hwif->ide_dma_test_irq = &__ide_dma_test_irq;	if (!hwif->ide_dma_timeout)		hwif->ide_dma_timeout = &__ide_dma_timeout;	if (!hwif->ide_dma_lostirq)		hwif->ide_dma_lostirq = &__ide_dma_lostirq;	if (hwif->chipset != ide_trm290) {		u8 dma_stat = hwif->INB(hwif->dma_status);		printk(", BIOS settings: %s:%s, %s:%s",		       hwif->drives[0].name, (dma_stat & 0x20) ? "DMA" : "pio",		       hwif->drives[1].name, (dma_stat & 0x40) ? "DMA" : "pio");	}	printk("\n");	if (!(hwif->dma_master))		BUG();}EXPORT_SYMBOL_GPL(ide_setup_dma);#endif /* CONFIG_BLK_DEV_IDEDMA_PCI */

⌨️ 快捷键说明

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