mapping a DMA buffer twice in vitual memory contiguously

There is a way to do this using supported APIs but it’s a bit convoluted:

  1. Mdl1 = MmAllocatePagesForMdlEx (1 MB);
  2. UserVa =
    3. MmMapLockedPagesSpecifyCache (Mdl1, UserMode, UserVa);
    4. MmMapLockedPagesSpecifyCache (Mdl1, UserMode, UserVa + 1 MB);
    5. Repeat steps 2-4 until both mappings succeed.
    6. Mdl2 = IoAllocateMdl (UserVa, 2 MB);
    7. MmProbeAndLockPages (Mdl2, UserMode);
    8. SystemVa = MmGetSystemAddressForMdlSafe (Mdl2);
    9. MmUnmapLockedPages (UserVa, Mdl1);
    10. MmUnmapLockedPages (UserVa + 1 MB, Mdl1);

    Now SystemVa will contain two virtually contiguous mappings of the same physical buffer. If the second mapping doesn’t need to cover the entire buffer, you can supply a smaller size to IoAllocateMdl in step 6, and maybe also use IoBuildPartialMdl instead of mapping the same MDL twice.

    -----Original Message-----
    From: xxxxx@lists.osr.com [mailto:xxxxx@lists.osr.com] On Behalf Of xxxxx@technolution.nl
    Sent: Monday, November 07, 2011 1:54 AM
    To: Windows System Software Devs Interest List
    Subject: [ntdev] mapping a DMA buffer twice in vitual memory contiguously

    Hello,

    I’m writing a driver for a device that receives a high speed data stream. The data is written in a DMA buffer (size > 1MB) at the host system. The device writes the data cyclical in the buffer. In a later stage messages are read from the cyclic buffer. This implicates that the message at the end of the buffer will be fragmented in two parts, one at the end of the buffer, and one at the start. I would like to prevent that software has handle the fragmentation. Therefore I would like to map the start of the DMA buffer for the second time in virtual memory, behind the end of the DMA buffer. This way the fragmented message can still be read contiguously from virtual memory. In whit way could this be done?

    I looked int the MDL structure. The MDL of the DMA buffer should be modified to add the pages of the start to the end. But thereis no API for it as far as I can see.

    I also looked into MmAllocateMappingAddress, but that seems to fail with the 1MB MDL. Besides that, the issue can not be solved with MmAllocateMappingAddress MmMapLockedPagesWithReservedMapping, because MmMapLockedPagesWithReservedMapping accepts only the start address of the VM area returned by MmAllocateMappingAddress. I cannot use an address half-way the VM area returned by MmAllocateMappingAddress.

    So, does anyone have any suggestion?

    Thanks in advance…