• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /** @file
2   The header file of iSCSI Protocol that defines many specific data structures.
3 
4 Copyright (c) 2004 - 2014, Intel Corporation. All rights reserved.<BR>
5 This program and the accompanying materials
6 are licensed and made available under the terms and conditions of the BSD License
7 which accompanies this distribution.  The full text of the license may be found at
8 http://opensource.org/licenses/bsd-license.php
9 
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
12 
13 **/
14 
15 #ifndef _ISCSI_PROTO_H_
16 #define _ISCSI_PROTO_H_
17 
18 #include <Protocol/ScsiPassThruExt.h>
19 
20 //
21 // RFC 1982 Serial Number Arithmetic, SERIAL_BITS = 32
22 //
23 #define ISCSI_SEQ_EQ(s1, s2)  ((s1) == (s2))
24 #define ISCSI_SEQ_LT(s1, s2) \
25     ( \
26       (((INT32) (s1) < (INT32) (s2)) && (s2 - s1) < ((UINT32) 1 << 31)) || \
27       (((INT32) (s1) > (INT32) (s2)) && (s1 - s2) > ((UINT32) 1 << 31)) \
28     )
29 #define ISCSI_SEQ_GT(s1, s2) \
30     ( \
31       (((INT32) (s1) < (INT32) (s2)) && (s2 - s1) > ((UINT32) 1 << 31)) || \
32       (((INT32) (s1) > (INT32) (s2)) && (s1 - s2) < ((UINT32) 1 << 31)) \
33     )
34 
35 #define ISCSI_WELL_KNOWN_PORT                   3260
36 #define ISCSI_MAX_CONNS_PER_SESSION             1
37 
38 #define DEFAULT_MAX_RECV_DATA_SEG_LEN           8192
39 #define MAX_RECV_DATA_SEG_LEN_IN_FFP            65536
40 #define DEFAULT_MAX_OUTSTANDING_R2T             1
41 
42 #define ISCSI_VERSION_MAX                       0x00
43 #define ISCSI_VERSION_MIN                       0x00
44 
45 #define ISCSI_KEY_AUTH_METHOD                   "AuthMethod"
46 #define ISCSI_KEY_HEADER_DIGEST                 "HeaderDigest"
47 #define ISCSI_KEY_DATA_DIGEST                   "DataDigest"
48 #define ISCSI_KEY_MAX_CONNECTIONS               "MaxConnections"
49 #define ISCSI_KEY_TARGET_NAME                   "TargetName"
50 #define ISCSI_KEY_INITIATOR_NAME                "InitiatorName"
51 #define ISCSI_KEY_TARGET_ALIAS                  "TargetAlias"
52 #define ISCSI_KEY_INITIATOR_ALIAS               "InitiatorAlias"
53 #define ISCSI_KEY_TARGET_ADDRESS                "TargetAddress"
54 #define ISCSI_KEY_INITIAL_R2T                   "InitialR2T"
55 #define ISCSI_KEY_IMMEDIATE_DATA                "ImmediateData"
56 #define ISCSI_KEY_TARGET_PORTAL_GROUP_TAG       "TargetPortalGroupTag"
57 #define ISCSI_KEY_MAX_BURST_LENGTH              "MaxBurstLength"
58 #define ISCSI_KEY_FIRST_BURST_LENGTH            "FirstBurstLength"
59 #define ISCSI_KEY_DEFAULT_TIME2WAIT             "DefaultTime2Wait"
60 #define ISCSI_KEY_DEFAULT_TIME2RETAIN           "DefaultTime2Retain"
61 #define ISCSI_KEY_MAX_OUTSTANDING_R2T           "MaxOutstandingR2T"
62 #define ISCSI_KEY_DATA_PDU_IN_ORDER             "DataPDUInOrder"
63 #define ISCSI_KEY_DATA_SEQUENCE_IN_ORDER        "DataSequenceInOrder"
64 #define ISCSI_KEY_ERROR_RECOVERY_LEVEL          "ErrorRecoveryLevel"
65 #define ISCSI_KEY_SESSION_TYPE                  "SessionType"
66 #define ISCSI_KEY_MAX_RECV_DATA_SEGMENT_LENGTH  "MaxRecvDataSegmentLength"
67 
68 #define ISCSI_KEY_VALUE_NONE                    "None"
69 
70 ///
71 /// connection state for initiator
72 ///
73 
74 #define CONN_STATE_FREE                         0
75 #define CONN_STATE_XPT_WAIT                     1
76 #define CONN_STATE_IN_LOGIN                     2
77 #define CONN_STATE_LOGGED_IN                    3
78 #define CONN_STATE_IN_LOGOUT                    4
79 #define CONN_STATE_LOGOUT_REQUESTED             5
80 #define CONN_STATE_CLEANUP_WAIT                 6
81 #define CONN_STATE_IN_CLEANUP                   7
82 
83 ///
84 /// session state for initiator
85 ///
86 #define SESSION_STATE_FREE                      0
87 #define SESSION_STATE_LOGGED_IN                 1
88 #define SESSION_STATE_FAILED                    2
89 
90 typedef enum {
91   DataIn  = 0,
92   DataOut = 1,
93   DataBi  = 2
94 } DATA_DIRECTION;
95 
96 #define ISCSI_RESERVED_TAG                  0xffffffff
97 
98 #define ISCSI_REQ_IMMEDIATE                 0x40
99 #define ISCSI_OPCODE_MASK                   0x3F
100 
101 #define ISCSI_SET_OPCODE(PduHdr, Op, Flgs)  ((((ISCSI_BASIC_HEADER *) (PduHdr))->OpCode) = ((Op) | (Flgs)))
102 #define ISCSI_GET_OPCODE(PduHdr)            ((((ISCSI_BASIC_HEADER *) (PduHdr))->OpCode) & ISCSI_OPCODE_MASK)
103 #define ISCSI_CHECK_OPCODE(PduHdr, Op)      ((((PduHdr)->OpCode) & ISCSI_OPCODE_MASK) == (Op))
104 #define ISCSI_IMMEDIATE_ON(PduHdr)          ((PduHdr)->OpCode & ISCSI_REQ_IMMEDIATE)
105 #define ISCSI_SET_FLAG(PduHdr, Flag)        (((ISCSI_BASIC_HEADER *) (PduHdr))->Flags |= (BOOLEAN)(Flag))
106 #define ISCSI_CLEAR_FLAG(PduHdr, Flag)      (((ISCSI_BASIC_HEADER *) (PduHdr))->Flags &= ~(Flag))
107 #define ISCSI_FLAG_ON(PduHdr, Flag)         ((((ISCSI_BASIC_HEADER *) (PduHdr))->Flags & (Flag)) == (Flag))
108 #define ISCSI_SET_STAGES(PduHdr, Cur, Nxt)  ((PduHdr)->Flags = (UINT8) ((PduHdr)->Flags | ((Cur) << 2 | (Nxt))))
109 #define ISCSI_GET_CURRENT_STAGE(PduHdr)     (((PduHdr)->Flags >> 2) & 0x3)
110 #define ISCSI_GET_NEXT_STAGE(PduHdr)        (((PduHdr)->Flags) & 0x3)
111 
112 #define ISCSI_GET_PAD_LEN(DataLen)          ((~(DataLen) + 1) & 0x3)
113 #define ISCSI_ROUNDUP(DataLen)              (((DataLen) + 3) &~(0x3))
114 
115 #define HTON24(Dst, Src) \
116   do { \
117     (Dst)[0]  = (UINT8) (((Src) >> 16) & 0xFF); \
118     (Dst)[1]  = (UINT8) (((Src) >> 8) & 0xFF); \
119     (Dst)[2]  = (UINT8) ((Src) & 0xFF); \
120   } while (0);
121 
122 #define NTOH24(src)                         (((src)[0] << 16) | ((src)[1] << 8) | ((src)[2]))
123 
124 #define ISCSI_GET_DATASEG_LEN(PduHdr)       NTOH24 (((ISCSI_BASIC_HEADER *) (PduHdr))->DataSegmentLength)
125 #define ISCSI_SET_DATASEG_LEN(PduHdr, Len)  HTON24 (((ISCSI_BASIC_HEADER *) (PduHdr))->DataSegmentLength, (Len))
126 
127 //
128 // initiator opcodes
129 //
130 #define ISCSI_OPCODE_NOP_OUT        0x00
131 #define ISCSI_OPCODE_SCSI_CMD       0x01
132 #define ISCSI_OPCODE_SCSI_TMF_REQ   0x02
133 #define ISCSI_OPCODE_LOGIN_REQ      0x03
134 #define ISCSI_OPCODE_TEXT_REQ       0x04
135 #define ISCSI_OPCODE_SCSI_DATA_OUT  0x05
136 #define ISCSI_OPCODE_LOGOUT_REQ     0x06
137 #define ISCSI_OPCODE_SNACK_REQ      0x10
138 #define ISCSI_OPCODE_VENDOR_I0      0x1c
139 #define ISCSI_OPCODE_VENDOR_I1      0x1d
140 #define ISCSI_OPCODE_VENDOR_I2      0x1e
141 
142 //
143 // target opcodes
144 //
145 #define ISCSI_OPCODE_NOP_IN       0x20
146 #define ISCSI_OPCODE_SCSI_RSP     0x21
147 #define ISCSI_OPCODE_SCSI_TMF_RSP 0x22
148 #define ISCSI_OPCODE_LOGIN_RSP    0x23
149 #define ISCSI_OPCODE_TEXT_RSP     0x24
150 #define ISCSI_OPCODE_SCSI_DATA_IN 0x25
151 #define ISCSI_OPCODE_LOGOUT_RSP   0x26
152 #define ISCSI_OPCODE_R2T          0x31
153 #define ISCSI_OPCODE_ASYNC_MSG    0x32
154 #define ISCSI_OPCODE_VENDOR_T0    0x3c
155 #define ISCSI_OPCODE_VENDOR_T1    0x3d
156 #define ISCSI_OPCODE_VENDOR_T2    0x3e
157 #define ISCSI_OPCODE_REJECT       0x3f
158 
159 #define ISCSI_BHS_FLAG_FINAL      0x80
160 
161 ///
162 /// iSCSI Basic Header Segment
163 ///
164 typedef struct _ISCSI_BASIC_HEADER {
165   UINT8   OpCode;
166   UINT8   Flags;
167   UINT16  OpCodeSpecific1;
168   UINT8   TotalAHSLength;
169   UINT8   DataSegmentLength[3];
170   UINT8   Lun[8];
171   UINT32  InitiatorTaskTag;
172   UINT32  OpCodeSpecific2[7];
173 } ISCSI_BASIC_HEADER;
174 
175 //
176 // Defined AHS types, others are reserved.
177 //
178 #define ISCSI_AHS_TYPE_EXT_CDB              0x1
179 #define ISCSI_AHS_TYPE_BI_EXP_READ_DATA_LEN 0x2
180 
181 typedef struct _ISCSI_ADDTIONAL_HEADER {
182   UINT16  Length;
183   UINT8   Type;
184   UINT8   TypeSpecific[1];
185 } ISCSI_ADDITIONAL_HEADER;
186 
187 typedef struct _ISCSI_BI_EXP_READ_DATA_LEN_AHS {
188   UINT16  Length;
189   UINT8   Type;
190   UINT8   Reserved;
191   UINT32  ExpReadDataLength;
192 } ISCSI_BI_EXP_READ_DATA_LEN_AHS;
193 
194 #define SCSI_CMD_PDU_FLAG_READ        0x40
195 #define SCSI_CMD_PDU_FLAG_WRITE       0x20
196 
197 #define ISCSI_CMD_PDU_TASK_ATTR_MASK  0x07
198 
199 //
200 // task attributes
201 //
202 #define ISCSI_TASK_ATTR_UNTAGGED  0x00
203 #define ISCSI_TASK_ATTR_SIMPLE    0x01
204 #define ISCSI_TASK_ATTR_ORDERD    0x02
205 #define ISCSI_TASK_ATTR_HOQ       0x03
206 #define ISCSI_TASK_ATTR_ACA       0x04
207 
208 ///
209 /// SCSI Command
210 ///
211 typedef struct _SCSI_COMMAND {
212   UINT8   OpCode;
213   UINT8   Flags;
214   UINT16  Reserved;
215   UINT8   TotalAHSLength;
216   UINT8   DataSegmentLength[3];
217   UINT8   Lun[8];
218   UINT32  InitiatorTaskTag;
219   UINT32  ExpDataXferLength;
220   UINT32  CmdSN;
221   UINT32  ExpStatSN;
222   UINT8   Cdb[16];
223 } SCSI_COMMAND;
224 
225 //
226 // flag bit definitions in SCSI response
227 //
228 #define SCSI_RSP_PDU_FLAG_BI_READ_OVERFLOW  0x10
229 #define SCSI_RSP_PDU_FLAG_BI_READ_UNDERFLOW 0x08
230 #define SCSI_RSP_PDU_FLAG_OVERFLOW          0x04
231 #define SCSI_RSP_PDU_FLAG_UNDERFLOW         0x02
232 
233 //
234 // iSCSI service response codes
235 //
236 #define ISCSI_SERVICE_RSP_COMMAND_COMPLETE_AT_TARGET  0x00
237 #define ISCSI_SERVICE_RSP_TARGET_FAILURE              0x01
238 
239 ///
240 /// SCSI Response
241 ///
242 typedef struct _SCSI_RESPONSE {
243   UINT8   OpCode;
244   UINT8   Flags;
245   UINT8   Response;
246   UINT8   Status;
247   UINT8   TotalAHSLength;
248   UINT8   DataSegmentLength[3];
249   UINT8   Reserved[8];
250   UINT32  InitiatorTaskTag;
251   UINT32  SNACKTag;
252   UINT32  StatSN;
253   UINT32  ExpCmdSN;
254   UINT32  MaxCmdSN;
255   UINT32  ExpDataSN;
256   UINT32  BiReadResidualCount;
257   UINT32  ResidualCount;
258 } SCSI_RESPONSE;
259 
260 typedef struct _ISCSI_SENSE_DATA {
261   UINT16  Length;
262   UINT8   Data[2];
263 } ISCSI_SENSE_DATA;
264 
265 ///
266 /// iSCSI Task Managment Function Request
267 ///
268 typedef struct _ISCSI_TMF_REQUEST {
269   UINT8   OpCode;
270   UINT8   Fuction;
271   UINT16  Reserved1;
272   UINT8   TotalAHSLength;
273   UINT8   DataSegmentLength[3];
274   UINT8   Lun[8];
275   UINT32  InitiatorTaskTag;
276   UINT32  ReferencedTaskTag;
277   UINT32  CmdSN;
278   UINT32  ExpStatSN;
279   UINT32  RefCmdSN;
280   UINT32  ExpDataSN;
281   UINT32  Reserved2[2];
282 } ISCSI_TMF_REQUEST;
283 
284 #define ISCSI_TMF_RSP_PDU_RSP_FUNCTION_COMPLETE           0
285 #define ISCSI_TMF_RSP_PDU_RSP_TASK_NOT_EXIST              1
286 #define ISCSI_TMF_RSP_PDU_RSP_LUN_NOT_EXIST               2
287 #define ISCSI_TMF_RSP_PDU_RSP_TASK_STILL_ALLEGIANT        3
288 #define ISCSI_TMF_RSP_PDU_RSP_TASK_REASSGIN_NOT_SUPPORTED 4
289 #define ISCSI_TMF_RSP_PDU_RSP_NOT_SUPPORTED               5
290 #define ISCSI_TMF_RSP_PDU_RSP_FUNCTION_AHTH_FAILED        6
291 #define ISCSI_TMF_RSP_PDU_RSP_FUNCTION_REJECTED           255
292 
293 ///
294 /// iSCSI Task Management Function Response
295 ///
296 typedef struct _ISCSI_TMF_RESPONSE {
297   UINT8   OpCode;
298   UINT8   Reserved1;
299   UINT8   Response;
300   UINT8   Reserved2;
301   UINT8   TotalAHSLength;
302   UINT8   DataSegmentLength[3];
303   UINT32  Reserver3[2];
304   UINT32  InitiatorTaskTag;
305   UINT32  Reserved4;
306   UINT32  StatSN;
307   UINT32  ExpCmdSN;
308   UINT32  MaxCmdSN;
309   UINT32  Reserved[3];
310 } ISCSI_TMF_RESPONSE;
311 
312 ///
313 /// SCSI Data-Out
314 ///
315 typedef struct _ISCSI_SCSI_DATA_OUT {
316   UINT8   OpCode;
317   UINT8   Reserved1[3];
318   UINT8   TotalAHSLength;
319   UINT8   DataSegmentLength[3];
320   UINT8   Lun[8];
321   UINT32  InitiatorTaskTag;
322   UINT32  TargetTransferTag;
323   UINT32  Reserved2;
324   UINT32  ExpStatSN;
325   UINT32  Reserved3;
326   UINT32  DataSN;
327   UINT32  BufferOffset;
328   UINT32  Reserved4;
329 } ISCSI_SCSI_DATA_OUT;
330 
331 #define SCSI_DATA_IN_PDU_FLAG_ACKKNOWLEDGE  0x40
332 #define SCSI_DATA_IN_PDU_FLAG_OVERFLOW      SCSI_RSP_PDU_FLAG_OVERFLOW
333 #define SCSI_DATA_IN_PDU_FLAG_UNDERFLOW     SCSI_RSP_PDU_FLAG_UNDERFLOW
334 #define SCSI_DATA_IN_PDU_FLAG_STATUS_VALID  0x01
335 
336 ///
337 /// SCSI Data-In
338 ///
339 typedef struct _ISCSI_SCSI_DATA_IN {
340   UINT8   OpCode;
341   UINT8   Flags;
342   UINT8   Reserved1;
343   UINT8   Status;
344   UINT8   TotalAHSLength;
345   UINT8   DataSegmentLength[3];
346   UINT8   Lun[8];
347   UINT32  InitiatorTaskTag;
348   UINT32  TargetTransferTag;
349   UINT32  StatSN;
350   UINT32  ExpCmdSN;
351   UINT32  MaxCmdSN;
352   UINT32  DataSN;
353   UINT32  BufferOffset;
354   UINT32  ResidualCount;
355 } ISCSI_SCSI_DATA_IN;
356 
357 #define ISCSI_GET_BUFFER_OFFSET(PduHdr) NTOHL (((ISCSI_SCSI_DATA_IN *) (PduHdr))->BufferOffset)
358 
359 ///
360 /// Ready To Transfer
361 ///
362 typedef struct _ISCSI_READY_TO_TRANSFER {
363   UINT8   OpCode;
364   UINT8   Reserved1[3];
365   UINT8   TotalAHSLength;
366   UINT8   DataSegmentLength[3];
367   UINT8   Lun[8];
368   UINT32  InitiatorTaskTag;
369   UINT32  TargetTransferTag;
370   UINT32  StatSN;
371   UINT32  ExpCmdSN;
372   UINT32  MaxCmdSN;
373   UINT32  R2TSeqNum;
374   UINT32  BufferOffset;
375   UINT32  DesiredDataTransferLength;
376 } ISCSI_READY_TO_TRANSFER;
377 
378 typedef struct _ISCSI_ASYNC_MESSAGE {
379   UINT8   OpCode;
380   UINT8   Reserved1[8];
381   UINT8   TotalAHSLength;
382   UINT8   DataSegmentLength[3];
383   UINT8   Lun[8];
384   UINT32  InitiatorTaskTag;
385   UINT32  Reserved2;
386   UINT32  StatSN;
387   UINT32  ExpCmdSN;
388   UINT32  MaxCmdSN;
389   UINT8   AsyncEvent;
390   UINT8   AsyncVCode;
391   UINT16  Parameter1;
392   UINT16  Parameter2;
393   UINT16  Parameter3;
394   UINT32  Reserved3;
395 } ISCSI_ASYNC_MESSAGE;
396 
397 #define ISCSI_LOGIN_REQ_PDU_FLAG_TRANSIT  0x80
398 #define ISCSI_LOGIN_REQ_PDU_FLAG_CONTINUE 0x40
399 
400 ///
401 /// Login Request
402 ///
403 typedef struct _ISCSI_LOGIN_REQUEST {
404   UINT8   OpCode;
405   UINT8   Flags;
406   UINT8   VersionMax;
407   UINT8   VersionMin;
408   UINT8   TotalAHSLength;
409   UINT8   DataSegmentLength[3];
410   UINT8   Isid[6];
411   UINT16  Tsih;
412   UINT32  InitiatorTaskTag;
413   UINT16  Cid;
414   UINT16  Reserved1;
415   UINT32  CmdSN;
416   UINT32  ExpStatSN;
417   UINT32  Reserved2[4];
418 } ISCSI_LOGIN_REQUEST;
419 
420 #define ISCSI_LOGIN_RSP_PDU_FLAG_TRANSIT    ISCSI_LOGIN_REQ_PDU_FLAG_TRANSIT
421 #define ISCSI_LOGIN_RSP_PDU_FLAG_CONTINUE   ISCSI_LOGIN_REQ_PDU_FLAG_CONTINUE
422 
423 #define ISCSI_LOGIN_STATUS_SUCCESS          0
424 #define ISCSI_LOGIN_STATUS_REDIRECTION      1
425 #define ISCSI_LOGIN_STATUS_INITIATOR_ERROR  2
426 #define ISCSI_LOGIN_STATUS_TARGET_ERROR     3
427 
428 ///
429 /// Login Response
430 ///
431 typedef struct _ISCSI_LOGIN_RESPONSE {
432   UINT8   OpCode;
433   UINT8   Flags;
434   UINT8   VersionMax;
435   UINT8   VersionActive;
436   UINT8   TotalAHSLength;
437   UINT8   DataSegmentLength[3];
438   UINT8   Isid[6];
439   UINT16  Tsih;
440   UINT32  InitiatorTaskTag;
441   UINT32  Reserved1;
442   UINT32  StatSN;
443   UINT32  ExpCmdSN;
444   UINT32  MaxCmdSN;
445   UINT8   StatusClass;
446   UINT8   StatusDetail;
447   UINT8   Reserved2[10];
448 } ISCSI_LOGIN_RESPONSE;
449 
450 #define ISCSI_LOGOUT_REASON_CLOSE_SESSION                   0
451 #define ISCSI_LOGOUT_REASON_CLOSE_CONNECTION                1
452 #define ISCSI_LOGOUT_REASON_REMOVE_CONNECTION_FOR_RECOVERY  2
453 
454 ///
455 /// Logout Request
456 ///
457 typedef struct _ISCSI_LOGOUT_REQUEST {
458   UINT8   OpCode;
459   UINT8   ReasonCode;
460   UINT16  Reserved1;
461   UINT8   TotalAHSLength;
462   UINT8   DataSegmentLength[3];
463   UINT32  Reserved2[2];
464   UINT32  InitiatorTaskTag;
465   UINT16  Cid;
466   UINT16  Reserved3;
467   UINT32  CmdSN;
468   UINT32  ExpStatSN;
469   UINT32  Reserved4[4];
470 } ISCSI_LOGOUT_REQUEST;
471 
472 #define ISCSI_LOGOUT_RESPONSE_SESSION_CLOSED_SUCCESS  0
473 #define ISCSI_LOGOUT_RESPONSE_CID_NOT_FOUND           1
474 #define ISCSI_LOGOUT_RESPONSE_RECOVERY_NOT_SUPPORTED  2
475 #define ISCSI_LOGOUT_RESPONSE_CLEANUP_FAILED          3
476 
477 ///
478 /// Logout Response
479 ///
480 typedef struct _ISCSI_LOGOUT_RESPONSE {
481   UINT8   OpCode;
482   UINT8   Reserved1;
483   UINT8   Response;
484   UINT8   Reserved2;
485   UINT8   TotalAHSLength;
486   UINT8   DataSegmentLength[3];
487   UINT32  Reserved3[2];
488   UINT32  InitiatorTaskTag;
489   UINT32  Reserved4;
490   UINT32  StatSN;
491   UINT32  ExpCmdSN;
492   UINT32  MaxCmdSN;
493   UINT32  Reserved5;
494   UINT16  Time2Wait;
495   UINT16  Time2Retain;
496   UINT32  Reserved6;
497 } ISCSI_LOGOUT_RESPONSE;
498 
499 #define ISCSI_SNACK_REQUEST_TYPE_DATA_OR_R2T  0
500 #define ISCSI_SNACK_REQUEST_TYPE_STATUS       1
501 #define ISCSI_SNACK_REQUEST_TYPE_DATA_ACK     2
502 #define ISCSI_SNACK_REQUEST_TYPE_RDATA        3
503 
504 ///
505 /// SNACK Request
506 ///
507 typedef struct _ISCSI_SNACK_REQUEST {
508   UINT8   OpCode;
509   UINT8   Type;
510   UINT16  Reserved1;
511   UINT8   TotalAHSLength;
512   UINT8   DataSegmentLength[3];
513   UINT8   Lun[8];
514   UINT32  InitiatorTaskTag;
515   UINT32  TargetTransferTag;
516   UINT32  Reserved2;
517   UINT32  ExpStatSN;
518   UINT32  Reserved[2];
519   UINT32  BegRun;
520   UINT32  RunLength;
521 } ISCSI_SNACK_REQUEST;
522 
523 ///
524 /// Reject
525 ///
526 typedef struct _ISCSI_REJECT {
527   UINT8   OpCode;
528   UINT8   Reserved1;
529   UINT8   Reason;
530   UINT8   Reserved2;
531   UINT8   TotalAHSLength;
532   UINT8   DataSegmentLength[3];
533   UINT32  Reserved3[2];
534   UINT32  InitiatorTaskTag;
535   UINT32  Reserved4;
536   UINT32  StatSN;
537   UINT32  ExpCmdSN;
538   UINT32  MaxCmdSN;
539   UINT32  DataSN;
540   UINT32  Reserved5[2];
541 } ISCSI_REJECT;
542 
543 ///
544 /// NOP-Out
545 ///
546 typedef struct _ISCSI_NOP_OUT {
547   UINT8   OpCode;
548   UINT8   Reserved1[3];
549   UINT8   TotalAHSLength;
550   UINT8   DataSegmentLength[3];
551   UINT8   Lun[8];
552   UINT32  InitiatorTaskTag;
553   UINT32  TargetTransferTag;
554   UINT32  CmdSN;
555   UINT32  ExpStatSN;
556   UINT32  Reserved2[4];
557 } ISCSI_NOP_OUT;
558 
559 ///
560 /// NOP-In
561 ///
562 typedef struct _ISCSI_NOP_IN {
563   UINT8   OpCode;
564   UINT8   Reserved1[3];
565   UINT8   TotalAHSLength;
566   UINT8   DataSegmentLength[3];
567   UINT8   Lun[8];
568   UINT32  InitiatorTaskTag;
569   UINT32  TargetTransferTag;
570   UINT32  StatSN;
571   UINT32  ExpCmdSN;
572   UINT32  MaxCmdSN;
573   UINT32  Reserved2[3];
574 } ISCSI_NOP_IN;
575 
576 #define ISCSI_SECURITY_NEGOTIATION          0
577 #define ISCSI_LOGIN_OPERATIONAL_NEGOTIATION 1
578 #define ISCSI_FULL_FEATURE_PHASE            3
579 
580 typedef enum {
581   IScsiDigestNone,
582   IScsiDigestCRC32
583 } ISCSI_DIGEST_TYPE;
584 
585 typedef struct _ISCSI_XFER_CONTEXT {
586   UINT32  TargetTransferTag;
587   UINT32  Offset;
588   UINT32  DesiredLength;
589   UINT32  ExpDataSN;
590 } ISCSI_XFER_CONTEXT;
591 
592 typedef struct _ISCSI_IN_BUFFER_CONTEXT {
593   UINT8   *InData;
594   UINT32  InDataLen;
595 } ISCSI_IN_BUFFER_CONTEXT;
596 
597 typedef struct _ISCSI_TCB {
598   LIST_ENTRY          Link;
599 
600   BOOLEAN             SoFarInOrder;
601   UINT32              ExpDataSN;
602   BOOLEAN             FbitReceived;
603   BOOLEAN             StatusXferd;
604   UINT32              ActiveR2Ts;
605   UINT32              Response;
606   CHAR8               *Reason;
607   UINT32              InitiatorTaskTag;
608   UINT32              CmdSN;
609   UINT32              SNACKTag;
610 
611   ISCSI_XFER_CONTEXT  XferContext;
612 
613   ISCSI_CONNECTION    *Conn;
614 } ISCSI_TCB;
615 
616 typedef struct _ISCSI_KEY_VALUE_PAIR {
617   LIST_ENTRY      List;
618 
619   CHAR8           *Key;
620   CHAR8           *Value;
621 } ISCSI_KEY_VALUE_PAIR;
622 
623 /**
624   Attach the iSCSI connection to the iSCSI session.
625 
626   @param[in, out]  Session The iSCSI session.
627   @param[in, out]  Conn    The iSCSI connection.
628 **/
629 VOID
630 IScsiAttatchConnection (
631   IN OUT ISCSI_SESSION     *Session,
632   IN OUT ISCSI_CONNECTION  *Conn
633   );
634 
635 /**
636   Detach the iSCSI connection from the session it belongs to.
637 
638   @param[in, out]  Conn The iSCSI connection.
639 **/
640 VOID
641 IScsiDetatchConnection (
642   IN OUT ISCSI_CONNECTION  *Conn
643   );
644 
645 /**
646   This function does the iSCSI connection login.
647 
648   @param[in, out]  Conn      The iSCSI connection to login.
649 
650   @retval EFI_SUCCESS        The iSCSI connection is logged into the iSCSI target.
651   @retval EFI_TIMEOUT        Timeout happened during the login procedure.
652   @retval Others             Other errors as indicated.
653 **/
654 EFI_STATUS
655 IScsiConnLogin (
656   IN OUT ISCSI_CONNECTION  *Conn
657   );
658 
659 /**
660   Create a TCP connection for the iSCSI session.
661 
662   @param[in]  Private The iSCSI driver data.
663   @param[in]  Session Maximum CmdSN from the target.
664 
665   @return The newly created iSCSI connection.
666 **/
667 ISCSI_CONNECTION *
668 IScsiCreateConnection (
669   IN ISCSI_DRIVER_DATA  *Private,
670   IN ISCSI_SESSION      *Session
671   );
672 
673 /**
674   Destroy an iSCSI connection.
675 
676   @param[in]  Conn The connection to destroy.
677 **/
678 VOID
679 IScsiDestroyConnection (
680   IN ISCSI_CONNECTION  *Conn
681   );
682 
683 /**
684   Login the iSCSI session.
685 
686   @param[in]  Private          The iSCSI driver data.
687 
688   @retval EFI_SUCCESS          The iSCSI session login procedure finished.
689   @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.
690   @retval EFI_NO_MEDIA         There was a media error.
691   @retval Others               Other errors as indicated.
692 
693 **/
694 EFI_STATUS
695 IScsiSessionLogin (
696   IN ISCSI_DRIVER_DATA  *Private
697   );
698 
699 /**
700   Build and send the iSCSI login request to the iSCSI target according to
701   the current login stage.
702 
703   @param[in]  Conn             The connection in the iSCSI login phase.
704 
705   @retval EFI_SUCCESS          The iSCSI login request PDU is built and sent on this
706                                connection.
707   @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.
708   @retval EFI_DEVICE_ERROR     Some kind of device error happened.
709 **/
710 EFI_STATUS
711 IScsiSendLoginReq (
712   IN ISCSI_CONNECTION  *Conn
713   );
714 
715 /**
716   Receive and process the iSCSI login response.
717 
718   @param[in]  Conn             The connection in the iSCSI login phase.
719 
720   @retval EFI_SUCCESS          The iSCSI login response PDU is received and processed.
721   @retval Others               Other errors as indicated.
722 **/
723 EFI_STATUS
724 IScsiReceiveLoginRsp (
725   IN ISCSI_CONNECTION  *Conn
726   );
727 
728 /**
729   Add an iSCSI key-value pair as a string into the data segment of the Login Request PDU.
730   The DataSegmentLength and the actual size of the net buffer containing this PDU will be
731   updated.
732 
733   @param[in, out]  Pdu         The iSCSI PDU whose data segment the key-value pair will
734                                be added to.
735   @param[in]       Key         The key name string.
736   @param[in]       Value       The value string.
737 
738   @retval EFI_SUCCESS          The key-valu pair is added to the PDU's datasegment and
739                                the correspondence length fields are updated.
740   @retval EFI_OUT_OF_RESOURCES There is not enough space in the PDU to add the key-value
741                                pair.
742 **/
743 EFI_STATUS
744 IScsiAddKeyValuePair (
745   IN OUT NET_BUF      *Pdu,
746   IN CHAR8            *Key,
747   IN CHAR8            *Value
748   );
749 
750 /**
751   Prepare the iSCSI login request to be sent according to the current login status.
752 
753   @param[in, out]  Conn The connection in the iSCSI login phase.
754 
755   @return The pointer to the net buffer containing the iSCSI login request built.
756   @retval Others    Other errors as indicated.
757 **/
758 NET_BUF *
759 IScsiPrepareLoginReq (
760   IN OUT ISCSI_CONNECTION  *Conn
761   );
762 
763 /**
764   Process the iSCSI Login Response.
765 
766   @param[in, out]  Conn The connection on which the iSCSI login response is received.
767   @param[in, out]  Pdu  The iSCSI login response PDU.
768 
769   @retval EFI_SUCCESS        The iSCSI login response PDU is processed and all check are passed.
770   @retval EFI_PROTOCOL_ERROR Some kind of iSCSI protocol error happened.
771   @retval EFI_MEDIA_CHANGED  Target is redirected.
772   @retval Others             Other errors as indicated.
773 **/
774 EFI_STATUS
775 IScsiProcessLoginRsp (
776   IN OUT ISCSI_CONNECTION  *Conn,
777   IN OUT NET_BUF           *Pdu
778   );
779 
780 /**
781   Updated the target information according the data received in the iSCSI
782   login response with an target redirection status.
783 
784   @param[in, out] Session      The iSCSI session.
785   @param[in]      Data         The data segment which should contain the
786                                TargetAddress key-value list.
787   @param[in]      Len          Length of the data.
788 
789   @retval EFI_SUCCESS          The target address is updated.
790   @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.
791   @retval EFI_NOT_FOUND        The TargetAddress key is not found.
792   @retval Others               Other errors as indicated.
793 **/
794 EFI_STATUS
795 IScsiUpdateTargetAddress (
796   IN OUT ISCSI_SESSION  *Session,
797   IN CHAR8              *Data,
798   IN UINT32             Len
799   );
800 
801 /**
802   The callback function to free the net buffer list.
803 
804   @param[in]  Arg The opaque parameter.
805 **/
806 VOID
807 EFIAPI
808 IScsiFreeNbufList (
809   VOID *Arg
810   );
811 
812 /**
813   Receive an iSCSI response PDU. An iSCSI response PDU contains an iSCSI PDU header and
814   an optional data segment. The two parts will be put into two blocks of buffers in the
815   net buffer. The digest check will be conducted in this function if needed and the digests
816   will be trimmed from the PDU buffer.
817 
818   @param[in]   Conn        The iSCSI connection to receive data from.
819   @param[out]  Pdu         The received iSCSI pdu.
820   @param[in]   Context     The context used to describe information on the caller provided
821                            buffer to receive data segment of the iSCSI pdu, it's optional.
822   @param[in]  HeaderDigest Whether there will be header digest received.
823   @param[in]  DataDigest   Whether there will be data digest.
824   @param[in]  TimeoutEvent The timeout event, it's optional.
825 
826   @retval EFI_SUCCESS          An iSCSI pdu is received.
827   @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.
828   @retval EFI_PROTOCOL_ERROR   Some kind of iSCSI protocol error happened.
829   @retval Others               Other errors as indicated.
830 **/
831 EFI_STATUS
832 IScsiReceivePdu (
833   IN ISCSI_CONNECTION                      *Conn,
834   OUT NET_BUF                              **Pdu,
835   IN ISCSI_IN_BUFFER_CONTEXT               *Context, OPTIONAL
836   IN BOOLEAN                               HeaderDigest,
837   IN BOOLEAN                               DataDigest,
838   IN EFI_EVENT                             TimeoutEvent OPTIONAL
839   );
840 
841 /**
842   Check and get the result of the prameter negotiation.
843 
844   @param[in, out]  Conn          The connection in iSCSI login.
845 
846   @retval EFI_SUCCESS          The parmeter check is passed and negotiation is finished.
847   @retval EFI_PROTOCOL_ERROR   Some kind of iSCSI protocol error happened.
848   @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.
849 **/
850 EFI_STATUS
851 IScsiCheckOpParams (
852   IN OUT ISCSI_CONNECTION  *Conn
853   );
854 
855 /**
856   Fill the oprational prameters.
857 
858   @param[in]       Conn        The connection in iSCSI login.
859   @param[in, out]  Pdu         The iSCSI login request PDU to fill the parameters.
860 
861   @retval EFI_SUCCESS          The parmeters are filled into the iSCSI login request PDU.
862 **/
863 EFI_STATUS
864 IScsiFillOpParams (
865   IN ISCSI_CONNECTION  *Conn,
866   IN OUT NET_BUF       *Pdu
867   );
868 
869 /**
870   Pad the iSCSI AHS or data segment to an integer number of 4 byte words.
871 
872   @param[in, out]  Pdu         The iSCSI pdu which contains segments to pad.
873   @param[in]       Len         The length of the last semgnet in the PDU.
874 
875   @retval EFI_SUCCESS          The segment is padded or no need to pad it.
876   @retval EFI_OUT_OF_RESOURCES There is not enough remaining free space to add the
877                                padding bytes.
878 **/
879 EFI_STATUS
880 IScsiPadSegment (
881   IN OUT NET_BUF  *Pdu,
882   IN UINT32       Len
883   );
884 
885 /**
886   Build a key-value list from the data segment.
887 
888   @param[in]  Data The data segment containing the key-value pairs.
889   @param[in]  Len  Length of the data segment.
890 
891   @return The key-value list.
892   @retval NULL Other errors as indicated.
893 **/
894 LIST_ENTRY *
895 IScsiBuildKeyValueList (
896   IN CHAR8  *Data,
897   IN UINT32 Len
898   );
899 
900 /**
901   Get the value string by the key name from the key-value list. If found,
902   the key-value entry will be removed from the list.
903 
904   @param[in, out]  KeyValueList  The key-value list.
905   @param[in]       Key           The key name to find.
906 
907   @return The value string.
908 **/
909 CHAR8 *
910 IScsiGetValueByKeyFromList (
911   IN OUT LIST_ENTRY  *KeyValueList,
912   IN CHAR8           *Key
913   );
914 
915 /**
916   Free the key-value list.
917 
918   @param[in]  KeyValueList The key-value list.
919 **/
920 VOID
921 IScsiFreeKeyValueList (
922   IN LIST_ENTRY      *KeyValueList
923   );
924 
925 /**
926   Normalize the iSCSI name according to RFC.
927 
928   @param[in, out]  Name       The iSCSI name.
929   @param[in]       Len        length of the iSCSI name.
930 
931   @retval EFI_SUCCESS        The iSCSI name is valid and normalized.
932   @retval EFI_PROTOCOL_ERROR The iSCSI name is mal-formatted or not in the IQN format.
933 **/
934 EFI_STATUS
935 IScsiNormalizeName (
936   IN OUT CHAR8  *Name,
937   IN UINTN      Len
938   );
939 
940 /**
941   Execute the SCSI command issued through the EXT SCSI PASS THRU protocol.
942 
943   @param[in]       PassThru  The EXT SCSI PASS THRU protocol.
944   @param[in]       Target    The target ID.
945   @param[in]       Lun       The LUN.
946   @param[in, out]  Packet    The request packet containing IO request, SCSI command
947                              buffer and buffers to read/write.
948 
949   @retval EFI_SUCCES           The SCSI command is executed and the result is updated to
950                                the Packet.
951   @retval EFI_DEVICE_ERROR     Session state was not as required.
952   @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.
953   @retval EFI_NOT_READY        The target can not accept new commands.
954   @retval Others               Other errors as indicated.
955 **/
956 EFI_STATUS
957 IScsiExecuteScsiCommand (
958   IN EFI_EXT_SCSI_PASS_THRU_PROTOCOL                 *PassThru,
959   IN UINT8                                           *Target,
960   IN UINT64                                          Lun,
961   IN OUT EFI_EXT_SCSI_PASS_THRU_SCSI_REQUEST_PACKET  *Packet
962   );
963 
964 /**
965   Reinstate the session on some error.
966 
967   @param[in, out]  Private The iSCSI driver data.
968 
969   @retval EFI_SUCCES  The session is reinstated from some error.
970   @retval Other       Reinstatement failed.
971 **/
972 EFI_STATUS
973 IScsiSessionReinstatement (
974   IN OUT ISCSI_DRIVER_DATA  *Private
975   );
976 
977 /**
978   Initialize some session parameters before login.
979 
980   @param[in, out]  Session  The iSCSI session.
981   @param[in]       Recovery Whether the request is from a fresh new start or recovery.
982 **/
983 VOID
984 IScsiSessionInit (
985   IN OUT ISCSI_SESSION  *Session,
986   IN BOOLEAN            Recovery
987   );
988 
989 /**
990   Abort the iSCSI session, that is, reset all the connection and free the
991   resources.
992 
993   @param[in, out]  Session The iSCSI session.
994 
995   @retval EFI_SUCCES  The session is aborted.
996 **/
997 EFI_STATUS
998 IScsiSessionAbort (
999   IN OUT ISCSI_SESSION  *Session
1000   );
1001 
1002 #endif
1003