📄 nwatadrv.c
字号:
STATUS ataRW(int ctrl,int drive,int cylinder,int head,int sector,void *buffer,int nSecs,int direction)
{
ATA_CTRL *pCtrl = &ataCtrl[ctrl];
ATA_DRIVE *pDrive = &pCtrl->drive[drive];
ATA_TYPE *pType = &ataTypes[ctrl][drive];
int retryCount = 0;
int block = 1;
int nSectors = nSecs;
int nWords;
int semStatus;
short *pBuf;
//
// If dma enabled then override this function
//
if (pDrive->okDma)
return ataDmaRW(ctrl,drive, cylinder, head, sector,buffer,nSecs,direction);
#ifdef ATA_DEBUG
printErr ("ataRW: ctrl=%d drive=%d c=%d h=%d s=%d buf=0x%x n=%d dir=%d\n",
ctrl, drive, cylinder, head, sector,
(int)buffer, nSecs, direction);
#endif /* ATA_DEBUG */
retryRW:
ataWait(ctrl, ATA_STAT_READY);
ATA_IO_BYTE_WRITE (pCtrl->sdh,
(drive << 4));
ataWait (ctrl, ATA_STAT_READY);
pBuf = (UINT16 *)buffer;
/*start modify by wb 2005-6-20 16:08*/
if (pDrive->lba48bit ==0)
{
ATA_IO_BYTE_WRITE (pCtrl->seccnt, nSecs);
ATA_IO_BYTE_WRITE (pCtrl->sector, sector);
ATA_IO_BYTE_WRITE (pCtrl->cylLo, cylinder);
ATA_IO_BYTE_WRITE (pCtrl->cylHi, cylinder>>8);
if (pDrive->okLba)
{
ATA_IO_BYTE_WRITE (pCtrl->sdh,
ATA_SDH_LBA | (drive << 4) | (head & 0xf));
}
else
{
ATA_IO_BYTE_WRITE (pCtrl->sdh,
ATA_SDH_IBM | (drive << 4) | (head & 0xf));
}
}
else
{
ATA_IO_BYTE_WRITE(pCtrl->seccnt, nSecs >> 8);
ATA_IO_BYTE_WRITE(pCtrl->sector, head);
ATA_IO_BYTE_WRITE(pCtrl->cylLo, 0x00);
ATA_IO_BYTE_WRITE(pCtrl->cylHi, 0x00);
ATA_IO_BYTE_WRITE(pCtrl->seccnt, nSecs & 0xFF);
ATA_IO_BYTE_WRITE(pCtrl->sector, sector);
ATA_IO_BYTE_WRITE(pCtrl->cylLo, (cylinder & 0xff));
ATA_IO_BYTE_WRITE(pCtrl->cylHi, (cylinder & 0xff00) >> 8);
ATA_IO_BYTE_WRITE(pCtrl->sdh,ATA_SDH_LBA | (drive << 4));
}
/*end modify by wb 2005-6-20 16:08*/
if (pDrive->rwPio == ATA_PIO_MULTI)
block = pDrive->multiSecs;
nWords = (pType->bytes * block) >> 1;
if (direction == O_WRONLY) /*1-write 0-read*/
{
if (pDrive->rwPio == ATA_PIO_MULTI)
{
if (pDrive->lba48bit == 0)
{
ATA_IO_BYTE_WRITE (pCtrl->command, ATA_CMD_WRITE_MULTI);
}
else
{
ATA_IO_BYTE_WRITE (pCtrl->command, ATA_CMD_WRITE_MULTI_EXT);
}
}
else
{
ATA_IO_BYTE_WRITE (pCtrl->command, ATA_CMD_WRITE);
}
taskDelay(0);
ataWait (ctrl, ATA_STAT_DRQ);
while (nSectors > 0)
{
if ((pDrive->rwPio == ATA_PIO_MULTI) && (nSectors < block))
{
block = nSectors;
nWords = (pType->bytes * block) >> 1;
}
if (pDrive->rwBits == ATA_BITS_16)
ATA_IO_NWORD_WRITE (pCtrl->data, pBuf, nWords);
else
ATA_IO_NLONG_WRITE (pCtrl->data, (ULONG *)pBuf, nWords >> 1);
semStatus = semTake (&pCtrl->syncSem,
sysClkRateGet() * pCtrl->semTimeout);
//pCtrl->intStatus = ATA_IO_BYTE_READ (pCtrl->status);
if ((pCtrl->intStatus & ATA_STAT_ERR) || (semStatus == ERROR)) {
goto errorRW;
}
pBuf += nWords;
nSectors -= block;
if (nSectors > 0) {
ataWait (ctrl, ATA_STAT_DRQ);
}
// ATA_IO_BYTE_READ (pCtrl->status);
}
}
else
{
if (pDrive->rwPio == ATA_PIO_MULTI)
{
if (pDrive->lba48bit == 1)
{
ATA_IO_BYTE_WRITE (pCtrl->command, ATA_CMD_READ_MULTI);
}
else
{
ATA_IO_BYTE_WRITE (pCtrl->command, ATA_CMD_READ_MULTI_EXT);
}
}
else
ATA_IO_BYTE_WRITE (pCtrl->command, ATA_CMD_READ);
while (nSectors > 0)
{
if ((pDrive->rwPio == ATA_PIO_MULTI) && (nSectors < block))
{
block = nSectors;
nWords = (pType->bytes * block) >> 1;
}
semStatus = semTake (&pCtrl->syncSem,
sysClkRateGet() * pCtrl->semTimeout);
//pCtrl->intStatus = ATA_IO_BYTE_READ (pCtrl->status);
if ((pCtrl->intStatus & ATA_STAT_ERR) || (semStatus == ERROR)) {
goto errorRW;
}
ataWait (ctrl, ATA_STAT_DRQ);
// ATA_IO_BYTE_READ (pCtrl->status);
if (pDrive->rwBits == ATA_BITS_16){
ATA_IO_NWORD_READ (pCtrl->data, pBuf, nWords);
}
else
{
ATA_IO_NLONG_READ (pCtrl->data, (ULONG *)pBuf, nWords >> 1);
}
pBuf += nWords;
nSectors -= block;
}
}
#ifdef ATA_DEBUG
printErr ("ataRW: end\n");
#endif /* ATA_DEBUG */
return (OK);
errorRW:
#ifdef ATA_DEBUG
{
int error = ATA_IO_BYTE_READ (pCtrl->error);
int status = ATA_IO_BYTE_READ (pCtrl->aStatus);
printErr ("ataRW err: stat=0x%x 0x%x semStatus=%d error=0x%x\n",
pCtrl->intStatus, status, semStatus, error);
}
#endif /* ATA_DEBUG */
if (++retryCount < ataRetry)
goto retryRW;
return (ERROR);
}
/*******************************************************************************
*
* ataDmaRW - read/write a number of sectors on the current track
*
* Read/write a number of sectors on the current track
*
* RETURNS: OK, ERROR if the command didn't succeed.
*/
//efine ATA_PERFORMANCE
STATUS ataDmaRW(int ctrl,int drive,int cylinder,int head,int sector,void *buffer,int nSecs,int direction)
{
ATA_CTRL *pCtrl = &ataCtrl[ctrl];
ATA_DRIVE *pDrive = &pCtrl->drive[drive];
ATA_TYPE *pType = &ataTypes[ctrl][drive];
int retryCount = 0;
int semStatus;
int i;
unsigned char tmp;
STATUS status;
#ifdef ATA_PERFORMANCE
int startTick,endTick;
#endif
#ifdef ATA_DEBUG
printErr ("ataDmaRW: ctrl=%d drive=%d c=%d h=%d s=%d buf=0x%x n=%d dir=%d\n",
ctrl, drive, cylinder, head, sector, (int)buffer, nSecs, direction);
#endif /* ATA_DEBUG */
//cacheLock(DATA_CACHE,buffer,sector*512);
/*cacheDisable(DATA_CACHE);quy del 2006-3-24 8:30*/
retryDmaRW:
status = ataDmaSetupXfer(ctrl,direction,buffer,nSecs*pType->bytes);
if (status != OK)
{
/*cacheEnable(DATA_CACHE);quy del 2006-3-24 8:29*/
return status;
}
if(pDrive->status == ATA_STANDBY_MODE)
{
ataWait(ctrl, ATA_STAT_BUSY);
ATA_IO_BYTE_WRITE(pCtrl->sdh, ATA_SDH_LBA | (drive << 4));
ATA_IO_BYTE_WRITE(pCtrl->command, IDE_CMD_IDLE);
pDrive->status = ATA_ACTIVE_MODE;
taskDelay(sysClkRateGet()*8);
}
ataWait(ctrl, ATA_STAT_READY);
ATA_IO_BYTE_WRITE (pCtrl->sdh,(drive << 4));
/*start modify by wb 2005-6-20 16:08*/
if (pDrive->lba48bit == 0)
{
ATA_IO_BYTE_WRITE (pCtrl->seccnt, nSecs);
ATA_IO_BYTE_WRITE (pCtrl->sector, sector);
ATA_IO_BYTE_WRITE (pCtrl->cylLo, cylinder);
ATA_IO_BYTE_WRITE (pCtrl->cylHi, cylinder>>8);
if (pDrive->okLba)
{
ATA_IO_BYTE_WRITE (pCtrl->sdh,ATA_SDH_LBA | (drive << 4) | (head & 0xf));
}
else
{
ATA_IO_BYTE_WRITE (pCtrl->sdh,ATA_SDH_IBM | (drive << 4) | (head & 0xf));
}
}
else
{
//ATA_IO_BYTE_WRITE(pCtrl->feature, 0);
ATA_IO_BYTE_WRITE(pCtrl->seccnt, nSecs >> 8);
ATA_IO_BYTE_WRITE(pCtrl->sector, head);
ATA_IO_BYTE_WRITE(pCtrl->cylLo, 0x00);
ATA_IO_BYTE_WRITE(pCtrl->cylHi, 0x00);
ATA_IO_BYTE_WRITE(pCtrl->seccnt, nSecs & 0xFF);
ATA_IO_BYTE_WRITE(pCtrl->sector, sector);
ATA_IO_BYTE_WRITE(pCtrl->cylLo, (cylinder & 0xff));
ATA_IO_BYTE_WRITE(pCtrl->cylHi, (cylinder & 0xff00) >> 8);
ATA_IO_BYTE_WRITE(pCtrl->sdh,ATA_SDH_LBA | (drive << 4));
}
/*end modify by wb 2005-6-20 16:08*/
ataWait (ctrl, ATA_STAT_READY);
/*写数据*/
if (direction == O_WRONLY)
{
#ifdef ATA_PERFORMANCE
startTick = hmpv_read_fcnt();
#endif
if (pDrive->lba48bit == 0)
{
ATA_IO_BYTE_WRITE (pCtrl->command, ATA_CMD_DMA_WRITE);
}
else
{
ATA_IO_BYTE_WRITE (pCtrl->command, ATA_CMD_DMA_WRITE_EXT);
}
/*cacheFlush(DATA_CACHE,(void *)buffer, nSecs*512);quy del 2006-3-24 8:28*/
ataWait (ctrl, ATA_STAT_DRQ);
enableChan(ctrl);
semStatus = semTake (&pCtrl->syncSem, sysClkRateGet() * pCtrl->semTimeout);
i=0;
while(i<5000)
{
if(ATA_IO_BYTE_READ( busMasterRegs[ctrl] + BM_STATUS_REG) & 0x4)
break;
}
disableChan(ctrl);
clearChan(ctrl);
pCtrl->intStatus = ATA_IO_BYTE_READ (pCtrl->status);
if ((pCtrl->intStatus & ATA_STAT_ERR) || (semStatus == ERROR))
goto errorDmaRW;
#ifdef ATA_PERFORMANCE
endTick = hmpv_read_fcnt();
#endif
}
else
{
#ifdef ATA_PERFORMANCE
startTick = hmpv_read_fcnt();
#endif
if (pDrive->lba48bit == 0)
{
ATA_IO_BYTE_WRITE (pCtrl->command, ATA_CMD_DMA_READ);
}
else
{
ATA_IO_BYTE_WRITE (pCtrl->command, ATA_CMD_DMA_READ_EXT);
}
ataWait(ctrl,ATA_STAT_DRQ);
/*cacheFlush(DATA_CACHE,(void *)buffer, nSecs*512);quy del 2006-3-24 8:28*/
enableChan(ctrl);
semStatus = semTake (&pCtrl->syncSem,sysClkRateGet() * pCtrl->semTimeout);
i=0;
while(i<100000)
{
if(ATA_IO_BYTE_READ( busMasterRegs[ctrl] + BM_STATUS_REG) & 0x4)
break;
}
disableChan(ctrl);
clearChan(ctrl);
pCtrl->intStatus = ATA_IO_BYTE_READ (pCtrl->status);
if ((pCtrl->intStatus & ATA_STAT_ERR) || (semStatus == ERROR))
goto errorDmaRW;
/*cacheFlush(DATA_CACHE,(void *)buffer, nSecs*512);quy del 2006-3-24 8:28*/
#ifdef ATA_PERFORMANCE
endTick = hmpv_read_fcnt();
#endif
}
#ifdef ATA_DEBUG
printf("ataDmaRW: end\n");
#endif /* ATA_DEBUG */
#ifdef ATA_PERFORMANCE
{
float count,MBps;
if (endTick > startTick)
count = endTick - startTick;
else
count = 0xFFFFFFF - startTick + endTick;
MBps = nSecs*pType->bytes/(count/CPU_MHZ);
if (direction == O_WRONLY )
printf("Wrote %d bytes. MBps %f\n",nSecs*pType->bytes,MBps);
else
printf("Read %d bytes. MBps %f\n",nSecs*pType->bytes,MBps);
}
#endif
/*cacheEnable(DATA_CACHE);*/
//cacheUnlock(DATA_CACHE,buffer,sector*512);
return (OK);
errorDmaRW:
#ifdef ATA_DEBUG
{
int error = ATA_IO_BYTE_READ (pCtrl->error);
int status = ATA_IO_BYTE_READ (pCtrl->aStatus);
printErr ("ataDmaRW err: stat=0x%x 0x%x semStatus=%d error=0x%x errorno 0x%x\n",
pCtrl->intStatus, status, semStatus, error,errno);
printErr("sysClkRateGet=%d timeout=%d\n",sysClkRateGet(),sysClkRateGet() * pCtrl->semTimeout);
}
#endif /* ATA_DEBUG */
if (++retryCount < ataRetry)
goto retryDmaRW;
/*cacheEnable(DATA_CACHE);*/
//cacheUnlock(DATA_CACHE,buffer,sector*512);
return (ERROR);
}
//***********************************************************
//
// ataDmaSetupXfer() -- set up 1, 2 or 3 PRD
//
//***********************************************************
STATUS ataDmaSetupXfer(int ctrl, int dir, char *addr, int count)
{
PPRD_ENTRY prdEntry;
int numBytes;
unsigned int tempData1,tempData2;
/*added by youyan*/
char *pAddr;
unsigned int dwBufLen;
// disable/stop the dma channel, clear interrupt and error bits
disableChan(ctrl);
clearChan(ctrl);
//logMsg("the dma data size = 0x%x \n",count,2,3,4,5,6);
if (count/MAX_TRANSFER /*+ 2*/ > MAX_PRD_ENTRIES) {
printf("ERROR: too many dma bytes 0x%x, expand table!!!!!\n",count);
return ERROR;
}
prdEntry = &prdTable[ctrl][0];
//
// build prd table
// each entry cannot cross a 64Kbyte bountry so...
//
#if 1
pAddr = addr;
dwBufLen = count;
while (dwBufLen)
{
prdEntry->address = (char *)((unsigned int)(pAddr) + PCI2DRAM_BASE_ADRS);
if (dwBufLen > MAX_TRANSFER)
{
prdEntry->bits.count = 0;//MAX_TRANSFER;
prdEntry->bits.EOT = 0;
dwBufLen -= MAX_TRANSFER;
pAddr += MAX_TRANSFER;
}
else
{
prdEntry->bits.count = dwBufLen;
prdEntry->bits.EOT = 1;
dwBufLen = 0;
}
prdEntry++;
}
#endif
#if 0
while (TRUE) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -