📄 sdiocontrollerbase.cpp
字号:
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, m_dwPollingTimeout);
if(m_bDriverShutdown)
{
DEBUGMSG(SDCARD_ZONE_WARN, (TEXT("SDHCardDetectIstThread: Thread Exiting\r\n")));
return FALSE;
}
// 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
} // 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;
DEBUGMSG (SDHC_SEND_ZONE,(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))
{
dwWaitCount++;
if( dwWaitCount > WAIT_TIME )
{
DEBUGMSG(SDCARD_ZONE_ERROR, (TEXT("SDHCD:SendCommand() - timeout waiting for command completion!\r\n")));
return SD_API_STATUS_RESPONSE_TIMEOUT;
}
if( !IsCardPresent() )
{
DEBUGMSG(SDCARD_ZONE_ERROR, (TEXT("SDHCD:SendCommand() - Card ejected!\r\n")));
return SD_API_STATUS_DEVICE_REMOVED;
}
if(vm_pSDIReg->SDICSTA & COMMAND_TIMED_OUT)
{
DEBUGMSG(SDCARD_ZONE_ERROR, (TEXT("SDHCD:SendCommand() - Command 0x%04x timed out!\r\n"), Cmd));
vm_pSDIReg->SDICSTA = COMMAND_TIMED_OUT; // Clear the error
return SD_API_STATUS_RESPONSE_TIMEOUT;
}
}
vm_pSDIReg->SDICSTA = COMMAND_SENT; // Clear the status
break;
case ResponseR1: // Short response required
case ResponseR1b:
case ResponseR3:
case ResponseR4:
case ResponseR5:
case ResponseR6:
DEBUGMSG (SDHC_RESPONSE_ZONE,(TEXT("sendSDICommand short response required\r\n")));
// vm_pSDIReg->SDICCON = uiNewCmdRegVal | WAIT_FOR_RESPONSE | START_COMMAND | COMMAND_START_BIT | (Cmd & MAX_CMD_VALUE);
vm_pSDIReg->SDICCON = WAIT_FOR_RESPONSE | START_COMMAND | COMMAND_START_BIT | (Cmd & MAX_CMD_VALUE);
break;
case ResponseR2: // Long response required
DEBUGMSG (SDHC_RESPONSE_ZONE,(TEXT("sendSDICommand long response required\r\n")));
// vm_pSDIReg->SDICCON = uiNewCmdRegVal | LONG_RESPONSE | WAIT_FOR_RESPONSE | START_COMMAND | COMMAND_START_BIT | (Cmd & MAX_CMD_VALUE);
vm_pSDIReg->SDICCON = LONG_RESPONSE | WAIT_FOR_RESPONSE | START_COMMAND | COMMAND_START_BIT | (Cmd & MAX_CMD_VALUE);
break;
default:
DEBUGMSG(SDCARD_ZONE_ERROR, (TEXT("SDHCD:sendSDICommand() - Invalid response type. Command not sent!\r\n")));
return SD_API_STATUS_NOT_IMPLEMENTED;
break;
}
return SD_API_STATUS_SUCCESS;
}
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Function: CSDIOControllerBase::GetCommandResponse()
Description: Retrieves the response info for the last SDI command
issues.
Notes: This routine assumes that the caller has already locked
the current request and checked for errors.
Returns: SD_API_STATUS status code.
-------------------------------------------------------------------*/
SD_API_STATUS CSDIOControllerBase::GetCommandResponse(PSD_BUS_REQUEST pRequest)
{
DEBUGMSG (SDHC_RESPONSE_ZONE,(TEXT("GetCommandResponse started\r\n")));
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -