Any driver might need to split up a transfer request and carry out more than one DMA transfer operation to satisfy a given IRP, depending on the following:
A driver can determine the number of map registers needed to transfer all the data specified by an IRP as follows:
If the value returned by ADDRESS_AND_SIZE_TO_SPAN_PAGES is greater than the NumberOfMapRegisters value returned by IoGetDmaAdapter, the driver cannot transfer all requested data for this IRP in a single DMA operation. Instead, it must do the following:
For example, suppose ADDRESS_AND_SIZE_TO_SPAN_PAGES indicates that twelve map registers are needed to satisfy a transfer request, but the NumberOfMapRegisters value returned by IoGetDmaAdapter is only five. (Assume no device-specific DMA constraints.) In this case, the driver must carry out three DMA transfer operations, calling MapTransfer three times to transfer all the data requested by the IRP.
The system's DMA device drivers use various techniques to split up a DMA transfer when there are not enough map registers to satisfy an IRP with a single I/O operation. One technique to use is the following:
If a highest-level driver cannot lock down the entire user buffer with MmProbeAndLockPages in a machine with limited memory, it can do the following:
When a storage class driver splits up large transfer requests for underlying SCSI port/miniport drivers, it allocates an additional IRP for each piece of the transfer request. It registers an IoCompletion routine for each driver-allocated IRP, to track the status of the full transfer request and to free the driver-allocated IRPs. Then it sends these IRPs on to the port driver using IoCallDriver.
Other class/port drivers can use this technique only if the class driver can determine how many map registers are available to the port driver. The port driver must store this configuration information in the registry for the paired class driver, or the paired drivers must define a private interface, using internal device I/O control requests, to pass configuration information about the number of available map registers from the port driver to the class driver.
A monolithic driver (that is, a driver not part of a class/port pair) for a DMA device must split up large transfer requests for itself. Such drivers usually split a large request into pieces and carry out a sequence of DMA operations in order to satisfy the IRP.
If a transfer request is too large for the underlying device driver to handle, a higher-level driver can call MmGetMdlVirtualAddress and IoBuildPartialMdl, then set up a sequence of partial-transfer IRPs for underlying device drivers.