📄 ata.c
字号:
/*Source Buffer 1 Setting*/
ATA_SetSBufStart( ucCon, uCurrentSrcAddr);
ATA_SetSBufSize( ucCon, uCurrentCount*ATA_SECTORSIZE);
ATA_SetXfrNum(ucCon, uCurrentCount*ATA_SECTORSIZE);
ATA_SetDevicePosition(ucCon, uCurrentLba, uCurrentCount);
ATA_SetTaskFileRegValue(ucCon, eCF_TASKFILE_COMMAND, ATA_CMD_WRITEDMA);
ATA_WaitForDeviceReady(ucCon);
ATA_SetConfig(ucCon, eATA_MODE_UDMA, eATA_DMA_WRITE_DATA);
#if PERF_TEST_UDMA
StartTimer(1);
#endif
/*ATA Transfer Command */
ATA_SetTransferCommand(ucCon, eATA_XFR_CMD_START);
ATA_WaitForTransferDone(ucCon);
ATA_SetTransferCommand(ucCon, eATA_XFR_CMD_ABORT);
#if PERF_TEST_UDMA
uElapsedTime += StopTimer(1);
#endif
ATA_SetConfig(ucCon, eATA_MODE_PIOCPU, eATA_DMA_WRITE_DATA);
ATA_WaitForDeviceReady(ucCon);
ATA_SetUdmaAutoMode(ucCon, DISABLE);
uRound++;
}
#if PERF_TEST_UDMA
Disp(" UDMA Writing time : %d us, Performance : %lf MByte/sec\n"
,uElapsedTime,(float)(uSectorCount*512./uElapsedTime));
#endif
return TRUE;
}
//////////
// Function Name : ATA_ReadSectors_UDMA
// Function Description : This function writes sector data to device in UDMA mode.
// Input : ucCon - ATA Controller Number
// uLBA - LBA Block
// uSectorCount - Sector Count
// uSrcAddress - Address of Buffer
// Output : true/false
// Version : v0.1
bool ATA_ReadSectors_UDMA(u8 ucCon, u32 uLBA, u32 uSectorCount, u32 uDstAddress)
{
u32 uCurrentCount;
u32 uRemainderCount;
u32 uCurrentLba;
u32 uCurrentDstAddr;
u32 uRound;
#if PERF_TEST_UDMA
u32 uElapsedTime = 0;
#endif
uRemainderCount = uSectorCount;
uRound = 0;
while(uRemainderCount != 0) {
if(uRemainderCount>256) {
uCurrentCount = 256; //0 means 256
uRemainderCount -= 256;
} else {
uCurrentCount = uRemainderCount;
uRemainderCount = 0;
}
uCurrentLba = uLBA + uRound*256;
uCurrentDstAddr = uDstAddress + uRound*256*ATA_SECTORSIZE;
/*Source Buffer 1 Setting*/
ATA_SetTBufStart( ucCon, uCurrentDstAddr);
ATA_SetTBufSize( ucCon, uCurrentCount*ATA_SECTORSIZE);
ATA_SetXfrNum(ucCon, uCurrentCount*ATA_SECTORSIZE);
ATA_SetDevicePosition(ucCon, uCurrentLba, uCurrentCount);
ATA_SetTaskFileRegValue(ucCon, eCF_TASKFILE_COMMAND, ATA_CMD_READDMA);
ATA_WaitForDeviceReady(ucCon);
ATA_SetConfig(ucCon, eATA_MODE_UDMA, eATA_DMA_READ_DATA);
#if PERF_TEST_UDMA
StartTimer(1);
#endif
/*ATA Transfer Command */
ATA_SetTransferCommand(ucCon, eATA_XFR_CMD_START);
ATA_WaitForTransferDone(ucCon); // Host
ATA_SetTransferCommand(ucCon, eATA_XFR_CMD_ABORT);
#if PERF_TEST_UDMA
uElapsedTime += StopTimer(1);
#endif
ATA_SetConfig(ucCon, eATA_MODE_PIOCPU, eATA_DMA_READ_DATA);
ATA_WaitForDeviceReady(ucCon);
ATA_SetUdmaAutoMode(ucCon, DISABLE);
uRound++;
}
#if PERF_TEST_UDMA
Disp(" UDMA Reading time : %d us, Performance : %lf MByte/sec\n"
,uElapsedTime,(float)(uSectorCount*512./uElapsedTime));
#endif
return TRUE;
}
void ATA_SetDevicePosition(u8 ucCon, u32 uLba, u32 uSectorCount)
{
ATA_SetTaskFileRegValue(ucCon, eCF_TASKFILE_SECTOR, uSectorCount&0xff);
ATA_SetTaskFileRegValue(ucCon, eCF_TASKFILE_LOWLBA, uLba&0xff);
ATA_SetTaskFileRegValue(ucCon, eCF_TASKFILE_MIDLBA, (uLba>>8)&0xff);
ATA_SetTaskFileRegValue(ucCon, eCF_TASKFILE_HIGHLBA, (uLba>>16)&0xff);
ATA_SetTaskFileRegValue(ucCon, eCF_TASKFILE_DEVICE, (uLba>>24)&0xf|0x40);
}
//////////
// Function Name : ATA_StartWritingSectors
// Function Description : This function sets writing function which transfers block data to device.
// Input : ucCon - ATA Controller Number
// uStBlock - LBA Block
// uBlocks - Block Count
// uBufAddr - Buffer Address
// Output : true/false
// Version : v0.1
bool ATA_StartWritingSectors(u8 ucCon, u32 uStBlock, u32 uBlocks, u32 uBufAddr)
{
u32 uDeviceCmd = 0;
// Disp("uStBlock:%d, uBlocks:%d, uBufAddr:0x%x\n", uStBlock, uBlocks, uBufAddr);
uDeviceCmd = (g_oaATAInform[ucCon].eAtaMode == eATA_MODE_UDMA) ? ATA_CMD_WRITEDMA : ATA_CMD_WRITESECTOR;
/*Source Buffer Setting*/
ATA_SetSBufStart( ucCon, uBufAddr);
ATA_SetSBufSize( ucCon, uBlocks*ATA_SECTORSIZE);
ATA_SetXfrNum(ucCon, uBlocks*ATA_SECTORSIZE);
ATA_SetDevicePosition(ucCon, uStBlock, uBlocks);
ATA_SetTaskFileRegValue( ucCon, eCF_TASKFILE_COMMAND , uDeviceCmd);
ATA_WaitForDeviceReady( ucCon);
// Disp("(");
ATA_SetConfig(ucCon, g_oaATAInform[ucCon].eAtaMode, eATA_DMA_WRITE_DATA);
// Disp(")");
#if 1
ATA_SetTransferCommand(ucCon, eATA_XFR_CMD_START);
#if 0 // These lines are only for ATA Bug Test
for ( uLoopCnt = 0; uLoopCnt < 1000; uLoopCnt++)
{
ATA_SetTransferCommand(ucCon, eATA_XFR_CMD_STOP);
ATA_SetTransferCommand(ucCon, eATA_XFR_CMD_CONTINUE);
}
Disp("$");
#endif
#else
Set_Ata_Cmd_START();
#endif
return TRUE;
}
//////////
// Function Name : ATA_StartReadingSectors
// Function Description : This function sets reading function which transfers block data from device.
// Input : ucCon - ATA Controller Number
// uStBlock - LBA Block
// uBlocks - Block Count
// uBufAddr - Buffer Address
// Output : true/false
// Version : v0.1
bool ATA_StartReadingSectors(u8 ucCon, u32 uStBlock, u32 uBlocks, u32 uBufAddr)
{
u32 uDeviceCmd = 0;
// Disp("uStBlock:%d, uBlocks:%d, uBufAddr:0x%x\n", uStBlock, uBlocks, uBufAddr);
uDeviceCmd = (g_oaATAInform[ucCon].eAtaMode == eATA_MODE_UDMA) ? ATA_CMD_READDMA : ATA_CMD_READSECTOR;
/*Target Buffer Setting*/
ATA_SetTBufStart( ucCon, uBufAddr);
ATA_SetTBufSize( ucCon, uBlocks*ATA_SECTORSIZE);
ATA_SetXfrNum(ucCon, uBlocks*ATA_SECTORSIZE);
ATA_SetDevicePosition(ucCon, uStBlock, uBlocks);
ATA_SetTaskFileRegValue( ucCon, eCF_TASKFILE_COMMAND , uDeviceCmd);
ATA_WaitForDeviceReady( ucCon);
// Disp("(");
ATA_SetConfig(ucCon, g_oaATAInform[ucCon].eAtaMode, eATA_DMA_READ_DATA);
// Disp(")");
#if 1
ATA_SetTransferCommand(ucCon, eATA_XFR_CMD_START);
#else
Set_Ata_Cmd_START();
#endif
return TRUE;
}
//////////
// Function Name : ATA_IsWritingBlocksDone
// Function Description : This function checks that data transfer to device has done.
// Input : ucCon - ATA Controller Number
// Output : true/false
// Version : v0.1
bool ATA_IsWritingSectorsDone(u8 ucCon)
{
bool bRetValue = false;
ATA_WaitForTransferDone(ucCon);
bRetValue = ATA_IsDmaDone(ucCon);
return bRetValue;
}
//////////
// Function Name : ATA_IsReadingBlocksDone
// Function Description : This function checks that data transfer from device to host has done.
// Input : ucCon - ATA Controller Number
// Output : true/false
// Version : v0.1
bool ATA_IsReadingSectorsDone(u8 ucCon)
{
return ATA_IsWritingSectorsDone(ucCon);
}
//////////
// Function Name : ATA_IsDmaDone
// Function Description : This function checks that data DMA transfer to device has done.
// Input : ucCon - ATA Controller Number
// Output : NONE
// Version : v0.1
bool ATA_IsDmaDone(u8 ucCon)
{
ATA_WaitForHostReady( ucCon);
ATA_SetTransferCommand(ucCon, eATA_XFR_CMD_ABORT);
ATA_WaitForHostReady( ucCon);
ATA_SetConfig( ucCon, eATA_MODE_PIOCPU, eATA_DMA_WRITE_DATA);
ATA_WaitForDeviceReady(ucCon);
if (g_oaATAInform[ucCon].eAtaMode == eATA_MODE_UDMA)
{
ATA_SetUdmaAutoMode(ucCon, DISABLE);
}
return TRUE;
}
/*---------------------------------- APIs of ATA_CONTROL Registers ---------------------------------*/
//////////
// Function Name : ATA_SetEnable
// Function Description : This function enables/disables ATA controller.
// Input : ucCon - ATA Controller Number
// ucEnFlag - ATA Enable/Disable
// Output : NONE
// Version : v0.1
void ATA_SetEnable(u8 ucCon, u8 ucEnFlag)
{
u32 uRegValue = 0;
uRegValue = ATA_GetRegValue(ucCon, eATA_CONTROL);
uRegValue = uRegValue & ~(0x1) | (ucEnFlag << 0);
ATA_SetRegValue(ucCon, eATA_CONTROL, uRegValue);
}
/*---------------------------------- APIs of ATA_STATUS Registers ---------------------------------*/
//////////
// Function Name : ATA_WaitForTransferDone
// Function Description : This function implements wait function by checking ATA STATUS Register.
// Input : ucCon - ATA Controller Number
// Output : NONE
// Version : v0.1
void ATA_WaitForTransferDone(u8 ucCon)
{
u32 uRegValue = 0;
// Disp("MODE3:%s\n", ATA_GetModeName(g_oaATAInform[ucCon].eAtaMode));
do {
ATA_WaitForHostReady(ucCon); /// needed
uRegValue = ATA_GetRegValue(ucCon, eATA_STATUS);
// Disp("%s,%d:Value:0x%x\n", __FUNCTION__, __LINE__, uRegValue);
} while((uRegValue & 3)!=0);
}
/*---------------------------------- APIs of ATA_COMMAND Registers ---------------------------------*/
//////////
// Function Name : ATA_SetTransferCommand
// Function Description : This function sets up ATA transfer command.
// Input : ucCon - ATA Controller Number
// eXfrCmd - STOP/START/ABORT/CONTINUE
// Output : NONE
// Version : v0.1
void ATA_SetTransferCommand(u8 ucCon, eATA_XFR_CMD eXfrCmd)
{
u32 uRegValue = 0;
uRegValue = ATA_GetRegValue(ucCon, eATA_COMMAND);
uRegValue = uRegValue & ~(0x3) | (eXfrCmd << 0);
ATA_SetRegValue(ucCon, eATA_COMMAND, uRegValue);
}
/*---------------------------------- APIs of ATA_SWRST Registers ---------------------------------*/
//////////
// Function Name : ATA_SetSwRst
// Function Description : This function implements s/w reset function of ATA controller.
// Input : ucCon - ATA Controller Number
// eIrqSrc - Interrupt source to mask
// Output : NONE
// Version : v0.1
void ATA_SetSwRst(u8 ucCon, u8 ucEnFlag)
{
u32 uRegValue = 0;
uRegValue = ATA_GetRegValue(ucCon, eATA_SWRST);
uRegValue = uRegValue & ~(0x1) | (ucEnFlag << 0);
ATA_SetRegValue(ucCon, eATA_SWRST, uRegValue);
}
/*---------------------------------- APIs of ATA_IRQ/ATA_IRQ_MASK Registers ---------------------------------*/
//////////
// Function Name : ATA_SetIRQMask
// Function Description : This function implements interrupt masking function of ATA controller.
// Input : ucCon - ATA Controller Number
// eIrqSrc - Interrupt source to mask
// Output : NONE
// Version : v0.1
void ATA_SetIRQ(u8 ucCon, eATA_IRQ_SRC eIrqSrc)
{
u32 uRegValue = 0;
uRegValue = ATA_GetRegValue(ucCon, eATA_IRQ);
uRegValue = uRegValue & ~(0x1f) | (eIrqSrc << 0);
ATA_SetRegValue(ucCon, eATA_IRQ, uRegValue);
}
//////////
// Function Name : ATA_SetIRQMask
// Function Description : This function implements interrupt masking function of ATA controller.
// Input : ucCon - ATA Controller Number
// eIrqSrc - Interrupt source to mask
// Output : NONE
// Version : v0.1
void ATA_SetIRQMask(u8 ucCon, eATA_IRQ_SRC eIrqSrc)
{
u32 uRegValue = 0;
uRegValue = ATA_GetRegValue(ucCon, eATA_IRQ_MASK);
uRegValue = uRegValue & ~(0x1f) | (eIrqSrc << 0);
ATA_SetRegValue(ucCon, eATA_IRQ_MASK, uRegValue);
}
bool ATA_FindInterruptRequest(u8 ucCon, u32* uNthBit)
{
u32 uLoopCnt = 0;
u32 uRegValue1 = 0;
u32 uRegValue2 = 0;
for(uLoopCnt=0;uLoopCnt< ATA_INT_NUM;uLoopCnt++) {
uRegValue1 = ATA_GetRegValue(ucCon, eATA_IRQ);
uRegValue2 = ATA_GetRegValue(ucCon, eATA_IRQ_MASK);
if(((uRegValue1&(~uRegValue2))>>uLoopCnt)&0x01)
break;
}
*uNthBit = uLoopCnt;
if (uLoopCnt == ATA_INT_NUM)
return FALSE;
else
return TRUE;
}
void ATA_ClearPending(u8 ucCon, u32 uSrcInt)
{
u32 uRegValue = 0;
uRegValue = ATA_GetRegValue(ucCon, eATA_IRQ);
uRegValue = uRegValue & ~(0x1 << uSrcInt) | (0x1 << uSrcInt);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -