📄 sdhcslot.cpp
字号:
)
{
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 = (_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(
)
{
#ifdef NEW_POWER_MANAGEMENT
DWORD waitResult;
#endif
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
#ifdef NEW_POWER_MANAGEMENT
// for wakeup problem. hsjang 070823
RETAILMSG(1,(TEXT("[HSMMC] Waiting for finishing the initialization of card\r\n")));
//waitResult = WaitForSingleObject(m_hWaitForEndofWakeup, INFINITE);
waitResult = WaitForSingleObject(m_hWaitForEndofWakeup, 10000);
if (WAIT_OBJECT_0 != waitResult )
RETAILMSG(1,(TEXT("[HSMMC] Fail to restart due to something\r\n")));
else
RETAILMSG(1,(TEXT("[HSMMC] Finished the initialization of card\r\n")));
#endif
}
SD_API_STATUS
CSDHCSlotBase::BusRequestHandler(
PSD_BUS_REQUEST pRequest
)
{
SETFNAME();
PREFAST_DEBUGCHK(pRequest);
Validate();
WORD wRegCommand;
SD_API_STATUS status;
WORD wIntStatusEn;
//2007.10.07 D.Baek
WORD wIntSignalEn;
BOOL fSuccess;
WORD wErrIntSignalEn = ReadWord(SDHC_ERROR_INT_SIGNAL_ENABLE);
WORD wErrIntStatusEn = ReadWord(SDHC_ERROR_INT_STATUS_ENABLE);
DEBUGCHK(m_dwReadyInts == 0);
DEBUGCHK(!m_fCommandCompleteOccurred);
RETAILMSG(0, (TEXT("%s CMD:%d\r\n"), pszFname, pRequest->CommandCode)); // jylee
DEBUGMSG(SDHC_SEND_ZONE, (TEXT("%s CMD:%d\r\n"), pszFname, pRequest->CommandCode));
// bypass CMD12 if AutoCMD12 was done by hardware
if (pRequest->CommandCode == 12) {
if (m_fAutoCMD12Success) {
RETAILMSG(CRC_DEBUG,(TEXT("%s AutoCMD12 Succeeded, bypass CMD12.\r\n"), pszFname));
DEBUGMSG(SDHC_SEND_ZONE, (TEXT("%s AutoCMD12 Succeeded, bypass CMD12.\r\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;
#ifdef NEW_POWER_MANAGEMENT
// for wakeup problem. hsjang 070823
if ( m_fWhileWakeup && pRequest->CommandCode == 17)
{
RETAILMSG(1,(TEXT("################# Release PM ###############\r\n")));
m_fWhileWakeup = FALSE;
SetEvent(m_hWaitForEndofWakeup);
}
#endif
// 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_40
/*************************************************************************/
/****** 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;
//--------------------------------------------------------------------------------------
//2007.10.07 D.Baek
wIntSignalEn = ReadWord(SDHC_NORMAL_INT_SIGNAL_ENABLE);
wIntSignalEn |= NORMAL_INT_ENABLE_CMD_COMPLETE | NORMAL_INT_ENABLE_TRX_COMPLETE;
//--------------------------------------------------------------------------------------
// check command inhibit, wait until OK
fSuccess = WaitForReg<DWORD>(&CSDHCSlotBase::ReadDword, SDHC_PRESENT_STATE, STATE_CMD_INHIBIT, 0);
if (!fSuccess) {
DEBUGMSG(SDCARD_ZONE_ERROR, (_T("%s Timeout waiting for CMD Inhibit\r\n"), pszFname));
RETAILMSG(1, (TEXT("%s Timeout waiting for CMD Inhibit\r\n"), pszFname)); // jylee
status = SD_API_STATUS_DEVICE_NOT_RESPONDING;
goto EXIT;
}
// programming registers
if (!TRANSFER_IS_COMMAND_ONLY(pRequest)) {
WORD wRegTxnMode = 0;
#ifdef MMC_SPEC_40
/*************************************************************************/
/****** Date : 07.05.14 ******/
/****** Developer : HS.JANG ******/
/****** Description : to support MMCmicro this code was added ******/
/*************************************************************************/
#if 1
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
/*************************************************************************/
#endif
wRegCommand |= CMD_DATA_PRESENT;
if (UseDmaForRequest(pRequest)) {
wIntStatusEn |= NORMAL_INT_ENABLE_DMA;
//2007.10.07 D.Baek
wIntSignalEn |= 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));
// WriteWord(SDHC_BLOCKSIZE, (WORD)((0x1<<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 0
if(pRequest->CommandCode == 18 || pRequest->CommandCode == 25)
wRegTxnMode |= (TXN_MODE_MULTI_BLOCK | TXN_MODE_BLOCK_COUNT_ENABLE);
else
wRegTxnMode |= ( TXN_MODE_BLOCK_COUNT_ENABLE);
#endif
// 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 ) {
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>(&CSDHCSlotBase::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(CRC_DEBUG, (TEXT("%s Timeout waiting for DAT Inhibit\r\n"), pszFname)); // jylee
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).
//---------------------------------------------------------------------------------------
// 2007.09.12 D.Baek
// The "Data CRC Error" occurs if the following code will be inserted.
// Especially, it causes this type of error to write the "Block Size" register again.
//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);
//---------------------------------------------------------------------------------------
//2007.10.07 D.Baek
WriteWord(SDHC_NORMAL_INT_SIGNAL_ENABLE, wIntSignalEn);
//---------------------------------------------------------------------------------------
// Turn the clock on. It is turned off in IndicateBusRequestComplete().
RETAILMSG(0,(TEXT("[BusRequestHandler]SDHC_CLOCK_CONTROL : 0x%x\r\n"),ReadWord(SDHC_CLOCK_CONTROL)));
SDClockOn();
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -