sdhcslot.cpp

来自「S3C2450BSP开发包,里面有很多资料。可以提供大家参考下。有什么需要解决问」· C++ 代码 · 共 1,936 行 · 第 1/5 页

CPP
1,936
字号
            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;
                memcpy(rgdwIntermediateBuffer, pdwUserBuffer, pRequest->BlockSize);
            }

            DWORD dwDwordsRemaining = cDwords;
            pRequest->HCParam += dwDwordsRemaining * 4;

            // Write data to buffer data port
            while ( dwDwordsRemaining-- ) {
                WriteDword(SDHC_BUFFER_DATA_PORT_0, *(pdwBuffer++));
            }

            if ( dwRemainder != 0 ) {
                DWORD dwLastWord = 0;
                memcpy(&dwLastWord, pdwBuffer, dwRemainder);
                WriteDword(SDHC_BUFFER_DATA_PORT_0, dwLastWord);
                pRequest->HCParam += dwRemainder;
            }

            SetProcPermissions(dwOldPermissions);
        }
        __except(SDProcessException(GetExceptionInformation())) {
            DEBUGMSG(SDCARD_ZONE_ERROR, (_T("Exception reading from client buffer!\r\n")));
            SetProcPermissions(dwOldPermissions);
            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_IN

⌨️ 快捷键说明

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