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

📄 ata.c

📁 s3c6400 ADS下官方测试程序
💻 C
📖 第 1 页 / 共 5 页
字号:
	ATA_SetSwRst( ucCon, NORESET);
	DelayfrTimer( milli, 2);	// wait for 2ms

	ATA_SetRst( ucCon, RESET);		// ata device reset.	
	DelayfrTimer( micro, 5);	// wait for 5us

	ATA_SetRst( ucCon, NORESET);		// ata device no reset.	
	DelayfrTimer( milli, 250);	// wait for 200ms

}

void ATA_ChangeATAMode(u8 ucCon)
{
	// CF controller - True IDE mode setting
	// Output pad disable, Card power off, PC card mode
	CF_SetMUXReg(eCF_MUX_OUTPUT_DISABLE, eCF_MUX_CARDPWR_OFF, eCF_MUX_MODE_IDE);
	DelayfrTimer( milli, 1);	// wait for 1ms
	// Output pad enable, Card power off, PC card mode
	CF_SetMUXReg(eCF_MUX_OUTPUT_ENABLE, eCF_MUX_CARDPWR_OFF, eCF_MUX_MODE_IDE);
	DelayfrTimer( milli, 1);	// wait for 1ms
	// Card Power on (PC Card mode)
	CF_SetMUXReg(eCF_MUX_OUTPUT_ENABLE, eCF_MUX_CARDPWR_ON, eCF_MUX_MODE_IDE);
	DelayfrTimer( milli, 400);	// wait for 400ms
		
}

//////////
// Function Name : ATA_IdentifyDevice
// Function Description : This function identifies ATA device.
// Input : 	ucCon - ATA Controller Number
// Output : 	NONE
// Version : v0.1
void ATA_IdentifyDevice(u8 ucCon)
{
	u16 usReadBuffer[ATA_SECTORSIZE/2];
	u8	ucTempBuffer;
	volatile u8*	ucTempString;
	unsigned int tBuf[4];
	u32 uLoopCnt = 0;

	for (uLoopCnt=0;uLoopCnt<ATA_SECTORSIZE/2;uLoopCnt++)
		usReadBuffer[uLoopCnt] = 1;

	ATA_SetEndian(ucCon, eATA_ENDIAN_BIG);		// Set Big endian (must be)

	ATA_SetIRQMask(ucCon, eATA_IRQ_ALL);		// Mask all interrupt sources

	ATA_SetTaskFileRegValue(ucCon, eCF_TASKFILE_DEVICE, 0x40);
	ATA_SetTaskFileRegValue(ucCon, eCF_TASKFILE_COMMAND, ATA_CMD_IDENTIFYDEVICE);
	
	ATA_WaitForDeviceReady(ucCon);

	Disp("\n");
	for(uLoopCnt=0; uLoopCnt<ATA_SECTORSIZE/2; uLoopCnt++) {
		usReadBuffer[uLoopCnt] = ATA_GetDataFromDevice(ucCon);
//		Disp("(DATA%d:0x%04X)", uLoopCnt, usReadBuffer[uLoopCnt]);
	}
	Disp("\n");

	ATA_WaitForDeviceReady(ucCon);

	//
	//verify identify data~~~~~~~~~~~~~~~~~~~~~~~~~~
	//
	ucTempString = (u8 *)&usReadBuffer[10];
	Disp("\nSerial Number :");
	for(uLoopCnt=0;uLoopCnt<20;uLoopCnt++) Disp("%c",*(ucTempString+uLoopCnt));

	ucTempString = (u8 *)&usReadBuffer[27];
	Disp("\nModel Number :");
	for(uLoopCnt=0;uLoopCnt<40;uLoopCnt++) Disp("%c",*(ucTempString+uLoopCnt));

	tBuf[0] = (u8)(usReadBuffer[61]&0xff);
	tBuf[1] = (u8)((usReadBuffer[61]&0xff00)>>8);
	tBuf[2] = (u8)(usReadBuffer[60]&0xff);
	tBuf[3] = (u8)((usReadBuffer[60]&0xff00)>>8);
	g_oaATAInform[ucCon].uMaxSectors = (u32)((tBuf[0]<<24)|(tBuf[1]<<16)|(tBuf[2]<<8)|tBuf[3]);
	Disp("\nMax Sectors : %d\n",g_oaATAInform[ucCon].uMaxSectors);

	// Caution: readBuffer[x] - Big Endian, so upper byte means LSB..
	g_oaATAInform[ucCon].uMaxMultiple = (usReadBuffer[47]>>8)&0xFF;
	Disp("\nMax Multiple : %02X\n",g_oaATAInform[ucCon].uMaxMultiple);
	if (usReadBuffer[59]&0x1) { //multiple sector setting is valid
		g_oaATAInform[ucCon].uCurrentMultiple = (usReadBuffer[59]>>8)&0xFF;
		Disp("Current Multiple : %03X\n",g_oaATAInform[ucCon].uCurrentMultiple);
	}
	
	if ((usReadBuffer[64]>>8)&0x3 == 1) g_oaATAInform[ucCon].eMaxPioMode = eATA_PIO3;
	else if ((usReadBuffer[64]>>8)&0x3 == 3) g_oaATAInform[ucCon].eMaxPioMode = eATA_PIO4;
	else g_oaATAInform[ucCon].eMaxPioMode = eATA_PIO2;
	Disp("Max PIO Mode : %d\n",g_oaATAInform[ucCon].eMaxPioMode);

	g_oaATAInform[ucCon].eMaxUdmaMode = eATA_UDMA0;
	ucTempBuffer = usReadBuffer[88]>>8;
	for(uLoopCnt=5;uLoopCnt>=1;uLoopCnt--) {
		if(ucTempBuffer&(0x01<<(uLoopCnt-1))) {
			g_oaATAInform[ucCon].eMaxUdmaMode = (eATA_UDMAMODE) (uLoopCnt-1);
			break; 
		}
	}

	g_oaATAInform[ucCon].eCurrentUdmaMode =eATA_UDMA0;
	ucTempBuffer = usReadBuffer[88]&0x00ff;
	for(uLoopCnt=0;uLoopCnt<5;uLoopCnt++) {
		if(ucTempBuffer&(0x01<<uLoopCnt)) {
			g_oaATAInform[ucCon].eCurrentUdmaMode = (eATA_UDMAMODE)uLoopCnt;
			break; ///
		}
	}

	Disp("Max UDMA Mode : %d\n", g_oaATAInform[ucCon].eMaxUdmaMode);
	Disp("Current UDMA Mode : %d\n", g_oaATAInform[ucCon].eCurrentUdmaMode);
	//
	//verify identify data~~~~~~~~~~~~~~~~~~~~~~~END
	//

	ATA_SetEndian(ucCon, eATA_ENDIAN_LITTLE);	
}

//////////
// Function Name : ATA_WaitForDeviceReady
// Function Description : This function awaits ready state of ATA device.
// Input : 	ucCon - ATA Controller Number
// Output : 	NONE
// Version : v0.1
void ATA_WaitForDeviceReady(u8 ucCon)
{
	u8 ucReadData = 0;

	while(1)
	{
		ucReadData = ATA_GetDeviceReg(ucCon, eCF_TASKFILE_ALTANATE);
		ucReadData = ATA_GetDeviceReg(ucCon, eCF_TASKFILE_STATUS);
			
		if ( (ucReadData&eATA_XFR_STATUS_DEVICE_BUSY) == 0 )
			break;
	}	
}

//////////
// Function Name : ATA_WaitForDeviceReady
// Function Description : This function gets data from ATA device register.
// Input : 	ucCon - ATA Controller Number
//			eTaskFileRegId - Id of TaskFileRegister
// Output : 	NONE
// Version : v0.1
u8 ATA_GetDeviceReg(u8 ucCon, eCF_TASKFILE_Id eTaskFileRegId)
{
	u8 ucTempRead = 0;
	
	ATA_WaitForHostReady(ucCon);
	ucTempRead = ATA_GetTaskFileRegValue(ucCon, eTaskFileRegId);
	ATA_WaitForHostReady(ucCon);
	ucTempRead = (u8)(ATA_GetRegValue(ucCon, eATA_PIO_RDATA)&0xff);

	return ucTempRead;
}

