?? sdhcslot.cpp
字號(hào):
}
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;
}
?? 快捷鍵說(shuō)明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號(hào)
Ctrl + =
減小字號(hào)
Ctrl + -