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

📄 sdhcslot.cpp

📁 6410BSP3
💻 CPP
📖 第 1 页 / 共 5 页
字号:
        }
        else {
            cps = D4;
        }

        SetHardwarePowerState(cps);
    }

    BOOL fKeepPower = FALSE;
    if (m_fSleepsWithPower || m_cpsCurrent == D0) {
        DEBUGCHK(!m_fSleepsWithPower || m_cpsCurrent == D3);
        fKeepPower = TRUE;
    }
    else
        m_fFakeCardRemoval = 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);
    if (m_fFakeCardRemoval){
        Start();
        SetInterruptEvent();
    }
}
//
// For BC, 
// 1. Returns SD_API_STATUS_FAST_PATH_SUCCESS, callback is NOT called. Fastpass only.
// 2. Return !SD_API_SUCCESS(status). callback is NOT called.
// 3. Return SD_API_STATUS_SUCCESS, callback is called
// 4. Return SD_API_STATUS_PENDING, callback is NOT call Yet.
//
    SD_API_STATUS
CSDHCSlotBase::BusRequestHandler( PSD_BUS_REQUEST pRequest)
{
    SETFNAME();
    SD_API_STATUS status;
    PREFAST_DEBUGCHK(pRequest);
    Validate();
    DEBUGMSG(SDHC_SEND_ZONE, (TEXT("%s CMD:%d\n"), pszFname, pRequest->CommandCode));

    if (m_pCurrentRequest) { // We have outstand request.
        ASSERT(FALSE);
        IndicateBusRequestComplete(pRequest, SD_API_STATUS_CANCELED);
        m_pCurrentRequest = NULL;
    }
    if (!m_fCardPresent) {
        status= SD_API_STATUS_DEVICE_REMOVED;
    }
    else {
        WORD wIntSignals = ReadWord(SDHC_NORMAL_INT_SIGNAL_ENABLE);
        WriteWord(SDHC_NORMAL_INT_SIGNAL_ENABLE,0);
        m_fCurrentRequestFastPath = FALSE ;
        m_pCurrentRequest = pRequest ;
        // if no data transfer involved, use FAST PATH
        if ((pRequest->SystemFlags & SD_FAST_PATH_AVAILABLE)!=0) { // Fastpath
            m_fCurrentRequestFastPath = TRUE;
            status = SubmitBusRequestHandler( pRequest );
            if( status == SD_API_STATUS_PENDING ) { // Polling for completion.
                BOOL fCardInserted = TRUE;
                DWORD dwStartTicks = GetTickCount();
#ifdef _SMDK6410_CH0_EXTCD_
                if (m_pCurrentRequest && 
                        (fCardInserted = (IsCardPresent() & TRUE)!=0) &&
                        GetTickCount() - dwStartTicks <= m_dwFastPathTimeoutTicks) {
#else
                    while (m_pCurrentRequest &&
                            (fCardInserted = (ReadDword(SDHC_PRESENT_STATE) & STATE_CARD_INSERTED)!=0 ) &&
                            ((GetTickCount() - dwStartTicks) <= m_dwFastPathTimeoutTicks)) {
#endif
                        HandleInterrupt();
                    } 
                    if (m_pCurrentRequest && fCardInserted ) { 
                        // Time out , need to switch to asyn.it will call callback after this
                        pRequest->SystemFlags &= ~SD_FAST_PATH_AVAILABLE;
                        m_fCurrentRequestFastPath = FALSE ;
                    }
                    else { // Fastpass completed.
                        status = m_FastPathStatus;
                        // Clear before status of fastpath.
                        m_FastPathStatus = 0;
                        if (m_pCurrentRequest) {
                            ASSERT(FALSE);
                            status = SD_API_STATUS_DEVICE_REMOVED;
                        }
                    }
                }
                if (status == SD_API_STATUS_SUCCESS) {
                    status = SD_API_STATUS_FAST_PATH_SUCCESS;
                }
            }
            else
                status = SubmitBusRequestHandler( pRequest );

            if (status!=SD_API_STATUS_PENDING && m_pCurrentRequest) { 
                // if there is error case. We don't notify the callback function either So.
                m_fCurrentRequestFastPath = TRUE;
                IndicateBusRequestComplete(pRequest,status);
            }
            WriteWord(SDHC_NORMAL_INT_SIGNAL_ENABLE,wIntSignals);
        }

        return status;
    }


    SD_API_STATUS
        CSDHCSlotBase::SubmitBusRequestHandler(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);

            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) {
                    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:
                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;

            // 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));
                status = SD_API_STATUS_DEVICE_NOT_RESPONDING;
                goto EXIT;
            }

            // programming registers
            if (!TRANSFER_IS_COMMAND_ONLY(pRequest)) {
                WORD wRegTxnMode = 0;        
#ifdef _MMC_SPEC_42_
                // To distinguish btween MMCmicro and MMCplus, we will issue MMC_CMD_SEND_EXT_CSD.
                // At that time, Dat line is 8bit. If the inserted card is MMCmicro, "Data timeout" error will be occurred.
                // Because MMCmicro does not supports 8bit DAT line but 4bit. To reduce the delay time on Data timeout error occurring,
                // we modify the timeout value.
                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 (m_SlotDma &&  m_SlotDma->ArmDMA(*pRequest,TRANSFER_IS_WRITE(pRequest))) {
                    wIntStatusEn |= NORMAL_INT_ENABLE_DMA;
                    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));
                ASSERT(PAGE_SIZE == 0x1000);
                WriteWord(SDHC_BLOCKSIZE, (WORD)(pRequest->BlockSize & 0xfff) | (0<<12)); // SDHC 2.2.2, CE is 4k-aligned page.

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

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

            // Status Busy bit checking for clearing the interrupt status register before "CMD ISSUE".
            fSuccess = WaitForReg<DWORD>(&CSDHCSlotBase::ReadDword, SDHC_CONTROL4, SDHC_CONTROL4_STABUSY, 0); 
            if (!fSuccess) {
                DEBUGMSG(SDCARD_ZONE_ERROR, (_T("%s Timeout waiting for CMD operation finish\r\n"),
                            pszFname));
                status = SD_API_STATUS_DEVICE_NOT_RESPONDING;
                goto EXIT;
            }

            // 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);
            if (m_fCommandPolling  ) {
                PollingForCommandComplete();
            }
            status = SD_API_STATUS_PENDING;

EXIT:
            return status;
        }

⌨️ 快捷键说明

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