A.1.4.4 SCSI Class Driver's BuildSrb Routine

Like all higher-level kernel-mode drivers, a SCSI class driver must set up the IRP's I/O stack location for the next-lower-level driver. In IRPs that the class driver sets up with SRBs for the system-supplied port driver, the port driver's I/O stack location is set with the following:

·IRP_MJ_SCSI is the major function code.

·Parameters.Scsi.Srb contains a pointer to the SRB.

Each class driver is responsible for allocating memory for SRBs as well as for setting them up with CDBs for the underlying port-miniport drivers. The class driver can either call ExAllocatePool for nonpaged memory or can set up a resident zone buffer for its SRBs. For more information about using nonpaged pool and zones, see Chapter 16.

Whether it allocates memory from pool or from a driver-created zone buffer, every SCSI class driver is responsible for freeing the memory it allocates for SRBs. SCSI class drivers' IoCompletion routines, described in Section A.1.5, usually free the memory allocated for SRBs.

A class driver's BuildSrb routine must set appropriate values in the SRB members, including the length of the CDB it has set up to communicate with its device. For requests that return request-sense information and/or that the driver might need to retry, it sets an IoCompletion routine in the IRP. For read or write requests, it ORs the SrbFlags with the appropriate transfer direction, SRB_FLAGS_DATA_IN or SRB_FLAGS_DATA_OUT, respectively.

A BuildSrb routine might split the responsibility for setting up an SRB with a pair of SendSrbSynchronous and SendSrbAsynchronous routines. That is, the BuildSrb routine could set up the SRB members that are commonly set up for all requests, while the SendSrbXxx routines each set SRB values pertinent only to each type of SCSI request. When an IRP is passed down to the port driver from a SendSrbAsynchronous routine, the IRP must be set up with a driver-supplied IoCompletion routine.

After the class driver has loaded, it sets up most SRBs with the Function member set to SRB_FUNCTION_EXECUTE_SCSI, indicating a device I/O request to be sent over the bus.

For more information about the system-defined SRB members and their values, see also the Kernel-Mode Driver Reference.

Setting Up SRBs for Request Sense

A class driver can request that the port driver perform a SCSI-II request-sense operation when the target controller returns a check condition. To do this, the class driver sets up the SenseInfoBuffer pointer and SenseInfoBufferLength in the SRB, so the port driver can return the request-sense information if a check condition occurs. The port driver indicates that it returned request-sense information by setting the SrbStatus member with SRB_STATUS_AUTOSENSE_VALID when it returns the IRP. For more information about InterpretRequestSense routines, see Section A.1.5.2.

Retries

SCSI class drivers are responsible for retrying requests that fail due to target controller errors, bus resets, or request time-outs. Consequently, many class drivers maintain a retry count in their own I/O stack location of the IRP. Such a class driver's BuildSrb routine also might initialize the retry limit for a given request before it sets up its IoCompletion routine and sends the IRP to the port driver. For more information about RetryRequest routines, see Section A.1.5.3.