⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 sdhcslot.cpp

📁 SAMSUNG S3C6410 CPU BSP for winmobile6
💻 CPP
📖 第 1 页 / 共 5 页
字号:
		)
{
	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
	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();

	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();

#if 0
	BYTE bHostCtr = 0;
	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
	BYTE bHostCtr = 0;
	if (1 == pInterface->InterfaceModeEx.bit.hsmmc8Bit) {
		DEBUGMSG(SDCARD_ZONE_INIT, 
				(TEXT("SHCSDSlotOptionHandler - Setting for 8 bit mode\n")));
		RETAILMSG(1, 
				(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(1, 
				(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(1, 
				(TEXT("[HSMMC1] Setting for 4 bit mode , Clock Rate = %d Hz\n"),pInterface->ClockRate));
		bHostCtr |= HOSTCTL_DAT_WIDTH;
		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 > 26000000) || (pInterface->InterfaceModeEx.bit.sdHighSpeed!=0) )
	{
		RETAILMSG(1, (TEXT("[HSMMC1] Setting for high speed mode.\n")));
		bHostCtr |= HOSTCTL_HIGH_SPEED;
	}
#endif


	DEBUGMSG(SDCARD_ZONE_INIT, 
			(TEXT("SHCSDSlotOptionHandler - Setting Host Control Register %x \n"),bHostCtr));
	//    WriteByte(SDHC_HOST_CONTROL, 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;
			cps = (_CEDEVICE_POWER_STATE)D4;	// KYS
		}

		SetHardwarePowerState(cps);
	}

	BOOL fKeepPower = FALSE;
	if (m_fSleepsWithPower || m_cpsCurrent == D0) {
		DEBUGCHK(!m_fSleepsWithPower || m_cpsCurrent == D3);
		fKeepPower = 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);
	// 08.07.06 by KYS
	Start();
}


	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));
	RETAILMSG(0, (TEXT("CMD:%d\n"), pRequest->CommandCode));
	if (m_pCurrentRequest) { // We have outstand request.
		ASSERT(FALSE);
		IndicateBusRequestComplete(pRequest, SD_API_STATUS_CANCELED);
		m_pCurrentRequest = NULL;
	}
	if (!m_fCardPresent) {
		status= SD_API_STATUS_DEVICE_REMOVED;
	}
	else {
		WORD wIntSignals = ReadWord(SDHC_NORMAL_INT_SIGNAL_ENABLE);
		WriteWord(SDHC_NORMAL_INT_SIGNAL_ENABLE,0);
		m_fCurrentRequestFastPath = FALSE;
		m_pCurrentRequest = pRequest ;
		// if no data transfer involved, use FAST PATH
		if ((pRequest->SystemFlags & SD_FAST_PATH_AVAILABLE)!=0) { // Fastpath 
			m_fCurrentRequestFastPath = TRUE;
			status = SubmitBusRequestHandler( pRequest );

			if( status == SD_API_STATUS_PENDING ) { // Polling for completion.
				// 08.04.04 by KYS
				// To check the state on CARD INSERTED on Ch0, use IsCardPresent().
				BOOL fCardInserted = TRUE;
				while (m_pCurrentRequest && (ReadDword(SDHC_PRESENT_STATE) & STATE_CARD_INSERTED)!=0 ) {
					HandleInterrupt();
				}
				if(m_pCurrentRequest && fCardInserted) {
					// Time out , need to switch to asyn.it will call callback after this
					pRequest->SystemFlags &= ~SD_FAST_PATH_AVAILABLE;
					m_fCurrentRequestFastPath = FALSE;
				}
				else {	// Fastpass complete
					status = m_FastPathStatus;
					// 08.01.27 by KYS
					// Below added code clear before status of fastpath.
					m_FastPathStatus = 0;
					if (m_pCurrentRequest) {
						ASSERT(FALSE);
						status = SD_API_STATUS_DEVICE_REMOVED;
					}
				}
			}
			if (status == SD_API_STATUS_SUCCESS) {
				status = SD_API_STATUS_FAST_PATH_SUCCESS;
			}

			// 08.04.21 by KYS
			// if there is error case. We don't notify the callback function either So.
			//ASSERT(m_fCurrentRequestFastPath);
			//m_pCurrentRequest = NULL;
		}
		else  
			status = SubmitBusRequestHandler( pRequest );
		// 08.04.21 by KYS
		// if there is error case. We don't notify the callback function either So.
		//if (status!=SD_API_STATUS_PENDING) { // This one has been finished.
		if (status!=SD_API_STATUS_PENDING && m_pCurrentRequest) {
			m_fCurrentRequestFastPath = TRUE;
			IndicateBusRequestComplete(pRequest, status);
			//m_pCurrentRequest = NULL;
		}
		WriteWord(SDHC_NORMAL_INT_SIGNAL_ENABLE,wIntSignals);
	}
	return status;
}

SD_API_STATUS
CSDHCSlotBase::SubmitBusRequestHandler(
		PSD_BUS_REQUEST pRequest
		)
{
	SETFNAME();

	PREFAST_DEBUGCHK(pRequest);
	Validate();

	WORD            wRegCommand;
	SD_API_STATUS   status;
	WORD            wIntStatusEn;
	//  WORD			wIntSignalEn;	// KYS
	BOOL            fSuccess;

	DEBUGCHK(m_dwReadyInts == 0);
	DEBUGCHK(!m_fCommandCompleteOccurred);

	DEBUGMSG(SDHC_SEND_ZONE, (TEXT("%s CMD:%d\n"), pszFname, pRequest->CommandCode));

	// bypass CMD12 if AutoCMD12 was done by hardware
	if (pRequest->CommandCode == 12) {
		if (m_fAutoCMD12Success) {
			DEBUGMSG(SDHC_SEND_ZONE, 
					(TEXT("%s AutoCMD12 Succeeded, bypass CMD12.\n"), pszFname));
			// The response for Auto CMD12 is in a special area
			UNALIGNED DWORD *pdwResponseBuffer = 
				(PDWORD) (pRequest->CommandResponse.ResponseBuffer + 1); // Skip CRC
			*pdwResponseBuffer = ReadDword(SDHC_R6);
			IndicateBusRequestComplete(pRequest, SD_API_STATUS_SUCCESS);
			status = SD_API_STATUS_SUCCESS;
			goto EXIT;
		}
	}

	m_fAutoCMD12Success = FALSE;

	// initialize command register with command code
	wRegCommand = (pRequest->CommandCode << CMD_INDEX_SHIFT) & CMD_INDEX_MASK;

	// check for a response
	switch (pRequest->CommandResponse.ResponseType) {
		case NoResponse:
			break;

		case ResponseR2:
			wRegCommand |= CMD_RESPONSE_R2;
			break;

		case ResponseR3:
		case ResponseR4:
			wRegCommand |= CMD_RESPONSE_R3_R4;
			break;

		case ResponseR1:
		case ResponseR5:
		case ResponseR6:
		case ResponseR7:
			wRegCommand |= CMD_RESPONSE_R1_R5_R6_R7;
			break;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -