Writing Device Drivers

Resource Allocation

To send a SCSI command to the device, the target driver must create and initialize a scsi_pkt(9S) structure and pass it to the host bus adapter driver.


The scsi_init_pkt(9F) routine allocates and zeros a scsi_pkt(9S) structure; it also sets pointers to pkt_private, *pkt_scbp, and *pkt_cdbp. Additionally, it provides a callback mechanism to handle the case where resources are not available. This structure contains the following fields:

	struct scsi_pkt *scsi_init_pkt(struct scsi_address *ap,
 		struct scsi_pkt *pktp, struct buf *bp, int cmdlen,
 		int statuslen, int privatelen, int flags,
 		int (*callback)(caddr_t), caddr_t arg)

ap is a pointer to a scsi_address structure. This is the sd_address field of the device's scsi_device(9S) structure.

pktp is a pointer to the scsi_pkt(9S) structure to be initialized. If this is set to NULL, a new packet is allocated.

bp is a pointer to a buf(9S) structure. If this is non-NULL and contains a valid byte count, DMA resources are allocated.

cmdlen is the length of the SCSI command descriptor block in bytes.

statuslen is the required length of the SCSI status completion block in bytes.

privatelen is the number of bytes to allocate for the pkt_private field. To store a pointer, specify the size of the pointer here (such as sizeof(struct xxstate *) when storing a pointer to the state structure).

flags is a set of flags. Possible bits include:

callback specifies the action to take if resources are not available. If set to NULL_FUNC, scsi_init_pkt(9F) returns immediately (returning NULL). If set to SLEEP_FUNC, it does not return until resources are available. Any other valid kernel address is interpreted as the address of a function to be called when resources are likely to be available.

arg is the parameter to pass to the callback function.

The scsi_init_pkt(9F) routine synchronizes the data prior to transport. If the driver needs to access the data after transport, the scsi_sync_pkt(9F) routine can be used to synchronize any cached data.

The scsi_destroy_pkt(9F) routine synchronizes any remaining cached data associated with the packet, if necessary, and then frees the packet and associated command, status, and target driver-private data areas. This routine should be called in the command completion routine.

If the target driver needs to resubmit the packet after changing the data, scsi_sync_pkt(9F) must be called before calling scsi_transport(9F). However, if the target driver does not need to access the data, there is no need to call scsi_sync_pkt(9F) after the transport.


For most I/O requests, the data buffer passed to the driver entry points is not accessed directly by the driver, it is just passed on to scsi_init_pkt(9F). If a driver sends SCSI commands that operate on buffers the driver examines itself (such as the SCSI request sense command), the buffers should be DMA consistent. The scsi_alloc_consistent_buf(9F) routine allocates a buf(9S) structure and a data buffer suitable for DMA-consistent operations. The HBA will perform any necessary synchronization of the buffer before performing the command completion callback.

Caution - Caution -

scsi_alloc_consistent_buf(9F) uses scarce system resources; it should be used sparingly.

scsi_free_consistent_buf(9F) releases a buf(9S) structure and the associated data buffer allocated with scsi_alloc_consistent_buf(9F). See "attach(9E)" and "detach(9E)"for examples.