aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDouglas Gilbert <dgilbert@interlog.com>2014-06-06 16:55:26 +0000
committerDouglas Gilbert <dgilbert@interlog.com>2014-06-06 16:55:26 +0000
commit737cdcd23f0a13963f97840cd0acd4672e9eb3ee (patch)
tree17269cb10efa49d496744420fcb9be019220f0ad
parent240dd15692debe127e57ff0fb4bc320f70614d5f (diff)
downloadsg3_utils-737cdcd23f0a13963f97840cd0acd4672e9eb3ee.tar.gz
sg_luns: add decoding for conglomerate LUNS; change struct sg_simple_inquiry_resp::rmb to byte_1
git-svn-id: https://svn.bingwo.ca/repos/sg3_utils/trunk@586 6180dd3e-e324-4e3e-922d-17de1ae2f315
-rw-r--r--ChangeLog8
-rw-r--r--doc/Makefile.am2
-rw-r--r--doc/Makefile.in10
-rw-r--r--doc/sg_luns.812
-rw-r--r--doc/sg_rep_zones.82
-rw-r--r--doc/sg_reset_wp.82
-rw-r--r--include/sg_cmds_basic.h2
-rw-r--r--lib/sg_cmds_basic.c4
-rw-r--r--lib/sg_pt_common.c2
-rw-r--r--lib/sg_pt_linux.c33
-rw-r--r--src/sg_luns.c192
-rw-r--r--src/sg_rep_zones.c9
-rw-r--r--src/sg_reset_wp.c9
13 files changed, 190 insertions, 97 deletions
diff --git a/ChangeLog b/ChangeLog
index 12253d6c..13b8cf72 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.39 [20140603] [svn: r585]
+Changelog for sg3_utils-1.39 [20140606] [svn: r586]
- sg_rep_zones: new utility for ZBC REPORT ZONES
- sg_reset_wp: new utility, ZBC RESET WRITE POINTER
- sg_ses: add --eiioe=auto|force option
@@ -22,6 +22,8 @@ Changelog for sg3_utils-1.39 [20140603] [svn: r585]
- suppress dev-id VPD messages so they only appear
when --verbose is given
- add new SCSI_IDENT_*_ATA pair to --export output
+ - sg_luns: add decoding for conglomerate LUNS
+ - add --lu_cong option for test mode
- sg_vpd: add --vendor=VP option, re-order vendor
specific pages, split lto into lto5 and lto6
- add Supported block lengths and protection types
@@ -38,9 +40,11 @@ Changelog for sg3_utils-1.39 [20140603] [svn: r585]
- add 'sense' categories for reservation conflict,
data protect and protection information violations
- add sg_get_category_sense_str() to API
+ - change struct sg_simple_inquiry_resp::rmb to byte_1
- add initial zbc service actions
- dStrHex(Err): fix output truncation error
- - linux, sg: support SCSI_PT_FLAGS_QUEUE_AT_TAIL
+ - linux, sg: support SCSI_PT_FLAGS_QUEUE_AT_TAIL and
+ SCSI_PT_FLAGS_QUEUE_AT_HEAD (block layer queueing)
- sg_lib_data: sync asc/ascq codes with T10 20140516
- sync operation code with T10 20140515
- add id string for SPC-5
diff --git a/doc/Makefile.am b/doc/Makefile.am
index bb26c739..f9ea1479 100644
--- a/doc/Makefile.am
+++ b/doc/Makefile.am
@@ -19,7 +19,7 @@ man_MANS = \
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_rep_zones.8 sg_requests.8 sg_reset.8 sg_reset_wp.8 sg_rmsn.8 \
- sg_rtpg.8 sg_safte.8 sg_sanitize.8 sg_sat_identify.8
+ sg_rtpg.8 sg_safte.8 sg_sanitize.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 \
diff --git a/doc/Makefile.in b/doc/Makefile.in
index 05e29dc5..f05bd28d 100644
--- a/doc/Makefile.in
+++ b/doc/Makefile.in
@@ -290,7 +290,11 @@ top_srcdir = @top_srcdir@
@OS_LINUX_TRUE@ sg_rbuf.8 sg_rdac.8 sg_read.8 sg_readcap.8 sg_read_block_limits.8 \
@OS_LINUX_TRUE@ sg_read_buffer.8 sg_read_long.8 sg_reassign.8 sg_referrals.8 \
@OS_LINUX_TRUE@ sg_rep_zones.8 sg_requests.8 sg_reset.8 sg_reset_wp.8 sg_rmsn.8 \
-@OS_LINUX_TRUE@ sg_rtpg.8 sg_safte.8 sg_sanitize.8 sg_sat_identify.8
+@OS_LINUX_TRUE@ sg_rtpg.8 sg_safte.8 sg_sanitize.8 sg_sat_identify.8 \
+@OS_LINUX_TRUE@ sg_sat_phy_event.8 sg_sat_set_features.8 sg_scan.8 sg_senddiag.8 \
+@OS_LINUX_TRUE@ sg_ses.8 sg_start.8 sg_stpg.8 sg_sync.8 sg_test_rwbuf.8 sg_turs.8 \
+@OS_LINUX_TRUE@ sg_unmap.8 sg_verify.8 sg_vpd.8 sg_write_buffer.8 sg_write_long.8 \
+@OS_LINUX_TRUE@ sg_write_same.8 sg_wr_mode.8 sg_xcopy.8
@OS_OSF_TRUE@man_MANS = \
@OS_OSF_TRUE@ sg3_utils.8 sg_decode_sense.8 \
@@ -596,10 +600,6 @@ uninstall-man: uninstall-man8
mostlyclean-libtool pdf pdf-am ps ps-am tags-am uninstall \
uninstall-am uninstall-man uninstall-man8
-@OS_LINUX_TRUE@ sg_sat_phy_event.8 sg_sat_set_features.8 sg_scan.8 sg_senddiag.8 \
-@OS_LINUX_TRUE@ sg_ses.8 sg_start.8 sg_stpg.8 sg_sync.8 sg_test_rwbuf.8 sg_turs.8 \
-@OS_LINUX_TRUE@ sg_unmap.8 sg_verify.8 sg_vpd.8 sg_write_buffer.8 sg_write_long.8 \
-@OS_LINUX_TRUE@ sg_write_same.8 sg_wr_mode.8 sg_xcopy.8
@OS_LINUX_TRUE@distclean-local:
@OS_LINUX_TRUE@ rm -f sg_scan.8
diff --git a/doc/sg_luns.8 b/doc/sg_luns.8
index 45f0befe..0ab74642 100644
--- a/doc/sg_luns.8
+++ b/doc/sg_luns.8
@@ -1,11 +1,12 @@
-.TH SG_LUNS "8" "May" "sg3_utils\-1.39" SG3_UTILS
+.TH SG_LUNS "8" "June" "sg3_utils\-1.39" SG3_UTILS
.SH NAME
sg_luns \- send SCSI REPORT LUNS command or decode given LUN
.SH SYNOPSIS
.B sg_luns
[\fI\-\-decode\fR] [\fI\-\-help\fR] [\fI\-\-hex\fR] [\fI\-\-linux\fR]
-[\fI\-\-maxlen=LEN\fR] [\fI\-\-quiet\fR] [\fI\-\-raw\fR] [\fI\-\-readonly\fR]
-[\fI\-\-select=SR\fR] [\fI\-\-verbose\fR] [\fI\-\-version\fR] \fIDEVICE\fR
+[\fI\-\-lu_cong\fR] [\fI\-\-maxlen=LEN\fR] [\fI\-\-quiet\fR] [\fI\-\-raw\fR]
+[\fI\-\-readonly\fR] [\fI\-\-select=SR\fR] [\fI\-\-verbose\fR]
+[\fI\-\-version\fR] \fIDEVICE\fR
.PP
.B sg_luns
\fI\-\-test=ALUN\fR [\fI\-\-hex\fR] [\fI\-\-verbose\fR]
@@ -52,6 +53,11 @@ to the right, in square brackets, is the Linux LUN integer in decimal.
If the \fI\-\-hex\fR option is given twice (e.g. \-HH) as well then the
Linux LUN integer is output in hexadecimal.
.TP
+\fB\-L\fR, \fB\-\-lu_cong\fR
+[test mode] decode \fIALUN\fR as if the LU_CONG bit is set in its
+corresponding standard INQUIRY response. In other words treat \fIALUN\fR
+as if it is a conglomerate LUN.
+.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 (or \fILEN\fR is zero)
diff --git a/doc/sg_rep_zones.8 b/doc/sg_rep_zones.8
index fe111606..6adce7b5 100644
--- a/doc/sg_rep_zones.8
+++ b/doc/sg_rep_zones.8
@@ -1,4 +1,4 @@
-.TH SG_REP_ZONES "8" "May 2014" "sg3_utils\-1.39" SG3_UTILS
+.TH SG_REP_ZONES "8" "June 2014" "sg3_utils\-1.39" SG3_UTILS
.SH NAME
sg_rep_zones \- send SCSI REPORT ZONES command
.SH SYNOPSIS
diff --git a/doc/sg_reset_wp.8 b/doc/sg_reset_wp.8
index 782c97a1..ef20be67 100644
--- a/doc/sg_reset_wp.8
+++ b/doc/sg_reset_wp.8
@@ -1,4 +1,4 @@
-.TH SG_RESET_WP "8" "May 2014" "sg3_utils\-1.39" SG3_UTILS
+.TH SG_RESET_WP "8" "June 2014" "sg3_utils\-1.39" SG3_UTILS
.SH NAME
sg_reset_wp \- send SCSI RESET WRITE POINTER command
.SH SYNOPSIS
diff --git a/include/sg_cmds_basic.h b/include/sg_cmds_basic.h
index 2ce05d65..ada13c93 100644
--- a/include/sg_cmds_basic.h
+++ b/include/sg_cmds_basic.h
@@ -168,7 +168,7 @@ int sg_ll_test_unit_ready_progress(int sg_fd, int pack_id, int * progress,
struct sg_simple_inquiry_resp {
unsigned char peripheral_qualifier;
unsigned char peripheral_type;
- unsigned char rmb;
+ unsigned char byte_1; /* was rmb only prior to version 1.39 */
unsigned char version; /* as per recent drafts: whole of byte 2 */
unsigned char byte_3;
unsigned char byte_5;
diff --git a/lib/sg_cmds_basic.c b/lib/sg_cmds_basic.c
index 43c127c7..46e567be 100644
--- a/lib/sg_cmds_basic.c
+++ b/lib/sg_cmds_basic.c
@@ -27,7 +27,7 @@
#endif
-static const char * version_str = "1.67 20140514";
+static const char * version_str = "1.68 20140604";
#define SENSE_BUFF_LEN 64 /* Arbitrary, could be larger */
@@ -361,7 +361,7 @@ sg_simple_inquiry(int sg_fd, struct sg_simple_inquiry_resp * inq_data,
if (0 == ret) {
inq_data->peripheral_qualifier = (inq_resp[0] >> 5) & 0x7;
inq_data->peripheral_type = inq_resp[0] & 0x1f;
- inq_data->rmb = (inq_resp[1] & 0x80) ? 1 : 0;
+ inq_data->byte_1 = inq_resp[1];
inq_data->version = inq_resp[2];
inq_data->byte_3 = inq_resp[3];
inq_data->byte_5 = inq_resp[5];
diff --git a/lib/sg_pt_common.c b/lib/sg_pt_common.c
index cc84cc21..357816a4 100644
--- a/lib/sg_pt_common.c
+++ b/lib/sg_pt_common.c
@@ -14,7 +14,7 @@
#endif
-static const char * scsi_pt_version_str = "2.11 20140603";
+static const char * scsi_pt_version_str = "2.12 20140606";
const char *
scsi_pt_version()
diff --git a/lib/sg_pt_linux.c b/lib/sg_pt_linux.c
index 18c318c4..ea16fd27 100644
--- a/lib/sg_pt_linux.c
+++ b/lib/sg_pt_linux.c
@@ -5,7 +5,7 @@
* license that can be found in the BSD_LICENSE file.
*/
-/* sg_pt_linux version 1.21 20140603 */
+/* sg_pt_linux version 1.22 20140606 */
#include <stdio.h>
@@ -278,6 +278,9 @@ set_scsi_pt_task_attr(struct sg_pt_base * vp, int attribute, int priority)
#ifndef SG_FLAG_Q_AT_TAIL
#define SG_FLAG_Q_AT_TAIL 0x10
#endif
+#ifndef SG_FLAG_Q_AT_HEAD
+#define SG_FLAG_Q_AT_HEAD 0x20
+#endif
void
set_scsi_pt_flags(struct sg_pt_base * vp, int flags)
@@ -286,10 +289,13 @@ set_scsi_pt_flags(struct sg_pt_base * vp, int flags)
/* default action of sg driver [sg v3 interface] is QUEUE_AT_HEAD */
/* default action of block layer SG_IO ioctl is QUEUE_AT_TAIL */
- if (SCSI_PT_FLAGS_QUEUE_AT_TAIL & flags)
- ptp->io_hdr.flags |= SG_FLAG_Q_AT_TAIL;
- if (SCSI_PT_FLAGS_QUEUE_AT_HEAD & flags)
+ if (SCSI_PT_FLAGS_QUEUE_AT_HEAD & flags) { /* favour AT_HEAD */
+ ptp->io_hdr.flags |= SG_FLAG_Q_AT_HEAD;
ptp->io_hdr.flags &= ~SG_FLAG_Q_AT_TAIL;
+ } else if (SCSI_PT_FLAGS_QUEUE_AT_TAIL & flags) {
+ ptp->io_hdr.flags |= SG_FLAG_Q_AT_TAIL;
+ ptp->io_hdr.flags &= ~SG_FLAG_Q_AT_HEAD;
+ }
}
/* Executes SCSI command (or at least forwards it to lower layers).
@@ -747,11 +753,17 @@ set_scsi_pt_task_attr(struct sg_pt_base * vp, int attribute, int priority)
#ifndef BSG_FLAG_Q_AT_TAIL
#define BSG_FLAG_Q_AT_TAIL 0x10
#endif
+#ifndef BSG_FLAG_Q_AT_HEAD
+#define BSG_FLAG_Q_AT_HEAD 0x20
+#endif
/* Need this later if translated to v3 interface */
#ifndef SG_FLAG_Q_AT_TAIL
#define SG_FLAG_Q_AT_TAIL 0x10
#endif
+#ifndef SG_FLAG_Q_AT_HEAD
+#define SG_FLAG_Q_AT_HEAD 0x20
+#endif
void
set_scsi_pt_flags(struct sg_pt_base * vp, int flags)
@@ -760,10 +772,13 @@ set_scsi_pt_flags(struct sg_pt_base * vp, int flags)
/* default action of bsg driver (sg v4) is QUEUE_AT_HEAD */
/* default action of block layer SG_IO ioctl is QUEUE_AT_TAIL */
- if (SCSI_PT_FLAGS_QUEUE_AT_TAIL & flags)
- ptp->io_hdr.flags |= BSG_FLAG_Q_AT_TAIL;
- if (SCSI_PT_FLAGS_QUEUE_AT_HEAD & flags)
+ if (SCSI_PT_FLAGS_QUEUE_AT_HEAD & flags) { /* favour AT_HEAD */
+ ptp->io_hdr.flags |= BSG_FLAG_Q_AT_HEAD;
ptp->io_hdr.flags &= ~BSG_FLAG_Q_AT_TAIL;
+ } else if (SCSI_PT_FLAGS_QUEUE_AT_TAIL & flags) {
+ ptp->io_hdr.flags |= BSG_FLAG_Q_AT_TAIL;
+ ptp->io_hdr.flags &= ~BSG_FLAG_Q_AT_HEAD;
+ }
}
/* N.B. Returns din_resid and ignores dout_resid */
@@ -930,7 +945,9 @@ do_scsi_pt_v3(struct sg_pt_linux_scsi * ptp, int fd, int time_secs,
v3_hdr.mx_sb_len = (unsigned char)ptp->io_hdr.max_response_len;
}
v3_hdr.pack_id = (int)ptp->io_hdr.spare_in;
- if (BSG_FLAG_Q_AT_TAIL & ptp->io_hdr.flags)
+ if (BSG_FLAG_Q_AT_HEAD & ptp->io_hdr.flags)
+ v3_hdr.flags |= SG_FLAG_Q_AT_HEAD; /* favour AT_HEAD */
+ else if (BSG_FLAG_Q_AT_TAIL & ptp->io_hdr.flags)
v3_hdr.flags |= SG_FLAG_Q_AT_TAIL;
if (NULL == v3_hdr.cmdp) {
diff --git a/src/sg_luns.c b/src/sg_luns.c
index e5097625..9e5c1c0d 100644
--- a/src/sg_luns.c
+++ b/src/sg_luns.c
@@ -9,6 +9,7 @@
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
+#include <stdarg.h>
#include <string.h>
#include <ctype.h>
#include <getopt.h>
@@ -28,13 +29,12 @@
* and decodes the response.
*/
-static const char * version_str = "1.25 20140514";
+static const char * version_str = "1.26 20140606";
#define MAX_RLUNS_BUFF_LEN (1024 * 1024)
#define DEF_RLUNS_BUFF_LEN (1024 * 8)
-
static struct option long_options[] = {
{"decode", no_argument, 0, 'd'},
{"help", no_argument, 0, 'h'},
@@ -42,6 +42,7 @@ static struct option long_options[] = {
#ifdef SG_LIB_LINUX
{"linux", no_argument, 0, 'l'},
#endif
+ {"lu_cong", no_argument, 0, 'L'},
{"maxlen", required_argument, 0, 'm'},
{"quiet", no_argument, 0, 'q'},
{"raw", no_argument, 0, 'r'},
@@ -53,27 +54,46 @@ static struct option long_options[] = {
{0, 0, 0, 0},
};
+
+#ifdef __GNUC__
+static int pr2serr(const char * fmt, ...)
+ __attribute__ ((format (printf, 1, 2)));
+#else
+static int pr2serr(const char * fmt, ...);
+#endif
+
+static int
+pr2serr(const char * fmt, ...)
+{
+ va_list args;
+ int n;
+
+ va_start(args, fmt);
+ n = vfprintf(stderr, fmt, args);
+ va_end(args);
+ return n;
+}
+
static void
usage()
{
#ifdef SG_LIB_LINUX
- fprintf(stderr, "Usage: "
+ pr2serr("Usage: "
"sg_luns [--decode] [--help] [--hex] [--linux] "
"[--maxlen=LEN]\n"
" [--quiet] [--raw] [--readonly] "
"[--select=SR]\n"
" [--verbose] [--version] DEVICE\n");
#else
- fprintf(stderr, "Usage: "
+ pr2serr("Usage: "
"sg_luns [--decode] [--help] [--hex] [--maxlen=LEN] "
"[--quiet]\n"
" [--raw] [--readonly] [--select=SR] "
"[--verbose]\n"
" [--version] DEVICE\n");
#endif
- fprintf(stderr,
- " or\n"
- " sg_luns --test=ALUN [--hex] [--verbose]\n"
+ pr2serr(" or\n"
+ " sg_luns --test=ALUN [--hex] [--lu_cong] [--verbose]\n"
" where:\n"
" --decode|-d decode all luns into component parts\n"
" --help|-h print out usage message\n"
@@ -81,11 +101,10 @@ usage()
"twice\n"
" shows decoded values in hex\n");
#ifdef SG_LIB_LINUX
- fprintf(stderr,
- " --linux|-l show Linux integer lun after T10 "
+ pr2serr(" --linux|-l show Linux integer lun after T10 "
"representation\n");
#endif
- fprintf(stderr,
+ pr2serr(" --lu_cong decode ALUN as if LU_CONG is set\n"
" --maxlen=LEN|-m LEN max response length (allocation "
"length in cdb)\n"
" (def: 0 -> %d bytes)\n"
@@ -113,11 +132,11 @@ usage()
* defines its own "bridge addressing method" in place of the SAM-3
* "logical addressing method". */
static void
-decode_lun(const char * leadin, const unsigned char * lunp, int do_hex,
- int verbose)
+decode_lun(const char * leadin, const unsigned char * lunp, int lu_cong,
+ int do_hex, int verbose)
{
int k, j, x, a_method, bus_id, target, lun, len_fld, e_a_method;
- int next_level;
+ int next_level, lu_cong_admin;
unsigned char not_spec[8] = {0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff};
char l_leadin[128];
@@ -128,39 +147,71 @@ decode_lun(const char * leadin, const unsigned char * lunp, int do_hex,
printf("%sLogical unit not specified\n", leadin);
return;
}
+ lu_cong_admin = lu_cong;
memset(l_leadin, 0, sizeof(l_leadin));
for (k = 0; k < 4; ++k, lunp += 2) {
next_level = 0;
strncpy(l_leadin, leadin, sizeof(l_leadin) - 3);
if (k > 0) {
- printf("%s>>%s level addressing:\n", l_leadin,
- ((1 == k) ? "Second" : ((2 == k) ? "Third" : "Fourth")));
+ if (lu_cong) {
+ lu_cong_admin = 0;
+ if ((0 == lunp[0]) && (0 == lunp[1])) {
+ printf("%s>>>> Administrative LU\n", l_leadin);
+ if (do_hex || verbose)
+ printf(" since Subsidiary element is "
+ "0x0000\n");
+ break;
+ } else
+ printf("%s>>Subsidiary element:\n", l_leadin);
+ } else
+ printf("%s>>%s level addressing:\n", l_leadin, ((1 == k) ?
+ "Second" : ((2 == k) ? "Third" : "Fourth")));
+ strcat(l_leadin, " ");
+ } else if (lu_cong) {
+ printf("%s>>Administrative element:\n", l_leadin);
strcat(l_leadin, " ");
}
a_method = (lunp[0] >> 6) & 0x3;
switch (a_method) {
case 0: /* peripheral device addressing method */
- bus_id = lunp[0] & 0x3f;
- snprintf(b, sizeof(b), "%sPeripheral device addressing: ",
- l_leadin);
- if ((0 == bus_id) && (0 == verbose)) {
+ if (lu_cong) {
+ snprintf(b, sizeof(b), "%sSimple lu addressing: ",
+ l_leadin);
+ x = ((lunp[0] & 0x3f) << 8) + lunp[1];
if (do_hex)
- printf("%slun=0x%02x\n", b, lunp[1]);
+ printf("%s0x%04x\n", b, x);
else
- printf("%slun=%d\n", b, lunp[1]);
+ printf("%s%d\n", b, x);
+ if (lu_cong_admin)
+ next_level = 1;
} else {
- if (do_hex)
- printf("%sbus_id=0x%02x, %s=0x%02x\n", b, bus_id,
- (bus_id ? "target" : "lun"), lunp[1]);
- else
- printf("%sbus_id=%d, %s=%d\n", b, bus_id,
- (bus_id ? "target" : "lun"), lunp[1]);
+ bus_id = lunp[0] & 0x3f;
+ snprintf(b, sizeof(b), "%sPeripheral device addressing: ",
+ l_leadin);
+ if ((0 == bus_id) && (0 == verbose)) {
+ if (do_hex)
+ printf("%slun=0x%02x\n", b, lunp[1]);
+ else
+ printf("%slun=%d\n", b, lunp[1]);
+ } else {
+ if (do_hex)
+ printf("%sbus_id=0x%02x, %s=0x%02x\n", b, bus_id,
+ (bus_id ? "target" : "lun"), lunp[1]);
+ else
+ printf("%sbus_id=%d, %s=%d\n", b, bus_id,
+ (bus_id ? "target" : "lun"), lunp[1]);
+ }
+ if (bus_id)
+ next_level = 1;
}
- if (bus_id)
- next_level = 1;
break;
case 1: /* flat space addressing method */
lun = ((lunp[0] & 0x3f) << 8) + lunp[1];
+ if (lu_cong) {
+ printf("%sSince LU_CONG=1, unexpected Flat space "
+ "addressing: lun=0x%04x\n", l_leadin, lun);
+ break;
+ }
if (do_hex)
printf("%sFlat space addressing: lun=0x%04x\n", l_leadin,
lun);
@@ -171,6 +222,12 @@ decode_lun(const char * leadin, const unsigned char * lunp, int do_hex,
target = (lunp[0] & 0x3f);
bus_id = (lunp[1] >> 5) & 0x7;
lun = lunp[1] & 0x1f;
+ if (lu_cong) {
+ printf("%sSince LU_CONG=1, unexpected lu addressing: "
+ "bus_id=0x%x, target=0x%02x, lun=0x%02x\n", l_leadin,
+ bus_id, target, lun);
+ break;
+ }
if (do_hex)
printf("%sLogical unit addressing: bus_id=0x%x, "
"target=0x%02x, lun=0x%02x\n", l_leadin, bus_id,
@@ -222,9 +279,9 @@ decode_lun(const char * leadin, const unsigned char * lunp, int do_hex,
}
if (do_hex)
printf("%sLong extended flat space addressing: "
- "lun=010x%" PRIx64 "\n", l_leadin, ull);
+ "lun=0x%010" PRIx64 "\n", l_leadin, ull);
else
- printf("%sLong extended flat space addressing: "
+ printf("%sLong extended flat space addressing: "
"lun=%" PRIu64 "\n", l_leadin, ull);
} else if ((3 == len_fld) && (0xf == e_a_method))
printf("%sLogical unit _not_ specified addressing\n",
@@ -341,6 +398,8 @@ main(int argc, char * argv[])
#ifdef SG_LIB_LINUX
int do_linux = 0;
#endif
+ int asif_lu_cong = 0;
+ int ir_lu_cong = 0;
int maxlen = 0;
int do_quiet = 0;
int do_raw = 0;
@@ -357,6 +416,7 @@ main(int argc, char * argv[])
const char * device_name = NULL;
const char * cp;
unsigned char lun_arr[8];
+ struct sg_simple_inquiry_resp sir;
unsigned char * reportLunsBuff = NULL;
int ret = 0;
@@ -364,10 +424,10 @@ main(int argc, char * argv[])
int option_index = 0;
#ifdef SG_LIB_LINUX
- c = getopt_long(argc, argv, "dhHlm:qrRs:t:vV", long_options,
+ c = getopt_long(argc, argv, "dhHlLm:qrRs:t:vV", long_options,
&option_index);
#else
- c = getopt_long(argc, argv, "dhHm:qrRs:t:vV", long_options,
+ c = getopt_long(argc, argv, "dhHLm:qrRs:t:vV", long_options,
&option_index);
#endif
if (c == -1)
@@ -389,11 +449,14 @@ main(int argc, char * argv[])
++do_linux;
break;
#endif
+ case 'L':
+ ++asif_lu_cong;
+ break;
case 'm':
maxlen = sg_get_num(optarg);
if ((maxlen < 0) || (maxlen > MAX_RLUNS_BUFF_LEN)) {
- fprintf(stderr, "argument to '--maxlen' should be %d or "
- "less\n", MAX_RLUNS_BUFF_LEN);
+ pr2serr("argument to '--maxlen' should be %d or less\n",
+ MAX_RLUNS_BUFF_LEN);
return SG_LIB_SYNTAX_ERROR;
}
break;
@@ -409,8 +472,7 @@ main(int argc, char * argv[])
case 's':
select_rep = sg_get_num(optarg);
if ((select_rep < 0) || (select_rep > 255)) {
- fprintf(stderr, "bad argument to '--select', expect 0 to "
- "255\n");
+ pr2serr("bad argument to '--select', expect 0 to 255\n");
return SG_LIB_SYNTAX_ERROR;
}
break;
@@ -421,10 +483,10 @@ main(int argc, char * argv[])
++verbose;
break;
case 'V':
- fprintf(stderr, "version: %s\n", version_str);
+ pr2serr("version: %s\n", version_str);
return 0;
default:
- fprintf(stderr, "unrecognised option code 0x%x ??\n", c);
+ pr2serr("unrecognised option code 0x%x ??\n", c);
usage();
return SG_LIB_SYNTAX_ERROR;
}
@@ -436,8 +498,7 @@ main(int argc, char * argv[])
}
if (optind < argc) {
for (; optind < argc; ++optind)
- fprintf(stderr, "Unexpected extra argument: %s\n",
- argv[optind]);
+ pr2serr("Unexpected extra argument: %s\n", argv[optind]);
usage();
return SG_LIB_SYNTAX_ERROR;
}
@@ -452,8 +513,8 @@ main(int argc, char * argv[])
uint64_t ull;
if (1 != sscanf(cp + 1, " %" SCNu64, &ull)) {
- fprintf(stderr, "Unable to read Linux style LUN integer "
- "given to --test=\n");
+ pr2serr("Unable to read Linux style LUN integer given to "
+ "--test=\n");
return SG_LIB_SYNTAX_ERROR;
}
linux2t10_lun(ull, lun_arr);
@@ -485,8 +546,8 @@ main(int argc, char * argv[])
}
}
if (0 == k) {
- fprintf(stderr, "expected a hex number, optionally prefixed "
- "by '0x'\n");
+ pr2serr("expected a hex number, optionally prefixed by "
+ "'0x'\n");
return SG_LIB_SYNTAX_ERROR;
}
}
@@ -525,11 +586,11 @@ main(int argc, char * argv[])
}
#endif
printf("Decoded LUN:\n");
- decode_lun(" ", lun_arr, do_hex, verbose);
+ decode_lun(" ", lun_arr, asif_lu_cong, do_hex, verbose);
return 0;
}
if (NULL == device_name) {
- fprintf(stderr, "missing device name!\n");
+ pr2serr("missing device name!\n");
usage();
return SG_LIB_SYNTAX_ERROR;
}
@@ -543,16 +604,27 @@ main(int argc, char * argv[])
sg_fd = sg_cmds_open_device(device_name, o_readonly, verbose);
if (sg_fd < 0) {
- fprintf(stderr, "open error: %s: %s\n", device_name,
- safe_strerror(-sg_fd));
+ pr2serr("open error: %s: %s\n", device_name, safe_strerror(-sg_fd));
return SG_LIB_FILE_ERROR;
}
+ if (decode) {
+ /* check if LU_CONG set in standard INQUIRY response */
+ res = sg_simple_inquiry(sg_fd, &sir, 0, verbose);
+ ret = res;
+ if (res) {
+ pr2serr("fetching standard INQUIRY response failed\n");
+ goto the_end;
+ }
+ ir_lu_cong = !!(0x40 & sir.byte_1);
+ if (verbose && ir_lu_cong)
+ pr2serr("LU_CONG bit set in standard INQUIRY response\n");
+ }
if (0 == maxlen)
maxlen = DEF_RLUNS_BUFF_LEN;
reportLunsBuff = (unsigned char *)calloc(1, maxlen);
if (NULL == reportLunsBuff) {
- fprintf(stderr, "unable to malloc %d bytes\n", maxlen);
+ pr2serr("unable to malloc %d bytes\n", maxlen);
return SG_LIB_CAT_OTHER;
}
trunc = 0;
@@ -581,11 +653,11 @@ main(int argc, char * argv[])
if ((list_len + 8) > maxlen) {
luns = ((maxlen - 8) / 8);
trunc = 1;
- fprintf(stderr, " <<too many luns for internal buffer, will "
- "show %d lun%s>>\n", luns, ((1 == luns) ? "" : "s"));
+ pr2serr(" <<too many luns for internal buffer, will show %d "
+ "lun%s>>\n", luns, ((1 == luns) ? "" : "s"));
}
if (verbose > 1) {
- fprintf(stderr, "\nOutput response in hex\n");
+ pr2serr("\nOutput response in hex\n");
dStrHexErr((const char *)reportLunsBuff,
(trunc ? maxlen : list_len + 8), 1);
}
@@ -610,21 +682,21 @@ main(int argc, char * argv[])
#endif
printf("\n");
if (decode)
- decode_lun(" ", reportLunsBuff + off, do_hex,
+ decode_lun(" ", reportLunsBuff + off, ir_lu_cong, do_hex,
verbose);
}
} else if (SG_LIB_CAT_INVALID_OP == res)
- fprintf(stderr, "Report Luns command not supported (support "
- "mandatory in SPC-3)\n");
+ pr2serr("Report Luns command not supported (support mandatory in "
+ "SPC-3)\n");
else if (SG_LIB_CAT_ABORTED_COMMAND == res)
- fprintf(stderr, "Report Luns, aborted command\n");
+ pr2serr("Report Luns, aborted command\n");
else if (SG_LIB_CAT_ILLEGAL_REQ == res)
- fprintf(stderr, "Report Luns command has bad field in cdb\n");
+ pr2serr("Report Luns command has bad field in cdb\n");
else {
char b[80];
sg_get_category_sense_str(res, sizeof(b), b, verbose);
- fprintf(stderr, "Report Luns command: %s\n", b);
+ pr2serr("Report Luns command: %s\n", b);
}
the_end:
@@ -632,7 +704,7 @@ the_end:
free(reportLunsBuff);
res = sg_cmds_close_device(sg_fd);
if (res < 0) {
- fprintf(stderr, "close error: %s\n", safe_strerror(-res));
+ pr2serr("close error: %s\n", safe_strerror(-res));
if (0 == ret)
return SG_LIB_FILE_ERROR;
}
diff --git a/src/sg_rep_zones.c b/src/sg_rep_zones.c
index 99d4f5d3..0494e759 100644
--- a/src/sg_rep_zones.c
+++ b/src/sg_rep_zones.c
@@ -30,7 +30,7 @@
* and decodes the response.
*/
-static const char * version_str = "1.01 20140527";
+static const char * version_str = "1.02 20140604";
#define MAX_RZONES_BUFF_LEN (1024 * 1024)
#define DEF_RZONES_BUFF_LEN (1024 * 8)
@@ -116,11 +116,8 @@ sg_ll_report_zones(int sg_fd, uint64_t zs_lba, int report_opts, void * resp,
unsigned char sense_b[SENSE_BUFF_LEN];
struct sg_pt_base * ptvp;
- if ((zs_lba >> 56) & 0xff) {
- pr2serr("%s: zone start LBA too large\n", __func__);
- return SG_LIB_CAT_MALFORMED;
- }
- /* a 7 byte field as zbc-r01a claims ?? */
+ /* assume zbc-r01a is wrong and that ZS LBA is an 8 byte field */
+ rzCmdBlk[2] = (zs_lba >> 56) & 0xff;
rzCmdBlk[3] = (zs_lba >> 48) & 0xff;
rzCmdBlk[4] = (zs_lba >> 40) & 0xff;
rzCmdBlk[5] = (zs_lba >> 32) & 0xff;
diff --git a/src/sg_reset_wp.c b/src/sg_reset_wp.c
index cdc1f5d4..6ca532ce 100644
--- a/src/sg_reset_wp.c
+++ b/src/sg_reset_wp.c
@@ -30,7 +30,7 @@
* device.
*/
-static const char * version_str = "1.00 20140527";
+static const char * version_str = "1.01 20140604";
#define SERVICE_ACTION_OUT_16_CMD 0x9f
#define SERVICE_ACTION_OUT_16_CMDLEN 16
@@ -103,11 +103,8 @@ sg_ll_reset_write_pointer(int sg_fd, uint64_t zid, int reset_all, int noisy,
unsigned char sense_b[SENSE_BUFF_LEN];
struct sg_pt_base * ptvp;
- if ((zid >> 56) & 0xff) {
- pr2serr("%s: zone id (LBA) too large\n", __func__);
- return SG_LIB_CAT_MALFORMED;
- }
- /* a 7 byte field as zbc-r01a claims ?? */
+ /* assume zbc-r01a is wrong and that ZS LBA is an 8 byte field */
+ rwpCmdBlk[2] = (zid >> 56) & 0xff;
rwpCmdBlk[3] = (zid >> 48) & 0xff;
rwpCmdBlk[4] = (zid >> 40) & 0xff;
rwpCmdBlk[5] = (zid >> 32) & 0xff;