At a minimum, an AdapterControl routine must do the following:
Depending on the driver’s design, its AdapterControl routine also can do the following before it returns control:
In general, it is the responsibility of the routine that calls IoAllocateAdapterChannel to determine whether a given transfer request must be split up into partial transfers due to any platform-specific limitations on the NumberOfMapRegisters available for each DMA transfer operation, as mentioned in Section 11.1.4.
For example, an AdapterControl routine might call KeSetTimer with the entry point for a CustomTimerDpc routine that times out DMA transfer operations for the driver. For more information about CustomTimerDpc routines, see Chapter 14.
If a given transfer request requires the driver to perform a sequence of partial-transfer operations to satisfy the current IRP, usually the driver’s DpcForIsr routine is responsible for reprogramming the device for subsequent transfer operations. An AdapterControl routine is called only once for each incoming transfer IRP.
The driver routine that completes the current transfer IRP, usually the DpcForIsr, also is responsible for releasing the system DMA controller or busmaster adapter by calling IoFreeAdapterChannel or IoFreeMapRegisters, respectively. This driver routine should make the appropriate call as soon as possible when its last partial-transfer operation is done so that NT drivers of slave DMA devices can allocate the system DMA controller or a busmaster driver can begin processing the next transfer IRP promptly.