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

📄 sdhcslot.cpp

📁 SAMSUNG S3C6410 CPU BSP for winmobile6
💻 CPP
📖 第 1 页 / 共 5 页
字号:
				fUsingIntermediateBuffer = TRUE;
			}

			DWORD dwDwordsRemaining = cDwords;
			pRequest->HCParam += dwDwordsRemaining * 4;

			// Read the data from the device
			while ( dwDwordsRemaining-- ) {
				*(pdwBuffer++) = ReadDword(SDHC_BUFFER_DATA_PORT_0);
			}

			if ( dwRemainder != 0 ) {
				DWORD dwLastWord = ReadDword(SDHC_BUFFER_DATA_PORT_0);
				memcpy(pdwBuffer, &dwLastWord, dwRemainder);
				pRequest->HCParam += dwRemainder;
			}

			if (fUsingIntermediateBuffer) {
				memcpy(pdwUserBuffer, rgdwIntermediateBuffer, pRequest->BlockSize);
			}

			SetKMode( fKMode );
			SetProcPermissions(dwOldPermissions);
		}
		__except(SDProcessException(GetExceptionInformation())) {
			DEBUGMSG(SDCARD_ZONE_ERROR, (_T("Exception reading from client buffer!\r\n")));
			SetKMode( fKMode );
			SetProcPermissions(dwOldPermissions);
			IndicateBusRequestComplete(pRequest, SD_API_STATUS_ACCESS_VIOLATION);
		}

		DEBUGCHK(pRequest->HCParam == (m_dwReadyInts * pRequest->BlockSize));
	}
	// else request must have been canceled due to an error
}


VOID 
CSDHCSlotBase::HandleWriteReady(
		)
{    
	DEBUGMSG(SDHC_TRANSMIT_ZONE, (TEXT("HandleWriteReady - HandleWriteReady! \n"))); 

	// get the current request  
	PSD_BUS_REQUEST pRequest = GetAndLockCurrentRequest();

	if (pRequest) {
		DEBUGCHK(TRANSFER_IS_WRITE(pRequest));
		DEBUGCHK(!UseDmaForRequest(pRequest));
		DEBUGCHK(pRequest->NumBlocks > 0);
		DEBUGCHK(pRequest->HCParam < TRANSFER_SIZE(pRequest));

#ifdef DEBUG
		++m_dwReadyInts;
#endif

		DWORD dwOldPermissions = SetProcPermissions(pRequest->CurrentPermissions);
		BOOL fKMode = SetKMode( TRUE );

		__try {
			PDWORD pdwUserBuffer = (PDWORD) &pRequest->pBlockBuffer[pRequest->HCParam];
			PDWORD pdwBuffer = pdwUserBuffer;
			DWORD  rgdwIntermediateBuffer[SDHC_MAX_BLOCK_LENGTH / sizeof(DWORD)];
			BOOL   fUsingIntermediateBuffer = FALSE;
			DWORD  cDwords = pRequest->BlockSize / 4;
			DWORD  dwRemainder = pRequest->BlockSize % 4;

			PREFAST_DEBUGCHK(sizeof(rgdwIntermediateBuffer) >= pRequest->BlockSize);

			if (((DWORD) pdwUserBuffer) % 4 != 0) {
				// Buffer is not DWORD aligned so we must use an
				// intermediate buffer.
				pdwBuffer = rgdwIntermediateBuffer;
				memcpy(rgdwIntermediateBuffer, pdwUserBuffer, pRequest->BlockSize);
			}

			DWORD dwDwordsRemaining = cDwords;
			pRequest->HCParam += dwDwordsRemaining * 4;

			// Write data to buffer data port
			while ( dwDwordsRemaining-- ) {
				WriteDword(SDHC_BUFFER_DATA_PORT_0, *(pdwBuffer++));
			}

			if ( dwRemainder != 0 ) {
				DWORD dwLastWord = 0;
				memcpy(&dwLastWord, pdwBuffer, dwRemainder);
				WriteDword(SDHC_BUFFER_DATA_PORT_0, dwLastWord);
				pRequest->HCParam += dwRemainder;
			}

			SetKMode( fKMode );
			SetProcPermissions(dwOldPermissions);
		}
		__except(SDProcessException(GetExceptionInformation())) {
			DEBUGMSG(SDCARD_ZONE_ERROR, (_T("Exception reading from client buffer!\r\n")));
			SetKMode( fKMode );
			SetProcPermissions(dwOldPermissions);
			IndicateBusRequestComplete(pRequest, SD_API_STATUS_ACCESS_VIOLATION);
		}

		DEBUGCHK(pRequest->HCParam == (m_dwReadyInts * pRequest->BlockSize));
	}
	// else request must have been canceled due to an error
}


VOID 
CSDHCSlotBase::HandleDma(
		)
{
	// Get the current request
	PSD_BUS_REQUEST pRequest = GetAndLockCurrentRequest();

	if (pRequest) {
		DEBUGCHK(pRequest->NumBlocks > 0);
		DEBUGCHK(UseDmaForRequest(pRequest));

		DWORD dwNewHCParam = pRequest->HCParam + CB_DMA_PAGE;

		// Only update our transferred count if we have not completed the
		// transfer already, since some host controllers give an extra
		// DMA interrupt after the last block transfer.
		if (dwNewHCParam < TRANSFER_SIZE(pRequest)) {
			pRequest->HCParam = dwNewHCParam;
			DWORD paCurrDmaBuffer = m_paDmaBuffer + pRequest->HCParam;
			DEBUGCHK( paCurrDmaBuffer < (m_paDmaBuffer + CB_DMA_BUFFER) );
			DEBUGCHK( paCurrDmaBuffer < (m_paDmaBuffer + TRANSFER_SIZE(pRequest)) );
			DEBUGCHK( paCurrDmaBuffer == ReadDword(SDHC_SYSTEMADDRESS_LO) );

			WriteDword(SDHC_SYSTEMADDRESS_LO, paCurrDmaBuffer);
		}
	}
	// else request must have been canceled due to an error
}


BOOL 
CSDHCSlotBase::UseDmaForRequest(
		PSD_BUS_REQUEST pRequest
		)
{
	PREFAST_DEBUGCHK(pRequest);

	BOOL fRet = FALSE;

	if (m_pbDmaBuffer) {
		DEBUGCHK(m_paDmaBuffer);

		if ( (pRequest->BlockSize % 4 == 0) &&
				(TRANSFER_SIZE(pRequest) <= CB_DMA_BUFFER) ) {
			DEBUGCHK(m_paDmaBuffer % 4 == 0);
			//DEBUGCHK(PAGE_SIZE == CB_DMA_PAGE);
			DEBUGCHK((PAGE_SIZE*32) == CB_DMA_PAGE);
			fRet = TRUE;
		}
	}

	return fRet;
}


PVOID
CSDHCSlotBase::AllocPhysBuffer(
		size_t cb,
		PDWORD pdwPhysAddr
		)
{
	PVOID pvUncached;
	PVOID pvRet = NULL;
	DWORD dwPhysAddr;

	pvUncached = AllocPhysMem(cb, PAGE_READWRITE, 0, 0, &dwPhysAddr);

	if (pvUncached) {
		*pdwPhysAddr = dwPhysAddr;
		pvRet = pvUncached;
	}

	return pvRet;
}


VOID
CSDHCSlotBase::FreePhysBuffer(
		PVOID pv
		)
{
	BOOL fSuccess;

	DEBUGCHK(pv);

	fSuccess = FreePhysMem(pv);
	DEBUGCHK(fSuccess);
}


VOID
CSDHCSlotBase::SetHardwarePowerState(
		CEDEVICE_POWER_STATE cpsNew
		)
{
	DEBUGCHK(VALID_DX(cpsNew));
	DEBUGCHK(!DX_D1_OR_D2(cpsNew));

	DEBUGCHK(m_cpsCurrent != cpsNew);
	CEDEVICE_POWER_STATE cpsCurrent = m_cpsCurrent;
	m_cpsCurrent = cpsNew;
	BYTE bWakeupControl = m_bWakeupControl;

	if (cpsCurrent == D0) {
		SDClockOff();

		if (cpsNew == D3) {
			if ( m_fSDIOInterruptsEnabled &&  
					(bWakeupControl & WAKEUP_INTERRUPT) ) {
				DEBUGCHK(m_fCardPresent);
				m_fSleepsWithPower = TRUE;
				m_fPowerUpDisabledInts = FALSE;
			}
			else {
				// Wake on status changes only
				WriteByte(SDHC_POWER_CONTROL, 0);
				bWakeupControl &= ~WAKEUP_INTERRUPT;
			}

			// enable wakeup sources
			m_wIntSignals = ReadWord(SDHC_NORMAL_INT_SIGNAL_ENABLE);
			WriteWord(SDHC_NORMAL_INT_SIGNAL_ENABLE, 0);
			WriteWord(SDHC_NORMAL_INT_STATUS, ReadWord(SDHC_NORMAL_INT_STATUS));
			WriteByte(SDHC_WAKEUP_CONTROL, bWakeupControl);
		}
		else {
			DEBUGCHK(cpsNew == D4);
			WriteByte(SDHC_CLOCK_CONTROL, 0);
			WriteByte(SDHC_POWER_CONTROL, 0);
		}
	}
	else if (cpsCurrent == D3) {
		// Coming out of wakeup state
		if (cpsNew == D0) {            
			WriteByte(SDHC_WAKEUP_CONTROL, 0);

			if (!m_fSleepsWithPower) {
				// Power was turned off to the socket. Re-enumerate card.
				if (m_fCardPresent) {
					HandleRemoval(TRUE);
				}

				m_fCheckSlot = TRUE;
				SetInterruptEvent();
			}
			else {
				if (m_fCardPresent) {
					// Do not do this if the card was removed or 
					// if power was not kept.
					if (m_fPowerUpDisabledInts) {
						EnableSDIOInterrupts(TRUE);
					}
				}
			}

			WriteWord(SDHC_NORMAL_INT_SIGNAL_ENABLE, m_wIntSignals);
		}
		else {
			DEBUGCHK(cpsNew == D4);
			WriteByte(SDHC_CLOCK_CONTROL, 0);
			WriteByte(SDHC_WAKEUP_CONTROL, 0);
			WriteByte(SDHC_POWER_CONTROL, 0);
			WriteWord(SDHC_NORMAL_INT_SIGNAL_ENABLE, m_wIntSignals);
		}

		m_fSleepsWithPower = FALSE;
	}
	else {
		DEBUGCHK(cpsCurrent == D4);

		// Coming out of unpowered state - signal card removal
		// so any card present will be re-enumerated.
		//
		// We do the same thing when we go to D3 as D0 because
		// the slot has lost power so it could have been removed
		// or changed. In other words, D3 is a meaningless state
		// after D4.
		m_cpsCurrent = D0; // Force to D0

		// Do not call HandleRemoval here because it could cause
		// a context switch in a PowerUp callback.
		m_fFakeCardRemoval = TRUE;

		m_fCheckSlot = TRUE;
		SetInterruptEvent();
	}
}


// 08.02.03 by KYS
// In order to prevent infinite CARD INT occuring, below code is needed because of the architecture of HSMMC on s3c6410.
// this process was copied from CE old version.
	BOOL
CSDHCSlotBase::IsOnlySDIOInterrupt()
{
	WORD wIntStatus = ReadWord(SDHC_NORMAL_INT_STATUS);
	if (wIntStatus == NORMAL_INT_STATUS_CARD_INT && isSDIOInterrupt == TRUE ) {
		return TRUE;
	}
	return FALSE;
}


VOID
CSDHCSlotBase::DoEnableSDIOInterrupts(
		BOOL fEnable
		)
{
	WORD wIntSignalEn = ReadWord(SDHC_NORMAL_INT_SIGNAL_ENABLE);

	if (fEnable) {
		isSDIOInterrupt = FALSE;	// copied from CE old version by KYS
		wIntSignalEn |= NORMAL_INT_SIGNAL_CARD_INT;
	}
	else {
		isSDIOInterrupt = TRUE;	// copied from CE old version by KYS
		wIntSignalEn &= (~NORMAL_INT_SIGNAL_CARD_INT);      
	}

	WriteWord(SDHC_NORMAL_INT_SIGNAL_ENABLE, wIntSignalEn);

	WORD wIntStatusEn = ReadWord(SDHC_NORMAL_INT_STATUS_ENABLE);

	if (fEnable) {
		wIntStatusEn |= NORMAL_INT_ENABLE_CARD_INT;
	}
	else {
		wIntStatusEn &= (~NORMAL_INT_ENABLE_CARD_INT);      
	}

	WriteWord(SDHC_NORMAL_INT_STATUS_ENABLE, wIntStatusEn);

}


template<class T>
BOOL
CSDHCSlotBase::WaitForReg(
		T (CSDHCSlotBase::*pfnReadReg)(DWORD),
		DWORD dwRegOffset,
		T tMask,
		T tWaitForEqual,
		DWORD dwTimeout
		)
{
	SETFNAME();

	const DWORD dwStart = GetTickCount();

	T tValue;

	BOOL fRet = TRUE;
	DWORD dwIteration = 1;

	// Verify that reset has completed.
	do {
		tValue = (this->*pfnReadReg)(dwRegOffset);

		if ( (dwIteration % 16) == 0 ) {
			// Check time
			DWORD dwCurr = GetTickCount();

			// Unsigned arithmetic handles rollover.
			DWORD dwTotal = dwCurr - dwStart;

			if (dwTotal > dwTimeout) {
				// Timeout
				fRet = FALSE;
				DEBUGMSG(SDCARD_ZONE_WARN, (_T("%s Timeout (%u ms) waiting for (ReadReg<%u>(0x%02x) & 0x%08x) == 0x%08x\r\n"),
							pszFname, dwTimeout, sizeof(T), dwRegOffset, tMask, tWaitForEqual));
				break;
			}
		}

		++dwIteration;
	} while ((tValue & tMask) != tWaitForEqual);

	return fRet;
}


BOOL 
CSDHCSlotBase::SoftwareReset(
		BYTE bResetBits
		)
{
	SETFNAME();

	// Reset the controller
	WriteByte(SDHC_SOFT_RESET, bResetBits);
	BOOL fSuccess = WaitForReg<BYTE>(ReadByte, SDHC_SOFT_RESET, bResetBits, 0);
	if (!fSuccess) {
		DEBUGMSG(SDCARD_ZONE_ERROR, (_T("%s Timeout waiting for controller reset - 0x%02x\r\n"),
					pszFname, bResetBits));
	}

	WriteDword(SDHC_CONTROL2, (ReadDword(SDHC_CONTROL2)|(0x1<<30)));	// Enable Command Conflict Mask

	return fSuccess;
}


VOID
CSDHCSlotBase::EnableLED(
		BOOL fEnable
		)
{
	BYTE bHostControl = ReadByte(SDHC_HOST_CONTROL);

	if (fEnable) {
		bHostControl |= HOSTCTL_LED_CONTROL;
	}
	else {
		bHostControl &= ~HOSTCTL_LED_CONTROL;
	}

	WriteByte(SDHC_HOST_CONTROL, bHostControl);
}


VOID 
CSDHCSlotBase::IndicateSlotStateChange(SD_SLOT_EVENT sdEvent) {
	SDHCDIndicateSlotStateChange(m_pHCDContext,
			(UCHAR) m_dwSlot, sdEvent);
}


PSD_BUS_

⌨️ 快捷键说明

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