A.1.5 SCSI Class Driver's IoCompletion Routines
As mentioned in Section A.1.4.4, SCSI class drivers are responsible for freeing the memory they allocate for SRBs. Like any other higher-level kernel-mode driver, they are also responsible for releasing any IRPs that they allocate, such as an IRP to split up a transfer request as described in the preceding section.
A class driver's IoCompletion routine is ultimately responsible for ensuring that the I/O status block is set and for completing the original IRP. Note that completing an IRP can include translating an error returned in the SRB's ScsiStatus member or SrbSenseInfoBuffer into an NTSTATUS-type value and/or logging an error, as described in Chapter 16.
SCSI class drivers must have one or more IoCompletion routines, unless a particular driver waits on the completion of every IRP it sends to the port driver, retries requests as necessary, and releases memory for SRBs from a Dispatch or BuildSrb routine. Note that handling every IRP as such a synchronous request would degrade the performance of any class driver. Furthermore, SCSI class drivers for devices that might hold the system page file must handle all transfer requests asynchronously. Such a class driver must have an IoCompletion routine for read/write requests.
When certain kinds of errors occur in processing a request, the system port driver freezes its internal queue for the target LU. Consequently, class drivers usually have internal routines to change the status of the queue for their device I/O requests. For more information about class drivers' ReleaseQueue routines, see Section A.1.5.1.
If the driver's BuildSrb routine requested that the port driver return request-sense information for a request, its IoCompletion routine either calls an InterpretRequestSense routine or implements the same functionality inline. For more information about InterpretRequestSense routines, see Section A.1.5.2.
As mentioned in Section A.1.4.4, SCSI class drivers are responsible for retrying requests that fail due to target controller errors, bus resets, or request time-outs. When the port driver returns a particular request with its SrbStatus set to indicate such an error, the class driver can call a RetryRequest routine from its IoCompletion routine or, possibly, from the InterpretRequestSense routine. For more information about RetryRequest routines, see Section A.1.5.3.
For more information about general requirements for IoCompletion routines, see Chapter 13.