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 usr/src/OPENSOLARIS.LICENSE
   9  * or http://www.opensolaris.org/os/licensing.
  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 /* Copyright 2010 QLogic Corporation */
  23 
  24 /*
  25  * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
  26  */
  27 
  28 #pragma ident   "Copyright 2010 QLogic Corporation; ql_mbx.c"
  29 
  30 /*
  31  * ISP2xxx Solaris Fibre Channel Adapter (FCA) driver source file.
  32  *
  33  * ***********************************************************************
  34  * *                                                                    **
  35  * *                            NOTICE                                  **
  36  * *            COPYRIGHT (C) 1996-2010 QLOGIC CORPORATION              **
  37  * *                    ALL RIGHTS RESERVED                             **
  38  * *                                                                    **
  39  * ***********************************************************************
  40  *
  41  */
  42 
  43 #include <ql_apps.h>
  44 #include <ql_api.h>
  45 #include <ql_debug.h>
  46 #include <ql_iocb.h>
  47 #include <ql_isr.h>
  48 #include <ql_mbx.h>
  49 #include <ql_xioctl.h>
  50 
  51 /*
  52  * Local data
  53  */
  54 
  55 /*
  56  * Local prototypes
  57  */
  58 static int ql_mailbox_command(ql_adapter_state_t *, mbx_cmd_t *);
  59 static int ql_task_mgmt_iocb(ql_adapter_state_t *, ql_tgt_t *, uint16_t,
  60     uint32_t, uint16_t);
  61 static int ql_abort_cmd_iocb(ql_adapter_state_t *, ql_srb_t *);
  62 static int ql_setup_mbox_dma_transfer(ql_adapter_state_t *, dma_mem_t *,
  63     caddr_t, uint32_t);
  64 static int ql_setup_mbox_dma_resources(ql_adapter_state_t *, dma_mem_t *,
  65     uint32_t);
  66 static void ql_setup_mbox_dma_data(dma_mem_t *, caddr_t);
  67 static void ql_get_mbox_dma_data(dma_mem_t *, caddr_t);
  68 
  69 /*
  70  * ql_mailbox_command
  71  *      Issue mailbox command and waits for completion.
  72  *
  73  * Input:
  74  *      ha = adapter state pointer.
  75  *      mcp = mailbox command parameter structure pointer.
  76  *
  77  * Returns:
  78  *      ql local function return status code.
  79  *
  80  * Context:
  81  *      Kernel context.
  82  */
  83 static int
  84 ql_mailbox_command(ql_adapter_state_t *vha, mbx_cmd_t *mcp)
  85 {
  86         uint16_t                cnt;
  87         uint32_t                data;
  88         clock_t                 timer, cv_stat;
  89         int                     rval;
  90         uint32_t                set_flags = 0;
  91         uint32_t                reset_flags = 0;
  92         ql_adapter_state_t      *ha = vha->pha;
  93         int                     mbx_cmd = mcp->mb[0];
  94 
  95         QL_PRINT_3(CE_CONT, "(%d): started, cmd=%xh\n", ha->instance, mbx_cmd);
  96 
  97         /* Acquire mailbox register lock. */
  98         MBX_REGISTER_LOCK(ha);
  99 
 100         /* Check for mailbox available, if not wait for signal. */
 101         while (ha->mailbox_flags & MBX_BUSY_FLG ||
 102             (CFG_IST(ha, CFG_CTRL_8021) &&
 103             RD32_IO_REG(ha, nx_host_int) & NX_MBX_CMD)) {
 104                 ha->mailbox_flags = (uint8_t)
 105                     (ha->mailbox_flags | MBX_WANT_FLG);
 106 
 107                 if (ha->task_daemon_flags & TASK_DAEMON_POWERING_DOWN) {
 108                         EL(vha, "failed availability cmd=%xh\n", mcp->mb[0]);
 109                         MBX_REGISTER_UNLOCK(ha);
 110                         return (QL_LOCK_TIMEOUT);
 111                 }
 112 
 113                 /* Set timeout after command that is running. */
 114                 timer = (mcp->timeout + 20) * drv_usectohz(1000000);
 115                 cv_stat = cv_reltimedwait_sig(&ha->cv_mbx_wait,
 116                     &ha->pha->mbx_mutex, timer, TR_CLOCK_TICK);
 117                 if (cv_stat == -1 || cv_stat == 0) {
 118                         /*
 119                          * The timeout time 'timer' was
 120                          * reached without the condition
 121                          * being signaled.
 122                          */
 123                         ha->mailbox_flags = (uint8_t)(ha->mailbox_flags &
 124                             ~MBX_WANT_FLG);
 125                         cv_broadcast(&ha->cv_mbx_wait);
 126 
 127                         /* Release mailbox register lock. */
 128                         MBX_REGISTER_UNLOCK(ha);
 129 
 130                         if (cv_stat == 0) {
 131                                 EL(vha, "waiting for availability aborted, "
 132                                     "cmd=%xh\n", mcp->mb[0]);
 133                                 return (QL_ABORTED);
 134                         }
 135                         EL(vha, "failed availability cmd=%xh\n", mcp->mb[0]);
 136                         return (QL_LOCK_TIMEOUT);
 137                 }
 138         }
 139 
 140         ha->mailbox_flags = (uint8_t)(ha->mailbox_flags | MBX_BUSY_FLG);
 141 
 142         /* Structure pointer for return mailbox registers. */
 143         ha->mcp = mcp;
 144 
 145         /* Load mailbox registers. */
 146         data = mcp->out_mb;
 147         for (cnt = 0; cnt < ha->reg_off->mbox_cnt && data; cnt++) {
 148                 if (data & MBX_0) {
 149                         WRT16_IO_REG(ha, mailbox_in[cnt], mcp->mb[cnt]);
 150                 }
 151                 data >>= 1;
 152         }
 153 
 154         /* Issue set host interrupt command. */
 155         ha->mailbox_flags = (uint8_t)(ha->mailbox_flags & ~MBX_INTERRUPT);
 156         if (CFG_IST(ha, CFG_CTRL_8021)) {
 157                 WRT32_IO_REG(ha, nx_host_int, NX_MBX_CMD);
 158         } else if (CFG_IST(ha, CFG_CTRL_242581)) {
 159                 WRT32_IO_REG(ha, hccr, HC24_SET_HOST_INT);
 160         } else {
 161                 WRT16_IO_REG(ha, hccr, HC_SET_HOST_INT);
 162         }
 163 
 164         /* Wait for command to complete. */
 165         if (ha->flags & INTERRUPTS_ENABLED &&
 166             !(ha->task_daemon_flags & (TASK_THREAD_CALLED |
 167             TASK_DAEMON_POWERING_DOWN)) &&
 168             !ddi_in_panic()) {
 169                 timer = mcp->timeout * drv_usectohz(1000000);
 170                 while (!(ha->mailbox_flags & (MBX_INTERRUPT | MBX_ABORT)) &&
 171                     !(ha->task_daemon_flags & ISP_ABORT_NEEDED)) {
 172 
 173                         if (cv_reltimedwait(&ha->cv_mbx_intr,
 174                             &ha->pha->mbx_mutex, timer, TR_CLOCK_TICK) == -1) {
 175                                 /*
 176                                  * The timeout time 'timer' was
 177                                  * reached without the condition
 178                                  * being signaled.
 179                                  */
 180                                 MBX_REGISTER_UNLOCK(ha);
 181                                 while (INTERRUPT_PENDING(ha)) {
 182                                         (void) ql_isr((caddr_t)ha);
 183                                         INTR_LOCK(ha);
 184                                         ha->intr_claimed = B_TRUE;
 185                                         INTR_UNLOCK(ha);
 186                                 }
 187                                 MBX_REGISTER_LOCK(ha);
 188                                 break;
 189                         }
 190                 }
 191         } else {
 192                 /* Release mailbox register lock. */
 193                 MBX_REGISTER_UNLOCK(ha);
 194 
 195                 /* Acquire interrupt lock. */
 196                 for (timer = mcp->timeout * 100; timer; timer--) {
 197                         /* Check for pending interrupts. */
 198                         while (INTERRUPT_PENDING(ha)) {
 199                                 (void) ql_isr((caddr_t)ha);
 200                                 INTR_LOCK(ha);
 201                                 ha->intr_claimed = B_TRUE;
 202                                 INTR_UNLOCK(ha);
 203                                 if (ha->mailbox_flags &
 204                                     (MBX_INTERRUPT | MBX_ABORT) ||
 205                                     ha->task_daemon_flags & ISP_ABORT_NEEDED) {
 206                                         break;
 207                                 }
 208                         }
 209                         if (ha->mailbox_flags & (MBX_INTERRUPT | MBX_ABORT) ||
 210                             ha->task_daemon_flags & ISP_ABORT_NEEDED) {
 211                                 break;
 212                         } else if (!ddi_in_panic() && timer % 101 == 0) {
 213                                 delay(drv_usectohz(10000));
 214                         } else {
 215                                 drv_usecwait(10000);
 216                         }
 217                 }
 218 
 219                 /* Acquire mailbox register lock. */
 220                 MBX_REGISTER_LOCK(ha);
 221         }
 222 
 223         /* Mailbox command timeout? */
 224         if (ha->task_daemon_flags & ISP_ABORT_NEEDED ||
 225             ha->mailbox_flags & MBX_ABORT) {
 226                 rval = QL_ABORTED;
 227         } else if ((ha->mailbox_flags & MBX_INTERRUPT) == 0) {
 228                 if (!CFG_IST(ha, CFG_CTRL_8021)) {
 229                         if (CFG_IST(ha, CFG_DUMP_MAILBOX_TIMEOUT)) {
 230                                 (void) ql_binary_fw_dump(ha, FALSE);
 231                         }
 232                         EL(vha, "command timeout, isp_abort_needed\n");
 233                         set_flags |= ISP_ABORT_NEEDED;
 234                 }
 235                 rval = QL_FUNCTION_TIMEOUT;
 236         } else {
 237                 ha->mailbox_flags = (uint8_t)
 238                     (ha->mailbox_flags & ~MBX_INTERRUPT);
 239                 /*
 240                  * This is the expected completion path so
 241                  * return the actual mbx cmd completion status.
 242                  */
 243                 rval = mcp->mb[0];
 244         }
 245 
 246         /*
 247          * Clear outbound to risc mailbox registers per spec. The exception
 248          * is on 2200 mailbox 4 and 5 affect the req and resp que indexes
 249          * so avoid writing them.
 250          */
 251         if (ha->cfg_flags & CFG_CTRL_2200) {
 252                 data = ((mcp->out_mb & ~(MBX_4 | MBX_5)) >> 1);
 253         } else {
 254                 data = (mcp->out_mb >> 1);
 255         }
 256         for (cnt = 1; cnt < ha->reg_off->mbox_cnt && data; cnt++) {
 257                 if (data & MBX_0) {
 258                         WRT16_IO_REG(ha, mailbox_in[cnt], (uint16_t)0);
 259                 }
 260                 data >>= 1;
 261         }
 262 
 263         /* Reset busy status. */
 264         ha->mailbox_flags = (uint8_t)(ha->mailbox_flags &
 265             ~(MBX_BUSY_FLG | MBX_ABORT));
 266         ha->mcp = NULL;
 267 
 268         /* If thread is waiting for mailbox go signal it to start. */
 269         if (ha->mailbox_flags & MBX_WANT_FLG) {
 270                 ha->mailbox_flags = (uint8_t)(ha->mailbox_flags &
 271                     ~MBX_WANT_FLG);
 272                 cv_broadcast(&ha->cv_mbx_wait);
 273         }
 274 
 275         /* Release mailbox register lock. */
 276         MBX_REGISTER_UNLOCK(ha);
 277 
 278         if (set_flags != 0 || reset_flags != 0) {
 279                 ql_awaken_task_daemon(ha, NULL, set_flags, reset_flags);
 280         }
 281 
 282         if (rval != QL_SUCCESS) {
 283                 EL(vha, "%s failed, rval=%xh, mcp->mb[0]=%xh\n",
 284                     mbx_cmd_text(mbx_cmd), rval, mcp->mb[0]);
 285         } else {
 286                 /*EMPTY*/
 287                 QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
 288         }
 289 
 290         return (rval);
 291 }
 292 
 293 /*
 294  * ql_setup_mbox_dma_resources
 295  *      Prepare the data for a mailbox dma transfer.
 296  *
 297  * Input:
 298  *      ha = adapter state pointer.
 299  *      mem_desc = descriptor to contain the dma resource information.
 300  *      data = pointer to the data.
 301  *      size = size of the data in bytes.
 302  *
 303  * Returns:
 304  *      ql local function return status code.
 305  *
 306  * Context:
 307  *      Kernel context.
 308  */
 309 static int
 310 ql_setup_mbox_dma_transfer(ql_adapter_state_t *ha, dma_mem_t *mem_desc,
 311     caddr_t data, uint32_t size)
 312 {
 313         int rval = QL_SUCCESS;
 314 
 315         if ((rval = ql_setup_mbox_dma_resources(ha, mem_desc, size)) ==
 316             QL_SUCCESS) {
 317                 ql_setup_mbox_dma_data(mem_desc, data);
 318         } else {
 319                 EL(ha, "failed, setup_mbox_dma_transfer: %xh\n", rval);
 320         }
 321 
 322         return (rval);
 323 }
 324 
 325 /*
 326  * ql_setup_mbox_dma_resources
 327  *      Prepare a dma buffer.
 328  *
 329  * Input:
 330  *      ha = adapter state pointer.
 331  *      mem_desc = descriptor to contain the dma resource information.
 332  *      data = pointer to the data.
 333  *      size = size of the data in bytes.
 334  *
 335  * Returns:
 336  *      ql local function return status code.
 337  *
 338  * Context:
 339  *      Kernel context.
 340  */
 341 static int
 342 ql_setup_mbox_dma_resources(ql_adapter_state_t *ha, dma_mem_t *mem_desc,
 343     uint32_t size)
 344 {
 345         int     rval = QL_SUCCESS;
 346 
 347         if ((rval = ql_get_dma_mem(ha, mem_desc, size, LITTLE_ENDIAN_DMA,
 348             QL_DMA_RING_ALIGN)) != QL_SUCCESS) {
 349                 EL(ha, "failed, ql_get_dma_mem FC_NOMEM\n");
 350                 rval = QL_MEMORY_ALLOC_FAILED;
 351         }
 352 
 353         return (rval);
 354 }
 355 
 356 /*
 357  * ql_setup_mbox_dma_data
 358  *      Move data to the dma buffer.
 359  *
 360  * Input:
 361  *      mem_desc = descriptor to contain the dma resource information.
 362  *      data = pointer to the data.
 363  *
 364  * Returns:
 365  *
 366  * Context:
 367  *      Kernel context.
 368  */
 369 static void
 370 ql_setup_mbox_dma_data(dma_mem_t *mem_desc, caddr_t data)
 371 {
 372         /* Copy out going data to DMA buffer. */
 373         ddi_rep_put8(mem_desc->acc_handle, (uint8_t *)data,
 374             (uint8_t *)mem_desc->bp, mem_desc->size, DDI_DEV_AUTOINCR);
 375 
 376         /* Sync DMA buffer. */
 377         (void) ddi_dma_sync(mem_desc->dma_handle, 0, mem_desc->size,
 378             DDI_DMA_SYNC_FORDEV);
 379 }
 380 
 381 /*
 382  * ql_get_mbox_dma_data
 383  *      Recover data from the dma buffer.
 384  *
 385  * Input:
 386  *      mem_desc = descriptor to contain the dma resource information.
 387  *      data = pointer to the data.
 388  *
 389  * Returns:
 390  *
 391  * Context:
 392  *      Kernel context.
 393  */
 394 static void
 395 ql_get_mbox_dma_data(dma_mem_t *mem_desc, caddr_t data)
 396 {
 397         /* Sync in coming DMA buffer. */
 398         (void) ddi_dma_sync(mem_desc->dma_handle, 0, mem_desc->size,
 399             DDI_DMA_SYNC_FORKERNEL);
 400         /* Copy in coming DMA data. */
 401         ddi_rep_get8(mem_desc->acc_handle, (uint8_t *)data,
 402             (uint8_t *)mem_desc->bp, mem_desc->size, DDI_DEV_AUTOINCR);
 403 }
 404 
 405 /*
 406  * ql_initialize_ip
 407  *      Initialize IP receive buffer queue.
 408  *
 409  * Input:
 410  *      ha = adapter state pointer.
 411  *      ha->ip_init_ctrl_blk = setup for transmit.
 412  *
 413  * Returns:
 414  *      ql local function return status code.
 415  *
 416  * Context:
 417  *      Kernel context.
 418  */
 419 int
 420 ql_initialize_ip(ql_adapter_state_t *ha)
 421 {
 422         ql_link_t       *link;
 423         ql_tgt_t        *tq;
 424         uint16_t        index;
 425         int             rval;
 426         dma_mem_t       mem_desc;
 427         mbx_cmd_t       mc = {0};
 428         mbx_cmd_t       *mcp = &mc;
 429 
 430         QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
 431 
 432         if (CFG_IST(ha, (CFG_CTRL_6322 | CFG_CTRL_258081)) ||
 433             ha->vp_index != 0) {
 434                 ha->flags &= ~IP_INITIALIZED;
 435                 EL(ha, "HBA does not support IP\n");
 436                 return (QL_FUNCTION_FAILED);
 437         }
 438 
 439         ha->rcvbuf_ring_ptr = ha->rcvbuf_ring_bp;
 440         ha->rcvbuf_ring_index = 0;
 441 
 442         /* Reset all sequence counts. */
 443         for (index = 0; index < DEVICE_HEAD_LIST_SIZE; index++) {
 444                 for (link = ha->dev[index].first; link != NULL;
 445                     link = link->next) {
 446                         tq = link->base_address;
 447                         tq->ub_total_seg_cnt = 0;
 448                 }
 449         }
 450 
 451         rval = ql_setup_mbox_dma_transfer(ha, &mem_desc,
 452             (caddr_t)&ha->ip_init_ctrl_blk, sizeof (ql_comb_ip_init_cb_t));
 453         if (rval != QL_SUCCESS) {
 454                 EL(ha, "failed, setup_mbox_dma_transfer: %xh\n", rval);
 455                 return (rval);
 456         }
 457 
 458         mcp->mb[0] = MBC_INITIALIZE_IP;
 459         mcp->mb[2] = MSW(LSD(mem_desc.cookie.dmac_laddress));
 460         mcp->mb[3] = LSW(LSD(mem_desc.cookie.dmac_laddress));
 461         mcp->mb[6] = MSW(MSD(mem_desc.cookie.dmac_laddress));
 462         mcp->mb[7] = LSW(MSD(mem_desc.cookie.dmac_laddress));
 463         mcp->mb[8] = 0;
 464         mcp->out_mb = MBX_8|MBX_7|MBX_6|MBX_3|MBX_2|MBX_0;
 465         mcp->in_mb = MBX_8|MBX_0;
 466         mcp->timeout = MAILBOX_TOV;
 467         rval = ql_mailbox_command(ha, mcp);
 468 
 469         ql_free_dma_resource(ha, &mem_desc);
 470 
 471         if (rval == QL_SUCCESS) {
 472                 ADAPTER_STATE_LOCK(ha);
 473                 ha->flags |= IP_INITIALIZED;
 474                 ADAPTER_STATE_UNLOCK(ha);
 475                 QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
 476         } else {
 477                 ha->flags &= ~IP_INITIALIZED;
 478                 EL(ha, "failed, rval = %xh\n", rval);
 479         }
 480         return (rval);
 481 }
 482 
 483 /*
 484  * ql_shutdown_ip
 485  *      Disconnects firmware IP from system buffers.
 486  *
 487  * Input:
 488  *      ha = adapter state pointer.
 489  *
 490  * Returns:
 491  *      ql local function return status code.
 492  *
 493  * Context:
 494  *      Kernel context.
 495  */
 496 int
 497 ql_shutdown_ip(ql_adapter_state_t *ha)
 498 {
 499         int             rval;
 500         mbx_cmd_t       mc = {0};
 501         mbx_cmd_t       *mcp = &mc;
 502         fc_unsol_buf_t  *ubp;
 503         ql_srb_t        *sp;
 504         uint16_t        index;
 505 
 506         QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
 507 
 508         mcp->mb[0] = MBC_UNLOAD_IP;
 509         mcp->out_mb = MBX_0;
 510         mcp->in_mb = MBX_0;
 511         mcp->timeout = MAILBOX_TOV;
 512         rval = ql_mailbox_command(ha, mcp);
 513 
 514         ADAPTER_STATE_LOCK(ha);
 515         QL_UB_LOCK(ha);
 516         /* Return all unsolicited buffers that ISP-IP has. */
 517         for (index = 0; index < QL_UB_LIMIT; index++) {
 518                 ubp = ha->ub_array[index];
 519                 if (ubp != NULL) {
 520                         sp = ubp->ub_fca_private;
 521                         sp->flags &= ~SRB_UB_IN_ISP;
 522                 }
 523         }
 524 
 525         ha->ub_outcnt = 0;
 526         QL_UB_UNLOCK(ha);
 527         ha->flags &= ~IP_INITIALIZED;
 528         ADAPTER_STATE_UNLOCK(ha);
 529 
 530         if (rval == QL_SUCCESS) {
 531                 /* EMPTY - no need to check return value of MBC_SHUTDOWN_IP */
 532                 QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
 533         } else {
 534                 EL(ha, "failed, rval = %xh\n", rval);
 535         }
 536         return (rval);
 537 }
 538 
 539 /*
 540  * ql_online_selftest
 541  *      Issue online self test mailbox command.
 542  *
 543  * Input:
 544  *      ha = adapter state pointer.
 545  *
 546  * Returns:
 547  *      ql local function return status code.
 548  *
 549  * Context:
 550  *      Kernel context.
 551  */
 552 int
 553 ql_online_selftest(ql_adapter_state_t *ha)
 554 {
 555         int             rval;
 556         mbx_cmd_t       mc = {0};
 557         mbx_cmd_t       *mcp = &mc;
 558 
 559         QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
 560 
 561         mcp->mb[0] = MBC_ONLINE_SELF_TEST;
 562         mcp->out_mb = MBX_0;
 563         mcp->in_mb = MBX_0 | MBX_1 | MBX_2 | MBX_3;
 564         mcp->timeout = MAILBOX_TOV;
 565         rval = ql_mailbox_command(ha, mcp);
 566 
 567         if (rval != QL_SUCCESS) {
 568                 EL(ha, "failed, rval = %xh, mb1=%xh, mb2=%xh, mb3=%xh\n",
 569                     rval, mcp->mb[1], mcp->mb[2], mcp->mb[3]);
 570         } else {
 571                 /*EMPTY*/
 572                 QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
 573         }
 574         return (rval);
 575 }
 576 
 577 /*
 578  * ql_loop_back
 579  *      Issue diagnostic loop back frame mailbox command.
 580  *
 581  * Input:
 582  *      ha:     adapter state pointer.
 583  *      findex: FCF index.
 584  *      lb:     loop back parameter structure pointer.
 585  *
 586  * Returns:
 587  *      ql local function return status code.
 588  *
 589  * Context:
 590  *      Kernel context.
 591  */
 592 #ifndef apps_64bit
 593 int
 594 ql_loop_back(ql_adapter_state_t *ha, uint16_t findex, lbp_t *lb,
 595     uint32_t h_xmit, uint32_t h_rcv)
 596 {
 597         int             rval;
 598         mbx_cmd_t       mc = {0};
 599         mbx_cmd_t       *mcp = &mc;
 600 
 601         QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
 602 
 603         mcp->mb[0] = MBC_DIAGNOSTIC_LOOP_BACK;
 604         mcp->mb[1] = lb->options;
 605         mcp->mb[2] = findex;
 606         mcp->mb[6] = LSW(h_rcv);
 607         mcp->mb[7] = MSW(h_rcv);
 608         mcp->mb[10] = LSW(lb->transfer_count);
 609         mcp->mb[11] = MSW(lb->transfer_count);
 610         mcp->mb[12] = lb->transfer_segment_count;
 611         mcp->mb[13] = lb->receive_segment_count;
 612         mcp->mb[14] = LSW(lb->transfer_data_address);
 613         mcp->mb[15] = MSW(lb->transfer_data_address);
 614         mcp->mb[16] = LSW(lb->receive_data_address);
 615         mcp->mb[17] = MSW(lb->receive_data_address);
 616         mcp->mb[18] = LSW(lb->iteration_count);
 617         mcp->mb[19] = MSW(lb->iteration_count);
 618         mcp->mb[20] = LSW(h_xmit);
 619         mcp->mb[21] = MSW(h_xmit);
 620         mcp->out_mb = MBX_21|MBX_20|MBX_19|MBX_18|MBX_17|MBX_16|MBX_15|
 621             MBX_14|MBX_13|MBX_12|MBX_11|MBX_10|MBX_7|MBX_6|MBX_2|MBX_1|MBX_0;
 622         mcp->in_mb = MBX_19|MBX_18|MBX_3|MBX_2|MBX_1|MBX_0;
 623         mcp->timeout = lb->iteration_count / 300;
 624 
 625         if (mcp->timeout < MAILBOX_TOV) {
 626                 mcp->timeout = MAILBOX_TOV;
 627         }
 628 
 629         rval = ql_mailbox_command(ha, mcp);
 630 
 631         if (rval != QL_SUCCESS) {
 632                 EL(ha, "failed, rval = %xh, mb1=%xh, mb2=%xh, mb3=%xh\n",
 633                     rval, mcp->mb[1], mcp->mb[2], mcp->mb[3]);
 634         } else {
 635                 /*EMPTY*/
 636                 QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
 637         }
 638         return (rval);
 639 }
 640 #else
 641 int
 642 ql_loop_back(ql_adapter_state_t *ha, uint16_t findex, lbp_t *lb)
 643 {
 644         int             rval;
 645         mbx_cmd_t       mc = {0};
 646         mbx_cmd_t       *mcp = &mc;
 647 
 648         QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
 649 
 650         mcp->mb[0] = MBC_DIAGNOSTIC_LOOP_BACK;
 651         mcp->mb[1] = lb->options;
 652         mcp->mb[2] = findex;
 653         mcp->mb[6] = LSW(h_rcv);
 654         mcp->mb[7] = MSW(h_rcv);
 655         mcp->mb[6] = LSW(MSD(lb->receive_data_address));
 656         mcp->mb[7] = MSW(MSD(lb->receive_data_address));
 657         mcp->mb[10] = LSW(lb->transfer_count);
 658         mcp->mb[11] = MSW(lb->transfer_count);
 659         mcp->mb[12] = lb->transfer_segment_count;
 660         mcp->mb[13] = lb->receive_segment_count;
 661         mcp->mb[14] = LSW(lb->transfer_data_address);
 662         mcp->mb[15] = MSW(lb->transfer_data_address);
 663         mcp->mb[14] = LSW(LSD(lb->transfer_data_address));
 664         mcp->mb[15] = MSW(LSD(lb->transfer_data_address));
 665         mcp->mb[16] = LSW(lb->receive_data_address);
 666         mcp->mb[17] = MSW(lb->receive_data_address);
 667         mcp->mb[16] = LSW(LSD(lb->receive_data_address));
 668         mcp->mb[17] = MSW(LSD(lb->receive_data_address));
 669         mcp->mb[18] = LSW(lb->iteration_count);
 670         mcp->mb[19] = MSW(lb->iteration_count);
 671         mcp->mb[20] = LSW(h_xmit);
 672         mcp->mb[21] = MSW(h_xmit);
 673         mcp->mb[20] = LSW(MSD(lb->transfer_data_address));
 674         mcp->mb[21] = MSW(MSD(lb->transfer_data_address));
 675         mcp->out_mb = MBX_21|MBX_20|MBX_19|MBX_18|MBX_17|MBX_16|MBX_15|
 676             MBX_14|MBX_13|MBX_12|MBX_11|MBX_10|MBX_7|MBX_6|MBX_2|MBX_1|MBX_0;
 677         mcp->in_mb = MBX_19|MBX_18|MBX_3|MBX_2|MBX_1|MBX_0;
 678         mcp->timeout = lb->iteration_count / 300;
 679 
 680         if (mcp->timeout < MAILBOX_TOV) {
 681                 mcp->timeout = MAILBOX_TOV;
 682         }
 683 
 684         rval = ql_mailbox_command(ha, mcp);
 685 
 686         if (rval != QL_SUCCESS) {
 687                 EL(ha, "failed, rval = %xh\n", rval);
 688         } else {
 689                 /*EMPTY*/
 690                 QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
 691         }
 692         return (rval);
 693 }
 694 #endif
 695 
 696 /*
 697  * ql_echo
 698  *      Issue an ELS echo using the user specified data to a user specified
 699  *      destination
 700  *
 701  * Input:
 702  *      ha:             adapter state pointer.
 703  *      findex:         FCF index.
 704  *      echo_pt:        echo parameter structure pointer.
 705  *
 706  * Returns:
 707  *      ql local function return status code.
 708  *
 709  * Context:
 710  *      Kernel context.
 711  */
 712 int
 713 ql_echo(ql_adapter_state_t *ha, uint16_t findex, echo_t *echo_pt)
 714 {
 715         int             rval;
 716         mbx_cmd_t       mc = {0};
 717         mbx_cmd_t       *mcp = &mc;
 718 
 719         QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
 720 
 721         mcp->mb[0] = MBC_ECHO;                       /* ECHO command */
 722         mcp->mb[1] = echo_pt->options;            /* command options; 64 bit */
 723                                                 /* addressing (bit 6) and */
 724                                                 /* real echo (bit 15 */
 725         mcp->mb[2] = findex;
 726 
 727         /*
 728          * I know this looks strange, using a field labled "not used"
 729          * The way the ddi_dma_cookie_t structure/union is defined
 730          * is a union of one 64 bit entity with an array of two 32
 731          * bit enititys.  Since we have routines to convert 32 bit
 732          * entities into 16 bit entities it is easier to use
 733          * both 32 bit union members then the one 64 bit union
 734          * member
 735          */
 736         if (echo_pt->options & BIT_6) {
 737                 /* 64 bit addressing */
 738                 /* Receive data dest add in system memory bits 47-32 */
 739                 mcp->mb[6] = LSW(echo_pt->receive_data_address.dmac_notused);
 740 
 741                 /* Receive data dest add in system memory bits 63-48 */
 742                 mcp->mb[7] = MSW(echo_pt->receive_data_address.dmac_notused);
 743 
 744                 /* Transmit data source address in system memory bits 47-32 */
 745                 mcp->mb[20] = LSW(echo_pt->transfer_data_address.dmac_notused);
 746 
 747                 /* Transmit data source address in system memory bits 63-48 */
 748                 mcp->mb[21] = MSW(echo_pt->transfer_data_address.dmac_notused);
 749         }
 750 
 751         /* transfer count bits 15-0 */
 752         mcp->mb[10] = LSW(echo_pt->transfer_count);
 753 
 754         /* Transmit data source address in system memory bits 15-0 */
 755         mcp->mb[14] = LSW(echo_pt->transfer_data_address.dmac_address);
 756 
 757         /*  Transmit data source address in system memory bits 31-16 */
 758         mcp->mb[15] = MSW(echo_pt->transfer_data_address.dmac_address);
 759 
 760         /* Receive data destination address in system memory bits 15-0 */
 761         mcp->mb[16] = LSW(echo_pt->receive_data_address.dmac_address);
 762 
 763         /*  Receive data destination address in system memory bits 31-16 */
 764         mcp->mb[17] = MSW(echo_pt->receive_data_address.dmac_address);
 765 
 766         mcp->out_mb = MBX_21|MBX_20|MBX_17|MBX_16|MBX_15|MBX_14|MBX_10|
 767             MBX_7|MBX_6|MBX_2|MBX_1|MBX_0;
 768         mcp->in_mb = MBX_3|MBX_1|MBX_0;
 769         mcp->timeout = MAILBOX_TOV;
 770 
 771         rval = ql_mailbox_command(ha, mcp);
 772 
 773         if (rval != QL_SUCCESS) {
 774                 EL(ha, "failed, rval = %xh\n", rval);
 775         } else {
 776                 /*EMPTY*/
 777                 QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
 778         }
 779         return (rval);
 780 }
 781 
 782 /*
 783  * ql_send_change_request
 784  *      Issue send change request mailbox command.
 785  *
 786  * Input:
 787  *      ha:     adapter state pointer.
 788  *      fmt:    Registration format.
 789  *
 790  * Returns:
 791  *      ql local function return status code.
 792  *
 793  * Context:
 794  *      Kernel context.
 795  */
 796 int
 797 ql_send_change_request(ql_adapter_state_t *ha, uint16_t fmt)
 798 {
 799         int             rval;
 800         mbx_cmd_t       mc = {0};
 801         mbx_cmd_t       *mcp = &mc;
 802 
 803         QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
 804 
 805         mcp->mb[0] = MBC_SEND_CHANGE_REQUEST;
 806         mcp->mb[1] = fmt;
 807         mcp->out_mb = MBX_1|MBX_0;
 808         if (ha->flags & VP_ENABLED) {
 809                 mcp->mb[9] = ha->vp_index;
 810                 mcp->out_mb |= MBX_9;
 811         }
 812         mcp->in_mb = MBX_0;
 813         mcp->timeout = MAILBOX_TOV;
 814         rval = ql_mailbox_command(ha, mcp);
 815 
 816         if (rval != QL_SUCCESS) {
 817                 EL(ha, "failed=%xh\n", rval);
 818         } else {
 819                 /*EMPTY*/
 820                 QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
 821         }
 822         return (rval);
 823 }
 824 
 825 /*
 826  * ql_send_lfa
 827  *      Send a Loop Fabric Address mailbox command.
 828  *
 829  * Input:
 830  *      ha:     adapter state pointer.
 831  *      lfa:    LFA command structure pointer.
 832  *
 833  * Returns:
 834  *      ql local function return status code.
 835  *
 836  * Context:
 837  *      Kernel context.
 838  */
 839 int
 840 ql_send_lfa(ql_adapter_state_t *ha, lfa_cmd_t *lfa)
 841 {
 842         int             rval;
 843         uint16_t        size;
 844         dma_mem_t       mem_desc;
 845         mbx_cmd_t       mc = {0};
 846         mbx_cmd_t       *mcp = &mc;
 847 
 848         QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
 849 
 850         /* LFA_CB sz = 4 16bit words subcommand + 10 16bit words header. */
 851         size = (uint16_t)((lfa->subcommand_length[0] + 10) << 1);
 852 
 853         rval = ql_setup_mbox_dma_transfer(ha, &mem_desc, (caddr_t)lfa, size);
 854         if (rval != QL_SUCCESS) {
 855                 EL(ha, "failed, setup_mbox_dma_transfer: %xh\n", rval);
 856                 return (rval);
 857         }
 858 
 859         mcp->mb[0] = MBC_SEND_LFA_COMMAND;
 860         mcp->mb[1] = (uint16_t)(size >> 1);
 861         mcp->mb[2] = MSW(LSD(mem_desc.cookie.dmac_laddress));
 862         mcp->mb[3] = LSW(LSD(mem_desc.cookie.dmac_laddress));
 863         mcp->mb[6] = MSW(MSD(mem_desc.cookie.dmac_laddress));
 864         mcp->mb[7] = LSW(MSD(mem_desc.cookie.dmac_laddress));
 865         mcp->in_mb = MBX_0;
 866         mcp->out_mb = MBX_7|MBX_6|MBX_3|MBX_2|MBX_1|MBX_0;
 867         if (ha->flags & VP_ENABLED) {
 868                 mcp->mb[9] = ha->vp_index;
 869                 mcp->out_mb |= MBX_9;
 870         }
 871         mcp->timeout = MAILBOX_TOV;
 872         rval = ql_mailbox_command(ha, mcp);
 873 
 874         ql_free_dma_resource(ha, &mem_desc);
 875 
 876         if (rval != QL_SUCCESS) {
 877                 EL(ha, "failed, rval = %xh\n", rval);
 878         } else {
 879                 /*EMPTY*/
 880                 QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
 881         }
 882 
 883         return (rval);
 884 }
 885 
 886 /*
 887  * ql_clear_aca
 888  *      Issue clear ACA mailbox command.
 889  *
 890  * Input:
 891  *      ha:     adapter state pointer.
 892  *      tq:     target queue pointer.
 893  *      lun:    LUN.
 894  *
 895  * Returns:
 896  *      ql local function return status code.
 897  *
 898  * Context:
 899  *      Kernel context.
 900  */
 901 int
 902 ql_clear_aca(ql_adapter_state_t *ha, ql_tgt_t *tq, uint16_t lun)
 903 {
 904         int             rval;
 905         mbx_cmd_t       mc = {0};
 906         mbx_cmd_t       *mcp = &mc;
 907 
 908         QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
 909 
 910         if (CFG_IST(ha, CFG_CTRL_24258081)) {
 911                 rval = ql_task_mgmt_iocb(ha, tq, lun, CF_CLEAR_ACA, 0);
 912         } else {
 913                 mcp->mb[0] = MBC_CLEAR_ACA;
 914                 if (CFG_IST(ha, CFG_EXT_FW_INTERFACE)) {
 915                         mcp->mb[1] = tq->loop_id;
 916                 } else {
 917                         mcp->mb[1] = (uint16_t)(tq->loop_id << 8);
 918                 }
 919                 mcp->mb[2] = lun;
 920                 mcp->out_mb = MBX_2|MBX_1|MBX_0;
 921                 mcp->in_mb = MBX_0;
 922                 mcp->timeout = MAILBOX_TOV;
 923                 rval = ql_mailbox_command(ha, mcp);
 924         }
 925 
 926         (void) ql_marker(ha, tq->loop_id, lun, MK_SYNC_ID);
 927 
 928         if (rval != QL_SUCCESS) {
 929                 EL(ha, "failed, rval = %xh\n", rval);
 930         } else {
 931                 /*EMPTY*/
 932                 QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
 933         }
 934 
 935         return (rval);
 936 }
 937 
 938 /*
 939  * ql_target_reset
 940  *      Issue target reset mailbox command.
 941  *
 942  * Input:
 943  *      ha:     adapter state pointer.
 944  *      tq:     target queue pointer.
 945  *      delay:  seconds.
 946  *
 947  * Returns:
 948  *      ql local function return status code.
 949  *
 950  * Context:
 951  *      Kernel context.
 952  */
 953 int
 954 ql_target_reset(ql_adapter_state_t *ha, ql_tgt_t *tq, uint16_t delay)
 955 {
 956         ql_link_t       *link;
 957         uint16_t        index;
 958         int             rval;
 959         mbx_cmd_t       mc = {0};
 960         mbx_cmd_t       *mcp = &mc;
 961 
 962         QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
 963 
 964         if (CFG_IST(ha, CFG_CTRL_24258081)) {
 965                 /* queue = NULL, all targets. */
 966                 if (tq == NULL) {
 967                         for (index = 0; index < DEVICE_HEAD_LIST_SIZE;
 968                             index++) {
 969                                 for (link = ha->dev[index].first; link !=
 970                                     NULL; link = link->next) {
 971                                         tq = link->base_address;
 972                                         if (!VALID_DEVICE_ID(ha,
 973                                             tq->loop_id)) {
 974                                                 continue;
 975                                         }
 976 
 977                                         if (CFG_IST(ha, CFG_FAST_TIMEOUT)) {
 978                                                 rval = ql_task_mgmt_iocb(ha,
 979                                                     tq, 0, CF_DO_NOT_SEND |
 980                                                     CF_TARGET_RESET, delay);
 981                                         } else {
 982                                                 rval = ql_task_mgmt_iocb(ha,
 983                                                     tq, 0, CF_TARGET_RESET,
 984                                                     delay);
 985                                         }
 986 
 987                                         if (rval != QL_SUCCESS) {
 988                                                 break;
 989                                         }
 990                                 }
 991 
 992                                 if (link != NULL) {
 993                                         break;
 994                                 }
 995                         }
 996                         tq = NULL;
 997                 } else {
 998 
 999                         if (CFG_IST(ha, CFG_FAST_TIMEOUT)) {
1000                                 rval = ql_task_mgmt_iocb(ha, tq, 0,
1001                                     CF_TARGET_RESET | CF_DO_NOT_SEND, delay);
1002                         } else {
1003                                 rval = ql_task_mgmt_iocb(ha, tq, 0,
1004                                     CF_TARGET_RESET, delay);
1005                         }
1006                 }
1007         } else {
1008                 /* queue = NULL, all targets. */
1009                 if (tq == NULL) {
1010                         mcp->mb[0] = MBC_RESET;
1011                         mcp->mb[1] = delay;
1012                         mcp->out_mb = MBX_1|MBX_0;
1013                 } else {
1014                         mcp->mb[0] = MBC_TARGET_RESET;
1015                         if (CFG_IST(ha, CFG_EXT_FW_INTERFACE)) {
1016                                 mcp->mb[1] = tq->loop_id;
1017                         } else {
1018                                 mcp->mb[1] = (uint16_t)(tq->loop_id << 8);
1019                         }
1020                         mcp->mb[2] = delay;
1021                         mcp->out_mb = MBX_2|MBX_1|MBX_0;
1022                 }
1023                 mcp->in_mb = MBX_0;
1024                 mcp->timeout = MAILBOX_TOV;
1025                 rval = ql_mailbox_command(ha, mcp);
1026         }
1027 
1028         tq == NULL ? (void) ql_marker(ha, 0, 0, MK_SYNC_ALL) :
1029             (void) ql_marker(ha, tq->loop_id, 0, MK_SYNC_ID);
1030 
1031         if (rval != QL_SUCCESS) {
1032                 EL(ha, "failed, rval = %xh\n", rval);
1033         } else {
1034                 /*EMPTY*/
1035                 QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
1036         }
1037 
1038         return (rval);
1039 }
1040 
1041 /*
1042  * ql_abort_target
1043  *      Issue abort target mailbox command.
1044  *
1045  * Input:
1046  *      ha:     adapter state pointer.
1047  *      tq:     target queue pointer.
1048  *      delay:  in seconds.
1049  *
1050  * Returns:
1051  *      ql local function return status code.
1052  *
1053  * Context:
1054  *      Kernel context.
1055  */
1056 int
1057 ql_abort_target(ql_adapter_state_t *ha, ql_tgt_t *tq, uint16_t delay)
1058 {
1059         int             rval;
1060         mbx_cmd_t       mc = {0};
1061         mbx_cmd_t       *mcp = &mc;
1062 
1063         QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
1064 
1065         if (CFG_IST(ha, CFG_CTRL_24258081)) {
1066                 rval = ql_task_mgmt_iocb(ha, tq, 0,
1067                     CF_DO_NOT_SEND | CF_TARGET_RESET, delay);
1068         } else {
1069                 mcp->mb[0] = MBC_ABORT_TARGET;
1070                 /* Don't send Task Mgt */
1071                 if (CFG_IST(ha, CFG_EXT_FW_INTERFACE)) {
1072                         mcp->mb[1] = tq->loop_id;
1073                         mcp->mb[10] = BIT_0;
1074                         mcp->out_mb = MBX_10|MBX_2|MBX_1|MBX_0;
1075                 } else {
1076                         mcp->mb[1] = (uint16_t)(tq->loop_id << 8 | BIT_0);
1077                         mcp->out_mb = MBX_2|MBX_1|MBX_0;
1078                 }
1079                 mcp->mb[2] = delay;
1080                 mcp->in_mb = MBX_0;
1081                 mcp->timeout = MAILBOX_TOV;
1082                 rval = ql_mailbox_command(ha, mcp);
1083         }
1084 
1085         (void) ql_marker(ha, tq->loop_id, 0, MK_SYNC_ID);
1086 
1087         if (rval != QL_SUCCESS) {
1088                 EL(ha, "failed=%xh, d_id=%xh\n", rval, tq->d_id.b24);
1089         } else {
1090                 /*EMPTY*/
1091                 QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
1092         }
1093         return (rval);
1094 }
1095 
1096 /*
1097  * ql_lun_reset
1098  *      Issue LUN reset task management mailbox command.
1099  *
1100  * Input:
1101  *      ha:     adapter state pointer.
1102  *      tq:     target queue pointer.
1103  *      lun:    LUN.
1104  *
1105  * Returns:
1106  *      ql local function return status code.
1107  *
1108  * Context:
1109  *      Kernel context.
1110  */
1111 int
1112 ql_lun_reset(ql_adapter_state_t *ha, ql_tgt_t *tq, uint16_t lun)
1113 {
1114         int             rval;
1115         mbx_cmd_t       mc = {0};
1116         mbx_cmd_t       *mcp = &mc;
1117 
1118         QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
1119 
1120         if (CFG_IST(ha, CFG_CTRL_24258081)) {
1121                 rval = ql_task_mgmt_iocb(ha, tq, lun, CF_LUN_RESET, 0);
1122         } else {
1123                 mcp->mb[0] = MBC_LUN_RESET;
1124                 if (CFG_IST(ha, CFG_EXT_FW_INTERFACE)) {
1125                         mcp->mb[1] = tq->loop_id;
1126                 } else {
1127                         mcp->mb[1] = (uint16_t)(tq->loop_id << 8);
1128                 }
1129                 mcp->mb[2] = lun;
1130                 mcp->out_mb = MBX_3|MBX_2|MBX_1|MBX_0;
1131                 mcp->in_mb = MBX_0;
1132                 mcp->timeout = MAILBOX_TOV;
1133                 rval = ql_mailbox_command(ha, mcp);
1134         }
1135 
1136         (void) ql_marker(ha, tq->loop_id, lun, MK_SYNC_ID);
1137 
1138         if (rval != QL_SUCCESS) {
1139                 EL(ha, "failed=%xh, d_id=%xh\n", rval, tq->d_id.b24);
1140         } else {
1141                 /*EMPTY*/
1142                 QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
1143         }
1144         return (rval);
1145 }
1146 
1147 /*
1148  * ql_clear_task_set
1149  *      Issue clear task set mailbox command.
1150  *
1151  * Input:
1152  *      ha:     adapter state pointer.
1153  *      tq:     target queue pointer.
1154  *      lun:    LUN.
1155  *
1156  * Returns:
1157  *      ql local function return status code.
1158  *
1159  * Context:
1160  *      Kernel context.
1161  */
1162 int
1163 ql_clear_task_set(ql_adapter_state_t *ha, ql_tgt_t *tq, uint16_t lun)
1164 {
1165         int             rval;
1166         mbx_cmd_t       mc = {0};
1167         mbx_cmd_t       *mcp = &mc;
1168 
1169         QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
1170 
1171         if (CFG_IST(ha, CFG_CTRL_24258081)) {
1172                 rval = ql_task_mgmt_iocb(ha, tq, lun, CF_CLEAR_TASK_SET, 0);
1173         } else {
1174                 mcp->mb[0] = MBC_CLEAR_TASK_SET;
1175                 if (CFG_IST(ha, CFG_EXT_FW_INTERFACE)) {
1176                         mcp->mb[1] = tq->loop_id;
1177                 } else {
1178                         mcp->mb[1] = (uint16_t)(tq->loop_id << 8);
1179                 }
1180                 mcp->mb[2] = lun;
1181                 mcp->out_mb = MBX_2|MBX_1|MBX_0;
1182                 mcp->in_mb = MBX_0;
1183                 mcp->timeout = MAILBOX_TOV;
1184                 rval = ql_mailbox_command(ha, mcp);
1185         }
1186 
1187         (void) ql_marker(ha, tq->loop_id, lun, MK_SYNC_ID);
1188 
1189         if (rval != QL_SUCCESS) {
1190                 EL(ha, "failed=%xh, d_id=%xh\n", rval, tq->d_id.b24);
1191         } else {
1192                 /*EMPTY*/
1193                 QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
1194         }
1195 
1196         return (rval);
1197 }
1198 
1199 /*
1200  * ql_abort_task_set
1201  *      Issue abort task set mailbox command.
1202  *
1203  * Input:
1204  *      ha:     adapter state pointer.
1205  *      tq:     target queue pointer.
1206  *      lun:    LUN.
1207  *
1208  * Returns:
1209  *      ql local function return status code.
1210  *
1211  * Context:
1212  *      Kernel context.
1213  */
1214 int
1215 ql_abort_task_set(ql_adapter_state_t *ha, ql_tgt_t *tq, uint16_t lun)
1216 {
1217         int             rval;
1218         mbx_cmd_t       mc = {0};
1219         mbx_cmd_t       *mcp = &mc;
1220 
1221         QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
1222 
1223         if (CFG_IST(ha, CFG_CTRL_24258081)) {
1224                 rval = ql_task_mgmt_iocb(ha, tq, lun, CF_ABORT_TASK_SET, 0);
1225         } else {
1226                 mcp->mb[0] = MBC_ABORT_TASK_SET;
1227                 if (CFG_IST(ha, CFG_EXT_FW_INTERFACE)) {
1228                         mcp->mb[1] = tq->loop_id;
1229                 } else {
1230                         mcp->mb[1] = (uint16_t)(tq->loop_id << 8);
1231                 }
1232                 mcp->mb[2] = lun;
1233                 mcp->out_mb = MBX_2|MBX_1|MBX_0;
1234                 mcp->in_mb = MBX_0;
1235                 mcp->timeout = MAILBOX_TOV;
1236                 rval = ql_mailbox_command(ha, mcp);
1237         }
1238 
1239         (void) ql_marker(ha, tq->loop_id, lun, MK_SYNC_ID);
1240 
1241         if (rval != QL_SUCCESS) {
1242                 EL(ha, "failed=%xh, d_id=%xh\n", rval, tq->d_id.b24);
1243         } else {
1244                 /*EMPTY*/
1245                 QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
1246         }
1247 
1248         return (rval);
1249 }
1250 
1251 /*
1252  * ql_task_mgmt_iocb
1253  *      Function issues task management IOCB.
1254  *
1255  * Input:
1256  *      ha:     adapter state pointer.
1257  *      tq:     target queue pointer.
1258  *      lun:    LUN.
1259  *      flags:  control flags.
1260  *      delay:  seconds.
1261  *
1262  * Returns:
1263  *      ql local function return status code.
1264  *
1265  * Context:
1266  *      Kernel context
1267  */
1268 static int
1269 ql_task_mgmt_iocb(ql_adapter_state_t *ha, ql_tgt_t *tq, uint16_t lun,
1270     uint32_t flags, uint16_t delay)
1271 {
1272         ql_mbx_iocb_t   *pkt;
1273         int             rval;
1274         uint32_t        pkt_size;
1275 
1276         QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
1277 
1278         pkt_size = sizeof (ql_mbx_iocb_t);
1279         pkt = kmem_zalloc(pkt_size, KM_SLEEP);
1280         if (pkt == NULL) {
1281                 EL(ha, "failed, kmem_zalloc\n");
1282                 return (QL_MEMORY_ALLOC_FAILED);
1283         }
1284 
1285         pkt->mgmt.entry_type = TASK_MGMT_TYPE;
1286         pkt->mgmt.entry_count = 1;
1287 
1288         pkt->mgmt.n_port_hdl = (uint16_t)LE_16(tq->loop_id);
1289         pkt->mgmt.delay = (uint16_t)LE_16(delay);
1290         pkt->mgmt.timeout = LE_16(MAILBOX_TOV);
1291         pkt->mgmt.fcp_lun[2] = LSB(lun);
1292         pkt->mgmt.fcp_lun[3] = MSB(lun);
1293         pkt->mgmt.control_flags = LE_32(flags);
1294         pkt->mgmt.target_id[0] = tq->d_id.b.al_pa;
1295         pkt->mgmt.target_id[1] = tq->d_id.b.area;
1296         pkt->mgmt.target_id[2] = tq->d_id.b.domain;
1297         pkt->mgmt.vp_index = ha->vp_index;
1298 
1299         rval = ql_issue_mbx_iocb(ha, (caddr_t)pkt, pkt_size);
1300         if (rval == QL_SUCCESS && (pkt->sts24.entry_status & 0x3c) != 0) {
1301                 EL(ha, "failed, entry_status=%xh, d_id=%xh\n",
1302                     pkt->sts24.entry_status, tq->d_id.b24);
1303                 rval = QL_FUNCTION_PARAMETER_ERROR;
1304         }
1305 
1306         LITTLE_ENDIAN_16(&pkt->sts24.comp_status);
1307 
1308         if (rval == QL_SUCCESS && pkt->sts24.comp_status != CS_COMPLETE) {
1309                 EL(ha, "failed, comp_status=%xh, d_id=%xh\n",
1310                     pkt->sts24.comp_status, tq->d_id.b24);
1311                 rval = QL_FUNCTION_FAILED;
1312         }
1313 
1314         kmem_free(pkt, pkt_size);
1315 
1316         if (rval != QL_SUCCESS) {
1317                 EL(ha, "failed, rval = %xh\n", rval);
1318         } else {
1319                 /*EMPTY*/
1320                 QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
1321         }
1322 
1323         return (rval);
1324 }
1325 
1326 /*
1327  * ql_loop_port_bypass
1328  *      Issue loop port bypass mailbox command.
1329  *
1330  * Input:
1331  *      ha:     adapter state pointer.
1332  *      tq:     target queue pointer.
1333  *
1334  * Returns:
1335  *      ql local function return status code.
1336  *
1337  * Context:
1338  *      Kernel context.
1339  */
1340 int
1341 ql_loop_port_bypass(ql_adapter_state_t *ha, ql_tgt_t *tq)
1342 {
1343         int             rval;
1344         mbx_cmd_t       mc = {0};
1345         mbx_cmd_t       *mcp = &mc;
1346 
1347         QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
1348 
1349         mcp->mb[0] = MBC_LOOP_PORT_BYPASS;
1350 
1351         if (CFG_IST(ha, CFG_CTRL_24258081)) {
1352                 mcp->mb[1] = tq->d_id.b.al_pa;
1353         } else if (CFG_IST(ha, CFG_EXT_FW_INTERFACE)) {
1354                 mcp->mb[1] = tq->loop_id;
1355         } else {
1356                 mcp->mb[1] = (uint16_t)(tq->loop_id << 8);
1357         }
1358 
1359         mcp->out_mb = MBX_1|MBX_0;
1360         mcp->in_mb = MBX_0;
1361         mcp->timeout = MAILBOX_TOV;
1362         rval = ql_mailbox_command(ha, mcp);
1363 
1364         if (rval != QL_SUCCESS) {
1365                 EL(ha, "failed=%xh, d_id=%xh\n", rval, tq->d_id.b24);
1366         } else {
1367                 /*EMPTY*/
1368                 QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
1369         }
1370 
1371         return (rval);
1372 }
1373 
1374 /*
1375  * ql_loop_port_enable
1376  *      Issue loop port enable mailbox command.
1377  *
1378  * Input:
1379  *      ha:     adapter state pointer.
1380  *      tq:     target queue pointer.
1381  *
1382  * Returns:
1383  *      ql local function return status code.
1384  *
1385  * Context:
1386  *      Kernel context.
1387  */
1388 int
1389 ql_loop_port_enable(ql_adapter_state_t *ha, ql_tgt_t *tq)
1390 {
1391         int             rval;
1392         mbx_cmd_t       mc = {0};
1393         mbx_cmd_t       *mcp = &mc;
1394 
1395         QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
1396 
1397         mcp->mb[0] = MBC_LOOP_PORT_ENABLE;
1398 
1399         if (CFG_IST(ha, CFG_CTRL_24258081)) {
1400                 mcp->mb[1] = tq->d_id.b.al_pa;
1401         } else if (CFG_IST(ha, CFG_EXT_FW_INTERFACE)) {
1402                 mcp->mb[1] = tq->loop_id;
1403         } else {
1404                 mcp->mb[1] = (uint16_t)(tq->loop_id << 8);
1405         }
1406         mcp->out_mb = MBX_1|MBX_0;
1407         mcp->in_mb = MBX_0;
1408         mcp->timeout = MAILBOX_TOV;
1409         rval = ql_mailbox_command(ha, mcp);
1410 
1411         if (rval != QL_SUCCESS) {
1412                 EL(ha, "failed=%xh, d_id=%xh\n", rval, tq->d_id.b24);
1413         } else {
1414                 /*EMPTY*/
1415                 QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
1416         }
1417 
1418         return (rval);
1419 }
1420 
1421 /*
1422  * ql_login_lport
1423  *      Issue login loop port mailbox command.
1424  *
1425  * Input:
1426  *      ha:             adapter state pointer.
1427  *      tq:             target queue pointer.
1428  *      loop_id:        FC loop id.
1429  *      opt:            options.
1430  *                      LLF_NONE, LLF_PLOGI
1431  *
1432  * Returns:
1433  *      ql local function return status code.
1434  *
1435  * Context:
1436  *      Kernel context.
1437  */
1438 int
1439 ql_login_lport(ql_adapter_state_t *ha, ql_tgt_t *tq, uint16_t loop_id,
1440     uint16_t opt)
1441 {
1442         int             rval;
1443         uint16_t        flags;
1444         ql_mbx_data_t   mr;
1445         mbx_cmd_t       mc = {0};
1446         mbx_cmd_t       *mcp = &mc;
1447 
1448         QL_PRINT_3(CE_CONT, "(%d): started, d_id=%xh, loop_id=%xh\n",
1449             ha->instance, tq->d_id.b24, loop_id);
1450 
1451         if (CFG_IST(ha, CFG_CTRL_24258081)) {
1452                 flags = CF_CMD_PLOGI;
1453                 if ((opt & LLF_PLOGI) == 0) {
1454                         flags = (uint16_t)(flags | CFO_COND_PLOGI);
1455                 }
1456                 rval = ql_log_iocb(ha, tq, loop_id, flags, &mr);
1457         } else {
1458                 mcp->mb[0] = MBC_LOGIN_LOOP_PORT;
1459                 if (CFG_IST(ha, CFG_EXT_FW_INTERFACE)) {
1460                         mcp->mb[1] = loop_id;
1461                 } else {
1462                         mcp->mb[1] = (uint16_t)(loop_id << 8);
1463                 }
1464                 mcp->mb[2] = opt;
1465                 mcp->out_mb = MBX_2|MBX_1|MBX_0;
1466                 mcp->in_mb = MBX_0;
1467                 mcp->timeout = MAILBOX_TOV;
1468                 rval = ql_mailbox_command(ha, mcp);
1469         }
1470 
1471         if (rval != QL_SUCCESS) {
1472                 EL(ha, "d_id=%xh, loop_id=%xh, failed=%xh\n", tq->d_id.b24,
1473                     loop_id, rval);
1474         } else {
1475                 /*EMPTY*/
1476                 QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
1477         }
1478 
1479         return (rval);
1480 }
1481 
1482 /*
1483  * ql_login_fport
1484  *      Issue login fabric port mailbox command.
1485  *
1486  * Input:
1487  *      ha:             adapter state pointer.
1488  *      tq:             target queue pointer.
1489  *      loop_id:        FC loop id.
1490  *      opt:            options.
1491  *                      LFF_NONE, LFF_NO_PLOGI, LFF_NO_PRLI
1492  *      mr:             pointer for mailbox data.
1493  *
1494  * Returns:
1495  *      ql local function return status code.
1496  *
1497  * Context:
1498  *      Kernel context.
1499  */
1500 int
1501 ql_login_fport(ql_adapter_state_t *ha, ql_tgt_t *tq, uint16_t loop_id,
1502     uint16_t opt, ql_mbx_data_t *mr)
1503 {
1504         int             rval;
1505         uint16_t        flags;
1506         mbx_cmd_t       mc = {0};
1507         mbx_cmd_t       *mcp = &mc;
1508 
1509         QL_PRINT_3(CE_CONT, "(%d): started, d_id=%xh, loop_id=%xh\n",
1510             ha->instance, tq->d_id.b24, loop_id);
1511 
1512         if ((tq->d_id.b24 & 0xffffff) == 0xfffffa) {
1513                 opt = (uint16_t)(opt | LFF_NO_PRLI);
1514         }
1515 
1516         if (CFG_IST(ha, CFG_CTRL_24258081)) {
1517                 flags = CF_CMD_PLOGI;
1518                 if (opt & LFF_NO_PLOGI) {
1519                         flags = (uint16_t)(flags | CFO_COND_PLOGI);
1520                 }
1521                 if (opt & LFF_NO_PRLI) {
1522                         flags = (uint16_t)(flags | CFO_SKIP_PRLI);
1523                 }
1524                 rval = ql_log_iocb(ha, tq, loop_id, flags, mr);
1525         } else {
1526                 mcp->mb[0] = MBC_LOGIN_FABRIC_PORT;
1527                 if (CFG_IST(ha, CFG_EXT_FW_INTERFACE)) {
1528                         mcp->mb[1] = loop_id;
1529                         mcp->mb[10] = opt;
1530                         mcp->out_mb = MBX_10|MBX_3|MBX_2|MBX_1|MBX_0;
1531                 } else {
1532                         mcp->mb[1] = (uint16_t)(loop_id << 8 | opt);
1533                         mcp->out_mb = MBX_3|MBX_2|MBX_1|MBX_0;
1534                 }
1535                 mcp->mb[2] = MSW(tq->d_id.b24);
1536                 mcp->mb[3] = LSW(tq->d_id.b24);
1537                 mcp->in_mb = MBX_7|MBX_6|MBX_2|MBX_1|MBX_0;
1538                 mcp->timeout = MAILBOX_TOV;
1539                 rval = ql_mailbox_command(ha, mcp);
1540 
1541                 /* Return mailbox data. */
1542                 if (mr != NULL) {
1543                         mr->mb[0] = mcp->mb[0];
1544                         mr->mb[1] = mcp->mb[1];
1545                         mr->mb[2] = mcp->mb[2];
1546                         mr->mb[6] = mcp->mb[6];
1547                         mr->mb[7] = mcp->mb[7];
1548                 }
1549         }
1550 
1551         if (rval != QL_SUCCESS) {
1552                 EL(ha, "d_id=%xh, loop_id=%xh, failed=%xh, mb1=%02xh, "
1553                     "mb2=%04x\n", tq->d_id.b24, loop_id, rval, mr->mb[1],
1554                     mr->mb[2]);
1555         } else {
1556                 /*EMPTY*/
1557                 QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
1558         }
1559 
1560         return (rval);
1561 }
1562 
1563 /*
1564  * ql_logout_fabric_port
1565  *      Issue logout fabric port mailbox command.
1566  *
1567  * Input:
1568  *      ha:     adapter state pointer.
1569  *      tq:     target queue pointer.
1570  *
1571  * Returns:
1572  *      ql local function return status code.
1573  *
1574  * Context:
1575  *      Kernel context.
1576  */
1577 int
1578 ql_logout_fabric_port(ql_adapter_state_t *ha, ql_tgt_t *tq)
1579 {
1580         int             rval;
1581         uint16_t        flag;
1582         ql_mbx_data_t   mr;
1583         mbx_cmd_t       mc = {0};
1584         mbx_cmd_t       *mcp = &mc;
1585 
1586         QL_PRINT_3(CE_CONT, "(%d): started, loop_id=%xh d_id=%xh\n",
1587             ha->instance, tq->loop_id, tq->d_id.b24);
1588 
1589         if (CFG_IST(ha, CFG_CTRL_24258081)) {
1590                 flag = (uint16_t)(RESERVED_LOOP_ID(ha, tq->loop_id) ?
1591                     CFO_EXPLICIT_LOGO |CF_CMD_LOGO | CFO_FREE_N_PORT_HANDLE :
1592                     CFO_IMPLICIT_LOGO |CF_CMD_LOGO | CFO_FREE_N_PORT_HANDLE);
1593                 rval = ql_log_iocb(ha, tq, tq->loop_id, flag, &mr);
1594         } else {
1595                 flag = (uint16_t)(RESERVED_LOOP_ID(ha, tq->loop_id) ?  1 : 0);
1596                 mcp->mb[0] = MBC_LOGOUT_FABRIC_PORT;
1597                 if (CFG_IST(ha, CFG_EXT_FW_INTERFACE)) {
1598                         mcp->mb[1] = tq->loop_id;
1599                         mcp->mb[10] = flag;
1600                         mcp->out_mb = MBX_10|MBX_1|MBX_0;
1601                 } else {
1602                         mcp->mb[1] = (uint16_t)(tq->loop_id << 8 | flag);
1603                         mcp->out_mb = MBX_1|MBX_0;
1604                 }
1605                 mcp->in_mb = MBX_0;
1606                 mcp->timeout = MAILBOX_TOV;
1607                 rval = ql_mailbox_command(ha, mcp);
1608         }
1609 
1610         if (rval != QL_SUCCESS) {
1611                 EL(ha, "d_id=%xh, loop_id=%xh, failed=%xh\n", rval,
1612                     tq->d_id.b24, tq->loop_id);
1613         } else {
1614                 /*EMPTY*/
1615                 QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
1616         }
1617 
1618         return (rval);
1619 }
1620 
1621 /*
1622  * ql_log_iocb
1623  *      Function issues login/logout IOCB.
1624  *
1625  * Input:
1626  *      ha:             adapter state pointer.
1627  *      tq:             target queue pointer.
1628  *      loop_id:        FC Loop ID.
1629  *      flags:          control flags.
1630  *      mr:             pointer for mailbox data.
1631  *
1632  * Returns:
1633  *      ql local function return status code.
1634  *
1635  * Context:
1636  *      Kernel context.
1637  */
1638 int
1639 ql_log_iocb(ql_adapter_state_t *ha, ql_tgt_t *tq, uint16_t loop_id,
1640     uint16_t flags, ql_mbx_data_t *mr)
1641 {
1642         ql_mbx_iocb_t   *pkt;
1643         int             rval;
1644         uint32_t        pkt_size;
1645 
1646         QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
1647 
1648         pkt_size = sizeof (ql_mbx_iocb_t);
1649         pkt = kmem_zalloc(pkt_size, KM_SLEEP);
1650         if (pkt == NULL) {
1651                 EL(ha, "failed, kmem_zalloc\n");
1652                 return (QL_MEMORY_ALLOC_FAILED);
1653         }
1654 
1655         pkt->log.entry_type = LOG_TYPE;
1656         pkt->log.entry_count = 1;
1657         pkt->log.n_port_hdl = (uint16_t)LE_16(loop_id);
1658         pkt->log.control_flags = (uint16_t)LE_16(flags);
1659         pkt->log.port_id[0] = tq->d_id.b.al_pa;
1660         pkt->log.port_id[1] = tq->d_id.b.area;
1661         pkt->log.port_id[2] = tq->d_id.b.domain;
1662         pkt->log.vp_index = ha->vp_index;
1663 
1664         rval = ql_issue_mbx_iocb(ha, (caddr_t)pkt, pkt_size);
1665         if (rval == QL_SUCCESS && (pkt->log.entry_status & 0x3c) != 0) {
1666                 EL(ha, "failed, entry_status=%xh, d_id=%xh\n",
1667                     pkt->log.entry_status, tq->d_id.b24);
1668                 rval = QL_FUNCTION_PARAMETER_ERROR;
1669         }
1670 
1671         if (rval == QL_SUCCESS) {
1672                 if (pkt->log.rsp_size == 0xB) {
1673                         LITTLE_ENDIAN_32(&pkt->log.io_param[5]);
1674                         tq->cmn_features = MSW(pkt->log.io_param[5]);
1675                         LITTLE_ENDIAN_32(&pkt->log.io_param[6]);
1676                         tq->conc_sequences = MSW(pkt->log.io_param[6]);
1677                         tq->relative_offset = LSW(pkt->log.io_param[6]);
1678                         LITTLE_ENDIAN_32(&pkt->log.io_param[9]);
1679                         tq->class3_recipient_ctl = MSW(pkt->log.io_param[9]);
1680                         tq->class3_conc_sequences = LSW(pkt->log.io_param[9]);
1681                         LITTLE_ENDIAN_32(&pkt->log.io_param[10]);
1682                         tq->class3_open_sequences_per_exch =
1683                             MSW(pkt->log.io_param[10]);
1684                         tq->prli_payload_length = 0x14;
1685                 }
1686                 if (mr != NULL) {
1687                         LITTLE_ENDIAN_16(&pkt->log.status);
1688                         LITTLE_ENDIAN_32(&pkt->log.io_param[0]);
1689                         LITTLE_ENDIAN_32(&pkt->log.io_param[1]);
1690 
1691                         if (pkt->log.status != CS_COMPLETE) {
1692                                 EL(ha, "failed, status=%xh, iop0=%xh, iop1="
1693                                     "%xh\n", pkt->log.status,
1694                                     pkt->log.io_param[0],
1695                                     pkt->log.io_param[1]);
1696 
1697                                 switch (pkt->log.io_param[0]) {
1698                                 case CS0_NO_LINK:
1699                                 case CS0_FIRMWARE_NOT_READY:
1700                                         mr->mb[0] = MBS_COMMAND_ERROR;
1701                                         mr->mb[1] = 1;
1702                                         break;
1703                                 case CS0_NO_IOCB:
1704                                 case CS0_NO_PCB_ALLOCATED:
1705                                         mr->mb[0] = MBS_COMMAND_ERROR;
1706                                         mr->mb[1] = 2;
1707                                         break;
1708                                 case CS0_NO_EXCH_CTRL_BLK:
1709                                         mr->mb[0] = MBS_COMMAND_ERROR;
1710                                         mr->mb[1] = 3;
1711                                         break;
1712                                 case CS0_COMMAND_FAILED:
1713                                         mr->mb[0] = MBS_COMMAND_ERROR;
1714                                         mr->mb[1] = 4;
1715                                         switch (LSB(pkt->log.io_param[1])) {
1716                                         case CS1_PLOGI_RESPONSE_FAILED:
1717                                                 mr->mb[2] = 3;
1718                                                 break;
1719                                         case CS1_PRLI_FAILED:
1720                                                 mr->mb[2] = 4;
1721                                                 break;
1722                                         case CS1_PRLI_RESPONSE_FAILED:
1723                                                 mr->mb[2] = 5;
1724                                                 break;
1725                                         case CS1_COMMAND_LOGGED_OUT:
1726                                                 mr->mb[2] = 7;
1727                                                 break;
1728                                         case CS1_PLOGI_FAILED:
1729                                         default:
1730                                                 EL(ha, "log iop1 = %xh\n",
1731                                                     LSB(pkt->log.io_param[1]))
1732                                                 mr->mb[2] = 2;
1733                                                 break;
1734                                         }
1735                                         break;
1736                                 case CS0_PORT_NOT_LOGGED_IN:
1737                                         mr->mb[0] = MBS_COMMAND_ERROR;
1738                                         mr->mb[1] = 4;
1739                                         mr->mb[2] = 7;
1740                                         break;
1741                                 case CS0_NO_FLOGI_ACC:
1742                                 case CS0_NO_FABRIC_PRESENT:
1743                                         mr->mb[0] = MBS_COMMAND_ERROR;
1744                                         mr->mb[1] = 5;
1745                                         break;
1746                                 case CS0_ELS_REJECT_RECEIVED:
1747                                         mr->mb[0] = MBS_COMMAND_ERROR;
1748                                         mr->mb[1] = 0xd;
1749                                         break;
1750                                 case CS0_PORT_ID_USED:
1751                                         mr->mb[0] = MBS_PORT_ID_USED;
1752                                         mr->mb[1] = LSW(pkt->log.io_param[1]);
1753                                         break;
1754                                 case CS0_N_PORT_HANDLE_USED:
1755                                         mr->mb[0] = MBS_LOOP_ID_USED;
1756                                         mr->mb[1] = MSW(pkt->log.io_param[1]);
1757                                         mr->mb[2] = LSW(pkt->log.io_param[1]);
1758                                         break;
1759                                 case CS0_NO_N_PORT_HANDLE_AVAILABLE:
1760                                         mr->mb[0] = MBS_ALL_IDS_IN_USE;
1761                                         break;
1762                                 case CS0_CMD_PARAMETER_ERROR:
1763                                 default:
1764                                         EL(ha, "pkt->log iop[0]=%xh\n",
1765                                             pkt->log.io_param[0]);
1766                                         mr->mb[0] =
1767                                             MBS_COMMAND_PARAMETER_ERROR;
1768                                         break;
1769                                 }
1770                         } else {
1771                                 QL_PRINT_3(CE_CONT, "(%d): status=%xh\n",
1772                                     ha->instance, pkt->log.status);
1773 
1774                                 mr->mb[0] = MBS_COMMAND_COMPLETE;
1775                                 mr->mb[1] = (uint16_t)
1776                                     (pkt->log.io_param[0] & BIT_4 ? 0 : BIT_0);
1777                                 if (pkt->log.io_param[0] & BIT_8) {
1778                                         mr->mb[1] = (uint16_t)
1779                                             (mr->mb[1] | BIT_1);
1780                                 }
1781                         }
1782                         rval = mr->mb[0];
1783                 }
1784 
1785         }
1786 
1787         kmem_free(pkt, pkt_size);
1788 
1789         if (rval != QL_SUCCESS) {
1790                 EL(ha, "failed=%xh, d_id=%xh\n", rval, tq->d_id.b24);
1791         } else {
1792                 /*EMPTY*/
1793                 QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
1794         }
1795 
1796         return (rval);
1797 }
1798 
1799 /*
1800  * ql_get_port_database
1801  *      Issue get port database mailbox command
1802  *      and copy context to device queue.
1803  *
1804  * Input:
1805  *      ha:     adapter state pointer.
1806  *      tq:     target queue pointer.
1807  *      opt:    options.
1808  *              PDF_NONE, PDF_PLOGI, PDF_ADISC
1809  * Returns:
1810  *      ql local function return status code.
1811  *
1812  * Context:
1813  *      Kernel context.
1814  */
1815 int
1816 ql_get_port_database(ql_adapter_state_t *ha, ql_tgt_t *tq, uint8_t opt)
1817 {
1818         int                     rval;
1819         dma_mem_t               mem_desc;
1820         mbx_cmd_t               mc = {0};
1821         mbx_cmd_t               *mcp = &mc;
1822         port_database_23_t      *pd23;
1823 
1824         QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
1825 
1826         pd23 = (port_database_23_t *)kmem_zalloc(PORT_DATABASE_SIZE, KM_SLEEP);
1827         if (pd23 == NULL) {
1828                 rval = QL_MEMORY_ALLOC_FAILED;
1829                 EL(ha, "failed, rval = %xh\n", rval);
1830                 return (rval);
1831         }
1832 
1833         if ((rval = ql_setup_mbox_dma_resources(ha, &mem_desc,
1834             PORT_DATABASE_SIZE)) != QL_SUCCESS) {
1835                 return (QL_MEMORY_ALLOC_FAILED);
1836         }
1837 
1838         if (CFG_IST(ha, CFG_CTRL_24258081)) {
1839                 mcp->mb[0] = MBC_GET_PORT_DATABASE;
1840                 mcp->mb[1] = tq->loop_id;
1841                 mcp->mb[4] = CHAR_TO_SHORT(tq->d_id.b.al_pa, tq->d_id.b.area);
1842                 mcp->mb[5] = (uint16_t)tq->d_id.b.domain;
1843                 mcp->mb[9] = ha->vp_index;
1844                 mcp->mb[10] = (uint16_t)(opt | PDF_ADISC);
1845                 mcp->out_mb = MBX_10|MBX_9|MBX_7|MBX_6|MBX_5|MBX_4|MBX_3|
1846                     MBX_2|MBX_1|MBX_0;
1847         } else {
1848                 mcp->mb[0] = (uint16_t)(opt == PDF_NONE ?
1849                     MBC_GET_PORT_DATABASE : MBC_ENHANCED_GET_PORT_DATABASE);
1850                 if (CFG_IST(ha, CFG_EXT_FW_INTERFACE)) {
1851                         mcp->mb[1] = tq->loop_id;
1852                         mcp->mb[10] = opt;
1853                         mcp->out_mb = MBX_10|MBX_7|MBX_6|MBX_3|
1854                             MBX_2|MBX_1|MBX_0;
1855                 } else {
1856                         mcp->mb[1] = (uint16_t)(tq->loop_id << 8 | opt);
1857                         mcp->out_mb = MBX_7|MBX_6|MBX_3|MBX_2|MBX_1|MBX_0;
1858                 }
1859         }
1860 
1861         mcp->mb[2] = MSW(LSD(mem_desc.cookie.dmac_laddress));
1862         mcp->mb[3] = LSW(LSD(mem_desc.cookie.dmac_laddress));
1863         mcp->mb[6] = MSW(MSD(mem_desc.cookie.dmac_laddress));
1864         mcp->mb[7] = LSW(MSD(mem_desc.cookie.dmac_laddress));
1865         mcp->in_mb = MBX_0;
1866         mcp->timeout = MAILBOX_TOV;
1867         rval = ql_mailbox_command(ha, mcp);
1868 
1869         if (rval == QL_SUCCESS) {
1870                 ql_get_mbox_dma_data(&mem_desc, (caddr_t)pd23);
1871         }
1872 
1873         ql_free_dma_resource(ha, &mem_desc);
1874 
1875         if (rval == QL_SUCCESS) {
1876                 if (CFG_IST(ha, CFG_CTRL_24258081)) {
1877                         port_database_24_t *pd24 = (port_database_24_t *)pd23;
1878 
1879                         tq->master_state = pd24->current_login_state;
1880                         tq->slave_state = pd24->last_stable_login_state;
1881                         if (PD_PORT_LOGIN(tq)) {
1882                                 /* Names are big endian. */
1883                                 bcopy((void *)&pd24->port_name[0],
1884                                     (void *)&tq->port_name[0], 8);
1885                                 bcopy((void *)&pd24->node_name[0],
1886                                     (void *)&tq->node_name[0], 8);
1887                                 tq->hard_addr.b.al_pa = pd24->hard_address[2];
1888                                 tq->hard_addr.b.area = pd24->hard_address[1];
1889                                 tq->hard_addr.b.domain = pd24->hard_address[0];
1890                                 tq->class3_rcv_data_size =
1891                                     pd24->receive_data_size;
1892                                 LITTLE_ENDIAN_16(&tq->class3_rcv_data_size);
1893                                 tq->prli_svc_param_word_0 =
1894                                     pd24->PRLI_service_parameter_word_0;
1895                                 LITTLE_ENDIAN_16(&tq->prli_svc_param_word_0);
1896                                 tq->prli_svc_param_word_3 =
1897                                     pd24->PRLI_service_parameter_word_3;
1898                                 LITTLE_ENDIAN_16(&tq->prli_svc_param_word_3);
1899                         }
1900                 } else {
1901                         tq->master_state = pd23->master_state;
1902                         tq->slave_state = pd23->slave_state;
1903                         if (PD_PORT_LOGIN(tq)) {
1904                                 /* Names are big endian. */
1905                                 bcopy((void *)&pd23->port_name[0],
1906                                     (void *)&tq->port_name[0], 8);
1907                                 bcopy((void *)&pd23->node_name[0],
1908                                     (void *)&tq->node_name[0], 8);
1909                                 tq->hard_addr.b.al_pa = pd23->hard_address[2];
1910                                 tq->hard_addr.b.area = pd23->hard_address[1];
1911                                 tq->hard_addr.b.domain = pd23->hard_address[0];
1912                                 tq->cmn_features = pd23->common_features;
1913                                 LITTLE_ENDIAN_16(&tq->cmn_features);
1914                                 tq->conc_sequences =
1915                                     pd23->total_concurrent_sequences;
1916                                 LITTLE_ENDIAN_16(&tq->conc_sequences);
1917                                 tq->relative_offset =
1918                                     pd23->RO_by_information_category;
1919                                 LITTLE_ENDIAN_16(&tq->relative_offset);
1920                                 tq->class3_recipient_ctl = pd23->recipient;
1921                                 LITTLE_ENDIAN_16(&tq->class3_recipient_ctl);
1922                                 tq->class3_rcv_data_size =
1923                                     pd23->receive_data_size;
1924                                 LITTLE_ENDIAN_16(&tq->class3_rcv_data_size);
1925                                 tq->class3_conc_sequences =
1926                                     pd23->concurrent_sequences;
1927                                 LITTLE_ENDIAN_16(&tq->class3_conc_sequences);
1928                                 tq->class3_open_sequences_per_exch =
1929                                     pd23->open_sequences_per_exchange;
1930                                 LITTLE_ENDIAN_16(
1931                                     &tq->class3_open_sequences_per_exch);
1932                                 tq->prli_payload_length =
1933                                     pd23->PRLI_payload_length;
1934                                 LITTLE_ENDIAN_16(&tq->prli_payload_length);
1935                                 tq->prli_svc_param_word_0 =
1936                                     pd23->PRLI_service_parameter_word_0;
1937                                 LITTLE_ENDIAN_16(&tq->prli_svc_param_word_0);
1938                                 tq->prli_svc_param_word_3 =
1939                                     pd23->PRLI_service_parameter_word_3;
1940                                 LITTLE_ENDIAN_16(&tq->prli_svc_param_word_3);
1941                         }
1942                 }
1943 
1944                 if (!PD_PORT_LOGIN(tq)) {
1945                         EL(ha, "d_id=%xh, loop_id=%xh, not logged in "
1946                             "master=%xh, slave=%xh\n", tq->d_id.b24,
1947                             tq->loop_id, tq->master_state, tq->slave_state);
1948                         rval = QL_NOT_LOGGED_IN;
1949                 } else {
1950                         tq->flags = tq->prli_svc_param_word_3 &
1951                             PRLI_W3_TARGET_FUNCTION ?
1952                             tq->flags & ~TQF_INITIATOR_DEVICE :
1953                             tq->flags | TQF_INITIATOR_DEVICE;
1954 
1955                         if ((tq->flags & TQF_INITIATOR_DEVICE) == 0) {
1956                                 tq->flags = tq->prli_svc_param_word_3 &
1957                                     PRLI_W3_RETRY ?
1958                                     tq->flags | TQF_TAPE_DEVICE :
1959                                     tq->flags & ~TQF_TAPE_DEVICE;
1960                         } else {
1961                                 tq->flags &= ~TQF_TAPE_DEVICE;
1962                         }
1963                 }
1964         }
1965 
1966         kmem_free(pd23, PORT_DATABASE_SIZE);
1967 
1968         if ((rval != QL_SUCCESS) && (rval != QL_PARAMETER_ERROR)) {
1969                 EL(ha, "d_id=%xh, loop_id=%xh, failed=%xh\n", tq->d_id.b24,
1970                     tq->loop_id, rval);
1971         } else {
1972                 /*EMPTY*/
1973                 QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
1974         }
1975 
1976         return (rval);
1977 }
1978 
1979 /*
1980  * ql_get_loop_position_map
1981  *      Issue get loop position map mailbox command.
1982  *
1983  * Input:
1984  *      ha:     adapter state pointer.
1985  *      size:   size of data buffer.
1986  *      bufp:   data pointer for DMA data.
1987  *
1988  * Returns:
1989  *      ql local function return status code.
1990  *
1991  * Context:
1992  *      Kernel context.
1993  */
1994 int
1995 ql_get_loop_position_map(ql_adapter_state_t *ha, size_t size, caddr_t bufp)
1996 {
1997         int             rval;
1998         dma_mem_t       mem_desc;
1999         mbx_cmd_t       mc = {0};
2000         mbx_cmd_t       *mcp = &mc;
2001 
2002         QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
2003 
2004         if ((rval = ql_setup_mbox_dma_resources(ha, &mem_desc,
2005             (uint32_t)size)) != QL_SUCCESS) {
2006                 EL(ha, "setup_mbox_dma_resources failed: %xh\n", rval);
2007                 return (QL_MEMORY_ALLOC_FAILED);
2008         }
2009 
2010         mcp->mb[0] = MBC_GET_FC_AL_POSITION_MAP;
2011         mcp->mb[2] = MSW(LSD(mem_desc.cookie.dmac_laddress));
2012         mcp->mb[3] = LSW(LSD(mem_desc.cookie.dmac_laddress));
2013         mcp->mb[6] = MSW(MSD(mem_desc.cookie.dmac_laddress));
2014         mcp->mb[7] = LSW(MSD(mem_desc.cookie.dmac_laddress));
2015         mcp->out_mb = MBX_7|MBX_6|MBX_3|MBX_2|MBX_0;
2016         mcp->in_mb = MBX_1|MBX_0;
2017         mcp->timeout = MAILBOX_TOV;
2018         rval = ql_mailbox_command(ha, mcp);
2019 
2020         if (rval == QL_SUCCESS) {
2021                 ql_get_mbox_dma_data(&mem_desc, bufp);
2022         }
2023 
2024         ql_free_dma_resource(ha, &mem_desc);
2025 
2026         if (rval != QL_SUCCESS) {
2027                 EL(ha, "failed=%xh\n", rval);
2028         } else {
2029                 /*EMPTY*/
2030                 QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
2031         }
2032 
2033         return (rval);
2034 }
2035 
2036 /*
2037  * ql_set_rnid_params
2038  *      Issue set RNID parameters mailbox command.
2039  *
2040  * Input:
2041  *      ha:             adapter state pointer.
2042  *      size:           size of data buffer.
2043  *      bufp:           data pointer for DMA data.
2044  *
2045  * Returns:
2046  *      ql local function return status code.
2047  *
2048  * Context:
2049  *      Kernel context.
2050  */
2051 int
2052 ql_set_rnid_params(ql_adapter_state_t *ha, size_t size, caddr_t bufp)
2053 {
2054         int             rval;
2055         dma_mem_t       mem_desc;
2056         mbx_cmd_t       mc = {0};
2057         mbx_cmd_t       *mcp = &mc;
2058 
2059         QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
2060 
2061         if ((rval = ql_setup_mbox_dma_transfer(ha, &mem_desc, bufp,
2062             (uint32_t)size)) != QL_SUCCESS) {
2063                 EL(ha, "failed, setup_mbox_dma_transfer: %x\n", rval);
2064                 return (rval);
2065         }
2066 
2067         mcp->mb[0] = MBC_SET_PARAMETERS;
2068         mcp->mb[2] = MSW(LSD(mem_desc.cookie.dmac_laddress));
2069         mcp->mb[3] = LSW(LSD(mem_desc.cookie.dmac_laddress));
2070         mcp->mb[6] = MSW(MSD(mem_desc.cookie.dmac_laddress));
2071         mcp->mb[7] = LSW(MSD(mem_desc.cookie.dmac_laddress));
2072         mcp->out_mb = MBX_7|MBX_6|MBX_3|MBX_2|MBX_1|MBX_0;
2073         mcp->in_mb = MBX_0;
2074         mcp->timeout = MAILBOX_TOV;
2075         rval = ql_mailbox_command(ha, mcp);
2076 
2077         ql_free_dma_resource(ha, &mem_desc);
2078 
2079         if (rval != QL_SUCCESS) {
2080                 EL(ha, "failed, rval = %xh\n", rval);
2081         } else {
2082                 /*EMPTY*/
2083                 QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
2084         }
2085 
2086         return (rval);
2087 }
2088 
2089 /*
2090  * ql_send_rnid_els
2091  *      Issue a send node identfication data mailbox command.
2092  *
2093  * Input:
2094  *      ha:             adapter state pointer.
2095  *      loop_id:        FC loop id.
2096  *      opt:            options.
2097  *      size:           size of data buffer.
2098  *      bufp:           data pointer for DMA data.
2099  *
2100  * Returns:
2101  *      ql local function return status code.
2102  *
2103  * Context:
2104  *      Kernel context.
2105  */
2106 int
2107 ql_send_rnid_els(ql_adapter_state_t *ha, uint16_t loop_id, uint8_t opt,
2108     size_t size, caddr_t bufp)
2109 {
2110         int             rval;
2111         dma_mem_t       mem_desc;
2112         mbx_cmd_t       mc = {0};
2113         mbx_cmd_t       *mcp = &mc;
2114 
2115         QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
2116 
2117         if ((rval = ql_setup_mbox_dma_resources(ha, &mem_desc,
2118             (uint32_t)size)) != QL_SUCCESS) {
2119                 return (QL_MEMORY_ALLOC_FAILED);
2120         }
2121 
2122         mcp->mb[0] = MBC_SEND_RNID_ELS;
2123         if (CFG_IST(ha, CFG_CTRL_24258081)) {
2124                 mcp->mb[1] = loop_id;
2125                 mcp->mb[9] = ha->vp_index;
2126                 mcp->mb[10] = opt;
2127                 mcp->out_mb = MBX_10|MBX_9|MBX_7|MBX_6|MBX_3|MBX_2|MBX_1|MBX_0;
2128         } else if (CFG_IST(ha, CFG_EXT_FW_INTERFACE)) {
2129                 mcp->mb[1] = loop_id;
2130                 mcp->mb[10] = opt;
2131                 mcp->out_mb = MBX_10|MBX_7|MBX_6|MBX_3|MBX_2|MBX_1|MBX_0;
2132         } else {
2133                 mcp->mb[1] = (uint16_t)(loop_id << 8 | opt);
2134                 mcp->out_mb = MBX_7|MBX_6|MBX_3|MBX_2|MBX_1|MBX_0;
2135         }
2136         mcp->mb[2] = MSW(LSD(mem_desc.cookie.dmac_laddress));
2137         mcp->mb[3] = LSW(LSD(mem_desc.cookie.dmac_laddress));
2138         mcp->mb[6] = MSW(MSD(mem_desc.cookie.dmac_laddress));
2139         mcp->mb[7] = LSW(MSD(mem_desc.cookie.dmac_laddress));
2140         mcp->in_mb = MBX_0;
2141         mcp->timeout = MAILBOX_TOV;
2142         rval = ql_mailbox_command(ha, mcp);
2143 
2144         if (rval == QL_SUCCESS) {
2145                 ql_get_mbox_dma_data(&mem_desc, bufp);
2146         }
2147 
2148         ql_free_dma_resource(ha, &mem_desc);
2149 
2150         if (rval != QL_SUCCESS) {
2151                 EL(ha, "failed, rval = %xh\n", rval);
2152         } else {
2153                 /*EMPTY*/
2154                 QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
2155         }
2156 
2157         return (rval);
2158 }
2159 
2160 /*
2161  * ql_get_rnid_params
2162  *      Issue get RNID parameters mailbox command.
2163  *
2164  * Input:
2165  *      ha:     adapter state pointer.
2166  *      size:   size of data buffer.
2167  *      bufp:   data pointer for DMA data.
2168  *
2169  * Returns:
2170  *      ql local function return status code.
2171  *
2172  * Context:
2173  *      Kernel context.
2174  */
2175 int
2176 ql_get_rnid_params(ql_adapter_state_t *ha, size_t size, caddr_t bufp)
2177 {
2178         int             rval;
2179         dma_mem_t       mem_desc;
2180         mbx_cmd_t       mc = {0};
2181         mbx_cmd_t       *mcp = &mc;
2182 
2183         QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
2184 
2185         if ((rval = ql_setup_mbox_dma_resources(ha, &mem_desc,
2186             (uint32_t)size)) != QL_SUCCESS) {
2187                 return (QL_MEMORY_ALLOC_FAILED);
2188         }
2189 
2190         mcp->mb[0] = MBC_GET_PARAMETERS;
2191         mcp->mb[2] = MSW(LSD(mem_desc.cookie.dmac_laddress));
2192         mcp->mb[3] = LSW(LSD(mem_desc.cookie.dmac_laddress));
2193         mcp->mb[6] = MSW(MSD(mem_desc.cookie.dmac_laddress));
2194         mcp->mb[7] = LSW(MSD(mem_desc.cookie.dmac_laddress));
2195         mcp->out_mb = MBX_7|MBX_6|MBX_3|MBX_2|MBX_1|MBX_0;
2196         mcp->in_mb = MBX_0;
2197         mcp->timeout = MAILBOX_TOV;
2198         rval = ql_mailbox_command(ha, mcp);
2199 
2200         if (rval == QL_SUCCESS) {
2201                 ql_get_mbox_dma_data(&mem_desc, bufp);
2202         }
2203 
2204         ql_free_dma_resource(ha, &mem_desc);
2205 
2206         if (rval != QL_SUCCESS) {
2207                 EL(ha, "failed=%xh\n", rval);
2208         } else {
2209                 /*EMPTY*/
2210                 QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
2211         }
2212 
2213         return (rval);
2214 }
2215 
2216 /*
2217  * ql_get_link_status
2218  *      Issue get link status mailbox command.
2219  *
2220  * Input:
2221  *      ha:             adapter state pointer.
2222  *      loop_id:        FC loop id or n_port_hdl.
2223  *      size:           size of data buffer.
2224  *      bufp:           data pointer for DMA data.
2225  *      port_no:        port number to query.
2226  *
2227  * Returns:
2228  *      ql local function return status code.
2229  *
2230  * Context:
2231  *      Kernel context.
2232  */
2233 int
2234 ql_get_link_status(ql_adapter_state_t *ha, uint16_t loop_id, size_t size,
2235     caddr_t bufp, uint8_t port_no)
2236 {
2237         dma_mem_t       mem_desc;
2238         mbx_cmd_t       mc = {0};
2239         mbx_cmd_t       *mcp = &mc;
2240         int             rval = QL_SUCCESS;
2241         int             retry = 0;
2242 
2243         QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
2244 
2245         do {
2246                 if ((rval = ql_setup_mbox_dma_resources(ha, &mem_desc,
2247                     (uint32_t)size)) != QL_SUCCESS) {
2248                         EL(ha, "setup_mbox_dma_resources failed: %xh\n", rval);
2249                         return (QL_MEMORY_ALLOC_FAILED);
2250                 }
2251 
2252                 mcp->mb[0] = MBC_GET_LINK_STATUS;
2253                 if (CFG_IST(ha, CFG_CTRL_24258081)) {
2254                         if (loop_id == ha->loop_id) {
2255                                 mcp->mb[0] = MBC_GET_STATUS_COUNTS;
2256                                 mcp->mb[8] = (uint16_t)(size >> 2);
2257                                 mcp->out_mb = MBX_10|MBX_8;
2258                         } else {
2259                                 mcp->mb[1] = loop_id;
2260                                 mcp->mb[4] = port_no;
2261                                 mcp->mb[10] = (uint16_t)(retry ? BIT_3 : 0);
2262                                 mcp->out_mb = MBX_10|MBX_4;
2263                         }
2264                 } else {
2265                         if (retry) {
2266                                 port_no = (uint8_t)(port_no | BIT_3);
2267                         }
2268                         if (CFG_IST(ha, CFG_EXT_FW_INTERFACE)) {
2269                                 mcp->mb[1] = loop_id;
2270                                 mcp->mb[10] = port_no;
2271                                 mcp->out_mb = MBX_10;
2272                         } else {
2273                                 mcp->mb[1] = (uint16_t)((loop_id << 8) |
2274                                     port_no);
2275                                 mcp->out_mb = 0;
2276                         }
2277                 }
2278                 mcp->mb[2] = MSW(LSD(mem_desc.cookie.dmac_laddress));
2279                 mcp->mb[3] = LSW(LSD(mem_desc.cookie.dmac_laddress));
2280                 mcp->mb[6] = MSW(MSD(mem_desc.cookie.dmac_laddress));
2281                 mcp->mb[7] = LSW(MSD(mem_desc.cookie.dmac_laddress));
2282                 mcp->in_mb = MBX_1|MBX_0;
2283                 mcp->out_mb |= MBX_7|MBX_6|MBX_3|MBX_2|MBX_1|MBX_0;
2284                 mcp->timeout = MAILBOX_TOV;
2285 
2286                 rval = ql_mailbox_command(ha, mcp);
2287 
2288                 if (rval == QL_SUCCESS) {
2289                         ql_get_mbox_dma_data(&mem_desc, bufp);
2290                 }
2291 
2292                 ql_free_dma_resource(ha, &mem_desc);
2293 
2294                 if (rval != QL_SUCCESS) {
2295                         EL(ha, "failed=%xh, mbx1=%xh\n", rval, mcp->mb[1]);
2296                 }
2297 
2298                 /*
2299                  * Some of the devices want d_id in the payload,
2300                  * strictly as per standard. Let's retry.
2301                  */
2302 
2303         } while (rval == QL_COMMAND_ERROR && !retry++);
2304 
2305         if (rval != QL_SUCCESS) {
2306                 EL(ha, "failed=%xh, mbx1=%xh\n", rval, mcp->mb[1]);
2307         } else {
2308                 /*EMPTY*/
2309                 QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
2310         }
2311 
2312         return (rval);
2313 }
2314 
2315 /*
2316  * ql_get_status_counts
2317  *      Issue get adapter link status counts mailbox command.
2318  *
2319  * Input:
2320  *      ha:             adapter state pointer.
2321  *      loop_id:        FC loop id or n_port_hdl.
2322  *      size:           size of data buffer.
2323  *      bufp:           data pointer for DMA data.
2324  *      port_no:        port number to query.
2325  *
2326  * Returns:
2327  *      ql local function return status code.
2328  *
2329  * Context:
2330  *      Kernel context.
2331  */
2332 int
2333 ql_get_status_counts(ql_adapter_state_t *ha, uint16_t loop_id, size_t size,
2334     caddr_t bufp, uint8_t port_no)
2335 {
2336         dma_mem_t       mem_desc;
2337         mbx_cmd_t       mc = {0};
2338         mbx_cmd_t       *mcp = &mc;
2339         int             rval = QL_SUCCESS;
2340 
2341         QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
2342 
2343         if ((rval = ql_setup_mbox_dma_resources(ha, &mem_desc,
2344             (uint32_t)size)) != QL_SUCCESS) {
2345                 EL(ha, "setup_mbox_dma_resources failed: %x\n", rval);
2346                 return (QL_MEMORY_ALLOC_FAILED);
2347         }
2348 
2349         if (CFG_IST(ha, CFG_CTRL_24258081)) {
2350                 mcp->mb[0] = MBC_GET_STATUS_COUNTS;
2351                 mcp->mb[8] = (uint16_t)(size / 4);
2352                 mcp->out_mb = MBX_10|MBX_8;
2353         } else {
2354                 mcp->mb[0] = MBC_GET_LINK_STATUS;
2355 
2356                 /* allows reporting when link is down */
2357                 if (CFG_IST(ha, CFG_CTRL_2200) == 0) {
2358                         port_no = (uint8_t)(port_no | BIT_6);
2359                 }
2360 
2361                 if (CFG_IST(ha, CFG_EXT_FW_INTERFACE)) {
2362                         mcp->mb[1] = loop_id;
2363                         mcp->mb[10] = port_no;
2364                         mcp->out_mb = MBX_10|MBX_1;
2365                 } else {
2366                         mcp->mb[1] = (uint16_t)((loop_id << 8) |
2367                             port_no);
2368                         mcp->out_mb = MBX_1;
2369                 }
2370         }
2371         mcp->mb[2] = MSW(LSD(mem_desc.cookie.dmac_laddress));
2372         mcp->mb[3] = LSW(LSD(mem_desc.cookie.dmac_laddress));
2373         mcp->mb[6] = MSW(MSD(mem_desc.cookie.dmac_laddress));
2374         mcp->mb[7] = LSW(MSD(mem_desc.cookie.dmac_laddress));
2375         mcp->out_mb |= MBX_7|MBX_6|MBX_3|MBX_2|MBX_0;
2376         mcp->in_mb = MBX_2|MBX_1|MBX_0;
2377         mcp->timeout = MAILBOX_TOV;
2378         rval = ql_mailbox_command(ha, mcp);
2379 
2380         if (rval == QL_SUCCESS) {
2381                 ql_get_mbox_dma_data(&mem_desc, bufp);
2382         }
2383 
2384         ql_free_dma_resource(ha, &mem_desc);
2385 
2386         if (rval != QL_SUCCESS) {
2387                 EL(ha, "failed=%xh, mbx1=%xh, mbx2=%xh\n", rval,
2388                     mcp->mb[1], mcp->mb[2]);
2389         } else {
2390                 /*EMPTY*/
2391                 QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
2392         }
2393 
2394         return (rval);
2395 }
2396 
2397 /*
2398  * ql_reset_link_status
2399  *      Issue Reset Link Error Status mailbox command
2400  *
2401  * Input:
2402  *      ha:     adapter state pointer.
2403  *
2404  * Returns:
2405  *      ql local function return status code.
2406  *
2407  * Context:
2408  *      Kernel context.
2409  */
2410 int
2411 ql_reset_link_status(ql_adapter_state_t *ha)
2412 {
2413         int             rval;
2414         mbx_cmd_t       mc = {0};
2415         mbx_cmd_t       *mcp = &mc;
2416 
2417         QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
2418 
2419         mcp->mb[0] = MBC_RESET_LINK_STATUS;
2420         mcp->out_mb = MBX_0;
2421         mcp->in_mb = MBX_0;
2422         mcp->timeout = MAILBOX_TOV;
2423         rval = ql_mailbox_command(ha, mcp);
2424 
2425         if (rval != QL_SUCCESS) {
2426                 EL(ha, "failed=%xh\n", rval);
2427         } else {
2428                 /*EMPTY*/
2429                 QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
2430         }
2431 
2432         return (rval);
2433 }
2434 
2435 /*
2436  * ql_loop_reset
2437  *      Issue loop reset.
2438  *
2439  * Input:
2440  *      ha:     adapter state pointer.
2441  *
2442  * Returns:
2443  *      ql local function return status code.
2444  *
2445  * Context:
2446  *      Kernel context.
2447  */
2448 int
2449 ql_loop_reset(ql_adapter_state_t *ha)
2450 {
2451         int     rval;
2452 
2453         QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
2454 
2455         if (CFG_IST(ha, CFG_ENABLE_LIP_RESET)) {
2456                 rval = ql_lip_reset(ha, 0xff);
2457         } else if (CFG_IST(ha, CFG_ENABLE_FULL_LIP_LOGIN)) {
2458                 rval = ql_full_login_lip(ha);
2459         } else if (CFG_IST(ha, CFG_ENABLE_TARGET_RESET)) {
2460                 rval = ql_target_reset(ha, NULL, ha->loop_reset_delay);
2461         } else {
2462                 rval = ql_initiate_lip(ha);
2463         }
2464 
2465         if (rval != QL_SUCCESS) {
2466                 EL(ha, "failed, rval = %xh\n", rval);
2467         } else {
2468                 /*EMPTY*/
2469                 QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
2470         }
2471 
2472         return (rval);
2473 }
2474 
2475 /*
2476  * ql_initiate_lip
2477  *      Initiate LIP mailbox command.
2478  *
2479  * Input:
2480  *      ha:     adapter state pointer.
2481  *
2482  * Returns:
2483  *      ql local function return status code.
2484  *
2485  * Context:
2486  *      Kernel context.
2487  */
2488 int
2489 ql_initiate_lip(ql_adapter_state_t *ha)
2490 {
2491         int             rval;
2492         mbx_cmd_t       mc = {0};
2493         mbx_cmd_t       *mcp = &mc;
2494 
2495         QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
2496 
2497         if (CFG_IST(ha, CFG_CTRL_24258081)) {
2498                 mcp->mb[0] = MBC_LIP_FULL_LOGIN;
2499                 mcp->mb[1] = (uint16_t)(CFG_IST(ha, CFG_CTRL_8081) ?
2500                     BIT_1 : BIT_4);
2501                 mcp->mb[3] = ha->loop_reset_delay;
2502                 mcp->out_mb = MBX_3|MBX_2|MBX_1|MBX_0;
2503         } else {
2504                 mcp->mb[0] = MBC_INITIATE_LIP;
2505                 mcp->out_mb = MBX_0;
2506         }
2507         mcp->in_mb = MBX_0;
2508         mcp->timeout = MAILBOX_TOV;
2509         rval = ql_mailbox_command(ha, mcp);
2510 
2511         if (rval != QL_SUCCESS) {
2512                 EL(ha, "failed, rval = %xh\n", rval);
2513         } else {
2514                 /*EMPTY*/
2515                 QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
2516         }
2517 
2518         return (rval);
2519 }
2520 
2521 /*
2522  * ql_full_login_lip
2523  *      Issue full login LIP mailbox command.
2524  *
2525  * Input:
2526  *      ha:     adapter state pointer.
2527  *
2528  * Returns:
2529  *      ql local function return status code.
2530  *
2531  * Context:
2532  *      Kernel context.
2533  */
2534 int
2535 ql_full_login_lip(ql_adapter_state_t *ha)
2536 {
2537         int             rval;
2538         mbx_cmd_t       mc = {0};
2539         mbx_cmd_t       *mcp = &mc;
2540 
2541         QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
2542 
2543         mcp->mb[0] = MBC_LIP_FULL_LOGIN;
2544         if (CFG_IST(ha, CFG_CTRL_2425)) {
2545                 mcp->mb[1] = BIT_3;
2546         } else if (CFG_IST(ha, CFG_CTRL_8081)) {
2547                 mcp->mb[1] = BIT_1;
2548         }
2549         mcp->out_mb = MBX_3|MBX_2|MBX_1|MBX_0;
2550         mcp->in_mb = MBX_0;
2551         mcp->timeout = MAILBOX_TOV;
2552         rval = ql_mailbox_command(ha, mcp);
2553 
2554         if (rval != QL_SUCCESS) {
2555                 EL(ha, "failed, rval = %xh\n", rval);
2556         } else {
2557                 /*EMPTY*/
2558                 QL_PRINT_3(CE_CONT, "(%d): done", ha->instance);
2559         }
2560 
2561         return (rval);
2562 }
2563 
2564 /*
2565  * ql_lip_reset
2566  *      Issue lip reset to a port.
2567  *
2568  * Input:
2569  *      ha:             adapter state pointer.
2570  *      loop_id:        FC loop id.
2571  *
2572  * Returns:
2573  *      ql local function return status code.
2574  *
2575  * Context:
2576  *      Kernel context.
2577  */
2578 int
2579 ql_lip_reset(ql_adapter_state_t *ha, uint16_t loop_id)
2580 {
2581         int             rval;
2582         mbx_cmd_t       mc = {0};
2583         mbx_cmd_t       *mcp = &mc;
2584 
2585         QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
2586 
2587         if (CFG_IST(ha, CFG_CTRL_24258081)) {
2588                 mcp->mb[0] = MBC_LIP_FULL_LOGIN;
2589                 mcp->mb[1] = (uint16_t)(CFG_IST(ha, CFG_CTRL_8081) ?
2590                     BIT_1 : BIT_6);
2591                 mcp->mb[3] = ha->loop_reset_delay;
2592                 mcp->out_mb = MBX_3|MBX_2|MBX_1|MBX_0;
2593         } else {
2594                 mcp->mb[0] = MBC_LIP_RESET;
2595                 if (CFG_IST(ha, CFG_EXT_FW_INTERFACE)) {
2596                         mcp->mb[1] = loop_id;
2597                         mcp->out_mb = MBX_10|MBX_3|MBX_2|MBX_1|MBX_0;
2598                 } else {
2599                         mcp->mb[1] = (uint16_t)(loop_id << 8);
2600                         mcp->out_mb = MBX_3|MBX_2|MBX_1|MBX_0;
2601                 }
2602                 mcp->mb[2] = ha->loop_reset_delay;
2603         }
2604         mcp->in_mb = MBX_0;
2605         mcp->timeout = MAILBOX_TOV;
2606         rval = ql_mailbox_command(ha, mcp);
2607 
2608         if (rval != QL_SUCCESS) {
2609                 EL(ha, "failed, rval = %xh\n", rval);
2610         } else {
2611                 /*EMPTY*/
2612                 QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
2613         }
2614 
2615         return (rval);
2616 }
2617 
2618 /*
2619  * ql_abort_command
2620  *      Abort command aborts a specified IOCB.
2621  *
2622  * Input:
2623  *      ha:     adapter state pointer.
2624  *      sp:     SRB structure pointer.
2625  *
2626  * Returns:
2627  *      ql local function return status code.
2628  *
2629  * Context:
2630  *      Kernel context.
2631  */
2632 int
2633 ql_abort_command(ql_adapter_state_t *ha, ql_srb_t *sp)
2634 {
2635         int             rval;
2636         mbx_cmd_t       mc = {0};
2637         mbx_cmd_t       *mcp = &mc;
2638         ql_tgt_t        *tq = sp->lun_queue->target_queue;
2639 
2640         QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
2641 
2642         if (CFG_IST(ha, CFG_CTRL_24258081)) {
2643                 rval = ql_abort_cmd_iocb(ha, sp);
2644         } else {
2645                 mcp->mb[0] = MBC_ABORT_COMMAND_IOCB;
2646                 if (CFG_IST(ha, CFG_EXT_FW_INTERFACE)) {
2647                         mcp->mb[1] = tq->loop_id;
2648                 } else {
2649                         mcp->mb[1] = (uint16_t)(tq->loop_id << 8);
2650                 }
2651                 mcp->mb[2] = LSW(sp->handle);
2652                 mcp->mb[3] = MSW(sp->handle);
2653                 mcp->mb[6] = (uint16_t)(sp->flags & SRB_FCP_CMD_PKT ?
2654                     sp->lun_queue->lun_no : 0);
2655                 mcp->out_mb = MBX_6|MBX_3|MBX_2|MBX_1|MBX_0;
2656                 mcp->in_mb = MBX_0;
2657                 mcp->timeout = MAILBOX_TOV;
2658                 rval = ql_mailbox_command(ha, mcp);
2659         }
2660 
2661         if (rval != QL_SUCCESS) {
2662                 EL(ha, "failed=%xh, d_id=%xh, handle=%xh\n", rval,
2663                     tq->d_id.b24, sp->handle);
2664         } else {
2665                 /*EMPTY*/
2666                 QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
2667         }
2668 
2669         return (rval);
2670 }
2671 
2672 /*
2673  * ql_abort_cmd_iocb
2674  *      Function issues abort command IOCB.
2675  *
2676  * Input:
2677  *      ha:     adapter state pointer.
2678  *      sp:     SRB structure pointer.
2679  *
2680  * Returns:
2681  *      ql local function return status code.
2682  *
2683  * Context:
2684  *      Interrupt or Kernel context, no mailbox commands allowed.
2685  */
2686 static int
2687 ql_abort_cmd_iocb(ql_adapter_state_t *ha, ql_srb_t *sp)
2688 {
2689         ql_mbx_iocb_t   *pkt;
2690         int             rval;
2691         uint32_t        pkt_size;
2692         uint16_t        comp_status;
2693         ql_tgt_t        *tq = sp->lun_queue->target_queue;
2694 
2695         QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
2696 
2697         pkt_size = sizeof (ql_mbx_iocb_t);
2698         if ((pkt = kmem_zalloc(pkt_size, KM_SLEEP)) == NULL) {
2699                 EL(ha, "failed, kmem_zalloc\n");
2700                 return (QL_MEMORY_ALLOC_FAILED);
2701         }
2702 
2703         pkt->abo.entry_type = ABORT_CMD_TYPE;
2704         pkt->abo.entry_count = 1;
2705         pkt->abo.n_port_hdl = (uint16_t)LE_16(tq->loop_id);
2706         if (!CFG_IST(ha, CFG_CTRL_8021)) {
2707                 pkt->abo.options = AF_NO_ABTS;
2708         }
2709         pkt->abo.cmd_handle = LE_32(sp->handle);
2710         pkt->abo.target_id[0] = tq->d_id.b.al_pa;
2711         pkt->abo.target_id[1] = tq->d_id.b.area;
2712         pkt->abo.target_id[2] = tq->d_id.b.domain;
2713         pkt->abo.vp_index = ha->vp_index;
2714 
2715         rval = ql_issue_mbx_iocb(ha, (caddr_t)pkt, pkt_size);
2716 
2717         if (rval == QL_SUCCESS) {
2718                 if ((pkt->abo.entry_status  & 0x3c) != 0) {
2719                         EL(ha, "failed, entry_status=%xh, d_id=%xh\n",
2720                             pkt->abo.entry_status, tq->d_id.b24);
2721                         rval = QL_FUNCTION_PARAMETER_ERROR;
2722                 } else {
2723                         comp_status = (uint16_t)LE_16(pkt->abo.n_port_hdl);
2724                         if (comp_status != CS_COMPLETE) {
2725                                 EL(ha, "failed, comp_status=%xh, d_id=%xh\n",
2726                                     comp_status, tq->d_id.b24);
2727                                 rval = QL_FUNCTION_FAILED;
2728                         }
2729                 }
2730         }
2731 
2732         kmem_free(pkt, pkt_size);
2733 
2734         if (rval != QL_SUCCESS) {
2735                 EL(ha, "failed=%xh, d_id=%xh\n", rval, tq->d_id.b24);
2736         } else {
2737                 /*EMPTY*/
2738                 QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
2739         }
2740 
2741         return (rval);
2742 }
2743 
2744 /*
2745  * ql_verify_checksum
2746  *      Verify loaded RISC firmware.
2747  *
2748  * Input:
2749  *      ha = adapter state pointer.
2750  *
2751  * Returns:
2752  *      ql local function return status code.
2753  *
2754  * Context:
2755  *      Kernel context.
2756  */
2757 int
2758 ql_verify_checksum(ql_adapter_state_t *ha)
2759 {
2760         int             rval;
2761         mbx_cmd_t       mc = {0};
2762         mbx_cmd_t       *mcp = &mc;
2763 
2764         QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
2765 
2766         mcp->mb[0] = MBC_VERIFY_CHECKSUM;
2767         if (CFG_IST(ha, CFG_CTRL_24258081)) {
2768                 mcp->mb[1] = MSW(ha->risc_fw[0].addr);
2769                 mcp->mb[2] = LSW(ha->risc_fw[0].addr);
2770         } else {
2771                 mcp->mb[1] = LSW(ha->risc_fw[0].addr);
2772         }
2773         mcp->out_mb = MBX_2|MBX_1|MBX_0;
2774         mcp->in_mb = MBX_2|MBX_1|MBX_0;
2775         mcp->timeout = MAILBOX_TOV;
2776         rval = ql_mailbox_command(ha, mcp);
2777 
2778         if (rval != QL_SUCCESS) {
2779                 EL(ha, "failed, rval = %xh\n", rval);
2780         } else {
2781                 /*EMPTY*/
2782                 QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
2783         }
2784 
2785         return (rval);
2786 }
2787 
2788 /*
2789  * ql_get_id_list
2790  *      Get d_id and loop ID list.
2791  *
2792  * Input:
2793  *      ha:     adapter state pointer.
2794  *      bp:     data pointer for DMA data.
2795  *      size:   size of data buffer.
2796  *      mr:     pointer for mailbox data.
2797  *
2798  * Returns:
2799  *      ql local function return status code.
2800  *
2801  * Context:
2802  *      Kernel context.
2803  */
2804 int
2805 ql_get_id_list(ql_adapter_state_t *ha, caddr_t bp, uint32_t size,
2806     ql_mbx_data_t *mr)
2807 {
2808         int             rval;
2809         dma_mem_t       mem_desc;
2810         mbx_cmd_t       mc = {0};
2811         mbx_cmd_t       *mcp = &mc;
2812 
2813         QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
2814 
2815         if ((rval = ql_setup_mbox_dma_resources(ha, &mem_desc,
2816             (uint32_t)size)) != QL_SUCCESS) {
2817                 EL(ha, "setup_mbox_dma_resources failed: %xh\n", rval);
2818                 return (QL_MEMORY_ALLOC_FAILED);
2819         }
2820 
2821         mcp->mb[0] = MBC_GET_ID_LIST;
2822         if (CFG_IST(ha, CFG_CTRL_24258081)) {
2823                 mcp->mb[2] = MSW(LSD(mem_desc.cookie.dmac_laddress));
2824                 mcp->mb[3] = LSW(LSD(mem_desc.cookie.dmac_laddress));
2825                 mcp->mb[6] = MSW(MSD(mem_desc.cookie.dmac_laddress));
2826                 mcp->mb[7] = LSW(MSD(mem_desc.cookie.dmac_laddress));
2827                 mcp->mb[8] = (uint16_t)size;
2828                 mcp->mb[9] = ha->vp_index;
2829                 mcp->out_mb = MBX_9|MBX_8|MBX_7|MBX_6|MBX_3|MBX_2|MBX_0;
2830         } else {
2831                 mcp->mb[1] = MSW(LSD(mem_desc.cookie.dmac_laddress));
2832                 mcp->mb[2] = LSW(LSD(mem_desc.cookie.dmac_laddress));
2833                 mcp->mb[3] = MSW(MSD(mem_desc.cookie.dmac_laddress));
2834                 mcp->mb[6] = LSW(MSD(mem_desc.cookie.dmac_laddress));
2835                 mcp->out_mb = MBX_6|MBX_3|MBX_2|MBX_1|MBX_0;
2836         }
2837         mcp->in_mb = MBX_1|MBX_0;
2838         mcp->timeout = MAILBOX_TOV;
2839         rval = ql_mailbox_command(ha, mcp);
2840 
2841         if (rval == QL_SUCCESS) {
2842                 ql_get_mbox_dma_data(&mem_desc, bp);
2843         }
2844 
2845         ql_free_dma_resource(ha, &mem_desc);
2846 
2847         /* Return mailbox data. */
2848         if (mr != NULL) {
2849                 mr->mb[0] = mcp->mb[0];
2850                 mr->mb[1] = mcp->mb[1];
2851         }
2852 
2853         if (rval != QL_SUCCESS) {
2854                 EL(ha, "failed, rval = %xh\n", rval);
2855         } else {
2856                 /*EMPTY*/
2857                 QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
2858         }
2859 
2860         return (rval);
2861 }
2862 
2863 /*
2864  * ql_wrt_risc_ram
2865  *      Load RISC RAM.
2866  *
2867  * Input:
2868  *      ha:             adapter state pointer.
2869  *      risc_address:   risc ram word address.
2870  *      bp:             DMA pointer.
2871  *      word_count:     16/32bit word count.
2872  *
2873  * Returns:
2874  *      ql local function return status code.
2875  *
2876  * Context:
2877  *      Kernel context.
2878  */
2879 int
2880 ql_wrt_risc_ram(ql_adapter_state_t *ha, uint32_t risc_address, uint64_t bp,
2881     uint32_t word_count)
2882 {
2883         int             rval;
2884         mbx_cmd_t       mc = {0};
2885         mbx_cmd_t       *mcp = &mc;
2886 
2887         QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
2888 
2889         if (CFG_IST(ha, CFG_CTRL_242581)) {
2890                 mcp->mb[0] = MBC_LOAD_RAM_EXTENDED;
2891                 mcp->mb[4] = MSW(word_count);
2892                 mcp->mb[5] = LSW(word_count);
2893                 mcp->mb[6] = MSW(MSD(bp));
2894                 mcp->mb[7] = LSW(MSD(bp));
2895                 mcp->mb[8] = MSW(risc_address);
2896                 mcp->out_mb = MBX_8|MBX_7|MBX_6|MBX_5|MBX_4|MBX_3|MBX_2|MBX_1|
2897                     MBX_0;
2898         } else {
2899                 mcp->mb[0] = MBC_LOAD_RAM;
2900                 mcp->mb[4] = LSW(word_count);
2901                 mcp->out_mb = MBX_4|MBX_3|MBX_2|MBX_1|MBX_0;
2902         }
2903         mcp->mb[1] = LSW(risc_address);
2904         mcp->mb[2] = MSW(LSD(bp));
2905         mcp->mb[3] = LSW(LSD(bp));
2906         mcp->in_mb = MBX_0;
2907         mcp->timeout = MAILBOX_TOV;
2908 
2909         rval = ql_mailbox_command(ha, mcp);
2910 
2911         if (rval != QL_SUCCESS) {
2912                 EL(ha, "failed, rval = %xh\n", rval);
2913         } else {
2914                 /*EMPTY*/
2915                 QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
2916         }
2917 
2918         return (rval);
2919 }
2920 
2921 /*
2922  * ql_rd_risc_ram
2923  *      Get RISC RAM.
2924  *
2925  * Input:
2926  *      ha:             adapter state pointer.
2927  *      risc_address:   risc ram word address.
2928  *      bp:             direct data pointer.
2929  *      word_count:     16/32bit word count.
2930  *
2931  * Returns:
2932  *      ql local function return status code.
2933  *
2934  * Context:
2935  *      Kernel context.
2936  */
2937 int
2938 ql_rd_risc_ram(ql_adapter_state_t *ha, uint32_t risc_address, uint64_t bp,
2939     uint32_t word_count)
2940 {
2941         int             rval;
2942         mbx_cmd_t       mc = {0};
2943         mbx_cmd_t       *mcp = &mc;
2944 
2945         QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
2946 
2947         if (CFG_IST(ha, CFG_CTRL_242581)) {
2948                 mcp->mb[0] = MBC_DUMP_RAM_EXTENDED;
2949                 mcp->mb[1] = LSW(risc_address);
2950                 mcp->mb[2] = MSW(LSD(bp));
2951                 mcp->mb[3] = LSW(LSD(bp));
2952                 mcp->mb[4] = MSW(word_count);
2953                 mcp->mb[5] = LSW(word_count);
2954                 mcp->mb[6] = MSW(MSD(bp));
2955                 mcp->mb[7] = LSW(MSD(bp));
2956                 mcp->mb[8] = MSW(risc_address);
2957                 mcp->out_mb = MBX_8|MBX_7|MBX_6|MBX_5|MBX_4|MBX_3|MBX_2|MBX_1|
2958                     MBX_0;
2959         } else {
2960                 mcp->mb[0] = MBC_DUMP_RAM;   /* doesn't support 64bit addr */
2961                 mcp->mb[1] = LSW(risc_address);
2962                 mcp->mb[2] = MSW(LSD(bp));
2963                 mcp->mb[3] = LSW(LSD(bp));
2964                 mcp->mb[4] = LSW(word_count);
2965                 mcp->out_mb = MBX_4|MBX_3|MBX_2|MBX_1|MBX_0;
2966         }
2967         mcp->in_mb = MBX_0;
2968         mcp->timeout = MAILBOX_TOV;
2969         rval = ql_mailbox_command(ha, mcp);
2970 
2971         if (rval != QL_SUCCESS) {
2972                 EL(ha, "failed, rval = %xh\n", rval);
2973         } else {
2974                 /*EMPTY*/
2975                 QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
2976         }
2977 
2978         return (rval);
2979 }
2980 
2981 /*
2982  * ql_wrt_risc_ram_word
2983  *      Write RISC RAM word.
2984  *
2985  * Input:
2986  *      ha:             adapter state pointer.
2987  *      risc_address:   risc ram word address.
2988  *      data:           data.
2989  *
2990  * Returns:
2991  *      ql local function return status code.
2992  *
2993  * Context:
2994  *      Kernel context.
2995  */
2996 int
2997 ql_wrt_risc_ram_word(ql_adapter_state_t *ha, uint32_t risc_address,
2998     uint32_t data)
2999 {
3000         int             rval;
3001         mbx_cmd_t       mc = {0};
3002         mbx_cmd_t       *mcp = &mc;
3003 
3004         QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
3005 
3006         mcp->mb[0] = MBC_WRITE_RAM_EXTENDED;
3007         mcp->mb[1] = LSW(risc_address);
3008         mcp->mb[2] = LSW(data);
3009         mcp->mb[3] = MSW(data);
3010         mcp->mb[8] = MSW(risc_address);
3011         mcp->out_mb = MBX_8|MBX_3|MBX_2|MBX_1|MBX_0;
3012         mcp->in_mb = MBX_0;
3013         mcp->timeout = MAILBOX_TOV;
3014 
3015         rval = ql_mailbox_command(ha, mcp);
3016 
3017         if (rval != QL_SUCCESS) {
3018                 EL(ha, "failed, rval = %xh\n", rval);
3019         } else {
3020                 /*EMPTY*/
3021                 QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
3022         }
3023 
3024         return (rval);
3025 }
3026 
3027 /*
3028  * ql_rd_risc_ram_word
3029  *      Read RISC RAM word.
3030  *
3031  * Input:
3032  *      ha:             adapter state pointer.
3033  *      risc_address:   risc ram word address.
3034  *      data:           data pointer.
3035  *
3036  * Returns:
3037  *      ql local function return status code.
3038  *
3039  * Context:
3040  *      Kernel context.
3041  */
3042 int
3043 ql_rd_risc_ram_word(ql_adapter_state_t *ha, uint32_t risc_address,
3044     uint32_t *data)
3045 {
3046         int             rval;
3047         mbx_cmd_t       mc = {0};
3048         mbx_cmd_t       *mcp = &mc;
3049 
3050         QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
3051 
3052         mcp->mb[0] = MBC_READ_RAM_EXTENDED;
3053         mcp->mb[1] = LSW(risc_address);
3054         mcp->mb[8] = MSW(risc_address);
3055         mcp->out_mb = MBX_8|MBX_1|MBX_0;
3056         mcp->in_mb = MBX_3|MBX_2|MBX_0;
3057         mcp->timeout = MAILBOX_TOV;
3058 
3059         rval = ql_mailbox_command(ha, mcp);
3060 
3061         if (rval != QL_SUCCESS) {
3062                 EL(ha, "failed, rval = %xh\n", rval);
3063         } else {
3064                 *data = mcp->mb[2];
3065                 if (CFG_IST(ha, CFG_CTRL_24258081)) {
3066                         *data |= mcp->mb[3] << 16;
3067                 }
3068                 QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
3069         }
3070 
3071         return (rval);
3072 }
3073 
3074 /*
3075  * ql_issue_mbx_iocb
3076  *      Issue IOCB using mailbox command
3077  *
3078  * Input:
3079  *      ha:     adapter state pointer.
3080  *      bp:     buffer pointer.
3081  *      size:   buffer size.
3082  *
3083  * Returns:
3084  *      ql local function return status code.
3085  *
3086  * Context:
3087  *      Kernel context.
3088  */
3089 int
3090 ql_issue_mbx_iocb(ql_adapter_state_t *ha, caddr_t bp, uint32_t size)
3091 {
3092         int             rval;
3093         dma_mem_t       mem_desc;
3094         mbx_cmd_t       mc = {0};
3095         mbx_cmd_t       *mcp = &mc;
3096 
3097         QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
3098 
3099         if ((rval = ql_setup_mbox_dma_transfer(ha, &mem_desc, bp, size)) !=
3100             QL_SUCCESS) {
3101                 EL(ha, "setup_mbox_dma_transfer failed: %x\n", rval);
3102                 return (rval);
3103         }
3104 
3105         mcp->mb[0] = MBC_EXECUTE_IOCB;
3106         mcp->mb[2] = MSW(LSD(mem_desc.cookie.dmac_laddress));
3107         mcp->mb[3] = LSW(LSD(mem_desc.cookie.dmac_laddress));
3108         mcp->mb[6] = MSW(MSD(mem_desc.cookie.dmac_laddress));
3109         mcp->mb[7] = LSW(MSD(mem_desc.cookie.dmac_laddress));
3110         mcp->out_mb = MBX_7|MBX_6|MBX_3|MBX_2|MBX_1|MBX_0;
3111         mcp->in_mb = MBX_1|MBX_0;
3112         mcp->timeout = MAILBOX_TOV + 5;
3113         rval = ql_mailbox_command(ha, mcp);
3114 
3115         if (rval == QL_SUCCESS) {
3116                 ql_get_mbox_dma_data(&mem_desc, bp);
3117         }
3118 
3119         ql_free_dma_resource(ha, &mem_desc);
3120 
3121         if (rval != QL_SUCCESS) {
3122                 EL(ha, "failed=%xh, mbx1=%xh\n", rval, mcp->mb[1]);
3123         } else {
3124                 /*EMPTY*/
3125                 QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
3126         }
3127 
3128         return (rval);
3129 }
3130 
3131 /*
3132  * ql_mbx_wrap_test
3133  *      Mailbox register wrap test.
3134  *
3135  * Input:
3136  *      ha:     adapter state pointer.
3137  *      mr:     pointer for in/out mailbox data.
3138  *
3139  * Returns:
3140  *      ql local function return status code.
3141  *
3142  * Context:
3143  *      Kernel context.
3144  */
3145 int
3146 ql_mbx_wrap_test(ql_adapter_state_t *ha, ql_mbx_data_t *mr)
3147 {
3148         int             rval;
3149         mbx_cmd_t       mc = {0};
3150         mbx_cmd_t       *mcp = &mc;
3151 
3152         QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
3153 
3154         if (mr != NULL) {
3155                 mcp->mb[0] = MBC_MAILBOX_REGISTER_TEST;
3156                 mcp->mb[1] = mr->mb[1];
3157                 mcp->mb[2] = mr->mb[2];
3158                 mcp->mb[3] = mr->mb[3];
3159                 mcp->mb[4] = mr->mb[4];
3160                 mcp->mb[5] = mr->mb[5];
3161                 mcp->mb[6] = mr->mb[6];
3162                 mcp->mb[7] = mr->mb[7];
3163                 mcp->out_mb = MBX_7|MBX_6|MBX_5|MBX_4|MBX_3|MBX_2|MBX_1|MBX_0;
3164                 mcp->in_mb = MBX_7|MBX_6|MBX_5|MBX_4|MBX_3|MBX_2|MBX_1|MBX_0;
3165                 mcp->timeout = MAILBOX_TOV;
3166                 rval = ql_mailbox_command(ha, mcp);
3167                 if (rval == QL_SUCCESS) {
3168                         mr->mb[1] = mcp->mb[1];
3169                         mr->mb[2] = mcp->mb[2];
3170                         mr->mb[3] = mcp->mb[3];
3171                         mr->mb[4] = mcp->mb[4];
3172                         mr->mb[5] = mcp->mb[5];
3173                         mr->mb[6] = mcp->mb[6];
3174                         mr->mb[7] = mcp->mb[7];
3175                 }
3176         } else {
3177                 rval = QL_FUNCTION_PARAMETER_ERROR;
3178         }
3179 
3180         if (rval != QL_SUCCESS) {
3181                 EL(ha, "failed=%xh\n", rval);
3182         } else {
3183                 /*EMPTY*/
3184                 QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
3185         }
3186 
3187         return (rval);
3188 }
3189 
3190 /*
3191  * ql_execute_fw
3192  *      Start adapter firmware.
3193  *
3194  * Input:
3195  *      ha:     adapter state pointer.
3196  *
3197  * Returns:
3198  *      ql local function return status code.
3199  *
3200  * Context:
3201  *      Kernel context.
3202  */
3203 int
3204 ql_execute_fw(ql_adapter_state_t *ha)
3205 {
3206         int             rval;
3207         mbx_cmd_t       mc = {0};
3208         mbx_cmd_t       *mcp = &mc;
3209 
3210         QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
3211 
3212         if (CFG_IST(ha, CFG_CTRL_8021)) {
3213                 return (QL_SUCCESS);
3214         }
3215 
3216         mcp->mb[0] = MBC_EXECUTE_FIRMWARE;
3217         if (CFG_IST(ha, CFG_CTRL_242581)) {
3218                 mcp->mb[1] = MSW(ha->risc_fw[0].addr);
3219                 mcp->mb[2] = LSW(ha->risc_fw[0].addr);
3220         } else {
3221                 mcp->mb[1] = LSW(ha->risc_fw[0].addr);
3222         }
3223         if (CFG_IST(ha, CFG_LR_SUPPORT)) {
3224                 mcp->mb[4] = BIT_0;
3225         }
3226         mcp->out_mb = MBX_4|MBX_3|MBX_2|MBX_1|MBX_0;
3227         mcp->in_mb = MBX_0;
3228         mcp->timeout = MAILBOX_TOV;
3229         rval = ql_mailbox_command(ha, mcp);
3230 
3231         if (CFG_IST(ha, CFG_CTRL_2200)) {
3232                 rval = QL_SUCCESS;
3233         }
3234 
3235         if (rval != QL_SUCCESS) {
3236                 EL(ha, "failed=%xh\n", rval);
3237         } else {
3238                 /*EMPTY*/
3239                 QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
3240         }
3241 
3242         return (rval);
3243 }
3244 
3245 /*
3246  * ql_get_firmware_option
3247  *       Get Firmware Options Mailbox Command.
3248  *
3249  * Input:
3250  *      ha:     adapter state pointer.
3251  *      mr:     pointer for mailbox data.
3252  *
3253  * Returns:
3254  *      ql local function return status code.
3255  *
3256  * Context:
3257  *      Kernel context.
3258  */
3259 int
3260 ql_get_firmware_option(ql_adapter_state_t *ha, ql_mbx_data_t *mr)
3261 {
3262         int             rval;
3263         mbx_cmd_t       mc = {0};
3264         mbx_cmd_t       *mcp = &mc;
3265 
3266         QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
3267 
3268         mcp->mb[0] = MBC_GET_FIRMWARE_OPTIONS;
3269         mcp->out_mb = MBX_0;
3270         mcp->in_mb = MBX_3|MBX_2|MBX_1|MBX_0;
3271         mcp->timeout = MAILBOX_TOV;
3272         rval = ql_mailbox_command(ha, mcp);
3273 
3274         /* Return mailbox data. */
3275         if (mr != NULL) {
3276                 mr->mb[0] = mcp->mb[0];
3277                 mr->mb[1] = mcp->mb[1];
3278                 mr->mb[2] = mcp->mb[2];
3279                 mr->mb[3] = mcp->mb[3];
3280         }
3281 
3282         if (rval != QL_SUCCESS) {
3283                 EL(ha, "failed=%xh\n", rval);
3284         } else {
3285                 /*EMPTY*/
3286                 QL_PRINT_9(CE_CONT, "(%d): done\n", ha->instance);
3287         }
3288 
3289         return (rval);
3290 }
3291 
3292 /*
3293  * ql_set_firmware_option
3294  *       Set Firmware Options Mailbox Command.
3295  *
3296  * Input:
3297  *      ha:     adapter state pointer.
3298  *      mr:     pointer for mailbox data.
3299  *
3300  * Returns:
3301  *      ql local function return status code.
3302  *
3303  * Context:
3304  *      Kernel context.
3305  */
3306 int
3307 ql_set_firmware_option(ql_adapter_state_t *ha, ql_mbx_data_t *mr)
3308 {
3309         int             rval;
3310         mbx_cmd_t       mc = {0};
3311         mbx_cmd_t       *mcp = &mc;
3312 
3313         QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
3314 
3315         if (mr != NULL) {
3316                 mcp->mb[0] = MBC_SET_FIRMWARE_OPTIONS;
3317                 mcp->mb[1] = mr->mb[1];
3318                 mcp->mb[2] = mr->mb[2];
3319                 mcp->mb[3] = mr->mb[3];
3320                 mcp->out_mb = MBX_3|MBX_2|MBX_1|MBX_0;
3321                 mcp->in_mb = MBX_0;
3322                 mcp->timeout = MAILBOX_TOV;
3323                 rval = ql_mailbox_command(ha, mcp);
3324         } else {
3325                 rval = QL_FUNCTION_PARAMETER_ERROR;
3326         }
3327 
3328         if (rval != QL_SUCCESS) {
3329                 EL(ha, "failed=%xh\n", rval);
3330         } else {
3331                 /*EMPTY*/
3332                 QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
3333         }
3334 
3335         return (rval);
3336 }
3337 
3338 /*
3339  * ql_init_firmware
3340  *       Initialize firmware mailbox command.
3341  *
3342  * Input:
3343  *      ha:     adapter state pointer.
3344  *      ha->init_ctrl_blk = setup for transmit.
3345  *
3346  * Returns:
3347  *      ql local function return status code.
3348  *
3349  * Context:
3350  *      Kernel context.
3351  */
3352 int
3353 ql_init_firmware(ql_adapter_state_t *ha)
3354 {
3355         int             rval;
3356         dma_mem_t       mem_desc;
3357         mbx_cmd_t       mc = {0};
3358         mbx_cmd_t       *mcp = &mc;
3359 
3360         QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
3361 
3362         if (CFG_IST(ha, CFG_CTRL_8021)) {
3363                 WRT32_IO_REG(ha, req_out, 0);
3364                 WRT32_IO_REG(ha, resp_in, 0);
3365                 WRT32_IO_REG(ha, resp_out, 0);
3366         } else if (CFG_IST(ha, CFG_CTRL_242581)) {
3367                 WRT32_IO_REG(ha, req_in, 0);
3368                 WRT32_IO_REG(ha, resp_out, 0);
3369                 WRT32_IO_REG(ha, pri_req_in, 0);
3370                 WRT32_IO_REG(ha, atio_req_out, 0);
3371         } else {
3372                 WRT16_IO_REG(ha, req_in, 0);
3373                 WRT16_IO_REG(ha, resp_out, 0);
3374         }
3375 
3376         if ((rval = ql_setup_mbox_dma_transfer(ha, &mem_desc,
3377             (caddr_t)&ha->init_ctrl_blk, sizeof (ql_comb_init_cb_t))) !=
3378             QL_SUCCESS) {
3379                 EL(ha, "dma setup failed=%xh\n", rval);
3380                 return (rval);
3381         }
3382 
3383         mcp->mb[0] = (uint16_t)(ha->flags & VP_ENABLED ?
3384             MBC_INITIALIZE_MULTI_ID_FW : MBC_INITIALIZE_FIRMWARE);
3385 
3386         if (CFG_IST(ha, CFG_SBUS_CARD)) {
3387                 mcp->mb[1] = (uint16_t)(CFG_IST(ha, CFG_CTRL_2200) ?
3388                     0x204c : 0x52);
3389         }
3390 
3391         mcp->mb[2] = MSW(LSD(mem_desc.cookie.dmac_laddress));
3392         mcp->mb[3] = LSW(LSD(mem_desc.cookie.dmac_laddress));
3393         mcp->mb[6] = MSW(MSD(mem_desc.cookie.dmac_laddress));
3394         mcp->mb[7] = LSW(MSD(mem_desc.cookie.dmac_laddress));
3395         if (CFG_IST(ha, CFG_CTRL_8081)) {
3396                 uint64_t                ofst, addr;
3397                 ql_init_24xx_cb_t       *icb = (ql_init_24xx_cb_t *)
3398                     &ha->init_ctrl_blk.cb24;
3399 
3400                 mcp->mb[0] = MBC_INITIALIZE_MULTI_ID_FW;
3401                 if (icb->ext_blk.version[0] | icb->ext_blk.version[1]) {
3402                         ofst = (uintptr_t)&icb->ext_blk - (uintptr_t)icb;
3403                         addr = mem_desc.cookie.dmac_laddress + ofst;
3404                         mcp->mb[10] = MSW(LSD(addr));
3405                         mcp->mb[11] = LSW(LSD(addr));
3406                         mcp->mb[12] = MSW(MSD(addr));
3407                         mcp->mb[13] = LSW(MSD(addr));
3408                         mcp->mb[14] = sizeof (ql_ext_icb_8100_t);
3409                         mcp->mb[1] = BIT_0;
3410                 }
3411                 mcp->out_mb = MBX_14|MBX_13|MBX_12|MBX_11|MBX_10|MBX_7|MBX_6|
3412                     MBX_5|MBX_4|MBX_3|MBX_2|MBX_1|MBX_0;
3413         } else {
3414                 mcp->out_mb = MBX_7|MBX_6|MBX_5|MBX_4|MBX_3|MBX_2|MBX_1|MBX_0;
3415         }
3416         mcp->in_mb = MBX_5|MBX_4|MBX_2|MBX_0;
3417         mcp->timeout = MAILBOX_TOV;
3418         rval = ql_mailbox_command(ha, mcp);
3419 
3420         if (rval == QL_SUCCESS) {
3421                 ha->sfp_stat = mcp->mb[2];
3422         }
3423         ql_free_dma_resource(ha, &mem_desc);
3424 
3425         if (rval != QL_SUCCESS) {
3426                 EL(ha, "failed=%xh\n", rval);
3427         } else {
3428                 /*EMPTY*/
3429                 QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
3430         }
3431 
3432         return (rval);
3433 }
3434 
3435 /*
3436  * ql_get_firmware_state
3437  *      Get adapter firmware state.
3438  *
3439  * Input:
3440  *      ha:     adapter state pointer.
3441  *      mr:     pointer for mailbox data.
3442  *
3443  * Returns:
3444  *      ql local function return status code.
3445  *
3446  * Context:
3447  *      Kernel context.
3448  */
3449 int
3450 ql_get_firmware_state(ql_adapter_state_t *ha, ql_mbx_data_t *mr)
3451 {
3452         int             rval;
3453         mbx_cmd_t       mc = {0};
3454         mbx_cmd_t       *mcp = &mc;
3455 
3456         QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
3457 
3458         mcp->mb[0] = MBC_GET_FIRMWARE_STATE;
3459         mcp->out_mb = MBX_0;
3460         mcp->in_mb = MBX_5|MBX_4|MBX_3|MBX_2|MBX_1|MBX_0;
3461         mcp->timeout = MAILBOX_TOV;
3462         rval = ql_mailbox_command(ha, mcp);
3463 
3464         /* Return mailbox data. */
3465         if (mr != NULL) {
3466                 mr->mb[1] = mcp->mb[1];
3467                 mr->mb[2] = mcp->mb[2];
3468                 mr->mb[3] = mcp->mb[3];
3469                 mr->mb[4] = mcp->mb[4];
3470                 mr->mb[5] = mcp->mb[5];
3471         }
3472 
3473         ha->sfp_stat = mcp->mb[2];
3474 
3475         if (rval != QL_SUCCESS) {
3476                 EL(ha, "failed=%xh\n", rval);
3477         } else {
3478                 /*EMPTY*/
3479                 QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
3480         }
3481 
3482         return (rval);
3483 }
3484 
3485 /*
3486  * ql_get_adapter_id
3487  *      Get adapter ID and topology.
3488  *
3489  * Input:
3490  *      ha:     adapter state pointer.
3491  *      mr:     pointer for mailbox data.
3492  *
3493  * Returns:
3494  *      ql local function return status code.
3495  *
3496  * Context:
3497  *      Kernel context.
3498  */
3499 int
3500 ql_get_adapter_id(ql_adapter_state_t *ha, ql_mbx_data_t *mr)
3501 {
3502         int             rval;
3503         mbx_cmd_t       mc = {0};
3504         mbx_cmd_t       *mcp = &mc;
3505 
3506         QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
3507 
3508         mcp->mb[0] = MBC_GET_ID;
3509         if (ha->flags & VP_ENABLED) {
3510                 mcp->mb[9] = ha->vp_index;
3511         }
3512         mcp->out_mb = MBX_9|MBX_0;
3513         mcp->in_mb = MBX_13|MBX_12|MBX_11|MBX_10|MBX_9|MBX_8|MBX_7|MBX_6|
3514             MBX_3|MBX_2|MBX_1|MBX_0;
3515         mcp->timeout = MAILBOX_TOV;
3516 
3517         rval = ql_mailbox_command(ha, mcp);
3518 
3519         /* Return mailbox data. */
3520         if (mr != NULL) {
3521                 mr->mb[1] = mcp->mb[1];
3522                 mr->mb[1] = (uint16_t)(CFG_IST(ha, CFG_CTRL_24258081) ?
3523                     0xffff : mcp->mb[1]);
3524                 mr->mb[2] = mcp->mb[2];
3525                 mr->mb[3] = mcp->mb[3];
3526                 mr->mb[6] = mcp->mb[6];
3527                 mr->mb[7] = mcp->mb[7];
3528                 mr->mb[8] = mcp->mb[8];
3529                 mr->mb[9] = mcp->mb[9];
3530                 mr->mb[10] = mcp->mb[10];
3531                 mr->mb[11] = mcp->mb[11];
3532                 mr->mb[12] = mcp->mb[12];
3533                 mr->mb[13] = mcp->mb[13];
3534         }
3535 
3536         if (rval != QL_SUCCESS) {
3537                 EL(ha, "failed=%xh\n", rval);
3538         } else {
3539                 /*EMPTY*/
3540                 QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
3541         }
3542 
3543         return (rval);
3544 }
3545 
3546 /*
3547  * ql_get_fw_version
3548  *      Get firmware version.
3549  *
3550  * Input:
3551  *      ha:     adapter state pointer.
3552  *      mr:     pointer for mailbox data.
3553  *
3554  * Returns:
3555  *      ql local function return status code.
3556  *
3557  * Context:
3558  *      Kernel context.
3559  */
3560 int
3561 ql_get_fw_version(ql_adapter_state_t *ha, ql_mbx_data_t *mr, uint16_t timeout)
3562 {
3563         int             rval;
3564         mbx_cmd_t       mc = {0};
3565         mbx_cmd_t       *mcp = &mc;
3566 
3567         QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
3568 
3569         mcp->mb[0] = MBC_ABOUT_FIRMWARE;
3570         mcp->out_mb = MBX_0;
3571         mcp->in_mb = MBX_13|MBX_12|MBX_11|MBX_10|MBX_9|MBX_8|MBX_6|MBX_5|
3572             MBX_4|MBX_3|MBX_2|MBX_1|MBX_0;
3573         mcp->timeout = timeout;
3574         rval = ql_mailbox_command(ha, mcp);
3575 
3576         /* Return mailbox data. */
3577         if (mr != NULL) {
3578                 mr->mb[1] = mcp->mb[1];
3579                 mr->mb[2] = mcp->mb[2];
3580                 mr->mb[3] = mcp->mb[3];
3581                 mr->mb[4] = mcp->mb[4];
3582                 mr->mb[5] = mcp->mb[5];
3583                 mr->mb[6] = mcp->mb[6];
3584                 mr->mb[8] = mcp->mb[8];
3585                 mr->mb[9] = mcp->mb[9];
3586                 mr->mb[10] = mcp->mb[10];
3587                 mr->mb[11] = mcp->mb[11];
3588                 mr->mb[12] = mcp->mb[12];
3589                 mr->mb[13] = mcp->mb[13];
3590         }
3591 
3592         if (rval != QL_SUCCESS) {
3593                 EL(ha, "failed=%xh\n", rval);
3594         } else {
3595                 /*EMPTY*/
3596                 QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
3597         }
3598 
3599         return (rval);
3600 }
3601 
3602 /*
3603  * ql_data_rate
3604  *       Issue data rate Mailbox Command.
3605  *
3606  * Input:
3607  *      ha:     adapter state pointer.
3608  *      mr:     pointer for mailbox data.
3609  *
3610  * Returns:
3611  *      ql local function return status code.
3612  *
3613  * Context:
3614  *      Kernel context.
3615  */
3616 int
3617 ql_data_rate(ql_adapter_state_t *ha, ql_mbx_data_t *mr)
3618 {
3619         int             rval;
3620         mbx_cmd_t       mc = {0};
3621         mbx_cmd_t       *mcp = &mc;
3622 
3623         QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
3624 
3625         if (mr != NULL) {
3626                 mcp->mb[0] = MBC_DATA_RATE;
3627                 mcp->mb[1] = mr->mb[1];
3628                 mcp->mb[2] = mr->mb[2];
3629                 mcp->out_mb = MBX_2|MBX_1|MBX_0;
3630                 mcp->in_mb = MBX_2|MBX_1|MBX_0;
3631                 mcp->timeout = MAILBOX_TOV;
3632                 rval = ql_mailbox_command(ha, mcp);
3633 
3634                 /* Return mailbox data. */
3635                 mr->mb[1] = mcp->mb[1];
3636                 mr->mb[2] = mcp->mb[2];
3637         } else {
3638                 rval = QL_FUNCTION_PARAMETER_ERROR;
3639         }
3640 
3641         ha->sfp_stat = mcp->mb[2];
3642 
3643         if (rval != QL_SUCCESS) {
3644                 EL(ha, "failed=%xh\n", rval);
3645         } else {
3646                 /*EMPTY*/
3647                 QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
3648         }
3649 
3650         return (rval);
3651 }
3652 
3653 /*
3654  * ql_Diag_Loopback
3655  *      Issue Reset Link Status mailbox command
3656  *
3657  * Input:
3658  *      ha:     adapter state pointer.
3659  *      findex: FCF index.
3660  *      bp:     buffer pointer.
3661  *      size:   buffer size.
3662  *      opt:    command options.
3663  *      it_cnt: iteration count.
3664  *      mr:     pointer for mailbox data.
3665  *
3666  * Returns:
3667  *      ql local function return status code.
3668  *
3669  * Context:
3670  *      Kernel context.
3671  */
3672 int
3673 ql_diag_loopback(ql_adapter_state_t *ha, uint16_t findex, caddr_t bp,
3674     uint32_t size, uint16_t opt, uint32_t it_cnt, ql_mbx_data_t *mr)
3675 {
3676         int             rval;
3677         dma_mem_t       mem_desc;
3678         mbx_cmd_t       mc = {0};
3679         mbx_cmd_t       *mcp = &mc;
3680 
3681         QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
3682 
3683         if ((rval = ql_setup_mbox_dma_transfer(ha, &mem_desc, bp, size)) !=
3684             QL_SUCCESS) {
3685                 EL(ha, "setup_mbox_dma_transfer failed: %x\n", rval);
3686                 return (rval);
3687         }
3688 
3689         mcp->mb[0] = MBC_DIAGNOSTIC_LOOP_BACK;
3690         mcp->mb[1] = opt;
3691         mcp->mb[2] = findex;
3692         mcp->mb[6] = LSW(MSD(mem_desc.cookie.dmac_laddress));
3693         mcp->mb[7] = MSW(MSD(mem_desc.cookie.dmac_laddress));
3694         mcp->mb[10] = LSW(size);
3695         mcp->mb[11] = MSW(size);
3696         mcp->mb[14] = LSW(LSD(mem_desc.cookie.dmac_laddress));
3697         mcp->mb[15] = MSW(LSD(mem_desc.cookie.dmac_laddress));
3698         mcp->mb[16] = LSW(LSD(mem_desc.cookie.dmac_laddress));
3699         mcp->mb[17] = MSW(LSD(mem_desc.cookie.dmac_laddress));
3700         mcp->mb[18] = LSW(it_cnt);
3701         mcp->mb[19] = MSW(it_cnt);
3702         mcp->mb[20] = LSW(MSD(mem_desc.cookie.dmac_laddress));
3703         mcp->mb[21] = MSW(MSD(mem_desc.cookie.dmac_laddress));
3704         mcp->out_mb = MBX_21|MBX_20|MBX_19|MBX_18|MBX_17|MBX_16|MBX_15|
3705             MBX_14|MBX_13|MBX_12|MBX_11|MBX_10|MBX_7|MBX_6|MBX_2|MBX_1|MBX_0;
3706         mcp->in_mb = MBX_19|MBX_18|MBX_3|MBX_2|MBX_1|MBX_0;
3707         mcp->timeout = it_cnt / 300;
3708         if (mcp->timeout < MAILBOX_TOV) {
3709                 mcp->timeout = MAILBOX_TOV;
3710         }
3711         rval = ql_mailbox_command(ha, mcp);
3712 
3713         if (rval == QL_SUCCESS) {
3714                 ql_get_mbox_dma_data(&mem_desc, bp);
3715         }
3716 
3717         ql_free_dma_resource(ha, &mem_desc);
3718 
3719         /* Return mailbox data. */
3720         if (mr != NULL) {
3721                 mr->mb[0] = mcp->mb[0];
3722                 mr->mb[1] = mcp->mb[1];
3723                 mr->mb[2] = mcp->mb[2];
3724                 mr->mb[3] = mcp->mb[3];
3725                 mr->mb[18] = mcp->mb[18];
3726                 mr->mb[19] = mcp->mb[19];
3727         }
3728 
3729         if (rval != QL_SUCCESS) {
3730                 EL(ha, "failed=%xh, mb1=%xh\n", rval, mcp->mb[1]);
3731         } else {
3732                 /*EMPTY*/
3733                 QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
3734         }
3735 
3736         return (rval);
3737 }
3738 
3739 /*
3740  * ql_diag_echo
3741  *      Issue Diag echo mailbox command.  Valid for qla23xx HBA's.
3742  *
3743  * Input:
3744  *      ha:     adapter state pointer.
3745  *      findex: FCF index.
3746  *      bp:     buffer pointer.
3747  *      size:   buffer size.
3748  *      opt:    command options.
3749  *      mr:     pointer to mailbox status.
3750  *
3751  * Returns:
3752  *      ql local function return status code.
3753  *
3754  * Context:
3755  *      Kernel context.
3756  */
3757 int
3758 ql_diag_echo(ql_adapter_state_t *ha, uint16_t findex, caddr_t bp,
3759     uint32_t size, uint16_t opt, ql_mbx_data_t *mr)
3760 {
3761         int             rval;
3762         dma_mem_t       mem_desc;
3763         mbx_cmd_t       mc = {0};
3764         mbx_cmd_t       *mcp = &mc;
3765 
3766         QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
3767 
3768         if ((rval = ql_setup_mbox_dma_transfer(ha, &mem_desc, bp, size)) !=
3769             QL_SUCCESS) {
3770                 EL(ha, "setup_mbox_dma_transfer failed: %x\n", rval);
3771                 return (rval);
3772         }
3773 
3774         mcp->mb[0] = MBC_ECHO;
3775         mcp->mb[1] = opt;
3776         mcp->mb[2] = findex;
3777         mcp->mb[6] = LSW(MSD(mem_desc.cookie.dmac_laddress));
3778         mcp->mb[7] = MSW(MSD(mem_desc.cookie.dmac_laddress));
3779         mcp->mb[10] = LSW(size);
3780         mcp->mb[14] = LSW(LSD(mem_desc.cookie.dmac_laddress));
3781         mcp->mb[15] = MSW(LSD(mem_desc.cookie.dmac_laddress));
3782         mcp->mb[16] = LSW(LSD(mem_desc.cookie.dmac_laddress));
3783         mcp->mb[17] = MSW(LSD(mem_desc.cookie.dmac_laddress));
3784         mcp->mb[20] = LSW(MSD(mem_desc.cookie.dmac_laddress));
3785         mcp->mb[21] = MSW(MSD(mem_desc.cookie.dmac_laddress));
3786         mcp->out_mb = MBX_21|MBX_20|MBX_17|MBX_16|MBX_15|
3787             MBX_14|MBX_10|MBX_7|MBX_6|MBX_2|MBX_1|MBX_0;
3788         mcp->in_mb = MBX_1|MBX_0;
3789         mcp->timeout = MAILBOX_TOV;
3790         rval = ql_mailbox_command(ha, mcp);
3791 
3792         if (rval == QL_SUCCESS) {
3793                 ql_get_mbox_dma_data(&mem_desc, bp);
3794         }
3795 
3796         ql_free_dma_resource(ha, &mem_desc);
3797 
3798         if (mr != NULL) {
3799                 mr->mb[0] = mcp->mb[0];
3800         }
3801 
3802         if (rval != QL_SUCCESS) {
3803                 EL(ha, "failed=%xh, mb1=%xh\n", rval,
3804                     mcp->mb[1]);
3805         } else {
3806                 /*EMPTY*/
3807                 QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
3808         }
3809 
3810         return (rval);
3811 }
3812 
3813 /*
3814  * ql_serdes_param
3815  *      Set/Get serdes transmit parameters mailbox command.
3816  *
3817  * Input:
3818  *      ha:     adapter state pointer.
3819  *      mr:     pointer to mailbox in/out parameters.
3820  *
3821  * Returns:
3822  *      ql local function return status code.
3823  *
3824  * Context:
3825  *      Kernel context.
3826  */
3827 int
3828 ql_serdes_param(ql_adapter_state_t *ha, ql_mbx_data_t *mr)
3829 {
3830         int             rval;
3831         mbx_cmd_t       mc = {0};
3832         mbx_cmd_t       *mcp = &mc;
3833 
3834         QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
3835 
3836         mcp->mb[0] = MBC_SERDES_TRANSMIT_PARAMETERS;
3837         mcp->mb[1] = mr->mb[1];
3838         mcp->mb[2] = mr->mb[2];
3839         mcp->mb[3] = mr->mb[3];
3840         mcp->mb[4] = mr->mb[4];
3841         mcp->out_mb = MBX_4|MBX_3|MBX_2|MBX_1|MBX_0;
3842         mcp->in_mb = MBX_4|MBX_3|MBX_2|MBX_0;
3843         mcp->timeout = MAILBOX_TOV;
3844         rval = ql_mailbox_command(ha, mcp);
3845 
3846         /* Return mailbox data. */
3847         if (mr != NULL) {
3848                 mr->mb[0] = mcp->mb[0];
3849                 mr->mb[2] = mcp->mb[2];
3850                 mr->mb[3] = mcp->mb[3];
3851                 mr->mb[4] = mcp->mb[4];
3852         }
3853 
3854         if (rval != QL_SUCCESS) {
3855                 EL(ha, "failed=%xh\n", rval);
3856         } else {
3857                 /*EMPTY*/
3858                 QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
3859         }
3860 
3861         return (rval);
3862 }
3863 
3864 /*
3865  * ql_get_timeout_parameters
3866  *      Issue get timeout parameters mailbox command.
3867  *
3868  * Input:
3869  *      ha:     adapter state pointer.
3870  *      mr:     pointer to mailbox in/out parameters.
3871  *
3872  * Returns:
3873  *      ql local function return status code.
3874  *
3875  * Context:
3876  *      Kernel context.
3877  */
3878 int
3879 ql_get_timeout_parameters(ql_adapter_state_t *ha, uint16_t *tov)
3880 {
3881         int             rval;
3882         mbx_cmd_t       mc = {0};
3883         mbx_cmd_t       *mcp = &mc;
3884 
3885         QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
3886 
3887         mcp->mb[0] = MBC_GET_TIMEOUT_PARAMETERS;
3888         mcp->out_mb = MBX_0;
3889         mcp->in_mb = MBX_3|MBX_0;
3890         mcp->timeout = MAILBOX_TOV;
3891         rval = ql_mailbox_command(ha, mcp);
3892         if (rval == QL_SUCCESS) {
3893                 /* Get 2 * R_A_TOV in seconds */
3894                 if (CFG_IST(ha, CFG_CTRL_2200) || mcp->mb[3] == 0) {
3895                         *tov = R_A_TOV_DEFAULT;
3896                 } else {
3897                         *tov = (uint16_t)(mcp->mb[3] / 10);
3898                         if (mcp->mb[3] % 10 != 0) {
3899                                 *tov = (uint16_t)(*tov + 1);
3900                         }
3901                         /*
3902                          * Adjust value to prevent driver timeout at the same
3903                          * time as device.
3904                          */
3905                         *tov = (uint16_t)(*tov + 5);
3906                 }
3907         } else {
3908                 *tov = R_A_TOV_DEFAULT;
3909         }
3910 
3911         if (rval != QL_SUCCESS) {
3912                 EL(ha, "failed=%xh\n", rval);
3913         } else {
3914                 /*EMPTY*/
3915                 QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
3916         }
3917 
3918         return (rval);
3919 }
3920 
3921 /*
3922  * ql_stop_firmware
3923  *       Issue stop firmware Mailbox Command.
3924  *
3925  * Input:
3926  *      ha:     adapter state pointer.
3927  *
3928  * Returns:
3929  *      ql local function return status code.
3930  *
3931  * Context:
3932  *      Kernel context.
3933  */
3934 int
3935 ql_stop_firmware(ql_adapter_state_t *ha)
3936 {
3937         int             rval;
3938         mbx_cmd_t       mc = {0};
3939         mbx_cmd_t       *mcp = &mc;
3940 
3941         QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
3942 
3943         mcp->mb[0] = MBC_STOP_FIRMWARE;
3944         mcp->out_mb = MBX_1|MBX_0;
3945         mcp->in_mb = MBX_0;
3946         mcp->timeout = 2;
3947         rval = ql_mailbox_command(ha, mcp);
3948 
3949         if (rval != QL_SUCCESS) {
3950                 EL(ha, "failed=%xh\n", rval);
3951         } else {
3952                 /*EMPTY*/
3953                 QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
3954         }
3955 
3956         return (rval);
3957 }
3958 
3959 /*
3960  * ql_read_sfp
3961  *      Issue Read SFP Mailbox command
3962  *
3963  * Input:
3964  *      ha:     adapter state pointer.
3965  *      mem:    pointer to dma memory object for command.
3966  *      dev:    Device address (A0h or A2h).
3967  *      addr:   Data address on SFP EEPROM (0–255).
3968  *
3969  * Returns:
3970  *      ql local function return status code.
3971  *
3972  * Context:
3973  *      Kernel context.
3974  */
3975 int
3976 ql_read_sfp(ql_adapter_state_t *ha, dma_mem_t *mem, uint16_t dev,
3977     uint16_t addr)
3978 {
3979         int             rval;
3980         mbx_cmd_t       mc = {0};
3981         mbx_cmd_t       *mcp = &mc;
3982 
3983         QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
3984 
3985         mcp->mb[0] = MBC_READ_SFP;
3986         mcp->mb[1] = dev;
3987         mcp->mb[2] = MSW(mem->cookies->dmac_address);
3988         mcp->mb[3] = LSW(mem->cookies->dmac_address);
3989         mcp->mb[6] = MSW(mem->cookies->dmac_notused);
3990         mcp->mb[7] = LSW(mem->cookies->dmac_notused);
3991         mcp->mb[8] = LSW(mem->size);
3992         mcp->mb[9] = addr;
3993         mcp->out_mb = MBX_10|MBX_9|MBX_8|MBX_7|MBX_6|MBX_3|MBX_2|MBX_1|MBX_0;
3994         mcp->in_mb = MBX_1|MBX_0;
3995         mcp->timeout = MAILBOX_TOV;
3996         rval = ql_mailbox_command(ha, mcp);
3997 
3998         (void) ddi_dma_sync(mem->dma_handle, 0, mem->size,
3999             DDI_DMA_SYNC_FORKERNEL);
4000 
4001         if (rval != QL_SUCCESS) {
4002                 EL(ha, "failed=%xh\n", rval);
4003         } else {
4004                 /*EMPTY*/
4005                 QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
4006         }
4007 
4008         return (rval);
4009 }
4010 
4011 /*
4012  * ql_iidma_rate
4013  *      Issue get/set iidma rate command
4014  *
4015  * Input:
4016  *      ha:             adapter state pointer.
4017  *      loop_id:        n-port handle to set/get iidma rate.
4018  *      idma_rate:      Pointer to iidma rate.
4019  *      option:         iidma firmware option (set or get data).
4020  *                              0 --> Get iidma rate
4021  *                              1 --> Set iidma rate
4022  *
4023  * Returns:
4024  *      ql local function return status code.
4025  *
4026  * Context:
4027  *      Kernel context.
4028  */
4029 int
4030 ql_iidma_rate(ql_adapter_state_t *ha, uint16_t loop_id, uint32_t *idma_rate,
4031     uint32_t option)
4032 {
4033         int             rval;
4034         mbx_cmd_t       mc = {0};
4035         mbx_cmd_t       *mcp = &mc;
4036 
4037         QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
4038 
4039         mcp->mb[0] = MBC_PORT_PARAM;
4040         mcp->mb[1] = loop_id;
4041         mcp->mb[2] = (uint16_t)option;
4042         mcp->out_mb = MBX_0|MBX_1|MBX_2;
4043         mcp->in_mb = MBX_0|MBX_1;
4044 
4045         if (option & BIT_0) {
4046                 mcp->mb[3] = (uint16_t)*idma_rate;
4047                 mcp->out_mb |= MBX_3;
4048         } else {
4049                 mcp->in_mb |= MBX_3;
4050         }
4051 
4052         mcp->timeout = MAILBOX_TOV;
4053         rval = ql_mailbox_command(ha, mcp);
4054 
4055         if (rval != QL_SUCCESS) {
4056                 EL(ha, "failed=%xh, mb1=%xh\n", rval, mcp->mb[1]);
4057         } else {
4058                 if (option == 0) {
4059                         *idma_rate = mcp->mb[3];
4060                 }
4061 
4062                 QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
4063         }
4064 
4065         return (rval);
4066 }
4067 
4068 /*
4069  * ql_set_xmit_parms
4070  *      Set transmit parameters
4071  *
4072  * Input:
4073  *      ha:     adapter state pointer.
4074  *
4075  * Returns:
4076  *      ql local function return status code.
4077  *
4078  * Context:
4079  *      Kernel context.
4080  */
4081 int
4082 ql_set_xmit_parms(ql_adapter_state_t *ha)
4083 {
4084         int             rval;
4085         mbx_cmd_t       mc = {0};
4086         mbx_cmd_t       *mcp = &mc;
4087 
4088         QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
4089 
4090         mcp->mb[0] = MBC_XMIT_PARM;
4091         mcp->mb[1] = BIT_1;
4092         mcp->out_mb = MBX_1|MBX_0;
4093         mcp->in_mb = MBX_0;
4094         mcp->timeout = MAILBOX_TOV;
4095         rval = ql_mailbox_command(ha, mcp);
4096 
4097         if (rval != QL_SUCCESS) {
4098                 EL(ha, "failed=%xh\n", rval);
4099         } else {
4100                 /*EMPTY*/
4101                 QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
4102         }
4103         return (rval);
4104 }
4105 
4106 /*
4107  * ql_fw_etrace
4108  *      Firmware extended tracing.
4109  *
4110  * Input:
4111  *      ha:     adapter state pointer.
4112  *      mem:    pointer to dma memory object for command.
4113  *      opt:    options and opcode.
4114  *
4115  * Returns:
4116  *      ql local function return status code.
4117  *
4118  * Context:
4119  *      Kernel context.
4120  */
4121 int
4122 ql_fw_etrace(ql_adapter_state_t *ha, dma_mem_t *mem, uint16_t opt)
4123 {
4124         int             rval = QL_SUCCESS;
4125         mbx_cmd_t       mc = {0};
4126         mbx_cmd_t       *mcp = &mc;
4127         uint16_t        op_code;
4128         uint64_t        time;
4129 
4130         QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
4131 
4132         /* currently no supported options */
4133         op_code = (uint16_t)(opt & ~0xFF00);
4134 
4135         mcp->mb[0] = MBC_TRACE_CONTROL;
4136         mcp->mb[1] = op_code;
4137         mcp->in_mb = MBX_0;
4138         mcp->timeout = MAILBOX_TOV;
4139 
4140         switch (op_code) {
4141         case FTO_INSERT_TIME_STAMP:
4142 
4143                 (void) drv_getparm(TIME, &time);
4144 
4145                 EL(ha, "insert time: %x %xh\n", MSD(time), LSD(time));
4146 
4147                 mcp->mb[2] = LSW(LSD(time));
4148                 mcp->mb[3] = MSW(LSD(time));
4149                 mcp->mb[4] = LSW(MSD(time));
4150                 mcp->mb[5] = MSW(MSD(time));
4151                 mcp->out_mb = MBX_0_THRU_5;
4152                 break;
4153 
4154         case FTO_FCE_TRACE_ENABLE:
4155                 /* Firmware Fibre Channel Event Trace Buffer */
4156                 mcp->mb[2] = LSW(mem->cookies->dmac_address);
4157                 mcp->mb[3] = MSW(mem->cookies->dmac_address);
4158                 mcp->mb[4] = LSW(mem->cookies->dmac_notused);
4159                 mcp->mb[5] = MSW(mem->cookies->dmac_notused);
4160                 mcp->mb[6] = (uint16_t)(mem->size / 0x4000);      /* 16kb blks */
4161                 mcp->mb[8] = (uint16_t)ha->fwfcetraceopt;
4162                 mcp->mb[9] = FTO_FCEMAXTRACEBUF;
4163                 mcp->mb[10] = FTO_FCEMAXTRACEBUF;
4164                 mcp->out_mb = MBX_0_THRU_10;
4165                 break;
4166 
4167         case FTO_EXT_TRACE_ENABLE:
4168                 /* Firmware Extended Trace Buffer */
4169                 mcp->mb[2] = LSW(mem->cookies->dmac_address);
4170                 mcp->mb[3] = MSW(mem->cookies->dmac_address);
4171                 mcp->mb[4] = LSW(mem->cookies->dmac_notused);
4172                 mcp->mb[5] = MSW(mem->cookies->dmac_notused);
4173                 mcp->mb[6] = (uint16_t)(mem->size / 0x4000);      /* 16kb blks */
4174                 mcp->out_mb = MBX_0_THRU_7;
4175                 break;
4176 
4177         case FTO_FCE_TRACE_DISABLE:
4178                 /* also causes ISP25xx to flush its internal FCE buffer. */
4179                 mcp->mb[2] = BIT_0;
4180                 mcp->out_mb = MBX_0_THRU_2;
4181                 break;
4182 
4183         case FTO_EXT_TRACE_DISABLE:
4184                 /* just sending the opcode disables it */
4185                 break;
4186 
4187         default:
4188                 EL(ha, "invalid option: %xh\n", opt);
4189                 rval = QL_PARAMETER_ERROR;
4190                 break;
4191         }
4192 
4193         if (rval == QL_SUCCESS) {
4194                 rval = ql_mailbox_command(ha, mcp);
4195         }
4196 
4197         if (rval != QL_SUCCESS) {
4198                 EL(ha, "failed=%xh\n", rval);
4199         } else {
4200                 /*EMPTY*/
4201                 QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
4202         }
4203 
4204         return (rval);
4205 }
4206 
4207 /*
4208  * ql_reset_menlo
4209  *       Reset Menlo Mailbox Command.
4210  *
4211  * Input:
4212  *      ha:     adapter state pointer.
4213  *      mr:     pointer to mailbox in/out parameters.
4214  *      opt:    options.
4215  *
4216  * Returns:
4217  *      ql local function return status code.
4218  *
4219  * Context:
4220  *      Kernel context.
4221  */
4222 int
4223 ql_reset_menlo(ql_adapter_state_t *ha, ql_mbx_data_t *mr, uint16_t opt)
4224 {
4225         int             rval;
4226         mbx_cmd_t       mc = {0};
4227         mbx_cmd_t       *mcp = &mc;
4228 
4229         QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
4230 
4231         mcp->mb[0] = MBC_RESET_MENLO;
4232         mcp->mb[1] = opt;
4233         mcp->out_mb = MBX_1|MBX_0;
4234         mcp->in_mb = MBX_1|MBX_0;
4235         mcp->timeout = MAILBOX_TOV;
4236         rval = ql_mailbox_command(ha, mcp);
4237 
4238         /* Return mailbox data. */
4239         if (mr != NULL) {
4240                 mr->mb[0] = mcp->mb[0];
4241                 mr->mb[1] = mcp->mb[1];
4242         }
4243 
4244         if (rval != QL_SUCCESS) {
4245                 EL(ha, "failed=%xh\n", rval);
4246         } else {
4247                 /*EMPTY*/
4248                 QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
4249         }
4250 
4251         return (rval);
4252 }
4253 
4254 /*
4255  * ql_restart_mpi
4256  *      The Restart MPI Firmware Mailbox Command will reset the MPI RISC,
4257  *      reload MPI firmware from Flash, and execute the firmware.
4258  *
4259  * Input:
4260  *      ha:     adapter state pointer.
4261  *
4262  * Returns:
4263  *      ql local function return status code.
4264  *
4265  * Context:
4266  *      Kernel context.
4267  */
4268 int
4269 ql_restart_mpi(ql_adapter_state_t *ha)
4270 {
4271         int             rval;
4272         mbx_cmd_t       mc = {0};
4273         mbx_cmd_t       *mcp = &mc;
4274 
4275         QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
4276 
4277         mcp->mb[0] = MBC_RESTART_MPI;
4278         mcp->out_mb = MBX_0;
4279         mcp->in_mb = MBX_1|MBX_0;
4280         mcp->timeout = MAILBOX_TOV;
4281         rval = ql_mailbox_command(ha, mcp);
4282 
4283         /* Return mailbox data. */
4284         if (rval != QL_SUCCESS) {
4285                 EL(ha, "status=%xh, mbx1=%xh\n", rval, mcp->mb[1]);
4286         } else {
4287                 /*EMPTY*/
4288                 QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
4289         }
4290 
4291         return (rval);
4292 }
4293 
4294 /*
4295  * ql_idc_request
4296  *      Inter-Driver Communication Request.
4297  *
4298  * Input:
4299  *      ha:     adapter state pointer.
4300  *      mr:     pointer for mailbox data.
4301  *
4302  * Returns:
4303  *      ql local function return status code.
4304  *
4305  * Context:
4306  *      Kernel context.
4307  */
4308 int
4309 ql_idc_request(ql_adapter_state_t *ha, ql_mbx_data_t *mr)
4310 {
4311         int             rval;
4312         mbx_cmd_t       mc = {0};
4313         mbx_cmd_t       *mcp = &mc;
4314 
4315         QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
4316 
4317         mcp->mb[0] = MBC_IDC_REQUEST;
4318         mcp->mb[1] = mr->mb[1];
4319         mcp->mb[2] = mr->mb[2];
4320         mcp->mb[3] = mr->mb[3];
4321         mcp->mb[4] = mr->mb[4];
4322         mcp->mb[5] = mr->mb[5];
4323         mcp->mb[6] = mr->mb[6];
4324         mcp->mb[7] = mr->mb[7];
4325         mcp->out_mb = MBX_7|MBX_6|MBX_5|MBX_4|MBX_3|MBX_2|MBX_1|MBX_0;
4326         mcp->in_mb = MBX_2|MBX_0;
4327         mcp->timeout = MAILBOX_TOV;
4328         rval = ql_mailbox_command(ha, mcp);
4329 
4330         if (rval == QL_SUCCESS) {
4331                 if (mr != NULL) {
4332                         mr->mb[2] = mcp->mb[2];
4333                 }
4334                 QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
4335         } else {
4336                 EL(ha, "status=%xh, mbx2=%xh\n", rval, mcp->mb[2]);
4337         }
4338 
4339         return (rval);
4340 }
4341 
4342 /*
4343  * ql_idc_ack
4344  *      Inter-Driver Communication Acknowledgement.
4345  *
4346  * Input:
4347  *      ha:     adapter state pointer.
4348  *
4349  * Returns:
4350  *      ql local function return status code.
4351  *
4352  * Context:
4353  *      Kernel context.
4354  */
4355 int
4356 ql_idc_ack(ql_adapter_state_t *ha)
4357 {
4358         int             rval;
4359         mbx_cmd_t       mc = {0};
4360         mbx_cmd_t       *mcp = &mc;
4361 
4362         QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
4363 
4364         mcp->mb[0] = MBC_IDC_ACK;
4365         mcp->mb[1] = ha->idc_mb[1];
4366         mcp->mb[2] = ha->idc_mb[2];
4367         mcp->mb[3] = ha->idc_mb[3];
4368         mcp->mb[4] = ha->idc_mb[4];
4369         mcp->mb[5] = ha->idc_mb[5];
4370         mcp->mb[6] = ha->idc_mb[6];
4371         mcp->mb[7] = ha->idc_mb[7];
4372         mcp->out_mb = MBX_7|MBX_6|MBX_5|MBX_4|MBX_3|MBX_2|MBX_1|MBX_0;
4373         mcp->in_mb = MBX_0;
4374         mcp->timeout = MAILBOX_TOV;
4375         rval = ql_mailbox_command(ha, mcp);
4376 
4377         QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
4378 
4379         return (rval);
4380 }
4381 
4382 /*
4383  * ql_idc_time_extend
4384  *      Inter-Driver Communication Time Extend
4385  *
4386  * Input:
4387  *      ha:     adapter state pointer.
4388  *      mr:     pointer for mailbox data.
4389  *
4390  * Returns:
4391  *      ql local function return status code.
4392  *
4393  * Context:
4394  *      Kernel context.
4395  */
4396 int
4397 ql_idc_time_extend(ql_adapter_state_t *ha, ql_mbx_data_t *mr)
4398 {
4399         int             rval;
4400         mbx_cmd_t       mc = {0};
4401         mbx_cmd_t       *mcp = &mc;
4402 
4403         QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
4404 
4405         mcp->mb[0] = MBC_IDC_TIME_EXTEND;
4406         mcp->mb[1] = mr->mb[1];
4407         mcp->mb[2] = mr->mb[2];
4408         mcp->out_mb = MBX_2|MBX_1|MBX_0;
4409         mcp->in_mb = MBX_0;
4410         mcp->timeout = MAILBOX_TOV;
4411         rval = ql_mailbox_command(ha, mcp);
4412 
4413         QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
4414 
4415         return (rval);
4416 }
4417 
4418 /*
4419  * ql_port_reset
4420  *      The Port Reset for the external 10G port associated with this function.
4421  *
4422  * Input:
4423  *      ha:     adapter state pointer.
4424  *
4425  * Returns:
4426  *      ql local function return status code.
4427  *
4428  * Context:
4429  *      Kernel context.
4430  */
4431 int
4432 ql_port_reset(ql_adapter_state_t *ha)
4433 {
4434         int             rval;
4435         mbx_cmd_t       mc = {0};
4436         mbx_cmd_t       *mcp = &mc;
4437 
4438         QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
4439 
4440         mcp->mb[0] = MBC_PORT_RESET;
4441         mcp->out_mb = MBX_0;
4442         mcp->in_mb = MBX_0;
4443         mcp->timeout = MAILBOX_TOV;
4444         rval = ql_mailbox_command(ha, mcp);
4445 
4446         QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
4447 
4448         return (rval);
4449 }
4450 
4451 /*
4452  * ql_set_port_config
4453  *      The Set Port Configuration command sets the configuration for the
4454  *      external 10G port associated with this function.
4455  *
4456  * Input:
4457  *      ha:     adapter state pointer.
4458  *      mr:     pointer for mailbox data.
4459  *
4460  * Returns:
4461  *      ql local function return status code.
4462  *
4463  * Context:
4464  *      Kernel context.
4465  */
4466 int
4467 ql_set_port_config(ql_adapter_state_t *ha, ql_mbx_data_t *mrp)
4468 {
4469         int             rval;
4470         mbx_cmd_t       mc = {0};
4471         mbx_cmd_t       *mcp = &mc;
4472 
4473         QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
4474 
4475         mcp->mb[0] = MBC_SET_PORT_CONFIG;
4476         mcp->mb[1] = mrp->mb[1];
4477         mcp->mb[2] = mrp->mb[2];
4478         mcp->mb[3] = mrp->mb[3];
4479         mcp->mb[4] = mrp->mb[4];
4480         mcp->out_mb = MBX_4|MBX_3|MBX_2|MBX_1|MBX_0;
4481         mcp->in_mb = MBX_0;
4482         mcp->timeout = MAILBOX_TOV;
4483         rval = ql_mailbox_command(ha, mcp);
4484 
4485         QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
4486 
4487         return (rval);
4488 }
4489 
4490 /*
4491  * ql_get_port_config
4492  *      The Get Port Configuration command retrieves the current configuration
4493  *      for the external 10G port associated with this function.
4494  *
4495  * Input:
4496  *      ha:     adapter state pointer.
4497  *      mr:     pointer for mailbox data.
4498  *
4499  * Returns:
4500  *      ql local function return status code.
4501  *
4502  * Context:
4503  *      Kernel context.
4504  */
4505 int
4506 ql_get_port_config(ql_adapter_state_t *ha, ql_mbx_data_t *mrp)
4507 {
4508         int             rval;
4509         mbx_cmd_t       mc = {0};
4510         mbx_cmd_t       *mcp = &mc;
4511 
4512         QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
4513 
4514         mcp->mb[0] = MBC_GET_PORT_CONFIG;
4515         mcp->out_mb = MBX_0;
4516         mcp->in_mb = MBX_4|MBX_3|MBX_2|MBX_1|MBX_0;
4517         mcp->timeout = MAILBOX_TOV;
4518         rval = ql_mailbox_command(ha, mcp);
4519 
4520         if (rval == QL_SUCCESS) {
4521                 if (mrp != NULL) {
4522                         mrp->mb[1] = mcp->mb[1];
4523                         mrp->mb[2] = mcp->mb[2];
4524                         mrp->mb[3] = mcp->mb[3];
4525                         mrp->mb[4] = mcp->mb[4];
4526                 }
4527                 QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
4528         } else {
4529                 EL(ha, "status=%xh, mbx1=%xh, mbx2=%xh, mbx3=%xh, mbx4=%xh\n",
4530                     rval, mcp->mb[1], mcp->mb[2], mcp->mb[3], mcp->mb[4]);
4531         }
4532 
4533         return (rval);
4534 }
4535 
4536 /*
4537  * ql_flash_access
4538  *      The Get Port Configuration command retrieves the current configuration
4539  *      for the external 10G port associated with this function
4540  *
4541  * Input:
4542  *      ha:     adapter state pointer.
4543  *      cmd:    command.
4544  *      start:  32bit word address.
4545  *      end:    32bit word address.
4546  *      dp:     32bit word pointer.
4547  *
4548  * Returns:
4549  *      ql local function return status code.
4550  *
4551  * Context:
4552  *      Kernel context.
4553  */
4554 int
4555 ql_flash_access(ql_adapter_state_t *ha, uint16_t cmd, uint32_t start,
4556     uint32_t end, uint32_t *dp)
4557 {
4558         int             rval;
4559         mbx_cmd_t       mc = {0};
4560         mbx_cmd_t       *mcp = &mc;
4561 
4562         QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
4563 
4564         mcp->mb[0] = MBC_FLASH_ACCESS;
4565         if (cmd > 0 && cmd < 4) {
4566                 mcp->mb[1] = (uint16_t)(FAC_FORCE_SEMA_LOCK | cmd);
4567         } else {
4568                 mcp->mb[1] = cmd;
4569         }
4570         mcp->mb[2] = LSW(start);
4571         mcp->mb[3] = MSW(start);
4572         mcp->mb[4] = LSW(end);
4573         mcp->mb[5] = MSW(end);
4574 
4575         mcp->out_mb = MBX_5|MBX_4|MBX_3|MBX_2|MBX_1|MBX_0;
4576         mcp->in_mb = MBX_2|MBX_1|MBX_0;
4577         mcp->timeout = MAILBOX_TOV;
4578         rval = ql_mailbox_command(ha, mcp);
4579 
4580         if (rval != QL_SUCCESS) {
4581                 EL(ha, "status=%xh, mbx1=%xh, mbx2=%xh\n", rval, mcp->mb[1],
4582                     mcp->mb[2]);
4583         } else {
4584                 if (dp != NULL) {
4585                         *dp = (uint32_t)mcp->mb[1];
4586                 }
4587                 QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
4588         }
4589 
4590         return (rval);
4591 }
4592 
4593 /*
4594  * ql_get_xgmac_stats
4595  *      Issue et XGMAC Statistics Mailbox command
4596  *
4597  * Input:
4598  *      ha:     adapter state pointer.
4599  *      size:   size of data buffer.
4600  *      bufp:   data pointer for DMA data.
4601  *
4602  * Returns:
4603  *      ql local function return status code.
4604  *
4605  * Context:
4606  *      Kernel context.
4607  */
4608 int
4609 ql_get_xgmac_stats(ql_adapter_state_t *ha, size_t size, caddr_t bufp)
4610 {
4611         int             rval;
4612         dma_mem_t       mem_desc;
4613         mbx_cmd_t       mc = {0};
4614         mbx_cmd_t       *mcp = &mc;
4615 
4616         QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
4617 
4618         if ((rval = ql_setup_mbox_dma_resources(ha, &mem_desc,
4619             (uint32_t)size)) != QL_SUCCESS) {
4620                 EL(ha, "setup_mbox_dma_resources failed: %xh\n", rval);
4621                 return (QL_MEMORY_ALLOC_FAILED);
4622         }
4623 
4624         mcp->mb[0] = MBC_GET_XGMAC_STATS;
4625         mcp->mb[2] = MSW(mem_desc.cookie.dmac_address);
4626         mcp->mb[3] = LSW(mem_desc.cookie.dmac_address);
4627         mcp->mb[6] = MSW(mem_desc.cookie.dmac_notused);
4628         mcp->mb[7] = LSW(mem_desc.cookie.dmac_notused);
4629         mcp->mb[8] = (uint16_t)(size >> 2);
4630         mcp->out_mb = MBX_8|MBX_7|MBX_6|MBX_3|MBX_2|MBX_0;
4631         mcp->in_mb = MBX_2|MBX_1|MBX_0;
4632         mcp->timeout = MAILBOX_TOV;
4633         rval = ql_mailbox_command(ha, mcp);
4634 
4635         if (rval == QL_SUCCESS) {
4636                 ql_get_mbox_dma_data(&mem_desc, bufp);
4637         }
4638         ql_free_dma_resource(ha, &mem_desc);
4639 
4640         if (rval != QL_SUCCESS) {
4641                 EL(ha, "status=%xh, mbx1=%xh, mbx2=%xh\n", rval, mcp->mb[1],
4642                     mcp->mb[2]);
4643         } else {
4644                 /*EMPTY*/
4645                 QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
4646         }
4647 
4648         return (rval);
4649 }
4650 
4651 /*
4652  * ql_get_dcbx_params
4653  *      Issue get DCBX parameters mailbox command.
4654  *
4655  * Input:
4656  *      ha:     adapter state pointer.
4657  *      size:   size of data buffer.
4658  *      bufp:   data pointer for DMA data.
4659  *
4660  * Returns:
4661  *      ql local function return status code.
4662  *
4663  * Context:
4664  *      Kernel context.
4665  */
4666 int
4667 ql_get_dcbx_params(ql_adapter_state_t *ha, uint32_t size, caddr_t bufp)
4668 {
4669         int             rval;
4670         dma_mem_t       mem_desc;
4671         mbx_cmd_t       mc = {0};
4672         mbx_cmd_t       *mcp = &mc;
4673 
4674         QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
4675 
4676         if ((rval = ql_setup_mbox_dma_resources(ha, &mem_desc, size)) !=
4677             QL_SUCCESS) {
4678                 EL(ha, "failed=%xh\n", QL_MEMORY_ALLOC_FAILED);
4679                 return (QL_MEMORY_ALLOC_FAILED);
4680         }
4681 
4682         mcp->mb[0] = MBC_GET_DCBX_PARAMS;
4683         mcp->mb[1] = 0;      /* Return all DCBX paramters */
4684         mcp->mb[2] = MSW(LSD(mem_desc.cookie.dmac_laddress));
4685         mcp->mb[3] = LSW(LSD(mem_desc.cookie.dmac_laddress));
4686         mcp->mb[6] = MSW(MSD(mem_desc.cookie.dmac_laddress));
4687         mcp->mb[7] = LSW(MSD(mem_desc.cookie.dmac_laddress));
4688         mcp->mb[8] = (uint16_t)size;
4689         mcp->out_mb = MBX_8|MBX_7|MBX_6|MBX_3|MBX_2|MBX_1|MBX_0;
4690         mcp->in_mb = MBX_2|MBX_1|MBX_0;
4691         mcp->timeout = MAILBOX_TOV;
4692         rval = ql_mailbox_command(ha, mcp);
4693 
4694         if (rval == QL_SUCCESS) {
4695                 ql_get_mbox_dma_data(&mem_desc, bufp);
4696         }
4697 
4698         ql_free_dma_resource(ha, &mem_desc);
4699 
4700         if (rval != QL_SUCCESS) {
4701                 EL(ha, "failed=%xh\n", rval);
4702         } else {
4703                 /*EMPTY*/
4704                 QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
4705         }
4706 
4707         return (rval);
4708 }
4709 /*
4710  * ql_get_fcf_list
4711  *      Issue get FCF list mailbox command.
4712  *
4713  * Input:
4714  *      ha:             adapter state pointer.
4715  *      fcf_list:       pointer to ql_fcf_list_desc_t
4716  *      bufp:           data pointer for DMA data.
4717  *
4718  * Returns:
4719  *      ql local function return status code.
4720  *
4721  * Context:
4722  *      Kernel context.
4723  */
4724 
4725 int
4726 ql_get_fcf_list_mbx(ql_adapter_state_t *ha, ql_fcf_list_desc_t *fcf_list,
4727     caddr_t bufp)
4728 {
4729         int             rval;
4730         dma_mem_t       mem_desc;
4731         mbx_cmd_t       mc = {0};
4732         mbx_cmd_t       *mcp = &mc;
4733 
4734         QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
4735 
4736         if ((rval = ql_setup_mbox_dma_resources(ha, &mem_desc,
4737             fcf_list->buffer_size)) !=
4738             QL_SUCCESS) {
4739                 EL(ha, "failed=%xh\n", QL_MEMORY_ALLOC_FAILED);
4740                 return (QL_MEMORY_ALLOC_FAILED);
4741         }
4742 
4743         mcp->mb[0] = MBC_GET_FCF_LIST;
4744         mcp->mb[1] = fcf_list->options;
4745         mcp->mb[2] = MSW(LSD(mem_desc.cookie.dmac_laddress));
4746         mcp->mb[3] = LSW(LSD(mem_desc.cookie.dmac_laddress));
4747         mcp->mb[6] = MSW(MSD(mem_desc.cookie.dmac_laddress));
4748         mcp->mb[7] = LSW(MSD(mem_desc.cookie.dmac_laddress));
4749         mcp->mb[8] = (uint16_t)fcf_list->buffer_size;
4750         mcp->mb[9] = fcf_list->fcf_index;
4751         mcp->out_mb = MBX_9|MBX_8|MBX_7|MBX_6|MBX_3|MBX_2|MBX_1|MBX_0;
4752         mcp->in_mb = MBX_2|MBX_1|MBX_0;
4753         mcp->timeout = MAILBOX_TOV;
4754         rval = ql_mailbox_command(ha, mcp);
4755 
4756         if (rval == QL_SUCCESS) {
4757                 ql_get_mbox_dma_data(&mem_desc, bufp);
4758                 fcf_list->buffer_size = (uint16_t)mcp->mb[1];
4759         }
4760 
4761         ql_free_dma_resource(ha, &mem_desc);
4762 
4763         if (rval != QL_SUCCESS) {
4764                 EL(ha, "status=%xh, mbx1=%xh, mbx2=%xh\n", rval, mcp->mb[1],
4765                     mcp->mb[2]);
4766         } else {
4767                 /*EMPTY*/
4768                 QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
4769         }
4770 
4771         return (rval);
4772 }
4773 
4774 /*
4775  * ql_get_resource_cnts
4776  *      Issue get Resourse Count mailbox command.
4777  *
4778  * Input:
4779  *      ha:     adapter state pointer.
4780  *      mr:     pointer for mailbox data.
4781  *
4782  * Returns:
4783  *      ql local function return status code.
4784  *
4785  * Context:
4786  *      Kernel context.
4787  */
4788 
4789 int
4790 ql_get_resource_cnts(ql_adapter_state_t *ha, ql_mbx_data_t *mr)
4791 {
4792         int             rval;
4793         mbx_cmd_t       mc = {0};
4794         mbx_cmd_t       *mcp = &mc;
4795 
4796         QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
4797 
4798         mcp->mb[0] = MBC_GET_RESOURCE_COUNTS;
4799         mcp->out_mb = MBX_0;
4800         mcp->in_mb = MBX_12|MBX_11|MBX_10|MBX_7|MBX_6|
4801             MBX_3|MBX_2|MBX_1|MBX_0;
4802         mcp->timeout = MAILBOX_TOV;
4803         rval = ql_mailbox_command(ha, mcp);
4804 
4805         /* Return mailbox data. */
4806         if (mr != NULL) {
4807                 mr->mb[1] = mcp->mb[1];
4808                 mr->mb[2] = mcp->mb[2];
4809                 mr->mb[3] = mcp->mb[3];
4810                 mr->mb[6] = mcp->mb[6];
4811                 mr->mb[7] = mcp->mb[7];
4812                 mr->mb[10] = mcp->mb[10];
4813                 mr->mb[11] = mcp->mb[11];
4814                 mr->mb[12] = mcp->mb[12];
4815         }
4816 
4817         if (rval != QL_SUCCESS) {
4818                 EL(ha, "failed=%xh\n", rval);
4819         } else {
4820                 /*EMPTY*/
4821                 QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
4822         }
4823 
4824         return (rval);
4825 }
4826 
4827 /*
4828  * ql_toggle_interrupt
4829  *       Issue Toggle Interrupt Mailbox Command.
4830  *
4831  * Input:
4832  *      ha:     adapter state pointer.
4833  *      opt:    0 = disable, 1 = enable.
4834  *
4835  * Returns:
4836  *      ql local function return status code.
4837  *
4838  * Context:
4839  *      Kernel context.
4840  */
4841 int
4842 ql_toggle_interrupt(ql_adapter_state_t *ha, uint16_t opt)
4843 {
4844         int             rval;
4845         mbx_cmd_t       mc = {0};
4846         mbx_cmd_t       *mcp = &mc;
4847 
4848         QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
4849 
4850         mcp->mb[0] = MBC_TOGGLE_INTERRUPT;
4851         mcp->mb[1] = opt;
4852         mcp->out_mb = MBX_1|MBX_0;
4853         mcp->in_mb = MBX_0;
4854         mcp->timeout = 2;
4855         rval = ql_mailbox_command(ha, mcp);
4856 
4857         if (rval != QL_SUCCESS) {
4858                 EL(ha, "failed=%xh\n", rval);
4859         } else {
4860                 /*EMPTY*/
4861                 QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
4862         }
4863 
4864         return (rval);
4865 }