1 /* $NetBSD: iscsi_pdu.h,v 1.4 2017/12/03 19:07:10 christos Exp $ */ 2 3 /*- 4 * Copyright (c) 2004,2005,2006,2011 The NetBSD Foundation, Inc. 5 * All rights reserved. 6 * 7 * This code is derived from software contributed to The NetBSD Foundation 8 * by Wasabi Systems, Inc. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 * POSSIBILITY OF SUCH DAMAGE. 30 */ 31 #ifndef _ISCSI_PDU_H 32 #define _ISCSI_PDU_H 33 34 #define BHS_SIZE 48 /* Basic Header Segment (without digest) */ 35 #define PDU_HEADER_SIZE 52 /* PDU Header with Digest */ 36 37 #define OP_IMMEDIATE 0x40 /* Bit 1 in Opcode field: immediate delivery */ 38 #define OPCODE_MASK 0x3f /* Mask for opcode */ 39 40 /* PDU Flags field */ 41 42 #define FLAG_FINAL 0x80 /* Bit 0: Final PDU in sequence */ 43 #define FLAG_TRANSIT 0x80 /* Bit 0: Transit to next login phase */ 44 #define FLAG_CONTINUE 0x40 /* Bit 1: Continue PDU */ 45 #define FLAG_ACK 0x40 /* Bit 1: Acknowledge */ 46 #define FLAG_READ 0x40 /* Bit 1: Read Data */ 47 #define FLAG_WRITE 0x20 /* Bit 2: Write Data */ 48 #define FLAG_BIDI_OFLO 0x10 /* Bit 3: Bidirectional Read Residual Oflow */ 49 #define FLAG_BIDI_UFLOW 0x08 /* Bit 4: Bidirectional Read Residual Uflow */ 50 #define FLAG_OVERFLOW 0x04 /* Bit 5: Residual Overflow */ 51 #define FLAG_UNDERFLOW 0x02 /* Bit 6: Residual Underflow */ 52 #define FLAG_STATUS 0x01 /* Bit 7: Command Status is valid */ 53 54 /* CSG/NSG flag field codes */ 55 56 #define SG_SECURITY_NEGOTIATION 0 57 #define SG_LOGIN_OPERATIONAL_NEGOTIATION 1 58 #define SG_FULL_FEATURE_PHASE 3 59 60 #define CSG_SHIFT 2 /* shift factor for CSG field */ 61 #define SG_MASK 3 /* mask for CSG (after shift) and NSG */ 62 63 #define NEXT_PHASE(ph) ((!ph) ? 1 : 3) /* no phase 2 */ 64 65 /* Task Management Function Codes (in Flags byte) */ 66 67 #define ABORT_TASK 1 68 #define ABORT_TASK_SET 2 69 #define CLEAR_ACA 3 70 #define CLEAR_TASK_SET 4 71 #define LOGICAL_UNIT_RESET 5 72 #define TARGET_WARM_RESET 6 73 #define TARGET_COLD_RESET 7 74 #define TASK_REASSIGN 8 75 76 /* ISID T-Field (first byte) */ 77 78 #define T_FORMAT_OUI 0x00 79 #define T_FORMAT_EN 0x40 80 #define T_FORMAT_RANDOM 0x80 81 82 83 /* Task Attributes */ 84 85 #define ATTR_UNTAGGED 0 86 #define ATTR_SIMPLE 1 87 #define ATTR_ORDERED 2 88 #define ATTR_HEAD_OF_QUEUE 3 89 #define ATTR_ACA 4 90 91 /* Initiator Opcodes */ 92 93 #define IOP_NOP_Out 0x00 94 #define IOP_SCSI_Command 0x01 95 #define IOP_SCSI_Task_Management 0x02 96 #define IOP_Login_Request 0x03 97 #define IOP_Text_Request 0x04 98 #define IOP_SCSI_Data_out 0x05 99 #define IOP_Logout_Request 0x06 100 #define IOP_SNACK_Request 0x10 101 102 /* Target Opcodes */ 103 104 #define TOP_NOP_In 0x20 105 #define TOP_SCSI_Response 0x21 106 #define TOP_SCSI_Task_Management 0x22 107 #define TOP_Login_Response 0x23 108 #define TOP_Text_Response 0x24 109 #define TOP_SCSI_Data_in 0x25 110 #define TOP_Logout_Response 0x26 111 #define TOP_R2T 0x31 112 #define TOP_Asynchronous_Message 0x32 113 #define TOP_Reject 0x3f 114 115 /* 116 * The Opcode-dependent fields of the BHS, defined per PDU 117 */ 118 119 /* Command + Response */ 120 121 struct scsi_command_pdu_s 122 { 123 uint32_t ExpectedDataTransferLength; 124 uint32_t CmdSN; 125 uint32_t ExpStatSN; 126 uint8_t SCSI_CDB[16]; 127 } __packed; 128 129 typedef struct scsi_command_pdu_s scsi_command_pdu_t; 130 131 struct scsi_response_pdu_s 132 { 133 uint32_t SNACKTag; 134 uint32_t StatSN; 135 uint32_t ExpCmdSN; 136 uint32_t MaxCmdSN; 137 uint32_t ExpDataSN; 138 uint32_t ReadResidualCount; 139 uint32_t ResidualCount; 140 } __packed; 141 142 typedef struct scsi_response_pdu_s scsi_response_pdu_t; 143 144 145 /* Task Management */ 146 147 struct task_management_req_pdu_s 148 { 149 uint32_t ReferencedTaskTag; 150 uint32_t CmdSN; 151 uint32_t ExpStatSN; 152 uint32_t RefCmdSN; 153 uint32_t ExpDataSN; 154 uint8_t reserved[8]; 155 } __packed; 156 157 typedef struct task_management_req_pdu_s task_management_req_pdu_t; 158 159 160 struct task_management_rsp_pdu_s 161 { 162 uint32_t reserved1; 163 uint32_t StatSN; 164 uint32_t ExpCmdSN; 165 uint32_t MaxCmdSN; 166 uint8_t reserved2[12]; 167 } __packed; 168 169 typedef struct task_management_rsp_pdu_s task_management_rsp_pdu_t; 170 171 172 /* Data Out & In, R2T */ 173 174 struct data_out_pdu_s 175 { 176 uint32_t TargetTransferTag; 177 uint32_t reserved1; 178 uint32_t ExpStatSN; 179 uint32_t reserved2; 180 uint32_t DataSN; 181 uint32_t BufferOffset; 182 uint32_t reserved3; 183 } __packed; 184 185 typedef struct data_out_pdu_s data_out_pdu_t; 186 187 188 struct data_in_pdu_s 189 { 190 uint32_t TargetTransferTag; 191 uint32_t StatSN; 192 uint32_t ExpCmdSN; 193 uint32_t MaxCmdSN; 194 uint32_t DataSN; 195 uint32_t BufferOffset; 196 uint32_t ResidualCount; 197 } __packed; 198 199 typedef struct data_in_pdu_s data_in_pdu_t; 200 201 202 struct r2t_pdu_s 203 { 204 uint32_t TargetTransferTag; 205 uint32_t StatSN; 206 uint32_t ExpCmdSN; 207 uint32_t MaxCmdSN; 208 uint32_t R2TSN; 209 uint32_t BufferOffset; 210 uint32_t DesiredDataTransferLength; 211 } __packed; 212 213 typedef struct r2t_pdu_s r2t_pdu_t; 214 215 216 /* Asynch message */ 217 218 struct asynch_pdu_s 219 { 220 uint32_t reserved1; 221 uint32_t StatSN; 222 uint32_t ExpCmdSN; 223 uint32_t MaxCmdSN; 224 uint8_t AsyncEvent; 225 uint8_t AsyncVCode; 226 uint16_t Parameter1; 227 uint16_t Parameter2; 228 uint16_t Parameter3; 229 uint32_t reserved2; 230 } __packed; 231 232 typedef struct asynch_pdu_s asynch_pdu_t; 233 234 235 /* Text request / response */ 236 237 struct text_req_pdu_s 238 { 239 uint32_t TargetTransferTag; 240 uint32_t CmdSN; 241 uint32_t ExpStatSN; 242 uint8_t reserved[16]; 243 } __packed; 244 245 typedef struct text_req_pdu_s text_req_pdu_t; 246 247 248 struct text_rsp_pdu_s 249 { 250 uint32_t TargetTransferTag; 251 uint32_t StatSN; 252 uint32_t ExpCmdSN; 253 uint32_t MaxCmdSN; 254 uint8_t reserved[12]; 255 } __packed; 256 257 typedef struct text_rsp_pdu_s text_rsp_pdu_t; 258 259 260 /* Login request / response */ 261 262 struct login_req_pdu_s 263 { 264 uint16_t CID; 265 uint16_t reserved1; 266 uint32_t CmdSN; 267 uint32_t ExpStatSN; 268 uint8_t reserved2[16]; 269 } __packed; 270 271 typedef struct login_req_pdu_s login_req_pdu_t; 272 273 /* Overlays LUN field in login request and response */ 274 struct login_isid_s 275 { 276 uint8_t ISID_A; 277 uint16_t ISID_B; 278 uint8_t ISID_C; 279 uint16_t ISID_D; 280 uint16_t TSIH; 281 } __packed; 282 283 typedef struct login_isid_s login_isid_t; 284 285 struct login_rsp_pdu_s 286 { 287 uint32_t reserved1; 288 uint32_t StatSN; 289 uint32_t ExpCmdSN; 290 uint32_t MaxCmdSN; 291 uint8_t StatusClass; 292 uint8_t StatusDetail; 293 uint8_t reserved2[10]; 294 } __packed; 295 296 typedef struct login_rsp_pdu_s login_rsp_pdu_t; 297 298 299 /* Logout request / response */ 300 301 struct logout_req_pdu_s 302 { 303 uint16_t CID; 304 uint16_t reserved2; 305 uint32_t CmdSN; 306 uint32_t ExpStatSN; 307 uint8_t reserved3[16]; 308 } __packed; 309 310 typedef struct logout_req_pdu_s logout_req_pdu_t; 311 312 313 struct logout_rsp_pdu_s 314 { 315 uint32_t reserved2; 316 uint32_t StatSN; 317 uint32_t ExpCmdSN; 318 uint32_t MaxCmdSN; 319 uint32_t reserved3; 320 uint16_t Time2Wait; 321 uint16_t Time2Retain; 322 uint32_t reserved4; 323 } __packed; 324 325 typedef struct logout_rsp_pdu_s logout_rsp_pdu_t; 326 327 328 /* SNACK request */ 329 330 /* SNACK Types (in Flags field) */ 331 332 #define SNACK_DATA_NAK 0 333 #define SNACK_STATUS_NAK 1 334 #define SNACK_DATA_ACK 2 335 #define SNACK_RDATA_NAK 3 336 337 struct snack_req_pdu_s 338 { 339 uint32_t TargetTransferTag; 340 uint32_t reserved1; 341 uint32_t ExpStatSN; 342 uint8_t reserved2[8]; 343 uint32_t BegRun; 344 uint32_t RunLength; 345 } __packed; 346 347 typedef struct snack_req_pdu_s snack_req_pdu_t; 348 349 350 /* Reject */ 351 352 #define REJECT_DIGEST_ERROR 2 353 #define REJECT_SNACK 3 354 #define REJECT_PROTOCOL_ERROR 4 355 #define REJECT_CMD_NOT_SUPPORTED 5 356 #define REJECT_IMMED_COMMAND 6 357 #define REJECT_TASK_IN_PROGRESS 7 358 #define REJECT_INVALID_DATA_ACK 8 359 #define REJECT_INVALID_PDU_FIELD 9 360 #define REJECT_LONG_OPERATION 10 361 #define REJECT_NEGOTIATION_RESET 11 362 #define REJECT_WAITING_FOR_LOGOUT 12 363 364 365 struct reject_pdu_s 366 { 367 uint32_t reserved2; 368 uint32_t StatSN; 369 uint32_t ExpCmdSN; 370 uint32_t MaxCmdSN; 371 uint8_t DataSN; 372 uint8_t reserved[8]; 373 } __packed; 374 375 typedef struct reject_pdu_s reject_pdu_t; 376 377 378 /* NOP Out & In */ 379 380 struct nop_out_pdu_s 381 { 382 uint32_t TargetTransferTag; 383 uint32_t CmdSN; 384 uint32_t ExpStatSN; 385 uint8_t reserved[16]; 386 } __packed; 387 388 typedef struct nop_out_pdu_s nop_out_pdu_t; 389 390 391 struct nop_in_pdu_s 392 { 393 uint32_t TargetTransferTag; 394 uint32_t StatSN; 395 uint32_t ExpCmdSN; 396 uint32_t MaxCmdSN; 397 uint8_t reserved3[12]; 398 } __packed; 399 400 typedef struct nop_in_pdu_s nop_in_pdu_t; 401 402 403 /* 404 * The complete PDU Header. 405 */ 406 407 struct pdu_header_s 408 { 409 uint8_t pduh_Opcode; 410 uint8_t pduh_Flags; 411 uint8_t pduh_OpcodeSpecific[2]; 412 uint8_t pduh_TotalAHSLength; 413 uint8_t pduh_DataSegmentLength[3]; 414 uint64_t pduh_LUN; 415 uint32_t pduh_InitiatorTaskTag; 416 union 417 { 418 scsi_command_pdu_t command; 419 scsi_response_pdu_t response; 420 task_management_req_pdu_t task_req; 421 task_management_rsp_pdu_t task_rsp; 422 data_out_pdu_t data_out; 423 data_in_pdu_t data_in; 424 r2t_pdu_t r2t; 425 asynch_pdu_t asynch; 426 text_req_pdu_t text_req; 427 text_rsp_pdu_t text_rsp; 428 login_req_pdu_t login_req; 429 login_rsp_pdu_t login_rsp; 430 logout_req_pdu_t logout_req; 431 logout_rsp_pdu_t logout_rsp; 432 snack_req_pdu_t snack; 433 reject_pdu_t reject; 434 nop_out_pdu_t nop_out; 435 nop_in_pdu_t nop_in; 436 } pduh_p; 437 uint32_t pduh_HeaderDigest; 438 } __packed; 439 440 typedef struct pdu_header_s pdu_header_t; 441 442 #endif /* !_ISCSI_PDU_H */ 443