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  */
srp_rsp_response_data(struct srp_rsp * rsp)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  */
srp_rsp_response_data_len(struct srp_rsp * rsp)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  */
srp_rsp_sense_data(struct srp_rsp * rsp)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  */
srp_rsp_sense_data_len(struct srp_rsp * rsp)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 *
srp_aer_req_sense_data(struct srp_aer_req * aer_req)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
srp_aer_req_sense_data_len(struct srp_aer_req * aer_req)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 *
srp_transport_priv(struct srp_device * srp)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