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

📄 sdhc.cpp

📁 Windows CE 6.0 BSP for the Beagle Board.
💻 CPP
📖 第 1 页 / 共 5 页
字号:
        wDiv = 0x03FF;

    DEBUGMSG(SHC_CLOCK_ZONE, (L"wDiv = 0x%x 0x%x", wDiv, *pdwRate
    ));

    // Program the divisor, but leave the rest of the register alone.
    WORD wRegValue = INREG16(&m_vpSDIOReg->MMC_CON);

    OUTREG16(&m_vpSDIOReg->MMC_CON, ((wRegValue & ~0x03FF) | wDiv));

    
    *pdwRate = MMCSD_CLOCK_INPUT / wDiv;
    DEBUGMSG(SHC_CLOCK_ZONE,(L"CSDIOControllerBase::SetClockRate: "
        L"Actual clock rate = 0x%x\n", *pdwRate
    ));
}

//  Turn on the clock
VOID 
CSDIOControllerBase::ClockOn()
{
    // Enable MMC clock - clocks on by default
    DWORD cbRet;
    DWORD regVal = PRCM_FCLKEN1_CORE_EN_MMC;
    KernelIoControl(IOCTL_FCLK1_ENB, (VOID *)&regVal, sizeof(DWORD), (VOID *)&regVal, sizeof(DWORD), &cbRet);
    regVal = PRCM_ICLKEN1_CORE_EN_MMC;
    KernelIoControl(IOCTL_ICLK1_ENB, (VOID *)&regVal, sizeof(DWORD), (VOID *)&regVal, sizeof(DWORD), &cbRet);   
}

// Turn the clock off
VOID 
CSDIOControllerBase::ClockOff()
{
    // disable MMC clock
    DWORD cbRet;
    DWORD regVal = PRCM_FCLKEN1_CORE_EN_MMC;
    KernelIoControl(IOCTL_FCLK1_DIS, (VOID *)&regVal, sizeof(DWORD), (VOID *)&regVal, sizeof(DWORD), &cbRet);
    regVal = PRCM_ICLKEN1_CORE_EN_MMC;
    KernelIoControl(IOCTL_ICLK1_DIS, (VOID *)&regVal, sizeof(DWORD), (VOID *)&regVal, sizeof(DWORD), &cbRet);   
}



