📄 ata.c
字号:
WriteOnTaskFileReg(DEV_COMMAND,SETFEATURES); //set feature command
WaitForNoBusyStatus();
//printf ("gh0522.cha's debugging ...%d\n",pmode);//gh0522.cha
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, 0x073);
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_oDevice[0].CurrentPioMode = nMode;
}
//nSector: 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(U32 nSector)
{
m_oDevice[0].CurrentMultiple = nSector;
WriteOnTaskFileReg(DEV_CONTROL,0);
WriteOnTaskFileReg(DEV_SECTOR,nSector&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 ??)
WaitForNoBusyStatus();
}
void 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 SetUdmaMode(int umode)
{
U8 nMode;
U32 uTdvh1;
U32 uTdvs;
U32 uTrp;
U32 uTss;
U32 uTackenv;
U32 i;
U32 uUdmaTime[5];
U32 m_uUdmaTdvh[5] = {7,7,7,7,7};
U32 m_uUdmaTdvs[5] = {70,48,31,20,7};
U32 m_uUdmaTrp[5] = {160,125,100,100,100};
U32 m_uUdmaTss[5] = {50,50,50,50,50};
U32 m_uUdmaTackenvMin[5] = {20,20,20,20,20};
U32 m_uUdmaTackenvMax[5] = {70,70,70,55,55};
U32 uCycleTime = (U32)(1000000000/HCLK);
for (i=0; i<5; i++)
{
uTdvh1 = (m_uUdmaTdvh[i] / uCycleTime + 1)&0x0f;
uTdvs = (m_uUdmaTdvs[i] / uCycleTime + 1)&0xff;
uTrp = (m_uUdmaTrp[i] / uCycleTime + 1)&0xff;
uTss = (m_uUdmaTss[i] / uCycleTime + 1)&0x0f;
uTackenv= (m_uUdmaTackenvMin[i]/uCycleTime + 1)&0x0f;
uUdmaTime[i] = (uTdvh1<<24)|(uTdvs<<16)|(uTrp<<8)|(uTss<<4)|uTackenv;
// DbgAta(("UDMA%dTIME = %x\n", i, uUdmaTime[i]));
}
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:
Disp("Wrong UDMA mode in SetUdmaMode()\n");
break;
}
m_oDevice[0].CurrentUdmaMode = nMode;
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);
WaitForNoBusyStatus();
}
U32 OpenMedia(int mode)
{
U32 udmaMode;
ATA_Init();
IdentifyDevice();
// Decide what mode is best choice in this media.
SetAtaMode(mode);
if (mode == PIO || mode == PIODMA)
{
SetPioMode(m_oDevice[0].MaxPioMode);
}
else
{
udmaMode =
(m_oDevice[0].MaxUdmaMode == 0) ? UDMA0 :
(m_oDevice[0].MaxUdmaMode == 1) ? UDMA1 :
(m_oDevice[0].MaxUdmaMode == 2) ? UDMA2 :
(m_oDevice[0].MaxUdmaMode == 3) ? UDMA3 : UDMA4;
SetPioMode(PIO0);
SetUdmaMode(udmaMode);
}
return TRUE;
}
void SetConfigMode(int mode, U32 isWriteMode)
{
switch(mode)
{
case PIO:
m_uCfgReg = ((m_uCfgReg&0x1F3) | (0<<2)); // set PIO class
break;
case PIODMA:
m_uCfgReg = ((m_uCfgReg&0x1F3) |(1<<2)); // set PDMA class
if (isWriteMode == 1)
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
if (isWriteMode == 1)
m_uCfgReg |= 0x10; // DMA write mode
else
m_uCfgReg &= (~0x10); // DMA read mode
break;
default:
break;
}
Outp32(ATA_CFG, m_uCfgReg);
}
void SetTransferCommand(U8 command)
{
WaitForDeviceAccessReady(); /// needed
Outp32(ATA_COMMAND, command);
}
void PutDataToDevice(U16 data)
{
WaitForDeviceAccessReady();
Outp32(ATA_PIO_DTR, data);
}
void VerifyData(U32 writeBufferAddr, U32 readBufferAddr, U32 sectors)
{
if (Compare32(writeBufferAddr, readBufferAddr, sectors*128) == FALSE)
{
Disp("Error detected\n");
Dump32(readBufferAddr, sectors*128);
}
else
{
Disp("Write/Read is OK\n");
}
}
U32 Compare32(U32 a0, U32 a1, U32 words)
{
U32 i;
U32* pD0 = (U32 *)a0;
U32* pD1 = (U32 *)a1;
U32 ret = TRUE;
for (i=0; i<words; i++)
{
if (*pD0 != *pD1) {
ret = FALSE;
//Disp(" %08x=%08x : %08x=%08x\n", pD0, *pD0, pD1, *pD1); //gh0522.cha
}
//Disp(" %08x=%08x : %08x=%08x\n", pD0, *pD0, pD1, *pD1); //gh0522.cha
pD0++;
pD1++;
}
return ret;
}
U32 ReadSectors_Pio(U32 uLBA, U32 uSectorCount, U32 uDesAddress)
{
U32 resCount;
U32 remainCount;
U32 goingLBA;
U32 goingDstAddr;
U32 wCount;
U16* uAtaHostAddr;
U32 i;
remainCount = uSectorCount;
goingLBA = uLBA;
wCount = 0;
SetLittleEndian();
Init_LED();
while(remainCount != 0)
{
if(remainCount>256)
{
resCount = 256; //0 means 256
remainCount -= 256;
}
else
{
resCount = remainCount;
remainCount = 0;
}
goingLBA = uLBA + wCount*256;
goingDstAddr = uDesAddress + wCount*256*ATA_SECTORSIZE;
uAtaHostAddr = (U16*)goingDstAddr;
SetAtaDevice(goingLBA, resCount);
WriteOnTaskFileReg(DEV_COMMAND, READSECTOR);
while(resCount-- )
{
WaitForNoBusyStatus();
WaitForDeviceAccessReady();
for (i=0;i<ATA_SECTORSIZE/2;i++)
{
//GetDataFromDevice(*uAtaHostAddr);
*uAtaHostAddr=GetDataFromDevice();
uAtaHostAddr++;
}
}
WaitForNoBusyStatus();
wCount++;
}
return 1;
}
U32 WriteSectors_Pio(U32 nLBA,U32 nSectorCount,U32 nSrcAddress)
{
U32 resCount;
U32 remainCount;
U32 goingLBA;
U32 goingSrcAddr;
U32 wCount;
U16* uAtaHostAddr;
U32 i;
remainCount = nSectorCount;
goingLBA = nLBA;
wCount = 0;
SetLittleEndian();
while(remainCount != 0)
{
if(remainCount>256)
{
resCount = 256; //0 means 256
remainCount -= 256;
}
else
{
resCount = remainCount;
remainCount = 0;
}
goingLBA = nLBA + wCount*256;
goingSrcAddr = nSrcAddress + wCount*256*ATA_SECTORSIZE;
uAtaHostAddr = (U16*)goingSrcAddr;
SetAtaDevice(goingLBA, resCount);
WriteOnTaskFileReg(DEV_COMMAND, WRITESECTOR);
while(resCount-- )
{
WaitForNoBusyStatus();
for (i=0;i<ATA_SECTORSIZE/2;i++)
{
PutDataToDevice(*uAtaHostAddr);
uAtaHostAddr++;
}
}
WaitForNoBusyStatus();
wCount++;
}
return 1;
}
/*=========================================================================
* INT, PIODMA function
*=========================================================================
*/
U32 ReadSector_PioDma(U32 uLBA, U32 uDesAddress)
{
// SetLittleEndian();
/*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);
WaitForNoBusyStatus();
//SetConfigMode(PIODMA, false);
SetConfigMode(PIODMA, 0);
/*ATA Transfer Command */
SetTransferCommand(ATA_CMD_START);
//Delay(2); /// 0.2ms (1 transfer==0.6us, 256 transfer == 153.6us)
WaitForTransferDone();
SetTransferCommand(ATA_CMD_ABORT);
//SetConfigMode(PIO, false);
SetConfigMode(PIO, 1);
WaitForNoBusyStatus();
return 1;
}
U32 WriteSector_PioDma(U32 uLBA, U32 uSrcAddress)
{
// SetLittleEndian();
/*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);
WaitForNoBusyStatus();
//SetConfigMode(PIODMA, true);
SetConfigMode(PIODMA, 1);
/*ATA Transfer Command */
SetTransferCommand(ATA_CMD_START);
//Delay(2); /// 0.2ms (1 transfer==0.6us, 256 transfer == 153.6us)
WaitForTransferDone();
SetTransferCommand(ATA_CMD_ABORT);
//SetConfigMode(PIO, true);
SetConfigMode(PIO, 1);
WaitForNoBusyStatus();
//return true;
return 1;
}
U32 ReadSectors_Udma(U32 uLBA,U32 uSectorCount,U32 uDstAddress)
{
/*Track Buffer 1 Setting*/
Outp32(ATA_TBUF_START, uDstAddress);
Outp32(ATA_TBUF_SIZE, uSectorCount*ATA_SECTORSIZE);
Outp32(ATA_XFR_NUM, uSectorCount*ATA_SECTORSIZE);
SetAtaDevice(uLBA, uSectorCount);
WriteOnTaskFileReg(DEV_COMMAND,READDMA);
WaitForNoBusyStatus();
//SetConfigMode(UDMA, false);
SetConfigMode(UDMA, 0);
/*ATA Transfer Command */
SetTransferCommand(ATA_CMD_START);
WaitForTransferDone();
SetTransferCommand(ATA_CMD_ABORT);
// WaitForNoBusyStatus();
//SetConfigMode(PIO, false);
SetConfigMode(PIO, 0);
Dbg("*");
//return true;
return 1;
}
U32 WriteSectors_Udma(U32 uLBA,U32 uSectorCount,U32 uSrcAddress)
{
U32 resCount;
U32 remainCount;
U32 goingLBA;
U32 goingSrcAddr;
U32 wCount;
remainCount = uSectorCount;
goingLBA = uLBA;
wCount = 0;
SetLittleEndian();
while(remainCount != 0)
{
if(remainCount>256)
{
resCount = 256; //0 means 256
remainCount -= 256;
}
else
{
resCount = remainCount;
remainCount = 0;
}
goingLBA = uLBA + wCount*256;
goingSrcAddr = uSrcAddress + wCount*256*ATA_SECTORSIZE;
/*Source Buffer 1 Setting*/
Outp32(ATA_SBUF_START, uSrcAddress);
Outp32(ATA_SBUF_SIZE, uSectorCount*ATA_SECTORSIZE);
Outp32(ATA_XFR_NUM, uSectorCount*ATA_SECTORSIZE);
SetAtaDevice(uLBA, uSectorCount);
WriteOnTaskFileReg(DEV_COMMAND,WRITEDMA);
WaitForNoBusyStatus();
//SetConfigMode(UDMA, true);
SetConfigMode(UDMA, 1);
/*ATA Transfer Command */
SetTransferCommand(ATA_CMD_START);
WaitForTransferDone();
SetTransferCommand(ATA_CMD_ABORT);
// WaitForNoBusyStatus();
//SetConfigMode(PIO, true);
SetConfigMode(PIO, 1);
wCount++;
}
//return true;
return 1;
}
U32 ReadBlocks(U32 uStBlock, U32 uBlocks, U32 uBufAddr)
{
U32 i;
int mode = m_eMode;
U32 status;
// Assert(uStBlock+uBlocks <= m_oDevice[0].MaxSectors);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -