aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog2
-rw-r--r--README33
-rw-r--r--README.freebsd3
-rw-r--r--README.solaris3
-rw-r--r--README.tru643
-rw-r--r--README.win323
-rw-r--r--debian/changelog2
-rw-r--r--doc/Makefile.am36
-rw-r--r--doc/sg_referrals.867
-rw-r--r--sg3_utils.spec4
-rw-r--r--src/sg_inq.c18
-rw-r--r--src/sg_referrals.c105
-rw-r--r--src/sg_vpd.c6
13 files changed, 199 insertions, 86 deletions
diff --git a/ChangeLog b/ChangeLog
index 8d06e635..d42a6210 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.30 [20100906] [svn: r353]
+Changelog for sg3_utils-1.30 [20100912] [svn: r354]
- sg_referrals: new utility for REPORT REFERRALS
- sg_inq: update version descriptor list to spc4r26
- sg_lib: sync asc/ascq list to spc4r25 (no change to r26)
diff --git a/README b/README
index 698e82b5..1f8d7081 100644
--- a/README
+++ b/README
@@ -198,11 +198,11 @@ subdirectory of the sg3_utils package:
sg_get_lba_status, sg_format, sg_ident, sg_inq, sg_logs, sg_luns, sg_map,
sg_map26, sg_modes, sg_opcodes, sg_persist, sg_prevent, sg_raw, sg_rbuf,
sg_rdac, sg_read, sg_readcap, sg_read_block_limits, sg_read_buffer,
- sg_read_long, sg_reassign, sg_request, sg_reset, sg_rmsn, sg_rtpg,
- sg_safte, sg_sat_identify, sg_sat_phy_event, sg_sat_set_features,
- sg_scan, sg_senddiag, sg_ses, sg_start, sg_stpg, sg_sync, sg_test_rwbuff,
- sg_turs, sg_unmap, sg_verify, sg_vpd, sg_write_buffer, sg_write_long,
- sg_write_same, sg_wr_mode
+ sg_read_long, sg_reassign, sg_referrals, sg_request, sg_reset, sg_rmsn,
+ sg_rtpg, sg_safte, sg_sat_identify, sg_sat_phy_event,
+ sg_sat_set_features, sg_scan, sg_senddiag, sg_ses, sg_start, sg_stpg,
+ sg_sync, sg_test_rwbuff, sg_turs, sg_unmap, sg_verify, sg_vpd,
+ sg_write_buffer, sg_write_long, sg_write_same, sg_wr_mode
Each of the above utilities depends on header files found in the 'include'
subdirectory and library code found in the 'lib' subdirectory. Associated
@@ -222,11 +222,6 @@ going to the 'doc' subdirectory and executing something like this:
To see which SCSI commands (and ATA commands) are used by these utilities
refer to the COVERAGE file.
-Here is a list in alphabetical order of utilities found in the 'archive'
-subdirectory:
- - isosize, scsi_devfs_scan, sg_debug, sgq_dd
-Some of these utilities have man pages.
-
Here is a list in alphabetical order of utilities found in the 'examples'
subdirectory:
- bsg_queue_tst, sg_excl, scsi_inquiry, sg_iovec_tst, sg_queue_tst,
@@ -266,14 +261,6 @@ SCSI sub system mid level and so is common to all sd, sr, st and sg devices.
That ioctl is deprecated in the lk 2.6 series. This program has been placed
in the "examples" subdirectory.
-"sgq_dd" is yet another variant of dd found in the archive directory.
-From the user's point of view it is very similar to sgp_dd but uses a
-non-blocking state machine rather then POSIX threads for parallelism.
-
-"sg_debug" is effectively defunct now. The user can instead execute:
-'cat /proc/scsi/sg/debug' . This command has been placed in the archive
-directory.
-
"sg_simple1" and "sg_simple2" are example programs demonstrating calls
to the SCSI INQUIRY and TEST UNIT READY commands. They only differ in their
error processing: sg_simple1 uses sg_lib.[hc] for error processing while
@@ -333,10 +320,10 @@ or using '-O' as the first command line option.
The more recent utilities that use "getopt_long" only are:
- sg_format sg_get_config sg_get_lba_status sg_ident sg_luns sg_map26
sg_persist sg_prevent sg_raw sg_read_block_limits sg_read_buffer
- sg_read_long sg_reassign sg_requests sg_rmsn sg_rtpg sg_safte
- sg_sat_identify sg_sat_phy_event sg_sat_set_features sg_scan(w) sg_ses
- sg_stpg sg_sync sg_test_rwbuf sg_unmap sg_verify sg_vpd sg_write_buffer
- sg_write_long sg_write_same sg_wr_mode
+ sg_read_long sg_reassign sg_referrals sg_requests sg_rmsn sg_rtpg
+ sg_safte sg_sat_identify sg_sat_phy_event sg_sat_set_features
+ sg_scan(w) sg_ses sg_stpg sg_sync sg_test_rwbuf sg_unmap sg_verify
+ sg_vpd sg_write_buffer sg_write_long sg_write_same sg_wr_mode
Dangerous code
@@ -358,4 +345,4 @@ See http://sg.danny.cz/sg/tools.html
Doug Gilbert
-19th August 2010
+13th September 2010
diff --git a/README.freebsd b/README.freebsd
index d0da5709..1db80d61 100644
--- a/README.freebsd
+++ b/README.freebsd
@@ -31,6 +31,7 @@ Here is a list of utilities that have been ported:
sg_read_long
sg_readcap
sg_reassign
+ sg_referrals
sg_requests
sg_rmsn
sg_rtpg
@@ -103,4 +104,4 @@ utilities.
Doug Gilbert
-10th April 2010
+13th September 2010
diff --git a/README.solaris b/README.solaris
index 75f30cac..1288802f 100644
--- a/README.solaris
+++ b/README.solaris
@@ -29,6 +29,7 @@ Here is a list of utilities that have been ported:
sg_read_long
sg_readcap
sg_reassign
+ sg_referrals
sg_requests
sg_rmsn
sg_rtpg
@@ -133,4 +134,4 @@ disks to accept SCSI commands including the SCSI ATA PASS THROUGH commands.
Doug Gilbert
-10th April 2010
+13th September 2010
diff --git a/README.tru64 b/README.tru64
index 9c9bea04..f35ee476 100644
--- a/README.tru64
+++ b/README.tru64
@@ -26,6 +26,7 @@ Here is a list of utilities that have been ported:
sg_read_long
sg_readcap
sg_reassign
+ sg_referrals
sg_requests
sg_rmsn
sg_rtpg
@@ -90,4 +91,4 @@ subdirectory. Currently only the Tru64 port uses it.
Doug Gilbert
-10th April 2010
+13th September 2010
diff --git a/README.win32 b/README.win32
index 5df272a9..8ea76e55 100644
--- a/README.win32
+++ b/README.win32
@@ -41,6 +41,7 @@ Here is a list of utilities that have been ported:
sg_read_long
sg_readcap
sg_reassign
+ sg_referrals
sg_requests
sg_rmsn
sg_rtpg
@@ -195,4 +196,4 @@ mode" with the setmode() Windows command.
Doug Gilbert
-10th April 2010
+13th September 2010
diff --git a/debian/changelog b/debian/changelog
index 6bdbfd4c..2e94886c 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -2,7 +2,7 @@ sg3-utils (1.30-0.1) unstable; urgency=low
* New upstream version
- -- Doug Gilbert <dgilbert@interlog.com> Thu, 19 Aug 2010 11:00:00 -0400
+ -- Doug Gilbert <dgilbert@interlog.com> Mon, 13 Sep 2010 11:00:00 -0400
sg3-utils (1.29-0.1) unstable; urgency=low
diff --git a/doc/Makefile.am b/doc/Makefile.am
index a5eb9290..2c4f75e3 100644
--- a/doc/Makefile.am
+++ b/doc/Makefile.am
@@ -11,13 +11,13 @@ man_MANS = \
sg3_utils.8 \
scsi_readcap.8 scsi_ready.8 scsi_start.8 scsi_stop.8 \
sg_dd.8 sg_emc_trespass.8 sg_format.8 sg_get_config.8 \
- sg_get_lba_status.8 sg_ident.8 \
- sginfo.8 sg_inq.8 sg_logs.8 sg_luns.8 sg_map26.8 sg_map.8 \
- sgm_dd.8 sg_modes.8 sg_opcodes.8 sgp_dd.8 sg_persist.8 \
- sg_prevent.8 sg_raw.8 sg_rbuf.8 sg_rdac.8 sg_read.8 sg_readcap.8 \
- sg_read_block_limits.8 sg_read_buffer.8 sg_read_long.8 sg_reassign.8 \
- sg_requests.8 sg_reset.8 sg_rmsn.8 sg_rtpg.8 sg_safte.8 \
- sg_sat_identify.8 sg_sat_phy_event.8 sg_sat_set_features.8 sg_scan.8 \
+ sg_get_lba_status.8 sg_ident.8 sginfo.8 sg_inq.8 sg_logs.8 \
+ sg_luns.8 sg_map26.8 sg_map.8 sgm_dd.8 sg_modes.8 sg_opcodes.8 \
+ sgp_dd.8 sg_persist.8 sg_prevent.8 sg_raw.8 sg_rbuf.8 sg_rdac.8 \
+ sg_read.8 sg_readcap.8 sg_read_block_limits.8 sg_read_buffer.8 \
+ sg_read_long.8 sg_reassign.8 sg_referrals.8 sg_requests.8 \
+ sg_reset.8 sg_rmsn.8 sg_rtpg.8 sg_safte.8 sg_sat_identify.8 \
+ sg_sat_phy_event.8 sg_sat_set_features.8 sg_scan.8 \
sg_senddiag.8 sg_ses.8 sg_start.8 sg_stpg.8 sg_sync.8 \
sg_test_rwbuf.8 sg_turs.8 sg_unmap.8 sg_verify.8 sg_vpd.8 \
sg_write_buffer.8 sg_write_long.8 sg_write_same.8 sg_wr_mode.8
@@ -37,10 +37,10 @@ man_MANS = \
sg3_utils.8 \
scsi_readcap.8 scsi_ready.8 scsi_start.8 scsi_stop.8 \
sg_format.8 sg_get_config.8 sg_get_lba_status.8 sg_ident.8 \
- sg_inq.8 sg_logs.8 sg_luns.8 \
- sg_modes.8 sg_opcodes.8 sg_persist.8 sg_prevent.8 sg_raw.8 \
- sg_rdac.8 sg_readcap.8 sg_read_block_limits.8 sg_read_buffer.8 \
- sg_read_long.8 sg_reassign.8 sg_requests.8 sg_rmsn.8 sg_rtpg.8 \
+ sg_inq.8 sg_logs.8 sg_luns.8 sg_modes.8 sg_opcodes.8 sg_persist.8 \
+ sg_prevent.8 sg_raw.8 sg_rdac.8 sg_readcap.8 \
+ sg_read_block_limits.8 sg_read_buffer.8 sg_read_long.8 \
+ sg_reassign.8 sg_referrals.8 sg_requests.8 sg_rmsn.8 sg_rtpg.8 \
sg_safte.8 sg_sat_identify.8 sg_sat_phy_event.8 \
sg_sat_set_features.8 sg_scan.8 sg_senddiag.8 sg_ses.8 sg_start.8 \
sg_stpg.8 sg_sync.8 sg_turs.8 sg_unmap.8 sg_verify.8 sg_vpd.8 \
@@ -61,10 +61,10 @@ man_MANS = \
sg3_utils.8 \
scsi_readcap.8 scsi_ready.8 scsi_start.8 scsi_stop.8 \
sg_format.8 sg_get_config.8 sg_get_lba_status.8 sg_ident.8 \
- sg_inq.8 sg_logs.8 sg_luns.8 \
- sg_modes.8 sg_opcodes.8 sg_persist.8 sg_prevent.8 sg_raw.8 \
- sg_rdac.8 sg_readcap.8 sg_read_block_limits.8 sg_read_buffer.8 \
- sg_read_long.8 sg_reassign.8 sg_requests.8 sg_rmsn.8 \
+ sg_inq.8 sg_logs.8 sg_luns.8 sg_modes.8 sg_opcodes.8 \
+ sg_persist.8 sg_prevent.8 sg_raw.8 sg_rdac.8 sg_readcap.8 \
+ sg_read_block_limits.8 sg_read_buffer.8 sg_read_long.8 \
+ sg_reassign.8 sg_referrals.8 sg_requests.8 sg_rmsn.8 \
sg_rtpg.8 sg_safte.8 sg_sat_identify.8 sg_sat_phy_event.8 \
sg_sat_set_features.8 sg_scan.8 sg_senddiag.8 sg_ses.8 sg_start.8 \
sg_stpg.8 sg_sync.8 sg_turs.8 sg_unmap.8 sg_verify.8 sg_vpd.8 \
@@ -88,7 +88,7 @@ man_MANS = \
sg_inq.8 sg_logs.8 sg_luns.8 \
sg_modes.8 sg_opcodes.8 sg_persist.8 sg_prevent.8 sg_raw.8 \
sg_rdac.8 sg_readcap.8 sg_read_block_limits.8 sg_read_buffer.8 \
- sg_read_long.8 sg_reassign.8 sg_requests.8 sg_rmsn.8 \
+ sg_read_long.8 sg_reassign.8 sg_referrals.8 sg_requests.8 sg_rmsn.8 \
sg_rtpg.8 sg_safte.8 sg_sat_identify.8 sg_sat_phy_event.8 \
sg_sat_set_features.8 sg_senddiag.8 sg_ses.8 sg_start.8 sg_stpg.8 \
sg_sync.8 sg_turs.8 sg_unmap.8 sg_verify.8 sg_vpd.8 \
@@ -106,7 +106,7 @@ man_MANS = \
sg_inq.8 sg_logs.8 sg_luns.8 \
sg_modes.8 sg_opcodes.8 sg_persist.8 sg_prevent.8 sg_raw.8 \
sg_rdac.8 sg_readcap.8 sg_read_block_limits.8 sg_read_buffer.8 \
- sg_read_long.8 sg_reassign.8 sg_requests.8 sg_rmsn.8 \
+ sg_read_long.8 sg_reassign.8 sg_referrals.8 sg_requests.8 sg_rmsn.8 \
sg_rtpg.8 sg_safte.8 sg_sat_identify.8 sg_sat_phy_event.8 \
sg_sat_set_features.8 sg_senddiag.8 sg_ses.8 sg_start.8 sg_stpg.8 \
sg_sync.8 sg_turs.8 sg_unmap.8 sg_verify.8 sg_vpd.8 \
@@ -124,7 +124,7 @@ man_MANS = \
sg_inq.8 sg_logs.8 sg_luns.8 \
sg_modes.8 sg_opcodes.8 sg_persist.8 sg_prevent.8 sg_raw.8 \
sg_rdac.8 sg_readcap.8 sg_read_block_limits.8 sg_read_buffer.8 \
- sg_read_long.8 sg_reassign.8 sg_requests.8 sg_rmsn.8 \
+ sg_read_long.8 sg_reassign.8 sg_referrals.8 sg_requests.8 sg_rmsn.8 \
sg_rtpg.8 sg_safte.8 sg_sat_identify.8 sg_sat_phy_event.8 \
sg_sat_set_features.8 sg_senddiag.8 sg_ses.8 sg_start.8 sg_stpg.8 \
sg_sync.8 sg_turs.8 sg_unmap.8 sg_verify.8 sg_vpd.8 \
diff --git a/doc/sg_referrals.8 b/doc/sg_referrals.8
new file mode 100644
index 00000000..ea3a80d6
--- /dev/null
+++ b/doc/sg_referrals.8
@@ -0,0 +1,67 @@
+.TH SG_REFERRALS "8" "March 2010" "sg3_utils\-1.29" SG3_UTILS
+.SH NAME
+sg_referrals \- send the SCSI REPORT REFERRALS command
+.SH SYNOPSIS
+.B sg_referrals
+[\fI\-\-help\fR] [\fI\-\-hex\fR] [\fI\-\-lba=LBA\fR] [\fI\-\-maxlen=LEN\fR]
+[\fI\-\-one-segment\fR] [\fI\-\-raw\fR] [\fI\-\-verbose\fR]
+[\fI\-\-version\fR] \fIDEVICE\fR
+.SH DESCRIPTION
+.\" Add any additional description here
+.PP
+Send the SCSI REPORT REFERRALS command to the \fIDEVICE\fR and outputs the
+response. This command was introduced in (draft) SBC\-3 revision 24 and
+devices that support referrals should support this command.
+.PP
+The default action is to decode the response for all user data segment
+referral descriptors. The amount of output can be reduced by the
+\fI\-\-lba\fR and \fI\-\-one-segment\fR options.
+.SH OPTIONS
+Arguments to long options are mandatory for short options as well.
+.TP
+\fB\-h\fR, \fB\-\-help\fR
+output the usage message then exit.
+.TP
+\fB\-H\fR, \fB\-\-hex\fR
+output response to this command in ASCII hex.
+.TP
+\fB\-l\fR, \fB\-\-lba\fR=\fILBA\fR
+where \fILBA\fR is the Logical Block Address (LBA) in the first user
+data segment the \fIDEVICE\fR should report the referrals parameter
+data for.
+.TP
+\fB\-m\fR, \fB\-\-maxlen\fR=\fILEN\fR
+where \fILEN\fR is the (maximum) response length in bytes. It is placed in
+the cdb's "allocation length" field. If not given then 256 is used. 256 is
+enough space for the response header and user data segment descriptors.
+.TP
+\fB\-s\fR, \fB\-\-one-segment\fR
+report the user data segment of the segment spefified by the \fILBA\fR
+parameter only.
+.TP
+\fB\-r\fR, \fB\-\-raw\fR
+output response in binary (to stdout).
+.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.
+.TP
+\fB\-V\fR, \fB\-\-version\fR
+print the version string and then exit.
+.SH NOTES
+For a discussion of referrals see section 4.25 of sbc3r24.pdf
+at http://www.t10.org (or the corresponding section of a later draft).
+.SH EXIT STATUS
+The exit status of sg_referrals is 0 when it is successful. Otherwise
+see the sg3_utils(8) man page.
+.SH AUTHORS
+Written by Douglas Gilbert and Hannes Reinecke.
+.SH "REPORTING BUGS"
+Report bugs to <dgilbert at interlog dot com>.
+.SH COPYRIGHT
+Copyright \(co 2009\-2010 Douglas Gilbert and Hannes Reinecke
+.br
+This software is distributed under a FreeBSD license. There is NO
+warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+.SH "SEE ALSO"
+.B sg_vpd(8)
diff --git a/sg3_utils.spec b/sg3_utils.spec
index b6227433..01b2ee19 100644
--- a/sg3_utils.spec
+++ b/sg3_utils.spec
@@ -79,8 +79,8 @@ fi
%{_libdir}/*.la
%changelog
-* Thu Aug 19 2010 - dgilbert at interlog dot com
-- track t10 changes
+* Mon Sep 13 2010 - dgilbert at interlog dot com
+- add sg_referrals; track t10 changes
* sg3_utils-1.30
* Wed Mar 31 2010 - dgilbert at interlog dot com
diff --git a/src/sg_inq.c b/src/sg_inq.c
index 03270741..c7c95f84 100644
--- a/src/sg_inq.c
+++ b/src/sg_inq.c
@@ -66,7 +66,7 @@
* information [MAINTENANCE IN, service action = 0xc]; see sg_opcodes.
*/
-static char * version_str = "0.91 20100819"; /* SPC-4 rev 26 */
+static char * version_str = "0.92 20100913"; /* SPC-4 rev 26 */
#define VPD_SUPPORTED_VPDS 0x0
@@ -83,6 +83,7 @@ static char * version_str = "0.91 20100819"; /* SPC-4 rev 26 */
#define VPD_PROTO_PORT 0x91
#define VPD_BLOCK_LIMITS 0xb0
#define VPD_BLOCK_DEV_CHARS 0xb1
+#define VPD_MAN_ASS_SN 0xb1
#define VPD_THIN_PROVISIONING 0xb2
#define VPD_REFERRALS 0xb3
#define VPD_UPR_EMC 0xc0
@@ -1465,6 +1466,8 @@ decode_b0_vpd(unsigned char * buff, int len, int do_hex, int pdt)
}
}
+/* VPD_BLOCK_DEV_CHARS sbc */
+/* VPD_MAN_ASS_SN ssc */
static void
decode_b1_vpd(unsigned char * buff, int len, int do_hex, int pdt)
{
@@ -1502,6 +1505,7 @@ decode_b1_vpd(unsigned char * buff, int len, int do_hex, int pdt)
}
}
+/* VPD_REFERRALS sbc */
static void
decode_b3_vpd(unsigned char * buff, int len, int do_hex, int pdt)
{
@@ -1514,8 +1518,7 @@ decode_b3_vpd(unsigned char * buff, int len, int do_hex, int pdt)
switch (pdt) {
case PDT_DISK: case PDT_WO: case PDT_OPTICAL:
if (len < 0xc0) {
- fprintf(stderr, "Block device characteristics VPD page length "
- "too short=%d\n", len);
+ fprintf(stderr, "Referrals VPD page length too short=%d\n", len);
return;
}
s = (buff[8] << 24) | (buff[9] << 16) | (buff[10] << 8) | buff[11];
@@ -2372,7 +2375,7 @@ decode_vpd(int sg_fd, const struct opts_t * optsp)
decode_power_condition(rsp_buff, len, optsp->do_hex);
}
break;
- case 0xb0: /* could be BLOCK LIMITS but need to know pdt to find out */
+ case 0xb0: /* VPD pages in B0h to BFh range depend on pdt */
res = sg_ll_inquiry(sg_fd, 0, 1, 0xb0, rsp_buff,
DEF_ALLOC_LEN, 1, optsp->do_verbose);
if (0 == res) {
@@ -2416,7 +2419,7 @@ decode_vpd(int sg_fd, const struct opts_t * optsp)
} else if (! optsp->do_raw)
printf("VPD INQUIRY: page=0xb0\n");
break;
- case 0xb1: /* could be BLOCK DEVICE CHARACTERISTICS but need pdt */
+ case 0xb1: /* VPD pages in B0h to BFh range depend on pdt */
res = sg_ll_inquiry(sg_fd, 0, 1, 0xb1, rsp_buff,
DEF_ALLOC_LEN, 1, optsp->do_verbose);
if (0 == res) {
@@ -2465,7 +2468,10 @@ decode_vpd(int sg_fd, const struct opts_t * optsp)
} else if (! optsp->do_raw)
printf("VPD INQUIRY: page=0xb1\n");
break;
- case 0xb3: /* could be REFERRALS but need pdt */
+ case 0xb2: /* VPD pages in B0h to BFh range depend on pdt */
+ printf(" Only hex output supported. sg_vpd decodes the B2h page.\n");
+ return process_vpd(sg_fd, optsp);
+ case 0xb3: /* VPD pages in B0h to BFh range depend on pdt */
res = sg_ll_inquiry(sg_fd, 0, 1, 0xb3, rsp_buff,
DEF_ALLOC_LEN, 1, optsp->do_verbose);
if (0 == res) {
diff --git a/src/sg_referrals.c b/src/sg_referrals.c
index 11d701cf..248faa96 100644
--- a/src/sg_referrals.c
+++ b/src/sg_referrals.c
@@ -29,17 +29,53 @@
* SCSI device.
*/
-static char * version_str = "1.01 20100806"; /* sbc3r24 */
+static char * version_str = "1.03 20100812"; /* sbc3r24 */
#define MAX_REFER_BUFF_LEN (1024 * 1024)
-#define DEF_REFER_BUFF_LEN 24
+#define DEF_REFER_BUFF_LEN 256
+
+#define TPGS_STATE_OPTIMIZED 0x0
+#define TPGS_STATE_NONOPTIMIZED 0x1
+#define TPGS_STATE_STANDBY 0x2
+#define TPGS_STATE_UNAVAILABLE 0x3
+#define TPGS_STATE_LB_DEPENDENT 0x4
+#define TPGS_STATE_OFFLINE 0xe /* SPC-4 rev 9 */
+#define TPGS_STATE_TRANSITIONING 0xf
static unsigned char referralBuff[DEF_REFER_BUFF_LEN];
static unsigned char * referralBuffp = referralBuff;
+static const char *decode_tpgs_state(const int st)
+{
+ switch (st) {
+ case TPGS_STATE_OPTIMIZED:
+ return "active/optimized";
+ break;
+ case TPGS_STATE_NONOPTIMIZED:
+ return "active/non optimized";
+ break;
+ case TPGS_STATE_STANDBY:
+ return "standby";
+ break;
+ case TPGS_STATE_UNAVAILABLE:
+ return "unavailable";
+ break;
+ case TPGS_STATE_LB_DEPENDENT:
+ return "logical block dependent";
+ break;
+ case TPGS_STATE_OFFLINE:
+ return "offline";
+ break;
+ case TPGS_STATE_TRANSITIONING:
+ return "transitioning between states";
+ break;
+ default:
+ return "unknown";
+ break;
+ }
+}
static struct option long_options[] = {
- {"brief", no_argument, 0, 'b'},
{"help", no_argument, 0, 'h'},
{"hex", no_argument, 0, 'H'},
{"lba", required_argument, 0, 'l'},
@@ -55,15 +91,11 @@ static void
usage()
{
fprintf(stderr, "Usage: "
- "sg_referrals [--brief] [--help] [--hex] [--lba=LBA]\n"
- " [--maxlen=LEN] [--raw] [--verbose] "
+ "sg_referrals [--help] [--hex] [--lba=LBA] [--maxlen=LEN]\n"
+ " [--one-segment] [--raw] [--verbose] "
"[--version]\n"
- " DEVICE\n"
+ " DEVICE\n"
" where:\n"
- " --brief|-b a descriptor per line: "
- "<lba_hex blocks_hex p_status>\n"
- " use twice ('-bb') for given LBA "
- "provisioning status\n"
" --help|-h print out usage message\n"
" --hex|-H output in hexadecimal\n"
" --lba=LBA|-l LBA starting LBA (logical block address) "
@@ -73,7 +105,7 @@ usage()
" (def: 0 -> %d bytes)\n",
DEF_REFER_BUFF_LEN );
fprintf(stderr,
- " --one-segment|-s return information about the specified\n"
+ " --one-segment|-s return information about the specified\n"
" segment only\n"
" --raw|-r output in binary\n"
" --verbose|-v increase verbosity\n"
@@ -96,7 +128,7 @@ dStrRaw(const char* str, int len)
* -1 for error.
*/
static int
-decode_referral_desc(const unsigned char * ucp)
+decode_referral_desc(const unsigned char * ucp, int bytes)
{
int j, n;
uint64_t first, last;
@@ -104,6 +136,9 @@ decode_referral_desc(const unsigned char * ucp)
if (NULL == ucp)
return -1;
+ if (bytes < 20)
+ return -1;
+
first = ((uint64_t)ucp[4] << 56) | ((uint64_t)ucp[5] << 48) |
((uint64_t)ucp[6] << 40) | ((uint64_t)ucp[7] << 32) |
((uint64_t)ucp[8] << 24) | ((uint64_t)ucp[9] << 16) |
@@ -115,14 +150,17 @@ decode_referral_desc(const unsigned char * ucp)
printf(" target port descriptors: %d\n", ucp[3]);
printf(" user data segment: first lba %" PRIu64 ", last lba %"
- PRIu64 "\n", first, last);
-
+ PRIu64 "\n", first, last);
n = 20;
+ bytes -= n;
for (j = 0; j < ucp[3]; j++) {
+ if (bytes < 4)
+ return -1;
printf(" target port descriptor %d:\n", j);
- printf(" port group %d state %x\n",
- (ucp[n+2] << 8) | (ucp[n+3]), ucp[n] & 0xf);
+ printf(" port group %x state (%s)\n",
+ (ucp[n+2] << 8) | (ucp[n+3]), decode_tpgs_state(ucp[n] & 0xf));
n += 4;
+ bytes -= 4;
}
return n;
}
@@ -132,7 +170,6 @@ int
main(int argc, char * argv[])
{
int sg_fd, k, res, c, rlen;
- int do_brief = 0;
int do_hex = 0;
int do_one_segment = 0;
int64_t ll;
@@ -140,6 +177,7 @@ main(int argc, char * argv[])
int maxlen = DEF_REFER_BUFF_LEN;
int do_raw = 0;
int verbose = 0;
+ int desc = 0;
const char * device_name = NULL;
const unsigned char * ucp;
int ret = 0;
@@ -147,15 +185,12 @@ main(int argc, char * argv[])
while (1) {
int option_index = 0;
- c = getopt_long(argc, argv, "bhHl:m:rvV", long_options,
+ c = getopt_long(argc, argv, "hHl:m:rsvV", long_options,
&option_index);
if (c == -1)
break;
switch (c) {
- case 'b':
- ++do_brief;
- break;
case 'h':
case '?':
usage();
@@ -179,7 +214,7 @@ main(int argc, char * argv[])
return SG_LIB_SYNTAX_ERROR;
}
break;
- case 'o':
+ case 's':
++do_one_segment;
break;
case 'r':
@@ -212,7 +247,7 @@ main(int argc, char * argv[])
}
if (NULL == device_name) {
- fprintf(stderr, "missing device name!\n");
+ fprintf(stderr, "No DEVICE argument given\n");
usage();
return SG_LIB_SYNTAX_ERROR;
}
@@ -244,8 +279,15 @@ main(int argc, char * argv[])
ret = res;
if (0 == res) {
if (maxlen >= 4)
+ /*
+ * This is strictly speaking incorrect. However, the
+ * spec reserved bytes 0 and 1, so some implementations
+ * might want to use them to increase the number of
+ * possible user segments.
+ * And maybe someone takes a pity and updates the spec ...
+ */
rlen = (referralBuffp[0] << 24) + (referralBuffp[1] << 16) +
- (referralBuffp[2] << 8) + referralBuffp[3] + 8;
+ (referralBuffp[2] << 8) + referralBuffp[3] + 4;
else
rlen = maxlen;
k = (rlen > maxlen) ? maxlen : rlen;
@@ -275,13 +317,16 @@ main(int argc, char * argv[])
ucp = referralBuffp + 4;
k = 0;
printf("Report referrals:\n");
- while (k < rlen) {
- printf(" descriptor %d:\n", k + 1);
- res = decode_referral_desc(ucp + k);
- if (res < 0)
- fprintf(stderr, "descriptor %d: bad LBA status descriptor "
- "returned %d\n", k + 1, res);
+ while (k < rlen - 4) {
+ printf(" descriptor %d:\n", desc);
+ res = decode_referral_desc(ucp + k, rlen - 4 - k);
+ if (res < 0) {
+ fprintf(stderr, "bad user data segment referral descriptor\n");
+ k = rlen - 4;
+ break;
+ }
k += res;
+ desc++;
}
} else if (SG_LIB_CAT_INVALID_OP == res)
fprintf(stderr, "Report Referrals command not supported\n");
diff --git a/src/sg_vpd.c b/src/sg_vpd.c
index e73cf5eb..63a56ee1 100644
--- a/src/sg_vpd.c
+++ b/src/sg_vpd.c
@@ -30,7 +30,7 @@
*/
-static char * version_str = "0.43 20100819"; /* spc4r26 + sbc3r24 */
+static char * version_str = "0.44 20100913"; /* spc4r26 + sbc3r24 */
extern void svpd_enumerate_vendor(void);
extern int svpd_decode_vendor(int sg_fd, int num_vpd, int subvalue,
@@ -1522,6 +1522,8 @@ decode_tapealert_supported_vpd(unsigned char * b, int len)
return 0;
}
+/* VPD_THIN_PROVISIONING sbc */
+/* VPD_TA_SUPPORTED ssc */
static void
decode_b2_vpd(unsigned char * buff, int len, int do_hex, int pdt)
{
@@ -1543,6 +1545,8 @@ decode_b2_vpd(unsigned char * buff, int len, int do_hex, int pdt)
}
}
+/* VPD_REFERRALS sbc */
+/* VPD_AUTOMATION_DEV_SN ssc */
static void
decode_b3_vpd(unsigned char * b, int len, int do_hex, int pdt)
{