📄 sdcontrol.cpp
字号:
DEBUGMSG(ZONE_INTERRUPT, (TEXT("Wait For Interrupt ... \r\n")));
if (WaitForSingleObject(pHCDevice->hControllerInterruptEvent, INFINITE) != WAIT_OBJECT_0)
{
// bail out
ERRORMSG(ZONE_ERROR, (TEXT("SDControllerIstThread: Wait Failed! \r\n")));
return 0;
}
if (pHCDevice->DriverShutdown)
{
DEBUGMSG(ZONE_WARN, (TEXT("SDControllerIstThread: Thread Exiting\r\n")));
return 0;
}
SDHCDAcquireHCLock(pHCDevice->pHCContext);
// Handle card insert/remove
SDCardPresenceDetect(pHCDevice);
if (pHCDevice->fDeviceStatusChange)
{
DEBUGMSG(ZONE_INTERRUPT, (TEXT("SDControllerIstThread: Device present %d\r\n"), pHCDevice->fDevicePresent));
if (pHCDevice->fDevicePresent)
{
ProcessCardInsertion(pHCDevice);
}
else
{
ProcessCardRemoval(pHCDevice);
}
goto _done;
}
if (pHCDevice->fFakeCardRemoval)
{
pHCDevice->fFakeCardRemoval = FALSE;
DEBUGMSG(ZONE_WARN, (TEXT("SDControllerIstThread:Fake card removal ... \r\n")));
ProcessCardRemoval(pHCDevice); // Upper layer should be notified of a card removal
pHCDevice->fDevicePresent = TRUE; //Device is present
ProcessCardInsertion(pHCDevice);
goto _done;
}
// If we are in the IST only because of a SDIO card interrupt, clocks to
// the controller could be cut off if clock gating between cmds is supported.
// Inorder to read the controller registers, should enable clocks here.
if ((pHCDevice->fClockGatedOff == TRUE) && (pHCDevice->fClockGatingSupported == TRUE))
{
// Controller clocks needs to be enabled
BSPSdhcSetClockGatingMode(TRUE, pHCDevice->ControllerIndex);
pHCDevice->fClockGatedOff = FALSE; // controller clocks are enabled
}
//Print STATUS and INT_CNT registers
DEBUGMSG(ZONE_INFO, (TEXT("IST: STATUS 0x%08X INT_CNT 0x%08X\r\n"),
INREG32(&pHCDevice->pSDMMCRegisters->STATUS),
INREG32(&pHCDevice->pSDMMCRegisters->INT_CNTR)));
if (EXTREG32BF(&pHCDevice->pSDMMCRegisters->INT_CNTR, SDHC_INT_SDIOIRQ))
{
if (EXTREG32BF(&pHCDevice->pSDMMCRegisters->STATUS, SDHC_SR_SDIOINT))
{
//Disable the SDIO interrupt controller bit before servicing SDIO interrupt
INSREG32BF(&pHCDevice->pSDMMCRegisters->INT_CNTR, SDHC_INT_SDIOIRQ, 0);
// Disable the wakeup intr
INSREG32BF(&pHCDevice->pSDMMCRegisters->INT_CNTR, SDHC_INT_SDIOIRQWKP, 0);
pHCDevice->fSDIOEnabled = FALSE;
//Clear SDIO interrupt status by writing 1
OUTREG32(&pHCDevice->pSDMMCRegisters->STATUS, CSP_BITFVAL(SDHC_SR_SDIOINT, 1));
// We do not clock gate the controller here, because a CMD52 is going to follow
// to get the card interrupt status register
//Indicate to upper layer that SDIO is interrupting
SDHCDIndicateSlotStateChange(pHCDevice->pHCContext, 0, DeviceInterrupting);
goto _done;
}
}
if (EXTREG32BF(&pHCDevice->pSDMMCRegisters->INT_CNTR, SDHC_INT_ECR))
{
if (EXTREG32BF(&pHCDevice->pSDMMCRegisters->STATUS, SDHC_SR_ECR))
{
//Negate End Command Response interrupt
INSREG32BF(&pHCDevice->pSDMMCRegisters->INT_CNTR, SDHC_INT_ECR, 0);
// Clear interrupt status by writing 1 to the corresponsing bit only
OUTREG32(&pHCDevice->pSDMMCRegisters->STATUS, CSP_BITFVAL(SDHC_SR_ECR, 1));
HandleCommandComplete(pHCDevice);
goto _done;
}
}
// If DMA transfer is active
if (pHCDevice->fDMATransfer == TRUE)
{
// Check DMA status for each buffer in the chain
UINT32 dmaStatus;
pHCDevice->fDmaBusy = FALSE;
for (UINT32 i = 0; i < pHCDevice->DmaChainSize; i++)
{
DDKSdmaGetBufDescStatus(pHCDevice->ChanSDHC, i, &dmaStatus);
if (dmaStatus & DDK_DMA_FLAGS_BUSY)
{
pHCDevice->fDmaBusy = TRUE;
}
if (dmaStatus & DDK_DMA_FLAGS_ERROR)
{
// there was an error during DMA transfer
pHCDevice->fDmaError = TRUE;
}
}
HandleTransferDone(pHCDevice);
DEBUGMSG(ZONE_INFO, (TEXT("SDControllerIstThread: Transfer Done ...\r\n")));
goto _done;
}
else
{
if (EXTREG32BF(&pHCDevice->pSDMMCRegisters->INT_CNTR, SDHC_INT_WODONE))
{
if (EXTREG32BF(&pHCDevice->pSDMMCRegisters->STATUS, SDHC_SR_WODONE) )
{
//Negate Write Operation Done interrupt
INSREG32BF(&pHCDevice->pSDMMCRegisters->INT_CNTR, SDHC_INT_WODONE, 0);
// Clear interrupt status by writing 1
OUTREG32(&pHCDevice->pSDMMCRegisters->STATUS, CSP_BITFVAL(SDHC_SR_WODONE, 1));
HandleTransferDone(pHCDevice);
DEBUGMSG(ZONE_INTERRUPT, (TEXT("SDControllerIstThread:write done ...\r\n")));
goto _done;
}
}
if (EXTREG32BF(&pHCDevice->pSDMMCRegisters->INT_CNTR, SDHC_INT_RODONE))
{
if (EXTREG32BF(&pHCDevice->pSDMMCRegisters->STATUS, SDHC_SR_RODONE))
{
//Negate Write Operation Done interrupt
INSREG32BF(&pHCDevice->pSDMMCRegisters->INT_CNTR, SDHC_INT_RODONE, 0);
// Clear interrupt status by writing 1
OUTREG32(&pHCDevice->pSDMMCRegisters->STATUS, CSP_BITFVAL(SDHC_SR_RODONE, 1));
HandleTransferDone(pHCDevice);
DEBUGMSG(ZONE_INTERRUPT, (TEXT("SDControllerIstThread:read done ...\r\n")));
goto _done;
}
}
}
// Spurious interrupt. Print STATUS and INT_CNT registers
RETAILMSG(1, (TEXT("SDControllerIstThread: Spurious Interrupt??? STATUS 0x%08X INT_CNT 0x%08X\r\n"),
INREG32(&pHCDevice->pSDMMCRegisters->STATUS),
INREG32(&pHCDevice->pSDMMCRegisters->INT_CNTR)));
_done:
InterruptDone(pHCDevice->dwSysintrSDHC);
SDHCDReleaseHCLock(pHCDevice->pHCContext);
}
}
//------------------------------------------------------------------------------
//
// Function: IndicateBusRequestComplete
//
// indicates to upper layer that command is done and its status
//
// Parameters:
// pHardwareContext[in] - hardware context
// pRequest[in] - the request
// status[in] - the status
//
// Returns:
// none
//
//------------------------------------------------------------------------------
static void IndicateBusRequestComplete(PSDH_HARDWARE_CONTEXT pController,
PSD_BUS_REQUEST pRequest,
SD_API_STATUS status)
{
DEBUGMSG(ZONE_FUNCTION, (TEXT("+IndicateBusRequestComplete\r\n")));
if (pRequest->CommandCode == SD_CMD_APP_CMD)
pController->fAppCommandSent = TRUE;
else
pController->fAppCommandSent = FALSE;
// Soft reset host on cmd response and data errors
if (status != SD_API_STATUS_SUCCESS)
{
if (status == SD_API_STATUS_RESPONSE_TIMEOUT ||
status == SD_API_STATUS_CRC_ERROR ||
status == SD_API_STATUS_DATA_ERROR ||
status == SD_API_STATUS_DATA_TIMEOUT )
{
// Soft reset but do not change any previous clock setting
SoftwareReset(pController, FALSE);
}
}
// Check whether clock gating between commands is supported
if (pController->fClockGatingSupported == TRUE)
{
// Cut off clocks to the controller
BSPSdhcSetClockGatingMode(FALSE, pController->ControllerIndex);
pController->fClockGatedOff = TRUE; // controller clocks are disabled
}
#if !VPMX31
SDHCDIndicateBusRequestComplete(pController->pHCContext, pRequest, status);
#else
if (pRequest->CommandCode == SD_CMD_IO_OP_COND)
{
SDHCDIndicateBusRequestComplete(pController->pHCContext, pRequest, SD_API_STATUS_RESPONSE_TIMEOUT);
} else
{
SDHCDIndicateBusRequestComplete(pController->pHCContext, pRequest, status);
}
#endif //VPMX31
DEBUGMSG(ZONE_FUNCTION, (TEXT("-IndicateBusRequestComplete\r\n")));
}
//------------------------------------------------------------------------------
//
// Function: HandleCommandComplete
//
// Handles an END_CMD_RESP event
//
// Parameters:
// pController - hardware context
//
// Returns:
// returns TRUE is command is completed. FALSE otherwise
//
//------------------------------------------------------------------------------
static BOOL HandleCommandComplete(PSDH_HARDWARE_CONTEXT pController)
{
PSD_BUS_REQUEST pRequest;
SD_API_STATUS status = SD_API_STATUS_SUCCESS;
DEBUGMSG(ZONE_FUNCTION, (TEXT("+HandleCommandComplete\r\n")));
pRequest = SDHCDGetAndLockCurrentRequest(pController->pHCContext, 0);
//Check for response time-out
if (EXTREG32BF(&pController->pSDMMCRegisters->STATUS, SDHC_SR_TORESP))
{
ERRORMSG(ZONE_ERROR, (TEXT(" Cmd %d: Command Response timeout! Status 0x%08X\r\n"),
pRequest->CommandCode, (INREG32(&pController->pSDMMCRegisters->STATUS))));
// Clear status by writing 1
OUTREG32(&pController->pSDMMCRegisters->STATUS, CSP_BITFVAL(SDHC_SR_TORESP, 1));
if (pRequest->CommandCode == SD_CMD_IO_OP_COND)
{
// Memory cards do not respond for CMD5.
pController->fClockGatingSupported = BspSdhcIsClockGatingBetweenCmdsSupported(pController->ControllerIndex);
}
IndicateBusRequestComplete(pController, pRequest, SD_API_STATUS_RESPONSE_TIMEOUT);
return TRUE;
}
else if (pRequest->CommandCode == SD_CMD_IO_OP_COND)
{
// Only SDIO cards will respond for CMD5
pController->fClockGatingSupported = FALSE;
}
//Check for crc error
if (EXTREG32BF(&pController->pSDMMCRegisters->STATUS, SDHC_SR_RSPCERR))
{
ERRORMSG(ZONE_ERROR, (TEXT("Cmd %d: Command Response CRC error! Status 0x%08X\r\n"),
pRequest->CommandCode, (INREG32(&pController->pSDMMCRegisters->STATUS))));
// Clear status by writing 1
OUTREG32(&pController->pSDMMCRegisters->STATUS, CSP_BITFVAL(SDHC_SR_RSPCERR, 1));
IndicateBusRequestComplete(pController, pRequest, SD_API_STATUS_CRC_ERROR);
return TRUE;
}
if (pRequest)
{
LONG ii; // loop variable
LONG startingOffset; // starting offset in response buffer
USHORT responseBuffer[SDH_RESPONSE_FIFO_DEPTH]; // response buffer
if (NoResponse != pRequest->CommandResponse.ResponseType)
{
if (ResponseR2 == pRequest->CommandResponse.ResponseType)
{
// 8 words - 128 bits
startingOffset = SDH_RESPONSE_FIFO_DEPTH - 1;
} else
{
// 3 WORDS - 48 bits
startingOffset = 2;
}
// read in the response words from the response fifo.
for (ii = startingOffset; ii >= 0; ii--)
{
// read from the fifo
responseBuffer[ii] =INREG16(&pController->pSDMMCRegisters->RES_FIFO);
DEBUGMSG(ZONE_INFO, (TEXT("responseBuffer[%d]=0x%x\r\n"),ii,responseBuffer[ii]));
}
memcpy(pRequest->CommandResponse.ResponseBuffer, responseBuffer, (sizeof(USHOR
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -