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