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

📄 commonapi.c

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

    // Set buffer request size
    pBufferObj->Size = pPciMem->Size;

    // Set Cacheability of the buffer
    pBufferObj->bCacheable = Gbl_PhysicalMemoryCacheable;

    // Setup amount to reduce on failure
    DecrementAmount = (pPciMem->Size / 10);

    DebugPrintf((
        "Attempting to allocate physical memory (%d Kb)...\n",
        (pPciMem->Size >> 10)
        ));

    do
    {
        // Attempt to allocate the buffer
        pBufferObj->pKernelVa =
            Plx_dma_buffer_alloc(
                pdx,
                pBufferObj
                );

        if (pBufferObj->pKernelVa == NULL)
        {
            // Reduce memory request size if requested
            if (bSmallerOk && (pBufferObj->Size > PAGE_SIZE))
            {
                pBufferObj->Size -= DecrementAmount;
            }
            else
            {
                // Release the list object
                ExFreePool(
                    pBufferObj
                    );

                DebugPrintf((
                    "ERROR - Physical memory allocation failed\n"
                    ));

                pPciMem->Size = 0;

                return ApiInsufficientResources;
            }
        }
    }
    while (pBufferObj->pKernelVa == NULL);

    // Record buffer owner
    pBufferObj->pOwner = pOwner;

    // Allocate MDL for buffer for later mapping into user space
    pBufferObj->pMdl =
        IoAllocateMdl(
            pBufferObj->pKernelVa,
            pBufferObj->Size,
            FALSE,          // Is this a secondary buffer?
            FALSE,          // Charge quota?
            NULL            // No IRP associated with MDL
            );

    // Check if the MDL allocation succeeded
    if (pBufferObj->pMdl == NULL)
        DebugPrintf(("ERROR - failed to allocate an MDL for buffer\n"));
    else
    {
        // Build the MDL
        MmBuildMdlForNonPagedPool(
            pBufferObj->pMdl
            );
    }

    // Initialize mappings list
    InitializeListHead(
        &(pBufferObj->List_Mappings)
        );

    KeInitializeSpinLock(
        &(pBufferObj->Lock_MappingsList)
        );

    // Return buffer information
    pPciMem->Size         = pBufferObj->Size;
    pPciMem->PhysicalAddr = pBufferObj->BusPhysical;
    pPciMem->CpuPhysical  = pBufferObj->CpuPhysical;

    // Add buffer object to list
    ExInterlockedInsertTailList(
        &(pdx->List_PhysicalMem),
        &(pBufferObj->ListEntry),
        &(pdx->Lock_PhysicalMemList)
        );

    // Check if this is the common buffer allocation
    if (pdx == pOwner)
    {
        // Store common buffer information
        pGbl_CommonBuffer = pBufferObj;
    }

    return ApiSuccess;
}




/******************************************************************************
 *
 * Function   :  PlxPciPhysicalMemoryFree
 *
 * Description:  Free previously allocated physically contiguous page-locked memory
 *
 ******************************************************************************/
RETURN_CODE
PlxPciPhysicalMemoryFree(
    DEVICE_EXTENSION *pdx,
    PLX_PHYSICAL_MEM *pPciMem
    )
{
    KIRQL                IrqL_Original;
    PLIST_ENTRY          pEntry;
    PLX_PHYS_MEM_OBJECT *pBufferObj;


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

    pEntry = pdx->List_PhysicalMem.Flink;

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

        // Check if the physical addresses matches
        if (pBufferObj->BusPhysical == pPciMem->PhysicalAddr)
        {
            // Release lock until mappings are removed
            KeReleaseSpinLock(
                &(pdx->Lock_PhysicalMemList),
                IrqL_Original
                );

            // Make sure all mappings to this memory are unmapped
            PlxPciPhysicalMemoryUnmapAll_ByOwner(
                pdx,
                pBufferObj,
                NULL         // Ignore owner to remove all mappings
                );

            // Remove the object from the list
            KeAcquireSpinLock(
                &(pdx->Lock_PhysicalMemList),
                &IrqL_Original
                );

            RemoveEntryList(
                pEntry
                );

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

            // Free the MDL
            if (pBufferObj->pMdl != NULL)
            {
                IoFreeMdl(
                    pBufferObj->pMdl
                    );
            }

            Plx_dma_buffer_free(
                pdx,
                pBufferObj
                );

            // Release the list object
            ExFreePool(
                pBufferObj
                );

            // Check if this is the common buffer release
            if (pGbl_CommonBuffer == pBufferObj)
            {
                // Clear common buffer information
                pGbl_CommonBuffer = NULL;
            }

            return ApiSuccess;
        }

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

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

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

    return ApiInvalidData;
}




/******************************************************************************
 *
 * Function   :  PlxPciPhysicalMemoryMap
 *
 * Description:  Maps physical memory to User virtual address space
 *
 ******************************************************************************/
RETURN_CODE
PlxPciPhysicalMemoryMap(
    DEVICE_EXTENSION *pdx,
    PLX_PHYSICAL_MEM *pPciMem,
    BOOLEAN           bDeviceMem,
    VOID             *pOwner
    )
{
    VOID                *pUserVa;
    KIRQL                IrqL_Original;
    BOOLEAN              bFound;
    PLIST_ENTRY          pEntry;
    PHYSICAL_ADDRESS     AddrPhysical;
    PLX_USER_MAPPING    *pMapObject;
    PLX_PHYS_MEM_OBJECT *pMemObject;
    MEMORY_CACHING_TYPE  CacheMode;


    // Set default return value
    pPciMem->UserAddr = 0;

    pMemObject = NULL;

    // Check if memory object is common buffer
    if (pGbl_CommonBuffer != NULL)
    {
        if (pPciMem->PhysicalAddr == pGbl_CommonBuffer->BusPhysical)
        {
            pMemObject = pGbl_CommonBuffer;
        }
    }

    // Find the memory object to map
    if (pMemObject == NULL)
    {
        // Find the object in the list
        KeAcquireSpinLock(
            &(pdx->Lock_PhysicalMemList),
            &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 map\n"
                ));

            return ApiInvalidAddress;
        }
    }

    // Verify an MDL for the memory
    if (pMemObject->pMdl == NULL)
    {
        DebugPrintf((
            "ERROR - MDL does not exist for this memory, cannot map to user space\n"
            ));

        return ApiInsufficientResources;
    }

    // Set cache mode
    if (Gbl_PhysicalMemoryCacheable)
    {
        CacheMode = MmCached;
    }
    else
    {
        CacheMode = MmNonCached;
    }

    // Attempt to map the region
    pUserVa =
        MmMapLockedPagesSpecifyCache(
            pMemObject->pMdl,
            UserMode,
            CacheMode,
            NULL,
            FALSE,
            NormalPagePriority
            );

    if (pUserVa == NULL)
    {
        DebugPrintf((
            "ERROR - Unable to map Physical address (0x%08lx) ==> User Space\n",
            pMemObject->CpuPhysical
            ));

        return ApiInsufficientResources;
    }

    DebugPrintf((
        "Mapped Physical address (0x%08lx) ==> Virtual address (0x%p) (owner=%p)\n",
        pMemObject->CpuPhysical, pUserVa, pOwner
        ));

    // Return virtual address
    pPciMem->UserAddr = (PLX_UINT_PTR)pUserVa;

    // Save mapping to list for this physical memory
    pMapObject =
        ExAllocatePool(
            NonPagedPool,
            sizeof(PLX_USER_MAPPING)
            );

    if (pMapObject == NULL)
    {
        DebugPrintf((
            "ERROR: Unable to save mapping, insufficient memory\n"
            ));
    }
    else
    {
        // Clear the virtual addresses
        RtlZeroMemory(
            pMapObject->pUserVa,
            MAX_VIRTUAL_ADDR * sizeof(VOID*)
            );

        // Record the IRP owner
        pMapObject->pOwner = pOwner;

        // Record the virtual address
        pMapObject->pUserVa[0] = pUserVa;

        // Save the mapping for later cleanup
        ExInterlockedInsertTailList(
            &(pMemObject->List_Mappings),
            &(pMapObject->ListEntry),
            &(pMemObject->Lock_MappingsList)
            );
    }

    return ApiSuccess;
}




/******************************************************************************
 *
 * Function   :  PlxPciPhysicalMemoryUnmap
 *
 * Description:  Unmap physical memory from User virtual address space
 *
 ******************************************************************************/
RETURN_CODE
PlxPciPhysicalMemoryUnmap(
    DEVICE_EXTENSION *pdx,
    PLX_PHYSICAL_MEM *pPciMem,
    VOID             *pOwner
    )
{
    VOID                *pUserVa;
    KIRQL                IrqL_Original;
    BOOLEAN              bFound;
    PLIST_ENTRY          pEntry;
    PHYSICAL_ADDRESS     AddrPhysical;
    PLX_USER_MAPPING    *pMapObject;
    PLX_PHYS_MEM_OBJECT *pMemObject;


    pMemObject = NULL;

    // Check if memory object is common buffer
    if (pGbl_CommonBuffer != NULL)
    {
        if (pPciMem->PhysicalAddr == pGbl_CommonBuffer->BusPhysical)
        {
            pMemObject = pGbl_CommonBuffer;
        }
    }

    // Find the memory object to unmap
    if (pMemObject == NULL)
    {
        // Find the object in the list
        KeAcquireSpinLock(
            &(pdx->Lock_PhysicalMemList),

⌨️ 快捷键说明

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