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

📄 sdhcslot.cpp

📁 SAMSUNG S3C6410 CPU BSP for winmobile6
💻 CPP
📖 第 1 页 / 共 5 页
字号:
{    
	m_fCardPresent = FALSE;
	m_fIsPowerManaged = FALSE;
	m_fSleepsWithPower = FALSE;
	m_fPowerUpDisabledInts = FALSE;
	m_f4BitMode = FALSE;
	m_cpsCurrent = D0;

	// Wake on SDIO interrupt must be set by the client
	m_bWakeupControl &= ~WAKEUP_INTERRUPT;

	// To control the Data CRC error
	WORD wErrIntSignalEn = ReadWord(SDHC_ERROR_INT_SIGNAL_ENABLE);
	WORD wErrIntStatusEn = ReadWord(SDHC_ERROR_INT_STATUS_ENABLE);
	WORD wErrIntStatus = ReadWord(SDHC_ERROR_INT_STATUS);
	WriteWord(SDHC_ERROR_INT_SIGNAL_ENABLE, (wErrIntSignalEn & ~(0x20))); //Command and Data CRC error disable
	WriteWord(SDHC_ERROR_INT_STATUS_ENABLE, (wErrIntStatusEn & ~(0x20))); //Command and Data CRC error disable


	if (m_fSDIOInterruptsEnabled) {
		EnableSDIOInterrupts(FALSE);
	}

	IndicateSlotStateChange(DeviceEjected);

	// turn off clock and remove power from the slot
	SDClockOff();
	WriteByte(SDHC_POWER_CONTROL, 0);

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

		if (pRequest != NULL) {
			DEBUGMSG(SDCARD_ZONE_WARN, 
					(TEXT("Card Removal Detected - Canceling current request: 0x%08X, command: %d\n"), 
					 pRequest, pRequest->CommandCode));
			DumpRequest(pRequest, SDHC_SEND_ZONE || SDHC_RECEIVE_ZONE);
			IndicateBusRequestComplete(pRequest, SD_API_STATUS_DEVICE_REMOVED);
		}
	}

	if (m_pbDmaBuffer) {
		DEBUGCHK(m_paDmaBuffer);
		FreePhysBuffer(m_pbDmaBuffer);
		m_pbDmaBuffer = NULL;
		m_paDmaBuffer = 0;

		// The Pegasus requires the following so that the next
		// insertion will work correctly.
		SoftwareReset(SOFT_RESET_CMD | SOFT_RESET_DAT);
		WriteDword(SDHC_SYSTEMADDRESS_LO, 0);
		WriteWord(SDHC_BLOCKSIZE, 0);
		WriteWord(SDHC_BLOCKCOUNT, 0);

		WriteWord(SDHC_NORMAL_INT_SIGNAL_ENABLE, (ReadWord(SDHC_NORMAL_INT_SIGNAL_ENABLE) & ~(NORMAL_INT_STATUS_DMA)));
		WriteWord(SDHC_NORMAL_INT_STATUS_ENABLE,(ReadWord(SDHC_NORMAL_INT_STATUS_ENABLE) & ~(NORMAL_INT_STATUS_DMA)));
		do {
			WriteWord(SDHC_NORMAL_INT_STATUS, NORMAL_INT_STATUS_DMA);
		}while(ReadWord(SDHC_NORMAL_INT_STATUS) & NORMAL_INT_STATUS_DMA);
		WriteWord(SDHC_NORMAL_INT_STATUS_ENABLE, (ReadWord(SDHC_NORMAL_INT_STATUS_ENABLE) | NORMAL_INT_STATUS_DMA));
		WriteWord(SDHC_NORMAL_INT_SIGNAL_ENABLE, (ReadWord(SDHC_NORMAL_INT_SIGNAL_ENABLE) | NORMAL_INT_STATUS_DMA));

		// To diable the Data CRC error interrupt
		WriteWord(SDHC_ERROR_INT_SIGNAL_ENABLE,0);  
		do
		{
			WriteWord(SDHC_ERROR_INT_STATUS,wErrIntStatus);
		}while(ReadWord(SDHC_ERROR_INT_STATUS));
		WriteWord(SDHC_ERROR_INT_SIGNAL_ENABLE,wErrIntSignalEn);
	}

	// 08.05.21 by KYS
	// Below code lines are needed for working as a mass storage device
	v_gBspArgs->g_SDCardState = CARD_REMOVED;
	SetEvent( v_gBspArgs->g_SDCardDetectEvent );
}


