11 FILE_LICENCE ( GPL2_OR_LATER );
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 #include <ipxe/socket.h>
21 /******************************************************************************
23 * Fibre Channel Names and identifiers
25 ******************************************************************************
28 /** A Fibre Channel name */
31 } __attribute__ (( packed ));
33 /** Length of Fibre Channel name text */
34 #define FC_NAME_STRLEN 23 /* "xx:xx:xx:xx:xx:xx:xx:xx" */
36 /** A Fibre Channel port identifier */
39 } __attribute__ (( packed ));
41 /** Length of Fibre Channel port identifier next */
42 #define FC_PORT_ID_STRLEN 9 /* "xx.xx.xx" */
45 * Fibre Channel socket address
48 /** Socket address family (part of struct @c sockaddr)
50 * Always set to @c AF_FC for Fibre Channel addresses
52 sa_family_t sfc_family;
54 struct fc_port_id sfc_port_id;
57 * This ensures that a struct @c sockaddr_tcpip is large
58 * enough to hold a socket address for any TCP/IP address
61 char pad[ sizeof ( struct sockaddr ) - sizeof ( sa_family_t )
62 - sizeof ( struct fc_port_id ) ];
63 } __attribute__ (( packed, may_alias ));
65 extern struct fc_port_id fc_empty_port_id;
66 extern struct fc_port_id fc_f_port_id;
67 extern struct fc_port_id fc_gs_port_id;
68 extern struct fc_port_id fc_ptp_low_port_id;
69 extern struct fc_port_id fc_ptp_high_port_id;
71 extern const char * fc_id_ntoa ( const struct fc_port_id *id );
72 extern int fc_id_aton ( const char *id_text, struct fc_port_id *id );
73 extern const char * fc_ntoa ( const struct fc_name *wwn );
74 extern int fc_aton ( const char *wwn_text, struct fc_name *wwn );
75 extern struct sockaddr * fc_fill_sockaddr ( struct sockaddr_fc *sa_fc,
76 struct fc_port_id *id );
78 /******************************************************************************
80 * Fibre Channel link state
82 ******************************************************************************
85 /** Delay between failed link-up attempts */
86 #define FC_LINK_RETRY_DELAY ( 2 * TICKS_PER_SEC )
88 /** A Fibre Channel link state nonitor */
89 struct fc_link_state {
91 struct retry_timer timer;
94 /** Examine link state
96 * @v link Fibre Channel link state monitor
98 void ( * examine ) ( struct fc_link_state *link );
102 * Check Fibre Channel link state
104 * @v link Fibre Channel link state monitor
105 * @ret link_up Link is up
107 static inline __attribute__ (( always_inline )) int
108 fc_link_ok ( struct fc_link_state *link ) {
109 return ( link->rc == 0 );
112 /******************************************************************************
114 * Fibre Channel packet formats and exchanges
116 ******************************************************************************
119 /** A Fibre Channel Frame Header */
120 struct fc_frame_header {
123 * This is the bitwise OR of one @c fc_r_ctl_routing value and
124 * one @c fc_r_ctl_info value.
127 /** Destination ID */
128 struct fc_port_id d_id;
129 /** Class-specific control / Priority */
132 struct fc_port_id s_id;
133 /** Data structure type */
135 /** Frame control - exchange and sequence */
137 /** Frame control - acknowledgements */
139 /** Frame control - miscellaneous */
143 /** Data field control */
145 /** Sequence count */
147 /** Originator exchange ID */
149 /** Responder exchange ID */
153 * Contains the relative offset when @c FC_F_CTL_MISC_REL_OFF
157 } __attribute__ (( packed ));
159 /** Fibre Channel Routing Control Routing */
160 enum fc_r_ctl_routing {
161 FC_R_CTL_DATA = 0x00, /**< Device Data */
162 FC_R_CTL_ELS = 0x20, /**< Extended Link Services */
163 FC_R_CTL_FC4_LINK = 0x30, /**< FC-4 Link Data */
164 FC_R_CTL_VIDEO = 0x40, /**< Video Data */
165 FC_R_CTL_EH = 0x50, /**< Extended Headers */
166 FC_R_CTL_BLS = 0x80, /**< Basic Link Services */
167 FC_R_CTL_LINK_CTRL = 0xc0, /**< Link Control */
168 FC_R_CTL_EXT_ROUTE = 0xf0, /**< Extended Routing */
171 /** Fibre Channel Routing Control Routing mask */
172 #define FC_R_CTL_ROUTING_MASK 0xf0
174 /** Fibre Channel Routing Control Information */
176 FC_R_CTL_UNCAT = 0x00, /**< Uncategorized */
177 FC_R_CTL_SOL_DATA = 0x01, /**< Solicited Data */
178 FC_R_CTL_UNSOL_CTRL = 0x02, /**< Unsolicited Control */
179 FC_R_CTL_SOL_CTRL = 0x03, /**< Solicited Control */
180 FC_R_CTL_UNSOL_DATA = 0x04, /**< Unsolicited Data */
181 FC_R_CTL_DATA_DESC = 0x05, /**< Data Descriptor */
182 FC_R_CTL_UNSOL_CMD = 0x06, /**< Unsolicited Command */
183 FC_R_CTL_CMD_STAT = 0x07, /**< Command Status */
186 /** Fibre Channel Routing Control Information mask */
187 #define FC_R_CTL_INFO_MASK 0x07
189 /** Fibre Channel Data Structure Type */
191 FC_TYPE_BLS = 0x00, /**< Basic Link Service */
192 FC_TYPE_ELS = 0x01, /**< Extended Link Service */
193 FC_TYPE_FCP = 0x08, /**< Fibre Channel Protocol */
194 FC_TYPE_CT = 0x20, /**< Common Transport */
197 /** Fibre Channel Frame Control - Exchange and Sequence */
199 FC_F_CTL_ES_RESPONDER = 0x80, /**< Responder of Exchange */
200 FC_F_CTL_ES_RECIPIENT = 0x40, /**< Sequence Recipient */
201 FC_F_CTL_ES_FIRST = 0x20, /**< First Sequence of Exchange */
202 FC_F_CTL_ES_LAST = 0x10, /**< Last Sequence of Exchange */
203 FC_F_CTL_ES_END = 0x08, /**< Last Data Frame of Sequence */
204 FC_F_CTL_ES_TRANSFER = 0x01, /**< Transfer Sequence Initiative */
207 /** Fibre Channel Frame Control - Miscellaneous */
209 FC_F_CTL_MISC_REL_OFF = 0x08, /**< Relative Offset Present */
212 /** Responder exchange identifier used before first response */
213 #define FC_RX_ID_UNKNOWN 0xffff
217 extern int fc_xchg_originate ( struct interface *parent, struct fc_port *port,
218 struct fc_port_id *peer_port_id,
221 /** A Fibre Channel responder */
222 struct fc_responder {
225 /** Respond to exchange
227 * @v xchg Exchange interface
228 * @v port Fibre Channel port
229 * @v port_id Local port ID
230 * @v peer_port_id Peer port ID
231 * @ret rc Return status code
233 int ( * respond ) ( struct interface *xchg, struct fc_port *port,
234 struct fc_port_id *port_id,
235 struct fc_port_id *peer_port_id );
238 /** Fibre Channel responder table */
239 #define FC_RESPONDERS __table ( struct fc_responder, "fc_responders" )
241 /** Declare a Fibre Channel responder */
242 #define __fc_responder __table_entry ( FC_RESPONDERS, 01 )
244 /******************************************************************************
246 * Fibre Channel ports
248 ******************************************************************************
251 /** A Fibre Channel port */
253 /** Reference count */
254 struct refcnt refcnt;
255 /** List of all ports */
256 struct list_head list;
257 /** Name of this port */
260 /** Transport interface */
261 struct interface transport;
263 struct fc_name node_wwn;
265 struct fc_name port_wwn;
267 struct fc_port_id port_id;
271 /** Link state monitor */
272 struct fc_link_state link;
273 /** FLOGI interface */
274 struct interface flogi;
275 /** Link node name */
276 struct fc_name link_node_wwn;
277 /** Link port name */
278 struct fc_name link_port_wwn;
279 /** Link port ID (for point-to-point links only) */
280 struct fc_port_id ptp_link_port_id;
282 /** Name server PLOGI interface */
283 struct interface ns_plogi;
285 /** List of active exchanges */
286 struct list_head xchgs;
289 /** Fibre Channel port flags */
291 /** Port is attached to a fabric */
292 FC_PORT_HAS_FABRIC = 0x0001,
293 /** Port is logged in to a name server */
294 FC_PORT_HAS_NS = 0x0002,
298 * Get reference to Fibre Channel port
300 * @v port Fibre Channel port
301 * @ret port Fibre Channel port
303 static inline __attribute__ (( always_inline )) struct fc_port *
304 fc_port_get ( struct fc_port *port ) {
305 ref_get ( &port->refcnt );
310 * Drop reference to Fibre Channel port
312 * @v port Fibre Channel port
314 static inline __attribute__ (( always_inline )) void
315 fc_port_put ( struct fc_port *port ) {
316 ref_put ( &port->refcnt );
319 extern struct list_head fc_ports;
321 extern int fc_port_login ( struct fc_port *port, struct fc_port_id *port_id,
322 const struct fc_name *link_node_wwn,
323 const struct fc_name *link_port_wwn,
325 extern void fc_port_logout ( struct fc_port *port, int rc );
326 extern int fc_port_open ( struct interface *transport,
327 const struct fc_name *node_wwn,
328 const struct fc_name *port_wwn,
330 extern struct fc_port * fc_port_find ( const char *name );
332 /******************************************************************************
334 * Fibre Channel peers
336 ******************************************************************************
339 /** A Fibre Channel peer */
341 /** Reference count */
342 struct refcnt refcnt;
343 /** List of all peers */
344 struct list_head list;
347 struct fc_name port_wwn;
349 /** Link state monitor */
350 struct fc_link_state link;
351 /** PLOGI interface */
352 struct interface plogi;
353 /** Fibre Channel port, if known */
354 struct fc_port *port;
355 /** Peer port ID, if known */
356 struct fc_port_id port_id;
358 /** List of upper-layer protocols */
359 struct list_head ulps;
360 /** Active usage count
362 * A peer (and attached ULPs) may be created in response to
363 * unsolicited login requests received via the fabric. We
364 * track our own active usage count independently of the
365 * existence of the peer, so that if the peer becomes logged
366 * out (e.g. due to a link failure) then we know whether or
367 * not we should attempt to relogin.
373 * Get reference to Fibre Channel peer
375 * @v peer Fibre Channel peer
376 * @ret peer Fibre Channel peer
378 static inline __attribute__ (( always_inline )) struct fc_peer *
379 fc_peer_get ( struct fc_peer *peer ) {
380 ref_get ( &peer->refcnt );
385 * Drop reference to Fibre Channel peer
387 * @v peer Fibre Channel peer
389 static inline __attribute__ (( always_inline )) void
390 fc_peer_put ( struct fc_peer *peer ) {
391 ref_put ( &peer->refcnt );
394 extern struct list_head fc_peers;
396 extern struct fc_peer * fc_peer_get_wwn ( const struct fc_name *port_wwn );
397 extern struct fc_peer *
398 fc_peer_get_port_id ( struct fc_port *port,
399 const struct fc_port_id *peer_port_id );
400 extern int fc_peer_login ( struct fc_peer *peer,
401 struct fc_port *port,
402 struct fc_port_id *port_id );
403 extern void fc_peer_logout ( struct fc_peer *peer, int rc );
405 /******************************************************************************
407 * Fibre Channel upper-layer protocols
409 ******************************************************************************
412 /** A Fibre Channel upper-layer protocol */
414 /** Reference count */
415 struct refcnt refcnt;
416 /** Fibre Channel peer */
417 struct fc_peer *peer;
418 /** List of upper-layer protocols */
419 struct list_head list;
426 /** Link state monitor */
427 struct fc_link_state link;
428 /** PRLI interface */
429 struct interface prli;
430 /** Service parameters, if any */
432 /** Service parameter length */
435 /** Active users of this upper-layer protocol
437 * As with peers, an upper-layer protocol may be created in
438 * response to an unsolicited login request received via the
439 * fabric. This list records the number of active users of
440 * the ULP; the number of entries in the list is equivalent to
441 * the peer usage count.
443 struct list_head users;
446 /** Fibre Channel upper-layer protocol flags */
448 /** A login originated by us has succeeded */
449 FC_ULP_ORIGINATED_LOGIN_OK = 0x0001,
452 /** A Fibre Channel upper-layer protocol user */
454 /** Fibre Channel upper layer protocol */
457 struct list_head list;
458 /** Containing object reference count, or NULL */
459 struct refcnt *refcnt;
460 /** Examine link state
462 * @v user Fibre Channel upper-layer-protocol user
464 void ( * examine ) ( struct fc_ulp_user *user );
468 * Get reference to Fibre Channel upper-layer protocol
470 * @v ulp Fibre Channel upper-layer protocol
471 * @ret ulp Fibre Channel upper-layer protocol
473 static inline __attribute__ (( always_inline )) struct fc_ulp *
474 fc_ulp_get ( struct fc_ulp *ulp ) {
475 ref_get ( &ulp->refcnt );
480 * Drop reference to Fibre Channel upper-layer protocol
482 * @v ulp Fibre Channel upper-layer protocol
484 static inline __attribute__ (( always_inline )) void
485 fc_ulp_put ( struct fc_ulp *ulp ) {
486 ref_put ( &ulp->refcnt );
490 * Get reference to Fibre Channel upper-layer protocol user
492 * @v user Fibre Channel upper-layer protocol user
493 * @ret user Fibre Channel upper-layer protocol user
495 static inline __attribute__ (( always_inline )) struct fc_ulp_user *
496 fc_ulp_user_get ( struct fc_ulp_user *user ) {
497 ref_get ( user->refcnt );
502 * Drop reference to Fibre Channel upper-layer protocol user
504 * @v user Fibre Channel upper-layer protocol user
506 static inline __attribute__ (( always_inline )) void
507 fc_ulp_user_put ( struct fc_ulp_user *user ) {
508 ref_put ( user->refcnt );
512 * Initialise Fibre Channel upper-layer protocol user
514 * @v user Fibre Channel upper-layer protocol user
515 * @v examine Examine link state method
516 * @v refcnt Containing object reference count, or NULL
518 static inline __attribute__ (( always_inline )) void
519 fc_ulp_user_init ( struct fc_ulp_user *user,
520 void ( * examine ) ( struct fc_ulp_user *user ),
521 struct refcnt *refcnt ) {
522 user->examine = examine;
523 user->refcnt = refcnt;
526 extern struct fc_ulp * fc_ulp_get_wwn_type ( const struct fc_name *port_wwn,
528 extern struct fc_ulp *
529 fc_ulp_get_port_id_type ( struct fc_port *port,
530 const struct fc_port_id *peer_port_id,
532 extern void fc_ulp_attach ( struct fc_ulp *ulp, struct fc_ulp_user *user );
533 extern void fc_ulp_detach ( struct fc_ulp_user *user );
534 extern int fc_ulp_login ( struct fc_ulp *ulp, const void *param,
535 size_t param_len, int originated );
536 extern void fc_ulp_logout ( struct fc_ulp *ulp, int rc );
538 #endif /* _IPXE_FC_H */