SCSI_INIT_PKT(9F) | Kernel Functions for Drivers | SCSI_INIT_PKT(9F) |
scsi_init_pkt - prepare a complete SCSI packet
#include <sys/scsi/scsi.h> 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);
illumos DDI specific (illumos DDI).
ap
pktp
bp
cmdlen
statuslen
0
1
sizeof(scsi_arq_status)
For extra sense packets (PKT_XARQ flag asserted), set statuslen to be a greater number like, (N + sizeof(struct scsi_arq_status)) where N is the number of extra bytes beyond the default 20. For example, N=1 requests 21 bytes of sense, N=235 asks for 255 bytes.
privatelen
flags
callback
arg
Target drivers use scsi_init_pkt() to request the transport layer to allocate and initialize a packet for a SCSI command which possibly includes a data transfer. If pktp is NULL, a new scsi_pkt(9S) is allocated using the HBA driver's packet allocator. The bp is a pointer to a buf(9S) structure. If bp is non-NULL and contains a valid byte count, the buf(9S) structure is also set up for DMA transfer using the HBA driver DMA resources allocator. When bp is allocated by scsi_alloc_consistent_buf(9F), the PKT_CONSISTENT bit must be set in the flags argument to ensure proper operation. If privatelen is non-zero then additional space is allocated for the pkt_private area of the scsi_pkt(9S). On return pkt_private points to this additional space. Otherwise pkt_private is a pointer that is typically used to store the bp during execution of the command. In this case pkt_private is NULL on return.
The flags argument is a set of bit flags. Possible bits include:
PKT_CONSISTENT
PKT_DMA_PARTIAL
PKT_XARQ
When calling scsi_init_pkt() to move already-allocated DMA resources, the cmdlen, statuslen, and privatelen fields are ignored.
The last argument arg is supplied to the callback function when it is invoked.
callback indicates what the allocator routines should do when resources are not available:
NULL_FUNC
SLEEP_FUNC
Other Values
When allocating DMA resources, scsi_init_pkt() returns the scsi_pkt field pkt_resid as the number of residual bytes for which the system was unable to allocate DMA resources. A pkt_resid of 0 means that all necessary DMA resources were allocated.
The scsi_init_pkt() function returns NULL if the packet or DMA resources could not be allocated. Otherwise, it returns a pointer to an initialized scsi_pkt(9S). If pktp was not NULL the return value will be pktp on successful initialization of the packet.
If callback is SLEEP_FUNC, then this routine can be called only from user-level code. Otherwise, it can be called from user, interrupt, or kernel context. The callback function may not block or call routines that block.
Example 1 Allocating a Packet Without DMA Resources Attached
To allocate a packet without DMA resources attached, use:
pkt = scsi_init_pkt(&devp->sd_address, NULL, NULL, CDB_GROUP1,
1, sizeof (struct my_pkt_private *), 0,
sd_runout, sd_unit);
Example 2 Allocating a Packet With DMA Resources Attached
To allocate a packet with DMA resources attached use:
pkt = scsi_init_pkt(&devp->sd_address, NULL, bp, CDB_GROUP1,
sizeof(struct scsi_arq_status), 0, 0, NULL_FUNC, NULL);
Example 3 Attaching DMA Resources to a Preallocated Packet
To attach DMA resources to a preallocated packet, use:
pkt = scsi_init_pkt(&devp->sd_address, old_pkt, bp, 0,
0, 0, 0, sd_runout, (caddr_t) sd_unit);
Example 4 Allocating a Packet with Consistent DMA Resources Attached
Since the packet is already allocated, the cmdlen, statuslen and privatelen are 0. To allocate a packet with consistent DMA resources attached, use:
bp = scsi_alloc_consistent_buf(&devp->sd_address, NULL, SENSE_LENGTH, B_READ, SLEEP_FUNC, NULL); pkt = scsi_init_pkt(&devp->sd_address, NULL, bp, CDB_GROUP0,
sizeof(struct scsi_arq_status), sizeof (struct my_pkt_private *),
PKT_CONSISTENT, SLEEP_FUNC, NULL);
Example 5 Allocating a Packet with Partial DMA Resources Attached
To allocate a packet with partial DMA resources attached, use:
my_pkt = scsi_init_pkt(&devp->sd_address, NULL, bp, CDB_GROUP0,
1, sizeof (struct buf *), PKT_DMA_PARTIAL,
SLEEP_FUNC, NULL);
scsi_alloc_consistent_buf(9F), scsi_destroy_pkt(9F), scsi_dmaget(9F), scsi_pktalloc(9F), buf(9S), scsi_address(9S), scsi_pkt(9S)
Writing Device Drivers
If a DMA allocation request fails with DDI_DMA_NOMAPPING, the B_ERROR flag will be set in bp, and the b_error field will be set to EFAULT.
If a DMA allocation request fails with DDI_DMA_TOOBIG, the B_ERROR flag will be set in bp, and the b_error field will be set to EINVAL.
May 24, 2014 | OmniOS |