📄 ata.c
字号:
void ChangeATAMode(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 SetAtaDevice(unsigned int uLBA, unsigned int 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 SetConfigMode(ATA_MODE mode, bool isWriteMode)
{
switch(mode)
{
case PIO_CPU:
uCfgReg = ((uCfgReg&0x1F3) | (0<<2)); // set PIO_CPU class
break;
case PIO_DMA:
uCfgReg = ((uCfgReg&0x1F3) | (1<<2)); // set PDMA class
if (isWriteMode == TRUE)
uCfgReg |= 0x10; // DMA write mode
else
uCfgReg &= (~0x10); // DMA read mode
break;
case UDMA:
uCfgReg = ((uCfgReg&0x1F3) | (2<<2)); // set UDMA class
uCfgReg |= 0x200; // set ATA DMA auto mode (enable multi block transfer)
if (isWriteMode == TRUE)
uCfgReg |= 0x10; // DMA write mode
else
uCfgReg &= (~0x10); // DMA read mode
break;
default:
break;
}
Outp32(ATA_CFG, uCfgReg);
}
bool WriteSectors_Pio(unsigned int uLBA,unsigned int uSectorCount,unsigned int uSrcAddress)
{
unsigned int uCurrentCount;
unsigned int uRemainderCount;
unsigned int uCurrentLba;
unsigned int uCurrentSrcAddr;
unsigned int uRound;
unsigned short* uAtaHostAddr;
unsigned int i;
#if PERF_TEST_PIO_D
unsigned int op_time = 0;
SetResStopwatch(10000); // us order, 10000us = 10ms
#endif
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;
uCurrentSrcAddr = uSrcAddress + uRound*256*ATA_SECTORSIZE;
uAtaHostAddr = (unsigned short*)uCurrentSrcAddr;
SetAtaDevice(uCurrentLba, uCurrentCount);
WriteOnTaskFileReg(DEV_COMMAND, WRITESECTOR);
while(uCurrentCount-- ) {
WaitForDeviceReady();
#if PERF_TEST_PIO_D
StartStopwatch(); // Start timer
#endif
for (i=0;i<ATA_SECTORSIZE/2;i++) {
PutDataToDevice(*uAtaHostAddr);
uAtaHostAddr++;
}
#if PERF_TEST_PIO_D
op_time += EndStopwatch(); // end timer, us order
#endif
}
WaitForDeviceReady();
uRound++;
}
#if PERF_TEST_PIO_D
printf ("PIO Writing time : %d us, Performance : %lf MByte/sec\n"
,op_time,(float)(uSectorCount*512./op_time));
#endif
return TRUE;
}
bool ReadSectors_Pio(unsigned int uLBA, unsigned int uSectorCount, unsigned int uDesAddress)
{
unsigned int uCurrentCount;
unsigned int uRemainderCount;
unsigned int uCurrentLba;
unsigned int uCurrentDstAddr;
unsigned int uRound;
unsigned short* uAtaHostAddr;
unsigned int i;
#if PERF_TEST_PIO_D
unsigned int op_time = 0;
SetResStopwatch(10000); // us order, 10000us = 10ms
#endif
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 = (unsigned short*)uCurrentDstAddr;
SetAtaDevice(uCurrentLba, uCurrentCount);
WriteOnTaskFileReg(DEV_COMMAND, READSECTOR);
while(uCurrentCount-- ) {
WaitForDeviceReady();
#if PERF_TEST_PIO_D
StartStopwatch(); // Start timer
#endif
for (i=0;i<ATA_SECTORSIZE/2;i++) {
GetDataFromDevice(uAtaHostAddr);
uAtaHostAddr++;
}
#if PERF_TEST_PIO_D
op_time += EndStopwatch(); // end timer, us order
#endif
}
WaitForDeviceReady();
uRound++;
}
#if PERF_TEST_PIO_D
printf ("PIO Reading time : %d us, Performance : %lf MByte/sec\n"
,op_time,(float)(uSectorCount*512./op_time));
#endif
return TRUE;
}
bool WriteSector_PioDma(unsigned int uLBA, unsigned int 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 ReadSector_PioDma(unsigned int uLBA, unsigned int 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 WriteSectors_Udma(unsigned int uLBA, unsigned int uSectorCount, unsigned int uSrcAddress)
{
unsigned int uCurrentCount;
unsigned int uRemainderCount;
unsigned int uCurrentLba;
unsigned int uCurrentSrcAddr;
unsigned int uRound;
#if PERF_TEST_UDMA_D
unsigned int op_time=0;
SetResStopwatch(10000); // us order, 10000us = 10ms
#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;
uCurrentSrcAddr = uSrcAddress + uRound*256*ATA_SECTORSIZE;
#if 0
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);
#if PERF_TEST_UDMA_D
StartStopwatch(); // Start timer
#endif
/*ATA Transfer Command */
ChangeBufferControl(UDMA);
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
ChangeBufferControl(PIO_CPU);
#if PERF_TEST_UDMA_D
op_time += EndStopwatch(); // end timer, us order
#endif
SetConfigMode(PIO_CPU, TRUE);
WaitForDeviceReady();
uCfgReg &= (~0x200); // disable ATA DMA auto mode
Outp32(ATA_CFG, uCfgReg);
#endif
uRound++;
}
#if PERF_TEST_UDMA_D
printf ("UDMA writing time : %d us, Performance : %lf MByte/sec\n"
,op_time,(float)(uSectorCount*512./op_time));
#endif
return TRUE;
}
bool ReadSectors_Udma(unsigned int uLBA, unsigned int uSectorCount, unsigned int uDstAddress)
{
unsigned int uCurrentCount;
unsigned int uRemainderCount;
unsigned int uCurrentLba;
unsigned int uCurrentDstAddr;
unsigned int uRound;
#if PERF_TEST_UDMA_D
unsigned int op_time=0;
SetResStopwatch(10000); // us order, 10000us = 10ms
#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;
#if 0
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(); // too long time.... in UDMA mode
SetConfigMode(UDMA, FALSE);
#if PERF_TEST_UDMA_D
StartStopwatch(); // Start timer
#endif
/*ATA Transfer Command */
ChangeBufferControl(UDMA);
SetBufferDirection(READDMA);
SetTransferCommand(ATA_CMD_START);
WaitForTransferDone(); // Host
SetTransferCommand(ATA_CMD_ABORT);
SetBufferDirection(0); // clear to H
ChangeBufferControl(PIO_CPU);
#if PERF_TEST_UDMA_D
op_time += EndStopwatch(); // end timer, us order
#endif
SetConfigMode(PIO_CPU, FALSE);
WaitForDeviceReady();
uCfgReg &= (~0x200); // disable ATA DMA auto mode
Outp32(ATA_CFG, uCfgReg);
#endif
uRound++;
}
#if PERF_TEST_UDMA_D
printf ("UDMA reading time : %d us, Performance : %lf MByte/sec\n"
,op_time,(float)(uSectorCount*512./op_time));
#endif
return TRUE;
}
void InitBufferControl(void) // added by junon for second UDMA test b'd 060902
{
#ifdef __EVT1
rGPACDH = 0x1aa8a; // GPA10 RDATA_OEN setting
#else
rGPBCON = rGPBCON & ~((3<<8)|(3)) | (1<<8)|(1); // GPB0,4 output setting (TOUT0, TCLK - TP21,20)
rGPBCON = rGPBCON & ~((3<<12)|(3<<10)) | (1<<12)|(1<<10); // GPB5,6 output setting (nXBACK, nXBREQ)
rGPBDAT = rGPBDAT & ~((7<<4)|(1)) | (1<<6); // GPB6->high, GPB0,4,5->low
#endif
DbgAta(("IBC - rGPBCON = 0x%x \n",rGPBCON));
}
void ChangeBufferControl(ATA_MODE mode) // only for SMDK b'd 060902 using additianal logic
{
if (mode == UDMA)
rGPBDAT = rGPBDAT | (1<<4)|(1); // GPB0->high,GPB4->high => UDMA mode
else // PIO
rGPBDAT = rGPBDAT & ~(1<<4) | (1); // GPB0->high,GPB4->low => ATA PIO mode
DbgAta(("BC - rGPBDAT = 0x%x \n",rGPBDAT));
}
void SetBufferDirection(unsigned int dir) // only for SMDK b'd 060812 using additianal logic
{
switch(dir)
{
case READDMA :
rGPBDAT &= ~(1<<5); // GPB5 -> L, buffer direction - read setting s
rGPBDAT &= ~(1<<6); // GPB6 -> L, buffer Output enable
break;
case WRITEDMA :
rGPBDAT |= (1<<5); // GPB5 -> H, buffer direction - write setting
rGPBDAT &= ~(1<<6); // GPB6 -> L, buffer Output enable 060812
break;
default : // clear
rGPBDAT &= ~(1<<5); // GPB5 -> L, buffer direction - read setting -> must change to PIO mode
rGPBDAT |= (1<<6); // GPB6 -> H, buffer Output disable
break;
}
DbgAta(("BD - rGPBDAT = 0x%x \n",rGPBDAT));
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -