aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDouglas Gilbert <dgilbert@interlog.com>2017-09-13 03:21:14 +0000
committerDouglas Gilbert <dgilbert@interlog.com>2017-09-13 03:21:14 +0000
commit3e3bb389c5718f595a07cd0a51ccd0162713f44f (patch)
tree970e512680be80718af7369e64f1b375fecff6e1
parentb8ac77b23171336c1ba3ef2bd82acbaee79463fb (diff)
downloadsg3_utils-3e3bb389c5718f595a07cd0a51ccd0162713f44f.tar.gz
sync up to spc5r16 and sbc4r14
git-svn-id: https://svn.bingwo.ca/repos/sg3_utils/trunk@714 6180dd3e-e324-4e3e-922d-17de1ae2f315
-rw-r--r--BSD_LICENSE2
-rw-r--r--ChangeLog23
-rw-r--r--doc/sg3_utils.84
-rw-r--r--doc/sg_get_lba_status.879
-rw-r--r--doc/sg_inq.88
-rw-r--r--doc/sg_ses.827
-rw-r--r--include/sg_cmds_extra.h17
-rw-r--r--include/sg_lib.h25
-rw-r--r--include/sg_lib_data.h3
-rw-r--r--lib/sg_cmds_extra.c91
-rw-r--r--lib/sg_lib.c96
-rw-r--r--lib/sg_lib_data.c40
-rw-r--r--sg3_utils.spec2
-rw-r--r--src/sg_get_lba_status.c181
-rw-r--r--src/sg_inq.c101
-rw-r--r--src/sg_inq_data.c16
-rw-r--r--src/sg_logs.c239
-rw-r--r--src/sg_ses.c140
-rw-r--r--src/sg_vpd.c124
19 files changed, 1040 insertions, 178 deletions
diff --git a/BSD_LICENSE b/BSD_LICENSE
index 98a89232..75de7f13 100644
--- a/BSD_LICENSE
+++ b/BSD_LICENSE
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1999-2016 Douglas Gilbert.
+ * Copyright (c) 1999-2017 Douglas Gilbert.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/ChangeLog b/ChangeLog
index 8c4d2da1..9ac2b4b4 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 sg3_utils-1.43 [20160914] [svn: r713]
+Changelog for sg3_utils-1.43 [20170912] [svn: r713]
- sg_bg_ctl: new Background control command (spc4r08)
- sg_senddiag: add --timeout=SEC option
- sg_sanitize: add --timeout=SEC option
@@ -14,6 +14,11 @@ Changelog for sg3_utils-1.43 [20160914] [svn: r713]
- expand join debug code
- allow multiple --clear=, --get= and --set= options
- allow individual index ranges (e.g. --index=3,5)
+ - allow --index=IIA with -ee to enumerate only fields
+ belonging to element type IIA
+ - add 'offset_temp' and 'rqst_override' to temperature
+ sensor element type
+ - sync to ses4r01
- sg_luns: resync with drafts (sam6r02+spc5r10)
- remove undocumented test "W" format
- accept and output on request "quad dashed" format
@@ -24,8 +29,10 @@ Changelog for sg3_utils-1.43 [20160914] [svn: r713]
Service buffer information lpages for tape
- add min+max 'mounted' temperature and rel. humidity
fields to Environmental reporting lpage (spc5r10)
+ - add zoned block device statistics lpage (zbc2r?,
+ 16-264r4)
- sg_inq: fix potential unbounded loop in --export
- - update version descriptor list to 20160510
+ - update version descriptor list to 20170114
- sg_inq+sg_vpd: update Extended inquiry data vpd
page (spc5r09)
- add --force option to bypass checking supported
@@ -39,13 +46,23 @@ Changelog for sg3_utils-1.43 [20160914] [svn: r713]
- sg_zone: fix debug cdb naming
- sg_opcode: add '--enumerate' and '--pdt=' options
- sg_raw: add '--enumerate' option
+ - sg_get_lba_status: add --report-type= option (sbc4r12)
+ - add support for 32 byte cdb variant (sbc4r14)
+ - add support for --element-id= and --scan-len=
+ options (sbc4r14)
+ - decode response's RTP and two more provisioning
+ statuses and the additional status (sbc4r12)
+ - decode completion condition (sbc4r14)
- sg_lib: add SSC maintenance in/out sa names
- add read buffer(16) command mode names
- add sg_decode_transportid_str()
- add sg_get_llnum_nomult()
+ - add sg_ll_get_lba_status16()
+ - add sg_ll_get_lba_status32()
- implement 'format' argument in dStrHexStr()
- add Microcode activation sense descriptor spc5r10
- - sg_lib_data: sync asc/ascq codes with T10 20160425
+ - add sg_get_sfs_name() for spc5r11 (Feature sets)
+ - sg_lib_data: sync asc/ascq codes with T10 20170114
- add write scattered (16+32) cdb names sbc4r11
- sg_cmds_extra: expand sg_ll_ata_pt() to send new
Ata pass-through(32) command (sat4r05)
diff --git a/doc/sg3_utils.8 b/doc/sg3_utils.8
index 5cdc3cc1..3ca6f2c3 100644
--- a/doc/sg3_utils.8
+++ b/doc/sg3_utils.8
@@ -1,4 +1,4 @@
-.TH SG3_UTILS "8" "July 2016" "sg3_utils\-1.43" SG3_UTILS
+.TH SG3_UTILS "8" "September 2017" "sg3_utils\-1.43" SG3_UTILS
.SH NAME
sg3_utils \- a package of utilities for sending SCSI commands
.SH SYNOPSIS
@@ -546,7 +546,7 @@ CREDITS file and individual source files (in the 'src' directory).
.SH "REPORTING BUGS"
Report bugs to <dgilbert at interlog dot com>.
.SH COPYRIGHT
-Copyright \(co 1999\-2016 Douglas Gilbert
+Copyright \(co 1999\-2017 Douglas Gilbert
.br
Some utilities are distributed under a GPL version 2 license while
others, usually more recent ones, are under a FreeBSD license. The files
diff --git a/doc/sg_get_lba_status.8 b/doc/sg_get_lba_status.8
index 30f179a2..cada6b49 100644
--- a/doc/sg_get_lba_status.8
+++ b/doc/sg_get_lba_status.8
@@ -1,39 +1,60 @@
-.TH SG_GET_LBA_STATUS "8" "May 2014" "sg3_utils\-1.39" SG3_UTILS
+.TH SG_GET_LBA_STATUS "8" "September 2017" "sg3_utils\-1.43" SG3_UTILS
.SH NAME
-sg_get_lba_status \- send SCSI GET LBA STATUS command
+sg_get_lba_status \- send SCSI GET LBA STATUS(16 or 32) command
.SH SYNOPSIS
.B sg_get_lba_status
-[\fI\-\-brief\fR] [\fI\-\-help\fR] [\fI\-\-hex\fR] [\fI\-\-lba=LBA\fR]
-[\fI\-\-maxlen=LEN\fR] [\fI\-\-raw\fR] [\fI\-\-readonly\fR]
-[\fI\-\-verbose\fR] [\fI\-\-version\fR] \fIDEVICE\fR
+[\fI\-\-16\fR] [\fI\-\-32\fR] [\fI\-\-brief\fR] [\fI\-\-element-id=EI\fR]
+[\fI\-\-help\fR] [\fI\-\-hex\fR] [\fI\-\-lba=LBA\fR] [\fI\-\-maxlen=LEN\fR]
+[\fI\-\-raw\fR] [\fI\-\-readonly\fR] [\fI\-\-report\-type=RT\fR]
+[\fI\-\-scan-len=SL\fR] [\fI\-\-verbose\fR] [\fI\-\-version\fR] \fIDEVICE\fR
.SH DESCRIPTION
.\" Add any additional description here
.PP
-Send the SCSI GET LBA STATUS command to the \fIDEVICE\fR and outputs the
-response. This command was introduced in (draft) SBC\-3 revision 20 and
-devices that support logical block provisioning should support this command.
+Send the SCSI GET LBA STATUS(16) or GET LBA STATUS(32) command to the
+\fIDEVICE\fR and outputs the response. The 16 byte command variant was
+introduced in (draft) SBC\-3 revision 20 and devices that support logical
+block provisioning should support this command. The GET LBA STATUS(32)
+command was added in (draft) SBC\-4 revision 14.
.PP
The default action is to decode the response into one LBA status descriptor
per line output to stdout. The descriptor LBA is output in hex (prefixed
by '0x') and the number of blocks is output in decimal followed by the
-provisioning status in decimal. The provisioning status can be in the
-range 0 to 15 of which only 0 (mapped), 1 (unmapped) and 2 (anchored) are
-used currently. The amount of output can be reduced by the \fI\-\-brief\fR
-option.
+provisioning status and additional status in decimal. The provisioning status
+can be in the range 0 to 15 of which only 0 (mapped or unknown), 1 (unmapped),
+2 (anchored), 3 (mapped) and 4 (unknown) are used currently. The amount of
+output can be reduced by the \fI\-\-brief\fR option.
.SH OPTIONS
Arguments to long options are mandatory for short options as well.
.TP
+\fB\-S\fR, \fB\-\-16\fR
+send SCSI GET LBA STATUS(16) command which is the 16 byte variant. In the
+absence of the \fI\-\-16\fR or the \fI\-\-32\fR options the SCSI GET LBA
+STATUS(16) command is sent. If both \fI\-\-16\fR and the \fI\-\-32\fR options
+are given then the GET LBA STATUS(16) command is sent.
+.TP
+\fB\-T\fR, \fB\-\-32\fR
+send SCSI GET LBA STATUS(32) command which is the 32 byte variant. When
+given together with the \fI\-\-16\fR option then this option is ignored (so
+the GET LBA STATUS(16) command is sent).
+.TP
\fB\-b\fR, \fB\-\-brief\fR
when use once then one LBA status descriptor per line is output to stdout.
Each line has this
-format: "0x<descriptor_LBA> 0x<blocks> <provisioning_status>". So the
-descriptor's starting LBA and number of blocks are output in hex and the
-provisioning status in decimal. When used twice (e.g. '\-bb' or '\-\-brief
-\-\-brief') then the provisioning status of the given \fILBA\fR (or LBA 0
-if the \fI\-\-lba\fR option is not given) is output to stdout. A check is
-made that the given \fILBA\fR lies in the range of the first returned LBA
-status descriptor (as it should according to SBC\-3 revision 20) and
-warnings are sent to stderr if it doesn't.
+format: "0x<descriptor_LBA> 0x<blocks> <provisioning_status>
+<additional_status>". So the descriptor's starting LBA and number of blocks
+are output in hex while the provisioning status and additional status are
+in decimal. When used twice (e.g. '\-bb' or '\-\-brief \-\-brief') then the
+provisioning status of the given \fILBA\fR (or LBA 0 if the \fI\-\-lba\fR
+option is not given) is output to stdout. A check is made that the given
+\fILBA\fR lies in the range of the first returned LBA status descriptor (as
+it should according to SBC\-3 revision 20) and warnings are sent to stderr
+if it doesn't.
+.TP
+\fB\-e\fR, \fB\-\-element\-id\fR=\fIEI\fR
+where \fIEI\fR is the element identifier of the physical element for which
+the LBAs shall be reported based on the value in the report type field (i.e.
+\fIRT\fR). This option is only active with the SCSI GET LBA STATUS(32)
+command (i.e. it is ignored if the GET LBA STATUS(16) command is sent).
.TP
\fB\-h\fR, \fB\-\-help\fR
output the usage message then exit.
@@ -59,6 +80,20 @@ output response in binary (to stdout).
open the \fIDEVICE\fR read\-only (e.g. in Unix with the O_RDONLY flag).
The default is to open it read\-write.
.TP
+\fB\-t\fR, \fB\-\-report\-type\fR=\fIRT\fR
+where \fIRT\fR is 0 for report all LBAs; 1 for report LBAs using non\-zero
+provisioning status; 2 for report LBAs that are mapped; 3 for report LBAs
+that are de-allocated; 4 for report LBAs that are anchored; 5 for report
+LBAs that may return an unrecovered error. The REPORT TYPE field was added
+to the GET LBA STATUS cdb in sbc4r12.
+.TP
+\fB\-s\fR, \fB\-\-scan\-len\fR=\fISL\fR
+where \fISL\fR is the scan length which is the maximum number of contiguous
+logical blocks to be scanned for logical blocks that meet the given report
+type (i.e. \fIRT\fR). This option is only active with the SCSI GET LBA
+STATUS(32) command (i.e. it is ignored if the GET LBA STATUS(16) command is
+sent).
+.TP
\fB\-v\fR, \fB\-\-verbose\fR
increase the level of verbosity, (i.e. debug output). Additional output
caused by this option is sent to stderr.
@@ -70,7 +105,7 @@ In SBC\-3 revision 25 the calculation associated with the Parameter Data
Length field in the response was modified. Prior to that the byte offset
was 8 and in revision 25 it was changed to 4.
.PP
-For a discussion of logical block provisioning see section 4.7 of sbc3r29.pdf
+For a discussion of logical block provisioning see section 4.7 of sbc4r14.pdf
at http://www.t10.org (or the corresponding section of a later draft).
.SH EXIT STATUS
The exit status of sg_get_lba_status is 0 when it is successful. Otherwise
@@ -80,7 +115,7 @@ Written by Douglas Gilbert.
.SH "REPORTING BUGS"
Report bugs to <dgilbert at interlog dot com>.
.SH COPYRIGHT
-Copyright \(co 2009\-2014 Douglas Gilbert
+Copyright \(co 2009\-2017 Douglas Gilbert
.br
This software is distributed under a FreeBSD license. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
diff --git a/doc/sg_inq.8 b/doc/sg_inq.8
index a08fe597..e123ce6e 100644
--- a/doc/sg_inq.8
+++ b/doc/sg_inq.8
@@ -1,4 +1,4 @@
-.TH SG_INQ "8" "April 2016" "sg3_utils\-1.43" SG3_UTILS
+.TH SG_INQ "8" "September 2017" "sg3_utils\-1.43" SG3_UTILS
.SH NAME
sg_inq \- issue SCSI INQUIRY command and/or decode its response
.SH SYNOPSIS
@@ -207,7 +207,8 @@ print out version string then exit.
set the Enable Vital Product Data (EVPD) bit (defaults to clear(0)). Used in
conjunction with the \fI\-\-page=PG\fR option where \fIPG\fR specifies the
VPD page number to query. If the \fI\-\-page=PG\fR is not given then \fIPG\fR
-defaults to zero which is the "Supported VPD pages" VPD page.
+defaults to zero which is the "Supported VPD pages" VPD page. A more up to
+date decoding of VPD pages can be found in the sg_vpd(8) utility.
.SH NOTES
Some devices with weak SCSI command set implementations lock up when
they receive commands they don't understand (or even response lengths
@@ -447,4 +448,5 @@ Copyright \(co 2001\-2016 Douglas Gilbert
This software is distributed under the GPL version 2. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
.SH "SEE ALSO"
-.B sg_opcodes(8), sg_vpd(8), sdparm(8), hdparm(8), sgdiag(scsirastools)
+.B sg_opcodes(8), sg_vpd(8), sg_logs(8), sg_modes(8), sdparm(8), hdparm(8),
+.B sgdiag(scsirastools)
diff --git a/doc/sg_ses.8 b/doc/sg_ses.8
index dfc42b21..aeef8f66 100644
--- a/doc/sg_ses.8
+++ b/doc/sg_ses.8
@@ -1,4 +1,4 @@
-.TH SG_SES "8" "June 2016" "sg3_utils\-1.43" SG3_UTILS
+.TH SG_SES "8" "September 2017" "sg3_utils\-1.43" SG3_UTILS
.SH NAME
sg_ses \- access a SCSI Enclosure Services (SES) device
.SH SYNOPSIS
@@ -20,7 +20,8 @@ sg_ses \- access a SCSI Enclosure Services (SES) device
\fIDEVICE\fR
.PP
.B sg_ses
-[\fI\-\-enumerate\fR] [\fI\-\-list\fR] [\fI\-\-help\fR] [\fI\-\-version\fR]
+[\fI\-\-enumerate\fR] [\fI\-\-index=IIA\fR] [\fI\-\-list\fR] [\fI\-\-help\fR]
+[\fI\-\-version\fR]
.SH DESCRIPTION
.\" Add any additional description here
.PP
@@ -35,10 +36,10 @@ response.
If the \fIDEVICE\fR argument is given with no options then the names of all
diagnostic pages supported are listed. Most, but not necessarily all, of the
named diagnostic pages are defined in the SES standards and drafts. The most
-recent reference for this utility is the draft SCSI Enclosure Services 3
-document T10/2149\-D Revision 13 at http://www.t10.org . Existing standards
-for SES and SES\-2 are ANSI INCITS 305\-1998 and ANSI INCITS 448\-2008
-respectively.
+recent reference for this utility is the draft SCSI Enclosure Services 4
+document T10/BSR INCITS 555 Revision 1 at http://www.t10.org . Existing
+standards for SES, SES\-2 and SES\-3 are ANSI INCITS 305\-1998 and ANSI
+INCITS 448\-2008 and ANSI INCITS 518\-2017 respectively.
.PP
The first form shown in the synopsis is for fetching and decoding pages
or fields from the SES \fIDEVICE\fR. Alternatively a fetched page may be
@@ -145,10 +146,16 @@ no effect. It is recommended that HP JBOD users set --eiioe=auto .
.TP
\fB\-e\fR, \fB\-\-enumerate\fR
enumerate all known page names and SES elements when this option is given
-once. If \fI\-\-enumerate\fR is given twice, then the recognised acronyms for
-the \fI\-\-clear=STR\fR, \fI\-\-get=STR\fR and \fI\-\-set=STR\fR options are
+once.
+.br
+If \fI\-\-enumerate\fR is given twice, then the recognised acronyms for the
+\fI\-\-clear=STR\fR, \fI\-\-get=STR\fR and \fI\-\-set=STR\fR options are
listed. The utility exits after listing this information (so most other
-options and \fIDEVICE\fR are ignored).
+options and \fIDEVICE\fR are ignored). Since there are many acronyms for
+the Enclosure Control/Status page then the output can be further restricted
+by giving the \fI\-\-index=IIA\fR option (e.g. "sg_ses \-ee \-I ts" to only
+show the acronyms associated with the Enclosure Control/Status page's
+Temperature Sensor Element Type).
.TP
\fB\-f\fR, \fB\-\-filter\fR
cuts down on the amount of output from the Enclosure Status page and the
@@ -613,7 +620,7 @@ Written by Douglas Gilbert.
.SH "REPORTING BUGS"
Report bugs to <dgilbert at interlog dot com>.
.SH COPYRIGHT
-Copyright \(co 2004\-2016 Douglas Gilbert
+Copyright \(co 2004\-2017 Douglas Gilbert
.br
This software is distributed under a FreeBSD license. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
diff --git a/include/sg_cmds_extra.h b/include/sg_cmds_extra.h
index b348084a..d46db1eb 100644
--- a/include/sg_cmds_extra.h
+++ b/include/sg_cmds_extra.h
@@ -2,7 +2,7 @@
#define SG_CMDS_EXTRA_H
/*
- * Copyright (c) 2004-2016 Douglas Gilbert.
+ * Copyright (c) 2004-2017 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.
@@ -61,12 +61,21 @@ int sg_ll_format_unit2(int sg_fd, int fmtpinfo, int longlist, int fmtdata,
int timeout_secs, void * paramp, int param_len,
int noisy, int verbose);
-/* Invokes a SCSI GET LBA STATUS command (SBC). Returns 0 -> success,
- * SG_LIB_CAT_INVALID_OP -> GET LBA STATUS not supported,
+/* Invokes a SCSI GET LBA STATUS(16) or GET LBA STATUS(32) command (SBC).
+ * Returns 0 -> success,
+ * SG_LIB_CAT_INVALID_OP -> GET LBA STATUS(16 or 32) not supported,
* SG_LIB_CAT_ILLEGAL_REQ -> bad field in cdb, SG_LIB_CAT_ABORTED_COMMAND,
- * SG_LIB_CAT_NOT_READY -> device not ready, -1 -> other failure */
+ * SG_LIB_CAT_NOT_READY -> device not ready, -1 -> other failure.
+ * sg_ll_get_lba_status() calls the 16 byte variant with rt=0 . */
int sg_ll_get_lba_status(int sg_fd, uint64_t start_llba, void * resp,
int alloc_len, int noisy, int verbose);
+int sg_ll_get_lba_status16(int sg_fd, uint64_t start_llba, uint8_t rt,
+ void * resp, int alloc_len, int noisy,
+ int verbose);
+int sg_ll_get_lba_status32(int sg_fd, uint64_t start_llba, uint32_t scan_len,
+ uint32_t element_id, uint8_t rt,
+ void * resp, int alloc_len, int noisy,
+ int verbose);
/* Invokes a SCSI PERSISTENT RESERVE IN command (SPC). Returns 0
* when successful, SG_LIB_CAT_INVALID_OP if command not supported,
diff --git a/include/sg_lib.h b/include/sg_lib.h
index 5829819c..9b451128 100644
--- a/include/sg_lib.h
+++ b/include/sg_lib.h
@@ -2,7 +2,7 @@
#define SG_LIB_H
/*
- * Copyright (c) 2004-2016 Douglas Gilbert.
+ * Copyright (c) 2004-2017 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.
@@ -109,8 +109,15 @@ extern "C" {
#define TPROTO_PCIE 0xb /* includes NVMe */
#define TPROTO_NONE 0xf
+/* SCSI Feature Sets (sfs) */
+#define SCSI_FS_SPC_DISCOVERY_2016 0x1
+#define SCSI_FS_SBC_BASE_2010 0x102
+#define SCSI_FS_SBC_BASE_2016 0x101
+#define SCSI_FS_SBC_BASIC_PROV_2016 0x103
+#define SCSI_FS_SBC_DRIVE_MAINT_2016 0x104
-/* The format of the version string is like this: "1.87 20130731" */
+
+/* The format of the version string is like this: "2.26 20170906" */
const char * sg_lib_version();
/* Returns length of SCSI command given the opcode (first byte).
@@ -264,6 +271,20 @@ const char * sg_get_desig_code_set_str(int val);
* otherwise returns NULL. */
const char * sg_get_desig_assoc_str(int val);
+/* Yield SCSI Feature Set (sfs) string. When 'peri_type' is < -1 (or > 31)
+ * returns pointer to string (same as 'buff') associated with 'sfs_code'.
+ * When 'peri_type' is between -1 (for SPC) and 31 (inclusive) then a match
+ * on both 'sfs_code' and 'peri_type' is required. If a match is found and
+ * 'foundp' is not NULL then the bool it points to is set to true; else if
+ * 'foundp' is not NULL then the bool it points to is set to false.
+ * Example:
+ * char b[64];
+ * ...
+ * printf("%s\n", sg_get_sfs_str(sfs_code, -2, sizeof(b), b, NULL, 0));
+ */
+const char * sg_get_sfs_str(uint16_t sfs_code, int peri_type, int buff_len,
+ char * buff, bool * foundp, int verbose);
+
extern FILE * sg_warnings_strm;
void sg_set_warnings_strm(FILE * warnings_strm);
diff --git a/include/sg_lib_data.h b/include/sg_lib_data.h
index a8a42f3a..86afd6e4 100644
--- a/include/sg_lib_data.h
+++ b/include/sg_lib_data.h
@@ -2,7 +2,7 @@
#define SG_LIB_DATA_H
/*
- * Copyright (c) 2007-2016 Douglas Gilbert.
+ * Copyright (c) 2007-2017 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.
@@ -92,6 +92,7 @@ extern struct sg_lib_value_name_t sg_lib_read_attr_arr[];
extern struct sg_lib_value_name_t sg_lib_read_pos_arr[];
extern struct sg_lib_asc_ascq_range_t sg_lib_asc_ascq_range[];
extern struct sg_lib_asc_ascq_t sg_lib_asc_ascq[];
+extern struct sg_lib_value_name_t sg_lib_scsi_feature_sets[];
extern const char * sg_lib_sense_key_desc[];
extern const char * sg_lib_pdt_strs[];
extern const char * sg_lib_transport_proto_strs[];
diff --git a/lib/sg_cmds_extra.c b/lib/sg_cmds_extra.c
index dd5430ac..1e8b88e0 100644
--- a/lib/sg_cmds_extra.c
+++ b/lib/sg_cmds_extra.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1999-2016 Douglas Gilbert.
+ * Copyright (c) 1999-2017 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.
@@ -82,7 +82,8 @@
#define WRITE_BUFFER_CMD 0x3b
#define WRITE_BUFFER_CMDLEN 10
-#define GET_LBA_STATUS_SA 0x12
+#define GET_LBA_STATUS16_SA 0x12
+#define GET_LBA_STATUS32_SA 0x12
#define READ_LONG_16_SA 0x11
#define READ_MEDIA_SERIAL_NUM_SA 0x1
#define REPORT_IDENTIFYING_INFORMATION_SA 0x5
@@ -123,13 +124,13 @@ create_pt_obj(const char * cname)
}
-/* Invokes a SCSI GET LBA STATUS command (SBC). Returns 0 -> success,
+/* Invokes a SCSI GET LBA STATUS(16) command (SBC). Returns 0 -> success,
* various SG_LIB_CAT_* positive values or -1 -> other errors */
int
-sg_ll_get_lba_status(int sg_fd, uint64_t start_llba, void * resp,
- int alloc_len, int noisy, int verbose)
+sg_ll_get_lba_status16(int sg_fd, uint64_t start_llba, uint8_t rt,
+ void * resp, int alloc_len, int noisy, int verbose)
{
- static const char * const cdb_name_s = "get LBA status";
+ static const char * const cdb_name_s = "Get LBA status(16)";
int k, res, sense_cat, ret;
unsigned char getLbaStatCmd[SERVICE_ACTION_IN_16_CMDLEN];
unsigned char sense_b[SENSE_BUFF_LEN];
@@ -137,10 +138,11 @@ sg_ll_get_lba_status(int sg_fd, uint64_t start_llba, void * resp,
memset(getLbaStatCmd, 0, sizeof(getLbaStatCmd));
getLbaStatCmd[0] = SERVICE_ACTION_IN_16_CMD;
- getLbaStatCmd[1] = GET_LBA_STATUS_SA;
+ getLbaStatCmd[1] = GET_LBA_STATUS16_SA;
sg_put_unaligned_be64(start_llba, getLbaStatCmd + 2);
sg_put_unaligned_be32((uint32_t)alloc_len, getLbaStatCmd + 10);
+ getLbaStatCmd[14] = rt;
if (verbose) {
pr2ws(" %s cdb: ", cdb_name_s);
for (k = 0; k < SERVICE_ACTION_IN_16_CMDLEN; ++k)
@@ -186,6 +188,81 @@ sg_ll_get_lba_status(int sg_fd, uint64_t start_llba, void * resp,
}
int
+sg_ll_get_lba_status(int sg_fd, uint64_t start_llba, void * resp,
+ int alloc_len, int noisy, int verbose)
+{
+ return sg_ll_get_lba_status16(sg_fd, start_llba, /* rt = */ 0x0, resp,
+ alloc_len, noisy, verbose);
+}
+
+#define GLS32_CMD_LEN 32
+
+int
+sg_ll_get_lba_status32(int sg_fd, uint64_t start_llba, uint32_t scan_len,
+ uint32_t element_id, uint8_t rt,
+ void * resp, int alloc_len, int noisy,
+ int verbose)
+{
+ static const char * const cdb_name_s = "Get LBA status(32)";
+ int k, res, sense_cat, ret;
+ unsigned char gls32_cmd[GLS32_CMD_LEN];
+ unsigned char sense_b[SENSE_BUFF_LEN];
+ struct sg_pt_base * ptvp;
+
+ memset(gls32_cmd, 0, sizeof(gls32_cmd));
+ gls32_cmd[0] = SG_VARIABLE_LENGTH_CMD;
+ gls32_cmd[7] = GLS32_CMD_LEN - 8;
+ sg_put_unaligned_be16((uint16_t)GET_LBA_STATUS32_SA, gls32_cmd + 8);
+ gls32_cmd[10] = rt;
+ sg_put_unaligned_be64(start_llba, gls32_cmd + 12);
+ sg_put_unaligned_be32(scan_len, gls32_cmd + 20);
+ sg_put_unaligned_be32(element_id, gls32_cmd + 24);
+ sg_put_unaligned_be32((uint32_t)alloc_len, gls32_cmd + 28);
+ if (verbose) {
+ pr2ws(" %s cdb: ", cdb_name_s);
+ for (k = 0; k < GLS32_CMD_LEN; ++k)
+ pr2ws("%02x ", gls32_cmd[k]);
+ pr2ws("\n");
+ }
+
+ if (NULL == ((ptvp = create_pt_obj(cdb_name_s))))
+ return -1;
+ set_scsi_pt_cdb(ptvp, gls32_cmd, sizeof(gls32_cmd));
+ set_scsi_pt_sense(ptvp, sense_b, sizeof(sense_b));
+ set_scsi_pt_data_in(ptvp, (unsigned char *)resp, alloc_len);
+ res = do_scsi_pt(ptvp, sg_fd, DEF_PT_TIMEOUT, verbose);
+ ret = sg_cmds_process_resp(ptvp, cdb_name_s, res, alloc_len, sense_b,
+ noisy, verbose, &sense_cat);
+ if (-1 == ret)
+ ;
+ else if (-2 == ret) {
+ switch (sense_cat) {
+ case SG_LIB_CAT_RECOVERED:
+ case SG_LIB_CAT_NO_SENSE:
+ ret = 0;
+ break;
+ default:
+ ret = sense_cat;
+ break;
+ }
+ } else {
+ if ((verbose > 2) && (ret > 0)) {
+ pr2ws(" %s: response\n", cdb_name_s);
+ if (3 == verbose) {
+ pr2ws("%s:\n", (ret > 256 ? ", first 256 bytes" : ""));
+ dStrHexErr((const char *)resp, (ret > 256 ? 256 : ret), -1);
+ } else {
+ pr2ws(":\n");
+ dStrHexErr((const char *)resp, ret, 0);
+ }
+ }
+ ret = 0;
+ }
+ destruct_scsi_pt_obj(ptvp);
+ return ret;
+}
+
+int
sg_ll_report_tgt_prt_grp(int sg_fd, void * resp, int mx_resp_len,
int noisy, int verbose)
{
diff --git a/lib/sg_lib.c b/lib/sg_lib.c
index 4f8eaf85..2c595ec4 100644
--- a/lib/sg_lib.c
+++ b/lib/sg_lib.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1999-2016 Douglas Gilbert.
+ * Copyright (c) 1999-2017 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.
@@ -39,6 +39,7 @@
#include "sg_lib.h"
#include "sg_lib_data.h"
#include "sg_unaligned.h"
+#include "sg_pr2serr.h"
#ifdef HAVE_CONFIG_H
#include "config.h"
@@ -2088,7 +2089,7 @@ sg_vpd_dev_id_iter(const unsigned char * initial_desig_desc, int page_len,
static const char * bad_sense_cat = "Bad sense category";
-/* Yield string associated with sense++ category. Returns 'buff' (or pointer
+/* Yield string associated with sense category. Returns 'buff' (or pointer
* to "Bad sense category" if 'buff' is NULL). If sense_cat unknown then
* yield "Sense category: <sense_cat>" string. */
const char *
@@ -2246,6 +2247,97 @@ sg_get_category_sense_str(int sense_cat, int buff_len, char * buff,
return buff;
}
+static const char * sg_sfs_spc_reserved = "SPC reserved";
+static const char * sg_sfs_sbc_reserved = "SBC reserved";
+static const char * sg_sfs_ssc_reserved = "SSC reserved";
+static const char * sg_sfs_zbc_reserved = "ZBC reserved";
+static const char * sg_sfs_reserved = "Reserved";
+
+/* Yield SCSI Feature Set (sfs) string. When 'peri_type' is < -1 (or > 31)
+ * returns pointer to string (same as 'buff') associated with 'sfs_code'.
+ * When 'peri_type' is between -1 (for SPC) and 31 (inclusive) then a match
+ * on both 'sfs_code' and 'peri_type' is required. If a match is found and
+ * 'foundp' is not NULL then the bool it points to is set to true; else if
+ * 'foundp' is not NULL then the bool it points to is set to false.
+ * Example:
+ * char b[64];
+ * ...
+ * printf("%s\n", sg_get_sfs_str(sfs_code, -2, sizeof(b), b, NULL, 0));
+ */
+const char *
+sg_get_sfs_str(uint16_t sfs_code, int peri_type, int buff_len, char * buff,
+ bool * foundp, int verbose)
+{
+ const struct sg_lib_value_name_t * vnp = NULL;
+ int n = 0;
+ int my_pdt;
+
+ if ((NULL == buff) || (buff_len < 1)) {
+ if (foundp)
+ *foundp = false;
+ return NULL;
+ } else if (1 == buff_len) {
+ buff[0] = '\0';
+ if (foundp)
+ *foundp = false;
+ return NULL;
+ }
+ my_pdt = ((peri_type < -1) || (peri_type > 0x1f)) ? -2 : peri_type;
+ vnp = get_value_name(sg_lib_scsi_feature_sets, sfs_code, my_pdt);
+ if (vnp && (-2 != my_pdt)) {
+ if (peri_type != vnp->peri_dev_type)
+ vnp = NULL; /* shouldn't really happen */
+ }
+ if (foundp)
+ *foundp = vnp ? true : false;
+ if (sfs_code < 0x100) { /* SPC Feature Sets */
+ if (vnp) {
+ if (verbose)
+ n += scnpr(buff, buff_len, "SPC %s", vnp->name);
+ else
+ n += scnpr(buff, buff_len, "%s", vnp->name);
+ } else
+ n += scnpr(buff, buff_len, "%s", sg_sfs_spc_reserved);
+ } else if (sfs_code < 0x200) { /* SBC Feature Sets */
+ if (vnp) {
+ if (verbose)
+ n += scnpr(buff, buff_len, "SBC %s", vnp->name);
+ else
+ n += scnpr(buff, buff_len, "%s", vnp->name);
+ } else
+ n += scnpr(buff, buff_len, "%s", sg_sfs_sbc_reserved);
+ } else if (sfs_code < 0x300) { /* SSC Feature Sets */
+ if (vnp) {
+ if (verbose)
+ n += scnpr(buff, buff_len, "SSC %s", vnp->name);
+ else
+ n += scnpr(buff, buff_len, "%s", vnp->name);
+ } else
+ n += scnpr(buff, buff_len, "%s", sg_sfs_ssc_reserved);
+ } else if (sfs_code < 0x400) { /* ZBC Feature Sets */
+ if (vnp) {
+ if (verbose)
+ n += scnpr(buff, buff_len, "ZBC %s", vnp->name);
+ else
+ n += scnpr(buff, buff_len, "%s", vnp->name);
+ } else
+ n += scnpr(buff, buff_len, "%s", sg_sfs_zbc_reserved);
+ } else { /* Other SCSI Feature Sets */
+ if (vnp) {
+ if (verbose)
+ n += scnpr(buff, buff_len, "[unrecognized PDT] %s",
+ vnp->name);
+ else
+ n += scnpr(buff, buff_len, "%s", vnp->name);
+ } else
+ n += scnpr(buff, buff_len, "%s", sg_sfs_reserved);
+
+ }
+ if (verbose > 4)
+ pr2serr("%s: length of returned string (n) %d\n", __func__, n);
+ return buff;
+}
+
/* safe_strerror() contributed by Clayton Weaver <cgweav at email dot com>
* Allows for situation in which strerror() is given a wild value (or the
* C library is incomplete) and returns NULL. Still not thread safe.
diff --git a/lib/sg_lib_data.c b/lib/sg_lib_data.c
index d4c2cd86..29ded316 100644
--- a/lib/sg_lib_data.c
+++ b/lib/sg_lib_data.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2007-2016 Douglas Gilbert.
+ * Copyright (c) 2007-2017 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.
@@ -17,7 +17,7 @@
#endif
-const char * sg_lib_version_str = "2.25 20160630";/* spc5r10, sbc4r11 */
+const char * sg_lib_version_str = "2.26 20170910";/* spc5r16, sbc4r14 */
/* indexed by pdt; those that map to own index do not decay */
@@ -346,18 +346,23 @@ struct sg_lib_value_name_t sg_lib_serv_out12_arr[] = {
/* Service action in(16) [0x9e] service actions */
struct sg_lib_value_name_t sg_lib_serv_in16_arr[] = {
+ {0xf, 0, "Receive binding report"}, /* added spc5r11 */
{0x10, 0, "Read capacity(16)"},
{0x11, 0, "Read long(16)"}, /* obsolete in SBC-4 r7 */
- {0x12, 0, "Get LBA status"},
+ {0x12, 0, "Get LBA status(16)"}, /* 32 byte variant added in sbc4r14 */
{0x13, 0, "Report referrals"},
{0x14, 0, "Stream control"},
{0x15, 0, "Background control"},
{0x16, 0, "Get stream status"},
+ {0x17, 0, "Get physical element status"}, /* added sbc4r13 */
+ {0x18, 0, "Remove element and truncate"}, /* added sbc4r13 */
{0xffff, 0, NULL},
};
/* Service action out(16) [0x9f] service actions */
struct sg_lib_value_name_t sg_lib_serv_out16_arr[] = {
+ {0x0b, 0, "Test bind"}, /* added spc5r13 */
+ {0x0c, 0, "Prepare bind report"}, /* added spc5r11 */
{0x0d, 0, "Set affiliation"},
{0x0e, 0, "Bind"},
{0x0f, 0, "Unbind"},
@@ -438,12 +443,13 @@ struct sg_lib_value_name_t sg_lib_variable_length_arr[] = {
{0xb, 0, "Write(32)"},
{0xc, 0, "Write and verify(32)"},
{0xd, 0, "Write same(32)"},
- {0xe, 0, "Orwrite(32)"}, /* added sbc3r25 */
- {0xf, 0, "Atomic write(32)"}, /* added sbc4r02 */
- {0x10, 0, "Write stream(32)"}, /* added sbc4r07 */
- {0x11, 0, "Write scattered(32)"}, /* added sbc4r11 */
+ {0xe, 0, "Orwrite(32)"}, /* added sbc3r25 */
+ {0xf, 0, "Atomic write(32)"}, /* added sbc4r02 */
+ {0x10, 0, "Write stream(32)"}, /* added sbc4r07 */
+ {0x11, 0, "Write scattered(32)"}, /* added sbc4r11 */
+ {0x12, 0, "Get LBA status(32)"}, /* added sbc4r14 */
{0x1800, 0, "Receive credential"},
- {0x1ff0, 0, "ATA pass-through(32)"}, /* added sat4r05 */
+ {0x1ff0, 0, "ATA pass-through(32)"},/* added sat4r05 */
{0x8801, 0, "Format OSD (osd)"},
{0x8802, 0, "Create (osd)"},
{0x8803, 0, "List (osd)"},
@@ -730,6 +736,8 @@ struct sg_lib_asc_ascq_t sg_lib_asc_ascq[] =
{0x0B,0x0F,"Warning - low critical humidity limit exceeded"},
{0x0B,0x10,"Warning - high operating humidity limit exceeded"},
{0x0B,0x11,"Warning - low operating humidity limit exceeded"},
+ {0x0B,0x12,"Warning - microcode security at risk"},
+ {0x0B,0x13,"Warning - microcode digital signature validation failure"},
{0x0C,0x00,"Write error"},
{0x0C,0x01,"Write error - recovered with auto reallocation"},
{0x0C,0x02,"Write error - auto reallocation failed"},
@@ -884,6 +892,7 @@ struct sg_lib_asc_ascq_t sg_lib_asc_ascq[] =
{0x24,0x06,"Nonce not unique"},
{0x24,0x07,"Nonce timestamp out of range"},
{0x24,0x08,"Invalid xcdb"},
+ {0x24,0x09,"Invalid fast format"},
{0x25,0x00,"Logical unit not supported"},
{0x26,0x00,"Invalid field in parameter list"},
{0x26,0x01,"Parameter not supported"},
@@ -905,6 +914,8 @@ struct sg_lib_asc_ascq_t sg_lib_asc_ascq[] =
{0x26,0x11,"Incomplete key-associated data set"},
{0x26,0x12,"Vendor specific key reference not found"},
{0x26,0x13,"Application tag mode page is invalid"},
+ {0x26,0x14,"Tape stream mirroring prevented"},
+ {0x26,0x15,"Copy source or copy destination not authorized"},
{0x27,0x00,"Write protected"},
{0x27,0x01,"Hardware write protected"},
{0x27,0x02,"Logical unit software write protected"},
@@ -1208,6 +1219,7 @@ struct sg_lib_asc_ascq_t sg_lib_asc_ascq[] =
{0x5D,0x1A,"Hardware impending failure seek time performance"},
{0x5D,0x1B,"Hardware impending failure spin-up retry count"},
{0x5D,0x1C,"Hardware impending failure drive calibration retry count"},
+ {0x5D,0x1D,"Hardware impending failure power loss protection circuit"},
{0x5D,0x20,"Controller impending failure general hard drive failure"},
{0x5D,0x21,"Controller impending failure drive error rate too high" },
{0x5D,0x22,"Controller impending failure data error rate too high" },
@@ -1273,6 +1285,7 @@ struct sg_lib_asc_ascq_t sg_lib_asc_ascq[] =
{0x5D,0x6A,"Firmware impending failure seek time performance"},
{0x5D,0x6B,"Firmware impending failure spin-up retry count"},
{0x5D,0x6C,"Firmware impending failure drive calibration retry count"},
+ {0x5D,0x73,"Media impending failure endurance limit met"},
{0x5D,0xFF,"Failure prediction threshold exceeded (false)"},
{0x5E,0x00,"Low power condition on"},
{0x5E,0x01,"Idle condition activated by timer"},
@@ -1481,3 +1494,14 @@ const char * sg_lib_transport_proto_strs[] =
"Oxc", "Oxd", "Oxe",
"No specific protocol"
};
+
+/* SCSI Feature Sets array. code->value, pdt->peri_dev_type (-1 for SPC) */
+struct sg_lib_value_name_t sg_lib_scsi_feature_sets[] =
+{
+ {SCSI_FS_SPC_DISCOVERY_2016, -1, "Discovery 2016"},
+ {SCSI_FS_SBC_BASE_2010, PDT_DISK, "SBC Base 2010"},
+ {SCSI_FS_SBC_BASE_2016, PDT_DISK, "SBC Base 2016"},
+ {SCSI_FS_SBC_BASIC_PROV_2016, PDT_DISK, "Basic provisioning 2016"},
+ {SCSI_FS_SBC_DRIVE_MAINT_2016, PDT_DISK, "Drive maintenance 2016"},
+ {0x0, 0, NULL}, /* 0x0 is reserved sfs; trailing sentinel */
+};
diff --git a/sg3_utils.spec b/sg3_utils.spec
index 9d40ec77..190841ed 100644
--- a/sg3_utils.spec
+++ b/sg3_utils.spec
@@ -79,7 +79,7 @@ fi
%{_libdir}/*.la
%changelog
-* Tue May 17 2016 - dgilbert at interlog dot com
+* Mon Sep 04 2017 - dgilbert at interlog dot com
- track t10 changes
* sg3_utils-1.43
diff --git a/src/sg_get_lba_status.c b/src/sg_get_lba_status.c
index 010822de..ceb9e324 100644
--- a/src/sg_get_lba_status.c
+++ b/src/sg_get_lba_status.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2009-2016 Douglas Gilbert.
+ * Copyright (c) 2009-2017 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.
@@ -30,7 +30,11 @@
* device.
*/
-static const char * version_str = "1.08 20160423";
+static const char * version_str = "1.09 20170912";
+
+#ifndef UINT32_MAX
+#define UINT32_MAX ((uint32_t)-1)
+#endif
#define MAX_GLBAS_BUFF_LEN (1024 * 1024)
#define DEF_GLBAS_BUFF_LEN 24
@@ -40,13 +44,21 @@ static unsigned char * glbasBuffp = glbasBuff;
static struct option long_options[] = {
+ {"16", no_argument, 0, 'S'},
+ {"32", no_argument, 0, 'T'},
{"brief", no_argument, 0, 'b'},
+ {"element-id", required_argument, 0, 'e'},
+ {"element_id", required_argument, 0, 'e'},
{"help", no_argument, 0, 'h'},
{"hex", no_argument, 0, 'H'},
{"lba", required_argument, 0, 'l'},
{"maxlen", required_argument, 0, 'm'},
{"raw", no_argument, 0, 'r'},
{"readonly", no_argument, 0, 'R'},
+ {"report-type", required_argument, 0, 't'},
+ {"report_type", required_argument, 0, 't'},
+ {"scan-len", required_argument, 0, 's'},
+ {"scan_len", required_argument, 0, 's'},
{"verbose", no_argument, 0, 'v'},
{"version", no_argument, 0, 'V'},
{0, 0, 0, 0},
@@ -55,16 +67,23 @@ static struct option long_options[] = {
static void
usage()
{
- pr2serr("Usage: sg_get_lba_status [--brief] [--help] [--hex] "
- "[--lba=LBA]\n"
- " [--maxlen=LEN] [--raw] [--readonly] "
- "[--verbose]\n"
- " [--version] DEVICE\n"
+ pr2serr("Usage: sg_get_lba_status [--16] [--32][--brief] "
+ "[--element-id=EI]\n"
+ " [--help] [--hex] "
+ "[--lba=LBA] [--maxlen=LEN]\n"
+ " [--raw] [--readonly] "
+ "[--report-type=RT]\n"
+ " [--scan-len=SL] [--verbose] "
+ "[--version] DEVICE\n"
" where:\n"
- " --brief|-b a descriptor per line: "
- "<lba_hex blocks_hex p_status>\n"
+ " --16|-S use GET LBA STATUS(16) cdb (def)\n"
+ " --32|-T use GET LBA STATUS(32) cdb\n"
+ " --brief|-b a descriptor per line:\n"
+ " <lba_hex blocks_hex p_status "
+ "add_status>\n"
" use twice ('-bb') for given LBA "
"provisioning status\n"
+ " --element-id=EI|-e EI EI is the element identifier\n"
" --help|-h print out usage message\n"
" --hex|-H output in hexadecimal\n"
" --lba=LBA|-l LBA starting LBA (logical block address) "
@@ -75,9 +94,20 @@ usage()
DEF_GLBAS_BUFF_LEN );
pr2serr(" --raw|-r output in binary\n"
" --readonly|-R open DEVICE read-only (def: read-write)\n"
+ " --report-type=RT|-t RT report type: 0->all LBAs (def);\n"
+ " 1-> LBAs with non-zero "
+ "provisioning status\n"
+ " 2-> LBAs that are mapped\n"
+ " 3-> LBAs that are deallocated\n"
+ " 4-> LBAs that are anchored\n"
+ " 5-> LBAs that may return "
+ "unrecovered error\n"
+ " --scan-len=SL|-s SL SL in maximum scan length "
+ "(unit: logical blocks)\n"
" --verbose|-v increase verbosity\n"
" --version|-V print version string and exit\n\n"
- "Performs a SCSI GET LBA STATUS command (SBC-3)\n"
+ "Performs a SCSI GET LBA STATUS(16) or GET LBA STATUS(32) "
+ "command\n(SBC-3 and SBC-4)\n"
);
}
@@ -95,7 +125,7 @@ dStrRaw(const char* str, int len)
*/
static int
decode_lba_status_desc(const unsigned char * bp, uint64_t * slbap,
- uint32_t * blocksp)
+ uint32_t * blocksp, uint8_t * add_statusp)
{
uint32_t blocks;
uint64_t ull;
@@ -108,6 +138,8 @@ decode_lba_status_desc(const unsigned char * bp, uint64_t * slbap,
*slbap = ull;
if (blocksp)
*blocksp = blocks;
+ if (add_statusp)
+ *add_statusp = bp[13];
return bp[12] & 0xf;
}
@@ -115,25 +147,31 @@ decode_lba_status_desc(const unsigned char * bp, uint64_t * slbap,
int
main(int argc, char * argv[])
{
- int sg_fd, k, j, res, c, rlen, num_descs;
+ int sg_fd, k, j, res, c, rlen, num_descs, completion_cond;
int do_brief = 0;
int do_hex = 0;
int64_t ll;
uint64_t lba = 0;
uint64_t d_lba = 0;
uint32_t d_blocks = 0;
+ uint32_t element_id = 0;
+ uint32_t scan_len = 0;
int maxlen = DEF_GLBAS_BUFF_LEN;
int do_raw = 0;
int o_readonly = 0;
+ int rt = 0;
int verbose = 0;
+ bool do_16 = false;
+ bool do_32 = false;
const char * device_name = NULL;
const unsigned char * bp;
int ret = 0;
+ uint8_t add_status;
while (1) {
int option_index = 0;
- c = getopt_long(argc, argv, "bhHl:m:rRvV", long_options,
+ c = getopt_long(argc, argv, "be:hHl:m:rRs:St:TvV", long_options,
&option_index);
if (c == -1)
break;
@@ -142,6 +180,14 @@ main(int argc, char * argv[])
case 'b':
++do_brief;
break;
+ case 'e':
+ ll = sg_get_llnum(optarg);
+ if ((ll < 0) || (ll > UINT32_MAX)) {
+ pr2serr("bad argument to '--element-id'\n");
+ return SG_LIB_SYNTAX_ERROR;
+ }
+ element_id = (uint32_t)ll;
+ break;
case 'h':
case '?':
usage();
@@ -171,6 +217,28 @@ main(int argc, char * argv[])
case 'R':
++o_readonly;
break;
+ case 's':
+ ll = sg_get_llnum(optarg);
+ if ((ll < 0) || (ll > UINT32_MAX)) {
+ pr2serr("bad argument to '--scan-len'\n");
+ return SG_LIB_SYNTAX_ERROR;
+ }
+ scan_len = (uint32_t)ll;
+ break;
+ case 'S':
+ do_16 = true;
+ break;
+ case 't':
+ rt = sg_get_num_nomult(optarg);
+ if ((rt < 0) || (rt > 255)) {
+ pr2serr("'--report-type=RT' should be between 0 and 255 "
+ "(inclusive)\n");
+ return SG_LIB_SYNTAX_ERROR;
+ }
+ break;
+ case 'T':
+ do_32 = true;
+ break;
case 'v':
++verbose;
break;
@@ -195,7 +263,6 @@ main(int argc, char * argv[])
return SG_LIB_SYNTAX_ERROR;
}
}
-
if (NULL == device_name) {
pr2serr("missing device name!\n");
usage();
@@ -215,7 +282,20 @@ main(int argc, char * argv[])
goto free_buff;
}
}
-
+ if (do_16 && do_32) {
+ pr2serr("both --16 and --32 given, choose --16\n");
+ do_32 = false;
+ } else if ((! do_16) && (! do_32)) {
+ if (verbose > 3)
+ pr2serr("choosing --16\n");
+ do_16 = true;
+ }
+ if (do_16) {
+ if (element_id != 0)
+ pr2serr("Warning: --element_id= ignored with 16 byte cdb\n");
+ if (scan_len != 0)
+ pr2serr("Warning: --scan_len= ignored with 16 byte cdb\n");
+ }
sg_fd = sg_cmds_open_device(device_name, o_readonly, verbose);
if (sg_fd < 0) {
pr2serr("open error: %s: %s\n", device_name, safe_strerror(-sg_fd));
@@ -223,8 +303,13 @@ main(int argc, char * argv[])
goto free_buff;
}
- res = sg_ll_get_lba_status(sg_fd, lba, glbasBuffp, maxlen, 1,
- verbose);
+ if (do_16)
+ res = sg_ll_get_lba_status16(sg_fd, lba, rt, glbasBuffp, maxlen, 1,
+ verbose);
+ else
+ res = sg_ll_get_lba_status32(sg_fd, lba, element_id, scan_len, rt,
+ glbasBuffp, maxlen, 1, verbose);
+
ret = res;
if (0 == res) {
/* in sbc3r25 offset for calculating the 'parameter data length'
@@ -264,7 +349,8 @@ main(int argc, char * argv[])
ret = SG_LIB_CAT_OTHER;
goto the_end;
}
- res = decode_lba_status_desc(glbasBuffp + 8, &d_lba, &d_blocks);
+ res = decode_lba_status_desc(glbasBuffp + 8, &d_lba, &d_blocks,
+ &add_status);
if ((res < 0) || (res > 15)) {
pr2serr("first LBA status descriptor returned %d ??\n", res);
ret = SG_LIB_CAT_OTHER;
@@ -275,8 +361,9 @@ main(int argc, char * argv[])
" descriptor LBA: 0x");
for (j = 0; j < 8; ++j)
pr2serr("%02x", glbasBuffp[8 + j]);
- pr2serr(" blocks: 0x%x p_status: %d\n",
- (unsigned int)d_blocks, res);
+ pr2serr(" blocks: 0x%x p_status: %d add_status: 0x%x\n",
+ (unsigned int)d_blocks, res,
+ (unsigned int)add_status);
ret = SG_LIB_CAT_OTHER;
goto the_end;
}
@@ -289,10 +376,37 @@ main(int argc, char * argv[])
goto the_end;
}
num_descs = (rlen - 8) / 16;
+ completion_cond = (*(glbasBuffp + 7) >> 1) & 7; /* added sbc4r14 */
+ if (do_brief)
+ printf("Completion condition=%d\n", completion_cond);
+ else {
+ switch (completion_cond) {
+ case 0:
+ printf("No indication of the completion condition\n");
+ break;
+ case 1:
+ printf("Command completed due to meeting allocation length "
+ "(--maxlen=LEN (def 24))\n");
+ break;
+ case 2:
+ printf("Command completed due to meeting scan length "
+ "(--scan-len=SL)\n");
+ break;
+ case 3:
+ printf("Command completed due to meeting capacity of "
+ "medium\n");
+ break;
+ default:
+ printf("Command completion is reserved [%d]\n",
+ completion_cond);
+ break;
+ }
+ }
+ printf("RTP=%d\n", *(glbasBuffp + 7) & 0x1); /* added sbc4r12 */
if (verbose)
pr2serr("%d complete LBA status descriptors found\n", num_descs);
for (bp = glbasBuffp + 8, k = 0; k < num_descs; bp += 16, ++k) {
- res = decode_lba_status_desc(bp, &d_lba, &d_blocks);
+ res = decode_lba_status_desc(bp, &d_lba, &d_blocks, &add_status);
if ((res < 0) || (res > 15))
pr2serr("descriptor %d: bad LBA status descriptor returned "
"%d\n", k + 1, res);
@@ -308,16 +422,33 @@ main(int argc, char * argv[])
printf(" blocks: %u", (unsigned int)d_blocks);
switch (res) {
case 0:
- printf(" mapped (or unknown)\n");
+ printf(" mapped (or unknown)");
break;
case 1:
- printf(" deallocated\n");
+ printf(" deallocated");
break;
case 2:
- printf(" anchored\n");
+ printf(" anchored");
+ break;
+ case 3:
+ printf(" mapped"); /* sbc4r12 */
+ break;
+ case 4:
+ printf(" unknown"); /* sbc4r12 */
+ break;
+ default:
+ printf(" Provisioning status: %d", res);
+ break;
+ }
+ switch (add_status) {
+ case 0:
+ printf("\n");
+ break;
+ case 1:
+ printf(" [may return unrecovered errors]\n");
break;
default:
- printf(" Provisioning status: %d\n", res);
+ printf(" [add_status: 0x%x]\n", (unsigned int)add_status);
break;
}
}
diff --git a/src/sg_inq.c b/src/sg_inq.c
index 2be835dc..5e7c6e8d 100644
--- a/src/sg_inq.c
+++ b/src/sg_inq.c
@@ -1,12 +1,12 @@
/* A utility program originally written for the Linux OS SCSI subsystem.
-* Copyright (C) 2000-2016 D. Gilbert
+* Copyright (C) 2000-2017 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)
* any later version.
This program outputs information provided by a SCSI INQUIRY command.
- It is mainly based on the SCSI SPC-4 document at http://www.t10.org .
+ It is mainly based on the SCSI SPC-5 document at http://www.t10.org .
Acknowledgment:
- Martin Schwenke <martin at meltin dot net> added the raw switch and
@@ -43,7 +43,7 @@
#include "sg_unaligned.h"
#include "sg_pr2serr.h"
-static const char * version_str = "1.63 20160531"; /* SPC-5 rev 10 */
+static const char * version_str = "1.64 20170912"; /* SPC-5 rev 14 */
/* INQUIRY notes:
* It is recommended that the initial allocation length given to a
@@ -90,11 +90,18 @@ static const char * version_str = "1.63 20160531"; /* SPC-5 rev 10 */
#define VPD_3PARTY_COPY 0x8f
#define VPD_PROTO_LU 0x90
#define VPD_PROTO_PORT 0x91
+#define VPD_SCSI_FEATURE_SETS 0x92 /* spc5r11 */
#define VPD_BLOCK_LIMITS 0xb0
#define VPD_BLOCK_DEV_CHARS 0xb1
#define VPD_MAN_ASS_SN 0xb1
#define VPD_LB_PROVISIONING 0xb2
#define VPD_REFERRALS 0xb3
+#define VPD_SUP_BLOCK_LENS 0xb4 /* sbc4r01 */
+#define VPD_BLOCK_DEV_C_EXTENS 0xb5 /* sbc4r02 */
+#define VPD_ZBC_DEV_CHARS 0xb6 /* zbc-r01b */
+#define VPD_BLOCK_LIMITS_EXT 0xb7 /* sbc4r08 */
+
+/* Vendor specific VPD pages (typically >= 0xc0) */
#define VPD_UPR_EMC 0xc0
#define VPD_RDAC_VERS 0xc2
#define VPD_RDAC_VAC 0xc9
@@ -146,7 +153,10 @@ static struct svpd_values_name_t vpd_pg[] = {
{VPD_ATA_INFO, 0, -1, 0, "ai", "ATA information (SAT)"},
{VPD_BLOCK_DEV_CHARS, 0, 0, 0, "bdc",
"Block device characteristics (SBC)"},
+ {VPD_BLOCK_DEV_C_EXTENS, 0, 0, 0, "bdce", "Block device characteristics "
+ "extension (SBC)"},
{VPD_BLOCK_LIMITS, 0, 0, 0, "bl", "Block limits (SBC)"},
+ {VPD_BLOCK_LIMITS_EXT, 0, 0, 0, "ble", "Block limits extension (SBC)"},
{VPD_DEVICE_ID, 0, -1, 0, "di", "Device identification"},
#if 0
{VPD_DEVICE_ID, VPD_DI_SEL_AS_IS, -1, 0, "di_asis", "Like 'di' "
@@ -169,11 +179,16 @@ static struct svpd_values_name_t vpd_pg[] = {
"information"},
{VPD_PROTO_PORT, 0, 0x0, 0, "pspo", "Protocol-specific port information"},
{VPD_REFERRALS, 0, 0, 0, "ref", "Referrals (SBC)"},
+ {VPD_SUP_BLOCK_LENS, 0, 0, 0, "sbl", "Supported block lengths and "
+ "protection types (SBC)"},
+ {VPD_SCSI_FEATURE_SETS, 0, -1, 0, "sfs", "SCSI Feature sets"},
{VPD_SOFTW_INF_ID, 0, -1, 0, "sii", "Software interface identification"},
{VPD_UNIT_SERIAL_NUM, 0, -1, 0, "sn", "Unit serial number"},
{VPD_SCSI_PORTS, 0, -1, 0, "sp", "SCSI ports"},
{VPD_SUPPORTED_VPDS, 0, -1, 0, "sv", "Supported VPD pages"},
{VPD_3PARTY_COPY, 0, -1, 0, "tpc", "Third party copy"},
+ {VPD_ZBC_DEV_CHARS, 0, -1, 0, "zbdc", "Zoned block device "
+ "characteristics"},
/* Following are vendor specific */
{VPD_RDAC_VAC, 0, -1, 1, "rdac_vac", "RDAC volume access control (RDAC)"},
{VPD_RDAC_VERS, 0, -1, 1, "rdac_vers", "RDAC software version (RDAC)"},
@@ -1155,6 +1170,9 @@ static struct vpd_name vpd_name_arr[] = {
{VPD_CFA_PROFILE_INFO, 0, "CFA profile information"}, /* 0x8c */
{VPD_POWER_CONSUMPTION, 0, "Power consumption"}, /* 0x8d */
{VPD_3PARTY_COPY, 0, "Third party copy"}, /* 0x8f */
+ {VPD_PROTO_LU, 0, "Protocol-specific logical unit information"}, /* 0x90 */
+ {VPD_PROTO_PORT, 0, "Protocol-specific port information"}, /* 0x91 */
+ {VPD_SCSI_FEATURE_SETS, 0, "SCSI Feature sets"}, /* 0x92 */
/* 0xb0 to 0xbf are per peripheral device type */
{VPD_BLOCK_LIMITS, 0, "Block limits (sbc2)"}, /* 0xb0 */
{VPD_BLOCK_DEV_CHARS, 0, "Block device characteristics (sbc3)"},
@@ -2156,7 +2174,7 @@ export_dev_ids(unsigned char * buff, int len, int verbose)
"around offset=%d\n", off);
}
-/* VPD_EXT_INQ Extended Inquiry */
+/* VPD_EXT_INQ Extended Inquiry [0x86] */
static void
decode_x_inq_vpd(unsigned char * buff, int len, int do_hex)
{
@@ -2182,10 +2200,11 @@ decode_x_inq_vpd(unsigned char * buff, int len, int do_hex)
/* NO_PI_CHK and HSSRELEF added in spc5r02 */
printf(" NO_PI_CHK=%d P_I_I_SUP=%d LUICLR=%d\n", !!(buff[7] & 0x20),
!!(buff[7] & 0x10), !!(buff[7] & 0x1));
- /* LU_COLL_TYPE in spc5r09, CBCS obsolete in spc5r01 */
- printf("LU_COLL_TYPE=%d R_SUP=%d HSSRELEF=%d [CBCS=%d]\n",
- (buff[8] >> 5) & 0x7, !!(buff[8] & 0x10), !!(buff[8] & 0x2),
- !!(buff[8] & 0x1));
+ /* LU_COLL_TYPE in spc5r09, CBCS obsolete in spc5r01, RTD_SUP added in
+ * spc5r11 */
+ printf("LU_COLL_TYPE=%d R_SUP=%d RTD_SUP=%d HSSRELEF=%d [CBCS=%d]\n",
+ (buff[8] >> 5) & 0x7, !!(buff[8] & 0x10), !!(buff[8] & 0x8),
+ !!(buff[8] & 0x2), !!(buff[8] & 0x1));
printf(" Multi I_T nexus microcode download=%d\n", buff[9] & 0xf);
printf(" Extended self-test completion minutes=%d\n",
sg_get_unaligned_be16(buff + 10)); /* spc4r27 */
@@ -2199,7 +2218,7 @@ decode_x_inq_vpd(unsigned char * buff, int len, int do_hex)
!!(buff[14] & 0x2), !!(buff[14] & 0x1));
}
-/* VPD_SOFTW_INF_ID */
+/* VPD_SOFTW_INF_ID [0x84] */
static void
decode_softw_inf_id(unsigned char * buff, int len, int do_hex)
{
@@ -2215,7 +2234,7 @@ decode_softw_inf_id(unsigned char * buff, int len, int do_hex)
sg_get_unaligned_be24(buff + 3));
}
-/* VPD_ATA_INFO */
+/* VPD_ATA_INFO [0x89] */
static void
decode_ata_info_vpd(unsigned char * buff, int len, int do_hex)
{
@@ -2274,7 +2293,7 @@ decode_ata_info_vpd(unsigned char * buff, int len, int do_hex)
sg_is_big_endian());
}
-/* VPD_POWER_CONDITION */
+/* VPD_POWER_CONDITION [0x8a] */
static void
decode_power_condition(unsigned char * buff, int len, int do_hex)
{
@@ -2303,6 +2322,53 @@ decode_power_condition(unsigned char * buff, int len, int do_hex)
sg_get_unaligned_be16(buff + 16));
}
+/* VPD_SCSI_FEATURE_SETS [0x92] (sfs) */
+static void
+decode_feature_sets_vpd(unsigned char * buff, int len,
+ const struct opts_t * op)
+{
+ int k, bump;
+ uint16_t sf_code;
+ bool found;
+ unsigned char * bp;
+ char b[64];
+
+ if ((1 == op->do_hex) || (op->do_hex > 2)) {
+ dStrHex((const char *)buff, len, (1 == op->do_hex) ? 1 : -1);
+ return;
+ }
+ if (len < 4) {
+ pr2serr("SCSI Feature sets VPD page length too short=%d\n", len);
+ return;
+ }
+ len -= 8;
+ bp = buff + 8;
+ for (k = 0; k < len; k += bump, bp += bump) {
+ sf_code = sg_get_unaligned_be16(bp);
+ bump = 2;
+ if ((k + bump) > len) {
+ pr2serr("SCSI Feature sets, short descriptor length=%d, "
+ "left=%d\n", bump, (len - k));
+ return;
+ }
+ if (2 == op->do_hex)
+ dStrHex((const char *)bp + 8, 2, 1);
+ else if (op->do_hex > 2)
+ dStrHex((const char *)bp, 2, 1);
+ else {
+ printf(" %s", sg_get_sfs_str(sf_code, -2, sizeof(b), b,
+ &found, op->do_verbose));
+ if (op->do_verbose == 1)
+ printf(" [0x%x]\n", (unsigned int)sf_code);
+ else if (op->do_verbose > 1)
+ printf(" [0x%x] found=%s\n", (unsigned int)sf_code,
+ found ? "true" : "false");
+ else
+ printf("\n");
+ }
+ }
+}
+
/* VPD_BLOCK_LIMITS sbc */
/* Sequential access device characteristics, ssc+smc */
/* OSD information, osd */
@@ -2433,6 +2499,8 @@ decode_b1_vpd(unsigned char * buff, int len, int do_hex)
printf(" ZONED=%d\n", (buff[8] >> 4) & 0x3); /* sbc4r04 */
printf(" FUAB=%d\n", buff[8] & 0x2);
printf(" VBULS=%d\n", buff[8] & 0x1);
+ printf(" DEPOPULATION_TIME=%u (seconds)\n",
+ sg_get_unaligned_be32(buff + 12)); /* added sbc4r14 */
break;
case PDT_TAPE: case PDT_MCHANGER: case PDT_ADC:
printf(" Manufacturer-assigned serial number: %.*s\n",
@@ -3540,6 +3608,17 @@ vpd_decode(int sg_fd, const struct opts_t * op, int inhex_len)
else
decode_power_condition(rp, len, op->do_hex);
break;
+ case VPD_SCSI_FEATURE_SETS: /* 0x92 */
+ if (!op->do_raw && (op->do_hex < 2))
+ printf("VPD INQUIRY: SCSI Feature sets\n");
+ res = vpd_fetch_page_from_dev(sg_fd, rp, pn, mxlen, vb, &len);
+ if (res)
+ break;
+ if (op->do_raw)
+ dStrRaw((const char *)rp, len);
+ else
+ decode_feature_sets_vpd(rp, len, op);
+ break;
case 0xb0: /* VPD pages in B0h to BFh range depend on pdt */
res = vpd_fetch_page_from_dev(sg_fd, rp, pn, mxlen, vb, &len);
if (0 == res) {
diff --git a/src/sg_inq_data.c b/src/sg_inq_data.c
index c4e15133..f86659f6 100644
--- a/src/sg_inq_data.c
+++ b/src/sg_inq_data.c
@@ -1,5 +1,5 @@
/* A utility program originally written for the Linux OS SCSI subsystem.
-* Copyright (C) 2000-2016 D. Gilbert
+* Copyright (C) 2000-2017 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)
@@ -48,8 +48,8 @@ struct sg_version_descriptor {
const char * name;
};
-/* table from SPC-5 revision 10 [sorted numerically (from Annex E.9)] */
-/* Can also be obtained from : http://www.t10.org/lists/stds.txt 20160510 */
+/* table from SPC-5 revision 16 [sorted numerically (from Annex E.9)] */
+/* Can also be obtained from : http://www.t10.org/lists/stds.txt 20170114 */
#ifdef SG_SCSI_STRINGS
@@ -76,6 +76,7 @@ struct sg_version_descriptor sg_version_descriptor_arr[] = {
{0xa0, "SAM-5 (no version claimed)"},
{0xa2, "SAM-5 T10/2104-D revision 4"},
{0xa4, "SAM-5 T10/2104-D revision 20"},
+ {0xa8, "SAM-5 ANSI INCITS 515-2016"},
{0xa6, "SAM-5 T10/2104-D revision 21"},
{0xc0, "SAM-6 (no version claimed)"},
{0x120, "SPC (no version claimed)"},
@@ -226,17 +227,20 @@ struct sg_version_descriptor sg_version_descriptor_arr[] = {
{0x560, "OSD-3 (no version claimed)"},
{0x580, "SES-3 (no version claimed)"},
{0x582, "SES-3 T10/BSR INCITS 518 revision 13"},
+ {0x584, "SES-3 T10/BSR INCITS 518 revision 14"},
{0x5a0, "SSC-5 (no version claimed)"},
{0x5c0, "SPC-5 (no version claimed)"},
{0x5e0, "SFSC (no version claimed)"},
{0x5e3, "SFSC BSR INCITS 501 revision 01"},
{0x5e5, "SFSC BSR INCITS 501 revision 02"},
+ {0x5e8, "SFSC ANSI INCITS 501-2016"},
{0x600, "SBC-4 (no version claimed)"},
{0x620, "ZBC (no version claimed)"},
{0x622, "ZBC BSR INCITS 536 revision 02"},
{0x624, "ZBC BSR INCITS 536 revision 05"},
{0x640, "ADC-4 (no version claimed)"},
{0x660, "ZBC-2 (no version claimed)"},
+ {0x680, "SES-4 (no version claimed)"},
{0x820, "SSA-TL2 (no version claimed)"},
{0x83b, "SSA-TL2 T10/1147-D revision 05b"},
{0x83c, "SSA-TL2 ANSI INCITS 308-1998"},
@@ -362,6 +366,7 @@ struct sg_version_descriptor sg_version_descriptor_arr[] = {
{0xc65, "SAS-3 T10/BSR INCITS 519 revision 06"},
{0xc68, "SAS-3 ANSI INCITS 519-2014"},
{0xc80, "SAS-4 (no version claimed)"},
+ {0xc82, "T10/BSR INCITS 534 revision 08a"},
{0xd20, "FC-PH (no version claimed)"},
{0xd3b, "FC-PH ANSI INCITS 230-1994"},
{0xd3c, "FC-PH ANSI INCITS 230-1994 with Amnd 1 ANSI INCITS "
@@ -499,6 +504,7 @@ struct sg_version_descriptor sg_version_descriptor_arr[] = {
{0x1ee8, "SAT-3 ANSI INCITS 517-2015"},
{0x1f00, "SAT-4 (no version claimed)"},
{0x1f02, "SAT-4 T10/BSR INCITS 491 revision 5"},
+ {0x1f04, "SAT-4 T10/BSR INCITS 491 revision 6"},
{0x20a0, "SPL (no version claimed)"},
{0x20a3, "SPL T10/2124-D revision 6a"},
{0x20a5, "SPL T10/2124-D revision 7"},
@@ -515,6 +521,9 @@ struct sg_version_descriptor sg_version_descriptor_arr[] = {
{0x20e8, "SPL-3 ANSI INCITS 492-2015"},
{0x2100, "SPL-4 (no version claimed)"},
{0x2102, "SPL-4 T10/BSR INCITS 538 revision 08a"},
+ {0x2104, "SPL-4 T10/BSR INCITS 538 revision 10"},
+ {0x2105, "SPL-4 T10/BSR INCITS 538 revision 11"},
+ {0x2120, "SPL-5 (no version claimed)"},
{0x21e0, "SOP (no version claimed)"},
{0x21e4, "SOP T10/BSR INCITS 489 revision 4"},
{0x21e6, "SOP T10/BSR INCITS 489 revision 5"},
@@ -525,6 +534,7 @@ struct sg_version_descriptor sg_version_descriptor_arr[] = {
{0x2208, "PQI ANSI INCITS 490-2014"},
{0x2220, "SOP-2 (no draft published)"},
{0x2240, "PQI-2 (no version claimed)"},
+ {0x2244, "PQI-2 PQI-2 ANSI INCITS 507-2016"},
{0x2242, "PQI-2 T10/BSR INCITS 507 revision 01"},
{0xffc0, "IEEE 1667 (no version claimed)"},
{0xffc1, "IEEE 1667-2006"},
diff --git a/src/sg_logs.c b/src/sg_logs.c
index 9b36a717..44bd9e28 100644
--- a/src/sg_logs.c
+++ b/src/sg_logs.c
@@ -1,5 +1,5 @@
/* A utility program originally written for the Linux OS SCSI subsystem.
- * Copyright (C) 2000-2016 D. Gilbert
+ * Copyright (C) 2000-2017 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)
@@ -31,7 +31,7 @@
#include "sg_unaligned.h"
#include "sg_pr2serr.h"
-static const char * version_str = "1.47 20160704"; /* spc5r10 + sbc4r11 */
+static const char * version_str = "1.48 20170912"; /* spc5r11 + sbc4r11 */
#define MX_ALLOC_LEN (0xfffc)
#define SHORT_RESP_LEN 128
@@ -70,6 +70,7 @@ static const char * version_str = "1.47 20160704"; /* spc5r10 + sbc4r11 */
#define UTILIZATION_SUBPG 0x1
#define ENV_LIMITS_SUBPG 0x2
#define LPS_MISALIGNMENT_SUBPG 0x3
+#define ZONED_BLOCK_DEV_STATS_SUBPG 0x1
/* Vendor product identifiers followed by associated mask values */
#define VP_NONE (-1)
@@ -241,6 +242,8 @@ 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_zoned_block_dev_stats(const uint8_t * resp, int len,
+ const struct opts_t * op);
static bool show_pending_defects_page(const uint8_t * resp, int len,
const struct opts_t * op);
static bool show_background_op_page(const uint8_t * resp, int len,
@@ -342,6 +345,8 @@ static struct log_elem log_arr[] = {
show_device_stats_page}, /* 0x14, 0x0 SSC,ADC */
{0x14, 0, 0, PDT_MCHANGER, 0, "Media changer statistics", "mcs",
show_media_stats_page}, /* 0x14, 0x0 SMC */
+ {0x14, ZONED_BLOCK_DEV_STATS_SUBPG, 0, 0, 0, /* 0x14,0x1 zbc2r01 */
+ "Zoned block device statistics", "zbds", show_zoned_block_dev_stats},
{BACKGROUND_SCAN_LPAGE, 0, 0, 0, 0, "Background scan results", "bsr",
show_background_scan_results_page}, /* 0x15, 0x0 SBC */
{BACKGROUND_SCAN_LPAGE, BACKGROUND_OP_SUBPG, 0, 0, 0,
@@ -1747,10 +1752,10 @@ show_buffer_over_under_run_page(const uint8_t * resp, int len,
cp = "over-run";
break;
case 0x2:
- cp = "transport under-run";
+ cp = "service delivery subsystem busy, under-run";
break;
case 0x3:
- cp = "transport over-run";
+ cp = "service delivery subsystem busy, over-run";
break;
case 0x4:
cp = "transfer too slow, under-run";
@@ -1765,10 +1770,10 @@ show_buffer_over_under_run_page(const uint8_t * resp, int len,
cp = "command, over-run";
break;
case 0x22:
- cp = "command, transport under-run";
+ cp = "command, service delivery subsystem busy, under-run";
break;
case 0x23:
- cp = "command, transport over-run";
+ cp = "command, service delivery subsystem busy, over-run";
break;
case 0x24:
cp = "command, transfer too slow, under-run";
@@ -1783,10 +1788,10 @@ show_buffer_over_under_run_page(const uint8_t * resp, int len,
cp = "I_T nexus, over-run";
break;
case 0x42:
- cp = "I_T nexus, transport under-run";
+ cp = "I_T nexus, service delivery subsystem busy, under-run";
break;
case 0x43:
- cp = "I_T nexus, transport over-run";
+ cp = "I_T nexus, service delivery subsystem busy, over-run";
break;
case 0x44:
cp = "I_T nexus, transfer too slow, under-run";
@@ -1801,10 +1806,10 @@ show_buffer_over_under_run_page(const uint8_t * resp, int len,
cp = "time, over-run";
break;
case 0x82:
- cp = "time, transport under-run";
+ cp = "time, service delivery subsystem busy, under-run";
break;
case 0x83:
- cp = "time, transport over-run";
+ cp = "time, service delivery subsystem busy, over-run";
break;
case 0x84:
cp = "time, transfer too slow, under-run";
@@ -2040,13 +2045,14 @@ humidity_str(uint8_t h, bool reporting, char * b, int blen)
return b;
}
-/* ENV_REPORTING_SUBPG [0xd,0x1] introduced: SPC-5 (rev 02) */
+/* ENV_REPORTING_SUBPG [0xd,0x1] introduced: SPC-5 (rev 02). "mounted"
+ * changed to "other" in spc5r11 */
static bool
show_environmental_reporting_page(const uint8_t * resp, int len,
const struct opts_t * op)
{
int num, pl, pc, blen;
- bool mounted_valid;
+ bool other_valid;
const uint8_t * bp;
char str[PCB_STR_LEN];
char b[32];
@@ -2070,7 +2076,7 @@ show_environmental_reporting_page(const uint8_t * resp, int len,
break;
}
}
- mounted_valid = !!(bp[4] & 1);
+ other_valid = !!(bp[4] & 1);
if (pc < 0x100) {
if (pl < 12) {
printf(" <<expect parameter 0x%x to be at least 12 bytes "
@@ -2078,7 +2084,7 @@ show_environmental_reporting_page(const uint8_t * resp, int len,
goto skip;
}
printf(" parameter code=0x%x\n", pc);
- printf(" MTV=%d\n", (int)mounted_valid);
+ printf(" OTV=%d\n", (int)other_valid);
printf(" Temperature: %s\n",
temperature_str(bp[5], true, b, blen));
printf(" Lifetime maximum temperature: %s\n",
@@ -2089,10 +2095,10 @@ show_environmental_reporting_page(const uint8_t * resp, int len,
temperature_str(bp[8], true, b, blen));
printf(" Minimum temperature since power on: %s\n",
temperature_str(bp[9], true, b, blen));
- if (mounted_valid) {
- printf(" Maximum mounted temperature: %s\n",
+ if (other_valid) {
+ printf(" Maximum other temperature: %s\n",
temperature_str(bp[10], true, b, blen));
- printf(" Minimum mounted temperature: %s\n",
+ printf(" Minimum other temperature: %s\n",
temperature_str(bp[11], true, b, blen));
}
} else if (pc < 0x200) {
@@ -2102,7 +2108,7 @@ show_environmental_reporting_page(const uint8_t * resp, int len,
goto skip;
}
printf(" parameter code=0x%x\n", pc);
- printf(" MRHV=%d\n", (int)mounted_valid);
+ printf(" ORHV=%d\n", (int)other_valid);
printf(" Relative humidity: %s\n",
humidity_str(bp[5], true, b, blen));
printf(" Lifetime maximum relative humidity: %s\n",
@@ -2113,10 +2119,10 @@ show_environmental_reporting_page(const uint8_t * resp, int len,
humidity_str(bp[8], true, b, blen));
printf(" Minimum relative humidity since power on: %s\n",
humidity_str(bp[9], true, b, blen));
- if (mounted_valid) {
- printf(" Maximum mounted relative humidity: %s\n",
+ if (other_valid) {
+ printf(" Maximum other relative humidity: %s\n",
temperature_str(bp[10], true, b, blen));
- printf(" Minimum mounted relative humidity: %s\n",
+ printf(" Minimum other relative humidity: %s\n",
temperature_str(bp[11], true, b, blen));
}
} else
@@ -3368,9 +3374,9 @@ show_sas_port_param(const uint8_t * bp, int param_len,
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 = %u\n", ui);
+ printf(" Loss of DWORD synchronization count = %u\n", ui);
ui = sg_get_unaligned_be32(vcp + 44);
- printf(" Phy reset problem = %u\n", ui);
+ printf(" Phy reset problem count = %u\n", ui);
}
if (spld_len > 51) {
int num_ped, pes;
@@ -4788,6 +4794,193 @@ skip:
return true;
}
+/* ZONED_BLOCK_DEV_STATS_SUBPG [0x14,0x1] introduced: zbc2r01 */
+static bool
+show_zoned_block_dev_stats(const uint8_t * resp, int len,
+ const struct opts_t * op)
+{
+ int num, pl, pc;
+ const uint8_t * bp;
+ char str[PCB_STR_LEN];
+
+ if (op->verbose || ((0 == op->do_raw) && (0 == op->do_hex)))
+ printf("Zoned block device statistics page [0x14,0x1]\n");
+ num = len - 4;
+ bp = &resp[0] + 4;
+ while (num > 3) {
+ pc = sg_get_unaligned_be16(bp + 0);
+ pl = bp[3] + 4;
+ if (op->filter_given) {
+ if (pc != op->filter)
+ goto skip;
+ if (op->do_raw) {
+ dStrRaw((const char *)bp, pl);
+ break;
+ } else if (op->do_hex) {
+ dStrHex((const char *)bp, pl, ((1 == op->do_hex) ? 1 : -1));
+ break;
+ }
+ }
+ switch (pc) {
+ case 0x0:
+ printf(" Maximum open zones:");
+ if ((pl < 8) || (num < 8)) {
+ if (num < 8)
+ pr2serr("\n truncated by response length, expected "
+ "at least 8 bytes\n");
+ else
+ pr2serr("\n parameter length >= 8 expected, got %d\n",
+ pl);
+ break;
+ }
+ printf(" %" PRIu64 "\n", sg_get_unaligned_be64(bp + 4));
+ break;
+ case 0x1:
+ printf(" Maximum explicitly open zones:");
+ if ((pl < 8) || (num < 8)) {
+ if (num < 8)
+ pr2serr("\n truncated by response length, expected "
+ "at least 8 bytes\n");
+ else
+ pr2serr("\n parameter length >= 8 expected, got %d\n",
+ pl);
+ break;
+ }
+ printf(" %" PRIu64 "\n", sg_get_unaligned_be64(bp + 4));
+ break;
+ case 0x2:
+ printf(" Maximum implicitly open zones:");
+ if ((pl < 8) || (num < 8)) {
+ if (num < 8)
+ pr2serr("\n truncated by response length, expected "
+ "at least 8 bytes\n");
+ else
+ pr2serr("\n parameter length >= 8 expected, got %d\n",
+ pl);
+ break;
+ }
+ printf(" %" PRIu64 "\n", sg_get_unaligned_be64(bp + 4));
+ break;
+ case 0x3:
+ printf(" Minimum empty zones:");
+ if ((pl < 8) || (num < 8)) {
+ if (num < 8)
+ pr2serr("\n truncated by response length, expected "
+ "at least 8 bytes\n");
+ else
+ pr2serr("\n parameter length >= 8 expected, got %d\n",
+ pl);
+ break;
+ }
+ printf(" %" PRIu64 "\n", sg_get_unaligned_be64(bp + 4));
+ break;
+ case 0x4:
+ printf(" Maximum number of non-sequential zones:");
+ if ((pl < 8) || (num < 8)) {
+ if (num < 8)
+ pr2serr("\n truncated by response length, expected "
+ "at least 8 bytes\n");
+ else
+ pr2serr("\n parameter length >= 8 expected, got %d\n",
+ pl);
+ break;
+ }
+ printf(" %" PRIu64 "\n", sg_get_unaligned_be64(bp + 4));
+ break;
+ case 0x5:
+ printf(" Zones emptied:");
+ if ((pl < 8) || (num < 8)) {
+ if (num < 8)
+ pr2serr("\n truncated by response length, expected "
+ "at least 8 bytes\n");
+ else
+ pr2serr("\n parameter length >= 8 expected, got %d\n",
+ pl);
+ break;
+ }
+ printf(" %" PRIu64 "\n", sg_get_unaligned_be64(bp + 4));
+ break;
+ case 0x6:
+ printf(" Suboptimal write commands:");
+ if ((pl < 8) || (num < 8)) {
+ if (num < 8)
+ pr2serr("\n truncated by response length, expected "
+ "at least 8 bytes\n");
+ else
+ pr2serr("\n parameter length >= 8 expected, got %d\n",
+ pl);
+ break;
+ }
+ printf(" %" PRIu64 "\n", sg_get_unaligned_be64(bp + 4));
+ break;
+ case 0x7:
+ printf(" Commands exceeding optimal limit:");
+ if ((pl < 8) || (num < 8)) {
+ if (num < 8)
+ pr2serr("\n truncated by response length, expected "
+ "at least 8 bytes\n");
+ else
+ pr2serr("\n parameter length >= 8 expected, got %d\n",
+ pl);
+ break;
+ }
+ printf(" %" PRIu64 "\n", sg_get_unaligned_be64(bp + 4));
+ break;
+ case 0x8:
+ printf(" Failed explicit opens:");
+ if ((pl < 8) || (num < 8)) {
+ if (num < 8)
+ pr2serr("\n truncated by response length, expected "
+ "at least 8 bytes\n");
+ else
+ pr2serr("\n parameter length >= 8 expected, got %d\n",
+ pl);
+ break;
+ }
+ printf(" %" PRIu64 "\n", sg_get_unaligned_be64(bp + 4));
+ break;
+ case 0x9:
+ printf(" Read rule violations:");
+ if ((pl < 8) || (num < 8)) {
+ if (num < 8)
+ pr2serr("\n truncated by response length, expected "
+ "at least 8 bytes\n");
+ else
+ pr2serr("\n parameter length >= 8 expected, got %d\n",
+ pl);
+ break;
+ }
+ printf(" %" PRIu64 "\n", sg_get_unaligned_be64(bp + 4));
+ break;
+ case 0xa:
+ printf(" Write rule violations:");
+ if ((pl < 8) || (num < 8)) {
+ if (num < 8)
+ pr2serr("\n truncated by response length, expected "
+ "at least 8 bytes\n");
+ else
+ pr2serr("\n parameter length >= 8 expected, got %d\n",
+ pl);
+ break;
+ }
+ printf(" %" PRIu64 "\n", sg_get_unaligned_be64(bp + 4));
+ break;
+ default:
+ printf(" Reserved [parameter_code=0x%x]:\n", pc);
+ dStrHex((const char *)bp, ((pl < num) ? pl : num), 0);
+ break;
+ }
+ if (op->do_pcb)
+ printf(" <%s>\n", get_pcb_str(bp[2], str, sizeof(str)));
+ if (op->filter_given)
+ break;
+skip:
+ num -= pl;
+ bp += pl;
+ }
+ return true;
+}
+
/* PENDING_DEFECTS_SUBPG [0x15,0x1] introduced: SBC-4 */
static bool
show_pending_defects_page(const uint8_t * resp, int len,
diff --git a/src/sg_ses.c b/src/sg_ses.c
index 26a36e63..017bda6c 100644
--- a/src/sg_ses.c
+++ b/src/sg_ses.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2004-2016 Douglas Gilbert.
+ * Copyright (c) 2004-2017 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.
@@ -31,7 +31,7 @@
* commands tailored for SES (enclosure) devices.
*/
-static const char * version_str = "2.19 20160610"; /* ses3r13 */
+static const char * version_str = "2.20 20170904"; /* ses4r01 */
#define MX_ALLOC_LEN ((64 * 1024) - 4) /* max allowable for big enclosures */
#define MX_ELEM_HDR 1024
@@ -215,11 +215,11 @@ struct join_row_t {
enum fj_select_t {FJ_IOE, FJ_EOE, FJ_AESS, FJ_SAS_CON};
-/* In some cases a type_desc_hdr_t array potentially with the matching
- * join array if present. */
+/* Instance ('tes' in main() ) holds a type_desc_hdr_t array potentially with
+ the matching join array if present. */
struct th_es_t {
const struct type_desc_hdr_t * th_base;
- int num_ths;
+ int num_ths; /* items in array pointed to by th_base */
struct join_row_t * j_base;
int num_j_rows;
int num_j_eoe;
@@ -596,6 +596,8 @@ static struct acronym2tuple ecs_a2t_arr[] = {
{"muted", AUD_ALARM_ETC, 3, 6, 1, "status only: alarm is muted"},
{"off", POWER_SUPPLY_ETC, 3, 4, 1, "Not providing power"},
{"off", COOLING_ETC, 3, 4, 1, "Not providing cooling"},
+ {"offset_temp", TEMPERATURE_ETC, 1, 5, 6, "Offset for reference "
+ "temperature"},
{"ok", ARRAY_DEV_ETC, 1, 7, 1, NULL},
{"on", COOLING_ETC, 3, 5, 1, NULL},
{"on", POWER_SUPPLY_ETC, 3, 5, 1, "0: turn (remain) off; 1: turn on"},
@@ -609,24 +611,29 @@ static struct acronym2tuple ecs_a2t_arr[] = {
{"overvoltage", POWER_SUPPLY_ETC, 2, 3, 1, "DC overvoltage"},
{"overvoltage", VOLT_SENSOR_ETC, 1, 1, 1, "overvoltage"},
{"overvoltage_warn", POWER_SUPPLY_ETC, 1, 3, 1, "DC overvoltage warning"},
- {"remind", AUD_ALARM_ETC, 3, 4, 1, NULL},
- {"report", ENC_SCELECTR_ETC, 2, 0, 1, NULL},
- {"report", SCC_CELECTR_ETC, 2, 0, 1, NULL},
- {"report", SCSI_IPORT_ETC, 2, 0, 1, NULL},
- {"report", SCSI_TPORT_ETC, 2, 0, 1, NULL},
- {"rqst_mute", AUD_ALARM_ETC, 3, 7, 1,
- "status only: alarm was manually muted"},
{"pow_cycle", ENCLOSURE_ETC, 2, 7, 2,
"0: no; 1: start in pow_c_delay minutes; 2: cancel"},
{"pow_c_delay", ENCLOSURE_ETC, 2, 5, 6,
- "delay in minutes before starting power cycle"},
- {"pow_c_duration", ENCLOSURE_ETC, 3, 7, 6, NULL},
+ "delay in minutes before starting power cycle (max: 60)"},
+ {"pow_c_duration", ENCLOSURE_ETC, 3, 7, 6,
+ "0: power off, restore within 1 minute; <=60: restore within that many "
+ "minutes; 63: power off, wait for manual power on"},
+ /* slightly different in Enclosure status element */
{"pow_c_time", ENCLOSURE_ETC, 2, 7, 6,
- "time in minutes remaining until starting power cycle"},
+ "time in minutes remaining until starting power cycle; 0: not "
+ "scheduled; <=60: scheduled in that many minutes; 63: in zero minutes"},
{"prdfail", -1, 0, 6, 1, "predict failure"},
{"rebuildremap", ARRAY_DEV_ETC, 1, 1, 1, NULL},
{"remove", DEVICE_ETC, 2, 2, 1, NULL},
{"remove", ARRAY_DEV_ETC, 2, 2, 1, NULL},
+ {"remind", AUD_ALARM_ETC, 3, 4, 1, NULL},
+ {"report", ENC_SCELECTR_ETC, 2, 0, 1, NULL},
+ {"report", SCC_CELECTR_ETC, 2, 0, 1, NULL},
+ {"report", SCSI_IPORT_ETC, 2, 0, 1, NULL},
+ {"report", SCSI_TPORT_ETC, 2, 0, 1, NULL},
+ {"rqst_mute", AUD_ALARM_ETC, 3, 7, 1,
+ "status only: alarm was manually muted"},
+ {"rqst_override", TEMPERATURE_ETC, 3, 7, 1, "Request(ed) override"},
{"rrabort", ARRAY_DEV_ETC, 1, 0, 1, "rebuild/remap abort"},
{"rsvddevice", ARRAY_DEV_ETC, 1, 6, 1, "reserved device"},
{"select_element", ENC_SCELECTR_ETC, 2, 0, 1, NULL},
@@ -637,6 +644,7 @@ static struct acronym2tuple ecs_a2t_arr[] = {
"0: leave; 1: lowest... 7: highest"},
{"size_mult", NV_CACHE_ETC, 1, 1, 2, NULL},
{"swap", -1, 0, 4, 1, NULL}, /* Reset swap */
+ {"temp", TEMPERATURE_ETC, 2, 7, 8, "(Requested) temperature"},
{"unlock", DOOR_ETC, 3, 0, 1, NULL},
{"undertemp_fail", TEMPERATURE_ETC, 3, 1, 1, "Undertemperature failure"},
{"undertemp_warn", TEMPERATURE_ETC, 3, 0, 1, "Undertemperature warning"},
@@ -645,7 +653,7 @@ static struct acronym2tuple ecs_a2t_arr[] = {
{"undervoltage_warn", POWER_SUPPLY_ETC, 1, 2, 1,
"DC undervoltage warning"},
{"ups_fail", UI_POWER_SUPPLY_ETC, 2, 2, 1, NULL},
- {"urgency", AUD_ALARM_ETC, 3, 3, 4, NULL},
+ {"urgency", AUD_ALARM_ETC, 3, 3, 4, NULL}, /* Tone urgency control bits */
{"voltage", VOLT_SENSOR_ETC, 2, 7, 16, "voltage in centivolts"},
{"warning", UI_POWER_SUPPLY_ETC, 2, 1, 1, NULL},
{"warning", ENCLOSURE_ETC, 3, 0, 1, NULL},
@@ -795,7 +803,8 @@ usage(int help_num)
" [--page=PG] [--sas-addr=SA] [--set=STR] "
"[--verbose]\n"
" DEVICE\n\n"
- " sg_ses [--enumerate] [--help] [--list] [--version]\n\n"
+ " sg_ses [--enumerate] [--help] [--index=IIA] [--list] "
+ "[--version]\n\n"
" where the main options are:\n"
" --clear=STR|-C STR clear field by acronym or position\n"
" --control|-c send control information (def: fetch "
@@ -1999,10 +2008,7 @@ find_sas_connector_type(int conn_type, bool abridged, char * buff,
"[max 16 phys]");
break;
case 0xf:
- if (abridged)
- snprintf(buff, buff_len, "VS external connector");
- else
- snprintf(buff, buff_len, "Vendor specific external connector");
+ snprintf(buff, buff_len, "Vendor specific");
break;
case 0x10:
if (abridged)
@@ -2031,6 +2037,41 @@ find_sas_connector_type(int conn_type, bool abridged, char * buff,
snprintf(buff, buff_len, "Mini SAS HD 8i receptacle (SFF-8643) "
"[max 8 phys]");
break;
+ case 0x14:
+ if (abridged)
+ snprintf(buff, buff_len, "Mini SAS HD 16i");
+ else
+ snprintf(buff, buff_len, "Mini SAS HD 16i receptacle (SFF-8643) "
+ "[max 16 phys]");
+ break;
+ case 0x15:
+ if (abridged)
+ snprintf(buff, buff_len, "SAS SlimLine 4i");
+ else
+ snprintf(buff, buff_len, "SAS SlimLine 4i (SFF-8654) "
+ "[max 4 phys]");
+ break;
+ case 0x16:
+ if (abridged)
+ snprintf(buff, buff_len, "SAS SlimLine 8i");
+ else
+ snprintf(buff, buff_len, "SAS SlimLine 8i (SFF-8654) "
+ "[max 8 phys]");
+ break;
+ case 0x17:
+ if (abridged)
+ snprintf(buff, buff_len, "SAS MiniLink 4i");
+ else
+ snprintf(buff, buff_len, "SAS MiniLink 4i (SFF-8612) "
+ "[max 4 phys]");
+ break;
+ case 0x18:
+ if (abridged)
+ snprintf(buff, buff_len, "SAS MiniLink 8i");
+ else
+ snprintf(buff, buff_len, "SAS MiniLink 8i (SFF-8612) "
+ "[max 8 phys]");
+ break;
case 0x20:
if (abridged)
snprintf(buff, buff_len, "SAS Drive backplane");
@@ -2111,6 +2152,28 @@ find_sas_connector_type(int conn_type, bool abridged, char * buff,
snprintf(buff, buff_len, "Multifunction 12 Gb/s 6x unshielded "
"plug (SFF-8639)");
break;
+ case 0x2c:
+ if (abridged)
+ snprintf(buff, buff_len, "SAS MultiLink Drive backplane "
+ "receptacle");
+ else
+ snprintf(buff, buff_len, "SAS MultiLink Drive backplane "
+ "receptacle (SFF-8630)");
+ break;
+ case 0x2d:
+ if (abridged)
+ snprintf(buff, buff_len, "SAS MultiLink Drive backplane plug");
+ else
+ snprintf(buff, buff_len, "SAS MultiLink Drive backplane plug "
+ "(SFF-8630)");
+ break;
+ case 0x2e:
+ if (abridged)
+ snprintf(buff, buff_len, "Reserved");
+ else
+ snprintf(buff, buff_len, "Reserved for internal connectors to "
+ "end device");
+ break;
case 0x2f:
if (abridged)
snprintf(buff, buff_len, "SAS virtual connector");
@@ -2123,6 +2186,22 @@ find_sas_connector_type(int conn_type, bool abridged, char * buff,
else
snprintf(buff, buff_len, "Vendor specific internal connector");
break;
+ case 0x40:
+ if (abridged)
+ snprintf(buff, buff_len, "SAS high density drive backplane "
+ "receptacle");
+ else
+ snprintf(buff, buff_len, "SAS high density drive backplane "
+ "receptacle (SFF-8631) [max 8 phys]");
+ break;
+ case 0x41:
+ if (abridged)
+ snprintf(buff, buff_len, "SAS high density drive backplane "
+ "plug");
+ else
+ snprintf(buff, buff_len, "SAS high density drive backplane "
+ "plug (SFF-8631) [max 8 phys]");
+ break;
default:
if (conn_type < 0x10)
snprintf(buff, buff_len, "unknown external connector type: 0x%x",
@@ -3406,8 +3485,8 @@ supported_pages_sdg(const char * leadin, const uint8_t * resp,
static struct diag_page_code mc_status_arr[] = {
{0x0, "No download microcode operation in progress"},
{0x1, "Download in progress, awaiting more"},
- {0x2, "Download complete, updating storage"},
- {0x3, "Updating storage with deferred microcode"},
+ {0x2, "Download complete, updating non-volatile storage"},
+ {0x3, "Updating non-volatile storage with deferred microcode"},
{0x10, "Complete, no error, starting now"},
{0x11, "Complete, no error, start after hard reset or power cycle"},
{0x12, "Complete, no error, start after power cycle"},
@@ -4895,10 +4974,21 @@ enumerate_work(const struct opts_t * op)
printf(" %s [%s] [0x%x]\n", etp->desc, etp->abbrev,
etp->elem_type_code);
} else {
+ char bb[64];
+ bool given_et = false;
+
/* command line has multiple --enumerate and/or --list options */
printf("--clear, --get, --set acronyms for Enclosure Status/Control "
- "['es' or 'ec'] page:\n");
+ "['es' or 'ec'] page");
+ if (op->ind_given && op->ind_etp &&
+ (cp = etype_str(op->ind_etp->elem_type_code, bb, sizeof(bb)))) {
+ printf("\n(element type: %s)", bb);
+ given_et = true;
+ }
+ printf(":\n");
for (ap = ecs_a2t_arr; ap->acron; ++ap) {
+ if (given_et && (op->ind_etp->elem_type_code != ap->etype))
+ continue;
cp = (ap->etype < 0) ? "*" : etype_str(ap->etype, b, sizeof(b));
snprintf(a, sizeof(a), " %s [%s] [%d:%d:%d]", ap->acron,
(cp ? cp : "??"), ap->start_byte, ap->start_bit,
@@ -4908,6 +4998,8 @@ enumerate_work(const struct opts_t * op)
else
printf("%s\n", a);
}
+ if (given_et)
+ return;
printf("\n--clear, --get, --set acronyms for Threshold In/Out "
"['th'] page:\n");
for (ap = th_a2t_arr; ap->acron; ++ap) {
diff --git a/src/sg_vpd.c b/src/sg_vpd.c
index 4164d506..e3b0fc68 100644
--- a/src/sg_vpd.c
+++ b/src/sg_vpd.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2006-2016 Douglas Gilbert.
+ * Copyright (c) 2006-2017 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.
@@ -37,7 +37,7 @@
*/
-static const char * version_str = "1.25 20160701"; /* spc5r10 + sbc4r11 */
+static const char * version_str = "1.26 20170911"; /* spc5r16 + sbc4r14 */
/* These structures are duplicates of those of the same name in
@@ -86,8 +86,8 @@ void dup_sanity_chk(int sz_opts_t, int sz_values_name_t);
/* standard VPD pages, in ascending page number order */
#define VPD_SUPPORTED_VPDS 0x0
#define VPD_UNIT_SERIAL_NUM 0x80
-#define VPD_IMP_OP_DEF 0x81 /* obsolete in SPC-2 */
-#define VPD_ASCII_OP_DEF 0x82 /* obsolete in SPC-2 */
+#define VPD_IMP_OP_DEF 0x81 /* obsolete in SPC-2 */
+#define VPD_ASCII_OP_DEF 0x82 /* obsolete in SPC-2 */
#define VPD_DEVICE_ID 0x83
#define VPD_SOFTW_INF_ID 0x84
#define VPD_MAN_NET_ADDR 0x85
@@ -99,26 +99,27 @@ void dup_sanity_chk(int sz_opts_t, int sz_values_name_t);
#define VPD_DEVICE_CONSTITUENTS 0x8b
#define VPD_CFA_PROFILE_INFO 0x8c
#define VPD_POWER_CONSUMPTION 0x8d
-#define VPD_3PARTY_COPY 0x8f /* 3PC, XCOPY, SPC-4, SBC-3 */
+#define VPD_3PARTY_COPY 0x8f /* 3PC, XCOPY, SPC-4, SBC-3 */
#define VPD_PROTO_LU 0x90
#define VPD_PROTO_PORT 0x91
-#define VPD_BLOCK_LIMITS 0xb0 /* SBC-3 */
-#define VPD_SA_DEV_CAP 0xb0 /* SSC-3 */
-#define VPD_OSD_INFO 0xb0 /* OSD */
-#define VPD_BLOCK_DEV_CHARS 0xb1 /* SBC-3 */
-#define VPD_MAN_ASS_SN 0xb1 /* SSC-3, ADC-2 */
-#define VPD_SECURITY_TOKEN 0xb1 /* OSD */
-#define VPD_TA_SUPPORTED 0xb2 /* SSC-3 */
-#define VPD_LB_PROVISIONING 0xb2 /* SBC-3 */
-#define VPD_REFERRALS 0xb3 /* SBC-3 */
-#define VPD_AUTOMATION_DEV_SN 0xb3 /* SSC-3 */
-#define VPD_SUP_BLOCK_LENS 0xb4 /* SBC-4 */
-#define VPD_DTDE_ADDRESS 0xb4 /* SSC-4 */
-#define VPD_BLOCK_DEV_C_EXTENS 0xb5 /* SBC-4 */
-#define VPD_LB_PROTECTION 0xb5 /* SSC-5 */
-#define VPD_ZBC_DEV_CHARS 0xb6 /* ZBC */
-#define VPD_BLOCK_LIMITS_EXT 0xb7 /* SBC-4 */
-#define VPD_NO_RATHER_STD_INQ -2 /* request for standard inquiry */
+#define VPD_SCSI_FEATURE_SETS 0x92 /* spc5r11 */
+#define VPD_BLOCK_LIMITS 0xb0 /* SBC-3 */
+#define VPD_SA_DEV_CAP 0xb0 /* SSC-3 */
+#define VPD_OSD_INFO 0xb0 /* OSD */
+#define VPD_BLOCK_DEV_CHARS 0xb1 /* SBC-3 */
+#define VPD_MAN_ASS_SN 0xb1 /* SSC-3, ADC-2 */
+#define VPD_SECURITY_TOKEN 0xb1 /* OSD */
+#define VPD_TA_SUPPORTED 0xb2 /* SSC-3 */
+#define VPD_LB_PROVISIONING 0xb2 /* SBC-3 */
+#define VPD_REFERRALS 0xb3 /* SBC-3 */
+#define VPD_AUTOMATION_DEV_SN 0xb3 /* SSC-3 */
+#define VPD_SUP_BLOCK_LENS 0xb4 /* sbc4r01 */
+#define VPD_DTDE_ADDRESS 0xb4 /* SSC-4 */
+#define VPD_BLOCK_DEV_C_EXTENS 0xb5 /* sbc4r02 */
+#define VPD_LB_PROTECTION 0xb5 /* SSC-5 */
+#define VPD_ZBC_DEV_CHARS 0xb6 /* zbc-r01b */
+#define VPD_BLOCK_LIMITS_EXT 0xb7 /* sbc4r08 */
+#define VPD_NO_RATHER_STD_INQ -2 /* request for standard inquiry */
/* Device identification VPD page associations */
#define VPD_ASSOC_LU 0
@@ -213,13 +214,14 @@ static struct svpd_values_name_t standard_vpd_pg[] = {
{VPD_REFERRALS, 0, 0, "ref", "Referrals (SBC)"},
{VPD_SA_DEV_CAP, 0, 1, "sad",
"Sequential access device capabilities (SSC)"},
+ {VPD_SUP_BLOCK_LENS, 0, 0, "sbl", "Supported block lengths and "
+ "protection types (SBC)"},
+ {VPD_SCSI_FEATURE_SETS, 0, -1, "sfs", "SCSI feature sets"},
{VPD_SOFTW_INF_ID, 0, -1, "sii", "Software interface identification"},
{VPD_NO_RATHER_STD_INQ, 0, -1, "sinq", "Standard inquiry response"},
{VPD_UNIT_SERIAL_NUM, 0, -1, "sn", "Unit serial number"},
{VPD_SCSI_PORTS, 0, -1, "sp", "SCSI ports"},
{VPD_SECURITY_TOKEN, 0, 0x11, "st", "Security token (OSD)"},
- {VPD_SUP_BLOCK_LENS, 0, 0, "sbl", "Supported block lengths and "
- "protection types (SBC)"},
{VPD_SUPPORTED_VPDS, 0, -1, "sv", "Supported VPD pages"},
{VPD_TA_SUPPORTED, 0, 1, "tas", "TapeAlert supported flags (SSC)"},
{VPD_3PARTY_COPY, 0, -1, "tpc", "Third party copy"},
@@ -1309,6 +1311,7 @@ decode_x_inq_vpd(unsigned char * b, int len, int do_hex, int do_long,
printf(" LUICLR=%d\n", !!(b[7] & 0x1));
printf(" LU_COLL_TYPE=%d\n", (b[8] >> 5) & 0x7); /* spc5r09 */
printf(" R_SUP=%d\n", !!(b[8] & 0x10));
+ printf(" RTD_SUP=%d\n", !!(b[8] & 0x8)); /* spc5r11 */
printf(" HSSRELEF=%d\n", !!(b[8] & 0x2)); /* spc5r02 */
printf(" CBCS=%d\n", !!(b[8] & 0x1)); /* obsolete in spc5r01 */
printf(" Multi I_T nexus microcode download=%d\n", b[9] & 0xf);
@@ -2020,6 +2023,54 @@ decode_proto_port_vpd(unsigned char * buff, int len, int do_hex)
}
}
+/* VPD_SCSI_FEATURE_SETS [0x92] (sfs) */
+static void
+decode_feature_sets_vpd(unsigned char * buff, int len,
+ const struct opts_t * op)
+{
+ int k, bump;
+ uint16_t sf_code;
+ bool found;
+ unsigned char * bp;
+ char b[64];
+
+ if ((1 == op->do_hex) || (op->do_hex > 2)) {
+ dStrHex((const char *)buff, len, (1 == op->do_hex) ? 1 : -1);
+ return;
+ }
+ if (len < 4) {
+ pr2serr("SCSI Feature sets VPD page length too short=%d\n", len);
+ return;
+ }
+ len -= 8;
+ bp = buff + 8;
+ for (k = 0; k < len; k += bump, bp += bump) {
+ sf_code = sg_get_unaligned_be16(bp);
+ bump = 2;
+ if ((k + bump) > len) {
+ pr2serr("SCSI Feature sets, short descriptor length=%d, "
+ "left=%d\n", bump, (len - k));
+ return;
+ }
+ if (2 == op->do_hex)
+ dStrHex((const char *)bp + 8, 2, 1);
+ else if (op->do_hex > 2)
+ dStrHex((const char *)bp, 2, 1);
+ else {
+ printf(" %s", sg_get_sfs_str(sf_code, -2, sizeof(b), b,
+ &found, op->verbose));
+ if (op->verbose == 1)
+ printf(" [0x%x]\n", (unsigned int)sf_code);
+ else if (op->verbose > 1)
+ printf(" [0x%x] found=%s\n", (unsigned int)sf_code,
+ found ? "true" : "false");
+ else
+ printf("\n");
+ }
+ }
+}
+
+
/* VPD_BLOCK_LIMITS sbc */
/* VPD_SA_DEV_CAP ssc */
/* VPD_OSD_INFO osd */
@@ -2175,9 +2226,12 @@ decode_b1_vpd(unsigned char * buff, int len, int do_hex, int pdt)
break;
}
printf(" ZONED=%d\n", (buff[8] >> 4) & 0x3); /* sbc4r04 */
+ printf(" RBWZ=%d\n", !!(buff[8] & 0x8)); /* sbc4r12 */
printf(" BOCS=%d\n", !!(buff[8] & 0x4)); /* sbc4r07 */
printf(" FUAB=%d\n", !!(buff[8] & 0x2));
printf(" VBULS=%d\n", !!(buff[8] & 0x1));
+ printf(" DEPOPULATION_TIME=%u (seconds)\n",
+ sg_get_unaligned_be32(buff + 12)); /* added sbc4r14 */
break;
case PDT_TAPE: case PDT_MCHANGER: case PDT_ADC:
printf(" Manufacturer-assigned serial number: %.*s\n",
@@ -2246,7 +2300,7 @@ decode_block_lb_prov_vpd(unsigned char * b, int len, const struct opts_t * op)
return 0;
}
-/* VPD_SUP_BLOCK_LENS 0xb4 */
+/* VPD_SUP_BLOCK_LENS 0xb4 (added sbc4r01) */
static void
decode_sup_block_lens_vpd(unsigned char * buff, int len)
{
@@ -2276,7 +2330,7 @@ decode_sup_block_lens_vpd(unsigned char * buff, int len)
}
}
-/* VPD_BLOCK_DEV_C_EXTENS 0xb5 */
+/* VPD_BLOCK_DEV_C_EXTENS 0xb5 (added sbc4r02) */
static void
decode_block_dev_char_ext_vpd(unsigned char * b, int len)
{
@@ -3013,6 +3067,24 @@ svpd_decode_t10(int sg_fd, struct opts_t * op, int subvalue, int off)
return 0;
}
break;
+ case VPD_SCSI_FEATURE_SETS: /* 0x92 */
+ if (allow_name)
+ printf("SCSI Feature sets:\n");
+ res = vpd_fetch_page_from_dev(sg_fd, rp, pn, op->maxlen, vb, &len);
+ if (0 == res) {
+ if (op->do_raw)
+ dStrRaw((const char *)rp, len);
+ else {
+ pdt = rp[0] & 0x1f;
+ if (vb || long_notquiet)
+ printf(" [PQual=%d Peripheral device type: %s]\n",
+ (rp[0] & 0xe0) >> 5,
+ sg_get_pdt_str(pdt, sizeof(b), b));
+ decode_feature_sets_vpd(rp, len, op);
+ }
+ return 0;
+ }
+ break;
case 0xb0: /* depends on pdt */
res = vpd_fetch_page_from_dev(sg_fd, rp, pn, op->maxlen, vb, &len);
if (0 == res) {