📄 sdcontrol.c
字号:
if ((SD_COMMAND == pRequest->TransferClass)) {
// set the length of the block
WRITE_MMC_REGISTER_DWORD(pController, MMC_BLKLEN, 0);
// set the number of blocks
WRITE_MMC_REGISTER_DWORD(pController, MMC_NOB, 0);
} else {
// its a command with a data phase
cmdatRegister |= MMC_CMDAT_DATA_EN;
// set the buffer index to the end of the buffer
pRequest->HCParam = 0;
// set the length of the block
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 can use DMA for data transfer
if( PrepareDmaTransfer( pController, pRequest ) )
{
cmdatRegister |= MMC_CMDAT_DMA_ENABLE;
pController->fDMATransfer = TRUE;
}
}
// 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("SDBusIssueRequest - 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 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("********* SDBusIssueRequest - MMC Status did not clear : 0x%08X \n"),
(mmcStatus & 0x0000003F)));
}
}
#endif
DbgPrintZo(SDH_SEND_ZONE, (TEXT("SDBusIssueRequest - Request Sent\n")));
return SD_API_STATUS_PENDING;
}
#define NUM_BYTE_FOR_FAST_PASS 0x1000
BOOL SDControllerISTHandler(PSDH_HARDWARE_CONTEXT pHCDevice, BOOL fTimeOut);
VOID HandleDMAInterrupt(PSDH_HARDWARE_CONTEXT pController);
///////////////////////////////////////////////////////////////////////////////
// SDHBusRequestHandler - bus request handler
// Input: pHostContext - host controller context
// Slot - slot the request is going on
// pRequest - the request
//
// Output:
// Return: SD_API_STATUS Code
// Notes: The request passed in is marked as uncancelable, this function
// has the option of making the outstanding request cancelable
//
///////////////////////////////////////////////////////////////////////////////
SD_API_STATUS SDHBusRequestHandler(PSDCARD_HC_CONTEXT pHCContext,
DWORD Slot,
PSD_BUS_REQUEST pRequest)
{
SD_API_STATUS status;
PSDH_HARDWARE_CONTEXT pController; // our controller
BOOL fHandled = FALSE;
const TCHAR inData[] = TEXT("SDHBusRequestHandler IN");
const TCHAR OutData[] = TEXT("SDHBusRequestHandler Out");
DEBUGMSG(SDCARD_ZONE_FUNC,(TEXT("+SDHBusRequestHandler pRequest=%x"),pRequest));
RETAILCELOG(_CeLogEnable,CELID_RAW_WCHAR, (PVOID)inData, sizeof(inData));
// get our extension
pController = GetExtensionFromHCDContext(PSDH_HARDWARE_CONTEXT, pHCContext);
ACQUIRE_LOCK(pController);
if ( pController->pCurrentRequest) { // We have outstand request.
ASSERT(FALSE);
IndicateBusRequestComplete(pHCContext, pRequest, SD_API_STATUS_CANCELED);
pController->pCurrentRequest = NULL;
}
pController->fCurrentRequestFastPath = FALSE;
pController->pCurrentRequest = pRequest ;
// if no data transfer involved, use FAST PATH
if ((pRequest->SystemFlags & SD_FAST_PATH_AVAILABLE) &&
!( SD_COMMAND != pRequest->TransferClass &&
pRequest->NumBlocks * pRequest->BlockSize >= pController->dwPollingModeSize)){ // We do fast path here.
pController->fCurrentRequestFastPath = TRUE;
InterruptMask(pController->dwSysintrSDMMC,TRUE);
InterruptMask(pController->dwDmaSysIntr,TRUE);
status = SDBusIssueRequest( pHCContext, Slot, pRequest );
if( status == SD_API_STATUS_PENDING ) { // Polling for completion.
while (pController->pCurrentRequest && IsCardPresent()) {
SDControllerISTHandler(pController, !IsCardPresent());
if ( pController->fDMATransfer && !pController->fDMATransferCancelled)
HandleDMAInterrupt(pController);
}
status = pController->FastPathStatus;
if (pController->pCurrentRequest) {
ASSERT(FALSE);
status = SD_API_STATUS_DEVICE_REMOVED;
pController->pCurrentRequest = NULL;
}
}
if (status == SD_API_STATUS_SUCCESS) {
status = SD_API_STATUS_FAST_PATH_SUCCESS;
}
InterruptMask(pController->dwDmaSysIntr,FALSE);
InterruptMask(pController->dwSysintrSDMMC,FALSE);
ASSERT(pController->fCurrentRequestFastPath);
fHandled = TRUE;
}
else {
pRequest->SystemFlags &= ~SD_FAST_PATH_AVAILABLE ;
status = SDBusIssueRequest( pHCContext, Slot, pRequest );
if (status!=SD_API_STATUS_PENDING) { // This has been completed.
pController->pCurrentRequest = NULL;
}
}
RELEASE_LOCK(pController);
RETAILCELOG(_CeLogEnable,CELID_RAW_WCHAR, (PVOID)OutData, sizeof(OutData));
DEBUGMSG(SDCARD_ZONE_FUNC,(TEXT("-SDHBusRequestHandler pRequest=%x"),pRequest));
return status;
}
///////////////////////////////////////////////////////////////////////////////
// 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 ( ( READ_MMC_REGISTER_DWORD( pController, MMC_STAT ) & 0x8000 ) &&
( READ_MMC_REGISTER_DWORD( pController, MMC_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
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -