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