sdcontrol.c
来自「该BSP是基于PXA270+WINCE的BSP」· C语言 代码 · 共 1,659 行 · 第 1/5 页
C
1,659 行
WRITE_MMC_REGISTER_DWORD(pController, MMC_RDTO, SDH_DEFAULT_DATA_TIMEOUT_CLOCKS);
SetCurrentState(pController, CommandSend);
// turn on the command complete and the response error interrupts
END_CMD_INTERRUPT_ON(pController);
PROGRAM_RESPONSE_ERROR_INTERRUPT_ON(pController);
// turn on the clock
SDClockOn(pController);
if( fExtraDelay )
{
fExtraDelay = FALSE;
Sleep(500);
}
#if DEBUG
{
DWORD mmcStatus;
mmcStatus = READ_MMC_REGISTER_DWORD(pController, MMC_STAT);
if (mmcStatus & 0x0000003F) {
// these errors should be cleared
DbgPrintZo(SDCARD_ZONE_ERROR,
(TEXT("********* SDHBusRequestHandler - MMC Status did not clear : 0x%08X \n"),
(mmcStatus & 0x0000003F)));
}
}
#endif
DbgPrintZo(SDH_SEND_ZONE, (TEXT("SDHBusRequestHandler - Request Sent\n")));
return SD_API_STATUS_PENDING;
}
///////////////////////////////////////////////////////////////////////////////
// SDHSlotOptionHandler - handler for slot option changes
// Input: pHostContext - host controller context
// SlotNumber - the slot the change is being applied to
// Option - the option code
// pData - data associated with the option
// OptionSize - size of option data
// Output:
// Return: SD_API_STATUS code
// Notes:
///////////////////////////////////////////////////////////////////////////////
SD_API_STATUS SDHSlotOptionHandler(PSDCARD_HC_CONTEXT pHCContext,
DWORD SlotNumber,
SD_SLOT_OPTION_CODE Option,
PVOID pData,
ULONG OptionSize)
{
SD_API_STATUS status = SD_API_STATUS_SUCCESS; // status
PSDH_HARDWARE_CONTEXT pController; // the controller
PSD_HOST_BLOCK_CAPABILITY pBlockCaps; // queried block capabilities
// get our extension
pController = GetExtensionFromHCDContext(PSDH_HARDWARE_CONTEXT, pHCContext);
switch (Option) {
case SDHCDSetSlotPower:
DbgPrintZo(SDCARD_ZONE_INIT,
(TEXT("SDHSlotOptionHandler - called - SetSlotPower : 0x%08X \n"),
*((PDWORD)pData)));
break;
case SDHCDSetSlotInterface:
DbgPrintZo(SDCARD_ZONE_INIT,
(TEXT("SDHSlotOptionHandler - called - SetSlotInterface : Clock Setting: %d \n"),
((PSD_CARD_INTERFACE)pData)->ClockRate));
if (SD_INTERFACE_SD_MMC_1BIT ==
((PSD_CARD_INTERFACE)pData)->InterfaceMode) {
DbgPrintZo(SDCARD_ZONE_INIT,
(TEXT("SDHSlotOptionHandler - called - SetSlotInterface : setting for 1 bit mode \n")));
pController->f4BitMode = FALSE;
} else {
DbgPrintZo(SDCARD_ZONE_INIT,
(TEXT("SDHSlotOptionHandler - called - SetSlotInterface : setting for 4 bit mode \n")));
pController->f4BitMode = TRUE;
}
// 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));
SDIO_INTERRUPT_ON(pController);
pController->fSDIOEnabled = TRUE;
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);
}
else if( pController->fSDIOEnabled )
{
SDIO_INTERRUPT_ON(pController);
}
RELEASE_LOCK(pController);
break;
case SDHCDDisableSDIOInterrupts:
DbgPrintZo(SDCARD_ZONE_INIT,
(TEXT("SDHSlotOptionHandler - called - DisableSDIOInterrupts : on slot %d \n"),
SlotNumber));
SDIO_INTERRUPT_OFF(pController);
pController->fSDIOEnabled = FALSE;
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, 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 = SDHCDGetAndLockCurrentRequest(pController->pHCContext, 0);
// 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")));
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)
{
ULONG receiveBufferIndex = 0; // receive buffer index
ULONG MaxBytesToRead;
volatile UCHAR *pMMC_RX_Fifo = (volatile UCHAR *)&(pController->pSDMMCRegisters->rxfifo);
volatile DWORD *pMMC_RX_FifoDW = (volatile DWORD *)&(pController->pSDMMCRegisters->rxfifo);
if( !IsCardPresent() )
{
DbgPrintZo(SDCARD_ZONE_ERROR, (TEXT("EmptyReceiveFifo: Card ejected!\n")));
return;
}
MaxBytesToRead = MaxBytes - pRequest->HCParam;
if( ByteCount > MaxBytesToRead )
{
ByteCount = MaxBytesToRead;
}
// we are touching the block buffer, we must set the process permissions
SD_SET_PROC_PERMISSIONS_FROM_REQUEST(pRequest) {
// empty the FIFO
while (ByteCount) {
// fill up the receive buffer
if (receiveBufferIndex < MMC_RXFIFO_SIZE) {
if( ByteCount >= 4 )
{
// read in the dword from the FIFO
*(DWORD*)(&pController->RcvBuffer[receiveBufferIndex]) = *pMMC_RX_FifoDW;
receiveBufferIndex+=4;
ByteCount-=4;
}
else
{
// 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
PREFAST_SUPPRESS( 12008, "False positive: the buffer access index 'pRequest->HCParam + receiveBufferIndex' is guaranteed to be valid prior to this call" );
SDPerformSafeCopy(&pRequest->pBlockBuffer[pRequest->HCParam],
pController->RcvBuffer,
receiveBufferIndex);
// bump the running count
pRequest->HCParam += receiveBufferIndex;
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?