Writing Device Drivers

Auto-Request Sense Mode

Auto-request sense mode is most desirable if tagged or untagged queuing is used. A contingent allegiance condition is cleared by any subsequent command and, consequently, the sense data is lost. Most HBA drivers will start the next command before performing the target driver callback. Other HBA drivers may use a separate and lower-priority thread to perform the callbacks, which may increase the time it takes to notify the target driver that the packet completed with a check condition. In this case, the target driver may not be able to submit a request sense command in time to retrieve the sense data.

To avoid this loss of sense data, the HBA driver, or controller, should issue a request sense command as soon as a check condition has been detected; this mode is known as auto-request sense mode. Note that not all HBA drivers are capable of auto-request sense mode, and some can only operate with auto-request-sense mode enabled.

A target driver enables auto-request-sense mode by using scsi_ifsetcap(9F). Example 13-6 shows enabling auto request sense.

Example 13-6 Enabling Auto Request Sense

static int
xxattach(dev_info_t *dip, ddi_attach_cmd_t cmd)
	struct xxstate *xsp;
	struct scsi_device *sdp = (struct scsi_device *)
	 * enable auto-request-sense; an auto-request-sense cmd may
	 * due to a BUSY condition or transport error. Therefore, it is
	 * recommended to allocate a separate request sense packet as
	 * well.
	 * Note that scsi_ifsetcap(9F) may return -1, 0, or 1
	xsp->sdp_arq_enabled =
	    ((scsi_ifsetcap(ROUTE, "auto-rqsense", 1, 1) == 1) ? 1 :
	 * if the HBA driver supports auto request sense then the
	 * status blocks should be sizeof (struct scsi_arq_status);
	 * one byte is sufficient
	xsp->sdp_cmd_stat_size =  (xsp->sdp_arq_enabled ?
	    sizeof (struct scsi_arq_status) : 1);

When a packet is allocated using scsi_init_pkt(9F) and auto request sense is desired on this packet then the target driver must request additional space for the status block to hold the auto request sense structure (as Example 13-7 illustrates). The sense length used in the request sense command is sizeof (struct scsi_extended_sense).

The scsi_arq_status structure contains the following members:

	struct scsi_status					sts_status;
 	struct scsi_status					sts_rqpkt_status;
 	u_char					sts_rqpkt_reason;	/* reason completion */
 	u_char					sts_rqpkt_resid;	/* residue */
 	u_int					sts_rqpkt_state;	/* state of command */
 	u_int					sts_rqpkt_statistics;	/* statistics */
 	struct scsi_extended_sense sts_sensedata;

Auto request sense can be disabled per individual packet by just allocating sizeof (struct scsi_status) for the status block.

Example 13-7 Allocating a Packet With Auto Request Sense

	pkt = scsi_init_pkt(ROUTE, NULL, bp, CDB_GROUP1,
	    xsp->sdp_cmd_stat_size, PP_LEN, 0, func, (caddr_t) xsp);

The packet is submitted using scsi_transport(9F) as usual. When a check condition occurs on this packet, the host adapter driver:

The target driver's callback routine should verify that sense data is available by checking the STATE_ARQ_DONE bit in pkt_state, which implies that a check condition has occurred and a request sense has been performed. If auto-request-sense has been temporarily disabled in a packet, there is no guarantee that the sense data can be retrieved at a later time.

The target driver should then verify whether the auto request sense command completed successfully and decode the sense data.

Example 13-8 Checking for Auto Request Sense

static void
xxcallback(struct scsi_pkt *pkt)
	if (pkt->pkt_state & STATE_ARQ_DONE) {
		    * The transport layer successfully completed an
		    * auto-request-sense.
		    * Decode the auto request sense data here