/////////////////////////////////////////////////////////////////////////////// // SDH_Write - the write entry point for the CE file system wrapper // Input: hOpenContext - the context from SDH_Open // pBuffer - the user's buffer // Count - the size of the transfer // Output: // Return: zero // Notes: Not used /////////////////////////////////////////////////////////////////////////////// DWORD SDH_Write(DWORD hOpenContext, LPCVOID pBuffer, DWORD Count) { DbgPrintZo(SDCARD_ZONE_FUNC, (TEXT("SDH: +-SDH_Write\n"))); return 0; }
/////////////////////////////////////////////////////////////////////////////// // SDH_Open - the open entry point for the bus driver // Input: hDeviceContext - the device context from SDH_Init // AccessCode - the desired access // ShareMode - the desired share mode // Output: // Return: 0 // Notes: not used /////////////////////////////////////////////////////////////////////////////// DWORD SDH_Open(DWORD hDeviceContext, DWORD AccessCode, DWORD ShareMode) { DbgPrintZo(SDCARD_ZONE_FUNC, (TEXT("SDH: +-SDH_Open\n"))); return 0; }
/////////////////////////////////////////////////////////////////////////////// // SDH_Seek - the seek entry point for the CE file system wrapper // Input: hOpenContext - the context from SDH_Open // Amount - the amount to seek // Type - the type of seek // Output: // Return: zero // Notes: not used /////////////////////////////////////////////////////////////////////////////// DWORD SDH_Seek(DWORD hOpenContext, long Amount, DWORD Type) { DbgPrintZo(SDCARD_ZONE_FUNC, (TEXT("SDH: +-SDH_Seek\n"))); return 0; }
/////////////////////////////////////////////////////////////////////////////// // SDH_IOControl - the I/O control entry point // Input: hOpenContext - the context returned from SDH_Open // dwCode - the ioctl code // pBufIn - the input buffer from the user // dwLenIn - the length of the input buffer // pBufOut - the output buffer from the user // dwLenOut - the length of the output buffer // pdwActualOut - the size of the transfer // Output: // Return: FALSE // Notes: Not used /////////////////////////////////////////////////////////////////////////////// BOOL SDH_IOControl(DWORD hOpenContext, DWORD dwCode, PBYTE pBufIn, DWORD dwLenIn, PBYTE pBufOut, DWORD dwLenOut, PDWORD pdwActualOut) { DbgPrintZo(SDCARD_ZONE_FUNC, (TEXT("SDH: +-SDH_IOControl \n"))); return FALSE;; }
/////////////////////////////////////////////////////////////////////////////// // SDH_PowerUp - the power up entry point // Input: hDeviceContext - the device context from SDH_Init // Output: // Notes: preforms no actions /////////////////////////////////////////////////////////////////////////////// void SDH_PowerUp(DWORD hDeviceContext) { PSDCARD_HC_CONTEXT pHostContext; PSDH_HARDWARE_CONTEXT pController; DbgPrintZo(SDCARD_ZONE_FUNC, (TEXT("SDH: +SDH_PowerDown\n"))); pHostContext = (PSDCARD_HC_CONTEXT)hDeviceContext; ASSERT( pHostContext ); if( pHostContext ) { pController = pHostContext->pHCSpecificContext; SDControllerPowerUp( pController ); } }
/////////////////////////////////////////////////////////////////////////////// // SDH_Deinit - the deinit entry point // Input: hDeviceContext - the context returned from SDH_Init // Output: // Return: always returns TRUE // Notes: /////////////////////////////////////////////////////////////////////////////// BOOL SDH_Deinit(DWORD hDeviceContext) { PSDCARD_HC_CONTEXT pHostContext; DbgPrintZo(SDCARD_ZONE_INIT, (TEXT("SDH: +SDH_Deinit\n"))); pHostContext = (PSDCARD_HC_CONTEXT)hDeviceContext; // deregister the host controller SDHCDDeregisterHostController(pHostContext); if( pHostContext && pHostContext->pHCSpecificContext ) { free( pHostContext->pHCSpecificContext ); } // cleanup the context SDHCDDeleteContext((PSDCARD_HC_CONTEXT)hDeviceContext); return TRUE; }
/////////////////////////////////////////////////////////////////////////////// // SDH_Close - the close entry point // Input: hOpenContext - the context returned from SDH_Open // Output: // Return: TRUE // Notes: not used /////////////////////////////////////////////////////////////////////////////// BOOL SDH_Close(DWORD hOpenContext) { DbgPrintZo(SDCARD_ZONE_FUNC, (TEXT("SDH: +-SDH_Close\n"))); return TRUE; }
/////////////////////////////////////////////////////////////////////////////// // SDH_Init - the init entry point // Input: dwContext - the context for this init // Output: // Return: returns instance context // Notes: /////////////////////////////////////////////////////////////////////////////// DWORD SDH_Init(DWORD dwContext) { PSDCARD_HC_CONTEXT pHostContext; // new HC context SD_API_STATUS status; // SD status PSDH_HARDWARE_CONTEXT pController; // new instance HKEY hKeyDevice; LPCTSTR pszActiveKey; DbgPrintZo(SDCARD_ZONE_INIT, (TEXT("SDH: +SDH_Init\n"))); DbgPrintZo(SDCARD_ZONE_INIT, (TEXT("SDH: Active RegPath: %s \n"), (PTSTR)dwContext)); pController = NULL; // allocate the context status = SDHCDAllocateContext(SDH_SLOTS, &pHostContext); if (!SD_API_SUCCESS(status)) { DbgPrintZo(SDCARD_ZONE_ERROR, (TEXT("SDH: Failed to allocate context : 0x%08X \n"), status)); return 0; } // create our extension pController = (PSDH_HARDWARE_CONTEXT)malloc( sizeof(SDH_HARDWARE_CONTEXT) ); if( pController == NULL ) { DbgPrintZo(SDCARD_ZONE_ERROR, (TEXT("SDH: Failed to allocate extension\n"))); return 0; } memset( pController, 0, sizeof(SDH_HARDWARE_CONTEXT) ); // Set our extension pHostContext->pHCSpecificContext = pController; pController = GetExtensionFromHCDContext(PSDH_HARDWARE_CONTEXT, pHostContext); pszActiveKey = (LPCTSTR) dwContext; pController->pszActiveKey = pszActiveKey; pController->hBusAccessHandle = CreateBusAccessHandle( pszActiveKey ); hKeyDevice = OpenDeviceKey(pszActiveKey); if (!hKeyDevice || !LoadRegistrySettings(hKeyDevice, pController) ) { DbgPrintZo(SDCARD_ZONE_ERROR, (TEXT("SDH: Failed load the registry settings\n"))); return 0; } RegCloseKey( hKeyDevice ); DbgPrintZo(SDCARD_ZONE_INIT, (TEXT("SDH: Real RegPath: %s \n"),pController->RegPath)); // save off the host context pController->pHCContext = pHostContext; // set the name SDHCDSetHCName(pHostContext, TEXT("Lubbock")); // set init handler SDHCDSetControllerInitHandler(pHostContext,SDInitialize); // set deinit handler SDHCDSetControllerDeinitHandler(pHostContext, SDDeinitialize); // set the bus request handler SDHCDSetBusRequestHandler(pHostContext,SDHBusRequestHandler); // set the cancel I/O handler SDHCDSetCancelIOHandler(pHostContext, SDHCancelIoHandler); // set the slot option handler SDHCDSetSlotOptionHandler(pHostContext, SDHSlotOptionHandler); // now register the host controller status = SDHCDRegisterHostController(pHostContext); if (!SD_API_SUCCESS(status)) { if( pController ) { free( pController ); } SDHCDDeleteContext(pHostContext); DbgPrintZo(SDCARD_ZONE_ERROR, (TEXT("SDH: Failed to register host controller: %0x08X \n"),status)); return 0; } DbgPrintZo(SDCARD_ZONE_INIT, (TEXT("SDH: -SDH_Init\n"))); // return the Host Controller context return (DWORD)pHostContext; }
/////////////////////////////////////////////////////////////////////////////// // SDSetCardFeature - Set card feature // Input: hDevice - SD Device Handle // CardFeature - Card Feature to set // StructureSize - size of card feature structure // Output: pCardInfo - Information for the feature // Return: SD_API_STATUS code // Notes: This function is provided to set various card features // in a thread safe manner. SDIO cards utilize shared register sets // between functions. This requires that the // register state be preserved between functions that can be // controlled in separate thread contexts. // This function can potentially block by issuing synchronous bus // request. This function must not be called from a bus request callback /////////////////////////////////////////////////////////////////////////////// SD_API_STATUS CSDDevice::SDSetCardFeature_I(SD_SET_FEATURE_TYPE CardFeature,PVOID pCardInfo,ULONG StructureSize) { SD_API_STATUS status = SD_API_STATUS_SUCCESS; // intermediate status PSD_DATA_TRANSFER_CLOCKS pClocks; // data transfer clocks variable switch (CardFeature) { case SD_IO_FUNCTION_ENABLE: if ((sizeof(SD_IO_FUNCTION_ENABLE_INFO) != StructureSize) || (NULL == pCardInfo)) { DEBUGMSG(SDCARD_ZONE_ERROR, (TEXT("SDSetCardFeature: SD_IO_FUNCTION_ENABLE - Invalid params \n"))); return SD_API_STATUS_INVALID_PARAMETER; } if (Device_SD_IO != m_DeviceType) { DEBUGMSG(SDCARD_ZONE_ERROR, (TEXT("SDSetCardFeature: device is not SDIO ! \n"))); return SD_API_STATUS_INVALID_PARAMETER; } status = SDEnableDisableFunction((PSD_IO_FUNCTION_ENABLE_INFO)pCardInfo, TRUE); break; case SD_IO_FUNCTION_DISABLE: if (Device_SD_IO != m_DeviceType) { DEBUGMSG(SDCARD_ZONE_ERROR, (TEXT("SDSetCardFeature: device is not SDIO ! \n"))); return SD_API_STATUS_INVALID_PARAMETER; } status = SDEnableDisableFunction(NULL, FALSE); break; case SD_IO_FUNCTION_HIGH_POWER: if (Device_SD_IO != m_DeviceType) { DEBUGMSG(SDCARD_ZONE_ERROR, (TEXT("SDSetCardFeature: device is not SDIO ! \n"))); return SD_API_STATUS_INVALID_PARAMETER; } status = SDFunctionSelectPower(FALSE); break; case SD_IO_FUNCTION_LOW_POWER: if (Device_SD_IO != m_DeviceType) { DEBUGMSG(SDCARD_ZONE_ERROR, (TEXT("SDSetCardFeature: device is not SDIO ! \n"))); return SD_API_STATUS_INVALID_PARAMETER; } status = SDFunctionSelectPower(TRUE); break; case SD_INFO_POWER_CONTROL_STATE: if ((sizeof(FUNCTION_POWER_STATE) != StructureSize) || (NULL == pCardInfo)) { DEBUGMSG(SDCARD_ZONE_ERROR, (TEXT("SDSetCardFeature: SD_INFO_POWER_CONTROL_STATE - Invalid params \n"))); return SD_API_STATUS_INVALID_PARAMETER; } if (Device_SD_IO != m_DeviceType) { DEBUGMSG(SDCARD_ZONE_ERROR, (TEXT("SDSetCardFeature: device is not SDIO ! \n"))); return SD_API_STATUS_INVALID_PARAMETER; } status = GetFunctionPowerState((PFUNCTION_POWER_STATE)pCardInfo); break; case SD_IO_FUNCTION_SET_BLOCK_SIZE: if ((sizeof(DWORD) != StructureSize) || (NULL == pCardInfo)) { DEBUGMSG(SDCARD_ZONE_ERROR, (TEXT("SDSetCardFeature: SD_IO_FUNCTION_SET_BLOCK_SIZE - Invalid params \n"))); return SD_API_STATUS_INVALID_PARAMETER; } if (Device_SD_IO != m_DeviceType) { DEBUGMSG(SDCARD_ZONE_ERROR, (TEXT("SDSetCardFeature: device is not SDIO ! \n"))); return SD_API_STATUS_INVALID_PARAMETER; } status = SDSetFunctionBlockSize(*((DWORD *)pCardInfo)); break; case SD_SET_DATA_TRANSFER_CLOCKS: if ((sizeof(SD_DATA_TRANSFER_CLOCKS) != StructureSize) || (NULL == pCardInfo)) { DEBUGMSG(SDCARD_ZONE_ERROR, (TEXT("SDSetCardFeature: SD_SET_DATA_TRANSFER_CLOCKS - Invalid params \n"))); return SD_API_STATUS_INVALID_PARAMETER; } pClocks = (PSD_DATA_TRANSFER_CLOCKS)pCardInfo; m_SDCardInfo.SDMMCInformation.DataAccessReadClocks = pClocks->ReadClocks; m_SDCardInfo.SDMMCInformation.DataAccessWriteClocks = pClocks->WriteClocks; status = SD_API_STATUS_SUCCESS; break; case SD_IS_FAST_PATH_AVAILABLE: status = SD_API_STATUS_SUCCESS; break; case SD_FAST_PATH_DISABLE: // Disable the use of Fast-Path for testing. m_SDCardInfo.SDIOInformation.Flags |= FSTPTH_DISABLE; status = SD_API_STATUS_SUCCESS; break; case SD_FAST_PATH_ENABLE: #ifdef _FASTPATH_ENABLE_ // Always use Fast-Path operations. m_SDCardInfo.SDIOInformation.Flags &= ~ FSTPTH_DISABLE; #else m_SDCardInfo.SDIOInformation.Flags |= FSTPTH_DISABLE; #endif status = SD_API_STATUS_SUCCESS; break; case SD_IS_SOFT_BLOCK_AVAILABLE: status = SD_API_STATUS_SUCCESS; break; case SD_SOFT_BLOCK_FORCE_UTILIZATION: // Always use Soft-Block operations. m_SDCardInfo.SDIOInformation.Flags |= SFTBLK_USE_ALWAYS; status = SD_API_STATUS_SUCCESS; break; case SD_SOFT_BLOCK_DEFAULT_UTILIZATON: // Use hardware multi-block operations if supported by the card, // otherwise use Soft-Block. m_SDCardInfo.SDIOInformation.Flags &= ~ SFTBLK_USE_ALWAYS; status = SD_API_STATUS_SUCCESS; break; case SD_SET_CARD_INTERFACE: { if ((sizeof(SD_CARD_INTERFACE) != StructureSize) || (NULL == pCardInfo)) { DEBUGMSG(SDCARD_ZONE_ERROR, (TEXT("SDSetCardFeature: SD_SET_CARD_INTERFACE - Invalid params \n"))); return SD_API_STATUS_INVALID_PARAMETER; } PSD_CARD_INTERFACE pCardInterface = (PSD_CARD_INTERFACE) pCardInfo ; SD_CARD_INTERFACE_EX sdCardInterfaceEx; memset (&sdCardInterfaceEx, 0, sizeof(sdCardInterfaceEx)); sdCardInterfaceEx.ClockRate = pCardInterface->ClockRate; sdCardInterfaceEx.InterfaceModeEx.bit.sdWriteProtected = (pCardInterface->WriteProtected?1:0); sdCardInterfaceEx.InterfaceModeEx.bit.sd4Bit = (pCardInterface->InterfaceMode == SD_INTERFACE_SD_4BIT?1:0) ; status =SetCardFeature_Interface(sdCardInterfaceEx); break; } case SD_SET_CARD_INTERFACE_EX: { if ((sizeof(SD_CARD_INTERFACE_EX) != StructureSize) || (NULL == pCardInfo)) { DEBUGMSG(SDCARD_ZONE_ERROR, (TEXT("SDSetCardFeature: SD_SET_CARD_INTERFACE_EX - Invalid params \n"))); return SD_API_STATUS_INVALID_PARAMETER; } status = SetCardFeature_Interface(*(PSD_CARD_INTERFACE_EX)pCardInfo); break; } case SD_SET_CLOCK_STATE_DURING_IDLE: if ( (sizeof(BOOL) != StructureSize) || (NULL == pCardInfo) ) { DEBUGMSG(SDCARD_ZONE_ERROR,(TEXT("SDSetCardFeature: SD_SET_CLOCK_ON_DURING_IDLE - Invalid params \n"))); return SD_API_STATUS_INVALID_PARAMETER; } // prompt the host to turn on or off the clock during the idle state based on the client's // request. status = m_sdSlot.GetHost().SlotOptionHandler(m_sdSlot.GetSlotIndex(), SDHCDSetClockStateDuringIdle, pCardInfo,StructureSize); DEBUGMSG(SDCARD_ZONE_INFO, (TEXT("SDSetCardFeature: SDHCDSetClockStateDuringIdle finished with status: %x\n"), status)); break; case SD_CARD_FORCE_RESET: DbgPrintZo(SDCARD_ZONE_INIT, (TEXT("SDSetCardFeature: call SD_CARD_FORCE_RESET \n"))); m_sdSlot.PostEvent(SlotResetRequest); break; case SD_CARD_SELECT_REQUEST: // request made by client driver to select the card. The request will not be honored // until all client drivers in this slot make such request. { BOOL bAllFunctionsRequestedCardSelect = TRUE;; DbgPrintZo(SDCARD_ZONE_INIT,(TEXT("SDSetCardFeature: call SD_CARD_SELECT_REQUEST \n"))); m_bCardSelectRequest = TRUE; NotifyClient(SDCardSelectRequest); for (DWORD dwIndex = 0; dwIndex < SD_MAXIMUM_DEVICE_PER_SLOT; dwIndex++) { CSDDevice * pDevice = m_sdSlot.GetFunctionDevice(dwIndex); if (pDevice != NULL) { if (pDevice->m_bCardSelectRequest == FALSE && pDevice->GetDeviceType()!= Device_Unknown ) { bAllFunctionsRequestedCardSelect = FALSE; } pDevice->DeRef(); } } if (bAllFunctionsRequestedCardSelect == FALSE) { DbgPrintZo(SDCARD_ZONE_INFO, (TEXT("SDSetCardFeature: SD_CARD_SELECT_REQUEST - request is pending\n"))); return SD_API_STATUS_PENDING; } DbgPrintZo(SDCARD_ZONE_INIT, (TEXT("SDSetCardFeature: SD_CARD_SELECT_REQUEST - request is processing\n"))); m_sdSlot.PostEvent(SlotSelectRequest); } break; case SD_CARD_DESELECT_REQUEST: { BOOL bAllFunctionsRequestedCardDeselect= TRUE;; DbgPrintZo(SDCARD_ZONE_INIT, (TEXT("SDSetCardFeature: call SD_CARD_DESELECT_REQUEST \n"))); if (!m_bCardDeselectRequest) { m_bCardDeselectRequest = TRUE; NotifyClient(SDCardDeselectRequest); } for (DWORD dwIndex = 0; dwIndex < SD_MAXIMUM_DEVICE_PER_SLOT; dwIndex++) { CSDDevice * pDevice = m_sdSlot.GetFunctionDevice(dwIndex); if (pDevice != NULL) { if (pDevice->m_bCardDeselectRequest == FALSE && pDevice->GetDeviceType()!= Device_Unknown) { bAllFunctionsRequestedCardDeselect = FALSE ; } pDevice->DeRef(); } } if (bAllFunctionsRequestedCardDeselect == FALSE) { DbgPrintZo(SDCARD_ZONE_INFO, (TEXT("SDSetCardFeature: SD_CARD_DESELECT_REQUEST - request is pending\n"))); return SD_API_STATUS_PENDING; } DbgPrintZo(SDCARD_ZONE_INIT, (TEXT("SDSetCardFeature: SD_CARD_DESELECT_REQUEST - request is processing\n"))); m_sdSlot.PostEvent(SlotDeselectRequest); } break; case SD_SET_SWITCH_FUNCTION: { if (pCardInfo!=NULL && StructureSize >= sizeof(SD_CARD_SWITCH_FUNCTION)) { PSD_CARD_SWITCH_FUNCTION psdSwitchFunction = (PSD_CARD_SWITCH_FUNCTION)pCardInfo; status = SwitchFunction((PSD_CARD_SWITCH_FUNCTION)pCardInfo,FALSE); } } break; case SD_DMA_ALLOC_PHYS_MEM: if (pCardInfo!=NULL && StructureSize >= sizeof(SD_HOST_ALLOC_FREE_DMA_BUFFER)) { status = m_sdSlot.GetHost().SlotOptionHandler(m_sdSlot.GetSlotIndex(),SDHCAllocateDMABuffer, pCardInfo,sizeof(SD_HOST_ALLOC_FREE_DMA_BUFFER)); } break; case SD_DMA_FREE_PHYS_MEM: if (pCardInfo!=NULL && StructureSize >= sizeof(SD_HOST_ALLOC_FREE_DMA_BUFFER)) { status = m_sdSlot.GetHost().SlotOptionHandler(m_sdSlot.GetSlotIndex(),SDHCFreeDMABuffer, pCardInfo,sizeof(SD_HOST_ALLOC_FREE_DMA_BUFFER)); } break; default: status = SD_API_STATUS_INVALID_PARAMETER; break; } return status; }
SD_API_STATUS CSDDevice::SetCardFeature_Interface(SD_CARD_INTERFACE_EX& CardInterfaceEx) { SD_API_STATUS status = SD_API_STATUS_SUCCESS; // intermediate status // Check if the slot can accept this interface request // For multifunction card or combo card, the requested interface may not be fitted // for other functions. { BOOL bAllFunctionsAcceptThisInterface = TRUE; // Start from parent device BOOL fContinue = TRUE; for (DWORD dwIndex = 0; dwIndex < SD_MAXIMUM_DEVICE_PER_SLOT && fContinue ; dwIndex++) { CSDDevice * pDevice = m_sdSlot.GetFunctionDevice(dwIndex); if (pDevice != NULL ) { if (dwIndex!=GetDeviceFuncionIndex() && pDevice->GetDeviceType() != Device_Unknown ) { // Check if current device supports 4 bit mode request if (CardInterfaceEx.InterfaceModeEx.bit.sd4Bit && !(pDevice->m_CardInterfaceEx.InterfaceModeEx.bit.sd4Bit)) { bAllFunctionsAcceptThisInterface = FALSE; fContinue = FALSE; } else // Check if request clock rate is too high for this device if (CardInterfaceEx.ClockRate > pDevice->m_CardInterfaceEx.ClockRate) { bAllFunctionsAcceptThisInterface = FALSE; fContinue = FALSE; } else if (!(CardInterfaceEx.InterfaceModeEx.bit.sdHighSpeed) && pDevice->m_CardInterfaceEx.InterfaceModeEx.bit.sdHighSpeed){ bAllFunctionsAcceptThisInterface = FALSE; fContinue = FALSE; } } pDevice->DeRef(); } } if (bAllFunctionsAcceptThisInterface == FALSE) { DbgPrintZo(SDCARD_ZONE_ERROR, (TEXT("SDSetCardFeature: SD_SET_CARD_INTERFACE - invalod interface request\n"))); return SD_API_STATUS_INVALID_DEVICE_REQUEST; } } // Changing the bus width is tricky when SDIO interrupts are // enabled. In 1-bit mode, DAT[1] is used as the interrupt line. // In 4-bit mode, DAT[1] is used for data and interrupts. If // we change from 1-bit mode to 4-bit mode while interrupts are // occurring (like when a BTH mouse is being moved franticly), we // need to disable SDIO interrupts while we are changing the mode // on both the host controller and the card. Otherwise an interrupt in // the middle could confuse the host controller. PSD_INTERRUPT_CALLBACK pInterruptCallBack = NULL; if ( (Device_SD_IO == m_DeviceType) && m_sdSlot.IsSlotInterruptOn() && (m_CardInterfaceEx.InterfaceModeEx.bit.sd4Bit != CardInterfaceEx.InterfaceModeEx.bit.sd4Bit) ) { // Temporarily disable SDIO interrupts pInterruptCallBack = m_SDCardInfo.SDIOInformation.pInterruptCallBack; DEBUGCHK(pInterruptCallBack); SDIOConnectDisconnectInterrupt( NULL, FALSE); } SD_CARD_INTERFACE_EX CardInterfaceExBackup = m_CardInterfaceEx; BOOL isRestore = FALSE; while (TRUE) { SD_API_STATUS inStatus = SD_API_STATUS_SUCCESS ; // check for success BOOL fContinue = TRUE; if (SD_API_SUCCESS(inStatus)) { // set the card interface for device's slot inStatus = m_sdSlot.GetHost().SlotSetupInterface(m_sdSlot.GetSlotIndex(),&CardInterfaceEx); //m_sdSlot.GetHost().SlotOptionHandler(m_sdSlot.GetSlotIndex(), SDHCDSetSlotInterface, &CardInterface, sizeof(CardInterface)); fContinue = SD_API_SUCCESS(inStatus) ; } for (DWORD dwIndex = 0; dwIndex < SD_MAXIMUM_DEVICE_PER_SLOT && fContinue; dwIndex++) { CSDDevice * pDevice = m_sdSlot.GetFunctionDevice(dwIndex); if (pDevice != NULL) { inStatus = pDevice->SetCardInterface(&CardInterfaceEx); if (!SD_API_SUCCESS(inStatus)) { fContinue = FALSE; } pDevice->DeRef(); } } if (!SD_API_SUCCESS(inStatus) &&!isRestore ) { ASSERT(FALSE); status = inStatus; CardInterfaceEx = CardInterfaceExBackup; isRestore = TRUE; } else break; } if (pInterruptCallBack) { // Re-enable SDIO interrupts DEBUGCHK(!m_sdSlot.IsSlotInterruptOn()); DEBUGCHK(Device_SD_IO == m_DeviceType); SDIOConnectDisconnectInterrupt(pInterruptCallBack, TRUE); } return status; }