--- /dev/null
+#ifndef _IPXE_FCNS_H
+#define _IPXE_FCNS_H
+
+/**
+ * @file
+ *
+ * Fibre Channel name server lookups
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <stdint.h>
+#include <ipxe/fc.h>
+
+/** A Fibre Channel Common Transport header */
+struct fc_ct_header {
+ /** Revision */
+ uint8_t revision;
+ /** Original requestor ID */
+ struct fc_port_id in_id;
+ /** Generic service type */
+ uint8_t type;
+ /** Generic service subtype */
+ uint8_t subtype;
+ /** Options */
+ uint8_t options;
+ /** Reserved */
+ uint8_t reserved;
+ /** Command/response code */
+ uint16_t code;
+ /** Maximum/residual size */
+ uint16_t size;
+ /** Fragment ID */
+ uint8_t fragment;
+ /** Reason code */
+ uint8_t reason;
+ /** Reason code explanation */
+ uint8_t explanation;
+ /** Vendor specific */
+ uint8_t vendor;
+} __attribute__ (( packed ));
+
+/** Fibre Channel Common Transport revision */
+#define FC_CT_REVISION 1
+
+/** Fibre Channel generic service type */
+enum fc_gs_type {
+ /** Directory service */
+ FC_GS_TYPE_DS = 0xfc,
+};
+
+/** Fibre Channel generic service response codes */
+enum fc_gs_response_code {
+ /** Accepted */
+ FC_GS_ACCEPT = 0x8002,
+ /** Rejected */
+ FC_GS_REJECT = 0x8001,
+};
+
+/** Fibre Channel generic service rejection reason codes */
+enum fc_gs_reason_code {
+ /** Invalid command code */
+ FC_GS_BAD_COMMAND = 0x01,
+ /** Invalid version level */
+ FC_GS_BAD_VERSION = 0x02,
+ /** Logical error */
+ FC_GS_ERROR = 0x03,
+ /** Invalid CT_IU size */
+ FC_GS_BAD_SIZE = 0x04,
+ /** Logical busy */
+ FC_GS_BUSY = 0x05,
+ /** Protocol error */
+ FC_GS_EPROTO = 0x07,
+ /** Unable to perform command request */
+ FC_GS_UNABLE = 0x09,
+ /** Command not supported */
+ FC_GS_ENOTSUP = 0x0b,
+ /** Server not available */
+ FC_GS_UNAVAILABLE = 0x0d,
+ /** Session could not be established */
+ FC_GS_SESSION = 0x0e,
+};
+
+/** Fibre Channel directory service subtype */
+enum fc_ds_subtype {
+ /** Name server */
+ FC_DS_SUBTYPE_NAME = 0x02,
+};
+
+/** Fibre Channel name server commands */
+enum fc_ns_command_nibble {
+ /** Get */
+ FC_NS_GET = 0x1,
+ /** Register */
+ FC_NS_REGISTER = 0x2,
+ /** De-register */
+ FC_NS_DEREGISTER = 0x3,
+};
+
+/** Fibre Channel name server objects */
+enum fc_ns_object_nibble {
+ /** Port ID */
+ FC_NS_PORT_ID = 0x1,
+ /** Port name */
+ FC_NS_PORT_NAME = 0x2,
+ /** Node name */
+ FC_NS_NODE_NAME = 0x3,
+ /** FC-4 types */
+ FC_NS_FC4_TYPES = 0x7,
+ /** Symbolic port name */
+ FC_NS_SYM_PORT_NAME = 0x8,
+ /** Symbolic node name */
+ FC_NS_SYM_NODE_NAME = 0x9,
+ /** FC-4 features */
+ FC_NS_FC4_FEATURES = 0xf,
+};
+
+/** Construct Fibre Channel name server command code
+ *
+ * @v command Name server command
+ * @v key Name server key
+ * @v value Name server value
+ * @ret code Name server command code
+ */
+#define FC_NS_CODE( command, key, value ) \
+ ( ( (command) << 8 ) | ( (key) << 4 ) | ( (value) << 0 ) )
+
+/** Construct Fibre Channel name server "get" command code
+ *
+ * @v key Name server key
+ * @v value Name server value to get
+ * @ret code Name server command code
+ */
+#define FC_NS_GET( key, value ) FC_NS_CODE ( FC_NS_GET, key, value )
+
+/** Construct Fibre Channel name server "register" command code
+ *
+ * @v key Name server key
+ * @v value Name server value to register
+ * @ret code Name server command code
+ */
+#define FC_NS_REGISTER( key, value ) FC_NS_CODE ( FC_NS_REGISTER, key, value )
+
+/** Extract Fibre Channel name server command
+ *
+ * @v code Name server command code
+ * @ret command Name server command
+ */
+#define FC_NS_COMMAND( code ) ( ( (code) >> 8 ) & 0xf )
+
+/** Extract Fibre Channel name server key
+ *
+ * @v code Name server command code
+ * @ret key Name server key
+ */
+#define FC_NS_KEY( code ) ( ( (code) >> 4 ) & 0xf )
+
+/** Extract Fibre Channel name server value
+ *
+ * @v code Name server command code
+ * @ret value NAme server value
+ */
+#define FC_NS_VALUE( code ) ( ( (code) >> 0 ) & 0xf )
+
+/** A Fibre Channel name server port ID */
+struct fc_ns_port_id {
+ /** Reserved */
+ uint8_t reserved;
+ /** Port ID */
+ struct fc_port_id port_id;
+} __attribute__ (( packed ));
+
+/** A Fibre Channel name server GID_PN request */
+struct fc_ns_gid_pn_request {
+ /** Common Transport header */
+ struct fc_ct_header ct;
+ /** Port name */
+ struct fc_name port_wwn;
+} __attribute__ (( packed ));
+
+/** A Fibre Channel name server request */
+union fc_ns_request {
+ /** Get ID by port name */
+ struct fc_ns_gid_pn_request gid_pn;
+};
+
+/** A Fibre Channel name server rejection response */
+struct fc_ns_reject_response {
+ /** Common Transport header */
+ struct fc_ct_header ct;
+} __attribute__ (( packed ));
+
+/** A Fibre Channel name server GID_PN response */
+struct fc_ns_gid_pn_response {
+ /** Common Transport header */
+ struct fc_ct_header ct;
+ /** Port ID */
+ struct fc_ns_port_id port_id;
+} __attribute__ (( packed ));
+
+/** A Fibre Channel name server response */
+union fc_ns_response {
+ /** Common Transport header */
+ struct fc_ct_header ct;
+ /** Rejection */
+ struct fc_ns_reject_response reject;
+ /** Get ID by port name */
+ struct fc_ns_gid_pn_response gid_pn;
+};
+
+extern int fc_ns_query ( struct fc_peer *peer, struct fc_port *port,
+ int ( * done ) ( struct fc_peer *peer,
+ struct fc_port *port,
+ struct fc_port_id *peer_port_id ) );
+
+#endif /* _IPXE_FCNS_H */