Browse Source

[fc] Add support for Fibre Channel devices

Add support for Fibre Channel ports, peers, and upper-layer protocols,
and for Fibre Channel extended link services.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
tags/v1.20.1
Michael Brown 14 years ago
parent
commit
508ff4d614
6 changed files with 3844 additions and 0 deletions
  1. 2
    0
      src/include/ipxe/errfile.h
  2. 439
    0
      src/include/ipxe/fc.h
  3. 452
    0
      src/include/ipxe/fcels.h
  4. 16
    0
      src/include/ipxe/xfer.h
  5. 1773
    0
      src/net/fc.c
  6. 1162
    0
      src/net/fcels.c

+ 2
- 0
src/include/ipxe/errfile.h View File

@@ -184,6 +184,8 @@ FILE_LICENCE ( GPL2_OR_LATER );
184 184
 #define ERRFILE_wpa_tkip		( ERRFILE_NET | 0x00280000 )
185 185
 #define ERRFILE_wpa_ccmp		( ERRFILE_NET | 0x00290000 )
186 186
 #define ERRFILE_eth_slow		( ERRFILE_NET | 0x002a0000 )
187
+#define ERRFILE_fc			( ERRFILE_NET | 0x002b0000 )
188
+#define ERRFILE_fcels			( ERRFILE_NET | 0x002c0000 )
187 189
 
188 190
 #define ERRFILE_image		      ( ERRFILE_IMAGE | 0x00000000 )
189 191
 #define ERRFILE_elf		      ( ERRFILE_IMAGE | 0x00010000 )

+ 439
- 0
src/include/ipxe/fc.h View File

