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

📄 commonapi.c

📁 本压缩包为作者截取的PCI9054的WDM官方驱动源码。欢迎下载。
💻 C
📖 第 1 页 / 共 4 页
字号:
            &IrqL_Original
            );

        pEntry = pdx->List_PhysicalMem.Flink;

        bFound = FALSE;

        // Traverse list to find the desired list object
        while (!bFound && (pEntry != &(pdx->List_PhysicalMem)))
        {
            // Get the object
            pMemObject =
                CONTAINING_RECORD(
                    pEntry,
                    PLX_PHYS_MEM_OBJECT,
                    ListEntry
                    );

            // Check if the physical addresses matches
            if (pMemObject->BusPhysical == pPciMem->PhysicalAddr)
            {
                bFound = TRUE;
            }
            else
            {
                // Jump to next item in the list
                pEntry = pEntry->Flink;
            }
        }

        KeReleaseSpinLock(
            &(pdx->Lock_PhysicalMemList),
            IrqL_Original
            );

        if (!bFound)
        {
            DebugPrintf((
                "ERROR - Physical memory object not found in list, unable to unmap\n"
                ));

            return ApiInvalidAddress;
        }
    }

    // Find the map object to unmap
    KeAcquireSpinLock(
        &(pMemObject->Lock_MappingsList),
        &IrqL_Original
        );

    pEntry = pMemObject->List_Mappings.Flink;

    bFound = FALSE;

    // Traverse list to find the desired list object
    while (!bFound && (pEntry != &(pMemObject->List_Mappings)))
    {
        // Get the object
        pMapObject =
            CONTAINING_RECORD(
                pEntry,
                PLX_USER_MAPPING,
                ListEntry
                );

        // Compare owner & virtual address
        if ((pOwner == pMapObject->pOwner) &&
            ((PLX_UINT_PTR)pMapObject->pUserVa[0] == pPciMem->UserAddr))
        {
            // Remove entry from the list
            RemoveEntryList(
                pEntry
                );

            bFound = TRUE;
        }
        else
        {
            // Jump to next item in the list
            pEntry = pEntry->Flink;
        }
    }

    KeReleaseSpinLock(
        &(pMemObject->Lock_MappingsList),
        IrqL_Original
        );

    if (!bFound)
    {
        DebugPrintf((
            "ERROR - Mapping object not found in list, unable to unmap\n"
            ));

        return ApiInvalidAddress;
    }

    // Unmap the memory
    if (pMapObject->pUserVa[0] != NULL)
    {
        DebugPrintf((
            "Unmapping Virtual address (0x%p) from User Space (owner=%p)...\n",
            pMapObject->pUserVa[0], pOwner
            ));

        MmUnmapLockedPages(
            pMapObject->pUserVa[0],
            pMemObject->pMdl
            );

        // Clear virtual address
        pPciMem->UserAddr = 0;
    }
    else
    {
        DebugPrintf((
            "ERROR - Invalid virtual address (0x%p), cannot unmap\n",
            pMapObject->pUserVa[0]
            ));

        return ApiInvalidAddress;
    }

    // Release memory for map object
    ExFreePool(
        pMapObject
        );

    return ApiSuccess;
}




/******************************************************************************
 *
 * Function   :  PlxPciBarMap
 *
 * Description:  Map a PCI BAR Space into User virtual space
 *
 ******************************************************************************/
RETURN_CODE
PlxPciBarMap(
    DEVICE_EXTENSION *pdx,
    U8                BarIndex,
    VOID             *pUserVa,
    VOID             *pOwner
    )
{
    U8                i;
    PMDL              pMdl[MAX_VIRTUAL_ADDR];
    VOID             *Va[MAX_VIRTUAL_ADDR];
    VOID             *VaBase;
    BOOLEAN           bMapError;
    PLX_USER_MAPPING *pMapObject;


    // Set default address
    *(PLX_UINT_PTR*)pUserVa = 0;

    // Verify BAR is of type memory
    if (pdx->PciBar[BarIndex].bIsIoSpace)
    {
        DebugPrintf((
            "ERROR - BAR %d is an I/O space, cannot map to user space\n",
            BarIndex
            ));

        return ApiInvalidPciSpace;
    }

    // Check if the space is valid
    if (pdx->PciBar[BarIndex].Physical.QuadPart == 0)
    {
        DebugPrintf((
            "ERROR - BAR %d address (0x%08lx) is invalid\n",
            BarIndex, pdx->PciBar[BarIndex].Physical
            ));

        return ApiInvalidAddress;
    }

    // Verify Kernel virtual address
    if (pdx->PciBar[BarIndex].pVa == NULL)
    {
        DebugPrintf((
            "ERROR - Kernel Virtual address for BAR %d is not valid\n",
            BarIndex
            ));

        return ApiInvalidAddress;
    }

    // Make sure memory size is valid
    if (pdx->PciBar[BarIndex].Size == 0)
    {
        DebugPrintf((
            "ERROR - Size of BAR %d is 0\n",
            BarIndex
            ));

        return ApiInvalidSize;
    }

    // Verify the MDL
    if (pdx->PciBar[BarIndex].pMdl == NULL)
    {
        DebugPrintf((
            "ERROR - MDL does not exist for BAR %d\n",
            BarIndex
            ));

        return ApiInsufficientResources;
    }

    // Make sure there is enough space to store all virtual addresses
    if (pdx->PciBar[BarIndex].Size >  (MAX_VIRTUAL_ADDR * MAX_MDL_SIZE))
    {
        DebugPrintf((
            "ERROR - Not enough virtual addresses for space of size %dMB\n",
            (pdx->PciBar[BarIndex].Size >> 20)
            ));

        return ApiInsufficientResources;
    }

    // Set initial values
    i         = 0;
    pMdl[0]   = pdx->PciBar[BarIndex].pMdl;
    VaBase    = NULL;
    bMapError = FALSE;

    // Clear the virtual addresses
    RtlZeroMemory(
        Va,
        MAX_VIRTUAL_ADDR * sizeof(VOID*)
        );

    // Attempt to map the BAR into user space
    while ((i < MAX_VIRTUAL_ADDR) && (pMdl[i] != NULL))
    {
        Va[i] =
            MmMapLockedPagesSpecifyCache(
                pMdl[i],
                UserMode,
                MmNonCached,                    // Do not cache PCI BAR space
                VaBase,                         // User address to use
                FALSE,
                LowPagePriority
                );

        // Check if the mapping succeeded
        if (Va[i] == NULL)
        {
            DebugPrintf((
                "ERROR - Unable to map PCI BAR %d (0x%08lx) ==> User space\n",
                BarIndex, pdx->PciBar[BarIndex].Physical
                ));

            bMapError = TRUE;
        }
        else if (VaBase != NULL)
        {
            // Make sure VA address is consecutive
            if (VaBase != Va[i])
            {
                DebugPrintf((
                    "ERROR - Unable to assign contiguous virtual addresses for PCI BAR %d (0x%08lx) ==> User space\n",
                    BarIndex, pdx->PciBar[BarIndex].Physical
                    ));

                bMapError = TRUE;
            }
        }

        if (bMapError)
        {
            // Release any previous mappings
            while (i != 0)
            {
                i--;

                MmUnmapLockedPages(
                    Va[i],
                    pMdl[i]
                    );
            }

            return ApiInsufficientResources;
        }

        // Adjust to next consecutive base address
        VaBase = ((U8*)Va[i]) + MmGetMdlByteCount(pMdl[i]);

        // Go to next entry
        i++;
        pMdl[i] = pMdl[i-1]->Next;
    }

    // Return initial base address
    *(PLX_UINT_PTR*)pUserVa = (PLX_UINT_PTR)Va[0];

    DebugPrintf((
        "Mapped PCI BAR %d (0x%08lx) ==> User VA (0x%08lx) (owner=%p)\n",
        BarIndex, pdx->PciBar[BarIndex].Physical, *(PLX_UINT_PTR*)pUserVa, pOwner
        ));


    // Add mapping to list for later unmapping
    pMapObject =
        ExAllocatePool(
            NonPagedPool,
            sizeof(PLX_USER_MAPPING)
            );

    if (pMapObject == NULL)
    {
        DebugPrintf(("ERROR: Unable to save mapping, insufficient memory\n"));
    }
    else
    {
        // Record mapping properties
        pMapObject->pOwner   = pOwner;
        pMapObject->BarIndex = BarIndex;

        RtlCopyMemory(
            pMapObject->pUserVa,
            Va,
            MAX_VIRTUAL_ADDR * sizeof(VOID*)
            );

        // Save the mapping for later cleanup
        ExInterlockedInsertTailList(
            &(pdx->List_BarMappings),
            &(pMapObject->ListEntry),
            &(pdx->Lock_BarMappingsList)
            );
    }

    return ApiSuccess;
}




/******************************************************************************
 *
 * Function   :  PlxPciBarUnmap
 *
 * Description:  Unmap a previously mapped PCI BAR Space from User virtual space
 *
 ******************************************************************************/
RETURN_CODE
PlxPciBarUnmap(
    DEVICE_EXTENSION *pdx,
    VOID             *UserVa,
    VOID             *pOwner
    )
{
    U8                i;
    PMDL              pMdl;
    KIRQL             IrqL_Original;
    PLIST_ENTRY       pEntry;
    PLX_USER_MAPPING *pMapObject;


    // Find the previous mapping object
    KeAcquireSpinLock(
        &(pdx->Lock_BarMappingsList),
        &IrqL_Original
        );

    pEntry = pdx->List_BarMappings.Flink;

    while (pEntry != &(pdx->List_BarMappings))
    {
        pMapObject =
            CONTAINING_RECORD(
                pEntry,
                PLX_USER_MAPPING,
                ListEntry
                );

        if ((pMapObject->pOwner == pOwner) &&
            (pMapObject->pUserVa[0] == UserVa))
        {
            // Remove map object from list
            RemoveEntryList(
                pEntry
                );

            KeReleaseSpinLock(
                &(pdx->Lock_BarMappingsList),
                IrqL_Original
                );

            DebugPrintf((
                "Unmapping Virtual address (0x%p) for BAR %d from User Space (owner=%p)...\n",
                pMapObject->pUserVa[0], pMapObject->BarIndex, pOwner
                ));

            // Unmap the space
            i    = 0;
            pMdl = pdx->PciBar[pMapObject->BarIndex].pMdl;

            while ((i < MAX_VIRTUAL_ADDR) && (pMapObject->pUserVa[i] != NULL))
            {
                MmUnmapLockedPages(
                    pMapObject->pUserVa[i],
                    pMdl
                    );

                i++;
                pMdl = pMdl->Next;
            }

            // Release the list object
            ExFreePool(
                pMapObject
                );

            return ApiSuccess;
        }

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

    DebugPrintf((
        "ERROR - Map object not found in list...\n"
        ));

    KeReleaseSpinLock(
        &(pdx->Lock_BarMappingsList),
        IrqL_Original
        );

    return ApiInvalidAddress;
}

⌨️ 快捷键说明

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