Hello,

This commit implements a new iprdumpfmt command that extracts driver information
from ipr dump files. It strips out driver version and IOA location, prints the
driver trace in the correct order and displays information from the smart dump
tables. It should be working correctly on both LE and BE dump formats.

I would greatly appreciate any feedback on the code, especially on output
formatting.

Thanks.

Signed-off-by: Heitor Ricardo Alves de Siqueira <hal...@linux.vnet.ibm.com>
---
 Makefile.am  |   5 +-
 iprdumpfmt.c | 683 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 687 insertions(+), 1 deletion(-)
 create mode 100644 iprdumpfmt.c

diff --git a/Makefile.am b/Makefile.am
index 4636ecbaf8ce..96b0cd2a5c4c 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -10,7 +10,7 @@
 noinst_LTLIBRARIES = libipr.la
 libipr_la_SOURCES = iprlib.c iprlib.h
 
-sbin_PROGRAMS = iprconfig iprdump iprupdate iprinit iprdbg
+sbin_PROGRAMS = iprconfig iprdump iprupdate iprinit iprdbg iprdumpfmt
 dist_sbin_SCRIPTS = iprsos
 
 iprconfig_SOURCES = iprconfig.c iprconfig.h
@@ -28,6 +28,9 @@ iprinit_LDADD= libipr.la
 iprdbg_SOURCES = iprdbg.c
 iprdbg_LDADD= libipr.la
 
+iprdumpfmt_SOURCES = iprdumpfmt.c
+iprdumpfmt_LDADD = libipr.la
+
 if STATIC_BUILD
 sbin_PROGRAMS += iprconfig-static
 
diff --git a/iprdumpfmt.c b/iprdumpfmt.c
new file mode 100644
index 000000000000..e5dc10a292c5
--- /dev/null
+++ b/iprdumpfmt.c
@@ -0,0 +1,683 @@
+#include <endian.h>
+#include "iprlib.h"
+
+#define EYE_CATCHER_BE 0xC5D4E3F2
+#define EYE_CATCHER_LE 0xF2E3D4C5
+
+#define OS_LINUX 0x4C4E5558
+#define OS_I5OS  0x69354F53
+
+#define DRV_IPR2 0x49505232
+#define DRV_V5R4 0x56355234
+
+#define TYPE_ASCII 0x41534349
+#define TYPE_BIN   0x42494E41
+#define TYPE_MR32  0x4D523332
+#define TYPE_MR64  0x4D523634
+
+#define ID_IOA_DUMP     0x494F4131
+#define ID_IOA_LOC      0x4C4F4341
+#define ID_DRV_TRACE    0x54524143
+#define ID_DRV_VER      0x44525652
+#define ID_DRV_TYPE     0x54595045
+#define ID_DRV_CTRL_BLK 0x494F4342
+#define ID_DRV_PEND_OPS 0x414F5053
+
+#define IPR_DUMP_STATUS_SUCCESS      0
+#define IPR_DUMP_STATUS_QUAL_SUCCESS 2
+#define IPR_DUMP_STATUS_FAILED       0xFFFFFFFF
+
+#define IPR_FMT2_SDT_READY_TO_USE 0xC4D4E3F2
+#define IPR_FMT3_SDT_READY_TO_USE 0xC4D4E3F3
+
+static const struct {
+       const u8 op;
+       const char *name;
+} scsi_cmnds[] = {
+       { 0xc1, "IPR_CANCEL_REQUEST" },
+       { 0x01, "IPR_CANCEL_64BIT_IOARCB" },
+       { 0xc2, "IPR_QUERY_RSRC_STATE" },
+       { 0xc3, "IPR_RESET_DEVICE" },
+       { 0x80, "IPR_RESET_TYPE_SELECT" },
+       { 0x40, "IPR_LUN_RESET" },
+       { 0x20, "IPR_TARGET_RESET" },
+       { 0x10, "IPR_BUS_RESET" },
+       { 0x80, "IPR_ATA_PHY_RESET" },
+       { 0xc4, "IPR_ID_HOST_RR_Q" },
+       { 0xc5, "IPR_QUERY_IOA_CONFIG" },
+       { 0xce, "IPR_CANCEL_ALL_REQUESTS" },
+       { 0xcf, "IPR_HOST_CONTROLLED_ASYNC" },
+       { 0x01, "IPR_HCAM_CDB_OP_CODE_CONFIG_CHANGE" },
+       { 0x02, "IPR_HCAM_CDB_OP_CODE_LOG_DATA" },
+       { 0xfb, "IPR_SET_SUPPORTED_DEVICES" },
+       { 0x80, "IPR_SET_ALL_SUPPORTED_DEVICES" },
+       { 0xf7, "IPR_IOA_SHUTDOWN" },
+       { 0x05, "IPR_WR_BUF_DOWNLOAD_AND_SAVE" },
+
+       { 0x00, "TEST_UNIT_READY" },
+       { 0x01, "REZERO_UNIT" },
+       { 0x03, "REQUEST_SENSE" },
+       { 0x04, "FORMAT_UNIT" },
+       { 0x05, "READ_BLOCK_LIMITS" },
+       { 0x07, "REASSIGN_BLOCKS" },
+       { 0x07, "INITIALIZE_ELEMENT_STATUS" },
+       { 0x08, "READ_6" },
+       { 0x0a, "WRITE_6" },
+       { 0x0b, "SEEK_6" },
+       { 0x0f, "READ_REVERSE" },
+       { 0x10, "WRITE_FILEMARKS" },
+       { 0x11, "SPACE" },
+       { 0x12, "INQUIRY" },
+       { 0x14, "RECOVER_BUFFERED_DATA" },
+       { 0x15, "MODE_SELECT" },
+       { 0x16, "RESERVE" },
+       { 0x17, "RELEASE" },
+       { 0x18, "COPY" },
+       { 0x19, "ERASE" },
+       { 0x1a, "MODE_SENSE" },
+       { 0x1b, "START_STOP" },
+       { 0x1c, "RECEIVE_DIAGNOSTIC" },
+       { 0x1d, "SEND_DIAGNOSTIC" },
+       { 0x1e, "ALLOW_MEDIUM_REMOVAL" },
+       { 0x23, "READ_FORMAT_CAPACITIES" },
+       { 0x24, "SET_WINDOW" },
+       { 0x25, "READ_CAPACITY" },
+       { 0x28, "READ_10" },
+       { 0x2a, "WRITE_10" },
+       { 0x2b, "SEEK_10" },
+       { 0x2b, "POSITION_TO_ELEMENT" },
+       { 0x2e, "WRITE_VERIFY" },
+       { 0x2f, "VERIFY" },
+       { 0x30, "SEARCH_HIGH" },
+       { 0x31, "SEARCH_EQUAL" },
+       { 0x32, "SEARCH_LOW" },
+       { 0x33, "SET_LIMITS" },
+       { 0x34, "PRE_FETCH" },
+       { 0x34, "READ_POSITION" },
+       { 0x35, "SYNCHRONIZE_CACHE" },
+       { 0x36, "LOCK_UNLOCK_CACHE" },
+       { 0x37, "READ_DEFECT_DATA" },
+       { 0x38, "MEDIUM_SCAN" },
+       { 0x39, "COMPARE" },
+       { 0x3a, "COPY_VERIFY" },
+       { 0x3b, "WRITE_BUFFER" },
+       { 0x3c, "READ_BUFFER" },
+       { 0x3d, "UPDATE_BLOCK" },
+       { 0x3e, "READ_LONG" },
+       { 0x3f, "WRITE_LONG" },
+       { 0x40, "CHANGE_DEFINITION" },
+       { 0x41, "WRITE_SAME" },
+       { 0x42, "UNMAP" },
+       { 0x43, "READ_TOC" },
+       { 0x44, "READ_HEADER" },
+       { 0x4a, "GET_EVENT_STATUS_NOTIFICATION" },
+       { 0x4c, "LOG_SELECT" },
+       { 0x4d, "LOG_SENSE" },
+       { 0x53, "XDWRITEREAD_10" },
+       { 0x55, "MODE_SELECT_10" },
+       { 0x56, "RESERVE_10" },
+       { 0x57, "RELEASE_10" },
+       { 0x5a, "MODE_SENSE_10" },
+       { 0x5e, "PERSISTENT_RESERVE_IN" },
+       { 0x5f, "PERSISTENT_RESERVE_OUT" },
+       { 0x7f, "VARIABLE_LENGTH_CMD" },
+       { 0xa0, "REPORT_LUNS" },
+       { 0xa2, "SECURITY_PROTOCOL_IN" },
+       { 0xa3, "MAINTENANCE_IN" },
+       { 0xa4, "MAINTENANCE_OUT" },
+       { 0xa5, "MOVE_MEDIUM" },
+       { 0xa6, "EXCHANGE_MEDIUM" },
+       { 0xa8, "READ_12" },
+       { 0xa9, "SERVICE_ACTION_OUT_12" },
+       { 0xaa, "WRITE_12" },
+       { 0xab, "SERVICE_ACTION_IN_12" },
+       { 0xae, "WRITE_VERIFY_12" },
+       { 0xaf, "VERIFY_12" },
+       { 0xb0, "SEARCH_HIGH_12" },
+       { 0xb1, "SEARCH_EQUAL_12" },
+       { 0xb2, "SEARCH_LOW_12" },
+       { 0xb5, "SECURITY_PROTOCOL_OUT" },
+       { 0xb8, "READ_ELEMENT_STATUS" },
+       { 0xb6, "SEND_VOLUME_TAG" },
+       { 0xea, "WRITE_LONG_2" },
+       { 0x83, "EXTENDED_COPY" },
+       { 0x84, "RECEIVE_COPY_RESULTS" },
+       { 0x86, "ACCESS_CONTROL_IN" },
+       { 0x87, "ACCESS_CONTROL_OUT" },
+       { 0x88, "READ_16" },
+       { 0x89, "COMPARE_AND_WRITE" },
+       { 0x8a, "WRITE_16" },
+       { 0x8c, "READ_ATTRIBUTE" },
+       { 0x8d, "WRITE_ATTRIBUTE" },
+       { 0x8f, "VERIFY_16" },
+       { 0x91, "SYNCHRONIZE_CACHE_16" },
+       { 0x93, "WRITE_SAME_16" },
+       { 0x9d, "SERVICE_ACTION_BIDIRECTIONAL" },
+       { 0x9e, "SERVICE_ACTION_IN_16" },
+       { 0x9f, "SERVICE_ACTION_OUT_16" }
+};
+
+struct ipr_dump_header {
+       u32 eye_catcher;
+       u32 len;
+       u32 num_entries;
+       u32 first_entry_offset;
+       u32 status;
+       u32 os;
+       u32 driver_name;
+};
+
+struct ipr_dump_entry_header {
+       u32 eye_catcher;
+       u32 len; /* does not include entry header */
+       u32 num_elems;
+       u32 offset; /* offset to data from beginning of dump file */
+       u32 data_type;
+       u32 id;
+       u32 status;
+};
+
+struct ipr_trace_entry {
+       u32 time;
+
+       u8 op_code; /* SCSI opcode */
+       u8 ata_op_code;
+       u8 type;
+#define IPR_TRACE_START                        0x00
+#define IPR_TRACE_FINISH               0xff
+       u8 cmd_index;
+
+       u32 res_handle; /* stored as BE */
+       union {
+               u32 ioasc;
+               u32 add_data;
+               u32 res_addr;
+       } u;
+};
+
+struct ipr_sdt_header {
+       /* all values in ipr_sdt_header are stored as BE */
+       u32 state;
+       u32 num_entries;
+       u32 entries_used;
+       u32 dump_size;
+};
+
+struct ipr_sdt {
+       struct ipr_sdt_header hdr;
+       struct ipr_sdt_entry *entry;
+};
+
+struct dump_node {
+       u32 pos;
+       struct ipr_dump_entry_header hdr;
+       struct dump_node *next;
+};
+
+struct trace_node {
+       struct ipr_trace_entry t;
+       struct trace_node *next;
+};
+
+void *dump_map;
+FILE *out_fp;
+
+/**
+ * get_scsi_command_literal -
+ * @value:             SCSI opcode
+ *
+ * Returns:
+ *   SCSI command string
+ **/
+static const char* get_scsi_command_literal(u32 value)
+{
+       u32 i = 0;
+
+       for (i=0; i<ARRAY_SIZE(scsi_cmnds); ++i) {
+               if (value == scsi_cmnds[i].op)
+                       return scsi_cmnds[i].name;
+       }
+       return "UNKNOWN";
+}
+
+/**
+ * read_dump_header -
+ * @fd:                dump file descriptor
+ *
+ * Returns:
+ *   ipr dump header structure
+ **/
+static struct ipr_dump_header read_dump_header(int fd)
+{
+       struct ipr_dump_header hdr;
+
+       read(fd, &hdr, sizeof(hdr));
+       hdr.eye_catcher = htobe32(hdr.eye_catcher);
+
+       /* convert to correct endianness */
+       if (hdr.eye_catcher == EYE_CATCHER_BE) {
+               hdr.len = be32toh(hdr.len);
+               hdr.num_entries = be32toh(hdr.num_entries);
+               hdr.first_entry_offset = be32toh(hdr.first_entry_offset);
+               hdr.status = be32toh(hdr.status);
+               hdr.os = be32toh(hdr.os);
+               hdr.driver_name = be32toh(hdr.driver_name);
+       } else {
+               hdr.len = le32toh(hdr.len);
+               hdr.num_entries = le32toh(hdr.num_entries);
+               hdr.first_entry_offset = le32toh(hdr.first_entry_offset);
+               hdr.status = le32toh(hdr.status);
+               hdr.os = le32toh(hdr.os);
+               hdr.driver_name = le32toh(hdr.driver_name);
+       }
+
+       return hdr;
+}
+
+/**
+ * print_dump_header -
+ * @hdr:               ipr dump header
+ *
+ * Returns:
+ *   nothing
+ **/
+static void print_dump_header(struct ipr_dump_header hdr)
+{
+       fprintf(out_fp, "IPR Adapter Dump Report\n\n");
+       switch (hdr.eye_catcher) {
+       case EYE_CATCHER_BE:
+               fprintf(out_fp, "Big Endian format: ");
+               break;
+       case EYE_CATCHER_LE:
+               fprintf(out_fp, "Little Endian format: ");
+               break;
+       default:
+               fprintf(out_fp, "Unknown dump format: ");
+       }
+       fprintf(out_fp, "Eye Catcher is 0x%08X\n", hdr.eye_catcher);
+
+       fprintf(out_fp, "Total length: %d bytes\n", hdr.len);
+       fprintf(out_fp, "Number of dump entries: %d\n", hdr.num_entries);
+       fprintf(out_fp, "Offset to first entry: 0x%08X bytes\n",
+               hdr.first_entry_offset);
+       fprintf(out_fp, "Dump status: 0x%08X ", hdr.status);
+       switch (hdr.status) {
+       case IPR_DUMP_STATUS_SUCCESS:
+               fprintf(out_fp, "(SUCCESS)\n");
+               break;
+       case IPR_DUMP_STATUS_QUAL_SUCCESS:
+               fprintf(out_fp, "(QUAL_SUCCESS)\n");
+               break;
+       case IPR_DUMP_STATUS_FAILED:
+               fprintf(out_fp, "(FAILED)\n");
+               break;
+       default:
+               fprintf(out_fp, "(UNKNOWN)\n");
+       }
+
+       fprintf(out_fp, "Operating System: ");
+       switch (hdr.os) {
+       case OS_LINUX:
+               fprintf(out_fp, "Linux\n");
+               break;
+       case OS_I5OS:
+               fprintf(out_fp, "i5OS\n");
+               break;
+       default:
+               fprintf(out_fp, "unknown\n");
+       }
+
+       fprintf(out_fp, "Driver: ");
+       switch (hdr.driver_name) {
+       case DRV_IPR2:
+               fprintf(out_fp, "ipr2\n");
+               break;
+       case DRV_V5R4:
+               fprintf(out_fp, "V5R4\n");
+               break;
+       default:
+               fprintf(out_fp, "unknown\n");
+       }
+}
+
+/**
+ * read_entry_header -
+ * @hdr:               ipr dump entry header
+ * @offset:            offset to entry data
+ *
+ * Returns:
+ *   offset to next entry header
+ **/
+static u32 read_entry_header(struct ipr_dump_entry_header *hdr, u32 offset)
+{
+       memcpy(hdr, dump_map+offset, sizeof(*hdr));
+       hdr->eye_catcher = htobe32(hdr->eye_catcher);
+
+       /* convert to correct endianness */
+       if (hdr->eye_catcher == EYE_CATCHER_BE) {
+               hdr->len = be32toh(hdr->len);
+               hdr->num_elems = be32toh(hdr->num_elems);
+               hdr->offset = be32toh(hdr->offset);
+               hdr->data_type = be32toh(hdr->data_type);
+               hdr->id = be32toh(hdr->id);
+               hdr->status = be32toh(hdr->status);
+       } else if (hdr->eye_catcher == EYE_CATCHER_LE) {
+               hdr->len = le32toh(hdr->len);
+               hdr->num_elems = le32toh(hdr->num_elems);
+               hdr->offset = le32toh(hdr->offset);
+               hdr->data_type = le32toh(hdr->data_type);
+               hdr->id = le32toh(hdr->id);
+               hdr->status = le32toh(hdr->status);
+       }
+       hdr->offset += offset;
+
+       return (hdr->offset + hdr->len);
+}
+
+/**
+ * read_trace_data -
+ * @offset:            offset to entry data
+ * @eye_catcher:       ipr entry eye catcher
+ *
+ * Returns:
+ *   ipr trace entry structure
+ **/
+static struct ipr_trace_entry read_trace_data(u32 offset, u32 eye_catcher)
+{
+       struct ipr_trace_entry trace;
+       memcpy(&trace, dump_map+offset, sizeof(trace));
+
+        /* always stored as BE */
+       trace.res_handle = htobe32(trace.res_handle);
+
+       /* convert to correct endianness */
+       if (eye_catcher == EYE_CATCHER_BE) {
+               trace.time = be32toh(trace.time);
+               trace.u.add_data = be32toh(trace.u.add_data);
+       } else {
+               trace.time = le32toh(trace.time);
+               trace.u.add_data = le32toh(trace.u.add_data);
+       }
+       return trace;
+}
+
+/**
+ * print_trace_data -
+ * @trace:             ipr trace entry
+ *
+ * Returns:
+ *   Nothing
+ **/
+static void print_trace_data(struct ipr_trace_entry trace)
+{
+       fprintf(out_fp, "\t Timestamp: %d (%lld us)\n", trace.time,
+              (long long unsigned)trace.time*1000*1000/sysconf(_SC_CLK_TCK));
+       fprintf(out_fp, "\t SCSI Opcode: 0x%02X ", trace.op_code);
+       fprintf(out_fp, "\t (%s)\n", get_scsi_command_literal(trace.op_code));
+       fprintf(out_fp, "\t ATA Opcode: 0x%02X\n", trace.ata_op_code);
+       fprintf(out_fp, "\t Type: 0x%02X ", trace.type);
+       switch (trace.type) {
+       case IPR_TRACE_START:
+               fprintf(out_fp, "(IPR_TRACE_START)\n");
+               break;
+       case IPR_TRACE_FINISH:
+               fprintf(out_fp, "(IPR_TRACE_FINISH)\n");
+               break;
+       default:
+               fprintf(out_fp, "(UNKNOWN)\n");
+       }
+       fprintf(out_fp, "\t Command index: 0x02%X\n", trace.cmd_index);
+       fprintf(out_fp, "\t Res Handle: 0x%08X\n", trace.res_handle);
+       fprintf(out_fp, "\t Additional Data: 0x08%X\n", trace.u.add_data);
+}
+
+/**
+ * build_sdt -
+ * @hdr:               ipr dump entry header
+ *
+ * Returns:
+ *   ipr sdt structure
+ **/
+static struct ipr_sdt build_sdt(struct ipr_dump_entry_header hdr)
+{
+       u32 i, offset;
+       struct ipr_sdt sdt;
+       struct ipr_sdt_entry *entry;
+
+       memcpy(&sdt.hdr, dump_map+hdr.offset, sizeof(sdt.hdr));
+       offset = hdr.offset + sizeof(sdt.hdr);
+
+       /* values below are always stored as BE */
+       sdt.hdr.state = htobe32(sdt.hdr.state);
+       sdt.hdr.num_entries = htobe32(sdt.hdr.num_entries);
+       sdt.hdr.entries_used = htobe32(sdt.hdr.entries_used);
+       sdt.hdr.dump_size = htobe32(sdt.hdr.dump_size);
+
+       sdt.entry = malloc(sdt.hdr.entries_used * sizeof(*sdt.entry));
+       for (i=0; i<sdt.hdr.entries_used; ++i) {
+               entry = &sdt.entry[i];
+
+               memcpy(entry, dump_map+offset+i*sizeof(*entry), sizeof(*entry));
+               /* values below are always stored as BE */
+               entry->bar_str_offset = htobe32(entry->bar_str_offset);
+               entry->end_offset = htobe32(entry->end_offset);
+               entry->priority = htobe16(entry->priority);
+       }
+
+       return sdt;
+}
+
+/**
+ * build_trace_list -
+ * @hdr:               ipr dump entry header
+ *
+ * Returns:
+ *   circular list of ipr trace entries
+ **/
+static struct trace_node* build_trace_list(struct ipr_dump_entry_header hdr)
+{
+       u32 i, min_time, min_pos = 0;
+       struct trace_node *head = malloc(sizeof(*head));
+       struct trace_node *aux = head;
+
+       head->t = read_trace_data(hdr.offset, hdr.eye_catcher);
+       min_time = head->t.time;
+       for (i=1; i<hdr.len/sizeof(head->t); ++i) {
+               aux->next = malloc(sizeof(*aux->next));
+               aux = aux->next;
+               aux->t = read_trace_data(hdr.offset+i*sizeof(head->t),
+                                        hdr.eye_catcher);
+               if (min_time > aux->t.time) {
+                       min_time = aux->t.time;
+                       min_pos = i;
+               }
+       }
+       aux->next = head;
+       while (min_pos--)
+               head = head->next;
+       return head;
+}
+
+/**
+ * clean_trace_list -
+ * @head:              circular list of ipr trace entries
+ *
+ * Returns:
+ *   nothing
+ **/
+static void clean_trace_list(struct trace_node* head)
+{
+       struct trace_node* aux = head->next;
+       struct trace_node* del;
+       while (aux != head) {
+               del = aux;
+               aux = aux->next;
+               free(del);
+       }
+       free(head);
+}
+
+/**
+ * print_sdt -
+ * @sdt:               ipr sdt structure
+ *
+ * Returns:
+ *   nothing
+ **/
+static void print_sdt(struct ipr_sdt sdt)
+{
+       u32 i;
+       struct ipr_sdt_entry *entry;
+
+       fprintf(out_fp, "Smart Dump Table Data:\n");
+       fprintf(out_fp, "\t state: 0x%X ", sdt.hdr.state);
+       switch(sdt.hdr.state) {
+       case IPR_FMT2_SDT_READY_TO_USE:
+       case IPR_FMT3_SDT_READY_TO_USE:
+               fprintf(out_fp, "(READY_TO_USE)\n");
+               break;
+       default:
+               fprintf(out_fp, "(UNKNOWN)\n");
+       }
+       fprintf(out_fp, "\t entries found: %d\n\n", sdt.hdr.entries_used);
+
+       for (i=0; i<sdt.hdr.entries_used; ++i) {
+               entry = &sdt.entry[i];
+               fprintf(out_fp, "\t start offset: 0x%08X\n",
+                       entry->bar_str_offset);
+               fprintf(out_fp, "\t end offset: 0x%08X\n", entry->end_offset);
+               fprintf(out_fp, "\t entry byte: 0x%02X\n", entry->entry_byte);
+               fprintf(out_fp, "\t endian: 0x%X\n", entry->endian);
+               fprintf(out_fp, "\t valid entry: 0x%X\n", entry->valid_entry);
+               fprintf(out_fp, "\t resv: %d\n", entry->resv);
+               fprintf(out_fp, "\t priority: 0x%04X\n", entry->priority);
+               fprintf(out_fp, "\n");
+       }
+}
+
+/**
+ * build_trace_list -
+ * @hdr:               ipr dump entry header
+ *
+ * Returns:
+ *   nothing
+ **/
+static void dump_entry_data(struct ipr_dump_entry_header hdr)
+{
+       u32 i;
+       char *s;
+       struct trace_node *tn, *tn_aux;
+       struct ipr_sdt sdt;
+
+       switch (hdr.id) {
+       case ID_IOA_DUMP:
+               sdt = build_sdt(hdr);
+               print_sdt(sdt);
+               free(sdt.entry);
+               break;
+       case ID_IOA_LOC:
+               fprintf(out_fp, "IOA Location:\n");
+               s = dump_map+hdr.offset;
+               fprintf(out_fp, "\t %.*s\n", hdr.len, s);
+               break;
+       case ID_DRV_VER:
+               fprintf(out_fp, "Driver Version:\n");
+               s = dump_map+hdr.offset;
+               fprintf(out_fp, "\t %.*s\n", hdr.len, s);
+               break;
+       case ID_DRV_TRACE:
+               fprintf(out_fp, "Driver Trace Entries:\n");
+               tn = build_trace_list(hdr);
+               tn_aux = tn;
+               print_trace_data(tn->t);
+               tn = tn->next;
+               while (tn != tn_aux) {
+                       fprintf(out_fp, "\n");
+                       print_trace_data(tn->t);
+                       tn = tn->next;
+               }
+               clean_trace_list(tn);
+               break;
+       case ID_DRV_TYPE:
+               fprintf(out_fp, "Driver Type:\n");
+               memcpy(&i, dump_map+hdr.offset, sizeof(i));
+               if (hdr.eye_catcher == EYE_CATCHER_BE)
+                       i = be32toh(i);
+               else
+                       i = le32toh(i);
+               fprintf(out_fp, "\t CCIN: 0x%04X\n", i);
+               memcpy(&i, dump_map+hdr.offset+sizeof(i), sizeof(i));
+               if (hdr.eye_catcher == EYE_CATCHER_BE)
+                       i = be32toh(i);
+               else
+                       i = le32toh(i);
+               fprintf(out_fp, "\t Adapter firmware Version: ");
+               fprintf(out_fp, " %02X:%02X:%02X:%02X\n",
+                       i >> 24,                /* major release */
+                       (i & 0x00FF0000) >> 16, /* card type */
+                       (i & 0x0000FF00) >> 8,  /* minor release 0 */
+                       i & 0x000000FF);        /* minor release 1 */
+               break;
+       case ID_DRV_CTRL_BLK:
+       case ID_DRV_PEND_OPS:
+               /* not implemented yet */
+               fprintf(stderr, "Warning: found IPR Control Block or ");
+               fprintf(stderr, "IPR Pending Ops structure!\n");
+               fprintf(stderr, "These are not implemented yet. Skipping...\n");
+               break;
+       default:
+               fprintf(stderr,
+                       "Warning: did not recognize data identification ");
+               fprintf(stderr, "(id 0x%08X). Skipping...\n", hdr.id);
+       }
+       fprintf(out_fp, "\n");
+}
+
+int main(int argc, char *argv[])
+{
+       u32 i, offset;
+       int in_fd;
+       struct ipr_dump_header hdr;
+       struct ipr_dump_entry_header entry_hdr;
+
+       if (argc != 3) {
+               fprintf(stderr, "Usage: %s <dump_file> <report_file>\n",
+                       argv[0]);
+               return 1;
+       }
+
+       in_fd = open(argv[1], O_RDONLY);
+       out_fp = fopen(argv[2], "w");
+
+       if (in_fd < 0) {
+               fprintf(stderr, "Error: could not open dump file %s\n",
+                       argv[1]);
+               fprintf(stderr, "Aborting...\n");
+               return 1;
+       }
+       if (out_fp == NULL) {
+               fprintf(stderr, "Error: could not open report file %s\n",
+                       argv[2]);
+               fprintf(stderr, "Aborting...\n");
+               return 1;
+       }
+
+       hdr = read_dump_header(in_fd);
+       print_dump_header(hdr);
+       fprintf(out_fp, "\n");
+
+       dump_map = mmap(NULL, hdr.len, PROT_READ, MAP_SHARED, in_fd, 0);
+       if (dump_map == MAP_FAILED) {
+               fprintf(stderr, "Error: could not map dump file to memory\n");
+               fprintf(stderr, "Aborting...\n");
+               return 1;
+       }
+
+       offset = hdr.first_entry_offset;
+       for (i=0; i<hdr.num_entries; ++i) {
+               offset = read_entry_header(&entry_hdr, offset);
+               dump_entry_data(entry_hdr);
+       }
+
+       return 0;
+}
-- 
2.4.3


------------------------------------------------------------------------------
_______________________________________________
Iprdd-devel mailing list
Iprdd-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/iprdd-devel

Reply via email to