10 FILE_LICENCE ( BSD2 );
14 #include <ipxe/iobuf.h>
15 #include <ipxe/xfer.h>
16 #include <ipxe/scsi.h>
17 #include <ipxe/acpi.h>
19 /*****************************************************************************
23 *****************************************************************************
26 /** An SRP information unit tag */
30 } __attribute__ (( packed ));
32 /** SRP tag magic marker */
33 #define SRP_TAG_MAGIC 0x69505845
39 } __attribute__ (( packed ));
41 /** SRP information unit common fields */
43 /** Information unit type */
49 } __attribute__ (( packed ));
51 /*****************************************************************************
55 *****************************************************************************
58 /** An SRP login request information unit */
59 struct srp_login_req {
60 /** Information unit type
62 * This must be @c SRP_LOGIN_REQ
69 /** Requested maximum initiator to target IU length */
70 uint32_t max_i_t_iu_len;
73 /** Required buffer formats
75 * This is the bitwise OR of one or more @c
76 * SRP_LOGIN_REQ_FMT_XXX constants.
78 uint16_t required_buffer_formats;
81 * This is the bitwise OR of zero or more @c
82 * SRP_LOGIN_REQ_FLAG_XXX and @c SRP_LOGIN_REQ_MCA_XXX
88 /** Initiator port identifier */
89 union srp_port_id initiator;
90 /** Target port identifier */
91 union srp_port_id target;
92 } __attribute__ (( packed ));
94 /** Type of an SRP login request */
95 #define SRP_LOGIN_REQ 0x00
97 /** Require indirect data buffer descriptor format */
98 #define SRP_LOGIN_REQ_FMT_IDBD 0x04
100 /** Require direct data buffer descriptor format */
101 #define SRP_LOGIN_REQ_FMT_DDBD 0x02
103 /** Use solicited notification for asynchronous events */
104 #define SRP_LOGIN_REQ_FLAG_AESOLNT 0x40
106 /** Use solicited notification for credit request */
107 #define SRP_LOGIN_REQ_FLAG_CRSOLNT 0x20
109 /** Use solicited notification for logouts */
110 #define SRP_LOGIN_REQ_FLAG_LOSOLNT 0x10
112 /** Multi-channel action mask */
113 #define SRP_LOGIN_REQ_MCA_MASK 0x03
115 /** Single RDMA channel operation */
116 #define SRP_LOGIN_REQ_MCA_SINGLE_CHANNEL 0x00
118 /** Multiple independent RDMA channel operation */
119 #define SRP_LOGIN_REQ_MCA_MULTIPLE_CHANNELS 0x01
121 /*****************************************************************************
125 *****************************************************************************
128 /** An SRP login response */
129 struct srp_login_rsp {
130 /** Information unit type
132 * This must be @c SRP_LOGIN_RSP
136 uint8_t reserved0[3];
137 /** Request limit delta */
138 uint32_t request_limit_delta;
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
147 * This is the bitwise OR of one or more @c
148 * SRP_LOGIN_RSP_FMT_XXX constants.
150 uint16_t supported_buffer_formats;
153 * This is the bitwise OR of zero or more @c
154 * SRP_LOGIN_RSP_FLAG_XXX and @c SRP_LOGIN_RSP_MCR_XXX
159 uint8_t reserved1[25];
160 } __attribute__ (( packed ));
162 /** Type of an SRP login response */
163 #define SRP_LOGIN_RSP 0xc0
165 /** Indirect data buffer descriptor format supported */
166 #define SRP_LOGIN_RSP_FMT_IDBD 0x04
168 /** Direct data buffer descriptor format supported */
169 #define SRP_LOGIN_RSP_FMT_DDBD 0x02
171 /** Solicited notification is supported */
172 #define SRP_LOGIN_RSP_FLAG_SOLNTSUP 0x10
174 /** Multi-channel result mask */
175 #define SRP_LOGIN_RSP_MCR_MASK 0x03
177 /** No existing RDMA channels were associated with the same I_T nexus */
178 #define SRP_LOGIN_RSP_MCR_NO_EXISTING_CHANNELS 0x00
180 /** One or more existing RDMA channels were terminated */
181 #define SRP_LOGIN_RSP_MCR_EXISTING_CHANNELS_TERMINATED 0x01
183 /** One or more existing RDMA channels continue to operate independently */
184 #define SRP_LOGIN_RSP_MCR_EXISTING_CHANNELS_CONTINUE 0x02
186 /*****************************************************************************
190 *****************************************************************************
193 /** An SRP login rejection */
194 struct srp_login_rej {
195 /** Information unit type
197 * This must be @c SRP_LOGIN_REJ
201 uint8_t reserved0[3];
204 * This is a @c SRP_LOGIN_REJ_REASON_XXX constant.
210 uint8_t reserved1[8];
211 /** Supported buffer formats
213 * This is the bitwise OR of one or more @c
214 * SRP_LOGIN_REJ_FMT_XXX constants.
216 uint16_t supported_buffer_formats;
218 uint8_t reserved2[6];
219 } __attribute__ (( packed ));
221 /** Type of an SRP login rejection */
222 #define SRP_LOGIN_REJ 0xc2
224 /** Unable to establish RDMA channel, no reason specified */
225 #define SRP_LOGIN_REJ_REASON_UNKNOWN 0x00010000UL
227 /** Insufficient RDMA channel resources */
228 #define SRP_LOGIN_REJ_REASON_INSUFFICIENT_RESOURCES 0x00010001UL
230 /** Requested maximum initiator to target IU length value too large */
231 #define SRP_LOGIN_REJ_REASON_BAD_MAX_I_T_IU_LEN 0x00010002UL
233 /** Unable to associate RDMA channel with specified I_T nexus */
234 #define SRP_LOGIN_REJ_REASON_CANNOT_ASSOCIATE 0x00010003UL
236 /** One or more requested data buffer descriptor formats are not supported */
237 #define SRP_LOGIN_REJ_REASON_UNSUPPORTED_BUFFER_FORMAT 0x00010004UL
239 /** SRP target port does not support multiple RDMA channels per I_T nexus */
240 #define SRP_LOGIN_REJ_REASON_NO_MULTIPLE_CHANNELS 0x00010005UL
242 /** RDMA channel limit reached for this initiator */
243 #define SRP_LOGIN_REJ_REASON_NO_MORE_CHANNELS 0x00010006UL
245 /** SRP login rejection reason is defined */
246 #define SRP_LOGIN_REJ_REASON_DEFINED( reason ) \
247 ( ( (reason) & 0xfffffff0UL ) == 0x00010000UL )
249 /** Indirect data buffer descriptor format supported */
250 #define SRP_LOGIN_REJ_FMT_IDBD 0x04
252 /** Direct data buffer descriptor format supported */
253 #define SRP_LOGIN_REJ_FMT_DDBD 0x02
255 /*****************************************************************************
259 *****************************************************************************
262 /** An SRP initiator logout request */
263 struct srp_i_logout {
264 /** Information unit type
266 * This must be @c SRP_I_LOGOUT
270 uint8_t reserved0[7];
273 } __attribute__ (( packed ));
275 /** Type of an SRP initiator logout request */
276 #define SRP_I_LOGOUT 0x03
278 /*****************************************************************************
282 *****************************************************************************
285 /** An SRP target logout request */
286 struct srp_t_logout {
287 /** Information unit type
289 * This must be @c SRP_T_LOGOUT
294 * This is the bitwise OR of zero or more @c
295 * SRP_T_LOGOUT_FLAG_XXX constants.
299 uint8_t reserved0[2];
302 * This is a @c SRP_T_LOGOUT_REASON_XXX constant.
307 } __attribute__ (( packed ));
309 /** Type of an SRP target logout request */
310 #define SRP_T_LOGOUT 0x80
312 /** The initiator specified solicited notification of logouts */
313 #define SRP_T_LOGOUT_FLAG_SOLNT 0x01
315 /** No reason specified */
316 #define SRP_T_LOGOUT_REASON_UNKNOWN 0x00000000UL
318 /** Inactive RDMA channel (reclaiming resources) */
319 #define SRP_T_LOGOUT_REASON_INACTIVE 0x00000001UL
321 /** Invalid information unit type code received by SRP target port */
322 #define SRP_T_LOGOUT_REASON_INVALID_TYPE 0x00000002UL
324 /** SRP initiator port sent response with no corresponding request */
325 #define SRP_T_LOGOUT_REASON_SPURIOUS_RESPONSE 0x00000003UL
327 /** RDMA channel disconnected due to multi-channel action code in new login */
328 #define SRP_T_LOGOUT_REASON_MCA 0x00000004UL
330 /** Unsuppported format code value specified in data-out buffer descriptor */
331 #define SRP_T_LOGOUT_UNSUPPORTED_DATA_OUT_FORMAT 0x00000005UL
333 /** Unsuppported format code value specified in data-in buffer descriptor */
334 #define SRP_T_LOGOUT_UNSUPPORTED_DATA_IN_FORMAT 0x00000006UL
336 /** Invalid length for IU type */
337 #define SRP_T_LOGOUT_INVALID_IU_LEN 0x00000008UL
339 /*****************************************************************************
343 *****************************************************************************
346 /** An SRP task management request */
347 struct srp_tsk_mgmt {
348 /** Information unit type
350 * This must be @c SRP_TSK_MGMT
355 * This is the bitwise OR of zero or more
356 * @c SRP_TSK_MGMT_FLAG_XXX constants.
360 uint8_t reserved0[6];
364 uint8_t reserved1[4];
365 /** Logical unit number */
368 uint8_t reserved2[2];
369 /** Task management function
371 * This is a @c SRP_TASK_MGMT_FUNC_XXX constant
375 uint8_t reserved3[1];
376 /** Tag of task to be managed */
377 union srp_tag managed_tag;
379 uint8_t reserved4[8];
380 } __attribute__ (( packed ));
382 /** Type of an SRP task management request */
383 #define SRP_TSK_MGMT 0x01
385 /** Use solicited notification for unsuccessful completions */
386 #define SRP_TSK_MGMT_FLAG_UCSOLNT 0x04
388 /** Use solicited notification for successful completions */
389 #define SRP_TSK_MGMT_FLAG_SCSOLNT 0x02
391 /** The task manager shall perform an ABORT TASK function */
392 #define SRP_TSK_MGMT_FUNC_ABORT_TASK 0x01
394 /** The task manager shall perform an ABORT TASK SET function */
395 #define SRP_TSK_MGMT_FUNC_ABORT_TASK_SET 0x02
397 /** The task manager shall perform a CLEAR TASK SET function */
398 #define SRP_TSK_MGMT_FUNC_CLEAR_TASK_SET 0x04
400 /** The task manager shall perform a LOGICAL UNIT RESET function */
401 #define SRP_TSK_MGMT_FUNC_LOGICAL_UNIT_RESET 0x08
403 /** The task manager shall perform a CLEAR ACA function */
404 #define SRP_TSK_MGMT_FUNC_CLEAR_ACA 0x40
406 /*****************************************************************************
410 *****************************************************************************
413 /** An SRP SCSI command */
415 /** Information unit type
417 * This must be @c SRP_CMD
422 * This is the bitwise OR of zero or more @c SRP_CMD_FLAG_XXX
427 uint8_t reserved0[3];
428 /** Data buffer descriptor formats
430 * This is the bitwise OR of one @c SRP_CMD_DO_FMT_XXX and one @c
431 * SRP_CMD_DI_FMT_XXX constant.
433 uint8_t data_buffer_formats;
434 /** Data-out buffer descriptor count */
435 uint8_t data_out_buffer_count;
436 /** Data-in buffer descriptor count */
437 uint8_t data_in_buffer_count;
441 uint8_t reserved1[4];
442 /** Logical unit number */
445 uint8_t reserved2[1];
448 * This is a @c SRP_CMD_TASK_ATTR_XXX constant.
452 uint8_t reserved3[1];
453 /** Additional CDB length */
454 uint8_t additional_cdb_len;
455 /** Command data block */
457 } __attribute__ (( packed ));
459 /** Type of an SRP SCSI command */
462 /** Use solicited notification for unsuccessful completions */
463 #define SRP_CMD_FLAG_UCSOLNT 0x04
465 /** Use solicited notification for successful completions */
466 #define SRP_CMD_FLAG_SCSOLNT 0x02
468 /** Data-out buffer format mask */
469 #define SRP_CMD_DO_FMT_MASK 0xf0
471 /** Direct data-out buffer format */
472 #define SRP_CMD_DO_FMT_DIRECT 0x10
474 /** Indirect data-out buffer format */
475 #define SRP_CMD_DO_FMT_INDIRECT 0x20
477 /** Data-in buffer format mask */
478 #define SRP_CMD_DI_FMT_MASK 0x0f
480 /** Direct data-in buffer format */
481 #define SRP_CMD_DI_FMT_DIRECT 0x01
483 /** Indirect data-in buffer format */
484 #define SRP_CMD_DI_FMT_INDIRECT 0x02
486 /** Use the rules for a simple task attribute */
487 #define SRP_CMD_TASK_ATTR_SIMPLE 0x00
489 /** Use the rules for a head of queue task attribute */
490 #define SRP_CMD_TASK_ATTR_QUEUE_HEAD 0x01
492 /** Use the rules for an ordered task attribute */
493 #define SRP_CMD_TASK_ATTR_ORDERED 0x02
495 /** Use the rules for an automatic contingent allegiance task attribute */
496 #define SRP_CMD_TASK_ATTR_AUTOMATIC_CONTINGENT_ALLEGIANCE 0x08
498 /** An SRP memory descriptor */
499 struct srp_memory_descriptor {
500 /** Virtual address */
506 } __attribute__ (( packed ));
508 /*****************************************************************************
512 *****************************************************************************
515 /** An SRP SCSI response */
517 /** Information unit type
519 * This must be @c SRP_RSP
524 * This is the bitwise OR of zero or more @c SRP_RSP_FLAG_XXX
529 uint8_t reserved0[2];
530 /** Request limit delta */
531 uint32_t request_limit_delta;
535 uint8_t reserved1[2];
538 * This is the bitwise OR of zero or more @c SRP_RSP_VALID_XXX
544 * This is the SCSI status code.
547 /** Data-out residual count */
548 uint32_t data_out_residual_count;
549 /** Data-in residual count */
550 uint32_t data_in_residual_count;
551 /** Sense data list length */
552 uint32_t sense_data_len;
553 /** Response data list length */
554 uint32_t response_data_len;
555 } __attribute__ (( packed ));
557 /** Type of an SRP SCSI response */
560 /** The initiator specified solicited notification of this response */
561 #define SRP_RSP_FLAG_SOLNT 0x01
563 /** Data-in residual count field is valid and represents an underflow */
564 #define SRP_RSP_VALID_DIUNDER 0x20
566 /** Data-in residual count field is valid and represents an overflow */
567 #define SRP_RSP_VALID_DIOVER 0x10
569 /** Data-out residual count field is valid and represents an underflow */
570 #define SRP_RSP_VALID_DOUNDER 0x08
572 /** Data-out residual count field is valid and represents an overflow */
573 #define SRP_RSP_VALID_DOOVER 0x04
575 /** Sense data list length field is valid */
576 #define SRP_RSP_VALID_SNSVALID 0x02
578 /** Response data list length field is valid */
579 #define SRP_RSP_VALID_RSPVALID 0x01
582 * Get response data portion of SCSI response
584 * @v rsp SCSI response
585 * @ret response_data Response data, or NULL if not present
587 static inline const void * srp_rsp_response_data ( const struct srp_rsp *rsp ) {
588 return ( ( rsp->valid & SRP_RSP_VALID_RSPVALID ) ?
589 ( ( ( const void * ) rsp ) + sizeof ( *rsp ) ) : NULL );
593 * Get length of response data portion of SCSI response
595 * @v rsp SCSI response
596 * @ret response_data_len Response data length
598 static inline size_t srp_rsp_response_data_len ( const struct srp_rsp *rsp ) {
599 return ( ( rsp->valid & SRP_RSP_VALID_RSPVALID ) ?
600 ntohl ( rsp->response_data_len ) : 0 );
604 * Get sense data portion of SCSI response
606 * @v rsp SCSI response
607 * @ret sense_data Sense data, or NULL if not present
609 static inline const void * srp_rsp_sense_data ( const struct srp_rsp *rsp ) {
610 return ( ( rsp->valid & SRP_RSP_VALID_SNSVALID ) ?
611 ( ( ( const void * ) rsp ) + sizeof ( *rsp ) +
612 srp_rsp_response_data_len ( rsp ) ) : NULL );
616 * Get length of sense data portion of SCSI response
618 * @v rsp SCSI response
619 * @ret sense_data_len Sense data length
621 static inline size_t srp_rsp_sense_data_len ( const struct srp_rsp *rsp ) {
622 return ( ( rsp->valid & SRP_RSP_VALID_SNSVALID ) ?
623 ntohl ( rsp->sense_data_len ) : 0 );
626 /*****************************************************************************
630 *****************************************************************************
633 /** An SRP credit request */
634 struct srp_cred_req {
635 /** Information unit type
637 * This must be @c SRP_CRED_REQ
642 * This is the bitwise OR of zero or more
643 * @c SRP_CRED_REQ_FLAG_XXX constants.
647 uint8_t reserved0[2];
648 /** Request limit delta */
649 uint32_t request_limit_delta;
652 } __attribute__ (( packed ));
654 /** Type of an SRP credit request */
655 #define SRP_CRED_REQ 0x81
657 /** The initiator specified solicited notification of credit requests */
658 #define SRP_CRED_REQ_FLAG_SOLNT 0x01
660 /*****************************************************************************
664 *****************************************************************************
667 /** An SRP credit response */
668 struct srp_cred_rsp {
669 /** Information unit type
671 * This must be @c SRP_CRED_RSP
675 uint8_t reserved0[7];
678 } __attribute__ (( packed ));
680 /** Type of an SRP credit response */
681 #define SRP_CRED_RSP 0x41
683 /*****************************************************************************
685 * Asynchronous event request
687 *****************************************************************************
690 /** An SRP asynchronous event request */
692 /** Information unit type
694 * This must be @c SRP_AER_REQ
699 * This is the bitwise OR of zero or more @c
700 * SRP_AER_REQ_FLAG_XXX constants.
704 uint8_t reserved0[2];
705 /** Request limit delta */
706 uint32_t request_limit_delta;
710 uint8_t reserved1[4];
711 /** Logical unit number */
713 /** Sense data list length */
714 uint32_t sense_data_len;
716 uint8_t reserved2[4];
717 } __attribute__ (( packed ));
719 /** Type of an SRP asynchronous event request */
720 #define SRP_AER_REQ 0x82
722 /** The initiator specified solicited notification of asynchronous events */
723 #define SRP_AER_REQ_FLAG_SOLNT 0x01
726 * Get sense data portion of asynchronous event request
728 * @v aer_req SRP asynchronous event request
729 * @ret sense_data Sense data
731 static inline __always_inline void *
732 srp_aer_req_sense_data ( struct srp_aer_req *aer_req ) {
733 return ( ( ( void * ) aer_req ) + sizeof ( *aer_req ) );
737 * Get length of sense data portion of asynchronous event request
739 * @v aer_req SRP asynchronous event request
740 * @ret sense_data_len Sense data length
742 static inline __always_inline size_t
743 srp_aer_req_sense_data_len ( struct srp_aer_req *aer_req ) {
744 return ( ntohl ( aer_req->sense_data_len ) );
747 /*****************************************************************************
749 * Asynchronous event response
751 *****************************************************************************
754 /** An SRP asynchronous event response */
756 /** Information unit type
758 * This must be @c SRP_AER_RSP
762 uint8_t reserved0[7];
765 } __attribute__ (( packed ));
767 /** Type of an SRP asynchronous event response */
768 #define SRP_AER_RSP 0x42
770 /*****************************************************************************
772 * SRP boot firmware table
774 * The working draft specification for the SRP boot firmware table can
777 * http://ipxe.org/wiki/srp/sbft
779 *****************************************************************************
782 /** SRP Boot Firmware Table signature */
783 #define SBFT_SIG ACPI_SIGNATURE ( 's', 'B', 'F', 'T' )
785 /** An offset from the start of the sBFT */
786 typedef uint16_t sbft_off_t;
789 * SRP Boot Firmware Table
793 struct acpi_description_header acpi;
794 /** Offset to SCSI subtable */
795 sbft_off_t scsi_offset;
796 /** Offset to SRP subtable */
797 sbft_off_t srp_offset;
798 /** Offset to IB subtable, if present */
799 sbft_off_t ib_offset;
802 } __attribute__ (( packed ));
807 struct sbft_scsi_subtable {
810 } __attribute__ (( packed ));
815 struct sbft_srp_subtable {
816 /** Initiator port identifier */
817 union srp_port_id initiator;
818 /** Target port identifier */
819 union srp_port_id target;
820 } __attribute__ (( packed ));
822 /*****************************************************************************
826 *****************************************************************************
829 extern int srp_open ( struct interface *block, struct interface *socket,
830 union srp_port_id *initiator, union srp_port_id *target,
831 uint32_t memory_handle, struct scsi_lun *lun );
833 #endif /* _IPXE_SRP_H */