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