Using Common-Buffer Bus-Master DMA
As described in Using Bus-Master DMA, some drivers for bus-master DMA devices use common-buffer DMA exclusively, and some use common-buffer DMA in combination with packet-based DMA.
Use common-buffer DMA economically. Setting up a common buffer can tie up some (or all, depending on the size of the requested buffer) of the map registers associated with the adapter object that represents the bus-master adapter.
Setting up common-buffer areas economically, such as by using PAGE_SIZE chunks or a single allocation, leaves more map registers available for packet-based DMA operations. It also leaves more system memory free for other purposes, which produces better overall driver and system performance.
To set up a common buffer for bus-master DMA, a bus-master DMA device driver must call AllocateCommonBuffer with the adapter object pointer returned by IoGetDmaAdapter. Typically, a driver makes this call from its DispatchPnP routine for IRP_MN_START_DEVICE requests. A driver should allocate a common buffer only if it will use the buffer repeatedly for its DMA operations while the driver remains loaded. The following diagram illustrates such a call to AllocateCommonBuffer.
The requested size for the buffer, shown in the previous diagram as LengthForBuffer, determines how many map registers must be used to provide a virtual-to-logical mapping for the common buffer. Use the BYTES_TO_PAGES macro to determine the maximum number of pages needed (BYTES_TO_PAGES (LengthForBuffer)). This value cannot be greater than the NumberOfMapRegisters returned by IoGetDmaAdapter.
In addition, the caller must supply the following:
A Boolean value that indicates whether caching should be enabled
A pointer to a driver-defined variable that will contain the device-accessible base Logical Address for the buffer (BufferLogicalAddress in the previous diagram) on return from AllocateCommonBuffer
If the call succeeds, AllocateCommonBuffer returns a driver-accessible base virtual address for the buffer (BufferVirtualAddress in the previous diagram), which the driver must save in its device extension, controller extension, or other driver-accessible resident storage area (nonpaged pool allocated by the driver).
AllocateCommonBuffer returns NULL if it cannot allocate memory for the buffer. If the returned base virtual address is NULL, the driver either must use the system's packet-based DMA support exclusively or the driver must fail the IRP_MN_START_DEVICE request, returning STATUS_INSUFFICIENT_RESOURCES.
Otherwise, the driver can use the allocated common buffer as a driver- and adapter-accessible storage area for DMA transfers.
When the PnP manager sends an IRP that stops or removes the device, the driver must call FreeCommonBuffer to release each common buffer it has allocated.