DOC HOME SITE MAP MAN PAGES GNU INFO SEARCH PRINT BOOK
 
TOC PREV NEXT INDEX

SCSI Metalanguage Interfaces

3

3.1 Introduction

This chapter specifies the channel operations and service calls of the SCSI Metalanguage. The SCSI Metalanguage defines the operations through which a SCSI peripheral driver (PD) communicates with a SCSI HBA driver (HD) and vice-versa. Subsections define the various channel operations' arguments, control block structures, constraints and guidelines for the use of each operation, along with any error conditions that can occur.

The SCSI Metalanguage operations are grouped into two roles: one for operations called by a PD to send an operation to the HD, and one for operations that are sent from the HD to the PD. Each role has a single channel ops vector. The PD-to-HD operations are called by a peripheral driver to request a service from the HBA driver, acknowledge an event from the HBA driver, or bind to the HBA driver. The HD-to-PD operations are called by an HBA driver to return completion information to the peripheral driver, to notify the peripheral driver of an asynchronous event, or to acknowledge a binding.

The only SCSI Metalanguage operation that is abortable with udi_channel_op_abort is udi_scsi_io_req. The only recoverable operations are udi_scsi_io_req and udi_scsi_ctl_req (see section 4.10 of the UDI Core Specification for a description of recoverable operations).

3.2 Overview of Interfaces and Data Structures

Channel operations in UDI are driver-callable functions that are used to communicate between driver modules. As alluded to above, there are two sets of channel operations in the SCSI Metalanguage which are distinguishable by the direction of communication: PD-to-HD operations are callable only by the PD, and HD-to-PD operations are callable only by the HD. Associated with each channel operation is a corresponding driver entry point in the target driver. Thus PD-to-HD operations are callable by PDs while HDs contain a corresponding driver entry point; and the reverse is true for HD-to-PD operations. Each driver registers its SCSI entry points by initializing a udi_ops_init_t in its udi_init_info to point to the driver's ops vector.

3.3 Control Blocks

The SCSI Metalanguage contains four types of control blocks for inter-driver communication: a bind control block for SCSI bind and unbind operations, an io control block for normal I/O requests on the SCSI interconnect, a ctl control block for control functions, and an event control block for asynchronous event notification and acknowledgment. These correspond to the four control block groups in the SCSI Metalanguage, one for each type of control block.

Control blocks contain space for an associated driver scratch area whose size requirement is specified in a corresponding udi_cb_init_t structure as part of udi_init_info. Access to the driver scratch area associated with a SCSI control block is provided via the scratch pointer in the gcb field at the front of the control block. This scratch area may be used for driver internal queuing, per-request state, or any other driver-specific purpose.

3.4 Status Codes

The following SCSI-specific status code values are defined in the SCSI Metalanguage. The semantic definitions of these statuses are given in the reference page where the status is used with a given operation or structure. The code values are consolidated here to simplify keeping the codes unique and to reduce clutter in the rest of the document. The value MS is replaced with UDI_STAT_META_SPECIFIC in each #define below.

/* SCSI I/O NAK status codes */
 
#define UDI_SCSI_STAT_NONZERO_STATUS_BYTE (1|MS)
#define UDI_SCSI_STAT_ACA_PENDING (2|MS)
#define UDI_SCSI_STAT_NOT_PRESENT (3|MS)
#define UDI_SCSI_STAT_DEVICE_PHASE_ERROR (4|MS)
#define UDI_SCSI_STAT_UNEXPECTED_BUS_FREE (5|MS)
#define UDI_SCSI_STAT_DEVICE_PARITY_ERROR (6|MS)
#define UDI_SCSI_STAT_ABORTED_HD_BUS_RESET (7|MS)
#define UDI_SCSI_STAT_ABORTED_RMT_BUS_RESET (8|MS)
#define UDI_SCSI_STAT_ABORTED_REQ_BUS_RESET (9|MS)
#define UDI_SCSI_STAT_ABORTED_REQ_TGT_RESET (10|MS)
#define UDI_SCSI_STAT_LINK_FAILURE (11|MS)
#define UDI_SCSI_STAT_SELECTION_TIMEOUT (12|MS)
#define UDI_SCSI_STAT_HD_ABORTED (13|MS)

 
/* SCSI Ctl Ack status codes */
 
#define UDI_SCSI_CTL_STAT_FAILED (100|MS)

3.5 Channel Ops Vectors

This section defines the channel ops vector types for use with the SCSI Metalanguage. There are two ops vector types in the SCSI Metalanguage: one that a PD uses on its end of a SCSI channel (udi_scsi_pd_ops_t) and one that an HD uses on its end of a SCSI channel (udi_scsi_hd_ops_t).

NAME udi_scsi_pd_ops_t

SCSI Peripheral Driver entry point ops vector

SYNOPSIS

#include <udi.h>

typedef const struct {

	udi_channel_event_ind_op_t *channel_event_ind_op;

	udi_scsi_bind_ack_op_t *bind_ack_op;

	udi_scsi_unbind_ack_op_t *unbind_ack_op;

	udi_scsi_io_ack_op_t *io_ack_op;

	udi_scsi_io_nak_op_t *io_nak_op;

	udi_scsi_ctl_ack_op_t *ctl_ack_op;

	udi_scsi_event_ind_op_t *event_ind_op;

} udi_scsi_pd_ops_t;
 
/* Ops Vector Number */
 
#define  UDI_SCSI_PD_OPS_NUM				1
 

DESCRIPTION A SCSI Peripheral Driver uses the udi_scsi_pd_ops_t structure in a udi_ops_init_t as part of its udi_init_info in order to register its SCSI Metalanguage entry points.

EXAMPLE The driver's udi_init_info might include the following:

#define MY_SCSI_OPS 1 /* Ops for my SCSI HBA parent */

#define MY_OTHER_OPS 2 /* Some other ops */

#define MY_SCSI_META 1 /* Meta index for the SCSI Metalanguage */

