📄 sdbusrequest.cpp
字号:
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
//
// Use of this source code is subject to the terms of the Microsoft end-user
// license agreement (EULA) under which you licensed this SOFTWARE PRODUCT.
// If you did not accept the terms of the EULA, you are not authorized to use
// this source code. For a copy of the EULA, please see the LICENSE.RTF on your
// install media.
//
// Copyright (c) 2002 BSQUARE Corporation. All rights reserved.
// DO NOT REMOVE --- BEGIN EXTERNALLY DEVELOPED SOURCE CODE ID 40973--- DO NOT REMOVE
// Bus request api implementation
#include "SDCardDDK.h"
#include "SDbusdriver.h"
#ifdef DEBUG
// card response text look up
static const WCHAR *SDCardResponseTypeLookUp[8] =
{{TEXT("NoResponse")},
{TEXT("R1")},
{TEXT("R1b")},
{TEXT("R2")},
{TEXT("R3")},
{TEXT("R4")},
{TEXT("R5")},
{TEXT("R6")}
};
// card state string look up
static const WCHAR *SDCardStateStringLookUp[16] =
{{TEXT("IDLE")},
{TEXT("READY")},
{TEXT("IDENT")},
{TEXT("STBY")},
{TEXT("TRAN")},
{TEXT("DATA")},
{TEXT("RCV")},
{TEXT("PRG")},
{TEXT("UNKN")},
{TEXT("UNKN")},
{TEXT("UNKN")},
{TEXT("UNKN")},
{TEXT("UNKN")},
{TEXT("UNKN")},
{TEXT("UNKN")},
{TEXT("UNKN")},
};
#endif
///////////////////////////////////////////////////////////////////////////////
// SDSynchCommandCompleteCallback - synchronous completion callback
// 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 SDSynchCommandCompleteCallback(SD_DEVICE_HANDLE hDevice,
HBUS_REQUEST hRequest,
PVOID pContext,
DWORD BusRequestParam)
{
PSD_SYNCH_REQUEST_INFO pSynchInfo = (PSD_SYNCH_REQUEST_INFO)BusRequestParam;
PSDBUS_BUS_REQUEST pRequest = (PSDBUS_BUS_REQUEST) hRequest;
// save off the status
pSynchInfo->Status = pRequest->Status;
if (NULL != pSynchInfo->pResponse) {
BOOL fNoException;
// we are copying data back from an arbitrary context, set access permissions
SD_SET_PROC_PERMISSIONS_FROM_REQUEST(pRequest) {
// copy the response buffer
fNoException = SDPerformSafeCopy(pSynchInfo->pResponse,
&pRequest->CommandResponse, sizeof(SD_COMMAND_RESPONSE));
} SD_RESTORE_PROC_PERMISSIONS();
if (fNoException == FALSE) {
DEBUGMSG(SDCARD_ZONE_ERROR,
(TEXT("SDBusDriver: Exception writing to response buffer\n")));
pSynchInfo->Status = SD_API_STATUS_ACCESS_VIOLATION;
}
}
// free this request
SDFreeBusRequest__X(hRequest);
// wake up the blocked thread
SetEvent(pSynchInfo->hWaitEvent);
}
///////////////////////////////////////////////////////////////////////////////
// SDSynchronousBusRequest__X - send an SD Bus request synchronously
// Input: hDevice - device handle
// Command - command to send
// Argument - argument for command
// TransferClass - Command only, or associated with read/write data
// ResponseType - expected response
// pResponse - buffer to hold response (OPTIONAL)
// NumBlocks - number of blocks
// BlockSize - block size
// pBuffer - block buffer
// Flags - bus request flags
//
// Output: pResponse - caller allocated storage for the return response
// Return: SD_API_STATUS
// Notes:
// This function provides a synchronous (blocking) call to perform a
// bus request.
///////////////////////////////////////////////////////////////////////////////
SD_API_STATUS SDSynchronousBusRequest__X(SD_DEVICE_HANDLE hDevice,
UCHAR Command,
DWORD Argument,
SD_TRANSFER_CLASS TransferClass,
SD_RESPONSE_TYPE ResponseType,
PSD_COMMAND_RESPONSE pResponse,
ULONG NumBlocks,
ULONG BlockSize,
PUCHAR pBuffer,
DWORD Flags)
{
SD_API_STATUS status; // intermediate status
PSD_SYNCH_REQUEST_INFO pSynchInfo; // synch information
HBUS_REQUEST hRequest; // the new request
DWORD waitResult; // wait result
CSDBusDriver *pBusDriver; // the bus driver
DEBUGMSG(SDCARD_ZONE_FUNC, (TEXT("SDCard: SendSynchCommandRequest+\n")));
PSDCARD_DEVICE_CONTEXT pDevice = (PSDCARD_DEVICE_CONTEXT) hDevice;
if (!ValidateClientHandle(pDevice)) {
return SD_API_STATUS_INVALID_HANDLE;
}
// get the bus driver
pBusDriver = SDDCGetBusDriver(pDevice);
// allocate a synch info structure, we pre-allocate event objects to
// minimize impact of creating and deleting wait objects
pSynchInfo = pBusDriver->AllocateSyncInfo();
if (NULL == pSynchInfo) {
DEBUGMSG(SDCARD_ZONE_ERROR, (TEXT("SDBusRequest: SendSynchCommandRequest- failed to allocate sync info \n")));
return SD_API_STATUS_INSUFFICIENT_RESOURCES;
}
// save the response
pSynchInfo->pResponse = pResponse;
// send the request
status = SDBusRequest__X(hDevice, // device
Command, // command
Argument, // command argument
TransferClass, //
ResponseType, // response
NumBlocks, // no blocks
BlockSize, //
pBuffer, //
SDSynchCommandCompleteCallback, // callback
(DWORD)pSynchInfo, // pass the synch information
&hRequest, // request
Flags); // flags
if (!SD_API_SUCCESS(status)) {
DEBUGMSG(SDCARD_ZONE_FUNC, (TEXT("SDCard: SendSynchCommandRequest-\n")));
pBusDriver->FreeSyncInfo(pSynchInfo);
return status;
}
// wait for the I/O to complete
waitResult = WaitForSingleObject(pSynchInfo->hWaitEvent, INFINITE);
if (WAIT_OBJECT_0 == waitResult) {
// the request finishes asynchronously and the callback updated the status in the synch struct
status = pSynchInfo->Status;
} else {
DEBUGMSG(SDCARD_ZONE_ERROR, (TEXT("SDBusDriver: SendSynchCommandRequest - Wait Failed 0x%08x Error 0x%08x\n"),
waitResult, GetLastError()));
// We can only cancel the bus request if it has not already been
// canceled in SDSynchCommandCompleteCallback.
DWORD dw = 1000;
while (dw--) {
if (pSynchInfo->Status != SD_API_STATUS_PENDING) {
break;
}
Sleep(1);
}
if (pSynchInfo->Status == SD_API_STATUS_PENDING) {
// The callback still has not been called. Cancel the request.
SDCancelBusRequest__X(hRequest);
}
status = SD_API_STATUS_UNSUCCESSFUL;
}
pBusDriver->FreeSyncInfo(pSynchInfo);
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,
DWORD Flags)
{
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) {
// build a CMD12 request
pRequest->CommandCode = SD_CMD_STOP_TRANSMISSION;
pRequest->CommandArgument = 0;
pRequest->CommandResponse.ResponseType = ResponseR1b;
} 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,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -