3.4.2 Allocating the Controller Object for I/O Operations

After a driver that uses a controller object has initialized, it is ready to process IRPs sent to its target device objects. Whenever the current IRP requires the driver to program the physical device represented by the controller object for an I/O operation, the driver calls IoAllocateController. Figure 3.14 illustrates such a call.

Figure 3.14 Allocating a Controller Object for I/O

As Figure 3.14 shows, a driver must supply more than the ControllerObject pointer that was returned by IoCreateController when it calls IoAllocateController. Along with this pointer, it must pass pointers to the device object representing the target of the current I/O request, to a driver-supplied ControllerControl routine, and to whatever Context its ControllerControl routine will need to set up the device for the requested I/O operation.

IoAllocateController queues the driver-supplied ControllerControl routine if the device represented by the controller object is already busy doing I/O for a target device object. Otherwise, the ControllerControl routine is called immediately with the input parameters shown in Figure 3.14. The input Context pointer to IoAllocateController is passed to the driver’s ControllerControl routine when it is run.

    Consider the following design guidelines to determine the location of such a context area:

The I/O Manager passes a pointer to the DeviceObject->CurrentIrp to a ControllerControl routine if the driver has a StartIo routine. If, like the system-supplied floppy driver described in Chapter 2, a driver manages its own queuing of IRPs instead of having a StartIo routine, the I/O Manager cannot give the ControllerControl routine a pointer to the current IRP. When it calls IoAllocateController, such a driver should include the current IRP as part of the Context-accessible data it passes.

The driver routine that calls IoAllocateController must be executing at IRQL DISPATCH_LEVEL when the call occurs. A driver that makes this call from its StartIo routine is already running at DISPATCH_LEVEL. For more information about the IRQLs at which NT drivers’ standard routines execute, see Chapters 5 through 15 or the section on managing IRQLs in Chapter 16. For more information about support-routine-specific IRQL requirements, see the Kernel-Mode Driver Reference.

The ControllerControl routine sets up the physical controller for the IRP’s requested operation.

As shown in Figure 3.14, the ControllerControl routine returns a value of type IO_ALLOCATION_ACTION, which can be either of the following system-defined values:

When a ControllerControl routine returns KeepObject, usually the driver’s ISR runs when the device interrupts, and its DpcForIsr routine completes the I/O operation and the current IRP for the target device object.

Whenever the ControllerControl routine returns KeepObject, the routine that completes the IRP must call IoFreeController. Such a driver routine should call IoFreeController as soon as possible so that its next device I/O operation can be set up promptly.