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