sdcontrol.c
来自「pxa27x library for windows ce 5.0」· C语言 代码 · 共 1,690 行 · 第 1/5 页
C
1,690 行
WRITE_MMC_REGISTER_DWORD(pController, MMC_BLKLEN, pRequest->BlockSize);
// set the number of blocks
WRITE_MMC_REGISTER_DWORD(pController, MMC_NOB, pRequest->NumBlocks);
// check for write
if (TRANSFER_IS_WRITE(pRequest)) {
cmdatRegister |= MMC_CMDAT_DATA_WRITE;
}
}
// check to see if we need to append the 80 clocks (i.e. this is the first transaction)
if (pController->SendInitClocks) {
pController->SendInitClocks = FALSE;
cmdatRegister |= MMC_CMDAT_INIT;
fExtraDelay = TRUE;
}
// check to see if we need to enable the SDIO interrupt checking
if (pController->fSDIOEnabled) {
cmdatRegister |= MMC_CMDAT_SDIO_INT_EN;
}
// check to see if we need to enable wide bus (4 bit) data transfer mode
if (pController->f4BitMode) {
cmdatRegister |= MMC_CMDAT_SD_4DAT;
}
// write the CMDAT register
WRITE_MMC_REGISTER_DWORD(pController, MMC_CMDAT, cmdatRegister);
DbgPrintZo(SDH_SEND_ZONE, (TEXT("SDHBusRequestHandler - CMDAT Reg: 0x%08X, CMD:%d \n"),
cmdatRegister, pRequest->CommandCode));
// set the the response timeout
WRITE_MMC_REGISTER_DWORD(pController, MMC_RESTO, SDH_DEFAULT_RESPONSE_TIMEOUT_CLOCKS);
// set the data receive timeout
WRITE_MMC_REGISTER_DWORD(pController, MMC_RDTO, SDH_DEFAULT_DATA_TIMEOUT_CLOCKS);
SetCurrentState(pController, CommandSend);
// turn on just the command complete interrupt
END_CMD_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;
}
// 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));
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, 10000000);
// 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);
// we are touching the block buffer, we must set the process permissions
SD_SET_PROC_PERMISSIONS_FROM_REQUEST(pRequest) {
// 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--;
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?