📄 sdcontrol.c
字号:
} else {
// we should never get here because the only interface mode we reported was 1-bit
DEBUG_ASSERT(FALSE);
}
// shut off clock first
SDClockOff(pController);
// set rate
SDSetRate(pController, &((PSD_CARD_INTERFACE)pData)->ClockRate);
break;
case SDHCDEnableSDIOInterrupts:
DbgPrintZo(SDCARD_ZONE_INIT,
(TEXT("SDHSlotOptionHandler - called - EnableSDIOInterrupts : on slot %d \n"),
SlotNumber));
// by default the detection is enabled, normally we could
// enable the Edge detect bit, but without a GPIO manager this cannot be done in
// thread safe way.
break;
case SDHCDAckSDIOInterrupt:
// acquire the lock to block the SDIO interrupt thread
ACQUIRE_LOCK(pController);
if ( ( pController->pSDMMCRegisters->STAT & 0x8000 ) &&
( pController->pSDMMCRegisters->IREG & 0x0800 ) &&
pController->fSDIOEnabled )
{
DbgPrintZo(/*SDCARD_ZONE_INIT*/SDH_INTERRUPT_ZONE, (TEXT("SDIO INT (still)!\n")));
SDHCDIndicateSlotStateChange(pController->pHCContext,
0,
DeviceInterrupting);
}
RELEASE_LOCK(pController);
break;
case SDHCDDisableSDIOInterrupts:
DbgPrintZo(SDCARD_ZONE_INIT,
(TEXT("SDHSlotOptionHandler - called - DisableSDIOInterrupts : on slot %d \n"),
SlotNumber));
// by default the detection always enabled, normally we could
// disable the Edge detect bit, but without a GPIO manager this cannot be done in
// thread safe way.
break;
case SDHCDGetWriteProtectStatus:
DbgPrintZo(SDCARD_ZONE_INIT,
(TEXT("SDHSlotOptionHandler - called - SDHCDGetWriteProtectStatus : on slot %d \n"),
SlotNumber));
if( IsCardWriteProtected() ) {
((PSD_CARD_INTERFACE)pData)->WriteProtected = TRUE;
DbgPrintZo(SDCARD_ZONE_INIT, (TEXT("SDHSlotOptionHandler - Card is write protected \n")));
} else {
((PSD_CARD_INTERFACE)pData)->WriteProtected = FALSE;
DbgPrintZo(SDCARD_ZONE_INIT, (TEXT("SDHSlotOptionHandler - Card is write enabled \n")));
}
break;
case SDHCDQueryBlockCapability:
pBlockCaps = (PSD_HOST_BLOCK_CAPABILITY)pData;
DbgPrintZo(SDCARD_ZONE_INIT,
(TEXT("SDHSlotOptionHandler: Read Block Length: %d , Read Blocks: %d\n"),
pBlockCaps->ReadBlockSize,
pBlockCaps->ReadBlocks));
DbgPrintZo(SDCARD_ZONE_INIT,
(TEXT("SDHSlotOptionHandler: Write Block Length: %d , Write Blocks: %d\n"),
pBlockCaps->WriteBlockSize,
pBlockCaps->WriteBlocks));
// the PXA27x controller can only handle up to 1024 bytes
// with a minimum of 32 bytes per transfer
if (pBlockCaps->ReadBlockSize > SDH_MAX_BLOCK_SIZE) {
pBlockCaps->ReadBlockSize = SDH_MAX_BLOCK_SIZE;
}
if (pBlockCaps->ReadBlockSize < SDH_MIN_BLOCK_SIZE ) {
pBlockCaps->ReadBlockSize = SDH_MIN_BLOCK_SIZE;
}
if (pBlockCaps->WriteBlockSize > SDH_MAX_BLOCK_SIZE) {
pBlockCaps->WriteBlockSize = SDH_MAX_BLOCK_SIZE;
}
if (pBlockCaps->WriteBlockSize < SDH_MIN_BLOCK_SIZE ) {
pBlockCaps->WriteBlockSize = SDH_MIN_BLOCK_SIZE;
}
// the PXA27x controller can handle 64K blocks,
// we leave the number of blocks alone
break;
case SDHCDGetSlotInfo:
if( OptionSize != sizeof(SDCARD_HC_SLOT_INFO) || pData == NULL )
{
status = SD_API_STATUS_INVALID_PARAMETER;
}
else
{
PSDCARD_HC_SLOT_INFO pSlotInfo = (PSDCARD_HC_SLOT_INFO)pData;
// set the slot capabilities
SDHCDSetSlotCapabilities(pSlotInfo, SD_SLOT_SD_1BIT_CAPABLE);
// |
// SD_SLOT_SD_4BIT_CAPABLE |
// SD_SLOT_SDIO_CAPABLE);
SDHCDSetVoltageWindowMask(pSlotInfo, (SD_VDD_WINDOW_3_2_TO_3_3 | SD_VDD_WINDOW_3_3_TO_3_4));
// Set optimal voltage
SDHCDSetDesiredSlotVoltage(pSlotInfo, SD_VDD_WINDOW_3_2_TO_3_3);
SDHCDSetMaxClockRate(pSlotInfo, 20000000);
// 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 = SDHCDGetAndLockCurrentRequest(pController->pHCContext, 0);
// this should never happen because we mark the request as un-cancelable.
DEBUG_ASSERT(NULL != pRequest);
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")));
SDHCDIndicateBusRequestComplete(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)
{
DWORD dwTmp;
ULONG receiveBufferIndex = 0; // receive buffer index
volatile UCHAR *pMMC_RX_Fifo = (volatile UCHAR *)&(pController->pSDMMCRegisters->RXFIFO);
// empty the FIFO
while (ByteCount) {
if( !IsCardPresent() )
{
DbgPrintZo(SDCARD_ZONE_ERROR, (TEXT("EmptyReceiveFifo: Card ejected!\n")));
break;
}
dwTmp = pController->pSDMMCRegisters->IREG;
// fill up the receive buffer
if (receiveBufferIndex < MMC_RXFIFO_SIZE) {
// read in the byte from the FIFO
pController->RcvBuffer[receiveBufferIndex] = *pMMC_RX_Fifo;
receiveBufferIndex++;
ByteCount--;
// check to see if we've read enough
if ((pRequest->HCParam + receiveBufferIndex) >= MaxBytes) {
break;
}
} else {
// receive buffer is full, now transfer the data safely
SDPerformSafeCopy(&pRequest->pBlockBuffer[pRequest->HCParam],
pController->RcvBuffer,
receiveBufferIndex);
// bump the running count
pRequest->HCParam += receiveBufferIndex;
// reset receive buffer index
receiveBufferIndex = 0;
}
} // while
// check for any left over data
if (receiveBufferIndex) {
// safely copy the data
SDPerformSafeCopy(&pRequest->pBlockBuffer[pRequest->HCParam],
pController->RcvBuffer,
receiveBufferIndex);
// bump the running count
pRequest->HCParam += receiveBufferIndex;
}
}
///////////////////////////////////////////////////////////////////////////////
// HandleTransferDone- Handle transfer done interrupt
// Input: pController - the controller that is interrupting
// Output:
// Return:
// Notes:
///////////////////////////////////////////////////////////////////////////////
VOID HandleTransferDone(PSDH_HARDWARE_CONTEXT pController)
{
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);
// get the current request
pRequest = SDHCDGetAndLockCurrentRequest(pController->pHCContext, 0);
// this should never happen because we mark the request as un-cancelable
DEBUG_ASSERT(NULL != pRequest);
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 = pController->pSDMMCRegisters->STAT;
// check for errors
if (regValue & MMC_STAT_READ_TIMEOUT) {
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")));
SDHCDIndicateBusRequestComplete(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")));
SDHCDIndicateBusRequestComplete(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
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -