Writing Device Drivers

Declarations and Data Structures

Target drivers must include the header file <sys/scsi/scsi.h>.

SCSI target drivers must also include this declaration:

	char _depends_on[] = "misc/scsi";

scsi_device Structure

The host bus adapter driver allocates and initializes a scsi_device(9S) structure for the target driver before either the probe(9E) or attach(9E) routine is called. This structure stores information about each SCSI logical unit, including pointers to information areas that contain both generic and device- specific information. There is one scsi_device(9S) structure for each logical unit attached to the system. The target driver can retrieve a pointer to this structure by calling ddi_get_driver_private(9F).

Caution - Caution -

Because the host bus adapter driver uses the private field in the target device's dev_info structure, target drivers should not use ddi_set_driver_private(9F).

The scsi_device(9S) structure contains the following fields:

		struct scsi_address 				sd_address;			
 	dev_info_t								*sd_dev;			
 	kmutex_t									sd_mutex;
 	struct scsi_inquiry					*sd_inq;
 	struct scsi_extended_sense 		*sd_sense;
 	caddr_t									sd_private;						

sd_address is a data structure that is passed to the SCSI resource allocation routines.

sd_dev is a pointer to the target's dev_info structure.

sd_mutex is a mutex for use by the target driver. This is initialized by the host bus adapter driver and can be used by the target driver as a per-device mutex. Do not hold this mutex across a call to scsi_transport(9F) or scsi_poll(9F). See Chapter 4, Multithreading, for more information on mutexes.

sd_inq is a pointer for the target device's SCSI inquiry data. The scsi_probe(9F) routine allocates a buffer, fills it in, and attaches it to this field.

sd_sense is a pointer to a buffer to contain SCSI request sense data from the device. The target driver must allocate and manage this buffer itself; see "attach(9E)".

sd_private is a pointer field for use by the target driver. It is commonly used to store a pointer to a private target driver state structure.

scsi_pkt Structure

This structure contains the following fields:

		struct scsi_address		pkt_address;
 	opaque_t						pkt_private;
 	void							(*pkt_comp)(struct scsi_pkt *pkt);
 	u_int							pkt_flags;
 	int							pkt_time;
 	u_char						*pkt_scbp;
 	u_char						*pkt_cdbp;
 	ssize_t						pkt_resid;
 	u_int							pkt_state;
 	u_int							pkt_statistics;
 	u_char						pkt_reason;

pkt_address is the target device's address set by scsi_init_pkt(9F)

pkt_private is a place to store private data for the target driver. It is commonly used to save the buf(9S) pointer for the command.

pkt_comp is the address of the completion routine. The host bus adapter driver calls this routine when it has transported the command. This does not mean that the command succeeded; the target might have been busy or might not have responded before the time-out time elapsed (see the description for pkt_time field). The target driver must supply a valid value in this field, though it can be NULL if the driver does not want to be notified.

Note -

There are two different SCSI callback routines. The pkt_comp field identifies a completion callback routine, which is called when the host bus adapter completes its processing. There is also a resource callback routine, called when currently unavailable resources are likely to be available (as in scsi_init_pkt(9F)).

pkt_flags provides additional control information, for example, to transport the command without disconnect privileges (FLAG_NODISCON) or to disable callbacks (FLAG_NOINTR). See scsi_pkt(9S) for details.

pkt_time is a time-out value (in seconds). If the command is not completed within this time, the host bus adapter calls the completion routine with pkt_reason set to CMD_TIMEOUT. The target driver should set this field to longer than the maximum time the command might take. If the timeout is zero, no timeout is requested. Timeout starts when the command is transmitted on the SCSI bus.

pkt_scbp is a pointer to the SCSI status completion block; this is filled in by the host bus adapter driver.

pkt_cdbp is a pointer to the SCSI command descriptor block, the actual command to be sent to the target device. The host bus adapter driver does not interpret this field. The target driver must fill it in with a command that the target device can process.

pkt_resid is the residual of the operation. When allocating DMA resources for a command scsi_init_pkt(9F), pkt_resid indicates the number of bytes for which DMA resources could not be allocated because of DMA hardware scatter-gather or other device limitations. After command transport, pkt_resid indicates the number of data bytes not transferred; this is filled in by the host bus adapter driver before the completion routine is called.

pkt_state indicates the state of the command. The host bus adapter driver fills in this field as the command progresses. One bit is set in this field for each of the five following command states:

pkt_statistics contains transport-related statistics set by the host bus adapter driver.

pkt_reason gives the reason the completion routine was called. The main function of the completion routine is to decode this field and take the appropriate action. If the command completed--in other words, if there were no transport errors--this field is set to CMD_CMPLT; other values in this field indicate an error. After a command is completed, the target driver should examine the pkt_scbp field for a check condition status. See scsi_pkt(9S) for more information.

SCSI Additions to the State Structure

This section adds the following fields to the state structure. See "Software State Structure" for more information.

struct scsi_pkt					*rqs;			/* Request Sense packet */
struct buf							*rqsbuf;		/* buf for Request Sense */
struct scsi_pkt					*pkt;			/* packet for current command */
struct scsi_device				*sdp;			/* pointer to device's */
 														/* scsi_device(9S) structure. */

rqs is a pointer to a SCSI request sense command scsi_pkt(9S) structure, allocated in the attach(9E) routine. This packet is preallocated because the request sense command is small and may be used in time-critical areas of the driver (such as when handling errors).