Writing a driver for a DMA device is somewhat more complicated than writing a driver for a most other types of devices. The job is easier if you understand the design details of the device and how the driver can control it before you begin to write the driver. Table 17-1 shows a checklist of the required design information.
DMA design type
Packet-based, common-buffer, or hybrid
Maximum addressing capability
32-bit, 64-bit, or other
Hardware scatter/gather support
Yes or no
Maximum transfer length per DMA operation
Number of bytes
Buffer alignment requirement
None, word, longword, or quadword
The information in Table 17-1 is important in determining overall driver I/O design, selecting a DMA profile for the device, and configuring the DMA enabler and transaction objects that the driver uses to perform DMA.
Because device implementations vary greatly, not all of these issues apply to your driver. Furthermore, it is impossible to discuss every issue you could possibly encounter. Check with the designer of your particular device, or with a hardware engineer who understands the details of your device's design, for any issues that you should consider that are unique to your device.
This section provides more detail on each of the items in Table 17-1. In particular, it discusses how the specific details of your device might influence the design of your DMA driver.
The most important fact that you must know about your device is whether it uses a packet-based DMA design, a common-buffer DMA design, or a hybrid of the two. The DMA design type dictates the overall architecture and design of your driver.
It is usually harder to write drivers for common-buffer and hybrid DMA devices than for packet-based devices, because device designs that use common buffers require a complete understanding and careful coordination of the data structures that the driver and the device share. Some of the issues that you might need to identify include the following:
How your driver communicates the base address of the common buffer to your device.
What format is used for pointers that are stored in the common buffer, such as for linked lists.
What types of synchronization are required between your driver and your device when updating structures in the common buffer area.
Designs that use common buffers can also introduce subtle side effects that a driver might be required to handle. For example, common-buffer devices perform frequent DMA transfers to or from system memory as the device hardware scans for changes to the shared data structures. Although this is not a problem in most desktop systems, on laptop systems such designs can have a negative impact on battery life. If you cannot avoid using a common-buffer DMA device design in a laptop, you should typically ensure that your driver implements an aggressive power-management scheme for the device. For example, you might design your driver to power down the device whenever the device is idle.
Some hybrid designs enable the device to be used as a completely packet-based device. Because drivers for packet-based DMA devices are typically less complex to write than those for common-buffer devices, you might consider first implementing a driver for a hybrid device by using the simpler packet-based interface and later adding support for the common-buffer area.
Another important detail is the physical addressing capability of the device-specifically, whether the device is capable of 64-bit addressing. When you select the DMA profile for the device, you indicate whether it supports DMA transfers to 64-bit addresses.
Newly designed devices for Windows should include hardware scatter/gather support because this can significantly reduce data transfer overhead and latency. You indicate whether your device supports hardware scatter/gather when you select its DMA profile.
Many devices have a maximum number of bytes that they can transfer in one DMA operation. If your device has such a limit, you must know what the limit is. Some devices have no limit on the maximum length of a DMA transfer. For these devices, you must determine a practical maximum transfer length that your driver will support.
Regardless of whether the limit is set by the device or by the driver, you must supply this value when you configure the DMA enabler object.
DMA devices often require that data buffers used in DMA transfers be aligned in particular ways. For example, one relatively common DMA support chipset requires data buffers used for DMA read and write operations to be aligned on a 16-byte boundary. This is because the chipset reserves the lowest 4 bits of each address for its own use. As with support for 64-bit addressing and hardware scatter/gather, the buffer alignment requirement helps to determine the appropriate DMA profile for the device.
Windows implements extensive system support for DMA according to the Windows DMA abstraction described later in this chapter. Drivers that use KMDF methods for DMA are guaranteed to conform to the Windows DMA model and thus avoid a considerable amount of complicated code to handle issues such as the following:
Windows 64-bit support Drivers that use the built-in KMDF DMA support are not typically required to implement any special code to work properly in the 64-bit virtual address space that 64-bit editions of Windows provide. Drivers should always use the 64-bit safe data types, such as ULONG_PTR, to make their data size specification clear and unambiguous. Drivers that must differentiate between 32-bit and 64-bit callers may do so by calling the WdfRequestIsFrom32BitProcess method.
Amount of physical memory present The capabilities of the device determine the size of the memory pointers that the framework uses, and not the physical addressing capability or the amount of memory that is available on a given system. The framework ensures that drivers always receive data buffer physical addresses that are within the addressing capabilities of their devices. Thus, a driver for a device that is capable of only 32-bit addressing will not receive a pointer with more than 32 significant bits.
Bus addressing capability Drivers that use the built-in KMDF DMA support are never required to determine the addressing capability of the bus to which their device is attached, because the framework handles all addressing issues. For example, the driver for a PCI bus device that is capable of 64-bit addressing is not required to be aware of whether the device is attached to a 64-bit-capable PCI bus. As with the amount of physical memory present on the machine, the addressing capability of the bus is made transparent by the framework's DMA implementation.
Bus addressing transparency is maintained for PCI buses with 64 address lines, as well as for PCI buses that support the dual address cycle (DAC) mode of 64-bit addressing.
The above features apply only to drivers that use the KMDF DMA support, which conforms to the implementation model based on the Windows DMA abstraction. Drivers that take shortcuts by not following the model-often in an unnecessary attempt at performance optimization-receive unpredictable levels of support for the features described above, depending on precisely which parts of the DMA model they use.