aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDouglas Gilbert <dgilbert@interlog.com>2022-03-09 15:52:27 +0000
committerDouglas Gilbert <dgilbert@interlog.com>2022-03-09 15:52:27 +0000
commit6498c8fa92b6ecfce411679af47064a6fd80ff33 (patch)
tree3a9ff8d3f4117965d82fe9105949e23dae93a023
parentd4e94e36b445985f8618ed048c98787ad0edfdf1 (diff)
downloadsg3_utils-6498c8fa92b6ecfce411679af47064a6fd80ff33.tar.gz
sg_logs: add --exclude and --undefined options, improve 'last_n' log pages; add inhex/logs_last_n.hex
git-svn-id: https://svn.bingwo.ca/repos/sg3_utils/trunk@942 6180dd3e-e324-4e3e-922d-17de1ae2f315
-rw-r--r--ChangeLog10
-rw-r--r--debian/changelog2
-rw-r--r--doc/sg3_utils.82
-rw-r--r--doc/sg_logs.8121
-rw-r--r--doc/sg_reset.84
-rw-r--r--include/Makefile.am1
-rw-r--r--include/Makefile.in16
-rw-r--r--include/sg_lib_names.h31
-rw-r--r--inhex/README6
-rw-r--r--inhex/inq_standard.hex4
-rw-r--r--inhex/logs_last_n.hex41
-rw-r--r--lib/Makefile.am1
-rw-r--r--lib/Makefile.in41
-rw-r--r--lib/sg_lib.c34
-rw-r--r--lib/sg_lib_data.c4
-rw-r--r--lib/sg_lib_names.c132
-rw-r--r--sg3_utils.spec2
-rw-r--r--src/sg_logs.c1477
-rw-r--r--src/sg_modes.c13
-rw-r--r--src/sg_reset.c6
20 files changed, 1279 insertions, 669 deletions
diff --git a/ChangeLog b/ChangeLog
index 1c53fc03..39c5a9a6 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -2,7 +2,7 @@ Each utility has its own version number, date of last change and
some description at the top of its ".c" file. All utilities in the main
directory have their own "man" pages. There is also a sg3_utils man page.
-Changelog for pre-release sg3_utils-1.48 [20220228] [svn: r941]
+Changelog for pre-release sg3_utils-1.48 [20220309] [svn: r942]
- sg_z_act_query: new utility for sending either a
Zone activate or Zone query command
- sg_rep_density: new utility for decoding the response of
@@ -25,14 +25,22 @@ Changelog for pre-release sg3_utils-1.48 [20220228] [svn: r941]
- sg_logs: tweak the meaning of --list option to more closely
reflect the contents of log pages 0x0 and 0x0,0xff
- make '-lll' set union of log pages 0x0 and 0x0,0xff
+ - add --exclude option to exclude vendor specific pages
+ and parameters
+ - add --undefined option for hex format of undefined/
+ unrecognized fields
- for short binary fields, remove address (index) from
the left hand side of each line of hex
+ - improve 'last_n' log pages; supply VPD and mode pages
+ with their name (if T10 defined)
- sg_modes: improve handling of zbc disks with pdt=0x14
- sg_inq, sg_vpd: Device Identication VPD page, change
"IEEE Company_id" to "AOI" as per spc6r06.pdf
- sg_opcodes: cleanup error reporting
- sg_format: allow disk formats on ZBC (zoned) disks
- sg_read_buffer: add --eh_code= and --no_output options
+ - inhex/logs_last_n.hex: new, tests for the 4 "Last n ..."
+ log (sub)pages
- sg_lib: add sg_pdt_s_eq() to cope with ZBC disks which may
be either PDT_ZBC (if host managed) or PDT_DISK
- cleanup masks for PDT [0x1f] and group_number [0x3f]
diff --git a/debian/changelog b/debian/changelog
index ba34077d..d8949b25 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -2,7 +2,7 @@ sg3-utils (1.48-0.1) unstable; urgency=low
* New upstream version
- -- Douglas Gilbert <dgilbert@interlog.com> Tue, 22 Feb 2022 19:00:00 -0500
+ -- Douglas Gilbert <dgilbert@interlog.com> Sun, 06 Mar 2022 13:00:00 -0500
sg3-utils (1.47-0.1) unstable; urgency=low
diff --git a/doc/sg3_utils.8 b/doc/sg3_utils.8
index bf81e3ad..c1254219 100644
--- a/doc/sg3_utils.8
+++ b/doc/sg3_utils.8
@@ -1,4 +1,4 @@
-.TH SG3_UTILS "8" "February 2022" "sg3_utils\-1.48" SG3_UTILS
+.TH SG3_UTILS "8" "March 2022" "sg3_utils\-1.48" SG3_UTILS
.SH NAME
sg3_utils \- a package of utilities for sending SCSI commands
.SH SYNOPSIS
diff --git a/doc/sg_logs.8 b/doc/sg_logs.8
index a81b78e8..84ccccd1 100644
--- a/doc/sg_logs.8
+++ b/doc/sg_logs.8
@@ -1,35 +1,36 @@
-.TH SG_LOGS "8" "December 2021" "sg3_utils\-1.48" SG3_UTILS
+.TH SG_LOGS "8" "March 2022" "sg3_utils\-1.48" SG3_UTILS
.SH NAME
sg_logs \- access log pages with SCSI LOG SENSE command
.SH SYNOPSIS
.B sg_logs
-[\fI\-\-All\fR] [\fI\-\-all\fR] [\fI\-\-brief\fR] [\fI\-\-filter=FL\fR]
-[\fI\-\-hex\fR] [\fI\-\-list\fR] [\fI\-\-maxlen=LEN\fR] [\fI\-\-name\fR]
-[\fI\-\-no_inq\fR] [\fI\-\-page=PG\fR] [\fI\-\-paramp=PP\fR] [\fI\-\-pcb\fR]
-[\fI\-\-ppc\fR] [\fI\-\-pdt=DT\fR] [\fI\-\-raw\fR] [\fI\-\-readonly\fR]
-[\fI\-\-sp\fR] [\fI\-\-temperature\fR] [\fI\-\-transport\fR]
-[\fI\-\-vendor=VP\fR] [\fI\-\-verbose\fR] \fIDEVICE\fR
+[\fI\-\-ALL\fR] [\fI\-\-all\fR] [\fI\-\-brief\fR] [\fI\-\-exclude\fR]
+[\fI\-\-filter=FL\fR] [\fI\-\-hex\fR] [\fI\-\-list\fR] [\fI\-\-maxlen=LEN\fR]
+[\fI\-\-name\fR] [\fI\-\-no_inq\fR] [\fI\-\-page=PG\fR] [\fI\-\-paramp=PP\fR]
+[\fI\-\-pcb\fR] [\fI\-\-ppc\fR] [\fI\-\-pdt=DT\fR] [\fI\-\-raw\fR]
+[\fI\-\-readonly\fR] [\fI\-\-sp\fR] [\fI\-\-temperature\fR]
+[\fI\-\-transport\fR] [\fI\-\-undefined\fR] [\fI\-\-vendor=VP\fR]
+[\fI\-\-verbose\fR] \fIDEVICE\fR
.PP
.B sg_logs
-[\fI\-\-brief\fR] [\fI\-\-filter=FL\fR] [\fI\-\-hex\fR] \fI\-\-in=FN\fR
-[\fI\-\-name\fR] [\fI\-\-pdt=DT\fR] [\fI\-\-raw\fR] [\fI\-\-vendor=VP\fR]
+\fI\-\-in=FN\fR [\fI\-\-brief\fR] [\fI\-\-exclude\fR] [\fI\-\-filter=FL\fR]
+[\fI\-\-hex\fR] [\fI\-\-name\fR] [\fI\-\-pdt=DT\fR] [\fI\-\-raw\fR]
+[\fI\-\-undefined\fR] [\fI\-\-vendor=VP\fR]
.PP
.B sg_logs
-[\fI\-\-control=PC\fR] [\fI\-\-in=FN\fR] [\fI\-\-page=PG\fR] [\fI\-\-raw\fR]
-[\fI\-\-reset\fR] \fI\-\-select\fR [\fI\-\-sp\fR] [\fI\-\-verbose\fR]
-\fIDEVICE\fR
+\fI\-\-select\fR [\fI\-\-control=PC\fR] [\fI\-\-page=PG\fR] [\fI\-\-raw\fR]
+[\fI\-\-reset\fR] [\fI\-\-sp\fR] [\fI\-\-verbose\fR] \fIDEVICE\fR
.PP
.B sg_logs
-[\fI\-\-enumerate\fR] [\fI\-\-filter=FL\fR] [\fI\-\-help\fR]
+\fI\-\-enumerate\fR [\fI\-\-filter=FL\fR] [\fI\-\-help\fR]
[\fI\-\-vendor=VP\fR] [\fI\-\-version\fR]
.PP
.B sg_logs
-[\fI\-a\fR] [\fI\-A\fR] [\fI\-b\fR] [\fI\-D=DT\fR] [\fI\-c=PC\fR] [\fI\-e\fR]
-[\fI\-f=FL\fR] [\fI\-h\fR] [\fI\-H\fR] [\fI\-i=FN\fR] [\fI\-l\fR] [\fI\-L\fR]
-[\fI\-m=LEN\fR] [\fI\-M=VP\fR] [\fI\-n\fR] [\fI\-p=PG\fR] [\fI\-paramp=PP\fR]
-[\fI\-pcb\fR] [\fI\-ppc\fR] [\fI\-r\fR] [\fI\-R\fR] [\fI\-select\fR]
-[\fI\-sp\fR] [\fI\-t\fR] [\fI\-T\fR] [\fI\-v\fR] [\fI\-V\fR] [\fI\-?\fR]
-[\fI\-x\fR] \fIDEVICE\fR
+[\fI\-a\fR] [\fI\-A\fR] [\fI\-b\fR] [\fI\-c=PC\fR] [\fI\-D=DT\fR] [\fI\-e\fR]
+[\fI\-E\fR] [\fI\-f=FL\fR] [\fI\-h\fR] [\fI\-H\fR] [\fI\-i=FN\fR] [\fI\-l\fR]
+[\fI\-L\fR] [\fI\-m=LEN\fR] [\fI\-M=VP\fR] [\fI\-n\fR] [\fI\-p=PG\fR]
+[\fI\-paramp=PP\fR] [\fI\-pcb\fR] [\fI\-ppc\fR] [\fI\-r\fR] [\fI\-R\fR]
+[\fI\-select\fR] [\fI\-sp\fR] [\fI\-t\fR] [\fI\-T\fR] [\fI\-u\fR] [\fI\-v\fR]
+[\fI\-V\fR] [\fI\-?\fR] [\fI\-x\fR] \fIDEVICE\fR
.SH DESCRIPTION
.\" Add any additional description here
.PP
@@ -41,7 +42,7 @@ to the \fIDEVICE\fR. Alternatively one or more log page responses can be in
a file read using the \fI\-\-in=FN\fR option; in this case those responses
are decoded and the \fIDEVICE\fR argument, if given, is ignored.
.PP
-In SPC\-4 revision 5 a subpage code was introduced to both the LOG SENSE and
+In SPC\-4 revision 5 the subpage code was introduced to both the LOG SENSE and
LOG SELECT command. At the same time a page code field was introduced to the
to the LOG SELECT command. The log subpage code can range from 0 to 255 (0xff)
inclusive. The subpage code value 255 can be thought of as a wildcard.
@@ -59,23 +60,25 @@ When no options are given, just a \fIDEVICE\fR, that is equivalent to calling
this utility with the \fI\-\-list\fR option. In that case the names of the
supported log pages (but not subpages) are listed out.
.SH OPTIONS
-Arguments to long options are mandatory for short options as well.
-The options are arranged in alphabetical order based on the long
-option name.
+Arguments to long options are mandatory for short options as well. The options
+are arranged in alphabetical order based on the long option name.
.TP
-\fB\-A\fR, \fB\-\-All\fR
+\fB\-A\fR, \fB\-\-ALL\fR
fetch and decode all the log pages and subpages supported by the \fIDEVICE\fR.
This requires a two stage process: first the "supported log pages and
subpages" log page is fetched, then for each entry in its response, the
corresponding log page (or subpage) is fetched and displayed. Note that there
are many SCSI devices that do not support LOG SENSE subpages and respond
-to this option with an illegal request sense key (or ignored the subpage
-field).
+to this option with an illegal request sense key.
.br
Since some vendors don't list all log pages in the "supported log pages and
subpages" log page, the '\-lll' option can be given in addition. This will
merge both "supported ..." log pages then, from that resultant merged list,
fetch page contents.
+.br
+The long option may also appear as \fB\-\-All\fR.
+.br
+This option overrides the \fI\-\-page=PG\fR if the latter is also given.
.TP
\fB\-a\fR, \fB\-\-all\fR
outputs all the log pages supported by the \fIDEVICE\fR. This requires a two
@@ -83,6 +86,8 @@ stage process: first the "supported log pages" log page is fetched, then for
each entry in its response, the corresponding log page is fetched and
displayed. When used twice (e.g. '\-aa') all log pages and subpages are
fetched.
+.br
+This option overrides the \fI\-\-page=PG\fR if the latter is also given.
.TP
\fB\-b\fR, \fB\-\-brief\fR
shorten the amount of output for some log pages. For example the Tape
@@ -115,6 +120,15 @@ four times, vendor pages are excluded from the numeric order.
The \fI\-\-filter=FL\fR and \fI\-\-verbose\fR options reduce the output
of the enumeration.
.TP
+\fB\-E\fR, \fB\-\-exclude\fR
+this option excludes vendor specific pages and parameters from the output.
+Trying to decode vendor specific pages and parameters does not necessarily
+work well for many reasons. This option limits the output to pages and
+parameters defined by T10.
+.br
+Only parameter fields identified in the drafts as 'vendor specific' are
+excluded. So parameters codes identified as 'reserved' are shown.
+.TP
\fB\-f\fR, \fB\-\-filter\fR=\fIFL\fR
\fIFL\fR is either a parameter code when \fIDEVICE\fR is given, or a
peripheral device type (pdt) (or other) if \fI\-\-enumerate\fR is given.
@@ -148,6 +162,10 @@ to the right. When used three times, the hex has no leading address nor
trailing ASCII making it suitable to be placed in a file (or piped). That
file might later be used by another invocation using the \fI\-\-in=FN\fR
option.
+.br
+A weaker form of this option, called \fI\-\-undefined\fR, handles the
+formatting of hexadecimal output for fields that this utility is unable to
+decode.
.TP
\fB\-i\fR, \fB\-\-in\fR=\fIFN\fR
This option may be used in two different contexts. One is with the
@@ -180,7 +198,7 @@ using this option three times will yield a list from the "supported log
pages" log page. In the absence of other options, the page/subpage names,
but not their contents, are shown when this option is given.
.br
-The '\-lll' form may be useful with the \fI\-\-All\fR option to show the
+The '\-lll' form may be useful with the \fI\-\-ALL\fR option to show the
contents of all pages referred to in either the "supported log page" or
the "supported log page and subpage" log pages.
.TP
@@ -189,13 +207,12 @@ sets the "allocation length" field in the LOG SENSE cdb. The is the maximum
length in bytes that the response will be. Without this option (or \fILEN\fR
equal to 0) this utility first fetches the 4 byte response then does a second
access with the length indicated in the first (4 byte) response. Negative
-values and 1 for \fILEN\fR are not accepted. \fILEN\fR cannot exceed
-65535 (0xffff). Responses can be quite large (e.g. the background scan
-results log page) and this option can be used to limit the amount of
-information returned.
+values and 1 for \fILEN\fR are not accepted. Responses can be quite
+large (e.g. the background scan results log page) and this option can be used
+to limit the amount of information returned.
.br
-If \fILEN\fR is less than 2 of greater than 65,535 an error is generated.
-Otherwise if \fILEN\fR is less than 4 then 4 is used instead.
+The default \fILEN\fR is 65532 unless the \fI\-\-in=FN\fR option is given;
+in that case the default is 262144 .
.TP
\fB\-n\fR, \fB\-\-name\fR
decode some log pages into 'name=value' entries, one per line. The name
@@ -232,25 +249,31 @@ used to fetch the Supported subpages log page (e.g. \-\-page=temp,0xff).
.TP
\fB\-P\fR, \fB\-\-paramp\fR=\fIPP\fR
\fIPP\fR is the parameter pointer value to place in a field of that name in
-the LOG SENSE cdb. A decimal number in the range 0 to 65535 (0xffff) is
+the LOG SENSE cdb. A number in the range 0 to 65535 (0x0 to 0xffff) is
expected. When a value greater than 0 is given the \fI\-\-ppc\fR option
should be selected. The default value is 0.
+.br
+For log pages that have parameter codes, the \fIDEVICE\fR should return
+only parameters code equal to \fIPP\fR or higher in its response.
.TP
\fB\-q\fR, \fB\-\-pcb\fR
show Parameter Control Byte settings (only relevant when log parameters
being output in ASCII). This byte includes the DU and TSD bits plus
the 'Format and linking' field (2 bits wide).
.TP
+\fB\-D\fR, \fB\-\-pdt\fR=\fIDT\fR
+\fIDT\fR is the peripheral device type (PDT) that is used when it is not
+available from the \fIDEVICE\fR. There are two main cases of this: with
+the \fI\-\-pdt=DT\fR without a \fIDEVICE\fR (e.g. when \fI\-\-in=FN\fR
+is used) and when \fI\-\-no_inq\fR is used with a \fIDEVICE\fR.
+.br
+\fIDT\fR may be -1 which is the default value. This value may select any
+device type but favours the lower numbers (e.g. the PDT of disks is 0).
+.TP
\fB\-Q\fR, \fB\-\-ppc\fR
sets the Parameter Pointer Control (PPC) bit in the LOG SENSE cdb. Default
is 0 (i.e. cleared). This bit was made obsolete in SPC\-4 revision 18.
.TP
-\fB\-D\fR, \fB\-\-pdt\fR=\fIDT\fR
-\fIDT\fR is the peripheral device type that is used when it is not available
-from the \fIDEVICE\fR. There are two main cases of this: with the
-\fI\-\-pdt=DT\fR without a \fIDEVICE\fR and when \fI\-\-no_inq\fR is used
-with a \fIDEVICE\fR.
-.TP
\fB\-r\fR, \fB\-\-raw\fR
output the response in binary to stdout. Error messages and warnings are
output to stderr.
@@ -303,6 +326,14 @@ may also have the current temperature (especially on older disks).
outputs the transport ('Protocol specific port') log page. Equivalent to
setting '\-\-page=18h'.
.TP
+\fB\-u\fR, \fB\-\-undefined\fR
+to see fields decoded, the \fI\-\-hex\fR option cannot be used. However some
+fields are not defined in the T10 documents and in that case they are output
+in hex. This option controls the format of 'undefined' fields when they
+output in hex. Multiple uses of this option has the same sense as the
+\fI\-\-hex\fR option. For example '\-uu' will output undefined fields in
+hexadecimal with an ASCII rendering to the right of each line.
+.TP
\fB\-M\fR, \fB\-\-vendor\fR=\fIVP\fR
where \fIVP\fR is a vendor/manufacturer (e.g. "sea" for Seagate) or
product (group) acronym (e.g. "lto5" for the 5th generation LTO (tape)
@@ -401,15 +432,21 @@ Equivalent to \fI\-\-all\fR in the main description.
.TP
\fB\-A\fR
outputs all the log pages and subpages supported by the \fIDEVICE\fR.
-Equivalent to '\-\-all \-\-all' in the main description.
+Equivalent to \fI\-\-ALL\fR in the main description.
.TP
\fB\-c\fR=\fIPC\fR
Equivalent to \fI\-\-control=PC\fR in the main description.
.TP
+\fB\-D\fR=\fIDT\fR
+Equivalent to \fI\-\-pdt=DT\fR in the main description.
+.TP
\fB\-e\fR
enumerate internal tables to show information about known log pages.
Equivalent to \fI\-\-enumerate\fR in the main description.
.TP
+\fB\-E\fR
+Equivalent to \fI\-\-exclude\fR in the main description.
+.TP
\fB\-h\fR
suppresses decoding of known log sense pages and prints out the
response in hex instead.
@@ -508,7 +545,7 @@ Written by Douglas Gilbert
.SH "REPORTING BUGS"
Report bugs to <dgilbert at interlog dot com>.
.SH COPYRIGHT
-Copyright \(co 2002\-2021 Douglas Gilbert
+Copyright \(co 2002\-2022 Douglas Gilbert
.br
This software is distributed under the GPL version 2. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
diff --git a/doc/sg_reset.8 b/doc/sg_reset.8
index 5d4f8f37..7406fa68 100644
--- a/doc/sg_reset.8
+++ b/doc/sg_reset.8
@@ -1,4 +1,4 @@
-.TH SG_RESET "8" "October 2017" "sg3_utils\-1.43" SG3_UTILS
+.TH SG_RESET "8" "March 2022" "sg3_utils\-1.48" SG3_UTILS
.SH NAME
sg_reset \- sends SCSI device, target, bus or host reset; or checks reset
state
@@ -129,7 +129,7 @@ expect the older command line options as outlined in the NOTES section.
.SH AUTHORS
Written by Douglas Gilbert.
.SH COPYRIGHT
-Copyright \(co 1999\-2017 Douglas Gilbert
+Copyright \(co 1999\-2022 Douglas Gilbert
.br
This software is distributed under the GPL version 2. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
diff --git a/include/Makefile.am b/include/Makefile.am
index 64c27b43..4cf82f15 100644
--- a/include/Makefile.am
+++ b/include/Makefile.am
@@ -4,6 +4,7 @@ scsiincludedir = $(includedir)/scsi
scsiinclude_HEADERS = \
sg_lib.h \
sg_lib_data.h \
+ sg_lib_names.h \
sg_cmds.h \
sg_cmds_basic.h \
sg_cmds_extra.h \
diff --git a/include/Makefile.in b/include/Makefile.in
index b39df120..af1d3a79 100644
--- a/include/Makefile.in
+++ b/include/Makefile.in
@@ -126,10 +126,10 @@ am__can_run_installinfo = \
*) (install-info --version) >/dev/null 2>&1;; \
esac
am__noinst_HEADERS_DIST = sg_linux_inc.h sg_io_linux.h sg_pt_win32.h
-am__scsiinclude_HEADERS_DIST = sg_lib.h sg_lib_data.h sg_cmds.h \
- sg_cmds_basic.h sg_cmds_extra.h sg_cmds_mmc.h sg_pr2serr.h \
- sg_unaligned.h sg_pt.h sg_pt_nvme.h sg_linux_inc.h \
- sg_io_linux.h sg_pt_linux.h sg_pt_win32.h
+am__scsiinclude_HEADERS_DIST = sg_lib.h sg_lib_data.h sg_lib_names.h \
+ sg_cmds.h sg_cmds_basic.h sg_cmds_extra.h sg_cmds_mmc.h \
+ sg_pr2serr.h sg_unaligned.h sg_pt.h sg_pt_nvme.h \
+ sg_linux_inc.h sg_io_linux.h sg_pt_linux.h sg_pt_win32.h
am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`;
am__vpath_adj = case $$p in \
$(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \
@@ -304,10 +304,10 @@ top_build_prefix = @top_build_prefix@
top_builddir = @top_builddir@
top_srcdir = @top_srcdir@
scsiincludedir = $(includedir)/scsi
-scsiinclude_HEADERS = sg_lib.h sg_lib_data.h sg_cmds.h sg_cmds_basic.h \
- sg_cmds_extra.h sg_cmds_mmc.h sg_pr2serr.h sg_unaligned.h \
- sg_pt.h sg_pt_nvme.h $(am__append_1) $(am__append_2) \
- $(am__append_3)
+scsiinclude_HEADERS = sg_lib.h sg_lib_data.h sg_lib_names.h sg_cmds.h \
+ sg_cmds_basic.h sg_cmds_extra.h sg_cmds_mmc.h sg_pr2serr.h \
+ sg_unaligned.h sg_pt.h sg_pt_nvme.h $(am__append_1) \
+ $(am__append_2) $(am__append_3)
@OS_FREEBSD_TRUE@noinst_HEADERS = \
@OS_FREEBSD_TRUE@ sg_linux_inc.h \
@OS_FREEBSD_TRUE@ sg_io_linux.h \
diff --git a/include/sg_lib_names.h b/include/sg_lib_names.h
new file mode 100644
index 00000000..df997edd
--- /dev/null
+++ b/include/sg_lib_names.h
@@ -0,0 +1,31 @@
+#ifndef SG_LIB_NAMES_H
+#define SG_LIB_NAMES_H
+
+/*
+ * Copyright (c) 2022 Douglas Gilbert.
+ * All rights reserved.
+ * Use of this source code is governed by a BSD-style
+ * license that can be found in the BSD_LICENSE file.
+ *
+ * SPDX-License-Identifier: BSD-2-Clause
+ */
+
+#include <stdint.h>
+
+#include "sg_lib_data.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+extern struct sg_lib_simple_value_name_t sg_lib_names_mode_arr[];
+extern struct sg_lib_simple_value_name_t sg_lib_names_vpd_arr[];
+
+extern const size_t sg_lib_names_mode_len;
+extern const size_t sg_lib_names_vpd_len;
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* end of SG_LIB_NAMES */
diff --git a/inhex/README b/inhex/README
index d1a50b19..ed2419ce 100644
--- a/inhex/README
+++ b/inhex/README
@@ -2,7 +2,9 @@
========================================
The files in this folder contain hexadecimal data (in ASCII) and associated
-comments (prefixed with the hash mark symbol: '#' ).
+comments (prefixed with the hash mark symbol: '#' ). Files containing
+hexadecimal data have the extension ".hex". There is at least one file
+containing binary data and it has the extension ".raw".
The utility that each hex file is associated with can be determined in most
case by prepending "sg_" to these filenames. Then go to the 'src' folder (a
@@ -15,7 +17,7 @@ after prepending 'sg_' becomes:
sg_vpd_dev_id.hex
which is a partial match on the sg_vpd utility.
The remaining 'dev_id.hex' is meant to suggest the 'device identifier'
-VPD page which is a mandatory VPD page.
+VPD page which is a mandatory VPD page for SCSI devices..
Assuming sg3_utils is installed, it can be tested like this:
sg_vpd --inhex=<folder_holding_sg3_utils>/inhex/vpd_dev_id.hex
diff --git a/inhex/inq_standard.hex b/inhex/inq_standard.hex
index 0c793fed..73c80f37 100644
--- a/inhex/inq_standard.hex
+++ b/inhex/inq_standard.hex
@@ -4,9 +4,9 @@
# SCSI INQUIRY command.
# The response in this file can be decoded with:
-# sg_inq --inhex=sg_inq_standard.hex
+# sg_inq --inhex=inq_standard.hex
# or
-# sg_vpd --inhex=sg_inq_standard.hex --page=sinq
+# sg_vpd --inhex=inq_standard.hex --page=sinq
#
# The sg_inq utility defaults to the 'standard' INQUIRY while the
# sg_vpd utility defaults to the "Supported VPD pages" VPD page.
diff --git a/inhex/logs_last_n.hex b/inhex/logs_last_n.hex
new file mode 100644
index 00000000..b6384d17
--- /dev/null
+++ b/inhex/logs_last_n.hex
@@ -0,0 +1,41 @@
+# This file contains the ASCII hex of a SCSI LOG SENSE command responses
+# for the various "Last n" log (sub)pages concaternated together.
+
+# The response in this file can be decoded with:
+# sg_logs --inhex=logs_last_n.hex
+# or
+# sg_logs --inhex=logs_last_n.hex --brief
+# or
+# sg_logs --inhex=logs_last_n.hex --exclude
+
+# Last n mode page data changed log subpage
+4b 02 00 28
+00 00 03 0c 00 00 00 04 00 00 00 02 00 00 00 01
+00 01 03 04 0a 00 00 00
+00 02 03 04 5a 01 00 00
+00 03 03 04 5c 02 00 00
+
+# Last n INQUIRY data changed log subpage
+4b 01 00 28
+00 00 03 0c 00 00 00 01 00 00 00 03 00 00 00 02
+00 01 03 04 00 00 00 00
+00 02 03 04 01 80 00 00
+00 03 03 04 01 83 00 00
+
+# Last n deferred errors or asynchronous events log subpage
+0b 00 00 5a
+00 00 03 40
+73,0,0,0,0,0,0 38
+b,36,1,0
+0,0,0,2,11,11,11,11,22,22,22,22,55,55,55,55,66,66,66,66 1,0,0,7, 2,0,0,8
+0,0,0,1,77,77,77,77,77,77,77,77,88,88,88,88,88,88,88,88, 3,0,0,5
+00 01 03 12
+f1 00 03 00 00 12 34 0a 00 00 00 00 11 00 00 00 00 00
+
+# Last n error events log page
+07 00 00 31
+00 00 01 0c
+6d 65 64 69 75 6d 20 65 72 72 6f 72
+00 01 01 1d
+55 41 3a 20 63 61 70 61 63 69 74 79 20 64 61 74
+61 20 68 61 73 20 63 68 61 6e 67 65 64
diff --git a/lib/Makefile.am b/lib/Makefile.am
index 16efe9e5..ec3932ed 100644
--- a/lib/Makefile.am
+++ b/lib/Makefile.am
@@ -1,6 +1,7 @@
libsgutils2_la_SOURCES = \
sg_lib.c \
sg_lib_data.c \
+ sg_lib_names.c \
sg_cmds_basic.c \
sg_cmds_basic2.c \
sg_cmds_extra.c \
diff --git a/lib/Makefile.in b/lib/Makefile.in
index e221b44e..3b07a603 100644
--- a/lib/Makefile.in
+++ b/lib/Makefile.in
@@ -145,10 +145,10 @@ am__uninstall_files_from_dir = { \
am__installdirs = "$(DESTDIR)$(libdir)"
LTLIBRARIES = $(lib_LTLIBRARIES)
am__libsgutils2_la_SOURCES_DIST = sg_lib.c sg_lib_data.c \
- sg_cmds_basic.c sg_cmds_basic2.c sg_cmds_extra.c sg_cmds_mmc.c \
- sg_pt_common.c sg_pt_dummy.c sg_pt_linux.c sg_io_linux.c \
- sg_pt_linux_nvme.c sg_pt_win32.c sg_pt_freebsd.c \
- sg_pt_solaris.c sg_pt_osf1.c sg_pt_haiku.c
+ sg_lib_names.c sg_cmds_basic.c sg_cmds_basic2.c \
+ sg_cmds_extra.c sg_cmds_mmc.c sg_pt_common.c sg_pt_dummy.c \
+ sg_pt_linux.c sg_io_linux.c sg_pt_linux_nvme.c sg_pt_win32.c \
+ sg_pt_freebsd.c sg_pt_solaris.c sg_pt_osf1.c sg_pt_haiku.c
@OS_LINUX_TRUE@@PT_DUMMY_TRUE@am__objects_1 = sg_pt_dummy.lo
@OS_LINUX_TRUE@@PT_DUMMY_FALSE@am__objects_2 = sg_pt_linux.lo \
@OS_LINUX_TRUE@@PT_DUMMY_FALSE@ sg_io_linux.lo \
@@ -164,13 +164,13 @@ am__libsgutils2_la_SOURCES_DIST = sg_lib.c sg_lib_data.c \
@OS_NETBSD_TRUE@am__objects_11 = sg_pt_dummy.lo
@OS_OPENBSD_TRUE@am__objects_12 = sg_pt_dummy.lo
@OS_OTHER_TRUE@am__objects_13 = sg_pt_dummy.lo
-am_libsgutils2_la_OBJECTS = sg_lib.lo sg_lib_data.lo sg_cmds_basic.lo \
- sg_cmds_basic2.lo sg_cmds_extra.lo sg_cmds_mmc.lo \
- sg_pt_common.lo $(am__objects_1) $(am__objects_2) \
- $(am__objects_3) $(am__objects_4) $(am__objects_5) \
- $(am__objects_6) $(am__objects_7) $(am__objects_8) \
- $(am__objects_9) $(am__objects_10) $(am__objects_11) \
- $(am__objects_12) $(am__objects_13)
+am_libsgutils2_la_OBJECTS = sg_lib.lo sg_lib_data.lo sg_lib_names.lo \
+ sg_cmds_basic.lo sg_cmds_basic2.lo sg_cmds_extra.lo \
+ sg_cmds_mmc.lo sg_pt_common.lo $(am__objects_1) \
+ $(am__objects_2) $(am__objects_3) $(am__objects_4) \
+ $(am__objects_5) $(am__objects_6) $(am__objects_7) \
+ $(am__objects_8) $(am__objects_9) $(am__objects_10) \
+ $(am__objects_11) $(am__objects_12) $(am__objects_13)
libsgutils2_la_OBJECTS = $(am_libsgutils2_la_OBJECTS)
AM_V_lt = $(am__v_lt_@AM_V@)
am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@)
@@ -199,11 +199,11 @@ am__depfiles_remade = ./$(DEPDIR)/sg_cmds_basic.Plo \
./$(DEPDIR)/sg_cmds_basic2.Plo ./$(DEPDIR)/sg_cmds_extra.Plo \
./$(DEPDIR)/sg_cmds_mmc.Plo ./$(DEPDIR)/sg_io_linux.Plo \
./$(DEPDIR)/sg_lib.Plo ./$(DEPDIR)/sg_lib_data.Plo \
- ./$(DEPDIR)/sg_pt_common.Plo ./$(DEPDIR)/sg_pt_dummy.Plo \
- ./$(DEPDIR)/sg_pt_freebsd.Plo ./$(DEPDIR)/sg_pt_haiku.Plo \
- ./$(DEPDIR)/sg_pt_linux.Plo ./$(DEPDIR)/sg_pt_linux_nvme.Plo \
- ./$(DEPDIR)/sg_pt_osf1.Plo ./$(DEPDIR)/sg_pt_solaris.Plo \
- ./$(DEPDIR)/sg_pt_win32.Plo
+ ./$(DEPDIR)/sg_lib_names.Plo ./$(DEPDIR)/sg_pt_common.Plo \
+ ./$(DEPDIR)/sg_pt_dummy.Plo ./$(DEPDIR)/sg_pt_freebsd.Plo \
+ ./$(DEPDIR)/sg_pt_haiku.Plo ./$(DEPDIR)/sg_pt_linux.Plo \
+ ./$(DEPDIR)/sg_pt_linux_nvme.Plo ./$(DEPDIR)/sg_pt_osf1.Plo \
+ ./$(DEPDIR)/sg_pt_solaris.Plo ./$(DEPDIR)/sg_pt_win32.Plo
am__mv = mv -f
COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
$(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
@@ -374,9 +374,9 @@ target_alias = @target_alias@
top_build_prefix = @top_build_prefix@
top_builddir = @top_builddir@
top_srcdir = @top_srcdir@
-libsgutils2_la_SOURCES = sg_lib.c sg_lib_data.c sg_cmds_basic.c \
- sg_cmds_basic2.c sg_cmds_extra.c sg_cmds_mmc.c sg_pt_common.c \
- $(am__append_1) $(am__append_2) $(am__append_3) \
+libsgutils2_la_SOURCES = sg_lib.c sg_lib_data.c sg_lib_names.c \
+ sg_cmds_basic.c sg_cmds_basic2.c sg_cmds_extra.c sg_cmds_mmc.c \
+ sg_pt_common.c $(am__append_1) $(am__append_2) $(am__append_3) \
$(am__append_4) $(am__append_5) $(am__append_6) \
$(am__append_7) $(am__append_8) $(am__append_9) \
$(am__append_10) $(am__append_11) $(am__append_12) \
@@ -491,6 +491,7 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sg_io_linux.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sg_lib.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sg_lib_data.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sg_lib_names.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sg_pt_common.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sg_pt_dummy.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sg_pt_freebsd.Plo@am__quote@ # am--include-marker
@@ -668,6 +669,7 @@ distclean: distclean-am
-rm -f ./$(DEPDIR)/sg_io_linux.Plo
-rm -f ./$(DEPDIR)/sg_lib.Plo
-rm -f ./$(DEPDIR)/sg_lib_data.Plo
+ -rm -f ./$(DEPDIR)/sg_lib_names.Plo
-rm -f ./$(DEPDIR)/sg_pt_common.Plo
-rm -f ./$(DEPDIR)/sg_pt_dummy.Plo
-rm -f ./$(DEPDIR)/sg_pt_freebsd.Plo
@@ -729,6 +731,7 @@ maintainer-clean: maintainer-clean-am
-rm -f ./$(DEPDIR)/sg_io_linux.Plo
-rm -f ./$(DEPDIR)/sg_lib.Plo
-rm -f ./$(DEPDIR)/sg_lib_data.Plo
+ -rm -f ./$(DEPDIR)/sg_lib_names.Plo
-rm -f ./$(DEPDIR)/sg_pt_common.Plo
-rm -f ./$(DEPDIR)/sg_pt_dummy.Plo
-rm -f ./$(DEPDIR)/sg_pt_freebsd.Plo
diff --git a/lib/sg_lib.c b/lib/sg_lib.c
index e504e6b8..c4fe1d7d 100644
--- a/lib/sg_lib.c
+++ b/lib/sg_lib.c
@@ -1063,7 +1063,7 @@ sg_get_designation_descriptor_str(const char * lip, const uint8_t * ddp,
}
ccc_id = sg_get_unaligned_be64(ip + ci_off);
n += sg_scnpr(b + n, blen - n, "%s IEEE identifier: 0x%"
- PRIx64 "x\n", lip, ccc_id);
+ PRIx64 "x\n", lip, ccc_id);
if (12 == dlen) {
d_id = sg_get_unaligned_be32(ip + 8);
n += sg_scnpr(b + n, blen - n, "%s Directory ID: 0x%x\n",
@@ -1093,7 +1093,7 @@ sg_get_designation_descriptor_str(const char * lip, const uint8_t * ddp,
n += sg_scnpr(b + n, blen - n, "%s NAA 2, vendor "
"specific identifier A: 0x%x\n", lip, d_id);
n += sg_scnpr(b + n, blen - n, "%s AOI: 0x%x\n", lip,
- c_id);
+ c_id);
n += sg_scnpr(b + n, blen - n, "%s vendor specific "
"identifier B: 0x%x\n", lip, vsi);
n += sg_scnpr(b + n, blen - n, "%s [0x", lip);
@@ -1137,7 +1137,7 @@ sg_get_designation_descriptor_str(const char * lip, const uint8_t * ddp,
}
if (do_long) {
n += sg_scnpr(b + n, blen - n, "%s NAA 5, AOI: 0x%x\n",
- lip, c_id);
+ lip, c_id);
n += sg_scnpr(b + n, blen - n, "%s Vendor Specific "
"Identifier: 0x%" PRIx64 "\n", lip, vsei);
n += sg_scnpr(b + n, blen - n, "%s [0x", lip);
@@ -1167,7 +1167,7 @@ sg_get_designation_descriptor_str(const char * lip, const uint8_t * ddp,
}
if (do_long) {
n += sg_scnpr(b + n, blen - n, "%s NAA 6, AOI: 0x%x\n",
- lip, c_id);
+ lip, c_id);
n += sg_scnpr(b + n, blen - n, "%s Vendor Specific "
"Identifier: 0x%" PRIx64 "\n", lip, vsei);
vsei = sg_get_unaligned_be64(ip + 8);
@@ -2943,24 +2943,27 @@ dStrHexErr(const char* str, int len, int no_ascii)
(sg_warnings_strm ? sg_warnings_strm : stderr));
}
-#define DSHS_LINE_BLEN 160
-#define DSHS_BPL 16
+#define DSHS_LINE_BLEN 160 /* maximum characters per line */
+#define DSHS_BPL 16 /* bytes per line */
/* Read 'len' bytes from 'str' and output as ASCII-Hex bytes (space
* separated) to 'b' not to exceed 'b_len' characters. Each line
* starts with 'leadin' (NULL for no leadin) and there are 16 bytes
* per line with an extra space between the 8th and 9th bytes. 'format'
- * is 0 for repeat in printable ASCII ('.' for non printable) to
- * right of each line; 1 don't (so just output ASCII hex). Returns
- * number of bytes written to 'b' excluding the trailing '\0'. */
+ * is 0 for repeat in printable ASCII ('.' for non printable chars) to
+ * right of each line; 1 don't (so just output ASCII hex). Note that
+ * an address is not printed on each line preceding the hex data. Returns
+ * number of bytes written to 'b' excluding the trailing '\0'.
+ * The only difference between dStrHexStr() and hex2str() is the type of
+ * the first argument. */
int
dStrHexStr(const char * str, int len, const char * leadin, int format,
int b_len, char * b)
{
int bpstart, bpos, k, n, prior_ascii_len;
bool want_ascii;
- char buff[DSHS_LINE_BLEN + 2];
- char a[DSHS_BPL + 1];
+ char buff[DSHS_LINE_BLEN + 2]; /* allow for trailing null */
+ char a[DSHS_BPL + 1]; /* printable ASCII bytes or '.' */
const char * p = str;
if (len <= 0) {
@@ -3531,6 +3534,8 @@ sg_get_llnum_nomult(const char * buf)
return (1 == res) ? num : -1;
}
+#define MAX_NUM_ASCII_LINES 1048576
+
/* Read ASCII hex bytes or binary from fname (a file named '-' taken as
* stdin). If reading ASCII hex then there should be either one entry per
* line or a comma, space or tab separated list of bytes. If no_space is
@@ -3622,7 +3627,7 @@ sg_f2hex_arr(const char * fname, bool as_binary, bool no_space,
}
carry_over[0] = 0;
- for (j = 0; j < 512; ++j) {
+ for (j = 0; j < MAX_NUM_ASCII_LINES; ++j) {
if (NULL == fgets(line, sizeof(line), fp))
break;
in_len = strlen(line);
@@ -3740,6 +3745,11 @@ sg_f2hex_arr(const char * fname, bool as_binary, bool no_space,
}
off += (k + 1);
}
+ } /* end of per line loop */
+ if (j >= MAX_NUM_ASCII_LINES) {
+ pr2ws("%s: wow, more than %d lines of ASCII, give up\n", __func__,
+ SG_LIB_LBA_OUT_OF_RANGE);
+ return SG_LIB_LBA_OUT_OF_RANGE;
}
*mp_arr_len = off;
if (stdin != fp)
diff --git a/lib/sg_lib_data.c b/lib/sg_lib_data.c
index a7970f2a..f6c9b3ac 100644
--- a/lib/sg_lib_data.c
+++ b/lib/sg_lib_data.c
@@ -19,7 +19,7 @@
#include "sg_lib_data.h"
-const char * sg_lib_version_str = "2.87 20220217";
+const char * sg_lib_version_str = "2.88 20220305";
/* spc6r06, sbc5r01, zbc2r12 */
@@ -257,7 +257,7 @@ struct sg_lib_value_name_t sg_lib_read_buff_arr[] = {
{0x3, PDT_ALL, "descriptor"},
{0xa, PDT_ALL, "read data from echo buffer"},
{0xb, PDT_ALL, "echo buffer descriptor"},
- {0xf, PDT_ALL, "read microcode status"}, /* added in spc5r20 */
+ {0xf, PDT_ALL, "read microcode status"}, /* added in spc5r20 */
{0x1a, PDT_ALL, "enable expander comms protocol and echo buffer"},
{0x1c, PDT_ALL, "error history"},
{0xffff, 0, NULL},
diff --git a/lib/sg_lib_names.c b/lib/sg_lib_names.c
new file mode 100644
index 00000000..2543f2ab
--- /dev/null
+++ b/lib/sg_lib_names.c
@@ -0,0 +1,132 @@
+/*
+ * Copyright (c) 2022 Douglas Gilbert.
+ * All rights reserved.
+ * Use of this source code is governed by a BSD-style
+ * license that can be found in the BSD_LICENSE file.
+ *
+ * SPDX-License-Identifier: BSD-2-Clause
+ */
+
+#include <stdlib.h>
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#else
+#define SG_SCSI_STRINGS 1
+#endif
+
+#include "sg_lib.h"
+#include "sg_lib_data.h"
+#include "sg_lib_names.h"
+
+/* List of SPC, then SBC, the ZBC mode page names. Tape and other mode pages
+ * are squeezed into this list as long as they don't conflict.
+ * The value is: (mode_page << 8) | mode_subpage
+ * Maintain the list in numerical order to allow binary search. */
+struct sg_lib_simple_value_name_t sg_lib_names_mode_arr[] = {
+ {0x0000, "Unit Attention condition"}, /* common vendor specific page */
+ {0x0100, "Read-Write error recovery"}, /* SBC */
+ {0x0200, "Disconnect-Reconnect"}, /* SPC */
+ {0x0300, "Format (obsolete)"}, /* SBC */
+ {0x0400, "Rigid disk geometry (obsolete)"}, /* SBC */
+ {0x0500, "Flexible disk (obsolete)"}, /* SBC */
+ {0x0700, "Verify error recovery"}, /* SBC */
+ {0x0800, "Caching"}, /* SBC */
+ {0x0900, "Peripheral device (obsolete)"}, /* SPC */
+ {0x0a00, "Control"}, /* SPC */
+ {0x0a01, "Control extension"}, /* SPC */
+ {0x0a02, "Application tage"}, /* SBC */
+ {0x0a03, "Command duration limit A"}, /* SPC */
+ {0x0a04, "Command duration limit B"}, /* SPC */
+ {0x0a05, "IO Advice Hints Grouping"}, /* SBC */
+ {0x0a06, "Background operation control"}, /* SBC */
+ {0x0af0, "Control data protection"}, /* SSC */
+ {0x0af1, "PATA control"}, /* SAT */
+ {0x0b00, "Medium Types Supported (obsolete)"}, /* SSC */
+ {0x0c00, "Notch and partition (obsolete)"}, /* SBC */
+ {0x0d00, "Power condition (obsolete), CD device parameters"},
+ {0x0e00, "CD audio control"}, /* MMC */
+ {0x0e01, "Target device"}, /* ADC */
+ {0x0e02, "DT device primary port"}, /* ADC */
+ {0x0e03, "Logical unit"}, /* ADC */
+ {0x0e04, "Target device serial number"}, /* ADC */
+ {0x0f00, "Data compression"}, /* SSC */
+ {0x1000, "XOR control (obsolete, Device configuration"}, /* SBC,SSC */
+ {0x1001, "Device configuration extension"}, /* SSC */
+ {0x1100, "Medium partition (1)"}, /* SSC */
+ {0x1400, "Enclosure services management"}, /* SES */
+ {0x1800, "Protocol specific logical unit"}, /* transport */
+ {0x1900, "Protocol specific port"}, /* transport */
+ {0x1901, "Phy control and discovery"}, /* SPL */
+ {0x1902, "Shared port control"}, /* SPL */
+ {0x1903, "Enhanced phy control"}, /* SPL */
+ {0x1904, "Out of band management control"}, /* SPL */
+ {0x1A00, "Power condition"}, /* SPC */
+ {0x1A01, "Power consumption"}, /* SPC */
+ {0x1Af1, "ATA Power condition"}, /* SPC */
+ {0x1b00, "LUN mapping"}, /* ADC */
+ {0x1c00, "Information exceptions control"}, /* SPC */
+ {0x1c01, "Background control"}, /* SBC */
+ {0x1c02, "Logical block provisioning"}, /* SBC */
+ {0x1c02, "Logical block provisioning"}, /* SBC */
+ {0x1d00, "Medium configuration, CD/DVD timeout, "
+ "element address assignments"}, /* SSC,MMC,SMC */
+ {0x1e00, "Transport geometry assignments"}, /* SMC */
+ {0x1f00, "Device capabilities"}, /* SMC */
+
+ {-1, NULL}, /* sentinel */
+};
+
+/* Don't count sentinel when doing binary searches, etc */
+const size_t sg_lib_names_mode_len =
+ SG_ARRAY_SIZE(sg_lib_names_mode_arr) - 1;
+
+/* List of SPC, then SBC, the ZBC VPD page names. Tape and other VPD pages
+ * are squeezed into this list as long as they don't conflict.
+ * For VPDs > 0 the value is: (vpd << 8) | vpd_number
+ * Maintain the list in numerical order to allow binary search. */
+struct sg_lib_simple_value_name_t sg_lib_names_vpd_arr[] = {
+ {0x00, "Supported VPD pages"}, /* SPC */
+ {0x80, "Unit serial number"}, /* SPC */
+ {0x81, "Implemented operating definition (obsolete)"}, /* SPC */
+ {0x82, "ASCII implemented operating definition (obsolete)"}, /* SPC */
+ {0x83, "Device identification"}, /* SPC */
+ {0x84, "Software interface identification"}, /* SPC */
+ {0x85, "Management network addresses"}, /* SPC */
+ {0x86, "Extended INQUIRY data"}, /* SPC */
+ {0x87, "Mode page policy"}, /* SPC */
+ {0x88, "SCSI ports"}, /* SPC */
+ {0x89, "ATA information"}, /* SAT */
+ {0x8a, "Power condition"}, /* SPC */
+ {0x8b, "Device constituents"}, /* SSC */
+ {0x8c, "CFA profile information"}, /* SPC */
+ {0x8d, "Power consumption"}, /* SPC */
+ {0x8f, "Third party copy"}, /* SPC */
+ {0x90, "Protocol specific logical unit information"}, /* transport */
+ {0x91, "Protocol specific port information"}, /* transport */
+ {0x92, "SCSI feature sets"}, /* SPC,SBC */
+ {0xb0, "Block limits"}, /* SBC */
+ {0xb1, "Block device characteristics"}, /* SBC */
+ {0xb2, "Logical block provisioning"}, /* SBC */
+ {0xb3, "Referrals"}, /* SBC */
+ {0xb4, "Supported Block Lengths and Protection Types"}, /* SBC */
+ {0xb5, "Block device characteristics extension"}, /* SBC */
+ {0xb6, "Zoned block device characteristics"}, /* ZBC */
+ {0xb7, "Block limits extension"}, /* SBC */
+ {0xb8, "Format presets"}, /* SBC */
+ {0xb9, "Concurrent positioning ranges"}, /* SBC */
+ {0x01b0, "Sequential access Device Capabilities"}, /* SSC */
+ {0x01b1, "Manufacturer-assigned serial number"}, /* SSC */
+ {0x01b2, "TapeAlert supported flags"}, /* SSC */
+ {0x01b3, "Automation device serial number"}, /* SSC */
+ {0x01b4, "Data transfer device element address"}, /* SSC */
+ {0x01b5, "Data transfer device element address"}, /* SSC */
+ {0x11b0, "OSD information"}, /* OSD */
+ {0x11b1, "Security token"}, /* OSD */
+
+ {-1, NULL}, /* sentinel */
+};
+
+/* Don't count sentinel when doing binary searches, etc */
+const size_t sg_lib_names_vpd_len =
+ SG_ARRAY_SIZE(sg_lib_names_vpd_arr) - 1;
diff --git a/sg3_utils.spec b/sg3_utils.spec
index fa3cfa2b..447018b7 100644
--- a/sg3_utils.spec
+++ b/sg3_utils.spec
@@ -84,7 +84,7 @@ fi
%{_libdir}/*.la
%changelog
-* Tue Feb 22 2022 - dgilbert at interlog dot com
+* Sun Mar 06 2022 - dgilbert at interlog dot com
- track t10 changes
* sg3_utils-1.48
diff --git a/src/sg_logs.c b/src/sg_logs.c
index f125878b..9c44d6be 100644
--- a/src/sg_logs.c
+++ b/src/sg_logs.c
@@ -29,6 +29,7 @@
#include "config.h"
#endif
#include "sg_lib.h"
+#include "sg_lib_names.h"
#include "sg_cmds_basic.h"
#ifdef SG_LIB_WIN32
#include "sg_pt.h" /* needed for scsi_pt_win32_direct() */
@@ -36,9 +37,11 @@
#include "sg_unaligned.h"
#include "sg_pr2serr.h"
-static const char * version_str = "1.95 20220218"; /* spc6r06 + sbc5r01 */
+static const char * version_str = "1.97 20220309"; /* spc6r06 + sbc5r01 */
#define MX_ALLOC_LEN (0xfffc)
+#define MX_INLEN_ALLOC_LEN (0x800000)
+#define DEF_INLEN_ALLOC_LEN (0x40000)
#define SHORT_RESP_LEN 128
#define SUPP_PAGES_LPAGE 0x0
@@ -114,16 +117,17 @@ static const char * version_str = "1.95 20220218"; /* spc6r06 + sbc5r01 */
static uint8_t * rsp_buff;
static uint8_t * free_rsp_buff;
-static const int rsp_buff_sz = MX_ALLOC_LEN + 4;
+static int rsp_buff_sz = MX_ALLOC_LEN + 4;
static const int parr_sz = 4096;
static struct option long_options[] = {
{"All", no_argument, 0, 'A'}, /* equivalent to '-aa' */
- {"ALL", no_argument, 0, 'A'},
+ {"ALL", no_argument, 0, 'A'}, /* equivalent to '-aa' */
{"all", no_argument, 0, 'a'},
{"brief", no_argument, 0, 'b'},
{"control", required_argument, 0, 'c'},
{"enumerate", no_argument, 0, 'e'},
+ {"exclude", no_argument, 0, 'E'},
{"filter", required_argument, 0, 'f'},
{"help", no_argument, 0, 'h'},
{"hex", no_argument, 0, 'H'},
@@ -148,6 +152,7 @@ static struct option long_options[] = {
{"select", no_argument, 0, 'S'},
{"temperature", no_argument, 0, 't'},
{"transport", no_argument, 0, 'T'},
+ {"undefined", no_argument, 0, 'u'},
{"vendor", required_argument, 0, 'M'},
{"verbose", no_argument, 0, 'v'},
{"version", no_argument, 0, 'V'},
@@ -164,7 +169,9 @@ struct opts_t {
bool do_sp;
bool do_temperature;
bool do_transport;
+ bool exclude_vendor;
bool filter_given;
+ bool maxlen_given;
bool o_readonly;
bool opt_new;
bool verbose_given;
@@ -175,6 +182,7 @@ struct opts_t {
int do_help;
int do_hex;
int do_list;
+ int dstrhex_no_ascii; /* value for dStrHex() no_ascii argument */
int vend_prod_num; /* one of the VP_* constants or -1 (def) */
int deduced_vpn; /* deduced vendor_prod_num; from INQUIRY, etc */
int verbose;
@@ -187,6 +195,7 @@ struct opts_t {
int no_inq;
int dev_pdt; /* from device or --pdt=DT */
int decod_subpg_code;
+ int undefined_hex; /* hex format of undefined/unrecognized fields */
const char * device_name;
const char * in_fn;
const char * pg_arg;
@@ -216,6 +225,8 @@ struct vp_name_t {
const char * t10_productp;
};
+static const char * ls_s = "log_sense: ";
+
static bool show_supported_pgs_page(const uint8_t * resp, int len,
const struct opts_t * op);
static bool show_supported_pgs_sub_page(const uint8_t * resp, int len,
@@ -498,20 +509,21 @@ usage(int hval)
{
if (1 == hval) {
pr2serr(
- "Usage: sg_logs [-All] [--all] [--brief] [--control=PC] "
+ "Usage: sg_logs [-ALL] [--all] [--brief] [--control=PC] "
"[--enumerate]\n"
- " [--filter=FL] [--help] [--hex] [--in=FN] "
- "[--list]\n"
- " [--no_inq] [--maxlen=LEN] [--name] [--page=PG]\n"
+ " [--exclude] [--filter=FL] [--help] [--hex] "
+ "[--in=FN]\n"
+ " [--list] [--no_inq] [--maxlen=LEN] [--name] "
+ "[--page=PG]\n"
" [--paramp=PP] [--pcb] [--ppc] [--pdt=DT] "
"[--raw]\n"
" [--readonly] [--reset] [--select] [--sp] "
- "[--temperature]\n"
- " [--transport] [--vendor=VP] [--verbose] "
- "[--version]\n"
- " DEVICE\n"
+ "[--undefined]\n"
+ " [--temperature] [--transport] [--vendor=VP] "
+ "[--verbose]\n"
+ " [--version] DEVICE\n"
" where the main options are:\n"
- " --All|-A fetch and decode all log pages and "
+ " --ALL|-A fetch and decode all log pages and "
"subpages\n"
" --all|-a fetch and decode all log pages, but not "
"subpages; use\n"
@@ -535,7 +547,8 @@ usage(int hval)
"known)\n"
" --in=FN|-i FN FN is a filename containing a log page "
"in ASCII hex\n"
- " or binary if --raw also given.\n"
+ " or binary if --raw also given. --inhex=FN "
+ "also accepted\n"
" --list|-l list supported log pages; twice: list "
"supported log\n"
" pages and subpages page; thrice: merge of "
@@ -567,6 +580,8 @@ usage(int hval)
"cumulative\n"
" 2: default threshold, 3: default "
"cumulative\n"
+ " --exclude|-E exclude vendor specific pages and "
+ "parameters\n"
" --list|-l list supported log page names (equivalent to "
"'-p sp')\n"
" use twice to list supported log page and "
@@ -579,7 +594,8 @@ usage(int hval)
" --no_inq|-x no initial INQUIRY output (twice: and no "
"INQUIRY call)\n"
" --old|-O use old interface (use as first option)\n"
- " --paramp=PP|-P PP parameter pointer (decimal) (def: 0)\n"
+ " --paramp=PP|-P PP place PP in parameter pointer field in "
+ "cdb (def: 0)\n"
" --pcb|-q show parameter control bytes in decoded "
"output\n"
" --ppc|-Q set the Parameter Pointer Control (PPC) bit "
@@ -596,6 +612,10 @@ usage(int hval)
" --select|-S perform LOG SELECT (def: LOG SENSE)\n"
" --sp|-s set the Saving Parameters (SP) bit (def: "
"0)\n"
+ " --undefined|-u hex format for undefined/unrecognized "
+ "fields,\n"
+ " use one or more times; format as per "
+ "--hex\n"
" --version|-V output version string then exit\n\n"
"If DEVICE and --select are given, a LOG SELECT command will be "
"issued.\nIf DEVICE is not given and '--in=FN' is given then FN "
@@ -609,13 +629,13 @@ usage(int hval)
static void
usage_old()
{
- printf("Usage: sg_logs [-a] [-A] [-b] [-c=PC] [-D=DT] [-e] [-f=FL] "
+ printf("Usage: sg_logs [-a] [-A] [-b] [-c=PC] [-D=DT] [-e] [-E] [-f=FL] "
"[-h]\n"
" [-H] [-i=FN] [-l] [-L] [-m=LEN] [-M=VP] [-n] "
"[-p=PG]\n"
" [-paramp=PP] [-pcb] [-ppc] [-r] [-select] [-sp] "
"[-t] [-T]\n"
- " [-v] [-V] [-x] [-X] [-?] DEVICE\n"
+ " [-u] [-v] [-V] [-x] [-X] [-?] DEVICE\n"
" where:\n"
" -a fetch and decode all log pages\n"
" -A fetch and decode all log pages and subpages\n"
@@ -624,6 +644,9 @@ usage_old()
" 0: current threshold, 1: current cumulative\n"
" 2: default threshold, 3: default cumulative\n"
" -e enumerate known log pages\n"
+ " -D=DT DT is peripheral device type to use with "
+ "'--in=FN'\n"
+ " -E exclude vendor specific pages and parameters\n"
" -f=FL filter match parameter code or pdt\n"
" -h output in hex (default: decode if known)\n"
" -H output in hex (same as '-h')\n"
@@ -656,6 +679,7 @@ usage_old()
" -t outputs temperature log page (0xd)\n"
" -T outputs transport (protocol specific port) log "
"page (0x18)\n"
+ " -u hex format for undefined/unrecognized fields\n"
" -v increase verbosity\n"
" -V output version string\n"
" -x no initial INQUIRY output (twice: no INQUIRY call)\n"
@@ -818,6 +842,8 @@ find_vpn_by_acron(const char * vp_ap)
return VP_NONE;
}
+/* Find vendor product number using T10 VENDOR and PRODUCT ID fields in a
+ INQUIRY response. */
static int
find_vpn_by_inquiry(void)
{
@@ -918,7 +944,7 @@ new_parse_cmd_line(struct opts_t * op, int argc, char * argv[])
int c, n;
int option_index = 0;
- c = getopt_long(argc, argv, "aAbc:D:ef:hHi:lLm:M:nNOp:P:qQrRsStTvV"
+ c = getopt_long(argc, argv, "aAbc:D:eEf:hHi:lLm:M:nNOp:P:qQrRsStTuvV"
"xX", long_options, &option_index);
if (c == -1)
break;
@@ -943,16 +969,23 @@ new_parse_cmd_line(struct opts_t * op, int argc, char * argv[])
op->page_control = n;
break;
case 'D':
- n = sg_get_num(optarg);
- if ((n < 0) || (n > 31)) {
- pr2serr("bad argument to '--pdt='\n");
- return SG_LIB_SYNTAX_ERROR;
+ if (0 == memcmp("-1", optarg, 3))
+ op->dev_pdt = -1;
+ else {
+ n = sg_get_num(optarg);
+ if ((n < 0) || (n > 31)) {
+ pr2serr("bad argument to '--pdt='\n");
+ return SG_LIB_SYNTAX_ERROR;
+ }
+ op->dev_pdt = n;
}
- op->dev_pdt = n;
break;
case 'e':
++op->do_enumerate;
break;
+ case 'E':
+ op->exclude_vendor = true;
+ break;
case 'f':
if ('-' == optarg[0]) {
n = sg_get_num(optarg + 1);
@@ -990,9 +1023,9 @@ new_parse_cmd_line(struct opts_t * op, int argc, char * argv[])
break;
case 'm':
n = sg_get_num(optarg);
- if ((n < 0) || (1 == n) || (n > 0xffff)) {
- pr2serr("bad argument to '--maxlen=', from 2 to 65535 "
- "(inclusive) expected\n");
+ if ((n < 0) || (1 == n)) {
+ pr2serr("bad argument to '--maxlen=', from 2 and up "
+ "expected\n");
usage(2);
return SG_LIB_SYNTAX_ERROR;
} else if (n < 4) {
@@ -1000,6 +1033,7 @@ new_parse_cmd_line(struct opts_t * op, int argc, char * argv[])
n = 4;
}
op->maxlen = n;
+ op->maxlen_given = true;
break;
case 'M':
if (op->vend_prod) {
@@ -1054,6 +1088,9 @@ new_parse_cmd_line(struct opts_t * op, int argc, char * argv[])
case 'T':
op->do_transport = true;
break;
+ case 'u':
+ ++op->undefined_hex;
+ break;
case 'v':
op->verbose_given = true;
++op->verbose;
@@ -1122,6 +1159,9 @@ old_parse_cmd_line(struct opts_t * op, int argc, char * argv[])
case 'e':
++op->do_enumerate;
break;
+ case 'E':
+ op->exclude_vendor = true;
+ break;
case 'h':
case 'H':
++op->do_hex;
@@ -1150,6 +1190,9 @@ old_parse_cmd_line(struct opts_t * op, int argc, char * argv[])
case 'T':
op->do_transport = true;
break;
+ case 'u':
+ ++op->undefined_hex;
+ break;
case 'v':
op->verbose_given = true;
++op->verbose;
@@ -1208,12 +1251,13 @@ old_parse_cmd_line(struct opts_t * op, int argc, char * argv[])
op->in_fn = cp + 2;
else if (0 == strncmp("m=", cp, 2)) {
num = sscanf(cp + 2, "%8d", &n);
- if ((1 != num) || (n < 0) || (n > MX_ALLOC_LEN)) {
+ if ((1 != num) || (n < 0)) {
pr2serr("Bad maximum response length after '-m=' "
"option\n");
usage_old();
return SG_LIB_SYNTAX_ERROR;
}
+ op->maxlen_given = true;
op->maxlen = n;
} else if (0 == strncmp("M=", cp, 2)) {
if (op->vend_prod) {
@@ -1520,6 +1564,13 @@ show_supported_pgs_page(const uint8_t * resp, int len,
printf("Supported log pages [0x0]:\n"); /* introduced: SPC-2 */
num = len - 4;
bp = &resp[0] + 4;
+ if ((op->do_hex > 0) || op->do_raw) {
+ if (op->do_raw)
+ dStrRaw(resp, len);
+ else
+ hex2stdout(resp, len, op->dstrhex_no_ascii);
+ return true;
+ }
for (k = 0; k < num; ++k) {
int pg_code = bp[k];
const struct log_elem * lep;
@@ -1558,6 +1609,13 @@ show_supported_pgs_sub_page(const uint8_t * resp, int len,
}
num = len - 4;
bp = &resp[0] + 4;
+ if ((op->do_hex > 0) || op->do_raw) {
+ if (op->do_raw)
+ dStrRaw(resp, len);
+ else
+ hex2stdout(resp, len, op->dstrhex_no_ascii);
+ return true;
+ }
for (k = 0; k < num; k += 2) {
int pg_code = bp[k];
int subpg_code = bp[k + 1];
@@ -1609,13 +1667,13 @@ show_buffer_over_under_run_page(const uint8_t * resp, int len,
if (op->filter_given) {
if (pc != op->filter)
goto skip;
- if (op->do_raw) {
- dStrRaw(bp, pl);
- break;
- } else if (op->do_hex) {
- hex2stdout(bp, pl, ((1 == op->do_hex) ? 1 : -1));
- break;
- }
+ }
+ if (op->do_raw) {
+ dStrRaw(bp, pl);
+ break;
+ } else if (op->do_hex) {
+ hex2stdout(bp, pl, op->dstrhex_no_ascii);
+ break;
}
switch (pc) {
case 0x0:
@@ -1716,6 +1774,8 @@ static bool
show_error_counter_page(const uint8_t * resp, int len,
const struct opts_t * op)
{
+ bool skip_out = false;
+ bool evsm_output = false;
int num, pl, pc, pg_code;
uint64_t val;
const uint8_t * bp;
@@ -1751,13 +1811,13 @@ show_error_counter_page(const uint8_t * resp, int len,
if (op->filter_given) {
if (pc != op->filter)
goto skip;
- if (op->do_raw) {
- dStrRaw(bp, pl);
- break;
- } else if (op->do_hex) {
- hex2stdout(bp, pl, ((1 == op->do_hex) ? 1 : -1));
- break;
- }
+ }
+ if (op->do_raw) {
+ dStrRaw(bp, pl);
+ break;
+ } else if (op->do_hex) {
+ hex2stdout(bp, pl, op->dstrhex_no_ascii);
+ break;
}
switch (pc) {
case 0: printf(" Errors corrected without substantial delay"); break;
@@ -1767,17 +1827,34 @@ show_error_counter_page(const uint8_t * resp, int len,
case 4: printf(" Total times correction algorithm processed"); break;
case 5: printf(" Total bytes processed"); break;
case 6: printf(" Total uncorrected errors"); break;
- case 0x8009: printf(" Track following errors [Hitachi]"); break;
- case 0x8015: printf(" Positioning errors [Hitachi]"); break;
- default: printf(" Reserved or vendor specific [0x%x]", pc); break;
- }
- val = sg_get_unaligned_be(pl - 4, bp + 4);
- printf(" = %" PRIu64 "", val);
- if (val > ((uint64_t)1 << 40))
- printf(" [%" PRIu64 " TB]\n",
- (val / (1000UL * 1000 * 1000 * 1000)));
- else
- printf("\n");
+ default:
+ if (op->exclude_vendor) {
+ skip_out = true;
+ if ((op->verbose > 0) && (0 == op->do_brief) &&
+ (! evsm_output)) {
+ evsm_output = true;
+ printf(" Vendor specific parameter(s) being ignored\n");
+ }
+ } else {
+ if (0x8009 == pc)
+ printf(" Track following errors [Hitachi]");
+ else if (0x8015 == pc)
+ printf(" Positioning errors [Hitachi]");
+ else
+ printf(" Reserved or vendor specific [0x%x]", pc);
+ }
+ }
+ if (skip_out)
+ skip_out = false;
+ else {
+ val = sg_get_unaligned_be(pl - 4, bp + 4);
+ printf(" = %" PRIu64 "", val);
+ if (val > ((uint64_t)1 << 40))
+ printf(" [%" PRIu64 " TB]\n",
+ (val / (1000UL * 1000 * 1000 * 1000)));
+ else
+ printf("\n");
+ }
if (op->do_pcb)
printf(" <%s>\n", get_pcb_str(bp[2], str, sizeof(str)));
if (op->filter_given)
@@ -1794,6 +1871,8 @@ static bool
show_non_medium_error_page(const uint8_t * resp, int len,
const struct opts_t * op)
{
+ bool skip_out = false;
+ bool evsm_output = false;
int num, pl, pc;
const uint8_t * bp;
char str[PCB_STR_LEN];
@@ -1808,13 +1887,13 @@ show_non_medium_error_page(const uint8_t * resp, int len,
if (op->filter_given) {
if (pc != op->filter)
goto skip;
- if (op->do_raw) {
- dStrRaw(bp, pl);
- break;
- } else if (op->do_hex) {
- hex2stdout(bp, pl, ((1 == op->do_hex) ? 1 : -1));
- break;
- }
+ }
+ if (op->do_raw) {
+ dStrRaw(bp, pl);
+ break;
+ } else if (op->do_hex) {
+ hex2stdout(bp, pl, op->dstrhex_no_ascii);
+ break;
}
switch (pc) {
case 0:
@@ -1823,12 +1902,26 @@ show_non_medium_error_page(const uint8_t * resp, int len,
default:
if (pc <= 0x7fff)
printf(" Reserved [0x%x]", pc);
- else
- printf(" Vendor specific [0x%x]", pc);
+ else {
+ if (op->exclude_vendor) {
+ skip_out = true;
+ if ((op->verbose > 0) && (0 == op->do_brief) &&
+ (! evsm_output)) {
+ evsm_output = true;
+ printf(" Vendor specific parameter(s) being "
+ "ignored\n");
+ }
+ } else
+ printf(" Vendor specific [0x%x]", pc);
+ }
break;
}
- printf(" = %" PRIu64 "", sg_get_unaligned_be(pl - 4, bp + 4));
- printf("\n");
+ if (skip_out)
+ skip_out = false;
+ else {
+ printf(" = %" PRIu64 "", sg_get_unaligned_be(pl - 4, bp + 4));
+ printf("\n");
+ }
if (op->do_pcb)
printf(" <%s>\n", get_pcb_str(bp[2], str, sizeof(str)));
if (op->filter_given)
@@ -1859,13 +1952,13 @@ show_power_condition_transitions_page(const uint8_t * resp, int len,
if (op->filter_given) {
if (pc != op->filter)
goto skip;
- if (op->do_raw) {
- dStrRaw(bp, pl);
- break;
- } else if (op->do_hex) {
- hex2stdout(bp, pl, ((1 == op->do_hex) ? 1 : -1));
- break;
- }
+ }
+ if (op->do_raw) {
+ dStrRaw(bp, pl);
+ break;
+ } else if (op->do_hex) {
+ hex2stdout(bp, pl, op->dstrhex_no_ascii);
+ break;
}
switch (pc) {
case 1:
@@ -1947,13 +2040,13 @@ show_environmental_reporting_page(const uint8_t * resp, int len,
if (op->filter_given) {
if (pc != op->filter)
goto skip;
- if (op->do_raw) {
- dStrRaw(bp, pl);
- break;
- } else if (op->do_hex) {
- hex2stdout(bp, pl, ((1 == op->do_hex) ? 1 : -1));
- break;
- }
+ }
+ if (op->do_raw) {
+ dStrRaw(bp, pl);
+ break;
+ } else if (op->do_hex) {
+ hex2stdout(bp, pl, op->dstrhex_no_ascii);
+ break;
}
other_valid = !!(bp[4] & 1);
if (pc < 0x100) {
@@ -2038,13 +2131,13 @@ show_environmental_limits_page(const uint8_t * resp, int len,
if (op->filter_given) {
if (pc != op->filter)
goto skip;
- if (op->do_raw) {
- dStrRaw(bp, pl);
- break;
- } else if (op->do_hex) {
- hex2stdout(bp, pl, ((1 == op->do_hex) ? 1 : -1));
- break;
- }
+ }
+ if (op->do_raw) {
+ dStrRaw(bp, pl);
+ break;
+ } else if (op->do_hex) {
+ hex2stdout(bp, pl, op->dstrhex_no_ascii);
+ break;
}
if (pc < 0x100) {
if (pl < 12) {
@@ -2117,13 +2210,13 @@ show_cmd_dur_limits_page(const uint8_t * resp, int len,
if (op->filter_given) {
if (pc != op->filter)
goto skip;
- if (op->do_raw) {
- dStrRaw(bp, pl);
- break;
- } else if (op->do_hex) {
- hex2stdout(bp, pl, ((1 == op->do_hex) ? 1 : -1));
- break;
- }
+ }
+ if (op->do_raw) {
+ dStrRaw(bp, pl);
+ break;
+ } else if (op->do_hex) {
+ hex2stdout(bp, pl, op->dstrhex_no_ascii);
+ break;
}
switch (pc) {
case 0x1:
@@ -2231,13 +2324,13 @@ show_tape_usage_page(const uint8_t * resp, int len, const struct opts_t * op)
if (op->filter_given) {
if (pc != op->filter)
continue;
- if (op->do_raw) {
- dStrRaw(bp, extra);
- break;
- } else if (op->do_hex) {
- hex2stdout(bp, extra, ((1 == op->do_hex) ? 1 : -1));
- break;
- }
+ }
+ if (op->do_raw) {
+ dStrRaw(bp, extra);
+ break;
+ } else if (op->do_hex) {
+ hex2stdout(bp, extra, op->dstrhex_no_ascii);
+ break;
}
ull = n = 0;
switch (bp[3]) {
@@ -2336,13 +2429,13 @@ show_hgst_perf_page(const uint8_t * resp, int len, const struct opts_t * op)
if (op->filter_given) {
if (pc != op->filter)
goto skip;
- if (op->do_raw) {
- dStrRaw(bp, pl);
- break;
- } else if (op->do_hex) {
- hex2stdout(bp, pl, ((1 == op->do_hex) ? 1 : -1));
- break;
- }
+ }
+ if (op->do_raw) {
+ dStrRaw(bp, pl);
+ break;
+ } else if (op->do_hex) {
+ hex2stdout(bp, pl, op->dstrhex_no_ascii);
+ break;
}
switch (pc) {
case 0:
@@ -2413,13 +2506,13 @@ show_tape_capacity_page(const uint8_t * resp, int len,
if (op->filter_given) {
if (pc != op->filter)
continue;
- if (op->do_raw) {
- dStrRaw(bp, extra);
- break;
- } else if (op->do_hex) {
- hex2stdout(bp, extra, ((1 == op->do_hex) ? 1 : -1));
- break;
- }
+ }
+ if (op->do_raw) {
+ dStrRaw(bp, extra);
+ break;
+ } else if (op->do_hex) {
+ hex2stdout(bp, extra, op->dstrhex_no_ascii);
+ break;
}
if (extra != 8)
continue;
@@ -2484,18 +2577,18 @@ show_data_compression_page(const uint8_t * resp, int len,
if (op->filter_given) {
if (pc != op->filter)
continue;
- if (op->do_raw) {
- dStrRaw(bp, extra);
- break;
- } else if (op->do_hex) {
- hex2stdout(bp, extra, ((1 == op->do_hex) ? 1 : -1));
- break;
- }
+ }
+ if (op->do_raw) {
+ dStrRaw(bp, extra);
+ break;
+ } else if (op->do_hex) {
+ hex2stdout(bp, extra, op->dstrhex_no_ascii);
+ break;
}
if ((0 == pl) || (pl > 8)) {
printf("badly formed data compression log parameter\n");
printf(" parameter code = 0x%x, contents in hex:\n", pc);
- hex2stdout(bp, extra, 1);
+ hex2stdout(bp, extra, op->dstrhex_no_ascii);
goto skip_para;
}
/* variable length integer, max length 8 bytes */
@@ -2541,7 +2634,7 @@ show_data_compression_page(const uint8_t * resp, int len,
default:
printf(" unknown parameter code = 0x%x, contents in "
"hex:\n", pc);
- hex2stdout(bp, extra, 1);
+ hex2stdout(bp, extra, op->dstrhex_no_ascii);
break;
}
skip_para:
@@ -2583,24 +2676,24 @@ show_last_n_error_page(const uint8_t * resp, int len,
if (op->filter_given) {
if (pc != op->filter)
continue;
- if (op->do_raw) {
- dStrRaw(bp, pl);
- break;
- } else if (op->do_hex) {
- hex2stdout(bp, pl, ((1 == op->do_hex) ? 1 : -1));
- break;
- }
+ }
+ if (op->do_raw) {
+ dStrRaw(bp, pl);
+ break;
+ } else if (op->do_hex) {
+ hex2stdout(bp, pl, op->dstrhex_no_ascii);
+ break;
}
printf(" Error event %d:\n", pc);
if (pl > 4) {
if ((bp[2] & 0x1) && (bp[2] & 0x2)) {
printf(" [binary]:\n");
- hex2stdout(bp + 4, pl - 4, 1);
- } else if (bp[2] & 0x1)
+ hex2stdout(bp + 4, pl - 4, op->dstrhex_no_ascii);
+ } else if (0x01 == (bp[2] & 0x3) /* ASCII */)
printf(" %.*s\n", pl - 4, (const char *)(bp + 4));
else {
printf(" [data counter?? (LP bit should be set)]:\n");
- hex2stdout(bp + 4, pl - 4, 1);
+ hex2stdout(bp + 4, pl - 4, op->dstrhex_no_ascii);
}
}
if (op->do_pcb)
@@ -2616,7 +2709,7 @@ static bool
show_last_n_deferred_error_page(const uint8_t * resp, int len,
const struct opts_t * op)
{
- int k, num, pl;
+ int k, n, num, pl;
const uint8_t * bp;
char str[PCB_STR_LEN];
@@ -2640,16 +2733,24 @@ show_last_n_deferred_error_page(const uint8_t * resp, int len,
if (op->filter_given) {
if (pc != op->filter)
continue;
- if (op->do_raw) {
- dStrRaw(bp, pl);
- break;
- } else if (op->do_hex) {
- hex2stdout(bp, pl, ((1 == op->do_hex) ? 1 : -1));
- break;
- }
}
- printf(" Deferred error %d:\n", pc);
- hex2stdout(bp + 4, pl - 4, 1);
+ if (op->do_raw) {
+ dStrRaw(bp, pl);
+ break;
+ } else if (op->do_hex) {
+ hex2stdout(bp, pl, op->dstrhex_no_ascii);
+ break;
+ }
+ printf(" Deferred error [0x%x]:\n", pc);
+ if (op->do_brief > 0)
+ hex2stdout(bp + 4, pl - 4, op->dstrhex_no_ascii);
+ else {
+ char b[512];
+
+ n = sg_get_sense_str(" ", bp + 4, pl - 4, false, sizeof(b),
+ b);
+ printf("%.*s\n", n, b);
+ }
if (op->do_pcb)
printf(" <%s>\n", get_pcb_str(bp[2], str, sizeof(str)));
if (op->filter_given)
@@ -2664,6 +2765,7 @@ show_last_n_inq_data_ch_page(const uint8_t * resp, int len,
const struct opts_t * op)
{
int j, num, pl;
+ unsigned int k;
const uint8_t * bp;
char str[PCB_STR_LEN];
@@ -2678,13 +2780,13 @@ show_last_n_inq_data_ch_page(const uint8_t * resp, int len,
if (op->filter_given) {
if (pc != op->filter)
goto skip;
- if (op->do_raw) {
- dStrRaw(bp, pl);
- break;
- } else if (op->do_hex) {
- hex2stdout(bp, pl, ((1 == op->do_hex) ? 1 : -1));
- break;
- }
+ }
+ if (op->do_raw) {
+ dStrRaw(bp, pl);
+ break;
+ } else if (op->do_hex) {
+ hex2stdout(bp, pl, op->dstrhex_no_ascii);
+ break;
}
if (0 == pc) {
if (pl < 8) {
@@ -2692,19 +2794,29 @@ show_last_n_inq_data_ch_page(const uint8_t * resp, int len,
"long, got %d, skip>>\n", pc, pl);
goto skip;
}
- printf(" Generation number of Inquiry data changed indication: "
- "%u\n", sg_get_unaligned_be32(bp + 4));
- if (pl > 11)
- printf(" Generation number of Mode page data changed "
- "indication: %u\n", sg_get_unaligned_be32(bp + 8));
- for (j = 12; j < pl; j +=4)
- printf(" Generation number of indication [0x%x]: %u\n",
- (j / 4), sg_get_unaligned_be32(bp + j));
+ printf(" Change list generation code [pc=0x0]:\n");
+ for (j = 4, k = 1; j < pl; j +=4, ++k)
+ printf(" Changed generation number [0x%x]: %u\n", k,
+ sg_get_unaligned_be32(bp + j));
} else {
printf(" Parameter code 0x%x, ", pc);
- if (1 & *(bp + 4))
- printf("VPD page 0x%x changed\n", *(bp + 5));
- else
+ if (1 & *(bp + 4)) { /* VPD bit set */
+ int vpd = *(bp + 5);
+ printf("VPD page 0x%x changed\n", vpd);
+ if (0 == op->do_brief) {
+ int k;
+ const int num = sg_lib_names_mode_len;
+ struct sg_lib_simple_value_name_t * nvp =
+ sg_lib_names_vpd_arr;
+
+ for (k = 0; k < num; ++k, ++nvp) {
+ if (nvp->value == vpd)
+ break;
+ }
+ if (k < num)
+ printf(" name: %s\n", nvp->name);
+ }
+ } else
printf("Standard Inquiry data changed\n");
}
if (op->do_pcb)
@@ -2723,7 +2835,7 @@ static bool
show_last_n_mode_pg_data_ch_page(const uint8_t * resp, int len,
const struct opts_t * op)
{
- int j, num, pl;
+ int j, num, pl, pg_code, spg_code;
const uint8_t * bp;
char str[PCB_STR_LEN];
@@ -2737,13 +2849,13 @@ show_last_n_mode_pg_data_ch_page(const uint8_t * resp, int len,
if (op->filter_given) {
if (pc != op->filter)
goto skip;
- if (op->do_raw) {
- dStrRaw(bp, pl);
- break;
- } else if (op->do_hex) {
- hex2stdout(bp, pl, ((1 == op->do_hex) ? 1 : -1));
- break;
- }
+ }
+ if (op->do_raw) {
+ dStrRaw(bp, pl);
+ break;
+ } else if (op->do_hex) {
+ hex2stdout(bp, pl, op->dstrhex_no_ascii);
+ break;
}
if (0 == pc) { /* Same as LAST_N_INQUIRY_DATA_CH_SUBPG [0xb,0x1] */
if (pl < 8) {
@@ -2751,21 +2863,32 @@ show_last_n_mode_pg_data_ch_page(const uint8_t * resp, int len,
"long, got %d, skip>>\n", pc, pl);
goto skip;
}
- printf(" Generation number of Inquiry data changed indication: "
- "%u\n", sg_get_unaligned_be32(bp + 4));
- if (pl > 11)
- printf(" Generation number of Mode page data changed "
- "indication: %u\n", sg_get_unaligned_be32(bp + 8));
- for (j = 12; j < pl; j +=4)
- printf(" Generation number of indication [0x%x]: %u\n",
+ printf(" Change list generation code [pc=0x0]:\n");
+ for (j = 4; j < pl; j +=4)
+ printf(" Changed generation number [0x%x]: %u\n",
(j / 4), sg_get_unaligned_be32(bp + j));
} else {
printf(" Parameter code 0x%x, ", pc);
- if (0x40 & *(bp + 5)) /* SPF bit set */
- printf("Mode page 0x%x,0%x changed\n", (0x3f & *(bp + 5)),
- *(bp + 6));
+ pg_code = 0x3f & *(bp + 4);
+ spg_code = (0x40 & *(bp + 4)) ? *(bp + 5) : 0;
+ if (spg_code > 0) /* SPF bit set */
+ printf("mode page 0x%x,0%x changed\n", pg_code, spg_code);
else
- printf("Mode page 0x%x changed\n", (0x3f & *(bp + 5)));
+ printf("mode page 0x%x changed\n", pg_code);
+ if (0 == op->do_brief) {
+ int k;
+ const int num = sg_lib_names_mode_len;
+ int val = (pg_code << 8) | spg_code;
+ struct sg_lib_simple_value_name_t * nmp =
+ sg_lib_names_mode_arr;
+
+ for (k = 0; k < num; ++k, ++nmp) {
+ if (nmp->value == val)
+ break;
+ }
+ if (k < num)
+ printf(" name: %s\n", nmp->name);
+ }
}
if (op->do_pcb)
printf(" <%s>\n", get_pcb_str(bp[2], str, sizeof(str)));
@@ -2822,13 +2945,13 @@ show_self_test_page(const uint8_t * resp, int len, const struct opts_t * op)
if (op->filter_given) {
if (pc != op->filter)
continue;
- if (op->do_raw) {
- dStrRaw(bp, pl);
- break;
- } else if (op->do_hex) {
- hex2stdout(bp, pl, ((1 == op->do_hex) ? 1 : -1));
- break;
- }
+ }
+ if (op->do_raw) {
+ dStrRaw(bp, pl);
+ break;
+ } else if (op->do_hex) {
+ hex2stdout(bp, pl, op->dstrhex_no_ascii);
+ break;
}
n = sg_get_unaligned_be16(bp + 6);
if ((0 == n) && (0 == bp[4]))
@@ -2848,14 +2971,17 @@ show_self_test_page(const uint8_t * resp, int len, const struct opts_t * op)
}
v = bp[16] & 0xf;
if (v) {
- printf(" sense key = 0x%x [%s] , asc = 0x%x, ascq = 0x%x",
- v, sg_get_sense_key_str(v, sizeof(b), b), bp[17],
- bp[18]);
- if (bp[17] || bp[18])
- printf(" [%s]\n", sg_get_asc_ascq_str(bp[17], bp[18],
+ if (op->do_brief)
+ printf(" sense key = 0x%x , asc = 0x%x, ascq = 0x%x\n",
+ v, bp[17], bp[18]);
+ else {
+ printf(" sense key = 0x%x [%s]\n", v,
+ sg_get_sense_key_str(v, sizeof(b), b));
+
+ printf(" asc = 0x%x, ascq = 0x%x [%s]\n",
+ bp[17], bp[18], sg_get_asc_ascq_str(bp[17], bp[18],
sizeof(b), b));
- else
- printf("\n");
+ }
}
if (op->do_pcb)
printf(" <%s>\n", get_pcb_str(bp[2], str, sizeof(str)));
@@ -2865,7 +2991,9 @@ show_self_test_page(const uint8_t * resp, int len, const struct opts_t * op)
return true;
}
-/* TEMPERATURE_LPAGE [0xd] <temp> introduced: SPC-3 */
+/* TEMPERATURE_LPAGE [0xd] <temp> introduced: SPC-3
+ * N.B. The ENV_REPORTING_SUBPG [0xd,0x1] and the ENV_LIMITS_SUBPG [0xd,0x2]
+ * (both added SPC-5) are a superset of this page. */
static bool
show_temperature_page(const uint8_t * resp, int len, const struct opts_t * op)
{
@@ -2895,13 +3023,13 @@ show_temperature_page(const uint8_t * resp, int len, const struct opts_t * op)
if (op->filter_given) {
if (pc != op->filter)
continue;
- if (op->do_raw) {
- dStrRaw(bp, extra);
- break;
- } else if (op->do_hex) {
- hex2stdout(bp, extra, ((1 == op->do_hex) ? 1 : -1));
- break;
- }
+ }
+ if (op->do_raw) {
+ dStrRaw(bp, extra);
+ goto skip;
+ } else if (op->do_hex) {
+ hex2stdout(bp, extra, op->dstrhex_no_ascii);
+ goto skip;
}
switch (pc) {
case 0:
@@ -2926,13 +3054,14 @@ show_temperature_page(const uint8_t * resp, int len, const struct opts_t * op)
if (! op->do_temperature) {
printf(" unknown parameter code = 0x%x, contents in "
"hex:\n", pc);
- hex2stdout(bp, extra, 1);
+ hex2stdout(bp, extra, op->dstrhex_no_ascii);
} else
continue;
break;
}
if (op->do_pcb)
printf(" <%s>\n", get_pcb_str(bp[2], str, sizeof(str)));
+skip:
if (op->filter_given)
break;
}
@@ -2967,13 +3096,13 @@ show_start_stop_page(const uint8_t * resp, int len, const struct opts_t * op)
if (op->filter_given) {
if (pc != op->filter)
continue;
- if (op->do_raw) {
- dStrRaw(bp, extra);
- break;
- } else if (op->do_hex) {
- hex2stdout(bp, extra, ((1 == op->do_hex) ? 1 : -1));
- break;
- }
+ }
+ if (op->do_raw) {
+ dStrRaw(bp, extra);
+ goto skip;
+ } else if (op->do_hex) {
+ hex2stdout(bp, extra, op->dstrhex_no_ascii);
+ goto skip;
}
switch (pc) {
case 1:
@@ -3037,12 +3166,13 @@ show_start_stop_page(const uint8_t * resp, int len, const struct opts_t * op)
default:
printf(" unknown parameter code = 0x%x, contents in "
"hex:\n", pc);
- hex2stdout(bp, extra, 1);
+ hex2stdout(bp, extra, op->dstrhex_no_ascii);
break;
}
printf("\n");
if (op->do_pcb)
printf(" <%s>\n", get_pcb_str(bp[2], str, sizeof(str)));
+skip:
if (op->filter_given)
break;
}
@@ -3067,12 +3197,12 @@ show_app_client_page(const uint8_t * resp, int len, const struct opts_t * op)
printf("Application client page [0xf]\n");
if (0 == op->filter_given) {
if ((len > 128) && (0 == op->do_hex)) {
- hex2stdout(resp, 64, 1);
+ hex2stdout(resp, 64, op->dstrhex_no_ascii);
printf(" ..... [truncated after 64 of %d bytes (use '-H' to "
"see the rest)]\n", len);
}
else
- hex2stdout(resp, len, 1);
+ hex2stdout(resp, len, op->dstrhex_no_ascii);
return true;
}
/* only here if filter_given set */
@@ -3087,14 +3217,13 @@ show_app_client_page(const uint8_t * resp, int len, const struct opts_t * op)
pc = sg_get_unaligned_be16(bp + 0);
if (op->filter != pc)
continue;
- if (op->do_raw)
+ if (op->do_raw) {
dStrRaw(bp, extra);
- else if (0 == op->do_hex)
- hex2stdout(bp, extra, 0);
- else if (1 == op->do_hex)
- hex2stdout(bp, extra, 1);
+ break;
+ } else if (0 == op->do_hex)
+ hex2stdout(bp, extra, op->dstrhex_no_ascii);
else
- hex2stdout(bp, extra, -1);
+ hex2stdout(bp, extra, op->dstrhex_no_ascii);
printf("\n");
if (op->do_pcb)
printf(" <%s>\n", get_pcb_str(bp[2], str, sizeof(str)));
@@ -3108,6 +3237,7 @@ show_app_client_page(const uint8_t * resp, int len, const struct opts_t * op)
static bool
show_ie_page(const uint8_t * resp, int len, const struct opts_t * op)
{
+ bool skip = false;
int k, num, param_len;
const uint8_t * bp;
const char * cp;
@@ -3146,13 +3276,13 @@ show_ie_page(const uint8_t * resp, int len, const struct opts_t * op)
if (op->filter_given) {
if (pc != op->filter)
continue;
- if (op->do_raw) {
- dStrRaw(bp, param_len);
- break;
- } else if (op->do_hex) {
- hex2stdout(bp, param_len, ((1 == op->do_hex) ? 1 : -1));
- break;
- }
+ }
+ if (op->do_raw) {
+ dStrRaw(bp, param_len);
+ goto skip;
+ } else if (op->do_hex) {
+ hex2stdout(bp, param_len, op->dstrhex_no_ascii);
+ goto skip;
}
decoded = true;
cp = NULL;
@@ -3192,6 +3322,11 @@ show_ie_page(const uint8_t * resp, int len, const struct opts_t * op)
}
break;
default:
+ if (op->do_brief > 0) {
+ cp = NULL;
+ skip = true;
+ break;
+ }
if (is_smstr && (param_len >= 24)) {
switch (pc) {
case 0x1:
@@ -3304,13 +3439,17 @@ show_ie_page(const uint8_t * resp, int len, const struct opts_t * op)
decoded = false;
break;
} /* end of switch statement */
- if ((! decoded) && full) {
- hex2str(bp, param_len, " ", 1 /* no ASCII */, sizeof(b), b);
+ if (skip)
+ skip = false;
+ else if ((! decoded) && full) {
+ hex2str(bp, param_len, " ", 0 != op->dstrhex_no_ascii,
+ sizeof(b), b);
printf(" parameter code = 0x%x, contents in hex:\n%s", pc, b);
} else
printf("\n");
if (op->do_pcb)
printf(" <%s>\n", get_pcb_str(bp[2], str, sizeof(str)));
+skip:
if (op->filter_given)
break;
} /* end of for loop */
@@ -3614,15 +3753,19 @@ show_sas_port_param(const uint8_t * bp, int param_len,
ull = sg_get_unaligned_be64(vcp + 16);
printf(" attached SAS address = 0x%" PRIx64 "\n", ull);
printf(" attached phy identifier = %d\n", vcp[24]);
- ui = sg_get_unaligned_be32(vcp + 32);
- printf(" Invalid DWORD count = %u\n", ui);
- ui = sg_get_unaligned_be32(vcp + 36);
- printf(" Running disparity error count = %u\n", ui);
- ui = sg_get_unaligned_be32(vcp + 40);
- printf(" Loss of DWORD synchronization count = %u\n", ui);
- ui = sg_get_unaligned_be32(vcp + 44);
- printf(" Phy reset problem count = %u\n", ui);
+ if (0 == op->do_brief) {
+ ui = sg_get_unaligned_be32(vcp + 32);
+ printf(" Invalid DWORD count = %u\n", ui);
+ ui = sg_get_unaligned_be32(vcp + 36);
+ printf(" Running disparity error count = %u\n", ui);
+ ui = sg_get_unaligned_be32(vcp + 40);
+ printf(" Loss of DWORD synchronization count = %u\n", ui);
+ ui = sg_get_unaligned_be32(vcp + 44);
+ printf(" Phy reset problem count = %u\n", ui);
+ }
}
+ if (op->do_brief > 0)
+ continue;
if (spld_len > 51) {
int num_ped;
const uint8_t * xcp;
@@ -3673,13 +3816,13 @@ show_protocol_specific_page(const uint8_t * resp, int len,
if (op->filter_given) {
if (pc != op->filter)
goto skip;
- if (op->do_raw) {
- dStrRaw(bp, pl);
- break;
- } else if (op->do_hex) {
- hex2stdout(bp, pl, ((1 == op->do_hex) ? 1 : -1));
- break;
- }
+ }
+ if (op->do_raw) {
+ dStrRaw(bp, pl);
+ goto skip;
+ } else if (op->do_hex) {
+ hex2stdout(bp, pl, op->dstrhex_no_ascii);
+ goto skip;
}
pid = 0xf & bp[4];
if (6 != pid) {
@@ -3747,13 +3890,13 @@ show_stats_perform_pages(const uint8_t * resp, int len,
if (op->filter_given) {
if (param_code != op->filter)
continue;
- if (op->do_raw) {
- dStrRaw(bp, extra);
- break;
- } else if (op->do_hex) {
- hex2stdout(bp, extra, ((1 == op->do_hex) ? 1 : -1));
- break;
- }
+ }
+ if (op->do_raw) {
+ dStrRaw(bp, extra);
+ goto skip;
+ } else if (op->do_hex) {
+ hex2stdout(bp, extra, op->dstrhex_no_ascii);
+ goto skip;
}
switch (param_code) {
case 1: /* Statistics and performance log parameter */
@@ -3875,6 +4018,7 @@ show_stats_perform_pages(const uint8_t * resp, int len,
}
if ((op->do_pcb) && (! op->do_name))
printf(" <%s>\n", get_pcb_str(bp[2], str, sizeof(str)));
+skip:
if (op->filter_given)
break;
}
@@ -3890,13 +4034,13 @@ show_stats_perform_pages(const uint8_t * resp, int len,
if (op->filter_given) {
if (param_code != op->filter)
continue;
- if (op->do_raw) {
- dStrRaw(bp, extra);
- break;
- } else if (op->do_hex) {
- hex2stdout(bp, extra, ((1 == op->do_hex) ? 1 : -1));
- break;
- }
+ }
+ if (op->do_raw) {
+ dStrRaw(bp, extra);
+ goto skip2;
+ } else if (op->do_hex) {
+ hex2stdout(bp, extra, op->dstrhex_no_ascii);
+ goto skip2;
}
switch (param_code) {
case 1: /* Group n Statistics and performance log parameter */
@@ -3980,6 +4124,7 @@ show_stats_perform_pages(const uint8_t * resp, int len,
}
if ((op->do_pcb) && (! op->do_name))
printf(" <%s>\n", get_pcb_str(bp[2], str, sizeof(str)));
+skip2:
if (op->filter_given)
break;
}
@@ -4035,13 +4180,13 @@ show_cache_stats_page(const uint8_t * resp, int len, const struct opts_t * op)
if (op->filter_given) {
if (pc != op->filter)
continue;
- if (op->do_raw) {
- dStrRaw(bp, extra);
- break;
- } else if (op->do_hex) {
- hex2stdout(bp, extra, ((1 == op->do_hex) ? 1 : -1));
- break;
- }
+ }
+ if (op->do_raw) {
+ dStrRaw(bp, extra);
+ goto skip;
+ } else if (op->do_hex) {
+ hex2stdout(bp, extra, op->dstrhex_no_ascii);
+ goto skip;
}
switch (pc) {
case 1: /* Read cache memory hits log parameter */
@@ -4115,6 +4260,7 @@ show_cache_stats_page(const uint8_t * resp, int len, const struct opts_t * op)
}
if ((op->do_pcb) && (! op->do_name))
printf(" <%s>\n", get_pcb_str(bp[2], str, sizeof(str)));
+skip:
if (op->filter_given)
break;
}
@@ -4144,13 +4290,13 @@ show_format_status_page(const uint8_t * resp, int len,
if (op->filter_given) {
if (pc != op->filter)
goto skip;
- if (op->do_raw) {
- dStrRaw(bp, pl);
- break;
- } else if (op->do_hex) {
- hex2stdout(bp, pl, ((1 == op->do_hex) ? 1 : -1));
- break;
- }
+ }
+ if (op->do_raw) {
+ dStrRaw(bp, pl);
+ goto filter_chk;
+ } else if (op->do_hex) {
+ hex2stdout(bp, pl, op->dstrhex_no_ascii);
+ goto filter_chk;
}
is_count = true;
switch (pc) {
@@ -4161,7 +4307,7 @@ show_format_status_page(const uint8_t * resp, int len,
if (sg_all_ffs(bp + 4, pl - 4))
printf(" Format data out: <not available>\n");
else {
- hex2str(bp + 4, pl - 4, " ", 1 /* no ASCII */,
+ hex2str(bp + 4, pl - 4, " ", 0 != op->dstrhex_no_ascii,
sizeof(b), b);
printf(" Format data out:\n%s", b);
}
@@ -4183,7 +4329,7 @@ show_format_status_page(const uint8_t * resp, int len,
default:
printf(" Unknown Format parameter code = 0x%x\n", pc);
is_count = false;
- hex2str(bp, pl, " ", 1 /* no ASCII */, sizeof(b), b);
+ hex2str(bp, pl, " ", 0 != op->dstrhex_no_ascii, sizeof(b), b);
printf("%s", b);
break;
}
@@ -4203,6 +4349,7 @@ show_format_status_page(const uint8_t * resp, int len,
}
if (op->do_pcb)
printf(" <%s>\n", get_pcb_str(bp[2], str, sizeof(str)));
+filter_chk:
if (op->filter_given)
break;
skip:
@@ -4231,13 +4378,13 @@ show_non_volatile_cache_page(const uint8_t * resp, int len,
if (op->filter_given) {
if (pc != op->filter)
goto skip;
- if (op->do_raw) {
- dStrRaw(bp, pl);
- break;
- } else if (op->do_hex) {
- hex2stdout(bp, pl, ((1 == op->do_hex) ? 1 : -1));
- break;
- }
+ }
+ if (op->do_raw) {
+ dStrRaw(bp, pl);
+ goto filter_chk;
+ } else if (op->do_hex) {
+ hex2stdout(bp, pl, op->dstrhex_no_ascii);
+ goto filter_chk;
}
switch (pc) {
case 0:
@@ -4284,11 +4431,12 @@ show_non_volatile_cache_page(const uint8_t * resp, int len,
break;
default:
printf(" Unknown parameter code = 0x%x\n", pc);
- hex2stdout(bp, pl, 0);
+ hex2stdout(bp, pl, op->dstrhex_no_ascii);
break;
}
if (op->do_pcb)
printf(" <%s>\n", get_pcb_str(bp[2], str, sizeof(str)));
+filter_chk:
if (op->filter_given)
break;
skip:
@@ -4303,6 +4451,7 @@ static bool
show_lb_provisioning_page(const uint8_t * resp, int len,
const struct opts_t * op)
{
+ bool evsm_output = false;
int num, pl, pc;
const uint8_t * bp;
const char * cp;
@@ -4318,13 +4467,13 @@ show_lb_provisioning_page(const uint8_t * resp, int len,
if (op->filter_given) {
if (pc != op->filter)
goto skip;
- if (op->do_raw) {
- dStrRaw(bp, pl);
- break;
- } else if (op->do_hex) {
- hex2stdout(bp, pl, ((1 == op->do_hex) ? 1 : -1));
- break;
- }
+ }
+ if (op->do_raw) {
+ dStrRaw(bp, pl);
+ goto filter_chk;
+ } else if (op->do_hex) {
+ hex2stdout(bp, pl, op->dstrhex_no_ascii);
+ goto filter_chk;
}
switch (pc) {
case 0x1:
@@ -4374,14 +4523,23 @@ show_lb_provisioning_page(const uint8_t * resp, int len,
printf(" Scope: %s\n", cp);
}
} else if ((pc >= 0xfff0) && (pc <= 0xffff)) {
- printf(" Vendor specific [0x%x]:", pc);
- hex2stdout(bp, ((pl < num) ? pl : num), 0);
+ if (op->exclude_vendor) {
+ if ((op->verbose > 0) && (0 == op->do_brief) &&
+ (! evsm_output)) {
+ evsm_output = true;
+ printf(" Vendor specific parameter(s) being ignored\n");
+ }
+ } else {
+ printf(" Vendor specific [0x%x]:", pc);
+ hex2stdout(bp, ((pl < num) ? pl : num), op->dstrhex_no_ascii);
+ }
} else {
printf(" Reserved [parameter_code=0x%x]:\n", pc);
- hex2stdout(bp, ((pl < num) ? pl : num), 0);
+ hex2stdout(bp, ((pl < num) ? pl : num), op->dstrhex_no_ascii);
}
if (op->do_pcb)
printf(" <%s>\n", get_pcb_str(bp[2], str, sizeof(str)));
+filter_chk:
if (op->filter_given)
break;
skip:
@@ -4409,13 +4567,13 @@ show_utilization_page(const uint8_t * resp, int len, const struct opts_t * op)
if (op->filter_given) {
if (pc != op->filter)
goto skip;
- if (op->do_raw) {
- dStrRaw(bp, pl);
- break;
- } else if (op->do_hex) {
- hex2stdout(bp, pl, ((1 == op->do_hex) ? 1 : -1));
- break;
- }
+ }
+ if (op->do_raw) {
+ dStrRaw(bp, pl);
+ goto filter_chk;
+ } else if (op->do_hex) {
+ hex2stdout(bp, pl, op->dstrhex_no_ascii);
+ goto filter_chk;
}
switch (pc) {
case 0x0:
@@ -4447,11 +4605,12 @@ show_utilization_page(const uint8_t * resp, int len, const struct opts_t * op)
break;
default:
printf(" Reserved [parameter_code=0x%x]:\n", pc);
- hex2stdout(bp, ((pl < num) ? pl : num), 0);
+ hex2stdout(bp, ((pl < num) ? pl : num), op->dstrhex_no_ascii);
break;
}
if (op->do_pcb)
printf(" <%s>\n", get_pcb_str(bp[2], str, sizeof(str)));
+filter_chk:
if (op->filter_given)
break;
skip:
@@ -4480,13 +4639,13 @@ show_solid_state_media_page(const uint8_t * resp, int len,
if (op->filter_given) {
if (pc != op->filter)
goto skip;
- if (op->do_raw) {
- dStrRaw(bp, pl);
- break;
- } else if (op->do_hex) {
- hex2stdout(bp, pl, ((1 == op->do_hex) ? 1 : -1));
- break;
- }
+ }
+ if (op->do_raw) {
+ dStrRaw(bp, pl);
+ goto filter_chk;
+ } else if (op->do_hex) {
+ hex2stdout(bp, pl, op->dstrhex_no_ascii);
+ goto filter_chk;
}
switch (pc) {
case 0x1:
@@ -4504,11 +4663,12 @@ show_solid_state_media_page(const uint8_t * resp, int len,
break;
default:
printf(" Reserved [parameter_code=0x%x]:\n", pc);
- hex2stdout(bp, ((pl < num) ? pl : num), 0);
+ hex2stdout(bp, ((pl < num) ? pl : num), op->dstrhex_no_ascii);
break;
}
if (op->do_pcb)
printf(" <%s>\n", get_pcb_str(bp[2], str, sizeof(str)));
+filter_chk:
if (op->filter_given)
break;
skip:
@@ -4543,6 +4703,7 @@ static bool
show_dt_device_status_page(const uint8_t * resp, int len,
const struct opts_t * op)
{
+ bool evsm_output = false;
int num, pl, pc, j;
const uint8_t * bp;
char str[PCB_STR_LEN];
@@ -4558,13 +4719,13 @@ show_dt_device_status_page(const uint8_t * resp, int len,
if (op->filter_given) {
if (pc != op->filter)
goto skip;
- if (op->do_raw) {
- dStrRaw(bp, pl);
- break;
- } else if (op->do_hex) {
- hex2stdout(bp, pl, ((1 == op->do_hex) ? 1 : -1));
- break;
- }
+ }
+ if (op->do_raw) {
+ dStrRaw(bp, pl);
+ goto filter_chk;
+ } else if (op->do_hex) {
+ hex2stdout(bp, pl, op->dstrhex_no_ascii);
+ goto filter_chk;
}
switch (pc) {
case 0x0:
@@ -4624,7 +4785,8 @@ show_dt_device_status_page(const uint8_t * resp, int len,
pl);
break;
}
- hex2str(bp + 4, 8, " ", 1 /* no ASCII */, sizeof(b), b);
+ hex2str(bp + 4, 8, " ", 0 != op->dstrhex_no_ascii,
+ sizeof(b), b);
printf("%s", b);
break;
case 0x3:
@@ -4638,7 +4800,8 @@ show_dt_device_status_page(const uint8_t * resp, int len,
pl);
break;
}
- hex2str(bp + 4, 12, " ", 1 /* no ASCII */, sizeof(b), b);
+ hex2str(bp + 4, 12, " ", 0 != op->dstrhex_no_ascii,
+ sizeof(b), b);
printf("%s", b);
break;
default:
@@ -4657,24 +4820,34 @@ show_dt_device_status_page(const uint8_t * resp, int len,
} else {
printf(" non-SAS transport, in hex:\n");
hex2str(bp + 4, ((pl < num) ? pl : num) - 4, " ",
- 1 /* no ASCII */, sizeof(b), b);
+ 0 != op->dstrhex_no_ascii, sizeof(b), b);
printf("%s", b);
}
} else if (pc >= 0x8000) {
- printf(" Vendor specific [parameter_code=0x%x]:\n", pc);
- hex2str(bp, ((pl < num) ? pl : num), " ", 1 /* no ASCII */,
- sizeof(b), b);
- printf("%s", b);
+ if (op->exclude_vendor) {
+ if ((op->verbose > 0) && (0 == op->do_brief) &&
+ (! evsm_output)) {
+ evsm_output = true;
+ printf(" Vendor specific parameter(s) being "
+ "ignored\n");
+ }
+ } else {
+ printf(" Vendor specific [parameter_code=0x%x]:\n", pc);
+ hex2str(bp, ((pl < num) ? pl : num), " ",
+ 0 != op->dstrhex_no_ascii, sizeof(b), b);
+ printf("%s", b);
+ }
} else {
printf(" Reserved [parameter_code=0x%x]:\n", pc);
- hex2str(bp, ((pl < num) ? pl : num), " ", 1 /* no ASCII */,
- sizeof(b), b);
+ hex2str(bp, ((pl < num) ? pl : num), " ",
+ 0 != op->dstrhex_no_ascii, sizeof(b), b);
printf("%s", b);
}
break;
}
if (op->do_pcb)
printf(" <%s>\n", get_pcb_str(bp[2], str, sizeof(str)));
+filter_chk:
if (op->filter_given)
break;
skip:
@@ -4689,6 +4862,7 @@ static bool
show_tapealert_response_page(const uint8_t * resp, int len,
const struct opts_t * op)
{
+ bool evsm_output = false;
int num, pl, pc, k, mod, div;
const uint8_t * bp;
char str[PCB_STR_LEN];
@@ -4704,13 +4878,13 @@ show_tapealert_response_page(const uint8_t * resp, int len,
if (op->filter_given) {
if (pc != op->filter)
goto skip;
- if (op->do_raw) {
- dStrRaw(bp, pl);
- break;
- } else if (op->do_hex) {
- hex2stdout(bp, pl, ((1 == op->do_hex) ? 1 : -1));
- break;
- }
+ }
+ if (op->do_raw) {
+ dStrRaw(bp, pl);
+ goto filter_chk;
+ } else if (op->do_hex) {
+ hex2stdout(bp, pl, op->dstrhex_no_ascii);
+ goto filter_chk;
}
switch (pc) {
case 0x0:
@@ -4734,18 +4908,28 @@ show_tapealert_response_page(const uint8_t * resp, int len,
if (pc <= 0x8000) {
printf(" Reserved [parameter_code=0x%x]:\n", pc);
hex2str(bp, ((pl < num) ? pl : num), " ",
- 1 /* no ASCII */, sizeof(b), b);
+ 0 != op->dstrhex_no_ascii, sizeof(b), b);
printf("%s", b);
} else {
- printf(" Vendor specific [parameter_code=0x%x]:\n", pc);
- hex2str(bp, ((pl < num) ? pl : num), " ",
- 1 /* no ASCII */, sizeof(b), b);
- printf("%s", b);
+ if (op->exclude_vendor) {
+ if ((op->verbose > 0) && (0 == op->do_brief) &&
+ (! evsm_output)) {
+ evsm_output = true;
+ printf(" Vendor specific parameter(s) being "
+ "ignored\n");
+ }
+ } else {
+ printf(" Vendor specific [parameter_code=0x%x]:\n", pc);
+ hex2str(bp, ((pl < num) ? pl : num), " ",
+ 0 != op->dstrhex_no_ascii, sizeof(b), b);
+ printf("%s", b);
+ }
}
break;
}
if (op->do_pcb)
printf(" <%s>\n", get_pcb_str(bp[2], str, sizeof(str)));
+filter_chk:
if (op->filter_given)
break;
skip:
@@ -4783,6 +4967,7 @@ static bool
show_requested_recovery_page(const uint8_t * resp, int len,
const struct opts_t * op)
{
+ bool evsm_output = false;
int num, pl, pc, j, k;
const uint8_t * bp;
char str[PCB_STR_LEN];
@@ -4798,13 +4983,13 @@ show_requested_recovery_page(const uint8_t * resp, int len,
if (op->filter_given) {
if (pc != op->filter)
goto skip;
- if (op->do_raw) {
- dStrRaw(bp, pl);
- break;
- } else if (op->do_hex) {
- hex2stdout(bp, pl, ((1 == op->do_hex) ? 1 : -1));
- break;
- }
+ }
+ if (op->do_raw) {
+ dStrRaw(bp, pl);
+ goto filter_chk;
+ } else if (op->do_hex) {
+ hex2stdout(bp, pl, op->dstrhex_no_ascii);
+ goto filter_chk;
}
switch (pc) {
case 0x0:
@@ -4823,18 +5008,28 @@ show_requested_recovery_page(const uint8_t * resp, int len,
if (pc <= 0x8000) {
printf(" Reserved [parameter_code=0x%x]:\n", pc);
hex2str(bp, ((pl < num) ? pl : num), " ",
- 1 /* no ASCII */, sizeof(b), b);
+ 0 != op->dstrhex_no_ascii, sizeof(b), b);
printf("%s", b);
} else {
- printf(" Vendor specific [parameter_code=0x%x]:\n", pc);
- hex2str(bp, ((pl < num) ? pl : num), " ",
- 1 /* no ASCII */, sizeof(b), b);
- printf("%s", b);
+ if (op->exclude_vendor) {
+ if ((op->verbose > 0) && (0 == op->do_brief) &&
+ (! evsm_output)) {
+ evsm_output = true;
+ printf(" Vendor specific parameter(s) being "
+ "ignored\n");
+ }
+ } else {
+ printf(" Vendor specific [parameter_code=0x%x]:\n", pc);
+ hex2str(bp, ((pl < num) ? pl : num), " ",
+ 0 != op->dstrhex_no_ascii, sizeof(b), b);
+ printf("%s", b);
+ }
}
break;
}
if (op->do_pcb)
printf(" <%s>\n", get_pcb_str(bp[2], str, sizeof(str)));
+filter_chk:
if (op->filter_given)
break;
skip:
@@ -4865,13 +5060,13 @@ show_ata_pt_results_page(const uint8_t * resp, int len,
if (op->filter_given) {
if (pc != op->filter)
goto skip;
- if (op->do_raw) {
- dStrRaw(bp, pl);
- break;
- } else if (op->do_hex) {
- hex2stdout(bp, pl, ((1 == op->do_hex) ? 1 : -1));
- break;
- }
+ }
+ if (op->do_raw) {
+ dStrRaw(bp, pl);
+ goto filter_chk;
+ } else if (op->do_hex) {
+ hex2stdout(bp, pl, op->dstrhex_no_ascii);
+ goto filter_chk;
}
if ((pc < 0xf) && (pl > 17)) {
int extend, count;
@@ -4892,17 +5087,18 @@ show_ata_pt_results_page(const uint8_t * resp, int len,
} else if (pl > 17) {
printf(" Reserved [parameter_code=0x%x]:\n", pc);
hex2str(bp, ((pl < num) ? pl : num), " ",
- 1 /* no ASCII */, sizeof(b), b);
+ 0 != op->dstrhex_no_ascii, sizeof(b), b);
printf("%s", b);
} else {
printf(" short parameter length: %d [parameter_code=0x%x]:\n",
pl, pc);
hex2str(bp, ((pl < num) ? pl : num), " ",
- 1 /* no ASCII */, sizeof(b), b);
+ 0 != op->dstrhex_no_ascii, sizeof(b), b);
printf("%s", b);
}
if (op->do_pcb)
printf(" <%s>\n", get_pcb_str(bp[2], str, sizeof(str)));
+filter_chk:
if (op->filter_given)
break;
skip:
@@ -4944,6 +5140,8 @@ static bool
show_background_scan_results_page(const uint8_t * resp, int len,
const struct opts_t * op)
{
+ bool skip_out = false;
+ bool evsm_output = false;
int j, m, num, pl, pc;
const uint8_t * bp;
char str[PCB_STR_LEN];
@@ -4959,13 +5157,13 @@ show_background_scan_results_page(const uint8_t * resp, int len,
if (op->filter_given) {
if (pc != op->filter)
goto skip;
- if (op->do_raw) {
- dStrRaw(bp, pl);
- break;
- } else if (op->do_hex) {
- hex2stdout(bp, pl, ((1 == op->do_hex) ? 1 : -1));
- break;
- }
+ }
+ if (op->do_raw) {
+ dStrRaw(bp, pl);
+ goto filter_chk;
+ } else if (op->do_hex) {
+ hex2stdout(bp, pl, op->dstrhex_no_ascii);
+ goto filter_chk;
}
switch (pc) {
case 0:
@@ -5008,15 +5206,28 @@ show_background_scan_results_page(const uint8_t * resp, int len,
break;
default:
if (pc > 0x800) {
- if ((pc >= 0x8000) && (pc <= 0xafff))
- printf(" Medium scan parameter # %d [0x%x], vendor "
- "specific\n", pc, pc);
- else
+ if ((pc >= 0x8000) && (pc <= 0xafff)) {
+ if (op->exclude_vendor) {
+ skip_out = true;
+ if ((op->verbose > 0) && (0 == op->do_brief) &&
+ (! evsm_output)) {
+ evsm_output = true;
+ printf(" Vendor specific parameter(s) being "
+ "ignored\n");
+ }
+ } else
+ printf(" Medium scan parameter # %d [0x%x], vendor "
+ "specific\n", pc, pc);
+ } else
printf(" Medium scan parameter # %d [0x%x], "
"reserved\n", pc, pc);
- hex2str(bp, ((pl < num) ? pl : num), " ",
- 1 /* no ASCII */, sizeof(b), b);
- printf("%s", b);
+ if (skip_out)
+ skip_out = false;
+ else {
+ hex2str(bp, ((pl < num) ? pl : num), " ",
+ 0 != op->dstrhex_no_ascii, sizeof(b), b);
+ printf("%s", b);
+ }
break;
} else
printf(" Medium scan parameter # %d [0x%x]\n", pc, pc);
@@ -5061,6 +5272,7 @@ show_background_scan_results_page(const uint8_t * resp, int len,
}
if (op->do_pcb)
printf(" <%s>\n", get_pcb_str(bp[2], str, sizeof(str)));
+filter_chk:
if (op->filter_given)
break;
skip:
@@ -5095,13 +5307,13 @@ show_zoned_block_dev_stats(const uint8_t * resp, int len,
if (op->filter_given) {
if (pc != op->filter)
goto skip;
- if (op->do_raw) {
- dStrRaw(bp, pl);
- break;
- } else if (op->do_hex) {
- hex2stdout(bp, pl, ((1 == op->do_hex) ? 1 : -1));
- break;
- }
+ }
+ if (op->do_raw) {
+ dStrRaw(bp, pl);
+ goto filter_chk;
+ } else if (op->do_hex) {
+ hex2stdout(bp, pl, op->dstrhex_no_ascii);
+ goto filter_chk;
}
switch (pc) {
case 0x0:
@@ -5227,7 +5439,7 @@ show_zoned_block_dev_stats(const uint8_t * resp, int len,
default:
printf(" Reserved [parameter_code=0x%x]:\n", pc);
hex2str(bp, ((pl < num) ? pl : num), " ",
- 1 /* no ASCII */, sizeof(b), b);
+ 0 != op->dstrhex_no_ascii, sizeof(b), b);
printf("%s", b);
break;
}
@@ -5238,6 +5450,7 @@ show_zoned_block_dev_stats(const uint8_t * resp, int len,
pr2serr(" parameter length >= 8 expected, got %d\n", pl);
if (op->do_pcb)
printf(" <%s>\n", get_pcb_str(bp[2], str, sizeof(str)));
+filter_chk:
if (op->filter_given)
break;
skip:
@@ -5267,13 +5480,13 @@ show_pending_defects_page(const uint8_t * resp, int len,
if (op->filter_given) {
if (pc != op->filter)
goto skip;
- if (op->do_raw) {
- dStrRaw(bp, pl);
- break;
- } else if (op->do_hex) {
- hex2stdout(bp, pl, ((1 == op->do_hex) ? 1 : -1));
- break;
- }
+ }
+ if (op->do_raw) {
+ dStrRaw(bp, pl);
+ goto filter_chk;
+ } else if (op->do_hex) {
+ hex2stdout(bp, pl, op->dstrhex_no_ascii);
+ goto filter_chk;
}
switch (pc) {
case 0x0:
@@ -5314,6 +5527,7 @@ show_pending_defects_page(const uint8_t * resp, int len,
}
if (op->do_pcb)
printf(" <%s>\n", get_pcb_str(bp[2], str, sizeof(str)));
+filter_chk:
if (op->filter_given)
break;
skip:
@@ -5343,13 +5557,13 @@ show_background_op_page(const uint8_t * resp, int len,
if (op->filter_given) {
if (pc != op->filter)
goto skip;
- if (op->do_raw) {
- dStrRaw(bp, pl);
- break;
- } else if (op->do_hex) {
- hex2stdout(bp, pl, ((1 == op->do_hex) ? 1 : -1));
- break;
- }
+ }
+ if (op->do_raw) {
+ dStrRaw(bp, pl);
+ goto filter_chk;
+ } else if (op->do_hex) {
+ hex2stdout(bp, pl, op->dstrhex_no_ascii);
+ goto filter_chk;
}
switch (pc) {
case 0x0:
@@ -5368,12 +5582,13 @@ show_background_op_page(const uint8_t * resp, int len,
default:
printf(" Reserved [parameter_code=0x%x]:\n", pc);
hex2str(bp, ((pl < num) ? pl : num), " ",
- 1 /* no ASCII */, sizeof(b), b);
+ 0 != op->dstrhex_no_ascii, sizeof(b), b);
printf("%s", b);
break;
}
if (op->do_pcb)
printf(" <%s>\n", get_pcb_str(bp[2], str, sizeof(str)));
+filter_chk:
if (op->filter_given)
break;
skip:
@@ -5404,13 +5619,13 @@ show_lps_misalignment_page(const uint8_t * resp, int len,
if (op->filter_given) {
if (pc != op->filter)
goto skip;
- if (op->do_raw) {
- dStrRaw(bp, pl);
- break;
- } else if (op->do_hex) {
- hex2stdout(bp, pl, ((1 == op->do_hex) ? 1 : -1));
- break;
- }
+ }
+ if (op->do_raw) {
+ dStrRaw(bp, pl);
+ goto filter_chk;
+ } else if (op->do_hex) {
+ hex2stdout(bp, pl, op->dstrhex_no_ascii);
+ goto filter_chk;
}
switch (pc) {
case 0x0:
@@ -5433,13 +5648,14 @@ show_lps_misalignment_page(const uint8_t * resp, int len,
} else {
printf("<unexpected pc=0x%x>\n", pc);
hex2str(bp, ((pl < num) ? pl : num), " ",
- 1 /* no ASCII */, sizeof(b), b);
+ 0 != op->dstrhex_no_ascii, sizeof(b), b);
printf("%s", b);
}
break;
}
if (op->do_pcb)
printf(" <%s>\n", get_pcb_str(bp[2], str, sizeof(str)));
+filter_chk:
if (op->filter_given)
break;
skip:
@@ -5454,6 +5670,7 @@ static bool
show_service_buffer_info_page(const uint8_t * resp, int len,
const struct opts_t * op)
{
+ bool evsm_output = false;
int num, pl, pc;
const uint8_t * bp;
char str[PCB_STR_LEN];
@@ -5469,13 +5686,13 @@ show_service_buffer_info_page(const uint8_t * resp, int len,
if (op->filter_given) {
if (pc != op->filter)
goto skip;
- if (op->do_raw) {
- dStrRaw(bp, pl);
- break;
- } else if (op->do_hex) {
- hex2stdout(bp, pl, ((1 == op->do_hex) ? 1 : -1));
- break;
- }
+ }
+ if (op->do_raw) {
+ dStrRaw(bp, pl);
+ goto filter_chk;
+ } else if (op->do_hex) {
+ hex2stdout(bp, pl, op->dstrhex_no_ascii);
+ goto filter_chk;
}
if (pc < 0x100) {
printf(" Service buffer identifier: 0x%x\n", pc);
@@ -5488,16 +5705,28 @@ show_service_buffer_info_page(const uint8_t * resp, int len,
} else if (pc < 0x8000) {
printf(" parameter_code=0x%x, Reserved, parameter in hex:\n",
pc);
- hex2str(bp + 4, pl - 4, " ", 1 /* no ASCII */, sizeof(b), b);
+ hex2str(bp + 4, pl - 4, " ", 0 != op->dstrhex_no_ascii,
+ sizeof(b), b);
printf("%s", b);
} else {
- printf(" parameter_code=0x%x, Vendor-specific, parameter in "
- "hex:\n", pc);
- hex2str(bp + 4, pl - 4, " ", 1 /* no ASCII */, sizeof(b), b);
- printf("%s", b);
+ if (op->exclude_vendor) {
+ if ((op->verbose > 0) && (0 == op->do_brief) &&
+ (! evsm_output)) {
+ evsm_output = true;
+ printf(" Vendor specific parameter(s) being "
+ "ignored\n");
+ }
+ } else {
+ printf(" parameter_code=0x%x, Vendor-specific, parameter in "
+ "hex:\n", pc);
+ hex2str(bp + 4, pl - 4, " ", 0 != op->dstrhex_no_ascii,
+ sizeof(b), b);
+ printf("%s", b);
+ }
}
if (op->do_pcb)
printf(" <%s>\n", get_pcb_str(bp[2], str, sizeof(str)));
+filter_chk:
if (op->filter_given)
break;
skip:
@@ -5512,6 +5741,7 @@ static bool
show_sequential_access_page(const uint8_t * resp, int len,
const struct opts_t * op)
{
+ bool evsm_output = false;
int num, pl, pc;
const uint8_t * bp;
uint64_t ull, gbytes;
@@ -5528,13 +5758,13 @@ show_sequential_access_page(const uint8_t * resp, int len,
if (op->filter_given) {
if (pc != op->filter)
goto skip;
- if (op->do_raw) {
- dStrRaw(bp, pl);
- break;
- } else if (op->do_hex) {
- hex2stdout(bp, pl, ((1 == op->do_hex) ? 1 : -1));
- break;
- }
+ }
+ if (op->do_raw) {
+ dStrRaw(bp, pl);
+ goto filter_chk;
+ } else if (op->do_hex) {
+ hex2stdout(bp, pl, op->dstrhex_no_ascii);
+ goto filter_chk;
}
ull = sg_get_unaligned_be(pl - 4, bp + 4);
all_set = sg_all_ffs(bp + 4, pl - 4);
@@ -5602,16 +5832,25 @@ show_sequential_access_page(const uint8_t * resp, int len,
printf(" cleaning value: %" PRIu64 "\n", ull);
break;
default:
- if (pc >= 0x8000)
- printf(" Vendor specific parameter [0x%x] value: %" PRIu64
- "\n", pc, ull);
- else
+ if (pc >= 0x8000) {
+ if (op->exclude_vendor) {
+ if ((op->verbose > 0) && (0 == op->do_brief) &&
+ (! evsm_output)) {
+ evsm_output = true;
+ printf(" Vendor specific parameter(s) being "
+ "ignored\n");
+ }
+ } else
+ printf(" Vendor specific parameter [0x%x] value: %"
+ PRIu64 "\n", pc, ull);
+ } else
printf(" Reserved parameter [0x%x] value: %" PRIu64 "\n",
pc, ull);
break;
}
if (op->do_pcb)
printf(" <%s>\n", get_pcb_str(bp[2], str, sizeof(str)));
+filter_chk:
if (op->filter_given)
break;
skip:
@@ -5626,6 +5865,7 @@ static bool
show_device_stats_page(const uint8_t * resp, int len,
const struct opts_t * op)
{
+ bool evsm_output = false;
int num, pl, pc;
const uint8_t * bp;
char str[PCB_STR_LEN];
@@ -5641,13 +5881,13 @@ show_device_stats_page(const uint8_t * resp, int len,
if (op->filter_given) {
if (pc != op->filter)
goto skip;
- if (op->do_raw) {
- dStrRaw(bp, pl);
- break;
- } else if (op->do_hex) {
- hex2stdout(bp, pl, ((1 == op->do_hex) ? 1 : -1));
- break;
- }
+ }
+ if (op->do_raw) {
+ dStrRaw(bp, pl);
+ goto filter_chk;
+ } else if (op->do_hex) {
+ hex2stdout(bp, pl, op->dstrhex_no_ascii);
+ goto filter_chk;
}
if (pc < 0x1000) {
bool vl_num = true;
@@ -5761,7 +6001,7 @@ show_device_stats_page(const uint8_t * resp, int len,
default:
vl_num = false;
printf(" Reserved parameter code [0x%x] data in hex:\n", pc);
- hex2str(bp + 4, pl - 4, " ", 1 /* no ASCII */,
+ hex2str(bp + 4, pl - 4, " ", 0 != op->dstrhex_no_ascii,
sizeof(b), b);
printf("%s", b);
break;
@@ -5781,19 +6021,29 @@ show_device_stats_page(const uint8_t * resp, int len,
sg_get_unaligned_be32(p + 4));
break;
default:
- if (pc >= 0x8000)
- printf(" Vendor specific parameter [0x%x], dump in "
- "hex:\n", pc);
- else
+ if (pc >= 0x8000) {
+ if (op->exclude_vendor) {
+ if ((op->verbose > 0) && (0 == op->do_brief) &&
+ (! evsm_output)) {
+ evsm_output = true;
+ printf(" Vendor specific parameter(s) being "
+ "ignored\n");
+ }
+ } else
+ printf(" Vendor specific parameter [0x%x], dump in "
+ "hex:\n", pc);
+ } else {
printf(" Reserved parameter [0x%x], dump in hex:\n", pc);
- hex2str(bp + 4, pl - 4, " ", 1 /* no ASCII */,
- sizeof(b), b);
- printf("%s", b);
+ hex2str(bp + 4, pl - 4, " ", 0 != op->dstrhex_no_ascii,
+ sizeof(b), b);
+ printf("%s", b);
+ }
break;
}
}
if (op->do_pcb)
printf(" <%s>\n", get_pcb_str(bp[2], str, sizeof(str)));
+filter_chk:
if (op->filter_given)
break;
skip:
@@ -5822,13 +6072,13 @@ show_media_stats_page(const uint8_t * resp, int len, const struct opts_t * op)
if (op->filter_given) {
if (pc != op->filter)
goto skip;
- if (op->do_raw) {
- dStrRaw(bp, pl);
- break;
- } else if (op->do_hex) {
- hex2stdout(bp, pl, ((1 == op->do_hex) ? 1 : -1));
- break;
- }
+ }
+ if (op->do_raw) {
+ dStrRaw(bp, pl);
+ goto filter_chk;
+ } else if (op->do_hex) {
+ hex2stdout(bp, pl, op->dstrhex_no_ascii);
+ goto filter_chk;
}
ull = sg_get_unaligned_be(pl - 4, bp + 4);
switch (pc) {
@@ -5929,6 +6179,7 @@ show_media_stats_page(const uint8_t * resp, int len, const struct opts_t * op)
}
if (op->do_pcb)
printf(" <%s>\n", get_pcb_str(bp[2], str, sizeof(str)));
+filter_chk:
if (op->filter_given)
break;
skip:
@@ -5958,13 +6209,13 @@ show_element_stats_page(const uint8_t * resp, int len,
if (op->filter_given) {
if (pc != op->filter)
goto skip;
- if (op->do_raw) {
- dStrRaw(bp, pl);
- break;
- } else if (op->do_hex) {
- hex2stdout(bp, pl, ((1 == op->do_hex) ? 1 : -1));
- break;
- }
+ }
+ if (op->do_raw) {
+ dStrRaw(bp, pl);
+ goto filter_chk;
+ } else if (op->do_hex) {
+ hex2stdout(bp, pl, op->dstrhex_no_ascii);
+ goto filter_chk;
}
printf(" Element address: %d\n", pc);
v = sg_get_unaligned_be32(bp + 4);
@@ -5981,6 +6232,7 @@ show_element_stats_page(const uint8_t * resp, int len,
printf(" Number of unreadable volume identifiers: %u\n", v);
if (op->do_pcb)
printf(" <%s>\n", get_pcb_str(bp[2], str, sizeof(str)));
+filter_chk:
if (op->filter_given)
break;
skip:
@@ -6011,13 +6263,13 @@ show_tape_diag_data_page(const uint8_t * resp, int len,
if (op->filter_given) {
if (pc != op->filter)
goto skip;
- if (op->do_raw) {
- dStrRaw(bp, pl);
- break;
- } else if (op->do_hex) {
- hex2stdout(bp, pl, ((1 == op->do_hex) ? 1 : -1));
- break;
- }
+ }
+ if (op->do_raw) {
+ dStrRaw(bp, pl);
+ goto filter_chk;
+ } else if (op->do_hex) {
+ hex2stdout(bp, pl, op->dstrhex_no_ascii);
+ goto filter_chk;
}
printf(" Parameter code: %d\n", pc);
printf(" Density code: 0x%x\n", bp[6]);
@@ -6054,12 +6306,13 @@ show_tape_diag_data_page(const uint8_t * resp, int len,
if (sg_all_zeros(bp + 66, 6))
printf(" Timestamp is all zeros:\n");
else {
- hex2str(bp + 66, 6, NULL, 1 /* no ASCII */, sizeof(b), b);
+ hex2str(bp + 66, 6, NULL, 0 != op->dstrhex_no_ascii,
+ sizeof(b), b);
printf(" Timestamp: %s", b);
}
if (pl > 72) {
n = pl - 72;
- k = hex2str(bp + 72, n, " ", 0 /* with ASCII */,
+ k = hex2str(bp + 72, n, " ", 0 != op->dstrhex_no_ascii,
sizeof(b), b);
printf(" Vendor specific:\n");
printf("%s", b);
@@ -6068,6 +6321,7 @@ show_tape_diag_data_page(const uint8_t * resp, int len,
}
if (op->do_pcb)
printf(" <%s>\n", get_pcb_str(bp[2], str, sizeof(str)));
+filter_chk:
if (op->filter_given)
break;
skip:
@@ -6098,13 +6352,13 @@ show_mchanger_diag_data_page(const uint8_t * resp, int len,
if (op->filter_given) {
if (pc != op->filter)
goto skip;
- if (op->do_raw) {
- dStrRaw(bp, pl);
- break;
- } else if (op->do_hex) {
- hex2stdout(bp, pl, ((1 == op->do_hex) ? 1 : -1));
- break;
- }
+ }
+ if (op->do_raw) {
+ dStrRaw(bp, pl);
+ goto filter_chk;
+ } else if (op->do_hex) {
+ hex2stdout(bp, pl, op->dstrhex_no_ascii);
+ goto filter_chk;
}
printf(" Parameter code: %d\n", pc);
printf(" Repeat: %d\n", !!(bp[5] & 0x80));
@@ -6151,19 +6405,20 @@ show_mchanger_diag_data_page(const uint8_t * resp, int len,
printf(" Destination address: 0x%x\n", v);
if (pl > 91) {
printf(" Volume tag information:\n");
- hex2str(bp + 56, 36, " ", 1 /* no ASCII */,
+ hex2str(bp + 56, 36, " ", 0 != op->dstrhex_no_ascii,
sizeof(b), b);
printf("%s", b);
}
if (pl > 99) {
printf(" Timestamp origin: 0x%x\n", bp[92] & 0xf);
printf(" Timestamp:\n");
- hex2str(bp + 94, 6, " ", 1 /* no ASCII */,
+ hex2str(bp + 94, 6, " ", 0 != op->dstrhex_no_ascii,
sizeof(b), b);
printf("%s", b);
}
if (op->do_pcb)
printf(" <%s>\n", get_pcb_str(bp[2], str, sizeof(str)));
+filter_chk:
if (op->filter_given)
break;
skip:
@@ -6249,6 +6504,8 @@ static bool
show_volume_stats_pages(const uint8_t * resp, int len,
const struct opts_t * op)
{
+ bool skip_out = false;
+ bool evsm_output = false;
int num, pl, pc, subpg_code;
bool spf;
const uint8_t * bp;
@@ -6275,13 +6532,13 @@ show_volume_stats_pages(const uint8_t * resp, int len,
if (op->filter_given) {
if (pc != op->filter)
goto skip;
- if (op->do_raw) {
- dStrRaw(bp, pl);
- break;
- } else if (op->do_hex) {
- hex2stdout(bp, pl, ((1 == op->do_hex) ? 1 : -1));
- break;
- }
+ }
+ if (op->do_raw) {
+ dStrRaw(bp, pl);
+ goto filter_chk;
+ } else if (op->do_hex) {
+ hex2stdout(bp, pl, op->dstrhex_no_ascii);
+ goto filter_chk;
}
switch (pc) {
@@ -6459,18 +6716,33 @@ show_volume_stats_pages(const uint8_t * resp, int len,
break;
default:
- if (pc >= 0xf000)
- printf(" Vendor specific parameter code (0x%x), payload "
- "in hex\n", pc);
- else
+ if (pc >= 0xf000) {
+ if (op->exclude_vendor) {
+ skip_out = true;
+ if ((op->verbose > 0) && (0 == op->do_brief) &&
+ (! evsm_output)) {
+ evsm_output = true;
+ printf(" Vendor specific parameter(s) being "
+ "ignored\n");
+ }
+ } else
+ printf(" Vendor specific parameter code (0x%x), payload "
+ "in hex\n", pc);
+ } else
printf(" Reserved parameter code (0x%x), payload in hex\n",
pc);
- hex2str(bp + 4, pl - 4, " ", 1 /* no ASCII */, sizeof(b), b);
- printf("%s", b);
+ if (skip_out)
+ skip_out = false;
+ else {
+ hex2str(bp + 4, pl - 4, " ", 0 != op->dstrhex_no_ascii,
+ sizeof(b), b);
+ printf("%s", b);
+ }
break;
}
if (op->do_pcb)
printf(" <%s>\n", get_pcb_str(bp[2], str, sizeof(str)));
+filter_chk:
if (op->filter_given)
break;
skip:
@@ -6564,13 +6836,13 @@ show_tape_alert_ssc_page(const uint8_t * resp, int len,
if (op->filter_given) {
if (pc != op->filter)
goto skip;
- if (op->do_raw) {
- dStrRaw(bp, pl);
- break;
- } else if (op->do_hex) {
- hex2stdout(bp, pl, ((1 == op->do_hex) ? 1 : -1));
- break;
- }
+ }
+ if (op->do_raw) {
+ dStrRaw(bp, pl);
+ goto filter_chk;
+ } else if (op->do_hex) {
+ hex2stdout(bp, pl, op->dstrhex_no_ascii);
+ goto filter_chk;
}
flag = bp[4] & 1;
if (op->verbose && (0 == op->do_brief) && flag)
@@ -6584,6 +6856,7 @@ show_tape_alert_ssc_page(const uint8_t * resp, int len,
}
if (op->do_pcb)
printf(" <%s>\n", get_pcb_str(bp[2], str, sizeof(str)));
+filter_chk:
if (op->filter_given)
break;
skip:
@@ -6598,7 +6871,9 @@ static bool
show_seagate_cache_page(const uint8_t * resp, int len,
const struct opts_t * op)
{
+ bool skip = false;
int num, pl, pc;
+ int bsti = 0;
const uint8_t * bp;
char str[PCB_STR_LEN];
@@ -6607,6 +6882,8 @@ show_seagate_cache_page(const uint8_t * resp, int len,
printf("Suspicious page 0x37, SPF=0 but subpage=0x%x\n", resp[1]);
if (op->verbose)
printf("... try vendor=wdc\n");
+ if (op->do_brief > 0)
+ return true;
} else
printf("Seagate cache page [0x37]\n");
}
@@ -6618,16 +6895,22 @@ show_seagate_cache_page(const uint8_t * resp, int len,
if (op->filter_given) {
if (pc != op->filter)
goto skip;
- if (op->do_raw) {
- dStrRaw(bp, pl);
- break;
- } else if (op->do_hex) {
- hex2stdout(bp, pl, ((1 == op->do_hex) ? 1 : -1));
- break;
- }
+ }
+ if (op->do_raw) {
+ dStrRaw(bp, pl);
+ goto filter_chk;
+ } else if (op->do_hex) {
+ hex2stdout(bp, pl, op->dstrhex_no_ascii);
+ goto filter_chk;
}
switch (pc) {
- case 0: printf(" Blocks sent to initiator"); break;
+ case 0:
+ ++bsti;
+ if (bsti < 2)
+ printf(" Blocks sent to initiator");
+ else
+ skip = true;
+ break;
case 1: printf(" Blocks received from initiator"); break;
case 2:
printf(" Blocks read from cache and sent to initiator");
@@ -6641,10 +6924,16 @@ show_seagate_cache_page(const uint8_t * resp, int len,
"> segment size"); break;
default: printf(" Unknown Seagate parameter code = 0x%x", pc); break;
}
- printf(" = %" PRIu64 "", sg_get_unaligned_be(pl - 4, bp + 4));
- printf("\n");
- if (op->do_pcb)
- printf(" <%s>\n", get_pcb_str(bp[2], str, sizeof(str)));
+ if (skip)
+ skip = false;
+ else {
+ printf(" = %" PRIu64 "", sg_get_unaligned_be(pl - 4, bp + 4));
+ printf("\n");
+ if (op->do_pcb)
+ printf(" <%s>\n", get_pcb_str(bp[2], str,
+ sizeof(str)));
+ }
+filter_chk:
if (op->filter_given)
break;
skip:
@@ -6678,13 +6967,13 @@ show_hgst_misc_page(const uint8_t * resp, int len, const struct opts_t * op)
if (op->filter_given) {
if (pc != op->filter)
goto skip;
- if (op->do_raw) {
- dStrRaw(bp, pl);
- break;
- } else if (op->do_hex) {
- hex2stdout(bp, pl, ((1 == op->do_hex) ? 1 : -1));
- break;
- }
+ }
+ if (op->do_raw) {
+ dStrRaw(bp, pl);
+ goto filter_chk;
+ } else if (op->do_hex) {
+ hex2stdout(bp, pl, op->dstrhex_no_ascii);
+ goto filter_chk;
}
switch (pc) {
case 0:
@@ -6713,6 +7002,7 @@ show_hgst_misc_page(const uint8_t * resp, int len, const struct opts_t * op)
}
if (op->do_pcb)
printf(" <%s>\n", get_pcb_str(bp[2], str, sizeof(str)));
+filter_chk:
if (op->filter_given)
break;
skip:
@@ -6743,13 +7033,13 @@ show_seagate_factory_page(const uint8_t * resp, int len,
if (op->filter_given) {
if (pc != op->filter)
goto skip;
- if (op->do_raw) {
- dStrRaw(bp, pl);
- break;
- } else if (op->do_hex) {
- hex2stdout(bp, pl, ((1 == op->do_hex) ? 1 : -1));
- break;
- }
+ }
+ if (op->do_raw) {
+ dStrRaw(bp, pl);
+ goto filter_chk;
+ } else if (op->do_hex) {
+ hex2stdout(bp, pl, op->dstrhex_no_ascii);
+ goto filter_chk;
}
valid = true;
switch (pc) {
@@ -6771,6 +7061,7 @@ show_seagate_factory_page(const uint8_t * resp, int len,
printf("\n");
if (op->do_pcb)
printf(" <%s>\n", get_pcb_str(bp[2], str, sizeof(str)));
+filter_chk:
if (op->filter_given)
break;
skip:
@@ -6807,28 +7098,40 @@ decode_page_contents(const uint8_t * resp, int len, struct opts_t * op)
}
vpn = (op->vend_prod_num >= 0) ? op->vend_prod_num : op->deduced_vpn;
lep = pg_subpg_pdt_search(pg_code, subpg_code, op->dev_pdt, vpn);
+
+ /* Below is the indirect function call to all the show_* functions */
if (lep && lep->show_pagep)
done = (*lep->show_pagep)(resp, len, op);
if (! done) {
- if (subpg_code > 0)
- printf("Unable to decode page = 0x%x, subpage = 0x%x, here is "
- "hex:\n", pg_code, subpg_code);
- else
- printf("Unable to decode page = 0x%x, here is hex:\n", pg_code);
- if (len > 128) {
- hex2str(resp, 64, " ", 1 /* no ASCII */, sizeof(b), b);
+ if (0 == op->do_hex) {
+ static const char * unable_s = "Unable to decode page = 0x";
+
+ if (subpg_code > 0)
+ printf("%s%x, subpage = 0x%x, here is hex:\n", unable_s,
+ pg_code, subpg_code);
+ else
+ printf("%s%x, here is hex:\n", unable_s, pg_code);
+ }
+ if ((len > 128) && (0 == op->do_hex)) {
+ hex2str(resp, 64, " ", 0 != op->dstrhex_no_ascii,
+ sizeof(b), b);
printf("%s", b);
printf(" ..... [truncated after 64 of %d bytes (use '-H' to "
"see the rest)]\n", len);
- }
- else {
- hex2str(resp, len, " ", 1 /* no ASCII */, sizeof(b), b);
- printf("%s", b);
+ } else {
+ if (0 == op->do_hex) {
+ hex2str(resp, len, " ", 0 != op->dstrhex_no_ascii,
+ sizeof(b), b);
+ printf("%s", b);
+ } else
+ hex2stdout(resp, len, op->dstrhex_no_ascii);
}
}
}
+/* Tries to fetch the TEMPERATURE_LPAGE [0xd] page first. If that fails
+ * tries to get the Informational Exceptions (IE_LPAGE) page. */
static int
fetchTemperature(int sg_fd, uint8_t * resp, int max_len, struct opts_t * op)
{
@@ -6843,7 +7146,7 @@ fetchTemperature(int sg_fd, uint8_t * resp, int max_len, struct opts_t * op)
if (op->do_raw)
dStrRaw(resp, len);
else if (op->do_hex)
- hex2stdout(resp, len, (1 == op->do_hex));
+ hex2stdout(resp, len, op->dstrhex_no_ascii);
else
show_temperature_page(resp, len, op);
} else if (SG_LIB_CAT_NOT_READY == res)
@@ -6856,7 +7159,7 @@ fetchTemperature(int sg_fd, uint8_t * resp, int max_len, struct opts_t * op)
if (op->do_raw)
dStrRaw(resp, len);
else if (op->do_hex)
- hex2stdout(resp, len, (1 == op->do_hex));
+ hex2stdout(resp, len, op->dstrhex_no_ascii);
else
show_ie_page(resp, len, op);
} else
@@ -6996,11 +7299,10 @@ main(int argc, char * argv[])
uint8_t * free_parr = NULL;
struct opts_t * op;
struct sg_simple_inquiry_resp inq_out;
- struct opts_t opts;
+ struct opts_t opts = {0};
uint8_t supp_pgs_rsp[256];
op = &opts;
- memset(op, 0, sizeof(opts));
/* N.B. some disks only give data for current cumulative */
op->page_control = 1;
op->dev_pdt = -1;
@@ -7033,9 +7335,25 @@ main(int argc, char * argv[])
pr2serr("Version string: %s\n", version_str);
return 0;
}
+ if (op->do_hex > 0) {
+ if (op->do_hex > 2)
+ op->dstrhex_no_ascii = -1;
+ else
+ op->dstrhex_no_ascii = (1 == op->do_hex);
+ } else {
+ if (op->undefined_hex > 0) {
+ if (op->undefined_hex > 2)
+ op->dstrhex_no_ascii = -1;
+ else
+ op->dstrhex_no_ascii = (1 == op->undefined_hex);
+ } else /* default when no --hex nor --undefined */
+ op->dstrhex_no_ascii = -1;
+ }
vb = op->verbose;
if (op->vend_prod) {
- if (isdigit((uint8_t)op->vend_prod[0]))
+ if (0 == memcmp("-1", op->vend_prod,3))
+ k = VP_NONE;
+ else if (isdigit((uint8_t)op->vend_prod[0]))
k = sg_get_num_nomult(op->vend_prod);
else
k = find_vpn_by_acron(op->vend_prod);
@@ -7056,6 +7374,26 @@ main(int argc, char * argv[])
enumerate_pages(op);
return 0;
}
+ if (op->in_fn) {
+ if (op->maxlen_given) {
+ if (op->maxlen > MX_INLEN_ALLOC_LEN) {
+ pr2serr("bad argument to '--maxlen=' when --in= given, from "
+ "2 to %d (inclusive) expected\n", MX_INLEN_ALLOC_LEN);
+ return SG_LIB_SYNTAX_ERROR;
+ }
+ rsp_buff_sz = op->maxlen;
+ } else
+ rsp_buff_sz = DEF_INLEN_ALLOC_LEN;
+ } else {
+ if (op->maxlen_given) {
+ if (op->maxlen > MX_ALLOC_LEN) {
+ pr2serr("bad argument to '--maxlen=', from 2 to 65535 "
+ "(inclusive) expected\n");
+ return SG_LIB_SYNTAX_ERROR;
+ }
+ rsp_buff_sz = op->maxlen;
+ }
+ }
rsp_buff = sg_memalign(rsp_buff_sz, 0 /* page aligned */, &free_rsp_buff,
false);
if (NULL == rsp_buff) {
@@ -7098,10 +7436,14 @@ main(int argc, char * argv[])
n);
n = in_len - k;
}
+ if (op->exclude_vendor && (pg_code >= 0x30))
+ continue;
pdt = op->dev_pdt;
lep = pg_subpg_pdt_search(pg_code, subpg_code, pdt,
op->vend_prod_num);
if (lep) {
+ /* Below is the indirect function call to all the
+ * show_* functions */
if (lep->show_pagep)
(*lep->show_pagep)(bp, n, op);
else
@@ -7154,11 +7496,6 @@ main(int argc, char * argv[])
ret = SG_LIB_CONTRADICT;
goto err_out;
}
- if (op->filter) {
- pr2serr("--all conflicts with --filter\n");
- ret = SG_LIB_CONTRADICT;
- goto err_out;
- }
}
if (op->in_fn) {
if (! op->do_select) {
@@ -7294,9 +7631,9 @@ main(int argc, char * argv[])
}
bad:
if (SG_LIB_CAT_INVALID_OP == res)
- pr2serr("log_sense: not supported\n");
+ pr2serr("%snot supported\n", ls_s);
else if (SG_LIB_CAT_NOT_READY == res)
- pr2serr("log_sense: device not ready\n");
+ pr2serr("%sdevice not ready\n", ls_s);
else if (SG_LIB_CAT_ILLEGAL_REQ == res) {
if ((op->do_list > 2) && (SUPP_SPGS_SUBPG == op->subpg_code)) {
rsp_buff[0] = 0x40;
@@ -7304,19 +7641,19 @@ bad:
pg_len = 0;
res = 0;
if (op->verbose)
- pr2serr("log_sense: field in cdb illegal in [0,0xff], "
- "continue with merge\n");
+ pr2serr("%sfield in cdb illegal in [0,0xff], "
+ "continue with merge\n", ls_s);
goto good;
} else
- pr2serr("log_sense: field in cdb illegal\n");
+ pr2serr("%sfield in cdb illegal\n", ls_s);
} else if (SG_LIB_CAT_UNIT_ATTENTION == res)
- pr2serr("log_sense: unit attention\n");
+ pr2serr("%sunit attention\n", ls_s);
else if (SG_LIB_CAT_ABORTED_COMMAND == res)
- pr2serr("log_sense: aborted command\n");
+ pr2serr("%saborted command\n", ls_s);
else if (SG_LIB_TRANSPORT_ERROR == res)
- pr2serr("log_sense: transport error\n");
+ pr2serr("%stransport error\n", ls_s);
else
- pr2serr("log_sense: other error [%d]\n", res);
+ pr2serr("%sother error [%d]\n", ls_s, res);
ret = res;
goto err_out;
@@ -7327,13 +7664,13 @@ good:
if (0 == op->do_all) {
if (op->filter_given) {
if (op->do_hex > 2)
- hex2stdout(rsp_buff, pg_len + 4, (op->do_hex < 4));
+ hex2stdout(rsp_buff, pg_len + 4, op->dstrhex_no_ascii);
else
decode_page_contents(rsp_buff, pg_len + 4, op);
} else if (op->do_raw)
dStrRaw(rsp_buff, pg_len + 4);
else if (op->do_hex > 1)
- hex2stdout(rsp_buff, pg_len + 4, (2 == op->do_hex) ? 0 : -1);
+ hex2stdout(rsp_buff, pg_len + 4, op->dstrhex_no_ascii);
else if (pg_len > 1) {
if (op->do_hex) {
if (rsp_buff[0] & 0x40)
@@ -7343,7 +7680,7 @@ good:
else
printf("Log page code=0x%x, DS=%d, SPF=0, page_len=0x%x\n",
rsp_buff[0] & 0x3f, !!(rsp_buff[0] & 0x80), pg_len);
- hex2stdout(rsp_buff, pg_len + 4, 1);
+ hex2stdout(rsp_buff, pg_len + 4, op->dstrhex_no_ascii);
}
else
decode_page_contents(rsp_buff, pg_len + 4, op);
@@ -7378,6 +7715,8 @@ good:
/* Some devices include [pg_code, 0xff] for all pg_code > 0 */
if ((op->pg_code > 0) && (SUPP_SPGS_SUBPG == op->subpg_code))
continue; /* skip since no new information */
+ if ((op->pg_code >= 0x30) && op->exclude_vendor)
+ continue;
if (! op->do_raw)
printf("\n");
res = do_logs(sg_fd, rsp_buff, resp_len, op);
@@ -7388,38 +7727,42 @@ good:
"output\n", resp_len);
pg_len = resp_len - 4;
}
- if (op->do_raw)
+ if (op->do_raw && (! op->filter_given))
dStrRaw(rsp_buff, pg_len + 4);
+ else if (op->do_hex > 4)
+ decode_page_contents(rsp_buff, pg_len + 4, op);
else if (op->do_hex > 1)
- hex2stdout(rsp_buff, pg_len + 4,
- (2 == op->do_hex) ? 0 : -1);
- else if (op->do_hex) {
- if (rsp_buff[0] & 0x40)
- printf("Log page code=0x%x,0x%x, DS=%d, SPF=1, page_"
- "len=0x%x\n", rsp_buff[0] & 0x3f, rsp_buff[1],
- !!(rsp_buff[0] & 0x80), pg_len);
- else
- printf("Log page code=0x%x, DS=%d, SPF=0, page_len="
- "0x%x\n", rsp_buff[0] & 0x3f,
- !!(rsp_buff[0] & 0x80), pg_len);
- hex2stdout(rsp_buff, pg_len + 4, 1);
+ hex2stdout(rsp_buff, pg_len + 4, op->dstrhex_no_ascii);
+ else if (1 == op->do_hex) {
+ if (0 == op->do_brief) {
+ if (rsp_buff[0] & 0x40)
+ printf("Log page code=0x%x,0x%x, DS=%d, SPF=1, "
+ "page_len=0x%x\n", rsp_buff[0] & 0x3f,
+ rsp_buff[1], !!(rsp_buff[0] & 0x80),
+ pg_len);
+ else
+ printf("Log page code=0x%x, DS=%d, SPF=0, "
+ "page_len=0x%x\n", rsp_buff[0] & 0x3f,
+ !!(rsp_buff[0] & 0x80), pg_len);
+ }
+ hex2stdout(rsp_buff, pg_len + 4, op->dstrhex_no_ascii);
}
else
decode_page_contents(rsp_buff, pg_len + 4, op);
} else if (SG_LIB_CAT_INVALID_OP == res)
- pr2serr("log_sense: page=0x%x,0x%x not supported\n",
+ pr2serr("%spage=0x%x,0x%x not supported\n", ls_s,
op->pg_code, op->subpg_code);
else if (SG_LIB_CAT_NOT_READY == res)
- pr2serr("log_sense: device not ready\n");
+ pr2serr("%sdevice not ready\n", ls_s);
else if (SG_LIB_CAT_ILLEGAL_REQ == res)
- pr2serr("log_sense: field in cdb illegal "
- "[page=0x%x,0x%x]\n", op->pg_code, op->subpg_code);
+ pr2serr("%sfield in cdb illegal [page=0x%x,0x%x]\n", ls_s,
+ op->pg_code, op->subpg_code);
else if (SG_LIB_CAT_UNIT_ATTENTION == res)
- pr2serr("log_sense: unit attention\n");
+ pr2serr("%sunit attention\n", ls_s);
else if (SG_LIB_CAT_ABORTED_COMMAND == res)
- pr2serr("log_sense: aborted command\n");
+ pr2serr("%saborted command\n", ls_s);
else
- pr2serr("log_sense: failed, try '-v' for more information\n");
+ pr2serr("%sfailed, try '-v' for more information\n", ls_s);
}
}
err_out:
diff --git a/src/sg_modes.c b/src/sg_modes.c
index 2eead452..0be40ee4 100644
--- a/src/sg_modes.c
+++ b/src/sg_modes.c
@@ -236,13 +236,14 @@ static struct page_code_desc pc_desc_t_spi4[] = {
{0x0, 0x0, NULL, NULL},
};
+/* SAS protocol layers now in SPL standards */
static struct page_code_desc pc_desc_t_sas[] = {
- {0x18, 0x0, "pslu", "Protocol specific logical unit (SAS)"},
- {0x19, 0x0, "pspo", "Protocol specific port (SAS)"},
- {0x19, 0x1, "pcd", "Phy control and discover (SAS)"},
- {0x19, 0x2, "spc", "Shared port control (SAS)"},
- {0x19, 0x3, "sep", "Enhanced phy control (SAS)"},
- {0x19, 0x4, "oobm", "Out of band management control (SAS)"}, /* spl5r01 */
+ {0x18, 0x0, "pslu", "Protocol specific logical unit (SPL)"},
+ {0x19, 0x0, "pspo", "Protocol specific port (SPL)"},
+ {0x19, 0x1, "pcd", "Phy control and discover (SPL)"},
+ {0x19, 0x2, "spc", "Shared port control (SPL)"},
+ {0x19, 0x3, "sep", "Enhanced phy control (SPL)"},
+ {0x19, 0x4, "oobm", "Out of band management control (SPL)"}, /* spl5r01 */
{0x0, 0x0, NULL, NULL},
};
diff --git a/src/sg_reset.c b/src/sg_reset.c
index d2cb2488..739a7f2d 100644
--- a/src/sg_reset.c
+++ b/src/sg_reset.c
@@ -1,5 +1,5 @@
/* A utility program originally written for the Linux OS SCSI subsystem.
- * Copyright (C) 1999-2020 D. Gilbert
+ * Copyright (C) 1999-2022 D. Gilbert
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
@@ -33,7 +33,7 @@
#define ME "sg_reset: "
-static const char * version_str = "0.67 20200501";
+static const char * version_str = "0.68 20220308";
#ifndef SG_SCSI_RESET
#define SG_SCSI_RESET 0x2284
@@ -107,7 +107,7 @@ usage(int compat_mode)
}
pr2serr(" --no-esc|-N overrides default action and only does "
"reset requested\n"
- " --no-escalate The same as --no-esc|-N"
+ " --no-escalate The same as --no-esc|-N\n"
" --target|-t target reset. The target holds the DEVICE "
"and perhaps\n"
" other LUs\n"