IoGetDmaAdapter

This function gets or creates an adapter object for a given device’s DMA operations.

Declaration

PDMA_ADAPTER
IoGetDmaAdapter (
    PDEVICE_OBJECT DeviceObject,
    PDEVICE_DESCRIPTION DeviceDescription,
    ULONG *NumberOfMapRegisters);

Parameters

The DeviceObject argument is the address of a structure that represents the device that seeks to perform DMA. This argument can be NULL.

The DeviceDescription argument is the address of a structure that describes the device’s DMA requirements.

The NumberOfMapRegisters argument is the address of a variable that is to receive the maximum number of map registers that the device can use for any DMA operation.

Return Value

If successful, the function returns the address of a structure that represents the DMA adapter. The function returns NULL to indicate failure.

Behaviour

The DMA adapter may be found in either of two ways. One is to send a PnP request through the given device object to see if the bus driver has its own routine for getting a DMA adapter. The other is to default to the HAL, essentially through the obsolete HalGetAdapter function.

PnP

The first method is possible only if a device object is given. Moreover, the device object must be a physical device object (PDO). This means specifically that it must be associated with a device node that is fully created and is not about to be destroyed. If this is not true of the given device object, the function raises the bug check PNP_DETECTED_FATAL_ERROR (0x00CA). The first bug-check argument is 2, the second is the address of the device object, and the remaining two are zero.

If the InterfaceType member of the DEVICE_DESCRIPTION is either InterfaceTypeUndefined or PnPBus, the function substitutes whatever interface type is obtained by calling the IoGetDeviceProperty function for DevicePropertyLegacyBusType. If this fails, the function substitutes a default, which is presently Isa. (The substitution is done in a copy of the given DEVICE_DESCRIPTION, as if the given structure is read-only.)

The function sends a synchronous IRP_MJ_PNP request to the top of the given device object’s driver stack. Failure to build the request is failure for the function. If the request fails, the function defaults to calling the HAL (see below). The PnP request is specifically an IRP_MN_QUERY_INTERFACE for the interface represented by GUID_BUS_INTERFACE_STANDARD, asking for version 1 of the interface, expecting some driver in the stack to provide the 0x20 bytes of a BUS_INTERFACE_STANDARD structure. Three members in this structure matter. The Context and InterfaceDereference members always matter, since the function must pass the former to the latter when done with the interface. If the structure provides a non-NULL GetDmaAdapter member, the function calls it to get the DMA adapter object, passing the Context member, the address of the DEVICE_DESCRIPTION structure (which may be a slightly modified copy) and the NumberOfMapRegisters argument.

HAL

If the DeviceObject argument is NULL or the IRP_MN_QUERY_INTERFACE request fails or the GetDmaAdapter routine returns NULL, then the function defaults to calling the HAL. The ordinary effect is of reverting to the obsolete function HalGetAdapter, passing the DeviceDescription and NumberOfMapRegisters arguments.

A less ordinary, perhaps even unusual, effect is possible because the call does not go directly to the function that the HAL exports as HalGetAdapter. It goes instead through the HalGetDmaAdapter member of the HalDispatchTable. The latter is a jump table in the kernel, but it is exported. Though the dispatch table is ordinarily set by the HAL, surely the only point to it is that its entries can be modified, and the call to the HAL for getting a DMA adapter object can therefore be filtered.

Availability

The IoGetDmaAdapter function is exported by name from the Windows kernel in version 5.0 and higher.

The function is documented. For Microsoft’s description of the implied PnP request, look to the documentation of IRP_MN_QUERY_INTERFACE.

The function is implemented in paged code and is to be called only at PASSIVE_LEVEL.