📄 atadrv.c
字号:
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);
int ideStatus = sysInByte( busMasterRegs[ctrl] + BM_STATUS_REG);
printf ("ataRW err: stat=0x%x 0x%x semStatus=%d error=0x%x errorno 0x%x,ideStatus 0x%x\n",
pCtrl->intStatus, status, semStatus, error,errno,ideStatus);
printf("sysClkRateGet=%d timeout=%d\n",sysClkRateGet(),sysClkRateGet() * pCtrl->semTimeout);
}
#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
LOCAL 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;
// struct timespec wait200ns;
int i;
unsigned char tmp;
STATUS status;
#ifdef ATA_PERFORMANCE
int startTick,endTick;
#endif
// wait200ns.tv_sec = 0;
// wait200ns.tv_nsec = 200;
#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 */
retryDmaRW:
status = ataDmaSetupXfer(ctrl,direction,buffer,nSecs*pType->bytes);
if (status != OK)
return status;
ataWait(ctrl, ATA_STAT_READY);
ATA_IO_BYTE_WRITE (pCtrl->sdh,
(drive << 4));
// ataWait (ctrl, ATA_STAT_READY);
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));
if (direction == O_WRONLY)
{
#ifdef ATA_PERFORMANCE
startTick = hmpv_read_fcnt();
#endif
ATA_IO_BYTE_WRITE (pCtrl->command, ATA_CMD_DMA_WRITE);
// ataWait (ctrl, ATA_STAT_DRQ);
enableChan(ctrl);
semStatus = semTake (&pCtrl->syncSem,
sysClkRateGet() * pCtrl->semTimeout);
if ((pCtrl->intStatus & ATA_STAT_ERR) || (semStatus == ERROR))
goto errorDmaRW;
for (i=0;i<1000;i++)
{
// nanosleep(&wait200ns,NULL);
tmp = sysInByte( busMasterRegs[ctrl] + BM_STATUS_REG);
if (tmp & 0x4) {
break;
}
taskDelay(0);
}
#ifdef ATA_PERFORMANCE
endTick = hmpv_read_fcnt();
#endif
// disableChan();
// clearChan();
// ATA_IO_BYTE_READ (pCtrl->status);
}
else
{
#ifdef ATA_PERFORMANCE
startTick = hmpv_read_fcnt();
#endif
ATA_IO_BYTE_WRITE (pCtrl->command, ATA_CMD_DMA_READ);
// ataWait(ctrl,ATA_STAT_DRQ);
enableChan(ctrl);
semStatus = semTake (&pCtrl->syncSem,
sysClkRateGet() * pCtrl->semTimeout);
if ((pCtrl->intStatus & ATA_STAT_ERR) || (semStatus == ERROR)) {
disableChan(ctrl);
clearChan(ctrl);
tmp = ATA_IO_BYTE_READ (pCtrl->status);
goto errorDmaRW;
}
//
// Wait for DMA Master to finsh
//
for (i=0;i<1000;i++)
{
// nanosleep(&wait200ns,NULL);
tmp = sysInByte( busMasterRegs[ctrl] + BM_STATUS_REG);
if (tmp & 0x4) {
break;
}
taskDelay(0);
}
#ifdef ATA_PERFORMANCE
endTick = hmpv_read_fcnt();
#endif
// disableChan();
// clearChan();
// tmp = ATA_IO_BYTE_READ (pCtrl->status);
}
#ifdef ATA_DEBUG
printErr ("ataDmaRW: end\n");
if (direction == O_WRONLY )
printf("Wrote %d bytes\n",nSecs*pType->bytes);
else
printf("Read %d bytes.\n",nSecs*pType->bytes);
#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
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;
return (ERROR);
}
static PRD_ENTRY prdTable[2][MAX_PRD_ENTRIES];
//***********************************************************
//
// ataDmaSetupXfer() -- set up 1, 2 or 3 PRD
//
//***********************************************************
static STATUS ataDmaSetupXfer(int ctrl, int dir, char *addr, int count)
{
PPRD_ENTRY prdEntry;
int numBytes;
// disable/stop the dma channel, clear interrupt and error bits
disableChan(ctrl);
clearChan(ctrl);
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 0
while (TRUE) {
prdEntry->address = addr;
if (count <= MAX_TRANSFER) {
prdEntry->bits.count = count;
prdEntry->bits.EOT = 1;
break;
} else {
prdEntry->bits.count = MAX_TRANSFER;
prdEntry->bits.EOT = 0;
}
count -= MAX_TRANSFER;
addr += MAX_TRANSFER;
prdEntry++;
}
#endif
while (TRUE) {
prdEntry->address = addr;
numBytes = 0x10000 - ((int)addr & 0xFFFF);
if (numBytes > count) {
prdEntry->bits.count = count;
prdEntry->bits.EOT = 1;
break;
} else {
prdEntry->bits.count = numBytes;
prdEntry->bits.EOT = 0;
}
count -= numBytes;
addr += numBytes;
prdEntry++;
}
// set the prd list address
sysOutLong(busMasterRegs[ctrl] + BM_PRD_ADDR,(ULONG)&prdTable[ctrl][0]);
// set the read/write control:
if ( dir == O_WRONLY)
rwControl[ctrl] = BM_CR_MASK_WRITE; // ATA Write DMA
else
rwControl[ctrl] = BM_CR_MASK_READ; // ATA Read DMA
return OK;
}
//***********************************************************
//
// ataDmaConfig() - configure/setup for Read/Write DMA
//
// The caller must call this function before attempting
// to use any ATA or ATAPI commands in PCI DMA mode.
//
//***********************************************************
int ataDmaConfig(int ctrl,UINT32 regAddr )
{
// save the address of the bus master (SFF-8038) regs
busMasterRegs[ctrl] = regAddr;
sysOutByte(busMasterRegs[ctrl]+BM_STATUS_REG,BM_SR_MASK_DRV0 | BM_SR_MASK_INT);
// the bus master must be setup now
// read the BM status reg and save the upper 3 bits.
statReg[ctrl] = sysInByte( busMasterRegs[ctrl] + BM_STATUS_REG );
statReg[ctrl] = statReg[ctrl] & 0xe0;
return 0;
}
static void ataPrintSpeed(char speed)
{
printf("Configured drive for \n");
switch(speed) {
case ATA_DMA_ULTRA_W_0:
printf("ultra DMA mode 0\n");
break;
case ATA_DMA_ULTRA_W_1:
printf("ultra DMA mode 1\n");
break;
case ATA_DMA_ULTRA_W_2:
printf("ultra DMA mode 2\n");
break;
case ATA_DMA_ULTRA_W_3:
printf("ultra DMA mode 3\n");
break;
case ATA_DMA_ULTRA_W_4:
printf("ultra DMA mode 4\n");
break;
case ATA_DMA_MULTI_W_0:
printf("multiword DMA mode 0\n");
break;
case ATA_DMA_MULTI_W_1:
printf("multiword DMA mode 1\n");
break;
case ATA_DMA_MULTI_W_2:
printf("multiword DMA mode 2\n");
break;
case ATA_DMA_SINGLE_W_0:
printf("singleword DMA mode 0\n");
break;
case ATA_DMA_SINGLE_W_1:
printf("singleword DMA mode 1\n");
break;
case ATA_DMA_SINGLE_W_2:
printf("singleword DMA mode 2\n");
break;
default:
printf("unknown speed\n");
}
}
extern STATUS usrFdiskPartRead();
STATUS
AtaMount(
int ctrl, /* 0: primary address, 1: secondary address */
int drive, /* drive number of hard disk (0 or 1) */
char * filename /* mount point */
)
{
BLK_DEV *pBlkDev;
CBIO_DEV_ID *pCbio, pCbioParts;
char Devs[6];
int i;
/* create the device */
if( !(pBlkDev=ataDevCreate( ctrl, drive, 0, 0)) )
{
printf( "Error creating device\n" );
return ERROR;
}
/* creat cache for accessing the device */
if ( (pCbio = dcacheDevCreate(pBlkDev, NULL, DISK_CACHE_SIZE, "master")) == NULL)
{
printf( "Error creating disk cache\n" );
return ERROR;
}
/* create partition manager */
if ( (pCbioParts = dpartDevCreate(pCbio, NUM_DISK_PARTITIONS, usrFdiskPartRead)) == NULL)
{
printf( "Error creating disk cache\n" );
return ERROR;
}
for (i=0; i<NUM_DISK_PARTITIONS; i++)
{
//sprintf(&Devs[0], "%s%d:",filename, i);
if (ctrl==0) sprintf(&Devs[0], "dev%d:", i);
else sprintf(&Devs[0],"cf%d:",(2+i));
printf("mounting %s\n",Devs);
dosFsDevCreate(Devs, dpartPartGet(pCbioParts, i), NUM_DOSFS_FILES, NONE);
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -