📄 sdcardio.cpp
字号:
// Notes:
///////////////////////////////////////////////////////////////////////////////
SD_API_STATUS SDSetFunctionBlockSize(PSDCARD_DEVICE_CONTEXT pDevice,
DWORD BlockSize)
{
USHORT bytesPerBlock = (USHORT)BlockSize; // desired block size
DWORD FBROffset; // FBR offset
SD_API_STATUS status;
DEBUGCHK(0 != pDevice->SDCardInfo.SDIOInformation.Function);
// calculate the FBR offset based on the function number
FBROffset = SD_IO_FBR_1_OFFSET + (pDevice->SDCardInfo.SDIOInformation.Function - 1) *
SD_IO_FBR_LENGTH;
// update the register
status = SDReadWriteRegistersDirect__X((SD_DEVICE_HANDLE)pDevice,
SD_IO_WRITE,
0, // all from function 0
FBROffset + SD_IO_FBR_IO_BLOCK_SIZE,
FALSE,
(PUCHAR)&bytesPerBlock, // reg
sizeof(USHORT)); // two bytes
return status;
}
///////////////////////////////////////////////////////////////////////////////
// SDEnableFunction - enable/disable the device function
// Input: pDevice - the device
// pInfo - enable info (required if Enable is TRUE)
// Enable - enable
// Output:
// Return: SD_API_STATUS code
//
// Notes:
///////////////////////////////////////////////////////////////////////////////
static
SD_API_STATUS SDEnableDisableFunction(PSDCARD_DEVICE_CONTEXT pDevice,
PSD_IO_FUNCTION_ENABLE_INFO pInfo,
BOOL Enable)
{
PREFAST_DEBUGCHK(pDevice);
PSDCARD_DEVICE_CONTEXT pParentDevice; // parent device
UCHAR regValue; // temp register value
ULONG retryCount; // ready retry count
SD_API_STATUS status; // intermediate status
// get the parent device
pParentDevice = pDevice->pParentDevice;
if (NULL == pParentDevice) {
DEBUGCHK(FALSE);
return SD_API_STATUS_INVALID_PARAMETER;
}
DEBUGMSG(SDBUS_ZONE_DEVICE, (TEXT("SDEnableDisableFunction: Enabling/Disabling SDIO Device Function %d \n"),
pDevice->SDCardInfo.SDIOInformation.Function));
// must interlock this request with the parent device to update the shadow register
SDDCAcquireDeviceLock(pParentDevice);
// update the parent device shadow register
if (Enable) {
DEBUGCHK(pInfo);
pParentDevice->SDCardInfo.SDIOInformation.pCommonInformation->CCCRShadowIOEnable
|= (1 << pDevice->SDCardInfo.SDIOInformation.Function);
} else {
DEBUGCHK(pInfo == NULL);
pParentDevice->SDCardInfo.SDIOInformation.pCommonInformation->CCCRShadowIOEnable &=
~(1 << pDevice->SDCardInfo.SDIOInformation.Function);
}
// get a copy
regValue = pParentDevice->SDCardInfo.SDIOInformation.pCommonInformation->CCCRShadowIOEnable;
// release the parent lock
SDDCReleaseDeviceLock(pParentDevice);
// update the register
status = SDReadWriteRegistersDirect__X((SD_DEVICE_HANDLE)pDevice,
SD_IO_WRITE,
0, // all from function 0
SD_IO_REG_ENABLE,
FALSE,
®Value, // reg
1); // one byte
if (!SD_API_SUCCESS(status)) {
return status;
}
// if enabling we check for I/O ready
if (Enable) {
retryCount = pInfo->ReadyRetryCount;
while (retryCount) {
// delay the interval time
Sleep(pInfo->Interval);
// read the I/O ready register
status = SDReadWriteRegistersDirect__X((SD_DEVICE_HANDLE)pDevice,
SD_IO_READ,
0, // all from function 0
SD_IO_REG_IO_READY,
FALSE,
®Value, // reg
1); // one byte
if (!SD_API_SUCCESS(status)) {
break;
}
// see if it is ready
if (regValue & (1 << pDevice->SDCardInfo.SDIOInformation.Function)) {
DEBUGMSG(SDBUS_ZONE_DEVICE, (TEXT("SDEnableDisableFunction: Card Function %d is now ready \n"),
pDevice->SDCardInfo.SDIOInformation.Function));
break;
}
// decrement the count
retryCount--;
DEBUGMSG(SDBUS_ZONE_DEVICE, (TEXT("SDEnableDisableFunction: Card Function %d, Not Ready, re-checking (%d) \n"),
pDevice->SDCardInfo.SDIOInformation.Function, retryCount));
}
if (0 == retryCount) {
DEBUGMSG(SDBUS_ZONE_DEVICE, (TEXT("SDEnableDisableFunction: Card Function %d, Not ready , exceeded retry count\n"),
pDevice->SDCardInfo.SDIOInformation.Function));
status = SD_API_STATUS_DEVICE_NOT_RESPONDING;
}
}
return status;
}
///////////////////////////////////////////////////////////////////////////////
// SDSetCardFeature - Set card feature
// Input: hDevice - SD Device Handle
// CardFeature - Card Feature to set
// StructureSize - size of card feature structure
// Output: pCardInfo - Information for the feature
// Return: SD_API_STATUS code
// Notes: This function is provided to set various card features
// in a thread safe manner. SDIO cards utilize shared register sets
// between functions. This requires that the
// register state be preserved between functions that can be
// controlled in separate thread contexts.
// This function can potentially block by issuing synchronous bus
// request. This function must not be called from a bus request callback
///////////////////////////////////////////////////////////////////////////////
SD_API_STATUS SDSetCardFeature__X(SD_DEVICE_HANDLE hDevice,
SD_SET_FEATURE_TYPE CardFeature,
PVOID pCardInfo,
ULONG StructureSize)
{
SD_API_STATUS status = SD_API_STATUS_SUCCESS; // intermediate status
PSD_DATA_TRANSFER_CLOCKS pClocks; // data transfer clocks variable
PSDCARD_DEVICE_CONTEXT pDevice = (PSDCARD_DEVICE_CONTEXT) hDevice;
if (!ValidateClientHandle(pDevice)) {
return SD_API_STATUS_INVALID_HANDLE;
}
if (NULL == pDevice) {
DEBUGMSG(SDCARD_ZONE_ERROR, (TEXT("SDSetCardFeature: device handle is NULL \n")));
return SD_API_STATUS_INVALID_PARAMETER;
}
switch (CardFeature) {
case SD_IO_FUNCTION_ENABLE:
if ((sizeof(SD_IO_FUNCTION_ENABLE_INFO) != StructureSize) ||
(NULL == pCardInfo)) {
DEBUGMSG(SDCARD_ZONE_ERROR, (TEXT("SDSetCardFeature: SD_IO_FUNCTION_ENABLE - Invalid params \n")));
return SD_API_STATUS_INVALID_PARAMETER;
}
if (Device_SD_IO != pDevice->DeviceType) {
DEBUGMSG(SDCARD_ZONE_ERROR, (TEXT("SDSetCardFeature: device is not SDIO ! \n")));
return SD_API_STATUS_INVALID_PARAMETER;
}
status = SDEnableDisableFunction(pDevice, (PSD_IO_FUNCTION_ENABLE_INFO)pCardInfo, TRUE);
break;
case SD_IO_FUNCTION_DISABLE:
if (Device_SD_IO != pDevice->DeviceType) {
DEBUGMSG(SDCARD_ZONE_ERROR, (TEXT("SDSetCardFeature: device is not SDIO ! \n")));
return SD_API_STATUS_INVALID_PARAMETER;
}
status = SDEnableDisableFunction(pDevice, NULL, FALSE);
break;
case SD_IO_FUNCTION_SET_BLOCK_SIZE:
if ((sizeof(DWORD) != StructureSize) ||
(NULL == pCardInfo)) {
DEBUGMSG(SDCARD_ZONE_ERROR, (TEXT("SDSetCardFeature: SD_IO_FUNCTION_SET_BLOCK_SIZE - Invalid params \n")));
return SD_API_STATUS_INVALID_PARAMETER;
}
if (Device_SD_IO != pDevice->DeviceType) {
DEBUGMSG(SDCARD_ZONE_ERROR, (TEXT("SDSetCardFeature: device is not SDIO ! \n")));
return SD_API_STATUS_INVALID_PARAMETER;
}
status = SDSetFunctionBlockSize(pDevice, *((DWORD *)pCardInfo));
break;
case SD_SET_DATA_TRANSFER_CLOCKS:
if ((sizeof(SD_DATA_TRANSFER_CLOCKS) != StructureSize) ||
(NULL == pCardInfo)) {
DEBUGMSG(SDCARD_ZONE_ERROR, (TEXT("SDSetCardFeature: SD_SET_DATA_TRANSFER_CLOCKS - Invalid params \n")));
return SD_API_STATUS_INVALID_PARAMETER;
}
pClocks = (PSD_DATA_TRANSFER_CLOCKS)pCardInfo;
pDevice->SDCardInfo.SDMMCInformation.DataAccessReadClocks = pClocks->ReadClocks;
pDevice->SDCardInfo.SDMMCInformation.DataAccessWriteClocks = pClocks->WriteClocks;
status = SD_API_STATUS_SUCCESS;
break;
case SD_SET_CARD_INTERFACE: {
if ((sizeof(SD_CARD_INTERFACE) != StructureSize) ||
(NULL == pCardInfo)) {
DEBUGMSG(SDCARD_ZONE_ERROR, (TEXT("SDSetCardFeature: SD_SET_CARD_INTERFACE - Invalid params \n")));
return SD_API_STATUS_INVALID_PARAMETER;
}
// Check this is NOT a multi function card
if(IS_DEVICE_MULTIFUNCTION(pDevice)) {
DEBUGMSG(SDCARD_ZONE_ERROR, (TEXT("SDSetCardFeature: SD_SET_CARD_INTERFACE - Device is multi function\n")));
return SD_API_STATUS_INVALID_DEVICE_REQUEST;
}
PSD_CARD_INTERFACE pCardInterface = (PSD_CARD_INTERFACE) pCardInfo;
// Changing the bus width is tricky when SDIO interrupts are
// enabled. In 1-bit mode, DAT[1] is used as the interrupt line.
// In 4-bit mode, DAT[1] is used for data and interrupts. If
// we change from 1-bit mode to 4-bit mode while interrupts are
// occurring (like when a BTH mouse is being moved franticly), we
// need to disable SDIO interrupts while we are changing the mode
// on both the host controller and the card. Otherwise an interrupt in
// the middle could confuse the host controller.
// Acquire lock so that we are not interrupted.
SDAcquireDeviceLock(pDevice->pParentDevice);
PSD_INTERRUPT_CALLBACK pInterruptCallBack = NULL;
if ( (Device_SD_IO == pDevice->DeviceType) &&
IS_SLOT_SDIO_INTERRUPT_ON(pDevice->pSlot) &&
(pDevice->CardInterface.InterfaceMode != pCardInterface->InterfaceMode) ) {
// Temporarily disable SDIO interrupts
pInterruptCallBack = pDevice->SDCardInfo.SDIOInformation.pInterruptCallBack;
DEBUGCHK(pInterruptCallBack);
SDIOConnectDisconnectInterrupt(hDevice, NULL, FALSE);
}
// set the card interface for device's slot
status = pDevice->pSlot->pHostController->pSlotOptionHandler(pDevice->pSlot->pHostController,
pDevice->pSlot->SlotIndex,
SDHCDSetSlotInterface,
pCardInterface,
sizeof(*pCardInterface));
// check for success
if (SD_API_SUCCESS(status)) {
// now set the interface in the card, this issues bus commands
status = SetCardInterface(pDevice, pCardInterface);
// check status
if (SD_API_SUCCESS(status)) {
// update the relevent information, keep write protect
// intact
pDevice->CardInterface.InterfaceMode = pCardInterface->InterfaceMode;
pDevice->CardInterface.ClockRate = pCardInterface->ClockRate;
}
}
if (pInterruptCallBack) {
// Re-enable SDIO interrupts
DEBUGCHK(!IS_SLOT_SDIO_INTERRUPT_ON(pDevice->pSlot));
DEBUGCHK(Device_SD_IO == pDevice->DeviceType);
SDIOConnectDisconnectInterrupt(hDevice, pInterruptCallBack, TRUE);
}
SDReleaseDeviceLock(pDevice->pParentDevice);
break;
}
case SD_SET_CLOCK_STATE_DURING_IDLE:
if ( (sizeof(BOOL) != StructureSize) || (NULL == pCardInfo) ) {
DEBUGMSG(SDCARD_ZONE_ERROR,
(TEXT("SDSetCardFeature: SD_SET_CLOCK_ON_DURING_IDLE - Invalid params \n")));
return SD_API_STATUS_INVALID_PARAMETER;
}
// prompt the host to turn on or off the clock during the idle state based on the client's
// request.
status = pDevice->pSlot->pHostController->pSlotOptionHandler(
pDevice->pSlot->pHostController,
pDevice->pSlot->SlotIndex,
SDHCDSetClockStateDuringIdle,
pCardInfo,
StructureSize);
DEBUGMSG(SDCARD_ZONE_INFO,
(TEXT("SDSetCardFeature: SDHCDSetClockStateDuringIdle finished with status: %x\n"),
status));
break;
default:
status = SD_API_STATUS_INVALID_PARAMETER;
}
return status;
}
// DO NOT REMOVE --- END EXTERNALLY DEVELOPED SOURCE CODE ID --- DO NOT REMOVE
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -