root/sys/scsi/iscsi.h
/*      $OpenBSD: iscsi.h,v 1.9 2019/09/27 23:07:42 krw Exp $ */

/*
 * Copyright (c) 2008 David Gwynne <dlg@openbsd.org>
 *
 * Permission to use, copy, modify, and distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice appear in all copies.
 *
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 */

#ifndef _SCSI_ISCSI_H
#define _SCSI_ISCSI_H

struct iscsi_pdu {
        u_int8_t        opcode;
        u_int8_t        flags;
        u_int8_t        _reserved1[2];

        u_int8_t        ahslen;
        u_int8_t        datalen[3];

        u_int8_t        lun[8];

        u_int32_t       itt;

        u_int8_t        _reserved2[4];

        u_int32_t       cmdsn;

        u_int32_t       expstatsn;

        u_int8_t        _reserved3[16];
} __packed;

/*
 * Initiator opcodes
 */

#define ISCSI_OP_I_NOP                  0x00
#define ISCSI_OP_SCSI_REQUEST           0x01
#define ISCSI_OP_TASK_REQUEST           0x02
#define ISCSI_OP_LOGIN_REQUEST          0x03
#define ISCSI_OP_TEXT_REQUEST           0x04
#define ISCSI_OP_DATA_OUT               0x05
#define ISCSI_OP_LOGOUT_REQUEST         0x06
#define ISCSI_OP_SNACK_REQUEST          0x10

/*
 * Target opcodes
 */

#define ISCSI_OP_T_NOP                  0x20
#define ISCSI_OP_SCSI_RESPONSE          0x21
#define ISCSI_OP_TASK_RESPONSE          0x22
#define ISCSI_OP_LOGIN_RESPONSE         0x23
#define ISCSI_OP_TEXT_RESPONSE          0x24
#define ISCSI_OP_DATA_IN                0x25
#define ISCSI_OP_LOGOUT_RESPONSE        0x26
#define ISCSI_OP_R2T                    0x31
#define ISCSI_OP_ASYNC                  0x32
#define ISCSI_OP_REJECT                 0x3f

#define ISCSI_PDU_OPCODE(_o)            ((_o) & 0x3f)
#define ISCSI_PDU_I(_h)                 ((_h)->opcode & 0x40)
#define ISCSI_PDU_F(_h)                 ((_h)->flags & 0x80)

#define ISCSI_OP_F_IMMEDIATE            0x40

/*
 * various other flags and values
 */
#define ISCSI_ISID_OUI                  0x00000000
#define ISCSI_ISID_EN                   0x40000000
#define ISCSI_ISID_RAND                 0x80000000

struct iscsi_pdu_scsi_request {
        u_int8_t        opcode;
        u_int8_t        flags;
        u_int8_t        _reserved[2];

        u_int8_t        ahslen;
        u_int8_t        datalen[3];

        u_int8_t        lun[8];

        u_int32_t       itt;

        u_int32_t       bytes;

        u_int32_t       cmdsn;

        u_int32_t       expstatsn;

        u_int8_t        cdb[16];
} __packed;

struct iscsi_pdu_scsi_response {
        u_int8_t        opcode;
        u_int8_t        flags;
        u_int8_t        response;
        u_int8_t        status;

        u_int8_t        ahslen;
        u_int8_t        datalen[3];

        u_int8_t        _reserved[8];

        u_int32_t       itt;

        u_int32_t       snack;

        u_int32_t       statsn;

        u_int32_t       expcmdsn;

        u_int32_t       maxcmdsn;

        u_int32_t       expdatasn;

        u_int32_t       birescount;

        u_int32_t       rescount;
} __packed;

#define ISCSI_SCSI_F_F                  0x80
#define ISCSI_SCSI_F_R                  0x40
#define ISCSI_SCSI_F_W                  0x20

#define ISCSI_SCSI_ATTR_UNTAGGED        0
#define ISCSI_SCSI_ATTR_SIMPLE          1
#define ISCSI_SCSI_ATTR_ORDERED         2
#define ISCSI_SCSI_ATTR_HEAD_OF_Q       3
#define ISCSI_SCSI_ATTR_ACA             4

#define ISCSI_SCSI_STAT_GOOD            0x00
#define ISCSI_SCSI_STAT_CHCK_COND       0x02
/* we don't care about the type of the other error conditions */

struct iscsi_pdu_task_request {
        u_int8_t        opcode;
        u_int8_t        flags;
        u_int8_t        reserved[2];

        u_int8_t        ahslen;
        u_int8_t        datalen[3];

        u_int8_t        lun[8];

        u_int32_t       itt;

        u_int32_t       tag;

        u_int32_t       cmdsn;

        u_int32_t       expstatsn;

        u_int32_t       refcmdsn;

        u_int32_t       expdatasn;

        u_int8_t        _reserved[8];
} __packed;

struct iscsi_pdu_task_response {
        u_int8_t        opcode;
        u_int8_t        flags;
        u_int8_t        response;
        u_int8_t        _reserved1;

        u_int8_t        ahslen;
        u_int8_t        datalen[3];

        u_int8_t        _reserved[8];

        u_int32_t       itt;

        u_int8_t        _reserved2[4];

        u_int32_t       statsn;

        u_int32_t       expcmdsn;

        u_int32_t       maxcmdsn;

        u_int8_t        _reserved3[12];
} __packed;

struct iscsi_pdu_data_out {
        u_int8_t        opcode;
        u_int8_t        flags;
        u_int8_t        _reserved1[2];

        u_int8_t        ahslen;
        u_int8_t        datalen[3];

        u_int8_t        lun[8];

        u_int32_t       itt;

        u_int32_t       ttt;

        u_int8_t        _reserved2[4];

        u_int32_t       expstatsn;

        u_int8_t        _reserved3[4];

        u_int32_t       datasn;

        u_int32_t       buffer_offs;

        u_int8_t        _reserved4[4];
} __packed;

struct iscsi_pdu_data_in {
        u_int8_t        opcode;
        u_int8_t        flags;
        u_int8_t        _reserved;
        u_int8_t        status;

        u_int8_t        ahslen;
        u_int8_t        datalen[3];

        u_int8_t        lun[8];

        u_int32_t       itt;

        u_int32_t       ttt;

        u_int32_t       statsn;

        u_int32_t       expcmdsn;

        u_int32_t       maxcmdsn;

        u_int32_t       datasn;

        u_int32_t       buffer_offs;

        u_int32_t       residual;
} __packed;

struct iscsi_pdu_rt2 {
        u_int8_t        opcode;
        u_int8_t        flags;
        u_int8_t        _reserved1[2];

        u_int8_t        ahslen;
        u_int8_t        datalen[3];

        u_int8_t        lun[8];

        u_int32_t       itt;

        u_int32_t       ttt;

        u_int32_t       statsn;

        u_int32_t       expcmdsn;

        u_int32_t       maxcmdsn;

        u_int32_t       r2tsn;

        u_int32_t       buffer_offs;

        u_int32_t       desired_datalen;
} __packed;

struct iscsi_pdu_async {
        u_int8_t        opcode;
        u_int8_t        flags;
        u_int8_t        _reserved1[2];

        u_int8_t        ahslen;
        u_int8_t        datalen[3];

        u_int8_t        lun[8];

        u_int32_t       ffffffff;

        u_int8_t        _reserved2[4];

        u_int32_t       statsn;

        u_int32_t       expcmdsn;

        u_int32_t       maxcmdsn;

        u_int8_t        event;
        u_int8_t        vcode;
        u_int16_t       param[3];

        u_int8_t        _reserved3[4];
} __packed;

struct iscsi_pdu_text_request {
        u_int8_t        opcode;
        u_int8_t        flags;
        u_int8_t        _reserved1[2];

        u_int8_t        ahslen;
        u_int8_t        datalen[3];

        u_int8_t        lun[8];

        u_int32_t       itt;

        u_int32_t       ttt;

        u_int32_t       cmdsn;

        u_int32_t       expstatsn;

        u_int8_t        _reserved2[16];
} __packed;

struct iscsi_pdu_text_response {
        u_int8_t        opcode;
        u_int8_t        flags;
        u_int8_t        _reserved1[2];

        u_int8_t        ahslen;
        u_int8_t        datalen[3];

        u_int8_t        lun[8];

        u_int32_t       itt;

        u_int32_t       ttt;

        u_int32_t       cmdsn;

        u_int32_t       expcmdsn;

        u_int32_t       maxcmdsn;

        u_int8_t        _reserved2[12];
} __packed;

#define ISCSI_TEXT_F_F  0x80
#define ISCSI_TEXT_F_C  0x40

struct iscsi_pdu_login_request {
        u_int8_t        opcode;
        u_int8_t        flags;
        u_int8_t        version_max;
        u_int8_t        version_min;

        u_int8_t        ahslen;
        u_int8_t        datalen[3];

        u_int32_t       isid_base;
        u_int16_t       isid_qual;
        u_int16_t       tsih;

        u_int32_t       itt;

        u_int16_t       cid;
        u_int8_t        _reserved1[2];

        u_int32_t       cmdsn;

        u_int32_t       expstatsn;

        u_int8_t        _reserved2[16];
} __packed;

