aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDouglas Gilbert <dgilbert@interlog.com>2016-03-14 01:10:45 +0000
committerDouglas Gilbert <dgilbert@interlog.com>2016-03-14 01:10:45 +0000
commitb798bfc6514f9dfff87da36456fe15d7e1b53e6f (patch)
treeff2a7c90888a1f7d1ab21c92f3d3c6af05f1a8fb
parent70cacd5629374ab1a56c4d372aac986f1de09207 (diff)
downloadsg3_utils-b798bfc6514f9dfff87da36456fe15d7e1b53e6f.tar.gz
sg_logs: fix volume statistics; add Requested recovery, TapeAlert response, and Service buffer information; sg_opcode: add '--enumerate' and '--pdt=' options; sg_lib: add SSC maintenance in/out sa names
git-svn-id: https://svn.bingwo.ca/repos/sg3_utils/trunk@685 6180dd3e-e324-4e3e-922d-17de1ae2f315
-rw-r--r--ChangeLog7
-rw-r--r--doc/sg_logs.830
-rw-r--r--doc/sg_opcodes.874
-rw-r--r--include/sg_lib.h2
-rw-r--r--lib/sg_lib.c25
-rw-r--r--lib/sg_lib_data.c30
-rw-r--r--src/sg_logs.c296
-rw-r--r--src/sg_opcodes.c267
-rw-r--r--src/sg_read_attr.c4
-rw-r--r--src/sg_vpd.c67
10 files changed, 596 insertions, 206 deletions
diff --git a/ChangeLog b/ChangeLog
index b0393322..b2a136ca 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -2,16 +2,21 @@ 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 sg3_utils-1.43 [20160304] [svn: r684]
+Changelog for sg3_utils-1.43 [20160313] [svn: r685]
- sg_senddiag: add --timeout=SEC option
- sg_sanitize: add --timeout=SEC option
- sg_format: add --timeout=SEC option
- sg_logs: fix volume statistics lpage when subpage
is zero (ssc5r02a); decode mount history log parameter
+ - decode Requested recovery, TapeAlert response, and
+ Service buffer information lpages
+ - add '--pdt=DT' option
- sg_reassign+sg_write_same: fix ULONG_MAX problem
- sg_turs+sg_requests: make both accept '--num=NUM'
and '--number=NUM' for mutual compatibility
- sg_ses: expand join debug code
+ - sg_opcode: add '--enumerate' and '--pdt=' options
+ - sg_lib: add SSC maintenance in/out sa names
- rescan-scsi-bus.sh: harden code
- shellcheck cleanup on scripts
- automake: add AM_PROG_AR to configure.ac
diff --git a/doc/sg_logs.8 b/doc/sg_logs.8
index 2356d03d..49af4d52 100644
--- a/doc/sg_logs.8
+++ b/doc/sg_logs.8
@@ -1,4 +1,4 @@
-.TH SG_LOGS "8" "February 2016" "sg3_utils\-1.42" SG3_UTILS
+.TH SG_LOGS "8" "March 2016" "sg3_utils\-1.43" SG3_UTILS
.SH NAME
sg_logs \- access log pages with SCSI LOG SENSE command
.SH SYNOPSIS
@@ -7,15 +7,15 @@ sg_logs \- access log pages with SCSI LOG SENSE command
[\fI\-\-enumerate\fR] [\fI\-\-enum_vendor\fR] [\fI\-\-filter=FL\fR]
[\fI\-\-help\fR] [\fI\-\-hex\fR] [\fI\-\-in=FN\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\-\-raw\fR]
-[\fI\-\-readonly\fR] [\fI\-\-reset\fR] [\fI\-\-select\fR] [\fI\-\-sp\fR]
-[\fI\-\-temperature\fR] [\fI\-\-transport\fR] [\fI\-\-verbose\fR]
-[\fI\-\-version\fR] \fIDEVICE\fR
+[\fI\-\-paramp=PP\fR] [\fI\-\-pcb\fR] [\fI\-\-ppc\fR] [\fI\-\-pdt=DT\fR]
+[\fI\-\-raw\fR] [\fI\-\-readonly\fR] [\fI\-\-reset\fR] [\fI\-\-select\fR]
+[\fI\-\-sp\fR] [\fI\-\-temperature\fR] [\fI\-\-transport\fR]
+[\fI\-\-verbose\fR] [\fI\-\-version\fR] \fIDEVICE\fR
.PP
.B sg_logs
-[\fI\-a\fR] [\fI\-A\fR] [\fI\-b\fR] [\fI\-c=PC\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\-n\fR] [\fI\-p=PG\fR] [\fI\-paramp=PP\fR]
+[\fI\-a\fR] [\fI\-A\fR] [\fI\-b\fR] [\fI\-D=DT\fR] [\fI\-c=PC\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\-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
@@ -129,8 +129,8 @@ see the LOG SELECT section below.
The other context is with no \fIDEVICE\fR argument given in which case
the contents of \fIFN\fR are decoded as if it were the response of a LOG
SENSE command (i.e. a log page). For decoding the page and subpage numbers
-are taken from \fIFN\fR while the device type is either generic (i.e. from
-SPC) or the value given by \fI\-\-filter=FL\fR.
+are taken from \fIFN\fR while the peripheral device type is either
+generic (i.e. from SPC) or the value given by \fI\-\-pdt=DT\fR.
.br
\fIFN\fR is treated as a file name (or '\-' for stdin) which contains ASCII
hexadecimal or binary representing a log page. The hexadecimal should be
@@ -202,9 +202,19 @@ being output in ASCII).
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.
+.br
+This option may also be given together with \fI\-\-in=FN\fR in which case
+the contents of \fIFN\fR are interpreted as binary data (and the response is
+decoded as normal, not dumped as binary).
.TP
\fB\-R\fR, \fB\-\-readonly\fR
open the \fIDEVICE\fR read\-only (e.g. in Unix with the O_RDONLY flag). The
diff --git a/doc/sg_opcodes.8 b/doc/sg_opcodes.8
index c9508113..a88ba751 100644
--- a/doc/sg_opcodes.8
+++ b/doc/sg_opcodes.8
@@ -1,17 +1,18 @@
-.TH SG_OPCODES "8" "December 2012" "sg3_utils\-1.35" SG3_UTILS
+.TH SG_OPCODES "8" "March 2016" "sg3_utils\-1.43" SG3_UTILS
.SH NAME
sg_opcodes \- report supported SCSI commands or task management functions
.SH SYNOPSIS
.B sg_opcodes
-[\fI\-\-alpha\fR] [\fI\-\-compact\fR] [\fI\-\-help\fR] [\fI\-\-hex\fR]
-[\fI\-\-no-inquiry\fR] [\fI\-\-opcode=OP\fR] [\fI\-\-raw\fR] [\fI\-\-rctd\fR]
-[\fI\-\-repd\fR] [\fI\-\-sa=SA\fR] [\fI\-\-tmf\fR] [\fI\-\-unsorted\fR]
-[\fI\-\-verbose\fR] [\fI\-\-version\fR] \fIDEVICE\fR
+[\fI\-\-alpha\fR] [\fI\-\-compact\fR] [\fI\-\-enumerate\fR] [\fI\-\-help\fR]
+[\fI\-\-hex\fR] [\fI\-\-mask\fR] [\fI\-\-no-inquiry\fR] [\fI\-\-opcode=OP\fR]
+[\fI\-\-pdt=DT\fR] [\fI\-\-raw\fR] [\fI\-\-rctd\fR] [\fI\-\-repd\fR]
+[\fI\-\-sa=SA\fR] [\fI\-\-tmf\fR] [\fI\-\-unsorted\fR] [\fI\-\-verbose\fR]
+[\fI\-\-version\fR] \fIDEVICE\fR
.PP
.B sg_opcodes
-[\fI\-a\fR] [\fI\-c\fR] [\fI\-n\fR] [\fI\-o=OP\fR] [\fI\-q\fR] [\fI\-R\fR]
-[\fI\-s=SA\fR] [\fI\-t\fR] [\fI\-u\fR] [\fI\-v\fR] [\fI\-V\fR] [\fI\-?\fR]
-\fIDEVICE\fR
+[\fI\-a\fR] [\fI\-c\fR] [\fI\-e\fR] [\fI\-H\fR] [\fI\-m\fR] [\fI\-n\fR]
+[\fI\-o=OP\fR] [\fI\-p=DT\fR] [\fI\-q\fR] [\fI\-R\fR] [\fI\-s=SA\fR]
+[\fI\-t\fR] [\fI\-u\fR] [\fI\-v\fR] [\fI\-V\fR] [\fI\-?\fR] \fIDEVICE\fR
.SH DESCRIPTION
.\" Add any additional description here
.PP
@@ -58,6 +59,15 @@ action associated with the command, then the comma and the service action
are not shown after the opcode. The CDB size field is not shown when this
option is given.
.TP
+\fB\-e\fR, \fB\-\-enumerate\fR
+this option prints the name of the SCSI command based on the given opcode,
+peripheral device type and optionally the service action. If given,
+\fIDEVICE\fR is ignored. The opcode, peripheral device type and service
+action default to zero if not given. Thus if this option is the only option
+given then "Test Unit ready" is output since its opcode is 0, it has no
+service action and it is common to all peripheral device types since it is
+defined in the SCSI Primary Commands (SPC) standard(s).
+.TP
\fB\-h\fR, \fB\-\-help\fR
outputs the usage message summarizing command line options
then exits. Ignores \fIDEVICE\fR if given.
@@ -65,6 +75,15 @@ then exits. Ignores \fIDEVICE\fR if given.
\fB\-H\fR, \fB\-\-hex\fR
outputs the response in ASCII hexadecimal to stdout.
.TP
+\fB\-m\fR, \fB\-\-mask\fR
+additionally prints out the cdb mask in hex. So a 12 byte cdb will have
+a 12 byte hexadecimal mask. If the hexadecimal is expanded (mentally)
+to binary then a "1" means the corresponding position in the cdb may
+be set. And "0" means the corresponding position in the cdb must not
+be set. For "0" mask positions that a user tries to set in a cdb, the
+device may either ignore it or report an error, typically with a
+sense key of "illegal request".
+.TP
\fB\-n\fR, \fB\-\-no-inquiry\fR
Prior to calling a SCSI REPORT SUPPORTED OPERATION CODES or a REPORT
SUPPORTED TASK MANAGEMENT FUNCTIONS command, a SCSI INQUIRY command
@@ -78,12 +97,21 @@ is given then that summary is not printed on stdout.
switch to older style options.
.TP
\fB\-o\fR, \fB\-\-opcode\fR=\fIOP\fR
-the \fIDEVICE\fR will be queried for the given operation code ( i.e. the
+the \fIDEVICE\fR will be queried for the given operation code (i.e. the
\fIOP\fR value) which is the first byte of a SCSI command. \fIOP\fR is
decimal unless prefixed by "0x" or it has a trailing "h". \fIOP\fR should
be in the range 0 to 255 (0xff) inclusive. When this option is not given
then all available SCSI commands supported by the \fIDEVICE\fR are listed.
.TP
+\fB\-p\fR, \fB\-\-pdt\fR=\fIDT\fR
+where \fIDT\fR is the peripheral device type. This is used together with
+the \fI\-\-enumerate\fR to differentiate when a command opcode (and perhaps
+service action) is shared by multiple device types.
+.br
+This option may also be used with the \fI\-\-no-inquiry\fR option to
+suppress this utility doing an INQUIRY command since the main reason
+for doing that is to find the peripheral device type of the \fIDEVICE\fR.
+.TP
\fB\-r\fR, \fB\-\-raw\fR
output the response in binary to stdout. Error messages and warnings, if
any, are sent to stderr.
@@ -128,12 +156,11 @@ increase level of verbosity. Can be used multiple times.
\fB\-V\fR, \fB\-\-version\fR
print out version string then exit.
.SH NOTES
-As of SPC\-4 revision 7a the recognized task management functions are:
-abort set, abort task set, clear ACA, clear task set, I_T nexus reset,
-logical unit reset, query task, target reset and wakeup.
-As of SPC\-4 revision 26 target reset and wakeup have been made obsolete
-while query task set and query asynchronous event notification have been
-added.
+As of SPC\-5 revision 8 the recognized task management functions are:
+abort set, abort task set, clear ACA, clear task set, logical unit reset,
+query task, query asynchronous event, query task set, and I_T nexus reset.
+In SPC\-4 revision 26 target reset and wakeup task management functions
+were made obsolete.
.PP
In the 2.4 series of Linux kernels the \fIDEVICE\fR must be a SCSI
generic (sg) device. In the 2.6 series block devices (e.g. SCSI disks
@@ -152,6 +179,18 @@ or using '\-\-old' (or '\-O) as the first option.
sort command alphabetically. Equivalent to \fI\-\-alpha\fR in main
description.
.TP
+\fB\-c\fR
+see the \fI\-\-compact\fR option above.
+.TP
+\fB\-e\fR
+see the \fI\-\-enumerate\fR option above.
+.TP
+\fB\-H\fR
+see the \fI\-\-hex\fR option above.
+.TP
+\fB\-m\fR
+see the \fI\-\-mask\fR option above.
+.TP
\fB\-n\fR
don't print a summary of the SCSI INQUIRY response on stdout.
.TP
@@ -165,6 +204,9 @@ hexadecimal and expected to be in the range 0 to ff inclusive.
When this option is not given then all available SCSI commands supported
by the \fIDEVICE\fR are listed.
.TP
+\fB\-p\fR=\fIDT\fR
+see the \fI\-\-pdt=DT\fR option above.
+.TP
\fB\-q\fR
set the read extended parameter data (REPD) bit in report TMF cdb.
Equivalent to \fI\-\-repd\fR in main description.
@@ -237,7 +279,7 @@ Written by Douglas Gilbert
.SH "REPORTING BUGS"
Report bugs to <dgilbert at interlog dot com>.
.SH COPYRIGHT
-Copyright \(co 2004\-2012 Douglas Gilbert
+Copyright \(co 2004\-2016 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/sg_lib.h b/include/sg_lib.h
index b3e741b0..1a33c195 100644
--- a/include/sg_lib.h
+++ b/include/sg_lib.h
@@ -237,7 +237,7 @@ char * sg_get_pdt_str(int pdt, int buff_len, char * buff);
* Examples are PDT_ADC decaying to PDT_TAPE and PDT_ZBC to PDT_DISK.
* If such a lesser used 'pdt' is given to this function, then it will
* return the more used PDT (i.e. "decays to"); otherwise 'pdt' is returned.
- * Valid for 'pdt' 0 to 31, for other values returns 'pdt'. */
+ * Valid for 'pdt' 0 to 31, for other values returns 0. */
int sg_lib_pdt_decay(int pdt);
/* Yield string associated with transport protocol identifier (tpi). Returns
diff --git a/lib/sg_lib.c b/lib/sg_lib.c
index 72f63394..71188fbb 100644
--- a/lib/sg_lib.c
+++ b/lib/sg_lib.c
@@ -107,6 +107,8 @@ get_value_name(const struct sg_lib_value_name_t * arr, int value,
const struct sg_lib_value_name_t * vp = arr;
const struct sg_lib_value_name_t * holdp;
+ if (peri_type < 0)
+ peri_type = 0;
for (; vp->name; ++vp) {
if (value == vp->value) {
if (peri_type == vp->peri_dev_type)
@@ -456,7 +458,7 @@ int
sg_lib_pdt_decay(int pdt)
{
if ((pdt < 0) || (pdt > 31))
- return pdt;
+ return 0;
return sg_lib_pdt_decay_arr[pdt];
}
@@ -1382,12 +1384,16 @@ sg_get_sense_descriptors_str(const char * leadin,
return n;
}
-/* Decode SAT ATA PASS-THROUGH fixed format sense */
+/* Decode SAT ATA PASS-THROUGH fixed format sense. Shows "+" after 'count'
+ * and/or 'lba' values to indicate that not all data in those fields is shown.
+ * That extra field information may be available in the ATA pass-through
+ * results log page parameter with the corresponding 'log_index'. */
static int
sg_get_sense_sat_pt_fixed_str(const char * leadin, const unsigned char * sp,
int slen, int blen, char * b)
{
int n = 0;
+ int extend, count_upper_nz, lba_upper_nz;
const char * lip = "";
if ((blen < 1) || (slen < 12))
@@ -1397,13 +1403,18 @@ sg_get_sense_sat_pt_fixed_str(const char * leadin, const unsigned char * sp,
if (SPC_SK_RECOVERED_ERROR != (0xf & sp[2]))
n += my_snprintf(b + n, blen - n, "%s >> expected Sense key: "
"Recovered Error ??\n", lip);
+ /* Fixed sense command-specific information field starts at sp + 8 */
+ extend = !!(0x80 & sp[8]);
+ count_upper_nz = !!(0x40 & sp[8]);
+ lba_upper_nz = !!(0x20 & sp[8]);
+ /* Fixed sense information field starts at sp + 3 */
n += my_snprintf(b + n, blen - n, "%s error=0x%x, status=0x%x, "
- "device=0x%x, sector_count(7:0)=0x%x%c\n", lip, sp[3],
- sp[4], sp[5], sp[6], ((0x40 & sp[8]) ? '+' : ' '));
+ "device=0x%x, count(7:0)=0x%x%c\n", lip, sp[3],
+ sp[4], sp[5], sp[6], (count_upper_nz ? '+' : ' '));
n += my_snprintf(b + n, blen - n, "%s extend=%d, log_index=0x%x, "
"lba_high,mid,low(7:0)=0x%x,0x%x,0x%x%c\n", lip,
- (!!(0x80 & sp[8])), (0xf & sp[8]), sp[9], sp[10], sp[11],
- ((0x20 & sp[8]) ? '+' : ' '));
+ extend, (0xf & sp[8]), sp[9], sp[10], sp[11],
+ (lba_upper_nz ? '+' : ' '));
return n;
}
@@ -1808,6 +1819,8 @@ sg_get_opcode_sa_name(unsigned char cmd_byte0, int service_action,
return;
}
+ if (peri_type < 0)
+ peri_type = 0;
d_pdt = sg_lib_pdt_decay(peri_type);
for (osp = op_code2sa_arr; osp->arr; ++osp) {
if ((int)cmd_byte0 == osp->op_code) {
diff --git a/lib/sg_lib_data.c b/lib/sg_lib_data.c
index 5114c12a..cb21d3c5 100644
--- a/lib/sg_lib_data.c
+++ b/lib/sg_lib_data.c
@@ -17,7 +17,7 @@
#endif
-const char * sg_lib_version_str = "2.17 20160202"; /* spc5r08, sbc4r10 */
+const char * sg_lib_version_str = "2.18 20160312"; /* spc5r08, sbc4r10 */
/* indexed by pdt; those that map to own index do not decay */
@@ -229,7 +229,7 @@ struct sg_lib_value_name_t sg_lib_normal_opcodes[] = {
{0xffff, 0, NULL},
};
-/* Read buffer [0x3c] service actions, need prefix */
+/* Read buffer [0x3c] service actions (sa), need prefix */
struct sg_lib_value_name_t sg_lib_read_buff_arr[] = {
{0x0, 0, "combined header and data [or multiple modes]"},
{0x2, 0, "data"},
@@ -271,8 +271,17 @@ struct sg_lib_value_name_t sg_lib_read_pos_arr[] = {
/* Maintenance in [0xa3] service actions */
struct sg_lib_value_name_t sg_lib_maint_in_arr[] = {
+ {0x0, PDT_SAC, "Report assigned/unassigned p_extent"},
+ {0x1, PDT_SAC, "Report component device"},
+ {0x2, PDT_SAC, "Report component device attachments"},
+ {0x3, PDT_SAC, "Report peripheral device"},
+ {0x4, PDT_SAC, "Report peripheral device associations"},
{0x5, 0, "Report identifying information"},
/* was "Report device identifier" prior to spc4r07 */
+ {0x6, PDT_SAC, "Report states"},
+ {0x7, PDT_SAC, "Report device identification"},
+ {0x8, PDT_SAC, "Report unconfigured capacity"},
+ {0x9, PDT_SAC, "Report supported configuration method"},
{0xa, 0, "Report target port groups"},
{0xb, 0, "Report aliases"},
{0xc, 0, "Report supported operation codes"},
@@ -280,21 +289,35 @@ struct sg_lib_value_name_t sg_lib_maint_in_arr[] = {
{0xe, 0, "Report priority"},
{0xf, 0, "Report timestamp"},
{0x10, 0, "Management protocol in"},
- {0x1d, 0, "Report provisioning initialization pattern"},
+ {0x1d, PDT_DISK, "Report provisioning initialization pattern"},
+ /* added in sbc4r07, shares sa 0x1d with ssc5r01 (tape) */
+ {0x1d, PDT_TAPE, "Receive recommended access order"},
+ {0x1e, PDT_TAPE, "Read dynamic runtime attribute"},
+ {0x1e, PDT_ADC, "Report automation device attributes"},
{0x1f, 0, "Maintenance in vendor specific"},
{0xffff, 0, NULL},
};
/* Maintenance out [0xa4] service actions */
struct sg_lib_value_name_t sg_lib_maint_out_arr[] = {
+ {0x0, PDT_SAC, "Add peripheral device / component device"},
+ {0x1, PDT_SAC, "Attach to component device"},
+ {0x2, PDT_SAC, "Exchange p_extent"},
+ {0x3, PDT_SAC, "Exchange peripheral device / component device"},
+ {0x4, PDT_SAC, "Instruct component device"},
+ {0x5, PDT_SAC, "Remove peripheral device / component device"},
{0x6, 0, "Set identifying information"},
/* was "Set device identifier" prior to spc4r07 */
+ {0x7, PDT_SAC, "Break peripheral device / component device"},
{0xa, 0, "Set target port groups"},
{0xb, 0, "Change aliases"},
{0xc, 0, "Remove I_T nexus"},
{0xe, 0, "Set priority"},
{0xf, 0, "Set timestamp"},
{0x10, 0, "Management protocol out"},
+ {0x1d, PDT_TAPE, "Generate recommended access order"},
+ {0x1e, PDT_TAPE, "write dynamic runtime attribute"},
+ {0x1e, PDT_ADC, "Set automation device attributes"},
{0x1f, 0, "Maintenance out vendor specific"},
{0xffff, 0, NULL},
};
@@ -414,6 +437,7 @@ struct sg_lib_value_name_t sg_lib_variable_length_arr[] = {
{0xf, 0, "Atomic write(32)"}, /* added sbc4r02 */
{0x10, 0, "Write stream(32)"}, /* added sbc4r07 */
{0x1800, 0, "Receive credential"},
+ {0x1ff0, 0, "ATA pass-through(32)"}, /* added sat4r05 */
{0x8801, 0, "Format OSD (osd)"},
{0x8802, 0, "Create (osd)"},
{0x8803, 0, "List (osd)"},
diff --git a/src/sg_logs.c b/src/sg_logs.c
index 74bea70d..ba5f82f8 100644
--- a/src/sg_logs.c
+++ b/src/sg_logs.c
@@ -31,7 +31,7 @@
#include "sg_unaligned.h"
#include "sg_pr2serr.h"
-static const char * version_str = "1.40 20160303"; /* spc5r08 + sbc4r10 */
+static const char * version_str = "1.40 20160313"; /* spc5r08 + sbc4r10 */
#define MX_ALLOC_LEN (0xfffc)
#define SHORT_RESP_LEN 128
@@ -101,6 +101,7 @@ static struct option long_options[] = {
{"paramp", required_argument, 0, 'P'},
{"pcb", no_argument, 0, 'q'},
{"ppc", no_argument, 0, 'Q'},
+ {"pdt", required_argument, 0, 'D'},
{"raw", no_argument, 0, 'r'},
{"readonly", no_argument, 0, 'X'},
{"reset", no_argument, 0, 'R'},
@@ -142,7 +143,7 @@ struct opts_t {
int paramp;
int opt_new;
int no_inq;
- int dev_pdt;
+ int dev_pdt; /* from device or --pdt=DT */
const char * device_name;
const char * in_fn;
const char * pg_arg;
@@ -201,6 +202,10 @@ static bool show_media_stats_page(const uint8_t * resp, int len,
const struct opts_t * op);
static bool show_dt_device_status_page(const uint8_t * resp, int len,
const struct opts_t * op);
+static bool show_tapealert_response_page(const uint8_t * resp, int len,
+ const struct opts_t * op);
+static bool show_requested_recovery_page(const uint8_t * resp, int len,
+ const struct opts_t * op);
static bool show_background_scan_results_page(const uint8_t * resp, int len,
const struct opts_t * op);
static bool show_pending_defects_page(const uint8_t * resp, int len,
@@ -211,6 +216,8 @@ static bool show_lps_misalignment_page(const uint8_t * resp, int len,
const struct opts_t * op);
static bool show_element_stats_page(const uint8_t * resp, int len,
const struct opts_t * op);
+static bool show_service_buffer_info_page(const uint8_t * resp, int len,
+ const struct opts_t * op);
static bool show_ata_pt_results_page(const uint8_t * resp, int len,
const struct opts_t * op);
static bool show_tape_diag_data_page(const uint8_t * resp, int len,
@@ -295,9 +302,9 @@ static struct log_elem log_arr[] = {
{0x11, 0, 0, PDT_TAPE, 0, "DT Device status", "dtds",
show_dt_device_status_page}, /* 0x11, 0x0 SSC,ADC */
{0x12, 0, 0, PDT_TAPE, 0, "Tape alert response", "tar",
- NULL}, /* 0x12, 0x0 SSC,ADC */
+ show_tapealert_response_page}, /* 0x12, 0x0 SSC,ADC */
{0x13, 0, 0, PDT_TAPE, 0, "Requested recovery", "rr",
- NULL}, /* 0x13, 0x0 SSC,ADC */
+ show_requested_recovery_page}, /* 0x13, 0x0 SSC,ADC */
{0x14, 0, 0, PDT_TAPE, 0, "Device statistics", "ds",
show_device_stats_page}, /* 0x14, 0x0 SSC,ADC */
{0x14, 0, 0, PDT_MCHANGER, 0, "Media changer statistics", "mcs",
@@ -313,7 +320,7 @@ static struct log_elem log_arr[] = {
{0x15, 0, 0, PDT_MCHANGER, 0, "Element statistics", "els",
show_element_stats_page}, /* 0x15, 0x0 SMC */
{0x15, 0, 0, PDT_ADC, 0, "Service buffers information", "sbi",
- NULL}, /* 0x15, 0x0 ADC */
+ show_service_buffer_info_page}, /* 0x15, 0x0 ADC */
{BACKGROUND_SCAN_LPAGE, PENDING_DEFECTS_SUBPG, 0, 0, 0,
"Pending defects", "pd", show_pending_defects_page}, /* 0x15, 0x1 SBC */
{SAT_ATA_RESULTS_LPAGE, 0, 0, 0, 0, "ATA pass-through results", "aptr",
@@ -404,11 +411,11 @@ usage(int hval)
"[--in=FN]\n"
" [--list] [--no_inq] [--maxlen=LEN] [--name] "
"[--page=PG]\n"
- " [--paramp=PP] [--pcb] [--ppc] [--raw] "
- "[--readonly]\n"
- " [--reset] [--select] [--sp] [--temperature] "
- "[--transport]\n"
- " [--verbose] [--version] DEVICE\n"
+ " [--paramp=PP] [--pcb] [--ppc] [--pdt=DT] "
+ "[--raw]\n"
+ " [--readonly] [--reset] [--select] [--sp] "
+ "[--temperature]\n"
+ " [--transport] [--verbose] [--version] DEVICE\n"
" where the main options are:\n"
" --All|-A fetch and decode all log pages and "
"subpages\n"
@@ -479,6 +486,9 @@ usage(int hval)
"output\n"
" --ppc|-Q set the Parameter Pointer Control (PPC) bit "
"(def: 0)\n"
+ " --pdt=DT|-D DT DT is peripheral device type to use with "
+ "'--in=FN'\n"
+ " or when '--no_inq' is used\n"
" --readonly|-X open DEVICE read-only (def: first "
"read-write then if\n"
" fails try open again read-only)\n"
@@ -491,17 +501,19 @@ usage(int hval)
" --version|-V output version string then exit\n\n"
"If DEVICE and --select are given, a LOG SELECT command will be "
"issued. If\nDEVICE is not given and '--in=FN' is given then FN "
- "will decoded as if it\nwere a log page. Pages defined in SPC "
- "are common to all device types.\n");
+ "will decoded as if it\nwere a log page. The contents of FN "
+ "typically generated by a prior\n"
+ "'sg_logs -HHH ...' invocation.\nPages defined in SPC are common "
+ "to all device types.\n");
}
}
static void
usage_old()
{
- printf("Usage: sg_logs [-a] [-A] [-b] [-c=PC] [-e] [-E] [-f=FL] [-h] "
- "[-H]\n"
- " [-i=FN] [-l] [-L] [-m=LEN] [-n] [-p=PG] "
+ printf("Usage: sg_logs [-a] [-A] [-b] [-c=PC] [-D=DT] [-e] [-E] [-f=FL] "
+ "[-h]\n"
+ " [-H] [-i=FN] [-l] [-L] [-m=LEN] [-n] [-p=PG] "
"[-paramp=PP]\n"
" [-pcb] [-ppc] [-r] [-select] [-sp] [-t] [-T] "
"[-v] [-V]\n"
@@ -711,7 +723,7 @@ process_cl_new(struct opts_t * op, int argc, char * argv[])
while (1) {
int option_index = 0;
- c = getopt_long(argc, argv, "aAbc:eEf:hHi:lLm:nNOp:P:qQrRsStTvVxX",
+ c = getopt_long(argc, argv, "aAbc:D:eEf:hHi:lLm:nNOp:P:qQrRsStTvVxX",
long_options, &option_index);
if (c == -1)
break;
@@ -735,6 +747,14 @@ process_cl_new(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;
+ }
+ op->dev_pdt = n;
+ break;
case 'e':
++op->do_enumerate;
break;
@@ -962,6 +982,14 @@ process_cl_old(struct opts_t * op, int argc, char * argv[])
return SG_LIB_SYNTAX_ERROR;
}
op->page_control = u;
+ } else if (0 == strncmp("D=", cp, 2)) {
+ n = sg_get_num(cp + 2);
+ if ((n < 0) || (n > 31)) {
+ pr2serr("Bad argument after '-D=' option\n");
+ usage_old();
+ return SG_LIB_SYNTAX_ERROR;
+ }
+ op->dev_pdt = n;
} else if (0 == strncmp("f=", cp, 2)) {
n = sg_get_num(cp + 2);
if ((n < 0) || (n > 0xffff)) {
@@ -4210,6 +4238,162 @@ skip:
return true;
}
+/* TapeAlert response [0x12] (adc,ssc) */
+static bool
+show_tapealert_response_page(const uint8_t * resp, int len,
+ const struct opts_t * op)
+{
+ int num, pl, pc, pcb, k, mod, div;
+ const uint8_t * ucp;
+ char str[PCB_STR_LEN];
+
+ if (op->verbose || ((0 == op->do_raw) && (0 == op->do_hex)))
+ printf("TapeAlert response page (ssc-3, adc-3) [0x12]\n");
+ num = len - 4;
+ ucp = &resp[0] + 4;
+ while (num > 3) {
+ pc = sg_get_unaligned_be16(ucp + 0);
+ pcb = ucp[2];
+ pl = ucp[3] + 4;
+ if (op->filter_given) {
+ if (pc != op->filter)
+ goto skip;
+ if (op->do_raw) {
+ dStrRaw((const char *)ucp, pl);
+ break;
+ } else if (op->do_hex) {
+ dStrHex((const char *)ucp, pl, ((1 == op->do_hex) ? 1 : -1));
+ break;
+ }
+ }
+ switch (pc) {
+ case 0x0:
+ if (pl < 12) {
+
+ }
+ for (k = 1; k < 0x41; ++k) {
+ mod = ((k - 1) % 8);
+ div = (k - 1) / 8;
+ if (0 == mod) {
+ if (div > 0)
+ printf("\n");
+ printf(" Flag%02Xh: %d", k, !! (ucp[4 + div] & 0x80));
+ } else
+ printf(" %02Xh: %d", k,
+ !! (ucp[4 + div] & (1 << (7 - mod))));
+ }
+ printf("\n");
+ break;
+ default:
+ if (pc <= 0x8000) {
+ printf(" Reserved [parameter_code=0x%x]:\n", pc);
+ dStrHex((const char *)ucp, ((pl < num) ? pl : num), 0);
+ } else {
+ printf(" Vendor specific [parameter_code=0x%x]:\n", pc);
+ dStrHex((const char *)ucp, ((pl < num) ? pl : num), 0);
+ }
+ break;
+ }
+ if (op->do_pcb) {
+ get_pcb_str(pcb, str, sizeof(str));
+ printf(" <%s>\n", str);
+ }
+ if (op->filter_given)
+ break;
+skip:
+ num -= pl;
+ ucp += pl;
+ }
+ return true;
+}
+
+#define NUM_REQ_REC_ARR_ELEMS 16
+static const char * req_rec_arr[NUM_REQ_REC_ARR_ELEMS] = {
+ "Recovery not requested",
+ "Recovery requested, no recovery procedure defined",
+ "Instruct operator to push volume",
+ "Instruct operator to remove and re-insert volume",
+ "Issue UNLOAD command. Instruct operator to remove and re-insert volume",
+ "Instruct operator to power cycle target device",
+ "Issue LOAD command",
+ "Issue UNLOAD command",
+ "Issue LOGICAL UNIT RESET task management function", /* 0x8 */
+ "No recovery procedure defined. Contact service organization",
+ "Issue UNLOAD command. Instruct operator to remove and quarantine "
+ "volume",
+ "Instruct operator to not insert a volume. Contact service organization",
+ "Issue UNLOAD command. Instruct operator to remove volume. Contact "
+ "service organization",
+ "Request creation of target device error log",
+ "Retrieve a target device error log",
+ "Modify configuration to all microcode update and instruct operator to "
+ "re-insert volume", /* 0xf */
+};
+
+/* Requested recovery [0x13] (ssc) */
+static bool
+show_requested_recovery_page(const uint8_t * resp, int len,
+ const struct opts_t * op)
+{
+ int num, pl, pc, pcb, j, k;
+ const uint8_t * ucp;
+ char str[PCB_STR_LEN];
+
+ if (op->verbose || ((0 == op->do_raw) && (0 == op->do_hex)))
+ printf("Requested recovery page (ssc-3) [0x13]\n");
+ num = len - 4;
+ ucp = &resp[0] + 4;
+ while (num > 3) {
+ pc = sg_get_unaligned_be16(ucp + 0);
+ pcb = ucp[2];
+ pl = ucp[3] + 4;
+ if (op->filter_given) {
+ if (pc != op->filter)
+ goto skip;
+ if (op->do_raw) {
+ dStrRaw((const char *)ucp, pl);
+ break;
+ } else if (op->do_hex) {
+ dStrHex((const char *)ucp, pl, ((1 == op->do_hex) ? 1 : -1));
+ break;
+ }
+ }
+ switch (pc) {
+ case 0x0:
+ printf(" Recovery procedures:\n");
+ for (k = 4; k < pl; ++ k) {
+ j = ucp[k];
+ if (j < NUM_REQ_REC_ARR_ELEMS)
+ printf(" %s\n", req_rec_arr[j]);
+ else if (j < 0x80)
+ printf(" Reserved [0x%x]\n", j);
+ else
+ printf(" Vendor specific [0x%x]\n", j);
+ }
+ break;
+ default:
+ if (pc <= 0x8000) {
+ printf(" Reserved [parameter_code=0x%x]:\n", pc);
+ dStrHex((const char *)ucp, ((pl < num) ? pl : num), 0);
+ } else {
+ printf(" Vendor specific [parameter_code=0x%x]:\n", pc);
+ dStrHex((const char *)ucp, ((pl < num) ? pl : num), 0);
+ }
+ break;
+ }
+ if (op->do_pcb) {
+ get_pcb_str(pcb, str, sizeof(str));
+ printf(" <%s>\n", str);
+ }
+ if (op->filter_given)
+ break;
+skip:
+ num -= pl;
+ ucp += pl;
+ }
+ return true;
+}
+
/* SAT_ATA_RESULTS_LPAGE (SAT-2) [0x16] */
static bool
show_ata_pt_results_page(const uint8_t * resp, int len,
@@ -4240,23 +4424,28 @@ show_ata_pt_results_page(const uint8_t * resp, int len,
}
}
if ((pc < 0xf) && (pl > 17)) {
- int extend, sector_count;
+ int extend, count;
- dp = ucp + 4;
printf(" Log_index=0x%x (parameter_code=0x%x)\n", pc + 1, pc);
+ dp = ucp + 4; /* dp is start of ATA Return descriptor
+ * which is 14 bytes long */
extend = dp[2] & 1;
- sector_count = dp[5] + (extend ? (dp[4] << 8) : 0);
- printf(" extend=%d error=0x%x sector_count=0x%x\n", extend,
- dp[3], sector_count);
+ count = dp[5] + (extend ? (dp[4] << 8) : 0);
+ printf(" extend=%d error=0x%x count=0x%x\n", extend,
+ dp[3], count);
if (extend)
printf(" lba=0x%02x%02x%02x%02x%02x%02x\n", dp[10], dp[8],
dp[6], dp[11], dp[9], dp[7]);
else
printf(" lba=0x%02x%02x%02x\n", dp[11], dp[9], dp[7]);
printf(" device=0x%x status=0x%x\n", dp[12], dp[13]);
- } else {
+ } else if (pl > 17) {
printf(" Reserved [parameter_code=0x%x]:\n", pc);
dStrHex((const char *)ucp, ((pl < num) ? pl : num), 0);
+ } else {
+ printf(" short parameter length: %d [parameter_code=0x%x]:\n",
+ pl, pc);
+ dStrHex((const char *)ucp, ((pl < num) ? pl : num), 0);
}
if (op->do_pcb) {
get_pcb_str(pcb, str, sizeof(str));
@@ -4622,6 +4811,63 @@ skip:
return true;
}
+/* Service buffer information [0x15] (adc) */
+static bool
+show_service_buffer_info_page(const uint8_t * resp, int len,
+ const struct opts_t * op)
+{
+ int num, pl, pc, pcb;
+ const uint8_t * ucp;
+ char str[PCB_STR_LEN];
+
+ if (op->verbose || ((0 == op->do_raw) && (0 == op->do_hex)))
+ printf("Service buffer information page (adc-3) [0x15]\n");
+ num = len - 4;
+ ucp = &resp[0] + 4;
+ while (num > 3) {
+ pc = sg_get_unaligned_be16(ucp + 0);
+ pcb = ucp[2];
+ pl = ucp[3] + 4;
+ if (op->filter_given) {
+ if (pc != op->filter)
+ goto skip;
+ if (op->do_raw) {
+ dStrRaw((const char *)ucp, pl);
+ break;
+ } else if (op->do_hex) {
+ dStrHex((const char *)ucp, pl, ((1 == op->do_hex) ? 1 : -1));
+ break;
+ }
+ }
+ if (pc < 0x100) {
+ printf(" Service buffer identifier: 0x%x\n", pc);
+ printf(" Buffer id: 0x%x, tu=%d, nmp=%d, nmm=%d, "
+ "offline=%d\n", ucp[4], !!(0x10 & ucp[5]),
+ !!(0x8 & ucp[5]), !!(0x4 & ucp[5]), !!(0x2 & ucp[5]));
+ printf(" pd=%d, code_set: %s, Service buffer title:\n",
+ !!(0x1 & ucp[5]), sg_get_desig_code_set_str(0xf & ucp[6]));
+ printf(" %*s\n", pl - 8, ucp + 8);
+ } else if (pc < 0x8000) {
+ printf(" parameter_code=0x%x, Reserved, parameter in hex:\n",
+ pc);
+ dStrHex((const char *)ucp + 4, pl - 4, 0);
+ } else {
+ printf(" parameter_code=0x%x, Vendor-specific, parameter in "
+ "hex:\n", pc);
+ dStrHex((const char *)ucp + 4, pl - 4, 0);
+ }
+ if (op->do_pcb) {
+ get_pcb_str(pcb, str, sizeof(str));
+ printf(" <%s>\n", str);
+ }
+ if (op->filter_given)
+ break;
+skip:
+ num -= pl;
+ ucp += pl;
+ }
+ return true;
+}
/* Sequential access device page [0xc] for tape */
static bool
@@ -5055,7 +5301,7 @@ skip:
return true;
}
-/* 0x15 for media changer */
+/* Element statistics page, 0x15 for SMC */
static bool
show_element_stats_page(const uint8_t * resp, int len,
const struct opts_t * op)
@@ -6039,9 +6285,7 @@ main(int argc, char * argv[])
n);
n = in_len - k;
}
- pdt = (op->filter_given && (op->filter >= 0)) ?
- op->filter : -1;
- op->dev_pdt = pdt;
+ pdt = op->dev_pdt;
lep = pg_subpg_pdt_search(pg_code, subpg_code, pdt);
if (lep) {
if (lep->show_pagep)
diff --git a/src/sg_opcodes.c b/src/sg_opcodes.c
index 1b42f172..eddf65a3 100644
--- a/src/sg_opcodes.c
+++ b/src/sg_opcodes.c
@@ -1,5 +1,5 @@
/* A utility program originally written for the Linux OS SCSI subsystem.
- * Copyright (C) 2004-2015 D. Gilbert
+ * Copyright (C) 2004-2016 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)
@@ -15,6 +15,7 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+#include <ctype.h>
#include <getopt.h>
#ifdef HAVE_CONFIG_H
@@ -28,7 +29,7 @@
#include "sg_pt.h"
-static const char * version_str = "0.45 20151219"; /* spc5r07 */
+static const char * version_str = "0.46 20160313"; /* spc5r08 */
#define SENSE_BUFF_LEN 64 /* Arbitrary, could be larger */
@@ -44,7 +45,7 @@ static const char * version_str = "0.45 20151219"; /* spc5r07 */
#define NAME_BUFF_SZ 128
-static int peri_type = 0; /* ugly but not easy to pass to alpha compare */
+static int peri_dtype = -1; /* ugly but not easy to pass to alpha compare */
static int do_rsoc(int sg_fd, int rctd, int rep_opts, int rq_opcode,
int rq_servact, void * resp, int mx_resp_len, int noisy,
@@ -56,6 +57,7 @@ static int do_rstmf(int sg_fd, int repd, void * resp, int mx_resp_len,
static struct option long_options[] = {
{"alpha", 0, 0, 'a'},
{"compact", 0, 0, 'c'},
+ {"enumerate", 0, 0, 'e'},
{"help", 0, 0, 'h'},
{"hex", 0, 0, 'H'},
{"mask", 0, 0, 'm'},
@@ -77,16 +79,17 @@ static struct option long_options[] = {
struct opts_t {
int do_alpha;
int do_compact;
+ int do_enumerate;
int do_help;
int do_hex;
int no_inquiry;
int do_mask;
- int do_opcode;
+ int opcode;
int do_raw;
int do_rctd;
int do_repd;
- int do_servact;
- int do_verbose;
+ int servact;
+ int verbose;
int do_version;
int do_unsorted;
int do_taskman;
@@ -98,17 +101,20 @@ struct opts_t {
static void
usage()
{
- pr2serr("Usage: sg_opcodes [--alpha] [--compact] [--help] [--hex] "
- "[--mask]\n"
- " [--no-inquiry] [--opcode=OP[,SA]] [--raw] "
- "[--rctd]\n"
- " [--repd] [--sa=SA] [--tmf] [--unsorted] "
- "[--verbose]\n"
- " [--version] DEVICE\n"
+ pr2serr("Usage: sg_opcodes [--alpha] [--compact] [--enumerate] "
+ "[--help] [--hex]\n"
+ " [--mask] [--no-inquiry] [--opcode=OP[,SA]] "
+ "[--pdt=DT]\n"
+ " [--raw] [--rctd] [--repd] [--sa=SA] [--tmf] "
+ "[--unsorted]\n"
+ " [--verbose] [--version] DEVICE\n"
" where:\n"
" --alpha|-a output list of operation codes sorted "
"alphabetically\n"
" --compact|-c more compact output\n"
+ " --enumerate|-e use '--opcode=' and '--pdt=' to look up "
+ "name,\n"
+ " ignore DEVICE\n"
" --help|-h print usage message then exit\n"
" --hex|-H output response in hex\n"
" --mask|-m and show cdb usage data (a mask) when "
@@ -120,6 +126,9 @@ usage()
"(SA)\n"
" (decimal, each prefix with '0x' for "
"hex)\n"
+ " --pdt=DT|-p DT give peripheral device type for "
+ "'--no-inquiry'\n"
+ " '--enumerate'\n"
" --raw|-r output response in binary to stdout\n"
" --rctd|-R set RCTD (return command timeout "
"descriptor) bit\n"
@@ -141,17 +150,22 @@ usage()
static void
usage_old()
{
- pr2serr("Usage: sg_opcodes [-a] [-c] [-H] [-m] [-n] [-o=OP] [-q] [-r] "
- "[-R] [-s=SA]\n"
- " [-t] [-u] [-v] [-V] DEVICE\n"
+ pr2serr("Usage: sg_opcodes [-a] [-c] [-e] [-H] [-m] [-n] [-o=OP] "
+ "[-p=DT] [-q]\n"
+ " [-r] [-R] [-s=SA] [-t] [-u] [-v] [-V] "
+ "DEVICE\n"
" where:\n"
" -a output list of operation codes sorted "
"alphabetically\n"
" -c more compact output\n"
+ " -e use '--opcode=' and '--pdt=' to look up name, "
+ "ignore DEVICE\n"
" -H print response in hex\n"
" -m and show cdb usage data (a mask) when all listed\n"
" -n don't output INQUIRY information\n"
" -o=OP first byte of command to query (in hex)\n"
+ " -p=DT alternate source of pdt (normally obtained from "
+ "inquiry)\n"
" -q set REPD bit for tmf_s\n"
" -r output response in binary to stdout\n"
" -R set RCTD (return command timeout "
@@ -167,7 +181,7 @@ usage_old()
}
static int
-process_cl_new(struct opts_t * optsp, int argc, char * argv[])
+process_cl_new(struct opts_t * op, int argc, char * argv[])
{
int c, n;
char * cp;
@@ -176,30 +190,33 @@ process_cl_new(struct opts_t * optsp, int argc, char * argv[])
while (1) {
int option_index = 0;
- c = getopt_long(argc, argv, "achHmnNo:OqrRs:tuvV", long_options,
+ c = getopt_long(argc, argv, "acehHmnNo:Op:qrRs:tuvV", long_options,
&option_index);
if (c == -1)
break;
switch (c) {
case 'a':
- ++optsp->do_alpha;
+ ++op->do_alpha;
break;
case 'c':
- ++optsp->do_compact;
+ ++op->do_compact;
+ break;
+ case 'e':
+ ++op->do_enumerate;
break;
case 'h':
case '?':
- ++optsp->do_help;
+ ++op->do_help;
break;
case 'H':
- ++optsp->do_hex;
+ ++op->do_hex;
break;
case 'm':
- ++optsp->do_mask;
+ ++op->do_mask;
break;
case 'n':
- ++optsp->no_inquiry;
+ ++op->no_inquiry;
break;
case 'N':
break; /* ignore */
@@ -217,14 +234,14 @@ process_cl_new(struct opts_t * optsp, int argc, char * argv[])
pr2serr("bad OP argument to '--opcode'\n");
return SG_LIB_SYNTAX_ERROR;
}
- optsp->do_opcode = n;
+ op->opcode = n;
n = sg_get_num(cp + 1);
if ((n < 0) || (n > 0xffff)) {
pr2serr("bad SA argument to '--opcode'\n");
usage();
return SG_LIB_SYNTAX_ERROR;
}
- optsp->do_servact = n;
+ op->servact = n;
} else {
n = sg_get_num(optarg);
if ((n < 0) || (n > 255)) {
@@ -232,20 +249,32 @@ process_cl_new(struct opts_t * optsp, int argc, char * argv[])
usage();
return SG_LIB_SYNTAX_ERROR;
}
- optsp->do_opcode = n;
+ op->opcode = n;
}
break;
case 'O':
- optsp->opt_new = 0;
+ op->opt_new = 0;
return 0;
+ case 'p':
+ n = -2;
+ if (isdigit(optarg[0]))
+ n = sg_get_num(optarg);
+ else if ((2 == strlen(optarg)) && (0 == strcmp("-1", optarg)))
+ n = -1;
+ if ((n < -1) || (n > 0x1f)) {
+ pr2serr("bad argument to '--pdt=DT', expect -1 to 31\n");
+ return SG_LIB_SYNTAX_ERROR;
+ }
+ peri_dtype = n;
+ break;
case 'q':
- ++optsp->do_repd;
+ ++op->do_repd;
break;
case 'r':
- ++optsp->do_raw;
+ ++op->do_raw;
break;
case 'R':
- ++optsp->do_rctd;
+ ++op->do_rctd;
break;
case 's':
n = sg_get_num(optarg);
@@ -254,31 +283,31 @@ process_cl_new(struct opts_t * optsp, int argc, char * argv[])
usage();
return SG_LIB_SYNTAX_ERROR;
}
- optsp->do_servact = n;
+ op->servact = n;
break;
case 't':
- ++optsp->do_taskman;
+ ++op->do_taskman;
break;
case 'u':
- ++optsp->do_unsorted;
+ ++op->do_unsorted;
break;
case 'v':
- ++optsp->do_verbose;
+ ++op->verbose;
break;
case 'V':
- ++optsp->do_version;
+ ++op->do_version;
break;
default:
pr2serr("unrecognised option code %c [0x%x]\n", c, c);
- if (optsp->do_help)
+ if (op->do_help)
break;
usage();
return SG_LIB_SYNTAX_ERROR;
}
}
if (optind < argc) {
- if (NULL == optsp->device_name) {
- optsp->device_name = argv[optind];
+ if (NULL == op->device_name) {
+ op->device_name = argv[optind];
++optind;
}
if (optind < argc) {
@@ -292,7 +321,7 @@ process_cl_new(struct opts_t * optsp, int argc, char * argv[])
}
static int
-process_cl_old(struct opts_t * optsp, int argc, char * argv[])
+process_cl_old(struct opts_t * op, int argc, char * argv[])
{
int k, jmp_out, plen, n, num;
const char * cp;
@@ -306,46 +335,49 @@ process_cl_old(struct opts_t * optsp, int argc, char * argv[])
for (--plen, ++cp, jmp_out = 0; plen > 0; --plen, ++cp) {
switch (*cp) {
case 'a':
- ++optsp->do_alpha;
+ ++op->do_alpha;
break;
case 'c':
- ++optsp->do_compact;
+ ++op->do_compact;
+ break;
+ case 'e':
+ ++op->do_enumerate;
break;
case 'H':
- ++optsp->do_hex;
+ ++op->do_hex;
break;
case 'm':
- ++optsp->do_mask;
+ ++op->do_mask;
break;
case 'n':
- ++optsp->no_inquiry;
+ ++op->no_inquiry;
break;
case 'N':
- optsp->opt_new = 1;
+ op->opt_new = 1;
return 0;
case 'O':
break;
case 'q':
- ++optsp->do_repd;
+ ++op->do_repd;
break;
case 'R':
- ++optsp->do_rctd;
+ ++op->do_rctd;
break;
case 't':
- ++optsp->do_taskman;
+ ++op->do_taskman;
break;
case 'u':
- ++optsp->do_unsorted;
+ ++op->do_unsorted;
break;
case 'v':
- ++optsp->do_verbose;
+ ++op->verbose;
break;
case 'V':
- ++optsp->do_version;
+ ++op->do_version;
break;
case 'h':
case '?':
- ++optsp->do_help;
+ ++op->do_help;
break;
default:
jmp_out = 1;
@@ -363,7 +395,15 @@ process_cl_old(struct opts_t * optsp, int argc, char * argv[])
usage_old();
return SG_LIB_SYNTAX_ERROR;
}
- optsp->do_opcode = n;
+ op->opcode = n;
+ } else if (0 == strncmp("p=", cp, 2)) {
+ num = sscanf(cp + 2, "%d", &n);
+ if ((1 != num) || (n > 0x1f) || (n < -1)) {
+ pr2serr("Bad number after 'p=' option, expect -1 to "
+ "31\n");
+ return SG_LIB_SYNTAX_ERROR;
+ }
+ peri_dtype = n;
} else if (0 == strncmp("s=", cp, 2)) {
num = sscanf(cp + 2, "%x", (unsigned int *)&n);
if (1 != num) {
@@ -371,7 +411,7 @@ process_cl_old(struct opts_t * optsp, int argc, char * argv[])
usage_old();
return SG_LIB_SYNTAX_ERROR;
}
- optsp->do_servact = n;
+ op->servact = n;
} else if (0 == strncmp("-old", cp, 4))
;
else if (jmp_out) {
@@ -379,11 +419,11 @@ process_cl_old(struct opts_t * optsp, int argc, char * argv[])
usage_old();
return SG_LIB_SYNTAX_ERROR;
}
- } else if (NULL == optsp->device_name)
- optsp->device_name = cp;
+ } else if (NULL == op->device_name)
+ op->device_name = cp;
else {
pr2serr("too many arguments, got: %s, not expecting: %s\n",
- optsp->device_name, cp);
+ op->device_name, cp);
usage_old();
return SG_LIB_SYNTAX_ERROR;
}
@@ -392,22 +432,22 @@ process_cl_old(struct opts_t * optsp, int argc, char * argv[])
}
static int
-process_cl(struct opts_t * optsp, int argc, char * argv[])
+process_cl(struct opts_t * op, int argc, char * argv[])
{
int res;
char * cp;
cp = getenv("SG3_UTILS_OLD_OPTS");
if (cp) {
- optsp->opt_new = 0;
- res = process_cl_old(optsp, argc, argv);
- if ((0 == res) && optsp->opt_new)
- res = process_cl_new(optsp, argc, argv);
+ op->opt_new = 0;
+ res = process_cl_old(op, argc, argv);
+ if ((0 == res) && op->opt_new)
+ res = process_cl_new(op, argc, argv);
} else {
- optsp->opt_new = 1;
- res = process_cl_new(optsp, argc, argv);
- if ((0 == res) && (0 == optsp->opt_new))
- res = process_cl_old(optsp, argc, argv);
+ op->opt_new = 1;
+ res = process_cl_new(op, argc, argv);
+ if ((0 == res) && (0 == op->opt_new))
+ res = process_cl_old(op, argc, argv);
}
return res;
}
@@ -472,13 +512,13 @@ opcode_alpha_compare(const void * left, const void * right)
if (ll[5] & 1)
l_serv_act = sg_get_unaligned_be16(ll + 2);
l_name_buff[0] = '\0';
- sg_get_opcode_sa_name(l_opc, l_serv_act, peri_type,
+ sg_get_opcode_sa_name(l_opc, l_serv_act, peri_dtype,
NAME_BUFF_SZ, l_name_buff);
r_opc = rr[0];
if (rr[5] & 1)
r_serv_act = sg_get_unaligned_be16(rr + 2);
r_name_buff[0] = '\0';
- sg_get_opcode_sa_name(r_opc, r_serv_act, peri_type,
+ sg_get_opcode_sa_name(r_opc, r_serv_act, peri_dtype,
NAME_BUFF_SZ, r_name_buff);
return strncmp(l_name_buff, r_name_buff, NAME_BUFF_SZ);
}
@@ -552,14 +592,14 @@ list_all_codes(unsigned char * rsoc_buff, int rsoc_len, struct opts_t * op,
serv_act = 0;
if (sa_v) {
serv_act = sg_get_unaligned_be16(ucp + 2);
- sg_get_opcode_sa_name(opcode, serv_act, peri_type, NAME_BUFF_SZ,
+ sg_get_opcode_sa_name(opcode, serv_act, peri_dtype, NAME_BUFF_SZ,
name_buff);
if (op->do_compact)
snprintf(sa_buff, sizeof(sa_buff), "%-4x", serv_act);
else
snprintf(sa_buff, sizeof(sa_buff), "%4x", serv_act);
} else {
- sg_get_opcode_name(opcode, peri_type, NAME_BUFF_SZ, name_buff);
+ sg_get_opcode_name(opcode, peri_dtype, NAME_BUFF_SZ, name_buff);
memset(sa_buff, ' ', sizeof(sa_buff));
}
if (op->do_rctd) {
@@ -602,7 +642,7 @@ list_all_codes(unsigned char * rsoc_buff, int rsoc_len, struct opts_t * op,
memset(b, 0, sizeof(b));
res = do_rsoc(sg_fd, 0, (sa_v ? 2 : 1), opcode, serv_act,
- b, sizeof(b), 1, op->do_verbose);
+ b, sizeof(b), 1, op->verbose);
if (0 == res) {
cdb_sz = sg_get_unaligned_be16(b + 2);
if ((cdb_sz > 0) && (cdb_sz <= 80)) {
@@ -664,13 +704,13 @@ list_one(unsigned char * rsoc_buff, int cd_len, int rep_opts,
int v = 0;
- printf("\n Opcode=0x%.2x", op->do_opcode);
+ printf("\n Opcode=0x%.2x", op->opcode);
if (rep_opts > 1)
- printf(" Service_action=0x%.4x", op->do_servact);
+ printf(" Service_action=0x%.4x", op->servact);
printf("\n");
- sg_get_opcode_sa_name(((op->do_opcode > 0) ? op->do_opcode : 0),
- ((op->do_servact > 0) ? op->do_servact : 0),
- peri_type, NAME_BUFF_SZ, name_buff);
+ sg_get_opcode_sa_name(((op->opcode > 0) ? op->opcode : 0),
+ ((op->servact > 0) ? op->servact : 0),
+ peri_dtype, NAME_BUFF_SZ, name_buff);
printf(" Command_name: %s\n", name_buff);
switch((int)(rsoc_buff[1] & 7)) {
case 0:
@@ -725,8 +765,8 @@ main(int argc, char * argv[])
op = &opts;
memset(op, 0, sizeof(opts));
- op->do_opcode = -1;
- op->do_servact = -1;
+ op->opcode = -1;
+ op->servact = -1;
res = process_cl(op, argc, argv);
if (res)
return SG_LIB_SYNTAX_ERROR;
@@ -742,7 +782,7 @@ main(int argc, char * argv[])
return 0;
}
- if (NULL == op->device_name) {
+ if ((NULL == op->device_name) && (0 == op->do_enumerate)) {
pr2serr("No DEVICE argument given\n");
if (op->opt_new)
usage();
@@ -750,7 +790,7 @@ main(int argc, char * argv[])
usage_old();
return SG_LIB_SYNTAX_ERROR;
}
- if ((-1 != op->do_servact) && (-1 == op->do_opcode)) {
+ if ((-1 != op->servact) && (-1 == op->opcode)) {
pr2serr("When '-s' is chosen, so must '-o' be chosen\n");
if (op->opt_new)
usage();
@@ -761,32 +801,59 @@ main(int argc, char * argv[])
if (op->do_unsorted && op->do_alpha)
pr2serr("warning: unsorted ('-u') and alpha ('-a') options chosen, "
"ignoring alpha\n");
- if (op->do_taskman && ((-1 != op->do_opcode) || op->do_alpha ||
+ if (op->do_taskman && ((-1 != op->opcode) || op->do_alpha ||
op->do_unsorted)) {
pr2serr("warning: task management functions ('-t') chosen so alpha "
"('-a'),\n unsorted ('-u') and opcode ('-o') "
"options ignored\n");
}
+ if (op->do_enumerate) {
+ char name_buff[NAME_BUFF_SZ];
+
+ if (op->do_taskman)
+ printf("enumerate not supported with task management "
+ "functions\n");
+ else { /* SCSI command */
+ if (op->opcode < 0)
+ op->opcode = 0;
+ if (op->servact < 0)
+ op->servact = 0;
+ if (peri_dtype < 0)
+ peri_dtype = 0;
+ printf("SCSI command:");
+ if (op->verbose)
+ printf(" [opcode=0x%x, sa=0x%x, pdt=0x%x]\n", op->opcode,
+ op->servact, peri_dtype);
+ else
+ printf("\n");
+ sg_get_opcode_sa_name(op->opcode, op->servact, peri_dtype,
+ NAME_BUFF_SZ, name_buff);
+ printf(" %s\n", name_buff);
+ }
+ return 0;
+ }
op_name = op->do_taskman ? "Report supported task management functions" :
"Report supported operation codes";
- if (op->do_opcode < 0) {
+ if (op->opcode < 0) {
if ((sg_fd = scsi_pt_open_device(op->device_name, 1 /* RO */,
- op->do_verbose)) < 0) {
+ op->verbose)) < 0) {
pr2serr("sg_opcodes: error opening file (ro): %s: %s\n",
op->device_name, safe_strerror(-sg_fd));
return SG_LIB_FILE_ERROR;
}
- if (0 == sg_simple_inquiry(sg_fd, &inq_resp, 1, op->do_verbose)) {
- peri_type = inq_resp.peripheral_type;
+ if (op->no_inquiry && (peri_dtype >= 0))
+ ;
+ else if (0 == sg_simple_inquiry(sg_fd, &inq_resp, 1, op->verbose)) {
+ peri_dtype = inq_resp.peripheral_type;
if (! (op->do_raw || op->no_inquiry)) {
printf(" %.8s %.16s %.4s\n", inq_resp.vendor,
inq_resp.product, inq_resp.revision);
- cp = sg_get_pdt_str(peri_type, sizeof(buff), buff);
+ cp = sg_get_pdt_str(peri_dtype, sizeof(buff), buff);
if (strlen(cp) > 0)
printf(" Peripheral device type: %s\n", cp);
else
- printf(" Peripheral device type: 0x%x\n", peri_type);
+ printf(" Peripheral device type: 0x%x\n", peri_dtype);
}
} else {
pr2serr("sg_opcodes: %s doesn't respond to a SCSI INQUIRY\n",
@@ -801,23 +868,23 @@ main(int argc, char * argv[])
}
if ((sg_fd = scsi_pt_open_device(op->device_name, 0 /* RW */,
- op->do_verbose)) < 0) {
+ op->verbose)) < 0) {
pr2serr("sg_opcodes: error opening file (rw): %s: %s\n",
op->device_name, safe_strerror(-sg_fd));
return SG_LIB_FILE_ERROR;
}
- if (op->do_opcode >= 0)
- rep_opts = ((op->do_servact >= 0) ? 2 : 1);
+ if (op->opcode >= 0)
+ rep_opts = ((op->servact >= 0) ? 2 : 1);
memset(rsoc_buff, 0, sizeof(rsoc_buff));
if (op->do_taskman)
res = do_rstmf(sg_fd, op->do_repd, rsoc_buff,
- (op->do_repd ? 16 : 4), 1, op->do_verbose);
+ (op->do_repd ? 16 : 4), 1, op->verbose);
else
- res = do_rsoc(sg_fd, op->do_rctd, rep_opts, op->do_opcode,
- op->do_servact, rsoc_buff, sizeof(rsoc_buff), 1,
- op->do_verbose);
+ res = do_rsoc(sg_fd, op->do_rctd, rep_opts, op->opcode,
+ op->servact, rsoc_buff, sizeof(rsoc_buff), 1,
+ op->verbose);
if (res) {
- sg_get_category_sense_str(res, sizeof(b), b, op->do_verbose);
+ sg_get_category_sense_str(res, sizeof(b), b, op->verbose);
pr2serr("%s: %s\n", op_name, b);
goto err_out;
}
@@ -844,9 +911,9 @@ main(int argc, char * argv[])
if (rsoc_buff[0] & 0x4)
printf(" Query task\n");
if (rsoc_buff[0] & 0x2)
- printf(" Target reset\n");
+ printf(" Target reset (obsolete)\n");
if (rsoc_buff[0] & 0x1)
- printf(" Wakeup\n");
+ printf(" Wakeup (obsolete)\n");
if (rsoc_buff[1] & 0x4)
printf(" Query asynchronous event\n");
if (rsoc_buff[1] & 0x2)
@@ -871,9 +938,9 @@ main(int argc, char * argv[])
printf(" QAETS=%d\n", !!(rsoc_buff[7] & 0x4));
printf(" QTSTS=%d\n", !!(rsoc_buff[7] & 0x2));
printf(" ITNRTS=%d\n", !!(rsoc_buff[7] & 0x1));
- printf(" tmf long timeout: %d (100 ms units)\n",
+ printf(" tmf long timeout: %u (100 ms units)\n",
sg_get_unaligned_be32(rsoc_buff + 8));
- printf(" tmf short timeout: %d (100 ms units)\n",
+ printf(" tmf short timeout: %u (100 ms units)\n",
sg_get_unaligned_be32(rsoc_buff + 12));
}
} else if (0 == rep_opts) { /* list all supported operation codes */
diff --git a/src/sg_read_attr.c b/src/sg_read_attr.c
index bd02a493..5083674b 100644
--- a/src/sg_read_attr.c
+++ b/src/sg_read_attr.c
@@ -34,7 +34,7 @@
* and decodes the response. Based on spc5r08.pdf
*/
-static const char * version_str = "1.00 20160207";
+static const char * version_str = "1.01 20160311";
#define MAX_RATTR_BUFF_LEN (1024 * 1024)
#define DEF_RATTR_BUFF_LEN (1024 * 8)
@@ -189,7 +189,7 @@ usage()
pr2serr("Usage: sg_read_attr [--cache] [--element=EA] [--enumerate] "
"[--filter=FL]\n"
" [--first=FAI] [--help] [--hex] [--in=FN] "
- "[--lvn-LVN]\n"
+ "[--lvn=LVN]\n"
" [--maxlen=LEN] [--partition=PN] [--quiet] "
"[--raw]\n"
" [--readonly] [--sa=SA] [--verbose] "
diff --git a/src/sg_vpd.c b/src/sg_vpd.c
index 831b0aaf..3a3cb68b 100644
--- a/src/sg_vpd.c
+++ b/src/sg_vpd.c
@@ -37,7 +37,7 @@
*/
-static const char * version_str = "1.14 20160217"; /* spc5r08 + sbc4r10 */
+static const char * version_str = "1.15 20160312"; /* spc5r08 + sbc4r10 */
/* These structures are duplicates of those of the same name in
@@ -2166,6 +2166,10 @@ decode_3party_copy_vpd(unsigned char * buff, int len, int do_hex, int verbose)
pr2serr("Third-party Copy VPD page length too short=%d\n", len);
return;
}
+ if (3 == do_hex) {
+ dStrHex((const char *)buff, len, -1);
+ return;
+ }
len -= 4;
ucp = buff + 4;
for (k = 0; k < len; k += bump, ucp += bump) {
@@ -2318,8 +2322,8 @@ decode_proto_lu_vpd(unsigned char * buff, int len, int do_hex)
int k, bump, rel_port, desc_len, proto;
unsigned char * ucp;
- if (1 == do_hex) {
- dStrHex((const char *)buff, len, 0);
+ if ((1 == do_hex) || (do_hex > 2)) {
+ dStrHex((const char *)buff, len, (1 == do_hex) ? 1 : -1);
return;
}
if (len < 4) {
@@ -2369,8 +2373,8 @@ decode_proto_port_vpd(unsigned char * buff, int len, int do_hex)
unsigned char * ucp;
unsigned char * pidp;
- if (1 == do_hex) {
- dStrHex((const char *)buff, len, 0);
+ if ((1 == do_hex) || (do_hex > 2)) {
+ dStrHex((const char *)buff, len, (1 == do_hex) ? 1 : -1);
return;
}
if (len < 4) {
@@ -2586,7 +2590,7 @@ decode_b1_vpd(unsigned char * buff, int len, int do_hex, int pdt)
}
}
-/* VPD_LB_PROVISIONING */
+/* VPD_LB_PROVISIONING 0xb2 */
static int
decode_block_lb_prov_vpd(unsigned char * b, int len, const struct opts_t * op)
{
@@ -2727,7 +2731,7 @@ decode_block_dev_char_ext_vpd(unsigned char * b, int len)
printf(" Utilization A: %u\n", sg_get_unaligned_be32(b + 12));
}
-/* VPD_LB_PROTECTION (SSC) [added in ssc5r02a] */
+/* VPD_LB_PROTECTION 0xb5 (SSC) [added in ssc5r02a] */
static void
decode_lb_protection_vpd(unsigned char * buff, int len, int do_hex)
{
@@ -2758,46 +2762,27 @@ decode_lb_protection_vpd(unsigned char * buff, int len, int do_hex)
}
}
-/* VPD_TA_SUPPORTED */
+/* VPD_TA_SUPPORTED 0xb2 */
static int
decode_tapealert_supported_vpd(unsigned char * b, int len)
{
+ int k, mod, div;
+
if (len < 12) {
pr2serr("TapeAlert supported flags length too short=%d\n", len);
return SG_LIB_CAT_MALFORMED;
}
- printf(" Flag01h: %d 02h: %d 03h: %d 04h: %d 05h: %d 06h: %d "
- "07h: %d 08h: %d\n", !!(b[4] & 0x80), !!(b[4] & 0x40),
- !!(b[4] & 0x20), !!(b[4] & 0x10), !!(b[4] & 0x8), !!(b[4] & 0x4),
- !!(b[4] & 0x2), !!(b[4] & 0x1));
- printf(" Flag09h: %d 0ah: %d 0bh: %d 0ch: %d 0dh: %d 0eh: %d "
- "0fh: %d 10h: %d\n", !!(b[5] & 0x80), !!(b[5] & 0x40),
- !!(b[5] & 0x20), !!(b[5] & 0x10), !!(b[5] & 0x8), !!(b[5] & 0x4),
- !!(b[5] & 0x2), !!(b[5] & 0x1));
- printf(" Flag11h: %d 12h: %d 13h: %d 14h: %d 15h: %d 16h: %d "
- "17h: %d 18h: %d\n", !!(b[6] & 0x80), !!(b[6] & 0x40),
- !!(b[6] & 0x20), !!(b[6] & 0x10), !!(b[6] & 0x8), !!(b[6] & 0x4),
- !!(b[6] & 0x2), !!(b[6] & 0x1));
- printf(" Flag19h: %d 1ah: %d 1bh: %d 1ch: %d 1dh: %d 1eh: %d "
- "1fh: %d 20h: %d\n", !!(b[7] & 0x80), !!(b[7] & 0x40),
- !!(b[7] & 0x20), !!(b[7] & 0x10), !!(b[7] & 0x8), !!(b[7] & 0x4),
- !!(b[7] & 0x2), !!(b[7] & 0x1));
- printf(" Flag21h: %d 22h: %d 23h: %d 24h: %d 25h: %d 26h: %d "
- "27h: %d 28h: %d\n", !!(b[8] & 0x80), !!(b[8] & 0x40),
- !!(b[8] & 0x20), !!(b[8] & 0x10), !!(b[8] & 0x8), !!(b[8] & 0x4),
- !!(b[8] & 0x2), !!(b[8] & 0x1));
- printf(" Flag29h: %d 2ah: %d 2bh: %d 2ch: %d 2dh: %d 2eh: %d "
- "2fh: %d 30h: %d\n", !!(b[9] & 0x80), !!(b[9] & 0x40),
- !!(b[9] & 0x20), !!(b[9] & 0x10), !!(b[9] & 0x8), !!(b[9] & 0x4),
- !!(b[9] & 0x2), !!(b[9] & 0x1));
- printf(" Flag31h: %d 32h: %d 33h: %d 34h: %d 35h: %d 36h: %d "
- "37h: %d 38h: %d\n", !!(b[10] & 0x80), !!(b[10] & 0x40),
- !!(b[10] & 0x20), !!(b[10] & 0x10), !!(b[10] & 0x8),
- !!(b[10] & 0x4), !!(b[10] & 0x2), !!(b[10] & 0x1));
- printf(" Flag39h: %d 3ah: %d 3bh: %d 3ch: %d 3dh: %d 3eh: %d "
- "3fh: %d 40h: %d\n", !!(b[11] & 0x80), !!(b[11] & 0x40),
- !!(b[11] & 0x20), !!(b[11] & 0x10), !!(b[11] & 0x8),
- !!(b[11] & 0x4), !!(b[11] & 0x2), !!(b[11] & 0x1));
+ for (k = 1; k < 0x41; ++k) {
+ mod = ((k - 1) % 8);
+ div = (k - 1) / 8;
+ if (0 == mod) {
+ if (div > 0)
+ printf("\n");
+ printf(" Flag%02Xh: %d", k, !! (b[4 + div] & 0x80));
+ } else
+ printf(" %02Xh: %d", k, !! (b[4 + div] & (1 << (7 - mod))));
+ }
+ printf("\n");
return 0;
}
@@ -2913,7 +2898,7 @@ decode_b5_vpd(unsigned char * b, int len, int do_hex, int pdt)
}
}
-/* VPD_ZBC_DEV_CHARS sbc or zbc */
+/* VPD_ZBC_DEV_CHARS 0xb6 sbc or zbc */
static void
decode_zbdc_vpd(unsigned char * b, int len, int do_hex)
{