VOID 
CSDHCSlotBase::HandleInsertion(
		)
{
	DWORD dwClockRate = SD_DEFAULT_CARD_ID_CLOCK_RATE;

	WORD wErrIntSignalEn = ReadWord(SDHC_ERROR_INT_SIGNAL_ENABLE);
	WORD wErrIntStatusEn = ReadWord(SDHC_ERROR_INT_STATUS_ENABLE);

	g_initialInsertion = 0;
	m_fCardPresent = TRUE;

	// Apply the initial voltage to the card.
	SetVoltage(GetMaxVddWindow());

	// Send at least 74 clocks to the card over the course of at least 1 ms
	// with allowance for power supply ramp-up time. (SD Phys Layer 6.4)
	// Note that power supply ramp-up time occurs in SetVoltage().
	SetClockRate(&dwClockRate);
	SDClockOn();
	DWORD dwSleepMs = (74 / (dwClockRate / 1000)) + 1;
	Sleep(dwSleepMs);
	SDClockOff();

	if (GetCapabilities().bits.DMA) {
		PHYSICAL_ADDRESS SystemAddr = { 0 };
		PVOID pvBuffer = AllocPhysBuffer(CB_DMA_BUFFER, &SystemAddr.LowPart);        
		if (pvBuffer) {
			PHYSICAL_ADDRESS BusAddr;

			// Translate physical address to logical (bus-relative) address.
			BOOL fSuccess = TranslateSystemAddr(m_hBusAccess, m_interfaceType, 
					m_dwBusNumber, SystemAddr, &BusAddr);
			if (fSuccess) {
				m_pbDmaBuffer= (PBYTE) pvBuffer;
				m_paDmaBuffer = BusAddr.LowPart;
			}
			else {
				// If we fail, we will simply fall back to PIO mode
				FreePhysBuffer(pvBuffer);
			}
		}
	}

	// Interrupts are not enabled on a newly inserted card.
	EnableSDIOInterrupts(FALSE);

	// Indicate device arrival
	IndicateSlotStateChange(DeviceInserted);

	WriteWord(SDHC_ERROR_INT_SIGNAL_ENABLE, (wErrIntSignalEn | (0x20))); //Command and Data CRC error disable
	WriteWord(SDHC_ERROR_INT_STATUS_ENABLE, (wErrIntStatusEn | (0x20))); //Command and Data CRC error disable

	// 08.05.21 by KYS
	// Below code lines are needed for working as a mass storage device
	v_gBspArgs->g_SDCardState = CARD_INSERTED;
	SetEvent( v_gBspArgs->g_SDCardDetectEvent );
}


