📄 ata.cpp
字号:
return IsDmaDone();
}
void ATA::ContinueWritingBlocks(void)
{
}
bool ATA::IsDmaDone(void)
{
SetTransferCommand(ATA_CMD_ABORT);
if (m_eMode == UDMA) // apply at specific set using buffer control
{
SetBufferDirection(0); // clear
printf("Return to PIO mode. Change dip SW & Press Enter..\n");
getchar();
}
SetConfigMode(PIO_CPU, true);
WaitForDeviceReady();
if (m_eMode == UDMA)
{
m_uCfgReg &= (~0x200); // disable ATA DMA auto mode
Outp32(ATA_CFG, m_uCfgReg);
}
return true;
}
void ATA::ChangeMode(void)
{
#ifdef CFCON_MODE
SetResTDelay(10); // TDelay 1 unit = 10us
InitTDelayFunc();
// CF controller - True IDE mode setting
Outp32(ATA_MUX, 0x07); // Output pad disable, Card power off, ATA mode
TDelay(100);
Outp32(ATA_MUX, 0x03); // Output pad enable, Card power off, ATA mode
TDelay(100);
Outp32(ATA_MUX, 0x01); // Output pad enable, Card power on, ATA mode
TDelay(50000); // wait for 500ms
#endif
}
void ATA::SetAtaDevice(U32 uLBA, U32 uSectorCount)
{
WriteOnTaskFileReg(DEV_SECTOR,uSectorCount&0xFF);
WriteOnTaskFileReg(DEV_LOWLBA,uLBA&0xFF);
WriteOnTaskFileReg(DEV_MIDLBA,(uLBA>>8)&0xFF);
WriteOnTaskFileReg(DEV_HIGHLBA,(uLBA>>16)&0xFF);
WriteOnTaskFileReg(DEV_DEVICE,((uLBA>>24)&0xF)|0x40);
}
void ATA::SetConfigMode(ATA_MODE mode, bool isWriteMode)
{
switch(mode)
{
case PIO_CPU:
m_uCfgReg = ((m_uCfgReg&0x1F3) | (0<<2)); // set PIO_CPU class
break;
case PIO_DMA:
m_uCfgReg = ((m_uCfgReg&0x1F3) | (1<<2)); // set PDMA class
if (isWriteMode == true)
m_uCfgReg |= 0x10; // DMA write mode
else
m_uCfgReg &= (~0x10); // DMA read mode
break;
case UDMA:
m_uCfgReg = ((m_uCfgReg&0x1F3) | (2<<2)); // set UDMA class
m_uCfgReg |= 0x200; // set ATA DMA auto mode (enable multi block transfer)
if (isWriteMode == true)
m_uCfgReg |= 0x10; // DMA write mode
else
m_uCfgReg &= (~0x10); // DMA read mode
break;
default:
break;
}
Outp32(ATA_CFG, m_uCfgReg);
}
bool ATA::WriteSectors_Pio(U32 nLBA,U32 nSectorCount,U32 nSrcAddress)
{
U32 uCurrentCount;
U32 uRemainderCount;
U32 uCurrentLba;
U32 uCurrentSrcAddr;
U32 uRound;
U16* uAtaHostAddr;
U32 i;
uRemainderCount = nSectorCount;
uCurrentLba = nLBA;
uRound = 0;
while(uRemainderCount != 0) {
if(uRemainderCount>256) {
uCurrentCount = 256; //0 means 256
uRemainderCount -= 256;
} else {
uCurrentCount = uRemainderCount;
uRemainderCount = 0;
}
uCurrentLba = nLBA + uRound*256;
uCurrentSrcAddr = nSrcAddress + uRound*256*ATA_SECTORSIZE;
uAtaHostAddr = (U16*)uCurrentSrcAddr;
SetAtaDevice(uCurrentLba, uCurrentCount);
WriteOnTaskFileReg(DEV_COMMAND, WRITESECTOR);
while(uCurrentCount-- ) {
WaitForDeviceReady();
for (i=0;i<ATA_SECTORSIZE/2;i++) {
PutDataToDevice(*uAtaHostAddr);
uAtaHostAddr++;
}
}
WaitForDeviceReady();
uRound++;
}
return true;
}
bool ATA::ReadSectors_Pio(U32 uLBA, U32 uSectorCount, U32 uDesAddress)
{
U32 uCurrentCount;
U32 uRemainderCount;
U32 uCurrentLba;
U32 uCurrentDstAddr;
U32 uRound;
U16* uAtaHostAddr;
U32 i;
uRemainderCount = uSectorCount;
uCurrentLba = uLBA;
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 = uDesAddress + uRound*256*ATA_SECTORSIZE;
uAtaHostAddr = (U16*)uCurrentDstAddr;
SetAtaDevice(uCurrentLba, uCurrentCount);
WriteOnTaskFileReg(DEV_COMMAND, READSECTOR);
while(uCurrentCount-- ) {
WaitForDeviceReady();
for (i=0;i<ATA_SECTORSIZE/2;i++) {
GetDataFromDevice(*uAtaHostAddr);
uAtaHostAddr++;
}
}
WaitForDeviceReady();
uRound++;
}
return true;
}
bool ATA::WriteSector_PioDma(U32 uLBA, U32 uSrcAddress)
{
#if 1
StartWritingBlocks(uLBA, 1, uSrcAddress);
return IsWritingBlocksDone();
#else
/*Source Buffer 1 Setting*/
Outp32(ATA_SBUF_START, uSrcAddress);
Outp32(ATA_SBUF_SIZE, 1*ATA_SECTORSIZE);
Outp32(ATA_XFR_NUM, 1*ATA_SECTORSIZE);
SetAtaDevice(uLBA, 1);
WriteOnTaskFileReg(DEV_COMMAND, WRITESECTOR);
WaitForDeviceReady();
SetConfigMode(PIO_DMA, true);
SetTransferCommand(ATA_CMD_START);
WaitForTransferDone();
SetTransferCommand(ATA_CMD_ABORT);
SetConfigMode(PIO_CPU, true);
WaitForDeviceReady();
return true;
#endif
}
bool ATA::ReadSector_PioDma(U32 uLBA, U32 uDesAddress)
{
#if 1
StartReadingBlocks(uLBA, 1, uDesAddress);
return IsReadingBlocksDone();
#else
/*Track Buffer 1 Setting*/
Outp32(ATA_TBUF_START, uDesAddress);
Outp32(ATA_TBUF_SIZE, 1*ATA_SECTORSIZE);
Outp32(ATA_XFR_NUM, 1*ATA_SECTORSIZE);
SetAtaDevice(uLBA, 1);
WriteOnTaskFileReg(DEV_COMMAND, READSECTOR);
WaitForDeviceReady();
SetConfigMode(PIO_DMA, false);
SetTransferCommand(ATA_CMD_START);
WaitForTransferDone();
SetTransferCommand(ATA_CMD_ABORT);
SetConfigMode(PIO_CPU, false);
WaitForDeviceReady();
return true;
#endif
}
bool ATA::WriteSectors_MultiplePioDma(U32 uLBA, U32 uSrcAddress)
{
/*Source Buffer 1 Setting*/
Outp32(ATA_SBUF_START, uSrcAddress);
Outp32(ATA_SBUF_SIZE, m_uCurrentMultiple*ATA_SECTORSIZE);
Outp32(ATA_XFR_NUM, m_uCurrentMultiple*ATA_SECTORSIZE);
SetAtaDevice(uLBA, m_uCurrentMultiple);
WriteOnTaskFileReg(DEV_COMMAND, WRITEMULTIPLE);
WaitForDeviceReady();
SetConfigMode(PIO_DMA, true);
/*ATA Transfer Command */
SetTransferCommand(ATA_CMD_START);
WaitForTransferDone();
SetTransferCommand(ATA_CMD_ABORT);
SetConfigMode(PIO_CPU, true);
WaitForDeviceReady();
return true;
}
bool ATA::ReadSectors_MultiplePioDma(U32 uLBA, U32 uDesAddress)
{
/*Track Buffer 1 Setting*/
Outp32(ATA_TBUF_START, uDesAddress);
Outp32(ATA_TBUF_SIZE, (m_uCurrentMultiple*ATA_SECTORSIZE));
Outp32(ATA_XFR_NUM, (m_uCurrentMultiple*ATA_SECTORSIZE));
SetAtaDevice(uLBA, m_uCurrentMultiple);
WriteOnTaskFileReg(DEV_COMMAND, READMULTIPLE);
WaitForDeviceReady();
SetConfigMode(PIO_DMA, false);
SetTransferCommand(ATA_CMD_START);
WaitForTransferDone();
SetTransferCommand(ATA_CMD_ABORT);
SetConfigMode(PIO_CPU, false);
WaitForDeviceReady();
return true;
}
bool ATA::WriteSectors_Udma(U32 uLBA, U32 uSectorCount, U32 uSrcAddress)
{
U32 uCurrentCount;
U32 uRemainderCount;
U32 uCurrentLba;
U32 uCurrentSrcAddr;
U32 uRound;
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;
uCurrentSrcAddr = uSrcAddress + uRound*256*ATA_SECTORSIZE;
#if 1
StartWritingBlocks(uCurrentLba, uCurrentCount, uCurrentSrcAddr);
IsWritingBlocksDone();
#else
/*Source Buffer 1 Setting*/
Outp32(ATA_SBUF_START, uCurrentSrcAddr);
Outp32(ATA_SBUF_SIZE, uCurrentCount*ATA_SECTORSIZE);
Outp32(ATA_XFR_NUM, uCurrentCount*ATA_SECTORSIZE);
SetAtaDevice(uCurrentLba, uCurrentCount);
WriteOnTaskFileReg(DEV_COMMAND,WRITEDMA);
WaitForDeviceReady();
SetConfigMode(UDMA, true);
printf("Ready for writing in UDMA. Change dip SW & Press Enter..\n");
getchar();
/*ATA Transfer Command */
SetBufferDirection(WRITEDMA);
SetTransferCommand(ATA_CMD_START);
#if 1
WaitForTransferDone();
#else // abort operation
while(1){
Inp32(ATA_XFR_CNT, temp);
if(temp <= uCurrentCount*ATA_SECTORSIZE) break;
}
#endif
SetTransferCommand(ATA_CMD_ABORT);
SetBufferDirection(0); // clear to H
printf("Return to PIO mode. Change dip SW & Press Enter..\n");
getchar();
SetConfigMode(PIO_CPU, true);
WaitForDeviceReady();
m_uCfgReg &= (~0x200); // disable ATA DMA auto mode
Outp32(ATA_CFG, m_uCfgReg);
#endif
uRound++;
}
return true;
}
bool ATA::ReadSectors_Udma(U32 uLBA, U32 uSectorCount, U32 uDstAddress)
{
U32 uCurrentCount;
U32 uRemainderCount;
U32 uCurrentLba;
U32 uCurrentDstAddr;
U32 uRound;
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;
#if 1
StartReadingBlocks(uCurrentLba, uCurrentCount, uCurrentDstAddr);
IsReadingBlocksDone();
#else
/*Track Buffer 1 Setting*/
Outp32(ATA_TBUF_START, uCurrentDstAddr);
Outp32(ATA_TBUF_SIZE, uCurrentCount*ATA_SECTORSIZE);
Outp32(ATA_XFR_NUM, uCurrentCount*ATA_SECTORSIZE);
SetAtaDevice(uCurrentLba, uCurrentCount);
WriteOnTaskFileReg(DEV_COMMAND,READDMA);
WaitForDeviceReady();
SetConfigMode(UDMA, false);
printf("Ready for reading in UDMA. Change dip SW & Press Enter..\n");
getchar();
/*ATA Transfer Command */
SetBufferDirection(READDMA);
SetTransferCommand(ATA_CMD_START);
WaitForTransferDone(); // Host
SetTransferCommand(ATA_CMD_ABORT);
SetBufferDirection(0); // clear to H
printf("Return to PIO mode. Change dip SW & Press Enter..\n");
getchar();
SetConfigMode(PIO_CPU, false);
WaitForDeviceReady();
m_uCfgReg &= (~0x200); // disable ATA DMA auto mode
Outp32(ATA_CFG, m_uCfgReg);
#endif
uRound++;
}
return true;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -