SCSA HBA Interfaces
SCSA HBA interfaces include HBA entry points, HBA data structures, and an HBA
framework.
SCSA HBA Entry Point Summary
SCSA defines a number of HBA driver entry points. These entry points are
listed in the following table. The entry points are called by the system
when a target driver instance connected to the HBA driver is configured. The
entry points are also called when the target driver makes a SCSA request.
See Entry Points for SCSA HBA Drivers for more information.
Table 18-1 SCSA HBA Entry Point Summary
SCSA HBA Data Structures
SCSA defines data structures to enable the exchange of information between the target
and HBA drivers. The following data structures are included:
scsi_hba_tran() Structure
Each instance of an HBA driver must allocate a scsi_hba_tran(9S) structure by using
the scsi_hba_tran_alloc(9F) function in the attach(9E) entry point. The scsi_hba_tran_alloc() function
initializes the scsi_hba_tran structure. The HBA driver must initialize specific vectors in the
transport structure to point to entry points within the HBA driver. After the
scsi_hba_tran structure is initialized, the HBA driver exports the transport structure to SCSA
by calling the scsi_hba_attach_setup(9F) function.
Caution - Because SCSA keeps a pointer to the transport structure in the driver-private field
on the devinfo node, HBA drivers must not use ddi_set_driver_private(9F). HBA drivers
can, however, use ddi_get_driver_private(9F) to retrieve the pointer to the transport
structure.
The SCSA interfaces require the HBA driver to supply a number of
entry points that are callable through the scsi_hba_tran structure. See Entry Points for SCSA HBA Drivers for more information.
The scsi_hba_tran structure contains the following fields:
struct scsi_hba_tran {
dev_info_t *tran_hba_dip; /* HBAs dev_info pointer */
void *tran_hba_private; /* HBA softstate */
void *tran_tgt_private; /* HBA target private pointer */
struct scsi_device *tran_sd; /* scsi_device */
int (*tran_tgt_init)(); /* Transport target */
/* Initialization */
int (*tran_tgt_probe)(); /* Transport target probe */
void (*tran_tgt_free)(); /* Transport target free */
int (*tran_start)(); /* Transport start */
int (*tran_reset)(); /* Transport reset */
int (*tran_abort)(); /* Transport abort */
int (*tran_getcap)(); /* Capability retrieval */
int (*tran_setcap)(); /* Capability establishment */
struct scsi_pkt *(*tran_init_pkt)(); /* Packet and DMA allocation */
void (*tran_destroy_pkt)(); /* Packet and DMA */
/* Deallocation */
void (*tran_dmafree)(); /* DMA deallocation */
void (*tran_sync_pkt)(); /* Sync DMA */
void (*tran_reset_notify)(); /* Bus reset notification */
int (*tran_bus_reset)(); /* Reset bus only */
int (*tran_quiesce)(); /* Quiesce a bus */
int (*tran_unquiesce)(); /* Unquiesce a bus */
int tran_interconnect_type; /* transport interconnect */
};
The following descriptions give more information about these scsi_hba_tran structure fields:
- tran_hba_dip
Pointer to the HBA device instance dev_info structure. The function scsi_hba_attach_setup(9F) sets this field.
- tran_hba_private
Pointer to private data maintained by the HBA driver. Usually, tran_hba_private contains a pointer to the state structure of the HBA driver.
- tran_tgt_private
Pointer to private data maintained by the HBA driver when using cloning. By specifying SCSI_HBA_TRAN_CLONE when calling scsi_hba_attach_setup(9F), the scsi_hba_tran(9S) structure is cloned once per target. This approach enables the HBA to initialize this field to point to a per-target instance data structure in the tran_tgt_init(9E) entry point. If SCSI_HBA_TRAN_CLONE is not specified, tran_tgt_private is NULL, and tran_tgt_private must not be referenced. See Transport Structure Cloning for more information.
- tran_sd
Pointer to a per-target instance scsi_device(9S) structure used when cloning. If SCSI_HBA_TRAN_CLONE is passed to scsi_hba_attach_setup(9F), tran_sd is initialized to point to the per-target scsi_device structure. This initialization takes place before any HBA functions are called on behalf of that target. If SCSI_HBA_TRAN_CLONE is not specified, tran_sd is NULL, and tran_sd must not be referenced. See Transport Structure Cloning for more information.
- tran_tgt_init
Pointer to the HBA driver entry point that is called when initializing a target device instance. If no per-target initialization is required, the HBA can leave tran_tgt_init set to NULL.
- tran_tgt_probe
Pointer to the HBA driver entry point that is called when a target driver instance calls scsi_probe(9F). This routine is called to probe for the existence of a target device. If no target probing customization is required for this HBA, the HBA should set tran_tgt_probe to scsi_hba_probe(9F).
- tran_tgt_free
Pointer to the HBA driver entry point that is called when a target device instance is destroyed. If no per-target deallocation is necessary, the HBA can leave tran_tgt_free set to NULL.
- tran_start
Pointer to the HBA driver entry point that is called when a target driver calls scsi_transport(9F).
- tran_reset
Pointer to the HBA driver entry point that is called when a target driver calls scsi_reset(9F).
- tran_abort
Pointer to the HBA driver entry point that is called when a target driver calls scsi_abort(9F).
- tran_getcap
Pointer to the HBA driver entry point that is called when a target driver calls scsi_ifgetcap(9F).
- tran_setcap
Pointer to the HBA driver entry point that is called when a target driver calls scsi_ifsetcap(9F).
- tran_init_pkt
Pointer to the HBA driver entry point that is called when a target driver calls scsi_init_pkt(9F).
- tran_destroy_pkt
Pointer to the HBA driver entry point that is called when a target driver calls scsi_destroy_pkt(9F).
- tran_dmafree
Pointer to the HBA driver entry point that is called when a target driver calls scsi_dmafree(9F).
- tran_sync_pkt
Pointer to the HBA driver entry point that is called when a target driver calls scsi_sync_pkt(9F).
- tran_reset_notify
Pointer to the HBA driver entry point that is called when a target driver calls tran_reset_notify(9E).
- tran_bus_reset
The function entry that resets the SCSI bus without resetting targets.
- tran_quiesce
The function entry that waits for all outstanding commands to complete and blocks (or queues) any I/O requests issued.
- tran_unquiesce
The function entry that allows I/O activities to resume on the SCSI bus.
- tran_interconnect_type
Integer value denoting interconnect type of the transport as defined in the services.h header file.
scsi_address Structure
The scsi_address(9S) structure provides transport and addressing information for each SCSI command that
is allocated and transported by a target driver instance.
The scsi_address structure contains the following fields:
struct scsi_address {
struct scsi_hba_tran *a_hba_tran; /* Transport vectors */
ushort_t a_target; /* Target identifier */
uchar_t a_lun; /* LUN on that target */
uchar_t a_sublun; /* Sub LUN on that LUN */
/* Not used */
};
- a_hba_tran
Pointer to the scsi_hba_tran(9S) structure, as allocated and initialized by the HBA driver. If SCSI_HBA_TRAN_CLONE was specified as the flag to scsi_hba_attach_setup(9F), a_hba_tran points to a copy of that structure.
- a_target
Identifies the SCSI target on the SCSI bus.
- a_lun
Identifies the SCSI logical unit on the SCSI target.
scsi_device Structure
The HBA framework allocates and initializes a scsi_device(9S) structure for each instance of
a target device. The allocation and initialization occur before the framework calls the
HBA driver's tran_tgt_init(9E) entry point. This structure stores information about each SCSI logical
unit, including pointers to information areas that contain both generic and device-specific information.
One scsi_device(9S) structure exists for each target device instance that is attached to
the system.
If the per-target initialization is successful, the HBA framework sets the target driver's
per-instance private data to point to the scsi_device(9S) structure, using ddi_set_driver_private(9F). Note
that an initialization is successful if tran_tgt_init() returns success or if the
vector is null.
The scsi_device(9S) structure contains the following fields:
struct scsi_device {
struct scsi_address sd_address; /* routing information */
dev_info_t *sd_dev; /* device dev_info node */
kmutex_t sd_mutex; /* mutex used by device */
void *sd_reserved;
struct scsi_inquiry *sd_inq;
struct scsi_extended_sense *sd_sense;
caddr_t sd_private; /* for driver's use */
};
where:
- sd_address
Data structure that is passed to the routines for SCSI resource allocation.
- sd_dev
Pointer to the target's dev_info structure.
- sd_mutex
Mutex for use by the target driver. This mutex is initialized by the HBA framework. The mutex can be used by the target driver as a per-device mutex. This mutex should not be held across a call to scsi_transport(9F) or scsi_poll(9F). See Chapter 3, Multithreading for more information on mutexes.
- sd_inq
Pointer for the target device's SCSI inquiry data. The scsi_probe(9F) routine allocates a buffer, fills the buffer in, and attaches the buffer to this field.
- sd_sense
Pointer to a buffer to contain request sense data from the device. The target driver must allocate and manage this buffer itself. See the target driver's attach(9E) routine in attach() Entry Point for more information.
- sd_private
Pointer field for use by the target driver. This field is commonly used to store a pointer to a private target driver state structure.
scsi_pkt Structure (HBA)
To execute SCSI commands, a target driver must first allocate a scsi_pkt(9S) structure for
the command. The target driver must then specify its own private data area
length, the command status, and the command length. The HBA driver is responsible
for implementing the packet allocation in the tran_init_pkt(9E) entry point. The HBA
driver is also responsible for freeing the packet in its tran_destroy_pkt(9E)
entry point. See scsi_pkt Structure (Target Drivers) for more information.
The scsi_pkt(9S) structure contains these fields:
struct scsi_pkt {
opaque_t pkt_ha_private; /* private data for host adapter */
struct scsi_address pkt_address; /* destination address */
opaque_t pkt_private; /* private data for target driver */
void (*pkt_comp)(struct scsi_pkt *); /* completion routine */
uint_t pkt_flags; /* flags */
int pkt_time; /* time allotted to complete command */
uchar_t *pkt_scbp; /* pointer to status block */
uchar_t *pkt_cdbp; /* pointer to command block */
ssize_t pkt_resid; /* data bytes not transferred */
uint_t pkt_state; /* state of command */
uint_t pkt_statistics; /* statistics */
uchar_t pkt_reason; /* reason completion called */
};
where:
- pkt_ha_private
Pointer to per-command HBA-driver private data.
- pkt_address
Pointer to the scsi_address(9S) structure providing address information for this command.
- pkt_private
Pointer to per-packet target-driver private data.
- pkt_comp
Pointer to the target-driver completion routine called by the HBA driver when the transport layer has completed this command.
- pkt_flags
Flags for the command.
- pkt_time
Specifies the completion timeout in seconds for the command.
- pkt_scbp
Pointer to the status completion block for the command.
- pkt_cdbp
Pointer to the command descriptor block (CDB) for the command.
- pkt_resid
Count of the data bytes that were not transferred when the command completed. This field can also be used to specify the amount of data for which resources have not been allocated. The HBA must modify this field during transport.
- pkt_state
State of the command. The HBA must modify this field during transport.
- pkt_statistics
Provides a history of the events that the command experienced while in the transport layer. The HBA must modify this field during transport.
- pkt_reason
Reason for command completion. The HBA must modify this field during transport.
Per-Target Instance Data
An HBA driver must allocate a scsi_hba_tran(9S) structure during attach(9E). The HBA
driver must then initialize the vectors in this transport structure to point to
the required entry points for the HBA driver. This scsi_hba_tran structure is then passed
into scsi_hba_attach_setup(9F).
The scsi_hba_tran structure contains a tran_hba_private field, which can be used to
refer to the HBA driver's per-instance state.
Each scsi_address(9S) structure contains a pointer to the scsi_hba_tran structure. In addition,
the scsi_address structure provides the target, that is, a_target, and logical unit (a_lun) addresses
for the particular target device. Each entry point for the HBA driver is
passed a pointer to the scsi_address structure, either directly or indirectly through
the scsi_device(9S) structure. As a result, the HBA driver can reference its own
state. The HBA driver can also identify the target device that is addressed.
The following figure illustrates the HBA data structures for transport operations.
Figure 18-3 HBA Transport Structures
Transport Structure Cloning
Cloning can be useful if an HBA driver needs to maintain per-target private
data in the scsi_hba_tran(9S) structure. Cloning can also be used to maintain a more
complex address than is provided in the scsi_address(9S) structure.
In the cloning process, the HBA driver must still allocate a scsi_hba_tran
structure at attach(9E) time. The HBA driver must also initialize the tran_hba_private
soft state pointer and the entry point vectors for the HBA driver. The
difference occurs when the framework begins to connect an instance of a target
driver to the HBA driver. Before calling the HBA driver's tran_tgt_init(9E) entry
point, the framework clones the scsi_hba_tran structure that is associated with that instance of
the HBA. Accordingly, each scsi_address structure that is allocated and initialized for a
particular target device instance points to a per-target instance copy of the scsi_hba_tran
structure. The scsi_address structures do not point to the scsi_hba_tran structure that is allocated
by the HBA driver at attach() time.
An HBA driver can use two important pointers when cloning is
specified. These pointers are contained in the scsi_hba_tran structure. The first pointer is the
tran_tgt_private field, which the driver can use to point to per-target HBA private
data. The tran_tgt_private pointer is useful, for example, if an HBA driver needs
to maintain a more complex address than a_target and a_lun provide. The
second pointer is the tran_sd field, which is a pointer to the scsi_device(9S)
structure referring to the particular target device.
When specifying cloning, the HBA driver must allocate and initialize the per-target data.
The HBA driver must then initialize the tran_tgt_private field to point to
this data during its tran_tgt_init(9E) entry point. The HBA driver must free
this per-target data during its tran_tgt_free(9E) entry point.
When cloning, the framework initializes the tran_sd field to point to the scsi_device
structure before the HBA driver tran_tgt_init() entry point is called. The driver requests
cloning by passing the SCSI_HBA_TRAN_CLONE flag to scsi_hba_attach_setup(9F). The following figure illustrates
the HBA data structures for cloning transport operations.
Figure 18-4 Cloning Transport Operation
SCSA HBA Functions
SCSA also provides a number of functions. The functions are listed in the
following table, for use by HBA drivers.
Table 18-2 SCSA HBA Functions