Sun Microsystems, Inc.
spacerspacer
spacer www.sun.com docs.sun.com |
spacer
black dot
 
 
15.  SCSI Host Bus Adapter Drivers SCSA HBA Interfaces SCSA HBA Data Structures scsi_device Structure  Previous   Contents   Next 
   
 

scsi_pkt Structure

To execute SCSI commands, a target driver must first allocate a scsi_pkt(9S) structure for the command, specifying 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(9S) in Chapter 14, SCSI 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 */
};
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 not transferred when the command has been completed or 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 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) and initialize the vectors in this transport structure to point to the required HBA driver entry points. This scsi_hba_tran(9S) structure is then passed into scsi_hba_attach_setup(9F).

The scsi_hba_tran(9S) 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(9S) structure and also provides the target (a_target) and logical unit (a_lun) addresses for the particular target device. Because every HBA driver entry point is passed a pointer to the scsi_address(9S) structure, either directly or indirectly through the scsi_device(9S) structure, the HBA driver can reference its own state and can identify the target device being addressed.

The following figure illustrates the HBA data structures for transport operations.

Figure 15-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, or if it needs to maintain a more complex address than is provided in the scsi_address(9S) structure.

When cloning, the HBA driver must still allocate a scsi_hba_tran structure at attach(9E) time and initialize the tran_hba_private soft state pointer and HBA entry point vectors as before. 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 duplicates (clones) thescsi_hba_tran structure associated with that instance of the HBA. This means that each scsi_address(9S) structure, allocated and initialized for a particular target device instance, points to a per-target instance copy of the scsi_hba_tran structure, not to the scsi_hba_tran structure allocated by the HBA driver at attach(9E) time.

Two important pointers that an HBA driver can use when it has specified cloning 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. This is useful, for example, if an HBA driver needs to maintain a more complex address than the a_target and a_lun fields in the scsi_address(9S) structure allow. 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 and 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(9S) structure before the HBA driver tran_tgt_init(9E) entry point is called. The driver requests cloning by passing the SCSI_HBA_TRAN_CLONE flag to scsi_hba_attach_setup(9F). Figure 15-4 illustrates the HBA data structures for cloning transport operations.

Figure 15-4 Cloning Transport Operation

SCSA HBA Functions

SCSA also provides a number of functions, listed in Table 15-2, for use by HBA drivers.

Table 15-2 SCSA HBA Functions

Function Name

Called by Driver Entry Point

scsi_hba_init(9F)

_init(9E)

scsi_hba_fini(9F)

_fini(9E)

scsi_hba_attach_setup(9F)

attach(9E)

scsi_hba_detach(9F)

detach(9E)

scsi_hba_tran_alloc(9F)

attach(9E)

scsi_hba_tran_free(9F)

detach(9E)

scsi_hba_probe(9F)

tran_tgt_probe(9E)

scsi_hba_pkt_alloc(9F)

tran_init_pkt(9E)

scsi_hba_pkt_free(9F)

tran_destroy_pkt(9E)

scsi_hba_lookup_capstr(9F)

tran_getcap(9E) and tran_setcap(9E)

HBA Driver Dependency and Configuration Issues

In addition to incorporating SCSA HBA entry points, structures, and functions into a driver, HBA driver developers must also concern themselves with issues surrounding driver dependency and configuration. These issues involve configuration properties, dependency declarations, state structure and per-command structure, module initialization entry points, and autoconfiguration entry points.

Declarations and Structures

HBA drivers must include the following header files:

#include <sys/scsi/scsi.h>
#include <sys/ddi.h>
#include <sys/sunddi.h>

To inform the system that the module depends on SCSA routines (see "SCSA HBA Interfaces" for more information), the driver binary must be generated with the following command:

% ld -r xx.o -o xx -N "misc/scsi"

The code samples are derived from a simplified isp driver for the QLogic Intelligent SCSI Peripheral device. The isp driver supports WIDE SCSI, with up to 15 target devices and 8 logical units (LUNs) per target.

Per-Command Structure

An HBA driver will usually need to define a structure to maintain state for each command submitted by a target driver. The layout of this per-command structure is entirely up to the device driver writer and needs to reflect the capabilities and features of the hardware and the software algorithms used in the driver.

The following structure is an example of a per-command structure. The remaining code fragments of this chapter use this structure to illustrate the HBA interfaces.

struct isp_cmd {
     struct isp_request            cmd_isp_request;
     struct isp_response           cmd_isp_response;
     struct scsi_pkt               *cmd_pkt;
     struct isp_cmd                *cmd_forw;
     uint32_t                      cmd_dmacount;
     ddi_dma_handle_t              cmd_dmahandle;
     uint_t                        cmd_cookie;
     uint_t                        cmd_ncookies;
     uint_t                        cmd_cookiecnt;
     uint_t                        cmd_nwin;
     uint_t                        cmd_curwin;
     off_t                         cmd_dma_offset;
     uint_t                        cmd_dma_len;
     ddi_dma_cookie_t              cmd_dmacookies[ISP_NDATASEGS];
     u_int                         cmd_flags;
     u_short                       cmd_slot;
     u_int                         cmd_cdblen;
     u_int                         cmd_scblen;
 };
 
 
 
  Previous   Contents   Next