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

📄 doch_ata.c

📁 电子盘DEMO板程序
💻 C
📖 第 1 页 / 共 5 页
字号:
			dmaParams.bDestAddrPtr		  = (FLByte*)buf + dmaRemainderOffset;
	
			dmaParams.wFrameSize		  = (FLWord)(dmaFrameSize * DOCH_SECTOR_SIZE);
			dmaParams.wFramesInBlock	  = (FLWord)(dmaBlocks);
	
			dmaParams.wFramesXferred	  = 0;
	
			DOCH_DMA_CONFIG(&dmaParams);
			if(dmaParams.fDmaStatus != 0)
			{
				DBG_PRINT_ERR(FLZONE_API, "io_input(): DOCH_DMA_CONFIG_TRANSACTION_DEVICE_TO_HOST Failed\r\n");
				return DOCH_GeneralFailure;
			}
	
	#ifdef DOCH_USE_BURST_MODE_READ
			if(pdev->bUseBurst)
			{
			    /*Set DOCH BURST READ Control Register*/
				DOCHWRITE_CTRL_REG (pdev->bRegBase,
									HIB_BURST_READ_MODE_CTRL_REG,
									(DOCH_BURST_ENABLE | DOCH_BURST_HOLD | DOCH_BURST_LENGTH | DOCH_BURST_LATENCY | DOCH_BURST_WAIT_STATE) );
		
				/*Set up the DMA transfer - Device*/
				wDmaRegValue &= ~(DOCH_DMA_REQ_EDGE);
			}
	#endif /*DOCH_USE_BURST_MODE_READ*/
	
			/*Set up the DMA transfer - Device*/
			DOCHWRITE_CTRL_REG (pdev->bRegBase, HIB_DMA_CTRL_REG, (wDmaRegValue | DOCH_DMA_REQ_ENABLE));
	
			/*Write ATA registers*/
			DOCHWRITE_ATA_REG (pdev->bRegBase, DOCH_SECTOR_CNT_REG,    (FLByte)(dmaFrameSize*dmaBlocks));
			DOCHWRITE_ATA_REG (pdev->bRegBase, DOCH_SECTOR_NO_REG,     (FLByte)(dmaFirstSectorToPerform));
			DOCHWRITE_ATA_REG (pdev->bRegBase, DOCH_CYLINDER_LOW_REG,  (FLByte)(dmaFirstSectorToPerform>>8));
			DOCHWRITE_ATA_REG (pdev->bRegBase, DOCH_CYLINDER_HIGH_REG, (FLByte)(dmaFirstSectorToPerform>>16));
			DOCHWRITE_ATA_REG (pdev->bRegBase, DOCH_DRIVE_HEAD_REG,    ((regs->bDriveHead & 0xF0) |
																		((FLByte)((dmaFirstSectorToPerform>>24) & 0x0F))));
			DOCHWRITE_ATA_REG (pdev->bRegBase, DOCH_FEATURES_REG,	   regs->bFeaturesError);
	
			/*Write ATA command*/
			/*This will also start DMA transfer*/
	        DOCHWRITE_ATA_REG (pdev->bRegBase, DOCH_COMMAND_REG, regs->bCommandStatus);
	
	#ifdef DOCH_USE_BURST_MODE_READ
			if(pdev->bUseBurst)
			{
				/*Enter BURST Mode*/
				DOCH_HOST_ENTER_READ_BURST_MODE
			}
	#endif /*DOCH_USE_BURST_MODE_READ*/
		
			/*Wait for DMA transfer to complete*/
			dmaParams.bOpType = DOCH_DMA_WAIT_FOR_READ_TRANSACTION_END;
			DOCH_DMA_CONFIG(&dmaParams);
	
	#ifdef DOCH_USE_BURST_MODE_READ
			if(pdev->bUseBurst)
			{
				/*Exit BURST Mode*/
				DOCH_HOST_EXIT_READ_BURST_MODE
		
			   /*Set DOCH BURST READ Control Register*/
				DOCHWRITE_CTRL_REG (pdev->bRegBase, HIB_BURST_READ_MODE_CTRL_REG , DOCH_BURST_DISABLE);
			}
	#endif /*DOCH_USE_BURST_MODE_READ*/
	
			/*Disable DMA in Device*/
			DOCHWRITE_CTRL_REG (pdev->bRegBase, HIB_DMA_CTRL_REG, (wDmaRegValue &= ~DOCH_DMA_REQ_ENABLE));

			/*Check status of DMA operation*/
			if(dmaParams.fDmaStatus != 0)
			{
				DBG_PRINT_ERR(FLZONE_API, "io_input(): DOCH_DMA_WAIT_FOR_READ_TRANSACTION_END Failed\r\n");

				DBG_PRINT_ERR(FLZONE_ATA, "ready(): Resetting device... ");
				rc = doch_reset (pdev->wSocketNo, devNum);
				if(rc == DOCH_OK)
					DBG_PRINT_ERR(FLZONE_ATA, "Passed! \r\n");
				else
				{
					DBG_PRINT_ERR(FLZONE_ATA, "Failed! \r\n");
					return rc;
				}

				return DOCH_GeneralFailure;
			}

		}	
		
		/*If DRQ is larger the 1 and some sectors are left to be transfered, 
		  perform another DMA transaction with altered frame/block sizes*/
		if(dmaRemainderSectors > 0)
		{
			dmaRemainderOffset		= (dmaBlocks * dmaFrameSize * DOCH_SECTOR_SIZE);
			dmaFirstSectorToPerform = (dmaFirstReqSector + (dmaBlocks * dmaFrameSize)); 

			dmaBlocks  = 1;
			dmaFrameSize = dmaRemainderSectors;
			
			dmaRemainderSectors = 0;

			goto dochIoInputDmaSequence;
		}

	}
	else
	#endif /*DOCH_DMA_CONFIG*/

	/*PIO transfer was requested*/
	{
		/*Write ATA command register*/
        DOCHWRITE_ATA_REG (pdev->bRegBase, DOCH_COMMAND_REG, regs->bCommandStatus);

		/* Check DRQ ready and not BSY before data xfer */
		(rc = ready(pdev, devNum, DOCH_STATUS_REG, (DOCH_READY | DOCH_DRQ | DOCH_BUSY | DOCH_ERROR),
													DOCH_READY | DOCH_DRQ, DOCH_LONG_WAIT));
		if(rc != DOCH_OK)
		{
			DBG_PRINT_ERR(FLZONE_ATA, "\r\nio_input(): ATA not Ready (before data XFER) \r\n");
			DBG_PRINT_ERR_PRM(FLZONE_ATA, (FLTXT("rc = 0x%x \r\n"),rc));
			return rc;
		}

		/*Perform per-sector
		1. Wait until device is ready to receive data
		2. Xfer 1 sector*/
		if((pdev->device[devNum].dataTransferMode == DOCH_DATA_MODE_SINGLE) || /*Single Sector was requested*/
			  (!(regs->bCommandStatus == DOCH_VSCMD_READ_PARTITION)) )			/*Command is OTHER than Read Partition*/
		{
			for(secPerformed=1; secPerformed<=sectors_to_read; secPerformed++)
			{
				/*Perform data xfer*/
				if( (DOCHBLK_READ(pdev->bRegBase,
								 ((FLByte*)buf + offset),
								 1)) != 0)
				{
					return DOCH_ReadFault;
				}

				/* Check DRQ ready and not BSY before next data xfer */
				/* (don`t perform after LAST sector was transfered) */
				if(secPerformed != sectors_to_read)
				{
					(rc = ready(pdev, devNum, DOCH_STATUS_REG, (DOCH_READY | DOCH_DRQ | DOCH_BUSY | DOCH_ERROR),
																DOCH_READY | DOCH_DRQ, DOCH_LONG_WAIT));
					if(rc != DOCH_OK)
					{
						DBG_PRINT_ERR(FLZONE_ATA, "\r\nio_input(): ATA not Ready (before data XFER) \r\n");
						DBG_PRINT_ERR_PRM(FLZONE_ATA, (FLTXT("rc = 0x%x \r\n"),rc));
						return rc;
					}
				}

				offset += DOCH_SECTOR_SIZE;
			}

		}
		else if(pdev->device[devNum].dataTransferMode == DOCH_DATA_MODE_MULT)
		{
			multCount = (FLByte)pdev->device[devNum].dwMulti_Current;

			for(secPerformed=0;	secPerformed<sectors_to_read;)
			{
				/*Determine how many sectors to read this cycle*/
				if((secPerformed + multCount) > sectors_to_read)
					multSecToRead = (sectors_to_read - secPerformed);
				else
					multSecToRead = multCount;

				/*Perform data xfer*/
				if( (DOCHBLK_READ(pdev->bRegBase, 
								  (FLByte*)buf + offset,
								  (multSecToRead))) != 0)
				{
					return DOCH_ReadFault;
				}

				/* Check DRQ ready and not BSY before next data xfer */
				/* (don`t perform after LAST sector was transfered) */
				if((secPerformed + multSecToRead) != sectors_to_read)
				{
					(rc = ready(pdev, devNum, DOCH_STATUS_REG, (DOCH_READY | DOCH_DRQ | DOCH_BUSY | DOCH_ERROR),
																DOCH_READY | DOCH_DRQ, DOCH_LONG_WAIT));
					if(rc != DOCH_OK)
					{
						DBG_PRINT_ERR(FLZONE_ATA, "\r\nio_input(): ATA not Ready (before data XFER) \r\n");
						DBG_PRINT_ERR_PRM(FLZONE_ATA, (FLTXT("rc = 0x%x \r\n"),rc));
						return rc;
					}
				}

				/*Advance number of written sectors and update pointer to buffer*/
				secPerformed +=  multSecToRead;
				offset		 += (multSecToRead * DOCH_SECTOR_SIZE);
			}
		}
		else
		{
			DBG_PRINT_ERR(FLZONE_ATA, "io_input(): Transfer Mode ");
			DBG_PRINT_ERR_PRM(FLZONE_ATA, (FLTXT("0x%x "), pdev->device[devNum].dataTransferMode));
			DBG_PRINT_ERR(FLZONE_ATA, "not supported\r\n");

			return DOCH_FeatureNotSupported;

		}	/* End of if/else on pdev->device[devNum].dataTransferMode */

	}	/* End of else on if(pdev->bUseDMA) */

	/* wait until device is ready */
	rc = ready(pdev, devNum, DOCH_STATUS_REG, (DOCH_READY | DOCH_BUSY), 
											   DOCH_READY, DOCH_SHORT_WAIT);
	if (rc != DOCH_OK)
	{
		DBG_PRINT_ERR(FLZONE_ATA, "\r\nio_input(): ATA not Ready\r\n");
		DBG_PRINT_ERR_PRM(FLZONE_ATA, (FLTXT("rc = 0x%x \r\n"),rc));
		return rc;
	}

	/* check operation's status; this also clears IRQ */
	status = DOCHREAD_ATA_REG(pdev->bRegBase, DOCH_STATUS_REG);
	if((status & (DOCH_BUSY | DOCH_READY | DOCH_ERROR)) != DOCH_READY)
	{
		if((status & DOCH_BUSY) == DOCH_BUSY)
			return DOCH_ATABusyNotCleared;
		else if((status & DOCH_READY) != DOCH_READY)
			return DOCH_ATANotReady;
		else if((status & DOCH_ERROR) == DOCH_ERROR)
			return DOCH_ATAErrorDetected;
	}

    return rc;
}

