A driver that uses programmed I/O (PIO) rather than DMA must doubly map user-space buffers into a system-space address range. The following figure illustrates how the I/O Manager sets up an IRP_MJ_READ request for a PIO transfer operation that uses direct I/O.

Direct I/O for Devices that Use PIO
The figure shows how a device that uses PIO handles the same task.
When the driver completes the IRP by calling IoCompleteRequest, the I/O Manager or file system releases the MDL's doubly mapped system-space range if the driver called MmGetSystemAddressForMdlSafe. The I/O manager or file system unlocks the pages described in the MDL, and disposes of the MDL and IRP on the driver's behalf. For better performance, drivers should avoid doubly mapping MDL physical addresses to system space, as described in step 3, unless they must use virtual addresses. Doing so uses system page-table entries unnecessarily and can decrease both driver performance and scalability. In addition, the system might crash if it runs out of page-table entries, because most older drivers cannot handle this situation.
The current user thread's buffers and the thread itself are guaranteed to be resident in physical memory only while that thread is current. For the thread shown in the previous figure, its user buffer's contents could be paged out to secondary storage while another process's threads are run. When another process's thread is run, the system physical memory for the requesting thread's buffer can be overwritten unless the Memory Manager has locked down and preserved the corresponding physical pages that contain the original thread's buffer.
However, the original thread's virtual addresses for its buffer do not remain visible while another thread is current, even if the Memory Manager preserves the buffer's physical pages. Consequently, drivers cannot use a virtual address returned by MmGetMdlVirtualAddress to access memory. Callers of this routine must pass its results to MapTransfer (along with the IRP's MdlAddress pointer) in order to transfer data using packet-based system or bus-master DMA.