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 #include <emlxs.h> 28 29 #ifdef DUMP_SUPPORT 30 31 /* Required for EMLXS_CONTEXT in EMLXS_MSGF calls */ 32 EMLXS_MSG_DEF(EMLXS_DUMP_C); 33 34 /* ************************************************************************* */ 35 /* Utility functions */ 36 /* ************************************************************************* */ 37 38 static uint32_t 39 emlxs_menlo_set_mode( 40 emlxs_hba_t *hba, 41 uint32_t mode) 42 { 43 emlxs_port_t *port = &PPORT; 44 uint32_t cmd_size; 45 uint32_t rsp_size; 46 menlo_cmd_t *cmd_buf = NULL; 47 menlo_rsp_t *rsp_buf = NULL; 48 uint32_t rval = 0; 49 50 if (hba->model_info.vendor_id != PCI_VENDOR_ID_EMULEX || 51 hba->model_info.device_id != PCI_DEVICE_ID_HORNET) { 52 return (DFC_INVALID_ADAPTER); 53 } 54 55 cmd_size = sizeof (menlo_set_cmd_t); 56 cmd_buf = (menlo_cmd_t *)kmem_zalloc(cmd_size, KM_SLEEP); 57 58 rsp_size = 4; 59 rsp_buf = (menlo_rsp_t *)kmem_zalloc(rsp_size, KM_SLEEP); 60 61 cmd_buf->code = MENLO_CMD_SET_MODE; 62 cmd_buf->set.value1 = mode; 63 cmd_buf->set.value2 = 0; 64 65 #ifdef EMLXS_BIG_ENDIAN 66 emlxs_swap32_buffer((uint8_t *)cmd_buf, cmd_size); 67 #endif /* EMLXS_BIG_ENDIAN */ 68 69 if (rval = emlxs_send_menlo_cmd(hba, (uint8_t *)cmd_buf, cmd_size, 70 (uint8_t *)rsp_buf, &rsp_size)) { 71 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg, 72 "menlo_set_mode: Unable to send command."); 73 goto done; 74 } 75 #ifdef EMLXS_BIG_ENDIAN 76 emlxs_swap32_buffer((uint8_t *)rsp_buf, rsp_size); 77 #endif /* EMLXS_BIG_ENDIAN */ 78 79 if (rsp_buf->code != 0) { 80 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg, 81 "menlo_set_mode: Menlo command error. code=%d.\n", 82 rsp_buf->code); 83 } 84 85 rval = rsp_buf->code; 86 87 done: 88 89 if (cmd_buf) { 90 kmem_free(cmd_buf, sizeof (menlo_set_cmd_t)); 91 } 92 93 if (rsp_buf) { 94 kmem_free(rsp_buf, 4); 95 } 96 97 return (rval); 98 99 } /* emlxs_menlo_set_mode() */ 100 101 102 static uint32_t 103 emlxs_menlo_reset( 104 emlxs_hba_t *hba, 105 uint32_t firmware) 106 { 107 emlxs_port_t *port = &PPORT; 108 uint32_t cmd_size; 109 uint32_t rsp_size; 110 menlo_cmd_t *cmd_buf = NULL; 111 menlo_rsp_t *rsp_buf = NULL; 112 uint32_t rval = 0; 113 114 if (hba->model_info.vendor_id != PCI_VENDOR_ID_EMULEX || 115 hba->model_info.device_id != PCI_DEVICE_ID_HORNET) { 116 return (DFC_INVALID_ADAPTER); 117 } 118 119 cmd_size = sizeof (menlo_reset_cmd_t); 120 cmd_buf = (menlo_cmd_t *)kmem_zalloc(cmd_size, KM_SLEEP); 121 122 rsp_size = 4; 123 rsp_buf = (menlo_rsp_t *)kmem_zalloc(rsp_size, KM_SLEEP); 124 125 cmd_buf->code = MENLO_CMD_RESET; 126 cmd_buf->reset.firmware = firmware; 127 128 #ifdef EMLXS_BIG_ENDIAN 129 emlxs_swap32_buffer((uint8_t *)cmd_buf, cmd_size); 130 #endif /* EMLXS_BIG_ENDIAN */ 131 132 if (rval = emlxs_send_menlo_cmd(hba, (uint8_t *)cmd_buf, cmd_size, 133 (uint8_t *)rsp_buf, &rsp_size)) { 134 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg, 135 "menlo_reset: Unable to send command."); 136 goto done; 137 } 138 #ifdef EMLXS_BIG_ENDIAN 139 emlxs_swap32_buffer((uint8_t *)rsp_buf, rsp_size); 140 #endif /* EMLXS_BIG_ENDIAN */ 141 142 if (rsp_buf->code != 0) { 143 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg, 144 "menlo_reset: Menlo command error. code=%d.\n", 145 rsp_buf->code); 146 } 147 148 rval = rsp_buf->code; 149 150 done: 151 152 if (cmd_buf) { 153 kmem_free(cmd_buf, sizeof (menlo_reset_cmd_t)); 154 } 155 156 if (rsp_buf) { 157 kmem_free(rsp_buf, 4); 158 } 159 160 return (rval); 161 162 } /* emlxs_menlo_reset() */ 163 164 165 static uint32_t 166 emlxs_menlo_get_cfg( 167 emlxs_hba_t *hba, 168 menlo_get_config_rsp_t *rsp_buf, 169 uint32_t rsp_size) 170 { 171 emlxs_port_t *port = &PPORT; 172 uint32_t cmd_size; 173 menlo_cmd_t *cmd_buf = NULL; 174 uint32_t rval = 0; 175 176 if (hba->model_info.vendor_id != PCI_VENDOR_ID_EMULEX || 177 hba->model_info.device_id != PCI_DEVICE_ID_HORNET) { 178 return (DFC_INVALID_ADAPTER); 179 } 180 181 cmd_size = sizeof (menlo_get_cmd_t); 182 cmd_buf = (menlo_cmd_t *)kmem_zalloc(cmd_size, KM_SLEEP); 183 184 rsp_size = sizeof (menlo_get_config_rsp_t); 185 186 cmd_buf->code = MENLO_CMD_GET_CONFIG; 187 cmd_buf->get.context = 0; 188 cmd_buf->get.length = rsp_size; 189 190 #ifdef EMLXS_BIG_ENDIAN 191 emlxs_swap32_buffer((uint8_t *)cmd_buf, cmd_size); 192 #endif /* EMLXS_BIG_ENDIAN */ 193 194 if (rval = emlxs_send_menlo_cmd(hba, (uint8_t *)cmd_buf, cmd_size, 195 (uint8_t *)rsp_buf, &rsp_size)) { 196 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg, 197 "menlo_get_cfg: Unable to send command."); 198 goto done; 199 } 200 #ifdef EMLXS_BIG_ENDIAN 201 emlxs_swap32_buffer((uint8_t *)rsp_buf, rsp_size); 202 #endif /* EMLXS_BIG_ENDIAN */ 203 204 if (rsp_buf->code != 0) { 205 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg, 206 "menlo_get_cfg: Menlo command error. code=%d.\n", 207 rsp_buf->code); 208 } 209 210 rval = rsp_buf->code; 211 212 done: 213 214 if (cmd_buf) { 215 kmem_free(cmd_buf, sizeof (menlo_get_cmd_t)); 216 } 217 218 return (rval); 219 220 } /* emlxs_menlo_get_cfg() */ 221 222 223 224 static uint32_t 225 emlxs_menlo_get_logcfg( 226 emlxs_hba_t *hba, 227 menlo_rsp_t *rsp_buf, 228 uint32_t rsp_size) 229 { 230 emlxs_port_t *port = &PPORT; 231 uint32_t cmd_size; 232 menlo_cmd_t *cmd_buf = NULL; 233 uint32_t rval = 0; 234 235 if (hba->model_info.vendor_id != PCI_VENDOR_ID_EMULEX || 236 hba->model_info.device_id != PCI_DEVICE_ID_HORNET) { 237 return (DFC_INVALID_ADAPTER); 238 } 239 240 cmd_size = sizeof (menlo_get_cmd_t); 241 cmd_buf = (menlo_cmd_t *)kmem_zalloc(cmd_size, KM_SLEEP); 242 243 cmd_buf->code = MENLO_CMD_GET_LOG_CONFIG; 244 cmd_buf->get.context = 0; 245 cmd_buf->get.length = rsp_size; 246 247 #ifdef EMLXS_BIG_ENDIAN 248 emlxs_swap32_buffer((uint8_t *)cmd_buf, cmd_size); 249 #endif /* EMLXS_BIG_ENDIAN */ 250 251 if (rval = emlxs_send_menlo_cmd(hba, (uint8_t *)cmd_buf, cmd_size, 252 (uint8_t *)rsp_buf, &rsp_size)) { 253 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg, 254 "menlo_get_logcfg: Unable to send command."); 255 goto done; 256 } 257 #ifdef EMLXS_BIG_ENDIAN 258 emlxs_swap32_buffer((uint8_t *)rsp_buf, rsp_size); 259 #endif /* EMLXS_BIG_ENDIAN */ 260 261 if (rsp_buf->code != 0) { 262 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg, 263 "menlo_get_logcfg: Menlo command error. code=%d.\n", 264 rsp_buf->code); 265 } 266 267 rval = rsp_buf->code; 268 269 done: 270 271 if (cmd_buf) { 272 kmem_free(cmd_buf, sizeof (menlo_get_cmd_t)); 273 } 274 275 return (rval); 276 277 } /* emlxs_menlo_get_logcfg() */ 278 279 280 static uint32_t 281 emlxs_menlo_get_log( 282 emlxs_hba_t *hba, 283 uint32_t id, 284 menlo_rsp_t *rsp_buf, 285 uint32_t rsp_size) 286 { 287 emlxs_port_t *port = &PPORT; 288 uint32_t cmd_size; 289 menlo_cmd_t *cmd_buf = NULL; 290 uint32_t rval = 0; 291 292 if (hba->model_info.vendor_id != PCI_VENDOR_ID_EMULEX || 293 hba->model_info.device_id != PCI_DEVICE_ID_HORNET) { 294 return (DFC_INVALID_ADAPTER); 295 } 296 297 cmd_size = sizeof (menlo_get_cmd_t); 298 cmd_buf = (menlo_cmd_t *)kmem_zalloc(cmd_size, KM_SLEEP); 299 300 cmd_buf->code = MENLO_CMD_GET_LOG_DATA; 301 cmd_buf->get.context = id; 302 cmd_buf->get.length = rsp_size; 303 304 #ifdef EMLXS_BIG_ENDIAN 305 emlxs_swap32_buffer((uint8_t *)cmd_buf, cmd_size); 306 #endif /* EMLXS_BIG_ENDIAN */ 307 308 if (rval = emlxs_send_menlo_cmd(hba, (uint8_t *)cmd_buf, cmd_size, 309 (uint8_t *)rsp_buf, &rsp_size)) { 310 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg, 311 "menlo_get_log: Unable to send command."); 312 goto done; 313 } 314 #ifdef EMLXS_BIG_ENDIAN 315 emlxs_swap32_buffer((uint8_t *)rsp_buf, rsp_size); 316 #endif /* EMLXS_BIG_ENDIAN */ 317 318 if (rsp_buf->code != 0) { 319 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg, 320 "menlo_get_log: Menlo command error. code=%d.\n", 321 rsp_buf->code); 322 } 323 324 rval = rsp_buf->code; 325 326 done: 327 328 if (cmd_buf) { 329 kmem_free(cmd_buf, sizeof (menlo_get_cmd_t)); 330 } 331 332 return (rval); 333 334 } /* emlxs_menlo_get_log() */ 335 336 337 static uint32_t 338 emlxs_menlo_get_paniclog( 339 emlxs_hba_t *hba, 340 menlo_rsp_t *rsp_buf, 341 uint32_t rsp_size) 342 { 343 emlxs_port_t *port = &PPORT; 344 uint32_t cmd_size; 345 menlo_cmd_t *cmd_buf = NULL; 346 uint32_t rval = 0; 347 348 if (hba->model_info.vendor_id != PCI_VENDOR_ID_EMULEX || 349 hba->model_info.device_id != PCI_DEVICE_ID_HORNET) { 350 return (DFC_INVALID_ADAPTER); 351 } 352 353 cmd_size = sizeof (menlo_get_cmd_t); 354 cmd_buf = (menlo_cmd_t *)kmem_zalloc(cmd_size, KM_SLEEP); 355 356 cmd_buf->code = MENLO_CMD_GET_PANIC_LOG; 357 cmd_buf->get.context = 0; 358 cmd_buf->get.length = rsp_size; 359 360 #ifdef EMLXS_BIG_ENDIAN 361 emlxs_swap32_buffer((uint8_t *)cmd_buf, cmd_size); 362 #endif /* EMLXS_BIG_ENDIAN */ 363 364 if (rval = emlxs_send_menlo_cmd(hba, (uint8_t *)cmd_buf, cmd_size, 365 (uint8_t *)rsp_buf, &rsp_size)) { 366 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg, 367 "menlo_get_paniclog: Unable to send command."); 368 goto done; 369 } 370 #ifdef EMLXS_BIG_ENDIAN 371 emlxs_swap32_buffer((uint8_t *)rsp_buf, rsp_size); 372 #endif /* EMLXS_BIG_ENDIAN */ 373 374 if (rsp_buf->code != 0) { 375 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg, 376 "menlo_get_paniclog: Menlo command error. code=%d.\n", 377 rsp_buf->code); 378 } 379 380 rval = rsp_buf->code; 381 382 done: 383 384 if (cmd_buf) { 385 kmem_free(cmd_buf, sizeof (menlo_get_cmd_t)); 386 } 387 388 return (rval); 389 390 } /* emlxs_menlo_get_paniclog() */ 391 392 393 394 395 extern void 396 emlxs_fflush( 397 emlxs_file_t *fp) 398 { 399 uint32_t offset; 400 401 offset = (uint32_t)((uintptr_t)fp->ptr - (uintptr_t)fp->buffer); 402 403 if (offset > fp->size) { 404 fp->ptr = fp->buffer + fp->size; 405 } 406 407 return; 408 409 } /* emlxs_fflush() */ 410 411 412 extern uint32_t 413 emlxs_ftell( 414 emlxs_file_t *fp) 415 { 416 uint32_t offset; 417 418 offset = (uint32_t)((uintptr_t)fp->ptr - (uintptr_t)fp->buffer); 419 420 return (offset); 421 422 } /* emlxs_ftell() */ 423 424 425 static void 426 emlxs_fputc( 427 uint8_t value, 428 emlxs_file_t *fp) 429 { 430 uint32_t offset; 431 432 offset = (uint32_t)((uintptr_t)fp->ptr - (uintptr_t)fp->buffer); 433 434 if ((offset + 1) <= fp->size) { 435 *fp->ptr++ = value; 436 } 437 438 return; 439 440 } /* emlxs_fputc() */ 441 442 443 static uint32_t 444 emlxs_fwrite( 445 uint8_t *buffer, 446 uint32_t size, 447 uint32_t nitems, 448 emlxs_file_t *fp) 449 { 450 uint32_t offset; 451 uint32_t length; 452 453 length = size * nitems; 454 455 if (length) { 456 offset = 457 (uint32_t)((uintptr_t)fp->ptr - (uintptr_t)fp->buffer); 458 459 if ((offset + length) > fp->size) { 460 length = fp->size - offset; 461 } 462 463 if (length) { 464 bcopy(buffer, fp->ptr, length); 465 fp->ptr += length; 466 } 467 } 468 469 return (length); 470 471 } /* emlxs_fwrite() */ 472 473 474 static uint32_t 475 emlxs_fprintf( 476 emlxs_file_t *fp, 477 const char *fmt, ...) 478 { 479 va_list valist; 480 char va_str[1024]; 481 uint32_t length; 482 483 va_start(valist, fmt); 484 (void) vsnprintf(va_str, sizeof (va_str), fmt, valist); 485 va_end(valist); 486 487 length = emlxs_fwrite((uint8_t *)va_str, strlen(va_str), 1, fp); 488 489 return (length); 490 491 } /* emlxs_fprintf() */ 492 493 494 extern emlxs_file_t * 495 emlxs_fopen( 496 emlxs_hba_t *hba, 497 uint32_t file_type) 498 { 499 emlxs_file_t *fp; 500 501 switch (file_type) { 502 case EMLXS_TXT_FILE: 503 fp = &hba->dump_txtfile; 504 fp->size = EMLXS_TXT_FILE_SIZE; 505 break; 506 507 case EMLXS_DMP_FILE: 508 fp = &hba->dump_dmpfile; 509 fp->size = EMLXS_DMP_FILE_SIZE; 510 break; 511 512 case EMLXS_CEE_FILE: 513 fp = &hba->dump_ceefile; 514 fp->size = EMLXS_CEE_FILE_SIZE; 515 break; 516 517 default: 518 return (NULL); 519 } 520 521 /* Make sure it is word aligned */ 522 fp->size &= 0xFFFFFFFC; 523 524 if (!fp->buffer) { 525 fp->buffer = 526 (uint8_t *)kmem_zalloc(fp->size, KM_SLEEP); 527 528 } else { 529 bzero(fp->buffer, fp->size); 530 } 531 532 fp->ptr = fp->buffer; 533 534 return (fp); 535 536 } /* emlxs_fopen() */ 537 538 539 extern uint32_t 540 emlxs_fclose( 541 emlxs_file_t *fp) 542 { 543 uint32_t offset; 544 545 if (fp == NULL) { 546 return (0); 547 } 548 549 offset = (uint32_t)((uintptr_t)fp->ptr - (uintptr_t)fp->buffer); 550 offset = offset % 4; 551 552 switch (offset) { 553 case 0: 554 break; 555 556 case 1: 557 *fp->ptr++ = 0; 558 *fp->ptr++ = 0; 559 *fp->ptr++ = 0; 560 break; 561 562 case 2: 563 *fp->ptr++ = 0; 564 *fp->ptr++ = 0; 565 break; 566 567 case 3: 568 *fp->ptr++ = 0; 569 break; 570 } 571 572 return (0); 573 574 } /* emlxs_fclose() */ 575 576 577 static void 578 emlxs_fdelete( 579 emlxs_file_t *fp) 580 { 581 if (fp == NULL) { 582 return; 583 } 584 585 if (fp->buffer && fp->size) { 586 kmem_free(fp->buffer, fp->size); 587 } 588 589 fp->buffer = NULL; 590 fp->ptr = NULL; 591 fp->size = 0; 592 593 return; 594 595 } /* emlxs_fdelete() */ 596 597 598 /* This builds a single core buffer for the IOCTL interface */ 599 extern uint32_t 600 emlxs_get_dump( 601 emlxs_hba_t *hba, 602 uint8_t *buffer, 603 uint32_t *buflen) 604 { 605 emlxs_port_t *port = &PPORT; 606 int32_t i; 607 int32_t size; 608 int32_t count; 609 uint32_t size_dmp; 610 uint32_t size_txt; 611 uint32_t size_cee; 612 emlxs_file_t *fp_txt; 613 emlxs_file_t *fp_dmp; 614 emlxs_file_t *fp_cee; 615 uint32_t *wptr; 616 uint8_t *bptr; 617 618 if (!buflen) { 619 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fw_dump_msg, 620 "get_dump: Buffer length = 0"); 621 return (1); 622 } 623 624 fp_txt = &hba->dump_txtfile; 625 fp_dmp = &hba->dump_dmpfile; 626 fp_cee = &hba->dump_ceefile; 627 628 size_txt = emlxs_ftell(fp_txt); 629 size_dmp = emlxs_ftell(fp_dmp); 630 size_cee = emlxs_ftell(fp_cee); 631 632 size = 0; 633 count = 0; 634 if (size_txt) { 635 count++; 636 size += size_txt + 8; 637 } 638 if (size_dmp) { 639 count++; 640 size += size_dmp + 8; 641 } 642 if (size_cee) { 643 count++; 644 size += size_cee + 8; 645 } 646 647 if (size) { 648 size += 4; 649 } 650 651 if (!buffer) { 652 goto done; 653 } 654 655 bzero(buffer, *buflen); 656 657 if (*buflen < size) { 658 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fw_dump_msg, 659 "get_dump: Buffer length too small. %d < %d", 660 *buflen, size); 661 662 *buflen = 0; 663 return (1); 664 } 665 666 wptr = (uint32_t *)buffer; 667 wptr[0] = count; 668 i = 1; 669 670 if (size_txt) { 671 wptr[i++] = EMLXS_TXT_FILE_ID; 672 wptr[i++] = size_txt; 673 } 674 675 if (size_dmp) { 676 wptr[i++] = EMLXS_DMP_FILE_ID; 677 wptr[i++] = size_dmp; 678 } 679 680 if (size_cee) { 681 if ((hba->model_info.chip == EMLXS_BE2_CHIP) || 682 (hba->model_info.chip == EMLXS_BE3_CHIP)) { 683 wptr[i++] = EMLXS_FAT_FILE_ID; 684 } else { 685 wptr[i++] = EMLXS_CEE_FILE_ID; 686 } 687 688 wptr[i++] = size_cee; 689 } 690 691 bptr = (uint8_t *)&wptr[i]; 692 693 if (size_txt) { 694 bcopy(fp_txt->buffer, bptr, size_txt); 695 bptr += size_txt; 696 } 697 698 if (size_dmp) { 699 bcopy(fp_dmp->buffer, bptr, size_dmp); 700 bptr += size_dmp; 701 } 702 703 if (size_cee) { 704 bcopy(fp_cee->buffer, bptr, size_cee); 705 bptr += size_cee; 706 } 707 708 done: 709 710 *buflen = size; 711 712 /* printf("Done. buflen=%d \n", *buflen); */ 713 714 return (0); 715 716 } /* emlxs_get_dump() */ 717 718 719 static uint32_t 720 emlxs_read_cfg_region( 721 emlxs_hba_t *hba, 722 uint32_t Identifier, 723 uint32_t ByteCount, 724 uint32_t *pRetByteCount, 725 uint8_t *pBuffer) 726 { 727 emlxs_port_t *port = &PPORT; 728 MAILBOXQ *mbq; 729 uint32_t ByteCountRem; /* remaining portion of original byte count */ 730 uint32_t ByteCountReq; /* requested byte count for a particular dump */ 731 uint32_t CopyCount; /* bytes to copy after each successful dump */ 732 uint32_t Offset; /* Offset into Config Region, for each dump */ 733 uint8_t *pLocalBuf; /* ptr to buffer to receive each dump */ 734 735 if (! ByteCount) { 736 return (0); 737 } 738 739 mbq = 740 (MAILBOXQ *)kmem_zalloc(sizeof (MAILBOXQ), KM_SLEEP); 741 742 pLocalBuf = pBuffer; /* init local pointer to caller's buffer */ 743 Offset = 0; /* start at offset 0 */ 744 *pRetByteCount = 0; /* init returned byte count */ 745 CopyCount = 0; 746 747 for (ByteCountRem = ByteCount; ByteCountRem > 0; 748 ByteCountRem -= CopyCount) { 749 750 if (hba->sli_mode == EMLXS_HBA_SLI4_MODE) { 751 MAILBOX4 *mb = (MAILBOX4 *)mbq; 752 753 ByteCountReq = 754 (ByteCountRem < hba->sli.sli4.dump_region.size) ? 755 ByteCountRem : hba->sli.sli4.dump_region.size; 756 757 /* Clear the local dump_region */ 758 bzero(hba->sli.sli4.dump_region.virt, 759 hba->sli.sli4.dump_region.size); 760 761 bzero((void *) mb, MAILBOX_CMD_SLI4_BSIZE); 762 763 mb->mbxCommand = MBX_DUMP_MEMORY; 764 mb->un.varDmp4.type = DMP_NV_PARAMS; 765 mb->un.varDmp4.entry_index = Offset; 766 mb->un.varDmp4.region_id = Identifier; 767 768 mb->un.varDmp4.available_cnt = ByteCountReq; 769 mb->un.varDmp4.addrHigh = 770 PADDR_HI(hba->sli.sli4.dump_region.phys); 771 mb->un.varDmp4.addrLow = 772 PADDR_LO(hba->sli.sli4.dump_region.phys); 773 mb->un.varDmp4.rsp_cnt = 0; 774 775 mb->mbxOwner = OWN_HOST; 776 mbq->mbox_cmpl = NULL; 777 778 if (EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbq, MBX_WAIT, 0) != 779 MBX_SUCCESS) { 780 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg, 781 "Unable to read config region. id=%x "\ 782 "offset=%x status=%x", 783 Identifier, Offset, mb->mbxStatus); 784 785 kmem_free(mbq, sizeof (MAILBOXQ)); 786 return (1); 787 } 788 789 CopyCount = mb->un.varDmp4.rsp_cnt; 790 791 /* if no more data returned */ 792 if (CopyCount == 0) { 793 break; 794 } 795 796 if (CopyCount > ByteCountReq) { 797 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg, 798 "read_cfg_region: " \ 799 "Byte count too big. %d > %d\n", 800 CopyCount, ByteCountReq); 801 802 CopyCount = ByteCountReq; 803 } 804 805 bcopy((uint8_t *)hba->sli.sli4.dump_region.virt, 806 pLocalBuf, CopyCount); 807 808 } else { 809 MAILBOX *mb = (MAILBOX *)mbq; 810 811 ByteCountReq = 812 (ByteCountRem < DUMP_BC_MAX) ? ByteCountRem : 813 DUMP_BC_MAX; 814 815 bzero((void *)mb, MAILBOX_CMD_BSIZE); 816 817 mb->mbxCommand = MBX_DUMP_MEMORY; 818 mb->un.varDmp.type = DMP_NV_PARAMS; 819 mb->un.varDmp.cv = 1; 820 mb->un.varDmp.region_id = Identifier; 821 mb->un.varDmp.entry_index = Offset; 822 mb->un.varDmp.word_cnt = ByteCountReq / 4; 823 mb->mbxOwner = OWN_HOST; 824 mbq->mbox_cmpl = NULL; 825 826 if (EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbq, MBX_WAIT, 0) != 827 MBX_SUCCESS) { 828 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg, 829 "Unable to read config region. id=%x "\ 830 "offset=%x status=%x", 831 Identifier, Offset, mb->mbxStatus); 832 833 kmem_free(mbq, sizeof (MAILBOXQ)); 834 return (1); 835 } 836 837 /* Note: for Type 2/3 Dumps, varDmp.word_cnt is */ 838 /* actually a byte count. */ 839 CopyCount = mb->un.varDmp.word_cnt; 840 841 /* if no more data returned */ 842 if (CopyCount == 0) { 843 break; 844 } 845 846 if (CopyCount > ByteCountReq) { 847 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg, 848 "read_cfg_region: " \ 849 "Byte count too big. %d > %d\n", 850 CopyCount, ByteCountReq); 851 852 CopyCount = ByteCountReq; 853 } 854 855 bcopy((uint8_t *)&mb->un.varDmp.resp_offset, pLocalBuf, 856 CopyCount); 857 } 858 859 pLocalBuf += CopyCount; 860 Offset += CopyCount; 861 *pRetByteCount += CopyCount; 862 } 863 864 return (0); 865 866 } /* emlxs_read_cfg_region() */ 867 868 869 870 /* ************************************************************************* */ 871 /* ************************************************************************* */ 872 /* Dump Generators, Low-Level */ 873 /* ************************************************************************* */ 874 /* ************************************************************************* */ 875 876 static uint32_t 877 emlxs_dump_string_txtfile( 878 emlxs_file_t *fpTxtFile, 879 char *pString, 880 char *pSidLegend, 881 char *pLidLegend, 882 uint32_t pure) 883 { 884 885 if (!fpTxtFile) { 886 return (1); 887 } 888 889 if (pSidLegend && pLidLegend) { 890 (void) emlxs_fprintf(fpTxtFile, "%s: %s\n", pSidLegend, 891 pLidLegend); 892 893 if (pure == 0) { 894 emlxs_fputc(' ', fpTxtFile); 895 } 896 897 (void) emlxs_fwrite((uint8_t *)pString, strlen(pString), 1, 898 fpTxtFile); 899 900 if (pure == 0) { 901 emlxs_fputc('\n', fpTxtFile); 902 emlxs_fputc('\n', fpTxtFile); 903 } 904 } else { 905 if (pure == 0) { 906 emlxs_fputc(' ', fpTxtFile); 907 } 908 (void) emlxs_fwrite((uint8_t *)pString, strlen(pString), 1, 909 fpTxtFile); 910 } 911 912 emlxs_fflush(fpTxtFile); 913 914 return (0); 915 916 } /* emlxs_dump_string_txtfile() */ 917 918 919 static uint32_t 920 emlxs_dump_word_txtfile( 921 emlxs_file_t *fpTxtFile, 922 uint32_t *pBuffer, 923 uint32_t WordCount, 924 char *pSidLegend, 925 char *pLidLegend) 926 { 927 char buf1[256]; 928 char buf2[256]; 929 uint32_t *ptr; 930 uint32_t j; 931 932 if (!fpTxtFile) { 933 return (1); 934 } 935 936 /* Write Legend String to the TXT File */ 937 (void) emlxs_fprintf(fpTxtFile, "%s: %s\n", pSidLegend, pLidLegend); 938 939 /* Write the buffer to the TXT File */ 940 ptr = pBuffer; 941 942 for (j = 0; j < WordCount; j++) { 943 buf1[0] = 0; 944 buf2[0] = 0; 945 946 if ((j & 0x03) == 0) { 947 (void) snprintf(buf1, sizeof (buf1), "\n%04x:", j * 4); 948 (void) strlcat(buf2, buf1, sizeof (buf2)); 949 } 950 /* print 1 word */ 951 (void) snprintf(buf1, sizeof (buf1), " %08x", ptr[j]); 952 (void) strlcat(buf2, buf1, sizeof (buf2)); 953 (void) emlxs_fwrite((uint8_t *)buf2, strlen(buf2), 1, 954 fpTxtFile); 955 } 956 957 emlxs_fputc('\n', fpTxtFile); 958 emlxs_fputc('\n', fpTxtFile); 959 emlxs_fflush(fpTxtFile); 960 return (0); 961 962 } /* emlxs_dump_word_txtfile() */ 963 964 965 966 967 static uint32_t 968 emlxs_dump_string_dmpfile( 969 emlxs_file_t *fpDmpFile, 970 char *pString, 971 uint8_t sid, 972 char *pSidLegend, 973 char *pLidLegend) 974 { 975 uint32_t length; 976 uint8_t byte; 977 uint32_t pos; 978 979 if (!fpDmpFile) { 980 return (1); 981 } 982 983 /* Write Legend SID to the DMP File */ 984 emlxs_fputc(SID_LEGEND, fpDmpFile); 985 986 /* Write Argument SID to the DMP File */ 987 emlxs_fputc(sid, fpDmpFile); 988 989 /* Write Legend String to the DMP File, including a Null Byte */ 990 (void) emlxs_fprintf(fpDmpFile, "%s: %s", pSidLegend, pLidLegend); 991 emlxs_fputc(0, fpDmpFile); 992 993 /* Write Argument SID to the DMP File */ 994 emlxs_fputc(sid, fpDmpFile); 995 996 /* Write Buffer Length to the DMP File */ 997 length = (uint32_t)(strlen(pString) + 1); 998 #ifdef EMLXS_LITTLE_ENDIAN 999 byte = (uint8_t)(length & 0x0000FF); 1000 emlxs_fputc(byte, fpDmpFile); 1001 byte = (uint8_t)((length & 0x00FF00) >> 8); 1002 emlxs_fputc(byte, fpDmpFile); 1003 byte = (uint8_t)((length & 0xFF0000) >> 16); 1004 emlxs_fputc(byte, fpDmpFile); 1005 #endif /* EMLXS_LITTLE_ENDIAN */ 1006 1007 #ifdef EMLXS_BIG_ENDIAN 1008 byte = (uint8_t)((length & 0xFF0000) >> 16); 1009 emlxs_fputc(byte, fpDmpFile); 1010 byte = (uint8_t)((length & 0x00FF00) >> 8); 1011 emlxs_fputc(byte, fpDmpFile); 1012 byte = (uint8_t)(length & 0x0000FF); 1013 emlxs_fputc(byte, fpDmpFile); 1014 #endif /* EMLXS_BIG_ENDIAN */ 1015 1016 /* Write Argument String to the DMP File, including a Null Byte */ 1017 (void) emlxs_fwrite((uint8_t *)pString, strlen(pString), 1, fpDmpFile); 1018 emlxs_fputc(0, fpDmpFile); 1019 1020 emlxs_fflush(fpDmpFile); 1021 1022 #if CC_DUMP_ENABLE_PAD 1023 /* check file size.. pad as necessary */ 1024 pos = emlxs_ftell(fpDmpFile); 1025 switch (pos & 0x03) { 1026 case 0: 1027 break; 1028 case 1: 1029 emlxs_fputc(0, fpDmpFile); 1030 emlxs_fputc(0, fpDmpFile); 1031 emlxs_fputc(0, fpDmpFile); 1032 break; 1033 case 2: 1034 emlxs_fputc(0, fpDmpFile); 1035 emlxs_fputc(0, fpDmpFile); 1036 break; 1037 case 3: 1038 emlxs_fputc(0, fpDmpFile); 1039 break; 1040 } 1041 emlxs_fflush(fpDmpFile); 1042 #endif 1043 1044 return (0); 1045 1046 } /* emlxs_dump_string_dmpfile() */ 1047 1048 1049 /* ************************************************************************** */ 1050 /* emlxs_dump_word_dmpfile */ 1051 /* If little endian, just write the buffer normally. */ 1052 /* However, if Big Endian... Consider the following: */ 1053 /* Automatic Dump, initiated by driver, Port Offline (FW WarmStart Mode), */ 1054 /* Mailbox in SLIM. */ 1055 /* On-Demand Dump, initiated by utility, Port Online (FW Normal Mode), */ 1056 /* Mailbox in Host Memory. */ 1057 /* We use the same IOCTL to get the DUMP Data, for both cases. */ 1058 /* However, it normalizes the data before delivering it to us. */ 1059 /* In the Dump File, we must always write the data in native mode. */ 1060 /* So, if Big Endian, On-demand Dump, we must swap the words. */ 1061 /* ************************************************************************* */ 1062 /*ARGSUSED*/ 1063 extern uint32_t 1064 emlxs_dump_word_dmpfile( 1065 emlxs_file_t *fpDmpFile, 1066 uint8_t *pBuffer, 1067 uint32_t bufferLen, 1068 int fSwap) 1069 { 1070 uint32_t i; 1071 uint32_t *wptr; 1072 1073 if (!fpDmpFile) { 1074 return (1); 1075 } 1076 1077 wptr = (uint32_t *)pBuffer; 1078 for (i = 0; i < bufferLen / 4; i++, wptr++) { 1079 if (fSwap) { 1080 uint32_t w1; 1081 w1 = *wptr; 1082 *wptr = BE_SWAP32(w1); 1083 } 1084 1085 (void) emlxs_fwrite((uint8_t *)wptr, 4, 1, fpDmpFile); 1086 } 1087 1088 emlxs_fflush(fpDmpFile); 1089 1090 return (0); 1091 1092 } /* emlxs_dump_word_dmpfile() */ 1093 1094 1095 static uint32_t 1096 emlxs_dump_port_block( 1097 emlxs_file_t *fpDmpFile, 1098 uint8_t *pBuffer, 1099 uint32_t bufferLen, 1100 DUMP_TABLE_ENTRY entry, 1101 int fSwap) 1102 { 1103 uint32_t status; 1104 uint32_t w; 1105 uint8_t b; 1106 1107 if (!fpDmpFile) { 1108 return (1); 1109 } 1110 1111 /* Write Argument SID to the DMP File */ 1112 b = (uint8_t)entry.un.PortBlock.un.s.sid; 1113 emlxs_fputc(b, fpDmpFile); 1114 1115 #ifdef EMLXS_LITTLE_ENDIAN 1116 /* Write Buffer Length to the DMP File */ 1117 w = entry.un.PortBlock.un.s.bc; 1118 b = (uint8_t)(w & 0x000000FF); 1119 emlxs_fputc(b, fpDmpFile); 1120 b = (uint8_t)((w & 0x0000FF00) >> 8); 1121 emlxs_fputc(b, fpDmpFile); 1122 b = (uint8_t)((w & 0x00FF0000) >> 16); 1123 emlxs_fputc(b, fpDmpFile); 1124 1125 /* Write address to the DMP File */ 1126 w = entry.un.PortBlock.un.s.addr; 1127 b = (uint8_t)(w & 0x000000FF); 1128 emlxs_fputc(b, fpDmpFile); 1129 b = (uint8_t)((w & 0x0000FF00) >> 8); 1130 emlxs_fputc(b, fpDmpFile); 1131 b = (uint8_t)((w & 0x00FF0000) >> 16); 1132 emlxs_fputc(b, fpDmpFile); 1133 b = (uint8_t)((w & 0xFF000000) >> 24); 1134 emlxs_fputc(b, fpDmpFile); 1135 #endif /* EMLXS_LITTLE_ENDIAN */ 1136 1137 #ifdef EMLXS_BIG_ENDIAN 1138 /* Write Buffer Length to the DMP File */ 1139 w = entry.un.PortBlock.un.s.bc; 1140 b = (uint8_t)((w & 0x00FF0000) >> 16); 1141 emlxs_fputc(b, fpDmpFile); 1142 b = (uint8_t)((w & 0x0000FF00) >> 8); 1143 emlxs_fputc(b, fpDmpFile); 1144 b = (uint8_t)(w & 0x000000FF); 1145 emlxs_fputc(b, fpDmpFile); 1146 1147 /* Write address to the DMP File */ 1148 w = entry.un.PortBlock.un.s.addr; 1149 b = (uint8_t)((w & 0xFF000000) >> 24); 1150 emlxs_fputc(b, fpDmpFile); 1151 b = (uint8_t)((w & 0x00FF0000) >> 16); 1152 emlxs_fputc(b, fpDmpFile); 1153 b = (uint8_t)((w & 0x0000FF00) >> 8); 1154 emlxs_fputc(b, fpDmpFile); 1155 b = (uint8_t)(w & 0x000000FF); 1156 emlxs_fputc(b, fpDmpFile); 1157 #endif /* EMLXS_BIG_ENDIAN */ 1158 1159 status = 1160 emlxs_dump_word_dmpfile(fpDmpFile, pBuffer, bufferLen, fSwap); 1161 1162 emlxs_fflush(fpDmpFile); 1163 1164 return (status); 1165 1166 } /* emlxs_dump_port_block() */ 1167 1168 1169 static uint32_t 1170 emlxs_dump_port_struct( 1171 emlxs_file_t *fpDmpFile, 1172 uint8_t *pBuffer, 1173 uint32_t bufferLen, 1174 DUMP_TABLE_ENTRY entry, 1175 int fSwap) 1176 { 1177 uint32_t status; 1178 uint32_t w; 1179 uint8_t b; 1180 1181 if (!fpDmpFile) { 1182 return (1); 1183 } 1184 1185 /* Write Argument SID to the DMP File */ 1186 b = (uint8_t)entry.un.PortStruct.un.s.sid; 1187 emlxs_fputc(b, fpDmpFile); 1188 1189 /* Write Element Length to the DMP File */ 1190 b = (uint8_t)entry.un.PortStruct.un.s.length; 1191 emlxs_fputc(b, fpDmpFile); 1192 1193 #ifdef EMLXS_LITTLE_ENDIAN 1194 /* Write Element Count to the DMP File */ 1195 w = entry.un.PortStruct.un.s.count; 1196 b = (uint8_t)(w & 0x000000FF); 1197 emlxs_fputc(b, fpDmpFile); 1198 b = (uint8_t)((w & 0x0000FF00) >> 8); 1199 emlxs_fputc(b, fpDmpFile); 1200 1201 /* Write Address to the DMP File */ 1202 w = entry.un.PortStruct.un.s.addr; 1203 b = (uint8_t)(w & 0x000000FF); 1204 emlxs_fputc(b, fpDmpFile); 1205 b = (uint8_t)((w & 0x0000FF00) >> 8); 1206 emlxs_fputc(b, fpDmpFile); 1207 b = (uint8_t)((w & 0x00FF0000) >> 16); 1208 emlxs_fputc(b, fpDmpFile); 1209 b = (uint8_t)((w & 0xFF000000) >> 24); 1210 emlxs_fputc(b, fpDmpFile); 1211 #endif /* EMLXS_LITTLE_ENDIAN */ 1212 1213 #ifdef EMLXS_BIG_ENDIAN 1214 /* Write Element Count to the DMP File */ 1215 w = entry.un.PortStruct.un.s.count; 1216 b = (uint8_t)((w & 0x0000FF00) >> 8); 1217 emlxs_fputc(b, fpDmpFile); 1218 b = (uint8_t)(w & 0x000000FF); 1219 emlxs_fputc(b, fpDmpFile); 1220 1221 /* Write Address to the DMP File */ 1222 w = entry.un.PortStruct.un.s.addr; 1223 b = (uint8_t)((w & 0xFF000000) >> 24); 1224 emlxs_fputc(b, fpDmpFile); 1225 b = (uint8_t)((w & 0x00FF0000) >> 16); 1226 emlxs_fputc(b, fpDmpFile); 1227 b = (uint8_t)((w & 0x0000FF00) >> 8); 1228 emlxs_fputc(b, fpDmpFile); 1229 b = (uint8_t)(w & 0x000000FF); 1230 emlxs_fputc(b, fpDmpFile); 1231 #endif /* EMLXS_BIG_ENDIAN */ 1232 1233 status = 1234 emlxs_dump_word_dmpfile(fpDmpFile, pBuffer, bufferLen, fSwap); 1235 1236 emlxs_fflush(fpDmpFile); 1237 1238 return (status); 1239 1240 } /* emlxs_dump_port_struct() */ 1241 1242 1243 static uint32_t 1244 emlxs_dump_host_block( 1245 emlxs_file_t *fpDmpFile, 1246 uint8_t *pBuffer, 1247 uint32_t bufferLen, 1248 uint8_t sid, 1249 char *pSidLegend, 1250 char *pLidLegend, 1251 int fSwap) 1252 { 1253 uint32_t status; 1254 uint32_t length; 1255 uint8_t byte; 1256 1257 if (!fpDmpFile) { 1258 return (1); 1259 } 1260 1261 /* Write Legend SID to the DMP File */ 1262 emlxs_fputc(SID_LEGEND, fpDmpFile); 1263 1264 /* Write Argument SID to the DMP File */ 1265 emlxs_fputc(sid, fpDmpFile); 1266 1267 /* Write Legend String to the DMP File, including a Null Byte */ 1268 (void) emlxs_fprintf(fpDmpFile, "%s: %s", pSidLegend, pLidLegend); 1269 emlxs_fputc(0, fpDmpFile); 1270 1271 /* Write Argument SID to the DMP File */ 1272 emlxs_fputc(sid, fpDmpFile); 1273 1274 /* Write Buffer Length to the DMP File */ 1275 length = bufferLen; 1276 #ifdef EMLXS_LITTLE_ENDIAN 1277 byte = (uint8_t)(length & 0x0000FF); 1278 emlxs_fputc(byte, fpDmpFile); 1279 byte = (uint8_t)((length & 0x00FF00) >> 8); 1280 emlxs_fputc(byte, fpDmpFile); 1281 byte = (uint8_t)((length & 0xFF0000) >> 16); 1282 emlxs_fputc(byte, fpDmpFile); 1283 #endif /* EMLXS_LITTLE_ENDIAN */ 1284 1285 #ifdef EMLXS_BIG_ENDIAN 1286 byte = (uint8_t)((length & 0xFF0000) >> 16); 1287 emlxs_fputc(byte, fpDmpFile); 1288 byte = (uint8_t)((length & 0x00FF00) >> 8); 1289 emlxs_fputc(byte, fpDmpFile); 1290 byte = (uint8_t)(length & 0x0000FF); 1291 emlxs_fputc(byte, fpDmpFile); 1292 #endif /* EMLXS_BIG_ENDIAN */ 1293 1294 status = 1295 emlxs_dump_word_dmpfile(fpDmpFile, pBuffer, bufferLen, fSwap); 1296 1297 emlxs_fflush(fpDmpFile); 1298 1299 return (status); 1300 1301 } /* emlxs_dump_host_block() */ 1302 1303 1304 static uint32_t 1305 emlxs_dump_host_struct( 1306 emlxs_file_t *fpDmpFile, 1307 uint8_t *pBuffer, 1308 uint32_t bufferLen, 1309 uint32_t elementLength, 1310 uint32_t elementCount, 1311 uint8_t sid, 1312 char *pSidLegend, 1313 char *pLidLegend, 1314 int fSwap) 1315 { 1316 uint32_t status; 1317 uint32_t w; 1318 uint8_t b; 1319 1320 if (!fpDmpFile) { 1321 return (1); 1322 } 1323 1324 /* Write Legend SID to the DMP File */ 1325 emlxs_fputc(SID_LEGEND, fpDmpFile); 1326 1327 /* Write Argument SID to the DMP File */ 1328 emlxs_fputc(sid, fpDmpFile); 1329 1330 /* Write Legend String to the DMP File, including a Null Byte */ 1331 (void) emlxs_fprintf(fpDmpFile, "%s: %s", pSidLegend, pLidLegend); 1332 emlxs_fputc(0, fpDmpFile); 1333 1334 /* Write Argument SID to the DMP File */ 1335 emlxs_fputc(sid, fpDmpFile); 1336 1337 /* Write Element Length to the DMP File */ 1338 b = (uint8_t)elementLength; 1339 emlxs_fputc(b, fpDmpFile); 1340 1341 /* Write Element Count to the DMP File */ 1342 w = elementCount; 1343 #ifdef EMLXS_LITTLE_ENDIAN 1344 b = (uint8_t)(w & 0x000000FF); 1345 emlxs_fputc(b, fpDmpFile); 1346 b = (uint8_t)((w & 0x0000FF00) >> 8); 1347 emlxs_fputc(b, fpDmpFile); 1348 #endif /* EMLXS_LITTLE_ENDIAN */ 1349 1350 #ifdef EMLXS_BIG_ENDIAN 1351 b = (uint8_t)((w & 0x0000FF00) >> 8); 1352 emlxs_fputc(b, fpDmpFile); 1353 b = (uint8_t)(w & 0x000000FF); 1354 emlxs_fputc(b, fpDmpFile); 1355 #endif /* EMLXS_BIG_ENDIAN */ 1356 1357 status = 1358 emlxs_dump_word_dmpfile(fpDmpFile, pBuffer, bufferLen, fSwap); 1359 1360 emlxs_fflush(fpDmpFile); 1361 1362 return (status); 1363 1364 } /* emlxs_dump_host_struct() */ 1365 1366 1367 /* ************************************************************************* */ 1368 /* ************************************************************************* */ 1369 /* Dump Generators, Mid-Level */ 1370 /* ************************************************************************* */ 1371 /* ************************************************************************* */ 1372 1373 static uint32_t 1374 emlxs_dump_parm_table( 1375 emlxs_hba_t *hba, 1376 emlxs_file_t *fpTxtFile, 1377 emlxs_file_t *fpDmpFile) 1378 { 1379 emlxs_config_t *cfg = &CFG; 1380 uint32_t status; 1381 uint32_t i; 1382 1383 /* vars used to build the Dump String */ 1384 char *buf1; 1385 char *buf2; 1386 1387 buf1 = (char *)kmem_zalloc(8192, KM_SLEEP); 1388 buf2 = (char *)kmem_zalloc(8192, KM_SLEEP); 1389 1390 /* Driver Parameters Heading */ 1391 (void) snprintf(buf1, 8192, 1392 "IDX string Low "\ 1393 "High Def Cur Exp Dyn"); 1394 1395 /* Build the buffer containing all the Driver Params */ 1396 for (i = 0; i < NUM_CFG_PARAM; i++) { 1397 (void) snprintf(buf2, 8192, 1398 "\n %02x: %25s %8x %8x %8x %8x %4x %4x", i, 1399 cfg[i].string, cfg[i].low, cfg[i].hi, cfg[i].def, 1400 cfg[i].current, (cfg[i].flags & PARM_HIDDEN) ? 0 : 1, 1401 (cfg[i].flags & PARM_DYNAMIC) ? 1 : 0); 1402 1403 (void) strlcat(buf1, buf2, 8192); 1404 } 1405 1406 status = 1407 emlxs_dump_string_txtfile(fpTxtFile, buf1, LEGEND_DP_TABLE, 1408 LEGEND_NULL, 0); 1409 1410 status = 1411 emlxs_dump_string_dmpfile(fpDmpFile, buf1, SID_DP_TABLE, 1412 LEGEND_DP_TABLE, LEGEND_NULL); 1413 1414 kmem_free(buf1, 8192); 1415 kmem_free(buf2, 8192); 1416 1417 return (status); 1418 1419 } /* emlxs_dump_parm_table() */ 1420 1421 1422 static uint32_t 1423 emlxs_dump_model( 1424 emlxs_hba_t *hba, 1425 emlxs_file_t *fpTxtFile, 1426 emlxs_file_t *fpDmpFile) 1427 { 1428 emlxs_vpd_t *vpd = &VPD; 1429 uint32_t status; 1430 1431 /* vars used to build the Dump String */ 1432 char buf1[512]; 1433 char buf2[512]; 1434 1435 /* Write the Model into the buffer */ 1436 (void) snprintf(buf2, sizeof (buf2), "%s", vpd->model); 1437 (void) strlcpy(buf1, "Model: ", sizeof (buf1)); 1438 (void) strlcat(buf1, buf2, sizeof (buf1)); 1439 1440 /* Write the Model Description into the buffer */ 1441 (void) snprintf(buf2, sizeof (buf2), "%s", vpd->model_desc); 1442 (void) strlcat(buf1, "\n Description: ", sizeof (buf1)); 1443 (void) strlcat(buf1, buf2, sizeof (buf1)); 1444 1445 status = 1446 emlxs_dump_string_txtfile(fpTxtFile, buf1, LEGEND_HBA_INFO, 1447 LEGEND_HBA_MODEL, 0); 1448 1449 status = 1450 emlxs_dump_string_dmpfile(fpDmpFile, buf1, SID_HBA_INFO, 1451 LEGEND_HBA_INFO, LEGEND_HBA_MODEL); 1452 1453 return (status); 1454 1455 } /* emlxs_dump_model() */ 1456 1457 1458 static uint32_t 1459 emlxs_dump_wwn( 1460 emlxs_hba_t *hba, 1461 emlxs_file_t *fpTxtFile, 1462 emlxs_file_t *fpDmpFile) 1463 { 1464 uint32_t status; 1465 1466 /* vars used to build the Dump String */ 1467 char buf1[512]; 1468 char buf2[512]; 1469 int i; 1470 uint8_t *p; 1471 1472 /* Write the WWPN into the buffer */ 1473 (void) strlcpy(buf1, "Port WWN: ", sizeof (buf1)); 1474 p = (uint8_t *)&hba->wwpn; 1475 for (i = 0; i < 7; i++) { 1476 (void) snprintf(buf2, sizeof (buf2), "%02x:", *p++); 1477 (void) strlcat(buf1, buf2, sizeof (buf1)); 1478 } 1479 (void) snprintf(buf2, sizeof (buf2), "%02x", *p++); 1480 (void) strlcat(buf1, buf2, sizeof (buf1)); 1481 1482 /* Write the WWNN into the buffer */ 1483 (void) strlcat(buf1, "\n Node WWN: ", sizeof (buf1)); 1484 p = (uint8_t *)&hba->wwnn; 1485 for (i = 0; i < 7; i++) { 1486 (void) snprintf(buf2, sizeof (buf2), "%02x:", *p++); 1487 (void) strlcat(buf1, buf2, sizeof (buf1)); 1488 } 1489 (void) snprintf(buf2, sizeof (buf2), "%02x", *p++); 1490 (void) strlcat(buf1, buf2, sizeof (buf1)); 1491 1492 status = 1493 emlxs_dump_string_txtfile(fpTxtFile, buf1, LEGEND_HBA_INFO, 1494 LEGEND_HBA_WWN, 0); 1495 1496 status = 1497 emlxs_dump_string_dmpfile(fpDmpFile, buf1, SID_HBA_INFO, 1498 LEGEND_HBA_INFO, LEGEND_HBA_WWN); 1499 1500 return (status); 1501 1502 } /* emlxs_dump_wwn() */ 1503 1504 1505 static uint32_t 1506 emlxs_dump_serial_number( 1507 emlxs_hba_t *hba, 1508 emlxs_file_t *fpTxtFile, 1509 emlxs_file_t *fpDmpFile) 1510 { 1511 emlxs_vpd_t *vpd = &VPD; 1512 uint32_t status; 1513 1514 /* vars used to build the Dump String */ 1515 char buf1[512]; 1516 char buf2[512]; 1517 1518 /* Write the Serial Number into the buffer */ 1519 (void) snprintf(buf2, sizeof (buf2), "%s", vpd->serial_num); 1520 (void) strlcpy(buf1, LEGEND_HBA_SN, sizeof (buf1)); 1521 (void) strlcat(buf1, ": ", sizeof (buf1)); 1522 (void) strlcat(buf1, buf2, sizeof (buf1)); 1523 1524 status = 1525 emlxs_dump_string_txtfile(fpTxtFile, buf1, LEGEND_HBA_INFO, 1526 LEGEND_HBA_SN, 0); 1527 1528 status = 1529 emlxs_dump_string_dmpfile(fpDmpFile, buf1, SID_HBA_INFO, 1530 LEGEND_HBA_INFO, LEGEND_HBA_SN); 1531 1532 return (status); 1533 1534 } /* emlxs_dump_serial_number() */ 1535 1536 1537 static uint32_t 1538 emlxs_dump_fw_version( 1539 emlxs_hba_t *hba, 1540 emlxs_file_t *fpTxtFile, 1541 emlxs_file_t *fpDmpFile) 1542 { 1543 emlxs_vpd_t *vpd = &VPD; 1544 uint32_t status; 1545 1546 char *buf1; 1547 char *buf2; 1548 uint32_t buf1_size; 1549 uint32_t buf2_size; 1550 1551 buf1_size = 1024; 1552 buf2_size = 1024; 1553 1554 buf1 = (char *)kmem_zalloc(buf1_size, KM_SLEEP); 1555 buf2 = (char *)kmem_zalloc(buf2_size, KM_SLEEP); 1556 1557 /* Write the Firmware Version into the buffer */ 1558 (void) snprintf(buf2, buf2_size, "%s", vpd->fw_version); 1559 (void) strlcpy(buf1, LEGEND_HBA_FW_VERSION, buf1_size); 1560 (void) strlcat(buf1, ": ", buf1_size); 1561 (void) strlcat(buf1, buf2, buf1_size); 1562 1563 /* Write the Operational FW Version into the buffer */ 1564 (void) snprintf(buf2, buf2_size, "%s", vpd->opFwName); 1565 (void) strlcat(buf1, "\n ", buf1_size); 1566 (void) strlcat(buf1, LEGEND_HBA_FW_OPVERSION, buf1_size); 1567 (void) strlcat(buf1, ": ", buf1_size); 1568 (void) strlcat(buf1, buf2, buf1_size); 1569 1570 /* Write the SLI-1 FW Version into the buffer */ 1571 (void) snprintf(buf2, buf2_size, "%s", vpd->sli1FwName); 1572 (void) strlcat(buf1, "\n ", buf1_size); 1573 (void) strlcat(buf1, LEGEND_HBA_FW_SLI1VERSION, buf1_size); 1574 (void) strlcat(buf1, ": ", buf1_size); 1575 (void) strlcat(buf1, buf2, buf1_size); 1576 1577 /* Write the SLI-2 FW Version into the buffer */ 1578 (void) snprintf(buf2, buf2_size, "%s", vpd->sli2FwName); 1579 (void) strlcat(buf1, "\n ", buf1_size); 1580 (void) strlcat(buf1, LEGEND_HBA_FW_SLI2VERSION, buf1_size); 1581 (void) strlcat(buf1, ": ", buf1_size); 1582 (void) strlcat(buf1, buf2, buf1_size); 1583 1584 /* Write the SLI-3 FW Version into the buffer */ 1585 (void) snprintf(buf2, buf2_size, "%s", vpd->sli3FwName); 1586 (void) strlcat(buf1, "\n ", buf1_size); 1587 (void) strlcat(buf1, LEGEND_HBA_FW_SLI3VERSION, buf1_size); 1588 (void) strlcat(buf1, ": ", buf1_size); 1589 (void) strlcat(buf1, buf2, buf1_size); 1590 1591 /* Write the Kernel FW Version into the buffer */ 1592 (void) snprintf(buf2, buf2_size, "%s", vpd->postKernName); 1593 (void) strlcat(buf1, "\n ", buf1_size); 1594 (void) strlcat(buf1, LEGEND_HBA_FW_KERNELVERSION, buf1_size); 1595 (void) strlcat(buf1, ": ", buf1_size); 1596 (void) strlcat(buf1, buf2, buf1_size); 1597 1598 status = 1599 emlxs_dump_string_txtfile(fpTxtFile, buf1, LEGEND_HBA_INFO, 1600 LEGEND_HBA_FW_VERSION, 0); 1601 1602 status = 1603 emlxs_dump_string_dmpfile(fpDmpFile, buf1, SID_HBA_INFO, 1604 LEGEND_HBA_INFO, LEGEND_HBA_FW_VERSION); 1605 1606 kmem_free(buf1, buf1_size); 1607 kmem_free(buf2, buf2_size); 1608 1609 return (status); 1610 1611 } /* emlxs_dump_fw_version() */ 1612 1613 1614 static uint32_t 1615 emlxs_dump_boot_version( 1616 emlxs_hba_t *hba, 1617 emlxs_file_t *fpTxtFile, 1618 emlxs_file_t *fpDmpFile) 1619 { 1620 emlxs_vpd_t *vpd = &VPD; 1621 uint32_t status; 1622 uint32_t state; 1623 1624 char *buf1; 1625 char *buf2; 1626 uint32_t buf1_size; 1627 uint32_t buf2_size; 1628 1629 buf1_size = 1024; 1630 buf2_size = 1024; 1631 1632 buf1 = (char *)kmem_zalloc(buf1_size, KM_SLEEP); 1633 buf2 = (char *)kmem_zalloc(buf2_size, KM_SLEEP); 1634 1635 #ifdef EMLXS_SPARC 1636 if (strcmp(vpd->fcode_version, "none") == 0) 1637 #else 1638 if (strcmp(vpd->boot_version, "none") == 0) 1639 #endif /* EMLXS_SPARC */ 1640 { 1641 state = 2; /* BOOT_BIOS_NOT_PRESENT */ 1642 } else { 1643 state = emlxs_boot_code_state(hba); 1644 } 1645 1646 /* Write the Boot Bios State into the buffer */ 1647 (void) snprintf(buf2, buf2_size, " %d", state); 1648 (void) strlcpy(buf1, LEGEND_HBA_BB_STATE, buf1_size); 1649 (void) strlcat(buf1, ": ", buf1_size); 1650 (void) strlcat(buf1, buf2, buf1_size); 1651 1652 /* Write the Boot Bios Version into the buffer */ 1653 if (state == 2) { 1654 (void) snprintf(buf2, buf2_size, "%s", "unknown"); 1655 } else { 1656 #ifdef EMLXS_SPARC 1657 (void) snprintf(buf2, buf2_size, "%s (FCode)", 1658 vpd->fcode_version); 1659 #else 1660 (void) snprintf(buf2, buf2_size, "%s", vpd->boot_version); 1661 #endif /* EMLXS_SPARC */ 1662 } 1663 1664 (void) strlcat(buf1, "\n ", buf1_size); 1665 (void) strlcat(buf1, LEGEND_HBA_BB_VERSION, buf1_size); 1666 (void) strlcat(buf1, ": ", buf1_size); 1667 (void) strlcat(buf1, buf2, buf1_size); 1668 1669 status = 1670 emlxs_dump_string_txtfile(fpTxtFile, buf1, LEGEND_HBA_INFO, 1671 LEGEND_HBA_BB_VERSION, 0); 1672 1673 status = 1674 emlxs_dump_string_dmpfile(fpDmpFile, buf1, SID_HBA_INFO, 1675 LEGEND_HBA_INFO, LEGEND_HBA_BB_VERSION); 1676 1677 kmem_free(buf1, buf1_size); 1678 kmem_free(buf2, buf2_size); 1679 1680 return (status); 1681 1682 } /* emlxs_dump_boot_version() */ 1683 1684 1685 /* ARGSUSED */ 1686 static uint32_t 1687 emlxs_dump_cfg_region4_decoded( 1688 emlxs_hba_t *hba, 1689 emlxs_file_t *fpTxtFile, 1690 char *pLidLegend, 1691 DUMP_WAKE_UP_PARAMS *pBuffer, 1692 uint32_t ByteCount) 1693 { 1694 uint32_t status; 1695 char *buf1; /* text buffer */ 1696 char *buf2; /* text buffer */ 1697 uint32_t buf1_size; 1698 uint32_t buf2_size; 1699 1700 buf1_size = 1024; 1701 buf2_size = 1024; 1702 1703 buf1 = (char *)kmem_zalloc(buf1_size, KM_SLEEP); 1704 buf2 = (char *)kmem_zalloc(buf2_size, KM_SLEEP); 1705 1706 /* Write the Initial ID into the buffer */ 1707 (void) snprintf(buf2, buf2_size, "%s: %08x %08x", 1708 LEGEND_CR4_INITIAL_LOAD, 1709 pBuffer->InitialId[0], pBuffer->InitialId[1]); 1710 (void) strlcat(buf1, buf2, buf1_size); 1711 1712 /* Write the Flags Word into the buffer */ 1713 (void) snprintf(buf2, buf2_size, "\n %s: %08x", LEGEND_CR4_FLAGS, 1714 pBuffer->Flags); 1715 (void) strlcat(buf1, buf2, buf1_size); 1716 1717 /* Write the Boot Bios ID into the buffer */ 1718 (void) snprintf(buf2, buf2_size, "\n %s: %08x %08x", 1719 LEGEND_CR4_BOOT_BIOS_ID, 1720 pBuffer->BootBiosId[0], pBuffer->BootBiosId[1]); 1721 (void) strlcat(buf1, buf2, buf1_size); 1722 1723 /* Write the SLI1 ID into the buffer */ 1724 (void) snprintf(buf2, buf2_size, "\n %s: %08x %08x", 1725 LEGEND_CR4_SLI1_ID, 1726 pBuffer->Sli1Id[0], pBuffer->Sli1Id[1]); 1727 (void) strlcat(buf1, buf2, buf1_size); 1728 1729 /* Write the SLI2 ID into the buffer */ 1730 (void) snprintf(buf2, buf2_size, "\n %s: %08x %08x", 1731 LEGEND_CR4_SLI2_ID, 1732 pBuffer->Sli2Id[0], pBuffer->Sli2Id[1]); 1733 (void) strlcat(buf1, buf2, buf1_size); 1734 1735 /* Write the SLI3 ID into the buffer */ 1736 (void) snprintf(buf2, buf2_size, "\n %s: %08x %08x", 1737 LEGEND_CR4_SLI3_ID, 1738 pBuffer->Sli3Id[0], pBuffer->Sli3Id[1]); 1739 (void) strlcat(buf1, buf2, buf1_size); 1740 1741 /* Write the SLI4 ID into the buffer */ 1742 (void) snprintf(buf2, buf2_size, "\n %s: %08x %08x", 1743 LEGEND_CR4_SLI4_ID, 1744 pBuffer->Sli4Id[0], pBuffer->Sli4Id[1]); 1745 (void) strlcat(buf1, buf2, buf1_size); 1746 1747 /* Write the Erom ID into the buffer */ 1748 (void) snprintf(buf2, buf2_size, "\n %s: %08x %08x", 1749 LEGEND_CR4_EROM_ID, 1750 pBuffer->EromId[0], pBuffer->EromId[1]); 1751 (void) strlcat(buf1, buf2, buf1_size); 1752 1753 status = 1754 emlxs_dump_string_txtfile(fpTxtFile, buf1, LEGEND_CONFIG_REGION, 1755 LEGEND_CONFIG_REGION_4, 0); 1756 1757 kmem_free(buf1, buf1_size); 1758 kmem_free(buf2, buf2_size); 1759 1760 return (status); 1761 1762 } /* emlxs_dump_cfg_region4_decoded() */ 1763 1764 1765 /* ARGSUSED */ 1766 uint32_t 1767 emlxs_dump_cfg_region14_decoded( 1768 emlxs_hba_t *hba, 1769 emlxs_file_t *fpTxtFile, 1770 char *pLidLegend, 1771 char *pBuffer, 1772 uint32_t ByteCount) 1773 { 1774 uint32_t status; 1775 char *buf1; /* text buffer */ 1776 char *buf2; /* text buffer */ 1777 uint32_t buf1_size; 1778 uint32_t buf2_size; 1779 int i; 1780 uint8_t tag; 1781 uint16_t length; 1782 uint16_t length2; 1783 char mnemonic[4]; 1784 int fDone = FALSE; /* flag to exit VPD loop */ 1785 1786 #ifdef EMLXS_BIG_ENDIAN 1787 uint32_t *wptr; 1788 uint32_t w1; 1789 #endif 1790 1791 buf1_size = 1024; 1792 buf2_size = 1024; 1793 1794 buf1 = (char *)kmem_zalloc(buf1_size, KM_SLEEP); 1795 buf2 = (char *)kmem_zalloc(buf2_size, KM_SLEEP); 1796 1797 /* If Big Endian, swap the data in place, */ 1798 /* because it's PCI Data (Little Endian) */ 1799 #ifdef EMLXS_BIG_ENDIAN 1800 wptr = (uint32_t *)pBuffer; 1801 for (i = 0; i < (int)ByteCount / 4; i++, wptr++) { 1802 w1 = *wptr; 1803 *wptr = BE_SWAP32(w1); 1804 } 1805 #endif /* EMLXS_BIG_ENDIAN */ 1806 1807 /* Decode the VPD Data and write it into the buffer */ 1808 1809 /* CR 26941 */ 1810 /* NOTE: The following code is correct, */ 1811 /* should work, and used to work. */ 1812 /* pBuffer points to char, and the symbol VPD_TAG_82 is 0x82. */ 1813 /* The test is an equality test, not a relational test. */ 1814 /* The compiler should generate an 8 bit test, and */ 1815 /* sign extension does not apply. */ 1816 /* I don't know when or why it stopped working, */ 1817 /* and don't have time to dig. */ 1818 /* The cast fixes it. */ 1819 1820 if (((unsigned char)pBuffer[0]) != VPD_TAG_82) { 1821 (void) snprintf(buf1, buf1_size, 1822 "Bad VPD Data: (w0=0x%08x)", *(uint32_t *)pBuffer); 1823 } else { /* begin good data */ 1824 i = 0; 1825 while (!fDone) { 1826 tag = pBuffer[i++]; 1827 length = pBuffer[i++]; 1828 length |= (pBuffer[i++] << 8); 1829 1830 switch (tag) { 1831 case VPD_TAG_82: 1832 (void) strncpy(buf2, &pBuffer[i], 1833 length > buf2_size ? buf2_size : length); 1834 buf2[length > 1835 (buf2_size - 1) ? (buf2_size - 1836 1) : length] = 0; 1837 (void) strlcat(buf1, "Name: ", buf1_size); 1838 (void) strlcat(buf1, buf2, buf1_size); 1839 i += length; 1840 break; 1841 1842 case VPD_TAG_90: 1843 for (;;) { 1844 mnemonic[0] = pBuffer[i++]; 1845 mnemonic[1] = pBuffer[i++]; 1846 mnemonic[2] = 0; 1847 1848 if (strcmp(mnemonic, "RV") == 0) { 1849 fDone = TRUE; 1850 break; 1851 } 1852 1853 if (mnemonic[0] == 0) { 1854 fDone = TRUE; 1855 break; 1856 } 1857 1858 length2 = pBuffer[i++]; 1859 (void) snprintf(buf2, buf2_size, 1860 "\n %s: ", mnemonic); 1861 (void) strlcat(buf1, buf2, 1862 buf1_size); 1863 (void) strncpy(buf2, &pBuffer[i], 1864 length2 > 1865 buf2_size ? buf2_size : length2); 1866 buf2[length2 > 1867 (buf2_size - 1) ? (buf2_size - 1868 1) : length2] = 0; 1869 (void) strlcat(buf1, buf2, 1870 buf1_size); 1871 i += length2; 1872 } 1873 break; 1874 1875 default: 1876 break; 1877 1878 } /* end switch */ 1879 1880 } /* end while */ 1881 1882 } /* good data */ 1883 1884 status = 1885 emlxs_dump_string_txtfile(fpTxtFile, buf1, LEGEND_CONFIG_REGION, 1886 LEGEND_CONFIG_REGION_14, 0); 1887 1888 kmem_free(buf1, buf1_size); 1889 kmem_free(buf2, buf2_size); 1890 1891 return (status); 1892 1893 } /* emlxs_dump_cfg_region14_decoded() */ 1894 1895 1896 static uint32_t 1897 emlxs_dump_cfg_region( 1898 emlxs_hba_t *hba, 1899 emlxs_file_t *fpTxtFile, 1900 emlxs_file_t *fpDmpFile, 1901 uint8_t Region, 1902 char *pLidLegend, 1903 int fSwap) 1904 { 1905 uint32_t status; 1906 uint32_t RetByteCount = 0; /* returned byte count */ 1907 char *buf1; /* string ops buffer */ 1908 char *buf2; /* string ops buffer */ 1909 uint32_t buf1_size; 1910 uint32_t buf2_size; 1911 uint32_t *buffer; 1912 int i; 1913 1914 #ifdef EMLXS_LITTLE_ENDIAN 1915 fSwap = FALSE; 1916 #endif /* EMLXS_LITTLE_ENDIAN */ 1917 1918 buf1_size = 4096; 1919 buf2_size = 1024; 1920 1921 buf1 = (char *)kmem_zalloc(buf1_size, KM_SLEEP); 1922 buf2 = (char *)kmem_zalloc(buf2_size, KM_SLEEP); 1923 1924 buffer = 1925 (uint32_t *)kmem_zalloc(DUMP_MAX_CONFIG_REGION_LENGTH, KM_SLEEP); 1926 1927 status = 1928 emlxs_read_cfg_region(hba, Region, DUMP_MAX_CONFIG_REGION_LENGTH, 1929 &RetByteCount, (uint8_t *)buffer); 1930 1931 if (status != 0) { 1932 kmem_free(buffer, DUMP_MAX_CONFIG_REGION_LENGTH); 1933 kmem_free(buf1, buf1_size); 1934 kmem_free(buf2, buf2_size); 1935 return (status); 1936 } 1937 1938 /* Write the Data into the buffer */ 1939 for (i = 0; i < (int)RetByteCount / 4; i++) { 1940 if ((i % 8 == 0) && (i != 0)) { 1941 (void) strlcat((char *)buf1, "\n ", buf1_size); 1942 } 1943 1944 (void) snprintf(buf2, buf2_size, "%08x, ", buffer[i]); 1945 (void) strlcat((char *)buf1, buf2, buf1_size); 1946 } 1947 1948 status = 1949 emlxs_dump_string_txtfile(fpTxtFile, buf1, LEGEND_CONFIG_REGION, 1950 pLidLegend, 0); 1951 1952 status = emlxs_dump_host_block(fpDmpFile, 1953 (uint8_t *)buffer, 1954 RetByteCount, 1955 SID_CONFIG_REGION, LEGEND_CONFIG_REGION, pLidLegend, fSwap); 1956 1957 if (Region == 4) { 1958 status = 1959 emlxs_dump_cfg_region4_decoded(hba, fpTxtFile, pLidLegend, 1960 (DUMP_WAKE_UP_PARAMS *)buffer, RetByteCount); 1961 } 1962 1963 if (Region == 14) { 1964 status = 1965 emlxs_dump_cfg_region14_decoded(hba, fpTxtFile, 1966 pLidLegend, (char *)buffer, RetByteCount); 1967 } 1968 1969 kmem_free(buffer, DUMP_MAX_CONFIG_REGION_LENGTH); 1970 kmem_free(buf1, buf1_size); 1971 kmem_free(buf2, buf2_size); 1972 1973 return (status); 1974 1975 } /* emlxs_dump_cfg_region() */ 1976 1977 1978 static uint32_t 1979 emlxs_dump_cfg_regions( 1980 emlxs_hba_t *hba, 1981 emlxs_file_t *fpTxtFile, 1982 emlxs_file_t *fpDmpFile) 1983 { 1984 uint32_t status; 1985 1986 status = 1987 emlxs_dump_cfg_region(hba, fpTxtFile, fpDmpFile, 0, 1988 LEGEND_CONFIG_REGION_0, FALSE); 1989 1990 status = 1991 emlxs_dump_cfg_region(hba, fpTxtFile, fpDmpFile, 1, 1992 LEGEND_CONFIG_REGION_1, FALSE); 1993 1994 status = 1995 emlxs_dump_cfg_region(hba, fpTxtFile, fpDmpFile, 2, 1996 LEGEND_CONFIG_REGION_2, FALSE); 1997 1998 status = 1999 emlxs_dump_cfg_region(hba, fpTxtFile, fpDmpFile, 3, 2000 LEGEND_CONFIG_REGION_3, FALSE); 2001 2002 status = 2003 emlxs_dump_cfg_region(hba, fpTxtFile, fpDmpFile, 4, 2004 LEGEND_CONFIG_REGION_4, FALSE); 2005 2006 status = 2007 emlxs_dump_cfg_region(hba, fpTxtFile, fpDmpFile, 5, 2008 LEGEND_CONFIG_REGION_5, FALSE); 2009 2010 status = 2011 emlxs_dump_cfg_region(hba, fpTxtFile, fpDmpFile, 6, 2012 LEGEND_CONFIG_REGION_6, FALSE); 2013 2014 status = 2015 emlxs_dump_cfg_region(hba, fpTxtFile, fpDmpFile, 7, 2016 LEGEND_CONFIG_REGION_7, FALSE); 2017 2018 status = 2019 emlxs_dump_cfg_region(hba, fpTxtFile, fpDmpFile, 8, 2020 LEGEND_CONFIG_REGION_8, TRUE); 2021 2022 status = 2023 emlxs_dump_cfg_region(hba, fpTxtFile, fpDmpFile, 9, 2024 LEGEND_CONFIG_REGION_9, TRUE); 2025 2026 status = 2027 emlxs_dump_cfg_region(hba, fpTxtFile, fpDmpFile, 10, 2028 LEGEND_CONFIG_REGION_10, TRUE); 2029 2030 status = 2031 emlxs_dump_cfg_region(hba, fpTxtFile, fpDmpFile, 11, 2032 LEGEND_CONFIG_REGION_11, FALSE); 2033 2034 status = 2035 emlxs_dump_cfg_region(hba, fpTxtFile, fpDmpFile, 12, 2036 LEGEND_CONFIG_REGION_12, FALSE); 2037 2038 status = 2039 emlxs_dump_cfg_region(hba, fpTxtFile, fpDmpFile, 13, 2040 LEGEND_CONFIG_REGION_13, FALSE); 2041 2042 status = 2043 emlxs_dump_cfg_region(hba, fpTxtFile, fpDmpFile, 14, 2044 LEGEND_CONFIG_REGION_14, FALSE); 2045 2046 status = 2047 emlxs_dump_cfg_region(hba, fpTxtFile, fpDmpFile, 15, 2048 LEGEND_CONFIG_REGION_15, FALSE); 2049 2050 status = 2051 emlxs_dump_cfg_region(hba, fpTxtFile, fpDmpFile, 16, 2052 LEGEND_CONFIG_REGION_16, FALSE); 2053 2054 status = 2055 emlxs_dump_cfg_region(hba, fpTxtFile, fpDmpFile, 17, 2056 LEGEND_CONFIG_REGION_17, FALSE); 2057 2058 status = 2059 emlxs_dump_cfg_region(hba, fpTxtFile, fpDmpFile, 18, 2060 LEGEND_CONFIG_REGION_18, FALSE); 2061 2062 status = 2063 emlxs_dump_cfg_region(hba, fpTxtFile, fpDmpFile, 19, 2064 LEGEND_CONFIG_REGION_19, FALSE); 2065 2066 status = 2067 emlxs_dump_cfg_region(hba, fpTxtFile, fpDmpFile, 20, 2068 LEGEND_CONFIG_REGION_20, FALSE); 2069 2070 status = 2071 emlxs_dump_cfg_region(hba, fpTxtFile, fpDmpFile, 21, 2072 LEGEND_CONFIG_REGION_21, FALSE); 2073 2074 status = 2075 emlxs_dump_cfg_region(hba, fpTxtFile, fpDmpFile, 22, 2076 LEGEND_CONFIG_REGION_22, FALSE); 2077 2078 status = 2079 emlxs_dump_cfg_region(hba, fpTxtFile, fpDmpFile, 23, 2080 LEGEND_CONFIG_REGION_23, FALSE); 2081 2082 status = 2083 emlxs_dump_cfg_region(hba, fpTxtFile, fpDmpFile, 24, 2084 LEGEND_CONFIG_REGION_24, FALSE); 2085 2086 status = 2087 emlxs_dump_cfg_region(hba, fpTxtFile, fpDmpFile, 25, 2088 LEGEND_CONFIG_REGION_25, FALSE); 2089 2090 status = 2091 emlxs_dump_cfg_region(hba, fpTxtFile, fpDmpFile, 26, 2092 LEGEND_CONFIG_REGION_26, FALSE); 2093 2094 status = 2095 emlxs_dump_cfg_region(hba, fpTxtFile, fpDmpFile, 27, 2096 LEGEND_CONFIG_REGION_27, FALSE); 2097 2098 status = 2099 emlxs_dump_cfg_region(hba, fpTxtFile, fpDmpFile, 28, 2100 LEGEND_CONFIG_REGION_28, FALSE); 2101 2102 status = 2103 emlxs_dump_cfg_region(hba, fpTxtFile, fpDmpFile, 29, 2104 LEGEND_CONFIG_REGION_29, FALSE); 2105 2106 status = 2107 emlxs_dump_cfg_region(hba, fpTxtFile, fpDmpFile, 30, 2108 LEGEND_CONFIG_REGION_30, FALSE); 2109 2110 status = 2111 emlxs_dump_cfg_region(hba, fpTxtFile, fpDmpFile, 31, 2112 LEGEND_CONFIG_REGION_31, FALSE); 2113 2114 status = 2115 emlxs_dump_cfg_region(hba, fpTxtFile, fpDmpFile, 32, 2116 LEGEND_CONFIG_REGION_32, FALSE); 2117 2118 return (status); 2119 2120 } /* emlxs_dump_cfg_regions() */ 2121 2122 2123 /*ARGSUSED*/ 2124 static uint32_t 2125 emlxs_dump_os_version( 2126 emlxs_hba_t *hba, 2127 emlxs_file_t *fpTxtFile, 2128 emlxs_file_t *fpDmpFile) 2129 { 2130 uint32_t status; 2131 char *buf1; 2132 char *buf2; 2133 uint32_t buf1_size; 2134 uint32_t buf2_size; 2135 2136 buf1_size = 1024; 2137 buf2_size = 1024; 2138 2139 buf1 = (char *)kmem_zalloc(buf1_size, KM_SLEEP); 2140 buf2 = (char *)kmem_zalloc(buf2_size, KM_SLEEP); 2141 2142 /* First, write the OS Name string into the buffer */ 2143 (void) strlcpy(buf1, utsname.sysname, buf1_size); 2144 2145 /* Second, write the Version Info into the buffer */ 2146 (void) snprintf(buf2, buf2_size, ", %s", utsname.release); 2147 (void) strlcat(buf1, buf2, buf1_size); 2148 2149 status = 2150 emlxs_dump_string_txtfile(fpTxtFile, buf1, LEGEND_REV_INFO, 2151 LEGEND_REV_OS_VERSION, 0); 2152 2153 status = 2154 emlxs_dump_string_dmpfile(fpDmpFile, buf1, SID_REV_INFO, 2155 LEGEND_REV_INFO, LEGEND_REV_OS_VERSION); 2156 2157 kmem_free(buf1, buf1_size); 2158 kmem_free(buf2, buf2_size); 2159 2160 return (status); 2161 2162 } /* emlxs_dump_os_version() */ 2163 2164 2165 /*ARGSUSED*/ 2166 static uint32_t 2167 emlxs_dump_drv_version( 2168 emlxs_hba_t *hba, 2169 emlxs_file_t *fpTxtFile, 2170 emlxs_file_t *fpDmpFile) 2171 { 2172 uint32_t status; 2173 char *buf1; 2174 char *buf2; 2175 uint32_t buf1_size; 2176 uint32_t buf2_size; 2177 2178 buf1_size = 1024; 2179 buf2_size = 1024; 2180 2181 buf1 = (char *)kmem_zalloc(buf1_size, KM_SLEEP); 2182 buf2 = (char *)kmem_zalloc(buf2_size, KM_SLEEP); 2183 2184 /* Write the Driver Type into the buffer */ 2185 (void) strlcpy(buf1, "Driver Type: ", buf1_size); 2186 (void) strlcat(buf1, DUMP_DRV_LEADVILLE, buf1_size); 2187 2188 /* Write the Driver Name into the buffer */ 2189 (void) snprintf(buf2, buf2_size, "%s", DRIVER_NAME); 2190 (void) strlcat(buf1, "\n Driver Name: ", buf1_size); 2191 (void) strlcat(buf1, buf2, buf1_size); 2192 2193 /* Write the Driver Version into the buffer */ 2194 (void) snprintf(buf2, buf2_size, "%s", emlxs_version); 2195 (void) strlcat(buf1, "\n Driver Version: ", buf1_size); 2196 (void) strlcat(buf1, buf2, buf1_size); 2197 2198 status = 2199 emlxs_dump_string_txtfile(fpTxtFile, buf1, LEGEND_REV_INFO, 2200 LEGEND_REV_DRV_VERSION, 0); 2201 2202 status = 2203 emlxs_dump_string_dmpfile(fpDmpFile, buf1, SID_REV_INFO, 2204 LEGEND_REV_INFO, LEGEND_REV_DRV_VERSION); 2205 2206 kmem_free(buf1, buf1_size); 2207 kmem_free(buf2, buf2_size); 2208 2209 return (status); 2210 2211 } /* emlxs_dump_drv_version() */ 2212 2213 2214 static uint32_t 2215 emlxs_dump_file_create( 2216 emlxs_hba_t *hba, 2217 emlxs_file_t ** fpTxtFile, 2218 emlxs_file_t ** fpDmpFile, 2219 emlxs_file_t ** fpCeeFile) 2220 { 2221 if (fpTxtFile) { 2222 /* Create the Dump Files */ 2223 if ((*fpTxtFile = emlxs_fopen(hba, EMLXS_TXT_FILE)) == NULL) { 2224 return (1); 2225 } 2226 } 2227 2228 if (fpCeeFile) { 2229 *fpCeeFile = NULL; 2230 2231 if ((hba->model_info.vendor_id == PCI_VENDOR_ID_EMULEX && 2232 hba->model_info.device_id == PCI_DEVICE_ID_HORNET) || 2233 (hba->model_info.chip == EMLXS_BE2_CHIP) || 2234 (hba->model_info.chip == EMLXS_BE3_CHIP)) { 2235 if ((*fpCeeFile = 2236 emlxs_fopen(hba, EMLXS_CEE_FILE)) == NULL) { 2237 emlxs_fdelete(*fpTxtFile); 2238 return (1); 2239 } 2240 } 2241 } 2242 2243 if (fpDmpFile) { 2244 if ((*fpDmpFile = emlxs_fopen(hba, EMLXS_DMP_FILE)) == NULL) { 2245 emlxs_fdelete(*fpTxtFile); 2246 emlxs_fdelete(*fpCeeFile); 2247 return (1); 2248 } 2249 2250 /* Initialize the DMP File */ 2251 /* Write the single-byte Dump Identification */ 2252 /* SID to the DMP File */ 2253 #ifdef EMLXS_LITTLE_ENDIAN 2254 emlxs_fputc(SID_DUMP_ID_LE, *fpDmpFile); 2255 #endif /* EMLXS_LITTLE_ENDIAN */ 2256 2257 #ifdef EMLXS_BIG_ENDIAN 2258 emlxs_fputc(SID_DUMP_ID_BE, *fpDmpFile); 2259 #endif /* EMLXS_BIG_ENDIAN */ 2260 2261 emlxs_fputc(SID_NULL, *fpDmpFile); 2262 emlxs_fputc(SID_NULL, *fpDmpFile); 2263 emlxs_fputc(SID_NULL, *fpDmpFile); 2264 emlxs_fflush(*fpDmpFile); 2265 } 2266 2267 return (0); 2268 2269 } /* emlxs_dump_file_create() */ 2270 2271 2272 static uint32_t 2273 emlxs_dump_file_terminate( 2274 emlxs_hba_t *hba, 2275 emlxs_file_t *fpTxtFile, 2276 emlxs_file_t *fpDmpFile, 2277 emlxs_file_t *fpCeeFile) 2278 { 2279 2280 if (fpTxtFile) { 2281 /* Write a suitable string to the Dump TXT File */ 2282 (void) emlxs_fprintf(fpTxtFile, "Dump File End\n"); 2283 emlxs_fflush(fpTxtFile); 2284 } 2285 2286 if (fpCeeFile) { 2287 if (hba->model_info.vendor_id == PCI_VENDOR_ID_EMULEX && 2288 hba->model_info.device_id == PCI_DEVICE_ID_HORNET) { 2289 (void) emlxs_fprintf(fpCeeFile, "Dump File End\n"); 2290 } 2291 2292 emlxs_fflush(fpCeeFile); 2293 } 2294 2295 /* Write the single-byte Dump Termination SID to the DMP File */ 2296 if (fpDmpFile) { 2297 emlxs_fputc(SID_DUMP_TERM, fpDmpFile); 2298 emlxs_fflush(fpDmpFile); 2299 } 2300 2301 2302 return (0); 2303 2304 } /* emlxs_dump_file_terminate() */ 2305 2306 2307 static uint32_t 2308 emlxs_dump_file_close( 2309 emlxs_file_t *fpTxtFile, 2310 emlxs_file_t *fpDmpFile, 2311 emlxs_file_t *fpCeeFile) 2312 { 2313 2314 if (fpTxtFile) { 2315 (void) emlxs_fclose(fpTxtFile); 2316 } 2317 2318 if (fpCeeFile) { 2319 (void) emlxs_fclose(fpCeeFile); 2320 } 2321 2322 if (fpDmpFile) { 2323 (void) emlxs_fclose(fpDmpFile); 2324 } 2325 2326 return (0); 2327 2328 } /* emlxs_dump_file_close() */ 2329 2330 2331 /* ************************************************************************* */ 2332 /* ************************************************************************* */ 2333 /* Dump Generators, High Level */ 2334 /* ************************************************************************* */ 2335 /* ************************************************************************* */ 2336 2337 2338 static uint32_t 2339 emlxs_dump_rev_info( 2340 emlxs_hba_t *hba, 2341 emlxs_file_t *fpTxtFile, 2342 emlxs_file_t *fpDmpFile) 2343 { 2344 (void) emlxs_dump_os_version(hba, fpTxtFile, fpDmpFile); 2345 (void) emlxs_dump_drv_version(hba, fpTxtFile, fpDmpFile); 2346 return (0); 2347 2348 } /* emlxs_dump_rev_info() */ 2349 2350 2351 /* ARGSUSED */ 2352 static uint32_t 2353 emlxs_dump_hba_info( 2354 emlxs_hba_t *hba, 2355 emlxs_file_t *fpTxtFile, 2356 emlxs_file_t *fpDmpFile, 2357 uint32_t dump_type) 2358 { 2359 (void) emlxs_dump_model(hba, fpTxtFile, fpDmpFile); 2360 (void) emlxs_dump_wwn(hba, fpTxtFile, fpDmpFile); 2361 (void) emlxs_dump_serial_number(hba, fpTxtFile, fpDmpFile); 2362 (void) emlxs_dump_fw_version(hba, fpTxtFile, fpDmpFile); 2363 (void) emlxs_dump_boot_version(hba, fpTxtFile, fpDmpFile); 2364 2365 2366 return (0); 2367 2368 } /* emlxs_dump_hba_info() */ 2369 2370 2371 /* ************************************************************************* */ 2372 /* emlxs_dump_table_check */ 2373 /* Examine Dump Table, and determine its size. */ 2374 /* Count and include ID SIDs, and the TERM SID, */ 2375 /* but not the Pointer at Addr 654. */ 2376 /* See comments for CC_DUMP_USE_ALL_TABLES for additional description. */ 2377 /* ************************************************************************* */ 2378 static uint32_t 2379 emlxs_dump_table_check( 2380 emlxs_hba_t *hba, 2381 uint32_t *pSize) 2382 { 2383 emlxs_port_t *port = &PPORT; 2384 int fDone = FALSE; /* loop control flag */ 2385 uint32_t tableSize = 0; /* dump table size (word count) */ 2386 MAILBOX *mb; 2387 MAILBOXQ *mbq; 2388 uint32_t DumpTableAddr; 2389 DUMP_TABLE_ENTRY entry; 2390 2391 *pSize = 0; 2392 2393 /* Read 1 word from low memory at address 654; */ 2394 /* save the returned Dump Table Base Address */ 2395 2396 mbq = 2397 (MAILBOXQ *)kmem_zalloc(sizeof (MAILBOXQ), KM_SLEEP); 2398 mb = (MAILBOX *) mbq; 2399 2400 /* Read the dump table address */ 2401 emlxs_mb_dump(hba, mbq, 0x654, 1); 2402 if (EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbq, MBX_WAIT, 0) != MBX_SUCCESS) { 2403 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg, 2404 "Unable to read dump table address. "\ 2405 "offset=0x654 status=%x", 2406 mb->mbxStatus); 2407 2408 kmem_free(mbq, sizeof (MAILBOXQ)); 2409 return (1); 2410 } 2411 2412 DumpTableAddr = mb->un.varDmp.resp_offset; 2413 2414 if (DumpTableAddr == 0) { 2415 kmem_free(mbq, sizeof (MAILBOXQ)); 2416 return (1); 2417 } 2418 2419 /* Now loop reading Dump Table Entries.. */ 2420 /* break out when we see a Terminator SID */ 2421 while (!fDone) { 2422 emlxs_mb_dump(hba, mbq, DumpTableAddr, 2); 2423 if (EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbq, MBX_WAIT, 0) != 2424 MBX_SUCCESS) { 2425 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg, 2426 "Unable to read dump table entry. "\ 2427 "offset=%x status=%x", 2428 DumpTableAddr, mb->mbxStatus); 2429 2430 kmem_free(mbq, sizeof (MAILBOXQ)); 2431 return (1); 2432 } 2433 2434 entry.un.PortBlock.un.w[0] = mb->un.varWords[4]; 2435 2436 switch (entry.un.PortBlock.un.s.sid) { 2437 /* New Dump Table */ 2438 case SID_ID01: 2439 tableSize++; 2440 DumpTableAddr += 4; 2441 break; 2442 2443 #ifdef CC_DUMP_USE_ALL_TABLES 2444 /* New Dump Table */ 2445 case SID_ID02: 2446 case SID_ID03: 2447 tableSize++; 2448 DumpTableAddr += 4; 2449 break; 2450 #else 2451 /* New Dump Table */ 2452 case SID_ID02: 2453 case SID_ID03: 2454 tableSize++; 2455 fDone = TRUE; 2456 break; 2457 #endif /* CC_DUMP_USE_ALL_TABLES */ 2458 2459 /* Dump Table(s) Termination - all done */ 2460 case SID_TERM: 2461 tableSize++; 2462 fDone = TRUE; 2463 break; 2464 2465 /* Dump Table Entry */ 2466 default: 2467 tableSize += 2; 2468 DumpTableAddr += 8; 2469 break; 2470 } 2471 2472 } /* end while */ 2473 2474 *pSize = (tableSize * 4); /* return the total Dump Table size */ 2475 2476 kmem_free(mbq, sizeof (MAILBOXQ)); 2477 return (0); 2478 2479 } /* emlxs_dump_table_check() */ 2480 2481 2482 /* ************************************************************************ */ 2483 /* emlxs_dump_table_read */ 2484 /* Read the Dump Table and store it, for use */ 2485 /* subsequently in emlxs_dump_hba_memory. */ 2486 /* See comments for CC_DUMP_USE_ALL_TABLES for additional description. */ 2487 /* ************************************************************************ */ 2488 static uint32_t 2489 emlxs_dump_table_read( 2490 emlxs_hba_t *hba, 2491 emlxs_file_t *fpTxtFile, 2492 uint32_t **ppDumpTable, 2493 uint32_t *pDumpTableSize) 2494 { 2495 emlxs_port_t *port = &PPORT; 2496 uint32_t status = 0; 2497 int fDone = FALSE; 2498 MAILBOXQ *mbq; 2499 MAILBOX *mb; 2500 uint32_t *pDumpTableEntry; 2501 uint32_t DumpTableAddr; 2502 DUMP_TABLE_ENTRY entry; 2503 2504 char buf2[256]; 2505 char *buf1; 2506 uint32_t size = (32 * 1024); 2507 2508 /* First, check the dump table and if valid, get its size */ 2509 status = emlxs_dump_table_check(hba, pDumpTableSize); 2510 if (status != 0) { 2511 return (status); 2512 } 2513 2514 buf1 = (char *)kmem_zalloc(size, KM_SLEEP); 2515 2516 /* Allocate a buffer to hold the Dump Table */ 2517 *ppDumpTable = (uint32_t *)kmem_zalloc(*pDumpTableSize, KM_SLEEP); 2518 2519 pDumpTableEntry = *ppDumpTable; 2520 2521 /* Read 1 word from low memory at address 654; */ 2522 /* save the returned Dump Table Base Address */ 2523 mbq = 2524 (MAILBOXQ *)kmem_zalloc(sizeof (MAILBOXQ), KM_SLEEP); 2525 2526 mb = (MAILBOX *) mbq; 2527 2528 /* Read the dump table address */ 2529 emlxs_mb_dump(hba, mbq, 0x654, 1); 2530 if (EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbq, MBX_WAIT, 0) != MBX_SUCCESS) { 2531 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg, 2532 "Unable to read dump table address. "\ 2533 "offset=0x654 status=%x", 2534 mb->mbxStatus); 2535 2536 kmem_free(buf1, size); 2537 kmem_free(mbq, sizeof (MAILBOXQ)); 2538 2539 kmem_free(*ppDumpTable, *pDumpTableSize); 2540 *pDumpTableSize = 0; 2541 *ppDumpTable = NULL; 2542 2543 return (1); 2544 } 2545 2546 DumpTableAddr = mb->un.varDmp.resp_offset; 2547 2548 if (DumpTableAddr == 0) { 2549 kmem_free(buf1, size); 2550 kmem_free(mbq, sizeof (MAILBOXQ)); 2551 2552 kmem_free(*ppDumpTable, *pDumpTableSize); 2553 *pDumpTableSize = 0; 2554 *ppDumpTable = NULL; 2555 2556 return (1); 2557 } 2558 2559 2560 /* Now loop reading Dump Table Entries.. */ 2561 /* break out when we see a Terminator SID */ 2562 while (!fDone) { 2563 emlxs_mb_dump(hba, mbq, DumpTableAddr, 2); 2564 if (EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbq, MBX_WAIT, 0) != 2565 MBX_SUCCESS) { 2566 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg, 2567 "Unable to read dump table entry. "\ 2568 "offset=%x status=%x", 2569 DumpTableAddr, mb->mbxStatus); 2570 2571 kmem_free(buf1, size); 2572 kmem_free(mbq, sizeof (MAILBOXQ)); 2573 2574 kmem_free(*ppDumpTable, *pDumpTableSize); 2575 *pDumpTableSize = 0; 2576 *ppDumpTable = NULL; 2577 2578 return (1); 2579 } 2580 2581 (void) snprintf(buf2, sizeof (buf2), "\n Addr=%08x: ", 2582 mb->un.varDmp.base_adr); 2583 (void) strlcat(buf1, buf2, size); 2584 2585 entry.un.PortBlock.un.w[0] = mb->un.varWords[4]; 2586 *pDumpTableEntry++ = mb->un.varWords[4]; 2587 2588 switch (entry.un.PortBlock.un.s.sid) { 2589 /* New Dump Table */ 2590 case SID_ID01: 2591 (void) snprintf(buf2, sizeof (buf2), "w0=%08x", 2592 entry.un.PortBlock.un.w[0]); 2593 (void) strlcat(buf1, buf2, size); 2594 DumpTableAddr += 4; 2595 break; 2596 2597 #ifdef CC_DUMP_USE_ALL_TABLES 2598 /* New Dump Table */ 2599 case SID_ID02: 2600 case SID_ID03: 2601 (void) snprintf(buf2, sizeof (buf2), "w0=%08x", 2602 entry.un.PortBlock.un.w[0]); 2603 (void) strlcat(buf1, buf2, size); 2604 DumpTableAddr += 4; 2605 break; 2606 #else 2607 /* New Dump Table */ 2608 case SID_ID02: 2609 case SID_ID03: 2610 (void) snprintf(buf2, sizeof (buf2), "w0=%08x", 2611 entry.un.PortBlock.un.w[0]); 2612 (void) strlcat(buf1, buf2, size); 2613 fDone = TRUE; 2614 break; 2615 #endif /* CC_DUMP_USE_ALL_TABLES */ 2616 2617 /* Dump Table(s) Termination - all done */ 2618 case SID_TERM: 2619 (void) snprintf(buf2, sizeof (buf2), "w0=%08x", 2620 entry.un.PortBlock.un.w[0]); 2621 (void) strlcat(buf1, buf2, size); 2622 fDone = TRUE; 2623 break; 2624 2625 /* Dump Table Entry */ 2626 default: 2627 entry.un.PortBlock.un.w[1] = mb->un.varWords[5]; 2628 *pDumpTableEntry++ = mb->un.varWords[5]; 2629 2630 (void) snprintf(buf2, sizeof (buf2), "w0=%08x, w1=%08x", 2631 entry.un.PortBlock.un.w[0], 2632 entry.un.PortBlock.un.w[1]); 2633 (void) strlcat(buf1, buf2, size); 2634 DumpTableAddr += 8; 2635 break; 2636 } 2637 2638 } /* end while */ 2639 2640 status = 2641 emlxs_dump_string_txtfile(fpTxtFile, buf1, LEGEND_HBA_MEM_DUMP, 2642 LEGEND_HBA_MEM_DUMP_TABLE, 0); 2643 2644 kmem_free(buf1, size); 2645 kmem_free(mbq, sizeof (MAILBOXQ)); 2646 2647 if (status != 0) { 2648 kmem_free(*ppDumpTable, *pDumpTableSize); 2649 *pDumpTableSize = 0; 2650 *ppDumpTable = NULL; 2651 2652 return (status); 2653 } 2654 2655 return (0); 2656 2657 } /* emlxs_dump_table_read() */ 2658 2659 2660 /* ************************************************************************* */ 2661 /* emlxs_dump_hba_memory */ 2662 /* Guided by the Dump Table previously read in, */ 2663 /* generate the Port Memory Dump. */ 2664 /* See comments for CC_DUMP_USE_ALL_TABLES for additional description. */ 2665 /* ************************************************************************* */ 2666 static uint32_t 2667 emlxs_dump_hba_memory( 2668 emlxs_hba_t *hba, 2669 emlxs_file_t *fpDmpFile, 2670 uint32_t *pDumpTable) 2671 { 2672 emlxs_port_t *port = &PPORT; 2673 uint32_t status = 0; 2674 int fDone = FALSE; 2675 DUMP_TABLE_ENTRY entry; 2676 MAILBOXQ *mbq; 2677 MAILBOX *mb; 2678 uint32_t byteCount; 2679 uint32_t byteCountRem; 2680 uint8_t *pBuf; 2681 uint8_t *p1; 2682 uint32_t portAddr; 2683 int fSwap = FALSE; 2684 uint32_t offset = 0; 2685 uint32_t wcount; 2686 uint32_t total = 0; 2687 2688 #ifdef EMLXS_BIG_ENDIAN 2689 fSwap = TRUE; 2690 #endif /* EMLXS_BIG_ENDIAN */ 2691 2692 if (!fpDmpFile) { 2693 return (1); 2694 } 2695 2696 mbq = 2697 (MAILBOXQ *)kmem_zalloc(sizeof (MAILBOXQ), KM_SLEEP); 2698 2699 mb = (MAILBOX *) mbq; 2700 2701 /* loop reading Dump Table Entries.. break out when */ 2702 /* we see a Terminator SID */ 2703 while (!fDone) { 2704 entry.un.PortBlock.un.w[0] = *pDumpTable++; 2705 2706 switch (entry.un.PortBlock.un.s.sid) { 2707 2708 /* New Dump Table */ 2709 case SID_ID01: 2710 break; 2711 2712 #ifdef CC_DUMP_USE_ALL_TABLES 2713 /* New Dump Table */ 2714 case SID_ID02: 2715 case SID_ID03: 2716 break; 2717 #else 2718 /* New Dump Table */ 2719 case SID_ID02: 2720 case SID_ID03: 2721 fDone = TRUE; 2722 break; 2723 #endif /* CC_DUMP_USE_ALL_TABLES */ 2724 2725 /* Dump Table(s) Termination - all done */ 2726 case SID_TERM: 2727 fDone = TRUE; 2728 break; 2729 2730 default: 2731 /* Dump Table Entry */ 2732 entry.un.PortBlock.un.w[1] = *pDumpTable++; 2733 2734 #ifdef CC_DUMP_FW_BUG_1 2735 if (entry.un.PortBlock.un.w[1] == 0x3E0000) { 2736 break; 2737 } 2738 #endif /* CC_DUMP_FW_BUG_1 */ 2739 2740 /* Check if indirect address, and */ 2741 /* obtain the new address if so */ 2742 if ((entry.un.PortBlock.un.s.addr & 0x80000000) != 0) { 2743 offset = 2744 (entry.un.PortBlock.un.s. 2745 addr & 0x01FFFFFF); 2746 emlxs_mb_dump(hba, mbq, offset, 1); 2747 if (EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbq, MBX_WAIT, 2748 0) != MBX_SUCCESS) { 2749 EMLXS_MSGF(EMLXS_CONTEXT, 2750 &emlxs_init_debug_msg, 2751 "Unable to read dump table entry. "\ 2752 "offset=%x status=%x", 2753 offset, mb->mbxStatus); 2754 2755 kmem_free(mbq, sizeof (MAILBOXQ)); 2756 return (1); 2757 } 2758 2759 /* replace the indirect address in the */ 2760 /* Dump Table */ 2761 entry.un.PortBlock.un.s.addr = 2762 mb->un.varWords[4]; 2763 } 2764 2765 /* determine byte count to dump */ 2766 byteCount = entry.un.PortBlock.un.s.bc; 2767 if (entry.un.PortBlock.un.s.sid & SID_MULT_ELEM) { 2768 if (entry.un.PortStruct.un.s.count == 0) { 2769 byteCount = 2770 256 * 2771 entry.un.PortStruct.un.s.length; 2772 } else { 2773 byteCount = 2774 entry.un.PortStruct.un.s.count * 2775 entry.un.PortStruct.un.s.length; 2776 } 2777 } 2778 2779 total += byteCount; 2780 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg, 2781 "Dump: addr=%x count=%d total=%d", offset, 2782 byteCount, total); 2783 2784 /* allocate a buffer to receive the dump data */ 2785 pBuf = (uint8_t *)kmem_zalloc(byteCount, KM_SLEEP); 2786 2787 /* loop issuing MBX commands, 18x measly words at */ 2788 /* a time */ 2789 2790 /* init vars */ 2791 byteCountRem = byteCount; 2792 p1 = pBuf; 2793 portAddr = entry.un.PortBlock.un.s.addr; 2794 2795 for (;;) { 2796 if (byteCountRem == 0) { 2797 break; 2798 } 2799 2800 wcount = 2801 (byteCountRem / 4 >= 2802 0x18) ? 0x18 : (byteCountRem / 4); 2803 emlxs_mb_dump(hba, mbq, portAddr, wcount); 2804 if (EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbq, MBX_WAIT, 2805 0) != MBX_SUCCESS) { 2806 EMLXS_MSGF(EMLXS_CONTEXT, 2807 &emlxs_init_debug_msg, 2808 "Unable to read dump table entry."\ 2809 " offset=%x wc=%d status=%x", 2810 portAddr, wcount, mb->mbxStatus); 2811 break; 2812 } 2813 2814 bcopy((uint8_t *)&mb->un.varWords[4], p1, 2815 (mb->un.varDmp.word_cnt * 4)); 2816 2817 byteCountRem -= (mb->un.varDmp.word_cnt * 4); 2818 p1 += (mb->un.varDmp.word_cnt * 4); 2819 portAddr += (mb->un.varDmp.word_cnt * 4); 2820 2821 } /* end for */ 2822 2823 if (status == 0) { 2824 if (entry.un.PortBlock.un.s. 2825 sid & SID_MULT_ELEM) { 2826 status = 2827 emlxs_dump_port_struct(fpDmpFile, 2828 pBuf, byteCount, entry, fSwap); 2829 } else { 2830 status = 2831 emlxs_dump_port_block(fpDmpFile, 2832 pBuf, byteCount, entry, fSwap); 2833 } 2834 } 2835 2836 if (pBuf) { 2837 kmem_free(pBuf, byteCount); 2838 } 2839 2840 break; 2841 2842 } /* end switch */ 2843 2844 } /* end while */ 2845 2846 kmem_free(mbq, sizeof (MAILBOXQ)); 2847 2848 return (status); 2849 2850 } /* emlxs_dump_hba_memory() */ 2851 2852 2853 static uint32_t 2854 emlxs_dump_hba( 2855 emlxs_hba_t *hba, 2856 emlxs_file_t *fpTxtFile, 2857 emlxs_file_t *fpDmpFile) 2858 { 2859 uint32_t status = 0; 2860 uint32_t *pDumpTable = 0; 2861 uint32_t DumpTableSize = 0; 2862 2863 if (hba->sli_mode >= EMLXS_HBA_SLI4_MODE) { 2864 return (1); 2865 } 2866 2867 /* HBA should be in WARM state here */ 2868 status = 2869 emlxs_dump_table_read(hba, fpTxtFile, &pDumpTable, 2870 &DumpTableSize); 2871 if (status) { 2872 return (status); 2873 } 2874 2875 status = emlxs_dump_hba_memory(hba, fpDmpFile, pDumpTable); 2876 2877 if (pDumpTable != 0) { 2878 kmem_free(pDumpTable, DumpTableSize); 2879 } 2880 2881 return (status); 2882 2883 } /* emlxs_dump_hba() */ 2884 2885 2886 /* ************************************************************************* */ 2887 /* emlxs_dump_drv_region */ 2888 /* Common subroutine for all the Dump_Sli"Structures" Routines */ 2889 /* NOTE: This routine does not free pBuf. This is by design. */ 2890 /* The caller does it. */ 2891 /* ************************************************************************* */ 2892 static uint32_t 2893 emlxs_dump_drv_region( 2894 emlxs_hba_t *hba, 2895 uint32_t regionId, 2896 uint8_t **pBuf, 2897 uint32_t *pBufLen) 2898 { /* ptr to length of buffer */ 2899 uint32_t status; 2900 uint32_t size; 2901 2902 *pBuf = NULL; 2903 *pBufLen = 0; 2904 2905 size = 0; 2906 status = emlxs_get_dump_region(hba, regionId, NULL, &size); 2907 2908 if (status != 0) { 2909 return (1); 2910 } 2911 2912 /* Now that we know the required length, request the actual data */ 2913 *pBuf = (uint8_t *)kmem_zalloc(size, KM_SLEEP); 2914 2915 status = emlxs_get_dump_region(hba, regionId, *pBuf, &size); 2916 2917 if (status != 0) { 2918 kmem_free(*pBuf, size); 2919 *pBuf = NULL; 2920 2921 return (1); 2922 } 2923 2924 *pBufLen = size; 2925 2926 return (status); 2927 2928 } /* emlxs_dump_drv_region() */ 2929 2930 2931 static uint32_t 2932 emlxs_dump_sli_regs( 2933 emlxs_hba_t *hba, 2934 emlxs_file_t *fpDmpFile) 2935 { 2936 uint32_t status; 2937 uint8_t *pBuf; /* ptr to data buffer to receive Dump Region Data */ 2938 uint32_t bufLen = 0; /* length of buffer */ 2939 int fSwap = FALSE; /* flag to pass to emlxs_dump_word_dmpfile */ 2940 2941 #ifdef EMLXS_BIG_ENDIAN 2942 fSwap = TRUE; 2943 #endif /* EMLXS_BIG_ENDIAN */ 2944 2945 if (!fpDmpFile) { 2946 return (1); 2947 } 2948 2949 status = emlxs_dump_drv_region(hba, DR_SLI_REGS, &pBuf, &bufLen); 2950 2951 if (status != 0) { 2952 return (status); 2953 } 2954 2955 status = 2956 emlxs_dump_host_block(fpDmpFile, pBuf, bufLen, SID_SLI_REGS, 2957 LEGEND_SLI_STRUCTURES, LEGEND_SLI_REGS, fSwap); 2958 2959 kmem_free(pBuf, bufLen); 2960 2961 return (status); 2962 2963 } /* emlxs_dump_sli_regs() */ 2964 2965 2966 static uint32_t 2967 emlxs_dump_slim( 2968 emlxs_hba_t *hba, 2969 emlxs_file_t *fpTxtFile, 2970 emlxs_file_t *fpDmpFile, 2971 uint32_t dump_type) 2972 { 2973 uint32_t status; 2974 uint8_t *pBuf; /* ptr to data buffer to receive Dump Region Data */ 2975 uint32_t bufLen = 0; /* length of buffer */ 2976 int fSwap = FALSE; /* flag to pass to emlxs_dump_word_dmpfile */ 2977 2978 #ifdef EMLXS_BIG_ENDIAN 2979 fSwap = TRUE; 2980 #endif /* EMLXS_BIG_ENDIAN */ 2981 2982 status = emlxs_dump_drv_region(hba, DR_SLIM, &pBuf, &bufLen); 2983 2984 if (status != 0) { 2985 return (status); 2986 } 2987 2988 /* The SLIM Dump is only useful if it's a */ 2989 /* Driver-Initiated dump, say, after a HW Error */ 2990 if (dump_type == DUMP_TYPE_DRIVER) { 2991 status = 2992 emlxs_dump_word_txtfile(fpTxtFile, (uint32_t *)pBuf, 2993 0x40, LEGEND_SLI_STRUCTURES, LEGEND_SLIM); 2994 } 2995 2996 status = 2997 emlxs_dump_host_block(fpDmpFile, pBuf, bufLen, SID_SLIM, 2998 LEGEND_SLI_STRUCTURES, LEGEND_SLIM, fSwap); 2999 3000 kmem_free(pBuf, bufLen); 3001 3002 return (status); 3003 3004 } /* emlxs_dump_slim() */ 3005 3006 3007 static uint32_t 3008 emlxs_dump_pcb( 3009 emlxs_hba_t *hba, 3010 emlxs_file_t *fpDmpFile) 3011 { 3012 uint32_t status; 3013 uint8_t *pBuf; /* ptr to data buffer to receive Dump Region Data */ 3014 uint32_t bufLen = 0; /* length of buffer */ 3015 int fSwap = FALSE; /* flag to pass to emlxs_dump_word_dmpfile */ 3016 3017 #ifdef EMLXS_BIG_ENDIAN 3018 fSwap = TRUE; 3019 #endif /* EMLXS_BIG_ENDIAN */ 3020 3021 if (!fpDmpFile) { 3022 return (1); 3023 } 3024 3025 status = emlxs_dump_drv_region(hba, DR_PCB, &pBuf, &bufLen); 3026 if (status != 0) { 3027 return (status); 3028 } 3029 3030 status = 3031 emlxs_dump_host_block(fpDmpFile, pBuf, bufLen, SID_PCB, 3032 LEGEND_SLI_STRUCTURES, LEGEND_PCB, fSwap); 3033 3034 kmem_free(pBuf, bufLen); 3035 3036 return (status); 3037 3038 } /* emlxs_dump_pcb() */ 3039 3040 3041 static uint32_t 3042 emlxs_dump_mbox( 3043 emlxs_hba_t *hba, 3044 emlxs_file_t *fpDmpFile) 3045 { 3046 uint32_t status; 3047 uint8_t *pBuf; /* ptr to data buffer to receive Dump Region Data */ 3048 uint32_t bufLen = 0; /* length of buffer */ 3049 int fSwap = FALSE; /* flag to pass to emlxs_dump_word_dmpfile */ 3050 3051 #ifdef EMLXS_BIG_ENDIAN 3052 fSwap = TRUE; 3053 #endif /* EMLXS_BIG_ENDIAN */ 3054 3055 if (!fpDmpFile) { 3056 return (1); 3057 } 3058 3059 status = emlxs_dump_drv_region(hba, DR_MBX, &pBuf, &bufLen); 3060 if (status != 0) { 3061 return (status); 3062 } 3063 3064 status = 3065 emlxs_dump_host_block(fpDmpFile, pBuf, bufLen, SID_MBX, 3066 LEGEND_SLI_STRUCTURES, LEGEND_MBX, fSwap); 3067 3068 kmem_free(pBuf, bufLen); 3069 3070 return (status); 3071 3072 } /* emlxs_dump_mbox() */ 3073 3074 3075 static uint32_t 3076 emlxs_dump_host_pointers( 3077 emlxs_hba_t *hba, 3078 emlxs_file_t *fpDmpFile) 3079 { 3080 uint32_t status; 3081 uint8_t *pBuf; /* ptr to data buffer to receive Dump Region Data */ 3082 uint32_t bufLen = 0; /* length of buffer */ 3083 int fSwap = FALSE; /* flag to pass to emlxs_dump_word_dmpfile */ 3084 3085 #ifdef EMLXS_BIG_ENDIAN 3086 fSwap = TRUE; 3087 #endif /* EMLXS_BIG_ENDIAN */ 3088 3089 if (!fpDmpFile) { 3090 return (1); 3091 } 3092 3093 status = emlxs_dump_drv_region(hba, DR_HOST_PTRS, &pBuf, &bufLen); 3094 if (status != 0) { 3095 return (status); 3096 } 3097 3098 status = 3099 emlxs_dump_host_block(fpDmpFile, pBuf, bufLen, SID_HOST_PTRS, 3100 LEGEND_SLI_STRUCTURES, LEGEND_HOST_PTRS, fSwap); 3101 3102 kmem_free(pBuf, bufLen); 3103 3104 return (status); 3105 3106 } /* emlxs_dump_host_pointers() */ 3107 3108 3109 static uint32_t 3110 emlxs_dump_port_pointers( 3111 emlxs_hba_t *hba, 3112 emlxs_file_t *fpDmpFile) 3113 { 3114 uint32_t status; 3115 uint8_t *pBuf; /* ptr to data buffer to receive Dump Region Data */ 3116 uint32_t bufLen = 0; /* length of buffer */ 3117 int fSwap = FALSE; /* flag to pass to emlxs_dump_word_dmpfile */ 3118 3119 #ifdef EMLXS_BIG_ENDIAN 3120 fSwap = TRUE; 3121 #endif /* EMLXS_BIG_ENDIAN */ 3122 3123 if (!fpDmpFile) { 3124 return (1); 3125 } 3126 3127 status = emlxs_dump_drv_region(hba, DR_PORT_PTRS, &pBuf, &bufLen); 3128 if (status != 0) { 3129 return (status); 3130 } 3131 3132 status = 3133 emlxs_dump_host_block(fpDmpFile, pBuf, bufLen, SID_PORT_PTRS, 3134 LEGEND_SLI_STRUCTURES, LEGEND_PORT_PTRS, fSwap); 3135 3136 kmem_free(pBuf, bufLen); 3137 3138 return (status); 3139 3140 } /* emlxs_dump_port_pointers() */ 3141 3142 3143 static uint32_t 3144 emlxs_dump_rings( 3145 emlxs_hba_t *hba, 3146 emlxs_file_t *fpDmpFile) 3147 { 3148 uint32_t status; 3149 uint8_t *pBuf; /* ptr to data buffer to receive Dump Region Data */ 3150 uint32_t bufLen = 0; /* length of buffer */ 3151 int fSwap = FALSE; /* flag to pass to emlxs_dump_word_dmpfile */ 3152 3153 #ifdef EMLXS_BIG_ENDIAN 3154 fSwap = TRUE; 3155 #endif /* EMLXS_BIG_ENDIAN */ 3156 3157 if (!fpDmpFile) { 3158 return (1); 3159 } 3160 3161 status = emlxs_dump_drv_region(hba, DR_RINGS, &pBuf, &bufLen); 3162 if (status != 0) { 3163 return (status); 3164 } 3165 3166 status = 3167 emlxs_dump_host_struct(fpDmpFile, pBuf, bufLen, sizeof (IOCB), 3168 bufLen / sizeof (IOCB), SID_RINGS, LEGEND_SLI_STRUCTURES, 3169 LEGEND_RINGS, fSwap); 3170 3171 kmem_free(pBuf, bufLen); 3172 3173 return (status); 3174 3175 } /* emlxs_dump_rings() */ 3176 3177 3178 static uint32_t 3179 emlxs_dump_drv_internals( 3180 emlxs_hba_t *hba, 3181 emlxs_file_t *fpDmpFile) 3182 { 3183 uint32_t status; 3184 uint8_t *pBuf; /* ptr to data buffer to receive Dump Region Data */ 3185 uint32_t bufLen = 0; /* length of buffer */ 3186 int fSwap = FALSE; /* flag to pass to emlxs_dump_word_dmpfile */ 3187 3188 #ifdef EMLXS_BIG_ENDIAN 3189 fSwap = TRUE; 3190 #endif /* EMLXS_BIG_ENDIAN */ 3191 3192 if (!fpDmpFile) { 3193 return (1); 3194 } 3195 3196 status = emlxs_dump_drv_region(hba, DR_INTERNAL, &pBuf, &bufLen); 3197 if (status != 0) { 3198 return (status); 3199 } 3200 3201 status = 3202 emlxs_dump_host_block(fpDmpFile, pBuf, bufLen, SID_INTERNAL_SOL, 3203 LEGEND_SLI_STRUCTURES, LEGEND_DRIVER_SPEC, fSwap); 3204 3205 kmem_free(pBuf, bufLen); 3206 3207 return (status); 3208 3209 } /* emlxs_dump_drv_internals() */ 3210 3211 3212 static uint32_t 3213 emlxs_dump_sli_interface( 3214 emlxs_hba_t *hba, 3215 emlxs_file_t *fpTxtFile, 3216 emlxs_file_t *fpDmpFile, 3217 uint32_t dump_type) 3218 { 3219 3220 if (hba->sli_mode <= EMLXS_HBA_SLI3_MODE) { 3221 /* HBA should be in OFFLINE state here */ 3222 3223 (void) emlxs_dump_sli_regs(hba, fpDmpFile); 3224 (void) emlxs_dump_slim(hba, fpTxtFile, fpDmpFile, dump_type); 3225 (void) emlxs_dump_pcb(hba, fpDmpFile); 3226 (void) emlxs_dump_mbox(hba, fpDmpFile); 3227 (void) emlxs_dump_host_pointers(hba, fpDmpFile); 3228 (void) emlxs_dump_port_pointers(hba, fpDmpFile); 3229 (void) emlxs_dump_rings(hba, fpDmpFile); 3230 } 3231 3232 (void) emlxs_dump_drv_internals(hba, fpDmpFile); 3233 3234 return (0); 3235 3236 } /* emlxs_dump_sli_interface() */ 3237 3238 3239 static uint32_t 3240 emlxs_dump_menlo_log( 3241 emlxs_hba_t *hba, 3242 emlxs_file_t *fpCeeFile) 3243 { 3244 uint32_t RmStatus; 3245 int i, j; 3246 int isWrapped = FALSE; 3247 char buf1[2048] = { 0 }; 3248 char buf2[2048] = { 0 }; 3249 3250 /* Get Config Command vars */ 3251 menlo_get_config_rsp_t GcBuf; 3252 menlo_get_config_rsp_t *pGcBuf = &GcBuf; 3253 3254 /* Get Log Config Command vars */ 3255 uint32_t LcBufSize; 3256 menlo_rsp_t *pLcBuf = NULL; 3257 uint32_t NumLogs; 3258 menlo_log_t *pLcEntry; 3259 3260 /* Get Log Data Command vars */ 3261 uint32_t LdBufSize; 3262 menlo_rsp_t *pLdBuf = NULL; 3263 uint16_t Head; 3264 uint8_t *pLogEntry; 3265 char *pLogString; 3266 3267 /* Get Panic Log Command vars */ 3268 uint32_t PlBufSize; 3269 menlo_rsp_t *pPlBuf = NULL; 3270 uint32_t PanicLogEntryCount; 3271 uint32_t PanicLogEntrySize; 3272 3273 if (hba->model_info.vendor_id != PCI_VENDOR_ID_EMULEX || 3274 hba->model_info.device_id != PCI_DEVICE_ID_HORNET) { 3275 return (DFC_INVALID_ADAPTER); 3276 } 3277 3278 /* First, issue a GetConfig command, which gives us */ 3279 /* the Log Config and Panic Log sizes */ 3280 3281 RmStatus = 3282 emlxs_menlo_get_cfg(hba, pGcBuf, sizeof (menlo_get_config_rsp_t)); 3283 3284 if (RmStatus != 0) { 3285 goto done; 3286 } 3287 3288 LcBufSize = GcBuf.log_cfg_size + 8; 3289 PlBufSize = GcBuf.panic_log_size; 3290 3291 pLcBuf = (menlo_rsp_t *)kmem_zalloc(LcBufSize, KM_SLEEP); 3292 3293 RmStatus = emlxs_menlo_get_logcfg(hba, pLcBuf, LcBufSize); 3294 3295 if (RmStatus != 0) { 3296 goto done; 3297 } 3298 3299 buf1[0] = 0; 3300 RmStatus = 3301 emlxs_dump_string_txtfile(fpCeeFile, buf1, 3302 LEGEND_MENLO_LOG_CONFIG, LEGEND_NULL, 0); 3303 3304 NumLogs = pLcBuf->log_cfg.num_logs; 3305 pLcEntry = (menlo_log_t *)&pLcBuf->log_cfg.data; 3306 3307 buf1[0] = 0; 3308 (void) snprintf(buf2, sizeof (buf2), "LogId Entries Size Name"); 3309 (void) strlcat(buf1, buf2, sizeof (buf1)); 3310 (void) snprintf(buf2, sizeof (buf2), "\n----- ------- ---- ----"); 3311 (void) strlcat(buf1, buf2, sizeof (buf1)); 3312 3313 RmStatus = emlxs_dump_string_txtfile(fpCeeFile, buf1, 0, 0, 1); 3314 3315 for (i = 0; i < (int)NumLogs; i++) { 3316 buf1[0] = 0; 3317 (void) snprintf(buf2, sizeof (buf2), 3318 "\n %2d %4d %4d %s", 3319 pLcEntry[i].id, 3320 pLcEntry[i].num_entries, 3321 pLcEntry[i].entry_size, pLcEntry[i].name); 3322 (void) strlcat(buf1, buf2, sizeof (buf1)); 3323 RmStatus = 3324 emlxs_dump_string_txtfile(fpCeeFile, buf1, 0, 0, 1); 3325 } 3326 3327 /* Now issue a series of GetLogData commands, */ 3328 /* which gives us the actual Logs */ 3329 3330 for (i = 0; i < (int)NumLogs; i++) { 3331 LdBufSize = 3332 (pLcEntry[i].num_entries *pLcEntry[i].entry_size) + 8; 3333 3334 pLdBuf = (menlo_rsp_t *)kmem_zalloc(LdBufSize, KM_SLEEP); 3335 3336 RmStatus = emlxs_menlo_get_log(hba, i, pLdBuf, LdBufSize); 3337 3338 if (RmStatus != 0) { 3339 goto done; 3340 } 3341 3342 /* print a caption for the current log */ 3343 buf1[0] = 0; 3344 (void) snprintf(buf2, sizeof (buf2), "\n\nLog %d:", i); 3345 (void) strlcat(buf1, buf2, sizeof (buf1)); 3346 (void) snprintf(buf2, sizeof (buf2), " %s", pLcEntry[i].name); 3347 (void) strlcat(buf1, buf2, sizeof (buf1)); 3348 (void) snprintf(buf2, sizeof (buf2), "\n"); 3349 3350 for (j = 0; j < 75; j++) { 3351 (void) strlcat(buf2, "-", sizeof (buf2)); 3352 } 3353 3354 (void) strlcat(buf1, buf2, sizeof (buf1)); 3355 RmStatus = 3356 emlxs_dump_string_txtfile(fpCeeFile, buf1, 0, 0, 1); 3357 3358 /* check the head entry to determine whether */ 3359 /* the log has wrapped or not */ 3360 Head = pLdBuf->log.head; 3361 pLogEntry = (uint8_t *)&pLdBuf->log.data; 3362 pLogString = 3363 (char *)&(pLogEntry[Head *pLcEntry[i].entry_size]); 3364 3365 isWrapped = FALSE; 3366 if (strlen(pLogString) != 0) { 3367 isWrapped = TRUE; 3368 } 3369 3370 /* if log is wrapped, get entries from the */ 3371 /* Head through the End */ 3372 if (isWrapped) { 3373 for (j = Head; j < (int)pLcEntry[i].num_entries; j++) { 3374 pLogString = 3375 (char *)&(pLogEntry[j * 3376 pLcEntry[i].entry_size]); 3377 buf1[0] = 0; 3378 (void) snprintf(buf2, sizeof (buf2), 3379 "\n%3d: %s", j, pLogString); 3380 (void) strlcat(buf1, buf2, sizeof (buf1)); 3381 RmStatus = 3382 emlxs_dump_string_txtfile(fpCeeFile, buf1, 3383 0, 0, 1); 3384 } 3385 } 3386 3387 /* if wrapped or not, get entries from the Top */ 3388 /* through the Head */ 3389 for (j = 0; j < Head; j++) { 3390 pLogString = 3391 (char *)&(pLogEntry[j * pLcEntry[i].entry_size]); 3392 buf1[0] = 0; 3393 (void) snprintf(buf2, sizeof (buf2), "\n%3d: %s", j, 3394 pLogString); 3395 (void) strlcat(buf1, buf2, sizeof (buf1)); 3396 RmStatus = 3397 emlxs_dump_string_txtfile(fpCeeFile, buf1, 0, 0, 3398 1); 3399 } 3400 } /* end for i */ 3401 3402 /* Now issue a GetPanicLog command, which gives us the Panic Log */ 3403 3404 /* print a caption for the current log */ 3405 (void) strlcpy(buf1, LEGEND_MENLO_LOG_PANIC_REGS, sizeof (buf1)); 3406 buf2[0] = 0; 3407 for (j = 0; j < 75; j++) { 3408 (void) strlcat(buf2, "-", sizeof (buf2)); 3409 } 3410 (void) strlcat(buf1, buf2, sizeof (buf1)); 3411 RmStatus = emlxs_dump_string_txtfile(fpCeeFile, buf1, 0, 0, 1); 3412 3413 pPlBuf = (menlo_rsp_t *)kmem_zalloc(PlBufSize, KM_SLEEP); 3414 3415 RmStatus = emlxs_menlo_get_paniclog(hba, pPlBuf, PlBufSize); 3416 3417 if (RmStatus == 0) { 3418 buf1[0] = 0; 3419 (void) snprintf(buf2, sizeof (buf2), "\nType = %x", 3420 pPlBuf->panic_log.type); 3421 (void) strlcat(buf1, buf2, sizeof (buf1)); 3422 (void) snprintf(buf2, sizeof (buf2), "\nRegsEpc = %08x", 3423 pPlBuf->panic_log.regs_epc); 3424 (void) strlcat(buf1, buf2, sizeof (buf1)); 3425 (void) snprintf(buf2, sizeof (buf2), "\nRegsCp0Cause = %08x", 3426 pPlBuf->panic_log.regs_cp0_cause); 3427 (void) strlcat(buf1, buf2, sizeof (buf1)); 3428 (void) snprintf(buf2, sizeof (buf2), "\nRegsCp0Stat = %08x", 3429 pPlBuf->panic_log.regs_cp0_status); 3430 (void) strlcat(buf1, buf2, sizeof (buf1)); 3431 RmStatus = 3432 emlxs_dump_string_txtfile(fpCeeFile, buf1, 0, 0, 1); 3433 3434 buf1[0] = 0; 3435 for (i = 0; i < MENLO_NUM_GP_REGS; i++) { 3436 (void) snprintf(buf2, sizeof (buf2), 3437 "\nRegsGp[%02x] = %08x", i, 3438 pPlBuf->panic_log.regs_gp[i]); 3439 (void) strlcat(buf1, buf2, sizeof (buf1)); 3440 } 3441 RmStatus = 3442 emlxs_dump_string_txtfile(fpCeeFile, buf1, 0, 0, 1); 3443 3444 buf1[0] = 0; 3445 (void) snprintf(buf2, sizeof (buf2), "\nLogPresent = %08x", 3446 pPlBuf->panic_log.log_present); 3447 (void) strlcat(buf1, buf2, sizeof (buf1)); 3448 PanicLogEntryCount = pPlBuf->panic_log.num_entries; 3449 (void) snprintf(buf2, sizeof (buf2), "\nNumEntries = %08x", 3450 PanicLogEntryCount); 3451 (void) strlcat(buf1, buf2, sizeof (buf1)); 3452 PanicLogEntrySize = pPlBuf->panic_log.entry_size; 3453 (void) snprintf(buf2, sizeof (buf2), "\nEntrySize = %d.", 3454 PanicLogEntrySize); 3455 (void) strlcat(buf1, buf2, sizeof (buf1)); 3456 (void) snprintf(buf2, sizeof (buf2), "\nHead Entry = %d.", 3457 pPlBuf->panic_log.head); 3458 (void) strlcat(buf1, buf2, sizeof (buf1)); 3459 RmStatus = 3460 emlxs_dump_string_txtfile(fpCeeFile, buf1, 0, 0, 1); 3461 3462 /* print a caption for the current log */ 3463 (void) strlcpy(buf1, LEGEND_MENLO_LOG_PANIC_LOGS, 3464 sizeof (buf1)); 3465 buf2[0] = 0; 3466 for (j = 0; j < 75; j++) { 3467 (void) strlcat(buf2, "-", sizeof (buf2)); 3468 } 3469 (void) strlcat(buf1, buf2, sizeof (buf2)); 3470 RmStatus = 3471 emlxs_dump_string_txtfile(fpCeeFile, buf1, 0, 0, 1); 3472 3473 /* check the head entry to determine whether the */ 3474 /* log has wrapped or not */ 3475 Head = pPlBuf->panic_log.head; 3476 pLogEntry = (uint8_t *)&pPlBuf->panic_log.data; 3477 pLogString = (char *)&(pLogEntry[Head * PanicLogEntrySize]); 3478 isWrapped = FALSE; 3479 if (strlen(pLogString) != 0) { 3480 isWrapped = TRUE; 3481 } 3482 3483 /* if log is wrapped, get entries from the */ 3484 /* Head through the End */ 3485 if (isWrapped) { 3486 for (j = Head; j < (int)PanicLogEntryCount; j++) { 3487 pLogString = 3488 (char *)&(pLogEntry[j * 3489 PanicLogEntrySize]); 3490 buf1[0] = 0; 3491 (void) snprintf(buf2, sizeof (buf2), 3492 "\n%3d: %s", j, pLogString); 3493 (void) strlcat(buf1, buf2, sizeof (buf2)); 3494 RmStatus = 3495 emlxs_dump_string_txtfile(fpCeeFile, buf1, 3496 0, 0, 1); 3497 } 3498 } 3499 /* if wrapped or not, get entries from the Top */ 3500 /* through the Head */ 3501 for (j = 0; j < Head; j++) { 3502 pLogString = 3503 (char *)&(pLogEntry[j * PanicLogEntrySize]); 3504 buf1[0] = 0; 3505 (void) snprintf(buf2, sizeof (buf2), "\n%3d: %s", j, 3506 pLogString); 3507 (void) strlcat(buf1, buf2, sizeof (buf2)); 3508 RmStatus = 3509 emlxs_dump_string_txtfile(fpCeeFile, buf1, 0, 0, 3510 1); 3511 } 3512 } 3513 3514 RmStatus = emlxs_dump_string_txtfile(fpCeeFile, "\n\n", 0, 0, 1); 3515 3516 done: 3517 3518 if (pLdBuf != 0) { 3519 kmem_free(pLdBuf, LdBufSize); 3520 } 3521 3522 if (pLcBuf != 0) { 3523 kmem_free(pLcBuf, LcBufSize); 3524 } 3525 3526 if (pPlBuf != 0) { 3527 kmem_free(pPlBuf, PlBufSize); 3528 } 3529 3530 return (RmStatus); 3531 3532 } /* emlxs_dump_menlo_log() */ 3533 3534 3535 static uint32_t 3536 emlxs_dump_saturn_log( 3537 emlxs_hba_t *hba, 3538 emlxs_file_t *fpTxtFile, 3539 emlxs_file_t *fpDmpFile) 3540 { 3541 emlxs_port_t *port = &PPORT; 3542 MAILBOXQ *mbq; 3543 MAILBOX *mb; 3544 MATCHMAP *mp = NULL; 3545 uint32_t status; 3546 uint32_t logSize = 0; 3547 uintptr_t tempAddress; 3548 int fSwap = FALSE; 3549 uint32_t i; 3550 uint32_t block_size; 3551 uint32_t offset; 3552 3553 #ifdef EMLXS_BIG_ENDIAN 3554 fSwap = TRUE; 3555 #endif /* EMLXS_BIG_ENDIAN */ 3556 3557 if (hba->model_info.chip != EMLXS_SATURN_CHIP) { 3558 return (1); 3559 } 3560 3561 mbq = 3562 (MAILBOXQ *)kmem_zalloc(sizeof (MAILBOXQ), KM_SLEEP); 3563 3564 mb = (MAILBOX *) mbq; 3565 3566 /* Step 1: Call MBX_READ_EVENT_LOG_STATUS to get the log size. */ 3567 for (i = 0; i < 10; i++) { 3568 bzero((void *)mb, MAILBOX_CMD_BSIZE); 3569 mb->mbxCommand = MBX_READ_EVENT_LOG_STATUS; 3570 mbq->mbox_cmpl = NULL; 3571 3572 if (EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbq, MBX_WAIT, 0) == 3573 MBX_SUCCESS) { 3574 break; 3575 } 3576 3577 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg, 3578 "Unable to read event log status. status=%x", 3579 mb->mbxStatus); 3580 3581 if ((mb->mbxStatus & 0xFFFF) == MBXERR_NOT_SUPPORTED || 3582 (mb->mbxStatus & 0xFFFF) == MBX_DRVR_ERROR) { 3583 (void) emlxs_dump_string_txtfile(fpTxtFile, 3584 NV_LOG_NOT_INCLUDED_IN_DMP, 3585 LEGEND_NON_VOLATILE_LOG, 3586 LEGEND_NV_LOG_DRIVER_NOT_SUPPORTED, 0); 3587 3588 kmem_free(mbq, sizeof (MAILBOXQ)); 3589 return (1); 3590 } 3591 3592 /* The call to get the log size simply fails. */ 3593 /* Retry up to 10 times. */ 3594 if ((mb->mbxStatus & 0xFFFF) != MBX_BUSY) { 3595 /* Mailbox fails for some unknown reason. */ 3596 /* Put something in the txt to indicate this case. */ 3597 (void) emlxs_dump_string_txtfile(fpTxtFile, 3598 NV_LOG_NOT_INCLUDED_IN_DMP, 3599 LEGEND_NON_VOLATILE_LOG, 3600 LEGEND_NV_LOG_STATUS_ERROR, 0); 3601 3602 kmem_free(mbq, sizeof (MAILBOXQ)); 3603 return (1); 3604 } 3605 } 3606 3607 if (i >= 10) { 3608 (void) emlxs_dump_string_txtfile(fpTxtFile, 3609 NV_LOG_NOT_INCLUDED_IN_DMP, LEGEND_NON_VOLATILE_LOG, 3610 LEGEND_NV_LOG_STATUS_ERROR, 0); 3611 3612 kmem_free(mbq, sizeof (MAILBOXQ)); 3613 return (1); 3614 } 3615 3616 /* Step 2: Use the log size from step 1 to call MBX_READ_EVENT_LOG */ 3617 logSize = mb->un.varLogStat.size; 3618 3619 if ((mp = emlxs_mem_buf_alloc(hba, logSize)) == 0) { 3620 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg, 3621 "Unable to allocate receive buffer. " 3622 "size=%d", 3623 logSize); 3624 3625 kmem_free(mbq, sizeof (MAILBOXQ)); 3626 return (1); 3627 } 3628 3629 for (offset = 0; offset < logSize; offset = offset + 1024) { 3630 if (logSize - offset < 1024) { 3631 block_size = logSize - offset; 3632 } else { 3633 block_size = 1024; 3634 } 3635 3636 tempAddress = (uintptr_t)(mp->phys + offset); 3637 3638 bzero((void *)mb, MAILBOX_CMD_BSIZE); 3639 mb->mbxCommand = MBX_READ_EVENT_LOG; /* 0x38 */ 3640 mb->un.varRdEvtLog.read_log = 1; /* read log */ 3641 mb->un.varRdEvtLog.mbox_rsp = 0; /* not using Mailbox */ 3642 mb->un.varRdEvtLog.offset = offset; 3643 mb->un.varRdEvtLog.un.sp64.tus.f.bdeFlags = 0x0; 3644 mb->un.varRdEvtLog.un.sp64.tus.f.bdeSize = block_size; 3645 mb->un.varRdEvtLog.un.sp64.addrLow = PADDR_LO(tempAddress); 3646 mb->un.varRdEvtLog.un.sp64.addrHigh = PADDR_HI(tempAddress); 3647 mbq->mbox_cmpl = NULL; 3648 3649 if (EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbq, MBX_WAIT, 0) != 3650 MBX_SUCCESS) { 3651 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg, 3652 "Unable to read event log. status=%x", 3653 mb->mbxStatus); 3654 3655 emlxs_mem_buf_free(hba, mp); 3656 kmem_free(mbq, sizeof (MAILBOXQ)); 3657 return (1); 3658 } 3659 } 3660 3661 /* Step 3: Dump the log to the DMP file as raw data. */ 3662 3663 /* Write a string to text file to direct the user to the DMP */ 3664 /* file for the actual log. */ 3665 status = 3666 emlxs_dump_string_txtfile(fpTxtFile, NV_LOG_INCLUDED_IN_DMP, 3667 LEGEND_NON_VOLATILE_LOG, LEGEND_NULL, 0); 3668 3669 /* Write the real log to the DMP file. */ 3670 EMLXS_MPDATA_SYNC(mp->dma_handle, 0, logSize, DDI_DMA_SYNC_FORKERNEL); 3671 3672 status = 3673 emlxs_dump_host_block(fpDmpFile, mp->virt, logSize, 3674 SID_NON_VOLATILE_LOG, LEGEND_NON_VOLATILE_LOG, LEGEND_NULL, 3675 fSwap); 3676 3677 #ifdef FMA_SUPPORT 3678 if (emlxs_fm_check_dma_handle(hba, mp->dma_handle) 3679 != DDI_FM_OK) { 3680 EMLXS_MSGF(EMLXS_CONTEXT, 3681 &emlxs_invalid_dma_handle_msg, 3682 "dump_saturn_log: hdl=%p", 3683 mp->dma_handle); 3684 status = 1; 3685 } 3686 #endif /* FMA_SUPPORT */ 3687 3688 emlxs_mem_buf_free(hba, mp); 3689 kmem_free(mbq, sizeof (MAILBOXQ)); 3690 return (status); 3691 3692 } /* emlxs_dump_saturn_log() */ 3693 3694 3695 static uint32_t 3696 emlxs_dump_tigershark_log( 3697 emlxs_hba_t *hba, 3698 emlxs_file_t *fpTxtFile, 3699 emlxs_file_t *fpCeeFile) 3700 { 3701 emlxs_port_t *port = &PPORT; 3702 uint32_t rval = 0; 3703 uint32_t offset; 3704 uint32_t log_size; 3705 uint32_t xfer_size; 3706 uint32_t buffer_size; 3707 uint8_t *buffer = NULL; 3708 uint8_t *bptr; 3709 uint8_t *payload; 3710 MAILBOXQ *mbq = NULL; 3711 MAILBOX4 *mb = NULL; 3712 MATCHMAP *mp = NULL; 3713 IOCTL_COMMON_MANAGE_FAT *fat; 3714 mbox_req_hdr_t *hdr_req; 3715 3716 if ((hba->model_info.chip != EMLXS_BE2_CHIP) && 3717 (hba->model_info.chip != EMLXS_BE3_CHIP)) { 3718 return (1); 3719 } 3720 3721 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fw_dump_msg, 3722 "Querying FAT..."); 3723 3724 mbq = (MAILBOXQ *)kmem_zalloc(sizeof (MAILBOXQ), 3725 KM_SLEEP); 3726 3727 mb = (MAILBOX4*)mbq; 3728 3729 if ((mp = emlxs_mem_buf_alloc(hba, (sizeof (mbox_req_hdr_t) + 3730 sizeof (IOCTL_COMMON_MANAGE_FAT) + BE_MAX_XFER_SIZE))) == NULL) { 3731 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fw_dump_msg, 3732 "Unable to allocate FAT buffer."); 3733 3734 rval = 1; 3735 goto done; 3736 } 3737 3738 /* Query FAT */ 3739 mb->un.varSLIConfig.be.embedded = 0; 3740 mbq->nonembed = (void *)mp; 3741 mbq->mbox_cmpl = NULL; 3742 3743 mb->mbxCommand = MBX_SLI_CONFIG; 3744 mb->mbxOwner = OWN_HOST; 3745 3746 hdr_req = (mbox_req_hdr_t *)mp->virt; 3747 hdr_req->subsystem = IOCTL_SUBSYSTEM_COMMON; 3748 hdr_req->opcode = COMMON_OPCODE_MANAGE_FAT; 3749 hdr_req->timeout = 0; 3750 hdr_req->req_length = sizeof (IOCTL_COMMON_MANAGE_FAT); 3751 3752 fat = (IOCTL_COMMON_MANAGE_FAT *)(hdr_req + 1); 3753 fat->params.request.fat_operation = QUERY_FAT; 3754 fat->params.request.read_log_offset = 0; 3755 fat->params.request.read_log_length = 0; 3756 fat->params.request.data_buffer_size = BE_MAX_XFER_SIZE; 3757 3758 if (EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbq, MBX_WAIT, 0) != 3759 MBX_SUCCESS) { 3760 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fw_dump_msg, 3761 "FAT Query failed. status=%x", 3762 mb->mbxStatus); 3763 3764 rval = 1; 3765 goto done; 3766 } 3767 3768 log_size = fat->params.response.log_size; 3769 buffer_size = fat->params.response.log_size; 3770 3771 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fw_dump_msg, 3772 "FAT: log_size=%d", log_size); 3773 3774 if (buffer_size == 0) { 3775 goto done; 3776 } 3777 3778 if ((buffer = (uint8_t *)kmem_alloc( 3779 buffer_size, KM_NOSLEEP)) == NULL) { 3780 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fw_dump_msg, 3781 "Unable to allocate log buffer."); 3782 3783 rval = 1; 3784 goto done; 3785 } 3786 bzero(buffer, buffer_size); 3787 3788 /* Upload Log */ 3789 bptr = buffer; 3790 offset = 0; 3791 3792 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fw_dump_msg, 3793 "Uploading log... (%d bytes)", log_size); 3794 3795 while (log_size) { 3796 bzero((void *) mb, MAILBOX_CMD_SLI4_BSIZE); 3797 bzero((void *) mp->virt, mp->size); 3798 3799 xfer_size = min(BE_MAX_XFER_SIZE, log_size); 3800 3801 mb->un.varSLIConfig.be.embedded = 0; 3802 mbq->nonembed = (void *)mp; 3803 mbq->mbox_cmpl = NULL; 3804 3805 mb->mbxCommand = MBX_SLI_CONFIG; 3806 mb->mbxOwner = OWN_HOST; 3807 3808 hdr_req = (mbox_req_hdr_t *)mp->virt; 3809 hdr_req->subsystem = IOCTL_SUBSYSTEM_COMMON; 3810 hdr_req->opcode = COMMON_OPCODE_MANAGE_FAT; 3811 hdr_req->timeout = 0; 3812 hdr_req->req_length = 3813 sizeof (IOCTL_COMMON_MANAGE_FAT) + xfer_size; 3814 3815 fat = (IOCTL_COMMON_MANAGE_FAT *)(hdr_req + 1); 3816 fat->params.request.fat_operation = RETRIEVE_FAT; 3817 fat->params.request.read_log_offset = offset; 3818 fat->params.request.read_log_length = xfer_size; 3819 fat->params.request.data_buffer_size = BE_MAX_XFER_SIZE; 3820 3821 if (EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbq, MBX_WAIT, 0) != 3822 MBX_SUCCESS) { 3823 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fw_dump_msg, 3824 "Failed to upload log. status=%x", 3825 mb->mbxStatus); 3826 3827 (void) emlxs_dump_string_txtfile(fpTxtFile, 3828 NV_LOG_NOT_INCLUDED_IN_FAT, 3829 LEGEND_NON_VOLATILE_LOG, 3830 LEGEND_NV_LOG_STATUS_ERROR, 0); 3831 3832 rval = 1; 3833 goto done; 3834 } 3835 3836 payload = (uint8_t *)(&fat->params.response.data_buffer); 3837 3838 BE_SWAP32_BCOPY(payload, bptr, xfer_size); 3839 3840 log_size -= xfer_size; 3841 offset += xfer_size; 3842 bptr += xfer_size; 3843 } 3844 3845 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fw_dump_msg, 3846 "Log upload complete."); 3847 3848 /* Write a string to text file to direct the user to the CEE */ 3849 /* file for the actual log. */ 3850 rval = 3851 emlxs_dump_string_txtfile(fpTxtFile, NV_LOG_INCLUDED_IN_FAT, 3852 LEGEND_NON_VOLATILE_LOG, LEGEND_NULL, 0); 3853 3854 3855 /* Write the log to the CEE file. */ 3856 /* First word is the log size */ 3857 bptr = buffer + sizeof (uint32_t); 3858 log_size = buffer_size - sizeof (uint32_t); 3859 rval = emlxs_dump_word_dmpfile(fpCeeFile, (uint8_t *)bptr, 3860 log_size, 0); 3861 3862 done: 3863 3864 if (mbq) { 3865 emlxs_mem_put(hba, MEM_MBOX, (void *)mbq); 3866 } 3867 3868 if (mp) { 3869 emlxs_mem_buf_free(hba, mp); 3870 } 3871 3872 if (buffer) { 3873 kmem_free(buffer, buffer_size); 3874 } 3875 3876 if (rval == 0) { 3877 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fw_dump_msg, 3878 "Dump complete."); 3879 } 3880 3881 return (rval); 3882 3883 } /* emlxs_dump_tigershark_log() */ 3884 3885 3886 extern uint32_t 3887 emlxs_dump_user_event( 3888 emlxs_hba_t *hba) 3889 { 3890 emlxs_port_t *port = &PPORT; 3891 uint32_t status; 3892 emlxs_file_t *fpTxtFile; 3893 emlxs_file_t *fpDmpFile; 3894 emlxs_file_t *fpCeeFile; 3895 3896 mutex_enter(&EMLXS_DUMP_LOCK); 3897 3898 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fw_dump_msg, 3899 "User Event: Firmware core dump initiated..."); 3900 3901 status = 3902 emlxs_dump_file_create(hba, &fpTxtFile, &fpDmpFile, &fpCeeFile); 3903 if (status != 0) { 3904 mutex_exit(&EMLXS_DUMP_LOCK); 3905 return (1); 3906 } 3907 3908 (void) emlxs_dump_rev_info(hba, fpTxtFile, fpDmpFile); 3909 (void) emlxs_dump_hba_info(hba, fpTxtFile, fpDmpFile, DUMP_TYPE_USER); 3910 (void) emlxs_dump_parm_table(hba, fpTxtFile, fpDmpFile); 3911 (void) emlxs_dump_cfg_regions(hba, fpTxtFile, fpDmpFile); 3912 3913 if (hba->model_info.chip == EMLXS_SATURN_CHIP) { 3914 (void) emlxs_set_hba_mode(hba, DDI_ONDI); 3915 (void) emlxs_dump_saturn_log(hba, fpTxtFile, fpDmpFile); 3916 } 3917 3918 if ((hba->model_info.chip == EMLXS_BE2_CHIP) || 3919 (hba->model_info.chip == EMLXS_BE3_CHIP)) { 3920 (void) emlxs_dump_tigershark_log(hba, fpTxtFile, fpCeeFile); 3921 } 3922 3923 if (hba->sli_mode <= EMLXS_HBA_SLI3_MODE) { 3924 (void) emlxs_set_hba_mode(hba, DDI_DIAGDI); 3925 } 3926 3927 (void) emlxs_dump_sli_interface(hba, fpTxtFile, fpDmpFile, 3928 DUMP_TYPE_USER); 3929 3930 if (hba->sli_mode <= EMLXS_HBA_SLI3_MODE) { 3931 (void) emlxs_set_hba_mode(hba, DDI_WARMDI); 3932 } 3933 3934 (void) emlxs_dump_hba(hba, fpTxtFile, fpDmpFile); 3935 3936 (void) emlxs_set_hba_mode(hba, DDI_ONDI); 3937 3938 status = emlxs_menlo_set_mode(hba, MENLO_MAINTENANCE_MODE_ENABLE); 3939 if (status == 0) { 3940 (void) emlxs_dump_menlo_log(hba, fpCeeFile); 3941 (void) emlxs_menlo_set_mode(hba, 3942 MENLO_MAINTENANCE_MODE_DISABLE); 3943 } 3944 3945 (void) emlxs_dump_file_terminate(hba, fpTxtFile, fpDmpFile, fpCeeFile); 3946 (void) emlxs_dump_file_close(fpTxtFile, fpDmpFile, fpCeeFile); 3947 3948 mutex_exit(&EMLXS_DUMP_LOCK); 3949 return (0); 3950 3951 } /* emlxs_dump_user_event() */ 3952 3953 3954 extern uint32_t 3955 emlxs_dump_temp_event( 3956 emlxs_hba_t *hba, 3957 uint32_t tempType, 3958 uint32_t temp) 3959 { 3960 emlxs_port_t *port = &PPORT; 3961 uint32_t status; 3962 emlxs_file_t *fpTxtFile; 3963 3964 /* misc vars */ 3965 char sBuf1[512]; /* general purpose string buffer */ 3966 char sBuf2[256]; /* general purpose string buffer */ 3967 char sBuf3[256]; /* general purpose string buffer */ 3968 3969 if (hba->sli_mode == EMLXS_HBA_SLI4_MODE) { 3970 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fw_dump_msg, 3971 "Temperature Event: type=%d temp=%d. "\ 3972 "Invalid SLI4 event.", 3973 tempType, temp); 3974 3975 return (1); 3976 } 3977 3978 mutex_enter(&EMLXS_DUMP_LOCK); 3979 3980 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fw_dump_msg, 3981 "Temperature Event: type=%d temp=%d. "\ 3982 "Firmware core dump initiated...", 3983 tempType, temp); 3984 3985 status = emlxs_dump_file_create(hba, &fpTxtFile, 0, 0); 3986 if (status != 0) { 3987 mutex_exit(&EMLXS_DUMP_LOCK); 3988 return (1); 3989 } 3990 3991 /* Now generate the Dump */ 3992 /* Note: ignore return (status); if one part fails, */ 3993 /* keep trying to dump more stuff. */ 3994 3995 /* Write a warning at the top of the file */ 3996 (void) strlcpy(sBuf1, "WARNING: HBA Temperature Event:\n", 3997 sizeof (sBuf1)); 3998 switch (tempType) { 3999 case TEMP_TYPE_CRITICAL: 4000 (void) snprintf(sBuf2, sizeof (sBuf2), 4001 " Event Type = %d (Critical)\n", tempType); 4002 break; 4003 case TEMP_TYPE_THRESHOLD: 4004 (void) snprintf(sBuf2, sizeof (sBuf2), 4005 " Event Type = %d (Threshold)\n", tempType); 4006 break; 4007 case TEMP_TYPE_NORMAL: 4008 (void) snprintf(sBuf2, sizeof (sBuf2), 4009 " Event Type = %d (Normal)\n", tempType); 4010 break; 4011 default: 4012 (void) snprintf(sBuf2, sizeof (sBuf2), 4013 " Unknown Event Type = %d\n", tempType); 4014 break; 4015 } 4016 (void) snprintf(sBuf3, sizeof (sBuf3), " Temperature = %d\n\n", temp); 4017 (void) strlcat(sBuf1, sBuf2, sizeof (sBuf1)); 4018 (void) strlcat(sBuf1, sBuf3, sizeof (sBuf1)); 4019 4020 (void) emlxs_dump_string_txtfile(fpTxtFile, sBuf1, 0, 0, 0); 4021 4022 (void) emlxs_dump_rev_info(hba, fpTxtFile, NULL); 4023 (void) emlxs_dump_hba_info(hba, fpTxtFile, NULL, DUMP_TYPE_TEMP); 4024 4025 (void) emlxs_dump_file_terminate(hba, fpTxtFile, NULL, NULL); 4026 (void) emlxs_dump_file_close(fpTxtFile, NULL, NULL); 4027 4028 mutex_exit(&EMLXS_DUMP_LOCK); 4029 return (0); 4030 4031 } /* emlxs_dump_temp_event() */ 4032 4033 4034 extern uint32_t 4035 emlxs_dump_drv_event( 4036 emlxs_hba_t *hba) 4037 { 4038 emlxs_port_t *port = &PPORT; 4039 uint32_t status; 4040 emlxs_file_t *fpTxtFile; 4041 emlxs_file_t *fpDmpFile; 4042 emlxs_file_t *fpCeeFile; 4043 4044 mutex_enter(&EMLXS_DUMP_LOCK); 4045 4046 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fw_dump_msg, 4047 "Dump Event: Firmware core dump initiated..."); 4048 4049 status = 4050 emlxs_dump_file_create(hba, &fpTxtFile, &fpDmpFile, &fpCeeFile); 4051 if (status != 0) { 4052 mutex_exit(&EMLXS_DUMP_LOCK); 4053 return (1); 4054 } 4055 4056 if (hba->model_info.chip == EMLXS_SATURN_CHIP) { 4057 (void) emlxs_set_hba_mode(hba, DDI_ONDI); 4058 (void) emlxs_dump_saturn_log(hba, fpTxtFile, fpDmpFile); 4059 } 4060 4061 if ((hba->model_info.chip == EMLXS_BE2_CHIP) || 4062 (hba->model_info.chip == EMLXS_BE3_CHIP)) { 4063 (void) emlxs_dump_tigershark_log(hba, fpTxtFile, fpCeeFile); 4064 } 4065 4066 if (hba->sli_mode <= EMLXS_HBA_SLI3_MODE) { 4067 (void) emlxs_set_hba_mode(hba, DDI_DIAGDI); 4068 } 4069 4070 (void) emlxs_dump_sli_interface(hba, fpTxtFile, fpDmpFile, 4071 DUMP_TYPE_DRIVER); 4072 4073 if (hba->sli_mode <= EMLXS_HBA_SLI3_MODE) { 4074 (void) emlxs_set_hba_mode(hba, DDI_WARMDI); 4075 } 4076 4077 (void) emlxs_dump_hba(hba, fpTxtFile, fpDmpFile); 4078 4079 if (hba->sli_mode <= EMLXS_HBA_SLI3_MODE) { 4080 (void) emlxs_set_hba_mode(hba, DDI_ONDI); 4081 } 4082 4083 status = emlxs_menlo_set_mode(hba, MENLO_MAINTENANCE_MODE_ENABLE); 4084 if (status == 0) { 4085 (void) emlxs_dump_menlo_log(hba, fpCeeFile); 4086 } 4087 4088 /* Now generate the rest of the Dump */ 4089 (void) emlxs_dump_rev_info(hba, fpTxtFile, fpDmpFile); 4090 (void) emlxs_dump_hba_info(hba, fpTxtFile, fpDmpFile, DUMP_TYPE_DRIVER); 4091 (void) emlxs_dump_parm_table(hba, fpTxtFile, fpDmpFile); 4092 (void) emlxs_dump_cfg_regions(hba, fpTxtFile, fpDmpFile); 4093 4094 (void) emlxs_dump_file_terminate(hba, fpTxtFile, fpDmpFile, fpCeeFile); 4095 (void) emlxs_dump_file_close(fpTxtFile, fpDmpFile, fpCeeFile); 4096 4097 /* The last step of the Menlo Dump. */ 4098 (void) emlxs_menlo_reset(hba, MENLO_FW_OPERATIONAL); 4099 4100 (void) emlxs_set_hba_mode(hba, DDI_WARMDI); 4101 4102 mutex_exit(&EMLXS_DUMP_LOCK); 4103 4104 4105 return (0); 4106 4107 } /* emlxs_dump_drv_event() */ 4108 4109 4110 /* ARGSUSED */ 4111 extern void 4112 emlxs_dump_drv_thread(emlxs_hba_t *hba, 4113 void *arg1, void *arg2) 4114 { 4115 (void) emlxs_dump_drv_event(hba); 4116 4117 /* Clear the Dump flag */ 4118 mutex_enter(&EMLXS_PORT_LOCK); 4119 hba->flag &= ~FC_DUMP_ACTIVE; 4120 mutex_exit(&EMLXS_PORT_LOCK); 4121 4122 return; 4123 4124 } /* emlxs_dump_drv_thread() */ 4125 4126 4127 /* ARGSUSED */ 4128 extern void 4129 emlxs_dump_user_thread(emlxs_hba_t *hba, 4130 void *arg1, void *arg2) 4131 { 4132 (void) emlxs_dump_user_event(hba); 4133 4134 /* Clear the Dump flag */ 4135 mutex_enter(&EMLXS_PORT_LOCK); 4136 hba->flag &= ~FC_DUMP_ACTIVE; 4137 mutex_exit(&EMLXS_PORT_LOCK); 4138 4139 return; 4140 4141 } /* emlxs_dump_user_thread() */ 4142 4143 4144 /* ARGSUSED */ 4145 extern void 4146 emlxs_dump_temp_thread(emlxs_hba_t *hba, 4147 void *arg1, void *arg2) 4148 { 4149 dump_temp_event_t *temp_event = (dump_temp_event_t *)arg1; 4150 4151 (void) emlxs_dump_temp_event(temp_event->hba, temp_event->type, 4152 temp_event->temp); 4153 4154 /* Free the temp event object */ 4155 kmem_free(temp_event, sizeof (dump_temp_event_t)); 4156 4157 /* Clear the Dump flag */ 4158 mutex_enter(&EMLXS_PORT_LOCK); 4159 hba->flag &= ~FC_DUMP_ACTIVE; 4160 mutex_exit(&EMLXS_PORT_LOCK); 4161 4162 return; 4163 4164 } /* emlxs_dump_temp_thread() */ 4165 4166 4167 /* Schedules a dump thread */ 4168 /* temp_type and temp are only valid for type=EMLXS_TEMP_DUMP */ 4169 extern void 4170 emlxs_dump(emlxs_hba_t *hba, uint32_t type, uint32_t temp_type, uint32_t temp) 4171 { 4172 emlxs_port_t *port = &PPORT; 4173 dump_temp_event_t *temp_event = NULL; 4174 4175 mutex_enter(&EMLXS_PORT_LOCK); 4176 4177 /* Check if it is safe to dump */ 4178 if (!(hba->flag & FC_DUMP_SAFE)) { 4179 mutex_exit(&EMLXS_PORT_LOCK); 4180 4181 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fw_dump_msg, 4182 "dump: Dump disabled."); 4183 4184 return; 4185 } 4186 4187 /* Check if a dump is already in progess */ 4188 if (hba->flag & FC_DUMP_ACTIVE) { 4189 mutex_exit(&EMLXS_PORT_LOCK); 4190 4191 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fw_dump_msg, 4192 "dump: Dump already in progress."); 4193 4194 return; 4195 } 4196 4197 /* Prepare to schedule dump */ 4198 switch (type) { 4199 case EMLXS_DRV_DUMP: 4200 case EMLXS_USER_DUMP: 4201 break; 4202 4203 case EMLXS_TEMP_DUMP: 4204 temp_event = (dump_temp_event_t *)kmem_alloc( 4205 sizeof (dump_temp_event_t), KM_NOSLEEP); 4206 4207 if (temp_event == NULL) { 4208 mutex_exit(&EMLXS_PORT_LOCK); 4209 4210 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fw_dump_msg, 4211 "dump: Unable to allocate temp object."); 4212 4213 return; 4214 } 4215 4216 temp_event->hba = hba; 4217 temp_event->type = temp_type; 4218 temp_event->temp = temp; 4219 break; 4220 4221 default: 4222 mutex_exit(&EMLXS_PORT_LOCK); 4223 4224 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fw_dump_msg, 4225 "dump: Error: Unknown dump type. (%x)", 4226 type); 4227 4228 return; 4229 } 4230 4231 /* Set the Dump-in-progess flag */ 4232 hba->flag |= FC_DUMP_ACTIVE; 4233 mutex_exit(&EMLXS_PORT_LOCK); 4234 4235 /* Create a separate thread to run the dump event */ 4236 switch (type) { 4237 case EMLXS_DRV_DUMP: 4238 emlxs_thread_spawn(hba, emlxs_dump_drv_thread, NULL, NULL); 4239 break; 4240 4241 case EMLXS_TEMP_DUMP: 4242 emlxs_thread_spawn(hba, emlxs_dump_temp_thread, 4243 (void *)temp_event, NULL); 4244 break; 4245 4246 case EMLXS_USER_DUMP: 4247 emlxs_thread_spawn(hba, emlxs_dump_user_thread, NULL, NULL); 4248 break; 4249 } 4250 4251 return; 4252 4253 } /* emlxs_dump() */ 4254 4255 extern void 4256 emlxs_dump_wait(emlxs_hba_t *hba) 4257 { 4258 /* Wait for the Dump flag to clear */ 4259 while ((hba->flag & FC_DUMP_ACTIVE)) { 4260 BUSYWAIT_MS(1000); 4261 } 4262 4263 } /* emlxs_dump_wait() */ 4264 4265 4266 #endif /* DUMP_SUPPORT */ 4267