/****************************************************************************** 
 *                                                                            * 
 *                             i o _ o u t p u t                              * 
 *                                                                            * 
 *  Write sectors to DOCH device.                                             * 
 *                                                                            * 
 *  Parameters :                                                              *
 *      pdev                 : device to act on                               *
 *		regs				 : DOCH_Registers								  *
 *      buf                  : user buffer to write from                      *
 *		secNum				 : # of sectors to write						  *
 *                                                                            * 
 *  Returns :                                                                 * 
 *      DOCH_OK in success, otherwise respective error code.                  *
 *                                                                            * 
 ******************************************************************************/
DOCH_Error io_output ( DOCH_Socket     * pdev,
					   FLSNative 		 devNum,
					   DOCH_Registers  * regs,
                       void            * buf, 
					   FLNative			 secNum)
{
    FLNative    sectors_to_write;
	FLNative	secPerformed;
	FLNative	offset = 0;
    DOCH_Error  rc;
	FLSNative 	status;
	FLByte		multCount = 0;
	
	/*Calculate how many sectors are to be written*/
	/*Note: "0" - 256 Sectors to write*/
	sectors_to_write = (secNum ? secNum : 256);

	/* First we write the device head register to ensure we are communicating
	   with the right device...*/
	DOCHWRITE_ATA_REG (pdev->bRegBase, DOCH_DRIVE_HEAD_REG, regs->bDriveHead);

	/*Wait for BUSY bit to clear*/
	status = DOCHREAD_ATA_REG(pdev->bRegBase, DOCH_STATUS_REG);
	if((status & DOCH_BUSY) == DOCH_BUSY)
	{
	    if ((rc = ready(pdev, devNum, DOCH_ALT_STATUS_REG, DOCH_BUSY, 0, DOCH_SHORT_WAIT)) != DOCH_OK)
		{
			DBG_PRINT_ERR(FLZONE_ATA, "\r\nio_output(): ATA not Ready\r\n");
			DBG_PRINT_ERR_PRM(FLZONE_ATA, (FLTXT("rc = 0x%x \r\n"),rc));
	        return rc;
		}
	}
	
	/*Write ATA registers, without ATA command register*/
	/*Note: if DMA was requested, registers will be written inside DMA context*/
	if(!pdev->bUseDMA)
	{
		DOCHWRITE_ATA_REG (pdev->bRegBase, DOCH_SECTOR_CNT_REG,		regs->bSectorCount);
		DOCHWRITE_ATA_REG (pdev->bRegBase, DOCH_SECTOR_NO_REG,		regs->bSectorNumber);
		DOCHWRITE_ATA_REG (pdev->bRegBase, DOCH_CYLINDER_LOW_REG,	regs->bCylLow);
		DOCHWRITE_ATA_REG (pdev->bRegBase, DOCH_CYLINDER_HIGH_REG,	regs->bCylHigh);
		DOCHWRITE_ATA_REG (pdev->bRegBase, DOCH_FEATURES_REG,		regs->bFeaturesError);
	}

	#ifdef DOCH_USE_BURST_MODE_WRITE
 	/*BURST transfer was requested*/
	if(pdev->bUseBurst)
	{
	   /*Initiate ATA Command*/
       DOCHWRITE_ATA_REG (pdev->bRegBase, DOCH_COMMAND_REG, regs->bCommandStatus);

  	    /* Check DRQ ready and not BSY before data xfer */
		(rc = ready(pdev, devNum, DOCH_STATUS_REG, (DOCH_READY | DOCH_DRQ | DOCH_BUSY | DOCH_ERROR),
													DOCH_READY | DOCH_DRQ, DOCH_LONG_WAIT));
		if(rc != DOCH_OK)
		{
			DBG_PRINT_ERR(FLZONE_ATA, "\r\nio_output(): ATA not Ready (before BURST) \r\n");
			DBG_PRINT_ERR_PRM(FLZONE_ATA, (FLTXT("rc = 0x%x \r\n"),rc));
			return rc;
		}

	   /*Set DOCH BURST WRITE Control Register*/
		DOCHWRITE_CTRL_REG (pdev->bRegBase,
							HIB_BURST_WRITE_MODE_CTRL_REG,
							(DOCH_BURST_ENABLE | DOCH_BURST_HOLD | DOCH_BURST_LENGTH | DOCH_BURST_LATENCY | DOCH_BURST_WAIT_STATE)
							);

		/*Enter BURST Mode*/
		DOCH_HOST_ENTER_WRITE_BURST_MODE
		
		/*Perform Write using burst*/
		DOCHWRITE_BURST((FLByte*)pdev->bRegBase,
						DOCH_DATA_PORT_AREA_OFFSET,
						buf,
						sectors_to_write);
						
		/*Exit BURST Mode*/
		DOCH_HOST_EXIT_WRITE_BURST_MODE

	   /*Set DOCH BURST WRITE Control Register*/
		DOCHWRITE_CTRL_REG (pdev->bRegBase, HIB_BURST_WRITE_MODE_CTRL_REG, DOCH_BURST_DISABLE);

		/* Wait until device is ready. This SHOULD NOT involve yielding the
		 * CPU and waiting for device interrupt, so we use DOCH_SHORT_WAIT.
		 */
		rc = ready(pdev, devNum, DOCH_ALT_STATUS_REG, (DOCH_READY | DOCH_BUSY | DOCH_DRQ),
													   DOCH_READY, DOCH_SHORT_WAIT);

	}
 	else
	#endif /*DOCH_USE_BURST_MODE_WRITE*/		
	
	#ifdef DOCH_DMA_CONFIG
	/*DMA transfer was requested*/
	if(pdev->bUseDMA)
	{
		DMA_Params_S dmaParams;
		FLDword dmaFirstReqSector,
			    dmaFirstSectorToPerform,
				dmaRemainderSectors,
				dmaRemainderOffset,
				dmaBlocks,
				dmaFrameSize;
		FLWord wDmaRegValue = DOCHREAD_CTRL_REG (pdev->bRegBase, HIB_DMA_CTRL_REG);

		/*Initial Value*/
		dmaRemainderOffset  = 0; 

		/*Save the first sector position*/
		dmaFirstReqSector = (regs->bSectorNumber + 
						    (regs->bCylLow<<8)  +
						    (regs->bCylHigh<<16)+
						    ((regs->bDriveHead & 0xF)<<24));

		dmaFirstSectorToPerform = dmaFirstReqSector;

⌨️ 快捷键说明

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