| #ifndef _IPXE_FCELS_H | |
| #define _IPXE_FCELS_H | |
| /** | |
| * @file | |
| * | |
| * Fibre Channel Extended Link Services | |
| * | |
| */ | |
| FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL ); | |
| FILE_SECBOOT ( PERMITTED ); | |
| #include <stdint.h> | |
| #include <ipxe/fc.h> | |
| #include <ipxe/tables.h> | |
| #include <ipxe/refcnt.h> | |
| #include <ipxe/list.h> | |
| #include <ipxe/process.h> | |
| #include <ipxe/interface.h> | |
| /** Fibre Channel ELS frame common parameters */ | |
| struct fc_els_frame_common { | |
| /** ELS command code */ | |
| uint8_t command; | |
| /** Reserved */ | |
| uint8_t reserved[3]; | |
| } __attribute__ (( packed )); | |
| /** Fibre Channel ELS command codes */ | |
| enum fc_els_command_code { | |
| FC_ELS_LS_RJT = 0x01, /**< Link Service Reject */ | |
| FC_ELS_LS_ACC = 0x02, /**< Link Service Accept */ | |
| FC_ELS_PLOGI = 0x03, /**< Port Login */ | |
| FC_ELS_FLOGI = 0x04, /**< Fabric Login */ | |
| FC_ELS_LOGO = 0x05, /**< Logout */ | |
| FC_ELS_RTV = 0x0e, /**< Read Timeout Value */ | |
| FC_ELS_ECHO = 0x10, /**< Echo */ | |
| FC_ELS_PRLI = 0x20, /**< Process Login */ | |
| FC_ELS_PRLO = 0x21, /**< Process Logout */ | |
| }; | |
| /** A Fibre Channel LS_RJT frame */ | |
| struct fc_ls_rjt_frame { | |
| /** ELS command code */ | |
| uint8_t command; | |
| /** Reserved */ | |
| uint8_t reserved[4]; | |
| /** Reason code */ | |
| uint8_t reason; | |
| /** Reason code explanation */ | |
| uint8_t explanation; | |
| /** Vendor unique */ | |
| uint8_t vendor; | |
| } __attribute__ (( packed )); | |
| /** Fibre Channel ELS rejection reason codes */ | |
| enum fc_els_reject_reason { | |
| /** Invalid ELS command code */ | |
| FC_ELS_RJT_INVALID_COMMAND = 0x01, | |
| /** Logical error */ | |
| FC_ELS_RJT_ILLOGICAL = 0x03, | |
| /** Logical busy */ | |
| FC_ELS_RJT_BUSY = 0x05, | |
| /** Protocol error */ | |
| FC_ELS_RJT_PROTOCOL = 0x07, | |
| /** Unable to perform command request */ | |
| FC_ELS_RJT_UNABLE = 0x09, | |
| /** Command not supported */ | |
| FC_ELS_RJT_UNSUPPORTED = 0x0b, | |
| /** Command already in progress */ | |
| FC_ELS_RJT_IN_PROGRESS = 0x0e, | |
| }; | |
| /** Fibre Channel "common" service parameters */ | |
| struct fc_login_common { | |
| /** Login version */ | |
| uint16_t version; | |
| /** Buffer-to-buffer credit */ | |
| uint16_t credit; | |
| /** Flags */ | |
| uint16_t flags; | |
| /** Receive size */ | |
| uint16_t mtu; | |
| /** "Common"?! */ | |
| union { | |
| struct { | |
| /** Maximum number of concurrent sequences */ | |
| uint16_t max_seq; | |
| /** Relative offset by info category */ | |
| uint16_t rel_offs; | |
| } plogi; | |
| struct { | |
| /** Resource allocation timeout value */ | |
| uint32_t r_a_tov; | |
| } flogi; | |
| } u; | |
| /** Error detection timeout value */ | |
| uint32_t e_d_tov; | |
| } __attribute__ (( packed )); | |
| /** Fibre Channel default login version */ | |
| #define FC_LOGIN_VERSION 0x2020 | |
| /** Fibre Channel default buffer-to-buffer credit */ | |
| #define FC_LOGIN_DEFAULT_B2B 10 | |
| /** Continuously increasing relative offset */ | |
| #define FC_LOGIN_CONTINUOUS_OFFSET 0x8000 | |
| /** Clean address */ | |
| #define FC_LOGIN_CLEAN 0x8000 | |
| /** Multiple N_Port_ID support */ | |
| #define FC_LOGIN_MULTI_N 0x8000 | |
| /** Random relative offset */ | |
| #define FC_LOGIN_RANDOM_OFFSET 0x4000 | |
| /** Virtual fabrics */ | |
| #define FC_LOGIN_VIRTUAL 0x4000 | |
| /** Vendor version level */ | |
| #define FC_LOGIN_VENDOR 0x2000 | |
| /** Multiple N_Port_ID support */ | |
| #define FC_LOGIN_MULTI_F 0x2000 | |
| /** Forwarder port */ | |
| #define FC_LOGIN_F_PORT 0x1000 | |
| /** Alternative credit management */ | |
| #define FC_LOGIN_ALT_CREDIT 0x0800 | |
| /** Name server session started */ | |
| #define FC_LOGIN_NSS_STARTED 0x0800 | |
| /** Begin name server session */ | |
| #define FC_LOGIN_NSS_BEGIN 0x0400 | |
| /** 1ns error detection timer resolution */ | |
| #define FC_LOGIN_HIRES_E_D_TOV 0x0400 | |
| /** Broadcast supported */ | |
| #define FC_LOGIN_BROADCAST 0x0100 | |
| /** Query buffer conditions */ | |
| #define FC_LOGIN_QUERY_BUF 0x0040 | |
| /** Security */ | |
| #define FC_LOGIN_SECURITY 0x0020 | |
| /** Clock sync primitive capable */ | |
| #define FC_LOGIN_CLOCK_SYNC 0x0010 | |
| /** Short R_T timeout */ | |
| #define FC_LOGIN_SHORT_R_T_TOV 0x0008 | |
| /** Dynamic half duplex */ | |
| #define FC_LOGIN_DHD 0x0004 | |
| /** Continuously increasing sequence count */ | |
| #define FC_LOGIN_CONTINUOUS_SEQ 0x0002 | |
| /** Payload */ | |
| #define FC_LOGIN_PAYLOAD 0x0001 | |
| /** Fibre Channel default MTU */ | |
| #define FC_LOGIN_DEFAULT_MTU 1452 | |
| /** Default maximum number of concurrent sequences */ | |
| #define FC_LOGIN_DEFAULT_MAX_SEQ 255 | |
| /** Default relative offset by info category */ | |
| #define FC_LOGIN_DEFAULT_REL_OFFS 0x1f | |
| /** Default E_D timeout value */ | |
| #define FC_LOGIN_DEFAULT_E_D_TOV 2000 | |
| /** Fibre Channel class-specific login parameters */ | |
| struct fc_login_class { | |
| /** Flags */ | |
| uint16_t flags; | |
| /** Initiator flags */ | |
| uint16_t init_flags; | |
| /** Recipient flags */ | |
| uint16_t recip_flags; | |
| /** Receive data field size */ | |
| uint16_t mtu; | |
| /** Maximum number of concurrent sequences */ | |
| uint16_t max_seq; | |
| /** End-to-end credit */ | |
| uint16_t credit; | |
| /** Reserved */ | |
| uint8_t reserved0; | |
| /** Maximum number of open sequences per exchange */ | |
| uint8_t max_seq_per_xchg; | |
| /** Reserved */ | |
| uint8_t reserved1[2]; | |
| } __attribute__ (( packed )); | |
| /** Class valid */ | |
| #define FC_LOGIN_CLASS_VALID 0x8000 | |
| /** Sequential delivery requested */ | |
| #define FC_LOGIN_CLASS_SEQUENTIAL 0x0800 | |
| /** A Fibre Channel FLOGI/PLOGI frame */ | |
| struct fc_login_frame { | |
| /** ELS command code */ | |
| uint8_t command; | |
| /** Reserved */ | |
| uint8_t reserved[3]; | |
| /** Common service parameters */ | |
| struct fc_login_common common; | |
| /** Port name */ | |
| struct fc_name port_wwn; | |
| /** Node name */ | |
| struct fc_name node_wwn; | |
| /** Class 1 service parameters */ | |
| struct fc_login_class class1; | |
| /** Class 2 service parameters */ | |
| struct fc_login_class class2; | |
| /** Class 3 service parameters */ | |
| struct fc_login_class class3; | |
| /** Class 4 service parameters */ | |
| struct fc_login_class class4; | |
| /** Vendor version level */ | |
| uint8_t vendor_version[16]; | |
| } __attribute__ (( packed )); | |
| /** A Fibre Channel LOGO request frame */ | |
| struct fc_logout_request_frame { | |
| /** ELS command code */ | |
| uint8_t command; | |
| /** Reserved */ | |
| uint8_t reserved[4]; | |
| /** Port ID */ | |
| struct fc_port_id port_id; | |
| /** Port name */ | |
| struct fc_name port_wwn; | |
| } __attribute__ (( packed )); | |
| /** A Fibre Channel LOGO response frame */ | |
| struct fc_logout_response_frame { | |
| /** ELS command code */ | |
| uint8_t command; | |
| /** Reserved */ | |
| uint8_t reserved[3]; | |
| } __attribute__ (( packed )); | |
| /** A Fibre Channel PRLI service parameter page */ | |
| struct fc_prli_page { | |
| /** Type code */ | |
| uint8_t type; | |
| /** Type code extension */ | |
| uint8_t type_ext; | |
| /** Flags and response code */ | |
| uint16_t flags; | |
| /** Reserved */ | |
| uint32_t reserved[2]; | |
| } __attribute__ (( packed )); | |
| /** Establish image pair */ | |
| #define FC_PRLI_ESTABLISH 0x2000 | |
| /** Response code mask */ | |
| #define FC_PRLI_RESPONSE_MASK 0x0f00 | |
| /** Request was executed successfully */ | |
| #define FC_PRLI_RESPONSE_SUCCESS 0x0100 | |
| /** A Fibre Channel PRLI frame */ | |
| struct fc_prli_frame { | |
| /** ELS command code */ | |
| uint8_t command; | |
| /** Page length */ | |
| uint8_t page_len; | |
| /** Payload length */ | |
| uint16_t len; | |
| /** Service parameter page */ | |
| struct fc_prli_page page; | |
| } __attribute__ (( packed )); | |
| /** A Fibre Channel RTV request frame */ | |
| struct fc_rtv_request_frame { | |
| /** ELS command code */ | |
| uint8_t command; | |
| /** Reserved */ | |
| uint8_t reserved[3]; | |
| } __attribute__ (( packed )); | |
| /** A Fibre Channel RTV response frame */ | |
| struct fc_rtv_response_frame { | |
| /** ELS command code */ | |
| uint8_t command; | |
| /** Reserved */ | |
| uint8_t reserved0[3]; | |
| /** Resource allocation timeout value */ | |
| uint32_t r_a_tov; | |
| /** Error detection timeout value */ | |
| uint32_t e_d_tov; | |
| /** Timeout qualifier */ | |
| uint16_t flags; | |
| /** Reserved */ | |
| uint16_t reserved1; | |
| } __attribute__ (( packed )); | |
| /** 1ns error detection timer resolution */ | |
| #define FC_RTV_HIRES_E_D_TOV 0x0400 | |
| /** Short R_T timeout */ | |
| #define FC_RTV_SHORT_R_T_TOV 0x0008 | |
| /** A Fibre Channel ECHO frame */ | |
| struct fc_echo_frame_header { | |
| /** ELS command code */ | |
| uint8_t command; | |
| /** Reserved */ | |
| uint8_t reserved[3]; | |
| } __attribute__ (( packed )); | |
| /** A Fibre Channel extended link services transaction */ | |
| struct fc_els { | |
| /** Reference count */ | |
| struct refcnt refcnt; | |
| /** Job control interface */ | |
| struct interface job; | |
| /** Fibre Channel exchange */ | |
| struct interface xchg; | |
| /** Request sending process */ | |
| struct process process; | |
| /** Fibre Channel port */ | |
| struct fc_port *port; | |
| /** Local port ID */ | |
| struct fc_port_id port_id; | |
| /** Peer port ID */ | |
| struct fc_port_id peer_port_id; | |
| /** ELS handler, if known */ | |
| struct fc_els_handler *handler; | |
| /** Flags */ | |
| unsigned int flags; | |
| }; | |
| /** Fibre Channel extended link services transaction flags */ | |
| enum fc_els_flags { | |
| /** ELS transaction is a request */ | |
| FC_ELS_REQUEST = 0x0001, | |
| }; | |
| /** A Fibre Channel extended link services handler */ | |
| struct fc_els_handler { | |
| /** Name */ | |
| const char *name; | |
| /** Transmit ELS frame | |
| * | |
| * @v els Fibre Channel ELS transaction | |
| * @ret rc Return status code | |
| */ | |
| int ( * tx ) ( struct fc_els *els ); | |
| /** Receive ELS frame | |
| * | |
| * @v els Fibre Channel ELS transaction | |
| * @v data ELS frame | |
| * @v len Length of ELS frame | |
| * @ret rc Return status code | |
| */ | |
| int ( * rx ) ( struct fc_els *els, void *data, size_t len ); | |
| /** Detect ELS frame | |
| * | |
| * @v els Fibre Channel ELS transaction | |
| * @v data ELS frame | |
| * @v len Length of ELS frame | |
| * @ret rc Return status code | |
| */ | |
| int ( * detect ) ( struct fc_els *els, const void *data, size_t len ); | |
| }; | |
| /** Fibre Channel ELS handler table */ | |
| #define FC_ELS_HANDLERS __table ( struct fc_els_handler, "fc_els_handlers" ) | |
| /** Declare a Fibre Channel ELS handler */ | |
| #define __fc_els_handler __table_entry ( FC_ELS_HANDLERS, 01 ) | |
| /** A Fibre Channel ELS PRLI descriptor */ | |
| struct fc_els_prli_descriptor { | |
| /** Upper-layer protocol type */ | |
| unsigned int type; | |
| /** Service parameter length */ | |
| size_t param_len; | |
| /** Fibre Channel ELS handler */ | |
| struct fc_els_handler *handler; | |
| }; | |
| /** Fibre Channel ELS PRLI descriptor table */ | |
| #define FC_ELS_PRLI_DESCRIPTORS \ | |
| __table ( struct fc_els_prli_descriptor, "fc_els_prli_descriptors" ) | |
| /** Declare a Fibre Channel ELS PRLI descriptor */ | |
| #define __fc_els_prli_descriptor __table_entry ( FC_ELS_PRLI_DESCRIPTORS, 01 ) | |
| /** | |
| * Check if Fibre Channel ELS transaction is a request | |
| * | |
| * @v els Fibre Channel ELS transaction | |
| * @ret is_request ELS transaction is a request | |
| */ | |
| static inline int fc_els_is_request ( struct fc_els *els ) { | |
| return ( els->flags & FC_ELS_REQUEST ); | |
| } | |
| /** | |
| * Calculate ELS command to transmit | |
| * | |
| * @v els Fibre Channel ELS transaction | |
| * @v request_command Command for requests | |
| * @v command Command to transmit | |
| */ | |
| static inline unsigned int fc_els_tx_command ( struct fc_els *els, | |
| unsigned int request_command ) { | |
| return ( fc_els_is_request ( els ) ? request_command : FC_ELS_LS_ACC ); | |
| } | |
| extern int fc_els_tx ( struct fc_els *els, const void *data, size_t len ); | |
| extern int fc_els_request ( struct interface *job, struct fc_port *port, | |
| struct fc_port_id *peer_port_id, | |
| struct fc_els_handler *handler ); | |
| extern int fc_els_flogi ( struct interface *parent, struct fc_port *port ); | |
| extern int fc_els_plogi ( struct interface *parent, struct fc_port *port, | |
| struct fc_port_id *peer_port_id ); | |
| extern int fc_els_logo ( struct interface *parent, struct fc_port *port, | |
| struct fc_port_id *peer_port_id ); | |
| extern int fc_els_prli ( struct interface *parent, struct fc_port *port, | |
| struct fc_port_id *peer_port_id, unsigned int type ); | |
| extern int fc_els_prli_tx ( struct fc_els *els, | |
| struct fc_els_prli_descriptor *descriptor, | |
| void *param ); | |
| extern int fc_els_prli_rx ( struct fc_els *els, | |
| struct fc_els_prli_descriptor *descriptor, | |
| void *data, size_t len ); | |
| extern int fc_els_prli_detect ( struct fc_els *els __unused, | |
| struct fc_els_prli_descriptor *descriptor, | |
| const void *data, size_t len ); | |
| #endif /* _IPXE_FCELS_H */ |