📄 sdbusrequest.cpp
字号:
/*====================================================================================================
Fast-Path goal is to replace the overhead of interrupts, thread
switching and thread synchronization with polling by the application
thread. This works well at high card clock rates when the card can
respond faster then the interrupt overhead allows. For this case
only, switching from interrupt driven to polling actually reduces
the amount of work done by the CPU to service this device. Eliminated
are:
* the thread switches required to handle the actual interrupt and
hand it off to the interrupt thread,
* the setting, clearing, and waiting for the interrupt event,
* the setting, clearing, and waiting for the dispatcher event,
* the thread switch to the dispatcher, and
* the setting, clearing, and waiting for the I/O completion event.
For Fast-Path, the client driver thread does all of the work to
perform the I/O operation.
-----------------------------------------------------------------------------------------
Fast-Path
-----------------------------------------------------------------------------------------
Client Driver Thread
|
v
calls SDSynchronousBusRequest
+-- |
| v
| D Build Bus Request
| r |
|B i v
|u v Place in Bus Request Queue
|s e |
| r v
| Start first bus request
+-- |
|H v
|o Start I/O on controller
|s |
|t v
| Poll for I/O Completion
|C |
|o D v
|n r return the I/O status
|t i |
|r v |
|o e |
|l r |
|l |
|e |
|r |
+ v
| D Free current request
| r |
|B i v
|u v Start next request
|s e |
| r v
| Return final status
+--
The main difference above is that the starting of the next request
is delayed until the stack is unwound. This prevents stack overflows!
====================================================================================================*/
// Complete the Fast-Path processing if necessary.
if ( SD_API_STATUS_FAST_PATH_SUCCESS == status )
{
PSDBUS_HC_SLOT_CONTEXT pSlot;
// The bus request queue is synchronized using the HCLock. The first
// entry on the queue is always active on the Host Controller. Proper
// queue maintenance requires holding the HCLock while removing the
// completed entry from the queue and starting the next entry on the
// queue. Releasing the lock between these two operations enables
// situations where the request at the head of the queue is started
// (passed to the host controller's bus request handler) twice, breaking
// the design critiera for the host controller driver.
// Synchronize with the request handling.
pSlot = (SDDCGetClientDeviceFromHandle(hDevice))->pSlot;
SDHCDAcquireHCLock(pSlot->pHostController); // SDHCDStartNextRequest releases the lock!!!
// dequeue the current request
if (( SDDequeueBusRequest ( & pSlot->RequestQueue )) != hRequest )
{
// the request we are completing should be the first request in the queue
DEBUG_CHECK(FALSE,(TEXT("SDSynchronousBusRequest__X - the HC is completing a request that is not the current request! \n")));
}
BOOL fResponseCopiedCorrectly = TRUE;
// Return the response data to the client driver if requested.
if (NULL != pResponse)
{
// copy the response buffer
fResponseCopiedCorrectly =
CeSafeCopyMemory(pResponse, &hRequest->CommandResponse, sizeof(SD_COMMAND_RESPONSE));
}
// free the request
SDFreeBusRequest__X(hRequest);
// decrement the ref count
SDDCDecrementRefCount(SDDCGetClientDeviceFromHandle(hDevice));
// Start the next SDIO request and release the HCLock.
SDHCDStartNextRequest ( pSlot->pHostController, pBusDriver, pSlot );
// Return a status value that existing client drivers understand.
if (fResponseCopiedCorrectly) {
status = SD_API_STATUS_SUCCESS;
}
else {
DEBUGMSG(SDCARD_ZONE_ERROR, (_T("SDCard: Access violation while copying command response to user buffer\r\n")));
status = SD_API_STATUS_ACCESS_VIOLATION;
}
}
//pBusDriver->FreeSyncInfo(pSynchInfo);
pDevice->syncCount--;
LeaveCriticalSection(&pDevice->syncCritSection);
DEBUGCELOGMSG(SDCARD_ZONESLOT_CELOG,(TEXT("-SDSynchronousBusRequest__X: status=%x\r\n"),status));
DEBUGMSG(SDCARD_ZONE_FUNC, (TEXT("SDCard: SendSynchCommandRequest-\n")));
return status;
}
///////////////////////////////////////////////////////////////////////////////
// OptionalRequestCallBack - completion callback for optional request
// Input: hDevice - the device handle
// pRequest - the request that just completed
// pContext - the context passed in register device
// BusRequestParam - the optional argument
// Output:
// Notes:
///////////////////////////////////////////////////////////////////////////////
VOID OptionalRequestCallBack(SD_DEVICE_HANDLE hDevice,
HBUS_REQUEST hRequest,
PVOID pContext,
DWORD BusRequestParam)
{
// just free this request
SDFreeBusRequest__X(hRequest);
}
///////////////////////////////////////////////////////////////////////////////
// BuildOptionalRequest - build the optional request based on the request flags
// Input: pDevice - the device
// pBusDriver - the bus driver object
// Flags - the flags passed in from the bus request API
// Output:
// Return: optional bus request
// Notes:
// returns the optional request that should be inserted behind the current request
///////////////////////////////////////////////////////////////////////////////
PSDBUS_BUS_REQUEST BuildOptionalRequest(PSDCARD_DEVICE_CONTEXT pDevice,
CSDBusDriver *pBusDriver,
#ifdef __MOVINAND_SUPPORT__
// added numBlock parameter to support multi block read/write
DWORD Flags,
DWORD numBlock)
#else
DWORD Flags)
#endif
{
PSDBUS_BUS_REQUEST pRequest = NULL; // optional request to return
if (Flags & (SD_AUTO_ISSUE_CMD12 | SD_SDIO_AUTO_IO_ABORT)) {
pRequest = pBusDriver->AllocateBusRequest();
if (NULL != pRequest) {
pRequest->hDevice = (SD_DEVICE_HANDLE)pDevice;
pRequest->SystemFlags = 0;
pRequest->HCParam = 0;
pRequest->NumBlocks = 0;
pRequest->BlockSize = 0;
pRequest->pBlockBuffer = NULL;
pRequest->pCallback = OptionalRequestCallBack;
pRequest->RequestParam = 0;
pRequest->ListEntry.Flink = NULL;
pRequest->ListEntry.Blink = NULL;
pRequest->TransferClass = SD_COMMAND;
if (Flags & SD_AUTO_ISSUE_CMD12) {
#ifdef __MOVINAND_SUPPORT__ // convert open-ended mode to pre-defined mode
if( (pDevice->DeviceType == Device_MMC) && pDevice->dwWhatIsCardType == 0)
{
// build a CMD23 request
RETAILMSG(0,(TEXT("PREDEFIEND!!\n")));
pRequest->CommandCode = SD_CMD_SET_BLOCK_COUNT;
pRequest->CommandArgument = numBlock;
pRequest->CommandResponse.ResponseType = ResponseR1;
}
else
{
#endif
// build a CMD12 request
pRequest->CommandCode = SD_CMD_STOP_TRANSMISSION;
pRequest->CommandArgument = 0;
pRequest->CommandResponse.ResponseType = ResponseR1b;
#ifdef __MOVINAND_SUPPORT__
}
#endif
} else if (Flags & SD_SDIO_AUTO_IO_ABORT) {
DEBUGCHK(pDevice->SDCardInfo.SDIOInformation.Function != 0);
// CMD52
pRequest->CommandCode = SD_IO_RW_DIRECT;
// set up argument to write the function number to the I/O abort register
pRequest->CommandArgument = BUILD_IO_RW_DIRECT_ARG(SD_IO_OP_WRITE,
SD_IO_RW_NORMAL,
0, // must be function 0 for access to common regs
SD_IO_REG_IO_ABORT,
pDevice->SDCardInfo.SDIOInformation.Function);
pRequest->CommandResponse.ResponseType = ResponseR5;
}
// set the retry count
SDRequestSetRetryCount(pRequest, pBusDriver->GetRetryCount());
}
}
return pRequest;
}
///////////////////////////////////////////////////////////////////////////////
// SDBusRequest__X - send command over SD bus
// Input: pHandle - SD bus device structure
// Command - SD command to send over bus
// Argument - 32 bit argument specific to the command
// TransferClass - Command only, or associated with read/write data
// ResponseType - Response Type for the command
// NumBlocks - Number of data blocks in pBlockArray, can be zero
// if transfer class is not read or write
// BlockSize - Size of data blocks in pBlockArray. All blocks
// must be same size.
// pBuffer - Pointer to buffer containing BlockSize*NumBlocks bytes
// pCallback - completion callback
// RequestParam - optional driver specific parameter for this request
// Flags - bus request flags
// Output: ppRequest - newly allocated request
// Return: SD_API_STATUS
// Notes:
///////////////////////////////////////////////////////////////////////////////
SD_API_STATUS SDBusRequest__X(SD_DEVICE_HANDLE hDevice,
UCHAR Command,
DWORD Argument,
SD_TRANSFER_CLASS TransferClass,
SD_RESPONSE_TYPE ResponseType,
ULONG NumBlocks,
ULONG BlockSize,
PUCHAR pBuffer,
PSD_BUS_REQUEST_CALLBACK pCallback,
DWORD RequestParam,
HBUS_REQUEST *phRequest,
DWORD Flags)
{
CSDBusDriver *pBusDriver; // the bus driver
PSDBUS_BUS_REQUEST pNewRequest; // the new request
SD_API_STATUS status = SD_API_STATUS_SUCCESS; // intermediate status
PSDBUS_BUS_REQUEST pOptionalRequest = NULL; // optional request to send down
DEBUGMSG(SDCARD_ZONE_FUNC, (TEXT("SDCard: SDBusRequest+ \n")));
PSDCARD_DEVICE_CONTEXT pDevice = (PSDCARD_DEVICE_CONTEXT) hDevice;
if (!ValidateClientHandle(pDevice)) {
return SD_API_STATUS_INVALID_HANDLE;
}
if( pCallback == NULL ) {
DEBUGMSG(SDCARD_ZONE_ERROR, (TEXT("SDBusRequest: SDBusRequest- Callback missing \n")));
return SD_API_STATUS_INVALID_PARAMETER;;
}
if( phRequest == NULL ) {
DEBUGMSG(SDCARD_ZONE_ERROR, (TEXT("SDBusRequest: SDBusRequest- caller supplied storage is NULL \n")));
return SD_API_STATUS_INVALID_PARAMETER;;
}
if( TransferClass == SD_READ || TransferClass == SD_WRITE ) {
if( NumBlocks == 0 ) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -