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

📄 sdhcslot.cpp

📁 Samsung公司S3C2443芯片的BSP源码包
💻 CPP
📖 第 1 页 / 共 5 页
字号:
            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));
		RETAILMSG(1,(TEXT("CSDHCSlotBase::HandleDma\n")));
		RETAILMSG(1,(TEXT("pRequest->HCParam=%d, CB_DMA_PAGE=%d, TRANSFER_SIZE(pRequest)=%d\n"),pRequest->HCParam,CB_DMA_PAGE,TRANSFER_SIZE(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)) {
		RETAILMSG(1,(TEXT("dwNewHCParam < TRANSFER_SIZE(pRequest)\n")));			
            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);
            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;
	RETAILMSG(1,(TEXT("CSDHCSlotBase::SetHardwarePowerState 0x%08X\n"),this));
    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();
    }
}



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 wIntStatusEn = ReadWord(SDHC_NORMAL_INT_STATUS_ENABLE);
    if (fEnable) {
		isSDIOInterrupt = FALSE;
	RETAILMSG(0,(TEXT("DoEnableSDIOInterrupts TRUE\n")));		
        wIntStatusEn |= NORMAL_INT_ENABLE_CARD_INT;
    }
    else {
		isSDIOInterrupt = TRUE;		
	RETAILMSG(0,(TEXT("DoEnableSDIOInterrupts FALSE\n")));		
        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));
    }


	// set Clock Source to EPLL	added by JJG	06.10.11
	WriteDword(SDHC_CONTROL2, (0x1<<15)|(0x1<<14)|(0x1<<8)|(0x2/*EPLL*/<<4) );
	WriteDword(SDHC_CONTROL3, (0<<31) | (1<<23) | (0<<15) | (1<<7) );

    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_REQUEST
CSDHCSlotBase::GetAndLockCurrentRequest() {
    return SDHCDGetAndLockCurrentRequest(m_pHCDContext,
        (UCHAR) m_dwSlot);
}


VOID CSDHCSlotBase::PowerUpDown(BOOL fPowerUp, BOOL fKeepPower) {
    SDHCDPowerUpDown(m_pHCDContext, fPowerUp, fKeepPower,
        (UCHAR) m_dwSlot);
    
}


VOID 
CSDHCSlotBase::IndicateBusRequestComplete(
    PSD_BUS_REQUEST pRequest,
    SD_API_STATUS status
    )
{
	RETAILMSG(0,(TEXT("CSDHCSlotBase::IndicateBusRequestComplete\n")));
    const WORD c_wTransferIntSources = 
        NORMAL_INT_STATUS_CMD_COMPLETE | 
        NORMAL_INT_STATUS_TRX_COMPLETE |
        NORMAL_INT_STATUS_DMA |
        NORMAL_INT_STATUS_BUF_WRITE_RDY | 
        NORMAL_INT_STATUS_BUF_READ_RDY;
        
    DEBUGCHK(pRequest);

    if ( (m_fSDIOInterruptsEnabled && m_f4BitMode) == FALSE ) {
        SDClockOff();
    }
    // else need to leave clock on in order to receive interrupts in 4 bit mode
    
    // Turn off LED.
    EnableLED(TRUE);

    // Turn off interrupt sources
    WORD wIntStatusEn = ReadWord(SDHC_NORMAL_INT_STATUS_ENABLE);
    wIntStatusEn &= ~c_wTransferIntSources;
    WriteWord(SDHC_NORMAL_INT_STATUS_ENABLE, wIntStatusEn);

    // Clear any remaining spurious interrupts.
    WriteWord(SDHC_NORMAL_INT_STATUS, c_wTransferIntSources);

#ifdef DEBUG
    m_dwReadyInts = 0;
#endif

    m_fCommandCompleteOccurred = FALSE;

    SDHCDIndicateBusRequestComplete(m_pHCDContext,
        pRequest, status);
}


VOID 
CSDHCSlotBase::SetClockRate(
                            PDWORD pdwRate
                            )
{
	RETAILMSG(0,(TEXT("DEBUGCHK(m_dwMa

⌨️ 快捷键说明

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