#define ISCSI_LOGIN_F_T         0x80
#define ISCSI_LOGIN_F_C         0x40
#define ISCSI_LOGIN_F_CSG(x)    (((x) & 0x3) << 2)
#define ISCSI_LOGIN_F_NSG(x)    ((x) & 0x3)
#define ISCSI_LOGIN_STG_SECNEG  0
#define ISCSI_LOGIN_STG_OPNEG   1
#define ISCSI_LOGIN_STG_FULL    3

struct iscsi_pdu_login_response {
        u_int8_t        opcode;
        u_int8_t        flags;
        u_int8_t        version_max;
        u_int8_t        version_active;

        u_int8_t        ahslen;
        u_int8_t        datalen[3];

        u_int32_t       isid_base;
        u_int16_t       isid_qual;
        u_int16_t       tsih;

        u_int32_t       itt;

        u_int8_t        _reserved1[4];

        u_int32_t       statsn;

        u_int32_t       expcmdsn;

        u_int32_t       maxcmdsn;

        u_int8_t        status_class;
        u_int8_t        status_detail;

        u_int8_t        _reserved2[10];
} __packed;

struct iscsi_pdu_logout_request {
        u_int8_t        opcode;
        u_int8_t        flags;
        u_int8_t        _reserved1[2];

        u_int8_t        ahslen;
        u_int8_t        datalen[3];

        u_int8_t        _reserved2[8];

        u_int32_t       itt;

        u_int16_t       cid;
        u_int8_t        _reserved3[2];

        u_int32_t       cmdsn;

        u_int32_t       expstatsn;

        u_int8_t        _reserved4[16];
} __packed;

#define ISCSI_LOGOUT_F          0x80
#define ISCSI_LOGOUT_CLOSE_SESS 0
#define ISCSI_LOGOUT_CLOSE_CONN 1
#define ISCSI_LOGOUT_RCVRY_CONN 2

#define ISCSI_LOGOUT_RESP_SUCCESS       0
#define ISCSI_LOGOUT_RESP_UNKN_CID      1
#define ISCSI_LOGOUT_RESP_NO_SUPPORT    2
#define ISCSI_LOGOUT_RESP_ERROR         3

struct iscsi_pdu_logout_response {
        u_int8_t        opcode;
        u_int8_t        flags;
        u_int8_t        response;
        u_int8_t        _reserved1;

        u_int8_t        ahslen;
        u_int8_t        datalen[3];

        u_int8_t        _reserved2[8];

        u_int32_t       itt;

        u_int8_t        _reserved3[4];

        u_int32_t       statsn;

        u_int32_t       expcmdsn;

        u_int32_t       maxcmdsn;

        u_int8_t        _reserved4[4];

        u_int16_t       time2wait;
        u_int16_t       time2retain;

        u_int8_t        _reserved5[4];
} __packed;

struct iscsi_pdu_snack_request {
        u_int8_t        opcode;
        u_int8_t        flags;
        u_int8_t        _reserved1[2];

        u_int8_t        ahslen;
        u_int8_t        datalen[3];

        u_int8_t        lun[8];

        u_int32_t       itt;

        u_int32_t       ttt;

        u_int8_t        _reserved2[4];

        u_int32_t       expstatsn;

        u_int8_t        _reserved3[8];

        u_int32_t       begrun;

        u_int32_t       runlength;
} __packed;

struct iscsi_pdu_reject {
        u_int8_t        opcode;
        u_int8_t        flags;
        u_int8_t        reason;
        u_int8_t        _reserved1;

        u_int8_t        ahslen;
        u_int8_t        datalen[3];

        u_int8_t        _reserved2[8];

        u_int32_t       ffffffff;

        u_int8_t        _reserved3[4];

        u_int32_t       statsn;

        u_int32_t       expcmdsn;

        u_int32_t       maxcmdsn;

        u_int32_t       datasn_r2tsn;

        u_int8_t        _reserved4[8];
} __packed;

struct iscsi_pdu_nop_out {
        u_int8_t        opcode;
        u_int8_t        flags;
        u_int8_t        _reserved1[2];

        u_int8_t        ahslen;
        u_int8_t        datalen[3];

        u_int8_t        lun[8];

        u_int32_t       itt;

        u_int32_t       ttt;

        u_int32_t       cmdsn;

        u_int32_t       expstatsn;

        u_int8_t        _reserved2[16];
} __packed;

struct iscsi_pdu_nop_in {
        u_int8_t        opcode;
        u_int8_t        flags;
        u_int8_t        _reserved1[2];

        u_int8_t        ahslen;
        u_int8_t        datalen[3];

        u_int8_t        lun[8];

        u_int32_t       itt;

        u_int32_t       ttt;

        u_int32_t       statsn;

        u_int32_t       expcmdsn;

        u_int32_t       maxcmdsn;

        u_int8_t        _reserved2[12];
} __packed;

#endif /* _SCSI_ISCSI_H */