Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

563 lines
16 KiB

/*++
Copyright (c) 2002 Microsoft Corporation
Module Name:
card.c
Abstract:
This module contains code to handle SD card operations like identification
and configuration.
Authors:
Neil Sandlin (neilsa) 1-Jan-2002
Environment:
Kernel mode only
Notes:
Revision History:
--*/
#include "pch.h"
//
// Internal References
//
VOID
SdbusReadCommonCIS(
IN PFDO_EXTENSION FdoExtension,
IN PSD_CARD_DATA CardData
);
VOID
SdbusReadFunctionCIS(
IN PFDO_EXTENSION FdoExtension,
IN PSD_FUNCTION_DATA FunctionData
);
NTSTATUS
SdbusGetCardConfigData(
IN PFDO_EXTENSION FdoExtension,
OUT PSD_CARD_DATA *pCardData
)
/*++
Routine Description:
This enumerates the IO card present in the given SDBUS controller,
and updates the internal structures to reflect the new card state.
Arguments
Return value
Status
--*/
{
NTSTATUS status = STATUS_UNSUCCESSFUL;
ULONG i;
ULONG relativeAddr = FdoExtension->RelativeAddr;
PSD_CARD_DATA cardData = NULL;
ULONG responseBuffer[4];
try{
if ((FdoExtension->numFunctions!=0) || FdoExtension->memFunction) {
PSD_FUNCTION_DATA functionData;
DebugPrint((SDBUS_DEBUG_ENUM, "fdo %08x IO functions found=%d, memFunction=%s\n",
FdoExtension->DeviceObject, FdoExtension->numFunctions,
(FdoExtension->memFunction ? "TRUE" : "FALSE")));
//
// At this point, it would be good to verify if the previous enumeration matches
// the present one. This hokey mechanism is just to get something working.
// ISSUE: NEED TO IMPLEMENT: swapping SD cards while hibernated
//
cardData = ExAllocatePool(NonPagedPool, sizeof(SD_CARD_DATA));
if (cardData == NULL) {
status = STATUS_INSUFFICIENT_RESOURCES;
leave;
}
RtlZeroMemory(cardData, sizeof(SD_CARD_DATA));
if (FdoExtension->memFunction) {
PUCHAR pResponse, pTarget;
UCHAR j;
cardData->SdCid = FdoExtension->SdCid;
cardData->SdCsd = FdoExtension->SdCsd;
for (j=0; j<5; j++) {
UCHAR data = cardData->SdCid.ProductName[4-j];
if ((data <= ' ') || data > 0x7F) {
break;
}
cardData->ProductName[j] = data;
}
}
if (FdoExtension->memFunction) {
//
// Read the SCR register
//
SdbusSendCmdSynchronous(FdoExtension, SDCMD_APP_CMD, SDCMD_RESP_1, relativeAddr, 0, NULL, 0);
//ISSUE: How do I get the data?
SdbusSendCmdSynchronous(FdoExtension, SDCMD_SEND_SCR, SDCMD_RESP_1, 0, SDCMDF_ACMD, NULL, 0);
}
if (FdoExtension->numFunctions) {
UCHAR function;
(*(FdoExtension->FunctionBlock->SetFunctionType))(FdoExtension, SDBUS_FUNCTION_TYPE_IO);
// This command seems to be needed to start reading tuples, but breaks memory
// enumeration (gets bad Cid, Csd)... need to figure that out later, since that
// would imply that a combo card wouldn't work.
SdbusReadCommonCIS(FdoExtension, cardData);
for (function=1; function<=FdoExtension->numFunctions; function++) {
functionData = ExAllocatePool(NonPagedPool, sizeof(SD_FUNCTION_DATA));
if (functionData == NULL) {
status = STATUS_INSUFFICIENT_RESOURCES;
leave;
}
RtlZeroMemory(functionData, sizeof(SD_FUNCTION_DATA));
functionData->Function = function;
SdbusReadFunctionCIS(FdoExtension, functionData);
functionData->Next = cardData->FunctionData;
cardData->FunctionData = functionData;
}
}
status = STATUS_SUCCESS;
}
} finally {
if (!NT_SUCCESS(status)) {
SdbusCleanupCardData(cardData);
} else {
*pCardData = cardData;
}
}
return status;
}
VOID
SdbusCleanupCardData(
IN PSD_CARD_DATA CardData
)
{
PSD_FUNCTION_DATA functionData;
PSD_FUNCTION_DATA nextFunctionData;
if (CardData != NULL) {
for (functionData = CardData->FunctionData; functionData != NULL; functionData = nextFunctionData) {
nextFunctionData = functionData->Next;
ExFreePool(functionData);
}
ExFreePool(CardData);
}
}
UCHAR
SdbusReadCIAChar(
IN PFDO_EXTENSION FdoExtension,
IN ULONG ciaPtr
)
{
SD_RW_DIRECT_ARGUMENT argument;
UCHAR response;
argument.u.AsULONG = 0;
argument.u.bits.Address = ciaPtr;
SdbusSendCmdSynchronous(FdoExtension,
SDCMD_IO_RW_DIRECT,
SDCMD_RESP_5,
argument.u.AsULONG,
0,
&response,
sizeof(UCHAR));
return response;
}
VOID
SdbusWriteCIAChar(
IN PFDO_EXTENSION FdoExtension,
IN ULONG ciaPtr,
IN UCHAR data
)
{
SD_RW_DIRECT_ARGUMENT argument;
ULONG responseBuffer[4];
argument.u.AsULONG = 0;
argument.u.bits.Address = ciaPtr;
argument.u.bits.Data = data;
argument.u.bits.WriteToDevice = 1;
SdbusSendCmdSynchronous(FdoExtension,
SDCMD_IO_RW_DIRECT,
SDCMD_RESP_5,
argument.u.AsULONG,
0,
NULL,
0);
}
USHORT
SdbusReadCIAWord(
IN PFDO_EXTENSION FdoExtension,
IN ULONG ciaPtr
)
{
USHORT data;
data = (USHORT) SdbusReadCIAChar(FdoExtension, ciaPtr+1) << 8;
data |= (USHORT) SdbusReadCIAChar(FdoExtension, ciaPtr);
return data;
}
ULONG
SdbusReadCIADword(
IN PFDO_EXTENSION FdoExtension,
IN ULONG ciaPtr
)
{
ULONG data;
data = (ULONG) SdbusReadCIAChar(FdoExtension, ciaPtr+3) << 24;
data |= (ULONG) SdbusReadCIAChar(FdoExtension, ciaPtr+2) << 16;
data |= (ULONG) SdbusReadCIAChar(FdoExtension, ciaPtr+1) << 8;
data |= (ULONG) SdbusReadCIAChar(FdoExtension, ciaPtr);
return data;
}
VOID
SdbusReadCommonCIS(
IN PFDO_EXTENSION FdoExtension,
IN PSD_CARD_DATA CardData
)
{
UCHAR cmd, link;
UCHAR i;
ULONG tupleCount = 0;
USHORT manfCode, manfInf;
UCHAR funcId;
UCHAR funcEType;
ULONG cisPtr;
ULONG index;
ULONG endStr;
UCHAR data;
CardData->CardCapabilities = SdbusReadCIAChar(FdoExtension,8);
//
// Get the common cisptr from the CCCR
//
cisPtr = ((SdbusReadCIAChar(FdoExtension, SD_CCCR_CIS_POINTER+2) << 16) +
(SdbusReadCIAChar(FdoExtension, SD_CCCR_CIS_POINTER+1) << 8) +
SdbusReadCIAChar(FdoExtension, SD_CCCR_CIS_POINTER));
DebugPrint((SDBUS_DEBUG_ENUM, "fdo %08x cisPtr=%.06x\n",
FdoExtension->DeviceObject, cisPtr));
cmd = SdbusReadCIAChar(FdoExtension, cisPtr);
link = SdbusReadCIAChar(FdoExtension, cisPtr+1);
while((cmd != CISTPL_END) && (cmd != CISTPL_NULL)) {
tupleCount++;
DebugPrint((SDBUS_DEBUG_ENUM, "fdo %08x CIS %.06x cmd=%.02x link=%.02x\n",
FdoExtension->DeviceObject, cisPtr, cmd, link));
switch(cmd) {
case CISTPL_MANFID:
if (link < 4) {
DebugPrint((SDBUS_DEBUG_FAIL, "fdo %08x CISTPL_MANFID invalid link %x\n",
FdoExtension->DeviceObject, link));
return;
}
CardData->MfgId = SdbusReadCIAWord(FdoExtension, cisPtr+2);
CardData->MfgInfo = SdbusReadCIAWord(FdoExtension, cisPtr+4);
DebugPrint((SDBUS_DEBUG_ENUM, "fdo %08x CISTPL_MANFID code=%x, inf=%x\n",
FdoExtension->DeviceObject, CardData->MfgId, CardData->MfgInfo));
break;
case CISTPL_VERS_1:
index = cisPtr+4;
endStr = index + (link - 2);
i = 0;
data = SdbusReadCIAChar(FdoExtension, index++);
while (data) {
if (index > endStr) {
DebugPrint((SDBUS_DEBUG_FAIL, "fdo %08x CISTPL_VERS_1 parse error\n",
FdoExtension->DeviceObject));
return;
}
if (data >= ' ' && data < 0x7F) {
CardData->MfgText[i++] = data;
}
data = SdbusReadCIAChar(FdoExtension, index++);
}
CardData->MfgText[i] = 0;
i = 0;
data = SdbusReadCIAChar(FdoExtension, index++);
while (data) {
if (index > endStr) {
DebugPrint((SDBUS_DEBUG_FAIL, "fdo %08x CISTPL_VERS_1 parse error\n",
FdoExtension->DeviceObject));
return;
}
if (data >= ' ' && data < 0x7F) {
CardData->ProductText[i++] = data;
}
data = SdbusReadCIAChar(FdoExtension, index++);
}
CardData->ProductText[i] = 0;
DebugPrint((SDBUS_DEBUG_ENUM, "fdo %08x CISTPL_VERS_1 %s %s\n",
FdoExtension->DeviceObject, CardData->MfgText, CardData->ProductText));
break;
case CISTPL_FUNCID:
if (link != 2) {
DebugPrint((SDBUS_DEBUG_FAIL, "fdo %08x CISTPL_FUNCID invalid link %x\n",
FdoExtension->DeviceObject, link));
return;
}
funcId = SdbusReadCIAChar(FdoExtension, cisPtr+2);
if (funcId != 12) {
DebugPrint((SDBUS_DEBUG_FAIL, "fdo %08x CISTPL_FUNCID invalid id %x\n",
FdoExtension->DeviceObject, funcId));
return;
}
break;
case CISTPL_FUNCE:
funcEType = SdbusReadCIAChar(FdoExtension, cisPtr+2);
if (funcEType == 0) {
USHORT blkSize;
UCHAR tranSpeed;
if (link != 4) {
DebugPrint((SDBUS_DEBUG_FAIL, "fdo %08x CISTPL_FUNCE invalid type0 link %x\n",
FdoExtension->DeviceObject, link));
return;
}
blkSize = SdbusReadCIAWord(FdoExtension, cisPtr+3);
tranSpeed = SdbusReadCIAChar(FdoExtension, cisPtr+5);
DebugPrint((SDBUS_DEBUG_ENUM, "fdo %08x CISTPL_FUNCE 0 blksize %04x transpeed %02x\n",
FdoExtension->DeviceObject, blkSize, tranSpeed));
} else {
DebugPrint((SDBUS_DEBUG_FAIL, "fdo %08x CISTPL_FUNCE invalid funce type %x\n",
FdoExtension->DeviceObject, funcEType));
return;
}
break;
}
cisPtr += link+2;
cmd = SdbusReadCIAChar(FdoExtension, cisPtr);
link = SdbusReadCIAChar(FdoExtension, cisPtr+1);
}
DebugPrint((SDBUS_DEBUG_ENUM, "fdo %08x CIS %.06x cmd=%.02x link=%.02x EXITING %d tuples read\n",
FdoExtension->DeviceObject, cisPtr, cmd, link, tupleCount));
}
VOID
SdbusReadFunctionCIS(
IN PFDO_EXTENSION FdoExtension,
IN PSD_FUNCTION_DATA FunctionData
)
{
UCHAR cmd, link;
UCHAR i;
ULONG tupleCount = 0;
UCHAR funcId;
UCHAR funcEType;
ULONG fbrPtr = FunctionData->Function*0x100;
ULONG cisPtr;
BOOLEAN hasCsa;
UCHAR data;
data = SdbusReadCIAChar(FdoExtension, fbrPtr);
FunctionData->IoDeviceInterface = data & 0xf;
hasCsa = ((data & 0x40) != 0);
cisPtr = ((SdbusReadCIAChar(FdoExtension, fbrPtr + SD_CCCR_CIS_POINTER + 2) << 16) +
(SdbusReadCIAChar(FdoExtension, fbrPtr + SD_CCCR_CIS_POINTER + 1) << 8) +
SdbusReadCIAChar(FdoExtension, fbrPtr + SD_CCCR_CIS_POINTER));
DebugPrint((SDBUS_DEBUG_ENUM, "fdo %08x function %d cisPtr=%.06x interfaceCode=%d hasCsa=%s\n",
FdoExtension->DeviceObject, FunctionData->Function, cisPtr, FunctionData->IoDeviceInterface,
hasCsa ? "TRUE" : "FALSE"));
if (!cisPtr || (cisPtr == 0xFFFFFF)) {
return;
}
cmd = SdbusReadCIAChar(FdoExtension, cisPtr);
link = SdbusReadCIAChar(FdoExtension, cisPtr+1);
while((cmd != CISTPL_END) && (cmd != CISTPL_NULL)) {
tupleCount++;
DebugPrint((SDBUS_DEBUG_ENUM, "fdo %08x CIS %.06x cmd=%.02x link=%.02x\n",
FdoExtension->DeviceObject, cisPtr, cmd, link));
switch(cmd) {
case CISTPL_FUNCID:
if (link != 2) {
DebugPrint((SDBUS_DEBUG_FAIL, "fdo %08x CISTPL_FUNCID invalid link %x\n",
FdoExtension->DeviceObject, link));
return;
}
funcId = SdbusReadCIAChar(FdoExtension, cisPtr+2);
if (funcId != 12) {
DebugPrint((SDBUS_DEBUG_FAIL, "fdo %08x CISTPL_FUNCID invalid id %x\n",
FdoExtension->DeviceObject, funcId));
return;
}
break;
case CISTPL_FUNCE:
funcEType = SdbusReadCIAChar(FdoExtension, cisPtr+2);
if (funcEType == 1) {
UCHAR fInfo, ioRev, csaProp, opMin, opAvg, opMax, sbMin, sbAvg, sbMax;
USHORT blkSize, minBw, optBw;
ULONG cardPsn, csaSize, ocr;
if (link != 0x1C) {
DebugPrint((SDBUS_DEBUG_FAIL, "fdo %08x CISTPL_FUNCE invalid type1 link %x\n",
FdoExtension->DeviceObject, link));
return;
}
fInfo = SdbusReadCIAChar(FdoExtension, cisPtr+3);
ioRev = SdbusReadCIAChar(FdoExtension, cisPtr+4);
cardPsn = SdbusReadCIADword(FdoExtension, cisPtr+5);
csaSize = SdbusReadCIADword(FdoExtension, cisPtr+9);
csaProp = SdbusReadCIAChar(FdoExtension, cisPtr+13);
blkSize = SdbusReadCIAWord(FdoExtension, cisPtr+14);
ocr = SdbusReadCIADword(FdoExtension, cisPtr+16);
opMin = SdbusReadCIAChar(FdoExtension, cisPtr+20);
opAvg = SdbusReadCIAChar(FdoExtension, cisPtr+21);
opMax = SdbusReadCIAChar(FdoExtension, cisPtr+22);
sbMin = SdbusReadCIAChar(FdoExtension, cisPtr+23);
sbAvg = SdbusReadCIAChar(FdoExtension, cisPtr+24);
sbMax = SdbusReadCIAChar(FdoExtension, cisPtr+25);
minBw = SdbusReadCIAWord(FdoExtension, cisPtr+26);
optBw = SdbusReadCIAWord(FdoExtension, cisPtr+28);
DebugPrint((SDBUS_DEBUG_ENUM, "fdo %08x CISTPL_FUNCE 1\n",
FdoExtension->DeviceObject));
} else {
DebugPrint((SDBUS_DEBUG_FAIL, "fdo %08x CISTPL_FUNCE invalid funce type %x\n",
FdoExtension->DeviceObject, funcEType));
return;
}
break;
}
cisPtr += link+2;
cmd = SdbusReadCIAChar(FdoExtension, cisPtr);
link = SdbusReadCIAChar(FdoExtension, cisPtr+1);
}
DebugPrint((SDBUS_DEBUG_ENUM, "fdo %08x CIS %.06x cmd=%.02x link=%.02x EXITING %d tuples read\n",
FdoExtension->DeviceObject, cisPtr, cmd, link, tupleCount));
}