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

📄 tuple.c

📁 YLP270的Windows CE5.0 bsp源码。
💻 C
📖 第 1 页 / 共 3 页
字号:
//
// Copyright (c) Microsoft Corporation.  All rights reserved.
//
//
// Use of this source code is subject to the terms of the Microsoft end-user
// license agreement (EULA) under which you licensed this SOFTWARE PRODUCT.
// If you did not accept the terms of the EULA, you are not authorized to use
// this source code. For a copy of the EULA, please see the LICENSE.RTF on your
// install media.
//
/*++
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:

    tuple.c

Abstract:

    This file implements the PCMCIA model device driver CIS tuple parsing
    functions.  This is provided as a sample to platform writers and is
    expected to be able to be used without modification on most (if not
    all) hardware platforms.

Functions:

    CheckTupleOffset
    I_ReadAttrByte()
    I_ReadAttrWord()
    I_TupleMapWindow()
    I_TupleGetWindow()
    I_ReadLink()
    I_CheckNextTuple()
    I_CheckNextLink()
    I_GetNextTuple()
    I_GetDesiredTuple()
    CardGetNextTuple()
    CardGetFirstTuple()
    CardGetTupleData()
    VarToFixed()
    ParseConfig()
    ConvertVoltage()
    ParseVoltageDescr()
    ParseCfTable()
    CardGetParsedTuple()

Notes:


--*/


#include <windows.h>
#include <types.h>
#include <cardserv.h>
#include <sockserv.h>
#include <pcmcia.h>
#include <tuple.h>
#include <extern.h>

#define MAX_TUPLE_MISSES 500
#define LINK_TARGET_SIG ('C'+('I'<<8)+('S'<<16))
#define TUPLE_WINDOW_SIZE   8192
//#define TUPLE_WINDOW_SIZE   16384
#define TUPLE_OFFSET_LIMIT  65536

//
// Check if the tuple offset fits in the current window and try to remap
// the window if it doesn't.
//
STATUS
CheckTupleOffset(
    UINT Address,
    PCARD_TUPLE_PARMS pParms
    )
{
    PLOG_WINDOW  pWin;
    PPHYS_WINDOW pPhys;
    PDCARD_WINDOW_STATE WinState;
    STATUS status;
    UINT CardOffset;
    UINT8 attr;

    if (pParms->fFlags & TUPLE_FLAG_COMMON) {
        pWin = v_Sockets[pParms->hSocket.uSocket].pCmnWin;
        CardOffset = Address;
        attr = 0;
    } else {
        pWin = v_Sockets[pParms->hSocket.uSocket].pAttrWin;
        CardOffset = Address*2;
        attr = WIN_STATE_ATTRIBUTE;
    }
    pPhys = pWin->pPhys;

    //
    // If we can't change the window offset, then just do a static check
    //
    if (!(pPhys->fOtherCaps & MEM_CAP_PRG_BASE)) {
        if (CardOffset >= TUPLE_WINDOW_SIZE) {
            return CERR_READ_FAILURE;
        }
        return CERR_SUCCESS;
    }

    if ((CardOffset < (pWin->uReqOffset + pWin->uReqSize)) &&
        (CardOffset >= pWin->uReqOffset)) {
        return CERR_SUCCESS;
    }

    if (CardOffset > TUPLE_OFFSET_LIMIT) {
        return CERR_READ_FAILURE;
    }

DEBUGMSG(ZONE_PDD,
    (TEXT("CheckTupleOffset remapping for CardOffset = 0x%x\r\n"),
    CardOffset));

    //
    // We need to remap!
    //
    status = PDCardGetWindow(pPhys->uWindow, &WinState);
    if (status != CERR_SUCCESS) {
        return CERR_READ_FAILURE;
    }

    pWin->uReqOffset = CardOffset & ~(TUPLE_WINDOW_SIZE - 1);
    pPhys->uOffset = WinState.uOffset = pWin->uReqOffset;
    pPhys->uSize = WinState.uSize = TUPLE_WINDOW_SIZE;
    WinState.fState &= ~WIN_STATE_ATTRIBUTE;
    WinState.fState |= attr;
    if (attr) {
        pPhys->fFlags |= PHYS_WIN_FLAG_ATTR_MODE;
    } else {
        pPhys->fFlags &= ~PHYS_WIN_FLAG_ATTR_MODE;
    }
    status = PDCardSetWindow(pPhys->uWindow, &WinState);
    if (status != CERR_SUCCESS) {
        return CERR_READ_FAILURE;
    }
    return CERR_SUCCESS;
}


//
// Read next byte from CIS (may be either in common or attribute space).
//
STATUS
I_ReadAttrByte(
    PCHAR * pAttr,
    PCARD_TUPLE_PARMS pParms,
    UINT32 uOffset,
    UINT8 * pByte
    )
{
    PLOG_WINDOW  pWin;
    STATUS status;
    UINT Address = pParms->uCISOffset+uOffset;

    status = CheckTupleOffset(Address, pParms);
    if (status != CERR_SUCCESS) {
        DEBUGMSG(ZONE_TUPLE|ZONE_WARNING,(
            TEXT("I_ReadAttrByte returning %d (offset = %d)\r\n"),
            status, Address));
        return status;
    }

    if (pParms->fFlags & TUPLE_FLAG_COMMON) {
        pWin = v_Sockets[pParms->hSocket.uSocket].pCmnWin;
        return CardReadCmnByte(*pAttr, Address - pWin->uReqOffset, pByte);
    } else {
        pWin = v_Sockets[pParms->hSocket.uSocket].pAttrWin;
        return CardReadAttrByte(*pAttr, Address - pWin->uReqOffset/2, pByte);
    }
}   // I_ReadAttrByte


//
// Read a 4 byte chunk of the CIS as a little endian word.
//
STATUS
I_ReadAttrWord(
    PCHAR *pAttr,
    PCARD_TUPLE_PARMS pParms,
    UINT32 uOffset,
    UINT * pWord
    )
{
    PLOG_WINDOW  pWin;
    UINT uTmp = 0;
    UINT i = pParms->uCISOffset+uOffset+3;    // start with high order byte
    UINT j = 4;
    STATUS status;
    UINT8 uByte;

    status = CheckTupleOffset(i, pParms);
    if (status != CERR_SUCCESS) {
        DEBUGMSG(ZONE_TUPLE|ZONE_WARNING,(
            TEXT("I_ReadAttrWord returning %d (offset = %d)\r\n"), status, i));
        return status;
    }
    if (pParms->fFlags & TUPLE_FLAG_COMMON) {
        pWin = v_Sockets[pParms->hSocket.uSocket].pCmnWin;
        i -= pWin->uReqOffset;
    } else {
        pWin = v_Sockets[pParms->hSocket.uSocket].pAttrWin;
        i -= pWin->uReqOffset/2;
    }

    while (j) {
        uTmp <<= 8;
        if (pParms->fFlags & TUPLE_FLAG_COMMON) {
            status = CardReadCmnByte(*pAttr, i, &uByte);
        } else {
            status = CardReadAttrByte(*pAttr, i, &uByte);
        }
        if (status) {
            return status;
        }
        uTmp += (UINT)uByte;

        j--;
        i--;
    }
    *pWord = uTmp;

    return CERR_SUCCESS;
}   // I_ReadAttrWord


//
// I_TupleMapWindow maps a logical window associated with a socket to a
// virtual memory region.
//
PVOID
I_TupleMapWindow(
    PPHYS_WINDOW pPhys,
    PCARD_TUPLE_PARMS pParms
    )
{
    PDCARD_WINDOW_STATE WinState;
    PLOG_WINDOW pWin;
    STATUS status;
    UINT addr = 0;      // Beginning of attribute space.

    //
    // If we can't change the window offset, then just do a static check
    //
    if (pPhys->fOtherCaps & MEM_CAP_PRG_BASE) {
        DEBUGMSG(ZONE_PDD, (TEXT("I_TupleMapWindow remapping for CardOffset = 0x0\r\n")));

        //
        // We need to remap!
        //
        status = PDCardGetWindow(pPhys->uWindow, &WinState);
        if (status != CERR_SUCCESS) {
            return NULL;
        }

        //
        // We'll set the attribute bit later on if necessary
        //
        pPhys->uOffset = WinState.uOffset = 0;
        pPhys->uSize = WinState.uSize = TUPLE_WINDOW_SIZE;
        status = PDCardSetWindow(pPhys->uWindow, &WinState);
        if (status != CERR_SUCCESS) {
            return NULL;
        }
    }

    pWin = I_MapWindow(
                pPhys,
                &addr,
                (TUPLE_WINDOW_SIZE > pPhys->uMaxSize) ?
                    pPhys->uMaxSize : TUPLE_WINDOW_SIZE,
                (pParms->fFlags & TUPLE_FLAG_COMMON) ? FALSE : TRUE
                );
    if (pWin == NULL) {
        return NULL;
    }

    PDCardGetWindow(pPhys->uWindow, &WinState);
    if (pParms->fFlags & TUPLE_FLAG_COMMON) {
        v_Sockets[pPhys->uSock].pCmnWin = pWin;
        WinState.fState &= ~WIN_STATE_ATTRIBUTE;
        pPhys->fFlags &= ~PHYS_WIN_FLAG_ATTR_MODE;
    } else {
        v_Sockets[pPhys->uSock].pAttrWin = pWin;
        WinState.fState |= WIN_STATE_ATTRIBUTE;
        pPhys->fFlags |= PHYS_WIN_FLAG_ATTR_MODE;
    }
    PDCardSetWindow(pPhys->uWindow, &WinState);

    return pWin->pVirtMem;
}   // I_TupleMapWindow


//
// I_TupleGetWindow is called by CardGetFirstTuple to allocate a virtual memory
// window to access the specified socket.  If there is already a window, then
// that will be returned.
//
// hSock is the socket to access
// fFlag specifies whether the CIS is in attribute or common memory.
//
PVOID
I_TupleGetWindow(
    PCARD_TUPLE_PARMS pParms
    )
{
    PPHYS_WINDOW pPhys;
    PLOG_WINDOW  pWin;

    if (pParms->fFlags & TUPLE_FLAG_COMMON) {
        pWin = v_Sockets[pParms->hSocket.uSocket].pCmnWin;
    } else {
        pWin = v_Sockets[pParms->hSocket.uSocket].pAttrWin;
    }

    if (pWin != NULL) {
        if (pWin->pVirtMem == NULL) {
            DEBUGMSG(ZONE_TUPLE|ZONE_WARNING,(
                TEXT("I_TupleGetWindow: Window allocated but not mapped!\r\n")));
        }
        return pWin->pVirtMem;
    }

    //
    // Find a physical memory window associated with this socket.
    //
    EnterCriticalSection(&v_WindowCrit);
    pPhys = v_pWinList;
    while (pPhys) {
        if (pPhys->uSock == pParms->hSocket.uSocket) {
            if ((((pParms->fFlags & TUPLE_FLAG_COMMON) == 0) && (pPhys->fWindowCaps & WIN_CAP_ATTRIBUTE)) ||
                 ((pParms->fFlags & TUPLE_FLAG_COMMON)  && (pPhys->fWindowCaps & WIN_CAP_COMMON))) {
                LeaveCriticalSection(&v_WindowCrit);
                return(I_TupleMapWindow(pPhys, pParms));
            }
        }
        pPhys = pPhys->Next;
    }
    LeaveCriticalSection(&v_WindowCrit);
    return NULL;
}   // I_TupleGetWindow


