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

📄 ide-ep93xx.c

📁 ep9315平台下硬盘驱动的源码
💻 C
📖 第 1 页 / 共 4 页
字号:
		return 0;	return 1;}/***************************************************************************** * * ep93xx_ide_dma_read() * * This function sets up a dma read operation. * ****************************************************************************/static intep93xx_ide_dma_read(ide_drive_t *drive){	u8 lba48 = (drive->addressing == 1) ? 1 : 0;	struct request *rq = HWGROUP(drive)->rq;	unsigned int flags, i;	ide_hwif_t *hwif = HWIF(drive);	task_ioreg_t command = WIN_NOP;	DPRINTK("%s: ep93xx_ide_dma_read\n", drive->name);	DPRINTK("    %ld, %ld\n", HWGROUP(drive)->rq->sector,		HWGROUP(drive)->rq->nr_sectors);	/*	 * Check if we are already transferring on this dma channel.	 */	if (hwif->sg_dma_active || drive->waiting_for_dma) {		DPRINTK("%s: dma_read: dma already active \n", drive->name);		return 1;	}	/*	 * Compute the array index used for this request.	 */	i = drive->name[2] == 'a' ? 0 : 2;	/*	 * See if this request matches the most recent request, and that the	 * most recent request ended in error.	 */	if (g_bad && (g_cmd == READ) && (g_drive == drive) &&	    (g_sector == HWGROUP(drive)->rq->sector) &&	    (g_nr_sectors == HWGROUP(drive)->rq->nr_sectors)) {		g_cur_retries++;		if (g_cur_retries > g_max_retries[i])			g_max_retries[i]++;		if (g_cur_retries == RETRIES_PER_TRANSFER) {			g_bad = 0;			return 1;		}	} else {		g_cur_retries = 0;		g_cmd = READ;		g_drive = drive;		g_sector = HWGROUP(drive)->rq->sector;		g_nr_sectors = HWGROUP(drive)->rq->nr_sectors;	}	/*	 * Save information about this transfer.	 */	g_xfers[i]++;	g_sectors[i] += HWGROUP(drive)->rq->nr_sectors;	/*	 * Indicate that we're waiting for dma.	 */	drive->waiting_for_dma = 1;	/*	 * Configure DMA M2M channel flags for a source address hold, h/w	 * initiated P2M transfer.	 */	flags = (SOURCE_HOLD | TRANSFER_MODE_HW_P2M);	if (drive->current_speed & 0x20) {		flags |= (WS_IDE_MDMA_READ << WAIT_STATES_SHIFT);		/*		 * MDMA data register address.		 */		hwif->dma_base = IDEMDMADATAIN - IO_BASE_VIRT + IO_BASE_PHYS;	} else {		flags |= (WS_IDE_UDMA_READ << WAIT_STATES_SHIFT);		/*		 * UDMA data register address.		 */		hwif->dma_base = IDEUDMADATAIN - IO_BASE_VIRT + IO_BASE_PHYS;	}	/*	 * Configure the dma interface for this IDE operation.	 */	if (ep93xx_dma_config(hwif->hw.dma, 0, flags, ep93xx_ide_callback,			      (unsigned int)drive) != 0) {		DPRINTK("%s: ep93xx_ide_dma_read: ERROR- dma config failed",				drive->name);		drive->waiting_for_dma = 0;		/*		 * Fail.		 */		return 1;	}	/*	 * Build the table of dma-able buffers.	 */	if (!(g_prd_count = ide_build_dmatable(drive))) {		DPRINTK("%s: ep93xx_ide_dma_read: ERROR- failed to build dma table",			drive->name);		drive->waiting_for_dma = 0;		/*		 * Fail, try PIO instead of DMA		 */		return 1;	}	/*	 * Indicate that the scatter gather is active.	 */	hwif->sg_dma_active = 1;	/*	 * test stuff	 */	g_prd_total = g_prd_count;	g_prd_returned = 0;	DPRINTK("%d buffers\n", g_prd_total);	/*	 * Prepare the dma interface with some buffers from the	 * dma_table.	 */	do {		/*		 * Add a buffer to the dma interface.		 */		if (ep93xx_dma_add_buffer(hwif->hw.dma, hwif->dma_base,					  hwif->dmatable_cpu[0],					  hwif->dmatable_cpu[1], 0,					  g_prd_count) != 0)			break;		hwif->dmatable_cpu += 2;		/*		 * Decrement the count of dmatable entries		 */		g_prd_count--;	} while (g_prd_count);	/*	 * Nothing further is required if this is not a ide_disk (i.e. an ATAPI	 * device).	 */	if (drive->media != ide_disk)		return 0;	/*	 * Determine the command to be sent to the device.	 */	command = (lba48) ? WIN_READDMA_EXT : WIN_READDMA;	if (rq->cmd == IDE_DRIVE_TASKFILE) {		ide_task_t *args = rq->special;		command = args->tfRegister[IDE_COMMAND_OFFSET];	}	/*	 * Send the read command to the device.	 */	ide_execute_command(drive, command, &ep93xx_ide_dma_intr, 2*WAIT_CMD,			    &ep93xx_idedma_timer_expiry);	/*	 * initiate the dma transfer.	 */	return hwif->ide_dma_begin(drive);}/***************************************************************************** * * ep93xx_ide_dma_first_read() * * This function handles the very first dma read operation. * ****************************************************************************/static intep93xx_ide_dma_first_read(ide_drive_t *drive){	ide_hwif_t *hwif = HWIF(drive);	/*	 * Switch the hwif to the real read routine.	 */	hwif->ide_dma_read = ep93xx_ide_dma_read;	/*	 * Register a proc entry for the statistics that we gather.	 */#ifdef CONFIG_PROC_FS	create_proc_info_entry("ide/ep93xx", 0, 0, ep93xx_get_info);#endif	/*	 * Do the actual read.	 */	return hwif->ide_dma_read(drive);}/***************************************************************************** * * ep93xx_ide_dma_write() * * This function sets up a dma write operation. * ****************************************************************************/static intep93xx_ide_dma_write(ide_drive_t *drive){	u8 lba48 = (drive->addressing == 1) ? 1 : 0;	struct request *rq = HWGROUP(drive)->rq;	unsigned int flags, i;	ide_hwif_t *hwif = HWIF(drive);	task_ioreg_t command = WIN_NOP;	DPRINTK("%s: ep93xx_ide_dma_write\n", drive->name);	/*	 * Check if we are already transferring on this dma channel.	 */	if (hwif->sg_dma_active || drive->waiting_for_dma) {		DPRINTK("%s: dma_write - dma is already active \n",			drive->name);		return 1;	}	/*	 * Compute the array index used for this request.	 */	i = drive->name[2] == 'a' ? 1 : 3;	/*	 * See if this request matches the most recent request, and that the	 * most recent request ended in error.	 */	if (g_bad && (g_cmd == WRITE) && (g_drive == drive) &&	    (g_sector == HWGROUP(drive)->rq->sector) &&	    (g_nr_sectors == HWGROUP(drive)->rq->nr_sectors)) {		g_cur_retries++;		if (g_cur_retries > g_max_retries[i])			g_max_retries[i]++;		if (g_cur_retries == RETRIES_PER_TRANSFER) {			g_bad = 0;			return 1;		}	} else {		g_cur_retries = 0;		g_cmd = WRITE;		g_drive = drive;		g_sector = HWGROUP(drive)->rq->sector;		g_nr_sectors = HWGROUP(drive)->rq->nr_sectors;	}	/*	 * Save information about this transfer.	 */	g_xfers[i]++;	g_sectors[i] += HWGROUP(drive)->rq->nr_sectors;	/*	 * Indicate that we're waiting for dma.	 */	drive->waiting_for_dma = 1;	/*	 * Configure DMA M2M channel flags for a destination address	 * hold, h/w initiated M2P transfer.	 */	flags = (DESTINATION_HOLD | TRANSFER_MODE_HW_M2P);	/*	 * Determine if we need the MDMA or UDMA data register.	 */	if (drive->current_speed & 0x20) {		flags |= (WS_IDE_MDMA_WRITE << WAIT_STATES_SHIFT);		/*		 * MDMA data register address.		 */		hwif->dma_base = IDEMDMADATAOUT - IO_BASE_VIRT + IO_BASE_PHYS;	} else {		flags |= (WS_IDE_UDMA_WRITE << WAIT_STATES_SHIFT);		/*		 * UDMA data register address.		 */		hwif->dma_base = IDEUDMADATAOUT - IO_BASE_VIRT + IO_BASE_PHYS;	}	/*	 * Configure the dma interface for this IDE operation.	 */	if (ep93xx_dma_config(hwif->hw.dma, 0, flags, ep93xx_ide_callback,			      (unsigned int)drive) != 0) {		drive->waiting_for_dma = 0;		return 1;	}	/*	 * Build the table of dma-able buffers.	 */	if (!(g_prd_count = ide_build_dmatable(drive))) {		drive->waiting_for_dma = 0;		/*		 * Fail, try PIO instead of DMA		 */		return 1;	}	/*	 * Indicate that we're waiting for dma.	 */	hwif->sg_dma_active = 1;	/*	 * test stuff	 */	g_prd_total = g_prd_count;	g_prd_returned = 0;	/*	 * Prepare the dma interface with some buffers from the	 * dma_table.	 */	do {		/*		 * Add a buffer to the dma interface.		 */		if (ep93xx_dma_add_buffer(hwif->hw.dma,					  hwif->dmatable_cpu[0],					  hwif->dma_base,					  hwif->dmatable_cpu[1], 0,					  g_prd_count) != 0)			break;		hwif->dmatable_cpu += 2;		/*		 * Decrement the count of dmatable entries		 */		g_prd_count--;	} while (g_prd_count);	/*	 * Nothing further is required if this is not a ide_disk (i.e. an ATAPI	 * device).	 */	if (drive->media != ide_disk)		return 0;	/*	 * Determine the command to be sent to the device.	 */	command = (lba48) ? WIN_WRITEDMA_EXT : WIN_WRITEDMA;	if (rq->cmd == IDE_DRIVE_TASKFILE) {		ide_task_t *args = rq->special;		command = args->tfRegister[IDE_COMMAND_OFFSET];	}	/*	 * Send the write dma command to the device.	 */	ide_execute_command(drive, command, &ep93xx_ide_dma_intr, 2*WAIT_CMD,			    &ep93xx_idedma_timer_expiry);	/*	 * initiate the dma transfer.	 */	return hwif->ide_dma_begin(drive);}/***************************************************************************** * * ep93xx_ide_dma_begin() * * This function initiates a dma transfer. * ****************************************************************************/static intep93xx_ide_dma_begin(ide_drive_t *drive){	ide_hwif_t *hwif = HWIF(drive);	DPRINTK("%s: ep93xx_ide_dma_begin\n", drive->name);	/*	 * The transfer is not bad yet.	 */	g_bad = 0;	/*	 * Configure the ep93xx ide controller for a dma operation.	 */	if (HWGROUP(drive)->rq->cmd == READ)		ep93xx_rwproc(drive, 0);	else		ep93xx_rwproc(drive, 1);	/*	 * Start the dma transfer.	 */	ep93xx_dma_start(hwif->hw.dma, 1, NULL);	return 0;}/***************************************************************************** * * ep93xx_ide_dma_end() * * This function performs any tasks needed to cleanup after a dma transfer. * Returns 1 if an error occured, and 0 otherwise. * ****************************************************************************/static intep93xx_ide_dma_end(ide_drive_t *drive){	ide_hwif_t * hwif = HWIF(drive);	int i, stat;	DPRINTK("%s: ep93xx_ide_dma_end\n", drive->name);	/*	 * See if there is any data left in UDMA FIFOs.  For a read, first wait	 * until either the DMA is done or the FIFO is empty.  If there is any	 * residual data in the FIFO, there was an error in the transfer.	 */	if (HWGROUP(drive)->rq->cmd == READ) {		do {			i = inl(IDEUDMARFST);		} while (!ep93xx_dma_is_done(hwif->hw.dma) &&			 ((i & 15) != ((i >> 4) & 15)));		udelay(1);	}	else		i = inl(IDEUDMAWFST);	if ((i & 15) != ((i >> 4) & 15))		g_bad = 1;            	/*	 * See if all of the buffers were returned by the DMA driver.  If not,	 * then a transfer error has occurred.	 */	if (!ep93xx_dma_is_done(hwif->hw.dma))		g_bad = 1;	/*	 * Put the dma interface into pause mode.	 */	ep93xx_dma_pause(hwif->hw.dma, 1, 0);	ep93xx_dma_flush(hwif->hw.dma);	/*	 * Enable PIO mode on the IDE interface.	 */	ep93xx_set_pio();	/*	 * Indicate there's no dma transfer currently in progress.	 */	hwif->sg_dma_active = 0;	drive->waiting_for_dma = 0;	/*	 * Get status from the ide device.	 */	stat = HWIF(drive)->INB(IDE_STATUS_REG);	/*	 * If this is an ATAPI device and it reported an error, then simply	 * return a DMA success.	 */	if ((drive->media != ide_disk) && (stat & ERR_STAT))		return 0;	/*	 * See if a CRC error occurred.  If so, then a transfer error has	 * occurred.	 */	if ((stat & ERR_STAT) && (HWIF(drive)->INB(IDE_ERROR_REG) & ICRC_ERR))		g_bad = 1;	/*	 * Compute the array index used for this request.	 */	i = HWGROUP(drive)->rq->cmd == READ ? 0 : 1;	i += drive->name[2] == 'a' ? 0 : 2;	/*	 * Fail if an error occurred during the DMA.	 */	if (g_bad) {		/*		 * Increment the number of retries for this request, along with		 * the number of consecutive errors for this drive.		 */		g_retries[i]++;		g_errors[i]++;		/*		 * See if the maximum number of consective errors has occurred.

⌨️ 快捷键说明

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