@@ -0,0 +1,439 @@
1
+#ifndef _IPXE_FC_H
2
+#define _IPXE_FC_H
3
+
4
+/**
5
+ * @file
6
+ *
7
+ * Fibre Channel
8
+ *
9
+ */
10
+
11
+FILE_LICENCE ( GPL2_OR_LATER );
12
+
13
+#include <stdint.h>
14
+#include <ipxe/refcnt.h>
15
+#include <ipxe/list.h>
16
+#include <ipxe/tables.h>
17
+#include <ipxe/interface.h>
18
+#include <ipxe/retry.h>
19
+
20
+/******************************************************************************
21
+ *
22
+ * Fibre Channel Names and identifiers
23
+ *
24
+ ******************************************************************************
25
+ */
26
+
27
+/** A Fibre Channel name */
28
+struct fc_name {
29
+	uint8_t bytes[8];
30
+} __attribute__ (( packed ));
31
+
32
+/** Length of Fibre Channel name text */
33
+#define FC_NAME_STRLEN 23 /* "xx:xx:xx:xx:xx:xx:xx:xx" */
34
+
35
+/** A Fibre Channel port identifier */
36
+struct fc_port_id {
37
+	uint8_t bytes[3];
38
+} __attribute__ (( packed ));
39
+
40
+/** Length of Fibre Channel port identifier next */
41
+#define FC_PORT_ID_STRLEN 9 /* "xx.xx.xx" */
42
+
43
+extern struct fc_port_id fc_empty_port_id;
44
+extern struct fc_port_id fc_f_port_id;
45
+extern struct fc_port_id fc_ptp_low_port_id;
46
+extern struct fc_port_id fc_ptp_high_port_id;
47
+
48
+extern const char * fc_id_ntoa ( const struct fc_port_id *id );
49
+extern int fc_id_aton ( const char *id_text, struct fc_port_id *id );
50
+extern const char * fc_ntoa ( const struct fc_name *wwn );
51
+extern int fc_aton ( const char *wwn_text, struct fc_name *wwn );
52
+
53
+/******************************************************************************
54
+ *
55
+ * Fibre Channel link state
56
+ *
57
+ ******************************************************************************
58
+ */
59
+
60
+/** Delay between failed link-up attempts */
61
+#define FC_LINK_RETRY_DELAY ( 2 * TICKS_PER_SEC )
62
+
63
+/** A Fibre Channel link state nonitor */
64
+struct fc_link_state {
65
+	/** Retry timer */
66
+	struct retry_timer timer;
67
+	/** Link state */
68
+	int rc;
69
+	/** Examine link state
70
+	 *
71
+	 * @v link		Fibre Channel link state monitor
72
+	 */
73
+	void ( * examine ) ( struct fc_link_state *link );
74
+};
75
+
76
+/**
77
+ * Check Fibre Channel link state
78
+ *
79
+ * @v link		Fibre Channel link state monitor
80
+ * @ret link_up		Link is up
81
+ */
82
+static inline __attribute__ (( always_inline )) int
83
+fc_link_ok ( struct fc_link_state *link ) {
84
+	return ( link->rc == 0 );
85
+}
86
+
87
+/******************************************************************************
88
+ *
89
+ * Fibre Channel packet formats and exchanges
90
+ *
91
+ ******************************************************************************
92
+ */
93
+
94
+/** A Fibre Channel Frame Header */
95
+struct fc_frame_header {
96
+	/** Routing control
97
+	 *
98
+	 * This is the bitwise OR of one @c fc_r_ctl_routing value and
99
+	 * one @c fc_r_ctl_info value.
100
+	 */
101
+	uint8_t r_ctl;
102
+	/** Destination ID */
103
+	struct fc_port_id d_id;
104
+	/** Class-specific control / Priority */
105
+	uint8_t cs_ctl_prio;
106
+	/** Source ID */
107
+	struct fc_port_id s_id;
108
+	/** Data structure type */
109
+	uint8_t type;
110
+	/** Frame control - exchange and sequence */
111
+	uint8_t f_ctl_es;
112
+	/** Frame control - acknowledgements  */
113
+	uint8_t f_ctl_ack;
114
+	/** Frame control - miscellaneous */
115
+	uint8_t f_ctl_misc;
116
+	/** Sequence ID */
117
+	uint8_t seq_id;
118
+	/** Data field control */
119
+	uint8_t df_ctl;
120
+	/** Sequence count */
121
+	uint16_t seq_cnt;
122
+	/** Originator exchange ID */
123
+	uint16_t ox_id;
124
+	/** Responder exchange ID */
125
+	uint16_t rx_id;
126
+	/** Parameter
127
+	 *
128
+	 * Contains the relative offset when @c FC_F_CTL_MISC_REL_OFF
129
+	 * is set.
130
+	 */
131
+	uint32_t parameter;
132
+} __attribute__ (( packed ));
133
+
134
+/** Fibre Channel Routing Control Routing */
135
+enum fc_r_ctl_routing {
136
+	FC_R_CTL_DATA = 0x00,		/**< Device Data */
137
+	FC_R_CTL_ELS = 0x20,		/**< Extended Link Services */
138
+	FC_R_CTL_FC4_LINK = 0x30,	/**< FC-4 Link Data */
139
+	FC_R_CTL_VIDEO = 0x40,		/**< Video Data */
140
+	FC_R_CTL_EH = 0x50,		/**< Extended Headers */
141
+	FC_R_CTL_BLS = 0x80,		/**< Basic Link Services */
142
+	FC_R_CTL_LINK_CTRL = 0xc0,	/**< Link Control */
143
+	FC_R_CTL_EXT_ROUTE = 0xf0,	/**< Extended Routing */
144
+};
145
+
146
+/** Fibre Channel Routing Control Routing mask */
147
+#define FC_R_CTL_ROUTING_MASK 0xf0
148
+
149
+/** Fibre Channel Routing Control Information */
150
+enum fc_r_ctl_info {
151
+	FC_R_CTL_UNCAT = 0x00,		/**< Uncategorized */
152
+	FC_R_CTL_SOL_DATA = 0x01,	/**< Solicited Data */
153
+	FC_R_CTL_UNSOL_CTRL = 0x02,	/**< Unsolicited Control */
154
+	FC_R_CTL_SOL_CTRL = 0x03,	/**< Solicited Control */
155
+	FC_R_CTL_UNSOL_DATA = 0x04,	/**< Unsolicited Data */
156
+	FC_R_CTL_DATA_DESC = 0x05,	/**< Data Descriptor */
157
+	FC_R_CTL_UNSOL_CMD = 0x06,	/**< Unsolicited Command */
158
+	FC_R_CTL_CMD_STAT = 0x07,	/**< Command Status */
159
+};
160
+
161
+/** Fibre Channel Routing Control Information mask */
162
+#define FC_R_CTL_INFO_MASK 0x07
163
+
164
+/** Fibre Channel Data Structure Type */
165
+enum fc_type {
166
+	FC_TYPE_BLS = 0x00,		/**< Basic Link Service */
167
+	FC_TYPE_ELS = 0x01,		/**< Extended Link Service */
168
+	FC_TYPE_FCP = 0x08,		/**< Fibre Channel Protocol */
169
+};
170
+
171
+/** Fibre Channel Frame Control - Exchange and Sequence */
172
+enum fc_f_ctl_es {
173
+	FC_F_CTL_ES_RESPONDER = 0x80,	/**< Responder of Exchange */
174
+	FC_F_CTL_ES_RECIPIENT = 0x40,	/**< Sequence Recipient */
175
+	FC_F_CTL_ES_FIRST = 0x20,	/**< First Sequence of Exchange */
176
+	FC_F_CTL_ES_LAST = 0x10,	/**< Last Sequence of Exchange */
177
+	FC_F_CTL_ES_END = 0x08,		/**< Last Data Frame of Sequence */
178
+	FC_F_CTL_ES_TRANSFER = 0x01,	/**< Transfer Sequence Initiative */
179
+};
180
+
181
+/** Fibre Channel Frame Control - Miscellaneous */
182
+enum fc_f_ctl_misc {
183
+	FC_F_CTL_MISC_REL_OFF = 0x08,	/**< Relative Offset Present */
184
+};
185
+
186
+/** Responder exchange identifier used before first response */
187
+#define FC_RX_ID_UNKNOWN 0xffff
188
+
189
+struct fc_port;
190
+
191
+extern int fc_xchg_originate ( struct interface *parent, struct fc_port *port,
192
+			       struct fc_port_id *peer_port_id,
193
+			       unsigned int type );
194
+
195
+/** A Fibre Channel responder */
196
+struct fc_responder {
197
+	/** Type */
198
+	unsigned int type;
199
+	/** Respond to exchange
200
+	 *
201
+	 * @v xchg		Exchange interface
202
+	 * @v port		Fibre Channel port
203
+	 * @v port_id		Local port ID
204
+	 * @v peer_port_id	Peer port ID
205
+	 * @ret rc		Return status code
206
+	 */
207
+	int ( * respond ) ( struct interface *xchg, struct fc_port *port,
208
+			    struct fc_port_id *port_id,
209
+			    struct fc_port_id *peer_port_id );
210
+};
211
+
212
+/** Fibre Channel responder table */
213
+#define FC_RESPONDERS __table ( struct fc_responder, "fc_responders" )
214
+
215
+/** Declare a Fibre Channel responder */
216
+#define __fc_responder __table_entry ( FC_RESPONDERS, 01 )
217
+
218
+/******************************************************************************
219
+ *
220
+ * Fibre Channel ports
221
+ *
222
+ ******************************************************************************
223
+ */
224
+
225
+/** A Fibre Channel port */
226
+struct fc_port {
227
+	/** Reference count */
228
+	struct refcnt refcnt;
229
+	/** List of all ports */
230
+	struct list_head list;
231
+	/** Name of this port */
232
+	char name[8];
233
+
234
+	/** Transport interface */
235
+	struct interface transport;
236
+	/** Node name */
237
+	struct fc_name node_wwn;
238
+	/** Port name */
239
+	struct fc_name port_wwn;
240
+	/** Local port ID */
241
+	struct fc_port_id port_id;
242
+	/** Flags */
243
+	unsigned int flags;
244
+
245
+	/** Link state monitor */
246
+	struct fc_link_state link;
247
+	/** FLOGI interface */
248
+	struct interface flogi;
249
+	/** Link node name */
250
+	struct fc_name link_node_wwn;
251
+	/** Link port name */
252
+	struct fc_name link_port_wwn;
253
+	/** Link port ID (for point-to-point links only) */
254
+	struct fc_port_id ptp_link_port_id;
255
+
256
+	/** List of active exchanges */
257
+	struct list_head xchgs;
258
+};
259
+
260
+/** Fibre Channel port flags */
261
+enum fc_port_flags {
262
+	/** Port is attached to a fabric */
263
+	FC_PORT_HAS_FABRIC = 0x0001,
264
+};
265
+
266
+/**
267
+ * Get reference to Fibre Channel port
268
+ *
269
+ * @v port		Fibre Channel port
270
+ * @ret port		Fibre Channel port
271
+ */
272
+static inline __attribute__ (( always_inline )) struct fc_port *
273
+fc_port_get ( struct fc_port *port ) {
274
+	ref_get ( &port->refcnt );
275
+	return port;
276
+}
277
+
278
+/**
279
+ * Drop reference to Fibre Channel port
280
+ *
281
+ * @v port		Fibre Channel port
282
+ */
283
+static inline __attribute__ (( always_inline )) void
284
+fc_port_put ( struct fc_port *port ) {
285
+	ref_put ( &port->refcnt );
286
+}
287
+
288
+extern struct list_head fc_ports;
289
+
290
+extern int fc_port_login ( struct fc_port *port, struct fc_port_id *port_id,
291
+			   const struct fc_name *link_node_wwn,
292
+			   const struct fc_name *link_port_wwn,
293
+			   int has_fabric );
294
+extern void fc_port_logout ( struct fc_port *port, int rc );
295
+extern int fc_port_open ( struct interface *transport,
296
+			  const struct fc_name *node_wwn,
297
+			  const struct fc_name *port_wwn );
298
+extern struct fc_port * fc_port_find ( const char *name );
299
+
300
+/******************************************************************************
301
+ *
302
+ * Fibre Channel peers
303
+ *
304
+ ******************************************************************************
305
+ */
306
+
307
+/** A Fibre Channel peer */
308
+struct fc_peer {
309
+	/** Reference count */
310
+	struct refcnt refcnt;
311
+	/** List of all peers */
312
+	struct list_head list;
313
+
314
+	/** Node name */
315
+	struct fc_name node_wwn;
316
+
317
+	/** Link state monitor */
318
+	struct fc_link_state link;
319
+	/** PLOGI interface */
320
+	struct interface plogi;
321
+	/** Fibre Channel port, if known */
322
+	struct fc_port *port;
323
+	/** Peer port ID, if known */
324
+	struct fc_port_id port_id;
325
+
326
+	/** List of upper-layer protocols */
327
+	struct list_head ulps;
328
+	/** Active usage count */
329
+	unsigned int usage;
330
+};
331
+
332
+/**
333
+ * Get reference to Fibre Channel peer
334
+ *
335
+ * @v peer		Fibre Channel peer
336
+ * @ret peer		Fibre Channel peer
337
+ */
338
+static inline __attribute__ (( always_inline )) struct fc_peer *
339
+fc_peer_get ( struct fc_peer *peer ) {
340
+	ref_get ( &peer->refcnt );
341
+	return peer;
342
+}
343
+
344
+/**
345
+ * Drop reference to Fibre Channel peer
346
+ *
347
+ * @v peer		Fibre Channel peer
348
+ */
349
+static inline __attribute__ (( always_inline )) void
350
+fc_peer_put ( struct fc_peer *peer ) {
351
+	ref_put ( &peer->refcnt );
352
+}
353
+
354
+extern struct list_head fc_peers;
355
+
356
+extern struct fc_peer * fc_peer_get_wwn ( const struct fc_name *node_wwn );
357
+extern struct fc_peer *
358
+fc_peer_get_port_id ( struct fc_port *port,
359
+		      const struct fc_port_id *peer_port_id );
360
+extern int fc_peer_login ( struct fc_peer *peer,
361
+			   struct fc_port *port,
362
+			   struct fc_port_id *port_id );
363
+extern void fc_peer_logout ( struct fc_peer *peer, int rc );
364
+
365
+/******************************************************************************
366
+ *
367
+ * Fibre Channel upper-layer protocols
368
+ *
369
+ ******************************************************************************
370
+ */
371
+
372
+/** A Fibre Channel upper-layer protocol */
373
+struct fc_ulp {
374
+	/** Reference count */
375
+	struct refcnt refcnt;
376
+	/** Fibre Channel peer */
377
+	struct fc_peer *peer;
378
+	/** List of upper-layer protocols */
379
+	struct list_head list;
380
+
381
+	/** Type */
382
+	unsigned int type;
383
+	/** Flags */
384
+	unsigned int flags;
385
+
386
+	/** Link state monitor */
387
+	struct fc_link_state link;
388
+	/** PRLI interface */
389
+	struct interface prli;
390
+	/** Service parameters, if any */
391
+	void *param;
392
+	/** Service parameter length */
393
+	size_t param_len;
394
+
395
+	/** Active usage count */
396
+	unsigned int usage;
397
+};
398
+
399
+/** Fibre Channel upper-layer protocol flags */
400
+enum fc_ulp_flags {
401
+	/** A login originated by us has succeeded */
402
+	FC_ULP_ORIGINATED_LOGIN_OK = 0x0001,
403
+};
404
+
405
+/**
406
+ * Get reference to Fibre Channel upper-layer protocol
407
+ *
408
+ * @v ulp		Fibre Channel upper-layer protocol
409
+ * @ret ulp		Fibre Channel upper-layer protocol
410
+ */
411
+static inline __attribute__ (( always_inline )) struct fc_ulp *
412
+fc_ulp_get ( struct fc_ulp *ulp ) {
413
+	ref_get ( &ulp->refcnt );
414
+	return ulp;
415
+}
416
+
417
+/**
418
+ * Drop reference to Fibre Channel upper-layer protocol
419
+ *
420
+ * @v ulp		Fibre Channel upper-layer protocol
421
+ */
422
+static inline __attribute__ (( always_inline )) void
423
+fc_ulp_put ( struct fc_ulp *ulp ) {
424
+	ref_put ( &ulp->refcnt );
425
+}
426
+
427
+extern struct fc_ulp * fc_ulp_get_wwn_type ( const struct fc_name *node_wwn,
428
+					     unsigned int type );
429
+extern struct fc_ulp *
430
+fc_ulp_get_port_id_type ( struct fc_port *port,
431
+			  const struct fc_port_id *peer_port_id,
432
+			  unsigned int type );
433
+extern void fc_ulp_increment ( struct fc_ulp *ulp );
434
+extern void fc_ulp_decrement ( struct fc_ulp *ulp );
435
+extern int fc_ulp_login ( struct fc_ulp *ulp, const void *param,
436
+			  size_t param_len, int originated );
437
+extern void fc_ulp_logout ( struct fc_ulp *ulp, int rc );
438
+
439
+#endif /* _IPXE_FC_H */

+ 452
- 0
src/include/ipxe/fcels.h View File

@@ -0,0 +1,452 @@
1
+#ifndef _IPXE_FCELS_H
2
+#define _IPXE_FCELS_H
3
+
4
+/**
5
+ * @file
6
+ *
7
+ * Fibre Channel Extended Link Services
8
+ *
9
+ */
10
+
11
+FILE_LICENCE ( GPL2_OR_LATER );
12
+
13
+#include <stdint.h>
14
+#include <ipxe/fc.h>
15
+#include <ipxe/tables.h>
16
+#include <ipxe/refcnt.h>
17
+#include <ipxe/list.h>
18
+#include <ipxe/process.h>
19
+#include <ipxe/interface.h>
20
+
21
+/** Fibre Channel ELS frame common parameters */
22
+struct fc_els_frame_common {
23
+	/** ELS command code */
24
+	uint8_t command;
25
+	/** Reserved */
26
+	uint8_t reserved[3];
27
+} __attribute__ (( packed ));
28
+
29
+/** Fibre Channel ELS command codes */
30
+enum fc_els_command_code {
31
+	FC_ELS_LS_RJT = 0x01,		/**< Link Service Reject */
32
+	FC_ELS_LS_ACC = 0x02,		/**< Link Service Accept */
33
+	FC_ELS_PLOGI = 0x03,		/**< Port Login */
34
+	FC_ELS_FLOGI = 0x04,		/**< Fabric Login */
35
+	FC_ELS_LOGO = 0x05,		/**< Logout */
36
+	FC_ELS_RTV = 0x0e,		/**< Read Timeout Value */
37
+	FC_ELS_PRLI = 0x20,		/**< Process Login */
38
+	FC_ELS_PRLO = 0x21,		/**< Process Logout */
39
+};
40
+
41
+/** A Fibre Channel LS_RJT frame */
42
+struct fc_ls_rjt_frame {
43
+	/** ELS command code */
44
+	uint8_t command;
45
+	/** Reserved */
46
+	uint8_t reserved[4];
47
+	/** Reason code */
48
+	uint8_t reason;
49
+	/** Reason code explanation */
50
+	uint8_t explanation;
51
+	/** Vendor unique */
52
+	uint8_t vendor;
53
+} __attribute__ (( packed ));
54
+
55
+/** Fibre Channel ELS rejection reason codes */
56
+enum fc_els_reject_reason {
57
+	/** Invalid ELS command code */
58
+	FC_ELS_RJT_INVALID_COMMAND = 0x01,
59
+	/** Logical error */
60
+	FC_ELS_RJT_ILLOGICAL = 0x03,
61
+	/** Logical busy */
62
+	FC_ELS_RJT_BUSY = 0x05,
63
+	/** Protocol error */
64
+	FC_ELS_RJT_PROTOCOL = 0x07,
65
+	/** Unable to perform command request */
66
+	FC_ELS_RJT_UNABLE = 0x09,
67
+	/** Command not supported */
68
+	FC_ELS_RJT_UNSUPPORTED = 0x0b,
69
+	/** Command already in progress */
70
+	FC_ELS_RJT_IN_PROGRESS = 0x0e,
71
+};
72
+
73
+/** Fibre Channel "common" service parameters */
74
+struct fc_login_common {
75
+	/** Login version */
76
+	uint16_t version;
77
+	/** Buffer-to-buffer credit */
78
+	uint16_t credit;
79
+	/** Flags */
80
+	uint16_t flags;
81
+	/** Receive size */
82
+	uint16_t mtu;
83
+	/** "Common"?! */
84
+	union {
85
+		struct {
86
+			/** Maximum number of concurrent sequences */
87
+			uint16_t max_seq;
88
+			/** Relative offset by info category */
89
+			uint16_t rel_offs;
90
+		} plogi;
91
+		struct {
92
+			/** Resource allocation timeout value */
93
+			uint32_t r_a_tov;
94
+		} flogi;
95
+	} u;
96
+	/** Error detection timeout value */
97
+	uint32_t e_d_tov;
98
+} __attribute__ (( packed ));
99
+
100
+/** Fibre Channel default login version */
101
+#define FC_LOGIN_VERSION 0x2020
102
+
103
+/** Fibre Channel default buffer-to-buffer credit */
104
+#define FC_LOGIN_DEFAULT_B2B 10
105
+
106
+/** Continuously increasing relative offset */
107
+#define FC_LOGIN_CONTINUOUS_OFFSET 0x8000
108
+
109
+/** Clean address */
110
+#define FC_LOGIN_CLEAN 0x8000
111
+
112
+/** Multiple N_Port_ID support */
113
+#define FC_LOGIN_MULTI_N 0x8000
114
+
115
+/** Random relative offset */
116
+#define FC_LOGIN_RANDOM_OFFSET 0x4000
117
+
118
+/** Virtual fabrics */
119
+#define FC_LOGIN_VIRTUAL 0x4000
120
+
121
+/** Vendor version level */
122
+#define FC_LOGIN_VENDOR 0x2000
123
+
124
+/** Multiple N_Port_ID support */
125
+#define FC_LOGIN_MULTI_F 0x2000
126
+
127
+/** Forwarder port */
128
+#define FC_LOGIN_F_PORT 0x1000
129
+
130
+/** Alternative credit management */
131
+#define FC_LOGIN_ALT_CREDIT 0x0800
132
+
133
+/** Name server session started */
134
+#define FC_LOGIN_NSS_STARTED 0x0800
135
+
136
+/** Begin name server session */
137
+#define FC_LOGIN_NSS_BEGIN 0x0400
138
+
139
+/** 1ns error detection timer resolution */
140
+#define FC_LOGIN_HIRES_E_D_TOV 0x0400
141
+
142
+/** Broadcast supported */
143
+#define FC_LOGIN_BROADCAST 0x0100
144
+
145
+/** Query buffer conditions */
146
+#define FC_LOGIN_QUERY_BUF 0x0040
147
+
148
+/** Security */
149
+#define FC_LOGIN_SECURITY 0x0020
150
+
151
+/** Clock sync primitive capable */
152
+#define FC_LOGIN_CLOCK_SYNC 0x0010
153
+
154
+/** Short R_T timeout */
155
+#define FC_LOGIN_SHORT_R_T_TOV 0x0008
156
+
157
+/** Dynamic half duplex */
158
+#define FC_LOGIN_DHD 0x0004
159
+
160
+/** Continuously increasing sequence count */
161
+#define FC_LOGIN_CONTINUOUS_SEQ 0x0002
162
+
163
+/** Payload */
164
+#define FC_LOGIN_PAYLOAD 0x0001
165
+
166
+/** Fibre Channel default MTU */
167
+#define FC_LOGIN_DEFAULT_MTU 1452
168
+
169
+/** Default maximum number of concurrent sequences */
170
+#define FC_LOGIN_DEFAULT_MAX_SEQ 255
171
+
172
+/** Default relative offset by info category */
173
+#define FC_LOGIN_DEFAULT_REL_OFFS 0x1f
174
+
175
+/** Default E_D timeout value */
176
+#define FC_LOGIN_DEFAULT_E_D_TOV 2000
177
+
178
+/** Fibre Channel class-specific login parameters */
179
+struct fc_login_class {
180
+	/** Flags */
181
+	uint16_t flags;
182
+	/** Initiator flags */
183
+	uint16_t init_flags;
184
+	/** Recipient flags */
185
+	uint16_t recip_flags;
186
+	/** Receive data field size */
187
+	uint16_t mtu;
188
+	/** Maximum number of concurrent sequences */
189
+	uint16_t max_seq;
190
+	/** End-to-end credit */
191
+	uint16_t credit;
192
+	/** Reserved */
193
+	uint8_t reserved0;
194
+	/** Maximum number of open sequences per exchange */
195
+	uint8_t max_seq_per_xchg;
196
+	/** Reserved */
197
+	uint8_t reserved1[2];
198
+} __attribute__ (( packed ));
199
+
200
+/** Class valid */
201
+#define FC_LOGIN_CLASS_VALID 0x8000
202
+
203
+/** Sequential delivery requested */
204
+#define FC_LOGIN_CLASS_SEQUENTIAL 0x0800
205
+
206
+/** A Fibre Channel FLOGI/PLOGI frame */
207
+struct fc_login_frame {
208
+	/** ELS command code */
209
+	uint8_t command;
210
+	/** Reserved */
211
+	uint8_t reserved[3];
212
+	/** Common service parameters */
213
+	struct fc_login_common common;
214
+	/** Port name */
215
+	struct fc_name port_wwn;
216
+	/** Node name */
217
+	struct fc_name node_wwn;
218
+	/** Class 1 service parameters */
219
+	struct fc_login_class class1;
220
+	/** Class 2 service parameters */
221
+	struct fc_login_class class2;
222
+	/** Class 3 service parameters */
223
+	struct fc_login_class class3;
224
+	/** Class 4 service parameters */
225
+	struct fc_login_class class4;
226
+	/** Vendor version level */
227
+	uint8_t vendor_version[16];
228
+} __attribute__ (( packed ));
229
+
230
+/** A Fibre Channel LOGO request frame */
231
+struct fc_logout_request_frame {
232
+	/** ELS command code */
233
+	uint8_t command;
234
+	/** Reserved */
235
+	uint8_t reserved[4];
236
+	/** Port ID */
237
+	struct fc_port_id port_id;
238
+	/** Port name */
239
+	struct fc_name port_wwn;
240
+} __attribute__ (( packed ));
241
+
242
+/** A Fibre Channel LOGO response frame */
243
+struct fc_logout_response_frame {
244
+	/** ELS command code */
245
+	uint8_t command;
246
+	/** Reserved */
247
+	uint8_t reserved[3];
248
+} __attribute__ (( packed ));
249
+
250
+/** A Fibre Channel PRLI service parameter page */
251
+struct fc_prli_page {
252
+	/** Type code */
253
+	uint8_t type;
254
+	/** Type code extension */
255
+	uint8_t type_ext;
256
+	/** Flags and response code */
257
+	uint16_t flags;
258
+	/** Reserved */
259
+	uint32_t reserved[2];
260
+} __attribute__ (( packed ));
261
+
262
+/** Establish image pair */
263
+#define FC_PRLI_ESTABLISH 0x2000
264
+
265
+/** Response code mask */
266
+#define FC_PRLI_RESPONSE_MASK 0x0f00
267
+
268
+/** Request was executed successfully */
269
+#define FC_PRLI_RESPONSE_SUCCESS 0x0100
270
+
271
+/** A Fibre Channel PRLI frame */
272
+struct fc_prli_frame {
273
+	/** ELS command code */
274
+	uint8_t command;
275
+	/** Page length */
276
+	uint8_t page_len;
277
+	/** Payload length */
278
+	uint16_t len;
279
+	/** Service parameter page */
280
+	struct fc_prli_page page;
281
+} __attribute__ (( packed ));
282
+
283
+/** A Fibre Channel RTV request frame */
284
+struct fc_rtv_request_frame {
285
+	/** ELS command code */
286
+	uint8_t command;
287
+	/** Reserved */
288
+	uint8_t reserved[3];
289
+} __attribute__ (( packed ));
290
+
291
+/** A Fibre Channel RTV response frame */
292
+struct fc_rtv_response_frame {
293
+	/** ELS command code */
294
+	uint8_t command;
295
+	/** Reserved */
296
+	uint8_t reserved0[3];
297
+	/** Resource allocation timeout value */
298
+	uint32_t r_a_tov;
299
+	/** Error detection timeout value */
300
+	uint32_t e_d_tov;
301
+	/** Timeout qualifier */
302
+	uint16_t flags;
303
+	/** Reserved */
304
+	uint16_t reserved1;
305
+} __attribute__ (( packed ));
306
+
307
+/** 1ns error detection timer resolution */
308
+#define FC_RTV_HIRES_E_D_TOV 0x0400
309
+
310
+/** Short R_T timeout */
311
+#define FC_RTV_SHORT_R_T_TOV 0x0008
312
+
313
+/** A Fibre Channel extended link services transaction */
314
+struct fc_els {
315
+	/** Reference count */
316
+	struct refcnt refcnt;
317
+	/** Job control interface */
318
+	struct interface job;
319
+	/** Fibre Channel exchange */
320
+	struct interface xchg;
321
+	/** Request sending process */
322
+	struct process process;
323
+
324
+	/** Fibre Channel port */
325
+	struct fc_port *port;
326
+	/** Local port ID */
327
+	struct fc_port_id port_id;
328
+	/** Peer port ID */
329
+	struct fc_port_id peer_port_id;
330
+	/** ELS handler, if known */
331
+	struct fc_els_handler *handler;
332
+	/** Flags */
333
+	unsigned int flags;
334
+};
335
+
336
+/** Fibre Channel extended link services transaction flags */
337
+enum fc_els_flags {
338
+	/** ELS transaction is a request */
339
+	FC_ELS_REQUEST = 0x0001,
340
+};
341
+
342
+/** A Fibre Channel extended link services handler */
343
+struct fc_els_handler {
344
+	/** Name */
345
+	const char *name;
346
+	/** Transmit ELS request frame
347
+	 *
348
+	 * @v els		Fibre Channel ELS transaction
349
+	 * @ret rc		Return status code
350
+	 */
351
+	int ( * tx_request ) ( struct fc_els *els );
352
+	/** Transmit ELS response frame
353
+	 *
354
+	 * @v els		Fibre Channel ELS transaction
355
+	 * @ret rc		Return status code
356
+	 */
357
+	int ( * tx_response ) ( struct fc_els *els );
358
+	/** Receive ELS request frame
359
+	 *
360
+	 * @v els		Fibre Channel ELS transaction
361
+	 * @v data		ELS frame
362
+	 * @v len		Length of ELS frame
363
+	 * @ret rc		Return status code
364
+	 */
365
+	int ( * rx_request ) ( struct fc_els *els, const void *data,
366
+			       size_t len );
367
+	/** Receive ELS response frame
368
+	 *
369
+	 * @v els		Fibre Channel ELS transaction
370
+	 * @v data		ELS frame
371
+	 * @v len		Length of ELS frame
372
+	 * @ret rc		Return status code
373
+	 */
374
+	int ( * rx_response ) ( struct fc_els *els, const void *data,
375
+				size_t len );
376
+	/** Detect ELS request frame
377
+	 *
378
+	 * @v els		Fibre Channel ELS transaction
379
+	 * @v data		ELS frame
380
+	 * @v len		Length of ELS frame
381
+	 * @ret rc		Return status code
382
+	 */
383
+	int ( * detect ) ( struct fc_els *els, const void *data, size_t len );
384
+};
385
+
386
+/** Fibre Channel ELS handler table */
387
+#define FC_ELS_HANDLERS __table ( struct fc_els_handler, "fc_els_handlers" )
388
+
389
+/** Declare a Fibre Channel ELS handler */
390
+#define __fc_els_handler __table_entry ( FC_ELS_HANDLERS, 01 )
391
+
392
+/** A Fibre Channel ELS PRLI descriptor */
393
+struct fc_els_prli_descriptor {
394
+	/** Upper-layer protocol type */
395
+	unsigned int type;
396
+	/** Service parameter length */
397
+	size_t param_len;
398
+	/** Fibre Channel ELS handler */
399
+	struct fc_els_handler *handler;
400
+};
401
+
402
+/** Fibre Channel ELS PRLI descriptor table */
403
+#define FC_ELS_PRLI_DESCRIPTORS \
404
+	__table ( struct fc_els_prli_descriptor, "fc_els_prli_descriptors" )
405
+
406
+/** Declare a Fibre Channel ELS PRLI descriptor */
407
+#define __fc_els_prli_descriptor __table_entry ( FC_ELS_PRLI_DESCRIPTORS, 01 )
408
+
409
+/**
410
+ * Check if Fibre Channel ELS transaction is a request
411
+ *
412
+ * @v els		Fibre Channel ELS transaction
413
+ * @ret is_request	ELS transaction is a request
414
+ */
415
+static inline int fc_els_is_request ( struct fc_els *els ) {
416
+	return ( els->flags & FC_ELS_REQUEST );
417
+}
418
+
419
+/**
420
+ * Calculate ELS command to transmit
421
+ *
422
+ * @v els		Fibre Channel ELS transaction
423
+ * @v request_command	Command for requests
424
+ * @v command		Command to transmit
425
+ */
426
+static inline unsigned int fc_els_tx_command ( struct fc_els *els,
427
+					       unsigned int request_command ) {
428
+	return ( fc_els_is_request ( els ) ? request_command : FC_ELS_LS_ACC );
429
+}
430
+
431
+extern int fc_els_tx ( struct fc_els *els, const void *data, size_t len );
432
+extern int fc_els_request ( struct interface *job, struct fc_port *port,
433
+			    struct fc_port_id *peer_port_id,
434
+			    struct fc_els_handler *handler );
435
+extern int fc_els_flogi ( struct interface *parent, struct fc_port *port );
436
+extern int fc_els_plogi ( struct interface *parent, struct fc_port *port,
437
+			  struct fc_port_id *peer_port_id );
438
+extern int fc_els_logo ( struct interface *parent, struct fc_port *port,
439
+			 struct fc_port_id *peer_port_id );
440
+extern int fc_els_prli ( struct interface *parent, struct fc_port *port,
441
+			 struct fc_port_id *peer_port_id, unsigned int type );
442
+extern int fc_els_prli_tx ( struct fc_els *els,
443
+			    struct fc_els_prli_descriptor *descriptor,
444
+			    void *param );
445
+extern int fc_els_prli_rx ( struct fc_els *els,
446
+			    struct fc_els_prli_descriptor *descriptor,
447
+			    const void *data, size_t len );
448
+extern int fc_els_prli_detect ( struct fc_els *els __unused,
449
+				struct fc_els_prli_descriptor *descriptor,
450
+				const void *data, size_t len );
451
+
452
+#endif /* _IPXE_FCELS_H */

+ 16
- 0
src/include/ipxe/xfer.h View File

@@ -46,6 +46,22 @@ struct xfer_metadata {
46 46
 /** Offset is absolute */
47 47
 #define XFER_FL_ABS_OFFSET 0x0001
48 48
 
49
+/** Sender is relinquishing use of half-duplex channel */
50
+#define XFER_FL_OVER 0x0002
51
+
52
+/** This is the final data transfer */
53
+#define XFER_FL_OUT 0x0004
54
+
55
+/** Data content represents a command or status message
56
+ *
57
+ * The flag @c XFER_FL_RESPONSE is used to distinguish between a
58
+ * command message and a status message.
59
+ */
60
+#define XFER_FL_CMD_STAT 0x0008
61
+
62
+/** Data content is a response */
63
+#define XFER_FL_RESPONSE 0x0010
64
+
49 65
 /* Data transfer interface operations */
50 66
 
51 67
 extern int xfer_vredirect ( struct interface *intf, int type,

+ 1773
- 0
src/net/fc.c
File diff suppressed because it is too large
View File


+ 1162
- 0
src/net/fcels.c
File diff suppressed because it is too large
View File


Loading…
Cancel
Save