Thanks for letting me know about the build system, Gabriel. I've followed your
suggestion of implementing a --enable-iprdumpfmt flag since it's much simpler
than the other solution.

If there are any other issues with the patch, please let me know!

-- >8 --

This commit implements a new iprdumpfmt command that takes an iprdump.XX file as
input and strips out driver information. This includes driver version and type,
driver trace in the correct order and SDT entries. It has a verbose option that
prints additional information for the driver trace, such as timestamps and SCSI
commands.

Signed-off-by: Heitor Ricardo Alves de Siqueira <hal...@linux.vnet.ibm.com>
---
 Makefile.am  |   7 +
 configure.ac |  16 ++
 iprdumpfmt.8 |  33 +++
 iprdumpfmt.c | 665 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 721 insertions(+)
 create mode 100644 iprdumpfmt.8
 create mode 100644 iprdumpfmt.c

diff --git a/Makefile.am b/Makefile.am
index 4636ecbaf8ce..d528c2628643 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -53,3 +53,10 @@ if SOSREPORT
 sosreportdir = @pythondir@/sos/plugins
 sosreport_PYTHON = iprutils.py
 endif
+
+if IPRDUMPFMT
+sbin_PROGRAMS += iprdumpfmt
+iprdumpfmt_SOURCES = iprdumpfmt.c
+iprdumpfmt_LDADD= libipr.la
+dist_man_MANS += iprdumpfmt.8
+endif
diff --git a/configure.ac b/configure.ac
index d19e5cc43e31..e4cf7a22859d 100644
--- a/configure.ac
+++ b/configure.ac
@@ -55,6 +55,22 @@ AC_ARG_ENABLE([sosreport],
  esac], [sosreport=false])
 AM_CONDITIONAL([SOSREPORT], [test "x${sosreport}" = xtrue])
 
+# --enable-iprdumpfmt.
+AC_ARG_ENABLE([iprdumpfmt],
+              [--enable-iprdumpfmt Install iprdumpfmt tool],
+[case "${enableval}" in
+  yes)
+     iprdumpfmt=true
+     ;;
+  no)
+     iprdumpfmt=false
+     ;;
+  *)
+    AC_MSG_ERROR([bad value ${enableval} for --enable-iprdumpfmt])
+    ;;
+ esac], [iprdumpfmt=false])
+AM_CONDITIONAL([IPRDUMPFMT], [test "x${iprdumpfmt}" = xtrue])
+
 # --with-systemd
 systemdunitdir='${exec_prefix}/lib/systemd/system/'
 AC_ARG_WITH([systemd],
diff --git a/iprdumpfmt.8 b/iprdumpfmt.8
new file mode 100644
index 000000000000..55e0f37b0797
--- /dev/null
+++ b/iprdumpfmt.8
@@ -0,0 +1,33 @@
+.\" (C) Copyright 2015
+.\" International Business Machines Corporation and others.
+.\" All Rights Reserved. This program and the accompanying
+.\" materials are made available under the terms of the
+.\" Common Public License v1.0 which accompanies this distribution.
+.TH IPRDUMPFMT 8 "November 2015"
+.SH NAME
+iprdumpfmt \- IBM Power RAID dump formatting utility
+.SH SYNOPSIS
+.BI "iprdumpfmt [options] dump_file"
+.sp
+.BI "iprdumpfmt -o <report_file> --verbose dump_file"
+.sp
+.SH DESCRIPTION
+.B iprdumpfmt
+is used to strip out driver information from iprdump.XX files. This includes
+driver type and version, smart dump table entries and driver trace ordered by
+jiffies. There is a verbose option that also prints timestamps and SCSI command
+for each driver trace entry. The information is stored in a file that can be
+optionally specified by the user. If no output file is specified, the
+information is printed to a new 'iprdump.XX.report' file.
+.br
+.SH OPTIONS
+.TP
+.B \-\-verbose
+Print detailed driver trace information.
+.TP
+.B \-\-output file
+Specify a different output file to store formatted information. If no file is
+chosen, a new one is created by appending '.report' to the input dump file.
+.br
+.SH AUTHOR
+Heitor R. A. de Siqueira <hal...@linux.vnet.ibm.com>
diff --git a/iprdumpfmt.c b/iprdumpfmt.c
new file mode 100644
index 000000000000..02e0d1763f91
--- /dev/null
+++ b/iprdumpfmt.c
@@ -0,0 +1,665 @@
+/**
+ * IBM IPR dump formatting utility
+ *
+ * (C) Copyright 2015
+ * International Business Machines Corporation and others.
+ * All Rights Reserved. This program and the accompanying
+ * materials are made available under the terms of the
+ * Common Public License v1.0 which accompanies this distribution.
+ **/
+
+#include <endian.h>
+#include <getopt.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;
+};
+
+static void *dump_map;    /* ipr dump memory map */
+static FILE *out_fp;      /* output report file pointer */
+static int verbose_trace; /* flag for verbose trace printing */
+
+#define TARGET_TO_HOST32(value, eye_catcher) \
+       (eye_catcher == EYE_CATCHER_BE ? \
+        be32toh(value) : \
+        le32toh(value))
+
+/**
+ * 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 NULL;
+}
+
+/**
+ * read_dump_header -
+ * @hdr:               ipr dump header pointer
+ *
+ * Returns:
+ *   nothing
+ **/
+static void read_dump_header(struct ipr_dump_header *hdr)
+{
+       struct ipr_dump_header *raw_hdr = dump_map;
+
+       hdr->eye_catcher = htobe32(raw_hdr->eye_catcher);
+
+       /* convert to correct endianness */
+       hdr->len = TARGET_TO_HOST32(raw_hdr->len, hdr->eye_catcher);
+       hdr->num_entries = TARGET_TO_HOST32(raw_hdr->num_entries,
+                                           hdr->eye_catcher);
+       hdr->first_entry_offset = TARGET_TO_HOST32(raw_hdr->first_entry_offset,
+                                                  hdr->eye_catcher);
+       hdr->status = TARGET_TO_HOST32(raw_hdr->status, hdr->eye_catcher);
+       hdr->os = TARGET_TO_HOST32(raw_hdr->os, hdr->eye_catcher);
+       hdr->driver_name = TARGET_TO_HOST32(raw_hdr->driver_name,
+                                           hdr->eye_catcher);
+}
+
+/**
+ * print_dump_header -
+ * @hdr:               ipr dump header pointer
+ *
+ * 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 pointer
+ * @offset:            offset to entry data
+ *
+ * Returns:
+ *   offset to next entry header
+ **/
+static u32 read_entry_header(struct ipr_dump_entry_header *hdr, u32 offset)
+{
+       struct ipr_dump_entry_header *raw_hdr = dump_map+offset;
+       hdr->eye_catcher = htobe32(raw_hdr->eye_catcher);
+
+       /* convert to correct endianness */
+       hdr->len = TARGET_TO_HOST32(raw_hdr->len, hdr->eye_catcher);
+       hdr->num_elems = TARGET_TO_HOST32(raw_hdr->num_elems, hdr->eye_catcher);
+       hdr->offset = TARGET_TO_HOST32(raw_hdr->offset, hdr->eye_catcher);
+       hdr->data_type = TARGET_TO_HOST32(raw_hdr->data_type, hdr->eye_catcher);
+       hdr->id = TARGET_TO_HOST32(raw_hdr->id, hdr->eye_catcher);
+       hdr->status = TARGET_TO_HOST32(raw_hdr->status, hdr->eye_catcher);
+       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;
+       struct ipr_trace_entry *raw_trace = dump_map+offset;
+
+        /* always stored as BE */
+       trace.res_handle = htobe32(raw_trace->res_handle);
+
+       /* convert to correct endianness */
+       trace.time = TARGET_TO_HOST32(raw_trace->time, eye_catcher);
+       trace.u.add_data = TARGET_TO_HOST32(raw_trace->u.add_data, eye_catcher);
+
+       /* copy remaining trace fields */
+       trace.op_code = raw_trace->op_code;
+       trace.ata_op_code = raw_trace->ata_op_code;
+       trace.type = raw_trace->type;
+       trace.cmd_index = raw_trace->cmd_index;
+
+       return trace;
+}
+
+#define JIFF_TO_USEC(x) x * 1000 * 1000 / sysconf(_SC_CLK_TCK)
+/**
+ * print_trace -
+ * @hdr:               ipr entry header pointer
+ *
+ * Returns:
+ *   nothing
+ **/
+static void print_trace(struct ipr_dump_entry_header *hdr)
+{
+       u32 i, min_pos, min_time, num_entries, offset;
+       struct ipr_trace_entry *raw_trace;
+       struct ipr_trace_entry t;
+       const char *cmnd;
+
+       num_entries = hdr->len / sizeof(*raw_trace);
+       raw_trace = dump_map + hdr->offset;
+       min_pos = 0;
+       min_time = TARGET_TO_HOST32(raw_trace->time, hdr->eye_catcher);
+
+       fprintf(out_fp, "\t entries found: %d\n\n", num_entries);
+       for (i = 1; i < num_entries; ++i) {
+               raw_trace = dump_map + hdr->offset + i*sizeof(*raw_trace);
+               if (TARGET_TO_HOST32(raw_trace->time, hdr->eye_catcher) <
+                   min_time) {
+                       min_time = TARGET_TO_HOST32(raw_trace->time,
+                                                   hdr->eye_catcher);
+                       min_pos = i;
+               }
+       }
+       for (i = 0; i < num_entries; ++i) {
+               offset = hdr->offset +
+                       ((min_pos+i)%num_entries) * sizeof(*raw_trace);
+               t = read_trace_data(offset, hdr->eye_catcher);
+               fprintf(out_fp, "\t %08X %02X%02X%02X%02X %08X %08X",
+                       t.time, t.op_code, t.ata_op_code, t.type, t.cmd_index,
+                       t.res_handle, t.u.add_data);
+               if (verbose_trace) {
+                       fprintf(out_fp, "\t | \t%lld\xC2\xB5s\t",
+                               (long long unsigned)JIFF_TO_USEC(t.time));
+                       switch(t.type) {
+                       case IPR_TRACE_START:
+                               fprintf(out_fp, "IPR_TRACE_START\t\t");
+                               break;
+                       case IPR_TRACE_FINISH:
+                               fprintf(out_fp, "IPR_TRACE_FINISH\t");
+                               break;
+                       default:
+                               fprintf(out_fp, "\t\t\t");
+                       }
+                       cmnd = get_scsi_command_literal(t.op_code);
+                       if (cmnd)
+                               fprintf(out_fp, "%s", cmnd);
+
+               }
+               fprintf(out_fp, "\n");
+       }
+}
+
+/**
+ * print_sdt -
+ * @data_offset:       offset to sdt data
+ *
+ * Returns:
+ *   nothing
+ **/
+static void print_sdt(u32 data_offset)
+{
+       u32 i;
+       struct ipr_sdt_header *raw_hdr;
+       struct ipr_sdt_entry *raw_entry;
+
+       raw_hdr = dump_map + data_offset;
+
+       fprintf(out_fp, "\t state: 0x%X", htobe32(raw_hdr->state));
+       if (htobe32(raw_hdr->state) == IPR_FMT2_SDT_READY_TO_USE ||
+           htobe32(raw_hdr->state) == IPR_FMT3_SDT_READY_TO_USE)
+               fprintf(out_fp, " (READY_TO_USE)\n");
+       else
+               fprintf(out_fp, "\n");
+       fprintf(out_fp, "\t entries found: %d\n\n",
+               htobe32(raw_hdr->entries_used));
+
+       for (i = 0; i < htobe32(raw_hdr->entries_used); ++i) {
+               raw_entry = dump_map + data_offset + sizeof(*raw_hdr)
+                       + i * sizeof(*raw_entry);
+               fprintf(out_fp, "\t %08X %08X %02X%02X%02X%02X %04X\n",
+                       htobe32(raw_entry->bar_str_offset),
+                       htobe32(raw_entry->end_offset),
+                       raw_entry->entry_byte, raw_entry->endian,
+                       raw_entry->valid_entry, raw_entry->resv,
+                       htobe16(raw_entry->priority));
+       }
+}
+
+/**
+ * dump_entry_data -
+ * @hdr:               ipr dump entry header pointer
+ *
+ * Returns:
+ *   nothing
+ **/
+static void dump_entry_data(struct ipr_dump_entry_header *hdr)
+{
+       u32 i;
+       char *s;
+
+       switch (hdr->id) {
+       case ID_IOA_DUMP:
+               fprintf(out_fp, "Smart Dump Table Data:\n");
+               print_sdt(hdr->offset);
+               break;
+       case ID_IOA_LOC:
+               fprintf(out_fp, "IOA Location:\n");
+               s = dump_map+hdr->offset;
+               fprintf(out_fp, "\t %.*s\n\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\n", hdr->len, s);
+               break;
+       case ID_DRV_TRACE:
+               fprintf(out_fp, "Driver Trace Entries:\n");
+               print_trace(hdr);
+               fprintf(out_fp, "\n");
+               break;
+       case ID_DRV_TYPE:
+               fprintf(out_fp, "Driver Type:\n");
+               i = TARGET_TO_HOST32(*(int*)(dump_map+hdr->offset),
+                                    hdr->eye_catcher);
+               fprintf(out_fp, "\t CCIN: 0x%04X\n", i);
+               i = TARGET_TO_HOST32(*(int*)(dump_map+hdr->offset+sizeof(i)),
+                                    hdr->eye_catcher);
+               fprintf(out_fp,"\t Adapter firmware Version: "
+                       " %02X:%02X:%02X:%02X\n\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 IPR Pending Ops!\n"
+                       "These are not implemented yet. Skipping...\n");
+               break;
+       default:
+               fprintf(stderr,
+                       "Warning: did not recognize data identification "
+                       "(id 0x%08X). Skipping...\n\n", hdr->id);
+       }
+}
+
+/**
+ * fsize -
+ * @filename:          ipr dump file name
+ *
+ * Returns:
+ *   ipr dump file size
+ **/
+off_t fsize(const char *filename)
+{
+       struct stat st;
+
+       if (stat(filename, &st) == 0)
+               return st.st_size;
+
+       return -1;
+}
+
+/**
+ * print_usage -
+ *
+ * Returns:
+ *   nothing
+ **/
+static void print_usage()
+{
+       fprintf(stdout,
+               "Usage: iprdumpfmt [options] dump_file\n"
+               "  Options:\n"
+               "\t-h --help\tPrint this message\n"
+               "\t-o --output\tSpecify an output file\n"
+               "\t-v --verbose\tPrint verbose trace data\n");
+}
+
+static struct option long_options[] = {
+       {"output", required_argument, 0, 'o'},
+       {"help", no_argument, 0, 'h'},
+       {"verbose", no_argument, &verbose_trace, 1},
+       {0, 0, 0, 0}
+};
+
+int main(int argc, char *argv[])
+{
+       u32 i, offset;
+       int in_fd, filesize;
+       struct ipr_dump_header hdr;
+       struct ipr_dump_entry_header entry_hdr;
+       int c, option_index = 0;
+       char out_filename[512] = {'\0'};
+
+       while ((c = getopt_long(argc, argv, "hvo:", long_options,
+                               &option_index)) != -1) {
+               switch (c) {
+               case 0:
+                       break;
+               case 'o':
+                       strncpy(out_filename, optarg, sizeof(out_filename) - 1);
+                       break;
+               case '?':
+               case 'h':
+                       print_usage();
+                       return 0;
+               case 'v':
+                       verbose_trace = 1;
+                       break;
+               default:
+                       return -1;
+               }
+       }
+
+       if (argc - optind < 1) {
+               /* needs at least a dump file */
+               print_usage();
+               return -1;
+       }
+
+       in_fd = open(argv[optind], O_RDONLY);
+       if (in_fd < 0) {
+               int rc = errno;
+               fprintf(stderr, "Could not open dump file %s: %s\n",
+                       argv[optind], strerror(errno));
+               return rc;
+       }
+
+       if (out_filename[0] == '\0')
+               snprintf(out_filename, sizeof(out_filename), "%s.report",
+                        argv[optind]);
+       out_fp = fopen(out_filename, "w");
+       if (out_fp == NULL) {
+               int rc = errno;
+               fprintf(stderr, "Could not open output file %s: %s\n",
+                       out_filename, strerror(errno));
+               return rc;
+       }
+
+       filesize = fsize(argv[optind]);
+       if (filesize < 0) {
+               int rc = errno;
+               fprintf(stderr, "Could not determine size of %s: %s\n",
+                       argv[optind], strerror(errno));
+               return rc;
+       }
+
+       dump_map = mmap(NULL, filesize, PROT_READ, MAP_PRIVATE, in_fd, 0);
+       if (dump_map == MAP_FAILED) {
+               int rc = errno;
+               fprintf(stderr, "Could not map dump file to memory: %s\n",
+                       strerror(errno));
+               return rc;
+       }
+
+       read_dump_header(&hdr);
+       print_dump_header(&hdr);
+       fprintf(out_fp, "\n");
+
+       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