📄 sdhcslot.cpp
字号:
EnableSDIOInterrupts(FALSE);
break;
case SDHCDGetWriteProtectStatus: {
DEBUGCHK(cbData == sizeof(SD_CARD_INTERFACE));
PSD_CARD_INTERFACE pInterface = (PSD_CARD_INTERFACE) pData;
pInterface->WriteProtected = IsWriteProtected();
break;
}
case SDHCDQueryBlockCapability: {
DEBUGCHK(cbData == sizeof(SD_HOST_BLOCK_CAPABILITY));
PSD_HOST_BLOCK_CAPABILITY pBlockCaps =
(PSD_HOST_BLOCK_CAPABILITY)pData;
DEBUGMSG(SDCARD_ZONE_INFO,
(TEXT("CSDHCSlotBase::SlotOptionHandler: Read Block Length: %d , Read Blocks: %d\n"),
pBlockCaps->ReadBlockSize, pBlockCaps->ReadBlocks));
DEBUGMSG(SDCARD_ZONE_INFO,
(TEXT("CSDHCSlotBase::SlotOptionHandler: Write Block Length: %d , Write Blocks: %d\n"),
pBlockCaps->WriteBlockSize, pBlockCaps->WriteBlocks));
pBlockCaps->ReadBlockSize = max(pBlockCaps->ReadBlockSize, SDHC_MIN_BLOCK_LENGTH);
pBlockCaps->ReadBlockSize = min(pBlockCaps->ReadBlockSize, (USHORT) m_dwMaxBlockLen);
pBlockCaps->WriteBlockSize = max(pBlockCaps->WriteBlockSize, SDHC_MIN_BLOCK_LENGTH);
pBlockCaps->WriteBlockSize = min(pBlockCaps->WriteBlockSize, (USHORT) m_dwMaxBlockLen);
break;
}
case SDHCDGetSlotPowerState: {
DEBUGCHK(cbData == sizeof(CEDEVICE_POWER_STATE));
PCEDEVICE_POWER_STATE pcps = (PCEDEVICE_POWER_STATE) pData;
*pcps = GetPowerState();
break;
}
case SDHCDSetSlotPowerState: {
DEBUGCHK(cbData == sizeof(CEDEVICE_POWER_STATE));
PCEDEVICE_POWER_STATE pcps = (PCEDEVICE_POWER_STATE) pData;
SetPowerState(*pcps);
break;
}
case SDHCDWakeOnSDIOInterrupts: {
DEBUGCHK(cbData == sizeof(BOOL));
PBOOL pfWake = (PBOOL) pData;
if (m_fCanWakeOnSDIOInterrupts) {
DWORD dwWakeupControl = m_dwDefaultWakeupControl;
if (*pfWake) {
dwWakeupControl |= WAKEUP_INTERRUPT;
}
m_bWakeupControl = (BYTE) dwWakeupControl;
}
else {
status = SD_API_STATUS_UNSUCCESSFUL;
}
break;
}
case SDHCDGetSlotInfo: {
DEBUGCHK(cbData == sizeof(SDCARD_HC_SLOT_INFO));
PSDCARD_HC_SLOT_INFO pSlotInfo = (PSDCARD_HC_SLOT_INFO) pData;
status = GetSlotInfo(pSlotInfo);
break;
}
case SDHCAllocateDMABuffer: {
DEBUGCHK (cbData == sizeof(SD_HOST_ALLOC_FREE_DMA_BUFFER));
PREFAST_ASSERT(pData!=NULL);
PSD_HOST_ALLOC_FREE_DMA_BUFFER pSdDmaBuffer = (PSD_HOST_ALLOC_FREE_DMA_BUFFER)pData;
pSdDmaBuffer->VirtualAddress =
SlotAllocDMABuffer(pSdDmaBuffer->Length, &pSdDmaBuffer->LogicalAddress,pSdDmaBuffer->CacheEnabled);
status = (pSdDmaBuffer->VirtualAddress!=NULL? SD_API_STATUS_SUCCESS: SD_API_STATUS_BUFFER_OVERFLOW);
break;
}
case SDHCFreeDMABuffer:{
DEBUGCHK (cbData == sizeof(SD_HOST_ALLOC_FREE_DMA_BUFFER));
PSD_HOST_ALLOC_FREE_DMA_BUFFER pSdDmaBuffer = (PSD_HOST_ALLOC_FREE_DMA_BUFFER)pData;
BOOL fResult =
SlotFreeDMABuffer(pSdDmaBuffer->Length, pSdDmaBuffer->LogicalAddress,pSdDmaBuffer->VirtualAddress,pSdDmaBuffer->CacheEnabled);
status = (fResult? SD_API_STATUS_SUCCESS: SD_API_STATUS_INVALID_PARAMETER);
break;
}
default:
status = SD_API_STATUS_INVALID_PARAMETER;
}
return status;
}
DWORD
CSDHCSlotBase::DetermineMaxClockRate(
)
{
DEBUGCHK(m_pregDevice->IsOK());
// We allow the registry to override what is in the capabilities register.
DWORD dwMaxClockRate = m_pregDevice->ValueDW(SDHC_FREQUENCY_KEY);
if (dwMaxClockRate == 0) {
SSDHC_CAPABILITIES caps = GetCapabilities();
dwMaxClockRate = caps.bits.ClkFreq * 1000000;
if (dwMaxClockRate == 0) {
// No clock frequency specified. Use the highest possible that
// could have been specified so that a working clock divisor
// will be chosen.
dwMaxClockRate = SDHC_MAX_CLOCK_FREQUENCY;
DEBUGMSG(SDCARD_ZONE_ERROR, (TEXT("SDHC: No base clock frequency specified\n")));
DEBUGMSG(SDCARD_ZONE_ERROR, (TEXT("SDHC: Using default frequency of %u\n"),
dwMaxClockRate));
}
}
return dwMaxClockRate;
}
DWORD
CSDHCSlotBase::DetermineMaxBlockLen(
)
{
static const USHORT sc_rgusBlockLen[] = {
SDHC_CAPABILITIES_MAX_BLOCK_LENGTH_0,
SDHC_CAPABILITIES_MAX_BLOCK_LENGTH_1,
SDHC_CAPABILITIES_MAX_BLOCK_LENGTH_2
};
SSDHC_CAPABILITIES caps = GetCapabilities();
// Determine the maximum block length
DWORD dwMaxBlockLen;
if (caps.bits.MaxBlockLen < _countof(sc_rgusBlockLen)) {
dwMaxBlockLen = sc_rgusBlockLen[caps.bits.MaxBlockLen];
}
else { // We hit reserved bit by Standard SDHC specification. So, it is better to returns smallest one.
ASSERT(FALSE);
dwMaxBlockLen = SDHC_CAPABILITIES_MAX_BLOCK_LENGTH_0 ;
}
return dwMaxBlockLen;
}
DWORD
CSDHCSlotBase::DetermineTimeoutControl(
)
{
DEBUGCHK(m_pregDevice->IsOK());
return SDHC_TIMEOUT_CONTROL_MAX;
}
DWORD
CSDHCSlotBase::DetermineWakeupSources(
)
{
DEBUGCHK(m_pregDevice->IsOK());
DWORD dwWakeupSources = m_pregDevice->ValueDW(SDHC_WAKEUP_SOURCES_KEY);
dwWakeupSources &= WAKEUP_ALL_SOURCES;
// Waking on SDIO interrupts must be enabled by the bus driver.
dwWakeupSources &= ~WAKEUP_INTERRUPT;
return dwWakeupSources;
}
VOID
CSDHCSlotBase::SetVoltage(
DWORD dwVddSetting
)
{
Validate();
UCHAR ucVoltageSelection = SDBUS_POWER_ON;
UCHAR ucOldVoltage;
DEBUGCHK(dwVddSetting & m_dwVddWindows);
if ( dwVddSetting &
(SD_VDD_WINDOW_3_2_TO_3_3 | SD_VDD_WINDOW_3_3_TO_3_4) ) {
ucVoltageSelection |= SDBUS_VOLTAGE_SELECT_3_3V;
}
else if ( dwVddSetting &
(SD_VDD_WINDOW_2_9_TO_3_0 | SD_VDD_WINDOW_3_0_TO_3_1) ) {
ucVoltageSelection |= SDBUS_VOLTAGE_SELECT_3_0V;
}
else if ( dwVddSetting &
(SD_VDD_WINDOW_1_7_TO_1_8 | SD_VDD_WINDOW_1_8_TO_1_9) ) {
ucVoltageSelection |= SDBUS_VOLTAGE_SELECT_1_8V;
}
ucOldVoltage = ReadByte(SDHC_POWER_CONTROL);
if (ucOldVoltage != ucVoltageSelection) {
// SD Bus Power must be initially set to 0 when changing voltages
WriteByte(SDHC_POWER_CONTROL, 0);
WriteByte(SDHC_POWER_CONTROL, ucVoltageSelection);
DEBUGMSG(SDCARD_ZONE_INFO,(
TEXT("CSDHCSlotBase::SetVoltage: Set SDHC_POWER_CONTROL reg = 0x%02x\n"),
ucVoltageSelection));
Sleep(GetPowerSupplyRampUpMs());
}
}
// Set up the controller according to the interface parameters.
VOID
CSDHCSlotBase::SetInterface(
PSD_CARD_INTERFACE_EX pInterface
)
{
PREFAST_DEBUGCHK(pInterface);
Validate();
BYTE bHostCtr = 0;
#ifdef _MMC_SPEC_42_
if (0 != pInterface->InterfaceModeEx.bit.hsmmc8Bit) {
DEBUGMSG(SDCARD_ZONE_INIT,
(TEXT("SHCSDSlotOptionHandler - Setting for 8 bit mode\n")));
RETAILMSG(TRUE,
(TEXT("[HSMMC1] Setting for 8 bit mode , Clock Rate = %d Hz\n"),pInterface->ClockRate));
bHostCtr |= HOSTCTL_DAT_WIDTH_8BIT;
m_f4BitMode = TRUE;
} else if (SD_INTERFACE_SD_MMC_1BIT == pInterface->InterfaceModeEx.bit.sd4Bit) {
DEBUGMSG(SDCARD_ZONE_INIT,
(TEXT("SHCSDSlotOptionHandler - Setting for 1 bit mode\n")));
RETAILMSG(TRUE,
(TEXT("[HSMMC1] Setting for 1 bit mode , Clock Rate = %d Hz\n"),pInterface->ClockRate));
bHostCtr = 0;
m_f4BitMode = FALSE;
} else if (SD_INTERFACE_SD_4BIT == pInterface->InterfaceModeEx.bit.sd4Bit) {
DEBUGMSG(SDCARD_ZONE_INIT,
(TEXT("SHCSDSlotOptionHandler - Setting for 4 bit mode\n")));
RETAILMSG(TRUE,
(TEXT("[HSMMC1] Setting for 4 bit mode , Clock Rate = %d Hz\n"),pInterface->ClockRate));
bHostCtr |= HOSTCTL_DAT_WIDTH;
m_f4BitMode = TRUE;
}
#else
m_f4BitMode = (pInterface->InterfaceModeEx.bit.sd4Bit!=0);
bHostCtr |= (m_f4BitMode?HOSTCTL_DAT_WIDTH:0);
bHostCtr |= (pInterface->InterfaceModeEx.bit.sdHighSpeed!=0?HOSTCTL_HIGH_SPEED:0);
#endif
if (m_SlotDma) {
bHostCtr |= (m_SlotDma->DmaSelectBit()<<3);
}
DEBUGMSG(SDCARD_ZONE_INIT,
(TEXT("SHCSDSlotOptionHandler - Setting Host Control Register %x \n"),bHostCtr));
WriteByte(SDHC_HOST_CONTROL, bHostCtr);
SetClockRate(&pInterface->ClockRate);
}
VOID
CSDHCSlotBase::SetPowerState(
CEDEVICE_POWER_STATE cpsNew
)
{
DEBUGCHK(VALID_DX(cpsNew));
m_fIsPowerManaged = TRUE;
if (DX_D1_OR_D2(cpsNew)) {
cpsNew = D0;
}
if (m_cpsCurrent != cpsNew) {
SetHardwarePowerState(cpsNew);
}
}
VOID
CSDHCSlotBase::PowerDown(
)
{
Validate();
m_cpsAtPowerDown = m_cpsCurrent;
if (!m_fIsPowerManaged) {
CEDEVICE_POWER_STATE cps;
if (m_bWakeupControl) {
cps = D3;
}
else {
cps = D4;
}
SetHardwarePowerState(cps);
}
BOOL fKeepPower = FALSE;
if (m_fSleepsWithPower || m_cpsCurrent == D0) {
DEBUGCHK(!m_fSleepsWithPower || m_cpsCurrent == D3);
fKeepPower = TRUE;
}
else
m_fFakeCardRemoval = TRUE;
PowerUpDown(FALSE, fKeepPower);
}
VOID
CSDHCSlotBase::PowerUp(
)
{
Validate();
if (!m_fIsPowerManaged) {
SetHardwarePowerState(m_cpsAtPowerDown);
}
else if (m_fSleepsWithPower) {
WORD wIntStatus = ReadWord(SDHC_NORMAL_INT_STATUS);
if (wIntStatus == NORMAL_INT_STATUS_CARD_INT) {
// We woke system through a card interrupt. We need to clear
// this so that the IST will not be signalled.
EnableSDIOInterrupts(FALSE);
m_fPowerUpDisabledInts = TRUE;
}
}
PowerUpDown(TRUE, TRUE);
if (m_fFakeCardRemoval){
Start();
SetInterruptEvent();
}
}
//
// For BC,
// 1. Returns SD_API_STATUS_FAST_PATH_SUCCESS, callback is NOT called. Fastpass only.
// 2. Return !SD_API_SUCCESS(status). callback is NOT called.
// 3. Return SD_API_STATUS_SUCCESS, callback is called
// 4. Return SD_API_STATUS_PENDING, callback is NOT call Yet.
//
SD_API_STATUS
CSDHCSlotBase::BusRequestHandler( PSD_BUS_REQUEST pRequest)
{
SETFNAME();
SD_API_STATUS status;
PREFAST_DEBUGCHK(pRequest);
Validate();
DEBUGMSG(SDHC_SEND_ZONE, (TEXT("%s CMD:%d\n"), pszFname, pRequest->CommandCode));
if (m_pCurrentRequest) { // We have outstand request.
ASSERT(FALSE);
IndicateBusRequestComplete(pRequest, SD_API_STATUS_CANCELED);
m_pCurrentRequest = NULL;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -