⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 tuple.c

📁 YLP270的Windows CE5.0 bsp源码。
💻 C
📖 第 1 页 / 共 3 页
字号:
    pTuple->fAttributes = 0;         // Not interested in links
    status = CardGetFirstTuple(pTuple);
    if (status) {
        DEBUGMSG(ZONE_TUPLE|ZONE_WARNING,
        (TEXT("ParseConfig: CardGetFirstTuple returned %d\r\n"), status));
        *pnItems = 0;
        return status;
    }

    status = CardGetNextTuple(pTuple);
    if (status) {
        status = CardGetFirstTuple(pTuple);
        if (status) {
            DEBUGMSG(ZONE_TUPLE|ZONE_WARNING,
            (TEXT("ParseConfig: CardGetFirstTuple returned %d\r\n"), status));
            *pnItems = 0;
            return status;
        }
    }

    pData = (PCARD_DATA_PARMS)buf;
    pData->uBufLen = BUFFER_SIZE;
    pData->uTupleOffset = 0;
    status = CardGetTupleData(pData);
    if (status) {
        DEBUGMSG(ZONE_TUPLE|ZONE_WARNING,
        (TEXT("ParseConfig: CardGetTupleData returned %d\r\n"), status));
        *pnItems = 0;
        return status;
    }

    if (pBuf == NULL) {
        *pnItems = 1;
        return CERR_SUCCESS;
    }

    if (*pnItems == 0) {
        return CERR_BAD_ARG_LENGTH;
    }

    *pnItems = 1;
    pCfg->ConfigBase = 0;
    pCfg->RegMask = 0;

    pCIS = buf + sizeof(CARD_DATA_PARMS);
    AddrSz = (*pCIS & 0x03) + 1;
    pCIS++;
    pCfg->LastConfigIndex = *pCIS & 0x3f;
    pCIS++;

    //
    // Read the configuration register offset address and leave it in real
    // physical address units.
    //
    pCfg->ConfigBase = VarToFixed(
                            AddrSz,
                            pCIS);          // pointer

    //
    // Now get the register presence mask (only the first byte)
    //
    pCfg->RegMask = pCIS[AddrSz];

    DEBUGMSG(ZONE_TUPLE,
        (TEXT("ParseConfig: Last configuration index = 0x%x\r\n"), pCfg->LastConfigIndex));
    DEBUGMSG(ZONE_TUPLE,
        (TEXT("ParseConfig: Config registers base = 0x%x\r\n"), pCfg->ConfigBase));
    DEBUGMSG(ZONE_TUPLE,
        (TEXT("ParseConfig: Register presence mask = 0x%x\r\n"), pCfg->RegMask));

    return CERR_SUCCESS;
}   // ParseConfig

BOOL
ValidPowerEntry(
    UINT fSupply,
    UINT16 uVoltage
    )
{
    UINT8 i;
    PPDCARD_POWER_ENTRY pPwr = (PPDCARD_POWER_ENTRY)(((PCHAR)v_pAdapterInfo) +
                                sizeof(PDCARD_ADAPTER_INFO));
    for (i = 0; i < v_pAdapterInfo->uPowerEntries; i++, pPwr++) {
        if (((pPwr->uPowerLevel * 9 / 10) <= uVoltage) &&
            (pPwr->uPowerLevel >= uVoltage) &&
            (pPwr->fSupply & fSupply)) {
            return TRUE;
        }
    }

    return FALSE;
}

