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 28 #define EMLXS_FW_TABLE_DEF 29 #define EMLXS_MODEL_DEF 30 31 #include <emlxs.h> 32 33 /* Required for EMLXS_CONTEXT in EMLXS_MSGF calls */ 34 EMLXS_MSG_DEF(EMLXS_HBA_C); 35 36 static uint32_t emlxs_decode_biu_rev(uint32_t rev); 37 static uint32_t emlxs_decode_endec_rev(uint32_t rev); 38 static void emlxs_handle_async_event(emlxs_hba_t *hba, CHANNEL *cp, 39 IOCBQ *iocbq); 40 41 #ifdef MSI_SUPPORT 42 uint32_t emlxs_msi_map[EMLXS_MSI_MODES][EMLXS_MSI_MAX_INTRS] = 43 {EMLXS_MSI_MAP1, EMLXS_MSI_MAP2, EMLXS_MSI_MAP4, EMLXS_MSI_MAP8}; 44 uint32_t emlxs_msi_mask[EMLXS_MSI_MODES] = 45 {EMLXS_MSI0_MASK1, EMLXS_MSI0_MASK2, EMLXS_MSI0_MASK4, 46 EMLXS_MSI0_MASK8}; 47 #endif /* MSI_SUPPORT */ 48 49 emlxs_firmware_t emlxs_fw_table[] = EMLXS_FW_TABLE; 50 int emlxs_fw_count = sizeof (emlxs_fw_table) / sizeof (emlxs_firmware_t); 51 52 emlxs_table_t emlxs_ring_table[] = { 53 {FC_FCP_RING, "FCP Ring"}, 54 {FC_IP_RING, "IP Ring"}, 55 {FC_ELS_RING, "ELS Ring"}, 56 {FC_CT_RING, "CT Ring"} 57 58 }; /* emlxs_ring_table */ 59 60 61 emlxs_table_t emlxs_ffstate_table[] = { 62 {0, "NULL"}, 63 {FC_ERROR, "ERROR"}, 64 {FC_KILLED, "KILLED"}, 65 {FC_WARM_START, "WARM_START"}, 66 {FC_INIT_START, "INIT_START"}, 67 {FC_INIT_NVPARAMS, "INIT_NVPARAMS"}, 68 {FC_INIT_REV, "INIT_REV"}, 69 {FC_INIT_CFGPORT, "INIT_CFGPORT"}, 70 {FC_INIT_CFGRING, "INIT_CFGRING"}, 71 {FC_INIT_INITLINK, "INIT_INITLINK"}, 72 {FC_LINK_DOWN, "LINK_DOWN"}, 73 {FC_LINK_UP, "LINK_UP"}, 74 {FC_CLEAR_LA, "CLEAR_LA"}, 75 {FC_READY, "READY"} 76 77 }; /* emlxs_ffstate_table */ 78 79 80 #ifdef MSI_SUPPORT 81 /* EMLXS_INTR_INIT */ 82 int32_t 83 emlxs_msi_init(emlxs_hba_t *hba, uint32_t max) 84 { 85 emlxs_port_t *port = &PPORT; 86 int32_t pass = 0; 87 int32_t type = 0; 88 char s_type[16]; 89 int32_t types; 90 int32_t count; 91 int32_t nintrs; 92 int32_t mode; 93 int32_t actual; 94 int32_t new_actual; 95 int32_t i; 96 int32_t ret; 97 ddi_intr_handle_t *htable = NULL; 98 ddi_intr_handle_t *new_htable = NULL; 99 uint32_t *intr_pri = NULL; 100 int32_t *intr_cap = NULL; 101 int32_t hilevel_pri; 102 emlxs_config_t *cfg = &CFG; 103 char buf[64]; 104 105 if (!(hba->intr_flags & EMLXS_MSI_ENABLED)) { 106 return (emlxs_intx_init(hba, max)); 107 } 108 109 if (hba->intr_flags & EMLXS_MSI_INITED) { 110 return (DDI_SUCCESS); 111 } 112 113 /* Set max interrupt count if not specified */ 114 if (max == 0) { 115 if ((cfg[CFG_MSI_MODE].current == 2) || 116 (cfg[CFG_MSI_MODE].current == 3)) { 117 max = EMLXS_MSI_MAX_INTRS; 118 } else { 119 max = 1; 120 } 121 } 122 123 /* Filter max interrupt count with adapter model specification */ 124 if (hba->model_info.intr_limit && (max > hba->model_info.intr_limit)) { 125 max = hba->model_info.intr_limit; 126 } 127 128 /* Get the available interrupt types from the kernel */ 129 types = 0; 130 ret = ddi_intr_get_supported_types(hba->dip, &types); 131 132 if ((ret != DDI_SUCCESS)) { 133 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg, 134 "MSI: ddi_intr_get_supported_types failed. ret=%d", ret); 135 136 /* Default to fixed type */ 137 types = DDI_INTR_TYPE_FIXED; 138 } 139 140 /* Check if fixed interrupts are being forced */ 141 if (cfg[CFG_MSI_MODE].current == 0) { 142 types &= DDI_INTR_TYPE_FIXED; 143 } 144 145 /* Check if MSI interrupts are being forced */ 146 else if ((cfg[CFG_MSI_MODE].current == 1) || 147 (cfg[CFG_MSI_MODE].current == 2)) { 148 types &= (DDI_INTR_TYPE_MSI | DDI_INTR_TYPE_FIXED); 149 } 150 151 begin: 152 153 /* Set interrupt type and interrupt count */ 154 type = 0; 155 156 /* Check if MSIX is fully supported */ 157 if ((types & DDI_INTR_TYPE_MSIX) && 158 (hba->model_info.flags & EMLXS_MSIX_SUPPORTED)) { 159 /* Get the max interrupt count from the adapter */ 160 nintrs = 0; 161 ret = 162 ddi_intr_get_nintrs(hba->dip, DDI_INTR_TYPE_MSIX, 163 &nintrs); 164 165 if (ret == DDI_SUCCESS && nintrs) { 166 type = DDI_INTR_TYPE_MSIX; 167 (void) strcpy(s_type, "TYPE_MSIX"); 168 goto initialize; 169 } 170 } 171 172 /* Check if MSI is fully supported */ 173 if ((types & DDI_INTR_TYPE_MSI) && 174 (hba->model_info.flags & EMLXS_MSI_SUPPORTED)) { 175 /* Get the max interrupt count from the adapter */ 176 nintrs = 0; 177 ret = 178 ddi_intr_get_nintrs(hba->dip, DDI_INTR_TYPE_MSI, &nintrs); 179 180 if (ret == DDI_SUCCESS && nintrs) { 181 type = DDI_INTR_TYPE_MSI; 182 (void) strcpy(s_type, "TYPE_MSI"); 183 goto initialize; 184 } 185 } 186 187 /* Check if fixed interrupts are fully supported */ 188 if ((types & DDI_INTR_TYPE_FIXED) && 189 (hba->model_info.flags & EMLXS_INTX_SUPPORTED)) { 190 /* Get the max interrupt count from the adapter */ 191 nintrs = 0; 192 ret = 193 ddi_intr_get_nintrs(hba->dip, DDI_INTR_TYPE_FIXED, 194 &nintrs); 195 196 if (ret == DDI_SUCCESS) { 197 type = DDI_INTR_TYPE_FIXED; 198 (void) strcpy(s_type, "TYPE_FIXED"); 199 goto initialize; 200 } 201 } 202 203 goto init_failed; 204 205 206 initialize: 207 208 pass++; 209 mode = 0; 210 actual = 0; 211 htable = NULL; 212 intr_pri = NULL; 213 intr_cap = NULL; 214 hilevel_pri = 0; 215 216 if (pass == 1) { 217 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg, 218 "MSI: %s: mode=%d types=0x%x nintrs=%d", s_type, 219 cfg[CFG_MSI_MODE].current, types, nintrs); 220 } 221 222 /* Validate interrupt count */ 223 count = min(nintrs, max); 224 225 if (count >= 8) { 226 count = 8; 227 } else if (count >= 4) { 228 count = 4; 229 } else if (count >= 2) { 230 count = 2; 231 } else { 232 count = 1; 233 } 234 235 /* Allocate an array of interrupt handles */ 236 htable = 237 kmem_alloc((size_t)(count * sizeof (ddi_intr_handle_t)), 238 KM_SLEEP); 239 240 /* Allocate 'count' interrupts */ 241 ret = 242 ddi_intr_alloc(hba->dip, htable, type, EMLXS_MSI_INUMBER, count, 243 &actual, DDI_INTR_ALLOC_NORMAL); 244 245 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg, 246 "MSI: %s: count=%d actual=%d ret=%d", s_type, count, actual, ret); 247 248 if ((ret != DDI_SUCCESS) || (actual == 0)) { 249 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg, 250 "MSI: Unable to allocate interrupts. error=%d", ret); 251 252 goto init_failed; 253 } 254 255 if (actual != count) { 256 /* Validate actual count */ 257 if (actual >= 8) { 258 new_actual = 8; 259 } else if (actual >= 4) { 260 new_actual = 4; 261 } else if (actual >= 2) { 262 new_actual = 2; 263 } else { 264 new_actual = 1; 265 } 266 267 if (new_actual < actual) { 268 /* Free extra handles */ 269 for (i = new_actual; i < actual; i++) { 270 (void) ddi_intr_free(htable[i]); 271 } 272 273 actual = new_actual; 274 } 275 276 /* Allocate a new array of interrupt handles */ 277 new_htable = 278 kmem_alloc((size_t)(actual * sizeof (ddi_intr_handle_t)), 279 KM_SLEEP); 280 281 /* Copy old array to new array */ 282 bcopy((uint8_t *)htable, (uint8_t *)new_htable, 283 (actual * sizeof (ddi_intr_handle_t))); 284 285 /* Free the old array */ 286 kmem_free(htable, (count * sizeof (ddi_intr_handle_t))); 287 288 htable = new_htable; 289 count = actual; 290 } 291 292 /* Allocate interrupt priority table */ 293 intr_pri = 294 (uint32_t *)kmem_alloc((size_t)(count * sizeof (uint32_t)), 295 KM_SLEEP); 296 297 /* Allocate interrupt capability table */ 298 intr_cap = kmem_alloc((size_t)(count * sizeof (uint32_t)), KM_SLEEP); 299 300 /* Get minimum hilevel priority */ 301 hilevel_pri = ddi_intr_get_hilevel_pri(); 302 303 /* Fill the priority and capability tables */ 304 for (i = 0; i < count; ++i) { 305 ret = ddi_intr_get_pri(htable[i], &intr_pri[i]); 306 307 if (ret != DDI_SUCCESS) { 308 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg, 309 "MSI: ddi_intr_get_pri(%d) failed. " 310 "handle=%p ret=%d", 311 i, &htable[i], ret); 312 313 /* Clean up the interrupts */ 314 goto init_failed; 315 } 316 317 if (intr_pri[i] >= hilevel_pri) { 318 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg, 319 "MSI: Interrupt(%d) level too high. " 320 "pri=0x%x hilevel=0x%x", 321 i, intr_pri[i], hilevel_pri); 322 323 /* Clean up the interrupts */ 324 goto init_failed; 325 } 326 327 ret = ddi_intr_get_cap(htable[i], &intr_cap[i]); 328 329 if (ret != DDI_SUCCESS) { 330 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg, 331 "MSI: ddi_intr_get_cap(%d) failed. " 332 "handle=%p ret=%d", 333 i, &htable[i], ret); 334 335 /* Clean up the interrupts */ 336 goto init_failed; 337 } 338 339 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg, 340 "MSI: %s: %d: cap=0x%x pri=0x%x hilevel=0x%x", s_type, i, 341 intr_cap[i], intr_pri[i], hilevel_pri); 342 343 } 344 345 /* Set mode */ 346 switch (count) { 347 case 8: 348 mode = EMLXS_MSI_MODE8; 349 break; 350 351 case 4: 352 mode = EMLXS_MSI_MODE4; 353 break; 354 355 case 2: 356 mode = EMLXS_MSI_MODE2; 357 break; 358 359 default: 360 mode = EMLXS_MSI_MODE1; 361 } 362 363 /* Save the info */ 364 hba->intr_htable = htable; 365 hba->intr_count = count; 366 hba->intr_pri = intr_pri; 367 hba->intr_cap = intr_cap; 368 hba->intr_type = type; 369 hba->intr_arg = (void *)((unsigned long)intr_pri[0]); 370 hba->intr_mask = emlxs_msi_mask[mode]; 371 372 hba->intr_cond = 0; 373 374 /* Adjust number of channels based on intr_count */ 375 if (hba->sli_mode == EMLXS_HBA_SLI4_MODE) { 376 hba->chan_count = hba->intr_count * cfg[CFG_NUM_WQ].current; 377 } 378 379 for (i = 0; i < EMLXS_MSI_MAX_INTRS; i++) { 380 hba->intr_map[i] = emlxs_msi_map[mode][i]; 381 hba->intr_cond |= emlxs_msi_map[mode][i]; 382 383 (void) sprintf(buf, "%s%d_msi%d mutex", DRIVER_NAME, 384 hba->ddiinst, i); 385 mutex_init(&hba->intr_lock[i], buf, MUTEX_DRIVER, 386 (void *)hba->intr_arg); 387 } 388 389 /* Set flag to indicate support */ 390 hba->intr_flags |= EMLXS_MSI_INITED; 391 392 /* Create the interrupt threads */ 393 for (i = 0; i < hba->chan_count; i++) { 394 (void) sprintf(buf, "%s%d_channel%d mutex", DRIVER_NAME, 395 hba->ddiinst, i); 396 mutex_init(&hba->chan[i].rsp_lock, buf, MUTEX_DRIVER, 397 (void *)hba->intr_arg); 398 399 emlxs_thread_create(hba, &hba->chan[i].intr_thread); 400 } 401 402 return (DDI_SUCCESS); 403 404 init_failed: 405 406 if (intr_cap) { 407 kmem_free(intr_cap, (count * sizeof (int32_t))); 408 } 409 410 if (intr_pri) { 411 kmem_free(intr_pri, (count * sizeof (int32_t))); 412 } 413 414 if (htable) { 415 /* Process the interrupt handlers */ 416 for (i = 0; i < actual; i++) { 417 /* Free the handle[i] */ 418 (void) ddi_intr_free(htable[i]); 419 } 420 421 kmem_free(htable, (count * sizeof (ddi_intr_handle_t))); 422 } 423 424 /* Initialize */ 425 hba->intr_htable = NULL; 426 hba->intr_count = 0; 427 hba->intr_pri = NULL; 428 hba->intr_cap = NULL; 429 hba->intr_type = 0; 430 hba->intr_arg = NULL; 431 hba->intr_cond = 0; 432 bzero(hba->intr_map, sizeof (hba->intr_map)); 433 bzero(hba->intr_lock, sizeof (hba->intr_lock)); 434 435 if (type == DDI_INTR_TYPE_MSIX) { 436 types &= (DDI_INTR_TYPE_MSI | DDI_INTR_TYPE_FIXED); 437 goto begin; 438 } else if (type == DDI_INTR_TYPE_MSI) { 439 types &= DDI_INTR_TYPE_FIXED; 440 goto begin; 441 } 442 443 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg, 444 "MSI: Unable to initialize interrupts"); 445 446 return (DDI_FAILURE); 447 448 449 } /* emlxs_msi_init() */ 450 451 452 /* EMLXS_INTR_UNINIT */ 453 int32_t 454 emlxs_msi_uninit(emlxs_hba_t *hba) 455 { 456 uint32_t count; 457 int32_t i; 458 ddi_intr_handle_t *htable; 459 uint32_t *intr_pri; 460 int32_t *intr_cap; 461 int32_t ret; 462 463 if (!(hba->intr_flags & EMLXS_MSI_ENABLED)) { 464 return (emlxs_intx_uninit(hba)); 465 } 466 467 /* 468 * EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg, 469 * "MSI: emlxs_msi_uninit called. flags=%x", 470 * hba->intr_flags); 471 */ 472 473 /* Make sure interrupts have been removed first */ 474 if ((hba->intr_flags & EMLXS_MSI_ADDED)) { 475 ret = emlxs_msi_remove(hba); 476 477 if (ret != DDI_SUCCESS) { 478 return (ret); 479 } 480 } 481 482 /* Check if the interrupts are still initialized */ 483 if (!(hba->intr_flags & EMLXS_MSI_INITED)) { 484 return (DDI_SUCCESS); 485 } 486 hba->intr_flags &= ~EMLXS_MSI_INITED; 487 488 /* Get handle table parameters */ 489 htable = hba->intr_htable; 490 count = hba->intr_count; 491 intr_pri = hba->intr_pri; 492 intr_cap = hba->intr_cap; 493 494 /* Clean up */ 495 hba->intr_count = 0; 496 hba->intr_htable = NULL; 497 hba->intr_pri = NULL; 498 hba->intr_cap = NULL; 499 hba->intr_type = 0; 500 hba->intr_arg = NULL; 501 hba->intr_cond = 0; 502 bzero(hba->intr_map, sizeof (hba->intr_map)); 503 504 if (intr_cap) { 505 kmem_free(intr_cap, (count * sizeof (int32_t))); 506 } 507 508 if (intr_pri) { 509 kmem_free(intr_pri, (count * sizeof (int32_t))); 510 } 511 512 if (htable) { 513 /* Process the interrupt handlers */ 514 for (i = 0; i < count; ++i) { 515 /* Free the handle[i] */ 516 ret = ddi_intr_free(htable[i]); 517 } 518 519 kmem_free(htable, (count * sizeof (ddi_intr_handle_t))); 520 } 521 522 /* Destroy the intr locks */ 523 for (i = 0; i < EMLXS_MSI_MAX_INTRS; i++) { 524 mutex_destroy(&hba->intr_lock[i]); 525 } 526 527 /* Destroy the interrupt threads */ 528 for (i = 0; i < hba->chan_count; i++) { 529 emlxs_thread_destroy(&hba->chan[i].intr_thread); 530 mutex_destroy(&hba->chan[i].rsp_lock); 531 } 532 533 /* 534 * EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg, 535 * "MSI: emlxs_msi_uninit done. flags=%x", 536 * hba->intr_flags); 537 */ 538 539 return (DDI_SUCCESS); 540 541 } /* emlxs_msi_uninit() */ 542 543 544 /* EMLXS_INTR_ADD */ 545 int32_t 546 emlxs_msi_add(emlxs_hba_t *hba) 547 { 548 emlxs_port_t *port = &PPORT; 549 int32_t count; 550 int32_t i; 551 int32_t ret; 552 ddi_intr_handle_t *htable = NULL; 553 int32_t *intr_cap = NULL; 554 555 if (!(hba->intr_flags & EMLXS_MSI_ENABLED)) { 556 return (emlxs_intx_add(hba)); 557 } 558 559 /* Check if interrupts have already been added */ 560 if (hba->intr_flags & EMLXS_MSI_ADDED) { 561 return (DDI_SUCCESS); 562 } 563 564 /* Check if interrupts have been initialized */ 565 if (!(hba->intr_flags & EMLXS_MSI_INITED)) { 566 ret = emlxs_msi_init(hba, 0); 567 568 if (ret != DDI_SUCCESS) { 569 return (ret); 570 } 571 } 572 573 /* Get handle table parameters */ 574 htable = hba->intr_htable; 575 count = hba->intr_count; 576 intr_cap = hba->intr_cap; 577 578 /* Add the interrupt handlers */ 579 for (i = 0; i < count; ++i) { 580 /* add handler for handle[i] */ 581 ret = 582 ddi_intr_add_handler(htable[i], EMLXS_SLI_MSI_INTR, 583 (char *)hba, (char *)((unsigned long)i)); 584 585 if (ret != DDI_SUCCESS) { 586 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg, 587 "MSI: ddi_intr_add_handler(%d) failed. " 588 "handle=%p ret=%d", 589 i, &htable[i], ret); 590 591 /* Process the remaining interrupt handlers */ 592 while (i) { 593 /* Decrement i */ 594 i--; 595 596 /* Remove the handler */ 597 ret = ddi_intr_remove_handler(htable[i]); 598 599 } 600 601 return (DDI_FAILURE); 602 } 603 } 604 605 /* Enable the interrupts */ 606 if (intr_cap[0] & DDI_INTR_FLAG_BLOCK) { 607 ret = ddi_intr_block_enable(htable, count); 608 609 if (ret != DDI_SUCCESS) { 610 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg, 611 "MSI: ddi_intr_block_enable(%d) failed. ret=%d", 612 count, ret); 613 614 for (i = 0; i < count; ++i) { 615 ret = ddi_intr_enable(htable[i]); 616 617 if (ret != DDI_SUCCESS) { 618 EMLXS_MSGF(EMLXS_CONTEXT, 619 &emlxs_init_debug_msg, 620 "MSI: ddi_intr_enable(%d) failed. " 621 "ret=%d", 622 i, ret); 623 } 624 } 625 } 626 } else { 627 for (i = 0; i < count; ++i) { 628 ret = ddi_intr_enable(htable[i]); 629 630 if (ret != DDI_SUCCESS) { 631 EMLXS_MSGF(EMLXS_CONTEXT, 632 &emlxs_init_debug_msg, 633 "MSI: ddi_intr_enable(%d) failed. ret=%d", 634 i, ret); 635 } 636 } 637 } 638 639 640 /* Set flag to indicate support */ 641 hba->intr_flags |= EMLXS_MSI_ADDED; 642 643 return (DDI_SUCCESS); 644 645 } /* emlxs_msi_add() */ 646 647 648 649 /* EMLXS_INTR_REMOVE */ 650 int32_t 651 emlxs_msi_remove(emlxs_hba_t *hba) 652 { 653 emlxs_port_t *port = &PPORT; 654 uint32_t count; 655 int32_t i; 656 ddi_intr_handle_t *htable; 657 int32_t *intr_cap; 658 int32_t ret; 659 660 if (!(hba->intr_flags & EMLXS_MSI_ENABLED)) { 661 return (emlxs_intx_remove(hba)); 662 } 663 664 /* 665 * EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg, 666 * "MSI: emlxs_msi_remove called. flags=%x", 667 * hba->intr_flags); 668 */ 669 670 /* Check if interrupts have already been removed */ 671 if (!(hba->intr_flags & EMLXS_MSI_ADDED)) { 672 return (DDI_SUCCESS); 673 } 674 hba->intr_flags &= ~EMLXS_MSI_ADDED; 675 676 /* Disable all adapter interrupts */ 677 EMLXS_SLI_DISABLE_INTR(hba, 0); 678 679 /* Get handle table parameters */ 680 htable = hba->intr_htable; 681 count = hba->intr_count; 682 intr_cap = hba->intr_cap; 683 684 /* Disable the interrupts */ 685 if (intr_cap[0] & DDI_INTR_FLAG_BLOCK) { 686 ret = ddi_intr_block_disable(htable, count); 687 688 if (ret != DDI_SUCCESS) { 689 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg, 690 "MSI: ddi_intr_block_disable(%d) failed. ret=%d", 691 count, ret); 692 693 for (i = 0; i < count; i++) { 694 ret = ddi_intr_disable(htable[i]); 695 696 if (ret != DDI_SUCCESS) { 697 EMLXS_MSGF(EMLXS_CONTEXT, 698 &emlxs_init_debug_msg, 699 "MSI: ddi_intr_disable(%d) failed. " 700 "ret=%d", 701 i, ret); 702 } 703 } 704 } 705 } else { 706 for (i = 0; i < count; i++) { 707 ret = ddi_intr_disable(htable[i]); 708 709 if (ret != DDI_SUCCESS) { 710 EMLXS_MSGF(EMLXS_CONTEXT, 711 &emlxs_init_debug_msg, 712 "MSI: ddi_intr_disable(%d) failed. ret=%d", 713 i, ret); 714 } 715 } 716 } 717 718 /* Process the interrupt handlers */ 719 for (i = 0; i < count; i++) { 720 /* Remove the handler */ 721 ret = ddi_intr_remove_handler(htable[i]); 722 723 724 } 725 726 return (DDI_SUCCESS); 727 728 } /* emlxs_msi_remove() */ 729 730 #endif /* MSI_SUPPORT */ 731 732 733 /* EMLXS_INTR_INIT */ 734 /* ARGSUSED */ 735 int32_t 736 emlxs_intx_init(emlxs_hba_t *hba, uint32_t max) 737 { 738 emlxs_port_t *port = &PPORT; 739 emlxs_config_t *cfg = &CFG; 740 int32_t ret; 741 uint32_t i; 742 char buf[64]; 743 744 /* Check if interrupts have already been initialized */ 745 if (hba->intr_flags & EMLXS_INTX_INITED) { 746 return (DDI_SUCCESS); 747 } 748 749 /* Check if adapter is flagged for INTX support */ 750 if (!(hba->model_info.flags & EMLXS_INTX_SUPPORTED)) { 751 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg, 752 "INTX: %s does not support INTX. flags=0x%x", 753 hba->model_info.model, hba->model_info.flags); 754 755 return (DDI_FAILURE); 756 } 757 758 /* 759 * Interrupt number '0' is a high-level interrupt. This driver 760 * does not support having its interrupts mapped above scheduler 761 * priority; i.e., we always expect to be able to call general 762 * kernel routines that may invoke the scheduler. 763 */ 764 if (ddi_intr_hilevel(hba->dip, EMLXS_INUMBER) != 0) { 765 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg, 766 "INTX: High-level interrupt not supported."); 767 768 return (DDI_FAILURE); 769 } 770 771 /* Get an iblock cookie */ 772 ret = 773 ddi_get_iblock_cookie(hba->dip, (uint32_t)EMLXS_INUMBER, 774 (ddi_iblock_cookie_t *)&hba->intr_arg); 775 if (ret != DDI_SUCCESS) { 776 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg, 777 "INTX: ddi_get_iblock_cookie failed. ret=%d", ret); 778 779 return (ret); 780 } 781 782 hba->intr_flags |= EMLXS_INTX_INITED; 783 784 hba->intr_count = 1; 785 /* Adjust number of channels based on intr_count */ 786 if (hba->sli_mode == EMLXS_HBA_SLI4_MODE) { 787 hba->chan_count = cfg[CFG_NUM_WQ].current; 788 } 789 790 /* Create the interrupt threads */ 791 for (i = 0; i < hba->chan_count; i++) { 792 (void) sprintf(buf, "%s%d_channel%d mutex", DRIVER_NAME, 793 hba->ddiinst, i); 794 mutex_init(&hba->chan[i].rsp_lock, buf, MUTEX_DRIVER, 795 (void *)hba->intr_arg); 796 797 emlxs_thread_create(hba, &hba->chan[i].intr_thread); 798 } 799 800 return (DDI_SUCCESS); 801 802 } /* emlxs_intx_init() */ 803 804 805 /* EMLXS_INTR_UNINIT */ 806 int32_t 807 emlxs_intx_uninit(emlxs_hba_t *hba) 808 { 809 int32_t ret; 810 uint32_t i; 811 812 /* Make sure interrupts have been removed */ 813 if ((hba->intr_flags & EMLXS_INTX_ADDED)) { 814 ret = emlxs_intx_remove(hba); 815 816 if (ret != DDI_SUCCESS) { 817 return (ret); 818 } 819 } 820 821 /* Check if the interrupts are still initialized */ 822 if (!(hba->intr_flags & EMLXS_INTX_INITED)) { 823 return (DDI_SUCCESS); 824 } 825 hba->intr_flags &= ~EMLXS_INTX_INITED; 826 827 hba->intr_arg = NULL; 828 829 /* Create the interrupt threads */ 830 for (i = 0; i < hba->chan_count; i++) { 831 emlxs_thread_destroy(&hba->chan[i].intr_thread); 832 mutex_destroy(&hba->chan[i].rsp_lock); 833 } 834 835 return (DDI_SUCCESS); 836 837 } /* emlxs_intx_uninit() */ 838 839 840 /* 841 * This is the legacy method for adding interrupts in Solaris 842 * EMLXS_INTR_ADD 843 */ 844 int32_t 845 emlxs_intx_add(emlxs_hba_t *hba) 846 { 847 emlxs_port_t *port = &PPORT; 848 int32_t ret; 849 850 /* Check if interrupts have already been added */ 851 if (hba->intr_flags & EMLXS_INTX_ADDED) { 852 return (DDI_SUCCESS); 853 } 854 855 /* Check if interrupts have been initialized */ 856 if (!(hba->intr_flags & EMLXS_INTX_INITED)) { 857 ret = emlxs_intx_init(hba, 0); 858 859 if (ret != DDI_SUCCESS) { 860 return (ret); 861 } 862 } 863 864 /* add intrrupt handler routine */ 865 ret = ddi_add_intr((void *)hba->dip, 866 (uint_t)EMLXS_INUMBER, 867 (ddi_iblock_cookie_t *)&hba->intr_arg, 868 (ddi_idevice_cookie_t *)0, 869 (uint_t(*)())EMLXS_SLI_INTX_INTR, (caddr_t)hba); 870 871 if (ret != DDI_SUCCESS) { 872 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_failed_msg, 873 "INTX: ddi_add_intr failed. ret=%d", ret); 874 875 return (ret); 876 } 877 878 hba->intr_flags |= EMLXS_INTX_ADDED; 879 880 return (DDI_SUCCESS); 881 882 } /* emlxs_intx_add() */ 883 884 885 /* EMLXS_INTR_REMOVE */ 886 int32_t 887 emlxs_intx_remove(emlxs_hba_t *hba) 888 { 889 /* Check if interrupts have already been removed */ 890 if (!(hba->intr_flags & EMLXS_INTX_ADDED)) { 891 return (DDI_SUCCESS); 892 } 893 hba->intr_flags &= ~EMLXS_INTX_ADDED; 894 895 /* Diable all adapter interrupts */ 896 EMLXS_SLI_DISABLE_INTR(hba, 0); 897 898 /* Remove the interrupt */ 899 (void) ddi_remove_intr((void *)hba->dip, (uint_t)EMLXS_INUMBER, 900 hba->intr_arg); 901 902 return (DDI_SUCCESS); 903 904 } /* emlxs_intx_remove() */ 905 906 907 extern void 908 emlxs_process_link_speed(emlxs_hba_t *hba) 909 { 910 emlxs_vpd_t *vpd; 911 emlxs_config_t *cfg; 912 char *cptr; 913 uint32_t hi; 914 915 /* 916 * This routine modifies the link-speed config parameter entry 917 * based on adapter capabilities 918 */ 919 vpd = &VPD; 920 cfg = &hba->config[CFG_LINK_SPEED]; 921 922 cptr = cfg->help; 923 (void) strcpy(cptr, "Select link speed. [0=Auto"); 924 cptr += 26; 925 hi = 0; 926 927 if (vpd->link_speed & LMT_1GB_CAPABLE) { 928 (void) strcpy(cptr, ", 1=1Gb"); 929 cptr += 7; 930 hi = 1; 931 } 932 933 if (vpd->link_speed & LMT_2GB_CAPABLE) { 934 (void) strcpy(cptr, ", 2=2Gb"); 935 cptr += 7; 936 hi = 2; 937 } 938 939 if (vpd->link_speed & LMT_4GB_CAPABLE) { 940 (void) strcpy(cptr, ", 4=4Gb"); 941 cptr += 7; 942 hi = 4; 943 } 944 945 if (vpd->link_speed & LMT_8GB_CAPABLE) { 946 (void) strcpy(cptr, ", 8=8Gb"); 947 cptr += 7; 948 hi = 8; 949 } 950 951 if (vpd->link_speed & LMT_10GB_CAPABLE) { 952 (void) strcpy(cptr, ", 10=10Gb"); 953 cptr += 9; 954 hi = 10; 955 } 956 957 (void) strcpy(cptr, "]"); 958 cfg->hi = hi; 959 960 /* Now revalidate the current parameter setting */ 961 cfg->current = emlxs_check_parm(hba, CFG_LINK_SPEED, cfg->current); 962 963 return; 964 965 } /* emlxs_process_link_speed() */ 966 967 968 /* 969 * emlxs_parse_vpd() 970 * 971 * This routine will parse the VPD data 972 */ 973 extern int 974 emlxs_parse_vpd(emlxs_hba_t *hba, uint8_t *vpd_buf, uint32_t size) 975 { 976 emlxs_port_t *port = &PPORT; 977 char tag[3]; 978 uint8_t lenlo, lenhi; 979 uint32_t n; 980 uint16_t block_size; 981 uint32_t block_index = 0; 982 uint8_t sub_size; 983 uint32_t sub_index; 984 int32_t finished = 0; 985 int32_t index = 0; 986 char buffer[128]; 987 emlxs_vpd_t *vpd; 988 989 vpd = &VPD; 990 991 992 while (!finished && (block_index < size)) { 993 /* 994 * EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_vpd_msg, 995 * "block_index = %x", block_index); 996 */ 997 998 switch (vpd_buf[block_index]) { 999 case 0x82: 1000 index = block_index; 1001 index += 1; 1002 lenlo = vpd_buf[index]; 1003 index += 1; 1004 lenhi = vpd_buf[index]; 1005 index += 1; 1006 block_index = index; 1007 1008 block_size = ((((uint16_t)lenhi) << 8) + lenlo); 1009 block_index += block_size; 1010 1011 /* 1012 * EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_vpd_msg, 1013 * "block_size = %x", block_size); 1014 */ 1015 1016 n = sizeof (buffer); 1017 bzero(buffer, n); 1018 bcopy(&vpd_buf[index], buffer, 1019 (block_size < (n - 1)) ? block_size : (n - 1)); 1020 1021 (void) strcpy(vpd->id, buffer); 1022 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_vpd_msg, "ID: %s", 1023 vpd->id); 1024 1025 break; 1026 1027 case 0x90: 1028 index = block_index; 1029 index += 1; 1030 lenlo = vpd_buf[index]; 1031 index += 1; 1032 lenhi = vpd_buf[index]; 1033 index += 1; 1034 block_index = index; 1035 sub_index = index; 1036 1037 block_size = ((((uint16_t)lenhi) << 8) + lenlo); 1038 block_index += block_size; 1039 1040 /* 1041 * EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_vpd_msg, 1042 * "block_size = %x", block_size); 1043 */ 1044 1045 /* Scan for sub-blocks */ 1046 while ((sub_index < block_index) && 1047 (sub_index < size)) { 1048 /* 1049 * EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_vpd_msg, 1050 * "sub_index = %x", sub_index); 1051 */ 1052 1053 index = sub_index; 1054 tag[0] = vpd_buf[index++]; 1055 tag[1] = vpd_buf[index++]; 1056 tag[2] = 0; 1057 sub_size = vpd_buf[index++]; 1058 1059 /* 1060 * EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_vpd_msg, 1061 * "sub_size = %x", sub_size); 1062 */ 1063 1064 sub_index = (index + sub_size); 1065 1066 n = sizeof (buffer); 1067 bzero(buffer, n); 1068 bcopy(&vpd_buf[index], buffer, 1069 (sub_size < (n - 1)) ? sub_size : (n - 1)); 1070 1071 /* 1072 * Look for Engineering Change (EC) 1073 */ 1074 if (strcmp(tag, "EC") == 0) { 1075 (void) strcpy(vpd->eng_change, buffer); 1076 EMLXS_MSGF(EMLXS_CONTEXT, 1077 &emlxs_vpd_msg, "EC: %s", 1078 vpd->eng_change); 1079 } 1080 /* 1081 * Look for Manufacturer (MN) 1082 */ 1083 else if (strcmp(tag, "MN") == 0) { 1084 (void) strcpy(vpd->manufacturer, 1085 buffer); 1086 EMLXS_MSGF(EMLXS_CONTEXT, 1087 &emlxs_vpd_msg, "MN: %s", 1088 vpd->manufacturer); 1089 } 1090 /* 1091 * Look for Serial Number (SN) 1092 */ 1093 else if (strcmp(tag, "SN") == 0) { 1094 (void) strcpy(vpd->serial_num, buffer); 1095 EMLXS_MSGF(EMLXS_CONTEXT, 1096 &emlxs_vpd_msg, "SN: %s", 1097 vpd->serial_num); 1098 1099 /* Validate the serial number */ 1100 if (strncmp(buffer, "FFFFFFFFFF", 10) == 1101 0 || 1102 strncmp(buffer, "0000000000", 10) == 1103 0) { 1104 vpd->serial_num[0] = 0; 1105 } 1106 } 1107 /* 1108 * Look for Part Number (PN) 1109 */ 1110 else if (strcmp(tag, "PN") == 0) { 1111 (void) strcpy(vpd->part_num, buffer); 1112 EMLXS_MSGF(EMLXS_CONTEXT, 1113 &emlxs_vpd_msg, "PN: %s", 1114 vpd->part_num); 1115 } 1116 /* 1117 * Look for (V0) 1118 */ 1119 else if (strcmp(tag, "V0") == 0) { 1120 /* Not used */ 1121 EMLXS_MSGF(EMLXS_CONTEXT, 1122 &emlxs_vpd_msg, "V0: %s", buffer); 1123 } 1124 /* 1125 * Look for model description (V1) 1126 */ 1127 else if (strcmp(tag, "V1") == 0) { 1128 (void) strcpy(vpd->model_desc, buffer); 1129 EMLXS_MSGF(EMLXS_CONTEXT, 1130 &emlxs_vpd_msg, "Desc: %s", 1131 vpd->model_desc); 1132 } 1133 /* 1134 * Look for model (V2) 1135 */ 1136 else if (strcmp(tag, "V2") == 0) { 1137 (void) strcpy(vpd->model, buffer); 1138 EMLXS_MSGF(EMLXS_CONTEXT, 1139 &emlxs_vpd_msg, "Model: %s", 1140 vpd->model); 1141 } 1142 /* 1143 * Look for program type (V3) 1144 */ 1145 1146 else if (strcmp(tag, "V3") == 0) { 1147 (void) strcpy(vpd->prog_types, buffer); 1148 EMLXS_MSGF(EMLXS_CONTEXT, 1149 &emlxs_vpd_msg, "Prog Types: %s", 1150 vpd->prog_types); 1151 } 1152 /* 1153 * Look for port number (V4) 1154 */ 1155 else if (strcmp(tag, "V4") == 0) { 1156 (void) strcpy(vpd->port_num, buffer); 1157 vpd->port_index = 1158 emlxs_strtol(vpd->port_num, 10); 1159 1160 EMLXS_MSGF(EMLXS_CONTEXT, 1161 &emlxs_vpd_msg, "Port: %s", 1162 (vpd->port_num[0]) ? vpd-> 1163 port_num : "not applicable"); 1164 } 1165 /* 1166 * Look for checksum (RV) 1167 */ 1168 else if (strcmp(tag, "RV") == 0) { 1169 /* Not used */ 1170 EMLXS_MSGF(EMLXS_CONTEXT, 1171 &emlxs_vpd_msg, "Checksum: 0x%x", 1172 buffer[0]); 1173 } 1174 1175 else { 1176 /* Generic */ 1177 EMLXS_MSGF(EMLXS_CONTEXT, 1178 &emlxs_vpd_msg, "Tag: %s: %s", 1179 tag, buffer); 1180 } 1181 } 1182 1183 break; 1184 1185 case 0x78: 1186 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_vpd_msg, "End Tag."); 1187 finished = 1; 1188 break; 1189 1190 default: 1191 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_vpd_msg, 1192 "Unknown block: %x %x %x %x %x %x %x %x", 1193 vpd_buf[index], vpd_buf[index + 1], 1194 vpd_buf[index + 2], vpd_buf[index + 3], 1195 vpd_buf[index + 4], vpd_buf[index + 5], 1196 vpd_buf[index + 6], vpd_buf[index + 7]); 1197 return (0); 1198 } 1199 } 1200 1201 return (1); 1202 1203 } /* emlxs_parse_vpd */ 1204 1205 1206 /* 1207 * emlxs_parse_fcoe() 1208 * 1209 * This routine will parse the VPD data 1210 */ 1211 extern int 1212 emlxs_parse_fcoe(emlxs_hba_t *hba, uint8_t *fcoep, uint32_t size) 1213 { 1214 emlxs_port_t *port = &PPORT; 1215 tlv_fcoe_t *fcoelist; 1216 tlv_fcfconnectlist_t *fcflist; 1217 int i; 1218 1219 /* Validate the config region 23 signature */ 1220 if ((*fcoep != 'R') || (*(fcoep+1) != 'G') || 1221 (*(fcoep+2) != '2') || (*(fcoep+3) != '3')) { 1222 return (0); 1223 } 1224 1225 /* Search the config region 23, for FCOE Parameters record */ 1226 i = 4; 1227 while ((i < size) && (*(fcoep+i) != 0xA0) && (*(fcoep+i) != 0xff)) { 1228 i += fcoep[i+1] * sizeof (uint32_t) + 2; 1229 } 1230 1231 if (*(fcoep+i) == 0xA0) { 1232 fcoelist = (tlv_fcoe_t *)(fcoep+i); 1233 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_vpd_msg, 1234 "Found FCOE Params (A0):%d x%x", 1235 fcoelist->length, fcoelist->fip_flags); 1236 bcopy((uint8_t *)fcoelist, (uint8_t *)&hba->sli.sli4.cfgFCOE, 1237 sizeof (tlv_fcoe_t)); 1238 } 1239 1240 1241 /* Search the config region 23, for FCF record */ 1242 i = 4; 1243 while ((i < size) && (*(fcoep+i) != 0xA1) && (*(fcoep+i) != 0xff)) { 1244 i += fcoep[i+1] * sizeof (uint32_t) + 2; 1245 } 1246 1247 if (*(fcoep+i) == 0xA1) { 1248 fcflist = (tlv_fcfconnectlist_t *)(fcoep+i); 1249 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_vpd_msg, 1250 "Found FCF ConnectList (A1):%d", fcflist->length); 1251 bcopy((uint8_t *)fcflist, (uint8_t *)&hba->sli.sli4.cfgFCF, 1252 sizeof (tlv_fcfconnectlist_t)); 1253 } 1254 1255 return (1); 1256 1257 } /* emlxs_parse_fcoe */ 1258 1259 1260 1261 static uint32_t 1262 emlxs_decode_biu_rev(uint32_t rev) 1263 { 1264 return (rev & 0xf); 1265 } /* End emlxs_decode_biu_rev */ 1266 1267 1268 static uint32_t 1269 emlxs_decode_endec_rev(uint32_t rev) 1270 { 1271 return ((rev >> 28) & 0xf); 1272 } /* End emlxs_decode_endec_rev */ 1273 1274 1275 extern void 1276 emlxs_decode_firmware_rev(emlxs_hba_t *hba, emlxs_vpd_t *vpd) 1277 { 1278 if (vpd->rBit) { 1279 switch (hba->sli_mode) { 1280 case EMLXS_HBA_SLI4_MODE: 1281 (void) strcpy(vpd->fw_version, vpd->sli4FwName); 1282 (void) strcpy(vpd->fw_label, vpd->sli4FwLabel); 1283 break; 1284 case EMLXS_HBA_SLI3_MODE: 1285 (void) strcpy(vpd->fw_version, vpd->sli3FwName); 1286 (void) strcpy(vpd->fw_label, vpd->sli3FwLabel); 1287 break; 1288 case EMLXS_HBA_SLI2_MODE: 1289 (void) strcpy(vpd->fw_version, vpd->sli2FwName); 1290 (void) strcpy(vpd->fw_label, vpd->sli2FwLabel); 1291 break; 1292 case EMLXS_HBA_SLI1_MODE: 1293 (void) strcpy(vpd->fw_version, vpd->sli1FwName); 1294 (void) strcpy(vpd->fw_label, vpd->sli1FwLabel); 1295 break; 1296 default: 1297 (void) strcpy(vpd->fw_version, "unknown"); 1298 (void) strcpy(vpd->fw_label, vpd->fw_version); 1299 } 1300 } else { 1301 emlxs_decode_version(vpd->smFwRev, vpd->fw_version); 1302 (void) strcpy(vpd->fw_label, vpd->fw_version); 1303 } 1304 1305 return; 1306 1307 } /* emlxs_decode_firmware_rev() */ 1308 1309 1310 1311 extern void 1312 emlxs_decode_version(uint32_t version, char *buffer) 1313 { 1314 uint32_t b1, b2, b3, b4; 1315 char c; 1316 1317 b1 = (version & 0x0000f000) >> 12; 1318 b2 = (version & 0x00000f00) >> 8; 1319 b3 = (version & 0x000000c0) >> 6; 1320 b4 = (version & 0x00000030) >> 4; 1321 1322 if (b1 == 0 && b2 == 0) { 1323 (void) sprintf(buffer, "none"); 1324 return; 1325 } 1326 1327 c = 0; 1328 switch (b4) { 1329 case 0: 1330 c = 'n'; 1331 break; 1332 case 1: 1333 c = 'a'; 1334 break; 1335 case 2: 1336 c = 'b'; 1337 break; 1338 case 3: 1339 if ((version & 0x0000000f)) { 1340 c = 'x'; 1341 } 1342 break; 1343 1344 } 1345 b4 = (version & 0x0000000f); 1346 1347 if (c == 0) { 1348 (void) sprintf(buffer, "%d.%d%d", b1, b2, b3); 1349 } else { 1350 (void) sprintf(buffer, "%d.%d%d%c%d", b1, b2, b3, c, b4); 1351 } 1352 1353 return; 1354 1355 } /* emlxs_decode_version() */ 1356 1357 1358 extern void 1359 emlxs_decode_label(char *label, char *buffer, int bige) 1360 { 1361 uint32_t i; 1362 char name[16]; 1363 1364 bcopy(label, name, sizeof (name)); 1365 /* bige is TRUE if the data format is big endian */ 1366 1367 if (bige) { 1368 /* Data format big Endian */ 1369 LE_SWAP32_BUFFER((uint8_t *)name, sizeof (name)); 1370 1371 for (i = 0; i < sizeof (name); i++) { 1372 if (name[i] == 0x20) { 1373 name[i] = 0; 1374 } 1375 } 1376 } else { 1377 /* Data format little Endian */ 1378 BE_SWAP32_BUFFER((uint8_t *)name, sizeof (name)); 1379 1380 for (i = 0; i < sizeof (name); i++) { 1381 if (name[i] == 0x20) { 1382 name[i] = 0; 1383 } 1384 } 1385 } 1386 1387 (void) strcpy(buffer, name); 1388 1389 return; 1390 1391 } /* emlxs_decode_label() */ 1392 1393 1394 extern uint32_t 1395 emlxs_strtol(char *str, uint32_t base) 1396 { 1397 uint32_t value = 0; 1398 char *ptr; 1399 uint32_t factor = 1; 1400 uint32_t digits; 1401 1402 if (*str == 0) { 1403 return (0); 1404 } 1405 1406 if (base != 10 && base != 16) { 1407 return (0); 1408 } 1409 1410 /* Get max digits of value */ 1411 digits = (base == 10) ? 9 : 8; 1412 1413 /* Position pointer to end of string */ 1414 ptr = str + strlen(str); 1415 1416 /* Process string backwards */ 1417 while ((ptr-- > str) && digits) { 1418 /* check for base 10 numbers */ 1419 if (*ptr >= '0' && *ptr <= '9') { 1420 value += ((uint32_t)(*ptr - '0')) * factor; 1421 factor *= base; 1422 digits--; 1423 } else if (base == 16) { 1424 /* Check for base 16 numbers */ 1425 if (*ptr >= 'a' && *ptr <= 'f') { 1426 value += 1427 ((uint32_t)(*ptr - 'a') + 10) * factor; 1428 factor *= base; 1429 digits--; 1430 } else if (*ptr >= 'A' && *ptr <= 'F') { 1431 value += 1432 ((uint32_t)(*ptr - 'A') + 10) * factor; 1433 factor *= base; 1434 digits--; 1435 } else if (factor > 1) { 1436 break; 1437 } 1438 } else if (factor > 1) { 1439 break; 1440 } 1441 } 1442 1443 return (value); 1444 1445 } /* emlxs_strtol() */ 1446 1447 1448 extern uint64_t 1449 emlxs_strtoll(char *str, uint32_t base) 1450 { 1451 uint64_t value = 0; 1452 char *ptr; 1453 uint32_t factor = 1; 1454 uint32_t digits; 1455 1456 if (*str == 0) { 1457 return (0); 1458 } 1459 1460 if (base != 10 && base != 16) { 1461 return (0); 1462 } 1463 1464 /* Get max digits of value */ 1465 digits = (base == 10) ? 19 : 16; 1466 1467 /* Position pointer to end of string */ 1468 ptr = str + strlen(str); 1469 1470 /* Process string backwards */ 1471 while ((ptr-- > str) && digits) { 1472 /* check for base 10 numbers */ 1473 if (*ptr >= '0' && *ptr <= '9') { 1474 value += ((uint32_t)(*ptr - '0')) * factor; 1475 factor *= base; 1476 digits--; 1477 } else if (base == 16) { 1478 /* Check for base 16 numbers */ 1479 if (*ptr >= 'a' && *ptr <= 'f') { 1480 value += 1481 ((uint32_t)(*ptr - 'a') + 10) * factor; 1482 factor *= base; 1483 digits--; 1484 } else if (*ptr >= 'A' && *ptr <= 'F') { 1485 value += 1486 ((uint32_t)(*ptr - 'A') + 10) * factor; 1487 factor *= base; 1488 digits--; 1489 } else if (factor > 1) { 1490 break; 1491 } 1492 } else if (factor > 1) { 1493 break; 1494 } 1495 } 1496 1497 return (value); 1498 1499 } /* emlxs_strtoll() */ 1500 1501 extern void 1502 emlxs_parse_prog_types(emlxs_hba_t *hba, char *prog_types) 1503 { 1504 emlxs_port_t *port = &PPORT; 1505 uint32_t i; 1506 char *ptr; 1507 emlxs_model_t *model; 1508 char types_buffer[256]; 1509 char *types; 1510 1511 bcopy(prog_types, types_buffer, 256); 1512 types = types_buffer; 1513 1514 model = &hba->model_info; 1515 1516 while (*types) { 1517 if (strncmp(types, "T2:", 3) == 0) { 1518 bzero(model->pt_2, sizeof (model->pt_2)); 1519 types += 3; 1520 1521 i = 0; 1522 while (*types && *types != 'T') { 1523 /* Null terminate the next value */ 1524 ptr = types; 1525 while (*ptr && (*ptr != ',')) 1526 ptr++; 1527 *ptr = 0; 1528 1529 /* Save the value */ 1530 model->pt_2[i++] = 1531 (uint8_t)emlxs_strtol(types, 16); 1532 1533 /* 1534 * EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_vpd_msg, 1535 * "T2[%d]: 0x%x", i-1, model->pt_2[i-1]); 1536 */ 1537 1538 /* Move the str pointer */ 1539 types = ptr + 1; 1540 } 1541 1542 } else if (strncmp(types, "T3:", 3) == 0) { 1543 bzero(model->pt_3, sizeof (model->pt_3)); 1544 types += 3; 1545 1546 i = 0; 1547 while (*types && *types != 'T') { 1548 /* Null terminate the next value */ 1549 ptr = types; 1550 while (*ptr && (*ptr != ',')) 1551 ptr++; 1552 *ptr = 0; 1553 1554 /* Save the value */ 1555 model->pt_3[i++] = 1556 (uint8_t)emlxs_strtol(types, 16); 1557 1558 /* 1559 * EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_vpd_msg, 1560 * "T3[%d]: 0x%x", i-1, model->pt_3[i-1]); 1561 */ 1562 1563 /* Move the str pointer */ 1564 types = ptr + 1; 1565 } 1566 } else if (strncmp(types, "T6:", 3) == 0) { 1567 bzero(model->pt_6, sizeof (model->pt_6)); 1568 types += 3; 1569 1570 i = 0; 1571 while (*types && *types != 'T') { 1572 /* Null terminate the next value */ 1573 ptr = types; 1574 while (*ptr && (*ptr != ',')) 1575 ptr++; 1576 *ptr = 0; 1577 1578 /* Save the value */ 1579 model->pt_6[i++] = 1580 (uint8_t)emlxs_strtol(types, 16); 1581 model->pt_6[i] = 0; 1582 1583 /* 1584 * EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_vpd_msg, 1585 * "T6[%d]: 0x%x", i-1, model->pt_6[i-1]); 1586 */ 1587 1588 /* Move the str pointer */ 1589 types = ptr + 1; 1590 } 1591 } else if (strncmp(types, "T7:", 3) == 0) { 1592 bzero(model->pt_7, sizeof (model->pt_7)); 1593 types += 3; 1594 1595 i = 0; 1596 while (*types && *types != 'T') { 1597 /* Null terminate the next value */ 1598 ptr = types; 1599 while (*ptr && (*ptr != ',')) 1600 ptr++; 1601 *ptr = 0; 1602 1603 /* Save the value */ 1604 model->pt_7[i++] = 1605 (uint8_t)emlxs_strtol(types, 16); 1606 model->pt_7[i] = 0; 1607 1608 /* 1609 * EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_vpd_msg, 1610 * "T7[%d]: 0x%x", i-1, model->pt_7[i-1]); 1611 */ 1612 1613 /* Move the str pointer */ 1614 types = ptr + 1; 1615 } 1616 } else if (strncmp(types, "TA:", 3) == 0) { 1617 bzero(model->pt_A, sizeof (model->pt_A)); 1618 types += 3; 1619 1620 i = 0; 1621 while (*types && *types != 'T') { 1622 /* Null terminate the next value */ 1623 ptr = types; 1624 while (*ptr && (*ptr != ',')) 1625 ptr++; 1626 *ptr = 0; 1627 1628 /* Save the value */ 1629 model->pt_A[i++] = 1630 (uint8_t)emlxs_strtol(types, 16); 1631 1632 /* 1633 * EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_vpd_msg, 1634 * "TA[%d]: 0x%x", i-1, model->pt_A[i-1]); 1635 */ 1636 1637 /* Move the str pointer */ 1638 types = ptr + 1; 1639 } 1640 } else if (strncmp(types, "TB:", 3) == 0) { 1641 bzero(model->pt_B, sizeof (model->pt_B)); 1642 types += 3; 1643 1644 i = 0; 1645 while (*types && *types != 'T') { 1646 /* Null terminate the next value */ 1647 ptr = types; 1648 while (*ptr && (*ptr != ',')) 1649 ptr++; 1650 *ptr = 0; 1651 1652 /* Save the value */ 1653 model->pt_B[i++] = 1654 (uint8_t)emlxs_strtol(types, 16); 1655 1656 /* 1657 * EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_vpd_msg, 1658 * "TB[%d]: 0x%x", i-1, model->pt_B[i-1]); 1659 */ 1660 1661 /* Move the str pointer */ 1662 types = ptr + 1; 1663 } 1664 } else if (strncmp(types, "TFF:", 4) == 0) { 1665 bzero(model->pt_FF, sizeof (model->pt_FF)); 1666 types += 4; 1667 1668 i = 0; 1669 while (*types && *types != 'T') { 1670 /* Null terminate the next value */ 1671 ptr = types; 1672 while (*ptr && (*ptr != ',')) 1673 ptr++; 1674 *ptr = 0; 1675 1676 /* Save the value */ 1677 model->pt_FF[i++] = 1678 (uint8_t)emlxs_strtol(types, 16); 1679 1680 /* 1681 * EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_vpd_msg, 1682 * "TF[%d]: 0x%x", i-1, model->pt_FF[i-1]); 1683 */ 1684 1685 /* Move the str pointer */ 1686 types = ptr + 1; 1687 } 1688 } else if (strncmp(types, "T20:", 4) == 0) { 1689 bzero(model->pt_20, sizeof (model->pt_20)); 1690 types += 4; 1691 1692 i = 0; 1693 while (*types && *types != 'T') { 1694 /* Null terminate the next value */ 1695 ptr = types; 1696 while (*ptr && (*ptr != ',')) 1697 ptr++; 1698 *ptr = 0; 1699 1700 /* Save the value */ 1701 model->pt_20[i++] = 1702 (uint8_t)emlxs_strtol(types, 16); 1703 model->pt_20[i] = 0; 1704 1705 /* 1706 * EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_vpd_msg, 1707 * "T20[%d]: 0x%x", i-1, model->pt_20[i-1]); 1708 */ 1709 1710 /* Move the str pointer */ 1711 types = ptr + 1; 1712 } 1713 } else { 1714 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_vpd_msg, 1715 "Unknown prog type string = %s", types); 1716 break; 1717 } 1718 } 1719 1720 return; 1721 1722 } /* emlxs_parse_prog_types() */ 1723 1724 1725 extern void 1726 emlxs_build_prog_types(emlxs_hba_t *hba, char *prog_types) 1727 { 1728 uint32_t i; 1729 uint32_t found = 0; 1730 char buffer[256]; 1731 1732 bzero(prog_types, 256); 1733 1734 /* Rebuild the prog type string */ 1735 if (hba->model_info.pt_2[0]) { 1736 (void) strcat(prog_types, "T2:"); 1737 found = 1; 1738 1739 i = 0; 1740 while (hba->model_info.pt_2[i] && i < 8) { 1741 (void) sprintf(buffer, "%X,", hba->model_info.pt_2[i]); 1742 (void) strcat(prog_types, buffer); 1743 i++; 1744 } 1745 } 1746 1747 if (hba->model_info.pt_3[0]) { 1748 (void) strcat(prog_types, "T3:"); 1749 found = 1; 1750 1751 i = 0; 1752 while (hba->model_info.pt_3[i] && i < 8) { 1753 (void) sprintf(buffer, "%X,", hba->model_info.pt_3[i]); 1754 (void) strcat(prog_types, buffer); 1755 i++; 1756 1757 } 1758 } 1759 1760 if (hba->model_info.pt_6[0]) { 1761 (void) strcat(prog_types, "T6:"); 1762 found = 1; 1763 1764 i = 0; 1765 while (hba->model_info.pt_6[i] && i < 8) { 1766 (void) sprintf(buffer, "%X,", hba->model_info.pt_6[i]); 1767 (void) strcat(prog_types, buffer); 1768 i++; 1769 } 1770 } 1771 1772 if (hba->model_info.pt_7[0]) { 1773 (void) strcat(prog_types, "T7:"); 1774 found = 1; 1775 1776 i = 0; 1777 while (hba->model_info.pt_7[i] && i < 8) { 1778 (void) sprintf(buffer, "%X,", hba->model_info.pt_7[i]); 1779 (void) strcat(prog_types, buffer); 1780 i++; 1781 } 1782 } 1783 1784 if (hba->model_info.pt_A[0]) { 1785 (void) strcat(prog_types, "TA:"); 1786 found = 1; 1787 1788 i = 0; 1789 while (hba->model_info.pt_A[i] && i < 8) { 1790 (void) sprintf(buffer, "%X,", hba->model_info.pt_A[i]); 1791 (void) strcat(prog_types, buffer); 1792 i++; 1793 } 1794 } 1795 1796 1797 if (hba->model_info.pt_B[0]) { 1798 (void) strcat(prog_types, "TB:"); 1799 found = 1; 1800 1801 i = 0; 1802 while (hba->model_info.pt_B[i] && i < 8) { 1803 (void) sprintf(buffer, "%X,", hba->model_info.pt_B[i]); 1804 (void) strcat(prog_types, buffer); 1805 i++; 1806 } 1807 } 1808 1809 if (hba->model_info.pt_20[0]) { 1810 (void) strcat(prog_types, "T20:"); 1811 found = 1; 1812 1813 i = 0; 1814 while (hba->model_info.pt_20[i] && i < 8) { 1815 (void) sprintf(buffer, "%X,", hba->model_info.pt_20[i]); 1816 (void) strcat(prog_types, buffer); 1817 i++; 1818 } 1819 } 1820 1821 if (hba->model_info.pt_FF[0]) { 1822 (void) strcat(prog_types, "TFF:"); 1823 found = 1; 1824 1825 i = 0; 1826 while (hba->model_info.pt_FF[i] && i < 8) { 1827 (void) sprintf(buffer, "%X,", hba->model_info.pt_FF[i]); 1828 (void) strcat(prog_types, buffer); 1829 i++; 1830 } 1831 } 1832 1833 if (found) { 1834 /* Terminate at the last comma in string */ 1835 prog_types[(strlen(prog_types) - 1)] = 0; 1836 } 1837 1838 return; 1839 1840 } /* emlxs_build_prog_types() */ 1841 1842 1843 1844 1845 extern uint32_t 1846 emlxs_init_adapter_info(emlxs_hba_t *hba) 1847 { 1848 emlxs_port_t *port = &PPORT; 1849 uint32_t pci_id; 1850 uint32_t cache_line; 1851 uint32_t channels; 1852 uint16_t device_id; 1853 uint16_t ssdid; 1854 uint32_t i; 1855 uint32_t found = 0; 1856 int32_t *prop; 1857 uint32_t num_prop; 1858 1859 if (hba->bus_type == SBUS_FC) { 1860 if (hba->pci_acc_handle == NULL) { 1861 bcopy(&emlxs_sbus_model[0], &hba->model_info, 1862 sizeof (emlxs_model_t)); 1863 1864 hba->model_info.device_id = 0; 1865 1866 return (0); 1867 } 1868 1869 /* Read the PCI device id */ 1870 pci_id = 1871 ddi_get32(hba->pci_acc_handle, 1872 (uint32_t *)(hba->pci_addr + PCI_VENDOR_ID_REGISTER)); 1873 device_id = (uint16_t)(pci_id >> 16); 1874 1875 /* Find matching adapter model */ 1876 for (i = 1; i < EMLXS_SBUS_MODEL_COUNT; i++) { 1877 if (emlxs_sbus_model[i].device_id == device_id) { 1878 bcopy(&emlxs_sbus_model[i], &hba->model_info, 1879 sizeof (emlxs_model_t)); 1880 found = 1; 1881 break; 1882 } 1883 } 1884 1885 /* If not found then use the unknown model */ 1886 if (!found) { 1887 bcopy(&emlxs_sbus_model[0], &hba->model_info, 1888 sizeof (emlxs_model_t)); 1889 1890 hba->model_info.device_id = device_id; 1891 1892 return (0); 1893 } 1894 } else { /* PCI model */ 1895 1896 if (hba->pci_acc_handle == NULL) { 1897 bcopy(&emlxs_pci_model[0], &hba->model_info, 1898 sizeof (emlxs_model_t)); 1899 1900 hba->model_info.device_id = 0; 1901 1902 return (0); 1903 } 1904 1905 /* Read the PCI device id */ 1906 device_id = 1907 ddi_get16(hba->pci_acc_handle, 1908 (uint16_t *)(hba->pci_addr + PCI_DEVICE_ID_REGISTER)); 1909 1910 /* Read the PCI Subsystem id */ 1911 ssdid = 1912 ddi_get16(hba->pci_acc_handle, 1913 (uint16_t *)(hba->pci_addr + PCI_SSDID_REGISTER)); 1914 1915 if (ssdid == 0 || ssdid == 0xffff) { 1916 ssdid = device_id; 1917 } 1918 1919 /* Read the Cache Line reg */ 1920 cache_line = 1921 ddi_get32(hba->pci_acc_handle, 1922 (uint32_t *)(hba->pci_addr + PCI_CACHE_LINE_REGISTER)); 1923 1924 /* Check for the multifunction bit being set */ 1925 if ((cache_line & 0x00ff0000) == 0x00800000) { 1926 channels = 2; 1927 } else { 1928 channels = 1; 1929 } 1930 1931 /* If device ids are unique, then use them for search */ 1932 if (device_id != ssdid) { 1933 if (channels > 1) { 1934 /* 1935 * Find matching adapter model using 1936 * device_id, ssdid and channels 1937 */ 1938 for (i = 1; i < emlxs_pci_model_count; i++) { 1939 if (emlxs_pci_model[i].device_id == 1940 device_id && 1941 emlxs_pci_model[i].ssdid == ssdid && 1942 emlxs_pci_model[i].channels == 1943 channels) { 1944 bcopy(&emlxs_pci_model[i], 1945 &hba->model_info, 1946 sizeof (emlxs_model_t)); 1947 found = 1; 1948 break; 1949 } 1950 } 1951 } else { 1952 /* 1953 * Find matching adapter model using 1954 * device_id and ssdid 1955 */ 1956 for (i = 1; i < emlxs_pci_model_count; i++) { 1957 if (emlxs_pci_model[i].device_id == 1958 device_id && 1959 emlxs_pci_model[i].ssdid == ssdid) { 1960 bcopy(&emlxs_pci_model[i], 1961 &hba->model_info, 1962 sizeof (emlxs_model_t)); 1963 found = 1; 1964 break; 1965 } 1966 } 1967 } 1968 } 1969 1970 /* If adapter not found, try again */ 1971 if (!found) { 1972 /* Find matching adapter model */ 1973 for (i = 1; i < emlxs_pci_model_count; i++) { 1974 if (emlxs_pci_model[i].device_id == device_id && 1975 emlxs_pci_model[i].channels == channels) { 1976 bcopy(&emlxs_pci_model[i], 1977 &hba->model_info, 1978 sizeof (emlxs_model_t)); 1979 found = 1; 1980 break; 1981 } 1982 } 1983 } 1984 1985 /* If adapter not found, try one last time */ 1986 if (!found) { 1987 /* Find matching adapter model */ 1988 for (i = 1; i < emlxs_pci_model_count; i++) { 1989 if (emlxs_pci_model[i].device_id == device_id) { 1990 bcopy(&emlxs_pci_model[i], 1991 &hba->model_info, 1992 sizeof (emlxs_model_t)); 1993 found = 1; 1994 break; 1995 } 1996 } 1997 } 1998 1999 /* If not found, set adapter to unknown */ 2000 if (!found) { 2001 bcopy(&emlxs_pci_model[0], &hba->model_info, 2002 sizeof (emlxs_model_t)); 2003 2004 hba->model_info.device_id = device_id; 2005 hba->model_info.ssdid = ssdid; 2006 2007 return (0); 2008 } 2009 2010 #ifndef SATURN_MSI_SUPPORT 2011 /* 2012 * This will disable MSI support for Saturn adapter's 2013 * due to a PCI bus issue 2014 */ 2015 if (hba->model_info.chip == EMLXS_SATURN_CHIP) { 2016 hba->model_info.flags &= 2017 ~(EMLXS_MSI_SUPPORTED | EMLXS_MSIX_SUPPORTED); 2018 } 2019 #endif /* !SATURN_MSI_SUPPORT */ 2020 2021 2022 #ifdef MSI_SUPPORT 2023 /* Verify MSI support */ 2024 if (hba->model_info.flags & EMLXS_MSI_SUPPORTED) { 2025 uint32_t offset; 2026 uint32_t reg; 2027 2028 /* Scan for MSI capabilities register */ 2029 offset = 2030 ddi_get32(hba->pci_acc_handle, 2031 (uint32_t *)(hba->pci_addr + PCI_CAP_POINTER)); 2032 offset &= 0xff; 2033 2034 while (offset) { 2035 reg = 2036 ddi_get32(hba->pci_acc_handle, 2037 (uint32_t *)(hba->pci_addr + offset)); 2038 2039 if ((reg & 0xff) == MSI_CAP_ID) { 2040 break; 2041 } 2042 offset = (reg >> 8) & 0xff; 2043 } 2044 2045 if (offset) { 2046 hba->msi_cap_offset = offset + 2; 2047 } else { 2048 hba->msi_cap_offset = 0; 2049 hba->model_info.flags &= ~EMLXS_MSI_SUPPORTED; 2050 2051 EMLXS_MSGF(EMLXS_CONTEXT, 2052 &emlxs_init_debug_msg, 2053 "MSI: control_reg capability not found!"); 2054 } 2055 } 2056 2057 /* Verify MSI-X support */ 2058 if (hba->model_info.flags & EMLXS_MSIX_SUPPORTED) { 2059 uint32_t offset; 2060 uint32_t reg; 2061 2062 /* Scan for MSI capabilities register */ 2063 offset = 2064 ddi_get32(hba->pci_acc_handle, 2065 (uint32_t *)(hba->pci_addr + PCI_CAP_POINTER)); 2066 offset &= 0xff; 2067 2068 while (offset) { 2069 reg = 2070 ddi_get32(hba->pci_acc_handle, 2071 (uint32_t *)(hba->pci_addr + offset)); 2072 2073 if ((reg & 0xff) == MSIX_CAP_ID) { 2074 break; 2075 } 2076 offset = (reg >> 8) & 0xff; 2077 } 2078 2079 if (offset) { 2080 hba->msix_cap_offset = offset; 2081 } else { 2082 hba->msix_cap_offset = 0; 2083 hba->model_info.flags &= 2084 ~EMLXS_MSIX_SUPPORTED; 2085 2086 EMLXS_MSGF(EMLXS_CONTEXT, 2087 &emlxs_init_debug_msg, 2088 "MSIX: control_reg capability not found!"); 2089 } 2090 } 2091 #endif /* MSI_SUPPORT */ 2092 2093 } 2094 2095 if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, hba->dip, 0, 2096 "reg", &prop, &num_prop) == DDI_PROP_SUCCESS) { 2097 /* Parse the property for PCI function, device and bus no. */ 2098 hba->pci_function_number = 2099 (uint8_t)((prop[0] & 0x00000700) >> 8); 2100 hba->pci_device_number = (uint8_t)((prop[0] & 0x00008100) >> 8); 2101 hba->pci_bus_number = (uint8_t)((prop[0] & 0x00ff0000) >> 16); 2102 ddi_prop_free((void *)prop); 2103 } 2104 2105 if (hba->model_info.sli_mask & EMLXS_SLI4_MASK) { 2106 hba->sli_api = emlxs_sli4_api; 2107 } else { 2108 hba->sli_api = emlxs_sli3_api; 2109 } 2110 2111 #ifdef FMA_SUPPORT 2112 if (emlxs_fm_check_acc_handle(hba, hba->pci_acc_handle) 2113 != DDI_FM_OK) { 2114 EMLXS_MSGF(EMLXS_CONTEXT, 2115 &emlxs_invalid_access_handle_msg, NULL); 2116 return (0); 2117 } 2118 #endif /* FMA_SUPPORT */ 2119 2120 return (1); 2121 2122 } /* emlxs_init_adapter_info() */ 2123 2124 2125 /* ARGSUSED */ 2126 static void 2127 emlxs_handle_async_event(emlxs_hba_t *hba, CHANNEL *cp, IOCBQ *iocbq) 2128 { 2129 emlxs_port_t *port = &PPORT; 2130 IOCB *iocb; 2131 uint32_t *w; 2132 int i, j; 2133 2134 iocb = &iocbq->iocb; 2135 2136 if (iocb->ULPSTATUS != 0) { 2137 return; 2138 } 2139 2140 switch (iocb->un.astat.EventCode) { 2141 case 0x0100: /* Temp Warning */ 2142 2143 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_temp_warning_msg, 2144 "Adapter is very hot (%d �C). Take corrective action.", 2145 iocb->ULPCONTEXT); 2146 2147 hba->temperature = iocb->ULPCONTEXT; 2148 emlxs_log_temp_event(port, 0x02, iocb->ULPCONTEXT); 2149 2150 2151 break; 2152 2153 2154 case 0x0101: /* Temp Safe */ 2155 2156 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_temp_msg, 2157 "Adapter temperature now safe (%d �C).", 2158 iocb->ULPCONTEXT); 2159 2160 hba->temperature = iocb->ULPCONTEXT; 2161 emlxs_log_temp_event(port, 0x03, iocb->ULPCONTEXT); 2162 2163 break; 2164 2165 default: 2166 2167 w = (uint32_t *)iocb; 2168 for (i = 0, j = 0; i < 8; i++, j += 2) { 2169 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_async_msg, 2170 "(Word[%d]=%x Word[%d]=%x)", j, w[j], j + 1, 2171 w[j + 1]); 2172 } 2173 2174 emlxs_log_async_event(port, iocb); 2175 } 2176 2177 return; 2178 2179 } /* emlxs_handle_async_event() */ 2180 2181 2182 /* ARGSUSED */ 2183 extern void 2184 emlxs_reset_link_thread(emlxs_hba_t *hba, void *arg1, void *arg2) 2185 { 2186 emlxs_port_t *port = &PPORT; 2187 2188 /* Attempt a link reset to recover */ 2189 (void) emlxs_reset(port, FC_FCA_LINK_RESET); 2190 2191 return; 2192 2193 } /* emlxs_reset_link_thread() */ 2194 2195 2196 /* ARGSUSED */ 2197 extern void 2198 emlxs_restart_thread(emlxs_hba_t *hba, void *arg1, void *arg2) 2199 { 2200 emlxs_port_t *port = &PPORT; 2201 2202 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_adapter_trans_msg, "Restarting..."); 2203 2204 /* Attempt a full hardware reset to recover */ 2205 if (emlxs_reset(port, FC_FCA_RESET) != FC_SUCCESS) { 2206 EMLXS_STATE_CHANGE(hba, FC_ERROR); 2207 2208 emlxs_shutdown_thread(hba, arg1, arg2); 2209 } 2210 2211 return; 2212 2213 } /* emlxs_restart_thread() */ 2214 2215 2216 /* ARGSUSED */ 2217 extern void 2218 emlxs_shutdown_thread(emlxs_hba_t *hba, void *arg1, void *arg2) 2219 { 2220 emlxs_port_t *port = &PPORT; 2221 2222 mutex_enter(&EMLXS_PORT_LOCK); 2223 if (hba->flag & FC_SHUTDOWN) { 2224 mutex_exit(&EMLXS_PORT_LOCK); 2225 return; 2226 } 2227 hba->flag |= FC_SHUTDOWN; 2228 mutex_exit(&EMLXS_PORT_LOCK); 2229 2230 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_adapter_trans_msg, 2231 "Shutting down..."); 2232 2233 /* Take adapter offline and leave it there */ 2234 (void) emlxs_offline(hba); 2235 2236 if (hba->sli_mode == EMLXS_HBA_SLI4_MODE) { 2237 /* 2238 * Dump is not defined for SLI4, so just 2239 * reset the HBA for now. 2240 */ 2241 EMLXS_SLI_HBA_RESET(hba, 1, 1, 0); 2242 2243 } else { 2244 if (hba->flag & FC_OVERTEMP_EVENT) { 2245 emlxs_log_temp_event(port, 0x01, 2246 hba->temperature); 2247 } else { 2248 emlxs_log_dump_event(port, NULL, 0); 2249 } 2250 } 2251 2252 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_shutdown_msg, "Reboot required."); 2253 2254 return; 2255 2256 } /* emlxs_shutdown_thread() */ 2257 2258 2259 /* ARGSUSED */ 2260 extern void 2261 emlxs_proc_channel(emlxs_hba_t *hba, CHANNEL *cp, void *arg2) 2262 { 2263 IOCBQ *iocbq; 2264 IOCBQ *rsp_head; 2265 2266 /* 2267 * EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg, 2268 * "emlxs_proc_channel: channel=%d", cp->channelno); 2269 */ 2270 2271 mutex_enter(&cp->rsp_lock); 2272 2273 while ((rsp_head = cp->rsp_head) != NULL) { 2274 cp->rsp_head = NULL; 2275 cp->rsp_tail = NULL; 2276 2277 mutex_exit(&cp->rsp_lock); 2278 2279 while ((iocbq = rsp_head) != NULL) { 2280 rsp_head = (IOCBQ *) iocbq->next; 2281 2282 emlxs_proc_channel_event(hba, cp, iocbq); 2283 } 2284 2285 mutex_enter(&cp->rsp_lock); 2286 } 2287 2288 mutex_exit(&cp->rsp_lock); 2289 2290 EMLXS_SLI_ISSUE_IOCB_CMD(hba, cp, 0); 2291 2292 return; 2293 2294 } /* emlxs_proc_channel() */ 2295 2296 2297 /* 2298 * Called from SLI ring event routines to process a rsp ring IOCB. 2299 */ 2300 void 2301 emlxs_proc_channel_event(emlxs_hba_t *hba, CHANNEL *cp, IOCBQ *iocbq) 2302 { 2303 emlxs_port_t *port = &PPORT; 2304 char buffer[MAX_MSG_DATA + 1]; 2305 IOCB *iocb; 2306 emlxs_buf_t *sbp; 2307 2308 iocb = &iocbq->iocb; 2309 2310 #ifdef DEBUG_CMPL_IOCB 2311 emlxs_data_dump(hba, "CMPL_IOCB", (uint32_t *)iocb, 8, 0); 2312 #endif 2313 2314 sbp = (emlxs_buf_t *)iocbq->sbp; 2315 if (sbp) { 2316 if (!(sbp->pkt_flags & PACKET_VALID) || 2317 (sbp->pkt_flags & (PACKET_ULP_OWNED | 2318 PACKET_IN_COMPLETION))) { 2319 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_iocb_stale_msg, 2320 "Duplicate: iocb=%p cmd=%x status=%x " 2321 "error=%x iotag=%x context=%x info=%x", 2322 iocbq, (uint8_t)iocbq->iocb.ULPCOMMAND, 2323 iocbq->iocb.ULPSTATUS, 2324 (uint8_t)iocbq->iocb.un.grsp.perr.statLocalError, 2325 (uint16_t)iocbq->iocb.ULPIOTAG, 2326 (uint16_t)iocbq->iocb.ULPCONTEXT, 2327 (uint8_t)iocbq->iocb.ULPRSVDBYTE); 2328 2329 /* Drop this IO immediately */ 2330 return; 2331 } 2332 2333 if (sbp->pkt_flags & PACKET_IN_TIMEOUT) { 2334 /* 2335 * If the packet is tagged for timeout then set the 2336 * return codes appropriately 2337 */ 2338 iocb->ULPSTATUS = IOSTAT_LOCAL_REJECT; 2339 iocb->un.grsp.perr.statLocalError = IOERR_ABORT_TIMEOUT; 2340 } else if (sbp->pkt_flags & 2341 (PACKET_IN_FLUSH | PACKET_IN_ABORT)) { 2342 /* 2343 * If the packet is tagged for abort then set the 2344 * return codes appropriately 2345 */ 2346 iocb->ULPSTATUS = IOSTAT_LOCAL_REJECT; 2347 iocb->un.grsp.perr.statLocalError = 2348 IOERR_ABORT_REQUESTED; 2349 } 2350 } 2351 2352 /* Check for IOCB local error */ 2353 if (iocb->ULPSTATUS == IOSTAT_LOCAL_REJECT) { 2354 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_iocb_event_msg, 2355 "Local reject. ringno=%d iocb=%p cmd=%x " 2356 "iotag=%x context=%x info=%x error=%x", 2357 cp->channelno, iocb, (uint8_t)iocb->ULPCOMMAND, 2358 (uint16_t)iocb->ULPIOTAG, (uint16_t)iocb->ULPCONTEXT, 2359 (uint8_t)iocb->ULPRSVDBYTE, 2360 (uint8_t)iocb->un.grsp.perr.statLocalError); 2361 } 2362 2363 switch (iocb->ULPCOMMAND) { 2364 /* RING 0 FCP commands */ 2365 case CMD_FCP_ICMND_CR: 2366 case CMD_FCP_ICMND_CX: 2367 case CMD_FCP_IREAD_CR: 2368 case CMD_FCP_IREAD_CX: 2369 case CMD_FCP_IWRITE_CR: 2370 case CMD_FCP_IWRITE_CX: 2371 case CMD_FCP_ICMND64_CR: 2372 case CMD_FCP_ICMND64_CX: 2373 case CMD_FCP_IREAD64_CR: 2374 case CMD_FCP_IREAD64_CX: 2375 case CMD_FCP_IWRITE64_CR: 2376 case CMD_FCP_IWRITE64_CX: 2377 emlxs_handle_fcp_event(hba, cp, iocbq); 2378 break; 2379 2380 #ifdef SFCT_SUPPORT 2381 case CMD_FCP_TSEND_CX: /* FCP_TARGET IOCB command */ 2382 case CMD_FCP_TSEND64_CX: /* FCP_TARGET IOCB command */ 2383 case CMD_FCP_TRECEIVE_CX: /* FCP_TARGET IOCB command */ 2384 case CMD_FCP_TRECEIVE64_CX: /* FCP_TARGET IOCB command */ 2385 case CMD_FCP_TRSP_CX: /* FCP_TARGET IOCB command */ 2386 case CMD_FCP_TRSP64_CX: /* FCP_TARGET IOCB command */ 2387 (void) emlxs_fct_handle_fcp_event(hba, cp, iocbq); 2388 break; 2389 #endif /* SFCT_SUPPORT */ 2390 2391 /* RING 1 IP commands */ 2392 case CMD_XMIT_BCAST_CN: 2393 case CMD_XMIT_BCAST_CX: 2394 case CMD_XMIT_BCAST64_CN: 2395 case CMD_XMIT_BCAST64_CX: 2396 (void) emlxs_ip_handle_event(hba, cp, iocbq); 2397 break; 2398 2399 case CMD_XMIT_SEQUENCE_CX: 2400 case CMD_XMIT_SEQUENCE_CR: 2401 case CMD_XMIT_SEQUENCE64_CX: 2402 case CMD_XMIT_SEQUENCE64_CR: 2403 switch (iocb->un.rcvseq64.w5.hcsw.Type) { 2404 case FC_TYPE_IS8802_SNAP: 2405 (void) emlxs_ip_handle_event(hba, cp, iocbq); 2406 break; 2407 2408 case FC_TYPE_FC_SERVICES: 2409 (void) emlxs_ct_handle_event(hba, cp, iocbq); 2410 break; 2411 2412 default: 2413 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_iocb_invalid_msg, 2414 "cmd=%x type=%x status=%x iotag=%x context=%x ", 2415 iocb->ULPCOMMAND, iocb->un.rcvseq64.w5.hcsw.Type, 2416 iocb->ULPSTATUS, iocb->ULPIOTAG, 2417 iocb->ULPCONTEXT); 2418 } 2419 break; 2420 2421 case CMD_RCV_SEQUENCE_CX: 2422 case CMD_RCV_SEQUENCE64_CX: 2423 case CMD_RCV_SEQ64_CX: 2424 case CMD_RCV_ELS_REQ_CX: /* Unsolicited ELS frame */ 2425 case CMD_RCV_ELS_REQ64_CX: /* Unsolicited ELS frame */ 2426 case CMD_RCV_ELS64_CX: /* Unsolicited ELS frame */ 2427 if (hba->sli_mode <= EMLXS_HBA_SLI3_MODE) { 2428 (void) emlxs_handle_rcv_seq(hba, cp, iocbq); 2429 } 2430 break; 2431 2432 case CMD_RCV_SEQ_LIST64_CX: 2433 (void) emlxs_ip_handle_rcv_seq_list(hba, cp, iocbq); 2434 break; 2435 2436 case CMD_CREATE_XRI_CR: 2437 case CMD_CREATE_XRI_CX: 2438 (void) emlxs_handle_create_xri(hba, cp, iocbq); 2439 break; 2440 2441 /* RING 2 ELS commands */ 2442 case CMD_ELS_REQUEST_CR: 2443 case CMD_ELS_REQUEST_CX: 2444 case CMD_XMIT_ELS_RSP_CX: 2445 case CMD_ELS_REQUEST64_CR: 2446 case CMD_ELS_REQUEST64_CX: 2447 case CMD_XMIT_ELS_RSP64_CX: 2448 (void) emlxs_els_handle_event(hba, cp, iocbq); 2449 break; 2450 2451 /* RING 3 CT commands */ 2452 case CMD_GEN_REQUEST64_CR: 2453 case CMD_GEN_REQUEST64_CX: 2454 switch (iocb->un.rcvseq64.w5.hcsw.Type) { 2455 #ifdef MENLO_SUPPORT 2456 case EMLXS_MENLO_TYPE: 2457 (void) emlxs_menlo_handle_event(hba, cp, iocbq); 2458 break; 2459 #endif /* MENLO_SUPPORT */ 2460 2461 case FC_TYPE_FC_SERVICES: 2462 (void) emlxs_ct_handle_event(hba, cp, iocbq); 2463 break; 2464 2465 default: 2466 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_iocb_invalid_msg, 2467 "cmd=%x type=%x status=%x iotag=%x context=%x ", 2468 iocb->ULPCOMMAND, iocb->un.rcvseq64.w5.hcsw.Type, 2469 iocb->ULPSTATUS, iocb->ULPIOTAG, 2470 iocb->ULPCONTEXT); 2471 } 2472 break; 2473 2474 case CMD_ABORT_XRI_CN: /* Abort fcp command */ 2475 2476 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_flushed_msg, 2477 "ABORT_XRI_CN: rpi=%d iotag=%x status=%x parm=%x", 2478 (uint32_t)iocb->un.acxri.abortContextTag, 2479 (uint32_t)iocb->un.acxri.abortIoTag, iocb->ULPSTATUS, 2480 iocb->un.acxri.parm); 2481 2482 #ifdef SFCT_SUPPORT 2483 if (port->tgt_mode) { 2484 (void) emlxs_fct_handle_abort(hba, cp, iocbq); 2485 } 2486 #endif /* SFCT_SUPPORT */ 2487 break; 2488 2489 case CMD_ABORT_XRI_CX: /* Abort command */ 2490 2491 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_flushed_msg, 2492 "ABORT_XRI_CX: rpi=%d iotag=%x status=%x parm=%x sbp=%p", 2493 (uint32_t)iocb->un.acxri.abortContextTag, 2494 (uint32_t)iocb->un.acxri.abortIoTag, iocb->ULPSTATUS, 2495 iocb->un.acxri.parm, iocbq->sbp); 2496 2497 #ifdef SFCT_SUPPORT 2498 if (port->tgt_mode) { 2499 (void) emlxs_fct_handle_abort(hba, cp, iocbq); 2500 } 2501 #endif /* SFCT_SUPPORT */ 2502 break; 2503 2504 case CMD_XRI_ABORTED_CX: /* Handle ABORT condition */ 2505 2506 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_flushed_msg, 2507 "XRI_ABORTED_CX: rpi=%d iotag=%x status=%x parm=%x", 2508 (uint32_t)iocb->un.acxri.abortContextTag, 2509 (uint32_t)iocb->un.acxri.abortIoTag, iocb->ULPSTATUS, 2510 iocb->un.acxri.parm); 2511 2512 #ifdef SFCT_SUPPORT 2513 if (port->tgt_mode) { 2514 (void) emlxs_fct_handle_abort(hba, cp, iocbq); 2515 } 2516 #endif /* SFCT_SUPPORT */ 2517 break; 2518 2519 case CMD_CLOSE_XRI_CN: /* Handle CLOSE condition */ 2520 2521 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_flushed_msg, 2522 "CLOSE_XRI_CN: rpi=%d iotag=%x status=%x parm=%x", 2523 (uint32_t)iocb->un.acxri.abortContextTag, 2524 (uint32_t)iocb->un.acxri.abortIoTag, iocb->ULPSTATUS, 2525 iocb->un.acxri.parm); 2526 2527 #ifdef SFCT_SUPPORT 2528 if (port->tgt_mode) { 2529 (void) emlxs_fct_handle_abort(hba, cp, iocbq); 2530 } 2531 #endif /* SFCT_SUPPORT */ 2532 break; 2533 2534 case CMD_CLOSE_XRI_CX: /* Handle CLOSE condition */ 2535 2536 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_flushed_msg, 2537 "CLOSE_XRI_CX: rpi=%d iotag=%x status=%x parm=%x sbp=%p", 2538 (uint32_t)iocb->un.acxri.abortContextTag, 2539 (uint32_t)iocb->un.acxri.abortIoTag, iocb->ULPSTATUS, 2540 iocb->un.acxri.parm, iocbq->sbp); 2541 2542 #ifdef SFCT_SUPPORT 2543 if (port->tgt_mode) { 2544 (void) emlxs_fct_handle_abort(hba, cp, iocbq); 2545 } 2546 #endif /* SFCT_SUPPORT */ 2547 break; 2548 2549 case CMD_ADAPTER_MSG: 2550 /* Allows debug adapter firmware messages to print on host */ 2551 bzero(buffer, sizeof (buffer)); 2552 bcopy((uint8_t *)iocb, buffer, MAX_MSG_DATA); 2553 2554 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_adapter_msg, "%s", buffer); 2555 2556 break; 2557 2558 case CMD_QUE_RING_LIST64_CN: 2559 case CMD_QUE_RING_BUF64_CN: 2560 break; 2561 2562 case CMD_ASYNC_STATUS: 2563 emlxs_handle_async_event(hba, cp, iocbq); 2564 break; 2565 2566 default: 2567 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_iocb_invalid_msg, 2568 "cmd=%x status=%x iotag=%x context=%x", iocb->ULPCOMMAND, 2569 iocb->ULPSTATUS, iocb->ULPIOTAG, iocb->ULPCONTEXT); 2570 2571 break; 2572 } /* switch(entry->ULPCOMMAND) */ 2573 2574 return; 2575 2576 } /* emlxs_proc_channel_event() */ 2577 2578 2579 extern char * 2580 emlxs_ffstate_xlate(uint32_t state) 2581 { 2582 static char buffer[32]; 2583 uint32_t i; 2584 uint32_t count; 2585 2586 count = sizeof (emlxs_ffstate_table) / sizeof (emlxs_table_t); 2587 for (i = 0; i < count; i++) { 2588 if (state == emlxs_ffstate_table[i].code) { 2589 return (emlxs_ffstate_table[i].string); 2590 } 2591 } 2592 2593 (void) sprintf(buffer, "state=0x%x", state); 2594 return (buffer); 2595 2596 } /* emlxs_ffstate_xlate() */ 2597 2598 2599 extern char * 2600 emlxs_ring_xlate(uint32_t ringno) 2601 { 2602 static char buffer[32]; 2603 uint32_t i; 2604 uint32_t count; 2605 2606 count = sizeof (emlxs_ring_table) / sizeof (emlxs_table_t); 2607 for (i = 0; i < count; i++) { 2608 if (ringno == emlxs_ring_table[i].code) { 2609 return (emlxs_ring_table[i].string); 2610 } 2611 } 2612 2613 (void) sprintf(buffer, "ring=0x%x", ringno); 2614 return (buffer); 2615 2616 } /* emlxs_ring_xlate() */ 2617 2618 2619 2620 extern void 2621 emlxs_pcix_mxr_update(emlxs_hba_t *hba, uint32_t verbose) 2622 { 2623 emlxs_port_t *port = &PPORT; 2624 MAILBOXQ *mbq; 2625 MAILBOX *mb; 2626 emlxs_config_t *cfg; 2627 uint32_t value; 2628 2629 cfg = &CFG; 2630 2631 xlate: 2632 2633 switch (cfg[CFG_PCI_MAX_READ].current) { 2634 case 512: 2635 value = 0; 2636 break; 2637 2638 case 1024: 2639 value = 1; 2640 break; 2641 2642 case 2048: 2643 value = 2; 2644 break; 2645 2646 case 4096: 2647 value = 3; 2648 break; 2649 2650 default: 2651 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg, 2652 "PCI_MAX_READ: Invalid parameter value. old=%d new=%d", 2653 cfg[CFG_PCI_MAX_READ].current, cfg[CFG_PCI_MAX_READ].def); 2654 2655 cfg[CFG_PCI_MAX_READ].current = cfg[CFG_PCI_MAX_READ].def; 2656 goto xlate; 2657 } 2658 2659 if ((mbq = (MAILBOXQ *)emlxs_mem_get(hba, MEM_MBOX, 1)) == 0) { 2660 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg, 2661 "PCI_MAX_READ: Unable to allocate mailbox buffer."); 2662 return; 2663 } 2664 mb = (MAILBOX *)mbq; 2665 2666 emlxs_mb_set_var(hba, mbq, 0x00100506, value); 2667 2668 if (EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbq, MBX_WAIT, 0) != MBX_SUCCESS) { 2669 if (verbose || (mb->mbxStatus != 0x12)) { 2670 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg, 2671 "PCI_MAX_READ: Unable to update. " 2672 "status=%x value=%d (%d bytes)", 2673 mb->mbxStatus, value, 2674 cfg[CFG_PCI_MAX_READ].current); 2675 } 2676 } else { 2677 if (verbose && 2678 (cfg[CFG_PCI_MAX_READ].current != 2679 cfg[CFG_PCI_MAX_READ].def)) { 2680 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg, 2681 "PCI_MAX_READ: Updated. %d bytes", 2682 cfg[CFG_PCI_MAX_READ].current); 2683 } 2684 } 2685 2686 (void) emlxs_mem_put(hba, MEM_MBOX, (uint8_t *)mbq); 2687 2688 return; 2689 2690 } /* emlxs_pcix_mxr_update */ 2691 2692 2693 2694 extern uint32_t 2695 emlxs_get_key(emlxs_hba_t *hba, MAILBOXQ *mbq) 2696 { 2697 emlxs_port_t *port = &PPORT; 2698 MAILBOX *mb = (MAILBOX *)mbq; 2699 uint32_t npname0, npname1; 2700 uint32_t tmpkey, theKey; 2701 uint16_t key850; 2702 uint32_t t1, t2, t3, t4; 2703 uint32_t ts; 2704 2705 #define SEED 0x876EDC21 2706 2707 /* This key is only used currently for SBUS adapters */ 2708 if (hba->bus_type != SBUS_FC) { 2709 return (0); 2710 } 2711 2712 tmpkey = mb->un.varWords[30]; 2713 EMLXS_STATE_CHANGE(hba, FC_INIT_NVPARAMS); 2714 2715 emlxs_mb_read_nv(hba, mbq); 2716 if (EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbq, MBX_WAIT, 0) != MBX_SUCCESS) { 2717 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg, 2718 "Unable to read nvram. cmd=%x status=%x", mb->mbxCommand, 2719 mb->mbxStatus); 2720 2721 return (0); 2722 } 2723 npname0 = mb->un.varRDnvp.portname[0]; 2724 npname1 = mb->un.varRDnvp.portname[1]; 2725 2726 key850 = (uint16_t)((tmpkey & 0x00FFFF00) >> 8); 2727 ts = (uint16_t)(npname1 + 1); 2728 t1 = ts * key850; 2729 ts = (uint16_t)((npname1 >> 16) + 1); 2730 t2 = ts * key850; 2731 ts = (uint16_t)(npname0 + 1); 2732 t3 = ts * key850; 2733 ts = (uint16_t)((npname0 >> 16) + 1); 2734 t4 = ts * key850; 2735 theKey = SEED + t1 + t2 + t3 + t4; 2736 2737 return (theKey); 2738 2739 } /* emlxs_get_key() */ 2740 2741 2742 extern void 2743 emlxs_fw_show(emlxs_hba_t *hba) 2744 { 2745 emlxs_port_t *port = &PPORT; 2746 uint32_t i; 2747 2748 /* Display firmware library one time */ 2749 for (i = 0; i < emlxs_fw_count; i++) { 2750 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_library_msg, "%s", 2751 emlxs_fw_table[i].label); 2752 } 2753 2754 return; 2755 2756 } /* emlxs_fw_show() */ 2757 2758 2759 #ifdef MODFW_SUPPORT 2760 extern void 2761 emlxs_fw_load(emlxs_hba_t *hba, emlxs_firmware_t *fw) 2762 { 2763 emlxs_port_t *port = &PPORT; 2764 int (*emlxs_fw_get)(emlxs_firmware_t *); 2765 int err; 2766 2767 /* Make sure image is unloaded and image buffer pointer is clear */ 2768 emlxs_fw_unload(hba, fw); 2769 2770 err = 0; 2771 hba->fw_modhandle = 2772 ddi_modopen(EMLXS_FW_MODULE, KRTLD_MODE_FIRST, &err); 2773 if (!hba->fw_modhandle) { 2774 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg, 2775 "Unable to load firmware module. error=%d", err); 2776 2777 return; 2778 } else { 2779 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_msg, 2780 "Firmware module loaded."); 2781 } 2782 2783 err = 0; 2784 emlxs_fw_get = 2785 (int (*)())ddi_modsym(hba->fw_modhandle, "emlxs_fw_get", &err); 2786 if ((void *)emlxs_fw_get == NULL) { 2787 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg, 2788 "emlxs_fw_get not present. error=%d", err); 2789 2790 emlxs_fw_unload(hba, fw); 2791 return; 2792 } 2793 2794 if (emlxs_fw_get(fw)) { 2795 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg, 2796 "Invalid firmware image module found. %s", fw->label); 2797 2798 emlxs_fw_unload(hba, fw); 2799 return; 2800 } 2801 2802 return; 2803 2804 } /* emlxs_fw_load() */ 2805 2806 2807 extern void 2808 emlxs_fw_unload(emlxs_hba_t *hba, emlxs_firmware_t *fw) 2809 { 2810 emlxs_port_t *port = &PPORT; 2811 2812 /* Clear the firmware image */ 2813 fw->image = NULL; 2814 fw->size = 0; 2815 2816 if (hba->fw_modhandle) { 2817 /* Close the module */ 2818 (void) ddi_modclose(hba->fw_modhandle); 2819 hba->fw_modhandle = NULL; 2820 2821 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_msg, 2822 "Firmware module unloaded."); 2823 } 2824 2825 return; 2826 2827 } /* emlxs_fw_unload() */ 2828 #endif /* MODFW_SUPPORT */ 2829