Home | History | Annotate | Download | only in gpxe
      1 #ifndef _GPXE_SRP_H
      2 #define _GPXE_SRP_H
      3 
      4 /** @file
      5  *
      6  * SCSI RDMA Protocol
      7  *
      8  */
      9 
     10 FILE_LICENCE ( BSD2 );
     11 
     12 #include <stdint.h>
     13 #include <byteswap.h>
     14 #include <gpxe/iobuf.h>
     15 #include <gpxe/xfer.h>
     16 #include <gpxe/scsi.h>
     17 
     18 /*****************************************************************************
     19  *
     20  * Common fields
     21  *
     22  *****************************************************************************
     23  */
     24 
     25 /** An SRP information unit tag */
     26 struct srp_tag {
     27 	uint32_t dwords[2];
     28 } __attribute__ (( packed ));
     29 
     30 /** An SRP port ID */
     31 struct srp_port_id {
     32 	uint8_t bytes[16];
     33 } __attribute__ (( packed ));
     34 
     35 /** An SRP port ID pair */
     36 struct srp_port_ids {
     37 	/** Initiator port ID */
     38 	struct srp_port_id initiator;
     39 	/** Target port ID */
     40 	struct srp_port_id target;
     41 } __attribute__ (( packed ));
     42 
     43 /** SRP information unit common fields */
     44 struct srp_common {
     45 	/** Information unit type */
     46 	uint8_t type;
     47 	/** Reserved */
     48 	uint8_t reserved0[7];
     49 	/** Tag */
     50 	struct srp_tag tag;
     51 } __attribute__ (( packed ));
     52 
     53 /*****************************************************************************
     54  *
     55  * Login request
     56  *
     57  *****************************************************************************
     58  */
     59 
     60 /** An SRP login request information unit */
     61 struct srp_login_req {
     62 	/** Information unit type
     63 	 *
     64 	 * This must be @c SRP_LOGIN_REQ
     65 	 */
     66 	uint8_t type;
     67 	/** Reserved */
     68 	uint8_t reserved0[7];
     69 	/** Tag */
     70 	struct srp_tag tag;
     71 	/** Requested maximum initiator to target IU length */
     72 	uint32_t max_i_t_iu_len;
     73 	/** Reserved */
     74 	uint8_t reserved1[4];
     75 	/** Required buffer formats
     76 	 *
     77 	 * This is the bitwise OR of one or more @c
     78 	 * SRP_LOGIN_REQ_FMT_XXX constants.
     79 	 */
     80 	uint16_t required_buffer_formats;
     81 	/** Flags
     82 	 *
     83 	 * This is the bitwise OR of zero or more @c
     84 	 * SRP_LOGIN_REQ_FLAG_XXX and @c SRP_LOGIN_REQ_MCA_XXX
     85 	 * constants.
     86 	 */
     87 	uint8_t flags;
     88 	/** Reserved */
     89 	uint8_t reserved2[5];
     90 	/** Initiator and target port identifiers */
     91 	struct srp_port_ids port_ids;
     92 } __attribute__ (( packed ));
     93 
     94 /** Type of an SRP login request */
     95 #define SRP_LOGIN_REQ 0x00
     96 
     97 /** Require indirect data buffer descriptor format */
     98 #define SRP_LOGIN_REQ_FMT_IDBD 0x04
     99 
    100 /** Require direct data buffer descriptor format */
    101 #define SRP_LOGIN_REQ_FMT_DDBD 0x02
    102 
    103 /** Use solicited notification for asynchronous events */
    104 #define SRP_LOGIN_REQ_FLAG_AESOLNT 0x40
    105 
    106 /** Use solicited notification for credit request */
    107 #define SRP_LOGIN_REQ_FLAG_CRSOLNT 0x20
    108 
    109 /** Use solicited notification for logouts */
    110 #define SRP_LOGIN_REQ_FLAG_LOSOLNT 0x10
    111 
    112 /** Multi-channel action mask */
    113 #define SRP_LOGIN_REQ_MCA_MASK 0x03
    114 
    115 /** Single RDMA channel operation */
    116 #define SRP_LOGIN_REQ_MCA_SINGLE_CHANNEL 0x00
    117 
    118 /** Multiple independent RDMA channel operation */
    119 #define SRP_LOGIN_REQ_MCA_MULTIPLE_CHANNELS 0x01
    120 
    121 /*****************************************************************************
    122  *
    123  * Login response
    124  *
    125  *****************************************************************************
    126  */
    127 
    128 /** An SRP login response */
    129 struct srp_login_rsp {
    130 	/** Information unit type
    131 	 *
    132 	 * This must be @c SRP_LOGIN_RSP
    133 	 */
    134 	uint8_t type;
    135 	/** Reserved */
    136 	uint8_t reserved0[3];
    137 	/** Request limit delta */
    138 	uint32_t request_limit_delta;
    139 	/** Tag */
    140 	struct srp_tag tag;
    141 	/** Maximum initiator to target IU length */
    142 	uint32_t max_i_t_iu_len;
    143 	/** Maximum target to initiator IU length */
    144 	uint32_t max_t_i_iu_len;
    145 	/** Supported buffer formats
    146 	 *
    147 	 * This is the bitwise OR of one or more @c
    148 	 * SRP_LOGIN_RSP_FMT_XXX constants.
    149 	 */
    150 	uint16_t supported_buffer_formats;
    151 	/** Flags
    152 	 *
    153 	 * This is the bitwise OR of zero or more @c
    154 	 * SRP_LOGIN_RSP_FLAG_XXX and @c SRP_LOGIN_RSP_MCR_XXX
    155 	 * constants.
    156 	 */
    157 	uint8_t flags;
    158 	/** Reserved */
    159 	uint8_t reserved1[25];
    160 } __attribute__ (( packed ));
    161 
    162 /** Type of an SRP login response */
    163 #define SRP_LOGIN_RSP 0xc0
    164 
    165 /** Indirect data buffer descriptor format supported */
    166 #define SRP_LOGIN_RSP_FMT_IDBD 0x04
    167 
    168 /** Direct data buffer descriptor format supported */
    169 #define SRP_LOGIN_RSP_FMT_DDBD 0x02
    170 
    171 /** Solicited notification is supported */
    172 #define SRP_LOGIN_RSP_FLAG_SOLNTSUP 0x10
    173 
    174 /** Multi-channel result mask */
    175 #define SRP_LOGIN_RSP_MCR_MASK 0x03
    176 
    177 /** No existing RDMA channels were associated with the same I_T nexus */
    178 #define SRP_LOGIN_RSP_MCR_NO_EXISTING_CHANNELS 0x00
    179 
    180 /** One or more existing RDMA channels were terminated */
    181 #define SRP_LOGIN_RSP_MCR_EXISTING_CHANNELS_TERMINATED 0x01
    182 
    183 /** One or more existing RDMA channels continue to operate independently */
    184 #define SRP_LOGIN_RSP_MCR_EXISTING_CHANNELS_CONTINUE 0x02
    185 
    186 /*****************************************************************************
    187  *
    188  * Login rejection
    189  *
    190  *****************************************************************************
    191  */
    192 
    193 /** An SRP login rejection */
    194 struct srp_login_rej {
    195 	/** Information unit type
    196 	 *
    197 	 * This must be @c SRP_LOGIN_REJ
    198 	 */
    199 	uint8_t type;
    200 	/** Reserved */
    201 	uint8_t reserved0[3];
    202 	/** Reason
    203 	 *
    204 	 * This is a @c SRP_LOGIN_REJ_REASON_XXX constant.
    205 	 */
    206 	uint32_t reason;
    207 	/** Tag */
    208 	struct srp_tag tag;
    209 	/** Reserved */
    210 	uint8_t reserved1[8];
    211 	/** Supported buffer formats
    212 	 *
    213 	 * This is the bitwise OR of one or more @c
    214 	 * SRP_LOGIN_REJ_FMT_XXX constants.
    215 	 */
    216 	uint16_t supported_buffer_formats;
    217 	/** Reserved */
    218 	uint8_t reserved2[6];
    219 } __attribute__ (( packed ));
    220 
    221 /** Type of an SRP login rejection */
    222 #define SRP_LOGIN_REJ 0xc2
    223 
    224 /** Unable to establish RDMA channel, no reason specified */
    225 #define SRP_LOGIN_REJ_REASON_UNKNOWN 0x00010000UL
    226 
    227 /** Insufficient RDMA channel resources */
    228 #define SRP_LOGIN_REJ_REASON_INSUFFICIENT_RESOURCES 0x00010001UL
    229 
    230 /** Requested maximum initiator to target IU length value too large */
    231 #define SRP_LOGIN_REJ_REASON_BAD_MAX_I_T_IU_LEN 0x00010002UL
    232 
    233 /** Unable to associate RDMA channel with specified I_T nexus */
    234 #define SRP_LOGIN_REJ_REASON_CANNOT_ASSOCIATE 0x00010003UL
    235 
    236 /** One or more requested data buffer descriptor formats are not supported */
    237 #define SRP_LOGIN_REJ_REASON_UNSUPPORTED_BUFFER_FORMAT 0x00010004UL
    238 
    239 /** SRP target port does not support multiple RDMA channels per I_T nexus */
    240 #define SRP_LOGIN_REJ_REASON_NO_MULTIPLE_CHANNELS 0x00010005UL
    241 
    242 /** RDMA channel limit reached for this initiator */
    243 #define SRP_LOGIN_REJ_REASON_NO_MORE_CHANNELS 0x00010006UL
    244 
    245 /** Indirect data buffer descriptor format supported */
    246 #define SRP_LOGIN_REJ_FMT_IDBD 0x04
    247 
    248 /** Direct data buffer descriptor format supported */
    249 #define SRP_LOGIN_REJ_FMT_DDBD 0x02
    250 
    251 /*****************************************************************************
    252  *
    253  * Initiator logout
    254  *
    255  *****************************************************************************
    256  */
    257 
    258 /** An SRP initiator logout request */
    259 struct srp_i_logout {
    260 	/** Information unit type
    261 	 *
    262 	 * This must be @c SRP_I_LOGOUT
    263 	 */
    264 	uint8_t type;
    265 	/** Reserved */
    266 	uint8_t reserved0[7];
    267 	/** Tag */
    268 	struct srp_tag tag;
    269 } __attribute__ (( packed ));
    270 
    271 /** Type of an SRP initiator logout request */
    272 #define SRP_I_LOGOUT 0x03
    273 
    274 /*****************************************************************************
    275  *
    276  * Target logout
    277  *
    278  *****************************************************************************
    279  */
    280 
    281 /** An SRP target logout request */
    282 struct srp_t_logout {
    283 	/** Information unit type
    284 	 *
    285 	 * This must be @c SRP_T_LOGOUT
    286 	 */
    287 	uint8_t type;
    288 	/** Flags
    289 	 *
    290 	 * This is the bitwise OR of zero or more @c
    291 	 * SRP_T_LOGOUT_FLAG_XXX constants.
    292 	 */
    293 	uint8_t flags;
    294 	/** Reserved */
    295 	uint8_t reserved0[2];
    296 	/** Reason
    297 	 *
    298 	 * This is a @c SRP_T_LOGOUT_REASON_XXX constant.
    299 	 */
    300 	uint32_t reason;
    301 	/** Tag */
    302 	struct srp_tag tag;
    303 } __attribute__ (( packed ));
    304 
    305 /** Type of an SRP target logout request */
    306 #define SRP_T_LOGOUT 0x80
    307 
    308 /** The initiator specified solicited notification of logouts */
    309 #define SRP_T_LOGOUT_FLAG_SOLNT 0x01
    310 
    311 /** No reason specified */
    312 #define SRP_T_LOGOUT_REASON_UNKNOWN 0x00000000UL
    313 
    314 /** Inactive RDMA channel (reclaiming resources) */
    315 #define SRP_T_LOGOUT_REASON_INACTIVE 0x00000001UL
    316 
    317 /** Invalid information unit type code received by SRP target port */
    318 #define SRP_T_LOGOUT_REASON_INVALID_TYPE 0x00000002UL
    319 
    320 /** SRP initiator port sent response with no corresponding request */
    321 #define SRP_T_LOGOUT_REASON_SPURIOUS_RESPONSE 0x00000003UL
    322 
    323 /** RDMA channel disconnected due to multi-channel action code in new login */
    324 #define SRP_T_LOGOUT_REASON_MCA 0x00000004UL
    325 
    326 /** Unsuppported format code value specified in data-out buffer descriptor */
    327 #define SRP_T_LOGOUT_UNSUPPORTED_DATA_OUT_FORMAT 0x00000005UL
    328 
    329 /** Unsuppported format code value specified in data-in buffer descriptor */
    330 #define SRP_T_LOGOUT_UNSUPPORTED_DATA_IN_FORMAT 0x00000006UL
    331 
    332 /** Invalid length for IU type */
    333 #define SRP_T_LOGOUT_INVALID_IU_LEN 0x00000008UL
    334 
    335 /*****************************************************************************
    336  *
    337  * Task management
    338  *
    339  *****************************************************************************
    340  */
    341 
    342 /** An SRP task management request */
    343 struct srp_tsk_mgmt {
    344 	/** Information unit type
    345 	 *
    346 	 * This must be @c SRP_TSK_MGMT
    347 	 */
    348 	uint8_t type;
    349 	/** Flags
    350 	 *
    351 	 * This is the bitwise OR of zero or more
    352 	 * @c SRP_TSK_MGMT_FLAG_XXX constants.
    353 	 */
    354 	uint8_t flags;
    355 	/** Reserved */
    356 	uint8_t reserved0[6];
    357 	/** Tag */
    358 	struct srp_tag tag;
    359 	/** Reserved */
    360 	uint8_t reserved1[4];
    361 	/** Logical unit number */
    362 	struct scsi_lun lun;
    363 	/** Reserved */
    364 	uint8_t reserved2[2];
    365 	/** Task management function
    366 	 *
    367 	 * This is a @c SRP_TASK_MGMT_FUNC_XXX constant
    368 	 */
    369 	uint8_t function;
    370 	/** Reserved */
    371 	uint8_t reserved3[1];
    372 	/** Tag of task to be managed */
    373 	struct srp_tag managed_tag;
    374 	/** Reserved */
    375 	uint8_t reserved4[8];
    376 } __attribute__ (( packed ));
    377 
    378 /** Type of an SRP task management request */
    379 #define SRP_TSK_MGMT 0x01
    380 
    381 /** Use solicited notification for unsuccessful completions */
    382 #define SRP_TSK_MGMT_FLAG_UCSOLNT 0x04
    383 
    384 /** Use solicited notification for successful completions */
    385 #define SRP_TSK_MGMT_FLAG_SCSOLNT 0x02
    386 
    387 /** The task manager shall perform an ABORT TASK function */
    388 #define SRP_TSK_MGMT_FUNC_ABORT_TASK 0x01
    389 
    390 /** The task manager shall perform an ABORT TASK SET function */
    391 #define SRP_TSK_MGMT_FUNC_ABORT_TASK_SET 0x02
    392 
    393 /** The task manager shall perform a CLEAR TASK SET function */
    394 #define SRP_TSK_MGMT_FUNC_CLEAR_TASK_SET 0x04
    395 
    396 /** The task manager shall perform a LOGICAL UNIT RESET function */
    397 #define SRP_TSK_MGMT_FUNC_LOGICAL_UNIT_RESET 0x08
    398 
    399 /** The task manager shall perform a CLEAR ACA function */
    400 #define SRP_TSK_MGMT_FUNC_CLEAR_ACA 0x40
    401 
    402 /*****************************************************************************
    403  *
    404  * SCSI command
    405  *
    406  *****************************************************************************
    407  */
    408 
    409 /** An SRP SCSI command */
    410 struct srp_cmd {
    411 	/** Information unit type
    412 	 *
    413 	 * This must be @c SRP_CMD
    414 	 */
    415 	uint8_t type;
    416 	/** Flags
    417 	 *
    418 	 * This is the bitwise OR of zero or more @c SRP_CMD_FLAG_XXX
    419 	 * constants.
    420 	 */
    421 	uint8_t flags;
    422 	/** Reserved */
    423 	uint8_t reserved0[3];
    424 	/** Data buffer descriptor formats
    425 	 *
    426 	 * This is the bitwise OR of one @c SRP_CMD_DO_FMT_XXX and one @c
    427 	 * SRP_CMD_DI_FMT_XXX constant.
    428 	 */
    429 	uint8_t data_buffer_formats;
    430 	/** Data-out buffer descriptor count */
    431 	uint8_t data_out_buffer_count;
    432 	/** Data-in buffer descriptor count */
    433 	uint8_t data_in_buffer_count;
    434 	/** Tag */
    435 	struct srp_tag tag;
    436 	/** Reserved */
    437 	uint8_t reserved1[4];
    438 	/** Logical unit number */
    439 	struct scsi_lun lun;
    440 	/** Reserved */
    441 	uint8_t reserved2[1];
    442 	/** Task attribute
    443 	 *
    444 	 * This is a @c SRP_CMD_TASK_ATTR_XXX constant.
    445 	 */
    446 	uint8_t task_attr;
    447 	/** Reserved */
    448 	uint8_t reserved3[1];
    449 	/** Additional CDB length */
    450 	uint8_t additional_cdb_len;
    451 	/** Command data block */
    452 	union scsi_cdb cdb;
    453 } __attribute__ (( packed ));
    454 
    455 /** Type of an SRP SCSI command */
    456 #define SRP_CMD 0x02
    457 
    458 /** Use solicited notification for unsuccessful completions */
    459 #define SRP_CMD_FLAG_UCSOLNT 0x04
    460 
    461 /** Use solicited notification for successful completions */
    462 #define SRP_CMD_FLAG_SCSOLNT 0x02
    463 
    464 /** Data-out buffer format mask */
    465 #define SRP_CMD_DO_FMT_MASK 0xf0
    466 
    467 /** Direct data-out buffer format */
    468 #define SRP_CMD_DO_FMT_DIRECT 0x10
    469 
    470 /** Indirect data-out buffer format */
    471 #define SRP_CMD_DO_FMT_INDIRECT 0x20
    472 
    473 /** Data-in buffer format mask */
    474 #define SRP_CMD_DI_FMT_MASK 0x0f
    475 
    476 /** Direct data-in buffer format */
    477 #define SRP_CMD_DI_FMT_DIRECT 0x01
    478 
    479 /** Indirect data-in buffer format */
    480 #define SRP_CMD_DI_FMT_INDIRECT 0x02
    481 
    482 /** Use the rules for a simple task attribute */
    483 #define SRP_CMD_TASK_ATTR_SIMPLE 0x00
    484 
    485 /** Use the rules for a head of queue task attribute */
    486 #define SRP_CMD_TASK_ATTR_QUEUE_HEAD 0x01
    487 
    488 /** Use the rules for an ordered task attribute */
    489 #define SRP_CMD_TASK_ATTR_ORDERED 0x02
    490 
    491 /** Use the rules for an automatic contingent allegiance task attribute */
    492 #define SRP_CMD_TASK_ATTR_AUTOMATIC_CONTINGENT_ALLEGIANCE 0x08
    493 
    494 /** An SRP memory descriptor */
    495 struct srp_memory_descriptor {
    496 	/** Virtual address */
    497 	uint64_t address;
    498 	/** Memory handle */
    499 	uint32_t handle;
    500 	/** Data length */
    501 	uint32_t len;
    502 } __attribute__ (( packed ));
    503 
    504 /*****************************************************************************
    505  *
    506  * SCSI response
    507  *
    508  *****************************************************************************
    509  */
    510 
    511 /** An SRP SCSI response */
    512 struct srp_rsp {
    513 	/** Information unit type
    514 	 *
    515 	 * This must be @c SRP_RSP
    516 	 */
    517 	uint8_t type;
    518 	/** Flags
    519 	 *
    520 	 * This is the bitwise OR of zero or more @c SRP_RSP_FLAG_XXX
    521 	 * constants.
    522 	 */
    523 	uint8_t flags;
    524 	/** Reserved */
    525 	uint8_t reserved0[2];
    526 	/** Request limit delta */
    527 	uint32_t request_limit_delta;
    528 	/** Tag */
    529 	struct srp_tag tag;
    530 	/** Reserved */
    531 	uint8_t reserved1[2];
    532 	/** Valid fields
    533 	 *
    534 	 * This is the bitwise OR of zero or more @c SRP_RSP_VALID_XXX
    535 	 * constants.
    536 	 */
    537 	uint8_t valid;
    538 	/** Status
    539 	 *
    540 	 * This is the SCSI status code.
    541 	 */
    542 	uint8_t status;
    543 	/** Data-out residual count */
    544 	uint32_t data_out_residual_count;
    545 	/** Data-in residual count */
    546 	uint32_t data_in_residual_count;
    547 	/** Sense data list length */
    548 	uint32_t sense_data_len;
    549 	/** Response data list length */
    550 	uint32_t response_data_len;
    551 } __attribute__ (( packed ));
    552 
    553 /** Type of an SRP SCSI response */
    554 #define SRP_RSP 0xc1
    555 
    556 /** The initiator specified solicited notification of this response */
    557 #define SRP_RSP_FLAG_SOLNT 0x01
    558 
    559 /** Data-in residual count field is valid and represents an underflow */
    560 #define SRP_RSP_VALID_DIUNDER 0x20
    561 
    562 /** Data-in residual count field is valid and represents an overflow */
    563 #define SRP_RSP_VALID_DIOVER 0x10
    564 
    565 /** Data-out residual count field is valid and represents an underflow */
    566 #define SRP_RSP_VALID_DOUNDER 0x08
    567 
    568 /** Data-out residual count field is valid and represents an overflow */
    569 #define SRP_RSP_VALID_DOOVER 0x04
    570 
    571 /** Sense data list length field is valid */
    572 #define SRP_RSP_VALID_SNSVALID 0x02
    573 
    574 /** Response data list length field is valid */
    575 #define SRP_RSP_VALID_RSPVALID 0x01
    576 
    577 /**
    578  * Get response data portion of SCSI response
    579  *
    580  * @v rsp			SCSI response
    581  * @ret response_data		Response data, or NULL if not present
    582  */
    583 static inline void * srp_rsp_response_data ( struct srp_rsp *rsp ) {
    584 	return ( ( rsp->valid & SRP_RSP_VALID_RSPVALID ) ?
    585 		 ( ( ( void * ) rsp ) + sizeof ( *rsp ) ) : NULL );
    586 }
    587 
    588 /**
    589  * Get length of response data portion of SCSI response
    590  *
    591  * @v rsp			SCSI response
    592  * @ret response_data_len	Response data length
    593  */
    594 static inline size_t srp_rsp_response_data_len ( struct srp_rsp *rsp ) {
    595 	return ( ( rsp->valid & SRP_RSP_VALID_RSPVALID ) ?
    596 		 ntohl ( rsp->response_data_len ) : 0 );
    597 }
    598 
    599 /**
    600  * Get sense data portion of SCSI response
    601  *
    602  * @v rsp			SCSI response
    603  * @ret sense_data		Sense data, or NULL if not present
    604  */
    605 static inline void * srp_rsp_sense_data ( struct srp_rsp *rsp ) {
    606 	return ( ( rsp->valid & SRP_RSP_VALID_SNSVALID ) ?
    607 		 ( ( ( void * ) rsp ) + sizeof ( *rsp ) +
    608 		   srp_rsp_response_data_len ( rsp ) ) : NULL );
    609 }
    610 
    611 /**
    612  * Get length of sense data portion of SCSI response
    613  *
    614  * @v rsp			SCSI response
    615  * @ret sense_data_len		Sense data length
    616  */
    617 static inline size_t srp_rsp_sense_data_len ( struct srp_rsp *rsp ) {
    618 	return ( ( rsp->valid & SRP_RSP_VALID_SNSVALID ) ?
    619 		 ntohl ( rsp->sense_data_len ) : 0 );
    620 }
    621 
    622 /*****************************************************************************
    623  *
    624  * Credit request
    625  *
    626  *****************************************************************************
    627  */
    628 
    629 /** An SRP credit request */
    630 struct srp_cred_req {
    631 	/** Information unit type
    632 	 *
    633 	 * This must be @c SRP_CRED_REQ
    634 	 */
    635 	uint8_t type;
    636 	/** Flags
    637 	 *
    638 	 * This is the bitwise OR of zero or more
    639 	 * @c SRP_CRED_REQ_FLAG_XXX constants.
    640 	 */
    641 	uint8_t flags;
    642 	/** Reserved */
    643 	uint8_t reserved0[2];
    644 	/** Request limit delta */
    645 	uint32_t request_limit_delta;
    646 	/** Tag */
    647 	struct srp_tag tag;
    648 } __attribute__ (( packed ));
    649 
    650 /** Type of an SRP credit request */
    651 #define SRP_CRED_REQ 0x81
    652 
    653 /** The initiator specified solicited notification of credit requests */
    654 #define SRP_CRED_REQ_FLAG_SOLNT 0x01
    655 
    656 /*****************************************************************************
    657  *
    658  * Credit response
    659  *
    660  *****************************************************************************
    661  */
    662 
    663 /** An SRP credit response */
    664 struct srp_cred_rsp {
    665 	/** Information unit type
    666 	 *
    667 	 * This must be @c SRP_CRED_RSP
    668 	 */
    669 	uint8_t type;
    670 	/** Reserved */
    671 	uint8_t reserved0[7];
    672 	/** Tag */
    673 	struct srp_tag tag;
    674 } __attribute__ (( packed ));
    675 
    676 /** Type of an SRP credit response */
    677 #define SRP_CRED_RSP 0x41
    678 
    679 /*****************************************************************************
    680  *
    681  * Asynchronous event request
    682  *
    683  *****************************************************************************
    684  */
    685 
    686 /** An SRP asynchronous event request */
    687 struct srp_aer_req {
    688 	/** Information unit type
    689 	 *
    690 	 * This must be @c SRP_AER_REQ
    691 	 */
    692 	uint8_t type;
    693 	/** Flags
    694 	 *
    695 	 * This is the bitwise OR of zero or more @c
    696 	 * SRP_AER_REQ_FLAG_XXX constants.
    697 	 */
    698 	uint8_t flags;
    699 	/** Reserved */
    700 	uint8_t reserved0[2];
    701 	/** Request limit delta */
    702 	uint32_t request_limit_delta;
    703 	/** Tag */
    704 	struct srp_tag tag;
    705 	/** Reserved */
    706 	uint8_t reserved1[4];
    707 	/** Logical unit number */
    708 	struct scsi_lun lun;
    709 	/** Sense data list length */
    710 	uint32_t sense_data_len;
    711 	/** Reserved */
    712 	uint8_t reserved2[4];
    713 } __attribute__ (( packed ));
    714 
    715 /** Type of an SRP asynchronous event request */
    716 #define SRP_AER_REQ 0x82
    717 
    718 /** The initiator specified solicited notification of asynchronous events */
    719 #define SRP_AER_REQ_FLAG_SOLNT 0x01
    720 
    721 /**
    722  * Get sense data portion of asynchronous event request
    723  *
    724  * @v aer_req			SRP asynchronous event request
    725  * @ret sense_data		Sense data
    726  */
    727 static inline __always_inline void *
    728 srp_aer_req_sense_data ( struct srp_aer_req *aer_req ) {
    729 	return ( ( ( void * ) aer_req ) + sizeof ( *aer_req ) );
    730 }
    731 
    732 /**
    733  * Get length of sense data portion of asynchronous event request
    734  *
    735  * @v aer_req			SRP asynchronous event request
    736  * @ret sense_data_len		Sense data length
    737  */
    738 static inline __always_inline size_t
    739 srp_aer_req_sense_data_len ( struct srp_aer_req *aer_req ) {
    740 	return ( ntohl ( aer_req->sense_data_len ) );
    741 }
    742 
    743 /*****************************************************************************
    744  *
    745  * Asynchronous event response
    746  *
    747  *****************************************************************************
    748  */
    749 
    750 /** An SRP asynchronous event response */
    751 struct srp_aer_rsp {
    752 	/** Information unit type
    753 	 *
    754 	 * This must be @c SRP_AER_RSP
    755 	 */
    756 	uint8_t type;
    757 	/** Reserved */
    758 	uint8_t reserved0[7];
    759 	/** Tag */
    760 	struct srp_tag tag;
    761 } __attribute__ (( packed ));
    762 
    763 /** Type of an SRP asynchronous event response */
    764 #define SRP_AER_RSP 0x42
    765 
    766 /*****************************************************************************
    767  *
    768  * Information units
    769  *
    770  *****************************************************************************
    771  */
    772 
    773 /** Maximum length of any initiator-to-target IU that we will send
    774  *
    775  * The longest IU is a SRP_CMD with no additional CDB and two direct
    776  * data buffer descriptors, which comes to 80 bytes.
    777  */
    778 #define SRP_MAX_I_T_IU_LEN 80
    779 
    780 /*****************************************************************************
    781  *
    782  * SRP device
    783  *
    784  *****************************************************************************
    785  */
    786 
    787 struct srp_device;
    788 
    789 /** An SRP transport type */
    790 struct srp_transport_type {
    791 	/** Length of transport private data */
    792 	size_t priv_len;
    793 	/** Parse root path
    794 	 *
    795 	 * @v srp		SRP device
    796 	 * @v root_path		Root path
    797 	 * @ret 		Return status code
    798 	 */
    799 	int ( * parse_root_path ) ( struct srp_device *srp,
    800 				    const char *root_path );
    801 	/** Connect SRP session
    802 	 *
    803 	 * @v srp		SRP device
    804 	 * @ret rc		Return status code
    805 	 *
    806 	 * This method should open the underlying socket.
    807 	 */
    808 	int ( * connect ) ( struct srp_device *srp );
    809 };
    810 
    811 /** An SRP device */
    812 struct srp_device {
    813 	/** Reference count */
    814 	struct refcnt refcnt;
    815 
    816 	/** Initiator and target port IDs */
    817 	struct srp_port_ids port_ids;
    818 	/** Logical unit number */
    819 	struct scsi_lun lun;
    820 	/** Memory handle */
    821 	uint32_t memory_handle;
    822 
    823 	/** Current state
    824 	 *
    825 	 * This is the bitwise-OR of zero or more @c SRP_STATE_XXX
    826 	 * flags.
    827 	 */
    828 	unsigned int state;
    829 	/** Retry counter */
    830 	unsigned int retry_count;
    831 	/** Current SCSI command */
    832 	struct scsi_command *command;
    833 
    834 	/** Underlying data transfer interface */
    835 	struct xfer_interface socket;
    836 
    837 	/** Transport type */
    838 	struct srp_transport_type *transport;
    839 	/** Transport private data */
    840 	char transport_priv[0];
    841 };
    842 
    843 /**
    844  * Get SRP transport private data
    845  *
    846  * @v srp		SRP device
    847  * @ret priv		SRP transport private data
    848  */
    849 static inline __always_inline void *
    850 srp_transport_priv ( struct srp_device *srp ) {
    851 	return ( ( void * ) srp->transport_priv );
    852 }
    853 
    854 /** SRP state flags */
    855 enum srp_state {
    856 	/** Underlying socket is open */
    857 	SRP_STATE_SOCKET_OPEN = 0x0001,
    858 	/** Session is logged in */
    859 	SRP_STATE_LOGGED_IN = 0x0002,
    860 };
    861 
    862 /** Maximum number of SRP retry attempts */
    863 #define SRP_MAX_RETRIES 3
    864 
    865 extern int srp_attach ( struct scsi_device *scsi, const char *root_path );
    866 extern void srp_detach ( struct scsi_device *scsi );
    867 
    868 #endif /* _GPXE_SRP_H */
    869