/* $NetBSD: iscsi_pdu.h,v 1.4 2017/12/03 19:07:10 christos Exp $ */ /*- * Copyright (c) 2004,2005,2006,2011 The NetBSD Foundation, Inc. * All rights reserved. * * This code is derived from software contributed to The NetBSD Foundation * by Wasabi Systems, Inc. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ #ifndef _ISCSI_PDU_H #define _ISCSI_PDU_H #define BHS_SIZE 48 /* Basic Header Segment (without digest) */ #define PDU_HEADER_SIZE 52 /* PDU Header with Digest */ #define OP_IMMEDIATE 0x40 /* Bit 1 in Opcode field: immediate delivery */ #define OPCODE_MASK 0x3f /* Mask for opcode */ /* PDU Flags field */ #define FLAG_FINAL 0x80 /* Bit 0: Final PDU in sequence */ #define FLAG_TRANSIT 0x80 /* Bit 0: Transit to next login phase */ #define FLAG_CONTINUE 0x40 /* Bit 1: Continue PDU */ #define FLAG_ACK 0x40 /* Bit 1: Acknowledge */ #define FLAG_READ 0x40 /* Bit 1: Read Data */ #define FLAG_WRITE 0x20 /* Bit 2: Write Data */ #define FLAG_BIDI_OFLO 0x10 /* Bit 3: Bidirectional Read Residual Oflow */ #define FLAG_BIDI_UFLOW 0x08 /* Bit 4: Bidirectional Read Residual Uflow */ #define FLAG_OVERFLOW 0x04 /* Bit 5: Residual Overflow */ #define FLAG_UNDERFLOW 0x02 /* Bit 6: Residual Underflow */ #define FLAG_STATUS 0x01 /* Bit 7: Command Status is valid */ /* CSG/NSG flag field codes */ #define SG_SECURITY_NEGOTIATION 0 #define SG_LOGIN_OPERATIONAL_NEGOTIATION 1 #define SG_FULL_FEATURE_PHASE 3 #define CSG_SHIFT 2 /* shift factor for CSG field */ #define SG_MASK 3 /* mask for CSG (after shift) and NSG */ #define NEXT_PHASE(ph) ((!ph) ? 1 : 3) /* no phase 2 */ /* Task Management Function Codes (in Flags byte) */ #define ABORT_TASK 1 #define ABORT_TASK_SET 2 #define CLEAR_ACA 3 #define CLEAR_TASK_SET 4 #define LOGICAL_UNIT_RESET 5 #define TARGET_WARM_RESET 6 #define TARGET_COLD_RESET 7 #define TASK_REASSIGN 8 /* ISID T-Field (first byte) */ #define T_FORMAT_OUI 0x00 #define T_FORMAT_EN 0x40 #define T_FORMAT_RANDOM 0x80 /* Task Attributes */ #define ATTR_UNTAGGED 0 #define ATTR_SIMPLE 1 #define ATTR_ORDERED 2 #define ATTR_HEAD_OF_QUEUE 3 #define ATTR_ACA 4 /* Initiator Opcodes */ #define IOP_NOP_Out 0x00 #define IOP_SCSI_Command 0x01 #define IOP_SCSI_Task_Management 0x02 #define IOP_Login_Request 0x03 #define IOP_Text_Request 0x04 #define IOP_SCSI_Data_out 0x05 #define IOP_Logout_Request 0x06 #define IOP_SNACK_Request 0x10 /* Target Opcodes */ #define TOP_NOP_In 0x20 #define TOP_SCSI_Response 0x21 #define TOP_SCSI_Task_Management 0x22 #define TOP_Login_Response 0x23 #define TOP_Text_Response 0x24 #define TOP_SCSI_Data_in 0x25 #define TOP_Logout_Response 0x26 #define TOP_R2T 0x31 #define TOP_Asynchronous_Message 0x32 #define TOP_Reject 0x3f /* * The Opcode-dependent fields of the BHS, defined per PDU */ /* Command + Response */ struct scsi_command_pdu_s { uint32_t ExpectedDataTransferLength; uint32_t CmdSN; uint32_t ExpStatSN; uint8_t SCSI_CDB[16]; } __packed; typedef struct scsi_command_pdu_s scsi_command_pdu_t; struct scsi_response_pdu_s { uint32_t SNACKTag; uint32_t StatSN; uint32_t ExpCmdSN; uint32_t MaxCmdSN; uint32_t ExpDataSN; uint32_t ReadResidualCount; uint32_t ResidualCount; } __packed; typedef struct scsi_response_pdu_s scsi_response_pdu_t; /* Task Management */ struct task_management_req_pdu_s { uint32_t ReferencedTaskTag; uint32_t CmdSN; uint32_t ExpStatSN; uint32_t RefCmdSN; uint32_t ExpDataSN; uint8_t reserved[8]; } __packed; typedef struct task_management_req_pdu_s task_management_req_pdu_t; struct task_management_rsp_pdu_s { uint32_t reserved1; uint32_t StatSN; uint32_t ExpCmdSN; uint32_t MaxCmdSN; uint8_t reserved2[12]; } __packed; typedef struct task_management_rsp_pdu_s task_management_rsp_pdu_t; /* Data Out & In, R2T */ struct data_out_pdu_s { uint32_t TargetTransferTag; uint32_t reserved1; uint32_t ExpStatSN; uint32_t reserved2; uint32_t DataSN; uint32_t BufferOffset; uint32_t reserved3; } __packed; typedef struct data_out_pdu_s data_out_pdu_t; struct data_in_pdu_s { uint32_t TargetTransferTag; uint32_t StatSN; uint32_t ExpCmdSN; uint32_t MaxCmdSN; uint32_t DataSN; uint32_t BufferOffset; uint32_t ResidualCount; } __packed; typedef struct data_in_pdu_s data_in_pdu_t; struct r2t_pdu_s { uint32_t TargetTransferTag; uint32_t StatSN; uint32_t ExpCmdSN; uint32_t MaxCmdSN; uint32_t R2TSN; uint32_t BufferOffset; uint32_t DesiredDataTransferLength; } __packed; typedef struct r2t_pdu_s r2t_pdu_t; /* Asynch message */ struct asynch_pdu_s { uint32_t reserved1; uint32_t StatSN; uint32_t ExpCmdSN; uint32_t MaxCmdSN; uint8_t AsyncEvent; uint8_t AsyncVCode; uint16_t Parameter1; uint16_t Parameter2; uint16_t Parameter3; uint32_t reserved2; } __packed; typedef struct asynch_pdu_s asynch_pdu_t; /* Text request / response */ struct text_req_pdu_s { uint32_t TargetTransferTag; uint32_t CmdSN; uint32_t ExpStatSN; uint8_t reserved[16]; } __packed; typedef struct text_req_pdu_s text_req_pdu_t; struct text_rsp_pdu_s { uint32_t TargetTransferTag; uint32_t StatSN; uint32_t ExpCmdSN; uint32_t MaxCmdSN; uint8_t reserved[12]; } __packed; typedef struct text_rsp_pdu_s text_rsp_pdu_t; /* Login request / response */ struct login_req_pdu_s { uint16_t CID; uint16_t reserved1; uint32_t CmdSN; uint32_t ExpStatSN; uint8_t reserved2[16]; } __packed; typedef struct login_req_pdu_s login_req_pdu_t; /* Overlays LUN field in login request and response */ struct login_isid_s { uint8_t ISID_A; uint16_t ISID_B; uint8_t ISID_C; uint16_t ISID_D; uint16_t TSIH; } __packed; typedef struct login_isid_s login_isid_t; struct login_rsp_pdu_s { uint32_t reserved1; uint32_t StatSN; uint32_t ExpCmdSN; uint32_t MaxCmdSN; uint8_t StatusClass; uint8_t StatusDetail; uint8_t reserved2[10]; } __packed; typedef struct login_rsp_pdu_s login_rsp_pdu_t; /* Logout request / response */ struct logout_req_pdu_s { uint16_t CID; uint16_t reserved2; uint32_t CmdSN; uint32_t ExpStatSN; uint8_t reserved3[16]; } __packed; typedef struct logout_req_pdu_s logout_req_pdu_t; struct logout_rsp_pdu_s { uint32_t reserved2; uint32_t StatSN; uint32_t ExpCmdSN; uint32_t MaxCmdSN; uint32_t reserved3; uint16_t Time2Wait; uint16_t Time2Retain; uint32_t reserved4; } __packed; typedef struct logout_rsp_pdu_s logout_rsp_pdu_t; /* SNACK request */ /* SNACK Types (in Flags field) */ #define SNACK_DATA_NAK 0 #define SNACK_STATUS_NAK 1 #define SNACK_DATA_ACK 2 #define SNACK_RDATA_NAK 3 struct snack_req_pdu_s { uint32_t TargetTransferTag; uint32_t reserved1; uint32_t ExpStatSN; uint8_t reserved2[8]; uint32_t BegRun; uint32_t RunLength; } __packed; typedef struct snack_req_pdu_s snack_req_pdu_t; /* Reject */ #define REJECT_DIGEST_ERROR 2 #define REJECT_SNACK 3 #define REJECT_PROTOCOL_ERROR 4 #define REJECT_CMD_NOT_SUPPORTED 5 #define REJECT_IMMED_COMMAND 6 #define REJECT_TASK_IN_PROGRESS 7 #define REJECT_INVALID_DATA_ACK 8 #define REJECT_INVALID_PDU_FIELD 9 #define REJECT_LONG_OPERATION 10 #define REJECT_NEGOTIATION_RESET 11 #define REJECT_WAITING_FOR_LOGOUT 12 struct reject_pdu_s { uint32_t reserved2; uint32_t StatSN; uint32_t ExpCmdSN; uint32_t MaxCmdSN; uint8_t DataSN; uint8_t reserved[8]; } __packed; typedef struct reject_pdu_s reject_pdu_t; /* NOP Out & In */ struct nop_out_pdu_s { uint32_t TargetTransferTag; uint32_t CmdSN; uint32_t ExpStatSN; uint8_t reserved[16]; } __packed; typedef struct nop_out_pdu_s nop_out_pdu_t; struct nop_in_pdu_s { uint32_t TargetTransferTag; uint32_t StatSN; uint32_t ExpCmdSN; uint32_t MaxCmdSN; uint8_t reserved3[12]; } __packed; typedef struct nop_in_pdu_s nop_in_pdu_t; /* * The complete PDU Header. */ struct pdu_header_s { uint8_t pduh_Opcode; uint8_t pduh_Flags; uint8_t pduh_OpcodeSpecific[2]; uint8_t pduh_TotalAHSLength; uint8_t pduh_DataSegmentLength[3]; uint64_t pduh_LUN; uint32_t pduh_InitiatorTaskTag; union { scsi_command_pdu_t command; scsi_response_pdu_t response; task_management_req_pdu_t task_req; task_management_rsp_pdu_t task_rsp; data_out_pdu_t data_out; data_in_pdu_t data_in; r2t_pdu_t r2t; asynch_pdu_t asynch; text_req_pdu_t text_req; text_rsp_pdu_t text_rsp; login_req_pdu_t login_req; login_rsp_pdu_t login_rsp; logout_req_pdu_t logout_req; logout_rsp_pdu_t logout_rsp; snack_req_pdu_t snack; reject_pdu_t reject; nop_out_pdu_t nop_out; nop_in_pdu_t nop_in; } pduh_p; uint32_t pduh_HeaderDigest; } __packed; typedef struct pdu_header_s pdu_header_t; #endif /* !_ISCSI_PDU_H */