linux/drivers/scsi/bfa/bfa_fcbuild.c
<<
>>
Prefs
   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 */
  27static void     fc_els_rsp_build(struct fchs_s *fchs, u32 d_id, u32 s_id,
  28                                 __be16 ox_id);
  29static void     fc_bls_rsp_build(struct fchs_s *fchs, u32 d_id, u32 s_id,
  30                                 __be16 ox_id);
  31static struct fchs_s fc_els_req_tmpl;
  32static struct fchs_s fc_els_rsp_tmpl;
  33static struct fchs_s fc_bls_req_tmpl;
  34static struct fchs_s fc_bls_rsp_tmpl;
  35static struct fc_ba_acc_s ba_acc_tmpl;
  36static struct fc_logi_s plogi_tmpl;
  37static struct fc_prli_s prli_tmpl;
  38static struct fc_rrq_s rrq_tmpl;
  39static struct fchs_s fcp_fchs_tmpl;
  40
  41void
  42fcbuild_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
 136static void
 137fc_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
 158static void
 159fc_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
 174void
 175fc_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
 183static void
 184fc_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
 192enum fc_parse_status
 193fc_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
 213static void
 214fc_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
 222static          u16
 223fc_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
 250u16
 251fc_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
 288u16
 289fc_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
 310u16
 311fc_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
 328u16
 329fc_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
 337u16
 338fc_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
 346enum fc_parse_status
 347fc_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
 380enum fc_parse_status
 381fc_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
 396u16
 397fc_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
 415u16
 416fc_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
 433enum fc_parse_status
 434fc_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
 452enum fc_parse_status
 453fc_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
 467u16
 468fc_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
 481static u16
 482fc_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
 503u16
 504fc_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
 511u16
 512fc_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
 520enum fc_parse_status
 521fc_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
 537enum fc_parse_status
 538fc_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
 554enum fc_parse_status
 555fc_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
 576u16
 577fc_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
 588enum fc_parse_status
 589fc_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
 598u16
 599fc_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
 615u16
 616fc_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
 629u16
 630fc_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
 645u16
 646fc_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
 661u16
 662fc_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
 672int
 673fc_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
 689u16
 690fc_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
 713u16
 714fc_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
 737u16
 738fc_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
 751u16
 752fc_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
 779u16
 780fc_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
 791u16
 792fc_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
 811u16
 812fc_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
 832u16
 833fc_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
 844u16
 845fc_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
 862u16
 863fc_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
 885u16
 886fc_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
 909u16
 910fc_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
 943u16
 944fc_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
 973u16
 974fc_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
1002enum fc_parse_status
1003fc_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
1014u16
1015fc_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
1028static void
1029fc_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
1038static void
1039fc_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
1048static void
1049fc_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
1059u16
1060fc_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
1075u16
1076fc_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
1091u16
1092fc_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
1107u16
1108fc_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
1120u16
1121fc_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
1135u16
1136fc_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
1152u16
1153fc_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
1172u16
1173fc_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
1196u16
1197fc_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
1216u16
1217fc_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
1236u16
1237fc_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
1258u16
1259fc_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
1279u16
1280fc_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
1299u16
1300fc_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
1317u16
1318fc_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
1335u16
1336fc_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
1354u16
1355fc_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
1372u16
1373fc_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 */
1391u16
1392fc_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 */
1408void
1409fc_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 */
1428u16
1429fc_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 */
1448u16
1449fc_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