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 /*
  23  * Copyright 2010 QLogic Corporation. All rights reserved.
  24  */
  25 
  26 #include <qlge.h>
  27 
  28 static int ql_async_event_parser(qlge_t *, mbx_data_t *);
  29 
  30 /*
  31  * Wait upto timeout seconds for Processor Interrupt
  32  * if timeout is 0, then wait for default waittime
  33  */
  34 static int
  35 ql_poll_processor_intr(qlge_t *qlge, uint8_t timeout)
  36 {
  37         int rtn_val = DDI_SUCCESS;
  38 
  39         if (ql_wait_reg_bit(qlge, REG_STATUS, STS_PI, BIT_SET, timeout)
  40             != DDI_SUCCESS) {
  41                 cmn_err(CE_WARN, "Polling for processor interrupt failed.");
  42                 rtn_val = DDI_FAILURE;
  43         }
  44         return (rtn_val);
  45 }
  46 
  47 /*
  48  * Wait for mailbox Processor Register Ready
  49  */
  50 static int
  51 ql_wait_processor_addr_reg_ready(qlge_t *qlge)
  52 {
  53         int rtn_val = DDI_SUCCESS;
  54 
  55         if (ql_wait_reg_bit(qlge, REG_PROCESSOR_ADDR,
  56             PROCESSOR_ADDRESS_RDY, BIT_SET, 0) != DDI_SUCCESS) {
  57                 cmn_err(CE_WARN,
  58                     "Wait for processor address register ready timeout.");
  59                 rtn_val = DDI_FAILURE;
  60         }
  61         return (rtn_val);
  62 }
  63 
  64 /*
  65  * Read and write MPI registers using the indirect register interface
  66  * Assume all the locks&semaphore have been acquired
  67  */
  68 int
  69 ql_write_processor_data(qlge_t *qlge, uint32_t addr, uint32_t data)
  70 {
  71         int rtn_val = DDI_FAILURE;
  72 
  73         /* wait for processor address register ready */
  74         if (ql_wait_processor_addr_reg_ready(qlge) == DDI_FAILURE)
  75                 goto out;
  76         /* write the data to the data reg */
  77         ql_write_reg(qlge, REG_PROCESSOR_DATA, data);
  78         /* trigger the write */
  79         ql_write_reg(qlge, REG_PROCESSOR_ADDR, addr);
  80         /* wait for register to come ready */
  81         if (ql_wait_processor_addr_reg_ready(qlge) == DDI_FAILURE)
  82                 goto out;
  83 
  84         rtn_val = DDI_SUCCESS;
  85 
  86 out:
  87         return (rtn_val);
  88 
  89 }
  90 
  91 /*
  92  * Read from processor register
  93  */
  94 int
  95 ql_read_processor_data(qlge_t *qlge, uint32_t addr, uint32_t *data)
  96 {
  97         int rtn_val = DDI_FAILURE;
  98 
  99         /* enable read operation */
 100         addr |= PROCESSOR_ADDRESS_READ;
 101         /* wait for processor address register ready */
 102         if (ql_wait_processor_addr_reg_ready(qlge) == DDI_FAILURE)
 103                 goto out;
 104 
 105         /* Write read address, wait for data ready in Data register */
 106         ql_write_reg(qlge, REG_PROCESSOR_ADDR, addr);
 107         /* wait for data ready */
 108         if (ql_wait_processor_addr_reg_ready(qlge) == DDI_FAILURE)
 109                 goto out;
 110         /* read data */
 111         *data = ql_read_reg(qlge, REG_PROCESSOR_DATA);
 112 
 113         rtn_val = DDI_SUCCESS;
 114 
 115 out:
 116         return (rtn_val);
 117 
 118 }
 119 
 120 /*
 121  * Read "count" number of outgoing Mailbox register starting
 122  * from mailbox #0 if count is 0 then read all mailboxes
 123  */
 124 static int
 125 ql_read_mailbox_cmd(qlge_t *qlge, mbx_data_t *mbx_buf, uint32_t count)
 126 {
 127         int rtn_val = DDI_FAILURE;
 128         uint32_t reg_status;
 129         uint32_t addr;
 130         int i;
 131 
 132         if (ql_sem_spinlock(qlge, QL_PROCESSOR_SEM_MASK) != DDI_SUCCESS) {
 133                 cmn_err(CE_WARN,
 134                     "%s(%d) get QL_PROCESSOR_SEM_MASK time out error",
 135                     __func__, qlge->instance);
 136                 return (DDI_FAILURE);
 137         }
 138 
 139         if (qlge->func_number == qlge->fn0_net)
 140                 addr = FUNC_0_OUT_MAILBOX_0_REG_OFFSET;
 141         else
 142                 addr = FUNC_1_OUT_MAILBOX_0_REG_OFFSET;
 143 
 144         if (count == 0)
 145                 count = NUM_MAILBOX_REGS;
 146         for (i = 0; i < count; i++) {
 147                 if (ql_read_processor_data(qlge, addr, &reg_status)
 148                     == DDI_FAILURE)
 149                         goto out;
 150                 QL_PRINT(DBG_MBX, ("%s(%d) mailbox %d value 0x%x\n",
 151                     __func__, qlge->instance, i, reg_status));
 152                 mbx_buf->mb[i] = reg_status;
 153                 addr ++;
 154         }
 155 
 156         rtn_val = DDI_SUCCESS;
 157 
 158 out:
 159         ql_sem_unlock(qlge, QL_PROCESSOR_SEM_MASK);
 160 
 161         return (rtn_val);
 162 
 163 }
 164 
 165 /*
 166  * Write mail box command (upto 16) to MPI Firmware
 167  */
 168 int
 169 ql_issue_mailbox_cmd(qlge_t *qlge, mbx_cmd_t *mbx_cmd)
 170 {
 171         int rtn_val = DDI_FAILURE;
 172         uint32_t addr;
 173         int i;
 174         /*
 175          * Get semaphore to access Processor Address and
 176          * Processor Data Registers
 177          */
 178         if (ql_sem_spinlock(qlge, QL_PROCESSOR_SEM_MASK) != DDI_SUCCESS) {
 179                 return (DDI_FAILURE);
 180         }
 181         /* ensure no overwriting current command */
 182         if (ql_wait_reg_bit(qlge, REG_HOST_CMD_STATUS,
 183             HOST_TO_MPI_INTR_NOT_DONE, BIT_RESET, 0) != DDI_SUCCESS) {
 184                 goto out;
 185         }
 186 
 187         if (qlge->func_number == qlge->fn0_net)
 188                 addr = FUNC_0_IN_MAILBOX_0_REG_OFFSET;
 189         else
 190                 addr = FUNC_1_IN_MAILBOX_0_REG_OFFSET;
 191 
 192         /* wait for mailbox registers to be ready to access */
 193         if (ql_wait_processor_addr_reg_ready(qlge) == DDI_FAILURE)
 194                 goto out;
 195 
 196         /* issue mailbox command one by one */
 197         for (i = 0; i < NUM_MAILBOX_REGS; i++) {
 198                 /* write sending cmd to mailbox data register */
 199                 ql_write_reg(qlge, REG_PROCESSOR_DATA, mbx_cmd->mb[i]);
 200                 /* write mailbox address to address register */
 201                 ql_write_reg(qlge, REG_PROCESSOR_ADDR, addr);
 202                 QL_PRINT(DBG_MBX, ("%s(%d) write %x to mailbox(%x) addr %x \n",
 203                     __func__, qlge->instance, mbx_cmd->mb[i], i, addr));
 204                 addr++;
 205                 /*
 206                  * wait for mailbox cmd to be written before
 207                  * next write can start
 208                  */
 209                 if (ql_wait_processor_addr_reg_ready(qlge) == DDI_FAILURE)
 210                         goto out;
 211         }
 212         /* inform MPI that new mailbox commands are available */
 213         ql_write_reg(qlge, REG_HOST_CMD_STATUS, HOST_CMD_SET_RISC_INTR);
 214         rtn_val = DDI_SUCCESS;
 215 out:
 216         ql_sem_unlock(qlge, QL_PROCESSOR_SEM_MASK);
 217         return (rtn_val);
 218 }
 219 
 220 /*
 221  * Send mail box command (upto 16) to MPI Firmware
 222  * and polling for MPI mailbox completion response when
 223  * interrupt is not enabled.
 224  * The MBX_LOCK mutexe should have been held and released
 225  * externally
 226  */
 227 int
 228 ql_issue_mailbox_cmd_and_poll_rsp(qlge_t *qlge, mbx_cmd_t *mbx_cmd,
 229     mbx_data_t *p_results)
 230 {
 231         int rtn_val = DDI_FAILURE;
 232         boolean_t done;
 233         int max_wait;
 234 
 235         if (mbx_cmd == NULL)
 236                 goto err;
 237 
 238         rtn_val = ql_issue_mailbox_cmd(qlge, mbx_cmd);
 239         if (rtn_val != DDI_SUCCESS) {
 240                 cmn_err(CE_WARN, "%s(%d) ql_issue_mailbox_cmd failed",
 241                     __func__, qlge->instance);
 242                 goto err;
 243         }
 244         done = B_FALSE;
 245         max_wait = 5; /* wait upto 5 PI interrupt */
 246         /* delay for the processor interrupt is received */
 247         while ((done != B_TRUE) && (max_wait--)) {
 248                 /* wait up to 5s for PI interrupt */
 249                 if (ql_poll_processor_intr(qlge, (uint8_t)mbx_cmd->timeout)
 250                     == DDI_SUCCESS) {
 251                         QL_PRINT(DBG_MBX, ("%s(%d) PI Intr received",
 252                             __func__, qlge->instance));
 253                         (void) ql_read_mailbox_cmd(qlge, p_results, 0);
 254                         /*
 255                          * Sometimes, the incoming messages is not what we are
 256                          * waiting for, ie. async events, then, continue to
 257                          * wait. If it is the result * of previous mailbox
 258                          * command, then Done. No matter what, send
 259                          * HOST_CMD_CLEAR_RISC_TO_HOST_INTR to clear each
 260                          * PI interrupt
 261                          */
 262                         if (ql_async_event_parser(qlge, p_results) == B_FALSE) {
 263                                 /*
 264                                  * we get what we are waiting for,
 265                                  * clear the interrupt
 266                                  */
 267                                 rtn_val = DDI_SUCCESS;
 268                                 done = B_TRUE;
 269                         } else {
 270                                 /*EMPTY*/
 271                                 QL_PRINT(DBG_MBX,
 272                                     ("%s(%d) result ignored, not we wait for\n",
 273                                     __func__, qlge->instance));
 274                         }
 275                         ql_write_reg(qlge, REG_HOST_CMD_STATUS,
 276                             HOST_CMD_CLEAR_RISC_TO_HOST_INTR);
 277                 } else { /* timeout */
 278                         done = B_TRUE;
 279                 }
 280                 rtn_val = DDI_SUCCESS;
 281         }
 282 err:
 283         return (rtn_val);
 284 }
 285 /*
 286  * Send mail box command (upto 16) to MPI Firmware
 287  * and wait for MPI mailbox completion response which
 288  * is saved in interrupt. Thus, this function can only
 289  * be used after interrupt is enabled.
 290  * Must hold MBX mutex before calling this function
 291  */
 292 static int
 293 ql_issue_mailbox_cmd_and_wait_rsp(qlge_t *qlge, mbx_cmd_t *mbx_cmd)
 294 {
 295         int rtn_val = DDI_FAILURE;
 296         clock_t timer;
 297         int i;
 298         int done = 0;
 299 
 300         if (mbx_cmd == NULL)
 301                 goto err;
 302 
 303         ASSERT(mutex_owned(&qlge->mbx_mutex));
 304 
 305         /* if interrupts are not enabled, poll when results are available */
 306         if (!(qlge->flags & INTERRUPTS_ENABLED)) {
 307                 rtn_val = ql_issue_mailbox_cmd_and_poll_rsp(qlge, mbx_cmd,
 308                     &qlge->received_mbx_cmds);
 309                 if (rtn_val == DDI_SUCCESS) {
 310                         for (i = 0; i < NUM_MAILBOX_REGS; i++)
 311                                 mbx_cmd->mb[i] = qlge->received_mbx_cmds.mb[i];
 312                 }
 313         } else {
 314                 rtn_val = ql_issue_mailbox_cmd(qlge, mbx_cmd);
 315                 if (rtn_val != DDI_SUCCESS) {
 316                         cmn_err(CE_WARN, "%s(%d) ql_issue_mailbox_cmd failed",
 317                             __func__, qlge->instance);
 318                         goto err;
 319                 }
 320                 qlge->mbx_wait_completion = 1;
 321                 while (!done && qlge->mbx_wait_completion && !ddi_in_panic()) {
 322                         /* default 5 seconds from now to timeout */
 323                         timer = ddi_get_lbolt();
 324                         if (mbx_cmd->timeout) {
 325                                 timer += drv_sectohz(mbx_cmd->timeout);
 326                         } else {
 327                                 timer += drv_sectohz(5);
 328                         }
 329                         if (cv_timedwait(&qlge->cv_mbx_intr, &qlge->mbx_mutex,
 330                             timer) == -1) {
 331                                 /*
 332                                  * The timeout time 'timer' was
 333                                  * reached or expired without the condition
 334                                  * being signaled.
 335                                  */
 336                                 cmn_err(CE_WARN, "%s(%d) Wait for Mailbox cmd "
 337                                     "complete timeout.",
 338                                     __func__, qlge->instance);
 339                                 rtn_val = DDI_FAILURE;
 340                                 done = 1;
 341                         } else {
 342                                 QL_PRINT(DBG_MBX,
 343                                     ("%s(%d) mailbox completion signal received"
 344                                     " \n", __func__, qlge->instance));
 345                                 for (i = 0; i < NUM_MAILBOX_REGS; i++) {
 346                                         mbx_cmd->mb[i] =
 347                                             qlge->received_mbx_cmds.mb[i];
 348                                 }
 349                                 rtn_val = DDI_SUCCESS;
 350                                 done = 1;
 351                         }
 352                 }
 353         }
 354 err:
 355         return (rtn_val);
 356 }
 357 
 358 /*
 359  * Inteprete incoming asynchronous events
 360  */
 361 static int
 362 ql_async_event_parser(qlge_t *qlge, mbx_data_t *mbx_cmds)
 363 {
 364         uint32_t link_status, cmd;
 365         uint8_t link_speed;
 366         uint8_t link_type;
 367         boolean_t proc_done = B_TRUE;
 368         mbx_cmd_t reply_cmd = {0};
 369         boolean_t fatal_error = B_FALSE;
 370 
 371         switch (mbx_cmds->mb[0]) {
 372         case MBA_IDC_INTERMEDIATE_COMPLETE /* 1000h */:
 373                 QL_PRINT(DBG_MBX, ("%s(%d):"
 374                     "MBA_IDC_INTERMEDIATE_COMPLETE received\n",
 375                     __func__, qlge->instance));
 376                 break;
 377         case MBA_SYSTEM_ERR /* 8002h */:
 378                 cmn_err(CE_WARN, "%s(%d): MBA_SYSTEM_ERR received",
 379                     __func__, qlge->instance);
 380                 cmn_err(CE_WARN, "%s(%d): File id %x, Line # %x,"
 381                     "Firmware Ver# %x",
 382                     __func__, qlge->instance, mbx_cmds->mb[1],
 383                     mbx_cmds->mb[2], mbx_cmds->mb[3]);
 384                 fatal_error = B_TRUE;
 385                 (void) ql_8xxx_binary_core_dump(qlge, &qlge->ql_mpi_coredump);
 386                 break;
 387         case MBA_LINK_UP /* 8011h */:
 388                 QL_PRINT(DBG_MBX, ("%s(%d): MBA_LINK_UP received\n",
 389                     __func__, qlge->instance));
 390                 link_status = mbx_cmds->mb[1];
 391                 QL_PRINT(DBG_MBX, ("%s(%d): Link Status %x \n",
 392                     __func__, qlge->instance, link_status));
 393                 link_speed = (uint8_t)((link_status >> 3) & 0x07);
 394 
 395                 if (link_speed == 0) {
 396                         qlge->speed = SPEED_100;
 397                         QL_PRINT(DBG_MBX, ("%s(%d):Link speed 100M\n",
 398                             __func__, qlge->instance));
 399                 } else if (link_speed == 1) {
 400                         qlge->speed = SPEED_1000;
 401                         QL_PRINT(DBG_MBX, ("%s(%d):Link speed 1G\n",
 402                             __func__, qlge->instance));
 403                 } else if (link_speed == 2) {
 404                         qlge->speed = SPEED_10G;
 405                         QL_PRINT(DBG_MBX, ("%s(%d):Link speed 10G\n",
 406                             __func__, qlge->instance));
 407                         }
 408 
 409                 qlge->link_type = link_type = (uint8_t)(link_status & 0x07);
 410 
 411                 if (link_type == XFI_NETWORK_INTERFACE) {
 412                         /* EMPTY */
 413                         QL_PRINT(DBG_MBX,
 414                             ("%s(%d):Link type XFI_NETWORK_INTERFACE\n",
 415                             __func__, qlge->instance));
 416                 } else if (link_type == XAUI_NETWORK_INTERFACE) {
 417                         /* EMPTY */
 418                         QL_PRINT(DBG_MBX, ("%s(%d):Link type"
 419                             "XAUI_NETWORK_INTERFACE\n",
 420                             __func__, qlge->instance));
 421                 } else if (link_type == XFI_BACKPLANE_INTERFACE) {
 422                         /* EMPTY */
 423                         QL_PRINT(DBG_MBX, ("%s(%d):Link type"
 424                             "XFI_BACKPLANE_INTERFACE\n",
 425                             __func__, qlge->instance));
 426                 } else if (link_type == XAUI_BACKPLANE_INTERFACE) {
 427                         /* EMPTY */
 428                         QL_PRINT(DBG_MBX, ("%s(%d):Link type "
 429                             "XAUI_BACKPLANE_INTERFACE\n",
 430                             __func__, qlge->instance));
 431                 } else if (link_type == EXT_10GBASE_T_PHY) {
 432                         /* EMPTY */
 433                         QL_PRINT(DBG_MBX,
 434                             ("%s(%d):Link type EXT_10GBASE_T_PHY\n",
 435                             __func__, qlge->instance));
 436                 } else if (link_type == EXT_EXT_EDC_PHY) {
 437                         /* EMPTY */
 438                         QL_PRINT(DBG_MBX,
 439                             ("%s(%d):Link type EXT_EXT_EDC_PHY\n",
 440                             __func__, qlge->instance));
 441                 } else {
 442                         /* EMPTY */
 443                         QL_PRINT(DBG_MBX,
 444                             ("%s(%d):unknown Link type \n",
 445                             __func__, qlge->instance));
 446                 }
 447                 cmn_err(CE_NOTE, "qlge(%d) mpi link up! speed %dMbps\n",
 448                     qlge->instance, qlge->speed);
 449                 /*
 450                  * start timer if not started to delay some time then
 451                  * check if link is really up or down
 452                  */
 453                 ql_restart_timer(qlge);
 454 
 455                 break;
 456         case MBA_LINK_DOWN /* 8012h */:
 457                 QL_PRINT(DBG_MBX,
 458                     ("%s(%d): MBA_LINK_DOWN received\n",
 459                     __func__, qlge->instance));
 460 
 461                 link_status = mbx_cmds->mb[1];
 462 
 463                 QL_PRINT(DBG_MBX, ("%s(%d): Link Status %x \n",
 464                     __func__, qlge->instance, link_status));
 465                 if (link_status & 0x1) {
 466                         /* EMPTY */
 467                         QL_PRINT(DBG_MBX, ("%s(%d): Loss of signal \n",
 468                             __func__, qlge->instance));
 469                 }
 470                 if (link_status & 0x2) {
 471                         /* EMPTY */
 472                         QL_PRINT(DBG_MBX,
 473                             ("%s(%d): Auto-Negotiation Failed \n",
 474                             __func__, qlge->instance));
 475                 }
 476                 if (link_status & 0x4) {
 477                         /* EMPTY */
 478                         QL_PRINT(DBG_MBX,
 479                             ("%s(%d): XTI-Training Failed \n",
 480                             __func__, qlge->instance));
 481                 }
 482 
 483                 cmn_err(CE_NOTE, "qlge(%d) mpi link down!\n", qlge->instance);
 484                 ql_restart_timer(qlge);
 485                 break;
 486         case MBA_IDC_COMPLETE /* 8100h */:
 487 
 488                 QL_PRINT(DBG_MBX,
 489                     ("%s(%d): MBA_IDC_COMPLETE received\n",
 490                     __func__, qlge->instance));
 491                 cmd = mbx_cmds->mb[1];
 492                 if (cmd == MBC_STOP_FIRMWARE) {
 493                         /* EMPTY */
 494                         QL_PRINT(DBG_MBX,
 495                             ("%s(%d): STOP_FIRMWARE event completed\n",
 496                             __func__, qlge->instance));
 497                 } else if (cmd == MBC_IDC_REQUEST) {
 498                         /* EMPTY */
 499                         QL_PRINT(DBG_MBX,
 500                             ("%s(%d): IDC_REQUEST event completed\n",
 501                             __func__, qlge->instance));
 502                 } else if (cmd == MBC_PORT_RESET) {
 503                         /* EMPTY */
 504                         QL_PRINT(DBG_MBX,
 505                             ("%s(%d): PORT_RESET event completed\n",
 506                             __func__, qlge->instance));
 507                 } else if (cmd == MBC_SET_PORT_CONFIG) {
 508                         /* EMPTY */
 509                         QL_PRINT(DBG_MBX,
 510                             ("%s(%d): SET_PORT_CONFIG event "
 511                             "completed\n", __func__, qlge->instance));
 512                 } else {
 513                         /* EMPTY */
 514                         QL_PRINT(DBG_MBX,
 515                             ("%s(%d): unknown IDC completion request"
 516                             " event %x %x\n", __func__, qlge->instance,
 517                             mbx_cmds->mb[1], mbx_cmds->mb[2]));
 518                 }
 519                 proc_done = B_FALSE;
 520                 break;
 521 
 522         case MBA_IDC_REQUEST_NOTIFICATION /* 8101h */:
 523                 QL_PRINT(DBG_MBX,
 524                     ("%s(%d): MBA_IDC_REQUEST_NOTIFICATION "
 525                     "received\n", __func__, qlge->instance));
 526                 cmd = mbx_cmds->mb[1];
 527                 if (cmd == MBC_STOP_FIRMWARE) {
 528                         /* EMPTY */
 529                         QL_PRINT(DBG_MBX,
 530                             ("%s(%d): STOP_FIRMWARE notification"
 531                             " received\n", __func__, qlge->instance));
 532                 } else if (cmd == MBC_IDC_REQUEST) {
 533                         /* EMPTY */
 534                         QL_PRINT(DBG_MBX,
 535                             ("%s(%d): IDC_REQUEST notification "
 536                             "received\n", __func__, qlge->instance));
 537                 } else if (cmd == MBC_PORT_RESET) {
 538                         /* EMPTY */
 539                         QL_PRINT(DBG_MBX, ("%s(%d): PORT_RESET "
 540                             "notification received\n",
 541                             __func__, qlge->instance));
 542                 } else if (cmd == MBC_SET_PORT_CONFIG) {
 543                         /* EMPTY */
 544                         QL_PRINT(DBG_MBX,
 545                             ("%s(%d): SET_PORT_CONFIG notification "
 546                             "received\n", __func__, qlge->instance));
 547                 } else {
 548                         /* EMPTY */
 549                         QL_PRINT(DBG_MBX, ("%s(%d): "
 550                             "unknown request received %x %x\n",
 551                             __func__, qlge->instance, mbx_cmds->mb[1],
 552                             mbx_cmds->mb[2]));
 553                 }
 554                 reply_cmd.mb[0] = MBC_IDC_ACK;
 555                 reply_cmd.mb[1] = mbx_cmds->mb[1];
 556                 reply_cmd.mb[2] = mbx_cmds->mb[2];
 557                 reply_cmd.mb[3] = mbx_cmds->mb[3];
 558                 reply_cmd.mb[4] = mbx_cmds->mb[4];
 559                 if (ql_issue_mailbox_cmd(qlge, &reply_cmd)
 560                     != DDI_SUCCESS) {
 561                         cmn_err(CE_WARN,
 562                             "%s(%d) send IDC Ack failed.",
 563                             __func__, qlge->instance);
 564                 }
 565                 /*
 566                  * verify if the incoming outbound mailbox value is what
 567                  * we just sent
 568                  */
 569                 if (mbx_cmds->mb[0] == MBS_COMMAND_COMPLETE) {
 570                         /* 0x4000 */
 571                         /* EMPTY */
 572                         QL_PRINT(DBG_MBX,
 573                             ("%s(%d): IDC Ack sent success.\n",
 574                             __func__, qlge->instance));
 575                         } else {
 576                         /* EMPTY */
 577                         QL_PRINT(DBG_MBX,
 578                             ("%s(%d): IDC Ack reply error %x %x %x.\n",
 579                             __func__, qlge->instance, mbx_cmds->mb[0],
 580                             mbx_cmds->mb[1], mbx_cmds->mb[2]));
 581                         }
 582                 break;
 583         case MBA_IDC_TIME_EXTENDED /* 8102 */:
 584                 QL_PRINT(DBG_MBX,
 585                     ("%s(%d): MBA_IDC_TIME_EXTENDED received\n",
 586                     __func__, qlge->instance));
 587                 break;
 588         case MBA_DCBX_CONFIG_CHANGE /* 8110 */:
 589                 QL_PRINT(DBG_MBX,
 590                     ("%s(%d): MBA_DCBX_CONFIG_CHANGE received\n",
 591                     __func__, qlge->instance));
 592                 break;
 593         case MBA_NOTIFICATION_LOST /* 8120 */:
 594                 QL_PRINT(DBG_MBX,
 595                     ("%s(%d): MBA_NOTIFICATION_LOST received\n",
 596                     __func__, qlge->instance));
 597                 break;
 598         case MBA_SFT_TRANSCEIVER_INSERTION /* 8130 */:
 599                 QL_PRINT(DBG_MBX,
 600                     ("%s(%d): MBA_SFT_TRANSCEIVER_INSERTION "
 601                     "received\n", __func__, qlge->instance));
 602                 break;
 603         case MBA_SFT_TRANSCEIVER_REMOVAL /* 8140 */:
 604                 QL_PRINT(DBG_MBX,
 605                     ("%s(%d): MBA_SFT_TRANSCEIVER_REMOVAL "
 606                     "received\n", __func__, qlge->instance));
 607                 break;
 608         case MBA_FIRMWARE_INIT_COMPLETE /* 8400 */:
 609                 QL_PRINT(DBG_MBX,
 610                     ("%s(%d): MBA_FIRMWARE_INIT_COMPLETE "
 611                     "received\n", __func__, qlge->instance));
 612                 QL_PRINT(DBG_MBX,
 613                     ("%s(%d): mbx[1] %x, mbx[2] %x\n", __func__,
 614                     qlge->instance, mbx_cmds->mb[1], mbx_cmds->mb[2]));
 615                 qlge->fw_init_complete = B_TRUE;
 616                 qlge->fw_version_info.major_version =
 617                     LSB(MSW(mbx_cmds->mb[1]));
 618                 qlge->fw_version_info.minor_version =
 619                     MSB(LSW(mbx_cmds->mb[1]));
 620                 qlge->fw_version_info.sub_minor_version =
 621                     LSB(LSW(mbx_cmds->mb[1]));
 622                 qlge->phy_version_info.major_version =
 623                     LSB(MSW(mbx_cmds->mb[2]));
 624                 qlge->phy_version_info.minor_version =
 625                     MSB(LSW(mbx_cmds->mb[2]));
 626                 qlge->phy_version_info.sub_minor_version =
 627                     LSB(LSW(mbx_cmds->mb[2]));
 628                 break;
 629         case MBA_FIRMWARE_INIT_FAILED /* 8401 */:
 630                 cmn_err(CE_WARN, "%s(%d):"
 631                     "ASYNC_EVENT_FIRMWARE_INIT_FAILURE "
 632                     "received:  mbx[1] %x, mbx[2] %x",
 633                     __func__, qlge->instance,
 634                     mbx_cmds->mb[1], mbx_cmds->mb[2]);
 635                 fatal_error = B_TRUE;
 636                 break;
 637         default:
 638                 if (mbx_cmds->mb[0] > 0x8000) {
 639                         cmn_err(CE_WARN, "%s(%d): "
 640                             "Unknown Async event received: mbx[0] %x ,"
 641                             "mbx[1] %x; mbx[2] %x",
 642                             __func__, qlge->instance,
 643                             mbx_cmds->mb[0], mbx_cmds->mb[1],
 644                             mbx_cmds->mb[2]);
 645                         proc_done = B_TRUE;
 646                 } else {
 647                         proc_done = B_FALSE;
 648                 }
 649                 break;
 650         }
 651         if (fatal_error) {
 652                 if (qlge->fm_enable) {
 653                         ql_fm_ereport(qlge, DDI_FM_DEVICE_NO_RESPONSE);
 654                         ddi_fm_service_impact(qlge->dip, DDI_SERVICE_LOST);
 655                         atomic_or_32(&qlge->flags, ADAPTER_ERROR);
 656                 }
 657         }
 658         return (proc_done);
 659 }
 660 
 661 
 662 /*
 663  * MPI Interrupt handler
 664  * Caller must have MBX_LOCK
 665  */
 666 void
 667 ql_do_mpi_intr(qlge_t *qlge)
 668 {
 669         /*
 670          * we just need to read first few mailboxes that this adapter's MPI
 671          * will write response to.
 672          */
 673         mutex_enter(&qlge->mbx_mutex);
 674 
 675         (void) ql_read_mailbox_cmd(qlge, &qlge->received_mbx_cmds,
 676             qlge->max_read_mbx);
 677 
 678         /*
 679          * process PI interrupt as async events, if not done,
 680          * then pass to mailbox processing
 681          */
 682         if (ql_async_event_parser(qlge, &qlge->received_mbx_cmds) == B_FALSE) {
 683                 QL_PRINT(DBG_MBX, ("%s(%d) mailbox completion interrupt\n",
 684                     __func__, qlge->instance));
 685                 /*
 686                  * If another thread is waiting for the mail box
 687                  * completion event to occur
 688                  */
 689                 if (qlge->mbx_wait_completion == 1) {
 690                         qlge->mbx_wait_completion = 0;
 691                         cv_broadcast(&qlge->cv_mbx_intr);
 692                         QL_PRINT(DBG_MBX,
 693                             ("%s(%d) mailbox completion signaled \n",
 694                             __func__, qlge->instance));
 695                 }
 696         }
 697         /* inform MPI Firmware to clear the interrupt */
 698         ql_write_reg(qlge, REG_HOST_CMD_STATUS,
 699             HOST_CMD_CLEAR_RISC_TO_HOST_INTR /* 0x0A */);
 700         mutex_exit(&qlge->mbx_mutex);
 701         ql_enable_completion_interrupt(qlge, 0); /* MPI is on irq 0 */
 702 }
 703 
 704 /*
 705  * Test if mailbox communication works
 706  * This is used when Interrupt is not enabled
 707  */
 708 int
 709 ql_mbx_test(qlge_t *qlge)
 710 {
 711         mbx_cmd_t mbx_cmds;
 712         mbx_data_t mbx_results;
 713         int i, test_ok = 1;
 714         int rtn_val = DDI_FAILURE;
 715 
 716         for (i = 0; i < NUM_MAILBOX_REGS; i++)
 717                 mbx_cmds.mb[i] = i;
 718 
 719         mbx_cmds.mb[0] = MBC_MAILBOX_REGISTER_TEST; /* 0x06 */
 720         if (ql_issue_mailbox_cmd(qlge, &mbx_cmds) != DDI_SUCCESS) {
 721                 cmn_err(CE_WARN, "%s(%d) ql_issue_mailbox_cmd timeout.",
 722                     __func__, qlge->instance);
 723                 goto out;
 724         }
 725 
 726         /* delay for the processor interrupt is received */
 727         if (ql_poll_processor_intr(qlge, (uint8_t)mbx_cmds.timeout)
 728             == DDI_SUCCESS) {
 729                 QL_PRINT(DBG_MBX, ("%s(%d) PI Intr received",
 730                     __func__, qlge->instance));
 731                 (void) ql_read_mailbox_cmd(qlge, &mbx_results, 0);
 732 
 733                 ql_write_reg(qlge, REG_HOST_CMD_STATUS,
 734                     HOST_CMD_CLEAR_RISC_TO_HOST_INTR);
 735 
 736                 if (mbx_results.mb[0] != MBS_COMMAND_COMPLETE /* 0x4000 */) {
 737                         test_ok = 0;
 738                 } else {
 739                         for (i = 1; i < NUM_MAILBOX_REGS; i++) {
 740                                 if (mbx_results.mb[i] != i) {
 741                                         test_ok = 0;
 742                                         break;
 743                                 }
 744                         }
 745                 }
 746                 if (test_ok) {
 747                         rtn_val = DDI_SUCCESS;
 748                 } else {
 749                         cmn_err(CE_WARN, "%s(%d) mailbox test failed!",
 750                             __func__, qlge->instance);
 751                 }
 752         } else {
 753                 cmn_err(CE_WARN, "%s(%d) mailbox testing error: "
 754                     "PI Intr not received ", __func__, qlge->instance);
 755         }
 756 out:
 757         return (rtn_val);
 758 }
 759 
 760 /*
 761  * ql_mbx_test2
 762  * Test if mailbox communication works
 763  * This is used when Interrupt is enabled
 764  * mailbox cmd:0x06h
 765  */
 766 int
 767 ql_mbx_test2(qlge_t *qlge)
 768 {
 769         mbx_cmd_t mbx_cmds = {0};
 770         int i, test_ok = 1;
 771         int rtn_val = DDI_FAILURE;
 772 
 773         for (i = 0; i < NUM_MAILBOX_REGS; i++)
 774                 mbx_cmds.mb[i] = i;
 775 
 776         mbx_cmds.mb[0] = MBC_MAILBOX_REGISTER_TEST; /* 0x06 */
 777         if (ql_issue_mailbox_cmd_and_wait_rsp(qlge, &mbx_cmds) != DDI_SUCCESS) {
 778                 cmn_err(CE_WARN,
 779                     "%s(%d) ql_issue_mailbox_cmd_and_wait_rsp failed.",
 780                     __func__, qlge->instance);
 781                 goto out;
 782         }
 783 
 784         /* verify if the incoming outbound mailbox value is what we just sent */
 785         if (mbx_cmds.mb[0] != MBS_COMMAND_COMPLETE /* 0x4000 */) {
 786                 test_ok = 0;
 787         } else {
 788                 for (i = 1; i < qlge->max_read_mbx; i++) {
 789                         if (mbx_cmds.mb[i] != i) {
 790                                 test_ok = 0;
 791                                 break;
 792                         }
 793                 }
 794         }
 795         if (test_ok) {
 796                 rtn_val = DDI_SUCCESS;
 797         } else {
 798                 cmn_err(CE_WARN, "%s(%d) mailbox test failed!",
 799                     __func__, qlge->instance);
 800         }
 801 out:
 802         if ((rtn_val != DDI_SUCCESS) && qlge->fm_enable) {
 803                 ql_fm_ereport(qlge, DDI_FM_DEVICE_NO_RESPONSE);
 804                 ddi_fm_service_impact(qlge->dip, DDI_SERVICE_DEGRADED);
 805         }
 806         return (rtn_val);
 807 }
 808 
 809 /*
 810  * ql_get_fw_state
 811  * Get fw state.
 812  * mailbox cmd:0x69h
 813  */
 814 int
 815 ql_get_fw_state(qlge_t *qlge, uint32_t *fw_state_ptr)
 816 {
 817         int rtn_val = DDI_FAILURE;
 818         mbx_cmd_t mbx_cmds = {0};
 819 
 820         mbx_cmds.mb[0] = MBC_GET_FIRMWARE_STATE;
 821 
 822         if (ql_issue_mailbox_cmd_and_wait_rsp(qlge, &mbx_cmds)
 823             != DDI_SUCCESS) {
 824                 cmn_err(CE_WARN, "%s(%d) ql_issue_mailbox_cmd_and_wait_rsp"
 825                     " failed.", __func__, qlge->instance);
 826                 goto out;
 827         }
 828         /* verify if the transaction is completed successful */
 829         if (mbx_cmds.mb[0] != MBS_COMMAND_COMPLETE /* 0x4000 */) {
 830                 cmn_err(CE_WARN, "%s(%d) failed, 0x%x",
 831                     __func__, qlge->instance, mbx_cmds.mb[0]);
 832         } else {
 833                 /* EMPTY */
 834                 QL_PRINT(DBG_MBX, ("firmware state: 0x%x\n", mbx_cmds.mb[1]));
 835         }
 836         if (fw_state_ptr != NULL)
 837                 *fw_state_ptr = mbx_cmds.mb[1];
 838         rtn_val = DDI_SUCCESS;
 839 out:
 840         if ((rtn_val != DDI_SUCCESS) && qlge->fm_enable) {
 841                 ql_fm_ereport(qlge, DDI_FM_DEVICE_NO_RESPONSE);
 842                 ddi_fm_service_impact(qlge->dip, DDI_SERVICE_DEGRADED);
 843         }
 844         return (rtn_val);
 845 }
 846 
 847 /*
 848  * ql_set_IDC_Req
 849  * Send a IDC Request to firmware to notify all functions
 850  * or any specific functions on the same port
 851  * mailbox cmd:0x100h
 852  */
 853 int
 854 ql_set_IDC_Req(qlge_t *qlge, uint8_t dest_functions, uint8_t timeout)
 855 {
 856         int rtn_val = DDI_FAILURE;
 857         mbx_cmd_t mbx_cmds = {0};
 858 
 859         mbx_cmds.mb[0] = MBC_IDC_REQUEST /* 0x100 */;
 860         mbx_cmds.mb[1] = (timeout<<8) | qlge->func_number;
 861 
 862         switch (dest_functions) {
 863         case IDC_REQ_DEST_FUNC_ALL:
 864                 mbx_cmds.mb[1] |= IDC_REQ_ALL_DEST_FUNC_MASK;
 865                 mbx_cmds.mb[2] = 0;
 866                 break;
 867         case IDC_REQ_DEST_FUNC_0:
 868                 mbx_cmds.mb[2] = IDC_REQ_DEST_FUNC_0_MASK;
 869                 break;
 870         case IDC_REQ_DEST_FUNC_1:
 871                 mbx_cmds.mb[2] = IDC_REQ_DEST_FUNC_1_MASK;
 872                 break;
 873         case IDC_REQ_DEST_FUNC_2:
 874                 mbx_cmds.mb[2] = IDC_REQ_DEST_FUNC_2_MASK;
 875                 break;
 876         case IDC_REQ_DEST_FUNC_3:
 877                 mbx_cmds.mb[2] = IDC_REQ_DEST_FUNC_3_MASK;
 878                 break;
 879         default:
 880                 cmn_err(CE_WARN, "Wrong dest functions %x",
 881                     dest_functions);
 882         }
 883 
 884         if (ql_issue_mailbox_cmd_and_wait_rsp(qlge, &mbx_cmds) != DDI_SUCCESS) {
 885                 cmn_err(CE_WARN,
 886                     "%s(%d) ql_issue_mailbox_cmd_and_wait_rsp failed.",
 887                     __func__, qlge->instance);
 888                 goto out;
 889         }
 890         /* verify if the transaction is completed successful */
 891         if (mbx_cmds.mb[0] == MBA_IDC_INTERMEDIATE_COMPLETE /* 0x1000 */) {
 892                 QL_PRINT(DBG_MBX, ("%s(%d) mbx1: 0x%x, mbx2: 0x%x\n",
 893                     __func__, qlge->instance, mbx_cmds.mb[1], mbx_cmds.mb[2]));
 894                 rtn_val = DDI_SUCCESS;
 895         } else if (mbx_cmds.mb[0] == MBS_COMMAND_COMPLETE /* 0x4000 */) {
 896                 QL_PRINT(DBG_MBX, ("%s(%d) cmd sent succesfully 0x%x\n",
 897                     __func__, qlge->instance));
 898                 rtn_val = DDI_SUCCESS;
 899         } else if (mbx_cmds.mb[0] == MBS_COMMAND_ERROR /* 0x4005 */) {
 900                 cmn_err(CE_WARN, "%s(%d) failed: COMMAND_ERROR",
 901                     __func__, qlge->instance);
 902         } else if (mbx_cmds.mb[0] == MBS_COMMAND_PARAMETER_ERROR /* 0x4006 */) {
 903                 cmn_err(CE_WARN, "%s(%d) failed: COMMAND_PARAMETER_ERROR",
 904                     __func__, qlge->instance);
 905         } else {
 906                 cmn_err(CE_WARN, "%s(%d) unknow result: mbx[0]: 0x%x; mbx[1]:"
 907                     " 0x%x; mbx[2]: 0x%x", __func__, qlge->instance,
 908                     mbx_cmds.mb[0], mbx_cmds.mb[1], mbx_cmds.mb[2]);
 909         }
 910 
 911 out:
 912         if ((rtn_val != DDI_SUCCESS) && qlge->fm_enable) {
 913                 ql_fm_ereport(qlge, DDI_FM_DEVICE_NO_RESPONSE);
 914                 ddi_fm_service_impact(qlge->dip, DDI_SERVICE_DEGRADED);
 915         }
 916 return (rtn_val);
 917 }
 918 
 919 /*
 920  * ql_set_mpi_port_config
 921  * Send new port configuration.to mpi
 922  * mailbox cmd:0x122h
 923  */
 924 int
 925 ql_set_mpi_port_config(qlge_t *qlge, port_cfg_info_t new_cfg)
 926 {
 927         int rtn_val = DDI_FAILURE;
 928         mbx_cmd_t mbx_cmds = {0};
 929 
 930         mbx_cmds.mb[0] = MBC_SET_PORT_CONFIG /* 0x122 */;
 931         mbx_cmds.mb[1] = new_cfg.link_cfg;
 932         mbx_cmds.mb[2] = new_cfg.max_frame_size;
 933 
 934         if (ql_issue_mailbox_cmd_and_wait_rsp(qlge, &mbx_cmds) != DDI_SUCCESS) {
 935                 cmn_err(CE_WARN, "%s(%d) ql_issue_mailbox_cmd_and_wait_rsp"
 936                     " failed.", __func__, qlge->instance);
 937                 goto out;
 938         }
 939         /* verify if the transaction is completed successful */
 940         if ((mbx_cmds.mb[0] != MBS_COMMAND_COMPLETE /* 0x4000 */) &&
 941             (mbx_cmds.mb[0] != MBA_IDC_COMPLETE /* 0x8100 */)) {
 942                 cmn_err(CE_WARN, "set port config (%d) failed, 0x%x",
 943                     qlge->instance, mbx_cmds.mb[0]);
 944         } else
 945                 rtn_val = DDI_SUCCESS;
 946 out:
 947         if ((rtn_val != DDI_SUCCESS) && qlge->fm_enable) {
 948                 ql_fm_ereport(qlge, DDI_FM_DEVICE_NO_RESPONSE);
 949                 ddi_fm_service_impact(qlge->dip, DDI_SERVICE_DEGRADED);
 950         }
 951         return (rtn_val);
 952 }
 953 
 954 int
 955 ql_set_pause_mode(qlge_t *qlge)
 956 {
 957         uint32_t pause_bit_mask = 0x60; /* bit 5-6 */
 958 
 959         /* clear pause bits */
 960         qlge->port_cfg_info.link_cfg &= ~pause_bit_mask;
 961 
 962         /* set new pause mode */
 963         if (qlge->pause == PAUSE_MODE_STANDARD)
 964                 qlge->port_cfg_info.link_cfg |= STD_PAUSE;
 965         else if (qlge->pause == PAUSE_MODE_PER_PRIORITY)
 966                 qlge->port_cfg_info.link_cfg |= PP_PAUSE;
 967 
 968         return (ql_set_mpi_port_config(qlge, qlge->port_cfg_info));
 969 }
 970 
 971 int
 972 ql_set_loop_back_mode(qlge_t *qlge)
 973 {
 974         uint32_t loop_back_bit_mask = 0x0e; /* bit 1-3 */
 975 
 976         /* clear loop back bits */
 977         qlge->port_cfg_info.link_cfg &= ~loop_back_bit_mask;
 978         /* loop back cfg: bit1-3 */
 979         if (qlge->loop_back_mode == QLGE_LOOP_INTERNAL_PARALLEL)
 980                 qlge->port_cfg_info.link_cfg |= LOOP_INTERNAL_PARALLEL;
 981         else if (qlge->loop_back_mode == QLGE_LOOP_INTERNAL_SERIAL)
 982                 qlge->port_cfg_info.link_cfg |= LOOP_INTERNAL_SERIAL;
 983         else if (qlge->loop_back_mode == QLGE_LOOP_EXTERNAL_PHY)
 984                 qlge->port_cfg_info.link_cfg |= LOOP_EXTERNAL_PHY;
 985 
 986         return (ql_set_mpi_port_config(qlge, qlge->port_cfg_info));
 987 
 988 }
 989 /*
 990  * ql_get_port_cfg
 991  * Get port configuration.
 992  * mailbox cmd:0x123h
 993  */
 994 int
 995 ql_get_port_cfg(qlge_t *qlge)
 996 {
 997         int rtn_val = DDI_FAILURE;
 998         mbx_cmd_t mbx_cmds = {0};
 999 
1000         mbx_cmds.mb[0] = MBC_GET_PORT_CONFIG /* 0x123 */;
1001         if (ql_issue_mailbox_cmd_and_wait_rsp(qlge, &mbx_cmds) != DDI_SUCCESS) {
1002                 cmn_err(CE_WARN, "%s(%d) ql_issue_mailbox_cmd_and_wait_rsp"
1003                     " failed.", __func__, qlge->instance);
1004                 goto out;
1005         }
1006         /* verify if the transaction is completed successfully */
1007         if (mbx_cmds.mb[0] != MBS_COMMAND_COMPLETE /* 0x4000 */) {
1008                 cmn_err(CE_WARN, "get port config (%d) failed, 0x%x",
1009                     qlge->instance, mbx_cmds.mb[0]);
1010         } else { /* verify frame size */
1011                 if ((mbx_cmds.mb[2] == NORMAL_FRAME_SIZE) ||
1012                     (mbx_cmds.mb[2] == JUMBO_FRAME_SIZE)) {
1013                         qlge->port_cfg_info.link_cfg = mbx_cmds.mb[1];
1014                         qlge->port_cfg_info.max_frame_size = mbx_cmds.mb[2];
1015                         QL_PRINT(DBG_MBX, ("link_cfg: 0x%x, max_frame_size:"
1016                             " %d bytes\n", mbx_cmds.mb[1], mbx_cmds.mb[2]));
1017                         rtn_val = DDI_SUCCESS;
1018                 } else {
1019                         cmn_err(CE_WARN, "bad link_cfg: 0x%x, max_frame_size:"
1020                             " %d bytes", mbx_cmds.mb[1], mbx_cmds.mb[2]);
1021                 }
1022         }
1023 out:
1024         if ((rtn_val != DDI_SUCCESS) && qlge->fm_enable) {
1025                 ql_fm_ereport(qlge, DDI_FM_DEVICE_NO_RESPONSE);
1026                 ddi_fm_service_impact(qlge->dip, DDI_SERVICE_DEGRADED);
1027         }
1028         return (rtn_val);
1029 }
1030 
1031 /*
1032  * qlge_get_link_status
1033  * Get link status.
1034  * mailbox cmd:0x124h
1035  */
1036 int
1037 qlge_get_link_status(qlge_t *qlge,
1038     struct qlnic_link_status_info *link_status_ptr)
1039 {
1040         int rtn_val = DDI_FAILURE;
1041         mbx_cmd_t mbx_cmds = {0};
1042 
1043         mbx_cmds.mb[0] = MBC_GET_LINK_STATUS /* 0x124 */;
1044 
1045         if (ql_issue_mailbox_cmd_and_wait_rsp(qlge, &mbx_cmds)
1046             != DDI_SUCCESS) {
1047                 cmn_err(CE_WARN,
1048                     "%s(%d) ql_issue_mailbox_cmd_and_wait_rsp failed.",
1049                     __func__, qlge->instance);
1050                 goto out;
1051         }
1052         /* verify if the transaction is completed successful */
1053         if (mbx_cmds.mb[0] != MBS_COMMAND_COMPLETE /* 0x4000 */) {
1054                 cmn_err(CE_WARN, "get link status(%d) failed, 0x%x",
1055                     qlge->instance, mbx_cmds.mb[0]);
1056         } else {
1057                 /* EMPTY */
1058                 QL_PRINT(DBG_MBX,
1059                     ("link status: status1 : 0x%x, status2 : 0x%x, "
1060                     "status3 : 0x%x\n",
1061                     mbx_cmds.mb[1], mbx_cmds.mb[2], mbx_cmds.mb[3]));
1062         }
1063         if (link_status_ptr != NULL) {
1064                 link_status_ptr->link_status_info = mbx_cmds.mb[1];
1065                 link_status_ptr->additional_info = mbx_cmds.mb[2];
1066                 link_status_ptr->network_hw_info = mbx_cmds.mb[3];
1067                 link_status_ptr->dcbx_frame_counters_info = mbx_cmds.mb[4];
1068                 link_status_ptr->change_counters_info = mbx_cmds.mb[5];
1069         }
1070         rtn_val = DDI_SUCCESS;
1071 out:
1072         if ((rtn_val != DDI_SUCCESS) && qlge->fm_enable) {
1073                 ql_fm_ereport(qlge, DDI_FM_DEVICE_NO_RESPONSE);
1074                 ddi_fm_service_impact(qlge->dip, DDI_SERVICE_DEGRADED);
1075         }
1076         return (rtn_val);
1077 }
1078 
1079 /*
1080  * ql_get_firmware_version
1081  * Get firmware version.
1082  */
1083 int
1084 ql_get_firmware_version(qlge_t *qlge,
1085     struct qlnic_mpi_version_info *mpi_version_ptr)
1086 {
1087         int rtn_val = DDI_FAILURE;
1088         mbx_cmd_t mbx_cmds = {0};
1089 
1090         mbx_cmds.mb[0] = MBC_ABOUT_FIRMWARE /* 0x08 */;
1091 
1092         if (ql_issue_mailbox_cmd_and_wait_rsp(qlge, &mbx_cmds)
1093             != DDI_SUCCESS) {
1094                 cmn_err(CE_WARN,
1095                     "%s(%d) ql_issue_mailbox_cmd_and_wait_rsp failed.",
1096                     __func__, qlge->instance);
1097                 goto out;
1098         }
1099 
1100         /* verify if the transaction is completed successful */
1101         if (mbx_cmds.mb[0] != MBS_COMMAND_COMPLETE /* 0x4000 */) {
1102                 cmn_err(CE_WARN, "get firmware version(%d) failed, 0x%x",
1103                     qlge->instance, mbx_cmds.mb[0]);
1104         } else {
1105                 qlge->fw_version_info.major_version =
1106                     LSB(MSW(mbx_cmds.mb[1]));
1107                 qlge->fw_version_info.minor_version =
1108                     MSB(LSW(mbx_cmds.mb[1]));
1109                 qlge->fw_version_info.sub_minor_version =
1110                     LSB(LSW(mbx_cmds.mb[1]));
1111                 qlge->phy_version_info.major_version =
1112                     LSB(MSW(mbx_cmds.mb[2]));
1113                 qlge->phy_version_info.minor_version =
1114                     MSB(LSW(mbx_cmds.mb[2]));
1115                 qlge->phy_version_info.sub_minor_version =
1116                     LSB(LSW(mbx_cmds.mb[2]));
1117 #ifdef QLGE_LOAD_UNLOAD
1118                 cmn_err(CE_NOTE, "firmware version: %d.%d.%d\n",
1119                     qlge->fw_version_info.major_version,
1120                     qlge->fw_version_info.minor_version,
1121                     qlge->fw_version_info.sub_minor_version);
1122 #endif
1123                 if (mpi_version_ptr != NULL) {
1124                         mpi_version_ptr->fw_version =
1125                             (qlge->fw_version_info.major_version<<16)
1126                             |(qlge->fw_version_info.minor_version<<8)
1127                             |(qlge->fw_version_info.sub_minor_version);
1128                         mpi_version_ptr->phy_version =
1129                             (qlge->phy_version_info.major_version<<16)
1130                             |(qlge->phy_version_info.minor_version<<8)
1131                             |(qlge->phy_version_info.sub_minor_version);
1132                 }
1133         }
1134         rtn_val = DDI_SUCCESS;
1135 out:
1136         if ((rtn_val != DDI_SUCCESS) && qlge->fm_enable) {
1137                 ql_fm_ereport(qlge, DDI_FM_DEVICE_NO_RESPONSE);
1138                 ddi_fm_service_impact(qlge->dip, DDI_SERVICE_DEGRADED);
1139         }
1140         return (rtn_val);
1141 }
1142 
1143 /*
1144  * Trigger a system error event
1145  */
1146 int
1147 ql_trigger_system_error_event(qlge_t *qlge)
1148 {
1149         mbx_cmd_t mbx_cmds = {0};
1150         int rtn_val = DDI_FAILURE;
1151 
1152         mbx_cmds.mb[0] = MBC_GENERATE_SYS_ERROR; /* 0x2A */
1153         if (ql_issue_mailbox_cmd(qlge, &mbx_cmds) != DDI_SUCCESS) {
1154                 cmn_err(CE_WARN, "%s(%d) ql_issue_mailbox_cmd timeout.",
1155                     __func__, qlge->instance);
1156                 goto out;
1157         }
1158         rtn_val = DDI_SUCCESS;
1159 out:
1160         return (rtn_val);
1161 }
1162 
1163 /*
1164  * Reset the MPI RISC Processor
1165  */
1166 int
1167 ql_reset_mpi_risc(qlge_t *qlge)
1168 {
1169         int rtn_val = DDI_FAILURE;
1170 
1171         /* Reset the MPI Processor */
1172         ql_write_reg(qlge, REG_HOST_CMD_STATUS, HOST_CMD_SET_RISC_RESET);
1173         if (ql_wait_reg_bit(qlge, REG_HOST_CMD_STATUS, RISC_RESET,
1174             BIT_SET, 0) != DDI_SUCCESS) {
1175                 (void) ql_read_reg(qlge, REG_HOST_CMD_STATUS);
1176                 goto out;
1177         }
1178         ql_write_reg(qlge, REG_HOST_CMD_STATUS, HOST_CMD_CLEAR_RISC_RESET);
1179         rtn_val = DDI_SUCCESS;
1180 out:
1181         return (rtn_val);
1182 }
1183 
1184 int
1185 ql_read_risc_ram(qlge_t *qlge, uint32_t risc_address, uint64_t bp,
1186     uint32_t word_count)
1187 {
1188         int rval = DDI_FAILURE;
1189         mbx_cmd_t mc = {0};
1190         mbx_cmd_t *mcp = &mc;
1191         mbx_data_t mbx_results;
1192 
1193         QL_PRINT(DBG_MBX, ("%s(%d): read risc addr:0x%x,"
1194             "phys_addr %x,%x words\n", __func__, qlge->instance,
1195             risc_address, bp, word_count));
1196         if (CFG_IST(qlge, CFG_CHIP_8100)) {
1197                 mcp->mb[0] = MBC_DUMP_RISC_RAM /* 0x0C */;
1198                 mcp->mb[1] = LSW(risc_address);
1199                 mcp->mb[2] = MSW(LSD(bp));
1200                 mcp->mb[3] = LSW(LSD(bp));
1201                 mcp->mb[4] = MSW(word_count);
1202                 mcp->mb[5] = LSW(word_count);
1203                 mcp->mb[6] = MSW(MSD(bp));
1204                 mcp->mb[7] = LSW(MSD(bp));
1205                 mcp->mb[8] = MSW(risc_address);
1206         }
1207         mcp->timeout = 10 /* MAILBOX_TOV */;
1208 
1209         if (ql_issue_mailbox_cmd_and_poll_rsp(qlge, mcp, &mbx_results)
1210             != DDI_SUCCESS) {
1211                 goto out;
1212         } else {
1213                 QL_PRINT(DBG_MBX, ("%s(%d) PI Intr received",
1214                     __func__, qlge->instance));
1215                 if (mbx_results.mb[0] == MBS_COMMAND_COMPLETE /* 0x4000 */) {
1216                         QL_PRINT(DBG_MBX, ("%s(%d): success\n",
1217                             __func__, qlge->instance));
1218                         rval = DDI_SUCCESS;
1219                 } else {
1220                         cmn_err(CE_WARN, "read_risc_ram(%d): failed, status %x",
1221                             qlge->instance, mbx_results.mb[0]);
1222                 }
1223         }
1224 out:
1225         return (rval);
1226 }