X-Git-Url: https://gerrit.opnfv.org/gerrit/gitweb?a=blobdiff_plain;f=qemu%2Froms%2Fipxe%2Fsrc%2Finclude%2Fipxe%2Ffc.h;fp=qemu%2Froms%2Fipxe%2Fsrc%2Finclude%2Fipxe%2Ffc.h;h=6fdef092dad2a977f486214e4c5573d28c0b7b1e;hb=e44e3482bdb4d0ebde2d8b41830ac2cdb07948fb;hp=0000000000000000000000000000000000000000;hpb=9ca8dbcc65cfc63d6f5ef3312a33184e1d726e00;p=kvmfornfv.git diff --git a/qemu/roms/ipxe/src/include/ipxe/fc.h b/qemu/roms/ipxe/src/include/ipxe/fc.h new file mode 100644 index 000000000..6fdef092d --- /dev/null +++ b/qemu/roms/ipxe/src/include/ipxe/fc.h @@ -0,0 +1,538 @@ +#ifndef _IPXE_FC_H +#define _IPXE_FC_H + +/** + * @file + * + * Fibre Channel + * + */ + +FILE_LICENCE ( GPL2_OR_LATER ); + +#include +#include +#include +#include +#include +#include +#include + +/****************************************************************************** + * + * Fibre Channel Names and identifiers + * + ****************************************************************************** + */ + +/** A Fibre Channel name */ +struct fc_name { + uint8_t bytes[8]; +} __attribute__ (( packed )); + +/** Length of Fibre Channel name text */ +#define FC_NAME_STRLEN 23 /* "xx:xx:xx:xx:xx:xx:xx:xx" */ + +/** A Fibre Channel port identifier */ +struct fc_port_id { + uint8_t bytes[3]; +} __attribute__ (( packed )); + +/** Length of Fibre Channel port identifier next */ +#define FC_PORT_ID_STRLEN 9 /* "xx.xx.xx" */ + +/** + * Fibre Channel socket address + */ +struct sockaddr_fc { + /** Socket address family (part of struct @c sockaddr) + * + * Always set to @c AF_FC for Fibre Channel addresses + */ + sa_family_t sfc_family; + /** Port ID */ + struct fc_port_id sfc_port_id; + /** Padding + * + * This ensures that a struct @c sockaddr_tcpip is large + * enough to hold a socket address for any TCP/IP address + * family. + */ + char pad[ sizeof ( struct sockaddr ) - sizeof ( sa_family_t ) + - sizeof ( struct fc_port_id ) ]; +} __attribute__ (( packed, may_alias )); + +extern struct fc_port_id fc_empty_port_id; +extern struct fc_port_id fc_f_port_id; +extern struct fc_port_id fc_gs_port_id; +extern struct fc_port_id fc_ptp_low_port_id; +extern struct fc_port_id fc_ptp_high_port_id; + +extern const char * fc_id_ntoa ( const struct fc_port_id *id ); +extern int fc_id_aton ( const char *id_text, struct fc_port_id *id ); +extern const char * fc_ntoa ( const struct fc_name *wwn ); +extern int fc_aton ( const char *wwn_text, struct fc_name *wwn ); +extern struct sockaddr * fc_fill_sockaddr ( struct sockaddr_fc *sa_fc, + struct fc_port_id *id ); + +/****************************************************************************** + * + * Fibre Channel link state + * + ****************************************************************************** + */ + +/** Delay between failed link-up attempts */ +#define FC_LINK_RETRY_DELAY ( 2 * TICKS_PER_SEC ) + +/** A Fibre Channel link state nonitor */ +struct fc_link_state { + /** Retry timer */ + struct retry_timer timer; + /** Link state */ + int rc; + /** Examine link state + * + * @v link Fibre Channel link state monitor + */ + void ( * examine ) ( struct fc_link_state *link ); +}; + +/** + * Check Fibre Channel link state + * + * @v link Fibre Channel link state monitor + * @ret link_up Link is up + */ +static inline __attribute__ (( always_inline )) int +fc_link_ok ( struct fc_link_state *link ) { + return ( link->rc == 0 ); +} + +/****************************************************************************** + * + * Fibre Channel packet formats and exchanges + * + ****************************************************************************** + */ + +/** A Fibre Channel Frame Header */ +struct fc_frame_header { + /** Routing control + * + * This is the bitwise OR of one @c fc_r_ctl_routing value and + * one @c fc_r_ctl_info value. + */ + uint8_t r_ctl; + /** Destination ID */ + struct fc_port_id d_id; + /** Class-specific control / Priority */ + uint8_t cs_ctl_prio; + /** Source ID */ + struct fc_port_id s_id; + /** Data structure type */ + uint8_t type; + /** Frame control - exchange and sequence */ + uint8_t f_ctl_es; + /** Frame control - acknowledgements */ + uint8_t f_ctl_ack; + /** Frame control - miscellaneous */ + uint8_t f_ctl_misc; + /** Sequence ID */ + uint8_t seq_id; + /** Data field control */ + uint8_t df_ctl; + /** Sequence count */ + uint16_t seq_cnt; + /** Originator exchange ID */ + uint16_t ox_id; + /** Responder exchange ID */ + uint16_t rx_id; + /** Parameter + * + * Contains the relative offset when @c FC_F_CTL_MISC_REL_OFF + * is set. + */ + uint32_t parameter; +} __attribute__ (( packed )); + +/** Fibre Channel Routing Control Routing */ +enum fc_r_ctl_routing { + FC_R_CTL_DATA = 0x00, /**< Device Data */ + FC_R_CTL_ELS = 0x20, /**< Extended Link Services */ + FC_R_CTL_FC4_LINK = 0x30, /**< FC-4 Link Data */ + FC_R_CTL_VIDEO = 0x40, /**< Video Data */ + FC_R_CTL_EH = 0x50, /**< Extended Headers */ + FC_R_CTL_BLS = 0x80, /**< Basic Link Services */ + FC_R_CTL_LINK_CTRL = 0xc0, /**< Link Control */ + FC_R_CTL_EXT_ROUTE = 0xf0, /**< Extended Routing */ +}; + +/** Fibre Channel Routing Control Routing mask */ +#define FC_R_CTL_ROUTING_MASK 0xf0 + +/** Fibre Channel Routing Control Information */ +enum fc_r_ctl_info { + FC_R_CTL_UNCAT = 0x00, /**< Uncategorized */ + FC_R_CTL_SOL_DATA = 0x01, /**< Solicited Data */ + FC_R_CTL_UNSOL_CTRL = 0x02, /**< Unsolicited Control */ + FC_R_CTL_SOL_CTRL = 0x03, /**< Solicited Control */ + FC_R_CTL_UNSOL_DATA = 0x04, /**< Unsolicited Data */ + FC_R_CTL_DATA_DESC = 0x05, /**< Data Descriptor */ + FC_R_CTL_UNSOL_CMD = 0x06, /**< Unsolicited Command */ + FC_R_CTL_CMD_STAT = 0x07, /**< Command Status */ +}; + +/** Fibre Channel Routing Control Information mask */ +#define FC_R_CTL_INFO_MASK 0x07 + +/** Fibre Channel Data Structure Type */ +enum fc_type { + FC_TYPE_BLS = 0x00, /**< Basic Link Service */ + FC_TYPE_ELS = 0x01, /**< Extended Link Service */ + FC_TYPE_FCP = 0x08, /**< Fibre Channel Protocol */ + FC_TYPE_CT = 0x20, /**< Common Transport */ +}; + +/** Fibre Channel Frame Control - Exchange and Sequence */ +enum fc_f_ctl_es { + FC_F_CTL_ES_RESPONDER = 0x80, /**< Responder of Exchange */ + FC_F_CTL_ES_RECIPIENT = 0x40, /**< Sequence Recipient */ + FC_F_CTL_ES_FIRST = 0x20, /**< First Sequence of Exchange */ + FC_F_CTL_ES_LAST = 0x10, /**< Last Sequence of Exchange */ + FC_F_CTL_ES_END = 0x08, /**< Last Data Frame of Sequence */ + FC_F_CTL_ES_TRANSFER = 0x01, /**< Transfer Sequence Initiative */ +}; + +/** Fibre Channel Frame Control - Miscellaneous */ +enum fc_f_ctl_misc { + FC_F_CTL_MISC_REL_OFF = 0x08, /**< Relative Offset Present */ +}; + +/** Responder exchange identifier used before first response */ +#define FC_RX_ID_UNKNOWN 0xffff + +struct fc_port; + +extern int fc_xchg_originate ( struct interface *parent, struct fc_port *port, + struct fc_port_id *peer_port_id, + unsigned int type ); + +/** A Fibre Channel responder */ +struct fc_responder { + /** Type */ + unsigned int type; + /** Respond to exchange + * + * @v xchg Exchange interface + * @v port Fibre Channel port + * @v port_id Local port ID + * @v peer_port_id Peer port ID + * @ret rc Return status code + */ + int ( * respond ) ( struct interface *xchg, struct fc_port *port, + struct fc_port_id *port_id, + struct fc_port_id *peer_port_id ); +}; + +/** Fibre Channel responder table */ +#define FC_RESPONDERS __table ( struct fc_responder, "fc_responders" ) + +/** Declare a Fibre Channel responder */ +#define __fc_responder __table_entry ( FC_RESPONDERS, 01 ) + +/****************************************************************************** + * + * Fibre Channel ports + * + ****************************************************************************** + */ + +/** A Fibre Channel port */ +struct fc_port { + /** Reference count */ + struct refcnt refcnt; + /** List of all ports */ + struct list_head list; + /** Name of this port */ + char name[8]; + + /** Transport interface */ + struct interface transport; + /** Node name */ + struct fc_name node_wwn; + /** Port name */ + struct fc_name port_wwn; + /** Local port ID */ + struct fc_port_id port_id; + /** Flags */ + unsigned int flags; + + /** Link state monitor */ + struct fc_link_state link; + /** FLOGI interface */ + struct interface flogi; + /** Link node name */ + struct fc_name link_node_wwn; + /** Link port name */ + struct fc_name link_port_wwn; + /** Link port ID (for point-to-point links only) */ + struct fc_port_id ptp_link_port_id; + + /** Name server PLOGI interface */ + struct interface ns_plogi; + + /** List of active exchanges */ + struct list_head xchgs; +}; + +/** Fibre Channel port flags */ +enum fc_port_flags { + /** Port is attached to a fabric */ + FC_PORT_HAS_FABRIC = 0x0001, + /** Port is logged in to a name server */ + FC_PORT_HAS_NS = 0x0002, +}; + +/** + * Get reference to Fibre Channel port + * + * @v port Fibre Channel port + * @ret port Fibre Channel port + */ +static inline __attribute__ (( always_inline )) struct fc_port * +fc_port_get ( struct fc_port *port ) { + ref_get ( &port->refcnt ); + return port; +} + +/** + * Drop reference to Fibre Channel port + * + * @v port Fibre Channel port + */ +static inline __attribute__ (( always_inline )) void +fc_port_put ( struct fc_port *port ) { + ref_put ( &port->refcnt ); +} + +extern struct list_head fc_ports; + +extern int fc_port_login ( struct fc_port *port, struct fc_port_id *port_id, + const struct fc_name *link_node_wwn, + const struct fc_name *link_port_wwn, + int has_fabric ); +extern void fc_port_logout ( struct fc_port *port, int rc ); +extern int fc_port_open ( struct interface *transport, + const struct fc_name *node_wwn, + const struct fc_name *port_wwn, + const char *name ); +extern struct fc_port * fc_port_find ( const char *name ); + +/****************************************************************************** + * + * Fibre Channel peers + * + ****************************************************************************** + */ + +/** A Fibre Channel peer */ +struct fc_peer { + /** Reference count */ + struct refcnt refcnt; + /** List of all peers */ + struct list_head list; + + /** Port name */ + struct fc_name port_wwn; + + /** Link state monitor */ + struct fc_link_state link; + /** PLOGI interface */ + struct interface plogi; + /** Fibre Channel port, if known */ + struct fc_port *port; + /** Peer port ID, if known */ + struct fc_port_id port_id; + + /** List of upper-layer protocols */ + struct list_head ulps; + /** Active usage count + * + * A peer (and attached ULPs) may be created in response to + * unsolicited login requests received via the fabric. We + * track our own active usage count independently of the + * existence of the peer, so that if the peer becomes logged + * out (e.g. due to a link failure) then we know whether or + * not we should attempt to relogin. + */ + unsigned int usage; +}; + +/** + * Get reference to Fibre Channel peer + * + * @v peer Fibre Channel peer + * @ret peer Fibre Channel peer + */ +static inline __attribute__ (( always_inline )) struct fc_peer * +fc_peer_get ( struct fc_peer *peer ) { + ref_get ( &peer->refcnt ); + return peer; +} + +/** + * Drop reference to Fibre Channel peer + * + * @v peer Fibre Channel peer + */ +static inline __attribute__ (( always_inline )) void +fc_peer_put ( struct fc_peer *peer ) { + ref_put ( &peer->refcnt ); +} + +extern struct list_head fc_peers; + +extern struct fc_peer * fc_peer_get_wwn ( const struct fc_name *port_wwn ); +extern struct fc_peer * +fc_peer_get_port_id ( struct fc_port *port, + const struct fc_port_id *peer_port_id ); +extern int fc_peer_login ( struct fc_peer *peer, + struct fc_port *port, + struct fc_port_id *port_id ); +extern void fc_peer_logout ( struct fc_peer *peer, int rc ); + +/****************************************************************************** + * + * Fibre Channel upper-layer protocols + * + ****************************************************************************** + */ + +/** A Fibre Channel upper-layer protocol */ +struct fc_ulp { + /** Reference count */ + struct refcnt refcnt; + /** Fibre Channel peer */ + struct fc_peer *peer; + /** List of upper-layer protocols */ + struct list_head list; + + /** Type */ + unsigned int type; + /** Flags */ + unsigned int flags; + + /** Link state monitor */ + struct fc_link_state link; + /** PRLI interface */ + struct interface prli; + /** Service parameters, if any */ + void *param; + /** Service parameter length */ + size_t param_len; + + /** Active users of this upper-layer protocol + * + * As with peers, an upper-layer protocol may be created in + * response to an unsolicited login request received via the + * fabric. This list records the number of active users of + * the ULP; the number of entries in the list is equivalent to + * the peer usage count. + */ + struct list_head users; +}; + +/** Fibre Channel upper-layer protocol flags */ +enum fc_ulp_flags { + /** A login originated by us has succeeded */ + FC_ULP_ORIGINATED_LOGIN_OK = 0x0001, +}; + +/** A Fibre Channel upper-layer protocol user */ +struct fc_ulp_user { + /** Fibre Channel upper layer protocol */ + struct fc_ulp *ulp; + /** List of users */ + struct list_head list; + /** Containing object reference count, or NULL */ + struct refcnt *refcnt; + /** Examine link state + * + * @v user Fibre Channel upper-layer-protocol user + */ + void ( * examine ) ( struct fc_ulp_user *user ); +}; + +/** + * Get reference to Fibre Channel upper-layer protocol + * + * @v ulp Fibre Channel upper-layer protocol + * @ret ulp Fibre Channel upper-layer protocol + */ +static inline __attribute__ (( always_inline )) struct fc_ulp * +fc_ulp_get ( struct fc_ulp *ulp ) { + ref_get ( &ulp->refcnt ); + return ulp; +} + +/** + * Drop reference to Fibre Channel upper-layer protocol + * + * @v ulp Fibre Channel upper-layer protocol + */ +static inline __attribute__ (( always_inline )) void +fc_ulp_put ( struct fc_ulp *ulp ) { + ref_put ( &ulp->refcnt ); +} + +/** + * Get reference to Fibre Channel upper-layer protocol user + * + * @v user Fibre Channel upper-layer protocol user + * @ret user Fibre Channel upper-layer protocol user + */ +static inline __attribute__ (( always_inline )) struct fc_ulp_user * +fc_ulp_user_get ( struct fc_ulp_user *user ) { + ref_get ( user->refcnt ); + return user; +} + +/** + * Drop reference to Fibre Channel upper-layer protocol user + * + * @v user Fibre Channel upper-layer protocol user + */ +static inline __attribute__ (( always_inline )) void +fc_ulp_user_put ( struct fc_ulp_user *user ) { + ref_put ( user->refcnt ); +} + +/** + * Initialise Fibre Channel upper-layer protocol user + * + * @v user Fibre Channel upper-layer protocol user + * @v examine Examine link state method + * @v refcnt Containing object reference count, or NULL + */ +static inline __attribute__ (( always_inline )) void +fc_ulp_user_init ( struct fc_ulp_user *user, + void ( * examine ) ( struct fc_ulp_user *user ), + struct refcnt *refcnt ) { + user->examine = examine; + user->refcnt = refcnt; +} + +extern struct fc_ulp * fc_ulp_get_wwn_type ( const struct fc_name *port_wwn, + unsigned int type ); +extern struct fc_ulp * +fc_ulp_get_port_id_type ( struct fc_port *port, + const struct fc_port_id *peer_port_id, + unsigned int type ); +extern void fc_ulp_attach ( struct fc_ulp *ulp, struct fc_ulp_user *user ); +extern void fc_ulp_detach ( struct fc_ulp_user *user ); +extern int fc_ulp_login ( struct fc_ulp *ulp, const void *param, + size_t param_len, int originated ); +extern void fc_ulp_logout ( struct fc_ulp *ulp, int rc ); + +#endif /* _IPXE_FC_H */