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 /* Required for EMLXS_CONTEXT in EMLXS_MSGF calls */
  30 EMLXS_MSG_DEF(EMLXS_SLI3_C);
  31 
  32 static void emlxs_sli3_issue_iocb(emlxs_hba_t *hba, RING *rp, IOCBQ *iocbq);
  33 static void emlxs_sli3_handle_link_event(emlxs_hba_t *hba);
  34 static void emlxs_sli3_handle_ring_event(emlxs_hba_t *hba, int32_t ring_no,
  35         uint32_t ha_copy);
  36 #ifdef SFCT_SUPPORT
  37 static uint32_t emlxs_fct_bde_setup(emlxs_port_t *port, emlxs_buf_t *sbp);
  38 #endif /* SFCT_SUPPORT */
  39 
  40 static uint32_t emlxs_bde_setup(emlxs_port_t *port, emlxs_buf_t *sbp);
  41 
  42 static uint32_t emlxs_disable_traffic_cop = 1;
  43 
  44 static int                      emlxs_sli3_map_hdw(emlxs_hba_t *hba);
  45 
  46 static void                     emlxs_sli3_unmap_hdw(emlxs_hba_t *hba);
  47 
  48 static int32_t                  emlxs_sli3_online(emlxs_hba_t *hba);
  49 
  50 static void                     emlxs_sli3_offline(emlxs_hba_t *hba,
  51                                         uint32_t reset_requested);
  52 
  53 static uint32_t                 emlxs_sli3_hba_reset(emlxs_hba_t *hba,
  54                                         uint32_t restart, uint32_t skip_post,
  55                                         uint32_t quiesce);
  56 
  57 static void                     emlxs_sli3_hba_kill(emlxs_hba_t *hba);
  58 static void                     emlxs_sli3_hba_kill4quiesce(emlxs_hba_t *hba);
  59 static uint32_t                 emlxs_sli3_hba_init(emlxs_hba_t *hba);
  60 
  61 static uint32_t                 emlxs_sli2_bde_setup(emlxs_port_t *port,
  62                                         emlxs_buf_t *sbp);
  63 static uint32_t                 emlxs_sli3_bde_setup(emlxs_port_t *port,
  64                                         emlxs_buf_t *sbp);
  65 static uint32_t                 emlxs_sli2_fct_bde_setup(emlxs_port_t *port,
  66                                         emlxs_buf_t *sbp);
  67 static uint32_t                 emlxs_sli3_fct_bde_setup(emlxs_port_t *port,
  68                                         emlxs_buf_t *sbp);
  69 
  70 
  71 static void                     emlxs_sli3_issue_iocb_cmd(emlxs_hba_t *hba,
  72                                         CHANNEL *rp, IOCBQ *iocb_cmd);
  73 
  74 
  75 static uint32_t                 emlxs_sli3_issue_mbox_cmd(emlxs_hba_t *hba,
  76                                         MAILBOXQ *mbq, int32_t flg,
  77                                         uint32_t tmo);
  78 
  79 
  80 #ifdef SFCT_SUPPORT
  81 static uint32_t                 emlxs_sli3_prep_fct_iocb(emlxs_port_t *port,
  82                                         emlxs_buf_t *cmd_sbp, int channel);
  83 
  84 #endif /* SFCT_SUPPORT */
  85 
  86 static uint32_t                 emlxs_sli3_prep_fcp_iocb(emlxs_port_t *port,
  87                                         emlxs_buf_t *sbp, int ring);
  88 
  89 static uint32_t                 emlxs_sli3_prep_ip_iocb(emlxs_port_t *port,
  90                                         emlxs_buf_t *sbp);
  91 
  92 static uint32_t                 emlxs_sli3_prep_els_iocb(emlxs_port_t *port,
  93                                         emlxs_buf_t *sbp);
  94 
  95 
  96 static uint32_t                 emlxs_sli3_prep_ct_iocb(emlxs_port_t *port,
  97                                         emlxs_buf_t *sbp);
  98 
  99 
 100 static void                     emlxs_sli3_poll_intr(emlxs_hba_t *hba);
 101 
 102 static int32_t                  emlxs_sli3_intx_intr(char *arg);
 103 #ifdef MSI_SUPPORT
 104 static uint32_t                 emlxs_sli3_msi_intr(char *arg1, char *arg2);
 105 #endif /* MSI_SUPPORT */
 106 
 107 static void                     emlxs_sli3_enable_intr(emlxs_hba_t *hba);
 108 
 109 static void                     emlxs_sli3_disable_intr(emlxs_hba_t *hba,
 110                                         uint32_t att);
 111 
 112 
 113 static void                     emlxs_handle_ff_error(emlxs_hba_t *hba);
 114 
 115 static uint32_t                 emlxs_handle_mb_event(emlxs_hba_t *hba);
 116 
 117 static void                     emlxs_sli3_timer_check_mbox(emlxs_hba_t *hba);
 118 
 119 static uint32_t                 emlxs_mb_config_port(emlxs_hba_t *hba,
 120                                         MAILBOXQ *mbq, uint32_t sli_mode,
 121                                         uint32_t hbainit);
 122 static void                     emlxs_enable_latt(emlxs_hba_t *hba);
 123 
 124 static uint32_t                 emlxs_check_attention(emlxs_hba_t *hba);
 125 
 126 static uint32_t                 emlxs_get_attention(emlxs_hba_t *hba,
 127                                         int32_t msgid);
 128 static void                     emlxs_proc_attention(emlxs_hba_t *hba,
 129                                         uint32_t ha_copy);
 130 /* static int                   emlxs_handle_rcv_seq(emlxs_hba_t *hba, */
 131                                         /* CHANNEL *cp, IOCBQ *iocbq); */
 132 /* static void                  emlxs_update_HBQ_index(emlxs_hba_t *hba, */
 133                                         /* uint32_t hbq_id); */
 134 /* static void                  emlxs_hbq_free_all(emlxs_hba_t *hba, */
 135                                         /* uint32_t hbq_id); */
 136 static uint32_t                 emlxs_hbq_setup(emlxs_hba_t *hba,
 137                                         uint32_t hbq_id);
 138 static void                     emlxs_sli3_timer(emlxs_hba_t *hba);
 139 
 140 static void                     emlxs_sli3_poll_erratt(emlxs_hba_t *hba);
 141 
 142 static uint32_t                 emlxs_sli3_reg_did(emlxs_port_t *port,
 143                                         uint32_t did, SERV_PARM *param,
 144                                         emlxs_buf_t *sbp, fc_unsol_buf_t *ubp,
 145                                         IOCBQ *iocbq);
 146 
 147 static uint32_t                 emlxs_sli3_unreg_node(emlxs_port_t *port,
 148                                         NODELIST *node, emlxs_buf_t *sbp,
 149                                         fc_unsol_buf_t *ubp, IOCBQ *iocbq);
 150 
 151 
 152 /* Define SLI3 API functions */
 153 emlxs_sli_api_t emlxs_sli3_api = {
 154         emlxs_sli3_map_hdw,
 155         emlxs_sli3_unmap_hdw,
 156         emlxs_sli3_online,
 157         emlxs_sli3_offline,
 158         emlxs_sli3_hba_reset,
 159         emlxs_sli3_hba_kill,
 160         emlxs_sli3_issue_iocb_cmd,
 161         emlxs_sli3_issue_mbox_cmd,
 162 #ifdef SFCT_SUPPORT
 163         emlxs_sli3_prep_fct_iocb,
 164 #else
 165         NULL,
 166 #endif /* SFCT_SUPPORT */
 167         emlxs_sli3_prep_fcp_iocb,
 168         emlxs_sli3_prep_ip_iocb,
 169         emlxs_sli3_prep_els_iocb,
 170         emlxs_sli3_prep_ct_iocb,
 171         emlxs_sli3_poll_intr,
 172         emlxs_sli3_intx_intr,
 173         emlxs_sli3_msi_intr,
 174         emlxs_sli3_disable_intr,
 175         emlxs_sli3_timer,
 176         emlxs_sli3_poll_erratt,
 177         emlxs_sli3_reg_did,
 178         emlxs_sli3_unreg_node
 179 };
 180 
 181 
 182 /*
 183  * emlxs_sli3_online()
 184  *
 185  * This routine will start initialization of the SLI2/3 HBA.
 186  */
 187 static int32_t
 188 emlxs_sli3_online(emlxs_hba_t *hba)
 189 {
 190         emlxs_port_t *port = &PPORT;
 191         emlxs_config_t *cfg;
 192         emlxs_vpd_t *vpd;
 193         MAILBOX *mb = NULL;
 194         MAILBOXQ *mbq = NULL;
 195         RING *rp;
 196         CHANNEL *cp;
 197         MATCHMAP *mp = NULL;
 198         MATCHMAP *mp1 = NULL;
 199         uint8_t *inptr;
 200         uint8_t *outptr;
 201         uint32_t status;
 202         uint16_t i;
 203         uint32_t j;
 204         uint32_t read_rev_reset;
 205         uint32_t key = 0;
 206         uint32_t fw_check;
 207         uint32_t kern_update = 0;
 208         uint32_t rval = 0;
 209         uint32_t offset;
 210         uint8_t vpd_data[DMP_VPD_SIZE];
 211         uint32_t MaxRbusSize;
 212         uint32_t MaxIbusSize;
 213         uint32_t sli_mode;
 214         uint32_t sli_mode_mask;
 215 
 216         cfg = &CFG;
 217         vpd = &VPD;
 218         MaxRbusSize = 0;
 219         MaxIbusSize = 0;
 220         read_rev_reset = 0;
 221         hba->chan_count = MAX_RINGS;
 222 
 223         if (hba->bus_type == SBUS_FC) {
 224                 (void) READ_SBUS_CSR_REG(hba, FC_SHS_REG(hba));
 225         }
 226 
 227         /* Set the fw_check flag */
 228         fw_check = cfg[CFG_FW_CHECK].current;
 229 
 230         if ((fw_check & 0x04) ||
 231             (hba->fw_flag & FW_UPDATE_KERNEL)) {
 232                 kern_update = 1;
 233         }
 234 
 235         hba->mbox_queue_flag = 0;
 236         hba->sli.sli3.hc_copy = 0;
 237         hba->fc_edtov = FF_DEF_EDTOV;
 238         hba->fc_ratov = FF_DEF_RATOV;
 239         hba->fc_altov = FF_DEF_ALTOV;
 240         hba->fc_arbtov = FF_DEF_ARBTOV;
 241 
 242         /*
 243          * Get a buffer which will be used repeatedly for mailbox commands
 244          */
 245         mbq = (MAILBOXQ *) kmem_zalloc((sizeof (MAILBOXQ)), KM_SLEEP);
 246 
 247         mb = (MAILBOX *)mbq;
 248 
 249         /* Initialize sli mode based on configuration parameter */
 250         switch (cfg[CFG_SLI_MODE].current) {
 251         case 2: /* SLI2 mode */
 252                 sli_mode = EMLXS_HBA_SLI2_MODE;
 253                 sli_mode_mask = EMLXS_SLI2_MASK;
 254                 break;
 255 
 256         case 3: /* SLI3 mode */
 257                 sli_mode = EMLXS_HBA_SLI3_MODE;
 258                 sli_mode_mask = EMLXS_SLI3_MASK;
 259                 break;
 260 
 261         case 0: /* Best available */
 262         case 1: /* Best available */
 263         default:
 264                 if (hba->model_info.sli_mask & EMLXS_SLI3_MASK) {
 265                         sli_mode = EMLXS_HBA_SLI3_MODE;
 266                         sli_mode_mask = EMLXS_SLI3_MASK;
 267                 } else if (hba->model_info.sli_mask & EMLXS_SLI2_MASK) {
 268                         sli_mode = EMLXS_HBA_SLI2_MODE;
 269                         sli_mode_mask = EMLXS_SLI2_MASK;
 270                 } else {
 271                         EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg,
 272                             "No SLI mode available.");
 273                         rval = EIO;
 274                         goto failed;
 275                 }
 276                 break;
 277         }
 278         /* SBUS adapters only available in SLI2 */
 279         if (hba->bus_type == SBUS_FC) {
 280                 sli_mode = EMLXS_HBA_SLI2_MODE;
 281                 sli_mode_mask = EMLXS_SLI2_MASK;
 282         }
 283 
 284 reset:
 285         /* Reset & Initialize the adapter */
 286         if (emlxs_sli3_hba_init(hba)) {
 287                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg,
 288                     "Unable to init hba.");
 289 
 290                 rval = EIO;
 291                 goto failed;
 292         }
 293 
 294 #ifdef FMA_SUPPORT
 295         /* Access handle validation */
 296         if ((emlxs_fm_check_acc_handle(hba, hba->pci_acc_handle)
 297             != DDI_FM_OK) ||
 298             (emlxs_fm_check_acc_handle(hba, hba->sli.sli3.slim_acc_handle)
 299             != DDI_FM_OK) ||
 300             (emlxs_fm_check_acc_handle(hba, hba->sli.sli3.csr_acc_handle)
 301             != DDI_FM_OK)) {
 302                 EMLXS_MSGF(EMLXS_CONTEXT,
 303                     &emlxs_invalid_access_handle_msg, NULL);
 304 
 305                 rval = EIO;
 306                 goto failed;
 307         }
 308 #endif  /* FMA_SUPPORT */
 309 
 310         /* Check for PEGASUS (This is a special case) */
 311         /* We need to check for dual channel adapter */
 312         if (hba->model_info.device_id == PCI_DEVICE_ID_PEGASUS) {
 313                 /* Try to determine if this is a DC adapter */
 314                 if (emlxs_get_max_sram(hba, &MaxRbusSize, &MaxIbusSize) == 0) {
 315                         if (MaxRbusSize == REDUCED_SRAM_CFG) {
 316                                 /* LP9802DC */
 317                                 for (i = 1; i < emlxs_pci_model_count; i++) {
 318                                         if (emlxs_pci_model[i].id == LP9802DC) {
 319                                                 bcopy(&emlxs_pci_model[i],
 320                                                     &hba->model_info,
 321                                                     sizeof (emlxs_model_t));
 322                                                 break;
 323                                         }
 324                                 }
 325                         } else if (hba->model_info.id != LP9802) {
 326                                 /* LP9802 */
 327                                 for (i = 1; i < emlxs_pci_model_count; i++) {
 328                                         if (emlxs_pci_model[i].id == LP9802) {
 329                                                 bcopy(&emlxs_pci_model[i],
 330                                                     &hba->model_info,
 331                                                     sizeof (emlxs_model_t));
 332                                                 break;
 333                                         }
 334                                 }
 335                         }
 336                 }
 337         }
 338 
 339         /*
 340          * Setup and issue mailbox READ REV command
 341          */
 342         vpd->opFwRev = 0;
 343         vpd->postKernRev = 0;
 344         vpd->sli1FwRev = 0;
 345         vpd->sli2FwRev = 0;
 346         vpd->sli3FwRev = 0;
 347         vpd->sli4FwRev = 0;
 348 
 349         vpd->postKernName[0] = 0;
 350         vpd->opFwName[0] = 0;
 351         vpd->sli1FwName[0] = 0;
 352         vpd->sli2FwName[0] = 0;
 353         vpd->sli3FwName[0] = 0;
 354         vpd->sli4FwName[0] = 0;
 355 
 356         vpd->opFwLabel[0] = 0;
 357         vpd->sli1FwLabel[0] = 0;
 358         vpd->sli2FwLabel[0] = 0;
 359         vpd->sli3FwLabel[0] = 0;
 360         vpd->sli4FwLabel[0] = 0;
 361 
 362         /* Sanity check */
 363         if (hba->model_info.sli_mask & EMLXS_SLI4_MASK) {
 364                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg,
 365                     "Adapter / SLI mode mismatch mask:x%x",
 366                     hba->model_info.sli_mask);
 367 
 368                 rval = EIO;
 369                 goto failed;
 370         }
 371 
 372         EMLXS_STATE_CHANGE(hba, FC_INIT_REV);
 373         emlxs_mb_read_rev(hba, mbq, 0);
 374         if (emlxs_sli3_issue_mbox_cmd(hba, mbq, MBX_WAIT, 0) != MBX_SUCCESS) {
 375                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg,
 376                     "Unable to read rev. Mailbox cmd=%x status=%x",
 377                     mb->mbxCommand, mb->mbxStatus);
 378 
 379                 rval = EIO;
 380                 goto failed;
 381         }
 382 
 383         if (mb->un.varRdRev.rr == 0) {
 384                 /* Old firmware */
 385                 if (read_rev_reset == 0) {
 386                         read_rev_reset = 1;
 387 
 388                         goto reset;
 389                 } else {
 390                         EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_msg,
 391                             "Outdated firmware detected.");
 392                 }
 393 
 394                 vpd->rBit = 0;
 395         } else {
 396                 if (mb->un.varRdRev.un.b.ProgType != FUNC_FIRMWARE) {
 397                         if (read_rev_reset == 0) {
 398                                 read_rev_reset = 1;
 399 
 400                                 goto reset;
 401                         } else {
 402                                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_msg,
 403                                     "Non-operational firmware detected. "
 404                                     "type=%x",
 405                                     mb->un.varRdRev.un.b.ProgType);
 406                         }
 407                 }
 408 
 409                 vpd->rBit = 1;
 410                 vpd->sli1FwRev = mb->un.varRdRev.sliFwRev1;
 411                 bcopy((char *)mb->un.varRdRev.sliFwName1, vpd->sli1FwLabel,
 412                     16);
 413                 vpd->sli2FwRev = mb->un.varRdRev.sliFwRev2;
 414                 bcopy((char *)mb->un.varRdRev.sliFwName2, vpd->sli2FwLabel,
 415                     16);
 416 
 417                 /*
 418                  * Lets try to read the SLI3 version
 419                  * Setup and issue mailbox READ REV(v3) command
 420                  */
 421                 EMLXS_STATE_CHANGE(hba, FC_INIT_REV);
 422 
 423                 /* Reuse mbq from previous mbox */
 424                 bzero(mbq, sizeof (MAILBOXQ));
 425 
 426                 emlxs_mb_read_rev(hba, mbq, 1);
 427 
 428                 if (emlxs_sli3_issue_mbox_cmd(hba, mbq, MBX_WAIT, 0) !=
 429                     MBX_SUCCESS) {
 430                         EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg,
 431                             "Unable to read rev (v3). Mailbox cmd=%x status=%x",
 432                             mb->mbxCommand, mb->mbxStatus);
 433 
 434                         rval = EIO;
 435                         goto failed;
 436                 }
 437 
 438                 if (mb->un.varRdRev.rf3) {
 439                         /*
 440                          * vpd->sli2FwRev = mb->un.varRdRev.sliFwRev1;
 441                          * Not needed
 442                          */
 443                         vpd->sli3FwRev = mb->un.varRdRev.sliFwRev2;
 444                         bcopy((char *)mb->un.varRdRev.sliFwName2,
 445                             vpd->sli3FwLabel, 16);
 446                 }
 447         }
 448 
 449         if ((sli_mode == EMLXS_HBA_SLI3_MODE) && (vpd->sli3FwRev == 0)) {
 450                 if (vpd->sli2FwRev) {
 451                         sli_mode = EMLXS_HBA_SLI2_MODE;
 452                         sli_mode_mask = EMLXS_SLI2_MASK;
 453                 } else {
 454                         sli_mode = 0;
 455                         sli_mode_mask = 0;
 456                 }
 457         }
 458 
 459         else if ((sli_mode == EMLXS_HBA_SLI2_MODE) && (vpd->sli2FwRev == 0)) {
 460                 if (vpd->sli3FwRev) {
 461                         sli_mode = EMLXS_HBA_SLI3_MODE;
 462                         sli_mode_mask = EMLXS_SLI3_MASK;
 463                 } else {
 464                         sli_mode = 0;
 465                         sli_mode_mask = 0;
 466                 }
 467         }
 468 
 469         if (!(hba->model_info.sli_mask & sli_mode_mask)) {
 470                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg,
 471                     "Firmware not available. sli-mode=%d",
 472                     cfg[CFG_SLI_MODE].current);
 473 
 474                 rval = EIO;
 475                 goto failed;
 476         }
 477 
 478         /* Save information as VPD data */
 479         vpd->postKernRev = mb->un.varRdRev.postKernRev;
 480         vpd->opFwRev = mb->un.varRdRev.opFwRev;
 481         bcopy((char *)mb->un.varRdRev.opFwName, vpd->opFwLabel, 16);
 482         vpd->biuRev = mb->un.varRdRev.biuRev;
 483         vpd->smRev = mb->un.varRdRev.smRev;
 484         vpd->smFwRev = mb->un.varRdRev.un.smFwRev;
 485         vpd->endecRev = mb->un.varRdRev.endecRev;
 486         vpd->fcphHigh = mb->un.varRdRev.fcphHigh;
 487         vpd->fcphLow = mb->un.varRdRev.fcphLow;
 488         vpd->feaLevelHigh = mb->un.varRdRev.feaLevelHigh;
 489         vpd->feaLevelLow = mb->un.varRdRev.feaLevelLow;
 490 
 491         /* Decode FW names */
 492         emlxs_decode_version(vpd->postKernRev, vpd->postKernName,
 493             sizeof (vpd->postKernName));
 494         emlxs_decode_version(vpd->opFwRev, vpd->opFwName,
 495             sizeof (vpd->opFwName));
 496         emlxs_decode_version(vpd->sli1FwRev, vpd->sli1FwName,
 497             sizeof (vpd->sli1FwName));
 498         emlxs_decode_version(vpd->sli2FwRev, vpd->sli2FwName,
 499             sizeof (vpd->sli2FwName));
 500         emlxs_decode_version(vpd->sli3FwRev, vpd->sli3FwName,
 501             sizeof (vpd->sli3FwName));
 502         emlxs_decode_version(vpd->sli4FwRev, vpd->sli4FwName,
 503             sizeof (vpd->sli4FwName));
 504 
 505         /* Decode FW labels */
 506         emlxs_decode_label(vpd->opFwLabel, vpd->opFwLabel, 1,
 507             sizeof (vpd->opFwLabel));
 508         emlxs_decode_label(vpd->sli1FwLabel, vpd->sli1FwLabel, 1,
 509             sizeof (vpd->sli1FwLabel));
 510         emlxs_decode_label(vpd->sli2FwLabel, vpd->sli2FwLabel, 1,
 511             sizeof (vpd->sli2FwLabel));
 512         emlxs_decode_label(vpd->sli3FwLabel, vpd->sli3FwLabel, 1,
 513             sizeof (vpd->sli3FwLabel));
 514         emlxs_decode_label(vpd->sli4FwLabel, vpd->sli4FwLabel, 1,
 515             sizeof (vpd->sli4FwLabel));
 516 
 517         /* Reuse mbq from previous mbox */
 518         bzero(mbq, sizeof (MAILBOXQ));
 519 
 520         key = emlxs_get_key(hba, mbq);
 521 
 522         /* Get adapter VPD information */
 523         offset = 0;
 524         bzero(vpd_data, sizeof (vpd_data));
 525         vpd->port_index = (uint32_t)-1;
 526 
 527         while (offset < DMP_VPD_SIZE) {
 528                 /* Reuse mbq from previous mbox */
 529                 bzero(mbq, sizeof (MAILBOXQ));
 530 
 531                 emlxs_mb_dump_vpd(hba, mbq, offset);
 532                 if (emlxs_sli3_issue_mbox_cmd(hba, mbq, MBX_WAIT, 0) !=
 533                     MBX_SUCCESS) {
 534                         /*
 535                          * Let it go through even if failed.
 536                          * Not all adapter's have VPD info and thus will
 537                          * fail here. This is not a problem
 538                          */
 539 
 540                         EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
 541                             "No VPD found. offset=%x status=%x", offset,
 542                             mb->mbxStatus);
 543                         break;
 544                 } else {
 545                         if (mb->un.varDmp.ra == 1) {
 546                                 uint32_t *lp1, *lp2;
 547                                 uint32_t bsize;
 548                                 uint32_t wsize;
 549 
 550                                 /*
 551                                  * mb->un.varDmp.word_cnt is actually byte
 552                                  * count for the dump reply
 553                                  */
 554                                 bsize = mb->un.varDmp.word_cnt;
 555 
 556                                 /* Stop if no data was received */
 557                                 if (bsize == 0) {
 558                                         break;
 559                                 }
 560 
 561                                 /* Check limit on byte size */
 562                                 bsize = (bsize >
 563                                     (sizeof (vpd_data) - offset)) ?
 564                                     (sizeof (vpd_data) - offset) : bsize;
 565 
 566                                 /*
 567                                  * Convert size from bytes to words with
 568                                  * minimum of 1 word
 569                                  */
 570                                 wsize = (bsize > 4) ? (bsize >> 2) : 1;
 571 
 572                                 /*
 573                                  * Transfer data into vpd_data buffer one
 574                                  * word at a time
 575                                  */
 576                                 lp1 = (uint32_t *)&mb->un.varDmp.resp_offset;
 577                                 lp2 = (uint32_t *)&vpd_data[offset];
 578 
 579                                 for (i = 0; i < wsize; i++) {
 580                                         status = *lp1++;
 581                                         *lp2++ = BE_SWAP32(status);
 582                                 }
 583 
 584                                 /* Increment total byte count saved */
 585                                 offset += (wsize << 2);
 586 
 587                                 /*
 588                                  * Stop if less than a full transfer was
 589                                  * received
 590                                  */
 591                                 if (wsize < DMP_VPD_DUMP_WCOUNT) {
 592                                         break;
 593                                 }
 594 
 595                         } else {
 596                                 EMLXS_MSGF(EMLXS_CONTEXT,
 597                                     &emlxs_init_debug_msg,
 598                                     "No VPD acknowledgment. offset=%x",
 599                                     offset);
 600                                 break;
 601                         }
 602                 }
 603 
 604         }
 605 
 606         if (vpd_data[0]) {
 607                 (void) emlxs_parse_vpd(hba, (uint8_t *)vpd_data, offset);
 608 
 609                 /*
 610                  * If there is a VPD part number, and it does not
 611                  * match the current default HBA model info,
 612                  * replace the default data with an entry that
 613                  * does match.
 614                  *
 615                  * After emlxs_parse_vpd model holds the VPD value
 616                  * for V2 and part_num hold the value for PN. These
 617                  * 2 values are NOT necessarily the same.
 618                  */
 619 
 620                 rval = 0;
 621                 if ((vpd->model[0] != 0) &&
 622                     (strcmp(&vpd->model[0], hba->model_info.model) != 0)) {
 623 
 624                         /* First scan for a V2 match */
 625 
 626                         for (i = 1; i < emlxs_pci_model_count; i++) {
 627                                 if (strcmp(&vpd->model[0],
 628                                     emlxs_pci_model[i].model) == 0) {
 629                                         bcopy(&emlxs_pci_model[i],
 630                                             &hba->model_info,
 631                                             sizeof (emlxs_model_t));
 632                                         rval = 1;
 633                                         break;
 634                                 }
 635                         }
 636                 }
 637 
 638                 if (!rval && (vpd->part_num[0] != 0) &&
 639                     (strcmp(&vpd->part_num[0], hba->model_info.model) != 0)) {
 640 
 641                         /* Next scan for a PN match */
 642 
 643                         for (i = 1; i < emlxs_pci_model_count; i++) {
 644                                 if (strcmp(&vpd->part_num[0],
 645                                     emlxs_pci_model[i].model) == 0) {
 646                                         bcopy(&emlxs_pci_model[i],
 647                                             &hba->model_info,
 648                                             sizeof (emlxs_model_t));
 649                                         break;
 650                                 }
 651                         }
 652                 }
 653 
 654                 /*
 655                  * Now lets update hba->model_info with the real
 656                  * VPD data, if any.
 657                  */
 658 
 659                 /*
 660                  * Replace the default model description with vpd data
 661                  */
 662                 if (vpd->model_desc[0] != 0) {
 663                         (void) strncpy(hba->model_info.model_desc,
 664                             vpd->model_desc,
 665                             (sizeof (hba->model_info.model_desc)-1));
 666                 }
 667 
 668                 /* Replace the default model with vpd data */
 669                 if (vpd->model[0] != 0) {
 670                         (void) strncpy(hba->model_info.model, vpd->model,
 671                             (sizeof (hba->model_info.model)-1));
 672                 }
 673 
 674                 /* Replace the default program types with vpd data */
 675                 if (vpd->prog_types[0] != 0) {
 676                         emlxs_parse_prog_types(hba, vpd->prog_types);
 677                 }
 678         }
 679 
 680         /*
 681          * Since the adapter model may have changed with the vpd data
 682          * lets double check if adapter is not supported
 683          */
 684         if (hba->model_info.flags & EMLXS_NOT_SUPPORTED) {
 685                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg,
 686                     "Unsupported adapter found.  "
 687                     "Id:%d  Device id:0x%x  SSDID:0x%x  Model:%s",
 688                     hba->model_info.id, hba->model_info.device_id,
 689                     hba->model_info.ssdid, hba->model_info.model);
 690 
 691                 rval = EIO;
 692                 goto failed;
 693         }
 694 
 695         /* Read the adapter's wakeup parms */
 696         (void) emlxs_read_wakeup_parms(hba, &hba->wakeup_parms, 1);
 697         emlxs_decode_version(hba->wakeup_parms.u0.boot_bios_wd[0],
 698             vpd->boot_version, sizeof (vpd->boot_version));
 699 
 700         /* Get fcode version property */
 701         emlxs_get_fcode_version(hba);
 702 
 703         EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
 704             "Firmware: kern=%08x stub=%08x sli1=%08x", vpd->postKernRev,
 705             vpd->opFwRev, vpd->sli1FwRev);
 706 
 707         EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
 708             "Firmware: sli2=%08x sli3=%08x sli4=%08x fl=%x", vpd->sli2FwRev,
 709             vpd->sli3FwRev, vpd->sli4FwRev, vpd->feaLevelHigh);
 710 
 711         EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
 712             "BIOS: boot=%s fcode=%s", vpd->boot_version, vpd->fcode_version);
 713 
 714         /*
 715          * If firmware checking is enabled and the adapter model indicates
 716          * a firmware image, then perform firmware version check
 717          */
 718         hba->fw_flag = 0;
 719         hba->fw_timer = 0;
 720 
 721         if (((fw_check & 0x1) &&
 722             (hba->model_info.flags & EMLXS_ORACLE_BRANDED) &&
 723             hba->model_info.fwid) || ((fw_check & 0x2) &&
 724             hba->model_info.fwid)) {
 725                 emlxs_firmware_t *fw;
 726 
 727                 /* Find firmware image indicated by adapter model */
 728                 fw = NULL;
 729                 for (i = 0; i < emlxs_fw_count; i++) {
 730                         if (emlxs_fw_table[i].id == hba->model_info.fwid) {
 731                                 fw = &emlxs_fw_table[i];
 732                                 break;
 733                         }
 734                 }
 735 
 736                 /*
 737                  * If the image was found, then verify current firmware
 738                  * versions of adapter
 739                  */
 740                 if (fw) {
 741                         if (!kern_update &&
 742                             ((fw->kern && (vpd->postKernRev != fw->kern)) ||
 743                             (fw->stub && (vpd->opFwRev != fw->stub)))) {
 744 
 745                                 hba->fw_flag |= FW_UPDATE_NEEDED;
 746 
 747                         } else if ((fw->kern && (vpd->postKernRev !=
 748                             fw->kern)) ||
 749                             (fw->stub && (vpd->opFwRev != fw->stub)) ||
 750                             (fw->sli1 && (vpd->sli1FwRev != fw->sli1)) ||
 751                             (fw->sli2 && (vpd->sli2FwRev != fw->sli2)) ||
 752                             (fw->sli3 && (vpd->sli3FwRev != fw->sli3)) ||
 753                             (fw->sli4 && (vpd->sli4FwRev != fw->sli4))) {
 754                                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_msg,
 755                                     "Firmware update needed. "
 756                                     "Updating. id=%d fw=%d",
 757                                     hba->model_info.id, hba->model_info.fwid);
 758 
 759 #ifdef MODFW_SUPPORT
 760                                 /*
 761                                  * Load the firmware image now
 762                                  * If MODFW_SUPPORT is not defined, the
 763                                  * firmware image will already be defined
 764                                  * in the emlxs_fw_table
 765                                  */
 766                                 emlxs_fw_load(hba, fw);
 767 #endif /* MODFW_SUPPORT */
 768 
 769                                 if (fw->image && fw->size) {
 770                                         uint32_t rc;
 771 
 772                                         rc = emlxs_fw_download(hba,
 773                                             (char *)fw->image, fw->size, 0);
 774                                         if ((rc != FC_SUCCESS) &&
 775                                             (rc != EMLXS_REBOOT_REQUIRED)) {
 776                                                 EMLXS_MSGF(EMLXS_CONTEXT,
 777                                                     &emlxs_init_msg,
 778                                                     "Firmware update failed.");
 779                                                 hba->fw_flag |=
 780                                                     FW_UPDATE_NEEDED;
 781                                         }
 782 #ifdef MODFW_SUPPORT
 783                                         /*
 784                                          * Unload the firmware image from
 785                                          * kernel memory
 786                                          */
 787                                         emlxs_fw_unload(hba, fw);
 788 #endif /* MODFW_SUPPORT */
 789 
 790                                         fw_check = 0;
 791 
 792                                         goto reset;
 793                                 }
 794 
 795                                 hba->fw_flag |= FW_UPDATE_NEEDED;
 796 
 797                                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_msg,
 798                                     "Firmware image unavailable.");
 799                         } else {
 800                                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_msg,
 801                                     "Firmware update not needed.");
 802                         }
 803                 } else {
 804                         /* This should not happen */
 805 
 806                         /*
 807                          * This means either the adapter database is not
 808                          * correct or a firmware image is missing from the
 809                          * compile
 810                          */
 811                         EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_msg,
 812                             "Firmware image unavailable. id=%d fw=%d",
 813                             hba->model_info.id, hba->model_info.fwid);
 814                 }
 815         }
 816 
 817         /*
 818          * Add our interrupt routine to kernel's interrupt chain & enable it
 819          * If MSI is enabled this will cause Solaris to program the MSI address
 820          * and data registers in PCI config space
 821          */
 822         if (EMLXS_INTR_ADD(hba) != DDI_SUCCESS) {
 823                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg,
 824                     "Unable to add interrupt(s).");
 825 
 826                 rval = EIO;
 827                 goto failed;
 828         }
 829 
 830         EMLXS_STATE_CHANGE(hba, FC_INIT_CFGPORT);
 831 
 832         /* Reuse mbq from previous mbox */
 833         bzero(mbq, sizeof (MAILBOXQ));
 834 
 835         (void) emlxs_mb_config_port(hba, mbq, sli_mode, key);
 836         if (emlxs_sli3_issue_mbox_cmd(hba, mbq, MBX_WAIT, 0) != MBX_SUCCESS) {
 837                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg,
 838                     "Unable to configure port. "
 839                     "Mailbox cmd=%x status=%x slimode=%d key=%x",
 840                     mb->mbxCommand, mb->mbxStatus, sli_mode, key);
 841 
 842                 for (sli_mode--; sli_mode > 0; sli_mode--) {
 843                         /* Check if sli_mode is supported by this adapter */
 844                         if (hba->model_info.sli_mask &
 845                             EMLXS_SLI_MASK(sli_mode)) {
 846                                 sli_mode_mask = EMLXS_SLI_MASK(sli_mode);
 847                                 break;
 848                         }
 849                 }
 850 
 851                 if (sli_mode) {
 852                         fw_check = 0;
 853 
 854                         goto reset;
 855                 }
 856 
 857                 hba->flag &= ~FC_SLIM2_MODE;
 858 
 859                 rval = EIO;
 860                 goto failed;
 861         }
 862 
 863         /* Check if SLI3 mode was achieved */
 864         if (mb->un.varCfgPort.rMA &&
 865             (mb->un.varCfgPort.sli_mode == EMLXS_HBA_SLI3_MODE)) {
 866 
 867                 if (mb->un.varCfgPort.vpi_max > 1) {
 868                         hba->flag |= FC_NPIV_ENABLED;
 869 
 870                         if (hba->model_info.chip >= EMLXS_SATURN_CHIP) {
 871                                 hba->vpi_max =
 872                                     min(mb->un.varCfgPort.vpi_max,
 873                                     MAX_VPORTS - 1);
 874                         } else {
 875                                 hba->vpi_max =
 876                                     min(mb->un.varCfgPort.vpi_max,
 877                                     MAX_VPORTS_LIMITED - 1);
 878                         }
 879                 }
 880 
 881 #if (EMLXS_MODREV >= EMLXS_MODREV5)
 882                 hba->fca_tran->fca_num_npivports =
 883                     (cfg[CFG_NPIV_ENABLE].current) ? hba->vpi_max : 0;
 884 #endif /* >= EMLXS_MODREV5 */
 885 
 886                 if (mb->un.varCfgPort.gerbm && mb->un.varCfgPort.max_hbq) {
 887                         hba->flag |= FC_HBQ_ENABLED;
 888                 }
 889 
 890                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
 891                     "SLI3 mode: flag=%x vpi_max=%d", hba->flag, hba->vpi_max);
 892         } else {
 893                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
 894                     "SLI2 mode: flag=%x", hba->flag);
 895                 sli_mode = EMLXS_HBA_SLI2_MODE;
 896                 sli_mode_mask = EMLXS_SLI2_MASK;
 897                 hba->sli_mode = sli_mode;
 898 #if (EMLXS_MODREV >= EMLXS_MODREV5)
 899                 hba->fca_tran->fca_num_npivports = 0;
 900 #endif /* >= EMLXS_MODREV5 */
 901 
 902         }
 903 
 904         /* Get and save the current firmware version (based on sli_mode) */
 905         emlxs_decode_firmware_rev(hba, vpd);
 906 
 907         emlxs_pcix_mxr_update(hba, 0);
 908 
 909         /* Reuse mbq from previous mbox */
 910         bzero(mbq, sizeof (MAILBOXQ));
 911 
 912         emlxs_mb_read_config(hba, mbq);
 913         if (emlxs_sli3_issue_mbox_cmd(hba, mbq, MBX_WAIT, 0) != MBX_SUCCESS) {
 914                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg,
 915                     "Unable to read configuration.  Mailbox cmd=%x status=%x",
 916                     mb->mbxCommand, mb->mbxStatus);
 917 
 918                 rval = EIO;
 919                 goto failed;
 920         }
 921 
 922         /* Save the link speed capabilities */
 923         vpd->link_speed = (uint16_t)mb->un.varRdConfig.lmt;
 924         emlxs_process_link_speed(hba);
 925 
 926         /* Set the max node count */
 927         if (cfg[CFG_NUM_NODES].current > 0) {
 928                 hba->max_nodes =
 929                     min(cfg[CFG_NUM_NODES].current,
 930                     mb->un.varRdConfig.max_rpi);
 931         } else {
 932                 hba->max_nodes = mb->un.varRdConfig.max_rpi;
 933         }
 934 
 935         /* Set the io throttle */
 936         hba->io_throttle = mb->un.varRdConfig.max_xri - IO_THROTTLE_RESERVE;
 937 
 938         /* Set max_iotag */
 939         if (cfg[CFG_NUM_IOTAGS].current) {
 940                 hba->max_iotag = (uint16_t)cfg[CFG_NUM_IOTAGS].current;
 941         } else {
 942                 hba->max_iotag = mb->un.varRdConfig.max_xri;
 943         }
 944 
 945         /* Set out-of-range iotag base */
 946         hba->fc_oor_iotag = hba->max_iotag;
 947 
 948         /*
 949          * Allocate some memory for buffers
 950          */
 951         if (emlxs_mem_alloc_buffer(hba) == 0) {
 952                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg,
 953                     "Unable to allocate memory buffers.");
 954 
 955                 EMLXS_STATE_CHANGE(hba, FC_ERROR);
 956                 return (ENOMEM);
 957         }
 958 
 959         /*
 960          * Setup and issue mailbox RUN BIU DIAG command Setup test buffers
 961          */
 962         if (((mp = (MATCHMAP *)emlxs_mem_get(hba, MEM_BUF)) == 0) ||
 963             ((mp1 = (MATCHMAP *)emlxs_mem_get(hba, MEM_BUF)) == 0)) {
 964                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg,
 965                     "Unable to allocate diag buffers.");
 966 
 967                 rval = ENOMEM;
 968                 goto failed;
 969         }
 970 
 971         bcopy((caddr_t)&emlxs_diag_pattern[0], (caddr_t)mp->virt,
 972             MEM_ELSBUF_SIZE);
 973         EMLXS_MPDATA_SYNC(mp->dma_handle, 0, MEM_ELSBUF_SIZE,
 974             DDI_DMA_SYNC_FORDEV);
 975 
 976         bzero(mp1->virt, MEM_ELSBUF_SIZE);
 977         EMLXS_MPDATA_SYNC(mp1->dma_handle, 0, MEM_ELSBUF_SIZE,
 978             DDI_DMA_SYNC_FORDEV);
 979 
 980         /* Reuse mbq from previous mbox */
 981         bzero(mbq, sizeof (MAILBOXQ));
 982 
 983         (void) emlxs_mb_run_biu_diag(hba, mbq, mp->phys, mp1->phys);
 984 
 985         if (emlxs_sli3_issue_mbox_cmd(hba, mbq, MBX_WAIT, 0) != MBX_SUCCESS) {
 986                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg,
 987                     "Unable to run BIU diag.  Mailbox cmd=%x status=%x",
 988                     mb->mbxCommand, mb->mbxStatus);
 989 
 990                 rval = EIO;
 991                 goto failed;
 992         }
 993 
 994         EMLXS_MPDATA_SYNC(mp1->dma_handle, 0, MEM_ELSBUF_SIZE,
 995             DDI_DMA_SYNC_FORKERNEL);
 996 
 997 #ifdef FMA_SUPPORT
 998         if (mp->dma_handle) {
 999                 if (emlxs_fm_check_dma_handle(hba, mp->dma_handle)
1000                     != DDI_FM_OK) {
1001                         EMLXS_MSGF(EMLXS_CONTEXT,
1002                             &emlxs_invalid_dma_handle_msg,
1003                             "sli3_online: hdl=%p",
1004                             mp->dma_handle);
1005                         rval = EIO;
1006                         goto failed;
1007                 }
1008         }
1009 
1010         if (mp1->dma_handle) {
1011                 if (emlxs_fm_check_dma_handle(hba, mp1->dma_handle)
1012                     != DDI_FM_OK) {
1013                         EMLXS_MSGF(EMLXS_CONTEXT,
1014                             &emlxs_invalid_dma_handle_msg,
1015                             "sli3_online: hdl=%p",
1016                             mp1->dma_handle);
1017                         rval = EIO;
1018                         goto failed;
1019                 }
1020         }
1021 #endif  /* FMA_SUPPORT */
1022 
1023         outptr = mp->virt;
1024         inptr = mp1->virt;
1025 
1026         for (i = 0; i < MEM_ELSBUF_SIZE; i++) {
1027                 if (*outptr++ != *inptr++) {
1028                         outptr--;
1029                         inptr--;
1030 
1031                         EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg,
1032                             "BIU diagnostic failed. "
1033                             "offset %x value %x should be %x.",
1034                             i, (uint32_t)*inptr, (uint32_t)*outptr);
1035 
1036                         rval = EIO;
1037                         goto failed;
1038                 }
1039         }
1040 
1041         /* Free the buffers since we were polling */
1042         emlxs_mem_put(hba, MEM_BUF, (void *)mp);
1043         mp = NULL;
1044         emlxs_mem_put(hba, MEM_BUF, (void *)mp1);
1045         mp1 = NULL;
1046 
1047         hba->channel_fcp = FC_FCP_RING;
1048         hba->channel_els = FC_ELS_RING;
1049         hba->channel_ip = FC_IP_RING;
1050         hba->channel_ct = FC_CT_RING;
1051         hba->sli.sli3.ring_count = MAX_RINGS;
1052 
1053         hba->channel_tx_count = 0;
1054         hba->io_count = 0;
1055         hba->fc_iotag = 1;
1056 
1057         for (i = 0; i < hba->chan_count; i++) {
1058                 cp = &hba->chan[i];
1059 
1060                 /* 1 to 1 mapping between ring and channel */
1061                 cp->iopath = (void *)&hba->sli.sli3.ring[i];
1062 
1063                 cp->hba = hba;
1064                 cp->channelno = i;
1065         }
1066 
1067         /*
1068          * Setup and issue mailbox CONFIGURE RING command
1069          */
1070         for (i = 0; i < (uint32_t)hba->sli.sli3.ring_count; i++) {
1071                 /*
1072                  * Initialize cmd/rsp ring pointers
1073                  */
1074                 rp = &hba->sli.sli3.ring[i];
1075 
1076                 /* 1 to 1 mapping between ring and channel */
1077                 rp->channelp = &hba->chan[i];
1078 
1079                 rp->hba = hba;
1080                 rp->ringno = (uint8_t)i;
1081 
1082                 rp->fc_cmdidx = 0;
1083                 rp->fc_rspidx = 0;
1084                 EMLXS_STATE_CHANGE(hba, FC_INIT_CFGRING);
1085 
1086                 /* Reuse mbq from previous mbox */
1087                 bzero(mbq, sizeof (MAILBOXQ));
1088 
1089                 emlxs_mb_config_ring(hba, i, mbq);
1090                 if (emlxs_sli3_issue_mbox_cmd(hba, mbq, MBX_WAIT, 0) !=
1091                     MBX_SUCCESS) {
1092                         EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg,
1093                             "Unable to configure ring. "
1094                             "Mailbox cmd=%x status=%x",
1095                             mb->mbxCommand, mb->mbxStatus);
1096 
1097                         rval = EIO;
1098                         goto failed;
1099                 }
1100         }
1101 
1102         /*
1103          * Setup link timers
1104          */
1105         EMLXS_STATE_CHANGE(hba, FC_INIT_INITLINK);
1106 
1107         /* Reuse mbq from previous mbox */
1108         bzero(mbq, sizeof (MAILBOXQ));
1109 
1110         emlxs_mb_config_link(hba, mbq);
1111         if (emlxs_sli3_issue_mbox_cmd(hba, mbq, MBX_WAIT, 0) != MBX_SUCCESS) {
1112                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg,
1113                     "Unable to configure link. Mailbox cmd=%x status=%x",
1114                     mb->mbxCommand, mb->mbxStatus);
1115 
1116                 rval = EIO;
1117                 goto failed;
1118         }
1119 
1120 #ifdef MAX_RRDY_SUPPORT
1121         /* Set MAX_RRDY if one is provided */
1122         if (cfg[CFG_MAX_RRDY].current) {
1123 
1124                 /* Reuse mbq from previous mbox */
1125                 bzero(mbq, sizeof (MAILBOXQ));
1126 
1127                 emlxs_mb_set_var(hba, (MAILBOX *)mbq, 0x00060412,
1128                     cfg[CFG_MAX_RRDY].current);
1129 
1130                 if (emlxs_sli3_issue_mbox_cmd(hba, mbq, MBX_WAIT, 0) !=
1131                     MBX_SUCCESS) {
1132                         EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
1133                             "MAX_RRDY: Unable to set.  status=%x " \
1134                             "value=%d",
1135                             mb->mbxStatus, cfg[CFG_MAX_RRDY].current);
1136                 } else {
1137                         EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
1138                             "MAX_RRDY: %d", cfg[CFG_MAX_RRDY].current);
1139                 }
1140         }
1141 #endif /* MAX_RRDY_SUPPORT */
1142 
1143         /* Reuse mbq from previous mbox */
1144         bzero(mbq, sizeof (MAILBOXQ));
1145 
1146         /*
1147          * We need to get login parameters for NID
1148          */
1149         (void) emlxs_mb_read_sparam(hba, mbq);
1150         mp = (MATCHMAP *)mbq->bp;
1151         if (emlxs_sli3_issue_mbox_cmd(hba, mbq, MBX_WAIT, 0) != MBX_SUCCESS) {
1152                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg,
1153                     "Unable to read parameters. Mailbox cmd=%x status=%x",
1154                     mb->mbxCommand, mb->mbxStatus);
1155 
1156                 rval = EIO;
1157                 goto failed;
1158         }
1159 
1160         /* Free the buffer since we were polling */
1161         emlxs_mem_put(hba, MEM_BUF, (void *)mp);
1162         mp = NULL;
1163 
1164         /* If no serial number in VPD data, then use the WWPN */
1165         if (vpd->serial_num[0] == 0) {
1166                 outptr = (uint8_t *)&hba->wwpn.IEEE[0];
1167                 for (i = 0; i < 12; i++) {
1168                         status = *outptr++;
1169                         j = ((status & 0xf0) >> 4);
1170                         if (j <= 9) {
1171                                 vpd->serial_num[i] =
1172                                     (char)((uint8_t)'0' + (uint8_t)j);
1173                         } else {
1174                                 vpd->serial_num[i] =
1175                                     (char)((uint8_t)'A' + (uint8_t)(j - 10));
1176                         }
1177 
1178                         i++;
1179                         j = (status & 0xf);
1180                         if (j <= 9) {
1181                                 vpd->serial_num[i] =
1182                                     (char)((uint8_t)'0' + (uint8_t)j);
1183                         } else {
1184                                 vpd->serial_num[i] =
1185                                     (char)((uint8_t)'A' + (uint8_t)(j - 10));
1186                         }
1187                 }
1188 
1189                 /*
1190                  * Set port number and port index to zero
1191                  * The WWN's are unique to each port and therefore port_num
1192                  * must equal zero. This effects the hba_fru_details structure
1193                  * in fca_bind_port()
1194                  */
1195                 vpd->port_num[0] = 0;
1196                 vpd->port_index = 0;
1197         }
1198 
1199         /*
1200          * Make first attempt to set a port index
1201          * Check if this is a multifunction adapter
1202          */
1203         if ((vpd->port_index == (uint32_t)-1) &&
1204             (hba->model_info.chip >= EMLXS_THOR_CHIP)) {
1205                 char *buffer;
1206                 int32_t i;
1207 
1208                 /*
1209                  * The port address looks like this:
1210                  * 1    - for port index 0
1211                  * 1,1  - for port index 1
1212                  * 1,2  - for port index 2
1213                  */
1214                 buffer = ddi_get_name_addr(hba->dip);
1215 
1216                 if (buffer) {
1217                         vpd->port_index = 0;
1218 
1219                         /* Reverse scan for a comma */
1220                         for (i = strlen(buffer) - 1; i > 0; i--) {
1221                                 if (buffer[i] == ',') {
1222                                         /* Comma found - set index now */
1223                                         vpd->port_index =
1224                                             emlxs_strtol(&buffer[i + 1], 10);
1225                                         break;
1226                                 }
1227                         }
1228                 }
1229         }
1230 
1231         /* Make final attempt to set a port index */
1232         if (vpd->port_index == (uint32_t)-1) {
1233                 dev_info_t *p_dip;
1234                 dev_info_t *c_dip;
1235 
1236                 p_dip = ddi_get_parent(hba->dip);
1237                 c_dip = ddi_get_child(p_dip);
1238 
1239                 vpd->port_index = 0;
1240                 while (c_dip && (hba->dip != c_dip)) {
1241                         c_dip = ddi_get_next_sibling(c_dip);
1242                         vpd->port_index++;
1243                 }
1244         }
1245 
1246         if (vpd->port_num[0] == 0) {
1247                 if (hba->model_info.channels == EMLXS_MULTI_CHANNEL) {
1248                         (void) snprintf(vpd->port_num,
1249                             (sizeof (vpd->port_num)-1),
1250                             "%d", vpd->port_index);
1251                 }
1252         }
1253 
1254         if (vpd->id[0] == 0) {
1255                 (void) strncpy(vpd->id, hba->model_info.model_desc,
1256                     (sizeof (vpd->id)-1));
1257         }
1258 
1259         if (vpd->manufacturer[0] == 0) {
1260                 (void) strncpy(vpd->manufacturer, hba->model_info.manufacturer,
1261                     (sizeof (vpd->manufacturer)-1));
1262         }
1263 
1264         if (vpd->part_num[0] == 0) {
1265                 (void) strncpy(vpd->part_num, hba->model_info.model,
1266                     (sizeof (vpd->part_num)-1));
1267         }
1268 
1269         if (vpd->model_desc[0] == 0) {
1270                 (void) strncpy(vpd->model_desc, hba->model_info.model_desc,
1271                     (sizeof (vpd->model_desc)-1));
1272         }
1273 
1274         if (vpd->model[0] == 0) {
1275                 (void) strncpy(vpd->model, hba->model_info.model,
1276                     (sizeof (vpd->model)-1));
1277         }
1278 
1279         if (vpd->prog_types[0] == 0) {
1280                 emlxs_build_prog_types(hba, vpd);
1281         }
1282 
1283         /* Create the symbolic names */
1284         (void) snprintf(hba->snn, (sizeof (hba->snn)-1),
1285             "Emulex %s FV%s DV%s %s",
1286             hba->model_info.model, hba->vpd.fw_version, emlxs_version,
1287             (char *)utsname.nodename);
1288 
1289         (void) snprintf(hba->spn, (sizeof (hba->spn)-1),
1290             "Emulex PPN-%01x%01x:%02x:%02x:%02x:%02x:%02x:%02x:%02x",
1291             hba->wwpn.nameType, hba->wwpn.IEEEextMsn, hba->wwpn.IEEEextLsb,
1292             hba->wwpn.IEEE[0], hba->wwpn.IEEE[1], hba->wwpn.IEEE[2],
1293             hba->wwpn.IEEE[3], hba->wwpn.IEEE[4], hba->wwpn.IEEE[5]);
1294 
1295         if (cfg[CFG_NETWORK_ON].current) {
1296                 if ((hba->sparam.portName.nameType != NAME_IEEE) ||
1297                     (hba->sparam.portName.IEEEextMsn != 0) ||
1298                     (hba->sparam.portName.IEEEextLsb != 0)) {
1299 
1300                         EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_msg,
1301                             "WWPN doesn't conform to IP profile: "
1302                             "nameType=%x. Disabling networking.",
1303                             hba->sparam.portName.nameType);
1304 
1305                         cfg[CFG_NETWORK_ON].current = 0;
1306                 }
1307         }
1308 
1309         if (cfg[CFG_NETWORK_ON].current) {
1310                 /* Reuse mbq from previous mbox */
1311                 bzero(mbq, sizeof (MAILBOXQ));
1312 
1313                 /* Issue CONFIG FARP */
1314                 emlxs_mb_config_farp(hba, mbq);
1315                 if (emlxs_sli3_issue_mbox_cmd(hba, mbq, MBX_WAIT, 0) !=
1316                     MBX_SUCCESS) {
1317                         /*
1318                          * Let it go through even if failed.
1319                          */
1320                         EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_msg,
1321                             "Unable to configure FARP. "
1322                             "Mailbox cmd=%x status=%x",
1323                             mb->mbxCommand, mb->mbxStatus);
1324                 }
1325         }
1326 #ifdef MSI_SUPPORT
1327         /* Configure MSI map if required */
1328         if (hba->intr_count > 1) {
1329 
1330                 if (hba->intr_type == DDI_INTR_TYPE_MSIX) {
1331                         /* always start from 0 */
1332                         hba->last_msiid = 0;
1333                 }
1334 
1335                 /* Reuse mbq from previous mbox */
1336                 bzero(mbq, sizeof (MAILBOXQ));
1337 
1338                 emlxs_mb_config_msix(hba, mbq, hba->intr_map, hba->intr_count);
1339 
1340                 if (emlxs_sli3_issue_mbox_cmd(hba, mbq, MBX_WAIT, 0) ==
1341                     MBX_SUCCESS) {
1342                         goto msi_configured;
1343                 }
1344 
1345                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
1346                     "Unable to config MSIX.  Mailbox cmd=0x%x status=0x%x",
1347                     mb->mbxCommand, mb->mbxStatus);
1348 
1349                 /* Reuse mbq from previous mbox */
1350                 bzero(mbq, sizeof (MAILBOXQ));
1351 
1352                 emlxs_mb_config_msi(hba, mbq, hba->intr_map, hba->intr_count);
1353 
1354                 if (emlxs_sli3_issue_mbox_cmd(hba, mbq, MBX_WAIT, 0) ==
1355                     MBX_SUCCESS) {
1356                         goto msi_configured;
1357                 }
1358 
1359 
1360                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
1361                     "Unable to config MSI.  Mailbox cmd=0x%x status=0x%x",
1362                     mb->mbxCommand, mb->mbxStatus);
1363 
1364                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
1365                     "Attempting single interrupt mode...");
1366 
1367                 /* First cleanup old interrupts */
1368                 (void) emlxs_msi_remove(hba);
1369                 (void) emlxs_msi_uninit(hba);
1370 
1371                 status = emlxs_msi_init(hba, 1);
1372 
1373                 if (status != DDI_SUCCESS) {
1374                         EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg,
1375                             "Unable to initialize interrupt. status=%d",
1376                             status);
1377 
1378                         rval = EIO;
1379                         goto failed;
1380                 }
1381 
1382                 /*
1383                  * Reset adapter - The adapter needs to be reset because
1384                  * the bus cannot handle the MSI change without handshaking
1385                  * with the adapter again
1386                  */
1387 
1388                 (void) emlxs_mem_free_buffer(hba);
1389                 fw_check = 0;
1390                 goto reset;
1391         }
1392 
1393 msi_configured:
1394 
1395 
1396         if ((hba->intr_count >= 1) &&
1397             (hba->sli_mode == EMLXS_HBA_SLI3_MODE)) {
1398                 /* intr_count is a sequence of msi id */
1399                 /* Setup msi2chan[msi_id] */
1400                 for (i = 0; i < hba->intr_count; i ++) {
1401                         hba->msi2chan[i] = i;
1402                         if (i >= hba->chan_count)
1403                                 hba->msi2chan[i] = (i - hba->chan_count);
1404                 }
1405         }
1406 #endif /* MSI_SUPPORT */
1407 
1408         /*
1409          * We always disable the firmware traffic cop feature
1410          */
1411         if (emlxs_disable_traffic_cop) {
1412                 /* Reuse mbq from previous mbox */
1413                 bzero(mbq, sizeof (MAILBOXQ));
1414 
1415                 emlxs_disable_tc(hba, mbq);
1416                 if (emlxs_sli3_issue_mbox_cmd(hba, mbq, MBX_WAIT, 0) !=
1417                     MBX_SUCCESS) {
1418                         EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg,
1419                             "Unable to disable traffic cop. "
1420                             "Mailbox cmd=%x status=%x",
1421                             mb->mbxCommand, mb->mbxStatus);
1422 
1423                         rval = EIO;
1424                         goto failed;
1425                 }
1426         }
1427 
1428 
1429         /* Reuse mbq from previous mbox */
1430         bzero(mbq, sizeof (MAILBOXQ));
1431 
1432         /* Register for async events */
1433         emlxs_mb_async_event(hba, mbq);
1434         if (emlxs_sli3_issue_mbox_cmd(hba, mbq, MBX_WAIT, 0) != MBX_SUCCESS) {
1435                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
1436                     "Async events disabled. Mailbox status=%x",
1437                     mb->mbxStatus);
1438         } else {
1439                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
1440                     "Async events enabled.");
1441                 hba->flag |= FC_ASYNC_EVENTS;
1442         }
1443 
1444         EMLXS_STATE_CHANGE(hba, FC_LINK_DOWN);
1445 
1446         emlxs_sli3_enable_intr(hba);
1447 
1448         if (hba->flag & FC_HBQ_ENABLED) {
1449                 if (port->flag & EMLXS_TGT_ENABLED) {
1450                         if (emlxs_hbq_setup(hba, EMLXS_FCT_HBQ_ID)) {
1451                                 EMLXS_MSGF(EMLXS_CONTEXT,
1452                                     &emlxs_init_failed_msg,
1453                                     "Unable to setup FCT HBQ.");
1454 
1455                                 rval = ENOMEM;
1456 
1457 #ifdef SFCT_SUPPORT
1458                                 /* Check if we can fall back to just */
1459                                 /* initiator mode */
1460                                 if ((hba->pm_state == EMLXS_PM_IN_ATTACH) &&
1461                                     (port->flag & EMLXS_INI_ENABLED) &&
1462                                     (cfg[CFG_DTM_ENABLE].current == 1) &&
1463                                     (cfg[CFG_TARGET_MODE].current == 0)) {
1464 
1465                                         cfg[CFG_DTM_ENABLE].current = 0;
1466 
1467                                         EMLXS_MSGF(EMLXS_CONTEXT,
1468                                             &emlxs_init_failed_msg,
1469                                             "Disabling dynamic target mode. "
1470                                             "Enabling initiator mode only.");
1471 
1472                                         /* This will trigger the driver to */
1473                                         /* reattach */
1474                                         rval = EAGAIN;
1475                                 }
1476 #endif /* SFCT_SUPPORT */
1477                                 goto failed;
1478                         }
1479                         EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
1480                             "FCT Ring: Posted %d buffers.", MEM_FCTBUF_COUNT);
1481                 }
1482 
1483                 if (cfg[CFG_NETWORK_ON].current) {
1484                         if (emlxs_hbq_setup(hba, EMLXS_IP_HBQ_ID)) {
1485                                 EMLXS_MSGF(EMLXS_CONTEXT,
1486                                     &emlxs_init_failed_msg,
1487                                     "Unable to setup IP HBQ.");
1488 
1489                                 rval = ENOMEM;
1490                                 goto failed;
1491                         }
1492                         EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
1493                             "IP  Ring: Posted %d buffers.", MEM_IPBUF_COUNT);
1494                 }
1495 
1496                 if (emlxs_hbq_setup(hba, EMLXS_ELS_HBQ_ID)) {
1497                         EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg,
1498                             "Unable to setup ELS HBQ.");
1499                         rval = ENOMEM;
1500                         goto failed;
1501                 }
1502                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
1503                     "ELS Ring: Posted %d buffers.", MEM_ELSBUF_COUNT);
1504 
1505                 if (emlxs_hbq_setup(hba, EMLXS_CT_HBQ_ID)) {
1506                         EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg,
1507                             "Unable to setup CT HBQ.");
1508 
1509                         rval = ENOMEM;
1510                         goto failed;
1511                 }
1512                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
1513                     "CT  Ring: Posted %d buffers.", MEM_CTBUF_COUNT);
1514         } else {
1515                 if (port->flag & EMLXS_TGT_ENABLED) {
1516                         /* Post the FCT unsol buffers */
1517                         rp = &hba->sli.sli3.ring[FC_FCT_RING];
1518                         for (j = 0; j < MEM_FCTBUF_COUNT; j += 2) {
1519                                 (void) emlxs_post_buffer(hba, rp, 2);
1520                         }
1521                         EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
1522                             "FCP Ring: Posted %d buffers.", MEM_FCTBUF_COUNT);
1523                 }
1524 
1525                 if (cfg[CFG_NETWORK_ON].current) {
1526                         /* Post the IP unsol buffers */
1527                         rp = &hba->sli.sli3.ring[FC_IP_RING];
1528                         for (j = 0; j < MEM_IPBUF_COUNT; j += 2) {
1529                                 (void) emlxs_post_buffer(hba, rp, 2);
1530                         }
1531                         EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
1532                             "IP  Ring: Posted %d buffers.", MEM_IPBUF_COUNT);
1533                 }
1534 
1535                 /* Post the ELS unsol buffers */
1536                 rp = &hba->sli.sli3.ring[FC_ELS_RING];
1537                 for (j = 0; j < MEM_ELSBUF_COUNT; j += 2) {
1538                         (void) emlxs_post_buffer(hba, rp, 2);
1539                 }
1540                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
1541                     "ELS Ring: Posted %d buffers.", MEM_ELSBUF_COUNT);
1542 
1543 
1544                 /* Post the CT unsol buffers */
1545                 rp = &hba->sli.sli3.ring[FC_CT_RING];
1546                 for (j = 0; j < MEM_CTBUF_COUNT; j += 2) {
1547                         (void) emlxs_post_buffer(hba, rp, 2);
1548                 }
1549                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
1550                     "CT  Ring: Posted %d buffers.", MEM_CTBUF_COUNT);
1551         }
1552 
1553         (void) kmem_free((uint8_t *)mbq, sizeof (MAILBOXQ));
1554 
1555         /* Check persist-linkdown */
1556         if (cfg[CFG_PERSIST_LINKDOWN].current) {
1557                 EMLXS_STATE_CHANGE(hba, FC_LINK_DOWN_PERSIST);
1558                 return (0);
1559         }
1560 
1561 #ifdef SFCT_SUPPORT
1562         if ((port->mode == MODE_TARGET) &&
1563             !(port->fct_flags & FCT_STATE_PORT_ONLINE)) {
1564                 emlxs_enable_latt(hba);
1565                 return (0);
1566         }
1567 #endif /* SFCT_SUPPORT */
1568 
1569         /*
1570          * Setup and issue mailbox INITIALIZE LINK command
1571          * At this point, the interrupt will be generated by the HW
1572          */
1573         mbq = (MAILBOXQ *)emlxs_mem_get(hba, MEM_MBOX);
1574         if (mbq == NULL) {
1575                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg,
1576                     "Unable to allocate mailbox buffer.");
1577 
1578                 rval = EIO;
1579                 goto failed;
1580         }
1581         mb = (MAILBOX *)mbq;
1582 
1583         emlxs_mb_init_link(hba, mbq, cfg[CFG_TOPOLOGY].current,
1584             cfg[CFG_LINK_SPEED].current);
1585 
1586         rval = emlxs_sli3_issue_mbox_cmd(hba, mbq, MBX_NOWAIT, 0);
1587         if ((rval != MBX_SUCCESS) && (rval != MBX_BUSY)) {
1588                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg,
1589                     "Unable to initialize link. " \
1590                     "Mailbox cmd=%x status=%x",
1591                     mb->mbxCommand, mb->mbxStatus);
1592 
1593                 emlxs_mem_put(hba, MEM_MBOX, (void *)mbq);
1594                 mbq = NULL;
1595                 rval = EIO;
1596                 goto failed;
1597         }
1598 
1599         /*
1600          * Enable link attention interrupt
1601          */
1602         emlxs_enable_latt(hba);
1603 
1604         /* Wait for link to come up */
1605         i = cfg[CFG_LINKUP_DELAY].current;
1606         while (i && (hba->state < FC_LINK_UP)) {
1607                 /* Check for hardware error */
1608                 if (hba->state == FC_ERROR) {
1609                         EMLXS_MSGF(EMLXS_CONTEXT,
1610                             &emlxs_init_failed_msg,
1611                             "Adapter error.");
1612 
1613                         mbq = NULL;
1614                         rval = EIO;
1615                         goto failed;
1616                 }
1617 
1618                 BUSYWAIT_MS(1000);
1619                 i--;
1620         }
1621 
1622         /*
1623          * The leadvile driver will now handle the FLOGI at the driver level
1624          */
1625 
1626         return (0);
1627 
1628 failed:
1629 
1630         EMLXS_STATE_CHANGE(hba, FC_ERROR);
1631 
1632         if (hba->intr_flags & EMLXS_MSI_ADDED) {
1633                 (void) EMLXS_INTR_REMOVE(hba);
1634         }
1635 
1636         if (mp) {
1637                 emlxs_mem_put(hba, MEM_BUF, (void *)mp);
1638                 mp = NULL;
1639         }
1640 
1641         if (mp1) {
1642                 emlxs_mem_put(hba, MEM_BUF, (void *)mp1);
1643                 mp1 = NULL;
1644         }
1645 
1646         (void) emlxs_mem_free_buffer(hba);
1647 
1648         if (mbq) {
1649                 (void) kmem_free((uint8_t *)mbq, sizeof (MAILBOXQ));
1650                 mbq = NULL;
1651                 mb = NULL;
1652         }
1653 
1654         if (rval == 0) {
1655                 rval = EIO;
1656         }
1657 
1658         return (rval);
1659 
1660 } /* emlxs_sli3_online() */
1661 
1662 
1663 /*ARGSUSED*/
1664 static void
1665 emlxs_sli3_offline(emlxs_hba_t *hba, uint32_t reset_requested)
1666 {
1667         /* Reverse emlxs_sli3_online */
1668 
1669         /* Kill the adapter */
1670         emlxs_sli3_hba_kill(hba);
1671 
1672         /* Free driver shared memory */
1673         (void) emlxs_mem_free_buffer(hba);
1674 
1675 } /* emlxs_sli3_offline() */
1676 
1677 
1678 static int
1679 emlxs_sli3_map_hdw(emlxs_hba_t *hba)
1680 {
1681         emlxs_port_t            *port = &PPORT;
1682         dev_info_t              *dip;
1683         ddi_device_acc_attr_t   dev_attr;
1684         int                     status;
1685 
1686         dip = (dev_info_t *)hba->dip;
1687         dev_attr = emlxs_dev_acc_attr;
1688 
1689         if (hba->bus_type == SBUS_FC) {
1690 
1691                 if (hba->sli.sli3.slim_acc_handle == 0) {
1692                         status = ddi_regs_map_setup(dip,
1693                             SBUS_DFLY_SLIM_RINDEX,
1694                             (caddr_t *)&hba->sli.sli3.slim_addr,
1695                             0, 0, &dev_attr, &hba->sli.sli3.slim_acc_handle);
1696                         if (status != DDI_SUCCESS) {
1697                                 EMLXS_MSGF(EMLXS_CONTEXT,
1698                                     &emlxs_attach_failed_msg,
1699                                     "(SBUS) ddi_regs_map_setup SLIM failed. "
1700                                     "status=%x", status);
1701                                 goto failed;
1702                         }
1703                 }
1704                 if (hba->sli.sli3.csr_acc_handle == 0) {
1705                         status = ddi_regs_map_setup(dip,
1706                             SBUS_DFLY_CSR_RINDEX,
1707                             (caddr_t *)&hba->sli.sli3.csr_addr,
1708                             0, 0, &dev_attr, &hba->sli.sli3.csr_acc_handle);
1709                         if (status != DDI_SUCCESS) {
1710                                 EMLXS_MSGF(EMLXS_CONTEXT,
1711                                     &emlxs_attach_failed_msg,
1712                                     "(SBUS) ddi_regs_map_setup DFLY CSR "
1713                                     "failed. status=%x", status);
1714                                 goto failed;
1715                         }
1716                 }
1717                 if (hba->sli.sli3.sbus_flash_acc_handle == 0) {
1718                         status = ddi_regs_map_setup(dip, SBUS_FLASH_RDWR,
1719                             (caddr_t *)&hba->sli.sli3.sbus_flash_addr, 0, 0,
1720                             &dev_attr, &hba->sli.sli3.sbus_flash_acc_handle);
1721                         if (status != DDI_SUCCESS) {
1722                                 EMLXS_MSGF(EMLXS_CONTEXT,
1723                                     &emlxs_attach_failed_msg,
1724                                     "(SBUS) ddi_regs_map_setup Fcode Flash "
1725                                     "failed. status=%x", status);
1726                                 goto failed;
1727                         }
1728                 }
1729                 if (hba->sli.sli3.sbus_core_acc_handle == 0) {
1730                         status = ddi_regs_map_setup(dip, SBUS_TITAN_CORE_RINDEX,
1731                             (caddr_t *)&hba->sli.sli3.sbus_core_addr, 0, 0,
1732                             &dev_attr, &hba->sli.sli3.sbus_core_acc_handle);
1733                         if (status != DDI_SUCCESS) {
1734                                 EMLXS_MSGF(EMLXS_CONTEXT,
1735                                     &emlxs_attach_failed_msg,
1736                                     "(SBUS) ddi_regs_map_setup TITAN CORE "
1737                                     "failed. status=%x", status);
1738                                 goto failed;
1739                         }
1740                 }
1741 
1742                 if (hba->sli.sli3.sbus_csr_handle == 0) {
1743                         status = ddi_regs_map_setup(dip, SBUS_TITAN_CSR_RINDEX,
1744                             (caddr_t *)&hba->sli.sli3.sbus_csr_addr,
1745                             0, 0, &dev_attr, &hba->sli.sli3.sbus_csr_handle);
1746                         if (status != DDI_SUCCESS) {
1747                                 EMLXS_MSGF(EMLXS_CONTEXT,
1748                                     &emlxs_attach_failed_msg,
1749                                     "(SBUS) ddi_regs_map_setup TITAN CSR "
1750                                     "failed. status=%x", status);
1751                                 goto failed;
1752                         }
1753                 }
1754         } else {        /* ****** PCI ****** */
1755 
1756                 if (hba->sli.sli3.slim_acc_handle == 0) {
1757                         status = ddi_regs_map_setup(dip, PCI_SLIM_RINDEX,
1758                             (caddr_t *)&hba->sli.sli3.slim_addr,
1759                             0, 0, &dev_attr, &hba->sli.sli3.slim_acc_handle);
1760                         if (status != DDI_SUCCESS) {
1761                                 EMLXS_MSGF(EMLXS_CONTEXT,
1762                                     &emlxs_attach_failed_msg,
1763                                     "(PCI) ddi_regs_map_setup SLIM failed. "
1764                                     "stat=%d mem=%p attr=%p hdl=%p",
1765                                     status, &hba->sli.sli3.slim_addr, &dev_attr,
1766                                     &hba->sli.sli3.slim_acc_handle);
1767                                 goto failed;
1768                         }
1769                 }
1770 
1771                 /*
1772                  * Map in control registers, using memory-mapped version of
1773                  * the registers rather than the I/O space-mapped registers.
1774                  */
1775                 if (hba->sli.sli3.csr_acc_handle == 0) {
1776                         status = ddi_regs_map_setup(dip, PCI_CSR_RINDEX,
1777                             (caddr_t *)&hba->sli.sli3.csr_addr,
1778                             0, 0, &dev_attr, &hba->sli.sli3.csr_acc_handle);
1779                         if (status != DDI_SUCCESS) {
1780                                 EMLXS_MSGF(EMLXS_CONTEXT,
1781                                     &emlxs_attach_failed_msg,
1782                                     "ddi_regs_map_setup CSR failed. status=%x",
1783                                     status);
1784                                 goto failed;
1785                         }
1786                 }
1787         }
1788 
1789         if (hba->sli.sli3.slim2.virt == 0) {
1790                 MBUF_INFO       *buf_info;
1791                 MBUF_INFO       bufinfo;
1792 
1793                 buf_info = &bufinfo;
1794 
1795                 bzero(buf_info, sizeof (MBUF_INFO));
1796                 buf_info->size = SLI_SLIM2_SIZE;
1797                 buf_info->flags =
1798                     FC_MBUF_DMA | FC_MBUF_SNGLSG | FC_MBUF_DMA32;
1799                 buf_info->align = ddi_ptob(dip, 1L);
1800 
1801                 (void) emlxs_mem_alloc(hba, buf_info);
1802 
1803                 if (buf_info->virt == NULL) {
1804                         goto failed;
1805                 }
1806 
1807                 hba->sli.sli3.slim2.virt = buf_info->virt;
1808                 hba->sli.sli3.slim2.phys = buf_info->phys;
1809                 hba->sli.sli3.slim2.size = SLI_SLIM2_SIZE;
1810                 hba->sli.sli3.slim2.data_handle = buf_info->data_handle;
1811                 hba->sli.sli3.slim2.dma_handle = buf_info->dma_handle;
1812                 bzero((char *)hba->sli.sli3.slim2.virt, SLI_SLIM2_SIZE);
1813         }
1814 
1815         /* offset from beginning of register space */
1816         hba->sli.sli3.ha_reg_addr = (uint32_t *)(hba->sli.sli3.csr_addr +
1817             (sizeof (uint32_t) * HA_REG_OFFSET));
1818         hba->sli.sli3.ca_reg_addr = (uint32_t *)(hba->sli.sli3.csr_addr +
1819             (sizeof (uint32_t) * CA_REG_OFFSET));
1820         hba->sli.sli3.hs_reg_addr = (uint32_t *)(hba->sli.sli3.csr_addr +
1821             (sizeof (uint32_t) * HS_REG_OFFSET));
1822         hba->sli.sli3.hc_reg_addr = (uint32_t *)(hba->sli.sli3.csr_addr +
1823             (sizeof (uint32_t) * HC_REG_OFFSET));
1824         hba->sli.sli3.bc_reg_addr = (uint32_t *)(hba->sli.sli3.csr_addr +
1825             (sizeof (uint32_t) * BC_REG_OFFSET));
1826 
1827         if (hba->bus_type == SBUS_FC) {
1828                 /* offset from beginning of register space */
1829                 /* for TITAN registers */
1830                 hba->sli.sli3.shc_reg_addr =
1831                     (uint32_t *)(hba->sli.sli3.sbus_csr_addr +
1832                     (sizeof (uint32_t) * SBUS_CTRL_REG_OFFSET));
1833                 hba->sli.sli3.shs_reg_addr =
1834                     (uint32_t *)(hba->sli.sli3.sbus_csr_addr +
1835                     (sizeof (uint32_t) * SBUS_STAT_REG_OFFSET));
1836                 hba->sli.sli3.shu_reg_addr =
1837                     (uint32_t *)(hba->sli.sli3.sbus_csr_addr +
1838                     (sizeof (uint32_t) * SBUS_UPDATE_REG_OFFSET));
1839         }
1840         hba->chan_count = MAX_RINGS;
1841 
1842         return (0);
1843 
1844 failed:
1845 
1846         emlxs_sli3_unmap_hdw(hba);
1847         return (ENOMEM);
1848 
1849 } /* emlxs_sli3_map_hdw() */
1850 
1851 
1852 static void
1853 emlxs_sli3_unmap_hdw(emlxs_hba_t *hba)
1854 {
1855         MBUF_INFO       bufinfo;
1856         MBUF_INFO       *buf_info = &bufinfo;
1857 
1858         if (hba->sli.sli3.csr_acc_handle) {
1859                 ddi_regs_map_free(&hba->sli.sli3.csr_acc_handle);
1860                 hba->sli.sli3.csr_acc_handle = 0;
1861         }
1862 
1863         if (hba->sli.sli3.slim_acc_handle) {
1864                 ddi_regs_map_free(&hba->sli.sli3.slim_acc_handle);
1865                 hba->sli.sli3.slim_acc_handle = 0;
1866         }
1867 
1868         if (hba->sli.sli3.sbus_flash_acc_handle) {
1869                 ddi_regs_map_free(&hba->sli.sli3.sbus_flash_acc_handle);
1870                 hba->sli.sli3.sbus_flash_acc_handle = 0;
1871         }
1872 
1873         if (hba->sli.sli3.sbus_core_acc_handle) {
1874                 ddi_regs_map_free(&hba->sli.sli3.sbus_core_acc_handle);
1875                 hba->sli.sli3.sbus_core_acc_handle = 0;
1876         }
1877 
1878         if (hba->sli.sli3.sbus_csr_handle) {
1879                 ddi_regs_map_free(&hba->sli.sli3.sbus_csr_handle);
1880                 hba->sli.sli3.sbus_csr_handle = 0;
1881         }
1882 
1883         if (hba->sli.sli3.slim2.virt) {
1884                 bzero(buf_info, sizeof (MBUF_INFO));
1885 
1886                 if (hba->sli.sli3.slim2.phys) {
1887                         buf_info->phys = hba->sli.sli3.slim2.phys;
1888                         buf_info->data_handle = hba->sli.sli3.slim2.data_handle;
1889                         buf_info->dma_handle = hba->sli.sli3.slim2.dma_handle;
1890                         buf_info->flags = FC_MBUF_DMA;
1891                 }
1892 
1893                 buf_info->virt = hba->sli.sli3.slim2.virt;
1894                 buf_info->size = hba->sli.sli3.slim2.size;
1895                 emlxs_mem_free(hba, buf_info);
1896 
1897                 hba->sli.sli3.slim2.virt = NULL;
1898         }
1899 
1900 
1901         return;
1902 
1903 } /* emlxs_sli3_unmap_hdw() */
1904 
1905 
1906 static uint32_t
1907 emlxs_sli3_hba_init(emlxs_hba_t *hba)
1908 {
1909         emlxs_port_t *port = &PPORT;
1910         emlxs_port_t *vport;
1911         emlxs_config_t *cfg;
1912         uint16_t i;
1913         VPIobj_t *vpip;
1914 
1915         cfg = &CFG;
1916         i = 0;
1917 
1918         /* Restart the adapter */
1919         if (emlxs_sli3_hba_reset(hba, 1, 0, 0)) {
1920                 return (1);
1921         }
1922 
1923         hba->channel_fcp = FC_FCP_RING;
1924         hba->channel_els = FC_ELS_RING;
1925         hba->channel_ip = FC_IP_RING;
1926         hba->channel_ct = FC_CT_RING;
1927         hba->chan_count = MAX_RINGS;
1928         hba->sli.sli3.ring_count = MAX_RINGS;
1929 
1930         /*
1931          * WARNING: There is a max of 6 ring masks allowed
1932          */
1933         /* RING 0 - FCP */
1934         if (port->flag & EMLXS_TGT_ENABLED) {
1935                 hba->sli.sli3.ring_masks[FC_FCP_RING] = 1;
1936                 hba->sli.sli3.ring_rval[i] = FC_FCP_CMND;
1937                 hba->sli.sli3.ring_rmask[i] = 0;
1938                 hba->sli.sli3.ring_tval[i] = FC_TYPE_SCSI_FCP;
1939                 hba->sli.sli3.ring_tmask[i++] = 0xFF;
1940         } else {
1941                 hba->sli.sli3.ring_masks[FC_FCP_RING] = 0;
1942         }
1943 
1944         hba->sli.sli3.ring[FC_FCP_RING].fc_numCiocb = SLIM_IOCB_CMD_R0_ENTRIES;
1945         hba->sli.sli3.ring[FC_FCP_RING].fc_numRiocb = SLIM_IOCB_RSP_R0_ENTRIES;
1946 
1947         /* RING 1 - IP */
1948         if (cfg[CFG_NETWORK_ON].current) {
1949                 hba->sli.sli3.ring_masks[FC_IP_RING] = 1;
1950                 hba->sli.sli3.ring_rval[i] = FC_UNSOL_DATA; /* Unsol Data */
1951                 hba->sli.sli3.ring_rmask[i] = 0xFF;
1952                 hba->sli.sli3.ring_tval[i] = FC_TYPE_IS8802_SNAP; /* LLC/SNAP */
1953                 hba->sli.sli3.ring_tmask[i++] = 0xFF;
1954         } else {
1955                 hba->sli.sli3.ring_masks[FC_IP_RING] = 0;
1956         }
1957 
1958         hba->sli.sli3.ring[FC_IP_RING].fc_numCiocb = SLIM_IOCB_CMD_R1_ENTRIES;
1959         hba->sli.sli3.ring[FC_IP_RING].fc_numRiocb = SLIM_IOCB_RSP_R1_ENTRIES;
1960 
1961         /* RING 2 - ELS */
1962         hba->sli.sli3.ring_masks[FC_ELS_RING] = 1;
1963         hba->sli.sli3.ring_rval[i] = FC_ELS_REQ;     /* ELS request/rsp */
1964         hba->sli.sli3.ring_rmask[i] = 0xFE;
1965         hba->sli.sli3.ring_tval[i] = FC_TYPE_EXTENDED_LS;    /* ELS */
1966         hba->sli.sli3.ring_tmask[i++] = 0xFF;
1967 
1968         hba->sli.sli3.ring[FC_ELS_RING].fc_numCiocb = SLIM_IOCB_CMD_R2_ENTRIES;
1969         hba->sli.sli3.ring[FC_ELS_RING].fc_numRiocb = SLIM_IOCB_RSP_R2_ENTRIES;
1970 
1971         /* RING 3 - CT */
1972         hba->sli.sli3.ring_masks[FC_CT_RING] = 1;
1973         hba->sli.sli3.ring_rval[i] = FC_UNSOL_CTL;   /* CT request/rsp */
1974         hba->sli.sli3.ring_rmask[i] = 0xFE;
1975         hba->sli.sli3.ring_tval[i] = FC_TYPE_FC_SERVICES;    /* CT */
1976         hba->sli.sli3.ring_tmask[i++] = 0xFF;
1977 
1978         hba->sli.sli3.ring[FC_CT_RING].fc_numCiocb = SLIM_IOCB_CMD_R3_ENTRIES;
1979         hba->sli.sli3.ring[FC_CT_RING].fc_numRiocb = SLIM_IOCB_RSP_R3_ENTRIES;
1980 
1981         if (i > 6) {
1982                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_failed_msg,
1983                     "hba_init: Too many ring masks defined. cnt=%d", i);
1984                 return (1);
1985         }
1986 
1987         /* Initialize all the port objects */
1988         hba->vpi_max = 0;
1989         for (i = 0; i < MAX_VPORTS; i++) {
1990                 vport = &VPORT(i);
1991                 vport->hba = hba;
1992                 vport->vpi = i;
1993 
1994                 vpip = &vport->VPIobj;
1995                 vpip->index = i;
1996                 vpip->VPI = i;
1997                 vpip->port = vport;
1998                 vpip->state = VPI_STATE_OFFLINE;
1999                 vport->vpip = vpip;
2000         }
2001 
2002         /*
2003          * Initialize the max_node count to a default value if needed
2004          * This determines how many node objects we preallocate in the pool
2005          * The actual max_nodes will be set later based on adapter info
2006          */
2007         if (hba->max_nodes == 0) {
2008                 if (cfg[CFG_NUM_NODES].current > 0) {
2009                         hba->max_nodes = cfg[CFG_NUM_NODES].current;
2010                 } else if (hba->model_info.chip >= EMLXS_SATURN_CHIP) {
2011                         hba->max_nodes = 4096;
2012                 } else {
2013                         hba->max_nodes = 512;
2014                 }
2015         }
2016 
2017         return (0);
2018 
2019 } /* emlxs_sli3_hba_init() */
2020 
2021 
2022 /*
2023  * 0: quiesce indicates the call is not from quiesce routine.
2024  * 1: quiesce indicates the call is from quiesce routine.
2025  */
2026 static uint32_t
2027 emlxs_sli3_hba_reset(emlxs_hba_t *hba, uint32_t restart, uint32_t skip_post,
2028         uint32_t quiesce)
2029 {
2030         emlxs_port_t *port = &PPORT;
2031         MAILBOX *swpmb;
2032         MAILBOX *mb;
2033         uint32_t word0;
2034         uint16_t cfg_value;
2035         uint32_t status = 0;
2036         uint32_t status1;
2037         uint32_t status2;
2038         uint32_t i;
2039         uint32_t ready;
2040         emlxs_port_t *vport;
2041         RING *rp;
2042         emlxs_config_t *cfg = &CFG;
2043 
2044         if (!cfg[CFG_RESET_ENABLE].current) {
2045                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_reset_failed_msg,
2046                     "Adapter reset disabled.");
2047                 EMLXS_STATE_CHANGE(hba, FC_ERROR);
2048 
2049                 return (1);
2050         }
2051 
2052         /* Kill the adapter first */
2053         if (quiesce == 0) {
2054                 emlxs_sli3_hba_kill(hba);
2055         } else {
2056                 emlxs_sli3_hba_kill4quiesce(hba);
2057         }
2058 
2059         if (restart) {
2060                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
2061                     "Restarting.");
2062                 EMLXS_STATE_CHANGE(hba, FC_INIT_START);
2063 
2064                 ready = (HS_FFRDY | HS_MBRDY);
2065         } else {
2066                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
2067                     "Resetting.");
2068                 EMLXS_STATE_CHANGE(hba, FC_WARM_START);
2069 
2070                 ready = HS_MBRDY;
2071         }
2072 
2073         hba->flag &= ~(FC_SLIM2_MODE | FC_HARDWARE_ERROR);
2074 
2075         mb = FC_SLIM1_MAILBOX(hba);
2076         swpmb = (MAILBOX *)&word0;
2077 
2078 reset:
2079 
2080         i = 0;
2081 
2082         /* Save reset time */
2083         HBASTATS.ResetTime = hba->timer_tics;
2084 
2085         if (restart) {
2086                 /* First put restart command in mailbox */
2087                 word0 = 0;
2088                 swpmb->mbxCommand = MBX_RESTART;
2089                 swpmb->mbxHc = 1;
2090                 WRITE_SLIM_ADDR(hba, ((volatile uint32_t *)mb), word0);
2091 
2092                 /* Only skip post after emlxs_sli3_online is completed */
2093                 if (skip_post) {
2094                         WRITE_SLIM_ADDR(hba, (((volatile uint32_t *)mb) + 1),
2095                             1);
2096                 } else {
2097                         WRITE_SLIM_ADDR(hba, (((volatile uint32_t *)mb) + 1),
2098                             0);
2099                 }
2100 
2101         }
2102 
2103         /*
2104          * Turn off SERR, PERR in PCI cmd register
2105          */
2106         cfg_value = ddi_get16(hba->pci_acc_handle,
2107             (uint16_t *)(hba->pci_addr + PCI_COMMAND_REGISTER));
2108 
2109         ddi_put16(hba->pci_acc_handle,
2110             (uint16_t *)(hba->pci_addr + PCI_COMMAND_REGISTER),
2111             (uint16_t)(cfg_value & ~(CMD_PARITY_CHK | CMD_SERR_ENBL)));
2112 
2113         hba->sli.sli3.hc_copy = HC_INITFF;
2114         WRITE_CSR_REG(hba, FC_HC_REG(hba), hba->sli.sli3.hc_copy);
2115 
2116         /* Wait 1 msec before restoring PCI config */
2117         BUSYWAIT_MS(1);
2118 
2119         /* Restore PCI cmd register */
2120         ddi_put16(hba->pci_acc_handle,
2121             (uint16_t *)(hba->pci_addr + PCI_COMMAND_REGISTER),
2122             (uint16_t)cfg_value);
2123 
2124         /* Wait 3 seconds before checking */
2125         BUSYWAIT_MS(3000);
2126         i += 3;
2127 
2128         /* Wait for reset completion */
2129         while (i < 30) {
2130                 /* Check status register to see what current state is */
2131                 status = READ_CSR_REG(hba, FC_HS_REG(hba));
2132 
2133                 /* Check to see if any errors occurred during init */
2134                 if (status & HS_FFERM) {
2135                         status1 = READ_SLIM_ADDR(hba, ((volatile uint8_t *)
2136                             hba->sli.sli3.slim_addr + 0xa8));
2137                         status2 = READ_SLIM_ADDR(hba, ((volatile uint8_t *)
2138                             hba->sli.sli3.slim_addr + 0xac));
2139 
2140                         EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_reset_failed_msg,
2141                             "HS_FFERM: status=0x%x status1=0x%x status2=0x%x",
2142                             status, status1, status2);
2143 
2144                         EMLXS_STATE_CHANGE(hba, FC_ERROR);
2145                         return (1);
2146                 }
2147 
2148                 if ((status & ready) == ready) {
2149                         /* Reset Done !! */
2150                         goto done;
2151                 }
2152 
2153                 /*
2154                  * Check every 1 second for 15 seconds, then reset board
2155                  * again (w/post), then check every 1 second for 15 * seconds.
2156                  */
2157                 BUSYWAIT_MS(1000);
2158                 i++;
2159 
2160                 /* Reset again (w/post) at 15 seconds */
2161                 if (i == 15) {
2162                         EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
2163                             "Reset failed. Retrying...");
2164 
2165                         goto reset;
2166                 }
2167         }
2168 
2169 #ifdef FMA_SUPPORT
2170 reset_fail:
2171 #endif  /* FMA_SUPPORT */
2172 
2173         /* Timeout occurred */
2174         EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_reset_failed_msg,
2175             "Timeout: status=0x%x", status);
2176         EMLXS_STATE_CHANGE(hba, FC_ERROR);
2177 
2178         /* Log a dump event */
2179         emlxs_log_dump_event(port, NULL, 0);
2180 
2181         return (1);
2182 
2183 done:
2184 
2185         /* Initialize hc_copy */
2186         hba->sli.sli3.hc_copy = READ_CSR_REG(hba, FC_HC_REG(hba));
2187 
2188 #ifdef FMA_SUPPORT
2189         /* Access handle validation */
2190         if ((emlxs_fm_check_acc_handle(hba, hba->pci_acc_handle)
2191             != DDI_FM_OK) ||
2192             (emlxs_fm_check_acc_handle(hba, hba->sli.sli3.slim_acc_handle)
2193             != DDI_FM_OK) ||
2194             (emlxs_fm_check_acc_handle(hba, hba->sli.sli3.csr_acc_handle)
2195             != DDI_FM_OK)) {
2196                 EMLXS_MSGF(EMLXS_CONTEXT,
2197                     &emlxs_invalid_access_handle_msg, NULL);
2198                 goto reset_fail;
2199         }
2200 #endif  /* FMA_SUPPORT */
2201 
2202         /* Reset the hba structure */
2203         hba->flag &= FC_RESET_MASK;
2204         hba->channel_tx_count = 0;
2205         hba->io_count = 0;
2206         hba->iodone_count = 0;
2207         hba->topology = 0;
2208         hba->linkspeed = 0;
2209         hba->heartbeat_active = 0;
2210         hba->discovery_timer = 0;
2211         hba->linkup_timer = 0;
2212         hba->loopback_tics = 0;
2213 
2214         /* Reset the ring objects */
2215         for (i = 0; i < MAX_RINGS; i++) {
2216                 rp = &hba->sli.sli3.ring[i];
2217                 rp->fc_mpon = 0;
2218                 rp->fc_mpoff = 0;
2219         }
2220 
2221         /* Reset the port objects */
2222         for (i = 0; i < MAX_VPORTS; i++) {
2223                 vport = &VPORT(i);
2224 
2225                 vport->flag &= EMLXS_PORT_RESET_MASK;
2226                 vport->did = 0;
2227                 vport->prev_did = 0;
2228                 vport->lip_type = 0;
2229                 bzero(&vport->fabric_sparam, sizeof (SERV_PARM));
2230                 bzero(&vport->prev_fabric_sparam, sizeof (SERV_PARM));
2231 
2232                 bzero((caddr_t)&vport->node_base, sizeof (NODELIST));
2233                 vport->node_base.nlp_Rpi = 0;
2234                 vport->node_base.nlp_DID = 0xffffff;
2235                 vport->node_base.nlp_list_next = NULL;
2236                 vport->node_base.nlp_list_prev = NULL;
2237                 vport->node_base.nlp_active = 1;
2238                 vport->node_count = 0;
2239 
2240                 if (vport->ub_count < EMLXS_UB_TOKEN_OFFSET) {
2241                         vport->ub_count = EMLXS_UB_TOKEN_OFFSET;
2242                 }
2243         }
2244 
2245         return (0);
2246 
2247 } /* emlxs_sli3_hba_reset */
2248 
2249 
2250 #define BPL_CMD         0
2251 #define BPL_RESP        1
2252 #define BPL_DATA        2
2253 
2254 static ULP_BDE64 *
2255 emlxs_pkt_to_bpl(fc_packet_t *pkt, ULP_BDE64 *bpl, uint32_t bpl_type)
2256 {
2257         ddi_dma_cookie_t *cp;
2258         uint_t  i;
2259         int32_t size;
2260         uint_t  cookie_cnt;
2261         uint8_t bdeFlags;
2262 
2263 #if (EMLXS_MODREV >= EMLXS_MODREV3)
2264         switch (bpl_type) {
2265         case BPL_CMD:
2266                 cp = pkt->pkt_cmd_cookie;
2267                 cookie_cnt = pkt->pkt_cmd_cookie_cnt;
2268                 size = (int32_t)pkt->pkt_cmdlen;
2269                 bdeFlags = 0;
2270                 break;
2271 
2272         case BPL_RESP:
2273                 cp = pkt->pkt_resp_cookie;
2274                 cookie_cnt = pkt->pkt_resp_cookie_cnt;
2275                 size = (int32_t)pkt->pkt_rsplen;
2276                 bdeFlags = BUFF_USE_RCV;
2277                 break;
2278 
2279 
2280         case BPL_DATA:
2281                 cp = pkt->pkt_data_cookie;
2282                 cookie_cnt = pkt->pkt_data_cookie_cnt;
2283                 size = (int32_t)pkt->pkt_datalen;
2284                 bdeFlags = (pkt->pkt_tran_type == FC_PKT_FCP_READ) ?
2285                     BUFF_USE_RCV : 0;
2286                 break;
2287 
2288         default:
2289                 return (NULL);
2290         }
2291 
2292 #else
2293         switch (bpl_type) {
2294         case BPL_CMD:
2295                 cp = &pkt->pkt_cmd_cookie;
2296                 cookie_cnt = 1;
2297                 size = (int32_t)pkt->pkt_cmdlen;
2298                 bdeFlags = 0;
2299                 break;
2300 
2301         case BPL_RESP:
2302                 cp = &pkt->pkt_resp_cookie;
2303                 cookie_cnt = 1;
2304                 size = (int32_t)pkt->pkt_rsplen;
2305                 bdeFlags = BUFF_USE_RCV;
2306                 break;
2307 
2308 
2309         case BPL_DATA:
2310                 cp = &pkt->pkt_data_cookie;
2311                 cookie_cnt = 1;
2312                 size = (int32_t)pkt->pkt_datalen;
2313                 bdeFlags = (pkt->pkt_tran_type == FC_PKT_FCP_READ) ?
2314                     BUFF_USE_RCV : 0;
2315                 break;
2316 
2317         default:
2318                 return (NULL);
2319         }
2320 #endif  /* >= EMLXS_MODREV3 */
2321 
2322         for (i = 0; i < cookie_cnt && size > 0; i++, cp++) {
2323                 bpl->addrHigh =
2324                     BE_SWAP32(PADDR_HI(cp->dmac_laddress));
2325                 bpl->addrLow =
2326                     BE_SWAP32(PADDR_LO(cp->dmac_laddress));
2327                 bpl->tus.f.bdeSize = MIN(size, cp->dmac_size);
2328                 bpl->tus.f.bdeFlags = bdeFlags;
2329                 bpl->tus.w = BE_SWAP32(bpl->tus.w);
2330 
2331                 bpl++;
2332                 size -= cp->dmac_size;
2333         }
2334 
2335         return (bpl);
2336 
2337 } /* emlxs_pkt_to_bpl */
2338 
2339 
2340 static uint32_t
2341 emlxs_sli2_bde_setup(emlxs_port_t *port, emlxs_buf_t *sbp)
2342 {
2343         emlxs_hba_t     *hba = HBA;
2344         fc_packet_t     *pkt;
2345         MATCHMAP        *bmp;
2346         ULP_BDE64       *bpl;
2347         uint64_t        bp;
2348         IOCB            *iocb;
2349         IOCBQ           *iocbq;
2350         CHANNEL *cp;
2351         uint32_t        data_cookie_cnt;
2352         uint32_t        channelno;
2353 
2354         cp = sbp->channel;
2355         iocb = (IOCB *) & sbp->iocbq;
2356         pkt = PRIV2PKT(sbp);
2357 
2358         if (hba->sli.sli3.bpl_table) {
2359                 bmp = hba->sli.sli3.bpl_table[sbp->iotag];
2360         } else {
2361                 bmp = (MATCHMAP *)emlxs_mem_get(hba, MEM_BPL);
2362         }
2363 
2364         if (!bmp) {
2365                 return (1);
2366         }
2367 
2368         sbp->bmp = bmp;
2369         bpl = (ULP_BDE64 *)bmp->virt;
2370         bp = bmp->phys;
2371 
2372 #if (EMLXS_MODREV >= EMLXS_MODREV3)
2373         data_cookie_cnt = pkt->pkt_data_cookie_cnt;
2374 #else
2375         data_cookie_cnt = 1;
2376 #endif  /* >= EMLXS_MODREV3 */
2377 
2378         iocbq = &sbp->iocbq;
2379 
2380         channelno = (iocbq->flag & IOCB_FCP_CMD)? FC_FCP_RING:cp->channelno;
2381         switch (channelno) {
2382                 case FC_FCP_RING:
2383 
2384                 /* CMD payload */
2385                 bpl = emlxs_pkt_to_bpl(pkt, bpl, BPL_CMD);
2386                 if (! bpl) {
2387                         return (1);
2388                 }
2389 
2390                 /* Check if response & data payloads are needed */
2391                 if (pkt->pkt_tran_type == FC_PKT_OUTBOUND) {
2392                         break;
2393                 }
2394 
2395                 /* RSP payload */
2396                 bpl = emlxs_pkt_to_bpl(pkt, bpl, BPL_RESP);
2397                 if (! bpl) {
2398                         return (1);
2399                 }
2400 
2401                 /* Check if data payload is needed */
2402                 if ((pkt->pkt_datalen == 0) ||
2403                     (data_cookie_cnt == 0)) {
2404                         break;
2405                 }
2406 
2407                 /* DATA payload */
2408                 bpl = emlxs_pkt_to_bpl(pkt, bpl, BPL_DATA);
2409                 if (! bpl) {
2410                         return (1);
2411                 }
2412                 break;
2413 
2414         case FC_IP_RING:
2415 
2416                 /* CMD payload */
2417                 bpl = emlxs_pkt_to_bpl(pkt, bpl, BPL_CMD);
2418                 if (! bpl) {
2419                         return (1);
2420                 }
2421                 break;
2422 
2423         case FC_ELS_RING:
2424 
2425                 /* CMD payload */
2426                 bpl = emlxs_pkt_to_bpl(pkt, bpl, BPL_CMD);
2427                 if (! bpl) {
2428                         return (1);
2429                 }
2430 
2431                 /* Check if response payload is needed */
2432                 if (pkt->pkt_tran_type == FC_PKT_OUTBOUND) {
2433                         break;
2434                 }
2435 
2436                 /* RSP payload */
2437                 bpl = emlxs_pkt_to_bpl(pkt, bpl, BPL_RESP);
2438                 if (! bpl) {
2439                         return (1);
2440                 }
2441                 break;
2442 
2443         case FC_CT_RING:
2444 
2445                 /* CMD payload */
2446                 bpl = emlxs_pkt_to_bpl(pkt, bpl, BPL_CMD);
2447                 if (! bpl) {
2448                         return (1);
2449                 }
2450 
2451                 /* Check if response payload is needed */
2452                 if ((pkt->pkt_tran_type == FC_PKT_OUTBOUND) &&
2453                     (pkt->pkt_cmd_fhdr.type != EMLXS_MENLO_TYPE)) {
2454                         break;
2455                 }
2456 
2457                 /* RSP payload */
2458                 bpl = emlxs_pkt_to_bpl(pkt, bpl, BPL_RESP);
2459                 if (! bpl) {
2460                         return (1);
2461                 }
2462                 break;
2463 
2464         }
2465 
2466         iocb->un.genreq64.bdl.bdeFlags = BUFF_TYPE_BDL;
2467         iocb->un.genreq64.bdl.addrHigh = PADDR_HI(bp);
2468         iocb->un.genreq64.bdl.addrLow  = PADDR_LO(bp);
2469         iocb->un.genreq64.bdl.bdeSize  =
2470             (uint32_t)(((uintptr_t)bpl - (uintptr_t)bmp->virt) & 0xFFFFFFFF);
2471         iocb->ULPBDECOUNT = 1;
2472         iocb->ULPLE = 1;
2473 
2474         return (0);
2475 
2476 } /* emlxs_sli2_bde_setup */
2477 
2478 
2479 static uint32_t
2480 emlxs_sli3_bde_setup(emlxs_port_t *port, emlxs_buf_t *sbp)
2481 {
2482         ddi_dma_cookie_t *cp_cmd;
2483         ddi_dma_cookie_t *cp_resp;
2484         ddi_dma_cookie_t *cp_data;
2485         fc_packet_t     *pkt;
2486         ULP_BDE64       *bde;
2487         int             data_cookie_cnt;
2488         uint32_t        i;
2489         uint32_t        channelno;
2490         IOCB            *iocb;
2491         IOCBQ           *iocbq;
2492         CHANNEL         *cp;
2493 
2494         pkt = PRIV2PKT(sbp);
2495 #if (EMLXS_MODREV >= EMLXS_MODREV3)
2496         if ((pkt->pkt_cmd_cookie_cnt > 1) ||
2497             (pkt->pkt_resp_cookie_cnt > 1) ||
2498             ((pkt->pkt_cmd_cookie_cnt + pkt->pkt_resp_cookie_cnt +
2499             pkt->pkt_data_cookie_cnt) > SLI3_MAX_BDE)) {
2500                 i = emlxs_sli2_bde_setup(port, sbp);
2501                 return (i);
2502         }
2503 
2504         cp_cmd = pkt->pkt_cmd_cookie;
2505         cp_resp = pkt->pkt_resp_cookie;
2506         cp_data = pkt->pkt_data_cookie;
2507         data_cookie_cnt = pkt->pkt_data_cookie_cnt;
2508 #else
2509         cp_cmd  = &pkt->pkt_cmd_cookie;
2510         cp_resp = &pkt->pkt_resp_cookie;
2511         cp_data = &pkt->pkt_data_cookie;
2512         data_cookie_cnt = 1;
2513 #endif  /* >= EMLXS_MODREV3 */
2514 
2515         cp = sbp->channel;
2516         iocbq = &sbp->iocbq;
2517         iocb = (IOCB *)iocbq;
2518         iocb->unsli3.ext_iocb.ebde_count = 0;
2519 
2520         channelno = (iocbq->flag & IOCB_FCP_CMD)? FC_FCP_RING:cp->channelno;
2521         switch (channelno) {
2522         case FC_FCP_RING:
2523                 /* CMD payload */
2524                 iocb->un.fcpi64.bdl.addrHigh =
2525                     PADDR_HI(cp_cmd->dmac_laddress);
2526                 iocb->un.fcpi64.bdl.addrLow =
2527                     PADDR_LO(cp_cmd->dmac_laddress);
2528                 iocb->un.fcpi64.bdl.bdeSize  = pkt->pkt_cmdlen;
2529                 iocb->un.fcpi64.bdl.bdeFlags = 0;
2530 
2531                 /* Check if a response & data payload are needed */
2532                 if (pkt->pkt_tran_type == FC_PKT_OUTBOUND) {
2533                         break;
2534                 }
2535 
2536                 /* RSP payload */
2537                 iocb->unsli3.ext_iocb.ebde1.addrHigh =
2538                     PADDR_HI(cp_resp->dmac_laddress);
2539                 iocb->unsli3.ext_iocb.ebde1.addrLow =
2540                     PADDR_LO(cp_resp->dmac_laddress);
2541                 iocb->unsli3.ext_iocb.ebde1.tus.f.bdeSize = pkt->pkt_rsplen;
2542                 iocb->unsli3.ext_iocb.ebde1.tus.f.bdeFlags = 0;
2543                 iocb->unsli3.ext_iocb.ebde_count = 1;
2544 
2545                 /* Check if a data payload is needed */
2546                 if ((pkt->pkt_datalen == 0) ||
2547                     (data_cookie_cnt == 0)) {
2548                         break;
2549                 }
2550 
2551                 /* DATA payload */
2552                 bde = (ULP_BDE64 *)&iocb->unsli3.ext_iocb.ebde2;
2553                 for (i = 0; i < data_cookie_cnt; i++) {
2554                         bde->addrHigh = PADDR_HI(cp_data->dmac_laddress);
2555                         bde->addrLow = PADDR_LO(cp_data->dmac_laddress);
2556                         bde->tus.f.bdeSize = cp_data->dmac_size;
2557                         bde->tus.f.bdeFlags = 0;
2558                         cp_data++;
2559                         bde++;
2560                 }
2561                 iocb->unsli3.ext_iocb.ebde_count += data_cookie_cnt;
2562 
2563                 break;
2564 
2565         case FC_IP_RING:
2566                 /* CMD payload */
2567                 iocb->un.xseq64.bdl.addrHigh =
2568                     PADDR_HI(cp_cmd->dmac_laddress);
2569                 iocb->un.xseq64.bdl.addrLow =
2570                     PADDR_LO(cp_cmd->dmac_laddress);
2571                 iocb->un.xseq64.bdl.bdeSize  = pkt->pkt_cmdlen;
2572                 iocb->un.xseq64.bdl.bdeFlags = 0;
2573 
2574                 break;
2575 
2576         case FC_ELS_RING:
2577 
2578                 /* CMD payload */
2579                 iocb->un.elsreq64.bdl.addrHigh =
2580                     PADDR_HI(cp_cmd->dmac_laddress);
2581                 iocb->un.elsreq64.bdl.addrLow =
2582                     PADDR_LO(cp_cmd->dmac_laddress);
2583                 iocb->un.elsreq64.bdl.bdeSize  = pkt->pkt_cmdlen;
2584                 iocb->un.elsreq64.bdl.bdeFlags = 0;
2585 
2586                 /* Check if a response payload is needed */
2587                 if (pkt->pkt_tran_type == FC_PKT_OUTBOUND) {
2588                         break;
2589                 }
2590 
2591                 /* RSP payload */
2592                 iocb->unsli3.ext_iocb.ebde1.addrHigh =
2593                     PADDR_HI(cp_resp->dmac_laddress);
2594                 iocb->unsli3.ext_iocb.ebde1.addrLow =
2595                     PADDR_LO(cp_resp->dmac_laddress);
2596                 iocb->unsli3.ext_iocb.ebde1.tus.f.bdeSize = pkt->pkt_rsplen;
2597                 iocb->unsli3.ext_iocb.ebde1.tus.f.bdeFlags = BUFF_USE_RCV;
2598                 iocb->unsli3.ext_iocb.ebde_count = 1;
2599                 break;
2600 
2601         case FC_CT_RING:
2602 
2603                 /* CMD payload */
2604                 iocb->un.genreq64.bdl.addrHigh =
2605                     PADDR_HI(cp_cmd->dmac_laddress);
2606                 iocb->un.genreq64.bdl.addrLow =
2607                     PADDR_LO(cp_cmd->dmac_laddress);
2608                 iocb->un.genreq64.bdl.bdeSize  = pkt->pkt_cmdlen;
2609                 iocb->un.genreq64.bdl.bdeFlags = 0;
2610 
2611                 /* Check if a response payload is needed */
2612                 if ((pkt->pkt_tran_type == FC_PKT_OUTBOUND) &&
2613                     (pkt->pkt_cmd_fhdr.type != EMLXS_MENLO_TYPE)) {
2614                         break;
2615                 }
2616 
2617                 /* RSP payload */
2618                 iocb->unsli3.ext_iocb.ebde1.addrHigh =
2619                     PADDR_HI(cp_resp->dmac_laddress);
2620                 iocb->unsli3.ext_iocb.ebde1.addrLow =
2621                     PADDR_LO(cp_resp->dmac_laddress);
2622                 iocb->unsli3.ext_iocb.ebde1.tus.f.bdeSize = pkt->pkt_rsplen;
2623                 iocb->unsli3.ext_iocb.ebde1.tus.f.bdeFlags = BUFF_USE_RCV;
2624                 iocb->unsli3.ext_iocb.ebde_count = 1;
2625                 break;
2626         }
2627 
2628         iocb->ULPBDECOUNT = 0;
2629         iocb->ULPLE = 0;
2630 
2631         return (0);
2632 
2633 } /* emlxs_sli3_bde_setup */
2634 
2635 
2636 /* Only used for FCP Data xfers */
2637 #ifdef SFCT_SUPPORT
2638 /*ARGSUSED*/
2639 static uint32_t
2640 emlxs_sli2_fct_bde_setup(emlxs_port_t *port, emlxs_buf_t *sbp)
2641 {
2642         emlxs_hba_t *hba = HBA;
2643         scsi_task_t *fct_task;
2644         MATCHMAP *bmp;
2645         ULP_BDE64 *bpl;
2646         uint64_t bp;
2647         uint8_t bdeFlags;
2648         IOCB *iocb;
2649         uint32_t size;
2650         MATCHMAP *mp;
2651 
2652         iocb = (IOCB *)&sbp->iocbq.iocb;
2653         sbp->bmp = NULL;
2654 
2655         if (!sbp->fct_buf) {
2656                 iocb->un.fcpt64.bdl.addrHigh = 0;
2657                 iocb->un.fcpt64.bdl.addrLow = 0;
2658                 iocb->un.fcpt64.bdl.bdeSize = 0;
2659                 iocb->un.fcpt64.bdl.bdeFlags = 0;
2660                 iocb->un.fcpt64.fcpt_Offset = 0;
2661                 iocb->un.fcpt64.fcpt_Length = 0;
2662                 iocb->ULPBDECOUNT = 0;
2663                 iocb->ULPLE = 1;
2664                 return (0);
2665         }
2666 
2667         if (hba->sli.sli3.bpl_table) {
2668                 bmp = hba->sli.sli3.bpl_table[sbp->iotag];
2669         } else {
2670                 bmp = (MATCHMAP *)emlxs_mem_get(hba, MEM_BPL);
2671         }
2672 
2673         if (!bmp) {
2674                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_error_msg,
2675                     "fct_sli2_bde_setup: Unable to BPL buffer. iotag=%d",
2676                     sbp->iotag);
2677 
2678                 iocb->un.fcpt64.bdl.addrHigh = 0;
2679                 iocb->un.fcpt64.bdl.addrLow = 0;
2680                 iocb->un.fcpt64.bdl.bdeSize = 0;
2681                 iocb->un.fcpt64.bdl.bdeFlags = 0;
2682                 iocb->un.fcpt64.fcpt_Offset = 0;
2683                 iocb->un.fcpt64.fcpt_Length = 0;
2684                 iocb->ULPBDECOUNT = 0;
2685                 iocb->ULPLE = 1;
2686                 return (1);
2687         }
2688 
2689         bpl = (ULP_BDE64 *)bmp->virt;
2690         bp = bmp->phys;
2691 
2692         fct_task = (scsi_task_t *)sbp->fct_cmd->cmd_specific;
2693 
2694         size = sbp->fct_buf->db_data_size;
2695         mp = (MATCHMAP *)sbp->fct_buf->db_port_private;
2696 
2697         bdeFlags = (fct_task->task_flags & TF_WRITE_DATA) ? BUFF_USE_RCV : 0;
2698 
2699         /* Init the buffer list */
2700         bpl->addrHigh = BE_SWAP32(PADDR_HI(mp->phys));
2701         bpl->addrLow = BE_SWAP32(PADDR_LO(mp->phys));
2702         bpl->tus.f.bdeSize = size;
2703         bpl->tus.f.bdeFlags = bdeFlags;
2704         bpl->tus.w = BE_SWAP32(bpl->tus.w);
2705 
2706         /* Init the IOCB */
2707         iocb->un.fcpt64.bdl.addrHigh = PADDR_HI(bp);
2708         iocb->un.fcpt64.bdl.addrLow = PADDR_LO(bp);
2709         iocb->un.fcpt64.bdl.bdeSize = sizeof (ULP_BDE64);
2710         iocb->un.fcpt64.bdl.bdeFlags = BUFF_TYPE_BDL;
2711 
2712         iocb->un.fcpt64.fcpt_Length =
2713             (fct_task->task_flags & TF_WRITE_DATA) ? size : 0;
2714         iocb->un.fcpt64.fcpt_Offset = 0;
2715 
2716         iocb->ULPBDECOUNT = 1;
2717         iocb->ULPLE = 1;
2718         sbp->bmp = bmp;
2719 
2720         return (0);
2721 
2722 } /* emlxs_sli2_fct_bde_setup */
2723 #endif /* SFCT_SUPPORT */
2724 
2725 
2726 #ifdef SFCT_SUPPORT
2727 /*ARGSUSED*/
2728 static uint32_t
2729 emlxs_sli3_fct_bde_setup(emlxs_port_t *port, emlxs_buf_t *sbp)
2730 {
2731         scsi_task_t *fct_task;
2732         IOCB *iocb;
2733         MATCHMAP *mp;
2734         uint32_t bdeFlags;
2735         uint32_t size;
2736 
2737         iocb = (IOCB *)&sbp->iocbq;
2738 
2739         if (!sbp->fct_buf) {
2740                 iocb->un.fcpt64.bdl.addrHigh = 0;
2741                 iocb->un.fcpt64.bdl.addrLow = 0;
2742                 iocb->un.fcpt64.bdl.bdeSize = 0;
2743                 iocb->un.fcpt64.bdl.bdeFlags = 0;
2744                 iocb->un.fcpt64.fcpt_Offset = 0;
2745                 iocb->un.fcpt64.fcpt_Length = 0;
2746                 iocb->ULPBDECOUNT = 0;
2747                 iocb->ULPLE = 0;
2748                 iocb->unsli3.ext_iocb.ebde_count = 0;
2749                 return (0);
2750         }
2751 
2752         fct_task = (scsi_task_t *)sbp->fct_cmd->cmd_specific;
2753 
2754         size = sbp->fct_buf->db_data_size;
2755         mp = (MATCHMAP *)sbp->fct_buf->db_port_private;
2756 
2757         bdeFlags = (fct_task->task_flags & TF_WRITE_DATA) ? BUFF_USE_RCV : 0;
2758 
2759         /* Init first BDE */
2760         iocb->un.fcpt64.bdl.addrHigh = PADDR_HI(mp->phys);
2761         iocb->un.fcpt64.bdl.addrLow = PADDR_LO(mp->phys);
2762         iocb->un.fcpt64.bdl.bdeSize = size;
2763         iocb->un.fcpt64.bdl.bdeFlags = bdeFlags;
2764 
2765         iocb->unsli3.ext_iocb.ebde_count = 0;
2766         iocb->un.fcpt64.fcpt_Length =
2767             (fct_task->task_flags & TF_WRITE_DATA) ? size : 0;
2768         iocb->un.fcpt64.fcpt_Offset = 0;
2769 
2770         iocb->ULPBDECOUNT = 0;
2771         iocb->ULPLE = 0;
2772 
2773         return (0);
2774 
2775 } /* emlxs_sli3_fct_bde_setup */
2776 #endif /* SFCT_SUPPORT */
2777 
2778 
2779 static void
2780 emlxs_sli3_issue_iocb_cmd(emlxs_hba_t *hba, CHANNEL *cp, IOCBQ *iocbq)
2781 {
2782 #ifdef FMA_SUPPORT
2783         emlxs_port_t *port = &PPORT;
2784 #endif  /* FMA_SUPPORT */
2785         PGP *pgp;
2786         emlxs_buf_t *sbp;
2787         SLIM2 *slim2p = (SLIM2 *)hba->sli.sli3.slim2.virt;
2788         RING *rp;
2789         uint32_t nextIdx;
2790         uint32_t status;
2791         void *ioa2;
2792         off_t offset;
2793         uint32_t count = 0;
2794         uint32_t flag;
2795         uint32_t channelno;
2796         int32_t throttle;
2797 #ifdef NODE_THROTTLE_SUPPORT
2798         int32_t node_throttle;
2799         NODELIST *marked_node = NULL;
2800 #endif /* NODE_THROTTLE_SUPPORT */
2801 
2802         channelno = cp->channelno;
2803         rp = (RING *)cp->iopath;
2804 
2805         throttle = 0;
2806 
2807         /* Check if FCP ring and adapter is not ready */
2808         /* We may use any ring for FCP_CMD */
2809         if (iocbq && (iocbq->flag & IOCB_FCP_CMD) && (hba->state != FC_READY)) {
2810                 if (!(iocbq->flag & IOCB_SPECIAL) || !iocbq->port ||
2811                     (((emlxs_port_t *)iocbq->port)->mode == MODE_INITIATOR)) {
2812                         emlxs_tx_put(iocbq, 1);
2813                         return;
2814                 }
2815         }
2816 
2817         /* Attempt to acquire CMD_RING lock */
2818         if (mutex_tryenter(&EMLXS_CMD_RING_LOCK(channelno)) == 0) {
2819                 /* Queue it for later */
2820                 if (iocbq) {
2821                         if ((hba->io_count -
2822                             hba->channel_tx_count) > 10) {
2823                                 emlxs_tx_put(iocbq, 1);
2824                                 return;
2825                         } else {
2826 
2827                                 /*
2828                                  * EMLXS_MSGF(EMLXS_CONTEXT,
2829                                  * &emlxs_ring_watchdog_msg,
2830                                  * "%s host=%d port=%d cnt=%d,%d  RACE
2831                                  * CONDITION3 DETECTED.",
2832                                  * emlxs_ring_xlate(channelno),
2833                                  * rp->fc_cmdidx, rp->fc_port_cmdidx,
2834                                  * hba->channel_tx_count,
2835                                  * hba->io_count);
2836                                  */
2837                                 mutex_enter(&EMLXS_CMD_RING_LOCK(channelno));
2838                         }
2839                 } else {
2840                         return;
2841                 }
2842         }
2843         /* CMD_RING_LOCK acquired */
2844 
2845         /* Throttle check only applies to non special iocb */
2846         if (iocbq && (!(iocbq->flag & IOCB_SPECIAL))) {
2847                 /* Check if HBA is full */
2848                 throttle = hba->io_throttle - hba->io_active;
2849                 if (throttle <= 0) {
2850                         /* Hitting adapter throttle limit */
2851                         /* Queue it for later */
2852                         if (iocbq) {
2853                                 emlxs_tx_put(iocbq, 1);
2854                         }
2855 
2856                         goto busy;
2857                 }
2858         }
2859 
2860         /* Read adapter's get index */
2861         pgp = (PGP *)
2862             &((SLIM2 *)hba->sli.sli3.slim2.virt)->mbx.us.s2.port[channelno];
2863         offset =
2864             (off_t)((uint64_t)((unsigned long)&(pgp->cmdGetInx)) -
2865             (uint64_t)((unsigned long)hba->sli.sli3.slim2.virt));
2866         EMLXS_MPDATA_SYNC(hba->sli.sli3.slim2.dma_handle, offset, 4,
2867             DDI_DMA_SYNC_FORKERNEL);
2868         rp->fc_port_cmdidx = BE_SWAP32(pgp->cmdGetInx);
2869 
2870         /* Calculate the next put index */
2871         nextIdx =
2872             (rp->fc_cmdidx + 1 >= rp->fc_numCiocb) ? 0 : rp->fc_cmdidx + 1;
2873 
2874         /* Check if ring is full */
2875         if (nextIdx == rp->fc_port_cmdidx) {
2876                 /* Try one more time */
2877                 EMLXS_MPDATA_SYNC(hba->sli.sli3.slim2.dma_handle, offset, 4,
2878                     DDI_DMA_SYNC_FORKERNEL);
2879                 rp->fc_port_cmdidx = BE_SWAP32(pgp->cmdGetInx);
2880 
2881                 if (nextIdx == rp->fc_port_cmdidx) {
2882                         /* Queue it for later */
2883                         if (iocbq) {
2884                                 emlxs_tx_put(iocbq, 1);
2885                         }
2886 
2887                         goto busy;
2888                 }
2889         }
2890 
2891         /*
2892          * We have a command ring slot available
2893          * Make sure we have an iocb to send
2894          */
2895         if (iocbq) {
2896                 mutex_enter(&EMLXS_TX_CHANNEL_LOCK);
2897 
2898                 /* Check if the ring already has iocb's waiting */
2899                 if (cp->nodeq.q_first != NULL) {
2900                         /* Put the current iocbq on the tx queue */
2901                         emlxs_tx_put(iocbq, 0);
2902 
2903                         /*
2904                          * Attempt to replace it with the next iocbq
2905                          * in the tx queue
2906                          */
2907                         iocbq = emlxs_tx_get(cp, 0);
2908                 }
2909 
2910                 mutex_exit(&EMLXS_TX_CHANNEL_LOCK);
2911         } else {
2912                 /* Try to get the next iocb on the tx queue */
2913                 iocbq = emlxs_tx_get(cp, 1);
2914         }
2915 
2916 sendit:
2917         count = 0;
2918 
2919         /* Process each iocbq */
2920         while (iocbq) {
2921                 sbp = iocbq->sbp;
2922 
2923 #ifdef NODE_THROTTLE_SUPPORT
2924                 if (sbp && sbp->node && sbp->node->io_throttle) {
2925                         node_throttle = sbp->node->io_throttle -
2926                             sbp->node->io_active;
2927                         if (node_throttle <= 0) {
2928                                 /* Node is busy */
2929                                 /* Queue this iocb and get next iocb from */
2930                                 /* channel */
2931 
2932                                 if (!marked_node) {
2933                                         marked_node = sbp->node;
2934                                 }
2935 
2936                                 mutex_enter(&EMLXS_TX_CHANNEL_LOCK);
2937                                 emlxs_tx_put(iocbq, 0);
2938 
2939                                 if (cp->nodeq.q_first == marked_node) {
2940                                         mutex_exit(&EMLXS_TX_CHANNEL_LOCK);
2941                                         goto busy;
2942                                 }
2943 
2944                                 iocbq = emlxs_tx_get(cp, 0);
2945                                 mutex_exit(&EMLXS_TX_CHANNEL_LOCK);
2946                                 continue;
2947                         }
2948                 }
2949                 marked_node = 0;
2950 #endif /* NODE_THROTTLE_SUPPORT */
2951 
2952                 if (sbp && (sbp->pkt_flags & PACKET_DELAY_REQUIRED)) {
2953                         /*
2954                          * Update adapter if needed, since we are about to
2955                          * delay here
2956                          */
2957                         if (count) {
2958                                 count = 0;
2959 
2960                                 /* Update the adapter's cmd put index */
2961                                 if (hba->bus_type == SBUS_FC) {
2962                                         slim2p->mbx.us.s2.host[channelno].
2963                                             cmdPutInx =
2964                                             BE_SWAP32(rp->fc_cmdidx);
2965 
2966                                         /* DMA sync the index for the adapter */
2967                                         offset = (off_t)
2968                                             ((uint64_t)
2969                                             ((unsigned long)&(slim2p->mbx.us.
2970                                             s2.host[channelno].cmdPutInx)) -
2971                                             (uint64_t)((unsigned long)slim2p));
2972                                         EMLXS_MPDATA_SYNC(hba->sli.sli3.slim2.
2973                                             dma_handle, offset, 4,
2974                                             DDI_DMA_SYNC_FORDEV);
2975                                 } else {
2976                                         ioa2 = (void *)
2977                                             ((char *)hba->sli.sli3.slim_addr +
2978                                             hba->sli.sli3.hgp_ring_offset +
2979                                             ((channelno * 2) *
2980                                             sizeof (uint32_t)));
2981                                         WRITE_SLIM_ADDR(hba,
2982                                             (volatile uint32_t *)ioa2,
2983                                             rp->fc_cmdidx);
2984                                 }
2985 
2986                                 status = (CA_R0ATT << (channelno * 4));
2987                                 WRITE_CSR_REG(hba, FC_CA_REG(hba),
2988                                     (volatile uint32_t)status);
2989 
2990                         }
2991                         /* Perform delay */
2992                         if ((channelno == FC_ELS_RING) &&
2993                             !(iocbq->flag & IOCB_FCP_CMD)) {
2994                                 drv_usecwait(100000);
2995                         } else {
2996                                 drv_usecwait(20000);
2997                         }
2998                 }
2999 
3000                 /*
3001                  * At this point, we have a command ring slot available
3002                  * and an iocb to send
3003                  */
3004                 flag =  iocbq->flag;
3005 
3006                 /* Send the iocb */
3007                 emlxs_sli3_issue_iocb(hba, rp, iocbq);
3008                 /*
3009                  * After this, the sbp / iocb should not be
3010                  * accessed in the xmit path.
3011                  */
3012 
3013                 count++;
3014                 if (iocbq && (!(flag & IOCB_SPECIAL))) {
3015                         /* Check if HBA is full */
3016                         throttle = hba->io_throttle - hba->io_active;
3017                         if (throttle <= 0) {
3018                                 goto busy;
3019                         }
3020                 }
3021 
3022                 /* Calculate the next put index */
3023                 nextIdx =
3024                     (rp->fc_cmdidx + 1 >=
3025                     rp->fc_numCiocb) ? 0 : rp->fc_cmdidx + 1;
3026 
3027                 /* Check if ring is full */
3028                 if (nextIdx == rp->fc_port_cmdidx) {
3029                         /* Try one more time */
3030                         EMLXS_MPDATA_SYNC(hba->sli.sli3.slim2.dma_handle,
3031                             offset, 4, DDI_DMA_SYNC_FORKERNEL);
3032                         rp->fc_port_cmdidx = BE_SWAP32(pgp->cmdGetInx);
3033 
3034                         if (nextIdx == rp->fc_port_cmdidx) {
3035                                 goto busy;
3036                         }
3037                 }
3038 
3039                 /* Get the next iocb from the tx queue if there is one */
3040                 iocbq = emlxs_tx_get(cp, 1);
3041         }
3042 
3043         if (count) {
3044                 /* Update the adapter's cmd put index */
3045                 if (hba->bus_type == SBUS_FC) {
3046                         slim2p->mbx.us.s2.host[channelno].
3047                             cmdPutInx = BE_SWAP32(rp->fc_cmdidx);
3048 
3049                         /* DMA sync the index for the adapter */
3050                         offset = (off_t)
3051                             ((uint64_t)((unsigned long)&(slim2p->mbx.us.s2.
3052                             host[channelno].cmdPutInx)) -
3053                             (uint64_t)((unsigned long)slim2p));
3054                         EMLXS_MPDATA_SYNC(hba->sli.sli3.slim2.dma_handle,
3055                             offset, 4, DDI_DMA_SYNC_FORDEV);
3056                 } else {
3057                         ioa2 =
3058                             (void *)((char *)hba->sli.sli3.slim_addr +
3059                             hba->sli.sli3.hgp_ring_offset +
3060                             ((channelno * 2) * sizeof (uint32_t)));
3061                         WRITE_SLIM_ADDR(hba, (volatile uint32_t *)ioa2,
3062                             rp->fc_cmdidx);
3063                 }
3064 
3065                 status = (CA_R0ATT << (channelno * 4));
3066                 WRITE_CSR_REG(hba, FC_CA_REG(hba),
3067                     (volatile uint32_t)status);
3068 
3069                 /* Check tx queue one more time before releasing */
3070                 if ((iocbq = emlxs_tx_get(cp, 1))) {
3071                         /*
3072                          * EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_ring_watchdog_msg,
3073                          * "%s host=%d port=%d   RACE CONDITION1
3074                          * DETECTED.", emlxs_ring_xlate(channelno),
3075                          * rp->fc_cmdidx, rp->fc_port_cmdidx);
3076                          */
3077                         goto sendit;
3078                 }
3079         }
3080 
3081 #ifdef FMA_SUPPORT
3082         /* Access handle validation */
3083         EMLXS_CHK_ACC_HANDLE(hba, hba->sli.sli3.slim_acc_handle);
3084         EMLXS_CHK_ACC_HANDLE(hba, hba->sli.sli3.csr_acc_handle);
3085 #endif  /* FMA_SUPPORT */
3086 
3087         mutex_exit(&EMLXS_CMD_RING_LOCK(channelno));
3088 
3089         return;
3090 
3091 busy:
3092 
3093         /*
3094          * Set ring to SET R0CE_REQ in Chip Att register.
3095          * Chip will tell us when an entry is freed.
3096          */
3097         if (count) {
3098                 /* Update the adapter's cmd put index */
3099                 if (hba->bus_type == SBUS_FC) {
3100                         slim2p->mbx.us.s2.host[channelno].cmdPutInx =
3101                             BE_SWAP32(rp->fc_cmdidx);
3102 
3103                         /* DMA sync the index for the adapter */
3104                         offset = (off_t)
3105                             ((uint64_t)((unsigned long)&(slim2p->mbx.us.s2.
3106                             host[channelno].cmdPutInx)) -
3107                             (uint64_t)((unsigned long)slim2p));
3108                         EMLXS_MPDATA_SYNC(hba->sli.sli3.slim2.dma_handle,
3109                             offset, 4, DDI_DMA_SYNC_FORDEV);
3110                 } else {
3111                         ioa2 =
3112                             (void *)((char *)hba->sli.sli3.slim_addr +
3113                             hba->sli.sli3.hgp_ring_offset +
3114                             ((channelno * 2) * sizeof (uint32_t)));
3115                         WRITE_SLIM_ADDR(hba, (volatile uint32_t *)ioa2,
3116                             rp->fc_cmdidx);
3117                 }
3118         }
3119 
3120         status = ((CA_R0ATT | CA_R0CE_REQ) << (channelno * 4));
3121         WRITE_CSR_REG(hba, FC_CA_REG(hba), (volatile uint32_t)status);
3122 
3123         if (throttle <= 0) {
3124                 HBASTATS.IocbThrottled++;
3125         } else {
3126                 HBASTATS.IocbRingFull[channelno]++;
3127         }
3128 
3129 #ifdef FMA_SUPPORT
3130         /* Access handle validation */
3131         EMLXS_CHK_ACC_HANDLE(hba, hba->sli.sli3.slim_acc_handle);
3132         EMLXS_CHK_ACC_HANDLE(hba, hba->sli.sli3.csr_acc_handle);
3133 #endif  /* FMA_SUPPORT */
3134 
3135         mutex_exit(&EMLXS_CMD_RING_LOCK(channelno));
3136 
3137         return;
3138 
3139 } /* emlxs_sli3_issue_iocb_cmd() */
3140 
3141 
3142 /* MBX_NOWAIT - returns MBX_BUSY or MBX_SUCCESS or MBX_HARDWARE_ERROR */
3143 /* MBX_WAIT   - returns MBX_TIMEOUT or mailbox_status */
3144 /* MBX_SLEEP  - returns MBX_TIMEOUT or mailbox_status */
3145 /* MBX_POLL   - returns MBX_TIMEOUT or mailbox_status */
3146 
3147 static uint32_t
3148 emlxs_sli3_issue_mbox_cmd(emlxs_hba_t *hba, MAILBOXQ *mbq, int32_t flag,
3149     uint32_t tmo)
3150 {
3151         emlxs_port_t            *port;
3152         SLIM2                   *slim2p = (SLIM2 *)hba->sli.sli3.slim2.virt;
3153         MAILBOX                 *mbox;
3154         MAILBOX                 *mb;
3155         volatile uint32_t       word0;
3156         volatile uint32_t       ldata;
3157         off_t                   offset;
3158         MATCHMAP                *mbox_bp;
3159         uint32_t                tmo_local;
3160         MAILBOX                 *swpmb;
3161 
3162         if (!mbq->port) {
3163                 mbq->port = &PPORT;
3164         }
3165 
3166         port = (emlxs_port_t *)mbq->port;
3167 
3168         mb = (MAILBOX *)mbq;
3169         swpmb = (MAILBOX *)&word0;
3170 
3171         mb->mbxStatus = MBX_SUCCESS;
3172 
3173         /* Check for minimum timeouts */
3174         switch (mb->mbxCommand) {
3175         /* Mailbox commands that erase/write flash */
3176         case MBX_DOWN_LOAD:
3177         case MBX_UPDATE_CFG:
3178         case MBX_LOAD_AREA:
3179         case MBX_LOAD_EXP_ROM:
3180         case MBX_WRITE_NV:
3181         case MBX_FLASH_WR_ULA:
3182         case MBX_DEL_LD_ENTRY:
3183         case MBX_LOAD_SM:
3184                 if (tmo < 300) {
3185                         tmo = 300;
3186                 }
3187                 break;
3188 
3189         default:
3190                 if (tmo < 30) {
3191                         tmo = 30;
3192                 }
3193                 break;
3194         }
3195 
3196         /* Convert tmo seconds to 10 millisecond tics */
3197         tmo_local = tmo * 100;
3198 
3199         /* Adjust wait flag */
3200         if (flag != MBX_NOWAIT) {
3201                 /* If interrupt is enabled, use sleep, otherwise poll */
3202                 if (hba->sli.sli3.hc_copy & HC_MBINT_ENA) {
3203                         flag = MBX_SLEEP;
3204                 } else {
3205                         flag = MBX_POLL;
3206                 }
3207         }
3208 
3209         mutex_enter(&EMLXS_PORT_LOCK);
3210 
3211         /* Check for hardware error */
3212         if (hba->flag & FC_HARDWARE_ERROR) {
3213                 mb->mbxStatus = (hba->flag & FC_OVERTEMP_EVENT) ?
3214                     MBX_OVERTEMP_ERROR : MBX_HARDWARE_ERROR;
3215 
3216                 mutex_exit(&EMLXS_PORT_LOCK);
3217 
3218                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mbox_detail_msg,
3219                     "Hardware error reported. %s failed. status=%x mb=%p",
3220                     emlxs_mb_cmd_xlate(mb->mbxCommand), mb->mbxStatus, mb);
3221 
3222                 return (MBX_HARDWARE_ERROR);
3223         }
3224 
3225         if (hba->mbox_queue_flag) {
3226                 /* If we are not polling, then queue it for later */
3227                 if (flag == MBX_NOWAIT) {
3228                         EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mbox_detail_msg,
3229                             "Busy.      %s: mb=%p NoWait.",
3230                             emlxs_mb_cmd_xlate(mb->mbxCommand), mb);
3231 
3232                         emlxs_mb_put(hba, mbq);
3233 
3234                         HBASTATS.MboxBusy++;
3235 
3236                         mutex_exit(&EMLXS_PORT_LOCK);
3237 
3238                         return (MBX_BUSY);
3239                 }
3240 
3241                 while (hba->mbox_queue_flag) {
3242                         mutex_exit(&EMLXS_PORT_LOCK);
3243 
3244                         if (tmo_local-- == 0) {
3245                                 EMLXS_MSGF(EMLXS_CONTEXT,
3246                                     &emlxs_mbox_event_msg,
3247                                     "Timeout.   %s: mb=%p tmo=%d Waiting.",
3248                                     emlxs_mb_cmd_xlate(mb->mbxCommand), mb,
3249                                     tmo);
3250 
3251                                 /* Non-lethalStatus mailbox timeout */
3252                                 /* Does not indicate a hardware error */
3253                                 mb->mbxStatus = MBX_TIMEOUT;
3254                                 return (MBX_TIMEOUT);
3255                         }
3256 
3257                         BUSYWAIT_MS(10);
3258                         mutex_enter(&EMLXS_PORT_LOCK);
3259 
3260                         /* Check for hardware error */
3261                         if (hba->flag & FC_HARDWARE_ERROR) {
3262                                 mb->mbxStatus =
3263                                     (hba->flag & FC_OVERTEMP_EVENT) ?
3264                                     MBX_OVERTEMP_ERROR : MBX_HARDWARE_ERROR;
3265 
3266                                 mutex_exit(&EMLXS_PORT_LOCK);
3267 
3268                                 EMLXS_MSGF(EMLXS_CONTEXT,
3269                                     &emlxs_mbox_detail_msg,
3270                                     "Hardware error reported. %s failed. "
3271                                     "status=%x mb=%p",
3272                                     emlxs_mb_cmd_xlate(mb->mbxCommand),
3273                                     mb->mbxStatus, mb);
3274 
3275                                 return (MBX_HARDWARE_ERROR);
3276                         }
3277                 }
3278         }
3279 
3280         /* Initialize mailbox area */
3281         emlxs_mb_init(hba, mbq, flag, tmo);
3282 
3283         switch (flag) {
3284         case MBX_NOWAIT:
3285 
3286                 if (mb->mbxCommand != MBX_HEARTBEAT) {
3287                         if (mb->mbxCommand != MBX_DOWN_LOAD &&
3288                             mb->mbxCommand != MBX_DUMP_MEMORY) {
3289                                 EMLXS_MSGF(EMLXS_CONTEXT,
3290                                     &emlxs_mbox_detail_msg,
3291                                     "Sending.   %s: mb=%p NoWait.",
3292                                     emlxs_mb_cmd_xlate(mb->mbxCommand), mb);
3293                         }
3294                 }
3295 
3296                 break;
3297 
3298         case MBX_SLEEP:
3299                 if (mb->mbxCommand != MBX_DOWN_LOAD &&
3300                     mb->mbxCommand != MBX_DUMP_MEMORY) {
3301                         EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mbox_detail_msg,
3302                             "Sending.   %s: mb=%p Sleep.",
3303                             emlxs_mb_cmd_xlate(mb->mbxCommand), mb);
3304                 }
3305 
3306                 break;
3307 
3308         case MBX_POLL:
3309                 if (mb->mbxCommand != MBX_DOWN_LOAD &&
3310                     mb->mbxCommand != MBX_DUMP_MEMORY) {
3311                         EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mbox_detail_msg,
3312                             "Sending.   %s: mb=%p Polled.",
3313                             emlxs_mb_cmd_xlate(mb->mbxCommand), mb);
3314                 }
3315                 break;
3316         }
3317 
3318         mb->mbxOwner = OWN_CHIP;
3319 
3320         /* Clear the attention bit */
3321         WRITE_CSR_REG(hba, FC_HA_REG(hba), HA_MBATT);
3322 
3323         if (hba->flag & FC_SLIM2_MODE) {
3324                 /* First copy command data */
3325                 mbox = FC_SLIM2_MAILBOX(hba);
3326                 offset =
3327                     (off_t)((uint64_t)((unsigned long)mbox)
3328                     - (uint64_t)((unsigned long)slim2p));
3329 
3330 #ifdef MBOX_EXT_SUPPORT
3331                 if (mbq->extbuf) {
3332                         uint32_t *mbox_ext =
3333                             (uint32_t *)((uint8_t *)mbox +
3334                             MBOX_EXTENSION_OFFSET);
3335                         off_t offset_ext   = offset + MBOX_EXTENSION_OFFSET;
3336 
3337                         BE_SWAP32_BCOPY((uint8_t *)mbq->extbuf,
3338                             (uint8_t *)mbox_ext, mbq->extsize);
3339 
3340                         EMLXS_MPDATA_SYNC(hba->sli.sli3.slim2.dma_handle,
3341                             offset_ext, mbq->extsize,
3342                             DDI_DMA_SYNC_FORDEV);
3343                 }
3344 #endif /* MBOX_EXT_SUPPORT */
3345 
3346                 BE_SWAP32_BCOPY((uint8_t *)mb, (uint8_t *)mbox,
3347                     MAILBOX_CMD_BSIZE);
3348 
3349                 EMLXS_MPDATA_SYNC(hba->sli.sli3.slim2.dma_handle, offset,
3350                     MAILBOX_CMD_BSIZE, DDI_DMA_SYNC_FORDEV);
3351         } else {        /* SLIM 1 */
3352 
3353                 mbox = FC_SLIM1_MAILBOX(hba);
3354 
3355 #ifdef MBOX_EXT_SUPPORT
3356                 if (mbq->extbuf) {
3357                         uint32_t *mbox_ext =
3358                             (uint32_t *)((uint8_t *)mbox +
3359                             MBOX_EXTENSION_OFFSET);
3360                         WRITE_SLIM_COPY(hba, (uint32_t *)mbq->extbuf,
3361                             mbox_ext, (mbq->extsize / 4));
3362                 }
3363 #endif /* MBOX_EXT_SUPPORT */
3364 
3365                 /* First copy command data */
3366                 WRITE_SLIM_COPY(hba, &mb->un.varWords, &mbox->un.varWords,
3367                     (MAILBOX_CMD_WSIZE - 1));
3368 
3369                 /* copy over last word, with mbxOwner set */
3370                 ldata = *((volatile uint32_t *)mb);
3371                 WRITE_SLIM_ADDR(hba, ((volatile uint32_t *)mbox), ldata);
3372         }
3373 
3374         /* Interrupt board to do it right away */
3375         WRITE_CSR_REG(hba, FC_CA_REG(hba), CA_MBATT);
3376 
3377         mutex_exit(&EMLXS_PORT_LOCK);
3378 
3379 #ifdef FMA_SUPPORT
3380         /* Access handle validation */
3381         if ((emlxs_fm_check_acc_handle(hba, hba->sli.sli3.slim_acc_handle)
3382             != DDI_FM_OK) ||
3383             (emlxs_fm_check_acc_handle(hba, hba->sli.sli3.csr_acc_handle)
3384             != DDI_FM_OK)) {
3385                 EMLXS_MSGF(EMLXS_CONTEXT,
3386                     &emlxs_invalid_access_handle_msg, NULL);
3387                 return (MBX_HARDWARE_ERROR);
3388         }
3389 #endif  /* FMA_SUPPORT */
3390 
3391         switch (flag) {
3392         case MBX_NOWAIT:
3393                 return (MBX_SUCCESS);
3394 
3395         case MBX_SLEEP:
3396 
3397                 /* Wait for completion */
3398                 /* The driver clock is timing the mailbox. */
3399                 /* emlxs_mb_fini() will be called externally. */
3400 
3401                 mutex_enter(&EMLXS_MBOX_LOCK);
3402                 while (!(mbq->flag & MBQ_COMPLETED)) {
3403                         cv_wait(&EMLXS_MBOX_CV, &EMLXS_MBOX_LOCK);
3404                 }
3405                 mutex_exit(&EMLXS_MBOX_LOCK);
3406 
3407                 if (mb->mbxStatus == MBX_TIMEOUT) {
3408                         EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mbox_event_msg,
3409                             "Timeout.   %s: mb=%p tmo=%d. Sleep.",
3410                             emlxs_mb_cmd_xlate(mb->mbxCommand), mb, tmo);
3411                 } else {
3412                         if (mb->mbxCommand != MBX_DOWN_LOAD &&
3413                             mb->mbxCommand != MBX_DUMP_MEMORY) {
3414                                 EMLXS_MSGF(EMLXS_CONTEXT,
3415                                     &emlxs_mbox_detail_msg,
3416                                     "Completed. %s: mb=%p status=%x Sleep.",
3417                                     emlxs_mb_cmd_xlate(mb->mbxCommand), mb,
3418                                     mb->mbxStatus);
3419                         }
3420                 }
3421 
3422                 break;
3423 
3424         case MBX_POLL:
3425 
3426                 /* Convert tmo seconds to 500 usec tics */
3427                 tmo_local = tmo * 2000;
3428 
3429                 /* Get first word of mailbox */
3430                 if (hba->flag & FC_SLIM2_MODE) {
3431                         mbox = FC_SLIM2_MAILBOX(hba);
3432                         offset = (off_t)((uint64_t)((unsigned long)mbox) -
3433                             (uint64_t)((unsigned long)slim2p));
3434 
3435                         EMLXS_MPDATA_SYNC(hba->sli.sli3.slim2.dma_handle,
3436                             offset, sizeof (uint32_t), DDI_DMA_SYNC_FORKERNEL);
3437                         word0 = *((volatile uint32_t *)mbox);
3438                         word0 = BE_SWAP32(word0);
3439                 } else {
3440                         mbox = FC_SLIM1_MAILBOX(hba);
3441                         word0 =
3442                             READ_SLIM_ADDR(hba, ((volatile uint32_t *)mbox));
3443                 }
3444 
3445                 /* Wait for command to complete */
3446                 while ((swpmb->mbxOwner == OWN_CHIP) &&
3447                     !(mbq->flag & MBQ_COMPLETED)) {
3448                         if (!hba->timer_id && (tmo_local-- == 0)) {
3449                                 /* self time */
3450                                 EMLXS_MSGF(EMLXS_CONTEXT,
3451                                     &emlxs_mbox_timeout_msg,
3452                                     "%s: mb=%p tmo=%d Polled.",
3453                                     emlxs_mb_cmd_xlate(mb->mbxCommand),
3454                                     mb, tmo);
3455 
3456                                 hba->flag |= FC_MBOX_TIMEOUT;
3457                                 EMLXS_STATE_CHANGE(hba, FC_ERROR);
3458                                 emlxs_mb_fini(hba, NULL, MBX_TIMEOUT);
3459 
3460                                 break;
3461                         }
3462 
3463                         BUSYWAIT_US(500);
3464 
3465                         /* Get first word of mailbox */
3466                         if (hba->flag & FC_SLIM2_MODE) {
3467                                 EMLXS_MPDATA_SYNC(
3468                                     hba->sli.sli3.slim2.dma_handle, offset,
3469                                     sizeof (uint32_t), DDI_DMA_SYNC_FORKERNEL);
3470                                 word0 = *((volatile uint32_t *)mbox);
3471                                 word0 = BE_SWAP32(word0);
3472                         } else {
3473                                 word0 =
3474                                     READ_SLIM_ADDR(hba,
3475                                     ((volatile uint32_t *)mbox));
3476                         }
3477 
3478                 }       /* while */
3479 
3480                 if (mb->mbxStatus == MBX_TIMEOUT) {
3481                         EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mbox_event_msg,
3482                             "Timeout.   %s: mb=%p tmo=%d. Polled.",
3483                             emlxs_mb_cmd_xlate(mb->mbxCommand), mb, tmo);
3484 
3485                         break;
3486                 }
3487 
3488                 /* Check for config port command */
3489                 if ((swpmb->mbxCommand == MBX_CONFIG_PORT) &&
3490                     (swpmb->mbxStatus == MBX_SUCCESS)) {
3491                         /* Setup host mbox for cmpl */
3492                         mbox = FC_SLIM2_MAILBOX(hba);
3493                         offset = (off_t)((uint64_t)((unsigned long)mbox)
3494                             - (uint64_t)((unsigned long)slim2p));
3495 
3496                         hba->flag |= FC_SLIM2_MODE;
3497                 }
3498 
3499                 /* copy results back to user */
3500                 if (hba->flag & FC_SLIM2_MODE) {
3501                         EMLXS_MPDATA_SYNC(hba->sli.sli3.slim2.dma_handle,
3502                             offset, MAILBOX_CMD_BSIZE, DDI_DMA_SYNC_FORKERNEL);
3503 
3504                         BE_SWAP32_BCOPY((uint8_t *)mbox, (uint8_t *)mb,
3505                             MAILBOX_CMD_BSIZE);
3506                 } else {
3507                         READ_SLIM_COPY(hba, (uint32_t *)mb,
3508                             (uint32_t *)mbox, MAILBOX_CMD_WSIZE);
3509                 }
3510 
3511 #ifdef MBOX_EXT_SUPPORT
3512                 if (mbq->extbuf) {
3513                         uint32_t *mbox_ext =
3514                             (uint32_t *)((uint8_t *)mbox +
3515                             MBOX_EXTENSION_OFFSET);
3516                         off_t offset_ext   = offset + MBOX_EXTENSION_OFFSET;
3517 
3518                         if (hba->flag & FC_SLIM2_MODE) {
3519                                 EMLXS_MPDATA_SYNC(
3520                                     hba->sli.sli3.slim2.dma_handle, offset_ext,
3521                                     mbq->extsize, DDI_DMA_SYNC_FORKERNEL);
3522 
3523                                 BE_SWAP32_BCOPY((uint8_t *)mbox_ext,
3524                                     (uint8_t *)mbq->extbuf, mbq->extsize);
3525                         } else {
3526                                 READ_SLIM_COPY(hba,
3527                                     (uint32_t *)mbq->extbuf, mbox_ext,
3528                                     (mbq->extsize / 4));
3529                         }
3530                 }
3531 #endif /* MBOX_EXT_SUPPORT */
3532 
3533                 /* Sync the memory buffer */
3534                 if (mbq->bp) {
3535                         mbox_bp = (MATCHMAP *)mbq->bp;
3536                         EMLXS_MPDATA_SYNC(mbox_bp->dma_handle, 0,
3537                             mbox_bp->size, DDI_DMA_SYNC_FORKERNEL);
3538                 }
3539 
3540                 if (mb->mbxCommand != MBX_DOWN_LOAD &&
3541                     mb->mbxCommand != MBX_DUMP_MEMORY) {
3542                         EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mbox_detail_msg,
3543                             "Completed. %s: mb=%p status=%x Polled.",
3544                             emlxs_mb_cmd_xlate(mb->mbxCommand), mb,
3545                             mb->mbxStatus);
3546                 }
3547 
3548                 /* Process the result */
3549                 if (!(mbq->flag & MBQ_PASSTHRU)) {
3550                         if (mbq->mbox_cmpl) {
3551                                 (void) (mbq->mbox_cmpl)(hba, mbq);
3552                         }
3553                 }
3554 
3555                 /* Clear the attention bit */
3556                 WRITE_CSR_REG(hba, FC_HA_REG(hba), HA_MBATT);
3557 
3558                 /* Clean up the mailbox area */
3559                 emlxs_mb_fini(hba, NULL, mb->mbxStatus);
3560 
3561                 break;
3562 
3563         }       /* switch (flag) */
3564 
3565         return (mb->mbxStatus);
3566 
3567 } /* emlxs_sli3_issue_mbox_cmd() */
3568 
3569 
3570 #ifdef SFCT_SUPPORT
3571 /*ARGSUSED*/
3572 static uint32_t
3573 emlxs_sli3_prep_fct_iocb(emlxs_port_t *port, emlxs_buf_t *cmd_sbp,
3574         int channel)
3575 {
3576         emlxs_hba_t *hba = HBA;
3577         emlxs_config_t *cfg = &CFG;
3578         fct_cmd_t *fct_cmd;
3579         stmf_data_buf_t *dbuf;
3580         scsi_task_t *fct_task;
3581         fc_packet_t *pkt;
3582         uint32_t did;
3583         IOCBQ *iocbq;
3584         IOCB *iocb;
3585         uint32_t timeout;
3586         uint32_t iotag;
3587         emlxs_node_t *ndlp;
3588         CHANNEL *cp;
3589         ddi_dma_cookie_t *cp_cmd;
3590 
3591         pkt = PRIV2PKT(cmd_sbp);
3592 
3593         cp = (CHANNEL *)cmd_sbp->channel;
3594 
3595         iocbq = &cmd_sbp->iocbq;
3596         iocb = &iocbq->iocb;
3597 
3598 
3599         /* Get the iotag by registering the packet */
3600         iotag = emlxs_register_pkt(cp, cmd_sbp);
3601 
3602         if (!iotag) {
3603                 /* No more command slots available, retry later */
3604                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_trans_msg,
3605                     "Adapter Busy. Unable to allocate iotag. did=0x%x",
3606                     cmd_sbp->did);
3607 
3608                 return (IOERR_NO_RESOURCES);
3609         }
3610 
3611 
3612         /* Point of no return */
3613 
3614         if (iocb->ULPCOMMAND == CMD_ABORT_XRI_CX) {
3615 
3616                 ndlp = cmd_sbp->node;
3617                 cp->ulpSendCmd++;
3618 
3619                 /* Initalize iocbq */
3620                 iocbq->port = (void *)port;
3621                 iocbq->node = (void *)ndlp;
3622                 iocbq->channel = (void *)cp;
3623 
3624                 /*
3625                  * Don't give the abort priority, we want the IOCB
3626                  * we are aborting to be processed first.
3627                  */
3628                 iocbq->flag |= IOCB_SPECIAL;
3629 
3630                 iocb->ULPCONTEXT = pkt->pkt_cmd_fhdr.rx_id;
3631                 iocb->ULPIOTAG = (uint16_t)iotag;
3632                 iocb->ULPLE = 1;
3633                 iocb->ULPCLASS = cmd_sbp->class;
3634                 iocb->ULPOWNER = OWN_CHIP;
3635 
3636                 if (hba->state >= FC_LINK_UP) {
3637                         /* Create the abort IOCB */
3638                         iocb->un.acxri.abortType = ABORT_TYPE_ABTS;
3639                         iocb->ULPCOMMAND = CMD_ABORT_XRI_CX;
3640 
3641                 } else {
3642                         /* Create the close IOCB */
3643                         iocb->ULPCOMMAND = CMD_CLOSE_XRI_CX;
3644 
3645                 }
3646 
3647                 iocb->ULPRSVDBYTE =
3648                     ((pkt->pkt_timeout > 0xff) ? 0 : pkt->pkt_timeout);
3649                 /* Set the pkt timer */
3650                 cmd_sbp->ticks = hba->timer_tics + pkt->pkt_timeout +
3651                     ((pkt->pkt_timeout > 0xff) ? 0 : 10);
3652 
3653                 return (IOERR_SUCCESS);
3654 
3655         } else if (iocb->ULPCOMMAND == CMD_FCP_TRSP64_CX) {
3656 
3657                 ndlp = cmd_sbp->node;
3658                 cp->ulpSendCmd++;
3659 
3660                 /* Initalize iocbq */
3661                 iocbq->port = (void *)port;
3662                 iocbq->node = (void *)ndlp;
3663                 iocbq->channel = (void *)cp;
3664 
3665 #if (EMLXS_MODREV >= EMLXS_MODREV3)
3666                 cp_cmd = pkt->pkt_cmd_cookie;
3667 #else
3668                 cp_cmd  = &pkt->pkt_cmd_cookie;
3669 #endif  /* >= EMLXS_MODREV3 */
3670 
3671                 iocb->un.fcpt64.bdl.addrHigh = PADDR_HI(cp_cmd->dmac_laddress);
3672                 iocb->un.fcpt64.bdl.addrLow = PADDR_LO(cp_cmd->dmac_laddress);
3673                 iocb->un.fcpt64.bdl.bdeSize = pkt->pkt_cmdlen;
3674                 iocb->un.fcpt64.bdl.bdeFlags = 0;
3675 
3676                 if (hba->sli_mode < 3) {
3677                         iocb->ULPBDECOUNT = 1;
3678                         iocb->ULPLE = 1;
3679                 } else {        /* SLI3 */
3680 
3681                         iocb->ULPBDECOUNT = 0;
3682                         iocb->ULPLE = 0;
3683                         iocb->unsli3.ext_iocb.ebde_count = 0;
3684                 }
3685 
3686                 /* Initalize iocb */
3687                 iocb->ULPCONTEXT = (uint16_t)pkt->pkt_cmd_fhdr.rx_id;
3688                 iocb->ULPIOTAG = (uint16_t)iotag;
3689                 iocb->ULPRSVDBYTE =
3690                     ((pkt->pkt_timeout > 0xff) ? 0 : pkt->pkt_timeout);
3691                 iocb->ULPOWNER = OWN_CHIP;
3692                 iocb->ULPCLASS = cmd_sbp->class;
3693                 iocb->ULPCOMMAND = CMD_FCP_TRSP64_CX;
3694 
3695                 /* Set the pkt timer */
3696                 cmd_sbp->ticks = hba->timer_tics + pkt->pkt_timeout +
3697                     ((pkt->pkt_timeout > 0xff) ? 0 : 10);
3698 
3699                 if (pkt->pkt_cmdlen) {
3700                         EMLXS_MPDATA_SYNC(pkt->pkt_cmd_dma, 0, pkt->pkt_cmdlen,
3701                             DDI_DMA_SYNC_FORDEV);
3702                 }
3703 
3704                 return (IOERR_SUCCESS);
3705         }
3706 
3707         dbuf = cmd_sbp->fct_buf;
3708         fct_cmd = cmd_sbp->fct_cmd;
3709         fct_task = (scsi_task_t *)fct_cmd->cmd_specific;
3710         ndlp = *(emlxs_node_t **)fct_cmd->cmd_rp->rp_fca_private;
3711         did = fct_cmd->cmd_rportid;
3712 
3713         iocbq->channel = (void *)cmd_sbp->channel;
3714 
3715         if (emlxs_fct_bde_setup(port, cmd_sbp)) {
3716                 /* Unregister the packet */
3717                 (void) emlxs_unregister_pkt(cmd_sbp->channel, iotag, 0);
3718 
3719                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_trans_msg,
3720                     "Adapter Busy. Unable to setup buffer list. did=%x", did);
3721 
3722                 return (IOERR_INTERNAL_ERROR);
3723         }
3724 
3725         if (cfg[CFG_TIMEOUT_ENABLE].current) {
3726                 timeout =
3727                     ((2 * hba->fc_ratov) < 60) ? 60 : (2 * hba->fc_ratov);
3728         } else {
3729                 timeout = 0x80000000;
3730         }
3731 
3732         cmd_sbp->ticks =
3733             hba->timer_tics + timeout + ((timeout > 0xff) ? 0 : 10);
3734 
3735         /* Initalize iocbq */
3736         iocbq->port = (void *)port;
3737         iocbq->node = (void *)ndlp;
3738 
3739         /* Initalize iocb */
3740         iocb->ULPCONTEXT = (uint16_t)fct_cmd->cmd_rxid;
3741         iocb->ULPIOTAG = (uint16_t)iotag;
3742         iocb->ULPRSVDBYTE = ((timeout > 0xff) ? 0 : timeout);
3743         iocb->ULPOWNER = OWN_CHIP;
3744         iocb->ULPCLASS = cmd_sbp->class;
3745 
3746         iocb->ULPPU = 1;     /* Wd4 is relative offset */
3747         iocb->un.fcpt64.fcpt_Offset = dbuf->db_relative_offset;
3748 
3749         if (fct_task->task_flags & TF_WRITE_DATA) {
3750                 iocb->ULPCOMMAND = CMD_FCP_TRECEIVE64_CX;
3751         } else {        /* TF_READ_DATA */
3752 
3753                 iocb->ULPCOMMAND = CMD_FCP_TSEND64_CX;
3754 
3755                 if ((hba->sli_mode == EMLXS_HBA_SLI3_MODE) &&
3756                     (dbuf->db_data_size >=
3757                     fct_task->task_expected_xfer_length)) {
3758                         iocb->ULPCT = 0x1;
3759                         /* enable auto-rsp AP feature */
3760                 }
3761         }
3762 
3763         return (IOERR_SUCCESS);
3764 
3765 } /* emlxs_sli3_prep_fct_iocb() */
3766 #endif /* SFCT_SUPPORT */
3767 
3768 /* ARGSUSED */
3769 static uint32_t
3770 emlxs_sli3_prep_fcp_iocb(emlxs_port_t *port, emlxs_buf_t *sbp, int channel)
3771 {
3772         emlxs_hba_t *hba = HBA;
3773         fc_packet_t *pkt;
3774         CHANNEL *cp;
3775         IOCBQ *iocbq;
3776         IOCB *iocb;
3777         NODELIST *ndlp;
3778         uint16_t iotag;
3779         uint32_t did;
3780 
3781         pkt = PRIV2PKT(sbp);
3782         did = LE_SWAP24_LO(pkt->pkt_cmd_fhdr.d_id);
3783         cp = &hba->chan[FC_FCP_RING];
3784 
3785         iocbq = &sbp->iocbq;
3786         iocb = &iocbq->iocb;
3787 
3788         /* Find target node object */
3789         ndlp = (NODELIST *)iocbq->node;
3790 
3791         /* Get the iotag by registering the packet */
3792         iotag = emlxs_register_pkt(cp, sbp);
3793 
3794         if (!iotag) {
3795                 /*
3796                  * No more command slots available, retry later
3797                  */
3798                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_trans_msg,
3799                     "Adapter Busy. Unable to allocate iotag: did=0x%x", did);
3800 
3801                 return (FC_TRAN_BUSY);
3802         }
3803 
3804         /* Initalize iocbq */
3805         iocbq->port = (void *) port;
3806         iocbq->channel = (void *) cp;
3807 
3808         /* Indicate this is a FCP cmd */
3809         iocbq->flag |= IOCB_FCP_CMD;
3810 
3811         if (emlxs_bde_setup(port, sbp)) {
3812                 /* Unregister the packet */
3813                 (void) emlxs_unregister_pkt(cp, iotag, 0);
3814 
3815                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_trans_msg,
3816                     "Adapter Busy. Unable to setup buffer list. did=%x", did);
3817 
3818                 return (FC_TRAN_BUSY);
3819         }
3820         /* Point of no return */
3821 
3822         /* Initalize iocb */
3823         iocb->ULPCONTEXT = ndlp->nlp_Rpi;
3824         iocb->ULPIOTAG = iotag;
3825         iocb->ULPRSVDBYTE =
3826             ((pkt->pkt_timeout > 0xff) ? 0 : pkt->pkt_timeout);
3827         iocb->ULPOWNER = OWN_CHIP;
3828 
3829         switch (FC_TRAN_CLASS(pkt->pkt_tran_flags)) {
3830         case FC_TRAN_CLASS1:
3831                 iocb->ULPCLASS = CLASS1;
3832                 break;
3833         case FC_TRAN_CLASS2:
3834                 iocb->ULPCLASS = CLASS2;
3835                 /* iocb->ULPCLASS = CLASS3; */
3836                 break;
3837         case FC_TRAN_CLASS3:
3838         default:
3839                 iocb->ULPCLASS = CLASS3;
3840                 break;
3841         }
3842 
3843         /* if device is FCP-2 device, set the following bit */
3844         /* that says to run the FC-TAPE protocol. */
3845         if (ndlp->nlp_fcp_info & NLP_FCP_2_DEVICE) {
3846                 iocb->ULPFCP2RCVY = 1;
3847         }
3848 
3849         if (pkt->pkt_datalen == 0) {
3850                 iocb->ULPCOMMAND = CMD_FCP_ICMND64_CR;
3851         } else if (pkt->pkt_tran_type == FC_PKT_FCP_READ) {
3852                 iocb->ULPCOMMAND = CMD_FCP_IREAD64_CR;
3853                 iocb->ULPPU = PARM_XFER_CHECK;
3854                 iocb->un.fcpi64.fcpi_parm = pkt->pkt_datalen;
3855         } else {
3856                 iocb->ULPCOMMAND = CMD_FCP_IWRITE64_CR;
3857         }
3858 
3859         return (FC_SUCCESS);
3860 
3861 } /* emlxs_sli3_prep_fcp_iocb() */
3862 
3863 
3864 static uint32_t
3865 emlxs_sli3_prep_ip_iocb(emlxs_port_t *port, emlxs_buf_t *sbp)
3866 {
3867         emlxs_hba_t *hba = HBA;
3868         fc_packet_t *pkt;
3869         IOCBQ *iocbq;
3870         IOCB *iocb;
3871         CHANNEL *cp;
3872         NODELIST *ndlp;
3873         uint16_t iotag;
3874         uint32_t did;
3875 
3876         pkt = PRIV2PKT(sbp);
3877         cp = &hba->chan[FC_IP_RING];
3878         did = LE_SWAP24_LO(pkt->pkt_cmd_fhdr.d_id);
3879 
3880         iocbq = &sbp->iocbq;
3881         iocb = &iocbq->iocb;
3882         ndlp = (NODELIST *)iocbq->node;
3883 
3884         /* Get the iotag by registering the packet */
3885         iotag = emlxs_register_pkt(cp, sbp);
3886 
3887         if (!iotag) {
3888                 /*
3889                  * No more command slots available, retry later
3890                  */
3891                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_trans_msg,
3892                     "Adapter Busy. Unable to allocate iotag: did=0x%x", did);
3893 
3894                 return (FC_TRAN_BUSY);
3895         }
3896 
3897         /* Initalize iocbq */
3898         iocbq->port = (void *) port;
3899         iocbq->channel = (void *) cp;
3900 
3901         if (emlxs_bde_setup(port, sbp)) {
3902                 /* Unregister the packet */
3903                 (void) emlxs_unregister_pkt(cp, iotag, 0);
3904 
3905                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_trans_msg,
3906                     "Adapter Busy. Unable to setup buffer list. did=%x", did);
3907 
3908                 return (FC_TRAN_BUSY);
3909         }
3910         /* Point of no return */
3911 
3912         /* Initalize iocb */
3913         iocb->un.xseq64.w5.hcsw.Fctl = 0;
3914 
3915         if (pkt->pkt_cmd_fhdr.f_ctl & F_CTL_FIRST_SEQ) {
3916                 iocb->un.xseq64.w5.hcsw.Fctl |= FSEQ;
3917         }
3918         if (pkt->pkt_cmd_fhdr.f_ctl & F_CTL_SEQ_INITIATIVE) {
3919                 iocb->un.xseq64.w5.hcsw.Fctl |= SI;
3920         }
3921 
3922         /* network headers */
3923         iocb->un.xseq64.w5.hcsw.Dfctl = pkt->pkt_cmd_fhdr.df_ctl;
3924         iocb->un.xseq64.w5.hcsw.Rctl = pkt->pkt_cmd_fhdr.r_ctl;
3925         iocb->un.xseq64.w5.hcsw.Type = pkt->pkt_cmd_fhdr.type;
3926 
3927         iocb->ULPIOTAG = iotag;
3928         iocb->ULPRSVDBYTE =
3929             ((pkt->pkt_timeout > 0xff) ? 0 : pkt->pkt_timeout);
3930         iocb->ULPOWNER = OWN_CHIP;
3931 
3932         if (pkt->pkt_tran_type == FC_PKT_BROADCAST) {
3933                 HBASTATS.IpBcastIssued++;
3934 
3935                 iocb->ULPCOMMAND = CMD_XMIT_BCAST64_CN;
3936                 iocb->ULPCONTEXT = 0;
3937 
3938                 if (hba->sli_mode == EMLXS_HBA_SLI3_MODE) {
3939                         if (hba->topology != TOPOLOGY_LOOP) {
3940                                 iocb->ULPCT = 0x1;
3941                         }
3942                         iocb->ULPCONTEXT = port->vpi;
3943                 }
3944         } else {
3945                 HBASTATS.IpSeqIssued++;
3946 
3947                 iocb->ULPCOMMAND = CMD_XMIT_SEQUENCE64_CX;
3948                 iocb->ULPCONTEXT = ndlp->nlp_Xri;
3949         }
3950 
3951         switch (FC_TRAN_CLASS(pkt->pkt_tran_flags)) {
3952         case FC_TRAN_CLASS1:
3953                 iocb->ULPCLASS = CLASS1;
3954                 break;
3955         case FC_TRAN_CLASS2:
3956                 iocb->ULPCLASS = CLASS2;
3957                 break;
3958         case FC_TRAN_CLASS3:
3959         default:
3960                 iocb->ULPCLASS = CLASS3;
3961                 break;
3962         }
3963 
3964         return (FC_SUCCESS);
3965 
3966 } /* emlxs_sli3_prep_ip_iocb() */
3967 
3968 
3969 static uint32_t
3970 emlxs_sli3_prep_els_iocb(emlxs_port_t *port, emlxs_buf_t *sbp)
3971 {
3972         emlxs_hba_t *hba = HBA;
3973         fc_packet_t *pkt;
3974         IOCBQ *iocbq;
3975         IOCB *iocb;
3976         CHANNEL *cp;
3977         uint16_t iotag;
3978         uint32_t did;
3979         uint32_t cmd;
3980 
3981         pkt = PRIV2PKT(sbp);
3982         cp = &hba->chan[FC_ELS_RING];
3983         did = LE_SWAP24_LO(pkt->pkt_cmd_fhdr.d_id);
3984 
3985         iocbq = &sbp->iocbq;
3986         iocb = &iocbq->iocb;
3987 
3988 
3989         /* Get the iotag by registering the packet */
3990         iotag = emlxs_register_pkt(cp, sbp);
3991 
3992         if (!iotag) {
3993                 /*
3994                  * No more command slots available, retry later
3995                  */
3996                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_trans_msg,
3997                     "Adapter Busy. Unable to allocate iotag. did=0x%x", did);
3998 
3999                 return (FC_TRAN_BUSY);
4000         }
4001         /* Initalize iocbq */
4002         iocbq->port = (void *) port;
4003         iocbq->channel = (void *) cp;
4004 
4005         if (emlxs_bde_setup(port, sbp)) {
4006                 /* Unregister the packet */
4007                 (void) emlxs_unregister_pkt(cp, iotag, 0);
4008 
4009                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_trans_msg,
4010                     "Adapter Busy. Unable to setup buffer list. did=%x", did);
4011 
4012                 return (FC_TRAN_BUSY);
4013         }
4014         /* Point of no return */
4015 
4016         /* Initalize iocb */
4017         if (pkt->pkt_tran_type == FC_PKT_OUTBOUND) {
4018                 /* ELS Response */
4019                 iocb->ULPCONTEXT = (volatile uint16_t) pkt->pkt_cmd_fhdr.rx_id;
4020                 iocb->ULPCOMMAND = CMD_XMIT_ELS_RSP64_CX;
4021         } else {
4022                 /* ELS Request */
4023                 iocb->un.elsreq64.remoteID = (did == BCAST_DID) ? 0 : did;
4024                 iocb->ULPCONTEXT =
4025                     (did == BCAST_DID) ? pkt->pkt_cmd_fhdr.seq_id : 0;
4026                 iocb->ULPCOMMAND = CMD_ELS_REQUEST64_CR;
4027 
4028                 if (hba->sli_mode == EMLXS_HBA_SLI3_MODE) {
4029                         if (hba->topology != TOPOLOGY_LOOP) {
4030                                 cmd = *((uint32_t *)pkt->pkt_cmd);
4031                                 cmd &= ELS_CMD_MASK;
4032 
4033                                 if ((cmd == ELS_CMD_FLOGI) ||
4034                                     (cmd == ELS_CMD_FDISC)) {
4035                                         iocb->ULPCT = 0x2;
4036                                 } else {
4037                                         iocb->ULPCT = 0x1;
4038                                 }
4039                         }
4040                         iocb->ULPCONTEXT = port->vpi;
4041                 }
4042         }
4043         iocb->ULPIOTAG = iotag;
4044         iocb->ULPRSVDBYTE =
4045             ((pkt->pkt_timeout > 0xff) ? 0 : pkt->pkt_timeout);
4046         iocb->ULPOWNER = OWN_CHIP;
4047 
4048         switch (FC_TRAN_CLASS(pkt->pkt_tran_flags)) {
4049         case FC_TRAN_CLASS1:
4050                 iocb->ULPCLASS = CLASS1;
4051                 break;
4052         case FC_TRAN_CLASS2:
4053                 iocb->ULPCLASS = CLASS2;
4054                 break;
4055         case FC_TRAN_CLASS3:
4056         default:
4057                 iocb->ULPCLASS = CLASS3;
4058                 break;
4059         }
4060         sbp->class = iocb->ULPCLASS;
4061 
4062         return (FC_SUCCESS);
4063 
4064 } /* emlxs_sli3_prep_els_iocb() */
4065 
4066 
4067 static uint32_t
4068 emlxs_sli3_prep_ct_iocb(emlxs_port_t *port, emlxs_buf_t *sbp)
4069 {
4070         emlxs_hba_t *hba = HBA;
4071         fc_packet_t *pkt;
4072         IOCBQ *iocbq;
4073         IOCB *iocb;
4074         CHANNEL *cp;
4075         NODELIST *ndlp;
4076         uint16_t iotag;
4077         uint32_t did;
4078 
4079         pkt = PRIV2PKT(sbp);
4080         did = LE_SWAP24_LO(pkt->pkt_cmd_fhdr.d_id);
4081         cp = &hba->chan[FC_CT_RING];
4082 
4083         iocbq = &sbp->iocbq;
4084         iocb = &iocbq->iocb;
4085         ndlp = (NODELIST *)iocbq->node;
4086 
4087         /* Get the iotag by registering the packet */
4088         iotag = emlxs_register_pkt(cp, sbp);
4089 
4090         if (!iotag) {
4091                 /*
4092                  * No more command slots available, retry later
4093                  */
4094                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_trans_msg,
4095                     "Adapter Busy. Unable to allocate iotag. did=0x%x", did);
4096 
4097                 return (FC_TRAN_BUSY);
4098         }
4099 
4100         if (emlxs_bde_setup(port, sbp)) {
4101                 /* Unregister the packet */
4102                 (void) emlxs_unregister_pkt(cp, iotag, 0);
4103 
4104                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_trans_msg,
4105                     "Adapter Busy. Unable to setup buffer list. did=%x", did);
4106 
4107                 return (FC_TRAN_BUSY);
4108         }
4109 
4110         /* Point of no return */
4111 
4112         /* Initalize iocbq */
4113         iocbq->port = (void *) port;
4114         iocbq->channel = (void *) cp;
4115 
4116         /* Fill in rest of iocb */
4117         iocb->un.genreq64.w5.hcsw.Fctl = LA;
4118 
4119         if (pkt->pkt_cmd_fhdr.f_ctl & F_CTL_LAST_SEQ) {
4120                 iocb->un.genreq64.w5.hcsw.Fctl |= LSEQ;
4121         }
4122         if (pkt->pkt_cmd_fhdr.f_ctl & F_CTL_SEQ_INITIATIVE) {
4123                 iocb->un.genreq64.w5.hcsw.Fctl |= SI;
4124         }
4125 
4126         /* Initalize iocb */
4127         if (pkt->pkt_tran_type == FC_PKT_OUTBOUND) {
4128                 /* CT Response */
4129                 iocb->ULPCOMMAND = CMD_XMIT_SEQUENCE64_CX;
4130                 iocb->un.genreq64.w5.hcsw.Dfctl  = pkt->pkt_cmd_fhdr.df_ctl;
4131                 iocb->ULPCONTEXT  = pkt->pkt_cmd_fhdr.rx_id;
4132         } else {
4133                 /* CT Request */
4134                 iocb->ULPCOMMAND  = CMD_GEN_REQUEST64_CR;
4135                 iocb->un.genreq64.w5.hcsw.Dfctl = 0;
4136                 iocb->ULPCONTEXT  = ndlp->nlp_Rpi;
4137         }
4138 
4139         iocb->un.genreq64.w5.hcsw.Rctl  = pkt->pkt_cmd_fhdr.r_ctl;
4140         iocb->un.genreq64.w5.hcsw.Type  = pkt->pkt_cmd_fhdr.type;
4141 
4142         iocb->ULPIOTAG    = iotag;
4143         iocb->ULPRSVDBYTE =
4144             ((pkt->pkt_timeout > 0xff) ? 0 : pkt->pkt_timeout);
4145         iocb->ULPOWNER    = OWN_CHIP;
4146 
4147         switch (FC_TRAN_CLASS(pkt->pkt_tran_flags)) {
4148         case FC_TRAN_CLASS1:
4149                 iocb->ULPCLASS = CLASS1;
4150                 break;
4151         case FC_TRAN_CLASS2:
4152                 iocb->ULPCLASS = CLASS2;
4153                 break;
4154         case FC_TRAN_CLASS3:
4155         default:
4156                 iocb->ULPCLASS = CLASS3;
4157                 break;
4158         }
4159 
4160         return (FC_SUCCESS);
4161 
4162 } /* emlxs_sli3_prep_ct_iocb() */
4163 
4164 
4165 #ifdef SFCT_SUPPORT
4166 static uint32_t
4167 emlxs_fct_bde_setup(emlxs_port_t *port, emlxs_buf_t *sbp)
4168 {
4169         emlxs_hba_t *hba = HBA;
4170         uint32_t rval;
4171 
4172         if (sbp->fct_buf->db_sglist_length != 1) {
4173                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_error_msg,
4174                     "fct_bde_setup: Only 1 sglist entry supported: %d",
4175                     sbp->fct_buf->db_sglist_length);
4176                 return (1);
4177         }
4178 
4179         if (hba->sli_mode < EMLXS_HBA_SLI3_MODE) {
4180                 rval = emlxs_sli2_fct_bde_setup(port, sbp);
4181         } else {
4182                 rval = emlxs_sli3_fct_bde_setup(port, sbp);
4183         }
4184 
4185         return (rval);
4186 
4187 } /* emlxs_fct_bde_setup() */
4188 #endif /* SFCT_SUPPORT */
4189 
4190 
4191 static uint32_t
4192 emlxs_bde_setup(emlxs_port_t *port, emlxs_buf_t *sbp)
4193 {
4194         uint32_t        rval;
4195         emlxs_hba_t     *hba = HBA;
4196 
4197         if (hba->sli_mode < EMLXS_HBA_SLI3_MODE) {
4198                 rval = emlxs_sli2_bde_setup(port, sbp);
4199         } else {
4200                 rval = emlxs_sli3_bde_setup(port, sbp);
4201         }
4202 
4203         return (rval);
4204 
4205 } /* emlxs_bde_setup() */
4206 
4207 
4208 static void
4209 emlxs_sli3_poll_intr(emlxs_hba_t *hba)
4210 {
4211         uint32_t ha_copy;
4212 
4213         /* Check attention bits once and process if required */
4214 
4215         ha_copy = emlxs_check_attention(hba);
4216 
4217         if (ha_copy == 0) {
4218                 return;
4219         }
4220 
4221         mutex_enter(&EMLXS_PORT_LOCK);
4222         ha_copy = emlxs_get_attention(hba, -1);
4223         mutex_exit(&EMLXS_PORT_LOCK);
4224 
4225         emlxs_proc_attention(hba, ha_copy);
4226 
4227         return;
4228 
4229 } /* emlxs_sli3_poll_intr() */
4230 
4231 
4232 #ifdef MSI_SUPPORT
4233 static uint32_t
4234 emlxs_sli3_msi_intr(char *arg1, char *arg2)
4235 {
4236         emlxs_hba_t *hba = (emlxs_hba_t *)arg1;
4237 #ifdef FMA_SUPPORT
4238         emlxs_port_t *port = &PPORT;
4239 #endif  /* FMA_SUPPORT */
4240         uint16_t msgid;
4241         uint32_t hc_copy;
4242         uint32_t ha_copy;
4243         uint32_t restore = 0;
4244 
4245         /*
4246          * EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
4247          * "sli3_msi_intr: arg1=%p arg2=%p", arg1, arg2);
4248          */
4249 
4250         /* Check for legacy interrupt handling */
4251         if (hba->intr_type == DDI_INTR_TYPE_FIXED) {
4252                 mutex_enter(&EMLXS_PORT_LOCK);
4253 
4254                 if (hba->flag & FC_OFFLINE_MODE) {
4255                         mutex_exit(&EMLXS_PORT_LOCK);
4256 
4257                         if (hba->bus_type == SBUS_FC) {
4258                                 return (DDI_INTR_CLAIMED);
4259                         } else {
4260                                 return (DDI_INTR_UNCLAIMED);
4261                         }
4262                 }
4263 
4264                 /* Get host attention bits */
4265                 ha_copy = emlxs_get_attention(hba, -1);
4266 
4267                 if (ha_copy == 0) {
4268                         if (hba->intr_unclaimed) {
4269                                 mutex_exit(&EMLXS_PORT_LOCK);
4270                                 return (DDI_INTR_UNCLAIMED);
4271                         }
4272 
4273                         hba->intr_unclaimed = 1;
4274                 } else {
4275                         hba->intr_unclaimed = 0;
4276                 }
4277 
4278                 mutex_exit(&EMLXS_PORT_LOCK);
4279 
4280                 /* Process the interrupt */
4281                 emlxs_proc_attention(hba, ha_copy);
4282 
4283                 return (DDI_INTR_CLAIMED);
4284         }
4285 
4286         /* DDI_INTR_TYPE_MSI  */
4287         /* DDI_INTR_TYPE_MSIX */
4288 
4289         /* Get MSI message id */
4290         msgid = (uint16_t)((unsigned long)arg2);
4291 
4292         /* Validate the message id */
4293         if (msgid >= hba->intr_count) {
4294                 msgid = 0;
4295         }
4296 
4297         mutex_enter(&EMLXS_INTR_LOCK(msgid));
4298 
4299         mutex_enter(&EMLXS_PORT_LOCK);
4300 
4301         /* Check if adapter is offline */
4302         if (hba->flag & FC_OFFLINE_MODE) {
4303                 mutex_exit(&EMLXS_PORT_LOCK);
4304                 mutex_exit(&EMLXS_INTR_LOCK(msgid));
4305 
4306                 /* Always claim an MSI interrupt */
4307                 return (DDI_INTR_CLAIMED);
4308         }
4309 
4310         /* Disable interrupts associated with this msgid */
4311         if (msgid == 0 && (hba->model_info.chip == EMLXS_ZEPHYR_CHIP)) {
4312                 hc_copy = hba->sli.sli3.hc_copy & ~hba->intr_mask;
4313                 WRITE_CSR_REG(hba, FC_HC_REG(hba), hc_copy);
4314                 restore = 1;
4315         }
4316 
4317         /* Get host attention bits */
4318         ha_copy = emlxs_get_attention(hba, msgid);
4319 
4320         mutex_exit(&EMLXS_PORT_LOCK);
4321 
4322         /* Process the interrupt */
4323         emlxs_proc_attention(hba, ha_copy);
4324 
4325         /* Restore interrupts */
4326         if (restore) {
4327                 mutex_enter(&EMLXS_PORT_LOCK);
4328                 WRITE_CSR_REG(hba, FC_HC_REG(hba), hba->sli.sli3.hc_copy);
4329 #ifdef FMA_SUPPORT
4330                 /* Access handle validation */
4331                 EMLXS_CHK_ACC_HANDLE(hba, hba->sli.sli3.csr_acc_handle);
4332 #endif  /* FMA_SUPPORT */
4333                 mutex_exit(&EMLXS_PORT_LOCK);
4334         }
4335 
4336         mutex_exit(&EMLXS_INTR_LOCK(msgid));
4337 
4338         return (DDI_INTR_CLAIMED);
4339 
4340 } /* emlxs_sli3_msi_intr() */
4341 #endif /* MSI_SUPPORT */
4342 
4343 
4344 static int
4345 emlxs_sli3_intx_intr(char *arg)
4346 {
4347         emlxs_hba_t *hba = (emlxs_hba_t *)arg;
4348         uint32_t ha_copy = 0;
4349 
4350         mutex_enter(&EMLXS_PORT_LOCK);
4351 
4352         if (hba->flag & FC_OFFLINE_MODE) {
4353                 mutex_exit(&EMLXS_PORT_LOCK);
4354 
4355                 if (hba->bus_type == SBUS_FC) {
4356                         return (DDI_INTR_CLAIMED);
4357                 } else {
4358                         return (DDI_INTR_UNCLAIMED);
4359                 }
4360         }
4361 
4362         /* Get host attention bits */
4363         ha_copy = emlxs_get_attention(hba, -1);
4364 
4365         if (ha_copy == 0) {
4366                 if (hba->intr_unclaimed) {
4367                         mutex_exit(&EMLXS_PORT_LOCK);
4368                         return (DDI_INTR_UNCLAIMED);
4369                 }
4370 
4371                 hba->intr_unclaimed = 1;
4372         } else {
4373                 hba->intr_unclaimed = 0;
4374         }
4375 
4376         mutex_exit(&EMLXS_PORT_LOCK);
4377 
4378         /* Process the interrupt */
4379         emlxs_proc_attention(hba, ha_copy);
4380 
4381         return (DDI_INTR_CLAIMED);
4382 
4383 } /* emlxs_sli3_intx_intr() */
4384 
4385 
4386 /* EMLXS_PORT_LOCK must be held when call this routine */
4387 static uint32_t
4388 emlxs_get_attention(emlxs_hba_t *hba, int32_t msgid)
4389 {
4390 #ifdef FMA_SUPPORT
4391         emlxs_port_t *port = &PPORT;
4392 #endif  /* FMA_SUPPORT */
4393         uint32_t ha_copy = 0;
4394         uint32_t ha_copy2;
4395         uint32_t mask = hba->sli.sli3.hc_copy;
4396 
4397 #ifdef MSI_SUPPORT
4398 
4399 read_ha_register:
4400 
4401         /* Check for default MSI interrupt */
4402         if (msgid == 0) {
4403                 /* Read host attention register to determine interrupt source */
4404                 ha_copy2 = READ_CSR_REG(hba, FC_HA_REG(hba));
4405 
4406                 /* Filter out MSI non-default attention bits */
4407                 ha_copy2 &= ~(hba->intr_cond);
4408         }
4409 
4410         /* Check for polled or fixed type interrupt */
4411         else if (msgid == -1) {
4412                 /* Read host attention register to determine interrupt source */
4413                 ha_copy2 = READ_CSR_REG(hba, FC_HA_REG(hba));
4414         }
4415 
4416         /* Otherwise, assume a mapped MSI interrupt */
4417         else {
4418                 /* Convert MSI msgid to mapped attention bits */
4419                 ha_copy2 = hba->intr_map[msgid];
4420         }
4421 
4422 #else /* !MSI_SUPPORT */
4423 
4424         /* Read host attention register to determine interrupt source */
4425         ha_copy2 = READ_CSR_REG(hba, FC_HA_REG(hba));
4426 
4427 #endif /* MSI_SUPPORT */
4428 
4429         /* Check if Hardware error interrupt is enabled */
4430         if ((ha_copy2 & HA_ERATT) && !(mask & HC_ERINT_ENA)) {
4431                 ha_copy2 &= ~HA_ERATT;
4432         }
4433 
4434         /* Check if link interrupt is enabled */
4435         if ((ha_copy2 & HA_LATT) && !(mask & HC_LAINT_ENA)) {
4436                 ha_copy2 &= ~HA_LATT;
4437         }
4438 
4439         /* Check if Mailbox interrupt is enabled */
4440         if ((ha_copy2 & HA_MBATT) && !(mask & HC_MBINT_ENA)) {
4441                 ha_copy2 &= ~HA_MBATT;
4442         }
4443 
4444         /* Check if ring0 interrupt is enabled */
4445         if ((ha_copy2 & HA_R0ATT) && !(mask & HC_R0INT_ENA)) {
4446                 ha_copy2 &= ~HA_R0ATT;
4447         }
4448 
4449         /* Check if ring1 interrupt is enabled */
4450         if ((ha_copy2 & HA_R1ATT) && !(mask & HC_R1INT_ENA)) {
4451                 ha_copy2 &= ~HA_R1ATT;
4452         }
4453 
4454         /* Check if ring2 interrupt is enabled */
4455         if ((ha_copy2 & HA_R2ATT) && !(mask & HC_R2INT_ENA)) {
4456                 ha_copy2 &= ~HA_R2ATT;
4457         }
4458 
4459         /* Check if ring3 interrupt is enabled */
4460         if ((ha_copy2 & HA_R3ATT) && !(mask & HC_R3INT_ENA)) {
4461                 ha_copy2 &= ~HA_R3ATT;
4462         }
4463 
4464         /* Accumulate attention bits */
4465         ha_copy |= ha_copy2;
4466 
4467         /* Clear attentions except for error, link, and autoclear(MSIX) */
4468         ha_copy2 &= ~(HA_ERATT | HA_LATT);  /* | hba->intr_autoClear */
4469 
4470         if (ha_copy2) {
4471                 WRITE_CSR_REG(hba, FC_HA_REG(hba), ha_copy2);
4472         }
4473 
4474 #ifdef FMA_SUPPORT
4475         /* Access handle validation */
4476         EMLXS_CHK_ACC_HANDLE(hba, hba->sli.sli3.csr_acc_handle);
4477 #endif  /* FMA_SUPPORT */
4478 
4479         return (ha_copy);
4480 
4481 } /* emlxs_get_attention() */
4482 
4483 
4484 static void
4485 emlxs_proc_attention(emlxs_hba_t *hba, uint32_t ha_copy)
4486 {
4487 #ifdef FMA_SUPPORT
4488         emlxs_port_t *port = &PPORT;
4489 #endif  /* FMA_SUPPORT */
4490 
4491         /* ha_copy should be pre-filtered */
4492 
4493         /*
4494          * EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
4495          * "proc_attention: ha_copy=%x", ha_copy);
4496          */
4497 
4498         if (hba->state < FC_WARM_START) {
4499                 return;
4500         }
4501 
4502         if (!ha_copy) {
4503                 return;
4504         }
4505 
4506         if (hba->bus_type == SBUS_FC) {
4507                 (void) READ_SBUS_CSR_REG(hba, FC_SHS_REG(hba));
4508         }
4509 
4510         /* Adapter error */
4511         if (ha_copy & HA_ERATT) {
4512                 HBASTATS.IntrEvent[6]++;
4513                 emlxs_handle_ff_error(hba);
4514                 return;
4515         }
4516 
4517         /* Mailbox interrupt */
4518         if (ha_copy & HA_MBATT) {
4519                 HBASTATS.IntrEvent[5]++;
4520                 (void) emlxs_handle_mb_event(hba);
4521         }
4522 
4523         /* Link Attention interrupt */
4524         if (ha_copy & HA_LATT) {
4525                 HBASTATS.IntrEvent[4]++;
4526                 emlxs_sli3_handle_link_event(hba);
4527         }
4528 
4529         /* event on ring 0 - FCP Ring */
4530         if (ha_copy & HA_R0ATT) {
4531                 HBASTATS.IntrEvent[0]++;
4532                 emlxs_sli3_handle_ring_event(hba, 0, ha_copy);
4533         }
4534 
4535         /* event on ring 1 - IP Ring */
4536         if (ha_copy & HA_R1ATT) {
4537                 HBASTATS.IntrEvent[1]++;
4538                 emlxs_sli3_handle_ring_event(hba, 1, ha_copy);
4539         }
4540 
4541         /* event on ring 2 - ELS Ring */
4542         if (ha_copy & HA_R2ATT) {
4543                 HBASTATS.IntrEvent[2]++;
4544                 emlxs_sli3_handle_ring_event(hba, 2, ha_copy);
4545         }
4546 
4547         /* event on ring 3 - CT Ring */
4548         if (ha_copy & HA_R3ATT) {
4549                 HBASTATS.IntrEvent[3]++;
4550                 emlxs_sli3_handle_ring_event(hba, 3, ha_copy);
4551         }
4552 
4553         if (hba->bus_type == SBUS_FC) {
4554                 WRITE_SBUS_CSR_REG(hba, FC_SHS_REG(hba), SBUS_STAT_IP);
4555         }
4556 
4557         /* Set heartbeat flag to show activity */
4558         hba->heartbeat_flag = 1;
4559 
4560 #ifdef FMA_SUPPORT
4561         if (hba->bus_type == SBUS_FC) {
4562                 /* Access handle validation */
4563                 EMLXS_CHK_ACC_HANDLE(hba, hba->sli.sli3.sbus_csr_handle);
4564         }
4565 #endif  /* FMA_SUPPORT */
4566 
4567         return;
4568 
4569 } /* emlxs_proc_attention() */
4570 
4571 
4572 /*
4573  * emlxs_handle_ff_error()
4574  *
4575  *    Description: Processes a FireFly error
4576  *    Runs at Interrupt level
4577  */
4578 static void
4579 emlxs_handle_ff_error(emlxs_hba_t *hba)
4580 {
4581         emlxs_port_t *port = &PPORT;
4582         uint32_t status;
4583         uint32_t status1;
4584         uint32_t status2;
4585         int i = 0;
4586 
4587         /* do what needs to be done, get error from STATUS REGISTER */
4588         status = READ_CSR_REG(hba, FC_HS_REG(hba));
4589 
4590         /* Clear Chip error bit */
4591         WRITE_CSR_REG(hba, FC_HA_REG(hba), HA_ERATT);
4592 
4593         /* If HS_FFER1 is set, then wait until the HS_FFER1 bit clears */
4594         if (status & HS_FFER1) {
4595 
4596                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_hardware_error_msg,
4597                     "HS_FFER1 received");
4598                 EMLXS_STATE_CHANGE(hba, FC_ERROR);
4599                 (void) emlxs_offline(hba, 1);
4600                 while ((status & HS_FFER1) && (i < 300)) {
4601                         status =
4602                             READ_CSR_REG(hba, FC_HS_REG(hba));
4603                         BUSYWAIT_MS(1000);
4604                         i++;
4605                 }
4606         }
4607 
4608         if (i == 300) {
4609                 /* 5 minutes is up, shutdown HBA */
4610                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_hardware_error_msg,
4611                     "HS_FFER1 clear timeout");
4612 
4613                 EMLXS_STATE_CHANGE(hba, FC_ERROR);
4614                 emlxs_thread_spawn(hba, emlxs_shutdown_thread, NULL, NULL);
4615 
4616                 goto done;
4617         }
4618 
4619         EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_hardware_error_msg,
4620             "HS_FFER1 cleared");
4621 
4622         if (status & HS_OVERTEMP) {
4623                 status1 =
4624                     READ_SLIM_ADDR(hba,
4625                     ((volatile uint8_t *)hba->sli.sli3.slim_addr + 0xb0));
4626 
4627                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_hardware_error_msg,
4628                     "Maximum adapter temperature exceeded (%d °C).", status1);
4629 
4630                 hba->temperature = status1;
4631                 hba->flag |= FC_OVERTEMP_EVENT;
4632 
4633                 EMLXS_STATE_CHANGE(hba, FC_ERROR);
4634                 emlxs_thread_spawn(hba, emlxs_shutdown_thread,
4635                     NULL, NULL);
4636 
4637         } else {
4638                 status1 =
4639                     READ_SLIM_ADDR(hba,
4640                     ((volatile uint8_t *)hba->sli.sli3.slim_addr + 0xa8));
4641                 status2 =
4642                     READ_SLIM_ADDR(hba,
4643                     ((volatile uint8_t *)hba->sli.sli3.slim_addr + 0xac));
4644 
4645                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_hardware_error_msg,
4646                     "Host Error Attention: "
4647                     "status=0x%x status1=0x%x status2=0x%x",
4648                     status, status1, status2);
4649 
4650                 EMLXS_STATE_CHANGE(hba, FC_ERROR);
4651 
4652                 if (status & HS_FFER6) {
4653                         emlxs_thread_spawn(hba, emlxs_restart_thread,
4654                             NULL, NULL);
4655                 } else {
4656                         emlxs_thread_spawn(hba, emlxs_shutdown_thread,
4657                             NULL, NULL);
4658                 }
4659         }
4660 
4661 done:
4662 #ifdef FMA_SUPPORT
4663         /* Access handle validation */
4664         EMLXS_CHK_ACC_HANDLE(hba, hba->sli.sli3.slim_acc_handle);
4665         EMLXS_CHK_ACC_HANDLE(hba, hba->sli.sli3.csr_acc_handle);
4666 #endif  /* FMA_SUPPORT */
4667 
4668         return;
4669 
4670 } /* emlxs_handle_ff_error() */
4671 
4672 
4673 /*
4674  *  emlxs_sli3_handle_link_event()
4675  *
4676  *    Description: Process a Link Attention.
4677  */
4678 static void
4679 emlxs_sli3_handle_link_event(emlxs_hba_t *hba)
4680 {
4681         emlxs_port_t *port = &PPORT;
4682         MAILBOXQ *mbq;
4683         int rc;
4684 
4685         HBASTATS.LinkEvent++;
4686 
4687         EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_link_event_msg, "event=%x",
4688             HBASTATS.LinkEvent);
4689 
4690         /* Make sure link is declared down */
4691         emlxs_linkdown(hba);
4692 
4693         /* Get a buffer which will be used for mailbox commands */
4694         if ((mbq = (MAILBOXQ *)emlxs_mem_get(hba, MEM_MBOX))) {
4695                 /* Get link attention message */
4696                 if (emlxs_mb_read_la(hba, mbq) == 0) {
4697                         rc =  emlxs_sli3_issue_mbox_cmd(hba, mbq,
4698                             MBX_NOWAIT, 0);
4699                         if ((rc != MBX_BUSY) && (rc != MBX_SUCCESS)) {
4700                                 emlxs_mem_put(hba, MEM_MBOX,
4701                                     (void *)mbq);
4702                         }
4703 
4704                         mutex_enter(&EMLXS_PORT_LOCK);
4705 
4706                         /*
4707                          * Clear Link Attention in HA REG
4708                          */
4709                         WRITE_CSR_REG(hba, FC_HA_REG(hba), HA_LATT);
4710 
4711 #ifdef FMA_SUPPORT
4712                         /* Access handle validation */
4713                         EMLXS_CHK_ACC_HANDLE(hba, hba->sli.sli3.csr_acc_handle);
4714 #endif  /* FMA_SUPPORT */
4715 
4716                         mutex_exit(&EMLXS_PORT_LOCK);
4717                 } else {
4718                         emlxs_mem_put(hba, MEM_MBOX, (void *)mbq);
4719                 }
4720         }
4721 
4722 } /* emlxs_sli3_handle_link_event()  */
4723 
4724 
4725 /*
4726  *  emlxs_sli3_handle_ring_event()
4727  *
4728  *    Description: Process a Ring Attention.
4729  */
4730 static void
4731 emlxs_sli3_handle_ring_event(emlxs_hba_t *hba, int32_t ring_no,
4732     uint32_t ha_copy)
4733 {
4734         emlxs_port_t *port = &PPORT;
4735         SLIM2 *slim2p = (SLIM2 *)hba->sli.sli3.slim2.virt;
4736         CHANNEL *cp;
4737         RING *rp;
4738         IOCB *entry;
4739         IOCBQ *iocbq;
4740         IOCBQ local_iocbq;
4741         PGP *pgp;
4742         uint32_t count;
4743         volatile uint32_t chipatt;
4744         void *ioa2;
4745         uint32_t reg;
4746         uint32_t channel_no;
4747         off_t offset;
4748         IOCBQ *rsp_head = NULL;
4749         IOCBQ *rsp_tail = NULL;
4750         emlxs_buf_t *sbp = NULL;
4751 
4752         count = 0;
4753         rp = &hba->sli.sli3.ring[ring_no];
4754         cp = rp->channelp;
4755         channel_no = cp->channelno;
4756 
4757         /*
4758          * Isolate this ring's host attention bits
4759          * This makes all ring attention bits equal
4760          * to Ring0 attention bits
4761          */
4762         reg = (ha_copy >> (ring_no * 4)) & 0x0f;
4763 
4764         /*
4765          * Gather iocb entries off response ring.
4766          * Ensure entry is owned by the host.
4767          */
4768         pgp = (PGP *)&slim2p->mbx.us.s2.port[ring_no];
4769         offset =
4770             (off_t)((uint64_t)((unsigned long)&(pgp->rspPutInx)) -
4771             (uint64_t)((unsigned long)slim2p));
4772         EMLXS_MPDATA_SYNC(hba->sli.sli3.slim2.dma_handle, offset, 4,
4773             DDI_DMA_SYNC_FORKERNEL);
4774         rp->fc_port_rspidx = BE_SWAP32(pgp->rspPutInx);
4775 
4776         /* While ring is not empty */
4777         while (rp->fc_rspidx != rp->fc_port_rspidx) {
4778                 HBASTATS.IocbReceived[channel_no]++;
4779 
4780                 /* Get the next response ring iocb */
4781                 entry =
4782                     (IOCB *)(((char *)rp->fc_rspringaddr +
4783                     (rp->fc_rspidx * hba->sli.sli3.iocb_rsp_size)));
4784 
4785                 /* DMA sync the response ring iocb for the adapter */
4786                 offset = (off_t)((uint64_t)((unsigned long)entry)
4787                     - (uint64_t)((unsigned long)slim2p));
4788                 EMLXS_MPDATA_SYNC(hba->sli.sli3.slim2.dma_handle, offset,
4789                     hba->sli.sli3.iocb_rsp_size, DDI_DMA_SYNC_FORKERNEL);
4790 
4791                 count++;
4792 
4793                 /* Copy word6 and word7 to local iocb for now */
4794                 iocbq = &local_iocbq;
4795 
4796                 BE_SWAP32_BCOPY((uint8_t *)entry + (sizeof (uint32_t) * 6),
4797                     (uint8_t *)iocbq + (sizeof (uint32_t) * 6),
4798                     (sizeof (uint32_t) * 2));
4799 
4800                 /* when LE is not set, entire Command has not been received */
4801                 if (!iocbq->iocb.ULPLE) {
4802                         /* This should never happen */
4803                         EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_ring_error_msg,
4804                             "ulpLE is not set. "
4805                             "ring=%d iotag=%d cmd=%x status=%x",
4806                             channel_no, iocbq->iocb.ULPIOTAG,
4807                             iocbq->iocb.ULPCOMMAND, iocbq->iocb.ULPSTATUS);
4808 
4809                         goto next;
4810                 }
4811 
4812                 sbp = NULL;
4813                 switch (iocbq->iocb.ULPCOMMAND) {
4814 #ifdef SFCT_SUPPORT
4815                 case CMD_CLOSE_XRI_CX:
4816                 case CMD_CLOSE_XRI_CN:
4817                 case CMD_ABORT_XRI_CX:
4818                         if (port->mode == MODE_TARGET) {
4819                                 sbp = emlxs_unregister_pkt(cp,
4820                                     iocbq->iocb.ULPIOTAG, 0);
4821                         }
4822                         break;
4823 #endif /* SFCT_SUPPORT */
4824 
4825                         /* Ring 0 registered commands */
4826                 case CMD_FCP_ICMND_CR:
4827                 case CMD_FCP_ICMND_CX:
4828                 case CMD_FCP_IREAD_CR:
4829                 case CMD_FCP_IREAD_CX:
4830                 case CMD_FCP_IWRITE_CR:
4831                 case CMD_FCP_IWRITE_CX:
4832                 case CMD_FCP_ICMND64_CR:
4833                 case CMD_FCP_ICMND64_CX:
4834                 case CMD_FCP_IREAD64_CR:
4835                 case CMD_FCP_IREAD64_CX:
4836                 case CMD_FCP_IWRITE64_CR:
4837                 case CMD_FCP_IWRITE64_CX:
4838 #ifdef SFCT_SUPPORT
4839                 case CMD_FCP_TSEND_CX:
4840                 case CMD_FCP_TSEND64_CX:
4841                 case CMD_FCP_TRECEIVE_CX:
4842                 case CMD_FCP_TRECEIVE64_CX:
4843                 case CMD_FCP_TRSP_CX:
4844                 case CMD_FCP_TRSP64_CX:
4845 #endif /* SFCT_SUPPORT */
4846 
4847                         /* Ring 1 registered commands */
4848                 case CMD_XMIT_BCAST_CN:
4849                 case CMD_XMIT_BCAST_CX:
4850                 case CMD_XMIT_SEQUENCE_CX:
4851                 case CMD_XMIT_SEQUENCE_CR:
4852                 case CMD_XMIT_BCAST64_CN:
4853                 case CMD_XMIT_BCAST64_CX:
4854                 case CMD_XMIT_SEQUENCE64_CX:
4855                 case CMD_XMIT_SEQUENCE64_CR:
4856                 case CMD_CREATE_XRI_CR:
4857                 case CMD_CREATE_XRI_CX:
4858 
4859                         /* Ring 2 registered commands */
4860                 case CMD_ELS_REQUEST_CR:
4861                 case CMD_ELS_REQUEST_CX:
4862                 case CMD_XMIT_ELS_RSP_CX:
4863                 case CMD_ELS_REQUEST64_CR:
4864                 case CMD_ELS_REQUEST64_CX:
4865                 case CMD_XMIT_ELS_RSP64_CX:
4866 
4867                         /* Ring 3 registered commands */
4868                 case CMD_GEN_REQUEST64_CR:
4869                 case CMD_GEN_REQUEST64_CX:
4870 
4871                         sbp =
4872                             emlxs_unregister_pkt(cp, iocbq->iocb.ULPIOTAG, 0);
4873                         break;
4874                 }
4875 
4876                 /* If packet is stale, then drop it. */
4877                 if (sbp == STALE_PACKET) {
4878                         cp->hbaCmplCmd_sbp++;
4879                         /* Copy entry to the local iocbq */
4880                         BE_SWAP32_BCOPY((uint8_t *)entry,
4881                             (uint8_t *)iocbq, hba->sli.sli3.iocb_rsp_size);
4882 
4883                         EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_iocb_stale_msg,
4884                             "channelno=%d iocb=%p cmd=%x status=%x "
4885                             "error=%x iotag=%d context=%x info=%x",
4886                             channel_no, iocbq, (uint8_t)iocbq->iocb.ULPCOMMAND,
4887                             iocbq->iocb.ULPSTATUS,
4888                             (uint8_t)iocbq->iocb.un.grsp.perr.statLocalError,
4889                             (uint16_t)iocbq->iocb.ULPIOTAG,
4890                             (uint16_t)iocbq->iocb.ULPCONTEXT,
4891                             (uint8_t)iocbq->iocb.ULPRSVDBYTE);
4892 
4893                         goto next;
4894                 }
4895 
4896                 /*
4897                  * If a packet was found, then queue the packet's
4898                  * iocb for deferred processing
4899                  */
4900                 else if (sbp) {
4901 #ifdef SFCT_SUPPORT
4902                         fct_cmd_t *fct_cmd;
4903                         emlxs_buf_t *cmd_sbp;
4904 
4905                         fct_cmd = sbp->fct_cmd;
4906                         if (fct_cmd) {
4907                                 cmd_sbp =
4908                                     (emlxs_buf_t *)fct_cmd->cmd_fca_private;
4909                                 mutex_enter(&cmd_sbp->fct_mtx);
4910                                 EMLXS_FCT_STATE_CHG(fct_cmd, cmd_sbp,
4911                                     EMLXS_FCT_IOCB_COMPLETE);
4912                                 mutex_exit(&cmd_sbp->fct_mtx);
4913                         }
4914 #endif /* SFCT_SUPPORT */
4915                         cp->hbaCmplCmd_sbp++;
4916                         atomic_dec_32(&hba->io_active);
4917 #ifdef NODE_THROTTLE_SUPPORT
4918                         if (sbp->node) {
4919                                 atomic_dec_32(&sbp->node->io_active);
4920                         }
4921 #endif /* NODE_THROTTLE_SUPPORT */
4922 
4923                         /* Copy entry to sbp's iocbq */
4924                         iocbq = &sbp->iocbq;
4925                         BE_SWAP32_BCOPY((uint8_t *)entry,
4926                             (uint8_t *)iocbq, hba->sli.sli3.iocb_rsp_size);
4927 
4928                         iocbq->next = NULL;
4929 
4930                         /*
4931                          * If this is NOT a polled command completion
4932                          * or a driver allocated pkt, then defer pkt
4933                          * completion.
4934                          */
4935                         if (!(sbp->pkt_flags &
4936                             (PACKET_POLLED | PACKET_ALLOCATED))) {
4937                                 /* Add the IOCB to the local list */
4938                                 if (!rsp_head) {
4939                                         rsp_head = iocbq;
4940                                 } else {
4941                                         rsp_tail->next = iocbq;
4942                                 }
4943 
4944                                 rsp_tail = iocbq;
4945 
4946                                 goto next;
4947                         }
4948                 } else {
4949                         cp->hbaCmplCmd++;
4950                         /* Copy entry to the local iocbq */
4951                         BE_SWAP32_BCOPY((uint8_t *)entry,
4952                             (uint8_t *)iocbq, hba->sli.sli3.iocb_rsp_size);
4953 
4954                         iocbq->next = NULL;
4955                         iocbq->bp = NULL;
4956                         iocbq->port = &PPORT;
4957                         iocbq->channel = cp;
4958                         iocbq->node = NULL;
4959                         iocbq->sbp = NULL;
4960                         iocbq->flag = 0;
4961                 }
4962 
4963                 /* process the channel event now */
4964                 emlxs_proc_channel_event(hba, cp, iocbq);
4965 
4966 next:
4967                 /* Increment the driver's local response get index */
4968                 if (++rp->fc_rspidx >= rp->fc_numRiocb) {
4969                         rp->fc_rspidx = 0;
4970                 }
4971 
4972         }       /* while (TRUE) */
4973 
4974         if (rsp_head) {
4975                 mutex_enter(&cp->rsp_lock);
4976                 if (cp->rsp_head == NULL) {
4977                         cp->rsp_head = rsp_head;
4978                         cp->rsp_tail = rsp_tail;
4979                 } else {
4980                         cp->rsp_tail->next = rsp_head;
4981                         cp->rsp_tail = rsp_tail;
4982                 }
4983                 mutex_exit(&cp->rsp_lock);
4984 
4985                 emlxs_thread_trigger2(&cp->intr_thread, emlxs_proc_channel, cp);
4986         }
4987 
4988         /* Check if at least one response entry was processed */
4989         if (count) {
4990                 /* Update response get index for the adapter */
4991                 if (hba->bus_type == SBUS_FC) {
4992                         slim2p->mbx.us.s2.host[channel_no].rspGetInx
4993                             = BE_SWAP32(rp->fc_rspidx);
4994 
4995                         /* DMA sync the index for the adapter */
4996                         offset = (off_t)
4997                             ((uint64_t)((unsigned long)&(slim2p->mbx.us.s2.
4998                             host[channel_no].rspGetInx))
4999                             - (uint64_t)((unsigned long)slim2p));
5000                         EMLXS_MPDATA_SYNC(hba->sli.sli3.slim2.dma_handle,
5001                             offset, 4, DDI_DMA_SYNC_FORDEV);
5002                 } else {
5003                         ioa2 =
5004                             (void *)((char *)hba->sli.sli3.slim_addr +
5005                             hba->sli.sli3.hgp_ring_offset + (((channel_no * 2) +
5006                             1) * sizeof (uint32_t)));
5007                         WRITE_SLIM_ADDR(hba, (volatile uint32_t *)ioa2,
5008                             rp->fc_rspidx);
5009 #ifdef FMA_SUPPORT
5010                         /* Access handle validation */
5011                         EMLXS_CHK_ACC_HANDLE(hba,
5012                             hba->sli.sli3.slim_acc_handle);
5013 #endif  /* FMA_SUPPORT */
5014                 }
5015 
5016                 if (reg & HA_R0RE_REQ) {
5017                         /* HBASTATS.chipRingFree++; */
5018 
5019                         mutex_enter(&EMLXS_PORT_LOCK);
5020 
5021                         /* Tell the adapter we serviced the ring */
5022                         chipatt = ((CA_R0ATT | CA_R0RE_RSP) <<
5023                             (channel_no * 4));
5024                         WRITE_CSR_REG(hba, FC_CA_REG(hba), chipatt);
5025 
5026 #ifdef FMA_SUPPORT
5027                         /* Access handle validation */
5028                         EMLXS_CHK_ACC_HANDLE(hba, hba->sli.sli3.csr_acc_handle);
5029 #endif  /* FMA_SUPPORT */
5030 
5031                         mutex_exit(&EMLXS_PORT_LOCK);
5032                 }
5033         }
5034 
5035         if ((reg & HA_R0CE_RSP) || hba->channel_tx_count) {
5036                 /* HBASTATS.hostRingFree++; */
5037 
5038                 /* Cmd ring may be available. Try sending more iocbs */
5039                 emlxs_sli3_issue_iocb_cmd(hba, cp, 0);
5040         }
5041 
5042         /* HBASTATS.ringEvent++; */
5043 
5044         return;
5045 
5046 } /* emlxs_sli3_handle_ring_event() */
5047 
5048 
5049 extern int
5050 emlxs_handle_rcv_seq(emlxs_hba_t *hba, CHANNEL *cp, IOCBQ *iocbq)
5051 {
5052         emlxs_port_t *port = &PPORT;
5053         IOCB *iocb;
5054         RING *rp;
5055         MATCHMAP *mp = NULL;
5056         uint64_t bdeAddr;
5057         uint32_t vpi = 0;
5058         uint32_t channelno;
5059         uint32_t size = 0;
5060         uint32_t *RcvError;
5061         uint32_t *RcvDropped;
5062         uint32_t *UbPosted;
5063         emlxs_msg_t *dropped_msg;
5064         char error_str[64];
5065         uint32_t buf_type;
5066         uint32_t *word;
5067 
5068         channelno = cp->channelno;
5069         rp = &hba->sli.sli3.ring[channelno];
5070 
5071         iocb = &iocbq->iocb;
5072         word = (uint32_t *)iocb;
5073 
5074         switch (channelno) {
5075 #ifdef SFCT_SUPPORT
5076         case FC_FCT_RING:
5077                 HBASTATS.FctRingEvent++;
5078                 RcvError = &HBASTATS.FctRingError;
5079                 RcvDropped = &HBASTATS.FctRingDropped;
5080                 UbPosted = &HBASTATS.FctUbPosted;
5081                 dropped_msg = &emlxs_fct_detail_msg;
5082                 buf_type = MEM_FCTBUF;
5083                 break;
5084 #endif /* SFCT_SUPPORT */
5085 
5086         case FC_IP_RING:
5087                 HBASTATS.IpRcvEvent++;
5088                 RcvError = &HBASTATS.IpDropped;
5089                 RcvDropped = &HBASTATS.IpDropped;
5090                 UbPosted = &HBASTATS.IpUbPosted;
5091                 dropped_msg = &emlxs_unsol_ip_dropped_msg;
5092                 buf_type = MEM_IPBUF;
5093                 break;
5094 
5095         case FC_ELS_RING:
5096                 HBASTATS.ElsRcvEvent++;
5097                 RcvError = &HBASTATS.ElsRcvError;
5098                 RcvDropped = &HBASTATS.ElsRcvDropped;
5099                 UbPosted = &HBASTATS.ElsUbPosted;
5100                 dropped_msg = &emlxs_unsol_els_dropped_msg;
5101                 buf_type = MEM_ELSBUF;
5102                 break;
5103 
5104         case FC_CT_RING:
5105                 HBASTATS.CtRcvEvent++;
5106                 RcvError = &HBASTATS.CtRcvError;
5107                 RcvDropped = &HBASTATS.CtRcvDropped;
5108                 UbPosted = &HBASTATS.CtUbPosted;
5109                 dropped_msg = &emlxs_unsol_ct_dropped_msg;
5110                 buf_type = MEM_CTBUF;
5111                 break;
5112 
5113         default:
5114                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_iocb_invalid_msg,
5115                     "channel=%d cmd=%x  %s %x %x %x %x",
5116                     channelno, iocb->ULPCOMMAND,
5117                     emlxs_state_xlate(iocb->ULPSTATUS), word[4], word[5],
5118                     word[6], word[7]);
5119                 return (1);
5120         }
5121 
5122         if (iocb->ULPSTATUS) {
5123                 if ((iocb->ULPSTATUS == IOSTAT_LOCAL_REJECT) &&
5124                     (iocb->un.grsp.perr.statLocalError ==
5125                     IOERR_RCV_BUFFER_TIMEOUT)) {
5126                         (void) strlcpy(error_str, "Out of posted buffers:",
5127                             sizeof (error_str));
5128                         iocb->ULPBDECOUNT = 0;
5129                 } else if ((iocb->ULPSTATUS == IOSTAT_LOCAL_REJECT) &&
5130                     (iocb->un.grsp.perr.statLocalError ==
5131                     IOERR_RCV_BUFFER_WAITING)) {
5132                         (void) strlcpy(error_str, "Buffer waiting:",
5133                             sizeof (error_str));
5134                         iocb->ULPBDECOUNT = 0;
5135                         goto done;
5136                 } else if (iocb->ULPSTATUS == IOSTAT_NEED_BUFF_ENTRY) {
5137                         (void) strlcpy(error_str, "Need Buffer Entry:",
5138                             sizeof (error_str));
5139                         iocb->ULPBDECOUNT = 0;
5140                         goto done;
5141                 } else {
5142                         (void) strlcpy(error_str, "General error:",
5143                             sizeof (error_str));
5144                 }
5145 
5146                 goto failed;
5147         }
5148 
5149         if (hba->flag & FC_HBQ_ENABLED) {
5150                 HBQ_INIT_t *hbq;
5151                 HBQE_t *hbqE;
5152                 uint32_t hbqe_tag;
5153                 uint32_t hbq_id;
5154 
5155                 (*UbPosted)--;
5156 
5157                 hbqE = (HBQE_t *)iocb;
5158                 hbq_id = hbqE->unt.ext.HBQ_tag;
5159                 hbqe_tag = hbqE->unt.ext.HBQE_tag;
5160 
5161                 hbq = &hba->sli.sli3.hbq_table[hbq_id];
5162 
5163                 if (hbqe_tag >= hbq->HBQ_numEntries) {
5164                         (void) snprintf(error_str, sizeof (error_str),
5165                             "Invalid HBQE iotag=%d:", hbqe_tag);
5166                         goto dropped;
5167                 }
5168 
5169                 mp = hba->sli.sli3.hbq_table[hbq_id].HBQ_PostBufs[hbqe_tag];
5170 
5171                 size = iocb->unsli3.ext_rcv.seq_len;
5172         } else {
5173                 bdeAddr =
5174                     PADDR(iocb->un.cont64[0].addrHigh,
5175                     iocb->un.cont64[0].addrLow);
5176 
5177                 /* Check for invalid buffer */
5178                 if (iocb->un.cont64[0].tus.f.bdeFlags & BUFF_TYPE_INVALID) {
5179                         (void) strlcpy(error_str, "Invalid buffer:",
5180                             sizeof (error_str));
5181                         goto dropped;
5182                 }
5183 
5184                 mp = emlxs_mem_get_vaddr(hba, rp, bdeAddr);
5185 
5186                 size = iocb->un.rcvseq64.rcvBde.tus.f.bdeSize;
5187         }
5188 
5189         if (!mp) {
5190                 (void) strlcpy(error_str, "Buffer not mapped:",
5191                     sizeof (error_str));
5192                 goto dropped;
5193         }
5194 
5195 #ifdef FMA_SUPPORT
5196         if (mp->dma_handle) {
5197                 if (emlxs_fm_check_dma_handle(hba, mp->dma_handle)
5198                     != DDI_FM_OK) {
5199                         EMLXS_MSGF(EMLXS_CONTEXT,
5200                             &emlxs_invalid_dma_handle_msg,
5201                             "handle_rcv_seq: hdl=%p",
5202                             mp->dma_handle);
5203                         goto dropped;
5204                 }
5205         }
5206 #endif  /* FMA_SUPPORT */
5207 
5208         if (!size) {
5209                 (void) strlcpy(error_str, "Buffer empty:", sizeof (error_str));
5210                 goto dropped;
5211         }
5212 
5213         /* To avoid we drop the broadcast packets */
5214         if (channelno != FC_IP_RING) {
5215                 /* Get virtual port */
5216                 if (hba->flag & FC_NPIV_ENABLED) {
5217                         vpi = iocb->unsli3.ext_rcv.vpi;
5218                         if (vpi >= hba->vpi_max) {
5219                                 (void) snprintf(error_str, sizeof (error_str),
5220                                 "Invalid VPI=%d:", vpi);
5221                                 goto dropped;
5222                         }
5223 
5224                         port = &VPORT(vpi);
5225                 }
5226         }
5227 
5228         /* Process request */
5229         switch (channelno) {
5230         case FC_FCT_RING:
5231                 if (port->mode == MODE_INITIATOR) {
5232                         (void) strlcpy(error_str, "Target mode disabled:",
5233                             sizeof (error_str));
5234                         goto dropped;
5235 #ifdef SFCT_SUPPORT
5236                 } else if (port->mode == MODE_TARGET) {
5237                         (void) emlxs_fct_handle_unsol_req(port, cp, iocbq, mp,
5238                             size);
5239 #endif /* SFCT_SUPPORT */
5240                 } else {
5241                         (void) snprintf(error_str, sizeof (error_str),
5242                             "Invalid mode=%x:", port->mode);
5243                         goto dropped;
5244                 }
5245                 break;
5246 
5247         case FC_IP_RING:
5248                 if (port->mode == MODE_INITIATOR) {
5249                         (void) emlxs_ip_handle_unsol_req(port, cp, iocbq,
5250                             mp, size);
5251 #ifdef SFCT_SUPPORT
5252                 } else if (port->mode == MODE_TARGET) {
5253                         (void) strlcpy(error_str, "Initiator mode disabled:",
5254                             sizeof (error_str));
5255                         goto dropped;
5256 #endif /* SFCT_SUPPORT */
5257                 } else {
5258                         (void) snprintf(error_str, sizeof (error_str),
5259                             "Invalid mode=%x:", port->mode);
5260                         goto dropped;
5261                 }
5262                 break;
5263 
5264         case FC_ELS_RING:
5265                 if (port->mode == MODE_INITIATOR) {
5266                         (void) emlxs_els_handle_unsol_req(port, cp, iocbq, mp,
5267                             size);
5268 #ifdef SFCT_SUPPORT
5269                 } else if (port->mode == MODE_TARGET) {
5270                         (void) emlxs_fct_handle_unsol_els(port, cp, iocbq, mp,
5271                             size);
5272 #endif /* SFCT_SUPPORT */
5273                 } else {
5274                         (void) snprintf(error_str, sizeof (error_str),
5275                             "Invalid mode=%x:", port->mode);
5276                         goto dropped;
5277                 }
5278                 break;
5279 
5280         case FC_CT_RING:
5281                 (void) emlxs_ct_handle_unsol_req(port, cp, iocbq, mp, size);
5282                 break;
5283         }
5284 
5285         goto done;
5286 
5287 dropped:
5288         (*RcvDropped)++;
5289 
5290         EMLXS_MSGF(EMLXS_CONTEXT, dropped_msg,
5291             "%s: cmd=%x  %s %x %x %x %x",
5292             error_str, iocb->ULPCOMMAND, emlxs_state_xlate(iocb->ULPSTATUS),
5293             word[4], word[5], word[6], word[7]);
5294 
5295         if (channelno == FC_FCT_RING) {
5296                 uint32_t sid;
5297 
5298                 if (hba->sli_mode == EMLXS_HBA_SLI3_MODE) {
5299                         emlxs_node_t *ndlp;
5300                         ndlp = emlxs_node_find_rpi(port, iocb->ULPIOTAG);
5301                         if (! ndlp) {
5302                                 goto done;
5303                         }
5304                         sid = ndlp->nlp_DID;
5305                 } else {
5306                         sid = iocb->un.ulpWord[4] & 0xFFFFFF;
5307                 }
5308 
5309                 emlxs_send_logo(port, sid);
5310         }
5311 
5312         goto done;
5313 
5314 failed:
5315         (*RcvError)++;
5316 
5317         EMLXS_MSGF(EMLXS_CONTEXT, dropped_msg,
5318             "%s: cmd=%x %s  %x %x %x %x  hba:%x %x",
5319             error_str, iocb->ULPCOMMAND, emlxs_state_xlate(iocb->ULPSTATUS),
5320             word[4], word[5], word[6], word[7], hba->state, hba->flag);
5321 
5322 done:
5323 
5324         if (hba->flag & FC_HBQ_ENABLED) {
5325                 if (iocb->ULPBDECOUNT) {
5326                         HBQE_t *hbqE;
5327                         uint32_t hbq_id;
5328 
5329                         hbqE = (HBQE_t *)iocb;
5330                         hbq_id = hbqE->unt.ext.HBQ_tag;
5331 
5332                         emlxs_update_HBQ_index(hba, hbq_id);
5333                 }
5334         } else {
5335                 if (mp) {
5336                         emlxs_mem_put(hba, buf_type, (void *)mp);
5337                 }
5338 
5339                 if (iocb->ULPBDECOUNT) {
5340                         (void) emlxs_post_buffer(hba, rp, 1);
5341                 }
5342         }
5343 
5344         return (0);
5345 
5346 } /* emlxs_handle_rcv_seq() */
5347 
5348 
5349 /* EMLXS_CMD_RING_LOCK must be held when calling this function */
5350 static void
5351 emlxs_sli3_issue_iocb(emlxs_hba_t *hba, RING *rp, IOCBQ *iocbq)
5352 {
5353         emlxs_port_t *port;
5354         IOCB *icmd;
5355         IOCB *iocb;
5356         emlxs_buf_t *sbp;
5357         off_t offset;
5358         uint32_t ringno;
5359 
5360         ringno = rp->ringno;
5361         sbp = iocbq->sbp;
5362         icmd = &iocbq->iocb;
5363         port = iocbq->port;
5364 
5365         HBASTATS.IocbIssued[ringno]++;
5366 
5367         /* Check for ULP pkt request */
5368         if (sbp) {
5369                 mutex_enter(&sbp->mtx);
5370 
5371                 if (sbp->node == NULL) {
5372                         /* Set node to base node by default */
5373                         iocbq->node = (void *)&port->node_base;
5374                         sbp->node = (void *)&port->node_base;
5375                 }
5376 
5377                 sbp->pkt_flags |= PACKET_IN_CHIPQ;
5378                 mutex_exit(&sbp->mtx);
5379 
5380                 atomic_inc_32(&hba->io_active);
5381 #ifdef NODE_THROTTLE_SUPPORT
5382                 if (sbp->node) {
5383                         atomic_inc_32(&sbp->node->io_active);
5384                 }
5385 #endif /* NODE_THROTTLE_SUPPORT */
5386 
5387 #ifdef SFCT_SUPPORT
5388 #ifdef FCT_IO_TRACE
5389                 if (sbp->fct_cmd) {
5390                         emlxs_fct_io_trace(port, sbp->fct_cmd,
5391                             EMLXS_FCT_IOCB_ISSUED);
5392                         emlxs_fct_io_trace(port, sbp->fct_cmd,
5393                             icmd->ULPCOMMAND);
5394                 }
5395 #endif /* FCT_IO_TRACE */
5396 #endif /* SFCT_SUPPORT */
5397 
5398                 rp->channelp->hbaSendCmd_sbp++;
5399                 iocbq->channel = rp->channelp;
5400         } else {
5401                 rp->channelp->hbaSendCmd++;
5402         }
5403 
5404         /* get the next available command ring iocb */
5405         iocb =
5406             (IOCB *)(((char *)rp->fc_cmdringaddr +
5407             (rp->fc_cmdidx * hba->sli.sli3.iocb_cmd_size)));
5408 
5409         /* Copy the local iocb to the command ring iocb */
5410         BE_SWAP32_BCOPY((uint8_t *)icmd, (uint8_t *)iocb,
5411             hba->sli.sli3.iocb_cmd_size);
5412 
5413         /* DMA sync the command ring iocb for the adapter */
5414         offset = (off_t)((uint64_t)((unsigned long)iocb)
5415             - (uint64_t)((unsigned long)hba->sli.sli3.slim2.virt));
5416         EMLXS_MPDATA_SYNC(hba->sli.sli3.slim2.dma_handle, offset,
5417             hba->sli.sli3.iocb_cmd_size, DDI_DMA_SYNC_FORDEV);
5418 
5419         /*
5420          * After this, the sbp / iocb should not be
5421          * accessed in the xmit path.
5422          */
5423 
5424         /* Free the local iocb if there is no sbp tracking it */
5425         if (!sbp) {
5426                 emlxs_mem_put(hba, MEM_IOCB, (void *)iocbq);
5427         }
5428 
5429         /* update local ring index to next available ring index */
5430         rp->fc_cmdidx =
5431             (rp->fc_cmdidx + 1 >= rp->fc_numCiocb) ? 0 : rp->fc_cmdidx + 1;
5432 
5433 
5434         return;
5435 
5436 } /* emlxs_sli3_issue_iocb() */
5437 
5438 
5439 static void
5440 emlxs_sli3_hba_kill(emlxs_hba_t *hba)
5441 {
5442         emlxs_port_t *port = &PPORT;
5443         MAILBOX *swpmb;
5444         MAILBOX *mb2;
5445         MAILBOX *mb1;
5446         uint32_t word0;
5447         uint32_t j;
5448         uint32_t interlock_failed;
5449         uint32_t ha_copy;
5450         uint32_t value;
5451         off_t offset;
5452         uint32_t size;
5453 
5454         /* Perform adapter interlock to kill adapter */
5455         interlock_failed = 0;
5456 
5457         mutex_enter(&EMLXS_PORT_LOCK);
5458         if (hba->flag & FC_INTERLOCKED) {
5459                 EMLXS_STATE_CHANGE_LOCKED(hba, FC_KILLED);
5460 
5461                 mutex_exit(&EMLXS_PORT_LOCK);
5462 
5463                 return;
5464         }
5465 
5466         j = 0;
5467         while (j++ < 10000) {
5468                 if (hba->mbox_queue_flag == 0) {
5469                         break;
5470                 }
5471 
5472                 mutex_exit(&EMLXS_PORT_LOCK);
5473                 BUSYWAIT_US(100);
5474                 mutex_enter(&EMLXS_PORT_LOCK);
5475         }
5476 
5477         if (hba->mbox_queue_flag != 0) {
5478                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
5479                     "Interlock failed. Mailbox busy.");
5480                 mutex_exit(&EMLXS_PORT_LOCK);
5481                 return;
5482         }
5483 
5484         hba->flag |= FC_INTERLOCKED;
5485         hba->mbox_queue_flag = 1;
5486 
5487         /* Disable all host interrupts */
5488         hba->sli.sli3.hc_copy = 0;
5489         WRITE_CSR_REG(hba, FC_HC_REG(hba), hba->sli.sli3.hc_copy);
5490         WRITE_CSR_REG(hba, FC_HA_REG(hba), 0xffffffff);
5491 
5492         mb2 = FC_SLIM2_MAILBOX(hba);
5493         mb1 = FC_SLIM1_MAILBOX(hba);
5494         swpmb = (MAILBOX *)&word0;
5495 
5496         if (!(hba->flag & FC_SLIM2_MODE)) {
5497                 goto mode_B;
5498         }
5499 
5500 mode_A:
5501 
5502         EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
5503             "Attempting SLIM2 Interlock...");
5504 
5505 interlock_A:
5506 
5507         value = 0x55555555;
5508         word0 = 0;
5509         swpmb->mbxCommand = MBX_KILL_BOARD;
5510         swpmb->mbxOwner = OWN_CHIP;
5511 
5512         /* Write value to SLIM */
5513         WRITE_SLIM_ADDR(hba, (((volatile uint32_t *)mb1) + 1), value);
5514         WRITE_SLIM_ADDR(hba, (((volatile uint32_t *)mb1)), word0);
5515 
5516         /* Send Kill board request */
5517         mb2->un.varWords[0] = value;
5518         mb2->mbxCommand = MBX_KILL_BOARD;
5519         mb2->mbxOwner = OWN_CHIP;
5520 
5521         /* Sync the memory */
5522         offset = (off_t)((uint64_t)((unsigned long)mb2)
5523             - (uint64_t)((unsigned long)hba->sli.sli3.slim2.virt));
5524         size = (sizeof (uint32_t) * 2);
5525 
5526         BE_SWAP32_BCOPY((uint8_t *)mb2, (uint8_t *)mb2, size);
5527 
5528         EMLXS_MPDATA_SYNC(hba->sli.sli3.slim2.dma_handle, offset, size,
5529             DDI_DMA_SYNC_FORDEV);
5530 
5531         /* interrupt board to do it right away */
5532         WRITE_CSR_REG(hba, FC_CA_REG(hba), CA_MBATT);
5533 
5534         /* First wait for command acceptence */
5535         j = 0;
5536         while (j++ < 1000) {
5537                 value = READ_SLIM_ADDR(hba, (((volatile uint32_t *)mb1) + 1));
5538 
5539                 if (value == 0xAAAAAAAA) {
5540                         break;
5541                 }
5542 
5543                 BUSYWAIT_US(50);
5544         }
5545 
5546         if (value == 0xAAAAAAAA) {
5547                 /* Now wait for mailbox ownership to clear */
5548                 while (j++ < 10000) {
5549                         word0 =
5550                             READ_SLIM_ADDR(hba, ((volatile uint32_t *)mb1));
5551 
5552                         if (swpmb->mbxOwner == 0) {
5553                                 break;
5554                         }
5555 
5556                         BUSYWAIT_US(50);
5557                 }
5558 
5559                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
5560                     "Interlock succeeded.");
5561 
5562                 goto done;
5563         }
5564 
5565         /* Interlock failed !!! */
5566         interlock_failed = 1;
5567 
5568         EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg, "Interlock failed.");
5569 
5570 mode_B:
5571 
5572         EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
5573             "Attempting SLIM1 Interlock...");
5574 
5575 interlock_B:
5576 
5577         value = 0x55555555;
5578         word0 = 0;
5579         swpmb->mbxCommand = MBX_KILL_BOARD;
5580         swpmb->mbxOwner = OWN_CHIP;
5581 
5582         /* Write KILL BOARD to mailbox */
5583         WRITE_SLIM_ADDR(hba, (((volatile uint32_t *)mb1) + 1), value);
5584         WRITE_SLIM_ADDR(hba, ((volatile uint32_t *)mb1), word0);
5585 
5586         /* interrupt board to do it right away */
5587         WRITE_CSR_REG(hba, FC_CA_REG(hba), CA_MBATT);
5588 
5589         /* First wait for command acceptence */
5590         j = 0;
5591         while (j++ < 1000) {
5592                 value = READ_SLIM_ADDR(hba, (((volatile uint32_t *)mb1) + 1));
5593 
5594                 if (value == 0xAAAAAAAA) {
5595                         break;
5596                 }
5597 
5598                 BUSYWAIT_US(50);
5599         }
5600 
5601         if (value == 0xAAAAAAAA) {
5602                 /* Now wait for mailbox ownership to clear */
5603                 while (j++ < 10000) {
5604                         word0 =
5605                             READ_SLIM_ADDR(hba, ((volatile uint32_t *)mb1));
5606 
5607                         if (swpmb->mbxOwner == 0) {
5608                                 break;
5609                         }
5610 
5611                         BUSYWAIT_US(50);
5612                 }
5613 
5614                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
5615                     "Interlock succeeded.");
5616 
5617                 goto done;
5618         }
5619 
5620         /* Interlock failed !!! */
5621 
5622         /* If this is the first time then try again */
5623         if (interlock_failed == 0) {
5624                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
5625                     "Interlock failed. Retrying...");
5626 
5627                 /* Try again */
5628                 interlock_failed = 1;
5629                 goto interlock_B;
5630         }
5631 
5632         /*
5633          * Now check for error attention to indicate the board has
5634          * been kiilled
5635          */
5636         j = 0;
5637         while (j++ < 10000) {
5638                 ha_copy = READ_CSR_REG(hba, FC_HA_REG(hba));
5639 
5640                 if (ha_copy & HA_ERATT) {
5641                         break;
5642                 }
5643 
5644                 BUSYWAIT_US(50);
5645         }
5646 
5647         if (ha_copy & HA_ERATT) {
5648                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
5649                     "Interlock failed. Board killed.");
5650         } else {
5651                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
5652                     "Interlock failed. Board not killed.");
5653         }
5654 
5655 done:
5656 
5657         hba->mbox_queue_flag = 0;
5658 
5659         EMLXS_STATE_CHANGE_LOCKED(hba, FC_KILLED);
5660 
5661 #ifdef FMA_SUPPORT
5662         /* Access handle validation */
5663         EMLXS_CHK_ACC_HANDLE(hba, hba->sli.sli3.slim_acc_handle);
5664         EMLXS_CHK_ACC_HANDLE(hba, hba->sli.sli3.csr_acc_handle);
5665 #endif  /* FMA_SUPPORT */
5666 
5667         mutex_exit(&EMLXS_PORT_LOCK);
5668 
5669         return;
5670 
5671 } /* emlxs_sli3_hba_kill() */
5672 
5673 
5674 static void
5675 emlxs_sli3_hba_kill4quiesce(emlxs_hba_t *hba)
5676 {
5677         emlxs_port_t *port = &PPORT;
5678         MAILBOX *swpmb;
5679         MAILBOX *mb2;
5680         MAILBOX *mb1;
5681         uint32_t word0;
5682         off_t offset;
5683         uint32_t j;
5684         uint32_t value;
5685         uint32_t size;
5686 
5687         /* Disable all host interrupts */
5688         hba->sli.sli3.hc_copy = 0;
5689         WRITE_CSR_REG(hba, FC_HC_REG(hba), hba->sli.sli3.hc_copy);
5690         WRITE_CSR_REG(hba, FC_HA_REG(hba), 0xffffffff);
5691 
5692         mb2 = FC_SLIM2_MAILBOX(hba);
5693         mb1 = FC_SLIM1_MAILBOX(hba);
5694         swpmb = (MAILBOX *)&word0;
5695 
5696         value = 0x55555555;
5697         word0 = 0;
5698         swpmb->mbxCommand = MBX_KILL_BOARD;
5699         swpmb->mbxOwner = OWN_CHIP;
5700 
5701         /* Write value to SLIM */
5702         WRITE_SLIM_ADDR(hba, (((volatile uint32_t *)mb1) + 1), value);
5703         WRITE_SLIM_ADDR(hba, (((volatile uint32_t *)mb1)), word0);
5704 
5705         /* Send Kill board request */
5706         mb2->un.varWords[0] = value;
5707         mb2->mbxCommand = MBX_KILL_BOARD;
5708         mb2->mbxOwner = OWN_CHIP;
5709 
5710         /* Sync the memory */
5711         offset = (off_t)((uint64_t)((unsigned long)mb2)
5712             - (uint64_t)((unsigned long)hba->sli.sli3.slim2.virt));
5713         size = (sizeof (uint32_t) * 2);
5714 
5715         BE_SWAP32_BCOPY((uint8_t *)mb2, (uint8_t *)mb2, size);
5716 
5717         EMLXS_MPDATA_SYNC(hba->sli.sli3.slim2.dma_handle, offset, size,
5718             DDI_DMA_SYNC_FORDEV);
5719 
5720         /* interrupt board to do it right away */
5721         WRITE_CSR_REG(hba, FC_CA_REG(hba), CA_MBATT);
5722 
5723         /* First wait for command acceptence */
5724         j = 0;
5725         while (j++ < 1000) {
5726                 value = READ_SLIM_ADDR(hba, (((volatile uint32_t *)mb1) + 1));
5727 
5728                 if (value == 0xAAAAAAAA) {
5729                         break;
5730                 }
5731                 BUSYWAIT_US(50);
5732         }
5733         if (value == 0xAAAAAAAA) {
5734                 /* Now wait for mailbox ownership to clear */
5735                 while (j++ < 10000) {
5736                         word0 =
5737                             READ_SLIM_ADDR(hba, ((volatile uint32_t *)mb1));
5738                         if (swpmb->mbxOwner == 0) {
5739                                 break;
5740                         }
5741                         BUSYWAIT_US(50);
5742                 }
5743                 goto done;
5744         }
5745 
5746 done:
5747         EMLXS_STATE_CHANGE_LOCKED(hba, FC_KILLED);
5748 
5749 #ifdef FMA_SUPPORT
5750         /* Access handle validation */
5751         EMLXS_CHK_ACC_HANDLE(hba, hba->sli.sli3.slim_acc_handle);
5752         EMLXS_CHK_ACC_HANDLE(hba, hba->sli.sli3.csr_acc_handle);
5753 #endif  /* FMA_SUPPORT */
5754         return;
5755 
5756 } /* emlxs_sli3_hba_kill4quiesce */
5757 
5758 
5759 
5760 
5761 /*
5762  * emlxs_handle_mb_event
5763  *
5764  * Description: Process a Mailbox Attention.
5765  * Called from host_interrupt to process MBATT
5766  *
5767  *   Returns:
5768  *
5769  */
5770 static uint32_t
5771 emlxs_handle_mb_event(emlxs_hba_t *hba)
5772 {
5773         emlxs_port_t            *port = &PPORT;
5774         MAILBOX                 *mb;
5775         MAILBOX                 *swpmb;
5776         MAILBOX                 *mbox;
5777         MAILBOXQ                *mbq = NULL;
5778         volatile uint32_t       word0;
5779         MATCHMAP                *mbox_bp;
5780         off_t                   offset;
5781         uint32_t                i;
5782         int                     rc;
5783 
5784         swpmb = (MAILBOX *)&word0;
5785 
5786         mutex_enter(&EMLXS_PORT_LOCK);
5787         switch (hba->mbox_queue_flag) {
5788         case 0:
5789                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_stray_mbox_intr_msg,
5790                     "No mailbox active.");
5791 
5792                 mutex_exit(&EMLXS_PORT_LOCK);
5793                 return (0);
5794 
5795         case MBX_POLL:
5796 
5797                 /* Mark mailbox complete, this should wake up any polling */
5798                 /* threads. This can happen if interrupts are enabled while */
5799                 /* a polled mailbox command is outstanding. If we don't set */
5800                 /* MBQ_COMPLETED here, the polling thread may wait until */
5801                 /* timeout error occurs */
5802 
5803                 mutex_enter(&EMLXS_MBOX_LOCK);
5804                 mbq = (MAILBOXQ *)hba->mbox_mbq;
5805                 if (mbq) {
5806                         port = (emlxs_port_t *)mbq->port;
5807                         EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mbox_detail_msg,
5808                             "Mailbox event. Completing Polled command.");
5809                         mbq->flag |= MBQ_COMPLETED;
5810                 }
5811                 mutex_exit(&EMLXS_MBOX_LOCK);
5812 
5813                 mutex_exit(&EMLXS_PORT_LOCK);
5814                 return (0);
5815 
5816         case MBX_SLEEP:
5817         case MBX_NOWAIT:
5818                 /* Check mbox_timer, it acts as a service flag too */
5819                 /* The first to service the mbox queue will clear the timer */
5820                 if (hba->mbox_timer) {
5821                         hba->mbox_timer = 0;
5822 
5823                         mutex_enter(&EMLXS_MBOX_LOCK);
5824                         mbq = (MAILBOXQ *)hba->mbox_mbq;
5825                         mutex_exit(&EMLXS_MBOX_LOCK);
5826                 }
5827 
5828                 if (!mbq) {
5829                         EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mbox_detail_msg,
5830                             "Mailbox event. No service required.");
5831                         mutex_exit(&EMLXS_PORT_LOCK);
5832                         return (0);
5833                 }
5834 
5835                 mb = (MAILBOX *)mbq;
5836                 mutex_exit(&EMLXS_PORT_LOCK);
5837                 break;
5838 
5839         default:
5840                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mbox_completion_error_msg,
5841                     "Invalid Mailbox flag (%x).");
5842 
5843                 mutex_exit(&EMLXS_PORT_LOCK);
5844                 return (0);
5845         }
5846 
5847         /* Set port context */
5848         port = (emlxs_port_t *)mbq->port;
5849 
5850         /* Get first word of mailbox */
5851         if (hba->flag & FC_SLIM2_MODE) {
5852                 mbox = FC_SLIM2_MAILBOX(hba);
5853                 offset = (off_t)((uint64_t)((unsigned long)mbox)
5854                     - (uint64_t)((unsigned long)hba->sli.sli3.slim2.virt));
5855 
5856                 EMLXS_MPDATA_SYNC(hba->sli.sli3.slim2.dma_handle, offset,
5857                     sizeof (uint32_t), DDI_DMA_SYNC_FORKERNEL);
5858                 word0 = *((volatile uint32_t *)mbox);
5859                 word0 = BE_SWAP32(word0);
5860         } else {
5861                 mbox = FC_SLIM1_MAILBOX(hba);
5862                 word0 = READ_SLIM_ADDR(hba, ((volatile uint32_t *)mbox));
5863         }
5864 
5865         i = 0;
5866         while (swpmb->mbxOwner == OWN_CHIP) {
5867                 if (i++ > 10000) {
5868                         EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_stray_mbox_intr_msg,
5869                             "OWN_CHIP: %s: status=%x",
5870                             emlxs_mb_cmd_xlate(swpmb->mbxCommand),
5871                             swpmb->mbxStatus);
5872 
5873                         return (1);
5874                 }
5875 
5876                 /* Get first word of mailbox */
5877                 if (hba->flag & FC_SLIM2_MODE) {
5878                         EMLXS_MPDATA_SYNC(hba->sli.sli3.slim2.dma_handle,
5879                             offset, sizeof (uint32_t), DDI_DMA_SYNC_FORKERNEL);
5880                         word0 = *((volatile uint32_t *)mbox);
5881                         word0 = BE_SWAP32(word0);
5882                 } else {
5883                         word0 =
5884                             READ_SLIM_ADDR(hba, ((volatile uint32_t *)mbox));
5885                 }
5886         }
5887 
5888         /* Now that we are the owner, DMA Sync entire mailbox if needed */
5889         if (hba->flag & FC_SLIM2_MODE) {
5890                 EMLXS_MPDATA_SYNC(hba->sli.sli3.slim2.dma_handle, offset,
5891                     MAILBOX_CMD_BSIZE, DDI_DMA_SYNC_FORKERNEL);
5892 
5893                 BE_SWAP32_BCOPY((uint8_t *)mbox, (uint8_t *)mb,
5894                     MAILBOX_CMD_BSIZE);
5895         } else {
5896                 READ_SLIM_COPY(hba, (uint32_t *)mb, (uint32_t *)mbox,
5897                     MAILBOX_CMD_WSIZE);
5898         }
5899 
5900 #ifdef MBOX_EXT_SUPPORT
5901         if (mbq->extbuf) {
5902                 uint32_t *mbox_ext =
5903                     (uint32_t *)((uint8_t *)mbox + MBOX_EXTENSION_OFFSET);
5904                 off_t offset_ext   = offset + MBOX_EXTENSION_OFFSET;
5905 
5906                 if (hba->flag & FC_SLIM2_MODE) {
5907                         EMLXS_MPDATA_SYNC(hba->sli.sli3.slim2.dma_handle,
5908                             offset_ext, mbq->extsize,
5909                             DDI_DMA_SYNC_FORKERNEL);
5910                         BE_SWAP32_BCOPY((uint8_t *)mbox_ext,
5911                             (uint8_t *)mbq->extbuf, mbq->extsize);
5912                 } else {
5913                         READ_SLIM_COPY(hba, (uint32_t *)mbq->extbuf,
5914                             mbox_ext, (mbq->extsize / 4));
5915                 }
5916         }
5917 #endif /* MBOX_EXT_SUPPORT */
5918 
5919 #ifdef FMA_SUPPORT
5920         if (!(hba->flag & FC_SLIM2_MODE)) {
5921                 /* Access handle validation */
5922                 EMLXS_CHK_ACC_HANDLE(hba, hba->sli.sli3.slim_acc_handle);
5923         }
5924 #endif  /* FMA_SUPPORT */
5925 
5926         /* Now sync the memory buffer if one was used */
5927         if (mbq->bp) {
5928                 mbox_bp = (MATCHMAP *)mbq->bp;
5929                 EMLXS_MPDATA_SYNC(mbox_bp->dma_handle, 0, mbox_bp->size,
5930                     DDI_DMA_SYNC_FORKERNEL);
5931         }
5932 
5933         /* Mailbox has been completely received at this point */
5934 
5935         if (mb->mbxCommand == MBX_HEARTBEAT) {
5936                 hba->heartbeat_active = 0;
5937                 goto done;
5938         }
5939 
5940         if (hba->mbox_queue_flag == MBX_SLEEP) {
5941                 if (swpmb->mbxCommand != MBX_DOWN_LOAD &&
5942                     swpmb->mbxCommand != MBX_DUMP_MEMORY) {
5943                         EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mbox_detail_msg,
5944                             "Received.  %s: status=%x Sleep.",
5945                             emlxs_mb_cmd_xlate(swpmb->mbxCommand),
5946                             swpmb->mbxStatus);
5947                 }
5948         } else {
5949                 if (swpmb->mbxCommand != MBX_DOWN_LOAD &&
5950                     swpmb->mbxCommand != MBX_DUMP_MEMORY) {
5951                         EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mbox_detail_msg,
5952                             "Completed. %s: status=%x",
5953                             emlxs_mb_cmd_xlate(swpmb->mbxCommand),
5954                             swpmb->mbxStatus);
5955                 }
5956         }
5957 
5958         /* Filter out passthru mailbox */
5959         if (mbq->flag & MBQ_PASSTHRU) {
5960                 goto done;
5961         }
5962 
5963         if (mb->mbxStatus) {
5964                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mbox_detail_msg,
5965                     "%s: status=0x%x", emlxs_mb_cmd_xlate(mb->mbxCommand),
5966                     (uint32_t)mb->mbxStatus);
5967         }
5968 
5969         if (mbq->mbox_cmpl) {
5970                 rc = (mbq->mbox_cmpl)(hba, mbq);
5971                 /* If mbox was retried, return immediately */
5972                 if (rc) {
5973                         return (0);
5974                 }
5975         }
5976 
5977 done:
5978 
5979         /* Clean up the mailbox area */
5980         emlxs_mb_fini(hba, mb, mb->mbxStatus);
5981 
5982         mbq = (MAILBOXQ *)emlxs_mb_get(hba);
5983         if (mbq) {
5984                 /* Attempt to send pending mailboxes */
5985                 rc =  emlxs_sli3_issue_mbox_cmd(hba, mbq, MBX_NOWAIT, 0);
5986                 if ((rc != MBX_BUSY) && (rc != MBX_SUCCESS)) {
5987                         emlxs_mem_put(hba, MEM_MBOX, (void *)mbq);
5988                 }
5989         }
5990         return (0);
5991 
5992 } /* emlxs_handle_mb_event() */
5993 
5994 
5995 static void
5996 emlxs_sli3_timer(emlxs_hba_t *hba)
5997 {
5998         /* Perform SLI3 level timer checks */
5999 
6000         emlxs_sli3_timer_check_mbox(hba);
6001 
6002 } /* emlxs_sli3_timer() */
6003 
6004 
6005 static void
6006 emlxs_sli3_timer_check_mbox(emlxs_hba_t *hba)
6007 {
6008         emlxs_port_t *port = &PPORT;
6009         emlxs_config_t *cfg = &CFG;
6010         MAILBOX *mb = NULL;
6011         uint32_t word0;
6012         uint32_t offset;
6013         uint32_t ha_copy = 0;
6014 
6015         if (!cfg[CFG_TIMEOUT_ENABLE].current) {
6016                 return;
6017         }
6018 
6019         mutex_enter(&EMLXS_PORT_LOCK);
6020 
6021         /* Return if timer hasn't expired */
6022         if (!hba->mbox_timer || (hba->timer_tics < hba->mbox_timer)) {
6023                 mutex_exit(&EMLXS_PORT_LOCK);
6024                 return;
6025         }
6026 
6027         /* Mailbox timed out, first check for error attention */
6028         ha_copy = emlxs_check_attention(hba);
6029 
6030         if (ha_copy & HA_ERATT) {
6031                 hba->mbox_timer = 0;
6032                 mutex_exit(&EMLXS_PORT_LOCK);
6033                 emlxs_handle_ff_error(hba);
6034                 return;
6035         }
6036 
6037         if (hba->mbox_queue_flag) {
6038                 /* Get first word of mailbox */
6039                 if (hba->flag & FC_SLIM2_MODE) {
6040                         mb = FC_SLIM2_MAILBOX(hba);
6041                         offset =
6042                             (off_t)((uint64_t)((unsigned long)mb) - (uint64_t)
6043                             ((unsigned long)hba->sli.sli3.slim2.virt));
6044 
6045                         EMLXS_MPDATA_SYNC(hba->sli.sli3.slim2.dma_handle,
6046                             offset, sizeof (uint32_t), DDI_DMA_SYNC_FORKERNEL);
6047                         word0 = *((volatile uint32_t *)mb);
6048                         word0 = BE_SWAP32(word0);
6049                 } else {
6050                         mb = FC_SLIM1_MAILBOX(hba);
6051                         word0 =
6052                             READ_SLIM_ADDR(hba, ((volatile uint32_t *)mb));
6053 #ifdef FMA_SUPPORT
6054                         /* Access handle validation */
6055                         EMLXS_CHK_ACC_HANDLE(hba,
6056                             hba->sli.sli3.slim_acc_handle);
6057 #endif  /* FMA_SUPPORT */
6058                 }
6059 
6060                 mb = (MAILBOX *)&word0;
6061 
6062                 /* Check if mailbox has actually completed */
6063                 if (mb->mbxOwner == OWN_HOST) {
6064                         /* Read host attention register to determine */
6065                         /* interrupt source */
6066                         uint32_t ha_copy = emlxs_check_attention(hba);
6067 
6068                         EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mbox_detail_msg,
6069                             "Mailbox attention missed: %s. Forcing event. "
6070                             "hc=%x ha=%x", emlxs_mb_cmd_xlate(mb->mbxCommand),
6071                             hba->sli.sli3.hc_copy, ha_copy);
6072 
6073                         mutex_exit(&EMLXS_PORT_LOCK);
6074 
6075                         (void) emlxs_handle_mb_event(hba);
6076 
6077                         return;
6078                 }
6079 
6080                 /* The first to service the mbox queue will clear the timer */
6081                 /* We will service the mailbox here */
6082                 hba->mbox_timer = 0;
6083 
6084                 mutex_enter(&EMLXS_MBOX_LOCK);
6085                 mb = (MAILBOX *)hba->mbox_mbq;
6086                 mutex_exit(&EMLXS_MBOX_LOCK);
6087         }
6088 
6089         if (mb) {
6090                 switch (hba->mbox_queue_flag) {
6091                 case MBX_NOWAIT:
6092                         EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mbox_timeout_msg,
6093                             "%s: Nowait.",
6094                             emlxs_mb_cmd_xlate(mb->mbxCommand));
6095                         break;
6096 
6097                 case MBX_SLEEP:
6098                         EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mbox_timeout_msg,
6099                             "%s: mb=%p Sleep.",
6100                             emlxs_mb_cmd_xlate(mb->mbxCommand),
6101                             mb);
6102                         break;
6103 
6104                 case MBX_POLL:
6105                         EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mbox_timeout_msg,
6106                             "%s: mb=%p Polled.",
6107                             emlxs_mb_cmd_xlate(mb->mbxCommand),
6108                             mb);
6109                         break;
6110 
6111                 default:
6112                         EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mbox_timeout_msg,
6113                             "%s: mb=%p (%d).",
6114                             emlxs_mb_cmd_xlate(mb->mbxCommand),
6115                             mb, hba->mbox_queue_flag);
6116                         break;
6117                 }
6118         } else {
6119                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mbox_timeout_msg, NULL);
6120         }
6121 
6122         hba->flag |= FC_MBOX_TIMEOUT;
6123         EMLXS_STATE_CHANGE_LOCKED(hba, FC_ERROR);
6124 
6125         mutex_exit(&EMLXS_PORT_LOCK);
6126 
6127         /* Perform mailbox cleanup */
6128         /* This will wake any sleeping or polling threads */
6129         emlxs_mb_fini(hba, NULL, MBX_TIMEOUT);
6130 
6131         /* Trigger adapter shutdown */
6132         emlxs_thread_spawn(hba, emlxs_shutdown_thread, NULL, NULL);
6133 
6134         return;
6135 
6136 } /* emlxs_sli3_timer_check_mbox() */
6137 
6138 
6139 /*
6140  * emlxs_mb_config_port  Issue a CONFIG_PORT mailbox command
6141  */
6142 static uint32_t
6143 emlxs_mb_config_port(emlxs_hba_t *hba, MAILBOXQ *mbq, uint32_t sli_mode,
6144     uint32_t hbainit)
6145 {
6146         MAILBOX         *mb = (MAILBOX *)mbq;
6147         emlxs_vpd_t     *vpd = &VPD;
6148         emlxs_port_t    *port = &PPORT;
6149         emlxs_config_t  *cfg;
6150         RING            *rp;
6151         uint64_t        pcb;
6152         uint64_t        mbx;
6153         uint64_t        hgp;
6154         uint64_t        pgp;
6155         uint64_t        rgp;
6156         MAILBOX         *mbox;
6157         SLIM2           *slim;
6158         SLI2_RDSC       *rdsc;
6159         uint64_t        offset;
6160         uint32_t        Laddr;
6161         uint32_t        i;
6162 
6163         cfg = &CFG;
6164         bzero((void *)mb, MAILBOX_CMD_BSIZE);
6165         mbox = NULL;
6166         slim = NULL;
6167 
6168         mb->mbxCommand = MBX_CONFIG_PORT;
6169         mb->mbxOwner = OWN_HOST;
6170         mbq->mbox_cmpl = NULL;
6171 
6172         mb->un.varCfgPort.pcbLen = sizeof (PCB);
6173         mb->un.varCfgPort.hbainit[0] = hbainit;
6174 
6175         pcb = hba->sli.sli3.slim2.phys +
6176             (uint64_t)((unsigned long)&(slim->pcb));
6177         mb->un.varCfgPort.pcbLow = PADDR_LO(pcb);
6178         mb->un.varCfgPort.pcbHigh = PADDR_HI(pcb);
6179 
6180         /* Set Host pointers in SLIM flag */
6181         mb->un.varCfgPort.hps = 1;
6182 
6183         /* Initialize hba structure for assumed default SLI2 mode */
6184         /* If config port succeeds, then we will update it then   */
6185         hba->sli_mode = sli_mode;
6186         hba->vpi_max = 0;
6187         hba->flag &= ~FC_NPIV_ENABLED;
6188 
6189         if (sli_mode == EMLXS_HBA_SLI3_MODE) {
6190                 mb->un.varCfgPort.sli_mode = EMLXS_HBA_SLI3_MODE;
6191                 mb->un.varCfgPort.cerbm = 1;
6192                 mb->un.varCfgPort.max_hbq = EMLXS_NUM_HBQ;
6193 
6194                 if (cfg[CFG_NPIV_ENABLE].current) {
6195                         if (vpd->feaLevelHigh >= 0x09) {
6196                                 if (hba->model_info.chip >= EMLXS_SATURN_CHIP) {
6197                                         mb->un.varCfgPort.vpi_max =
6198                                             MAX_VPORTS - 1;
6199                                 } else {
6200                                         mb->un.varCfgPort.vpi_max =
6201                                             MAX_VPORTS_LIMITED - 1;
6202                                 }
6203 
6204                                 mb->un.varCfgPort.cmv = 1;
6205                         } else {
6206                                 EMLXS_MSGF(EMLXS_CONTEXT,
6207                                     &emlxs_init_debug_msg,
6208                                     "CFGPORT: Firmware does not support NPIV. "
6209                                     "level=%d", vpd->feaLevelHigh);
6210                         }
6211 
6212                 }
6213         }
6214 
6215         /*
6216          * Now setup pcb
6217          */
6218         ((SLIM2 *)hba->sli.sli3.slim2.virt)->pcb.type = TYPE_NATIVE_SLI2;
6219         ((SLIM2 *)hba->sli.sli3.slim2.virt)->pcb.feature = FEATURE_INITIAL_SLI2;
6220         ((SLIM2 *)hba->sli.sli3.slim2.virt)->pcb.maxRing =
6221             (hba->sli.sli3.ring_count - 1);
6222         ((SLIM2 *)hba->sli.sli3.slim2.virt)->pcb.mailBoxSize =
6223             sizeof (MAILBOX) + MBOX_EXTENSION_SIZE;
6224 
6225         mbx = hba->sli.sli3.slim2.phys +
6226             (uint64_t)((unsigned long)&(slim->mbx));
6227         ((SLIM2 *)hba->sli.sli3.slim2.virt)->pcb.mbAddrHigh = PADDR_HI(mbx);
6228         ((SLIM2 *)hba->sli.sli3.slim2.virt)->pcb.mbAddrLow = PADDR_LO(mbx);
6229 
6230 
6231         /*
6232          * Set up HGP - Port Memory
6233          *
6234          * CR0Put   - SLI2(no HBQs) =   0xc0, With HBQs =       0x80
6235          * RR0Get                       0xc4                    0x84
6236          * CR1Put                       0xc8                    0x88
6237          * RR1Get                       0xcc                    0x8c
6238          * CR2Put                       0xd0                    0x90
6239          * RR2Get                       0xd4                    0x94
6240          * CR3Put                       0xd8                    0x98
6241          * RR3Get                       0xdc                    0x9c
6242          *
6243          * Reserved                     0xa0-0xbf
6244          *
6245          * If HBQs configured:
6246          * HBQ 0 Put ptr  0xc0
6247          * HBQ 1 Put ptr  0xc4
6248          * HBQ 2 Put ptr  0xc8
6249          * ...
6250          * HBQ(M-1)Put Pointer 0xc0+(M-1)*4
6251          */
6252 
6253         if (sli_mode >= EMLXS_HBA_SLI3_MODE) {
6254                 /* ERBM is enabled */
6255                 hba->sli.sli3.hgp_ring_offset = 0x80;
6256                 hba->sli.sli3.hgp_hbq_offset = 0xC0;
6257 
6258                 hba->sli.sli3.iocb_cmd_size = SLI3_IOCB_CMD_SIZE;
6259                 hba->sli.sli3.iocb_rsp_size = SLI3_IOCB_RSP_SIZE;
6260 
6261         } else { /* SLI2 */
6262                 /* ERBM is disabled */
6263                 hba->sli.sli3.hgp_ring_offset = 0xC0;
6264                 hba->sli.sli3.hgp_hbq_offset = 0;
6265 
6266                 hba->sli.sli3.iocb_cmd_size = SLI2_IOCB_CMD_SIZE;
6267                 hba->sli.sli3.iocb_rsp_size = SLI2_IOCB_RSP_SIZE;
6268         }
6269 
6270         /* The Sbus card uses Host Memory. The PCI card uses SLIM POINTER */
6271         if (hba->bus_type == SBUS_FC) {
6272                 hgp = hba->sli.sli3.slim2.phys +
6273                     (uint64_t)((unsigned long)&(mbox->us.s2.host));
6274                 ((SLIM2 *)hba->sli.sli3.slim2.virt)->pcb.hgpAddrHigh =
6275                     PADDR_HI(hgp);
6276                 ((SLIM2 *)hba->sli.sli3.slim2.virt)->pcb.hgpAddrLow =
6277                     PADDR_LO(hgp);
6278         } else {
6279                 ((SLIM2 *)hba->sli.sli3.slim2.virt)->pcb.hgpAddrHigh =
6280                     (uint32_t)ddi_get32(hba->pci_acc_handle,
6281                     (uint32_t *)(hba->pci_addr + PCI_BAR_1_REGISTER));
6282 
6283                 Laddr =
6284                     ddi_get32(hba->pci_acc_handle,
6285                     (uint32_t *)(hba->pci_addr + PCI_BAR_0_REGISTER));
6286                 Laddr &= ~0x4;
6287                 ((SLIM2 *)hba->sli.sli3.slim2.virt)->pcb.hgpAddrLow =
6288                     (uint32_t)(Laddr + hba->sli.sli3.hgp_ring_offset);
6289 
6290 #ifdef FMA_SUPPORT
6291                 /* Access handle validation */
6292                 EMLXS_CHK_ACC_HANDLE(hba, hba->pci_acc_handle);
6293 #endif  /* FMA_SUPPORT */
6294 
6295         }
6296 
6297         pgp = hba->sli.sli3.slim2.phys +
6298             (uint64_t)((unsigned long)&(mbox->us.s2.port));
6299         ((SLIM2 *)hba->sli.sli3.slim2.virt)->pcb.pgpAddrHigh =
6300             PADDR_HI(pgp);
6301         ((SLIM2 *)hba->sli.sli3.slim2.virt)->pcb.pgpAddrLow =
6302             PADDR_LO(pgp);
6303 
6304         offset = 0;
6305         for (i = 0; i < 4; i++) {
6306                 rp = &hba->sli.sli3.ring[i];
6307                 rdsc = &((SLIM2 *)hba->sli.sli3.slim2.virt)->pcb.rdsc[i];
6308 
6309                 /* Setup command ring */
6310                 rgp = hba->sli.sli3.slim2.phys +
6311                     (uint64_t)((unsigned long)&(slim->IOCBs[offset]));
6312                 rdsc->cmdAddrHigh = PADDR_HI(rgp);
6313                 rdsc->cmdAddrLow = PADDR_LO(rgp);
6314                 rdsc->cmdEntries = rp->fc_numCiocb;
6315 
6316                 rp->fc_cmdringaddr =
6317                     (void *)&((SLIM2 *)hba->sli.sli3.slim2.virt)->IOCBs[offset];
6318                 offset += rdsc->cmdEntries * hba->sli.sli3.iocb_cmd_size;
6319 
6320                 /* Setup response ring */
6321                 rgp = hba->sli.sli3.slim2.phys +
6322                     (uint64_t)((unsigned long)&(slim->IOCBs[offset]));
6323                 rdsc->rspAddrHigh = PADDR_HI(rgp);
6324                 rdsc->rspAddrLow = PADDR_LO(rgp);
6325                 rdsc->rspEntries = rp->fc_numRiocb;
6326 
6327                 rp->fc_rspringaddr =
6328                     (void *)&((SLIM2 *)hba->sli.sli3.slim2.virt)->IOCBs[offset];
6329                 offset += rdsc->rspEntries * hba->sli.sli3.iocb_rsp_size;
6330         }
6331 
6332         BE_SWAP32_BCOPY((uint8_t *)
6333             (&((SLIM2 *)hba->sli.sli3.slim2.virt)->pcb),
6334             (uint8_t *)(&((SLIM2 *)hba->sli.sli3.slim2.virt)->pcb),
6335             sizeof (PCB));
6336 
6337         offset = ((uint64_t)((unsigned long)
6338             &(((SLIM2 *)hba->sli.sli3.slim2.virt)->pcb)) -
6339             (uint64_t)((unsigned long)hba->sli.sli3.slim2.virt));
6340         EMLXS_MPDATA_SYNC(hba->sli.sli3.slim2.dma_handle, (off_t)offset,
6341             sizeof (PCB), DDI_DMA_SYNC_FORDEV);
6342 
6343         return (0);
6344 
6345 } /* emlxs_mb_config_port() */
6346 
6347 
6348 static uint32_t
6349 emlxs_hbq_setup(emlxs_hba_t *hba, uint32_t hbq_id)
6350 {
6351         emlxs_port_t *port = &PPORT;
6352         HBQ_INIT_t *hbq;
6353         MATCHMAP *mp;
6354         HBQE_t *hbqE;
6355         MAILBOX *mb;
6356         MAILBOXQ *mbq;
6357         void *ioa2;
6358         uint32_t j;
6359         uint32_t count;
6360         uint32_t size;
6361         uint32_t ringno;
6362         uint32_t seg;
6363 
6364         switch (hbq_id) {
6365         case EMLXS_ELS_HBQ_ID:
6366                 count = MEM_ELSBUF_COUNT;
6367                 size = MEM_ELSBUF_SIZE;
6368                 ringno = FC_ELS_RING;
6369                 seg = MEM_ELSBUF;
6370                 HBASTATS.ElsUbPosted = count;
6371                 break;
6372 
6373         case EMLXS_IP_HBQ_ID:
6374                 count = MEM_IPBUF_COUNT;
6375                 size = MEM_IPBUF_SIZE;
6376                 ringno = FC_IP_RING;
6377                 seg = MEM_IPBUF;
6378                 HBASTATS.IpUbPosted = count;
6379                 break;
6380 
6381         case EMLXS_CT_HBQ_ID:
6382                 count = MEM_CTBUF_COUNT;
6383                 size = MEM_CTBUF_SIZE;
6384                 ringno = FC_CT_RING;
6385                 seg = MEM_CTBUF;
6386                 HBASTATS.CtUbPosted = count;
6387                 break;
6388 
6389 #ifdef SFCT_SUPPORT
6390         case EMLXS_FCT_HBQ_ID:
6391                 count = MEM_FCTBUF_COUNT;
6392                 size = MEM_FCTBUF_SIZE;
6393                 ringno = FC_FCT_RING;
6394                 seg = MEM_FCTBUF;
6395                 HBASTATS.FctUbPosted = count;
6396                 break;
6397 #endif /* SFCT_SUPPORT */
6398 
6399         default:
6400                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mem_alloc_msg,
6401                     "hbq_setup: Invalid HBQ id. (%x)", hbq_id);
6402                 return (1);
6403         }
6404 
6405         /* Configure HBQ */
6406         hbq = &hba->sli.sli3.hbq_table[hbq_id];
6407         hbq->HBQ_numEntries = count;
6408 
6409         /* Get a Mailbox buffer to setup mailbox commands for CONFIG_HBQ */
6410         if ((mbq = (MAILBOXQ *)emlxs_mem_get(hba, MEM_MBOX)) == 0) {
6411                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mem_alloc_msg,
6412                     "hbq_setup: Unable to get mailbox.");
6413                 return (1);
6414         }
6415         mb = (MAILBOX *)mbq;
6416 
6417         /* Allocate HBQ Host buffer and Initialize the HBQEs */
6418         if (emlxs_hbq_alloc(hba, hbq_id)) {
6419                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mem_alloc_msg,
6420                     "hbq_setup: Unable to allocate HBQ.");
6421                 emlxs_mem_put(hba, MEM_MBOX, (void *)mbq);
6422                 return (1);
6423         }
6424 
6425         hbq->HBQ_recvNotify = 1;
6426         hbq->HBQ_num_mask = 0;                       /* Bind to ring */
6427         hbq->HBQ_profile = 0;                        /* Selection profile */
6428                                                 /* 0=all, 7=logentry */
6429         hbq->HBQ_ringMask = 1 << ringno;       /* b0100 * ringno - Binds */
6430                                                 /* HBQ to a ring */
6431                                                 /* Ring0=b0001, Ring1=b0010, */
6432                                                 /* Ring2=b0100 */
6433         hbq->HBQ_headerLen = 0;                      /* 0 if not profile 4 or 5 */
6434         hbq->HBQ_logEntry = 0;                       /* Set to 1 if this HBQ will */
6435                                                 /* be used for */
6436         hbq->HBQ_id = hbq_id;
6437         hbq->HBQ_PutIdx_next = 0;
6438         hbq->HBQ_PutIdx = hbq->HBQ_numEntries - 1;
6439         hbq->HBQ_GetIdx = 0;
6440         hbq->HBQ_PostBufCnt = hbq->HBQ_numEntries;
6441         bzero(hbq->HBQ_PostBufs, sizeof (hbq->HBQ_PostBufs));
6442 
6443         /* Fill in POST BUFFERs in HBQE */
6444         hbqE = (HBQE_t *)hbq->HBQ_host_buf.virt;
6445         for (j = 0; j < hbq->HBQ_numEntries; j++, hbqE++) {
6446                 /* Allocate buffer to post */
6447                 if ((mp = (MATCHMAP *)emlxs_mem_get(hba,
6448                     seg)) == 0) {
6449                         EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mem_alloc_msg,
6450                             "hbq_setup: Unable to allocate HBQ buffer. "
6451                             "cnt=%d", j);
6452                         emlxs_hbq_free_all(hba, hbq_id);
6453                         return (1);
6454                 }
6455 
6456                 hbq->HBQ_PostBufs[j] = mp;
6457 
6458                 hbqE->unt.ext.HBQ_tag = hbq_id;
6459                 hbqE->unt.ext.HBQE_tag = j;
6460                 hbqE->bde.tus.f.bdeSize = size;
6461                 hbqE->bde.tus.f.bdeFlags = 0;
6462                 hbqE->unt.w = BE_SWAP32(hbqE->unt.w);
6463                 hbqE->bde.tus.w = BE_SWAP32(hbqE->bde.tus.w);
6464                 hbqE->bde.addrLow =
6465                     BE_SWAP32(PADDR_LO(mp->phys));
6466                 hbqE->bde.addrHigh =
6467                     BE_SWAP32(PADDR_HI(mp->phys));
6468         }
6469 
6470         /* Issue CONFIG_HBQ */
6471         emlxs_mb_config_hbq(hba, mbq, hbq_id);
6472         if (emlxs_sli3_issue_mbox_cmd(hba, mbq, MBX_WAIT, 0) != MBX_SUCCESS) {
6473                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
6474                     "hbq_setup: Unable to config HBQ. cmd=%x status=%x",
6475                     mb->mbxCommand, mb->mbxStatus);
6476 
6477                 emlxs_mem_put(hba, MEM_MBOX, (void *)mbq);
6478                 emlxs_hbq_free_all(hba, hbq_id);
6479                 return (1);
6480         }
6481 
6482         /* Setup HBQ Get/Put indexes */
6483         ioa2 = (void *)((char *)hba->sli.sli3.slim_addr +
6484             (hba->sli.sli3.hgp_hbq_offset + (hbq_id * sizeof (uint32_t))));
6485         WRITE_SLIM_ADDR(hba, (volatile uint32_t *)ioa2, hbq->HBQ_PutIdx);
6486 
6487         hba->sli.sli3.hbq_count++;
6488 
6489         emlxs_mem_put(hba, MEM_MBOX, (void *)mbq);
6490 
6491 #ifdef FMA_SUPPORT
6492         /* Access handle validation */
6493         if (emlxs_fm_check_acc_handle(hba, hba->sli.sli3.slim_acc_handle)
6494             != DDI_FM_OK) {
6495                 EMLXS_MSGF(EMLXS_CONTEXT,
6496                     &emlxs_invalid_access_handle_msg, NULL);
6497                 emlxs_hbq_free_all(hba, hbq_id);
6498                 return (1);
6499         }
6500 #endif  /* FMA_SUPPORT */
6501 
6502         return (0);
6503 
6504 } /* emlxs_hbq_setup() */
6505 
6506 
6507 extern void
6508 emlxs_hbq_free_all(emlxs_hba_t *hba, uint32_t hbq_id)
6509 {
6510         HBQ_INIT_t *hbq;
6511         MBUF_INFO *buf_info;
6512         MBUF_INFO bufinfo;
6513         uint32_t seg;
6514         uint32_t j;
6515 
6516         switch (hbq_id) {
6517         case EMLXS_ELS_HBQ_ID:
6518                 seg = MEM_ELSBUF;
6519                 HBASTATS.ElsUbPosted = 0;
6520                 break;
6521 
6522         case EMLXS_IP_HBQ_ID:
6523                 seg = MEM_IPBUF;
6524                 HBASTATS.IpUbPosted = 0;
6525                 break;
6526 
6527         case EMLXS_CT_HBQ_ID:
6528                 seg = MEM_CTBUF;
6529                 HBASTATS.CtUbPosted = 0;
6530                 break;
6531 
6532 #ifdef SFCT_SUPPORT
6533         case EMLXS_FCT_HBQ_ID:
6534                 seg = MEM_FCTBUF;
6535                 HBASTATS.FctUbPosted = 0;
6536                 break;
6537 #endif /* SFCT_SUPPORT */
6538 
6539         default:
6540                 return;
6541         }
6542 
6543 
6544         hbq = &hba->sli.sli3.hbq_table[hbq_id];
6545 
6546         if (hbq->HBQ_host_buf.virt != 0) {
6547                 for (j = 0; j < hbq->HBQ_PostBufCnt; j++) {
6548                         emlxs_mem_put(hba, seg,
6549                             (void *)hbq->HBQ_PostBufs[j]);
6550                         hbq->HBQ_PostBufs[j] = NULL;
6551                 }
6552                 hbq->HBQ_PostBufCnt = 0;
6553 
6554                 buf_info = &bufinfo;
6555                 bzero(buf_info, sizeof (MBUF_INFO));
6556 
6557                 buf_info->size = hbq->HBQ_host_buf.size;
6558                 buf_info->virt = hbq->HBQ_host_buf.virt;
6559                 buf_info->phys = hbq->HBQ_host_buf.phys;
6560                 buf_info->dma_handle = hbq->HBQ_host_buf.dma_handle;
6561                 buf_info->data_handle = hbq->HBQ_host_buf.data_handle;
6562                 buf_info->flags = FC_MBUF_DMA;
6563 
6564                 emlxs_mem_free(hba, buf_info);
6565 
6566                 hbq->HBQ_host_buf.virt = NULL;
6567         }
6568 
6569         return;
6570 
6571 } /* emlxs_hbq_free_all() */
6572 
6573 
6574 extern void
6575 emlxs_update_HBQ_index(emlxs_hba_t *hba, uint32_t hbq_id)
6576 {
6577 #ifdef FMA_SUPPORT
6578         emlxs_port_t *port = &PPORT;
6579 #endif  /* FMA_SUPPORT */
6580         void *ioa2;
6581         uint32_t status;
6582         uint32_t HBQ_PortGetIdx;
6583         HBQ_INIT_t *hbq;
6584 
6585         switch (hbq_id) {
6586         case EMLXS_ELS_HBQ_ID:
6587                 HBASTATS.ElsUbPosted++;
6588                 break;
6589 
6590         case EMLXS_IP_HBQ_ID:
6591                 HBASTATS.IpUbPosted++;
6592                 break;
6593 
6594         case EMLXS_CT_HBQ_ID:
6595                 HBASTATS.CtUbPosted++;
6596                 break;
6597 
6598 #ifdef SFCT_SUPPORT
6599         case EMLXS_FCT_HBQ_ID:
6600                 HBASTATS.FctUbPosted++;
6601                 break;
6602 #endif /* SFCT_SUPPORT */
6603 
6604         default:
6605                 return;
6606         }
6607 
6608         hbq = &hba->sli.sli3.hbq_table[hbq_id];
6609 
6610         hbq->HBQ_PutIdx =
6611             (hbq->HBQ_PutIdx + 1 >=
6612             hbq->HBQ_numEntries) ? 0 : hbq->HBQ_PutIdx + 1;
6613 
6614         if (hbq->HBQ_PutIdx == hbq->HBQ_GetIdx) {
6615                 HBQ_PortGetIdx =
6616                     BE_SWAP32(((SLIM2 *)hba->sli.sli3.slim2.virt)->mbx.us.s2.
6617                     HBQ_PortGetIdx[hbq_id]);
6618 
6619                 hbq->HBQ_GetIdx = HBQ_PortGetIdx;
6620 
6621                 if (hbq->HBQ_PutIdx == hbq->HBQ_GetIdx) {
6622                         return;
6623                 }
6624         }
6625 
6626         ioa2 = (void *)((char *)hba->sli.sli3.slim_addr +
6627             (hba->sli.sli3.hgp_hbq_offset + (hbq_id * sizeof (uint32_t))));
6628         status = hbq->HBQ_PutIdx;
6629         WRITE_SLIM_ADDR(hba, (volatile uint32_t *)ioa2, status);
6630 
6631 #ifdef FMA_SUPPORT
6632         /* Access handle validation */
6633         EMLXS_CHK_ACC_HANDLE(hba, hba->sli.sli3.slim_acc_handle);
6634 #endif  /* FMA_SUPPORT */
6635 
6636         return;
6637 
6638 } /* emlxs_update_HBQ_index() */
6639 
6640 
6641 static void
6642 emlxs_sli3_enable_intr(emlxs_hba_t *hba)
6643 {
6644 #ifdef FMA_SUPPORT
6645         emlxs_port_t *port = &PPORT;
6646 #endif  /* FMA_SUPPORT */
6647         uint32_t status;
6648 
6649         /* Enable mailbox, error attention interrupts */
6650         status = (uint32_t)(HC_MBINT_ENA);
6651 
6652         /* Enable ring interrupts */
6653         if (hba->sli.sli3.ring_count >= 4) {
6654                 status |=
6655                     (HC_R3INT_ENA | HC_R2INT_ENA | HC_R1INT_ENA |
6656                     HC_R0INT_ENA);
6657         } else if (hba->sli.sli3.ring_count == 3) {
6658                 status |= (HC_R2INT_ENA | HC_R1INT_ENA | HC_R0INT_ENA);
6659         } else if (hba->sli.sli3.ring_count == 2) {
6660                 status |= (HC_R1INT_ENA | HC_R0INT_ENA);
6661         } else if (hba->sli.sli3.ring_count == 1) {
6662                 status |= (HC_R0INT_ENA);
6663         }
6664 
6665         hba->sli.sli3.hc_copy = status;
6666         WRITE_CSR_REG(hba, FC_HC_REG(hba), hba->sli.sli3.hc_copy);
6667 
6668 #ifdef FMA_SUPPORT
6669         /* Access handle validation */
6670         EMLXS_CHK_ACC_HANDLE(hba, hba->sli.sli3.csr_acc_handle);
6671 #endif  /* FMA_SUPPORT */
6672 
6673 } /* emlxs_sli3_enable_intr() */
6674 
6675 
6676 static void
6677 emlxs_enable_latt(emlxs_hba_t *hba)
6678 {
6679 #ifdef FMA_SUPPORT
6680         emlxs_port_t *port = &PPORT;
6681 #endif  /* FMA_SUPPORT */
6682 
6683         mutex_enter(&EMLXS_PORT_LOCK);
6684         hba->sli.sli3.hc_copy |= HC_LAINT_ENA;
6685         WRITE_CSR_REG(hba, FC_HC_REG(hba), hba->sli.sli3.hc_copy);
6686 #ifdef FMA_SUPPORT
6687         /* Access handle validation */
6688         EMLXS_CHK_ACC_HANDLE(hba, hba->sli.sli3.csr_acc_handle);
6689 #endif  /* FMA_SUPPORT */
6690         mutex_exit(&EMLXS_PORT_LOCK);
6691 
6692 } /* emlxs_enable_latt() */
6693 
6694 
6695 static void
6696 emlxs_sli3_disable_intr(emlxs_hba_t *hba, uint32_t att)
6697 {
6698 #ifdef FMA_SUPPORT
6699         emlxs_port_t *port = &PPORT;
6700 #endif  /* FMA_SUPPORT */
6701 
6702         /* Disable all adapter interrupts */
6703         hba->sli.sli3.hc_copy = att;
6704         WRITE_CSR_REG(hba, FC_HC_REG(hba), hba->sli.sli3.hc_copy);
6705 #ifdef FMA_SUPPORT
6706         /* Access handle validation */
6707         EMLXS_CHK_ACC_HANDLE(hba, hba->sli.sli3.csr_acc_handle);
6708 #endif  /* FMA_SUPPORT */
6709 
6710 } /* emlxs_sli3_disable_intr() */
6711 
6712 
6713 static uint32_t
6714 emlxs_check_attention(emlxs_hba_t *hba)
6715 {
6716 #ifdef FMA_SUPPORT
6717         emlxs_port_t *port = &PPORT;
6718 #endif  /* FMA_SUPPORT */
6719         uint32_t ha_copy;
6720 
6721         ha_copy = READ_CSR_REG(hba, FC_HA_REG(hba));
6722 #ifdef FMA_SUPPORT
6723         /* Access handle validation */
6724         EMLXS_CHK_ACC_HANDLE(hba, hba->sli.sli3.csr_acc_handle);
6725 #endif  /* FMA_SUPPORT */
6726         return (ha_copy);
6727 
6728 } /* emlxs_check_attention() */
6729 
6730 
6731 static void
6732 emlxs_sli3_poll_erratt(emlxs_hba_t *hba)
6733 {
6734         uint32_t ha_copy;
6735 
6736         ha_copy = emlxs_check_attention(hba);
6737 
6738         /* Adapter error */
6739         if (ha_copy & HA_ERATT) {
6740                 HBASTATS.IntrEvent[6]++;
6741                 emlxs_handle_ff_error(hba);
6742         }
6743 
6744 } /* emlxs_sli3_poll_erratt() */
6745 
6746 
6747 static uint32_t
6748 emlxs_sli3_reg_did_mbcmpl(emlxs_hba_t *hba, MAILBOXQ *mbq)
6749 {
6750         emlxs_port_t *port = (emlxs_port_t *)mbq->port;
6751         MAILBOXQ *mboxq;
6752         MAILBOX *mb;
6753         MATCHMAP *mp;
6754         NODELIST *ndlp;
6755         emlxs_port_t *vport;
6756         SERV_PARM *sp;
6757         int32_t i;
6758         uint32_t  control;
6759         uint32_t ldata;
6760         uint32_t ldid;
6761         uint16_t lrpi;
6762         uint16_t lvpi;
6763         uint32_t rval;
6764 
6765         mb = (MAILBOX *)mbq;
6766 
6767         if (mb->mbxStatus) {
6768                 if (mb->mbxStatus == MBXERR_NO_RESOURCES) {
6769                         control = mb->un.varRegLogin.un.sp.bdeSize;
6770                         if (control == 0) {
6771                                 /* Special handle for vport PLOGI */
6772                                 if (mbq->iocbq == (uint8_t *)1) {
6773                                         mbq->iocbq = NULL;
6774                                 }
6775                                 return (0);
6776                         }
6777                         emlxs_mb_retry(hba, mbq);
6778                         return (1);
6779                 }
6780                 if (mb->mbxStatus == MBXERR_RPI_FULL) {
6781                         EMLXS_MSGF(EMLXS_CONTEXT,
6782                             &emlxs_node_create_failed_msg,
6783                             "Limit reached. count=%d", port->node_count);
6784                 }
6785 
6786                 /* Special handle for vport PLOGI */
6787                 if (mbq->iocbq == (uint8_t *)1) {
6788                         mbq->iocbq = NULL;
6789                 }
6790 
6791                 return (0);
6792         }
6793 
6794         mp = (MATCHMAP *)mbq->bp;
6795         if (!mp) {
6796                 return (0);
6797         }
6798 
6799         ldata = mb->un.varWords[5];
6800         lvpi = (ldata & 0xffff);
6801         port = &VPORT(lvpi);
6802 
6803         /* First copy command data */
6804         ldata = mb->un.varWords[0];  /* get rpi */
6805         lrpi = ldata & 0xffff;
6806 
6807         ldata = mb->un.varWords[1];  /* get did */
6808         ldid = ldata & MASK_DID;
6809 
6810         sp = (SERV_PARM *)mp->virt;
6811 
6812         /* Create or update the node */
6813         ndlp = emlxs_node_create(port, ldid, lrpi, sp);
6814 
6815         if (ndlp == NULL) {
6816                 emlxs_ub_priv_t *ub_priv;
6817 
6818                 /*
6819                  * Fake a mailbox error, so the mbox_fini
6820                  * can take appropriate action
6821                  */
6822                 mb->mbxStatus = MBXERR_RPI_FULL;
6823                 if (mbq->ubp) {
6824                         ub_priv = ((fc_unsol_buf_t *)mbq->ubp)->ub_fca_private;
6825                         ub_priv->flags |= EMLXS_UB_REPLY;
6826                 }
6827 
6828                 /* This must be (0xFFFFFE) which was registered by vport */
6829                 if (lrpi == 0) {
6830                         return (0);
6831                 }
6832 
6833                 if (!(mboxq = (MAILBOXQ *)emlxs_mem_get(hba, MEM_MBOX))) {
6834                         EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
6835                             "reg_did_mbcmpl:failed. Unable to allocate mbox");
6836                         return (0);
6837                 }
6838 
6839                 mb = (MAILBOX *)mboxq->mbox;
6840                 mb->un.varUnregLogin.rpi = lrpi;
6841                 mb->un.varUnregLogin.vpi = lvpi;
6842 
6843                 mb->mbxCommand = MBX_UNREG_LOGIN;
6844                 mb->mbxOwner = OWN_HOST;
6845                 mboxq->sbp = NULL;
6846                 mboxq->ubp = NULL;
6847                 mboxq->iocbq = NULL;
6848                 mboxq->mbox_cmpl = NULL;
6849                 mboxq->context = NULL;
6850                 mboxq->port = (void *)port;
6851 
6852                 rval = EMLXS_SLI_ISSUE_MBOX_CMD(hba, mboxq, MBX_NOWAIT, 0);
6853                 if ((rval != MBX_BUSY) && (rval != MBX_SUCCESS)) {
6854                         EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
6855                             "reg_did_mbcmpl:failed. Unable to send request.");
6856 
6857                         emlxs_mem_put(hba, MEM_MBOX, (void *)mboxq);
6858                         return (0);
6859                 }
6860 
6861                 return (0);
6862         }
6863 
6864         if (ndlp->nlp_DID == FABRIC_DID) {
6865                 /* FLOGI/FDISC successfully completed on this port */
6866                 mutex_enter(&EMLXS_PORT_LOCK);
6867                 port->flag |= EMLXS_PORT_FLOGI_CMPL;
6868                 mutex_exit(&EMLXS_PORT_LOCK);
6869 
6870                 /* If CLEAR_LA has been sent, then attempt to */
6871                 /* register the vpi now */
6872                 if (hba->state == FC_READY) {
6873                         (void) emlxs_mb_reg_vpi(port, NULL);
6874                 }
6875 
6876                 /*
6877                  * If NPIV Fabric support has just been established on
6878                  * the physical port, then notify the vports of the
6879                  * link up
6880                  */
6881                 if ((lvpi == 0) &&
6882                     (hba->flag & FC_NPIV_ENABLED) &&
6883                     (hba->flag & FC_NPIV_SUPPORTED)) {
6884                         /* Skip the physical port */
6885                         for (i = 1; i < MAX_VPORTS; i++) {
6886                                 vport = &VPORT(i);
6887 
6888                                 if (!(vport->flag & EMLXS_PORT_BOUND) ||
6889                                     !(vport->flag &
6890                                     EMLXS_PORT_ENABLED)) {
6891                                         continue;
6892                                 }
6893 
6894                                 emlxs_port_online(vport);
6895                         }
6896                 }
6897         }
6898 
6899         /* Check for special restricted login flag */
6900         if (mbq->iocbq == (uint8_t *)1) {
6901                 mbq->iocbq = NULL;
6902                 (void) EMLXS_SLI_UNREG_NODE(port, ndlp, NULL, NULL, NULL);
6903                 return (0);
6904         }
6905 
6906         /* Needed for FCT trigger in emlxs_mb_deferred_cmpl */
6907         if (mbq->sbp) {
6908                 ((emlxs_buf_t *)mbq->sbp)->node = ndlp;
6909         }
6910 
6911 #ifdef DHCHAP_SUPPORT
6912         if (mbq->sbp || mbq->ubp) {
6913                 if (emlxs_dhc_auth_start(port, ndlp, mbq->sbp,
6914                     mbq->ubp) == 0) {
6915                         /* Auth started - auth completion will */
6916                         /* handle sbp and ubp now */
6917                         mbq->sbp = NULL;
6918                         mbq->ubp = NULL;
6919                 }
6920         }
6921 #endif  /* DHCHAP_SUPPORT */
6922 
6923         return (0);
6924 
6925 } /* emlxs_sli3_reg_did_mbcmpl() */
6926 
6927 
6928 static uint32_t
6929 emlxs_sli3_reg_did(emlxs_port_t *port, uint32_t did, SERV_PARM *param,
6930     emlxs_buf_t *sbp, fc_unsol_buf_t *ubp, IOCBQ *iocbq)
6931 {
6932         emlxs_hba_t     *hba = HBA;
6933         MATCHMAP        *mp;
6934         MAILBOXQ        *mbq;
6935         MAILBOX         *mb;
6936         uint32_t        rval;
6937 
6938         /* Check for invalid node ids to register */
6939         if ((did == 0) && (!(hba->flag & FC_LOOPBACK_MODE))) {
6940                 return (1);
6941         }
6942 
6943         if (did & 0xff000000) {
6944                 return (1);
6945         }
6946 
6947         if ((rval = emlxs_mb_check_sparm(hba, param))) {
6948                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_node_create_failed_msg,
6949                     "Invalid service parameters. did=%06x rval=%d", did,
6950                     rval);
6951 
6952                 return (1);
6953         }
6954 
6955         /* Check if the node limit has been reached */
6956         if (port->node_count >= hba->max_nodes) {
6957                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_node_create_failed_msg,
6958                     "Limit reached. did=%06x count=%d", did,
6959                     port->node_count);
6960 
6961                 return (1);
6962         }
6963 
6964         if (!(mbq = (MAILBOXQ *)emlxs_mem_get(hba, MEM_MBOX))) {
6965                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_node_create_failed_msg,
6966                     "Unable to allocate mailbox. did=%x", did);
6967 
6968                 return (1);
6969         }
6970         mb = (MAILBOX *)mbq->mbox;
6971         bzero((void *)mb, MAILBOX_CMD_BSIZE);
6972 
6973         /* Build login request */
6974         if ((mp = (MATCHMAP *)emlxs_mem_get(hba, MEM_BUF)) == 0) {
6975                 emlxs_mem_put(hba, MEM_MBOX, (void *)mbq);
6976 
6977                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_node_create_failed_msg,
6978                     "Unable to allocate buffer. did=%x", did);
6979                 return (1);
6980         }
6981         bcopy((void *)param, (void *)mp->virt, sizeof (SERV_PARM));
6982 
6983         mb->un.varRegLogin.un.sp64.tus.f.bdeSize = sizeof (SERV_PARM);
6984         mb->un.varRegLogin.un.sp64.addrHigh = PADDR_HI(mp->phys);
6985         mb->un.varRegLogin.un.sp64.addrLow = PADDR_LO(mp->phys);
6986         mb->un.varRegLogin.did = did;
6987         mb->un.varWords[30] = 0;     /* flags */
6988         mb->mbxCommand = MBX_REG_LOGIN64;
6989         mb->mbxOwner = OWN_HOST;
6990         mb->un.varRegLogin.vpi = port->vpi;
6991         mb->un.varRegLogin.rpi = 0;
6992 
6993         mbq->sbp = (void *)sbp;
6994         mbq->ubp = (void *)ubp;
6995         mbq->iocbq = (void *)iocbq;
6996         mbq->bp = (void *)mp;
6997         mbq->mbox_cmpl = emlxs_sli3_reg_did_mbcmpl;
6998         mbq->context = NULL;
6999         mbq->port = (void *)port;
7000 
7001         rval = EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbq, MBX_NOWAIT, 0);
7002         if ((rval != MBX_BUSY) && (rval != MBX_SUCCESS)) {
7003                 emlxs_mem_put(hba, MEM_BUF, (void *)mp);
7004                 emlxs_mem_put(hba, MEM_MBOX, (void *)mbq);
7005 
7006                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_node_create_failed_msg,
7007                     "Unable to send mbox. did=%x", did);
7008                 return (1);
7009         }
7010 
7011         return (0);
7012 
7013 } /* emlxs_sli3_reg_did() */
7014 
7015 
7016 /*ARGSUSED*/
7017 static uint32_t
7018 emlxs_sli3_unreg_node_mbcmpl(emlxs_hba_t *hba, MAILBOXQ *mbq)
7019 {
7020         emlxs_port_t    *port = (emlxs_port_t *)mbq->port;
7021         MAILBOX         *mb;
7022         NODELIST        *node;
7023         uint16_t        rpi;
7024 
7025         node = (NODELIST *)mbq->context;
7026         mb = (MAILBOX *)mbq;
7027         rpi = (node)? node->nlp_Rpi:0xffff;
7028 
7029         if (mb->mbxStatus) {
7030                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
7031                     "unreg_node_mbcmpl:failed. node=%p rpi=%d status=%x",
7032                     node, rpi, mb->mbxStatus);
7033 
7034                 return (0);
7035         }
7036 
7037         EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
7038             "unreg_node_mbcmpl: node=%p rpi=%d",
7039             node, rpi);
7040 
7041         if (node) {
7042                 emlxs_node_rm(port, node);
7043 
7044         } else {  /* All nodes */
7045                 emlxs_node_destroy_all(port);
7046         }
7047 
7048         return (0);
7049 
7050 } /* emlxs_sli3_unreg_node_mbcmpl */
7051 
7052 
7053 static uint32_t
7054 emlxs_sli3_unreg_node(emlxs_port_t *port, NODELIST *node, emlxs_buf_t *sbp,
7055     fc_unsol_buf_t *ubp, IOCBQ *iocbq)
7056 {
7057         emlxs_hba_t     *hba = HBA;
7058         MAILBOXQ        *mbq;
7059         MAILBOX         *mb;
7060         uint16_t        rpi;
7061         uint32_t        rval;
7062 
7063         if (node) {
7064                 /* Check for base node */
7065                 if (node == &port->node_base) {
7066                         /* just flush base node */
7067                         (void) emlxs_tx_node_flush(port, &port->node_base,
7068                             0, 0, 0);
7069                         (void) emlxs_chipq_node_flush(port, 0,
7070                             &port->node_base, 0);
7071 
7072                         port->did = 0;
7073 
7074                         /* Return now */
7075                         return (1);
7076                 }
7077 
7078                 rpi = (uint16_t)node->nlp_Rpi;
7079 
7080                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
7081                     "unreg_node:%p  rpi=%d", node, rpi);
7082 
7083                 /* This node must be (0xFFFFFE) which registered by vport */
7084                 if (rpi == 0) {
7085                         emlxs_node_rm(port, node);
7086                         return (0);
7087                 }
7088 
7089         } else {        /* Unreg all nodes */
7090                 rpi = 0xffff;
7091 
7092                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
7093                     "unreg_node: All");
7094         }
7095 
7096         if (!(mbq = (MAILBOXQ *)emlxs_mem_get(hba, MEM_MBOX))) {
7097                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
7098                     "unreg_node:failed. Unable to allocate mbox");
7099                 return (1);
7100         }
7101 
7102         mb = (MAILBOX *)mbq->mbox;
7103         mb->un.varUnregLogin.rpi = rpi;
7104         mb->un.varUnregLogin.vpi = port->vpip->VPI;
7105 
7106         mb->mbxCommand = MBX_UNREG_LOGIN;
7107         mb->mbxOwner = OWN_HOST;
7108         mbq->sbp = (void *)sbp;
7109         mbq->ubp = (void *)ubp;
7110         mbq->iocbq = (void *)iocbq;
7111         mbq->mbox_cmpl = emlxs_sli3_unreg_node_mbcmpl;
7112         mbq->context = (void *)node;
7113         mbq->port = (void *)port;
7114 
7115         rval = EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbq, MBX_NOWAIT, 0);
7116         if ((rval != MBX_BUSY) && (rval != MBX_SUCCESS)) {
7117                 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
7118                     "unreg_node:failed. Unable to send request.");
7119 
7120                 emlxs_mem_put(hba, MEM_MBOX, (void *)mbq);
7121                 return (1);
7122         }
7123 
7124         return (0);
7125 
7126 } /* emlxs_sli3_unreg_node() */