📄 sdcontrol.c
字号:
SDHCDSetMaxClockRate(pSlotInfo, pController->dwMaximumSDClockFrequency);
// Set power up delay. We handle this in SetVoltage().
SDHCDSetPowerUpDelay(pSlotInfo, 300);
}
break;
default:
status = SD_API_STATUS_INVALID_PARAMETER;
}
return status;
}
///////////////////////////////////////////////////////////////////////////////
// HandleProgramDone - Handle program done interrupt
// Input: pController - the controller that is interrupting
// Output:
// Return:
// Notes:
///////////////////////////////////////////////////////////////////////////////
VOID HandleProgramDone(PSDH_HARDWARE_CONTEXT pController)
{
PSD_BUS_REQUEST pRequest; // current request
PROGRAM_DONE_INTERRUPT_OFF(pController);
// get the current request
pRequest = pController->pCurrentRequest;
// this should never happen because we mark the request as un-cancelable.
DEBUG_ASSERT(NULL != pRequest);
if(NULL == pRequest)
{
return;
}
SetCurrentState(pController, WriteDataDone);
// notice there is no status to check for a programming error
// this is up to the upper level drivers to send a card status command
DbgPrintZo(SDH_TRANSMIT_ZONE, (TEXT("HandleProgramDone: Programming Complete \n")));
if( !( pController->fClockAlwaysOn || ( pController->fClockOnIfInterruptsEnabled && pController->fSDIOEnabled ) ) )
{
// turn off the clock
SDClockOff(pController);
// complete the request
}
DbgPrintZo(SDH_SDBUS_INTERACTION_ZONE, (TEXT("HandleProgramDone reports Bus Request Succeeded\n")));
IndicateBusRequestComplete(pController->pHCContext,
pRequest ,
SD_API_STATUS_SUCCESS);
}
///////////////////////////////////////////////////////////////////////////////
// EmptyReceiveFifo - Empty the receive Fifo
// Input: pController - the controller instance
// pRequest - the request to get the data from
// ByteCount - number of bytes to read
// MaxBytes - limit of this transfer
// Output:
// Return:
// Notes:
//
///////////////////////////////////////////////////////////////////////////////
VOID EmptyReceiveFifo(PSDH_HARDWARE_CONTEXT pController,
PSD_BUS_REQUEST pRequest,
ULONG ByteCount,
ULONG MaxBytes)
{
ULONG MaxBytesToRead;
PBYTE pCurPtr;
DWORD dwTotalRead;
volatile UCHAR *pMMC_RX_Fifo = (volatile UCHAR *)&(pController->pSDMMCRegisters->rxfifo);
volatile DWORD *pMMC_RX_FifoDW = (volatile DWORD *)&(pController->pSDMMCRegisters->rxfifo);
MaxBytesToRead = MaxBytes - pRequest->HCParam;
pCurPtr = pRequest->pBlockBuffer+pRequest->HCParam;
if( ByteCount > MaxBytesToRead )
{
ByteCount = MaxBytesToRead;
}
dwTotalRead = ByteCount;
// we are touching the block buffer, we must set the process permissions
// empty the FIFO
while (ByteCount) {
if( ByteCount >= 4 )
{
union {
BYTE dataByte[4];
DWORD dataLong;
} data;
register PBYTE pSrc = data.dataByte;
// read in the dword from the FIFO
data.dataLong = *pMMC_RX_FifoDW;
*(pCurPtr++) = *(pSrc++);
*(pCurPtr++) = *(pSrc++);
*(pCurPtr++) = *(pSrc++);
*(pCurPtr++) = *(pSrc++);
ByteCount -= 4;
}
else while (ByteCount) {
// read in the byte from the FIFO
*(pCurPtr++) = *pMMC_RX_Fifo;
ByteCount--;
}
};
pRequest->HCParam += dwTotalRead;
}
///////////////////////////////////////////////////////////////////////////////
// HandleTransferDone- Handle transfer done interrupt
// Input: pController - the controller that is interrupting
// fForceTimeout - if true, we reached a timeout during transfer
// Output:
// Return:
// Notes:
///////////////////////////////////////////////////////////////////////////////
VOID HandleTransferDone(PSDH_HARDWARE_CONTEXT pController, BOOL fForceTimeout)
{
PSD_BUS_REQUEST pRequest; // current request
DWORD regValue; // intermediate byte value
ULONG maxBytes; // max bytes
// turn off the transfer done interrupt
TRANSFER_DONE_INTERRUPT_OFF(pController);
// turn off data error interrupt
PROGRAM_DATA_ERROR_INTERRUPT_OFF(pController);
pController->dwControllerIstTimeout = INFINITE;
// get the current request
pRequest = pController->pCurrentRequest;
// this should never happen because we mark the request as un-cancelable
DEBUG_ASSERT(NULL != pRequest);
if( !pRequest )
{
RX_FIFO_INTERRUPT_OFF(pController);
TX_FIFO_INTERRUPT_OFF(pController);
return;
}
if (TRANSFER_IS_READ(pRequest)) {
// make sure RX fifo interrupt is off
RX_FIFO_INTERRUPT_OFF(pController);
} else if (TRANSFER_IS_WRITE(pRequest)) {
// make sure TX fifo interrupt is off
TX_FIFO_INTERRUPT_OFF(pController);
// can't turn off the clock until the prog done interrupt!
} else {
DEBUG_ASSERT(FALSE);
}
// check the transfer status
regValue = READ_MMC_REGISTER_DWORD(pController, MMC_STAT);
// check for errors
if (regValue & MMC_STAT_FLASH_ERROR) {
ASSERT(0);
DbgPrintZo(SDH_SDBUS_INTERACTION_ZONE, (TEXT("HandleTransferDone reports FLASH ERROR\n")));
IndicateBusRequestComplete(pController->pHCContext,
pRequest ,
SD_API_STATUS_DATA_ERROR);
return;
}
if (regValue & MMC_STAT_SPI_WR_ERROR) {
ASSERT(0);
}
if (regValue & MMC_STAT_RD_STALLED) {
ASSERT(0);
}
if ( ( regValue & MMC_STAT_READ_TIMEOUT ) || fForceTimeout ) {
DbgPrintZo(SDCARD_ZONE_ERROR, (TEXT("HandleTransferDoneInterrupt: Read Data TimedOut \n")));
if( !( pController->fClockAlwaysOn ||
( pController->fClockOnIfInterruptsEnabled && pController->fSDIOEnabled ) ) )
{
// turn off the clock
SDClockOff(pController);
}
DbgPrintZo(SDH_SDBUS_INTERACTION_ZONE, (TEXT("HandleTransferDone reports DATA TIMEOUT\n")));
IndicateBusRequestComplete(pController->pHCContext,
pRequest ,
SD_API_STATUS_DATA_TIMEOUT);
return;
} else if (regValue & MMC_STAT_READ_DATA_CRC_ERROR) {
DbgPrintZo(SDCARD_ZONE_ERROR, (TEXT("HandleTransferDoneInterrupt: Read Data Contains CRC error \n")));
if( !( pController->fClockAlwaysOn ||
( pController->fClockOnIfInterruptsEnabled && pController->fSDIOEnabled ) ) )
{
// turn off the clock
SDClockOff(pController);
}
DbgPrintZo(SDH_SDBUS_INTERACTION_ZONE, (TEXT("HandleTransferDone reports CRC ERROR\n")));
IndicateBusRequestComplete(pController->pHCContext,
pRequest ,
SD_API_STATUS_CRC_ERROR);
return;
} else if (regValue & MMC_STAT_WRITE_DATA_CRC_ERROR) {
DbgPrintZo(SDCARD_ZONE_ERROR, (TEXT("HandleTransferDoneInterrupt: Card received Write Data with CRC error \n")));
if( !( pController->fClockAlwaysOn ||
( pController->fClockOnIfInterruptsEnabled && pController->fSDIOEnabled ) ) )
{
// turn off the clock
SDClockOff(pController);
}
DbgPrintZo(SDH_SDBUS_INTERACTION_ZONE, (TEXT("HandleTransferDone reports CRC ERROR\n")));
IndicateBusRequestComplete(pController->pHCContext,
pRequest ,
SD_API_STATUS_CRC_ERROR);
return;
}
#ifdef DEBUG
ASSERT( pController->fDMATransferInProgress == FALSE );
#endif
if(pController->fDMATransfer)
{
pRequest->HCParam = pRequest->NumBlocks * pRequest->BlockSize;
}
if (TRANSFER_IS_READ(pRequest)) {
if( pController->fDMATransfer ) {
if( pController->fDMAUsingDriverBuffer )
{
// copy data from our DMA buffer into client buffer
if( !SDPerformSafeCopy(pRequest->pBlockBuffer,
pController->pDMABuffer,
pRequest->BlockSize * pRequest->NumBlocks) )
{
ASSERT(0);
DbgPrintZo(SDCARD_ZONE_ERROR, (TEXT("HandleTransferDoneInterrupt: Access Violation\n")));
if( !( pController->fClockAlwaysOn ||
( pController->fClockOnIfInterruptsEnabled && pController->fSDIOEnabled ) ) )
{
// turn off the clock
SDClockOff(pController);
}
DbgPrintZo(SDH_SDBUS_INTERACTION_ZONE, (TEXT("HandleTransferDone reports Access Violation\n")));
IndicateBusRequestComplete(pController->pHCContext,
pRequest ,
SD_API_STATUS_ACCESS_VIOLATION);
return;
}
}
} else {
// why are we doing this here? If the remaining read data is less than a Fifo's worth (32)
// we won't get the RX Fifo Read Request interrupt because the fifo won't be full.
// also even if it is full or if this isn't the case the TRANSFER_DONE bit seems to mask it out
// anyways this prevents the problem where there are bytes stuck in the Fifo
maxBytes = pRequest->NumBlocks * pRequest->BlockSize;
if (pRequest->HCParam < maxBytes) {
DbgPrintZo(SDH_RECEIVE_ZONE, (TEXT("HandleTransferDoneInterrupt: Fifo contains remaining data, Max: %d, current count %d \n"),
maxBytes, pRequest->HCParam));
// get the remaining bytes out of the FIFO
__try {
EmptyReceiveFifo(pController,
pRequest,
(maxBytes - pRequest->HCParam),
maxBytes);
}__except(EXCEPTION_EXECUTE_HANDLER) {
}
}
}
SetCurrentState(pController, ReadDataDone);
if( !( pController->fClockAlwaysOn ||
( pController->fClockOnIfInterruptsEnabled && pController->fSDIOEnabled ) ) )
{
// now it is safe to turn off the clock
SDClockOff(pController);
}
DbgPrintZo(SDH_SDBUS_INTERACTION_ZONE, (TEXT("Bytes read: [%S]\n"), HexDisplay( pRequest->pBlockBuffer, TRANSFER_SIZE(pRequest) ) ) );
}
if (TRANSFER_IS_WRITE(pRequest)) {
if (!IS_PROGRAM_DONE(pController)) {
SetCurrentState(pController, ProgramWait);
// turn on programming done interrupt
PROGRAM_DONE_INTERRUPT_ON(pController);
//Sleep(500);
// check to see if programming is finished
if (!IS_PROGRAM_DONE(pController)) {
DbgPrintZo(SDH_TRANSMIT_ZONE, (TEXT("HandleTransferDoneInterrupt: Programming Not Complete \n")));
}
// if we wait on the programming done interrupt this could
// go on forever because now it is up to the memory card,
// we may have to make this request cancelable at this point
return;
}
}
DEBUG_ASSERT((pRequest->HCParam >= (pRequest->NumBlocks * pRequest->BlockSize)));
// complete the request
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -