📄 sdcontrol.cpp
字号:
}
while (1)
{
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;
}
if (pHCDevice->fFakeCardRemoval)
{
pHCDevice->fFakeCardRemoval = FALSE;
DEBUGMSG(ZONE_WARN, (TEXT("SDControllerIstThread:Fake card removal ... \r\n")));
ProcessCardRemoval(pHCDevice);
//Function ResetCard() will be called if hardware does not reset the card after waking up.
//If during power down (D0 to D4) hardware has set slot voltage to 0 and waking up
//(D4 to D0) hardware has set voltage to optimum voltage, then calling ResetCard() will
//not be necessary
//ResetCard(pHCDevice);
// Check for card presence again
ProcessCardInsertion(pHCDevice);
}
//Print STATUS and INT_CNT registers
DEBUGMSG(ZONE_INTERRUPT, (TEXT("IST: STATUS 0x%08X INT_CNT 0x%08X\r\n"),
INREG32(&pHCDevice->pSDMMCRegisters->STATUS),
(INREG32(&pHCDevice->pSDMMCRegisters->INT_CNTR))));
// Handle card insert/remove
// Wait for cmds to complete cos SDHC don't take reset very well.
// status register contents are not reset.
if (pHCDevice->fDeviceStatusChange)
{
EnterCriticalSection(&pHCDevice->ControllerCriticalSection);
DEBUGMSG(ZONE_INTERRUPT, (TEXT("SDControllerIstThread: Device present %d\r\n"), pHCDevice->fDevicePresent));
if (pHCDevice->fDevicePresent)
ProcessCardInsertion(pHCDevice);
else
ProcessCardRemoval(pHCDevice);
pHCDevice->fDeviceStatusChange = FALSE;
LeaveCriticalSection(&pHCDevice->ControllerCriticalSection);
goto _done;
}
// Check for INT_CNTR because SDIO status bit will be always set until
// the card deasserts the SDIO int.
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));
//Indicate to upper layer that SDIO is interrupting
SDHCDIndicateSlotStateChange(pHCDevice->pHCContext, 0, DeviceInterrupting);
DEBUGMSG(ZONE_INTERRUPT, (TEXT("SDControllerIstThread:IO Int\r\n")));
}
}
// Check End Command Response interrupt
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));
if(pHCDevice->SDCommandStatus == SD_COMMAND_STATUS_CMD)
HandleCommandComplete(pHCDevice);
}
}
// Check write operation done interrupt
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));
if(pHCDevice->SDCommandStatus == SD_COMMAND_STATUS_WRITE)
HandleTransferDone(pHCDevice);
DEBUGMSG(ZONE_INTERRUPT, (TEXT("SDControllerIstThread:write done ...\r\n")));
}
}
// Check read operation done interrupt
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));
if(pHCDevice->SDCommandStatus == SD_COMMAND_STATUS_READ)
HandleTransferDone(pHCDevice);
DEBUGMSG(ZONE_INTERRUPT, (TEXT("SDControllerIstThread:read done ...\r\n")));
}
}
_done:
InterruptDone(pHCDevice->dwSysintrSDHC);
}
}
//------------------------------------------------------------------------------
//
// 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;
//TODO: done in Mx21. is this really required???
// 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);
}
}
//SetClock(pController, FALSE);
SDHCDIndicateBusRequestComplete(pController->pHCContext, pRequest, status);
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))
{
DEBUGMSG(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));
IndicateBusRequestComplete(pController, pRequest, SD_API_STATUS_RESPONSE_TIMEOUT);
return TRUE;
}
//Check for crc error
if (EXTREG32BF(&pController->pSDMMCRegisters->STATUS, SDHC_SR_RSPCERR))
{
DEBUGMSG(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(USHORT)) * (startingOffset + 1));
}
////////////////////////////////////////////////////////////////////////////
//If this is a data transfer, start the I/O operation; otherwise, finish the request -----
///////////////////////////////////////////////////////////////////////////
if (pRequest->TransferClass == SD_COMMAND)
{
IndicateBusRequestComplete(pController, pRequest, status);
return TRUE;
}
else if (pRequest->TransferClass == SD_WRITE)
{
DWORD m_dwNumBytesToTransfer ;
m_dwNumBytesToTransfer = pRequest->NumBlocks * pRequest->BlockSize;
pController->SDCommandStatus = SD_COMMAND_STATUS_WRITE;
//Check whether DMA or CPU transfer
if (pController->fDMATransfer == TRUE)
{
DDKDmacSetTransCount(pController->DmaReqTxCH, m_dwNumBytesToTransfer);
// Start the output DMA
DDKDmacStartChan(pController->DmaReqTxCH);
}
else
{
BYTE* tempBuff = pRequest->pBlockBuffer ;
DWORD no_of_fill_fifo, j, k, remainder, tempData ;
DWORD byteCount = 0; //count the bytes written
no_of_fill_fifo = (m_dwNumBytesToTransfer)/(pController->Bytes_in_fifo);
//remaining bytes which are less than FIFO size
remainder = (m_dwNumBytesToTransfer)-(pController->Bytes_in_fifo)*no_of_fill_fifo;
DEBUGMSG(ZONE_INFO, (TEXT("m_dwNumBytesToTransfer:%d Bytes_in_fifo:%d no_of_fill_fifo:%d\r\n")
,m_dwNumBytesToTransfer, pController->Bytes_in_fifo, no_of_fill_fifo));
for (j=0; j<no_of_fill_fifo; j++)
{
//Wait till buffer ready
while (!EXTREG32BF(&pController->pSDMMCRegisters->STATUS, SDHC_SR_BWR))Sleep(0);
for (k=0; k<pController->Units_in_fifo; k++)
{
tempData = ((tempBuff[0]) | (tempBuff[1] << 8) | (tempBuff[2] << 16) | (tempBuff[3] << 24));
OUTREG32(&pController->pSDMMCRegisters->BUFFER_ACCESS, tempData);
tempBuff+=4 ;
byteCount+=4; //count the bytes written
}
}
if (remainder)
{
//Wait till buffer ready
while (!EXTREG32BF(&pController->pSDMMCRegisters->STATUS, SDHC_SR_BWR))Sleep(0);
for (j=0;j<remainder/4;j++)
{
tempData = ((tempBuff[0]) | (tempBuff[1] << 8) | (tempBuff[2] << 16) | (tempBuff[3] << 24));
OUTREG32(&pController->pSDMMCRegisters->BUFFER_ACCESS, tempData);
tempBuff+=4 ;
byteCount+=4; //count the bytes written
}
if ((remainder%4)==1)
{
tempData = tempBuff[0];
OUTREG32(&pController->pSDMMCRegisters->BUFFER_ACCESS, tempData);
byteCount++; //count the bytes written
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -