?? sdhceventhandlers.cpp
字號:
} else {
// the VER_1 tuple is optional, so if we could not find it, we
// allocate the string identifying it as unknown
found = FALSE;
length = UNKNOWN_PRODUCT_INFO_STRING_LENGTH;
}
// allocate the string (include NULL) even if no tuple
pDevice->SDCardInfo.SDIOInformation.pCommonInformation->pProductInformation =
(PWCHAR)SDAllocateMemoryWithTag((sizeof(WCHAR)) * (length + 1),
SD_BUS_DRIVER_TAG);
if (NULL == pDevice->SDCardInfo.SDIOInformation.pCommonInformation->pProductInformation) {
DEBUGMSG(SDCARD_ZONE_ERROR, (TEXT("SDBusDriver: Failed to allocate product information string \n")));
return SD_API_STATUS_INSUFFICIENT_RESOURCES;
}
if (found) {
pVersionBuffer = (PCHAR)SDAllocateMemoryWithTag((sizeof(CHAR)) * (length + 1),
SD_BUS_DRIVER_TAG);
if (NULL == pVersionBuffer) {
DEBUGMSG(SDCARD_ZONE_ERROR, (TEXT("SDBusDriver: Failed to allocate product information string \n")));
return SD_API_STATUS_INSUFFICIENT_RESOURCES;
}
// retrieve the tuple from the common CIS
status = SDGetTuple__X((SD_DEVICE_HANDLE)pDevice,
SD_CISTPL_VERS_1,
(PUCHAR)pVersionBuffer,
&length,
TRUE);
if (!SD_API_SUCCESS(status)) {
SDFreeMemory(pVersionBuffer);
return status;
}
// make sure the string is null terminated
pVersionBuffer[length] = NULL;
// bump past the binary version info,
// and format the string to wide char
FormatProductString(&pVersionBuffer[2],
pDevice->SDCardInfo.SDIOInformation.pCommonInformation->pProductInformation);
// free the version buffer
SDFreeMemory(pVersionBuffer);
} else {
// form the product name based on the required MANF and CARDID instead of the
// ver1 string
swprintf( pDevice->SDCardInfo.SDIOInformation.pCommonInformation->pProductInformation,
TEXT("Manufacturer ID:0x%04X, Card ID:0x%04X"),
pDevice->SDCardInfo.SDIOInformation.pCommonInformation->ManufacturerID,
pDevice->SDCardInfo.SDIOInformation.pCommonInformation->CardID);
}
}
// function 0 is a fictitious function
DEBUGCHK(0 != pDevice->SDCardInfo.SDIOInformation.Function);
// calculate the FBR offset
FBROffset = SD_IO_FBR_1_OFFSET + (pDevice->SDCardInfo.SDIOInformation.Function - 1) *
SD_IO_FBR_LENGTH;
// fetch the device code
status = SDReadWriteRegistersDirect__X((SD_DEVICE_HANDLE)pDevice,
SD_IO_READ,
0, // all from function 0
FBROffset + SD_IO_FBR_DEVICE_CODE,
FALSE,
regValue,
1);
if (!SD_API_SUCCESS(status)) {
return status;
}
// save the device code, 1.0 style
pDevice->SDCardInfo.SDIOInformation.DeviceCode =
(regValue[0] & SDIO_DEV_CODE_MASK);
// check to see if we are using the special device code extension token
if (SDIO_DEV_CODE_USES_EXTENSION ==
pDevice->SDCardInfo.SDIOInformation.DeviceCode) {
// check the CCCR revision for 1.1
if ((pDevice->SDCardInfo.SDIOInformation.pCommonInformation->CCCRRev
& SDIO_CCCR_SPEC_REV_MASK) == SDIO_CCCR_SPEC_REV_1_1) {
// fetch the device code extension
status = SDReadWriteRegistersDirect__X((SD_DEVICE_HANDLE)pDevice,
SD_IO_READ,
0,
FBROffset + SD_IO_FBR_DEVICE_CODE_EXT,
FALSE,
regValue,
1);
if (!SD_API_SUCCESS(status)) {
return status;
}
// now 0x10-0xFF are available as device code extensions
pDevice->SDCardInfo.SDIOInformation.DeviceCode = regValue[0];
}
}
// get the CIS and CSA pointers, we do a multi-byte read here
status = SDReadWriteRegistersDirect__X((SD_DEVICE_HANDLE)pDevice,
SD_IO_READ,
0, // all from function 0
FBROffset + SD_IO_FBR_CISP_BYTE_0,
FALSE,
CSA_CISBuffer,
CIS_CSA_BYTES);
if (!SD_API_SUCCESS(status)) {
return status;
}
pDevice->SDCardInfo.SDIOInformation.CISPointer = CSA_CISBuffer[CIS_OFFSET_BYTE_0] |
(CSA_CISBuffer[CIS_OFFSET_BYTE_1] << 8) |
(CSA_CISBuffer[CIS_OFFSET_BYTE_2] << 16);
pDevice->SDCardInfo.SDIOInformation.CSAPointer = CSA_CISBuffer[CSA_OFFSET_BYTE_0] |
(CSA_CISBuffer[CSA_OFFSET_BYTE_1] << 8) |
(CSA_CISBuffer[CSA_OFFSET_BYTE_2] << 16);
// allocate a product information tuple and fill it will some sort of
// friendly name string
pDevice->SDCardInfo.SDIOInformation.pFunctionInformation =
(PWCHAR)SDAllocateMemoryWithTag((sizeof(CHAR)) * (UNKNOWN_PRODUCT_INFO_STRING_LENGTH + 1),
SD_BUS_DRIVER_TAG);
if (NULL == pDevice->SDCardInfo.SDIOInformation.pFunctionInformation) {
DEBUGMSG(SDCARD_ZONE_ERROR, (TEXT("SDBusDriver: Failed to allocate product information string \n")));
status = SD_API_STATUS_INSUFFICIENT_RESOURCES;
return status;
}
// form the product name using the device class
swprintf(pDevice->SDCardInfo.SDIOInformation.pFunctionInformation,
TEXT("Device of Class Type: %d"),
pDevice->SDCardInfo.SDIOInformation.DeviceCode);
DEBUGMSG(SDBUS_ZONE_DEVICE, (TEXT("SDBusDriver: Device 0x%08X , Function String: %s \n"),
pDevice,
pDevice->SDCardInfo.SDIOInformation.pFunctionInformation));
DEBUGMSG(SDBUS_ZONE_DEVICE, (TEXT("SDBusDriver: Common Product String: %s \n"),
pDevice->pParentDevice->SDCardInfo.SDIOInformation.pCommonInformation->pProductInformation));
return status;
}
///////////////////////////////////////////////////////////////////////////////
// SDIOSupportsWakeup - Look at CISTPL_FUNCE for the function to see if
// wakeup is supported
// Input: pDevice - the device
//
// Return: TRUE if wakeup is supported
///////////////////////////////////////////////////////////////////////////////
static
BOOL SDIOSupportsWakeup(PSDCARD_DEVICE_CONTEXT pDevice)
{
PREFAST_DEBUGCHK(pDevice);
BOOL fRet = FALSE;
BYTE rgbFunce[SD_CISTPLE_MAX_BODY_SIZE];
PSD_CISTPL_FUNCE_FUNCTION pFunce = (PSD_CISTPL_FUNCE_FUNCTION) rgbFunce;
DWORD cbTuple;
SD_API_STATUS status = SDGetTuple__X((SD_DEVICE_HANDLE)pDevice,
SD_CISTPL_FUNCE, NULL, &cbTuple, FALSE);
if ( SD_API_SUCCESS(status) && (cbTuple <= sizeof(rgbFunce)) ) {
status = SDGetTuple__X((SD_DEVICE_HANDLE)pDevice,
SD_CISTPL_FUNCE, rgbFunce, &cbTuple, FALSE);
if ( SD_API_SUCCESS(status) && (pFunce->bType == SD_CISTPL_FUNCE_FUNCTION_TYPE) ) {
// Valid FUNCE tuple. Check the wake up support bit.
if (pFunce->FN_WUS) {
fRet = TRUE;
}
}
}
return fRet;
}
///////////////////////////////////////////////////////////////////////////////
// SDCreateChildDevice - create a child device for a multifunction parent device
// Input: pParent - the parent device
// DeviceType - the device type
// FunctionNumber - function number
//
// Output: ppChildDevice - the new child device
// Return: SD_API_STATUS code
// Notes:
// This function adds a child device to a parent device. This
// allows us to keep track of multifunction devices.
///////////////////////////////////////////////////////////////////////////////
SD_API_STATUS SDCreateChildDevice(PSDCARD_DEVICE_CONTEXT pParent,
SDCARD_DEVICE_TYPE DeviceType,
UCHAR FunctionNumber,
PSDCARD_DEVICE_CONTEXT *ppChildDevice)
{
PSDCARD_DEVICE_CONTEXT pNewDevice;
// allocate a device
pNewDevice = ((CSDBusDriver *)pParent->pSystemContext)->AllocateDeviceContext();
if (NULL == pNewDevice) {
DEBUGMSG(SDCARD_ZONE_ERROR, (TEXT("SDBusDriver: SDCreateChildDevice- , Failed to create device. \n")));
return SD_API_STATUS_INSUFFICIENT_RESOURCES;
}
// copy some parameters inherited from the parent device
pNewDevice->pSlot = pParent->pSlot;
pNewDevice->RelativeAddress = pParent->RelativeAddress;
pNewDevice->OperatingVoltage = pParent->OperatingVoltage;
if (Device_SD_IO == DeviceType) {
pNewDevice->SDCardInfo.SDIOInformation.Function = FunctionNumber;
}
// set the parent device
pNewDevice->pParentDevice = pParent;
// set new device type
pNewDevice->DeviceType = DeviceType;
if (Device_SD_IO == DeviceType) {
// copy the I/O Ocr
memcpy(&pNewDevice->CachedRegisters.IO_OCR,
&pParent->CachedRegisters.IO_OCR,
sizeof(pParent->CachedRegisters.IO_OCR));
} else if (Device_SD_Memory == DeviceType) {
// copy all the shadowed registers from the parent
memcpy(&pNewDevice->CachedRegisters,
&pParent->CachedRegisters,
sizeof(pParent->CachedRegisters));
} else {
DEBUGCHK(FALSE);
SDFreeMemory(pNewDevice);
return SD_API_STATUS_INVALID_PARAMETER;
}
// insert the device into the list
if (NULL == pParent->pNext) {
pNewDevice->pNext = NULL;
pParent->pNext = pNewDevice;
} else {
// insert at the head of the list
pNewDevice->pNext = pParent->pNext;
pParent->pNext = pNewDevice;
}
// return the device
*ppChildDevice = pNewDevice;
return SD_API_STATUS_SUCCESS;
}
///////////////////////////////////////////////////////////////////////////////
// SDGetOperationalVoltageRange - Get the operation voltage range
// Input: OcrValue - OCR bit mask to determine the voltage range
// pSlot - the slot
//
// Output:
// Return: DWORD bit mask for optimal operational voltage
// Notes:
// This function compares the OcrValue against the desired
// voltage range of the slot and the capabilities of the slot
// the operational value (also encoded as an OCR value) is returned
// A value of zero indicates no usable voltage range.
///////////////////////////////////////////////////////////////////////////////
DWORD SDGetOperationalVoltageRange(DWORD OcrValue, PSDBUS_HC_SLOT_CONTEXT pSlot)
{
ULONG i; // loop variable
// check to see if the voltages can be supported
if (OcrValue & pSlot->VoltageWindowMask) {
// check to see if the voltage meets the desired voltage range
if (OcrValue & pSlot->DesiredVoltageMask) {
DEBUGMSG(SDBUS_ZONE_DEVICE, (TEXT("SDBusDriver: Device Power Range:0x%08X matches HC desired power: 0x%08X \n"),
OcrValue, pSlot->DesiredVoltageMask));
// returned desired voltage range suggested by host controller
return pSlot->DesiredVoltageMask;
} else {
// walk through the voltage mask starting at the low end looking for
// a voltage that will work with the OCR value
for (i = 0; i < 32; i++) {
if (OcrValue & pSlot->VoltageWindowMask & (1 << i)) {
DEBUGMSG(SDBUS_ZONE_DEVICE, (TEXT("SDBusDriver: Device Power Range:0x%08X does not match HC desired power 0x%08X \n"),
OcrValue, pSlot->DesiredVoltageMask));
DEBUGMSG(SDBUS_ZONE_DEVICE, (TEXT("Using negotiated power range: 0x%08X \n"),
(1 << i)));
// found a match
return (1 << i);
}
}
// this should never happen,
DEBUGCHK(FALSE);
return 0;
}
} else {
return 0;
}
}
///////////////////////////////////////////////////////////////////////////////
// SendSDAppCmd - send an SD App Command synchronously (sends CMD55 followed by command)
// Input: hDevice - device handle
// Command - command to send
// Argument - argument for command
// TransferClass - transfer class
// ResponseType - expected response
// NumberOfBlocks - number of blocks
// BlockSize - number of blocks
// pBlockBuffer - buffer size
// Output:
// pResponse - response buffer
// Return: SD_API_STATUS code
// Notes:
//
///////////////////////////////////////////////////////////////////////////////
SD_API_STATUS SendSDAppCmd(SD_DEVICE_HANDLE hDevice,
UCHAR Command,
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -