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

📄 doch_ata.c

📁 电子盘DEMO板程序
💻 C
📖 第 1 页 / 共 5 页
字号:

		if(pdev->device[devNum].dataTransferMode == DOCH_DATA_MODE_SINGLE)
		{
			dmaRemainderSectors = 0;
			dmaFrameSize		= 1;
			dmaBlocks			= sectors_to_write;
		}
		else if (pdev->device[devNum].dataTransferMode == DOCH_DATA_MODE_MULT)
		{
			dmaRemainderSectors = (sectors_to_write % pdev->device[devNum].dwMulti_Current);
			
			/*Set initial parameters (will be altered afterwards to transfer "remainder" sectors*/
			dmaBlocks		    = (sectors_to_write / 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 */

dochIoOutputDmaSequence:
		if(dmaBlocks > 0)
		{
			/*Set up the DMA transfer - Platfrom*/
			dmaParams.bOpType			  = DOCH_DMA_CONFIG_TRANSACTION_HOST_TO_DEVICE;
	
			dmaParams.bDiskOnChip_BasePtr = ((FLByte*)pdev->bRegBase);
			dmaParams.wDiskOnChip_Offset  = DOCH_DATA_PORT_AREA;
			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_output(): DOCH_DMA_CONFIG_TRANSACTION_HOST_TO_DEVICE Failed\r\n");
				return DOCH_GeneralFailure;
			}
	
			/*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);
	
			/*Wait for DMA transfer to complete*/
			dmaParams.bOpType = DOCH_DMA_WAIT_FOR_WRITE_TRANSACTION_END;
			DOCH_DMA_CONFIG(&dmaParams);

			/*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_output(): DOCH_DMA_WAIT_FOR_WRITE_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 then 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 dochIoOutputDmaSequence;
		}

		/* 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_DMA_CONFIG*/

	/*PIO transfer was requested*/
	{
		/*Write 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_SHORT_WAIT));
		if(rc != 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;
		}

		/*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_WRITE_PARTITION)) )			/*Command is OTHER than Write Partition*/
		{
			for(secPerformed=1; secPerformed<=sectors_to_write; secPerformed++)
			{
				/*Perform data xfer*/
				if( (DOCHBLK_WRITE(pdev->bRegBase, 
								   (FLByte*)buf + offset,
								   1)) != 0)
				{
					return DOCH_WriteFault;
				}

				/* Check DRQ ready and not BSY before next data xfer */
				/* (don`t perform after LAST sector was transfered) */
				if(secPerformed != sectors_to_write)
				{
					(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\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_write;)
			{
            	FLByte		multSecToWrite;

				/*Determine how many sectors to write this cycle*/
				if((secPerformed + multCount) > sectors_to_write)
					multSecToWrite = (sectors_to_write - secPerformed);
				else
					multSecToWrite = multCount;

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

				/* Check DRQ ready and not BSY before next data xfer */
				/* (don`t perform after LAST sector was transfered) */
				if((secPerformed + multSecToWrite) != sectors_to_write)
				{
					(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\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 +=  multSecToWrite;
				offset		 += (multSecToWrite * 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 */

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

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

	/* check operation's status; this also clear 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 _ c t r l                                 * 
 *                                                                            * 
 *  Pass command 'cmd' to DOCH device.                                        * 
 *                                                                            * 
 *  Parameters :                                                              *
 *      pdev                 : device to act on                               *
 *		regs				 : DOCH_Registers								  *
 *                                                                            * 
 *  Returns :                                                                 * 
 *      DOCH_OK in success, otherwise respective error code.                  *
 *                                                                            * 
 ******************************************************************************/
DOCH_Error io_ctrl ( DOCH_Socket     * pdev,
					 FLSNative 		   devNum,
				     DOCH_Registers	 * regs)
{
    DOCH_Error  rc;
	FLSNative 	status;

	/* 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 DOCH BUSY flag to clear*/
    if ((rc = ready(pdev, devNum, DOCH_ALT_STATUS_REG, DOCH_BUSY, 0, DOCH_SHORT_WAIT)) != DOCH_OK)
	{
		DBG_PRINT_ERR(FLZONE_ATA, "\r\nio_ctrl(): ATA not Ready\r\n");
		DBG_PRINT_ERR_PRM(FLZONE_ATA, (FLTXT("rc = 0x%x \r\n"),rc));
        return rc;
	}

	/*If DOCH is ready, write registers*/
    if (rc == DOCH_OK)
    {
		/*Write ATA registers*/
		DOCHWRITE_ATA_REG (pdev->bRegBase, DOCH_FEATURES_REG,		regs->bFeaturesError);
        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_COMMAND_REG,		regs->bCommandStatus);

		/* wait until device is ready */
		rc = ready(pdev, devNum, DOCH_STATUS_REG, (DOCH_READY |  DOCH_BUSY), 
												   DOCH_READY, DOCH_LONG_WAIT);
		if(rc != DOCH_OK)
		{
			DBG_PRINT_ERR(FLZONE_ATA, "\r\nio_ctrl(): 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 clear 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;
}

DOCH_Error retrieveAndPrintAtaDebug(DOCH_Socket* pdev)
{
    DOCH_Error rc = DOCH_OK;
	DOCH_Registers in_regs;
	DOCH_Registers out_regs;
	/*FLWord numOfDataBytes;*/
	FLWord currentINTEnabled, currentDMAEnabled, currentBurstEnabled;

	tffsset(&in_regs, 0, sizeof(in_regs));
	in_regs.bFeaturesError = DOCH_RETRIEVE_DBG_MSG;
	in_regs.bCommandStatus = DOCH_VSCMD_EXT_DEVICE_CTRL;
	in_regs.bSectorCount   = 1;
	in_regs.bDriveHead = (pdev->bAtaDevNum * DOCH_DEVICE);

	/* Disable interrupts */
	/* Disable DMA/Burst */
	/* (retain original values)*/
	currentINTEnabled = pdev->bUseInterrupt;
	currentDMAEnabled = pdev->bUseDMA;
	currentBurstEnabled = pdev->bUseBurst;
	pdev->bUseInterrupt = FALSE;
	pdev->bUseDMA		= FALSE;
	pdev->bUseBurst		= FALSE;
	dochEnableATAInterrupt(pdev->wSocketNo, FALSE, 0);


	/*Perform debug ocommand*/
	rc = io_input(pdev, 0, &in_regs, ataDBG, 1);

	/*Revert interrupts/DMA/Burst to original state*/
	pdev->bUseInterrupt = currentINTEnabled;
	pdev->bUseDMA		= currentDMAEnabled;
	pdev->bUseBurst		= currentBurstEnabled;
	dochEnableATAInterrupt(pdev->wSocketNo,
						   (DOCH_IRQ_RB_INIT(pdev->wSocketNo) && currentINTEnabled),
						   0);


	/*Retrieve ATA out registers*/
	rc = get_out_registers(pdev, 0, &out_regs);
	if(rc != DOCH_OK)
		return rc;

	/*numOfDataBytes = (out_regs.bSectorNumber + (out_regs.bCylLow<<8));*/

	if(ataDBG[0] != '\0')
	{
		DBG_PRINT_ERR(FLZONE_ATA, "\r\n~~~~~~~~~~~~~~~~~~~~~~~~~");
		DBG_PRINT_ERR(FLZONE_ATA, "\r\n*** ETFFS Debug string: ");
		DBG_PRINT_ATA(FLZONE_ATA, (ataDBG));
		DBG_PRINT_ERR(FLZONE_ATA, " ***");
		DBG_PRINT_ERR(FLZONE_ATA, "\r\n~~~~~~~~~~~~~~~~~~~~~~~~~\r\n");
	}

	return rc;
}

/****************************************************************************** 

⌨️ 快捷键说明

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