📄 doch_ata.c
字号:
if(pdev->device[devNum].dataTransferMode == DOCH_DATA_MODE_SINGLE)
{
dmaRemainderSectors = 0;
dmaFrameSize = 1;
dmaBlocks = sectors_to_write;
}
else if (pdev->device[devNum].dataTransferMode == DOCH_DATA_MODE_MULT)
{
dmaRemainderSectors = (sectors_to_write % pdev->device[devNum].dwMulti_Current);
/*Set initial parameters (will be altered afterwards to transfer "remainder" sectors*/
dmaBlocks = (sectors_to_write / pdev->device[devNum].dwMulti_Current);
dmaFrameSize = pdev->device[devNum].dwMulti_Current;
}
else
{
DBG_PRINT_ERR(FLZONE_ATA, "io_input(): DMA 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 */
dochIoOutputDmaSequence:
if(dmaBlocks > 0)
{
/*Set up the DMA transfer - Platfrom*/
dmaParams.bOpType = DOCH_DMA_CONFIG_TRANSACTION_HOST_TO_DEVICE;
dmaParams.bDiskOnChip_BasePtr = ((FLByte*)pdev->bRegBase);
dmaParams.wDiskOnChip_Offset = DOCH_DATA_PORT_AREA;
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_output(): DOCH_DMA_CONFIG_TRANSACTION_HOST_TO_DEVICE Failed\r\n");
return DOCH_GeneralFailure;
}
/*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);
/*Wait for DMA transfer to complete*/
dmaParams.bOpType = DOCH_DMA_WAIT_FOR_WRITE_TRANSACTION_END;
DOCH_DMA_CONFIG(&dmaParams);
/*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_output(): DOCH_DMA_WAIT_FOR_WRITE_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 then 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 dochIoOutputDmaSequence;
}
/* 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_DMA_CONFIG*/
/*PIO transfer was requested*/
{
/*Write 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_SHORT_WAIT));
if(rc != 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;
}
/*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_WRITE_PARTITION)) ) /*Command is OTHER than Write Partition*/
{
for(secPerformed=1; secPerformed<=sectors_to_write; secPerformed++)
{
/*Perform data xfer*/
if( (DOCHBLK_WRITE(pdev->bRegBase,
(FLByte*)buf + offset,
1)) != 0)
{
return DOCH_WriteFault;
}
/* Check DRQ ready and not BSY before next data xfer */
/* (don`t perform after LAST sector was transfered) */
if(secPerformed != sectors_to_write)
{
(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\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_write;)
{
FLByte multSecToWrite;
/*Determine how many sectors to write this cycle*/
if((secPerformed + multCount) > sectors_to_write)
multSecToWrite = (sectors_to_write - secPerformed);
else
multSecToWrite = multCount;
/*Perform data xfer*/
if( (DOCHBLK_WRITE(pdev->bRegBase,
(FLByte*)buf + offset,
(multSecToWrite))) != 0)
{
return DOCH_WriteFault;
}
/* Check DRQ ready and not BSY before next data xfer */
/* (don`t perform after LAST sector was transfered) */
if((secPerformed + multSecToWrite) != sectors_to_write)
{
(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\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 += multSecToWrite;
offset += (multSecToWrite * 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 */
/* Wait until device is ready. This might involve yielding the
* CPU and waiting for device interrupt, so we use DOCH_LONG_WAIT.
*/
rc = ready(pdev, devNum, DOCH_ALT_STATUS_REG, (DOCH_READY | DOCH_BUSY | DOCH_DRQ),
DOCH_READY, DOCH_LONG_WAIT);
} /* End of else on if(pdev->bUseDMA) */
/* check operation's status; this also clear 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 _ c t r l *
* *
* Pass command 'cmd' to DOCH device. *
* *
* Parameters : *
* pdev : device to act on *
* regs : DOCH_Registers *
* *
* Returns : *
* DOCH_OK in success, otherwise respective error code. *
* *
******************************************************************************/
DOCH_Error io_ctrl ( DOCH_Socket * pdev,
FLSNative devNum,
DOCH_Registers * regs)
{
DOCH_Error rc;
FLSNative status;
/* 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 DOCH BUSY flag to clear*/
if ((rc = ready(pdev, devNum, DOCH_ALT_STATUS_REG, DOCH_BUSY, 0, DOCH_SHORT_WAIT)) != DOCH_OK)
{
DBG_PRINT_ERR(FLZONE_ATA, "\r\nio_ctrl(): ATA not Ready\r\n");
DBG_PRINT_ERR_PRM(FLZONE_ATA, (FLTXT("rc = 0x%x \r\n"),rc));
return rc;
}
/*If DOCH is ready, write registers*/
if (rc == DOCH_OK)
{
/*Write ATA registers*/
DOCHWRITE_ATA_REG (pdev->bRegBase, DOCH_FEATURES_REG, regs->bFeaturesError);
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_COMMAND_REG, regs->bCommandStatus);
/* wait until device is ready */
rc = ready(pdev, devNum, DOCH_STATUS_REG, (DOCH_READY | DOCH_BUSY),
DOCH_READY, DOCH_LONG_WAIT);
if(rc != DOCH_OK)
{
DBG_PRINT_ERR(FLZONE_ATA, "\r\nio_ctrl(): 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 clear 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;
}
DOCH_Error retrieveAndPrintAtaDebug(DOCH_Socket* pdev)
{
DOCH_Error rc = DOCH_OK;
DOCH_Registers in_regs;
DOCH_Registers out_regs;
/*FLWord numOfDataBytes;*/
FLWord currentINTEnabled, currentDMAEnabled, currentBurstEnabled;
tffsset(&in_regs, 0, sizeof(in_regs));
in_regs.bFeaturesError = DOCH_RETRIEVE_DBG_MSG;
in_regs.bCommandStatus = DOCH_VSCMD_EXT_DEVICE_CTRL;
in_regs.bSectorCount = 1;
in_regs.bDriveHead = (pdev->bAtaDevNum * DOCH_DEVICE);
/* Disable interrupts */
/* Disable DMA/Burst */
/* (retain original values)*/
currentINTEnabled = pdev->bUseInterrupt;
currentDMAEnabled = pdev->bUseDMA;
currentBurstEnabled = pdev->bUseBurst;
pdev->bUseInterrupt = FALSE;
pdev->bUseDMA = FALSE;
pdev->bUseBurst = FALSE;
dochEnableATAInterrupt(pdev->wSocketNo, FALSE, 0);
/*Perform debug ocommand*/
rc = io_input(pdev, 0, &in_regs, ataDBG, 1);
/*Revert interrupts/DMA/Burst to original state*/
pdev->bUseInterrupt = currentINTEnabled;
pdev->bUseDMA = currentDMAEnabled;
pdev->bUseBurst = currentBurstEnabled;
dochEnableATAInterrupt(pdev->wSocketNo,
(DOCH_IRQ_RB_INIT(pdev->wSocketNo) && currentINTEnabled),
0);
/*Retrieve ATA out registers*/
rc = get_out_registers(pdev, 0, &out_regs);
if(rc != DOCH_OK)
return rc;
/*numOfDataBytes = (out_regs.bSectorNumber + (out_regs.bCylLow<<8));*/
if(ataDBG[0] != '\0')
{
DBG_PRINT_ERR(FLZONE_ATA, "\r\n~~~~~~~~~~~~~~~~~~~~~~~~~");
DBG_PRINT_ERR(FLZONE_ATA, "\r\n*** ETFFS Debug string: ");
DBG_PRINT_ATA(FLZONE_ATA, (ataDBG));
DBG_PRINT_ERR(FLZONE_ATA, " ***");
DBG_PRINT_ERR(FLZONE_ATA, "\r\n~~~~~~~~~~~~~~~~~~~~~~~~~\r\n");
}
return rc;
}
/******************************************************************************
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -