DMA is a method of transferring data between a device and main memory without intervention by the CPU. Instead of the CPU copying the data from one location to the other, the CPU initiates the copy operation and then is free to service other requests. Depending on the type of DMA device, either the device or a separate DMA controller actually copies the data. Devices such as network adapters are typically designed to support DMA, which improves both device and system performance.
Windows supports two types of DMA devices: bus-master devices and system devices, which are sometimes called "slave" devices.
Modern buses such as PCI Express typically support bus-master devices, which are now the most common type of DMA devices. A bus-master DMA device contains all of the required electronics and logic to take control of-or "master"-the bus on which it is located and to transfer data between the device's buffer and the host's system memory. Drivers for bus-master devices can take advantage of framework support for DMA.
System DMA devices are vestiges of the original IBM PC design and are typically supported by an ISA bus. These devices rely on a DMA controller chip on the motherboard to perform data transfers. KMDF does not support system DMA because modern devices that use system DMA are relatively scarce. Drivers for system DMA devices must use WDM.
Note Unless stated otherwise, the term "DMA" in this chapter refers only to bus-master DMA.
Two terms are critically important to understanding DMA, DMA devices, and the Windows DMA model:
DMA transaction A complete I/O operation that involves DMA, such as a single read or write request from an application.
DMA transfer A single hardware operation that transfers data from main memory to a device or from the device to main memory.
When a KMDF driver receives an I/O request, it creates a DMA transaction object to represent the request. The DMA transaction might involve one or more transfers, depending on the size of the request. Internally, the framework determines whether the device can satisfy the entire transaction in a single transfer. If the transaction is too large, the framework divides the transaction into multiple transfer operations, each of which transfers a fragment of the requested data.
Thus, a DMA transfer is always associated with a single DMA transaction, but a DMA transaction can involve multiple DMA transfers.
The two basic types of DMA device design are packet-based DMA and common-buffer DMA. Devices can also incorporate a hybrid design that has features of both packet-based and common-buffer DMA.
Packet-based DMA devices are the most common design. In this design, the driver explicitly sets up and requests each data transfer from the device. Each DMA operation thus transfers a packet of data.
One example of a packet-based DMA device is a mass storage device. To read data from such a device, the driver programs the DMA device to read the required sectors and provides the device with a pointer to a buffer in system memory that will receive the data. The device generates an interrupt after the read operation is complete. When the interrupt occurs, the driver performs any required teardown and completes the request.
In a common-buffer DMA design, the driver allocates an area in system memory-the common buffer-that it shares with the DMA device. The format of this area is defined by the DMA device and is understood by the driver. The shared area can contain data structures that the driver uses to control the device, and it might also contain one or more data buffers. The device periodically checks the data structures in the shared area and updates them by performing DMA transfers. Because these DMA transfers occur as required by the device without any specific initiating action by the driver, common-buffer DMA is sometimes referred to as "continuous DMA."
One example of a common-buffer DMA device is an intelligent network adapter. The common buffer for such an adapter might contain a set of data buffers and a pair of circular lists: one for transmit and one for receive. Each entry in the receive list might contain a description of a corresponding data buffer-which can hold an incoming network message-and a status field that indicates whether the data buffer is available or whether it already contains a message.
Hybrid DMA device designs incorporate both packet-based and common-buffer DMA. These designs typically use both a host-resident shared memory buffer that contains control structures for the device-the common-buffer part of the design-and a set of descriptors that contain information about each data packet to be transmitted. Before each DMA transfer, software sets up the descriptors and then makes an entry in the common buffer for a new packet to transmit. The device then transmits the packet directly from the data buffer-the packet-based part of the design.
Unlike a pure common-buffer design, the driver does not copy the contents of the data buffer to the common buffer. After the device transmits the packet, the device generates an interrupt. After receiving the interrupt, the driver for the device determines which packets are complete, performs any required teardown, and completes the associated requests.
Scatter/gather is a DMA technique in which a single transfer includes data from multiple locations in physical memory. Some devices support scatter/gather DMA in hardware. For devices that do not have such hardware, Windows implements an internal scatter/gather mechanism in software.
Hardware support for scatter/gather DMA, also called DMA chaining, is particularly efficient on Windows systems. Because Windows uses demand-paged virtual memory, virtually contiguous data buffers are often not physically contiguous. That is, a buffer that is contiguous in virtual memory might actually map to multiple locations in physical memory. A device that supports scatter/gather DMA in hardware can complete the request in a single transfer, whereas a device that can perform DMA only from a single, contiguous memory location might be required to make several smaller transfers to complete a request.
The buffer for scatter/gather DMA is described by a scatter/gather list, which is simply a list that contains a base address and length for each physical location in the buffer. The number of entries in the list depends on the device, but in most modern devices the maximum number is unlimited.
KMDF drivers are not required to implement any special handling to support scatter/gather. During initialization, the driver fills in a configuration data structure that describes the capabilities of the device. The framework then uses the device's hardware scatter/gather capabilities or the Windows software implementation, as appropriate.