bfa_fcbuild.c 37 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439
  1. /*
  2. * Copyright (c) 2005-2010 Brocade Communications Systems, Inc.
  3. * All rights reserved
  4. * www.brocade.com
  5. *
  6. * Linux driver for Brocade Fibre Channel Host Bus Adapter.
  7. *
  8. * This program is free software; you can redistribute it and/or modify it
  9. * under the terms of the GNU General Public License (GPL) Version 2 as
  10. * published by the Free Software Foundation
  11. *
  12. * This program is distributed in the hope that it will be useful, but
  13. * WITHOUT ANY WARRANTY; without even the implied warranty of
  14. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  15. * General Public License for more details.
  16. */
  17. /*
  18. * fcbuild.c - FC link service frame building and parsing routines
  19. */
  20. #include "bfad_drv.h"
  21. #include "bfa_fcbuild.h"
  22. /*
  23. * static build functions
  24. */
  25. static void fc_els_rsp_build(struct fchs_s *fchs, u32 d_id, u32 s_id,
  26. __be16 ox_id);
  27. static void fc_bls_rsp_build(struct fchs_s *fchs, u32 d_id, u32 s_id,
  28. __be16 ox_id);
  29. static struct fchs_s fc_els_req_tmpl;
  30. static struct fchs_s fc_els_rsp_tmpl;
  31. static struct fchs_s fc_bls_req_tmpl;
  32. static struct fchs_s fc_bls_rsp_tmpl;
  33. static struct fc_ba_acc_s ba_acc_tmpl;
  34. static struct fc_logi_s plogi_tmpl;
  35. static struct fc_prli_s prli_tmpl;
  36. static struct fc_rrq_s rrq_tmpl;
  37. static struct fchs_s fcp_fchs_tmpl;
  38. void
  39. fcbuild_init(void)
  40. {
  41. /*
  42. * fc_els_req_tmpl
  43. */
  44. fc_els_req_tmpl.routing = FC_RTG_EXT_LINK;
  45. fc_els_req_tmpl.cat_info = FC_CAT_LD_REQUEST;
  46. fc_els_req_tmpl.type = FC_TYPE_ELS;
  47. fc_els_req_tmpl.f_ctl =
  48. bfa_hton3b(FCTL_SEQ_INI | FCTL_FS_EXCH | FCTL_END_SEQ |
  49. FCTL_SI_XFER);
  50. fc_els_req_tmpl.rx_id = FC_RXID_ANY;
  51. /*
  52. * fc_els_rsp_tmpl
  53. */
  54. fc_els_rsp_tmpl.routing = FC_RTG_EXT_LINK;
  55. fc_els_rsp_tmpl.cat_info = FC_CAT_LD_REPLY;
  56. fc_els_rsp_tmpl.type = FC_TYPE_ELS;
  57. fc_els_rsp_tmpl.f_ctl =
  58. bfa_hton3b(FCTL_EC_RESP | FCTL_SEQ_INI | FCTL_LS_EXCH |
  59. FCTL_END_SEQ | FCTL_SI_XFER);
  60. fc_els_rsp_tmpl.rx_id = FC_RXID_ANY;
  61. /*
  62. * fc_bls_req_tmpl
  63. */
  64. fc_bls_req_tmpl.routing = FC_RTG_BASIC_LINK;
  65. fc_bls_req_tmpl.type = FC_TYPE_BLS;
  66. fc_bls_req_tmpl.f_ctl = bfa_hton3b(FCTL_END_SEQ | FCTL_SI_XFER);
  67. fc_bls_req_tmpl.rx_id = FC_RXID_ANY;
  68. /*
  69. * fc_bls_rsp_tmpl
  70. */
  71. fc_bls_rsp_tmpl.routing = FC_RTG_BASIC_LINK;
  72. fc_bls_rsp_tmpl.cat_info = FC_CAT_BA_ACC;
  73. fc_bls_rsp_tmpl.type = FC_TYPE_BLS;
  74. fc_bls_rsp_tmpl.f_ctl =
  75. bfa_hton3b(FCTL_EC_RESP | FCTL_SEQ_INI | FCTL_LS_EXCH |
  76. FCTL_END_SEQ | FCTL_SI_XFER);
  77. fc_bls_rsp_tmpl.rx_id = FC_RXID_ANY;
  78. /*
  79. * ba_acc_tmpl
  80. */
  81. ba_acc_tmpl.seq_id_valid = 0;
  82. ba_acc_tmpl.low_seq_cnt = 0;
  83. ba_acc_tmpl.high_seq_cnt = 0xFFFF;
  84. /*
  85. * plogi_tmpl
  86. */
  87. plogi_tmpl.csp.verhi = FC_PH_VER_PH_3;
  88. plogi_tmpl.csp.verlo = FC_PH_VER_4_3;
  89. plogi_tmpl.csp.ciro = 0x1;
  90. plogi_tmpl.csp.cisc = 0x0;
  91. plogi_tmpl.csp.altbbcred = 0x0;
  92. plogi_tmpl.csp.conseq = cpu_to_be16(0x00FF);
  93. plogi_tmpl.csp.ro_bitmap = cpu_to_be16(0x0002);
  94. plogi_tmpl.csp.e_d_tov = cpu_to_be32(2000);
  95. plogi_tmpl.class3.class_valid = 1;
  96. plogi_tmpl.class3.sequential = 1;
  97. plogi_tmpl.class3.conseq = 0xFF;
  98. plogi_tmpl.class3.ospx = 1;
  99. /*
  100. * prli_tmpl
  101. */
  102. prli_tmpl.command = FC_ELS_PRLI;
  103. prli_tmpl.pglen = 0x10;
  104. prli_tmpl.pagebytes = cpu_to_be16(0x0014);
  105. prli_tmpl.parampage.type = FC_TYPE_FCP;
  106. prli_tmpl.parampage.imagepair = 1;
  107. prli_tmpl.parampage.servparams.rxrdisab = 1;
  108. /*
  109. * rrq_tmpl
  110. */
  111. rrq_tmpl.els_cmd.els_code = FC_ELS_RRQ;
  112. /*
  113. * fcp_struct fchs_s mpl
  114. */
  115. fcp_fchs_tmpl.routing = FC_RTG_FC4_DEV_DATA;
  116. fcp_fchs_tmpl.cat_info = FC_CAT_UNSOLICIT_CMD;
  117. fcp_fchs_tmpl.type = FC_TYPE_FCP;
  118. fcp_fchs_tmpl.f_ctl =
  119. bfa_hton3b(FCTL_FS_EXCH | FCTL_END_SEQ | FCTL_SI_XFER);
  120. fcp_fchs_tmpl.seq_id = 1;
  121. fcp_fchs_tmpl.rx_id = FC_RXID_ANY;
  122. }
  123. static void
  124. fc_gs_fchdr_build(struct fchs_s *fchs, u32 d_id, u32 s_id, u32 ox_id)
  125. {
  126. memset(fchs, 0, sizeof(struct fchs_s));
  127. fchs->routing = FC_RTG_FC4_DEV_DATA;
  128. fchs->cat_info = FC_CAT_UNSOLICIT_CTRL;
  129. fchs->type = FC_TYPE_SERVICES;
  130. fchs->f_ctl =
  131. bfa_hton3b(FCTL_SEQ_INI | FCTL_FS_EXCH | FCTL_END_SEQ |
  132. FCTL_SI_XFER);
  133. fchs->rx_id = FC_RXID_ANY;
  134. fchs->d_id = (d_id);
  135. fchs->s_id = (s_id);
  136. fchs->ox_id = cpu_to_be16(ox_id);
  137. /*
  138. * @todo no need to set ox_id for request
  139. * no need to set rx_id for response
  140. */
  141. }
  142. static void
  143. fc_gsresp_fchdr_build(struct fchs_s *fchs, u32 d_id, u32 s_id, u16 ox_id)
  144. {
  145. memset(fchs, 0, sizeof(struct fchs_s));
  146. fchs->routing = FC_RTG_FC4_DEV_DATA;
  147. fchs->cat_info = FC_CAT_SOLICIT_CTRL;
  148. fchs->type = FC_TYPE_SERVICES;
  149. fchs->f_ctl =
  150. bfa_hton3b(FCTL_EC_RESP | FCTL_SEQ_INI | FCTL_LS_EXCH |
  151. FCTL_END_SEQ | FCTL_SI_XFER);
  152. fchs->d_id = d_id;
  153. fchs->s_id = s_id;
  154. fchs->ox_id = ox_id;
  155. }
  156. void
  157. fc_els_req_build(struct fchs_s *fchs, u32 d_id, u32 s_id, __be16 ox_id)
  158. {
  159. memcpy(fchs, &fc_els_req_tmpl, sizeof(struct fchs_s));
  160. fchs->d_id = (d_id);
  161. fchs->s_id = (s_id);
  162. fchs->ox_id = cpu_to_be16(ox_id);
  163. }
  164. static void
  165. fc_els_rsp_build(struct fchs_s *fchs, u32 d_id, u32 s_id, __be16 ox_id)
  166. {
  167. memcpy(fchs, &fc_els_rsp_tmpl, sizeof(struct fchs_s));
  168. fchs->d_id = d_id;
  169. fchs->s_id = s_id;
  170. fchs->ox_id = ox_id;
  171. }
  172. enum fc_parse_status
  173. fc_els_rsp_parse(struct fchs_s *fchs, int len)
  174. {
  175. struct fc_els_cmd_s *els_cmd = (struct fc_els_cmd_s *) (fchs + 1);
  176. struct fc_ls_rjt_s *ls_rjt = (struct fc_ls_rjt_s *) els_cmd;
  177. len = len;
  178. switch (els_cmd->els_code) {
  179. case FC_ELS_LS_RJT:
  180. if (ls_rjt->reason_code == FC_LS_RJT_RSN_LOGICAL_BUSY)
  181. return FC_PARSE_BUSY;
  182. else
  183. return FC_PARSE_FAILURE;
  184. case FC_ELS_ACC:
  185. return FC_PARSE_OK;
  186. }
  187. return FC_PARSE_OK;
  188. }
  189. static void
  190. fc_bls_rsp_build(struct fchs_s *fchs, u32 d_id, u32 s_id, __be16 ox_id)
  191. {
  192. memcpy(fchs, &fc_bls_rsp_tmpl, sizeof(struct fchs_s));
  193. fchs->d_id = d_id;
  194. fchs->s_id = s_id;
  195. fchs->ox_id = ox_id;
  196. }
  197. static u16
  198. fc_plogi_x_build(struct fchs_s *fchs, void *pld, u32 d_id, u32 s_id,
  199. __be16 ox_id, wwn_t port_name, wwn_t node_name,
  200. u16 pdu_size, u16 bb_cr, u8 els_code)
  201. {
  202. struct fc_logi_s *plogi = (struct fc_logi_s *) (pld);
  203. memcpy(plogi, &plogi_tmpl, sizeof(struct fc_logi_s));
  204. plogi->els_cmd.els_code = els_code;
  205. if (els_code == FC_ELS_PLOGI)
  206. fc_els_req_build(fchs, d_id, s_id, ox_id);
  207. else
  208. fc_els_rsp_build(fchs, d_id, s_id, ox_id);
  209. plogi->csp.rxsz = plogi->class3.rxsz = cpu_to_be16(pdu_size);
  210. plogi->csp.bbcred = cpu_to_be16(bb_cr);
  211. memcpy(&plogi->port_name, &port_name, sizeof(wwn_t));
  212. memcpy(&plogi->node_name, &node_name, sizeof(wwn_t));
  213. return sizeof(struct fc_logi_s);
  214. }
  215. u16
  216. fc_flogi_build(struct fchs_s *fchs, struct fc_logi_s *flogi, u32 s_id,
  217. u16 ox_id, wwn_t port_name, wwn_t node_name, u16 pdu_size,
  218. u8 set_npiv, u8 set_auth, u16 local_bb_credits)
  219. {
  220. u32 d_id = bfa_hton3b(FC_FABRIC_PORT);
  221. __be32 *vvl_info;
  222. memcpy(flogi, &plogi_tmpl, sizeof(struct fc_logi_s));
  223. flogi->els_cmd.els_code = FC_ELS_FLOGI;
  224. fc_els_req_build(fchs, d_id, s_id, ox_id);
  225. flogi->csp.rxsz = flogi->class3.rxsz = cpu_to_be16(pdu_size);
  226. flogi->port_name = port_name;
  227. flogi->node_name = node_name;
  228. /*
  229. * Set the NPIV Capability Bit ( word 1, bit 31) of Common
  230. * Service Parameters.
  231. */
  232. flogi->csp.ciro = set_npiv;
  233. /* set AUTH capability */
  234. flogi->csp.security = set_auth;
  235. flogi->csp.bbcred = cpu_to_be16(local_bb_credits);
  236. /* Set brcd token in VVL */
  237. vvl_info = (u32 *)&flogi->vvl[0];
  238. /* set the flag to indicate the presence of VVL */
  239. flogi->csp.npiv_supp = 1; /* @todo. field name is not correct */
  240. vvl_info[0] = cpu_to_be32(FLOGI_VVL_BRCD);
  241. return sizeof(struct fc_logi_s);
  242. }
  243. u16
  244. fc_flogi_acc_build(struct fchs_s *fchs, struct fc_logi_s *flogi, u32 s_id,
  245. __be16 ox_id, wwn_t port_name, wwn_t node_name,
  246. u16 pdu_size, u16 local_bb_credits, u8 bb_scn)
  247. {
  248. u32 d_id = 0;
  249. u16 bbscn_rxsz = (bb_scn << 12) | pdu_size;
  250. memcpy(flogi, &plogi_tmpl, sizeof(struct fc_logi_s));
  251. fc_els_rsp_build(fchs, d_id, s_id, ox_id);
  252. flogi->els_cmd.els_code = FC_ELS_ACC;
  253. flogi->class3.rxsz = cpu_to_be16(pdu_size);
  254. flogi->csp.rxsz = cpu_to_be16(bbscn_rxsz); /* bb_scn/rxsz */
  255. flogi->port_name = port_name;
  256. flogi->node_name = node_name;
  257. flogi->csp.bbcred = cpu_to_be16(local_bb_credits);
  258. return sizeof(struct fc_logi_s);
  259. }
  260. u16
  261. fc_fdisc_build(struct fchs_s *fchs, struct fc_logi_s *flogi, u32 s_id,
  262. u16 ox_id, wwn_t port_name, wwn_t node_name, u16 pdu_size)
  263. {
  264. u32 d_id = bfa_hton3b(FC_FABRIC_PORT);
  265. memcpy(flogi, &plogi_tmpl, sizeof(struct fc_logi_s));
  266. flogi->els_cmd.els_code = FC_ELS_FDISC;
  267. fc_els_req_build(fchs, d_id, s_id, ox_id);
  268. flogi->csp.rxsz = flogi->class3.rxsz = cpu_to_be16(pdu_size);
  269. flogi->port_name = port_name;
  270. flogi->node_name = node_name;
  271. return sizeof(struct fc_logi_s);
  272. }
  273. u16
  274. fc_plogi_build(struct fchs_s *fchs, void *pld, u32 d_id, u32 s_id,
  275. u16 ox_id, wwn_t port_name, wwn_t node_name,
  276. u16 pdu_size, u16 bb_cr)
  277. {
  278. return fc_plogi_x_build(fchs, pld, d_id, s_id, ox_id, port_name,
  279. node_name, pdu_size, bb_cr, FC_ELS_PLOGI);
  280. }
  281. u16
  282. fc_plogi_acc_build(struct fchs_s *fchs, void *pld, u32 d_id, u32 s_id,
  283. u16 ox_id, wwn_t port_name, wwn_t node_name,
  284. u16 pdu_size, u16 bb_cr)
  285. {
  286. return fc_plogi_x_build(fchs, pld, d_id, s_id, ox_id, port_name,
  287. node_name, pdu_size, bb_cr, FC_ELS_ACC);
  288. }
  289. enum fc_parse_status
  290. fc_plogi_rsp_parse(struct fchs_s *fchs, int len, wwn_t port_name)
  291. {
  292. struct fc_els_cmd_s *els_cmd = (struct fc_els_cmd_s *) (fchs + 1);
  293. struct fc_logi_s *plogi;
  294. struct fc_ls_rjt_s *ls_rjt;
  295. switch (els_cmd->els_code) {
  296. case FC_ELS_LS_RJT:
  297. ls_rjt = (struct fc_ls_rjt_s *) (fchs + 1);
  298. if (ls_rjt->reason_code == FC_LS_RJT_RSN_LOGICAL_BUSY)
  299. return FC_PARSE_BUSY;
  300. else
  301. return FC_PARSE_FAILURE;
  302. case FC_ELS_ACC:
  303. plogi = (struct fc_logi_s *) (fchs + 1);
  304. if (len < sizeof(struct fc_logi_s))
  305. return FC_PARSE_FAILURE;
  306. if (!wwn_is_equal(plogi->port_name, port_name))
  307. return FC_PARSE_FAILURE;
  308. if (!plogi->class3.class_valid)
  309. return FC_PARSE_FAILURE;
  310. if (be16_to_cpu(plogi->class3.rxsz) < (FC_MIN_PDUSZ))
  311. return FC_PARSE_FAILURE;
  312. return FC_PARSE_OK;
  313. default:
  314. return FC_PARSE_FAILURE;
  315. }
  316. }
  317. enum fc_parse_status
  318. fc_plogi_parse(struct fchs_s *fchs)
  319. {
  320. struct fc_logi_s *plogi = (struct fc_logi_s *) (fchs + 1);
  321. if (plogi->class3.class_valid != 1)
  322. return FC_PARSE_FAILURE;
  323. if ((be16_to_cpu(plogi->class3.rxsz) < FC_MIN_PDUSZ)
  324. || (be16_to_cpu(plogi->class3.rxsz) > FC_MAX_PDUSZ)
  325. || (plogi->class3.rxsz == 0))
  326. return FC_PARSE_FAILURE;
  327. return FC_PARSE_OK;
  328. }
  329. u16
  330. fc_prli_build(struct fchs_s *fchs, void *pld, u32 d_id, u32 s_id,
  331. u16 ox_id)
  332. {
  333. struct fc_prli_s *prli = (struct fc_prli_s *) (pld);
  334. fc_els_req_build(fchs, d_id, s_id, ox_id);
  335. memcpy(prli, &prli_tmpl, sizeof(struct fc_prli_s));
  336. prli->command = FC_ELS_PRLI;
  337. prli->parampage.servparams.initiator = 1;
  338. prli->parampage.servparams.retry = 1;
  339. prli->parampage.servparams.rec_support = 1;
  340. prli->parampage.servparams.task_retry_id = 0;
  341. prli->parampage.servparams.confirm = 1;
  342. return sizeof(struct fc_prli_s);
  343. }
  344. u16
  345. fc_prli_acc_build(struct fchs_s *fchs, void *pld, u32 d_id, u32 s_id,
  346. __be16 ox_id, enum bfa_lport_role role)
  347. {
  348. struct fc_prli_s *prli = (struct fc_prli_s *) (pld);
  349. fc_els_rsp_build(fchs, d_id, s_id, ox_id);
  350. memcpy(prli, &prli_tmpl, sizeof(struct fc_prli_s));
  351. prli->command = FC_ELS_ACC;
  352. prli->parampage.servparams.initiator = 1;
  353. prli->parampage.rspcode = FC_PRLI_ACC_XQTD;
  354. return sizeof(struct fc_prli_s);
  355. }
  356. enum fc_parse_status
  357. fc_prli_rsp_parse(struct fc_prli_s *prli, int len)
  358. {
  359. if (len < sizeof(struct fc_prli_s))
  360. return FC_PARSE_FAILURE;
  361. if (prli->command != FC_ELS_ACC)
  362. return FC_PARSE_FAILURE;
  363. if ((prli->parampage.rspcode != FC_PRLI_ACC_XQTD)
  364. && (prli->parampage.rspcode != FC_PRLI_ACC_PREDEF_IMG))
  365. return FC_PARSE_FAILURE;
  366. if (prli->parampage.servparams.target != 1)
  367. return FC_PARSE_FAILURE;
  368. return FC_PARSE_OK;
  369. }
  370. enum fc_parse_status
  371. fc_prli_parse(struct fc_prli_s *prli)
  372. {
  373. if (prli->parampage.type != FC_TYPE_FCP)
  374. return FC_PARSE_FAILURE;
  375. if (!prli->parampage.imagepair)
  376. return FC_PARSE_FAILURE;
  377. if (!prli->parampage.servparams.initiator)
  378. return FC_PARSE_FAILURE;
  379. return FC_PARSE_OK;
  380. }
  381. u16
  382. fc_logo_build(struct fchs_s *fchs, struct fc_logo_s *logo, u32 d_id, u32 s_id,
  383. u16 ox_id, wwn_t port_name)
  384. {
  385. fc_els_req_build(fchs, d_id, s_id, ox_id);
  386. memset(logo, '\0', sizeof(struct fc_logo_s));
  387. logo->els_cmd.els_code = FC_ELS_LOGO;
  388. logo->nport_id = (s_id);
  389. logo->orig_port_name = port_name;
  390. return sizeof(struct fc_logo_s);
  391. }
  392. static u16
  393. fc_adisc_x_build(struct fchs_s *fchs, struct fc_adisc_s *adisc, u32 d_id,
  394. u32 s_id, __be16 ox_id, wwn_t port_name,
  395. wwn_t node_name, u8 els_code)
  396. {
  397. memset(adisc, '\0', sizeof(struct fc_adisc_s));
  398. adisc->els_cmd.els_code = els_code;
  399. if (els_code == FC_ELS_ADISC)
  400. fc_els_req_build(fchs, d_id, s_id, ox_id);
  401. else
  402. fc_els_rsp_build(fchs, d_id, s_id, ox_id);
  403. adisc->orig_HA = 0;
  404. adisc->orig_port_name = port_name;
  405. adisc->orig_node_name = node_name;
  406. adisc->nport_id = (s_id);
  407. return sizeof(struct fc_adisc_s);
  408. }
  409. u16
  410. fc_adisc_build(struct fchs_s *fchs, struct fc_adisc_s *adisc, u32 d_id,
  411. u32 s_id, __be16 ox_id, wwn_t port_name, wwn_t node_name)
  412. {
  413. return fc_adisc_x_build(fchs, adisc, d_id, s_id, ox_id, port_name,
  414. node_name, FC_ELS_ADISC);
  415. }
  416. u16
  417. fc_adisc_acc_build(struct fchs_s *fchs, struct fc_adisc_s *adisc, u32 d_id,
  418. u32 s_id, __be16 ox_id, wwn_t port_name,
  419. wwn_t node_name)
  420. {
  421. return fc_adisc_x_build(fchs, adisc, d_id, s_id, ox_id, port_name,
  422. node_name, FC_ELS_ACC);
  423. }
  424. enum fc_parse_status
  425. fc_adisc_rsp_parse(struct fc_adisc_s *adisc, int len, wwn_t port_name,
  426. wwn_t node_name)
  427. {
  428. if (len < sizeof(struct fc_adisc_s))
  429. return FC_PARSE_FAILURE;
  430. if (adisc->els_cmd.els_code != FC_ELS_ACC)
  431. return FC_PARSE_FAILURE;
  432. if (!wwn_is_equal(adisc->orig_port_name, port_name))
  433. return FC_PARSE_FAILURE;
  434. return FC_PARSE_OK;
  435. }
  436. enum fc_parse_status
  437. fc_adisc_parse(struct fchs_s *fchs, void *pld, u32 host_dap, wwn_t node_name,
  438. wwn_t port_name)
  439. {
  440. struct fc_adisc_s *adisc = (struct fc_adisc_s *) pld;
  441. if (adisc->els_cmd.els_code != FC_ELS_ACC)
  442. return FC_PARSE_FAILURE;
  443. if ((adisc->nport_id == (host_dap))
  444. && wwn_is_equal(adisc->orig_port_name, port_name)
  445. && wwn_is_equal(adisc->orig_node_name, node_name))
  446. return FC_PARSE_OK;
  447. return FC_PARSE_FAILURE;
  448. }
  449. enum fc_parse_status
  450. fc_pdisc_parse(struct fchs_s *fchs, wwn_t node_name, wwn_t port_name)
  451. {
  452. struct fc_logi_s *pdisc = (struct fc_logi_s *) (fchs + 1);
  453. if (pdisc->class3.class_valid != 1)
  454. return FC_PARSE_FAILURE;
  455. if ((be16_to_cpu(pdisc->class3.rxsz) <
  456. (FC_MIN_PDUSZ - sizeof(struct fchs_s)))
  457. || (pdisc->class3.rxsz == 0))
  458. return FC_PARSE_FAILURE;
  459. if (!wwn_is_equal(pdisc->port_name, port_name))
  460. return FC_PARSE_FAILURE;
  461. if (!wwn_is_equal(pdisc->node_name, node_name))
  462. return FC_PARSE_FAILURE;
  463. return FC_PARSE_OK;
  464. }
  465. u16
  466. fc_abts_build(struct fchs_s *fchs, u32 d_id, u32 s_id, u16 ox_id)
  467. {
  468. memcpy(fchs, &fc_bls_req_tmpl, sizeof(struct fchs_s));
  469. fchs->cat_info = FC_CAT_ABTS;
  470. fchs->d_id = (d_id);
  471. fchs->s_id = (s_id);
  472. fchs->ox_id = cpu_to_be16(ox_id);
  473. return sizeof(struct fchs_s);
  474. }
  475. enum fc_parse_status
  476. fc_abts_rsp_parse(struct fchs_s *fchs, int len)
  477. {
  478. if ((fchs->cat_info == FC_CAT_BA_ACC)
  479. || (fchs->cat_info == FC_CAT_BA_RJT))
  480. return FC_PARSE_OK;
  481. return FC_PARSE_FAILURE;
  482. }
  483. u16
  484. fc_rrq_build(struct fchs_s *fchs, struct fc_rrq_s *rrq, u32 d_id, u32 s_id,
  485. u16 ox_id, u16 rrq_oxid)
  486. {
  487. fc_els_req_build(fchs, d_id, s_id, ox_id);
  488. /*
  489. * build rrq payload
  490. */
  491. memcpy(rrq, &rrq_tmpl, sizeof(struct fc_rrq_s));
  492. rrq->s_id = (s_id);
  493. rrq->ox_id = cpu_to_be16(rrq_oxid);
  494. rrq->rx_id = FC_RXID_ANY;
  495. return sizeof(struct fc_rrq_s);
  496. }
  497. u16
  498. fc_logo_acc_build(struct fchs_s *fchs, void *pld, u32 d_id, u32 s_id,
  499. __be16 ox_id)
  500. {
  501. struct fc_els_cmd_s *acc = pld;
  502. fc_els_rsp_build(fchs, d_id, s_id, ox_id);
  503. memset(acc, 0, sizeof(struct fc_els_cmd_s));
  504. acc->els_code = FC_ELS_ACC;
  505. return sizeof(struct fc_els_cmd_s);
  506. }
  507. u16
  508. fc_ls_rjt_build(struct fchs_s *fchs, struct fc_ls_rjt_s *ls_rjt, u32 d_id,
  509. u32 s_id, __be16 ox_id, u8 reason_code,
  510. u8 reason_code_expl)
  511. {
  512. fc_els_rsp_build(fchs, d_id, s_id, ox_id);
  513. memset(ls_rjt, 0, sizeof(struct fc_ls_rjt_s));
  514. ls_rjt->els_cmd.els_code = FC_ELS_LS_RJT;
  515. ls_rjt->reason_code = reason_code;
  516. ls_rjt->reason_code_expl = reason_code_expl;
  517. ls_rjt->vendor_unique = 0x00;
  518. return sizeof(struct fc_ls_rjt_s);
  519. }
  520. u16
  521. fc_ba_acc_build(struct fchs_s *fchs, struct fc_ba_acc_s *ba_acc, u32 d_id,
  522. u32 s_id, __be16 ox_id, u16 rx_id)
  523. {
  524. fc_bls_rsp_build(fchs, d_id, s_id, ox_id);
  525. memcpy(ba_acc, &ba_acc_tmpl, sizeof(struct fc_ba_acc_s));
  526. fchs->rx_id = rx_id;
  527. ba_acc->ox_id = fchs->ox_id;
  528. ba_acc->rx_id = fchs->rx_id;
  529. return sizeof(struct fc_ba_acc_s);
  530. }
  531. u16
  532. fc_ls_acc_build(struct fchs_s *fchs, struct fc_els_cmd_s *els_cmd, u32 d_id,
  533. u32 s_id, __be16 ox_id)
  534. {
  535. fc_els_rsp_build(fchs, d_id, s_id, ox_id);
  536. memset(els_cmd, 0, sizeof(struct fc_els_cmd_s));
  537. els_cmd->els_code = FC_ELS_ACC;
  538. return sizeof(struct fc_els_cmd_s);
  539. }
  540. int
  541. fc_logout_params_pages(struct fchs_s *fc_frame, u8 els_code)
  542. {
  543. int num_pages = 0;
  544. struct fc_prlo_s *prlo;
  545. struct fc_tprlo_s *tprlo;
  546. if (els_code == FC_ELS_PRLO) {
  547. prlo = (struct fc_prlo_s *) (fc_frame + 1);
  548. num_pages = (be16_to_cpu(prlo->payload_len) - 4) / 16;
  549. } else {
  550. tprlo = (struct fc_tprlo_s *) (fc_frame + 1);
  551. num_pages = (be16_to_cpu(tprlo->payload_len) - 4) / 16;
  552. }
  553. return num_pages;
  554. }
  555. u16
  556. fc_tprlo_acc_build(struct fchs_s *fchs, struct fc_tprlo_acc_s *tprlo_acc,
  557. u32 d_id, u32 s_id, __be16 ox_id, int num_pages)
  558. {
  559. int page;
  560. fc_els_rsp_build(fchs, d_id, s_id, ox_id);
  561. memset(tprlo_acc, 0, (num_pages * 16) + 4);
  562. tprlo_acc->command = FC_ELS_ACC;
  563. tprlo_acc->page_len = 0x10;
  564. tprlo_acc->payload_len = cpu_to_be16((num_pages * 16) + 4);
  565. for (page = 0; page < num_pages; page++) {
  566. tprlo_acc->tprlo_acc_params[page].opa_valid = 0;
  567. tprlo_acc->tprlo_acc_params[page].rpa_valid = 0;
  568. tprlo_acc->tprlo_acc_params[page].fc4type_csp = FC_TYPE_FCP;
  569. tprlo_acc->tprlo_acc_params[page].orig_process_assc = 0;
  570. tprlo_acc->tprlo_acc_params[page].resp_process_assc = 0;
  571. }
  572. return be16_to_cpu(tprlo_acc->payload_len);
  573. }
  574. u16
  575. fc_prlo_acc_build(struct fchs_s *fchs, struct fc_prlo_acc_s *prlo_acc, u32 d_id,
  576. u32 s_id, __be16 ox_id, int num_pages)
  577. {
  578. int page;
  579. fc_els_rsp_build(fchs, d_id, s_id, ox_id);
  580. memset(prlo_acc, 0, (num_pages * 16) + 4);
  581. prlo_acc->command = FC_ELS_ACC;
  582. prlo_acc->page_len = 0x10;
  583. prlo_acc->payload_len = cpu_to_be16((num_pages * 16) + 4);
  584. for (page = 0; page < num_pages; page++) {
  585. prlo_acc->prlo_acc_params[page].opa_valid = 0;
  586. prlo_acc->prlo_acc_params[page].rpa_valid = 0;
  587. prlo_acc->prlo_acc_params[page].fc4type_csp = FC_TYPE_FCP;
  588. prlo_acc->prlo_acc_params[page].orig_process_assc = 0;
  589. prlo_acc->prlo_acc_params[page].resp_process_assc = 0;
  590. }
  591. return be16_to_cpu(prlo_acc->payload_len);
  592. }
  593. u16
  594. fc_rnid_build(struct fchs_s *fchs, struct fc_rnid_cmd_s *rnid, u32 d_id,
  595. u32 s_id, u16 ox_id, u32 data_format)
  596. {
  597. fc_els_req_build(fchs, d_id, s_id, ox_id);
  598. memset(rnid, 0, sizeof(struct fc_rnid_cmd_s));
  599. rnid->els_cmd.els_code = FC_ELS_RNID;
  600. rnid->node_id_data_format = data_format;
  601. return sizeof(struct fc_rnid_cmd_s);
  602. }
  603. u16
  604. fc_rnid_acc_build(struct fchs_s *fchs, struct fc_rnid_acc_s *rnid_acc, u32 d_id,
  605. u32 s_id, __be16 ox_id, u32 data_format,
  606. struct fc_rnid_common_id_data_s *common_id_data,
  607. struct fc_rnid_general_topology_data_s *gen_topo_data)
  608. {
  609. memset(rnid_acc, 0, sizeof(struct fc_rnid_acc_s));
  610. fc_els_rsp_build(fchs, d_id, s_id, ox_id);
  611. rnid_acc->els_cmd.els_code = FC_ELS_ACC;
  612. rnid_acc->node_id_data_format = data_format;
  613. rnid_acc->common_id_data_length =
  614. sizeof(struct fc_rnid_common_id_data_s);
  615. rnid_acc->common_id_data = *common_id_data;
  616. if (data_format == RNID_NODEID_DATA_FORMAT_DISCOVERY) {
  617. rnid_acc->specific_id_data_length =
  618. sizeof(struct fc_rnid_general_topology_data_s);
  619. rnid_acc->gen_topology_data = *gen_topo_data;
  620. return sizeof(struct fc_rnid_acc_s);
  621. } else {
  622. return sizeof(struct fc_rnid_acc_s) -
  623. sizeof(struct fc_rnid_general_topology_data_s);
  624. }
  625. }
  626. u16
  627. fc_rpsc_build(struct fchs_s *fchs, struct fc_rpsc_cmd_s *rpsc, u32 d_id,
  628. u32 s_id, u16 ox_id)
  629. {
  630. fc_els_req_build(fchs, d_id, s_id, ox_id);
  631. memset(rpsc, 0, sizeof(struct fc_rpsc_cmd_s));
  632. rpsc->els_cmd.els_code = FC_ELS_RPSC;
  633. return sizeof(struct fc_rpsc_cmd_s);
  634. }
  635. u16
  636. fc_rpsc2_build(struct fchs_s *fchs, struct fc_rpsc2_cmd_s *rpsc2, u32 d_id,
  637. u32 s_id, u32 *pid_list, u16 npids)
  638. {
  639. u32 dctlr_id = FC_DOMAIN_CTRLR(bfa_hton3b(d_id));
  640. int i = 0;
  641. fc_els_req_build(fchs, bfa_hton3b(dctlr_id), s_id, 0);
  642. memset(rpsc2, 0, sizeof(struct fc_rpsc2_cmd_s));
  643. rpsc2->els_cmd.els_code = FC_ELS_RPSC;
  644. rpsc2->token = cpu_to_be32(FC_BRCD_TOKEN);
  645. rpsc2->num_pids = cpu_to_be16(npids);
  646. for (i = 0; i < npids; i++)
  647. rpsc2->pid_list[i].pid = pid_list[i];
  648. return sizeof(struct fc_rpsc2_cmd_s) + ((npids - 1) * (sizeof(u32)));
  649. }
  650. u16
  651. fc_rpsc_acc_build(struct fchs_s *fchs, struct fc_rpsc_acc_s *rpsc_acc,
  652. u32 d_id, u32 s_id, __be16 ox_id,
  653. struct fc_rpsc_speed_info_s *oper_speed)
  654. {
  655. memset(rpsc_acc, 0, sizeof(struct fc_rpsc_acc_s));
  656. fc_els_rsp_build(fchs, d_id, s_id, ox_id);
  657. rpsc_acc->command = FC_ELS_ACC;
  658. rpsc_acc->num_entries = cpu_to_be16(1);
  659. rpsc_acc->speed_info[0].port_speed_cap =
  660. cpu_to_be16(oper_speed->port_speed_cap);
  661. rpsc_acc->speed_info[0].port_op_speed =
  662. cpu_to_be16(oper_speed->port_op_speed);
  663. return sizeof(struct fc_rpsc_acc_s);
  664. }
  665. u16
  666. fc_logo_rsp_parse(struct fchs_s *fchs, int len)
  667. {
  668. struct fc_els_cmd_s *els_cmd = (struct fc_els_cmd_s *) (fchs + 1);
  669. len = len;
  670. if (els_cmd->els_code != FC_ELS_ACC)
  671. return FC_PARSE_FAILURE;
  672. return FC_PARSE_OK;
  673. }
  674. u16
  675. fc_pdisc_build(struct fchs_s *fchs, u32 d_id, u32 s_id, u16 ox_id,
  676. wwn_t port_name, wwn_t node_name, u16 pdu_size)
  677. {
  678. struct fc_logi_s *pdisc = (struct fc_logi_s *) (fchs + 1);
  679. memcpy(pdisc, &plogi_tmpl, sizeof(struct fc_logi_s));
  680. pdisc->els_cmd.els_code = FC_ELS_PDISC;
  681. fc_els_req_build(fchs, d_id, s_id, ox_id);
  682. pdisc->csp.rxsz = pdisc->class3.rxsz = cpu_to_be16(pdu_size);
  683. pdisc->port_name = port_name;
  684. pdisc->node_name = node_name;
  685. return sizeof(struct fc_logi_s);
  686. }
  687. u16
  688. fc_pdisc_rsp_parse(struct fchs_s *fchs, int len, wwn_t port_name)
  689. {
  690. struct fc_logi_s *pdisc = (struct fc_logi_s *) (fchs + 1);
  691. if (len < sizeof(struct fc_logi_s))
  692. return FC_PARSE_LEN_INVAL;
  693. if (pdisc->els_cmd.els_code != FC_ELS_ACC)
  694. return FC_PARSE_ACC_INVAL;
  695. if (!wwn_is_equal(pdisc->port_name, port_name))
  696. return FC_PARSE_PWWN_NOT_EQUAL;
  697. if (!pdisc->class3.class_valid)
  698. return FC_PARSE_NWWN_NOT_EQUAL;
  699. if (be16_to_cpu(pdisc->class3.rxsz) < (FC_MIN_PDUSZ))
  700. return FC_PARSE_RXSZ_INVAL;
  701. return FC_PARSE_OK;
  702. }
  703. u16
  704. fc_prlo_build(struct fchs_s *fchs, u32 d_id, u32 s_id, u16 ox_id,
  705. int num_pages)
  706. {
  707. struct fc_prlo_s *prlo = (struct fc_prlo_s *) (fchs + 1);
  708. int page;
  709. fc_els_req_build(fchs, d_id, s_id, ox_id);
  710. memset(prlo, 0, (num_pages * 16) + 4);
  711. prlo->command = FC_ELS_PRLO;
  712. prlo->page_len = 0x10;
  713. prlo->payload_len = cpu_to_be16((num_pages * 16) + 4);
  714. for (page = 0; page < num_pages; page++) {
  715. prlo->prlo_params[page].type = FC_TYPE_FCP;
  716. prlo->prlo_params[page].opa_valid = 0;
  717. prlo->prlo_params[page].rpa_valid = 0;
  718. prlo->prlo_params[page].orig_process_assc = 0;
  719. prlo->prlo_params[page].resp_process_assc = 0;
  720. }
  721. return be16_to_cpu(prlo->payload_len);
  722. }
  723. u16
  724. fc_prlo_rsp_parse(struct fchs_s *fchs, int len)
  725. {
  726. struct fc_prlo_acc_s *prlo = (struct fc_prlo_acc_s *) (fchs + 1);
  727. int num_pages = 0;
  728. int page = 0;
  729. len = len;
  730. if (prlo->command != FC_ELS_ACC)
  731. return FC_PARSE_FAILURE;
  732. num_pages = ((be16_to_cpu(prlo->payload_len)) - 4) / 16;
  733. for (page = 0; page < num_pages; page++) {
  734. if (prlo->prlo_acc_params[page].type != FC_TYPE_FCP)
  735. return FC_PARSE_FAILURE;
  736. if (prlo->prlo_acc_params[page].opa_valid != 0)
  737. return FC_PARSE_FAILURE;
  738. if (prlo->prlo_acc_params[page].rpa_valid != 0)
  739. return FC_PARSE_FAILURE;
  740. if (prlo->prlo_acc_params[page].orig_process_assc != 0)
  741. return FC_PARSE_FAILURE;
  742. if (prlo->prlo_acc_params[page].resp_process_assc != 0)
  743. return FC_PARSE_FAILURE;
  744. }
  745. return FC_PARSE_OK;
  746. }
  747. u16
  748. fc_tprlo_build(struct fchs_s *fchs, u32 d_id, u32 s_id, u16 ox_id,
  749. int num_pages, enum fc_tprlo_type tprlo_type, u32 tpr_id)
  750. {
  751. struct fc_tprlo_s *tprlo = (struct fc_tprlo_s *) (fchs + 1);
  752. int page;
  753. fc_els_req_build(fchs, d_id, s_id, ox_id);
  754. memset(tprlo, 0, (num_pages * 16) + 4);
  755. tprlo->command = FC_ELS_TPRLO;
  756. tprlo->page_len = 0x10;
  757. tprlo->payload_len = cpu_to_be16((num_pages * 16) + 4);
  758. for (page = 0; page < num_pages; page++) {
  759. tprlo->tprlo_params[page].type = FC_TYPE_FCP;
  760. tprlo->tprlo_params[page].opa_valid = 0;
  761. tprlo->tprlo_params[page].rpa_valid = 0;
  762. tprlo->tprlo_params[page].orig_process_assc = 0;
  763. tprlo->tprlo_params[page].resp_process_assc = 0;
  764. if (tprlo_type == FC_GLOBAL_LOGO) {
  765. tprlo->tprlo_params[page].global_process_logout = 1;
  766. } else if (tprlo_type == FC_TPR_LOGO) {
  767. tprlo->tprlo_params[page].tpo_nport_valid = 1;
  768. tprlo->tprlo_params[page].tpo_nport_id = (tpr_id);
  769. }
  770. }
  771. return be16_to_cpu(tprlo->payload_len);
  772. }
  773. u16
  774. fc_tprlo_rsp_parse(struct fchs_s *fchs, int len)
  775. {
  776. struct fc_tprlo_acc_s *tprlo = (struct fc_tprlo_acc_s *) (fchs + 1);
  777. int num_pages = 0;
  778. int page = 0;
  779. len = len;
  780. if (tprlo->command != FC_ELS_ACC)
  781. return FC_PARSE_ACC_INVAL;
  782. num_pages = (be16_to_cpu(tprlo->payload_len) - 4) / 16;
  783. for (page = 0; page < num_pages; page++) {
  784. if (tprlo->tprlo_acc_params[page].type != FC_TYPE_FCP)
  785. return FC_PARSE_NOT_FCP;
  786. if (tprlo->tprlo_acc_params[page].opa_valid != 0)
  787. return FC_PARSE_OPAFLAG_INVAL;
  788. if (tprlo->tprlo_acc_params[page].rpa_valid != 0)
  789. return FC_PARSE_RPAFLAG_INVAL;
  790. if (tprlo->tprlo_acc_params[page].orig_process_assc != 0)
  791. return FC_PARSE_OPA_INVAL;
  792. if (tprlo->tprlo_acc_params[page].resp_process_assc != 0)
  793. return FC_PARSE_RPA_INVAL;
  794. }
  795. return FC_PARSE_OK;
  796. }
  797. enum fc_parse_status
  798. fc_rrq_rsp_parse(struct fchs_s *fchs, int len)
  799. {
  800. struct fc_els_cmd_s *els_cmd = (struct fc_els_cmd_s *) (fchs + 1);
  801. len = len;
  802. if (els_cmd->els_code != FC_ELS_ACC)
  803. return FC_PARSE_FAILURE;
  804. return FC_PARSE_OK;
  805. }
  806. u16
  807. fc_ba_rjt_build(struct fchs_s *fchs, u32 d_id, u32 s_id, __be16 ox_id,
  808. u32 reason_code, u32 reason_expl)
  809. {
  810. struct fc_ba_rjt_s *ba_rjt = (struct fc_ba_rjt_s *) (fchs + 1);
  811. fc_bls_rsp_build(fchs, d_id, s_id, ox_id);
  812. fchs->cat_info = FC_CAT_BA_RJT;
  813. ba_rjt->reason_code = reason_code;
  814. ba_rjt->reason_expl = reason_expl;
  815. return sizeof(struct fc_ba_rjt_s);
  816. }
  817. static void
  818. fc_gs_cthdr_build(struct ct_hdr_s *cthdr, u32 s_id, u16 cmd_code)
  819. {
  820. memset(cthdr, 0, sizeof(struct ct_hdr_s));
  821. cthdr->rev_id = CT_GS3_REVISION;
  822. cthdr->gs_type = CT_GSTYPE_DIRSERVICE;
  823. cthdr->gs_sub_type = CT_GSSUBTYPE_NAMESERVER;
  824. cthdr->cmd_rsp_code = cpu_to_be16(cmd_code);
  825. }
  826. static void
  827. fc_gs_fdmi_cthdr_build(struct ct_hdr_s *cthdr, u32 s_id, u16 cmd_code)
  828. {
  829. memset(cthdr, 0, sizeof(struct ct_hdr_s));
  830. cthdr->rev_id = CT_GS3_REVISION;
  831. cthdr->gs_type = CT_GSTYPE_MGMTSERVICE;
  832. cthdr->gs_sub_type = CT_GSSUBTYPE_HBA_MGMTSERVER;
  833. cthdr->cmd_rsp_code = cpu_to_be16(cmd_code);
  834. }
  835. static void
  836. fc_gs_ms_cthdr_build(struct ct_hdr_s *cthdr, u32 s_id, u16 cmd_code,
  837. u8 sub_type)
  838. {
  839. memset(cthdr, 0, sizeof(struct ct_hdr_s));
  840. cthdr->rev_id = CT_GS3_REVISION;
  841. cthdr->gs_type = CT_GSTYPE_MGMTSERVICE;
  842. cthdr->gs_sub_type = sub_type;
  843. cthdr->cmd_rsp_code = cpu_to_be16(cmd_code);
  844. }
  845. u16
  846. fc_gidpn_build(struct fchs_s *fchs, void *pyld, u32 s_id, u16 ox_id,
  847. wwn_t port_name)
  848. {
  849. struct ct_hdr_s *cthdr = (struct ct_hdr_s *) pyld;
  850. struct fcgs_gidpn_req_s *gidpn = (struct fcgs_gidpn_req_s *)(cthdr + 1);
  851. u32 d_id = bfa_hton3b(FC_NAME_SERVER);
  852. fc_gs_fchdr_build(fchs, d_id, s_id, ox_id);
  853. fc_gs_cthdr_build(cthdr, s_id, GS_GID_PN);
  854. memset(gidpn, 0, sizeof(struct fcgs_gidpn_req_s));
  855. gidpn->port_name = port_name;
  856. return sizeof(struct fcgs_gidpn_req_s) + sizeof(struct ct_hdr_s);
  857. }
  858. u16
  859. fc_gpnid_build(struct fchs_s *fchs, void *pyld, u32 s_id, u16 ox_id,
  860. u32 port_id)
  861. {
  862. struct ct_hdr_s *cthdr = (struct ct_hdr_s *) pyld;
  863. fcgs_gpnid_req_t *gpnid = (fcgs_gpnid_req_t *) (cthdr + 1);
  864. u32 d_id = bfa_hton3b(FC_NAME_SERVER);
  865. fc_gs_fchdr_build(fchs, d_id, s_id, ox_id);
  866. fc_gs_cthdr_build(cthdr, s_id, GS_GPN_ID);
  867. memset(gpnid, 0, sizeof(fcgs_gpnid_req_t));
  868. gpnid->dap = port_id;
  869. return sizeof(fcgs_gpnid_req_t) + sizeof(struct ct_hdr_s);
  870. }
  871. u16
  872. fc_gnnid_build(struct fchs_s *fchs, void *pyld, u32 s_id, u16 ox_id,
  873. u32 port_id)
  874. {
  875. struct ct_hdr_s *cthdr = (struct ct_hdr_s *) pyld;
  876. fcgs_gnnid_req_t *gnnid = (fcgs_gnnid_req_t *) (cthdr + 1);
  877. u32 d_id = bfa_hton3b(FC_NAME_SERVER);
  878. fc_gs_fchdr_build(fchs, d_id, s_id, ox_id);
  879. fc_gs_cthdr_build(cthdr, s_id, GS_GNN_ID);
  880. memset(gnnid, 0, sizeof(fcgs_gnnid_req_t));
  881. gnnid->dap = port_id;
  882. return sizeof(fcgs_gnnid_req_t) + sizeof(struct ct_hdr_s);
  883. }
  884. u16
  885. fc_ct_rsp_parse(struct ct_hdr_s *cthdr)
  886. {
  887. if (be16_to_cpu(cthdr->cmd_rsp_code) != CT_RSP_ACCEPT) {
  888. if (cthdr->reason_code == CT_RSN_LOGICAL_BUSY)
  889. return FC_PARSE_BUSY;
  890. else
  891. return FC_PARSE_FAILURE;
  892. }
  893. return FC_PARSE_OK;
  894. }
  895. u16
  896. fc_gs_rjt_build(struct fchs_s *fchs, struct ct_hdr_s *cthdr,
  897. u32 d_id, u32 s_id, u16 ox_id, u8 reason_code,
  898. u8 reason_code_expl)
  899. {
  900. fc_gsresp_fchdr_build(fchs, d_id, s_id, ox_id);
  901. cthdr->cmd_rsp_code = cpu_to_be16(CT_RSP_REJECT);
  902. cthdr->rev_id = CT_GS3_REVISION;
  903. cthdr->reason_code = reason_code;
  904. cthdr->exp_code = reason_code_expl;
  905. return sizeof(struct ct_hdr_s);
  906. }
  907. u16
  908. fc_scr_build(struct fchs_s *fchs, struct fc_scr_s *scr,
  909. u8 set_br_reg, u32 s_id, u16 ox_id)
  910. {
  911. u32 d_id = bfa_hton3b(FC_FABRIC_CONTROLLER);
  912. fc_els_req_build(fchs, d_id, s_id, ox_id);
  913. memset(scr, 0, sizeof(struct fc_scr_s));
  914. scr->command = FC_ELS_SCR;
  915. scr->reg_func = FC_SCR_REG_FUNC_FULL;
  916. if (set_br_reg)
  917. scr->vu_reg_func = FC_VU_SCR_REG_FUNC_FABRIC_NAME_CHANGE;
  918. return sizeof(struct fc_scr_s);
  919. }
  920. u16
  921. fc_rscn_build(struct fchs_s *fchs, struct fc_rscn_pl_s *rscn,
  922. u32 s_id, u16 ox_id)
  923. {
  924. u32 d_id = bfa_hton3b(FC_FABRIC_CONTROLLER);
  925. u16 payldlen;
  926. fc_els_req_build(fchs, d_id, s_id, ox_id);
  927. rscn->command = FC_ELS_RSCN;
  928. rscn->pagelen = sizeof(rscn->event[0]);
  929. payldlen = sizeof(u32) + rscn->pagelen;
  930. rscn->payldlen = cpu_to_be16(payldlen);
  931. rscn->event[0].format = FC_RSCN_FORMAT_PORTID;
  932. rscn->event[0].portid = s_id;
  933. return sizeof(struct fc_rscn_pl_s);
  934. }
  935. u16
  936. fc_rftid_build(struct fchs_s *fchs, void *pyld, u32 s_id, u16 ox_id,
  937. enum bfa_lport_role roles)
  938. {
  939. struct ct_hdr_s *cthdr = (struct ct_hdr_s *) pyld;
  940. struct fcgs_rftid_req_s *rftid = (struct fcgs_rftid_req_s *)(cthdr + 1);
  941. u32 type_value, d_id = bfa_hton3b(FC_NAME_SERVER);
  942. u8 index;
  943. fc_gs_fchdr_build(fchs, d_id, s_id, ox_id);
  944. fc_gs_cthdr_build(cthdr, s_id, GS_RFT_ID);
  945. memset(rftid, 0, sizeof(struct fcgs_rftid_req_s));
  946. rftid->dap = s_id;
  947. /* By default, FCP FC4 Type is registered */
  948. index = FC_TYPE_FCP >> 5;
  949. type_value = 1 << (FC_TYPE_FCP % 32);
  950. rftid->fc4_type[index] = cpu_to_be32(type_value);
  951. return sizeof(struct fcgs_rftid_req_s) + sizeof(struct ct_hdr_s);
  952. }
  953. u16
  954. fc_rftid_build_sol(struct fchs_s *fchs, void *pyld, u32 s_id, u16 ox_id,
  955. u8 *fc4_bitmap, u32 bitmap_size)
  956. {
  957. struct ct_hdr_s *cthdr = (struct ct_hdr_s *) pyld;
  958. struct fcgs_rftid_req_s *rftid = (struct fcgs_rftid_req_s *)(cthdr + 1);
  959. u32 d_id = bfa_hton3b(FC_NAME_SERVER);
  960. fc_gs_fchdr_build(fchs, d_id, s_id, ox_id);
  961. fc_gs_cthdr_build(cthdr, s_id, GS_RFT_ID);
  962. memset(rftid, 0, sizeof(struct fcgs_rftid_req_s));
  963. rftid->dap = s_id;
  964. memcpy((void *)rftid->fc4_type, (void *)fc4_bitmap,
  965. (bitmap_size < 32 ? bitmap_size : 32));
  966. return sizeof(struct fcgs_rftid_req_s) + sizeof(struct ct_hdr_s);
  967. }
  968. u16
  969. fc_rffid_build(struct fchs_s *fchs, void *pyld, u32 s_id, u16 ox_id,
  970. u8 fc4_type, u8 fc4_ftrs)
  971. {
  972. struct ct_hdr_s *cthdr = (struct ct_hdr_s *) pyld;
  973. struct fcgs_rffid_req_s *rffid = (struct fcgs_rffid_req_s *)(cthdr + 1);
  974. u32 d_id = bfa_hton3b(FC_NAME_SERVER);
  975. fc_gs_fchdr_build(fchs, d_id, s_id, ox_id);
  976. fc_gs_cthdr_build(cthdr, s_id, GS_RFF_ID);
  977. memset(rffid, 0, sizeof(struct fcgs_rffid_req_s));
  978. rffid->dap = s_id;
  979. rffid->fc4ftr_bits = fc4_ftrs;
  980. rffid->fc4_type = fc4_type;
  981. return sizeof(struct fcgs_rffid_req_s) + sizeof(struct ct_hdr_s);
  982. }
  983. u16
  984. fc_rspnid_build(struct fchs_s *fchs, void *pyld, u32 s_id, u16 ox_id,
  985. u8 *name)
  986. {
  987. struct ct_hdr_s *cthdr = (struct ct_hdr_s *) pyld;
  988. struct fcgs_rspnid_req_s *rspnid =
  989. (struct fcgs_rspnid_req_s *)(cthdr + 1);
  990. u32 d_id = bfa_hton3b(FC_NAME_SERVER);
  991. fc_gs_fchdr_build(fchs, d_id, s_id, ox_id);
  992. fc_gs_cthdr_build(cthdr, s_id, GS_RSPN_ID);
  993. memset(rspnid, 0, sizeof(struct fcgs_rspnid_req_s));
  994. rspnid->dap = s_id;
  995. rspnid->spn_len = (u8) strlen((char *)name);
  996. strncpy((char *)rspnid->spn, (char *)name, rspnid->spn_len);
  997. return sizeof(struct fcgs_rspnid_req_s) + sizeof(struct ct_hdr_s);
  998. }
  999. u16
  1000. fc_gid_ft_build(struct fchs_s *fchs, void *pyld, u32 s_id, u8 fc4_type)
  1001. {
  1002. struct ct_hdr_s *cthdr = (struct ct_hdr_s *) pyld;
  1003. struct fcgs_gidft_req_s *gidft = (struct fcgs_gidft_req_s *)(cthdr + 1);
  1004. u32 d_id = bfa_hton3b(FC_NAME_SERVER);
  1005. fc_gs_fchdr_build(fchs, d_id, s_id, 0);
  1006. fc_gs_cthdr_build(cthdr, s_id, GS_GID_FT);
  1007. memset(gidft, 0, sizeof(struct fcgs_gidft_req_s));
  1008. gidft->fc4_type = fc4_type;
  1009. gidft->domain_id = 0;
  1010. gidft->area_id = 0;
  1011. return sizeof(struct fcgs_gidft_req_s) + sizeof(struct ct_hdr_s);
  1012. }
  1013. u16
  1014. fc_rpnid_build(struct fchs_s *fchs, void *pyld, u32 s_id, u32 port_id,
  1015. wwn_t port_name)
  1016. {
  1017. struct ct_hdr_s *cthdr = (struct ct_hdr_s *) pyld;
  1018. struct fcgs_rpnid_req_s *rpnid = (struct fcgs_rpnid_req_s *)(cthdr + 1);
  1019. u32 d_id = bfa_hton3b(FC_NAME_SERVER);
  1020. fc_gs_fchdr_build(fchs, d_id, s_id, 0);
  1021. fc_gs_cthdr_build(cthdr, s_id, GS_RPN_ID);
  1022. memset(rpnid, 0, sizeof(struct fcgs_rpnid_req_s));
  1023. rpnid->port_id = port_id;
  1024. rpnid->port_name = port_name;
  1025. return sizeof(struct fcgs_rpnid_req_s) + sizeof(struct ct_hdr_s);
  1026. }
  1027. u16
  1028. fc_rnnid_build(struct fchs_s *fchs, void *pyld, u32 s_id, u32 port_id,
  1029. wwn_t node_name)
  1030. {
  1031. struct ct_hdr_s *cthdr = (struct ct_hdr_s *) pyld;
  1032. struct fcgs_rnnid_req_s *rnnid = (struct fcgs_rnnid_req_s *)(cthdr + 1);
  1033. u32 d_id = bfa_hton3b(FC_NAME_SERVER);
  1034. fc_gs_fchdr_build(fchs, d_id, s_id, 0);
  1035. fc_gs_cthdr_build(cthdr, s_id, GS_RNN_ID);
  1036. memset(rnnid, 0, sizeof(struct fcgs_rnnid_req_s));
  1037. rnnid->port_id = port_id;
  1038. rnnid->node_name = node_name;
  1039. return sizeof(struct fcgs_rnnid_req_s) + sizeof(struct ct_hdr_s);
  1040. }
  1041. u16
  1042. fc_rcsid_build(struct fchs_s *fchs, void *pyld, u32 s_id, u32 port_id,
  1043. u32 cos)
  1044. {
  1045. struct ct_hdr_s *cthdr = (struct ct_hdr_s *) pyld;
  1046. struct fcgs_rcsid_req_s *rcsid =
  1047. (struct fcgs_rcsid_req_s *) (cthdr + 1);
  1048. u32 d_id = bfa_hton3b(FC_NAME_SERVER);
  1049. fc_gs_fchdr_build(fchs, d_id, s_id, 0);
  1050. fc_gs_cthdr_build(cthdr, s_id, GS_RCS_ID);
  1051. memset(rcsid, 0, sizeof(struct fcgs_rcsid_req_s));
  1052. rcsid->port_id = port_id;
  1053. rcsid->cos = cos;
  1054. return sizeof(struct fcgs_rcsid_req_s) + sizeof(struct ct_hdr_s);
  1055. }
  1056. u16
  1057. fc_rptid_build(struct fchs_s *fchs, void *pyld, u32 s_id, u32 port_id,
  1058. u8 port_type)
  1059. {
  1060. struct ct_hdr_s *cthdr = (struct ct_hdr_s *) pyld;
  1061. struct fcgs_rptid_req_s *rptid = (struct fcgs_rptid_req_s *)(cthdr + 1);
  1062. u32 d_id = bfa_hton3b(FC_NAME_SERVER);
  1063. fc_gs_fchdr_build(fchs, d_id, s_id, 0);
  1064. fc_gs_cthdr_build(cthdr, s_id, GS_RPT_ID);
  1065. memset(rptid, 0, sizeof(struct fcgs_rptid_req_s));
  1066. rptid->port_id = port_id;
  1067. rptid->port_type = port_type;
  1068. return sizeof(struct fcgs_rptid_req_s) + sizeof(struct ct_hdr_s);
  1069. }
  1070. u16
  1071. fc_ganxt_build(struct fchs_s *fchs, void *pyld, u32 s_id, u32 port_id)
  1072. {
  1073. struct ct_hdr_s *cthdr = (struct ct_hdr_s *) pyld;
  1074. struct fcgs_ganxt_req_s *ganxt = (struct fcgs_ganxt_req_s *)(cthdr + 1);
  1075. u32 d_id = bfa_hton3b(FC_NAME_SERVER);
  1076. fc_gs_fchdr_build(fchs, d_id, s_id, 0);
  1077. fc_gs_cthdr_build(cthdr, s_id, GS_GA_NXT);
  1078. memset(ganxt, 0, sizeof(struct fcgs_ganxt_req_s));
  1079. ganxt->port_id = port_id;
  1080. return sizeof(struct ct_hdr_s) + sizeof(struct fcgs_ganxt_req_s);
  1081. }
  1082. /*
  1083. * Builds fc hdr and ct hdr for FDMI requests.
  1084. */
  1085. u16
  1086. fc_fdmi_reqhdr_build(struct fchs_s *fchs, void *pyld, u32 s_id,
  1087. u16 cmd_code)
  1088. {
  1089. struct ct_hdr_s *cthdr = (struct ct_hdr_s *) pyld;
  1090. u32 d_id = bfa_hton3b(FC_MGMT_SERVER);
  1091. fc_gs_fchdr_build(fchs, d_id, s_id, 0);
  1092. fc_gs_fdmi_cthdr_build(cthdr, s_id, cmd_code);
  1093. return sizeof(struct ct_hdr_s);
  1094. }
  1095. /*
  1096. * Given a FC4 Type, this function returns a fc4 type bitmask
  1097. */
  1098. void
  1099. fc_get_fc4type_bitmask(u8 fc4_type, u8 *bit_mask)
  1100. {
  1101. u8 index;
  1102. __be32 *ptr = (__be32 *) bit_mask;
  1103. u32 type_value;
  1104. /*
  1105. * @todo : Check for bitmask size
  1106. */
  1107. index = fc4_type >> 5;
  1108. type_value = 1 << (fc4_type % 32);
  1109. ptr[index] = cpu_to_be32(type_value);
  1110. }
  1111. /*
  1112. * GMAL Request
  1113. */
  1114. u16
  1115. fc_gmal_req_build(struct fchs_s *fchs, void *pyld, u32 s_id, wwn_t wwn)
  1116. {
  1117. struct ct_hdr_s *cthdr = (struct ct_hdr_s *) pyld;
  1118. fcgs_gmal_req_t *gmal = (fcgs_gmal_req_t *) (cthdr + 1);
  1119. u32 d_id = bfa_hton3b(FC_MGMT_SERVER);
  1120. fc_gs_fchdr_build(fchs, d_id, s_id, 0);
  1121. fc_gs_ms_cthdr_build(cthdr, s_id, GS_FC_GMAL_CMD,
  1122. CT_GSSUBTYPE_CFGSERVER);
  1123. memset(gmal, 0, sizeof(fcgs_gmal_req_t));
  1124. gmal->wwn = wwn;
  1125. return sizeof(struct ct_hdr_s) + sizeof(fcgs_gmal_req_t);
  1126. }
  1127. /*
  1128. * GFN (Get Fabric Name) Request
  1129. */
  1130. u16
  1131. fc_gfn_req_build(struct fchs_s *fchs, void *pyld, u32 s_id, wwn_t wwn)
  1132. {
  1133. struct ct_hdr_s *cthdr = (struct ct_hdr_s *) pyld;
  1134. fcgs_gfn_req_t *gfn = (fcgs_gfn_req_t *) (cthdr + 1);
  1135. u32 d_id = bfa_hton3b(FC_MGMT_SERVER);
  1136. fc_gs_fchdr_build(fchs, d_id, s_id, 0);
  1137. fc_gs_ms_cthdr_build(cthdr, s_id, GS_FC_GFN_CMD,
  1138. CT_GSSUBTYPE_CFGSERVER);
  1139. memset(gfn, 0, sizeof(fcgs_gfn_req_t));
  1140. gfn->wwn = wwn;
  1141. return sizeof(struct ct_hdr_s) + sizeof(fcgs_gfn_req_t);
  1142. }