SCSI_INIT_PKT(9F) Kernel Functions for Drivers SCSI_INIT_PKT(9F)
NAME
scsi_init_pkt - prepare a complete SCSI packet
SYNOPSIS
#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);
INTERFACE LEVEL
illumos DDI specific (illumos DDI).
PARAMETERS
ap Pointer to a
scsi_address(9S) structure.
pktp A pointer to a
scsi_pkt(9S) structure.
bp Pointer to a
buf(9S) structure.
cmdlen The required length for the
SCSI command descriptor block (
CDB)
in bytes.
statuslen The required length for the
SCSI status completion block (
SCB) in
bytes. Valid values are:
0 No status back.
1 Return SCSI status byte.
sizeof(scsi_arq_status) Return status information in a
scsi_arq_status structure.
This will include up to 20 bytes of sense data. Please refer
to
scsi_arq_status(9S) for more information.
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 The required length for the
pkt_private area.
flags Flags modifier.
callback A pointer to a callback function,
NULL_FUNC, or
SLEEP_FUNC.
arg The
callback function argument.
DESCRIPTION
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 This must be set if the
DMA buffer was allocated using
scsi_alloc_consistent_buf(9F). In this case, the
HBA driver will
guarantee that the data transfer is properly synchronized before
performing the target driver's command completion callback.
PKT_DMA_PARTIAL This may be set if the driver can accept a partial
DMA mapping.
If set,
scsi_init_pkt() will allocate
DMA resources with the
DDI_DMA_PARTIAL bit set in the DMA flags. The
pkt_resid field of
the
scsi_pkt(9S) structure may be returned with a non-zero value,
which indicates the number of bytes for which
scsi_init_pkt() was
unable to allocate DMA resources. In this case, a subsequent call
to
scsi_init_pkt() may be made for the same
pktp and
bp to adjust
the DMA resources to the next portion of the transfer. This
sequence should be repeated until the
pkt_resid field is returned
with a zero value, which indicates that with transport of this
final portion the entire original request will have been
satisfied.
PKT_XARQ Setting this flag requests that the
HBA return extra sense data
for this
scsi_pkt(9S). The default auto request sense mechanism
returns up to 20 bytes. More than 20 bytes of sense data can be
requested by setting this flag and setting the
statuslen correctly. Set the
statuslen to be the
sizeof(struct scsi_arq_status) plus the number of sense bytes needed beyond 20.
For example, set statuslen to be
(sizeof(struct scsi_arq_status) + 5) for 25 bytes of sense.
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 Do not wait for resources. Return a
NULL pointer.
SLEEP_FUNC Wait indefinitely for resources.
Other Values callback points to a function which is called when
resources may have become available.
callback must
return either
0 (indicating that it attempted to
allocate resources but again failed to do so), in
which case it is put back on a list to be called
again later, or
1 indicating either success in
allocating resources or indicating that it no longer
cares for a retry.
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.
RETURN VALUES
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.
CONTEXT
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.
EXAMPLES
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);
SEE ALSO
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 DriversNOTES
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 SCSI_INIT_PKT(9F)