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

📄 ide-dma.c

📁 Linux环境下java编程的经典书籍
💻 C
📖 第 1 页 / 共 2 页
字号:
		/* Consult the list of known "good" drives */		list = good_dma_drives;		while (*list) {			if (!strcmp(*list++,id->model))				return 1;		}	} else {		/* Consult the list of known "bad" drives */		list = bad_dma_drives;		while (*list) {			if (!strcmp(*list++,id->model)) {				printk("%s: Disabling (U)DMA for %s\n",					drive->name, id->model);				return 1;			}		}	}#endif /* CONFIG_IDEDMA_NEW_DRIVE_LISTINGS */	return 0;}int report_drive_dmaing (ide_drive_t *drive){	struct hd_driveid *id = drive->id;	if ((id->field_valid & 4) && (eighty_ninty_three(drive)) &&	    (id->dma_ultra & (id->dma_ultra >> 11) & 7)) {		if ((id->dma_ultra >> 13) & 1) {			printk(", UDMA(100)");	/* UDMA BIOS-enabled! */		} else if ((id->dma_ultra >> 12) & 1) {			printk(", UDMA(66)");	/* UDMA BIOS-enabled! */		} else {			printk(", UDMA(44)");	/* UDMA BIOS-enabled! */		}	} else if ((id->field_valid & 4) &&		   (id->dma_ultra & (id->dma_ultra >> 8) & 7)) {		if ((id->dma_ultra >> 10) & 1) {			printk(", UDMA(33)");	/* UDMA BIOS-enabled! */		} else if ((id->dma_ultra >> 9) & 1) {			printk(", UDMA(25)");	/* UDMA BIOS-enabled! */		} else {			printk(", UDMA(16)");	/* UDMA BIOS-enabled! */		}	} else if (id->field_valid & 4) {		printk(", (U)DMA");	/* Can be BIOS-enabled! */	} else {		printk(", DMA");	}	return 1;}static int config_drive_for_dma (ide_drive_t *drive){	struct hd_driveid *id = drive->id;	ide_hwif_t *hwif = HWIF(drive);	if (id && (id->capability & 1) && hwif->autodma) {		/* Consult the list of known "bad" drives */		if (ide_dmaproc(ide_dma_bad_drive, drive))			return hwif->dmaproc(ide_dma_off, drive);		/* Enable DMA on any drive that has UltraDMA (mode 3/4/5) enabled */		if ((id->field_valid & 4) && (eighty_ninty_three(drive)))			if ((id->dma_ultra & (id->dma_ultra >> 11) & 7))				return hwif->dmaproc(ide_dma_on, drive);		/* Enable DMA on any drive that has UltraDMA (mode 0/1/2) enabled */		if (id->field_valid & 4)	/* UltraDMA */			if ((id->dma_ultra & (id->dma_ultra >> 8) & 7))				return hwif->dmaproc(ide_dma_on, drive);		/* Enable DMA on any drive that has mode2 DMA (multi or single) enabled */		if (id->field_valid & 2)	/* regular DMA */			if ((id->dma_mword & 0x404) == 0x404 || (id->dma_1word & 0x404) == 0x404)				return hwif->dmaproc(ide_dma_on, drive);		/* Consult the list of known "good" drives */		if (ide_dmaproc(ide_dma_good_drive, drive))			return hwif->dmaproc(ide_dma_on, drive);	}	return hwif->dmaproc(ide_dma_off_quietly, drive);}#ifndef CONFIG_BLK_DEV_IDEDMA_TIMEOUT/* * 1 dmaing, 2 error, 4 intr */static int dma_timer_expiry (ide_drive_t *drive){	byte dma_stat = inb(HWIF(drive)->dma_base+2);#ifdef DEBUG	printk("%s: dma_timer_expiry: dma status == 0x%02x\n", drive->name, dma_stat);#endif /* DEBUG */#if 1	HWGROUP(drive)->expiry = NULL;	/* one free ride for now */#endif	if (dma_stat & 2) {	/* ERROR */		byte stat = GET_STAT();		return ide_error(drive, "dma_timer_expiry", stat);	}	if (dma_stat & 1)	/* DMAing */		return WAIT_CMD;	return 0;}#else /* CONFIG_BLK_DEV_IDEDMA_TIMEOUT */static ide_startstop_t ide_dma_timeout_revovery (ide_drive_t *drive){	ide_hwgroup_t *hwgroup	= HWGROUP(drive);	ide_hwif_t *hwif	= HWIF(drive);	int enable_dma		= drive->using_dma;	unsigned long flags;	ide_startstop_t startstop;	spin_lock_irqsave(&io_request_lock, flags);	hwgroup->handler = NULL;	del_timer(&hwgroup->timer);	spin_unlock_irqrestore(&io_request_lock, flags);	drive->waiting_for_dma = 0;	startstop = ide_do_reset(drive);	if ((enable_dma) && !(drive->using_dma))		(void) hwif->dmaproc(ide_dma_on, drive);	return startstop;}#endif /* CONFIG_BLK_DEV_IDEDMA_TIMEOUT *//* * ide_dmaproc() initiates/aborts DMA read/write operations on a drive. * * The caller is assumed to have selected the drive and programmed the drive's * sector address using CHS or LBA.  All that remains is to prepare for DMA * and then issue the actual read/write DMA/PIO command to the drive. * * For ATAPI devices, we just prepare for DMA and return. The caller should * then issue the packet command to the drive and call us again with * ide_dma_begin afterwards. * * Returns 0 if all went well. * Returns 1 if DMA read/write could not be started, in which case * the caller should revert to PIO for the current request. * May also be invoked from trm290.c */int ide_dmaproc (ide_dma_action_t func, ide_drive_t *drive){//	ide_hwgroup_t *hwgroup		= HWGROUP(drive);	ide_hwif_t *hwif		= HWIF(drive);	unsigned long dma_base		= hwif->dma_base;	byte unit			= (drive->select.b.unit & 0x01);	unsigned int count, reading	= 0;	byte dma_stat;	switch (func) {		case ide_dma_off:			printk("%s: DMA disabled\n", drive->name);		case ide_dma_off_quietly:			outb(inb(dma_base+2) & ~(1<<(5+unit)), dma_base+2);		case ide_dma_on:			drive->using_dma = (func == ide_dma_on);			if (drive->using_dma)				outb(inb(dma_base+2)|(1<<(5+unit)), dma_base+2);			return 0;		case ide_dma_check:			return config_drive_for_dma (drive);		case ide_dma_read:			reading = 1 << 3;		case ide_dma_write:			SELECT_READ_WRITE(hwif,drive,func);			if (!(count = ide_build_dmatable(drive, func)))				return 1;	/* try PIO instead of DMA */			outl(hwif->dmatable_dma, dma_base + 4); /* PRD table */			outb(reading, dma_base);			/* specify r/w */			outb(inb(dma_base+2)|6, dma_base+2);		/* clear INTR & ERROR flags */			drive->waiting_for_dma = 1;			if (drive->media != ide_disk)				return 0;#ifdef CONFIG_BLK_DEV_IDEDMA_TIMEOUT			ide_set_handler(drive, &ide_dma_intr, WAIT_CMD, NULL);	/* issue cmd to drive */#else /* !CONFIG_BLK_DEV_IDEDMA_TIMEOUT */			ide_set_handler(drive, &ide_dma_intr, WAIT_CMD, dma_timer_expiry);	/* issue cmd to drive */#endif /* CONFIG_BLK_DEV_IDEDMA_TIMEOUT */			OUT_BYTE(reading ? WIN_READDMA : WIN_WRITEDMA, IDE_COMMAND_REG);		case ide_dma_begin:			/* 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.			 */			outb(inb(dma_base)|1, dma_base);		/* start DMA */			return 0;		case ide_dma_end: /* returns 1 on error, 0 otherwise */			drive->waiting_for_dma = 0;			outb(inb(dma_base)&~1, dma_base);	/* stop DMA */			dma_stat = inb(dma_base+2);		/* get DMA status */			outb(dma_stat|6, dma_base+2);	/* clear the INTR & ERROR bits */			ide_destroy_dmatable(drive);	/* purge DMA mappings */			return (dma_stat & 7) != 4 ? (0x10 | dma_stat) : 0;	/* verify good DMA status */		case ide_dma_test_irq: /* returns 1 if dma irq issued, 0 otherwise */			dma_stat = inb(dma_base+2);#if 0	/* do not set unless you know what you are doing */			if (dma_stat & 4) {				byte stat = GET_STAT();				outb(dma_base+2, dma_stat & 0xE4);			}#endif			return (dma_stat & 4) == 4;	/* return 1 if INTR asserted */		case ide_dma_bad_drive:		case ide_dma_good_drive:			return check_drive_lists(drive, (func == ide_dma_good_drive));		case ide_dma_verbose:			return report_drive_dmaing(drive);		case ide_dma_timeout:			// FIXME: Many IDE chipsets do not permit command file register access			// FIXME: while the bus-master function is still active.			// FIXME: To prevent deadlock with those chipsets, we must be extremely			// FIXME: careful here (and in ide_intr() as well) to NOT access any			// FIXME: registers from the 0x1Fx/0x17x sets before terminating the			// FIXME: bus-master operation via the bus-master control reg.			// FIXME: Otherwise, chipset deadlock will occur, and some systems will			// FIXME: lock up completely!!#ifdef CONFIG_BLK_DEV_IDEDMA_TIMEOUT			/*			 * Have to issue an abort and requeue the request			 * DMA engine got turned off by a goofy ASIC, and			 * we have to clean up the mess, and here is as good			 * as any.  Do it globally for all chipsets.			 */			outb(0x00, dma_base);		/* stop DMA */			dma_stat = inb(dma_base+2);	/* get DMA status */			outb(dma_stat|6, dma_base+2);	/* clear the INTR & ERROR bits */			printk("%s: %s: Lets do it again!" \				"stat = 0x%02x, dma_stat = 0x%02x\n",				drive->name, ide_dmafunc_verbose(func),				GET_STAT(), dma_stat);			if (dma_stat & 0xF0)				return ide_dma_timeout_revovery(drive);			printk("%s: %s: (restart_request) Lets do it again!" \				"stat = 0x%02x, dma_stat = 0x%02x\n",				drive->name, ide_dmafunc_verbose(func),				GET_STAT(), dma_stat);			return restart_request(drive);  // BUG: return types do not match!!#endif /* CONFIG_BLK_DEV_IDEDMA_TIMEOUT */		case ide_dma_retune:		case ide_dma_lostirq:			printk("ide_dmaproc: chipset supported %s func only: %d\n", ide_dmafunc_verbose(func),  func);			return 1;		default:			printk("ide_dmaproc: unsupported %s func: %d\n", ide_dmafunc_verbose(func), func);			return 1;	}}/* * Needed for allowing full modular support of ide-driver */int ide_release_dma (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;	}	if (hwif->sg_table) {		kfree(hwif->sg_table);		hwif->sg_table = NULL;	}	if ((hwif->dma_extra) && (hwif->channel == 0))		release_region((hwif->dma_base + 16), hwif->dma_extra);	release_region(hwif->dma_base, 8);	return 1;}/* *	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){	printk("    %s: BM-DMA at 0x%04lx-0x%04lx", hwif->name, dma_base, dma_base + num_ports - 1);	if (!request_region(dma_base, num_ports, hwif->name)) {		printk(" -- ERROR, PORT ADDRESSES ALREADY IN USE\n");		return;	}	hwif->dma_base = dma_base;	hwif->dmatable_cpu = pci_alloc_consistent(hwif->pci_dev,						  PRD_ENTRIES * PRD_BYTES,						  &hwif->dmatable_dma);	if (hwif->dmatable_cpu == NULL)		goto dma_alloc_failure;	hwif->sg_table = kmalloc(sizeof(struct scatterlist) * PRD_ENTRIES,				 GFP_KERNEL);	if (hwif->sg_table == NULL) {		pci_free_consistent(hwif->pci_dev, PRD_ENTRIES * PRD_BYTES,				    hwif->dmatable_cpu, hwif->dmatable_dma);		goto dma_alloc_failure;	}	hwif->dmaproc = &ide_dmaproc;	if (hwif->chipset != ide_trm290) {		byte dma_stat = inb(dma_base+2);		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");	return;dma_alloc_failure:	printk(" -- ERROR, UNABLE TO ALLOCATE DMA TABLES\n");}/* * Fetch the DMA Bus-Master-I/O-Base-Address (BMIBA) from PCI space: */unsigned long __init ide_get_or_set_dma_base (ide_hwif_t *hwif, int extra, const char *name){	unsigned long	dma_base = 0;	struct pci_dev	*dev = hwif->pci_dev;#ifdef CONFIG_BLK_DEV_IDEDMA_FORCED	int second_chance = 0;second_chance_to_dma:#endif /* CONFIG_BLK_DEV_IDEDMA_FORCED */	if (hwif->mate && hwif->mate->dma_base) {		dma_base = hwif->mate->dma_base - (hwif->channel ? 0 : 8);	} else {		dma_base = pci_resource_start(dev, 4);		if (!dma_base) {			printk("%s: dma_base is invalid (0x%04lx)\n", name, dma_base);			dma_base = 0;		}	}#ifdef CONFIG_BLK_DEV_IDEDMA_FORCED	if ((!dma_base) && (!second_chance)) {		unsigned long set_bmiba = 0;		second_chance++;		switch(dev->vendor) {			case PCI_VENDOR_ID_AL:				set_bmiba = DEFAULT_BMALIBA; break;			case PCI_VENDOR_ID_VIA:				set_bmiba = DEFAULT_BMCRBA; break;			case PCI_VENDOR_ID_INTEL:				set_bmiba = DEFAULT_BMIBA; break;			default:				return dma_base;		}		pci_write_config_dword(dev, 0x20, set_bmiba|1);		goto second_chance_to_dma;	}#endif /* CONFIG_BLK_DEV_IDEDMA_FORCED */	if (dma_base) {		if (extra) /* PDC20246, PDC20262, HPT343, & HPT366 */			request_region(dma_base+16, extra, name);		dma_base += hwif->channel ? 8 : 0;		hwif->dma_extra = extra;		switch(dev->device) {			/*			 * This is buggy.  Device numbers are not unique			 * between vendors.  We should be checking			 * both dev->vendor and dev->device			 */			case PCI_DEVICE_ID_AL_M5219:			case PCI_DEVICE_ID_AMD_VIPER_7409:			case PCI_DEVICE_ID_CMD_643:			case PCI_DEVICE_ID_WINBOND_82C105:				outb(inb(dma_base+2) & 0x60, dma_base+2);				if (inb(dma_base+2) & 0x80) {					printk("%s: simplex device: DMA forced\n", name);				}				break;			default:				/*				 * If the device claims "simplex" DMA,				 * this means only one of the two interfaces				 * can be trusted with DMA at any point in time.				 * So we should enable DMA only on one of the				 * two interfaces.				 */				if ((inb(dma_base+2) & 0x80)) {	/* simplex device? */					if ((!hwif->drives[0].present && !hwif->drives[1].present) ||					    (hwif->mate && hwif->mate->dma_base)) {						printk("%s: simplex device:  DMA disabled\n", name);						dma_base = 0;					}				}		}	}	return dma_base;}

⌨️ 快捷键说明

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