📄 sdhc.cpp
字号:
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 *)®Val, sizeof(DWORD), (VOID *)®Val, sizeof(DWORD), &cbRet);
regVal = PRCM_ICLKEN1_CORE_EN_MMC;
KernelIoControl(IOCTL_ICLK1_ENB, (VOID *)®Val, sizeof(DWORD), (VOID *)®Val, 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 *)®Val, sizeof(DWORD), (VOID *)®Val, sizeof(DWORD), &cbRet);
regVal = PRCM_ICLKEN1_CORE_EN_MMC;
KernelIoControl(IOCTL_ICLK1_DIS, (VOID *)®Val, sizeof(DWORD), (VOID *)®Val, 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 + -