Add qemu 2.4.0
[kvmfornfv.git] / qemu / roms / ipxe / src / include / ipxe / fc.h
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 #include <ipxe/socket.h>
20
21 /******************************************************************************
22  *
23  * Fibre Channel Names and identifiers
24  *
25  ******************************************************************************
26  */
27
28 /** A Fibre Channel name */
29 struct fc_name {
30         uint8_t bytes[8];
31 } __attribute__ (( packed ));
32
33 /** Length of Fibre Channel name text */
34 #define FC_NAME_STRLEN 23 /* "xx:xx:xx:xx:xx:xx:xx:xx" */
35
36 /** A Fibre Channel port identifier */
37 struct fc_port_id {
38         uint8_t bytes[3];
39 } __attribute__ (( packed ));
40
41 /** Length of Fibre Channel port identifier next */
42 #define FC_PORT_ID_STRLEN 9 /* "xx.xx.xx" */
43
44 /**
45  * Fibre Channel socket address
46  */
47 struct sockaddr_fc {
48         /** Socket address family (part of struct @c sockaddr)
49          *
50          * Always set to @c AF_FC for Fibre Channel addresses
51          */
52         sa_family_t sfc_family;
53         /** Port ID */
54         struct fc_port_id sfc_port_id;
55         /** Padding
56          *
57          * This ensures that a struct @c sockaddr_tcpip is large
58          * enough to hold a socket address for any TCP/IP address
59          * family.
60          */
61         char pad[ sizeof ( struct sockaddr ) - sizeof ( sa_family_t )
62                                              - sizeof ( struct fc_port_id ) ];
63 } __attribute__ (( packed, may_alias ));
64
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;
70
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 );
77
78 /******************************************************************************
79  *
80  * Fibre Channel link state
81  *
82  ******************************************************************************
83  */
84
85 /** Delay between failed link-up attempts */
86 #define FC_LINK_RETRY_DELAY ( 2 * TICKS_PER_SEC )
87
88 /** A Fibre Channel link state nonitor */
89 struct fc_link_state {
90         /** Retry timer */
91         struct retry_timer timer;
92         /** Link state */
93         int rc;
94         /** Examine link state
95          *
96          * @v link              Fibre Channel link state monitor
97          */
98         void ( * examine ) ( struct fc_link_state *link );
99 };
100
101 /**
102  * Check Fibre Channel link state
103  *
104  * @v link              Fibre Channel link state monitor
105  * @ret link_up         Link is up
106  */
107 static inline __attribute__ (( always_inline )) int
108 fc_link_ok ( struct fc_link_state *link ) {
109         return ( link->rc == 0 );
110 }
111
112 /******************************************************************************
113  *
114  * Fibre Channel packet formats and exchanges
115  *
116  ******************************************************************************
117  */
118
119 /** A Fibre Channel Frame Header */
120 struct fc_frame_header {
121         /** Routing control
122          *
123          * This is the bitwise OR of one @c fc_r_ctl_routing value and
124          * one @c fc_r_ctl_info value.
125          */
126         uint8_t r_ctl;
127         /** Destination ID */
128         struct fc_port_id d_id;
129         /** Class-specific control / Priority */
130         uint8_t cs_ctl_prio;
131         /** Source ID */
132         struct fc_port_id s_id;
133         /** Data structure type */
134         uint8_t type;
135         /** Frame control - exchange and sequence */
136         uint8_t f_ctl_es;
137         /** Frame control - acknowledgements  */
138         uint8_t f_ctl_ack;
139         /** Frame control - miscellaneous */
140         uint8_t f_ctl_misc;
141         /** Sequence ID */
142         uint8_t seq_id;
143         /** Data field control */
144         uint8_t df_ctl;
145         /** Sequence count */
146         uint16_t seq_cnt;
147         /** Originator exchange ID */
148         uint16_t ox_id;
149         /** Responder exchange ID */
150         uint16_t rx_id;
151         /** Parameter
152          *
153          * Contains the relative offset when @c FC_F_CTL_MISC_REL_OFF
154          * is set.
155          */
156         uint32_t parameter;
157 } __attribute__ (( packed ));
158
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 */
169 };
170
171 /** Fibre Channel Routing Control Routing mask */
172 #define FC_R_CTL_ROUTING_MASK 0xf0
173
174 /** Fibre Channel Routing Control Information */
175 enum fc_r_ctl_info {
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 */
184 };
185
186 /** Fibre Channel Routing Control Information mask */
187 #define FC_R_CTL_INFO_MASK 0x07
188
189 /** Fibre Channel Data Structure Type */
190 enum fc_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 */
195 };
196
197 /** Fibre Channel Frame Control - Exchange and Sequence */
198 enum fc_f_ctl_es {
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 */
205 };
206
207 /** Fibre Channel Frame Control - Miscellaneous */
208 enum fc_f_ctl_misc {
209         FC_F_CTL_MISC_REL_OFF = 0x08,   /**< Relative Offset Present */
210 };
211
212 /** Responder exchange identifier used before first response */
213 #define FC_RX_ID_UNKNOWN 0xffff
214
215 struct fc_port;
216
217 extern int fc_xchg_originate ( struct interface *parent, struct fc_port *port,
218                                struct fc_port_id *peer_port_id,
219                                unsigned int type );
220
221 /** A Fibre Channel responder */
222 struct fc_responder {
223         /** Type */
224         unsigned int type;
225         /** Respond to exchange
226          *
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
232          */
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 );
236 };
237
238 /** Fibre Channel responder table */
239 #define FC_RESPONDERS __table ( struct fc_responder, "fc_responders" )
240
241 /** Declare a Fibre Channel responder */
242 #define __fc_responder __table_entry ( FC_RESPONDERS, 01 )
243
244 /******************************************************************************
245  *
246  * Fibre Channel ports
247  *
248  ******************************************************************************
249  */
250
251 /** A Fibre Channel port */
252 struct fc_port {
253         /** Reference count */
254         struct refcnt refcnt;
255         /** List of all ports */
256         struct list_head list;
257         /** Name of this port */
258         char name[8];
259
260         /** Transport interface */
261         struct interface transport;
262         /** Node name */
263         struct fc_name node_wwn;
264         /** Port name */
265         struct fc_name port_wwn;
266         /** Local port ID */
267         struct fc_port_id port_id;
268         /** Flags */
269         unsigned int flags;
270
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;
281
282         /** Name server PLOGI interface */
283         struct interface ns_plogi;
284
285         /** List of active exchanges */
286         struct list_head xchgs;
287 };
288
289 /** Fibre Channel port flags */
290 enum fc_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,
295 };
296
297 /**
298  * Get reference to Fibre Channel port
299  *
300  * @v port              Fibre Channel port
301  * @ret port            Fibre Channel port
302  */
303 static inline __attribute__ (( always_inline )) struct fc_port *
304 fc_port_get ( struct fc_port *port ) {
305         ref_get ( &port->refcnt );
306         return port;
307 }
308
309 /**
310  * Drop reference to Fibre Channel port
311  *
312  * @v port              Fibre Channel port
313  */
314 static inline __attribute__ (( always_inline )) void
315 fc_port_put ( struct fc_port *port ) {
316         ref_put ( &port->refcnt );
317 }
318
319 extern struct list_head fc_ports;
320
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,
324                            int has_fabric );
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,
329                           const char *name );
330 extern struct fc_port * fc_port_find ( const char *name );
331
332 /******************************************************************************
333  *
334  * Fibre Channel peers
335  *
336  ******************************************************************************
337  */
338
339 /** A Fibre Channel peer */
340 struct fc_peer {
341         /** Reference count */
342         struct refcnt refcnt;
343         /** List of all peers */
344         struct list_head list;
345
346         /** Port name */
347         struct fc_name port_wwn;
348
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;
357
358         /** List of upper-layer protocols */
359         struct list_head ulps;
360         /** Active usage count
361          *
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.
368          */
369         unsigned int usage;
370 };
371
372 /**
373  * Get reference to Fibre Channel peer
374  *
375  * @v peer              Fibre Channel peer
376  * @ret peer            Fibre Channel peer
377  */
378 static inline __attribute__ (( always_inline )) struct fc_peer *
379 fc_peer_get ( struct fc_peer *peer ) {
380         ref_get ( &peer->refcnt );
381         return peer;
382 }
383
384 /**
385  * Drop reference to Fibre Channel peer
386  *
387  * @v peer              Fibre Channel peer
388  */
389 static inline __attribute__ (( always_inline )) void
390 fc_peer_put ( struct fc_peer *peer ) {
391         ref_put ( &peer->refcnt );
392 }
393
394 extern struct list_head fc_peers;
395
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 );
404
405 /******************************************************************************
406  *
407  * Fibre Channel upper-layer protocols
408  *
409  ******************************************************************************
410  */
411
412 /** A Fibre Channel upper-layer protocol */
413 struct fc_ulp {
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;
420
421         /** Type */
422         unsigned int type;
423         /** Flags */
424         unsigned int flags;
425
426         /** Link state monitor */
427         struct fc_link_state link;
428         /** PRLI interface */
429         struct interface prli;
430         /** Service parameters, if any */
431         void *param;
432         /** Service parameter length */
433         size_t param_len;
434
435         /** Active users of this upper-layer protocol
436          *
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.
442          */
443         struct list_head users;
444 };
445
446 /** Fibre Channel upper-layer protocol flags */
447 enum fc_ulp_flags {
448         /** A login originated by us has succeeded */
449         FC_ULP_ORIGINATED_LOGIN_OK = 0x0001,
450 };
451
452 /** A Fibre Channel upper-layer protocol user */
453 struct fc_ulp_user {
454         /** Fibre Channel upper layer protocol */
455         struct fc_ulp *ulp;
456         /** List of users */
457         struct list_head list;
458         /** Containing object reference count, or NULL */
459         struct refcnt *refcnt;
460         /** Examine link state
461          *
462          * @v user              Fibre Channel upper-layer-protocol user
463          */
464         void ( * examine ) ( struct fc_ulp_user *user );
465 };
466
467 /**
468  * Get reference to Fibre Channel upper-layer protocol
469  *
470  * @v ulp               Fibre Channel upper-layer protocol
471  * @ret ulp             Fibre Channel upper-layer protocol
472  */
473 static inline __attribute__ (( always_inline )) struct fc_ulp *
474 fc_ulp_get ( struct fc_ulp *ulp ) {
475         ref_get ( &ulp->refcnt );
476         return ulp;
477 }
478
479 /**
480  * Drop reference to Fibre Channel upper-layer protocol
481  *
482  * @v ulp               Fibre Channel upper-layer protocol
483  */
484 static inline __attribute__ (( always_inline )) void
485 fc_ulp_put ( struct fc_ulp *ulp ) {
486         ref_put ( &ulp->refcnt );
487 }
488
489 /**
490  * Get reference to Fibre Channel upper-layer protocol user
491  *
492  * @v user              Fibre Channel upper-layer protocol user
493  * @ret user            Fibre Channel upper-layer protocol user
494  */
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 );
498         return user;
499 }
500
501 /**
502  * Drop reference to Fibre Channel upper-layer protocol user
503  *
504  * @v user              Fibre Channel upper-layer protocol user
505  */
506 static inline __attribute__ (( always_inline )) void
507 fc_ulp_user_put ( struct fc_ulp_user *user ) {
508         ref_put ( user->refcnt );
509 }
510
511 /**
512  * Initialise Fibre Channel upper-layer protocol user
513  *
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
517  */
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;
524 }
525
526 extern struct fc_ulp * fc_ulp_get_wwn_type ( const struct fc_name *port_wwn,
527                                              unsigned int type );
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,
531                           unsigned int type );
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 );
537
538 #endif /* _IPXE_FC_H */