📄 ata.c
字号:
void GetMaxMultiple(unsigned int* maxMulti)
{
*maxMulti = uMaxMultiple;
}
/**********************************
* 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 SetPioMode(PIOMODE pmode)
{
unsigned char nMode = (pmode == PIO0) ? 0 :
(pmode == PIO1) ? 1 :
(pmode == PIO2) ? 2 :
(pmode == PIO3) ? 3 :
(pmode == PIO4) ? 4 : 0;
unsigned int uT1;
unsigned int uT2;
unsigned int uTeoc;
unsigned int i;
unsigned int uPioTime[5];
unsigned int m_uPioT1[5] = {70,50,30,30,30}; // min = {70,50,30,30,25}; edited by junon 060827
unsigned int m_uPioT2[5] = {290,290,290,80,70}; // min = {290,290,290,80,70};
unsigned int m_uPioTeoc[5] = {20,20,10,10,10}; // min = {20,15,10,10,10};
unsigned int uCycleTime = (unsigned int)(1000000000/HCLK);
for (i=0; i<5; i++)
{
uT1 = (m_uPioT1[i] /uCycleTime)&0xff; // edited by junon 060827
uT2 = (m_uPioT2[i] /uCycleTime)&0xff;
uTeoc = (m_uPioTeoc[i]/uCycleTime)&0x0f;
uPioTime[i] = (uTeoc<<12)|(uT2<<4)|uT1;
DbgAta(("PIO%dTIME = %x\n", i, uPioTime[i]));
}
Outp32(ATA_IRQ, 0xff);
Outp32(ATA_IRQ_MASK, ATAPI_MASK);
WriteOnTaskFileReg(DEV_CONTROL,0);
WriteOnTaskFileReg(DEV_FEATURE,0x03); //set transfer mode based on value in Sector Count register
WriteOnTaskFileReg(DEV_SECTOR,0x08|(nMode&0x7)); // PIO flow control transfer mode
WriteOnTaskFileReg(DEV_LOWLBA,0x00);
WriteOnTaskFileReg(DEV_MIDLBA,0x00);
WriteOnTaskFileReg(DEV_HIGHLBA,0x00);
WriteOnTaskFileReg(DEV_DEVICE,0x40);
WriteOnTaskFileReg(DEV_COMMAND,SETFEATURES); //set feature command
WaitForDeviceReady();
switch(pmode) { // modified by Bryan W. Lee (Oct. 19th, 2005)
case PIO1:
uCfgReg &= (~0x2); //IORDY disable
Outp32(ATA_PIO_TIME, uPioTime[1]);
break;
case PIO2:
uCfgReg &= (~0x2); //IORDY disable
Outp32(ATA_PIO_TIME, uPioTime[2]);
break;
case PIO3:
uCfgReg |= 0x2; //IORDY enable
Outp32(ATA_PIO_TIME, uPioTime[3]);
break;
case PIO4:
uCfgReg |= 0x2; //IORDY enable
Outp32(ATA_PIO_TIME, uPioTime[4]);
break;
default:
uCfgReg &= (~0x2); //IORDY disable
Outp32(ATA_PIO_TIME, uPioTime[0]);
break;
}
Outp32(ATA_CFG, uCfgReg);
eCurrentPioMode = pmode;
}
//uSector: the number of sectors per block
// if the block count is not supported, an Abort Command error is posted,
// and the Read Multiple and Write Multiple commands are disabled.
void SetMultiple(unsigned int uSector)
{
uCurrentMultiple = uSector;
WriteOnTaskFileReg(DEV_CONTROL,0);
WriteOnTaskFileReg(DEV_SECTOR,uSector&0xff);
WriteOnTaskFileReg(DEV_LOWLBA,0x00);
WriteOnTaskFileReg(DEV_MIDLBA,0x00);
WriteOnTaskFileReg(DEV_HIGHLBA,0x00);
WriteOnTaskFileReg(DEV_DEVICE,0x40);
WriteOnTaskFileReg(DEV_COMMAND,0xC6); //Set Multiple mode (implemented in ATA IP ??)
WaitForDeviceReady();
}
/**********************************
* 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 SetUdmaMode(UDMAMODE umode)
{
unsigned char nMode = 0;
unsigned int uTdvh1;
unsigned int uTdvs;
unsigned int uTrp;
unsigned int uTss;
unsigned int uTackenv;
unsigned int i;
unsigned int uUdmaTime[5]; // Tdvh+Tdvs min = {120,80,60,45,30}
unsigned int uUdmaTdvh[5] = {10,10,10,10,10}; // min = {6.2,6.2,6.2,6.2,6.2}; edited by junon 060827
unsigned int uUdmaTdvs[5] = {100,60,50,35,20}; // min = {70,48,31,20,6.7};
unsigned int uUdmaTrp[5] = {160,125,100,100,100}; // min = {160,125,100,100,100};
unsigned int uUdmaTss[5] = {50,50,50,50,50}; // min = {50,50,50,50,50};
unsigned int uUdmaTackenvMin[5] = {20,20,20,20,20};
unsigned int uCycleTime = (unsigned int)(1000000000/HCLK);
for (i=0; i<5; i++)
{
uTdvh1 = (uUdmaTdvh[i] / uCycleTime)&0x0f; // edited by junon 060827
uTdvs = (uUdmaTdvs[i] / uCycleTime)&0xff;
uTrp = (uUdmaTrp[i] / uCycleTime)&0xff;
uTss = (uUdmaTss[i] / uCycleTime)&0x0f;
uTackenv= (uUdmaTackenvMin[i]/uCycleTime)&0x0f;
uUdmaTime[i] = (uTdvh1<<24)|(uTdvs<<16)|(uTrp<<8)|(uTss<<4)|uTackenv;
DbgAta(("UDMA%dTIME = %x\n", i, uUdmaTime[i]));
}
Outp32(ATA_IRQ, 0xff);
Outp32(ATA_IRQ_MASK, ATAPI_MASK);
WriteOnTaskFileReg(DEV_CONTROL,0);
WriteOnTaskFileReg(DEV_FEATURE,0x03);
WriteOnTaskFileReg(DEV_SECTOR,0x40|(nMode&0x7));
WriteOnTaskFileReg(DEV_LOWLBA,0x00);
WriteOnTaskFileReg(DEV_MIDLBA,0x00);
WriteOnTaskFileReg(DEV_HIGHLBA,0x00);
WriteOnTaskFileReg(DEV_DEVICE,0x40);
WriteOnTaskFileReg(DEV_COMMAND,SETFEATURES);
WaitForDeviceReady();
switch(umode) {
case UDMA0:
nMode = 0;
Outp32(ATA_UDMA_TIME, uUdmaTime[0]);
break;
case UDMA1:
nMode = 1;
Outp32(ATA_UDMA_TIME, uUdmaTime[1]);
break;
case UDMA2:
nMode = 2;
Outp32(ATA_UDMA_TIME, uUdmaTime[2]);
break;
case UDMA3:
nMode = 3;
Outp32(ATA_UDMA_TIME, uUdmaTime[3]);
break;
case UDMA4:
nMode = 4;
Outp32(ATA_UDMA_TIME, uUdmaTime[4]);
break;
default:
DbgAta(("Wrong UDMA mode in SetUdmaMode()\n"));
break;
}
uCurrentUdmaMode = nMode;
}
bool OpenATAMedia(void)
{
ATA_MODE mode;
Init();
IdentifyDevice();
// Decide what mode is best choice in this media.
if (uMaxUdmaMode == 0)
{
mode = PIO_DMA;
}
else
{
mode = UDMA;
}
SetAtaMode(mode);
if (mode == PIO_CPU || mode == PIO_DMA)
{
SetPioMode(eMaxPioMode);
}
else
{
UDMAMODE udmaMode =
(uMaxUdmaMode == 0) ? UDMA0 :
(uMaxUdmaMode == 1) ? UDMA1 :
(uMaxUdmaMode == 2) ? UDMA2 :
(uMaxUdmaMode == 3) ? UDMA3 : UDMA4;
SetPioMode(PIO0);
SetUdmaMode(udmaMode);
}
return TRUE;
}
bool OpenATAMediaWithMode(ATA_MODE mode)
{
Init();
IdentifyDevice();
SetAtaMode(mode);
if (mode == PIO_CPU || mode == PIO_DMA)
{
SetPioMode(eMaxPioMode);
DbgAta(("Now PIO mode%d is set!!\n",eMaxPioMode));
}
else
{
UDMAMODE udmaMode =
(uMaxUdmaMode == 0) ? UDMA0 :
(uMaxUdmaMode == 1) ? UDMA1 :
(uMaxUdmaMode == 2) ? UDMA2 :
(uMaxUdmaMode == 3) ? UDMA3 : UDMA4;
SetPioMode(PIO0);
SetUdmaMode(udmaMode);
DbgAta(("Now PIO mode0, UDMA mode%d is set!!\n",udmaMode));
}
return TRUE;
}
bool CloseATAMedia(void)
{
SetAtaOnOff(0);
// Output pad disable, Card power off, PC card mode
Outp32(ATA_MUX, 0x06);
return TRUE;
}
bool ReadATABlocks(unsigned int uStBlock, unsigned int uBlocks, unsigned int uBufAddr)
{
unsigned int k;
ATA_MODE mode = eMode;
bool status = FALSE;
#if PERF_TEST_ATA
unsigned int op_time=0;
SetResStopwatch(10000); // us order, 10000us = 10ms
StartStopwatch(); // Start timer
#endif
switch(mode)
{
case PIO_CPU:
status = ReadSectors_Pio( uStBlock, uBlocks, uBufAddr);
break;
case PIO_DMA:
for(k=0; k<uBlocks; k++)
{
ReadSector_PioDma(uStBlock+k, uBufAddr+ATA_SECTORSIZE*k);
WaitForTransferDone();
}
status = TRUE; // need to move..
break;
case UDMA:
status = ReadSectors_Udma( uStBlock, uBlocks, uBufAddr);
break;
default:
DbgAta(("Not supported mode in ReadBlocks()\n"));
break;
}
#if PERF_TEST_ATA
op_time = EndStopwatch(); // end timer, us order
printf (" Reading time : %d us, Performance : %lf MByte/sec\n"
,op_time,(float)(uBlocks*512./op_time));
#endif
return status;
}
bool WriteATABlocks(unsigned int uStBlock, unsigned int uBlocks, unsigned int uBufAddr)
{
unsigned int k;
ATA_MODE mode = eMode;
bool status = FALSE;
#if PERF_TEST_ATA
unsigned int op_time=0;
SetResStopwatch(10000); // us order, 10000us = 10ms
StartStopwatch(); // Start timer
#endif
switch(mode)
{
case PIO_CPU:
status = WriteSectors_Pio( uStBlock, uBlocks, uBufAddr);
break;
case PIO_DMA:
for(k=0; k<uBlocks; k++)
{
WriteSector_PioDma(uStBlock+k, uBufAddr+ATA_SECTORSIZE*k);
WaitForTransferDone();
}
status = TRUE;
break;
case UDMA:
status = WriteSectors_Udma( uStBlock, uBlocks, uBufAddr);
break;
default:
DbgAta(("Not supported mode in WriteBlocks()\n"));
break;
}
#if PERF_TEST_ATA
op_time = EndStopwatch(); // end timer, us order
printf (" Writing time : %d us, Performance : %lf MByte/sec\n"
,op_time,(float)(uBlocks*512./op_time));
#endif
return status;
}
bool StartReadingBlocks(unsigned int uStBlock, unsigned int uBlocks, unsigned int uBufAddr)
{
unsigned int deviceCmd = (eMode == UDMA) ? READDMA : READSECTOR;
/*Track Buffer 1 Setting*/
Outp32(ATA_TBUF_START, uBufAddr);
Outp32(ATA_TBUF_SIZE, uBlocks*ATA_SECTORSIZE);
Outp32(ATA_XFR_NUM, uBlocks*ATA_SECTORSIZE);
SetAtaDevice(uStBlock, uBlocks);
WriteOnTaskFileReg(DEV_COMMAND, deviceCmd);
WaitForDeviceReady();
SetConfigMode(eMode, FALSE);
#ifndef __EVT1
if (eMode == UDMA) // apply at specific set using buffer control
{
DbgAta(("Ready for reading data in UDMA..\n"));
SetBufferDirection(READDMA);
}
#endif
SetTransferCommand(ATA_CMD_START);
return TRUE;
}
bool IsReadingBlocksDone(void)
{
return IsWritingBlocksDone();
}
void ContinueReadingBlocks(void)
{
}
bool StartWritingBlocks(unsigned int uStBlock, unsigned int uBlocks, unsigned int uBufAddr)
{
unsigned int deviceCmd = (eMode == UDMA) ? WRITEDMA : WRITESECTOR;
/*Source Buffer Setting*/
Outp32(ATA_SBUF_START, uBufAddr);
Outp32(ATA_SBUF_SIZE, uBlocks*ATA_SECTORSIZE);
Outp32(ATA_XFR_NUM, uBlocks*ATA_SECTORSIZE);
SetAtaDevice(uStBlock, uBlocks);
WriteOnTaskFileReg(DEV_COMMAND, deviceCmd);
WaitForDeviceReady();
SetConfigMode(eMode, TRUE);
#ifndef __EVT1
if (eMode == UDMA) // apply at specific set using buffer control
{
printf("Ready for writing data in UDMA. \n");
SetBufferDirection(WRITEDMA); // for SMDK buffer direction only
}
#endif
SetTransferCommand(ATA_CMD_START);
return TRUE;
}
bool IsWritingBlocksDone(void)
{
WaitForTransferDone();
return IsDmaDone();
}
void ContinueWritingBlocks(void)
{
}
bool IsDmaDone(void)
{
SetTransferCommand(ATA_CMD_ABORT);
#ifndef __EVT1
if (eMode == UDMA) // apply at specific set using buffer control
{
SetBufferDirection(0); // clear
ChangeBufferControl(PIO_CPU);
DbgAta(("Return to PIO mode. \n"));
}
#endif
SetConfigMode(PIO_CPU, TRUE);
WaitForDeviceReady();
if (eMode == UDMA)
{
uCfgReg &= (~0x200); // disable ATA DMA auto mode
Outp32(ATA_CFG, uCfgReg);
}
return TRUE;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -