6.3.4.3  Dispatch(Internal)DeviceControl in Class/Port Drivers

The higher-level driver of a class/port pair can sometimes complete IRPs in its DispatchDeviceControl routine. For example, if a class driver gathers and stores information about the features of the underlying device during initialization, which might be sought in a subsequent IRP_MJ_DEVICE_CONTROL request, that class driver might satisfy such a request without passing it on to the underlying device driver to save processing time. Depending on the designer, a class driver also might check the IRP’s parameters for its paired port driver so that it could send down only requests with valid parameters.

Closely coupled class/port drivers also can define a set of driver- and/or device-specific I/O control codes that the class driver uses to set up IRPs for IRP_MJ_INTERNAL_DEVICE_CONTROL requests to the port driver.

For example, the system keyboard and mouse class drivers send system-defined internal device control requests to enable/disable keyboard/mouse interrupts to the underlying port driver(s) from each class driver’s DispatchCreateClose routine. These system class drivers handle IRP_MJ_DEVICE_CONTROL requests by setting up IRP_MJ_INTERNAL_DEVICE_CONTROL requests for an underlying port driver. Any new keyboard or mouse port driver that interoperates with these system class drivers also must support these public internal device control requests.

The system parallel class/port driver model has similar features. New parallel class drivers can get support from the system parallel port driver by setting up IRPs for IRP_MJ_INTERNAL_DEVICE_CONTROL requests with public IOCTL_PARALLEL_PORT_XXX control codes. NT driver writers can replace the system parallel port driver, but such a new driver also must support this set of public internal device control requests.

For more information about these public internal device control requests and about how to define private I/O control codes for new class/port drivers, see the Kernel-mode Driver Reference.

For a closely coupled pair of port/class drivers, the class driver might handle the processing of certain device control requests without passing them on to the port driver. The designer of a new class/port driver pair can implement the class driver’s DispatchDeviceControl routine to do either of the following:

·Check the validity of the parameters in its own I/O stack location in the IRP, set the I/O status block if it finds any parameter errors, and call IoCompleteRequest with the IRP and a PriorityBoost of IO_NO_INCREMENT; otherwise, call IoGetNextIrpStackLocation, copy its own I/O stack location into the port driver’s, and pass the IRP on with IoCallDriver.

·Or, do nothing more than set up the port driver’s I/O stack location in the IRP without checking parameters and pass it on to the port driver for processing.

NT SCSI class drivers have special requirements for handling device control requests. For more information about these requirements, see Appendix A.