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

📄 supportfunc.c

📁 本压缩包为作者截取的PCI9054的WDM官方驱动源码。欢迎下载。
💻 C
📖 第 1 页 / 共 3 页
字号:
/*******************************************************************************
 * Copyright (c) 2006 PLX Technology, Inc.
 *
 * PLX Technology Inc. licenses this software under specific terms and
 * conditions.  Use of any of the software or derviatives thereof in any
 * product without a PLX Technology chip is strictly prohibited.
 *
 * PLX Technology, Inc. provides this software AS IS, WITHOUT ANY WARRANTY,
 * EXPRESS OR IMPLIED, INCLUDING, WITHOUT LIMITATION, ANY WARRANTY OF
 * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.  PLX makes no guarantee
 * or representations regarding the use of, or the results of the use of,
 * the software and documentation in terms of correctness, accuracy,
 * reliability, currentness, or otherwise; and you rely on the software,
 * documentation and results solely at your own risk.
 *
 * IN NO EVENT SHALL PLX BE LIABLE FOR ANY LOSS OF USE, LOSS OF BUSINESS,
 * LOSS OF PROFITS, INDIRECT, INCIDENTAL, SPECIAL OR CONSEQUENTIAL DAMAGES
 * OF ANY KIND.  IN NO EVENT SHALL PLX'S TOTAL LIABILITY EXCEED THE SUM
 * PAID TO PLX FOR THE PRODUCT LICENSED HEREUNDER.
 *
 ******************************************************************************/

/******************************************************************************
 *
 * File Name:
 *
 *      SupportFunc.c
 *
 * Description:
 *
 *      Additional support functions
 *
 * Revision History:
 *
 *      03-01-06 : PCI SDK v4.40
 *
 ******************************************************************************/


#include "ApiFunctions.h"
#include "CommonApi.h"
#include "GlobalVars.h"
#include "PciSupport.h"
#include "SupportFunc.h"




/*********************************************************************
 *
 * Function   :  PlxSynchronizedRegisterModify
 *
 * Description:  Register modify to be called with KeSynchronizeExecution()
 *
 ********************************************************************/
BOOLEAN
PlxSynchronizedRegisterModify(
    PLX_REG_DATA *pRegData
    )
{
    U32 RegValue;


    RegValue =
        PLX_REG_READ(
            pRegData->pdx,
            pRegData->offset
            );

    RegValue |= pRegData->BitsToSet;
    RegValue &= ~(pRegData->BitsToClear);

    PLX_REG_WRITE(
        pRegData->pdx,
        pRegData->offset,
        RegValue
        );

    return TRUE;
}




/******************************************************************************
 *
 * Function   :  PlxSignalNotifications
 *
 * Description:  Called by the ISR to signal any notification events
 *
 * Note       :  This is expected to be called at DPC level
 *
 ******************************************************************************/
VOID
PlxSignalNotifications(
    DEVICE_EXTENSION *pdx,
    U32               IntSource
    )
{
    PLIST_ENTRY      pEntry;
    PLX_WAIT_OBJECT *pWaitObject;


    KeAcquireSpinLockAtDpcLevel(
        &(pdx->Lock_WaitObjectsList)
        );

    // Get the interrupt wait list
    pEntry = pdx->List_WaitObjects.Flink;

    // Traverse wait objects and wake-up processes
    while (pEntry != &(pdx->List_WaitObjects))
    {
        // Get the wait object
        pWaitObject =
            CONTAINING_RECORD(
                pEntry,
                PLX_WAIT_OBJECT,
                ListEntry
                );

        // Check if waiting for active interrupt
        if (pWaitObject->NotifyOnInterrupt & IntSource)
        {
            DebugPrintf((
                "DPC signaling wait object (%p)\n",
                pWaitObject
                ));

            // Save the new interrupt source in case later requested
            pWaitObject->IntSource |= pWaitObject->NotifyOnInterrupt & IntSource;

            // Signal wait object
            KeSetEvent(
                pWaitObject->pKEvent,
                IO_NO_INCREMENT,
                FALSE
                );
        }

        // Jump to next item in the list
        pEntry = pEntry->Flink;
    }

    KeReleaseSpinLockFromDpcLevel(
        &(pdx->Lock_WaitObjectsList)
        );
}




/*********************************************************************
 *
 * Function   :  PlxRegistryInformationGet
 *
 * Description:  Gets driver configuration information from the registry
 *
 ********************************************************************/
