aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDouglas Gilbert <dgilbert@interlog.com>2014-05-22 13:17:09 +0000
committerDouglas Gilbert <dgilbert@interlog.com>2014-05-22 13:17:09 +0000
commiteebe59ce63d30da476a04e294a3c06ff5ae20aab (patch)
treef36076a5c4aa7b4b3fe0bf2adde80c1f7648f2f4
parent9647d3e6173589213cf585d24b8764dabf6a0c76 (diff)
downloadsg3_utils-eebe59ce63d30da476a04e294a3c06ff5ae20aab.tar.gz
sg_vpd: Supported block lengths and protection types + Block device characterics extension VPD pages added [sbc4r01/02]
git-svn-id: https://svn.bingwo.ca/repos/sg3_utils/trunk@583 6180dd3e-e324-4e3e-922d-17de1ae2f315
-rw-r--r--COVERAGE3
-rw-r--r--ChangeLog8
-rw-r--r--doc/sg_persist.82
-rwxr-xr-xexamples/sg_persist_tst.sh6
-rw-r--r--lib/sg_lib_data.c2
-rw-r--r--src/sg_opcodes.c6
-rw-r--r--src/sg_vpd.c244
7 files changed, 241 insertions, 30 deletions
diff --git a/COVERAGE b/COVERAGE
index 7e8f6645..ec3777d7 100644
--- a/COVERAGE
+++ b/COVERAGE
@@ -78,6 +78,7 @@ WRITE(6) sg_dd, sgm_dd, sgp_dd
WRITE(10) sg_dd, sgm_dd, sgp_dd
WRITE(12) sg_dd, sgm_dd, sgp_dd
WRITE(16) sg_dd, sgm_dd, sgp_dd
+WRITE ATOMIC(16) ddpt
WRITE BUFFER sg_test_rwbuf, sg_write_buffer, ++
WRITE LONG(10) sg_write_long, ++
WRITE LONG(16) sg_write_long, ++
@@ -115,4 +116,4 @@ THIRD PARTY COPY IN (0x83).
Douglas Gilbert
-15th April 2014
+22nd May 2014
diff --git a/ChangeLog b/ChangeLog
index 5702a291..083e4575 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 [20140521] [svn: r582]
+Changelog for sg3_utils-1.39 [20140522] [svn: r583]
- sg_ses: add --eiioe=auto|force option
- fix AES dpage element indexing problems
- add --readonly option
@@ -19,10 +19,14 @@ Changelog for sg3_utils-1.39 [20140521] [svn: r582]
- sg_inq: sync version descriptors dated 20105176
- sg_vpd: add --vendor=VP option, re-order vendor
specific pages, split lto into lto5 and lto6
+ - add Supported block lengths and protection types
+ page (sbc4r01)
+ - add Block device characterics extension
+ page (sbc4r02)
- sg_copy_results, sg_get_lba_status, sg_luns,
sg_read_buffer, sg_readcap, sg_referrals, sg_rtpg,
sg_sat_set_features, sg_sat_identify:
- add --readonly option
+ add --readonly option
- sginfo: strip trailing spaces from INQUIRY text
- sg_rbuf: add --echo option (to use echo buffer)
- sg_lib: add sanitize command service action names
diff --git a/doc/sg_persist.8 b/doc/sg_persist.8
index af11edea..e62c49a5 100644
--- a/doc/sg_persist.8
+++ b/doc/sg_persist.8
@@ -407,7 +407,7 @@ examples sub\-directory of the sg3_utils package. There is also a
simple test script called sg_persist_tst.sh in the same directory.
.PP
The above sequence of commands was tested successfully on a Seagate Savvio
-10K.3 disk which has a SAS interface.
+10K.3 disk and a 1200 SSD both of which have SAS interfaces.
.SH EXIT STATUS
The exit status of sg_persist is 0 when it is successful. Otherwise see
the sg3_utils(8) man page.
diff --git a/examples/sg_persist_tst.sh b/examples/sg_persist_tst.sh
index 4d68248b..c7483811 100755
--- a/examples/sg_persist_tst.sh
+++ b/examples/sg_persist_tst.sh
@@ -3,7 +3,7 @@
# in the sg3_utils package. This script works as expected on the
# author's Fujitsu MAM3184, Seagate ST373455 and ST9146803SS disks.
#
-# Version 1.8 20140516
+# Version 1.8 20140521
# N.B. make sure the device name is correct for your environment.
@@ -19,10 +19,14 @@ usage()
echo " -h, --help print usage message"
echo " -s, --second use second key"
echo " -v, --verbose more verbose output"
+ echo " -vv even more verbose output"
+ echo " -vvv even more verbose output"
echo ""
echo "Test SCSI Persistent Reservations with sg_persist utility."
echo "Default key is ${key} and alternate, second key is ${key2} ."
echo "Should be harmless (unless one of those keys is already in use)."
+ echo "Also the APTPL bit is not set on the PR register so a power cycle"
+ echo "on the device will clear it."
}
opt="$1"
diff --git a/lib/sg_lib_data.c b/lib/sg_lib_data.c
index f5a0ad68..d4002b06 100644
--- a/lib/sg_lib_data.c
+++ b/lib/sg_lib_data.c
@@ -17,7 +17,7 @@
#endif
-const char * sg_lib_version_str = "2.01 20140521"; /* spc4r36u, sbc4r02 */
+const char * sg_lib_version_str = "2.01 20140521"; /* spc4r37, sbc4r02 */
#ifdef SG_SCSI_STRINGS
struct sg_lib_value_name_t sg_lib_normal_opcodes[] = {
diff --git a/src/sg_opcodes.c b/src/sg_opcodes.c
index 4c8fe51f..862b518e 100644
--- a/src/sg_opcodes.c
+++ b/src/sg_opcodes.c
@@ -26,7 +26,7 @@
#include "sg_pt.h"
-static const char * version_str = "0.40 20140518"; /* spc4r37 */
+static const char * version_str = "0.41 20140521"; /* spc4r37 */
#define SENSE_BUFF_LEN 64 /* Arbitrary, could be larger */
@@ -505,7 +505,7 @@ list_all_codes(unsigned char * rsoc_buff, int rsoc_len, struct opts_t * op,
printf( "(hex) action(h) size \n");
printf("-----------------------------------------------\n");
}
- /* N.B. SPC-4 does _not_ requiring any ordering of response */
+ /* SPC-4 does _not_ require any ordering of opcodes in the response */
if (! op->do_unsorted) {
sort_arr = (unsigned char **)malloc(cd_len * sizeof(unsigned char *));
if (NULL == sort_arr) {
@@ -579,6 +579,8 @@ list_all_codes(unsigned char * rsoc_buff, int rsoc_len, struct opts_t * op,
}
}
}
+ if (sort_arr)
+ free(sort_arr);
}
static void
diff --git a/src/sg_vpd.c b/src/sg_vpd.c
index 577704eb..0cb1cfef 100644
--- a/src/sg_vpd.c
+++ b/src/sg_vpd.c
@@ -33,7 +33,7 @@
*/
-static const char * version_str = "0.85 20140521"; /* spc4r37 + sbc4r01 */
+static const char * version_str = "0.85 20140522"; /* spc4r37 + sbc4r01 */
/* And with sbc3r35, vale Mark Evans */
void svpd_enumerate_vendor(int vp_num);
@@ -76,7 +76,9 @@ const struct svpd_values_name_t * svpd_find_vendor_by_num(int page_num,
#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_NO_RATHER_STD_INQ -2 /* request for standard inquiry */
/* Device identification VPD page associations */
@@ -149,6 +151,8 @@ static struct svpd_values_name_t standard_vpd_pg[] = {
{VPD_BLOCK_LIMITS, 0, 0, "bl", "Block limits (SBC)"},
{VPD_BLOCK_DEV_CHARS, 0, 0, "bdc", "Block device characteristics "
"(SBC)"},
+ {VPD_BLOCK_DEV_C_EXTENS, 0, 0, "bdce", "Block device characteristics "
+ "extension (SBC)"},
{VPD_CFA_PROFILE_INFO, 0, 0, "cfa", "CFA profile information"},
{VPD_DEVICE_CONSTITUENTS, 0, -1, "dc", "Device constituents"},
{VPD_DEVICE_ID, 0, -1, "di", "Device identification"},
@@ -187,6 +191,8 @@ static struct svpd_values_name_t standard_vpd_pg[] = {
{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"},
@@ -2254,7 +2260,7 @@ decode_b0_vpd(unsigned char * buff, int len, int do_hex, int pdt)
return;
}
switch (pdt) {
- case PDT_DISK: case PDT_WO: case PDT_OPTICAL: /* Block limits */
+ case PDT_DISK: case PDT_WO: case PDT_OPTICAL: case PDT_ZBC:
if (len < 16) {
pr2serr("Block limits VPD page length too short=%d\n", len);
return;
@@ -2306,6 +2312,17 @@ decode_b0_vpd(unsigned char * buff, int len, int do_hex, int pdt)
printf(" Maximum write same length: 0x%" PRIx64 " blocks\n",
mwsl);
}
+ if (len > 44) { /* added in sbc4r02 */
+ u = ((unsigned int)buff[44] << 24) | (buff[45] << 16) |
+ (buff[46] << 8) | buff[47];
+ printf(" Maximum atomic transfer length: %u\n", u);
+ u = ((unsigned int)buff[48] << 24) | (buff[49] << 16) |
+ (buff[50] << 8) | buff[51];
+ printf(" Atomic alignment: %u\n", u);
+ u = ((unsigned int)buff[52] << 24) | (buff[53] << 16) |
+ (buff[54] << 8) | buff[55];
+ printf(" Atomic transfer length granularity: %u\n", u);
+ }
break;
case PDT_TAPE: case PDT_MCHANGER:
printf(" WORM=%d\n", !!(buff[4] & 0x1));
@@ -2343,7 +2360,7 @@ decode_b1_vpd(unsigned char * buff, int len, int do_hex, int pdt)
return;
}
switch (pdt) {
- case PDT_DISK: case PDT_WO: case PDT_OPTICAL:
+ case PDT_DISK: case PDT_WO: case PDT_OPTICAL: case PDT_ZBC:
if (len < 64) {
pr2serr("Block device characteristics VPD page length too "
"short=%d\n", len);
@@ -2453,6 +2470,104 @@ decode_block_lb_prov_vpd(unsigned char * b, int len)
return 0;
}
+/* VPD_SUP_BLOCK_LENS 0xb4 */
+static void
+decode_sup_block_lens_vpd(unsigned char * buff, int len)
+{
+ int k;
+ unsigned int u;
+ unsigned char * ucp;
+
+ if (len < 4) {
+ pr2serr("Supported block lengths and protection types VPD page "
+ "length too short=%d\n", len);
+ return;
+ }
+ len -= 4;
+ ucp = buff + 4;
+ for (k = 0; k < len; k += 8, ucp += 8) {
+ u = ((unsigned int)ucp[0] << 24) | (ucp[1] << 16) | (ucp[2] << 8) |
+ ucp[3];
+ printf(" Logical block length: %u\n", u);
+ printf(" P_I_I_SUP: %d\n", !!(ucp[4] & 0x40));
+ printf(" GRD_CHK: %d\n", !!(ucp[4] & 0x4));
+ printf(" APP_CHK: %d\n", !!(ucp[4] & 0x2));
+ printf(" REF_CHK: %d\n", !!(ucp[4] & 0x1));
+ printf(" T3PS_SUP: %d\n", !!(ucp[5] & 0x8));
+ printf(" T2PS_SUP: %d\n", !!(ucp[5] & 0x4));
+ printf(" T1PS_SUP: %d\n", !!(ucp[5] & 0x2));
+ printf(" T0PS_SUP: %d\n", !!(ucp[5] & 0x1));
+ }
+}
+
+/* VPD_BLOCK_DEV_C_EXTENS 0xb5 */
+static void
+decode_block_dev_char_ext_vpd(unsigned char * b, int len)
+{
+ unsigned int u;
+
+ if (len < 16) {
+ pr2serr("Block device characteristics extension VPD page "
+ "length too short=%d\n", len);
+ return;
+ }
+ printf(" Utilization type: ");
+ switch (b[5]) {
+ case 1:
+ printf("Combined writes and reads");
+ break;
+ case 2:
+ printf("Writes only");
+ break;
+ case 3:
+ printf("Separate writes and reads");
+ break;
+ default:
+ printf("Reserved");
+ break;
+ }
+ printf(" [0x%x]\n", b[5]);
+ printf(" Utilization units: ");
+ switch (b[6]) {
+ case 2:
+ printf("megabytes");
+ break;
+ case 3:
+ printf("gigabytes");
+ break;
+ case 4:
+ printf("terabytes");
+ break;
+ case 5:
+ printf("petabytes");
+ break;
+ case 6:
+ printf("exabytes");
+ break;
+ default:
+ printf("Reserved");
+ break;
+ }
+ printf(" [0x%x]\n", b[6]);
+ printf(" Utilization interval: ");
+ switch (b[7]) {
+ case 0xa:
+ printf("per day");
+ break;
+ case 0xe:
+ printf("per year");
+ break;
+ default:
+ printf("Reserved");
+ break;
+ }
+ printf(" [0x%x]\n", b[7]);
+ u = ((unsigned int)b[8] << 24) | (b[9] << 16) | (b[10] << 8) | b[11];
+ printf(" Utilization B: %u\n", u);
+ u = ((unsigned int)b[12] << 24) | (b[13] << 16) | (b[14] << 8) | b[15];
+ printf(" Utilization A: %u\n", u);
+}
+
/* VPD_TA_SUPPORTED */
static int
decode_tapealert_supported_vpd(unsigned char * b, int len)
@@ -2506,7 +2621,7 @@ 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:
+ case PDT_DISK: case PDT_WO: case PDT_OPTICAL: case PDT_ZBC:
decode_block_lb_prov_vpd(buff, len);
break;
case PDT_TAPE: case PDT_MCHANGER:
@@ -2532,7 +2647,7 @@ decode_b3_vpd(unsigned char * b, int len, int do_hex, int pdt)
return;
}
switch (pdt) {
- case PDT_DISK: case PDT_WO: case PDT_OPTICAL:
+ case PDT_DISK: case PDT_WO: case PDT_OPTICAL: case PDT_ZBC:
if (len < 16) {
pr2serr("Referrals VPD page length too short=%d\n", len);
break;
@@ -2558,6 +2673,53 @@ decode_b3_vpd(unsigned char * b, int len, int do_hex, int pdt)
}
}
+/* VPD_SUP_BLOCK_LENS sbc */
+/* VPD_DTDE_ADDRESS ssc */
+static void
+decode_b4_vpd(unsigned char * b, int len, int do_hex, int pdt)
+{
+ int k;
+
+ if (do_hex) {
+ dStrHex((const char *)b, len, (1 == do_hex) ? 0 : -1);
+ return;
+ }
+ switch (pdt) {
+ case PDT_DISK: case PDT_WO: case PDT_OPTICAL: case PDT_ZBC:
+ decode_sup_block_lens_vpd(b, len);
+ break;
+ case PDT_TAPE: case PDT_MCHANGER:
+ printf(" Data transfer device element address: 0x");
+ for (k = 4; k < len; ++k)
+ printf("%02x", (unsigned int)b[k]);
+ printf("\n");
+ break;
+ default:
+ pr2serr(" Unable to decode pdt=0x%x, in hex:\n", pdt);
+ dStrHexErr((const char *)b, len, 0);
+ break;
+ }
+}
+
+/* VPD_BLOCK_DEV_C_EXTENS sbc */
+static void
+decode_b5_vpd(unsigned char * b, int len, int do_hex, int pdt)
+{
+ if (do_hex) {
+ dStrHex((const char *)b, len, (1 == do_hex) ? 0 : -1);
+ return;
+ }
+ switch (pdt) {
+ case PDT_DISK: case PDT_WO: case PDT_OPTICAL: case PDT_ZBC:
+ decode_block_dev_char_ext_vpd(b, len);
+ break;
+ default:
+ pr2serr(" Unable to decode pdt=0x%x, in hex:\n", pdt);
+ dStrHexErr((const char *)b, len, 0);
+ break;
+ }
+}
+
/* Returns 0 if successful */
static int
svpd_unable_to_decode(int sg_fd, int num_vpd, int subvalue, int maxlen,
@@ -2951,7 +3113,7 @@ svpd_decode_t10(int sg_fd, int pn, int subvalue, int vp_num, int maxlen,
pdt = rp[0] & 0x1f;
if ((! do_raw) && (! do_quiet) && (do_hex < 3)) {
switch (pdt) {
- case PDT_DISK: case PDT_WO: case PDT_OPTICAL:
+ case PDT_DISK: case PDT_WO: case PDT_OPTICAL: case PDT_ZBC:
printf("Block limits VPD page (SBC):\n");
break;
case PDT_TAPE: case PDT_MCHANGER:
@@ -2962,7 +3124,7 @@ svpd_decode_t10(int sg_fd, int pn, int subvalue, int vp_num, int maxlen,
printf("OSD information VPD page (OSD):\n");
break;
default:
- printf("VPD page=0x%x, pdt=0x%x:\n", 0xb0, pdt);
+ printf("VPD page=0x%x, pdt=0x%x:\n", pn, pdt);
break;
}
}
@@ -2986,7 +3148,7 @@ svpd_decode_t10(int sg_fd, int pn, int subvalue, int vp_num, int maxlen,
pdt = rp[0] & 0x1f;
if ((! do_raw) && (! do_quiet) && (do_hex < 3)) {
switch (pdt) {
- case PDT_DISK: case PDT_WO: case PDT_OPTICAL:
+ case PDT_DISK: case PDT_WO: case PDT_OPTICAL: case PDT_ZBC:
printf("Block device characteristics VPD page (SBC):\n");
break;
case PDT_TAPE: case PDT_MCHANGER:
@@ -3001,7 +3163,7 @@ svpd_decode_t10(int sg_fd, int pn, int subvalue, int vp_num, int maxlen,
"(ADC):\n");
break;
default:
- printf("VPD page=0x%x, pdt=0x%x:\n", 0xb1, pdt);
+ printf("VPD page=0x%x, pdt=0x%x:\n", pn, pdt);
break;
}
}
@@ -3024,14 +3186,14 @@ svpd_decode_t10(int sg_fd, int pn, int subvalue, int vp_num, int maxlen,
pdt = rp[0] & 0x1f;
if ((! do_raw) && (! do_quiet) && (do_hex < 3)) {
switch (pdt) {
- case PDT_DISK: case PDT_WO: case PDT_OPTICAL:
+ case PDT_DISK: case PDT_WO: case PDT_OPTICAL: case PDT_ZBC:
printf("Logical block provisioning VPD page (SBC):\n");
break;
case PDT_TAPE: case PDT_MCHANGER:
printf("TapeAlert supported flags VPD page (SSC):\n");
break;
default:
- printf("VPD page=0x%x, pdt=0x%x:\n", 0xb2, pdt);
+ printf("VPD page=0x%x, pdt=0x%x:\n", pn, pdt);
break;
}
}
@@ -3054,7 +3216,7 @@ svpd_decode_t10(int sg_fd, int pn, int subvalue, int vp_num, int maxlen,
pdt = rp[0] & 0x1f;
if ((! do_raw) && (! do_quiet) && (do_hex < 3)) {
switch (pdt) {
- case PDT_DISK: case PDT_WO: case PDT_OPTICAL:
+ case PDT_DISK: case PDT_WO: case PDT_OPTICAL: case PDT_ZBC:
printf("Referrals VPD page (SBC):\n");
break;
case PDT_TAPE: case PDT_MCHANGER:
@@ -3062,7 +3224,7 @@ svpd_decode_t10(int sg_fd, int pn, int subvalue, int vp_num, int maxlen,
"(SSC):\n");
break;
default:
- printf("VPD page=0x%x, pdt=0x%x:\n", 0xb3, pdt);
+ printf("VPD page=0x%x, pdt=0x%x:\n", pn, pdt);
break;
}
}
@@ -3079,26 +3241,64 @@ svpd_decode_t10(int sg_fd, int pn, int subvalue, int vp_num, int maxlen,
} else if ((! do_raw) && (! do_quiet) && (do_hex < 3))
printf("VPD page=0xb3\n");
break;
- case VPD_DTDE_ADDRESS: /* 0xb4 */
- if ((! do_raw) && (! do_quiet) && (do_hex < 3))
- printf("Data transfer device element address (SSC):\n");
+ case 0xb4: /* VPD page depends on pdt */
+ res = vpd_fetch_page_from_dev(sg_fd, rp, pn, maxlen, vb, &len);
+ if (0 == res) {
+ pdt = rp[0] & 0x1f;
+ if ((! do_raw) && (! do_quiet) && (do_hex < 3)) {
+ switch (pdt) {
+ case PDT_DISK: case PDT_WO: case PDT_OPTICAL: case PDT_ZBC:
+ printf("Supported block lengths and protection types "
+ "VPD page (SBC):\n");
+ break;
+ case PDT_TAPE: case PDT_MCHANGER:
+ printf("Data transfer device element address (SSC):\n");
+ break;
+ default:
+ printf("VPD page=0x%x, pdt=0x%x:\n", pn, pdt);
+ break;
+ }
+ }
+ if (do_raw)
+ dStrRaw((const char *)rp, len);
+ else {
+ if (vb || do_long)
+ printf(" [PQual=%d Peripheral device type: %s]\n",
+ (rp[0] & 0xe0) >> 5,
+ sg_get_pdt_str(pdt, sizeof(b), b));
+ decode_b4_vpd(rp, len, do_hex, pdt);
+ }
+ return 0;
+ } else if ((! do_raw) && (! do_quiet) && (do_hex < 3))
+ printf("VPD page=0xb4\n");
+ break;
+ case 0xb5: /* VPD page depends on pdt */
res = vpd_fetch_page_from_dev(sg_fd, rp, pn, maxlen, vb, &len);
if (0 == res) {
+ pdt = rp[0] & 0x1f;
+ if ((! do_raw) && (! do_quiet) && (do_hex < 3)) {
+ switch (pdt) {
+ case PDT_DISK: case PDT_WO: case PDT_OPTICAL: case PDT_ZBC:
+ printf("Block device characteristics extension VPD page "
+ "(SBC):\n");
+ break;
+ default:
+ printf("VPD page=0x%x, pdt=0x%x:\n", pn, pdt);
+ break;
+ }
+ }
if (do_raw)
dStrRaw((const char *)rp, len);
else {
- pdt = rp[0] & 0x1f;
if (vb || do_long)
printf(" [PQual=%d Peripheral device type: %s]\n",
(rp[0] & 0xe0) >> 5,
sg_get_pdt_str(pdt, sizeof(b), b));
- printf(" Data transfer device element address: 0x");
- for (k = 4; k < len; ++k)
- printf("%02x", (unsigned int)rp[k]);
- printf("\n");
+ decode_b5_vpd(rp, len, do_hex, pdt);
}
return 0;
- }
+ } else if ((! do_raw) && (! do_quiet) && (do_hex < 3))
+ printf("VPD page=0xb5\n");
break;
default:
return SG_LIB_SYNTAX_ERROR;