As its name implies, a ControllerControl routine is associated with an NT controller object. When the ControllerControl routine executes, the hardware represented by the controller object is free and the controller extension generally is not being accessed by another driver routine unless the controller extension contains context that is shared with the driver’s ISR.
Usually, a ControllerControl routine does at least the following:
If the driver uses DMA, its ControllerControl routine usually is responsible for determining whether a given transfer request must be split up into partial transfers due to any system- or device-imposed limitations on the size of each DMA transfer. In these circumstances, the ControllerControl routine also is responsible for calling IoAllocateAdapterChannel if the driver has an AdapterControl routine.
If the driver uses PIO, its ControllerControl routine also is responsible for splitting large transfer requests, if its hardware requires it, into partial-transfer ranges and for calling MmGetSystemAddressForMdl with the MDL at Irp->MdlAddress.
If the device or controller extension can be accessed from the ISR, the ControllerControl routine must call KeSynchronizeExecution with a SynchCritSection routine, described in Chapter 10, to program the hardware or to set up context shared with the ISR.
If the driver has a Cancel routine, its ControllerControl routine also must check the Irp->Cancel field to determine whether the current IRP should be cancelled, and do either of the following:
For more information about Cancel routines and handling cancelable IRPs, see Chapter 12.
For most interrupt-driven I/O operations except overlapped operations on different devices attached to the physical controller/adapter, a ControllerControl routine should return KeepObject because the DpcForIsr or CustomDpc routine completes the operation and the IRP.
As soon as the I/O operation(s) to satisfy the current request are done, the routine that will complete the IRP should call IoFreeController and IoStartNextPacket so that the next request can be processed as quickly as possible.
If the ControllerControl routine itself completes an IRP or if it can set up an operation, such as a disk seek, for one target device object (disk) that could be overlapped with an operation for another device object, the ControllerControl routine should return DeallocateObject.