?? sdiofeat.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.
//
//
/*++
THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
PARTICULAR PURPOSE.
Module Name:
SDIOFeat.cpp
Abstract:
SDBus SDIO Setup Feature Implementation.
Notes:
--*/
#include <windows.h>
#include <types.h>
#include "../HSMMCCh1/s3c6410_hsmmc_lib/sdhcd.h"
#include "sdbus.hpp"
#include "sdslot.hpp"
//#include "sdbusreq.hpp"
#include "sddevice.hpp"
///////////////////////////////////////////////////////////////////////////////
// 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:
///////////////////////////////////////////////////////////////////////////////
SD_API_STATUS CSDDevice::SDEnableDisableFunction(PSD_IO_FUNCTION_ENABLE_INFO pInfo,BOOL Enable)
{
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
if (m_FuncionIndex == 0 ) {
DEBUGCHK(FALSE);
return SD_API_STATUS_INVALID_PARAMETER;
}
DEBUGMSG(SDBUS_ZONE_DEVICE, (TEXT("SDEnableDisableFunction: Enabling/Disabling SDIO Device Function %d \n"), m_FuncionIndex));
// Get the functions power state
status = GetFunctionPowerState(&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
status = m_sdSlot.GetHost().ChangeCardPowerHandler(m_sdSlot.GetSlotIndex(),PowerState.EnableDelta);
if (!SD_API_SUCCESS(status)) {
return status;
}
//update the power used at the slot
{
INT SlotPower = m_sdSlot.GetSlotPower();
SlotPower += PowerState.EnableDelta;
m_sdSlot.SetSlotPower( SlotPower >= 0? (USHORT)SlotPower : 0 );
}
CSDDevice *pDevice0 = m_sdSlot.GetFunctionDevice(0 );
status = SD_API_STATUS_NO_SUCH_DEVICE;
if (pDevice0) {
// update the parent device shadow register
if (Enable) {
pDevice0->m_SDCardInfo.SDIOInformation.pCommonInformation->CCCRShadowIOEnable
|= (1 << m_SDCardInfo.SDIOInformation.Function);
} else {
pDevice0->m_SDCardInfo.SDIOInformation.pCommonInformation->CCCRShadowIOEnable &=
~(1 << m_SDCardInfo.SDIOInformation.Function);
}
// get a copy
regValue = pDevice0->m_SDCardInfo.SDIOInformation.pCommonInformation->CCCRShadowIOEnable;
// update the register
status = pDevice0->SDReadWriteRegistersDirect_I(SD_IO_WRITE, SD_IO_REG_ENABLE,FALSE, ®Value, 1);
pDevice0->DeRef();
}
if (!SD_API_SUCCESS(status)) {
return status;
}
}
// if enabling we check for I/O ready
if (Enable) {
CSDDevice *pDevice0 = m_sdSlot.GetFunctionDevice(0 );
status = SD_API_STATUS_NO_SUCH_DEVICE;
if (pDevice0) {
retryCount = pInfo->ReadyRetryCount;
while (retryCount) {
// delay the interval time
Sleep(pInfo->Interval);
// read the I/O ready register
status = pDevice0->SDReadWriteRegistersDirect_I( SD_IO_READ, SD_IO_REG_IO_READY,FALSE,®Value,1); // one byte
if (!SD_API_SUCCESS(status)) {
break;
}
// see if it is ready
if (regValue & (1 << m_SDCardInfo.SDIOInformation.Function)) {
DEBUGMSG(SDBUS_ZONE_DEVICE, (TEXT("SDEnableDisableFunction: Card Function %d is now ready \n"),
m_SDCardInfo.SDIOInformation.Function));
break;
}
// decrement the count
retryCount--;
DEBUGMSG(SDBUS_ZONE_DEVICE, (TEXT("SDEnableDisableFunction: Card Function %d, Not Ready, re-checking (%d) \n"),
m_SDCardInfo.SDIOInformation.Function, retryCount));
}
if (0 == retryCount) {
DEBUGMSG(SDBUS_ZONE_DEVICE, (TEXT("SDEnableDisableFunction: Card Function %d, Not ready , exceeded retry count\n"),
m_SDCardInfo.SDIOInformation.Function));
status = SD_API_STATUS_DEVICE_NOT_RESPONDING;
}
pDevice0->DeRef();
}
}
return status;
}
///////////////////////////////////////////////////////////////////////////////
// SDFunctionSelectPower - switch device function to High or Low power state
// Input: pDevice - the device
// fLowPower - High or Low Power state
// Output:
// Return: SD_API_STATUS code
//
// Notes:
///////////////////////////////////////////////////////////////////////////////
SD_API_STATUS CSDDevice::SDFunctionSelectPower( BOOL fLowPower)
{
UCHAR regValue; // temp register value
SD_API_STATUS status; // intermediate status
FUNCTION_POWER_STATE PowerState; // The function's power state
DWORD FBROffset; // calculated FBR offset
// get the parent device
if (0 == m_FuncionIndex) {
DEBUG_ASSERT(FALSE);
return SD_API_STATUS_INVALID_PARAMETER;
}
DEBUGMSG(SDBUS_ZONE_DEVICE, (TEXT("SDFunctionSelectPower: SDIO Device Function %d Power Select\n"),
m_SDCardInfo.SDIOInformation.Function));
// Get the functions power state
status = GetFunctionPowerState(&PowerState);
if (!SD_API_SUCCESS(status)) {
return status;
}
//check if power selection is supported
if((!PowerState.fPowerControlSupport) || (!PowerState.fSupportsPowerSelect)) {
DEBUGMSG(SDCARD_ZONE_ERROR, (TEXT("SDFunctionSelectPower: Card or Function does not support Power Select.\n")));
return SD_API_STATUS_INVALID_DEVICE_REQUEST;
}
// Check if states already match
if (PowerState.fLowPower == fLowPower){
if (fLowPower) {
DEBUGMSG(SDCARD_ZONE_WARN, (TEXT("SDFunctionSelectPower: Attempting to select low power state when that is already enabled \n")));
}
else{
DEBUGMSG(SDCARD_ZONE_WARN, (TEXT("SDFunctionSelectPower: Attempting to select high power state when that is already enabled \n")));
}
return SD_API_STATUS_SUCCESS;
}
// Attempt to change cards power draw
status = m_sdSlot.GetHost().ChangeCardPowerHandler(m_sdSlot.GetSlotIndex(),PowerState.SelectDelta);
if (!SD_API_SUCCESS(status)) {
return status;
}
//update the power used at the slot
{
INT SlotPower = m_sdSlot.GetSlotPower();
SlotPower += PowerState.SelectDelta;
m_sdSlot.SetSlotPower( SlotPower >= 0? (USHORT)SlotPower : 0 );
}
CSDDevice *pDevice0 = m_sdSlot.GetFunctionDevice(0 );
status = SD_API_STATUS_NO_SUCH_DEVICE;
if (pDevice0) {
// select the function's power state
FBROffset = SD_IO_FBR_1_OFFSET + (m_SDCardInfo.SDIOInformation.Function - 1) * SD_IO_FBR_LENGTH;
status = pDevice0->SDReadWriteRegistersDirect_I(SD_IO_READ,FBROffset + SD_IO_FBR_POWER_SELECT,FALSE,®Value,1);
if (SD_API_SUCCESS(status)) {
if(fLowPower) {
regValue |= SD_IO_FUNCTION_POWER_SELECT_STATE;
}
else {
regValue &= ~SD_IO_FUNCTION_POWER_SELECT_STATE;
}
status = pDevice0->SDReadWriteRegistersDirect_I(SD_IO_WRITE,FBROffset + SD_IO_FBR_POWER_SELECT,FALSE,®Value,1);
}
pDevice0->DeRef();
}
return status;
}
///////////////////////////////////////////////////////////////////////////////
// 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 CSDDevice::SDSetFunctionBlockSize(DWORD BlockSize)
{
USHORT bytesPerBlock = (USHORT)BlockSize; // desired block size
DWORD FBROffset; // FBR offset
SD_API_STATUS status;
DEBUGCHK(0 != m_SDCardInfo.SDIOInformation.Function);
// calculate the FBR offset based on the function number
FBROffset = SD_IO_FBR_1_OFFSET + (m_SDCardInfo.SDIOInformation.Function - 1) * SD_IO_FBR_LENGTH;
CSDDevice *pDevice0 = m_sdSlot.GetFunctionDevice(0 );
status = SD_API_STATUS_NO_SUCH_DEVICE;
if (pDevice0) {
// update the register
status = pDevice0->SDReadWriteRegistersDirect_I( SD_IO_WRITE, FBROffset + SD_IO_FBR_IO_BLOCK_SIZE, FALSE,(PUCHAR)&bytesPerBlock,sizeof(USHORT)); // two bytes
pDevice0->DeRef();
}
return status;
}
SD_API_STATUS CSDDevice::SetCardFeature_Interface(SD_CARD_INTERFACE_EX& CardInterfaceEx)
{
SD_API_STATUS status = SD_API_STATUS_SUCCESS; // intermediate status
// Check if the slot can accept this interface request
// For multifunction card or combo card, the requested interface may not be fitted
// for other functions.
{
BOOL bAllFunctionsAcceptThisInterface = TRUE;
// Start from parent device
BOOL fContinue = TRUE;
for (DWORD dwIndex = 0; dwIndex < SD_MAXIMUM_DEVICE_PER_SLOT && fContinue ; dwIndex++) {
CSDDevice * pDevice = m_sdSlot.GetFunctionDevice(dwIndex);
if (pDevice != NULL ) {
if (dwIndex!=GetDeviceFuncionIndex() && pDevice->GetDeviceType() != Device_Unknown ) {
// Check if current device supports 4 bit mode request
if (CardInterfaceEx.InterfaceModeEx.bit.sd4Bit && !(pDevice->m_CardInterfaceEx.InterfaceModeEx.bit.sd4Bit)) {
bAllFunctionsAcceptThisInterface = FALSE;
fContinue = FALSE;
}
else
// Check if request clock rate is too high for this device
if (CardInterfaceEx.ClockRate > pDevice->m_CardInterfaceEx.ClockRate) {
bAllFunctionsAcceptThisInterface = FALSE;
fContinue = FALSE;
}
else
if (!(CardInterfaceEx.InterfaceModeEx.bit.sdHighSpeed) && pDevice->m_CardInterfaceEx.InterfaceModeEx.bit.sdHighSpeed){
bAllFunctionsAcceptThisInterface = FALSE;
fContinue = FALSE;
}
}
pDevice->DeRef();
}
}
if (bAllFunctionsAcceptThisInterface == FALSE) {
DbgPrintZo(SDCARD_ZONE_ERROR, (TEXT("SDSetCardFeature: SD_SET_CARD_INTERFACE - invalod interface request\n")));
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -