aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDouglas Gilbert <dgilbert@interlog.com>2013-12-20 06:46:44 +0000
committerDouglas Gilbert <dgilbert@interlog.com>2013-12-20 06:46:44 +0000
commitd95fb62cfb049ca3c682da9b21d32157c46d4800 (patch)
treeff8b327d961c0b31b1b8f66e894fe74ac456f614
parente66f316105e49a4682d09b3d45c622b4d8b76b36 (diff)
downloadsg3_utils-d95fb62cfb049ca3c682da9b21d32157c46d4800.tar.gz
sg_vpd: decode Third Party Copy (tpc) page; sg_ses: add --maxlen= option
git-svn-id: https://svn.bingwo.ca/repos/sg3_utils/trunk@540 6180dd3e-e324-4e3e-922d-17de1ae2f315
-rw-r--r--ChangeLog4
-rw-r--r--lib/Makefile.am2
-rw-r--r--src/Makefile.am2
-rw-r--r--src/sg_inq.c9
-rw-r--r--src/sg_raw.c4
-rw-r--r--src/sg_ses.c68
-rw-r--r--src/sg_vpd.c274
7 files changed, 327 insertions, 36 deletions
diff --git a/ChangeLog b/ChangeLog
index 6f905020..4deff663 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -2,14 +2,16 @@ 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.38 [20131218] [svn: r539]
+Changelog for sg3_utils-1.38 [20131219] [svn: r540]
- sg_ses: add --dev-slot-num= and --sas-addr=
- error and warning message cleanup
+ - add --maxlen= option
- sg_inq: add --block=0|1 option to control opens
- add LU_CONG to standard inquiry response output
- sync version descriptors dated 20131126
- fix overflow in encode_whitespaces
- sg_vpd: add LU_CONG to standard inquiry response output
+ - decode Third Party Copy (tpc) page
- sg_xcopy: environment variables: XCOPY_TO_SRC and
XCOPY_TO_DST indicate where xcopy command is sent
- change default to send xcopy to dst (was src)
diff --git a/lib/Makefile.am b/lib/Makefile.am
index 9e232c6a..dde5883c 100644
--- a/lib/Makefile.am
+++ b/lib/Makefile.am
@@ -34,7 +34,7 @@ libsgutils2_la_SOURCES += sg_pt_osf1.c
endif
# For C++/clang testing
-## CC = g++ -std=c++11
+## CC = g++
## CC = g++
## CC = clang
## CC = clang++
diff --git a/src/Makefile.am b/src/Makefile.am
index f01761c6..b4f2eb7a 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -120,7 +120,7 @@ bin_PROGRAMS = \
endif
# For C++/clang testing
-## CC = g++ -std=c++11
+## CC = g++
## CC = g++
## CC = clang
## CC = clang++
diff --git a/src/sg_inq.c b/src/sg_inq.c
index 6320bf86..26bf3c3d 100644
--- a/src/sg_inq.c
+++ b/src/sg_inq.c
@@ -67,7 +67,7 @@
* information [MAINTENANCE IN, service action = 0xc]; see sg_opcodes.
*/
-static const char * version_str = "1.23 20131202"; /* SPC-4 rev 36n */
+static const char * version_str = "1.24 20131219"; /* SPC-4 rev 36n */
/* Following VPD pages are in ascending page number order */
@@ -296,8 +296,8 @@ usage()
"'--page=PG')\n\n"
"Performs a SCSI INQUIRY command. "
"If no options given then does a\n'standard' INQUIRY. Can list "
- "VPD pages with '--vpd' or '--page=PG'\noption. The sg_vpd "
- "utility has a more up to date list of VPD pages.\n");
+ "VPD pages with '--vpd' or '--page=PG'\noption. sg_vpd and "
+ "sdparm decode more VPD pages than this utility.\n");
}
#ifdef SG_SCSI_STRINGS
@@ -3316,7 +3316,8 @@ decode_vpd(int sg_fd, const struct opts_t * optsp)
}
break;
default:
- printf(" Only hex output supported. sg_vpd decodes more pages.\n");
+ printf(" Only hex output supported. sg_vpd and sdparm decode more "
+ "VPD pages.\n");
return vpd_mainly_hex(sg_fd, optsp);
}
if (res) {
diff --git a/src/sg_raw.c b/src/sg_raw.c
index ce6ed7f3..72dae6bb 100644
--- a/src/sg_raw.c
+++ b/src/sg_raw.c
@@ -12,6 +12,8 @@
* data phase) through a Generic SCSI interface.
*/
+#define _XOPEN_SOURCE 600 /* clear up posix_memalign() warning */
+
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
@@ -25,7 +27,7 @@
#include "sg_lib.h"
#include "sg_pt.h"
-#define SG_RAW_VERSION "0.4.7 (2013-11-24)"
+#define SG_RAW_VERSION "0.4.8 (2013-12-19)"
#ifdef SG_LIB_WIN32
#ifndef HAVE_SYSCONF
diff --git a/src/sg_ses.c b/src/sg_ses.c
index c2063e61..7b4afe65 100644
--- a/src/sg_ses.c
+++ b/src/sg_ses.c
@@ -28,7 +28,7 @@
* commands tailored for SES (enclosure) devices.
*/
-static const char * version_str = "1.81 20131125"; /* ses3r06 */
+static const char * version_str = "1.82 20131219"; /* ses3r06 */
#define MX_ALLOC_LEN ((64 * 1024) - 1) /* max allowable for big enclosures */
#define MX_ELEM_HDR 1024
@@ -111,6 +111,7 @@ struct opts_t {
int inner_hex;
int do_join;
int do_list;
+ int maxlen;
int seid;
int seid_given;
int page_code;
@@ -479,6 +480,7 @@ static struct option long_options[] = {
{"list", no_argument, 0, 'l'},
{"nickid", required_argument, 0, 'N'},
{"nickname", required_argument, 0, 'n'},
+ {"maxlen", required_argument, 0, 'm'},
{"page", required_argument, 0, 'p'},
{"raw", no_argument, 0, 'r'},
{"sas-addr", required_argument, 0, 'A'},
@@ -526,9 +528,9 @@ usage(int help_num)
" [--filter] [--get=STR] [--help] [--hex]\n"
" [--index=IIA | =TIA,II] [--inner-hex] "
"[--join] [--list]\n"
- " [--nickname=SEN] [--nickid=SEID] [--page=PG] "
- "[--raw]\n"
- " [--sas-addr=SA] [--set=STR] [--status] "
+ " [--maxlen=LEN] [--nickname=SEN] [--nickid=SEID] "
+ "[--page=PG]\n"
+ " [--raw] [--sas-addr=SA] [--set=STR] [--status] "
"[--verbose]\n"
" [--version] DEVICE\n"
" where the main options are:\n"
@@ -589,6 +591,8 @@ usage(int help_num)
" --inner-hex|-i print innermost level of a"
" status page in hex\n"
" --list|-l same as '--enumerate' option\n"
+ " --maxlen=LEN|-m LEN max response length (allocation "
+ "length in cdb)\n"
" --nickname=SEN|-n SEN SEN is new subenclosure nickname\n"
" --nickid=SEID|-N SEID SEID is subenclosure identifier "
"(def: 0)\n"
@@ -754,7 +758,7 @@ cl_process(struct opts_t *op, int argc, char *argv[])
while (1) {
int option_index = 0;
- c = getopt_long(argc, argv, "A:b:cC:d:D:efG:hHiI:jln:N:p:rsS:vVx:",
+ c = getopt_long(argc, argv, "A:b:cC:d:D:efG:hHiI:jln:N:m:p:rsS:vVx:",
long_options, &option_index);
if (c == -1)
break;
@@ -845,6 +849,14 @@ cl_process(struct opts_t *op, int argc, char *argv[])
}
++op->seid_given;
break;
+ case 'm':
+ op->maxlen = sg_get_num(optarg);
+ if ((op->maxlen < 0) || (op->maxlen > 65535)) {
+ pr2serr("bad argument to '--maxlen' (0 to 65535 "
+ "inclusive expected)\n");
+ return SG_LIB_SYNTAX_ERROR;
+ }
+ break;
case 'p':
if (isdigit(optarg[0])) {
op->page_code = sg_get_num(optarg);
@@ -913,6 +925,8 @@ cl_process(struct opts_t *op, int argc, char *argv[])
goto err_help;
}
}
+ if (op->maxlen <= 0)
+ op->maxlen = MX_ALLOC_LEN;
if (op->do_join && (op->do_control)) {
pr2serr("cannot have '--join' and '--control'\n");
goto err_help;
@@ -1401,15 +1415,14 @@ populate_type_desc_hdr_arr(int fd, struct type_desc_hdr_t * tdhp,
const unsigned char * ucp;
const unsigned char * last_ucp;
- resp = (unsigned char *)calloc(MX_ALLOC_LEN, 1);
+ resp = (unsigned char *)calloc(op->maxlen, 1);
if (NULL == resp) {
pr2serr("populate: unable to allocate %d bytes on heap\n",
- MX_ALLOC_LEN);
+ op->maxlen);
ret = -1;
goto the_end;
}
- res = do_rec_diag(fd, DPC_CONFIGURATION, resp, MX_ALLOC_LEN, op,
- &resp_len);
+ res = do_rec_diag(fd, DPC_CONFIGURATION, resp, op->maxlen, op, &resp_len);
if (res) {
pr2serr("populate: couldn't read config page, res=%d\n", res);
ret = -1;
@@ -2750,16 +2763,15 @@ ses_process_status_page(int sg_fd, struct opts_t * op)
const char * cp;
struct enclosure_info primary_info;
- resp = (unsigned char *)calloc(MX_ALLOC_LEN, 1);
+ resp = (unsigned char *)calloc(op->maxlen, 1);
if (NULL == resp) {
pr2serr("process_status_page: unable to allocate %d bytes on heap\n",
- MX_ALLOC_LEN);
+ op->maxlen);
ret = -1;
goto fini;
}
cp = find_in_diag_page_desc(op->page_code);
- ret = do_rec_diag(sg_fd, op->page_code, resp, MX_ALLOC_LEN,
- op, &resp_len);
+ ret = do_rec_diag(sg_fd, op->page_code, resp, op->maxlen, op, &resp_len);
if (ret)
goto fini;
if (op->do_raw) {
@@ -2956,7 +2968,7 @@ static int
join_work(int sg_fd, struct opts_t * op, int display)
{
int k, j, res, num_t_hdrs, elem_ind, ei, get_out, desc_len, dn_len;
- int et4aes, broken_ei, ei2, got1, jr_max_ind, eip, eiioe;
+ int et4aes, broken_ei, ei2, got1, jr_max_ind, eip, eiioe, mlen;
unsigned int ref_gen_code, gen_code;
struct join_row_t * jrp;
struct join_row_t * jr2p;
@@ -2987,8 +2999,11 @@ join_work(int sg_fd, struct opts_t * op, int display)
printf("%02x", primary_info.enc_log_id[j]);
printf("\n");
}
- res = do_rec_diag(sg_fd, DPC_ENC_STATUS, enc_stat_rsp,
- sizeof(enc_stat_rsp), op, &enc_stat_rsp_len);
+ mlen = sizeof(enc_stat_rsp);
+ if (mlen > op->maxlen)
+ mlen = op->maxlen;
+ res = do_rec_diag(sg_fd, DPC_ENC_STATUS, enc_stat_rsp, mlen, op,
+ &enc_stat_rsp_len);
if (res)
return res;
if (enc_stat_rsp_len < 8) {
@@ -3004,8 +3019,11 @@ join_work(int sg_fd, struct opts_t * op, int display)
es_ucp = enc_stat_rsp + 8;
/* es_last_ucp = enc_stat_rsp + enc_stat_rsp_len - 1; */
- res = do_rec_diag(sg_fd, DPC_ELEM_DESC, elem_desc_rsp,
- sizeof(elem_desc_rsp), op, &elem_desc_rsp_len);
+ mlen = sizeof(elem_desc_rsp);
+ if (mlen > op->maxlen)
+ mlen = op->maxlen;
+ res = do_rec_diag(sg_fd, DPC_ELEM_DESC, elem_desc_rsp, mlen, op,
+ &elem_desc_rsp_len);
if (0 == res) {
if (elem_desc_rsp_len < 8) {
pr2serr("Element Descriptor response too short\n");
@@ -3029,8 +3047,11 @@ join_work(int sg_fd, struct opts_t * op, int display)
if (display || (DPC_ADD_ELEM_STATUS == op->page_code) ||
(op->dev_slot_num >= 0) || saddr_non_zero(op->sas_addr)) {
- res = do_rec_diag(sg_fd, DPC_ADD_ELEM_STATUS, add_elem_rsp,
- sizeof(add_elem_rsp), op, &add_elem_rsp_len);
+ mlen = sizeof(add_elem_rsp);
+ if (mlen > op->maxlen)
+ mlen = op->maxlen;
+ res = do_rec_diag(sg_fd, DPC_ADD_ELEM_STATUS, add_elem_rsp, mlen, op,
+ &add_elem_rsp_len);
if (0 == res) {
if (add_elem_rsp_len < 8) {
pr2serr("Additional Element Status response too short\n");
@@ -3059,8 +3080,11 @@ join_work(int sg_fd, struct opts_t * op, int display)
if ((op->do_join > 1) ||
((0 == display) && (DPC_THRESHOLD == op->page_code))) {
- res = do_rec_diag(sg_fd, DPC_THRESHOLD, threshold_rsp,
- sizeof(threshold_rsp), op, &threshold_rsp_len);
+ mlen = sizeof(threshold_rsp);
+ if (mlen > op->maxlen)
+ mlen = op->maxlen;
+ res = do_rec_diag(sg_fd, DPC_THRESHOLD, threshold_rsp, mlen, op,
+ &threshold_rsp_len);
if (0 == res) {
if (threshold_rsp_len < 8) {
pr2serr("Threshold In response too short\n");
diff --git a/src/sg_vpd.c b/src/sg_vpd.c
index 168bcfff..a9a73136 100644
--- a/src/sg_vpd.c
+++ b/src/sg_vpd.c
@@ -30,7 +30,7 @@
*/
-static const char * version_str = "0.72 20131202"; /* spc4r36 + sbc3r35 */
+static const char * version_str = "0.73 20131219"; /* spc4r36 + sbc3r35 */
/* And with sbc3r35, vale Mark Evans */
void svpd_enumerate_vendor(void);
@@ -84,7 +84,6 @@ const struct svpd_values_name_t * svpd_find_vendor_by_acron(const char * ap);
#define VPD_DI_SEL_TARGET 4
#define VPD_DI_SEL_AS_IS 32
-
#define DEF_ALLOC_LEN 252
#define MX_ALLOC_LEN (0xc000 + 0x80)
#define VPD_ATA_INFO_LEN 572
@@ -1515,6 +1514,266 @@ decode_power_consumption_vpd(unsigned char * buff, int len, int do_hex)
}
}
+/* This is xcopy(LID4) related: "ROD" == Representation Of Data
+ * Used by VPD_3PARTY_COPY */
+static void
+decode_rod_descriptor(const unsigned char * buff, int len)
+{
+ const unsigned char * ucp = buff;
+ int k, bump, j;
+ uint64_t ull;
+
+ for (k = 0; k < len; k += bump, ucp += bump) {
+ bump = (ucp[2] << 8) + ucp[3];
+ switch (ucp[0]) {
+ case 0:
+ /* Block ROD device type specific descriptor */
+ printf(" Optimal block ROD length granularity: %d\n",
+ (ucp[6] << 8) + ucp[7]);
+ ull = 0;
+ for (j = 0; j < 8; j++) {
+ if (j > 0)
+ ull <<= 8;
+ ull |= ucp[8 + j];
+ }
+ printf(" Maximum Bytes in block ROD: %" PRIu64 "\n", ull);
+ ull = 0;
+ for (j = 0; j < 8; j++) {
+ if (j > 0)
+ ull <<= 8;
+ ull |= ucp[16 + j];
+ }
+ printf(" Optimal Bytes in block ROD transfer: %" PRIu64 "\n",
+ ull);
+ ull = 0;
+ for (j = 0; j < 8; j++) {
+ if (j > 0)
+ ull <<= 8;
+ ull |= ucp[24 + j];
+ }
+ printf(" Optimal Bytes to token per segment: %" PRIu64 "\n",
+ ull);
+ ull = 0;
+ for (j = 0; j < 8; j++) {
+ if (j > 0)
+ ull <<= 8;
+ ull |= ucp[32 + j];
+ }
+ printf(" Optimal Bytes from token per segment:"
+ " %" PRIu64 "\n", ull);
+ break;
+ case 1:
+ /* Stream ROD device type specific descriptor */
+ ull = 0;
+ for (j = 0; j < 8; j++) {
+ if (j > 0)
+ ull <<= 8;
+ ull |= ucp[8 + j];
+ }
+ printf(" Maximum Bytes in stream ROD: %" PRIu64 "\n", ull);
+ ull = 0;
+ for (j = 0; j < 8; j++) {
+ if (j > 0)
+ ull <<= 8;
+ ull |= ucp[16 + j];
+ }
+ printf(" Optimal Bytes in stream ROD transfer:"
+ " %" PRIu64 "\n", ull);
+ break;
+ case 3:
+ /* Copy manager ROD device type specific descriptor */
+ ull = 0;
+ for (j = 0; j < 8; j++) {
+ if (j > 0)
+ ull <<= 8;
+ ull |= ucp[8 + j];
+ }
+ printf(" Maximum Bytes in processor ROD:"
+ " %" PRIu64 "\n", ull);
+ ull = 0;
+ for (j = 0; j < 8; j++) {
+ if (j > 0)
+ ull <<= 8;
+ ull |= ucp[16 + j];
+ }
+ printf(" Optimal Bytes in processor ROD transfer:"
+ " %" PRIu64 "\n", ull);
+ break;
+ default:
+ printf(" Unhandled descriptor (format %d, device type %d)\n",
+ ucp[0] >> 5, ucp[0] & 0x1F);
+ break;
+ }
+ }
+}
+
+/* VPD_3PARTY_COPY */
+static void
+decode_3party_copy_vpd(unsigned char * buff, int len, int do_hex)
+{
+ int j, k, bump, desc_type, desc_len, u, c, sa_len;
+ const unsigned char * ucp;
+ uint64_t ull;
+
+ if (len < 4) {
+ fprintf(stderr, "Third-party Copy VPD page length too short=%d\n",
+ len);
+ return;
+ }
+ len -= 4;
+ ucp = buff + 4;
+ for (k = 0; k < len; k += bump, ucp += bump) {
+ desc_type = (ucp[0] << 8) + ucp[1];
+ desc_len = (ucp[2] << 8) + ucp[3];
+ printf("Descriptor type=%d, len %d\n", desc_type, desc_len);
+ bump = 4 + desc_len;
+ if ((k + bump) > len) {
+ fprintf(stderr, "Third-party Copy VPD "
+ "page, short descriptor length=%d, left=%d\n", bump,
+ (len - k));
+ return;
+ }
+ if (0 == desc_len)
+ continue;
+ if (2 == do_hex)
+ dStrHex((const char *)ucp + 4, desc_len, 1);
+ else if (do_hex > 2)
+ dStrHex((const char *)ucp, bump, 1);
+ else {
+ switch (desc_type) {
+ case 0x0000: /* Block Device ROD Limits */
+ printf(" Block Device ROD Limits:\n");
+ printf(" Maximum Range Descriptors: %d\n",
+ (ucp[10] << 8) + ucp[11]);
+ u = (ucp[12] << 24) | (ucp[13] << 16) | (ucp[14] << 8) |
+ ucp[15];
+ printf(" Maximum Inactivity Timeout: %d\n", u);
+ u = (ucp[16] << 24) | (ucp[17] << 16) | (ucp[18] << 8) |
+ ucp[19];
+ printf(" Default Inactivity Timeout: %d\n", u);
+ ull = 0;
+ for (j = 0; j < 8; j++) {
+ if (j > 0)
+ ull <<= 8;
+ ull |= ucp[20 + j];
+ }
+ printf(" Maximum Token Transfer Size: %" PRIu64 "\n", ull);
+ ull = 0;
+ for (j = 0; j < 8; j++) {
+ if (j > 0)
+ ull <<= 8;
+ ull |= ucp[28 + j];
+ }
+ printf(" Optimal Transfer Count: %" PRIu64 "\n", ull);
+ break;
+ case 0x0001: /* Supported Commands */
+ printf(" Supported Commands:\n");
+ j = 0;
+ while (j < ucp[4]) {
+ c = ucp[5 + j];
+ printf(" 0x%02x\n", c);
+ sa_len = ucp[6 + j];
+ for (k = 0; k < sa_len; k++) {
+ printf(" SA 0x%02x\n", ucp[7 + j + k]);
+ }
+ j += sa_len;
+ }
+ break;
+ case 0x0004: /* Parameter Data */
+ printf(" Parameter Data:\n");
+ printf(" Maximum CSCD Descriptor Count: %d\n",
+ (ucp[8] << 8) + ucp[9]);
+ printf(" Maximum Segment Descriptor Count: %d\n",
+ (ucp[10] << 8) + ucp[11]);
+ u = (ucp[12] << 24) | (ucp[13] << 16) | (ucp[14] << 8) |
+ ucp[15];
+ printf(" Maximum Descriptor List Length: %d\n", u);
+ u = (ucp[16] << 24) | (ucp[17] << 16) | (ucp[18] << 8) |
+ ucp[19];
+ printf(" Maximum Inline Data Length: %d\n", u);
+ break;
+ case 0x0008: /* Supported Descriptors */
+ printf(" Supported Descriptors:\n");
+ for (j = 0; j < ucp[4]; j++) {
+ printf(" 0x%x\n", ucp[5 + j]);
+ }
+ break;
+ case 0x000C: /* Supported CSCD IDs */
+ printf(" Supported CSCD IDs:\n");
+ for (j = 0; j < (ucp[4] << 8) + ucp[5]; j += 2) {
+ u = (ucp[6 + j] << 8) | ucp[7 + j];
+ printf(" 0x%04x\n", u);
+ }
+ break;
+ case 0x0106: /* ROD Token Features */
+ printf(" ROD Token Features:\n");
+ printf(" Remote Tokens: %d\n", ucp[4] & 0x0f);
+ u = (ucp[16] << 24) | (ucp[17] << 16) | (ucp[18] << 8) |
+ ucp[19];
+ printf(" Minimum Token Lifetime: %d\n", u);
+ u = (ucp[20] << 24) | (ucp[21] << 16) | (ucp[22] << 8) |
+ ucp[23];
+ printf(" Maximum Token Lifetime: %d\n", u);
+ u = (ucp[24] << 24) | (ucp[25] << 16) | (ucp[26] << 8) |
+ ucp[27];
+ printf(" Maximum Token inactivity timeout: %d\n", u);
+ decode_rod_descriptor(&ucp[48], (ucp[46] << 8) + ucp[47]);
+ break;
+ case 0x0108: /* Supported ROD Token and ROD Types */
+ printf(" Supported ROD Token and ROD Types:\n");
+ for (j = 0; j < (ucp[6] << 8) + ucp[7]; j+= 64) {
+ u = (ucp[8 + j] << 24) | (ucp[8 + j + 1] << 16) |
+ (ucp[8 + j + 2] << 8) | ucp[8 + j + 3];
+ printf(" ROD Type %d:\n", u);
+ printf(" Internal: %s\n",
+ ucp[8 + j + 4] & 0x80 ? "yes" : "no");
+ printf(" Token In: %s\n",
+ ucp[8 + j + 4] & 0x02 ? "yes" : "no");
+ printf(" Token Out: %s\n",
+ ucp[8 + j + 4] & 0x01 ? "yes" : "no");
+ printf(" Preference: %d\n",
+ (ucp[8 + j + 6] << 8) + ucp[8 + j + 7]);
+ }
+ break;
+ case 0x8001: /* General Copy Operations */
+ printf(" General Copy Operations:\n");
+ u = (ucp[4] << 24) | (ucp[5] << 16) | (ucp[6] << 8) |
+ ucp[7];
+ printf(" Total Concurrent Copies: %d\n", u);
+ u = (ucp[8] << 24) | (ucp[9] << 16) | (ucp[10] << 8) |
+ ucp[11];
+ printf(" Maximum Identified Concurrent Copies: %d\n", u);
+ u = (ucp[12] << 24) | (ucp[13] << 16) | (ucp[14] << 8) |
+ ucp[15];
+ printf(" Maximum Segment Length: %d\n", u);
+ ull = (1 << ucp[16]);
+ printf(" Data Segment Granularity: %" PRIu64 "\n", ull);
+ ull = (1 << ucp[17]);
+ printf(" Inline Data Granularity: %" PRIu64 "\n", ull);
+ break;
+ case 0x9101: /* Stream Copy Operations */
+ printf(" Stream Copy Operations:\n");
+ u = (ucp[4] << 24) | (ucp[5] << 16) | (ucp[6] << 8) |
+ ucp[7];
+ printf(" Maximum Stream Device Transfer Size: %d\n", u);
+ break;
+ case 0xC001: /* Held Data */
+ printf(" Held Data:\n");
+ u = (ucp[4] << 24) | (ucp[5] << 16) | (ucp[6] << 8) |
+ ucp[7];
+ printf(" Held Data Limit: %d\n", u);
+ ull = (1 << ucp[8]);
+ printf(" Held Data Granularity: %" PRIu64 "\n", ull);
+ break;
+ default:
+ fprintf(stderr, "Unexpected type=%d\n", desc_type);
+ dStrHexErr((const char *)ucp, bump, 1);
+ break;
+ }
+ }
+ }
+}
+
/* VPD_PROTO_LU */
static void
decode_proto_lu_vpd(unsigned char * buff, int len, int do_hex)
@@ -2596,12 +2855,15 @@ svpd_decode_t10(int sg_fd, int num_vpd, int subvalue, int maxlen, int do_hex,
}
if (do_raw)
dStrRaw((const char *)rsp_buff, len);
- else if (do_hex)
+ else if (1 == do_hex)
dStrHex((const char *)rsp_buff, len, 0);
else {
- printf(" Leave decoding of this page until it is wanted, "
- "in hex:\n");
- dStrHex((const char *)rsp_buff, len, 0);
+ pdt = rsp_buff[0] & 0x1f;
+ if (verbose || do_long)
+ printf(" [PQual=%d Peripheral device type: %s]\n",
+ (rsp_buff[0] & 0xe0) >> 5,
+ sg_get_pdt_str(pdt, sizeof(buff), buff));
+ decode_3party_copy_vpd(rsp_buff, len, do_hex);
}
return 0;
}