//////////
// Function Name : ATA_GetDataFromDevice
// Function Description : This function gets data from ATA device register.
// Input : 	ucCon - ATA Controller Number
// Output : 	NONE
// Version : v0.1
u16 ATA_GetDataFromDevice(u8 ucCon)
{
	u32 ucTempRead = 0;
	
	ATA_WaitForHostReady(ucCon);
	ucTempRead = ATA_GetTaskFileRegValue16(ucCon, eCF_TASKFILE_DATA);
	ATA_WaitForHostReady(ucCon);
	ucTempRead = ATA_GetRegValue(ucCon, eATA_PIO_RDATA);

	return (u16)(ucTempRead&0xffff);
}

//////////
// Function Name : ATA_WaitForDeviceReady
// Function Description : This function gets data from ATA device register.
// Input : 	ucCon - ATA Controller Number
//			eTaskFileRegId - Id of TaskFileRegister
// Output : 	NONE
// Version : v0.1
void ATA_SetDataToDevice(u8 ucCon, u16 usData)
{
	ATA_WaitForHostReady(ucCon);
	ATA_SetTaskFileRegValue16(ucCon, eCF_TASKFILE_DATA, usData);
}

//////////
// Function Name : ATA_WaitForDeviceReady
// Function Description : This function sets up ATA mode as PIO.
// Input : 	ucCon - ATA Controller Number
//			ePioMode - PIO0/PIO1/PIO2/PIO3/PIO4
// Output : 	NONE
// Version : v0.1
//-------------------------------------------------------------
// PIO mode maximum transfer rate
// PIO0 : 3.3MB/s
// PIO1 : 5.2MB/s
// PIO2 : 8.3MB/s
// PIO3 : 11.1MB/s
// PIO4 : 16.7MB/s
//-------------------------------------------------------------

void ATA_SetPIOMode(u8 ucCon, eATA_PIOMODE ePioMode)
{
	u32 uT1;
	u32 uT2;
	u32 uTeoc;
	u32 uLoopCnt;
	
	u32 uPioTime[5];
	u32 uPioT1[5] = {70,50,30,30,30};    // min = {70,50,30,30,25};  edited by junon 060827
	u32 uPioT2[5] = {290,290,290,80,70}; // min = {290,290,290,80,70};
	u32 uPioTeoc[5] = {20,20,10,10,10};  // min = {20,15,10,10,10};

	u32 uCycleTime = (unsigned int)(1000000000/g_HCLK);

	for (uLoopCnt=0; uLoopCnt<5; uLoopCnt++)
	{
		uT1   = (uPioT1[uLoopCnt]  /uCycleTime)&0xff;  // edited by junon 060827
		uT2   = (uPioT2[uLoopCnt]  /uCycleTime)&0xff;
		uTeoc = (uPioTeoc[uLoopCnt]/uCycleTime)&0x0f;
		uPioTime[uLoopCnt] = (uTeoc<<12)|(uT2<<4)|uT1;
		Disp("PIO%dTIME = %x\n", uLoopCnt, uPioTime[uLoopCnt]);
	}

	ATA_SetIRQ(ucCon, eATA_IRQ_ALL);
	ATA_SetIRQMask(ucCon, (eATA_IRQ_SRC)0x0);			// unmask all

	ATA_SetTaskFileRegValue(ucCon, eCF_TASKFILE_CONTROL,	0x00);
	ATA_SetTaskFileRegValue(ucCon, eCF_TASKFILE_FEATURE,	0x03);	//set transfer mode based on value in Sector Count register
	ATA_SetTaskFileRegValue(ucCon, eCF_TASKFILE_SECTOR,	0x08|(ePioMode&0x7));	// PIO flow control transfer mode
	ATA_SetTaskFileRegValue(ucCon, eCF_TASKFILE_LOWLBA,	0x00);
	ATA_SetTaskFileRegValue(ucCon, eCF_TASKFILE_MIDLBA,		0x00);
	ATA_SetTaskFileRegValue(ucCon, eCF_TASKFILE_HIGHLBA,	0x00);
	ATA_SetTaskFileRegValue(ucCon, eCF_TASKFILE_DEVICE,		0x40);
	
	ATA_SetTaskFileRegValue(ucCon, eCF_TASKFILE_COMMAND,	ATA_CMD_SETFEATURES);	//set feature command

	ATA_WaitForDeviceReady(ucCon);

	switch(ePioMode) { 
		case eATA_PIO1:
			ATA_SetTimingParams(ucCon, eATA_MODE_PIO, uPioTime[1]);
			ATA_SetIORDY(ucCon, DISABLE);
			break;
		case eATA_PIO2:
			ATA_SetTimingParams(ucCon, eATA_MODE_PIO, uPioTime[2]);
			ATA_SetIORDY(ucCon, DISABLE);
			break;
		case eATA_PIO3:
			ATA_SetTimingParams(ucCon, eATA_MODE_PIO, uPioTime[3]);
			ATA_SetIORDY(ucCon, ENABLE);
			break;
		case eATA_PIO4:
			ATA_SetTimingParams(ucCon, eATA_MODE_PIO, uPioTime[4]);
			ATA_SetIORDY(ucCon, ENABLE);
			break;
		default:
			ATA_SetTimingParams(ucCon, eATA_MODE_PIO, uPioTime[0]);
			ATA_SetIORDY(ucCon, DISABLE);
			break;
		}
	g_oaATAInform[ucCon].eCurrentPioMode = ePioMode;	
}

//////////
// Function Name : ATA_SetUdmaMode
// Function Description : This function sets up ATA mode as UDMA
// Input : 	ucCon - ATA Controller Number
//			eUdmaMode - UDMA0/UDMA1/UDMA2/UDMA3/UDMA4
// Output : 	NONE
// Version : v0.1
//-------------------------------------------------------------
// UDMA mode maximum transfer rate
// UDMA0 : 16.7MB/s
// UDMA1 : 25.0MB/s
// UDMA2 : 33.3MB/s
// UDMA3 : 44.4MB/s
// UDMA4 : 66.7MB/s
// UDMA5 : 100 MB/s 
//-------------------------------------------------------------
void ATA_SetUdmaMode(u8 ucCon, eATA_UDMAMODE eUdmaMode)
{
	u32 uTdvh1	= 0;
	u32 uTdvs	= 0;
	u32 uTrp		= 0;
	u32 uTss		= 0;
	u32 uTackenv	= 0;
	u32 uLoopCnt	= 0;
#if 0
	u32 uUdmaTime[5]	= {0};					// Tdvh+Tdvs min = {120,80,60,45,30}
	u32 uUdmaTdvh[5]	= {10,10,10,10,10}; 	// min = {6.2,6.2,6.2,6.2,6.2}; edited by junon 060827
	u32 uUdmaTdvs[5]	= {100,60,50,35,20}; 	// min = {70,48,31,20,6.7};
	u32 uUdmaTrp[5]		= {160,125,100,100,100}; // min = {160,125,100,100,100};
	u32 uUdmaTss[5]		= {50,50,50,50,50};		 // min = {50,50,50,50,50};
	u32 uUdmaTackenvMin[5]	= {20,20,20,20,20};
#else
	u32 uUdmaTime[5]	= {0};					// Tdvh+Tdvs min = {120,80,60,45,30}
	u32 uUdmaTdvh[5]	= {7,7,7,7,7}; 	// min = {6.2,6.2,6.2,6.2,6.2}; edited by junon 060827
	u32 uUdmaTdvs[5]	= {70,48,31,20,7}; 	// min = {70,48,31,20,6.7};
	u32 uUdmaTrp[5]		= {160,125,100,100,100}; // min = {160,125,100,100,100};
	u32 uUdmaTss[5]		= {50,50,50,50,50};		 // min = {50,50,50,50,50};
	u32 uUdmaTackenvMin[5]	= {20,20,20,20,20};
#endif
	u32 uCycleTime = (u32)(1000000000/g_HCLK);	

	for (uLoopCnt=0; uLoopCnt<5; uLoopCnt++)
	{
		uTdvh1	= (uUdmaTdvh[uLoopCnt] / uCycleTime)&0x0f;		// edited by junon 060827
		uTdvs	= (uUdmaTdvs[uLoopCnt] / uCycleTime)&0xff;
		uTrp	= (uUdmaTrp[uLoopCnt]  / uCycleTime)&0xff;
		uTss	= (uUdmaTss[uLoopCnt]  / uCycleTime)&0x0f;
		uTackenv= (uUdmaTackenvMin[uLoopCnt]/uCycleTime)&0x0f;
		uUdmaTime[uLoopCnt] = (uTdvh1<<24)|(uTdvs<<16)|(uTrp<<8)|(uTss<<4)|uTackenv;
		Disp("UDMA%dTIME = %x\n", uLoopCnt, uUdmaTime[uLoopCnt]);
	}	

	ATA_SetIRQ(ucCon, eATA_IRQ_ALL);
	ATA_SetIRQMask(ucCon, (eATA_IRQ_SRC)0x0);			// unmask all

	ATA_SetTaskFileRegValue(ucCon, eCF_TASKFILE_CONTROL,	0x00);
	ATA_SetTaskFileRegValue(ucCon, eCF_TASKFILE_FEATURE,	0x03);	//set transfer mode based on value in Sector Count register
	ATA_SetTaskFileRegValue(ucCon, eCF_TASKFILE_SECTOR,	0x40|(eUdmaMode&0x7));	// PIO flow control transfer mode
	ATA_SetTaskFileRegValue(ucCon, eCF_TASKFILE_LOWLBA,	0x00);
	ATA_SetTaskFileRegValue(ucCon, eCF_TASKFILE_MIDLBA,		0x00);
	ATA_SetTaskFileRegValue(ucCon, eCF_TASKFILE_HIGHLBA,	0x00);
	ATA_SetTaskFileRegValue(ucCon, eCF_TASKFILE_DEVICE,		0x40);
	
	ATA_SetTaskFileRegValue(ucCon, eCF_TASKFILE_COMMAND,	ATA_CMD_SETFEATURES);	//set feature command

	ATA_WaitForDeviceReady(ucCon);

	switch(eUdmaMode) { 
		case eATA_UDMA0:
			ATA_SetTimingParams(ucCon, eATA_MODE_UDMA, uUdmaTime[0]);
			break;
		case eATA_UDMA1:
			ATA_SetTimingParams(ucCon, eATA_MODE_UDMA, uUdmaTime[1]);
			break;
		case eATA_UDMA2:
			ATA_SetTimingParams(ucCon, eATA_MODE_UDMA, uUdmaTime[2]);
			break;
		case eATA_UDMA3:
			ATA_SetTimingParams(ucCon, eATA_MODE_UDMA, uUdmaTime[3]);
			break;
		case eATA_UDMA4:
			ATA_SetTimingParams(ucCon, eATA_MODE_UDMA, uUdmaTime[4]);
			break;
		default:
			Disp("Wrong UDMA mode in SetUdmaMode()\n");
			break;
		}
	g_oaATAInform[ucCon].eCurrentUdmaMode = eUdmaMode;	
}

