📄 sdcardio.cpp
字号:
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
//
// Use of this sample source code is subject to the terms of the Microsoft
// license agreement under which you licensed this sample source code. If
// you did not accept the terms of the license agreement, you are not
// authorized to use this sample source code. For the terms of the license,
// please see the license agreement between you and Microsoft or, if applicable,
// see the LICENSE.RTF on your install media or the root of your tools installation.
// THE SAMPLE SOURCE CODE IS PROVIDED "AS IS", WITH NO WARRANTIES OR INDEMNITIES.
//
// Copyright (c) 2002-2004 BSQUARE Corporation. All rights reserved.
// DO NOT REMOVE --- BEGIN EXTERNALLY DEVELOPED SOURCE CODE ID 40973--- DO NOT REMOVE
// SD Bus driver Card I/O request implementation
#include <SDCardDDK.h>
#include "SDbusdriver.h"
#include <celog.h>
#define SD_GET_IO_RW_DIRECT_RESPONSE_FLAGS(pResponse) (pResponse)->ResponseBuffer[SD_IO_R5_RESPONSE_FLAGS_BYTE_OFFSET]
#define SD_GET_IO_RW_DIRECT_DATA(pResponse) (pResponse)->ResponseBuffer[SD_IO_R5_RESPONSE_DATA_BYTE_OFFSET]
SD_API_STATUS SetCardInterface(PSDCARD_DEVICE_CONTEXT pDevice, PSD_CARD_INTERFACE pInterface);
///////////////////////////////////////////////////////////////////////////////
// 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 SDReadWriteRegistersCompleteCallback(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;
// wake up the blocked thread
SetEvent(pSynchInfo->hWaitEvent);
}
///////////////////////////////////////////////////////////////////////////////
// SDReadWriteRegistersDirect - Read/Write I/O register(s) direct
// Input: hDevice - the device
// ReadWrite - read write flag
// Function - Function number
// Address - starting address
// ReadAfterWrite - flag to instruct card to read after write
// pBuffer - buffer to hold value of registers
// BufferLength - number of bytes to read/write
//
// Output:
// Return: SD_API_STATUS code
// Notes:
// This function can be called to read or write multiple contigous registers synchronously
// using the SDIO RW_DIRECT command. This function issues multiple commands to transfer
// to or from the user's buffer
// If ReadAfterWrite is set to 1, the operation will instruct the card
// to return the new value of the register in the response.
///////////////////////////////////////////////////////////////////////////////
SD_API_STATUS SDReadWriteRegistersDirect__X(SD_DEVICE_HANDLE hDevice,
SD_IO_TRANSFER_TYPE ReadWrite,
UCHAR Function,
DWORD Address,
BOOLEAN ReadAfterWrite,
PUCHAR pBuffer,
ULONG BufferLength)
{
SD_API_STATUS status = SD_API_STATUS_SUCCESS; // intermediate status
CSDBusDriver *pBusDriver; // the bus driver
UCHAR responseStatus; // IO response status
ULONG ii; // loop count
DEBUGMSG(SDCARD_ZONE_FUNC, (TEXT("SDCard: SDReadWriteRegistersDirect+\n")));
DEBUGCELOGMSG(SDCARD_ZONESLOT_CELOG,(TEXT("+SDReadWriteRegistersDirect__X(ReadWrite=%x,Function=%x,Address=%x,BufferLength=%x\r\n"),
(DWORD)ReadWrite,Function,Address,BufferLength));
PSDCARD_DEVICE_CONTEXT pDevice = (PSDCARD_DEVICE_CONTEXT) hDevice;
if (!ValidateClientHandle(pDevice)) {
return SD_API_STATUS_INVALID_HANDLE;
}
if (NULL == pBuffer) {
DEBUGMSG(SDCARD_ZONE_ERROR, (TEXT("SDCard: SDReadWriteRegistersDirect- NULL buffer passed \n")));
return SD_API_STATUS_INVALID_PARAMETER;
}
// get the bus driver
pBusDriver = SDDCGetBusDriver(pDevice);
PREFAST_DEBUGCHK(pBusDriver);
PSDBUS_BUS_REQUEST pNewRequest = pBusDriver->AllocateBusRequest();
if (pNewRequest == NULL) {
DEBUGMSG(SDCARD_ZONE_ERROR, (TEXT("SDBusRequest: SDBusRequest- failed to allocate bus request \n")));
status = SD_API_STATUS_UNSUCCESSFUL;
}
else {
EnterCriticalSection(&pDevice->syncCritSection);
ASSERT(pDevice->syncCount==0);
pDevice->syncCount++;
for (ii = 0; ii < BufferLength; ii++) {
ResetEvent(pDevice->synchInfo.hWaitEvent);
pDevice->synchInfo.pResponse = NULL; // Don't need copy response.
pNewRequest->ListEntry.Flink = pNewRequest->ListEntry.Blink = NULL;
pNewRequest->hDevice = hDevice;
pNewRequest->SystemFlags = pNewRequest->Flags = 0;
pNewRequest->TransferClass = SD_COMMAND;
pNewRequest->CommandCode = SD_IO_RW_DIRECT;
pNewRequest->CommandArgument = BUILD_IO_RW_DIRECT_ARG((UCHAR)ReadWrite,ReadAfterWrite,Function,(Address + ii),
(ReadWrite==SD_IO_READ)? 0: pBuffer[ii]);
pNewRequest->CommandResponse.ResponseType = ResponseR5;
pNewRequest->RequestParam = (DWORD)&pDevice->synchInfo;
pNewRequest->NumBlocks = pNewRequest->BlockSize = pNewRequest->HCParam = 0;
pNewRequest->pCallback = SDReadWriteRegistersCompleteCallback, // callback
pNewRequest->DataAccessClocks = 0; // reset data access clocks
if (( pDevice->SDCardInfo.SDIOInformation.Flags & FSTPTH_DISABLE ) == 0 ) {
pNewRequest->Flags = SD_SYNCHRONOUS_REQUEST ;
pNewRequest->SystemFlags = SD_FAST_PATH_AVAILABLE;
}
pNewRequest->pBlockBuffer = 0;
SDDCIncrementRefCount(pDevice);
status = pBusDriver->SubmitBusRequest(pNewRequest);
if (!SD_API_SUCCESS(status)){
ASSERT(FALSE);
break;
}
else if (status == SD_API_STATUS_FAST_PATH_SUCCESS) {
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 )) != pNewRequest )
{
// 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")));
}
// decrement the ref count
SDDCDecrementRefCount(pDevice);
SDHCDStartNextRequest ( pSlot->pHostController, pBusDriver, pSlot );
}
else {
// wait for the I/O to complete
DWORD waitResult = WaitForSingleObject(pDevice->synchInfo.hWaitEvent, INFINITE);
if (WAIT_OBJECT_0 == waitResult) {
// the request finishes asynchronously and the callback updated the status in the synch struct
status = pDevice->synchInfo.Status;
}
else {
ASSERT(FALSE);
DbgPrintZo(SDCARD_ZONE_ERROR, (TEXT("SDBusDriver: SDReadWriteRegistersDirect__X - Wait Failed 0x%08X \n"),waitResult));
// cancel the bus request
SDCancelBusRequest__X(pNewRequest);
status = SD_API_STATUS_UNSUCCESSFUL;
break;
}
}
responseStatus = SD_GET_IO_RW_DIRECT_RESPONSE_FLAGS(&pNewRequest->CommandResponse);
// mask out the previous CRC error, the command is retried on CRC errors
// so this bit will reflect the previous command instead
responseStatus &= ~SD_IO_COM_CRC_ERROR;
if (!SD_IO_R5_RESPONSE_ERROR(responseStatus)) {
status = SD_API_STATUS_SUCCESS;
// check to see if read after write or just a read
if (ReadAfterWrite || (SD_IO_READ == ReadWrite)) {
pBuffer[ii] = SD_GET_IO_RW_DIRECT_DATA(&pNewRequest->CommandResponse);
}
} else {
DEBUGMSG(SDCARD_ZONE_ERROR, (TEXT("SDCard: SDReadWriteRegistersDirect- R5 response returned error code : 0x%02X \n"),responseStatus));
status = SD_API_STATUS_DEVICE_RESPONSE_ERROR;
break;
}
}
// free the request
pBusDriver->FreeBusRequest(pNewRequest);
pDevice->syncCount--;
LeaveCriticalSection(&pDevice->syncCritSection);
}
DEBUGMSG(SDCARD_ZONE_FUNC, (TEXT("SDCard: SDReadWriteRegistersDirect-\n")));
if (!SD_API_SUCCESS(status)) {
DEBUGMSG(SDCARD_ZONE_ERROR, (TEXT("SDCard: SDReadWriteRegistersDirect: Request Failed at address : 0x%08X status:0x%08X \n"),(Address + ii), status));
}
DEBUGCELOGMSG(SDCARD_ZONESLOT_CELOG,(TEXT("-SDReadWriteRegistersDirect__X: status=%x\r\n"),status));
return status;
}
///////////////////////////////////////////////////////////////////////////////
// SDIOConnectDisconnectInterrupt - connect/disconnect an interrupt service routine
// for an SDIO peripheral interrupt
//
// Input: hDevice - SD device handle
// pIsrFunction - the interrupt service routine
// Connect - connect , if TRUE, pIsrFunction must not be NULL
// Output:
// Return: SD_API_STATUS code
//
// Notes:
///////////////////////////////////////////////////////////////////////////////
static
SD_API_STATUS SDIOConnectDisconnectInterrupt(SD_DEVICE_HANDLE hDevice,
PSD_INTERRUPT_CALLBACK pIsrFunction,
BOOL Connect)
{
PSDCARD_DEVICE_CONTEXT pParentDevice; // parent device
UCHAR regValue; // intermediate register value
SD_API_STATUS status; // intermediate status
PSDCARD_DEVICE_CONTEXT pDevice = (PSDCARD_DEVICE_CONTEXT) hDevice;
if (!ValidateClientHandle(pDevice)) {
return SD_API_STATUS_INVALID_HANDLE;
}
if (Device_SD_IO != pDevice->DeviceType) {
DEBUGMSG(SDCARD_ZONE_ERROR, (TEXT("SDIOConnectDisconnectInterrupt: device is not SDIO ! \n")));
return SD_API_STATUS_INVALID_PARAMETER;
}
if ( Connect && (NULL == pIsrFunction) ) {
DEBUGMSG(SDCARD_ZONE_ERROR, (TEXT("SDCard: SDIOConnectInterrupt: callback function is NULL \n")));
return SD_API_STATUS_INVALID_PARAMETER;
}
// get the parent device
pParentDevice = pDevice->pParentDevice;
if (NULL == pParentDevice) {
DEBUGCHK(FALSE);
return SD_API_STATUS_INVALID_PARAMETER;
}
DEBUGCHK(0 != pDevice->SDCardInfo.SDIOInformation.Function);
// must interlock this request with the parent device to update the shadow register
SDDCAcquireDeviceLock(pParentDevice);
if (Connect) {
// set the interrupt function
pDevice->SDCardInfo.SDIOInformation.pInterruptCallBack = pIsrFunction;
// update shadow register , we automatically enable the master interrupt enable bit
pParentDevice->SDCardInfo.SDIOInformation.pCommonInformation->CCCRShadowIntEnable |=
((1 << pDevice->SDCardInfo.SDIOInformation.Function) | SD_IO_INT_ENABLE_MASTER_ENABLE);
} else {
DEBUGCHK(pIsrFunction == NULL);
pDevice->SDCardInfo.SDIOInformation.pInterruptCallBack = NULL;
// mask out this function
pParentDevice->SDCardInfo.SDIOInformation.pCommonInformation->CCCRShadowIntEnable &=
~(1 << pDevice->SDCardInfo.SDIOInformation.Function);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -