12 #include <gpxe/async.h>
13 #include <gpxe/scsi.h>
14 #include <gpxe/chap.h>
16 /** Default iSCSI port */
17 #define ISCSI_PORT 3260
20 * iSCSI segment lengths
22 * iSCSI uses an icky structure with one one-byte field (a dword
23 * count) and one three-byte field (a byte count). This structure,
24 * and the accompanying macros, relieve some of the pain.
26 union iscsi_segment_lengths {
28 /** The AHS length (measured in dwords) */
30 /** The data length (measured in bytes), in network
35 /** Ths data length (measured in bytes), in network byte
36 * order, with ahs_len as the first byte.
38 uint32_t ahs_and_data_len;
41 /** The length of the additional header segment, in dwords */
42 #define ISCSI_AHS_LEN( segment_lengths ) \
43 ( (segment_lengths).bytes.ahs_len )
45 /** The length of the data segment, in bytes, excluding any padding */
46 #define ISCSI_DATA_LEN( segment_lengths ) \
47 ( ntohl ( (segment_lengths).ahs_and_data_len ) & 0xffffff )
49 /** The padding of the data segment, in bytes */
50 #define ISCSI_DATA_PAD_LEN( segment_lengths ) \
51 ( ( 0 - (segment_lengths).bytes.data_len[2] ) & 0x03 )
53 /** Set additional header and data segment lengths */
54 #define ISCSI_SET_LENGTHS( segment_lengths, ahs_len, data_len ) do { \
55 (segment_lengths).ahs_and_data_len = \
56 htonl ( data_len | ( ahs_len << 24 ) ); \
60 * iSCSI basic header segment common fields
63 struct iscsi_bhs_common {
68 /** Fields specific to the PDU type */
70 /** Segment lengths */
71 union iscsi_segment_lengths lengths;
72 /** Fields specific to the PDU type */
74 /** Initiator Task Tag */
76 /** Fields specific to the PDU type */
81 #define ISCSI_OPCODE_MASK 0x3f
83 /** Immediate delivery */
84 #define ISCSI_FLAG_IMMEDIATE 0x40
86 /** Final PDU of a sequence */
87 #define ISCSI_FLAG_FINAL 0x80
90 * iSCSI basic header segment common request fields
93 struct iscsi_bhs_common_response {
98 /** Fields specific to the PDU type */
100 /** Segment lengths */
101 union iscsi_segment_lengths lengths;
102 /** Fields specific to the PDU type */
104 /** Initiator Task Tag */
106 /** Fields specific to the PDU type */
108 /** Status sequence number */
110 /** Expected command sequence number */
112 /** Fields specific to the PDU type */
117 * iSCSI login request basic header segment
120 struct iscsi_bhs_login_request {
125 /** Maximum supported version number */
127 /** Minimum supported version number */
129 /** Segment lengths */
130 union iscsi_segment_lengths lengths;
131 /** Initiator session ID (IANA format) enterprise number and flags */
132 uint32_t isid_iana_en;
133 /** Initiator session ID (IANA format) qualifier */
134 uint16_t isid_iana_qual;
135 /** Target session identifying handle */
137 /** Initiator Task Tag */
143 /** Command sequence number */
145 /** Expected status sequence number */
148 uint8_t reserved_b[16];
151 /** Login request opcode */
152 #define ISCSI_OPCODE_LOGIN_REQUEST 0x03
154 /** Willingness to transition to next stage */
155 #define ISCSI_LOGIN_FLAG_TRANSITION 0x80
157 /** Key=value pairs continued in subsequent request */
158 #define ISCSI_LOGIN_FLAG_CONTINUE 0x40
160 /* Current stage values and mask */
161 #define ISCSI_LOGIN_CSG_MASK 0x0c
162 #define ISCSI_LOGIN_CSG_SECURITY_NEGOTIATION 0x00
163 #define ISCSI_LOGIN_CSG_OPERATIONAL_NEGOTIATION 0x04
164 #define ISCSI_LOGIN_CSG_FULL_FEATURE_PHASE 0x0c
166 /* Next stage values and mask */
167 #define ISCSI_LOGIN_NSG_MASK 0x03
168 #define ISCSI_LOGIN_NSG_SECURITY_NEGOTIATION 0x00
169 #define ISCSI_LOGIN_NSG_OPERATIONAL_NEGOTIATION 0x01
170 #define ISCSI_LOGIN_NSG_FULL_FEATURE_PHASE 0x03
172 /** ISID IANA format marker */
173 #define ISCSI_ISID_IANA 0x40000000
175 /** Fen Systems Ltd. IANA enterprise number
177 * Permission is hereby granted to use Fen Systems Ltd.'s IANA
178 * enterprise number with this iSCSI implementation.
180 #define IANA_EN_FEN_SYSTEMS 10019
183 * iSCSI login response basic header segment
186 struct iscsi_bhs_login_response {
191 /** Maximum supported version number */
193 /** Minimum supported version number */
195 /** Segment lengths */
196 union iscsi_segment_lengths lengths;
197 /** Initiator session ID (IANA format) enterprise number and flags */
198 uint32_t isid_iana_en;
199 /** Initiator session ID (IANA format) qualifier */
200 uint16_t isid_iana_qual;
201 /** Target session identifying handle */
203 /** Initiator Task Tag */
207 /** Status sequence number */
209 /** Expected command sequence number */
211 /** Maximum command sequence number */
214 uint8_t status_class;
216 uint8_t status_detail;
218 uint8_t reserved_b[10];
221 /** Login response opcode */
222 #define ISCSI_OPCODE_LOGIN_RESPONSE 0x23
225 * iSCSI SCSI command basic header segment
228 struct iscsi_bhs_scsi_command {
235 /** Segment lengths */
236 union iscsi_segment_lengths lengths;
237 /** SCSI Logical Unit Number */
239 /** Initiator Task Tag */
241 /** Expected data transfer length */
243 /** Command sequence number */
245 /** Expected status sequence number */
247 /** SCSI Command Descriptor Block (CDB) */
251 /** SCSI command opcode */
252 #define ISCSI_OPCODE_SCSI_COMMAND 0x01
254 /** Command will read data */
255 #define ISCSI_COMMAND_FLAG_READ 0x40
257 /** Command will write data */
258 #define ISCSI_COMMAND_FLAG_WRITE 0x20
260 /* Task attributes */
261 #define ISCSI_COMMAND_ATTR_UNTAGGED 0x00
262 #define ISCSI_COMMAND_ATTR_SIMPLE 0x01
263 #define ISCSI_COMMAND_ATTR_ORDERED 0x02
264 #define ISCSI_COMMAND_ATTR_HEAD_OF_QUEUE 0x03
265 #define ISCSI_COMMAND_ATTR_ACA 0x04
268 * iSCSI SCSI response basic header segment
271 struct iscsi_bhs_scsi_response {
278 /** SCSI status code */
280 /** Segment lengths */
281 union iscsi_segment_lengths lengths;
283 uint8_t reserved_a[8];
284 /** Initiator Task Tag */
288 /** Status sequence number */
290 /** Expected command sequence number */
292 /** Maximum command sequence number */
294 /** Expected data sequence number */
297 uint8_t reserved_b[8];
300 /** SCSI response opcode */
301 #define ISCSI_OPCODE_SCSI_RESPONSE 0x21
303 /** SCSI command completed at target */
304 #define ISCSI_RESPONSE_COMMAND_COMPLETE 0x00
306 /** SCSI target failure */
307 #define ISCSI_RESPONSE_TARGET_FAILURE 0x01
309 /** SCSI sense response code offset
311 * The SCSI response may contain unsolicited sense data in the data
312 * segment. If it does, this is the offset to the sense response code
313 * byte, which is the only byte we care about.
315 #define ISCSI_SENSE_RESPONSE_CODE_OFFSET 2
318 * iSCSI data-in basic header segment
321 struct iscsi_bhs_data_in {
328 /** SCSI status code */
330 /** Segment lengths */
331 union iscsi_segment_lengths lengths;
332 /** Logical Unit Number */
334 /** Initiator Task Tag */
336 /** Target Transfer Tag */
338 /** Status sequence number */
340 /** Expected command sequence number */
342 /** Maximum command sequence number */
344 /** Data sequence number */
348 /** Residual count */
349 uint32_t residual_count;
352 /** Data-in opcode */
353 #define ISCSI_OPCODE_DATA_IN 0x25
355 /** Data requires acknowledgement */
356 #define ISCSI_DATA_FLAG_ACKNOWLEDGE 0x40
358 /** Data overflow occurred */
359 #define ISCSI_DATA_FLAG_OVERFLOW 0x04
361 /** Data underflow occurred */
362 #define ISCSI_DATA_FLAG_UNDERFLOW 0x02
364 /** SCSI status code and overflow/underflow flags are valid */
365 #define ISCSI_DATA_FLAG_STATUS 0x01
368 * iSCSI data-out basic header segment
371 struct iscsi_bhs_data_out {
378 /** Segment lengths */
379 union iscsi_segment_lengths lengths;
380 /** Logical Unit Number */
382 /** Initiator Task Tag */
384 /** Target Transfer Tag */
388 /** Expected status sequence number */
392 /** Data sequence number */
400 /** Data-out opcode */
401 #define ISCSI_OPCODE_DATA_OUT 0x05
404 * iSCSI request to transfer basic header segment
407 struct iscsi_bhs_r2t {
414 /** Segment lengths */
415 union iscsi_segment_lengths lengths;
416 /** Logical Unit Number */
418 /** Initiator Task Tag */
420 /** Target Transfer Tag */
422 /** Status sequence number */
424 /** Expected command sequence number */
426 /** Maximum command sequence number */
428 /** R2T sequence number */
432 /** Desired data transfer length */
437 #define ISCSI_OPCODE_R2T 0x31
440 * An iSCSI basic header segment
443 struct iscsi_bhs_common common;
444 struct iscsi_bhs_common_response common_response;
445 struct iscsi_bhs_login_request login_request;
446 struct iscsi_bhs_login_response login_response;
447 struct iscsi_bhs_scsi_command scsi_command;
448 struct iscsi_bhs_scsi_response scsi_response;
449 struct iscsi_bhs_data_in data_in;
450 struct iscsi_bhs_data_out data_out;
451 struct iscsi_bhs_r2t r2t;
452 unsigned char bytes[ sizeof ( struct iscsi_bhs_common ) ];
455 /** State of an iSCSI TX engine */
456 enum iscsi_tx_state {
457 /** Nothing to send */
459 /** Sending the basic header segment */
461 /** Sending the additional header segment */
463 /** Sending the data segment */
465 /** Sending the data segment padding */
466 ISCSI_TX_DATA_PADDING,
469 /** State of an iSCSI RX engine */
470 enum iscsi_rx_state {
471 /** Receiving the basic header segment */
473 /** Receiving the additional header segment */
475 /** Receiving the data segment */
477 /** Receiving the data segment padding */
478 ISCSI_RX_DATA_PADDING,
481 /** An iSCSI session */
482 struct iscsi_session {
483 /** TCP connection for this session */
484 struct tcp_connection tcp;
487 * This is the bitwise-OR of zero or more ISCSI_STATUS_XXX
491 /** Asynchronous operation for the current iSCSI operation */
492 struct async_operation aop;
495 * Number of times that the connection has been retried.
496 * Reset upon a successful connection.
501 const char *initiator;
504 /** Logical Unit Number (LUN) */
508 const char *username;
510 const char *password;
511 /** CHAP challenge/response */
512 struct chap_challenge chap;
514 /** Target session identifying handle
516 * This is assigned by the target when we first log in, and
517 * must be reused on subsequent login attempts.
520 /** Initiator task tag
522 * This is the tag of the current command. It is incremented
523 * whenever a new command is started.
526 /** Target transfer tag
528 * This is the tag attached to a sequence of data-out PDUs in
529 * response to an R2T.
535 * This is the offset for an in-progress sequence of data-out
536 * PDUs in response to an R2T.
538 uint32_t transfer_offset;
542 * This is the length for an in-progress sequence of data-out
543 * PDUs in response to an R2T.
545 uint32_t transfer_len;
546 /** Command sequence number
548 * This is the sequence number of the current command, used to
549 * fill out the CmdSN field in iSCSI request PDUs. It is
550 * updated with the value of the ExpCmdSN field whenever we
551 * receive an iSCSI response PDU containing such a field.
554 /** Status sequence number
556 * This is the most recent status sequence number present in
557 * the StatSN field of an iSCSI response PDU containing such a
558 * field. Whenever we send an iSCSI request PDU, we fill out
559 * the ExpStatSN field with this value plus one.
563 /** Basic header segment for current TX PDU */
564 union iscsi_bhs tx_bhs;
565 /** State of the TX engine */
566 enum iscsi_tx_state tx_state;
567 /** Byte offset within the current TX state */
569 /** Length of the current TX state */
572 /** Basic header segment for current RX PDU */
573 union iscsi_bhs rx_bhs;
574 /** State of the RX engine */
575 enum iscsi_rx_state rx_state;
576 /** Byte offset within the current RX state */
578 /** Length of the current RX state */
580 /** Buffer for received data (not always used) */
583 /** Current SCSI command
585 * Set to NULL when command is complete.
587 struct scsi_command *command;
590 /** iSCSI session is currently in the security negotiation phase */
591 #define ISCSI_STATUS_SECURITY_NEGOTIATION_PHASE \
592 ( ISCSI_LOGIN_CSG_SECURITY_NEGOTIATION | \
593 ISCSI_LOGIN_NSG_OPERATIONAL_NEGOTIATION )
595 /** iSCSI session is currently in the operational parameter
598 #define ISCSI_STATUS_OPERATIONAL_NEGOTIATION_PHASE \
599 ( ISCSI_LOGIN_CSG_OPERATIONAL_NEGOTIATION | \
600 ISCSI_LOGIN_NSG_FULL_FEATURE_PHASE )
602 /** iSCSI session is currently in the full feature phase */
603 #define ISCSI_STATUS_FULL_FEATURE_PHASE ISCSI_LOGIN_CSG_FULL_FEATURE_PHASE
605 /** Mask for all iSCSI session phases */
606 #define ISCSI_STATUS_PHASE_MASK ( ISCSI_LOGIN_CSG_MASK | ISCSI_LOGIN_NSG_MASK )
608 /** iSCSI session needs to send the initial security negotiation strings */
609 #define ISCSI_STATUS_STRINGS_SECURITY 0x0100
611 /** iSCSI session needs to send the CHAP_A string */
612 #define ISCSI_STATUS_STRINGS_CHAP_ALGORITHM 0x0200
614 /** iSCSI session needs to send the CHAP response */
615 #define ISCSI_STATUS_STRINGS_CHAP_RESPONSE 0x0400
617 /** iSCSI session needs to send the operational negotiation strings */
618 #define ISCSI_STATUS_STRINGS_OPERATIONAL 0x0800
620 /** Mask for all iSCSI "needs to send" flags */
621 #define ISCSI_STATUS_STRINGS_MASK 0xff00
623 /** Maximum number of retries at connecting */
624 #define ISCSI_MAX_RETRIES 2
626 extern struct async_operation * iscsi_issue ( struct iscsi_session *iscsi,
627 struct scsi_command *command );
629 /** An iSCSI device */
630 struct iscsi_device {
631 /** SCSI device interface */
632 struct scsi_device scsi;
633 /** iSCSI protocol instance */
634 struct iscsi_session iscsi;
637 extern int init_iscsidev ( struct iscsi_device *iscsidev );
639 #endif /* _GPXE_ISCSI_H */