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

📄 sdhcslot.cpp

📁 SMDK2416_BSP
💻 CPP
📖 第 1 页 / 共 5 页
字号:
		)
{
	Validate();

	m_cpsAtPowerDown = m_cpsCurrent;

	if (!m_fIsPowerManaged) {
		CEDEVICE_POWER_STATE cps;

		if (m_bWakeupControl) {
			cps = D3;
		}
		else {
			cps = (_CEDEVICE_POWER_STATE)D4;
		}

		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);
	Start();	// added by JJG 06.11.11
}


#if (BSP_TYPE == BSP_SMDK2443)
SD_API_STATUS
CSDHCSlotBase::BusRequestHandler(
		PSD_BUS_REQUEST pRequest
		)
{
	SETFNAME();

	PREFAST_DEBUGCHK(pRequest);
	Validate();

	WORD            wRegCommand;
	SD_API_STATUS   status;
	WORD            wIntStatusEn;
	BOOL            fSuccess;

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

	RETAILMSG(0, (TEXT("%s CMD:%d\n"), pszFname, pRequest->CommandCode));
	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) {
			RETAILMSG(0, 
					(TEXT("%s AutoCMD12 Succeeded, bypass CMD12.\n"), pszFname));			
			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
	RETAILMSG(0,(TEXT("SendCommand  0x%x\n"),pRequest->CommandCode));
	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:
#ifdef _MMC_SPEC_42_
			/*************************************************************************/
			/****** Date : 07.05.14                                         	******/
			/****** Developer : HS.JANG											******/
			/****** Description : to support SD SPEC20 card. Response7 is added	******/
			/****** 			  for supporting SD SPEC20 card					******/
			/*************************************************************************/

		case ResponseR7:
			/*************************************************************************/
#endif    

			wRegCommand |= CMD_RESPONSE_R1_R5_R6;
			break;

		case ResponseR1b:
			wRegCommand |= CMD_RESPONSE_R1B_R5B;   
			break;

		default:
			status = SD_API_STATUS_INVALID_PARAMETER;
			goto EXIT;
	}

	// Set up variable for the new interrupt sources. Note that we must
	// enable DMA and read/write interrupts in this routine (not in
	// HandleCommandComplete) or they will be missed.
	wIntStatusEn = ReadWord(SDHC_NORMAL_INT_STATUS_ENABLE);
	wIntStatusEn |= NORMAL_INT_ENABLE_CMD_COMPLETE | NORMAL_INT_ENABLE_TRX_COMPLETE;

	// check command inhibit, wait until OK
	fSuccess = WaitForReg<DWORD>(ReadDword, SDHC_PRESENT_STATE, STATE_CMD_INHIBIT, 0);
	if (!fSuccess) {
		DEBUGMSG(SDCARD_ZONE_ERROR, (_T("%s Timeout waiting for CMD Inhibit\r\n"),
					pszFname));
		status = SD_API_STATUS_DEVICE_NOT_RESPONDING;
		goto EXIT;
	}

	// programming registers
	if (!TRANSFER_IS_COMMAND_ONLY(pRequest)) {
		WORD wRegTxnMode = 0;   

#ifdef _MMC_SPEC_42_
		/*************************************************************************/
		/****** Date : 07.05.14                                         	******/
		/****** Developer : HS.JANG											******/
		/****** Description : to support MMCMicro this code was added	 	******/
		/*************************************************************************/

		if ( (ReadByte(SDHC_TIMEOUT_CONTROL) != m_dwTimeoutControl) && 
				pRequest->CommandCode != MMC_CMD_SEND_EXT_CSD ) 
		{
			WriteByte(SDHC_TIMEOUT_CONTROL, (BYTE) m_dwTimeoutControl);
		}

		if ( pRequest->CommandCode == MMC_CMD_SEND_EXT_CSD ) 
		{
			WriteByte(SDHC_TIMEOUT_CONTROL, 0x3);
		}
		/*************************************************************************/
#endif


		wRegCommand |= CMD_DATA_PRESENT;

		if (UseDmaForRequest(pRequest)) {
			wIntStatusEn |= NORMAL_INT_ENABLE_DMA;

			BOOL fNoException;
			DEBUGCHK(TRANSFER_SIZE(pRequest) <= CB_DMA_BUFFER);

			if (TRANSFER_IS_WRITE(pRequest)) {
				DWORD cbToTransfer = TRANSFER_SIZE(pRequest);

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

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

			WriteDword(SDHC_SYSTEMADDRESS_LO, m_paDmaBuffer);
			wRegTxnMode |= TXN_MODE_DMA;
		}
		else {
			if (TRANSFER_IS_WRITE(pRequest)) {
				wIntStatusEn |= NORMAL_INT_ENABLE_BUF_WRITE_RDY;
			}
			else {
				wIntStatusEn |= NORMAL_INT_ENABLE_BUF_READ_RDY;
			}
		}

		// BlockSize
		// Note that for DMA we are programming the buffer boundary for 512K Bytes
		DEBUGMSG(SDHC_SEND_ZONE,(TEXT("Sending command block size 0x%04X\r\n"), (WORD) pRequest->BlockSize));
		WriteWord(SDHC_BLOCKSIZE,  (WORD)((0x7<<12)| pRequest->BlockSize));

		// We always go into block mode even if there is only 1 block. 
		// Otherwise the Pegasus will occaissionally hang when
		// writing a single block with DMA.

		wRegTxnMode |= (TXN_MODE_MULTI_BLOCK | TXN_MODE_BLOCK_COUNT_ENABLE);
		/*
		   if(pRequest->CommandCode == 18 || pRequest->CommandCode == 25)
		   wRegTxnMode |= (TXN_MODE_MULTI_BLOCK | TXN_MODE_BLOCK_COUNT_ENABLE);
		   else
		   wRegTxnMode |= ( TXN_MODE_BLOCK_COUNT_ENABLE);*/


		// BlockCount
		DEBUGMSG(SDHC_SEND_ZONE,(TEXT("Sending command block count 0x%04X\r\n"), 
					(WORD) pRequest->NumBlocks));            
		WriteWord(SDHC_BLOCKCOUNT, (WORD) pRequest->NumBlocks);

		//if (pRequest->Flags & SD_AUTO_ISSUE_CMD12 && *((DWORD *)(pRequest->hDevice)) != 0 ) {
		if (pRequest->Flags & SD_AUTO_ISSUE_CMD12) {
			wRegTxnMode |= TXN_MODE_AUTO_CMD12;
		}

		if (TRANSFER_IS_READ(pRequest)) {
			wRegTxnMode |= TXN_MODE_DATA_DIRECTION_READ;     
		}

		// check dat inhibit, wait until okay
		fSuccess = WaitForReg<DWORD>(ReadDword, SDHC_PRESENT_STATE, STATE_DAT_INHIBIT, 0); 
		if (!fSuccess) {
			DEBUGMSG(SDCARD_ZONE_ERROR, (_T("%s Timeout waiting for DAT Inhibit\r\n"),
						pszFname));
			RETAILMSG(1, (_T("%s Timeout waiting for DAT Inhibit\r\n"),
						pszFname));

			status = SD_API_STATUS_DEVICE_NOT_RESPONDING;
			goto EXIT;
		}

		DEBUGMSG(SDHC_SEND_ZONE,(TEXT("Sending Transfer Mode 0x%04X\r\n"),wRegTxnMode));	
		WriteWord(SDHC_TRANSFERMODE, wRegTxnMode);
	} else {
		RETAILMSG(0,(TEXT("Command Only\n")));
		// Command-only
		if (pRequest->CommandCode == SD_CMD_STOP_TRANSMISSION) {
			wRegCommand |= CMD_TYPE_ABORT;
		}
		else if (TransferIsSDIOAbort(pRequest)) {
			// Use R5b For CMD52, Function 0, I/O Abort
			DEBUGMSG(SDHC_SEND_ZONE, (TEXT("Sending Abort command \r\n")));
			wRegCommand |= CMD_TYPE_ABORT | CMD_RESPONSE_R1B_R5B;
		}
		if (pRequest->CommandCode == 23) {
			wRegCommand |= CMD_INDEX_CHECK | CMD_CRC_CHECK | CMD_RESPONSE_LENGTH_48;
		}	

		// The following is required for the Pegasus. If it is not present,
		// command-only transfers will sometimes fail (especially R1B and R5B).
		WriteDword(SDHC_SYSTEMADDRESS_LO, 0);
		WriteWord(SDHC_BLOCKSIZE, 0);
		WriteWord(SDHC_BLOCKCOUNT, 0);
	}

	RETAILMSG(0,(TEXT("Sending command register 0x%04X\r\n"),wRegCommand));
	RETAILMSG(0,(TEXT("Sending command Argument 0x%08X\r\n"),pRequest->CommandArgument));
	RETAILMSG(0,(TEXT("Sending command IntStatusEn 0x%08X\r\n"),wIntStatusEn));

	DEBUGMSG(SDHC_SEND_ZONE,(TEXT("Sending command register 0x%04X\r\n"),wRegCommand));
	DEBUGMSG(SDHC_SEND_ZONE,(TEXT("Sending command Argument 0x%08X\r\n"),pRequest->CommandArgument));

	WriteDword(SDHC_ARGUMENT_0, pRequest->CommandArgument);

	// Enable transfer interrupt sources.
	WriteWord(SDHC_NORMAL_INT_STATUS_ENABLE, wIntStatusEn);

	// Turn the clock on. It is turned off in IndicateBusRequestComplete().
	SDClockOn();

	// Turn the LED on.
	EnableLED(FALSE);

	// Writing the upper byte of the command register starts the command.
	// All register initialization must already be complete by this point.
	WriteWord(SDHC_COMMAND, wRegCommand);

	status = SD_API_STATUS_PENDING;
	RETAILMSG(0,(TEXT("Sending command IntStatusEn 0x%08X\r\n"),ReadWord(SDHC_NORMAL_INT_STATUS_ENABLE)));
EXIT:
	return status;
}

#elif (BSP_TYPE == BSP_SMDK2450)
	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.
				//while (m_pCurrentRequest && (ReadDword(SDHC_PRESENT_STATE) & STATE_CARD_INSERTED)!=0) {
				// 08.04.04 by KYS
				// To check the state on CARD INSERTED on Ch0, use IsCardPresent().
				BOOL fCardInserted = TRUE;
				while (m_pCurrentRequest && (fCardInserted = (IsCardPresent() & TRUE)!=0)) {
					if (IsOnlySDIOInterrupt() != TRUE)
					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;
	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

⌨️ 快捷键说明

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