Home | History | Annotate | Download | only in IScsiDxe
      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