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 #define DUMP_SUPPORT 28 29 #include <emlxs_mdb.h> 30 #include <emlxs_msg.h> 31 #include <emlxs_dump.h> 32 #include <emlxs_device.h> 33 34 /* 35 * MDB module linkage information: 36 */ 37 38 static const mdb_dcmd_t dcmds[] = 39 { 40 { "emlxs_msgbuf", "<instance>", "dumps the emlxs driver internal " \ 41 "message buffer", emlxs_msgbuf, emlxs_msgbuf_help}, 42 { "emlxs_dump", "<type> <instance>", "dumps the emlxs driver " \ 43 "firmware core", emlxs_dump, emlxs_dump_help}, 44 { NULL } 45 }; 46 47 static const mdb_modinfo_t modinfo = 48 { 49 MDB_API_VERSION, 50 dcmds, 51 NULL 52 }; 53 54 const mdb_modinfo_t * 55 _mdb_init(void) 56 { 57 return (&modinfo); 58 } 59 60 61 /* 62 * emlxs_msgbuf library 63 */ 64 void 65 emlxs_msgbuf_help() 66 { 67 68 mdb_printf("Usage: ::%s_msgbuf <instance(hex)>\n\n", DRIVER_NAME); 69 mdb_printf(" <instance> This is the %s driver instance " \ 70 "number in hex.\n", DRIVER_NAME); 71 mdb_printf(" (e.g. 0, 1,..., e, f, etc.)\n"); 72 73 } /* emlxs_msgbuf_help() */ 74 75 76 /*ARGSUSED*/ 77 int emlxs_msgbuf(uintptr_t base_addr, uint_t flags, int argc, 78 const mdb_arg_t *argv) 79 { 80 uintptr_t addr; 81 emlxs_device_t device; 82 uint32_t brd_no; 83 emlxs_msg_log_t log; 84 uint32_t count; 85 uint32_t first; 86 uint32_t last; 87 uint32_t idx; 88 uint32_t i; 89 char *level; 90 emlxs_msg_t msg; 91 uint32_t secs; 92 uint32_t hsecs; 93 emlxs_msg_entry_t entry; 94 char buffer[256]; 95 char buffer2[256]; 96 int32_t instance[MAX_FC_BRDS]; 97 char driver[32]; 98 int32_t instance_count; 99 uint32_t ddiinst; 100 101 if (argc != 1) { 102 mdb_printf("Usage: ::%s_msgbuf <instance(hex)>\n", 103 DRIVER_NAME); 104 mdb_printf("mdb: try \"::help %s_msgbuf\" for more information", 105 DRIVER_NAME); 106 107 return (DCMD_ERR); 108 } 109 110 /* Get the device address */ 111 mdb_snprintf(buffer, sizeof (buffer), "%s_device", DRIVER_NAME); 112 if (mdb_readvar(&device, buffer) == -1) { 113 mdb_snprintf(buffer2, sizeof (buffer2), 114 "%s not found.\n", buffer); 115 mdb_warn(buffer2); 116 117 mdb_snprintf(buffer2, sizeof (buffer2), 118 "Is the %s driver loaded ?\n", DRIVER_NAME); 119 mdb_warn(buffer2); 120 return (DCMD_ERR); 121 } 122 123 /* Get the device instance table */ 124 mdb_snprintf(buffer, sizeof (buffer), "%s_instance", DRIVER_NAME); 125 if (mdb_readvar(&instance, buffer) == -1) { 126 mdb_snprintf(buffer2, sizeof (buffer2), "%s not found.\n", 127 buffer); 128 mdb_warn(buffer2); 129 130 mdb_snprintf(buffer2, sizeof (buffer2), 131 "Is the %s driver loaded ?\n", DRIVER_NAME); 132 mdb_warn(buffer2); 133 return (DCMD_ERR); 134 } 135 136 /* Get the device instance count */ 137 mdb_snprintf(buffer, sizeof (buffer), "%s_instance_count", DRIVER_NAME); 138 if (mdb_readvar(&instance_count, buffer) == -1) { 139 mdb_snprintf(buffer2, sizeof (buffer2), "%s not found.\n", 140 buffer); 141 mdb_warn(buffer2); 142 143 mdb_snprintf(buffer2, sizeof (buffer2), 144 "Is the %s driver loaded ?\n", DRIVER_NAME); 145 mdb_warn(buffer2); 146 return (DCMD_ERR); 147 } 148 149 ddiinst = (uint32_t)mdb_strtoull(argv[0].a_un.a_str); 150 151 for (brd_no = 0; brd_no < instance_count; brd_no++) { 152 if (instance[brd_no] == ddiinst) { 153 break; 154 } 155 } 156 157 if (brd_no == instance_count) { 158 mdb_warn("Device instance not found. ddinst=%d\n", ddiinst); 159 return (DCMD_ERR); 160 } 161 162 /* Check if buffer is null */ 163 addr = (uintptr_t)device.log[brd_no]; 164 if (addr == 0) { 165 mdb_warn("Device instance not found. ddinst=%d\n", ddiinst); 166 return (0); 167 } 168 169 if (mdb_vread(&log, sizeof (emlxs_msg_log_t), addr) != 170 sizeof (emlxs_msg_log_t)) { 171 mdb_warn("\nUnable to read %d bytes @ %llx.\n", 172 sizeof (emlxs_msg_log_t), addr); 173 return (0); 174 } 175 176 /* Check if buffer is empty */ 177 if (log.count == 0) { 178 mdb_warn("Log buffer empty.\n"); 179 return (0); 180 } 181 182 /* Get last entry id saved */ 183 last = log.count - 1; 184 185 /* Check if buffer has already been filled once */ 186 if (log.count >= log.size) { 187 first = log.count - log.size; 188 idx = log.next; 189 } else { 190 /* Buffer not yet filled */ 191 first = 0; 192 idx = 0; 193 } 194 195 /* Get the total number of messages available for return */ 196 count = last - first + 1; 197 198 mdb_printf("\n"); 199 200 /* Print the messages */ 201 for (i = 0; i < count; i++) { 202 if (mdb_vread(&entry, sizeof (emlxs_msg_entry_t), 203 (uintptr_t)&log.entry[idx]) != sizeof (emlxs_msg_entry_t)) { 204 mdb_warn("Cannot read log entry. index=%d count=%d\n", 205 idx, count); 206 return (DCMD_ERR); 207 } 208 209 if (mdb_vread(&msg, sizeof (emlxs_msg_t), 210 (uintptr_t)entry.msg) != sizeof (emlxs_msg_t)) { 211 mdb_warn("Cannot read msg. index=%d count=%d\n", 212 idx, count); 213 return (DCMD_ERR); 214 } 215 216 hsecs = (entry.time%100); 217 secs = entry.time/100; 218 219 switch (msg.level) { 220 case EMLXS_DEBUG: 221 level = " DEBUG"; 222 break; 223 224 case EMLXS_NOTICE: 225 level = " NOTICE"; 226 break; 227 228 case EMLXS_WARNING: 229 level = "WARNING"; 230 break; 231 232 case EMLXS_ERROR: 233 level = " ERROR"; 234 break; 235 236 case EMLXS_PANIC: 237 level = " PANIC"; 238 break; 239 240 case EMLXS_EVENT: 241 level = " EVENT"; 242 break; 243 244 default: 245 level = "UNKNOWN"; 246 break; 247 } 248 249 if (entry.vpi == 0) { 250 mdb_snprintf(driver, sizeof (driver), "%s%d", 251 DRIVER_NAME, entry.instance); 252 } else { 253 mdb_snprintf(driver, sizeof (driver), "%s%d.%d", 254 DRIVER_NAME, entry.instance, entry.vpi); 255 } 256 257 /* Generate the message string */ 258 if (msg.buffer[0] != 0) { 259 if (entry.buffer[0] != 0) { 260 mdb_snprintf(buffer, sizeof (buffer), 261 "%8d.%02d: " 262 "%6d:[%1X.%04X]%s:%7s:%4d: %s\n(%s)\n", 263 secs, hsecs, entry.id, entry.fileno, 264 entry.line, driver, level, msg.id, 265 msg.buffer, entry.buffer); 266 267 } else { 268 mdb_snprintf(buffer, sizeof (buffer), 269 "%8d.%02d: %6d:[%1X.%04X]%s:%7s:%4d: %s\n", 270 secs, hsecs, entry.id, entry.fileno, 271 entry.line, driver, level, msg.id, 272 msg.buffer); 273 } 274 } else { 275 if (entry.buffer[0] != 0) { 276 mdb_snprintf(buffer, sizeof (buffer), 277 "%8d.%02d: " 278 "%6d:[%1X.%04X]%s:%7s:%4d:\n(%s)\n", 279 secs, hsecs, entry.id, entry.fileno, 280 entry.line, driver, level, msg.id, 281 entry.buffer); 282 } else { 283 mdb_snprintf(buffer, sizeof (buffer), 284 "%8d.%02d: %6d:[%1X.%04X]%s:%7s:%4d:\n", 285 secs, hsecs, entry.id, entry.fileno, 286 entry.line, driver, level, msg.id); 287 } 288 } 289 290 mdb_printf("%s", buffer); 291 292 /* Increment index */ 293 if (++idx >= log.size) { 294 idx = 0; 295 } 296 } 297 298 mdb_printf("\n"); 299 300 return (0); 301 302 } /* emlxs_msgbuf() */ 303 304 305 void 306 emlxs_dump_help() 307 { 308 mdb_printf("Usage: ::%s_dump all <instance(hex)>\n", DRIVER_NAME); 309 mdb_printf(" ::%s_dump txt <instance(hex)>\n", DRIVER_NAME); 310 mdb_printf(" ::%s_dump dmp <instance(hex)>\n", DRIVER_NAME); 311 mdb_printf(" ::%s_dump cee <instance(hex)>\n", DRIVER_NAME); 312 mdb_printf("\n"); 313 mdb_printf(" txt Display firmware text summary " \ 314 "file.\n"); 315 mdb_printf(" dmp Display firmware dmp binary file.\n"); 316 mdb_printf(" cee Display firmware cee binary file. " \ 317 "(FCOE adapters only)\n"); 318 mdb_printf(" all Display all firmware core files.\n"); 319 mdb_printf(" <instance> This is the %s driver instance " \ 320 "number in hex.\n", DRIVER_NAME); 321 mdb_printf(" (e.g. 0, 1,..., e, f, etc.)\n"); 322 323 } /* emlxs_dump_help() */ 324 325 326 /*ARGSUSED*/ 327 int 328 emlxs_dump(uintptr_t base_addr, uint_t flags, int argc, 329 const mdb_arg_t *argv) 330 { 331 uintptr_t addr; 332 emlxs_device_t device; 333 uint32_t brd_no; 334 uint32_t i; 335 char buffer[256]; 336 char buffer2[256]; 337 int32_t instance[MAX_FC_BRDS]; 338 int32_t instance_count; 339 uint32_t ddiinst; 340 uint8_t *bptr; 341 char *cptr; 342 emlxs_file_t dump_txtfile; 343 emlxs_file_t dump_dmpfile; 344 emlxs_file_t dump_ceefile; 345 uint32_t size; 346 uint32_t file; 347 348 if (argc != 2) { 349 goto usage; 350 } 351 352 if ((strcmp(argv[0].a_un.a_str, "all") == 0) || 353 (strcmp(argv[0].a_un.a_str, "ALL") == 0) || 354 (strcmp(argv[0].a_un.a_str, "All") == 0)) { 355 file = 0; 356 } else if ((strcmp(argv[0].a_un.a_str, "txt") == 0) || 357 (strcmp(argv[0].a_un.a_str, "TXT") == 0) || 358 (strcmp(argv[0].a_un.a_str, "Txt") == 0)) { 359 file = 1; 360 } else if ((strcmp(argv[0].a_un.a_str, "dmp") == 0) || 361 (strcmp(argv[0].a_un.a_str, "DMP") == 0) || 362 (strcmp(argv[0].a_un.a_str, "Dmp") == 0)) { 363 file = 2; 364 } else if ((strcmp(argv[0].a_un.a_str, "cee") == 0) || 365 (strcmp(argv[0].a_un.a_str, "CEE") == 0) || 366 (strcmp(argv[0].a_un.a_str, "Cee") == 0)) { 367 file = 3; 368 } else { 369 goto usage; 370 } 371 372 /* Get the device address */ 373 mdb_snprintf(buffer, sizeof (buffer), "%s_device", DRIVER_NAME); 374 if (mdb_readvar(&device, buffer) == -1) { 375 mdb_snprintf(buffer2, sizeof (buffer2), 376 "%s not found.\n", buffer); 377 mdb_warn(buffer2); 378 379 mdb_snprintf(buffer2, sizeof (buffer2), 380 "Is the %s driver loaded ?\n", DRIVER_NAME); 381 mdb_warn(buffer2); 382 return (DCMD_ERR); 383 } 384 385 /* Get the device instance table */ 386 mdb_snprintf(buffer, sizeof (buffer), "%s_instance", DRIVER_NAME); 387 if (mdb_readvar(&instance, buffer) == -1) { 388 mdb_snprintf(buffer2, sizeof (buffer2), "%s not found.\n", 389 buffer); 390 mdb_warn(buffer2); 391 392 mdb_snprintf(buffer2, sizeof (buffer2), 393 "Is the %s driver loaded ?\n", DRIVER_NAME); 394 mdb_warn(buffer2); 395 return (DCMD_ERR); 396 } 397 398 /* Get the device instance count */ 399 mdb_snprintf(buffer, sizeof (buffer), "%s_instance_count", DRIVER_NAME); 400 if (mdb_readvar(&instance_count, buffer) == -1) { 401 mdb_snprintf(buffer2, sizeof (buffer2), "%s not found.\n", 402 buffer); 403 mdb_warn(buffer2); 404 405 mdb_snprintf(buffer2, sizeof (buffer2), 406 "Is the %s driver loaded ?\n", DRIVER_NAME); 407 mdb_warn(buffer2); 408 return (DCMD_ERR); 409 } 410 411 ddiinst = (uint32_t)mdb_strtoull(argv[1].a_un.a_str); 412 413 for (brd_no = 0; brd_no < instance_count; brd_no++) { 414 if (instance[brd_no] == ddiinst) { 415 break; 416 } 417 } 418 419 if (brd_no == instance_count) { 420 mdb_warn("Device instance not found. ddinst=%d\n", ddiinst); 421 return (DCMD_ERR); 422 } 423 424 if (file == 0 || file == 1) { 425 426 addr = (uintptr_t)device.dump_txtfile[brd_no]; 427 if (addr == 0) { 428 mdb_warn("TXT file: Device instance not found. " \ 429 "ddinst=%d\n", ddiinst); 430 goto dmp_file; 431 } 432 433 if (mdb_vread(&dump_txtfile, sizeof (dump_txtfile), addr) 434 != sizeof (dump_txtfile)) { 435 mdb_warn("TXT file: Unable to read %d bytes @ %llx.\n", 436 sizeof (dump_txtfile), addr); 437 goto dmp_file; 438 } 439 440 size = (uintptr_t)dump_txtfile.ptr - 441 (uintptr_t)dump_txtfile.buffer; 442 443 if (size == 0) { 444 mdb_printf("TXT file: Not available.\n"); 445 goto dmp_file; 446 } 447 bptr = (uint8_t *)mdb_zalloc(size, UM_SLEEP|UM_GC); 448 449 if (bptr == 0) { 450 mdb_warn("TXT file: Unable to allocate file buffer. " \ 451 "ddinst=%d size=%d\n", ddiinst, size); 452 goto dmp_file; 453 } 454 455 if (mdb_vread(bptr, size, (uintptr_t)dump_txtfile.buffer) 456 != size) { 457 mdb_warn("TXT file: Unable to read %d bytes @ %llx.\n", 458 size, dump_txtfile.buffer); 459 goto dmp_file; 460 } 461 462 mdb_printf("<TXT File Start>\n"); 463 mdb_printf("\n"); 464 mdb_printf("%s", bptr); 465 mdb_printf("\n"); 466 mdb_printf("<TXT File End>\n"); 467 } 468 469 dmp_file: 470 471 if (file == 0 || file == 2) { 472 addr = (uintptr_t)device.dump_dmpfile[brd_no]; 473 if (addr == 0) { 474 mdb_warn("DMP file: Device instance not found. " \ 475 "ddinst=%d\n", ddiinst); 476 goto cee_file; 477 } 478 479 if (mdb_vread(&dump_dmpfile, sizeof (dump_dmpfile), addr) 480 != sizeof (dump_dmpfile)) { 481 mdb_warn("DMP file: Unable to read %d bytes @ %llx.\n", 482 sizeof (dump_dmpfile), addr); 483 goto cee_file; 484 } 485 486 size = (uintptr_t)dump_dmpfile.ptr - 487 (uintptr_t)dump_dmpfile.buffer; 488 489 if (size == 0) { 490 mdb_printf("DMP file: Not available.\n"); 491 goto cee_file; 492 } 493 494 bptr = (uint8_t *)mdb_zalloc(size, UM_SLEEP|UM_GC); 495 496 if (bptr == 0) { 497 mdb_warn("DMP file: Unable to allocate file buffer. " \ 498 "ddinst=%d size=%d\n", ddiinst, size); 499 goto cee_file; 500 } 501 502 if (mdb_vread(bptr, size, (uintptr_t)dump_dmpfile.buffer) 503 != size) { 504 mdb_warn("DMP file: Unable to read %d bytes @ %llx.\n", 505 size, dump_dmpfile.buffer); 506 goto cee_file; 507 } 508 509 mdb_printf("<DMP File Start>\n"); 510 mdb_printf("\n"); 511 512 bzero(buffer2, sizeof (buffer2)); 513 cptr = buffer2; 514 for (i = 0; i < size; i++) { 515 if (i && !(i % 16)) { 516 mdb_printf(" %s\n", buffer2); 517 bzero(buffer2, sizeof (buffer2)); 518 cptr = buffer2; 519 } 520 521 if (!(i % 16)) { 522 mdb_printf("%08X: ", i); 523 } 524 525 if (!(i % 4)) { 526 mdb_printf(" "); 527 } 528 529 if ((*bptr >= 32) && (*bptr <= 126)) { 530 *cptr++ = *bptr; 531 } else { 532 *cptr++ = '.'; 533 } 534 535 mdb_printf("%02X ", *bptr++); 536 } 537 538 size = 16 - (i % 16); 539 for (i = 0; size < 16 && i < size; i++) { 540 if (!(i % 4)) { 541 mdb_printf(" "); 542 } 543 544 mdb_printf(" "); 545 } 546 mdb_printf(" %s\n", buffer2); 547 mdb_printf("\n"); 548 mdb_printf("<DMP File End>\n"); 549 } 550 551 cee_file: 552 553 if (file == 0 || file == 3) { 554 555 addr = (uintptr_t)device.dump_ceefile[brd_no]; 556 if (addr == 0) { 557 mdb_warn("CEE file: Device instance not found. " \ 558 "ddinst=%d\n", ddiinst); 559 goto done; 560 } 561 562 if (mdb_vread(&dump_ceefile, sizeof (dump_ceefile), addr) 563 != sizeof (dump_ceefile)) { 564 mdb_warn("CEE file: Unable to read %d bytes @ %llx.\n", 565 sizeof (dump_ceefile), addr); 566 goto done; 567 } 568 569 size = (uintptr_t)dump_ceefile.ptr - 570 (uintptr_t)dump_ceefile.buffer; 571 572 if (size == 0) { 573 mdb_printf("CEE file: Not available.\n"); 574 goto done; 575 } 576 577 bptr = (uint8_t *)mdb_zalloc(size, UM_SLEEP|UM_GC); 578 579 if (bptr == 0) { 580 mdb_warn("CEE file: Unable to allocate file buffer. " \ 581 "ddinst=%d size=%d\n", ddiinst, size); 582 goto done; 583 } 584 585 if (mdb_vread(bptr, size, (uintptr_t)dump_ceefile.buffer) 586 != size) { 587 mdb_warn("CEE file: Unable to read %d bytes @ %llx.\n", 588 size, dump_ceefile.buffer); 589 goto done; 590 } 591 592 mdb_printf("<CEE File Start>\n"); 593 mdb_printf("\n"); 594 595 bzero(buffer2, sizeof (buffer2)); 596 cptr = buffer2; 597 for (i = 0; i < size; i++) { 598 if (i && !(i % 16)) { 599 mdb_printf(" %s\n", buffer2); 600 bzero(buffer2, sizeof (buffer2)); 601 cptr = buffer2; 602 } 603 604 if (!(i % 16)) { 605 mdb_printf("%08X: ", i); 606 } 607 608 if (!(i % 4)) { 609 mdb_printf(" "); 610 } 611 612 if ((*bptr >= 32) && (*bptr <= 126)) { 613 *cptr++ = *bptr; 614 } else { 615 *cptr++ = '.'; 616 } 617 618 mdb_printf("%02X ", *bptr++); 619 } 620 621 size = 16 - (i % 16); 622 for (i = 0; size < 16 && i < size; i++) { 623 if (!(i % 4)) { 624 mdb_printf(" "); 625 } 626 627 mdb_printf(" "); 628 } 629 mdb_printf(" %s\n", buffer2); 630 mdb_printf("\n"); 631 mdb_printf("<CEE File End>\n"); 632 } 633 done: 634 635 mdb_printf("\n"); 636 return (0); 637 638 usage: 639 mdb_printf("Usage: ::%s_dump <file> <instance (hex)>\n", 640 DRIVER_NAME); 641 mdb_printf("mdb: try \"::help %s_dump\" for more information", 642 DRIVER_NAME); 643 644 return (DCMD_ERR); 645 646 } /* emlxs_dump() */ 647