BOOL 
CSDHCSlotBase::HandleCommandComplete(
		)
{
	SETFNAME();

	PSD_BUS_REQUEST pRequest;
	BOOL fRet = FALSE;

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

	DEBUGCHK(m_dwReadyInts == 0);

	if (pRequest) {

		DEBUGCHK(pRequest->HCParam == 0);
		// 08.02.03 by KYS
		// INT_TRX_COMPLETE is not suitable for s3c6410, so I comment out below code.
		// therefore, in order to keep fastpath status, those code like just below is needed.
		//SD_API_STATUS transferStatus = SD_API_STATUS_SUCCESS;
		SD_API_STATUS transferStatus = m_FastPathStatus>=0 ? SD_API_STATUS_SUCCESS : m_FastPathStatus;

		if (NoResponse != pRequest->CommandResponse.ResponseType) {
			// Copy response over to request structure. Note that this is a 
			// bus driver buffer, so we do not need to SetProcPermissions 
			// or __try/__except.
			UNALIGNED DWORD *pdwResponseBuffer = 
				(PDWORD) (pRequest->CommandResponse.ResponseBuffer + 1); // Skip CRC
			WORD wCommand = ReadWord(SDHC_COMMAND);

			if ((wCommand & CMD_RESPONSE_R1B_R5B) == CMD_RESPONSE_R1B_R5B) {
				// wait for Transfer Complete status, which indicate the busy wait is over.
				// we should not handle this TXN_COMPLETE interrupt in IST in this case
#if 0
				BOOL fSuccess = WaitForReg<WORD>(ReadWord, SDHC_NORMAL_INT_STATUS, 
						NORMAL_INT_STATUS_TRX_COMPLETE, NORMAL_INT_STATUS_TRX_COMPLETE, 5000);
				if (!fSuccess) {
					DEBUGMSG(SDCARD_ZONE_ERROR, (_T("%s Timeout waiting for NORMAL_INT_STATUS_TRX_COMPLETE\r\n"),
								pszFname));
					transferStatus = SD_API_STATUS_RESPONSE_TIMEOUT;
				}
#endif
				// Reset cmd and dat circuits
				SoftwareReset(SOFT_RESET_CMD | SOFT_RESET_DAT);
			}

			pdwResponseBuffer[0] = ReadDword(SDHC_R0);

			if (pRequest->CommandResponse.ResponseType == ResponseR2) {
				pdwResponseBuffer[1] = ReadDword(SDHC_R2);
				pdwResponseBuffer[2] = ReadDword(SDHC_R4);
				pdwResponseBuffer[3] = ReadDword(SDHC_R6);
			}
		}

		// check for command/response only
		if (TRANSFER_IS_COMMAND_ONLY(pRequest)) {
			IndicateBusRequestComplete(pRequest, transferStatus);
			fRet = TRUE;
		} else {
			// handle data phase transfer
			pRequest->HCParam = 0;
			fRet = FALSE;
		}
	}
	// else request must have been canceled due to an error

	return fRet;
}


VOID 
CSDHCSlotBase::HandleErrors(
		)
{
	SD_API_STATUS status = SD_API_STATUS_SUCCESS;
	// 2007.06.10
	// S/W workaround for the following problem
	// Problem : When the interrupt is occurred, it is late to update the interrupt status register related to the interrupt source
	while((ReadWord(SDHC_ERROR_INT_STATUS) == 0));

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

	WORD wErrorStatus = ReadWord(SDHC_ERROR_INT_STATUS);
	DEBUGMSG(SDCARD_ZONE_ERROR, 
			(TEXT("HandleErrors - ERROR INT STATUS=0x%02X\n"), wErrorStatus));
	if (pRequest) {
		DumpRequest(pRequest, SDCARD_ZONE_ERROR);
		// 08.04.27 by KYS
		// For simple debugging, we have to confirm the command number!
		RETAILMSG(1, (TEXT("ERR CMD:%d : "), pRequest->CommandCode));
	}

	DEBUGCHK( (wErrorStatus & ERR_INT_STATUS_VENDOR) == 0 );

	if (wErrorStatus) {
		if ( wErrorStatus & ERR_INT_STATUS_CMD_TIMEOUT ) {
			status = SD_API_STATUS_RESPONSE_TIMEOUT;
			switch(pRequest->CommandCode) {
				case 1 : RETAILMSG(1, (TEXT("If the card is not a MMC, CMD 1 does not work in reason.\n")));
						 break;
				case 5 : RETAILMSG(1, (TEXT("If the card is not a SDIO, CMD 5 does not work in reason.\n")));
						 break;
				case 8 : RETAILMSG(1, (TEXT("If the card is not SD SPEC 2.0, CMD 8 does not work in reason.\n")));
						 break;
				default :
						 RETAILMSG(1, (TEXT("[HSMMC0] CMD Timeout Error...\n")));
						 break;
			}
		}

		if ( wErrorStatus & ERR_INT_STATUS_CMD_CRC ) {
			status = SD_API_STATUS_CRC_ERROR;
			RETAILMSG(1, (TEXT("[HSMMC0] CMD CRC Error...\n")));
			if ( wErrorStatus & ERR_INT_STATUS_CMD_TIMEOUT )
				status = SD_API_STATUS_DEVICE_RESPONSE_ERROR;
			RETAILMSG(1, (TEXT("[HSMMC0] CMD Timeout Error...\n")));
		}

		if ( wErrorStatus & ERR_INT_STATUS_CMD_ENDBIT ) {
			status = SD_API_STATUS_RESPONSE_TIMEOUT;
			RETAILMSG(1, (TEXT("[HSMMC0] CMD ENDBIT Error...\n")));
		}

		if ( wErrorStatus & ERR_INT_STATUS_CMD_INDEX ) {
			status = SD_API_STATUS_DEVICE_RESPONSE_ERROR;
			RETAILMSG(1, (TEXT("[HSMMC0] CMD INDEX Error...\n")));
		}

		if ( wErrorStatus & ERR_INT_STATUS_DAT_TIMEOUT ) {
			status = SD_API_STATUS_DATA_TIMEOUT;
			RETAILMSG(1, (TEXT("[HSMMC0] DAT Timeout Error...\n")));
		}

		if ( wErrorStatus & ERR_INT_STATUS_DAT_CRC ) {
			status = SD_API_STATUS_CRC_ERROR;
			RETAILMSG(1, (TEXT("[HSMMC0] DAT CRC Error...\n")));
		}

		if ( wErrorStatus & ERR_INT_STATUS_DAT_ENDBIT ) {
			status = SD_API_STATUS_DEVICE_RESPONSE_ERROR;
			RETAILMSG(1, (TEXT("[HSMMC0] DAT ENDBIT Error...\n")));
		}

		if ( wErrorStatus & ERR_INT_STATUS_BUS_POWER ) {
			status = SD_API_STATUS_DEVICE_RESPONSE_ERROR;
			RETAILMSG(1, (TEXT("[HSMMC0] BUS POWER Error...\n")));
		}

		if ( wErrorStatus & ERR_INT_STATUS_AUTOCMD12 ) {
			status = SD_API_STATUS_DEVICE_RESPONSE_ERROR;
			RETAILMSG(1, (TEXT("[HSMMC0] AUTOCMD12 Error...\n")));
		}

		// Perform basic error recovery
		WORD wErrIntSignal = ReadWord(SDHC_ERROR_INT_SIGNAL_ENABLE);
		WriteWord(SDHC_ERROR_INT_SIGNAL_ENABLE, 0);
		WORD wErrIntStatusEn = ReadWord(SDHC_ERROR_INT_STATUS_ENABLE);	// KYS
		WriteWord(SDHC_ERROR_INT_STATUS_ENABLE,0);	// KYS


		if (IS_CMD_LINE_ERROR(wErrorStatus)) {
			// Reset CMD line
			DEBUGMSG(SDCARD_ZONE_ERROR, (TEXT("HandleErrors - Command line error (0x%x). Resetting CMD line.\r\n"),
						wErrorStatus));
			do {
				WriteWord(SDHC_ERROR_INT_STATUS, wErrorStatus);
			} while(ReadWord(SDHC_ERROR_INT_STATUS) && (ReadWord(SDHC_NORMAL_INT_STATUS) & NORMAL_INT_STATUS_ERROR_INT));

			SoftwareReset(SOFT_RESET_CMD);
		}

		if (IS_DAT_LINE_ERROR(wErrorStatus)) {
			// Reset DAT line
			DEBUGMSG(SDCARD_ZONE_ERROR, (TEXT("HandleErrors - Data line error (0x%x). Resetting DAT line.\r\n"),
						wErrorStatus));
			SoftwareReset(SOFT_RESET_DAT);
		}

		// clear all error status
		do {
			WriteWord(SDHC_ERROR_INT_STATUS, wErrorStatus);
		}while(ReadWord(SDHC_ERROR_INT_STATUS));	// KYS

		// re-enable error interrupt signals
		WriteWord(SDHC_ERROR_INT_STATUS_ENABLE, wErrIntStatusEn);
		WriteWord(SDHC_ERROR_INT_SIGNAL_ENABLE, wErrIntSignal);	// KYS

		// complete the request
		if (pRequest) {
			IndicateBusRequestComplete(pRequest, status);
		}
		else {  // KYS
			WORD wIntEnable = ReadWord(SDHC_NORMAL_INT_STATUS_ENABLE);
			wIntEnable |= NORMAL_INT_ENABLE_CMD_COMPLETE | NORMAL_INT_ENABLE_TRX_COMPLETE;
			WriteWord(SDHC_NORMAL_INT_STATUS_ENABLE,wIntEnable);
			RETAILMSG(0,(TEXT("Error Handler : 0x%X\n"),ReadWord(SDHC_NORMAL_INT_STATUS_ENABLE)));
		}
	}
}


VOID 
CSDHCSlotBase::HandleTransferDone(
		)
{
	PSD_BUS_REQUEST pRequest;
	SD_API_STATUS   status = SD_API_STATUS_SUCCESS;

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

	if (pRequest) {
		if (!TRANSFER_IS_COMMAND_ONLY(pRequest)) {
			if (UseDmaForRequest(pRequest)) {
				DWORD cbTransfer = TRANSFER_SIZE(pRequest);
				DWORD cbRemainder = cbTransfer % CB_DMA_PAGE;

				if (cbRemainder == 0) {
					cbRemainder = CB_DMA_PAGE;
				}

				pRequest->HCParam += cbRemainder;

				if (TRANSFER_IS_READ(pRequest)) {
					BOOL fNoException;
					DEBUGCHK(cbTransfer <= CB_DMA_BUFFER);

					SD_SET_PROC_PERMISSIONS_FROM_REQUEST(pRequest) {               
						fNoException = SDPerformSafeCopy(pRequest->pBlockBuffer,
								m_pbDmaBuffer, cbTransfer);
					} SD_RESTORE_PROC_PERMISSIONS();

					if (fNoException == FALSE) {
						status = SD_API_STATUS_ACCESS_VIOLATION;
					}
				}
			}
		}

		if (pRequest->HCParam != TRANSFER_SIZE(pRequest)) {
			// This means that a Command Complete interrupt occurred before
			// a Buffer Ready interrupt. Hardware should not allow this. 
			DEBUGCHK(FALSE);
			status = SD_API_STATUS_DEVICE_RESPONSE_ERROR;
		}
		RETAILMSG(0, (TEXT("TransferDone, HCParam: %d, TranSize: %d\n"), pRequest->HCParam, TRANSFER_SIZE(pRequest)));

		// complete the request
		if (pRequest->Flags & SD_AUTO_ISSUE_CMD12) {
			m_fAutoCMD12Success = TRUE;
		}

		IndicateBusRequestComplete(pRequest, status);
	}
	// else request must have been canceled due to an error
}


VOID 
CSDHCSlotBase::HandleReadReady(
		)
{
	DEBUGMSG(SDHC_RECEIVE_ZONE, (TEXT("HandleReadReady - HandleReadReady!\n"))); 

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

	if (pRequest) {
		DEBUGCHK(!UseDmaForRequest(pRequest));
		DEBUGCHK(pRequest->NumBlocks > 0);
		DEBUGCHK(pRequest->HCParam < TRANSFER_SIZE(pRequest));
		DEBUGCHK(TRANSFER_IS_READ(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;

⌨️ 快捷键说明

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