// Issues the specified SDI command
SD_API_STATUS
CSDIOControllerBase::SendCommand( PSD_BUS_REQUEST pRequest )
{
    WORD MMC_CMD;
    DWORD dwCurrentTickCount;
    DWORD dwTimeout;
    DWORD dwCountStart;
    BOOL  fTimeoutOverflow = FALSE;
    UINT16 Cmd = pRequest->CommandCode;
    UINT32 Arg = pRequest->CommandArgument;
    UINT16 respType = pRequest->CommandResponse.ResponseType;
    UINT16 TransferClass = pRequest->TransferClass;

    DEBUGMSG(SHC_SEND_ZONE, (L"CSDIOControllerBase::SendCommand: "
        L"Cmd = 0x%x Arg = 0x%x respType = 0x%x TransferClass = 0x%x\r\n", Cmd, Arg, respType, TransferClass
    ));

    if( TransferClass == SD_READ || TransferClass == SD_WRITE )
    {
        DEBUGMSG(SHC_SDBUS_INTERACT_ZONE, (L"CSDIOControllerBase::SendCommand: "
            L"Cmd=0x%04x, Arg=0x%08x, RespType=0x%04x, Data=0x%x <%dx%d>) starts\r\n", 
            Cmd, Arg, respType, (TransferClass==SD_COMMAND)?FALSE:TRUE, pRequest->NumBlocks, pRequest->BlockSize
        ));
    }
    else
    {
        DEBUGMSG(SHC_SDBUS_INTERACT_ZONE, (L"CSDIOControllerBase::SendCommand: "
            L"Cmd=0x%04x, Arg=0x%08x, RespType=0x%04x, Data=0x%x) starts\r\n", 
            Cmd, Arg, respType, (TransferClass==SD_COMMAND)?FALSE:TRUE
        ));
    }

    // turn the clock on
    ClockOn();

    WORD MMC_STAT = Read_MMC_STAT();

    if ( MMC_STAT & MMC_STAT_CB )
    {
        DEBUGMSG(SHC_BUSY_STATE_ZONE, (L"CSDIOControllerBase::SendCommand: "
            L"Card in busy state before command sent!\r\n"
        ));
    }

    if (m_fFirstTime) 
    {
        m_fFirstTime = FALSE;

        // Clear the MMC_STAT register
        Write_MMC_STAT( Read_MMC_STAT() & (~MMC_STAT_CIRQ) );

        // temporarily mask all interrupts
        OUTREG16(&m_vpSDIOReg->MMC_IE, 0x00);

        // send the initialization command
        OUTREG16(&m_vpSDIOReg->MMC_CMD, 0x80);

        // calculate timeout conditions
        dwCountStart = GetTickCount();
        dwTimeout = dwCountStart + m_dwMaxTimeout;
        if( dwTimeout < dwCountStart )
            fTimeoutOverflow = TRUE;

        // poll until command complete
        while( !( Read_MMC_STAT() & ( MMC_IE_EOC | MMC_IE_CTO | MMC_IE_CCRC | MMC_IE_CERR ) ) )
        {
            // check for a timeout
            dwCurrentTickCount = GetTickCount();
            if( fTimeoutOverflow ? ( dwTimeout < dwCurrentTickCount && dwCurrentTickCount < dwCountStart )
                : ( dwTimeout < dwCurrentTickCount || dwCurrentTickCount < dwCountStart ) )
            {
                DEBUGMSG(SDCARD_ZONE_ERROR, (L"CSDIOControllerBase::SendCommand: "
                    L"Exit: TIMEOUT while sending INIB.\r\n"
                ));
                ClockOff();
                return SD_API_STATUS_UNSUCCESSFUL;
            }

            // check for card ejection
            if( !SDCardDetect() )
            {
                DEBUGMSG(SDCARD_ZONE_ERROR, (L"CSDIOControllerBase::SendCommand: "
                    L"Exit: card ejected while sending INIB.\r\n"
                ));
                ClockOff();
                return SD_API_STATUS_DEVICE_REMOVED;
            }
        }

        // Clear the MMC_STAT register
        Write_MMC_STAT( Read_MMC_STAT() & (~MMC_STAT_CIRQ) );

        // unmask interrupts
        OUTREG16(&m_vpSDIOReg->MMC_IE, (MMC_IE_EOC | MMC_IE_CTO | MMC_IE_CCRC | MMC_IE_CERR | MMC_IE_BRS));           
    }

    // Clear the MMC_STAT register before issues command.
    Write_MMC_STAT( Read_MMC_STAT() & (~MMC_STAT_CIRQ) );

    MMC_CMD = Cmd;
    ASSERT( ( MMC_CMD & 0x003f ) == MMC_CMD );

    if( m_fAppCmdMode )
    {
        ASSERT( gwaCMD[Cmd].ACmd != 0 );
        MMC_CMD |= gwaCMD[Cmd].ACMD_TYPE;
    }
    else
    {
        if( m_fMMCMode )
        {
            ASSERT( gwaCMD[Cmd].Cmd != 0 || gwaCMD[Cmd].MMCCmd != 0 );
            if( gwaCMD[Cmd].MMCCmd )
                MMC_CMD |= gwaCMD[Cmd].MMC_CMD_TYPE;
            else
                MMC_CMD |= gwaCMD[Cmd].CMD_TYPE;
        }
        else
        {
            ASSERT( gwaCMD[Cmd].Cmd != 0 || gwaCMD[Cmd].MMCCmd != 0 );
            MMC_CMD |= gwaCMD[Cmd].CMD_TYPE;
        }
    }

    switch( respType )
    {
    case ResponseR1:                // Short response required
        MMC_CMD |= 0x100;
        break;
    case ResponseR1b:
        MMC_CMD |= 0x900;
        break;
    case ResponseR2:
        MMC_CMD |= 0x200;
        break;
    case ResponseR3:
        MMC_CMD |= 0x300;
        break;
    case ResponseR4:
        MMC_CMD |= 0x400;
        Write_MMC_SDIO( Read_MMC_SDIO() | MMC_IE_CTO ); // disable CRC check in R4 response
        break;
    case ResponseR5:                
        MMC_CMD |= 0x500;
        break;
    case ResponseR6:
        MMC_CMD |= 0x600;
        break;
    }

    if ((Cmd == SD_CMD_IO_RW_DIRECT) || (Cmd == SD_CMD_IO_RW_EXTENDED))
    {
        Write_MMC_SDIO( Read_MMC_SDIO() | ( BIT15 | BIT6 ) );
        MMC_CMD |= 0x0040;
    }

    CLRREG16(&m_vpSDIOReg->MMC_BUF, (MMC_BUF_RXDE|MMC_BUF_TXDE));

    if( TransferClass == SD_READ )
    {
        MMC_CMD |= 0x8000;
        OUTREG16(&m_vpSDIOReg->MMC_BLEN, ((WORD)(( pRequest->BlockSize - 1 ) & 0x7ff)));
        OUTREG16(&m_vpSDIOReg->MMC_NBLK, ((WORD)(( pRequest->NumBlocks - 1 ) & 0x7ff)));
    }
    else if( TransferClass == SD_WRITE )
    {
        MMC_CMD &= ~0x8000;
        OUTREG16(&m_vpSDIOReg->MMC_BLEN, ((WORD)(( pRequest->BlockSize - 1 ) & 0x7ff)));
        OUTREG16(&m_vpSDIOReg->MMC_NBLK, ((WORD)(( pRequest->NumBlocks - 1 ) & 0x7ff)));
    }

    // Program the argument into the argument registers
    OUTREG16(&m_vpSDIOReg->MMC_ARG1, Arg);
    OUTREG16(&m_vpSDIOReg->MMC_ARG2, ((WORD)(Arg >> 16)));

    DEBUGMSG(SHC_SEND_ZONE, (L"CSDIOControllerBase::SendCommand: "
        L"Registers:Command = 0x%x, MMC_ARG1 = 0x%x, MMC_ARG2 = 0x%x\r\n",
        MMC_CMD, m_vpSDIOReg->MMC_ARG1 , m_vpSDIOReg->MMC_ARG2
    ));

    MMC_STAT = Read_MMC_STAT();

    // Issue the command.
    OUTREG16(&m_vpSDIOReg->MMC_CMD, MMC_CMD);
    MMC_STAT = Read_MMC_STAT();

    return SD_API_STATUS_PENDING;
}

