📄 ata.c
字号:
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 + -