//
// Remember info from current link tuple.
//
STATUS
I_ReadLink(
    PCHAR * pAttr,
    PCARD_TUPLE_PARMS pParms
    )
{
    STATUS status;
    UINT8 byte;

    switch (pParms->uTupleCode) {
    case CISTPL_LONGLINK_A:
    case CISTPL_LONGLINK_C:
        status = I_ReadAttrWord(pAttr, pParms, 2, &(pParms->uLinkOffset));
        if (status != CERR_SUCCESS) {
            return status;
        }
        pParms->fFlags &= TUPLE_FLAG_COMMON;    // clear all but mem mode.

        if (pParms->uTupleCode == CISTPL_LONGLINK_A) {
            pParms->fFlags |= TUPLE_FLAG_LINK_TO_A;
            pParms->uLinkOffset *= 2;
        } else {
            pParms->fFlags |= TUPLE_FLAG_LINK_TO_C;
        }
        break;

    case CISTPL_LONGLINK_MFC:
        //
        // Make sure the requested function number exists
        //
        status = I_ReadAttrByte(pAttr, pParms, 2, &byte);
        if (status != CERR_SUCCESS) {
            return status;
        }
        if (byte <= pParms->hSocket.uFunction) {
            break;
        }

        //
        // Also verify that the link shows enough room for the requested function
        //
        status = I_ReadAttrByte(pAttr, pParms, 1, &byte);
        if (status != CERR_SUCCESS) {
            return status;
        }
        if (byte < (pParms->hSocket.uFunction * 5) + 1) {
            DEBUGMSG(ZONE_CALLBACK|ZONE_TUPLE,
                (TEXT("I_ReadLink: CISTPL_LONGLINK_MFC length=%d, expecting at least %d\r\n"),
                byte, pParms->hSocket.uFunction * 5 + 1));
            break;
        }

        status = I_ReadAttrWord(pAttr, pParms, (pParms->hSocket.uFunction * 5) + 4, &(pParms->uLinkOffset));
        if (status != CERR_SUCCESS) {
            return status;
        }

        //
        // Check which memory space the link goes to
        //
        status = I_ReadAttrByte(pAttr, pParms, (pParms->hSocket.uFunction * 5) + 3, &byte);
        if (status != CERR_SUCCESS) {
            return status;
        }
        if (byte == 0) {
            pParms->fFlags |= TUPLE_FLAG_LINK_TO_A;
            pParms->uLinkOffset *= 2;
        } else {
            pParms->fFlags |= TUPLE_FLAG_LINK_TO_C;
        }
        break;

    case CISTPL_NO_LINK:
        //
        // CISTPL_NO_LINK means that all long links in this chain
        // should be ignored.
        //
        pParms->fFlags &= TUPLE_FLAG_COMMON;    // clear all but mem mode.
        pParms->fFlags |= TUPLE_FLAG_NO_LINK;
        break;
    }
    return CERR_SUCCESS;
}   // I_ReadLink



//
// Examine the next tuple in the chain
//
STATUS
I_CheckNextTuple(
    PCHAR * pAttr,
    PCARD_TUPLE_PARMS pParms
    )
{
    UINT8 tuple;
    STATUS status;

    status = I_ReadAttrByte(pAttr, pParms, 0, &tuple);
    if (status != CERR_SUCCESS) {
        return status;
    }

    if (tuple == CISTPL_END) {
        return CERR_NO_MORE_ITEMS;
    }

    //
    // CISTPL_NULL is a one byte tuple with no info so it is skipped.
    //
    if (tuple == CISTPL_NULL) {
        pParms->uCISOffset += 1;          // skip to next tuple
    } else {
        status = I_ReadAttrByte(pAttr, pParms, 1, &tuple);
        if (status != CERR_SUCCESS) {
            return status;
        }
        if (tuple == CISTPL_END) {
            DEBUGMSG(ZONE_TUPLE, (TEXT("I_CheckNextTuple: TupleLink == CISTPL_END, assuming end\r\n")));
            return CERR_NO_MORE_ITEMS;
        }
        pParms->uCISOffset += tuple+2;    // skip to next tuple
    }
    return CERR_SUCCESS;
}   // I_CheckNextTuple


//
// Check and follow the link at the current CIS offset
//
// pAttr may get changed to a pointer to common memory if the CIS is in common
// memory.
//
STATUS
I_CheckNextLink(
    PCHAR * pAttr,
    PCARD_TUPLE_PARMS pParms
    )
{
    UINT uSig;    // link target signature.
    UINT8 tuple;
    STATUS status;

    if (pParms->fFlags & TUPLE_FLAG_LINK_TO_C) {
        //
        // Process a link to common memory.
        //
        pParms->fFlags |= TUPLE_FLAG_COMMON;
        DEBUGMSG(ZONE_TUPLE,
            (TEXT("I_CheckNextLink: processing CISTPL_LONGLINK_TO_C\r\n")));
    } else if (pParms->fFlags & TUPLE_FLAG_LINK_TO_A) {
        //
        // Process a link to attribute memory.
        //
        pParms->fFlags &= ~TUPLE_FLAG_COMMON;

⌨️ 快捷键说明

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