📄 common.cpp
字号:
pCfTable->ReadyActive = *pCIS & 0x40;
pCfTable->WaitRequired = *pCIS & 0x80;
} else {
//pCfTable->IFacePresent = FALSE;
}
pCIS++;
if (dwLen--==0) goto pcft_continue;
//
// Parse the feature select byte
//
//
// Power requirements present
//
bmPowerPresent = *pCIS & 0x03;
//
// Timing description present
//
TimingPresent = *pCIS & 0x04;
//
// I/O space descriptions present
//
IOPresent = *pCIS & 0x08;
//
// Irq description present
//
IrqPresent = *pCIS & 0x10;
//
// Memory description present
//
MemPresent = *pCIS & 0x60;
pCIS++;
if (dwLen--==0) goto pcft_continue;
//
// Parse the power description structures if present
//
DWORD dwParsedLength;
if (bmPowerPresent >= 1) {
pCfTable->VccDescr.ValidMask = 0xFF;
pCIS +=(dwParsedLength=ParseVoltageDescr(pCIS, &pCfTable->VccDescr));
if (dwParsedLength >dwLen) goto pcft_continue;
dwLen -=dwParsedLength;
for (i = 0; i < 3; i++) {
if ((PWR_DESCR_NOMINALV << i) & pCfTable->VccDescr.ValidMask )
pCfTable->VccDescr.ValidMask |= (PWR_AVAIL_NOMINALV << i);
}
}
if (bmPowerPresent >= 2) {
pCfTable->Vpp1Descr.ValidMask = 0xFF;
pCIS += (dwParsedLength=ParseVoltageDescr(pCIS, &pCfTable->Vpp1Descr));
if (dwParsedLength >dwLen) goto pcft_continue;
dwLen -=dwParsedLength;
for (i = 0; i < 3; i++) {
if ((PWR_DESCR_NOMINALV << i) & pCfTable->Vpp1Descr.ValidMask )
pCfTable->Vpp1Descr.ValidMask |= (PWR_AVAIL_NOMINALV << i);
}
pCfTable->Vpp2Descr.ValidMask = 0xFF;
if (bmPowerPresent == 3) {
pCIS += (dwParsedLength=ParseVoltageDescr(pCIS, &pCfTable->Vpp2Descr));
if (dwParsedLength >dwLen) goto pcft_continue;
dwLen -=dwParsedLength;
for (i = 0; i < 3; i++) {
if ((PWR_DESCR_NOMINALV << i) & pCfTable->Vpp1Descr.ValidMask )
pCfTable->Vpp2Descr.ValidMask |= (PWR_AVAIL_NOMINALV << i);
}
} else
pCfTable->Vpp2Descr = pCfTable->Vpp1Descr;
}
//
// Skip the timing information
//
if ( TimingPresent ) {
pTmp = pCIS;
pCIS++;
if (dwLen--==0) goto pcft_continue;
if ( (*pTmp & 0x03) != 0x03 ) {
while ( *pCIS++ & TPCE_PD_EXT ){
if (dwLen--==0) goto pcft_continue;
}
}
if ( (*pTmp & 0x1C) != 0x1C ) {
while ( *pCIS++ & TPCE_PD_EXT ){
if (dwLen--==0) goto pcft_continue;
}
}
}
//
// Process the I/O address ranges (up to MAX_IO_RANGES)
//
if (IOPresent) {
pCfTable->NumIOAddrLines = *pCIS & 0x1F;
pCfTable->IOAccess = (*pCIS & 0x60) >> 5; // type of access allowed
if (*pCIS & 0x80) { // range present bit
UINT8 AddrSize, LengthSize;
pCIS++;
if (dwLen--==0) goto pcft_continue;
pCfTable->NumIOEntries = (*pCIS & 0x0F) + 1;
if (pCfTable->NumIOEntries > MAX_IO_RANGES) {
DEBUGMSG(ZONE_WARNING,
(TEXT("PCMCIA ParseCfTable: too many I/O ranges; ignoring some.\n")));
pCfTable->NumIOEntries = MAX_IO_RANGES;
}
AddrSize = (*pCIS & 0x30) >> 4;
if (AddrSize == 3) {
AddrSize = 4;
}
LengthSize = (*pCIS & 0xC0) >> 6;
if (LengthSize == 3) {
LengthSize = 4;
}
pCIS++;
if (dwLen--==0) goto pcft_continue;
for (i = 0; i < pCfTable->NumIOEntries; i++) {
pCfTable->IOBase[i] = VarToFixed(AddrSize, pCIS);
pCIS += AddrSize;
if((dwLen - AddrSize) <= 0) goto pcft_continue;
pCfTable->IOLength[i] = VarToFixed(LengthSize, pCIS);
pCIS += LengthSize;
if((dwLen - AddrSize) <= 0) goto pcft_continue;
}
} else {
// NumIOEntries is a misnomer; it's really the number of IO ranges.
pCfTable->NumIOEntries = 0;
}
}
// Irq description present
//
if ( IrqPresent) {
if ((*pCIS & 0x10)==0) { // Mask Bit is set
pCfTable->wIrqMask =(1<< (*pCIS & 0xf));
pCIS++;
if (dwLen--==0) goto pcft_continue;
}
else {
if (dwLen <3) goto pcft_continue;
pCIS++;
pCfTable->wIrqMask=*pCIS+(((WORD)*(pCIS+1))<<8);
pCIS+=2;
dwLen -= 3;
}
}
if (MemPresent) {
if (MemPresent == 0x20) {//Signle 2 byte length present
if (dwLen<2) goto pcft_continue;
UINT32 uSize = *pCIS + (*(pCIS+1)<<8);
ASSERT(uSize!=0);
pCIS += 2;
pCfTable->NumMemEntries= 1;
pCfTable->MemBase[0] = 0;
pCfTable->MemLength[0] = uSize*0x100;
dwLen -=2;
}
else
if (MemPresent == 0x40) {//Signle 2 byte length & base present
if (dwLen<4) goto pcft_continue;
UINT32 uSize = *pCIS + (*(pCIS+1)<<8);
ASSERT(uSize!=0);
pCIS +=2;
UINT32 uBase =*pCIS + (*(pCIS+1)<<8);
pCIS +=2;
pCfTable->NumMemEntries = 1;
pCfTable->MemLength[0] = uSize*0x100;
pCfTable->MemBase[0] = uBase*0x100;
}
else { // Memory Descriptor structure present.
UINT8 AddrSize, LengthSize,bHostAddress, NumOfEntries;
pCfTable->NumMemEntries = NumOfEntries= (*pCIS & 0x07) + 1;
LengthSize = ((*pCIS & 0x18)>>3);
AddrSize = ((*pCIS & 0x60)>> 5);
bHostAddress = (*pCIS & 0x80);
if (pCfTable->NumMemEntries > MAX_WINDOWS_RANGES) {
DEBUGMSG(ZONE_WARNING, (TEXT("PCMCIA ParseCfTable: too many I/O ranges; ignoring some.\n")));
pCfTable->NumMemEntries = MAX_IO_RANGES;
}
pCIS++;
if (dwLen--==0) goto pcft_continue;
for (i =0 ; i< NumOfEntries; i ++) {
UINT32 uSize = 0;
UINT32 uBase = 0;
UINT32 uShift = 0;
for (int NumOfBytes =0; NumOfBytes < LengthSize; NumOfBytes++) {
uSize += ((*pCIS)<<uShift);
pCIS++;
uShift +=8;
if (dwLen--==0) goto pcft_continue;
}
for (NumOfBytes =0; NumOfBytes < AddrSize; NumOfBytes++) {
uBase += ((*pCIS)<<uShift);
pCIS++;
uShift +=8;
if (dwLen--==0) goto pcft_continue;
}
// We ignore host address. but we have to parsed it.
for (NumOfBytes =0; NumOfBytes < AddrSize && bHostAddress!=0; NumOfBytes++) {
pCIS++;
if (dwLen--==0) goto pcft_continue;
}
ASSERT(uSize!=0 );
if (i < MAX_WINDOWS_RANGES) {
pCfTable->MemBase[i] = uBase*0x100;
pCfTable->MemLength[i] = uSize*0x100;
}
}
}
}
// else it has already been either defaulted or memset to zeros.
pcft_continue:
pCfTable++;
pcft_next:
if ((pBuf != NULL) && (nItems == *pnItems)) {
status = CERR_NO_MORE_ITEMS; // no more room in caller's buffer
} else {
//
// Get the next CISTPL_CFTABLE_ENTRY
//
status = CardGetNextTuple(pTuple);
}
} // while (status == CERR_SUCCESS)
pcft_exit:
*pnItems = nItems;
//
// If there were problems and no CFTABLE_ENTRYs found then return an error.
//
if (nItems) {
return CERR_SUCCESS;
}
return status;
}
USHORT VoltageConversionTable[16] = {
10, 12, 13, 15, 20, 25, 30, 35,
40, 45, 50, 55, 60, 70, 80, 90
};
//
// ConvertVoltage - normalize a single CISTPL_CFTABLE_ENTRY voltage entry and
// return its length in bytes
//
UINT ConvertVoltage(PUCHAR pCIS, PUSHORT pDescr)
{
if(pCIS == NULL || pDescr == NULL)
return 0;
UINT Length;
SHORT power;
USHORT value;
UCHAR MantissaExponentByte;
UCHAR ExtensionByte;
Length = 1;
power = 1;
MantissaExponentByte = pCIS[0];
ExtensionByte = pCIS[1];
value = VoltageConversionTable[(MantissaExponentByte >> 3) & 0x0f];
if ((MantissaExponentByte & TPCE_PD_EXT) &&
(ExtensionByte < 100)) {
value = (100 * value + (ExtensionByte & 0x7f));
power += 2;
}
power = (MantissaExponentByte & 0x07) - 4 - power;
while (power > 0) {
value *= 10;
power--;
}
while (power < 0) {
value /= 10;
power++;
}
*pDescr = value;
//
// Skip any subsequent extension bytes for now.
//
while (*pCIS & TPCE_PD_EXT) {
Length++;
pCIS++;
}
return Length;
} // ConvertVoltage
//
// ParseVoltageDescr - convert the variable length power description structure
// from a CISTPL_CFTABLE_ENTRY to a POWER_DESCR structure
// and normalize the values.
// Returns the length of the variable length power description structure.
//
// A typical call would be:
// if (pCfTable->VccDescr.ValidMask) {
// pCIS += ParseVoltageDescr(pCIS, &pCfTable->VccDescr);
// }
//
UINT ParseVoltageDescr(PUCHAR pVolt, PPOWER_DESCR pDescr)
{
if(pVolt == NULL || pDescr == NULL)
return 0;
UINT Length;
UINT Mask;
UINT i;
PUSHORT pDVolt;
Length = 1;
Mask = pDescr->ValidMask = (UINT)*pVolt;
pVolt++;
pDVolt = &(pDescr->NominalV);
while (Mask) {
if (Mask & 1) {
i = ConvertVoltage(pVolt, pDVolt);
Length += i;
pVolt += i;
} else {
*pDVolt = 0;
}
pDVolt++;
Mask >>= 1;
}
return Length;
} // ParseVoltageDescr
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -