3.3.2 Getting an NT Adapter Object
When it initializes, an NT driver that uses system or busmaster DMA calls HalGetAdapter in order to get a pointer to a HAL-created adapter object and to determine the maximum number of map registers available for each transfer operation. Figure 3.6 illustrates such a call to HalGetAdapter.
Figure 3.6 Getting an Adapter Object
As Figure 3.6 shows, the driver supplies certain kinds of information to HalGetAdapter in a system-defined DEVICE_DESCRIPTION structure. The required data includes information about the features of the driver’s device, such as whether the device is a busmaster, whether it has scatter/gather capabilities, and how many bytes of data the device can transfer at a time (MaximumLength). Note that MaximumLength effectively specifies the maximum number of map registers the driver could use for each transfer operation, assuming the HAL could make an unlimited number of map registers available on every Windows NT platform.
The required device description data also includes certain platform-specific information, which the driver can obtain when it finds its adapter by calling HalGetBusData or HalGetBusDataByOffset or from the registry, such as the platform-specific and system-assigned number of the bus that a driver of a busmaster device controls. For more information about using the registry, see Chapter 16.
As Figure 3.6 also shows, the DEVICE_DESCRIPTION structure includes some fields that might be irrelevant to some DMA devices on any Windows NT platform. For example, an EISA or ISA DMA device would not use a particular DmaPort as a microchannel-type device would. Each NT driver should supply appropriate values for device description members that are relevant and should set the values for all other members to zero.
The driver of a slave device should not claim it supports scatter/gather unless the device is capable of waiting for the system DMA controller to be reprogrammed when a request must be broken up into two or more DMA operations.
All NT drivers must initialize the DeviceDescription area by calling RtlZeroMemory before they set relevant values in it.
As Figure 3.6 also shows, HalGetAdapter returns both a pointer to an adapter object and a platform-specific or device-specific value indicating how many map registers are available with the adapter object for each DMA transfer operation. As mentioned in Section 3.3.1, this value can vary from device to device and from platform to platform. Generally, the HAL assigns values according to the following criteria:
·If possible, the HAL returns a value that is one more than the number of map registers needed to transfer MaximumLength bytes, as specified in the driver’s call to HalGetAdapter.
·Otherwise, the HAL returns a lesser value that is as large as possible for the particular platform.
In other words, the NT HAL usually gives each driver enough map registers to maximize DMA throughput for its device, but the HAL can return a lesser value on some Windows NT platforms.
Any DMA device driver must provide storage for the adapter object pointer and NumberOfMapRegisters value returned by HalGetAdapter. This pointer is a required parameter to every IoXxx and/or HalXxx used for DMA. Because many of these support routines must be called at IRQL DISPATCH_LEVEL, the driver-allocated storage must be resident. Most DMA device drivers provide the necessary storage in a device extension (see Section 3.2.1). However, the storage can be in a controller extension if the driver also uses a controller object (see Section 3.4) or in nonpaged pool, allocated by the driver. For more information about allocating nonpaged pool memory and about managing IRQLs, see Chapter 16.