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 2009 Emulex. All rights reserved. 24 * Use is subject to License terms. 25 */ 26 27 #define EMLXS_FW_TABLE_DEF 28 #define EMLXS_MODEL_DEF 29 30 #include <emlxs.h> 31 32 /* Required for EMLXS_CONTEXT in EMLXS_MSGF calls */ 33 EMLXS_MSG_DEF(EMLXS_HBA_C); 34 35 static uint32_t emlxs_decode_biu_rev(uint32_t rev); 36 static uint32_t emlxs_decode_endec_rev(uint32_t rev); 37 static void emlxs_parse_prog_types(emlxs_hba_t *hba, char *types); 38 static int32_t emlxs_parse_vpd(emlxs_hba_t *hba, uint8_t *vpd, 39 uint32_t size); 40 static void emlxs_build_prog_types(emlxs_hba_t *hba, char *prog_types); 41 static void emlxs_handle_async_event(emlxs_hba_t *hba, RING *rp, 42 IOCBQ *iocbq); 43 static void emlxs_process_link_speed(emlxs_hba_t *hba); 44 static void emlxs_decode_label(char *label, char *buffer); 45 46 #ifdef MODFW_SUPPORT 47 static void emlxs_fw_load(emlxs_hba_t *hba, emlxs_firmware_t *fw); 48 static void emlxs_fw_unload(emlxs_hba_t *hba, emlxs_firmware_t *fw); 49 #endif /* MODFW_SUPPORT */ 50 51 #ifdef MSI_SUPPORT 52 uint32_t emlxs_msi_map[EMLXS_MSI_MODES][EMLXS_MSI_MAX_INTRS] = 53 {EMLXS_MSI_MAP1, EMLXS_MSI_MAP2, EMLXS_MSI_MAP4, EMLXS_MSI_MAP8}; 54 uint32_t emlxs_msi_mask[EMLXS_MSI_MODES] = 55 {EMLXS_MSI0_MASK1, EMLXS_MSI0_MASK2, EMLXS_MSI0_MASK4, 56 EMLXS_MSI0_MASK8}; 57 #endif /* MSI_SUPPORT */ 58 59 60 static uint32_t emlxs_disable_traffic_cop = 1; 61 62 emlxs_table_t emlxs_ring_table[] = { 63 {FC_FCP_RING, "FCP Ring"}, 64 {FC_IP_RING, "IP Ring"}, 65 {FC_ELS_RING, "ELS Ring"}, 66 {FC_CT_RING, "CT Ring"} 67 68 }; /* emlxs_ring_table */ 69 70 71 emlxs_table_t emlxs_ffstate_table[] = { 72 {0, "NULL"}, 73 {FC_ERROR, "ERROR"}, 74 {FC_KILLED, "KILLED"}, 75 {FC_WARM_START, "WARM_START"}, 76 {FC_INIT_START, "INIT_START"}, 77 {FC_INIT_NVPARAMS, "INIT_NVPARAMS"}, 78 {FC_INIT_REV, "INIT_REV"}, 79 {FC_INIT_CFGPORT, "INIT_CFGPORT"}, 80 {FC_INIT_CFGRING, "INIT_CFGRING"}, 81 {FC_INIT_INITLINK, "INIT_INITLINK"}, 82 {FC_LINK_DOWN, "LINK_DOWN"}, 83 {FC_LINK_UP, "LINK_UP"}, 84 {FC_CLEAR_LA, "CLEAR_LA"}, 85 {FC_READY, "READY"} 86 87 }; /* emlxs_ffstate_table */ 88 89 90 /* 91 * emlxs_ffinit() 92 * 93 * This routine will start initialization of the FireFly Chipset 94 */ 95 extern int 96 emlxs_ffinit(emlxs_hba_t *hba) 97 { 98 emlxs_port_t *port = &PPORT; 99 emlxs_config_t *cfg; 100 emlxs_vpd_t *vpd; 101 MAILBOX *mb; 102 RING *rp; 103 MATCHMAP *mp; 104 MATCHMAP *mp1; 105 uint8_t *inptr; 106 uint8_t *outptr; 107 uint32_t status; 108 uint32_t i; 109 uint32_t j; 110 uint32_t read_rev_reset; 111 uint32_t key = 0; 112 uint32_t fw_check; 113 uint32_t rval; 114 uint32_t offset; 115 uint8_t vpd_data[DMP_VPD_SIZE]; 116 uint32_t MaxRbusSize; 117 uint32_t MaxIbusSize; 118 uint32_t sli_mode; 119 uint32_t sli_mode_mask; 120 121 cfg = &CFG; 122 vpd = &VPD; 123 mb = 0; 124 MaxRbusSize = 0; 125 MaxIbusSize = 0; 126 read_rev_reset = 0; 127 128 if (hba->bus_type == SBUS_FC) { 129 (void) READ_SBUS_CSR_REG(hba, FC_SHS_REG(hba, 130 hba->sbus_csr_addr)); 131 } 132 133 #ifdef SLI3_SUPPORT 134 /* Initialize sli mode based on configuration parameter */ 135 switch (cfg[CFG_SLI_MODE].current) { 136 case 2: /* SLI2 mode */ 137 sli_mode = EMLXS_HBA_SLI2_MODE; 138 sli_mode_mask = EMLXS_SLI2_MASK; 139 break; 140 141 case 3: /* SLI3 mode */ 142 sli_mode = EMLXS_HBA_SLI3_MODE; 143 sli_mode_mask = EMLXS_SLI3_MASK; 144 break; 145 146 case 0: /* Best available */ 147 case 1: /* Best available */ 148 default: 149 if (hba->model_info.sli_mask & EMLXS_SLI4_MASK) { 150 sli_mode = EMLXS_HBA_SLI4_MODE; 151 sli_mode_mask = EMLXS_SLI4_MASK; 152 } else if (hba->model_info.sli_mask & EMLXS_SLI3_MASK) { 153 sli_mode = EMLXS_HBA_SLI3_MODE; 154 sli_mode_mask = EMLXS_SLI3_MASK; 155 } else if (hba->model_info.sli_mask & EMLXS_SLI2_MASK) { 156 sli_mode = EMLXS_HBA_SLI2_MODE; 157 sli_mode_mask = EMLXS_SLI2_MASK; 158 } 159 } 160 /* SBUS adapters only available in SLI2 */ 161 if (hba->bus_type == SBUS_FC) { 162 sli_mode = EMLXS_HBA_SLI2_MODE; 163 sli_mode_mask = EMLXS_SLI2_MASK; 164 } 165 166 #endif /* SLI3_SUPPORT */ 167 168 /* Set the fw_check flag */ 169 fw_check = cfg[CFG_FW_CHECK].current; 170 171 hba->mbox_queue_flag = 0; 172 hba->hc_copy = 0; 173 hba->fc_edtov = FF_DEF_EDTOV; 174 hba->fc_ratov = FF_DEF_RATOV; 175 hba->fc_altov = FF_DEF_ALTOV; 176 hba->fc_arbtov = FF_DEF_ARBTOV; 177 178 reset: 179 180 /* Reset and initialize the adapter */ 181 if (emlxs_sli_online(hba)) { 182 return (EIO); 183 } 184 185 #ifdef FMA_SUPPORT 186 /* Access handle validation */ 187 if (hba->fm_caps & DDI_FM_ACCCHK_CAPABLE) { 188 if ((emlxs_fm_check_acc_handle(hba->pci_acc_handle) 189 != DDI_FM_OK) || 190 (emlxs_fm_check_acc_handle(hba->slim_acc_handle) 191 != DDI_FM_OK) || 192 (emlxs_fm_check_acc_handle(hba->csr_acc_handle) 193 != DDI_FM_OK)) { 194 EMLXS_MSGF(EMLXS_CONTEXT, 195 &emlxs_invalid_access_handle_msg, NULL); 196 return (EIO); 197 } 198 } 199 #endif /* FMA_SUPPORT */ 200 201 /* 202 * Allocate some memory for buffers 203 */ 204 if (emlxs_mem_alloc_buffer(hba) == 0) { 205 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg, 206 "Unable to allocate memory buffers."); 207 208 emlxs_ffstate_change(hba, FC_ERROR); 209 210 return (ENOMEM); 211 } 212 213 /* 214 * Get a buffer which will be used repeatedly for mailbox commands 215 */ 216 if ((mb = (MAILBOX *) emlxs_mem_get(hba, MEM_MBOX | MEM_PRI)) == 0) { 217 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg, 218 "Unable to allocate mailbox buffer."); 219 220 emlxs_ffstate_change(hba, FC_ERROR); 221 (void) emlxs_mem_free_buffer(hba); 222 223 return (ENOMEM); 224 } 225 226 /* Check for the LP9802 (This is a special case) */ 227 /* We need to check for dual channel adapter */ 228 if (hba->model_info.device_id == PCI_DEVICE_ID_LP9802) { 229 /* Try to determine if this is a DC adapter */ 230 if (emlxs_get_max_sram(hba, &MaxRbusSize, &MaxIbusSize) == 0) { 231 if (MaxRbusSize == REDUCED_SRAM_CFG) { 232 /* LP9802DC */ 233 for (i = 1; i < EMLXS_PCI_MODEL_COUNT; i++) { 234 if (emlxs_pci_model[i].id == LP9802DC) { 235 bcopy(&emlxs_pci_model[i], 236 &hba->model_info, 237 sizeof (emlxs_model_t)); 238 break; 239 } 240 } 241 } else if (hba->model_info.id != LP9802) { 242 /* LP9802 */ 243 for (i = 1; i < EMLXS_PCI_MODEL_COUNT; i++) { 244 if (emlxs_pci_model[i].id == LP9802) { 245 bcopy(&emlxs_pci_model[i], 246 &hba->model_info, 247 sizeof (emlxs_model_t)); 248 break; 249 } 250 } 251 } 252 } 253 } 254 255 /* 256 * Setup and issue mailbox READ REV command 257 */ 258 vpd->opFwRev = 0; 259 vpd->postKernRev = 0; 260 vpd->sli1FwRev = 0; 261 vpd->sli2FwRev = 0; 262 vpd->sli3FwRev = 0; 263 vpd->sli4FwRev = 0; 264 265 vpd->postKernName[0] = 0; 266 vpd->opFwName[0] = 0; 267 vpd->sli1FwName[0] = 0; 268 vpd->sli2FwName[0] = 0; 269 vpd->sli3FwName[0] = 0; 270 vpd->sli4FwName[0] = 0; 271 272 vpd->opFwLabel[0] = 0; 273 vpd->sli1FwLabel[0] = 0; 274 vpd->sli2FwLabel[0] = 0; 275 vpd->sli3FwLabel[0] = 0; 276 vpd->sli4FwLabel[0] = 0; 277 278 emlxs_ffstate_change(hba, FC_INIT_REV); 279 emlxs_mb_read_rev(hba, mb, 0); 280 if (emlxs_sli_issue_mbox_cmd(hba, mb, MBX_WAIT, 0) != MBX_SUCCESS) { 281 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg, 282 "Unable to read rev. Mailbox cmd=%x status=%x", 283 mb->mbxCommand, mb->mbxStatus); 284 285 emlxs_ffstate_change(hba, FC_ERROR); 286 (void) emlxs_mem_put(hba, MEM_MBOX, (uint8_t *)mb); 287 (void) emlxs_mem_free_buffer(hba); 288 289 return (EIO); 290 } 291 292 if (mb->un.varRdRev.rr == 0) { 293 /* Old firmware */ 294 if (read_rev_reset == 0) { 295 /* Clean up */ 296 (void) emlxs_mem_put(hba, MEM_MBOX, (uint8_t *)mb); 297 (void) emlxs_mem_free_buffer(hba); 298 299 read_rev_reset = 1; 300 301 goto reset; 302 } else { 303 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_msg, 304 "Outdated firmware detected."); 305 } 306 307 vpd->rBit = 0; 308 } else { 309 if (mb->un.varRdRev.un.b.ProgType != FUNC_FIRMWARE) { 310 if (read_rev_reset == 0) { 311 /* Clean up */ 312 (void) emlxs_mem_put(hba, MEM_MBOX, 313 (uint8_t *)mb); 314 (void) emlxs_mem_free_buffer(hba); 315 316 read_rev_reset = 1; 317 318 goto reset; 319 } else { 320 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_msg, 321 "Non-operational firmware detected. " 322 "type=%x", 323 mb->un.varRdRev.un.b.ProgType); 324 } 325 } 326 327 vpd->rBit = 1; 328 vpd->sli1FwRev = mb->un.varRdRev.sliFwRev1; 329 bcopy((char *)mb->un.varRdRev.sliFwName1, vpd->sli1FwLabel, 330 16); 331 vpd->sli2FwRev = mb->un.varRdRev.sliFwRev2; 332 bcopy((char *)mb->un.varRdRev.sliFwName2, vpd->sli2FwLabel, 333 16); 334 335 /* 336 * Lets try to read the SLI3 version 337 * Setup and issue mailbox READ REV(v3) command 338 */ 339 emlxs_ffstate_change(hba, FC_INIT_REV); 340 emlxs_mb_read_rev(hba, mb, 1); 341 342 if (emlxs_sli_issue_mbox_cmd(hba, mb, MBX_WAIT, 0) != 343 MBX_SUCCESS) { 344 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg, 345 "Unable to read rev (v3). Mailbox cmd=%x status=%x", 346 mb->mbxCommand, mb->mbxStatus); 347 348 emlxs_ffstate_change(hba, FC_ERROR); 349 (void) emlxs_mem_put(hba, MEM_MBOX, (uint8_t *)mb); 350 (void) emlxs_mem_free_buffer(hba); 351 352 return (EIO); 353 } 354 355 if (mb->un.varRdRev.rf3) { 356 /* 357 * vpd->sli2FwRev = mb->un.varRdRev.sliFwRev1; 358 * Not needed 359 */ 360 vpd->sli3FwRev = mb->un.varRdRev.sliFwRev2; 361 bcopy((char *)mb->un.varRdRev.sliFwName2, 362 vpd->sli3FwLabel, 16); 363 } 364 } 365 366 367 if ((sli_mode == EMLXS_HBA_SLI3_MODE) && (vpd->sli3FwRev == 0)) { 368 if (vpd->sli2FwRev) { 369 sli_mode = EMLXS_HBA_SLI2_MODE; 370 sli_mode_mask = EMLXS_SLI2_MASK; 371 } else { 372 sli_mode = 0; 373 sli_mode_mask = 0; 374 } 375 } 376 377 else if ((sli_mode == EMLXS_HBA_SLI2_MODE) && (vpd->sli2FwRev == 0)) { 378 if (vpd->sli3FwRev) { 379 sli_mode = EMLXS_HBA_SLI3_MODE; 380 sli_mode_mask = EMLXS_SLI3_MASK; 381 } else { 382 sli_mode = 0; 383 sli_mode_mask = 0; 384 } 385 } 386 387 if (!(hba->model_info.sli_mask & sli_mode_mask)) { 388 #ifdef SLI3_SUPPORT 389 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg, 390 "Firmware not available. sli-mode=%d", 391 cfg[CFG_SLI_MODE].current); 392 #else 393 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg, 394 "Firmware not available. sli-mode=2"); 395 #endif /* SLI3_SUPPORT */ 396 397 emlxs_ffstate_change(hba, FC_ERROR); 398 (void) emlxs_mem_put(hba, MEM_MBOX, (uint8_t *)mb); 399 (void) emlxs_mem_free_buffer(hba); 400 401 return (EIO); 402 } 403 404 /* Save information as VPD data */ 405 vpd->postKernRev = mb->un.varRdRev.postKernRev; 406 vpd->opFwRev = mb->un.varRdRev.opFwRev; 407 bcopy((char *)mb->un.varRdRev.opFwName, vpd->opFwLabel, 16); 408 vpd->biuRev = mb->un.varRdRev.biuRev; 409 vpd->smRev = mb->un.varRdRev.smRev; 410 vpd->smFwRev = mb->un.varRdRev.un.smFwRev; 411 vpd->endecRev = mb->un.varRdRev.endecRev; 412 vpd->fcphHigh = mb->un.varRdRev.fcphHigh; 413 vpd->fcphLow = mb->un.varRdRev.fcphLow; 414 vpd->feaLevelHigh = mb->un.varRdRev.feaLevelHigh; 415 vpd->feaLevelLow = mb->un.varRdRev.feaLevelLow; 416 417 /* Decode FW names */ 418 emlxs_decode_version(vpd->postKernRev, vpd->postKernName); 419 emlxs_decode_version(vpd->opFwRev, vpd->opFwName); 420 emlxs_decode_version(vpd->sli1FwRev, vpd->sli1FwName); 421 emlxs_decode_version(vpd->sli2FwRev, vpd->sli2FwName); 422 emlxs_decode_version(vpd->sli3FwRev, vpd->sli3FwName); 423 emlxs_decode_version(vpd->sli4FwRev, vpd->sli4FwName); 424 425 /* Decode FW labels */ 426 emlxs_decode_label(vpd->opFwLabel, vpd->opFwLabel); 427 emlxs_decode_label(vpd->sli1FwLabel, vpd->sli1FwLabel); 428 emlxs_decode_label(vpd->sli2FwLabel, vpd->sli2FwLabel); 429 emlxs_decode_label(vpd->sli3FwLabel, vpd->sli3FwLabel); 430 emlxs_decode_label(vpd->sli4FwLabel, vpd->sli4FwLabel); 431 432 key = emlxs_get_key(hba, mb); 433 434 /* Get adapter VPD information */ 435 offset = 0; 436 bzero(vpd_data, sizeof (vpd_data)); 437 vpd->port_index = (uint32_t)-1; 438 439 while (offset < DMP_VPD_SIZE) { 440 emlxs_mb_dump_vpd(hba, mb, offset); 441 if (emlxs_sli_issue_mbox_cmd(hba, mb, MBX_WAIT, 0) != 442 MBX_SUCCESS) { 443 /* 444 * Let it go through even if failed. 445 * Not all adapter's have VPD info and thus will 446 * fail here. This is not a problem 447 */ 448 449 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg, 450 "No VPD found. offset=%x status=%x", offset, 451 mb->mbxStatus); 452 break; 453 } else { 454 if (mb->un.varDmp.ra == 1) { 455 uint32_t *lp1, *lp2; 456 uint32_t bsize; 457 uint32_t wsize; 458 459 /* 460 * mb->un.varDmp.word_cnt is actually byte 461 * count for the dump reply 462 */ 463 bsize = mb->un.varDmp.word_cnt; 464 465 /* Stop if no data was received */ 466 if (bsize == 0) { 467 break; 468 } 469 470 /* Check limit on byte size */ 471 bsize = (bsize > 472 (sizeof (vpd_data) - offset)) ? 473 (sizeof (vpd_data) - offset) : bsize; 474 475 /* 476 * Convert size from bytes to words with 477 * minimum of 1 word 478 */ 479 wsize = (bsize > 4) ? (bsize >> 2) : 1; 480 481 /* 482 * Transfer data into vpd_data buffer one 483 * word at a time 484 */ 485 lp1 = (uint32_t *)&mb->un.varDmp.resp_offset; 486 lp2 = (uint32_t *)&vpd_data[offset]; 487 488 for (i = 0; i < wsize; i++) { 489 status = *lp1++; 490 *lp2++ = SWAP_LONG(status); 491 } 492 493 /* Increment total byte count saved */ 494 offset += (wsize << 2); 495 496 /* 497 * Stop if less than a full transfer was 498 * received 499 */ 500 if (wsize < DMP_VPD_DUMP_WCOUNT) { 501 break; 502 } 503 504 } else { 505 EMLXS_MSGF(EMLXS_CONTEXT, 506 &emlxs_init_debug_msg, 507 "No VPD acknowledgment. offset=%x", 508 offset); 509 break; 510 } 511 } 512 513 } 514 515 if (vpd_data[0]) { 516 (void) emlxs_parse_vpd(hba, (uint8_t *)vpd_data, offset); 517 518 /* 519 * If there is a VPD part number, and it does not 520 * match the current default HBA model info, 521 * replace the default data with an entry that 522 * does match. 523 * 524 * After emlxs_parse_vpd model holds the VPD value 525 * for V2 and part_num hold the value for PN. These 526 * 2 values are NOT necessarily the same. 527 */ 528 529 rval = 0; 530 if ((vpd->model[0] != 0) && 531 (strcmp(&vpd->model[0], hba->model_info.model) != 0)) { 532 533 /* First scan for a V2 match */ 534 535 for (i = 1; i < EMLXS_PCI_MODEL_COUNT; i++) { 536 if (strcmp(&vpd->model[0], 537 emlxs_pci_model[i].model) == 0) { 538 bcopy(&emlxs_pci_model[i], 539 &hba->model_info, 540 sizeof (emlxs_model_t)); 541 rval = 1; 542 break; 543 } 544 } 545 } 546 547 if (!rval && (vpd->part_num[0] != 0) && 548 (strcmp(&vpd->part_num[0], hba->model_info.model) != 0)) { 549 550 /* Next scan for a PN match */ 551 552 for (i = 1; i < EMLXS_PCI_MODEL_COUNT; i++) { 553 if (strcmp(&vpd->part_num[0], 554 emlxs_pci_model[i].model) == 0) { 555 bcopy(&emlxs_pci_model[i], 556 &hba->model_info, 557 sizeof (emlxs_model_t)); 558 break; 559 } 560 } 561 } 562 563 /* 564 * Now lets update hba->model_info with the real 565 * VPD data, if any. 566 */ 567 568 /* 569 * Replace the default model description with vpd data 570 */ 571 if (vpd->model_desc[0] != 0) { 572 (void) strcpy(hba->model_info.model_desc, 573 vpd->model_desc); 574 } 575 576 /* Replace the default model with vpd data */ 577 if (vpd->model[0] != 0) { 578 (void) strcpy(hba->model_info.model, vpd->model); 579 } 580 581 /* Replace the default program types with vpd data */ 582 if (vpd->prog_types[0] != 0) { 583 emlxs_parse_prog_types(hba, vpd->prog_types); 584 } 585 } 586 587 /* 588 * Since the adapter model may have changed with the vpd data 589 * lets double check if adapter is not supported 590 */ 591 if (hba->model_info.flags & EMLXS_NOT_SUPPORTED) { 592 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg, 593 "Unsupported adapter found. " 594 "Id:%d Device id:0x%x SSDID:0x%x Model:%s", 595 hba->model_info.id, hba->model_info.device_id, 596 hba->model_info.ssdid, hba->model_info.model); 597 598 emlxs_ffstate_change(hba, FC_ERROR); 599 (void) emlxs_mem_put(hba, MEM_MBOX, (uint8_t *)mb); 600 (void) emlxs_mem_free_buffer(hba); 601 602 return (EIO); 603 } 604 605 /* Read the adapter's wakeup parms */ 606 (void) emlxs_read_wakeup_parms(hba, &hba->wakeup_parms, 1); 607 emlxs_decode_version(hba->wakeup_parms.u0.boot_bios_wd[0], 608 vpd->boot_version); 609 610 /* Get fcode version property */ 611 emlxs_get_fcode_version(hba); 612 613 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg, 614 "Firmware: kern=%08x stub=%08x sli1=%08x", vpd->postKernRev, 615 vpd->opFwRev, vpd->sli1FwRev); 616 617 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg, 618 "Firmware: sli2=%08x sli3=%08x sli4=%08x fl=%x", vpd->sli2FwRev, 619 vpd->sli3FwRev, vpd->sli4FwRev, vpd->feaLevelHigh); 620 621 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg, 622 "BIOS: boot=%s fcode=%s", vpd->boot_version, vpd->fcode_version); 623 624 /* 625 * If firmware checking is enabled and the adapter model indicates 626 * a firmware image, then perform firmware version check 627 */ 628 if (((fw_check == 1) && (hba->model_info.flags & EMLXS_SUN_BRANDED) && 629 hba->model_info.fwid) || ((fw_check == 2) && 630 hba->model_info.fwid)) { 631 emlxs_firmware_t *fw; 632 633 /* Find firmware image indicated by adapter model */ 634 fw = NULL; 635 for (i = 0; i < EMLXS_FW_COUNT; i++) { 636 if (emlxs_fw_table[i].id == hba->model_info.fwid) { 637 fw = &emlxs_fw_table[i]; 638 break; 639 } 640 } 641 642 /* 643 * If the image was found, then verify current firmware 644 * versions of adapter 645 */ 646 if (fw) { 647 if ((vpd->postKernRev != fw->kern) || 648 (vpd->opFwRev != fw->stub) || 649 (vpd->sli1FwRev != fw->sli1) || 650 (vpd->sli2FwRev != fw->sli2) || 651 (fw->sli3 && (vpd->sli3FwRev != fw->sli3)) || 652 (fw->sli4 && (vpd->sli4FwRev != fw->sli4))) { 653 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_msg, 654 "Firmware update needed. " 655 "Updating. id=%d fw=%d", 656 hba->model_info.id, hba->model_info.fwid); 657 658 #ifdef MODFW_SUPPORT 659 /* 660 * Load the firmware image now 661 * If MODFW_SUPPORT is not defined, the 662 * firmware image will already be defined 663 * in the emlxs_fw_table 664 */ 665 emlxs_fw_load(hba, fw); 666 #endif /* MODFW_SUPPORT */ 667 668 if (fw->image && fw->size) { 669 if (emlxs_fw_download(hba, 670 (char *)fw->image, fw->size, 0)) { 671 EMLXS_MSGF(EMLXS_CONTEXT, 672 &emlxs_init_msg, 673 "Firmware update failed."); 674 } 675 #ifdef MODFW_SUPPORT 676 /* 677 * Unload the firmware image from 678 * kernel memory 679 */ 680 emlxs_fw_unload(hba, fw); 681 #endif /* MODFW_SUPPORT */ 682 683 (void) emlxs_mem_put(hba, MEM_MBOX, 684 (uint8_t *)mb); 685 (void) emlxs_mem_free_buffer(hba); 686 687 fw_check = 0; 688 689 goto reset; 690 } 691 692 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_msg, 693 "Firmware image unavailable."); 694 } 695 } else { 696 /* This should not happen */ 697 698 /* 699 * This means either the adapter database is not 700 * correct or a firmware image is missing from the 701 * compile 702 */ 703 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_msg, 704 "Firmware image unavailable. id=%d fw=%d", 705 hba->model_info.id, hba->model_info.fwid); 706 } 707 } 708 709 /* 710 * Add our interrupt routine to kernel's interrupt chain & enable it 711 * If MSI is enabled this will cause Solaris to program the MSI address 712 * and data registers in PCI config space 713 */ 714 if (EMLXS_INTR_ADD(hba) != DDI_SUCCESS) { 715 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg, 716 "Unable to add interrupt(s)."); 717 718 emlxs_ffstate_change(hba, FC_ERROR); 719 (void) emlxs_mem_put(hba, MEM_MBOX, (uint8_t *)mb); 720 (void) emlxs_mem_free_buffer(hba); 721 722 return (EIO); 723 } 724 725 emlxs_ffstate_change(hba, FC_INIT_CFGPORT); 726 (void) emlxs_mb_config_port(hba, mb, sli_mode, key); 727 if (emlxs_sli_issue_mbox_cmd(hba, mb, MBX_WAIT, 0) != MBX_SUCCESS) { 728 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg, 729 "Unable to configure port. " 730 "Mailbox cmd=%x status=%x slimode=%d key=%x", 731 mb->mbxCommand, mb->mbxStatus, sli_mode, key); 732 733 #ifdef SLI3_SUPPORT 734 for (sli_mode--; sli_mode > 0; sli_mode--) { 735 /* Check if sli_mode is supported by this adapter */ 736 if (hba->model_info.sli_mask & 737 EMLXS_SLI_MASK(sli_mode)) { 738 sli_mode_mask = EMLXS_SLI_MASK(sli_mode); 739 break; 740 } 741 } 742 743 if (sli_mode) { 744 /* Clean up */ 745 (void) emlxs_mem_put(hba, MEM_MBOX, (uint8_t *)mb); 746 (void) emlxs_mem_free_buffer(hba); 747 748 fw_check = 0; 749 750 goto reset; 751 } 752 #endif /* SLI3_SUPPORT */ 753 754 hba->flag &= ~FC_SLIM2_MODE; 755 emlxs_ffstate_change(hba, FC_ERROR); 756 (void) emlxs_mem_put(hba, MEM_MBOX, (uint8_t *)mb); 757 (void) emlxs_mem_free_buffer(hba); 758 759 return (EIO); 760 } 761 #ifdef SLI3_SUPPORT 762 /* Check if SLI3 mode was achieved */ 763 if (mb->un.varCfgPort.rMA && 764 (mb->un.varCfgPort.sli_mode == EMLXS_HBA_SLI3_MODE)) { 765 766 #ifdef NPIV_SUPPORT 767 if (mb->un.varCfgPort.vpi_max > 1) { 768 hba->flag |= FC_NPIV_ENABLED; 769 770 if (hba->model_info.chip >= EMLXS_SATURN_CHIP) { 771 hba->vpi_max = 772 min(mb->un.varCfgPort.vpi_max, 773 MAX_VPORTS - 1); 774 } else { 775 hba->vpi_max = 776 min(mb->un.varCfgPort.vpi_max, 777 MAX_VPORTS_LIMITED - 1); 778 } 779 } 780 781 #if (EMLXS_MODREV >= EMLXS_MODREV5) 782 hba->fca_tran->fca_num_npivports = 783 (cfg[CFG_NPIV_ENABLE].current) ? hba->vpi_max : 0; 784 #endif /* >= EMLXS_MODREV5 */ 785 786 #endif /* NPIV_SUPPORT */ 787 788 if (mb->un.varCfgPort.gerbm && mb->un.varCfgPort.max_hbq) { 789 hba->flag |= FC_HBQ_ENABLED; 790 } 791 792 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg, 793 "SLI3 mode: flag=%x vpi_max=%d", hba->flag, hba->vpi_max); 794 } else { 795 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg, 796 "SLI2 mode: flag=%x", hba->flag); 797 sli_mode = EMLXS_HBA_SLI2_MODE; 798 sli_mode_mask = EMLXS_SLI2_MASK; 799 hba->sli_mode = sli_mode; 800 } 801 #endif /* SLI3_SUPPORT */ 802 803 /* Get and save the current firmware version (based on sli_mode) */ 804 emlxs_decode_firmware_rev(hba, vpd); 805 806 emlxs_pcix_mxr_update(hba, 0); 807 808 /* 809 * Setup and issue mailbox RUN BIU DIAG command Setup test buffers 810 */ 811 mp = 0; 812 mp1 = 0; 813 if (((mp = (MATCHMAP *)emlxs_mem_get(hba, MEM_BUF | MEM_PRI)) == 0) || 814 ((mp1 = (MATCHMAP *)emlxs_mem_get(hba, MEM_BUF | MEM_PRI)) == 0)) { 815 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg, 816 "Unable to allocate diag buffers."); 817 818 emlxs_ffstate_change(hba, FC_ERROR); 819 820 if (mp) { 821 (void) emlxs_mem_put(hba, MEM_BUF, (uint8_t *)mp); 822 } 823 if (mp1) { 824 (void) emlxs_mem_put(hba, MEM_BUF, (uint8_t *)mp1); 825 } 826 827 (void) emlxs_mem_put(hba, MEM_MBOX, (uint8_t *)mb); 828 (void) emlxs_mem_free_buffer(hba); 829 830 return (ENOMEM); 831 } 832 833 bcopy((caddr_t)&emlxs_diag_pattern[0], (caddr_t)mp->virt, 834 MEM_ELSBUF_SIZE); 835 emlxs_mpdata_sync(mp->dma_handle, 0, MEM_ELSBUF_SIZE, 836 DDI_DMA_SYNC_FORDEV); 837 838 bzero(mp1->virt, MEM_ELSBUF_SIZE); 839 emlxs_mpdata_sync(mp1->dma_handle, 0, MEM_ELSBUF_SIZE, 840 DDI_DMA_SYNC_FORDEV); 841 842 (void) emlxs_mb_run_biu_diag(hba, mb, mp->phys, mp1->phys); 843 844 if (emlxs_sli_issue_mbox_cmd(hba, mb, MBX_WAIT, 0) != MBX_SUCCESS) { 845 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg, 846 "Unable to run BIU diag. Mailbox cmd=%x status=%x", 847 mb->mbxCommand, mb->mbxStatus); 848 849 emlxs_ffstate_change(hba, FC_ERROR); 850 851 (void) emlxs_mem_put(hba, MEM_BUF, (uint8_t *)mp); 852 (void) emlxs_mem_put(hba, MEM_BUF, (uint8_t *)mp1); 853 (void) emlxs_mem_put(hba, MEM_MBOX, (uint8_t *)mb); 854 (void) emlxs_mem_free_buffer(hba); 855 856 return (EIO); 857 } 858 859 emlxs_mpdata_sync(mp1->dma_handle, 0, MEM_ELSBUF_SIZE, 860 DDI_DMA_SYNC_FORKERNEL); 861 862 outptr = mp->virt; 863 inptr = mp1->virt; 864 865 for (i = 0; i < MEM_ELSBUF_SIZE; i++) { 866 if (*outptr++ != *inptr++) { 867 outptr--; 868 inptr--; 869 870 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg, 871 "BIU diagnostic failed. " 872 "offset %x value %x should be %x.", 873 i, (uint32_t)*inptr, (uint32_t)*outptr); 874 875 emlxs_ffstate_change(hba, FC_ERROR); 876 877 (void) emlxs_mem_put(hba, MEM_BUF, (uint8_t *)mp); 878 (void) emlxs_mem_put(hba, MEM_BUF, (uint8_t *)mp1); 879 (void) emlxs_mem_put(hba, MEM_MBOX, (uint8_t *)mb); 880 (void) emlxs_mem_free_buffer(hba); 881 882 return (EIO); 883 } 884 } 885 886 (void) emlxs_mem_put(hba, MEM_BUF, (uint8_t *)mp); 887 (void) emlxs_mem_put(hba, MEM_BUF, (uint8_t *)mp1); 888 889 /* 890 * Setup and issue mailbox CONFIGURE RING command 891 */ 892 for (i = 0; i < (uint32_t)hba->ring_count; i++) { 893 /* 894 * Initialize cmd/rsp ring pointers 895 */ 896 rp = &hba->ring[i]; 897 898 rp->hba = hba; 899 rp->ringno = (uint8_t)i; 900 901 rp->fc_iocbhd = 0; 902 rp->fc_iocbtl = 0; 903 rp->fc_cmdidx = 0; 904 rp->fc_rspidx = 0; 905 rp->fc_iotag = 1; /* Used for pkt io */ 906 rp->fc_abort_iotag = rp->max_iotag; /* Used for abort or */ 907 /* close XRI iotags */ 908 emlxs_ffstate_change(hba, FC_INIT_CFGRING); 909 emlxs_mb_config_ring(hba, i, mb); 910 if (emlxs_sli_issue_mbox_cmd(hba, mb, MBX_WAIT, 0) != 911 MBX_SUCCESS) { 912 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg, 913 "Unable to configure ring. " 914 "Mailbox cmd=%x status=%x", 915 mb->mbxCommand, mb->mbxStatus); 916 917 emlxs_ffstate_change(hba, FC_ERROR); 918 (void) emlxs_mem_put(hba, MEM_MBOX, (uint8_t *)mb); 919 (void) emlxs_mem_free_buffer(hba); 920 921 return (EIO); 922 } 923 } 924 925 /* 926 * Setup link timers 927 */ 928 emlxs_ffstate_change(hba, FC_INIT_INITLINK); 929 emlxs_mb_config_link(hba, mb); 930 if (emlxs_sli_issue_mbox_cmd(hba, mb, MBX_WAIT, 0) != MBX_SUCCESS) { 931 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg, 932 "Unable to configure link. Mailbox cmd=%x status=%x", 933 mb->mbxCommand, mb->mbxStatus); 934 935 emlxs_ffstate_change(hba, FC_ERROR); 936 (void) emlxs_mem_put(hba, MEM_MBOX, (uint8_t *)mb); 937 emlxs_ffcleanup(hba); 938 (void) emlxs_mem_free_buffer(hba); 939 940 return (EIO); 941 } 942 #ifdef MAX_RRDY_PATCH 943 /* Set MAX_RRDY if one is provided */ 944 if (cfg[CFG_MAX_RRDY].current) { 945 emlxs_mb_set_var(hba, (MAILBOX *)mb, 0x00060412, 946 cfg[CFG_MAX_RRDY].current); 947 948 if (emlxs_sli_issue_mbox_cmd(hba, mb, MBX_WAIT, 0) != 949 MBX_SUCCESS) { 950 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg, 951 "MAX_RRDY: Unable to set. status=%x value=%d", 952 mb->mbxStatus, cfg[CFG_MAX_RRDY].current); 953 } else { 954 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg, 955 "MAX_RRDY: %d", cfg[CFG_MAX_RRDY].current); 956 } 957 } 958 #endif /* MAX_RRDY_PATCH */ 959 960 /* 961 * We need to get login parameters for NID 962 */ 963 (void) emlxs_mb_read_sparam(hba, mb); 964 mp = (MATCHMAP *)(((MAILBOXQ *)mb)->bp); 965 if (emlxs_sli_issue_mbox_cmd(hba, mb, MBX_WAIT, 0) != MBX_SUCCESS) { 966 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg, 967 "Unable to read parameters. Mailbox cmd=%x status=%x", 968 mb->mbxCommand, mb->mbxStatus); 969 970 emlxs_ffstate_change(hba, FC_ERROR); 971 (void) emlxs_mem_put(hba, MEM_BUF, (uint8_t *)mp); 972 (void) emlxs_mem_put(hba, MEM_MBOX, (uint8_t *)mb); 973 emlxs_ffcleanup(hba); 974 (void) emlxs_mem_free_buffer(hba); 975 976 return (EIO); 977 } 978 979 /* Free the buffer since we were polling */ 980 (void) emlxs_mem_put(hba, MEM_BUF, (uint8_t *)mp); 981 982 /* If no serial number in VPD data, then use the WWPN */ 983 if (vpd->serial_num[0] == 0) { 984 outptr = (uint8_t *)&hba->wwpn.IEEE[0]; 985 for (i = 0; i < 12; i++) { 986 status = *outptr++; 987 j = ((status & 0xf0) >> 4); 988 if (j <= 9) { 989 vpd->serial_num[i] = 990 (char)((uint8_t)'0' + (uint8_t)j); 991 } else { 992 vpd->serial_num[i] = 993 (char)((uint8_t)'A' + (uint8_t)(j - 10)); 994 } 995 996 i++; 997 j = (status & 0xf); 998 if (j <= 9) { 999 vpd->serial_num[i] = 1000 (char)((uint8_t)'0' + (uint8_t)j); 1001 } else { 1002 vpd->serial_num[i] = 1003 (char)((uint8_t)'A' + (uint8_t)(j - 10)); 1004 } 1005 } 1006 1007 /* 1008 * Set port number and port index to zero 1009 * The WWN's are unique to each port and therefore port_num 1010 * must equal zero. This effects the hba_fru_details structure 1011 * in fca_bind_port() 1012 */ 1013 vpd->port_num[0] = 0; 1014 vpd->port_index = 0; 1015 } 1016 1017 /* 1018 * Make first attempt to set a port index 1019 * Check if this is a multifunction adapter 1020 */ 1021 if ((vpd->port_index == -1) && 1022 (hba->model_info.chip >= EMLXS_THOR_CHIP)) { 1023 char *buffer; 1024 int32_t i; 1025 1026 /* 1027 * The port address looks like this: 1028 * 1 - for port index 0 1029 * 1,1 - for port index 1 1030 * 1,2 - for port index 2 1031 */ 1032 buffer = ddi_get_name_addr(hba->dip); 1033 1034 if (buffer) { 1035 vpd->port_index = 0; 1036 1037 /* Reverse scan for a comma */ 1038 for (i = strlen(buffer) - 1; i > 0; i--) { 1039 if (buffer[i] == ',') { 1040 /* Comma found - set index now */ 1041 vpd->port_index = 1042 emlxs_strtol(&buffer[i + 1], 10); 1043 break; 1044 } 1045 } 1046 } 1047 } 1048 1049 /* Make final attempt to set a port index */ 1050 if (vpd->port_index == -1) { 1051 dev_info_t *p_dip; 1052 dev_info_t *c_dip; 1053 1054 p_dip = ddi_get_parent(hba->dip); 1055 c_dip = ddi_get_child(p_dip); 1056 1057 vpd->port_index = 0; 1058 while (c_dip && (hba->dip != c_dip)) { 1059 c_dip = ddi_get_next_sibling(c_dip); 1060 vpd->port_index++; 1061 } 1062 } 1063 1064 if (vpd->port_num[0] == 0) { 1065 if (hba->model_info.channels > 1) { 1066 (void) sprintf(vpd->port_num, "%d", vpd->port_index); 1067 } 1068 } 1069 1070 if (vpd->id[0] == 0) { 1071 (void) strcpy(vpd->id, hba->model_info.model_desc); 1072 } 1073 1074 if (vpd->manufacturer[0] == 0) { 1075 (void) strcpy(vpd->manufacturer, hba->model_info.manufacturer); 1076 } 1077 1078 if (vpd->part_num[0] == 0) { 1079 (void) strcpy(vpd->part_num, hba->model_info.model); 1080 } 1081 1082 if (vpd->model_desc[0] == 0) { 1083 (void) strcpy(vpd->model_desc, hba->model_info.model_desc); 1084 } 1085 1086 if (vpd->model[0] == 0) { 1087 (void) strcpy(vpd->model, hba->model_info.model); 1088 } 1089 1090 if (vpd->prog_types[0] == 0) { 1091 emlxs_build_prog_types(hba, vpd->prog_types); 1092 } 1093 1094 /* Create the symbolic names */ 1095 (void) sprintf(hba->snn, "Emulex %s FV%s DV%s %s", 1096 hba->model_info.model, hba->vpd.fw_version, emlxs_version, 1097 (char *)utsname.nodename); 1098 1099 (void) sprintf(hba->spn, 1100 "Emulex PPN-%01x%01x:%02x:%02x:%02x:%02x:%02x:%02x:%02x", 1101 hba->wwpn.nameType, hba->wwpn.IEEEextMsn, hba->wwpn.IEEEextLsb, 1102 hba->wwpn.IEEE[0], hba->wwpn.IEEE[1], hba->wwpn.IEEE[2], 1103 hba->wwpn.IEEE[3], hba->wwpn.IEEE[4], hba->wwpn.IEEE[5]); 1104 1105 if (cfg[CFG_NETWORK_ON].current) { 1106 if ((hba->sparam.portName.nameType != NAME_IEEE) || 1107 (hba->sparam.portName.IEEEextMsn != 0) || 1108 (hba->sparam.portName.IEEEextLsb != 0)) { 1109 1110 cfg[CFG_NETWORK_ON].current = 0; 1111 1112 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_msg, 1113 "WWPN doesn't conform to IP profile: nameType=%x", 1114 hba->sparam.portName.nameType); 1115 } 1116 1117 /* Issue CONFIG FARP */ 1118 emlxs_mb_config_farp(hba, mb); 1119 if (emlxs_sli_issue_mbox_cmd(hba, mb, MBX_WAIT, 0) != 1120 MBX_SUCCESS) { 1121 /* 1122 * Let it go through even if failed. 1123 */ 1124 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_msg, 1125 "Unable to configure FARP. " 1126 "Mailbox cmd=%x status=%x", 1127 mb->mbxCommand, mb->mbxStatus); 1128 } 1129 } 1130 #ifdef MSI_SUPPORT 1131 /* Configure MSI map if required */ 1132 if (hba->intr_count > 1) { 1133 emlxs_mb_config_msix(hba, mb, hba->intr_map, hba->intr_count); 1134 1135 if (emlxs_sli_issue_mbox_cmd(hba, mb, MBX_WAIT, 0) == 1136 MBX_SUCCESS) { 1137 goto msi_configured; 1138 } 1139 1140 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg, 1141 "Unable to config MSIX. Mailbox cmd=0x%x status=0x%x", 1142 mb->mbxCommand, mb->mbxStatus); 1143 1144 emlxs_mb_config_msi(hba, mb, hba->intr_map, hba->intr_count); 1145 1146 if (emlxs_sli_issue_mbox_cmd(hba, mb, MBX_WAIT, 0) == 1147 MBX_SUCCESS) { 1148 goto msi_configured; 1149 } 1150 1151 1152 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg, 1153 "Unable to config MSI. Mailbox cmd=0x%x status=0x%x", 1154 mb->mbxCommand, mb->mbxStatus); 1155 1156 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg, 1157 "Attempting single interrupt mode..."); 1158 1159 /* First cleanup old interrupts */ 1160 (void) emlxs_msi_remove(hba); 1161 (void) emlxs_msi_uninit(hba); 1162 1163 status = emlxs_msi_init(hba, 1); 1164 1165 if (status != DDI_SUCCESS) { 1166 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg, 1167 "Unable to initialize interrupt. status=%d", 1168 status); 1169 1170 emlxs_ffstate_change(hba, FC_ERROR); 1171 (void) emlxs_mem_put(hba, MEM_MBOX, (uint8_t *)mb); 1172 emlxs_ffcleanup(hba); 1173 (void) emlxs_mem_free_buffer(hba); 1174 1175 return (EIO); 1176 } 1177 1178 /* 1179 * Reset adapter - The adapter needs to be reset because 1180 * the bus cannot handle the MSI change without handshaking 1181 * with the adapter again 1182 */ 1183 1184 (void) emlxs_mem_put(hba, MEM_MBOX, (uint8_t *)mb); 1185 (void) emlxs_mem_free_buffer(hba); 1186 fw_check = 0; 1187 goto reset; 1188 } 1189 1190 msi_configured: 1191 1192 #endif /* MSI_SUPPORT */ 1193 1194 /* 1195 * We always disable the firmware traffic cop feature 1196 */ 1197 if (emlxs_disable_traffic_cop) { 1198 emlxs_disable_tc(hba, (MAILBOX *)mb); 1199 if (emlxs_sli_issue_mbox_cmd(hba, mb, MBX_WAIT, 0) != 1200 MBX_SUCCESS) { 1201 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg, 1202 "Unable to disable traffic cop. " 1203 "Mailbox cmd=%x status=%x", 1204 mb->mbxCommand, mb->mbxStatus); 1205 1206 (void) EMLXS_INTR_REMOVE(hba); 1207 emlxs_ffstate_change(hba, FC_ERROR); 1208 (void) emlxs_mem_put(hba, MEM_MBOX, (uint8_t *)mb); 1209 emlxs_ffcleanup(hba); 1210 (void) emlxs_mem_free_buffer(hba); 1211 1212 return (EIO); 1213 } 1214 } 1215 1216 emlxs_mb_read_config(hba, (MAILBOX *)mb); 1217 if (emlxs_sli_issue_mbox_cmd(hba, mb, MBX_WAIT, 0) != MBX_SUCCESS) { 1218 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg, 1219 "Unable to read configuration. Mailbox cmd=%x status=%x", 1220 mb->mbxCommand, mb->mbxStatus); 1221 1222 (void) EMLXS_INTR_REMOVE(hba); 1223 emlxs_ffstate_change(hba, FC_ERROR); 1224 (void) emlxs_mem_put(hba, MEM_MBOX, (uint8_t *)mb); 1225 emlxs_ffcleanup(hba); 1226 (void) emlxs_mem_free_buffer(hba); 1227 1228 return (EIO); 1229 } 1230 1231 /* Save the link speed capabilities */ 1232 vpd->link_speed = mb->un.varRdConfig.lmt; 1233 emlxs_process_link_speed(hba); 1234 1235 /* Set the io throttle */ 1236 hba->io_throttle = mb->un.varRdConfig.max_xri - IO_THROTTLE_RESERVE; 1237 1238 /* Set the max node count */ 1239 if (cfg[CFG_NUM_NODES].current > 0) { 1240 hba->max_nodes = 1241 min(cfg[CFG_NUM_NODES].current, 1242 mb->un.varRdConfig.max_rpi); 1243 } else { 1244 hba->max_nodes = mb->un.varRdConfig.max_rpi; 1245 } 1246 1247 /* Register for async events */ 1248 emlxs_mb_async_event(hba, mb); 1249 if (emlxs_sli_issue_mbox_cmd(hba, mb, MBX_WAIT, 0) != MBX_SUCCESS) { 1250 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg, 1251 "Async events disabled. Mailbox status=%x", 1252 mb->mbxStatus); 1253 } else { 1254 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg, 1255 "Async events enabled."); 1256 hba->flag |= FC_ASYNC_EVENTS; 1257 } 1258 1259 emlxs_ffstate_change(hba, FC_LINK_DOWN); 1260 1261 emlxs_intr_initialize(hba); 1262 1263 #ifdef SLI3_SUPPORT 1264 1265 if (hba->flag & FC_HBQ_ENABLED) { 1266 if (hba->tgt_mode) { 1267 if (emlxs_hbq_setup(hba, EMLXS_FCT_HBQ_ID)) { 1268 return (ENOMEM); 1269 } 1270 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg, 1271 "FCT Ring: Posted %d buffers.", MEM_FCTBUF_COUNT); 1272 } 1273 1274 if (cfg[CFG_NETWORK_ON].current) { 1275 if (emlxs_hbq_setup(hba, EMLXS_IP_HBQ_ID)) { 1276 return (ENOMEM); 1277 } 1278 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg, 1279 "IP Ring: Posted %d buffers.", MEM_IPBUF_COUNT); 1280 } 1281 1282 if (emlxs_hbq_setup(hba, EMLXS_ELS_HBQ_ID)) { 1283 return (ENOMEM); 1284 } 1285 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg, 1286 "ELS Ring: Posted %d buffers.", MEM_ELSBUF_COUNT); 1287 1288 if (emlxs_hbq_setup(hba, EMLXS_CT_HBQ_ID)) { 1289 return (ENOMEM); 1290 } 1291 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg, 1292 "CT Ring: Posted %d buffers.", MEM_CTBUF_COUNT); 1293 } else 1294 #endif /* SLI3_SUPPORT */ 1295 { 1296 if (hba->tgt_mode) { 1297 /* Post the FCT unsol buffers */ 1298 rp = &hba->ring[FC_FCT_RING]; 1299 for (j = 0; j < MEM_FCTBUF_COUNT; j += 2) { 1300 (void) emlxs_post_buffer(hba, rp, 2); 1301 } 1302 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg, 1303 "FCP Ring: Posted %d buffers.", MEM_FCTBUF_COUNT); 1304 } 1305 1306 if (cfg[CFG_NETWORK_ON].current) { 1307 /* Post the IP unsol buffers */ 1308 rp = &hba->ring[FC_IP_RING]; 1309 for (j = 0; j < MEM_IPBUF_COUNT; j += 2) { 1310 (void) emlxs_post_buffer(hba, rp, 2); 1311 } 1312 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg, 1313 "IP Ring: Posted %d buffers.", MEM_IPBUF_COUNT); 1314 } 1315 1316 /* Post the ELS unsol buffers */ 1317 rp = &hba->ring[FC_ELS_RING]; 1318 for (j = 0; j < MEM_ELSBUF_COUNT; j += 2) { 1319 (void) emlxs_post_buffer(hba, rp, 2); 1320 } 1321 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg, 1322 "ELS Ring: Posted %d buffers.", MEM_ELSBUF_COUNT); 1323 1324 1325 /* Post the CT unsol buffers */ 1326 rp = &hba->ring[FC_CT_RING]; 1327 for (j = 0; j < MEM_CTBUF_COUNT; j += 2) { 1328 (void) emlxs_post_buffer(hba, rp, 2); 1329 } 1330 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg, 1331 "CT Ring: Posted %d buffers.", MEM_CTBUF_COUNT); 1332 } 1333 1334 1335 /* 1336 * Setup and issue mailbox INITIALIZE LINK command At this point, 1337 * the interrupt will be generated by the HW 1338 */ 1339 emlxs_mb_init_link(hba, 1340 mb, cfg[CFG_TOPOLOGY].current, cfg[CFG_LINK_SPEED].current); 1341 1342 rval = emlxs_sli_issue_mbox_cmd(hba, mb, MBX_NOWAIT, 0); 1343 1344 if (rval != MBX_SUCCESS && rval != MBX_BUSY) { 1345 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg, 1346 "Unable to initialize link. Mailbox cmd=%x status=%x", 1347 mb->mbxCommand, mb->mbxStatus); 1348 1349 (void) EMLXS_INTR_REMOVE(hba); 1350 emlxs_ffstate_change(hba, FC_ERROR); 1351 (void) emlxs_mem_put(hba, MEM_MBOX, (uint8_t *)mb); 1352 emlxs_ffcleanup(hba); 1353 (void) emlxs_mem_free_buffer(hba); 1354 1355 return (EIO); 1356 } 1357 1358 (void) emlxs_mem_put(hba, MEM_MBOX, (uint8_t *)mb); 1359 1360 /* 1361 * Enable link attention interrupt 1362 */ 1363 emlxs_enable_latt(hba); 1364 1365 /* Wait for link to come up */ 1366 i = cfg[CFG_LINKUP_DELAY].current; 1367 while (i && (hba->state < FC_LINK_UP)) { 1368 /* Check for hardware error */ 1369 if (hba->state == FC_ERROR) { 1370 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg, 1371 "Adapter error.", mb->mbxCommand, mb->mbxStatus); 1372 1373 (void) EMLXS_INTR_REMOVE(hba); 1374 emlxs_ffcleanup(hba); 1375 (void) emlxs_mem_free_buffer(hba); 1376 1377 return (EIO); 1378 } 1379 1380 DELAYMS(1000); 1381 i--; 1382 } 1383 1384 out: 1385 1386 /* 1387 * The leadvile driver will now handle the FLOGI at the driver level 1388 */ 1389 1390 return (0); 1391 } /* emlxs_ffinit() */ 1392 1393 1394 #ifdef MSI_SUPPORT 1395 1396 /* EMLXS_INTR_INIT */ 1397 int32_t 1398 emlxs_msi_init(emlxs_hba_t *hba, uint32_t max) 1399 { 1400 emlxs_port_t *port = &PPORT; 1401 int32_t pass = 0; 1402 int32_t type = 0; 1403 char s_type[16]; 1404 int32_t types; 1405 int32_t count; 1406 int32_t nintrs; 1407 int32_t mode; 1408 int32_t actual; 1409 int32_t new_actual; 1410 int32_t i; 1411 int32_t ret; 1412 ddi_intr_handle_t *htable = NULL; 1413 ddi_intr_handle_t *new_htable = NULL; 1414 uint32_t *intr_pri = NULL; 1415 int32_t *intr_cap = NULL; 1416 int32_t hilevel_pri; 1417 emlxs_config_t *cfg = &CFG; 1418 char buf[64]; 1419 1420 if (!(hba->intr_flags & EMLXS_MSI_ENABLED)) { 1421 return (emlxs_intx_init(hba, max)); 1422 } 1423 1424 if (hba->intr_flags & EMLXS_MSI_INITED) { 1425 return (DDI_SUCCESS); 1426 } 1427 1428 /* Set max interrupt count if not specified */ 1429 if (max == 0) { 1430 if ((cfg[CFG_MSI_MODE].current == 2) || 1431 (cfg[CFG_MSI_MODE].current == 3)) { 1432 max = EMLXS_MSI_MAX_INTRS; 1433 } else { 1434 max = 1; 1435 } 1436 } 1437 1438 /* Filter max interrupt count with adapter model specification */ 1439 if (hba->model_info.intr_limit && (max > hba->model_info.intr_limit)) { 1440 max = hba->model_info.intr_limit; 1441 } 1442 1443 /* Get the available interrupt types from the kernel */ 1444 types = 0; 1445 ret = ddi_intr_get_supported_types(hba->dip, &types); 1446 1447 if ((ret != DDI_SUCCESS)) { 1448 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg, 1449 "MSI: ddi_intr_get_supported_types failed. ret=%d", ret); 1450 1451 /* Default to fixed type */ 1452 types = DDI_INTR_TYPE_FIXED; 1453 } 1454 1455 /* Check if fixed interrupts are being forced */ 1456 if (cfg[CFG_MSI_MODE].current == 0) { 1457 types &= DDI_INTR_TYPE_FIXED; 1458 } 1459 1460 /* Check if MSI interrupts are being forced */ 1461 else if ((cfg[CFG_MSI_MODE].current == 1) || 1462 (cfg[CFG_MSI_MODE].current == 2)) { 1463 types &= (DDI_INTR_TYPE_MSI | DDI_INTR_TYPE_FIXED); 1464 } 1465 1466 begin: 1467 1468 /* Set interrupt type and interrupt count */ 1469 type = 0; 1470 1471 /* Check if MSIX is fully supported */ 1472 if ((types & DDI_INTR_TYPE_MSIX) && 1473 (hba->model_info.flags & EMLXS_MSIX_SUPPORTED)) { 1474 /* Get the max interrupt count from the adapter */ 1475 nintrs = 0; 1476 ret = 1477 ddi_intr_get_nintrs(hba->dip, DDI_INTR_TYPE_MSIX, 1478 &nintrs); 1479 1480 if (ret == DDI_SUCCESS && nintrs) { 1481 type = DDI_INTR_TYPE_MSIX; 1482 (void) strcpy(s_type, "TYPE_MSIX"); 1483 goto initialize; 1484 } 1485 } 1486 1487 /* Check if MSI is fully supported */ 1488 if ((types & DDI_INTR_TYPE_MSI) && 1489 (hba->model_info.flags & EMLXS_MSI_SUPPORTED)) { 1490 /* Get the max interrupt count from the adapter */ 1491 nintrs = 0; 1492 ret = 1493 ddi_intr_get_nintrs(hba->dip, DDI_INTR_TYPE_MSI, &nintrs); 1494 1495 if (ret == DDI_SUCCESS && nintrs) { 1496 type = DDI_INTR_TYPE_MSI; 1497 (void) strcpy(s_type, "TYPE_MSI"); 1498 goto initialize; 1499 } 1500 } 1501 1502 /* Check if fixed interrupts are fully supported */ 1503 if ((types & DDI_INTR_TYPE_FIXED) && 1504 (hba->model_info.flags & EMLXS_INTX_SUPPORTED)) { 1505 /* Get the max interrupt count from the adapter */ 1506 nintrs = 0; 1507 ret = 1508 ddi_intr_get_nintrs(hba->dip, DDI_INTR_TYPE_FIXED, 1509 &nintrs); 1510 1511 if (ret == DDI_SUCCESS) { 1512 type = DDI_INTR_TYPE_FIXED; 1513 (void) strcpy(s_type, "TYPE_FIXED"); 1514 goto initialize; 1515 } 1516 } 1517 1518 goto init_failed; 1519 1520 1521 initialize: 1522 1523 pass++; 1524 mode = 0; 1525 actual = 0; 1526 htable = NULL; 1527 intr_pri = NULL; 1528 intr_cap = NULL; 1529 hilevel_pri = 0; 1530 1531 if (pass == 1) { 1532 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg, 1533 "MSI: %s: mode=%d types=0x%x nintrs=%d", s_type, 1534 cfg[CFG_MSI_MODE].current, types, nintrs); 1535 } 1536 1537 /* Validate interrupt count */ 1538 count = min(nintrs, max); 1539 1540 if (count >= 8) { 1541 count = 8; 1542 } else if (count >= 4) { 1543 count = 4; 1544 } else if (count >= 2) { 1545 count = 2; 1546 } else { 1547 count = 1; 1548 } 1549 1550 /* Allocate an array of interrupt handles */ 1551 htable = 1552 kmem_alloc((size_t)(count * sizeof (ddi_intr_handle_t)), 1553 KM_SLEEP); 1554 1555 if (htable == NULL) { 1556 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg, 1557 "MSI: Unable to allocate interrupt handle table"); 1558 1559 goto init_failed; 1560 } 1561 1562 /* Allocate 'count' interrupts */ 1563 ret = 1564 ddi_intr_alloc(hba->dip, htable, type, EMLXS_MSI_INUMBER, count, 1565 &actual, DDI_INTR_ALLOC_NORMAL); 1566 1567 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg, 1568 "MSI: %s: count=%d actual=%d", s_type, count, actual); 1569 1570 if ((ret != DDI_SUCCESS) || (actual == 0)) { 1571 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg, 1572 "MSI: Unable to allocate interrupts. error=%d", ret); 1573 1574 goto init_failed; 1575 } 1576 1577 if (actual != count) { 1578 /* Validate actual count */ 1579 if (actual >= 8) { 1580 new_actual = 8; 1581 } else if (actual >= 4) { 1582 new_actual = 4; 1583 } else if (actual >= 2) { 1584 new_actual = 2; 1585 } else { 1586 new_actual = 1; 1587 } 1588 1589 if (new_actual < actual) { 1590 /* Free extra handles */ 1591 for (i = new_actual; i < actual; i++) { 1592 (void) ddi_intr_free(htable[i]); 1593 } 1594 1595 actual = new_actual; 1596 } 1597 1598 /* Allocate a new array of interrupt handles */ 1599 new_htable = 1600 kmem_alloc((size_t)(actual * sizeof (ddi_intr_handle_t)), 1601 KM_SLEEP); 1602 1603 if (new_htable == NULL) { 1604 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg, 1605 "MSI: Unable to allocate new " 1606 "interrupt handle table"); 1607 1608 goto init_failed; 1609 } 1610 1611 /* Copy old array to new array */ 1612 bcopy((uint8_t *)htable, (uint8_t *)new_htable, 1613 (actual * sizeof (ddi_intr_handle_t))); 1614 1615 /* Free the old array */ 1616 kmem_free(htable, (count * sizeof (ddi_intr_handle_t))); 1617 1618 htable = new_htable; 1619 count = actual; 1620 } 1621 1622 /* Allocate interrupt priority table */ 1623 intr_pri = 1624 (uint32_t *)kmem_alloc((size_t)(count * sizeof (uint32_t)), 1625 KM_SLEEP); 1626 1627 if (intr_pri == NULL) { 1628 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg, 1629 "MSI: Unable to allocate interrupt priority table"); 1630 1631 goto init_failed; 1632 } 1633 1634 /* Allocate interrupt capability table */ 1635 intr_cap = kmem_alloc((size_t)(count * sizeof (uint32_t)), KM_SLEEP); 1636 1637 if (intr_cap == NULL) { 1638 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg, 1639 "MSI: Unable to allocate interrupt capability table"); 1640 1641 goto init_failed; 1642 } 1643 1644 /* Get minimum hilevel priority */ 1645 hilevel_pri = ddi_intr_get_hilevel_pri(); 1646 1647 /* Fill the priority and capability tables */ 1648 for (i = 0; i < count; ++i) { 1649 ret = ddi_intr_get_pri(htable[i], &intr_pri[i]); 1650 1651 if (ret != DDI_SUCCESS) { 1652 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg, 1653 "MSI: ddi_intr_get_pri(%d) failed. " 1654 "handle=%p ret=%d", 1655 i, &htable[i], ret); 1656 1657 /* Clean up the interrupts */ 1658 goto init_failed; 1659 } 1660 1661 if (intr_pri[i] >= hilevel_pri) { 1662 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg, 1663 "MSI: Interrupt(%d) level too high. " 1664 "pri=0x%x hilevel=0x%x", 1665 i, intr_pri[i], hilevel_pri); 1666 1667 /* Clean up the interrupts */ 1668 goto init_failed; 1669 } 1670 1671 ret = ddi_intr_get_cap(htable[i], &intr_cap[i]); 1672 1673 if (ret != DDI_SUCCESS) { 1674 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg, 1675 "MSI: ddi_intr_get_cap(%d) failed. " 1676 "handle=%p ret=%d", 1677 i, &htable[i], ret); 1678 1679 /* Clean up the interrupts */ 1680 goto init_failed; 1681 } 1682 1683 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg, 1684 "MSI: %s: %d: cap=0x%x pri=0x%x hilevel=0x%x", s_type, i, 1685 intr_cap[i], intr_pri[i], hilevel_pri); 1686 1687 } 1688 1689 /* Set mode */ 1690 switch (count) { 1691 case 8: 1692 mode = EMLXS_MSI_MODE8; 1693 break; 1694 1695 case 4: 1696 mode = EMLXS_MSI_MODE4; 1697 break; 1698 1699 case 2: 1700 mode = EMLXS_MSI_MODE2; 1701 break; 1702 1703 default: 1704 mode = EMLXS_MSI_MODE1; 1705 } 1706 1707 /* Save the info */ 1708 hba->intr_htable = htable; 1709 hba->intr_count = count; 1710 hba->intr_pri = intr_pri; 1711 hba->intr_cap = intr_cap; 1712 hba->intr_type = type; 1713 hba->intr_arg = (void *)((unsigned long)intr_pri[0]); 1714 hba->intr_mask = emlxs_msi_mask[mode]; 1715 1716 hba->intr_cond = 0; 1717 for (i = 0; i < EMLXS_MSI_MAX_INTRS; i++) { 1718 hba->intr_map[i] = emlxs_msi_map[mode][i]; 1719 hba->intr_cond |= emlxs_msi_map[mode][i]; 1720 1721 (void) sprintf(buf, "%s%d_msi%d mutex", DRIVER_NAME, 1722 hba->ddiinst, i); 1723 mutex_init(&hba->intr_lock[i], buf, MUTEX_DRIVER, 1724 (void *)hba->intr_arg); 1725 } 1726 1727 /* Set flag to indicate support */ 1728 hba->intr_flags |= EMLXS_MSI_INITED; 1729 1730 /* Create the interrupt threads */ 1731 for (i = 0; i < MAX_RINGS; i++) { 1732 (void) sprintf(buf, "%s%d_ring%d mutex", DRIVER_NAME, 1733 hba->ddiinst, i); 1734 mutex_init(&hba->ring[i].rsp_lock, buf, MUTEX_DRIVER, 1735 (void *)hba->intr_arg); 1736 1737 emlxs_thread_create(hba, &hba->ring[i].intr_thread); 1738 } 1739 1740 return (DDI_SUCCESS); 1741 1742 1743 init_failed: 1744 1745 if (intr_cap) { 1746 kmem_free(intr_cap, (count * sizeof (int32_t))); 1747 } 1748 1749 if (intr_pri) { 1750 kmem_free(intr_pri, (count * sizeof (int32_t))); 1751 } 1752 1753 if (htable) { 1754 /* Process the interrupt handlers */ 1755 for (i = 0; i < actual; i++) { 1756 /* Free the handle[i] */ 1757 (void) ddi_intr_free(htable[i]); 1758 } 1759 1760 kmem_free(htable, (count * sizeof (ddi_intr_handle_t))); 1761 } 1762 1763 /* Initialize */ 1764 hba->intr_htable = NULL; 1765 hba->intr_count = 0; 1766 hba->intr_pri = NULL; 1767 hba->intr_cap = NULL; 1768 hba->intr_type = 0; 1769 hba->intr_arg = NULL; 1770 hba->intr_cond = 0; 1771 bzero(hba->intr_map, sizeof (hba->intr_map)); 1772 bzero(hba->intr_lock, sizeof (hba->intr_lock)); 1773 1774 if (type == DDI_INTR_TYPE_MSIX) { 1775 types &= (DDI_INTR_TYPE_MSI | DDI_INTR_TYPE_FIXED); 1776 goto begin; 1777 } else if (type == DDI_INTR_TYPE_MSI) { 1778 types &= DDI_INTR_TYPE_FIXED; 1779 goto begin; 1780 } 1781 1782 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg, 1783 "MSI: Unable to initialize interrupts"); 1784 1785 return (DDI_FAILURE); 1786 1787 1788 } /* emlxs_msi_init() */ 1789 1790 1791 /* EMLXS_INTR_UNINIT */ 1792 int32_t 1793 emlxs_msi_uninit(emlxs_hba_t *hba) 1794 { 1795 uint32_t count; 1796 int32_t i; 1797 ddi_intr_handle_t *htable; 1798 uint32_t *intr_pri; 1799 int32_t *intr_cap; 1800 int32_t ret; 1801 1802 if (!(hba->intr_flags & EMLXS_MSI_ENABLED)) { 1803 return (emlxs_intx_uninit(hba)); 1804 } 1805 1806 /* 1807 * EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg, 1808 * "MSI: emlxs_msi_uninit called. flags=%x", 1809 * hba->intr_flags); 1810 */ 1811 1812 /* Make sure interrupts have been removed first */ 1813 if ((hba->intr_flags & EMLXS_MSI_ADDED)) { 1814 ret = emlxs_msi_remove(hba); 1815 1816 if (ret != DDI_SUCCESS) { 1817 return (ret); 1818 } 1819 } 1820 1821 /* Check if the interrupts are still initialized */ 1822 if (!(hba->intr_flags & EMLXS_MSI_INITED)) { 1823 return (DDI_SUCCESS); 1824 } 1825 hba->intr_flags &= ~EMLXS_MSI_INITED; 1826 1827 /* Get handle table parameters */ 1828 htable = hba->intr_htable; 1829 count = hba->intr_count; 1830 intr_pri = hba->intr_pri; 1831 intr_cap = hba->intr_cap; 1832 1833 /* Clean up */ 1834 hba->intr_count = 0; 1835 hba->intr_htable = NULL; 1836 hba->intr_pri = NULL; 1837 hba->intr_cap = NULL; 1838 hba->intr_type = 0; 1839 hba->intr_arg = NULL; 1840 hba->intr_cond = 0; 1841 bzero(hba->intr_map, sizeof (hba->intr_map)); 1842 1843 if (intr_cap) { 1844 kmem_free(intr_cap, (count * sizeof (int32_t))); 1845 } 1846 1847 if (intr_pri) { 1848 kmem_free(intr_pri, (count * sizeof (int32_t))); 1849 } 1850 1851 if (htable) { 1852 /* Process the interrupt handlers */ 1853 for (i = 0; i < count; ++i) { 1854 /* Free the handle[i] */ 1855 ret = ddi_intr_free(htable[i]); 1856 } 1857 1858 kmem_free(htable, (count * sizeof (ddi_intr_handle_t))); 1859 } 1860 1861 /* Destroy the intr locks */ 1862 for (i = 0; i < EMLXS_MSI_MAX_INTRS; i++) { 1863 mutex_destroy(&hba->intr_lock[i]); 1864 } 1865 1866 /* Destroy the interrupt threads */ 1867 for (i = 0; i < MAX_RINGS; i++) { 1868 emlxs_thread_destroy(&hba->ring[i].intr_thread); 1869 mutex_destroy(&hba->ring[i].rsp_lock); 1870 } 1871 1872 /* 1873 * EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg, 1874 * "MSI: emlxs_msi_uninit done. flags=%x", 1875 * hba->intr_flags); 1876 */ 1877 1878 return (DDI_SUCCESS); 1879 1880 } /* emlxs_msi_uninit() */ 1881 1882 1883 /* EMLXS_INTR_ADD */ 1884 int32_t 1885 emlxs_msi_add(emlxs_hba_t *hba) 1886 { 1887 emlxs_port_t *port = &PPORT; 1888 int32_t count; 1889 int32_t i; 1890 int32_t ret; 1891 ddi_intr_handle_t *htable = NULL; 1892 int32_t *intr_cap = NULL; 1893 1894 if (!(hba->intr_flags & EMLXS_MSI_ENABLED)) { 1895 return (emlxs_intx_add(hba)); 1896 } 1897 1898 /* Check if interrupts have already been added */ 1899 if (hba->intr_flags & EMLXS_MSI_ADDED) { 1900 return (DDI_SUCCESS); 1901 } 1902 1903 /* Check if interrupts have been initialized */ 1904 if (!(hba->intr_flags & EMLXS_MSI_INITED)) { 1905 ret = emlxs_msi_init(hba, 0); 1906 1907 if (ret != DDI_SUCCESS) { 1908 return (ret); 1909 } 1910 } 1911 1912 /* Get handle table parameters */ 1913 htable = hba->intr_htable; 1914 count = hba->intr_count; 1915 intr_cap = hba->intr_cap; 1916 1917 /* Add the interrupt handlers */ 1918 for (i = 0; i < count; ++i) { 1919 /* add handler for handle[i] */ 1920 ret = 1921 ddi_intr_add_handler(htable[i], emlxs_sli_msi_intr, 1922 (char *)hba, (char *)((unsigned long)i)); 1923 1924 if (ret != DDI_SUCCESS) { 1925 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg, 1926 "MSI: ddi_intr_add_handler(%d) failed. " 1927 "handle=%p ret=%d", 1928 i, &htable[i], ret); 1929 1930 /* Process the remaining interrupt handlers */ 1931 while (i) { 1932 /* Decrement i */ 1933 i--; 1934 1935 /* Remove the handler */ 1936 ret = ddi_intr_remove_handler(htable[i]); 1937 1938 } 1939 1940 return (DDI_FAILURE); 1941 } 1942 } 1943 1944 /* Enable the interrupts */ 1945 if (intr_cap[0] & DDI_INTR_FLAG_BLOCK) { 1946 ret = ddi_intr_block_enable(htable, count); 1947 1948 if (ret != DDI_SUCCESS) { 1949 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg, 1950 "MSI: ddi_intr_block_enable(%d) failed. ret=%d", 1951 count, ret); 1952 1953 for (i = 0; i < count; ++i) { 1954 ret = ddi_intr_enable(htable[i]); 1955 1956 if (ret != DDI_SUCCESS) { 1957 EMLXS_MSGF(EMLXS_CONTEXT, 1958 &emlxs_init_debug_msg, 1959 "MSI: ddi_intr_enable(%d) failed. " 1960 "ret=%d", 1961 i, ret); 1962 } 1963 } 1964 } 1965 } else { 1966 for (i = 0; i < count; ++i) { 1967 ret = ddi_intr_enable(htable[i]); 1968 1969 if (ret != DDI_SUCCESS) { 1970 EMLXS_MSGF(EMLXS_CONTEXT, 1971 &emlxs_init_debug_msg, 1972 "MSI: ddi_intr_enable(%d) failed. ret=%d", 1973 i, ret); 1974 } 1975 } 1976 } 1977 1978 1979 /* Set flag to indicate support */ 1980 hba->intr_flags |= EMLXS_MSI_ADDED; 1981 1982 return (DDI_SUCCESS); 1983 1984 } /* emlxs_msi_add() */ 1985 1986 1987 1988 /* EMLXS_INTR_REMOVE */ 1989 int32_t 1990 emlxs_msi_remove(emlxs_hba_t *hba) 1991 { 1992 emlxs_port_t *port = &PPORT; 1993 uint32_t count; 1994 int32_t i; 1995 ddi_intr_handle_t *htable; 1996 int32_t *intr_cap; 1997 int32_t ret; 1998 1999 if (!(hba->intr_flags & EMLXS_MSI_ENABLED)) { 2000 return (emlxs_intx_remove(hba)); 2001 } 2002 2003 /* 2004 * EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg, 2005 * "MSI: emlxs_msi_remove called. flags=%x", 2006 * hba->intr_flags); 2007 */ 2008 2009 /* Check if interrupts have already been removed */ 2010 if (!(hba->intr_flags & EMLXS_MSI_ADDED)) { 2011 return (DDI_SUCCESS); 2012 } 2013 hba->intr_flags &= ~EMLXS_MSI_ADDED; 2014 2015 /* Disable all adapter interrupts */ 2016 emlxs_disable_intr(hba, 0); 2017 2018 /* Get handle table parameters */ 2019 htable = hba->intr_htable; 2020 count = hba->intr_count; 2021 intr_cap = hba->intr_cap; 2022 2023 /* Disable the interrupts */ 2024 if (intr_cap[0] & DDI_INTR_FLAG_BLOCK) { 2025 ret = ddi_intr_block_disable(htable, count); 2026 2027 if (ret != DDI_SUCCESS) { 2028 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg, 2029 "MSI: ddi_intr_block_disable(%d) failed. ret=%d", 2030 count, ret); 2031 2032 for (i = 0; i < count; i++) { 2033 ret = ddi_intr_disable(htable[i]); 2034 2035 if (ret != DDI_SUCCESS) { 2036 EMLXS_MSGF(EMLXS_CONTEXT, 2037 &emlxs_init_debug_msg, 2038 "MSI: ddi_intr_disable(%d) failed. " 2039 "ret=%d", 2040 i, ret); 2041 } 2042 } 2043 } 2044 } else { 2045 for (i = 0; i < count; i++) { 2046 ret = ddi_intr_disable(htable[i]); 2047 2048 if (ret != DDI_SUCCESS) { 2049 EMLXS_MSGF(EMLXS_CONTEXT, 2050 &emlxs_init_debug_msg, 2051 "MSI: ddi_intr_disable(%d) failed. ret=%d", 2052 i, ret); 2053 } 2054 } 2055 } 2056 2057 /* Process the interrupt handlers */ 2058 for (i = 0; i < count; i++) { 2059 /* Remove the handler */ 2060 ret = ddi_intr_remove_handler(htable[i]); 2061 2062 2063 } 2064 2065 return (DDI_SUCCESS); 2066 2067 } /* emlxs_msi_remove() */ 2068 2069 2070 #endif /* MSI_SUPPORT */ 2071 2072 2073 /* EMLXS_INTR_INIT */ 2074 /* ARGSUSED */ 2075 int32_t 2076 emlxs_intx_init(emlxs_hba_t *hba, uint32_t max) 2077 { 2078 emlxs_port_t *port = &PPORT; 2079 int32_t ret; 2080 uint32_t i; 2081 char buf[64]; 2082 2083 /* Check if interrupts have already been initialized */ 2084 if (hba->intr_flags & EMLXS_INTX_INITED) { 2085 return (DDI_SUCCESS); 2086 } 2087 2088 /* Check if adapter is flagged for INTX support */ 2089 if (!(hba->model_info.flags & EMLXS_INTX_SUPPORTED)) { 2090 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg, 2091 "INTX: %s does not support INTX. flags=0x%x", 2092 hba->model_info.model, hba->model_info.flags); 2093 2094 return (DDI_FAILURE); 2095 } 2096 2097 /* 2098 * Interrupt number '0' is a high-level interrupt. This driver 2099 * does not support having its interrupts mapped above scheduler 2100 * priority; i.e., we always expect to be able to call general 2101 * kernel routines that may invoke the scheduler. 2102 */ 2103 if (ddi_intr_hilevel(hba->dip, EMLXS_INUMBER) != 0) { 2104 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg, 2105 "INTX: High-level interrupt not supported."); 2106 2107 return (DDI_FAILURE); 2108 } 2109 2110 /* Get an iblock cookie */ 2111 ret = 2112 ddi_get_iblock_cookie(hba->dip, (uint32_t)EMLXS_INUMBER, 2113 (ddi_iblock_cookie_t *)&hba->intr_arg); 2114 if (ret != DDI_SUCCESS) { 2115 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg, 2116 "INTX: ddi_get_iblock_cookie failed. ret=%d", ret); 2117 2118 return (ret); 2119 } 2120 2121 hba->intr_flags |= EMLXS_INTX_INITED; 2122 2123 /* Create the interrupt threads */ 2124 for (i = 0; i < MAX_RINGS; i++) { 2125 (void) sprintf(buf, "%s%d_ring%d mutex", DRIVER_NAME, 2126 hba->ddiinst, i); 2127 mutex_init(&hba->ring[i].rsp_lock, buf, MUTEX_DRIVER, 2128 (void *)hba->intr_arg); 2129 2130 emlxs_thread_create(hba, &hba->ring[i].intr_thread); 2131 } 2132 2133 return (DDI_SUCCESS); 2134 2135 } /* emlxs_intx_init() */ 2136 2137 2138 /* EMLXS_INTR_UNINIT */ 2139 int32_t 2140 emlxs_intx_uninit(emlxs_hba_t *hba) 2141 { 2142 int32_t ret; 2143 uint32_t i; 2144 2145 /* Make sure interrupts have been removed */ 2146 if ((hba->intr_flags & EMLXS_INTX_ADDED)) { 2147 ret = emlxs_intx_remove(hba); 2148 2149 if (ret != DDI_SUCCESS) { 2150 return (ret); 2151 } 2152 } 2153 2154 /* Check if the interrupts are still initialized */ 2155 if (!(hba->intr_flags & EMLXS_INTX_INITED)) { 2156 return (DDI_SUCCESS); 2157 } 2158 hba->intr_flags &= ~EMLXS_INTX_INITED; 2159 2160 hba->intr_arg = NULL; 2161 2162 /* Create the interrupt threads */ 2163 for (i = 0; i < MAX_RINGS; i++) { 2164 emlxs_thread_destroy(&hba->ring[i].intr_thread); 2165 mutex_destroy(&hba->ring[i].rsp_lock); 2166 } 2167 2168 return (DDI_SUCCESS); 2169 2170 } /* emlxs_intx_uninit() */ 2171 2172 2173 /* 2174 * This is the legacy method for adding interrupts in Solaris 2175 * EMLXS_INTR_ADD 2176 */ 2177 int32_t 2178 emlxs_intx_add(emlxs_hba_t *hba) 2179 { 2180 emlxs_port_t *port = &PPORT; 2181 int32_t ret; 2182 2183 /* Check if interrupts have already been added */ 2184 if (hba->intr_flags & EMLXS_INTX_ADDED) { 2185 return (DDI_SUCCESS); 2186 } 2187 2188 /* Check if interrupts have been initialized */ 2189 if (!(hba->intr_flags & EMLXS_INTX_INITED)) { 2190 ret = emlxs_intx_init(hba, 0); 2191 2192 if (ret != DDI_SUCCESS) { 2193 return (ret); 2194 } 2195 } 2196 2197 /* add intrrupt handler routine */ 2198 ret = ddi_add_intr((void *)hba->dip, 2199 (uint_t)EMLXS_INUMBER, 2200 (ddi_iblock_cookie_t *)&hba->intr_arg, 2201 (ddi_idevice_cookie_t *)0, 2202 (uint_t(*)())emlxs_sli_intx_intr, (caddr_t)hba); 2203 2204 if (ret != DDI_SUCCESS) { 2205 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_failed_msg, 2206 "INTX: ddi_add_intr failed. ret=%d", ret); 2207 2208 return (ret); 2209 } 2210 2211 hba->intr_flags |= EMLXS_INTX_ADDED; 2212 2213 return (DDI_SUCCESS); 2214 2215 } /* emlxs_intx_add() */ 2216 2217 2218 /* EMLXS_INTR_REMOVE */ 2219 int32_t 2220 emlxs_intx_remove(emlxs_hba_t *hba) 2221 { 2222 /* Check if interrupts have already been removed */ 2223 if (!(hba->intr_flags & EMLXS_INTX_ADDED)) { 2224 return (DDI_SUCCESS); 2225 } 2226 hba->intr_flags &= ~EMLXS_INTX_ADDED; 2227 2228 /* Diable all adapter interrupts */ 2229 emlxs_disable_intr(hba, 0); 2230 2231 /* Remove the interrupt */ 2232 (void) ddi_remove_intr((void *)hba->dip, (uint_t)EMLXS_INUMBER, 2233 hba->intr_arg); 2234 2235 return (DDI_SUCCESS); 2236 2237 } /* emlxs_intx_remove() */ 2238 2239 2240 static void 2241 emlxs_process_link_speed(emlxs_hba_t *hba) 2242 { 2243 emlxs_vpd_t *vpd; 2244 emlxs_config_t *cfg; 2245 char *cptr; 2246 uint32_t hi; 2247 2248 /* 2249 * This routine modifies the link-speed config parameter entry 2250 * based on adapter capabilities 2251 */ 2252 vpd = &VPD; 2253 cfg = &hba->config[CFG_LINK_SPEED]; 2254 2255 cptr = cfg->help; 2256 (void) strcpy(cptr, "Select link speed. [0=Auto"); 2257 cptr += 26; 2258 hi = 0; 2259 2260 if (vpd->link_speed & LMT_1GB_CAPABLE) { 2261 (void) strcpy(cptr, ", 1=1Gb"); 2262 cptr += 7; 2263 hi = 1; 2264 } 2265 2266 if (vpd->link_speed & LMT_2GB_CAPABLE) { 2267 (void) strcpy(cptr, ", 2=2Gb"); 2268 cptr += 7; 2269 hi = 2; 2270 } 2271 2272 if (vpd->link_speed & LMT_4GB_CAPABLE) { 2273 (void) strcpy(cptr, ", 4=4Gb"); 2274 cptr += 7; 2275 hi = 4; 2276 } 2277 2278 if (vpd->link_speed & LMT_8GB_CAPABLE) { 2279 (void) strcpy(cptr, ", 8=8Gb"); 2280 cptr += 7; 2281 hi = 8; 2282 } 2283 2284 if (vpd->link_speed & LMT_10GB_CAPABLE) { 2285 (void) strcpy(cptr, ", 10=10Gb"); 2286 cptr += 9; 2287 hi = 10; 2288 } 2289 2290 (void) strcpy(cptr, "]"); 2291 cfg->hi = hi; 2292 2293 /* Now revalidate the current parameter setting */ 2294 cfg->current = emlxs_check_parm(hba, CFG_LINK_SPEED, cfg->current); 2295 2296 return; 2297 2298 } /* emlxs_process_link_speed() */ 2299 2300 2301 /* 2302 * emlxs_parse_vpd() 2303 * 2304 * This routine will parse the VPD data 2305 */ 2306 extern int 2307 emlxs_parse_vpd(emlxs_hba_t *hba, uint8_t *vpd_buf, uint32_t size) 2308 { 2309 emlxs_port_t *port = &PPORT; 2310 char tag[3]; 2311 uint8_t lenlo, lenhi; 2312 uint32_t n; 2313 uint16_t block_size; 2314 uint32_t block_index = 0; 2315 uint8_t sub_size; 2316 uint32_t sub_index; 2317 int32_t finished = 0; 2318 int32_t index = 0; 2319 char buffer[128]; 2320 emlxs_vpd_t *vpd; 2321 2322 vpd = &VPD; 2323 2324 2325 while (!finished && (block_index < size)) { 2326 /* 2327 * EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_vpd_msg, 2328 * "block_index = %x", block_index); 2329 */ 2330 2331 switch (vpd_buf[block_index]) { 2332 case 0x82: 2333 index = block_index; 2334 index += 1; 2335 lenlo = vpd_buf[index]; 2336 index += 1; 2337 lenhi = vpd_buf[index]; 2338 index += 1; 2339 block_index = index; 2340 2341 block_size = ((((uint16_t)lenhi) << 8) + lenlo); 2342 block_index += block_size; 2343 2344 /* 2345 * EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_vpd_msg, 2346 * "block_size = %x", block_size); 2347 */ 2348 2349 n = sizeof (buffer); 2350 bzero(buffer, n); 2351 bcopy(&vpd_buf[index], buffer, 2352 (block_size < (n - 1)) ? block_size : (n - 1)); 2353 2354 (void) strcpy(vpd->id, buffer); 2355 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_vpd_msg, "ID: %s", 2356 vpd->id); 2357 2358 break; 2359 2360 case 0x90: 2361 index = block_index; 2362 index += 1; 2363 lenlo = vpd_buf[index]; 2364 index += 1; 2365 lenhi = vpd_buf[index]; 2366 index += 1; 2367 block_index = index; 2368 sub_index = index; 2369 2370 block_size = ((((uint16_t)lenhi) << 8) + lenlo); 2371 block_index += block_size; 2372 2373 /* 2374 * EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_vpd_msg, 2375 * "block_size = %x", block_size); 2376 */ 2377 2378 /* Scan for sub-blocks */ 2379 while ((sub_index < block_index) && 2380 (sub_index < size)) { 2381 /* 2382 * EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_vpd_msg, 2383 * "sub_index = %x", sub_index); 2384 */ 2385 2386 index = sub_index; 2387 tag[0] = vpd_buf[index++]; 2388 tag[1] = vpd_buf[index++]; 2389 tag[2] = 0; 2390 sub_size = vpd_buf[index++]; 2391 2392 /* 2393 * EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_vpd_msg, 2394 * "sub_size = %x", sub_size); 2395 */ 2396 2397 sub_index = (index + sub_size); 2398 2399 n = sizeof (buffer); 2400 bzero(buffer, n); 2401 bcopy(&vpd_buf[index], buffer, 2402 (sub_size < (n - 1)) ? sub_size : (n - 1)); 2403 2404 /* 2405 * Look for Engineering Change (EC) 2406 */ 2407 if (strcmp(tag, "EC") == 0) { 2408 (void) strcpy(vpd->eng_change, buffer); 2409 EMLXS_MSGF(EMLXS_CONTEXT, 2410 &emlxs_vpd_msg, "EC: %s", 2411 vpd->eng_change); 2412 } 2413 /* 2414 * Look for Manufacturer (MN) 2415 */ 2416 else if (strcmp(tag, "MN") == 0) { 2417 (void) strcpy(vpd->manufacturer, 2418 buffer); 2419 EMLXS_MSGF(EMLXS_CONTEXT, 2420 &emlxs_vpd_msg, "MN: %s", 2421 vpd->manufacturer); 2422 } 2423 /* 2424 * Look for Serial Number (SN) 2425 */ 2426 else if (strcmp(tag, "SN") == 0) { 2427 (void) strcpy(vpd->serial_num, buffer); 2428 EMLXS_MSGF(EMLXS_CONTEXT, 2429 &emlxs_vpd_msg, "SN: %s", 2430 vpd->serial_num); 2431 2432 /* Validate the serial number */ 2433 if (strncmp(buffer, "FFFFFFFFFF", 10) == 2434 0 || 2435 strncmp(buffer, "0000000000", 10) == 2436 0) { 2437 vpd->serial_num[0] = 0; 2438 } 2439 } 2440 /* 2441 * Look for Part Number (PN) 2442 */ 2443 else if (strcmp(tag, "PN") == 0) { 2444 (void) strcpy(vpd->part_num, buffer); 2445 EMLXS_MSGF(EMLXS_CONTEXT, 2446 &emlxs_vpd_msg, "PN: %s", 2447 vpd->part_num); 2448 } 2449 /* 2450 * Look for (V0) 2451 */ 2452 else if (strcmp(tag, "V0") == 0) { 2453 /* Not used */ 2454 EMLXS_MSGF(EMLXS_CONTEXT, 2455 &emlxs_vpd_msg, "V0: %s", buffer); 2456 } 2457 /* 2458 * Look for model description (V1) 2459 */ 2460 else if (strcmp(tag, "V1") == 0) { 2461 (void) strcpy(vpd->model_desc, buffer); 2462 EMLXS_MSGF(EMLXS_CONTEXT, 2463 &emlxs_vpd_msg, "Desc: %s", 2464 vpd->model_desc); 2465 } 2466 /* 2467 * Look for model (V2) 2468 */ 2469 else if (strcmp(tag, "V2") == 0) { 2470 (void) strcpy(vpd->model, buffer); 2471 EMLXS_MSGF(EMLXS_CONTEXT, 2472 &emlxs_vpd_msg, "Model: %s", 2473 vpd->model); 2474 } 2475 /* 2476 * Look for program type (V3) 2477 */ 2478 2479 else if (strcmp(tag, "V3") == 0) { 2480 (void) strcpy(vpd->prog_types, buffer); 2481 EMLXS_MSGF(EMLXS_CONTEXT, 2482 &emlxs_vpd_msg, "Prog Types: %s", 2483 vpd->prog_types); 2484 } 2485 /* 2486 * Look for port number (V4) 2487 */ 2488 else if (strcmp(tag, "V4") == 0) { 2489 (void) strcpy(vpd->port_num, buffer); 2490 vpd->port_index = 2491 emlxs_strtol(vpd->port_num, 10); 2492 2493 EMLXS_MSGF(EMLXS_CONTEXT, 2494 &emlxs_vpd_msg, "Port: %s", 2495 (vpd->port_num[0]) ? vpd-> 2496 port_num : "not applicable"); 2497 } 2498 /* 2499 * Look for checksum (RV) 2500 */ 2501 else if (strcmp(tag, "RV") == 0) { 2502 /* Not used */ 2503 EMLXS_MSGF(EMLXS_CONTEXT, 2504 &emlxs_vpd_msg, "Checksum: 0x%x", 2505 buffer[0]); 2506 } 2507 2508 else { 2509 /* Generic */ 2510 EMLXS_MSGF(EMLXS_CONTEXT, 2511 &emlxs_vpd_msg, "Tag: %s: %s", 2512 tag, buffer); 2513 } 2514 } 2515 2516 break; 2517 2518 case 0x78: 2519 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_vpd_msg, "End Tag."); 2520 finished = 1; 2521 break; 2522 2523 default: 2524 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_vpd_msg, 2525 "Unknown block: %x %x %x %x %x %x %x %x", 2526 vpd_buf[index], vpd_buf[index + 1], 2527 vpd_buf[index + 2], vpd_buf[index + 3], 2528 vpd_buf[index + 4], vpd_buf[index + 5], 2529 vpd_buf[index + 6], vpd_buf[index + 7]); 2530 return (0); 2531 } 2532 } 2533 2534 return (1); 2535 2536 } /* emlxs_parse_vpd */ 2537 2538 2539 2540 static uint32_t 2541 emlxs_decode_biu_rev(uint32_t rev) 2542 { 2543 return (rev & 0xf); 2544 } /* End emlxs_decode_biu_rev */ 2545 2546 2547 static uint32_t 2548 emlxs_decode_endec_rev(uint32_t rev) 2549 { 2550 return ((rev >> 28) & 0xf); 2551 } /* End emlxs_decode_endec_rev */ 2552 2553 2554 extern void 2555 emlxs_decode_firmware_rev(emlxs_hba_t *hba, emlxs_vpd_t *vpd) 2556 { 2557 if (vpd->rBit) { 2558 switch (hba->sli_mode) { 2559 case EMLXS_HBA_SLI4_MODE: 2560 (void) strcpy(vpd->fw_version, vpd->sli4FwName); 2561 (void) strcpy(vpd->fw_label, vpd->sli4FwLabel); 2562 break; 2563 case EMLXS_HBA_SLI3_MODE: 2564 (void) strcpy(vpd->fw_version, vpd->sli3FwName); 2565 (void) strcpy(vpd->fw_label, vpd->sli3FwLabel); 2566 break; 2567 case EMLXS_HBA_SLI2_MODE: 2568 (void) strcpy(vpd->fw_version, vpd->sli2FwName); 2569 (void) strcpy(vpd->fw_label, vpd->sli2FwLabel); 2570 break; 2571 case EMLXS_HBA_SLI1_MODE: 2572 (void) strcpy(vpd->fw_version, vpd->sli1FwName); 2573 (void) strcpy(vpd->fw_label, vpd->sli1FwLabel); 2574 break; 2575 default: 2576 (void) strcpy(vpd->fw_version, "unknown"); 2577 (void) strcpy(vpd->fw_label, vpd->fw_version); 2578 } 2579 } else { 2580 emlxs_decode_version(vpd->smFwRev, vpd->fw_version); 2581 (void) strcpy(vpd->fw_label, vpd->fw_version); 2582 } 2583 2584 return; 2585 2586 } /* emlxs_decode_firmware_rev() */ 2587 2588 2589 2590 extern void 2591 emlxs_decode_version(uint32_t version, char *buffer) 2592 { 2593 uint32_t b1, b2, b3, b4; 2594 char c; 2595 2596 b1 = (version & 0x0000f000) >> 12; 2597 b2 = (version & 0x00000f00) >> 8; 2598 b3 = (version & 0x000000c0) >> 6; 2599 b4 = (version & 0x00000030) >> 4; 2600 2601 if (b1 == 0 && b2 == 0) { 2602 (void) sprintf(buffer, "none"); 2603 return; 2604 } 2605 2606 c = 0; 2607 switch (b4) { 2608 case 0: 2609 c = 'n'; 2610 break; 2611 case 1: 2612 c = 'a'; 2613 break; 2614 case 2: 2615 c = 'b'; 2616 break; 2617 case 3: 2618 if ((version & 0x0000000f)) { 2619 c = 'x'; 2620 } 2621 break; 2622 2623 } 2624 b4 = (version & 0x0000000f); 2625 2626 if (c == 0) { 2627 (void) sprintf(buffer, "%d.%d%d", b1, b2, b3); 2628 } else { 2629 (void) sprintf(buffer, "%d.%d%d%c%d", b1, b2, b3, c, b4); 2630 } 2631 2632 return; 2633 2634 } /* emlxs_decode_version() */ 2635 2636 2637 static void 2638 emlxs_decode_label(char *label, char *buffer) 2639 { 2640 uint32_t i; 2641 char name[16]; 2642 #ifdef EMLXS_LITTLE_ENDIAN 2643 uint32_t *wptr; 2644 uint32_t word; 2645 #endif /* EMLXS_LITTLE_ENDIAN */ 2646 2647 bcopy(label, name, 16); 2648 2649 #ifdef EMLXS_LITTLE_ENDIAN 2650 wptr = (uint32_t *)name; 2651 for (i = 0; i < 3; i++) { 2652 word = *wptr; 2653 word = SWAP_DATA32(word); 2654 *wptr++ = word; 2655 } 2656 #endif /* EMLXS_LITTLE_ENDIAN */ 2657 2658 for (i = 0; i < 16; i++) { 2659 if (name[i] == 0x20) { 2660 name[i] = 0; 2661 } 2662 } 2663 2664 (void) strcpy(buffer, name); 2665 2666 return; 2667 2668 } /* emlxs_decode_label() */ 2669 2670 2671 extern uint32_t 2672 emlxs_strtol(char *str, uint32_t base) 2673 { 2674 uint32_t value = 0; 2675 char *ptr; 2676 uint32_t factor = 1; 2677 uint32_t digits; 2678 2679 if (*str == 0) { 2680 return (0); 2681 } 2682 2683 if (base != 10 && base != 16) { 2684 return (0); 2685 } 2686 2687 /* Get max digits of value */ 2688 digits = (base == 10) ? 9 : 8; 2689 2690 /* Position pointer to end of string */ 2691 ptr = str + strlen(str); 2692 2693 /* Process string backwards */ 2694 while ((ptr-- > str) && digits) { 2695 /* check for base 10 numbers */ 2696 if (*ptr >= '0' && *ptr <= '9') { 2697 value += ((uint32_t)(*ptr - '0')) * factor; 2698 factor *= base; 2699 digits--; 2700 } else if (base == 16) { 2701 /* Check for base 16 numbers */ 2702 if (*ptr >= 'a' && *ptr <= 'f') { 2703 value += 2704 ((uint32_t)(*ptr - 'a') + 10) * factor; 2705 factor *= base; 2706 digits--; 2707 } else if (*ptr >= 'A' && *ptr <= 'F') { 2708 value += 2709 ((uint32_t)(*ptr - 'A') + 10) * factor; 2710 factor *= base; 2711 digits--; 2712 } else if (factor > 1) { 2713 break; 2714 } 2715 } else if (factor > 1) { 2716 break; 2717 } 2718 } 2719 2720 return (value); 2721 2722 } /* emlxs_strtol() */ 2723 2724 2725 extern uint64_t 2726 emlxs_strtoll(char *str, uint32_t base) 2727 { 2728 uint64_t value = 0; 2729 char *ptr; 2730 uint32_t factor = 1; 2731 uint32_t digits; 2732 2733 if (*str == 0) { 2734 return (0); 2735 } 2736 2737 if (base != 10 && base != 16) { 2738 return (0); 2739 } 2740 2741 /* Get max digits of value */ 2742 digits = (base == 10) ? 19 : 16; 2743 2744 /* Position pointer to end of string */ 2745 ptr = str + strlen(str); 2746 2747 /* Process string backwards */ 2748 while ((ptr-- > str) && digits) { 2749 /* check for base 10 numbers */ 2750 if (*ptr >= '0' && *ptr <= '9') { 2751 value += ((uint32_t)(*ptr - '0')) * factor; 2752 factor *= base; 2753 digits--; 2754 } else if (base == 16) { 2755 /* Check for base 16 numbers */ 2756 if (*ptr >= 'a' && *ptr <= 'f') { 2757 value += 2758 ((uint32_t)(*ptr - 'a') + 10) * factor; 2759 factor *= base; 2760 digits--; 2761 } else if (*ptr >= 'A' && *ptr <= 'F') { 2762 value += 2763 ((uint32_t)(*ptr - 'A') + 10) * factor; 2764 factor *= base; 2765 digits--; 2766 } else if (factor > 1) { 2767 break; 2768 } 2769 } else if (factor > 1) { 2770 break; 2771 } 2772 } 2773 2774 return (value); 2775 2776 } /* emlxs_strtoll() */ 2777 2778 static void 2779 emlxs_parse_prog_types(emlxs_hba_t *hba, char *prog_types) 2780 { 2781 emlxs_port_t *port = &PPORT; 2782 uint32_t i; 2783 char *ptr; 2784 emlxs_model_t *model; 2785 char types_buffer[256]; 2786 char *types; 2787 2788 bcopy(prog_types, types_buffer, 256); 2789 types = types_buffer; 2790 2791 model = &hba->model_info; 2792 2793 while (*types) { 2794 if (strncmp(types, "T2:", 3) == 0) { 2795 bzero(model->pt_2, sizeof (model->pt_2)); 2796 types += 3; 2797 2798 i = 0; 2799 while (*types && *types != 'T') { 2800 /* Null terminate the next value */ 2801 ptr = types; 2802 while (*ptr && (*ptr != ',')) 2803 ptr++; 2804 *ptr = 0; 2805 2806 /* Save the value */ 2807 model->pt_2[i++] = 2808 (uint8_t)emlxs_strtol(types, 16); 2809 2810 /* 2811 * EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_vpd_msg, 2812 * "T2[%d]: 0x%x", i-1, model->pt_2[i-1]); 2813 */ 2814 2815 /* Move the str pointer */ 2816 types = ptr + 1; 2817 } 2818 2819 } else if (strncmp(types, "T3:", 3) == 0) { 2820 bzero(model->pt_3, sizeof (model->pt_3)); 2821 types += 3; 2822 2823 i = 0; 2824 while (*types && *types != 'T') { 2825 /* Null terminate the next value */ 2826 ptr = types; 2827 while (*ptr && (*ptr != ',')) 2828 ptr++; 2829 *ptr = 0; 2830 2831 /* Save the value */ 2832 model->pt_3[i++] = 2833 (uint8_t)emlxs_strtol(types, 16); 2834 2835 /* 2836 * EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_vpd_msg, 2837 * "T3[%d]: 0x%x", i-1, model->pt_3[i-1]); 2838 */ 2839 2840 /* Move the str pointer */ 2841 types = ptr + 1; 2842 } 2843 } else if (strncmp(types, "T6:", 3) == 0) { 2844 bzero(model->pt_6, sizeof (model->pt_6)); 2845 types += 3; 2846 2847 i = 0; 2848 while (*types && *types != 'T') { 2849 /* Null terminate the next value */ 2850 ptr = types; 2851 while (*ptr && (*ptr != ',')) 2852 ptr++; 2853 *ptr = 0; 2854 2855 /* Save the value */ 2856 model->pt_6[i++] = 2857 (uint8_t)emlxs_strtol(types, 16); 2858 model->pt_6[i] = 0; 2859 2860 /* 2861 * EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_vpd_msg, 2862 * "T6[%d]: 0x%x", i-1, model->pt_6[i-1]); 2863 */ 2864 2865 /* Move the str pointer */ 2866 types = ptr + 1; 2867 } 2868 } else if (strncmp(types, "T7:", 3) == 0) { 2869 bzero(model->pt_7, sizeof (model->pt_7)); 2870 types += 3; 2871 2872 i = 0; 2873 while (*types && *types != 'T') { 2874 /* Null terminate the next value */ 2875 ptr = types; 2876 while (*ptr && (*ptr != ',')) 2877 ptr++; 2878 *ptr = 0; 2879 2880 /* Save the value */ 2881 model->pt_7[i++] = 2882 (uint8_t)emlxs_strtol(types, 16); 2883 model->pt_7[i] = 0; 2884 2885 /* 2886 * EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_vpd_msg, 2887 * "T7[%d]: 0x%x", i-1, model->pt_7[i-1]); 2888 */ 2889 2890 /* Move the str pointer */ 2891 types = ptr + 1; 2892 } 2893 } else if (strncmp(types, "TA:", 3) == 0) { 2894 bzero(model->pt_A, sizeof (model->pt_A)); 2895 types += 3; 2896 2897 i = 0; 2898 while (*types && *types != 'T') { 2899 /* Null terminate the next value */ 2900 ptr = types; 2901 while (*ptr && (*ptr != ',')) 2902 ptr++; 2903 *ptr = 0; 2904 2905 /* Save the value */ 2906 model->pt_A[i++] = 2907 (uint8_t)emlxs_strtol(types, 16); 2908 2909 /* 2910 * EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_vpd_msg, 2911 * "TA[%d]: 0x%x", i-1, model->pt_A[i-1]); 2912 */ 2913 2914 /* Move the str pointer */ 2915 types = ptr + 1; 2916 } 2917 } else if (strncmp(types, "TB:", 3) == 0) { 2918 bzero(model->pt_B, sizeof (model->pt_B)); 2919 types += 3; 2920 2921 i = 0; 2922 while (*types && *types != 'T') { 2923 /* Null terminate the next value */ 2924 ptr = types; 2925 while (*ptr && (*ptr != ',')) 2926 ptr++; 2927 *ptr = 0; 2928 2929 /* Save the value */ 2930 model->pt_B[i++] = 2931 (uint8_t)emlxs_strtol(types, 16); 2932 2933 /* 2934 * EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_vpd_msg, 2935 * "TB[%d]: 0x%x", i-1, model->pt_B[i-1]); 2936 */ 2937 2938 /* Move the str pointer */ 2939 types = ptr + 1; 2940 } 2941 } else if (strncmp(types, "TFF:", 4) == 0) { 2942 bzero(model->pt_FF, sizeof (model->pt_FF)); 2943 types += 4; 2944 2945 i = 0; 2946 while (*types && *types != 'T') { 2947 /* Null terminate the next value */ 2948 ptr = types; 2949 while (*ptr && (*ptr != ',')) 2950 ptr++; 2951 *ptr = 0; 2952 2953 /* Save the value */ 2954 model->pt_FF[i++] = 2955 (uint8_t)emlxs_strtol(types, 16); 2956 2957 /* 2958 * EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_vpd_msg, 2959 * "TF[%d]: 0x%x", i-1, model->pt_FF[i-1]); 2960 */ 2961 2962 /* Move the str pointer */ 2963 types = ptr + 1; 2964 } 2965 } else if (strncmp(types, "T20:", 4) == 0) { 2966 bzero(model->pt_20, sizeof (model->pt_20)); 2967 types += 4; 2968 2969 i = 0; 2970 while (*types && *types != 'T') { 2971 /* Null terminate the next value */ 2972 ptr = types; 2973 while (*ptr && (*ptr != ',')) 2974 ptr++; 2975 *ptr = 0; 2976 2977 /* Save the value */ 2978 model->pt_20[i++] = 2979 (uint8_t)emlxs_strtol(types, 16); 2980 model->pt_20[i] = 0; 2981 2982 /* 2983 * EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_vpd_msg, 2984 * "T20[%d]: 0x%x", i-1, model->pt_20[i-1]); 2985 */ 2986 2987 /* Move the str pointer */ 2988 types = ptr + 1; 2989 } 2990 } else { 2991 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_vpd_msg, 2992 "Unknown prog type string = %s", types); 2993 break; 2994 } 2995 } 2996 2997 return; 2998 2999 } /* emlxs_parse_prog_types() */ 3000 3001 3002 static void 3003 emlxs_build_prog_types(emlxs_hba_t *hba, char *prog_types) 3004 { 3005 uint32_t i; 3006 uint32_t found = 0; 3007 char buffer[256]; 3008 3009 bzero(prog_types, 256); 3010 3011 /* Rebuild the prog type string */ 3012 if (hba->model_info.pt_2[0]) { 3013 (void) strcat(prog_types, "T2:"); 3014 found = 1; 3015 3016 i = 0; 3017 while (hba->model_info.pt_2[i] && i < 8) { 3018 (void) sprintf(buffer, "%X,", hba->model_info.pt_2[i]); 3019 (void) strcat(prog_types, buffer); 3020 i++; 3021 } 3022 } 3023 3024 if (hba->model_info.pt_3[0]) { 3025 (void) strcat(prog_types, "T3:"); 3026 found = 1; 3027 3028 i = 0; 3029 while (hba->model_info.pt_3[i] && i < 8) { 3030 (void) sprintf(buffer, "%X,", hba->model_info.pt_3[i]); 3031 (void) strcat(prog_types, buffer); 3032 i++; 3033 3034 } 3035 } 3036 3037 if (hba->model_info.pt_6[0]) { 3038 (void) strcat(prog_types, "T6:"); 3039 found = 1; 3040 3041 i = 0; 3042 while (hba->model_info.pt_6[i] && i < 8) { 3043 (void) sprintf(buffer, "%X,", hba->model_info.pt_6[i]); 3044 (void) strcat(prog_types, buffer); 3045 i++; 3046 } 3047 } 3048 3049 if (hba->model_info.pt_7[0]) { 3050 (void) strcat(prog_types, "T7:"); 3051 found = 1; 3052 3053 i = 0; 3054 while (hba->model_info.pt_7[i] && i < 8) { 3055 (void) sprintf(buffer, "%X,", hba->model_info.pt_7[i]); 3056 (void) strcat(prog_types, buffer); 3057 i++; 3058 } 3059 } 3060 3061 if (hba->model_info.pt_A[0]) { 3062 (void) strcat(prog_types, "TA:"); 3063 found = 1; 3064 3065 i = 0; 3066 while (hba->model_info.pt_A[i] && i < 8) { 3067 (void) sprintf(buffer, "%X,", hba->model_info.pt_A[i]); 3068 (void) strcat(prog_types, buffer); 3069 i++; 3070 } 3071 } 3072 3073 3074 if (hba->model_info.pt_B[0]) { 3075 (void) strcat(prog_types, "TB:"); 3076 found = 1; 3077 3078 i = 0; 3079 while (hba->model_info.pt_B[i] && i < 8) { 3080 (void) sprintf(buffer, "%X,", hba->model_info.pt_B[i]); 3081 (void) strcat(prog_types, buffer); 3082 i++; 3083 } 3084 } 3085 3086 if (hba->model_info.pt_20[0]) { 3087 (void) strcat(prog_types, "T20:"); 3088 found = 1; 3089 3090 i = 0; 3091 while (hba->model_info.pt_20[i] && i < 8) { 3092 (void) sprintf(buffer, "%X,", hba->model_info.pt_20[i]); 3093 (void) strcat(prog_types, buffer); 3094 i++; 3095 } 3096 } 3097 3098 if (hba->model_info.pt_FF[0]) { 3099 (void) strcat(prog_types, "TFF:"); 3100 found = 1; 3101 3102 i = 0; 3103 while (hba->model_info.pt_FF[i] && i < 8) { 3104 (void) sprintf(buffer, "%X,", hba->model_info.pt_FF[i]); 3105 (void) strcat(prog_types, buffer); 3106 i++; 3107 } 3108 } 3109 3110 if (found) { 3111 /* Terminate at the last comma in string */ 3112 prog_types[(strlen(prog_types) - 1)] = 0; 3113 } 3114 3115 return; 3116 3117 } /* emlxs_build_prog_types() */ 3118 3119 3120 3121 3122 extern uint32_t 3123 emlxs_init_adapter_info(emlxs_hba_t *hba) 3124 { 3125 emlxs_port_t *port = &PPORT; 3126 uint32_t pci_id; 3127 uint32_t cache_line; 3128 uint32_t channels; 3129 uint16_t device_id; 3130 uint16_t ssdid; 3131 uint32_t i; 3132 uint32_t found = 0; 3133 3134 if (hba->bus_type == SBUS_FC) { 3135 if (hba->pci_acc_handle == NULL) { 3136 bcopy(&emlxs_sbus_model[0], &hba->model_info, 3137 sizeof (emlxs_model_t)); 3138 3139 hba->model_info.device_id = 0; 3140 3141 return (0); 3142 } 3143 3144 /* Read the PCI device id */ 3145 pci_id = 3146 ddi_get32(hba->pci_acc_handle, 3147 (uint32_t *)(hba->pci_addr + PCI_VENDOR_ID_REGISTER)); 3148 device_id = (uint16_t)(pci_id >> 16); 3149 3150 /* Find matching adapter model */ 3151 for (i = 1; i < EMLXS_SBUS_MODEL_COUNT; i++) { 3152 if (emlxs_sbus_model[i].device_id == device_id) { 3153 bcopy(&emlxs_sbus_model[i], &hba->model_info, 3154 sizeof (emlxs_model_t)); 3155 found = 1; 3156 break; 3157 } 3158 } 3159 3160 /* If not found then use the unknown model */ 3161 if (!found) { 3162 bcopy(&emlxs_sbus_model[0], &hba->model_info, 3163 sizeof (emlxs_model_t)); 3164 3165 hba->model_info.device_id = device_id; 3166 3167 return (0); 3168 } 3169 } else { /* PCI model */ 3170 3171 if (hba->pci_acc_handle == NULL) { 3172 bcopy(&emlxs_pci_model[0], &hba->model_info, 3173 sizeof (emlxs_model_t)); 3174 3175 hba->model_info.device_id = 0; 3176 3177 return (0); 3178 } 3179 3180 /* Read the PCI device id */ 3181 device_id = 3182 ddi_get16(hba->pci_acc_handle, 3183 (uint16_t *)(hba->pci_addr + PCI_DEVICE_ID_REGISTER)); 3184 3185 /* Read the PCI Subsystem id */ 3186 ssdid = 3187 ddi_get16(hba->pci_acc_handle, 3188 (uint16_t *)(hba->pci_addr + PCI_SSDID_REGISTER)); 3189 3190 if (ssdid == 0 || ssdid == 0xffff) { 3191 ssdid = device_id; 3192 } 3193 3194 /* Read the Cache Line reg */ 3195 cache_line = 3196 ddi_get32(hba->pci_acc_handle, 3197 (uint32_t *)(hba->pci_addr + PCI_CACHE_LINE_REGISTER)); 3198 3199 /* Check for the multifunction bit being set */ 3200 if ((cache_line & 0x00ff0000) == 0x00800000) { 3201 channels = 2; 3202 } else { 3203 channels = 1; 3204 } 3205 3206 /* If device ids are unique, then use them for search */ 3207 if (device_id != ssdid) { 3208 if (channels > 1) { 3209 /* 3210 * Find matching adapter model using 3211 * device_id, ssdid and channels 3212 */ 3213 for (i = 1; i < EMLXS_PCI_MODEL_COUNT; i++) { 3214 if (emlxs_pci_model[i].device_id == 3215 device_id && 3216 emlxs_pci_model[i].ssdid == ssdid && 3217 emlxs_pci_model[i].channels == 3218 channels) { 3219 bcopy(&emlxs_pci_model[i], 3220 &hba->model_info, 3221 sizeof (emlxs_model_t)); 3222 found = 1; 3223 break; 3224 } 3225 } 3226 } else { 3227 /* 3228 * Find matching adapter model using 3229 * device_id and ssdid 3230 */ 3231 for (i = 1; i < EMLXS_PCI_MODEL_COUNT; i++) { 3232 if (emlxs_pci_model[i].device_id == 3233 device_id && 3234 emlxs_pci_model[i].ssdid == ssdid) { 3235 bcopy(&emlxs_pci_model[i], 3236 &hba->model_info, 3237 sizeof (emlxs_model_t)); 3238 found = 1; 3239 break; 3240 } 3241 } 3242 } 3243 } 3244 3245 /* If adapter not found, try again */ 3246 if (!found) { 3247 /* Find matching adapter model */ 3248 for (i = 1; i < EMLXS_PCI_MODEL_COUNT; i++) { 3249 if (emlxs_pci_model[i].device_id == device_id && 3250 emlxs_pci_model[i].channels == channels) { 3251 bcopy(&emlxs_pci_model[i], 3252 &hba->model_info, 3253 sizeof (emlxs_model_t)); 3254 found = 1; 3255 break; 3256 } 3257 } 3258 } 3259 3260 /* If adapter not found, try one last time */ 3261 if (!found) { 3262 /* Find matching adapter model */ 3263 for (i = 1; i < EMLXS_PCI_MODEL_COUNT; i++) { 3264 if (emlxs_pci_model[i].device_id == device_id) { 3265 bcopy(&emlxs_pci_model[i], 3266 &hba->model_info, 3267 sizeof (emlxs_model_t)); 3268 found = 1; 3269 break; 3270 } 3271 } 3272 } 3273 3274 /* If not found, set adapter to unknown */ 3275 if (!found) { 3276 bcopy(&emlxs_pci_model[0], &hba->model_info, 3277 sizeof (emlxs_model_t)); 3278 3279 hba->model_info.device_id = device_id; 3280 hba->model_info.ssdid = ssdid; 3281 3282 return (0); 3283 } 3284 3285 #ifndef SATURN_MSI_SUPPORT 3286 /* 3287 * This will disable MSI support for Saturn adapter's 3288 * due to a PCI bus issue 3289 */ 3290 if (hba->model_info.chip == EMLXS_SATURN_CHIP) { 3291 hba->model_info.flags &= 3292 ~(EMLXS_MSI_SUPPORTED | EMLXS_MSIX_SUPPORTED); 3293 } 3294 #endif /* !SATURN_MSI_SUPPORT */ 3295 3296 3297 #ifdef MSI_SUPPORT 3298 /* Verify MSI support */ 3299 if (hba->model_info.flags & EMLXS_MSI_SUPPORTED) { 3300 uint32_t offset; 3301 uint32_t reg; 3302 3303 /* Scan for MSI capabilities register */ 3304 offset = 3305 ddi_get32(hba->pci_acc_handle, 3306 (uint32_t *)(hba->pci_addr + PCI_CAP_POINTER)); 3307 offset &= 0xff; 3308 3309 while (offset) { 3310 reg = 3311 ddi_get32(hba->pci_acc_handle, 3312 (uint32_t *)(hba->pci_addr + offset)); 3313 3314 if ((reg & 0xff) == MSI_CAP_ID) { 3315 break; 3316 } 3317 offset = (reg >> 8) & 0xff; 3318 } 3319 3320 if (offset) { 3321 hba->msi_cap_offset = offset + 2; 3322 } else { 3323 hba->msi_cap_offset = 0; 3324 hba->model_info.flags &= ~EMLXS_MSI_SUPPORTED; 3325 3326 EMLXS_MSGF(EMLXS_CONTEXT, 3327 &emlxs_init_debug_msg, 3328 "MSI: control_reg capability not found!"); 3329 } 3330 } 3331 3332 /* Verify MSI-X support */ 3333 if (hba->model_info.flags & EMLXS_MSIX_SUPPORTED) { 3334 uint32_t offset; 3335 uint32_t reg; 3336 3337 /* Scan for MSI capabilities register */ 3338 offset = 3339 ddi_get32(hba->pci_acc_handle, 3340 (uint32_t *)(hba->pci_addr + PCI_CAP_POINTER)); 3341 offset &= 0xff; 3342 3343 while (offset) { 3344 reg = 3345 ddi_get32(hba->pci_acc_handle, 3346 (uint32_t *)(hba->pci_addr + offset)); 3347 3348 if ((reg & 0xff) == MSIX_CAP_ID) { 3349 break; 3350 } 3351 offset = (reg >> 8) & 0xff; 3352 } 3353 3354 if (offset) { 3355 hba->msix_cap_offset = offset; 3356 } else { 3357 hba->msix_cap_offset = 0; 3358 hba->model_info.flags &= 3359 ~EMLXS_MSIX_SUPPORTED; 3360 3361 EMLXS_MSGF(EMLXS_CONTEXT, 3362 &emlxs_init_debug_msg, 3363 "MSIX: control_reg capability not found!"); 3364 } 3365 } 3366 #endif /* MSI_SUPPORT */ 3367 3368 } 3369 3370 if (hba->model_info.sli_mask & EMLXS_SLI4_MASK) { 3371 return (0); 3372 } 3373 3374 /* For now we just support SLI2 and SLI3 */ 3375 hba->emlxs_sli_api_map_hdw = emlxs_sli3_map_hdw; 3376 hba->emlxs_sli_api_unmap_hdw = emlxs_sli3_unmap_hdw; 3377 hba->emlxs_sli_api_online = emlxs_sli3_online; 3378 hba->emlxs_sli_api_offline = emlxs_sli3_offline; 3379 hba->emlxs_sli_api_hba_reset = emlxs_sli3_hba_reset; 3380 hba->emlxs_sli_api_issue_iocb_cmd = emlxs_sli3_issue_iocb_cmd; 3381 hba->emlxs_sli_api_issue_mbox_cmd = emlxs_sli3_issue_mbox_cmd; 3382 #ifdef SFCT_SUPPORT 3383 hba->emlxs_sli_api_prep_fct_iocb = emlxs_sli3_prep_fct_iocb; 3384 #endif /* SFCT_SUPPORT */ 3385 hba->emlxs_sli_api_prep_fcp_iocb = emlxs_sli3_prep_fcp_iocb; 3386 hba->emlxs_sli_api_prep_ip_iocb = emlxs_sli3_prep_ip_iocb; 3387 hba->emlxs_sli_api_prep_els_iocb = emlxs_sli3_prep_els_iocb; 3388 hba->emlxs_sli_api_prep_ct_iocb = emlxs_sli3_prep_ct_iocb; 3389 hba->emlxs_sli_api_poll_intr = emlxs_sli3_poll_intr; 3390 hba->emlxs_sli_api_intx_intr = emlxs_sli3_intx_intr; 3391 hba->emlxs_sli_api_msi_intr = emlxs_sli3_msi_intr; 3392 return (1); 3393 3394 } /* emlxs_init_adapter_info() */ 3395 3396 3397 /* ARGSUSED */ 3398 static void 3399 emlxs_handle_async_event(emlxs_hba_t *hba, RING *rp, IOCBQ *iocbq) 3400 { 3401 emlxs_port_t *port = &PPORT; 3402 IOCB *iocb; 3403 uint32_t *w; 3404 int i, j; 3405 3406 iocb = &iocbq->iocb; 3407 3408 if (iocb->ulpStatus != 0) { 3409 return; 3410 } 3411 3412 switch (iocb->un.astat.EventCode) { 3413 case 0x0100: /* Temp Warning */ 3414 3415 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_temp_warning_msg, 3416 "Adapter is very hot (%d �C). Take corrective action.", 3417 iocb->ulpContext); 3418 3419 emlxs_log_temp_event(port, 0x02, iocb->ulpContext); 3420 3421 break; 3422 3423 3424 case 0x0101: /* Temp Safe */ 3425 3426 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_temp_msg, 3427 "Adapter temperature now safe (%d �C).", 3428 iocb->ulpContext); 3429 3430 emlxs_log_temp_event(port, 0x03, iocb->ulpContext); 3431 3432 break; 3433 3434 default: 3435 3436 w = (uint32_t *)iocb; 3437 for (i = 0, j = 0; i < 8; i++, j += 2) { 3438 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_async_msg, 3439 "(Word[%d]=%x Word[%d]=%x)", j, w[j], j + 1, 3440 w[j + 1]); 3441 } 3442 3443 emlxs_log_async_event(port, iocb); 3444 } 3445 3446 return; 3447 3448 } /* emlxs_handle_async_event() */ 3449 3450 3451 extern void 3452 emlxs_reset_link_thread(void *arg) 3453 { 3454 emlxs_hba_t *hba = (emlxs_hba_t *)arg; 3455 emlxs_port_t *port = &PPORT; 3456 3457 /* Attempt a link reset to recover */ 3458 (void) emlxs_reset(port, FC_FCA_LINK_RESET); 3459 3460 thread_exit(); 3461 3462 } /* emlxs_reset_link_thread() */ 3463 3464 3465 extern void 3466 emlxs_restart_thread(void *arg) 3467 { 3468 emlxs_hba_t *hba = (emlxs_hba_t *)arg; 3469 emlxs_port_t *port = &PPORT; 3470 3471 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_adapter_trans_msg, "Restarting..."); 3472 3473 /* Attempt a full hardware reset to recover */ 3474 if (emlxs_reset(port, FC_FCA_RESET) != FC_SUCCESS) { 3475 emlxs_ffstate_change(hba, FC_ERROR); 3476 3477 thread_create(NULL, 0, emlxs_shutdown_thread, (char *)hba, 0, 3478 &p0, TS_RUN, v.v_maxsyspri - 2); 3479 } 3480 3481 thread_exit(); 3482 3483 } /* emlxs_restart_thread() */ 3484 3485 3486 extern void 3487 emlxs_shutdown_thread(void *arg) 3488 { 3489 emlxs_hba_t *hba = (emlxs_hba_t *)arg; 3490 emlxs_port_t *port = &PPORT; 3491 3492 mutex_enter(&EMLXS_PORT_LOCK); 3493 if (hba->flag & FC_SHUTDOWN) { 3494 mutex_exit(&EMLXS_PORT_LOCK); 3495 thread_exit(); 3496 } 3497 hba->flag |= FC_SHUTDOWN; 3498 mutex_exit(&EMLXS_PORT_LOCK); 3499 3500 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_adapter_trans_msg, 3501 "Shutting down..."); 3502 3503 /* Take adapter offline and leave it there */ 3504 (void) emlxs_offline(hba); 3505 3506 /* Log a dump event */ 3507 emlxs_log_dump_event(port, NULL, 0); 3508 3509 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_shutdown_msg, "Reboot required."); 3510 3511 thread_exit(); 3512 3513 } /* emlxs_shutdown_thread() */ 3514 3515 3516 /* ARGSUSED */ 3517 extern void 3518 emlxs_proc_ring(emlxs_hba_t *hba, RING *rp, void *arg2) 3519 { 3520 IOCBQ *iocbq; 3521 IOCBQ *rsp_head; 3522 3523 /* 3524 * EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg, 3525 * "emlxs_proc_ring: ringo=%d", rp->ringno); 3526 */ 3527 3528 mutex_enter(&rp->rsp_lock); 3529 3530 while ((rsp_head = rp->rsp_head) != NULL) { 3531 rp->rsp_head = NULL; 3532 rp->rsp_tail = NULL; 3533 3534 mutex_exit(&rp->rsp_lock); 3535 3536 while ((iocbq = rsp_head) != NULL) { 3537 rsp_head = (IOCBQ *) iocbq->next; 3538 3539 emlxs_proc_ring_event(hba, rp, iocbq); 3540 } 3541 3542 mutex_enter(&rp->rsp_lock); 3543 } 3544 3545 mutex_exit(&rp->rsp_lock); 3546 3547 emlxs_sli_issue_iocb_cmd(hba, rp, 0); 3548 3549 return; 3550 3551 } /* emlxs_proc_ring() */ 3552 3553 3554 /* 3555 * Called from SLI ring event routines to process a rsp ring IOCB. 3556 */ 3557 void 3558 emlxs_proc_ring_event(emlxs_hba_t *hba, RING *rp, IOCBQ *iocbq) 3559 { 3560 emlxs_port_t *port = &PPORT; 3561 char buffer[MAX_MSG_DATA + 1]; 3562 IOCB *iocb; 3563 3564 iocb = &iocbq->iocb; 3565 3566 /* Check for IOCB local error */ 3567 if (iocb->ulpStatus == IOSTAT_LOCAL_REJECT) { 3568 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_iocb_event_msg, 3569 "Local reject. ringno=%d iocb=%p cmd=%x " 3570 "iotag=%x context=%x info=%x error=%x", 3571 rp->ringno, iocb, (uint8_t)iocb->ulpCommand, 3572 (uint16_t)iocb->ulpIoTag, (uint16_t)iocb->ulpContext, 3573 (uint8_t)iocb->ulpRsvdByte, 3574 (uint8_t)iocb->un.grsp.perr.statLocalError); 3575 } else if (iocb->ulpStatus == IOSTAT_ILLEGAL_FRAME_RCVD) { 3576 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_iocb_event_msg, 3577 "Illegal frame. ringno=%d iocb=%p cmd=%x " 3578 "iotag=%x context=%x info=%x error=%x", 3579 rp->ringno, iocb, (uint8_t)iocb->ulpCommand, 3580 (uint16_t)iocb->ulpIoTag, (uint16_t)iocb->ulpContext, 3581 (uint8_t)iocb->ulpRsvdByte, 3582 (uint8_t)iocb->un.grsp.perr.statLocalError); 3583 } 3584 3585 switch (iocb->ulpCommand) { 3586 /* RING 0 FCP commands */ 3587 case CMD_FCP_ICMND_CR: 3588 case CMD_FCP_ICMND_CX: 3589 case CMD_FCP_IREAD_CR: 3590 case CMD_FCP_IREAD_CX: 3591 case CMD_FCP_IWRITE_CR: 3592 case CMD_FCP_IWRITE_CX: 3593 case CMD_FCP_ICMND64_CR: 3594 case CMD_FCP_ICMND64_CX: 3595 case CMD_FCP_IREAD64_CR: 3596 case CMD_FCP_IREAD64_CX: 3597 case CMD_FCP_IWRITE64_CR: 3598 case CMD_FCP_IWRITE64_CX: 3599 emlxs_handle_fcp_event(hba, rp, iocbq); 3600 break; 3601 3602 #ifdef SFCT_SUPPORT 3603 case CMD_FCP_TSEND_CX: /* FCP_TARGET IOCB command */ 3604 case CMD_FCP_TSEND64_CX: /* FCP_TARGET IOCB command */ 3605 case CMD_FCP_TRECEIVE_CX: /* FCP_TARGET IOCB command */ 3606 case CMD_FCP_TRECEIVE64_CX: /* FCP_TARGET IOCB command */ 3607 case CMD_FCP_TRSP_CX: /* FCP_TARGET IOCB command */ 3608 case CMD_FCP_TRSP64_CX: /* FCP_TARGET IOCB command */ 3609 (void) emlxs_fct_handle_fcp_event(hba, rp, iocbq); 3610 break; 3611 #endif /* SFCT_SUPPORT */ 3612 3613 /* RING 1 IP commands */ 3614 case CMD_XMIT_BCAST_CN: 3615 case CMD_XMIT_BCAST_CX: 3616 case CMD_XMIT_BCAST64_CN: 3617 case CMD_XMIT_BCAST64_CX: 3618 (void) emlxs_ip_handle_event(hba, rp, iocbq); 3619 break; 3620 3621 case CMD_XMIT_SEQUENCE_CX: 3622 case CMD_XMIT_SEQUENCE_CR: 3623 case CMD_XMIT_SEQUENCE64_CX: 3624 case CMD_XMIT_SEQUENCE64_CR: 3625 switch (iocb->un.rcvseq64.w5.hcsw.Type) { 3626 case FC_TYPE_IS8802_SNAP: 3627 (void) emlxs_ip_handle_event(hba, rp, iocbq); 3628 break; 3629 3630 case FC_TYPE_FC_SERVICES: 3631 (void) emlxs_ct_handle_event(hba, rp, iocbq); 3632 break; 3633 3634 default: 3635 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_iocb_invalid_msg, 3636 "cmd=%x type=%x status=%x iotag=%x context=%x ", 3637 iocb->ulpCommand, iocb->un.rcvseq64.w5.hcsw.Type, 3638 iocb->ulpStatus, iocb->ulpIoTag, 3639 iocb->ulpContext); 3640 } 3641 break; 3642 3643 case CMD_RCV_SEQUENCE_CX: 3644 case CMD_RCV_SEQUENCE64_CX: 3645 case CMD_RCV_SEQ64_CX: 3646 case CMD_RCV_ELS_REQ_CX: /* Unsolicited ELS frame */ 3647 case CMD_RCV_ELS_REQ64_CX: /* Unsolicited ELS frame */ 3648 case CMD_RCV_ELS64_CX: /* Unsolicited ELS frame */ 3649 (void) emlxs_handle_rcv_seq(hba, rp, iocbq); 3650 break; 3651 3652 case CMD_RCV_SEQ_LIST64_CX: 3653 (void) emlxs_ip_handle_rcv_seq_list(hba, rp, iocbq); 3654 break; 3655 3656 case CMD_CREATE_XRI_CR: 3657 case CMD_CREATE_XRI_CX: 3658 (void) emlxs_handle_create_xri(hba, rp, iocbq); 3659 break; 3660 3661 /* RING 2 ELS commands */ 3662 case CMD_ELS_REQUEST_CR: 3663 case CMD_ELS_REQUEST_CX: 3664 case CMD_XMIT_ELS_RSP_CX: 3665 case CMD_ELS_REQUEST64_CR: 3666 case CMD_ELS_REQUEST64_CX: 3667 case CMD_XMIT_ELS_RSP64_CX: 3668 (void) emlxs_els_handle_event(hba, rp, iocbq); 3669 break; 3670 3671 /* RING 3 CT commands */ 3672 case CMD_GEN_REQUEST64_CR: 3673 case CMD_GEN_REQUEST64_CX: 3674 switch (iocb->un.rcvseq64.w5.hcsw.Type) { 3675 #ifdef MENLO_SUPPORT 3676 case EMLXS_MENLO_TYPE: 3677 (void) emlxs_menlo_handle_event(hba, rp, iocbq); 3678 break; 3679 #endif /* MENLO_SUPPORT */ 3680 3681 case FC_TYPE_FC_SERVICES: 3682 (void) emlxs_ct_handle_event(hba, rp, iocbq); 3683 break; 3684 3685 default: 3686 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_iocb_invalid_msg, 3687 "cmd=%x type=%x status=%x iotag=%x context=%x ", 3688 iocb->ulpCommand, iocb->un.rcvseq64.w5.hcsw.Type, 3689 iocb->ulpStatus, iocb->ulpIoTag, 3690 iocb->ulpContext); 3691 } 3692 break; 3693 3694 case CMD_ABORT_XRI_CN: /* Abort fcp command */ 3695 3696 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_flushed_msg, 3697 "ABORT_XRI_CN: rpi=%d iotag=%x status=%x parm=%x", 3698 (uint32_t)iocb->un.acxri.abortContextTag, 3699 (uint32_t)iocb->un.acxri.abortIoTag, iocb->ulpStatus, 3700 iocb->un.acxri.parm); 3701 3702 #ifdef SFCT_SUPPORT 3703 if (port->tgt_mode) { 3704 (void) emlxs_fct_handle_abort(hba, rp, iocbq); 3705 } 3706 #endif /* SFCT_SUPPORT */ 3707 break; 3708 3709 case CMD_ABORT_XRI_CX: /* Abort command */ 3710 3711 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_flushed_msg, 3712 "ABORT_XRI_CX: rpi=%d iotag=%x status=%x parm=%x sbp=%p", 3713 (uint32_t)iocb->un.acxri.abortContextTag, 3714 (uint32_t)iocb->un.acxri.abortIoTag, iocb->ulpStatus, 3715 iocb->un.acxri.parm, iocbq->sbp); 3716 3717 #ifdef SFCT_SUPPORT 3718 if (port->tgt_mode) { 3719 (void) emlxs_fct_handle_abort(hba, rp, iocbq); 3720 } 3721 #endif /* SFCT_SUPPORT */ 3722 break; 3723 3724 case CMD_XRI_ABORTED_CX: /* Handle ABORT condition */ 3725 3726 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_flushed_msg, 3727 "XRI_ABORTED_CX: rpi=%d iotag=%x status=%x parm=%x", 3728 (uint32_t)iocb->un.acxri.abortContextTag, 3729 (uint32_t)iocb->un.acxri.abortIoTag, iocb->ulpStatus, 3730 iocb->un.acxri.parm); 3731 3732 #ifdef SFCT_SUPPORT 3733 if (port->tgt_mode) { 3734 (void) emlxs_fct_handle_abort(hba, rp, iocbq); 3735 } 3736 #endif /* SFCT_SUPPORT */ 3737 break; 3738 3739 case CMD_CLOSE_XRI_CN: /* Handle CLOSE condition */ 3740 3741 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_flushed_msg, 3742 "CLOSE_XRI_CR: rpi=%d iotag=%x status=%x parm=%x", 3743 (uint32_t)iocb->un.acxri.abortContextTag, 3744 (uint32_t)iocb->un.acxri.abortIoTag, iocb->ulpStatus, 3745 iocb->un.acxri.parm); 3746 3747 #ifdef SFCT_SUPPORT 3748 if (port->tgt_mode) { 3749 (void) emlxs_fct_handle_abort(hba, rp, iocbq); 3750 } 3751 #endif /* SFCT_SUPPORT */ 3752 break; 3753 3754 case CMD_CLOSE_XRI_CX: /* Handle CLOSE condition */ 3755 3756 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_flushed_msg, 3757 "CLOSE_XRI_CX: rpi=%d iotag=%x status=%x parm=%x sbp=%p", 3758 (uint32_t)iocb->un.acxri.abortContextTag, 3759 (uint32_t)iocb->un.acxri.abortIoTag, iocb->ulpStatus, 3760 iocb->un.acxri.parm, iocbq->sbp); 3761 3762 #ifdef SFCT_SUPPORT 3763 if (port->tgt_mode) { 3764 (void) emlxs_fct_handle_abort(hba, rp, iocbq); 3765 } 3766 #endif /* SFCT_SUPPORT */ 3767 break; 3768 3769 case CMD_ADAPTER_MSG: 3770 /* Allows debug adapter firmware messages to print on host */ 3771 bzero(buffer, sizeof (buffer)); 3772 bcopy((uint8_t *)iocb, buffer, MAX_MSG_DATA); 3773 3774 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_adapter_msg, "%s", buffer); 3775 3776 break; 3777 3778 case CMD_QUE_RING_LIST64_CN: 3779 case CMD_QUE_RING_BUF64_CN: 3780 break; 3781 3782 case CMD_ASYNC_STATUS: 3783 emlxs_handle_async_event(hba, rp, iocbq); 3784 break; 3785 3786 default: 3787 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_iocb_invalid_msg, 3788 "cmd=%x status=%x iotag=%x context=%x", iocb->ulpCommand, 3789 iocb->ulpStatus, iocb->ulpIoTag, iocb->ulpContext); 3790 3791 break; 3792 } /* switch(entry->ulpCommand) */ 3793 3794 return; 3795 3796 } /* emlxs_proc_ring_event() */ 3797 3798 3799 3800 extern char * 3801 emlxs_ffstate_xlate(uint32_t state) 3802 { 3803 static char buffer[32]; 3804 uint32_t i; 3805 uint32_t count; 3806 3807 count = sizeof (emlxs_ffstate_table) / sizeof (emlxs_table_t); 3808 for (i = 0; i < count; i++) { 3809 if (state == emlxs_ffstate_table[i].code) { 3810 return (emlxs_ffstate_table[i].string); 3811 } 3812 } 3813 3814 (void) sprintf(buffer, "state=0x%x", state); 3815 return (buffer); 3816 3817 } /* emlxs_ffstate_xlate() */ 3818 3819 3820 extern char * 3821 emlxs_ring_xlate(uint32_t ringno) 3822 { 3823 static char buffer[32]; 3824 uint32_t i; 3825 uint32_t count; 3826 3827 count = sizeof (emlxs_ring_table) / sizeof (emlxs_table_t); 3828 for (i = 0; i < count; i++) { 3829 if (ringno == emlxs_ring_table[i].code) { 3830 return (emlxs_ring_table[i].string); 3831 } 3832 } 3833 3834 (void) sprintf(buffer, "ring=0x%x", ringno); 3835 return (buffer); 3836 3837 } /* emlxs_ring_xlate() */ 3838 3839 3840 3841 extern void 3842 emlxs_pcix_mxr_update(emlxs_hba_t *hba, uint32_t verbose) 3843 { 3844 emlxs_port_t *port = &PPORT; 3845 MAILBOX *mb; 3846 emlxs_config_t *cfg; 3847 uint32_t value; 3848 3849 cfg = &CFG; 3850 3851 xlate: 3852 3853 switch (cfg[CFG_PCI_MAX_READ].current) { 3854 case 512: 3855 value = 0; 3856 break; 3857 3858 case 1024: 3859 value = 1; 3860 break; 3861 3862 case 2048: 3863 value = 2; 3864 break; 3865 3866 case 4096: 3867 value = 3; 3868 break; 3869 3870 default: 3871 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg, 3872 "PCI_MAX_READ: Invalid parameter value. old=%d new=%d", 3873 cfg[CFG_PCI_MAX_READ].current, cfg[CFG_PCI_MAX_READ].def); 3874 3875 cfg[CFG_PCI_MAX_READ].current = cfg[CFG_PCI_MAX_READ].def; 3876 goto xlate; 3877 } 3878 3879 if ((mb = (MAILBOX *)emlxs_mem_get(hba, MEM_MBOX | MEM_PRI)) == 0) { 3880 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg, 3881 "PCI_MAX_READ: Unable to allocate mailbox buffer."); 3882 return; 3883 } 3884 3885 emlxs_mb_set_var(hba, (MAILBOX *)mb, 0x00100506, value); 3886 3887 if (emlxs_sli_issue_mbox_cmd(hba, mb, MBX_WAIT, 0) != MBX_SUCCESS) { 3888 if (verbose || (mb->mbxStatus != 0x12)) { 3889 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg, 3890 "PCI_MAX_READ: Unable to update. " 3891 "status=%x value=%d (%d bytes)", 3892 mb->mbxStatus, value, 3893 cfg[CFG_PCI_MAX_READ].current); 3894 } 3895 } else { 3896 if (verbose && 3897 (cfg[CFG_PCI_MAX_READ].current != 3898 cfg[CFG_PCI_MAX_READ].def)) { 3899 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg, 3900 "PCI_MAX_READ: Updated. %d bytes", 3901 cfg[CFG_PCI_MAX_READ].current); 3902 } 3903 } 3904 3905 (void) emlxs_mem_put(hba, MEM_MBOX, (uint8_t *)mb); 3906 3907 return; 3908 3909 } /* emlxs_pcix_mxr_update */ 3910 3911 3912 3913 extern uint32_t 3914 emlxs_get_key(emlxs_hba_t *hba, MAILBOX *mb) 3915 { 3916 emlxs_port_t *port = &PPORT; 3917 uint32_t npname0, npname1; 3918 uint32_t tmpkey, theKey; 3919 uint16_t key850; 3920 uint32_t t1, t2, t3, t4; 3921 uint32_t ts; 3922 3923 #define SEED 0x876EDC21 3924 3925 /* This key is only used currently for SBUS adapters */ 3926 if (hba->bus_type != SBUS_FC) { 3927 return (0); 3928 } 3929 3930 tmpkey = mb->un.varWords[30]; 3931 emlxs_ffstate_change(hba, FC_INIT_NVPARAMS); 3932 3933 emlxs_mb_read_nv(hba, mb); 3934 if (emlxs_sli_issue_mbox_cmd(hba, mb, MBX_WAIT, 0) != MBX_SUCCESS) { 3935 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg, 3936 "Unable to read nvram. cmd=%x status=%x", mb->mbxCommand, 3937 mb->mbxStatus); 3938 3939 return (0); 3940 } 3941 npname0 = mb->un.varRDnvp.portname[0]; 3942 npname1 = mb->un.varRDnvp.portname[1]; 3943 3944 key850 = (uint16_t)((tmpkey & 0x00FFFF00) >> 8); 3945 ts = (uint16_t)(npname1 + 1); 3946 t1 = ts * key850; 3947 ts = (uint16_t)((npname1 >> 16) + 1); 3948 t2 = ts * key850; 3949 ts = (uint16_t)(npname0 + 1); 3950 t3 = ts * key850; 3951 ts = (uint16_t)((npname0 >> 16) + 1); 3952 t4 = ts * key850; 3953 theKey = SEED + t1 + t2 + t3 + t4; 3954 3955 return (theKey); 3956 3957 } /* emlxs_get_key() */ 3958 3959 3960 extern void 3961 emlxs_fw_show(emlxs_hba_t *hba) 3962 { 3963 emlxs_port_t *port = &PPORT; 3964 uint32_t i; 3965 3966 /* Display firmware library one time */ 3967 for (i = 0; i < EMLXS_FW_COUNT; i++) { 3968 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_library_msg, "%s", 3969 emlxs_fw_table[i].label); 3970 } 3971 3972 return; 3973 3974 } /* emlxs_fw_show() */ 3975 3976 3977 #ifdef MODFW_SUPPORT 3978 static void 3979 emlxs_fw_load(emlxs_hba_t *hba, emlxs_firmware_t *fw) 3980 { 3981 emlxs_port_t *port = &PPORT; 3982 int (*emlxs_fw_get)(emlxs_firmware_t *); 3983 int err; 3984 3985 /* Make sure image is unloaded and image buffer pointer is clear */ 3986 emlxs_fw_unload(hba, fw); 3987 3988 err = 0; 3989 hba->fw_modhandle = 3990 ddi_modopen(EMLXS_FW_MODULE, KRTLD_MODE_FIRST, &err); 3991 if (!hba->fw_modhandle) { 3992 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg, 3993 "Unable to load firmware module. error=%d", err); 3994 3995 return; 3996 } else { 3997 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_msg, 3998 "Firmware module loaded."); 3999 } 4000 4001 err = 0; 4002 emlxs_fw_get = 4003 (int (*)())ddi_modsym(hba->fw_modhandle, "emlxs_fw_get", &err); 4004 if ((void *)emlxs_fw_get == NULL) { 4005 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg, 4006 "emlxs_fw_get not present. error=%d", err); 4007 4008 emlxs_fw_unload(hba, fw); 4009 return; 4010 } 4011 4012 if (emlxs_fw_get(fw)) { 4013 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg, 4014 "Invalid firmware image module found. %s", fw->label); 4015 4016 emlxs_fw_unload(hba, fw); 4017 return; 4018 } 4019 4020 return; 4021 4022 } /* emlxs_fw_load() */ 4023 4024 4025 static void 4026 emlxs_fw_unload(emlxs_hba_t *hba, emlxs_firmware_t *fw) 4027 { 4028 emlxs_port_t *port = &PPORT; 4029 4030 /* Clear the firmware image */ 4031 fw->image = NULL; 4032 fw->size = 0; 4033 4034 if (hba->fw_modhandle) { 4035 /* Close the module */ 4036 (void) ddi_modclose(hba->fw_modhandle); 4037 hba->fw_modhandle = NULL; 4038 4039 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_msg, 4040 "Firmware module unloaded."); 4041 } 4042 4043 return; 4044 4045 } /* emlxs_fw_unload() */ 4046 #endif /* MODFW_SUPPORT */ 4047