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