📄 sdhcslot.cpp
字号:
PDWORD pdwVddSetting = (PDWORD) pData;
SetVoltage(*pdwVddSetting);
break;
}
case SDHCDSetSlotInterface: {
DEBUGCHK(cbData == sizeof(SD_CARD_INTERFACE));
PSD_CARD_INTERFACE pInterface = (PSD_CARD_INTERFACE) pData;
//-----------------------------------------------------------------
// 2007.10.08 D.Baek
#ifdef __MMCmicro_SUPPORT__
if(pInterface->IsMMCmicro == TRUE)
{
g_bIsMMCmicro = TRUE;
}else
{
g_bIsMMCmicro = FALSE;
}
#endif
//-----------------------------------------------------------------
DEBUGMSG(SDCARD_ZONE_INFO, (TEXT("CSDHCSlotBase::SlotOptionHandler: Clock Setting: %d\n"), pInterface->ClockRate));
RETAILMSG(CRC_DEBUG,(TEXT("CSDHCSlotBase::SlotOptionHandler -> SetInterface()\r\n"))); // jylee
SetInterface(pInterface);
RETAILMSG(0,(TEXT("CSDHCSlotBase::SlotOptionHandler -> SetInterface is exited\r\n"))); // jylee
break;
}
case SDHCDEnableSDIOInterrupts:
case SDHCDAckSDIOInterrupt:
EnableSDIOInterrupts(TRUE);
break;
case SDHCDDisableSDIOInterrupts:
EnableSDIOInterrupts(FALSE);
break;
case SDHCDGetWriteProtectStatus: {
DEBUGCHK(cbData == sizeof(SD_CARD_INTERFACE));
PSD_CARD_INTERFACE pInterface = (PSD_CARD_INTERFACE) pData;
// For the case of s3c6400
// PRESENT_STATE_REGISTER[19] = 0 : Write protected
// PRESENT_STATE_REGISTER[19] = 1 : Write enabled
// STATE_WRITE_PROTECT = 0x00080000
if(IsWriteProtected())
{
pInterface->WriteProtected = false;
}else
{
pInterface->WriteProtected = true;
}
RETAILMSG(0,(TEXT("Write Protected 0x%x\n"),(ReadDword(SDHC_PRESENT_STATE) & STATE_WRITE_PROTECT))); // jylee
RETAILMSG(0,(TEXT("Write Protected 0x%x \n"),pInterface->WriteProtected )); // jylee
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;
}
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));
}
}
RETAILMSG(CRC_DEBUG,(TEXT("[DetemineMaxClockRate] dwMaxClockRate = %d\n\r"),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
DEBUGCHK(caps.bits.MaxBlockLen < dim(sc_rgusBlockLen));
DWORD dwMaxBlockLen = sc_rgusBlockLen[caps.bits.MaxBlockLen];
DEBUGCHK(dwMaxBlockLen <= SDHC_MAX_BLOCK_LENGTH);
return dwMaxBlockLen;
}
DWORD
CSDHCSlotBase::DetermineTimeoutControl(
)
{
// We try to come as close to the desired timeout without going below it.
DEBUGCHK(m_pregDevice->IsOK());
SSDHC_CAPABILITIES caps = GetCapabilities();
// Determine the DAT line timeout divisor.
// We allow the registry to override what is in the capabilities register.
DWORD dwTimeoutClock = m_pregDevice->ValueDW(SDHC_TIMEOUT_FREQUENCY_KEY);
if (dwTimeoutClock == 0) {
dwTimeoutClock = caps.bits.TOFreq * 1000;
if (dwTimeoutClock == 0) {
dwTimeoutClock = SDHC_MAX_CLOCK_FREQUENCY;
DEBUGMSG(SDCARD_ZONE_ERROR,(_T("SDHC: No timeout frequency specified. Using default of %u\n"),dwTimeoutClock));
}
else if (caps.bits.TimeoutUnit == 1) {
// listing is in MHz, not KHz
dwTimeoutClock *= 1000;
}
}
DEBUGCHK(dwTimeoutClock != 0);
DWORD dwTimeoutInMS = m_pregDevice->ValueDW(SDHC_TIMEOUT_KEY, SDHC_DEFAULT_TIMEOUT);
DOUBLE dTimeoutControl = SdhcTimeoutSecondsToControl(dwTimeoutClock, dwTimeoutInMS / 1000.0);
DWORD dwTimeoutControl;
if (dTimeoutControl < 0) {
dwTimeoutControl = 0;
}
else {
dTimeoutControl = ceil(dTimeoutControl);
dwTimeoutControl= (DWORD) dTimeoutControl;
}
dwTimeoutControl = min(dwTimeoutControl, SDHC_TIMEOUT_CONTROL_MAX);
#ifdef DEBUG
{
TCHAR szTimeout[4];
DOUBLE dActualTimeout = SdhcTimeoutControlToSeconds(dwTimeoutClock,dwTimeoutControl);
_sntprintf(szTimeout, dim(szTimeout), _T("%0.1f"), dActualTimeout);
DEBUGCHK(szTimeout[dim(szTimeout) - 1] == 0);
szTimeout[dim(szTimeout) - 1] = 0; // Null-terminate
DEBUGMSG(SDCARD_ZONE_INIT, (_T("SDHC: Using timeout control value of 0x%x for %s seconds\n"),
dwTimeoutControl, szTimeout));
}
#endif
dwTimeoutControl = 0xe;
return dwTimeoutControl;
}
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();
RETAILMSG(0,(TEXT("CSDHCSlotBase::SetVoltage 0x%X\n"),dwVddSetting)); // jylee
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);
WriteByte(SDHC_POWER_CONTROL, ucVoltageSelection);
RETAILMSG(0,( // jylee
TEXT("CSDHCSlotBase::SetVoltage: Set SDHC_POWER_CONTROL reg = 0x%02x %d\n"),
ReadByte(SDHC_POWER_CONTROL),GetPowerSupplyRampUpMs()));
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 pInterface
)
{
PREFAST_DEBUGCHK(pInterface);
Validate();
BYTE hostctl = 0;
if (SD_INTERFACE_SD_MMC_1BIT == pInterface->InterfaceMode) {
DEBUGMSG(SDCARD_ZONE_INIT, (TEXT("SHCSDSlotOptionHandler - Setting for 1 bit mode \n\r")));
RETAILMSG(1,(TEXT("[HSMMC] Set to the 1 Bit Data Bus\r\n"))); // jylee
hostctl = 0;
m_f4BitMode = FALSE;
} else if (SD_INTERFACE_SD_4BIT == pInterface->InterfaceMode) {
DEBUGMSG(SDCARD_ZONE_INIT,
(TEXT("CSDHCSlotOptionHandler - Setting for 4 bit mode \n")));
RETAILMSG(1,(TEXT("[HSMMC] Set to the 4 Bit Data Bus\r\n"))); // jylee
hostctl |= HOSTCTL_DAT_WIDTH;
m_f4BitMode = TRUE;
} else if (SD_INTERFACE_MMC_8BIT == pInterface->InterfaceMode) {
DEBUGMSG(SDCARD_ZONE_INIT, (TEXT("SHCSDSlotOptionHandler - Setting for 8 bit mode \n")));
RETAILMSG(1,(TEXT("[HSMMC] Set to the 8 Bit Data Bus\r\n"))); // jylee
hostctl |= HOSTCTL_DAT_WIDTH_8BIT;
m_f4BitMode = TRUE;
}else {
DEBUGCHK(FALSE);
}
//--------------------------------------------------------------------------------------------
// 2007.09.01 D.Baek
// In the S3C6400, the high-speed enable bit of HOST_CONTROL register must be disabled
// even if the card inserted operates at high-speed mode. This is limited only to the S3C6400.
#if 0
if(pInterface->ClockRate > 25000000)
{
hostctl |= HOSTCTL_HIGHSPEED;
RETAILMSG(0,(TEXT("Set the \"High Speed Enable\" bit is set\r\n"))); // jylee
}
#endif
RETAILMSG(0,(TEXT("HOST_CONTROL : 0x%x\r\n"),hostctl)); // jylee
SetClockRate(&pInterface->ClockRate);
WriteByte(SDHC_HOST_CONTROL, hostctl);
}
VOID
CSDHCSlotBase::SetPowerState(
CEDEVICE_POWER_STATE cpsNew
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -