aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog2
-rw-r--r--README2
-rw-r--r--debian/changelog2
-rw-r--r--doc/sg_get_lba_status.811
-rw-r--r--doc/sg_unmap.816
-rw-r--r--doc/sg_write_same.820
-rw-r--r--include/sg_cmds_extra.h5
-rw-r--r--lib/sg_cmds_basic.c2
-rw-r--r--lib/sg_cmds_extra.c12
-rw-r--r--lib/sg_lib_data.c3
-rw-r--r--sg3_utils.spec2
-rw-r--r--src/sg_get_lba_status.c19
-rw-r--r--src/sg_inq.c5
-rw-r--r--src/sg_logs.c8
-rw-r--r--src/sg_unmap.c22
-rw-r--r--src/sg_vpd.c306
-rw-r--r--src/sg_write_same.c17
-rw-r--r--utils/Makefile.cygwin33
-rw-r--r--utils/README7
19 files changed, 324 insertions, 170 deletions
diff --git a/ChangeLog b/ChangeLog
index 38aa0e76..514fdf67 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.29 [20100326] [svn: r332]
+Changelog for sg3_utils-1.29 [20100331] [svn: r333]
- sg_rtpg: new logical block dependent state and bit (spc4r23)
- sg_start: add '--readonly' option for ATA disks
- sg_lib: update asc/ascq list to spc4r22
diff --git a/README b/README
index 5f52792a..88fad270 100644
--- a/README
+++ b/README
@@ -364,4 +364,4 @@ See http://sg.danny.cz/sg/tools.html
Doug Gilbert
-26th March 2010
+31st March 2010
diff --git a/debian/changelog b/debian/changelog
index e4c47d4c..7f4f30cf 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -2,7 +2,7 @@ sg3-utils (1.29-0.1) unstable; urgency=low
* New upstream version
- -- Doug Gilbert <dgilbert@interlog.com> Sun, 21 Mar 2010 14:00:00 -0400
+ -- Doug Gilbert <dgilbert@interlog.com> Wed, 31 Mar 2010 23:00:00 -0400
sg3-utils (1.28-0.1) unstable; urgency=low
diff --git a/doc/sg_get_lba_status.8 b/doc/sg_get_lba_status.8
index 52658d4a..088b15a6 100644
--- a/doc/sg_get_lba_status.8
+++ b/doc/sg_get_lba_status.8
@@ -1,4 +1,4 @@
-.TH SG_GET_LBA_STATUS "8" "September 2009" "sg3_utils\-1.28" SG3_UTILS
+.TH SG_GET_LBA_STATUS "8" "March 2010" "sg3_utils\-1.29" SG3_UTILS
.SH NAME
sg_get_lba_status \- send the SCSI GET LBA STATUS command
.SH SYNOPSIS
@@ -17,8 +17,9 @@ 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) and 1 (unmapped) are used currently.
-The amount of output can be reduced by the \fI\-\-brief\fR option.
+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.
.SH OPTIONS
Arguments to long options are mandatory for short options as well.
.TP
@@ -61,7 +62,7 @@ caused by this option is sent to stderr.
\fB\-V\fR, \fB\-\-version\fR
print the version string and then exit.
.SH NOTES
-For a discussion of thin provisioning see section 4.6.3 of sbcr20.pdf
+For a discussion of thin provisioning see section 4.6.3 of sbcr22.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
@@ -71,7 +72,7 @@ Written by Douglas Gilbert.
.SH "REPORTING BUGS"
Report bugs to <dgilbert at interlog dot com>.
.SH COPYRIGHT
-Copyright \(co 2009 Douglas Gilbert
+Copyright \(co 2009\-2010 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_unmap.8 b/doc/sg_unmap.8
index 08e12316..be0b546d 100644
--- a/doc/sg_unmap.8
+++ b/doc/sg_unmap.8
@@ -1,17 +1,18 @@
-.TH SG_UNMAP "8" "June 2009" "sg3_utils\-1.28" SG3_UTILS
+.TH SG_UNMAP "8" "March 2010" "sg3_utils\-1.29" SG3_UTILS
.SH NAME
sg_unmap \- sends a SCSI UNMAP command
.SH SYNOPSIS
.B sg_unmap
-[\fI\-\-grpnum=GN\fR] [\fI\-\-help\fR] [\fI\-\-in=FILE\fR]
+[\fI\-\-anchor\fR] [\fI\-\-grpnum=GN\fR] [\fI\-\-help\fR] [\fI\-\-in=FILE\fR]
[\fI\-\-lba=LBA,LBA...\fR] [\fI\-\-num=NUM,NUM...\fR] [\fI\-\-timeout=TO\fR]
[\fI\-\-verbose\fR] [\fI\-\-version\fR] \fIDEVICE\fR
.SH DESCRIPTION
.\" Add any additional description here
.PP
Send a SCSI UNMAP command to \fIDEVICE\fR to unmap one or more logical
-blocks. Introduced in SBC\-3 revision 18 under the broad heading
-of "logical block provisioning" or more specifically "thin provisioning".
+blocks. This command was introduced in SBC\-3 revision 18 under the broad
+heading of "logical block provisioning" or more specifically "thin
+provisioning".
Logical blocks may also be unmapped by the SCSI WRITE SAME (16 and 32
byte cdbs); see sg_write_same. The unmap capability is closely related to
the ATA DATA SET MANAGEMENT command with the "Trim" bit set.
@@ -39,6 +40,9 @@ on separate lines.
.SH OPTIONS
Arguments to long options are mandatory for short options as well.
.TP
+\fB\-a\fR, \fB\-\-anchor\fR
+sets the 'Anchor' bit in the command (introduced in sbc3r22).
+.TP
\fB\-g\fR, \fB\-\-grpnum\fR=\fIGN\fR
sets the 'Group number' field to \fIGN\fR. Defaults to a value of zero.
\fIGN\fR should be a value between 0 and 31.
@@ -109,9 +113,9 @@ Written by Douglas Gilbert.
.SH "REPORTING BUGS"
Report bugs to <dgilbert at interlog dot com>.
.SH COPYRIGHT
-Copyright \(co 2009 Douglas Gilbert
+Copyright \(co 2009\-2010 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.
.SH "SEE ALSO"
-.B sg_format,sg_readcap,sg_write_same(sg3_utils)
+.B sg_format,sg_get_lba_status,sg_readcap,sg_write_same(sg3_utils)
diff --git a/doc/sg_write_same.8 b/doc/sg_write_same.8
index de463790..b4c6915b 100644
--- a/doc/sg_write_same.8
+++ b/doc/sg_write_same.8
@@ -1,13 +1,13 @@
-.TH SG_WRITE_SAME "8" "June 2009" "sg3_utils\-1.28" SG3_UTILS
+.TH SG_WRITE_SAME "8" "March 2010" "sg3_utils\-1.29" SG3_UTILS
.SH NAME
sg_write_same \- send the SCSI WRITE SAME command
.SH SYNOPSIS
.B sg_write_same
-[\fI\-\-16\fR] [\fI\-\-32\fR] [\fI\-\-grpnum=GN\fR] [\fI\-\-help\fR]
-[\fI\-\-in=IF\fR] [\fI\-\-lba=LBA\fR] [\fI\-\-lbdata\fR] [\fI\-\-num=NUM\fR]
-[\fI\-\-pbdata\fR] [\fI\-\-timeout=TO\fR] [\fI\-\-unmap\fR]
-[\fI\-\-verbose\fR] [\fI\-\-version\fR] [\fI\-\-wrprotect=WPR\fR]
-[\fI\-\-xferlen=LEN\fR] \fIDEVICE\fR
+[\fI\-\-16\fR] [\fI\-\-32\fR] [\fI\-\-anchor\fR] [\fI\-\-grpnum=GN\fR]
+[\fI\-\-help\fR] [\fI\-\-in=IF\fR] [\fI\-\-lba=LBA\fR] [\fI\-\-lbdata\fR]
+[\fI\-\-num=NUM\fR] [\fI\-\-pbdata\fR] [\fI\-\-timeout=TO\fR]
+[\fI\-\-unmap\fR] [\fI\-\-verbose\fR] [\fI\-\-version\fR]
+[\fI\-\-wrprotect=WPR\fR] [\fI\-\-xferlen=LEN\fR] \fIDEVICE\fR
.SH DESCRIPTION
.\" Add any additional description here
Send the SCSI WRITE SAME (10, 16 or 32 byte) command to \fIDEVICE\fR. This
@@ -55,6 +55,10 @@ send a SCSI WRITE SAME (32) command to \fIDEVICE\fR. The default action (in
the absence of this option and the \fI\-\-16\fR option) is to send a SCSI
WRITE SAME (10) command.
.TP
+\fB\-a\fR, \fB\-\-anchor\fR
+sets the 'Anchor' bit in the cdb. Ignored by WRITE SAME(10). Introduced in
+sbc3r22.
+.TP
\fB\-g\fR, \fB\-\-grpnum\fR=\fIGN\fR
sets the 'Group number' field to \fIGN\fR. Defaults to a value of zero.
\fIGN\fR should be a value between 0 and 31.
@@ -167,9 +171,9 @@ Written by Douglas Gilbert.
.SH "REPORTING BUGS"
Report bugs to <dgilbert at interlog dot com>.
.SH COPYRIGHT
-Copyright \(co 2009 Douglas Gilbert
+Copyright \(co 2009\-2010 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.
.SH "SEE ALSO"
-.B sg_format,sg_readcap,sg_unmap(sg3_utils)
+.B sg_format,sg_get_lba_status,sg_readcap,sg_unmap(sg3_utils)
diff --git a/include/sg_cmds_extra.h b/include/sg_cmds_extra.h
index fc99ec94..d3bf6c8f 100644
--- a/include/sg_cmds_extra.h
+++ b/include/sg_cmds_extra.h
@@ -193,6 +193,11 @@ extern int sg_ll_set_id_info(int sg_fd, int itype, void * paramp,
* SG_LIB_CAT_UNIT_ATTENTION, -1 -> other failure */
extern int sg_ll_unmap(int sg_fd, int group_num, int timeout_secs,
void * paramp, int param_len, int noisy, int verbose);
+/* Invokes a SCSI UNMAP (SBC-3) command. Version 2 adds anchor field
+ * (sbc3r22). Otherwise same as sg_ll_unmap() . */
+extern int sg_ll_unmap_v2(int sg_fd, int anchor, int group_num,
+ int timeout_secs, void * paramp, int param_len,
+ int noisy, int verbose);
/* Invokes a SCSI VERIFY (10) command (SBC and MMC).
* Note that 'veri_len' is in blocks while 'data_out_len' is in bytes.
diff --git a/lib/sg_cmds_basic.c b/lib/sg_cmds_basic.c
index 719bd005..2602b3e4 100644
--- a/lib/sg_cmds_basic.c
+++ b/lib/sg_cmds_basic.c
@@ -27,7 +27,7 @@
#endif
-static char * version_str = "1.48 20100312";
+static char * version_str = "1.49 20100331";
#define SENSE_BUFF_LEN 32 /* Arbitrary, could be larger */
diff --git a/lib/sg_cmds_extra.c b/lib/sg_cmds_extra.c
index 78041e25..0206f32b 100644
--- a/lib/sg_cmds_extra.c
+++ b/lib/sg_cmds_extra.c
@@ -1829,12 +1829,24 @@ int
sg_ll_unmap(int sg_fd, int group_num, int timeout_secs, void * paramp,
int param_len, int noisy, int verbose)
{
+ return sg_ll_unmap_v2(sg_fd, 0, group_num, timeout_secs, paramp,
+ param_len, noisy, verbose);
+}
+
+/* Invokes a SCSI UNMAP (SBC-3) command. Version 2 adds anchor field
+ * (sbc3r22). Otherwise same as sg_ll_unmap() . */
+int
+sg_ll_unmap_v2(int sg_fd, int anchor, int group_num, int timeout_secs,
+ void * paramp, int param_len, int noisy, int verbose)
+{
int k, res, ret, sense_cat, tmout;
unsigned char uCmdBlk[UNMAP_CMDLEN] =
{UNMAP_CMD, 0, 0, 0, 0, 0, 0, 0, 0, 0};
unsigned char sense_b[SENSE_BUFF_LEN];
struct sg_pt_base * ptvp;
+ if (anchor)
+ uCmdBlk[1] |= 0x1;
tmout = (timeout_secs > 0) ? timeout_secs : DEF_PT_TIMEOUT;
uCmdBlk[7] = group_num & 0x1f;
uCmdBlk[7] = (param_len >> 8) & 0xff;
diff --git a/lib/sg_lib_data.c b/lib/sg_lib_data.c
index 9155d49b..5d471677 100644
--- a/lib/sg_lib_data.c
+++ b/lib/sg_lib_data.c
@@ -15,7 +15,7 @@
#endif
-const char * sg_lib_version_str = "1.57 20100312"; /* spc-4 rev 23 */
+const char * sg_lib_version_str = "1.58 20100329"; /* spc-4 rev 23 */
struct sg_lib_value_name_t sg_lib_normal_opcodes[] = {
{0, 0, "Test Unit Ready"},
@@ -239,6 +239,7 @@ struct sg_lib_value_name_t sg_lib_serv_in16_arr[] = {
{0x10, 0, "Read capacity(16)"},
{0x11, 0, "Read long(16)"},
{0x12, 0, "Get LBA status"},
+ {0x13, 0, "Report referrals"},
{0xffff, 0, NULL},
};
diff --git a/sg3_utils.spec b/sg3_utils.spec
index a98017ac..020947a6 100644
--- a/sg3_utils.spec
+++ b/sg3_utils.spec
@@ -79,7 +79,7 @@ fi
%{_libdir}/*.la
%changelog
-* Sun Mar 21 2010 - dgilbert at interlog dot com
+* Wed Mar 31 2010 - dgilbert at interlog dot com
- track t10 changes
* sg3_utils-1.29
diff --git a/src/sg_get_lba_status.c b/src/sg_get_lba_status.c
index 70dec322..dc2f33a9 100644
--- a/src/sg_get_lba_status.c
+++ b/src/sg_get_lba_status.c
@@ -27,7 +27,7 @@
* This program issues the SCSI GET LBA STATUS command to the given SCSI device.
*/
-static char * version_str = "1.01 20100312";
+static char * version_str = "1.02 20100329"; /* sbc2r22 */
#define MAX_GLBAS_BUFF_LEN (1024 * 1024)
#define DEF_GLBAS_BUFF_LEN 24
@@ -312,11 +312,20 @@ main(int argc, char * argv[])
for (j = 0; j < 8; ++j)
printf("%02x", ucp[j]);
printf(" blocks: %d", d_blocks);
- if ((0 == res) || (1 == res))
- printf(" %s\n",
- ((0x1 & ucp[12]) ? "unmapped" : "mapped"));
- else
+ switch (res) {
+ case 0:
+ printf(" mapped\n");
+ break;
+ case 1:
+ printf(" deallocated\n");
+ break;
+ case 2:
+ printf(" anchored\n");
+ break;
+ default:
printf(" Provisioning status: %d\n", res);
+ break;
+ }
}
}
if ((num_descs * 16) + 8 < rlen)
diff --git a/src/sg_inq.c b/src/sg_inq.c
index 65c17366..7b1d3eeb 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.87 20100228"; /* SPC-4 rev 23 */
+static char * version_str = "0.88 20100331"; /* SPC-4 rev 23 */
#define VPD_SUPPORTED_VPDS 0x0
@@ -84,6 +84,7 @@ static char * version_str = "0.87 20100228"; /* SPC-4 rev 23 */
#define VPD_BLOCK_LIMITS 0xb0
#define VPD_BLOCK_DEV_CHARS 0xb1
#define VPD_THIN_PROVISIONING 0xb2
+#define VPD_REFERRALS 0xb3
#define VPD_UPR_EMC 0xc0
#define VPD_RDAC_VERS 0xc2
#define VPD_RDAC_VAC 0xc9
@@ -1408,6 +1409,8 @@ decode_b0_vpd(unsigned char * buff, int len, int do_hex, int pdt)
"short=%d\n", len);
return;
}
+ printf(" Maximum compare and write length: %u blocks\n",
+ buff[5]);
u = (buff[6] << 8) | buff[7];
printf(" Optimal transfer length granularity: %u blocks\n", u);
u = (buff[8] << 24) | (buff[9] << 16) | (buff[10] << 8) |
diff --git a/src/sg_logs.c b/src/sg_logs.c
index 6126632b..770c542a 100644
--- a/src/sg_logs.c
+++ b/src/sg_logs.c
@@ -25,7 +25,7 @@
*/
-static char * version_str = "0.94 20100226"; /* SPC-4 revision 23 */
+static char * version_str = "0.95 20100331"; /* SPC-4 revision 23 */
#define MX_ALLOC_LEN (0xfffc)
#define SHORT_RESP_LEN 128
@@ -2620,6 +2620,7 @@ show_thin_provisioning_page(unsigned char * resp, int len, int show_pcb)
{
int j, num, pl, pc, pcb;
unsigned char * ucp;
+ char * cp;
char str[PCB_STR_LEN];
printf("Thin provisioning page (sbc-3) [0xc]\n");
@@ -2629,8 +2630,9 @@ show_thin_provisioning_page(unsigned char * resp, int len, int show_pcb)
pc = (ucp[0] << 8) | ucp[1];
pcb = ucp[2];
pl = ucp[3] + 4;
- if ((pc >= 0x1) && (pc <= 0xff)) {
- printf(" Threshold resource count [0x%x]:", pc);
+ if ((pc >= 0x1) && (pc <= 0x2)) {
+ cp = (0x1 == pc)? "Available" : "Used";
+ printf(" %s LBA mapping threshold resource count:", cp);
if ((pl < 8) || (num < 8)) {
if (num < 8)
fprintf(stderr, "\n truncated by response length, "
diff --git a/src/sg_unmap.c b/src/sg_unmap.c
index f6566f01..db151a7f 100644
--- a/src/sg_unmap.c
+++ b/src/sg_unmap.c
@@ -29,7 +29,7 @@
* logical blocks.
*/
-static char * version_str = "1.00 20100312";
+static char * version_str = "1.01 20100331";
#define DEF_TIMEOUT_SECS 60
@@ -37,6 +37,7 @@ static char * version_str = "1.00 20100312";
static struct option long_options[] = {
+ {"anchor", no_argument, 0, 'a'},
{"grpnum", required_argument, 0, 'g'},
{"help", no_argument, 0, 'h'},
{"in", required_argument, 0, 'I'},
@@ -52,11 +53,12 @@ static void
usage()
{
fprintf(stderr, "Usage: "
- "sg_unmap [--grpnum=GN] [--help] [--in=FILE] [--lba=LBA,LBA..]\n"
- " [--num=NUM,NUM...] [--timeout=TO] [--verbose] "
- "[--version]\n"
- " DEVICE\n"
+ "sg_unmap [--anchor] [--grpnum=GN] [--help] [--in=FILE]\n"
+ " [--lba=LBA,LBA..] [--num=NUM,NUM...] "
+ "[--timeout=TO]\n"
+ " [--verbose] [--version] DEVICE\n"
" where:\n"
+ " --anchor|-a set anchor field in cdb\n"
" --grpnum=GN|-g GN GN is group number field (def: 0)\n"
" --help|-h print out usage message\n"
" --in=FILE|-I FILE read LBA, NUM pairs in ASCII hex "
@@ -331,6 +333,7 @@ main(int argc, char * argv[])
const char * in_op = NULL;
int addr_arr_len = 0;
int num_arr_len = 0;
+ int anchor = 0;
int timeout = DEF_TIMEOUT_SECS;
int verbose = 0;
const char * device_name = NULL;
@@ -343,12 +346,15 @@ main(int argc, char * argv[])
while (1) {
int option_index = 0;
- c = getopt_long(argc, argv, "ghIHl:n:t:vV", long_options,
+ c = getopt_long(argc, argv, "aghIHl:n:t:vV", long_options,
&option_index);
if (c == -1)
break;
switch (c) {
+ case 'a':
+ ++anchor;
+ break;
case 'g':
num = sscanf(optarg, "%d", &res);
if ((1 == num) && ((res < 0) || (res > 31)))
@@ -493,8 +499,8 @@ main(int argc, char * argv[])
return SG_LIB_FILE_ERROR;
}
- res = sg_ll_unmap(sg_fd, grpnum, timeout, param_arr, param_len,
- 1, verbose);
+ res = sg_ll_unmap_v2(sg_fd, anchor, grpnum, timeout, param_arr, param_len,
+ 1, verbose);
ret = res;
if (SG_LIB_CAT_NOT_READY == res) {
fprintf(stderr, "UNMAP failed, device not ready\n");
diff --git a/src/sg_vpd.c b/src/sg_vpd.c
index 38ef62e9..08e4d0c6 100644
--- a/src/sg_vpd.c
+++ b/src/sg_vpd.c
@@ -30,7 +30,7 @@
*/
-static char * version_str = "0.40 20100312"; /* spc4r23 + sbc3r21 */
+static char * version_str = "0.41 20100331"; /* spc4r23 + sbc3r22 */
extern void svpd_enumerate_vendor(void);
extern int svpd_decode_vendor(int sg_fd, int num_vpd, int subvalue,
@@ -64,6 +64,7 @@ extern const struct svpd_values_name_t *
#define VPD_SECURITY_TOKEN 0xb1 /* OSD */
#define VPD_TA_SUPPORTED 0xb2 /* SSC-3 */
#define VPD_THIN_PROVISIONING 0xb2 /* SBC-3 */
+#define VPD_REFERRALS 0xb3 /* SBC-3 */
#define VPD_AUTOMATION_DEV_SN 0xb3 /* SSC-3 */
#define VPD_DTDE_ADDRESS 0xb4 /* SSC-4 */
@@ -158,6 +159,7 @@ static struct svpd_values_name_t standard_vpd_pg[] = {
{VPD_PROTO_LU, 0, 0x0, 0, "pslu", "Protocol-specific logical unit "
"information"},
{VPD_PROTO_PORT, 0, 0x0, 0, "pspo", "Protocol-specific port information"},
+ {VPD_REFERRALS, 0, 0, 0, "ref", "Referrals (SBC)"},
{VPD_SA_DEV_CAP, 0, 1, 0, "sad",
"Sequential access device capabilities (SSC)"},
{VPD_SOFTW_INF_ID, 0, -1, 0, "sii", "Software interface identification"},
@@ -166,7 +168,7 @@ static struct svpd_values_name_t standard_vpd_pg[] = {
{VPD_SECURITY_TOKEN, 0, 0x11, 0, "st", "Security token (OSD)"},
{VPD_SUPPORTED_VPDS, 0, -1, 0, "sv", "Supported VPD pages"},
{VPD_TA_SUPPORTED, 0, 1, 0, "tas", "TapeAlert supported flags (SSC)"},
- {VPD_THIN_PROVISIONING, 0, 0, 0, "thp", "Thin provisioning (SBC)"},
+ {VPD_THIN_PROVISIONING, 0, 0, 0, "thpv", "Thin provisioning (SBC)"},
{0, 0, 0, 0, NULL, NULL},
};
@@ -1302,53 +1304,55 @@ decode_b0_vpd(unsigned char * buff, int len, int do_hex, int pdt)
return;
}
switch (pdt) {
- case 0: case 4: case 7: /* Block limits */
- if (len < 16) {
- fprintf(stderr, "Block limits VPD page length too "
- "short=%d\n", len);
- return;
- }
- u = (buff[6] << 8) | buff[7];
- printf(" Optimal transfer length granularity: %u blocks\n", u);
- u = (buff[8] << 24) | (buff[9] << 16) | (buff[10] << 8) |
- buff[11];
- printf(" Maximum transfer length: %u blocks\n", u);
- u = (buff[12] << 24) | (buff[13] << 16) | (buff[14] << 8) |
- buff[15];
- printf(" Optimal transfer length: %u blocks\n", u);
- if (len > 19) { /* added in sbc3r09 */
- u = (buff[16] << 24) | (buff[17] << 16) | (buff[18] << 8) |
- buff[19];
- printf(" Maximum prefetch, xdread, xdwrite transfer length: "
- "%u blocks\n", u);
- }
- if (len > 27) { /* added in sbc3r18 */
- u = ((unsigned int)buff[20] << 24) | (buff[21] << 16) |
- (buff[22] << 8) | buff[23];
- printf(" Maximum unmap LBA count: %u\n", u);
- u = ((unsigned int)buff[24] << 24) | (buff[25] << 16) |
- (buff[26] << 8) | buff[27];
- printf(" Maximum unmap block descriptor count: %u\n", u);
- }
- if (len > 35) { /* added in sbc3r19 */
- u = ((unsigned int)buff[28] << 24) | (buff[29] << 16) |
- (buff[30] << 8) | buff[31];
- printf(" Optimal unmap granularity: %u\n", u);
- printf(" Unmap granularity alignment valid: %u\n",
- !!(buff[32] & 0x80));
- u = ((unsigned int)(buff[32] & 0x7f) << 24) | (buff[33] << 16) |
- (buff[34] << 8) | buff[35];
- printf(" Unmap granularity alignment: %u\n", u);
- }
- break;
- case 1: case 8:
- printf(" WORM=%d\n", !!(buff[4] & 0x1));
- break;
- case 0x11:
- default:
- printf(" Unable to decode pdt=0x%x, in hex:\n", pdt);
- dStrHex((const char *)buff, len, 0);
- break;
+ case 0: case 4: case 7: /* Block limits */
+ if (len < 16) {
+ fprintf(stderr, "Block limits VPD page length too "
+ "short=%d\n", len);
+ return;
+ }
+ printf(" Maximum compare and write length: %u blocks\n",
+ buff[5]);
+ u = (buff[6] << 8) | buff[7];
+ printf(" Optimal transfer length granularity: %u blocks\n", u);
+ u = (buff[8] << 24) | (buff[9] << 16) | (buff[10] << 8) |
+ buff[11];
+ printf(" Maximum transfer length: %u blocks\n", u);
+ u = (buff[12] << 24) | (buff[13] << 16) | (buff[14] << 8) |
+ buff[15];
+ printf(" Optimal transfer length: %u blocks\n", u);
+ if (len > 19) { /* added in sbc3r09 */
+ u = (buff[16] << 24) | (buff[17] << 16) | (buff[18] << 8) |
+ buff[19];
+ printf(" Maximum prefetch, xdread, xdwrite transfer length: "
+ "%u blocks\n", u);
+ }
+ if (len > 27) { /* added in sbc3r18 */
+ u = ((unsigned int)buff[20] << 24) | (buff[21] << 16) |
+ (buff[22] << 8) | buff[23];
+ printf(" Maximum unmap LBA count: %u\n", u);
+ u = ((unsigned int)buff[24] << 24) | (buff[25] << 16) |
+ (buff[26] << 8) | buff[27];
+ printf(" Maximum unmap block descriptor count: %u\n", u);
+ }
+ if (len > 35) { /* added in sbc3r19 */
+ u = ((unsigned int)buff[28] << 24) | (buff[29] << 16) |
+ (buff[30] << 8) | buff[31];
+ printf(" Optimal unmap granularity: %u\n", u);
+ printf(" Unmap granularity alignment valid: %u\n",
+ !!(buff[32] & 0x80));
+ u = ((unsigned int)(buff[32] & 0x7f) << 24) | (buff[33] << 16) |
+ (buff[34] << 8) | buff[35];
+ printf(" Unmap granularity alignment: %u\n", u);
+ }
+ break;
+ case 1: case 8:
+ printf(" WORM=%d\n", !!(buff[4] & 0x1));
+ break;
+ case 0x11:
+ default:
+ printf(" Unable to decode pdt=0x%x, in hex:\n", pdt);
+ dStrHex((const char *)buff, len, 0);
+ break;
}
}
@@ -1362,72 +1366,85 @@ decode_b1_vpd(unsigned char * buff, int len, int do_hex, int pdt)
return;
}
switch (pdt) {
- case 0: case 4: case 7:
- if (len < 64) {
- fprintf(stderr, "Block device characteristics VPD page length "
- "too short=%d\n", len);
- return;
- }
- u = (buff[4] << 8) | buff[5];
- if (0 == u)
- printf(" Medium rotation rate is not reported\n");
- else if (1 == u)
- printf(" Non-rotating medium (e.g. solid state)\n");
- else if ((u < 0x401) || (0xffff == u))
- printf(" Reserved [0x%x]\n", u);
- else
- printf(" Nominal rotation rate: %d rpm\n", u);
- u = buff[7] & 0xf;
- printf(" Nominal form factor");
- switch (u)
- {
- case 0:
- printf(" not reported\n");
- break;
- case 1:
- printf(": 5.25 inch\n");
- break;
- case 2:
- printf(": 3.5 inch\n");
- break;
- case 3:
- printf(": 2.5 inch\n");
- break;
- case 4:
- printf(": 1.8 inch\n");
- break;
- case 5:
- printf(": less then 1.8 inch\n");
- break;
- default:
- printf(": reserved\n");
- break;
- }
+ case PDT_DISK: case PDT_WO: case PDT_OPTICAL:
+ if (len < 64) {
+ fprintf(stderr, "Block device characteristics VPD page length "
+ "too short=%d\n", len);
+ return;
+ }
+ u = (buff[4] << 8) | buff[5];
+ if (0 == u)
+ printf(" Medium rotation rate is not reported\n");
+ else if (1 == u)
+ printf(" Non-rotating medium (e.g. solid state)\n");
+ else if ((u < 0x401) || (0xffff == u))
+ printf(" Reserved [0x%x]\n", u);
+ else
+ printf(" Nominal rotation rate: %d rpm\n", u);
+ u = buff[7] & 0xf;
+ printf(" Nominal form factor");
+ switch (u) {
+ case 0:
+ printf(" not reported\n");
+ break;
+ case 1:
+ printf(": 5.25 inch\n");
break;
- case 1: case 8: case 0x12:
- printf(" Manufacturer-assigned serial number: %.*s\n",
- len - 4, buff + 4);
+ case 2:
+ printf(": 3.5 inch\n");
+ break;
+ case 3:
+ printf(": 2.5 inch\n");
+ break;
+ case 4:
+ printf(": 1.8 inch\n");
+ break;
+ case 5:
+ printf(": less then 1.8 inch\n");
break;
default:
- printf(" Unable to decode pdt=0x%x, in hex:\n", pdt);
- dStrHex((const char *)buff, len, 0);
+ printf(": reserved\n");
break;
+ }
+ break;
+ case PDT_TAPE: case PDT_MCHANGER: case PDT_ADC:
+ printf(" Manufacturer-assigned serial number: %.*s\n",
+ len - 4, buff + 4);
+ break;
+ default:
+ printf(" Unable to decode pdt=0x%x, in hex:\n", pdt);
+ dStrHex((const char *)buff, len, 0);
+ break;
}
}
static int
decode_block_thin_prov_vpd(unsigned char * b, int len)
{
- int dp;
+ int dp, anc_sup;
if (len < 4) {
fprintf(stderr, "Thin provisioning page too short=%d\n",
len);
return SG_LIB_CAT_MALFORMED;
}
+ printf(" Unmap supported (TPU): %d\n", !!(0x80 & b[5]));
+ printf(" Write same with unmap supported (TPWS): %d\n", !!(0x40 & b[5]));
+ anc_sup = (b[5] >> 1) & 0x7;
+ switch (anc_sup) {
+ case 0:
+ printf(" Anchored LBAs not supported\n");
+ break;
+ case 1:
+ printf(" Anchored LBAs supported\n");
+ break;
+ default:
+ printf(" Anchored LBAs support reserved [%d]\n", anc_sup);
+ break;
+ }
dp = !!(b[5] & 0x1);
printf(" Threshold exponent: %d\n", b[4]);
- printf(" Descriptor present: %d\n", dp);
+ printf(" Descriptor present (DP): %d\n", dp);
if (dp) {
const unsigned char * ucp;
int i_len;
@@ -1496,16 +1513,53 @@ decode_b2_vpd(unsigned char * buff, int len, int do_hex, int pdt)
return;
}
switch (pdt) {
- case PDT_DISK: case PDT_WO: case PDT_OPTICAL:
- decode_block_thin_prov_vpd(buff, len);
- break;
- case PDT_TAPE: case PDT_MCHANGER:
- decode_tapealert_supported_vpd(buff, len);
- break;
- default:
- printf(" Unable to decode pdt=0x%x, in hex:\n", pdt);
- dStrHex((const char *)buff, len, 0);
+ case PDT_DISK: case PDT_WO: case PDT_OPTICAL:
+ decode_block_thin_prov_vpd(buff, len);
+ break;
+ case PDT_TAPE: case PDT_MCHANGER:
+ decode_tapealert_supported_vpd(buff, len);
+ break;
+ default:
+ printf(" Unable to decode pdt=0x%x, in hex:\n", pdt);
+ dStrHex((const char *)buff, len, 0);
+ break;
+ }
+}
+
+static void
+decode_b3_vpd(unsigned char * b, int len, int do_hex, int pdt)
+{
+ char obuff[DEF_ALLOC_LEN];
+ unsigned int u;
+
+ if (do_hex) {
+ dStrHex((const char *)b, len, 0);
+ return;
+ }
+ switch (pdt) {
+ case PDT_DISK: case PDT_WO: case PDT_OPTICAL:
+ if (len < 16) {
+ fprintf(stderr, "Referrals VPD page length too short=%d\n", len);
break;
+ }
+ u = ((unsigned int)b[8] << 24) | (b[9] << 16) | (b[10] << 8) | b[11];
+ printf(" User data segment size: %u\n", u);
+ u = ((unsigned int)b[12] << 24) | (b[13] << 16) |
+ (b[14] << 8) | b[15];
+ printf(" User data segment multiplier: %u\n", u);
+ break;
+ case PDT_TAPE: case PDT_MCHANGER:
+ memset(obuff, 0, sizeof(obuff));
+ len -= 4;
+ if (len >= (int)sizeof(obuff))
+ len = sizeof(obuff) - 1;
+ memcpy(obuff, b + 4, len);
+ printf(" Automation device serial number: %s\n", obuff);
+ break;
+ default:
+ printf(" Unable to decode pdt=0x%x, in hex:\n", pdt);
+ dStrHex((const char *)b, len, 0);
+ break;
}
}
@@ -2205,17 +2259,17 @@ svpd_decode_t10(int sg_fd, int num_vpd, int subvalue, int maxlen, int do_hex,
pdt = rsp_buff[0] & 0x1f;
if ((! do_raw) && (! do_quiet)) {
switch (pdt) {
- case 0: case 4: case 7:
+ case PDT_DISK: case PDT_WO: case PDT_OPTICAL:
printf("Block device characteristics VPD page (SBC):\n");
break;
- case 1: case 8:
+ case PDT_TAPE: case PDT_MCHANGER:
printf("Manufactured assigned serial number VPD page "
"(SSC):\n");
break;
- case 0x11:
+ case PDT_OSD:
printf("Security token VPD page (OSD):\n");
break;
- case 0x12:
+ case PDT_ADC:
printf("Manufactured assigned serial number VPD page "
"(ADC):\n");
break;
@@ -2320,12 +2374,24 @@ svpd_decode_t10(int sg_fd, int num_vpd, int subvalue, int maxlen, int do_hex,
} else if (! do_raw)
printf("VPD page=0xb2\n");
break;
- case VPD_AUTOMATION_DEV_SN: /* 0xb3 */
- if ((! do_raw) && (! do_quiet))
- printf("Automation device serial number (SSC):\n");
+ case 0xb3: /* VPD page depends on pdt */
res = sg_ll_inquiry(sg_fd, 0, 1, num_vpd, rsp_buff, alloc_len, 1,
verbose);
if (0 == res) {
+ pdt = rsp_buff[0] & 0x1f;
+ if ((! do_raw) && (! do_quiet)) {
+ switch (pdt) {
+ case PDT_DISK: case PDT_WO: case PDT_OPTICAL:
+ printf("Referrals VPD page (SBC):\n");
+ break;
+ case PDT_TAPE: case PDT_MCHANGER:
+ printf("Automation device serial number VPD page (SSC):\n");
+ break;
+ default:
+ printf("VPD page=0x%x, pdt=0x%x:\n", 0xb3, pdt);
+ break;
+ }
+ }
len = ((rsp_buff[2] << 8) + rsp_buff[3]) + 4;
if (num_vpd != rsp_buff[1]) {
fprintf(stderr, "invalid VPD response; probably a STANDARD "
@@ -2341,8 +2407,8 @@ svpd_decode_t10(int sg_fd, int num_vpd, int subvalue, int maxlen, int do_hex,
res = sg_ll_inquiry(sg_fd, 0, 1, num_vpd, rsp_buff, len,
1, verbose);
if (res) {
- fprintf(stderr, "fetching Automation device serial "
- "number page (alloc_len=%d) failed\n", len);
+ fprintf(stderr, "fetching VPD page 0x%x "
+ "(alloc_len=%d) failed\n", num_vpd, len);
return res;
}
} else {
@@ -2359,15 +2425,11 @@ svpd_decode_t10(int sg_fd, int num_vpd, int subvalue, int maxlen, int do_hex,
printf(" [PQual=%d Peripheral device type: %s]\n",
(rsp_buff[0] & 0xe0) >> 5,
sg_get_pdt_str(pdt, sizeof(buff), buff));
- memset(obuff, 0, sizeof(obuff));
- len -= 4;
- if (len >= (int)sizeof(obuff))
- len = sizeof(obuff) - 1;
- memcpy(obuff, rsp_buff + 4, len);
- printf(" Automation device serial number: %s\n", obuff);
+ decode_b3_vpd(rsp_buff, len, do_hex, pdt);
}
return 0;
- }
+ } else if (! do_raw)
+ printf("VPD page=0xb3\n");
break;
case VPD_DTDE_ADDRESS: /* 0xb4 */
if ((! do_raw) && (! do_quiet))
diff --git a/src/sg_write_same.c b/src/sg_write_same.c
index 8ba1a290..189a7f82 100644
--- a/src/sg_write_same.c
+++ b/src/sg_write_same.c
@@ -26,7 +26,7 @@
#include "sg_cmds_basic.h"
#include "sg_cmds_extra.h"
-static char * version_str = "0.94 20100312";
+static char * version_str = "0.95 20100331";
#define ME "sg_write_same: "
@@ -50,6 +50,7 @@ static char * version_str = "0.94 20100312";
static struct option long_options[] = {
{"16", no_argument, 0, 'S'},
{"32", no_argument, 0, 'T'},
+ {"anchor", no_argument, 0, 'a'},
{"grpnum", required_argument, 0, 'g'},
{"help", no_argument, 0, 'h'},
{"in", required_argument, 0, 'i'},
@@ -67,6 +68,7 @@ static struct option long_options[] = {
};
struct opts_t {
+ int anchor;
int grpnum;
char ifilename[256];
uint64_t lba;
@@ -87,7 +89,8 @@ static void
usage()
{
fprintf(stderr, "Usage: "
- "sg_write_same [--16] [--32] [--grpnum=GN] [--help] [--in=IF]\n"
+ "sg_write_same [--16] [--32] [--anchor] [--grpnum=GN] [--help] "
+ "[--in=IF]\n"
" [--lba=LBA] [--lbdata] [--num=NUM] "
"[--pbdata]\n"
" [--timeout=TO] [--unmap] [--verbose] "
@@ -98,6 +101,7 @@ usage()
"'--unmap' given\n"
" or LBA+NUM needs more than 32 bits)\n"
" --32|-T do WRITE SAME(32) (def: 10 or 16)\n"
+ " --anchor|-a set anchor field in cdb\n"
" --grpnum=GN|-g GN GN is group number field (def: 0)\n"
" --help|-h print out usage message\n"
" --in=IF|-i IF IF is file to fetch one block of data "
@@ -170,6 +174,8 @@ do_write_same(int sg_fd, const struct opts_t * optsp, const void * dataoutp,
case WRITE_SAME16_LEN:
wsCmdBlk[0] = WRITE_SAME16_OP;
wsCmdBlk[1] = ((optsp->wrprotect & 0x7) << 5);
+ if (optsp->anchor)
+ wsCmdBlk[1] |= 0x10;
if (optsp->unmap)
wsCmdBlk[1] |= 0x8;
if (optsp->pbdata)
@@ -195,6 +201,8 @@ do_write_same(int sg_fd, const struct opts_t * optsp, const void * dataoutp,
wsCmdBlk[8] = ((WRITE_SAME32_SA >> 8) & 0xff);
wsCmdBlk[9] = (WRITE_SAME32_SA & 0xff);
wsCmdBlk[10] = ((optsp->wrprotect & 0x7) << 5);
+ if (optsp->anchor)
+ wsCmdBlk[10] |= 0x10;
if (optsp->unmap)
wsCmdBlk[10] |= 0x8;
if (optsp->pbdata)
@@ -305,12 +313,15 @@ main(int argc, char * argv[])
while (1) {
int option_index = 0;
- c = getopt_long(argc, argv, "g:hi:l:Ln:PSt:TUvVw:x:", long_options,
+ c = getopt_long(argc, argv, "ag:hi:l:Ln:PSt:TUvVw:x:", long_options,
&option_index);
if (c == -1)
break;
switch (c) {
+ case 'a':
+ ++opts.anchor;
+ break;
case 'g':
opts.grpnum = sg_get_num(optarg);
if ((opts.grpnum < 0) || (opts.grpnum > 31)) {
diff --git a/utils/Makefile.cygwin b/utils/Makefile.cygwin
new file mode 100644
index 00000000..86e9fa34
--- /dev/null
+++ b/utils/Makefile.cygwin
@@ -0,0 +1,33 @@
+# Assumes Makefile is used in a cygwin shell
+
+SHELL = /bin/sh
+
+CC = gcc
+LD = gcc
+
+EXECS = hxascdmp
+
+EXE_S = hxascdmp.exe
+
+# OS_FLAGS = -DSG_LIB_WIN32 -DSPTD
+OS_FLAGS = -DSG_LIB_WIN32
+LARGE_FILE_FLAGS = -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64
+EXTRA_FLAGS = $(OS_FLAGS) $(LARGE_FILE_FLAGS)
+
+# CFLAGS = -O2 -Wall -W $(EXTRA_FLAGS)
+CFLAGS = -g -O2 -Wall -W $(EXTRA_FLAGS)
+# CFLAGS = -g -O2 -Wall -W -pedantic -std=c99 $(EXTRA_FLAGS)
+
+LDFLAGS =
+
+all: $(EXECS)
+
+clean:
+ rm *.o $(EXE_S)
+
+.c.o:
+ $(CC) $(INCLUDES) $(CFLAGS) $(S_CFLAGS) -c -o $@ $<
+
+hxascdmp: hxascdmp.o
+ $(LD) -o $@ $(LDFLAGS) $@.o
+
diff --git a/utils/README b/utils/README
index a5e4fcdc..1662c928 100644
--- a/utils/README
+++ b/utils/README
@@ -15,8 +15,9 @@ This directory contains these utilities:
By default, the Makefile only builds the hxascdmp utility. The 'Makefile'
file (i.e. with no suffix) builds for Linux; the 'Makefile.freebsd' file
builds for FreeBSD (e.g. 'make -f Makefile.freebsd'); the
-'Makefile.solaris' file builds for Solaris; and the 'Makefile.mingw' builds
-in the Windows MinGW environment (e.g. msys shell).
+'Makefile.solaris' file builds for Solaris; the 'Makefile.mingw' builds
+in the Windows MinGW environment (e.g. msys shell); and 'Makefile.cygwin'
+builds in the Windows Cygwin environment.
To build sg_chk_asc the sg_lib.o and sg_lib_data.o files must be present
(i.e. compiled) in the lib/ subdirectory. One way to meet that requirement
@@ -25,4 +26,4 @@ Then return to this directory and do 'make sg_chk_asc'.
Doug Gilbert
-23rd June 2008
+30th March 2010