VOID
PlxRegistryInformationGet(
    UNICODE_STRING       *pRegistryPath,
    REGISTRY_INFORMATION *pRegistryInfo
    )
{
    NTSTATUS                  status;
    RTL_QUERY_REGISTRY_TABLE  RegTable[2];
#if defined(PLX_NT_DRIVER)
    U32                      *marker;
    WCHAR                     slBuffer[200];
    UNICODE_STRING            supportedList;
    UNICODE_STRING            fragment;
#endif


    RtlZeroMemory(
        RegTable,
        sizeof(RegTable)
        );

    RegTable[0].Flags = RTL_QUERY_REGISTRY_REQUIRED | RTL_QUERY_REGISTRY_DIRECT;


    // Get Common DMA buffer size
    RegTable[0].Name         = L"CommonBufferSize";
    RegTable[0].EntryContext = &(pRegistryInfo->CommonBufferSize);

    status =
        RtlQueryRegistryValues(
            RTL_REGISTRY_ABSOLUTE,
            pRegistryPath->Buffer,
            RegTable,
            NULL,
            NULL
            );

    if ( !NT_SUCCESS(status) )
    {
        pRegistryInfo->CommonBufferSize = DEFAULT_SIZE_COMMON_BUFFER;
    }

    // Get cacheability of physical memory buffers
    RegTable[0].Name         = L"PhysicalMemoryCacheable";
    RegTable[0].EntryContext = &(pRegistryInfo->PhysicalMemoryCacheable);

    status =
        RtlQueryRegistryValues(
            RTL_REGISTRY_ABSOLUTE,
            pRegistryPath->Buffer,
            RegTable,
            NULL,
            NULL
            );

    if ( !NT_SUCCESS(status) )
    {
        pRegistryInfo->PhysicalMemoryCacheable = DEFAULT_PHYS_MEM_CACHE_ENABLED;
    }
    else
    {
        if (pRegistryInfo->PhysicalMemoryCacheable == 0)
        {
            pRegistryInfo->PhysicalMemoryCacheable = FALSE;
        }
        else
        {
            pRegistryInfo->PhysicalMemoryCacheable = TRUE;
        }
    }


#if defined(PLX_NT_DRIVER)
    // Get list of Valid IDs
    supportedList.MaximumLength = sizeof(slBuffer);
    supportedList.Buffer        = slBuffer;

    RegTable[0].Name          = L"SupportedIDs";
    RegTable[0].EntryContext  = &supportedList;

    status =
        RtlQueryRegistryValues(
            RTL_REGISTRY_ABSOLUTE,
            pRegistryPath->Buffer,
            RegTable,
            NULL,
            NULL
            );

    if ( !NT_SUCCESS(status) )
    {
        DebugPrintf((
            "ERROR - Unable to read %ws registry entry\n",
            RegTable[0].Name
            ));

        pRegistryInfo->ValidIdList[0] = PLX_DEFAULT_DEV_VEN_ID;
        pRegistryInfo->IdListSize     = 1;
    }
    else
    {
        // Now parse the unicode list and place the ID values into the array

        marker                    = pRegistryInfo->ValidIdList;
        pRegistryInfo->IdListSize = 0;
        fragment.Buffer           = supportedList.Buffer;
        fragment.MaximumLength    = sizeof(WCHAR) * 8;
        fragment.Length           = sizeof(WCHAR) * 8;

        while (1)
        {
            RtlUnicodeStringToInteger(
                &fragment,
                0x10,
                marker
                );

            fragment.Buffer += 9; /* must skip to next value +1 for space */
            marker++;
            (pRegistryInfo->IdListSize) += 1;

            if ((U32)fragment.Buffer >= (U32)supportedList.Buffer + (U32)supportedList.Length)
                break;
        }
    }
#endif
}




/******************************************************************************
 *
 * Function   :  GetBarIndex
 *
 * Description:  Associate a h/w resource with a bar number
 *
 ******************************************************************************/
U8
GetBarIndex(
    PHYSICAL_ADDRESS   address,
    PCI_COMMON_CONFIG *pPciRegs
    )
{
    U8  i;
    U32 CompareAddress;


    // Compare the physical address with each BAR
    for (i = 0; i < PCI_NUM_BARS_TYPE_00; i++)
    {
        if (pPciRegs->u.type0.BaseAddresses[i] & 0x1)
            CompareAddress = pPciRegs->u.type0.BaseAddresses[i] & 0xFFFFFFFC;
        else
            CompareAddress = pPciRegs->u.type0.BaseAddresses[i] & 0xFFFFFFF0;

        if (address.u.LowPart == CompareAddress)
            return i;
    }

    // Unable to find the BAR index
    DebugPrintf((
        "ERROR - GetBarIndex() unable to match BAR value (0x%08lx)\n",
        address
        ));

    return (U8)-1;
}




/******************************************************************************
 *
 * Function   :  PlxCompleteIrp
 *
 * Description:  Complete an IRP
 *
 ******************************************************************************/
NTSTATUS
PlxCompleteIrp(
    PIRP     pIrp,
    NTSTATUS status
    )
{
    pIrp->IoStatus.Status = status;

    IoCompleteRequest(
        pIrp,
        IO_NO_INCREMENT
        );

    if (status == STATUS_CANCELLED)
        DebugPrintf(("...Cancelled IRP (0x%p)\n", pIrp));
    else
        DebugPrintf(("...Completed IRP (0x%p)\n", pIrp));

    return status;
}




/******************************************************************************
 *
 * Function   :  PlxCompleteIrpWithInformation
 *
 * Description:  Complete an IRP including modification of the Information field
 *
 ******************************************************************************/
NTSTATUS
PlxCompleteIrpWithInformation(
    PIRP         pIrp,
    NTSTATUS     status,
    PLX_UINT_PTR Info
    )
{
    pIrp->IoStatus.Status      = status;
    pIrp->IoStatus.Information = Info;

    IoCompleteRequest(
        pIrp,
        IO_NO_INCREMENT
        );

    if (status == STATUS_CANCELLED)
        DebugPrintf(("...Cancelled IRP (0x%p)\n", pIrp));
    else
        DebugPrintf(("...Completed IRP (0x%p)\n", pIrp));

    return status;
}




/******************************************************************************
 *
 * Function   :  Plx_sleep
 *
 * Description:  Function as a normal sleep. Parameter is in millisecond
 *
 ******************************************************************************/
VOID
Plx_sleep(
    U32 delay
    )
{
    LARGE_INTEGER liTime;


    /* Convert milliseconds to 100-nanosecond increments using:
     *
     *     1 ns  = 10 ^ -9 sec
     *   100 ns  = 10 ^ -7 sec (1 timer interval)
     *     1 ms  = 10 ^ -3 sec
     *     1 ms  = (1 timer interval) * 10^4
     */
    delay = delay * 10000;

    // Negative value means relative time, not absolute
    liTime =
        RtlConvertLongToLargeInteger(
            -(LONG)delay
            );

    KeDelayExecutionThread(
        KernelMode,
        TRUE,
        &liTime
        );
}




/******************************************************************************
 *
 * Function   :  PlxPciBarResourceMap
 *
 * Description:  Maps a PCI BAR resource into kernel space
 *
 ******************************************************************************/
NTSTATUS
PlxPciBarResourceMap(
    DEVICE_EXTENSION *pdx,
    U8                BarIndex
    )
{
    U32   SizeToMap;
    U32   SizeRemain;
    VOID *pVa;
    PMDL  pMdl;
    PMDL  pMdl_Previous;


    // Map into Kernel Virtual Space
    pdx->PciBar[BarIndex].pVa =
        MmMapIoSpace(
            pdx->PciBar[BarIndex].Physical,
            pdx->PciBar[BarIndex].Size,
            MmNonCached
            );

    if (pdx->PciBar[BarIndex].pVa == NULL)
    {
        return STATUS_INSUFFICIENT_RESOURCES;
    }

    /******************************************************************
     * A future mapping into user space will require an MDL.  Although
     * it is not documented in the Windows DDK, a single MDL is limited
     * to describing just under 64MB.  This is because IoAllocateMdl
     * only allocates 64k for the MDL, which includes space for the
     * physical page addresses that follow the MDL.
     *
     * In that case, we must allocate multiple MDLs and connect them
     * by using the "Next" field of the MDL.
     *****************************************************************/

    // Set initial values
    pVa        = pdx->PciBar[BarIndex].pVa;
    SizeRemain = pdx->PciBar[BarIndex].Size;

    while (SizeRemain != 0)
    {
        // Determine size for MDL
        if (SizeRemain <= MAX_MDL_SIZE)
        {
            SizeToMap = SizeRemain;
        }
        else
        {
            SizeToMap = MAX_MDL_SIZE;
        }

        // Get an MDL for future mapping into user space
        pMdl =

⌨️ 快捷键说明

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