static const udi_scsi_pd_ops_t ddd_scsi_pd_ops = {

	ddd_scsi_channel_event_ind,

	ddd_scsi_bind_ack,

	ddd_scsi_unbind_ack,

	ddd_scsi_io_ack,

	ddd_scsi_io_nak,

	ddd_scsi_ctl_ack,

	ddd_scsi_event_ind

};

...

static const udi_ops_init_t ddd_ops_init_list[] = {

	{	MY_SCSI_OPS,

		MY_SCSI_META,

		UDI_SCSI_PD_OPS_NUM,

		0, /* chan_context_size */

		(udi_ops_vector_t *)&ddd_scsi_pd_ops },

	{ 0 }

};
 

NAME udi_scsi_hd_ops_t

SCSI HBA Driver entry point ops vector

SYNOPSIS

#include <udi.h>

typedef const struct {

	udi_channel_event_ind_op_t *channel_event_ind_op;

	udi_scsi_bind_req_op_t *bind_req_op;

	udi_scsi_unbind_req_op_t *unbind_req_op;

	udi_scsi_io_req_op_t *io_req_op;

	udi_scsi_ctl_req_op_t *ctl_req_op;

	udi_scsi_event_res_op_t *event_res_op;

} udi_scsi_hd_ops_t;
 
/* Ops Vector Number */
 
#define  UDI_SCSI_HD_OPS_NUM				2
 

DESCRIPTION A SCSI HBA Driver uses the udi_scsi_hd_ops_t structure in a udi_ops_init_t as part of its udi_init_info in order to register its SCSI Metalanguage entry points.

EXAMPLE The driver's udi_init_info might include the following:

#define MY_BRIDGE_OPS 1 /* Ops for my parent bridge */

#define MY_SCSI_OPS   2 /* Ops for my SCSI PD children */

#define MY_SCSI_META  1 /* Meta index for the SCSI Metalanguage */

#define MY_BUS_META   2 /* Meta index for Bus Bridge Metalanguage */

static const udi_scsi_hd_ops_t ddd_scsi_hd_ops = {

	ddd_scsi_channel_event_ind,

	ddd_scsi_bind_req,

	ddd_scsi_unbind_req,

	ddd_scsi_io_req,

	ddd_scsi_ctl_req,

	ddd_scsi_event_res

};

...

static const udi_ops_init_t ddd_ops_init_list[] = {

	{	MY_SCSI_OPS,

		MY_SCSI_META,

		UDI_SCSI_HD_OPS_NUM,

		0, /* chan_context_size */

		(udi_ops_vector_t *)&ddd_scsi_hd_ops },

	{	MY_BRIDGE_OPS,

		MY_BUS_META,

		UDI_BUS_BRIDGE_OPS_NUM,

		0, /* chan_context_size */

		(udi_ops_vector_t *)&ddd_bus_bridge_ops },

	...

};
 

3.6 Binding Operations

Once the HD is bound to its parent, it can receive bindings for its PD children. As defined in "Driver Instantiation" on page 24-2 of the UDI Core Specification, this involves interaction with the Management Agent (MA) on the Management Channel and with the child PD directly on the newly created SCSI bind channel. The metalanguage-specific bind request and ack steps in that description in the Core Specification correspond to the udi_scsi_bind_req and udi_scsi_bind_ack operations. The udi_scsi_bind_req, sent by the PD to the HD, is the first operation passed on the SCSI bind channel. Once the HD has received and processed the udi_scsi_bind_req the HD must then call udi_scsi_bind_ack.

At this point the SCSI channel is "open for business" and any of the other SCSI operations may be performed on it. Note that the PD must not do a udi_scsi_bind_req to the HD after this point without an intervening udi_scsi_unbind_req.

When it binds with the HD, the PD may request exclusive access to its device via the UDI_SCSI_BIND_EXCLUSIVE flag. If the HD finds that there is another PD already bound to the device then it will fail the bind with UDI_STAT_CANNOT_BIND_EXCLUSIVE status. A PD may also request "temporary exclusive access" via the UDI_SCSI_TEMP_BIND_EXCLUSIVE flag even while other PDs are bound to the device, as long as none of them are bound exclusively. While the HD has a PD bound exclusively (via either of the two exclusive bind flags), it will reject all other binds to that PD's device with UDI_STAT_BOUND_EXCLUSIVELY.

NAME udi_scsi_bind_cb_t

Control block for SCSI bind operations

SYNOPSIS

#include <udi.h>

typedef struct {

	udi_cb_t gcb;

	udi_ubit16_t events;

} udi_scsi_bind_cb_t;
 
/* SCSI Events */
 
#define  UDI_SCSI_EVENT_AEN				(1U<<0)
 
#define  UDI_SCSI_EVENT_TGT_RESET				(1U<<1)
 
#define  UDI_SCSI_EVENT_BUS_RESET				(1U<<2)
 
#define  UDI_SCSI_EVENT_UNSOLICITED_RESELECT				(1U<<3)
 
/* Control Block Group Number */
 
#define UDI_SCSI_BIND_CB_NUM 1

MEMBERS gcb is a generic control block header, which includes a pointer to the scratch space associated with this control block. The driver may use the scratch space while it owns the control block, but the values are not guaranteed to persist across channel operations.

events is a set of SCSI event types. On the udi_scsi_bind_req the PD sets the events for which it wants to be notified. On the corresponding ack the HD masks off any requested events that it doesn't support, and passes back that (potentially smaller) set of events to the PD. An HD for a parallel SCSI bus must support UDI_SCSI_EVENT_TGT_RESET and UDI_SCSI_EVENT_BUS_RESET. The events field is ignored on SCSI unbind operations.

Note that if a SCSI event occurs which affects the PDs on a given LUN, any multi-lun PDs which have the event enabled will be notified along with the single-lun PDs attached to the LUN.

The following events are defined:

UDI_SCSI_EVENT_AEN - Asynchronous Event Notification. The HD will send notification to the PD when its device sends a SCSI AEN, which is typically used to send notification of out-of-band events - i.e., device events that occur outside the context of a SCSI command from this HD initiator. If the PD finds that the HD doesn't support receiving AENs (by noting that the HD has cleared this flag), then the PD must poll for events that it cares about. The PD must also poll if it determines that its device does not support SCSI AEN.

