?? ata.cpp
字號(hào):
}
/**********************************
* 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(PIOMODE pmode)
{
U8 nMode = (pmode == PIO0) ? 0 :
(pmode == PIO1) ? 1 :
(pmode == PIO2) ? 2 :
(pmode == PIO3) ? 3 :
(pmode == PIO4) ? 4 : 0;
U32 uT1;
U32 uT2;
U32 uTeoc;
U32 i;
U32 uPioTime[5];
U32 m_uPioT1[5] = {200,50,30,50,30}; // min = {70,50,30,30,25};
U32 m_uPioT2[5] = {300,300,290,100,70}; // min = {290,290,290,80,70};
U32 m_uPioTeoc[5] = {100,40,20,30,20}; // min = {20,15,10,10,10};
U32 uCycleTime = (U32)(1000000000/HCLK);
for (i=0; i<5; i++)
{
uT1 = (m_uPioT1[i] /uCycleTime + 1)&0xff;
uT2 = (m_uPioT2[i] /uCycleTime + 1)&0xff;
uTeoc = (m_uPioTeoc[i]/uCycleTime + 1)&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:
m_uCfgReg &= (~0x2); //IORDY disable
Outp32(ATA_PIO_TIME, uPioTime[1]);
break;
case PIO2:
m_uCfgReg &= (~0x2); //IORDY disable
Outp32(ATA_PIO_TIME, uPioTime[2]);
break;
case PIO3:
m_uCfgReg |= 0x2; //IORDY enable
Outp32(ATA_PIO_TIME, uPioTime[3]);
break;
case PIO4:
m_uCfgReg |= 0x2; //IORDY enable
Outp32(ATA_PIO_TIME, uPioTime[4]);
break;
default:
m_uCfgReg &= (~0x2); //IORDY disable
Outp32(ATA_PIO_TIME, uPioTime[0]);
break;
}
Outp32(ATA_CFG, m_uCfgReg);
m_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 ATA::SetMultiple(U32 uSector)
{
m_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 ATA::SetUdmaMode(UDMAMODE umode)
{
U8 nMode;
U32 uTdvh1;
U32 uTdvs;
U32 uTrp;
U32 uTss;
U32 uTackenv;
U32 i;
U32 uUdmaTime[5];
U32 uUdmaTdvh[5] = {20,20,10,10,10}; //{7,7,7,7,7};
U32 uUdmaTdvs[5] = {100,60,50,35,20}; //{70,48,31,20,7};
U32 uUdmaTrp[5] = {160,125,100,100,100};
U32 uUdmaTss[5] = {50,50,50,50,50};
U32 uUdmaTackenvMin[5] = {20,20,20,20,20};
U32 uUdmaTackenvMax[5] = {70,70,70,55,55};
U32 uCycleTime = (U32)(1000000000/HCLK);
// added GPB setting for SMDK buffer mechanism 060812
rGPBDAT |= (3<<5); // GPB5,6 -> H
rGPBCON = rGPBCON & ~(0xf<<10) | (5<<10); // GPB5,6 output mode
for (i=0; i<5; i++)
{
uTdvh1 = (uUdmaTdvh[i] / uCycleTime + 1)&0x0f;
uTdvs = (uUdmaTdvs[i] / uCycleTime + 1)&0xff;
uTrp = (uUdmaTrp[i] / uCycleTime + 1)&0xff;
uTss = (uUdmaTss[i] / uCycleTime + 1)&0x0f;
uTackenv= (uUdmaTackenvMin[i]/uCycleTime + 1)&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;
}
m_uCurrentUdmaMode = nMode;
}
bool ATA::OpenMedia(void)
{
ATA_MODE mode;
Init();
IdentifyDevice();
// Decide what mode is best choice in this media.
if (m_uMaxUdmaMode == 0)
{
mode = PIO_DMA;
}
else
{
mode = UDMA;
}
SetAtaMode(mode);
if (mode == PIO_CPU || mode == PIO_DMA)
{
SetPioMode(m_eMaxPioMode);
}
else
{
UDMAMODE udmaMode =
(m_uMaxUdmaMode == 0) ? UDMA0 :
(m_uMaxUdmaMode == 1) ? UDMA1 :
(m_uMaxUdmaMode == 2) ? UDMA2 :
(m_uMaxUdmaMode == 3) ? UDMA3 : UDMA4;
SetPioMode(PIO0);
SetUdmaMode(udmaMode);
}
return true;
}
bool ATA::OpenMedia(ATA_MODE mode)
{
Init();
IdentifyDevice();
SetAtaMode(mode);
if (mode == PIO_CPU || mode == PIO_DMA)
{
SetPioMode(m_eMaxPioMode);
}
else
{
UDMAMODE udmaMode =
(m_uMaxUdmaMode == 0) ? UDMA0 :
(m_uMaxUdmaMode == 1) ? UDMA1 :
(m_uMaxUdmaMode == 2) ? UDMA2 :
(m_uMaxUdmaMode == 3) ? UDMA3 : UDMA4;
SetPioMode(PIO0);
SetUdmaMode(udmaMode);
}
return true;
}
bool ATA::CloseMedia(void)
{
SetAtaOnOff(0);
// Output pad disable, Card power off, PC card mode
Outp32(ATA_MUX, 0x06);
return true;
}
bool ATA::ReadBlocks(U32 uStBlock, U32 uBlocks, U32 uBufAddr)
{
// Assert(uStBlock+uBlocks <= m_uMaxSectors);
U32 k;
ATA_MODE mode = m_eMode;
bool status;
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;
}
return status;
}
bool ATA::WriteBlocks(U32 uStBlock, U32 uBlocks, U32 uBufAddr)
{
// Assert(uStBlock+uBlocks <= m_uMaxSectors);
U32 k;
ATA_MODE mode = m_eMode;
bool status;
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;
}
return status;
}
void SetBufferDirection(U32 dir) // only for SMDK b'd 060812
{
switch(dir)
{
case READDMA :
rGPBDAT &= ~(3<<5); // GPB5 -> L, buffer direction - read setting
// 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 |= (3<<5); // GPB5 -> H, buffer direction - write setting
// GPB6 -> H, buffer Output disable
break;
}
}
bool ATA::StartReadingBlocks(U32 uStBlock, U32 uBlocks, U32 uBufAddr)
{
// Assert(!(m_eMode == PIO_CPU));
U32 deviceCmd = (m_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(m_eMode, false);
if (m_eMode == UDMA) // apply at specific set using buffer control
{
printf("Ready for reading data in UDMA. Change dip SW & Press Enter..\n");
getchar();
SetBufferDirection(READDMA);
}
SetTransferCommand(ATA_CMD_START);
return true;
}
bool ATA::IsReadingBlocksDone(void)
{
return IsWritingBlocksDone();
}
void ATA::ContinueReadingBlocks(void)
{
}
bool ATA::StartWritingBlocks(U32 uStBlock, U32 uBlocks, U32 uBufAddr)
{
// Assert(!(m_eMode == PIO_CPU));
U32 deviceCmd = (m_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(m_eMode, true);
if (m_eMode == UDMA) // apply at specific set using buffer control
{
printf("Ready for writing data in UDMA. Change dip SW & Press Enter..\n");
getchar();
SetBufferDirection(WRITEDMA); // for SMDK buffer direction only
}
SetTransferCommand(ATA_CMD_START);
return true;
}
bool ATA::IsWritingBlocksDone(void)
{
WaitForTransferDone();
?? 快捷鍵說明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號(hào)
Ctrl + =
減小字號(hào)
Ctrl + -