📄 doch_ata.c
字号:
dmaParams.bDestAddrPtr = (FLByte*)buf + dmaRemainderOffset;
dmaParams.wFrameSize = (FLWord)(dmaFrameSize * DOCH_SECTOR_SIZE);
dmaParams.wFramesInBlock = (FLWord)(dmaBlocks);
dmaParams.wFramesXferred = 0;
DOCH_DMA_CONFIG(&dmaParams);
if(dmaParams.fDmaStatus != 0)
{
DBG_PRINT_ERR(FLZONE_API, "io_input(): DOCH_DMA_CONFIG_TRANSACTION_DEVICE_TO_HOST Failed\r\n");
return DOCH_GeneralFailure;
}
#ifdef DOCH_USE_BURST_MODE_READ
if(pdev->bUseBurst)
{
/*Set DOCH BURST READ Control Register*/
DOCHWRITE_CTRL_REG (pdev->bRegBase,
HIB_BURST_READ_MODE_CTRL_REG,
(DOCH_BURST_ENABLE | DOCH_BURST_HOLD | DOCH_BURST_LENGTH | DOCH_BURST_LATENCY | DOCH_BURST_WAIT_STATE) );
/*Set up the DMA transfer - Device*/
wDmaRegValue &= ~(DOCH_DMA_REQ_EDGE);
}
#endif /*DOCH_USE_BURST_MODE_READ*/
/*Set up the DMA transfer - Device*/
DOCHWRITE_CTRL_REG (pdev->bRegBase, HIB_DMA_CTRL_REG, (wDmaRegValue | DOCH_DMA_REQ_ENABLE));
/*Write ATA registers*/
DOCHWRITE_ATA_REG (pdev->bRegBase, DOCH_SECTOR_CNT_REG, (FLByte)(dmaFrameSize*dmaBlocks));
DOCHWRITE_ATA_REG (pdev->bRegBase, DOCH_SECTOR_NO_REG, (FLByte)(dmaFirstSectorToPerform));
DOCHWRITE_ATA_REG (pdev->bRegBase, DOCH_CYLINDER_LOW_REG, (FLByte)(dmaFirstSectorToPerform>>8));
DOCHWRITE_ATA_REG (pdev->bRegBase, DOCH_CYLINDER_HIGH_REG, (FLByte)(dmaFirstSectorToPerform>>16));
DOCHWRITE_ATA_REG (pdev->bRegBase, DOCH_DRIVE_HEAD_REG, ((regs->bDriveHead & 0xF0) |
((FLByte)((dmaFirstSectorToPerform>>24) & 0x0F))));
DOCHWRITE_ATA_REG (pdev->bRegBase, DOCH_FEATURES_REG, regs->bFeaturesError);
/*Write ATA command*/
/*This will also start DMA transfer*/
DOCHWRITE_ATA_REG (pdev->bRegBase, DOCH_COMMAND_REG, regs->bCommandStatus);
#ifdef DOCH_USE_BURST_MODE_READ
if(pdev->bUseBurst)
{
/*Enter BURST Mode*/
DOCH_HOST_ENTER_READ_BURST_MODE
}
#endif /*DOCH_USE_BURST_MODE_READ*/
/*Wait for DMA transfer to complete*/
dmaParams.bOpType = DOCH_DMA_WAIT_FOR_READ_TRANSACTION_END;
DOCH_DMA_CONFIG(&dmaParams);
#ifdef DOCH_USE_BURST_MODE_READ
if(pdev->bUseBurst)
{
/*Exit BURST Mode*/
DOCH_HOST_EXIT_READ_BURST_MODE
/*Set DOCH BURST READ Control Register*/
DOCHWRITE_CTRL_REG (pdev->bRegBase, HIB_BURST_READ_MODE_CTRL_REG , DOCH_BURST_DISABLE);
}
#endif /*DOCH_USE_BURST_MODE_READ*/
/*Disable DMA in Device*/
DOCHWRITE_CTRL_REG (pdev->bRegBase, HIB_DMA_CTRL_REG, (wDmaRegValue &= ~DOCH_DMA_REQ_ENABLE));
/*Check status of DMA operation*/
if(dmaParams.fDmaStatus != 0)
{
DBG_PRINT_ERR(FLZONE_API, "io_input(): DOCH_DMA_WAIT_FOR_READ_TRANSACTION_END Failed\r\n");
DBG_PRINT_ERR(FLZONE_ATA, "ready(): Resetting device... ");
rc = doch_reset (pdev->wSocketNo, devNum);
if(rc == DOCH_OK)
DBG_PRINT_ERR(FLZONE_ATA, "Passed! \r\n");
else
{
DBG_PRINT_ERR(FLZONE_ATA, "Failed! \r\n");
return rc;
}
return DOCH_GeneralFailure;
}
}
/*If DRQ is larger the 1 and some sectors are left to be transfered,
perform another DMA transaction with altered frame/block sizes*/
if(dmaRemainderSectors > 0)
{
dmaRemainderOffset = (dmaBlocks * dmaFrameSize * DOCH_SECTOR_SIZE);
dmaFirstSectorToPerform = (dmaFirstReqSector + (dmaBlocks * dmaFrameSize));
dmaBlocks = 1;
dmaFrameSize = dmaRemainderSectors;
dmaRemainderSectors = 0;
goto dochIoInputDmaSequence;
}
}
else
#endif /*DOCH_DMA_CONFIG*/
/*PIO transfer was requested*/
{
/*Write ATA command register*/
DOCHWRITE_ATA_REG (pdev->bRegBase, DOCH_COMMAND_REG, regs->bCommandStatus);
/* Check DRQ ready and not BSY before data xfer */
(rc = ready(pdev, devNum, DOCH_STATUS_REG, (DOCH_READY | DOCH_DRQ | DOCH_BUSY | DOCH_ERROR),
DOCH_READY | DOCH_DRQ, DOCH_LONG_WAIT));
if(rc != DOCH_OK)
{
DBG_PRINT_ERR(FLZONE_ATA, "\r\nio_input(): ATA not Ready (before data XFER) \r\n");
DBG_PRINT_ERR_PRM(FLZONE_ATA, (FLTXT("rc = 0x%x \r\n"),rc));
return rc;
}
/*Perform per-sector
1. Wait until device is ready to receive data
2. Xfer 1 sector*/
if((pdev->device[devNum].dataTransferMode == DOCH_DATA_MODE_SINGLE) || /*Single Sector was requested*/
(!(regs->bCommandStatus == DOCH_VSCMD_READ_PARTITION)) ) /*Command is OTHER than Read Partition*/
{
for(secPerformed=1; secPerformed<=sectors_to_read; secPerformed++)
{
/*Perform data xfer*/
if( (DOCHBLK_READ(pdev->bRegBase,
((FLByte*)buf + offset),
1)) != 0)
{
return DOCH_ReadFault;
}
/* Check DRQ ready and not BSY before next data xfer */
/* (don`t perform after LAST sector was transfered) */
if(secPerformed != sectors_to_read)
{
(rc = ready(pdev, devNum, DOCH_STATUS_REG, (DOCH_READY | DOCH_DRQ | DOCH_BUSY | DOCH_ERROR),
DOCH_READY | DOCH_DRQ, DOCH_LONG_WAIT));
if(rc != DOCH_OK)
{
DBG_PRINT_ERR(FLZONE_ATA, "\r\nio_input(): ATA not Ready (before data XFER) \r\n");
DBG_PRINT_ERR_PRM(FLZONE_ATA, (FLTXT("rc = 0x%x \r\n"),rc));
return rc;
}
}
offset += DOCH_SECTOR_SIZE;
}
}
else if(pdev->device[devNum].dataTransferMode == DOCH_DATA_MODE_MULT)
{
multCount = (FLByte)pdev->device[devNum].dwMulti_Current;
for(secPerformed=0; secPerformed<sectors_to_read;)
{
/*Determine how many sectors to read this cycle*/
if((secPerformed + multCount) > sectors_to_read)
multSecToRead = (sectors_to_read - secPerformed);
else
multSecToRead = multCount;
/*Perform data xfer*/
if( (DOCHBLK_READ(pdev->bRegBase,
(FLByte*)buf + offset,
(multSecToRead))) != 0)
{
return DOCH_ReadFault;
}
/* Check DRQ ready and not BSY before next data xfer */
/* (don`t perform after LAST sector was transfered) */
if((secPerformed + multSecToRead) != sectors_to_read)
{
(rc = ready(pdev, devNum, DOCH_STATUS_REG, (DOCH_READY | DOCH_DRQ | DOCH_BUSY | DOCH_ERROR),
DOCH_READY | DOCH_DRQ, DOCH_LONG_WAIT));
if(rc != DOCH_OK)
{
DBG_PRINT_ERR(FLZONE_ATA, "\r\nio_input(): ATA not Ready (before data XFER) \r\n");
DBG_PRINT_ERR_PRM(FLZONE_ATA, (FLTXT("rc = 0x%x \r\n"),rc));
return rc;
}
}
/*Advance number of written sectors and update pointer to buffer*/
secPerformed += multSecToRead;
offset += (multSecToRead * DOCH_SECTOR_SIZE);
}
}
else
{
DBG_PRINT_ERR(FLZONE_ATA, "io_input(): Transfer Mode ");
DBG_PRINT_ERR_PRM(FLZONE_ATA, (FLTXT("0x%x "), pdev->device[devNum].dataTransferMode));
DBG_PRINT_ERR(FLZONE_ATA, "not supported\r\n");
return DOCH_FeatureNotSupported;
} /* End of if/else on pdev->device[devNum].dataTransferMode */
} /* End of else on if(pdev->bUseDMA) */
/* wait until device is ready */
rc = ready(pdev, devNum, DOCH_STATUS_REG, (DOCH_READY | DOCH_BUSY),
DOCH_READY, DOCH_SHORT_WAIT);
if (rc != DOCH_OK)
{
DBG_PRINT_ERR(FLZONE_ATA, "\r\nio_input(): ATA not Ready\r\n");
DBG_PRINT_ERR_PRM(FLZONE_ATA, (FLTXT("rc = 0x%x \r\n"),rc));
return rc;
}
/* check operation's status; this also clears IRQ */
status = DOCHREAD_ATA_REG(pdev->bRegBase, DOCH_STATUS_REG);
if((status & (DOCH_BUSY | DOCH_READY | DOCH_ERROR)) != DOCH_READY)
{
if((status & DOCH_BUSY) == DOCH_BUSY)
return DOCH_ATABusyNotCleared;
else if((status & DOCH_READY) != DOCH_READY)
return DOCH_ATANotReady;
else if((status & DOCH_ERROR) == DOCH_ERROR)
return DOCH_ATAErrorDetected;
}
return rc;
}
/******************************************************************************
* *
* i o _ o u t p u t *
* *
* Write sectors to DOCH device. *
* *
* Parameters : *
* pdev : device to act on *
* regs : DOCH_Registers *
* buf : user buffer to write from *
* secNum : # of sectors to write *
* *
* Returns : *
* DOCH_OK in success, otherwise respective error code. *
* *
******************************************************************************/
DOCH_Error io_output ( DOCH_Socket * pdev,
FLSNative devNum,
DOCH_Registers * regs,
void * buf,
FLNative secNum)
{
FLNative sectors_to_write;
FLNative secPerformed;
FLNative offset = 0;
DOCH_Error rc;
FLSNative status;
FLByte multCount = 0;
/*Calculate how many sectors are to be written*/
/*Note: "0" - 256 Sectors to write*/
sectors_to_write = (secNum ? secNum : 256);
/* First we write the device head register to ensure we are communicating
with the right device...*/
DOCHWRITE_ATA_REG (pdev->bRegBase, DOCH_DRIVE_HEAD_REG, regs->bDriveHead);
/*Wait for BUSY bit to clear*/
status = DOCHREAD_ATA_REG(pdev->bRegBase, DOCH_STATUS_REG);
if((status & DOCH_BUSY) == DOCH_BUSY)
{
if ((rc = ready(pdev, devNum, DOCH_ALT_STATUS_REG, DOCH_BUSY, 0, DOCH_SHORT_WAIT)) != DOCH_OK)
{
DBG_PRINT_ERR(FLZONE_ATA, "\r\nio_output(): ATA not Ready\r\n");
DBG_PRINT_ERR_PRM(FLZONE_ATA, (FLTXT("rc = 0x%x \r\n"),rc));
return rc;
}
}
/*Write ATA registers, without ATA command register*/
/*Note: if DMA was requested, registers will be written inside DMA context*/
if(!pdev->bUseDMA)
{
DOCHWRITE_ATA_REG (pdev->bRegBase, DOCH_SECTOR_CNT_REG, regs->bSectorCount);
DOCHWRITE_ATA_REG (pdev->bRegBase, DOCH_SECTOR_NO_REG, regs->bSectorNumber);
DOCHWRITE_ATA_REG (pdev->bRegBase, DOCH_CYLINDER_LOW_REG, regs->bCylLow);
DOCHWRITE_ATA_REG (pdev->bRegBase, DOCH_CYLINDER_HIGH_REG, regs->bCylHigh);
DOCHWRITE_ATA_REG (pdev->bRegBase, DOCH_FEATURES_REG, regs->bFeaturesError);
}
#ifdef DOCH_USE_BURST_MODE_WRITE
/*BURST transfer was requested*/
if(pdev->bUseBurst)
{
/*Initiate ATA Command*/
DOCHWRITE_ATA_REG (pdev->bRegBase, DOCH_COMMAND_REG, regs->bCommandStatus);
/* Check DRQ ready and not BSY before data xfer */
(rc = ready(pdev, devNum, DOCH_STATUS_REG, (DOCH_READY | DOCH_DRQ | DOCH_BUSY | DOCH_ERROR),
DOCH_READY | DOCH_DRQ, DOCH_LONG_WAIT));
if(rc != DOCH_OK)
{
DBG_PRINT_ERR(FLZONE_ATA, "\r\nio_output(): ATA not Ready (before BURST) \r\n");
DBG_PRINT_ERR_PRM(FLZONE_ATA, (FLTXT("rc = 0x%x \r\n"),rc));
return rc;
}
/*Set DOCH BURST WRITE Control Register*/
DOCHWRITE_CTRL_REG (pdev->bRegBase,
HIB_BURST_WRITE_MODE_CTRL_REG,
(DOCH_BURST_ENABLE | DOCH_BURST_HOLD | DOCH_BURST_LENGTH | DOCH_BURST_LATENCY | DOCH_BURST_WAIT_STATE)
);
/*Enter BURST Mode*/
DOCH_HOST_ENTER_WRITE_BURST_MODE
/*Perform Write using burst*/
DOCHWRITE_BURST((FLByte*)pdev->bRegBase,
DOCH_DATA_PORT_AREA_OFFSET,
buf,
sectors_to_write);
/*Exit BURST Mode*/
DOCH_HOST_EXIT_WRITE_BURST_MODE
/*Set DOCH BURST WRITE Control Register*/
DOCHWRITE_CTRL_REG (pdev->bRegBase, HIB_BURST_WRITE_MODE_CTRL_REG, DOCH_BURST_DISABLE);
/* Wait until device is ready. This SHOULD NOT involve yielding the
* CPU and waiting for device interrupt, so we use DOCH_SHORT_WAIT.
*/
rc = ready(pdev, devNum, DOCH_ALT_STATUS_REG, (DOCH_READY | DOCH_BUSY | DOCH_DRQ),
DOCH_READY, DOCH_SHORT_WAIT);
}
else
#endif /*DOCH_USE_BURST_MODE_WRITE*/
#ifdef DOCH_DMA_CONFIG
/*DMA transfer was requested*/
if(pdev->bUseDMA)
{
DMA_Params_S dmaParams;
FLDword dmaFirstReqSector,
dmaFirstSectorToPerform,
dmaRemainderSectors,
dmaRemainderOffset,
dmaBlocks,
dmaFrameSize;
FLWord wDmaRegValue = DOCHREAD_CTRL_REG (pdev->bRegBase, HIB_DMA_CTRL_REG);
/*Initial Value*/
dmaRemainderOffset = 0;
/*Save the first sector position*/
dmaFirstReqSector = (regs->bSectorNumber +
(regs->bCylLow<<8) +
(regs->bCylHigh<<16)+
((regs->bDriveHead & 0xF)<<24));
dmaFirstSectorToPerform = dmaFirstReqSector;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -