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 +=
 326                                     mbx_cmd->timeout * drv_usectohz(1000000);
 327                         } else {
 328                                 timer += 5 * drv_usectohz(1000000);
 329                         }
 330                         if (cv_timedwait(&qlge->cv_mbx_intr, &qlge->mbx_mutex,
 331                             timer) == -1) {
 332                                 /*
 333                                  * The timeout time 'timer' was
 334                                  * reached or expired without the condition
 335                                  * being signaled.
 336                                  */
 337                                 cmn_err(CE_WARN, "%s(%d) Wait for Mailbox cmd "
 338                                     "complete timeout.",
 339                                     __func__, qlge->instance);
 340                                 rtn_val = DDI_FAILURE;
 341                                 done = 1;
 342                         } else {
 343                                 QL_PRINT(DBG_MBX,
 344                                     ("%s(%d) mailbox completion signal received"
 345                                     " \n", __func__, qlge->instance));
 346                                 for (i = 0; i < NUM_MAILBOX_REGS; i++) {
 347                                         mbx_cmd->mb[i] =
 348                                             qlge->received_mbx_cmds.mb[i];
 349                                 }
 350                                 rtn_val = DDI_SUCCESS;
 351                                 done = 1;
 352                         }
 353                 }
 354         }
 355 err:
 356         return (rtn_val);
 357 }
 358 
 359 /*
 360  * Inteprete incoming asynchronous events
 361  */
 362 static int
 363 ql_async_event_parser(qlge_t *qlge, mbx_data_t *mbx_cmds)
 364 {
 365         uint32_t link_status, cmd;
 366         uint8_t link_speed;
 367         uint8_t link_type;
 368         boolean_t proc_done = B_TRUE;
 369         mbx_cmd_t reply_cmd = {0};
 370         boolean_t fatal_error = B_FALSE;
 371 
 372         switch (mbx_cmds->mb[0]) {
 373         case MBA_IDC_INTERMEDIATE_COMPLETE /* 1000h */:
 374                 QL_PRINT(DBG_MBX, ("%s(%d):"
 375                     "MBA_IDC_INTERMEDIATE_COMPLETE received\n",
 376                     __func__, qlge->instance));
 377                 break;
 378         case MBA_SYSTEM_ERR /* 8002h */:
 379                 cmn_err(CE_WARN, "%s(%d): MBA_SYSTEM_ERR received",
 380                     __func__, qlge->instance);
 381                 cmn_err(CE_WARN, "%s(%d): File id %x, Line # %x,"
 382                     "Firmware Ver# %x",
 383                     __func__, qlge->instance, mbx_cmds->mb[1],
 384                     mbx_cmds->mb[2], mbx_cmds->mb[3]);
 385                 fatal_error = B_TRUE;
 386                 (void) ql_8xxx_binary_core_dump(qlge, &qlge->ql_mpi_coredump);
 387                 break;
 388         case MBA_LINK_UP /* 8011h */:
 389                 QL_PRINT(DBG_MBX, ("%s(%d): MBA_LINK_UP received\n",
 390                     __func__, qlge->instance));
 391                 link_status = mbx_cmds->mb[1];
 392                 QL_PRINT(DBG_MBX, ("%s(%d): Link Status %x \n",
 393                     __func__, qlge->instance, link_status));
 394                 link_speed = (uint8_t)((link_status >> 3) & 0x07);
 395 
 396                 if (link_speed == 0) {
 397                         qlge->speed = SPEED_100;
 398                         QL_PRINT(DBG_MBX, ("%s(%d):Link speed 100M\n",
 399                             __func__, qlge->instance));
 400                 } else if (link_speed == 1) {
 401                         qlge->speed = SPEED_1000;
 402                         QL_PRINT(DBG_MBX, ("%s(%d):Link speed 1G\n",
 403                             __func__, qlge->instance));
 404                 } else if (link_speed == 2) {
 405                         qlge->speed = SPEED_10G;
 406                         QL_PRINT(DBG_MBX, ("%s(%d):Link speed 10G\n",
 407                             __func__, qlge->instance));
 408                         }
 409 
 410                 qlge->link_type = link_type = (uint8_t)(link_status & 0x07);
 411 
 412                 if (link_type == XFI_NETWORK_INTERFACE) {
 413                         /* EMPTY */
 414                         QL_PRINT(DBG_MBX,
 415                             ("%s(%d):Link type XFI_NETWORK_INTERFACE\n",
 416                             __func__, qlge->instance));
 417                 } else if (link_type == XAUI_NETWORK_INTERFACE) {
 418                         /* EMPTY */
 419                         QL_PRINT(DBG_MBX, ("%s(%d):Link type"
 420                             "XAUI_NETWORK_INTERFACE\n",
 421                             __func__, qlge->instance));
 422                 } else if (link_type == XFI_BACKPLANE_INTERFACE) {
 423                         /* EMPTY */
 424                         QL_PRINT(DBG_MBX, ("%s(%d):Link type"
 425                             "XFI_BACKPLANE_INTERFACE\n",
 426                             __func__, qlge->instance));
 427                 } else if (link_type == XAUI_BACKPLANE_INTERFACE) {
 428                         /* EMPTY */
 429                         QL_PRINT(DBG_MBX, ("%s(%d):Link type "
 430                             "XAUI_BACKPLANE_INTERFACE\n",
 431                             __func__, qlge->instance));
 432                 } else if (link_type == EXT_10GBASE_T_PHY) {
 433                         /* EMPTY */
 434                         QL_PRINT(DBG_MBX,
 435                             ("%s(%d):Link type EXT_10GBASE_T_PHY\n",
 436                             __func__, qlge->instance));
 437                 } else if (link_type == EXT_EXT_EDC_PHY) {
 438                         /* EMPTY */
 439                         QL_PRINT(DBG_MBX,
 440                             ("%s(%d):Link type EXT_EXT_EDC_PHY\n",
 441                             __func__, qlge->instance));
 442                 } else {
 443                         /* EMPTY */
 444                         QL_PRINT(DBG_MBX,
 445                             ("%s(%d):unknown Link type \n",
 446                             __func__, qlge->instance));
 447                 }
 448                 cmn_err(CE_NOTE, "qlge(%d) mpi link up! speed %dMbps\n",
 449                     qlge->instance, qlge->speed);
 450                 /*
 451                  * start timer if not started to delay some time then
 452                  * check if link is really up or down
 453                  */
 454                 ql_restart_timer(qlge);
 455 
 456                 break;
 457         case MBA_LINK_DOWN /* 8012h */:
 458                 QL_PRINT(DBG_MBX,
 459                     ("%s(%d): MBA_LINK_DOWN received\n",
 460                     __func__, qlge->instance));
 461 
 462                 link_status = mbx_cmds->mb[1];
 463 
 464                 QL_PRINT(DBG_MBX, ("%s(%d): Link Status %x \n",
 465                     __func__, qlge->instance, link_status));
 466                 if (link_status & 0x1) {
 467                         /* EMPTY */
 468                         QL_PRINT(DBG_MBX, ("%s(%d): Loss of signal \n",
 469                             __func__, qlge->instance));
 470                 }
 471                 if (link_status & 0x2) {
 472                         /* EMPTY */
 473                         QL_PRINT(DBG_MBX,
 474                             ("%s(%d): Auto-Negotiation Failed \n",
 475                             __func__, qlge->instance));
 476                 }
 477                 if (link_status & 0x4) {
 478                         /* EMPTY */
 479                         QL_PRINT(DBG_MBX,
 480                             ("%s(%d): XTI-Training Failed \n",
 481                             __func__, qlge->instance));
 482                 }
 483 
 484                 cmn_err(CE_NOTE, "qlge(%d) mpi link down!\n", qlge->instance);
 485                 ql_restart_timer(qlge);
 486                 break;
 487         case MBA_IDC_COMPLETE /* 8100h */:
 488 
 489                 QL_PRINT(DBG_MBX,
 490                     ("%s(%d): MBA_IDC_COMPLETE received\n",
 491                     __func__, qlge->instance));
 492                 cmd = mbx_cmds->mb[1];
 493                 if (cmd == MBC_STOP_FIRMWARE) {
 494                         /* EMPTY */
 495                         QL_PRINT(DBG_MBX,
 496                             ("%s(%d): STOP_FIRMWARE event completed\n",
 497                             __func__, qlge->instance));
 498                 } else if (cmd == MBC_IDC_REQUEST) {
 499                         /* EMPTY */
 500                         QL_PRINT(DBG_MBX,
 501                             ("%s(%d): IDC_REQUEST event completed\n",
 502                             __func__, qlge->instance));
 503                 } else if (cmd == MBC_PORT_RESET) {
 504                         /* EMPTY */
 505                         QL_PRINT(DBG_MBX,
 506                             ("%s(%d): PORT_RESET event completed\n",
 507                             __func__, qlge->instance));
 508                 } else if (cmd == MBC_SET_PORT_CONFIG) {
 509                         /* EMPTY */
 510                         QL_PRINT(DBG_MBX,
 511                             ("%s(%d): SET_PORT_CONFIG event "
 512                             "completed\n", __func__, qlge->instance));
 513                 } else {
 514                         /* EMPTY */
 515                         QL_PRINT(DBG_MBX,
 516                             ("%s(%d): unknown IDC completion request"
 517                             " event %x %x\n", __func__, qlge->instance,
 518                             mbx_cmds->mb[1], mbx_cmds->mb[2]));
 519                 }
 520                 proc_done = B_FALSE;
 521                 break;
 522 
 523         case MBA_IDC_REQUEST_NOTIFICATION /* 8101h */:
 524                 QL_PRINT(DBG_MBX,
 525                     ("%s(%d): MBA_IDC_REQUEST_NOTIFICATION "
 526                     "received\n", __func__, qlge->instance));
 527                 cmd = mbx_cmds->mb[1];
 528                 if (cmd == MBC_STOP_FIRMWARE) {
 529                         /* EMPTY */
 530                         QL_PRINT(DBG_MBX,
 531                             ("%s(%d): STOP_FIRMWARE notification"
 532                             " received\n", __func__, qlge->instance));
 533                 } else if (cmd == MBC_IDC_REQUEST) {
 534                         /* EMPTY */
 535                         QL_PRINT(DBG_MBX,
 536                             ("%s(%d): IDC_REQUEST notification "
 537                             "received\n", __func__, qlge->instance));
 538                 } else if (cmd == MBC_PORT_RESET) {
 539                         /* EMPTY */
 540                         QL_PRINT(DBG_MBX, ("%s(%d): PORT_RESET "
 541                             "notification received\n",
 542                             __func__, qlge->instance));
 543                 } else if (cmd == MBC_SET_PORT_CONFIG) {
 544                         /* EMPTY */
 545                         QL_PRINT(DBG_MBX,
 546                             ("%s(%d): SET_PORT_CONFIG notification "
 547                             "received\n", __func__, qlge->instance));
 548                 } else {
 549                         /* EMPTY */
 550                         QL_PRINT(DBG_MBX, ("%s(%d): "
 551                             "unknown request received %x %x\n",
 552                             __func__, qlge->instance, mbx_cmds->mb[1],
 553                             mbx_cmds->mb[2]));
 554                 }
 555                 reply_cmd.mb[0] = MBC_IDC_ACK;
 556                 reply_cmd.mb[1] = mbx_cmds->mb[1];
 557                 reply_cmd.mb[2] = mbx_cmds->mb[2];
 558                 reply_cmd.mb[3] = mbx_cmds->mb[3];
 559                 reply_cmd.mb[4] = mbx_cmds->mb[4];
 560                 if (ql_issue_mailbox_cmd(qlge, &reply_cmd)
 561                     != DDI_SUCCESS) {
 562                         cmn_err(CE_WARN,
 563                             "%s(%d) send IDC Ack failed.",
 564                             __func__, qlge->instance);
 565                 }
 566                 /*
 567                  * verify if the incoming outbound mailbox value is what
 568                  * we just sent
 569                  */
 570                 if (mbx_cmds->mb[0] == MBS_COMMAND_COMPLETE) {
 571                         /* 0x4000 */
 572                         /* EMPTY */
 573                         QL_PRINT(DBG_MBX,
 574                             ("%s(%d): IDC Ack sent success.\n",
 575                             __func__, qlge->instance));
 576                         } else {
 577                         /* EMPTY */
 578                         QL_PRINT(DBG_MBX,
 579                             ("%s(%d): IDC Ack reply error %x %x %x.\n",
 580                             __func__, qlge->instance, mbx_cmds->mb[0],
 581                             mbx_cmds->mb[1], mbx_cmds->mb[2]));
 582                         }
 583                 break;
 584         case MBA_IDC_TIME_EXTENDED /* 8102 */:
 585                 QL_PRINT(DBG_MBX,
 586                     ("%s(%d): MBA_IDC_TIME_EXTENDED received\n",
 587                     __func__, qlge->instance));
 588                 break;
 589         case MBA_DCBX_CONFIG_CHANGE /* 8110 */:
 590                 QL_PRINT(DBG_MBX,
 591                     ("%s(%d): MBA_DCBX_CONFIG_CHANGE received\n",
 592                     __func__, qlge->instance));
 593                 break;
 594         case MBA_NOTIFICATION_LOST /* 8120 */:
 595                 QL_PRINT(DBG_MBX,
 596                     ("%s(%d): MBA_NOTIFICATION_LOST received\n",
 597                     __func__, qlge->instance));
 598                 break;
 599         case MBA_SFT_TRANSCEIVER_INSERTION /* 8130 */:
 600                 QL_PRINT(DBG_MBX,
 601                     ("%s(%d): MBA_SFT_TRANSCEIVER_INSERTION "
 602                     "received\n", __func__, qlge->instance));
 603                 break;
 604         case MBA_SFT_TRANSCEIVER_REMOVAL /* 8140 */:
 605                 QL_PRINT(DBG_MBX,
 606                     ("%s(%d): MBA_SFT_TRANSCEIVER_REMOVAL "
 607                     "received\n", __func__, qlge->instance));
 608                 break;
 609         case MBA_FIRMWARE_INIT_COMPLETE /* 8400 */:
 610                 QL_PRINT(DBG_MBX,
 611                     ("%s(%d): MBA_FIRMWARE_INIT_COMPLETE "
 612                     "received\n", __func__, qlge->instance));
 613                 QL_PRINT(DBG_MBX,
 614                     ("%s(%d): mbx[1] %x, mbx[2] %x\n", __func__,
 615                     qlge->instance, mbx_cmds->mb[1], mbx_cmds->mb[2]));
 616                 qlge->fw_init_complete = B_TRUE;
 617                 qlge->fw_version_info.major_version =
 618                     LSB(MSW(mbx_cmds->mb[1]));
 619                 qlge->fw_version_info.minor_version =
 620                     MSB(LSW(mbx_cmds->mb[1]));
 621                 qlge->fw_version_info.sub_minor_version =
 622                     LSB(LSW(mbx_cmds->mb[1]));
 623                 qlge->phy_version_info.major_version =
 624                     LSB(MSW(mbx_cmds->mb[2]));
 625                 qlge->phy_version_info.minor_version =
 626                     MSB(LSW(mbx_cmds->mb[2]));
 627                 qlge->phy_version_info.sub_minor_version =
 628                     LSB(LSW(mbx_cmds->mb[2]));
 629                 break;
 630         case MBA_FIRMWARE_INIT_FAILED /* 8401 */:
 631                 cmn_err(CE_WARN, "%s(%d):"
 632                     "ASYNC_EVENT_FIRMWARE_INIT_FAILURE "
 633                     "received:  mbx[1] %x, mbx[2] %x",
 634                     __func__, qlge->instance,
 635                     mbx_cmds->mb[1], mbx_cmds->mb[2]);
 636                 fatal_error = B_TRUE;
 637                 break;
 638         default:
 639                 if (mbx_cmds->mb[0] > 0x8000) {
 640                         cmn_err(CE_WARN, "%s(%d): "
 641                             "Unknown Async event received: mbx[0] %x ,"
 642                             "mbx[1] %x; mbx[2] %x",
 643                             __func__, qlge->instance,
 644                             mbx_cmds->mb[0], mbx_cmds->mb[1],
 645                             mbx_cmds->mb[2]);
 646                         proc_done = B_TRUE;
 647                 } else {
 648                         proc_done = B_FALSE;
 649                 }
 650                 break;
 651         }
 652         if (fatal_error) {
 653                 if (qlge->fm_enable) {
 654                         ql_fm_ereport(qlge, DDI_FM_DEVICE_NO_RESPONSE);
 655                         ddi_fm_service_impact(qlge->dip, DDI_SERVICE_LOST);
 656                         atomic_or_32(&qlge->flags, ADAPTER_ERROR);
 657                 }
 658         }
 659         return (proc_done);
 660 }
 661 
 662 
 663 /*
 664  * MPI Interrupt handler
 665  * Caller must have MBX_LOCK
 666  */
 667 void
 668 ql_do_mpi_intr(qlge_t *qlge)
 669 {
 670         /*
 671          * we just need to read first few mailboxes that this adapter's MPI
 672          * will write response to.
 673          */
 674         mutex_enter(&qlge->mbx_mutex);
 675 
 676         (void) ql_read_mailbox_cmd(qlge, &qlge->received_mbx_cmds,
 677             qlge->max_read_mbx);
 678 
 679         /*
 680          * process PI interrupt as async events, if not done,
 681          * then pass to mailbox processing
 682          */
 683         if (ql_async_event_parser(qlge, &qlge->received_mbx_cmds) == B_FALSE) {
 684                 QL_PRINT(DBG_MBX, ("%s(%d) mailbox completion interrupt\n",
 685                     __func__, qlge->instance));
 686                 /*
 687                  * If another thread is waiting for the mail box
 688                  * completion event to occur
 689                  */
 690                 if (qlge->mbx_wait_completion == 1) {
 691                         qlge->mbx_wait_completion = 0;
 692                         cv_broadcast(&qlge->cv_mbx_intr);
 693                         QL_PRINT(DBG_MBX,
 694                             ("%s(%d) mailbox completion signaled \n",
 695                             __func__, qlge->instance));
 696                 }
 697         }
 698         /* inform MPI Firmware to clear the interrupt */
 699         ql_write_reg(qlge, REG_HOST_CMD_STATUS,
 700             HOST_CMD_CLEAR_RISC_TO_HOST_INTR /* 0x0A */);
 701         mutex_exit(&qlge->mbx_mutex);
 702         ql_enable_completion_interrupt(qlge, 0); /* MPI is on irq 0 */
 703 }
 704 
 705 /*
 706  * Test if mailbox communication works
 707  * This is used when Interrupt is not enabled
 708  */
 709 int
 710 ql_mbx_test(qlge_t *qlge)
 711 {
 712         mbx_cmd_t mbx_cmds;
 713         mbx_data_t mbx_results;
 714         int i, test_ok = 1;
 715         int rtn_val = DDI_FAILURE;
 716 
 717         for (i = 0; i < NUM_MAILBOX_REGS; i++)
 718                 mbx_cmds.mb[i] = i;
 719 
 720         mbx_cmds.mb[0] = MBC_MAILBOX_REGISTER_TEST; /* 0x06 */
 721         if (ql_issue_mailbox_cmd(qlge, &mbx_cmds) != DDI_SUCCESS) {
 722                 cmn_err(CE_WARN, "%s(%d) ql_issue_mailbox_cmd timeout.",
 723                     __func__, qlge->instance);
 724                 goto out;
 725         }
 726 
 727         /* delay for the processor interrupt is received */
 728         if (ql_poll_processor_intr(qlge, (uint8_t)mbx_cmds.timeout)
 729             == DDI_SUCCESS) {
 730                 QL_PRINT(DBG_MBX, ("%s(%d) PI Intr received",
 731                     __func__, qlge->instance));
 732                 (void) ql_read_mailbox_cmd(qlge, &mbx_results, 0);
 733 
 734                 ql_write_reg(qlge, REG_HOST_CMD_STATUS,
 735                     HOST_CMD_CLEAR_RISC_TO_HOST_INTR);
 736 
 737                 if (mbx_results.mb[0] != MBS_COMMAND_COMPLETE /* 0x4000 */) {
 738                         test_ok = 0;
 739                 } else {
 740                         for (i = 1; i < NUM_MAILBOX_REGS; i++) {
 741                                 if (mbx_results.mb[i] != i) {
 742                                         test_ok = 0;
 743                                         break;
 744                                 }
 745                         }
 746                 }
 747                 if (test_ok) {
 748                         rtn_val = DDI_SUCCESS;
 749                 } else {
 750                         cmn_err(CE_WARN, "%s(%d) mailbox test failed!",
 751                             __func__, qlge->instance);
 752                 }
 753         } else {
 754                 cmn_err(CE_WARN, "%s(%d) mailbox testing error: "
 755                     "PI Intr not received ", __func__, qlge->instance);
 756         }
 757 out:
 758         return (rtn_val);
 759 }
 760 
 761 /*
 762  * ql_mbx_test2
 763  * Test if mailbox communication works
 764  * This is used when Interrupt is enabled
 765  * mailbox cmd:0x06h
 766  */
 767 int
 768 ql_mbx_test2(qlge_t *qlge)
 769 {
 770         mbx_cmd_t mbx_cmds = {0};
 771         int i, test_ok = 1;
 772         int rtn_val = DDI_FAILURE;
 773 
 774         for (i = 0; i < NUM_MAILBOX_REGS; i++)
 775                 mbx_cmds.mb[i] = i;
 776 
 777         mbx_cmds.mb[0] = MBC_MAILBOX_REGISTER_TEST; /* 0x06 */
 778         if (ql_issue_mailbox_cmd_and_wait_rsp(qlge, &mbx_cmds) != DDI_SUCCESS) {
 779                 cmn_err(CE_WARN,
 780                     "%s(%d) ql_issue_mailbox_cmd_and_wait_rsp failed.",
 781                     __func__, qlge->instance);
 782                 goto out;
 783         }
 784 
 785         /* verify if the incoming outbound mailbox value is what we just sent */
 786         if (mbx_cmds.mb[0] != MBS_COMMAND_COMPLETE /* 0x4000 */) {
 787                 test_ok = 0;
 788         } else {
 789                 for (i = 1; i < qlge->max_read_mbx; i++) {
 790                         if (mbx_cmds.mb[i] != i) {
 791                                 test_ok = 0;
 792                                 break;
 793                         }
 794                 }
 795         }
 796         if (test_ok) {
 797                 rtn_val = DDI_SUCCESS;
 798         } else {
 799                 cmn_err(CE_WARN, "%s(%d) mailbox test failed!",
 800                     __func__, qlge->instance);
 801         }
 802 out:
 803         if ((rtn_val != DDI_SUCCESS) && qlge->fm_enable) {
 804                 ql_fm_ereport(qlge, DDI_FM_DEVICE_NO_RESPONSE);
 805                 ddi_fm_service_impact(qlge->dip, DDI_SERVICE_DEGRADED);
 806         }
 807         return (rtn_val);
 808 }
 809 
 810 /*
 811  * ql_get_fw_state
 812  * Get fw state.
 813  * mailbox cmd:0x69h
 814  */
 815 int
 816 ql_get_fw_state(qlge_t *qlge, uint32_t *fw_state_ptr)
 817 {
 818         int rtn_val = DDI_FAILURE;
 819         mbx_cmd_t mbx_cmds = {0};
 820 
 821         mbx_cmds.mb[0] = MBC_GET_FIRMWARE_STATE;
 822 
 823         if (ql_issue_mailbox_cmd_and_wait_rsp(qlge, &mbx_cmds)
 824             != DDI_SUCCESS) {
 825                 cmn_err(CE_WARN, "%s(%d) ql_issue_mailbox_cmd_and_wait_rsp"
 826                     " failed.", __func__, qlge->instance);
 827                 goto out;
 828         }
 829         /* verify if the transaction is completed successful */
 830         if (mbx_cmds.mb[0] != MBS_COMMAND_COMPLETE /* 0x4000 */) {
 831                 cmn_err(CE_WARN, "%s(%d) failed, 0x%x",
 832                     __func__, qlge->instance, mbx_cmds.mb[0]);
 833         } else {
 834                 /* EMPTY */
 835                 QL_PRINT(DBG_MBX, ("firmware state: 0x%x\n", mbx_cmds.mb[1]));
 836         }
 837         if (fw_state_ptr != NULL)
 838                 *fw_state_ptr = mbx_cmds.mb[1];
 839         rtn_val = DDI_SUCCESS;
 840 out:
 841         if ((rtn_val != DDI_SUCCESS) && qlge->fm_enable) {
 842                 ql_fm_ereport(qlge, DDI_FM_DEVICE_NO_RESPONSE);
 843                 ddi_fm_service_impact(qlge->dip, DDI_SERVICE_DEGRADED);
 844         }
 845         return (rtn_val);
 846 }
 847 
 848 /*
 849  * ql_set_IDC_Req
 850  * Send a IDC Request to firmware to notify all functions
 851  * or any specific functions on the same port
 852  * mailbox cmd:0x100h
 853  */
 854 int
 855 ql_set_IDC_Req(qlge_t *qlge, uint8_t dest_functions, uint8_t timeout)
 856 {
 857         int rtn_val = DDI_FAILURE;
 858         mbx_cmd_t mbx_cmds = {0};
 859 
 860         mbx_cmds.mb[0] = MBC_IDC_REQUEST /* 0x100 */;
 861         mbx_cmds.mb[1] = (timeout<<8) | qlge->func_number;
 862 
 863         switch (dest_functions) {
 864         case IDC_REQ_DEST_FUNC_ALL:
 865                 mbx_cmds.mb[1] |= IDC_REQ_ALL_DEST_FUNC_MASK;
 866                 mbx_cmds.mb[2] = 0;
 867                 break;
 868         case IDC_REQ_DEST_FUNC_0:
 869                 mbx_cmds.mb[2] = IDC_REQ_DEST_FUNC_0_MASK;
 870                 break;
 871         case IDC_REQ_DEST_FUNC_1:
 872                 mbx_cmds.mb[2] = IDC_REQ_DEST_FUNC_1_MASK;
 873                 break;
 874         case IDC_REQ_DEST_FUNC_2:
 875                 mbx_cmds.mb[2] = IDC_REQ_DEST_FUNC_2_MASK;
 876                 break;
 877         case IDC_REQ_DEST_FUNC_3:
 878                 mbx_cmds.mb[2] = IDC_REQ_DEST_FUNC_3_MASK;
 879                 break;
 880         default:
 881                 cmn_err(CE_WARN, "Wrong dest functions %x",
 882                     dest_functions);
 883         }
 884 
 885         if (ql_issue_mailbox_cmd_and_wait_rsp(qlge, &mbx_cmds) != DDI_SUCCESS) {
 886                 cmn_err(CE_WARN,
 887                     "%s(%d) ql_issue_mailbox_cmd_and_wait_rsp failed.",
 888                     __func__, qlge->instance);
 889                 goto out;
 890         }
 891         /* verify if the transaction is completed successful */
 892         if (mbx_cmds.mb[0] == MBA_IDC_INTERMEDIATE_COMPLETE /* 0x1000 */) {
 893                 QL_PRINT(DBG_MBX, ("%s(%d) mbx1: 0x%x, mbx2: 0x%x\n",
 894                     __func__, qlge->instance, mbx_cmds.mb[1], mbx_cmds.mb[2]));
 895                 rtn_val = DDI_SUCCESS;
 896         } else if (mbx_cmds.mb[0] == MBS_COMMAND_COMPLETE /* 0x4000 */) {
 897                 QL_PRINT(DBG_MBX, ("%s(%d) cmd sent succesfully 0x%x\n",
 898                     __func__, qlge->instance));
 899                 rtn_val = DDI_SUCCESS;
 900         } else if (mbx_cmds.mb[0] == MBS_COMMAND_ERROR /* 0x4005 */) {
 901                 cmn_err(CE_WARN, "%s(%d) failed: COMMAND_ERROR",
 902                     __func__, qlge->instance);
 903         } else if (mbx_cmds.mb[0] == MBS_COMMAND_PARAMETER_ERROR /* 0x4006 */) {
 904                 cmn_err(CE_WARN, "%s(%d) failed: COMMAND_PARAMETER_ERROR",
 905                     __func__, qlge->instance);
 906         } else {
 907                 cmn_err(CE_WARN, "%s(%d) unknow result: mbx[0]: 0x%x; mbx[1]:"
 908                     " 0x%x; mbx[2]: 0x%x", __func__, qlge->instance,
 909                     mbx_cmds.mb[0], mbx_cmds.mb[1], mbx_cmds.mb[2]);
 910         }
 911 
 912 out:
 913         if ((rtn_val != DDI_SUCCESS) && qlge->fm_enable) {
 914                 ql_fm_ereport(qlge, DDI_FM_DEVICE_NO_RESPONSE);
 915                 ddi_fm_service_impact(qlge->dip, DDI_SERVICE_DEGRADED);
 916         }
 917 return (rtn_val);
 918 }
 919 
 920 /*
 921  * ql_set_mpi_port_config
 922  * Send new port configuration.to mpi
 923  * mailbox cmd:0x122h
 924  */
 925 int
 926 ql_set_mpi_port_config(qlge_t *qlge, port_cfg_info_t new_cfg)
 927 {
 928         int rtn_val = DDI_FAILURE;
 929         mbx_cmd_t mbx_cmds = {0};
 930 
 931         mbx_cmds.mb[0] = MBC_SET_PORT_CONFIG /* 0x122 */;
 932         mbx_cmds.mb[1] = new_cfg.link_cfg;
 933         mbx_cmds.mb[2] = new_cfg.max_frame_size;
 934 
 935         if (ql_issue_mailbox_cmd_and_wait_rsp(qlge, &mbx_cmds) != DDI_SUCCESS) {
 936                 cmn_err(CE_WARN, "%s(%d) ql_issue_mailbox_cmd_and_wait_rsp"
 937                     " failed.", __func__, qlge->instance);
 938                 goto out;
 939         }
 940         /* verify if the transaction is completed successful */
 941         if ((mbx_cmds.mb[0] != MBS_COMMAND_COMPLETE /* 0x4000 */) &&
 942             (mbx_cmds.mb[0] != MBA_IDC_COMPLETE /* 0x8100 */)) {
 943                 cmn_err(CE_WARN, "set port config (%d) failed, 0x%x",
 944                     qlge->instance, mbx_cmds.mb[0]);
 945         } else
 946                 rtn_val = DDI_SUCCESS;
 947 out:
 948         if ((rtn_val != DDI_SUCCESS) && qlge->fm_enable) {
 949                 ql_fm_ereport(qlge, DDI_FM_DEVICE_NO_RESPONSE);
 950                 ddi_fm_service_impact(qlge->dip, DDI_SERVICE_DEGRADED);
 951         }
 952         return (rtn_val);
 953 }
 954 
 955 int
 956 ql_set_pause_mode(qlge_t *qlge)
 957 {
 958         uint32_t pause_bit_mask = 0x60; /* bit 5-6 */
 959 
 960         /* clear pause bits */
 961         qlge->port_cfg_info.link_cfg &= ~pause_bit_mask;
 962 
 963         /* set new pause mode */
 964         if (qlge->pause == PAUSE_MODE_STANDARD)
 965                 qlge->port_cfg_info.link_cfg |= STD_PAUSE;
 966         else if (qlge->pause == PAUSE_MODE_PER_PRIORITY)
 967                 qlge->port_cfg_info.link_cfg |= PP_PAUSE;
 968 
 969         return (ql_set_mpi_port_config(qlge, qlge->port_cfg_info));
 970 }
 971 
 972 int
 973 ql_set_loop_back_mode(qlge_t *qlge)
 974 {
 975         uint32_t loop_back_bit_mask = 0x0e; /* bit 1-3 */
 976 
 977         /* clear loop back bits */
 978         qlge->port_cfg_info.link_cfg &= ~loop_back_bit_mask;
 979         /* loop back cfg: bit1-3 */
 980         if (qlge->loop_back_mode == QLGE_LOOP_INTERNAL_PARALLEL)
 981                 qlge->port_cfg_info.link_cfg |= LOOP_INTERNAL_PARALLEL;
 982         else if (qlge->loop_back_mode == QLGE_LOOP_INTERNAL_SERIAL)
 983                 qlge->port_cfg_info.link_cfg |= LOOP_INTERNAL_SERIAL;
 984         else if (qlge->loop_back_mode == QLGE_LOOP_EXTERNAL_PHY)
 985                 qlge->port_cfg_info.link_cfg |= LOOP_EXTERNAL_PHY;
 986 
 987         return (ql_set_mpi_port_config(qlge, qlge->port_cfg_info));
 988 
 989 }
 990 /*
 991  * ql_get_port_cfg
 992  * Get port configuration.
 993  * mailbox cmd:0x123h
 994  */
 995 int
 996 ql_get_port_cfg(qlge_t *qlge)
 997 {
 998         int rtn_val = DDI_FAILURE;
 999         mbx_cmd_t mbx_cmds = {0};
1000 
1001         mbx_cmds.mb[0] = MBC_GET_PORT_CONFIG /* 0x123 */;
1002         if (ql_issue_mailbox_cmd_and_wait_rsp(qlge, &mbx_cmds) != DDI_SUCCESS) {
1003                 cmn_err(CE_WARN, "%s(%d) ql_issue_mailbox_cmd_and_wait_rsp"
1004                     " failed.", __func__, qlge->instance);
1005                 goto out;
1006         }
1007         /* verify if the transaction is completed successfully */
1008         if (mbx_cmds.mb[0] != MBS_COMMAND_COMPLETE /* 0x4000 */) {
1009                 cmn_err(CE_WARN, "get port config (%d) failed, 0x%x",
1010                     qlge->instance, mbx_cmds.mb[0]);
1011         } else { /* verify frame size */
1012                 if ((mbx_cmds.mb[2] == NORMAL_FRAME_SIZE) ||
1013                     (mbx_cmds.mb[2] == JUMBO_FRAME_SIZE)) {
1014                         qlge->port_cfg_info.link_cfg = mbx_cmds.mb[1];
1015                         qlge->port_cfg_info.max_frame_size = mbx_cmds.mb[2];
1016                         QL_PRINT(DBG_MBX, ("link_cfg: 0x%x, max_frame_size:"
1017                             " %d bytes\n", mbx_cmds.mb[1], mbx_cmds.mb[2]));
1018                         rtn_val = DDI_SUCCESS;
1019                 } else {
1020                         cmn_err(CE_WARN, "bad link_cfg: 0x%x, max_frame_size:"
1021                             " %d bytes", mbx_cmds.mb[1], mbx_cmds.mb[2]);
1022                 }
1023         }
1024 out:
1025         if ((rtn_val != DDI_SUCCESS) && qlge->fm_enable) {
1026                 ql_fm_ereport(qlge, DDI_FM_DEVICE_NO_RESPONSE);
1027                 ddi_fm_service_impact(qlge->dip, DDI_SERVICE_DEGRADED);
1028         }
1029         return (rtn_val);
1030 }
1031 
1032 /*
1033  * qlge_get_link_status
1034  * Get link status.
1035  * mailbox cmd:0x124h
1036  */
1037 int
1038 qlge_get_link_status(qlge_t *qlge,
1039     struct qlnic_link_status_info *link_status_ptr)
1040 {
1041         int rtn_val = DDI_FAILURE;
1042         mbx_cmd_t mbx_cmds = {0};
1043 
1044         mbx_cmds.mb[0] = MBC_GET_LINK_STATUS /* 0x124 */;
1045 
1046         if (ql_issue_mailbox_cmd_and_wait_rsp(qlge, &mbx_cmds)
1047             != DDI_SUCCESS) {
1048                 cmn_err(CE_WARN,
1049                     "%s(%d) ql_issue_mailbox_cmd_and_wait_rsp failed.",
1050                     __func__, qlge->instance);
1051                 goto out;
1052         }
1053         /* verify if the transaction is completed successful */
1054         if (mbx_cmds.mb[0] != MBS_COMMAND_COMPLETE /* 0x4000 */) {
1055                 cmn_err(CE_WARN, "get link status(%d) failed, 0x%x",
1056                     qlge->instance, mbx_cmds.mb[0]);
1057         } else {
1058                 /* EMPTY */
1059                 QL_PRINT(DBG_MBX,
1060                     ("link status: status1 : 0x%x, status2 : 0x%x, "
1061                     "status3 : 0x%x\n",
1062                     mbx_cmds.mb[1], mbx_cmds.mb[2], mbx_cmds.mb[3]));
1063         }
1064         if (link_status_ptr != NULL) {
1065                 link_status_ptr->link_status_info = mbx_cmds.mb[1];
1066                 link_status_ptr->additional_info = mbx_cmds.mb[2];
1067                 link_status_ptr->network_hw_info = mbx_cmds.mb[3];
1068                 link_status_ptr->dcbx_frame_counters_info = mbx_cmds.mb[4];
1069                 link_status_ptr->change_counters_info = mbx_cmds.mb[5];
1070         }
1071         rtn_val = DDI_SUCCESS;
1072 out:
1073         if ((rtn_val != DDI_SUCCESS) && qlge->fm_enable) {
1074                 ql_fm_ereport(qlge, DDI_FM_DEVICE_NO_RESPONSE);
1075                 ddi_fm_service_impact(qlge->dip, DDI_SERVICE_DEGRADED);
1076         }
1077         return (rtn_val);
1078 }
1079 
1080 /*
1081  * ql_get_firmware_version
1082  * Get firmware version.
1083  */
1084 int
1085 ql_get_firmware_version(qlge_t *qlge,
1086     struct qlnic_mpi_version_info *mpi_version_ptr)
1087 {
1088         int rtn_val = DDI_FAILURE;
1089         mbx_cmd_t mbx_cmds = {0};
1090 
1091         mbx_cmds.mb[0] = MBC_ABOUT_FIRMWARE /* 0x08 */;
1092 
1093         if (ql_issue_mailbox_cmd_and_wait_rsp(qlge, &mbx_cmds)
1094             != DDI_SUCCESS) {
1095                 cmn_err(CE_WARN,
1096                     "%s(%d) ql_issue_mailbox_cmd_and_wait_rsp failed.",
1097                     __func__, qlge->instance);
1098                 goto out;
1099         }
1100 
1101         /* verify if the transaction is completed successful */
1102         if (mbx_cmds.mb[0] != MBS_COMMAND_COMPLETE /* 0x4000 */) {
1103                 cmn_err(CE_WARN, "get firmware version(%d) failed, 0x%x",
1104                     qlge->instance, mbx_cmds.mb[0]);
1105         } else {
1106                 qlge->fw_version_info.major_version =
1107                     LSB(MSW(mbx_cmds.mb[1]));
1108                 qlge->fw_version_info.minor_version =
1109                     MSB(LSW(mbx_cmds.mb[1]));
1110                 qlge->fw_version_info.sub_minor_version =
1111                     LSB(LSW(mbx_cmds.mb[1]));
1112                 qlge->phy_version_info.major_version =
1113                     LSB(MSW(mbx_cmds.mb[2]));
1114                 qlge->phy_version_info.minor_version =
1115                     MSB(LSW(mbx_cmds.mb[2]));
1116                 qlge->phy_version_info.sub_minor_version =
1117                     LSB(LSW(mbx_cmds.mb[2]));
1118 #ifdef QLGE_LOAD_UNLOAD
1119                 cmn_err(CE_NOTE, "firmware version: %d.%d.%d\n",
1120                     qlge->fw_version_info.major_version,
1121                     qlge->fw_version_info.minor_version,
1122                     qlge->fw_version_info.sub_minor_version);
1123 #endif
1124                 if (mpi_version_ptr != NULL) {
1125                         mpi_version_ptr->fw_version =
1126                             (qlge->fw_version_info.major_version<<16)
1127                             |(qlge->fw_version_info.minor_version<<8)
1128                             |(qlge->fw_version_info.sub_minor_version);
1129                         mpi_version_ptr->phy_version =
1130                             (qlge->phy_version_info.major_version<<16)
1131                             |(qlge->phy_version_info.minor_version<<8)
1132                             |(qlge->phy_version_info.sub_minor_version);
1133                 }
1134         }
1135         rtn_val = DDI_SUCCESS;
1136 out:
1137         if ((rtn_val != DDI_SUCCESS) && qlge->fm_enable) {
1138                 ql_fm_ereport(qlge, DDI_FM_DEVICE_NO_RESPONSE);
1139                 ddi_fm_service_impact(qlge->dip, DDI_SERVICE_DEGRADED);
1140         }
1141         return (rtn_val);
1142 }
1143 
1144 /*
1145  * Trigger a system error event
1146  */
1147 int
1148 ql_trigger_system_error_event(qlge_t *qlge)
1149 {
1150         mbx_cmd_t mbx_cmds = {0};
1151         int rtn_val = DDI_FAILURE;
1152 
1153         mbx_cmds.mb[0] = MBC_GENERATE_SYS_ERROR; /* 0x2A */
1154         if (ql_issue_mailbox_cmd(qlge, &mbx_cmds) != DDI_SUCCESS) {
1155                 cmn_err(CE_WARN, "%s(%d) ql_issue_mailbox_cmd timeout.",
1156                     __func__, qlge->instance);
1157                 goto out;
1158         }
1159         rtn_val = DDI_SUCCESS;
1160 out:
1161         return (rtn_val);
1162 }
1163 
1164 /*
1165  * Reset the MPI RISC Processor
1166  */
1167 int
1168 ql_reset_mpi_risc(qlge_t *qlge)
1169 {
1170         int rtn_val = DDI_FAILURE;
1171 
1172         /* Reset the MPI Processor */
1173         ql_write_reg(qlge, REG_HOST_CMD_STATUS, HOST_CMD_SET_RISC_RESET);
1174         if (ql_wait_reg_bit(qlge, REG_HOST_CMD_STATUS, RISC_RESET,
1175             BIT_SET, 0) != DDI_SUCCESS) {
1176                 (void) ql_read_reg(qlge, REG_HOST_CMD_STATUS);
1177                 goto out;
1178         }
1179         ql_write_reg(qlge, REG_HOST_CMD_STATUS, HOST_CMD_CLEAR_RISC_RESET);
1180         rtn_val = DDI_SUCCESS;
1181 out:
1182         return (rtn_val);
1183 }
1184 
1185 int
1186 ql_read_risc_ram(qlge_t *qlge, uint32_t risc_address, uint64_t bp,
1187     uint32_t word_count)
1188 {
1189         int rval = DDI_FAILURE;
1190         mbx_cmd_t mc = {0};
1191         mbx_cmd_t *mcp = &mc;
1192         mbx_data_t mbx_results;
1193 
1194         QL_PRINT(DBG_MBX, ("%s(%d): read risc addr:0x%x,"
1195             "phys_addr %x,%x words\n", __func__, qlge->instance,
1196             risc_address, bp, word_count));
1197         if (CFG_IST(qlge, CFG_CHIP_8100)) {
1198                 mcp->mb[0] = MBC_DUMP_RISC_RAM /* 0x0C */;
1199                 mcp->mb[1] = LSW(risc_address);
1200                 mcp->mb[2] = MSW(LSD(bp));
1201                 mcp->mb[3] = LSW(LSD(bp));
1202                 mcp->mb[4] = MSW(word_count);
1203                 mcp->mb[5] = LSW(word_count);
1204                 mcp->mb[6] = MSW(MSD(bp));
1205                 mcp->mb[7] = LSW(MSD(bp));
1206                 mcp->mb[8] = MSW(risc_address);
1207         }
1208         mcp->timeout = 10 /* MAILBOX_TOV */;
1209 
1210         if (ql_issue_mailbox_cmd_and_poll_rsp(qlge, mcp, &mbx_results)
1211             != DDI_SUCCESS) {
1212                 goto out;
1213         } else {
1214                 QL_PRINT(DBG_MBX, ("%s(%d) PI Intr received",
1215                     __func__, qlge->instance));
1216                 if (mbx_results.mb[0] == MBS_COMMAND_COMPLETE /* 0x4000 */) {
1217                         QL_PRINT(DBG_MBX, ("%s(%d): success\n",
1218                             __func__, qlge->instance));
1219                         rval = DDI_SUCCESS;
1220                 } else {
1221                         cmn_err(CE_WARN, "read_risc_ram(%d): failed, status %x",
1222                             qlge->instance, mbx_results.mb[0]);
1223                 }
1224         }
1225 out:
1226         return (rval);
1227 }