📄 sdiocontrollerbase.cpp
字号:
DWORD dwWaitCount = 0;
//----- 13. Wait until the I/O transfer is complete -----
while(!(vm_pSDIReg->SDIDSTA & DATA_TRANSMIT_FINISHED))
{
dwWaitCount++;
if( dwWaitCount > WAIT_TIME )
{
DEBUGMSG(SDCARD_ZONE_ERROR, (TEXT("SDHCD:SDHControllerIstThread() - timeout waiting for DMA transfer completion!\r\n")));
status = SD_API_STATUS_DATA_TIMEOUT;
goto TRANSFER_DONE;
}
if( !IsCardPresent() )
{
DEBUGMSG(SDCARD_ZONE_ERROR, (TEXT("SDHCD:SDHControllerIstThread() - Card ejected!\r\n")));
status = SD_API_STATUS_DEVICE_REMOVED;
goto TRANSFER_DONE;
}
if((vm_pSDIReg->SDIFSTA & FIFO_FAIL_ERROR))
{
vm_pSDIReg->SDIDSTA = BUSY_CHECKS_FINISH;
vm_pSDIReg->SDIFSTA &= FIFO_FAIL_ERROR;
DEBUGMSG(SDCARD_ZONE_ERROR, (TEXT("SDHCD:SDHControllerIstThread() - FIFO Error waiting for DMA transfer completion!\r\n")));
status = SD_API_STATUS_DATA_ERROR;
goto TRANSFER_DONE;
}
if((vm_pSDIReg->SDIDSTA & DATA_TRANSMIT_CRC_ERROR))
{
vm_pSDIReg->SDIDSTA = BUSY_CHECKS_FINISH | DATA_TRANSMIT_CRC_ERROR;
DEBUGMSG(SDCARD_ZONE_ERROR, (TEXT("SDHCD:SDHControllerIstThread() - Transmit CRC Error waiting for DMA transfer completion!\r\n")));
status = SD_API_STATUS_DATA_ERROR;
goto TRANSFER_DONE;
}
if((vm_pSDIReg->SDIDSTA & DATA_RECEIVE_CRC_ERROR))
{
vm_pSDIReg->SDIDSTA = BUSY_CHECKS_FINISH | DATA_RECEIVE_CRC_ERROR;
DEBUGMSG(SDCARD_ZONE_ERROR, (TEXT("SDHCD:SDHControllerIstThread() - Receive CRC Error waiting for DMA transfer completion!\r\n")));
status = SD_API_STATUS_DATA_ERROR;
goto TRANSFER_DONE;
}
if((vm_pSDIReg->SDIDSTA & DATA_TIME_OUT))
{
vm_pSDIReg->SDIDSTA = BUSY_CHECKS_FINISH | DATA_TIME_OUT;
DEBUGMSG(SDCARD_ZONE_ERROR, (TEXT("SDHCD:SDHControllerIstThread() - Data timeout waiting for DMA transfer completion!\r\n")));
status = SD_API_STATUS_DATA_TIMEOUT;
goto TRANSFER_DONE;
}
}
vm_pSDIReg->SDIDSTA = DATA_TRANSMIT_FINISHED;
//----- 14. For READ requests, be sure to copy the data read from the DMA memory into the caller's buffer -----
if(pRequest->TransferClass == SD_READ)
{
BOOL fNoException;
DEBUGCHK(m_dwNumBytesToTransfer <= MAXIMUM_DMA_TRANSFER_SIZE);
SD_SET_PROC_PERMISSIONS_FROM_REQUEST( pRequest ) {
fNoException = SDPerformSafeCopy( pRequest->pBlockBuffer, m_pDMABuffer, m_dwNumBytesToTransfer );
} SD_RESTORE_PROC_PERMISSIONS();
if (fNoException == FALSE) {
status = SD_API_STATUS_ACCESS_VIOLATION;
goto TRANSFER_DONE;
}
}
//----- 15. I/O is complete. Finish the bus request! -----
status = SD_API_STATUS_SUCCESS;
}
TRANSFER_DONE:
if( !( Is_SDIO_Interrupt_Enabled() && ( Get_SDI_Bus_Width() == WIDE_BUS_ENABLE ) ) )
{
Stop_SDI_Clock();
}
m_CurrentState = CommandComplete;
SDHCDIndicateBusRequestComplete(m_pHCContext, pRequest, status);
pRequest = NULL;
}
return TRUE;
}
///////////////////////////////////////////////////////////////////////////////
// CSDIOControllerBase::IOInterruptIstThread - IST thread for SDIO Interrupts
// Input: pHCDevice - the controller instance
// Output:
// Return: thread exit code
// Notes:
///////////////////////////////////////////////////////////////////////////////
DWORD CSDIOControllerBase::IOInterruptIstThread()
{
if( m_nSDIOIstThreadPriority != 0xffffffff && !CeSetThreadPriority( GetCurrentThread(), m_nSDIOIstThreadPriority ) )
{
DEBUGMSG(SDCARD_ZONE_WARN,(TEXT("SDHCDriver:SDIOInterruptIstThread(): warning, failed to set CEThreadPriority \r\n")));
}
for(;;)
{
//----- 1. Wait for a SDIO interrupt -----
if(WaitForSingleObject(m_hSDIOInterruptEvent, INFINITE) != WAIT_OBJECT_0)
{
DEBUGMSG(SDCARD_ZONE_WARN, (TEXT("SDHCD:SDIOInterruptIstThread(): Wait Failed!\r\n")));
return FALSE;
}
if(m_bDriverShutdown)
{
DEBUGMSG(SDCARD_ZONE_WARN, (TEXT("SDHCD:SDIOInterruptIstThread(): Thread Exiting\r\n")));
return FALSE;
}
if(m_bDevicePresent && IsCardPresent())
{
// indicate that the card is interrupting
SDHCDIndicateSlotStateChange(m_pHCContext, 0, DeviceInterrupting);
}
// NOTE: SDHCDIndicateSlotStateChange() is called above to inform the bus driver
// that the SDIO card has generated an interrupt. After this notification, the
// bus driver will eventually call back SDHCDSlotOptionHandler() to enable/disable
// and ACK the SDIO interrupt as necessary. Consequently, we DO NOT acknowledge
// the interrupt here...
}
}
///////////////////////////////////////////////////////////////////////////////
// CSDIOControllerBase::CardDetectThread - thread for card insert/removal detection
// Input:
// Output:
//
// Return: thread exit code
///////////////////////////////////////////////////////////////////////////////
DWORD CSDIOControllerBase::CardDetectThread()
{
BOOL bSlotStateChanged = FALSE;
DWORD dwWaitResult = WAIT_TIMEOUT;
if( m_nCardDetectIstThreadPriority != 0xffffffff && !CeSetThreadPriority( GetCurrentThread(), m_nCardDetectIstThreadPriority ) )
{
DEBUGMSG(SDCARD_ZONE_WARN, (TEXT("SDHCDriver:CardDetectThread(): warning, failed to set CEThreadPriority \r\n")));
}
for(;;)
{
//----- 1. Wait for the next insertion/removal interrupt -----
dwWaitResult = WaitForSingleObject(m_hCardInsertInterruptEvent, INFINITE);
Lock();
//RETAILMSG(1,(TEXT("Card insert/remove detected......................!!!!\r\n")));
if(m_bDriverShutdown)
{
DEBUGMSG(SDCARD_ZONE_WARN, (TEXT("SDHCardDetectIstThread: Thread Exiting\r\n")));
return FALSE;
}
#if 0
// Test if a card is present
if( IsCardPresent() == m_bDevicePresent )
{
bSlotStateChanged = FALSE;
}
else
{
bSlotStateChanged = TRUE;
}
if( bSlotStateChanged || m_bReinsertTheCard )
{
m_bReinsertTheCard = FALSE;
// If a card is inserted, unload the driver...
if(m_bDevicePresent == TRUE)
{
m_fCardInTheSlot = FALSE;
// indicate the slot change
SDHCDIndicateSlotStateChange(m_pHCContext, 0, DeviceEjected);
m_bDevicePresent = FALSE;
Stop_SDI_Clock();
}
if(IsCardPresent())
{
m_fCardInTheSlot = TRUE;
m_bDevicePresent = TRUE;
//----- 5. Reset the clock to the ID rate -----
vm_pSDIReg->SDICON |= LITTLE_ENDIAN_BYTE_ORDER; // Windows CE is always Little Endian.
vm_pSDIReg->SDIFSTA |= FIFO_RESET; // Reset the FIFO
vm_pSDIReg->SDIBSIZE = BYTES_PER_SECTOR;
vm_pSDIReg->SDIDTIMER = MAX_DATABUSY_TIMEOUT; // Data/busy timeout
SetClockRate(SD_DEFAULT_CARD_ID_CLOCK_RATE);
// give the card enough time for initialization
Start_SDI_Clock();
Wait_80_SDI_Clock_Cycles();
//----- 6. Inform the bus handler that this is the first command sent -----
m_bSendInitClocks = TRUE;
//----- 7. Indicate the slot change -----
SDHCDIndicateSlotStateChange(m_pHCContext, 0, DeviceInserted);
}
} // if
#else
if (m_bReinsertTheCard) // when it resumes from suspend.
{
RETAILMSG(1,(TEXT("SDHC wakeuped\r\n")));
if ( m_bDevicePresent ) // if when it gets suspend a t-flash card existed
{
RETAILMSG(1,(TEXT("Unload sdmemory\r\n")));
m_fCardInTheSlot = FALSE;
// indicate the slot change
SDHCDIndicateSlotStateChange(m_pHCContext, 0, DeviceEjected);
m_bDevicePresent = FALSE;
Stop_SDI_Clock();
}
m_bReinsertTheCard = FALSE;
}
//RETAILMSG(1,(TEXT("IsCardPresent = %d, m_bDevicePresent = %d\n"),IsCardPresent(),m_bDevicePresent));
if( IsCardPresent() && !m_bDevicePresent ) // TF-detect INT occured. and a card exists.
{
RETAILMSG(1,(TEXT("Card was detected\r\n")));
m_fCardInTheSlot = TRUE;
m_bDevicePresent = TRUE;
//----- 5. Reset the clock to the ID rate -----
vm_pSDIReg->SDICON |= LITTLE_ENDIAN_BYTE_ORDER; // Windows CE is always Little Endian.
vm_pSDIReg->SDIFSTA |= FIFO_RESET; // Reset the FIFO
vm_pSDIReg->SDIBSIZE = BYTES_PER_SECTOR;
vm_pSDIReg->SDIDTIMER = MAX_DATABUSY_TIMEOUT; // Data/busy timeout
SetClockRate(SD_DEFAULT_CARD_ID_CLOCK_RATE);
// give the card enough time for initialization
Start_SDI_Clock();
Wait_80_SDI_Clock_Cycles();
//----- 6. Inform the bus handler that this is the first command sent -----
m_bSendInitClocks = TRUE;
//----- 7. Indicate the slot change -----
SDHCDIndicateSlotStateChange(m_pHCContext, 0, DeviceInserted);
}
else if ( !IsCardPresent() && m_bDevicePresent ) // TF-detect INT occured. but card doesn't exist.
{
m_fCardInTheSlot = FALSE;
// indicate the slot change
SDHCDIndicateSlotStateChange(m_pHCContext, 0, DeviceEjected);
m_bDevicePresent = FALSE;
RETAILMSG(1,(TEXT("Card was removed\r\n")));
Stop_SDI_Clock();
}
UnLock();
InterruptDone(m_dwSDDetectSysIntr);
#endif
} // for
return TRUE;
}
//-------------------------------------------- Helper Functions ---------------------------------------
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Function: CSDIOControllerBase::SendCommand()
Description: Issues the specified SDI command
Returns: SD_API_STATUS status code.
-------------------------------------------------------------------*/
SD_API_STATUS CSDIOControllerBase::SendCommand(UINT16 Cmd, UINT32 Arg, UINT16 respType, BOOL bDataTransfer)
{
unsigned int uiNewCmdRegVal = 0;
DWORD dwWaitCount = 0;
RETAILMSG (0,(TEXT("SendCommand (0x%08x, 0x%04x, 0x%08x, 0x%04x, 0x%x) starts\r\n"),
this, Cmd, Arg, respType, bDataTransfer));
DEBUGMSG (SDHC_SEND_ZONE,(TEXT("SendCommand (0x%08x, 0x%04x, 0x%08x, 0x%04x, 0x%x) starts\r\n"),
this, Cmd, Arg, respType, bDataTransfer));
//RETAILMSG (1,(TEXT("SendCommand (0x%08x, 0x%04x, 0x%08x, 0x%04x, 0x%x) starts\r\n"),
// this, Cmd, Arg, respType, bDataTransfer));
//----- 1. Reset any pending status flags -----
vm_pSDIReg->SDICSTA = (CRC_CHECK_FAILED | COMMAND_SENT | COMMAND_TIMED_OUT | RESPONSE_RECEIVED);
//----- 2. Specify the command's argument -----
vm_pSDIReg->SDICARG = Arg;
//----- 3. Specify the command's data transfer requirements -----
if(bDataTransfer == TRUE)
{
vm_pSDIReg->SDICCON |= SDIO_COMMAND_WITH_DATA;
}else
{
vm_pSDIReg->SDICCON &= ~SDIO_COMMAND_WITH_DATA;
}
//----- 4. Send the command to the MMC controller -----
switch(respType)
{
case NoResponse: // Response is not required, but make sure the command was sent
DEBUGMSG (SDHC_RESPONSE_ZONE,(TEXT("SendCommand no response required\r\n")));
vm_pSDIReg->SDICCON = START_COMMAND | COMMAND_START_BIT | (Cmd & MAX_CMD_VALUE);
while(!(vm_pSDIReg->SDICSTA & COMMAND_SENT))
{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -