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