iPXE
fc.h
Go to the documentation of this file.
00001 #ifndef _IPXE_FC_H
00002 #define _IPXE_FC_H
00003 
00004 /**
00005  * @file
00006  *
00007  * Fibre Channel
00008  *
00009  */
00010 
00011 FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
00012 
00013 #include <stdint.h>
00014 #include <ipxe/refcnt.h>
00015 #include <ipxe/list.h>
00016 #include <ipxe/tables.h>
00017 #include <ipxe/interface.h>
00018 #include <ipxe/retry.h>
00019 #include <ipxe/socket.h>
00020 
00021 /******************************************************************************
00022  *
00023  * Fibre Channel Names and identifiers
00024  *
00025  ******************************************************************************
00026  */
00027 
00028 /** A Fibre Channel name */
00029 struct fc_name {
00030         uint8_t bytes[8];
00031 } __attribute__ (( packed ));
00032 
00033 /** Length of Fibre Channel name text */
00034 #define FC_NAME_STRLEN 23 /* "xx:xx:xx:xx:xx:xx:xx:xx" */
00035 
00036 /** A Fibre Channel port identifier */
00037 struct fc_port_id {
00038         uint8_t bytes[3];
00039 } __attribute__ (( packed ));
00040 
00041 /** Length of Fibre Channel port identifier next */
00042 #define FC_PORT_ID_STRLEN 9 /* "xx.xx.xx" */
00043 
00044 /**
00045  * Fibre Channel socket address
00046  */
00047 struct sockaddr_fc {
00048         /** Socket address family (part of struct @c sockaddr)
00049          *
00050          * Always set to @c AF_FC for Fibre Channel addresses
00051          */
00052         sa_family_t sfc_family;
00053         /** Port ID */
00054         struct fc_port_id sfc_port_id;
00055         /** Padding
00056          *
00057          * This ensures that a struct @c sockaddr_tcpip is large
00058          * enough to hold a socket address for any TCP/IP address
00059          * family.
00060          */
00061         char pad[ sizeof ( struct sockaddr ) - sizeof ( sa_family_t )
00062                                              - sizeof ( struct fc_port_id ) ];
00063 } __attribute__ (( packed, may_alias ));
00064 
00065 extern struct fc_port_id fc_empty_port_id;
00066 extern struct fc_port_id fc_f_port_id;
00067 extern struct fc_port_id fc_gs_port_id;
00068 extern struct fc_port_id fc_ptp_low_port_id;
00069 extern struct fc_port_id fc_ptp_high_port_id;
00070 
00071 extern const char * fc_id_ntoa ( const struct fc_port_id *id );
00072 extern int fc_id_aton ( const char *id_text, struct fc_port_id *id );
00073 extern const char * fc_ntoa ( const struct fc_name *wwn );
00074 extern int fc_aton ( const char *wwn_text, struct fc_name *wwn );
00075 extern struct sockaddr * fc_fill_sockaddr ( struct sockaddr_fc *sa_fc,
00076                                             struct fc_port_id *id );
00077 
00078 /******************************************************************************
00079  *
00080  * Fibre Channel link state
00081  *
00082  ******************************************************************************
00083  */
00084 
00085 /** Delay between failed link-up attempts */
00086 #define FC_LINK_RETRY_DELAY ( 2 * TICKS_PER_SEC )
00087 
00088 /** A Fibre Channel link state nonitor */
00089 struct fc_link_state {
00090         /** Retry timer */
00091         struct retry_timer timer;
00092         /** Link state */
00093         int rc;
00094         /** Examine link state
00095          *
00096          * @v link              Fibre Channel link state monitor
00097          */
00098         void ( * examine ) ( struct fc_link_state *link );
00099 };
00100 
00101 /**
00102  * Check Fibre Channel link state
00103  *
00104  * @v link              Fibre Channel link state monitor
00105  * @ret link_up         Link is up
00106  */
00107 static inline __attribute__ (( always_inline )) int
00108 fc_link_ok ( struct fc_link_state *link ) {
00109         return ( link->rc == 0 );
00110 }
00111 
00112 /******************************************************************************
00113  *
00114  * Fibre Channel packet formats and exchanges
00115  *
00116  ******************************************************************************
00117  */
00118 
00119 /** A Fibre Channel Frame Header */
00120 struct fc_frame_header {
00121         /** Routing control
00122          *
00123          * This is the bitwise OR of one @c fc_r_ctl_routing value and
00124          * one @c fc_r_ctl_info value.
00125          */
00126         uint8_t r_ctl;
00127         /** Destination ID */
00128         struct fc_port_id d_id;
00129         /** Class-specific control / Priority */
00130         uint8_t cs_ctl_prio;
00131         /** Source ID */
00132         struct fc_port_id s_id;
00133         /** Data structure type */
00134         uint8_t type;
00135         /** Frame control - exchange and sequence */
00136         uint8_t f_ctl_es;
00137         /** Frame control - acknowledgements  */
00138         uint8_t f_ctl_ack;
00139         /** Frame control - miscellaneous */
00140         uint8_t f_ctl_misc;
00141         /** Sequence ID */
00142         uint8_t seq_id;
00143         /** Data field control */
00144         uint8_t df_ctl;
00145         /** Sequence count */
00146         uint16_t seq_cnt;
00147         /** Originator exchange ID */
00148         uint16_t ox_id;
00149         /** Responder exchange ID */
00150         uint16_t rx_id;
00151         /** Parameter
00152          *
00153          * Contains the relative offset when @c FC_F_CTL_MISC_REL_OFF
00154          * is set.
00155          */
00156         uint32_t parameter;
00157 } __attribute__ (( packed ));
00158 
00159 /** Fibre Channel Routing Control Routing */
00160 enum fc_r_ctl_routing {
00161         FC_R_CTL_DATA = 0x00,           /**< Device Data */
00162         FC_R_CTL_ELS = 0x20,            /**< Extended Link Services */
00163         FC_R_CTL_FC4_LINK = 0x30,       /**< FC-4 Link Data */
00164         FC_R_CTL_VIDEO = 0x40,          /**< Video Data */
00165         FC_R_CTL_EH = 0x50,             /**< Extended Headers */
00166         FC_R_CTL_BLS = 0x80,            /**< Basic Link Services */
00167         FC_R_CTL_LINK_CTRL = 0xc0,      /**< Link Control */
00168         FC_R_CTL_EXT_ROUTE = 0xf0,      /**< Extended Routing */
00169 };
00170 
00171 /** Fibre Channel Routing Control Routing mask */
00172 #define FC_R_CTL_ROUTING_MASK 0xf0
00173 
00174 /** Fibre Channel Routing Control Information */
00175 enum fc_r_ctl_info {
00176         FC_R_CTL_UNCAT = 0x00,          /**< Uncategorized */
00177         FC_R_CTL_SOL_DATA = 0x01,       /**< Solicited Data */
00178         FC_R_CTL_UNSOL_CTRL = 0x02,     /**< Unsolicited Control */
00179         FC_R_CTL_SOL_CTRL = 0x03,       /**< Solicited Control */
00180         FC_R_CTL_UNSOL_DATA = 0x04,     /**< Unsolicited Data */
00181         FC_R_CTL_DATA_DESC = 0x05,      /**< Data Descriptor */
00182         FC_R_CTL_UNSOL_CMD = 0x06,      /**< Unsolicited Command */
00183         FC_R_CTL_CMD_STAT = 0x07,       /**< Command Status */
00184 };
00185 
00186 /** Fibre Channel Routing Control Information mask */
00187 #define FC_R_CTL_INFO_MASK 0x07
00188 
00189 /** Fibre Channel Data Structure Type */
00190 enum fc_type {
00191         FC_TYPE_BLS = 0x00,             /**< Basic Link Service */
00192         FC_TYPE_ELS = 0x01,             /**< Extended Link Service */
00193         FC_TYPE_FCP = 0x08,             /**< Fibre Channel Protocol */
00194         FC_TYPE_CT  = 0x20,             /**< Common Transport */
00195 };
00196 
00197 /** Fibre Channel Frame Control - Exchange and Sequence */
00198 enum fc_f_ctl_es {
00199         FC_F_CTL_ES_RESPONDER = 0x80,   /**< Responder of Exchange */
00200         FC_F_CTL_ES_RECIPIENT = 0x40,   /**< Sequence Recipient */
00201         FC_F_CTL_ES_FIRST = 0x20,       /**< First Sequence of Exchange */
00202         FC_F_CTL_ES_LAST = 0x10,        /**< Last Sequence of Exchange */
00203         FC_F_CTL_ES_END = 0x08,         /**< Last Data Frame of Sequence */
00204         FC_F_CTL_ES_TRANSFER = 0x01,    /**< Transfer Sequence Initiative */
00205 };
00206 
00207 /** Fibre Channel Frame Control - Miscellaneous */
00208 enum fc_f_ctl_misc {
00209         FC_F_CTL_MISC_REL_OFF = 0x08,   /**< Relative Offset Present */
00210 };
00211 
00212 /** Responder exchange identifier used before first response */
00213 #define FC_RX_ID_UNKNOWN 0xffff
00214 
00215 struct fc_port;
00216 
00217 extern int fc_xchg_originate ( struct interface *parent, struct fc_port *port,
00218                                struct fc_port_id *peer_port_id,
00219                                unsigned int type );
00220 
00221 /** A Fibre Channel responder */
00222 struct fc_responder {
00223         /** Type */
00224         unsigned int type;
00225         /** Respond to exchange
00226          *
00227          * @v xchg              Exchange interface
00228          * @v port              Fibre Channel port
00229          * @v port_id           Local port ID
00230          * @v peer_port_id      Peer port ID
00231          * @ret rc              Return status code
00232          */
00233         int ( * respond ) ( struct interface *xchg, struct fc_port *port,
00234                             struct fc_port_id *port_id,
00235                             struct fc_port_id *peer_port_id );
00236 };
00237 
00238 /** Fibre Channel responder table */
00239 #define FC_RESPONDERS __table ( struct fc_responder, "fc_responders" )
00240 
00241 /** Declare a Fibre Channel responder */
00242 #define __fc_responder __table_entry ( FC_RESPONDERS, 01 )
00243 
00244 /******************************************************************************
00245  *
00246  * Fibre Channel ports
00247  *
00248  ******************************************************************************
00249  */
00250 
00251 /** A Fibre Channel port */
00252 struct fc_port {
00253         /** Reference count */
00254         struct refcnt refcnt;
00255         /** List of all ports */
00256         struct list_head list;
00257         /** Name of this port */
00258         char name[8];
00259 
00260         /** Transport interface */
00261         struct interface transport;
00262         /** Node name */
00263         struct fc_name node_wwn;
00264         /** Port name */
00265         struct fc_name port_wwn;
00266         /** Local port ID */
00267         struct fc_port_id port_id;
00268         /** Flags */
00269         unsigned int flags;
00270 
00271         /** Link state monitor */
00272         struct fc_link_state link;
00273         /** FLOGI interface */
00274         struct interface flogi;
00275         /** Link node name */
00276         struct fc_name link_node_wwn;
00277         /** Link port name */
00278         struct fc_name link_port_wwn;
00279         /** Link port ID (for point-to-point links only) */
00280         struct fc_port_id ptp_link_port_id;
00281 
00282         /** Name server PLOGI interface */
00283         struct interface ns_plogi;
00284 
00285         /** List of active exchanges */
00286         struct list_head xchgs;
00287 };
00288 
00289 /** Fibre Channel port flags */
00290 enum fc_port_flags {
00291         /** Port is attached to a fabric */
00292         FC_PORT_HAS_FABRIC = 0x0001,
00293         /** Port is logged in to a name server */
00294         FC_PORT_HAS_NS = 0x0002,
00295 };
00296 
00297 /**
00298  * Get reference to Fibre Channel port
00299  *
00300  * @v port              Fibre Channel port
00301  * @ret port            Fibre Channel port
00302  */
00303 static inline __attribute__ (( always_inline )) struct fc_port *
00304 fc_port_get ( struct fc_port *port ) {
00305         ref_get ( &port->refcnt );
00306         return port;
00307 }
00308 
00309 /**
00310  * Drop reference to Fibre Channel port
00311  *
00312  * @v port              Fibre Channel port
00313  */
00314 static inline __attribute__ (( always_inline )) void
00315 fc_port_put ( struct fc_port *port ) {
00316         ref_put ( &port->refcnt );
00317 }
00318 
00319 extern struct list_head fc_ports;
00320 
00321 extern int fc_port_login ( struct fc_port *port, struct fc_port_id *port_id,
00322                            const struct fc_name *link_node_wwn,
00323                            const struct fc_name *link_port_wwn,
00324                            int has_fabric );
00325 extern void fc_port_logout ( struct fc_port *port, int rc );
00326 extern int fc_port_open ( struct interface *transport,
00327                           const struct fc_name *node_wwn,
00328                           const struct fc_name *port_wwn,
00329                           const char *name );
00330 extern struct fc_port * fc_port_find ( const char *name );
00331 
00332 /******************************************************************************
00333  *
00334  * Fibre Channel peers
00335  *
00336  ******************************************************************************
00337  */
00338 
00339 /** A Fibre Channel peer */
00340 struct fc_peer {
00341         /** Reference count */
00342         struct refcnt refcnt;
00343         /** List of all peers */
00344         struct list_head list;
00345 
00346         /** Port name */
00347         struct fc_name port_wwn;
00348 
00349         /** Link state monitor */
00350         struct fc_link_state link;
00351         /** PLOGI interface */
00352         struct interface plogi;
00353         /** Fibre Channel port, if known */
00354         struct fc_port *port;
00355         /** Peer port ID, if known */
00356         struct fc_port_id port_id;
00357 
00358         /** List of upper-layer protocols */
00359         struct list_head ulps;
00360         /** Active usage count
00361          *
00362          * A peer (and attached ULPs) may be created in response to
00363          * unsolicited login requests received via the fabric.  We
00364          * track our own active usage count independently of the
00365          * existence of the peer, so that if the peer becomes logged
00366          * out (e.g. due to a link failure) then we know whether or
00367          * not we should attempt to relogin.
00368          */
00369         unsigned int usage;
00370 };
00371 
00372 /**
00373  * Get reference to Fibre Channel peer
00374  *
00375  * @v peer              Fibre Channel peer
00376  * @ret peer            Fibre Channel peer
00377  */
00378 static inline __attribute__ (( always_inline )) struct fc_peer *
00379 fc_peer_get ( struct fc_peer *peer ) {
00380         ref_get ( &peer->refcnt );
00381         return peer;
00382 }
00383 
00384 /**
00385  * Drop reference to Fibre Channel peer
00386  *
00387  * @v peer              Fibre Channel peer
00388  */
00389 static inline __attribute__ (( always_inline )) void
00390 fc_peer_put ( struct fc_peer *peer ) {
00391         ref_put ( &peer->refcnt );
00392 }
00393 
00394 extern struct list_head fc_peers;
00395 
00396 extern struct fc_peer * fc_peer_get_wwn ( const struct fc_name *port_wwn );
00397 extern struct fc_peer *
00398 fc_peer_get_port_id ( struct fc_port *port,
00399                       const struct fc_port_id *peer_port_id );
00400 extern int fc_peer_login ( struct fc_peer *peer,
00401                            struct fc_port *port,
00402                            struct fc_port_id *port_id );
00403 extern void fc_peer_logout ( struct fc_peer *peer, int rc );
00404 
00405 /******************************************************************************
00406  *
00407  * Fibre Channel upper-layer protocols
00408  *
00409  ******************************************************************************
00410  */
00411 
00412 /** A Fibre Channel upper-layer protocol */
00413 struct fc_ulp {
00414         /** Reference count */
00415         struct refcnt refcnt;
00416         /** Fibre Channel peer */
00417         struct fc_peer *peer;
00418         /** List of upper-layer protocols */
00419         struct list_head list;
00420 
00421         /** Type */
00422         unsigned int type;
00423         /** Flags */
00424         unsigned int flags;
00425 
00426         /** Link state monitor */
00427         struct fc_link_state link;
00428         /** PRLI interface */
00429         struct interface prli;
00430         /** Service parameters, if any */
00431         void *param;
00432         /** Service parameter length */
00433         size_t param_len;
00434 
00435         /** Active users of this upper-layer protocol
00436          *
00437          * As with peers, an upper-layer protocol may be created in
00438          * response to an unsolicited login request received via the
00439          * fabric.  This list records the number of active users of
00440          * the ULP; the number of entries in the list is equivalent to
00441          * the peer usage count.
00442          */
00443         struct list_head users;
00444 };
00445 
00446 /** Fibre Channel upper-layer protocol flags */
00447 enum fc_ulp_flags {
00448         /** A login originated by us has succeeded */
00449         FC_ULP_ORIGINATED_LOGIN_OK = 0x0001,
00450 };
00451 
00452 /** A Fibre Channel upper-layer protocol user */
00453 struct fc_ulp_user {
00454         /** Fibre Channel upper layer protocol */
00455         struct fc_ulp *ulp;
00456         /** List of users */
00457         struct list_head list;
00458         /** Containing object reference count, or NULL */
00459         struct refcnt *refcnt;
00460         /** Examine link state
00461          *
00462          * @v user              Fibre Channel upper-layer-protocol user
00463          */
00464         void ( * examine ) ( struct fc_ulp_user *user );
00465 };
00466 
00467 /**
00468  * Get reference to Fibre Channel upper-layer protocol
00469  *
00470  * @v ulp               Fibre Channel upper-layer protocol
00471  * @ret ulp             Fibre Channel upper-layer protocol
00472  */
00473 static inline __attribute__ (( always_inline )) struct fc_ulp *
00474 fc_ulp_get ( struct fc_ulp *ulp ) {
00475         ref_get ( &ulp->refcnt );
00476         return ulp;
00477 }
00478 
00479 /**
00480  * Drop reference to Fibre Channel upper-layer protocol
00481  *
00482  * @v ulp               Fibre Channel upper-layer protocol
00483  */
00484 static inline __attribute__ (( always_inline )) void
00485 fc_ulp_put ( struct fc_ulp *ulp ) {
00486         ref_put ( &ulp->refcnt );
00487 }
00488 
00489 /**
00490  * Get reference to Fibre Channel upper-layer protocol user
00491  *
00492  * @v user              Fibre Channel upper-layer protocol user
00493  * @ret user            Fibre Channel upper-layer protocol user
00494  */
00495 static inline __attribute__ (( always_inline )) struct fc_ulp_user *
00496 fc_ulp_user_get ( struct fc_ulp_user *user ) {
00497         ref_get ( user->refcnt );
00498         return user;
00499 }
00500 
00501 /**
00502  * Drop reference to Fibre Channel upper-layer protocol user
00503  *
00504  * @v user              Fibre Channel upper-layer protocol user
00505  */
00506 static inline __attribute__ (( always_inline )) void
00507 fc_ulp_user_put ( struct fc_ulp_user *user ) {
00508         ref_put ( user->refcnt );
00509 }
00510 
00511 /**
00512  * Initialise Fibre Channel upper-layer protocol user
00513  *
00514  * @v user              Fibre Channel upper-layer protocol user
00515  * @v examine           Examine link state method
00516  * @v refcnt            Containing object reference count, or NULL
00517  */
00518 static inline __attribute__ (( always_inline )) void
00519 fc_ulp_user_init ( struct fc_ulp_user *user,
00520                    void ( * examine ) ( struct fc_ulp_user *user ),
00521                    struct refcnt *refcnt ) {
00522         user->examine = examine;
00523         user->refcnt = refcnt;
00524 }
00525 
00526 extern struct fc_ulp * fc_ulp_get_wwn_type ( const struct fc_name *port_wwn,
00527                                              unsigned int type );
00528 extern struct fc_ulp *
00529 fc_ulp_get_port_id_type ( struct fc_port *port,
00530                           const struct fc_port_id *peer_port_id,
00531                           unsigned int type );
00532 extern void fc_ulp_attach ( struct fc_ulp *ulp, struct fc_ulp_user *user );
00533 extern void fc_ulp_detach ( struct fc_ulp_user *user );
00534 extern int fc_ulp_login ( struct fc_ulp *ulp, const void *param,
00535                           size_t param_len, int originated );
00536 extern void fc_ulp_logout ( struct fc_ulp *ulp, int rc );
00537 
00538 #endif /* _IPXE_FC_H */