//////////
// Function Name : ATA_WriteBlocks
// Function Description : This function writes block data to device.
// Input : 	ucCon - ATA Controller Number
//			uStBlock - LBA Block
//			uBlocks	- Block Count
//			uBufAddr - Address of Buffer
// Output : 	true/false
// Version : v0.1
bool ATA_WriteBlocks(u8 ucCon, u32 uStBlock, u32 uBlocks, u32 uBufAddr)
{
	eATA_MODE_6400	eAtaMode	= g_oaATAInform[ucCon].eAtaMode;
	bool			bStatus		= FALSE;
#if PERF_TEST_ATA
	u32			uElapsedTime = 0;
#endif

	Disp("WriteBlocks() in %s mode...\n", ATA_GetModeName(eAtaMode));

#if PERF_TEST_ATA
	StartTimer(0);
#endif
	switch(eAtaMode)
	{
		case eATA_MODE_PIOCPU :
			bStatus = ATA_WriteSectors_PIO( ucCon, uStBlock, uBlocks, uBufAddr);
			break;
		case eATA_MODE_PIODMA :
			bStatus = ATA_WriteSectors_PDMA( ucCon, uStBlock, uBlocks, uBufAddr);
			break;
		case eATA_MODE_UDMA :
			bStatus = ATA_WriteSectors_UDMA( ucCon, uStBlock, uBlocks, uBufAddr);
			break;
		default : 
			Disp("Not supported mode in WriteBlocks()\n");

⌨️ 快捷键说明

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