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

📄 doch_ata.c

📁 电子盘DEMO板程序
💻 C
📖 第 1 页 / 共 5 页
字号:
	}
	else if(resetOccured)
	{
		if(beforeCommand)
			DBG_PRINT_ERR(FLZONE_ATA, "\r\ndoch_command(): Suspend mode detected (Before Command)\r\n");
		else
			DBG_PRINT_ERR(FLZONE_ATA, "\r\ndoch_command(): Suspend mode detected (After Command)\r\n");

		gDeviceTurnedOff = TRUE;
		return DOCH_DeviceTurnedOff;
	}
	#ifdef DOCH_CHECK_CHIP_ID
	else
	{
		if(beforeCommand)
			DBG_PRINT_ERR(FLZONE_ATA, "\r\ndoch_command(): Suspend mode not detected but failed to read chip id (Before Command)\r\n");
		else
			DBG_PRINT_ERR(FLZONE_ATA, "\r\ndoch_command(): Suspend mode not detected but failed to read chip id (After Command)\r\n");

		gDeviceTurnedOff = TRUE;
		return DOCH_DeviceTurnedOff;    
	}
	#else /*DOCH_CHECK_CHIP_ID*/
	return DOCH_OK;
	#endif /*DOCH_CHECK_CHIP_ID*/
}
#endif /*CHECK_POWER_ON_EVERY_COMMAND*/

/****************************************************************************** 
 *                                                                            * 
 *                             r e a d y		                              * 
 *                                                                            * 
 *  Wait until particular bit pattern appears in specified DOCH register      * 
 *                                                                            * 
 *  Parameters :                                                              *
 *      pdev                 : device to act on                               *
 *      reg                  : DOCH register offset from base address         *
 *      mask                 : bits we are interested in                      *
 *      on_bits              : bits we are waiting to become '1'              *
 *      millisec             : timeout value in milliseconds                  *
 *                                                                            * 
 *  Returns :                                                                 * 
 *      DOCH_OK in success, otherwise respective error code.                  *
 *                                                                            * 
 ******************************************************************************/
static 
DOCH_Error ready ( DOCH_Socket   * pdev,
				   FLSNative 	   devNum,
                   DOCH_Reg        reg,
                   FLByte		   mask,
                   FLByte		   on_bits,
                   FLDword		   millisec )
{
	DOCH_Error error = DOCH_OK;
    register FLDword tries;
	FLByte status = 0;

	FLDword use_interrupt = 
		( ((pdev->device[devNum].flags & DOCH_FLAGSB_USE_INTERRUPT) == DOCH_FLAGSB_USE_INTERRUPT) &&
		  (pdev->bUseInterrupt) );

	/*Special case: ignore error bit 
	  (should be ignored when performing ATA standard IDENTIFY DEVICE command)*/
	if(gIgnoreErrorBit)
		mask &= ~(DOCH_ERROR);

	/*Protect against access time set to 0*/
	if(gDochAccessNanosec == 0)
		return DOCH_BadParameter;
	tries = millisec * (1000000UL / gDochAccessNanosec);

	/*If popper environment variable was set - set timeout to max*/
	if(gATANoTimeout == DOCH_GLOBAL_BOOL_PATTERN)
	{
		tries = DOCH_ATA_MAX_TIMEOUT;
	}

    /*If gUseShortWaitOnBusy is set, use its value*/
    if(gUseShortWaitOnBusy != 0)
    {
        tries = gUseShortWaitOnBusy;
    }

	/*Protect tries from being set to "0"
	  (in conjunction with tries-- might cause a very long delay...)*/
	if(tries == 0)
		tries = 1;

    /*Wait for BUSY bit to clear*/
    while (tries-- > 0)
    {
		if ((millisec >= DOCH_LONG_WAIT) && (use_interrupt))
		{
			/* wait for device's interrupt */		
			DOCH_SLEEP(pdev->wSocketNo, devNum, DOCH_DEFAULT_SLEEP_PERIOD);
		}

		status = DOCHREAD_ATA_REG(pdev->bRegBase, reg);
        if ((status & mask) == on_bits)
        {
            /* read status once again, just to be sure .. */
            /*if ((DOCHREAD_ATA_REG(pdev->device[devNum].bRegBase, reg) & mask) == on_bits)*/
                return DOCH_OK;
        }
		/*If an error was detected - return the error code*/
		else if( ((status & DOCH_ERROR) == DOCH_ERROR) &&
				 ((status & DOCH_BUSY)  != DOCH_BUSY))
		{
			error = (DOCH_Error)DOCHREAD_ATA_REG(pdev->bRegBase, DOCH_ERROR_REG);

			/*Special Case - Device returned "0" in the error register.
			 This DOES NOT mean that everything is OK, since the error bit was raised.
			 Hence, we will return "DOCH_ATA_ERROR_ABORT"*/
			if(error == DOCH_OK)
				error = DOCH_ATA_ERROR_ABORT;

			if(pdev->bUseInterrupt && (millisec == DOCH_SHORT_WAIT))
				DOCH_UNSERVICED_INTERRUPT(pdev->wSocketNo, devNum);

			DBG_PRINT_ERR(FLZONE_ATA, "ready(): ATA Error: ");
			DBG_PRINT_ERR_PRM(FLZONE_ATA, (FLTXT("0x%x "), error));
			DBG_PRINT_ERR(FLZONE_ATA, "\r\n");

			return error;
		}
    }

	DBG_PRINT_ERR(FLZONE_ATA, "\r\nready(): Timed Out\r\n");

	/* If timeout had occurred, and not whilst looking for a device,
	   reset ATA and poll for ready */
	if(gUseShortWaitOnBusy == 0)
	{
		DBG_PRINT_ERR(FLZONE_ATA, "ready(): Resetting device... ");
		error = doch_reset (pdev->wSocketNo, devNum);
		if(error == DOCH_OK)
			DBG_PRINT_ERR(FLZONE_ATA, "Passed! \r\n");
		else
		{
			DBG_PRINT_ERR(FLZONE_ATA, "Failed! \r\n");
			return error;
		}
	}

    return DOCH_TimedOut;
}

/****************************************************************************** 
 *                                                                            * 
 *                             i o _ i n p u t                                * 
 *                                                                            * 
 *  Read sectors from DOCH device.                                            * 
 *                                                                            * 
 *  Parameters :                                                              *
 *      pdev                 : device to act on                               *
 *		regs				 : DOCH_Registers								  *
 *      buf                  : user buffer to read to                         *
 *		secNum				 : # of sectors to read							  *
 *                                                                            * 
 *  Returns :                                                                 * 
 *      DOCH_OK in success, otherwise respective error code.                  *
 *                                                                            * 
 ******************************************************************************/
DOCH_Error io_input  ( DOCH_Socket     * pdev,  
					   FLSNative 		 devNum,
					   DOCH_Registers  * regs,
                       void            * buf, 
					   FLNative		     secNum)
{
    FLNative    sectors_to_read;
	FLNative	secPerformed;
	FLNative	offset = 0;
    DOCH_Error  rc;
	FLSNative 	status;
	FLByte		multCount = 0;
	FLByte		multSecToRead = 0;

	/*Calculate how many sectors are to be read*/
	/*Note: "0" - 256 Sectors to read*/
	sectors_to_read = (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_input(): ATA not Ready (before command) \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);
	}

 	/*BURST transfer was requested*/
	#ifdef DOCH_USE_BURST_MODE_READ
	if((pdev->bUseBurst) && (!pdev->bUseDMA))
	{
	   FLByte drqSize = 0;
	   FLByte burstSizeInBytes;
	   FLByte i;
	   
		if(pdev->device[devNum].dataTransferMode == DOCH_DATA_MODE_SINGLE)
		{
			drqSize = 1;
		}
		else if(pdev->device[devNum].dataTransferMode == DOCH_DATA_MODE_MULT)
		{
			drqSize = (FLByte)pdev->device[devNum].dwMulti_Current;
		}
		
		switch(DOCH_BURST_LENGTH)
		{
		case DOCH_BURST_LEN_4_CYC:
			burstSizeInBytes = 8;
		break;
		
		case DOCH_BURST_LEN_8_CYC:
			burstSizeInBytes = 16;
		break;
		
		case DOCH_BURST_LEN_16_CYC:
			burstSizeInBytes = 32;
		break;
		
		case DOCH_BURST_LEN_32_CYC:
			burstSizeInBytes = 64;
		break;
		
		default:
			return DOCH_BadParameter;
		}


	   /*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<<8) | (DOCH_BURST_WAIT_STATE<<4))
							);

		/*Enter BURST Mode*/
		DOCH_HOST_ENTER_READ_BURST_MODE

	   	/*Initiate ATA Command*/
       	DOCHWRITE_ATA_REG (pdev->bRegBase, DOCH_COMMAND_REG, regs->bCommandStatus);

		for(i=0; i<sectors_to_read; i += drqSize)
		{
		
	  	    /* 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 BURST) \r\n");
				DBG_PRINT_ERR_PRM(FLZONE_ATA, (FLTXT("rc = 0x%x \r\n"),rc));
				return rc;
			}
*/
	
	        if(i == 0)
			{
				FLDword tempBuf[4];
				FLWord temp;
				volatile FLWord* vPtr = (volatile FLWord*)addToFarPointer(pdev->bRegBase, (DOCH_ALT_STATUS_REG<<1) + DOCH_CONT_REG_AREA);
		
				do
				{
					tffscpy(tempBuf, (FLByte*)vPtr, burstSizeInBytes);
					/*OMAP1610_Read512Bytes_SW_DMA_BURST((FLByte*)pdev->bRegBase,
														((DOCH_ALT_STATUS_REG<<1) + DOCH_CONT_REG_AREA),
														tempBuf,
														burstSizeInBytes);*/
					temp = (tempBuf[3] >> 16);
				}
				while((temp & (DOCH_READY | DOCH_DRQ | DOCH_BUSY | DOCH_ERROR)) != 
					  (DOCH_READY | DOCH_DRQ));
			}
	
			/*Perform Read using burst*/
			DOCHREAD_BURST((FLByte*)pdev->bRegBase,
							DOCH_DATA_PORT_AREA_OFFSET,
							(FLByte*)buf + (i<<DOCH_SECTOR_SIZE_BITS),
							drqSize);
		}			
		
		/*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);
	}
	else
	#endif /*DOCH_USE_BURST_MODE_READ*/

	#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;

		if(pdev->device[devNum].dataTransferMode == DOCH_DATA_MODE_SINGLE)
		{
			dmaRemainderSectors = 0;
			dmaFrameSize		= 1;
			dmaBlocks			= sectors_to_read;
		}
		else if (pdev->device[devNum].dataTransferMode == DOCH_DATA_MODE_MULT)
		{
			dmaRemainderSectors = (sectors_to_read % pdev->device[devNum].dwMulti_Current);

			/*Set initial parameters (will be altered afterwards to transfer "remainder" sectors*/
			dmaBlocks		    = (sectors_to_read / pdev->device[devNum].dwMulti_Current);
			dmaFrameSize		= pdev->device[devNum].dwMulti_Current;
		}
		else
		{
			DBG_PRINT_ERR(FLZONE_ATA, "io_input(): DMA 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 */

dochIoInputDmaSequence:
		if(dmaBlocks > 0)
		{
			/*Set up the DMA transfer - Platfrom*/
			dmaParams.bOpType			  = DOCH_DMA_CONFIG_TRANSACTION_DEVICE_TO_HOST;
	
			dmaParams.bDiskOnChip_BasePtr = (FLByte*)pdev->bRegBase;
			dmaParams.wDiskOnChip_Offset  = (FLWord)DOCH_DATA_PORT_AREA;

⌨️ 快捷键说明

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