1/*
2 * Copyright 2010, Andreas F��rber <andreas.faerber@web.de>
3 * All rights reserved. Distributed under the terms of the MIT License.
4 */
5#ifndef ISCSI_CMDS_H
6#define ISCSI_CMDS_H
7
8
9#include <ByteOrder.h>
10
11
12// TODO Add Little Endian support by introducing more macros
13#if __BYTE_ORDER != __BIG_ENDIAN
14#error Only Big Endian systems supported yet.
15#endif
16
17
18// iSCSI Basic Header Segment (BHS) (RFC 3720 10.2.1)
19
20#define ISCSI_BHS_BYTE0 			\
21	bool reserved : 1;				\
22	bool immediateDelivery : 1;		\
23	uint8 opcode : 6;
24
25// TODO This macro is LE-incompatible
26#define ISCSI_BHS_START 			\
27	ISCSI_BHS_BYTE0					\
28	bool final : 1;
29
30#define ISCSI_BHS_LENGTHS 			\
31	uint8 totalAHSLength; 			\
32	uint32 dataSegmentLength : 24;
33
34#define ISCSI_BHS_TASK_TAG 			\
35	uint32 initiatorTaskTag;
36
37#define ISCSI_BHS_TAGS				\
38	ISCSI_BHS_TASK_TAG				\
39	uint32 targetTransferTag;
40
41struct iscsi_basic_header_segment {
42	ISCSI_BHS_START
43	uint32 opcodeSpecific : 23;
44	ISCSI_BHS_LENGTHS
45	uint64 lun;
46	ISCSI_BHS_TASK_TAG
47	uint8 opcodeSpecific2[28];
48} _PACKED;
49
50// initiator opcodes
51#define ISCSI_OPCODE_NOP_OUT			0x00
52#define ISCSI_OPCODE_SCSI_COMMAND		0x01
53#define ISCSI_OPCODE_LOGIN_REQUEST		0x03
54#define ISCSI_OPCODE_TEXT_REQUEST		0x04
55#define ISCSI_OPCODE_LOGOUT_REQUEST		0x06
56// target opcodes
57#define ISCSI_OPCODE_NOP_IN				0x20
58#define ISCSI_OPCODE_SCSI_RESPONSE		0x21
59#define ISCSI_OPCODE_LOGIN_RESPONSE 	0x23
60#define ISCSI_OPCODE_TEXT_RESPONSE		0x24
61#define ISCSI_OPCODE_SCSI_DATA_IN		0x25
62#define ISCSI_OPCODE_LOGOUT_RESPONSE	0x26
63
64// SCSI Command (RFC 3720 10.3)
65struct iscsi_scsi_command {
66	iscsi_scsi_command()
67		:
68		reserved(0),
69		opcode(ISCSI_OPCODE_SCSI_COMMAND),
70		reserved2(0),
71		reserved3(0)
72	{
73	}
74	ISCSI_BHS_START
75	bool r : 1;
76	bool w : 1;
77	uint8 reserved2 : 2;
78	uint8 attr : 3;
79	uint16 reserved3;
80	ISCSI_BHS_LENGTHS
81	uint64 lun;
82	ISCSI_BHS_TASK_TAG
83	uint32 expectedDataTransferLength;
84	uint32 cmdSN;
85	uint32 expStatSN;
86	uint8 cdb[16];
87} _PACKED;
88
89// SCSI Response (RFC 3720 10.4)
90struct iscsi_scsi_response {
91	ISCSI_BHS_START
92	uint8 reserved2 : 2;
93	bool o : 1;
94	bool u : 1;
95	bool O : 1;
96	bool U : 1;
97	bool reserved3 : 1;
98	uint8 response;
99	uint8 status;
100	ISCSI_BHS_LENGTHS
101	uint32 reserved4[2];
102	ISCSI_BHS_TASK_TAG
103	uint32 snackTag;
104	uint32 statSN;
105	uint32 expCmdSN;
106	uint32 maxCmdSN;
107	uint32 expDataSN;
108	uint32 bidirectionalReadResidualCount;
109	uint32 residualCount;
110} _PACKED;
111
112// SCSI Data-In (RFC 3270 10.7)
113struct iscsi_scsi_data_in {
114	ISCSI_BHS_START
115	bool acknowledge : 1;
116	uint8 reserved2 : 3;
117	bool O : 1;
118	bool U : 1;
119	bool S : 1;
120	uint8 reserved3;
121	uint8 status;
122	ISCSI_BHS_LENGTHS
123	uint64 lun;
124	ISCSI_BHS_TAGS
125	uint32 statSN;
126	uint32 expCmdSN;
127	uint32 maxCmdSN;
128	uint32 dataSN;
129	uint32 bufferOffset;
130	uint32 residualCount;
131} _PACKED;
132
133// Text Request (RFC 3720 10.10)
134struct iscsi_text_request {
135	iscsi_text_request()
136		:
137		reserved(0),
138		opcode(ISCSI_OPCODE_TEXT_REQUEST),
139		reserved2(2)
140	{
141		reserved3[0] = 0;
142		reserved3[1] = 0;
143		reserved3[2] = 0;
144		reserved3[3] = 0;
145	}
146	ISCSI_BHS_START
147	bool c : 1;				// continue
148	uint32 reserved2 : 22;
149	ISCSI_BHS_LENGTHS
150	uint64 lun;
151	ISCSI_BHS_TAGS
152	uint32 cmdSN;
153	uint32 expStatSN;
154	uint32 reserved3[4];
155} _PACKED;
156
157// Text Response (RFC 3720 10.11)
158struct iscsi_text_response {
159	ISCSI_BHS_START
160	bool c : 1; // continue
161	uint32 reserved2 : 22;
162	ISCSI_BHS_LENGTHS
163	uint64 lun;
164	ISCSI_BHS_TAGS
165	uint32 statSN;
166	uint32 expCmdSN;
167	uint32 maxCmdSN;
168	uint32 reserved3[3];
169} _PACKED;
170
171struct iscsi_isid {
172	uint8 t : 2;
173	uint8 a : 6;
174	uint16 b;
175	uint8 c;
176	uint16 d;
177} _PACKED;
178
179// Login Request (RFC 3720 10.12)
180struct iscsi_login_request {
181	iscsi_login_request()
182		:
183		reserved(false),
184		immediateDelivery(1),
185		opcode(ISCSI_OPCODE_LOGIN_REQUEST),
186		reserved2(0),
187		reserved3(0)
188	{
189		memset(reserved4, 0, sizeof(reserved4));
190	}
191
192	ISCSI_BHS_BYTE0
193	bool transit : 1;
194	bool c : 1;					// continue
195	uint8 reserved2 : 2;
196	uint8 currentStage : 2;
197	uint8 nextStage : 2;
198	uint8 versionMax;
199	uint8 versionMin;
200	ISCSI_BHS_LENGTHS
201	iscsi_isid isid;
202	uint16 tsih;
203	ISCSI_BHS_TASK_TAG
204	uint16 cid;
205	uint16 reserved3;
206	uint32 cmdSN;
207	uint32 expStatSN;
208	uint32 reserved4[4];
209} _PACKED;
210
211#define ISCSI_SESSION_STAGE_SECURITY_NEGOTIATION			0
212#define ISCSI_SESSION_STAGE_LOGIN_OPERATIONAL_NEGOTIATION	1
213#define ISCSI_SESSION_STAGE_FULL_FEATURE_PHASE				3
214
215#define ISCSI_VERSION 0x00
216
217#define ISCSI_ISID_OUI		0
218#define ISCSI_ISID_EN		1
219#define ISCSI_ISID_RANDOM	2
220
221// Login Response (RFC 3720 10.13)
222struct iscsi_login_response {
223	ISCSI_BHS_BYTE0
224	bool transit : 1;
225	bool c : 1;					// continue
226	uint8 reserved2 : 2;
227	uint8 currentStage : 2;
228	uint8 nextStage : 2;
229	uint8 versionMax;
230	uint8 versionActive;
231	ISCSI_BHS_LENGTHS
232	iscsi_isid isid;
233	uint16 tsih;
234	ISCSI_BHS_TASK_TAG
235	uint32 reserved3;
236	uint32 statSN;
237	uint32 expCmdSN;
238	uint32 maxCmdSN;
239	uint8 statusClass;
240	uint8 statusDetail;
241	uint16 reserved4;
242	uint32 reserved5[2];
243} _PACKED;
244
245// Logout Request (RFC 3720 10.14)
246struct iscsi_logout_request {
247	iscsi_logout_request()
248		:
249		reserved(0),
250		opcode(ISCSI_OPCODE_LOGOUT_REQUEST),
251		final(true),
252		reserved2(0),
253		reserved4(0)
254	{
255		reserved3[0] = 0;
256		reserved3[1] = 0;
257		reserved5[0] = 0;
258		reserved5[1] = 0;
259		reserved5[2] = 0;
260		reserved5[3] = 0;
261	}
262	ISCSI_BHS_START
263	uint8 reasonCode : 7;
264	uint16 reserved2;
265	ISCSI_BHS_LENGTHS
266	uint32 reserved3[2];
267	ISCSI_BHS_TASK_TAG
268	uint16 cid;
269	uint16 reserved4;
270	uint32 cmdSN;
271	uint32 expStatSN;
272	uint32 reserved5[4];
273} _PACKED;
274
275#define ISCSI_LOGOUT_REASON_CLOSE_SESSION		0
276#define ISCSI_LOGOUT_REASON_CLOSE_CONNECTION	1
277#define ISCSI_LOGOUT_REASON_REMOVE_CONNECTION	2
278
279// Logout Response (RFC 3720 10.15)
280struct iscsi_logout_response {
281	ISCSI_BHS_START
282	uint8 reserved2 : 7;
283	uint8 response;
284	uint8 reserved3;
285	ISCSI_BHS_LENGTHS
286	uint32 reserved4[2];
287	ISCSI_BHS_TASK_TAG
288	uint32 reserved5;
289	uint32 statSN;
290	uint32 expCmdSN;
291	uint32 maxCmdSN;
292	uint32 reserved6;
293	uint16 time2Wait;
294	uint16 time2Remain;
295	uint32 reserved7;
296} _PACKED;
297
298// NOP-Out (RFC 3270, 10.18)
299struct iscsi_nop_out {
300	iscsi_nop_out()
301		:
302		reserved(0),
303		opcode(ISCSI_OPCODE_NOP_OUT),
304		final(true),
305		reserved2(0)
306	{
307		reserved3[0] = 0;
308		reserved3[1] = 0;
309		reserved3[2] = 0;
310		reserved3[3] = 0;
311	}
312	ISCSI_BHS_START
313	uint32 reserved2 : 23;
314	ISCSI_BHS_LENGTHS
315	uint64 lun;
316	ISCSI_BHS_TAGS
317	uint32 cmdSN;
318	uint32 expStatSN;
319	uint32 reserved3[4];
320} _PACKED;
321
322// NOP-In (RFC 3270, 10.19)
323struct iscsi_nop_in {
324	ISCSI_BHS_START
325	uint32 reserved2 : 23;
326	ISCSI_BHS_LENGTHS
327	uint64 lun;
328	ISCSI_BHS_TAGS
329	uint32 statSN;
330	uint32 expCmdSN;
331	uint32 maxCmdSN;
332	uint32 reserved3[3];
333} _PACKED;
334
335
336#endif
337