📄 sdio_bus_misc.c
字号:
if (pHcd->CardProperties.Flags & (CARD_SD | CARD_MMC)) { if (0 == cardReportedRate) { /* extract rate from CSD only if it was not set by earlier tests */ cardReportedRate = ConvertEncodedTransSpeed( GET_SD_CSD_TRANS_SPEED(pHcd->CardProperties.CardCSD)); /* fall through and test for zero again */ } if (cardReportedRate != 0) { /* adjust clock based on what the card can handle */ ADJUST_OPER_CLOCK(pBusMode,cardReportedRate); } else {#ifdef DEBUG /* something is wrong with the CSD */ if (DBG_GET_DEBUG_LEVEL() >= SDDBG_TRACE) { SDLIB_PrintBuffer(pHcd->CardProperties.CardCSD, MAX_CARD_RESPONSE_BYTES, "SDIO Bus Driver: CSD Dump"); }#endif /* can't figure out the card rate, so set reasonable defaults */ if (pHcd->CardProperties.Flags & CARD_SD) { ADJUST_OPER_CLOCK(pBusMode,SD_MAX_BUS_CLOCK); } else { ADJUST_OPER_CLOCK(pBusMode,MMC_MAX_BUS_CLOCK); } } }#endif // CT_CONFIG_NO_SDMMC /* note, we do SDIO card "after" SD in case this is a combo card */ if (pHcd->CardProperties.Flags & CARD_SDIO) { /* read card capabilities */ status = Cmd52ReadByteCommon(pHcd->pPseudoDev, SDIO_CARD_CAPS_REG, &pHcd->CardProperties.SDIOCaps); if (!SDIO_SUCCESS(status)) { break; } DBG_PRINT(SDDBG_TRACE, ("SDIO Card Caps: 0x%X \n",pHcd->CardProperties.SDIOCaps)); if (pHcd->CardProperties.SDIOCaps & SDIO_CAPS_LOW_SPEED) { /* adjust max clock for LS device */ ADJUST_OPER_CLOCK(pBusMode,SDIO_LOW_SPEED_MAX_BUS_CLOCK); /* adjust bus if LS device does not support 4 bit mode */ if (!(pHcd->CardProperties.SDIOCaps & SDIO_CAPS_4BIT_LS)) { if (!spiMode) { /* low speed device does not support 4 bit mode, force us to 1 bit */ SDCONFIG_SET_BUS_WIDTH(pBusMode->BusModeFlags, SDCONFIG_BUS_WIDTH_1_BIT); } } } /* check if 1.2 card supports high speed mode, checking HCD as well*/ if (SDDEVICE_IS_SDIO_REV_GTEQ_1_20(pHcd->pPseudoDev) && (pHcd->Attributes & SDHCD_ATTRIB_SD_HIGH_SPEED) && !spiMode) { UCHAR hsControl = 0; status = Cmd52ReadByteCommon(pHcd->pPseudoDev, SDIO_HS_CONTROL_REG, &hsControl); if (!SDIO_SUCCESS(status)) { DBG_PRINT(SDDBG_TRACE, ("SDIO Failed to read high speed control (%d) \n",status)); /* reset status and continue */ status = SDIO_STATUS_SUCCESS; } else { if (hsControl & SDIO_HS_CONTROL_SHS) { DBG_PRINT(SDDBG_TRACE, ("SDIO Card Supports High Speed Mode\n")); pBusMode->BusModeFlags |= SDCONFIG_BUS_MODE_SD_HS; } } } cardReportedRate = 0; temp = sizeof(func0ext); tplAddr = pHcd->CardProperties.CommonCISPtr; /* get the FUNCE tuple */ status = SDLIB_FindTuple(pHcd->pPseudoDev, CISTPL_FUNCE, &tplAddr, (PUINT8)&func0ext, &temp); if (!SDIO_SUCCESS(status) || (temp < sizeof(func0ext))) { DBG_PRINT(SDDBG_WARN, ("SDIO Function 0 Ext. Tuple Missing (Got size:%d) \n", temp)); /* reset status */ status = SDIO_STATUS_SUCCESS; } else { /* convert encoded value to rate */ cardReportedRate = ConvertEncodedTransSpeed(func0ext.MaxTransSpeed); } if (cardReportedRate != 0) { if (pBusMode->BusModeFlags & SDCONFIG_BUS_MODE_SD_HS) { if (cardReportedRate <= SD_MAX_BUS_CLOCK) { DBG_PRINT(SDDBG_WARN, ("SDIO Function tuple reports clock:%d Hz, with advertised High Speed support \n", cardReportedRate)); /* back off high speed support */ pBusMode->BusModeFlags &= ~SDCONFIG_BUS_MODE_SD_HS; } } else { if (cardReportedRate > SD_MAX_BUS_CLOCK) { DBG_PRINT(SDDBG_WARN, ("SDIO Function tuple reports clock:%d Hz, without advertising High Speed support..using 25Mhz \n", cardReportedRate)); cardReportedRate = SD_MAX_BUS_CLOCK; } } /* adjust clock based on what the card can handle */ ADJUST_OPER_CLOCK(pBusMode,cardReportedRate); } else { /* set a reasonable default */ ADJUST_OPER_CLOCK(pBusMode,SD_MAX_BUS_CLOCK); } } } while (FALSE); if (pReq != NULL) { FreeRequest(pReq); } return status;}/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ SetOperationalBusMode - set operational bus mode Input: pDevice - pDevice that is requesting the change pBusMode - operational bus mode Output: pBusMode - on return will have the actual clock rate set Return: status Notes:++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/SDIO_STATUS SetOperationalBusMode(PSDDEVICE pDevice, PSDCONFIG_BUS_MODE_DATA pBusMode){ SDIO_STATUS status = SDIO_STATUS_SUCCESS; UCHAR regData; UINT32 arg; UINT32 switcharg; PSDHCD pHcd = pDevice->pHcd; /* synchronize access for updating bus mode settings */ status = SemaphorePendInterruptable(&pDevice->pHcd->ConfigureOpsSem); if (!SDIO_SUCCESS(status)) { return status; } do { if (!IS_CARD_PRESENT(pHcd)) { /* for an empty slot (a Pseudo dev was passed in) we still allow the * bus mode to be set for the card detect * polling */ status = _IssueConfig(pHcd,SDCONFIG_BUS_MODE_CTRL,pBusMode,sizeof(SDCONFIG_BUS_MODE_DATA)); if (!SDIO_SUCCESS(status)) { DBG_PRINT(SDDBG_ERROR, ("SDIO Bus Driver: Failed to set bus mode in hcd : Err:%d \n", status)); } /* nothing more to do */ break; } if ((pBusMode->BusModeFlags == SDDEVICE_GET_BUSMODE_FLAGS(pDevice)) && (pBusMode->ClockRate == SDDEVICE_GET_OPER_CLOCK(pDevice))) { DBG_PRINT(SDDBG_TRACE, ("SDIO Bus Driver: Bus mode already set, nothing to do\n")); pBusMode->ActualClockRate = SDDEVICE_GET_OPER_CLOCK(pDevice); break; }#ifndef CT_CONFIG_NO_SDMMC if (pBusMode->BusModeFlags & SDCONFIG_BUS_MODE_MMC_HS) { if (!(pHcd->Attributes & SDHCD_ATTRIB_MMC_HIGH_SPEED)) { status = SDIO_STATUS_INVALID_PARAMETER; DBG_PRINT(SDDBG_ERROR, ("SDIO Bus Driver: HCD does not support MMC High Speed\n")); break; } }#endif if (pBusMode->BusModeFlags & SDCONFIG_BUS_MODE_SD_HS) { if (!(pHcd->Attributes & SDHCD_ATTRIB_SD_HIGH_SPEED)) { status = SDIO_STATUS_INVALID_PARAMETER; DBG_PRINT(SDDBG_ERROR, ("SDIO Bus Driver: HCD does not support SD High Speed\n")); break; } }#ifndef CT_CONFIG_NO_SDMMC /* before we set the operational clock and mode, configure the clock for high * speed mode on the card , if necessary */ if ((pHcd->CardProperties.Flags & CARD_MMC) && (pBusMode->BusModeFlags & SDCONFIG_BUS_MODE_MMC_HS) && !(SDDEVICE_GET_BUSMODE_FLAGS(pDevice) & SDCONFIG_BUS_MODE_MMC_HS)) { switcharg = MMC_SWITCH_BUILD_ARG(MMC_SWITCH_CMD_SET0, MMC_SWITCH_WRITE_BYTE, MMC_EXT_HS_TIMING_OFFSET, MMC_EXT_HS_TIMING_ENABLE); status = _IssueSimpleBusRequest(pHcd, MMC_CMD_SWITCH, switcharg, SDREQ_FLAGS_RESP_R1B, NULL); if (!SDIO_SUCCESS(status)) { DBG_PRINT(SDDBG_ERROR, ("SDIO Bus Driver: Failed to switch MMC High Speed Mode (arg:0x%X): %d \n", switcharg, status)); break; } DBG_PRINT(SDDBG_TRACE, ("SDIO Bus Driver: High Speed MMC enabled (arg:0x%X)\n", switcharg)); }#endif#ifndef CT_CONFIG_NO_SDMMC /* before setting bus mode and clock in the HCD, switch card to high speed mode * if necessary */ if ((pHcd->CardProperties.Flags & CARD_SD) && (pBusMode->BusModeFlags & SDCONFIG_BUS_MODE_SD_HS) && !(SDDEVICE_GET_BUSMODE_FLAGS(pDevice) & SDCONFIG_BUS_MODE_SD_HS)) { UINT32 arg; PUINT8 pSwitchStatusBlock; pSwitchStatusBlock = KernelAlloc(SD_SWITCH_FUNC_STATUS_BLOCK_BYTES); if (NULL == pSwitchStatusBlock) { status = SDIO_STATUS_NO_RESOURCES; break; } /* set high speed group */ arg = SD_SWITCH_FUNC_ARG_GROUP_SET(SD_SWITCH_HIGH_SPEED_GROUP, SD_SWITCH_HIGH_SPEED_FUNC_NO); DBG_PRINT(SDDBG_TRACE, ("SDIO Bus Driver: Setting SD Card for High Speed mode (CMD6 arg:0x%X)\n",arg)); /* issue simple data transfer request to switch modes */ status = _IssueBusRequestBd(pHcd, CMD6, arg, SDREQ_FLAGS_RESP_R1 | SDREQ_FLAGS_DATA_TRANS, NULL, pSwitchStatusBlock, SD_SWITCH_FUNC_STATUS_BLOCK_BYTES); if (SDIO_SUCCESS(status)) { ReorderBuffer(pSwitchStatusBlock,SD_SWITCH_FUNC_STATUS_BLOCK_BYTES); DBG_PRINT(SDDBG_TRACE, ("SDIO Bus Driver: SD High Speed Result, Got Max Current:%d mA, SwitchResult:0x%X \n", SD_SWITCH_FUNC_STATUS_GET_MAX_CURRENT(pSwitchStatusBlock), SDSwitchGetSwitchResult(pSwitchStatusBlock, SD_SWITCH_HIGH_SPEED_GROUP))); if (SD_SWITCH_FUNC_STATUS_GET_MAX_CURRENT(pSwitchStatusBlock) == 0) { DBG_PRINT(SDDBG_ERROR, ("SDIO Bus Driver: Error in Status Block after High Speed Switch (current==0) \n")); status = SDIO_STATUS_DEVICE_ERROR; } if (SDSwitchGetSwitchResult(pSwitchStatusBlock, SD_SWITCH_HIGH_SPEED_GROUP) != SD_SWITCH_HIGH_SPEED_FUNC_NO) { DBG_PRINT(SDDBG_ERROR, ("SDIO Bus Driver: Error in Status Block after High Speed Switch (Group1 did not switch) \n")); status = SDIO_STATUS_DEVICE_ERROR; } if (SDIO_SUCCESS(status)) { DBG_PRINT(SDDBG_TRACE, ("SDIO Bus Driver: SD High Speed Mode Enabled \n")); } else { SDLIB_PrintBuffer(pSwitchStatusBlock, SD_SWITCH_FUNC_STATUS_BLOCK_BYTES, "SDIO Bus Driver: SD Switch Status Block Error"); } } else { DBG_PRINT(SDDBG_ERROR, ("SDIO Bus Driver: Failed to Set SD High Speed Mode (%d) \n",status)); } KernelFree(pSwitchStatusBlock); if (!SDIO_SUCCESS(status)) { break; } }#endif /* enable/disable high speed mode for SDIO card */ if (pHcd->CardProperties.Flags & CARD_SDIO) { BOOL doSet = TRUE; if ((pBusMode->BusModeFlags & SDCONFIG_BUS_MODE_SD_HS) && !(SDDEVICE_GET_BUSMODE_FLAGS(pDevice) & SDCONFIG_BUS_MODE_SD_HS)) { /* enable */ regData = SDIO_HS_CONTROL_EHS; } else if (!(pBusMode->BusModeFlags & SDCONFIG_BUS_MODE_SD_HS) && (SDDEVICE_GET_BUSMODE_FLAGS(pDevice) & SDCONFIG_BUS_MODE_SD_HS)) { /* disable */ regData = 0; } else { /* do nothing */ doSet = FALSE; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -