A.2.4 SCSI Filter Driver’s Dispatch Routines
Like any other higher-level kernel-mode driver, a SCSI filter driver must have one or more Dispatch routines to handle every IRP_MJ_XXX request for which the underlying SCSI class driver supplies a Dispatch entry point. Depending on the nature of its device, an SFD’s Dispatch entry point for any given request might do either of the following:
·For a request that requires no special handling, set up the I/O stack location in the IRP for the next-lower-level class driver, possibly call IoSetCompletionRoutine to set up its IoCompletion routine for the IRP, and pass the IRP on for further processing by lower drivers with IoCallDriver
·Or, set up a new IRP with an SRB and CDB for its device, call IoSetCompletionRoutine so the SRB (and the IRP if the driver calls IoAllocateIrp or IoBuildAsynchronousFsdRequest) can be freed, and pass the IRP on with IoCallDriver
An SFD is most likely to set up new IRPs with the major function code IRP_MJ_INTERNAL_DEVICE_CONTROL.
For requests that require no special handling, an SFD’s Dispatch routine usually calls IoGetNextIrpStackLocation with an input IRP, sets up the class driver’s I/O stack location and, then, calls IoCallDriver with pointers to the class driver’s device object and the IRP. Note that an SFD seldom sets its IoCompletion routine in IRPs that require no special handling both because a call to the IoCompletion routine is unnecessary and because it degrades I/O throughput for the SFD’s device(s).
For requests that do require special handling, the SFD can do the following:
1.Create a new IRP with IoBuildDeviceIoControlRequest, IoAllocateIrp, IoBuildSynchronousFsdRequest, or IoBuildAsynchronousFsdRequest, usually specifying an I/O stack location for itself.
2.Check the returned IRP pointer for NULL and return STATUS_INSUFFICIENT_RESOURCES if an IRP could not be allocated.
3.If the driver-created IRP includes an I/O stack location for the SFD, call IoSetNextIrpStackLocation to set up the IRP stack location pointer. Then, call IoGetCurrentIrpStackLocation to get a pointer to its own I/O stack location in the driver-created IRP and set up it up with state to be used by its own IoCompletion routine.
4.Call IoGetNextIrpStackLocation to get a pointer to the class driver’s I/O stack location in the driver-created IRP and set it up with the major function code IRP_MJ_SCSI and an SRB (see Sections A.1.4 through A.1.4.5).
5.Translate data to be transferred to the device into a device-specific, nonstandard format if necessary.
6.Call IoSetCompletionRoutine if the driver allocated any memory, such as memory for an SRB, SCSI request-sense buffer, MDL, and/or IRP with a call to IoAllocateIrp or IoBuildAsynchronousFsdRequest, or if the driver must translate data transferred from the device in a device-specific, nonstandard format.
7.Pass the driver-created IRP to (and through) the class driver with IoCallDriver.
Like a SCSI class driver, an SFD might have SCSI-specific BuildSrb or SplitTransferRequest routines to be called from the driver’s Dispatch routine(s), or might implement the same functionality inline.
For more information about BuildSrb and SplitTransferRequest routines, see Sections A.1.4.4 and A.1.4.5. For more information about general requirements for Dispatch routines, see Chapter 6.