diff options
author | Douglas Gilbert <dgilbert@interlog.com> | 2009-09-18 23:35:06 +0000 |
---|---|---|
committer | Douglas Gilbert <dgilbert@interlog.com> | 2009-09-18 23:35:06 +0000 |
commit | 9e11e00479a4cd919028ecf226856e4c78c87354 (patch) | |
tree | 1de3dcb14a5496785d01a09c175a512a71e63339 /src | |
parent | 302a707e5073b1419bfe0097a1b76e1f70336ce9 (diff) | |
download | sg3_utils-9e11e00479a4cd919028ecf226856e4c78c87354.tar.gz |
start work on thin provisioning sbc3r20 additions
git-svn-id: https://svn.bingwo.ca/repos/sg3_utils/trunk@300 6180dd3e-e324-4e3e-922d-17de1ae2f315
Diffstat (limited to 'src')
-rw-r--r-- | src/sg_inq.c | 25 | ||||
-rw-r--r-- | src/sg_logs.c | 17 | ||||
-rw-r--r-- | src/sg_rbuf.c | 3 | ||||
-rw-r--r-- | src/sg_vpd.c | 654 |
4 files changed, 438 insertions, 261 deletions
diff --git a/src/sg_inq.c b/src/sg_inq.c index 749539a1..12e7dd14 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.85 20090826"; /* SPC-4 rev 21 */ +static char * version_str = "0.86 20090916"; /* SPC-4 rev 21 */ #define VPD_SUPPORTED_VPDS 0x0 @@ -81,9 +81,10 @@ static char * version_str = "0.85 20090826"; /* SPC-4 rev 21 */ #define VPD_POWER_CONDITION 0x8a #define VPD_PROTO_LU 0x90 #define VPD_PROTO_PORT 0x91 -#define VPD_BLOCK_LIMITS 0xb0 -#define VPD_BLOCK_DEV_CHARS 0xb1 -#define VPD_UPR_EMC 0xc0 +#define VPD_BLOCK_LIMITS 0xb0 +#define VPD_BLOCK_DEV_CHARS 0xb1 +#define VPD_THIN_PROVISIONING 0xb2 +#define VPD_UPR_EMC 0xc0 #define VPD_RDAC_VERS 0xc2 #define VPD_RDAC_VAC 0xc9 @@ -155,6 +156,7 @@ static struct svpd_values_name_t vpd_pg[] = { {VPD_SUPPORTED_VPDS, 0, -1, 0, "sv", "Supported VPD pages"}, {VPD_RDAC_VAC, 0, -1, 1, "rdac_vac", "RDAC volume access control (IBM)"}, {VPD_RDAC_VERS, 0, -1, 1, "rdac_vers", "RDAC software version (IBM)"}, + {VPD_THIN_PROVISIONING, 0, 0, 0, "thp", "Thin provisioning (SBC)"}, {VPD_UPR_EMC, 0, -1, 1, "upr", "Unit path report (EMC)"}, {0, 0, 0, 0, NULL, NULL}, }; @@ -649,6 +651,7 @@ static struct vpd_name vpd_name_arr[] = { {VPD_POWER_CONDITION, 0, "Power condition"}, {VPD_BLOCK_LIMITS, 0, "Block limits (sbc2)"}, {VPD_BLOCK_DEV_CHARS, 0, "Block device characteristics (sbc3)"}, + {VPD_THIN_PROVISIONING, 0, "Thin provisioning (sbc3)"}, {0xb0, PDT_TAPE, "Sequential access device capabilities (ssc3)"}, {0xb2, PDT_TAPE, "TapeAlert supported flags (ssc3)"}, {0xb0, PDT_OSD, "OSD information (osd)"}, @@ -869,7 +872,7 @@ static const char * code_set_arr[] = "Reserved [0xc]", "Reserved [0xd]", "Reserved [0xe]", "Reserved [0xf]", }; -static const char * id_type_arr[] = +static const char * desig_type_arr[] = { "vendor specific [0x0]", "T10 vendor identification", @@ -888,7 +891,7 @@ static const char * id_type_arr[] = static void decode_dev_ids(const char * leadin, unsigned char * buff, int len, int do_hex) { - int u, j, m, id_len, p_id, c_set, piv, assoc, id_type, i_len; + int u, j, m, id_len, p_id, c_set, piv, assoc, desig_type, i_len; int off, ci_off, c_id, d_id, naa, vsi, k; uint64_t vsei; uint64_t id_ext; @@ -915,12 +918,12 @@ decode_dev_ids(const char * leadin, unsigned char * buff, int len, int do_hex) c_set = (ucp[0] & 0xf); piv = ((ucp[1] & 0x80) ? 1 : 0); assoc = ((ucp[1] >> 4) & 0x3); - id_type = (ucp[1] & 0xf); + desig_type = (ucp[1] & 0xf); if (piv && ((1 == assoc) || (2 == assoc))) printf(" transport: %s\n", sg_get_trans_proto_str(p_id, sizeof(b), b)); - printf(" id_type: %s, code_set: %s\n", id_type_arr[id_type], - code_set_arr[c_set]); + printf(" designator_type: %s, code_set: %s\n", + desig_type_arr[desig_type], code_set_arr[c_set]); printf(" associated with the %s\n", assoc_arr[assoc]); if (do_hex) { printf(" designator header(hex): %.2x %.2x %.2x %.2x\n", @@ -929,7 +932,7 @@ decode_dev_ids(const char * leadin, unsigned char * buff, int len, int do_hex) dStrHex((const char *)ip, i_len, 0); continue; } - switch (id_type) { + switch (desig_type) { case 0: /* vendor specific */ k = 0; if ((1 == c_set) || (2 == c_set)) { /* ASCII or UTF-8 */ @@ -2532,7 +2535,7 @@ decode_vpd(int sg_fd, const struct opts_t * optsp) } break; default: - printf(" Only hex output supported\n"); + printf(" Only hex output supported. sg_vpd decodes more pages.\n"); return process_vpd(sg_fd, optsp); } if (res) { diff --git a/src/sg_logs.c b/src/sg_logs.c index 5e6526e4..f6dabf3f 100644 --- a/src/sg_logs.c +++ b/src/sg_logs.c @@ -25,7 +25,7 @@ */ -static char * version_str = "0.89 20090827"; /* SPC-4 revision 21 */ +static char * version_str = "0.91 20090918"; /* SPC-4 revision 21 */ #define MX_ALLOC_LEN (0xfffc) #define SHORT_RESP_LEN 128 @@ -39,6 +39,7 @@ static char * version_str = "0.89 20090827"; /* SPC-4 revision 21 */ #define NON_MEDIUM_LPAGE 0x6 #define LAST_N_ERR_LPAGE 0x7 #define LAST_N_DEFERRED_LPAGE 0xb +#define THIN_PROV_LPAGE 0xc #define TEMPERATURE_LPAGE 0xd #define START_STOP_LPAGE 0xe #define APP_CLIENT_LPAGE 0xf @@ -706,7 +707,7 @@ show_page_name(int pg_code, int subpg_code, case 0x8: printf("%sFormat status (sbc-2)\n", b); break; - case 0xc: + case THIN_PROV_LPAGE: /* 0xc */ printf("%sThin provisioning (sbc-3)\n", b); break; case 0x15: @@ -2455,7 +2456,17 @@ show_background_scan_results_page(unsigned char * resp, int len, int show_pcb, "%d\n", j); break; default: - printf(" Medium scan parameter # %d\n", pc); + if (pc > 0x800) { + if ((pc >= 0x8000) && (pc <= 0xafff)) + printf(" Medium scan parameter # %d [0x%x], vendor " + "specific\n", pc, pc); + else + printf(" Medium scan parameter # %d [0x%x], " + "reserved\n", pc, pc); + dStrHex((const char *)ucp, ((pl < num) ? pl : num), 0); + break; + } else + printf(" Medium scan parameter # %d [0x%x]\n", pc, pc); if ((pl < 24) || (num < 24)) { if (num < 24) fprintf(stderr, " truncated by response length, " diff --git a/src/sg_rbuf.c b/src/sg_rbuf.c index 2148d911..9f3e9f39 100644 --- a/src/sg_rbuf.c +++ b/src/sg_rbuf.c @@ -4,7 +4,6 @@ #endif #include <unistd.h> -#include <signal.h> #include <fcntl.h> #include <stdio.h> #include <stdlib.h> @@ -52,7 +51,7 @@ #endif -static char * version_str = "4.88 20071226"; +static char * version_str = "4.88 20090908"; static struct option long_options[] = { {"buffer", 1, 0, 'b'}, diff --git a/src/sg_vpd.c b/src/sg_vpd.c index fb67a2a3..0794cbfa 100644 --- a/src/sg_vpd.c +++ b/src/sg_vpd.c @@ -52,7 +52,7 @@ */ -static char * version_str = "0.35 20090827"; /* spc4r21 + sbc3r19 */ +static char * version_str = "0.36 20090916"; /* spc4r21 + sbc3r20 */ extern void svpd_enumerate_vendor(void); extern int svpd_decode_vendor(int sg_fd, int num_vpd, int subvalue, @@ -667,285 +667,298 @@ decode_dev_ids_quiet(unsigned char * buff, int len, int m_assoc, return 0; } -/* Prints outs device identification designators selected by association, - designator type and/or code set. */ -static int -decode_dev_ids(const char * print_if_found, unsigned char * buff, int len, - int m_assoc, int m_desig_type, int m_code_set, int long_out, - int quiet) +static void +decode_designation_descriptor(const unsigned char * ucp, int i_len, + int long_out, int print_assoc) { - int m, p_id, c_set, piv, assoc, desig_type, i_len; - int ci_off, c_id, d_id, naa, vsi, printed, off, u, k; + int m, p_id, piv, c_set, assoc, desig_type, ci_off, c_id, d_id, naa; + int vsi, k; + const unsigned char * ip; uint64_t vsei; uint64_t id_ext; - const unsigned char * ucp; - const unsigned char * ip; char b[64]; - if (quiet) - return decode_dev_ids_quiet(buff, len, m_assoc, m_desig_type, - m_code_set); - off = -1; - printed = 0; - while ((u = sg_vpd_dev_id_iter(buff, len, &off, m_assoc, m_desig_type, - m_code_set)) == 0) { - ucp = buff + off; - i_len = ucp[3]; - if ((off + i_len + 4) > len) { - fprintf(stderr, " VPD page error: designator length longer " - "than\n remaining response length=%d\n", (len - off)); - return SG_LIB_CAT_MALFORMED; + ip = ucp + 4; + p_id = ((ucp[0] >> 4) & 0xf); + c_set = (ucp[0] & 0xf); + piv = ((ucp[1] & 0x80) ? 1 : 0); + assoc = ((ucp[1] >> 4) & 0x3); + desig_type = (ucp[1] & 0xf); + if (print_assoc) + printf(" %s:\n", assoc_arr[assoc]); + printf(" designator type: %s, code set: %s\n", + desig_type_arr[desig_type], code_set_arr[c_set]); + if (piv && ((1 == assoc) || (2 == assoc))) + printf(" transport: %s\n", + sg_get_trans_proto_str(p_id, sizeof(b), b)); + /* printf(" associated with the %s\n", assoc_arr[assoc]); */ + switch (desig_type) { + case 0: /* vendor specific */ + k = 0; + if ((1 == c_set) || (2 == c_set)) { /* ASCII or UTF-8 */ + for (k = 0; (k < i_len) && isprint(ip[k]); ++k) + ; + if (k >= i_len) + k = 1; } - ip = ucp + 4; - p_id = ((ucp[0] >> 4) & 0xf); - c_set = (ucp[0] & 0xf); - piv = ((ucp[1] & 0x80) ? 1 : 0); - assoc = ((ucp[1] >> 4) & 0x3); - desig_type = (ucp[1] & 0xf); - if (print_if_found && (0 == printed)) { - printed = 1; - printf(" %s:\n", print_if_found); - } - if (NULL == print_if_found) - printf(" %s:\n", assoc_arr[assoc]); - printf(" designator type: %s, code_set: %s\n", - desig_type_arr[desig_type], code_set_arr[c_set]); - if (piv && ((1 == assoc) || (2 == assoc))) - printf(" transport: %s\n", - sg_get_trans_proto_str(p_id, sizeof(b), b)); - /* printf(" associated with the %s\n", assoc_arr[assoc]); */ - switch (desig_type) { - case 0: /* vendor specific */ - k = 0; - if ((1 == c_set) || (2 == c_set)) { /* ASCII or UTF-8 */ - for (k = 0; (k < i_len) && isprint(ip[k]); ++k) - ; - if (k >= i_len) - k = 1; - } - if (k) - printf(" vendor specific: %.*s\n", i_len, ip); - else - dStrHex((const char *)ip, i_len, 0); - break; - case 1: /* T10 vendor identification */ - printf(" vendor id: %.8s\n", ip); - if (i_len > 8) - printf(" vendor specific: %.*s\n", i_len - 8, ip + 8); - break; - case 2: /* EUI-64 based */ - if (! long_out) { - if ((8 != i_len) && (12 != i_len) && (16 != i_len)) { - fprintf(stderr, " << expect 8, 12 and 16 byte " - "ids, got %d>>\n", i_len); - dStrHex((const char *)ip, i_len, 0); - break; - } - printf(" 0x"); - for (m = 0; m < i_len; ++m) - printf("%02x", (unsigned int)ip[m]); - printf("\n"); - break; - } - printf(" EUI-64 based %d byte identifier\n", i_len); - if (1 != c_set) { - fprintf(stderr, " << expected binary code_set (1)>>\n"); - dStrHex((const char *)ip, i_len, 0); - break; - } - ci_off = 0; - if (16 == i_len) { - ci_off = 8; - id_ext = 0; - for (m = 0; m < 8; ++m) { - if (m > 0) - id_ext <<= 8; - id_ext |= ip[m]; - } - printf(" Identifier extension: 0x%" PRIx64 "\n", id_ext); - } else if ((8 != i_len) && (12 != i_len)) { - fprintf(stderr, " << can only decode 8, 12 and 16 " - "byte ids>>\n"); + if (k) + printf(" vendor specific: %.*s\n", i_len, ip); + else + dStrHex((const char *)ip, i_len, 0); + break; + case 1: /* T10 vendor identification */ + printf(" vendor id: %.8s\n", ip); + if (i_len > 8) + printf(" vendor specific: %.*s\n", i_len - 8, ip + 8); + break; + case 2: /* EUI-64 based */ + if (! long_out) { + if ((8 != i_len) && (12 != i_len) && (16 != i_len)) { + fprintf(stderr, " << expect 8, 12 and 16 byte " + "EUI, got %d>>\n", i_len); dStrHex((const char *)ip, i_len, 0); break; } - c_id = ((ip[ci_off] << 16) | (ip[ci_off + 1] << 8) | - ip[ci_off + 2]); - printf(" IEEE Company_id: 0x%x\n", c_id); - vsei = 0; - for (m = 0; m < 5; ++m) { + printf(" 0x"); + for (m = 0; m < i_len; ++m) + printf("%02x", (unsigned int)ip[m]); + printf("\n"); + break; + } + printf(" EUI-64 based %d byte identifier\n", i_len); + if (1 != c_set) { + fprintf(stderr, " << expected binary code_set (1)>>\n"); + dStrHex((const char *)ip, i_len, 0); + break; + } + ci_off = 0; + if (16 == i_len) { + ci_off = 8; + id_ext = 0; + for (m = 0; m < 8; ++m) { if (m > 0) - vsei <<= 8; - vsei |= ip[ci_off + 3 + m]; - } - printf(" Vendor Specific Extension Identifier: 0x%" PRIx64 - "\n", vsei); - if (12 == i_len) { - d_id = ((ip[8] << 24) | (ip[9] << 16) | (ip[10] << 8) | - ip[11]); - printf(" Directory ID: 0x%x\n", d_id); + id_ext <<= 8; + id_ext |= ip[m]; } + printf(" Identifier extension: 0x%" PRIx64 "\n", id_ext); + } else if ((8 != i_len) && (12 != i_len)) { + fprintf(stderr, " << can only decode 8, 12 and 16 " + "byte ids>>\n"); + dStrHex((const char *)ip, i_len, 0); break; - case 3: /* NAA */ - if (1 != c_set) { - fprintf(stderr, " << unexpected code set %d for " - "NAA>>\n", c_set); + } + c_id = ((ip[ci_off] << 16) | (ip[ci_off + 1] << 8) | + ip[ci_off + 2]); + printf(" IEEE Company_id: 0x%x\n", c_id); + vsei = 0; + for (m = 0; m < 5; ++m) { + if (m > 0) + vsei <<= 8; + vsei |= ip[ci_off + 3 + m]; + } + printf(" Vendor Specific Extension Identifier: 0x%" PRIx64 + "\n", vsei); + if (12 == i_len) { + d_id = (((unsigned int)ip[8] << 24) | (ip[9] << 16) | + (ip[10] << 8) | ip[11]); + printf(" Directory ID: 0x%x\n", d_id); + } + break; + case 3: /* NAA */ + if (1 != c_set) { + fprintf(stderr, " << unexpected code set %d for " + "NAA>>\n", c_set); + dStrHex((const char *)ip, i_len, 0); + break; + } + naa = (ip[0] >> 4) & 0xff; + if (! ((2 == naa) || (5 == naa) || (6 == naa))) { + fprintf(stderr, " << unexpected NAA [0x%x]>>\n", naa); + dStrHex((const char *)ip, i_len, 0); + break; + } + if (2 == naa) { + if (8 != i_len) { + fprintf(stderr, " << unexpected NAA 2 identifier " + "length: 0x%x>>\n", i_len); dStrHex((const char *)ip, i_len, 0); break; } - naa = (ip[0] >> 4) & 0xff; - if (! ((2 == naa) || (5 == naa) || (6 == naa))) { - fprintf(stderr, " << unexpected NAA [0x%x]>>\n", naa); + d_id = (((ip[0] & 0xf) << 8) | ip[1]); + c_id = ((ip[2] << 16) | (ip[3] << 8) | ip[4]); + vsi = ((ip[5] << 16) | (ip[6] << 8) | ip[7]); + if (long_out) { + printf(" NAA 2, vendor specific identifier A: " + "0x%x\n", d_id); + printf(" IEEE Company_id: 0x%x\n", c_id); + printf(" vendor specific identifier B: 0x%x\n", vsi); + printf(" [0x"); + for (m = 0; m < 8; ++m) + printf("%02x", (unsigned int)ip[m]); + printf("]\n"); + } + printf(" 0x"); + for (m = 0; m < 8; ++m) + printf("%02x", (unsigned int)ip[m]); + printf("\n"); + } else if (5 == naa) { + if (8 != i_len) { + fprintf(stderr, " << unexpected NAA 5 identifier " + "length: 0x%x>>\n", i_len); dStrHex((const char *)ip, i_len, 0); break; } - if (2 == naa) { - if (8 != i_len) { - fprintf(stderr, " << unexpected NAA 2 identifier " - "length: 0x%x>>\n", i_len); - dStrHex((const char *)ip, i_len, 0); - break; - } - d_id = (((ip[0] & 0xf) << 8) | ip[1]); - c_id = ((ip[2] << 16) | (ip[3] << 8) | ip[4]); - vsi = ((ip[5] << 16) | (ip[6] << 8) | ip[7]); - if (long_out) { - printf(" NAA 2, vendor specific identifier A: " - "0x%x\n", d_id); - printf(" IEEE Company_id: 0x%x\n", c_id); - printf(" vendor specific identifier B: 0x%x\n", vsi); - printf(" [0x"); - for (m = 0; m < 8; ++m) - printf("%02x", (unsigned int)ip[m]); - printf("]\n"); - } + c_id = (((ip[0] & 0xf) << 20) | (ip[1] << 12) | + (ip[2] << 4) | ((ip[3] & 0xf0) >> 4)); + vsei = ip[3] & 0xf; + for (m = 1; m < 5; ++m) { + vsei <<= 8; + vsei |= ip[3 + m]; + } + if (long_out) { + printf(" NAA 5, IEEE Company_id: 0x%x\n", c_id); + printf(" Vendor Specific Identifier: 0x%" PRIx64 + "\n", vsei); + printf(" [0x"); + for (m = 0; m < 8; ++m) + printf("%02x", (unsigned int)ip[m]); + printf("]\n"); + } else { printf(" 0x"); for (m = 0; m < 8; ++m) printf("%02x", (unsigned int)ip[m]); printf("\n"); - } else if (5 == naa) { - if (8 != i_len) { - fprintf(stderr, " << unexpected NAA 5 identifier " - "length: 0x%x>>\n", i_len); - dStrHex((const char *)ip, i_len, 0); - break; - } - c_id = (((ip[0] & 0xf) << 20) | (ip[1] << 12) | - (ip[2] << 4) | ((ip[3] & 0xf0) >> 4)); - vsei = ip[3] & 0xf; - for (m = 1; m < 5; ++m) { - vsei <<= 8; - vsei |= ip[3 + m]; - } - if (long_out) { - printf(" NAA 5, IEEE Company_id: 0x%x\n", c_id); - printf(" Vendor Specific Identifier: 0x%" PRIx64 - "\n", vsei); - printf(" [0x"); - for (m = 0; m < 8; ++m) - printf("%02x", (unsigned int)ip[m]); - printf("]\n"); - } else { - printf(" 0x"); - for (m = 0; m < 8; ++m) - printf("%02x", (unsigned int)ip[m]); - printf("\n"); - } - } else if (6 == naa) { - if (16 != i_len) { - fprintf(stderr, " << unexpected NAA 6 identifier " - "length: 0x%x>>\n", i_len); - dStrHex((const char *)ip, i_len, 0); - break; - } - c_id = (((ip[0] & 0xf) << 20) | (ip[1] << 12) | - (ip[2] << 4) | ((ip[3] & 0xf0) >> 4)); - vsei = ip[3] & 0xf; - for (m = 1; m < 5; ++m) { - vsei <<= 8; - vsei |= ip[3 + m]; - } - if (long_out) { - printf(" NAA 6, IEEE Company_id: 0x%x\n", c_id); - printf(" Vendor Specific Identifier: 0x%" PRIx64 - "\n", vsei); - vsei = 0; - for (m = 0; m < 8; ++m) { - if (m > 0) - vsei <<= 8; - vsei |= ip[8 + m]; - } - printf(" Vendor Specific Identifier Extension: " - "0x%" PRIx64 "\n", vsei); - printf(" [0x"); - for (m = 0; m < 16; ++m) - printf("%02x", (unsigned int)ip[m]); - printf("]\n"); - } else { - printf(" 0x"); - for (m = 0; m < 16; ++m) - printf("%02x", (unsigned int)ip[m]); - printf("\n"); - } } - break; - case 4: /* Relative target port */ - if ((1 != c_set) || (1 != assoc) || (4 != i_len)) { - fprintf(stderr, " << expected binary code_set, target " - "port association, length 4>>\n"); + } else if (6 == naa) { + if (16 != i_len) { + fprintf(stderr, " << unexpected NAA 6 identifier " + "length: 0x%x>>\n", i_len); dStrHex((const char *)ip, i_len, 0); break; } - d_id = ((ip[2] << 8) | ip[3]); - printf(" Relative target port: 0x%x\n", d_id); - break; - case 5: /* (primary) Target port group */ - if ((1 != c_set) || (1 != assoc) || (4 != i_len)) { - fprintf(stderr, " << expected binary code_set, target " - "port association, length 4>>\n"); - dStrHex((const char *)ip, i_len, 0); - break; + c_id = (((ip[0] & 0xf) << 20) | (ip[1] << 12) | + (ip[2] << 4) | ((ip[3] & 0xf0) >> 4)); + vsei = ip[3] & 0xf; + for (m = 1; m < 5; ++m) { + vsei <<= 8; + vsei |= ip[3 + m]; + } + if (long_out) { + printf(" NAA 6, IEEE Company_id: 0x%x\n", c_id); + printf(" Vendor Specific Identifier: 0x%" PRIx64 + "\n", vsei); + vsei = 0; + for (m = 0; m < 8; ++m) { + if (m > 0) + vsei <<= 8; + vsei |= ip[8 + m]; + } + printf(" Vendor Specific Identifier Extension: " + "0x%" PRIx64 "\n", vsei); + printf(" [0x"); + for (m = 0; m < 16; ++m) + printf("%02x", (unsigned int)ip[m]); + printf("]\n"); + } else { + printf(" 0x"); + for (m = 0; m < 16; ++m) + printf("%02x", (unsigned int)ip[m]); + printf("\n"); } - d_id = ((ip[2] << 8) | ip[3]); - printf(" Target port group: 0x%x\n", d_id); + } + break; + case 4: /* Relative target port */ + if ((1 != c_set) || (1 != assoc) || (4 != i_len)) { + fprintf(stderr, " << expected binary code_set, target " + "port association, length 4>>\n"); + dStrHex((const char *)ip, i_len, 0); break; - case 6: /* Logical unit group */ - if ((1 != c_set) || (0 != assoc) || (4 != i_len)) { - fprintf(stderr, " << expected binary code_set, logical " - "unit association, length 4>>\n"); - dStrHex((const char *)ip, i_len, 0); - break; - } - d_id = ((ip[2] << 8) | ip[3]); - printf(" Logical unit group: 0x%x\n", d_id); + } + d_id = ((ip[2] << 8) | ip[3]); + printf(" Relative target port: 0x%x\n", d_id); + break; + case 5: /* (primary) Target port group */ + if ((1 != c_set) || (1 != assoc) || (4 != i_len)) { + fprintf(stderr, " << expected binary code_set, target " + "port association, length 4>>\n"); + dStrHex((const char *)ip, i_len, 0); break; - case 7: /* MD5 logical unit identifier */ - if ((1 != c_set) || (0 != assoc)) { - printf(" << expected binary code_set, logical " - "unit association>>\n"); - dStrHex((const char *)ip, i_len, 0); - break; - } - printf(" MD5 logical unit identifier:\n"); + } + d_id = ((ip[2] << 8) | ip[3]); + printf(" Target port group: 0x%x\n", d_id); + break; + case 6: /* Logical unit group */ + if ((1 != c_set) || (0 != assoc) || (4 != i_len)) { + fprintf(stderr, " << expected binary code_set, logical " + "unit association, length 4>>\n"); dStrHex((const char *)ip, i_len, 0); break; - case 8: /* SCSI name string */ - if (3 != c_set) { - fprintf(stderr, " << expected UTF-8 code_set>>\n"); - dStrHex((const char *)ip, i_len, 0); - break; - } - printf(" SCSI name string:\n"); - /* does %s print out UTF-8 ok?? - * Seems to depend on the locale. Looks ok here with my - * locale setting: en_AU.UTF-8 - */ - printf(" %s\n", (const char *)ip); + } + d_id = ((ip[2] << 8) | ip[3]); + printf(" Logical unit group: 0x%x\n", d_id); + break; + case 7: /* MD5 logical unit identifier */ + if ((1 != c_set) || (0 != assoc)) { + printf(" << expected binary code_set, logical " + "unit association>>\n"); + dStrHex((const char *)ip, i_len, 0); break; - default: /* reserved */ + } + printf(" MD5 logical unit identifier:\n"); + dStrHex((const char *)ip, i_len, 0); + break; + case 8: /* SCSI name string */ + if (3 != c_set) { + fprintf(stderr, " << expected UTF-8 code_set>>\n"); dStrHex((const char *)ip, i_len, 0); break; } + printf(" SCSI name string:\n"); + /* does %s print out UTF-8 ok?? + * Seems to depend on the locale. Looks ok here with my + * locale setting: en_AU.UTF-8 + */ + printf(" %s\n", (const char *)ip); + break; + default: /* reserved */ + dStrHex((const char *)ip, i_len, 0); + break; + } +} + +/* Prints outs device identification designators selected by association, + designator type and/or code set. */ +static int +decode_dev_ids(const char * print_if_found, unsigned char * buff, int len, + int m_assoc, int m_desig_type, int m_code_set, int long_out, + int quiet) +{ + int assoc, i_len; + int printed, off, u; + const unsigned char * ucp; + + if (quiet) + return decode_dev_ids_quiet(buff, len, m_assoc, m_desig_type, + m_code_set); + off = -1; + printed = 0; + while ((u = sg_vpd_dev_id_iter(buff, len, &off, m_assoc, m_desig_type, + m_code_set)) == 0) { + ucp = buff + off; + i_len = ucp[3]; + if ((off + i_len + 4) > len) { + fprintf(stderr, " VPD page error: designator length longer " + "than\n remaining response length=%d\n", (len - off)); + return SG_LIB_CAT_MALFORMED; + } + assoc = ((ucp[1] >> 4) & 0x3); + if (print_if_found && (0 == printed)) { + printed = 1; + printf(" %s:\n", print_if_found); + } + if (NULL == print_if_found) + printf(" %s:\n", assoc_arr[assoc]); + decode_designation_descriptor(ucp, i_len, long_out, 0); } if (-2 == u) { fprintf(stderr, "VPD page error: short designator around " @@ -1418,6 +1431,100 @@ decode_b1_vpd(unsigned char * buff, int len, int do_hex, int pdt) } } +static int +decode_block_thin_prov_vpd(unsigned char * b, int len) +{ + int dp; + + if (len < 4) { + fprintf(stderr, "Thin provisioning page too short=%d\n", + len); + return SG_LIB_CAT_MALFORMED; + } + dp = !!(b[5] & 0x1); + printf(" Threshold exponent: %d\n", b[4]); + printf(" Descriptor present: %d\n", dp); + if (dp) { + const unsigned char * ucp; + int i_len; + + ucp = b + 8; + i_len = ucp[3]; + if (0 == i_len) { + fprintf(stderr, "Thin provisioning page provisioning group " + "descriptor too short=%d\n", i_len); + return 0; + } + printf(" Provisioning group descriptor\n"); + decode_designation_descriptor(ucp, i_len, 0, 1); + } + return 0; +} + +static int +decode_tapealert_supported_vpd(unsigned char * b, int len) +{ + if (len < 12) { + fprintf(stderr, "TapeAlert supported flags length too short=%d\n", + len); + return SG_LIB_CAT_MALFORMED; + } + printf(" Flag01h: %d 02h: %d 03h: %d 04h: %d 05h: %d 06h: %d " + "07h: %d 08h: %d\n", !!(b[4] & 0x80), !!(b[4] & 0x40), + !!(b[4] & 0x20), !!(b[4] & 0x10), !!(b[4] & 0x8), !!(b[4] & 0x4), + !!(b[4] & 0x2), !!(b[4] & 0x1)); + printf(" Flag09h: %d 0ah: %d 0bh: %d 0ch: %d 0dh: %d 0eh: %d " + "0fh: %d 10h: %d\n", !!(b[5] & 0x80), !!(b[5] & 0x40), + !!(b[5] & 0x20), !!(b[5] & 0x10), !!(b[5] & 0x8), !!(b[5] & 0x4), + !!(b[5] & 0x2), !!(b[5] & 0x1)); + printf(" Flag11h: %d 12h: %d 13h: %d 14h: %d 15h: %d 16h: %d " + "17h: %d 18h: %d\n", !!(b[6] & 0x80), !!(b[6] & 0x40), + !!(b[6] & 0x20), !!(b[6] & 0x10), !!(b[6] & 0x8), !!(b[6] & 0x4), + !!(b[6] & 0x2), !!(b[6] & 0x1)); + printf(" Flag19h: %d 1ah: %d 1bh: %d 1ch: %d 1dh: %d 1eh: %d " + "1fh: %d 20h: %d\n", !!(b[7] & 0x80), !!(b[7] & 0x40), + !!(b[7] & 0x20), !!(b[7] & 0x10), !!(b[7] & 0x8), !!(b[7] & 0x4), + !!(b[7] & 0x2), !!(b[7] & 0x1)); + printf(" Flag21h: %d 22h: %d 23h: %d 24h: %d 25h: %d 26h: %d " + "27h: %d 28h: %d\n", !!(b[8] & 0x80), !!(b[8] & 0x40), + !!(b[8] & 0x20), !!(b[8] & 0x10), !!(b[8] & 0x8), !!(b[8] & 0x4), + !!(b[8] & 0x2), !!(b[8] & 0x1)); + printf(" Flag29h: %d 2ah: %d 2bh: %d 2ch: %d 2dh: %d 2eh: %d " + "2fh: %d 30h: %d\n", !!(b[9] & 0x80), !!(b[9] & 0x40), + !!(b[9] & 0x20), !!(b[9] & 0x10), !!(b[9] & 0x8), !!(b[9] & 0x4), + !!(b[9] & 0x2), !!(b[9] & 0x1)); + printf(" Flag31h: %d 32h: %d 33h: %d 34h: %d 35h: %d 36h: %d " + "37h: %d 38h: %d\n", !!(b[10] & 0x80), !!(b[10] & 0x40), + !!(b[10] & 0x20), !!(b[10] & 0x10), !!(b[10] & 0x8), + !!(b[10] & 0x4), !!(b[10] & 0x2), !!(b[10] & 0x1)); + printf(" Flag39h: %d 3ah: %d 3bh: %d 3ch: %d 3dh: %d 3eh: %d " + "3fh: %d 40h: %d\n", !!(b[11] & 0x80), !!(b[11] & 0x40), + !!(b[11] & 0x20), !!(b[11] & 0x10), !!(b[11] & 0x8), + !!(b[11] & 0x4), !!(b[11] & 0x2), !!(b[11] & 0x1)); + return 0; +} + +static void +decode_b2_vpd(unsigned char * buff, int len, int do_hex, int pdt) +{ + if (do_hex) { + dStrHex((const char *)buff, len, 0); + 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); + break; + } +} + /* Returns 0 if successful */ static int svpd_unable_to_decode(int sg_fd, int num_vpd, int subvalue, int maxlen, @@ -2172,6 +2279,63 @@ svpd_decode_t10(int sg_fd, int num_vpd, int subvalue, int maxlen, int do_hex, } else if (! do_raw) printf("VPD page=0xb1\n"); break; + case 0xb2: /* 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("Thin 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); + break; + } + } + len = ((rsp_buff[2] << 8) + rsp_buff[3]) + 4; + if (num_vpd != rsp_buff[1]) { + fprintf(stderr, "invalid VPD response; probably a STANDARD " + "INQUIRY response\n"); + if (verbose) { + fprintf(stderr, "First 32 bytes of bad response\n"); + dStrHex((const char *)rsp_buff, 32, 0); + } + return SG_LIB_CAT_MALFORMED; + } + if (len > alloc_len) { + if ((0 == maxlen) && (len < MX_ALLOC_LEN)) { + res = sg_ll_inquiry(sg_fd, 0, 1, num_vpd, rsp_buff, len, + 1, verbose); + if (res) { + fprintf(stderr, "fetching 0xb2 page " + "(alloc_len=%d) failed\n", len); + return res; + } + } else { + fprintf(stderr, ">>> warning: response length (%d) " + "longer than requested (%d)\n", len, alloc_len); + len = alloc_len; + } + } + if (do_raw) + dStrRaw((const char *)rsp_buff, len); + else { + 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_b2_vpd(rsp_buff, len, do_hex, pdt); + } + return 0; + } else if (! do_raw) + printf("VPD page=0xb2\n"); + break; default: return SG_LIB_SYNTAX_ERROR; } |