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.

scsi_init_pkt() Function

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 function has the following syntax:

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

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

pktp

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

bp

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

cmdlen

Length of the SCSI command descriptor block in bytes.

statuslen

Required length of the SCSI status completion block in bytes.

privatelen

Number of bytes to allocate for the pkt_private field.

flags

Set of flags. Possible bits include:

  • PKT_CONSISTENT – This bit must be set if the DMA buffer was allocated using scsi_alloc_consistent_buf(9F). In this case, the host bus adapter driver guarantees that the data transfer is properly synchronized before performing the target driver's command completion callback.

  • PKT_DMA_PARTIAL – This bit can be set if the driver accepts a partial DMA mapping. If set, scsi_init_pkt(9F) allocates DMA resources with the DDI_DMA_PARTIAL flag set. The pkt_resid field of the scsi_pkt(9S) structure can be returned with a nonzero residual, indicating the number of bytes for which scsi_init_pkt(9F) was unable to allocate DMA resources.

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

Parameter to pass to the callback function.

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

scsi_sync_pkt() Function

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() after the transport.

scsi_destroy_pkt() Function

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.

scsi_alloc_consistent_buf() Function

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 that the driver itself examines (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; use it sparingly.


scsi_free_consistent_buf() Function

scsi_free_consistent_buf(9F) releases a buf(9S) structure and the associated data buffer allocated with scsi_alloc_consistent_buf(9F). See attach() Entry Point (SCSI Target Drivers) and detach() Entry Point (SCSI Target Drivers) for examples.