You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

fc.h 14KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538
  1. #ifndef _IPXE_FC_H
  2. #define _IPXE_FC_H
  3. /**
  4. * @file
  5. *
  6. * Fibre Channel
  7. *
  8. */
  9. FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
  10. #include <stdint.h>
  11. #include <ipxe/refcnt.h>
  12. #include <ipxe/list.h>
  13. #include <ipxe/tables.h>
  14. #include <ipxe/interface.h>
  15. #include <ipxe/retry.h>
  16. #include <ipxe/socket.h>
  17. /******************************************************************************
  18. *
  19. * Fibre Channel Names and identifiers
  20. *
  21. ******************************************************************************
  22. */
  23. /** A Fibre Channel name */
  24. struct fc_name {
  25. uint8_t bytes[8];
  26. } __attribute__ (( packed ));
  27. /** Length of Fibre Channel name text */
  28. #define FC_NAME_STRLEN 23 /* "xx:xx:xx:xx:xx:xx:xx:xx" */
  29. /** A Fibre Channel port identifier */
  30. struct fc_port_id {
  31. uint8_t bytes[3];
  32. } __attribute__ (( packed ));
  33. /** Length of Fibre Channel port identifier next */
  34. #define FC_PORT_ID_STRLEN 9 /* "xx.xx.xx" */
  35. /**
  36. * Fibre Channel socket address
  37. */
  38. struct sockaddr_fc {
  39. /** Socket address family (part of struct @c sockaddr)
  40. *
  41. * Always set to @c AF_FC for Fibre Channel addresses
  42. */
  43. sa_family_t sfc_family;
  44. /** Port ID */
  45. struct fc_port_id sfc_port_id;
  46. /** Padding
  47. *
  48. * This ensures that a struct @c sockaddr_tcpip is large
  49. * enough to hold a socket address for any TCP/IP address
  50. * family.
  51. */
  52. char pad[ sizeof ( struct sockaddr ) - sizeof ( sa_family_t )
  53. - sizeof ( struct fc_port_id ) ];
  54. } __attribute__ (( packed, may_alias ));
  55. extern struct fc_port_id fc_empty_port_id;
  56. extern struct fc_port_id fc_f_port_id;
  57. extern struct fc_port_id fc_gs_port_id;
  58. extern struct fc_port_id fc_ptp_low_port_id;
  59. extern struct fc_port_id fc_ptp_high_port_id;
  60. extern const char * fc_id_ntoa ( const struct fc_port_id *id );
  61. extern int fc_id_aton ( const char *id_text, struct fc_port_id *id );
  62. extern const char * fc_ntoa ( const struct fc_name *wwn );
  63. extern int fc_aton ( const char *wwn_text, struct fc_name *wwn );
  64. extern struct sockaddr * fc_fill_sockaddr ( struct sockaddr_fc *sa_fc,
  65. struct fc_port_id *id );
  66. /******************************************************************************
  67. *
  68. * Fibre Channel link state
  69. *
  70. ******************************************************************************
  71. */
  72. /** Delay between failed link-up attempts */
  73. #define FC_LINK_RETRY_DELAY ( 2 * TICKS_PER_SEC )
  74. /** A Fibre Channel link state nonitor */
  75. struct fc_link_state {
  76. /** Retry timer */
  77. struct retry_timer timer;
  78. /** Link state */
  79. int rc;
  80. /** Examine link state
  81. *
  82. * @v link Fibre Channel link state monitor
  83. */
  84. void ( * examine ) ( struct fc_link_state *link );
  85. };
  86. /**
  87. * Check Fibre Channel link state
  88. *
  89. * @v link Fibre Channel link state monitor
  90. * @ret link_up Link is up
  91. */
  92. static inline __attribute__ (( always_inline )) int
  93. fc_link_ok ( struct fc_link_state *link ) {
  94. return ( link->rc == 0 );
  95. }
  96. /******************************************************************************
  97. *
  98. * Fibre Channel packet formats and exchanges
  99. *
  100. ******************************************************************************
  101. */
  102. /** A Fibre Channel Frame Header */
  103. struct fc_frame_header {
  104. /** Routing control
  105. *
  106. * This is the bitwise OR of one @c fc_r_ctl_routing value and
  107. * one @c fc_r_ctl_info value.
  108. */
  109. uint8_t r_ctl;
  110. /** Destination ID */
  111. struct fc_port_id d_id;
  112. /** Class-specific control / Priority */
  113. uint8_t cs_ctl_prio;
  114. /** Source ID */
  115. struct fc_port_id s_id;
  116. /** Data structure type */
  117. uint8_t type;
  118. /** Frame control - exchange and sequence */
  119. uint8_t f_ctl_es;
  120. /** Frame control - acknowledgements */
  121. uint8_t f_ctl_ack;
  122. /** Frame control - miscellaneous */
  123. uint8_t f_ctl_misc;
  124. /** Sequence ID */
  125. uint8_t seq_id;
  126. /** Data field control */
  127. uint8_t df_ctl;
  128. /** Sequence count */
  129. uint16_t seq_cnt;
  130. /** Originator exchange ID */
  131. uint16_t ox_id;
  132. /** Responder exchange ID */
  133. uint16_t rx_id;
  134. /** Parameter
  135. *
  136. * Contains the relative offset when @c FC_F_CTL_MISC_REL_OFF
  137. * is set.
  138. */
  139. uint32_t parameter;
  140. } __attribute__ (( packed ));
  141. /** Fibre Channel Routing Control Routing */
  142. enum fc_r_ctl_routing {
  143. FC_R_CTL_DATA = 0x00, /**< Device Data */
  144. FC_R_CTL_ELS = 0x20, /**< Extended Link Services */
  145. FC_R_CTL_FC4_LINK = 0x30, /**< FC-4 Link Data */
  146. FC_R_CTL_VIDEO = 0x40, /**< Video Data */
  147. FC_R_CTL_EH = 0x50, /**< Extended Headers */
  148. FC_R_CTL_BLS = 0x80, /**< Basic Link Services */
  149. FC_R_CTL_LINK_CTRL = 0xc0, /**< Link Control */
  150. FC_R_CTL_EXT_ROUTE = 0xf0, /**< Extended Routing */
  151. };
  152. /** Fibre Channel Routing Control Routing mask */
  153. #define FC_R_CTL_ROUTING_MASK 0xf0
  154. /** Fibre Channel Routing Control Information */
  155. enum fc_r_ctl_info {
  156. FC_R_CTL_UNCAT = 0x00, /**< Uncategorized */
  157. FC_R_CTL_SOL_DATA = 0x01, /**< Solicited Data */
  158. FC_R_CTL_UNSOL_CTRL = 0x02, /**< Unsolicited Control */
  159. FC_R_CTL_SOL_CTRL = 0x03, /**< Solicited Control */
  160. FC_R_CTL_UNSOL_DATA = 0x04, /**< Unsolicited Data */
  161. FC_R_CTL_DATA_DESC = 0x05, /**< Data Descriptor */
  162. FC_R_CTL_UNSOL_CMD = 0x06, /**< Unsolicited Command */
  163. FC_R_CTL_CMD_STAT = 0x07, /**< Command Status */
  164. };
  165. /** Fibre Channel Routing Control Information mask */
  166. #define FC_R_CTL_INFO_MASK 0x07
  167. /** Fibre Channel Data Structure Type */
  168. enum fc_type {
  169. FC_TYPE_BLS = 0x00, /**< Basic Link Service */
  170. FC_TYPE_ELS = 0x01, /**< Extended Link Service */
  171. FC_TYPE_FCP = 0x08, /**< Fibre Channel Protocol */
  172. FC_TYPE_CT = 0x20, /**< Common Transport */
  173. };
  174. /** Fibre Channel Frame Control - Exchange and Sequence */
  175. enum fc_f_ctl_es {
  176. FC_F_CTL_ES_RESPONDER = 0x80, /**< Responder of Exchange */
  177. FC_F_CTL_ES_RECIPIENT = 0x40, /**< Sequence Recipient */
  178. FC_F_CTL_ES_FIRST = 0x20, /**< First Sequence of Exchange */
  179. FC_F_CTL_ES_LAST = 0x10, /**< Last Sequence of Exchange */
  180. FC_F_CTL_ES_END = 0x08, /**< Last Data Frame of Sequence */
  181. FC_F_CTL_ES_TRANSFER = 0x01, /**< Transfer Sequence Initiative */
  182. };
  183. /** Fibre Channel Frame Control - Miscellaneous */
  184. enum fc_f_ctl_misc {
  185. FC_F_CTL_MISC_REL_OFF = 0x08, /**< Relative Offset Present */
  186. };
  187. /** Responder exchange identifier used before first response */
  188. #define FC_RX_ID_UNKNOWN 0xffff
  189. struct fc_port;
  190. extern int fc_xchg_originate ( struct interface *parent, struct fc_port *port,
  191. struct fc_port_id *peer_port_id,
  192. unsigned int type );
  193. /** A Fibre Channel responder */
  194. struct fc_responder {
  195. /** Type */
  196. unsigned int type;
  197. /** Respond to exchange
  198. *
  199. * @v xchg Exchange interface
  200. * @v port Fibre Channel port
  201. * @v port_id Local port ID
  202. * @v peer_port_id Peer port ID
  203. * @ret rc Return status code
  204. */
  205. int ( * respond ) ( struct interface *xchg, struct fc_port *port,
  206. struct fc_port_id *port_id,
  207. struct fc_port_id *peer_port_id );
  208. };
  209. /** Fibre Channel responder table */
  210. #define FC_RESPONDERS __table ( struct fc_responder, "fc_responders" )
  211. /** Declare a Fibre Channel responder */
  212. #define __fc_responder __table_entry ( FC_RESPONDERS, 01 )
  213. /******************************************************************************
  214. *
  215. * Fibre Channel ports
  216. *
  217. ******************************************************************************
  218. */
  219. /** A Fibre Channel port */
  220. struct fc_port {
  221. /** Reference count */
  222. struct refcnt refcnt;
  223. /** List of all ports */
  224. struct list_head list;
  225. /** Name of this port */
  226. char name[8];
  227. /** Transport interface */
  228. struct interface transport;
  229. /** Node name */
  230. struct fc_name node_wwn;
  231. /** Port name */
  232. struct fc_name port_wwn;
  233. /** Local port ID */
  234. struct fc_port_id port_id;
  235. /** Flags */
  236. unsigned int flags;
  237. /** Link state monitor */
  238. struct fc_link_state link;
  239. /** FLOGI interface */
  240. struct interface flogi;
  241. /** Link node name */
  242. struct fc_name link_node_wwn;
  243. /** Link port name */
  244. struct fc_name link_port_wwn;
  245. /** Link port ID (for point-to-point links only) */
  246. struct fc_port_id ptp_link_port_id;
  247. /** Name server PLOGI interface */
  248. struct interface ns_plogi;
  249. /** List of active exchanges */
  250. struct list_head xchgs;
  251. };
  252. /** Fibre Channel port flags */
  253. enum fc_port_flags {
  254. /** Port is attached to a fabric */
  255. FC_PORT_HAS_FABRIC = 0x0001,
  256. /** Port is logged in to a name server */
  257. FC_PORT_HAS_NS = 0x0002,
  258. };
  259. /**
  260. * Get reference to Fibre Channel port
  261. *
  262. * @v port Fibre Channel port
  263. * @ret port Fibre Channel port
  264. */
  265. static inline __attribute__ (( always_inline )) struct fc_port *
  266. fc_port_get ( struct fc_port *port ) {
  267. ref_get ( &port->refcnt );
  268. return port;
  269. }
  270. /**
  271. * Drop reference to Fibre Channel port
  272. *
  273. * @v port Fibre Channel port
  274. */
  275. static inline __attribute__ (( always_inline )) void
  276. fc_port_put ( struct fc_port *port ) {
  277. ref_put ( &port->refcnt );
  278. }
  279. extern struct list_head fc_ports;
  280. extern int fc_port_login ( struct fc_port *port, struct fc_port_id *port_id,
  281. const struct fc_name *link_node_wwn,
  282. const struct fc_name *link_port_wwn,
  283. int has_fabric );
  284. extern void fc_port_logout ( struct fc_port *port, int rc );
  285. extern int fc_port_open ( struct interface *transport,
  286. const struct fc_name *node_wwn,
  287. const struct fc_name *port_wwn,
  288. const char *name );
  289. extern struct fc_port * fc_port_find ( const char *name );
  290. /******************************************************************************
  291. *
  292. * Fibre Channel peers
  293. *
  294. ******************************************************************************
  295. */
  296. /** A Fibre Channel peer */
  297. struct fc_peer {
  298. /** Reference count */
  299. struct refcnt refcnt;
  300. /** List of all peers */
  301. struct list_head list;
  302. /** Port name */
  303. struct fc_name port_wwn;
  304. /** Link state monitor */
  305. struct fc_link_state link;
  306. /** PLOGI interface */
  307. struct interface plogi;
  308. /** Fibre Channel port, if known */
  309. struct fc_port *port;
  310. /** Peer port ID, if known */
  311. struct fc_port_id port_id;
  312. /** List of upper-layer protocols */
  313. struct list_head ulps;
  314. /** Active usage count
  315. *
  316. * A peer (and attached ULPs) may be created in response to
  317. * unsolicited login requests received via the fabric. We
  318. * track our own active usage count independently of the
  319. * existence of the peer, so that if the peer becomes logged
  320. * out (e.g. due to a link failure) then we know whether or
  321. * not we should attempt to relogin.
  322. */
  323. unsigned int usage;
  324. };
  325. /**
  326. * Get reference to Fibre Channel peer
  327. *
  328. * @v peer Fibre Channel peer
  329. * @ret peer Fibre Channel peer
  330. */
  331. static inline __attribute__ (( always_inline )) struct fc_peer *
  332. fc_peer_get ( struct fc_peer *peer ) {
  333. ref_get ( &peer->refcnt );
  334. return peer;
  335. }
  336. /**
  337. * Drop reference to Fibre Channel peer
  338. *
  339. * @v peer Fibre Channel peer
  340. */
  341. static inline __attribute__ (( always_inline )) void
  342. fc_peer_put ( struct fc_peer *peer ) {
  343. ref_put ( &peer->refcnt );
  344. }
  345. extern struct list_head fc_peers;
  346. extern struct fc_peer * fc_peer_get_wwn ( const struct fc_name *port_wwn );
  347. extern struct fc_peer *
  348. fc_peer_get_port_id ( struct fc_port *port,
  349. const struct fc_port_id *peer_port_id );
  350. extern int fc_peer_login ( struct fc_peer *peer,
  351. struct fc_port *port,
  352. struct fc_port_id *port_id );
  353. extern void fc_peer_logout ( struct fc_peer *peer, int rc );
  354. /******************************************************************************
  355. *
  356. * Fibre Channel upper-layer protocols
  357. *
  358. ******************************************************************************
  359. */
  360. /** A Fibre Channel upper-layer protocol */
  361. struct fc_ulp {
  362. /** Reference count */
  363. struct refcnt refcnt;
  364. /** Fibre Channel peer */
  365. struct fc_peer *peer;
  366. /** List of upper-layer protocols */
  367. struct list_head list;
  368. /** Type */
  369. unsigned int type;
  370. /** Flags */
  371. unsigned int flags;
  372. /** Link state monitor */
  373. struct fc_link_state link;
  374. /** PRLI interface */
  375. struct interface prli;
  376. /** Service parameters, if any */
  377. void *param;
  378. /** Service parameter length */
  379. size_t param_len;
  380. /** Active users of this upper-layer protocol
  381. *
  382. * As with peers, an upper-layer protocol may be created in
  383. * response to an unsolicited login request received via the
  384. * fabric. This list records the number of active users of
  385. * the ULP; the number of entries in the list is equivalent to
  386. * the peer usage count.
  387. */
  388. struct list_head users;
  389. };
  390. /** Fibre Channel upper-layer protocol flags */
  391. enum fc_ulp_flags {
  392. /** A login originated by us has succeeded */
  393. FC_ULP_ORIGINATED_LOGIN_OK = 0x0001,
  394. };
  395. /** A Fibre Channel upper-layer protocol user */
  396. struct fc_ulp_user {
  397. /** Fibre Channel upper layer protocol */
  398. struct fc_ulp *ulp;
  399. /** List of users */
  400. struct list_head list;
  401. /** Containing object reference count, or NULL */
  402. struct refcnt *refcnt;
  403. /** Examine link state
  404. *
  405. * @v user Fibre Channel upper-layer-protocol user
  406. */
  407. void ( * examine ) ( struct fc_ulp_user *user );
  408. };
  409. /**
  410. * Get reference to Fibre Channel upper-layer protocol
  411. *
  412. * @v ulp Fibre Channel upper-layer protocol
  413. * @ret ulp Fibre Channel upper-layer protocol
  414. */
  415. static inline __attribute__ (( always_inline )) struct fc_ulp *
  416. fc_ulp_get ( struct fc_ulp *ulp ) {
  417. ref_get ( &ulp->refcnt );
  418. return ulp;
  419. }
  420. /**
  421. * Drop reference to Fibre Channel upper-layer protocol
  422. *
  423. * @v ulp Fibre Channel upper-layer protocol
  424. */
  425. static inline __attribute__ (( always_inline )) void
  426. fc_ulp_put ( struct fc_ulp *ulp ) {
  427. ref_put ( &ulp->refcnt );
  428. }
  429. /**
  430. * Get reference to Fibre Channel upper-layer protocol user
  431. *
  432. * @v user Fibre Channel upper-layer protocol user
  433. * @ret user Fibre Channel upper-layer protocol user
  434. */
  435. static inline __attribute__ (( always_inline )) struct fc_ulp_user *
  436. fc_ulp_user_get ( struct fc_ulp_user *user ) {
  437. ref_get ( user->refcnt );
  438. return user;
  439. }
  440. /**
  441. * Drop reference to Fibre Channel upper-layer protocol user
  442. *
  443. * @v user Fibre Channel upper-layer protocol user
  444. */
  445. static inline __attribute__ (( always_inline )) void
  446. fc_ulp_user_put ( struct fc_ulp_user *user ) {
  447. ref_put ( user->refcnt );
  448. }
  449. /**
  450. * Initialise Fibre Channel upper-layer protocol user
  451. *
  452. * @v user Fibre Channel upper-layer protocol user
  453. * @v examine Examine link state method
  454. * @v refcnt Containing object reference count, or NULL
  455. */
  456. static inline __attribute__ (( always_inline )) void
  457. fc_ulp_user_init ( struct fc_ulp_user *user,
  458. void ( * examine ) ( struct fc_ulp_user *user ),
  459. struct refcnt *refcnt ) {
  460. user->examine = examine;
  461. user->refcnt = refcnt;
  462. }
  463. extern struct fc_ulp * fc_ulp_get_wwn_type ( const struct fc_name *port_wwn,
  464. unsigned int type );
  465. extern struct fc_ulp *
  466. fc_ulp_get_port_id_type ( struct fc_port *port,
  467. const struct fc_port_id *peer_port_id,
  468. unsigned int type );
  469. extern void fc_ulp_attach ( struct fc_ulp *ulp, struct fc_ulp_user *user );
  470. extern void fc_ulp_detach ( struct fc_ulp_user *user );
  471. extern int fc_ulp_login ( struct fc_ulp *ulp, const void *param,
  472. size_t param_len, int originated );
  473. extern void fc_ulp_logout ( struct fc_ulp *ulp, int rc );
  474. #endif /* _IPXE_FC_H */