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

📄 ide-dma.c

📁 em85xx的大硬盘修正代码包
💻 C
📖 第 1 页 / 共 3 页
字号:
//	printk ("***************\n");	do {		unsigned char *virt_addr = bh->b_data;		unsigned int size = bh->b_size;		if (nents >= PRD_ENTRIES)			return 0;		while ((bh = bh->b_reqnext) != NULL) {			if ((virt_addr + size) != (unsigned char *) bh->b_data)				break;			size += bh->b_size;		}		memset(&sg[nents], 0, sizeof(*sg));		sg[nents].address = virt_addr;		sg[nents].length = size;		nents++;			} while (bh != NULL);//	return pci_map_sg(PCIDEV(hwif), sg, nents, hwif->sg_dma_direction);	{		int i;		for (i = 0; i < nents; i++, sg++) {//			consistent_sync(sg->address, sg->length, direction);			sg->dma_address = virt_to_bus(sg->address);		}	}	return nents;}/* * ide_build_dmatable() prepares a dma request. * Returns 0 if all went okay, returns 1 otherwise. * May also be invoked from trm290.c */int ide_build_dmatable (ide_drive_t *drive, ide_dma_action_t func){	unsigned int *table = HWIF(drive)->dmatable_cpu;#ifdef CONFIG_BLK_DEV_TRM290	unsigned int is_trm290_chipset = (HWIF(drive)->chipset == ide_trm290);#else	const int is_trm290_chipset = 0;#endif	unsigned int count = 0;	int i;	struct scatterlist *sg;	HWIF(drive)->sg_nents = i = ide_build_sglist(HWIF(drive), HWGROUP(drive)->rq);	if (!i)		return 0;	sg = HWIF(drive)->sg_table;	while (i && sg_dma_len(sg)) {		u32 cur_addr;		u32 cur_len;		cur_addr = sg_dma_address(sg);		cur_len = sg_dma_len(sg);		/*		 * Fill in the dma table, without crossing any 64kB boundaries.		 * Most hardware requires 16-bit alignment of all blocks,		 * but the trm290 requires 32-bit alignment.		 */		while (cur_len) {			if (count++ >= PRD_ENTRIES) {				printk("%s: DMA table too small\n", drive->name);				goto use_pio_instead;			} else {				u32 xcount, bcount = 0x10000 - (cur_addr & 0xffff);				if (bcount > cur_len)					bcount = cur_len;				*table++ = cpu_to_le32(cur_addr);				xcount = bcount & 0xffff;				if (is_trm290_chipset)					xcount = ((xcount >> 2) - 1) << 16;				if (xcount == 0x0000) {					/* 					 * Most chipsets correctly interpret a length of 0x0000 as 64KB,					 * but at least one (e.g. CS5530) misinterprets it as zero (!).					 * So here we break the 64KB entry into two 32KB entries instead.					 */					if (count++ >= PRD_ENTRIES) {						printk("%s: DMA table too small\n", drive->name);						goto use_pio_instead;					}					*table++ = cpu_to_le32(0x8000);					*table++ = cpu_to_le32(cur_addr + 0x8000);					xcount = 0x8000;				}				*table++ = cpu_to_le32(xcount);				cur_addr += bcount;				cur_len -= bcount;			}		}		sg++;		i--;	}	if (count) {		if (!is_trm290_chipset)			*--table |= cpu_to_le32(0x80000000);		return count;	}	printk("%s: empty DMA table?\n", drive->name);use_pio_instead:	pci_unmap_sg(PCIDEV(HWIF(drive)),		     HWIF(drive)->sg_table,		     HWIF(drive)->sg_nents,		     HWIF(drive)->sg_dma_direction);	HWIF(drive)->sg_dma_active = 0;	return 0; /* revert to PIO for this request */}/* Teardown mappings after DMA has completed.  */void ide_destroy_dmatable (ide_drive_t *drive){	struct pci_dev *dev = PCIDEV(HWIF(drive));	struct scatterlist *sg = HWIF(drive)->sg_table;	int nents = HWIF(drive)->sg_nents;	pci_unmap_sg(dev, sg, nents, HWIF(drive)->sg_dma_direction);	HWIF(drive)->sg_dma_active = 0;}/* *  For both Blacklisted and Whitelisted drives. *  This is setup to be called as an extern for future support *  to other special driver code. */int check_drive_lists (ide_drive_t *drive, int good_bad){	struct hd_driveid *id = drive->id;#ifdef CONFIG_IDEDMA_NEW_DRIVE_LISTINGS	if (good_bad) {		return in_drive_list(id, drive_whitelist);	} else {		int blacklist = in_drive_list(id, drive_blacklist);		if (blacklist)			printk("%s: Disabling (U)DMA for %s\n", drive->name, id->model);		return(blacklist);	}#else /* !CONFIG_IDEDMA_NEW_DRIVE_LISTINGS */	const char **list;	if (good_bad) {		/* 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);	int autodma = hwif->autodma;#ifndef CONFIG_ARCH_JASPER // we dont have no BIOS	if (hwif->chipset != ide_trm290 && hwif->chipset != ide_acorn)	{		/* take note of what the bios did when setting up		* the interface.  If the BIOS didn't configure		* the drive for DMA mode, then we should not use		* it unless we are prepared to configure the		* drive as well.  -- rmk		*/		byte dma_stat = inb(hwif->dma_base+BMIS_OFFSET);		if (drive->select.b.unit) 		{			if (!(dma_stat & 0x40))				autodma = 0;		}		else		{			if (!(dma_stat & 0x20))				autodma = 0;		}	}#endif	printk ("config_drive_for_dma:\n");	printk (" capability    = 0x%04x\n", id->capability);	printk (" field_valid   = 0x%04x\n", id->field_valid);	printk (" dma_ultra     = 0x%04x\n", id->dma_ultra);	printk (" dma_lword (s) = 0x%04x\n", id->dma_1word);	printk (" dma_mword (m) = 0x%04x\n", id->dma_mword);	printk (" autodma       = 0x%04x\n", autodma);	if (id && (id->capability & 1) && 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))//			{//				printk("UltraDMA mode 3/4/5\n");//				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))//			{//				printk("UltraDMA mode 0/1/2\n");//				return hwif->dmaproc(ide_dma_on, drive);//			}		/* Enable DMA on any drive that has UltraDMA (mode 2) supported, but not enabled */		if (id->dma_ultra & (1 << 2))		{			printk("Jasper IDE controller activated - UDMA mode 2\n");			outl (0x3, JASPER_IDE_BASE + 0x54);		// enable UDMA			outl (0x22,JASPER_IDE_BASE + 0x58);		// UDMA2 - Cycle time = 4 clocks, Ready to Pause = 8 clocks			ide_config_drive_speed (drive, XFER_UDMA_2);			ide_config_drive_speed (drive, XFER_UDMA_2);			return hwif->dmaproc(ide_dma_on, drive);		}		/* Enable DMA on any drive that has UltraDMA (mode 1) supported, but not enabled */		if (id->dma_ultra & (1 << 1))		{			printk("Jasper IDE controller activated - UDMA mode 1\n");			outl (0x3, JASPER_IDE_BASE + 0x54);		// enable UDMA			outl (0x11,JASPER_IDE_BASE + 0x58);		// UDMA1 - Cycle time = 6 clocks, Ready to Pause = 10 clocks			ide_config_drive_speed (drive, XFER_UDMA_1);			ide_config_drive_speed (drive, XFER_UDMA_1);			return hwif->dmaproc(ide_dma_on, drive);		}		/* Enable DMA on any drive that has UltraDMA (mode 0) supported, but not enabled */		if (id->dma_ultra & (1 << 1))		{			printk("Jasper IDE controller activated - UDMA mode 0\n");			outl (0x3, JASPER_IDE_BASE + 0x54);		// enable UDMA			outl (0x00,JASPER_IDE_BASE + 0x58);		// UDMA0 - Cycle time = 6 clocks, Ready to Pause = 10 clocks			ide_config_drive_speed (drive, XFER_UDMA_0);			ide_config_drive_speed (drive, XFER_UDMA_0);			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 */		{			// XXX vincent			if ((id->dma_mword & 0x404) == 0x404 || (id->dma_1word & 0x404) == 0x404)				return hwif->dmaproc(ide_dma_on, drive);			// allow any mode			if (id->dma_mword & 0xff00)	// single word dma				return hwif->dmaproc(ide_dma_on, drive);			if (id->dma_1word & 0xff00)	// multiword dma				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);	}	printk ("DMA disabled quitely\n");	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+BMIS_OFFSET);#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 */

⌨️ 快捷键说明

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