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

📄 sdhcslot.cpp

📁 2443 wince5.0 bsp, source code
💻 CPP
📖 第 1 页 / 共 5 页
字号:
        SDHC_CAPABILITIES_MAX_BLOCK_LENGTH_2
    };
    
    SSDHC_CAPABILITIES caps = GetCapabilities();
    
    // Determine the maximum block length
    DEBUGCHK(caps.bits.MaxBlockLen < dim(sc_rgusBlockLen));
    DWORD dwMaxBlockLen = sc_rgusBlockLen[caps.bits.MaxBlockLen];
    DEBUGCHK(dwMaxBlockLen <= SDHC_MAX_BLOCK_LENGTH);
    return dwMaxBlockLen;
}


DWORD
CSDHCSlotBase::DetermineTimeoutControl(
                                      )
{
    // We try to come as close to the desired timeout without going below it.
    
    DEBUGCHK(m_pregDevice->IsOK());
    
    SSDHC_CAPABILITIES caps = GetCapabilities();
    
    // Determine the DAT line timeout divisor.
    // We allow the registry to override what is in the capabilities register.
    DWORD dwTimeoutClock = m_pregDevice->ValueDW(SDHC_TIMEOUT_FREQUENCY_KEY);
    if (dwTimeoutClock == 0) {
        dwTimeoutClock = caps.bits.TOFreq * 1000;

        if (dwTimeoutClock == 0) {
            dwTimeoutClock = SDHC_MAX_CLOCK_FREQUENCY;
            DEBUGMSG(SDCARD_ZONE_ERROR, 
                (_T("SDHC: No timeout frequency specified. Using default of %u\n"), 
                dwTimeoutClock));
        }
        else if (caps.bits.TimeoutUnit == 1) {
            // listing is in MHz, not KHz
            dwTimeoutClock *= 1000;
        }
    }

    DEBUGCHK(dwTimeoutClock != 0);

    DWORD dwTimeoutInMS = m_pregDevice->ValueDW(SDHC_TIMEOUT_KEY, 
        SDHC_DEFAULT_TIMEOUT);

    DOUBLE dTimeoutControl = SdhcTimeoutSecondsToControl(dwTimeoutClock, 
        dwTimeoutInMS / 1000.0);
    DWORD dwTimeoutControl;
    
    if (dTimeoutControl < 0) {
        dwTimeoutControl = 0;
    }
    else {
        dTimeoutControl = ceil(dTimeoutControl);
        dwTimeoutControl= (DWORD) dTimeoutControl;
    }

    dwTimeoutControl = min(dwTimeoutControl, SDHC_TIMEOUT_CONTROL_MAX);

#ifdef DEBUG
    {        
        TCHAR szTimeout[4];
        DOUBLE dActualTimeout = SdhcTimeoutControlToSeconds(dwTimeoutClock, 
            dwTimeoutControl);
        _sntprintf(szTimeout, dim(szTimeout), _T("%0.1f"), dActualTimeout);
		DEBUGCHK(szTimeout[dim(szTimeout) - 1] == 0);
        szTimeout[dim(szTimeout) - 1] = 0; // Null-terminate
        
        DEBUGMSG(SDCARD_ZONE_INIT, (_T("SDHC: Using timeout control value of 0x%x for %s seconds\n"), 
            dwTimeoutControl, szTimeout));
    }
#endif

	dwTimeoutControl	= 0xe;
    return dwTimeoutControl;
}


DWORD 
CSDHCSlotBase::DetermineWakeupSources(
                                     )
{
    DEBUGCHK(m_pregDevice->IsOK());
    DWORD dwWakeupSources = m_pregDevice->ValueDW(SDHC_WAKEUP_SOURCES_KEY);
    dwWakeupSources &= WAKEUP_ALL_SOURCES;

    // Waking on SDIO interrupts must be enabled by the bus driver.
    dwWakeupSources &= ~WAKEUP_INTERRUPT; 

    return dwWakeupSources;
}


