[infiniband] Allow SRP reconnection attempts even after reporting failures
[people/oremanj/gpxe.git] / src / include / gpxe / srp.h
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 */