Using Direct I/O with DMA
The following figure illustrates how the I/O manager sets up an IRP_MJ_READ request for a DMA transfer operation that uses direct I/O.
The previous figure illustrates how drivers can use the IRP's MdlAddress to transfer data for a read request. The driver in the figure uses packet-based system or bus-master DMA, and has ORed the device object's Flags with DO_DIRECT_IO.
Some range of user-space virtual addresses represents the current thread's buffer, and that buffer's contents might actually be stored on some number of physically discontiguous pages (dark shading in the previous figure). The I/O manager creates an MDL to describe this buffer. An MDL is an opaque data structure, defined by the memory manager, that maps a particular virtual address range to one or more page-based physical address ranges. For more information, see Using MDLs.
The I/O manager services the current thread's read request, for which the thread passes a range of user-space virtual addresses that represent a buffer.
The I/O manager or file system driver (FSD) checks the user-supplied buffer for accessibility and calls MmProbeAndLockPages with the previously created MDL. MmProbeAndLockPages also fills in the corresponding physical address range in the MDL.
As the previous figure shows, an MDL for a virtual range can have several corresponding page-based physical address entries, and the virtual range for a buffer might begin and end at some byte offset from the start of the first and last pages described by an MDL.
The I/O manager provides a pointer to the MDL (MdlAddress) in an IRP that requests a transfer operation. Until the I/O manager or file system calls MmUnlockPages after the driver completes the IRP, the physical pages described in the MDL remain locked down and assigned to the buffer. However, the virtual addresses in such an MDL can become invisible (and invalid), even before the IRP is sent to the device driver or to any intermediate driver that might be layered above the device driver.
If the driver uses packet-based system or bus-master DMA, its AdapterControl routine calls MmGetMdlVirtualAddress with the IRP's MdlAddress pointer to get the base virtual address for the MDL's page-based entries.
The AdapterControl routine then calls MapTransfer with the base address returned by MmGetMdlVirtualAddress, to read data from the device directly into physical memory. (For more information, see Adapter Objects and DMA.)
Drivers should always check buffer lengths. Note that the I/O manager does not create an MDL for a zero-length buffer.