mirror of
https://github.com/xcat2/xNBA.git
synced 2026-05-14 10:24:11 +00:00
965a0f7a75
With iSCSI, connection attempts are expensive; it may take many seconds to determine that a connection will fail. SRP connection attempts are much less expensive, so we may as well avoid the "optimisation" of declaring a state of permanent failure after a certain number of attempts. This allows a gPXE SRP initiator to resume operations after an arbitrary amount of SRP target downtime.
869 lines
21 KiB
C
869 lines
21 KiB
C
#ifndef _GPXE_SRP_H
|
|
#define _GPXE_SRP_H
|
|
|
|
/** @file
|
|
*
|
|
* SCSI RDMA Protocol
|
|
*
|
|
*/
|
|
|
|
FILE_LICENCE ( BSD2 );
|
|
|
|
#include <stdint.h>
|
|
#include <byteswap.h>
|
|
#include <gpxe/iobuf.h>
|
|
#include <gpxe/xfer.h>
|
|
#include <gpxe/scsi.h>
|
|
|
|
/*****************************************************************************
|
|
*
|
|
* Common fields
|
|
*
|
|
*****************************************************************************
|
|
*/
|
|
|
|
/** An SRP information unit tag */
|
|
struct srp_tag {
|
|
uint32_t dwords[2];
|
|
} __attribute__ (( packed ));
|
|
|
|
/** An SRP port ID */
|
|
struct srp_port_id {
|
|
uint8_t bytes[16];
|
|
} __attribute__ (( packed ));
|
|
|
|
/** An SRP port ID pair */
|
|
struct srp_port_ids {
|
|
/** Initiator port ID */
|
|
struct srp_port_id initiator;
|
|
/** Target port ID */
|
|
struct srp_port_id target;
|
|
} __attribute__ (( packed ));
|
|
|
|
/** SRP information unit common fields */
|
|
struct srp_common {
|
|
/** Information unit type */
|
|
uint8_t type;
|
|
/** Reserved */
|
|
uint8_t reserved0[7];
|
|
/** Tag */
|
|
struct srp_tag tag;
|
|
} __attribute__ (( packed ));
|
|
|
|
/*****************************************************************************
|
|
*
|
|
* Login request
|
|
*
|
|
*****************************************************************************
|
|
*/
|
|
|
|
/** An SRP login request information unit */
|
|
struct srp_login_req {
|
|
/** Information unit type
|
|
*
|
|
* This must be @c SRP_LOGIN_REQ
|
|
*/
|
|
uint8_t type;
|
|
/** Reserved */
|
|
uint8_t reserved0[7];
|
|
/** Tag */
|
|
struct srp_tag tag;
|
|
/** Requested maximum initiator to target IU length */
|
|
uint32_t max_i_t_iu_len;
|
|
/** Reserved */
|
|
uint8_t reserved1[4];
|
|
/** Required buffer formats
|
|
*
|
|
* This is the bitwise OR of one or more @c
|
|
* SRP_LOGIN_REQ_FMT_XXX constants.
|
|
*/
|
|
uint16_t required_buffer_formats;
|
|
/** Flags
|
|
*
|
|
* This is the bitwise OR of zero or more @c
|
|
* SRP_LOGIN_REQ_FLAG_XXX and @c SRP_LOGIN_REQ_MCA_XXX
|
|
* constants.
|
|
*/
|
|
uint8_t flags;
|
|
/** Reserved */
|
|
uint8_t reserved2[5];
|
|
/** Initiator and target port identifiers */
|
|
struct srp_port_ids port_ids;
|
|
} __attribute__ (( packed ));
|
|
|
|
/** Type of an SRP login request */
|
|
#define SRP_LOGIN_REQ 0x00
|
|
|
|
/** Require indirect data buffer descriptor format */
|
|
#define SRP_LOGIN_REQ_FMT_IDBD 0x04
|
|
|
|
/** Require direct data buffer descriptor format */
|
|
#define SRP_LOGIN_REQ_FMT_DDBD 0x02
|
|
|
|
/** Use solicited notification for asynchronous events */
|
|
#define SRP_LOGIN_REQ_FLAG_AESOLNT 0x40
|
|
|
|
/** Use solicited notification for credit request */
|
|
#define SRP_LOGIN_REQ_FLAG_CRSOLNT 0x20
|
|
|
|
/** Use solicited notification for logouts */
|
|
#define SRP_LOGIN_REQ_FLAG_LOSOLNT 0x10
|
|
|
|
/** Multi-channel action mask */
|
|
#define SRP_LOGIN_REQ_MCA_MASK 0x03
|
|
|
|
/** Single RDMA channel operation */
|
|
#define SRP_LOGIN_REQ_MCA_SINGLE_CHANNEL 0x00
|
|
|
|
/** Multiple independent RDMA channel operation */
|
|
#define SRP_LOGIN_REQ_MCA_MULTIPLE_CHANNELS 0x01
|
|
|
|
/*****************************************************************************
|
|
*
|
|
* Login response
|
|
*
|
|
*****************************************************************************
|
|
*/
|
|
|
|
/** An SRP login response */
|
|
struct srp_login_rsp {
|
|
/** Information unit type
|
|
*
|
|
* This must be @c SRP_LOGIN_RSP
|
|
*/
|
|
uint8_t type;
|
|
/** Reserved */
|
|
uint8_t reserved0[3];
|
|
/** Request limit delta */
|
|
uint32_t request_limit_delta;
|
|
/** Tag */
|
|
struct srp_tag tag;
|
|
/** Maximum initiator to target IU length */
|
|
uint32_t max_i_t_iu_len;
|
|
/** Maximum target to initiator IU length */
|
|
uint32_t max_t_i_iu_len;
|
|
/** Supported buffer formats
|
|
*
|
|
* This is the bitwise OR of one or more @c
|
|
* SRP_LOGIN_RSP_FMT_XXX constants.
|
|
*/
|
|
uint16_t supported_buffer_formats;
|
|
/** Flags
|
|
*
|
|
* This is the bitwise OR of zero or more @c
|
|
* SRP_LOGIN_RSP_FLAG_XXX and @c SRP_LOGIN_RSP_MCR_XXX
|
|
* constants.
|
|
*/
|
|
uint8_t flags;
|
|
/** Reserved */
|
|
uint8_t reserved1[25];
|
|
} __attribute__ (( packed ));
|
|
|
|
/** Type of an SRP login response */
|
|
#define SRP_LOGIN_RSP 0xc0
|
|
|
|
/** Indirect data buffer descriptor format supported */
|
|
#define SRP_LOGIN_RSP_FMT_IDBD 0x04
|
|
|
|
/** Direct data buffer descriptor format supported */
|
|
#define SRP_LOGIN_RSP_FMT_DDBD 0x02
|
|
|
|
/** Solicited notification is supported */
|
|
#define SRP_LOGIN_RSP_FLAG_SOLNTSUP 0x10
|
|
|
|
/** Multi-channel result mask */
|
|
#define SRP_LOGIN_RSP_MCR_MASK 0x03
|
|
|
|
/** No existing RDMA channels were associated with the same I_T nexus */
|
|
#define SRP_LOGIN_RSP_MCR_NO_EXISTING_CHANNELS 0x00
|
|
|
|
/** One or more existing RDMA channels were terminated */
|
|
#define SRP_LOGIN_RSP_MCR_EXISTING_CHANNELS_TERMINATED 0x01
|
|
|
|
/** One or more existing RDMA channels continue to operate independently */
|
|
#define SRP_LOGIN_RSP_MCR_EXISTING_CHANNELS_CONTINUE 0x02
|
|
|
|
/*****************************************************************************
|
|
*
|
|
* Login rejection
|
|
*
|
|
*****************************************************************************
|
|
*/
|
|
|
|
/** An SRP login rejection */
|
|
struct srp_login_rej {
|
|
/** Information unit type
|
|
*
|
|
* This must be @c SRP_LOGIN_REJ
|
|
*/
|
|
uint8_t type;
|
|
/** Reserved */
|
|
uint8_t reserved0[3];
|
|
/** Reason
|
|
*
|
|
* This is a @c SRP_LOGIN_REJ_REASON_XXX constant.
|
|
*/
|
|
uint32_t reason;
|
|
/** Tag */
|
|
struct srp_tag tag;
|
|
/** Reserved */
|
|
uint8_t reserved1[8];
|
|
/** Supported buffer formats
|
|
*
|
|
* This is the bitwise OR of one or more @c
|
|
* SRP_LOGIN_REJ_FMT_XXX constants.
|
|
*/
|
|
uint16_t supported_buffer_formats;
|
|
/** Reserved */
|
|
uint8_t reserved2[6];
|
|
} __attribute__ (( packed ));
|
|
|
|
/** Type of an SRP login rejection */
|
|
#define SRP_LOGIN_REJ 0xc2
|
|
|
|
/** Unable to establish RDMA channel, no reason specified */
|
|
#define SRP_LOGIN_REJ_REASON_UNKNOWN 0x00010000UL
|
|
|
|
/** Insufficient RDMA channel resources */
|
|
#define SRP_LOGIN_REJ_REASON_INSUFFICIENT_RESOURCES 0x00010001UL
|
|
|
|
/** Requested maximum initiator to target IU length value too large */
|
|
#define SRP_LOGIN_REJ_REASON_BAD_MAX_I_T_IU_LEN 0x00010002UL
|
|
|
|
/** Unable to associate RDMA channel with specified I_T nexus */
|
|
#define SRP_LOGIN_REJ_REASON_CANNOT_ASSOCIATE 0x00010003UL
|
|
|
|
/** One or more requested data buffer descriptor formats are not supported */
|
|
#define SRP_LOGIN_REJ_REASON_UNSUPPORTED_BUFFER_FORMAT 0x00010004UL
|
|
|
|
/** SRP target port does not support multiple RDMA channels per I_T nexus */
|
|
#define SRP_LOGIN_REJ_REASON_NO_MULTIPLE_CHANNELS 0x00010005UL
|
|
|
|
/** RDMA channel limit reached for this initiator */
|
|
#define SRP_LOGIN_REJ_REASON_NO_MORE_CHANNELS 0x00010006UL
|
|
|
|
/** Indirect data buffer descriptor format supported */
|
|
#define SRP_LOGIN_REJ_FMT_IDBD 0x04
|
|
|
|
/** Direct data buffer descriptor format supported */
|
|
#define SRP_LOGIN_REJ_FMT_DDBD 0x02
|
|
|
|
/*****************************************************************************
|
|
*
|
|
* Initiator logout
|
|
*
|
|
*****************************************************************************
|
|
*/
|
|
|
|
/** An SRP initiator logout request */
|
|
struct srp_i_logout {
|
|
/** Information unit type
|
|
*
|
|
* This must be @c SRP_I_LOGOUT
|
|
*/
|
|
uint8_t type;
|
|
/** Reserved */
|
|
uint8_t reserved0[7];
|
|
/** Tag */
|
|
struct srp_tag tag;
|
|
} __attribute__ (( packed ));
|
|
|
|
/** Type of an SRP initiator logout request */
|
|
#define SRP_I_LOGOUT 0x03
|
|
|
|
/*****************************************************************************
|
|
*
|
|
* Target logout
|
|
*
|
|
*****************************************************************************
|
|
*/
|
|
|
|
/** An SRP target logout request */
|
|
struct srp_t_logout {
|
|
/** Information unit type
|
|
*
|
|
* This must be @c SRP_T_LOGOUT
|
|
*/
|
|
uint8_t type;
|
|
/** Flags
|
|
*
|
|
* This is the bitwise OR of zero or more @c
|
|
* SRP_T_LOGOUT_FLAG_XXX constants.
|
|
*/
|
|
uint8_t flags;
|
|
/** Reserved */
|
|
uint8_t reserved0[2];
|
|
/** Reason
|
|
*
|
|
* This is a @c SRP_T_LOGOUT_REASON_XXX constant.
|
|
*/
|
|
uint32_t reason;
|
|
/** Tag */
|
|
struct srp_tag tag;
|
|
} __attribute__ (( packed ));
|
|
|
|
/** Type of an SRP target logout request */
|
|
#define SRP_T_LOGOUT 0x80
|
|
|
|
/** The initiator specified solicited notification of logouts */
|
|
#define SRP_T_LOGOUT_FLAG_SOLNT 0x01
|
|
|
|
/** No reason specified */
|
|
#define SRP_T_LOGOUT_REASON_UNKNOWN 0x00000000UL
|
|
|
|
/** Inactive RDMA channel (reclaiming resources) */
|
|
#define SRP_T_LOGOUT_REASON_INACTIVE 0x00000001UL
|
|
|
|
/** Invalid information unit type code received by SRP target port */
|
|
#define SRP_T_LOGOUT_REASON_INVALID_TYPE 0x00000002UL
|
|
|
|
/** SRP initiator port sent response with no corresponding request */
|
|
#define SRP_T_LOGOUT_REASON_SPURIOUS_RESPONSE 0x00000003UL
|
|
|
|
/** RDMA channel disconnected due to multi-channel action code in new login */
|
|
#define SRP_T_LOGOUT_REASON_MCA 0x00000004UL
|
|
|
|
/** Unsuppported format code value specified in data-out buffer descriptor */
|
|
#define SRP_T_LOGOUT_UNSUPPORTED_DATA_OUT_FORMAT 0x00000005UL
|
|
|
|
/** Unsuppported format code value specified in data-in buffer descriptor */
|
|
#define SRP_T_LOGOUT_UNSUPPORTED_DATA_IN_FORMAT 0x00000006UL
|
|
|
|
/** Invalid length for IU type */
|
|
#define SRP_T_LOGOUT_INVALID_IU_LEN 0x00000008UL
|
|
|
|
/*****************************************************************************
|
|
*
|
|
* Task management
|
|
*
|
|
*****************************************************************************
|
|
*/
|
|
|
|
/** An SRP task management request */
|
|
struct srp_tsk_mgmt {
|
|
/** Information unit type
|
|
*
|
|
* This must be @c SRP_TSK_MGMT
|
|
*/
|
|
uint8_t type;
|
|
/** Flags
|
|
*
|
|
* This is the bitwise OR of zero or more
|
|
* @c SRP_TSK_MGMT_FLAG_XXX constants.
|
|
*/
|
|
uint8_t flags;
|
|
/** Reserved */
|
|
uint8_t reserved0[6];
|
|
/** Tag */
|
|
struct srp_tag tag;
|
|
/** Reserved */
|
|
uint8_t reserved1[4];
|
|
/** Logical unit number */
|
|
struct scsi_lun lun;
|
|
/** Reserved */
|
|
uint8_t reserved2[2];
|
|
/** Task management function
|
|
*
|
|
* This is a @c SRP_TASK_MGMT_FUNC_XXX constant
|
|
*/
|
|
uint8_t function;
|
|
/** Reserved */
|
|
uint8_t reserved3[1];
|
|
/** Tag of task to be managed */
|
|
struct srp_tag managed_tag;
|
|
/** Reserved */
|
|
uint8_t reserved4[8];
|
|
} __attribute__ (( packed ));
|
|
|
|
/** Type of an SRP task management request */
|
|
#define SRP_TSK_MGMT 0x01
|
|
|
|
/** Use solicited notification for unsuccessful completions */
|
|
#define SRP_TSK_MGMT_FLAG_UCSOLNT 0x04
|
|
|
|
/** Use solicited notification for successful completions */
|
|
#define SRP_TSK_MGMT_FLAG_SCSOLNT 0x02
|
|
|
|
/** The task manager shall perform an ABORT TASK function */
|
|
#define SRP_TSK_MGMT_FUNC_ABORT_TASK 0x01
|
|
|
|
/** The task manager shall perform an ABORT TASK SET function */
|
|
#define SRP_TSK_MGMT_FUNC_ABORT_TASK_SET 0x02
|
|
|
|
/** The task manager shall perform a CLEAR TASK SET function */
|
|
#define SRP_TSK_MGMT_FUNC_CLEAR_TASK_SET 0x04
|
|
|
|
/** The task manager shall perform a LOGICAL UNIT RESET function */
|
|
#define SRP_TSK_MGMT_FUNC_LOGICAL_UNIT_RESET 0x08
|
|
|
|
/** The task manager shall perform a CLEAR ACA function */
|
|
#define SRP_TSK_MGMT_FUNC_CLEAR_ACA 0x40
|
|
|
|
/*****************************************************************************
|
|
*
|
|
* SCSI command
|
|
*
|
|
*****************************************************************************
|
|
*/
|
|
|
|
/** An SRP SCSI command */
|
|
struct srp_cmd {
|
|
/** Information unit type
|
|
*
|
|
* This must be @c SRP_CMD
|
|
*/
|
|
uint8_t type;
|
|
/** Flags
|
|
*
|
|
* This is the bitwise OR of zero or more @c SRP_CMD_FLAG_XXX
|
|
* constants.
|
|
*/
|
|
uint8_t flags;
|
|
/** Reserved */
|
|
uint8_t reserved0[3];
|
|
/** Data buffer descriptor formats
|
|
*
|
|
* This is the bitwise OR of one @c SRP_CMD_DO_FMT_XXX and one @c
|
|
* SRP_CMD_DI_FMT_XXX constant.
|
|
*/
|
|
uint8_t data_buffer_formats;
|
|
/** Data-out buffer descriptor count */
|
|
uint8_t data_out_buffer_count;
|
|
/** Data-in buffer descriptor count */
|
|
uint8_t data_in_buffer_count;
|
|
/** Tag */
|
|
struct srp_tag tag;
|
|
/** Reserved */
|
|
uint8_t reserved1[4];
|
|
/** Logical unit number */
|
|
struct scsi_lun lun;
|
|
/** Reserved */
|
|
uint8_t reserved2[1];
|
|
/** Task attribute
|
|
*
|
|
* This is a @c SRP_CMD_TASK_ATTR_XXX constant.
|
|
*/
|
|
uint8_t task_attr;
|
|
/** Reserved */
|
|
uint8_t reserved3[1];
|
|
/** Additional CDB length */
|
|
uint8_t additional_cdb_len;
|
|
/** Command data block */
|
|
union scsi_cdb cdb;
|
|
} __attribute__ (( packed ));
|
|
|
|
/** Type of an SRP SCSI command */
|
|
#define SRP_CMD 0x02
|
|
|
|
/** Use solicited notification for unsuccessful completions */
|
|
#define SRP_CMD_FLAG_UCSOLNT 0x04
|
|
|
|
/** Use solicited notification for successful completions */
|
|
#define SRP_CMD_FLAG_SCSOLNT 0x02
|
|
|
|
/** Data-out buffer format mask */
|
|
#define SRP_CMD_DO_FMT_MASK 0xf0
|
|
|
|
/** Direct data-out buffer format */
|
|
#define SRP_CMD_DO_FMT_DIRECT 0x10
|
|
|
|
/** Indirect data-out buffer format */
|
|
#define SRP_CMD_DO_FMT_INDIRECT 0x20
|
|
|
|
/** Data-in buffer format mask */
|
|
#define SRP_CMD_DI_FMT_MASK 0x0f
|
|
|
|
/** Direct data-in buffer format */
|
|
#define SRP_CMD_DI_FMT_DIRECT 0x01
|
|
|
|
/** Indirect data-in buffer format */
|
|
#define SRP_CMD_DI_FMT_INDIRECT 0x02
|
|
|
|
/** Use the rules for a simple task attribute */
|
|
#define SRP_CMD_TASK_ATTR_SIMPLE 0x00
|
|
|
|
/** Use the rules for a head of queue task attribute */
|
|
#define SRP_CMD_TASK_ATTR_QUEUE_HEAD 0x01
|
|
|
|
/** Use the rules for an ordered task attribute */
|
|
#define SRP_CMD_TASK_ATTR_ORDERED 0x02
|
|
|
|
/** Use the rules for an automatic contingent allegiance task attribute */
|
|
#define SRP_CMD_TASK_ATTR_AUTOMATIC_CONTINGENT_ALLEGIANCE 0x08
|
|
|
|
/** An SRP memory descriptor */
|
|
struct srp_memory_descriptor {
|
|
/** Virtual address */
|
|
uint64_t address;
|
|
/** Memory handle */
|
|
uint32_t handle;
|
|
/** Data length */
|
|
uint32_t len;
|
|
} __attribute__ (( packed ));
|
|
|
|
/*****************************************************************************
|
|
*
|
|
* SCSI response
|
|
*
|
|
*****************************************************************************
|
|
*/
|
|
|
|
/** An SRP SCSI response */
|
|
struct srp_rsp {
|
|
/** Information unit type
|
|
*
|
|
* This must be @c SRP_RSP
|
|
*/
|
|
uint8_t type;
|
|
/** Flags
|
|
*
|
|
* This is the bitwise OR of zero or more @c SRP_RSP_FLAG_XXX
|
|
* constants.
|
|
*/
|
|
uint8_t flags;
|
|
/** Reserved */
|
|
uint8_t reserved0[2];
|
|
/** Request limit delta */
|
|
uint32_t request_limit_delta;
|
|
/** Tag */
|
|
struct srp_tag tag;
|
|
/** Reserved */
|
|
uint8_t reserved1[2];
|
|
/** Valid fields
|
|
*
|
|
* This is the bitwise OR of zero or more @c SRP_RSP_VALID_XXX
|
|
* constants.
|
|
*/
|
|
uint8_t valid;
|
|
/** Status
|
|
*
|
|
* This is the SCSI status code.
|
|
*/
|
|
uint8_t status;
|
|
/** Data-out residual count */
|
|
uint32_t data_out_residual_count;
|
|
/** Data-in residual count */
|
|
uint32_t data_in_residual_count;
|
|
/** Sense data list length */
|
|
uint32_t sense_data_len;
|
|
/** Response data list length */
|
|
uint32_t response_data_len;
|
|
} __attribute__ (( packed ));
|
|
|
|
/** Type of an SRP SCSI response */
|
|
#define SRP_RSP 0xc1
|
|
|
|
/** The initiator specified solicited notification of this response */
|
|
#define SRP_RSP_FLAG_SOLNT 0x01
|
|
|
|
/** Data-in residual count field is valid and represents an underflow */
|
|
#define SRP_RSP_VALID_DIUNDER 0x20
|
|
|
|
/** Data-in residual count field is valid and represents an overflow */
|
|
#define SRP_RSP_VALID_DIOVER 0x10
|
|
|
|
/** Data-out residual count field is valid and represents an underflow */
|
|
#define SRP_RSP_VALID_DOUNDER 0x08
|
|
|
|
/** Data-out residual count field is valid and represents an overflow */
|
|
#define SRP_RSP_VALID_DOOVER 0x04
|
|
|
|
/** Sense data list length field is valid */
|
|
#define SRP_RSP_VALID_SNSVALID 0x02
|
|
|
|
/** Response data list length field is valid */
|
|
#define SRP_RSP_VALID_RSPVALID 0x01
|
|
|
|
/**
|
|
* Get response data portion of SCSI response
|
|
*
|
|
* @v rsp SCSI response
|
|
* @ret response_data Response data, or NULL if not present
|
|
*/
|
|
static inline void * srp_rsp_response_data ( struct srp_rsp *rsp ) {
|
|
return ( ( rsp->valid & SRP_RSP_VALID_RSPVALID ) ?
|
|
( ( ( void * ) rsp ) + sizeof ( *rsp ) ) : NULL );
|
|
}
|
|
|
|
/**
|
|
* Get length of response data portion of SCSI response
|
|
*
|
|
* @v rsp SCSI response
|
|
* @ret response_data_len Response data length
|
|
*/
|
|
static inline size_t srp_rsp_response_data_len ( struct srp_rsp *rsp ) {
|
|
return ( ( rsp->valid & SRP_RSP_VALID_RSPVALID ) ?
|
|
ntohl ( rsp->response_data_len ) : 0 );
|
|
}
|
|
|
|
/**
|
|
* Get sense data portion of SCSI response
|
|
*
|
|
* @v rsp SCSI response
|
|
* @ret sense_data Sense data, or NULL if not present
|
|
*/
|
|
static inline void * srp_rsp_sense_data ( struct srp_rsp *rsp ) {
|
|
return ( ( rsp->valid & SRP_RSP_VALID_SNSVALID ) ?
|
|
( ( ( void * ) rsp ) + sizeof ( *rsp ) +
|
|
srp_rsp_response_data_len ( rsp ) ) : NULL );
|
|
}
|
|
|
|
/**
|
|
* Get length of sense data portion of SCSI response
|
|
*
|
|
* @v rsp SCSI response
|
|
* @ret sense_data_len Sense data length
|
|
*/
|
|
static inline size_t srp_rsp_sense_data_len ( struct srp_rsp *rsp ) {
|
|
return ( ( rsp->valid & SRP_RSP_VALID_SNSVALID ) ?
|
|
ntohl ( rsp->sense_data_len ) : 0 );
|
|
}
|
|
|
|
/*****************************************************************************
|
|
*
|
|
* Credit request
|
|
*
|
|
*****************************************************************************
|
|
*/
|
|
|
|
/** An SRP credit request */
|
|
struct srp_cred_req {
|
|
/** Information unit type
|
|
*
|
|
* This must be @c SRP_CRED_REQ
|
|
*/
|
|
uint8_t type;
|
|
/** Flags
|
|
*
|
|
* This is the bitwise OR of zero or more
|
|
* @c SRP_CRED_REQ_FLAG_XXX constants.
|
|
*/
|
|
uint8_t flags;
|
|
/** Reserved */
|
|
uint8_t reserved0[2];
|
|
/** Request limit delta */
|
|
uint32_t request_limit_delta;
|
|
/** Tag */
|
|
struct srp_tag tag;
|
|
} __attribute__ (( packed ));
|
|
|
|
/** Type of an SRP credit request */
|
|
#define SRP_CRED_REQ 0x81
|
|
|
|
/** The initiator specified solicited notification of credit requests */
|
|
#define SRP_CRED_REQ_FLAG_SOLNT 0x01
|
|
|
|
/*****************************************************************************
|
|
*
|
|
* Credit response
|
|
*
|
|
*****************************************************************************
|
|
*/
|
|
|
|
/** An SRP credit response */
|
|
struct srp_cred_rsp {
|
|
/** Information unit type
|
|
*
|
|
* This must be @c SRP_CRED_RSP
|
|
*/
|
|
uint8_t type;
|
|
/** Reserved */
|
|
uint8_t reserved0[7];
|
|
/** Tag */
|
|
struct srp_tag tag;
|
|
} __attribute__ (( packed ));
|
|
|
|
/** Type of an SRP credit response */
|
|
#define SRP_CRED_RSP 0x41
|
|
|
|
/*****************************************************************************
|
|
*
|
|
* Asynchronous event request
|
|
*
|
|
*****************************************************************************
|
|
*/
|
|
|
|
/** An SRP asynchronous event request */
|
|
struct srp_aer_req {
|
|
/** Information unit type
|
|
*
|
|
* This must be @c SRP_AER_REQ
|
|
*/
|
|
uint8_t type;
|
|
/** Flags
|
|
*
|
|
* This is the bitwise OR of zero or more @c
|
|
* SRP_AER_REQ_FLAG_XXX constants.
|
|
*/
|
|
uint8_t flags;
|
|
/** Reserved */
|
|
uint8_t reserved0[2];
|
|
/** Request limit delta */
|
|
uint32_t request_limit_delta;
|
|
/** Tag */
|
|
struct srp_tag tag;
|
|
/** Reserved */
|
|
uint8_t reserved1[4];
|
|
/** Logical unit number */
|
|
struct scsi_lun lun;
|
|
/** Sense data list length */
|
|
uint32_t sense_data_len;
|
|
/** Reserved */
|
|
uint8_t reserved2[4];
|
|
} __attribute__ (( packed ));
|
|
|
|
/** Type of an SRP asynchronous event request */
|
|
#define SRP_AER_REQ 0x82
|
|
|
|
/** The initiator specified solicited notification of asynchronous events */
|
|
#define SRP_AER_REQ_FLAG_SOLNT 0x01
|
|
|
|
/**
|
|
* Get sense data portion of asynchronous event request
|
|
*
|
|
* @v aer_req SRP asynchronous event request
|
|
* @ret sense_data Sense data
|
|
*/
|
|
static inline __always_inline void *
|
|
srp_aer_req_sense_data ( struct srp_aer_req *aer_req ) {
|
|
return ( ( ( void * ) aer_req ) + sizeof ( *aer_req ) );
|
|
}
|
|
|
|
/**
|
|
* Get length of sense data portion of asynchronous event request
|
|
*
|
|
* @v aer_req SRP asynchronous event request
|
|
* @ret sense_data_len Sense data length
|
|
*/
|
|
static inline __always_inline size_t
|
|
srp_aer_req_sense_data_len ( struct srp_aer_req *aer_req ) {
|
|
return ( ntohl ( aer_req->sense_data_len ) );
|
|
}
|
|
|
|
/*****************************************************************************
|
|
*
|
|
* Asynchronous event response
|
|
*
|
|
*****************************************************************************
|
|
*/
|
|
|
|
/** An SRP asynchronous event response */
|
|
struct srp_aer_rsp {
|
|
/** Information unit type
|
|
*
|
|
* This must be @c SRP_AER_RSP
|
|
*/
|
|
uint8_t type;
|
|
/** Reserved */
|
|
uint8_t reserved0[7];
|
|
/** Tag */
|
|
struct srp_tag tag;
|
|
} __attribute__ (( packed ));
|
|
|
|
/** Type of an SRP asynchronous event response */
|
|
#define SRP_AER_RSP 0x42
|
|
|
|
/*****************************************************************************
|
|
*
|
|
* Information units
|
|
*
|
|
*****************************************************************************
|
|
*/
|
|
|
|
/** Maximum length of any initiator-to-target IU that we will send
|
|
*
|
|
* The longest IU is a SRP_CMD with no additional CDB and two direct
|
|
* data buffer descriptors, which comes to 80 bytes.
|
|
*/
|
|
#define SRP_MAX_I_T_IU_LEN 80
|
|
|
|
/*****************************************************************************
|
|
*
|
|
* SRP device
|
|
*
|
|
*****************************************************************************
|
|
*/
|
|
|
|
struct srp_device;
|
|
|
|
/** An SRP transport type */
|
|
struct srp_transport_type {
|
|
/** Length of transport private data */
|
|
size_t priv_len;
|
|
/** Parse root path
|
|
*
|
|
* @v srp SRP device
|
|
* @v root_path Root path
|
|
* @ret Return status code
|
|
*/
|
|
int ( * parse_root_path ) ( struct srp_device *srp,
|
|
const char *root_path );
|
|
/** Connect SRP session
|
|
*
|
|
* @v srp SRP device
|
|
* @ret rc Return status code
|
|
*
|
|
* This method should open the underlying socket.
|
|
*/
|
|
int ( * connect ) ( struct srp_device *srp );
|
|
};
|
|
|
|
/** An SRP device */
|
|
struct srp_device {
|
|
/** Reference count */
|
|
struct refcnt refcnt;
|
|
|
|
/** Initiator and target port IDs */
|
|
struct srp_port_ids port_ids;
|
|
/** Logical unit number */
|
|
struct scsi_lun lun;
|
|
/** Memory handle */
|
|
uint32_t memory_handle;
|
|
|
|
/** Current state
|
|
*
|
|
* This is the bitwise-OR of zero or more @c SRP_STATE_XXX
|
|
* flags.
|
|
*/
|
|
unsigned int state;
|
|
/** Retry counter */
|
|
unsigned int retry_count;
|
|
/** Current SCSI command */
|
|
struct scsi_command *command;
|
|
|
|
/** Underlying data transfer interface */
|
|
struct xfer_interface socket;
|
|
|
|
/** Transport type */
|
|
struct srp_transport_type *transport;
|
|
/** Transport private data */
|
|
char transport_priv[0];
|
|
};
|
|
|
|
/**
|
|
* Get SRP transport private data
|
|
*
|
|
* @v srp SRP device
|
|
* @ret priv SRP transport private data
|
|
*/
|
|
static inline __always_inline void *
|
|
srp_transport_priv ( struct srp_device *srp ) {
|
|
return ( ( void * ) srp->transport_priv );
|
|
}
|
|
|
|
/** SRP state flags */
|
|
enum srp_state {
|
|
/** Underlying socket is open */
|
|
SRP_STATE_SOCKET_OPEN = 0x0001,
|
|
/** Session is logged in */
|
|
SRP_STATE_LOGGED_IN = 0x0002,
|
|
};
|
|
|
|
/** Maximum number of SRP retry attempts */
|
|
#define SRP_MAX_RETRIES 3
|
|
|
|
extern int srp_attach ( struct scsi_device *scsi, const char *root_path );
|
|
extern void srp_detach ( struct scsi_device *scsi );
|
|
|
|
#endif /* _GPXE_SRP_H */
|