///////////////////////////////////////////////////////////////////////////////////////////////

// Remove the device instance in the slot
VOID 
CSDIOControllerBase::HandleRemoval(
                                   BOOL fCancelRequest
                                   )
{    
    m_fCardPresent = FALSE;
    m_fMMCMode = FALSE;

    IndicateSlotStateChange(DeviceEjected);

    // turn clock off and remove power from the slot
    ClockOff();
    TurnCardPowerOff();

    // turn off SDIO interrupts
    if( m_fSDIOInterruptsEnabled )
    {
        DisableSDIOInterrupts();
    }

    if (fCancelRequest) {
        // get the current request  
        PSD_BUS_REQUEST pRequest = GetAndLockCurrentRequest();

        if (pRequest != NULL) {
            DEBUGMSG(SDCARD_ZONE_WARN, (L"CSDIOControllerBase::HandleRemoval: "
                L"Card Removal Detected - Canceling current request: 0x%08X, command: %d\r\n", 
                pRequest, pRequest->CommandCode
            ));
            DumpRequest(pRequest);
            IndicateBusRequestComplete(pRequest, SD_API_STATUS_DEVICE_REMOVED);
            
            ClockOff();
        }
    }
}


// Initialize the card
VOID 
CSDIOControllerBase::HandleInsertion()
{
    DWORD dwClockRate = SD_DEFAULT_CARD_ID_CLOCK_RATE;

    m_fCardPresent = TRUE;

    DEBUGMSG(SDCARD_ZONE_FUNC, (L"+CSDIOControllerBase::HandleInsertion\r\n"));

    // turn power to the card on
    TurnCardPowerOn();

    SetClockRate(&dwClockRate);
    
    ClockOn();

    // indicate device arrival
    IndicateSlotStateChange(DeviceInserted);
}

// Static interrupt routine for the entire controller.
VOID CSDIOControllerBase::HandleCardDetectInterrupt() 
{
    DEBUGMSG(SHC_INTERRUPT_ZONE, (L"+CSDHCSlot::HandleCardDetectInterrupt\r\n"));

    SDHCDAcquireHCLock(m_pHCContext);

    if( SDCardDetect() )
    {
        DEBUGMSG(SHC_INTERRUPT_ZONE, (L"CSDHCSlot::HandleCardDetectInterrupt: "
            L"Card is Inserted!\r\n"
        ));
        
        if( m_fCardPresent == FALSE || m_bReinsertTheCard ) {
            m_bReinsertTheCard = FALSE;
            m_fFirstTime = TRUE;
            HandleInsertion();
        }
    }
    else if( m_fCardPresent ) 
    {
        DEBUGMSG(SHC_INTERRUPT_ZONE, (L"CSDHCSlot::HandleCardDetectInterrupt: "
            L"Card is Removed!\r\n"));
        HandleRemoval(TRUE);
    }

    SDHCDReleaseHCLock(m_pHCContext);
}


#ifdef ENABLE_DEBUG

