All uses iscsi_state were removed some time ago; removing the
[people/xl0/gpxe.git] / src / include / gpxe / iscsi.h
1 #ifndef _GPXE_ISCSI_H
2 #define _GPXE_ISCSI_H
3
4 /** @file
5  *
6  * iSCSI protocol
7  *
8  */
9
10 #include <stdint.h>
11 #include <gpxe/tcp.h>
12 #include <gpxe/scsi.h>
13
14 /**
15  * iSCSI segment lengths
16  *
17  * iSCSI uses an icky structure with one one-byte field (a dword
18  * count) and one three-byte field (a byte count).  This structure,
19  * and the accompanying macros, relieve some of the pain.
20  */
21 union iscsi_segment_lengths {
22         struct {
23                 /** The AHS length (measured in dwords) */
24                 uint8_t ahs_len;
25                 /** The data length (measured in bytes), in network
26                  * byte order
27                  */
28                 uint8_t data_len[3];
29         } bytes;
30         /** Ths data length (measured in bytes), in network byte
31          * order, with ahs_len as the first byte.
32          */
33         uint32_t ahs_and_data_len;
34 };
35
36 /** The length of the additional header segment, in dwords */
37 #define ISCSI_AHS_LEN( segment_lengths ) \
38         ( (segment_lengths).bytes.ahs_len )
39
40 /** The length of the data segment, in bytes, excluding any padding */
41 #define ISCSI_DATA_LEN( segment_lengths ) \
42         ( ntohl ( (segment_lengths).ahs_and_data_len ) & 0xffffff )
43
44 /** The padding of the data segment, in bytes */
45 #define ISCSI_DATA_PAD_LEN( segment_lengths ) \
46         ( ( 0 - (segment_lengths).bytes.data_len[2] ) & 0x03 )
47
48 /** Set additional header and data segment lengths */
49 #define ISCSI_SET_LENGTHS( segment_lengths, ahs_len, data_len ) do {    \
50         (segment_lengths).ahs_and_data_len =                            \
51                 htonl ( data_len | ( ahs_len << 24 ) );                 \
52         } while ( 0 )
53
54 /**
55  * iSCSI basic header segment common fields
56  *
57  */
58 struct iscsi_bhs_common {
59         /** Opcode */
60         uint8_t opcode;
61         /** Flags */
62         uint8_t flags;
63         /** Fields specific to the PDU type */
64         uint8_t other_a[2];
65         /** Segment lengths */
66         union iscsi_segment_lengths lengths;
67         /** Fields specific to the PDU type */
68         uint8_t other_b[8];
69         /** Initiator Task Tag */
70         uint32_t itt;
71         /** Fields specific to the PDU type */
72         uint8_t other_c[28];
73 };
74
75 /** Opcode mask */
76 #define ISCSI_OPCODE_MASK 0x3f
77
78 /** Immediate delivery */
79 #define ISCSI_FLAG_IMMEDIATE 0x40
80
81 /** Final PDU of a sequence */
82 #define ISCSI_FLAG_FINAL 0x80
83
84 /**
85  * iSCSI basic header segment common request fields
86  *
87  */
88 struct iscsi_bhs_common_request {
89         /** Opcode */
90         uint8_t opcode;
91         /** Flags */
92         uint8_t flags;
93         /** Fields specific to the PDU type */
94         uint8_t other_a[2];
95         /** Segment lengths */
96         union iscsi_segment_lengths lengths;
97         /** Fields specific to the PDU type */
98         uint8_t other_b[8];
99         /** Initiator Task Tag */
100         uint32_t itt;
101         /** Fields specific to the PDU type */
102         uint8_t other_c[4];
103         /** Command sequence number */
104         uint32_t cmdsn;
105         /** Expected status sequence number */
106         uint32_t expstatsn;
107         /** Fields specific to the PDU type */
108         uint8_t other_d[16];
109 };
110
111 /**
112  * iSCSI basic header segment common request fields
113  *
114  */
115 struct iscsi_bhs_common_response {
116         /** Opcode */
117         uint8_t opcode;
118         /** Flags */
119         uint8_t flags;
120         /** Fields specific to the PDU type */
121         uint8_t other_a[2];
122         /** Segment lengths */
123         union iscsi_segment_lengths lengths;
124         /** Fields specific to the PDU type */
125         uint8_t other_b[8];
126         /** Initiator Task Tag */
127         uint32_t itt;
128         /** Fields specific to the PDU type */
129         uint8_t other_c[4];
130         /** Status sequence number */
131         uint32_t statsn;
132         /** Expected command sequence number */
133         uint32_t expcmdsn;
134         /** Fields specific to the PDU type */
135         uint8_t other_d[16];
136 };
137
138 /**
139  * iSCSI login request basic header segment
140  *
141  */
142 struct iscsi_bhs_login_request {
143         /** Opcode */
144         uint8_t opcode;
145         /** Flags */
146         uint8_t flags;
147         /** Maximum supported version number */
148         uint8_t version_max;
149         /** Minimum supported version number */
150         uint8_t version_min;
151         /** Segment lengths */
152         union iscsi_segment_lengths lengths;
153         /** Initiator session ID (IANA format) enterprise number and flags */
154         uint32_t isid_iana_en;
155         /** Initiator session ID (IANA format) qualifier */
156         uint16_t isid_iana_qual;
157         /** Target session identifying handle */
158         uint16_t tsih;
159         /** Initiator Task Tag */
160         uint32_t itt;
161         /** Connection ID */
162         uint16_t cid;
163         /** Reserved */
164         uint16_t reserved_a;
165         /** Command sequence number */
166         uint32_t cmdsn;
167         /** Expected status sequence number */
168         uint32_t expstatsn;
169         /** Reserved */
170         uint8_t reserved_b[16];
171 };
172
173 /** Login request opcode */
174 #define ISCSI_OPCODE_LOGIN_REQUEST 0x03
175
176 /** Willingness to transition to next stage */
177 #define ISCSI_LOGIN_FLAG_TRANSITION 0x80
178
179 /** Key=value pairs continued in subsequent request */
180 #define ISCSI_LOGIN_FLAG_CONTINUE 0x40
181
182 /* Current stage values and mask */
183 #define ISCSI_LOGIN_CSG_MASK 0x0c
184 #define ISCSI_LOGIN_CSG_SECURITY_NEGOTIATION 0x00
185 #define ISCSI_LOGIN_CSG_OPERATIONAL_NEGOTIATION 0x04
186 #define ISCSI_LOGIN_CSG_FULL_FEATURE_PHASE 0x0c
187
188 /* Next stage values and mask */
189 #define ISCSI_LOGIN_NSG_MASK 0x03
190 #define ISCSI_LOGIN_NSG_SECURITY_NEGOTIATION 0x00
191 #define ISCSI_LOGIN_NSG_OPERATIONAL_NEGOTIATION 0x01
192 #define ISCSI_LOGIN_NSG_FULL_FEATURE_PHASE 0x03
193
194 /** ISID IANA format marker */
195 #define ISCSI_ISID_IANA 0x40000000
196
197 /** Fen Systems Ltd. IANA enterprise number
198  *
199  * Permission is hereby granted to use Fen Systems Ltd.'s IANA
200  * enterprise number with this iSCSI implementation.
201  */
202 #define IANA_EN_FEN_SYSTEMS 10019
203
204 /**
205  * iSCSI login response basic header segment
206  *
207  */
208 struct iscsi_bhs_login_response {
209         /** Opcode */
210         uint8_t opcode;
211         /** Flags */
212         uint8_t flags;
213         /** Maximum supported version number */
214         uint8_t version_max;
215         /** Minimum supported version number */
216         uint8_t version_min;
217         /** Segment lengths */
218         union iscsi_segment_lengths lengths;
219         /** Initiator session ID (IANA format) enterprise number and flags */
220         uint32_t isid_iana_en;
221         /** Initiator session ID (IANA format) qualifier */
222         uint16_t isid_iana_qual;
223         /** Target session identifying handle */
224         uint16_t tsih;
225         /** Initiator Task Tag */
226         uint32_t itt;
227         /** Reserved */
228         uint32_t reserved_a;
229         /** Status sequence number */
230         uint32_t statsn;
231         /** Expected command sequence number */
232         uint32_t expcmdsn;
233         /** Maximum command sequence number */
234         uint32_t maxcmdsn;
235         /** Status class */
236         uint8_t status_class;
237         /** Status detail */
238         uint8_t status_detail;
239         /** Reserved */
240         uint8_t reserved_b[10];
241 };
242
243 /** Login response opcode */
244 #define ISCSI_OPCODE_LOGIN_RESPONSE 0x23
245
246 /**
247  * iSCSI SCSI command basic header segment
248  *
249  */
250 struct iscsi_bhs_scsi_command {
251         /** Opcode */
252         uint8_t opcode;
253         /** Flags */
254         uint8_t flags;
255         /** Reserved */
256         uint16_t reserved_a;
257         /** Segment lengths */
258         union iscsi_segment_lengths lengths;
259         /** SCSI Logical Unit Number */
260         uint64_t lun;
261         /** Initiator Task Tag */
262         uint32_t itt;
263         /** Expected data transfer length */
264         uint32_t exp_len;
265         /** Command sequence number */
266         uint32_t cmdsn;
267         /** Expected status sequence number */
268         uint32_t expstatsn;
269         /** SCSI Command Descriptor Block (CDB) */
270         union scsi_cdb cdb;
271 };
272
273 /** SCSI command opcode */
274 #define ISCSI_OPCODE_SCSI_COMMAND 0x01
275
276 /** Command will read data */
277 #define ISCSI_COMMAND_FLAG_READ 0x40
278
279 /** Command will write data */
280 #define ISCSI_COMMAND_FLAG_WRITE 0x20
281
282 /* Task attributes */
283 #define ISCSI_COMMAND_ATTR_UNTAGGED 0x00
284 #define ISCSI_COMMAND_ATTR_SIMPLE 0x01
285 #define ISCSI_COMMAND_ATTR_ORDERED 0x02
286 #define ISCSI_COMMAND_ATTR_HEAD_OF_QUEUE 0x03
287 #define ISCSI_COMMAND_ATTR_ACA 0x04
288
289 /**
290  * iSCSI SCSI response basic header segment
291  *
292  */
293 struct iscsi_bhs_scsi_response {
294         /** Opcode */
295         uint8_t opcode;
296         /** Flags */
297         uint8_t flags;
298         /** Response code */
299         uint8_t response;
300         /** SCSI status code */
301         uint8_t status;
302         /** Segment lengths */
303         union iscsi_segment_lengths lengths;
304         /** Reserved */
305         uint8_t reserved_a[8];
306         /** Initiator Task Tag */
307         uint32_t itt;
308         /** SNACK tag */
309         uint32_t snack;
310         /** Status sequence number */
311         uint32_t statsn;
312         /** Expected command sequence number */
313         uint32_t expcmdsn;
314         /** Maximum command sequence number */
315         uint32_t maxcmdsn;
316         /** Expected data sequence number */
317         uint32_t expdatasn;
318         /** Reserved */
319         uint8_t reserved_b[8];
320 };
321
322 /** SCSI response opcode */
323 #define ISCSI_OPCODE_SCSI_RESPONSE 0x21
324
325 /** SCSI command completed at target */
326 #define ISCSI_RESPONSE_COMMAND_COMPLETE 0x00
327
328 /** SCSI target failure */
329 #define ISCSI_RESPONSE_TARGET_FAILURE 0x01
330
331 /**
332  * iSCSI data in basic header segment
333  *
334  */
335 struct iscsi_bhs_data_in {
336         /** Opcode */
337         uint8_t opcode;
338         /** Flags */
339         uint8_t flags;
340         /** Reserved */
341         uint8_t reserved_a;
342         /** SCSI status code */
343         uint8_t status;
344         /** Segment lengths */
345         union iscsi_segment_lengths lengths;
346         /** Logical Unit Number */
347         uint64_t lun;
348         /** Initiator Task Tag */
349         uint32_t itt;
350         /** Target Transfer Tag */
351         uint32_t ttt;
352         /** Status sequence number */
353         uint32_t statsn;
354         /** Expected command sequence number */
355         uint32_t expcmdsn;
356         /** Maximum command sequence number */
357         uint32_t maxcmdsn;
358         /** Data sequence number */
359         uint32_t datasn;
360         /** Buffer offset */
361         uint32_t offset;
362         /** Residual count */
363         uint32_t residual_count;
364 };
365
366 /** Data in opcode */
367 #define ISCSI_OPCODE_DATA_IN 0x25
368
369 /** Data requires acknowledgement */
370 #define ISCSI_DATA_FLAG_ACKNOWLEDGE 0x40
371
372 /** Data overflow occurred */
373 #define ISCSI_DATA_FLAG_OVERFLOW 0x04
374
375 /** Data underflow occurred */
376 #define ISCSI_DATA_FLAG_UNDERFLOW 0x02
377
378 /** SCSI status code and verflow/underflow flags are valid */
379 #define ISCSI_DATA_FLAG_STATUS 0x01
380
381 /**
382  * An iSCSI basic header segment
383  */
384 union iscsi_bhs {
385         struct iscsi_bhs_common common;
386         struct iscsi_bhs_common_request common_request;
387         struct iscsi_bhs_common_response common_response;
388         struct iscsi_bhs_login_request login_request;
389         struct iscsi_bhs_login_response login_response;
390         struct iscsi_bhs_scsi_command scsi_command;
391         struct iscsi_bhs_scsi_response scsi_response;
392         struct iscsi_bhs_data_in data_in;
393         unsigned char bytes[ sizeof ( struct iscsi_bhs_common ) ];
394 };
395
396 /** State of an iSCSI TX engine */
397 enum iscsi_tx_state {
398         /** Nothing to send */
399         ISCSI_TX_IDLE = 0,
400         /** Sending the basic header segment */
401         ISCSI_TX_BHS,
402         /** Sending the additional header segment */
403         ISCSI_TX_AHS,
404         /** Sending the data segment */
405         ISCSI_TX_DATA,
406         /** Sending the data segment padding */
407         ISCSI_TX_DATA_PADDING,
408 };
409
410 /** State of an iSCSI RX engine */
411 enum iscsi_rx_state {
412         /** Receiving the basic header segment */
413         ISCSI_RX_BHS = 0,
414         /** Receiving the additional header segment */
415         ISCSI_RX_AHS,
416         /** Receiving the data segment */
417         ISCSI_RX_DATA,
418         /** Receiving the data segment padding */
419         ISCSI_RX_DATA_PADDING,
420 };
421
422 /** An iSCSI session */
423 struct iscsi_session {
424         /** TCP connection for this session */
425         struct tcp_connection tcp;
426         /** Session status
427          *
428          * This is the bitwise-OR of zero or more ISCSI_STATUS_XXX
429          * constants.
430          */
431         int status;
432         /** Retry count
433          *
434          * Number of times that the connection has been retried.
435          * Reset upon a successful connection.
436          */
437         int retry_count;
438
439         /** Initiator IQN */
440         const char *initiator;
441         /** Target IQN */
442         const char *target;
443         /** Logical Unit Number (LUN) */
444         uint64_t lun;
445
446         /** Target session identifying handle
447          *
448          * This is assigned by the target when we first log in, and
449          * must be reused on subsequent login attempts.
450          */
451         uint16_t tsih;
452         /** Initiator task tag
453          *
454          * This is the tag of the current command.  It is incremented
455          * whenever a final response PDU is received.
456          */
457         uint32_t itt;
458         /** Command sequence number
459          *
460          * This is the sequence number of the current command, used to
461          * fill out the CmdSN field in iSCSI request PDUs.  It is
462          * updated with the value of the ExpCmdSN field whenever we
463          * receive an iSCSI response PDU containing such a field.
464          */
465         uint32_t cmdsn;
466         /** Status sequence number
467          *
468          * This is the most recent status sequence number present in
469          * the StatSN field of an iSCSI response PDU containing such a
470          * field.  Whenever we send an iSCSI request PDU, we fill out
471          * the ExpStatSN field with this value plus one.
472          */
473         uint32_t statsn;
474         
475         /** Basic header segment for current TX PDU */
476         union iscsi_bhs tx_bhs;
477         /** State of the TX engine */
478         enum iscsi_tx_state tx_state;
479         /** Byte offset within the current TX state */
480         size_t tx_offset;
481
482         /** Basic header segment for current RX PDU */
483         union iscsi_bhs rx_bhs;
484         /** State of the RX engine */
485         enum iscsi_rx_state rx_state;
486         /** Byte offset within the current RX state */
487         size_t rx_offset;
488
489         /** Current SCSI command
490          *
491          * Set to NULL when command is complete.
492          */
493         struct scsi_command *command;
494 };
495
496 /** Session is currently connected */
497 #define ISCSI_STATUS_CONNECTED 0x01
498
499 /** Session has completed */
500 #define ISCSI_STATUS_DONE 0x02
501
502 /** Session failed */
503 #define ISCSI_STATUS_ERR 0x04
504
505 /** Maximum number of retries at connecting */
506 #define ISCSI_MAX_RETRIES 2
507
508 extern int iscsi_issue ( struct iscsi_session *iscsi,
509                          struct scsi_command *command );
510
511 /** An iSCSI device */
512 struct iscsi_device {
513         /** SCSI device interface */
514         struct scsi_device scsi;
515         /** iSCSI protocol instance */
516         struct iscsi_session iscsi;
517 };
518
519 extern int init_iscsidev ( struct iscsi_device *iscsidev );
520
521 #endif /* _GPXE_ISCSI_H */