const 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
    )
{
    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
    )
{
    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

//
// ParseCfTable - Read the CISTPL_CFTABLE_ENTRY tuples from the CIS and format them into
// an array of PARSED_CFTABLE structures.
//
STATUS
ParseCfTable(
    CARD_SOCKET_HANDLE hSocket,
    PVOID   pBuf,
    PUINT   pnItems
    )
{
    STATUS status;
    UCHAR buf[BUFFER_SIZE + sizeof(CARD_DATA_PARMS)];
    PCARD_DATA_PARMS pData;
    PCARD_TUPLE_PARMS pTuple;
    PUCHAR  pCIS;
    PUCHAR  pTmp;
    PPARSED_CFTABLE pCfTable = (PPARSED_CFTABLE)pBuf;
    PPARSED_CFTABLE pCfDefault = NULL;
    BOOL    TimingPresent;  // This tuple contains a description of the card's timing
    BOOL    IOPresent;      // This tuple contains I/O descriptor bytes
    DWORD   bmPowerPresent; // This tuple has some power descriptors
    int     lastCFI = -1;   // Configuration Index of the previous CFTABLE_ENTRY tuple
    UINT    i;
    UINT    nItems;
    
    nItems = 0;

    //
    // Find the first CISTPL_CFTABLE_ENTRY tuple
    //
    pTuple = (PCARD_TUPLE_PARMS)buf;
    pTuple->hSocket = hSocket;
    pTuple->uDesiredTuple = CISTPL_CFTABLE_ENTRY;
    pTuple->fAttributes = 0;         // Not interested in links
    status = CardGetFirstTuple(pTuple);
    if (status) {
        DEBUGMSG(ZONE_TUPLE|ZONE_WARNING,
            (TEXT("ParseCfTable: CardGetFirstTuple returned %d\r\n"), status));
        goto pcft_exit;
    }

    if (pBuf != NULL) {
        if (*pnItems == 0) {
            status = CERR_BAD_ARG_LENGTH;
        } else {
            memset(pBuf, 0, *pnItems * sizeof(PARSED_CFTABLE));
        }
    }

    //
    // Parse all the CISTPL_CFTABLE_ENTRYs or as many as fit in the user's buffer
    //
    while (status == CERR_SUCCESS) {
        nItems++;
        if (pBuf == NULL) {
            goto pcft_next;
        }

        pData = (PCARD_DATA_PARMS)buf;
        pData->uBufLen = BUFFER_SIZE;
        pData->uTupleOffset = 0;
        status = CardGetTupleData(pData);
        if (status) {
            DEBUGMSG(ZONE_TUPLE|ZONE_WARNING,
            (TEXT("ParseCfTable: CardGetTupleData returned %d\r\n"), status));
            goto pcft_exit;
        }

        //
        // Parse this CISTPL_CFTABLE_ENTRY
        //
        pCIS = buf + sizeof(CARD_DATA_PARMS);

        // Default all the fields of the current parsed entry if necessary
        //
        // !! The ContainsDefaults field is now deprecated and should be
        // !! set to non-zero in every parsed entry.
        //
        pCfTable->ContainsDefaults = *pCIS & 0x40;
        pCfTable->ConfigIndex = *pCIS & 0x3F;
        if (pCfTable->ContainsDefaults)
            pCfDefault = pCfTable;
        else if (pCfTable->ConfigIndex == lastCFI) {
            ASSERT(pCfTable != pBuf && lastCFI >= 0);
            *pCfTable = *(pCfTable - 1);
            pCfTable->ContainsDefaults = TRUE;
        } else if (pCfDefault)
            *pCfTable = *pCfDefault;

        // Reset the ConfigIndex after defaulting
        pCfTable->ConfigIndex = *pCIS & 0x3F;
        lastCFI = pCfTable->ConfigIndex;
        // lastCFI is not used beyond this point

        //
        // Parse the interface type byte if present
        //
        if (*pCIS & 0x80) {
            pCIS++;
            pCfTable->IFacePresent = TRUE;
            pCfTable->IFaceType     = *pCIS & 0x0F;
            pCfTable->BVDActive     = *pCIS & 0x10;
            pCfTable->WPActive      = *pCIS & 0x20;
            pCfTable->ReadyActive   = *pCIS & 0x40;
            pCfTable->WaitRequired  = *pCIS & 0x80;
        } else {
            //pCfTable->IFacePresent = FALSE;
        }
        pCIS++;

        //
        // 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;

        pCIS++;

        //
        // Parse the power description structures if present
        //
        if (bmPowerPresent >= 1) {
            pCfTable->VccDescr.ValidMask = 0xFF;
            pCIS += ParseVoltageDescr(pCIS, &pCfTable->VccDescr);
            for (i = 0; i < 3; i++) {
                if ((PWR_DESCR_NOMINALV << i) & pCfTable->VccDescr.ValidMask &&
                    ValidPowerEntry(PWR_SUPPLY_VCC, (&pCfTable->VccDescr.NominalV)[i]))
                    pCfTable->VccDescr.ValidMask |= (PWR_AVAIL_NOMINALV << i);
            }
        }
        if (bmPowerPresent >= 2) {
            pCfTable->Vpp1Descr.ValidMask = 0xFF;
            pCIS += ParseVoltageDescr(pCIS, &pCfTable->Vpp1Descr);
            for (i = 0; i < 3; i++) {
                if ((PWR_DESCR_NOMINALV << i) & pCfTable->Vpp1Descr.ValidMask &&
                    ValidPowerEntry(PWR_SUPPLY_VPP1, (&pCfTable->Vpp1Descr.NominalV)[i]))
                    pCfTable->Vpp1Descr.ValidMask |= (PWR_AVAIL_NOMINALV << i);
            }

            pCfTable->Vpp2Descr.ValidMask = 0xFF;
            if (bmPowerPresent == 3) {
                pCIS += ParseVoltageDescr(pCIS, &pCfTable->Vpp2Descr);
                for (i = 0; i < 3; i++) {
                    if ((PWR_DESCR_NOMINALV << i) & pCfTable->Vpp1Descr.ValidMask &&
                        ValidPowerEntry(PWR_SUPPLY_VPP2, (&pCfTable->Vpp1Descr.NominalV)[i]))
                        pCfTable->Vpp2Descr.ValidMask |= (PWR_AVAIL_NOMINALV << i);
                }
            } else
                pCfTable->Vpp2Descr = pCfTable->Vpp1Descr;
        }


        //
        // Skip the timing information
        //
        if ( TimingPresent ) {
            pTmp = pCIS;

            pCIS++;
            if ( (*pTmp & 0x03) != 0x03 ) {
                while ( *pCIS++ & TPCE_PD_EXT ) ;
            }
            if ( (*pTmp & 0x1C) != 0x1C ) {
                while ( *pCIS++ & TPCE_PD_EXT );
            }
        }


        //
        // 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++;
                pCfTable->NumIOEntries = (*pCIS & 0x0F) + 1;
                if (pCfTable->NumIOEntries > MAX_IO_RANGES) {
                    DEBUGMSG(ZONE_TUPLE|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++;

                for (i = 0; i < pCfTable->NumIOEntries; i++) {
                    pCfTable->IOBase[i] = VarToFixed(AddrSize, pCIS);
                    pCIS += AddrSize;
                    pCfTable->IOLength[i] = VarToFixed(LengthSize, pCIS);
                    pCIS += LengthSize;
                }
            } else {
                // NumIOEntries is a misnomer; it's really the number of IO ranges.
                pCfTable->NumIOEntries = 0;
            }
        }
        // else it has already been either defaulted or memset to zeros.

        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;

}   // ParseCfTable


//
// CardGetParsedTuple
//
// @func    STATUS | CardGetParsedTuple | Reads and parses the specified tuple.
// @rdesc   Returns one of CERR_SUCCESS, CERR_BAD_ARGS, CERR_BAD_SOCKET, CERR_READ_FAILURE,
//          CERR_OUT_OF_RESOURCE, CERR_NO_MORE_ITEMS or CERR_BAD_ARG_LENGTH.
//
// @comm    Reads the CIS data from the specified PC card of the specified tuple code and
//          formats the encoded data into an easily accessed structure.  CISTPL_CONFIG and
//          CISTPL_CFTABLE_ENTRY are currently the only tuples parsed.  When CardGetParsedTuple
//          is called with CISTPL_CONFIG, it returns a PARSED_CONFIG structure.  When it
//          is called with CISTPLE_CFTABLE_ENTRY, it returns a PARSED_CFTABLE structure.
//          On input, the value pointed to by pnItems is the number of items the buffer, pBuf
//          can contain.  On output, pnItems indicates the number items in pBuf.
//          If pBuf is NULL, then pnItems indicates how many of the requested tuples there are.
//
// @xref    <t PARSED_CONFIG> <t PARSED_CFTABLE> <t POWER_DESCR>
//
STATUS
CardGetParsedTuple(
    CARD_SOCKET_HANDLE hSocket, // @parm Socket/function identifier
    UINT8   DesiredTuple,       // @parm Desired tuple to parse (only CISTPL_CONFIG and CISTPL_CFTABLE_ENTRY for now)
    PVOID   pBuf,               // @parm Pointer to buffer to receive parsed data
    PUINT   pnItems             // @parm Pointer to number of items in pBuf.
    )
{
    STATUS status;

    DEBUGMSG(ZONE_FUNCTION|ZONE_TUPLE,
        (TEXT("CardGetParsedTuple entered %d\r\n"), DesiredTuple));

    if (pnItems == NULL) {
        status = CERR_BAD_ARGS;
        goto parsed_exit;
    }

    switch (DesiredTuple) {
    case CISTPL_CONFIG:
        status = ParseConfig(hSocket, pBuf, pnItems);
        break;

    case CISTPL_CFTABLE_ENTRY:
        status = ParseCfTable(hSocket, pBuf, pnItems);
        break;

    default:
        status = CERR_BAD_ARGS;
        break;
    }


parsed_exit:
#ifdef DEBUG
    if (status) {
        DEBUGMSG(ZONE_FUNCTION|ZONE_ERROR|ZONE_TUPLE,
            (TEXT("CardGetParsedTuple failed %d\r\n"), status));
    } else {
        DEBUGMSG(ZONE_FUNCTION|ZONE_TUPLE,
            (TEXT("CardGetParsedTuple succeeded\r\n")));
    }
#endif
    return status;
}   // CardGetParsedTuple

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -