summaryrefslogtreecommitdiffstats
path: root/debian/grub-extras/disabled/gpxe/src/include/gpxe/srp.h
blob: 85f39b933cc76ac5c44c330361e75aaf929f5e26 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
#ifndef _GPXE_SRP_H
#define _GPXE_SRP_H

/** @file
 *
 * SCSI RDMA Protocol
 *
 */

FILE_LICENCE ( BSD2 );

#include <stdint.h>
#include <byteswap.h>
#include <gpxe/iobuf.h>
#include <gpxe/xfer.h>
#include <gpxe/scsi.h>

/*****************************************************************************
 *
 * Common fields
 *
 *****************************************************************************
 */

/** An SRP information unit tag */
struct srp_tag {
	uint32_t dwords[2];
} __attribute__ (( packed ));

/** An SRP port ID */
struct srp_port_id {
	uint8_t bytes[16];
} __attribute__ (( packed ));

/** An SRP port ID pair */
struct srp_port_ids {
	/** Initiator port ID */
	struct srp_port_id initiator;
	/** Target port ID */
	struct srp_port_id target;
} __attribute__ (( packed ));

/** SRP information unit common fields */
struct srp_common {
	/** Information unit type */
	uint8_t type;
	/** Reserved */
	uint8_t reserved0[7];
	/** Tag */
	struct srp_tag tag;
} __attribute__ (( packed ));

/*****************************************************************************
 *
 * Login request
 *
 *****************************************************************************
 */

/** An SRP login request information unit */
struct srp_login_req {
	/** Information unit type
	 *
	 * This must be @c SRP_LOGIN_REQ
	 */
	uint8_t type;
	/** Reserved */
	uint8_t reserved0[7];
	/** Tag */
	struct srp_tag tag;
	/** Requested maximum initiator to target IU length */
	uint32_t max_i_t_iu_len;
	/** Reserved */
	uint8_t reserved1[4];
	/** Required buffer formats
	 *
	 * This is the bitwise OR of one or more @c
	 * SRP_LOGIN_REQ_FMT_XXX constants.
	 */
	uint16_t required_buffer_formats;
	/** Flags
	 *
	 * This is the bitwise OR of zero or more @c
	 * SRP_LOGIN_REQ_FLAG_XXX and @c SRP_LOGIN_REQ_MCA_XXX
	 * constants.
	 */
	uint8_t flags;
	/** Reserved */
	uint8_t reserved2[5];
	/** Initiator and target port identifiers */
	struct srp_port_ids port_ids;
} __attribute__ (( packed ));

/** Type of an SRP login request */
#define SRP_LOGIN_REQ 0x00

/** Require indirect data buffer descriptor format */
#define SRP_LOGIN_REQ_FMT_IDBD 0x04

/** Require direct data buffer descriptor format */
#define SRP_LOGIN_REQ_FMT_DDBD 0x02

/** Use solicited notification for asynchronous events */
#define SRP_LOGIN_REQ_FLAG_AESOLNT 0x40

/** Use solicited notification for credit request */
#define SRP_LOGIN_REQ_FLAG_CRSOLNT 0x20

/** Use solicited notification for logouts */
#define SRP_LOGIN_REQ_FLAG_LOSOLNT 0x10

/** Multi-channel action mask */
#define SRP_LOGIN_REQ_MCA_MASK 0x03

/** Single RDMA channel operation */
#define SRP_LOGIN_REQ_MCA_SINGLE_CHANNEL 0x00

/** Multiple independent RDMA channel operation */
#define SRP_LOGIN_REQ_MCA_MULTIPLE_CHANNELS 0x01

/*****************************************************************************
 *
 * Login response
 *
 *****************************************************************************
 */

/** An SRP login response */
struct srp_login_rsp {
	/** Information unit type
	 *
	 * This must be @c SRP_LOGIN_RSP
	 */
	uint8_t type;
	/** Reserved */
	uint8_t reserved0[3];
	/** Request limit delta */
	uint32_t request_limit_delta;
	/** Tag */
	struct srp_tag tag;
	/** Maximum initiator to target IU length */
	uint32_t max_i_t_iu_len;
	/** Maximum target to initiator IU length */
	uint32_t max_t_i_iu_len;
	/** Supported buffer formats
	 *
	 * This is the bitwise OR of one or more @c
	 * SRP_LOGIN_RSP_FMT_XXX constants.
	 */
	uint16_t supported_buffer_formats;
	/** Flags
	 *
	 * This is the bitwise OR of zero or more @c
	 * SRP_LOGIN_RSP_FLAG_XXX and @c SRP_LOGIN_RSP_MCR_XXX
	 * constants.
	 */
	uint8_t flags;
	/** Reserved */
	uint8_t reserved1[25];
} __attribute__ (( packed ));

/** Type of an SRP login response */
#define SRP_LOGIN_RSP 0xc0

/** Indirect data buffer descriptor format supported */
#define SRP_LOGIN_RSP_FMT_IDBD 0x04

/** Direct data buffer descriptor format supported */
#define SRP_LOGIN_RSP_FMT_DDBD 0x02

/** Solicited notification is supported */
#define SRP_LOGIN_RSP_FLAG_SOLNTSUP 0x10

/** Multi-channel result mask */
#define SRP_LOGIN_RSP_MCR_MASK 0x03

/** No existing RDMA channels were associated with the same I_T nexus */
#define SRP_LOGIN_RSP_MCR_NO_EXISTING_CHANNELS 0x00

/** One or more existing RDMA channels were terminated */
#define SRP_LOGIN_RSP_MCR_EXISTING_CHANNELS_TERMINATED 0x01

/** One or more existing RDMA channels continue to operate independently */
#define SRP_LOGIN_RSP_MCR_EXISTING_CHANNELS_CONTINUE 0x02

/*****************************************************************************
 *
 * Login rejection
 *
 *****************************************************************************
 */

/** An SRP login rejection */
struct srp_login_rej {
	/** Information unit type
	 *
	 * This must be @c SRP_LOGIN_REJ
	 */
	uint8_t type;
	/** Reserved */
	uint8_t reserved0[3];
	/** Reason
	 *
	 * This is a @c SRP_LOGIN_REJ_REASON_XXX constant.
	 */
	uint32_t reason;
	/** Tag */
	struct srp_tag tag;
	/** Reserved */
	uint8_t reserved1[8];
	/** Supported buffer formats
	 *
	 * This is the bitwise OR of one or more @c
	 * SRP_LOGIN_REJ_FMT_XXX constants.
	 */
	uint16_t supported_buffer_formats;
	/** Reserved */
	uint8_t reserved2[6];
} __attribute__ (( packed ));

/** Type of an SRP login rejection */
#define SRP_LOGIN_REJ 0xc2

/** Unable to establish RDMA channel, no reason specified */
#define SRP_LOGIN_REJ_REASON_UNKNOWN 0x00010000UL

/** Insufficient RDMA channel resources */
#define SRP_LOGIN_REJ_REASON_INSUFFICIENT_RESOURCES 0x00010001UL

/** Requested maximum initiator to target IU length value too large */
#define SRP_LOGIN_REJ_REASON_BAD_MAX_I_T_IU_LEN 0x00010002UL

/** Unable to associate RDMA channel with specified I_T nexus */
#define SRP_LOGIN_REJ_REASON_CANNOT_ASSOCIATE 0x00010003UL

/** One or more requested data buffer descriptor formats are not supported */
#define SRP_LOGIN_REJ_REASON_UNSUPPORTED_BUFFER_FORMAT 0x00010004UL

/** SRP target port does not support multiple RDMA channels per I_T nexus */
#define SRP_LOGIN_REJ_REASON_NO_MULTIPLE_CHANNELS 0x00010005UL

/** RDMA channel limit reached for this initiator */
#define SRP_LOGIN_REJ_REASON_NO_MORE_CHANNELS 0x00010006UL

/** Indirect data buffer descriptor format supported */
#define SRP_LOGIN_REJ_FMT_IDBD 0x04

/** Direct data buffer descriptor format supported */
#define SRP_LOGIN_REJ_FMT_DDBD 0x02

/*****************************************************************************
 *
 * Initiator logout
 *
 *****************************************************************************
 */

/** An SRP initiator logout request */
struct srp_i_logout {
	/** Information unit type
	 *
	 * This must be @c SRP_I_LOGOUT
	 */
	uint8_t type;
	/** Reserved */
	uint8_t reserved0[7];
	/** Tag */
	struct srp_tag tag;
} __attribute__ (( packed ));

/** Type of an SRP initiator logout request */
#define SRP_I_LOGOUT 0x03

/*****************************************************************************
 *
 * Target logout
 *
 *****************************************************************************
 */

/** An SRP target logout request */
struct srp_t_logout {
	/** Information unit type
	 *
	 * This must be @c SRP_T_LOGOUT
	 */
	uint8_t type;
	/** Flags
	 *
	 * This is the bitwise OR of zero or more @c
	 * SRP_T_LOGOUT_FLAG_XXX constants.
	 */
	uint8_t flags;
	/** Reserved */
	uint8_t reserved0[2];
	/** Reason
	 *
	 * This is a @c SRP_T_LOGOUT_REASON_XXX constant.
	 */
	uint32_t reason;
	/** Tag */
	struct srp_tag tag;
} __attribute__ (( packed ));

/** Type of an SRP target logout request */
#define SRP_T_LOGOUT 0x80

/** The initiator specified solicited notification of logouts */
#define SRP_T_LOGOUT_FLAG_SOLNT 0x01

/** No reason specified */
#define SRP_T_LOGOUT_REASON_UNKNOWN 0x00000000UL

/** Inactive RDMA channel (reclaiming resources) */
#define SRP_T_LOGOUT_REASON_INACTIVE 0x00000001UL

/** Invalid information unit type code received by SRP target port */
#define SRP_T_LOGOUT_REASON_INVALID_TYPE 0x00000002UL

/** SRP initiator port sent response with no corresponding request */
#define SRP_T_LOGOUT_REASON_SPURIOUS_RESPONSE 0x00000003UL

/** RDMA channel disconnected due to multi-channel action code in new login */
#define SRP_T_LOGOUT_REASON_MCA 0x00000004UL

/** Unsuppported format code value specified in data-out buffer descriptor */
#define SRP_T_LOGOUT_UNSUPPORTED_DATA_OUT_FORMAT 0x00000005UL

/** Unsuppported format code value specified in data-in buffer descriptor */
#define SRP_T_LOGOUT_UNSUPPORTED_DATA_IN_FORMAT 0x00000006UL

/** Invalid length for IU type */
#define SRP_T_LOGOUT_INVALID_IU_LEN 0x00000008UL

/*****************************************************************************
 *
 * Task management
 *
 *****************************************************************************
 */

/** An SRP task management request */
struct srp_tsk_mgmt {
	/** Information unit type
	 *
	 * This must be @c SRP_TSK_MGMT
	 */
	uint8_t type;
	/** Flags
	 *
	 * This is the bitwise OR of zero or more
	 * @c SRP_TSK_MGMT_FLAG_XXX constants.
	 */
	uint8_t flags;
	/** Reserved */
	uint8_t reserved0[6];
	/** Tag */
	struct srp_tag tag;
	/** Reserved */
	uint8_t reserved1[4];
	/** Logical unit number */
	struct scsi_lun lun;
	/** Reserved */
	uint8_t reserved2[2];
	/** Task management function
	 *
	 * This is a @c SRP_TASK_MGMT_FUNC_XXX constant
	 */
	uint8_t function;
	/** Reserved */
	uint8_t reserved3[1];
	/** Tag of task to be managed */
	struct srp_tag managed_tag;
	/** Reserved */
	uint8_t reserved4[8];
} __attribute__ (( packed ));

/** Type of an SRP task management request */
#define SRP_TSK_MGMT 0x01

/** Use solicited notification for unsuccessful completions */
#define SRP_TSK_MGMT_FLAG_UCSOLNT 0x04

/** Use solicited notification for successful completions */
#define SRP_TSK_MGMT_FLAG_SCSOLNT 0x02

/** The task manager shall perform an ABORT TASK function */
#define SRP_TSK_MGMT_FUNC_ABORT_TASK 0x01

/** The task manager shall perform an ABORT TASK SET function */
#define SRP_TSK_MGMT_FUNC_ABORT_TASK_SET 0x02

/** The task manager shall perform a CLEAR TASK SET function */
#define SRP_TSK_MGMT_FUNC_CLEAR_TASK_SET 0x04

/** The task manager shall perform a LOGICAL UNIT RESET function */
#define SRP_TSK_MGMT_FUNC_LOGICAL_UNIT_RESET 0x08

/** The task manager shall perform a CLEAR ACA function */
#define SRP_TSK_MGMT_FUNC_CLEAR_ACA 0x40

/*****************************************************************************
 *
 * SCSI command
 *
 *****************************************************************************
 */

/** An SRP SCSI command */
struct srp_cmd {
	/** Information unit type
	 *
	 * This must be @c SRP_CMD
	 */
	uint8_t type;
	/** Flags
	 *
	 * This is the bitwise OR of zero or more @c SRP_CMD_FLAG_XXX
	 * constants.
	 */
	uint8_t flags;
	/** Reserved */
	uint8_t reserved0[3];
	/** Data buffer descriptor formats
	 *
	 * This is the bitwise OR of one @c SRP_CMD_DO_FMT_XXX and one @c
	 * SRP_CMD_DI_FMT_XXX constant.
	 */
	uint8_t data_buffer_formats;
	/** Data-out buffer descriptor count */
	uint8_t data_out_buffer_count;
	/** Data-in buffer descriptor count */
	uint8_t data_in_buffer_count;
	/** Tag */
	struct srp_tag tag;
	/** Reserved */
	uint8_t reserved1[4];
	/** Logical unit number */
	struct scsi_lun lun;
	/** Reserved */
	uint8_t reserved2[1];
	/** Task attribute
	 *
	 * This is a @c SRP_CMD_TASK_ATTR_XXX constant.
	 */
	uint8_t task_attr;
	/** Reserved */
	uint8_t reserved3[1];
	/** Additional CDB length */
	uint8_t additional_cdb_len;
	/** Command data block */
	union scsi_cdb cdb;
} __attribute__ (( packed ));

/** Type of an SRP SCSI command */
#define SRP_CMD 0x02

/** Use solicited notification for unsuccessful completions */
#define SRP_CMD_FLAG_UCSOLNT 0x04

/** Use solicited notification for successful completions */
#define SRP_CMD_FLAG_SCSOLNT 0x02

/** Data-out buffer format mask */
#define SRP_CMD_DO_FMT_MASK 0xf0

/** Direct data-out buffer format */
#define SRP_CMD_DO_FMT_DIRECT 0x10

/** Indirect data-out buffer format */
#define SRP_CMD_DO_FMT_INDIRECT 0x20

/** Data-in buffer format mask */
#define SRP_CMD_DI_FMT_MASK 0x0f

/** Direct data-in buffer format */
#define SRP_CMD_DI_FMT_DIRECT 0x01

/** Indirect data-in buffer format */
#define SRP_CMD_DI_FMT_INDIRECT 0x02

/** Use the rules for a simple task attribute */
#define SRP_CMD_TASK_ATTR_SIMPLE 0x00

/** Use the rules for a head of queue task attribute */
#define SRP_CMD_TASK_ATTR_QUEUE_HEAD 0x01

/** Use the rules for an ordered task attribute */
#define SRP_CMD_TASK_ATTR_ORDERED 0x02

/** Use the rules for an automatic contingent allegiance task attribute */
#define SRP_CMD_TASK_ATTR_AUTOMATIC_CONTINGENT_ALLEGIANCE 0x08

/** An SRP memory descriptor */
struct srp_memory_descriptor {
	/** Virtual address */
	uint64_t address;
	/** Memory handle */
	uint32_t handle;
	/** Data length */
	uint32_t len;
} __attribute__ (( packed ));

/*****************************************************************************
 *
 * SCSI response
 *
 *****************************************************************************
 */

/** An SRP SCSI response */
struct srp_rsp {
	/** Information unit type
	 *
	 * This must be @c SRP_RSP
	 */
	uint8_t type;
	/** Flags
	 *
	 * This is the bitwise OR of zero or more @c SRP_RSP_FLAG_XXX
	 * constants.
	 */
	uint8_t flags;
	/** Reserved */
	uint8_t reserved0[2];
	/** Request limit delta */
	uint32_t request_limit_delta;
	/** Tag */
	struct srp_tag tag;
	/** Reserved */
	uint8_t reserved1[2];
	/** Valid fields
	 *
	 * This is the bitwise OR of zero or more @c SRP_RSP_VALID_XXX
	 * constants.
	 */
	uint8_t valid;
	/** Status
	 *
	 * This is the SCSI status code.
	 */
	uint8_t status;
	/** Data-out residual count */
	uint32_t data_out_residual_count;
	/** Data-in residual count */
	uint32_t data_in_residual_count;
	/** Sense data list length */
	uint32_t sense_data_len;
	/** Response data list length */
	uint32_t response_data_len;
} __attribute__ (( packed ));

/** Type of an SRP SCSI response */
#define SRP_RSP 0xc1

/** The initiator specified solicited notification of this response */
#define SRP_RSP_FLAG_SOLNT 0x01

/** Data-in residual count field is valid and represents an underflow */
#define SRP_RSP_VALID_DIUNDER 0x20

/** Data-in residual count field is valid and represents an overflow */
#define SRP_RSP_VALID_DIOVER 0x10

/** Data-out residual count field is valid and represents an underflow */
#define SRP_RSP_VALID_DOUNDER 0x08

/** Data-out residual count field is valid and represents an overflow */
#define SRP_RSP_VALID_DOOVER 0x04

/** Sense data list length field is valid */
#define SRP_RSP_VALID_SNSVALID 0x02

/** Response data list length field is valid */
#define SRP_RSP_VALID_RSPVALID 0x01

/**
 * Get response data portion of SCSI response
 *
 * @v rsp			SCSI response
 * @ret response_data		Response data, or NULL if not present
 */
static inline void * srp_rsp_response_data ( struct srp_rsp *rsp ) {
	return ( ( rsp->valid & SRP_RSP_VALID_RSPVALID ) ?
		 ( ( ( void * ) rsp ) + sizeof ( *rsp ) ) : NULL );
}

/**
 * Get length of response data portion of SCSI response
 *
 * @v rsp			SCSI response
 * @ret response_data_len	Response data length
 */
static inline size_t srp_rsp_response_data_len ( struct srp_rsp *rsp ) {
	return ( ( rsp->valid & SRP_RSP_VALID_RSPVALID ) ?
		 ntohl ( rsp->response_data_len ) : 0 );
}

/**
 * Get sense data portion of SCSI response
 *
 * @v rsp			SCSI response
 * @ret sense_data		Sense data, or NULL if not present
 */
static inline void * srp_rsp_sense_data ( struct srp_rsp *rsp ) {
	return ( ( rsp->valid & SRP_RSP_VALID_SNSVALID ) ?
		 ( ( ( void * ) rsp ) + sizeof ( *rsp ) +
		   srp_rsp_response_data_len ( rsp ) ) : NULL );
}

/**
 * Get length of sense data portion of SCSI response
 *
 * @v rsp			SCSI response
 * @ret sense_data_len		Sense data length
 */
static inline size_t srp_rsp_sense_data_len ( struct srp_rsp *rsp ) {
	return ( ( rsp->valid & SRP_RSP_VALID_SNSVALID ) ?
		 ntohl ( rsp->sense_data_len ) : 0 );
}

/*****************************************************************************
 *
 * Credit request
 *
 *****************************************************************************
 */

/** An SRP credit request */
struct srp_cred_req {
	/** Information unit type
	 *
	 * This must be @c SRP_CRED_REQ
	 */
	uint8_t type;
	/** Flags
	 *
	 * This is the bitwise OR of zero or more
	 * @c SRP_CRED_REQ_FLAG_XXX constants.
	 */
	uint8_t flags;
	/** Reserved */
	uint8_t reserved0[2];
	/** Request limit delta */
	uint32_t request_limit_delta;
	/** Tag */
	struct srp_tag tag;
} __attribute__ (( packed ));

/** Type of an SRP credit request */
#define SRP_CRED_REQ 0x81

/** The initiator specified solicited notification of credit requests */
#define SRP_CRED_REQ_FLAG_SOLNT 0x01

/*****************************************************************************
 *
 * Credit response
 *
 *****************************************************************************
 */

/** An SRP credit response */
struct srp_cred_rsp {
	/** Information unit type
	 *
	 * This must be @c SRP_CRED_RSP
	 */
	uint8_t type;
	/** Reserved */
	uint8_t reserved0[7];
	/** Tag */
	struct srp_tag tag;
} __attribute__ (( packed ));

/** Type of an SRP credit response */
#define SRP_CRED_RSP 0x41

/*****************************************************************************
 *
 * Asynchronous event request
 *
 *****************************************************************************
 */

/** An SRP asynchronous event request */
struct srp_aer_req {
	/** Information unit type
	 *
	 * This must be @c SRP_AER_REQ
	 */
	uint8_t type;
	/** Flags
	 *
	 * This is the bitwise OR of zero or more @c
	 * SRP_AER_REQ_FLAG_XXX constants.
	 */
	uint8_t flags;
	/** Reserved */
	uint8_t reserved0[2];
	/** Request limit delta */
	uint32_t request_limit_delta;
	/** Tag */
	struct srp_tag tag;
	/** Reserved */
	uint8_t reserved1[4];
	/** Logical unit number */
	struct scsi_lun lun;
	/** Sense data list length */
	uint32_t sense_data_len;
	/** Reserved */
	uint8_t reserved2[4];
} __attribute__ (( packed ));

/** Type of an SRP asynchronous event request */
#define SRP_AER_REQ 0x82

/** The initiator specified solicited notification of asynchronous events */
#define SRP_AER_REQ_FLAG_SOLNT 0x01

/**
 * Get sense data portion of asynchronous event request
 *
 * @v aer_req			SRP asynchronous event request
 * @ret sense_data		Sense data
 */
static inline __always_inline void *
srp_aer_req_sense_data ( struct srp_aer_req *aer_req ) {
	return ( ( ( void * ) aer_req ) + sizeof ( *aer_req ) );
}

/**
 * Get length of sense data portion of asynchronous event request
 *
 * @v aer_req			SRP asynchronous event request
 * @ret sense_data_len		Sense data length
 */
static inline __always_inline size_t
srp_aer_req_sense_data_len ( struct srp_aer_req *aer_req ) {
	return ( ntohl ( aer_req->sense_data_len ) );
}

/*****************************************************************************
 *
 * Asynchronous event response
 *
 *****************************************************************************
 */

/** An SRP asynchronous event response */
struct srp_aer_rsp {
	/** Information unit type
	 *
	 * This must be @c SRP_AER_RSP
	 */
	uint8_t type;
	/** Reserved */
	uint8_t reserved0[7];
	/** Tag */
	struct srp_tag tag;
} __attribute__ (( packed ));

/** Type of an SRP asynchronous event response */
#define SRP_AER_RSP 0x42

/*****************************************************************************
 *
 * Information units
 *
 *****************************************************************************
 */

/** Maximum length of any initiator-to-target IU that we will send
 *
 * The longest IU is a SRP_CMD with no additional CDB and two direct
 * data buffer descriptors, which comes to 80 bytes.
 */
#define SRP_MAX_I_T_IU_LEN 80

/*****************************************************************************
 *
 * SRP device
 *
 *****************************************************************************
 */

struct srp_device;

/** An SRP transport type */
struct srp_transport_type {
	/** Length of transport private data */
	size_t priv_len;
	/** Parse root path
	 *
	 * @v srp		SRP device
	 * @v root_path		Root path
	 * @ret 		Return status code
	 */
	int ( * parse_root_path ) ( struct srp_device *srp,
				    const char *root_path );
	/** Connect SRP session
	 *
	 * @v srp		SRP device
	 * @ret rc		Return status code
	 *
	 * This method should open the underlying socket.
	 */
	int ( * connect ) ( struct srp_device *srp );
};

/** An SRP device */
struct srp_device {
	/** Reference count */
	struct refcnt refcnt;

	/** Initiator and target port IDs */
	struct srp_port_ids port_ids;
	/** Logical unit number */
	struct scsi_lun lun;
	/** Memory handle */
	uint32_t memory_handle;

	/** Current state
	 *
	 * This is the bitwise-OR of zero or more @c SRP_STATE_XXX
	 * flags.
	 */
	unsigned int state;
	/** Retry counter */
	unsigned int retry_count;
	/** Current SCSI command */
	struct scsi_command *command;

	/** Underlying data transfer interface */
	struct xfer_interface socket;

	/** Transport type */
	struct srp_transport_type *transport;
	/** Transport private data */
	char transport_priv[0];
};

/**
 * Get SRP transport private data
 *
 * @v srp		SRP device
 * @ret priv		SRP transport private data
 */
static inline __always_inline void *
srp_transport_priv ( struct srp_device *srp ) {
	return ( ( void * ) srp->transport_priv );
}

/** SRP state flags */
enum srp_state {
	/** Underlying socket is open */
	SRP_STATE_SOCKET_OPEN = 0x0001,
	/** Session is logged in */
	SRP_STATE_LOGGED_IN = 0x0002,
};

/** Maximum number of SRP retry attempts */
#define SRP_MAX_RETRIES 3

extern int srp_attach ( struct scsi_device *scsi, const char *root_path );
extern void srp_detach ( struct scsi_device *scsi );

#endif /* _GPXE_SRP_H */