📄 sdcardio.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
// SD Bus driver Card I/O request implementation
#include "SDCardDDK.h"
#include "SDbusdriver.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);
///////////////////////////////////////////////////////////////////////////////
// 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
PSD_SYNCH_REQUEST_INFO pSynchInfo; // synch information
CSDBusDriver *pBusDriver; // the bus driver
UCHAR responseStatus; // IO response status
ULONG ii; // loop count
DEBUGMSG(SDCARD_ZONE_FUNC, (TEXT("SDCard: SDReadWriteRegistersDirect+\n")));
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);
// allocate a synch info structure to use for the response buffer
// we do not use the event
pSynchInfo = pBusDriver->AllocateSyncInfo();
if (NULL == pSynchInfo) {
DEBUGMSG(SDCARD_ZONE_ERROR, (TEXT("SDCard: SDReadWriteRegistersDirect- failed to allocate sync info \n")));
return SD_API_STATUS_INSUFFICIENT_RESOURCES;
}
// transfer the buffer
for (ii = 0; ii < BufferLength; ii++) {
// send the request
status = SDSynchronousBusRequest__X(hDevice,
SD_IO_RW_DIRECT,
BUILD_IO_RW_DIRECT_ARG((UCHAR)ReadWrite,
ReadAfterWrite,
Function,
(Address + ii),
pBuffer[ii]),
SD_COMMAND,
ResponseR5,
&pSynchInfo->TempResponse, // use the synch info for the response buffer
0,
0,
NULL,
0);
if (!SD_API_SUCCESS(status)) {
break;
}
responseStatus = SD_GET_IO_RW_DIRECT_RESPONSE_FLAGS(&pSynchInfo->TempResponse);
// 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(&pSynchInfo->TempResponse);
}
} 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;
}
}
pBusDriver->FreeSyncInfo(pSynchInfo);
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));
}
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);
}
// get a copy
regValue = pParentDevice->SDCardInfo.SDIOInformation.pCommonInformation->CCCRShadowIntEnable;
// check to see if there are interrupts to keep enabled
if (!(regValue & SD_IO_INT_ENABLE_ALL_FUNCTIONS)) {
// if none, then clear out master enable
regValue &= ~SD_IO_INT_ENABLE_MASTER_ENABLE;
pParentDevice->SDCardInfo.SDIOInformation.pCommonInformation->CCCRShadowIntEnable = regValue;
}
// set status
status = SD_API_STATUS_SUCCESS;
// now check and see if we need to enable/disable interrupts in the host controller
if (Connect) {
// check to see if the interrupt logic is already on
if (!IS_SLOT_SDIO_INTERRUPT_ON(pDevice->pSlot)) {
// enable it in the host controller
status = SDEnableSDIOInterrupts(pDevice->pSlot);
if (SD_API_SUCCESS(status)) {
// flag it as on
FLAG_SD_SLOT_INTERRUPTS_ON(pDevice->pSlot);
}
}
} else {
// check to see if all the interrupts have been turned off
if (0 == regValue) {
// disable interrupts, we don't really care about the result
SDDisableSDIOInterrupts(pDevice->pSlot);
// flag it off
FLAG_SD_SLOT_INTERRUPTS_OFF(pDevice->pSlot);
}
}
if (!SD_API_SUCCESS(status)) {
SDDCReleaseDeviceLock(pParentDevice);
return status;
}
// update the INT Enable register
status = SDReadWriteRegistersDirect__X((SD_DEVICE_HANDLE)pDevice,
SD_IO_WRITE,
0, // all from function 0
SD_IO_REG_INT_ENABLE,
FALSE,
®Value, // reg
1);
if (!SD_API_SUCCESS(status)) {
DEBUGMSG(SDCARD_ZONE_ERROR, (TEXT("SDIOConnectDisconnectInterrupt: failed to write INT_ENABLE register for function %d \n"),
pDevice->SDCardInfo.SDIOInformation.Function));
pDevice->SDCardInfo.SDIOInformation.pInterruptCallBack = NULL;
} else {
if (Connect) {
DEBUGMSG(SDBUS_ZONE_DEVICE, (TEXT("SDIOConnectDisconnectInterrupt: Interrupt enabled for function %d \n"),
pDevice->SDCardInfo.SDIOInformation.Function));
} else {
DEBUGMSG(SDBUS_ZONE_DEVICE, (TEXT("SDIOConnectDisconnectInterrupt: Interrupt disabled for function %d \n"),
pDevice->SDCardInfo.SDIOInformation.Function));
}
}
SDDCReleaseDeviceLock(pParentDevice);
return status;
}
///////////////////////////////////////////////////////////////////////////////
// SDIOConnectInterrupt - Associate an interrupt service routine for an SDIO
// peripheral interrupt
// Input: hDevice - SD device handle
// pIsrFunction - the interrupt service routine
// Output:
// Return: SD_API_STATUS code
//
// Notes: This function is provided for an SDIO peripheral driver to
// register an interrupt routine for the device.
// The interrupt function has the form of PSD_INTERRUPT_CALLBACK.
// The caller should call SDIODisconnectInterrupt when cleaning up
// the device. The bus driver will enable the interrupt for the function in the
// card's CCCR area prior to returning from this function.
// The interrupt callback is called whenever the device function is
// interrupting. The bus driver will determine the interrupting function,
// disable the interrupt on the card and call the callback. Upon return
// from the callback the bus driver will reenable the interrupt in the
// card's CCR.
///////////////////////////////////////////////////////////////////////////////
SD_API_STATUS SDIOConnectInterrupt__X(SD_DEVICE_HANDLE hDevice,
PSD_INTERRUPT_CALLBACK pIsrFunction)
{
// All error checking is done in SDIOConnectDisconnectInterrupt.
return SDIOConnectDisconnectInterrupt(hDevice,
pIsrFunction,
TRUE);
}
///////////////////////////////////////////////////////////////////////////////
// SDIODisconnectInterrupt - disconnect the interrupt
// Input: hDevice - SD device handle
// Output:
// Return:
//
// Notes: This function should be called to disconnect the interrupt
// from the device. The bus driver will disable the interrupt in the
// card's CCCR area
///////////////////////////////////////////////////////////////////////////////
VOID SDIODisconnectInterrupt__X(SD_DEVICE_HANDLE hDevice)
{
// All error checking is done in SDIOConnectDisconnectInterrupt.
SDIOConnectDisconnectInterrupt(hDevice,
NULL,
FALSE);
}
///////////////////////////////////////////////////////////////////////////////
// SDSetFunctionBlockSize - set the block size of the function
// Input: pDevice - the device
// BlockSize - block size to set
// Output:
// Return: SD_API_STATUS code
//
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -