[Return to Library] [Contents] [Previous Chapter] [Next Section] [Next Chapter] [Index] [Help]


5    CAM Data Structures

Data structures are the mechanism used to pass information between peripheral device drivers and the CAM subsystem. This chapter describes the CAM data structures that peripheral device drivers use. They are defined in the file /usr/sys/include/io/cam/cam.h. This chapter discusses the following:

Other chapters reference these structures. You can read this chapter now to become familiar with the structures, or you can refer to it when you encounter references to the structures in other chapters.


[Return to Library] [Contents] [Previous Chapter] [Next Section] [Next Chapter] [Index] [Help]


5.1    CAM Control Blocks

The CAM control block (CCB) data structures let the device driver writer specify the action to be performed by the XPT and SIM. The CCBs are allocated by calling the xpt_ccb_alloc routine. Table 5-1 contains the name of each CCB data structure and a brief description.

Table 5-1: CAM Control Blocks

CCB Name Description
CCB_SCSIIO Requests SCSI I/O.
CCB_GETDEV Gets device type.
CCB_PATHINQ Sends a path inquiry.
CCB_RELSIM Releases SIM queue.
CCB_SETASYNC Sets asynchronous callback.
CCB_SETDEV Sets device type.
CCB_ABORT Aborts XPT request.
CCB_RESETBUS Resets SCSI bus.
CCB_RESETDEV Resets SCSI device.
CCB_TERMIO Terminates I/O process request.

All CCBs contain a CCB_HEADER structure. Peripheral device driver writers need to understand the CCB_HEADER data structure, which is discussed in the section that follows.


[Return to Library] [Contents] [Previous Chapter] [Previous Section] [Next Section] [Next Chapter] [Index] [Help]


5.1.1    The CCB_HEADER Structure

SCSI/CAM peripheral device driver writers allocate a CCB structure by calling the xpt_ccb_alloc routine. The CCB_HEADER structure is common to all CCBs and is the first structure filled in. It contains the following members:

typedef struct ccb_header
{
    struct ccb_header *my_addr; /* The address of this CCB */
    u_short cam_ccb_len;        /* Length of the entire CCB */
    u_char cam_func_code;       /* XPT function code */
    u_char cam_status;          /* Returned CAM subsystem */
                                /* status */
    u_char cam_path_id;         /* Path ID for the request */
    u_char cam_target_id;       /* Target device ID */
    u_char cam_target_lun;      /* Target LUN number */
    u_long cam_flags;           /* Flags for operation of */
                                /* the subsystem */
} CCB_HEADER;


[Return to Library] [Contents] [Previous Chapter] [Previous Section] [Next Section] [Next Chapter] [Index] [Help]


5.1.1.1    The my_addr and cam_ccb_len Members

The my_addr member is set to a pointer to the virtual address of the starting address of the CCB. The xpt_ccb_alloc routine automatically fills it in.

The cam_ccb_len member is set to the length (in bytes) of this specific CCB type. The ccmn_get_ccb routine fills in this member. The length includes the my_addr and cam_ccb_len members.


[Return to Library] [Contents] [Previous Chapter] [Previous Section] [Next Section] [Next Chapter] [Index] [Help]


5.1.1.2    The cam_func_code Member

The cam_func_code member lets device driver writers specify the CCB type XPT/SIM functions. Device driver writers can set this member to one of the function codes listed in Table 5-2. They are defined in the file /usr/sys/include/io/cam/cam.h.

Table 5-2: CAM Function Codes

Function Code Meaning
XPT_NOOP Do not execute anything in the XPT/SIM.
XPT_SCSI_IO Execute the requested SCSI I/O. You specify the details of the SCSI I/O by setting the appropriate members of the CCB_SCSIIO structure.
XPT_GDEV_TYPE Get the device type information. You obtain this information by referencing the CCB_GETDEV structure.
XPT_PATH_INQ Get the path inquiry information. You obtain this information by referencing the CCB_PATHINQ structure.
XPT_REL_SIMQ Release the SIM queue that is frozen.
XPT_ASYNC_CB Set the asynchronous callback parameters. You obtain asynchronous callback information from the CCB_SETASYNC structure.
XPT_SDEV_TYPE Set the device type information. You obtain the device type information from the CCB_SETDEV structure.
XPT_ABORT Abort the specified CCB. You specify the abort to the CCB by setting the appropriate member of the CCB_ABORT structure.
XPT_RESET_BUS Reset the SCSI bus.
XPT_RESET_DEV Reset the SCSI device.
XPT_TERM_IO Terminate the I/O process. You specify the CCB process to terminate by setting the appropriate member of the CCB_TERMIO structure.


[Return to Library] [Contents] [Previous Chapter] [Previous Section] [Next Section] [Next Chapter] [Index] [Help]


5.1.1.3    The cam_status Member

The cam_status member is the action or event that occurred during this CCB request. The cam_status member is set by the XPT/SIM after the specified function has completed. A CAM_REQ_INPROG status indicates that either the function is still executing or is still in the queue. The XPT/SIM can set this member to one of the CAM status codes listed in Table 5-3. They are defined in the file /usr/sys/include/io/cam/cam.h.

Table 5-3: CAM Status Codes

CAM Status Code Meaning
CAM_REQ_INPROG A CCB request is in progress.
CAM_REQ_CMP A CCB request was completed without errors.
CAM_REQ_ABORTED A CCB request was aborted by the host processor.
CAM_REQ_UA_ABORT The SIM was not able to abort the specified CCB.
CAM_REQ_CMP_ERR The specified CCB request was completed with an error.
CAM_BUSY The CAM subsystem is busy. The CCB returns to the caller; the request must be resubmitted.
CAM_REQ_INVALID The specified CCB request is not valid.
CAM_PATH_INVALID The path ID specified in the cam_path_id member of the CCB_HEADER structure is not valid.
CAM_DEV_NOT_THERE The specified SCSI device is not installed at this location.
CAM_UA_TERMIO The CAM subsystem was unable to terminate the specified CCB I/O request.
CAM_SEL_TIMEOUT A target-selection timeout occurred.
CAM_CMD_TIMEOUT A command timeout occurred.
CAM_MSG_REJECT_REC A message rejection was received by the SIM.
CAM_SCSI_BUS_RESET The SCSI bus-reset was issued by the SIM or was seen on the bus by the SIM.
CAM_UNCOR_PARITY An uncorrectable parity error occurred.
CAM_AUTOSENSE_FAIL The autosense request-sense command failed.
CAM_NO_HBA No HBA was detected.
CAM_DATA_RUN_ERR A data overflow or underflow error occurred.
CAM_UNEXP_BUSFREE An unexpected bus free was detected.
CAM_SEQUENCE_FAIL A target bus phase-sequence failure occurred.
CAM_CCB_LEN_ERR The CCB length specified in the cam_ccb_len member of the CCB_HEADER structure is incorrect.
CAM_PROVIDE_FAIL The requested capability could not be provided.
CAM_BDR_SENT A SCSI BDR message was sent to the target.
CAM_REQ_TERMIO The CCB request was terminated by the host.
CAM_LUN_INVALID The LUN supplied is invalid.
CAM_TID_INVALID The target ID supplied is invalid.
CAM_FUNC_NOTAVAIL The requested function is not available.
CAM_NO_NEXUS A nexus has not been established.
CAM_IID_INVALID The initiator ID is invalid.
CAM_CDB_RECVD The SCSI CDB has been received.
CAM_SCSI_BUSY The SCSI bus is busy.
CAM_SIM_QFRZN The SIM queue is frozen.
CAM_AUTOSNS_VALID Autosense data is valid for the target.
CAM_STATUS_MASK The mask bits are only for the status.


[Return to Library] [Contents] [Previous Chapter] [Previous Section] [Next Section] [Next Chapter] [Index] [Help]


5.2    I/O Data Structure

Peripheral device drivers make SCSI device action requests through the following data structures:


[Return to Library] [Contents] [Previous Chapter] [Previous Section] [Next Section] [Next Chapter] [Index] [Help]


5.2.1    The CCB_SCSIIO Structure

A peripheral driver indicates to the XPT/SIM that it wants to make a SCSI device action request by setting the cam_func_code member of the CCB_HEADER structure to the constant XPT_SCSI_IO. The peripheral driver writer then uses the CCB_SCSIIO structure to specify the requests.

The CCB_SCSIIO structure is defined as follows:

typedef struct
{
    CCB_HEADER cam_ch;        /* Header information fields */
    u_char *cam_pdrv_ptr;     /* Ptr to the Peripheral driver */
                              /* working set */
    CCB_HEADER *cam_next_ccb; /* Ptr to the next CCB for action */
    u_char *cam_req_map;      /* Ptr for mapping info on the Req. */
    void (*cam_cbfcnp)();     /* Callback on completion function */
    u_char *cam_data_ptr;     /* Pointer to the data buf/SG list */
    u_long cam_dxfer_len;     /* Data xfer length */
    u_char *cam_sense_ptr;    /* Pointer to the sense data buffer */
    u_char cam_sense_len;     /* Num of bytes in the Autosense buf */
    u_char cam_cdb_len;       /* Number of bytes for the CDB */
    u_short cam_sglist_cnt;   /* Num of scatter/gather list entries */
    u_long cam_sort;          /* Value used by the SIM to sort on  */
    cam_scsi_status           /* Returned SCSI device status */
    cam_sense_resid           /* Autosense residual length: */
                                      /* two's complement */
    cam_osd_rsvdi[2]          /* OSD reserved field for alignment */
    long cam_resid;           /* Transfer residual length: */
                                      /* two's complement */
    CDB_UN cam_cdb_io;        /* Union for CDB bytes/pointer */
    u_long cam_timeout;       /* Timeout value */
    u_char *cam_msg_ptr;      /* Pointer to the message buffer */
    u_short cam_msgb_len;     /* Num of bytes in the message buf */
    u_short cam_vu_flags;     /* Vendor unique flags */
    u_char cam_tag_action;    /* What to do for tag queuing */
    u_char cam_iorsvd0[3];    /* Reserved field, for alignment */
    u_char cam_sim_priv[ SIM_PRIV ];   /* SIM private data area */
} CCB_SCSIIO;


[Return to Library] [Contents] [Previous Chapter] [Previous Section] [Next Section] [Next Chapter] [Index] [Help]


5.2.2    The CDB_UN Structure

The CDB_UN structure is defined as follows:

typedef union
{
    u_char *cam_cdb_ptr;                /* Pointer to the CDB bytes */
                                                       /* to send */
    u_char cam_cdb_bytes[ IOCDBLEN ];   /* Area for the inline CDB *?
                                                       /* to send */
} CDB_UN;


[Return to Library] [Contents] [Previous Chapter] [Previous Section] [Next Section] [Next Chapter] [Index] [Help]


5.3    Control CCB Structures

The control CCB structures allow the driver writer to specify such tasks as resetting the SCSI bus, terminating an I/O process request, and so forth. This section discusses the following control structures:


[Return to Library] [Contents] [Previous Chapter] [Previous Section] [Next Section] [Next Chapter] [Index] [Help]


5.3.1    The CCB_RELSIM Structure

Device driver writers use the CCB_RELSIM structure to release the SIM's internal CCB queue. The CCB_RELSIM structure is defined as follows:

typedef struct
{
    CCB_HEADER cam_ch;           /* Header information fields */
} CCB_RELSIM;


[Return to Library] [Contents] [Previous Chapter] [Previous Section] [Next Section] [Next Chapter] [Index] [Help]


5.3.2    The CCB_SETASYNC Structure

SCSI/CAM peripheral device driver writers use the CCB_SETASYNC structure to set the asynchronous callback for notification of the following events when they occur:

The CCB_SETASYNC structure is defined as follows:

typedef struct
{
    CCB_HEADER cam_ch;         /* Header information fields */
    u_long cam_async_flags;    /* Event enables for Callback response */
    void (*cam_async_func)();  /* Async Callback function address */
    u_char *pdrv_buf;          /* Buffer set aside by the */
                               /* peripheral driver */
    u_char pdrv_buf_len;       /* The size of the buffer */
} CCB_SETASYNC;


[Return to Library] [Contents] [Previous Chapter] [Previous Section] [Next Section] [Next Chapter] [Index] [Help]


5.3.3    The CCB_ABORT Structure

Device driver writers use the CCB_ABORT structure to abort a CCB that is on the SIM queue. The CCB_ABORT structure is defined as follows:

typedef struct
{
    CCB_HEADER cam_ch;             /* Header information fields */
    CCB_HEADER *cam_abort_ch;      /* Pointer to the CCB to abort */
} CCB_ABORT;


[Return to Library] [Contents] [Previous Chapter] [Previous Section] [Next Section] [Next Chapter] [Index] [Help]


5.3.4    The CCB_RESETBUS Structure

Device driver writers use the CCB_RESETBUS structure to reset the SCSI bus. The CCB_RESETBUS structure is defined as follows:

typedef struct
{
    CCB_HEADER cam_ch;      /* Header information fields */
} CCB_RESETBUS;


[Return to Library] [Contents] [Previous Chapter] [Previous Section] [Next Section] [Next Chapter] [Index] [Help]


5.3.5    The CCB_RESETDEV Structure

Device driver writers use the CCB_RESETDEV structure to reset a single SCSI device. The CCB_RESETDEV structure is defined as follows:

typedef struct
{
    CCB_HEADER cam_ch;      /* Header information fields */
} CCB_RESETDEV;


[Return to Library] [Contents] [Previous Chapter] [Previous Section] [Next Section] [Next Chapter] [Index] [Help]


5.3.6    The CCB_TERMIO Structure

Device driver writers use the CCB_TERMIO structure to terminate an I/O process request. The CCB_TERMIO structure is defined as follows:

typedef struct
{
    CCB_HEADER cam_ch;             /* Header information fields */
    CCB_HEADER *cam_termio_ch;     /* Pointer to the CCB to terminate */
} CCB_TERMIO;


[Return to Library] [Contents] [Previous Chapter] [Previous Section] [Next Section] [Next Chapter] [Index] [Help]


5.4    Configuration CCB Structures

The configuration CCB structures let the driver writer obtain information such as the device type, version number for the SIM/HBA, and vendor IDs. The following configuration CCBs are described in this section:


[Return to Library] [Contents] [Previous Chapter] [Previous Section] [Next Section] [Next Chapter] [Index] [Help]


5.4.1    The CCB_GETDEV Structure

Device driver writers use the CCB_GETDEV structure to obtain a device type and inquiry information. The CCB_GETDEV structure is defined as follows:

typedef struct
{
    CCB_HEADER cam_ch;       /* Header information fields */
    u_char cam_pd_type;      /* Peripheral device type from the TLUN */
    char *cam_inq_data;      /* Ptr to the inquiry data space */
} CCB_GETDEV;


[Return to Library] [Contents] [Previous Chapter] [Previous Section] [Next Section] [Next Chapter] [Index] [Help]


5.4.2    The CCB_SETDEV Structure

Device driver writers use the CCB_SETDEV structure to set the device type. The CCB_SETDEV structure is defined as follows:

typedef struct
{
    CCB_HEADER cam_ch;      /* Header information fields */
    u_char cam_dev_type;    /* Value for the dev type field in EDT */
} CCB_SETDEV;


[Return to Library] [Contents] [Previous Chapter] [Previous Section] [Next Chapter] [Index] [Help]


5.4.3    The CCB_PATHINQ Structure

Device driver writers use the CCB_PATHINQ structure to obtain SIM information such as supported features and version numbers. The CCB_PATHINQ structure is defined as follows:

typedef struct
{
   CCB_HEADER cam_ch;               /* Header information fields */
   u_char cam_version_num;          /* Version number for the SIM/HBA */
   u_char cam_hba_inquiry;          /* Mimic of INQ byte 7 for the HBA */
   u_char cam_target_sprt;          /* Flags for target mode support */
   u_char cam_hba_misc;             /* Misc HBA feature flags */
   u_char cam_vuhba_flags[ VUHBA ]; /* Vendor unique capabilities */
   u_long cam_sim_priv;             /* Size of SIM private data area */
   u_long cam_async_flags;          /* Event cap. for Async Callback */
   u_char cam_hpath_id;             /* Highest path ID in subsystem */
   u_char cam_initiator_id;         /* ID of the HBA on the SCSI bus */
   char cam_sim_vid[ SIM_ID ];      /* Vendor ID of the SIM */
   char cam_hba_vid[ HBA_ID ];      /* Vendor ID of the HBA */
   u_char *cam_osd_usage;           /* Ptr for the OSD specific area */
} CCB_PATHINQ;