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