// Reads from SD Standard Host registers and writes them to the debugger.
VOID CSDIOControllerBase::DumpRegisters()
{
    EnterCriticalSection( &m_critSec );
    DEBUGMSG(SDCARD_ZONE_INIT, (L"+DumpStdHCRegs-------------------------\r\n"));
    DEBUGMSG(SDCARD_ZONE_INIT, (L"MMC_CMD 0x%04X \r\n", m_vpSDIOReg->MMC_CMD    ));
    DEBUGMSG(SDCARD_ZONE_INIT, (L"MMC_ARG1 0x%04X \r\n", m_vpSDIOReg->MMC_ARG1  ));
    DEBUGMSG(SDCARD_ZONE_INIT, (L"MMC_ARG2 0x%04X \r\n", m_vpSDIOReg->MMC_ARG2  ));
    DEBUGMSG(SDCARD_ZONE_INIT, (L"MMC_CON  0x%04X \r\n", m_vpSDIOReg->MMC_CON   ));
    DEBUGMSG(SDCARD_ZONE_INIT, (L"MMC_STAT 0x%04X \r\n", m_vpSDIOReg->MMC_STAT  ));
    DEBUGMSG(SDCARD_ZONE_INIT, (L"MMC_IE 0x%04X \r\n", m_vpSDIOReg->MMC_IE  ));
    DEBUGMSG(SDCARD_ZONE_INIT, (L"MMC_CTO 0x%04X \r\n", m_vpSDIOReg->MMC_CTO    ));
    DEBUGMSG(SDCARD_ZONE_INIT, (L"MMC_DTO 0x%04X \r\n", m_vpSDIOReg->MMC_DTO    ));
    DEBUGMSG(SDCARD_ZONE_INIT, (L"MMC_DATA 0x---- \r\n"/*, m_vpSDIOReg->MMC_DATA*/  ));
    DEBUGMSG(SDCARD_ZONE_INIT, (L"MMC_BLEN 0x%04X \r\n", m_vpSDIOReg->MMC_BLEN  ));
    DEBUGMSG(SDCARD_ZONE_INIT, (L"MMC_NBLK 0x%04X \r\n", m_vpSDIOReg->MMC_NBLK  ));
    DEBUGMSG(SDCARD_ZONE_INIT, (L"MMC_BUF 0x%04X \r\n", m_vpSDIOReg->MMC_BUF    ));
    DEBUGMSG(SDCARD_ZONE_INIT, (L"MMC_SDIO 0x%04X \r\n", m_vpSDIOReg->MMC_SDIO  ));
    DEBUGMSG(SDCARD_ZONE_INIT, (L"MMC_SYSTEST 0x%04X \r\n", m_vpSDIOReg->MMC_SYSTEST    ));
    DEBUGMSG(SDCARD_ZONE_INIT, (L"MMC_REV 0x%04X \r\n", m_vpSDIOReg->MMC_REV    ));
    DEBUGMSG(SDCARD_ZONE_INIT, (L"MMC_RSP0 0x%04X \r\n", m_vpSDIOReg->MMC_RSP0  ));
    DEBUGMSG(SDCARD_ZONE_INIT, (L"MMC_RSP1 0x%04X \r\n", m_vpSDIOReg->MMC_RSP1  ));
    DEBUGMSG(SDCARD_ZONE_INIT, (L"MMC_RSP2 0x%04X \r\n", m_vpSDIOReg->MMC_RSP2  ));
    DEBUGMSG(SDCARD_ZONE_INIT, (L"MMC_RSP3 0x%04X \r\n", m_vpSDIOReg->MMC_RSP3  ));
    DEBUGMSG(SDCARD_ZONE_INIT, (L"MMC_RSP4 0x%04X \r\n", m_vpSDIOReg->MMC_RSP4  ));
    DEBUGMSG(SDCARD_ZONE_INIT, (L"MMC_RSP5 0x%04X \r\n", m_vpSDIOReg->MMC_RSP5  ));
    DEBUGMSG(SDCARD_ZONE_INIT, (L"MMC_RSP6 0x%04X \r\n", m_vpSDIOReg->MMC_RSP6  ));
    DEBUGMSG(SDCARD_ZONE_INIT, (L"MMC_RSP7 0x%04X \r\n", m_vpSDIOReg->MMC_RSP7  ));
    DEBUGMSG(SDCARD_ZONE_INIT, (L"MMC_IOSR 0x%04X \r\n", m_vpSDIOReg->MMC_IOSR  ));
    DEBUGMSG(SDCARD_ZONE_INIT, (L"MMC_SYSC 0x%04X \r\n", m_vpSDIOReg->MMC_SYSC  ));
    DEBUGMSG(SDCARD_ZONE_INIT, (L"MMC_SISS 0x%04X \r\n", m_vpSDIOReg->MMC_SISS  ));
    DEBUGMSG(SDCARD_ZONE_INIT, (L"-DumpStdHCRegs-------------------------\r\n"));
    LeaveCriticalSection( &m_critSec );
}

#endif

CSDIOControllerBase::~CSDIOControllerBase()
{
    DeleteCriticalSection( &m_critSec );
}

BOOL CSDIOControllerBase::Init( LPCTSTR pszActiveKey )
{
    PSDCARD_HC_CONTEXT pHostContext = NULL; // new HC context
    SD_API_STATUS      status;              // SD status
    HKEY               hKeyDevice = NULL;   // device key
    CReg               regDevice;           // encapsulated device key
    DWORD              dwRet = 0;           // return value    

⌨️ 快捷键说明

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