1 /*
   2  * CDDL HEADER START
   3  *
   4  * The contents of this file are subject to the terms of the
   5  * Common Development and Distribution License (the "License").
   6  * You may not use this file except in compliance with the License.
   7  *
   8  * You can obtain a copy of the license at
   9  * http://www.opensource.org/licenses/cddl1.txt.
  10  * See the License for the specific language governing permissions
  11  * and limitations under the License.
  12  *
  13  * When distributing Covered Code, include this CDDL HEADER in each
  14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15  * If applicable, add the following below this CDDL HEADER, with the
  16  * fields enclosed by brackets "[]" replaced with your own identifying
  17  * information: Portions Copyright [yyyy] [name of copyright owner]
  18  *
  19  * CDDL HEADER END
  20  */
  21 
  22 /*
  23  * Copyright (c) 2004-2012 Emulex. All rights reserved.
  24  * Use is subject to license terms.
  25  */
  26 
  27 #include <emlxs.h>
  28 
  29 
  30 /* Required for EMLXS_CONTEXT in EMLXS_MSGF calls */
  31 EMLXS_MSG_DEF(EMLXS_SLI4_C);
  32 
  33 static int              emlxs_sli4_init_extents(emlxs_hba_t *hba,
  34                                 MAILBOXQ *mbq);
  35 static uint32_t         emlxs_sli4_read_status(emlxs_hba_t *hba);
  36 
  37 static int              emlxs_init_bootstrap_mb(emlxs_hba_t *hba);
  38 
  39 static uint32_t         emlxs_sli4_read_sema(emlxs_hba_t *hba);
  40 
  41 static uint32_t         emlxs_sli4_read_mbdb(emlxs_hba_t *hba);
  42 
  43 static void             emlxs_sli4_write_mbdb(emlxs_hba_t *hba, uint32_t value);
  44 
  45 static void             emlxs_sli4_write_wqdb(emlxs_hba_t *hba, uint32_t value);
  46 
  47 static void             emlxs_sli4_write_mqdb(emlxs_hba_t *hba, uint32_t value);
  48 
  49 static void             emlxs_sli4_write_rqdb(emlxs_hba_t *hba, uint32_t value);
  50 
  51 static void             emlxs_sli4_write_cqdb(emlxs_hba_t *hba, uint32_t value);
  52 
  53 static int              emlxs_sli4_create_queues(emlxs_hba_t *hba,
  54                                 MAILBOXQ *mbq);
  55 static int              emlxs_sli4_post_hdr_tmplates(emlxs_hba_t *hba,
  56                                 MAILBOXQ *mbq);
  57 static int              emlxs_sli4_post_sgl_pages(emlxs_hba_t *hba,
  58                                 MAILBOXQ *mbq);
  59 
  60 static int              emlxs_sli4_read_eq(emlxs_hba_t *hba, EQ_DESC_t *eq);
  61 
  62 static int              emlxs_sli4_map_hdw(emlxs_hba_t *hba);
  63 
  64 static void             emlxs_sli4_unmap_hdw(emlxs_hba_t *hba);
  65 
  66 static int32_t          emlxs_sli4_online(emlxs_hba_t *hba);
  67 
  68 static void             emlxs_sli4_offline(emlxs_hba_t *hba,
  69                                 uint32_t reset_requested);
  70 
  71 static uint32_t         emlxs_sli4_hba_reset(emlxs_hba_t *hba, uint32_t restart,
  72                                 uint32_t skip_post, uint32_t quiesce);
  73 static void             emlxs_sli4_hba_kill(emlxs_hba_t *hba);
  74 
  75 static uint32_t         emlxs_sli4_hba_init(emlxs_hba_t *hba);
  76 
  77 static uint32_t         emlxs_sli4_bde_setup(emlxs_port_t *port,
  78                                 emlxs_buf_t *sbp);
  79 
  80 static void             emlxs_sli4_issue_iocb_cmd(emlxs_hba_t *hba,
  81                                 CHANNEL *cp, IOCBQ *iocb_cmd);
  82 static uint32_t         emlxs_sli4_issue_mbox_cmd(emlxs_hba_t *hba,
  83                                 MAILBOXQ *mbq, int32_t flg, uint32_t tmo);
  84 static uint32_t         emlxs_sli4_issue_mbox_cmd4quiesce(emlxs_hba_t *hba,
  85                                 MAILBOXQ *mbq, int32_t flg, uint32_t tmo);
  86 #ifdef SFCT_SUPPORT
  87 static uint32_t         emlxs_sli4_prep_fct_iocb(emlxs_port_t *port,
  88                                 emlxs_buf_t *cmd_sbp, int channel);
  89 static uint32_t         emlxs_sli4_fct_bde_setup(emlxs_port_t *port,
  90                                 emlxs_buf_t *sbp);
  91 #endif /* SFCT_SUPPORT */
  92 
  93 static uint32_t         emlxs_sli4_prep_fcp_iocb(emlxs_port_t *port,
  94                                 emlxs_buf_t *sbp, int ring);
  95 static uint32_t         emlxs_sli4_prep_ip_iocb(emlxs_port_t *port,
  96                                 emlxs_buf_t *sbp);
  97 static uint32_t         emlxs_sli4_prep_els_iocb(emlxs_port_t *port,
  98                                 emlxs_buf_t *sbp);
  99 static uint32_t         emlxs_sli4_prep_ct_iocb(emlxs_port_t *port,
 100                                 emlxs_buf_t *sbp);
 101 static void             emlxs_sli4_poll_intr(emlxs_hba_t *hba);
 102 static int32_t          emlxs_sli4_intx_intr(char *arg);
 103 
 104 #ifdef MSI_SUPPORT
 105 static uint32_t         emlxs_sli4_msi_intr(char *arg1, char *arg2);
 106 #endif /* MSI_SUPPORT */
 107 
 108 static void             emlxs_sli4_resource_free(emlxs_hba_t *hba);
 109 
 110 static int              emlxs_sli4_resource_alloc(emlxs_hba_t *hba);
 111 extern void             emlxs_sli4_zero_queue_stat(emlxs_hba_t *hba);
 112 
 113 static XRIobj_t         *emlxs_sli4_alloc_xri(emlxs_port_t *port,
 114                                 emlxs_buf_t *sbp, RPIobj_t *rpip,
 115                                 uint32_t type);
 116 static void             emlxs_sli4_enable_intr(emlxs_hba_t *hba);
 117 
 118 static void             emlxs_sli4_disable_intr(emlxs_hba_t *hba, uint32_t att);
 119 
 120 static void             emlxs_sli4_timer(emlxs_hba_t *hba);
 121 
 122 static void             emlxs_sli4_timer_check_mbox(emlxs_hba_t *hba);
 123 
 124 static void             emlxs_sli4_poll_erratt(emlxs_hba_t *hba);
 125 
 126 extern XRIobj_t         *emlxs_sli4_reserve_xri(emlxs_port_t *port,
 127                                 RPIobj_t *rpip, uint32_t type, uint16_t rx_id);
 128 static int              emlxs_check_hdw_ready(emlxs_hba_t *);
 129 
 130 static uint32_t         emlxs_sli4_reg_did(emlxs_port_t *port,
 131                                 uint32_t did, SERV_PARM *param,
 132                                 emlxs_buf_t *sbp, fc_unsol_buf_t *ubp,
 133                                 IOCBQ *iocbq);
 134 
 135 static uint32_t         emlxs_sli4_unreg_node(emlxs_port_t *port,
 136                                 emlxs_node_t *node, emlxs_buf_t *sbp,
 137                                 fc_unsol_buf_t *ubp, IOCBQ *iocbq);
 138 
 139 static void             emlxs_sli4_handle_fc_link_att(emlxs_hba_t *hba,
 140                                 CQE_ASYNC_t *cqe);
 141 static void             emlxs_sli4_handle_fcoe_link_event(emlxs_hba_t *hba,
 142                                 CQE_ASYNC_t *cqe);
 143 
 144 
 145 static uint16_t         emlxs_sli4_rqid_to_index(emlxs_hba_t *hba,
 146                                 uint16_t rqid);
 147 static uint16_t         emlxs_sli4_wqid_to_index(emlxs_hba_t *hba,
 148                                 uint16_t wqid);
 149 static uint16_t         emlxs_sli4_cqid_to_index(emlxs_hba_t *hba,
 150                                 uint16_t cqid);
 151 
 152 /* Define SLI4 API functions */
 153 emlxs_sli_api_t emlxs_sli4_api = {
 154         emlxs_sli4_map_hdw,
 155         emlxs_sli4_unmap_hdw,
 156         emlxs_sli4_online,
 157         emlxs_sli4_offline,
 158         emlxs_sli4_hba_reset,
 159         emlxs_sli4_hba_kill,
 160         emlxs_sli4_issue_iocb_cmd,
 161         emlxs_sli4_issue_mbox_cmd,
 162 #ifdef SFCT_SUPPORT
 163         emlxs_sli4_prep_fct_iocb,
 164 #else
 165         NULL,
 166 #endif /* SFCT_SUPPORT */
 167         emlxs_sli4_prep_fcp_iocb,
 168         emlxs_sli4_prep_ip_iocb,
 169         emlxs_sli4_prep_els_iocb,
 170         emlxs_sli4_prep_ct_iocb,
 171         emlxs_sli4_poll_intr,
 172         emlxs_sli4_intx_intr,
 173         emlxs_sli4_msi_intr,
 174         emlxs_sli4_disable_intr,
 175         emlxs_sli4_timer,
 176         emlxs_sli4_poll_erratt,
 177         emlxs_sli4_reg_did,
 178         emlxs_sli4_unreg_node
 179 };
 180 
 181 
 182 /* ************************************************************************** */
 183 
 184 static void
 185 emlxs_sli4_set_default_params(emlxs_hba_t *hba)
 186 {
 187         emlxs_port_t *port = &PPORT;
 188 
 189         bzero((char *)&hba->sli.sli4.param, sizeof (sli_params_t));
 190 
 191         hba->sli.sli4.param.ProtocolType = 0x3; /* FC/FCoE */
 192 
 193         hba->sli.sli4.param.SliHint2 = 0;
 194         hba->sli.sli4.param.SliHint1 = 0;
 195         hba->sli.sli4.param.IfType = 0;
 196         hba->sli.sli4.param.SliFamily = 0;
 197         hba->sli.sli4.param.Revision = 0x4; /* SLI4 */
 198         hba->sli.sli4.param.FT = 0;
 199 
 200         hba->sli.sli4.param.EqeCntMethod = 0x1; /* Bit pattern */
 201         hba->sli.sli4.param.EqPageSize = 0x1; /* 4096 */
 202         hba->sli.sli4.param.EqeSize = 0x1; /* 4 byte */
 203         hba->sli.sli4.param.EqPageCnt = 8;
 204         hba->sli.sli4.param.EqeCntMask = 0x1F; /* 256-4096 elements */
 205 
 206         hba->sli.sli4.param.CqeCntMethod = 0x1; /* Bit pattern */
 207         hba->sli.sli4.param.CqPageSize = 0x1; /* 4096 */
 208         hba->sli.sli4.param.CQV = 0;
 209         hba->sli.sli4.param.CqeSize = 0x3; /* 16 byte */
 210         hba->sli.sli4.param.CqPageCnt = 4;
 211         hba->sli.sli4.param.CqeCntMask = 0x70; /* 256-1024 elements */
 212 
 213         hba->sli.sli4.param.MqeCntMethod = 0x1; /* Bit pattern */
 214         hba->sli.sli4.param.MqPageSize = 0x1; /* 4096 */
 215         hba->sli.sli4.param.MQV = 0;
 216         hba->sli.sli4.param.MqPageCnt = 8;
 217         hba->sli.sli4.param.MqeCntMask = 0x0F; /* 16-128 elements */
 218 
 219         hba->sli.sli4.param.WqeCntMethod = 0; /* Page Count */
 220         hba->sli.sli4.param.WqPageSize = 0x1; /* 4096 */
 221         hba->sli.sli4.param.WQV = 0;
 222         hba->sli.sli4.param.WqeSize = 0x5; /* 64 byte */
 223         hba->sli.sli4.param.WqPageCnt = 4;
 224         hba->sli.sli4.param.WqeCntMask = 0x10; /* 256 elements */
 225 
 226         hba->sli.sli4.param.RqeCntMethod = 0; /* Page Count */
 227         hba->sli.sli4.param.RqPageSize = 0x1; /* 4096 */
 228         hba->sli.sli4.param.RQV = 0;
 229         hba->sli.sli4.param.RqeSize = 0x2; /* 8 byte */
 230         hba->sli.sli4.param.RqPageCnt = 8;
 231         hba->sli.sli4.param.RqDbWin = 1;
 232         hba->sli.sli4.param.RqeCntMask = 0x100; /* 4096 elements */
 233 
 234         hba->sli.sli4.param.Loopback = 0xf; /* unsupported */
 235         hba->sli.sli4.param.PHWQ = 0;
 236         hba->sli.sli4.param.PHON = 0;
 237         hba->sli.sli4.param.TRIR = 0;
 238         hba->sli.sli4.param.TRTY = 0;
 239         hba->sli.sli4.param.TCCA = 0;
 240         hba->sli.sli4.param.MWQE = 0;
 241         hba->sli.sli4.param.ASSI = 0;
 242         hba->sli.sli4.param.TERP = 0;
 243         hba->sli.sli4.param.TGT  = 0;
 244         hba->sli.sli4.param.AREG = 0;
 245         hba->sli.sli4.param.FBRR = 0;
 246         hba->sli.sli4.param.SGLR = 1;
 247         hba->sli.sli4.param.HDRR = 1;
 248         hba->sli.sli4.param.EXT  = 0;
 249         hba->sli.sli4.param.FCOE = 1;
 250 
 251         hba->sli.sli4.param.SgeLength = (64 * 1024);
 252         hba->sli.sli4.param.SglAlign = 0x7 /* 4096 */;
 253         hba->sli.sli4.param.SglPageSize = 0x1; /* 4096 */
 254         hba->sli.sli4.param.SglPageCnt = 2;
 255 
 256         hba->sli.sli4.param.MinRqSize = 128;
 257         hba->sli.sli4.param.MaxRqSize = 2048;
 258 
 259         hba->sli.sli4.param.RPIMax = 0x3ff;
 260         hba->sli.sli4.param.XRIMax = 0x3ff;
 261         hba->sli.sli4.param.VFIMax = 0xff;
 262         hba->sli.sli4.param.VPIMax = 0xff;
 263 
 264         EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
 265             "Default SLI4 parameters set.");
 266 
 267 } /* emlxs_sli4_set_default_params() */
 268 
 269 
 270 /*
 271  * emlxs_sli4_online()
 272  *
 273  * This routine will start initialization of the SLI4 HBA.
 274  */
 275 static int32_t
 276 emlxs_sli4_online(emlxs_hba_t *hba)
 277 {
 278         emlxs_port_t *port = &PPORT;
 279         emlxs_config_t *cfg;
 280         emlxs_vpd_t *vpd;
 281         MAILBOXQ *mbq = NULL;
 282         MAILBOX4 *mb  = NULL;
 283         MATCHMAP *mp  = NULL;
 284         uint32_t i;
 285         uint32_t j;
 286         uint32_t rval = 0;
 287         uint8_t *vpd_data;
 288         uint32_t sli_mode;
 289         uint8_t *outptr;
 290         uint32_t status;
 291         uint32_t fw_check;
 292         uint32_t kern_update = 0;
 293         emlxs_firmware_t hba_fw;
 294         emlxs_firmware_t *fw;
 295         uint16_t ssvid;
 296         char buf[64];
 297 
 298         cfg = &CFG;
 299         vpd = &VPD;
 300 
 301         sli_mode = EMLXS_HBA_SLI4_MODE;
 302         hba->sli_mode = sli_mode;
 303 
 304         /* Set the fw_check flag */
 305         fw_check = cfg[CFG_FW_CHECK].current;
 306 
 307         if ((fw_check & 0x04) ||
 308             (hba->fw_flag & FW_UPDATE_KERNEL)) {
 309                 kern_update = 1;
 310         }
 311 
 312         hba->mbox_queue_flag = 0;
 313         hba->fc_edtov = FF_DEF_EDTOV;
 314         hba->fc_ratov = FF_DEF_RATOV;
 315         hba->fc_altov = FF_DEF_ALTOV;
 316         hba->fc_arbtov = FF_DEF_ARBTOV;
 317 
 318         /* Networking not supported */
 319         if (cfg[CFG_NETWORK_ON].current) {
 320                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_msg,
 321                     "Networking is not supported in SLI4, turning it off");
 322                 cfg[CFG_NETWORK_ON].current = 0;
 323         }
 324 
 325         hba->chan_count = hba->intr_count * cfg[CFG_NUM_WQ].current;
 326         if (hba->chan_count > MAX_CHANNEL) {
 327                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg,
 328                     "Max channels exceeded, dropping num-wq from %d to 1",
 329                     cfg[CFG_NUM_WQ].current);
 330                 cfg[CFG_NUM_WQ].current = 1;
 331                 hba->chan_count = hba->intr_count * cfg[CFG_NUM_WQ].current;
 332         }
 333         hba->channel_fcp = 0; /* First channel */
 334 
 335         /* Default channel for everything else is the last channel */
 336         hba->channel_ip = hba->chan_count - 1;
 337         hba->channel_els = hba->chan_count - 1;
 338         hba->channel_ct = hba->chan_count - 1;
 339 
 340         hba->fc_iotag = 1;
 341         hba->io_count = 0;
 342         hba->channel_tx_count = 0;
 343 
 344         /* Initialize the local dump region buffer */
 345         bzero(&hba->sli.sli4.dump_region, sizeof (MBUF_INFO));
 346         hba->sli.sli4.dump_region.size = EMLXS_DUMP_REGION_SIZE;
 347         hba->sli.sli4.dump_region.flags = FC_MBUF_DMA | FC_MBUF_SNGLSG
 348             | FC_MBUF_DMA32;
 349         hba->sli.sli4.dump_region.align = ddi_ptob(hba->dip, 1L);
 350 
 351         (void) emlxs_mem_alloc(hba, &hba->sli.sli4.dump_region);
 352 
 353         if (hba->sli.sli4.dump_region.virt == NULL) {
 354                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg,
 355                     "Unable to allocate dump region buffer.");
 356 
 357                 return (ENOMEM);
 358         }
 359 
 360         /*
 361          * Get a buffer which will be used repeatedly for mailbox commands
 362          */
 363         mbq = (MAILBOXQ *) kmem_zalloc((sizeof (MAILBOXQ)), KM_SLEEP);
 364 
 365         mb = (MAILBOX4 *)mbq;
 366 
 367 reset:
 368         /* Reset & Initialize the adapter */
 369         if (emlxs_sli4_hba_init(hba)) {
 370                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg,
 371                     "Unable to init hba.");
 372 
 373                 rval = EIO;
 374                 goto failed1;
 375         }
 376 
 377 #ifdef FMA_SUPPORT
 378         /* Access handle validation */
 379         switch (hba->sli_intf & SLI_INTF_IF_TYPE_MASK) {
 380         case SLI_INTF_IF_TYPE_2:
 381                 if ((emlxs_fm_check_acc_handle(hba,
 382                     hba->pci_acc_handle) != DDI_FM_OK) ||
 383                     (emlxs_fm_check_acc_handle(hba,
 384                     hba->sli.sli4.bar0_acc_handle) != DDI_FM_OK)) {
 385                         EMLXS_MSGF(EMLXS_CONTEXT,
 386                             &emlxs_invalid_access_handle_msg, NULL);
 387 
 388                         rval = EIO;
 389                         goto failed1;
 390                 }
 391                 break;
 392 
 393         default :
 394                 if ((emlxs_fm_check_acc_handle(hba,
 395                     hba->pci_acc_handle) != DDI_FM_OK) ||
 396                     (emlxs_fm_check_acc_handle(hba,
 397                     hba->sli.sli4.bar1_acc_handle) != DDI_FM_OK) ||
 398                     (emlxs_fm_check_acc_handle(hba,
 399                     hba->sli.sli4.bar2_acc_handle) != DDI_FM_OK)) {
 400                         EMLXS_MSGF(EMLXS_CONTEXT,
 401                             &emlxs_invalid_access_handle_msg, NULL);
 402 
 403                         rval = EIO;
 404                         goto failed1;
 405                 }
 406                 break;
 407         }
 408 #endif  /* FMA_SUPPORT */
 409 
 410         /*
 411          * Setup and issue mailbox READ REV command
 412          */
 413         vpd->opFwRev = 0;
 414         vpd->postKernRev = 0;
 415         vpd->sli1FwRev = 0;
 416         vpd->sli2FwRev = 0;
 417         vpd->sli3FwRev = 0;
 418         vpd->sli4FwRev = 0;
 419 
 420         vpd->postKernName[0] = 0;
 421         vpd->opFwName[0] = 0;
 422         vpd->sli1FwName[0] = 0;
 423         vpd->sli2FwName[0] = 0;
 424         vpd->sli3FwName[0] = 0;
 425         vpd->sli4FwName[0] = 0;
 426 
 427         vpd->opFwLabel[0] = 0;
 428         vpd->sli1FwLabel[0] = 0;
 429         vpd->sli2FwLabel[0] = 0;
 430         vpd->sli3FwLabel[0] = 0;
 431         vpd->sli4FwLabel[0] = 0;
 432 
 433         EMLXS_STATE_CHANGE(hba, FC_INIT_REV);
 434 
 435         emlxs_mb_get_sli4_params(hba, mbq);
 436         if (emlxs_sli4_issue_mbox_cmd(hba, mbq, MBX_WAIT, 0) != MBX_SUCCESS) {
 437                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
 438                     "Unable to read parameters. Mailbox cmd=%x status=%x",
 439                     mb->mbxCommand, mb->mbxStatus);
 440 
 441                 /* Set param defaults */
 442                 emlxs_sli4_set_default_params(hba);
 443 
 444         } else {
 445                 /* Save parameters */
 446                 bcopy((char *)&mb->un.varSLIConfig.payload,
 447                     (char *)&hba->sli.sli4.param, sizeof (sli_params_t));
 448 
 449                 emlxs_data_dump(port, "SLI_PARMS",
 450                     (uint32_t *)&hba->sli.sli4.param,
 451                     sizeof (sli_params_t), 0);
 452         }
 453 
 454         /* Reuse mbq from previous mbox */
 455         bzero(mbq, sizeof (MAILBOXQ));
 456 
 457         emlxs_mb_get_port_name(hba, mbq);
 458         if (emlxs_sli4_issue_mbox_cmd(hba, mbq, MBX_WAIT, 0) != MBX_SUCCESS) {
 459                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
 460                     "Unable to get port names. Mailbox cmd=%x status=%x",
 461                     mb->mbxCommand, mb->mbxStatus);
 462 
 463                 bzero(hba->sli.sli4.port_name,
 464                     sizeof (hba->sli.sli4.port_name));
 465         } else {
 466                 /* Save port names */
 467                 bcopy((char *)&mb->un.varSLIConfig.payload,
 468                     (char *)&hba->sli.sli4.port_name,
 469                     sizeof (hba->sli.sli4.port_name));
 470         }
 471 
 472         /* Reuse mbq from previous mbox */
 473         bzero(mbq, sizeof (MAILBOXQ));
 474 
 475         emlxs_mb_read_rev(hba, mbq, 0);
 476         if (emlxs_sli4_issue_mbox_cmd(hba, mbq, MBX_WAIT, 0) != MBX_SUCCESS) {
 477                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg,
 478                     "Unable to read rev. Mailbox cmd=%x status=%x",
 479                     mb->mbxCommand, mb->mbxStatus);
 480 
 481                 rval = EIO;
 482                 goto failed1;
 483 
 484         }
 485 
 486         emlxs_data_dump(port, "RD_REV", (uint32_t *)mb, 18, 0);
 487         if (mb->un.varRdRev4.sliLevel != 4) {
 488                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg,
 489                     "Invalid read rev Version for SLI4: 0x%x",
 490                     mb->un.varRdRev4.sliLevel);
 491 
 492                 rval = EIO;
 493                 goto failed1;
 494         }
 495 
 496         switch (mb->un.varRdRev4.dcbxMode) {
 497         case EMLXS_DCBX_MODE_CIN:       /* Mapped to nonFIP mode */
 498                 hba->flag &= ~FC_FIP_SUPPORTED;
 499                 break;
 500 
 501         case EMLXS_DCBX_MODE_CEE:       /* Mapped to FIP mode */
 502                 hba->flag |= FC_FIP_SUPPORTED;
 503                 break;
 504 
 505         default:
 506                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg,
 507                     "Invalid read rev dcbx mode for SLI4: 0x%x",
 508                     mb->un.varRdRev4.dcbxMode);
 509 
 510                 rval = EIO;
 511                 goto failed1;
 512         }
 513 
 514         /* Set FC/FCoE mode */
 515         if (mb->un.varRdRev4.FCoE) {
 516                 hba->sli.sli4.flag |= EMLXS_SLI4_FCOE_MODE;
 517         } else {
 518                 hba->sli.sli4.flag &= ~EMLXS_SLI4_FCOE_MODE;
 519         }
 520 
 521         /* Save information as VPD data */
 522         vpd->rBit = 1;
 523 
 524         vpd->sli4FwRev = (mb->un.varRdRev4.ULPFwId);
 525         bcopy((char *)mb->un.varRdRev4.ULPFwName, vpd->sli4FwName, 16);
 526 
 527         vpd->opFwRev = (mb->un.varRdRev4.ULPFwId);
 528         bcopy((char *)mb->un.varRdRev4.ULPFwName, vpd->opFwName, 16);
 529 
 530         vpd->postKernRev = (mb->un.varRdRev4.ARMFwId);
 531         bcopy((char *)mb->un.varRdRev4.ARMFwName, vpd->postKernName, 16);
 532 
 533         vpd->biuRev = mb->un.varRdRev4.HwRev1;
 534         vpd->fcphHigh = mb->un.varRdRev4.fcphHigh;
 535         vpd->fcphLow = mb->un.varRdRev4.fcphLow;
 536         vpd->feaLevelHigh = mb->un.varRdRev4.feaLevelHigh;
 537         vpd->feaLevelLow = mb->un.varRdRev4.feaLevelLow;
 538 
 539         /* Decode FW labels */
 540         if (hba->model_info.chip == EMLXS_LANCER_CHIP) {
 541                 bcopy(vpd->postKernName, vpd->sli4FwName, 16);
 542         }
 543         emlxs_decode_label(vpd->sli4FwName, vpd->sli4FwName, 0,
 544             sizeof (vpd->sli4FwName));
 545         emlxs_decode_label(vpd->opFwName, vpd->opFwName, 0,
 546             sizeof (vpd->opFwName));
 547         emlxs_decode_label(vpd->postKernName, vpd->postKernName, 0,
 548             sizeof (vpd->postKernName));
 549 
 550         if (hba->model_info.chip == EMLXS_BE2_CHIP) {
 551                 (void) strlcpy(vpd->sli4FwLabel, "be2.ufi",
 552                     sizeof (vpd->sli4FwLabel));
 553         } else if (hba->model_info.chip == EMLXS_BE3_CHIP) {
 554                 (void) strlcpy(vpd->sli4FwLabel, "be3.ufi",
 555                     sizeof (vpd->sli4FwLabel));
 556         } else if (hba->model_info.chip == EMLXS_LANCER_CHIP) {
 557                 (void) strlcpy(vpd->sli4FwLabel, "xe201.grp",
 558                     sizeof (vpd->sli4FwLabel));
 559         } else {
 560                 (void) strlcpy(vpd->sli4FwLabel, "sli4.fw",
 561                     sizeof (vpd->sli4FwLabel));
 562         }
 563 
 564         EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
 565             "VPD ULP:%08x %s ARM:%08x %s f:%d %d %d %d : dcbx %d",
 566             vpd->opFwRev, vpd->opFwName, vpd->postKernRev, vpd->postKernName,
 567             vpd->fcphHigh, vpd->fcphLow, vpd->feaLevelHigh, vpd->feaLevelLow,
 568             mb->un.varRdRev4.dcbxMode);
 569 
 570         /* No key information is needed for SLI4 products */
 571 
 572         /* Get adapter VPD information */
 573         vpd->port_index = (uint32_t)-1;
 574 
 575         /* Reuse mbq from previous mbox */
 576         bzero(mbq, sizeof (MAILBOXQ));
 577 
 578         emlxs_mb_dump_vpd(hba, mbq, 0);
 579         vpd_data = hba->sli.sli4.dump_region.virt;
 580 
 581         if (emlxs_sli4_issue_mbox_cmd(hba, mbq, MBX_WAIT, 0) !=
 582             MBX_SUCCESS) {
 583                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
 584                     "No VPD found. status=%x", mb->mbxStatus);
 585         } else {
 586                 EMLXS_MSGF(EMLXS_CONTEXT,
 587                     &emlxs_init_debug_msg,
 588                     "VPD dumped. rsp_cnt=%d status=%x",
 589                     mb->un.varDmp4.rsp_cnt, mb->mbxStatus);
 590 
 591                 if (mb->un.varDmp4.rsp_cnt) {
 592                         EMLXS_MPDATA_SYNC(hba->sli.sli4.dump_region.dma_handle,
 593                             0, mb->un.varDmp4.rsp_cnt, DDI_DMA_SYNC_FORKERNEL);
 594 
 595 #ifdef FMA_SUPPORT
 596                         if (hba->sli.sli4.dump_region.dma_handle) {
 597                                 if (emlxs_fm_check_dma_handle(hba,
 598                                     hba->sli.sli4.dump_region.dma_handle)
 599                                     != DDI_FM_OK) {
 600                                         EMLXS_MSGF(EMLXS_CONTEXT,
 601                                             &emlxs_invalid_dma_handle_msg,
 602                                             "sli4_online: hdl=%p",
 603                                             hba->sli.sli4.dump_region.
 604                                             dma_handle);
 605                                         rval = EIO;
 606                                         goto failed1;
 607                                 }
 608                         }
 609 #endif /* FMA_SUPPORT */
 610 
 611                 }
 612         }
 613 
 614         if (vpd_data[0]) {
 615                 (void) emlxs_parse_vpd(hba, (uint8_t *)vpd_data,
 616                     mb->un.varDmp4.rsp_cnt);
 617 
 618                 /*
 619                  * If there is a VPD part number, and it does not
 620                  * match the current default HBA model info,
 621                  * replace the default data with an entry that
 622                  * does match.
 623                  *
 624                  * After emlxs_parse_vpd model holds the VPD value
 625                  * for V2 and part_num hold the value for PN. These
 626                  * 2 values are NOT necessarily the same.
 627                  */
 628 
 629                 rval = 0;
 630                 if ((vpd->model[0] != 0) &&
 631                     (strcmp(&vpd->model[0], hba->model_info.model) != 0)) {
 632 
 633                         /* First scan for a V2 match */
 634 
 635                         for (i = 1; i < emlxs_pci_model_count; i++) {
 636                                 if (strcmp(&vpd->model[0],
 637                                     emlxs_pci_model[i].model) == 0) {
 638                                         bcopy(&emlxs_pci_model[i],
 639                                             &hba->model_info,
 640                                             sizeof (emlxs_model_t));
 641                                         rval = 1;
 642                                         break;
 643                                 }
 644                         }
 645                 }
 646 
 647                 if (!rval && (vpd->part_num[0] != 0) &&
 648                     (strcmp(&vpd->part_num[0], hba->model_info.model) != 0)) {
 649 
 650                         /* Next scan for a PN match */
 651 
 652                         for (i = 1; i < emlxs_pci_model_count; i++) {
 653                                 if (strcmp(&vpd->part_num[0],
 654                                     emlxs_pci_model[i].model) == 0) {
 655                                         bcopy(&emlxs_pci_model[i],
 656                                             &hba->model_info,
 657                                             sizeof (emlxs_model_t));
 658                                         break;
 659                                 }
 660                         }
 661                 }
 662 
 663                 /* HP CNA port indices start at 1 instead of 0 */
 664                 if (hba->model_info.chip & EMLXS_BE_CHIPS) {
 665                         ssvid = ddi_get16(hba->pci_acc_handle,
 666                             (uint16_t *)(hba->pci_addr + PCI_SSVID_REGISTER));
 667 
 668                         if ((ssvid == PCI_SSVID_HP) && (vpd->port_index > 0)) {
 669                                 vpd->port_index--;
 670                         }
 671                 }
 672 
 673                 /*
 674                  * Now lets update hba->model_info with the real
 675                  * VPD data, if any.
 676                  */
 677 
 678                 /*
 679                  * Replace the default model description with vpd data
 680                  */
 681                 if (vpd->model_desc[0] != 0) {
 682                         (void) strncpy(hba->model_info.model_desc,
 683                             vpd->model_desc,
 684                             (sizeof (hba->model_info.model_desc)-1));
 685                 }
 686 
 687                 /* Replace the default model with vpd data */
 688                 if (vpd->model[0] != 0) {
 689                         (void) strncpy(hba->model_info.model, vpd->model,
 690                             (sizeof (hba->model_info.model)-1));
 691                 }
 692 
 693                 /* Replace the default program types with vpd data */
 694                 if (vpd->prog_types[0] != 0) {
 695                         emlxs_parse_prog_types(hba, vpd->prog_types);
 696                 }
 697         }
 698 
 699         /*
 700          * Since the adapter model may have changed with the vpd data
 701          * lets double check if adapter is not supported
 702          */
 703         if (hba->model_info.flags & EMLXS_NOT_SUPPORTED) {
 704                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg,
 705                     "Unsupported adapter found.  "
 706                     "Id:%d  Device id:0x%x  SSDID:0x%x  Model:%s",
 707                     hba->model_info.id, hba->model_info.device_id,
 708                     hba->model_info.ssdid, hba->model_info.model);
 709 
 710                 rval = EIO;
 711                 goto failed1;
 712         }
 713 
 714         (void) strncpy(vpd->boot_version, vpd->sli4FwName,
 715             (sizeof (vpd->boot_version)-1));
 716 
 717         /* Get fcode version property */
 718         emlxs_get_fcode_version(hba);
 719 
 720         EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
 721             "Firmware: kern=%08x stub=%08x sli1=%08x", vpd->postKernRev,
 722             vpd->opFwRev, vpd->sli1FwRev);
 723 
 724         EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
 725             "Firmware: sli2=%08x sli3=%08x sli4=%08x fl=%x", vpd->sli2FwRev,
 726             vpd->sli3FwRev, vpd->sli4FwRev, vpd->feaLevelHigh);
 727 
 728         EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
 729             "BIOS: boot=%s fcode=%s", vpd->boot_version, vpd->fcode_version);
 730 
 731         /*
 732          * If firmware checking is enabled and the adapter model indicates
 733          * a firmware image, then perform firmware version check
 734          */
 735         hba->fw_flag = 0;
 736         hba->fw_timer = 0;
 737 
 738         if (((fw_check & 0x1) &&
 739             (hba->model_info.flags & EMLXS_ORACLE_BRANDED) &&
 740             hba->model_info.fwid) ||
 741             ((fw_check & 0x2) && hba->model_info.fwid)) {
 742 
 743                 /* Find firmware image indicated by adapter model */
 744                 fw = NULL;
 745                 for (i = 0; i < emlxs_fw_count; i++) {
 746                         if (emlxs_fw_table[i].id == hba->model_info.fwid) {
 747                                 fw = &emlxs_fw_table[i];
 748                                 break;
 749                         }
 750                 }
 751 
 752                 /*
 753                  * If the image was found, then verify current firmware
 754                  * versions of adapter
 755                  */
 756                 if (fw) {
 757                         /* Obtain current firmware version info */
 758                         if (hba->model_info.chip & EMLXS_BE_CHIPS) {
 759                                 (void) emlxs_be_read_fw_version(hba, &hba_fw);
 760                         } else {
 761                                 hba_fw.kern = vpd->postKernRev;
 762                                 hba_fw.stub = vpd->opFwRev;
 763                                 hba_fw.sli1 = vpd->sli1FwRev;
 764                                 hba_fw.sli2 = vpd->sli2FwRev;
 765                                 hba_fw.sli3 = vpd->sli3FwRev;
 766                                 hba_fw.sli4 = vpd->sli4FwRev;
 767                         }
 768 
 769                         if (!kern_update &&
 770                             ((fw->kern && (hba_fw.kern != fw->kern)) ||
 771                             (fw->stub && (hba_fw.stub != fw->stub)))) {
 772 
 773                                 hba->fw_flag |= FW_UPDATE_NEEDED;
 774 
 775                         } else if ((fw->kern && (hba_fw.kern != fw->kern)) ||
 776                             (fw->stub && (hba_fw.stub != fw->stub)) ||
 777                             (fw->sli1 && (hba_fw.sli1 != fw->sli1)) ||
 778                             (fw->sli2 && (hba_fw.sli2 != fw->sli2)) ||
 779                             (fw->sli3 && (hba_fw.sli3 != fw->sli3)) ||
 780                             (fw->sli4 && (hba_fw.sli4 != fw->sli4))) {
 781 
 782                                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_msg,
 783                                     "Firmware update needed. "
 784                                     "Updating. id=%d fw=%d",
 785                                     hba->model_info.id, hba->model_info.fwid);
 786 
 787 #ifdef MODFW_SUPPORT
 788                                 /*
 789                                  * Load the firmware image now
 790                                  * If MODFW_SUPPORT is not defined, the
 791                                  * firmware image will already be defined
 792                                  * in the emlxs_fw_table
 793                                  */
 794                                 emlxs_fw_load(hba, fw);
 795 #endif /* MODFW_SUPPORT */
 796 
 797                                 if (fw->image && fw->size) {
 798                                         uint32_t rc;
 799 
 800                                         rc = emlxs_fw_download(hba,
 801                                             (char *)fw->image, fw->size, 0);
 802                                         if ((rc != FC_SUCCESS) &&
 803                                             (rc != EMLXS_REBOOT_REQUIRED)) {
 804                                                 EMLXS_MSGF(EMLXS_CONTEXT,
 805                                                     &emlxs_init_msg,
 806                                                     "Firmware update failed.");
 807                                                 hba->fw_flag |=
 808                                                     FW_UPDATE_NEEDED;
 809                                         }
 810 #ifdef MODFW_SUPPORT
 811                                         /*
 812                                          * Unload the firmware image from
 813                                          * kernel memory
 814                                          */
 815                                         emlxs_fw_unload(hba, fw);
 816 #endif /* MODFW_SUPPORT */
 817 
 818                                         fw_check = 0;
 819 
 820                                         goto reset;
 821                                 }
 822 
 823                                 hba->fw_flag |= FW_UPDATE_NEEDED;
 824 
 825                                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_msg,
 826                                     "Firmware image unavailable.");
 827                         } else {
 828                                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_msg,
 829                                     "Firmware update not needed.");
 830                         }
 831                 } else {
 832                         /*
 833                          * This means either the adapter database is not
 834                          * correct or a firmware image is missing from the
 835                          * compile
 836                          */
 837                         EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_msg,
 838                             "Firmware image unavailable. id=%d fw=%d",
 839                             hba->model_info.id, hba->model_info.fwid);
 840                 }
 841         }
 842 
 843         /* Reuse mbq from previous mbox */
 844         bzero(mbq, sizeof (MAILBOXQ));
 845 
 846         emlxs_mb_dump_fcoe(hba, mbq, 0);
 847 
 848         if (emlxs_sli4_issue_mbox_cmd(hba, mbq, MBX_WAIT, 0) !=
 849             MBX_SUCCESS) {
 850                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
 851                     "No FCOE info found. status=%x", mb->mbxStatus);
 852         } else {
 853                 EMLXS_MSGF(EMLXS_CONTEXT,
 854                     &emlxs_init_debug_msg,
 855                     "FCOE info dumped. rsp_cnt=%d status=%x",
 856                     mb->un.varDmp4.rsp_cnt, mb->mbxStatus);
 857                 (void) emlxs_parse_fcoe(hba,
 858                     (uint8_t *)hba->sli.sli4.dump_region.virt,
 859                     mb->un.varDmp4.rsp_cnt);
 860         }
 861 
 862         /* Reuse mbq from previous mbox */
 863         bzero(mbq, sizeof (MAILBOXQ));
 864 
 865         status = 0;
 866         if (port->flag & EMLXS_INI_ENABLED) {
 867                 status |= SLI4_FEATURE_FCP_INITIATOR;
 868         }
 869         if (port->flag & EMLXS_TGT_ENABLED) {
 870                 status |= SLI4_FEATURE_FCP_TARGET;
 871         }
 872         if (cfg[CFG_NPIV_ENABLE].current) {
 873                 status |= SLI4_FEATURE_NPIV;
 874         }
 875         if (cfg[CFG_RQD_MODE].current) {
 876                 status |= SLI4_FEATURE_RQD;
 877         }
 878         if (cfg[CFG_PERF_HINT].current) {
 879                 if (hba->sli.sli4.param.PHON) {
 880                         status |= SLI4_FEATURE_PERF_HINT;
 881                 }
 882         }
 883 
 884         emlxs_mb_request_features(hba, mbq, status);
 885 
 886         if (emlxs_sli4_issue_mbox_cmd(hba, mbq, MBX_WAIT, 0) != MBX_SUCCESS) {
 887                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg,
 888                     "Unable to REQUEST_FEATURES. Mailbox cmd=%x status=%x",
 889                     mb->mbxCommand, mb->mbxStatus);
 890 
 891                 rval = EIO;
 892                 goto failed1;
 893         }
 894         emlxs_data_dump(port, "REQ_FEATURE", (uint32_t *)mb, 6, 0);
 895 
 896         /* Check to see if we get the features we requested */
 897         if (status != mb->un.varReqFeatures.featuresEnabled) {
 898 
 899                 /* Just report descrepencies, don't abort the attach */
 900 
 901                 outptr = (uint8_t *)emlxs_request_feature_xlate(
 902                     mb->un.varReqFeatures.featuresRequested);
 903                 (void) strlcpy(buf, (char *)outptr, sizeof (buf));
 904 
 905                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
 906                     "REQUEST_FEATURES: wanted:%s  got:%s",
 907                     &buf[0], emlxs_request_feature_xlate(
 908                     mb->un.varReqFeatures.featuresEnabled));
 909 
 910         }
 911 
 912         if ((port->flag & EMLXS_INI_ENABLED) &&
 913             !(mb->un.varReqFeatures.featuresEnabled &
 914             SLI4_FEATURE_FCP_INITIATOR)) {
 915                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg,
 916                     "Initiator mode not supported by adapter.");
 917 
 918                 rval = EIO;
 919 
 920 #ifdef SFCT_SUPPORT
 921                 /* Check if we can fall back to just target mode */
 922                 if ((hba->pm_state == EMLXS_PM_IN_ATTACH) &&
 923                     (mb->un.varReqFeatures.featuresEnabled &
 924                     SLI4_FEATURE_FCP_TARGET) &&
 925                     (cfg[CFG_DTM_ENABLE].current == 1) &&
 926                     (cfg[CFG_TARGET_MODE].current == 1)) {
 927 
 928                         cfg[CFG_DTM_ENABLE].current = 0;
 929 
 930                         EMLXS_MSGF(EMLXS_CONTEXT,
 931                             &emlxs_init_failed_msg,
 932                             "Disabling dynamic target mode. "
 933                             "Enabling target mode only.");
 934 
 935                         /* This will trigger the driver to reattach */
 936                         rval = EAGAIN;
 937                 }
 938 #endif /* SFCT_SUPPORT */
 939                 goto failed1;
 940         }
 941 
 942         if ((port->flag & EMLXS_TGT_ENABLED) &&
 943             !(mb->un.varReqFeatures.featuresEnabled &
 944             SLI4_FEATURE_FCP_TARGET)) {
 945                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg,
 946                     "Target mode not supported by adapter.");
 947 
 948                 rval = EIO;
 949 
 950 #ifdef SFCT_SUPPORT
 951                 /* Check if we can fall back to just initiator mode */
 952                 if ((hba->pm_state == EMLXS_PM_IN_ATTACH) &&
 953                     (mb->un.varReqFeatures.featuresEnabled &
 954                     SLI4_FEATURE_FCP_INITIATOR) &&
 955                     (cfg[CFG_DTM_ENABLE].current == 1) &&
 956                     (cfg[CFG_TARGET_MODE].current == 0)) {
 957 
 958                         cfg[CFG_DTM_ENABLE].current = 0;
 959 
 960                         EMLXS_MSGF(EMLXS_CONTEXT,
 961                             &emlxs_init_failed_msg,
 962                             "Disabling dynamic target mode. "
 963                             "Enabling initiator mode only.");
 964 
 965                         /* This will trigger the driver to reattach */
 966                         rval = EAGAIN;
 967                 }
 968 #endif /* SFCT_SUPPORT */
 969                 goto failed1;
 970         }
 971 
 972         if (mb->un.varReqFeatures.featuresEnabled & SLI4_FEATURE_NPIV) {
 973                 hba->flag |= FC_NPIV_ENABLED;
 974         }
 975 
 976         if (mb->un.varReqFeatures.featuresEnabled & SLI4_FEATURE_PERF_HINT) {
 977                 hba->sli.sli4.flag |= EMLXS_SLI4_PHON;
 978                 if (hba->sli.sli4.param.PHWQ) {
 979                         hba->sli.sli4.flag |= EMLXS_SLI4_PHWQ;
 980                 }
 981         }
 982 
 983         /* Reuse mbq from previous mbox */
 984         bzero(mbq, sizeof (MAILBOXQ));
 985 
 986         emlxs_mb_read_config(hba, mbq);
 987         if (emlxs_sli4_issue_mbox_cmd(hba, mbq, MBX_WAIT, 0) != MBX_SUCCESS) {
 988                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg,
 989                     "Unable to READ_CONFIG. Mailbox cmd=%x status=%x",
 990                     mb->mbxCommand, mb->mbxStatus);
 991 
 992                 rval = EIO;
 993                 goto failed1;
 994         }
 995         emlxs_data_dump(port, "READ_CONFIG4", (uint32_t *)mb, 18, 0);
 996 
 997         /* Set default extents */
 998         hba->sli.sli4.XRICount = mb->un.varRdConfig4.XRICount;
 999         hba->sli.sli4.XRIExtCount = 1;
1000         hba->sli.sli4.XRIExtSize = hba->sli.sli4.XRICount;
1001         hba->sli.sli4.XRIBase[0] = mb->un.varRdConfig4.XRIBase;
1002 
1003         hba->sli.sli4.RPICount = mb->un.varRdConfig4.RPICount;
1004         hba->sli.sli4.RPIExtCount = 1;
1005         hba->sli.sli4.RPIExtSize = hba->sli.sli4.RPICount;
1006         hba->sli.sli4.RPIBase[0] = mb->un.varRdConfig4.RPIBase;
1007 
1008         hba->sli.sli4.VPICount = mb->un.varRdConfig4.VPICount;
1009         hba->sli.sli4.VPIExtCount = 1;
1010         hba->sli.sli4.VPIExtSize = hba->sli.sli4.VPICount;
1011         hba->sli.sli4.VPIBase[0] = mb->un.varRdConfig4.VPIBase;
1012 
1013         hba->sli.sli4.VFICount = mb->un.varRdConfig4.VFICount;
1014         hba->sli.sli4.VFIExtCount = 1;
1015         hba->sli.sli4.VFIExtSize = hba->sli.sli4.VFICount;
1016         hba->sli.sli4.VFIBase[0] = mb->un.varRdConfig4.VFIBase;
1017 
1018         hba->sli.sli4.FCFICount = mb->un.varRdConfig4.FCFICount;
1019 
1020         EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
1021             "CONFIG: xri:%d rpi:%d vpi:%d vfi:%d fcfi:%d",
1022             hba->sli.sli4.XRICount,
1023             hba->sli.sli4.RPICount,
1024             hba->sli.sli4.VPICount,
1025             hba->sli.sli4.VFICount,
1026             hba->sli.sli4.FCFICount);
1027 
1028         if ((hba->sli.sli4.XRICount == 0) ||
1029             (hba->sli.sli4.RPICount == 0) ||
1030             (hba->sli.sli4.VPICount == 0) ||
1031             (hba->sli.sli4.VFICount == 0) ||
1032             (hba->sli.sli4.FCFICount == 0)) {
1033                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg,
1034                     "Invalid extent value(s) - xri:%d rpi:%d vpi:%d "
1035                     "vfi:%d fcfi:%d",
1036                     hba->sli.sli4.XRICount,
1037                     hba->sli.sli4.RPICount,
1038                     hba->sli.sli4.VPICount,
1039                     hba->sli.sli4.VFICount,
1040                     hba->sli.sli4.FCFICount);
1041 
1042                 rval = EIO;
1043                 goto failed1;
1044         }
1045 
1046         if (mb->un.varRdConfig4.extents) {
1047                 if (emlxs_sli4_init_extents(hba, mbq)) {
1048                         EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg,
1049                             "Unable to initialize extents.");
1050 
1051                         rval = EIO;
1052                         goto failed1;
1053                 }
1054         }
1055 
1056         EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
1057             "CONFIG: port_name:%c %c %c %c",
1058             hba->sli.sli4.port_name[0],
1059             hba->sli.sli4.port_name[1],
1060             hba->sli.sli4.port_name[2],
1061             hba->sli.sli4.port_name[3]);
1062 
1063         EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
1064             "CONFIG: ldv:%d link_type:%d link_number:%d",
1065             mb->un.varRdConfig4.ldv,
1066             mb->un.varRdConfig4.link_type,
1067             mb->un.varRdConfig4.link_number);
1068 
1069         if (mb->un.varRdConfig4.ldv) {
1070                 hba->sli.sli4.link_number = mb->un.varRdConfig4.link_number;
1071         } else {
1072                 hba->sli.sli4.link_number = (uint32_t)-1;
1073         }
1074 
1075         if (hba->sli.sli4.VPICount) {
1076                 hba->vpi_max = min(hba->sli.sli4.VPICount, MAX_VPORTS) - 1;
1077         }
1078 
1079         /* Set the max node count */
1080         if (cfg[CFG_NUM_NODES].current > 0) {
1081                 hba->max_nodes =
1082                     min(cfg[CFG_NUM_NODES].current,
1083                     hba->sli.sli4.RPICount);
1084         } else {
1085                 hba->max_nodes = hba->sli.sli4.RPICount;
1086         }
1087 
1088         /* Set the io throttle */
1089         hba->io_throttle = hba->sli.sli4.XRICount - IO_THROTTLE_RESERVE;
1090 
1091         /* Set max_iotag */
1092         /* We add 1 in case all XRI's are non-zero */
1093         hba->max_iotag = hba->sli.sli4.XRICount + 1;
1094 
1095         if (cfg[CFG_NUM_IOTAGS].current) {
1096                 hba->max_iotag = min(hba->max_iotag,
1097                     (uint16_t)cfg[CFG_NUM_IOTAGS].current);
1098         }
1099 
1100         /* Set out-of-range iotag base */
1101         hba->fc_oor_iotag = hba->max_iotag;
1102 
1103         /* Save the link speed capabilities */
1104         vpd->link_speed = (uint16_t)mb->un.varRdConfig4.lmt;
1105         emlxs_process_link_speed(hba);
1106 
1107         /*
1108          * Allocate some memory for buffers
1109          */
1110         if (emlxs_mem_alloc_buffer(hba) == 0) {
1111                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg,
1112                     "Unable to allocate memory buffers.");
1113 
1114                 rval = ENOMEM;
1115                 goto failed1;
1116         }
1117 
1118         if (emlxs_sli4_resource_alloc(hba)) {
1119                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg,
1120                     "Unable to allocate resources.");
1121 
1122                 rval = ENOMEM;
1123                 goto failed2;
1124         }
1125         emlxs_data_dump(port, "XRIp", (uint32_t *)hba->sli.sli4.XRIp, 18, 0);
1126         emlxs_sli4_zero_queue_stat(hba);
1127 
1128 #if (EMLXS_MODREV >= EMLXS_MODREV5)
1129         if ((cfg[CFG_NPIV_ENABLE].current) && (hba->flag & FC_NPIV_ENABLED)) {
1130                 hba->fca_tran->fca_num_npivports = hba->vpi_max;
1131         }
1132 #endif /* >= EMLXS_MODREV5 */
1133 
1134         /* Reuse mbq from previous mbox */
1135         bzero(mbq, sizeof (MAILBOXQ));
1136 
1137         if (emlxs_sli4_post_sgl_pages(hba, mbq)) {
1138                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg,
1139                     "Unable to post sgl pages.");
1140 
1141                 rval = EIO;
1142                 goto failed3;
1143         }
1144 
1145         /* Reuse mbq from previous mbox */
1146         bzero(mbq, sizeof (MAILBOXQ));
1147 
1148         if (emlxs_sli4_post_hdr_tmplates(hba, mbq)) {
1149                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg,
1150                     "Unable to post header templates.");
1151 
1152                 rval = EIO;
1153                 goto failed3;
1154         }
1155 
1156         /*
1157          * Add our interrupt routine to kernel's interrupt chain & enable it
1158          * If MSI is enabled this will cause Solaris to program the MSI address
1159          * and data registers in PCI config space
1160          */
1161         if (EMLXS_INTR_ADD(hba) != DDI_SUCCESS) {
1162                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg,
1163                     "Unable to add interrupt(s).");
1164 
1165                 rval = EIO;
1166                 goto failed3;
1167         }
1168 
1169         /* Reuse mbq from previous mbox */
1170         bzero(mbq, sizeof (MAILBOXQ));
1171 
1172         /* This MUST be done after EMLXS_INTR_ADD */
1173         if (emlxs_sli4_create_queues(hba, mbq)) {
1174                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg,
1175                     "Unable to create queues.");
1176 
1177                 rval = EIO;
1178                 goto failed3;
1179         }
1180 
1181         EMLXS_STATE_CHANGE(hba, FC_INIT_CFGPORT);
1182 
1183         /* Get and save the current firmware version (based on sli_mode) */
1184         emlxs_decode_firmware_rev(hba, vpd);
1185 
1186 
1187         EMLXS_STATE_CHANGE(hba, FC_INIT_INITLINK);
1188 
1189         if (SLI4_FC_MODE) {
1190                 /* Reuse mbq from previous mbox */
1191                 bzero(mbq, sizeof (MAILBOXQ));
1192 
1193                 emlxs_mb_config_link(hba, mbq);
1194                 if (emlxs_sli4_issue_mbox_cmd(hba, mbq, MBX_WAIT, 0) !=
1195                     MBX_SUCCESS) {
1196                         EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg,
1197                             "Unable to configure link. Mailbox cmd=%x "
1198                             "status=%x",
1199                             mb->mbxCommand, mb->mbxStatus);
1200 
1201                         rval = EIO;
1202                         goto failed3;
1203                 }
1204         }
1205 
1206         /* Reuse mbq from previous mbox */
1207         bzero(mbq, sizeof (MAILBOXQ));
1208 
1209         /*
1210          * We need to get login parameters for NID
1211          */
1212         (void) emlxs_mb_read_sparam(hba, mbq);
1213         mp = (MATCHMAP *)mbq->bp;
1214         if (emlxs_sli4_issue_mbox_cmd(hba, mbq, MBX_WAIT, 0) != MBX_SUCCESS) {
1215                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg,
1216                     "Unable to read parameters. Mailbox cmd=%x status=%x",
1217                     mb->mbxCommand, mb->mbxStatus);
1218 
1219                 rval = EIO;
1220                 goto failed3;
1221         }
1222 
1223         /* Free the buffer since we were polling */
1224         emlxs_mem_put(hba, MEM_BUF, (void *)mp);
1225         mp = NULL;
1226 
1227         /* If no serial number in VPD data, then use the WWPN */
1228         if (vpd->serial_num[0] == 0) {
1229                 outptr = (uint8_t *)&hba->wwpn.IEEE[0];
1230                 for (i = 0; i < 12; i++) {
1231                         status = *outptr++;
1232                         j = ((status & 0xf0) >> 4);
1233                         if (j <= 9) {
1234                                 vpd->serial_num[i] =
1235                                     (char)((uint8_t)'0' + (uint8_t)j);
1236                         } else {
1237                                 vpd->serial_num[i] =
1238                                     (char)((uint8_t)'A' + (uint8_t)(j - 10));
1239                         }
1240 
1241                         i++;
1242                         j = (status & 0xf);
1243                         if (j <= 9) {
1244                                 vpd->serial_num[i] =
1245                                     (char)((uint8_t)'0' + (uint8_t)j);
1246                         } else {
1247                                 vpd->serial_num[i] =
1248                                     (char)((uint8_t)'A' + (uint8_t)(j - 10));
1249                         }
1250                 }
1251 
1252                 /*
1253                  * Set port number and port index to zero
1254                  * The WWN's are unique to each port and therefore port_num
1255                  * must equal zero. This effects the hba_fru_details structure
1256                  * in fca_bind_port()
1257                  */
1258                 vpd->port_num[0] = 0;
1259                 vpd->port_index = 0;
1260 
1261                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
1262                     "CONFIG: WWPN: port_index=0");
1263         }
1264 
1265         /* Make final attempt to set a port index */
1266         if (vpd->port_index == (uint32_t)-1) {
1267                 dev_info_t *p_dip;
1268                 dev_info_t *c_dip;
1269 
1270                 p_dip = ddi_get_parent(hba->dip);
1271                 c_dip = ddi_get_child(p_dip);
1272 
1273                 vpd->port_index = 0;
1274                 while (c_dip && (hba->dip != c_dip)) {
1275                         c_dip = ddi_get_next_sibling(c_dip);
1276 
1277                         if (strcmp(ddi_get_name(c_dip), "ethernet") == 0) {
1278                                 continue;
1279                         }
1280 
1281                         vpd->port_index++;
1282                 }
1283 
1284                 EMLXS_MSGF(EMLXS_CONTEXT,
1285                     &emlxs_init_debug_msg,
1286                     "CONFIG: Device tree: port_index=%d",
1287                     vpd->port_index);
1288         }
1289 
1290         if (vpd->port_num[0] == 0) {
1291                 if (hba->model_info.channels == EMLXS_MULTI_CHANNEL) {
1292                         (void) snprintf(vpd->port_num,
1293                             (sizeof (vpd->port_num)-1),
1294                             "%d", vpd->port_index);
1295                 }
1296         }
1297 
1298         if (vpd->id[0] == 0) {
1299                 (void) snprintf(vpd->id, (sizeof (vpd->id)-1),
1300                     "%s %d",
1301                     hba->model_info.model_desc, vpd->port_index);
1302 
1303         }
1304 
1305         if (vpd->manufacturer[0] == 0) {
1306                 (void) strncpy(vpd->manufacturer, hba->model_info.manufacturer,
1307                     (sizeof (vpd->manufacturer)-1));
1308         }
1309 
1310         if (vpd->part_num[0] == 0) {
1311                 (void) strncpy(vpd->part_num, hba->model_info.model,
1312                     (sizeof (vpd->part_num)-1));
1313         }
1314 
1315         if (vpd->model_desc[0] == 0) {
1316                 (void) snprintf(vpd->model_desc, (sizeof (vpd->model_desc)-1),
1317                     "%s %d",
1318                     hba->model_info.model_desc, vpd->port_index);
1319         }
1320 
1321         if (vpd->model[0] == 0) {
1322                 (void) strncpy(vpd->model, hba->model_info.model,
1323                     (sizeof (vpd->model)-1));
1324         }
1325 
1326         if (vpd->prog_types[0] == 0) {
1327                 emlxs_build_prog_types(hba, vpd);
1328         }
1329 
1330         /* Create the symbolic names */
1331         (void) snprintf(hba->snn, (sizeof (hba->snn)-1),
1332             "Emulex %s FV%s DV%s %s",
1333             hba->model_info.model, hba->vpd.fw_version, emlxs_version,
1334             (char *)utsname.nodename);
1335 
1336         (void) snprintf(hba->spn, (sizeof (hba->spn)-1),
1337             "Emulex PPN-%01x%01x:%02x:%02x:%02x:%02x:%02x:%02x:%02x",
1338             hba->wwpn.nameType, hba->wwpn.IEEEextMsn, hba->wwpn.IEEEextLsb,
1339             hba->wwpn.IEEE[0], hba->wwpn.IEEE[1], hba->wwpn.IEEE[2],
1340             hba->wwpn.IEEE[3], hba->wwpn.IEEE[4], hba->wwpn.IEEE[5]);
1341 
1342 
1343         EMLXS_STATE_CHANGE(hba, FC_LINK_DOWN);
1344         emlxs_sli4_enable_intr(hba);
1345 
1346         /* Check persist-linkdown */
1347         if (cfg[CFG_PERSIST_LINKDOWN].current) {
1348                 EMLXS_STATE_CHANGE(hba, FC_LINK_DOWN_PERSIST);
1349                 goto done;
1350         }
1351 
1352 #ifdef SFCT_SUPPORT
1353         if ((port->mode == MODE_TARGET) &&
1354             !(port->fct_flags & FCT_STATE_PORT_ONLINE)) {
1355                 goto done;
1356         }
1357 #endif /* SFCT_SUPPORT */
1358 
1359         /* Reuse mbq from previous mbox */
1360         bzero(mbq, sizeof (MAILBOXQ));
1361 
1362         /*
1363          * Setup and issue mailbox INITIALIZE LINK command
1364          * At this point, the interrupt will be generated by the HW
1365          */
1366         emlxs_mb_init_link(hba, mbq,
1367             cfg[CFG_TOPOLOGY].current, cfg[CFG_LINK_SPEED].current);
1368 
1369         rval = emlxs_sli4_issue_mbox_cmd(hba, mbq, MBX_NOWAIT, 0);
1370         if ((rval != MBX_SUCCESS) && (rval != MBX_BUSY)) {
1371                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg,
1372                     "Unable to initialize link. "
1373                     "Mailbox cmd=%x status=%x",
1374                     mb->mbxCommand, mb->mbxStatus);
1375 
1376                 rval = EIO;
1377                 goto failed3;
1378         }
1379 
1380         /* Wait for link to come up */
1381         i = cfg[CFG_LINKUP_DELAY].current;
1382         while (i && (hba->state < FC_LINK_UP)) {
1383                 /* Check for hardware error */
1384                 if (hba->state == FC_ERROR) {
1385                         EMLXS_MSGF(EMLXS_CONTEXT,
1386                             &emlxs_init_failed_msg,
1387                             "Adapter error.", mb->mbxCommand,
1388                             mb->mbxStatus);
1389 
1390                         rval = EIO;
1391                         goto failed3;
1392                 }
1393 
1394                 BUSYWAIT_MS(1000);
1395                 i--;
1396         }
1397 
1398 done:
1399         /*
1400          * The leadville driver will now handle the FLOGI at the driver level
1401          */
1402 
1403         if (mbq) {
1404                 (void) kmem_free((uint8_t *)mbq, sizeof (MAILBOXQ));
1405                 mbq = NULL;
1406                 mb = NULL;
1407         }
1408         return (0);
1409 
1410 failed3:
1411         EMLXS_STATE_CHANGE(hba, FC_ERROR);
1412 
1413         if (mp) {
1414                 emlxs_mem_put(hba, MEM_BUF, (void *)mp);
1415                 mp = NULL;
1416         }
1417 
1418 
1419         if (hba->intr_flags & EMLXS_MSI_ADDED) {
1420                 (void) EMLXS_INTR_REMOVE(hba);
1421         }
1422 
1423         emlxs_sli4_resource_free(hba);
1424 
1425 failed2:
1426         (void) emlxs_mem_free_buffer(hba);
1427 
1428 failed1:
1429         if (mbq) {
1430                 (void) kmem_free((uint8_t *)mbq, sizeof (MAILBOXQ));
1431                 mbq = NULL;
1432                 mb = NULL;
1433         }
1434 
1435         if (hba->sli.sli4.dump_region.virt) {
1436                 (void) emlxs_mem_free(hba, &hba->sli.sli4.dump_region);
1437         }
1438 
1439         if (rval == 0) {
1440                 rval = EIO;
1441         }
1442 
1443         return (rval);
1444 
1445 } /* emlxs_sli4_online() */
1446 
1447 
1448 static void
1449 emlxs_sli4_offline(emlxs_hba_t *hba, uint32_t reset_requested)
1450 {
1451         /* Reverse emlxs_sli4_online */
1452 
1453         mutex_enter(&EMLXS_PORT_LOCK);
1454         if (hba->flag & FC_INTERLOCKED) {
1455                 mutex_exit(&EMLXS_PORT_LOCK);
1456                 goto killed;
1457         }
1458         mutex_exit(&EMLXS_PORT_LOCK);
1459 
1460         if (reset_requested) {
1461                 (void) emlxs_sli4_hba_reset(hba, 0, 0, 0);
1462         }
1463 
1464         /* Shutdown the adapter interface */
1465         emlxs_sli4_hba_kill(hba);
1466 
1467 killed:
1468 
1469         /* Free SLI shared memory */
1470         emlxs_sli4_resource_free(hba);
1471 
1472         /* Free driver shared memory */
1473         (void) emlxs_mem_free_buffer(hba);
1474 
1475         /* Free the host dump region buffer */
1476         (void) emlxs_mem_free(hba, &hba->sli.sli4.dump_region);
1477 
1478 } /* emlxs_sli4_offline() */
1479 
1480 
1481 /*ARGSUSED*/
1482 static int
1483 emlxs_sli4_map_hdw(emlxs_hba_t *hba)
1484 {
1485         emlxs_port_t            *port = &PPORT;
1486         dev_info_t              *dip;
1487         ddi_device_acc_attr_t   dev_attr;
1488         int                     status;
1489 
1490         dip = (dev_info_t *)hba->dip;
1491         dev_attr = emlxs_dev_acc_attr;
1492 
1493         switch (hba->sli_intf & SLI_INTF_IF_TYPE_MASK) {
1494         case SLI_INTF_IF_TYPE_0:
1495 
1496                 /* Map in Hardware BAR pages that will be used for */
1497                 /* communication with HBA. */
1498                 if (hba->sli.sli4.bar1_acc_handle == 0) {
1499                         status = ddi_regs_map_setup(dip, PCI_BAR1_RINDEX,
1500                             (caddr_t *)&hba->sli.sli4.bar1_addr,
1501                             0, 0, &dev_attr, &hba->sli.sli4.bar1_acc_handle);
1502                         if (status != DDI_SUCCESS) {
1503                                 EMLXS_MSGF(EMLXS_CONTEXT,
1504                                     &emlxs_attach_failed_msg,
1505                                     "(PCI) ddi_regs_map_setup BAR1 failed. "
1506                                     "stat=%d mem=%p attr=%p hdl=%p",
1507                                     status, &hba->sli.sli4.bar1_addr, &dev_attr,
1508                                     &hba->sli.sli4.bar1_acc_handle);
1509                                 goto failed;
1510                         }
1511                 }
1512 
1513                 if (hba->sli.sli4.bar2_acc_handle == 0) {
1514                         status = ddi_regs_map_setup(dip, PCI_BAR2_RINDEX,
1515                             (caddr_t *)&hba->sli.sli4.bar2_addr,
1516                             0, 0, &dev_attr, &hba->sli.sli4.bar2_acc_handle);
1517                         if (status != DDI_SUCCESS) {
1518                                 EMLXS_MSGF(EMLXS_CONTEXT,
1519                                     &emlxs_attach_failed_msg,
1520                                     "ddi_regs_map_setup BAR2 failed. status=%x",
1521                                     status);
1522                                 goto failed;
1523                         }
1524                 }
1525 
1526                 /* offset from beginning of register space */
1527                 hba->sli.sli4.MPUEPSemaphore_reg_addr =
1528                     (uint32_t *)(hba->sli.sli4.bar1_addr +
1529                     CSR_MPU_EP_SEMAPHORE_OFFSET);
1530                 hba->sli.sli4.MBDB_reg_addr =
1531                     (uint32_t *)(hba->sli.sli4.bar2_addr + PD_MB_DB_OFFSET);
1532                 hba->sli.sli4.CQDB_reg_addr =
1533                     (uint32_t *)(hba->sli.sli4.bar2_addr + PD_CQ_DB_OFFSET);
1534                 hba->sli.sli4.MQDB_reg_addr =
1535                     (uint32_t *)(hba->sli.sli4.bar2_addr + PD_MQ_DB_OFFSET);
1536                 hba->sli.sli4.WQDB_reg_addr =
1537                     (uint32_t *)(hba->sli.sli4.bar2_addr + PD_WQ_DB_OFFSET);
1538                 hba->sli.sli4.RQDB_reg_addr =
1539                     (uint32_t *)(hba->sli.sli4.bar2_addr + PD_RQ_DB_OFFSET);
1540 
1541                 hba->sli.sli4.STATUS_reg_addr = 0;
1542                 hba->sli.sli4.CNTL_reg_addr = 0;
1543 
1544                 hba->sli.sli4.ERR1_reg_addr =
1545                     (uint32_t *)(hba->pci_addr + PCICFG_UE_STATUS_LO_OFFSET);
1546                 hba->sli.sli4.ERR2_reg_addr =
1547                     (uint32_t *)(hba->pci_addr + PCICFG_UE_STATUS_HI_OFFSET);
1548 
1549                 hba->sli.sli4.PHYSDEV_reg_addr = 0;
1550                 break;
1551 
1552         case SLI_INTF_IF_TYPE_2:
1553 
1554                 /* Map in Hardware BAR pages that will be used for */
1555                 /* communication with HBA. */
1556                 if (hba->sli.sli4.bar0_acc_handle == 0) {
1557                         status = ddi_regs_map_setup(dip, PCI_BAR0_RINDEX,
1558                             (caddr_t *)&hba->sli.sli4.bar0_addr,
1559                             0, 0, &dev_attr, &hba->sli.sli4.bar0_acc_handle);
1560                         if (status != DDI_SUCCESS) {
1561                                 EMLXS_MSGF(EMLXS_CONTEXT,
1562                                     &emlxs_attach_failed_msg,
1563                                     "(PCI) ddi_regs_map_setup BAR0 failed. "
1564                                     "stat=%d mem=%p attr=%p hdl=%p",
1565                                     status, &hba->sli.sli4.bar0_addr, &dev_attr,
1566                                     &hba->sli.sli4.bar0_acc_handle);
1567                                 goto failed;
1568                         }
1569                 }
1570 
1571                 /* offset from beginning of register space */
1572                 hba->sli.sli4.MPUEPSemaphore_reg_addr =
1573                     (uint32_t *)(hba->sli.sli4.bar0_addr +
1574                     SLIPORT_SEMAPHORE_OFFSET);
1575                 hba->sli.sli4.MBDB_reg_addr =
1576                     (uint32_t *)(hba->sli.sli4.bar0_addr + PD_MB_DB_OFFSET);
1577                 hba->sli.sli4.CQDB_reg_addr =
1578                     (uint32_t *)(hba->sli.sli4.bar0_addr + PD_CQ_DB_OFFSET);
1579                 hba->sli.sli4.MQDB_reg_addr =
1580                     (uint32_t *)(hba->sli.sli4.bar0_addr + PD_MQ_DB_OFFSET);
1581                 hba->sli.sli4.WQDB_reg_addr =
1582                     (uint32_t *)(hba->sli.sli4.bar0_addr + PD_WQ_DB_OFFSET);
1583                 hba->sli.sli4.RQDB_reg_addr =
1584                     (uint32_t *)(hba->sli.sli4.bar0_addr + PD_RQ_DB_OFFSET);
1585 
1586                 hba->sli.sli4.STATUS_reg_addr =
1587                     (uint32_t *)(hba->sli.sli4.bar0_addr +
1588                     SLIPORT_STATUS_OFFSET);
1589                 hba->sli.sli4.CNTL_reg_addr =
1590                     (uint32_t *)(hba->sli.sli4.bar0_addr +
1591                     SLIPORT_CONTROL_OFFSET);
1592                 hba->sli.sli4.ERR1_reg_addr =
1593                     (uint32_t *)(hba->sli.sli4.bar0_addr +
1594                     SLIPORT_ERROR1_OFFSET);
1595                 hba->sli.sli4.ERR2_reg_addr =
1596                     (uint32_t *)(hba->sli.sli4.bar0_addr +
1597                     SLIPORT_ERROR2_OFFSET);
1598                 hba->sli.sli4.PHYSDEV_reg_addr =
1599                     (uint32_t *)(hba->sli.sli4.bar0_addr +
1600                     PHYSDEV_CONTROL_OFFSET);
1601 
1602                 break;
1603 
1604         case SLI_INTF_IF_TYPE_1:
1605         case SLI_INTF_IF_TYPE_3:
1606         default:
1607                 EMLXS_MSGF(EMLXS_CONTEXT,
1608                     &emlxs_attach_failed_msg,
1609                     "Map hdw: Unsupported if_type %08x",
1610                     (hba->sli_intf & SLI_INTF_IF_TYPE_MASK));
1611 
1612                 goto failed;
1613         }
1614 
1615         if (hba->sli.sli4.bootstrapmb.virt == 0) {
1616                 MBUF_INFO       *buf_info;
1617                 MBUF_INFO       bufinfo;
1618 
1619                 buf_info = &bufinfo;
1620 
1621                 bzero(buf_info, sizeof (MBUF_INFO));
1622                 buf_info->size = EMLXS_BOOTSTRAP_MB_SIZE + MBOX_EXTENSION_SIZE;
1623                 buf_info->flags =
1624                     FC_MBUF_DMA | FC_MBUF_SNGLSG | FC_MBUF_DMA32;
1625                 buf_info->align = ddi_ptob(dip, 1L);
1626 
1627                 (void) emlxs_mem_alloc(hba, buf_info);
1628 
1629                 if (buf_info->virt == NULL) {
1630                         goto failed;
1631                 }
1632 
1633                 hba->sli.sli4.bootstrapmb.virt = buf_info->virt;
1634                 hba->sli.sli4.bootstrapmb.phys = buf_info->phys;
1635                 hba->sli.sli4.bootstrapmb.size = EMLXS_BOOTSTRAP_MB_SIZE +
1636                     MBOX_EXTENSION_SIZE;
1637                 hba->sli.sli4.bootstrapmb.data_handle = buf_info->data_handle;
1638                 hba->sli.sli4.bootstrapmb.dma_handle = buf_info->dma_handle;
1639                 bzero((char *)hba->sli.sli4.bootstrapmb.virt,
1640                     EMLXS_BOOTSTRAP_MB_SIZE);
1641         }
1642 
1643         hba->chan_count = MAX_CHANNEL;
1644 
1645         return (0);
1646 
1647 failed:
1648 
1649         emlxs_sli4_unmap_hdw(hba);
1650         return (ENOMEM);
1651 
1652 
1653 } /* emlxs_sli4_map_hdw() */
1654 
1655 
1656 /*ARGSUSED*/
1657 static void
1658 emlxs_sli4_unmap_hdw(emlxs_hba_t *hba)
1659 {
1660         MBUF_INFO       bufinfo;
1661         MBUF_INFO       *buf_info = &bufinfo;
1662 
1663 
1664         if (hba->sli.sli4.bar0_acc_handle) {
1665                 ddi_regs_map_free(&hba->sli.sli4.bar0_acc_handle);
1666                 hba->sli.sli4.bar0_acc_handle = 0;
1667         }
1668 
1669         if (hba->sli.sli4.bar1_acc_handle) {
1670                 ddi_regs_map_free(&hba->sli.sli4.bar1_acc_handle);
1671                 hba->sli.sli4.bar1_acc_handle = 0;
1672         }
1673 
1674         if (hba->sli.sli4.bar2_acc_handle) {
1675                 ddi_regs_map_free(&hba->sli.sli4.bar2_acc_handle);
1676                 hba->sli.sli4.bar2_acc_handle = 0;
1677         }
1678 
1679         if (hba->sli.sli4.bootstrapmb.virt) {
1680                 bzero(buf_info, sizeof (MBUF_INFO));
1681 
1682                 if (hba->sli.sli4.bootstrapmb.phys) {
1683                         buf_info->phys = hba->sli.sli4.bootstrapmb.phys;
1684                         buf_info->data_handle =
1685                             hba->sli.sli4.bootstrapmb.data_handle;
1686                         buf_info->dma_handle =
1687                             hba->sli.sli4.bootstrapmb.dma_handle;
1688                         buf_info->flags = FC_MBUF_DMA;
1689                 }
1690 
1691                 buf_info->virt = hba->sli.sli4.bootstrapmb.virt;
1692                 buf_info->size = hba->sli.sli4.bootstrapmb.size;
1693                 emlxs_mem_free(hba, buf_info);
1694 
1695                 hba->sli.sli4.bootstrapmb.virt = NULL;
1696         }
1697 
1698         return;
1699 
1700 } /* emlxs_sli4_unmap_hdw() */
1701 
1702 
1703 static int
1704 emlxs_check_hdw_ready(emlxs_hba_t *hba)
1705 {
1706         emlxs_port_t *port = &PPORT;
1707         uint32_t status;
1708         uint32_t i = 0;
1709         uint32_t err1;
1710         uint32_t err2;
1711 
1712         /* Wait for reset completion */
1713         while (i < 30) {
1714 
1715                 switch (hba->sli_intf & SLI_INTF_IF_TYPE_MASK) {
1716                 case SLI_INTF_IF_TYPE_0:
1717                         status = emlxs_sli4_read_sema(hba);
1718 
1719                         /* Check to see if any errors occurred during init */
1720                         if (status & ARM_POST_FATAL) {
1721                                 EMLXS_MSGF(EMLXS_CONTEXT,
1722                                     &emlxs_reset_failed_msg,
1723                                     "SEMA Error: status=%x", status);
1724 
1725                                 EMLXS_STATE_CHANGE(hba, FC_ERROR);
1726 
1727                                 return (1);
1728                         }
1729 
1730                         if ((status & ARM_UNRECOVERABLE_ERROR) ==
1731                             ARM_UNRECOVERABLE_ERROR) {
1732                                 EMLXS_MSGF(EMLXS_CONTEXT,
1733                                     &emlxs_reset_failed_msg,
1734                                     "Unrecoverable Error: status=%x", status);
1735 
1736                                 EMLXS_STATE_CHANGE(hba, FC_ERROR);
1737 
1738                                 return (1);
1739                         }
1740 
1741                         if ((status & ARM_POST_MASK) == ARM_POST_READY) {
1742                                 /* ARM Ready !! */
1743                                 EMLXS_MSGF(EMLXS_CONTEXT,
1744                                     &emlxs_sli_detail_msg,
1745                                     "ARM Ready: status=%x", status);
1746 
1747                                 return (0);
1748                         }
1749                         break;
1750 
1751                 case SLI_INTF_IF_TYPE_2:
1752                         status = emlxs_sli4_read_status(hba);
1753 
1754                         if (status & SLI_STATUS_READY) {
1755                                 if (!(status & SLI_STATUS_ERROR)) {
1756                                         /* ARM Ready !! */
1757                                         EMLXS_MSGF(EMLXS_CONTEXT,
1758                                             &emlxs_sli_detail_msg,
1759                                             "ARM Ready: status=%x", status);
1760 
1761                                         return (0);
1762                                 }
1763 
1764                                 err1 = ddi_get32(hba->sli.sli4.bar0_acc_handle,
1765                                     hba->sli.sli4.ERR1_reg_addr);
1766                                 err2 = ddi_get32(hba->sli.sli4.bar0_acc_handle,
1767                                     hba->sli.sli4.ERR2_reg_addr);
1768 
1769                                 if (status & SLI_STATUS_RESET_NEEDED) {
1770                                         EMLXS_MSGF(EMLXS_CONTEXT,
1771                                             &emlxs_sli_detail_msg,
1772                                             "ARM Ready (Reset Needed): "
1773                                             "status=%x err1=%x "
1774                                             "err2=%x",
1775                                             status, err1, err2);
1776 
1777                                         return (1);
1778                                 }
1779 
1780                                 EMLXS_MSGF(EMLXS_CONTEXT,
1781                                     &emlxs_reset_failed_msg,
1782                                     "Unrecoverable Error: status=%x err1=%x "
1783                                     "err2=%x",
1784                                     status, err1, err2);
1785 
1786                                 EMLXS_STATE_CHANGE(hba, FC_ERROR);
1787 
1788                                 return (2);
1789                         }
1790 
1791                         break;
1792 
1793                 default:
1794                         EMLXS_STATE_CHANGE(hba, FC_ERROR);
1795 
1796                         return (3);
1797                 }
1798 
1799                 BUSYWAIT_MS(1000);
1800                 i++;
1801         }
1802 
1803         /* Timeout occurred */
1804         switch (hba->sli_intf & SLI_INTF_IF_TYPE_MASK) {
1805         case SLI_INTF_IF_TYPE_0:
1806                 err1 = ddi_get32(hba->pci_acc_handle,
1807                     hba->sli.sli4.ERR1_reg_addr);
1808                 err2 = ddi_get32(hba->pci_acc_handle,
1809                     hba->sli.sli4.ERR2_reg_addr);
1810                 break;
1811 
1812         default:
1813                 err1 = ddi_get32(hba->sli.sli4.bar0_acc_handle,
1814                     hba->sli.sli4.ERR1_reg_addr);
1815                 err2 = ddi_get32(hba->sli.sli4.bar0_acc_handle,
1816                     hba->sli.sli4.ERR2_reg_addr);
1817                 break;
1818         }
1819 
1820         if (status & SLI_STATUS_ERROR) {
1821                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_reset_failed_msg,
1822                     "Ready Timeout: Port Error: status=%x err1=%x err2=%x",
1823                     status, err1, err2);
1824         } else {
1825                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_reset_failed_msg,
1826                     "Ready Timeout: status=%x err1=%x err2=%x",
1827                     status, err1, err2);
1828         }
1829 
1830         EMLXS_STATE_CHANGE(hba, FC_ERROR);
1831 
1832         return (3);
1833 
1834 } /* emlxs_check_hdw_ready() */
1835 
1836 
1837 static uint32_t
1838 emlxs_sli4_read_status(emlxs_hba_t *hba)
1839 {
1840 #ifdef FMA_SUPPORT
1841         emlxs_port_t *port = &PPORT;
1842 #endif  /* FMA_SUPPORT */
1843         uint32_t status;
1844 
1845         switch (hba->sli_intf & SLI_INTF_IF_TYPE_MASK) {
1846         case SLI_INTF_IF_TYPE_2:
1847                 status = ddi_get32(hba->sli.sli4.bar0_acc_handle,
1848                     hba->sli.sli4.STATUS_reg_addr);
1849 #ifdef FMA_SUPPORT
1850                 /* Access handle validation */
1851                 EMLXS_CHK_ACC_HANDLE(hba, hba->sli.sli4.bar0_acc_handle);
1852 #endif  /* FMA_SUPPORT */
1853                 break;
1854         default:
1855                 status = 0;
1856                 break;
1857         }
1858 
1859         return (status);
1860 
1861 } /* emlxs_sli4_read_status() */
1862 
1863 
1864 static uint32_t
1865 emlxs_sli4_read_sema(emlxs_hba_t *hba)
1866 {
1867 #ifdef FMA_SUPPORT
1868         emlxs_port_t *port = &PPORT;
1869 #endif  /* FMA_SUPPORT */
1870         uint32_t status;
1871 
1872         switch (hba->sli_intf & SLI_INTF_IF_TYPE_MASK) {
1873         case SLI_INTF_IF_TYPE_0:
1874                 status = ddi_get32(hba->sli.sli4.bar1_acc_handle,
1875                     hba->sli.sli4.MPUEPSemaphore_reg_addr);
1876 #ifdef FMA_SUPPORT
1877                 /* Access handle validation */
1878                 EMLXS_CHK_ACC_HANDLE(hba, hba->sli.sli4.bar1_acc_handle);
1879 #endif  /* FMA_SUPPORT */
1880                 break;
1881 
1882         case SLI_INTF_IF_TYPE_2:
1883                 status = ddi_get32(hba->sli.sli4.bar0_acc_handle,
1884                     hba->sli.sli4.MPUEPSemaphore_reg_addr);
1885 #ifdef FMA_SUPPORT
1886                 /* Access handle validation */
1887                 EMLXS_CHK_ACC_HANDLE(hba, hba->sli.sli4.bar0_acc_handle);
1888 #endif  /* FMA_SUPPORT */
1889                 break;
1890         default:
1891                 status = 0;
1892                 break;
1893         }
1894 
1895         return (status);
1896 
1897 } /* emlxs_sli4_read_sema() */
1898 
1899 
1900 static uint32_t
1901 emlxs_sli4_read_mbdb(emlxs_hba_t *hba)
1902 {
1903 #ifdef FMA_SUPPORT
1904         emlxs_port_t *port = &PPORT;
1905 #endif  /* FMA_SUPPORT */
1906         uint32_t status;
1907 
1908         switch (hba->sli_intf & SLI_INTF_IF_TYPE_MASK) {
1909         case SLI_INTF_IF_TYPE_0:
1910                 status = ddi_get32(hba->sli.sli4.bar2_acc_handle,
1911                     hba->sli.sli4.MBDB_reg_addr);
1912 
1913 #ifdef FMA_SUPPORT
1914                 /* Access handle validation */
1915                 EMLXS_CHK_ACC_HANDLE(hba, hba->sli.sli4.bar2_acc_handle);
1916 #endif  /* FMA_SUPPORT */
1917                 break;
1918 
1919         case SLI_INTF_IF_TYPE_2:
1920                 status = ddi_get32(hba->sli.sli4.bar0_acc_handle,
1921                     hba->sli.sli4.MBDB_reg_addr);
1922 #ifdef FMA_SUPPORT
1923                 /* Access handle validation */
1924                 EMLXS_CHK_ACC_HANDLE(hba, hba->sli.sli4.bar0_acc_handle);
1925 #endif  /* FMA_SUPPORT */
1926                 break;
1927         default:
1928                 status = 0;
1929                 break;
1930         }
1931 
1932         return (status);
1933 
1934 } /* emlxs_sli4_read_mbdb() */
1935 
1936 
1937 static void
1938 emlxs_sli4_write_mbdb(emlxs_hba_t *hba, uint32_t value)
1939 {
1940         switch (hba->sli_intf & SLI_INTF_IF_TYPE_MASK) {
1941         case SLI_INTF_IF_TYPE_0:
1942                 ddi_put32(hba->sli.sli4.bar2_acc_handle,
1943                     hba->sli.sli4.MBDB_reg_addr, value);
1944                 break;
1945 
1946         case SLI_INTF_IF_TYPE_2:
1947                 ddi_put32(hba->sli.sli4.bar0_acc_handle,
1948                     hba->sli.sli4.MBDB_reg_addr, value);
1949                 break;
1950         }
1951 
1952 } /* emlxs_sli4_write_mbdb() */
1953 
1954 
1955 static void
1956 emlxs_sli4_write_cqdb(emlxs_hba_t *hba, uint32_t value)
1957 {
1958         switch (hba->sli_intf & SLI_INTF_IF_TYPE_MASK) {
1959         case SLI_INTF_IF_TYPE_0:
1960                 ddi_put32(hba->sli.sli4.bar2_acc_handle,
1961                     hba->sli.sli4.CQDB_reg_addr, value);
1962                 break;
1963 
1964         case SLI_INTF_IF_TYPE_2:
1965                 ddi_put32(hba->sli.sli4.bar0_acc_handle,
1966                     hba->sli.sli4.CQDB_reg_addr, value);
1967                 break;
1968         }
1969 
1970 } /* emlxs_sli4_write_cqdb() */
1971 
1972 
1973 static void
1974 emlxs_sli4_write_rqdb(emlxs_hba_t *hba, uint32_t value)
1975 {
1976         switch (hba->sli_intf & SLI_INTF_IF_TYPE_MASK) {
1977         case SLI_INTF_IF_TYPE_0:
1978                 ddi_put32(hba->sli.sli4.bar2_acc_handle,
1979                     hba->sli.sli4.RQDB_reg_addr, value);
1980                 break;
1981 
1982         case SLI_INTF_IF_TYPE_2:
1983                 ddi_put32(hba->sli.sli4.bar0_acc_handle,
1984                     hba->sli.sli4.RQDB_reg_addr, value);
1985                 break;
1986         }
1987 
1988 } /* emlxs_sli4_write_rqdb() */
1989 
1990 
1991 static void
1992 emlxs_sli4_write_mqdb(emlxs_hba_t *hba, uint32_t value)
1993 {
1994         switch (hba->sli_intf & SLI_INTF_IF_TYPE_MASK) {
1995         case SLI_INTF_IF_TYPE_0:
1996                 ddi_put32(hba->sli.sli4.bar2_acc_handle,
1997                     hba->sli.sli4.MQDB_reg_addr, value);
1998                 break;
1999 
2000         case SLI_INTF_IF_TYPE_2:
2001                 ddi_put32(hba->sli.sli4.bar0_acc_handle,
2002                     hba->sli.sli4.MQDB_reg_addr, value);
2003                 break;
2004         }
2005 
2006 } /* emlxs_sli4_write_mqdb() */
2007 
2008 
2009 static void
2010 emlxs_sli4_write_wqdb(emlxs_hba_t *hba, uint32_t value)
2011 {
2012         switch (hba->sli_intf & SLI_INTF_IF_TYPE_MASK) {
2013         case SLI_INTF_IF_TYPE_0:
2014                 ddi_put32(hba->sli.sli4.bar2_acc_handle,
2015                     hba->sli.sli4.WQDB_reg_addr, value);
2016                 break;
2017 
2018         case SLI_INTF_IF_TYPE_2:
2019                 ddi_put32(hba->sli.sli4.bar0_acc_handle,
2020                     hba->sli.sli4.WQDB_reg_addr, value);
2021                 break;
2022         }
2023 
2024 } /* emlxs_sli4_write_wqdb() */
2025 
2026 
2027 static uint32_t
2028 emlxs_check_bootstrap_ready(emlxs_hba_t *hba, uint32_t tmo)
2029 {
2030         emlxs_port_t *port = &PPORT;
2031         uint32_t status = 0;
2032         uint32_t err1;
2033         uint32_t err2;
2034 
2035         /* Wait for reset completion, tmo is in 10ms ticks */
2036         while (tmo) {
2037                 status = emlxs_sli4_read_mbdb(hba);
2038 
2039                 /* Check to see if any errors occurred during init */
2040                 if (status & BMBX_READY) {
2041                         EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
2042                             "BMBX Ready: status=0x%x", status);
2043 
2044                         return (tmo);
2045                 }
2046 
2047                 BUSYWAIT_MS(10);
2048                 tmo--;
2049         }
2050 
2051         switch (hba->sli_intf & SLI_INTF_IF_TYPE_MASK) {
2052         case SLI_INTF_IF_TYPE_0:
2053                 err1 = ddi_get32(hba->pci_acc_handle,
2054                     hba->sli.sli4.ERR1_reg_addr);
2055                 err2 = ddi_get32(hba->pci_acc_handle,
2056                     hba->sli.sli4.ERR2_reg_addr);
2057                 break;
2058 
2059         default:
2060                 err1 = ddi_get32(hba->sli.sli4.bar0_acc_handle,
2061                     hba->sli.sli4.ERR1_reg_addr);
2062                 err2 = ddi_get32(hba->sli.sli4.bar0_acc_handle,
2063                     hba->sli.sli4.ERR2_reg_addr);
2064                 break;
2065         }
2066 
2067         /* Timeout occurred */
2068         EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_reset_failed_msg,
2069             "Timeout waiting for BMailbox: status=%x err1=%x err2=%x",
2070             status, err1, err2);
2071 
2072         EMLXS_STATE_CHANGE(hba, FC_ERROR);
2073 
2074         return (0);
2075 
2076 } /* emlxs_check_bootstrap_ready() */
2077 
2078 
2079 static uint32_t
2080 emlxs_issue_bootstrap_mb(emlxs_hba_t *hba, uint32_t tmo)
2081 {
2082         emlxs_port_t *port = &PPORT;
2083         uint32_t *iptr;
2084         uint32_t addr30;
2085 
2086         /*
2087          * This routine assumes the bootstrap mbox is loaded
2088          * with the mailbox command to be executed.
2089          *
2090          * First, load the high 30 bits of bootstrap mailbox
2091          */
2092         addr30 = (uint32_t)((hba->sli.sli4.bootstrapmb.phys>>32) & 0xfffffffc);
2093         addr30 |= BMBX_ADDR_HI;
2094         emlxs_sli4_write_mbdb(hba, addr30);
2095 
2096         tmo = emlxs_check_bootstrap_ready(hba, tmo);
2097         if (tmo == 0) {
2098                 return (0);
2099         }
2100 
2101         /* Load the low 30 bits of bootstrap mailbox */
2102         addr30 = (uint32_t)((hba->sli.sli4.bootstrapmb.phys>>2) & 0xfffffffc);
2103         emlxs_sli4_write_mbdb(hba, addr30);
2104 
2105         tmo = emlxs_check_bootstrap_ready(hba, tmo);
2106         if (tmo == 0) {
2107                 return (0);
2108         }
2109 
2110         iptr = (uint32_t *)hba->sli.sli4.bootstrapmb.virt;
2111 
2112         EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
2113             "BootstrapMB: %p Completed %08x %08x %08x",
2114             hba->sli.sli4.bootstrapmb.virt,
2115             *iptr, *(iptr+1), *(iptr+2));
2116 
2117         return (tmo);
2118 
2119 } /* emlxs_issue_bootstrap_mb() */
2120 
2121 
2122 static int
2123 emlxs_init_bootstrap_mb(emlxs_hba_t *hba)
2124 {
2125 #ifdef FMA_SUPPORT
2126         emlxs_port_t *port = &PPORT;
2127 #endif /* FMA_SUPPORT */
2128         uint32_t *iptr;
2129         uint32_t tmo;
2130 
2131         if (emlxs_check_hdw_ready(hba)) {
2132                 return (1);
2133         }
2134 
2135         if (hba->flag & FC_BOOTSTRAPMB_INIT) {
2136                 return (0);  /* Already initialized */
2137         }
2138 
2139         /* NOTE: tmo is in 10ms ticks */
2140         tmo = emlxs_check_bootstrap_ready(hba, 3000);
2141         if (tmo == 0) {
2142                 return (1);
2143         }
2144 
2145         /* Issue FW_INITIALIZE command */
2146 
2147         /* Special words to initialize bootstrap mbox MUST be little endian */
2148         iptr = (uint32_t *)hba->sli.sli4.bootstrapmb.virt;
2149         *iptr = LE_SWAP32(FW_INITIALIZE_WORD0);
2150         *(iptr+1) = LE_SWAP32(FW_INITIALIZE_WORD1);
2151 
2152         EMLXS_MPDATA_SYNC(hba->sli.sli4.bootstrapmb.dma_handle, 0,
2153             MAILBOX_CMD_BSIZE, DDI_DMA_SYNC_FORDEV);
2154 
2155         emlxs_data_dump(port, "FW_INIT", (uint32_t *)iptr, 6, 0);
2156         if (!emlxs_issue_bootstrap_mb(hba, tmo)) {
2157                 return (1);
2158         }
2159 
2160 #ifdef FMA_SUPPORT
2161         if (emlxs_fm_check_dma_handle(hba, hba->sli.sli4.bootstrapmb.dma_handle)
2162             != DDI_FM_OK) {
2163                 EMLXS_MSGF(EMLXS_CONTEXT,
2164                     &emlxs_invalid_dma_handle_msg,
2165                     "init_bootstrap_mb: hdl=%p",
2166                     hba->sli.sli4.bootstrapmb.dma_handle);
2167                 return (1);
2168         }
2169 #endif
2170         hba->flag |= FC_BOOTSTRAPMB_INIT;
2171         return (0);
2172 
2173 } /* emlxs_init_bootstrap_mb() */
2174 
2175 
2176 
2177 
2178 static uint32_t
2179 emlxs_sli4_hba_init(emlxs_hba_t *hba)
2180 {
2181         int rc;
2182         uint16_t i;
2183         emlxs_port_t *vport;
2184         emlxs_config_t *cfg = &CFG;
2185         CHANNEL *cp;
2186         VPIobj_t *vpip;
2187 
2188         /* Restart the adapter */
2189         if (emlxs_sli4_hba_reset(hba, 1, 0, 0)) {
2190                 return (1);
2191         }
2192 
2193         for (i = 0; i < hba->chan_count; i++) {
2194                 cp = &hba->chan[i];
2195                 cp->iopath = (void *)&hba->sli.sli4.wq[i];
2196         }
2197 
2198         /* Initialize all the port objects */
2199         hba->vpi_max  = 0;
2200         for (i = 0; i < MAX_VPORTS; i++) {
2201                 vport = &VPORT(i);
2202                 vport->hba = hba;
2203                 vport->vpi = i;
2204 
2205                 vpip = &vport->VPIobj;
2206                 vpip->index = i;
2207                 vpip->VPI = i;
2208                 vpip->port = vport;
2209                 vpip->state = VPI_STATE_OFFLINE;
2210                 vport->vpip = vpip;
2211         }
2212 
2213         /* Set the max node count */
2214         if (hba->max_nodes == 0) {
2215                 if (cfg[CFG_NUM_NODES].current > 0) {
2216                         hba->max_nodes = cfg[CFG_NUM_NODES].current;
2217                 } else {
2218                         hba->max_nodes = 4096;
2219                 }
2220         }
2221 
2222         rc = emlxs_init_bootstrap_mb(hba);
2223         if (rc) {
2224                 return (rc);
2225         }
2226 
2227         hba->sli.sli4.cfgFCOE.FCMap[0] = FCOE_FCF_MAP0;
2228         hba->sli.sli4.cfgFCOE.FCMap[1] = FCOE_FCF_MAP1;
2229         hba->sli.sli4.cfgFCOE.FCMap[2] = FCOE_FCF_MAP2;
2230 
2231         if ((hba->sli_intf & SLI_INTF_IF_TYPE_MASK) == SLI_INTF_IF_TYPE_0) {
2232                 /* Cache the UE MASK registers value for UE error detection */
2233                 hba->sli.sli4.ue_mask_lo = ddi_get32(hba->pci_acc_handle,
2234                     (uint32_t *)(hba->pci_addr + PCICFG_UE_MASK_LO_OFFSET));
2235                 hba->sli.sli4.ue_mask_hi = ddi_get32(hba->pci_acc_handle,
2236                     (uint32_t *)(hba->pci_addr + PCICFG_UE_MASK_HI_OFFSET));
2237         }
2238 
2239         return (0);
2240 
2241 } /* emlxs_sli4_hba_init() */
2242 
2243 
2244 /*ARGSUSED*/
2245 static uint32_t
2246 emlxs_sli4_hba_reset(emlxs_hba_t *hba, uint32_t restart, uint32_t skip_post,
2247                 uint32_t quiesce)
2248 {
2249         emlxs_port_t *port = &PPORT;
2250         emlxs_port_t *vport;
2251         CHANNEL *cp;
2252         emlxs_config_t *cfg = &CFG;
2253         MAILBOXQ mboxq;
2254         uint32_t value;
2255         uint32_t i;
2256         uint32_t rc;
2257         uint16_t channelno;
2258         uint32_t status;
2259         uint32_t err1;
2260         uint32_t err2;
2261         uint8_t generate_event = 0;
2262 
2263         if (!cfg[CFG_RESET_ENABLE].current) {
2264                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_reset_failed_msg,
2265                     "Adapter reset disabled.");
2266                 EMLXS_STATE_CHANGE(hba, FC_ERROR);
2267 
2268                 return (1);
2269         }
2270 
2271         switch (hba->sli_intf & SLI_INTF_IF_TYPE_MASK) {
2272         case SLI_INTF_IF_TYPE_0:
2273                 if (quiesce == 0) {
2274                         emlxs_sli4_hba_kill(hba);
2275 
2276                         /*
2277                          * Initalize Hardware that will be used to bring
2278                          * SLI4 online.
2279                          */
2280                         rc = emlxs_init_bootstrap_mb(hba);
2281                         if (rc) {
2282                                 return (rc);
2283                         }
2284                 }
2285 
2286                 bzero((void *)&mboxq, sizeof (MAILBOXQ));
2287                 emlxs_mb_resetport(hba, &mboxq);
2288 
2289                 if (quiesce == 0) {
2290                         if (emlxs_sli4_issue_mbox_cmd(hba, &mboxq,
2291                             MBX_POLL, 0) != MBX_SUCCESS) {
2292                                 /* Timeout occurred */
2293                                 EMLXS_MSGF(EMLXS_CONTEXT,
2294                                     &emlxs_reset_failed_msg,
2295                                     "Timeout: RESET");
2296                                 EMLXS_STATE_CHANGE(hba, FC_ERROR);
2297                                 /* Log a dump event - not supported */
2298                                 return (1);
2299                         }
2300                 } else {
2301                         if (emlxs_sli4_issue_mbox_cmd4quiesce(hba, &mboxq,
2302                             MBX_POLL, 0) != MBX_SUCCESS) {
2303                                 EMLXS_STATE_CHANGE(hba, FC_ERROR);
2304                                 /* Log a dump event - not supported */
2305                                 return (1);
2306                         }
2307                 }
2308                 emlxs_data_dump(port, "resetPort", (uint32_t *)&mboxq, 12, 0);
2309                 break;
2310 
2311         case SLI_INTF_IF_TYPE_2:
2312                 if (quiesce == 0) {
2313                         emlxs_sli4_hba_kill(hba);
2314                 }
2315 
2316                 rc = emlxs_check_hdw_ready(hba);
2317                 if (rc > 1) {
2318                         EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_debug_msg,
2319                             "Adapter not ready for reset.");
2320                         return (1);
2321                 }
2322 
2323                 if (rc == 1) {
2324                         err1 = ddi_get32(hba->sli.sli4.bar0_acc_handle,
2325                             hba->sli.sli4.ERR1_reg_addr);
2326                         err2 = ddi_get32(hba->sli.sli4.bar0_acc_handle,
2327                             hba->sli.sli4.ERR2_reg_addr);
2328 
2329                         /* Don't generate an event if dump was forced */
2330                         if ((err1 != 0x2) || (err2 != 0x2)) {
2331                                 generate_event = 1;
2332                         }
2333                 }
2334 
2335                 /* Reset the port now */
2336 
2337                 mutex_enter(&EMLXS_PORT_LOCK);
2338                 value = SLI_CNTL_INIT_PORT;
2339 
2340                 ddi_put32(hba->sli.sli4.bar0_acc_handle,
2341                     hba->sli.sli4.CNTL_reg_addr, value);
2342                 mutex_exit(&EMLXS_PORT_LOCK);
2343 
2344                 break;
2345         }
2346 
2347         /* Reset the hba structure */
2348         hba->flag &= FC_RESET_MASK;
2349 
2350         for (channelno = 0; channelno < hba->chan_count; channelno++) {
2351                 cp = &hba->chan[channelno];
2352                 cp->hba = hba;
2353                 cp->channelno = channelno;
2354         }
2355 
2356         hba->channel_tx_count = 0;
2357         hba->io_count = 0;
2358         hba->iodone_count = 0;
2359         hba->topology = 0;
2360         hba->linkspeed = 0;
2361         hba->heartbeat_active = 0;
2362         hba->discovery_timer = 0;
2363         hba->linkup_timer = 0;
2364         hba->loopback_tics = 0;
2365 
2366         /* Reset the port objects */
2367         for (i = 0; i < MAX_VPORTS; i++) {
2368                 vport = &VPORT(i);
2369 
2370                 vport->flag &= EMLXS_PORT_RESET_MASK;
2371                 vport->did = 0;
2372                 vport->prev_did = 0;
2373                 vport->lip_type = 0;
2374                 bzero(&vport->fabric_sparam, sizeof (SERV_PARM));
2375                 bzero(&vport->prev_fabric_sparam, sizeof (SERV_PARM));
2376 
2377                 bzero((caddr_t)&vport->node_base, sizeof (NODELIST));
2378                 vport->node_base.nlp_Rpi = 0;
2379                 vport->node_base.nlp_DID = 0xffffff;
2380                 vport->node_base.nlp_list_next = NULL;
2381                 vport->node_base.nlp_list_prev = NULL;
2382                 vport->node_base.nlp_active = 1;
2383                 vport->node_count = 0;
2384 
2385                 if (vport->ub_count < EMLXS_UB_TOKEN_OFFSET) {
2386                         vport->ub_count = EMLXS_UB_TOKEN_OFFSET;
2387                 }
2388         }
2389 
2390         if (emlxs_check_hdw_ready(hba)) {
2391                 return (1);
2392         }
2393 
2394         if (generate_event) {
2395                 status = emlxs_sli4_read_status(hba);
2396                 if (status & SLI_STATUS_DUMP_IMAGE_PRESENT) {
2397                         emlxs_log_dump_event(port, NULL, 0);
2398                 }
2399         }
2400 
2401         return (0);
2402 
2403 } /* emlxs_sli4_hba_reset */
2404 
2405 
2406 #define SGL_CMD         0
2407 #define SGL_RESP        1
2408 #define SGL_DATA        2
2409 #define SGL_LAST        0x80
2410 
2411 /*ARGSUSED*/
2412 static ULP_SGE64 *
2413 emlxs_pkt_to_sgl(emlxs_port_t *port, fc_packet_t *pkt, ULP_SGE64 *sge,
2414     uint32_t sgl_type, uint32_t *pcnt)
2415 {
2416 #ifdef DEBUG_SGE
2417         emlxs_hba_t *hba = HBA;
2418 #endif /* DEBUG_SGE */
2419         ddi_dma_cookie_t *cp;
2420         uint_t i;
2421         uint_t last;
2422         int32_t size;
2423         int32_t sge_size;
2424         uint64_t sge_addr;
2425         int32_t len;
2426         uint32_t cnt;
2427         uint_t cookie_cnt;
2428         ULP_SGE64 stage_sge;
2429 
2430         last = sgl_type & SGL_LAST;
2431         sgl_type &= ~SGL_LAST;
2432 
2433 #if (EMLXS_MODREV >= EMLXS_MODREV3)
2434         switch (sgl_type) {
2435         case SGL_CMD:
2436                 cp = pkt->pkt_cmd_cookie;
2437                 cookie_cnt = pkt->pkt_cmd_cookie_cnt;
2438                 size = (int32_t)pkt->pkt_cmdlen;
2439                 break;
2440 
2441         case SGL_RESP:
2442                 cp = pkt->pkt_resp_cookie;
2443                 cookie_cnt = pkt->pkt_resp_cookie_cnt;
2444                 size = (int32_t)pkt->pkt_rsplen;
2445                 break;
2446 
2447 
2448         case SGL_DATA:
2449                 cp = pkt->pkt_data_cookie;
2450                 cookie_cnt = pkt->pkt_data_cookie_cnt;
2451                 size = (int32_t)pkt->pkt_datalen;
2452                 break;
2453 
2454         default:
2455                 return (NULL);
2456         }
2457 
2458 #else
2459         switch (sgl_type) {
2460         case SGL_CMD:
2461                 cp = &pkt->pkt_cmd_cookie;
2462                 cookie_cnt = 1;
2463                 size = (int32_t)pkt->pkt_cmdlen;
2464                 break;
2465 
2466         case SGL_RESP:
2467                 cp = &pkt->pkt_resp_cookie;
2468                 cookie_cnt = 1;
2469                 size = (int32_t)pkt->pkt_rsplen;
2470                 break;
2471 
2472 
2473         case SGL_DATA:
2474                 cp = &pkt->pkt_data_cookie;
2475                 cookie_cnt = 1;
2476                 size = (int32_t)pkt->pkt_datalen;
2477                 break;
2478 
2479         default:
2480                 return (NULL);
2481         }
2482 #endif  /* >= EMLXS_MODREV3 */
2483 
2484         stage_sge.offset = 0;
2485         stage_sge.type = 0;
2486         stage_sge.last = 0;
2487         cnt = 0;
2488         for (i = 0; i < cookie_cnt && size > 0; i++, cp++) {
2489 
2490                 sge_size = cp->dmac_size;
2491                 sge_addr = cp->dmac_laddress;
2492                 while (sge_size && size) {
2493                         if (cnt) {
2494                                 /* Copy staged SGE before we build next one */
2495                                 BE_SWAP32_BCOPY((uint8_t *)&stage_sge,
2496                                     (uint8_t *)sge, sizeof (ULP_SGE64));
2497                                 sge++;
2498                         }
2499                         len = MIN(EMLXS_MAX_SGE_SIZE, sge_size);
2500                         len = MIN(size, len);
2501 
2502                         stage_sge.addrHigh =
2503                             PADDR_HI(sge_addr);
2504                         stage_sge.addrLow =
2505                             PADDR_LO(sge_addr);
2506                         stage_sge.length = len;
2507                         if (sgl_type == SGL_DATA) {
2508                                 stage_sge.offset = cnt;
2509                         }
2510 #ifdef DEBUG_SGE
2511                         emlxs_data_dump(port, "SGE", (uint32_t *)&stage_sge,
2512                             4, 0);
2513 #endif /* DEBUG_SGE */
2514                         sge_addr += len;
2515                         sge_size -= len;
2516 
2517                         cnt += len;
2518                         size -= len;
2519                 }
2520         }
2521 
2522         if (last) {
2523                 stage_sge.last = 1;
2524         }
2525         BE_SWAP32_BCOPY((uint8_t *)&stage_sge, (uint8_t *)sge,
2526             sizeof (ULP_SGE64));
2527 
2528         sge++;
2529 
2530         if (pcnt) {
2531                 *pcnt = cnt;
2532         }
2533         return (sge);
2534 
2535 } /* emlxs_pkt_to_sgl */
2536 
2537 
2538 /*ARGSUSED*/
2539 uint32_t
2540 emlxs_sli4_bde_setup(emlxs_port_t *port, emlxs_buf_t *sbp)
2541 {
2542         emlxs_hba_t *hba = HBA;
2543         fc_packet_t *pkt;
2544         XRIobj_t *xrip;
2545         ULP_SGE64 *sge;
2546         emlxs_wqe_t *wqe;
2547         IOCBQ *iocbq;
2548         ddi_dma_cookie_t *cp_cmd;
2549         ddi_dma_cookie_t *cp_data;
2550         uint64_t sge_addr;
2551         uint32_t cmd_cnt;
2552         uint32_t resp_cnt;
2553 
2554         iocbq = (IOCBQ *) &sbp->iocbq;
2555         wqe = &iocbq->wqe;
2556         pkt = PRIV2PKT(sbp);
2557         xrip = sbp->xrip;
2558         sge = xrip->SGList.virt;
2559 
2560 #if (EMLXS_MODREV >= EMLXS_MODREV3)
2561         cp_cmd = pkt->pkt_cmd_cookie;
2562         cp_data = pkt->pkt_data_cookie;
2563 #else
2564         cp_cmd  = &pkt->pkt_cmd_cookie;
2565         cp_data = &pkt->pkt_data_cookie;
2566 #endif  /* >= EMLXS_MODREV3 */
2567 
2568         iocbq = &sbp->iocbq;
2569         if (iocbq->flag & IOCB_FCP_CMD) {
2570 
2571                 if (pkt->pkt_tran_type == FC_PKT_OUTBOUND) {
2572                         return (1);
2573                 }
2574 
2575                 /* CMD payload */
2576                 sge = emlxs_pkt_to_sgl(port, pkt, sge, SGL_CMD, &cmd_cnt);
2577                 if (! sge) {
2578                         return (1);
2579                 }
2580 
2581                 /* DATA payload */
2582                 if (pkt->pkt_datalen != 0) {
2583                         /* RSP payload */
2584                         sge = emlxs_pkt_to_sgl(port, pkt, sge,
2585                             SGL_RESP, &resp_cnt);
2586                         if (! sge) {
2587                                 return (1);
2588                         }
2589 
2590                         /* Data payload */
2591                         sge = emlxs_pkt_to_sgl(port, pkt, sge,
2592                             SGL_DATA | SGL_LAST, 0);
2593                         if (! sge) {
2594                                 return (1);
2595                         }
2596 sgl_done:
2597                         if (hba->sli.sli4.flag & EMLXS_SLI4_PHON) {
2598                                 sge_addr = cp_data->dmac_laddress;
2599                                 wqe->FirstData.addrHigh = PADDR_HI(sge_addr);
2600                                 wqe->FirstData.addrLow = PADDR_LO(sge_addr);
2601                                 wqe->FirstData.tus.f.bdeSize =
2602                                     cp_data->dmac_size;
2603                         }
2604                 } else {
2605                         /* RSP payload */
2606                         sge = emlxs_pkt_to_sgl(port, pkt, sge,
2607                             SGL_RESP | SGL_LAST, &resp_cnt);
2608                         if (! sge) {
2609                                 return (1);
2610                         }
2611                 }
2612 
2613                 wqe->un.FcpCmd.Payload.addrHigh =
2614                     PADDR_HI(cp_cmd->dmac_laddress);
2615                 wqe->un.FcpCmd.Payload.addrLow =
2616                     PADDR_LO(cp_cmd->dmac_laddress);
2617                 wqe->un.FcpCmd.Payload.tus.f.bdeSize = cmd_cnt;
2618                 wqe->un.FcpCmd.PayloadLength = cmd_cnt + resp_cnt;
2619 
2620         } else {
2621 
2622                 if (pkt->pkt_tran_type == FC_PKT_OUTBOUND) {
2623                         /* CMD payload */
2624                         sge = emlxs_pkt_to_sgl(port, pkt, sge,
2625                             SGL_CMD | SGL_LAST, &cmd_cnt);
2626                         if (! sge) {
2627                                 return (1);
2628                         }
2629                 } else {
2630                         /* CMD payload */
2631                         sge = emlxs_pkt_to_sgl(port, pkt, sge,
2632                             SGL_CMD, &cmd_cnt);
2633                         if (! sge) {
2634                                 return (1);
2635                         }
2636 
2637                         /* RSP payload */
2638                         sge = emlxs_pkt_to_sgl(port, pkt, sge,
2639                             SGL_RESP | SGL_LAST, &resp_cnt);
2640                         if (! sge) {
2641                                 return (1);
2642                         }
2643                         wqe->un.GenReq.PayloadLength = cmd_cnt;
2644                 }
2645 
2646                 wqe->un.GenReq.Payload.addrHigh =
2647                     PADDR_HI(cp_cmd->dmac_laddress);
2648                 wqe->un.GenReq.Payload.addrLow =
2649                     PADDR_LO(cp_cmd->dmac_laddress);
2650                 wqe->un.GenReq.Payload.tus.f.bdeSize = cmd_cnt;
2651         }
2652         return (0);
2653 } /* emlxs_sli4_bde_setup */
2654 
2655 
2656 
2657 
2658 #ifdef SFCT_SUPPORT
2659 /*ARGSUSED*/
2660 static uint32_t
2661 emlxs_sli4_fct_bde_setup(emlxs_port_t *port, emlxs_buf_t *sbp)
2662 {
2663         emlxs_hba_t *hba = HBA;
2664         emlxs_wqe_t *wqe;
2665         ULP_SGE64 stage_sge;
2666         ULP_SGE64 *sge;
2667         IOCB *iocb;
2668         IOCBQ *iocbq;
2669         MATCHMAP *mp;
2670         MATCHMAP *fct_mp;
2671         XRIobj_t *xrip;
2672         uint64_t sge_addr;
2673         uint32_t sge_size;
2674         uint32_t cnt;
2675         uint32_t len;
2676         uint32_t size;
2677         uint32_t *xrdy_vaddr;
2678         stmf_data_buf_t *dbuf;
2679 
2680         iocbq = &sbp->iocbq;
2681         iocb = &iocbq->iocb;
2682         wqe = &iocbq->wqe;
2683         xrip = sbp->xrip;
2684 
2685         if (!sbp->fct_buf) {
2686                 return (0);
2687         }
2688 
2689         size = sbp->fct_buf->db_data_size;
2690 
2691         /*
2692          * The hardware will automaticlly round up
2693          * to multiple of 4.
2694          *
2695          * if (size & 3) {
2696          *      size = (size + 3) & 0xfffffffc;
2697          * }
2698          */
2699         fct_mp = (MATCHMAP *)sbp->fct_buf->db_port_private;
2700 
2701         if (sbp->fct_buf->db_sglist_length != 1) {
2702                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_error_msg,
2703                     "fct_bde_setup: Only 1 sglist entry supported: %d",
2704                     sbp->fct_buf->db_sglist_length);
2705                 return (1);
2706         }
2707 
2708         sge = xrip->SGList.virt;
2709 
2710         if (iocb->ULPCOMMAND == CMD_FCP_TRECEIVE64_CX) {
2711 
2712                 mp = emlxs_mem_buf_alloc(hba, EMLXS_XFER_RDY_SIZE);
2713                 if (!mp || !mp->virt || !mp->phys) {
2714                         EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_error_msg,
2715                             "fct_bde_setup: Cannot allocate XRDY memory");
2716                         return (1);
2717                 }
2718                 /* Save the MATCHMAP info to free this memory later */
2719                 iocbq->bp = mp;
2720 
2721                 /* Point to XRDY payload */
2722                 xrdy_vaddr = (uint32_t *)(mp->virt);
2723 
2724                 /* Fill in burstsize in payload */
2725                 *xrdy_vaddr++ = 0;
2726                 *xrdy_vaddr++ = LE_SWAP32(size);
2727                 *xrdy_vaddr = 0;
2728 
2729                 /* First 2 SGEs are XRDY and SKIP */
2730                 stage_sge.addrHigh = PADDR_HI(mp->phys);
2731                 stage_sge.addrLow = PADDR_LO(mp->phys);
2732                 stage_sge.length = EMLXS_XFER_RDY_SIZE;
2733                 stage_sge.offset = 0;
2734                 stage_sge.type = 0;
2735                 stage_sge.last = 0;
2736 
2737                 /* Words  0-3 */
2738                 wqe->un.FcpCmd.Payload.addrHigh = stage_sge.addrHigh;
2739                 wqe->un.FcpCmd.Payload.addrLow = stage_sge.addrLow;
2740                 wqe->un.FcpCmd.Payload.tus.f.bdeSize = EMLXS_XFER_RDY_SIZE;
2741                 wqe->un.FcpCmd.PayloadLength = EMLXS_XFER_RDY_SIZE;
2742 
2743         } else {        /* CMD_FCP_TSEND64_CX */
2744                 /* First 2 SGEs are SKIP */
2745                 stage_sge.addrHigh = 0;
2746                 stage_sge.addrLow = 0;
2747                 stage_sge.length = 0;
2748                 stage_sge.offset = 0;
2749                 stage_sge.type = EMLXS_SGE_TYPE_SKIP;
2750                 stage_sge.last = 0;
2751 
2752                 /* Words  0-3 */
2753                 wqe->un.FcpCmd.Payload.addrHigh = PADDR_HI(fct_mp->phys);
2754                 wqe->un.FcpCmd.Payload.addrLow = PADDR_LO(fct_mp->phys);
2755 
2756                 /* The BDE should match the contents of the first SGE payload */
2757                 len = MIN(EMLXS_MAX_SGE_SIZE, size);
2758                 wqe->un.FcpCmd.Payload.tus.f.bdeSize = len;
2759 
2760                 /* The PayloadLength should be set to 0 for TSEND64. */
2761                 wqe->un.FcpCmd.PayloadLength = 0;
2762         }
2763 
2764         dbuf = sbp->fct_buf;
2765         /*
2766          * TotalTransferCount equals to Relative Offset field (Word 4)
2767          * in both TSEND64 and TRECEIVE64 WQE.
2768          */
2769         wqe->un.FcpCmd.TotalTransferCount = dbuf->db_relative_offset;
2770 
2771         /* Copy staged SGE into SGL */
2772         BE_SWAP32_BCOPY((uint8_t *)&stage_sge,
2773             (uint8_t *)sge, sizeof (ULP_SGE64));
2774         sge++;
2775 
2776         stage_sge.addrHigh = 0;
2777         stage_sge.addrLow = 0;
2778         stage_sge.length = 0;
2779         stage_sge.offset = 0;
2780         stage_sge.type = EMLXS_SGE_TYPE_SKIP;
2781         stage_sge.last = 0;
2782 
2783         /* Copy staged SGE into SGL */
2784         BE_SWAP32_BCOPY((uint8_t *)&stage_sge,
2785             (uint8_t *)sge, sizeof (ULP_SGE64));
2786         sge++;
2787 
2788         sge_size = size;
2789         sge_addr = fct_mp->phys;
2790         cnt = 0;
2791 
2792         /* Build SGEs */
2793         while (sge_size) {
2794                 if (cnt) {
2795                         /* Copy staged SGE before we build next one */
2796                         BE_SWAP32_BCOPY((uint8_t *)&stage_sge,
2797                             (uint8_t *)sge, sizeof (ULP_SGE64));
2798                         sge++;
2799                 }
2800 
2801                 len = MIN(EMLXS_MAX_SGE_SIZE, sge_size);
2802 
2803                 stage_sge.addrHigh = PADDR_HI(sge_addr);
2804                 stage_sge.addrLow = PADDR_LO(sge_addr);
2805                 stage_sge.length = len;
2806                 stage_sge.offset = cnt;
2807                 stage_sge.type = EMLXS_SGE_TYPE_DATA;
2808 
2809                 sge_addr += len;
2810                 sge_size -= len;
2811                 cnt += len;
2812         }
2813 
2814         stage_sge.last = 1;
2815 
2816         if (hba->sli.sli4.flag & EMLXS_SLI4_PHON) {
2817                 wqe->FirstData.addrHigh = stage_sge.addrHigh;
2818                 wqe->FirstData.addrLow = stage_sge.addrLow;
2819                 wqe->FirstData.tus.f.bdeSize = stage_sge.length;
2820         }
2821         /* Copy staged SGE into SGL */
2822         BE_SWAP32_BCOPY((uint8_t *)&stage_sge,
2823             (uint8_t *)sge, sizeof (ULP_SGE64));
2824 
2825         return (0);
2826 
2827 } /* emlxs_sli4_fct_bde_setup */
2828 #endif /* SFCT_SUPPORT */
2829 
2830 
2831 static void
2832 emlxs_sli4_issue_iocb_cmd(emlxs_hba_t *hba, CHANNEL *cp, IOCBQ *iocbq)
2833 {
2834         emlxs_port_t *port = &PPORT;
2835         emlxs_buf_t *sbp;
2836         uint32_t channelno;
2837         int32_t throttle;
2838         emlxs_wqe_t *wqe;
2839         emlxs_wqe_t *wqeslot;
2840         WQ_DESC_t *wq;
2841         uint32_t flag;
2842         uint32_t wqdb;
2843         uint16_t next_wqe;
2844         off_t offset;
2845 #ifdef NODE_THROTTLE_SUPPORT
2846         int32_t node_throttle;
2847         NODELIST *marked_node = NULL;
2848 #endif /* NODE_THROTTLE_SUPPORT */
2849 
2850 
2851         channelno = cp->channelno;
2852         wq = (WQ_DESC_t *)cp->iopath;
2853 
2854 #ifdef DEBUG_FASTPATH
2855         EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
2856             "ISSUE WQE channel: %x  %p", channelno, wq);
2857 #endif /* DEBUG_FASTPATH */
2858 
2859         throttle = 0;
2860 
2861         /* Check if FCP ring and adapter is not ready */
2862         /* We may use any ring for FCP_CMD */
2863         if (iocbq && (iocbq->flag & IOCB_FCP_CMD) && (hba->state != FC_READY)) {
2864                 if (!(iocbq->flag & IOCB_SPECIAL) || !iocbq->port ||
2865                     (((emlxs_port_t *)iocbq->port)->mode == MODE_INITIATOR)) {
2866                         emlxs_tx_put(iocbq, 1);
2867                         return;
2868                 }
2869         }
2870 
2871         /* Attempt to acquire CMD_RING lock */
2872         if (mutex_tryenter(&EMLXS_QUE_LOCK(channelno)) == 0) {
2873                 /* Queue it for later */
2874                 if (iocbq) {
2875                         if ((hba->io_count -
2876                             hba->channel_tx_count) > 10) {
2877                                 emlxs_tx_put(iocbq, 1);
2878                                 return;
2879                         } else {
2880 
2881                                 mutex_enter(&EMLXS_QUE_LOCK(channelno));
2882                         }
2883                 } else {
2884                         return;
2885                 }
2886         }
2887         /* EMLXS_QUE_LOCK acquired */
2888 
2889         /* Throttle check only applies to non special iocb */
2890         if (iocbq && (!(iocbq->flag & IOCB_SPECIAL))) {
2891                 /* Check if HBA is full */
2892                 throttle = hba->io_throttle - hba->io_active;
2893                 if (throttle <= 0) {
2894                         /* Hitting adapter throttle limit */
2895                         /* Queue it for later */
2896                         if (iocbq) {
2897                                 emlxs_tx_put(iocbq, 1);
2898                         }
2899 
2900                         goto busy;
2901                 }
2902         }
2903 
2904         /* Check to see if we have room for this WQE */
2905         next_wqe = wq->host_index + 1;
2906         if (next_wqe >= wq->max_index) {
2907                 next_wqe = 0;
2908         }
2909 
2910         if (next_wqe == wq->port_index) {
2911                 /* Queue it for later */
2912                 if (iocbq) {
2913                         emlxs_tx_put(iocbq, 1);
2914                 }
2915                 goto busy;
2916         }
2917 
2918         /*
2919          * We have a command ring slot available
2920          * Make sure we have an iocb to send
2921          */
2922         if (iocbq) {
2923                 mutex_enter(&EMLXS_TX_CHANNEL_LOCK);
2924 
2925                 /* Check if the ring already has iocb's waiting */
2926                 if (cp->nodeq.q_first != NULL) {
2927                         /* Put the current iocbq on the tx queue */
2928                         emlxs_tx_put(iocbq, 0);
2929 
2930                         /*
2931                          * Attempt to replace it with the next iocbq
2932                          * in the tx queue
2933                          */
2934                         iocbq = emlxs_tx_get(cp, 0);
2935                 }
2936 
2937                 mutex_exit(&EMLXS_TX_CHANNEL_LOCK);
2938         } else {
2939                 iocbq = emlxs_tx_get(cp, 1);
2940         }
2941 
2942 sendit:
2943         /* Process each iocbq */
2944         while (iocbq) {
2945                 sbp = iocbq->sbp;
2946 
2947 #ifdef NODE_THROTTLE_SUPPORT
2948                 if (sbp && sbp->node && sbp->node->io_throttle) {
2949                         node_throttle = sbp->node->io_throttle -
2950                             sbp->node->io_active;
2951                         if (node_throttle <= 0) {
2952                                 /* Node is busy */
2953                                 /* Queue this iocb and get next iocb from */
2954                                 /* channel */
2955 
2956                                 if (!marked_node) {
2957                                         marked_node = sbp->node;
2958                                 }
2959 
2960                                 mutex_enter(&EMLXS_TX_CHANNEL_LOCK);
2961                                 emlxs_tx_put(iocbq, 0);
2962 
2963                                 if (cp->nodeq.q_first == marked_node) {
2964                                         mutex_exit(&EMLXS_TX_CHANNEL_LOCK);
2965                                         goto busy;
2966                                 }
2967 
2968                                 iocbq = emlxs_tx_get(cp, 0);
2969                                 mutex_exit(&EMLXS_TX_CHANNEL_LOCK);
2970                                 continue;
2971                         }
2972                 }
2973                 marked_node = 0;
2974 #endif /* NODE_THROTTLE_SUPPORT */
2975 
2976                 wqe = &iocbq->wqe;
2977 #ifdef DEBUG_FASTPATH
2978                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
2979                     "ISSUE QID %d WQE iotag:%x xri:%d", wq->qid,
2980                     wqe->RequestTag, wqe->XRITag);
2981 #endif /* DEBUG_FASTPATH */
2982 
2983                 if (sbp) {
2984                         /* If exchange removed after wqe was prep'ed, drop it */
2985                         if (!(sbp->xrip)) {
2986                                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
2987                                     "Xmit WQE iotag:%x xri:%d aborted",
2988                                     wqe->RequestTag, wqe->XRITag);
2989 
2990                                 /* Get next iocb from the tx queue */
2991                                 iocbq = emlxs_tx_get(cp, 1);
2992                                 continue;
2993                         }
2994 
2995                         if (sbp->pkt_flags & PACKET_DELAY_REQUIRED) {
2996 
2997                                 /* Perform delay */
2998                                 if ((channelno == hba->channel_els) &&
2999                                     !(iocbq->flag & IOCB_FCP_CMD)) {
3000                                         drv_usecwait(100000);
3001                                 } else {
3002                                         drv_usecwait(20000);
3003                                 }
3004                         }
3005 
3006                         /* Check for ULP pkt request */
3007                         mutex_enter(&sbp->mtx);
3008 
3009                         if (sbp->node == NULL) {
3010                                 /* Set node to base node by default */
3011                                 iocbq->node = (void *)&port->node_base;
3012                                 sbp->node = (void *)&port->node_base;
3013                         }
3014 
3015                         sbp->pkt_flags |= PACKET_IN_CHIPQ;
3016                         mutex_exit(&sbp->mtx);
3017 
3018                         atomic_inc_32(&hba->io_active);
3019 #ifdef NODE_THROTTLE_SUPPORT
3020                         if (sbp->node) {
3021                                 atomic_inc_32(&sbp->node->io_active);
3022                         }
3023 #endif /* NODE_THROTTLE_SUPPORT */
3024 
3025                         sbp->xrip->flag |= EMLXS_XRI_PENDING_IO;
3026 #ifdef SFCT_SUPPORT
3027 #ifdef FCT_IO_TRACE
3028                         if (sbp->fct_cmd) {
3029                                 emlxs_fct_io_trace(port, sbp->fct_cmd,
3030                                     EMLXS_FCT_IOCB_ISSUED);
3031                                 emlxs_fct_io_trace(port, sbp->fct_cmd,
3032                                     icmd->ULPCOMMAND);
3033                         }
3034 #endif /* FCT_IO_TRACE */
3035 #endif /* SFCT_SUPPORT */
3036                         cp->hbaSendCmd_sbp++;
3037                         iocbq->channel = cp;
3038                 } else {
3039                         cp->hbaSendCmd++;
3040                 }
3041 
3042                 flag = iocbq->flag;
3043 
3044                 /*
3045                  * At this point, we have a command ring slot available
3046                  * and an iocb to send
3047                  */
3048                 wq->release_depth--;
3049                 if (wq->release_depth == 0) {
3050                         wq->release_depth = WQE_RELEASE_DEPTH;
3051                         wqe->WQEC = 1;
3052                 }
3053 
3054                 HBASTATS.IocbIssued[channelno]++;
3055                 wq->num_proc++;
3056 
3057                 /* Send the iocb */
3058                 wqeslot = (emlxs_wqe_t *)wq->addr.virt;
3059                 wqeslot += wq->host_index;
3060 
3061                 wqe->CQId = wq->cqid;
3062                 if (hba->sli.sli4.param.PHWQ) {
3063                         WQE_PHWQ_WQID(wqe, wq->qid);
3064                 }
3065                 BE_SWAP32_BCOPY((uint8_t *)wqe, (uint8_t *)wqeslot,
3066                     sizeof (emlxs_wqe_t));
3067 #ifdef DEBUG_WQE
3068                 emlxs_data_dump(port, "WQE", (uint32_t *)wqe, 18, 0);
3069 #endif /* DEBUG_WQE */
3070                 offset = (off_t)((uint64_t)((unsigned long)
3071                     wq->addr.virt) -
3072                     (uint64_t)((unsigned long)
3073                     hba->sli.sli4.slim2.virt));
3074 
3075                 EMLXS_MPDATA_SYNC(wq->addr.dma_handle, offset,
3076                     4096, DDI_DMA_SYNC_FORDEV);
3077 
3078                 /* Ring the WQ Doorbell */
3079                 wqdb = wq->qid;
3080                 wqdb |= ((1 << 24) | (wq->host_index << 16));
3081 
3082                 /*
3083                  * After this, the sbp / iocb / wqe should not be
3084                  * accessed in the xmit path.
3085                  */
3086 
3087                 emlxs_sli4_write_wqdb(hba, wqdb);
3088                 wq->host_index = next_wqe;
3089 
3090 #ifdef DEBUG_FASTPATH
3091                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
3092                     "WQ RING: %08x", wqdb);
3093 #endif /* DEBUG_FASTPATH */
3094 
3095                 if (!sbp) {
3096                         emlxs_mem_put(hba, MEM_IOCB, (void *)iocbq);
3097                 }
3098 
3099                 if (iocbq && (!(flag & IOCB_SPECIAL))) {
3100                         /* Check if HBA is full */
3101                         throttle = hba->io_throttle - hba->io_active;
3102                         if (throttle <= 0) {
3103                                 goto busy;
3104                         }
3105                 }
3106 
3107                 /* Check to see if we have room for another WQE */
3108                 next_wqe++;
3109                 if (next_wqe >= wq->max_index) {
3110                         next_wqe = 0;
3111                 }
3112 
3113                 if (next_wqe == wq->port_index) {
3114                         /* Queue it for later */
3115                         goto busy;
3116                 }
3117 
3118                 /* Get the next iocb from the tx queue if there is one */
3119                 iocbq = emlxs_tx_get(cp, 1);
3120         }
3121 
3122         mutex_exit(&EMLXS_QUE_LOCK(channelno));
3123 
3124         return;
3125 
3126 busy:
3127         wq->num_busy++;
3128         if (throttle <= 0) {
3129                 HBASTATS.IocbThrottled++;
3130         } else {
3131                 HBASTATS.IocbRingFull[channelno]++;
3132         }
3133 
3134         mutex_exit(&EMLXS_QUE_LOCK(channelno));
3135 
3136         return;
3137 
3138 } /* emlxs_sli4_issue_iocb_cmd() */
3139 
3140 
3141 /*ARGSUSED*/
3142 static uint32_t
3143 emlxs_sli4_issue_mq(emlxs_port_t *port, MAILBOX4 *mqe, MAILBOX *mb,
3144     uint32_t tmo)
3145 {
3146         emlxs_hba_t *hba = HBA;
3147         MAILBOXQ        *mbq;
3148         MAILBOX4        *mb4;
3149         MATCHMAP        *mp;
3150         uint32_t        *iptr;
3151         uint32_t        mqdb;
3152         off_t           offset;
3153 
3154         mbq = (MAILBOXQ *)mb;
3155         mb4 = (MAILBOX4 *)mb;
3156         mp = (MATCHMAP *) mbq->nonembed;
3157         hba->mbox_mqe = (void *)mqe;
3158 
3159         if ((mb->mbxCommand != MBX_SLI_CONFIG) ||
3160             (mb4->un.varSLIConfig.be.embedded)) {
3161                 /*
3162                  * If this is an embedded mbox, everything should fit
3163                  * into the mailbox area.
3164                  */
3165                 BE_SWAP32_BCOPY((uint8_t *)mb, (uint8_t *)mqe,
3166                     MAILBOX_CMD_SLI4_BSIZE);
3167 
3168                 EMLXS_MPDATA_SYNC(hba->sli.sli4.mq.addr.dma_handle, 0,
3169                     4096, DDI_DMA_SYNC_FORDEV);
3170 
3171                 if (mb->mbxCommand != MBX_HEARTBEAT) {
3172                         emlxs_data_dump(port, "MBOX CMD", (uint32_t *)mqe,
3173                             18, 0);
3174                 }
3175         } else {
3176                 /* SLI_CONFIG and non-embedded */
3177 
3178                 /*
3179                  * If this is not embedded, the MQ area
3180                  * MUST contain a SGE pointer to a larger area for the
3181                  * non-embedded mailbox command.
3182                  * mp will point to the actual mailbox command which
3183                  * should be copied into the non-embedded area.
3184                  */
3185                 mb4->un.varSLIConfig.be.sge_cnt = 1;
3186                 mb4->un.varSLIConfig.be.payload_length = mp->size;
3187                 iptr = (uint32_t *)&mb4->un.varSLIConfig.be.un_hdr.hdr_req;
3188                 *iptr++ = (uint32_t)PADDR_LO(mp->phys);
3189                 *iptr++ = (uint32_t)PADDR_HI(mp->phys);
3190                 *iptr = mp->size;
3191 
3192                 BE_SWAP32_BUFFER(mp->virt, mp->size);
3193 
3194                 EMLXS_MPDATA_SYNC(mp->dma_handle, 0, mp->size,
3195                     DDI_DMA_SYNC_FORDEV);
3196 
3197                 BE_SWAP32_BCOPY((uint8_t *)mb, (uint8_t *)mqe,
3198                     MAILBOX_CMD_SLI4_BSIZE);
3199 
3200                 offset = (off_t)((uint64_t)((unsigned long)
3201                     hba->sli.sli4.mq.addr.virt) -
3202                     (uint64_t)((unsigned long)
3203                     hba->sli.sli4.slim2.virt));
3204 
3205                 EMLXS_MPDATA_SYNC(hba->sli.sli4.mq.addr.dma_handle, offset,
3206                     4096, DDI_DMA_SYNC_FORDEV);
3207 
3208                 emlxs_data_dump(port, "MBOX EXT", (uint32_t *)mqe, 12, 0);
3209                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mbox_detail_msg,
3210                     "Extension Addr %p %p", mp->phys, (uint32_t *)(mp->virt));
3211                 emlxs_data_dump(port, "EXT AREA", (uint32_t *)mp->virt, 24, 0);
3212         }
3213 
3214         /* Ring the MQ Doorbell */
3215         mqdb = hba->sli.sli4.mq.qid;
3216         mqdb |= ((1 << MQ_DB_POP_SHIFT) & MQ_DB_POP_MASK);
3217 
3218         if (mb->mbxCommand != MBX_HEARTBEAT) {
3219                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
3220                     "MQ RING: %08x", mqdb);
3221         }
3222 
3223         emlxs_sli4_write_mqdb(hba, mqdb);
3224 
3225         return (MBX_SUCCESS);
3226 
3227 } /* emlxs_sli4_issue_mq() */
3228 
3229 
3230 /*ARGSUSED*/
3231 static uint32_t
3232 emlxs_sli4_issue_bootstrap(emlxs_hba_t *hba, MAILBOX *mb, uint32_t tmo)
3233 {
3234         emlxs_port_t    *port = &PPORT;
3235         MAILBOXQ        *mbq;
3236         MAILBOX4        *mb4;
3237         MATCHMAP        *mp = NULL;
3238         uint32_t        *iptr;
3239         int             nonembed = 0;
3240 
3241         mbq = (MAILBOXQ *)mb;
3242         mb4 = (MAILBOX4 *)mb;
3243         mp = (MATCHMAP *) mbq->nonembed;
3244         hba->mbox_mqe = hba->sli.sli4.bootstrapmb.virt;
3245 
3246         if ((mb->mbxCommand != MBX_SLI_CONFIG) ||
3247             (mb4->un.varSLIConfig.be.embedded)) {
3248                 /*
3249                  * If this is an embedded mbox, everything should fit
3250                  * into the bootstrap mailbox area.
3251                  */
3252                 iptr = (uint32_t *)hba->sli.sli4.bootstrapmb.virt;
3253                 BE_SWAP32_BCOPY((uint8_t *)mb, (uint8_t *)iptr,
3254                     MAILBOX_CMD_SLI4_BSIZE);
3255 
3256                 EMLXS_MPDATA_SYNC(hba->sli.sli4.bootstrapmb.dma_handle, 0,
3257                     MAILBOX_CMD_SLI4_BSIZE, DDI_DMA_SYNC_FORDEV);
3258                 emlxs_data_dump(port, "MBOX CMD", iptr, 18, 0);
3259         } else {
3260                 /*
3261                  * If this is not embedded, the bootstrap mailbox area
3262                  * MUST contain a SGE pointer to a larger area for the
3263                  * non-embedded mailbox command.
3264                  * mp will point to the actual mailbox command which
3265                  * should be copied into the non-embedded area.
3266                  */
3267                 nonembed = 1;
3268                 mb4->un.varSLIConfig.be.sge_cnt = 1;
3269                 mb4->un.varSLIConfig.be.payload_length = mp->size;
3270                 iptr = (uint32_t *)&mb4->un.varSLIConfig.be.un_hdr.hdr_req;
3271                 *iptr++ = (uint32_t)PADDR_LO(mp->phys);
3272                 *iptr++ = (uint32_t)PADDR_HI(mp->phys);
3273                 *iptr = mp->size;
3274 
3275                 BE_SWAP32_BUFFER(mp->virt, mp->size);
3276 
3277                 EMLXS_MPDATA_SYNC(mp->dma_handle, 0, mp->size,
3278                     DDI_DMA_SYNC_FORDEV);
3279 
3280                 iptr = (uint32_t *)hba->sli.sli4.bootstrapmb.virt;
3281                 BE_SWAP32_BCOPY((uint8_t *)mb, (uint8_t *)iptr,
3282                     MAILBOX_CMD_SLI4_BSIZE);
3283 
3284                 EMLXS_MPDATA_SYNC(hba->sli.sli4.bootstrapmb.dma_handle, 0,
3285                     EMLXS_BOOTSTRAP_MB_SIZE + MBOX_EXTENSION_SIZE,
3286                     DDI_DMA_SYNC_FORDEV);
3287 
3288                 emlxs_data_dump(port, "MBOX EXT", iptr, 12, 0);
3289                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mbox_detail_msg,
3290                     "Extension Addr %p %p", mp->phys,
3291                     (uint32_t *)((uint8_t *)mp->virt));
3292                 iptr = (uint32_t *)((uint8_t *)mp->virt);
3293                 emlxs_data_dump(port, "EXT AREA", (uint32_t *)mp->virt, 24, 0);
3294         }
3295 
3296 
3297         /* NOTE: tmo is in 10ms ticks */
3298         if (!emlxs_issue_bootstrap_mb(hba, tmo)) {
3299                 return (MBX_TIMEOUT);
3300         }
3301 
3302         if ((mb->mbxCommand != MBX_SLI_CONFIG) ||
3303             (mb4->un.varSLIConfig.be.embedded)) {
3304                 EMLXS_MPDATA_SYNC(hba->sli.sli4.bootstrapmb.dma_handle, 0,
3305                     MAILBOX_CMD_SLI4_BSIZE, DDI_DMA_SYNC_FORKERNEL);
3306 
3307                 iptr = (uint32_t *)hba->sli.sli4.bootstrapmb.virt;
3308                 BE_SWAP32_BCOPY((uint8_t *)iptr, (uint8_t *)mb,
3309                     MAILBOX_CMD_SLI4_BSIZE);
3310 
3311                 emlxs_data_dump(port, "MBOX CMP", iptr, 18, 0);
3312 
3313         } else {
3314                 EMLXS_MPDATA_SYNC(hba->sli.sli4.bootstrapmb.dma_handle, 0,
3315                     EMLXS_BOOTSTRAP_MB_SIZE + MBOX_EXTENSION_SIZE,
3316                     DDI_DMA_SYNC_FORKERNEL);
3317 
3318                 EMLXS_MPDATA_SYNC(mp->dma_handle, 0, mp->size,
3319                     DDI_DMA_SYNC_FORKERNEL);
3320 
3321                 BE_SWAP32_BUFFER(mp->virt, mp->size);
3322 
3323                 iptr = (uint32_t *)hba->sli.sli4.bootstrapmb.virt;
3324                 BE_SWAP32_BCOPY((uint8_t *)iptr, (uint8_t *)mb,
3325                     MAILBOX_CMD_SLI4_BSIZE);
3326 
3327                 emlxs_data_dump(port, "MBOX CMP", iptr, 12, 0);
3328                 iptr = (uint32_t *)((uint8_t *)mp->virt);
3329                 emlxs_data_dump(port, "EXT AREA", (uint32_t *)iptr, 24, 0);
3330         }
3331 
3332 #ifdef FMA_SUPPORT
3333         if (nonembed && mp) {
3334                 if (emlxs_fm_check_dma_handle(hba, mp->dma_handle)
3335                     != DDI_FM_OK) {
3336                         EMLXS_MSGF(EMLXS_CONTEXT,
3337                             &emlxs_invalid_dma_handle_msg,
3338                             "sli4_issue_bootstrap: mp_hdl=%p",
3339                             mp->dma_handle);
3340                         return (MBXERR_DMA_ERROR);
3341                 }
3342         }
3343 
3344         if (emlxs_fm_check_dma_handle(hba,
3345             hba->sli.sli4.bootstrapmb.dma_handle)
3346             != DDI_FM_OK) {
3347                 EMLXS_MSGF(EMLXS_CONTEXT,
3348                     &emlxs_invalid_dma_handle_msg,
3349                     "sli4_issue_bootstrap: hdl=%p",
3350                     hba->sli.sli4.bootstrapmb.dma_handle);
3351                 return (MBXERR_DMA_ERROR);
3352         }
3353 #endif
3354 
3355         return (MBX_SUCCESS);
3356 
3357 } /* emlxs_sli4_issue_bootstrap() */
3358 
3359 
3360 /*ARGSUSED*/
3361 static uint32_t
3362 emlxs_sli4_issue_mbox_cmd(emlxs_hba_t *hba, MAILBOXQ *mbq, int32_t flag,
3363     uint32_t tmo)
3364 {
3365         emlxs_port_t    *port;
3366         MAILBOX4        *mb4;
3367         MAILBOX         *mb;
3368         mbox_rsp_hdr_t  *hdr_rsp;
3369         MATCHMAP        *mp;
3370         uint32_t        *iptr;
3371         uint32_t        rc;
3372         uint32_t        i;
3373         uint32_t        tmo_local;
3374 
3375         if (!mbq->port) {
3376                 mbq->port = &PPORT;
3377         }
3378 
3379         port = (emlxs_port_t *)mbq->port;
3380 
3381         mb4 = (MAILBOX4 *)mbq;
3382         mb = (MAILBOX *)mbq;
3383 
3384         mb->mbxStatus = MBX_SUCCESS;
3385         rc = MBX_SUCCESS;
3386 
3387         /* Check for minimum timeouts */
3388         switch (mb->mbxCommand) {
3389         /* Mailbox commands that erase/write flash */
3390         case MBX_DOWN_LOAD:
3391         case MBX_UPDATE_CFG:
3392         case MBX_LOAD_AREA:
3393         case MBX_LOAD_EXP_ROM:
3394         case MBX_WRITE_NV:
3395         case MBX_FLASH_WR_ULA:
3396         case MBX_DEL_LD_ENTRY:
3397         case MBX_LOAD_SM:
3398         case MBX_DUMP_MEMORY:
3399         case MBX_WRITE_VPARMS:
3400         case MBX_ACCESS_VDATA:
3401                 if (tmo < 300) {
3402                         tmo = 300;
3403                 }
3404                 break;
3405 
3406         case MBX_SLI_CONFIG: {
3407                 mbox_req_hdr_t *hdr_req;
3408 
3409                 hdr_req = (mbox_req_hdr_t *)
3410                     &mb4->un.varSLIConfig.be.un_hdr.hdr_req;
3411 
3412                 if (hdr_req->subsystem == IOCTL_SUBSYSTEM_COMMON) {
3413                         switch (hdr_req->opcode) {
3414                         case COMMON_OPCODE_WRITE_OBJ:
3415                         case COMMON_OPCODE_READ_OBJ:
3416                         case COMMON_OPCODE_READ_OBJ_LIST:
3417                         case COMMON_OPCODE_DELETE_OBJ:
3418                         case COMMON_OPCODE_SET_BOOT_CFG:
3419                         case COMMON_OPCODE_GET_PROFILE_CFG:
3420                         case COMMON_OPCODE_SET_PROFILE_CFG:
3421                         case COMMON_OPCODE_GET_PROFILE_LIST:
3422                         case COMMON_OPCODE_SET_ACTIVE_PROFILE:
3423                         case COMMON_OPCODE_GET_PROFILE_CAPS:
3424                         case COMMON_OPCODE_GET_MR_PROFILE_CAPS:
3425                         case COMMON_OPCODE_SET_MR_PROFILE_CAPS:
3426                         case COMMON_OPCODE_SET_FACTORY_PROFILE_CFG:
3427                         case COMMON_OPCODE_SEND_ACTIVATION:
3428                         case COMMON_OPCODE_RESET_LICENSES:
3429                         case COMMON_OPCODE_SET_PHYSICAL_LINK_CFG_V1:
3430                         case COMMON_OPCODE_GET_VPD_DATA:
3431                                 if (tmo < 300) {
3432                                         tmo = 300;
3433                                 }
3434                                 break;
3435                         default:
3436                                 if (tmo < 30) {
3437                                         tmo = 30;
3438                                 }
3439                         }
3440                 } else if (hdr_req->subsystem == IOCTL_SUBSYSTEM_FCOE) {
3441                         switch (hdr_req->opcode) {
3442                         case FCOE_OPCODE_SET_FCLINK_SETTINGS:
3443                                 if (tmo < 300) {
3444                                         tmo = 300;
3445                                 }
3446                                 break;
3447                         default:
3448                                 if (tmo < 30) {
3449                                         tmo = 30;
3450                                 }
3451                         }
3452                 } else {
3453                         if (tmo < 30) {
3454                                 tmo = 30;
3455                         }
3456                 }
3457 
3458                 /*
3459                  * Also: VENDOR_MANAGE_FFV  (0x13, 0x02) (not currently used)
3460                  */
3461 
3462                 break;
3463         }
3464         default:
3465                 if (tmo < 30) {
3466                         tmo = 30;
3467                 }
3468                 break;
3469         }
3470 
3471         /* Convert tmo seconds to 10 millisecond tics */
3472         tmo_local = tmo * 100;
3473 
3474         mutex_enter(&EMLXS_PORT_LOCK);
3475 
3476         /* Adjust wait flag */
3477         if (flag != MBX_NOWAIT) {
3478                 if (hba->sli.sli4.flag & EMLXS_SLI4_INTR_ENABLED) {
3479                         flag = MBX_SLEEP;
3480                 } else {
3481                         flag = MBX_POLL;
3482                 }
3483         } else {
3484                 /* Must have interrupts enabled to perform MBX_NOWAIT */
3485                 if (!(hba->sli.sli4.flag & EMLXS_SLI4_INTR_ENABLED)) {
3486 
3487                         mb->mbxStatus = MBX_HARDWARE_ERROR;
3488                         mutex_exit(&EMLXS_PORT_LOCK);
3489 
3490                         EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mbox_detail_msg,
3491                             "Interrupts disabled. %s failed.",
3492                             emlxs_mb_cmd_xlate(mb->mbxCommand));
3493 
3494                         return (MBX_HARDWARE_ERROR);
3495                 }
3496         }
3497 
3498         /* Check for hardware error ; special case SLI_CONFIG */
3499         if ((hba->flag & FC_HARDWARE_ERROR) &&
3500             ! ((mb4->mbxCommand == MBX_SLI_CONFIG) &&
3501             (mb4->un.varSLIConfig.be.un_hdr.hdr_req.opcode ==
3502             COMMON_OPCODE_RESET))) {
3503                 mb->mbxStatus = MBX_HARDWARE_ERROR;
3504 
3505                 mutex_exit(&EMLXS_PORT_LOCK);
3506 
3507                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mbox_detail_msg,
3508                     "Hardware error reported. %s failed. status=%x mb=%p",
3509                     emlxs_mb_cmd_xlate(mb->mbxCommand), mb->mbxStatus, mb);
3510 
3511                 return (MBX_HARDWARE_ERROR);
3512         }
3513 
3514         if (hba->mbox_queue_flag) {
3515                 /* If we are not polling, then queue it for later */
3516                 if (flag == MBX_NOWAIT) {
3517                         EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mbox_detail_msg,
3518                             "Busy.      %s: mb=%p NoWait.",
3519                             emlxs_mb_cmd_xlate(mb->mbxCommand), mb);
3520 
3521                         emlxs_mb_put(hba, mbq);
3522 
3523                         HBASTATS.MboxBusy++;
3524 
3525                         mutex_exit(&EMLXS_PORT_LOCK);
3526 
3527                         return (MBX_BUSY);
3528                 }
3529 
3530                 while (hba->mbox_queue_flag) {
3531                         mutex_exit(&EMLXS_PORT_LOCK);
3532 
3533                         if (tmo_local-- == 0) {
3534                                 EMLXS_MSGF(EMLXS_CONTEXT,
3535                                     &emlxs_mbox_event_msg,
3536                                     "Timeout.   %s: mb=%p tmo=%d Waiting.",
3537                                     emlxs_mb_cmd_xlate(mb->mbxCommand), mb,
3538                                     tmo);
3539 
3540                                 /* Non-lethalStatus mailbox timeout */
3541                                 /* Does not indicate a hardware error */
3542                                 mb->mbxStatus = MBX_TIMEOUT;
3543                                 return (MBX_TIMEOUT);
3544                         }
3545 
3546                         BUSYWAIT_MS(10);
3547                         mutex_enter(&EMLXS_PORT_LOCK);
3548 
3549                         /* Check for hardware error ; special case SLI_CONFIG */
3550                         if ((hba->flag & FC_HARDWARE_ERROR) &&
3551                             ! ((mb4->mbxCommand == MBX_SLI_CONFIG) &&
3552                             (mb4->un.varSLIConfig.be.un_hdr.hdr_req.opcode ==
3553                             COMMON_OPCODE_RESET))) {
3554                                 mb->mbxStatus = MBX_HARDWARE_ERROR;
3555 
3556                                 mutex_exit(&EMLXS_PORT_LOCK);
3557 
3558                                 EMLXS_MSGF(EMLXS_CONTEXT,
3559                                     &emlxs_mbox_detail_msg,
3560                                     "Hardware error reported. %s failed. "
3561                                     "status=%x mb=%p",
3562                                     emlxs_mb_cmd_xlate(mb->mbxCommand),
3563                                     mb->mbxStatus, mb);
3564 
3565                                 return (MBX_HARDWARE_ERROR);
3566                         }
3567                 }
3568         }
3569 
3570         /* Initialize mailbox area */
3571         emlxs_mb_init(hba, mbq, flag, tmo);
3572 
3573         if (mb->mbxCommand == MBX_DOWN_LINK) {
3574                 hba->sli.sli4.flag |= EMLXS_SLI4_DOWN_LINK;
3575         }
3576 
3577         mutex_exit(&EMLXS_PORT_LOCK);
3578         switch (flag) {
3579 
3580         case MBX_NOWAIT:
3581                 if (mb->mbxCommand != MBX_HEARTBEAT) {
3582                         if (mb->mbxCommand != MBX_DOWN_LOAD
3583                             /* && mb->mbxCommand != MBX_DUMP_MEMORY */) {
3584                                 EMLXS_MSGF(EMLXS_CONTEXT,
3585                                     &emlxs_mbox_detail_msg,
3586                                     "Sending.   %s: mb=%p NoWait. embedded %d",
3587                                     emlxs_mb_cmd_xlate(mb->mbxCommand), mb,
3588                                     ((mb->mbxCommand != MBX_SLI_CONFIG) ? 1 :
3589                                     (mb4->un.varSLIConfig.be.embedded)));
3590                         }
3591                 }
3592 
3593                 iptr = hba->sli.sli4.mq.addr.virt;
3594                 iptr += (hba->sli.sli4.mq.host_index * MAILBOX_CMD_SLI4_WSIZE);
3595                 hba->sli.sli4.mq.host_index++;
3596                 if (hba->sli.sli4.mq.host_index >= hba->sli.sli4.mq.max_index) {
3597                         hba->sli.sli4.mq.host_index = 0;
3598                 }
3599 
3600                 if (mbq->bp) {
3601                         EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mbox_detail_msg,
3602                             "BDE virt %p phys %p size x%x",
3603                             ((MATCHMAP *)mbq->bp)->virt,
3604                             ((MATCHMAP *)mbq->bp)->phys,
3605                             ((MATCHMAP *)mbq->bp)->size);
3606                         emlxs_data_dump(port, "DATA",
3607                             (uint32_t *)(((MATCHMAP *)mbq->bp)->virt), 30, 0);
3608                 }
3609                 rc = emlxs_sli4_issue_mq(port, (MAILBOX4 *)iptr, mb, tmo_local);
3610                 break;
3611 
3612         case MBX_POLL:
3613                 if (mb->mbxCommand != MBX_DOWN_LOAD
3614                     /* && mb->mbxCommand != MBX_DUMP_MEMORY */) {
3615                         EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mbox_detail_msg,
3616                             "Sending.   %s: mb=%p Poll. embedded %d",
3617                             emlxs_mb_cmd_xlate(mb->mbxCommand), mb,
3618                             ((mb->mbxCommand != MBX_SLI_CONFIG) ? 1 :
3619                             (mb4->un.varSLIConfig.be.embedded)));
3620                 }
3621 
3622                 rc = emlxs_sli4_issue_bootstrap(hba, mb, tmo_local);
3623 
3624                 /* Clean up the mailbox area */
3625                 if (rc == MBX_TIMEOUT) {
3626                         EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mbox_detail_msg,
3627                             "Timeout.   %s: mb=%p tmo=%x Poll. embedded %d",
3628                             emlxs_mb_cmd_xlate(mb->mbxCommand), mb, tmo,
3629                             ((mb->mbxCommand != MBX_SLI_CONFIG) ? 1 :
3630                             (mb4->un.varSLIConfig.be.embedded)));
3631 
3632                         hba->flag |= FC_MBOX_TIMEOUT;
3633                         EMLXS_STATE_CHANGE(hba, FC_ERROR);
3634                         emlxs_mb_fini(hba, NULL, MBX_TIMEOUT);
3635 
3636                 } else {
3637                         if (mb->mbxCommand != MBX_DOWN_LOAD
3638                             /* && mb->mbxCommand != MBX_DUMP_MEMORY */) {
3639                                 EMLXS_MSGF(EMLXS_CONTEXT,
3640                                     &emlxs_mbox_detail_msg,
3641                                     "Completed.   %s: mb=%p status=%x Poll. "
3642                                     "embedded %d",
3643                                     emlxs_mb_cmd_xlate(mb->mbxCommand), mb, rc,
3644                                     ((mb->mbxCommand != MBX_SLI_CONFIG) ? 1 :
3645                                     (mb4->un.varSLIConfig.be.embedded)));
3646                         }
3647 
3648                         /* Process the result */
3649                         if (!(mbq->flag & MBQ_PASSTHRU)) {
3650                                 if (mbq->mbox_cmpl) {
3651                                         (void) (mbq->mbox_cmpl)(hba, mbq);
3652                                 }
3653                         }
3654 
3655                         emlxs_mb_fini(hba, NULL, mb->mbxStatus);
3656                 }
3657 
3658                 mp = (MATCHMAP *)mbq->nonembed;
3659                 if (mp) {
3660                         hdr_rsp = (mbox_rsp_hdr_t *)mp->virt;
3661                         if (hdr_rsp->status) {
3662                                 EMLXS_MSGF(EMLXS_CONTEXT,
3663                                     &emlxs_mbox_detail_msg,
3664                                     "%s: MBX_NONEMBED_ERROR: 0x%x, 0x%x",
3665                                     emlxs_mb_cmd_xlate(mb->mbxCommand),
3666                                     hdr_rsp->status, hdr_rsp->extra_status);
3667 
3668                                 mb->mbxStatus = MBX_NONEMBED_ERROR;
3669                         }
3670                 }
3671                 rc = mb->mbxStatus;
3672 
3673                 /* Attempt to send pending mailboxes */
3674                 mbq = (MAILBOXQ *)emlxs_mb_get(hba);
3675                 if (mbq) {
3676                         /* Attempt to send pending mailboxes */
3677                         i =  emlxs_sli4_issue_mbox_cmd(hba, mbq, MBX_NOWAIT, 0);
3678                         if ((i != MBX_BUSY) && (i != MBX_SUCCESS)) {
3679                                 emlxs_mem_put(hba, MEM_MBOX, (void *)mbq);
3680                         }
3681                 }
3682                 break;
3683 
3684         case MBX_SLEEP:
3685                 if (mb->mbxCommand != MBX_DOWN_LOAD
3686                     /* && mb->mbxCommand != MBX_DUMP_MEMORY */) {
3687                         EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mbox_detail_msg,
3688                             "Sending.   %s: mb=%p Sleep. embedded %d",
3689                             emlxs_mb_cmd_xlate(mb->mbxCommand), mb,
3690                             ((mb->mbxCommand != MBX_SLI_CONFIG) ? 1 :
3691                             (mb4->un.varSLIConfig.be.embedded)));
3692                 }
3693 
3694                 iptr = hba->sli.sli4.mq.addr.virt;
3695                 iptr += (hba->sli.sli4.mq.host_index * MAILBOX_CMD_SLI4_WSIZE);
3696                 hba->sli.sli4.mq.host_index++;
3697                 if (hba->sli.sli4.mq.host_index >= hba->sli.sli4.mq.max_index) {
3698                         hba->sli.sli4.mq.host_index = 0;
3699                 }
3700 
3701                 rc = emlxs_sli4_issue_mq(port, (MAILBOX4 *)iptr, mb, tmo_local);
3702 
3703                 if (rc != MBX_SUCCESS) {
3704                         break;
3705                 }
3706 
3707                 /* Wait for completion */
3708                 /* The driver clock is timing the mailbox. */
3709 
3710                 mutex_enter(&EMLXS_MBOX_LOCK);
3711                 while (!(mbq->flag & MBQ_COMPLETED)) {
3712                         cv_wait(&EMLXS_MBOX_CV, &EMLXS_MBOX_LOCK);
3713                 }
3714                 mutex_exit(&EMLXS_MBOX_LOCK);
3715 
3716                 mp = (MATCHMAP *)mbq->nonembed;
3717                 if (mp) {
3718                         hdr_rsp = (mbox_rsp_hdr_t *)mp->virt;
3719                         if (hdr_rsp->status) {
3720                                 EMLXS_MSGF(EMLXS_CONTEXT,
3721                                     &emlxs_mbox_detail_msg,
3722                                     "%s: MBX_NONEMBED_ERROR: 0x%x, 0x%x",
3723                                     emlxs_mb_cmd_xlate(mb->mbxCommand),
3724                                     hdr_rsp->status, hdr_rsp->extra_status);
3725 
3726                                 mb->mbxStatus = MBX_NONEMBED_ERROR;
3727                         }
3728                 }
3729                 rc = mb->mbxStatus;
3730 
3731                 if (rc == MBX_TIMEOUT) {
3732                         EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mbox_detail_msg,
3733                             "Timeout.   %s: mb=%p tmo=%x Sleep. embedded %d",
3734                             emlxs_mb_cmd_xlate(mb->mbxCommand), mb, tmo,
3735                             ((mb->mbxCommand != MBX_SLI_CONFIG) ? 1 :
3736                             (mb4->un.varSLIConfig.be.embedded)));
3737                 } else {
3738                         if (mb->mbxCommand != MBX_DOWN_LOAD
3739                             /* && mb->mbxCommand != MBX_DUMP_MEMORY */) {
3740                                 EMLXS_MSGF(EMLXS_CONTEXT,
3741                                     &emlxs_mbox_detail_msg,
3742                                     "Completed.   %s: mb=%p status=%x Sleep. "
3743                                     "embedded %d",
3744                                     emlxs_mb_cmd_xlate(mb->mbxCommand), mb, rc,
3745                                     ((mb->mbxCommand != MBX_SLI_CONFIG) ? 1 :
3746                                     (mb4->un.varSLIConfig.be.embedded)));
3747                         }
3748                 }
3749                 break;
3750         }
3751 
3752         return (rc);
3753 
3754 } /* emlxs_sli4_issue_mbox_cmd() */
3755 
3756 
3757 
3758 /*ARGSUSED*/
3759 static uint32_t
3760 emlxs_sli4_issue_mbox_cmd4quiesce(emlxs_hba_t *hba, MAILBOXQ *mbq, int32_t flag,
3761     uint32_t tmo)
3762 {
3763         emlxs_port_t    *port = &PPORT;
3764         MAILBOX         *mb;
3765         mbox_rsp_hdr_t  *hdr_rsp;
3766         MATCHMAP        *mp;
3767         uint32_t        rc;
3768         uint32_t        tmo_local;
3769 
3770         mb = (MAILBOX *)mbq;
3771 
3772         mb->mbxStatus = MBX_SUCCESS;
3773         rc = MBX_SUCCESS;
3774 
3775         if (tmo < 30) {
3776                 tmo = 30;
3777         }
3778 
3779         /* Convert tmo seconds to 10 millisecond tics */
3780         tmo_local = tmo * 100;
3781 
3782         flag = MBX_POLL;
3783 
3784         /* Check for hardware error */
3785         if (hba->flag & FC_HARDWARE_ERROR) {
3786                 mb->mbxStatus = MBX_HARDWARE_ERROR;
3787                 return (MBX_HARDWARE_ERROR);
3788         }
3789 
3790         /* Initialize mailbox area */
3791         emlxs_mb_init(hba, mbq, flag, tmo);
3792 
3793         switch (flag) {
3794 
3795         case MBX_POLL:
3796 
3797                 rc = emlxs_sli4_issue_bootstrap(hba, mb, tmo_local);
3798 
3799                 /* Clean up the mailbox area */
3800                 if (rc == MBX_TIMEOUT) {
3801                         hba->flag |= FC_MBOX_TIMEOUT;
3802                         EMLXS_STATE_CHANGE(hba, FC_ERROR);
3803                         emlxs_mb_fini(hba, NULL, MBX_TIMEOUT);
3804 
3805                 } else {
3806                         /* Process the result */
3807                         if (!(mbq->flag & MBQ_PASSTHRU)) {
3808                                 if (mbq->mbox_cmpl) {
3809                                         (void) (mbq->mbox_cmpl)(hba, mbq);
3810                                 }
3811                         }
3812 
3813                         emlxs_mb_fini(hba, NULL, mb->mbxStatus);
3814                 }
3815 
3816                 mp = (MATCHMAP *)mbq->nonembed;
3817                 if (mp) {
3818                         hdr_rsp = (mbox_rsp_hdr_t *)mp->virt;
3819                         if (hdr_rsp->status) {
3820                                 EMLXS_MSGF(EMLXS_CONTEXT,
3821                                     &emlxs_mbox_detail_msg,
3822                                     "%s: MBX_NONEMBED_ERROR: 0x%x, 0x%x",
3823                                     emlxs_mb_cmd_xlate(mb->mbxCommand),
3824                                     hdr_rsp->status, hdr_rsp->extra_status);
3825 
3826                                 mb->mbxStatus = MBX_NONEMBED_ERROR;
3827                         }
3828                 }
3829                 rc = mb->mbxStatus;
3830 
3831                 break;
3832         }
3833 
3834         return (rc);
3835 
3836 } /* emlxs_sli4_issue_mbox_cmd4quiesce() */
3837 
3838 
3839 
3840 #ifdef SFCT_SUPPORT
3841 /*ARGSUSED*/
3842 extern uint32_t
3843 emlxs_sli4_prep_fct_iocb(emlxs_port_t *port, emlxs_buf_t *cmd_sbp, int channel)
3844 {
3845         emlxs_hba_t *hba = HBA;
3846         emlxs_config_t *cfg = &CFG;
3847         fct_cmd_t *fct_cmd;
3848         stmf_data_buf_t *dbuf;
3849         scsi_task_t *fct_task;
3850         fc_packet_t *pkt;
3851         CHANNEL *cp;
3852         XRIobj_t *xrip;
3853         emlxs_node_t *ndlp;
3854         IOCBQ *iocbq;
3855         IOCB *iocb;
3856         emlxs_wqe_t *wqe;
3857         ULP_SGE64 stage_sge;
3858         ULP_SGE64 *sge;
3859         RPIobj_t *rpip;
3860         int32_t sge_size;
3861         uint64_t sge_addr;
3862         uint32_t did;
3863         uint32_t timeout;
3864 
3865         ddi_dma_cookie_t *cp_cmd;
3866 
3867         pkt = PRIV2PKT(cmd_sbp);
3868 
3869         cp = (CHANNEL *)cmd_sbp->channel;
3870 
3871         iocbq = &cmd_sbp->iocbq;
3872         iocb = &iocbq->iocb;
3873 
3874         did = cmd_sbp->did;
3875         if (iocb->ULPCOMMAND == CMD_ABORT_XRI_CX) {
3876 
3877                 ndlp = cmd_sbp->node;
3878                 rpip = EMLXS_NODE_TO_RPI(port, ndlp);
3879 
3880                 if (!rpip) {
3881                         /* Use the fabric rpi */
3882                         rpip = port->vpip->fabric_rpip;
3883                 }
3884 
3885                 /* Next allocate an Exchange for this command */
3886                 xrip = emlxs_sli4_alloc_xri(port, cmd_sbp, rpip,
3887                     EMLXS_XRI_SOL_BLS_TYPE);
3888 
3889                 if (!xrip) {
3890                         EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_trans_msg,
3891                             "Adapter Busy. Unable to allocate exchange. "
3892                             "did=0x%x", did);
3893 
3894                         return (FC_TRAN_BUSY);
3895                 }
3896 
3897                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
3898                     "FCT Abort Request: xri=%d iotag=%d sbp=%p rxid=%x",
3899                     xrip->XRI, xrip->iotag, cmd_sbp, pkt->pkt_cmd_fhdr.rx_id);
3900 
3901                 cmd_sbp->xrip = xrip;
3902 
3903                 cp->ulpSendCmd++;
3904 
3905                 /* Initalize iocbq */
3906                 iocbq->port = (void *)port;
3907                 iocbq->node = (void *)ndlp;
3908                 iocbq->channel = (void *)cp;
3909 
3910                 /*
3911                  * Don't give the abort priority, we want the IOCB
3912                  * we are aborting to be processed first.
3913                  */
3914                 iocbq->flag |= IOCB_SPECIAL;
3915 
3916                 wqe = &iocbq->wqe;
3917                 bzero((void *)wqe, sizeof (emlxs_wqe_t));
3918 
3919                 wqe = &iocbq->wqe;
3920                 wqe->un.Abort.Criteria = ABORT_XRI_TAG;
3921                 wqe->RequestTag = xrip->iotag;
3922                 wqe->AbortTag = pkt->pkt_cmd_fhdr.rx_id;
3923                 wqe->Command = CMD_ABORT_XRI_CX;
3924                 wqe->Class = CLASS3;
3925                 wqe->CQId = 0xffff;
3926                 wqe->CmdType = WQE_TYPE_ABORT;
3927 
3928                 if (hba->state >= FC_LINK_UP) {
3929                         wqe->un.Abort.IA = 0;
3930                 } else {
3931                         wqe->un.Abort.IA = 1;
3932                 }
3933 
3934                 /* Set the pkt timer */
3935                 cmd_sbp->ticks = hba->timer_tics + pkt->pkt_timeout +
3936                     ((pkt->pkt_timeout > 0xff) ? 0 : 10);
3937 
3938                 return (IOERR_SUCCESS);
3939 
3940         } else if (iocb->ULPCOMMAND == CMD_FCP_TRSP64_CX) {
3941 
3942                 timeout = pkt->pkt_timeout;
3943                 ndlp = cmd_sbp->node;
3944                 if (!ndlp) {
3945                         EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_trans_msg,
3946                             "Unable to find rpi. did=0x%x", did);
3947 
3948                         emlxs_set_pkt_state(cmd_sbp, IOSTAT_LOCAL_REJECT,
3949                             IOERR_INVALID_RPI, 0);
3950                         return (0xff);
3951                 }
3952 
3953                 cp->ulpSendCmd++;
3954 
3955                 /* Initalize iocbq */
3956                 iocbq->port = (void *)port;
3957                 iocbq->node = (void *)ndlp;
3958                 iocbq->channel = (void *)cp;
3959 
3960                 wqe = &iocbq->wqe;
3961                 bzero((void *)wqe, sizeof (emlxs_wqe_t));
3962 
3963                 xrip = emlxs_sli4_register_xri(port, cmd_sbp,
3964                     pkt->pkt_cmd_fhdr.rx_id, did);
3965 
3966                 if (!xrip) {
3967                         EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_trans_msg,
3968                             "Unable to register xri %x. did=0x%x",
3969                             pkt->pkt_cmd_fhdr.rx_id, did);
3970 
3971                         emlxs_set_pkt_state(cmd_sbp, IOSTAT_LOCAL_REJECT,
3972                             IOERR_NO_XRI, 0);
3973                         return (0xff);
3974                 }
3975 
3976                 cmd_sbp->iotag = xrip->iotag;
3977                 cmd_sbp->channel = cp;
3978 
3979 #if (EMLXS_MODREV >= EMLXS_MODREV3)
3980                 cp_cmd = pkt->pkt_cmd_cookie;
3981 #else
3982                 cp_cmd  = &pkt->pkt_cmd_cookie;
3983 #endif  /* >= EMLXS_MODREV3 */
3984 
3985                 sge_size = pkt->pkt_cmdlen;
3986                 /* Make size a multiple of 4 */
3987                 if (sge_size & 3) {
3988                         sge_size = (sge_size + 3) & 0xfffffffc;
3989                 }
3990                 sge_addr = cp_cmd->dmac_laddress;
3991                 sge = xrip->SGList.virt;
3992 
3993                 stage_sge.addrHigh = PADDR_HI(sge_addr);
3994                 stage_sge.addrLow = PADDR_LO(sge_addr);
3995                 stage_sge.length = sge_size;
3996                 stage_sge.offset = 0;
3997                 stage_sge.type = 0;
3998                 stage_sge.last = 1;
3999 
4000                 /* Copy staged SGE into SGL */
4001                 BE_SWAP32_BCOPY((uint8_t *)&stage_sge,
4002                     (uint8_t *)sge, sizeof (ULP_SGE64));
4003 
4004                 /* Words  0-3 */
4005                 wqe->un.FcpCmd.Payload.addrHigh = stage_sge.addrHigh;
4006                 wqe->un.FcpCmd.Payload.addrLow = stage_sge.addrLow;
4007                 wqe->un.FcpCmd.Payload.tus.f.bdeSize = sge_size;
4008                 wqe->un.FcpCmd.PayloadLength = sge_size;
4009 
4010                 /*  Word  6 */
4011                 wqe->ContextTag = ndlp->nlp_Rpi;
4012                 wqe->XRITag = xrip->XRI;
4013 
4014                 /*  Word  7 */
4015                 wqe->Command  = iocb->ULPCOMMAND;
4016                 wqe->Class = cmd_sbp->class;
4017                 wqe->ContextType = WQE_RPI_CONTEXT;
4018                 wqe->Timer = ((timeout > 0xff) ? 0 : timeout);
4019 
4020                 /*  Word  8 */
4021                 wqe->AbortTag = 0;
4022 
4023                 /*  Word  9 */
4024                 wqe->RequestTag = xrip->iotag;
4025                 wqe->OXId = (uint16_t)xrip->rx_id;
4026 
4027                 /*  Word  10 */
4028                 if (xrip->flag & EMLXS_XRI_BUSY) {
4029                         wqe->XC = 1;
4030                 }
4031 
4032                 if (!(hba->sli.sli4.param.PHWQ)) {
4033                         wqe->QOSd = 1;
4034                         wqe->DBDE = 1; /* Data type for BDE 0 */
4035                 }
4036 
4037                 /*  Word  11 */
4038                 wqe->CmdType = WQE_TYPE_TRSP;
4039                 wqe->CQId = (uint16_t)0xffff;  /* default CQ for response */
4040 
4041                 /* Set the pkt timer */
4042                 cmd_sbp->ticks = hba->timer_tics + timeout +
4043                     ((timeout > 0xff) ? 0 : 10);
4044 
4045                 if (pkt->pkt_cmdlen) {
4046                         EMLXS_MPDATA_SYNC(pkt->pkt_cmd_dma, 0, pkt->pkt_cmdlen,
4047                             DDI_DMA_SYNC_FORDEV);
4048                 }
4049 
4050                 return (IOERR_SUCCESS);
4051         }
4052 
4053         fct_cmd = cmd_sbp->fct_cmd;
4054         did = fct_cmd->cmd_rportid;
4055         dbuf = cmd_sbp->fct_buf;
4056         fct_task = (scsi_task_t *)fct_cmd->cmd_specific;
4057         ndlp = *(emlxs_node_t **)fct_cmd->cmd_rp->rp_fca_private;
4058         if (!ndlp) {
4059                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_trans_msg,
4060                     "Unable to find rpi. did=0x%x", did);
4061 
4062                 emlxs_set_pkt_state(cmd_sbp, IOSTAT_LOCAL_REJECT,
4063                     IOERR_INVALID_RPI, 0);
4064                 return (0xff);
4065         }
4066 
4067 
4068         /* Initalize iocbq */
4069         iocbq->port = (void *) port;
4070         iocbq->node = (void *)ndlp;
4071         iocbq->channel = (void *) cp;
4072 
4073         wqe = &iocbq->wqe;
4074         bzero((void *)wqe, sizeof (emlxs_wqe_t));
4075 
4076         xrip = cmd_sbp->xrip;
4077         if (!xrip) {
4078                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_trans_msg,
4079                     "Unable to find xri. did=0x%x", did);
4080 
4081                 emlxs_set_pkt_state(cmd_sbp, IOSTAT_LOCAL_REJECT,
4082                     IOERR_NO_XRI, 0);
4083                 return (0xff);
4084         }
4085 
4086         if (emlxs_sli4_register_xri(port, cmd_sbp,
4087             xrip->XRI, ndlp->nlp_DID) == NULL) {
4088                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_trans_msg,
4089                     "Unable to register xri. did=0x%x", did);
4090 
4091                 emlxs_set_pkt_state(cmd_sbp, IOSTAT_LOCAL_REJECT,
4092                     IOERR_NO_XRI, 0);
4093                 return (0xff);
4094         }
4095         cmd_sbp->iotag = xrip->iotag;
4096         cmd_sbp->channel = cp;
4097 
4098         if (cfg[CFG_TIMEOUT_ENABLE].current) {
4099                 timeout =
4100                     ((2 * hba->fc_ratov) < 60) ? 60 : (2 * hba->fc_ratov);
4101         } else {
4102                 timeout = 0x80000000;
4103         }
4104         cmd_sbp->ticks =
4105             hba->timer_tics + timeout + ((timeout > 0xff) ? 0 : 10);
4106 
4107 
4108         iocb->ULPCT = 0;
4109         if (fct_task->task_flags & TF_WRITE_DATA) {
4110                 iocb->ULPCOMMAND = CMD_FCP_TRECEIVE64_CX;
4111                 wqe->CmdType = WQE_TYPE_TRECEIVE;            /* Word 11 */
4112 
4113         } else { /* TF_READ_DATA */
4114 
4115                 iocb->ULPCOMMAND = CMD_FCP_TSEND64_CX;
4116                 wqe->CmdType = WQE_TYPE_TSEND;                       /* Word 11 */
4117 
4118                 if ((dbuf->db_data_size >=
4119                     fct_task->task_expected_xfer_length)) {
4120                         /* enable auto-rsp AP feature */
4121                         wqe->AR = 0x1;
4122                         iocb->ULPCT = 0x1; /* for cmpl */
4123                 }
4124         }
4125 
4126         (void) emlxs_sli4_fct_bde_setup(port, cmd_sbp);
4127 
4128         /*  Word  6 */
4129         wqe->ContextTag = ndlp->nlp_Rpi;
4130         wqe->XRITag = xrip->XRI;
4131 
4132         /*  Word  7 */
4133         wqe->Command  = iocb->ULPCOMMAND;
4134         wqe->Class = cmd_sbp->class;
4135         wqe->ContextType = WQE_RPI_CONTEXT;
4136         wqe->Timer = ((timeout > 0xff) ? 0 : timeout);
4137         wqe->PU = 1;
4138 
4139         /*  Word  8 */
4140         wqe->AbortTag = 0;
4141 
4142         /*  Word  9 */
4143         wqe->RequestTag = xrip->iotag;
4144         wqe->OXId = (uint16_t)fct_cmd->cmd_oxid;
4145 
4146         /*  Word  10 */
4147         if (xrip->flag & EMLXS_XRI_BUSY) {
4148                 wqe->XC = 1;
4149         }
4150 
4151         if (!(hba->sli.sli4.param.PHWQ)) {
4152                 wqe->QOSd = 1;
4153                 wqe->DBDE = 1; /* Data type for BDE 0 */
4154         }
4155 
4156         /*  Word  11 */
4157         wqe->CQId = (uint16_t)0xffff;  /* default CQ for response */
4158 
4159         /*  Word  12 */
4160         wqe->CmdSpecific = dbuf->db_data_size;
4161 
4162         return (IOERR_SUCCESS);
4163 
4164 } /* emlxs_sli4_prep_fct_iocb() */
4165 #endif /* SFCT_SUPPORT */
4166 
4167 
4168 /*ARGSUSED*/
4169 extern uint32_t
4170 emlxs_sli4_prep_fcp_iocb(emlxs_port_t *port, emlxs_buf_t *sbp, int channel)
4171 {
4172         emlxs_hba_t *hba = HBA;
4173         fc_packet_t *pkt;
4174         CHANNEL *cp;
4175         RPIobj_t *rpip;
4176         XRIobj_t *xrip;
4177         emlxs_wqe_t *wqe;
4178         IOCBQ *iocbq;
4179         IOCB *iocb;
4180         NODELIST *node;
4181         uint16_t iotag;
4182         uint32_t did;
4183         off_t offset;
4184 
4185         pkt = PRIV2PKT(sbp);
4186         did = LE_SWAP24_LO(pkt->pkt_cmd_fhdr.d_id);
4187         cp = &hba->chan[channel];
4188 
4189         iocbq = &sbp->iocbq;
4190         iocbq->channel = (void *) cp;
4191         iocbq->port = (void *) port;
4192 
4193         wqe = &iocbq->wqe;
4194         iocb = &iocbq->iocb;
4195         bzero((void *)wqe, sizeof (emlxs_wqe_t));
4196         bzero((void *)iocb, sizeof (IOCB));
4197 
4198         /* Find target node object */
4199         node = (NODELIST *)iocbq->node;
4200         rpip = EMLXS_NODE_TO_RPI(port, node);
4201 
4202         if (!rpip) {
4203                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_trans_msg,
4204                     "Unable to find rpi. did=0x%x", did);
4205 
4206                 emlxs_set_pkt_state(sbp, IOSTAT_LOCAL_REJECT,
4207                     IOERR_INVALID_RPI, 0);
4208                 return (0xff);
4209         }
4210 
4211         sbp->channel = cp;
4212         /* Next allocate an Exchange for this command */
4213         xrip = emlxs_sli4_alloc_xri(port, sbp, rpip,
4214             EMLXS_XRI_SOL_FCP_TYPE);
4215 
4216         if (!xrip) {
4217                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_trans_msg,
4218                     "Adapter Busy. Unable to allocate exchange. did=0x%x", did);
4219 
4220                 return (FC_TRAN_BUSY);
4221         }
4222         sbp->bmp = NULL;
4223         iotag = sbp->iotag;
4224 
4225 #ifdef DEBUG_FASTPATH
4226         EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
4227             "FCP: Prep xri=%d iotag=%d oxid=%x rpi=%d",
4228             xrip->XRI, xrip->iotag, xrip->rx_id, rpip->RPI);
4229 #endif /* DEBUG_FASTPATH */
4230 
4231         /* Indicate this is a FCP cmd */
4232         iocbq->flag |= IOCB_FCP_CMD;
4233 
4234         if (emlxs_sli4_bde_setup(port, sbp)) {
4235                 emlxs_sli4_free_xri(port, sbp, xrip, 1);
4236                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_trans_msg,
4237                     "Adapter Busy. Unable to setup SGE. did=0x%x", did);
4238 
4239                 return (FC_TRAN_BUSY);
4240         }
4241 
4242         /* DEBUG */
4243 #ifdef DEBUG_FCP
4244         EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
4245             "FCP: SGLaddr virt %p phys %p size %d", xrip->SGList.virt,
4246             xrip->SGList.phys, pkt->pkt_datalen);
4247         emlxs_data_dump(port, "FCP: SGL", (uint32_t *)xrip->SGList.virt, 20, 0);
4248         EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
4249             "FCP: CMD virt %p len %d:%d:%d",
4250             pkt->pkt_cmd, pkt->pkt_cmdlen, pkt->pkt_rsplen, pkt->pkt_datalen);
4251         emlxs_data_dump(port, "FCP: CMD", (uint32_t *)pkt->pkt_cmd, 10, 0);
4252 #endif /* DEBUG_FCP */
4253 
4254         offset = (off_t)((uint64_t)((unsigned long)
4255             xrip->SGList.virt) -
4256             (uint64_t)((unsigned long)
4257             hba->sli.sli4.slim2.virt));
4258 
4259         EMLXS_MPDATA_SYNC(xrip->SGList.dma_handle, offset,
4260             xrip->SGList.size, DDI_DMA_SYNC_FORDEV);
4261 
4262         /* if device is FCP-2 device, set the following bit */
4263         /* that says to run the FC-TAPE protocol. */
4264         if (node->nlp_fcp_info & NLP_FCP_2_DEVICE) {
4265                 wqe->ERP = 1;
4266         }
4267 
4268         if (pkt->pkt_datalen == 0) {
4269                 iocb->ULPCOMMAND = CMD_FCP_ICMND64_CR;
4270                 wqe->Command = CMD_FCP_ICMND64_CR;
4271                 wqe->CmdType = WQE_TYPE_FCP_DATA_IN;
4272         } else if (pkt->pkt_tran_type == FC_PKT_FCP_READ) {
4273                 iocb->ULPCOMMAND = CMD_FCP_IREAD64_CR;
4274                 wqe->Command = CMD_FCP_IREAD64_CR;
4275                 wqe->CmdType = WQE_TYPE_FCP_DATA_IN;
4276                 wqe->PU = PARM_XFER_CHECK;
4277         } else {
4278                 iocb->ULPCOMMAND = CMD_FCP_IWRITE64_CR;
4279                 wqe->Command = CMD_FCP_IWRITE64_CR;
4280                 wqe->CmdType = WQE_TYPE_FCP_DATA_OUT;
4281         }
4282         wqe->un.FcpCmd.TotalTransferCount = pkt->pkt_datalen;
4283 
4284         if (!(hba->sli.sli4.param.PHWQ)) {
4285                 wqe->DBDE = 1; /* Data type for BDE 0 */
4286         }
4287         wqe->ContextTag = rpip->RPI;
4288         wqe->ContextType = WQE_RPI_CONTEXT;
4289         wqe->XRITag = xrip->XRI;
4290         wqe->Timer =
4291             ((pkt->pkt_timeout > 0xff) ? 0 : pkt->pkt_timeout);
4292 
4293         if (pkt->pkt_cmd_fhdr.f_ctl & F_CTL_CHAINED_SEQ) {
4294                 wqe->CCPE = 1;
4295                 wqe->CCP = pkt->pkt_cmd_fhdr.rsvd;
4296         }
4297 
4298         switch (FC_TRAN_CLASS(pkt->pkt_tran_flags)) {
4299         case FC_TRAN_CLASS2:
4300                 wqe->Class = CLASS2;
4301                 break;
4302         case FC_TRAN_CLASS3:
4303         default:
4304                 wqe->Class = CLASS3;
4305                 break;
4306         }
4307         sbp->class = wqe->Class;
4308         wqe->RequestTag = iotag;
4309         wqe->CQId = (uint16_t)0xffff;  /* default CQ for response */
4310 
4311         return (FC_SUCCESS);
4312 } /* emlxs_sli4_prep_fcp_iocb() */
4313 
4314 
4315 /*ARGSUSED*/
4316 static uint32_t
4317 emlxs_sli4_prep_ip_iocb(emlxs_port_t *port, emlxs_buf_t *sbp)
4318 {
4319         return (FC_TRAN_BUSY);
4320 
4321 } /* emlxs_sli4_prep_ip_iocb() */
4322 
4323 
4324 /*ARGSUSED*/
4325 static uint32_t
4326 emlxs_sli4_prep_els_iocb(emlxs_port_t *port, emlxs_buf_t *sbp)
4327 {
4328         emlxs_hba_t *hba = HBA;
4329         fc_packet_t *pkt;
4330         IOCBQ *iocbq;
4331         IOCB *iocb;
4332         emlxs_wqe_t *wqe;
4333         FCFIobj_t *fcfp;
4334         RPIobj_t *reserved_rpip = NULL;
4335         RPIobj_t *rpip = NULL;
4336         XRIobj_t *xrip;
4337         CHANNEL *cp;
4338         uint32_t did;
4339         uint32_t cmd;
4340         ULP_SGE64 stage_sge;
4341         ULP_SGE64 *sge;
4342         ddi_dma_cookie_t *cp_cmd;
4343         ddi_dma_cookie_t *cp_resp;
4344         emlxs_node_t *node;
4345         off_t offset;
4346 
4347         pkt = PRIV2PKT(sbp);
4348         did = LE_SWAP24_LO(pkt->pkt_cmd_fhdr.d_id);
4349 
4350         iocbq = &sbp->iocbq;
4351         wqe = &iocbq->wqe;
4352         iocb = &iocbq->iocb;
4353         bzero((void *)wqe, sizeof (emlxs_wqe_t));
4354         bzero((void *)iocb, sizeof (IOCB));
4355         cp = &hba->chan[hba->channel_els];
4356 
4357         /* Initalize iocbq */
4358         iocbq->port = (void *) port;
4359         iocbq->channel = (void *) cp;
4360 
4361         sbp->channel = cp;
4362         sbp->bmp = NULL;
4363 
4364 #if (EMLXS_MODREV >= EMLXS_MODREV3)
4365         cp_cmd = pkt->pkt_cmd_cookie;
4366         cp_resp = pkt->pkt_resp_cookie;
4367 #else
4368         cp_cmd  = &pkt->pkt_cmd_cookie;
4369         cp_resp = &pkt->pkt_resp_cookie;
4370 #endif  /* >= EMLXS_MODREV3 */
4371 
4372         /* CMD payload */
4373         sge = &stage_sge;
4374         sge->addrHigh = PADDR_HI(cp_cmd->dmac_laddress);
4375         sge->addrLow = PADDR_LO(cp_cmd->dmac_laddress);
4376         sge->length = pkt->pkt_cmdlen;
4377         sge->offset = 0;
4378         sge->type = 0;
4379 
4380         cmd = *((uint32_t *)pkt->pkt_cmd);
4381         cmd &= ELS_CMD_MASK;
4382 
4383         /* Initalize iocb */
4384         if (pkt->pkt_tran_type == FC_PKT_OUTBOUND) {
4385                 /* ELS Response */
4386 
4387                 sbp->xrip = 0;
4388                 xrip = emlxs_sli4_register_xri(port, sbp,
4389                     pkt->pkt_cmd_fhdr.rx_id, did);
4390 
4391                 if (!xrip) {
4392                         EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_trans_failed_msg,
4393                             "Unable to find XRI. rxid=%x",
4394                             pkt->pkt_cmd_fhdr.rx_id);
4395 
4396                         emlxs_set_pkt_state(sbp, IOSTAT_LOCAL_REJECT,
4397                             IOERR_NO_XRI, 0);
4398                         return (0xff);
4399                 }
4400 
4401                 rpip = xrip->rpip;
4402 
4403                 if (!rpip) {
4404                         /* This means that we had a node registered */
4405                         /* when the unsol request came in but the node */
4406                         /* has since been unregistered. */
4407                         EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_trans_failed_msg,
4408                             "Unable to find RPI. rxid=%x",
4409                             pkt->pkt_cmd_fhdr.rx_id);
4410 
4411                         emlxs_set_pkt_state(sbp, IOSTAT_LOCAL_REJECT,
4412                             IOERR_INVALID_RPI, 0);
4413                         return (0xff);
4414                 }
4415 
4416                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
4417                     "ELS: Prep xri=%d iotag=%d oxid=%x rpi=%d",
4418                     xrip->XRI, xrip->iotag, xrip->rx_id, rpip->RPI);
4419 
4420                 iocb->ULPCOMMAND = CMD_XMIT_ELS_RSP64_CX;
4421                 wqe->Command = CMD_XMIT_ELS_RSP64_CX;
4422                 wqe->CmdType = WQE_TYPE_GEN;
4423                 if (!(hba->sli.sli4.param.PHWQ)) {
4424                         wqe->DBDE = 1; /* Data type for BDE 0 */
4425                 }
4426 
4427                 wqe->un.ElsRsp.Payload.addrHigh = sge->addrHigh;
4428                 wqe->un.ElsRsp.Payload.addrLow = sge->addrLow;
4429                 wqe->un.ElsRsp.Payload.tus.f.bdeSize = pkt->pkt_cmdlen;
4430                 wqe->un.ElsCmd.PayloadLength = pkt->pkt_cmdlen;
4431 
4432                 wqe->un.ElsRsp.RemoteId = did;
4433                 wqe->PU = 0x3;
4434                 wqe->OXId = xrip->rx_id;
4435 
4436                 sge->last = 1;
4437                 /* Now sge is fully staged */
4438 
4439                 sge = xrip->SGList.virt;
4440                 BE_SWAP32_BCOPY((uint8_t *)&stage_sge, (uint8_t *)sge,
4441                     sizeof (ULP_SGE64));
4442 
4443                 if (rpip->RPI == FABRIC_RPI) {
4444                         wqe->ContextTag = port->vpip->VPI;
4445                         wqe->ContextType = WQE_VPI_CONTEXT;
4446                 } else {
4447                         wqe->ContextTag = rpip->RPI;
4448                         wqe->ContextType = WQE_RPI_CONTEXT;
4449                 }
4450 
4451                 if ((cmd == ELS_CMD_ACC) && (sbp->ucmd == ELS_CMD_FLOGI)) {
4452                         wqe->un.ElsCmd.SP = 1;
4453                         wqe->un.ElsCmd.LocalId = 0xFFFFFE;
4454                 }
4455 
4456         } else {
4457                 /* ELS Request */
4458 
4459                 fcfp = port->vpip->vfip->fcfp;
4460                 node = (emlxs_node_t *)iocbq->node;
4461                 rpip = EMLXS_NODE_TO_RPI(port, node);
4462 
4463                 if (!rpip) {
4464                         /* Use the fabric rpi */
4465                         rpip = port->vpip->fabric_rpip;
4466                 }
4467 
4468                 /* Next allocate an Exchange for this command */
4469                 xrip = emlxs_sli4_alloc_xri(port, sbp, rpip,
4470                     EMLXS_XRI_SOL_ELS_TYPE);
4471 
4472                 if (!xrip) {
4473                         EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_trans_msg,
4474                             "Adapter Busy. Unable to allocate exchange. "
4475                             "did=0x%x", did);
4476 
4477                         return (FC_TRAN_BUSY);
4478                 }
4479 
4480                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
4481                     "ELS: Prep xri=%d iotag=%d rpi=%d",
4482                     xrip->XRI, xrip->iotag, rpip->RPI);
4483 
4484                 iocb->ULPCOMMAND = CMD_ELS_REQUEST64_CR;
4485                 wqe->Command = CMD_ELS_REQUEST64_CR;
4486                 wqe->CmdType = WQE_TYPE_ELS;
4487                 if (!(hba->sli.sli4.param.PHWQ)) {
4488                         wqe->DBDE = 1; /* Data type for BDE 0 */
4489                 }
4490 
4491                 wqe->un.ElsCmd.Payload.addrHigh = sge->addrHigh;
4492                 wqe->un.ElsCmd.Payload.addrLow = sge->addrLow;
4493                 wqe->un.ElsCmd.Payload.tus.f.bdeSize = pkt->pkt_cmdlen;
4494 
4495                 wqe->un.ElsCmd.RemoteId = did;
4496                 wqe->Timer = ((pkt->pkt_timeout > 0xff) ? 0 : pkt->pkt_timeout);
4497 
4498                 /* setup for rsp */
4499                 iocb->un.elsreq64.remoteID = (did == BCAST_DID) ? 0 : did;
4500                 iocb->ULPPU = 1;     /* Wd4 is relative offset */
4501 
4502                 sge->last = 0;
4503 
4504                 sge = xrip->SGList.virt;
4505                 BE_SWAP32_BCOPY((uint8_t *)&stage_sge, (uint8_t *)sge,
4506                     sizeof (ULP_SGE64));
4507 
4508                 wqe->un.ElsCmd.PayloadLength =
4509                     pkt->pkt_cmdlen; /* Byte offset of rsp data */
4510 
4511                 /* RSP payload */
4512                 sge = &stage_sge;
4513                 sge->addrHigh = PADDR_HI(cp_resp->dmac_laddress);
4514                 sge->addrLow = PADDR_LO(cp_resp->dmac_laddress);
4515                 sge->length = pkt->pkt_rsplen;
4516                 sge->offset = 0;
4517                 sge->last = 1;
4518                 /* Now sge is fully staged */
4519 
4520                 sge = xrip->SGList.virt;
4521                 sge++;
4522                 BE_SWAP32_BCOPY((uint8_t *)&stage_sge, (uint8_t *)sge,
4523                     sizeof (ULP_SGE64));
4524 #ifdef DEBUG_ELS
4525                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
4526                     "ELS: SGLaddr virt %p phys %p",
4527                     xrip->SGList.virt, xrip->SGList.phys);
4528                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
4529                     "ELS: PAYLOAD virt %p phys %p",
4530                     pkt->pkt_cmd, cp_cmd->dmac_laddress);
4531                 emlxs_data_dump(port, "ELS: SGL", (uint32_t *)xrip->SGList.virt,
4532                     12, 0);
4533 #endif /* DEBUG_ELS */
4534 
4535                 switch (cmd) {
4536                 case ELS_CMD_FLOGI:
4537                         wqe->un.ElsCmd.SP = 1;
4538 
4539                         if ((hba->sli_intf & SLI_INTF_IF_TYPE_MASK) ==
4540                             SLI_INTF_IF_TYPE_0) {
4541                                 wqe->ContextTag = fcfp->FCFI;
4542                                 wqe->ContextType = WQE_FCFI_CONTEXT;
4543                         } else {
4544                                 wqe->ContextTag = port->vpip->VPI;
4545                                 wqe->ContextType = WQE_VPI_CONTEXT;
4546                         }
4547 
4548                         if (hba->flag & FC_FIP_SUPPORTED) {
4549                                 wqe->CmdType |= WQE_TYPE_MASK_FIP;
4550                         }
4551 
4552                         if (hba->topology == TOPOLOGY_LOOP) {
4553                                 wqe->un.ElsCmd.LocalId = port->did;
4554                         }
4555 
4556                         wqe->ELSId = WQE_ELSID_FLOGI;
4557                         break;
4558                 case ELS_CMD_FDISC:
4559                         wqe->un.ElsCmd.SP = 1;
4560                         wqe->ContextTag = port->vpip->VPI;
4561                         wqe->ContextType = WQE_VPI_CONTEXT;
4562 
4563                         if (hba->flag & FC_FIP_SUPPORTED) {
4564                                 wqe->CmdType |= WQE_TYPE_MASK_FIP;
4565                         }
4566 
4567                         wqe->ELSId = WQE_ELSID_FDISC;
4568                         break;
4569                 case ELS_CMD_LOGO:
4570                         if ((did == FABRIC_DID) &&
4571                             (hba->flag & FC_FIP_SUPPORTED)) {
4572                                 wqe->CmdType |= WQE_TYPE_MASK_FIP;
4573                         }
4574 
4575                         wqe->ContextTag = port->vpip->VPI;
4576                         wqe->ContextType = WQE_VPI_CONTEXT;
4577                         wqe->ELSId = WQE_ELSID_LOGO;
4578                         break;
4579                 case ELS_CMD_PLOGI:
4580                         if (rpip->RPI == FABRIC_RPI) {
4581                                 if (hba->flag & FC_PT_TO_PT) {
4582                                         wqe->un.ElsCmd.SP = 1;
4583                                         wqe->un.ElsCmd.LocalId = port->did;
4584                                 }
4585 
4586                                 wqe->ContextTag = port->vpip->VPI;
4587                                 wqe->ContextType = WQE_VPI_CONTEXT;
4588                         } else {
4589                                 wqe->ContextTag = rpip->RPI;
4590                                 wqe->ContextType = WQE_RPI_CONTEXT;
4591                         }
4592 
4593                         wqe->ELSId = WQE_ELSID_PLOGI;
4594                         break;
4595                 default:
4596                         if (rpip->RPI == FABRIC_RPI) {
4597                                 wqe->ContextTag = port->vpip->VPI;
4598                                 wqe->ContextType = WQE_VPI_CONTEXT;
4599                         } else {
4600                                 wqe->ContextTag = rpip->RPI;
4601                                 wqe->ContextType = WQE_RPI_CONTEXT;
4602                         }
4603 
4604                         wqe->ELSId = WQE_ELSID_CMD;
4605                         break;
4606                 }
4607 
4608 #ifdef SFCT_SUPPORT
4609                 /* This allows fct to abort the request */
4610                 if (sbp->fct_cmd) {
4611                         sbp->fct_cmd->cmd_oxid = xrip->XRI;
4612                         sbp->fct_cmd->cmd_rxid = 0xFFFF;
4613                 }
4614 #endif /* SFCT_SUPPORT */
4615         }
4616 
4617         if (wqe->ContextType == WQE_VPI_CONTEXT) {
4618                 reserved_rpip = emlxs_rpi_reserve_notify(port, did, xrip);
4619 
4620                 if (!reserved_rpip) {
4621                         EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_trans_failed_msg,
4622                             "Unable to alloc reserved RPI. rxid=%x. Rejecting.",
4623                             pkt->pkt_cmd_fhdr.rx_id);
4624 
4625                         emlxs_set_pkt_state(sbp, IOSTAT_LOCAL_REJECT,
4626                             IOERR_INVALID_RPI, 0);
4627                         return (0xff);
4628                 }
4629 
4630                 /* Store the reserved rpi */
4631                 if (wqe->Command == CMD_ELS_REQUEST64_CR) {
4632                         wqe->OXId = reserved_rpip->RPI;
4633                 } else {
4634                         wqe->CmdSpecific = reserved_rpip->RPI;
4635                 }
4636         }
4637 
4638         offset = (off_t)((uint64_t)((unsigned long)
4639             xrip->SGList.virt) -
4640             (uint64_t)((unsigned long)
4641             hba->sli.sli4.slim2.virt));
4642 
4643         EMLXS_MPDATA_SYNC(xrip->SGList.dma_handle, offset,
4644             xrip->SGList.size, DDI_DMA_SYNC_FORDEV);
4645 
4646         if (pkt->pkt_cmd_fhdr.f_ctl & F_CTL_CHAINED_SEQ) {
4647                 wqe->CCPE = 1;
4648                 wqe->CCP = pkt->pkt_cmd_fhdr.rsvd;
4649         }
4650 
4651         switch (FC_TRAN_CLASS(pkt->pkt_tran_flags)) {
4652         case FC_TRAN_CLASS2:
4653                 wqe->Class = CLASS2;
4654                 break;
4655         case FC_TRAN_CLASS3:
4656         default:
4657                 wqe->Class = CLASS3;
4658                 break;
4659         }
4660         sbp->class = wqe->Class;
4661         wqe->XRITag = xrip->XRI;
4662         wqe->RequestTag = xrip->iotag;
4663         wqe->CQId = (uint16_t)0xffff;  /* default CQ for response */
4664         return (FC_SUCCESS);
4665 
4666 } /* emlxs_sli4_prep_els_iocb() */
4667 
4668 
4669 /*ARGSUSED*/
4670 static uint32_t
4671 emlxs_sli4_prep_ct_iocb(emlxs_port_t *port, emlxs_buf_t *sbp)
4672 {
4673         emlxs_hba_t *hba = HBA;
4674         fc_packet_t *pkt;
4675         IOCBQ *iocbq;
4676         IOCB *iocb;
4677         emlxs_wqe_t *wqe;
4678         NODELIST *node = NULL;
4679         CHANNEL *cp;
4680         RPIobj_t *rpip;
4681         XRIobj_t *xrip;
4682         uint32_t did;
4683         off_t offset;
4684 
4685         pkt = PRIV2PKT(sbp);
4686         did = LE_SWAP24_LO(pkt->pkt_cmd_fhdr.d_id);
4687 
4688         iocbq = &sbp->iocbq;
4689         wqe = &iocbq->wqe;
4690         iocb = &iocbq->iocb;
4691         bzero((void *)wqe, sizeof (emlxs_wqe_t));
4692         bzero((void *)iocb, sizeof (IOCB));
4693 
4694         cp = &hba->chan[hba->channel_ct];
4695 
4696         iocbq->port = (void *) port;
4697         iocbq->channel = (void *) cp;
4698 
4699         sbp->bmp = NULL;
4700         sbp->channel = cp;
4701 
4702         /* Initalize wqe */
4703         if (pkt->pkt_tran_type == FC_PKT_OUTBOUND) {
4704                 /* CT Response */
4705 
4706                 sbp->xrip = 0;
4707                 xrip = emlxs_sli4_register_xri(port, sbp,
4708                     pkt->pkt_cmd_fhdr.rx_id, did);
4709 
4710                 if (!xrip) {
4711                         EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_trans_failed_msg,
4712                             "Unable to find XRI. rxid=%x",
4713                             pkt->pkt_cmd_fhdr.rx_id);
4714 
4715                         emlxs_set_pkt_state(sbp, IOSTAT_LOCAL_REJECT,
4716                             IOERR_NO_XRI, 0);
4717                         return (0xff);
4718                 }
4719 
4720                 rpip = xrip->rpip;
4721 
4722                 if (!rpip) {
4723                         /* This means that we had a node registered */
4724                         /* when the unsol request came in but the node */
4725                         /* has since been unregistered. */
4726                         EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_trans_failed_msg,
4727                             "Unable to find RPI. rxid=%x",
4728                             pkt->pkt_cmd_fhdr.rx_id);
4729 
4730                         emlxs_set_pkt_state(sbp, IOSTAT_LOCAL_REJECT,
4731                             IOERR_INVALID_RPI, 0);
4732                         return (0xff);
4733                 }
4734 
4735                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
4736                     "CT: Prep xri=%d iotag=%d oxid=%x rpi=%d",
4737                     xrip->XRI, xrip->iotag, xrip->rx_id, rpip->RPI);
4738 
4739                 if (emlxs_sli4_bde_setup(port, sbp)) {
4740                         EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_trans_msg,
4741                             "Adapter Busy. Unable to setup SGE. did=0x%x", did);
4742 
4743                         return (FC_TRAN_BUSY);
4744                 }
4745 
4746                 if (!(hba->model_info.chip & EMLXS_BE_CHIPS)) {
4747                         wqe->un.XmitSeq.Rsvd0 = 0; /* Word3 now reserved */
4748                 }
4749 
4750                 if (!(hba->sli.sli4.param.PHWQ)) {
4751                         wqe->DBDE = 1; /* Data type for BDE 0 */
4752                 }
4753 
4754                 iocb->ULPCOMMAND = CMD_XMIT_SEQUENCE64_CR;
4755                 wqe->CmdType = WQE_TYPE_GEN;
4756                 wqe->Command = CMD_XMIT_SEQUENCE64_CR;
4757                 wqe->LenLoc = 2;
4758 
4759                 if (((SLI_CT_REQUEST *) pkt->pkt_cmd)->CommandResponse.bits.
4760                     CmdRsp == (LE_SWAP16(SLI_CT_LOOPBACK))) {
4761                         wqe->un.XmitSeq.xo = 1;
4762                 } else {
4763                         wqe->un.XmitSeq.xo = 0;
4764                 }
4765 
4766                 if (pkt->pkt_cmd_fhdr.f_ctl & F_CTL_LAST_SEQ) {
4767                         wqe->un.XmitSeq.ls = 1;
4768                 }
4769 
4770                 if (pkt->pkt_cmd_fhdr.f_ctl & F_CTL_SEQ_INITIATIVE) {
4771                         wqe->un.XmitSeq.si = 1;
4772                 }
4773 
4774                 wqe->un.XmitSeq.DFctl  = pkt->pkt_cmd_fhdr.df_ctl;
4775                 wqe->un.XmitSeq.Rctl  = pkt->pkt_cmd_fhdr.r_ctl;
4776                 wqe->un.XmitSeq.Type  = pkt->pkt_cmd_fhdr.type;
4777                 wqe->OXId = xrip->rx_id;
4778                 wqe->XC = 0; /* xri_tag is a new exchange */
4779                 wqe->CmdSpecific = wqe->un.GenReq.Payload.tus.f.bdeSize;
4780 
4781         } else {
4782                 /* CT Request */
4783 
4784                 node = (emlxs_node_t *)iocbq->node;
4785                 rpip = EMLXS_NODE_TO_RPI(port, node);
4786 
4787                 if (!rpip) {
4788                         EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_trans_failed_msg,
4789                             "Unable to find rpi. did=0x%x rpi=%d",
4790                             did, node->nlp_Rpi);
4791 
4792                         emlxs_set_pkt_state(sbp, IOSTAT_LOCAL_REJECT,
4793                             IOERR_INVALID_RPI, 0);
4794                         return (0xff);
4795                 }
4796 
4797                 /* Next allocate an Exchange for this command */
4798                 xrip = emlxs_sli4_alloc_xri(port, sbp, rpip,
4799                     EMLXS_XRI_SOL_CT_TYPE);
4800 
4801                 if (!xrip) {
4802                         EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_trans_msg,
4803                             "Adapter Busy. Unable to allocate exchange. "
4804                             "did=0x%x", did);
4805 
4806                         return (FC_TRAN_BUSY);
4807                 }
4808 
4809                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
4810                     "CT: Prep xri=%d iotag=%d oxid=%x rpi=%d",
4811                     xrip->XRI, xrip->iotag, xrip->rx_id, rpip->RPI);
4812 
4813                 if (emlxs_sli4_bde_setup(port, sbp)) {
4814                         EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_trans_msg,
4815                             "Adapter Busy. Unable to setup SGE. did=0x%x", did);
4816 
4817                         emlxs_sli4_free_xri(port, sbp, xrip, 1);
4818                         return (FC_TRAN_BUSY);
4819                 }
4820 
4821                 if (!(hba->sli.sli4.param.PHWQ)) {
4822                         wqe->DBDE = 1; /* Data type for BDE 0 */
4823                 }
4824 
4825                 iocb->ULPCOMMAND = CMD_GEN_REQUEST64_CR;
4826                 wqe->CmdType = WQE_TYPE_GEN;
4827                 wqe->Command = CMD_GEN_REQUEST64_CR;
4828                 wqe->un.GenReq.la = 1;
4829                 wqe->un.GenReq.DFctl  = pkt->pkt_cmd_fhdr.df_ctl;
4830                 wqe->un.GenReq.Rctl  = pkt->pkt_cmd_fhdr.r_ctl;
4831                 wqe->un.GenReq.Type  = pkt->pkt_cmd_fhdr.type;
4832 
4833 #ifdef DEBUG_CT
4834                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
4835                     "CT: SGLaddr virt %p phys %p", xrip->SGList.virt,
4836                     xrip->SGList.phys);
4837                 emlxs_data_dump(port, "CT: SGL", (uint32_t *)xrip->SGList.virt,
4838                     12, 0);
4839                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
4840                     "CT: CMD virt %p len %d:%d",
4841                     pkt->pkt_cmd, pkt->pkt_cmdlen, pkt->pkt_rsplen);
4842                 emlxs_data_dump(port, "CT: DATA", (uint32_t *)pkt->pkt_cmd,
4843                     20, 0);
4844 #endif /* DEBUG_CT */
4845 
4846 #ifdef SFCT_SUPPORT
4847                 /* This allows fct to abort the request */
4848                 if (sbp->fct_cmd) {
4849                         sbp->fct_cmd->cmd_oxid = xrip->XRI;
4850                         sbp->fct_cmd->cmd_rxid = 0xFFFF;
4851                 }
4852 #endif /* SFCT_SUPPORT */
4853         }
4854 
4855         /* Setup for rsp */
4856         iocb->un.genreq64.w5.hcsw.Rctl  = pkt->pkt_cmd_fhdr.r_ctl;
4857         iocb->un.genreq64.w5.hcsw.Type  = pkt->pkt_cmd_fhdr.type;
4858         iocb->un.genreq64.w5.hcsw.Dfctl  = pkt->pkt_cmd_fhdr.df_ctl;
4859         iocb->ULPPU = 1;     /* Wd4 is relative offset */
4860 
4861         offset = (off_t)((uint64_t)((unsigned long)
4862             xrip->SGList.virt) -
4863             (uint64_t)((unsigned long)
4864             hba->sli.sli4.slim2.virt));
4865 
4866         EMLXS_MPDATA_SYNC(xrip->SGList.dma_handle, offset,
4867             xrip->SGList.size, DDI_DMA_SYNC_FORDEV);
4868 
4869         wqe->ContextTag = rpip->RPI;
4870         wqe->ContextType = WQE_RPI_CONTEXT;
4871         wqe->XRITag = xrip->XRI;
4872         wqe->Timer = ((pkt->pkt_timeout > 0xff) ? 0 : pkt->pkt_timeout);
4873 
4874         if (pkt->pkt_cmd_fhdr.f_ctl & F_CTL_CHAINED_SEQ) {
4875                 wqe->CCPE = 1;
4876                 wqe->CCP = pkt->pkt_cmd_fhdr.rsvd;
4877         }
4878 
4879         switch (FC_TRAN_CLASS(pkt->pkt_tran_flags)) {
4880         case FC_TRAN_CLASS2:
4881                 wqe->Class = CLASS2;
4882                 break;
4883         case FC_TRAN_CLASS3:
4884         default:
4885                 wqe->Class = CLASS3;
4886                 break;
4887         }
4888         sbp->class = wqe->Class;
4889         wqe->RequestTag = xrip->iotag;
4890         wqe->CQId = (uint16_t)0xffff;  /* default CQ for response */
4891         return (FC_SUCCESS);
4892 
4893 } /* emlxs_sli4_prep_ct_iocb() */
4894 
4895 
4896 /*ARGSUSED*/
4897 static int
4898 emlxs_sli4_read_eq(emlxs_hba_t *hba, EQ_DESC_t *eq)
4899 {
4900         uint32_t *ptr;
4901         EQE_u eqe;
4902         int rc = 0;
4903         off_t offset;
4904 
4905         mutex_enter(&EMLXS_PORT_LOCK);
4906 
4907         ptr = eq->addr.virt;
4908         ptr += eq->host_index;
4909 
4910         offset = (off_t)((uint64_t)((unsigned long)
4911             eq->addr.virt) -
4912             (uint64_t)((unsigned long)
4913             hba->sli.sli4.slim2.virt));
4914 
4915         EMLXS_MPDATA_SYNC(eq->addr.dma_handle, offset,
4916             4096, DDI_DMA_SYNC_FORKERNEL);
4917 
4918         eqe.word = *ptr;
4919         eqe.word = BE_SWAP32(eqe.word);
4920 
4921         if (eqe.word & EQE_VALID) {
4922                 rc = 1;
4923         }
4924 
4925         mutex_exit(&EMLXS_PORT_LOCK);
4926 
4927         return (rc);
4928 
4929 } /* emlxs_sli4_read_eq */
4930 
4931 
4932 static void
4933 emlxs_sli4_poll_intr(emlxs_hba_t *hba)
4934 {
4935         int rc = 0;
4936         int i;
4937         char arg[] = {0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7};
4938 
4939         /* Check attention bits once and process if required */
4940 
4941         for (i = 0; i < hba->intr_count; i++) {
4942                 rc = emlxs_sli4_read_eq(hba, &hba->sli.sli4.eq[i]);
4943                 if (rc == 1) {
4944                         break;
4945                 }
4946         }
4947 
4948         if (rc != 1) {
4949                 return;
4950         }
4951 
4952         (void) emlxs_sli4_msi_intr((char *)hba,
4953             (char *)(unsigned long)arg[i]);
4954 
4955         return;
4956 
4957 } /* emlxs_sli4_poll_intr() */
4958 
4959 
4960 /*ARGSUSED*/
4961 static void
4962 emlxs_sli4_process_async_event(emlxs_hba_t *hba, CQE_ASYNC_t *cqe)
4963 {
4964         emlxs_port_t *port = &PPORT;
4965         uint8_t status;
4966 
4967         /* Save the event tag */
4968         if (hba->link_event_tag == cqe->un.link.event_tag) {
4969                 HBASTATS.LinkMultiEvent++;
4970         } else if (hba->link_event_tag + 1 < cqe->un.link.event_tag) {
4971                 HBASTATS.LinkMultiEvent++;
4972         }
4973         hba->link_event_tag = cqe->un.link.event_tag;
4974 
4975         switch (cqe->event_code) {
4976         case ASYNC_EVENT_CODE_FCOE_LINK_STATE:
4977                 HBASTATS.LinkEvent++;
4978 
4979                 switch (cqe->un.link.link_status) {
4980                 case ASYNC_EVENT_PHYS_LINK_UP:
4981                         EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
4982                             "Link Async Event: PHYS_LINK_UP. val=%d "
4983                             "type=%x event=%x",
4984                             cqe->valid, cqe->event_type, HBASTATS.LinkEvent);
4985                         break;
4986 
4987                 case ASYNC_EVENT_LOGICAL_LINK_UP:
4988                         EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
4989                             "Link Async Event: LOGICAL_LINK_UP. val=%d "
4990                             "type=%x event=%x",
4991                             cqe->valid, cqe->event_type, HBASTATS.LinkEvent);
4992 
4993                         emlxs_sli4_handle_fcoe_link_event(hba, cqe);
4994                         break;
4995 
4996                 case ASYNC_EVENT_PHYS_LINK_DOWN:
4997                         EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
4998                             "Link Async Event: PHYS_LINK_DOWN. val=%d "
4999                             "type=%x event=%x",
5000                             cqe->valid, cqe->event_type, HBASTATS.LinkEvent);
5001 
5002                         emlxs_sli4_handle_fcoe_link_event(hba, cqe);
5003                         break;
5004 
5005                 case ASYNC_EVENT_LOGICAL_LINK_DOWN:
5006                         EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
5007                             "Link Async Event: LOGICAL_LINK_DOWN. val=%d "
5008                             "type=%x event=%x",
5009                             cqe->valid, cqe->event_type, HBASTATS.LinkEvent);
5010 
5011                         emlxs_sli4_handle_fcoe_link_event(hba, cqe);
5012                         break;
5013                 default:
5014                         EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
5015                             "Link Async Event: Unknown link status=%d event=%x",
5016                             cqe->un.link.link_status, HBASTATS.LinkEvent);
5017                         break;
5018                 }
5019                 break;
5020         case ASYNC_EVENT_CODE_FCOE_FIP:
5021                 switch (cqe->un.fcoe.evt_type) {
5022                 case ASYNC_EVENT_NEW_FCF_DISC:
5023                         EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
5024                             "FIP Async Event: FCF_FOUND %d:%d",
5025                             cqe->un.fcoe.ref_index, cqe->un.fcoe.fcf_count);
5026 
5027                         (void) emlxs_fcf_found_notify(port,
5028                             cqe->un.fcoe.ref_index);
5029                         break;
5030                 case ASYNC_EVENT_FCF_TABLE_FULL:
5031                         EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
5032                             "FIP Async Event: FCFTAB_FULL %d:%d",
5033                             cqe->un.fcoe.ref_index, cqe->un.fcoe.fcf_count);
5034 
5035                         (void) emlxs_fcf_full_notify(port);
5036                         break;
5037                 case ASYNC_EVENT_FCF_DEAD:
5038                         EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
5039                             "FIP Async Event: FCF_LOST %d:%d",
5040                             cqe->un.fcoe.ref_index, cqe->un.fcoe.fcf_count);
5041 
5042                         (void) emlxs_fcf_lost_notify(port,
5043                             cqe->un.fcoe.ref_index);
5044                         break;
5045                 case ASYNC_EVENT_VIRT_LINK_CLEAR:
5046                         EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
5047                             "FIP Async Event: CVL %d",
5048                             cqe->un.fcoe.ref_index);
5049 
5050                         (void) emlxs_fcf_cvl_notify(port,
5051                             emlxs_sli4_vpi_to_index(hba,
5052                             cqe->un.fcoe.ref_index));
5053                         break;
5054 
5055                 case ASYNC_EVENT_FCF_MODIFIED:
5056                         EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
5057                             "FIP Async Event: FCF_CHANGED %d",
5058                             cqe->un.fcoe.ref_index);
5059 
5060                         (void) emlxs_fcf_changed_notify(port,
5061                             cqe->un.fcoe.ref_index);
5062                         break;
5063                 default:
5064                         EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
5065                             "FIP Async Event: Unknown event type=%d",
5066                             cqe->un.fcoe.evt_type);
5067                         break;
5068                 }
5069                 break;
5070         case ASYNC_EVENT_CODE_DCBX:
5071                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
5072                     "DCBX Async Event: type=%d. Not supported.",
5073                     cqe->event_type);
5074                 break;
5075         case ASYNC_EVENT_CODE_GRP_5:
5076                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
5077                     "Group 5 Async Event: type=%d.", cqe->event_type);
5078                 if (cqe->event_type == ASYNC_EVENT_QOS_SPEED) {
5079                         hba->qos_linkspeed = cqe->un.qos.qos_link_speed;
5080                 }
5081                 break;
5082         case ASYNC_EVENT_CODE_FC_EVENT:
5083                 switch (cqe->event_type) {
5084                 case ASYNC_EVENT_FC_LINK_ATT:
5085                         HBASTATS.LinkEvent++;
5086 
5087                         EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
5088                             "FC Async Event: Link Attention. event=%x",
5089                             HBASTATS.LinkEvent);
5090 
5091                         emlxs_sli4_handle_fc_link_att(hba, cqe);
5092                         break;
5093                 case ASYNC_EVENT_FC_SHARED_LINK_ATT:
5094                         HBASTATS.LinkEvent++;
5095 
5096                         EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
5097                             "FC Async Event: Shared Link Attention. event=%x",
5098                             HBASTATS.LinkEvent);
5099 
5100                         emlxs_sli4_handle_fc_link_att(hba, cqe);
5101                         break;
5102                 default:
5103                         EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
5104                             "FC Async Event: Unknown event. type=%d event=%x",
5105                             cqe->event_type, HBASTATS.LinkEvent);
5106                 }
5107                 break;
5108         case ASYNC_EVENT_CODE_PORT:
5109                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
5110                     "SLI Port Async Event: type=%d", cqe->event_type);
5111                 if (cqe->event_type == ASYNC_EVENT_MISCONFIG_PORT) {
5112                         *((uint32_t *)cqe->un.port.link_status) =
5113                             BE_SWAP32(*((uint32_t *)cqe->un.port.link_status));
5114                         status =
5115                             cqe->un.port.link_status[hba->sli.sli4.link_number];
5116 
5117                         switch (status) {
5118                                 case 0 :
5119                                 break;
5120 
5121                                 case 1 :
5122                                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_err_msg,
5123                                     "SLI Port Async Event: Physical media not "
5124                                     "detected");
5125                                 cmn_err(CE_WARN,
5126                                     "^%s%d: Optics faulted/incorrectly "
5127                                     "installed/not installed - Reseat optics, "
5128                                     "if issue not resolved, replace.",
5129                                     DRIVER_NAME, hba->ddiinst);
5130                                 break;
5131 
5132                                 case 2 :
5133                                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_err_msg,
5134                                     "SLI Port Async Event: Wrong physical "
5135                                     "media detected");
5136                                 cmn_err(CE_WARN,
5137                                     "^%s%d: Optics of two types installed - "
5138                                     "Remove one optic or install matching"
5139                                     "pair of optics.",
5140                                     DRIVER_NAME, hba->ddiinst);
5141                                 break;
5142 
5143                                 case 3 :
5144                                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_err_msg,
5145                                     "SLI Port Async Event: Unsupported "
5146                                     "physical media detected");
5147                                 cmn_err(CE_WARN,
5148                                     "^%s%d:  Incompatible optics - Replace "
5149                                     "with compatible optics for card to "
5150                                     "function.",
5151                                     DRIVER_NAME, hba->ddiinst);
5152                                 break;
5153 
5154                                 default :
5155                                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_err_msg,
5156                                     "SLI Port Async Event: Physical media "
5157                                     "error, status=%x", status);
5158                                 cmn_err(CE_WARN,
5159                                     "^%s%d: Misconfigured port: status=0x%x - "
5160                                     "Check optics on card.",
5161                                     DRIVER_NAME, hba->ddiinst, status);
5162                                 break;
5163                         }
5164                 }
5165                 break;
5166         case ASYNC_EVENT_CODE_VF:
5167                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
5168                     "VF Async Event: type=%d",
5169                     cqe->event_type);
5170                 break;
5171         case ASYNC_EVENT_CODE_MR:
5172                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
5173                     "MR Async Event: type=%d",
5174                     cqe->event_type);
5175                 break;
5176         default:
5177                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
5178                     "Unknown Async Event: code=%d type=%d.",
5179                     cqe->event_code, cqe->event_type);
5180                 break;
5181         }
5182 
5183 } /* emlxs_sli4_process_async_event() */
5184 
5185 
5186 /*ARGSUSED*/
5187 static void
5188 emlxs_sli4_process_mbox_event(emlxs_hba_t *hba, CQE_MBOX_t *cqe)
5189 {
5190         emlxs_port_t *port = &PPORT;
5191         MAILBOX4 *mb;
5192         MATCHMAP *mbox_bp;
5193         MATCHMAP *mbox_nonembed;
5194         MAILBOXQ *mbq = NULL;
5195         uint32_t size;
5196         uint32_t *iptr;
5197         int rc;
5198         off_t offset;
5199 
5200         if (cqe->consumed && !cqe->completed) {
5201                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
5202                     "CQ ENTRY: Mbox event. Entry consumed but not completed");
5203                 return;
5204         }
5205 
5206         mutex_enter(&EMLXS_PORT_LOCK);
5207         switch (hba->mbox_queue_flag) {
5208         case 0:
5209                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_stray_mbox_intr_msg,
5210                     "CQ ENTRY: Mbox event. No mailbox active.");
5211 
5212                 mutex_exit(&EMLXS_PORT_LOCK);
5213                 return;
5214 
5215         case MBX_POLL:
5216 
5217                 /* Mark mailbox complete, this should wake up any polling */
5218                 /* threads. This can happen if interrupts are enabled while */
5219                 /* a polled mailbox command is outstanding. If we don't set */
5220                 /* MBQ_COMPLETED here, the polling thread may wait until */
5221                 /* timeout error occurs */
5222 
5223                 mutex_enter(&EMLXS_MBOX_LOCK);
5224                 mbq = (MAILBOXQ *)hba->mbox_mbq;
5225                 if (mbq) {
5226                         port = (emlxs_port_t *)mbq->port;
5227                         EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mbox_detail_msg,
5228                             "CQ ENTRY: Mbox event. Completing Polled command.");
5229                         mbq->flag |= MBQ_COMPLETED;
5230                 }
5231                 mutex_exit(&EMLXS_MBOX_LOCK);
5232 
5233                 mutex_exit(&EMLXS_PORT_LOCK);
5234                 return;
5235 
5236         case MBX_SLEEP:
5237         case MBX_NOWAIT:
5238                 /* Check mbox_timer, it acts as a service flag too */
5239                 /* The first to service the mbox queue will clear the timer */
5240                 if (hba->mbox_timer) {
5241                         hba->mbox_timer = 0;
5242 
5243                         mutex_enter(&EMLXS_MBOX_LOCK);
5244                         mbq = (MAILBOXQ *)hba->mbox_mbq;
5245                         mutex_exit(&EMLXS_MBOX_LOCK);
5246                 }
5247 
5248                 if (!mbq) {
5249                         EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mbox_detail_msg,
5250                             "Mailbox event. No service required.");
5251                         mutex_exit(&EMLXS_PORT_LOCK);
5252                         return;
5253                 }
5254 
5255                 mb = (MAILBOX4 *)mbq;
5256                 mutex_exit(&EMLXS_PORT_LOCK);
5257                 break;
5258 
5259         default:
5260                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mbox_completion_error_msg,
5261                     "CQ ENTRY: Mbox event. Invalid Mailbox flag (%x).",
5262                     hba->mbox_queue_flag);
5263 
5264                 mutex_exit(&EMLXS_PORT_LOCK);
5265                 return;
5266         }
5267 
5268         /* Set port context */
5269         port = (emlxs_port_t *)mbq->port;
5270 
5271         offset = (off_t)((uint64_t)((unsigned long)
5272             hba->sli.sli4.mq.addr.virt) -
5273             (uint64_t)((unsigned long)
5274             hba->sli.sli4.slim2.virt));
5275 
5276         /* Now that we are the owner, DMA Sync entire MQ if needed */
5277         EMLXS_MPDATA_SYNC(hba->sli.sli4.mq.addr.dma_handle, offset,
5278             4096, DDI_DMA_SYNC_FORDEV);
5279 
5280         BE_SWAP32_BCOPY((uint8_t *)hba->mbox_mqe, (uint8_t *)mb,
5281             MAILBOX_CMD_SLI4_BSIZE);
5282 
5283         if (mb->mbxCommand != MBX_HEARTBEAT) {
5284                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
5285                     "CQ ENTRY: Mbox event. Mbox complete. status=%x cmd=%x",
5286                     mb->mbxStatus, mb->mbxCommand);
5287 
5288                 emlxs_data_dump(port, "MBOX CMP", (uint32_t *)hba->mbox_mqe,
5289                     12, 0);
5290         }
5291 
5292         if (mb->mbxCommand == MBX_SLI_CONFIG) {
5293                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
5294                     "Mbox sge_cnt: %d length: %d embed: %d",
5295                     mb->un.varSLIConfig.be.sge_cnt,
5296                     mb->un.varSLIConfig.be.payload_length,
5297                     mb->un.varSLIConfig.be.embedded);
5298         }
5299 
5300         /* Now sync the memory buffer if one was used */
5301         if (mbq->bp) {
5302                 mbox_bp = (MATCHMAP *)mbq->bp;
5303                 EMLXS_MPDATA_SYNC(mbox_bp->dma_handle, 0, mbox_bp->size,
5304                     DDI_DMA_SYNC_FORKERNEL);
5305 #ifdef FMA_SUPPORT
5306                 if (emlxs_fm_check_dma_handle(hba, mbox_bp->dma_handle)
5307                     != DDI_FM_OK) {
5308                         EMLXS_MSGF(EMLXS_CONTEXT,
5309                             &emlxs_invalid_dma_handle_msg,
5310                             "sli4_process_mbox_event: hdl=%p",
5311                             mbox_bp->dma_handle);
5312 
5313                         mb->mbxStatus = MBXERR_DMA_ERROR;
5314 }
5315 #endif
5316         }
5317 
5318         /* Now sync the memory buffer if one was used */
5319         if (mbq->nonembed) {
5320                 mbox_nonembed = (MATCHMAP *)mbq->nonembed;
5321                 size = mbox_nonembed->size;
5322                 EMLXS_MPDATA_SYNC(mbox_nonembed->dma_handle, 0, size,
5323                     DDI_DMA_SYNC_FORKERNEL);
5324                 iptr = (uint32_t *)((uint8_t *)mbox_nonembed->virt);
5325                 BE_SWAP32_BCOPY((uint8_t *)iptr, (uint8_t *)iptr, size);
5326 
5327 #ifdef FMA_SUPPORT
5328                 if (emlxs_fm_check_dma_handle(hba,
5329                     mbox_nonembed->dma_handle) != DDI_FM_OK) {
5330                         EMLXS_MSGF(EMLXS_CONTEXT,
5331                             &emlxs_invalid_dma_handle_msg,
5332                             "sli4_process_mbox_event: hdl=%p",
5333                             mbox_nonembed->dma_handle);
5334 
5335                         mb->mbxStatus = MBXERR_DMA_ERROR;
5336                 }
5337 #endif
5338                 emlxs_data_dump(port, "EXT AREA", (uint32_t *)iptr, 24, 0);
5339         }
5340 
5341         /* Mailbox has been completely received at this point */
5342 
5343         if (mb->mbxCommand == MBX_HEARTBEAT) {
5344                 hba->heartbeat_active = 0;
5345                 goto done;
5346         }
5347 
5348         if (hba->mbox_queue_flag == MBX_SLEEP) {
5349                 if (mb->mbxCommand != MBX_DOWN_LOAD
5350                     /* && mb->mbxCommand != MBX_DUMP_MEMORY */) {
5351                         EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mbox_detail_msg,
5352                             "Received.  %s: status=%x Sleep.",
5353                             emlxs_mb_cmd_xlate(mb->mbxCommand),
5354                             mb->mbxStatus);
5355                 }
5356         } else {
5357                 if (mb->mbxCommand != MBX_DOWN_LOAD
5358                     /* && mb->mbxCommand != MBX_DUMP_MEMORY */) {
5359                         EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mbox_detail_msg,
5360                             "Completed. %s: status=%x",
5361                             emlxs_mb_cmd_xlate(mb->mbxCommand),
5362                             mb->mbxStatus);
5363                 }
5364         }
5365 
5366         /* Filter out passthru mailbox */
5367         if (mbq->flag & MBQ_PASSTHRU) {
5368                 goto done;
5369         }
5370 
5371         if (mb->mbxStatus) {
5372                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mbox_detail_msg,
5373                     "%s: status=0x%x", emlxs_mb_cmd_xlate(mb->mbxCommand),
5374                     (uint32_t)mb->mbxStatus);
5375         }
5376 
5377         if (mbq->mbox_cmpl) {
5378                 rc = (mbq->mbox_cmpl)(hba, mbq);
5379 
5380                 /* If mbox was retried, return immediately */
5381                 if (rc) {
5382                         return;
5383                 }
5384         }
5385 
5386 done:
5387 
5388         /* Clean up the mailbox area */
5389         emlxs_mb_fini(hba, (MAILBOX *)mb, mb->mbxStatus);
5390 
5391         /* Attempt to send pending mailboxes */
5392         mbq = (MAILBOXQ *)emlxs_mb_get(hba);
5393         if (mbq) {
5394                 /* Attempt to send pending mailboxes */
5395                 rc =  emlxs_sli4_issue_mbox_cmd(hba, mbq, MBX_NOWAIT, 0);
5396                 if ((rc != MBX_BUSY) && (rc != MBX_SUCCESS)) {
5397                         emlxs_mem_put(hba, MEM_MBOX, (void *)mbq);
5398                 }
5399         }
5400         return;
5401 
5402 } /* emlxs_sli4_process_mbox_event() */
5403 
5404 
5405 /*ARGSUSED*/
5406 static void
5407 emlxs_CQE_to_IOCB(emlxs_hba_t *hba, CQE_CmplWQ_t *cqe, emlxs_buf_t *sbp)
5408 {
5409 #ifdef DEBUG_FASTPATH
5410         emlxs_port_t *port = &PPORT;
5411 #endif /* DEBUG_FASTPATH */
5412         IOCBQ *iocbq;
5413         IOCB *iocb;
5414         uint32_t *iptr;
5415         fc_packet_t *pkt;
5416         emlxs_wqe_t *wqe;
5417 
5418         iocbq = &sbp->iocbq;
5419         wqe = &iocbq->wqe;
5420         iocb = &iocbq->iocb;
5421 
5422 #ifdef DEBUG_FASTPATH
5423         EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
5424             "CQE to IOCB: cmd:%x tag:%x xri:%d", wqe->Command,
5425             wqe->RequestTag, wqe->XRITag);
5426 #endif /* DEBUG_FASTPATH */
5427 
5428         iocb->ULPSTATUS = cqe->Status;
5429         iocb->un.ulpWord[4] = cqe->Parameter;
5430         iocb->ULPIOTAG = cqe->RequestTag;
5431         iocb->ULPCONTEXT = wqe->XRITag;
5432 
5433         switch (wqe->Command) {
5434 
5435         case CMD_FCP_ICMND64_CR:
5436                 iocb->ULPCOMMAND = CMD_FCP_ICMND64_CX;
5437                 break;
5438 
5439         case CMD_FCP_IREAD64_CR:
5440                 iocb->ULPCOMMAND = CMD_FCP_IREAD64_CX;
5441                 iocb->ULPPU = PARM_XFER_CHECK;
5442                 if (iocb->ULPSTATUS ==  IOSTAT_FCP_RSP_ERROR) {
5443                         iocb->un.fcpi64.fcpi_parm =
5444                             wqe->un.FcpCmd.TotalTransferCount -
5445                             cqe->CmdSpecific;
5446                 }
5447                 break;
5448 
5449         case CMD_FCP_IWRITE64_CR:
5450                 iocb->ULPCOMMAND = CMD_FCP_IWRITE64_CX;
5451                 if (iocb->ULPSTATUS ==  IOSTAT_FCP_RSP_ERROR) {
5452                         if (wqe->un.FcpCmd.TotalTransferCount >
5453                             cqe->CmdSpecific) {
5454                                 iocb->un.fcpi64.fcpi_parm =
5455                                     wqe->un.FcpCmd.TotalTransferCount -
5456                                     cqe->CmdSpecific;
5457                         } else {
5458                                 iocb->un.fcpi64.fcpi_parm = 0;
5459                         }
5460                 }
5461                 break;
5462 
5463         case CMD_ELS_REQUEST64_CR:
5464                 iocb->ULPCOMMAND = CMD_ELS_REQUEST64_CX;
5465                 iocb->un.elsreq64.bdl.bdeSize = cqe->CmdSpecific;
5466                 if (iocb->ULPSTATUS == 0) {
5467                         iocb->unsli3.ext_iocb.rsplen = cqe->CmdSpecific;
5468                 }
5469                 if (iocb->ULPSTATUS == IOSTAT_LS_RJT) {
5470                         /* For LS_RJT, the driver populates the rsp buffer */
5471                         pkt = PRIV2PKT(sbp);
5472                         iptr = (uint32_t *)pkt->pkt_resp;
5473                         *iptr++ = ELS_CMD_LS_RJT;
5474                         *iptr = cqe->Parameter;
5475                 }
5476                 break;
5477 
5478         case CMD_GEN_REQUEST64_CR:
5479                 iocb->ULPCOMMAND = CMD_GEN_REQUEST64_CX;
5480                 iocb->unsli3.ext_iocb.rsplen = cqe->CmdSpecific;
5481                 break;
5482 
5483         case CMD_XMIT_SEQUENCE64_CR:
5484                 iocb->ULPCOMMAND = CMD_XMIT_SEQUENCE64_CX;
5485                 break;
5486 
5487         case CMD_ABORT_XRI_CX:
5488                 iocb->ULPCONTEXT = wqe->AbortTag;
5489                 break;
5490 
5491         case CMD_FCP_TRECEIVE64_CX:
5492                 /* free memory for XRDY */
5493                 if (iocbq->bp) {
5494                         emlxs_mem_buf_free(hba, iocbq->bp);
5495                         iocbq->bp = 0;
5496                 }
5497 
5498                 /*FALLTHROUGH*/
5499 
5500         case CMD_FCP_TSEND64_CX:
5501         case CMD_FCP_TRSP64_CX:
5502         default:
5503                 iocb->ULPCOMMAND = wqe->Command;
5504 
5505         }
5506 } /* emlxs_CQE_to_IOCB() */
5507 
5508 
5509 /*ARGSUSED*/
5510 static void
5511 emlxs_sli4_hba_flush_chipq(emlxs_hba_t *hba)
5512 {
5513         emlxs_port_t *port = &PPORT;
5514         CHANNEL *cp;
5515         emlxs_buf_t *sbp;
5516         IOCBQ *iocbq;
5517         uint16_t i;
5518         uint32_t trigger = 0;
5519         CQE_CmplWQ_t cqe;
5520 
5521         mutex_enter(&EMLXS_FCTAB_LOCK);
5522         for (i = 0; i < hba->max_iotag; i++) {
5523                 sbp = hba->fc_table[i];
5524                 if (sbp == NULL || sbp == STALE_PACKET) {
5525                         continue;
5526                 }
5527                 hba->fc_table[i] = STALE_PACKET;
5528                 hba->io_count--;
5529                 sbp->iotag = 0;
5530                 mutex_exit(&EMLXS_FCTAB_LOCK);
5531 
5532                 cp = sbp->channel;
5533                 bzero(&cqe, sizeof (CQE_CmplWQ_t));
5534                 cqe.RequestTag = i;
5535                 cqe.Status = IOSTAT_LOCAL_REJECT;
5536                 cqe.Parameter = IOERR_SEQUENCE_TIMEOUT;
5537 
5538                 cp->hbaCmplCmd_sbp++;
5539 
5540 #ifdef SFCT_SUPPORT
5541 #ifdef FCT_IO_TRACE
5542                 if (sbp->fct_cmd) {
5543                         emlxs_fct_io_trace(port, sbp->fct_cmd,
5544                             EMLXS_FCT_IOCB_COMPLETE);
5545                 }
5546 #endif /* FCT_IO_TRACE */
5547 #endif /* SFCT_SUPPORT */
5548 
5549                 if (sbp->pkt_flags & PACKET_IN_CHIPQ) {
5550                         atomic_dec_32(&hba->io_active);
5551 #ifdef NODE_THROTTLE_SUPPORT
5552                         if (sbp->node) {
5553                                 atomic_dec_32(&sbp->node->io_active);
5554                         }
5555 #endif /* NODE_THROTTLE_SUPPORT */
5556                 }
5557 
5558                 /* Copy entry to sbp's iocbq */
5559                 iocbq = &sbp->iocbq;
5560                 emlxs_CQE_to_IOCB(hba, &cqe, sbp);
5561 
5562                 iocbq->next = NULL;
5563 
5564                 /* Exchange is no longer busy on-chip, free it */
5565                 emlxs_sli4_free_xri(port, sbp, sbp->xrip, 1);
5566 
5567                 if (!(sbp->pkt_flags &
5568                     (PACKET_POLLED | PACKET_ALLOCATED))) {
5569                         /* Add the IOCB to the channel list */
5570                         mutex_enter(&cp->rsp_lock);
5571                         if (cp->rsp_head == NULL) {
5572                                 cp->rsp_head = iocbq;
5573                                 cp->rsp_tail = iocbq;
5574                         } else {
5575                                 cp->rsp_tail->next = iocbq;
5576                                 cp->rsp_tail = iocbq;
5577                         }
5578                         mutex_exit(&cp->rsp_lock);
5579                         trigger = 1;
5580                 } else {
5581                         emlxs_proc_channel_event(hba, cp, iocbq);
5582                 }
5583                 mutex_enter(&EMLXS_FCTAB_LOCK);
5584         }
5585         mutex_exit(&EMLXS_FCTAB_LOCK);
5586 
5587         if (trigger) {
5588                 for (i = 0; i < hba->chan_count; i++) {
5589                         cp = &hba->chan[i];
5590                         if (cp->rsp_head != NULL) {
5591                                 emlxs_thread_trigger2(&cp->intr_thread,
5592                                     emlxs_proc_channel, cp);
5593                         }
5594                 }
5595         }
5596 
5597 } /* emlxs_sli4_hba_flush_chipq() */
5598 
5599 
5600 /*ARGSUSED*/
5601 static void
5602 emlxs_sli4_process_oor_wqe_cmpl(emlxs_hba_t *hba,
5603     CQ_DESC_t *cq, CQE_CmplWQ_t *cqe)
5604 {
5605         emlxs_port_t *port = &PPORT;
5606         CHANNEL *cp;
5607         uint16_t request_tag;
5608 
5609         request_tag = cqe->RequestTag;
5610 
5611         /* 1 to 1 mapping between CQ and channel */
5612         cp = cq->channelp;
5613 
5614         cp->hbaCmplCmd++;
5615 
5616         EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
5617             "CQ ENTRY: OOR Cmpl: iotag=%d", request_tag);
5618 
5619         emlxs_data_dump(port, "CQE", (uint32_t *)cqe, 4, 0);
5620 
5621 } /* emlxs_sli4_process_oor_wqe_cmpl() */
5622 
5623 
5624 /*ARGSUSED*/
5625 static void
5626 emlxs_sli4_process_wqe_cmpl(emlxs_hba_t *hba, CQ_DESC_t *cq, CQE_CmplWQ_t *cqe)
5627 {
5628         emlxs_port_t *port = &PPORT;
5629         CHANNEL *cp;
5630         emlxs_buf_t *sbp;
5631         IOCBQ *iocbq;
5632         uint16_t request_tag;
5633 #ifdef SFCT_SUPPORT
5634 #ifdef FCT_IO_TRACE
5635         fct_cmd_t *fct_cmd;
5636         emlxs_buf_t *cmd_sbp;
5637 #endif /* FCT_IO_TRACE */
5638 #endif /* SFCT_SUPPORT */
5639 
5640         request_tag = cqe->RequestTag;
5641 
5642         /* 1 to 1 mapping between CQ and channel */
5643         cp = cq->channelp;
5644 
5645         mutex_enter(&EMLXS_FCTAB_LOCK);
5646         sbp = hba->fc_table[request_tag];
5647 
5648         if (!sbp) {
5649                 cp->hbaCmplCmd++;
5650                 mutex_exit(&EMLXS_FCTAB_LOCK);
5651                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
5652                     "CQ ENTRY: NULL sbp. iotag=%d. Dropping...",
5653                     request_tag);
5654                 return;
5655         }
5656 
5657         if (sbp == STALE_PACKET) {
5658                 cp->hbaCmplCmd_sbp++;
5659                 mutex_exit(&EMLXS_FCTAB_LOCK);
5660                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
5661                     "CQ ENTRY: Stale sbp. iotag=%d. Dropping...", request_tag);
5662                 return;
5663         }
5664 
5665         if (sbp->pkt_flags & PACKET_IN_CHIPQ) {
5666                 atomic_add_32(&hba->io_active, -1);
5667 #ifdef NODE_THROTTLE_SUPPORT
5668                 if (sbp->node) {
5669                         atomic_add_32(&sbp->node->io_active, -1);
5670                 }
5671 #endif /* NODE_THROTTLE_SUPPORT */
5672         }
5673 
5674         if (!(sbp->xrip)) {
5675                 cp->hbaCmplCmd++;
5676                 mutex_exit(&EMLXS_FCTAB_LOCK);
5677                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
5678                     "CQ ENTRY: NULL sbp xrip %p. iotag=%d. Dropping...",
5679                     sbp, request_tag);
5680                 return;
5681         }
5682 
5683 #ifdef DEBUG_FASTPATH
5684         EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
5685             "CQ ENTRY: process wqe compl");
5686 #endif /* DEBUG_FASTPATH */
5687         cp->hbaCmplCmd_sbp++;
5688 
5689         /* Copy entry to sbp's iocbq */
5690         iocbq = &sbp->iocbq;
5691         emlxs_CQE_to_IOCB(hba, cqe, sbp);
5692 
5693         iocbq->next = NULL;
5694 
5695         if (cqe->XB) {
5696                 /* Mark exchange as ABORT in progress */
5697                 sbp->xrip->flag &= ~EMLXS_XRI_PENDING_IO;
5698                 sbp->xrip->flag |= EMLXS_XRI_BUSY;
5699 
5700                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
5701                     "CQ ENTRY: XRI BUSY: iotag=%d xri=%d", request_tag,
5702                     sbp->xrip->XRI);
5703 
5704                 emlxs_sli4_free_xri(port, sbp, 0, 0);
5705         } else {
5706                 /* Exchange is no longer busy on-chip, free it */
5707                 emlxs_sli4_free_xri(port, sbp, sbp->xrip, 0);
5708         }
5709 
5710         mutex_exit(&EMLXS_FCTAB_LOCK);
5711 
5712 #ifdef SFCT_SUPPORT
5713 #ifdef FCT_IO_TRACE
5714         fct_cmd = sbp->fct_cmd;
5715         if (fct_cmd) {
5716                 cmd_sbp = (emlxs_buf_t *)fct_cmd->cmd_fca_private;
5717                 mutex_enter(&cmd_sbp->fct_mtx);
5718                 EMLXS_FCT_STATE_CHG(fct_cmd, cmd_sbp, EMLXS_FCT_IOCB_COMPLETE);
5719                 mutex_exit(&cmd_sbp->fct_mtx);
5720         }
5721 #endif /* FCT_IO_TRACE */
5722 #endif /* SFCT_SUPPORT */
5723 
5724         /*
5725          * If this is NOT a polled command completion
5726          * or a driver allocated pkt, then defer pkt
5727          * completion.
5728          */
5729         if (!(sbp->pkt_flags &
5730             (PACKET_POLLED | PACKET_ALLOCATED))) {
5731                 /* Add the IOCB to the channel list */
5732                 mutex_enter(&cp->rsp_lock);
5733                 if (cp->rsp_head == NULL) {
5734                         cp->rsp_head = iocbq;
5735                         cp->rsp_tail = iocbq;
5736                 } else {
5737                         cp->rsp_tail->next = iocbq;
5738                         cp->rsp_tail = iocbq;
5739                 }
5740                 mutex_exit(&cp->rsp_lock);
5741 
5742                 /* Delay triggering thread till end of ISR */
5743                 cp->chan_flag |= EMLXS_NEEDS_TRIGGER;
5744         } else {
5745                 emlxs_proc_channel_event(hba, cp, iocbq);
5746         }
5747 
5748 } /* emlxs_sli4_process_wqe_cmpl() */
5749 
5750 
5751 /*ARGSUSED*/
5752 static void
5753 emlxs_sli4_process_release_wqe(emlxs_hba_t *hba, CQ_DESC_t *cq,
5754     CQE_RelWQ_t *cqe)
5755 {
5756         emlxs_port_t *port = &PPORT;
5757         WQ_DESC_t *wq;
5758         CHANNEL *cp;
5759         uint32_t i;
5760         uint16_t wqi;
5761 
5762         wqi = emlxs_sli4_wqid_to_index(hba, (uint16_t)cqe->WQid);
5763 
5764         /* Verify WQ index */
5765         if (wqi == 0xffff) {
5766                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_err_msg,
5767                     "CQ ENTRY: Invalid WQid:%d. Dropping...",
5768                     cqe->WQid);
5769                 return;
5770         }
5771 
5772         wq = &hba->sli.sli4.wq[wqi];
5773 
5774 #ifdef DEBUG_FASTPATH
5775         EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
5776             "CQ ENTRY: process release wqe: old %d new %d", wq->port_index,
5777             cqe->WQindex);
5778 #endif /* DEBUG_FASTPATH */
5779 
5780         wq->port_index = cqe->WQindex;
5781 
5782         /* Cmd ring may be available. Try sending more iocbs */
5783         for (i = 0; i < hba->chan_count; i++) {
5784                 cp = &hba->chan[i];
5785                 if (wq == (WQ_DESC_t *)cp->iopath) {
5786                         emlxs_sli4_issue_iocb_cmd(hba, cp, 0);
5787                 }
5788         }
5789 
5790 } /* emlxs_sli4_process_release_wqe() */
5791 
5792 
5793 /*ARGSUSED*/
5794 emlxs_iocbq_t *
5795 emlxs_sli4_rxq_get(emlxs_hba_t *hba, fc_frame_hdr_t *fchdr)
5796 {
5797         emlxs_queue_t *q;
5798         emlxs_iocbq_t *iocbq;
5799         emlxs_iocbq_t *prev;
5800         fc_frame_hdr_t *fchdr2;
5801         RXQ_DESC_t *rxq;
5802 
5803         switch (fchdr->type) {
5804         case 1: /* ELS */
5805                 rxq = &hba->sli.sli4.rxq[EMLXS_RXQ_ELS];
5806                 break;
5807         case 0x20: /* CT */
5808                 rxq = &hba->sli.sli4.rxq[EMLXS_RXQ_CT];
5809                 break;
5810         default:
5811                 return (NULL);
5812         }
5813 
5814         mutex_enter(&rxq->lock);
5815 
5816         q = &rxq->active;
5817         iocbq  = (emlxs_iocbq_t *)q->q_first;
5818         prev = NULL;
5819 
5820         while (iocbq) {
5821 
5822                 fchdr2 = (fc_frame_hdr_t *)iocbq->iocb.un.ulpWord;
5823 
5824                 if ((fchdr2->s_id == fchdr->s_id) &&
5825                     (fchdr2->ox_id == fchdr->ox_id) &&
5826                     (fchdr2->seq_id == fchdr->seq_id)) {
5827                         /* Remove iocbq */
5828                         if (prev) {
5829                                 prev->next = iocbq->next;
5830                         }
5831                         if (q->q_first == (uint8_t *)iocbq) {
5832                                 q->q_first = (uint8_t *)iocbq->next;
5833                         }
5834                         if (q->q_last == (uint8_t *)iocbq) {
5835                                 q->q_last = (uint8_t *)prev;
5836                         }
5837                         q->q_cnt--;
5838 
5839                         break;
5840                 }
5841 
5842                 prev  = iocbq;
5843                 iocbq = iocbq->next;
5844         }
5845 
5846         mutex_exit(&rxq->lock);
5847 
5848         return (iocbq);
5849 
5850 } /* emlxs_sli4_rxq_get() */
5851 
5852 
5853 /*ARGSUSED*/
5854 void
5855 emlxs_sli4_rxq_put(emlxs_hba_t *hba, emlxs_iocbq_t *iocbq)
5856 {
5857         emlxs_queue_t *q;
5858         fc_frame_hdr_t *fchdr;
5859         RXQ_DESC_t *rxq;
5860 
5861         fchdr = (fc_frame_hdr_t *)iocbq->iocb.RXFCHDR;
5862 
5863         switch (fchdr->type) {
5864         case 1: /* ELS */
5865                 rxq = &hba->sli.sli4.rxq[EMLXS_RXQ_ELS];
5866                 break;
5867         case 0x20: /* CT */
5868                 rxq = &hba->sli.sli4.rxq[EMLXS_RXQ_CT];
5869                 break;
5870         default:
5871                 return;
5872         }
5873 
5874         mutex_enter(&rxq->lock);
5875 
5876         q = &rxq->active;
5877 
5878         if (q->q_last) {
5879                 ((emlxs_iocbq_t *)q->q_last)->next = iocbq;
5880                 q->q_cnt++;
5881         } else {
5882                 q->q_first = (uint8_t *)iocbq;
5883                 q->q_cnt = 1;
5884         }
5885 
5886         q->q_last = (uint8_t *)iocbq;
5887         iocbq->next = NULL;
5888 
5889         mutex_exit(&rxq->lock);
5890 
5891         return;
5892 
5893 } /* emlxs_sli4_rxq_put() */
5894 
5895 
5896 static void
5897 emlxs_sli4_rq_post(emlxs_port_t *port, uint16_t rqid)
5898 {
5899         emlxs_hba_t *hba = HBA;
5900         emlxs_rqdbu_t rqdb;
5901 
5902         EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
5903             "RQ POST: rqid=%d count=1", rqid);
5904 
5905         /* Ring the RQ doorbell once to repost the RQ buffer */
5906         rqdb.word = 0;
5907         rqdb.db.Qid = rqid;
5908         rqdb.db.NumPosted = 1;
5909 
5910         emlxs_sli4_write_rqdb(hba, rqdb.word);
5911 
5912 } /* emlxs_sli4_rq_post() */
5913 
5914 
5915 /*ARGSUSED*/
5916 static void
5917 emlxs_sli4_process_unsol_rcv(emlxs_hba_t *hba, CQ_DESC_t *cq,
5918     CQE_UnsolRcv_t *cqe)
5919 {
5920         emlxs_port_t *port = &PPORT;
5921         emlxs_port_t *vport;
5922         RQ_DESC_t *hdr_rq;
5923         RQ_DESC_t *data_rq;
5924         MBUF_INFO *hdr_mp;
5925         MBUF_INFO *data_mp;
5926         MATCHMAP *seq_mp;
5927         uint32_t *data;
5928         fc_frame_hdr_t fchdr;
5929         uint16_t hdr_rqi;
5930         uint32_t host_index;
5931         emlxs_iocbq_t *iocbq = NULL;
5932         emlxs_iocb_t *iocb;
5933         emlxs_node_t *node = NULL;
5934         uint32_t i;
5935         uint32_t seq_len;
5936         uint32_t seq_cnt;
5937         uint32_t buf_type;
5938         char label[32];
5939         emlxs_wqe_t *wqe;
5940         CHANNEL *cp;
5941         XRIobj_t *xrip;
5942         RPIobj_t *rpip = NULL;
5943         uint32_t        cmd;
5944         uint32_t posted = 0;
5945         uint32_t abort = 1;
5946         off_t offset;
5947         uint32_t status;
5948         uint32_t data_size;
5949         uint16_t rqid;
5950         uint32_t hdr_size;
5951         fc_packet_t *pkt;
5952         emlxs_buf_t *sbp;
5953 
5954         if (cqe->Code == CQE_TYPE_UNSOL_RCV_V1) {
5955                 CQE_UnsolRcvV1_t *cqeV1 = (CQE_UnsolRcvV1_t *)cqe;
5956 
5957                 status    = cqeV1->Status;
5958                 data_size = cqeV1->data_size;
5959                 rqid      = cqeV1->RQid;
5960                 hdr_size  = cqeV1->hdr_size;
5961         } else {
5962                 status    = cqe->Status;
5963                 data_size = cqe->data_size;
5964                 rqid      = cqe->RQid;
5965                 hdr_size  = cqe->hdr_size;
5966         }
5967 
5968         /* Validate the CQE */
5969 
5970         /* Check status */
5971         switch (status) {
5972         case RQ_STATUS_SUCCESS: /* 0x10 */
5973                 break;
5974 
5975         case RQ_STATUS_BUFLEN_EXCEEDED:  /* 0x11 */
5976                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_err_msg,
5977                     "CQ ENTRY: Unsol Rcv: Payload truncated.");
5978                 break;
5979 
5980         case RQ_STATUS_NEED_BUFFER: /* 0x12 */
5981                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
5982                     "CQ ENTRY: Unsol Rcv: Payload buffer needed.");
5983                 return;
5984 
5985         case RQ_STATUS_FRAME_DISCARDED:  /* 0x13 */
5986                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
5987                     "CQ ENTRY: Unsol Rcv: Payload buffer discarded.");
5988                 return;
5989 
5990         default:
5991                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_err_msg,
5992                     "CQ ENTRY: Unsol Rcv: Unknown status=%x.",
5993                     status);
5994                 break;
5995         }
5996 
5997         /* Make sure there is a frame header */
5998         if (hdr_size < sizeof (fc_frame_hdr_t)) {
5999                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_err_msg,
6000                     "CQ ENTRY: Unsol Rcv: FC header too small. Dropping...");
6001                 return;
6002         }
6003 
6004         hdr_rqi = emlxs_sli4_rqid_to_index(hba, rqid);
6005 
6006         /* Verify RQ index */
6007         if (hdr_rqi == 0xffff) {
6008                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_err_msg,
6009                     "CQ ENTRY: Unsol Rcv: Invalid RQID:%d. Dropping...",
6010                     rqid);
6011                 return;
6012         }
6013 
6014         hdr_rq  = &hba->sli.sli4.rq[hdr_rqi];
6015         data_rq = &hba->sli.sli4.rq[hdr_rqi + 1];
6016 
6017         EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
6018             "CQ ENTRY: Unsol Rcv:%x rqid=%d,%d index=%d status=%x "
6019             "hdr_size=%d data_size=%d",
6020             cqe->Code, rqid, hdr_rqi, hdr_rq->host_index, status, hdr_size,
6021             data_size);
6022 
6023         hdr_rq->num_proc++;
6024 
6025         /* Update host index */
6026         mutex_enter(&hba->sli.sli4.rq[hdr_rqi].lock);
6027         host_index = hdr_rq->host_index;
6028         hdr_rq->host_index++;
6029 
6030         if (hdr_rq->host_index >= hdr_rq->max_index) {
6031                 hdr_rq->host_index = 0;
6032         }
6033         data_rq->host_index = hdr_rq->host_index;
6034         mutex_exit(&hba->sli.sli4.rq[hdr_rqi].lock);
6035 
6036         /* Get the next header rqb */
6037         hdr_mp  = &hdr_rq->rqb[host_index];
6038 
6039         offset = (off_t)((uint64_t)((unsigned long)hdr_mp->virt) -
6040             (uint64_t)((unsigned long)hba->sli.sli4.slim2.virt));
6041 
6042         EMLXS_MPDATA_SYNC(hdr_mp->dma_handle, offset,
6043             sizeof (fc_frame_hdr_t), DDI_DMA_SYNC_FORKERNEL);
6044 
6045         LE_SWAP32_BCOPY(hdr_mp->virt, (uint8_t *)&fchdr,
6046             sizeof (fc_frame_hdr_t));
6047 
6048         EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
6049             "RQ HDR[%d]: rctl:%x type:%x "
6050             "sid:%x did:%x oxid:%x rxid:%x",
6051             host_index, fchdr.r_ctl, fchdr.type,
6052             fchdr.s_id,  fchdr.d_id, fchdr.ox_id, fchdr.rx_id);
6053 
6054         EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
6055             "RQ HDR[%d]: fctl:%x seq_id:%x seq_cnt:%x df_ctl:%x ro:%x",
6056             host_index, fchdr.f_ctl, fchdr.seq_id, fchdr.seq_cnt,
6057             fchdr.df_ctl, fchdr.ro);
6058 
6059         /* Verify fc header type */
6060         switch (fchdr.type) {
6061         case 0: /* BLS */
6062                 if (fchdr.r_ctl != 0x81) {
6063                         EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
6064                             "RQ ENTRY: Unexpected FC rctl (0x%x) "
6065                             "received. Dropping...",
6066                             fchdr.r_ctl);
6067 
6068                         goto done;
6069                 }
6070 
6071                 /* Make sure there is no payload */
6072                 if (data_size != 0) {
6073                         EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_err_msg,
6074                             "RQ ENTRY: ABTS payload provided. Dropping...");
6075 
6076                         goto done;
6077                 }
6078 
6079                 buf_type = 0xFFFFFFFF;
6080                 (void) strlcpy(label, "ABTS", sizeof (label));
6081                 cp = &hba->chan[hba->channel_els];
6082                 break;
6083 
6084         case 0x01: /* ELS */
6085                 /* Make sure there is a payload */
6086                 if (data_size == 0) {
6087                         EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_err_msg,
6088                             "RQ ENTRY: Unsol Rcv: No ELS payload provided. "
6089                             "Dropping...");
6090 
6091                         goto done;
6092                 }
6093 
6094                 buf_type = MEM_ELSBUF;
6095                 (void) strlcpy(label, "Unsol ELS", sizeof (label));
6096                 cp = &hba->chan[hba->channel_els];
6097                 break;
6098 
6099         case 0x20: /* CT */
6100                 /* Make sure there is a payload */
6101                 if (data_size == 0) {
6102                         EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_err_msg,
6103                             "RQ ENTRY: Unsol Rcv: No CT payload provided. "
6104                             "Dropping...");
6105 
6106                         goto done;
6107                 }
6108 
6109                 buf_type = MEM_CTBUF;
6110                 (void) strlcpy(label, "Unsol CT", sizeof (label));
6111                 cp = &hba->chan[hba->channel_ct];
6112                 break;
6113 
6114         case 0x08: /* FCT */
6115                 /* Make sure there is a payload */
6116                 if (data_size == 0) {
6117                         EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_err_msg,
6118                             "RQ ENTRY: Unsol Rcv: No FCP payload provided. "
6119                             "Dropping...");
6120 
6121                         goto done;
6122                 }
6123 
6124                 buf_type = MEM_FCTBUF;
6125                 (void) strlcpy(label, "Unsol FCT", sizeof (label));
6126                 cp = &hba->chan[hba->CHANNEL_FCT];
6127                 break;
6128 
6129         default:
6130                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
6131                     "RQ ENTRY: Unexpected FC type (0x%x) received. Dropping...",
6132                     fchdr.type);
6133 
6134                 goto done;
6135         }
6136         /* Fc Header is valid */
6137 
6138         /* Check if this is an active sequence */
6139         iocbq = emlxs_sli4_rxq_get(hba, &fchdr);
6140 
6141         if (!iocbq) {
6142                 if (fchdr.type != 0) {
6143                         if (!(fchdr.f_ctl & F_CTL_FIRST_SEQ)) {
6144                                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
6145                                     "RQ ENTRY: %s: First of sequence not"
6146                                     " set.  Dropping...",
6147                                     label);
6148 
6149                                 goto done;
6150                         }
6151                 }
6152 
6153                 if ((fchdr.type != 0) && (fchdr.seq_cnt != 0)) {
6154                         EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
6155                             "RQ ENTRY: %s: Sequence count not zero (%d).  "
6156                             "Dropping...",
6157                             label, fchdr.seq_cnt);
6158 
6159                         goto done;
6160                 }
6161 
6162                 /* Find vport */
6163                 for (i = 0; i < MAX_VPORTS; i++) {
6164                         vport = &VPORT(i);
6165 
6166                         if (vport->did == fchdr.d_id) {
6167                                 port = vport;
6168                                 break;
6169                         }
6170                 }
6171 
6172                 if (i == MAX_VPORTS) {
6173                         /* Allow unsol FLOGI & PLOGI for P2P */
6174                         if ((fchdr.type != 1 /* ELS*/) ||
6175                             ((fchdr.d_id != FABRIC_DID) &&
6176                             !(hba->flag & FC_PT_TO_PT))) {
6177                                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
6178                                     "RQ ENTRY: %s: Invalid did=%x. Dropping...",
6179                                     label, fchdr.d_id);
6180 
6181                                 goto done;
6182                         }
6183                 }
6184 
6185                 /* Allocate an IOCBQ */
6186                 iocbq = (emlxs_iocbq_t *)emlxs_mem_get(hba, MEM_IOCB);
6187 
6188                 if (!iocbq) {
6189                         EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
6190                             "RQ ENTRY: %s: Out of IOCB "
6191                             "resources.  Dropping...",
6192                             label);
6193 
6194                         goto done;
6195                 }
6196 
6197                 seq_mp = NULL;
6198                 if (fchdr.type != 0) {
6199                         /* Allocate a buffer */
6200                         seq_mp = (MATCHMAP *)emlxs_mem_get(hba, buf_type);
6201 
6202                         if (!seq_mp) {
6203                                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
6204                                     "RQ ENTRY: %s: Out of buffer "
6205                                     "resources.  Dropping...",
6206                                     label);
6207 
6208                                 goto done;
6209                         }
6210 
6211                         iocbq->bp = (uint8_t *)seq_mp;
6212                 }
6213 
6214                 node = (void *)emlxs_node_find_did(port, fchdr.s_id, 1);
6215                 if (node == NULL) {
6216                         EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
6217                             "RQ ENTRY: %s: Node not found. sid=%x",
6218                             label, fchdr.s_id);
6219                 }
6220 
6221                 /* Initialize the iocbq */
6222                 iocbq->port = port;
6223                 iocbq->channel = cp;
6224                 iocbq->node = node;
6225 
6226                 iocb = &iocbq->iocb;
6227                 iocb->RXSEQCNT = 0;
6228                 iocb->RXSEQLEN = 0;
6229 
6230                 seq_len = 0;
6231                 seq_cnt = 0;
6232 
6233         } else {
6234 
6235                 iocb = &iocbq->iocb;
6236                 port = iocbq->port;
6237                 node = (emlxs_node_t *)iocbq->node;
6238 
6239                 seq_mp = (MATCHMAP *)iocbq->bp;
6240                 seq_len = iocb->RXSEQLEN;
6241                 seq_cnt = iocb->RXSEQCNT;
6242 
6243                 /* Check sequence order */
6244                 if (fchdr.seq_cnt != seq_cnt) {
6245                         EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
6246                             "RQ ENTRY: %s: Out of order frame received "
6247                             "(%d != %d).  Dropping...",
6248                             label, fchdr.seq_cnt, seq_cnt);
6249 
6250                         goto done;
6251                 }
6252         }
6253 
6254         /* We now have an iocbq */
6255 
6256         if (!port->vpip->vfip) {
6257                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
6258                     "RQ ENTRY: %s: No fabric connection. "
6259                     "Dropping...",
6260                     label);
6261 
6262                 goto done;
6263         }
6264 
6265         /* Save the frame data to our seq buffer */
6266         if (data_size && seq_mp) {
6267                 /* Get the next data rqb */
6268                 data_mp = &data_rq->rqb[host_index];
6269 
6270                 offset = (off_t)((uint64_t)((unsigned long)
6271                     data_mp->virt) -
6272                     (uint64_t)((unsigned long)
6273                     hba->sli.sli4.slim2.virt));
6274 
6275                 EMLXS_MPDATA_SYNC(data_mp->dma_handle, offset,
6276                     data_size, DDI_DMA_SYNC_FORKERNEL);
6277 
6278                 data = (uint32_t *)data_mp->virt;
6279 
6280                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
6281                     "RQ DAT[%d]: %08x %08x %08x %08x %08x %08x ...",
6282                     host_index, data[0], data[1], data[2], data[3],
6283                     data[4], data[5]);
6284 
6285                 /* Check sequence length */
6286                 if ((seq_len + data_size) > seq_mp->size) {
6287                         EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_err_msg,
6288                             "RQ ENTRY: %s: Sequence buffer overflow. "
6289                             "(%d > %d). Dropping...",
6290                             label, (seq_len + data_size), seq_mp->size);
6291 
6292                         goto done;
6293                 }
6294 
6295                 /* Copy data to local receive buffer */
6296                 bcopy((uint8_t *)data, ((uint8_t *)seq_mp->virt +
6297                     seq_len), data_size);
6298 
6299                 seq_len += data_size;
6300         }
6301 
6302         /* If this is not the last frame of sequence, queue it. */
6303         if (!(fchdr.f_ctl & F_CTL_END_SEQ)) {
6304                 /* Save sequence header */
6305                 if (seq_cnt == 0) {
6306                         bcopy((uint8_t *)&fchdr, (uint8_t *)iocb->RXFCHDR,
6307                             sizeof (fc_frame_hdr_t));
6308                 }
6309 
6310                 /* Update sequence info in iocb */
6311                 iocb->RXSEQCNT = seq_cnt + 1;
6312                 iocb->RXSEQLEN = seq_len;
6313 
6314                 /* Queue iocbq for next frame */
6315                 emlxs_sli4_rxq_put(hba, iocbq);
6316 
6317                 /* Don't free resources */
6318                 iocbq = NULL;
6319 
6320                 /* No need to abort */
6321                 abort = 0;
6322 
6323                 goto done;
6324         }
6325 
6326         emlxs_sli4_rq_post(port, hdr_rq->qid);
6327         posted = 1;
6328 
6329         /* End of sequence found. Process request now. */
6330 
6331         if (seq_cnt > 0) {
6332                 /* Retrieve first frame of sequence */
6333                 bcopy((uint8_t *)iocb->RXFCHDR, (uint8_t *)&fchdr,
6334                     sizeof (fc_frame_hdr_t));
6335 
6336                 bzero((uint8_t *)iocb, sizeof (emlxs_iocb_t));
6337         }
6338 
6339         /* Build rcv iocb and process it */
6340         switch (fchdr.type) {
6341         case 0: /* BLS */
6342 
6343                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
6344                     "RQ ENTRY: %s: oxid:%x rxid %x sid:%x. Sending BLS ACC...",
6345                     label, fchdr.ox_id, fchdr.rx_id, fchdr.s_id);
6346 
6347                 /* Try to send abort response */
6348                 if (!(pkt = emlxs_pkt_alloc(port, 0, 0, 0, KM_NOSLEEP))) {
6349                         EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
6350                             "RQ ENTRY: %s: Unable to alloc pkt. Dropping...",
6351                             label);
6352                         goto done;
6353                 }
6354 
6355                 /* Setup sbp / iocb for driver initiated cmd */
6356                 sbp = PKT2PRIV(pkt);
6357 
6358                 /* Free the temporary iocbq */
6359                 emlxs_mem_put(hba, MEM_IOCB, (void *)iocbq);
6360 
6361                 iocbq = (emlxs_iocbq_t *)&sbp->iocbq;
6362                 iocbq->port = port;
6363                 iocbq->channel = cp;
6364                 iocbq->node = node;
6365 
6366                 sbp->pkt_flags &= ~PACKET_ULP_OWNED;
6367 
6368                 if (node) {
6369                         sbp->node = node;
6370                         sbp->did  = node->nlp_DID;
6371                 }
6372 
6373                 iocbq->flag |= (IOCB_PRIORITY | IOCB_SPECIAL);
6374 
6375                 /* BLS ACC Response */
6376                 wqe = &iocbq->wqe;
6377                 bzero((void *)wqe, sizeof (emlxs_wqe_t));
6378 
6379                 iocbq->iocb.ULPCOMMAND = CMD_XMIT_BLS_RSP64_CX;
6380                 wqe->Command = CMD_XMIT_BLS_RSP64_CX;
6381                 wqe->CmdType = WQE_TYPE_GEN;
6382 
6383                 wqe->un.BlsRsp.Payload0 = 0x80;
6384                 wqe->un.BlsRsp.Payload1 = fchdr.seq_id;
6385 
6386                 wqe->un.BlsRsp.OXId = fchdr.ox_id;
6387                 wqe->un.BlsRsp.RXId = fchdr.rx_id;
6388 
6389                 wqe->un.BlsRsp.SeqCntLow = 0;
6390                 wqe->un.BlsRsp.SeqCntHigh = 0xFFFF;
6391 
6392                 wqe->un.BlsRsp.XO = ((fchdr.f_ctl & F_CTL_XCHG_CONTEXT)? 1:0);
6393                 wqe->un.BlsRsp.AR = 0;
6394 
6395                 rpip = EMLXS_NODE_TO_RPI(port, node);
6396 
6397                 if (rpip) {
6398                         wqe->ContextType = WQE_RPI_CONTEXT;
6399                         wqe->ContextTag = rpip->RPI;
6400                 } else {
6401                         wqe->ContextType = WQE_VPI_CONTEXT;
6402                         wqe->ContextTag = port->vpip->VPI;
6403 
6404                         rpip = emlxs_rpi_reserve_notify(port, fchdr.s_id, 0);
6405 
6406                         if (!rpip) {
6407                                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
6408                                     "RQ ENTRY: %s: Unable to alloc "
6409                                     "reserved RPI. Dropping...",
6410                                     label);
6411 
6412                                 goto done;
6413                         }
6414 
6415                         /* Store the reserved rpi */
6416                         wqe->CmdSpecific = rpip->RPI;
6417 
6418                         wqe->un.BlsRsp.RemoteId = fchdr.s_id;
6419                         wqe->un.BlsRsp.LocalId = fchdr.d_id;
6420                 }
6421 
6422                 if (fchdr.f_ctl & F_CTL_CHAINED_SEQ) {
6423                         wqe->CCPE = 1;
6424                         wqe->CCP = fchdr.rsvd;
6425                 }
6426 
6427                 /* Allocate an exchange for this command */
6428                 xrip = emlxs_sli4_alloc_xri(port, sbp, rpip,
6429                     EMLXS_XRI_SOL_BLS_TYPE);
6430 
6431                 if (!xrip) {
6432                         EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
6433                             "RQ ENTRY: %s: Unable to alloc XRI. Dropping...",
6434                             label);
6435                         goto done;
6436                 }
6437 
6438                 wqe->XRITag = xrip->XRI;
6439                 wqe->Class = CLASS3;
6440                 wqe->RequestTag = xrip->iotag;
6441                 wqe->CQId = (uint16_t)0xffff;  /* default CQ for response */
6442 
6443                 sbp->ticks = hba->timer_tics + 30;
6444 
6445                 emlxs_sli4_issue_iocb_cmd(hba, iocbq->channel, iocbq);
6446 
6447                 /* The temporary iocbq has been freed already */
6448                 iocbq = NULL;
6449 
6450                 break;
6451 
6452         case 1: /* ELS */
6453                 cmd = *((uint32_t *)seq_mp->virt);
6454                 cmd &= ELS_CMD_MASK;
6455 
6456                 if (!(port->vpip->flag & EMLXS_VPI_PORT_ENABLED)) {
6457                         uint32_t dropit = 1;
6458 
6459                         /* Allow for P2P handshaking */
6460                         switch (cmd) {
6461                         case ELS_CMD_FLOGI:
6462                                 dropit = 0;
6463                                 break;
6464 
6465                         case ELS_CMD_PLOGI:
6466                         case ELS_CMD_PRLI:
6467                                 if (hba->flag & FC_PT_TO_PT) {
6468                                         dropit = 0;
6469                                 }
6470                                 break;
6471                         }
6472 
6473                         if (dropit) {
6474                                 EMLXS_MSGF(EMLXS_CONTEXT,
6475                                     &emlxs_sli_detail_msg,
6476                                     "RQ ENTRY: %s: Port not yet enabled. "
6477                                     "Dropping...",
6478                                     label);
6479                                 goto done;
6480                         }
6481                 }
6482 
6483                 rpip = NULL;
6484 
6485                 if (cmd != ELS_CMD_LOGO) {
6486                         rpip = EMLXS_NODE_TO_RPI(port, node);
6487                 }
6488 
6489                 if (!rpip) {
6490                         /* Use the fabric rpi */
6491                         rpip = port->vpip->fabric_rpip;
6492                 }
6493 
6494                 xrip = emlxs_sli4_reserve_xri(port, rpip,
6495                     EMLXS_XRI_UNSOL_ELS_TYPE, fchdr.ox_id);
6496 
6497                 if (!xrip) {
6498                         EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
6499                             "RQ ENTRY: %s: Out of exchange "
6500                             "resources.  Dropping...",
6501                             label);
6502 
6503                         goto done;
6504                 }
6505 
6506                 /* Build CMD_RCV_ELS64_CX */
6507                 iocb->un.rcvels64.elsReq.tus.f.bdeFlags = 0;
6508                 iocb->un.rcvels64.elsReq.tus.f.bdeSize  = seq_len;
6509                 iocb->un.rcvels64.elsReq.addrLow  = PADDR_LO(seq_mp->phys);
6510                 iocb->un.rcvels64.elsReq.addrHigh = PADDR_HI(seq_mp->phys);
6511                 iocb->ULPBDECOUNT = 1;
6512 
6513                 iocb->un.rcvels64.remoteID = fchdr.s_id;
6514                 iocb->un.rcvels64.parmRo = fchdr.d_id;
6515 
6516                 iocb->ULPPU = 0x3;
6517                 iocb->ULPCONTEXT = xrip->XRI;
6518                 iocb->ULPIOTAG = ((node)? node->nlp_Rpi:0);
6519                 iocb->ULPCLASS = CLASS3;
6520                 iocb->ULPCOMMAND = CMD_RCV_ELS64_CX;
6521 
6522                 iocb->unsli3.ext_rcv.seq_len = seq_len;
6523                 iocb->unsli3.ext_rcv.vpi = port->vpip->VPI;
6524                 iocb->unsli3.ext_rcv.oxid = fchdr.ox_id;
6525 
6526                 if (fchdr.f_ctl & F_CTL_CHAINED_SEQ) {
6527                         iocb->unsli3.ext_rcv.ccpe = 1;
6528                         iocb->unsli3.ext_rcv.ccp = fchdr.rsvd;
6529                 }
6530 
6531                 if (port->mode == MODE_INITIATOR) {
6532                         (void) emlxs_els_handle_unsol_req(port, iocbq->channel,
6533                             iocbq, seq_mp, seq_len);
6534                 }
6535 #ifdef SFCT_SUPPORT
6536                 else if (port->mode == MODE_TARGET) {
6537                         (void) emlxs_fct_handle_unsol_els(port, iocbq->channel,
6538                             iocbq, seq_mp, seq_len);
6539                 }
6540 #endif /* SFCT_SUPPORT */
6541                 break;
6542 
6543 #ifdef SFCT_SUPPORT
6544         case 8: /* FCT */
6545                 if (!(port->VPIobj.flag & EMLXS_VPI_PORT_ENABLED)) {
6546                         EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
6547                             "RQ ENTRY: %s: Port not yet enabled. "
6548                             "Dropping...",
6549                             label);
6550 
6551                         goto done;
6552                 }
6553 
6554                 rpip = EMLXS_NODE_TO_RPI(port, node);
6555 
6556                 if (!rpip) {
6557                         EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
6558                             "RQ ENTRY: %s: Port not logged in. "
6559                             "Dropping...",
6560                             label);
6561 
6562                         goto done;
6563                 }
6564 
6565                 xrip = emlxs_sli4_reserve_xri(port, rpip,
6566                     EMLXS_XRI_UNSOL_FCP_TYPE, fchdr.ox_id);
6567 
6568                 if (!xrip) {
6569                         EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
6570                             "RQ ENTRY: %s: Out of exchange "
6571                             "resources.  Dropping...",
6572                             label);
6573 
6574                         goto done;
6575                 }
6576 
6577                 /* Build CMD_RCV_SEQUENCE64_CX */
6578                 iocb->un.rcvseq64.rcvBde.tus.f.bdeFlags = 0;
6579                 iocb->un.rcvseq64.rcvBde.tus.f.bdeSize  = seq_len;
6580                 iocb->un.rcvseq64.rcvBde.addrLow  = PADDR_LO(seq_mp->phys);
6581                 iocb->un.rcvseq64.rcvBde.addrHigh = PADDR_HI(seq_mp->phys);
6582                 iocb->ULPBDECOUNT = 1;
6583 
6584                 iocb->ULPPU = 0x3;
6585                 iocb->ULPCONTEXT = xrip->XRI;
6586                 iocb->ULPIOTAG = ((node)? node->nlp_Rpi:0);
6587                 iocb->ULPCLASS = CLASS3;
6588                 iocb->ULPCOMMAND = CMD_RCV_ELS64_CX;
6589 
6590                 iocb->unsli3.ext_rcv.seq_len = seq_len;
6591                 iocb->unsli3.ext_rcv.vpi = port->VPIobj.VPI;
6592                 iocb->unsli3.ext_rcv.oxid = fchdr.ox_id;
6593 
6594                 if (fchdr.f_ctl & F_CTL_CHAINED_SEQ) {
6595                         iocb->unsli3.ext_rcv.ccpe = 1;
6596                         iocb->unsli3.ext_rcv.ccp = fchdr.rsvd;
6597                 }
6598 
6599                 /* pass xrip to FCT in the iocbq */
6600                 iocbq->sbp = xrip;
6601 
6602 #define EMLXS_FIX_CISCO_BUG1
6603 #ifdef EMLXS_FIX_CISCO_BUG1
6604 {
6605 uint8_t *ptr;
6606 ptr = ((uint8_t *)seq_mp->virt);
6607 if (((*ptr+12) != 0xa0) && (*(ptr+20) == 0x8) && (*(ptr+21) == 0x8)) {
6608         EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_err_msg,
6609             "RQ ENTRY: Bad CDB fixed");
6610         *ptr++ = 0;
6611         *ptr = 0;
6612 }
6613 }
6614 #endif
6615                 (void) emlxs_fct_handle_unsol_req(port, cp, iocbq,
6616                         seq_mp, seq_len);
6617                 break;
6618 #endif /* SFCT_SUPPORT */
6619 
6620         case 0x20: /* CT */
6621                 if (!(port->vpip->flag & EMLXS_VPI_PORT_ENABLED) &&
6622                     !(hba->flag & FC_LOOPBACK_MODE)) {
6623                         EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
6624                             "RQ ENTRY: %s: Port not yet enabled. "
6625                             "Dropping...",
6626                             label);
6627 
6628                         goto done;
6629                 }
6630 
6631                 if (!node) {
6632                         EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
6633                             "RQ ENTRY: %s: Node not found (did=%x).  "
6634                             "Dropping...",
6635                             label, fchdr.d_id);
6636 
6637                         goto done;
6638                 }
6639 
6640                 rpip = EMLXS_NODE_TO_RPI(port, node);
6641 
6642                 if (!rpip) {
6643                         EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
6644                             "RQ ENTRY: %s: RPI not found (did=%x rpi=%d).  "
6645                             "Dropping...",
6646                             label, fchdr.d_id, node->nlp_Rpi);
6647 
6648                         goto done;
6649                 }
6650 
6651                 xrip = emlxs_sli4_reserve_xri(port, rpip,
6652                     EMLXS_XRI_UNSOL_CT_TYPE, fchdr.ox_id);
6653 
6654                 if (!xrip) {
6655                         EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
6656                             "RQ ENTRY: %s: Out of exchange "
6657                             "resources.  Dropping...",
6658                             label);
6659 
6660                         goto done;
6661                 }
6662 
6663                 /* Build CMD_RCV_SEQ64_CX */
6664                 iocb->un.rcvseq64.rcvBde.tus.f.bdeFlags = 0;
6665                 iocb->un.rcvseq64.rcvBde.tus.f.bdeSize  = seq_len;
6666                 iocb->un.rcvseq64.rcvBde.addrLow  = PADDR_LO(seq_mp->phys);
6667                 iocb->un.rcvseq64.rcvBde.addrHigh = PADDR_HI(seq_mp->phys);
6668                 iocb->ULPBDECOUNT = 1;
6669 
6670                 iocb->un.rcvseq64.xrsqRo = 0;
6671                 iocb->un.rcvseq64.w5.hcsw.Rctl = fchdr.r_ctl;
6672                 iocb->un.rcvseq64.w5.hcsw.Type = fchdr.type;
6673                 iocb->un.rcvseq64.w5.hcsw.Dfctl = fchdr.df_ctl;
6674                 iocb->un.rcvseq64.w5.hcsw.Fctl = fchdr.f_ctl;
6675 
6676                 iocb->ULPPU = 0x3;
6677                 iocb->ULPCONTEXT = xrip->XRI;
6678                 iocb->ULPIOTAG = rpip->RPI;
6679                 iocb->ULPCLASS = CLASS3;
6680                 iocb->ULPCOMMAND = CMD_RCV_SEQ64_CX;
6681 
6682                 iocb->unsli3.ext_rcv.seq_len = seq_len;
6683                 iocb->unsli3.ext_rcv.vpi = port->vpip->VPI;
6684 
6685                 if (fchdr.f_ctl & F_CTL_CHAINED_SEQ) {
6686                         iocb->unsli3.ext_rcv.ccpe = 1;
6687                         iocb->unsli3.ext_rcv.ccp = fchdr.rsvd;
6688                 }
6689 
6690                 (void) emlxs_ct_handle_unsol_req(port, iocbq->channel,
6691                     iocbq, seq_mp, seq_len);
6692 
6693                 break;
6694         }
6695 
6696         /* Sequence handled, no need to abort */
6697         abort = 0;
6698 
6699 done:
6700 
6701         if (!posted) {
6702                 emlxs_sli4_rq_post(port, hdr_rq->qid);
6703         }
6704 
6705         if (abort) {
6706                 /* Send ABTS for this exchange */
6707                 /* !!! Currently, we have no implementation for this !!! */
6708                 abort = 0;
6709         }
6710 
6711         /* Return memory resources to pools */
6712         if (iocbq) {
6713                 if (iocbq->bp) {
6714                         emlxs_mem_put(hba, buf_type, (void *)iocbq->bp);
6715                         iocbq->bp = 0;
6716                 }
6717 
6718                 emlxs_mem_put(hba, MEM_IOCB, (void *)iocbq);
6719         }
6720 
6721 #ifdef FMA_SUPPORT
6722         if (emlxs_fm_check_dma_handle(hba,
6723             hba->sli.sli4.slim2.dma_handle)
6724             != DDI_FM_OK) {
6725                 EMLXS_MSGF(EMLXS_CONTEXT,
6726                     &emlxs_invalid_dma_handle_msg,
6727                     "sli4_process_unsol_rcv: hdl=%p",
6728                     hba->sli.sli4.slim2.dma_handle);
6729 
6730                 emlxs_thread_spawn(hba, emlxs_restart_thread,
6731                     0, 0);
6732         }
6733 #endif
6734         return;
6735 
6736 } /* emlxs_sli4_process_unsol_rcv() */
6737 
6738 
6739 /*ARGSUSED*/
6740 static void
6741 emlxs_sli4_process_xri_aborted(emlxs_hba_t *hba, CQ_DESC_t *cq,
6742     CQE_XRI_Abort_t *cqe)
6743 {
6744         emlxs_port_t *port = &PPORT;
6745         XRIobj_t *xrip;
6746 
6747         mutex_enter(&EMLXS_FCTAB_LOCK);
6748 
6749         xrip = emlxs_sli4_find_xri(port, cqe->XRI);
6750         if (xrip == NULL) {
6751                 /* EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_err_msg, */
6752                 /*    "CQ ENTRY: process xri aborted ignored");  */
6753 
6754                 mutex_exit(&EMLXS_FCTAB_LOCK);
6755                 return;
6756         }
6757 
6758         EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
6759             "CQ ENTRY: XRI Aborted: xri=%d IA=%d EO=%d BR=%d",
6760             cqe->XRI, cqe->IA, cqe->EO, cqe->BR);
6761 
6762         if (!(xrip->flag & EMLXS_XRI_BUSY)) {
6763                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_err_msg,
6764                     "CQ ENTRY: XRI Aborted: xri=%d flag=%x. Bad state.",
6765                     xrip->XRI, xrip->flag);
6766 
6767                 mutex_exit(&EMLXS_FCTAB_LOCK);
6768                 return;
6769         }
6770 
6771         /* Exchange is no longer busy on-chip, free it */
6772         emlxs_sli4_free_xri(port, 0, xrip, 0);
6773 
6774         mutex_exit(&EMLXS_FCTAB_LOCK);
6775 
6776         return;
6777 
6778 } /* emlxs_sli4_process_xri_aborted () */
6779 
6780 
6781 /*ARGSUSED*/
6782 static void
6783 emlxs_sli4_process_cq(emlxs_hba_t *hba, CQ_DESC_t *cq)
6784 {
6785         emlxs_port_t *port = &PPORT;
6786         CQE_u *cqe;
6787         CQE_u cq_entry;
6788         uint32_t cqdb;
6789         int num_entries = 0;
6790         off_t offset;
6791 
6792         /* EMLXS_PORT_LOCK must be held when entering this routine */
6793 
6794         cqe = (CQE_u *)cq->addr.virt;
6795         cqe += cq->host_index;
6796 
6797         offset = (off_t)((uint64_t)((unsigned long)
6798             cq->addr.virt) -
6799             (uint64_t)((unsigned long)
6800             hba->sli.sli4.slim2.virt));
6801 
6802         EMLXS_MPDATA_SYNC(cq->addr.dma_handle, offset,
6803             4096, DDI_DMA_SYNC_FORKERNEL);
6804 
6805         for (;;) {
6806                 cq_entry.word[3] = BE_SWAP32(cqe->word[3]);
6807                 if (!(cq_entry.word[3] & CQE_VALID)) {
6808                         break;
6809                 }
6810 
6811                 cq_entry.word[2] = BE_SWAP32(cqe->word[2]);
6812                 cq_entry.word[1] = BE_SWAP32(cqe->word[1]);
6813                 cq_entry.word[0] = BE_SWAP32(cqe->word[0]);
6814 
6815 #ifdef  DEBUG_CQE
6816                 emlxs_data_dump(port, "CQE", (uint32_t *)cqe, 6, 0);
6817 #endif /* DEBUG_CQE */
6818                 num_entries++;
6819                 cqe->word[3] = 0;
6820 
6821                 cq->host_index++;
6822                 if (cq->host_index >= cq->max_index) {
6823                         cq->host_index = 0;
6824                         cqe = (CQE_u *)cq->addr.virt;
6825                 } else {
6826                         cqe++;
6827                 }
6828                 mutex_exit(&EMLXS_PORT_LOCK);
6829 
6830                 /* Now handle specific cq type */
6831                 if (cq->type == EMLXS_CQ_TYPE_GROUP1) {
6832                         if (cq_entry.cqAsyncEntry.async_evt) {
6833                                 emlxs_sli4_process_async_event(hba,
6834                                     (CQE_ASYNC_t *)&cq_entry);
6835                         } else {
6836                                 emlxs_sli4_process_mbox_event(hba,
6837                                     (CQE_MBOX_t *)&cq_entry);
6838                         }
6839                 } else { /* EMLXS_CQ_TYPE_GROUP2 */
6840                         switch (cq_entry.cqCmplEntry.Code) {
6841                         case CQE_TYPE_WQ_COMPLETION:
6842                                 if (cq_entry.cqCmplEntry.RequestTag <
6843                                     hba->max_iotag) {
6844                                         emlxs_sli4_process_wqe_cmpl(hba, cq,
6845                                             (CQE_CmplWQ_t *)&cq_entry);
6846                                 } else {
6847                                         emlxs_sli4_process_oor_wqe_cmpl(hba, cq,
6848                                             (CQE_CmplWQ_t *)&cq_entry);
6849                                 }
6850                                 break;
6851                         case CQE_TYPE_RELEASE_WQE:
6852                                 emlxs_sli4_process_release_wqe(hba, cq,
6853                                     (CQE_RelWQ_t *)&cq_entry);
6854                                 break;
6855                         case CQE_TYPE_UNSOL_RCV:
6856                         case CQE_TYPE_UNSOL_RCV_V1:
6857                                 emlxs_sli4_process_unsol_rcv(hba, cq,
6858                                     (CQE_UnsolRcv_t *)&cq_entry);
6859                                 break;
6860                         case CQE_TYPE_XRI_ABORTED:
6861                                 emlxs_sli4_process_xri_aborted(hba, cq,
6862                                     (CQE_XRI_Abort_t *)&cq_entry);
6863                                 break;
6864                         default:
6865                                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_err_msg,
6866                                     "Invalid CQ entry %d: %08x %08x %08x %08x",
6867                                     cq_entry.cqCmplEntry.Code, cq_entry.word[0],
6868                                     cq_entry.word[1], cq_entry.word[2],
6869                                     cq_entry.word[3]);
6870                                 break;
6871                         }
6872                 }
6873 
6874                 mutex_enter(&EMLXS_PORT_LOCK);
6875         }
6876 
6877         /* Number of times this routine gets called for this CQ */
6878         cq->isr_count++;
6879 
6880         /* num_entries is the number of CQEs we process in this specific CQ */
6881         cq->num_proc += num_entries;
6882         if (cq->max_proc < num_entries)
6883                 cq->max_proc = num_entries;
6884 
6885         cqdb = cq->qid;
6886         cqdb |= CQ_DB_REARM;
6887         if (num_entries != 0) {
6888                 cqdb |= ((num_entries << CQ_DB_POP_SHIFT) & CQ_DB_POP_MASK);
6889         }
6890 
6891 #ifdef DEBUG_FASTPATH
6892         EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
6893             "CQE: CLEAR cqdb=%08x: pops=%d", cqdb, num_entries);
6894 #endif /* DEBUG_FASTPATH */
6895 
6896         emlxs_sli4_write_cqdb(hba, cqdb);
6897 
6898         /* EMLXS_PORT_LOCK must be held when exiting this routine */
6899 
6900 } /* emlxs_sli4_process_cq() */
6901 
6902 
6903 /*ARGSUSED*/
6904 static void
6905 emlxs_sli4_process_eq(emlxs_hba_t *hba, EQ_DESC_t *eq)
6906 {
6907         emlxs_port_t *port = &PPORT;
6908         uint32_t eqdb;
6909         uint32_t *ptr;
6910         CHANNEL *cp;
6911         EQE_u eqe;
6912         uint32_t i;
6913         uint16_t cqi;
6914         int num_entries = 0;
6915         off_t offset;
6916 
6917         /* EMLXS_PORT_LOCK must be held when entering this routine */
6918 
6919         hba->intr_busy_cnt ++;
6920 
6921         ptr = eq->addr.virt;
6922         ptr += eq->host_index;
6923 
6924         offset = (off_t)((uint64_t)((unsigned long)
6925             eq->addr.virt) -
6926             (uint64_t)((unsigned long)
6927             hba->sli.sli4.slim2.virt));
6928 
6929         EMLXS_MPDATA_SYNC(eq->addr.dma_handle, offset,
6930             4096, DDI_DMA_SYNC_FORKERNEL);
6931 
6932         for (;;) {
6933                 eqe.word = *ptr;
6934                 eqe.word = BE_SWAP32(eqe.word);
6935 
6936                 if (!(eqe.word & EQE_VALID)) {
6937                         break;
6938                 }
6939 
6940 #ifdef DEBUG_FASTPATH
6941                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
6942                     "EQE00: %08x", eqe.word);
6943 #endif /* DEBUG_FASTPATH */
6944 
6945                 *ptr = 0;
6946                 num_entries++;
6947                 eq->host_index++;
6948                 if (eq->host_index >= eq->max_index) {
6949                         eq->host_index = 0;
6950                         ptr = eq->addr.virt;
6951                 } else {
6952                         ptr++;
6953                 }
6954 
6955                 cqi = emlxs_sli4_cqid_to_index(hba, eqe.entry.CQId);
6956 
6957                 /* Verify CQ index */
6958                 if (cqi == 0xffff) {
6959                         EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_err_msg,
6960                             "EQE: Invalid CQid: %d. Dropping...",
6961                             eqe.entry.CQId);
6962                         continue;
6963                 }
6964 
6965 #ifdef DEBUG_FASTPATH
6966                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
6967                     "EQE: CQIndex:%x cqid:%x", cqi, eqe.entry.CQId);
6968 #endif /* DEBUG_FASTPATH */
6969 
6970                 emlxs_sli4_process_cq(hba, &hba->sli.sli4.cq[cqi]);
6971         }
6972 
6973         /* Number of times the ISR for this EQ gets called */
6974         eq->isr_count++;
6975 
6976         /* num_entries is the number of EQEs we process in this specific ISR */
6977         eq->num_proc += num_entries;
6978         if (eq->max_proc < num_entries) {
6979                 eq->max_proc = num_entries;
6980         }
6981 
6982         eqdb = eq->qid;
6983         eqdb |= (EQ_DB_CLEAR | EQ_DB_EVENT | EQ_DB_REARM);
6984 
6985 #ifdef DEBUG_FASTPATH
6986         EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
6987             "EQE: CLEAR eqdb=%08x pops=%d", eqdb, num_entries);
6988 #endif /* DEBUG_FASTPATH */
6989 
6990         if (num_entries != 0) {
6991                 eqdb |= ((num_entries << EQ_DB_POP_SHIFT) & EQ_DB_POP_MASK);
6992                 for (i = 0; i < hba->chan_count; i++) {
6993                         cp = &hba->chan[i];
6994                         if (cp->chan_flag & EMLXS_NEEDS_TRIGGER) {
6995                                 cp->chan_flag &= ~EMLXS_NEEDS_TRIGGER;
6996                                 emlxs_thread_trigger2(&cp->intr_thread,
6997                                     emlxs_proc_channel, cp);
6998                         }
6999                 }
7000         }
7001 
7002         emlxs_sli4_write_cqdb(hba, eqdb);
7003 
7004         /* EMLXS_PORT_LOCK must be held when exiting this routine */
7005 
7006         hba->intr_busy_cnt --;
7007 
7008 } /* emlxs_sli4_process_eq() */
7009 
7010 
7011 #ifdef MSI_SUPPORT
7012 /*ARGSUSED*/
7013 static uint32_t
7014 emlxs_sli4_msi_intr(char *arg1, char *arg2)
7015 {
7016         emlxs_hba_t *hba = (emlxs_hba_t *)arg1;
7017 #ifdef DEBUG_FASTPATH
7018         emlxs_port_t *port = &PPORT;
7019 #endif /* DEBUG_FASTPATH */
7020         uint16_t msgid;
7021         int rc;
7022 
7023 #ifdef DEBUG_FASTPATH
7024         EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
7025             "msiINTR arg1:%p arg2:%p", arg1, arg2);
7026 #endif /* DEBUG_FASTPATH */
7027 
7028         /* Check for legacy interrupt handling */
7029         if (hba->intr_type == DDI_INTR_TYPE_FIXED) {
7030                 rc = emlxs_sli4_intx_intr(arg1);
7031                 return (rc);
7032         }
7033 
7034         /* Get MSI message id */
7035         msgid = (uint16_t)((unsigned long)arg2);
7036 
7037         /* Validate the message id */
7038         if (msgid >= hba->intr_count) {
7039                 msgid = 0;
7040         }
7041         mutex_enter(&EMLXS_PORT_LOCK);
7042 
7043         if ((hba->state == FC_KILLED) || (hba->flag & FC_OFFLINE_MODE)) {
7044                 mutex_exit(&EMLXS_PORT_LOCK);
7045                 return (DDI_INTR_UNCLAIMED);
7046         }
7047 
7048         /* The eq[] index == the MSI vector number */
7049         emlxs_sli4_process_eq(hba, &hba->sli.sli4.eq[msgid]);
7050 
7051         mutex_exit(&EMLXS_PORT_LOCK);
7052         return (DDI_INTR_CLAIMED);
7053 
7054 } /* emlxs_sli4_msi_intr() */
7055 #endif /* MSI_SUPPORT */
7056 
7057 
7058 /*ARGSUSED*/
7059 static int
7060 emlxs_sli4_intx_intr(char *arg)
7061 {
7062         emlxs_hba_t *hba = (emlxs_hba_t *)arg;
7063 #ifdef DEBUG_FASTPATH
7064         emlxs_port_t *port = &PPORT;
7065 #endif /* DEBUG_FASTPATH */
7066 
7067 #ifdef DEBUG_FASTPATH
7068         EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
7069             "intxINTR arg:%p", arg);
7070 #endif /* DEBUG_FASTPATH */
7071 
7072         mutex_enter(&EMLXS_PORT_LOCK);
7073 
7074         if ((hba->state == FC_KILLED) || (hba->flag & FC_OFFLINE_MODE)) {
7075                 mutex_exit(&EMLXS_PORT_LOCK);
7076                 return (DDI_INTR_UNCLAIMED);
7077         }
7078 
7079         emlxs_sli4_process_eq(hba, &hba->sli.sli4.eq[0]);
7080 
7081         mutex_exit(&EMLXS_PORT_LOCK);
7082         return (DDI_INTR_CLAIMED);
7083 } /* emlxs_sli4_intx_intr() */
7084 
7085 
7086 static void
7087 emlxs_sli4_hba_kill(emlxs_hba_t *hba)
7088 {
7089         emlxs_port_t *port = &PPORT;
7090         uint32_t j;
7091 
7092         mutex_enter(&EMLXS_PORT_LOCK);
7093         if (hba->flag & FC_INTERLOCKED) {
7094                 EMLXS_STATE_CHANGE_LOCKED(hba, FC_KILLED);
7095 
7096                 mutex_exit(&EMLXS_PORT_LOCK);
7097 
7098                 return;
7099         }
7100 
7101         j = 0;
7102         while (j++ < 10000) {
7103                 if ((hba->mbox_queue_flag == 0) &&
7104                     (hba->intr_busy_cnt == 0)) {
7105                         break;
7106                 }
7107 
7108                 mutex_exit(&EMLXS_PORT_LOCK);
7109                 BUSYWAIT_US(100);
7110                 mutex_enter(&EMLXS_PORT_LOCK);
7111         }
7112 
7113         if ((hba->mbox_queue_flag != 0) || (hba->intr_busy_cnt > 0)) {
7114                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
7115                     "Board kill failed. Adapter busy, %d, %d.",
7116                     hba->mbox_queue_flag, hba->intr_busy_cnt);
7117                 mutex_exit(&EMLXS_PORT_LOCK);
7118                 return;
7119         }
7120 
7121         hba->flag |= FC_INTERLOCKED;
7122 
7123         EMLXS_STATE_CHANGE_LOCKED(hba, FC_KILLED);
7124 
7125         mutex_exit(&EMLXS_PORT_LOCK);
7126 
7127 } /* emlxs_sli4_hba_kill() */
7128 
7129 
7130 extern void
7131 emlxs_sli4_hba_reset_all(emlxs_hba_t *hba, uint32_t flag)
7132 {
7133         emlxs_port_t *port = &PPORT;
7134         uint32_t value;
7135 
7136         mutex_enter(&EMLXS_PORT_LOCK);
7137 
7138         if ((hba->sli_intf & SLI_INTF_IF_TYPE_MASK) != SLI_INTF_IF_TYPE_2) {
7139                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_debug_msg,
7140                     "Reset All failed. Invalid Operation.");
7141                 mutex_exit(&EMLXS_PORT_LOCK);
7142                 return;
7143         }
7144 
7145         /* Issue a Firmware Reset All Request */
7146         if (flag) {
7147                 value = SLI_PHYDEV_FRST | SLI_PHYDEV_FRL_ALL | SLI_PHYDEV_DD;
7148         } else {
7149                 value = SLI_PHYDEV_FRST | SLI_PHYDEV_FRL_ALL;
7150         }
7151 
7152         ddi_put32(hba->sli.sli4.bar0_acc_handle,
7153             hba->sli.sli4.PHYSDEV_reg_addr, value);
7154 
7155         mutex_exit(&EMLXS_PORT_LOCK);
7156 
7157 } /* emlxs_sli4_hba_reset_all() */
7158 
7159 
7160 static void
7161 emlxs_sli4_enable_intr(emlxs_hba_t *hba)
7162 {
7163         emlxs_config_t *cfg = &CFG;
7164         int i;
7165         int num_cq;
7166         uint32_t data;
7167 
7168         hba->sli.sli4.flag |= EMLXS_SLI4_INTR_ENABLED;
7169 
7170         num_cq = (hba->intr_count * cfg[CFG_NUM_WQ].current) +
7171             EMLXS_CQ_OFFSET_WQ;
7172 
7173         /* ARM EQ / CQs */
7174         for (i = 0; i < num_cq; i++) {
7175                 data = hba->sli.sli4.cq[i].qid;
7176                 data |= CQ_DB_REARM;
7177                 emlxs_sli4_write_cqdb(hba, data);
7178         }
7179         for (i = 0; i < hba->intr_count; i++) {
7180                 data = hba->sli.sli4.eq[i].qid;
7181                 data |= (EQ_DB_REARM | EQ_DB_EVENT);
7182                 emlxs_sli4_write_cqdb(hba, data);
7183         }
7184 } /* emlxs_sli4_enable_intr() */
7185 
7186 
7187 static void
7188 emlxs_sli4_disable_intr(emlxs_hba_t *hba, uint32_t att)
7189 {
7190         if (att) {
7191                 return;
7192         }
7193 
7194         hba->sli.sli4.flag &= ~EMLXS_SLI4_INTR_ENABLED;
7195 
7196         /* Short of reset, we cannot disable interrupts */
7197 } /* emlxs_sli4_disable_intr() */
7198 
7199 
7200 static void
7201 emlxs_sli4_resource_free(emlxs_hba_t *hba)
7202 {
7203         emlxs_port_t    *port = &PPORT;
7204         MBUF_INFO       *buf_info;
7205         uint32_t        i;
7206 
7207         buf_info = &hba->sli.sli4.slim2;
7208         if (buf_info->virt == 0) {
7209                 /* Already free */
7210                 return;
7211         }
7212 
7213         emlxs_fcf_fini(hba);
7214 
7215         buf_info = &hba->sli.sli4.HeaderTmplate;
7216         if (buf_info->virt) {
7217                 bzero(buf_info, sizeof (MBUF_INFO));
7218         }
7219 
7220         if (hba->sli.sli4.XRIp) {
7221                 if ((hba->sli.sli4.XRIinuse_f !=
7222                     (XRIobj_t *)&hba->sli.sli4.XRIinuse_f) ||
7223                     (hba->sli.sli4.XRIinuse_b !=
7224                     (XRIobj_t *)&hba->sli.sli4.XRIinuse_f)) {
7225                         EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_debug_msg,
7226                             "XRIs in use during free!: %p %p != %p\n",
7227                             hba->sli.sli4.XRIinuse_f,
7228                             hba->sli.sli4.XRIinuse_b,
7229                             &hba->sli.sli4.XRIinuse_f);
7230                 }
7231                 kmem_free(hba->sli.sli4.XRIp,
7232                     (sizeof (XRIobj_t) * hba->sli.sli4.XRICount));
7233                 hba->sli.sli4.XRIp = NULL;
7234 
7235                 hba->sli.sli4.XRIfree_f =
7236                     (XRIobj_t *)&hba->sli.sli4.XRIfree_f;
7237                 hba->sli.sli4.XRIfree_b =
7238                     (XRIobj_t *)&hba->sli.sli4.XRIfree_f;
7239                 hba->sli.sli4.xrif_count = 0;
7240         }
7241 
7242         for (i = 0; i < hba->intr_count; i++) {
7243                 mutex_destroy(&hba->sli.sli4.eq[i].lastwq_lock);
7244                 bzero(&hba->sli.sli4.eq[i], sizeof (EQ_DESC_t));
7245                 hba->sli.sli4.eq[i].qid = 0xffff;
7246         }
7247         for (i = 0; i < EMLXS_MAX_CQS; i++) {
7248                 bzero(&hba->sli.sli4.cq[i], sizeof (CQ_DESC_t));
7249                 hba->sli.sli4.cq[i].qid = 0xffff;
7250         }
7251         for (i = 0; i < EMLXS_MAX_WQS; i++) {
7252                 bzero(&hba->sli.sli4.wq[i], sizeof (WQ_DESC_t));
7253                 hba->sli.sli4.wq[i].qid = 0xffff;
7254         }
7255         for (i = 0; i < EMLXS_MAX_RXQS; i++) {
7256                 mutex_destroy(&hba->sli.sli4.rxq[i].lock);
7257                 bzero(&hba->sli.sli4.rxq[i], sizeof (RXQ_DESC_t));
7258         }
7259         for (i = 0; i < EMLXS_MAX_RQS; i++) {
7260                 mutex_destroy(&hba->sli.sli4.rq[i].lock);
7261                 bzero(&hba->sli.sli4.rq[i], sizeof (RQ_DESC_t));
7262                 hba->sli.sli4.rq[i].qid = 0xffff;
7263         }
7264 
7265         /* Free the MQ */
7266         bzero(&hba->sli.sli4.mq, sizeof (MQ_DESC_t));
7267 
7268         buf_info = &hba->sli.sli4.slim2;
7269         if (buf_info->virt) {
7270                 buf_info->flags = FC_MBUF_DMA;
7271                 emlxs_mem_free(hba, buf_info);
7272                 bzero(buf_info, sizeof (MBUF_INFO));
7273         }
7274 
7275 } /* emlxs_sli4_resource_free() */
7276 
7277 
7278 static int
7279 emlxs_sli4_resource_alloc(emlxs_hba_t *hba)
7280 {
7281         emlxs_port_t    *port = &PPORT;
7282         emlxs_config_t  *cfg = &CFG;
7283         MBUF_INFO       *buf_info;
7284         int             num_eq;
7285         int             num_wq;
7286         uint16_t        i;
7287         uint32_t        j;
7288         uint32_t        k;
7289         uint16_t        cq_depth;
7290         uint32_t        cq_size;
7291         uint32_t        word;
7292         XRIobj_t        *xrip;
7293         RQE_t           *rqe;
7294         MBUF_INFO       *rqb;
7295         uint64_t        phys;
7296         uint64_t        tmp_phys;
7297         char            *virt;
7298         char            *tmp_virt;
7299         void            *data_handle;
7300         void            *dma_handle;
7301         int32_t         size;
7302         off_t           offset;
7303         uint32_t        count = 0;
7304         uint32_t        hddr_size = 0;
7305         uint32_t        align;
7306         uint32_t        iotag;
7307 
7308         buf_info = &hba->sli.sli4.slim2;
7309         if (buf_info->virt) {
7310                 /* Already allocated */
7311                 return (0);
7312         }
7313 
7314         emlxs_fcf_init(hba);
7315 
7316         switch (hba->sli.sli4.param.CQV) {
7317         case 0:
7318                 cq_depth = CQ_DEPTH;
7319                 break;
7320         case 2:
7321         default:
7322                 cq_depth = CQ_DEPTH_V2;
7323                 break;
7324         }
7325         cq_size = (cq_depth * CQE_SIZE);
7326 
7327         /* EQs - 1 per Interrupt vector */
7328         num_eq = hba->intr_count;
7329 
7330         /* CQs  - number of WQs + 1 for RQs + 1 for mbox/async events */
7331         num_wq = cfg[CFG_NUM_WQ].current * num_eq;
7332 
7333         /* Calculate total dmable memory we need */
7334         /* WARNING: make sure each section is aligned on 4K boundary */
7335 
7336         /* EQ */
7337         count += num_eq * 4096;
7338 
7339         /* CQ */
7340         count += (num_wq + EMLXS_CQ_OFFSET_WQ) * cq_size;
7341 
7342         /* WQ */
7343         count += num_wq * (4096 * EMLXS_NUM_WQ_PAGES);
7344 
7345         /* MQ */
7346         count +=  EMLXS_MAX_MQS * 4096;
7347 
7348         /* RQ */
7349         count +=  EMLXS_MAX_RQS * 4096;
7350 
7351         /* RQB/E */
7352         count += RQB_COUNT * (RQB_DATA_SIZE + RQB_HEADER_SIZE);
7353         count += (4096 - (count%4096)); /* Ensure 4K alignment */
7354 
7355         /* SGL */
7356         count += hba->sli.sli4.XRIExtSize * hba->sli.sli4.mem_sgl_size;
7357         count += (4096 - (count%4096)); /* Ensure 4K alignment */
7358 
7359         /* RPI Header Templates */
7360         if (hba->sli.sli4.param.HDRR) {
7361                 /* Bytes per extent */
7362                 j = hba->sli.sli4.RPIExtSize * sizeof (RPIHdrTmplate_t);
7363 
7364                 /* Pages required per extent (page == 4096 bytes) */
7365                 k = (j/4096) + ((j%4096)? 1:0);
7366 
7367                 /* Total size */
7368                 hddr_size = (k * hba->sli.sli4.RPIExtCount * 4096);
7369 
7370                 count += hddr_size;
7371         }
7372 
7373         /* Allocate slim2 for SLI4 */
7374         buf_info = &hba->sli.sli4.slim2;
7375         buf_info->size = count;
7376         buf_info->flags = FC_MBUF_DMA | FC_MBUF_SNGLSG | FC_MBUF_DMA32;
7377         buf_info->align = ddi_ptob(hba->dip, 1L);
7378 
7379         (void) emlxs_mem_alloc(hba, buf_info);
7380 
7381         if (buf_info->virt == NULL) {
7382                 EMLXS_MSGF(EMLXS_CONTEXT,
7383                     &emlxs_init_failed_msg,
7384                     "Unable to allocate internal memory for SLI4: %d",
7385                     count);
7386                 goto failed;
7387         }
7388         bzero(buf_info->virt, buf_info->size);
7389         EMLXS_MPDATA_SYNC(buf_info->dma_handle, 0,
7390             buf_info->size, DDI_DMA_SYNC_FORDEV);
7391 
7392         /* Assign memory to SGL, Head Template, EQ, CQ, WQ, RQ and MQ */
7393         data_handle = buf_info->data_handle;
7394         dma_handle = buf_info->dma_handle;
7395         phys = buf_info->phys;
7396         virt = (char *)buf_info->virt;
7397 
7398         /* Allocate space for queues */
7399 
7400         /* EQ */
7401         size = 4096;
7402         for (i = 0; i < num_eq; i++) {
7403                 bzero(&hba->sli.sli4.eq[i], sizeof (EQ_DESC_t));
7404 
7405                 buf_info = &hba->sli.sli4.eq[i].addr;
7406                 buf_info->size = size;
7407                 buf_info->flags =
7408                     FC_MBUF_DMA | FC_MBUF_SNGLSG | FC_MBUF_DMA32;
7409                 buf_info->align = ddi_ptob(hba->dip, 1L);
7410                 buf_info->phys = phys;
7411                 buf_info->virt = (void *)virt;
7412                 buf_info->data_handle = data_handle;
7413                 buf_info->dma_handle = dma_handle;
7414 
7415                 phys += size;
7416                 virt += size;
7417 
7418                 hba->sli.sli4.eq[i].max_index = EQ_DEPTH;
7419                 hba->sli.sli4.eq[i].qid = 0xffff;
7420 
7421                 mutex_init(&hba->sli.sli4.eq[i].lastwq_lock, NULL,
7422                     MUTEX_DRIVER, NULL);
7423         }
7424 
7425 
7426         /* CQ */
7427         for (i = 0; i < (num_wq + EMLXS_CQ_OFFSET_WQ); i++) {
7428                 bzero(&hba->sli.sli4.cq[i], sizeof (CQ_DESC_t));
7429 
7430                 buf_info = &hba->sli.sli4.cq[i].addr;
7431                 buf_info->size = cq_size;
7432                 buf_info->flags =
7433                     FC_MBUF_DMA | FC_MBUF_SNGLSG | FC_MBUF_DMA32;
7434                 buf_info->align = ddi_ptob(hba->dip, 1L);
7435                 buf_info->phys = phys;
7436                 buf_info->virt = (void *)virt;
7437                 buf_info->data_handle = data_handle;
7438                 buf_info->dma_handle = dma_handle;
7439 
7440                 phys += cq_size;
7441                 virt += cq_size;
7442 
7443                 hba->sli.sli4.cq[i].max_index = cq_depth;
7444                 hba->sli.sli4.cq[i].qid = 0xffff;
7445         }
7446 
7447 
7448         /* WQ */
7449         size = 4096 * EMLXS_NUM_WQ_PAGES;
7450         for (i = 0; i < num_wq; i++) {
7451                 bzero(&hba->sli.sli4.wq[i], sizeof (WQ_DESC_t));
7452 
7453                 buf_info = &hba->sli.sli4.wq[i].addr;
7454                 buf_info->size = size;
7455                 buf_info->flags =
7456                     FC_MBUF_DMA | FC_MBUF_SNGLSG | FC_MBUF_DMA32;
7457                 buf_info->align = ddi_ptob(hba->dip, 1L);
7458                 buf_info->phys = phys;
7459                 buf_info->virt = (void *)virt;
7460                 buf_info->data_handle = data_handle;
7461                 buf_info->dma_handle = dma_handle;
7462 
7463                 phys += size;
7464                 virt += size;
7465 
7466                 hba->sli.sli4.wq[i].max_index = WQ_DEPTH;
7467                 hba->sli.sli4.wq[i].release_depth = WQE_RELEASE_DEPTH;
7468                 hba->sli.sli4.wq[i].qid = 0xFFFF;
7469         }
7470 
7471 
7472         /* MQ */
7473         size = 4096;
7474         bzero(&hba->sli.sli4.mq, sizeof (MQ_DESC_t));
7475 
7476         buf_info = &hba->sli.sli4.mq.addr;
7477         buf_info->size = size;
7478         buf_info->flags =
7479             FC_MBUF_DMA | FC_MBUF_SNGLSG | FC_MBUF_DMA32;
7480         buf_info->align = ddi_ptob(hba->dip, 1L);
7481         buf_info->phys = phys;
7482         buf_info->virt = (void *)virt;
7483         buf_info->data_handle = data_handle;
7484         buf_info->dma_handle = dma_handle;
7485 
7486         phys += size;
7487         virt += size;
7488 
7489         hba->sli.sli4.mq.max_index = MQ_DEPTH;
7490 
7491 
7492         /* RXQ */
7493         for (i = 0; i < EMLXS_MAX_RXQS; i++) {
7494                 bzero(&hba->sli.sli4.rxq[i], sizeof (RXQ_DESC_t));
7495 
7496                 mutex_init(&hba->sli.sli4.rxq[i].lock, NULL, MUTEX_DRIVER,
7497                     NULL);
7498         }
7499 
7500 
7501         /* RQ */
7502         size = 4096;
7503         for (i = 0; i < EMLXS_MAX_RQS; i++) {
7504                 bzero(&hba->sli.sli4.rq[i], sizeof (RQ_DESC_t));
7505 
7506                 buf_info = &hba->sli.sli4.rq[i].addr;
7507                 buf_info->size = size;
7508                 buf_info->flags =
7509                     FC_MBUF_DMA | FC_MBUF_SNGLSG | FC_MBUF_DMA32;
7510                 buf_info->align = ddi_ptob(hba->dip, 1L);
7511                 buf_info->phys = phys;
7512                 buf_info->virt = (void *)virt;
7513                 buf_info->data_handle = data_handle;
7514                 buf_info->dma_handle = dma_handle;
7515 
7516                 phys += size;
7517                 virt += size;
7518 
7519                 hba->sli.sli4.rq[i].max_index = RQ_DEPTH;
7520                 hba->sli.sli4.rq[i].qid = 0xFFFF;
7521 
7522                 mutex_init(&hba->sli.sli4.rq[i].lock, NULL, MUTEX_DRIVER, NULL);
7523         }
7524 
7525 
7526         /* RQB/E */
7527         for (i = 0; i < EMLXS_MAX_RQS; i++) {
7528                 size = (i & 0x1) ? RQB_DATA_SIZE : RQB_HEADER_SIZE;
7529                 tmp_phys = phys;
7530                 tmp_virt = virt;
7531 
7532                 /* Initialize the RQEs */
7533                 rqe = (RQE_t *)hba->sli.sli4.rq[i].addr.virt;
7534                 for (j = 0; j < (RQ_DEPTH/RQB_COUNT); j++) {
7535                         phys = tmp_phys;
7536                         virt = tmp_virt;
7537                         for (k = 0; k < RQB_COUNT; k++) {
7538                                 word = PADDR_HI(phys);
7539                                 rqe->AddrHi = BE_SWAP32(word);
7540 
7541                                 word = PADDR_LO(phys);
7542                                 rqe->AddrLo = BE_SWAP32(word);
7543 
7544                                 rqb = &hba->sli.sli4.rq[i].
7545                                     rqb[k + (j * RQB_COUNT)];
7546                                 rqb->size = size;
7547                                 rqb->flags = FC_MBUF_DMA |
7548                                     FC_MBUF_SNGLSG | FC_MBUF_DMA32;
7549                                 rqb->align = ddi_ptob(hba->dip, 1L);
7550                                 rqb->phys = phys;
7551                                 rqb->virt = (void *)virt;
7552                                 rqb->data_handle = data_handle;
7553                                 rqb->dma_handle = dma_handle;
7554 
7555                                 phys += size;
7556                                 virt += size;
7557 #ifdef DEBUG_RQE
7558                                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
7559                                     "RQ_ALLOC: rq[%d] rqb[%d,%d]=%p iotag=%d",
7560                                     i, j, k, mp, mp->tag);
7561 #endif /* DEBUG_RQE */
7562 
7563                                 rqe++;
7564                         }
7565                 }
7566 
7567                 offset = (off_t)((uint64_t)((unsigned long)
7568                     hba->sli.sli4.rq[i].addr.virt) -
7569                     (uint64_t)((unsigned long)
7570                     hba->sli.sli4.slim2.virt));
7571 
7572                 /* Sync the RQ buffer list */
7573                 EMLXS_MPDATA_SYNC(hba->sli.sli4.rq[i].addr.dma_handle, offset,
7574                     hba->sli.sli4.rq[i].addr.size, DDI_DMA_SYNC_FORDEV);
7575         }
7576 
7577         /* 4K Alignment */
7578         align = (4096 - (phys%4096));
7579         phys += align;
7580         virt += align;
7581 
7582         /* SGL */
7583         /* Initialize double linked lists */
7584         hba->sli.sli4.XRIinuse_f =
7585             (XRIobj_t *)&hba->sli.sli4.XRIinuse_f;
7586         hba->sli.sli4.XRIinuse_b =
7587             (XRIobj_t *)&hba->sli.sli4.XRIinuse_f;
7588         hba->sli.sli4.xria_count = 0;
7589 
7590         hba->sli.sli4.XRIfree_f =
7591             (XRIobj_t *)&hba->sli.sli4.XRIfree_f;
7592         hba->sli.sli4.XRIfree_b =
7593             (XRIobj_t *)&hba->sli.sli4.XRIfree_f;
7594         hba->sli.sli4.xria_count = 0;
7595 
7596         hba->sli.sli4.XRIp = (XRIobj_t *)kmem_zalloc(
7597             (sizeof (XRIobj_t) * hba->sli.sli4.XRICount), KM_SLEEP);
7598 
7599         xrip = hba->sli.sli4.XRIp;
7600         size = hba->sli.sli4.mem_sgl_size;
7601         iotag = 1;
7602         for (i = 0; i < hba->sli.sli4.XRICount; i++) {
7603                 xrip->XRI = emlxs_sli4_index_to_xri(hba, i);
7604 
7605                 /* We don't use XRI==0, since it also represents an */
7606                 /* uninitialized exchange */
7607                 if (xrip->XRI == 0) {
7608                         xrip++;
7609                         continue;
7610                 }
7611 
7612                 xrip->iotag = iotag++;
7613                 xrip->sge_count =
7614                     (hba->sli.sli4.mem_sgl_size / sizeof (ULP_SGE64));
7615 
7616                 /* Add xrip to end of free list */
7617                 xrip->_b = hba->sli.sli4.XRIfree_b;
7618                 hba->sli.sli4.XRIfree_b->_f = xrip;
7619                 xrip->_f = (XRIobj_t *)&hba->sli.sli4.XRIfree_f;
7620                 hba->sli.sli4.XRIfree_b = xrip;
7621                 hba->sli.sli4.xrif_count++;
7622 
7623                 /* Allocate SGL for this xrip */
7624                 buf_info = &xrip->SGList;
7625                 buf_info->size = size;
7626                 buf_info->flags =
7627                     FC_MBUF_DMA | FC_MBUF_SNGLSG | FC_MBUF_DMA32;
7628                 buf_info->align = size;
7629                 buf_info->phys = phys;
7630                 buf_info->virt = (void *)virt;
7631                 buf_info->data_handle = data_handle;
7632                 buf_info->dma_handle = dma_handle;
7633 
7634                 phys += size;
7635                 virt += size;
7636 
7637                 xrip++;
7638         }
7639 
7640         /* 4K Alignment */
7641         align = (4096 - (phys%4096));
7642         phys += align;
7643         virt += align;
7644 
7645         /* RPI Header Templates */
7646         if (hba->sli.sli4.param.HDRR) {
7647                 buf_info = &hba->sli.sli4.HeaderTmplate;
7648                 bzero(buf_info, sizeof (MBUF_INFO));
7649                 buf_info->size = hddr_size;
7650                 buf_info->flags = FC_MBUF_DMA | FC_MBUF_DMA32;
7651                 buf_info->align = ddi_ptob(hba->dip, 1L);
7652                 buf_info->phys = phys;
7653                 buf_info->virt = (void *)virt;
7654                 buf_info->data_handle = data_handle;
7655                 buf_info->dma_handle = dma_handle;
7656         }
7657 
7658 #ifdef FMA_SUPPORT
7659         if (hba->sli.sli4.slim2.dma_handle) {
7660                 if (emlxs_fm_check_dma_handle(hba,
7661                     hba->sli.sli4.slim2.dma_handle)
7662                     != DDI_FM_OK) {
7663                         EMLXS_MSGF(EMLXS_CONTEXT,
7664                             &emlxs_invalid_dma_handle_msg,
7665                             "sli4_resource_alloc: hdl=%p",
7666                             hba->sli.sli4.slim2.dma_handle);
7667                         goto failed;
7668                 }
7669         }
7670 #endif /* FMA_SUPPORT */
7671 
7672         return (0);
7673 
7674 failed:
7675 
7676         (void) emlxs_sli4_resource_free(hba);
7677         return (ENOMEM);
7678 
7679 } /* emlxs_sli4_resource_alloc */
7680 
7681 
7682 extern void
7683 emlxs_sli4_zero_queue_stat(emlxs_hba_t *hba)
7684 {
7685         uint32_t i;
7686         uint32_t num_wq;
7687         emlxs_config_t  *cfg = &CFG;
7688         clock_t         time;
7689 
7690         /* EQ */
7691         for (i = 0; i < hba->intr_count; i++) {
7692                 hba->sli.sli4.eq[i].num_proc = 0;
7693                 hba->sli.sli4.eq[i].max_proc = 0;
7694                 hba->sli.sli4.eq[i].isr_count = 0;
7695         }
7696         num_wq = cfg[CFG_NUM_WQ].current * hba->intr_count;
7697         /* CQ */
7698         for (i = 0; i < (num_wq + EMLXS_CQ_OFFSET_WQ); i++) {
7699                 hba->sli.sli4.cq[i].num_proc = 0;
7700                 hba->sli.sli4.cq[i].max_proc = 0;
7701                 hba->sli.sli4.cq[i].isr_count = 0;
7702         }
7703         /* WQ */
7704         for (i = 0; i < num_wq; i++) {
7705                 hba->sli.sli4.wq[i].num_proc = 0;
7706                 hba->sli.sli4.wq[i].num_busy = 0;
7707         }
7708         /* RQ */
7709         for (i = 0; i < EMLXS_MAX_RQS; i++) {
7710                 hba->sli.sli4.rq[i].num_proc = 0;
7711         }
7712         (void) drv_getparm(LBOLT, &time);
7713         hba->sli.sli4.que_stat_timer = (uint32_t)time;
7714 
7715 } /* emlxs_sli4_zero_queue_stat */
7716 
7717 
7718 extern XRIobj_t *
7719 emlxs_sli4_reserve_xri(emlxs_port_t *port,  RPIobj_t *rpip, uint32_t type,
7720     uint16_t rx_id)
7721 {
7722         emlxs_hba_t *hba = HBA;
7723         XRIobj_t        *xrip;
7724         uint16_t        iotag;
7725 
7726         mutex_enter(&EMLXS_FCTAB_LOCK);
7727 
7728         xrip = hba->sli.sli4.XRIfree_f;
7729 
7730         if (xrip == (XRIobj_t *)&hba->sli.sli4.XRIfree_f) {
7731                 mutex_exit(&EMLXS_FCTAB_LOCK);
7732 
7733                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_err_msg,
7734                     "Unable to reserve XRI. type=%d",
7735                     type);
7736 
7737                 return (NULL);
7738         }
7739 
7740         iotag = xrip->iotag;
7741 
7742         if ((!iotag) ||
7743             ((hba->fc_table[iotag] != NULL) &&
7744             (hba->fc_table[iotag] != STALE_PACKET))) {
7745                 /*
7746                  * No more command slots available, retry later
7747                  */
7748                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_trans_msg,
7749                     "Adapter Busy. Unable to reserve iotag. type=%d",
7750                     type);
7751 
7752                 mutex_exit(&EMLXS_FCTAB_LOCK);
7753                 return (NULL);
7754         }
7755 
7756         xrip->state = XRI_STATE_ALLOCATED;
7757         xrip->type = type;
7758         xrip->flag = EMLXS_XRI_RESERVED;
7759         xrip->sbp = NULL;
7760 
7761         xrip->rpip = rpip;
7762         xrip->rx_id = rx_id;
7763         rpip->xri_count++;
7764 
7765         /* Take it off free list */
7766         (xrip->_b)->_f = xrip->_f;
7767         (xrip->_f)->_b = xrip->_b;
7768         xrip->_f = NULL;
7769         xrip->_b = NULL;
7770         hba->sli.sli4.xrif_count--;
7771 
7772         /* Add it to end of inuse list */
7773         xrip->_b = hba->sli.sli4.XRIinuse_b;
7774         hba->sli.sli4.XRIinuse_b->_f = xrip;
7775         xrip->_f = (XRIobj_t *)&hba->sli.sli4.XRIinuse_f;
7776         hba->sli.sli4.XRIinuse_b = xrip;
7777         hba->sli.sli4.xria_count++;
7778 
7779         mutex_exit(&EMLXS_FCTAB_LOCK);
7780         return (xrip);
7781 
7782 } /* emlxs_sli4_reserve_xri() */
7783 
7784 
7785 extern uint32_t
7786 emlxs_sli4_unreserve_xri(emlxs_port_t *port, uint16_t xri, uint32_t lock)
7787 {
7788         emlxs_hba_t *hba = HBA;
7789         XRIobj_t *xrip;
7790 
7791         if (lock) {
7792                 mutex_enter(&EMLXS_FCTAB_LOCK);
7793         }
7794 
7795         xrip = emlxs_sli4_find_xri(port, xri);
7796 
7797         if (!xrip || xrip->state == XRI_STATE_FREE) {
7798                 if (lock) {
7799                         mutex_exit(&EMLXS_FCTAB_LOCK);
7800                 }
7801 
7802                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
7803                     "sli4_unreserve_xri:%d already freed.", xri);
7804                 return (0);
7805         }
7806 
7807         /* Flush this unsolicited ct command */
7808         if (xrip->type == EMLXS_XRI_UNSOL_CT_TYPE) {
7809                 (void) emlxs_flush_ct_event(port, xrip->rx_id);
7810         }
7811 
7812         if (!(xrip->flag & EMLXS_XRI_RESERVED)) {
7813                 if (lock) {
7814                         mutex_exit(&EMLXS_FCTAB_LOCK);
7815                 }
7816 
7817                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
7818                     "sli4_unreserve_xri:%d in use. type=%d",
7819                     xrip->XRI, xrip->type);
7820                 return (1);
7821         }
7822 
7823         if (xrip->iotag &&
7824             (hba->fc_table[xrip->iotag] != NULL) &&
7825             (hba->fc_table[xrip->iotag] != STALE_PACKET)) {
7826                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_err_msg,
7827                     "sli4_unreserve_xri:%d  sbp dropped:%p type=%d",
7828                     xrip->XRI, hba->fc_table[xrip->iotag], xrip->type);
7829 
7830                 hba->fc_table[xrip->iotag] = NULL;
7831                 hba->io_count--;
7832         }
7833 
7834         EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
7835             "sli4_unreserve_xri:%d unreserved. type=%d",
7836             xrip->XRI, xrip->type);
7837 
7838         xrip->state = XRI_STATE_FREE;
7839         xrip->type = 0;
7840 
7841         if (xrip->rpip) {
7842                 xrip->rpip->xri_count--;
7843                 xrip->rpip = NULL;
7844         }
7845 
7846         if (xrip->reserved_rpip) {
7847                 xrip->reserved_rpip->xri_count--;
7848                 xrip->reserved_rpip = NULL;
7849         }
7850 
7851         /* Take it off inuse list */
7852         (xrip->_b)->_f = xrip->_f;
7853         (xrip->_f)->_b = xrip->_b;
7854         xrip->_f = NULL;
7855         xrip->_b = NULL;
7856         hba->sli.sli4.xria_count--;
7857 
7858         /* Add it to end of free list */
7859         xrip->_b = hba->sli.sli4.XRIfree_b;
7860         hba->sli.sli4.XRIfree_b->_f = xrip;
7861         xrip->_f = (XRIobj_t *)&hba->sli.sli4.XRIfree_f;
7862         hba->sli.sli4.XRIfree_b = xrip;
7863         hba->sli.sli4.xrif_count++;
7864 
7865         if (lock) {
7866                 mutex_exit(&EMLXS_FCTAB_LOCK);
7867         }
7868 
7869         return (0);
7870 
7871 } /* emlxs_sli4_unreserve_xri() */
7872 
7873 
7874 XRIobj_t *
7875 emlxs_sli4_register_xri(emlxs_port_t *port, emlxs_buf_t *sbp, uint16_t xri,
7876     uint32_t did)
7877 {
7878         emlxs_hba_t *hba = HBA;
7879         uint16_t        iotag;
7880         XRIobj_t        *xrip;
7881         emlxs_node_t    *node;
7882         RPIobj_t        *rpip;
7883 
7884         mutex_enter(&EMLXS_FCTAB_LOCK);
7885 
7886         xrip = sbp->xrip;
7887         if (!xrip) {
7888                 xrip = emlxs_sli4_find_xri(port, xri);
7889 
7890                 if (!xrip) {
7891                         EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_trans_msg,
7892                             "sli4_register_xri:%d XRI not found.", xri);
7893 
7894                         mutex_exit(&EMLXS_FCTAB_LOCK);
7895                         return (NULL);
7896                 }
7897         }
7898 
7899         if ((xrip->state == XRI_STATE_FREE) ||
7900             !(xrip->flag & EMLXS_XRI_RESERVED)) {
7901 
7902                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_trans_msg,
7903                     "sli4_register_xri:%d Invalid XRI. xrip=%p "
7904                     "state=%x flag=%x",
7905                     xrip->XRI, xrip, xrip->state, xrip->flag);
7906 
7907                 mutex_exit(&EMLXS_FCTAB_LOCK);
7908                 return (NULL);
7909         }
7910 
7911         iotag = xrip->iotag;
7912 
7913         if ((!iotag) ||
7914             ((hba->fc_table[iotag] != NULL) &&
7915             (hba->fc_table[iotag] != STALE_PACKET))) {
7916 
7917                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_trans_msg,
7918                     "sli4_register_xri:%d Invalid fc_table entry. "
7919                     "iotag=%d entry=%p",
7920                     xrip->XRI, iotag, hba->fc_table[iotag]);
7921 
7922                 mutex_exit(&EMLXS_FCTAB_LOCK);
7923                 return (NULL);
7924         }
7925 
7926         hba->fc_table[iotag] = sbp;
7927         hba->io_count++;
7928 
7929         sbp->iotag = iotag;
7930         sbp->xrip = xrip;
7931 
7932         xrip->flag &= ~EMLXS_XRI_RESERVED;
7933         xrip->sbp = sbp;
7934 
7935         /* If we did not have a registered RPI when we reserved */
7936         /* this exchange, check again now. */
7937         if (xrip->rpip && (xrip->rpip->RPI == FABRIC_RPI)) {
7938                 node = emlxs_node_find_did(port, did, 1);
7939                 rpip = EMLXS_NODE_TO_RPI(port, node);
7940 
7941                 if (rpip && (rpip->RPI != FABRIC_RPI)) {
7942                         /* Move the XRI to the new RPI */
7943                         xrip->rpip->xri_count--;
7944                         xrip->rpip = rpip;
7945                         rpip->xri_count++;
7946                 }
7947         }
7948 
7949         mutex_exit(&EMLXS_FCTAB_LOCK);
7950 
7951         return (xrip);
7952 
7953 } /* emlxs_sli4_register_xri() */
7954 
7955 
7956 /* Performs both reserve and register functions for XRI */
7957 static XRIobj_t *
7958 emlxs_sli4_alloc_xri(emlxs_port_t *port, emlxs_buf_t *sbp, RPIobj_t *rpip,
7959     uint32_t type)
7960 {
7961         emlxs_hba_t *hba = HBA;
7962         XRIobj_t        *xrip;
7963         uint16_t        iotag;
7964 
7965         mutex_enter(&EMLXS_FCTAB_LOCK);
7966 
7967         xrip = hba->sli.sli4.XRIfree_f;
7968 
7969         if (xrip == (XRIobj_t *)&hba->sli.sli4.XRIfree_f) {
7970                 mutex_exit(&EMLXS_FCTAB_LOCK);
7971 
7972                 return (NULL);
7973         }
7974 
7975         /* Get the iotag by registering the packet */
7976         iotag = xrip->iotag;
7977 
7978         if ((!iotag) ||
7979             ((hba->fc_table[iotag] != NULL) &&
7980             (hba->fc_table[iotag] != STALE_PACKET))) {
7981                 /*
7982                  * No more command slots available, retry later
7983                  */
7984                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_trans_msg,
7985                     "Adapter Busy. Unable to alloc iotag:(0x%x)(%p) type=%d",
7986                     iotag, hba->fc_table[iotag], type);
7987 
7988                 mutex_exit(&EMLXS_FCTAB_LOCK);
7989                 return (NULL);
7990         }
7991 
7992         hba->fc_table[iotag] = sbp;
7993         hba->io_count++;
7994 
7995         sbp->iotag = iotag;
7996         sbp->xrip = xrip;
7997 
7998         xrip->state = XRI_STATE_ALLOCATED;
7999         xrip->type = type;
8000         xrip->flag = 0;
8001         xrip->sbp = sbp;
8002 
8003         xrip->rpip = rpip;
8004         rpip->xri_count++;
8005 
8006         /* Take it off free list */
8007         (xrip->_b)->_f = xrip->_f;
8008         (xrip->_f)->_b = xrip->_b;
8009         xrip->_f = NULL;
8010         xrip->_b = NULL;
8011         hba->sli.sli4.xrif_count--;
8012 
8013         /* Add it to end of inuse list */
8014         xrip->_b = hba->sli.sli4.XRIinuse_b;
8015         hba->sli.sli4.XRIinuse_b->_f = xrip;
8016         xrip->_f = (XRIobj_t *)&hba->sli.sli4.XRIinuse_f;
8017         hba->sli.sli4.XRIinuse_b = xrip;
8018         hba->sli.sli4.xria_count++;
8019 
8020         mutex_exit(&EMLXS_FCTAB_LOCK);
8021 
8022         return (xrip);
8023 
8024 } /* emlxs_sli4_alloc_xri() */
8025 
8026 
8027 /* EMLXS_FCTAB_LOCK must be held to enter */
8028 extern XRIobj_t *
8029 emlxs_sli4_find_xri(emlxs_port_t *port, uint16_t xri)
8030 {
8031         emlxs_hba_t *hba = HBA;
8032         XRIobj_t        *xrip;
8033 
8034         xrip = (XRIobj_t *)hba->sli.sli4.XRIinuse_f;
8035         while (xrip != (XRIobj_t *)&hba->sli.sli4.XRIinuse_f) {
8036                 if ((xrip->state >= XRI_STATE_ALLOCATED) &&
8037                     (xrip->XRI == xri)) {
8038                         return (xrip);
8039                 }
8040                 xrip = xrip->_f;
8041         }
8042 
8043         EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
8044             "Unable to find XRI x%x", xri);
8045 
8046         return (NULL);
8047 
8048 } /* emlxs_sli4_find_xri() */
8049 
8050 
8051 
8052 
8053 extern void
8054 emlxs_sli4_free_xri(emlxs_port_t *port, emlxs_buf_t *sbp, XRIobj_t *xrip,
8055     uint8_t lock)
8056 {
8057         emlxs_hba_t *hba = HBA;
8058 
8059         if (lock) {
8060                 mutex_enter(&EMLXS_FCTAB_LOCK);
8061         }
8062 
8063         if (xrip) {
8064                 if (xrip->state == XRI_STATE_FREE) {
8065                         if (lock) {
8066                                 mutex_exit(&EMLXS_FCTAB_LOCK);
8067                         }
8068                         EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
8069                             "Free XRI:%x, Already freed. type=%d",
8070                             xrip->XRI, xrip->type);
8071                         return;
8072                 }
8073 
8074                 if (xrip->type == EMLXS_XRI_UNSOL_CT_TYPE) {
8075                         (void) emlxs_flush_ct_event(port, xrip->rx_id);
8076                 }
8077 
8078                 if (xrip->iotag &&
8079                     (hba->fc_table[xrip->iotag] != NULL) &&
8080                     (hba->fc_table[xrip->iotag] != STALE_PACKET)) {
8081                         hba->fc_table[xrip->iotag] = NULL;
8082                         hba->io_count--;
8083                 }
8084 
8085                 xrip->state = XRI_STATE_FREE;
8086                 xrip->type  = 0;
8087                 xrip->flag  = 0;
8088 
8089                 if (xrip->rpip) {
8090                         xrip->rpip->xri_count--;
8091                         xrip->rpip = NULL;
8092                 }
8093 
8094                 if (xrip->reserved_rpip) {
8095                         xrip->reserved_rpip->xri_count--;
8096                         xrip->reserved_rpip = NULL;
8097                 }
8098 
8099                 /* Take it off inuse list */
8100                 (xrip->_b)->_f = xrip->_f;
8101                 (xrip->_f)->_b = xrip->_b;
8102                 xrip->_f = NULL;
8103                 xrip->_b = NULL;
8104                 hba->sli.sli4.xria_count--;
8105 
8106                 /* Add it to end of free list */
8107                 xrip->_b = hba->sli.sli4.XRIfree_b;
8108                 hba->sli.sli4.XRIfree_b->_f = xrip;
8109                 xrip->_f = (XRIobj_t *)&hba->sli.sli4.XRIfree_f;
8110                 hba->sli.sli4.XRIfree_b = xrip;
8111                 hba->sli.sli4.xrif_count++;
8112         }
8113 
8114         if (sbp) {
8115                 if (!(sbp->pkt_flags & PACKET_VALID) ||
8116                     (sbp->pkt_flags &
8117                     (PACKET_ULP_OWNED|PACKET_COMPLETED|PACKET_IN_COMPLETION))) {
8118                         if (lock) {
8119                                 mutex_exit(&EMLXS_FCTAB_LOCK);
8120                         }
8121                         EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
8122                             "Free XRI: sbp invalid. sbp=%p flags=%x xri=%d",
8123                             sbp, sbp->pkt_flags, ((xrip)? xrip->XRI:0));
8124                         return;
8125                 }
8126 
8127                 if (xrip && (xrip->iotag != sbp->iotag)) {
8128                         EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_debug_msg,
8129                             "sbp/iotag mismatch %p iotag:%d %d", sbp,
8130                             sbp->iotag, xrip->iotag);
8131                 }
8132 
8133                 if (sbp->iotag) {
8134                         if (sbp == hba->fc_table[sbp->iotag]) {
8135                                 hba->fc_table[sbp->iotag] = NULL;
8136                                 hba->io_count--;
8137 
8138                                 if (sbp->xrip) {
8139                                         /* Exchange is still reserved */
8140                                         sbp->xrip->flag |= EMLXS_XRI_RESERVED;
8141                                 }
8142                         }
8143                         sbp->iotag = 0;
8144                 }
8145 
8146                 if (xrip) {
8147                         sbp->xrip = 0;
8148                 }
8149 
8150                 if (lock) {
8151                         mutex_exit(&EMLXS_FCTAB_LOCK);
8152                 }
8153 
8154                 /* Clean up the sbp */
8155                 mutex_enter(&sbp->mtx);
8156 
8157                 if (sbp->pkt_flags & PACKET_IN_TXQ) {
8158                         sbp->pkt_flags &= ~PACKET_IN_TXQ;
8159                         hba->channel_tx_count--;
8160                 }
8161 
8162                 if (sbp->pkt_flags & PACKET_IN_CHIPQ) {
8163                         sbp->pkt_flags &= ~PACKET_IN_CHIPQ;
8164                 }
8165 
8166                 mutex_exit(&sbp->mtx);
8167         } else {
8168                 if (lock) {
8169                         mutex_exit(&EMLXS_FCTAB_LOCK);
8170                 }
8171         }
8172 
8173 } /* emlxs_sli4_free_xri() */
8174 
8175 
8176 static int
8177 emlxs_sli4_post_sgl_pages(emlxs_hba_t *hba, MAILBOXQ *mbq)
8178 {
8179         MAILBOX4        *mb = (MAILBOX4 *)mbq;
8180         emlxs_port_t    *port = &PPORT;
8181         XRIobj_t        *xrip;
8182         MATCHMAP        *mp;
8183         mbox_req_hdr_t  *hdr_req;
8184         uint32_t        i;
8185         uint32_t        cnt;
8186         uint32_t        xri_cnt;
8187         uint32_t        j;
8188         uint32_t        size;
8189         IOCTL_FCOE_CFG_POST_SGL_PAGES *post_sgl;
8190 
8191         bzero((void *) mb, MAILBOX_CMD_SLI4_BSIZE);
8192         mbq->bp = NULL;
8193         mbq->mbox_cmpl = NULL;
8194 
8195         if ((mp = emlxs_mem_buf_alloc(hba, EMLXS_MAX_NONEMBED_SIZE)) == 0) {
8196                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
8197                     "Unable to POST_SGL. Mailbox cmd=%x  ",
8198                     mb->mbxCommand);
8199                 return (EIO);
8200         }
8201         mbq->nonembed = (void *)mp;
8202 
8203         /*
8204          * Signifies a non embedded command
8205          */
8206         mb->un.varSLIConfig.be.embedded = 0;
8207         mb->mbxCommand = MBX_SLI_CONFIG;
8208         mb->mbxOwner = OWN_HOST;
8209 
8210         hdr_req = (mbox_req_hdr_t *)mp->virt;
8211         post_sgl =
8212             (IOCTL_FCOE_CFG_POST_SGL_PAGES *)(hdr_req + 1);
8213 
8214         xrip = hba->sli.sli4.XRIp;
8215 
8216         /* For each extent */
8217         for (j = 0; j < hba->sli.sli4.XRIExtCount; j++) {
8218                 cnt = hba->sli.sli4.XRIExtSize;
8219                 while (cnt) {
8220                         if (xrip->XRI == 0) {
8221                                 cnt--;
8222                                 xrip++;
8223                                 continue;
8224                         }
8225 
8226                         bzero((void *) hdr_req, mp->size);
8227                         size = mp->size - IOCTL_HEADER_SZ;
8228 
8229                         mb->un.varSLIConfig.be.payload_length =
8230                             mp->size;
8231                         mb->un.varSLIConfig.be.un_hdr.hdr_req.subsystem =
8232                             IOCTL_SUBSYSTEM_FCOE;
8233                         mb->un.varSLIConfig.be.un_hdr.hdr_req.opcode =
8234                             FCOE_OPCODE_CFG_POST_SGL_PAGES;
8235                         mb->un.varSLIConfig.be.un_hdr.hdr_req.timeout = 0;
8236                         mb->un.varSLIConfig.be.un_hdr.hdr_req.req_length = size;
8237 
8238                         hdr_req->subsystem = IOCTL_SUBSYSTEM_FCOE;
8239                         hdr_req->opcode = FCOE_OPCODE_CFG_POST_SGL_PAGES;
8240                         hdr_req->timeout = 0;
8241                         hdr_req->req_length = size;
8242 
8243                         post_sgl->params.request.xri_count = 0;
8244                         post_sgl->params.request.xri_start = xrip->XRI;
8245 
8246                         xri_cnt = (size -
8247                             sizeof (IOCTL_FCOE_CFG_POST_SGL_PAGES)) /
8248                             sizeof (FCOE_SGL_PAGES);
8249 
8250                         for (i = 0; (i < xri_cnt) && cnt; i++) {
8251                                 post_sgl->params.request.xri_count++;
8252                                 post_sgl->params.request.pages[i].\
8253                                     sgl_page0.addrLow =
8254                                     PADDR_LO(xrip->SGList.phys);
8255                                 post_sgl->params.request.pages[i].\
8256                                     sgl_page0.addrHigh =
8257                                     PADDR_HI(xrip->SGList.phys);
8258 
8259                                 cnt--;
8260                                 xrip++;
8261                         }
8262 
8263                         if (emlxs_sli4_issue_mbox_cmd(hba, mbq, MBX_WAIT, 0) !=
8264                             MBX_SUCCESS) {
8265                                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
8266                                     "Unable to POST_SGL. Mailbox cmd=%x "
8267                                     "status=%x XRI cnt:%d start:%d",
8268                                     mb->mbxCommand, mb->mbxStatus,
8269                                     post_sgl->params.request.xri_count,
8270                                     post_sgl->params.request.xri_start);
8271                                 emlxs_mem_buf_free(hba, mp);
8272                                 mbq->nonembed = NULL;
8273                                 return (EIO);
8274                         }
8275                 }
8276         }
8277 
8278         emlxs_mem_buf_free(hba, mp);
8279         mbq->nonembed = NULL;
8280         return (0);
8281 
8282 } /* emlxs_sli4_post_sgl_pages() */
8283 
8284 
8285 static int
8286 emlxs_sli4_post_hdr_tmplates(emlxs_hba_t *hba, MAILBOXQ *mbq)
8287 {
8288         MAILBOX4        *mb = (MAILBOX4 *)mbq;
8289         emlxs_port_t    *port = &PPORT;
8290         uint32_t        j;
8291         uint32_t        k;
8292         uint64_t        addr;
8293         IOCTL_FCOE_POST_HDR_TEMPLATES *post_hdr;
8294         uint16_t        num_pages;
8295 
8296         if (!(hba->sli.sli4.param.HDRR)) {
8297                 return (0);
8298         }
8299 
8300         /* Bytes per extent */
8301         j = hba->sli.sli4.RPIExtSize * sizeof (RPIHdrTmplate_t);
8302 
8303         /* Pages required per extent (page == 4096 bytes) */
8304         num_pages = (j/4096) + ((j%4096)? 1:0);
8305 
8306         addr = hba->sli.sli4.HeaderTmplate.phys;
8307 
8308         /* For each extent */
8309         for (j = 0; j < hba->sli.sli4.RPIExtCount; j++) {
8310                 bzero((void *) mb, MAILBOX_CMD_SLI4_BSIZE);
8311                 mbq->bp = NULL;
8312                 mbq->mbox_cmpl = NULL;
8313 
8314                 /*
8315                  * Signifies an embedded command
8316                  */
8317                 mb->un.varSLIConfig.be.embedded = 1;
8318 
8319                 mb->mbxCommand = MBX_SLI_CONFIG;
8320                 mb->mbxOwner = OWN_HOST;
8321                 mb->un.varSLIConfig.be.payload_length =
8322                     sizeof (IOCTL_FCOE_POST_HDR_TEMPLATES) + IOCTL_HEADER_SZ;
8323                 mb->un.varSLIConfig.be.un_hdr.hdr_req.subsystem =
8324                     IOCTL_SUBSYSTEM_FCOE;
8325                 mb->un.varSLIConfig.be.un_hdr.hdr_req.opcode =
8326                     FCOE_OPCODE_POST_HDR_TEMPLATES;
8327                 mb->un.varSLIConfig.be.un_hdr.hdr_req.timeout = 0;
8328                 mb->un.varSLIConfig.be.un_hdr.hdr_req.req_length =
8329                     sizeof (IOCTL_FCOE_POST_HDR_TEMPLATES);
8330 
8331                 post_hdr =
8332                     (IOCTL_FCOE_POST_HDR_TEMPLATES *)
8333                     &mb->un.varSLIConfig.payload;
8334                 post_hdr->params.request.num_pages = num_pages;
8335                 post_hdr->params.request.rpi_offset = hba->sli.sli4.RPIBase[j];
8336 
8337                 for (k = 0; k < num_pages; k++) {
8338                         post_hdr->params.request.pages[k].addrLow =
8339                             PADDR_LO(addr);
8340                         post_hdr->params.request.pages[k].addrHigh =
8341                             PADDR_HI(addr);
8342                         addr += 4096;
8343                 }
8344 
8345                 if (emlxs_sli4_issue_mbox_cmd(hba, mbq, MBX_WAIT, 0) !=
8346                     MBX_SUCCESS) {
8347                         EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
8348                             "Unable to POST_HDR_TEMPLATES. Mailbox cmd=%x "
8349                             "status=%x ",
8350                             mb->mbxCommand, mb->mbxStatus);
8351                         return (EIO);
8352                 }
8353                 emlxs_data_dump(port, "POST_HDR", (uint32_t *)mb, 18, 0);
8354         }
8355 
8356         return (0);
8357 
8358 } /* emlxs_sli4_post_hdr_tmplates() */
8359 
8360 
8361 static int
8362 emlxs_sli4_create_queues(emlxs_hba_t *hba, MAILBOXQ *mbq)
8363 {
8364         MAILBOX4        *mb = (MAILBOX4 *)mbq;
8365         emlxs_port_t    *port = &PPORT;
8366         emlxs_config_t  *cfg = &CFG;
8367         IOCTL_COMMON_EQ_CREATE *eq;
8368         IOCTL_COMMON_CQ_CREATE *cq;
8369         IOCTL_FCOE_WQ_CREATE *wq;
8370         IOCTL_FCOE_RQ_CREATE *rq;
8371         IOCTL_COMMON_MQ_CREATE *mq;
8372         IOCTL_COMMON_MQ_CREATE_EXT *mq_ext;
8373         emlxs_rqdbu_t   rqdb;
8374         uint16_t i, j;
8375         uint16_t num_cq, total_cq;
8376         uint16_t num_wq, total_wq;
8377 
8378         /*
8379          * The first CQ is reserved for ASYNC events,
8380          * the second is reserved for unsol rcv, the rest
8381          * correspond to WQs. (WQ0 -> CQ2, WQ1 -> CQ3, ...)
8382          */
8383 
8384         total_cq = 0;
8385         total_wq = 0;
8386 
8387         /* Create EQ's */
8388         for (i = 0; i < hba->intr_count; i++) {
8389                 emlxs_mb_eq_create(hba, mbq, i);
8390                 if (emlxs_sli4_issue_mbox_cmd(hba, mbq, MBX_WAIT, 0) !=
8391                     MBX_SUCCESS) {
8392                         EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg,
8393                             "Unable to Create EQ %d: Mailbox cmd=%x status=%x ",
8394                             i, mb->mbxCommand, mb->mbxStatus);
8395                         return (EIO);
8396                 }
8397                 eq = (IOCTL_COMMON_EQ_CREATE *)&mb->un.varSLIConfig.payload;
8398                 hba->sli.sli4.eq[i].qid = eq->params.response.EQId;
8399                 hba->sli.sli4.eq[i].lastwq = total_wq;
8400                 hba->sli.sli4.eq[i].msix_vector = i;
8401 
8402                 emlxs_data_dump(port, "EQ0_CREATE", (uint32_t *)mb, 18, 0);
8403                 num_wq = cfg[CFG_NUM_WQ].current;
8404                 num_cq = num_wq;
8405                 if (i == 0) {
8406                         /* One for RQ handling, one for mbox/event handling */
8407                         num_cq += EMLXS_CQ_OFFSET_WQ;
8408                 }
8409 
8410                 /* Create CQ's */
8411                 for (j = 0; j < num_cq; j++) {
8412                         /* Reuse mbq from previous mbox */
8413                         bzero(mbq, sizeof (MAILBOXQ));
8414 
8415                         hba->sli.sli4.cq[total_cq].eqid =
8416                             hba->sli.sli4.eq[i].qid;
8417 
8418                         emlxs_mb_cq_create(hba, mbq, total_cq);
8419                         if (emlxs_sli4_issue_mbox_cmd(hba, mbq, MBX_WAIT, 0) !=
8420                             MBX_SUCCESS) {
8421                                 EMLXS_MSGF(EMLXS_CONTEXT,
8422                                     &emlxs_init_failed_msg, "Unable to Create "
8423                                     "CQ %d: Mailbox cmd=%x status=%x ",
8424                                     total_cq, mb->mbxCommand, mb->mbxStatus);
8425                                 return (EIO);
8426                         }
8427                         cq = (IOCTL_COMMON_CQ_CREATE *)
8428                             &mb->un.varSLIConfig.payload;
8429                         hba->sli.sli4.cq[total_cq].qid =
8430                             cq->params.response.CQId;
8431 
8432                         switch (total_cq) {
8433                         case EMLXS_CQ_MBOX:
8434                                 /* First CQ is for async event handling */
8435                                 hba->sli.sli4.cq[total_cq].type =
8436                                     EMLXS_CQ_TYPE_GROUP1;
8437                                 break;
8438 
8439                         case EMLXS_CQ_RCV:
8440                                 /* Second CQ is for unsol receive handling */
8441                                 hba->sli.sli4.cq[total_cq].type =
8442                                     EMLXS_CQ_TYPE_GROUP2;
8443                                 break;
8444 
8445                         default:
8446                                 /* Setup CQ to channel mapping */
8447                                 hba->sli.sli4.cq[total_cq].type =
8448                                     EMLXS_CQ_TYPE_GROUP2;
8449                                 hba->sli.sli4.cq[total_cq].channelp =
8450                                     &hba->chan[total_cq - EMLXS_CQ_OFFSET_WQ];
8451                                 break;
8452                         }
8453                         emlxs_data_dump(port, "CQX_CREATE", (uint32_t *)mb,
8454                             18, 0);
8455                         total_cq++;
8456                 }
8457 
8458                 /* Create WQ's */
8459                 for (j = 0; j < num_wq; j++) {
8460                         /* Reuse mbq from previous mbox */
8461                         bzero(mbq, sizeof (MAILBOXQ));
8462 
8463                         hba->sli.sli4.wq[total_wq].cqid =
8464                             hba->sli.sli4.cq[total_wq + EMLXS_CQ_OFFSET_WQ].qid;
8465 
8466                         emlxs_mb_wq_create(hba, mbq, total_wq);
8467                         if (emlxs_sli4_issue_mbox_cmd(hba, mbq, MBX_WAIT, 0) !=
8468                             MBX_SUCCESS) {
8469                                 EMLXS_MSGF(EMLXS_CONTEXT,
8470                                     &emlxs_init_failed_msg, "Unable to Create "
8471                                     "WQ %d: Mailbox cmd=%x status=%x ",
8472                                     total_wq, mb->mbxCommand, mb->mbxStatus);
8473                                 return (EIO);
8474                         }
8475                         wq = (IOCTL_FCOE_WQ_CREATE *)
8476                             &mb->un.varSLIConfig.payload;
8477                         hba->sli.sli4.wq[total_wq].qid =
8478                             wq->params.response.WQId;
8479 
8480                         hba->sli.sli4.wq[total_wq].cqid =
8481                             hba->sli.sli4.cq[total_wq+EMLXS_CQ_OFFSET_WQ].qid;
8482                         emlxs_data_dump(port, "WQ_CREATE", (uint32_t *)mb,
8483                             18, 0);
8484                         total_wq++;
8485                 }
8486                 hba->last_msiid = i;
8487         }
8488 
8489         /* We assume 1 RQ pair will handle ALL incoming data */
8490         /* Create RQs */
8491         for (i = 0; i < EMLXS_MAX_RQS; i++) {
8492                 /* Personalize the RQ */
8493                 switch (i) {
8494                 case 0:
8495                         hba->sli.sli4.rq[i].cqid =
8496                             hba->sli.sli4.cq[EMLXS_CQ_RCV].qid;
8497                         break;
8498                 case 1:
8499                         hba->sli.sli4.rq[i].cqid =
8500                             hba->sli.sli4.cq[EMLXS_CQ_RCV].qid;
8501                         break;
8502                 default:
8503                         hba->sli.sli4.rq[i].cqid = 0xffff;
8504                 }
8505 
8506                 /* Reuse mbq from previous mbox */
8507                 bzero(mbq, sizeof (MAILBOXQ));
8508 
8509                 emlxs_mb_rq_create(hba, mbq, i);
8510                 if (emlxs_sli4_issue_mbox_cmd(hba, mbq, MBX_WAIT, 0) !=
8511                     MBX_SUCCESS) {
8512                         EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg,
8513                             "Unable to Create RQ %d: Mailbox cmd=%x status=%x ",
8514                             i, mb->mbxCommand, mb->mbxStatus);
8515                         return (EIO);
8516                 }
8517 
8518                 rq = (IOCTL_FCOE_RQ_CREATE *)&mb->un.varSLIConfig.payload;
8519                 hba->sli.sli4.rq[i].qid = rq->params.response.RQId;
8520                 emlxs_data_dump(port, "RQ CREATE", (uint32_t *)mb, 18, 0);
8521 
8522                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
8523                     "RQ CREATE: rq[%d].qid=%d cqid=%d",
8524                     i, hba->sli.sli4.rq[i].qid, hba->sli.sli4.rq[i].cqid);
8525 
8526                 /* Initialize the host_index */
8527                 hba->sli.sli4.rq[i].host_index = 0;
8528 
8529                 /* If Data queue was just created, */
8530                 /* then post buffers using the header qid */
8531                 if ((i & 0x1)) {
8532                         /* Ring the RQ doorbell to post buffers */
8533                         rqdb.word = 0;
8534                         rqdb.db.Qid = hba->sli.sli4.rq[i-1].qid;
8535                         rqdb.db.NumPosted = RQB_COUNT;
8536 
8537                         emlxs_sli4_write_rqdb(hba, rqdb.word);
8538 
8539                         EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
8540                             "RQ CREATE: Doorbell rang: qid=%d count=%d",
8541                             hba->sli.sli4.rq[i-1].qid, RQB_COUNT);
8542                 }
8543         }
8544 
8545         /* Create MQ */
8546 
8547         /* Personalize the MQ */
8548         hba->sli.sli4.mq.cqid = hba->sli.sli4.cq[EMLXS_CQ_MBOX].qid;
8549 
8550         /* Reuse mbq from previous mbox */
8551         bzero(mbq, sizeof (MAILBOXQ));
8552 
8553         emlxs_mb_mq_create_ext(hba, mbq);
8554         if (emlxs_sli4_issue_mbox_cmd(hba, mbq, MBX_WAIT, 0) !=
8555             MBX_SUCCESS) {
8556                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg,
8557                     "Unable to Create MQ_EXT %d: Mailbox cmd=%x status=%x ",
8558                     i, mb->mbxCommand, mb->mbxStatus);
8559 
8560                 /* Reuse mbq from previous mbox */
8561                 bzero(mbq, sizeof (MAILBOXQ));
8562 
8563                 emlxs_mb_mq_create(hba, mbq);
8564                 if (emlxs_sli4_issue_mbox_cmd(hba, mbq, MBX_WAIT, 0) !=
8565                     MBX_SUCCESS) {
8566                         EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg,
8567                             "Unable to Create MQ %d: Mailbox cmd=%x status=%x ",
8568                             i, mb->mbxCommand, mb->mbxStatus);
8569                         return (EIO);
8570                 }
8571 
8572                 mq = (IOCTL_COMMON_MQ_CREATE *)&mb->un.varSLIConfig.payload;
8573                 hba->sli.sli4.mq.qid = mq->params.response.MQId;
8574                 return (0);
8575         }
8576 
8577         mq_ext = (IOCTL_COMMON_MQ_CREATE_EXT *)&mb->un.varSLIConfig.payload;
8578         hba->sli.sli4.mq.qid = mq_ext->params.response.MQId;
8579         return (0);
8580 
8581 } /* emlxs_sli4_create_queues() */
8582 
8583 
8584 extern void
8585 emlxs_sli4_timer(emlxs_hba_t *hba)
8586 {
8587         /* Perform SLI4 level timer checks */
8588 
8589         emlxs_fcf_timer_notify(hba);
8590 
8591         emlxs_sli4_timer_check_mbox(hba);
8592 
8593         return;
8594 
8595 } /* emlxs_sli4_timer() */
8596 
8597 
8598 static void
8599 emlxs_sli4_timer_check_mbox(emlxs_hba_t *hba)
8600 {
8601         emlxs_port_t *port = &PPORT;
8602         emlxs_config_t *cfg = &CFG;
8603         MAILBOX *mb = NULL;
8604 
8605         if (!cfg[CFG_TIMEOUT_ENABLE].current) {
8606                 return;
8607         }
8608 
8609         mutex_enter(&EMLXS_PORT_LOCK);
8610 
8611         /* Return if timer hasn't expired */
8612         if (!hba->mbox_timer || (hba->timer_tics < hba->mbox_timer)) {
8613                 mutex_exit(&EMLXS_PORT_LOCK);
8614                 return;
8615         }
8616 
8617         /* The first to service the mbox queue will clear the timer */
8618         hba->mbox_timer = 0;
8619 
8620         if (hba->mbox_queue_flag) {
8621                 if (hba->mbox_mbq) {
8622                         mb = (MAILBOX *)hba->mbox_mbq;
8623                 }
8624         }
8625 
8626         if (mb) {
8627                 switch (hba->mbox_queue_flag) {
8628                 case MBX_NOWAIT:
8629                         EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mbox_timeout_msg,
8630                             "%s: Nowait.",
8631                             emlxs_mb_cmd_xlate(mb->mbxCommand));
8632                         break;
8633 
8634                 case MBX_SLEEP:
8635                         EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mbox_timeout_msg,
8636                             "%s: mb=%p Sleep.",
8637                             emlxs_mb_cmd_xlate(mb->mbxCommand),
8638                             mb);
8639                         break;
8640 
8641                 case MBX_POLL:
8642                         EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mbox_timeout_msg,
8643                             "%s: mb=%p Polled.",
8644                             emlxs_mb_cmd_xlate(mb->mbxCommand),
8645                             mb);
8646                         break;
8647 
8648                 default:
8649                         EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mbox_timeout_msg,
8650                             "%s: mb=%p (%d).",
8651                             emlxs_mb_cmd_xlate(mb->mbxCommand),
8652                             mb, hba->mbox_queue_flag);
8653                         break;
8654                 }
8655         } else {
8656                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mbox_timeout_msg, NULL);
8657         }
8658 
8659         hba->flag |= FC_MBOX_TIMEOUT;
8660         EMLXS_STATE_CHANGE_LOCKED(hba, FC_ERROR);
8661 
8662         mutex_exit(&EMLXS_PORT_LOCK);
8663 
8664         /* Perform mailbox cleanup */
8665         /* This will wake any sleeping or polling threads */
8666         emlxs_mb_fini(hba, NULL, MBX_TIMEOUT);
8667 
8668         /* Trigger adapter shutdown */
8669         emlxs_thread_spawn(hba, emlxs_shutdown_thread, 0, 0);
8670 
8671         return;
8672 
8673 } /* emlxs_sli4_timer_check_mbox() */
8674 
8675 
8676 extern void
8677 emlxs_data_dump(emlxs_port_t *port, char *str, uint32_t *iptr, int cnt, int err)
8678 {
8679         void *msg;
8680 
8681         if (!port || !str || !iptr || !cnt) {
8682                 return;
8683         }
8684 
8685         if (err) {
8686                 msg = &emlxs_sli_err_msg;
8687         } else {
8688                 msg = &emlxs_sli_detail_msg;
8689         }
8690 
8691         if (cnt) {
8692                 EMLXS_MSGF(EMLXS_CONTEXT, msg,
8693                     "%s00: %08x %08x %08x %08x %08x %08x", str, *iptr,
8694                     *(iptr+1), *(iptr+2), *(iptr+3), *(iptr+4), *(iptr+5));
8695         }
8696         if (cnt > 6) {
8697                 EMLXS_MSGF(EMLXS_CONTEXT, msg,
8698                     "%s06: %08x %08x %08x %08x %08x %08x", str, *(iptr+6),
8699                     *(iptr+7), *(iptr+8), *(iptr+9), *(iptr+10), *(iptr+11));
8700         }
8701         if (cnt > 12) {
8702                 EMLXS_MSGF(EMLXS_CONTEXT, msg,
8703                     "%s12: %08x %08x %08x %08x %08x %08x", str, *(iptr+12),
8704                     *(iptr+13), *(iptr+14), *(iptr+15), *(iptr+16), *(iptr+17));
8705         }
8706         if (cnt > 18) {
8707                 EMLXS_MSGF(EMLXS_CONTEXT, msg,
8708                     "%s18: %08x %08x %08x %08x %08x %08x", str, *(iptr+18),
8709                     *(iptr+19), *(iptr+20), *(iptr+21), *(iptr+22), *(iptr+23));
8710         }
8711         if (cnt > 24) {
8712                 EMLXS_MSGF(EMLXS_CONTEXT, msg,
8713                     "%s24: %08x %08x %08x %08x %08x %08x", str, *(iptr+24),
8714                     *(iptr+25), *(iptr+26), *(iptr+27), *(iptr+28), *(iptr+29));
8715         }
8716         if (cnt > 30) {
8717                 EMLXS_MSGF(EMLXS_CONTEXT, msg,
8718                     "%s30: %08x %08x %08x %08x %08x %08x", str, *(iptr+30),
8719                     *(iptr+31), *(iptr+32), *(iptr+33), *(iptr+34), *(iptr+35));
8720         }
8721         if (cnt > 36) {
8722                 EMLXS_MSGF(EMLXS_CONTEXT, msg,
8723                     "%s36: %08x %08x %08x %08x %08x %08x", str, *(iptr+36),
8724                     *(iptr+37), *(iptr+38), *(iptr+39), *(iptr+40), *(iptr+41));
8725         }
8726 
8727 } /* emlxs_data_dump() */
8728 
8729 
8730 extern void
8731 emlxs_ue_dump(emlxs_hba_t *hba, char *str)
8732 {
8733         emlxs_port_t *port = &PPORT;
8734         uint32_t status;
8735         uint32_t ue_h;
8736         uint32_t ue_l;
8737         uint32_t on1;
8738         uint32_t on2;
8739 
8740         switch (hba->sli_intf & SLI_INTF_IF_TYPE_MASK) {
8741         case SLI_INTF_IF_TYPE_0:
8742                 ue_l = ddi_get32(hba->pci_acc_handle,
8743                     hba->sli.sli4.ERR1_reg_addr);
8744                 ue_h = ddi_get32(hba->pci_acc_handle,
8745                     hba->sli.sli4.ERR2_reg_addr);
8746 
8747                 on1 = ddi_get32(hba->pci_acc_handle,
8748                     (uint32_t *)(hba->pci_addr + PCICFG_UE_STATUS_ONLINE1));
8749                 on2 = ddi_get32(hba->pci_acc_handle,
8750                     (uint32_t *)(hba->pci_addr + PCICFG_UE_STATUS_ONLINE2));
8751 
8752                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
8753                     "%s: ueLow:%08x ueHigh:%08x on1:%08x on2:%08x", str,
8754                     ue_l, ue_h, on1, on2);
8755                 break;
8756 
8757         case SLI_INTF_IF_TYPE_2:
8758                 status = ddi_get32(hba->sli.sli4.bar0_acc_handle,
8759                     hba->sli.sli4.STATUS_reg_addr);
8760 
8761                 ue_l = ddi_get32(hba->sli.sli4.bar0_acc_handle,
8762                     hba->sli.sli4.ERR1_reg_addr);
8763                 ue_h = ddi_get32(hba->sli.sli4.bar0_acc_handle,
8764                     hba->sli.sli4.ERR2_reg_addr);
8765 
8766                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
8767                     "%s: status:%08x err1:%08x err2:%08x", str,
8768                     status, ue_l, ue_h);
8769 
8770                 break;
8771         }
8772 
8773 #ifdef FMA_SUPPORT
8774         /* Access handle validation */
8775         EMLXS_CHK_ACC_HANDLE(hba, hba->pci_acc_handle);
8776 #endif  /* FMA_SUPPORT */
8777 
8778 } /* emlxs_ue_dump() */
8779 
8780 
8781 static void
8782 emlxs_sli4_poll_erratt(emlxs_hba_t *hba)
8783 {
8784         emlxs_port_t *port = &PPORT;
8785         uint32_t status;
8786         uint32_t ue_h;
8787         uint32_t ue_l;
8788         uint32_t error = 0;
8789 
8790         if (hba->flag & FC_HARDWARE_ERROR) {
8791                 return;
8792         }
8793 
8794         switch (hba->sli_intf & SLI_INTF_IF_TYPE_MASK) {
8795         case SLI_INTF_IF_TYPE_0:
8796                 ue_l = ddi_get32(hba->pci_acc_handle,
8797                     hba->sli.sli4.ERR1_reg_addr);
8798                 ue_h = ddi_get32(hba->pci_acc_handle,
8799                     hba->sli.sli4.ERR2_reg_addr);
8800 
8801                 if ((~hba->sli.sli4.ue_mask_lo & ue_l) ||
8802                     (~hba->sli.sli4.ue_mask_hi & ue_h) ||
8803                     (hba->sli.sli4.flag & EMLXS_SLI4_HW_ERROR)) {
8804                         EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_hardware_error_msg,
8805                             "Host Error: ueLow:%08x ueHigh:%08x maskLow:%08x "
8806                             "maskHigh:%08x flag:%08x",
8807                             ue_l, ue_h, hba->sli.sli4.ue_mask_lo,
8808                             hba->sli.sli4.ue_mask_hi, hba->sli.sli4.flag);
8809 
8810                         error = 2;
8811                 }
8812                 break;
8813 
8814         case SLI_INTF_IF_TYPE_2:
8815                 status = ddi_get32(hba->sli.sli4.bar0_acc_handle,
8816                     hba->sli.sli4.STATUS_reg_addr);
8817 
8818                 if ((status & SLI_STATUS_ERROR) ||
8819                     (hba->sli.sli4.flag & EMLXS_SLI4_HW_ERROR)) {
8820                         ue_l = ddi_get32(hba->sli.sli4.bar0_acc_handle,
8821                             hba->sli.sli4.ERR1_reg_addr);
8822                         ue_h = ddi_get32(hba->sli.sli4.bar0_acc_handle,
8823                             hba->sli.sli4.ERR2_reg_addr);
8824 
8825                         error = (status & SLI_STATUS_RESET_NEEDED)? 1:2;
8826 
8827                         if (error == 1) {
8828                                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_debug_msg,
8829                                     "Host Error: status:%08x err1:%08x "
8830                                     "err2:%08x flag:%08x",
8831                                     status, ue_l, ue_h, hba->sli.sli4.flag);
8832                         } else {
8833                                 EMLXS_MSGF(EMLXS_CONTEXT,
8834                                     &emlxs_hardware_error_msg,
8835                                     "Host Error: status:%08x err1:%08x "
8836                                     "err2:%08x flag:%08x",
8837                                     status, ue_l, ue_h, hba->sli.sli4.flag);
8838                         }
8839                 }
8840                 break;
8841         }
8842 
8843         if (error == 2) {
8844                 EMLXS_STATE_CHANGE(hba, FC_ERROR);
8845 
8846                 emlxs_sli4_hba_flush_chipq(hba);
8847 
8848                 emlxs_thread_spawn(hba, emlxs_shutdown_thread, 0, 0);
8849 
8850         } else if (error == 1) {
8851                 EMLXS_STATE_CHANGE(hba, FC_ERROR);
8852 
8853                 emlxs_sli4_hba_flush_chipq(hba);
8854 
8855                 emlxs_thread_spawn(hba, emlxs_restart_thread, 0, 0);
8856         }
8857 
8858 #ifdef FMA_SUPPORT
8859         /* Access handle validation */
8860         EMLXS_CHK_ACC_HANDLE(hba, hba->pci_acc_handle);
8861 #endif  /* FMA_SUPPORT */
8862 
8863 } /* emlxs_sli4_poll_erratt() */
8864 
8865 
8866 static uint32_t
8867 emlxs_sli4_reg_did(emlxs_port_t *port, uint32_t did, SERV_PARM *param,
8868     emlxs_buf_t *sbp, fc_unsol_buf_t *ubp, IOCBQ *iocbq)
8869 {
8870         emlxs_hba_t     *hba = HBA;
8871         NODELIST        *node;
8872         RPIobj_t        *rpip;
8873         uint32_t        rval;
8874 
8875         /* Check for invalid node ids to register */
8876         if ((did == 0) && (!(hba->flag & FC_LOOPBACK_MODE))) {
8877                 return (1);
8878         }
8879 
8880         if (did & 0xff000000) {
8881                 return (1);
8882         }
8883 
8884         /* We don't register our own did */
8885         if ((did == port->did) && (!(hba->flag & FC_LOOPBACK_MODE))) {
8886                 return (1);
8887         }
8888 
8889         if (did != FABRIC_DID) {
8890                 if ((rval = emlxs_mb_check_sparm(hba, param))) {
8891                         EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_node_create_failed_msg,
8892                             "Invalid service parameters. did=%06x rval=%d", did,
8893                             rval);
8894 
8895                         return (1);
8896                 }
8897         }
8898 
8899         /* Check if the node limit has been reached */
8900         if (port->node_count >= hba->max_nodes) {
8901                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_node_create_failed_msg,
8902                     "Limit reached. did=%06x count=%d", did,
8903                     port->node_count);
8904 
8905                 return (1);
8906         }
8907 
8908         node = emlxs_node_find_did(port, did, 1);
8909         rpip = EMLXS_NODE_TO_RPI(port, node);
8910 
8911         rval = emlxs_rpi_online_notify(port, rpip, did, param, (void *)sbp,
8912             (void *)ubp, (void *)iocbq);
8913 
8914         return (rval);
8915 
8916 } /* emlxs_sli4_reg_did() */
8917 
8918 
8919 static uint32_t
8920 emlxs_sli4_unreg_node(emlxs_port_t *port, emlxs_node_t *node,
8921     emlxs_buf_t *sbp, fc_unsol_buf_t *ubp, IOCBQ *iocbq)
8922 {
8923         RPIobj_t        *rpip;
8924         uint32_t        rval;
8925 
8926         if (!node) {
8927                 /* Unreg all nodes */
8928                 (void) emlxs_sli4_unreg_all_nodes(port);
8929                 return (1);
8930         }
8931 
8932         /* Check for base node */
8933         if (node == &port->node_base) {
8934                 /* Just flush base node */
8935                 (void) emlxs_tx_node_flush(port, &port->node_base,
8936                     0, 0, 0);
8937 
8938                 (void) emlxs_chipq_node_flush(port, 0,
8939                     &port->node_base, 0);
8940 
8941                 port->did = 0;
8942 
8943                 /* Return now */
8944                 return (1);
8945         }
8946 
8947         EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
8948             "unreg_node:%p did=%x rpi=%d",
8949             node, node->nlp_DID, node->nlp_Rpi);
8950 
8951         rpip = EMLXS_NODE_TO_RPI(port, node);
8952 
8953         if (!rpip) {
8954                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
8955                     "unreg_node:%p did=%x rpi=%d. RPI not found.",
8956                     node, node->nlp_DID, node->nlp_Rpi);
8957 
8958                 emlxs_node_rm(port, node);
8959                 return (1);
8960         }
8961 
8962         rval = emlxs_rpi_offline_notify(port, rpip, (void *)sbp, (void *)ubp,
8963             (void *)iocbq);
8964 
8965         return (rval);
8966 
8967 } /* emlxs_sli4_unreg_node() */
8968 
8969 
8970 extern uint32_t
8971 emlxs_sli4_unreg_all_nodes(emlxs_port_t *port)
8972 {
8973         NODELIST        *nlp;
8974         int             i;
8975         uint32_t        found;
8976 
8977         /* Set the node tags */
8978         /* We will process all nodes with this tag */
8979         rw_enter(&port->node_rwlock, RW_READER);
8980         found = 0;
8981         for (i = 0; i < EMLXS_NUM_HASH_QUES; i++) {
8982                 nlp = port->node_table[i];
8983                 while (nlp != NULL) {
8984                         found = 1;
8985                         nlp->nlp_tag = 1;
8986                         nlp = nlp->nlp_list_next;
8987                 }
8988         }
8989         rw_exit(&port->node_rwlock);
8990 
8991         if (!found) {
8992                 return (0);
8993         }
8994 
8995         for (;;) {
8996                 rw_enter(&port->node_rwlock, RW_READER);
8997                 found = 0;
8998                 for (i = 0; i < EMLXS_NUM_HASH_QUES; i++) {
8999                         nlp = port->node_table[i];
9000                         while (nlp != NULL) {
9001                                 if (!nlp->nlp_tag) {
9002                                         nlp = nlp->nlp_list_next;
9003                                         continue;
9004                                 }
9005                                 nlp->nlp_tag = 0;
9006                                 found = 1;
9007                                 break;
9008                         }
9009 
9010                         if (found) {
9011                                 break;
9012                         }
9013                 }
9014                 rw_exit(&port->node_rwlock);
9015 
9016                 if (!found) {
9017                         break;
9018                 }
9019 
9020                 (void) emlxs_sli4_unreg_node(port, nlp, 0, 0, 0);
9021         }
9022 
9023         return (0);
9024 
9025 } /* emlxs_sli4_unreg_all_nodes() */
9026 
9027 
9028 static void
9029 emlxs_sli4_handle_fcoe_link_event(emlxs_hba_t *hba, CQE_ASYNC_t *cqe)
9030 {
9031         emlxs_port_t *port = &PPORT;
9032 
9033         /* Handle link down */
9034         if ((cqe->un.link.link_status == ASYNC_EVENT_LOGICAL_LINK_DOWN) ||
9035             (cqe->un.link.link_status == ASYNC_EVENT_PHYS_LINK_DOWN)) {
9036                 (void) emlxs_fcf_linkdown_notify(port);
9037 
9038                 mutex_enter(&EMLXS_PORT_LOCK);
9039                 hba->sli.sli4.flag &= ~EMLXS_SLI4_DOWN_LINK;
9040                 mutex_exit(&EMLXS_PORT_LOCK);
9041                 return;
9042         }
9043 
9044         /* Link is up */
9045 
9046         /* Set linkspeed */
9047         switch (cqe->un.link.port_speed) {
9048         case PHY_1GHZ_LINK:
9049                 hba->linkspeed = LA_1GHZ_LINK;
9050                 break;
9051         case PHY_10GHZ_LINK:
9052                 hba->linkspeed = LA_10GHZ_LINK;
9053                 break;
9054         default:
9055                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
9056                     "sli4_handle_fcoe_link_event: Unknown link speed=%x.",
9057                     cqe->un.link.port_speed);
9058                 hba->linkspeed = 0;
9059                 break;
9060         }
9061 
9062         /* Set qos_linkspeed */
9063         hba->qos_linkspeed = cqe->un.link.qos_link_speed;
9064 
9065         /* Set topology */
9066         hba->topology = TOPOLOGY_PT_PT;
9067 
9068         mutex_enter(&EMLXS_PORT_LOCK);
9069         hba->sli.sli4.flag &= ~EMLXS_SLI4_DOWN_LINK;
9070         mutex_exit(&EMLXS_PORT_LOCK);
9071 
9072         (void) emlxs_fcf_linkup_notify(port);
9073 
9074         return;
9075 
9076 } /* emlxs_sli4_handle_fcoe_link_event()  */
9077 
9078 
9079 static void
9080 emlxs_sli4_handle_fc_link_att(emlxs_hba_t *hba, CQE_ASYNC_t *cqe)
9081 {
9082         emlxs_port_t *port = &PPORT;
9083 
9084         /* Handle link down */
9085         if (cqe->un.fc.att_type == ATT_TYPE_LINK_DOWN) {
9086                 (void) emlxs_fcf_linkdown_notify(port);
9087 
9088                 mutex_enter(&EMLXS_PORT_LOCK);
9089                 hba->sli.sli4.flag &= ~EMLXS_SLI4_DOWN_LINK;
9090                 mutex_exit(&EMLXS_PORT_LOCK);
9091                 return;
9092         }
9093 
9094         /* Link is up */
9095 
9096         /* Set linkspeed */
9097         switch (cqe->un.fc.port_speed) {
9098         case 1:
9099                 hba->linkspeed = LA_1GHZ_LINK;
9100                 break;
9101         case 2:
9102                 hba->linkspeed = LA_2GHZ_LINK;
9103                 break;
9104         case 4:
9105                 hba->linkspeed = LA_4GHZ_LINK;
9106                 break;
9107         case 8:
9108                 hba->linkspeed = LA_8GHZ_LINK;
9109                 break;
9110         case 10:
9111                 hba->linkspeed = LA_10GHZ_LINK;
9112                 break;
9113         case 16:
9114                 hba->linkspeed = LA_16GHZ_LINK;
9115                 break;
9116         default:
9117                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
9118                     "sli4_handle_fc_link_att: Unknown link speed=%x.",
9119                     cqe->un.fc.port_speed);
9120                 hba->linkspeed = 0;
9121                 break;
9122         }
9123 
9124         /* Set qos_linkspeed */
9125         hba->qos_linkspeed = cqe->un.fc.link_speed;
9126 
9127         /* Set topology */
9128         hba->topology = cqe->un.fc.topology;
9129 
9130         mutex_enter(&EMLXS_PORT_LOCK);
9131         hba->sli.sli4.flag &= ~EMLXS_SLI4_DOWN_LINK;
9132         mutex_exit(&EMLXS_PORT_LOCK);
9133 
9134         (void) emlxs_fcf_linkup_notify(port);
9135 
9136         return;
9137 
9138 } /* emlxs_sli4_handle_fc_link_att() */
9139 
9140 
9141 static int
9142 emlxs_sli4_init_extents(emlxs_hba_t *hba, MAILBOXQ *mbq)
9143 {
9144         emlxs_port_t *port = &PPORT;
9145         MAILBOX4 *mb4;
9146         IOCTL_COMMON_EXTENTS *ep;
9147         uint32_t i;
9148         uint32_t ExtentCnt;
9149 
9150         if (!(hba->sli.sli4.param.EXT)) {
9151                 return (0);
9152         }
9153 
9154         mb4 = (MAILBOX4 *) mbq;
9155 
9156         /* Discover XRI Extents */
9157         bzero(mbq, sizeof (MAILBOXQ));
9158         emlxs_mb_get_extents_info(hba, mbq, RSC_TYPE_FCOE_XRI);
9159 
9160         if (emlxs_sli4_issue_mbox_cmd(hba, mbq, MBX_WAIT, 0) != MBX_SUCCESS) {
9161                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg,
9162                     "Unable to discover XRI extents.  Mailbox cmd=%x status=%x",
9163                     mb4->mbxCommand, mb4->mbxStatus);
9164 
9165                 return (EIO);
9166         }
9167 
9168         ep = (IOCTL_COMMON_EXTENTS *)&mb4->un.varSLIConfig.payload;
9169         hba->sli.sli4.XRIExtSize = ep->params.response.ExtentSize;
9170         ExtentCnt = ep->params.response.ExtentCnt;
9171 
9172         /* Allocate XRI Extents */
9173         bzero(mbq, sizeof (MAILBOXQ));
9174         emlxs_mb_alloc_extents(hba, mbq, RSC_TYPE_FCOE_XRI, ExtentCnt);
9175 
9176         if (emlxs_sli4_issue_mbox_cmd(hba, mbq, MBX_WAIT, 0) != MBX_SUCCESS) {
9177                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg,
9178                     "Unable to allocate XRI extents.  Mailbox cmd=%x status=%x",
9179                     mb4->mbxCommand, mb4->mbxStatus);
9180 
9181                 return (EIO);
9182         }
9183         ep = (IOCTL_COMMON_EXTENTS *)&mb4->un.varSLIConfig.payload;
9184 
9185         bcopy((uint8_t *)ep->params.response.RscId,
9186             (uint8_t *)hba->sli.sli4.XRIBase,
9187             (ep->params.response.ExtentCnt * sizeof (uint16_t)));
9188 
9189         hba->sli.sli4.XRIExtCount = ep->params.response.ExtentCnt;
9190         hba->sli.sli4.XRICount = hba->sli.sli4.XRIExtCount *
9191             hba->sli.sli4.XRIExtSize;
9192 
9193         EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
9194             "XRI Ext: size=%d cnt=%d/%d",
9195             hba->sli.sli4.XRIExtSize,
9196             hba->sli.sli4.XRIExtCount, ExtentCnt);
9197 
9198         for (i = 0; i < ep->params.response.ExtentCnt; i += 4) {
9199                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
9200                     "XRI Ext%d: %d, %d, %d, %d", i,
9201                     hba->sli.sli4.XRIBase[i],
9202                     hba->sli.sli4.XRIBase[i+1],
9203                     hba->sli.sli4.XRIBase[i+2],
9204                     hba->sli.sli4.XRIBase[i+3]);
9205         }
9206 
9207 
9208         /* Discover RPI Extents */
9209         bzero(mbq, sizeof (MAILBOXQ));
9210         emlxs_mb_get_extents_info(hba, mbq, RSC_TYPE_FCOE_RPI);
9211 
9212         if (emlxs_sli4_issue_mbox_cmd(hba, mbq, MBX_WAIT, 0) != MBX_SUCCESS) {
9213                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg,
9214                     "Unable to discover RPI extents.  Mailbox cmd=%x status=%x",
9215                     mb4->mbxCommand, mb4->mbxStatus);
9216 
9217                 return (EIO);
9218         }
9219 
9220         ep = (IOCTL_COMMON_EXTENTS *)&mb4->un.varSLIConfig.payload;
9221         hba->sli.sli4.RPIExtSize = ep->params.response.ExtentSize;
9222         ExtentCnt = ep->params.response.ExtentCnt;
9223 
9224         /* Allocate RPI Extents */
9225         bzero(mbq, sizeof (MAILBOXQ));
9226         emlxs_mb_alloc_extents(hba, mbq, RSC_TYPE_FCOE_RPI, ExtentCnt);
9227 
9228         if (emlxs_sli4_issue_mbox_cmd(hba, mbq, MBX_WAIT, 0) != MBX_SUCCESS) {
9229                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg,
9230                     "Unable to allocate RPI extents.  Mailbox cmd=%x status=%x",
9231                     mb4->mbxCommand, mb4->mbxStatus);
9232 
9233                 return (EIO);
9234         }
9235         ep = (IOCTL_COMMON_EXTENTS *)&mb4->un.varSLIConfig.payload;
9236 
9237         bcopy((uint8_t *)ep->params.response.RscId,
9238             (uint8_t *)hba->sli.sli4.RPIBase,
9239             (ep->params.response.ExtentCnt * sizeof (uint16_t)));
9240 
9241         hba->sli.sli4.RPIExtCount = ep->params.response.ExtentCnt;
9242         hba->sli.sli4.RPICount = hba->sli.sli4.RPIExtCount *
9243             hba->sli.sli4.RPIExtSize;
9244 
9245         EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
9246             "RPI Ext: size=%d cnt=%d/%d",
9247             hba->sli.sli4.RPIExtSize,
9248             hba->sli.sli4.RPIExtCount, ExtentCnt);
9249 
9250         for (i = 0; i < ep->params.response.ExtentCnt; i += 4) {
9251                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
9252                     "RPI Ext%d: %d, %d, %d, %d", i,
9253                     hba->sli.sli4.RPIBase[i],
9254                     hba->sli.sli4.RPIBase[i+1],
9255                     hba->sli.sli4.RPIBase[i+2],
9256                     hba->sli.sli4.RPIBase[i+3]);
9257         }
9258 
9259 
9260         /* Discover VPI Extents */
9261         bzero(mbq, sizeof (MAILBOXQ));
9262         emlxs_mb_get_extents_info(hba, mbq, RSC_TYPE_FCOE_VPI);
9263 
9264         if (emlxs_sli4_issue_mbox_cmd(hba, mbq, MBX_WAIT, 0) != MBX_SUCCESS) {
9265                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg,
9266                     "Unable to discover VPI extents.  Mailbox cmd=%x status=%x",
9267                     mb4->mbxCommand, mb4->mbxStatus);
9268 
9269                 return (EIO);
9270         }
9271 
9272         ep = (IOCTL_COMMON_EXTENTS *)&mb4->un.varSLIConfig.payload;
9273         hba->sli.sli4.VPIExtSize = ep->params.response.ExtentSize;
9274         ExtentCnt = ep->params.response.ExtentCnt;
9275 
9276         /* Allocate VPI Extents */
9277         bzero(mbq, sizeof (MAILBOXQ));
9278         emlxs_mb_alloc_extents(hba, mbq, RSC_TYPE_FCOE_VPI, ExtentCnt);
9279 
9280         if (emlxs_sli4_issue_mbox_cmd(hba, mbq, MBX_WAIT, 0) != MBX_SUCCESS) {
9281                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg,
9282                     "Unable to allocate VPI extents.  Mailbox cmd=%x status=%x",
9283                     mb4->mbxCommand, mb4->mbxStatus);
9284 
9285                 return (EIO);
9286         }
9287         ep = (IOCTL_COMMON_EXTENTS *)&mb4->un.varSLIConfig.payload;
9288 
9289         bcopy((uint8_t *)ep->params.response.RscId,
9290             (uint8_t *)hba->sli.sli4.VPIBase,
9291             (ep->params.response.ExtentCnt * sizeof (uint16_t)));
9292 
9293         hba->sli.sli4.VPIExtCount = ep->params.response.ExtentCnt;
9294         hba->sli.sli4.VPICount = hba->sli.sli4.VPIExtCount *
9295             hba->sli.sli4.VPIExtSize;
9296 
9297         EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
9298             "VPI Ext: size=%d cnt=%d/%d",
9299             hba->sli.sli4.VPIExtSize,
9300             hba->sli.sli4.VPIExtCount, ExtentCnt);
9301 
9302         for (i = 0; i < ep->params.response.ExtentCnt; i += 4) {
9303                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
9304                     "VPI Ext%d: %d, %d, %d, %d", i,
9305                     hba->sli.sli4.VPIBase[i],
9306                     hba->sli.sli4.VPIBase[i+1],
9307                     hba->sli.sli4.VPIBase[i+2],
9308                     hba->sli.sli4.VPIBase[i+3]);
9309         }
9310 
9311         /* Discover VFI Extents */
9312         bzero(mbq, sizeof (MAILBOXQ));
9313         emlxs_mb_get_extents_info(hba, mbq, RSC_TYPE_FCOE_VFI);
9314 
9315         if (emlxs_sli4_issue_mbox_cmd(hba, mbq, MBX_WAIT, 0) != MBX_SUCCESS) {
9316                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg,
9317                     "Unable to discover VFI extents.  Mailbox cmd=%x status=%x",
9318                     mb4->mbxCommand, mb4->mbxStatus);
9319 
9320                 return (EIO);
9321         }
9322 
9323         ep = (IOCTL_COMMON_EXTENTS *)&mb4->un.varSLIConfig.payload;
9324         hba->sli.sli4.VFIExtSize = ep->params.response.ExtentSize;
9325         ExtentCnt = ep->params.response.ExtentCnt;
9326 
9327         /* Allocate VFI Extents */
9328         bzero(mbq, sizeof (MAILBOXQ));
9329         emlxs_mb_alloc_extents(hba, mbq, RSC_TYPE_FCOE_VFI, ExtentCnt);
9330 
9331         if (emlxs_sli4_issue_mbox_cmd(hba, mbq, MBX_WAIT, 0) != MBX_SUCCESS) {
9332                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg,
9333                     "Unable to allocate VFI extents.  Mailbox cmd=%x status=%x",
9334                     mb4->mbxCommand, mb4->mbxStatus);
9335 
9336                 return (EIO);
9337         }
9338         ep = (IOCTL_COMMON_EXTENTS *)&mb4->un.varSLIConfig.payload;
9339 
9340         bcopy((uint8_t *)ep->params.response.RscId,
9341             (uint8_t *)hba->sli.sli4.VFIBase,
9342             (ep->params.response.ExtentCnt * sizeof (uint16_t)));
9343 
9344         hba->sli.sli4.VFIExtCount = ep->params.response.ExtentCnt;
9345         hba->sli.sli4.VFICount = hba->sli.sli4.VFIExtCount *
9346             hba->sli.sli4.VFIExtSize;
9347 
9348         EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
9349             "VFI Ext: size=%d cnt=%d/%d",
9350             hba->sli.sli4.VFIExtSize,
9351             hba->sli.sli4.VFIExtCount, ExtentCnt);
9352 
9353         for (i = 0; i < ep->params.response.ExtentCnt; i += 4) {
9354                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
9355                     "VFI Ext%d: %d, %d, %d, %d", i,
9356                     hba->sli.sli4.VFIBase[i],
9357                     hba->sli.sli4.VFIBase[i+1],
9358                     hba->sli.sli4.VFIBase[i+2],
9359                     hba->sli.sli4.VFIBase[i+3]);
9360         }
9361 
9362         return (0);
9363 
9364 } /* emlxs_sli4_init_extents() */
9365 
9366 
9367 extern uint32_t
9368 emlxs_sli4_index_to_rpi(emlxs_hba_t *hba, uint32_t index)
9369 {
9370         uint32_t i;
9371         uint32_t j;
9372         uint32_t rpi;
9373 
9374         i = index / hba->sli.sli4.RPIExtSize;
9375         j = index % hba->sli.sli4.RPIExtSize;
9376         rpi = hba->sli.sli4.RPIBase[i] + j;
9377 
9378         return (rpi);
9379 
9380 } /* emlxs_sli4_index_to_rpi */
9381 
9382 
9383 extern uint32_t
9384 emlxs_sli4_rpi_to_index(emlxs_hba_t *hba, uint32_t rpi)
9385 {
9386         uint32_t i;
9387         uint32_t lo;
9388         uint32_t hi;
9389         uint32_t index = hba->sli.sli4.RPICount;
9390 
9391         for (i = 0; i < hba->sli.sli4.RPIExtCount; i++) {
9392                 lo = hba->sli.sli4.RPIBase[i];
9393                 hi = lo + hba->sli.sli4.RPIExtSize;
9394 
9395                 if ((rpi < hi) && (rpi >= lo)) {
9396                         index = (i * hba->sli.sli4.RPIExtSize) + (rpi - lo);
9397                         break;
9398                 }
9399         }
9400 
9401         return (index);
9402 
9403 } /* emlxs_sli4_rpi_to_index */
9404 
9405 
9406 extern uint32_t
9407 emlxs_sli4_index_to_xri(emlxs_hba_t *hba, uint32_t index)
9408 {
9409         uint32_t i;
9410         uint32_t j;
9411         uint32_t xri;
9412 
9413         i = index / hba->sli.sli4.XRIExtSize;
9414         j = index % hba->sli.sli4.XRIExtSize;
9415         xri = hba->sli.sli4.XRIBase[i] + j;
9416 
9417         return (xri);
9418 
9419 } /* emlxs_sli4_index_to_xri */
9420 
9421 
9422 
9423 
9424 extern uint32_t
9425 emlxs_sli4_index_to_vpi(emlxs_hba_t *hba, uint32_t index)
9426 {
9427         uint32_t i;
9428         uint32_t j;
9429         uint32_t vpi;
9430 
9431         i = index / hba->sli.sli4.VPIExtSize;
9432         j = index % hba->sli.sli4.VPIExtSize;
9433         vpi = hba->sli.sli4.VPIBase[i] + j;
9434 
9435         return (vpi);
9436 
9437 } /* emlxs_sli4_index_to_vpi */
9438 
9439 
9440 extern uint32_t
9441 emlxs_sli4_vpi_to_index(emlxs_hba_t *hba, uint32_t vpi)
9442 {
9443         uint32_t i;
9444         uint32_t lo;
9445         uint32_t hi;
9446         uint32_t index = hba->sli.sli4.VPICount;
9447 
9448         for (i = 0; i < hba->sli.sli4.VPIExtCount; i++) {
9449                 lo = hba->sli.sli4.VPIBase[i];
9450                 hi = lo + hba->sli.sli4.VPIExtSize;
9451 
9452                 if ((vpi < hi) && (vpi >= lo)) {
9453                         index = (i * hba->sli.sli4.VPIExtSize) + (vpi - lo);
9454                         break;
9455                 }
9456         }
9457 
9458         return (index);
9459 
9460 } /* emlxs_sli4_vpi_to_index */
9461 
9462 
9463 
9464 
9465 extern uint32_t
9466 emlxs_sli4_index_to_vfi(emlxs_hba_t *hba, uint32_t index)
9467 {
9468         uint32_t i;
9469         uint32_t j;
9470         uint32_t vfi;
9471 
9472         i = index / hba->sli.sli4.VFIExtSize;
9473         j = index % hba->sli.sli4.VFIExtSize;
9474         vfi = hba->sli.sli4.VFIBase[i] + j;
9475 
9476         return (vfi);
9477 
9478 } /* emlxs_sli4_index_to_vfi */
9479 
9480 
9481 static uint16_t
9482 emlxs_sli4_rqid_to_index(emlxs_hba_t *hba, uint16_t rqid)
9483 {
9484         uint16_t i;
9485 
9486         if (rqid < 0xffff) {
9487                 for (i = 0; i < EMLXS_MAX_RQS; i++) {
9488                         if (hba->sli.sli4.rq[i].qid == rqid) {
9489                                 return (i);
9490                         }
9491                 }
9492         }
9493 
9494         return (0xffff);
9495 
9496 } /* emlxs_sli4_rqid_to_index */
9497 
9498 
9499 static uint16_t
9500 emlxs_sli4_wqid_to_index(emlxs_hba_t *hba, uint16_t wqid)
9501 {
9502         uint16_t i;
9503 
9504         if (wqid < 0xffff) {
9505                 for (i = 0; i < EMLXS_MAX_WQS; i++) {
9506                         if (hba->sli.sli4.wq[i].qid == wqid) {
9507                                 return (i);
9508                         }
9509                 }
9510         }
9511 
9512         return (0xffff);
9513 
9514 } /* emlxs_sli4_wqid_to_index */
9515 
9516 
9517 static uint16_t
9518 emlxs_sli4_cqid_to_index(emlxs_hba_t *hba, uint16_t cqid)
9519 {
9520         uint16_t i;
9521 
9522         if (cqid < 0xffff) {
9523                 for (i = 0; i < EMLXS_MAX_CQS; i++) {
9524                         if (hba->sli.sli4.cq[i].qid == cqid) {
9525                                 return (i);
9526                         }
9527                 }
9528         }
9529 
9530         return (0xffff);
9531 
9532 } /* emlxs_sli4_cqid_to_index */