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