windows PCI驱动Block DMA使用问题

最近在修改一份基于DriverStudio的PCI视频采集卡驱动代码,遇到了关于DMA的使用上的疑惑。
其OnStartDevice初始化了相关资源,代码如下:

    PCM_RESOURCE_LIST pResListRaw = I.AllocatedResources();
    // Get the list of translated resources from the IRP
    PCM_RESOURCE_LIST pResListTranslated = I.TranslatedResources();
    // Initialize the device descriptor for the DMA object using the assigned resource
    DEVICE_DESCRIPTION dd;
    RtlZeroMemory(&dd, sizeof(dd));
    dd.Version = DEVICE_DESCRIPTION_VERSION;
    dd.Master = TRUE;
    dd.ScatterGather = FALSE;
    dd.DemandMode = TRUE;
    dd.AutoInitialize = FALSE;
    dd.Dma32BitAddresses = TRUE;
    dd.IgnoreCount = FALSE;
    dd.DmaChannel = 3;
    dd.InterfaceType = PCIBus;
    dd.DmaWidth = Width32Bits;  // PCI default width
    dd.DmaSpeed = MaximumDmaSpeed;
    dd.MaximumLength = m_nDmaBufferSize;

    // Initialize the DMA adapter object
    m_Dma.Initialize(&dd, m_Lower.TopOfStack());
    m_DmaBuffer.Initialize(&m_Dma,m_nDmaBufferSize,true);

    // Create an instance of KPciConfiguration so we can map Base Address
    // Register indicies to ordinals for memory or I/O port ranges.
    KPciConfiguration PciConfig(m_Lower.TopOfStack());

    // For each I/O port mapped region, initialize the I/O port range using
    // the resources provided by NT. Once initialized, use member functions such as
    // inb/outb, or the array element operator to access the ports range.
    status = m_IoPortRange0.Initialize(
        pResListTranslated,
        pResListRaw,
        PciConfig.BaseAddressIndexToOrdinal(0)
        );

    status = m_Irq.InitializeAndConnect(
    pResListTranslated, 
    LinkTo(Isr_Irq), 
    this
    );

    if (!NT_SUCCESS(status))
    {
        Invalidate();
        return status;      
    }

    // Setup the DPC to be used for interrupt processing
    m_DpcFor_Irq.Setup(LinkTo(DpcFor_Irq), this);

这里初始化了DMA,但是没有绑定PCI设备物理地址与驱动空间地址的相关代码。然而在IoControl中却有以下操作

//写
 UCHAR* pDMA = (UCHAR*)m_DmaBuffer.pVirtualAddress() + pCapInfo->nCode*pCapInfo->nSize + pCapInfo->nOffset;
        memcpy(pDMA,pCapInfo->pData,pCapInfo->nSize);
//读
UCHAR* pDMA = (UCHAR*)m_DmaBuffer.pVirtualAddress() + pCapInfo->nCode*pCapInfo->nSize + pCapInfo->nOffset;
        memcpy(pCapInfo->pData,pDMA,pCapInfo->nSize);

从代码可以看出,直接将m_DmaBuffer当做PCI的内存进行了访问。简单阅读了DriverStudio的封装源代码,初始化过程实际上调用了IoGetDmaAdapter与AllocateCommonBuffer,也就是说m_DmaBuffer.pVirtualAddress()实际上是AllocateCommonBuffer分配的公用缓冲区,而实际上并没有任何地方将该地址与PCI实际的物理地址进行绑定。查阅相关资料,AllocateCommonBuffer一般用于ScatterGather模式,这里使用的是block DMA模式。难道是IoGetDmaAdapter或者AllocateCommonBuffer自动将pVirtualAddress()与PCI的物理地址空间进行了绑定?查询相关资料,也没有这种解释。那究竟为什么能直接通过m_DmaBuffer.pVirtualAddress()操作PCI的物理地址空间呢?

求各位大神解答。

0
Csdn user default icon
上传中...
上传图片
插入图片
抄袭、复制答案,以达到刷声望分或其他目的的行为,在CSDN问答是严格禁止的,一经发现立刻封号。是时候展现真正的技术了!