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

📄 sdhcslot.cpp

📁 SAMSUNG S3C6410 CPU BSP for winmobile6
💻 CPP
📖 第 1 页 / 共 5 页
字号:
			wRegCommand |= CMD_RESPONSE_R3_R4;
			break;

		case ResponseR1:
		case ResponseR5:
		case ResponseR6:
		case ResponseR7:
			wRegCommand |= CMD_RESPONSE_R1_R5_R6_R7;
			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;

	//  wIntSignalEn = ReadWord(SDHC_NORMAL_INT_SIGNAL_ENABLE);	// KYS
	//  wIntSignalEn |= NORMAL_INT_ENABLE_CMD_COMPLETE | NORMAL_INT_ENABLE_TRX_COMPLETE;	// KYS

	// 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);
		} else if ( (ReadByte(SDHC_TIMEOUT_CONTROL) == m_dwTimeoutControl) &&
				(pRequest->CommandCode == MMC_CMD_SEND_EXT_CSD) ) {
			WriteByte(SDHC_TIMEOUT_CONTROL, (BYTE)0x3);
		}
#endif

		wRegCommand |= CMD_DATA_PRESENT;

		if (UseDmaForRequest(pRequest)) {
			// 08.05.30 by KYS
			// Note that we can not know the next address if use DMA interrupt, so DMA should be disabled!.
			//wIntStatusEn |= NORMAL_INT_ENABLE_DMA;
			//      wIntSignalEn |= NORMAL_INT_SIGNAL_DMA;	// KYS

			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 4k
		DEBUGMSG(SDHC_SEND_ZONE,(TEXT("Sending command block size 0x%04X\r\n"), (WORD) pRequest->BlockSize));
		//WriteWord(SDHC_BLOCKSIZE, (WORD) pRequest->BlockSize);
		//WriteWord(SDHC_BLOCKSIZE, (WORD)( (0x7<<12) | pRequest->BlockSize ));  // KYS
		// 08.05.30 by KYS
		// BlockSize
		// Note that for DMA we are programming the buffer boundary for 512k beacause we cat not know the next address if use DMA interrupt.
		WriteWord(SDHC_BLOCKSIZE, (WORD)(pRequest->BlockSize & 0xfff) | (0x7<<12));

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

		// 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) {
			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));
			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 {
		// 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;
		}

		// 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);
	}

	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);
	//  WriteWord(SDHC_NORMAL_INT_SIGNAL_ENABLE, wIntSignalEn);	// KYS

	// 08.03.27, by KYS
	// Status Busy bit checking for clearing the interrupt status register before "CMD ISSUE".
	while(ReadDword(SDHC_CONTROL4)&(0x1));

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

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

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

	// 08.04.21 by KYS
	// Polling the command complete for "Real" FastPath
	PollingForCommandComplete();
	status = SD_API_STATUS_PENDING;

EXIT:
	return status;
}

// 08.04.21 by KYS
// This polling function is needed for Fastpath and perform polling the command complete.
BOOL CSDHCSlotBase::PollingForCommandComplete()
{
	BOOL            fContinue = TRUE;
	if (m_fFakeCardRemoval && m_fCardPresent) {
		m_fFakeCardRemoval = FALSE;
		HandleRemoval(TRUE);
	}
	else {
		// Assume we reading PCI register at 66 Mhz. for times of 100 us. it should be 10*1000 time
		for (DWORD dwIndex=0; fContinue  && dwIndex<10*1000; dwIndex ++ ) {
			WORD wIntStatus = ReadWord(SDHC_NORMAL_INT_STATUS);
			if (wIntStatus != 0) {
				DEBUGMSG(SDHC_INTERRUPT_ZONE,
						(TEXT("PollingForCommandComplete (%u) - Normal Interrupt_Status=0x%02x\n"),
						 m_dwSlot, wIntStatus));

				// Error handling. Make sure to handle errors first. 
				if ( wIntStatus & NORMAL_INT_STATUS_ERROR_INT ) {
					HandleErrors();
					// 08.01.27 by KYS
					// you can also activate below code "continue;" in order to ensure the fastpath.
					// then, you don't need to keep the fastpath status varible at "HandleCommandComplete" function.
					//continue;
					fContinue = FALSE;	// Comment out this orginal line by KYS
				}

				// Command Complete handling.
				if ( wIntStatus & NORMAL_INT_STATUS_CMD_COMPLETE ) {
					// Clear status
					m_fCommandCompleteOccurred = TRUE;
					fContinue = FALSE;
					WriteWord(SDHC_NORMAL_INT_STATUS, NORMAL_INT_STATUS_CMD_COMPLETE);

					if (HandleCommandComplete()) { // If completed. 
						WriteWord(SDHC_NORMAL_INT_STATUS, (wIntStatus & NORMAL_INT_STATUS_TRX_COMPLETE));
					}
				}
			}
		}
	}
	ASSERT(!fContinue);
	return (!fContinue);
}

VOID 
CSDHCSlotBase::EnableSDIOInterrupts(
		BOOL fEnable
		)
{
	Validate();

	if (fEnable) {
		m_fSDIOInterruptsEnabled = TRUE;
		DoEnableSDIOInterrupts(fEnable);
	}
	else {
		DoEnableSDIOInterrupts(fEnable);
		m_fSDIOInterruptsEnabled = FALSE;
	}
}

#ifndef _SMDK6410_CH0_EXTCD_
VOID 
CSDHCSlotBase::HandleInterrupt(
		)
#else
// 08.03.20 by KYS
// New Interrupt handler function can process factors on new card detect interrupt of HSMMC ch0 on SMDK6410.
VOID CSDHCSlotBase::HandleInterrupt(SDSLOT_INT_TYPE intType)
#endif
{
	Validate();
#ifdef _SMDK6410_CH0_EXTCD_
	// in case of it is occurred a card detect interrupt of HSMMC ch0 on SMDK6410
	if (intType == SDSLOT_INT_CARD_DETECTED) {
		RETAILMSG(0,(TEXT("[HSMMC0] Card Insertion or Removal Detect!!\n")));	
		m_fCheckSlot = TRUE;
	} else {  
#endif
		WORD wIntStatus = ReadWord(SDHC_NORMAL_INT_STATUS);
		//        if(g_initialInsertion != 1) {
		//            while(( wIntStatus=ReadWord(SDHC_NORMAL_INT_STATUS)) == 0);
		//        }

		if (m_fFakeCardRemoval && m_fCardPresent) {
			m_fFakeCardRemoval = FALSE;
			HandleRemoval(TRUE);
		}

		if (wIntStatus != 0) {
			DEBUGMSG(SDHC_INTERRUPT_ZONE, 
					(TEXT("HandleInterrupt (%u) - Normal Interrupt_Status=0x%02x\n"),
					 m_dwSlot, wIntStatus));
			RETAILMSG(0, 
					(TEXT("HandleInterrupt (%u) - Normal Interrupt_Status=0x%02x\n"),
					 m_dwSlot, wIntStatus));

			// Error handling. Make sure to handle errors first. 
			if ( wIntStatus & NORMAL_INT_STATUS_ERROR_INT ) {
				HandleErrors();
			}

			// Command Complete handling.
			if ( wIntStatus & NORMAL_INT_STATUS_CMD_COMPLETE ) {
				// Clear status
				m_fCommandCompleteOccurred = TRUE;
				WriteWord(SDHC_NORMAL_INT_STATUS, NORMAL_INT_STATUS_CMD_COMPLETE);

				if ( HandleCommandComplete() ) {
					wIntStatus &= ~NORMAL_INT_STATUS_TRX_COMPLETE; // this is command-only request. 
				}
			}

			// Sometimes at the lowest clock rate, the Read/WriteBufferReady
			// interrupt actually occurs before the CommandComplete interrupt.
			// This confuses our debug validation code and could potentially
			// cause problems. This is why we will verify that the CommandComplete
			// occurred before processing any data transfer interrupts.
			if (m_fCommandCompleteOccurred) {
				if (wIntStatus & NORMAL_INT_STATUS_DMA) {
					WriteWord(SDHC_NORMAL_INT_STATUS, NORMAL_INT_STATUS_DMA);

					HandleDma();
					// do not break here. Continue to check TransferComplete. 
				}

				// Buffer Read Ready handling
				if (wIntStatus & NORMAL_INT_STATUS_BUF_READ_RDY ) {
					// Clear status
					WriteWord(SDHC_NORMAL_INT_STATUS, NORMAL_INT_STATUS_BUF_READ_RDY);

					HandleReadReady();
					// do not break here. Continue to check TransferComplete. 
				}

				// Buffer Write Ready handling
				if (wIntStatus & NORMAL_INT_STATUS_BUF_WRITE_RDY ) {
					// Clear status
					WriteWord(SDHC_NORMAL_INT_STATUS, NORMAL_INT_STATUS_BUF_WRITE_RDY);

					HandleWriteReady();
					// do not break here. Continue to check TransferComplete. 
				}
			}
			else {
				// We received data transfer interrupt before command 
				// complete interrupt. Wait for the command complete before
				// processing the data interrupt.
			}

			// Transfer Complete handling
			if ( wIntStatus & NORMAL_INT_STATUS_TRX_COMPLETE ) {
				// Clear status
				WriteWord(SDHC_NORMAL_INT_STATUS, NORMAL_INT_STATUS_TRX_COMPLETE | NORMAL_INT_STATUS_DMA);


				HandleTransferDone();
			}

			// SDIO Interrupt Handling
			if ( wIntStatus & NORMAL_INT_STATUS_CARD_INT ) {
				DEBUGCHK(m_fSDIOInterruptsEnabled);
				DEBUGMSG(SDHC_INTERRUPT_ZONE, (_T("SDHCControllerIst: Card interrupt!\n")));

				// Because SDIO Interrupt is level triggered, we are not able to clear
				// the status. The status should be cleared by the card
				// we just disable the interrupt from Interrupt Signal Register
				// and Interrupt Status Enable register, and indicate that 
				// the card is interrupting
				EnableSDIOInterrupts(FALSE);
				IndicateSlotStateChange(DeviceInterrupting);
			}

			// Card Detect Interrupt Handling
			if (wIntStatus & (NORMAL_INT_STATUS_CARD_INSERTION | NORMAL_INT_STATUS_CARD_REMOVAL)) {
				WriteWord(
						SDHC_NORMAL_INT_STATUS,
						NORMAL_INT_STATUS_CARD_INSERTION | NORMAL_INT_STATUS_CARD_REMOVAL);

				m_fCheckSlot = TRUE;
			}
		}
#ifdef _SMDK6410_CH0_EXTCD_
	} // The end of "if(intType == SDSLOT_INT_CARD_DETECTED)"
#endif

	if (m_fCheckSlot) {
		m_fCheckSlot = FALSE;
#ifdef _SMDK6410_CH0_EXTCD_
		// At this time, we have to validate the card present status.
		if((IsCardPresent() == TRUE) && (m_fCardPresent != TRUE))
#else	
			// check card inserted or removed
			DWORD dwPresentState = ReadDword(SDHC_PRESENT_STATE);
		if (dwPresentState & STATE_CARD_INSERTED)
#endif
		{
			DEBUGMSG(SDHC_INTERRUPT_ZONE, (TEXT("SDHCControllerIst - Card is Inserted! \n")));
			RETAILMSG(1, (TEXT("[HSMMC0] Card is Inserted! \n")));
			m_fFakeCardRemoval = FALSE;	// KYS
			if (m_fCardPresent != TRUE ) {
				Start();
				HandleInsertion();
			}
		}
#ifdef _SMDK6410_CH0_EXTCD_
		else if((IsCardPresent() != TRUE) && (m_fCardPresent != FALSE))
#else    
		else
#endif
		{
			DEBUGMSG(SDHC_INTERRUPT_ZONE, (TEXT("SDHCControllerIst - Card is Removed! \n")));
			RETAILMSG(1, (TEXT("[HSMMC0] Card is Removed! \n")));
			m_fFakeCardRemoval = FALSE;	// KYS
			if (m_fCardPresent) {
				HandleRemoval(TRUE);
			}
		}
	}
}


#ifdef _SMDK6410_CH0_EXTCD_
// New function can detect whether card is presented of HSMMC ch0 on SMDK6410.
BOOL CSDHCSlotBase::IsCardPresent()
{
	BOOL fRetVal;
	volatile S3C6410_GPIO_REG *pIOPreg = NULL;

	pIOPreg = (volatile S3C6410_GPIO_REG *)DrvLib_MapIoSpace(S3C6410_BASE_REG_PA_GPIO, sizeof(S3C6410_GPIO_REG), FALSE);

	if (pIOPreg == NULL) {
		RETAILMSG (1,(TEXT("[HSMMC0] GPIO registers not mapped\r\n")));
		return FALSE;
	}

	if ( (pIOPreg->GPNDAT & (0x1<<13)) == 0 ) {
		fRetVal = TRUE;
	}	else {
		fRetVal = FALSE;
	}

	RETAILMSG(0,(TEXT("IsCardPresent() : fRetVal = %d  GPNDAT = 0x%x\r\n"), fRetVal, (pIOPreg->GPNDAT & (0x1<<13)) ));

	DrvLib_UnmapIoSpace((PVOID)pIOPreg);

	return fRetVal;
}
#endif


VOID 
CSDHCSlotBase::HandleRemoval(
		BOOL fCancelRequest
		)

⌨️ 快捷键说明

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