aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/Makefile.am2
-rw-r--r--src/Makefile.in4
-rw-r--r--src/sg_inq.c218
-rw-r--r--src/sg_sat_read_gplog.c4
-rw-r--r--src/sg_vpd.c23
-rw-r--r--src/sg_vpd_common.c512
-rw-r--r--src/sg_vpd_common.h12
-rw-r--r--src/sg_vpd_vendor.c227
8 files changed, 576 insertions, 426 deletions
diff --git a/src/Makefile.am b/src/Makefile.am
index f75bc7cb..95144625 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -93,7 +93,7 @@ sg_ident_LDADD = ../lib/libsgutils2.la
sginfo_LDADD = ../lib/libsgutils2.la
-sg_inq_SOURCES = sg_inq.c sg_inq_data.c sg_vpd_vendor.c sg_vpd_common.c
+sg_inq_SOURCES = sg_inq.c sg_inq_data.c sg_vpd_common.c
sg_inq_LDADD = ../lib/libsgutils2.la
sg_logs_LDADD = ../lib/libsgutils2.la
diff --git a/src/Makefile.in b/src/Makefile.in
index c5217b1e..96880766 100644
--- a/src/Makefile.in
+++ b/src/Makefile.in
@@ -188,7 +188,7 @@ sg_ident_SOURCES = sg_ident.c
sg_ident_OBJECTS = sg_ident.$(OBJEXT)
sg_ident_DEPENDENCIES = ../lib/libsgutils2.la
am_sg_inq_OBJECTS = sg_inq.$(OBJEXT) sg_inq_data.$(OBJEXT) \
- sg_vpd_vendor.$(OBJEXT) sg_vpd_common.$(OBJEXT)
+ sg_vpd_common.$(OBJEXT)
sg_inq_OBJECTS = $(am_sg_inq_OBJECTS)
sg_inq_DEPENDENCIES = ../lib/libsgutils2.la
sg_logs_SOURCES = sg_logs.c
@@ -682,7 +682,7 @@ sg_get_elem_status_LDADD = ../lib/libsgutils2.la
sg_get_lba_status_LDADD = ../lib/libsgutils2.la
sg_ident_LDADD = ../lib/libsgutils2.la
sginfo_LDADD = ../lib/libsgutils2.la
-sg_inq_SOURCES = sg_inq.c sg_inq_data.c sg_vpd_vendor.c sg_vpd_common.c
+sg_inq_SOURCES = sg_inq.c sg_inq_data.c sg_vpd_common.c
sg_inq_LDADD = ../lib/libsgutils2.la
sg_logs_LDADD = ../lib/libsgutils2.la
sg_luns_LDADD = ../lib/libsgutils2.la
diff --git a/src/sg_inq.c b/src/sg_inq.c
index edd571c7..8a9b43e2 100644
--- a/src/sg_inq.c
+++ b/src/sg_inq.c
@@ -53,7 +53,7 @@
#include "sg_vpd_common.h" /* for shared VPD page processing with sg_vpd */
-static const char * version_str = "2.30 20220904"; /* spc6r06, sbc5r03 */
+static const char * version_str = "2.31 20220915"; /* spc6r06, sbc5r03 */
#define MY_NAME "sg_inq"
@@ -1122,17 +1122,6 @@ svpd_inhex_decode_all(struct opts_t * op, sgj_opaque_p jop)
return res;
}
-static int
-no_ascii_4hex(const struct opts_t * op)
-{
- if (op->do_hex < 2)
- return 1;
- else if (2 == op->do_hex)
- return 0;
- else
- return -1;
-}
-
static void
decode_supported_vpd_4inq(uint8_t * buff, int len, struct opts_t * op,
sgj_opaque_p jap)
@@ -2089,185 +2078,7 @@ decode_b3_vpd(uint8_t * buff, int len, struct opts_t * op, sgj_opaque_p jop)
}
}
-static const char * lun_state_arr[] =
-{
- "LUN not bound or LUN_Z report",
- "LUN bound, but not owned by this SP",
- "LUN bound and owned by this SP",
-};
-
-static const char * ip_mgmt_arr[] =
-{
- "No IP access",
- "Reserved (undefined)",
- "via IPv4",
- "via IPv6",
-};
-
-static const char * sp_arr[] =
-{
- "SP A",
- "SP B",
-};
-
-static const char * lun_op_arr[] =
-{
- "Normal operations",
- "I/O Operations being rejected, SP reboot or NDU in progress",
-};
-
-static const char * failover_mode_arr[] =
-{
- "Legacy mode 0",
- "Unknown mode (1)",
- "Unknown mode (2)",
- "Unknown mode (3)",
- "Active/Passive (PNR) mode 1",
- "Unknown mode (5)",
- "Active/Active (ALUA) mode 4",
- "Unknown mode (7)",
- "Legacy mode 2",
- "Unknown mode (9)",
- "Unknown mode (10)",
- "Unknown mode (11)",
- "Unknown mode (12)",
- "Unknown mode (13)",
- "AIX Active/Passive (PAR) mode 3",
- "Unknown mode (15)",
-};
-
-static void
-decode_upr_vpd_c0_emc(uint8_t * buff, int len, struct opts_t * op,
- sgj_opaque_p jop)
-{
- uint8_t uc;
- int k, n, ip_mgmt, vpp80, lun_z;
- sgj_state * jsp = &op->json_st;
- const char * cp;
- char b[256];
- static const int blen = sizeof(b);
-
- if (len < 3) {
- pr2serr("EMC upr VPD page [0xc0]: length too short=%d\n", len);
- return;
- }
- if (op->do_hex) {
- hex2stdout(buff, len, no_ascii_4hex(op));
- return;
- }
- if (buff[9] != 0x00) {
- pr2serr("Unsupported page revision %d, decoding not possible.\n",
- buff[9]);
- return;
- }
- for (k = 0, n = 0; k < 16; ++k)
- n += sg_scnpr(b + n, blen - n, "%02x", buff[10 + k]);
- sgj_haj_vs(jsp, jop, 2, "LUN WWN", SGJ_SEP_COLON_1_SPACE, b);
- snprintf(b, blen, "%.*s", buff[49], buff + 50);
- sgj_haj_vs(jsp, jop, 2, "Array Serial Number", SGJ_SEP_COLON_1_SPACE, b);
-
- if (buff[4] > 0x02)
- snprintf(b, blen, "Unknown (%x)", buff[4]);
- else
- snprintf(b, blen, "%s", lun_state_arr[buff[4]]);
- sgj_haj_vistr(jsp, jop, 2, "LUN State", SGJ_SEP_COLON_1_SPACE,
- buff[4], true, b);
-
- uc = buff[8];
- n = 0;
- if (uc > 0x01)
- n += sg_scnpr(b + n, blen - n, "Unknown SP (%x)", uc);
- else
- n += sg_scnpr(b + n, blen - n, "%s", sp_arr[uc]);
- sgj_js_nv_ihexstr(jsp, jop, "path_connects_to", uc, NULL, b);
- n += sg_scnpr(b + n, blen - n, ", Port Number: %u", buff[7]);
- sgj_pr_hr(jsp, " This path connects to: %s\n", b);
- sgj_js_nv_ihex(jsp, jop, "port_number", buff[7]);
-
- if (buff[5] > 0x01)
- snprintf(b, blen, "Unknown (%x)\n", buff[5]);
- else
- snprintf(b, blen, "%s\n", sp_arr[buff[5]]);
- sgj_haj_vistr(jsp, jop, 2, "Default owner", SGJ_SEP_COLON_1_SPACE,
- buff[5], true, b);
-
- cp = (buff[6] & 0x40) ? "supported" : "not supported";
- sgj_pr_hr(jsp, " NO_ATF: %s, Access Logix: %s\n",
- buff[6] & 0x80 ? "set" : "not set", cp);
- sgj_js_nv_i(jsp, jop, "no_atf", !! (buff[6] & 0x80));
- sgj_js_nv_istr(jsp, jop, "access_logix", !! (buff[6] & 0x40),
- NULL, cp);
-
- ip_mgmt = (buff[6] >> 4) & 0x3;
- cp = ip_mgmt_arr[ip_mgmt];
- sgj_pr_hr(jsp, " SP IP Management Mode: %s\n", cp);
- sgj_js_nv_istr(jsp, jop, "sp_ip_management_mode", !! ip_mgmt,
- NULL, cp);
- if (ip_mgmt == 2) {
- snprintf(b, blen, "%u.%u.%u.%u", buff[44], buff[45], buff[46],
- buff[47]);
- sgj_pr_hr(jsp, " SP IPv4 address: %s\n", b);
- sgj_js_nv_s(jsp, jop, "sp_ipv4_address", b);
- } else if (ip_mgmt == 3) {
- printf(" SP IPv6 address: ");
- n = 0;
- for (k = 0; k < 16; ++k)
- n += sg_scnpr(b + n, blen - n, "%02x", buff[32 + k]);
- sgj_pr_hr(jsp, " SP IPv6 address: %s\n", b);
- sgj_js_nv_hex_bytes(jsp, jop, "sp_ipv6_address", buff + 32, 16);
- }
-
-// yyyyyyy more conversion work needed below this point
- vpp80 = buff[30] & 0x08;
- lun_z = buff[30] & 0x04;
-
- printf(" System Type: %x, Failover mode: %s\n",
- buff[27], failover_mode_arr[buff[28] & 0x0f]);
-
- printf(" Inquiry VPP 0x80 returns: %s, Arraycommpath: %s\n",
- vpp80 ? "array serial#" : "LUN serial#",
- lun_z ? "Set to 1" : "Unknown");
-
- printf(" Lun operations: %s\n",
- buff[48] > 1 ? "undefined" : lun_op_arr[buff[48]]);
-
- return;
-}
-
-static void
-decode_rdac_vpd_c2(uint8_t * buff, int len, struct opts_t * op)
-{
- if (len < 3) {
- pr2serr("Software Version VPD page length too short=%d\n", len);
- return;
- }
- if (op->do_hex) {
- hex2stdout(buff, len, no_ascii_4hex(op));
- return;
- }
- if (buff[4] != 's' && buff[5] != 'w' && buff[6] != 'r') {
- pr2serr("Invalid page identifier %c%c%c%c, decoding "
- "not possible.\n" , buff[4], buff[5], buff[6], buff[7]);
- return;
- }
- printf(" Software Version: %02x.%02x.%02x\n", buff[8], buff[9], buff[10]);
- printf(" Software Date: %02d/%02d/%02d\n", buff[11], buff[12], buff[13]);
- printf(" Features:");
- if (buff[14] & 0x01)
- printf(" Dual Active,");
- if (buff[14] & 0x02)
- printf(" Series 3,");
- if (buff[14] & 0x04)
- printf(" Multiple Sub-enclosures,");
- if (buff[14] & 0x08)
- printf(" DCE/DRM/DSS/DVE,");
- if (buff[14] & 0x10)
- printf(" Asymmetric Logical Unit Access,");
- printf("\n");
- printf(" Max. #of LUNS: %d\n", buff[15]);
- return;
-}
-
+#if 0
static void
decode_rdac_vpd_c9_rtpg_data(uint8_t aas, uint8_t vendor)
{
@@ -2440,6 +2251,7 @@ decode_rdac_vpd_c9(uint8_t * buff, int len, struct opts_t * op)
return;
}
+#endif
extern const char * sg_ansi_version_arr[];
@@ -3840,7 +3652,7 @@ vpd_decode(int sg_fd, struct opts_t * op, sgj_opaque_p jop, int off)
break;
/* Vendor specific VPD pages (>= 0xc0) */
case VPD_UPR_EMC: /* 0xc0 */
- np = "Block device characteristics VPD page";
+ np = "Unit path report VPD page";
ep = "(EMC)";
if (!op->do_raw && (op->do_hex < 3))
sgj_pr_hr(jsp, "VPD INQUIRY: %s %s\n", np, ep);
@@ -3856,26 +3668,36 @@ vpd_decode(int sg_fd, struct opts_t * op, sgj_opaque_p jop, int off)
}
break;
case VPD_RDAC_VERS: /* 0xc2 */
+ np = "Software Version VPD page";
+ ep = "(RDAC)";
if (!op->do_raw && (op->do_hex < 3))
- printf("VPD INQUIRY: Software Version (RDAC)\n");
+ sgj_pr_hr(jsp, "VPD INQUIRY: %s %s\n", np, ep);
res = vpd_fetch_page(sg_fd, rp, pn, -1, qt, vb, &len);
if (res)
break;
if (op->do_raw)
dStrRaw((const char *)rp, len);
- else
- decode_rdac_vpd_c2(rp, len, op);
+ else {
+ if (as_json)
+ jo2p = sg_vpd_js_hdr(jsp, jop, np, rp);
+ decode_rdac_vpd_c2(rp, len, op, jo2p);
+ }
break;
case VPD_RDAC_VAC: /* 0xc9 */
+ np = "Volume access control VPD page";
+ ep = "(RDAC)";
if (!op->do_raw && (op->do_hex < 3))
- printf("VPD INQUIRY: Volume Access Control (RDAC)\n");
+ sgj_pr_hr(jsp, "VPD INQUIRY: %s %s\n", np, ep);
res = vpd_fetch_page(sg_fd, rp, pn, -1, qt, vb, &len);
if (res)
break;
if (op->do_raw)
dStrRaw((const char *)rp, len);
- else
- decode_rdac_vpd_c9(rp, len, op);
+ else {
+ if (as_json)
+ jo2p = sg_vpd_js_hdr(jsp, jop, np, rp);
+ decode_rdac_vpd_c9(rp, len, op, jo2p);
+ }
break;
case SG_NVME_VPD_NICR: /* 0xde */
np = "NVMe Identify Controller Response VPD page";
diff --git a/src/sg_sat_read_gplog.c b/src/sg_sat_read_gplog.c
index a1afc828..55c164eb 100644
--- a/src/sg_sat_read_gplog.c
+++ b/src/sg_sat_read_gplog.c
@@ -54,7 +54,7 @@
#define DEF_TIMEOUT 20
-static const char * version_str = "1.22 20220425";
+static const char * version_str = "1.23 20220917";
struct opts_t {
bool ck_cond;
@@ -124,7 +124,7 @@ usage()
}
static int
-do_read_gplog(int sg_fd, int ata_cmd, uint8_t *inbuff,
+do_read_gplog(int sg_fd, int ata_cmd, uint8_t * inbuff,
const struct opts_t * op)
{
const bool extend = true;
diff --git a/src/sg_vpd.c b/src/sg_vpd.c
index 707d3e12..35de6ca4 100644
--- a/src/sg_vpd.c
+++ b/src/sg_vpd.c
@@ -42,7 +42,7 @@
*/
-static const char * version_str = "1.82 20220826"; /* spc6r06 + sbc5r03 */
+static const char * version_str = "1.83 20220915"; /* spc6r06 + sbc5r03 */
#define MY_NAME "sg_vpd"
@@ -444,17 +444,6 @@ device_id_vpd_variants(uint8_t * buff, int len, int subvalue,
}
}
-static int
-no_ascii_4hex(const struct opts_t * op)
-{
- if (op->do_hex < 2)
- return 1;
- else if (2 == op->do_hex)
- return 0;
- else
- return -1;
-}
-
static void /* VPD_SUPPORTED_VPDS ["sv"] */
decode_supported_vpd_4vpd(uint8_t * buff, int len, struct opts_t * op,
sgj_opaque_p jap)
@@ -1100,16 +1089,6 @@ svpd_unable_to_decode(int sg_fd, struct opts_t * op, int subvalue, int off)
}
} else
hex2stdout(rp, len, no_ascii_4hex(op));
-#if 0
- if (op->do_hex > 1)
- hex2stdout(rp, len, -1);
- else if (VPD_ASCII_OP_DEF == op->vpd_pn)
- hex2stdout(rp, len, 0);
- else if (1 == op->do_hex)
- hex2stdout(rp, len, (op->do_long ? 0 : 1));
- else
- hex2stdout(rp, len, 0);
-#endif
}
} else if ((! op->do_quiet) && (! op->examine_given)) {
if (op->vpd_pn >= 0)
diff --git a/src/sg_vpd_common.c b/src/sg_vpd_common.c
index dcc7727b..31c74ea0 100644
--- a/src/sg_vpd_common.c
+++ b/src/sg_vpd_common.c
@@ -132,6 +132,17 @@ struct svpd_values_name_t vendor_vpd_pg[] = {
int
+no_ascii_4hex(const struct opts_t * op)
+{
+ if (op->do_hex < 2)
+ return 1;
+ else if (2 == op->do_hex)
+ return 0;
+ else
+ return -1;
+}
+
+int
svpd_find_vp_num_by_acron(const char * vp_ap)
{
size_t len;
@@ -696,9 +707,9 @@ decode_mode_policy_vpd(const uint8_t * buff, int len, struct opts_t * op,
n = 0;
ppc = (bp[0] & 0x3f);
pspc = bp[1];
- n = snprintf(b + n, blen - n, " Policy page code: 0x%x", ppc);
+ n = sg_scnpr(b + n, blen - n, " Policy page code: 0x%x", ppc);
if (pspc)
- n += snprintf(b + n, blen - n, ", subpage code: 0x%x", pspc);
+ n += sg_scnpr(b + n, blen - n, ", subpage code: 0x%x", pspc);
sgj_pr_hr(jsp, "%s\n", b);
if ((0 == k) && (0x3f == (0x3f & bp[0])) && (0xff == bp[1]))
sgj_pr_hr(jsp, " therefore the policy applies to all modes "
@@ -839,7 +850,7 @@ decode_ata_info_vpd(const uint8_t * buff, int len, struct opts_t * op,
ata_transp);
cc = buff[56]; /* 0xec for IDENTIFY DEVICE and 0xa1 for IDENTIFY
* PACKET DEVICE (obsolete) */
- n = snprintf(b, blen, " Command code: 0x%x\n", cc);
+ n = sg_scnpr(b, blen, " Command code: 0x%x\n", cc);
if (len < 60)
return;
if (0xec == cc)
@@ -2993,3 +3004,498 @@ decode_tapealert_supported_vpd(const uint8_t * buff, int len,
}
sgj_pr_hr(jsp, "%s\n", b);
}
+
+/*
+ * Some of the vendor specific VPD pages are common as well. So place them here
+ * to save on code duplication.
+ */
+
+static const char * lun_state_arr[] =
+{
+ "LUN not bound or LUN_Z report",
+ "LUN bound, but not owned by this SP",
+ "LUN bound and owned by this SP",
+};
+
+static const char * ip_mgmt_arr[] =
+{
+ "No IP access",
+ "Reserved (undefined)",
+ "via IPv4",
+ "via IPv6",
+};
+
+static const char * sp_arr[] =
+{
+ "SP A",
+ "SP B",
+};
+
+static const char * lun_op_arr[] =
+{
+ "Normal operations",
+ "I/O Operations being rejected, SP reboot or NDU in progress",
+};
+
+static const char * failover_mode_arr[] =
+{
+ "Legacy mode 0",
+ "Unknown mode (1)",
+ "Unknown mode (2)",
+ "Unknown mode (3)",
+ "Active/Passive (PNR) mode 1",
+ "Unknown mode (5)",
+ "Active/Active (ALUA) mode 4",
+ "Unknown mode (7)",
+ "Legacy mode 2",
+ "Unknown mode (9)",
+ "Unknown mode (10)",
+ "Unknown mode (11)",
+ "Unknown mode (12)",
+ "Unknown mode (13)",
+ "AIX Active/Passive (PAR) mode 3",
+ "Unknown mode (15)",
+};
+
+/* VPD_UPR_EMC,VPD_V_UPR_EMC 0xc0 ["upr","upr"] */
+void
+decode_upr_vpd_c0_emc(uint8_t * buff, int len, struct opts_t * op,
+ sgj_opaque_p jop)
+{
+ uint8_t uc;
+ int k, n, ip_mgmt, vpp80, lun_z;
+ sgj_state * jsp = &op->json_st;
+ const char * cp;
+ const char * c2p;
+ char b[256];
+ static const int blen = sizeof(b);
+
+ if (len < 3) {
+ pr2serr("EMC upr VPD page [0xc0]: length too short=%d\n", len);
+ return;
+ }
+ if (op->do_hex) {
+ hex2stdout(buff, len, no_ascii_4hex(op));
+ return;
+ }
+ if (buff[9] != 0x00) {
+ pr2serr("Unsupported page revision %d, decoding not possible.\n",
+ buff[9]);
+ return;
+ }
+ for (k = 0, n = 0; k < 16; ++k)
+ n += sg_scnpr(b + n, blen - n, "%02x", buff[10 + k]);
+ sgj_haj_vs(jsp, jop, 2, "LUN WWN", SGJ_SEP_COLON_1_SPACE, b);
+ snprintf(b, blen, "%.*s", buff[49], buff + 50);
+ sgj_haj_vs(jsp, jop, 2, "Array Serial Number", SGJ_SEP_COLON_1_SPACE, b);
+
+ if (buff[4] > 0x02)
+ snprintf(b, blen, "Unknown (%x)", buff[4]);
+ else
+ snprintf(b, blen, "%s", lun_state_arr[buff[4]]);
+ sgj_haj_vistr(jsp, jop, 2, "LUN State", SGJ_SEP_COLON_1_SPACE,
+ buff[4], true, b);
+
+ uc = buff[8];
+ n = 0;
+ if (uc > 0x01)
+ n += sg_scnpr(b + n, blen - n, "Unknown SP (%x)", uc);
+ else
+ n += sg_scnpr(b + n, blen - n, "%s", sp_arr[uc]);
+ sgj_js_nv_ihexstr(jsp, jop, "path_connects_to", uc, NULL, b);
+ n += sg_scnpr(b + n, blen - n, ", Port Number: %u", buff[7]);
+ sgj_pr_hr(jsp, " This path connects to: %s\n", b);
+ sgj_js_nv_ihex(jsp, jop, "port_number", buff[7]);
+
+ if (buff[5] > 0x01)
+ snprintf(b, blen, "Unknown (%x)\n", buff[5]);
+ else
+ snprintf(b, blen, "%s\n", sp_arr[buff[5]]);
+ sgj_haj_vistr(jsp, jop, 2, "Default owner", SGJ_SEP_COLON_1_SPACE,
+ buff[5], true, b);
+
+ cp = (buff[6] & 0x40) ? "supported" : "not supported";
+ sgj_pr_hr(jsp, " NO_ATF: %s, Access Logix: %s\n",
+ buff[6] & 0x80 ? "set" : "not set", cp);
+ sgj_js_nv_i(jsp, jop, "no_atf", !! (buff[6] & 0x80));
+ sgj_js_nv_istr(jsp, jop, "access_logix", !! (buff[6] & 0x40),
+ NULL, cp);
+
+ ip_mgmt = (buff[6] >> 4) & 0x3;
+ cp = ip_mgmt_arr[ip_mgmt];
+ sgj_pr_hr(jsp, " SP IP Management Mode: %s\n", cp);
+ sgj_js_nv_istr(jsp, jop, "sp_ip_management_mode", !! ip_mgmt,
+ NULL, cp);
+ if (ip_mgmt == 2) {
+ snprintf(b, blen, "%u.%u.%u.%u", buff[44], buff[45], buff[46],
+ buff[47]);
+ sgj_pr_hr(jsp, " SP IPv4 address: %s\n", b);
+ sgj_js_nv_s(jsp, jop, "sp_ipv4_address", b);
+ } else if (ip_mgmt == 3) {
+ printf(" SP IPv6 address: ");
+ n = 0;
+ for (k = 0; k < 16; ++k)
+ n += sg_scnpr(b + n, blen - n, "%02x", buff[32 + k]);
+ sgj_pr_hr(jsp, " SP IPv6 address: %s\n", b);
+ sgj_js_nv_hex_bytes(jsp, jop, "sp_ipv6_address", buff + 32, 16);
+ }
+
+ k = buff[28] & 0x0f;
+ sgj_pr_hr(jsp, " System Type: %x, Failover mode: %s\n",
+ buff[27], failover_mode_arr[k]);
+ sgj_js_nv_ihex(jsp, jop, "system_type", buff[27]);
+ sgj_js_nv_ihexstr(jsp, jop, "failover_mode", k, NULL,
+ failover_mode_arr[k]);
+
+ vpp80 = buff[30] & 0x08;
+ lun_z = buff[30] & 0x04;
+ cp = vpp80 ? "array serial#" : "LUN serial#";
+ c2p = lun_z ? "Set to 1" : "Unknown";
+ sgj_pr_hr(jsp, " Inquiry VPP 0x80 returns: %s, Arraycommpath: %s\n",
+ cp, c2p);
+ sgj_js_nv_istr(jsp, jop, "inquiry_vpp_0x80_returns", !! vpp80, NULL, cp);
+ sgj_js_nv_istr(jsp, jop, "arraycommpath", !! lun_z, NULL, c2p);
+
+ cp = buff[48] > 1 ? "undefined" : lun_op_arr[buff[48]];
+ sgj_pr_hr(jsp, " Lun operations: %s\n", cp);
+ sgj_js_nv_istr(jsp, jop, "lun_operations", 0x1 & buff[48], NULL, cp);
+
+ return;
+}
+
+/* VPD_RDAC_VERS,VPD_V_SVER_RDAC 0xc2 ["rdac_vers", "swr4"] */
+void
+decode_rdac_vpd_c2(uint8_t * buff, int len, struct opts_t * op,
+ sgj_opaque_p jop)
+{
+ int i, n, v, r, m, p, d, y, num_part;
+ sgj_state * jsp = &op->json_st;
+ sgj_opaque_p jo2p = NULL;
+ sgj_opaque_p jap = NULL;
+ // const char * cp;
+ // const char * c2p;
+ char b[256];
+ static const int blen = sizeof(b);
+ char part[5];
+
+ if (len < 3) {
+ pr2serr("Software Version VPD page length too short=%d\n", len);
+ return;
+ }
+ if (op->do_hex) {
+ hex2stdout(buff, len, no_ascii_4hex(op));
+ return;
+ }
+ if (buff[4] != 's' && buff[5] != 'w' && buff[6] != 'r') {
+ pr2serr("Invalid page identifier %c%c%c%c, decoding not possible.\n",
+ buff[4], buff[5], buff[6], buff[7]);
+ return;
+ }
+ snprintf(b, blen, "%02x.%02x.%02x", buff[8], buff[9], buff[10]);
+ sgj_haj_vs(jsp, jop, 2, "Software Version", SGJ_SEP_COLON_1_SPACE, b);
+ snprintf(b, blen, "%02d/%02d/%02d\n", buff[11], buff[12], buff[13]);
+ sgj_haj_vs(jsp, jop, 2, "Software Date", SGJ_SEP_COLON_1_SPACE, b);
+ n = 0;
+ n += sg_scnpr(b + n, blen - n, " Features:");
+ if (buff[14] & 0x01)
+ n += sg_scnpr(b + n, blen - n, " Dual Active,");
+ if (buff[14] & 0x02)
+ n += sg_scnpr(b + n, blen - n, " Series 3,");
+ if (buff[14] & 0x04)
+ n += sg_scnpr(b + n, blen - n, " Multiple Sub-enclosures,");
+ if (buff[14] & 0x08)
+ n += sg_scnpr(b + n, blen - n, " DCE/DRM/DSS/DVE,");
+ if (buff[14] & 0x10)
+ n += sg_scnpr(b + n, blen - n, " Asymmetric Logical Unit Access,");
+ sgj_pr_hr(jsp, "%s\n", b);
+ if (jsp->pr_as_json) {
+ jo2p = sgj_snake_named_subobject_r(jsp, jop, "features");
+ sgj_js_nv_i(jsp, jo2p, "dual_active", !! (buff[14] & 0x01));
+ sgj_js_nv_i(jsp, jo2p, "series_3", !! (buff[14] & 0x02));
+ sgj_js_nv_i(jsp, jo2p, "multiple_sub_enclosures",
+ !! (buff[14] & 0x04));
+ sgj_js_nv_i(jsp, jo2p, "dcm_drm_dss_dve", !! (buff[14] & 0x08));
+ sgj_js_nv_i(jsp, jo2p, "asymmetric_logical_unit_access",
+ !! (buff[14] & 0x10));
+ }
+ sgj_haj_vi(jsp, jop, 2, "Maximum number of LUNS",
+ SGJ_SEP_COLON_1_SPACE, buff[15], true);
+
+ num_part = (len - 12) / 16;
+ n = 16;
+ printf(" Partitions: %d\n", num_part);
+ sgj_haj_vi(jsp, jop, 2, "Partitions", SGJ_SEP_COLON_1_SPACE, num_part,
+ true);
+ if (num_part > 0)
+ jap = sgj_named_subarray_r(jsp, jop, "partition_list");
+ for (i = 0; i < num_part; i++) {
+ memset(part,0, 5);
+ memcpy(part, &buff[n], 4);
+ sgj_pr_hr(jsp, " Name: %s\n", part);
+ if (jsp->pr_as_json) {
+ jo2p = sgj_new_unattached_object_r(jsp);
+ sgj_js_nv_s(jsp, jo2p, "name", part);
+ }
+ n += 4;
+ v = buff[n++];
+ r = buff[n++];
+ m = buff[n++];
+ p = buff[n++];
+ snprintf(b, blen, "%d.%d.%d.%d", v, r, m, p);
+ sgj_pr_hr(jsp, " Version: %s\n", b);
+ if (jsp->pr_as_json)
+ sgj_js_nv_s(jsp, jo2p, "version", b);
+ m = buff[n++];
+ d = buff[n++];
+ y = buff[n++];
+ snprintf(b, blen, "%d/%d/%d\n", m, d, y);
+ sgj_pr_hr(jsp, " Date: %s\n", b);
+ if (jsp->pr_as_json) {
+ sgj_js_nv_s(jsp, jo2p, "date", b);
+ sgj_js_nv_o(jsp, jap, NULL /* name */, jo2p);
+ }
+
+ n += 5;
+ }
+ return;
+}
+
+static char *
+decode_rdac_vpd_c9_aas_s(uint8_t aas, char * b, int blen)
+{
+ // snprintf(" Asymmetric Access State:");
+ switch(aas & 0x0F) {
+ case 0x0:
+ snprintf(b, blen, "Active/Optimized");
+ break;
+ case 0x1:
+ snprintf(b, blen, "Active/Non-Optimized");
+ break;
+ case 0x2:
+ snprintf(b, blen, "Standby");
+ break;
+ case 0x3:
+ snprintf(b, blen, "Unavailable");
+ break;
+ case 0xE:
+ snprintf(b, blen, "Offline");
+ break;
+ case 0xF:
+ snprintf(b, blen, "Transitioning");
+ break;
+ default:
+ snprintf(b, blen, "(unknown)");
+ break;
+ }
+ return b;
+}
+
+static char *
+decode_rdac_vpd_c9_vs_s(uint8_t vendor, char * b, int blen)
+{
+ // printf(" Vendor Specific Field:");
+ switch(vendor) {
+ case 0x01:
+ snprintf(b, blen, "Operating normally");
+ break;
+ case 0x02:
+ snprintf(b, blen, "Non-responsive to queries");
+ break;
+ case 0x03:
+ snprintf(b, blen, "Controller being held in reset");
+ break;
+ case 0x04:
+ snprintf(b, blen, "Performing controller firmware download (1st "
+ "controller)");
+ break;
+ case 0x05:
+ snprintf(b, blen, "Performing controller firmware download (2nd "
+ "controller)");
+ break;
+ case 0x06:
+ snprintf(b, blen,
+ "Quiesced as a result of an administrative request");
+ break;
+ case 0x07:
+ snprintf(b, blen,
+ "Service mode as a result of an administrative request");
+ break;
+ case 0xFF:
+ snprintf(b, blen, "Details are not available");
+ break;
+ default:
+ snprintf(b, blen, "(unknown)");
+ break;
+ }
+ return b;
+}
+
+/* VPD_RDAC_VAC,VPD_V_VAC_RDAC 0xc9 ["rdac_vac", "vac1"] */
+void
+decode_rdac_vpd_c9(uint8_t * buff, int len, struct opts_t * op,
+ sgj_opaque_p jop)
+{
+ bool vav;
+ int n, n_hold;
+ sgj_state * jsp = &op->json_st;
+ char b[196];
+ static const int blen = sizeof(b);
+
+ if (len < 3) {
+ pr2serr("Volume Access Control VPD page length too short=%d\n", len);
+ return;
+ }
+ if (op->do_hex) {
+ hex2stdout(buff, len, no_ascii_4hex(op));
+ return;
+ }
+ if (buff[4] != 'v' && buff[5] != 'a' && buff[6] != 'c') {
+ pr2serr("Invalid page identifier %c%c%c%c, decoding "
+ "not possible.\n" , buff[4], buff[5], buff[6], buff[7]);
+ return;
+ }
+ if (buff[7] != '1') {
+ pr2serr("Invalid page version '%c' (should be 1)\n", buff[7]);
+ }
+ n = ((buff[8] & 0xE0) == 0xE0 );
+ if (n) {
+ sgj_pr_hr(jsp, " IOShipping (ALUA): Enabled\n");
+ sgj_js_nv_ihexstr_nex(jsp, jop, "ioshipping", n, true, NULL,
+ "Enabled",
+ "a.k.a. ALUA (Asymmetric Logical Unit Access)");
+ } else {
+ n = 0;
+ n = snprintf(b, blen, " AVT:");
+ n_hold = n;
+ if (buff[8] & 0x80) {
+ n += sg_scnpr(b + n, blen - n, " Enabled");
+ if (buff[8] & 0x40)
+ n += sg_scnpr(b + n, blen - n, " (Allow reads on sector 0)");
+ sgj_pr_hr(jsp, "%s\n", b);
+ sgj_js_nv_ihexstr(jsp, jop, "avt", buff[8], NULL, b + n_hold);
+
+ } else {
+ sgj_pr_hr(jsp, "%s: Disabled\n", b);
+ sgj_js_nv_ihexstr(jsp, jop, "avt", buff[8], NULL, "Disabled");
+ }
+ }
+ vav = !! (0x1 & buff[8]);
+ sgj_haj_vistr(jsp, jop, 2, "Volume access via", SGJ_SEP_COLON_1_SPACE,
+ (int)vav, false,
+ (vav ? "primary controller" : "alternate controller"));
+
+ if (buff[8] & 0x08) {
+ n = buff[15] & 0xf;
+ // printf(" Path priority: %d ", n);
+ switch (n) {
+ case 0x1:
+ snprintf(b, blen, "(preferred path)");
+ break;
+ case 0x2:
+ snprintf(b, blen, "(secondary path)");
+ break;
+ default:
+ snprintf(b, blen, "(unknown)");
+ break;
+ }
+ sgj_haj_vistr(jsp, jop, 2, "Path priority", SGJ_SEP_COLON_1_SPACE, n,
+ true, b);
+
+ // printf(" Preferred Path Auto Changeable:");
+ n = buff[14] & 0x3C;
+ switch (n) {
+ case 0x14:
+ snprintf(b, blen, "No (User Disabled and Host Type Restricted)");
+ break;
+ case 0x18:
+ snprintf(b, blen, "No (User Disabled)");
+ break;
+ case 0x24:
+ snprintf(b, blen, "No (Host Type Restricted)");
+ break;
+ case 0x28:
+ snprintf(b, blen, "Yes");
+ break;
+ default:
+ snprintf(b, blen, "(Unknown)");
+ break;
+ }
+ sgj_haj_vistr(jsp, jop, 2, "Preferred path auto changeable",
+ SGJ_SEP_COLON_1_SPACE, n, true, b);
+
+ n = buff[14] & 0x03;
+ // printf(" Implicit Failback:");
+ switch (n) {
+ case 0x1:
+ snprintf(b, blen, "Disabled");
+ break;
+ case 0x2:
+ snprintf(b, blen, "Enabled");
+ break;
+ default:
+ snprintf(b, blen, "(Unknown)");
+ break;
+ }
+ sgj_haj_vistr(jsp, jop, 2, "Implicit failback",
+ SGJ_SEP_COLON_1_SPACE, n, false, b);
+ } else {
+ n = buff[9] & 0xf;
+ // printf(" Path priority: %d ", buff[9] & 0xf);
+ switch (n) {
+ case 0x1:
+ snprintf(b, blen, "(preferred path)");
+ break;
+ case 0x2:
+ snprintf(b, blen, "(secondary path)");
+ break;
+ default:
+ snprintf(b, blen, "(unknown)");
+ break;
+ }
+ sgj_haj_vistr(jsp, jop, 2, "Path priority",
+ SGJ_SEP_COLON_1_SPACE, n, false, b);
+ }
+
+ n = !! (buff[8] & 0x80);
+ sgj_haj_vi(jsp, jop, 2, "Target port group present",
+ SGJ_SEP_COLON_1_SPACE, n, false);
+ if (n) {
+ sgj_opaque_p jo2p = NULL;
+ sgj_opaque_p jo3p = NULL;
+ static const char * tpg_s = "Target port group data";
+ static const char * aas_s = "Asymmetric access state";
+ static const char * vs_s = "Vendor specific field";
+ char d1[80];
+ char d2[80];
+
+ sgj_pr_hr(jsp, " Target Port Group Data (This controller):\n");
+ decode_rdac_vpd_c9_aas_s(buff[10], d1, sizeof(d1));
+ decode_rdac_vpd_c9_vs_s(buff[11], d2, sizeof(d2));
+ sgj_pr_hr(jsp, " %s: %s\n", aas_s, d1);
+ sgj_pr_hr(jsp, " %s: %s\n", vs_s, d2);
+ if (jsp->pr_as_json) {
+ jo2p = sgj_snake_named_subobject_r(jsp, jop, tpg_s);
+ jo3p = sgj_snake_named_subobject_r(jsp, jo2p, "this_controller");
+ sgj_convert_to_snake_name(aas_s, b, blen);
+ sgj_js_nv_ihexstr(jsp, jo3p, b, buff[10], NULL, d1);
+ sgj_convert_to_snake_name(vs_s, b, blen);
+ sgj_js_nv_ihexstr(jsp, jo3p, b, buff[11], NULL, d2);
+ }
+ sgj_pr_hr(jsp, " Target Port Group Data (Alternate controller):\n");
+ // decode_rdac_vpd_c9_rtpg_data(buff[12], buff[13]);
+
+ decode_rdac_vpd_c9_aas_s(buff[12], d1, sizeof(d1));
+ decode_rdac_vpd_c9_vs_s(buff[13], d2, sizeof(d2));
+ sgj_pr_hr(jsp, " %s: %s\n", aas_s, d1);
+ sgj_pr_hr(jsp, " %s: %s\n", vs_s, d2);
+ if (jsp->pr_as_json) {
+ jo2p = sgj_snake_named_subobject_r(jsp, jop, tpg_s);
+ jo3p = sgj_snake_named_subobject_r(jsp, jo2p,
+ "alternate_controller");
+ sgj_convert_to_snake_name(aas_s, b, blen);
+ sgj_js_nv_ihexstr(jsp, jo3p, b, buff[12], NULL, d1);
+ sgj_convert_to_snake_name(vs_s, b, blen);
+ sgj_js_nv_ihexstr(jsp, jo3p, b, buff[13], NULL, d2);
+ }
+ }
+}
diff --git a/src/sg_vpd_common.h b/src/sg_vpd_common.h
index 50cdb48a..13134336 100644
--- a/src/sg_vpd_common.h
+++ b/src/sg_vpd_common.h
@@ -250,7 +250,19 @@ decode_lb_protection_vpd(const uint8_t * buff, int len, struct opts_t * op,
void
decode_tapealert_supported_vpd(const uint8_t * buff, int len,
struct opts_t * op, sgj_opaque_p jop);
+/* Share some vendor specific VPD pages as well */
+void
+decode_upr_vpd_c0_emc(uint8_t * buff, int len, struct opts_t * op,
+ sgj_opaque_p jop);
+void
+decode_rdac_vpd_c2(uint8_t * buff, int len, struct opts_t * op,
+ sgj_opaque_p jop);
+void
+decode_rdac_vpd_c9(uint8_t * buff, int len, struct opts_t * op,
+ sgj_opaque_p jop);
+
const char * pqual_str(int pqual);
+int no_ascii_4hex(const struct opts_t * op);
void svpd_enumerate_vendor(int vend_prod_num);
int svpd_count_vendor_vpds(int vpd_pn, int vend_prod_num);
diff --git a/src/sg_vpd_vendor.c b/src/sg_vpd_vendor.c
index 5cfc7ee3..156dd83b 100644
--- a/src/sg_vpd_vendor.c
+++ b/src/sg_vpd_vendor.c
@@ -111,17 +111,6 @@ dup_sanity_chk(int sz_opts_t, int sz_values_name_t)
sz_values_name_t);
}
-static int
-no_ascii_4hex(const struct opts_t * op)
-{
- if (op->do_hex < 2)
- return 1;
- else if (2 == op->do_hex)
- return 0;
- else
- return -1;
-}
-
static bool
is_like_pdt(int actual_pdt, const struct svpd_values_name_t * vnp)
{
@@ -350,127 +339,6 @@ decode_dev_beh_vpd_c3_sea(uint8_t * buff, int len)
printf(" Default number of cache segments: %d\n", buff[24]);
}
-static const char * lun_state_arr[] =
-{
- "LUN not bound or LUN_Z report",
- "LUN bound, but not owned by this SP",
- "LUN bound and owned by this SP",
-};
-
-static const char * ip_mgmt_arr[] =
-{
- "No IP access",
- "Reserved (undefined)",
- "via IPv4",
- "via IPv6",
-};
-
-static const char * sp_arr[] =
-{
- "SP A",
- "SP B",
-};
-
-static const char * lun_op_arr[] =
-{
- "Normal operations",
- "I/O Operations being rejected, SP reboot or NDU in progress",
-};
-
-static const char * failover_mode_arr[] =
-{
- "Legacy mode 0",
- "Unknown mode (1)",
- "Unknown mode (2)",
- "Unknown mode (3)",
- "Active/Passive (PNR) mode 1",
- "Unknown mode (5)",
- "Active/Active (ALUA) mode 4",
- "Unknown mode (7)",
- "Legacy mode 2",
- "Unknown mode (9)",
- "Unknown mode (10)",
- "Unknown mode (11)",
- "Unknown mode (12)",
- "Unknown mode (13)",
- "AIX Active/Passive (PAR) mode 3",
- "Unknown mode (15)",
-};
-
-static void
-decode_upr_vpd_c0_emc(uint8_t * buff, int len)
-{
- int k, ip_mgmt, vpp80, lun_z;
-
- if (len < 3) {
- pr2serr("EMC upr VPD page [0xc0]: length too short=%d\n", len);
- return;
- }
- if (buff[9] != 0x00) {
- pr2serr("Unsupported page revision %d, decoding not possible.\n",
- buff[9]);
- return;
- }
- printf(" LUN WWN: ");
- for (k = 0; k < 16; ++k)
- printf("%02x", buff[10 + k]);
- printf("\n");
- printf(" Array Serial Number: ");
- dStrRaw(&buff[50], buff[49]);
- printf("\n");
-
- printf(" LUN State: ");
- if (buff[4] > 0x02)
- printf("Unknown (%x)\n", buff[4]);
- else
- printf("%s\n", lun_state_arr[buff[4]]);
-
- printf(" This path connects to: ");
- if (buff[8] > 0x01)
- printf("Unknown SP (%x)", buff[8]);
- else
- printf("%s", sp_arr[buff[8]]);
- printf(", Port Number: %u\n", buff[7]);
-
- printf(" Default Owner: ");
- if (buff[5] > 0x01)
- printf("Unknown (%x)\n", buff[5]);
- else
- printf("%s\n", sp_arr[buff[5]]);
-
- printf(" NO_ATF: %s, Access Logix: %s\n",
- buff[6] & 0x80 ? "set" : "not set",
- buff[6] & 0x40 ? "supported" : "not supported");
-
- ip_mgmt = (buff[6] >> 4) & 0x3;
-
- printf(" SP IP Management Mode: %s\n", ip_mgmt_arr[ip_mgmt]);
- if (ip_mgmt == 2)
- printf(" SP IPv4 address: %u.%u.%u.%u\n",
- buff[44], buff[45], buff[46], buff[47]);
- else {
- printf(" SP IPv6 address: ");
- for (k = 0; k < 16; ++k)
- printf("%02x", buff[32 + k]);
- printf("\n");
- }
-
- vpp80 = buff[30] & 0x08;
- lun_z = buff[30] & 0x04;
-
- printf(" System Type: %x, Failover mode: %s\n",
- buff[27], failover_mode_arr[buff[28] & 0x0f]);
-
- printf(" Inquiry VPP 0x80 returns: %s, Arraycommpath: %s\n",
- vpp80 ? "array serial#" : "LUN serial#",
- lun_z ? "Set to 1" : "Unknown");
-
- printf(" Lun operations: %s\n",
- buff[48] > 1 ? "undefined" : lun_op_arr[buff[48]]);
-
- return;
-}
-
static void
decode_rdac_vpd_c0(uint8_t * buff, int len)
{
@@ -560,61 +428,6 @@ decode_rdac_vpd_c1(uint8_t * buff, int len)
}
static void
-decode_rdac_vpd_c2(uint8_t * buff, int len)
-{
- int i, n, v, r, m, p, d, y, num_part;
- char part[5];
-
- if (len < 3) {
- pr2serr("Software Version VPD page length too short=%d\n", len);
- return;
- }
- if (buff[4] != 's' && buff[5] != 'w' && buff[6] != 'r') {
- pr2serr("Invalid page identifier %c%c%c%c, decoding not possible.\n",
- buff[4], buff[5], buff[6], buff[7]);
- return;
- }
- printf(" Software Version: %02x.%02x.%02x\n", buff[8], buff[9], buff[10]);
- printf(" Software Date: %02d/%02d/%02d\n", buff[11], buff[12], buff[13]);
- printf(" Features:");
- if (buff[14] & 0x01)
- printf(" Dual Active,");
- if (buff[14] & 0x02)
- printf(" Series 3,");
- if (buff[14] & 0x04)
- printf(" Multiple Sub-enclosures,");
- if (buff[14] & 0x08)
- printf(" DCE/DRM/DSS/DVE,");
- if (buff[14] & 0x10)
- printf(" Asymmetric Logical Unit Access,");
- printf("\n");
- printf(" Max. #of LUNS: %d\n", buff[15]);
-
- num_part = (len - 12) / 16;
- n = 16;
- printf(" Partitions: %d\n", num_part);
- for (i = 0; i < num_part; i++) {
- memset(part,0, 5);
- memcpy(part, &buff[n], 4);
- printf(" Name: %s\n", part);
- n += 4;
- v = buff[n++];
- r = buff[n++];
- m = buff[n++];
- p = buff[n++];
- printf(" Version: %d.%d.%d.%d\n", v, r, m, p);
- m = buff[n++];
- d = buff[n++];
- y = buff[n++];
- printf(" Date: %d/%d/%d\n", m, d, y);
-
- n += 5;
- }
-
- return;
-}
-
-static void
decode_rdac_vpd_c3(uint8_t * buff, int len)
{
if (len < 0x2c) {
@@ -827,6 +640,7 @@ decode_rdac_vpd_c8(uint8_t * buff, int len)
return;
}
+#if 0
static void
decode_rdac_vpd_c9_rtpg_data(uint8_t aas, uint8_t vendor)
{
@@ -992,6 +806,7 @@ decode_rdac_vpd_c9(uint8_t * buff, int len)
decode_rdac_vpd_c9_rtpg_data(buff[12], buff[13]);
}
}
+#endif
static void
decode_rdac_vpd_ca(uint8_t * buff, int len)
@@ -1237,15 +1052,17 @@ int
svpd_decode_vendor(int sg_fd, struct opts_t * op, sgj_opaque_p jop, int off)
{
bool hex0 = (0 == op->do_hex);
+ bool as_json;
int len, pdt, plen, pn;
int alloc_len = op->maxlen;
int res = 0;
const struct svpd_values_name_t * vnp;
sgj_state * jsp = &op->json_st;
- sgj_opaque_p jo2p;
+ sgj_opaque_p jo2p = NULL;
uint8_t * rp;
char name[80];
+ as_json = jsp->pr_as_json;
pn = op->vpd_pn;
switch (pn) { /* VPD codes that we support vendor pages for */
case 0x3:
@@ -1300,9 +1117,12 @@ svpd_decode_vendor(int sg_fd, struct opts_t * op, sgj_opaque_p jop, int off)
hex2stdout(rp, len, no_ascii_4hex(op));
else if (VPD_VP_SEAGATE == op->vend_prod_num)
decode_firm_vpd_c0_sea(rp, len);
- else if (VPD_VP_EMC == op->vend_prod_num)
- decode_upr_vpd_c0_emc(rp, len);
- else if (VPD_VP_HP3PAR == op->vend_prod_num)
+ else if (VPD_VP_EMC == op->vend_prod_num) {
+ if (as_json)
+ jo2p = sg_vpd_js_hdr(jsp, jop,
+ "Unit serial number VPD page", rp);
+ decode_upr_vpd_c0_emc(rp, len, op, jo2p);
+ } else if (VPD_VP_HP3PAR == op->vend_prod_num)
decode_vpd_c0_hp3par(rp, len);
else if (VPD_VP_RDAC == op->vend_prod_num)
decode_rdac_vpd_c0(rp, len);
@@ -1332,9 +1152,12 @@ svpd_decode_vendor(int sg_fd, struct opts_t * op, sgj_opaque_p jop, int off)
case 0xc2:
if (! hex0)
hex2stdout(rp, len, no_ascii_4hex(op));
- else if (VPD_VP_RDAC == op->vend_prod_num)
- decode_rdac_vpd_c2(rp, len);
- else if (VPD_VP_HP_LTO == op->vend_prod_num)
+ else if (VPD_VP_RDAC == op->vend_prod_num) {
+ if (as_json)
+ jo2p = sg_vpd_js_hdr(jsp, jop,
+ "Software version VPD page", rp);
+ decode_rdac_vpd_c2(rp, len, op, jo2p);
+ } else if (VPD_VP_HP_LTO == op->vend_prod_num)
decode_hp_lto_vpd_cx(rp, len, pn);
else
res = SG_LIB_CAT_OTHER;
@@ -1380,9 +1203,12 @@ svpd_decode_vendor(int sg_fd, struct opts_t * op, sgj_opaque_p jop, int off)
case 0xc9:
if (! hex0)
hex2stdout(rp, len, no_ascii_4hex(op));
- else if (VPD_VP_RDAC == op->vend_prod_num)
- decode_rdac_vpd_c9(rp, len);
- else
+ else if (VPD_VP_RDAC == op->vend_prod_num) {
+ if (as_json)
+ jo2p = sg_vpd_js_hdr(jsp, jop,
+ "Volume access control VPD page", rp);
+ decode_rdac_vpd_c9(rp, len, op, jo2p);
+ } else
res = SG_LIB_CAT_OTHER;
break;
case 0xca:
@@ -1438,16 +1264,21 @@ svpd_decode_vendor(int sg_fd, struct opts_t * op, sgj_opaque_p jop, int off)
break;
} else {
int n = len - 16;
+ const char * np = "NVMe Identify Controller Response VPD page";
+ /* NVMe: Identify Controller data structure (CNS 01h) */
+ const char * ep = "(sg3_utils)";
if (n > 4096) {
pr2serr("NVMe Identify response expected to be "
"<= 4096 bytes (got: %d)\n", n);
break;
}
+ if (op->do_hex < 3)
+ sgj_pr_hr(jsp, "VPD INQUIRY: %s %s\n", np, ep);
if (op->do_hex)
hex2stdout(rp, len, no_ascii_4hex(op));
else if (jsp->pr_as_json) {
- jo2p = sg_vpd_js_hdr(jsp, jop, name, rp);
+ jo2p = sg_vpd_js_hdr(jsp, jop, np, rp);
sgj_js_nv_hex_bytes(jsp, jo2p, "response_bytes",
rp + 16, n);
} else