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