VOID
CSDHCSlotBase::SetVoltage(
                          DWORD dwVddSetting
                          )
{
    Validate();

	RETAILMSG(0,(TEXT("CSDHCSlotBase::SetVoltage  0x%X\n"),dwVddSetting));

    UCHAR ucVoltageSelection = SDBUS_POWER_ON;
    UCHAR ucOldVoltage;

    DEBUGCHK(dwVddSetting & m_dwVddWindows);

    if ( dwVddSetting & 
         (SD_VDD_WINDOW_3_2_TO_3_3 | SD_VDD_WINDOW_3_3_TO_3_4) ) {
        ucVoltageSelection |= SDBUS_VOLTAGE_SELECT_3_3V;
    }
    else if ( dwVddSetting & 
              (SD_VDD_WINDOW_2_9_TO_3_0 | SD_VDD_WINDOW_3_0_TO_3_1) ) {
        ucVoltageSelection |= SDBUS_VOLTAGE_SELECT_3_0V;
    }
    else if ( dwVddSetting & 
              (SD_VDD_WINDOW_1_7_TO_1_8 | SD_VDD_WINDOW_1_8_TO_1_9) ) {
        ucVoltageSelection |= SDBUS_VOLTAGE_SELECT_1_8V;
    }

    ucOldVoltage = ReadByte(SDHC_POWER_CONTROL);
    if (ucOldVoltage != ucVoltageSelection) {
        // SD Bus Power must be initially set to 0 when changing voltages
        WriteByte(SDHC_POWER_CONTROL, 0);
        WriteByte(SDHC_POWER_CONTROL, ucVoltageSelection);
        WriteByte(SDHC_POWER_CONTROL, ucVoltageSelection);		
        RETAILMSG(0,( 
            TEXT("CSDHCSlotBase::SetVoltage: Set SDHC_POWER_CONTROL reg = 0x%02x     %d\n"),
            ReadByte(SDHC_POWER_CONTROL),GetPowerSupplyRampUpMs()));		

        DEBUGMSG(SDCARD_ZONE_INFO,( 
            TEXT("CSDHCSlotBase::SetVoltage: Set SDHC_POWER_CONTROL reg = 0x%02x\n"),
            ucVoltageSelection));

        Sleep(GetPowerSupplyRampUpMs());			
    }
}


// Set up the controller according to the interface parameters.
VOID 
CSDHCSlotBase::SetInterface(
                            PSD_CARD_INTERFACE pInterface
                            )
{            
    PREFAST_DEBUGCHK(pInterface);
    Validate();
	RETAILMSG(0,(TEXT("CSDHCSlotBase::SetInterface %d\n"),pInterface->InterfaceMode));
    if (SD_INTERFACE_SD_MMC_1BIT == pInterface->InterfaceMode) {
        DEBUGMSG(SDCARD_ZONE_INIT, 
            (TEXT("SHCSDSlotOptionHandler - Setting for 1 bit mode \n")));
        RETAILMSG(1, 
            (TEXT("SHCSDSlotOptionHandler - Setting for 1 bit mode , Clock Rate =%d \n"),pInterface->ClockRate));		
        WriteByte(SDHC_HOST_CONTROL, 0);

        m_f4BitMode = FALSE;
    } else if (SD_INTERFACE_SD_4BIT == pInterface->InterfaceMode) {
        DEBUGMSG(SDCARD_ZONE_INIT, 
            (TEXT("SHCSDSlotOptionHandler - Setting for 4 bit mode \n")));
        RETAILMSG(1, 
            (TEXT("SHCSDSlotOptionHandler - Setting for 4 bit mode , Clock Rate =%d \n"),pInterface->ClockRate));
        WriteByte(SDHC_HOST_CONTROL, HOSTCTL_DAT_WIDTH);

        m_f4BitMode = TRUE;
    } else if (SD_INTERFACE_MMC_8BIT == pInterface->InterfaceMode) {
        DEBUGMSG(SDCARD_ZONE_INIT, 
            (TEXT("SHCSDSlotOptionHandler - Setting for 8 bit mode \n")));
        RETAILMSG(1, 
            (TEXT("SHCSDSlotOptionHandler - Setting for 8 bit mode , Clock Rate =%d \n"),pInterface->ClockRate));		
        WriteByte(SDHC_HOST_CONTROL, HOSTCTL_DAT_WIDTH_8BIT|HOSTCTL_HIGHSPEED);

        m_f4BitMode = TRUE;
    }else {
        DEBUGCHK(FALSE);
    }

    SetClockRate(&pInterface->ClockRate);
}


VOID
CSDHCSlotBase::SetPowerState(
                             CEDEVICE_POWER_STATE cpsNew
                             )
{
    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(
                       )
{
    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
}


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

⌨️ 快捷键说明

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