UDI_SCSI_EVENT_TGT_RESET - A reset on the SCSI target ID has occured (via a BDR or Target Reset). The HD will only deliver this event for a locally requested Target Reset (as opposed to a reset due to another initiator), and in that case it will only deliver the event to other PDs attached to the LUN than the one that requested the reset (which includes any multi-lun PDs).

UDI_SCSI_EVENT_BUS_RESET - A SCSI bus reset occurred.

UDI_SCSI_EVENT_UNSOLICITED_RESELECT - The PD's LUN generated an unsolicited re-selection.

DESCRIPTION The SCSI bind control block is used in udi_scsi_bind_req/ack and udi_scsi_unbind_req/ack operations.

In order to use this type of control block it must be associated with a control block index by including UDI_SCSI_BIND_CB_NUM in a udi_cb_init_t in the driver's udi_init_info.

REFERENCES udi_scsi_bind_req, udi_scsi_bind_ack, udi_scsi_unbind_req, udi_scsi_unbind_ack, udi_cb_alloc

NAME udi_scsi_bind_req

Request a SCSI binding (PD-to-HD)

SYNOPSIS

#include <udi.h>

void udi_scsi_bind_req (

	udi_scsi_bind_cb_t *cb,

	udi_ubit16_t bind_flags,

	udi_ubit16_t queue_depth,

	udi_ubit16_t max_sense_len,

	udi_ubit16_t aen_buf_size );
 
/* Bind Flags */
 
#define  UDI_SCSI_BIND_EXCLUSIVE				(1U<<0)
 
#define  UDI_SCSI_TEMP_BIND_EXCLUSIVE				(1U<<1)
 

ARGUMENTS cb is a pointer to a SCSI bind control block.

bind_flags contains flags restricting or qualifying this binding. The following flags are defined. At most one of UDI_SCSI_BIND_EXCLUSIVE and UDI_SCSI_TEMP_BIND_EXCLUSIVE must be set.

UDI_SCSI_BIND_EXCLUSIVE - Indicates that the PD wants to get an exclusive bind to the SCSI device (target/LUN) associated with this bind channel. The HD will respond with a status of UDI_SCSI_CANNOT_BIND_EXCLUSIVE if another PD is currently bound to the target/LUN.

UDI_SCSI_TEMP_BIND_EXCLUSIVE - Indicates that the PD wants "temporary exclusive access" to the device. If no PD is currently exclusively bound to the device the HD will grant this bind as follows: the HD will quiesce any other PDs bound to the device (transparently to those PDs), and will then ack back to this PD with UDI_OK status. Any requests which come in from other PDs while this PD has exclusive access will be queued until this PD unbinds.

      Drivers which bind with this flag must not remain bound any longer than the number of milliseconds specified by the %scsi_pd_max_temp_bind_excl attribute; failure to do so is considered illegal driver behavior which can result in the PD instance being killed.

queue_depth is the number of SCSI commands that the HD is allowed to have pending to the device simultaneously. This is used to avoid excessive queue-full statuses. The PD may change this value later using the UDI_SCSI_CTL_SET_QUEUE_DEPTH control request. Note that the HD must manage queue depth on a per-LUN basis, guaranteeing that the queue depth to the device (i.e., the minimum of the queue depths specified by PDs attached to a given LUN) is not exceeded. See Section 2.4.5, "Task/Queue Management" for additional details.

max_sense_len is the maximum sense data size required for the corresponding peripheral device. This sense data must be requested by the HD on behalf of the PD for all check conditions reported by the device. If max_sense_len is zero, the HD does not report the data to the PD.

Warning - While the HD is not required to request pending sense data from the device if max_sense_len is zero, it should do so, since not doing so could result in sense data building up on the device, particularly for multi-hosted devices.

aen_buf_size is the valid data size, in bytes, of AEN data buffers to be allocated by the HD and sent to the PD with each UDI_SCSI_EVENT_AEN event. If aen_buf_size is zero, no AEN buffers will be allocated.

aen_buf_size is ignored if the UDI_SCSI_EVENT_AEN event is either not supported by the HD or not enabled by the PD.

TARGET CHANNEL The target channel for this operation is the bind channel connecting a SCSI PD to its parent HD.

DESCRIPTION A SCSI PD uses this operation to bind to its parent HD.

The PD must prepare for the udi_scsi_bind_req operation by allocating a SCSI bind control block (calling udi_cb_alloc with a cb_idx that was previously associated with UDI_SCSI_BIND_CB_NUM). Next, the PD fills in the control block and sends it to the HD in a udi_scsi_bind_req operation.

The udi_scsi_bind_req operation must either be the first channel operation sent on the bind channel or the first operation since a SCSI unbind was done on the channel. The PD must not send any further operations on the bind channel until it receives the corresponding udi_scsi_bind_ack from the HD.

REFERENCES udi_scsi_bind_cb_t, udi_scsi_bind_ack

NAME udi_scsi_bind_ack

Acknowledge a SCSI bind request (HD-to-PD)

SYNOPSIS

#include <udi.h>

void udi_scsi_bind_ack (

	udi_scsi_bind_cb_t *cb,

	udi_ubit32_t hd_timeout_increase,

	udi_status_t status );
 

ARGUMENTS cb is a pointer to a SCSI bind control block.

hd_timeout_increase is the time in milliseconds by which the PD must increase its request timeouts to account for the HD's interconnect type to the PD. Failure to add this hd_timeout_increase value to the PD's device-specific timeout request may result in requests being timed out unnecessarily and in inordinate amounts.

status is the status of this SCSI bind.

TARGET CHANNEL The target channel for this operation is the bind channel connecting a SCSI HD to its child PD.

DESCRIPTION The udi_scsi_bind_ack operation is used by an HD to acknowledge binding with a child PD (or failure to do so, as indicated by status), as requested by a udi_scsi_bind_req operation.

STATUS VALUES UDI_OK indicates that the SCSI bind succeeded.

UDI_STAT_BOUND_EXCLUSIVELY  is returned by the HD to the PD to reject a bind because the device is bound exclusively by another PD and cannot therefore be bound by this PD.

UDI_STAT_CANNOT_BIND_EXCLUSIVE  is returned by the HD to the PD to reject a UDI_SCSI_BIND_EXCLUSIVE bind when one or more PDs are already bound to this device and cannot therefore be bound exclusively.

UDI_STAT_CANNOT_BIND  indicates that the HD cannot bind to this PD for some reason other than exclusivity.

UDI_STAT_ATTR_MISMATCH  indicates that the HD cannot adhere to one or more of the per-PD (parent-visible) attribute settings.

warnings The control block must be the same control block as passed to the HD in the corresponding udi_scsi_bind_req operation.

REFERENCES udi_scsi_bind_cb_t, udi_scsi_bind_req

3.7 Unbinding Operations

NAME udi_scsi_unbind_req

Request a SCSI unbind (PD-to-HD)

SYNOPSIS

#include <udi.h>

void udi_scsi_unbind_req (

	udi_scsi_bind_cb_t *cb );
 

ARGUMENTS cb is a pointer to a SCSI bind control block.

TARGET CHANNEL The target channel for this operation is the bind channel connecting a SCSI PD to its parent HD.

DESCRIPTION A SCSI PD uses this operation to unbind from its parent HD.

The PD must prepare for the udi_scsi_unbind_req operation by allocating a SCSI bind control block (calling udi_cb_alloc with a cb_idx that was previously associated with UDI_SCSI_BIND_CB_NUM). Next, the PD fills in the control block and sends it to the HD in a udi_scsi_unbind_req operation.

The PD may follow a SCSI unbind with another SCSI bind; the SCSI unbind in and of itself is not necessarily indicative of the PD instance going away.

REFERENCES udi_scsi_bind_cb_t, udi_scsi_unbind_ack

NAME udi_scsi_unbind_ack

Acknowledge a SCSI unbind (HD-to-PD)

SYNOPSIS

#include <udi.h>

void udi_scsi_unbind_ack (

	udi_scsi_bind_cb_t *cb );
 

ARGUMENTS cb is a pointer to a SCSI bind control block.

TARGET CHANNEL The target channel for this operation is the bind channel connecting a SCSI HD to its child PD.

DESCRIPTION The udi_scsi_unbind_ack operation is used by a SCSI HD to acknowledge unbinding from a child PD, as requested by a udi_scsi_unbind_req operation.

There is no status parameter associated with this operation; the HD is expected to always be able to handle the unbind request and respond appropriately. If, for example, the HD were to receive an unbind from a PD without having first received a bind (or two unbinds in a row from the PD), the HD may log this condition but must always respond with this acknowledgment.

warnings The control block must be the same control block as passed to the HD in the corresponding udi_scsi_unbind_req operation.

REFERENCES udi_scsi_bind_cb_t, udi_scsi_unbind_req

3.8 I/O Operations

NAME udi_scsi_io_cb_t

Control block for SCSI I/O operations

SYNOPSIS

#include <udi.h>

typedef struct {

	udi_cb_t gcb;

	udi_buf_t *data_buf;

	udi_ubit32_t timeout;

	udi_ubit16_t flags;

	udi_ubit8_t attribute;

	udi_ubit8_t cdb_len;

	udi_ubit8_t *cdb_ptr;

} udi_scsi_io_cb_t;
 
/* I/O Request Flags */
 
#define  UDI_SCSI_DATA_IN				(1U<<0)
 
#define  UDI_SCSI_DATA_OUT				(1U<<1)
 
#define  UDI_SCSI_NO_DISCONNECT				(1U<<2)
 
/* SCSI Task Attributes */
 
#define UDI_SCSI_SIMPLE_TASK 1 #define UDI_SCSI_ORDERED_TASK 2 #define UDI_SCSI_HEAD_OF_Q_TASK 3 #define UDI_SCSI_ACA_TASK 4 #define UDI_SCSI_UNTAGGED_TASK 5
/* Control Block Group Number */
 
#define UDI_SCSI_IO_CB_NUM 2

MEMBERS gcb is a standard member at the front of SCSI control blocks, as defined in udi_scsi_bind_cb_t.

data_buf is a pointer to a buffer used to carry the data portion of a transfer. See udi_scsi_io_req and udi_scsi_io_ack for details on buffer usage.

timeout is an I/O timeout in milliseconds. A timeout value of zero specifies an infinite period, meaning that the HD will not time the request. If the timeout value is non-zero, the HD must ensure that the request is timed for the specified number of milliseconds. As described in Section 2.4.2, to reduce variability, the request must be timed starting from when it is started on the SCSI interconnect, or as close to that point as possible.

If the request doesn't complete within the specified timeout period the HD must abort the request and complete it with status UDI_STAT_TIMEOUT.

flags is a set of flags associated with this I/O request. The flag bit values are defined below. At most one of UDI_SCSI_DATA_IN or UDI_SCSI_DATA_OUT must be specified, and exactly one of these two flags must be specified if data_buf->buf_size is non-zero. UDI_SCSI_NO_DISCONNECT may be optionally combined (ORed) with either of the IN/OUT flags.

UDI_SCSI_DATA_IN - Data-in from device to host.
UDI_SCSI_DATA_OUT - Data-out from host to device.

UDI_SCSI_NO_DISCONNECT - Disconnects on a parallel SCSI bus are disallowed during this I/O. On serial links this flag is ignored.

attribute is a SCSI-3 task attribute which specifies ordering and other constraints of requests (tasks) sent to the device. Exactly one of the following values may be associated with the I/O request by assigning it into the attribute field:

UDI_SCSI_SIMPLE_TASK

UDI_SCSI_ORDERED_TASK

UDI_SCSI_HEAD_OF_Q_TASK

UDI_SCSI_ACA_TASK

UDI_SCSI_UNTAGGED_TASK

All of the above attributes except UDI_SCSI_ACA_TASK are supported in the SCSI-2 architecture. If UDI_SCSI_ACA_TASK is passed to a SCSI-2 HD, it is the HD's responsibility to emulate SCSI-3 ACA behavior by freezing the queues in the HD that correspond to a given LUN and only allowing ACA_TASK'd requests through until a CLEAR_ACA control request is received from the PD.

cdb_len is the number of valid CDB bytes for this request. (This does not include any extra bytes used for multi-LUN addressing.)

cdb_ptr is a pointer to cdb_len bytes of SCSI CDB. If this is a multi-LUN binding the CDB bytes are followed by an 8-bit bus number, 3 pad bytes, a 32-bit Target ID, and a 64-bit LUN. The 32-bit Target ID shall be encoded as a little-endian quantity. The 64-bit LUN value shall be treated as an array of 8 bytes, formatted as per the SCSI Architecture Model - 2 (SAM-2) specification. Refer to Section 2.3 for further information on Target ID and LUN values.

This pointer is set by the environment when the control block is allocated and, like the scratch pointer, points to additional memory associated with this control block. The size of this memory area, and hence the maximum size of CDBs used by this driver, is set via the inline_size member of the relevant udi_cb_init_t, and must be incremented by 16 if this is a multi-LUN binding (i.e., maximum CDB size + 16) to provide room for the 32-bit Target ID and 64-bit LUN. The pointer itself must not be modified by the driver.

DESCRIPTION The SCSI I/O control block is used between the PD and HD to process a SCSI I/O request.

In order to use this type of control block it must be associated with a control block index by including UDI_SCSI_IO_CB_NUM in a udi_cb_init_t in the driver's udi_init_info.

The size of the inline memory area pointed to by cdb_ptr must be specified using the inline_size member of that udi_cb_init_t structure (see Chapter 10, "Initialization", of the UDI Core Specification). The memory is treated as an array of unstructured bytes. (I.e. cdb_ptr is a UDI_DL_INLINE_UNTYPED field.) Since the HD never allocates this type of control block, it must set inline_size to zero.

REFERENCES udi_scsi_io_req, udi_scsi_io_ack, udi_scsi_io_nak, udi_cb_alloc

NAME udi_scsi_io_req

Request a SCSI I/O operation (PD-to-HD)

SYNOPSIS

#include <udi.h>

void udi_scsi_io_req (

	udi_scsi_io_cb_t *cb );
 

ARGUMENTS cb is a pointer to a SCSI IO control block.

TARGET CHANNEL The target channel for this operation is the bind channel connecting a SCSI PD to its parent HD.

DESCRIPTION A PD uses this operation to send a SCSI I/O request to its parent HD.

The PD must prepare for the udi_scsi_io_req operation by allocating a SCSI I/O control block (calling udi_cb_alloc with a cb_idx that was previously associated with UDI_SCSI_IO_CB_NUM) and filling in all of its members.

The PD indicates the desired transfer size by setting data_buf->buf_size to the desired number of bytes. If no bytes are to be transferred, the PD may set data_buf to NULL.

If flags in the control block do not include UDI_SCSI_DATA_OUT, any data in data_buf is not guaranteed to be preserved by this channel operation. That is, when the HD receives this operation, the contents (but not the size) of the buffer are unspecified unless UDI_SCSI_DATA_OUT is set.

This operation is abortable with udi_channel_op_abort.

This operation is recoverable by the PD upon abrupt termination of an instance of the HD. Each SCSI I/O request outstanding in the HD when it is abruptly terminated will be completed by the environment with a corresponding udi_scsi_io_nak operation with a status code of UDI_STAT_TERMINATED. (See the definition of UDI_STAT_TERMINATED in Table 9 of the UDI Core Specification.)

REFERENCES udi_scsi_io_cb_t, udi_scsi_io_ack, udi_scsi_io_nak

NAME udi_scsi_io_ack

Acknowledge normal completion of SCSI I/O request

SYNOPSIS

#include <udi.h>

void udi_scsi_io_ack (

	udi_scsi_io_cb_t *cb );
 

ARGUMENTS cb is a pointer to a SCSI IO control block.

TARGET CHANNEL The target channel for this operation is the bind channel connecting a SCSI HD to its child PD.

DESCRIPTION The udi_scsi_io_ack operation is used by an HD to acknowledge the normal completion of a SCSI I/O request back to a child PD, in response to a udi_scsi_io_req operation. This operation must be used to indicate to the PD a completion status of UDI_OK; otherwise, the udi_scsi_io_nak operation must be used.

If data_buf is not NULL, data_buf->buf_size must be the same as in the original request and must equal the number of bytes actually transferred. The data_buf pointer must either be the same as in the original request, or a direct "descendant" of the original buffer (i.e. results from a chain of one or more service calls such as udi_buf_write that replace the original buffer with a modified version).

If flags in the control block do not include UDI_SCSI_DATA_IN, any data in data_buf is not guaranteed to be preserved by this channel operation. That is, when the PD receives this operation, the contents (but not the size) of the buffer are unspecified unless UDI_SCSI_DATA_IN is set.

warnings The control block must be the same control block as passed to the HD in the corresponding udi_scsi_io_req operation.

REFERENCES udi_scsi_io_cb_t, udi_scsi_io_req, udi_scsi_io_nak

NAME udi_scsi_io_nak

Indicate abnormal completion of SCSI I/O request

SYNOPSIS

#include <udi.h>

void udi_scsi_io_nak (

	udi_scsi_io_cb_t *cb,

	udi_scsi_status_t status,

	udi_buf_t *sense_buf );
 

ARGUMENTS cb is a pointer to a SCSI IO control block.

status is the status of the I/O request.

sense_buf is a pointer to the sense data buffer containing the details of a SCSI command failure if the values in status are set to indicate a CHECK CONDITION; otherwise, sense_buf must be NULL. If non-NULL, sense_buf->buf_size must equal the number of bytes of valid sense data. If there are no sense data bytes, sense_buf may be NULL.

TARGET CHANNEL The target channel for this operation is the bind channel connecting a SCSI HD to its child PD.

DESCRIPTION The udi_scsi_io_nak operation is used by an HD to indicate abnormal completion of a SCSI I/O request back to a child PD, in response to a udi_scsi_io_req operation. This operation must be used to indicate a status other than UDI_OK to the PD. The udi_scsi_io_ack operation must be used to indicate a UDI_OK status in which the exact amount of data requested was transferred.

If data_buf is not NULL, the HD must set data_buf->buf_size to the number of bytes actually transferred, which must be less than or equal to the requested size. The data_buf pointer must either be the same as in the original request, or a direct "descendant" of the original buffer (i.e. results from a chain of one or more service calls such as udi_buf_write that replace the original buffer with a modified version).

If flags in the control block include UDI_SCSI_DATA_OUT, the contents of the data buffer must be the same as in the original request. This allows the PD to retry failed operations if it so chooses.

Data in data_buf is always preserved by this channel operation.

After receiving and processing a udi_scsi_io_nak, the PD must free sense_buf, if non-NULL, by calling udi_buf_free. The HD can reclaim the sense data buffer by copying it before sending it off in the nak; in many environment implementations this will be accomplished (via copy-on-write semantics) without any actual data copy.

warnings The control block must be the same control block as passed to the HD in the corresponding udi_scsi_io_req operation.

REFERENCES udi_scsi_io_cb_t, udi_scsi_io_req, udi_scsi_io_ack

NAME udi_scsi_status_t

Status structure in SCSI I/O Acknowledgement

SYNOPSIS

#include <udi.h>

typedef struct {

	udi_status_t req_status;

	udi_ubit8_t scsi_status;

	udi_ubit8_t sense_status;

} udi_scsi_status_t;
 

MEMBERS req_status is the main software status associated with this I/O request. See below for definitions of status values.

scsi_status is the status byte received over the SCSI bus as defined in the SCSI protocol.

sense_status is the status byte for the REQUEST SENSE command on the SCSI bus. This is valid only when scsi_status indicates a CHECK CONDITION.

DESCRIPTION The SCSI status structure gives the status of the I/O request on I/O completion.

STATUS VALUES The following status codes are defined for req_status:

UDI_SCSI_STAT_ACA_PENDING - A contingent-allegiance condition remains pending at the SCSI device.

UDI_SCSI_STAT_SELECTION_TIMEOUT - SCSI device did not respond to selection.

UDI_SCSI_STAT_DEVICE_PHASE_ERROR - Adapter detected an illegal SCSI bus phase change on the part of the device.

UDI_SCSI_STAT_UNEXPECTED_BUS_FREE - Either the adapter or the device terminated the command prematurely by putting the SCSI bus in a free state.

UDI_SCSI_STAT_DEVICE_PARITY_ERROR - Adapter detected a parity error on the part of the device. (Device-detected parity errors are reported through sense data.)

UDI_SCSI_STAT_ABORTED_HD_BUS_RESET - The I/O command was aborted by a SCSI bus reset generated internally by the HD, probably to resolve a SCSI bus hang. This I/O command may or may not have actually been started on the device. It is unknown if this particular command caused a bus hang.

UDI_SCSI_STAT_ABORTED_RMT_BUS_RESET - The I/O command was aborted by a SCSI bus reset generated by a device on the SCSI bus other than the adapter that this HD controls. This I/O command may or may not have actually been started on the device.

UDI_SCSI_STAT_ABORTED_REQ_BUS_RESET - The I/O command was aborted by a SCSI bus reset requested by the PD. This I/O command may or may not have actually been started on the device.

UDI_SCSI_STAT_ABORTED_REQ_TGT_RESET - The I/O command was aborted by a SCSI target reset requested by the PD. This I/O command may or may not have actually been started on the device.

UDI_SCSI_STAT_HD_ABORTED -- I/O aborted by the HD for reasons other than a reset, timeout, or PD-requested abort; e.g., for a sympathetic error which clears the device queue.

UDI_SCSI_STAT_LINK_FAILURE - The link between the adapter and the device has failed. It is unknown whether this command was active at the time of hardware failure.

UDI_SCSI_STAT_NONZERO_STATUS_BYTE - Device request returned a non-zero SCSI status byte and no other status value applies. If another status code is applicable the HD must set req_status to the other applicable value. The PD must check scsi_status regardless of the value of req_status.

UDI_STAT_NOT_UNDERSTOOD - Request received from the PD was invalid.

UDI_STAT_TIMEOUT - This command was timed out by the HD and aborted.

UDI_STAT_ABORTED - I/O command was successfully aborted as a result of an explicit abort request from the PD (a SCSI control abort request, or a call to udi_channel_op_abort). The command may or may not have been actually started at the device.

UDI_STAT_DATA_OVERRUN - This target device attempted to send more data than was requested.

UDI_STAT_DATA_UNDERRUN - This target device sent less data than was requested.

UDI_STAT_HW_PROBLEM - This command terminated with an indeterminate hardware error.

UDI_STAT_TERMINATED - The HD instance was abruptly terminated and this command was automatically completed by the environment. Drivers must never generate this status code directly.

Note that UDI_STAT_NOT_UNDERSTOOD, UDI_STAT_TIMEOUT, UDI_STAT_ABORTED, UDI_STAT_DATA_OVERRUN, UDI_STAT_DATA_UNDERRUN, UDI_STAT_HW_PROBLEM, and UDI_STAT_TERMINATED are common status codes whose constant values are defined in Chapter 9, "Fundamental Types", of the UDI Core Specification.

REFERENCES udi_scsi_io_cb_t, udi_scsi_io_ack

3.9 Control Operations

NAME udi_scsi_ctl_cb_t

Control block for SCSI control operations

SYNOPSIS

#include <udi.h>

typedef struct {

	udi_cb_t gcb;

	udi_ubit8_t ctrl_func;

	udi_ubit16_t queue_depth;

} udi_scsi_ctl_cb_t;
 
/* Values for ctrl_func */
 
#define  UDI_SCSI_CTL_ABORT_TASK_SET				1
 
#define  UDI_SCSI_CTL_CLEAR_TASK_SET				2
 
#define  UDI_SCSI_CTL_LUN_RESET				3
 
#define  UDI_SCSI_CTL_TGT_RESET				4
 
#define  UDI_SCSI_CTL_BUS_RESET				5
 
#define  UDI_SCSI_CTL_CLEAR_ACA				6
 
#define  UDI_SCSI_CTL_SET_QUEUE_DEPTH				7
 
/* Control Block Group Number */
 
#define UDI_SCSI_CTL_CB_NUM 3

MEMBERS gcb are standard members at the front of SCSI control blocks, as defined in udi_scsi_bind_cb_t.

ctrl_func is one of the following SCSI control functions:

UDI_SCSI_CTL_ABORT_TASK_SET -- Sends the appropriate interconnect-specific operation to abort all tasks in the Logical Unit's task set for the requesting initiator. This will cause the corresponding completion operations to be sent to the PD before responding with the udi_scsi_ctl_ack. On interconnects that do not support this operation, ctrl_func is typically a no-op and the status UDI_STAT_NOT_SUPPORTED is returned in the udi_scsi_ctl_ack.

UDI_SCSI_CTL_CLEAR_TASK_SET -- Sends the appropriate interconnect-specific operation to abort all tasks in the Logical Unit's task set for all initiators. This will cause the the corresponding completion operations to be sent to the PDs before responding with the udi_scsi_ctl_ack. On interconnects that do not support this operation, ctrl_func is typically a no-op and the status UDI_STAT_NOT_SUPPORTED is returned in the udi_scsi_ctl_ack.

UDI_SCSI_CTL_LUN_RESET -- Sends the appropriate interconnect-specific operation to perform a logical unit reset as defined by SAM-2. This will cause the the corresponding completion operations to be sent to the PDs before responding with the udi_scsi_ctl_ack. On interconnects that do not support this operation, ctrl_func is typically a no-op and the status UDI_STAT_NOT_SUPPORTED is returned in the udi_scsi_ctl_ack.

UDI_SCSI_CTL_TGT_RESET -- Sends the appropriate interconnect-specific operation to perform a target-level reset to the SCSI device. This will abort all I/Os outstanding on the LUNs attached to the specified SCSI target and will cause corresponding completion operations to be sent to the PD before responding with the udi_scsi_ctl_ack.

UDI_SCSI_CTL_BUS_RESET -- Reset the SCSI bus (parallel SCSI only) associated with this SCSI device. This will abort all I/Os outstanding on the bus and will cause corresponding completion operations to be sent to the PD before responding with the udi_scsi_ctl_ack. On serial SCSI links this ctrl_func is typically a no-op and the status UDI_STAT_NOT_SUPPORTED is returned in the udi_scsi_ctl_ack.

UDI_SCSI_CTL_CLEAR_ACA -- Clear auto-contingent- allegiance condition at the SCSI device.

UDI_SCSI_CTL_SET_QUEUE_DEPTH -- Change the maximum number of commands the HD is allowed to have pending to the device on behalf of this PD simultaneously. This takes effect with respect to subsequent requests received from the PD. QUEUE FULL conditions are handled by the PD.

queue_depth is the maximum number of commands the HD is allowed to have pending to the device simultaneously. Used only with UDI_SCSI_CTL_SET_QUEUE_DEPTH.

DESCRIPTION The control block for SCSI Control operations is used between the PD and HD to process a SCSI Control request.

In order to use this type of control block it must be associated with a control block index by including UDI_SCSI_CTL_CB_NUM in a udi_cb_init_t in the driver's udi_init_info.

REFERENCES udi_scsi_ctl_req, udi_scsi_ctl_ack, udi_cb_alloc

NAME udi_scsi_ctl_req

Request a SCSI control operation (PD-to-HD)

SYNOPSIS

#include <udi.h>

void udi_scsi_ctl_req (

	udi_scsi_ctl_cb_t *cb );
 

ARGUMENTS cb is a pointer to a SCSI ctl control block.

TARGET CHANNEL The target channel for this operation is the bind channel connecting a SCSI PD to its parent HD.

DESCRIPTION A PD uses this operation to send a SCSI Control request to its parent HD.

The PD must prepare for the udi_scsi_ctl_req operation by allocating a scsi_ctl control block (calling udi_cb_alloc with a cb_idx that was previously associated with UDI_SCSI_CTL_CB_NUM). Next, the PD fills in the control block and sends it to the HD in a udi_scsi_ctl_req operation.

This operation is recoverable by the PD upon abrupt termination of an instance of the HD. Each SCSI control request outstanding in the HD when it is abruptly terminates will be completed by the environment with a corresponding udi_scsi_ctl_nak operation with a status code of UDI_STAT_TERMINATED. (See the definition of UDI_STAT_TERMINATED in Table 9 of the UDI Core Specification.)

REFERENCES udi_scsi_ctl_cb_t, udi_scsi_ctl_ack

NAME udi_scsi_ctl_ack

Ack completion of SCSI control request (HD-to-PD)

SYNOPSIS

#include <udi.h>

void udi_scsi_ctl_ack (

	udi_scsi_ctl_cb_t *cb,

	udi_status_t status );
 

ARGUMENTS cb is a pointer to a SCSI ctl control block.

status is the status of the SCSI control request, and shall be one of the following values:

UDI_OK -- Normal completion.

UDI_STAT_HW_PROBLEM -- Adapter hardware error prevented completion of control request.

UDI_STAT_NOT_UNDERSTOOD -- Control request block is invalid.

UDI_STAT_NOT_SUPPORTED -- Control request block is not in error, but the specific request type is not supported by the HD.

UDI_STAT_TERMINATED - The HD instance was abruptly terminated and this command was automatically completed by the environment. Drivers must never generate this status code directly.

UDI_SCSI_CTL_STAT_FAILED -- Control request failed for some other unspecified reason.

Note that all the status codes except UDI_SCSI_CTL_STAT_FAILED are common status codes whose constant values are defined in Chapter 9, "Fundamental Types", of the UDI Core Specification.

TARGET CHANNEL The target channel for this operation is the bind channel connecting a SCSI HD to its child PD.

DESCRIPTION udi_scsi_ctl_ack is called by an HD to acknowledge completion of a SCSI Control request back to a child PD (indicating success or failure), as requested by a udi_scsi_ctl_req operation.

warnings The control block must be the same control block as passed to the HD in the corresponding udi_scsi_ctl_req operation.

REFERENCES udi_scsi_ctl_cb_t, udi_scsi_ctl_req

3.10 Event Operations

NAME udi_scsi_event_cb_t

Control block for SCSI event operations

SYNOPSIS

#include <udi.h>

typedef struct {

	udi_cb_t gcb;

	udi_ubit8_t event;

	udi_buf_t *aen_data_buf;

} udi_scsi_event_cb_t;
 
/* Control Block Group Number */
 
#define  UDI_SCSI_EVENT_CB_NUM				4
 

MEMBERS gcb is a standard members at the front of SCSI control blocks, as defined in udi_scsi_bind_cb_t.

event is the type of asynchronous event. See the event field in the udi_scsi_bind_cb_t for valid event types.

aen_data_buf is a pointer to a data buffer containing AEN data and is only valid if UDI_SCSI_EVENT_AEN is set in event; otherwise it must be set to NULL. In the AEN case, aen_data_buf must contain no more than aen_buf_size bytes of valid data, as specified in the udi_scsi_bind_req. If aen_buf_size was zero, aen_data_buf must be NULL. It is legal in the SCSI architecture to send zero bytes of data with an AEN, so if the PD's device supports AEN but always sends zero bytes of data (indicating to the PD that it should go check its device) then this would be an example where an aen_buf_size of zero would be appropriate.

See udi_scsi_event_ind and udi_scsi_event_res for additional details on the usage of AEN buffers.

DESCRIPTION The SCSI event control block is used between the HD and its PD children to notify the PD of an asynchronous event.

In order to use this type of control block it must be associated with a control block index by including UDI_SCSI_EVENT_CB_NUM in a udi_cb_init_t in the driver's udi_init_info.

REFERENCES udi_scsi_event_ind, udi_scsi_event_res, udi_cb_alloc

NAME udi_scsi_event_ind

SCSI event notification (HD-to-PD)

SYNOPSIS

#include <udi.h>

void udi_scsi_event_ind (

	udi_scsi_event_cb_t *cb );
 

ARGUMENTS cb is a pointer to a SCSI event control block.

TARGET CHANNEL The target channel for this operation is the bind channel connecting a SCSI HD to its child PD.

PROXIES udi_scsi_event_ind_unused

Proxy for udi_scsi_event_ind
udi_scsi_event_ind_op_t

	udi_scsi_event_ind_unused;
 

udi_scsi_event_ind_unused may be used as a PD's udi_scsi_event_ind entry point if the PD never enables any events for notification.

DESCRIPTION An HD uses the udi_scsi_event_ind operation to send an event notification to its child PD.

The HD must prepare for the udi_scsi_event_ind operation by allocating a SCSI event control block (calling udi_cb_alloc with a cb_idx that was previously associated with UDI_SCSI_EVENT_CB_NUM).

If event is UDI_SCSI_EVENT_AEN and aen_buf_size in the udi_scsi_bind_req was nonzero, the HD must also obtain an AEN buffer containing aen_buf_size valid bytes. In this case, if the size of the AEN data received from the device is greater than aen_buf_size, only the first aen_buf_size byte will be placed in the buffer; the size of the AEN data in the buffer, up to this maximum, will be indicated by the buf_size field of the buffer.

Next, the HD sends the SCSI event control block to the PD with a udi_scsi_event_ind operation. The HD does not need to wait to receive a response before sending another udi_scsi_event_ind; multiple indications may be pending at once.

Whether or not an HD supports a particular type of event notification, and whether or not the PD has enabled those events, is negotiated in the SCSI bind operations.

Note that some events (e.g., SCSI bus reset) can be triggered by a PD through control operations. The event is still sent to the PD that requested the control operation, and is sent before the control operation completes.

REFERENCES udi_scsi_event_cb_t, udi_scsi_event_res

NAME udi_scsi_event_res

Acknowledge a SCSI event (PD-to-HD)

SYNOPSIS

#include <udi.h>

void udi_scsi_event_res (

	udi_scsi_event_cb_t *cb );
 

ARGUMENTS cb is a pointer to a SCSI event control block.

TARGET CHANNEL The target channel for this operation is the bind channel connecting a SCSI HD to its child PD.

DESCRIPTION The udi_scsi_event_res operation is used by a PD to acknowledge an event indication from its parent HD, as delivered by a udi_scsi_event_ind operation.

If event is UDI_SCSI_EVENT_AEN, the aen_data_buf handle must have the same value as was received in the udi_scsi_event_ind, and the buffer itself must not have been modified by the PD.

warnings The control block must be the same control block as passed to the PD in the corresponding udi_scsi_event_ind operation.

REFERENCES udi_scsi_event_cb_t, udi_scsi_event_ind

3.11 Utility Functions

NAME udi_scsi_inquiry_to_string

Encode SCSI INQUIRY data as a string

SYNOPSIS

#include <udi.h>

void udi_scsi_inquiry_to_string (

	const udi_ubit8_t *inquiry_data,

	udi_size_t inquiry_len,

	char *str );
 

ARGUMENTS inquiry_data is a pointer to up to 36 bytes of SCSI INQUIRY data.

inquiry_len is the length of the inquiry_data array.

str is a pointer to a character array, at least 45 bytes long, that will be filled in with the encoded string.

description This utility function converts binary SCSI INQUIRY data to a string, encoded as required for the "identifier" attribute when the device does not have a LUN World-Wide ID. See Section 2.5.2.2.1, "identifier attribute" for details.


TOC PREV NEXT INDEX