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