/* $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 */