📄 sdcardio.cpp
字号:
// 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
//
// 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
BOOL fSkipIfMatch; // Test for setting the same bit twice
FUNCTION_POWER_STATE PowerState; // The function's power state
PSD_CHANGE_CARD_POWER pPowerChangeHandler;
CSDBusDriver *pBusDriver; // Pointer to the bus driver class
// 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));
// Get a pointer to the bus driver calss
pBusDriver = SDDCGetBusDriver(pDevice);
// Get the functions power state
status = pBusDriver->GetFunctionPowerState(pDevice, &PowerState);
if (!SD_API_SUCCESS(status)) {
return status;
}
// First check if states already match
fSkipIfMatch = FALSE;
if (PowerState.fFunctionEnabled == Enable)
{
if (Enable) {
DEBUGMSG(SDCARD_ZONE_WARN,
(TEXT("SDEnableDisableFunction: Attempting to enable function that is already enabled \n")));
fSkipIfMatch = TRUE;
}
else
{
DEBUGMSG(SDCARD_ZONE_WARN,
(TEXT("SDEnableDisableFunction: Attempting to disable function that is already disabled \n")));
fSkipIfMatch = TRUE;
}
}
if (!fSkipIfMatch) {
// Attempt to change cards power draw
pPowerChangeHandler = SDHCDGetChangePowerHandler(pDevice->pSlot->pHostController);
status = pPowerChangeHandler(pDevice->pSlot->pHostController, pDevice->pSlot->SlotIndex, PowerState.EnableDelta);
if (!SD_API_SUCCESS(status)) {
return status;
}
//update the power used at the slot
{
INT SlotPower = (INT)SDHCDGetSlotPower(pDevice->pSlot->pHostController, pDevice->pSlot->SlotIndex);
SlotPower += PowerState.EnableDelta;
if(SlotPower >= 0)
{
SDHCDSetSlotPower(pDevice->pSlot->pHostController, pDevice->pSlot->SlotIndex, (USHORT)SlotPower);
}
else
{
SDHCDSetSlotPower(pDevice->pSlot->pHostController, pDevice->pSlot->SlotIndex, 0);
}
}
// must interlock this request with the parent device to update the shadow register
SDDCAcquireDeviceLock(pParentDevice);
// update the parent device shadow register
if (Enable) {
pParentDevice->SDCardInfo.SDIOInformation.pCommonInformation->CCCRShadowIOEnable
|= (1 << pDevice->SDCardInfo.SDIOInformation.Function);
} else {
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,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -