1*44704f69SBart Van Assche /*
2*44704f69SBart Van Assche * Copyright (c) 2006-2022 Douglas Gilbert.
3*44704f69SBart Van Assche * All rights reserved.
4*44704f69SBart Van Assche * Use of this source code is governed by a BSD-style
5*44704f69SBart Van Assche * license that can be found in the BSD_LICENSE file.
6*44704f69SBart Van Assche *
7*44704f69SBart Van Assche * SPDX-License-Identifier: BSD-2-Clause
8*44704f69SBart Van Assche */
9*44704f69SBart Van Assche
10*44704f69SBart Van Assche #include <unistd.h>
11*44704f69SBart Van Assche #include <fcntl.h>
12*44704f69SBart Van Assche #include <stdio.h>
13*44704f69SBart Van Assche #include <stdlib.h>
14*44704f69SBart Van Assche #include <stdarg.h>
15*44704f69SBart Van Assche #include <stdbool.h>
16*44704f69SBart Van Assche #include <string.h>
17*44704f69SBart Van Assche #include <ctype.h>
18*44704f69SBart Van Assche #include <assert.h>
19*44704f69SBart Van Assche #include <getopt.h>
20*44704f69SBart Van Assche #define __STDC_FORMAT_MACROS 1
21*44704f69SBart Van Assche #include <inttypes.h>
22*44704f69SBart Van Assche #include <errno.h>
23*44704f69SBart Van Assche #include <sys/types.h>
24*44704f69SBart Van Assche #include <sys/stat.h>
25*44704f69SBart Van Assche
26*44704f69SBart Van Assche #ifdef HAVE_CONFIG_H
27*44704f69SBart Van Assche #include "config.h"
28*44704f69SBart Van Assche #endif
29*44704f69SBart Van Assche
30*44704f69SBart Van Assche #include "sg_lib.h"
31*44704f69SBart Van Assche #include "sg_lib_data.h"
32*44704f69SBart Van Assche #include "sg_cmds_basic.h"
33*44704f69SBart Van Assche #include "sg_unaligned.h"
34*44704f69SBart Van Assche #include "sg_pr2serr.h"
35*44704f69SBart Van Assche
36*44704f69SBart Van Assche #include "sg_vpd_common.h"
37*44704f69SBart Van Assche
38*44704f69SBart Van Assche /* This file holds common code for sg_inq and sg_vpd as both those utilities
39*44704f69SBart Van Assche * decode SCSI VPD pages. */
40*44704f69SBart Van Assche
41*44704f69SBart Van Assche const char * t10_vendor_id_hr = "T10_vendor_identification";
42*44704f69SBart Van Assche const char * t10_vendor_id_js = "t10_vendor_identification";
43*44704f69SBart Van Assche const char * product_id_hr = "Product_identification";
44*44704f69SBart Van Assche const char * product_id_js = "product_identification";
45*44704f69SBart Van Assche const char * product_rev_lev_hr = "Product_revision_level";
46*44704f69SBart Van Assche const char * product_rev_lev_js = "product_revision_level";
47*44704f69SBart Van Assche static const char * const y_s = "yes";
48*44704f69SBart Van Assche static const char * const n_s = "no";
49*44704f69SBart Van Assche static const char * const nl_s = "no limit";
50*44704f69SBart Van Assche static const char * const nlr_s = "no limit reported";
51*44704f69SBart Van Assche /* Earlier gcc compilers (e.g. 6.4) don't accept this first form when it is
52*44704f69SBart Van Assche * used in another array of strings initialization (e.g. bdc_zoned_strs) */
53*44704f69SBart Van Assche // static const char * const nr_s = "not reported";
54*44704f69SBart Van Assche static char nr_s[] = "not reported";
55*44704f69SBart Van Assche static const char * const ns_s = "not supported";
56*44704f69SBart Van Assche // static const char * const rsv_s = "Reserved";
57*44704f69SBart Van Assche static char rsv_s[] = "Reserved";
58*44704f69SBart Van Assche static const char * const vs_s = "Vendor specific";
59*44704f69SBart Van Assche static const char * const null_s = "";
60*44704f69SBart Van Assche static const char * const mn_s = "meaning";
61*44704f69SBart Van Assche
62*44704f69SBart Van Assche /* Supported vendor specific VPD pages */
63*44704f69SBart Van Assche /* Arrange in alphabetical order by acronym */
64*44704f69SBart Van Assche struct svpd_vp_name_t vp_arr[] = {
65*44704f69SBart Van Assche {VPD_VP_DDS, "dds", "DDS tape family from IBM"},
66*44704f69SBart Van Assche {VPD_VP_EMC, "emc", "EMC (company)"},
67*44704f69SBart Van Assche {VPD_VP_WDC_HITACHI, "hit", "WDC/Hitachi disk"},
68*44704f69SBart Van Assche {VPD_VP_HP3PAR, "hp3par", "3PAR array (HP was Left Hand)"},
69*44704f69SBart Van Assche {VPD_VP_HP_LTO, "hp_lto", "HP LTO tape/systems"},
70*44704f69SBart Van Assche {VPD_VP_IBM_LTO, "ibm_lto", "IBM LTO tape/systems"},
71*44704f69SBart Van Assche {VPD_VP_NVME, "nvme", "NVMe related"},
72*44704f69SBart Van Assche {VPD_VP_RDAC, "rdac", "RDAC array (NetApp E-Series)"},
73*44704f69SBart Van Assche {VPD_VP_SEAGATE, "sea", "Seagate disk"},
74*44704f69SBart Van Assche {VPD_VP_SG, "sg", "sg3_utils extensions"},
75*44704f69SBart Van Assche {VPD_VP_WDC_HITACHI, "wdc", "WDC/Hitachi disk"},
76*44704f69SBart Van Assche {0, NULL, NULL},
77*44704f69SBart Van Assche };
78*44704f69SBart Van Assche
79*44704f69SBart Van Assche /* Supported vendor specific VPD pages */
80*44704f69SBart Van Assche /* 'subvalue' holds vendor/product number to disambiguate */
81*44704f69SBart Van Assche /* Arrange in alphabetical order by acronym */
82*44704f69SBart Van Assche struct svpd_values_name_t vendor_vpd_pg[] = {
83*44704f69SBart Van Assche {VPD_V_ACI_LTO, VPD_VP_HP_LTO, 1, "aci", "ACI revision level (HP LTO)"},
84*44704f69SBart Van Assche {VPD_V_DATC_SEA, VPD_VP_SEAGATE, 0, "datc", "Date code (Seagate)"},
85*44704f69SBart Van Assche {VPD_V_DCRL_LTO, VPD_VP_IBM_LTO, 1, "dcrl", "Drive component revision "
86*44704f69SBart Van Assche "levels (IBM LTO)"},
87*44704f69SBart Van Assche {VPD_V_FVER_DDS, VPD_VP_DDS, 1, "ddsver", "Firmware revision (DDS)"},
88*44704f69SBart Van Assche {VPD_V_DEV_BEH_SEA, VPD_VP_SEAGATE, 0, "devb", "Device behavior "
89*44704f69SBart Van Assche "(Seagate)"},
90*44704f69SBart Van Assche {VPD_V_DSN_LTO, VPD_VP_IBM_LTO, 1, "dsn", "Drive serial numbers (IBM "
91*44704f69SBart Van Assche "LTO)"},
92*44704f69SBart Van Assche {VPD_V_DUCD_LTO, VPD_VP_IBM_LTO, 1, "ducd", "Device unique "
93*44704f69SBart Van Assche "configuration data (IBM LTO)"},
94*44704f69SBart Van Assche {VPD_V_EDID_RDAC, VPD_VP_RDAC, 0, "edid", "Extended device "
95*44704f69SBart Van Assche "identification (RDAC)"},
96*44704f69SBart Van Assche {VPD_V_FIRM_SEA, VPD_VP_SEAGATE, 0, "firm", "Firmware numbers "
97*44704f69SBart Van Assche "(Seagate)"},
98*44704f69SBart Van Assche {VPD_V_FVER_LTO, VPD_VP_HP_LTO, 0, "frl", "Firmware revision level "
99*44704f69SBart Van Assche "(HP LTO)"},
100*44704f69SBart Van Assche {VPD_V_FVER_RDAC, VPD_VP_RDAC, 0, "fwr4", "Firmware version (RDAC)"},
101*44704f69SBart Van Assche {VPD_V_HEAD_LTO, VPD_VP_HP_LTO, 1, "head", "Head Assy revision level "
102*44704f69SBart Van Assche "(HP LTO)"},
103*44704f69SBart Van Assche {VPD_V_HP3PAR, VPD_VP_HP3PAR, 0, "hp3par", "Volume information "
104*44704f69SBart Van Assche "(HP/3PAR)"},
105*44704f69SBart Van Assche {VPD_V_HVER_LTO, VPD_VP_HP_LTO, 1, "hrl", "Hardware revision level "
106*44704f69SBart Van Assche "(HP LTO)"},
107*44704f69SBart Van Assche {VPD_V_HVER_RDAC, VPD_VP_RDAC, 0, "hwr4", "Hardware version (RDAC)"},
108*44704f69SBart Van Assche {VPD_V_JUMP_SEA, VPD_VP_SEAGATE, 0, "jump", "Jump setting (Seagate)"},
109*44704f69SBart Van Assche {VPD_V_MECH_LTO, VPD_VP_HP_LTO, 1, "mech", "Mechanism revision level "
110*44704f69SBart Van Assche "(HP LTO)"},
111*44704f69SBart Van Assche {VPD_V_MPDS_LTO, VPD_VP_IBM_LTO, 1, "mpds", "Mode parameter default "
112*44704f69SBart Van Assche "settings (IBM LTO)"},
113*44704f69SBart Van Assche {SG_NVME_VPD_NICR, VPD_VP_SG, 0, "nicr",
114*44704f69SBart Van Assche "NVMe Identify Controller Response (sg3_utils)"},
115*44704f69SBart Van Assche {VPD_V_PCA_LTO, VPD_VP_HP_LTO, 1, "pca", "PCA revision level (HP LTO)"},
116*44704f69SBart Van Assche {VPD_V_FEAT_RDAC, VPD_VP_RDAC, 0, "prm4", "Feature Parameters (RDAC)"},
117*44704f69SBart Van Assche {VPD_V_RVSI_RDAC, VPD_VP_RDAC, 0, "rvsi", "Replicated volume source "
118*44704f69SBart Van Assche "identifier (RDAC)"},
119*44704f69SBart Van Assche {VPD_V_SAID_RDAC, VPD_VP_RDAC, 0, "said", "Storage array world wide "
120*44704f69SBart Van Assche "name (RDAC)"},
121*44704f69SBart Van Assche {VPD_V_SUBS_RDAC, VPD_VP_RDAC, 0, "subs", "Subsystem identifier (RDAC)"},
122*44704f69SBart Van Assche {VPD_V_SVER_RDAC, VPD_VP_RDAC, 0, "swr4", "Software version (RDAC)"},
123*44704f69SBart Van Assche {VPD_V_UPR_EMC, VPD_VP_EMC, 0, "upr", "Unit path report (EMC)"},
124*44704f69SBart Van Assche {VPD_V_VAC_RDAC, VPD_VP_RDAC, 0, "vac1", "Volume access control (RDAC)"},
125*44704f69SBart Van Assche {VPD_V_HIT_PG3, VPD_VP_WDC_HITACHI, 0, "wp3", "Page 0x3 (WDC/Hitachi)"},
126*44704f69SBart Van Assche {VPD_V_HIT_PG_D1, VPD_VP_WDC_HITACHI, 0, "wpd1",
127*44704f69SBart Van Assche "Page 0xd1 (WDC/Hitachi)"},
128*44704f69SBart Van Assche {VPD_V_HIT_PG_D2, VPD_VP_WDC_HITACHI, 0, "wpd2",
129*44704f69SBart Van Assche "Page 0xd2 (WDC/Hitachi)"},
130*44704f69SBart Van Assche {0, 0, 0, NULL, NULL},
131*44704f69SBart Van Assche };
132*44704f69SBart Van Assche
133*44704f69SBart Van Assche
134*44704f69SBart Van Assche int
no_ascii_4hex(const struct opts_t * op)135*44704f69SBart Van Assche no_ascii_4hex(const struct opts_t * op)
136*44704f69SBart Van Assche {
137*44704f69SBart Van Assche if (op->do_hex < 2)
138*44704f69SBart Van Assche return 1;
139*44704f69SBart Van Assche else if (2 == op->do_hex)
140*44704f69SBart Van Assche return 0;
141*44704f69SBart Van Assche else
142*44704f69SBart Van Assche return -1;
143*44704f69SBart Van Assche }
144*44704f69SBart Van Assche
145*44704f69SBart Van Assche int
svpd_find_vp_num_by_acron(const char * vp_ap)146*44704f69SBart Van Assche svpd_find_vp_num_by_acron(const char * vp_ap)
147*44704f69SBart Van Assche {
148*44704f69SBart Van Assche size_t len;
149*44704f69SBart Van Assche const struct svpd_vp_name_t * vpp;
150*44704f69SBart Van Assche
151*44704f69SBart Van Assche for (vpp = vp_arr; vpp->acron; ++vpp) {
152*44704f69SBart Van Assche len = strlen(vpp->acron);
153*44704f69SBart Van Assche if (0 == strncmp(vpp->acron, vp_ap, len))
154*44704f69SBart Van Assche return vpp->vend_prod_num;
155*44704f69SBart Van Assche }
156*44704f69SBart Van Assche return -1;
157*44704f69SBart Van Assche }
158*44704f69SBart Van Assche
159*44704f69SBart Van Assche /* if vend_prod_num < -1 then list vendor_product ids + vendor pages, =-1
160*44704f69SBart Van Assche * list only vendor_product ids, else list pages for that vend_prod_num */
161*44704f69SBart Van Assche void
svpd_enumerate_vendor(int vend_prod_num)162*44704f69SBart Van Assche svpd_enumerate_vendor(int vend_prod_num)
163*44704f69SBart Van Assche {
164*44704f69SBart Van Assche bool seen;
165*44704f69SBart Van Assche const struct svpd_vp_name_t * vpp;
166*44704f69SBart Van Assche const struct svpd_values_name_t * vnp;
167*44704f69SBart Van Assche
168*44704f69SBart Van Assche if (vend_prod_num < 0) {
169*44704f69SBart Van Assche for (seen = false, vpp = vp_arr; vpp->acron; ++vpp) {
170*44704f69SBart Van Assche if (vpp->name) {
171*44704f69SBart Van Assche if (! seen) {
172*44704f69SBart Van Assche printf("\nVendor/product identifiers:\n");
173*44704f69SBart Van Assche seen = true;
174*44704f69SBart Van Assche }
175*44704f69SBart Van Assche printf(" %-10s %d %s\n", vpp->acron,
176*44704f69SBart Van Assche vpp->vend_prod_num, vpp->name);
177*44704f69SBart Van Assche }
178*44704f69SBart Van Assche }
179*44704f69SBart Van Assche }
180*44704f69SBart Van Assche if (-1 == vend_prod_num)
181*44704f69SBart Van Assche return;
182*44704f69SBart Van Assche for (seen = false, vnp = vendor_vpd_pg; vnp->acron; ++vnp) {
183*44704f69SBart Van Assche if ((vend_prod_num >= 0) && (vend_prod_num != vnp->subvalue))
184*44704f69SBart Van Assche continue;
185*44704f69SBart Van Assche if (vnp->name) {
186*44704f69SBart Van Assche if (! seen) {
187*44704f69SBart Van Assche printf("\nVendor specific VPD pages:\n");
188*44704f69SBart Van Assche seen = true;
189*44704f69SBart Van Assche }
190*44704f69SBart Van Assche printf(" %-10s 0x%02x,%d %s\n", vnp->acron,
191*44704f69SBart Van Assche vnp->value, vnp->subvalue, vnp->name);
192*44704f69SBart Van Assche }
193*44704f69SBart Van Assche }
194*44704f69SBart Van Assche }
195*44704f69SBart Van Assche
196*44704f69SBart Van Assche /* mxlen is command line --maxlen=LEN option (def: 0) or -1 for a VPD page
197*44704f69SBart Van Assche * with a short length (1 byte). Returns 0 for success. */
198*44704f69SBart Van Assche int /* global: use by sg_vpd_vendor.c */
vpd_fetch_page(int sg_fd,uint8_t * rp,int page,int mxlen,bool qt,int vb,int * rlenp)199*44704f69SBart Van Assche vpd_fetch_page(int sg_fd, uint8_t * rp, int page, int mxlen, bool qt,
200*44704f69SBart Van Assche int vb, int * rlenp)
201*44704f69SBart Van Assche {
202*44704f69SBart Van Assche int res, resid, rlen, len, n;
203*44704f69SBart Van Assche
204*44704f69SBart Van Assche if (sg_fd < 0) {
205*44704f69SBart Van Assche len = sg_get_unaligned_be16(rp + 2) + 4;
206*44704f69SBart Van Assche if (vb && (len > mxlen))
207*44704f69SBart Van Assche pr2serr("warning: VPD page's length (%d) > bytes in --inhex=FN "
208*44704f69SBart Van Assche "file (%d)\n", len , mxlen);
209*44704f69SBart Van Assche if (rlenp)
210*44704f69SBart Van Assche *rlenp = (len < mxlen) ? len : mxlen;
211*44704f69SBart Van Assche return 0;
212*44704f69SBart Van Assche }
213*44704f69SBart Van Assche if (mxlen > MX_ALLOC_LEN) {
214*44704f69SBart Van Assche pr2serr("--maxlen=LEN too long: %d > %d\n", mxlen, MX_ALLOC_LEN);
215*44704f69SBart Van Assche return SG_LIB_SYNTAX_ERROR;
216*44704f69SBart Van Assche }
217*44704f69SBart Van Assche n = (mxlen > 0) ? mxlen : DEF_ALLOC_LEN;
218*44704f69SBart Van Assche res = sg_ll_inquiry_v2(sg_fd, true, page, rp, n, DEF_PT_TIMEOUT, &resid,
219*44704f69SBart Van Assche ! qt, vb);
220*44704f69SBart Van Assche if (res)
221*44704f69SBart Van Assche return res;
222*44704f69SBart Van Assche rlen = n - resid;
223*44704f69SBart Van Assche if (rlen < 4) {
224*44704f69SBart Van Assche pr2serr("VPD response too short (len=%d)\n", rlen);
225*44704f69SBart Van Assche return SG_LIB_CAT_MALFORMED;
226*44704f69SBart Van Assche }
227*44704f69SBart Van Assche if (page != rp[1]) {
228*44704f69SBart Van Assche pr2serr("invalid VPD response; probably a STANDARD INQUIRY "
229*44704f69SBart Van Assche "response\n");
230*44704f69SBart Van Assche n = (rlen < 32) ? rlen : 32;
231*44704f69SBart Van Assche if (vb) {
232*44704f69SBart Van Assche pr2serr("First %d bytes of bad response\n", n);
233*44704f69SBart Van Assche hex2stderr(rp, n, 0);
234*44704f69SBart Van Assche }
235*44704f69SBart Van Assche return SG_LIB_CAT_MALFORMED;
236*44704f69SBart Van Assche } else if ((0x80 == page) && (0x2 == rp[2]) && (0x2 == rp[3])) {
237*44704f69SBart Van Assche /* could be a Unit Serial number VPD page with a very long
238*44704f69SBart Van Assche * length of 4+514 bytes; more likely standard response for
239*44704f69SBart Van Assche * SCSI-2, RMB=1 and a response_data_format of 0x2. */
240*44704f69SBart Van Assche pr2serr("invalid Unit Serial Number VPD response; probably a "
241*44704f69SBart Van Assche "STANDARD INQUIRY response\n");
242*44704f69SBart Van Assche return SG_LIB_CAT_MALFORMED;
243*44704f69SBart Van Assche }
244*44704f69SBart Van Assche if (mxlen < 0)
245*44704f69SBart Van Assche len = rp[3] + 4;
246*44704f69SBart Van Assche else
247*44704f69SBart Van Assche len = sg_get_unaligned_be16(rp + 2) + 4;
248*44704f69SBart Van Assche if (len <= rlen) {
249*44704f69SBart Van Assche if (rlenp)
250*44704f69SBart Van Assche *rlenp = len;
251*44704f69SBart Van Assche return 0;
252*44704f69SBart Van Assche } else if (mxlen) {
253*44704f69SBart Van Assche if (rlenp)
254*44704f69SBart Van Assche *rlenp = rlen;
255*44704f69SBart Van Assche return 0;
256*44704f69SBart Van Assche }
257*44704f69SBart Van Assche if (len > MX_ALLOC_LEN) {
258*44704f69SBart Van Assche pr2serr("response length too long: %d > %d\n", len, MX_ALLOC_LEN);
259*44704f69SBart Van Assche return SG_LIB_CAT_MALFORMED;
260*44704f69SBart Van Assche } else {
261*44704f69SBart Van Assche res = sg_ll_inquiry_v2(sg_fd, true, page, rp, len, DEF_PT_TIMEOUT,
262*44704f69SBart Van Assche &resid, ! qt, vb);
263*44704f69SBart Van Assche if (res)
264*44704f69SBart Van Assche return res;
265*44704f69SBart Van Assche rlen = len - resid;
266*44704f69SBart Van Assche /* assume it is well behaved: hence page and len still same */
267*44704f69SBart Van Assche if (rlenp)
268*44704f69SBart Van Assche *rlenp = rlen;
269*44704f69SBart Van Assche return 0;
270*44704f69SBart Van Assche }
271*44704f69SBart Van Assche }
272*44704f69SBart Van Assche
273*44704f69SBart Van Assche sgj_opaque_p
sg_vpd_js_hdr(sgj_state * jsp,sgj_opaque_p jop,const char * name,const uint8_t * vpd_hdrp)274*44704f69SBart Van Assche sg_vpd_js_hdr(sgj_state * jsp, sgj_opaque_p jop, const char * name,
275*44704f69SBart Van Assche const uint8_t * vpd_hdrp)
276*44704f69SBart Van Assche {
277*44704f69SBart Van Assche int pdt = vpd_hdrp[0] & PDT_MASK;
278*44704f69SBart Van Assche int pqual = (vpd_hdrp[0] & 0xe0) >> 5;
279*44704f69SBart Van Assche int pn = vpd_hdrp[1];
280*44704f69SBart Van Assche const char * pdt_str;
281*44704f69SBart Van Assche sgj_opaque_p jo2p = sgj_snake_named_subobject_r(jsp, jop, name);
282*44704f69SBart Van Assche char d[64];
283*44704f69SBart Van Assche
284*44704f69SBart Van Assche pdt_str = sg_get_pdt_str(pdt, sizeof(d), d);
285*44704f69SBart Van Assche sgj_js_nv_ihexstr(jsp, jo2p, "peripheral_qualifier",
286*44704f69SBart Van Assche pqual, NULL, pqual_str(pqual));
287*44704f69SBart Van Assche sgj_js_nv_ihexstr(jsp, jo2p, "peripheral_device_type",
288*44704f69SBart Van Assche pdt, NULL, pdt_str);
289*44704f69SBart Van Assche sgj_js_nv_ihex(jsp, jo2p, "page_code", pn);
290*44704f69SBart Van Assche return jo2p;
291*44704f69SBart Van Assche }
292*44704f69SBart Van Assche
293*44704f69SBart Van Assche const char *
pqual_str(int pqual)294*44704f69SBart Van Assche pqual_str(int pqual)
295*44704f69SBart Van Assche {
296*44704f69SBart Van Assche switch (pqual) {
297*44704f69SBart Van Assche case 0:
298*44704f69SBart Van Assche return "LU accessible";
299*44704f69SBart Van Assche case 1:
300*44704f69SBart Van Assche return "LU temporarily unavailable";
301*44704f69SBart Van Assche case 3:
302*44704f69SBart Van Assche return "LU not accessible via this port";
303*44704f69SBart Van Assche default:
304*44704f69SBart Van Assche return "value reserved by T10";
305*44704f69SBart Van Assche }
306*44704f69SBart Van Assche }
307*44704f69SBart Van Assche
308*44704f69SBart Van Assche static const char * network_service_type_arr[] =
309*44704f69SBart Van Assche {
310*44704f69SBart Van Assche "unspecified",
311*44704f69SBart Van Assche "storage configuration service",
312*44704f69SBart Van Assche "diagnostics",
313*44704f69SBart Van Assche "status",
314*44704f69SBart Van Assche "logging",
315*44704f69SBart Van Assche "code download",
316*44704f69SBart Van Assche "copy service",
317*44704f69SBart Van Assche "administrative configuration service",
318*44704f69SBart Van Assche "reserved[0x8]", "reserved[0x9]",
319*44704f69SBart Van Assche "reserved[0xa]", "reserved[0xb]", "reserved[0xc]", "reserved[0xd]",
320*44704f69SBart Van Assche "reserved[0xe]", "reserved[0xf]", "reserved[0x10]", "reserved[0x11]",
321*44704f69SBart Van Assche "reserved[0x12]", "reserved[0x13]", "reserved[0x14]", "reserved[0x15]",
322*44704f69SBart Van Assche "reserved[0x16]", "reserved[0x17]", "reserved[0x18]", "reserved[0x19]",
323*44704f69SBart Van Assche "reserved[0x1a]", "reserved[0x1b]", "reserved[0x1c]", "reserved[0x1d]",
324*44704f69SBart Van Assche "reserved[0x1e]", "reserved[0x1f]",
325*44704f69SBart Van Assche };
326*44704f69SBart Van Assche
327*44704f69SBart Van Assche /* VPD_MAN_NET_ADDR 0x85 ["mna"] */
328*44704f69SBart Van Assche void
decode_net_man_vpd(const uint8_t * buff,int len,struct opts_t * op,sgj_opaque_p jap)329*44704f69SBart Van Assche decode_net_man_vpd(const uint8_t * buff, int len, struct opts_t * op,
330*44704f69SBart Van Assche sgj_opaque_p jap)
331*44704f69SBart Van Assche {
332*44704f69SBart Van Assche int k, bump, na_len, assoc, nst;
333*44704f69SBart Van Assche sgj_state * jsp = &op->json_st;
334*44704f69SBart Van Assche sgj_opaque_p jo2p;
335*44704f69SBart Van Assche const uint8_t * bp;
336*44704f69SBart Van Assche const char * assoc_str;
337*44704f69SBart Van Assche const char * nst_str;
338*44704f69SBart Van Assche
339*44704f69SBart Van Assche if ((1 == op->do_hex) || (op->do_hex > 2)) {
340*44704f69SBart Van Assche hex2stdout(buff, len, (1 == op->do_hex) ? 0 : -1);
341*44704f69SBart Van Assche return;
342*44704f69SBart Van Assche }
343*44704f69SBart Van Assche if (len < 4) {
344*44704f69SBart Van Assche pr2serr("Management network addresses VPD page length too short=%d\n",
345*44704f69SBart Van Assche len);
346*44704f69SBart Van Assche return;
347*44704f69SBart Van Assche }
348*44704f69SBart Van Assche len -= 4;
349*44704f69SBart Van Assche bp = buff + 4;
350*44704f69SBart Van Assche for (k = 0; k < len; k += bump, bp += bump) {
351*44704f69SBart Van Assche assoc = (bp[0] >> 5) & 0x3;
352*44704f69SBart Van Assche assoc_str = sg_get_desig_assoc_str(assoc);
353*44704f69SBart Van Assche nst = bp[0] & 0x1f;
354*44704f69SBart Van Assche nst_str = network_service_type_arr[nst];
355*44704f69SBart Van Assche sgj_pr_hr(jsp, " %s, Service type: %s\n", assoc_str, nst_str);
356*44704f69SBart Van Assche na_len = sg_get_unaligned_be16(bp + 2);
357*44704f69SBart Van Assche if (jsp->pr_as_json) {
358*44704f69SBart Van Assche jo2p = sgj_new_unattached_object_r(jsp);
359*44704f69SBart Van Assche sgj_js_nv_ihexstr(jsp, jo2p, "association", assoc, NULL,
360*44704f69SBart Van Assche assoc_str);
361*44704f69SBart Van Assche sgj_js_nv_ihexstr(jsp, jo2p, "service_type", nst, NULL,
362*44704f69SBart Van Assche nst_str);
363*44704f69SBart Van Assche sgj_js_nv_s_len(jsp, jo2p, "network_address",
364*44704f69SBart Van Assche (const char *)(bp + 4), na_len);
365*44704f69SBart Van Assche sgj_js_nv_o(jsp, jap, NULL /* name */, jo2p);
366*44704f69SBart Van Assche }
367*44704f69SBart Van Assche if (na_len > 0) {
368*44704f69SBart Van Assche if (op->do_hex > 1) {
369*44704f69SBart Van Assche sgj_pr_hr(jsp, " Network address:\n");
370*44704f69SBart Van Assche hex2stdout((bp + 4), na_len, 0);
371*44704f69SBart Van Assche } else
372*44704f69SBart Van Assche sgj_pr_hr(jsp, " %s\n", bp + 4);
373*44704f69SBart Van Assche }
374*44704f69SBart Van Assche bump = 4 + na_len;
375*44704f69SBart Van Assche if ((k + bump) > len) {
376*44704f69SBart Van Assche pr2serr("Management network addresses VPD page, short "
377*44704f69SBart Van Assche "descriptor length=%d, left=%d\n", bump, (len - k));
378*44704f69SBart Van Assche return;
379*44704f69SBart Van Assche }
380*44704f69SBart Van Assche }
381*44704f69SBart Van Assche }
382*44704f69SBart Van Assche
383*44704f69SBart Van Assche /* VPD_EXT_INQ Extended Inquiry VPD ["ei"] */
384*44704f69SBart Van Assche void
decode_x_inq_vpd(const uint8_t * b,int len,bool protect,struct opts_t * op,sgj_opaque_p jop)385*44704f69SBart Van Assche decode_x_inq_vpd(const uint8_t * b, int len, bool protect, struct opts_t * op,
386*44704f69SBart Van Assche sgj_opaque_p jop)
387*44704f69SBart Van Assche {
388*44704f69SBart Van Assche bool do_long_nq = op->do_long && (! op->do_quiet);
389*44704f69SBart Van Assche int n;
390*44704f69SBart Van Assche sgj_state * jsp = &op->json_st;
391*44704f69SBart Van Assche sgj_opaque_p jo2p;
392*44704f69SBart Van Assche const char * cp;
393*44704f69SBart Van Assche const char * np;
394*44704f69SBart Van Assche const char * nex_p;
395*44704f69SBart Van Assche char d[128];
396*44704f69SBart Van Assche static const int dlen = sizeof(d);
397*44704f69SBart Van Assche
398*44704f69SBart Van Assche if (len < 7) {
399*44704f69SBart Van Assche pr2serr("Extended INQUIRY data VPD page length too short=%d\n", len);
400*44704f69SBart Van Assche return;
401*44704f69SBart Van Assche }
402*44704f69SBart Van Assche if (op->do_hex) {
403*44704f69SBart Van Assche hex2stdout(b, len, (1 == op->do_hex) ? 0 : -1);
404*44704f69SBart Van Assche return;
405*44704f69SBart Van Assche }
406*44704f69SBart Van Assche if (do_long_nq || jsp->pr_as_json) {
407*44704f69SBart Van Assche n = (b[4] >> 6) & 0x3;
408*44704f69SBart Van Assche if (1 == n)
409*44704f69SBart Van Assche cp = "before final WRITE BUFFER";
410*44704f69SBart Van Assche else if (2 == n)
411*44704f69SBart Van Assche cp = "after power on or hard reset";
412*44704f69SBart Van Assche else {
413*44704f69SBart Van Assche cp = "none";
414*44704f69SBart Van Assche d[0] = '\0';
415*44704f69SBart Van Assche }
416*44704f69SBart Van Assche if (cp[0])
417*44704f69SBart Van Assche snprintf(d, dlen, " [%s]", cp);
418*44704f69SBart Van Assche sgj_pr_hr(jsp, " ACTIVATE_MICROCODE=%d%s\n", n, d);
419*44704f69SBart Van Assche sgj_js_nv_ihexstr(jsp, jop, "activate_microcode", n, NULL, cp);
420*44704f69SBart Van Assche n = (b[4] >> 3) & 0x7;
421*44704f69SBart Van Assche if (protect) {
422*44704f69SBart Van Assche switch (n)
423*44704f69SBart Van Assche {
424*44704f69SBart Van Assche case 0:
425*44704f69SBart Van Assche cp = "protection type 1 supported";
426*44704f69SBart Van Assche break;
427*44704f69SBart Van Assche case 1:
428*44704f69SBart Van Assche cp = "protection types 1 and 2 supported";
429*44704f69SBart Van Assche break;
430*44704f69SBart Van Assche case 2:
431*44704f69SBart Van Assche cp = "protection type 2 supported";
432*44704f69SBart Van Assche break;
433*44704f69SBart Van Assche case 3:
434*44704f69SBart Van Assche cp = "protection types 1 and 3 supported";
435*44704f69SBart Van Assche break;
436*44704f69SBart Van Assche case 4:
437*44704f69SBart Van Assche cp = "protection type 3 supported";
438*44704f69SBart Van Assche break;
439*44704f69SBart Van Assche case 5:
440*44704f69SBart Van Assche cp = "protection types 2 and 3 supported";
441*44704f69SBart Van Assche break;
442*44704f69SBart Van Assche case 6:
443*44704f69SBart Van Assche cp = "see Supported block lengths and protection types "
444*44704f69SBart Van Assche "VPD page";
445*44704f69SBart Van Assche break;
446*44704f69SBart Van Assche case 7:
447*44704f69SBart Van Assche cp = "protection types 1, 2 and 3 supported";
448*44704f69SBart Van Assche break;
449*44704f69SBart Van Assche }
450*44704f69SBart Van Assche } else if (op->protect_not_sure) {
451*44704f69SBart Van Assche cp = "Unsure because unable to read PROTECT bit in standard "
452*44704f69SBart Van Assche "INQUIRY response";
453*44704f69SBart Van Assche d[0] = '\0';
454*44704f69SBart Van Assche } else {
455*44704f69SBart Van Assche cp = "none";
456*44704f69SBart Van Assche d[0] = '\0';
457*44704f69SBart Van Assche }
458*44704f69SBart Van Assche if (cp[0])
459*44704f69SBart Van Assche snprintf(d, dlen, " [%s]", cp);
460*44704f69SBart Van Assche sgj_pr_hr(jsp, " SPT=%d%s\n", n, d);
461*44704f69SBart Van Assche sgj_js_nv_ihexstr_nex(jsp, jop, "spt", n, false, NULL,
462*44704f69SBart Van Assche cp, "Supported Protection Type");
463*44704f69SBart Van Assche sgj_haj_vi_nex(jsp, jop, 2, "GRD_CHK", SGJ_SEP_EQUAL_NO_SPACE,
464*44704f69SBart Van Assche !!(b[4] & 0x4), false, "guard check");
465*44704f69SBart Van Assche sgj_haj_vi_nex(jsp, jop, 2, "APP_CHK", SGJ_SEP_EQUAL_NO_SPACE,
466*44704f69SBart Van Assche !!(b[4] & 0x2), false, "application tag check");
467*44704f69SBart Van Assche sgj_haj_vi_nex(jsp, jop, 2, "REF_CHK", SGJ_SEP_EQUAL_NO_SPACE,
468*44704f69SBart Van Assche !!(b[4] & 0x1), false, "reference tag check");
469*44704f69SBart Van Assche sgj_haj_vi_nex(jsp, jop, 2, "UASK_SUP", SGJ_SEP_EQUAL_NO_SPACE,
470*44704f69SBart Van Assche !!(b[5] & 0x20), false, "Unit Attention "
471*44704f69SBart Van Assche "condition Sense Key specific data Supported");
472*44704f69SBart Van Assche sgj_haj_vi_nex(jsp, jop, 2, "GROUP_SUP", SGJ_SEP_EQUAL_NO_SPACE,
473*44704f69SBart Van Assche !!(b[5] & 0x10), false, "grouping function supported");
474*44704f69SBart Van Assche sgj_haj_vi_nex(jsp, jop, 2, "PRIOR_SUP", SGJ_SEP_EQUAL_NO_SPACE,
475*44704f69SBart Van Assche !!(b[5] & 0x8), false, "priority supported");
476*44704f69SBart Van Assche sgj_haj_vi_nex(jsp, jop, 2, "HEADSUP", SGJ_SEP_EQUAL_NO_SPACE,
477*44704f69SBart Van Assche !!(b[5] & 0x4), false, "head of queue supported");
478*44704f69SBart Van Assche sgj_haj_vi_nex(jsp, jop, 2, "ORDSUP", SGJ_SEP_EQUAL_NO_SPACE,
479*44704f69SBart Van Assche !!(b[5] & 0x2), false, "ordered (task attribute) "
480*44704f69SBart Van Assche "supported");
481*44704f69SBart Van Assche sgj_haj_vi_nex(jsp, jop, 2, "SIMPSUP", SGJ_SEP_EQUAL_NO_SPACE,
482*44704f69SBart Van Assche !!(b[5] & 0x1), false, "simple (task attribute) "
483*44704f69SBart Van Assche "supported");
484*44704f69SBart Van Assche sgj_haj_vi_nex(jsp, jop, 2, "WU_SUP", SGJ_SEP_EQUAL_NO_SPACE,
485*44704f69SBart Van Assche !!(b[6] & 0x8), false, "Write uncorrectable "
486*44704f69SBart Van Assche "supported");
487*44704f69SBart Van Assche sgj_haj_vi_nex(jsp, jop, 2, "CRD_SUP", SGJ_SEP_EQUAL_NO_SPACE,
488*44704f69SBart Van Assche !!(b[6] & 0x4), false, "Correction disable "
489*44704f69SBart Van Assche "supported (obsolete SPC-5)");
490*44704f69SBart Van Assche sgj_haj_vi_nex(jsp, jop, 2, "NV_SUP", SGJ_SEP_EQUAL_NO_SPACE,
491*44704f69SBart Van Assche !!(b[6] & 0x2), false, "Nonvolatile cache "
492*44704f69SBart Van Assche "supported");
493*44704f69SBart Van Assche sgj_haj_vi_nex(jsp, jop, 2, "V_SUP", SGJ_SEP_EQUAL_NO_SPACE,
494*44704f69SBart Van Assche !!(b[6] & 0x1), false, "Volatile cache supported");
495*44704f69SBart Van Assche sgj_haj_vi_nex(jsp, jop, 2, "NO_PI_CHK", SGJ_SEP_EQUAL_NO_SPACE,
496*44704f69SBart Van Assche !!(b[7] & 0x20), false, "No protection "
497*44704f69SBart Van Assche "information checking"); /* spc5r02 */
498*44704f69SBart Van Assche sgj_haj_vi_nex(jsp, jop, 2, "P_I_I_SUP", SGJ_SEP_EQUAL_NO_SPACE,
499*44704f69SBart Van Assche !!(b[7] & 0x10), false, "Protection information "
500*44704f69SBart Van Assche "interval supported");
501*44704f69SBart Van Assche sgj_haj_vi_nex(jsp, jop, 2, "LUICLR", SGJ_SEP_EQUAL_NO_SPACE,
502*44704f69SBart Van Assche !!(b[7] & 0x1), false, "Logical unit I_T nexus clear");
503*44704f69SBart Van Assche np = "LU_COLL_TYPE";
504*44704f69SBart Van Assche n = (b[8] >> 5) & 0x7;
505*44704f69SBart Van Assche nex_p = "Logical unit collection type";
506*44704f69SBart Van Assche if (jsp && (jsp->pr_string)) {
507*44704f69SBart Van Assche switch (n) {
508*44704f69SBart Van Assche case 0:
509*44704f69SBart Van Assche cp = "not reported";
510*44704f69SBart Van Assche break;
511*44704f69SBart Van Assche case 1:
512*44704f69SBart Van Assche cp = "Conglomerate";
513*44704f69SBart Van Assche break;
514*44704f69SBart Van Assche case 2:
515*44704f69SBart Van Assche cp = "Logical unit group";
516*44704f69SBart Van Assche break;
517*44704f69SBart Van Assche default:
518*44704f69SBart Van Assche cp = rsv_s;
519*44704f69SBart Van Assche break;
520*44704f69SBart Van Assche }
521*44704f69SBart Van Assche jo2p = sgj_haj_subo_r(jsp, jop, 2, np, SGJ_SEP_EQUAL_NO_SPACE,
522*44704f69SBart Van Assche n, false);
523*44704f69SBart Van Assche sgj_js_nv_s(jsp, jo2p, mn_s, cp);
524*44704f69SBart Van Assche if (jsp->pr_name_ex)
525*44704f69SBart Van Assche sgj_js_nv_s(jsp, jo2p, "abbreviated_name_expansion", nex_p);
526*44704f69SBart Van Assche } else
527*44704f69SBart Van Assche sgj_haj_vi_nex(jsp, jop, 2, np, SGJ_SEP_EQUAL_NO_SPACE, n,
528*44704f69SBart Van Assche true, nex_p);
529*44704f69SBart Van Assche
530*44704f69SBart Van Assche sgj_haj_vi_nex(jsp, jop, 2, "R_SUP", SGJ_SEP_EQUAL_NO_SPACE,
531*44704f69SBart Van Assche !!(b[8] & 0x10), false, "Referrals supported");
532*44704f69SBart Van Assche sgj_haj_vi_nex(jsp, jop, 2, "RTD_SUP", SGJ_SEP_EQUAL_NO_SPACE,
533*44704f69SBart Van Assche !!(b[8] & 0x8), false,
534*44704f69SBart Van Assche "Revert to defaults supported");
535*44704f69SBart Van Assche sgj_haj_vi_nex(jsp, jop, 2, "HSSRELEF", SGJ_SEP_EQUAL_NO_SPACE,
536*44704f69SBart Van Assche !!(b[8] & 0x2), false,
537*44704f69SBart Van Assche "History snapshots release effects");
538*44704f69SBart Van Assche sgj_haj_vi_nex(jsp, jop, 2, "CBCS", SGJ_SEP_EQUAL_NO_SPACE,
539*44704f69SBart Van Assche !!(b[8] & 0x1), false, "Capability-based command "
540*44704f69SBart Van Assche "security (obsolete SPC-5)");
541*44704f69SBart Van Assche sgj_haj_vi(jsp, jop, 2, "Multi I_T nexus microcode download",
542*44704f69SBart Van Assche SGJ_SEP_EQUAL_NO_SPACE, b[9] & 0xf, true);
543*44704f69SBart Van Assche sgj_haj_vi(jsp, jop, 2, "Extended self-test completion minutes",
544*44704f69SBart Van Assche SGJ_SEP_EQUAL_NO_SPACE,
545*44704f69SBart Van Assche sg_get_unaligned_be16(b + 10), true);
546*44704f69SBart Van Assche sgj_haj_vi_nex(jsp, jop, 2, "POA_SUP", SGJ_SEP_EQUAL_NO_SPACE,
547*44704f69SBart Van Assche !!(b[12] & 0x80), false,
548*44704f69SBart Van Assche "Power on activation supported");
549*44704f69SBart Van Assche sgj_haj_vi_nex(jsp, jop, 2, "HRA_SUP", SGJ_SEP_EQUAL_NO_SPACE,
550*44704f69SBart Van Assche !!(b[12] & 0x40), false,
551*44704f69SBart Van Assche "Hard reset activation supported");
552*44704f69SBart Van Assche sgj_haj_vi_nex(jsp, jop, 2, "VSA_SUP", SGJ_SEP_EQUAL_NO_SPACE,
553*44704f69SBart Van Assche !!(b[12] & 0x20), false,
554*44704f69SBart Van Assche "Vendor specific activation supported");
555*44704f69SBart Van Assche sgj_haj_vi_nex(jsp, jop, 2, "DMS_VALID", SGJ_SEP_EQUAL_NO_SPACE,
556*44704f69SBart Van Assche !!(b[12] & 0x10), false,
557*44704f69SBart Van Assche "Download microcode support byte valid");
558*44704f69SBart Van Assche sgj_haj_vi(jsp, jop, 2, "Maximum supported sense data length",
559*44704f69SBart Van Assche SGJ_SEP_EQUAL_NO_SPACE, b[13], true);
560*44704f69SBart Van Assche sgj_haj_vi_nex(jsp, jop, 2, "IBS", SGJ_SEP_EQUAL_NO_SPACE,
561*44704f69SBart Van Assche !!(b[14] & 0x80), false, "Implicit bind supported");
562*44704f69SBart Van Assche sgj_haj_vi_nex(jsp, jop, 2, "IAS", SGJ_SEP_EQUAL_NO_SPACE,
563*44704f69SBart Van Assche !!(b[14] & 0x40), false,
564*44704f69SBart Van Assche "Implicit affiliation supported");
565*44704f69SBart Van Assche sgj_haj_vi_nex(jsp, jop, 2, "SAC", SGJ_SEP_EQUAL_NO_SPACE,
566*44704f69SBart Van Assche !!(b[14] & 0x4), false,
567*44704f69SBart Van Assche "Set affiliation command supported");
568*44704f69SBart Van Assche sgj_haj_vi_nex(jsp, jop, 2, "NRD1", SGJ_SEP_EQUAL_NO_SPACE,
569*44704f69SBart Van Assche !!(b[14] & 0x2), false,
570*44704f69SBart Van Assche "No redirect one supported (BIND)");
571*44704f69SBart Van Assche sgj_haj_vi_nex(jsp, jop, 2, "NRD0", SGJ_SEP_EQUAL_NO_SPACE,
572*44704f69SBart Van Assche !!(b[14] & 0x1), false,
573*44704f69SBart Van Assche "No redirect zero supported (BIND)");
574*44704f69SBart Van Assche sgj_haj_vi(jsp, jop, 2, "Maximum inquiry change logs",
575*44704f69SBart Van Assche SGJ_SEP_EQUAL_NO_SPACE,
576*44704f69SBart Van Assche sg_get_unaligned_be16(b + 15), true);
577*44704f69SBart Van Assche sgj_haj_vi(jsp, jop, 2, "Maximum mode page change logs",
578*44704f69SBart Van Assche SGJ_SEP_EQUAL_NO_SPACE,
579*44704f69SBart Van Assche sg_get_unaligned_be16(b + 17), true);
580*44704f69SBart Van Assche sgj_haj_vi_nex(jsp, jop, 2, "DM_MD_4", SGJ_SEP_EQUAL_NO_SPACE,
581*44704f69SBart Van Assche !!(b[19] & 0x80), false,
582*44704f69SBart Van Assche "Download microcode mode 4 supported");
583*44704f69SBart Van Assche sgj_haj_vi_nex(jsp, jop, 2, "DM_MD_5", SGJ_SEP_EQUAL_NO_SPACE,
584*44704f69SBart Van Assche !!(b[19] & 0x40), false,
585*44704f69SBart Van Assche "Download microcode mode 5 supported");
586*44704f69SBart Van Assche sgj_haj_vi_nex(jsp, jop, 2, "DM_MD_6", SGJ_SEP_EQUAL_NO_SPACE,
587*44704f69SBart Van Assche !!(b[19] & 0x20), false,
588*44704f69SBart Van Assche "Download microcode mode 6 supported");
589*44704f69SBart Van Assche sgj_haj_vi_nex(jsp, jop, 2, "DM_MD_7", SGJ_SEP_EQUAL_NO_SPACE,
590*44704f69SBart Van Assche !!(b[19] & 0x10), false,
591*44704f69SBart Van Assche "Download microcode mode 7 supported");
592*44704f69SBart Van Assche sgj_haj_vi_nex(jsp, jop, 2, "DM_MD_D", SGJ_SEP_EQUAL_NO_SPACE,
593*44704f69SBart Van Assche !!(b[19] & 0x8), false,
594*44704f69SBart Van Assche "Download microcode mode 0xd supported");
595*44704f69SBart Van Assche sgj_haj_vi_nex(jsp, jop, 2, "DM_MD_E", SGJ_SEP_EQUAL_NO_SPACE,
596*44704f69SBart Van Assche !!(b[19] & 0x4), false,
597*44704f69SBart Van Assche "Download microcode mode 0xe supported");
598*44704f69SBart Van Assche sgj_haj_vi_nex(jsp, jop, 2, "DM_MD_F", SGJ_SEP_EQUAL_NO_SPACE,
599*44704f69SBart Van Assche !!(b[19] & 0x2), false,
600*44704f69SBart Van Assche "Download microcode mode 0xf supported");
601*44704f69SBart Van Assche if (do_long_nq || (! jsp->pr_out_hr))
602*44704f69SBart Van Assche return;
603*44704f69SBart Van Assche }
604*44704f69SBart Van Assche sgj_pr_hr(jsp, " ACTIVATE_MICROCODE=%d SPT=%d GRD_CHK=%d APP_CHK=%d "
605*44704f69SBart Van Assche "REF_CHK=%d\n", ((b[4] >> 6) & 0x3), ((b[4] >> 3) & 0x7),
606*44704f69SBart Van Assche !!(b[4] & 0x4), !!(b[4] & 0x2), !!(b[4] & 0x1));
607*44704f69SBart Van Assche sgj_pr_hr(jsp, " UASK_SUP=%d GROUP_SUP=%d PRIOR_SUP=%d HEADSUP=%d "
608*44704f69SBart Van Assche "ORDSUP=%d SIMPSUP=%d\n", !!(b[5] & 0x20), !!(b[5] & 0x10),
609*44704f69SBart Van Assche !!(b[5] & 0x8), !!(b[5] & 0x4), !!(b[5] & 0x2), !!(b[5] & 0x1));
610*44704f69SBart Van Assche sgj_pr_hr(jsp, " WU_SUP=%d [CRD_SUP=%d] NV_SUP=%d V_SUP=%d\n",
611*44704f69SBart Van Assche !!(b[6] & 0x8), !!(b[6] & 0x4), !!(b[6] & 0x2), !!(b[6] & 0x1));
612*44704f69SBart Van Assche sgj_pr_hr(jsp, " NO_PI_CHK=%d P_I_I_SUP=%d LUICLR=%d\n", !!(b[7] & 0x20),
613*44704f69SBart Van Assche !!(b[7] & 0x10), !!(b[7] & 0x1));
614*44704f69SBart Van Assche /* RTD_SUP added in spc5r11, LU_COLL_TYPE added in spc5r09,
615*44704f69SBart Van Assche * HSSRELEF added in spc5r02; CBCS obsolete in spc5r01 */
616*44704f69SBart Van Assche sgj_pr_hr(jsp, " LU_COLL_TYPE=%d R_SUP=%d RTD_SUP=%d HSSRELEF=%d "
617*44704f69SBart Van Assche "[CBCS=%d]\n", (b[8] >> 5) & 0x7, !!(b[8] & 0x10),
618*44704f69SBart Van Assche !!(b[8] & 0x8), !!(b[8] & 0x2), !!(b[8] & 0x1));
619*44704f69SBart Van Assche sgj_pr_hr(jsp, " Multi I_T nexus microcode download=%d\n", b[9] & 0xf);
620*44704f69SBart Van Assche sgj_pr_hr(jsp, " Extended self-test completion minutes=%d\n",
621*44704f69SBart Van Assche sg_get_unaligned_be16(b + 10)); /* spc4r27 */
622*44704f69SBart Van Assche sgj_pr_hr(jsp, " POA_SUP=%d HRA_SUP=%d VSA_SUP=%d DMS_VALID=%d\n",
623*44704f69SBart Van Assche !!(b[12] & 0x80), !!(b[12] & 0x40), !!(b[12] & 0x20),
624*44704f69SBart Van Assche !!(b[12] & 0x10)); /* spc5r20 */
625*44704f69SBart Van Assche sgj_pr_hr(jsp, " Maximum supported sense data length=%d\n",
626*44704f69SBart Van Assche b[13]); /* spc4r34 */
627*44704f69SBart Van Assche sgj_pr_hr(jsp, " IBS=%d IAS=%d SAC=%d NRD1=%d NRD0=%d\n",
628*44704f69SBart Van Assche !!(b[14] & 0x80), !!(b[14] & 0x40), !!(b[14] & 0x4),
629*44704f69SBart Van Assche !!(b[14] & 0x2), !!(b[14] & 0x1)); /* added in spc5r09 */
630*44704f69SBart Van Assche sgj_pr_hr(jsp, " Maximum inquiry change logs=%u\n",
631*44704f69SBart Van Assche sg_get_unaligned_be16(b + 15)); /* spc5r17 */
632*44704f69SBart Van Assche sgj_pr_hr(jsp, " Maximum mode page change logs=%u\n",
633*44704f69SBart Van Assche sg_get_unaligned_be16(b + 17)); /* spc5r17 */
634*44704f69SBart Van Assche sgj_pr_hr(jsp, " DM_MD_4=%d DM_MD_5=%d DM_MD_6=%d DM_MD_7=%d\n",
635*44704f69SBart Van Assche !!(b[19] & 0x80), !!(b[19] & 0x40), !!(b[19] & 0x20),
636*44704f69SBart Van Assche !!(b[19] & 0x10)); /* spc5r20 */
637*44704f69SBart Van Assche sgj_pr_hr(jsp, " DM_MD_D=%d DM_MD_E=%d DM_MD_F=%d\n",
638*44704f69SBart Van Assche !!(b[19] & 0x8), !!(b[19] & 0x4), !!(b[19] & 0x2));
639*44704f69SBart Van Assche }
640*44704f69SBart Van Assche
641*44704f69SBart Van Assche /* VPD_SOFTW_INF_ID 0x84 */
642*44704f69SBart Van Assche void
decode_softw_inf_id(const uint8_t * buff,int len,struct opts_t * op,sgj_opaque_p jap)643*44704f69SBart Van Assche decode_softw_inf_id(const uint8_t * buff, int len, struct opts_t * op,
644*44704f69SBart Van Assche sgj_opaque_p jap)
645*44704f69SBart Van Assche {
646*44704f69SBart Van Assche sgj_state * jsp = &op->json_st;
647*44704f69SBart Van Assche sgj_opaque_p jop;
648*44704f69SBart Van Assche uint64_t ieee_id;
649*44704f69SBart Van Assche
650*44704f69SBart Van Assche if (op->do_hex) {
651*44704f69SBart Van Assche hex2stdout(buff, len, (1 == op->do_hex) ? 0 : -1);
652*44704f69SBart Van Assche return;
653*44704f69SBart Van Assche }
654*44704f69SBart Van Assche len -= 4;
655*44704f69SBart Van Assche buff += 4;
656*44704f69SBart Van Assche for ( ; len > 5; len -= 6, buff += 6) {
657*44704f69SBart Van Assche ieee_id = sg_get_unaligned_be48(buff + 0);
658*44704f69SBart Van Assche sgj_pr_hr(jsp, " IEEE identifier: 0x%" PRIx64 "\n", ieee_id);
659*44704f69SBart Van Assche if (jsp->pr_as_json) {
660*44704f69SBart Van Assche jop = sgj_new_unattached_object_r(jsp);
661*44704f69SBart Van Assche sgj_js_nv_ihex(jsp, jop, "ieee_identifier", ieee_id);
662*44704f69SBart Van Assche sgj_js_nv_o(jsp, jap, NULL /* name */, jop);
663*44704f69SBart Van Assche }
664*44704f69SBart Van Assche }
665*44704f69SBart Van Assche }
666*44704f69SBart Van Assche
667*44704f69SBart Van Assche static const char * mode_page_policy_arr[] =
668*44704f69SBart Van Assche {
669*44704f69SBart Van Assche "shared",
670*44704f69SBart Van Assche "per target port",
671*44704f69SBart Van Assche "per initiator port",
672*44704f69SBart Van Assche "per I_T nexus",
673*44704f69SBart Van Assche };
674*44704f69SBart Van Assche
675*44704f69SBart Van Assche /* VPD_MODE_PG_POLICY 0x87 ["mpp"] */
676*44704f69SBart Van Assche void
decode_mode_policy_vpd(const uint8_t * buff,int len,struct opts_t * op,sgj_opaque_p jap)677*44704f69SBart Van Assche decode_mode_policy_vpd(const uint8_t * buff, int len, struct opts_t * op,
678*44704f69SBart Van Assche sgj_opaque_p jap)
679*44704f69SBart Van Assche {
680*44704f69SBart Van Assche int k, n, bump, ppc, pspc;
681*44704f69SBart Van Assche sgj_state * jsp = &op->json_st;
682*44704f69SBart Van Assche sgj_opaque_p jo2p;
683*44704f69SBart Van Assche const uint8_t * bp;
684*44704f69SBart Van Assche char b[128];
685*44704f69SBart Van Assche static const int blen = sizeof(b);
686*44704f69SBart Van Assche
687*44704f69SBart Van Assche if ((1 == op->do_hex) || (op->do_hex > 2)) {
688*44704f69SBart Van Assche hex2stdout(buff, len, (1 == op->do_hex) ? 1 : -1);
689*44704f69SBart Van Assche return;
690*44704f69SBart Van Assche }
691*44704f69SBart Van Assche if (len < 4) {
692*44704f69SBart Van Assche pr2serr("Mode page policy VPD page length too short=%d\n", len);
693*44704f69SBart Van Assche return;
694*44704f69SBart Van Assche }
695*44704f69SBart Van Assche len -= 4;
696*44704f69SBart Van Assche bp = buff + 4;
697*44704f69SBart Van Assche for (k = 0; k < len; k += bump, bp += bump) {
698*44704f69SBart Van Assche bump = 4;
699*44704f69SBart Van Assche if ((k + bump) > len) {
700*44704f69SBart Van Assche pr2serr("Mode page policy VPD page, short "
701*44704f69SBart Van Assche "descriptor length=%d, left=%d\n", bump, (len - k));
702*44704f69SBart Van Assche return;
703*44704f69SBart Van Assche }
704*44704f69SBart Van Assche if (op->do_hex > 1)
705*44704f69SBart Van Assche hex2stdout(bp, 4, 1);
706*44704f69SBart Van Assche else {
707*44704f69SBart Van Assche n = 0;
708*44704f69SBart Van Assche ppc = (bp[0] & 0x3f);
709*44704f69SBart Van Assche pspc = bp[1];
710*44704f69SBart Van Assche n = sg_scnpr(b + n, blen - n, " Policy page code: 0x%x", ppc);
711*44704f69SBart Van Assche if (pspc)
712*44704f69SBart Van Assche n += sg_scnpr(b + n, blen - n, ", subpage code: 0x%x", pspc);
713*44704f69SBart Van Assche sgj_pr_hr(jsp, "%s\n", b);
714*44704f69SBart Van Assche if ((0 == k) && (0x3f == (0x3f & bp[0])) && (0xff == bp[1]))
715*44704f69SBart Van Assche sgj_pr_hr(jsp, " therefore the policy applies to all modes "
716*44704f69SBart Van Assche "pages and subpages\n");
717*44704f69SBart Van Assche sgj_pr_hr(jsp, " MLUS=%d, Policy: %s\n", !!(bp[2] & 0x80),
718*44704f69SBart Van Assche mode_page_policy_arr[bp[2] & 0x3]);
719*44704f69SBart Van Assche if (jsp->pr_as_json) {
720*44704f69SBart Van Assche jo2p = sgj_new_unattached_object_r(jsp);
721*44704f69SBart Van Assche sgj_js_nv_ihex(jsp, jo2p, "policy_page_code", ppc);
722*44704f69SBart Van Assche sgj_js_nv_ihex(jsp, jo2p, "policy_subpage_code", pspc);
723*44704f69SBart Van Assche sgj_js_nv_ihex_nex(jsp, jo2p, "mlus", !!(bp[2] & 0x80), false,
724*44704f69SBart Van Assche "Multiple logical units share");
725*44704f69SBart Van Assche sgj_js_nv_ihexstr(jsp, jo2p, "mode_page_policy", bp[2] & 0x3,
726*44704f69SBart Van Assche NULL, mode_page_policy_arr[bp[2] & 0x3]);
727*44704f69SBart Van Assche sgj_js_nv_o(jsp, jap, NULL /* name */, jo2p);
728*44704f69SBart Van Assche }
729*44704f69SBart Van Assche }
730*44704f69SBart Van Assche }
731*44704f69SBart Van Assche }
732*44704f69SBart Van Assche
733*44704f69SBart Van Assche /* VPD_POWER_CONDITION 0x8a ["pc"] */
734*44704f69SBart Van Assche void
decode_power_condition(const uint8_t * buff,int len,struct opts_t * op,sgj_opaque_p jop)735*44704f69SBart Van Assche decode_power_condition(const uint8_t * buff, int len, struct opts_t * op,
736*44704f69SBart Van Assche sgj_opaque_p jop)
737*44704f69SBart Van Assche {
738*44704f69SBart Van Assche sgj_state * jsp = &op->json_st;
739*44704f69SBart Van Assche
740*44704f69SBart Van Assche if (len < 18) {
741*44704f69SBart Van Assche pr2serr("Power condition VPD page length too short=%d\n", len);
742*44704f69SBart Van Assche return;
743*44704f69SBart Van Assche }
744*44704f69SBart Van Assche if (op->do_hex) {
745*44704f69SBart Van Assche hex2stdout(buff, len, (1 == op->do_hex) ? 0 : -1);
746*44704f69SBart Van Assche return;
747*44704f69SBart Van Assche }
748*44704f69SBart Van Assche sgj_pr_hr(jsp, " Standby_y=%d Standby_z=%d Idle_c=%d Idle_b=%d "
749*44704f69SBart Van Assche "Idle_a=%d\n", !!(buff[4] & 0x2), !!(buff[4] & 0x1),
750*44704f69SBart Van Assche !!(buff[5] & 0x4), !!(buff[5] & 0x2), !!(buff[5] & 0x1));
751*44704f69SBart Van Assche if (jsp->pr_as_json) {
752*44704f69SBart Van Assche sgj_js_nv_ihex(jsp, jop, "standby_y", !!(buff[4] & 0x2));
753*44704f69SBart Van Assche sgj_js_nv_ihex(jsp, jop, "standby_z", !!(buff[4] & 0x1));
754*44704f69SBart Van Assche sgj_js_nv_ihex(jsp, jop, "idle_c", !!(buff[5] & 0x4));
755*44704f69SBart Van Assche sgj_js_nv_ihex(jsp, jop, "idle_b", !!(buff[5] & 0x2));
756*44704f69SBart Van Assche sgj_js_nv_ihex(jsp, jop, "idle_a", !!(buff[5] & 0x1));
757*44704f69SBart Van Assche }
758*44704f69SBart Van Assche sgj_haj_vi_nex(jsp, jop, 2, "Stopped condition recovery time",
759*44704f69SBart Van Assche SGJ_SEP_SPACE_1, sg_get_unaligned_be16(buff + 6),
760*44704f69SBart Van Assche true, "unit: millisecond");
761*44704f69SBart Van Assche sgj_haj_vi_nex(jsp, jop, 2, "Standby_z condition recovery time",
762*44704f69SBart Van Assche SGJ_SEP_SPACE_1, sg_get_unaligned_be16(buff + 8),
763*44704f69SBart Van Assche true, "unit: millisecond");
764*44704f69SBart Van Assche sgj_haj_vi_nex(jsp, jop, 2, "Standby_y condition recovery time",
765*44704f69SBart Van Assche SGJ_SEP_SPACE_1, sg_get_unaligned_be16(buff + 10),
766*44704f69SBart Van Assche true, "unit: millisecond");
767*44704f69SBart Van Assche sgj_haj_vi_nex(jsp, jop, 2, "Idle_a condition recovery time",
768*44704f69SBart Van Assche SGJ_SEP_SPACE_1, sg_get_unaligned_be16(buff + 12),
769*44704f69SBart Van Assche true, "unit: millisecond");
770*44704f69SBart Van Assche sgj_haj_vi_nex(jsp, jop, 2, "Idle_b condition recovery time",
771*44704f69SBart Van Assche SGJ_SEP_SPACE_1, sg_get_unaligned_be16(buff + 14),
772*44704f69SBart Van Assche true, "unit: millisecond");
773*44704f69SBart Van Assche sgj_haj_vi_nex(jsp, jop, 2, "Idle_c condition recovery time",
774*44704f69SBart Van Assche SGJ_SEP_SPACE_1, sg_get_unaligned_be16(buff + 16),
775*44704f69SBart Van Assche true, "unit: millisecond");
776*44704f69SBart Van Assche }
777*44704f69SBart Van Assche
778*44704f69SBart Van Assche int
filter_json_dev_ids(uint8_t * buff,int len,int m_assoc,struct opts_t * op,sgj_opaque_p jap)779*44704f69SBart Van Assche filter_json_dev_ids(uint8_t * buff, int len, int m_assoc, struct opts_t * op,
780*44704f69SBart Van Assche sgj_opaque_p jap)
781*44704f69SBart Van Assche {
782*44704f69SBart Van Assche int u, off, i_len;
783*44704f69SBart Van Assche sgj_opaque_p jo2p;
784*44704f69SBart Van Assche const uint8_t * bp;
785*44704f69SBart Van Assche sgj_state * jsp = &op->json_st;
786*44704f69SBart Van Assche
787*44704f69SBart Van Assche off = -1;
788*44704f69SBart Van Assche while ((u = sg_vpd_dev_id_iter(buff, len, &off, m_assoc, -1, -1)) == 0) {
789*44704f69SBart Van Assche bp = buff + off;
790*44704f69SBart Van Assche i_len = bp[3];
791*44704f69SBart Van Assche if ((off + i_len + 4) > len) {
792*44704f69SBart Van Assche pr2serr(" VPD page error: designator length longer than\n"
793*44704f69SBart Van Assche " remaining response length=%d\n", (len - off));
794*44704f69SBart Van Assche return SG_LIB_CAT_MALFORMED;
795*44704f69SBart Van Assche }
796*44704f69SBart Van Assche jo2p = sgj_new_unattached_object_r(jsp);
797*44704f69SBart Van Assche sgj_js_designation_descriptor(jsp, jo2p, bp, i_len + 4);
798*44704f69SBart Van Assche sgj_js_nv_o(jsp, jap, NULL /* name */, jo2p);
799*44704f69SBart Van Assche }
800*44704f69SBart Van Assche if (-2 == u) {
801*44704f69SBart Van Assche pr2serr("VPD page error: short designator around offset %d\n", off);
802*44704f69SBart Van Assche return SG_LIB_CAT_MALFORMED;
803*44704f69SBart Van Assche }
804*44704f69SBart Van Assche return 0;
805*44704f69SBart Van Assche }
806*44704f69SBart Van Assche
807*44704f69SBart Van Assche /* VPD_ATA_INFO 0x89 ["ai"] */
808*44704f69SBart Van Assche void
decode_ata_info_vpd(const uint8_t * buff,int len,struct opts_t * op,sgj_opaque_p jop)809*44704f69SBart Van Assche decode_ata_info_vpd(const uint8_t * buff, int len, struct opts_t * op,
810*44704f69SBart Van Assche sgj_opaque_p jop)
811*44704f69SBart Van Assche {
812*44704f69SBart Van Assche bool do_long_nq = op->do_long && (! op->do_quiet);
813*44704f69SBart Van Assche int num, is_be, cc, n;
814*44704f69SBart Van Assche sgj_state * jsp = &op->json_st;
815*44704f69SBart Van Assche const char * cp;
816*44704f69SBart Van Assche const char * ata_transp;
817*44704f69SBart Van Assche char b[512];
818*44704f69SBart Van Assche char d[80];
819*44704f69SBart Van Assche static const int blen = sizeof(b);
820*44704f69SBart Van Assche static const int dlen = sizeof(d);
821*44704f69SBart Van Assche static const char * sat_vip = "SAT Vendor identification";
822*44704f69SBart Van Assche static const char * sat_pip = "SAT Product identification";
823*44704f69SBart Van Assche static const char * sat_prlp = "SAT Product revision level";
824*44704f69SBart Van Assche
825*44704f69SBart Van Assche if (len < 36) {
826*44704f69SBart Van Assche pr2serr("ATA information VPD page length too short=%d\n", len);
827*44704f69SBart Van Assche return;
828*44704f69SBart Van Assche }
829*44704f69SBart Van Assche if (op->do_hex && (2 != op->do_hex)) {
830*44704f69SBart Van Assche hex2stdout(buff, len, (1 == op->do_hex) ? 0 : -1);
831*44704f69SBart Van Assche return;
832*44704f69SBart Van Assche }
833*44704f69SBart Van Assche memcpy(b, buff + 8, 8);
834*44704f69SBart Van Assche b[8] = '\0';
835*44704f69SBart Van Assche sgj_pr_hr(jsp, " %s: %s\n", sat_vip, b);
836*44704f69SBart Van Assche memcpy(b, buff + 16, 16);
837*44704f69SBart Van Assche b[16] = '\0';
838*44704f69SBart Van Assche sgj_pr_hr(jsp, " %s: %s\n", sat_pip, b);
839*44704f69SBart Van Assche memcpy(b, buff + 32, 4);
840*44704f69SBart Van Assche b[4] = '\0';
841*44704f69SBart Van Assche sgj_pr_hr(jsp, " %s: %s\n", sat_prlp, b);
842*44704f69SBart Van Assche if (len < 56)
843*44704f69SBart Van Assche return;
844*44704f69SBart Van Assche ata_transp = (0x34 == buff[36]) ? "SATA" : "PATA";
845*44704f69SBart Van Assche if (do_long_nq) {
846*44704f69SBart Van Assche sgj_pr_hr(jsp, " Device signature [%s] (in hex):\n", ata_transp);
847*44704f69SBart Van Assche hex2stdout(buff + 36, 20, 0);
848*44704f69SBart Van Assche } else
849*44704f69SBart Van Assche sgj_pr_hr(jsp, " Device signature indicates %s transport\n",
850*44704f69SBart Van Assche ata_transp);
851*44704f69SBart Van Assche cc = buff[56]; /* 0xec for IDENTIFY DEVICE and 0xa1 for IDENTIFY
852*44704f69SBart Van Assche * PACKET DEVICE (obsolete) */
853*44704f69SBart Van Assche n = sg_scnpr(b, blen, " Command code: 0x%x\n", cc);
854*44704f69SBart Van Assche if (len < 60)
855*44704f69SBart Van Assche return;
856*44704f69SBart Van Assche if (0xec == cc)
857*44704f69SBart Van Assche cp = null_s;
858*44704f69SBart Van Assche else if (0xa1 == cc)
859*44704f69SBart Van Assche cp = "PACKET ";
860*44704f69SBart Van Assche else
861*44704f69SBart Van Assche cp = NULL;
862*44704f69SBart Van Assche is_be = sg_is_big_endian();
863*44704f69SBart Van Assche if (cp) {
864*44704f69SBart Van Assche n += sg_scnpr(b + n, blen - n, " ATA command IDENTIFY %sDEVICE "
865*44704f69SBart Van Assche "response summary:\n", cp);
866*44704f69SBart Van Assche num = sg_ata_get_chars((const unsigned short *)(buff + 60), 27, 20,
867*44704f69SBart Van Assche is_be, d);
868*44704f69SBart Van Assche d[num] = '\0';
869*44704f69SBart Van Assche n += sg_scnpr(b + n, blen - n, " model: %s\n", d);
870*44704f69SBart Van Assche num = sg_ata_get_chars((const unsigned short *)(buff + 60), 10, 10,
871*44704f69SBart Van Assche is_be, d);
872*44704f69SBart Van Assche d[num] = '\0';
873*44704f69SBart Van Assche n += sg_scnpr(b + n, blen - n, " serial number: %s\n", d);
874*44704f69SBart Van Assche num = sg_ata_get_chars((const unsigned short *)(buff + 60), 23, 4,
875*44704f69SBart Van Assche is_be, d);
876*44704f69SBart Van Assche d[num] = '\0';
877*44704f69SBart Van Assche n += sg_scnpr(b + n, blen - n, " firmware revision: %s\n", d);
878*44704f69SBart Van Assche sgj_pr_hr(jsp, "%s", b);
879*44704f69SBart Van Assche if (do_long_nq)
880*44704f69SBart Van Assche sgj_pr_hr(jsp, " ATA command IDENTIFY %sDEVICE response in "
881*44704f69SBart Van Assche "hex:\n", cp);
882*44704f69SBart Van Assche } else if (do_long_nq)
883*44704f69SBart Van Assche sgj_pr_hr(jsp, " ATA command 0x%x got following response:\n",
884*44704f69SBart Van Assche (unsigned int)cc);
885*44704f69SBart Van Assche if (jsp->pr_as_json) {
886*44704f69SBart Van Assche sgj_convert_to_snake_name(sat_vip, d, dlen);
887*44704f69SBart Van Assche sgj_js_nv_s_len(jsp, jop, d, (const char *)(buff + 8), 8);
888*44704f69SBart Van Assche sgj_convert_to_snake_name(sat_pip, d, dlen);
889*44704f69SBart Van Assche sgj_js_nv_s_len(jsp, jop, d, (const char *)(buff + 16), 16);
890*44704f69SBart Van Assche sgj_convert_to_snake_name(sat_prlp, d, dlen);
891*44704f69SBart Van Assche sgj_js_nv_s_len(jsp, jop, d, (const char *)(buff + 32), 4);
892*44704f69SBart Van Assche sgj_js_nv_hex_bytes(jsp, jop, "ata_device_signature", buff + 36, 20);
893*44704f69SBart Van Assche sgj_js_nv_ihex(jsp, jop, "command_code", buff[56]);
894*44704f69SBart Van Assche sgj_js_nv_s(jsp, jop, "ata_identify_device_data_example",
895*44704f69SBart Van Assche "sg_vpd -p ai -HHH /dev/sdc | hdparm --Istdin");
896*44704f69SBart Van Assche }
897*44704f69SBart Van Assche if (len < 572)
898*44704f69SBart Van Assche return;
899*44704f69SBart Van Assche if (2 == op->do_hex)
900*44704f69SBart Van Assche hex2stdout((buff + 60), 512, 0);
901*44704f69SBart Van Assche else if (do_long_nq)
902*44704f69SBart Van Assche dWordHex((const unsigned short *)(buff + 60), 256, 0, is_be);
903*44704f69SBart Van Assche }
904*44704f69SBart Van Assche
905*44704f69SBart Van Assche /* VPD_SCSI_FEATURE_SETS 0x92 ["sfs"] */
906*44704f69SBart Van Assche void
decode_feature_sets_vpd(const uint8_t * buff,int len,struct opts_t * op,sgj_opaque_p jap)907*44704f69SBart Van Assche decode_feature_sets_vpd(const uint8_t * buff, int len, struct opts_t * op,
908*44704f69SBart Van Assche sgj_opaque_p jap)
909*44704f69SBart Van Assche {
910*44704f69SBart Van Assche int k, bump;
911*44704f69SBart Van Assche uint16_t sf_code;
912*44704f69SBart Van Assche bool found;
913*44704f69SBart Van Assche const uint8_t * bp;
914*44704f69SBart Van Assche sgj_opaque_p jo2p;
915*44704f69SBart Van Assche sgj_state * jsp = &op->json_st;
916*44704f69SBart Van Assche char b[256];
917*44704f69SBart Van Assche char d[80];
918*44704f69SBart Van Assche
919*44704f69SBart Van Assche if ((1 == op->do_hex) || (op->do_hex > 2)) {
920*44704f69SBart Van Assche hex2stdout(buff, len, (1 == op->do_hex) ? 1 : -1);
921*44704f69SBart Van Assche return;
922*44704f69SBart Van Assche }
923*44704f69SBart Van Assche if (len < 4) {
924*44704f69SBart Van Assche pr2serr("SCSI Feature sets VPD page length too short=%d\n", len);
925*44704f69SBart Van Assche return;
926*44704f69SBart Van Assche }
927*44704f69SBart Van Assche len -= 8;
928*44704f69SBart Van Assche bp = buff + 8;
929*44704f69SBart Van Assche for (k = 0; k < len; k += bump, bp += bump) {
930*44704f69SBart Van Assche jo2p = sgj_new_unattached_object_r(jsp);
931*44704f69SBart Van Assche sf_code = sg_get_unaligned_be16(bp);
932*44704f69SBart Van Assche bump = 2;
933*44704f69SBart Van Assche if ((k + bump) > len) {
934*44704f69SBart Van Assche pr2serr("SCSI Feature sets, short descriptor length=%d, "
935*44704f69SBart Van Assche "left=%d\n", bump, (len - k));
936*44704f69SBart Van Assche return;
937*44704f69SBart Van Assche }
938*44704f69SBart Van Assche if (2 == op->do_hex)
939*44704f69SBart Van Assche hex2stdout(bp + 8, 2, 1);
940*44704f69SBart Van Assche else if (op->do_hex > 2)
941*44704f69SBart Van Assche hex2stdout(bp, 2, 1);
942*44704f69SBart Van Assche else {
943*44704f69SBart Van Assche sg_scnpr(b, sizeof(b), " %s",
944*44704f69SBart Van Assche sg_get_sfs_str(sf_code, -2, sizeof(d), d, &found,
945*44704f69SBart Van Assche op->verbose));
946*44704f69SBart Van Assche if (op->verbose == 1)
947*44704f69SBart Van Assche sgj_pr_hr(jsp, "%s [0x%x]\n", b, (unsigned int)sf_code);
948*44704f69SBart Van Assche else if (op->verbose > 1)
949*44704f69SBart Van Assche sgj_pr_hr(jsp, "%s [0x%x] found=%s\n", b,
950*44704f69SBart Van Assche (unsigned int)sf_code, found ? "true" : "false");
951*44704f69SBart Van Assche else
952*44704f69SBart Van Assche sgj_pr_hr(jsp, "%s\n", b);
953*44704f69SBart Van Assche sgj_js_nv_ihexstr(jsp, jo2p, "feature_set_code", sf_code, NULL,
954*44704f69SBart Van Assche d);
955*44704f69SBart Van Assche if (jsp->verbose)
956*44704f69SBart Van Assche sgj_js_nv_b(jsp, jo2p, "meaning_is_match", found);
957*44704f69SBart Van Assche }
958*44704f69SBart Van Assche sgj_js_nv_o(jsp, jap, NULL, jo2p);
959*44704f69SBart Van Assche }
960*44704f69SBart Van Assche }
961*44704f69SBart Van Assche
962*44704f69SBart Van Assche static const char * constituent_type_arr[] = {
963*44704f69SBart Van Assche "Reserved",
964*44704f69SBart Van Assche "Virtual tape library",
965*44704f69SBart Van Assche "Virtual tape drive",
966*44704f69SBart Van Assche "Direct access block device",
967*44704f69SBart Van Assche };
968*44704f69SBart Van Assche
969*44704f69SBart Van Assche /* VPD_DEVICE_CONSTITUENTS 0x8b ["dc"] */
970*44704f69SBart Van Assche void
decode_dev_constit_vpd(const uint8_t * buff,int len,struct opts_t * op,sgj_opaque_p jap,recurse_vpd_decodep fp)971*44704f69SBart Van Assche decode_dev_constit_vpd(const uint8_t * buff, int len, struct opts_t * op,
972*44704f69SBart Van Assche sgj_opaque_p jap, recurse_vpd_decodep fp)
973*44704f69SBart Van Assche {
974*44704f69SBart Van Assche uint16_t constit_type;
975*44704f69SBart Van Assche int k, j, res, bump, csd_len;
976*44704f69SBart Van Assche sgj_state * jsp = &op->json_st;
977*44704f69SBart Van Assche sgj_opaque_p jo2p, jo3p, ja2p;
978*44704f69SBart Van Assche const uint8_t * bp;
979*44704f69SBart Van Assche char b[256];
980*44704f69SBart Van Assche char d[64];
981*44704f69SBart Van Assche static const int blen = sizeof(b);
982*44704f69SBart Van Assche static const int dlen = sizeof(d);
983*44704f69SBart Van Assche
984*44704f69SBart Van Assche if ((1 == op->do_hex) || (op->do_hex > 2)) {
985*44704f69SBart Van Assche hex2stdout(buff, len, (1 == op->do_hex) ? 0 : -1);
986*44704f69SBart Van Assche return;
987*44704f69SBart Van Assche }
988*44704f69SBart Van Assche if (len < 4) {
989*44704f69SBart Van Assche pr2serr("page length too short=%d\n", len);
990*44704f69SBart Van Assche return;
991*44704f69SBart Van Assche }
992*44704f69SBart Van Assche len -= 4;
993*44704f69SBart Van Assche bp = buff + 4;
994*44704f69SBart Van Assche for (k = 0, j = 0; k < len; k += bump, bp += bump, ++j) {
995*44704f69SBart Van Assche jo2p = sgj_new_unattached_object_r(jsp);
996*44704f69SBart Van Assche if (j > 0)
997*44704f69SBart Van Assche sgj_pr_hr(jsp, "\n");
998*44704f69SBart Van Assche sgj_pr_hr(jsp, " Constituent descriptor %d:\n", j + 1);
999*44704f69SBart Van Assche if ((k + 36) > len) {
1000*44704f69SBart Van Assche pr2serr("short descriptor length=36, left=%d\n", (len - k));
1001*44704f69SBart Van Assche sgj_js_nv_o(jsp, jap, NULL, jo2p);
1002*44704f69SBart Van Assche return;
1003*44704f69SBart Van Assche }
1004*44704f69SBart Van Assche constit_type = sg_get_unaligned_be16(bp + 0);
1005*44704f69SBart Van Assche if (constit_type >= SG_ARRAY_SIZE(constituent_type_arr))
1006*44704f69SBart Van Assche sgj_pr_hr(jsp," Constituent type: unknown [0x%x]\n",
1007*44704f69SBart Van Assche constit_type);
1008*44704f69SBart Van Assche else
1009*44704f69SBart Van Assche sgj_pr_hr(jsp, " Constituent type: %s [0x%x]\n",
1010*44704f69SBart Van Assche constituent_type_arr[constit_type], constit_type);
1011*44704f69SBart Van Assche sg_scnpr(b, blen, " Constituent device type: ");
1012*44704f69SBart Van Assche if (0xff == bp[2])
1013*44704f69SBart Van Assche sgj_pr_hr(jsp, "%sUnknown [0xff]\n", b);
1014*44704f69SBart Van Assche else if (bp[2] >= 0x20)
1015*44704f69SBart Van Assche sgj_pr_hr(jsp, "%s%s [0x%x]\n", b, rsv_s, bp[2]);
1016*44704f69SBart Van Assche else
1017*44704f69SBart Van Assche sgj_pr_hr(jsp, "%s%s [0x%x]\n", b,
1018*44704f69SBart Van Assche sg_get_pdt_str(PDT_MASK & bp[2], dlen, d), bp[2]);
1019*44704f69SBart Van Assche snprintf(b, blen, "%.8s", bp + 4);
1020*44704f69SBart Van Assche sgj_pr_hr(jsp, " %s: %s\n", t10_vendor_id_hr, b);
1021*44704f69SBart Van Assche sgj_js_nv_s(jsp, jo2p, t10_vendor_id_js, b);
1022*44704f69SBart Van Assche snprintf(b, blen, "%.16s", bp + 12);
1023*44704f69SBart Van Assche sgj_pr_hr(jsp, " %s: %s\n", product_id_hr, b);
1024*44704f69SBart Van Assche sgj_js_nv_s(jsp, jo2p, product_id_js, b);
1025*44704f69SBart Van Assche snprintf(b, blen, "%.4s", bp + 28);
1026*44704f69SBart Van Assche sgj_pr_hr(jsp, " %s: %s\n", product_rev_lev_hr, b);
1027*44704f69SBart Van Assche sgj_js_nv_s(jsp, jo2p, product_rev_lev_js, b);
1028*44704f69SBart Van Assche csd_len = sg_get_unaligned_be16(bp + 34);
1029*44704f69SBart Van Assche bump = 36 + csd_len;
1030*44704f69SBart Van Assche if ((k + bump) > len) {
1031*44704f69SBart Van Assche pr2serr("short descriptor length=%d, left=%d\n", bump, (len - k));
1032*44704f69SBart Van Assche sgj_js_nv_o(jsp, jap, NULL, jo2p);
1033*44704f69SBart Van Assche return;
1034*44704f69SBart Van Assche }
1035*44704f69SBart Van Assche if (csd_len > 0) {
1036*44704f69SBart Van Assche int m, q, cs_bump;
1037*44704f69SBart Van Assche uint8_t cs_type;
1038*44704f69SBart Van Assche uint8_t cs_len;
1039*44704f69SBart Van Assche const uint8_t * cs_bp;
1040*44704f69SBart Van Assche
1041*44704f69SBart Van Assche sgj_pr_hr(jsp, " Constituent specific descriptors:\n");
1042*44704f69SBart Van Assche ja2p = sgj_named_subarray_r(jsp, jo2p,
1043*44704f69SBart Van Assche "constituent_specific_descriptor_list");
1044*44704f69SBart Van Assche for (m = 0, q = 0, cs_bp = bp + 36; m < csd_len;
1045*44704f69SBart Van Assche m += cs_bump, ++q, cs_bp += cs_bump) {
1046*44704f69SBart Van Assche jo3p = sgj_new_unattached_object_r(jsp);
1047*44704f69SBart Van Assche cs_type = cs_bp[0];
1048*44704f69SBart Van Assche cs_len = sg_get_unaligned_be16(cs_bp + 2);
1049*44704f69SBart Van Assche cs_bump = cs_len + 4;
1050*44704f69SBart Van Assche sgj_js_nv_ihex(jsp, jo3p, "constituent_specific_type",
1051*44704f69SBart Van Assche cs_type);
1052*44704f69SBart Van Assche if (1 == cs_type) { /* VPD page */
1053*44704f69SBart Van Assche int off = cs_bp + 4 - buff;
1054*44704f69SBart Van Assche
1055*44704f69SBart Van Assche sgj_pr_hr(jsp, " Constituent specific VPD page "
1056*44704f69SBart Van Assche "%d:\n", q + 1);
1057*44704f69SBart Van Assche /* SPC-5 says these shall _not_ themselves be Device
1058*44704f69SBart Van Assche * Constituent VPD pages. So no infinite recursion. */
1059*44704f69SBart Van Assche res = (*fp)(op, jo3p, off);
1060*44704f69SBart Van Assche if (res)
1061*44704f69SBart Van Assche pr2serr("%s: recurse_vpd_decode() failed, res=%d\n",
1062*44704f69SBart Van Assche __func__, res);
1063*44704f69SBart Van Assche } else {
1064*44704f69SBart Van Assche if (0xff == cs_type)
1065*44704f69SBart Van Assche sgj_pr_hr(jsp, " Vendor specific data (in "
1066*44704f69SBart Van Assche "hex):\n");
1067*44704f69SBart Van Assche else
1068*44704f69SBart Van Assche sgj_pr_hr(jsp, " %s [0x%x] specific data (in "
1069*44704f69SBart Van Assche "hex):\n", rsv_s, cs_type);
1070*44704f69SBart Van Assche if (jsp->pr_as_json)
1071*44704f69SBart Van Assche sgj_js_nv_hex_bytes(jsp, jo3p,
1072*44704f69SBart Van Assche "constituent_specific_data_hex",
1073*44704f69SBart Van Assche cs_bp + 4, cs_len);
1074*44704f69SBart Van Assche else
1075*44704f69SBart Van Assche hex2stdout(cs_bp + 4, cs_len, 0 /* plus ASCII */);
1076*44704f69SBart Van Assche }
1077*44704f69SBart Van Assche sgj_js_nv_o(jsp, ja2p, NULL, jo3p);
1078*44704f69SBart Van Assche } /* end of Constituent specific descriptor loop */
1079*44704f69SBart Van Assche }
1080*44704f69SBart Van Assche sgj_js_nv_o(jsp, jap, NULL, jo2p);
1081*44704f69SBart Van Assche } /* end Constituent descriptor loop */
1082*44704f69SBart Van Assche }
1083*44704f69SBart Van Assche
1084*44704f69SBart Van Assche /* VPD_CFA_PROFILE_INFO 0x8c ["cfa"] */
1085*44704f69SBart Van Assche void
decode_cga_profile_vpd(const uint8_t * buff,int len,struct opts_t * op,sgj_opaque_p jap)1086*44704f69SBart Van Assche decode_cga_profile_vpd(const uint8_t * buff, int len, struct opts_t * op,
1087*44704f69SBart Van Assche sgj_opaque_p jap)
1088*44704f69SBart Van Assche {
1089*44704f69SBart Van Assche int k;
1090*44704f69SBart Van Assche uint32_t u;
1091*44704f69SBart Van Assche sgj_state * jsp = &op->json_st;
1092*44704f69SBart Van Assche const uint8_t * bp;
1093*44704f69SBart Van Assche sgj_opaque_p jo2p;
1094*44704f69SBart Van Assche
1095*44704f69SBart Van Assche if (op->do_hex) {
1096*44704f69SBart Van Assche hex2stdout(buff, len, (1 == op->do_hex) ? 0 : -1);
1097*44704f69SBart Van Assche return;
1098*44704f69SBart Van Assche }
1099*44704f69SBart Van Assche if (len < 4) {
1100*44704f69SBart Van Assche pr2serr("VPD page length too short=%d\n", len);
1101*44704f69SBart Van Assche return;
1102*44704f69SBart Van Assche }
1103*44704f69SBart Van Assche len -= 4;
1104*44704f69SBart Van Assche bp = buff + 4;
1105*44704f69SBart Van Assche for (k = 0; k < len; k += 4, bp += 4) {
1106*44704f69SBart Van Assche jo2p = sgj_new_unattached_object_r(jsp);
1107*44704f69SBart Van Assche sgj_haj_vi(jsp, jo2p, 0, "CGA profile supported",
1108*44704f69SBart Van Assche SGJ_SEP_COLON_1_SPACE, bp[0], true);
1109*44704f69SBart Van Assche u = sg_get_unaligned_be16(bp + 2);
1110*44704f69SBart Van Assche sgj_haj_vi_nex(jsp, jo2p, 2, "Sequential write data size",
1111*44704f69SBart Van Assche SGJ_SEP_COLON_1_SPACE, u, true, "unit: LB");
1112*44704f69SBart Van Assche sgj_js_nv_o(jsp, jap, NULL /* name */, jo2p);
1113*44704f69SBart Van Assche }
1114*44704f69SBart Van Assche }
1115*44704f69SBart Van Assche
1116*44704f69SBart Van Assche /* Assume index is less than 16 */
1117*44704f69SBart Van Assche static const char * sg_ansi_version_arr[16] =
1118*44704f69SBart Van Assche {
1119*44704f69SBart Van Assche "no conformance claimed",
1120*44704f69SBart Van Assche "SCSI-1", /* obsolete, ANSI X3.131-1986 */
1121*44704f69SBart Van Assche "SCSI-2", /* obsolete, ANSI X3.131-1994 */
1122*44704f69SBart Van Assche "SPC", /* withdrawn, ANSI INCITS 301-1997 */
1123*44704f69SBart Van Assche "SPC-2", /* ANSI INCITS 351-2001, ISO/IEC 14776-452 */
1124*44704f69SBart Van Assche "SPC-3", /* ANSI INCITS 408-2005, ISO/IEC 14776-453 */
1125*44704f69SBart Van Assche "SPC-4", /* ANSI INCITS 513-2015 */
1126*44704f69SBart Van Assche "SPC-5", /* ANSI INCITS 502-2020 */
1127*44704f69SBart Van Assche "ecma=1, [8h]",
1128*44704f69SBart Van Assche "ecma=1, [9h]",
1129*44704f69SBart Van Assche "ecma=1, [Ah]",
1130*44704f69SBart Van Assche "ecma=1, [Bh]",
1131*44704f69SBart Van Assche "reserved [Ch]",
1132*44704f69SBart Van Assche "reserved [Dh]",
1133*44704f69SBart Van Assche "reserved [Eh]",
1134*44704f69SBart Van Assche "reserved [Fh]",
1135*44704f69SBart Van Assche };
1136*44704f69SBart Van Assche
1137*44704f69SBart Van Assche static const char *
hot_pluggable_str(int hp)1138*44704f69SBart Van Assche hot_pluggable_str(int hp)
1139*44704f69SBart Van Assche {
1140*44704f69SBart Van Assche switch (hp) {
1141*44704f69SBart Van Assche case 0:
1142*44704f69SBart Van Assche return "No information";
1143*44704f69SBart Van Assche case 1:
1144*44704f69SBart Van Assche return "target device designed to be removed from SCSI domain";
1145*44704f69SBart Van Assche case 2:
1146*44704f69SBart Van Assche return "target device not designed to be removed from SCSI domain";
1147*44704f69SBart Van Assche default:
1148*44704f69SBart Van Assche return "value reserved by T10";
1149*44704f69SBart Van Assche }
1150*44704f69SBart Van Assche }
1151*44704f69SBart Van Assche
1152*44704f69SBart Van Assche static const char *
tpgs_str(int tpgs)1153*44704f69SBart Van Assche tpgs_str(int tpgs)
1154*44704f69SBart Van Assche {
1155*44704f69SBart Van Assche switch (tpgs) {
1156*44704f69SBart Van Assche case 1:
1157*44704f69SBart Van Assche return "only implicit asymmetric logical unit access";
1158*44704f69SBart Van Assche case 2:
1159*44704f69SBart Van Assche return "only explicit asymmetric logical unit access";
1160*44704f69SBart Van Assche case 3:
1161*44704f69SBart Van Assche return "both explicit and implicit asymmetric logical unit access";
1162*44704f69SBart Van Assche case 0:
1163*44704f69SBart Van Assche default:
1164*44704f69SBart Van Assche return ns_s;
1165*44704f69SBart Van Assche }
1166*44704f69SBart Van Assche }
1167*44704f69SBart Van Assche
1168*44704f69SBart Van Assche sgj_opaque_p
std_inq_decode_js(const uint8_t * b,int len,struct opts_t * op,sgj_opaque_p jop)1169*44704f69SBart Van Assche std_inq_decode_js(const uint8_t * b, int len, struct opts_t * op,
1170*44704f69SBart Van Assche sgj_opaque_p jop)
1171*44704f69SBart Van Assche {
1172*44704f69SBart Van Assche int tpgs;
1173*44704f69SBart Van Assche int pqual = (b[0] & 0xe0) >> 5;
1174*44704f69SBart Van Assche int pdt = b[0] & PDT_MASK;
1175*44704f69SBart Van Assche int hp = (b[1] >> 4) & 0x3;
1176*44704f69SBart Van Assche int ver = b[2];
1177*44704f69SBart Van Assche sgj_state * jsp = &op->json_st;
1178*44704f69SBart Van Assche sgj_opaque_p jo2p = NULL;
1179*44704f69SBart Van Assche char c[256];
1180*44704f69SBart Van Assche static const int clen = sizeof(c);
1181*44704f69SBart Van Assche
1182*44704f69SBart Van Assche jo2p = sgj_named_subobject_r(jsp, jop, "standard_inquiry_data_format");
1183*44704f69SBart Van Assche sgj_js_nv_ihexstr(jsp, jo2p, "peripheral_qualifier", pqual, NULL,
1184*44704f69SBart Van Assche pqual_str(pqual));
1185*44704f69SBart Van Assche sgj_js_nv_ihexstr(jsp, jo2p, "peripheral_device_type", pdt, NULL,
1186*44704f69SBart Van Assche sg_get_pdt_str(pdt, clen, c));
1187*44704f69SBart Van Assche sgj_js_nv_ihex_nex(jsp, jo2p, "rmb", !!(b[1] & 0x80), false,
1188*44704f69SBart Van Assche "Removable Medium Bit");
1189*44704f69SBart Van Assche sgj_js_nv_ihex_nex(jsp, jo2p, "lu_cong", !!(b[1] & 0x40), false,
1190*44704f69SBart Van Assche "Logical Unit Conglomerate");
1191*44704f69SBart Van Assche sgj_js_nv_ihexstr(jsp, jo2p, "hot_pluggable", hp, NULL,
1192*44704f69SBart Van Assche hot_pluggable_str(hp));
1193*44704f69SBart Van Assche snprintf(c, clen, "%s", (ver > 0xf) ? "old or reserved version code" :
1194*44704f69SBart Van Assche sg_ansi_version_arr[ver]);
1195*44704f69SBart Van Assche sgj_js_nv_ihexstr(jsp, jo2p, "version", ver, NULL, c);
1196*44704f69SBart Van Assche sgj_js_nv_ihex_nex(jsp, jo2p, "aerc", !!(b[3] & 0x80), false,
1197*44704f69SBart Van Assche "Asynchronous Event Reporting Capability (obsolete "
1198*44704f69SBart Van Assche "SPC-3)");
1199*44704f69SBart Van Assche sgj_js_nv_ihex_nex(jsp, jo2p, "trmtsk", !!(b[3] & 0x40), false,
1200*44704f69SBart Van Assche "Terminate Task (obsolete SPC-2)");
1201*44704f69SBart Van Assche sgj_js_nv_ihex_nex(jsp, jo2p, "normaca", !!(b[3] & 0x20), false,
1202*44704f69SBart Van Assche "Normal ACA (Auto Contingent Allegiance)");
1203*44704f69SBart Van Assche sgj_js_nv_ihex_nex(jsp, jo2p, "hisup", !!(b[3] & 0x10), false,
1204*44704f69SBart Van Assche "Hierarchial Support");
1205*44704f69SBart Van Assche sgj_js_nv_ihex(jsp, jo2p, "response_data_format", b[3] & 0xf);
1206*44704f69SBart Van Assche sgj_js_nv_ihex_nex(jsp, jo2p, "sccs", !!(b[5] & 0x80), false,
1207*44704f69SBart Van Assche "SCC (SCSI Storage Commands) Supported");
1208*44704f69SBart Van Assche sgj_js_nv_ihex_nex(jsp, jo2p, "acc", !!(b[5] & 0x40), false,
1209*44704f69SBart Van Assche "Access Commands Coordinator (obsolete SPC-5)");
1210*44704f69SBart Van Assche tpgs = (b[5] >> 4) & 0x3;
1211*44704f69SBart Van Assche sgj_js_nv_ihexstr_nex(jsp, jo2p, "tpgs", tpgs, false, NULL,
1212*44704f69SBart Van Assche tpgs_str(tpgs), "Target Port Group Support");
1213*44704f69SBart Van Assche sgj_js_nv_ihex_nex(jsp, jo2p, "3pc", !!(b[5] & 0x8), false,
1214*44704f69SBart Van Assche "Third Party Copy");
1215*44704f69SBart Van Assche sgj_js_nv_ihex(jsp, jo2p, "protect", !!(b[5] & 0x1));
1216*44704f69SBart Van Assche /* Skip SPI specific flags which have been obsolete for a while) */
1217*44704f69SBart Van Assche sgj_js_nv_ihex_nex(jsp, jo2p, "bque", !!(b[6] & 0x80), false,
1218*44704f69SBart Van Assche "Basic task management model (obsolete SPC-4)");
1219*44704f69SBart Van Assche sgj_js_nv_ihex_nex(jsp, jo2p, "encserv", !!(b[6] & 0x40), false,
1220*44704f69SBart Van Assche "Enclousure Services supported");
1221*44704f69SBart Van Assche sgj_js_nv_ihex_nex(jsp, jo2p, "multip", !!(b[6] & 0x10), false,
1222*44704f69SBart Van Assche "Multiple SCSI port");
1223*44704f69SBart Van Assche sgj_js_nv_ihex_nex(jsp, jo2p, "mchngr", !!(b[6] & 0x8), false,
1224*44704f69SBart Van Assche "Medium changer (obsolete SPC-4)");
1225*44704f69SBart Van Assche sgj_js_nv_ihex_nex(jsp, jo2p, "reladr", !!(b[7] & 0x80), false,
1226*44704f69SBart Van Assche "Relative Addressing (obsolete in SPC-4)");
1227*44704f69SBart Van Assche sgj_js_nv_ihex_nex(jsp, jo2p, "linked", !!(b[7] & 0x8), false,
1228*44704f69SBart Van Assche "Linked Commands (obsolete in SPC-4)");
1229*44704f69SBart Van Assche sgj_js_nv_ihex_nex(jsp, jo2p, "cmdque", !!(b[7] & 0x2), false,
1230*44704f69SBart Van Assche "Command Management Model (command queuing)");
1231*44704f69SBart Van Assche if (len < 16)
1232*44704f69SBart Van Assche return jo2p;
1233*44704f69SBart Van Assche snprintf(c, clen, "%.8s", b + 8);
1234*44704f69SBart Van Assche sgj_js_nv_s(jsp, jo2p, t10_vendor_id_js, c);
1235*44704f69SBart Van Assche if (len < 32)
1236*44704f69SBart Van Assche return jo2p;
1237*44704f69SBart Van Assche snprintf(c, clen, "%.16s", b + 16);
1238*44704f69SBart Van Assche sgj_js_nv_s(jsp, jo2p, product_id_js, c);
1239*44704f69SBart Van Assche if (len < 36)
1240*44704f69SBart Van Assche return jo2p;
1241*44704f69SBart Van Assche snprintf(c, clen, "%.4s", b + 32);
1242*44704f69SBart Van Assche sgj_js_nv_s(jsp, jo2p, product_rev_lev_js, c);
1243*44704f69SBart Van Assche return jo2p;
1244*44704f69SBart Van Assche }
1245*44704f69SBart Van Assche
1246*44704f69SBart Van Assche static const char * power_unit_arr[] =
1247*44704f69SBart Van Assche {
1248*44704f69SBart Van Assche "Gigawatts",
1249*44704f69SBart Van Assche "Megawatts",
1250*44704f69SBart Van Assche "Kilowatts",
1251*44704f69SBart Van Assche "Watts",
1252*44704f69SBart Van Assche "Milliwatts",
1253*44704f69SBart Van Assche "Microwatts",
1254*44704f69SBart Van Assche "Unit reserved",
1255*44704f69SBart Van Assche "Unit reserved",
1256*44704f69SBart Van Assche };
1257*44704f69SBart Van Assche
1258*44704f69SBart Van Assche /* VPD_POWER_CONSUMPTION 0x8d ["psm"] */
1259*44704f69SBart Van Assche void
decode_power_consumption(const uint8_t * buff,int len,struct opts_t * op,sgj_opaque_p jap)1260*44704f69SBart Van Assche decode_power_consumption(const uint8_t * buff, int len, struct opts_t * op,
1261*44704f69SBart Van Assche sgj_opaque_p jap)
1262*44704f69SBart Van Assche {
1263*44704f69SBart Van Assche int k, bump, pcmp_id, pcmp_unit;
1264*44704f69SBart Van Assche unsigned int pcmp_val;
1265*44704f69SBart Van Assche sgj_state * jsp = &op->json_st;
1266*44704f69SBart Van Assche sgj_opaque_p jo2p;
1267*44704f69SBart Van Assche const uint8_t * bp;
1268*44704f69SBart Van Assche char b[128];
1269*44704f69SBart Van Assche static const int blen = sizeof(b);
1270*44704f69SBart Van Assche static const char * pcmp = "power_consumption";
1271*44704f69SBart Van Assche static const char * pci = "Power consumption identifier";
1272*44704f69SBart Van Assche static const char * mpc = "Maximum power consumption";
1273*44704f69SBart Van Assche
1274*44704f69SBart Van Assche if ((1 == op->do_hex) || (op->do_hex > 2)) {
1275*44704f69SBart Van Assche hex2stdout(buff, len, (1 == op->do_hex) ? 1 : -1);
1276*44704f69SBart Van Assche return;
1277*44704f69SBart Van Assche }
1278*44704f69SBart Van Assche if (len < 4) {
1279*44704f69SBart Van Assche pr2serr("length too short=%d\n", len);
1280*44704f69SBart Van Assche return;
1281*44704f69SBart Van Assche }
1282*44704f69SBart Van Assche len -= 4;
1283*44704f69SBart Van Assche bp = buff + 4;
1284*44704f69SBart Van Assche for (k = 0; k < len; k += bump, bp += bump) {
1285*44704f69SBart Van Assche bump = 4;
1286*44704f69SBart Van Assche if ((k + bump) > len) {
1287*44704f69SBart Van Assche pr2serr("short descriptor length=%d, left=%d\n", bump,
1288*44704f69SBart Van Assche (len - k));
1289*44704f69SBart Van Assche return;
1290*44704f69SBart Van Assche }
1291*44704f69SBart Van Assche if (op->do_hex > 1)
1292*44704f69SBart Van Assche hex2stdout(bp, 4, 1);
1293*44704f69SBart Van Assche else {
1294*44704f69SBart Van Assche jo2p = sgj_new_unattached_object_r(jsp);
1295*44704f69SBart Van Assche pcmp_id = bp[0];
1296*44704f69SBart Van Assche pcmp_unit = 0x7 & bp[1];
1297*44704f69SBart Van Assche pcmp_val = sg_get_unaligned_be16(bp + 2);
1298*44704f69SBart Van Assche if (jsp->pr_as_json) {
1299*44704f69SBart Van Assche sgj_convert_to_snake_name(pci, b, blen);
1300*44704f69SBart Van Assche sgj_js_nv_ihex(jsp, jo2p, b, pcmp_id);
1301*44704f69SBart Van Assche snprintf(b, blen, "%s_units", pcmp);
1302*44704f69SBart Van Assche sgj_js_nv_ihexstr(jsp, jo2p, b, pcmp_unit, NULL,
1303*44704f69SBart Van Assche power_unit_arr[pcmp_unit]);
1304*44704f69SBart Van Assche snprintf(b, blen, "%s_value", pcmp);
1305*44704f69SBart Van Assche sgj_js_nv_ihex(jsp, jo2p, b, pcmp_val);
1306*44704f69SBart Van Assche }
1307*44704f69SBart Van Assche snprintf(b, blen, " %s: 0x%x", pci, pcmp_id);
1308*44704f69SBart Van Assche if (pcmp_val >= 1000 && pcmp_unit > 0)
1309*44704f69SBart Van Assche sgj_pr_hr(jsp, "%s %s: %d.%03d %s\n", b, mpc,
1310*44704f69SBart Van Assche pcmp_val / 1000, pcmp_val % 1000,
1311*44704f69SBart Van Assche power_unit_arr[pcmp_unit - 1]); /* up one unit */
1312*44704f69SBart Van Assche else
1313*44704f69SBart Van Assche sgj_pr_hr(jsp, "%s %s: %u %s\n", b, mpc, pcmp_val,
1314*44704f69SBart Van Assche power_unit_arr[pcmp_unit]);
1315*44704f69SBart Van Assche sgj_js_nv_o(jsp, jap, NULL /* name */, jo2p);
1316*44704f69SBart Van Assche }
1317*44704f69SBart Van Assche }
1318*44704f69SBart Van Assche }
1319*44704f69SBart Van Assche
1320*44704f69SBart Van Assche
1321*44704f69SBart Van Assche /* VPD_BLOCK_LIMITS 0xb0 ["bl"] */
1322*44704f69SBart Van Assche void
decode_block_limits_vpd(const uint8_t * buff,int len,struct opts_t * op,sgj_opaque_p jop)1323*44704f69SBart Van Assche decode_block_limits_vpd(const uint8_t * buff, int len, struct opts_t * op,
1324*44704f69SBart Van Assche sgj_opaque_p jop)
1325*44704f69SBart Van Assche {
1326*44704f69SBart Van Assche int wsnz, ugavalid;
1327*44704f69SBart Van Assche uint32_t u;
1328*44704f69SBart Van Assche uint64_t ull;
1329*44704f69SBart Van Assche sgj_state * jsp = &op->json_st;
1330*44704f69SBart Van Assche char b[144];
1331*44704f69SBart Van Assche static const int blen = sizeof(b);
1332*44704f69SBart Van Assche static const char * mcawl = "Maximum compare and write length";
1333*44704f69SBart Van Assche static const char * otlg = "Optimal transfer length granularity";
1334*44704f69SBart Van Assche static const char * cni = "command not implemented";
1335*44704f69SBart Van Assche static const char * ul = "unlimited";
1336*44704f69SBart Van Assche static const char * mtl = "Maximum transfer length";
1337*44704f69SBart Van Assche static const char * otl = "Optimal transfer length";
1338*44704f69SBart Van Assche static const char * mpl = "Maximum prefetch length";
1339*44704f69SBart Van Assche static const char * mulc = "Maximum unmap LBA count";
1340*44704f69SBart Van Assche static const char * mubdc = "Maximum unmap block descriptor count";
1341*44704f69SBart Van Assche static const char * oug = "Optimal unmap granularity";
1342*44704f69SBart Van Assche static const char * ugav = "Unmap granularity alignment valid";
1343*44704f69SBart Van Assche static const char * uga = "Unmap granularity alignment";
1344*44704f69SBart Van Assche static const char * mwsl = "Maximum write same length";
1345*44704f69SBart Van Assche static const char * matl = "Maximum atomic transfer length";
1346*44704f69SBart Van Assche static const char * aa = "Atomic alignment";
1347*44704f69SBart Van Assche static const char * atlg = "Atomic transfer length granularity";
1348*44704f69SBart Van Assche static const char * matlwab = "Maximum atomic transfer length with "
1349*44704f69SBart Van Assche "atomic boundary";
1350*44704f69SBart Van Assche static const char * mabs = "Maximum atomic boundary size";
1351*44704f69SBart Van Assche
1352*44704f69SBart Van Assche if (len < 16) {
1353*44704f69SBart Van Assche pr2serr("page length too short=%d\n", len);
1354*44704f69SBart Van Assche return;
1355*44704f69SBart Van Assche }
1356*44704f69SBart Van Assche wsnz = !!(buff[4] & 0x1);
1357*44704f69SBart Van Assche sgj_pr_hr(jsp, " Write same non-zero (WSNZ): %d\n", wsnz);
1358*44704f69SBart Van Assche sgj_js_nv_ihex_nex(jsp, jop, "wsnz", wsnz, false,
1359*44704f69SBart Van Assche "Write Same Non-Zero (number of LBs must be > 0)");
1360*44704f69SBart Van Assche u = buff[5];
1361*44704f69SBart Van Assche if (0 == u) {
1362*44704f69SBart Van Assche sgj_pr_hr(jsp, " %s: 0 blocks [%s]\n", mcawl, cni);
1363*44704f69SBart Van Assche sgj_convert_to_snake_name(mcawl, b, blen);
1364*44704f69SBart Van Assche sgj_js_nv_ihexstr(jsp, jop, b, u, NULL, cni);
1365*44704f69SBart Van Assche } else
1366*44704f69SBart Van Assche sgj_haj_vi_nex(jsp, jop, 2, mcawl, SGJ_SEP_COLON_1_SPACE, u,
1367*44704f69SBart Van Assche true, "unit: LB");
1368*44704f69SBart Van Assche
1369*44704f69SBart Van Assche u = sg_get_unaligned_be16(buff + 6);
1370*44704f69SBart Van Assche if (0 == u) {
1371*44704f69SBart Van Assche sgj_pr_hr(jsp, " %s: 0 blocks [%s]\n", otlg, nr_s);
1372*44704f69SBart Van Assche sgj_convert_to_snake_name(otlg, b, blen);
1373*44704f69SBart Van Assche sgj_js_nv_ihexstr(jsp, jop, b, u, NULL, nr_s);
1374*44704f69SBart Van Assche } else
1375*44704f69SBart Van Assche sgj_haj_vi_nex(jsp, jop, 2, otlg, SGJ_SEP_COLON_1_SPACE, u,
1376*44704f69SBart Van Assche true, "unit: LB");
1377*44704f69SBart Van Assche
1378*44704f69SBart Van Assche u = sg_get_unaligned_be32(buff + 8);
1379*44704f69SBart Van Assche if (0 == u) {
1380*44704f69SBart Van Assche sgj_pr_hr(jsp, " %s: 0 blocks [%s]\n", mtl, nr_s);
1381*44704f69SBart Van Assche sgj_convert_to_snake_name(mtl, b, blen);
1382*44704f69SBart Van Assche sgj_js_nv_ihexstr(jsp, jop, b, u, NULL, nr_s);
1383*44704f69SBart Van Assche } else
1384*44704f69SBart Van Assche sgj_haj_vi_nex(jsp, jop, 2, mtl, SGJ_SEP_COLON_1_SPACE, u,
1385*44704f69SBart Van Assche true, "unit: LB");
1386*44704f69SBart Van Assche
1387*44704f69SBart Van Assche u = sg_get_unaligned_be32(buff + 12);
1388*44704f69SBart Van Assche if (0 == u) {
1389*44704f69SBart Van Assche sgj_pr_hr(jsp, " %s: 0 blocks [%s]\n", otl, nr_s);
1390*44704f69SBart Van Assche sgj_convert_to_snake_name(otl, b, blen);
1391*44704f69SBart Van Assche sgj_js_nv_ihexstr(jsp, jop, b, u, NULL, nr_s);
1392*44704f69SBart Van Assche } else
1393*44704f69SBart Van Assche sgj_haj_vi_nex(jsp, jop, 2, otl, SGJ_SEP_COLON_1_SPACE, u,
1394*44704f69SBart Van Assche true, "unit: LB");
1395*44704f69SBart Van Assche if (len > 19) { /* added in sbc3r09 */
1396*44704f69SBart Van Assche u = sg_get_unaligned_be32(buff + 16);
1397*44704f69SBart Van Assche if (0 == u) {
1398*44704f69SBart Van Assche sgj_pr_hr(jsp, " %s: 0 blocks [%s]\n", mpl, nr_s);
1399*44704f69SBart Van Assche sgj_convert_to_snake_name(mpl, b, blen);
1400*44704f69SBart Van Assche sgj_js_nv_ihexstr(jsp, jop, b, u, NULL, nr_s);
1401*44704f69SBart Van Assche } else
1402*44704f69SBart Van Assche sgj_haj_vi_nex(jsp, jop, 2, mpl, SGJ_SEP_COLON_1_SPACE, u,
1403*44704f69SBart Van Assche true, "unit: LB");
1404*44704f69SBart Van Assche }
1405*44704f69SBart Van Assche if (len > 27) { /* added in sbc3r18 */
1406*44704f69SBart Van Assche u = sg_get_unaligned_be32(buff + 20);
1407*44704f69SBart Van Assche sgj_convert_to_snake_name(mulc, b, blen);
1408*44704f69SBart Van Assche if (0 == u) {
1409*44704f69SBart Van Assche sgj_pr_hr(jsp, " %s: 0 blocks [%s]\n", mulc, cni);
1410*44704f69SBart Van Assche sgj_js_nv_ihexstr(jsp, jop, b, u, NULL, cni);
1411*44704f69SBart Van Assche } else if (0xffffffff == u) {
1412*44704f69SBart Van Assche sgj_pr_hr(jsp, " %s: %s blocks\n", ul, mulc);
1413*44704f69SBart Van Assche sgj_js_nv_ihexstr(jsp, jop, b, u, NULL, ul);
1414*44704f69SBart Van Assche } else
1415*44704f69SBart Van Assche sgj_haj_vi_nex(jsp, jop, 2, mulc, SGJ_SEP_COLON_1_SPACE, u,
1416*44704f69SBart Van Assche true, "unit: LB");
1417*44704f69SBart Van Assche
1418*44704f69SBart Van Assche u = sg_get_unaligned_be32(buff + 24);
1419*44704f69SBart Van Assche sgj_convert_to_snake_name(mulc, b, blen);
1420*44704f69SBart Van Assche if (0 == u) {
1421*44704f69SBart Van Assche sgj_pr_hr(jsp, " %s: 0 block descriptors [%s]\n", mubdc, cni);
1422*44704f69SBart Van Assche sgj_js_nv_ihexstr(jsp, jop, b, u, NULL, cni);
1423*44704f69SBart Van Assche } else if (0xffffffff == u) {
1424*44704f69SBart Van Assche sgj_pr_hr(jsp, " %s: %s block descriptors\n", ul, mubdc);
1425*44704f69SBart Van Assche sgj_js_nv_ihexstr(jsp, jop, b, u, NULL, ul);
1426*44704f69SBart Van Assche } else
1427*44704f69SBart Van Assche sgj_haj_vi(jsp, jop, 2, mubdc, SGJ_SEP_COLON_1_SPACE,
1428*44704f69SBart Van Assche u, true);
1429*44704f69SBart Van Assche }
1430*44704f69SBart Van Assche if (len > 35) { /* added in sbc3r19 */
1431*44704f69SBart Van Assche u = sg_get_unaligned_be32(buff + 28);
1432*44704f69SBart Van Assche if (0 == u) {
1433*44704f69SBart Van Assche sgj_pr_hr(jsp, " %s: 0 blocks [%s]\n", oug, nr_s);
1434*44704f69SBart Van Assche sgj_convert_to_snake_name(oug, b, blen);
1435*44704f69SBart Van Assche sgj_js_nv_ihexstr(jsp, jop, b, u, NULL, nr_s);
1436*44704f69SBart Van Assche } else
1437*44704f69SBart Van Assche sgj_haj_vi_nex(jsp, jop, 2, oug, SGJ_SEP_COLON_1_SPACE, u,
1438*44704f69SBart Van Assche true, "unit: LB");
1439*44704f69SBart Van Assche
1440*44704f69SBart Van Assche ugavalid = !!(buff[32] & 0x80);
1441*44704f69SBart Van Assche sgj_pr_hr(jsp, " %s: %s\n", ugav, ugavalid ? "true" : "false");
1442*44704f69SBart Van Assche sgj_js_nv_i(jsp, jop, ugav, ugavalid);
1443*44704f69SBart Van Assche if (ugavalid) {
1444*44704f69SBart Van Assche u = 0x7fffffff & sg_get_unaligned_be32(buff + 32);
1445*44704f69SBart Van Assche sgj_haj_vi_nex(jsp, jop, 2, uga, SGJ_SEP_COLON_1_SPACE, u,
1446*44704f69SBart Van Assche true, "unit: LB");
1447*44704f69SBart Van Assche }
1448*44704f69SBart Van Assche }
1449*44704f69SBart Van Assche if (len > 43) { /* added in sbc3r26 */
1450*44704f69SBart Van Assche ull = sg_get_unaligned_be64(buff + 36);
1451*44704f69SBart Van Assche if (0 == ull) {
1452*44704f69SBart Van Assche sgj_pr_hr(jsp, " %s: 0 blocks [%s]\n", mwsl, nr_s);
1453*44704f69SBart Van Assche sgj_convert_to_snake_name(mwsl, b, blen);
1454*44704f69SBart Van Assche sgj_js_nv_ihexstr(jsp, jop, b, ull, NULL, nr_s);
1455*44704f69SBart Van Assche } else
1456*44704f69SBart Van Assche sgj_haj_vi_nex(jsp, jop, 2, mwsl, SGJ_SEP_COLON_1_SPACE,
1457*44704f69SBart Van Assche ull, true, "unit: LB");
1458*44704f69SBart Van Assche }
1459*44704f69SBart Van Assche if (len > 47) { /* added in sbc4r02 */
1460*44704f69SBart Van Assche u = sg_get_unaligned_be32(buff + 44);
1461*44704f69SBart Van Assche if (0 == u) {
1462*44704f69SBart Van Assche sgj_pr_hr(jsp, " %s: 0 blocks [%s]\n", matl, nr_s);
1463*44704f69SBart Van Assche sgj_convert_to_snake_name(matl, b, blen);
1464*44704f69SBart Van Assche sgj_js_nv_ihexstr(jsp, jop, b, u, NULL, nr_s);
1465*44704f69SBart Van Assche } else
1466*44704f69SBart Van Assche sgj_haj_vi_nex(jsp, jop, 2, matl, SGJ_SEP_COLON_1_SPACE,
1467*44704f69SBart Van Assche u, true, "unit: LB");
1468*44704f69SBart Van Assche
1469*44704f69SBart Van Assche u = sg_get_unaligned_be32(buff + 48);
1470*44704f69SBart Van Assche if (0 == u) {
1471*44704f69SBart Van Assche static const char * uawp = "unaligned atomic writes permitted";
1472*44704f69SBart Van Assche
1473*44704f69SBart Van Assche sgj_pr_hr(jsp, " %s: 0 blocks [%s]\n", aa, uawp);
1474*44704f69SBart Van Assche sgj_convert_to_snake_name(aa, b, blen);
1475*44704f69SBart Van Assche sgj_js_nv_ihexstr(jsp, jop, b, u, NULL, uawp);
1476*44704f69SBart Van Assche } else
1477*44704f69SBart Van Assche sgj_haj_vi_nex(jsp, jop, 2, aa, SGJ_SEP_COLON_1_SPACE,
1478*44704f69SBart Van Assche u, true, "unit: LB");
1479*44704f69SBart Van Assche
1480*44704f69SBart Van Assche u = sg_get_unaligned_be32(buff + 52);
1481*44704f69SBart Van Assche if (0 == u) {
1482*44704f69SBart Van Assche static const char * ngr = "no granularity requirement";
1483*44704f69SBart Van Assche
1484*44704f69SBart Van Assche sgj_pr_hr(jsp, " %s: 0 blocks [%s]\n", atlg, ngr);
1485*44704f69SBart Van Assche sgj_convert_to_snake_name(atlg, b, blen);
1486*44704f69SBart Van Assche sgj_js_nv_ihexstr(jsp, jop, b, u, NULL, ngr);
1487*44704f69SBart Van Assche } else
1488*44704f69SBart Van Assche sgj_haj_vi_nex(jsp, jop, 2, aa, SGJ_SEP_COLON_1_SPACE,
1489*44704f69SBart Van Assche u, true, "unit: LB");
1490*44704f69SBart Van Assche }
1491*44704f69SBart Van Assche if (len > 56) {
1492*44704f69SBart Van Assche u = sg_get_unaligned_be32(buff + 56);
1493*44704f69SBart Van Assche if (0 == u) {
1494*44704f69SBart Van Assche sgj_pr_hr(jsp, " %s: 0 blocks [%s]\n", matlwab, nr_s);
1495*44704f69SBart Van Assche sgj_convert_to_snake_name(matlwab, b, blen);
1496*44704f69SBart Van Assche sgj_js_nv_ihexstr(jsp, jop, b, u, NULL, nr_s);
1497*44704f69SBart Van Assche } else
1498*44704f69SBart Van Assche sgj_haj_vi_nex(jsp, jop, 2, matlwab, SGJ_SEP_COLON_1_SPACE,
1499*44704f69SBart Van Assche u, true, "unit: LB");
1500*44704f69SBart Van Assche
1501*44704f69SBart Van Assche u = sg_get_unaligned_be32(buff + 60);
1502*44704f69SBart Van Assche if (0 == u) {
1503*44704f69SBart Van Assche static const char * cowa1b = "can only write atomic 1 block";
1504*44704f69SBart Van Assche
1505*44704f69SBart Van Assche sgj_pr_hr(jsp, " %s: 0 blocks [%s]\n", mabs, cowa1b);
1506*44704f69SBart Van Assche sgj_convert_to_snake_name(mabs, b, blen);
1507*44704f69SBart Van Assche sgj_js_nv_ihexstr(jsp, jop, b, u, NULL, cowa1b);
1508*44704f69SBart Van Assche } else
1509*44704f69SBart Van Assche sgj_haj_vi_nex(jsp, jop, 2, mabs, SGJ_SEP_COLON_1_SPACE,
1510*44704f69SBart Van Assche u, true, "unit: LB");
1511*44704f69SBart Van Assche }
1512*44704f69SBart Van Assche }
1513*44704f69SBart Van Assche
1514*44704f69SBart Van Assche static const char * product_type_arr[] =
1515*44704f69SBart Van Assche {
1516*44704f69SBart Van Assche "Not specified",
1517*44704f69SBart Van Assche "CFast",
1518*44704f69SBart Van Assche "CompactFlash",
1519*44704f69SBart Van Assche "MemoryStick",
1520*44704f69SBart Van Assche "MultiMediaCard",
1521*44704f69SBart Van Assche "Secure Digital Card (SD)",
1522*44704f69SBart Van Assche "XQD",
1523*44704f69SBart Van Assche "Universal Flash Storage Card (UFS)",
1524*44704f69SBart Van Assche };
1525*44704f69SBart Van Assche
1526*44704f69SBart Van Assche /* ZONED field here replaced by ZONED BLOCK DEVICE EXTENSION field in the
1527*44704f69SBart Van Assche * Zoned Block Device Characteristics VPD page. The new field includes
1528*44704f69SBart Van Assche * Zone Domains and Realms (see ZBC-2) */
1529*44704f69SBart Van Assche static const char * bdc_zoned_strs[] = {
1530*44704f69SBart Van Assche nr_s,
1531*44704f69SBart Van Assche "host-aware",
1532*44704f69SBart Van Assche "host-managed",
1533*44704f69SBart Van Assche rsv_s,
1534*44704f69SBart Van Assche };
1535*44704f69SBart Van Assche
1536*44704f69SBart Van Assche /* VPD_BLOCK_DEV_CHARS 0xb1 ["bdc"] */
1537*44704f69SBart Van Assche void
decode_block_dev_ch_vpd(const uint8_t * buff,int len,struct opts_t * op,sgj_opaque_p jop)1538*44704f69SBart Van Assche decode_block_dev_ch_vpd(const uint8_t * buff, int len, struct opts_t * op,
1539*44704f69SBart Van Assche sgj_opaque_p jop)
1540*44704f69SBart Van Assche {
1541*44704f69SBart Van Assche int zoned;
1542*44704f69SBart Van Assche unsigned int u, k;
1543*44704f69SBart Van Assche sgj_state * jsp = &op->json_st;
1544*44704f69SBart Van Assche const char * cp;
1545*44704f69SBart Van Assche char b[144];
1546*44704f69SBart Van Assche static const char * mrr_j = "medium_rotation_rate";
1547*44704f69SBart Van Assche static const char * mrr_h = "Medium rotation rate";
1548*44704f69SBart Van Assche static const char * nrm = "Non-rotating medium (e.g. solid state)";
1549*44704f69SBart Van Assche static const char * pt_j = "product_type";
1550*44704f69SBart Van Assche
1551*44704f69SBart Van Assche if (len < 64) {
1552*44704f69SBart Van Assche pr2serr("page length too short=%d\n", len);
1553*44704f69SBart Van Assche return;
1554*44704f69SBart Van Assche }
1555*44704f69SBart Van Assche u = sg_get_unaligned_be16(buff + 4);
1556*44704f69SBart Van Assche if (0 == u) {
1557*44704f69SBart Van Assche sgj_pr_hr(jsp, " %s is %s\n", mrr_h, nr_s);
1558*44704f69SBart Van Assche sgj_js_nv_ihexstr(jsp, jop, mrr_j, 0, NULL, nr_s);
1559*44704f69SBart Van Assche } else if (1 == u) {
1560*44704f69SBart Van Assche sgj_pr_hr(jsp, " %s\n", nrm);
1561*44704f69SBart Van Assche sgj_js_nv_ihexstr(jsp, jop, mrr_j, 1, NULL, nrm);
1562*44704f69SBart Van Assche } else if ((u < 0x401) || (0xffff == u)) {
1563*44704f69SBart Van Assche sgj_pr_hr(jsp, " %s [0x%x]\n", rsv_s, u);
1564*44704f69SBart Van Assche sgj_js_nv_ihexstr(jsp, jop, mrr_j, u, NULL, rsv_s);
1565*44704f69SBart Van Assche } else {
1566*44704f69SBart Van Assche sgj_js_nv_ihex_nex(jsp, jop, mrr_j, u, true,
1567*44704f69SBart Van Assche "unit: rpm; nominal rotation rate");
1568*44704f69SBart Van Assche }
1569*44704f69SBart Van Assche u = buff[6];
1570*44704f69SBart Van Assche k = SG_ARRAY_SIZE(product_type_arr);
1571*44704f69SBart Van Assche if (u < k) {
1572*44704f69SBart Van Assche sgj_pr_hr(jsp, " %s: %s\n", "Product type", product_type_arr[u]);
1573*44704f69SBart Van Assche sgj_js_nv_ihexstr(jsp, jop, pt_j, u, NULL, product_type_arr[u]);
1574*44704f69SBart Van Assche } else {
1575*44704f69SBart Van Assche sgj_pr_hr(jsp, " %s: %s [0x%x]\n", "Product type",
1576*44704f69SBart Van Assche (u < 0xf0) ? rsv_s : vs_s, u);
1577*44704f69SBart Van Assche sgj_js_nv_ihexstr(jsp, jop, pt_j, u, NULL, (u < 0xf0) ? rsv_s : vs_s);
1578*44704f69SBart Van Assche }
1579*44704f69SBart Van Assche sgj_haj_vi_nex(jsp, jop, 2, "WABEREQ", SGJ_SEP_EQUAL_NO_SPACE,
1580*44704f69SBart Van Assche (buff[7] >> 6) & 0x3, false,
1581*44704f69SBart Van Assche "Write After Block Erase REQuired");
1582*44704f69SBart Van Assche sgj_haj_vi_nex(jsp, jop, 2, "WACEREQ", SGJ_SEP_EQUAL_NO_SPACE,
1583*44704f69SBart Van Assche (buff[7] >> 4) & 0x3, false,
1584*44704f69SBart Van Assche "Write After Cryptographic Erase REQuired");
1585*44704f69SBart Van Assche u = buff[7] & 0xf;
1586*44704f69SBart Van Assche switch (u) {
1587*44704f69SBart Van Assche case 0:
1588*44704f69SBart Van Assche strcpy(b, nr_s);
1589*44704f69SBart Van Assche break;
1590*44704f69SBart Van Assche case 1:
1591*44704f69SBart Van Assche strcpy(b, "5.25 inch");
1592*44704f69SBart Van Assche break;
1593*44704f69SBart Van Assche case 2:
1594*44704f69SBart Van Assche strcpy(b, "3.5 inch");
1595*44704f69SBart Van Assche break;
1596*44704f69SBart Van Assche case 3:
1597*44704f69SBart Van Assche strcpy(b, "2.5 inch");
1598*44704f69SBart Van Assche break;
1599*44704f69SBart Van Assche case 4:
1600*44704f69SBart Van Assche strcpy(b, "1.8 inch");
1601*44704f69SBart Van Assche break;
1602*44704f69SBart Van Assche case 5:
1603*44704f69SBart Van Assche strcpy(b, "less then 1.8 inch");
1604*44704f69SBart Van Assche break;
1605*44704f69SBart Van Assche default:
1606*44704f69SBart Van Assche strcpy(b, rsv_s);
1607*44704f69SBart Van Assche break;
1608*44704f69SBart Van Assche }
1609*44704f69SBart Van Assche sgj_pr_hr(jsp, " Nominal form factor: %s\n", b);
1610*44704f69SBart Van Assche sgj_js_nv_ihexstr(jsp, jop, "nominal_forn_factor", u, NULL, b);
1611*44704f69SBart Van Assche sgj_haj_vi_nex(jsp, jop, 2, "MACT", SGJ_SEP_EQUAL_NO_SPACE,
1612*44704f69SBart Van Assche !!(buff[8] & 0x40), false, "Multiple ACTuator");
1613*44704f69SBart Van Assche zoned = (buff[8] >> 4) & 0x3; /* added sbc4r04, obsolete sbc5r01 */
1614*44704f69SBart Van Assche cp = bdc_zoned_strs[zoned];
1615*44704f69SBart Van Assche sgj_pr_hr(jsp, " ZONED=%d [%s]\n", zoned, cp);
1616*44704f69SBart Van Assche sgj_js_nv_ihexstr_nex(jsp, jop, "zoned", zoned, false, NULL,
1617*44704f69SBart Van Assche cp, "Added in SBC-4, obsolete in SBC-5");
1618*44704f69SBart Van Assche sgj_haj_vi_nex(jsp, jop, 2, "RBWZ", SGJ_SEP_EQUAL_NO_SPACE,
1619*44704f69SBart Van Assche !!(buff[8] & 0x4), false,
1620*44704f69SBart Van Assche "Background Operation Control Supported");
1621*44704f69SBart Van Assche sgj_haj_vi_nex(jsp, jop, 2, "FUAB", SGJ_SEP_EQUAL_NO_SPACE,
1622*44704f69SBart Van Assche !!(buff[8] & 0x2), false,
1623*44704f69SBart Van Assche "Force Unit Access Behaviour");
1624*44704f69SBart Van Assche sgj_haj_vi_nex(jsp, jop, 2, "VBULS", SGJ_SEP_EQUAL_NO_SPACE,
1625*44704f69SBart Van Assche !!(buff[8] & 0x1), false,
1626*44704f69SBart Van Assche "Verify Byte check Unmapped Lba Supported");
1627*44704f69SBart Van Assche u = sg_get_unaligned_be32(buff + 12);
1628*44704f69SBart Van Assche sgj_haj_vi_nex(jsp, jop, 2, "DEPOPULATION TIME", SGJ_SEP_COLON_1_SPACE,
1629*44704f69SBart Van Assche u, true, "unit: second");
1630*44704f69SBart Van Assche }
1631*44704f69SBart Van Assche
1632*44704f69SBart Van Assche static const char * prov_type_arr[8] = {
1633*44704f69SBart Van Assche "not known or fully provisioned",
1634*44704f69SBart Van Assche "resource provisioned",
1635*44704f69SBart Van Assche "thin provisioned",
1636*44704f69SBart Van Assche rsv_s,
1637*44704f69SBart Van Assche rsv_s,
1638*44704f69SBart Van Assche rsv_s,
1639*44704f69SBart Van Assche rsv_s,
1640*44704f69SBart Van Assche rsv_s,
1641*44704f69SBart Van Assche };
1642*44704f69SBart Van Assche
1643*44704f69SBart Van Assche /* VPD_LB_PROVISIONING 0xb2 ["lbpv"] */
1644*44704f69SBart Van Assche int
decode_block_lb_prov_vpd(const uint8_t * buff,int len,struct opts_t * op,sgj_opaque_p jop)1645*44704f69SBart Van Assche decode_block_lb_prov_vpd(const uint8_t * buff, int len, struct opts_t * op,
1646*44704f69SBart Van Assche sgj_opaque_p jop)
1647*44704f69SBart Van Assche {
1648*44704f69SBart Van Assche unsigned int u, dp, pt, t_exp;
1649*44704f69SBart Van Assche sgj_state * jsp = &op->json_st;
1650*44704f69SBart Van Assche const char * cp;
1651*44704f69SBart Van Assche char b[1024];
1652*44704f69SBart Van Assche static const int blen = sizeof(b);
1653*44704f69SBart Van Assche static const char * mp = "Minimum percentage";
1654*44704f69SBart Van Assche static const char * tp = "Threshold percentage";
1655*44704f69SBart Van Assche static const char * pgd = "Provisioning group descriptor";
1656*44704f69SBart Van Assche
1657*44704f69SBart Van Assche if (len < 4) {
1658*44704f69SBart Van Assche pr2serr("page too short=%d\n", len);
1659*44704f69SBart Van Assche return SG_LIB_CAT_MALFORMED;
1660*44704f69SBart Van Assche }
1661*44704f69SBart Van Assche t_exp = buff[4];
1662*44704f69SBart Van Assche sgj_js_nv_ihexstr(jsp, jop, "threshold_exponent", t_exp, NULL,
1663*44704f69SBart Van Assche (0 == t_exp) ? ns_s : NULL);
1664*44704f69SBart Van Assche sgj_haj_vi_nex(jsp, jop, 2, "LBPU", SGJ_SEP_EQUAL_NO_SPACE,
1665*44704f69SBart Van Assche !!(buff[5] & 0x80), false,
1666*44704f69SBart Van Assche "Logical Block Provisioning Unmap command supported");
1667*44704f69SBart Van Assche sgj_haj_vi_nex(jsp, jop, 2, "LBPWS", SGJ_SEP_EQUAL_NO_SPACE,
1668*44704f69SBart Van Assche !!(buff[5] & 0x40), false, "Logical Block Provisioning "
1669*44704f69SBart Van Assche "Write Same (16) command supported");
1670*44704f69SBart Van Assche sgj_haj_vi_nex(jsp, jop, 2, "LBPWS10", SGJ_SEP_EQUAL_NO_SPACE,
1671*44704f69SBart Van Assche !!(buff[5] & 0x20), false, "Logical Block Provisioning "
1672*44704f69SBart Van Assche "Write Same (10) command supported");
1673*44704f69SBart Van Assche sgj_haj_vi_nex(jsp, jop, 2, "LBPRZ", SGJ_SEP_EQUAL_NO_SPACE,
1674*44704f69SBart Van Assche (0x7 & (buff[5] >> 2)), true,
1675*44704f69SBart Van Assche "Logical Block Provisioning Read Zero");
1676*44704f69SBart Van Assche sgj_haj_vi_nex(jsp, jop, 2, "ANC_SUP", SGJ_SEP_EQUAL_NO_SPACE,
1677*44704f69SBart Van Assche !!(buff[5] & 0x2), false,
1678*44704f69SBart Van Assche "ANChor SUPported");
1679*44704f69SBart Van Assche dp = !!(buff[5] & 0x1);
1680*44704f69SBart Van Assche sgj_haj_vi_nex(jsp, jop, 2, "DP", SGJ_SEP_EQUAL_NO_SPACE,
1681*44704f69SBart Van Assche dp, false, "Descriptor Present");
1682*44704f69SBart Van Assche u = 0x1f & (buff[6] >> 3); /* minimum percentage */
1683*44704f69SBart Van Assche if (0 == u)
1684*44704f69SBart Van Assche sgj_pr_hr(jsp, " %s: 0 [%s]\n", mp, nr_s);
1685*44704f69SBart Van Assche else
1686*44704f69SBart Van Assche sgj_pr_hr(jsp, " %s: %u\n", mp, u);
1687*44704f69SBart Van Assche sgj_convert_to_snake_name(mp, b, blen);
1688*44704f69SBart Van Assche sgj_js_nv_ihexstr(jsp, jop, b, u, NULL, (0 == u) ? nr_s : NULL);
1689*44704f69SBart Van Assche pt = buff[6] & 0x7;
1690*44704f69SBart Van Assche cp = prov_type_arr[pt];
1691*44704f69SBart Van Assche if (pt > 2)
1692*44704f69SBart Van Assche snprintf(b, blen, " [%u]", u);
1693*44704f69SBart Van Assche else
1694*44704f69SBart Van Assche b[0] = '\0';
1695*44704f69SBart Van Assche sgj_pr_hr(jsp, " Provisioning type: %s%s\n", cp, b);
1696*44704f69SBart Van Assche sgj_js_nv_ihexstr(jsp, jop, "provisioning_type", pt, NULL, cp);
1697*44704f69SBart Van Assche u = buff[7]; /* threshold percentage */
1698*44704f69SBart Van Assche strcpy(b, tp);
1699*44704f69SBart Van Assche if (0 == u)
1700*44704f69SBart Van Assche sgj_pr_hr(jsp, " %s: 0 [percentages %s]\n", b, ns_s);
1701*44704f69SBart Van Assche else
1702*44704f69SBart Van Assche sgj_pr_hr(jsp, " %s: %u", b, u);
1703*44704f69SBart Van Assche sgj_convert_to_snake_name(tp, b, blen);
1704*44704f69SBart Van Assche sgj_js_nv_ihexstr(jsp, jop, b, u, NULL, (0 == u) ? ns_s : NULL);
1705*44704f69SBart Van Assche if (dp && (len > 11)) {
1706*44704f69SBart Van Assche int i_len;
1707*44704f69SBart Van Assche const uint8_t * bp;
1708*44704f69SBart Van Assche sgj_opaque_p jo2p;
1709*44704f69SBart Van Assche
1710*44704f69SBart Van Assche bp = buff + 8;
1711*44704f69SBart Van Assche i_len = bp[3];
1712*44704f69SBart Van Assche if (0 == i_len) {
1713*44704f69SBart Van Assche pr2serr("%s too short=%d\n", pgd, i_len);
1714*44704f69SBart Van Assche return 0;
1715*44704f69SBart Van Assche }
1716*44704f69SBart Van Assche if (jsp->pr_as_json) {
1717*44704f69SBart Van Assche jo2p = sgj_snake_named_subobject_r(jsp, jop, pgd);
1718*44704f69SBart Van Assche sgj_js_designation_descriptor(jsp, jo2p, bp, i_len + 4);
1719*44704f69SBart Van Assche }
1720*44704f69SBart Van Assche sgj_pr_hr(jsp, " %s:\n", pgd);
1721*44704f69SBart Van Assche sg_get_designation_descriptor_str(" ", bp, i_len + 4, true,
1722*44704f69SBart Van Assche op->do_long, blen, b);
1723*44704f69SBart Van Assche if (jsp->pr_as_json && jsp->pr_out_hr)
1724*44704f69SBart Van Assche sgj_js_str_out(jsp, b, strlen(b));
1725*44704f69SBart Van Assche else
1726*44704f69SBart Van Assche sgj_pr_hr(jsp, "%s", b);
1727*44704f69SBart Van Assche }
1728*44704f69SBart Van Assche return 0;
1729*44704f69SBart Van Assche }
1730*44704f69SBart Van Assche
1731*44704f69SBart Van Assche /* VPD_REFERRALS 0xb3 ["ref"] */
1732*44704f69SBart Van Assche void
decode_referrals_vpd(const uint8_t * buff,int len,struct opts_t * op,sgj_opaque_p jop)1733*44704f69SBart Van Assche decode_referrals_vpd(const uint8_t * buff, int len, struct opts_t * op,
1734*44704f69SBart Van Assche sgj_opaque_p jop)
1735*44704f69SBart Van Assche {
1736*44704f69SBart Van Assche uint32_t u;
1737*44704f69SBart Van Assche sgj_state * jsp = &op->json_st;
1738*44704f69SBart Van Assche char b[64];
1739*44704f69SBart Van Assche
1740*44704f69SBart Van Assche if (len < 16) {
1741*44704f69SBart Van Assche pr2serr("Referrals VPD page length too short=%d\n", len);
1742*44704f69SBart Van Assche return;
1743*44704f69SBart Van Assche }
1744*44704f69SBart Van Assche u = sg_get_unaligned_be32(buff + 8);
1745*44704f69SBart Van Assche strcpy(b, " User data segment size: ");
1746*44704f69SBart Van Assche if (0 == u)
1747*44704f69SBart Van Assche sgj_pr_hr(jsp, "%s0 [per sense descriptor]\n", b);
1748*44704f69SBart Van Assche else
1749*44704f69SBart Van Assche sgj_pr_hr(jsp, "%s%u\n", b, u);
1750*44704f69SBart Van Assche sgj_js_nv_ihex(jsp, jop, "user_data_segment_size", u);
1751*44704f69SBart Van Assche u = sg_get_unaligned_be32(buff + 12);
1752*44704f69SBart Van Assche sgj_haj_vi(jsp, jop, 2, "User data segment multiplier",
1753*44704f69SBart Van Assche SGJ_SEP_COLON_1_SPACE, u, true);
1754*44704f69SBart Van Assche }
1755*44704f69SBart Van Assche
1756*44704f69SBart Van Assche /* VPD_SUP_BLOCK_LENS 0xb4 ["sbl"] (added sbc4r01) */
1757*44704f69SBart Van Assche void
decode_sup_block_lens_vpd(const uint8_t * buff,int len,struct opts_t * op,sgj_opaque_p jap)1758*44704f69SBart Van Assche decode_sup_block_lens_vpd(const uint8_t * buff, int len, struct opts_t * op,
1759*44704f69SBart Van Assche sgj_opaque_p jap)
1760*44704f69SBart Van Assche {
1761*44704f69SBart Van Assche int k;
1762*44704f69SBart Van Assche unsigned int u;
1763*44704f69SBart Van Assche const uint8_t * bp;
1764*44704f69SBart Van Assche sgj_state * jsp = &op->json_st;
1765*44704f69SBart Van Assche sgj_opaque_p jo2p = NULL;
1766*44704f69SBart Van Assche
1767*44704f69SBart Van Assche if (len < 4) {
1768*44704f69SBart Van Assche pr2serr("page length too short=%d\n", len);
1769*44704f69SBart Van Assche return;
1770*44704f69SBart Van Assche }
1771*44704f69SBart Van Assche len -= 4;
1772*44704f69SBart Van Assche bp = buff + 4;
1773*44704f69SBart Van Assche for (k = 0; k < len; k += 8, bp += 8) {
1774*44704f69SBart Van Assche if (jsp->pr_as_json)
1775*44704f69SBart Van Assche jo2p = sgj_new_unattached_object_r(jsp);
1776*44704f69SBart Van Assche u = sg_get_unaligned_be32(bp);
1777*44704f69SBart Van Assche sgj_haj_vi(jsp, jo2p, 2, "Logical block length",
1778*44704f69SBart Van Assche SGJ_SEP_COLON_1_SPACE, u, true);
1779*44704f69SBart Van Assche sgj_haj_vi_nex(jsp, jo2p, 4, "P_I_I_SUP",
1780*44704f69SBart Van Assche SGJ_SEP_COLON_1_SPACE, !!(bp[4] & 0x40), false,
1781*44704f69SBart Van Assche "Protection Information Interval SUPported");
1782*44704f69SBart Van Assche sgj_haj_vi_nex(jsp, jo2p, 4, "NO_PI_CHK",
1783*44704f69SBart Van Assche SGJ_SEP_COLON_1_SPACE, !!(bp[4] & 0x8), false,
1784*44704f69SBart Van Assche "NO Protection Information CHecKing");
1785*44704f69SBart Van Assche sgj_haj_vi_nex(jsp, jo2p, 4, "GRD_CHK", SGJ_SEP_COLON_1_SPACE,
1786*44704f69SBart Van Assche !!(bp[4] & 0x4), false, "GuaRD CHecK");
1787*44704f69SBart Van Assche sgj_haj_vi_nex(jsp, jo2p, 4, "APP_CHK", SGJ_SEP_COLON_1_SPACE,
1788*44704f69SBart Van Assche !!(bp[4] & 0x2), false, "APPlication tag CHecK");
1789*44704f69SBart Van Assche sgj_haj_vi_nex(jsp, jo2p, 4, "REF_CHK", SGJ_SEP_COLON_1_SPACE,
1790*44704f69SBart Van Assche !!(bp[4] & 0x1), false, "REFerence tag CHecK");
1791*44704f69SBart Van Assche sgj_haj_vi_nex(jsp, jo2p, 4, "T3PS", SGJ_SEP_COLON_1_SPACE,
1792*44704f69SBart Van Assche !!(bp[5] & 0x8), false, "Type 3 Protection Supported");
1793*44704f69SBart Van Assche sgj_haj_vi_nex(jsp, jo2p, 4, "T2PS", SGJ_SEP_COLON_1_SPACE,
1794*44704f69SBart Van Assche !!(bp[5] & 0x4), false, "Type 2 Protection Supported");
1795*44704f69SBart Van Assche sgj_haj_vi_nex(jsp, jo2p, 4, "T1PS", SGJ_SEP_COLON_1_SPACE,
1796*44704f69SBart Van Assche !!(bp[5] & 0x2), false, "Type 1 Protection Supported");
1797*44704f69SBart Van Assche sgj_haj_vi_nex(jsp, jo2p, 4, "T0PS", SGJ_SEP_COLON_1_SPACE,
1798*44704f69SBart Van Assche !!(bp[5] & 0x1), false, "Type 0 Protection Supported");
1799*44704f69SBart Van Assche sgj_js_nv_o(jsp, jap, NULL /* name */, jo2p);
1800*44704f69SBart Van Assche }
1801*44704f69SBart Van Assche }
1802*44704f69SBart Van Assche
1803*44704f69SBart Van Assche /* VPD_BLOCK_DEV_C_EXTENS 0xb5 ["bdce"] (added sbc4r02) */
1804*44704f69SBart Van Assche void
decode_block_dev_char_ext_vpd(const uint8_t * buff,int len,struct opts_t * op,sgj_opaque_p jop)1805*44704f69SBart Van Assche decode_block_dev_char_ext_vpd(const uint8_t * buff, int len,
1806*44704f69SBart Van Assche struct opts_t * op, sgj_opaque_p jop)
1807*44704f69SBart Van Assche {
1808*44704f69SBart Van Assche bool b_active = false;
1809*44704f69SBart Van Assche bool combined = false;
1810*44704f69SBart Van Assche int n;
1811*44704f69SBart Van Assche uint32_t u;
1812*44704f69SBart Van Assche sgj_state * jsp = &op->json_st;
1813*44704f69SBart Van Assche const char * utp = null_s;
1814*44704f69SBart Van Assche const char * uup = null_s;
1815*44704f69SBart Van Assche const char * uip = null_s;
1816*44704f69SBart Van Assche char b[128];
1817*44704f69SBart Van Assche static const int blen = sizeof(b);
1818*44704f69SBart Van Assche
1819*44704f69SBart Van Assche if (len < 16) {
1820*44704f69SBart Van Assche pr2serr("page length too short=%d\n", len);
1821*44704f69SBart Van Assche return;
1822*44704f69SBart Van Assche }
1823*44704f69SBart Van Assche switch (buff[5]) {
1824*44704f69SBart Van Assche case 1:
1825*44704f69SBart Van Assche utp = "Combined writes and reads";
1826*44704f69SBart Van Assche combined = true;
1827*44704f69SBart Van Assche break;
1828*44704f69SBart Van Assche case 2:
1829*44704f69SBart Van Assche utp = "Writes only";
1830*44704f69SBart Van Assche break;
1831*44704f69SBart Van Assche case 3:
1832*44704f69SBart Van Assche utp = "Separate writes and reads";
1833*44704f69SBart Van Assche b_active = true;
1834*44704f69SBart Van Assche break;
1835*44704f69SBart Van Assche default:
1836*44704f69SBart Van Assche utp = rsv_s;
1837*44704f69SBart Van Assche break;
1838*44704f69SBart Van Assche }
1839*44704f69SBart Van Assche sgj_haj_vistr(jsp, jop, 2, "Utilization type", SGJ_SEP_COLON_1_SPACE,
1840*44704f69SBart Van Assche buff[5], true, utp);
1841*44704f69SBart Van Assche switch (buff[6]) {
1842*44704f69SBart Van Assche case 2:
1843*44704f69SBart Van Assche uup = "megabytes";
1844*44704f69SBart Van Assche break;
1845*44704f69SBart Van Assche case 3:
1846*44704f69SBart Van Assche uup = "gigabytes";
1847*44704f69SBart Van Assche break;
1848*44704f69SBart Van Assche case 4:
1849*44704f69SBart Van Assche uup = "terabytes";
1850*44704f69SBart Van Assche break;
1851*44704f69SBart Van Assche case 5:
1852*44704f69SBart Van Assche uup = "petabytes";
1853*44704f69SBart Van Assche break;
1854*44704f69SBart Van Assche case 6:
1855*44704f69SBart Van Assche uup = "exabytes";
1856*44704f69SBart Van Assche break;
1857*44704f69SBart Van Assche default:
1858*44704f69SBart Van Assche uup = rsv_s;
1859*44704f69SBart Van Assche break;
1860*44704f69SBart Van Assche }
1861*44704f69SBart Van Assche sgj_haj_vistr(jsp, jop, 2, "Utilization units", SGJ_SEP_COLON_1_SPACE,
1862*44704f69SBart Van Assche buff[6], true, uup);
1863*44704f69SBart Van Assche switch (buff[7]) {
1864*44704f69SBart Van Assche case 0xa:
1865*44704f69SBart Van Assche uip = "per day";
1866*44704f69SBart Van Assche break;
1867*44704f69SBart Van Assche case 0xe:
1868*44704f69SBart Van Assche uip = "per year";
1869*44704f69SBart Van Assche break;
1870*44704f69SBart Van Assche default:
1871*44704f69SBart Van Assche uip = rsv_s;
1872*44704f69SBart Van Assche break;
1873*44704f69SBart Van Assche }
1874*44704f69SBart Van Assche sgj_haj_vistr(jsp, jop, 2, "Utilization interval", SGJ_SEP_COLON_1_SPACE,
1875*44704f69SBart Van Assche buff[7], true, uip);
1876*44704f69SBart Van Assche u = sg_get_unaligned_be32(buff + 8);
1877*44704f69SBart Van Assche sgj_haj_vistr(jsp, jop, 2, "Utilization B", SGJ_SEP_COLON_1_SPACE,
1878*44704f69SBart Van Assche u, true, (b_active ? NULL : rsv_s));
1879*44704f69SBart Van Assche n = sg_scnpr(b, blen, "%s: ", "Designed utilization");
1880*44704f69SBart Van Assche if (b_active)
1881*44704f69SBart Van Assche n += sg_scnpr(b + n, blen - n, "%u %s for reads and ", u, uup);
1882*44704f69SBart Van Assche u = sg_get_unaligned_be32(buff + 12);
1883*44704f69SBart Van Assche sgj_haj_vi(jsp, jop, 2, "Utilization A", SGJ_SEP_COLON_1_SPACE, u, true);
1884*44704f69SBart Van Assche n += sg_scnpr(b + n, blen - n, "%u %s for %swrites, %s", u, uup,
1885*44704f69SBart Van Assche combined ? "reads and " : null_s, uip);
1886*44704f69SBart Van Assche sgj_pr_hr(jsp, " %s\n", b);
1887*44704f69SBart Van Assche if (jsp->pr_string)
1888*44704f69SBart Van Assche sgj_js_nv_s(jsp, jop, "summary", b);
1889*44704f69SBart Van Assche }
1890*44704f69SBart Van Assche
1891*44704f69SBart Van Assche /* VPD_ZBC_DEV_CHARS 0xb6 ["zdbch"] sbc or zbc [zbc2r04] */
1892*44704f69SBart Van Assche void
decode_zbdch_vpd(const uint8_t * buff,int len,struct opts_t * op,sgj_opaque_p jop)1893*44704f69SBart Van Assche decode_zbdch_vpd(const uint8_t * buff, int len, struct opts_t * op,
1894*44704f69SBart Van Assche sgj_opaque_p jop)
1895*44704f69SBart Van Assche {
1896*44704f69SBart Van Assche uint32_t u, pdt;
1897*44704f69SBart Van Assche sgj_state * jsp = &op->json_st;
1898*44704f69SBart Van Assche char b[128];
1899*44704f69SBart Van Assche static const int blen = sizeof(b);
1900*44704f69SBart Van Assche
1901*44704f69SBart Van Assche if (op->do_hex) {
1902*44704f69SBart Van Assche hex2stdout(buff, len, (1 == op->do_hex) ? 0 : -1);
1903*44704f69SBart Van Assche return;
1904*44704f69SBart Van Assche }
1905*44704f69SBart Van Assche if (len < 64) {
1906*44704f69SBart Van Assche pr2serr("Zoned block device characteristics VPD page length too "
1907*44704f69SBart Van Assche "short=%d\n", len);
1908*44704f69SBart Van Assche return;
1909*44704f69SBart Van Assche }
1910*44704f69SBart Van Assche pdt = PDT_MASK & buff[0];
1911*44704f69SBart Van Assche sgj_pr_hr(jsp, " Peripheral device type: %s\n",
1912*44704f69SBart Van Assche sg_get_pdt_str(pdt, blen, b));
1913*44704f69SBart Van Assche
1914*44704f69SBart Van Assche sgj_pr_hr(jsp, " Zoned block device extension: ");
1915*44704f69SBart Van Assche u = (buff[4] >> 4) & 0xf;
1916*44704f69SBart Van Assche switch (u) {
1917*44704f69SBart Van Assche case 0:
1918*44704f69SBart Van Assche if (PDT_ZBC == (PDT_MASK & buff[0]))
1919*44704f69SBart Van Assche strcpy(b, "host managed zoned block device");
1920*44704f69SBart Van Assche else
1921*44704f69SBart Van Assche strcpy(b, nr_s);
1922*44704f69SBart Van Assche break;
1923*44704f69SBart Van Assche case 1:
1924*44704f69SBart Van Assche strcpy(b, "host aware zoned block device model");
1925*44704f69SBart Van Assche break;
1926*44704f69SBart Van Assche case 2:
1927*44704f69SBart Van Assche strcpy(b, "Domains and realms zoned block device model");
1928*44704f69SBart Van Assche break;
1929*44704f69SBart Van Assche default:
1930*44704f69SBart Van Assche strcpy(b, rsv_s);
1931*44704f69SBart Van Assche break;
1932*44704f69SBart Van Assche }
1933*44704f69SBart Van Assche sgj_haj_vistr(jsp, jop, 2, "Zoned block device extension",
1934*44704f69SBart Van Assche SGJ_SEP_COLON_1_SPACE, u, true, b);
1935*44704f69SBart Van Assche sgj_haj_vi_nex(jsp, jop, 2, "AAORB", SGJ_SEP_COLON_1_SPACE,
1936*44704f69SBart Van Assche !!(buff[4] & 0x2), false,
1937*44704f69SBart Van Assche "Activation Aligned On Realm Boundaries");
1938*44704f69SBart Van Assche sgj_haj_vi_nex(jsp, jop, 2, "URSWRZ", SGJ_SEP_COLON_1_SPACE,
1939*44704f69SBart Van Assche !!(buff[4] & 0x1), false,
1940*44704f69SBart Van Assche "Unrestricted Read in Sequential Write Required Zone");
1941*44704f69SBart Van Assche u = sg_get_unaligned_be32(buff + 8);
1942*44704f69SBart Van Assche sgj_haj_vistr(jsp, jop, 2, "Optimal number of open sequential write "
1943*44704f69SBart Van Assche "preferred zones", SGJ_SEP_COLON_1_SPACE, u, true,
1944*44704f69SBart Van Assche (SG_LIB_UNBOUNDED_32BIT == u) ? nr_s : NULL);
1945*44704f69SBart Van Assche u = sg_get_unaligned_be32(buff + 12);
1946*44704f69SBart Van Assche sgj_haj_vistr(jsp, jop, 2, "Optimal number of non-sequentially "
1947*44704f69SBart Van Assche "written sequential write preferred zones",
1948*44704f69SBart Van Assche SGJ_SEP_COLON_1_SPACE, u, true,
1949*44704f69SBart Van Assche (SG_LIB_UNBOUNDED_32BIT == u) ? nr_s : NULL);
1950*44704f69SBart Van Assche u = sg_get_unaligned_be32(buff + 16);
1951*44704f69SBart Van Assche sgj_haj_vistr(jsp, jop, 2, "Maximum number of open sequential write "
1952*44704f69SBart Van Assche "required zones", SGJ_SEP_COLON_1_SPACE, u, true,
1953*44704f69SBart Van Assche (SG_LIB_UNBOUNDED_32BIT == u) ? nl_s : NULL);
1954*44704f69SBart Van Assche u = buff[23] & 0xf;
1955*44704f69SBart Van Assche switch (u) {
1956*44704f69SBart Van Assche case 0:
1957*44704f69SBart Van Assche strcpy(b, nr_s);
1958*44704f69SBart Van Assche break;
1959*44704f69SBart Van Assche case 1:
1960*44704f69SBart Van Assche strcpy(b, "Zoned starting LBAs aligned using constant zone lengths");
1961*44704f69SBart Van Assche break;
1962*44704f69SBart Van Assche case 0x8:
1963*44704f69SBart Van Assche strcpy(b, "Zoned starting LBAs potentially non-constant (as "
1964*44704f69SBart Van Assche "reported by REPORT ZONES)");
1965*44704f69SBart Van Assche break;
1966*44704f69SBart Van Assche default:
1967*44704f69SBart Van Assche strcpy(b, rsv_s);
1968*44704f69SBart Van Assche break;
1969*44704f69SBart Van Assche }
1970*44704f69SBart Van Assche sgj_haj_vistr(jsp, jop, 2, "Zoned alignment method",
1971*44704f69SBart Van Assche SGJ_SEP_COLON_1_SPACE, u, true, b);
1972*44704f69SBart Van Assche sgj_haj_vi(jsp, jop, 2, "Zone starting LBA granularity",
1973*44704f69SBart Van Assche SGJ_SEP_COLON_1_SPACE, sg_get_unaligned_be64(buff + 24), true);
1974*44704f69SBart Van Assche }
1975*44704f69SBart Van Assche
1976*44704f69SBart Van Assche /* VPD_BLOCK_LIMITS_EXT 0xb7 ["ble"] SBC */
1977*44704f69SBart Van Assche void
decode_block_limits_ext_vpd(const uint8_t * buff,int len,struct opts_t * op,sgj_opaque_p jop)1978*44704f69SBart Van Assche decode_block_limits_ext_vpd(const uint8_t * buff, int len, struct opts_t * op,
1979*44704f69SBart Van Assche sgj_opaque_p jop)
1980*44704f69SBart Van Assche {
1981*44704f69SBart Van Assche uint32_t u;
1982*44704f69SBart Van Assche sgj_state * jsp = &op->json_st;
1983*44704f69SBart Van Assche
1984*44704f69SBart Van Assche if (op->do_hex) {
1985*44704f69SBart Van Assche hex2stdout(buff, len, (1 == op->do_hex) ? 0 : -1);
1986*44704f69SBart Van Assche return;
1987*44704f69SBart Van Assche }
1988*44704f69SBart Van Assche if (len < 12) {
1989*44704f69SBart Van Assche pr2serr("page length too short=%d\n", len);
1990*44704f69SBart Van Assche return;
1991*44704f69SBart Van Assche }
1992*44704f69SBart Van Assche u = sg_get_unaligned_be16(buff + 6);
1993*44704f69SBart Van Assche sgj_haj_vistr(jsp, jop, 2, "Maximum number of streams",
1994*44704f69SBart Van Assche SGJ_SEP_COLON_1_SPACE, u, true,
1995*44704f69SBart Van Assche (0 == u) ? "Stream control not supported" : NULL);
1996*44704f69SBart Van Assche u = sg_get_unaligned_be16(buff + 8);
1997*44704f69SBart Van Assche sgj_haj_vi_nex(jsp, jop, 2, "Optimal stream write size",
1998*44704f69SBart Van Assche SGJ_SEP_COLON_1_SPACE, u, true, "unit: LB");
1999*44704f69SBart Van Assche u = sg_get_unaligned_be32(buff + 10);
2000*44704f69SBart Van Assche sgj_haj_vi_nex(jsp, jop, 2, "Stream granularity size",
2001*44704f69SBart Van Assche SGJ_SEP_COLON_1_SPACE, u, true,
2002*44704f69SBart Van Assche "unit: number of optimal stream write size blocks");
2003*44704f69SBart Van Assche if (len < 28)
2004*44704f69SBart Van Assche return;
2005*44704f69SBart Van Assche u = sg_get_unaligned_be32(buff + 16);
2006*44704f69SBart Van Assche sgj_haj_vistr_nex(jsp, jop, 2, "Maximum scattered LBA range transfer "
2007*44704f69SBart Van Assche "length", SGJ_SEP_COLON_1_SPACE, u, true,
2008*44704f69SBart Van Assche (0 == u ? nlr_s : NULL),
2009*44704f69SBart Van Assche "unit: LB (in a single LBA range descriptor)");
2010*44704f69SBart Van Assche u = sg_get_unaligned_be16(buff + 22);
2011*44704f69SBart Van Assche sgj_haj_vistr(jsp, jop, 2, "Maximum scattered LBA range descriptor "
2012*44704f69SBart Van Assche "count", SGJ_SEP_COLON_1_SPACE, u, true,
2013*44704f69SBart Van Assche (0 == u ? nlr_s : NULL));
2014*44704f69SBart Van Assche u = sg_get_unaligned_be32(buff + 24);
2015*44704f69SBart Van Assche sgj_haj_vistr_nex(jsp, jop, 2, "Maximum scattered transfer length",
2016*44704f69SBart Van Assche SGJ_SEP_COLON_1_SPACE, u, true,
2017*44704f69SBart Van Assche (0 == u ? nlr_s : NULL),
2018*44704f69SBart Van Assche "unit: LB (per single Write Scattered command)");
2019*44704f69SBart Van Assche }
2020*44704f69SBart Van Assche
2021*44704f69SBart Van Assche static const char * sch_type_arr[8] = {
2022*44704f69SBart Van Assche rsv_s,
2023*44704f69SBart Van Assche "non-zoned",
2024*44704f69SBart Van Assche "host aware zoned",
2025*44704f69SBart Van Assche "host managed zoned",
2026*44704f69SBart Van Assche "zone domain and realms zoned",
2027*44704f69SBart Van Assche rsv_s,
2028*44704f69SBart Van Assche rsv_s,
2029*44704f69SBart Van Assche rsv_s,
2030*44704f69SBart Van Assche };
2031*44704f69SBart Van Assche
2032*44704f69SBart Van Assche static char *
get_zone_align_method(uint8_t val,char * b,int blen)2033*44704f69SBart Van Assche get_zone_align_method(uint8_t val, char * b, int blen)
2034*44704f69SBart Van Assche {
2035*44704f69SBart Van Assche assert(blen > 32);
2036*44704f69SBart Van Assche switch (val) {
2037*44704f69SBart Van Assche case 0:
2038*44704f69SBart Van Assche strcpy(b, nr_s);
2039*44704f69SBart Van Assche break;
2040*44704f69SBart Van Assche case 1:
2041*44704f69SBart Van Assche strcpy(b, "using constant zone lengths");
2042*44704f69SBart Van Assche break;
2043*44704f69SBart Van Assche case 8:
2044*44704f69SBart Van Assche strcpy(b, "taking gap zones into account");
2045*44704f69SBart Van Assche break;
2046*44704f69SBart Van Assche default:
2047*44704f69SBart Van Assche strcpy(b, rsv_s);
2048*44704f69SBart Van Assche break;
2049*44704f69SBart Van Assche }
2050*44704f69SBart Van Assche return b;
2051*44704f69SBart Van Assche }
2052*44704f69SBart Van Assche
2053*44704f69SBart Van Assche /* VPD_FORMAT_PRESETS 0xb8 ["fp"] (added sbc4r18) */
2054*44704f69SBart Van Assche void
decode_format_presets_vpd(const uint8_t * buff,int len,struct opts_t * op,sgj_opaque_p jap)2055*44704f69SBart Van Assche decode_format_presets_vpd(const uint8_t * buff, int len, struct opts_t * op,
2056*44704f69SBart Van Assche sgj_opaque_p jap)
2057*44704f69SBart Van Assche {
2058*44704f69SBart Van Assche uint8_t sch_type;
2059*44704f69SBart Van Assche int k;
2060*44704f69SBart Van Assche uint32_t u;
2061*44704f69SBart Van Assche uint64_t ul;
2062*44704f69SBart Van Assche sgj_state * jsp = &op->json_st;
2063*44704f69SBart Van Assche const uint8_t * bp;
2064*44704f69SBart Van Assche sgj_opaque_p jo2p, jo3p;
2065*44704f69SBart Van Assche const char * cp;
2066*44704f69SBart Van Assche char b[128];
2067*44704f69SBart Van Assche char d[64];
2068*44704f69SBart Van Assche static const int blen = sizeof(b);
2069*44704f69SBart Van Assche static const int dlen = sizeof(d);
2070*44704f69SBart Van Assche static const char * llczp = "Low LBA conventional zones percentage";
2071*44704f69SBart Van Assche static const char * hlczp = "High LBA conventional zones percentage";
2072*44704f69SBart Van Assche static const char * ztzd = "Zone type for zone domain";
2073*44704f69SBart Van Assche
2074*44704f69SBart Van Assche if (op->do_hex) {
2075*44704f69SBart Van Assche hex2stdout(buff, len, (1 == op->do_hex) ? 0 : -1);
2076*44704f69SBart Van Assche return;
2077*44704f69SBart Van Assche }
2078*44704f69SBart Van Assche if (len < 4) {
2079*44704f69SBart Van Assche pr2serr("VPD page length too short=%d\n", len);
2080*44704f69SBart Van Assche return;
2081*44704f69SBart Van Assche }
2082*44704f69SBart Van Assche len -= 4;
2083*44704f69SBart Van Assche bp = buff + 4;
2084*44704f69SBart Van Assche for (k = 0; k < len; k += 64, bp += 64) {
2085*44704f69SBart Van Assche jo2p = sgj_new_unattached_object_r(jsp);
2086*44704f69SBart Van Assche sgj_haj_vi(jsp, jo2p, 2, "Preset identifier", SGJ_SEP_COLON_1_SPACE,
2087*44704f69SBart Van Assche sg_get_unaligned_be64(bp + 0), true);
2088*44704f69SBart Van Assche sch_type = bp[4];
2089*44704f69SBart Van Assche if (sch_type < 8) {
2090*44704f69SBart Van Assche cp = sch_type_arr[sch_type];
2091*44704f69SBart Van Assche if (rsv_s != cp)
2092*44704f69SBart Van Assche snprintf(b, blen, "%s block device", cp);
2093*44704f69SBart Van Assche else
2094*44704f69SBart Van Assche snprintf(b, blen, "%s", cp);
2095*44704f69SBart Van Assche } else
2096*44704f69SBart Van Assche strcpy(b, rsv_s);
2097*44704f69SBart Van Assche sgj_haj_vistr(jsp, jo2p, 4, "Schema type", SGJ_SEP_COLON_1_SPACE,
2098*44704f69SBart Van Assche sch_type, true, b);
2099*44704f69SBart Van Assche sgj_haj_vi(jsp, jo2p, 4, "Logical blocks per physical block "
2100*44704f69SBart Van Assche "exponent", SGJ_SEP_COLON_1_SPACE,
2101*44704f69SBart Van Assche 0xf & bp[7], true);
2102*44704f69SBart Van Assche sgj_haj_vi_nex(jsp, jo2p, 4, "Logical block length",
2103*44704f69SBart Van Assche SGJ_SEP_COLON_1_SPACE, sg_get_unaligned_be32(bp + 8),
2104*44704f69SBart Van Assche true, "unit: byte");
2105*44704f69SBart Van Assche sgj_haj_vi(jsp, jo2p, 4, "Designed last Logical Block Address",
2106*44704f69SBart Van Assche SGJ_SEP_COLON_1_SPACE,
2107*44704f69SBart Van Assche sg_get_unaligned_be64(bp + 16), true);
2108*44704f69SBart Van Assche sgj_haj_vi_nex(jsp, jo2p, 4, "FMTPINFO", SGJ_SEP_COLON_1_SPACE,
2109*44704f69SBart Van Assche (bp[38] >> 6) & 0x3, false,
2110*44704f69SBart Van Assche "ForMaT Protection INFOrmation (see Format Unit)");
2111*44704f69SBart Van Assche sgj_haj_vi(jsp, jo2p, 4, "Protection field usage",
2112*44704f69SBart Van Assche SGJ_SEP_COLON_1_SPACE, bp[38] & 0x7, false);
2113*44704f69SBart Van Assche sgj_haj_vi(jsp, jo2p, 4, "Protection interval exponent",
2114*44704f69SBart Van Assche SGJ_SEP_COLON_1_SPACE, bp[39] & 0xf, true);
2115*44704f69SBart Van Assche jo3p = sgj_named_subobject_r(jsp, jo2p,
2116*44704f69SBart Van Assche "schema_type_specific_information");
2117*44704f69SBart Van Assche switch (sch_type) {
2118*44704f69SBart Van Assche case 2:
2119*44704f69SBart Van Assche sgj_pr_hr(jsp, " Defines zones for host aware device:\n");
2120*44704f69SBart Van Assche u = bp[40 + 0];
2121*44704f69SBart Van Assche sgj_pr_hr(jsp, " %s: %u.%u %%\n", llczp, u / 10, u % 10);
2122*44704f69SBart Van Assche sgj_convert_to_snake_name(llczp, b, blen);
2123*44704f69SBart Van Assche sgj_js_nv_ihex_nex(jsp, jo3p, b, u, true, "unit: 1/10 of a "
2124*44704f69SBart Van Assche "percent");
2125*44704f69SBart Van Assche u = bp[40 + 1];
2126*44704f69SBart Van Assche sgj_pr_hr(jsp, " %s: %u.%u %%\n", hlczp, u / 10, u % 10);
2127*44704f69SBart Van Assche sgj_convert_to_snake_name(hlczp, b, blen);
2128*44704f69SBart Van Assche sgj_js_nv_ihex_nex(jsp, jo3p, b, u, true, "unit: 1/10 of a "
2129*44704f69SBart Van Assche "percent");
2130*44704f69SBart Van Assche u = sg_get_unaligned_be32(bp + 40 + 12);
2131*44704f69SBart Van Assche sgj_haj_vistr(jsp, jo3p, 6, "Logical blocks per zone",
2132*44704f69SBart Van Assche SGJ_SEP_COLON_1_SPACE, u, true,
2133*44704f69SBart Van Assche (0 == u ? rsv_s : NULL));
2134*44704f69SBart Van Assche break;
2135*44704f69SBart Van Assche case 3:
2136*44704f69SBart Van Assche sgj_pr_hr(jsp, " Defines zones for host managed device:\n");
2137*44704f69SBart Van Assche u = bp[40 + 0];
2138*44704f69SBart Van Assche sgj_pr_hr(jsp, " %s: %u.%u %%\n", llczp, u / 10, u % 10);
2139*44704f69SBart Van Assche sgj_convert_to_snake_name(llczp, b, blen);
2140*44704f69SBart Van Assche sgj_js_nv_ihex_nex(jsp, jo3p, b, u, true, "unit: 1/10 of a "
2141*44704f69SBart Van Assche "percent");
2142*44704f69SBart Van Assche u = bp[40 + 1];
2143*44704f69SBart Van Assche sgj_pr_hr(jsp, " %s: %u.%u %%\n", hlczp, u / 10, u % 10);
2144*44704f69SBart Van Assche sgj_convert_to_snake_name(hlczp, b, blen);
2145*44704f69SBart Van Assche sgj_js_nv_ihex_nex(jsp, jo3p, b, u, true, "unit: 1/10 of a "
2146*44704f69SBart Van Assche "percent");
2147*44704f69SBart Van Assche u = bp[40 + 3] & 0x7;
2148*44704f69SBart Van Assche sgj_haj_vistr(jsp, jo3p, 6, "Designed zone alignment method",
2149*44704f69SBart Van Assche SGJ_SEP_COLON_1_SPACE, u, true,
2150*44704f69SBart Van Assche get_zone_align_method(u, d, dlen));
2151*44704f69SBart Van Assche ul = sg_get_unaligned_be64(bp + 40 + 4);
2152*44704f69SBart Van Assche sgj_haj_vi_nex(jsp, jo3p, 6, "Designed zone starting LBA "
2153*44704f69SBart Van Assche "granularity", SGJ_SEP_COLON_1_SPACE, ul, true,
2154*44704f69SBart Van Assche "unit: LB");
2155*44704f69SBart Van Assche u = sg_get_unaligned_be32(bp + 40 + 12);
2156*44704f69SBart Van Assche sgj_haj_vistr(jsp, jo3p, 6, "Logical blocks per zone",
2157*44704f69SBart Van Assche SGJ_SEP_COLON_1_SPACE, u, true,
2158*44704f69SBart Van Assche (0 == u ? rsv_s : NULL));
2159*44704f69SBart Van Assche break;
2160*44704f69SBart Van Assche case 4:
2161*44704f69SBart Van Assche sgj_pr_hr(jsp, " Defines zones for zone domains and realms "
2162*44704f69SBart Van Assche "device:\n");
2163*44704f69SBart Van Assche snprintf(b, blen, "%s 0", ztzd);
2164*44704f69SBart Van Assche u = bp[40 + 0];
2165*44704f69SBart Van Assche sg_get_zone_type_str((u >> 4) & 0xf, dlen, d);
2166*44704f69SBart Van Assche sgj_haj_vistr(jsp, jo3p, 6, b, SGJ_SEP_COLON_1_SPACE, u, true, d);
2167*44704f69SBart Van Assche snprintf(b, blen, "%s 1", ztzd);
2168*44704f69SBart Van Assche sg_get_zone_type_str(u & 0xf, dlen, d);
2169*44704f69SBart Van Assche sgj_haj_vistr(jsp, jo3p, 6, b, SGJ_SEP_COLON_1_SPACE, u, true, d);
2170*44704f69SBart Van Assche
2171*44704f69SBart Van Assche snprintf(b, blen, "%s 2", ztzd);
2172*44704f69SBart Van Assche u = bp[40 + 1];
2173*44704f69SBart Van Assche sg_get_zone_type_str((u >> 4) & 0xf, dlen, d);
2174*44704f69SBart Van Assche sgj_haj_vistr(jsp, jo3p, 6, b, SGJ_SEP_COLON_1_SPACE, u, true, d);
2175*44704f69SBart Van Assche snprintf(b, blen, "%s 3", ztzd);
2176*44704f69SBart Van Assche sg_get_zone_type_str(u & 0xf, dlen, d);
2177*44704f69SBart Van Assche sgj_haj_vistr(jsp, jo3p, 6, b, SGJ_SEP_COLON_1_SPACE, u, true, d);
2178*44704f69SBart Van Assche u = bp[40 + 3] & 0x7;
2179*44704f69SBart Van Assche sgj_haj_vistr(jsp, jo3p, 6, "Designed zone alignment method",
2180*44704f69SBart Van Assche SGJ_SEP_COLON_1_SPACE, u, true,
2181*44704f69SBart Van Assche get_zone_align_method(u, d, dlen));
2182*44704f69SBart Van Assche ul = sg_get_unaligned_be64(bp + 40 + 4);
2183*44704f69SBart Van Assche sgj_haj_vi_nex(jsp, jo3p, 6, "Designed zone starting LBA "
2184*44704f69SBart Van Assche "granularity", SGJ_SEP_COLON_1_SPACE, ul, true,
2185*44704f69SBart Van Assche "unit: LB");
2186*44704f69SBart Van Assche u = sg_get_unaligned_be32(bp + 40 + 12);
2187*44704f69SBart Van Assche sgj_haj_vistr(jsp, jo3p, 6, "Logical blocks per zone",
2188*44704f69SBart Van Assche SGJ_SEP_COLON_1_SPACE, u, true,
2189*44704f69SBart Van Assche (0 == u ? rsv_s : NULL));
2190*44704f69SBart Van Assche ul = sg_get_unaligned_be64(bp + 40 + 16);
2191*44704f69SBart Van Assche sgj_haj_vi_nex(jsp, jo3p, 6, "Designed zone maximum address",
2192*44704f69SBart Van Assche SGJ_SEP_COLON_1_SPACE, ul, true, "unit: LBA");
2193*44704f69SBart Van Assche break;
2194*44704f69SBart Van Assche default:
2195*44704f69SBart Van Assche sgj_pr_hr(jsp, " No schema type specific information\n");
2196*44704f69SBart Van Assche break;
2197*44704f69SBart Van Assche }
2198*44704f69SBart Van Assche sgj_js_nv_o(jsp, jap, NULL /* name */, jo2p);
2199*44704f69SBart Van Assche }
2200*44704f69SBart Van Assche }
2201*44704f69SBart Van Assche
2202*44704f69SBart Van Assche /* VPD_CON_POS_RANGE 0xb9 (added sbc5r01) */
2203*44704f69SBart Van Assche void
decode_con_pos_range_vpd(const uint8_t * buff,int len,struct opts_t * op,sgj_opaque_p jap)2204*44704f69SBart Van Assche decode_con_pos_range_vpd(const uint8_t * buff, int len, struct opts_t * op,
2205*44704f69SBart Van Assche sgj_opaque_p jap)
2206*44704f69SBart Van Assche {
2207*44704f69SBart Van Assche int k;
2208*44704f69SBart Van Assche uint32_t u;
2209*44704f69SBart Van Assche sgj_state * jsp = &op->json_st;
2210*44704f69SBart Van Assche const uint8_t * bp;
2211*44704f69SBart Van Assche sgj_opaque_p jo2p;
2212*44704f69SBart Van Assche
2213*44704f69SBart Van Assche if (op->do_hex) {
2214*44704f69SBart Van Assche hex2stdout(buff, len, (1 == op->do_hex) ? 0 : -1);
2215*44704f69SBart Van Assche return;
2216*44704f69SBart Van Assche }
2217*44704f69SBart Van Assche if (len < 64) {
2218*44704f69SBart Van Assche pr2serr("VPD page length too short=%d\n", len);
2219*44704f69SBart Van Assche return;
2220*44704f69SBart Van Assche }
2221*44704f69SBart Van Assche len -= 64;
2222*44704f69SBart Van Assche bp = buff + 64;
2223*44704f69SBart Van Assche for (k = 0; k < len; k += 32, bp += 32) {
2224*44704f69SBart Van Assche jo2p = sgj_new_unattached_object_r(jsp);
2225*44704f69SBart Van Assche sgj_haj_vi(jsp, jo2p, 2, "LBA range number",
2226*44704f69SBart Van Assche SGJ_SEP_COLON_1_SPACE, bp[0], true);
2227*44704f69SBart Van Assche u = bp[1];
2228*44704f69SBart Van Assche sgj_haj_vistr(jsp, jo2p, 4, "Number of storage elements",
2229*44704f69SBart Van Assche SGJ_SEP_COLON_1_SPACE, u, true, (0 == u ? nr_s : NULL));
2230*44704f69SBart Van Assche sgj_haj_vi(jsp, jo2p, 4, "Starting LBA", SGJ_SEP_COLON_1_SPACE,
2231*44704f69SBart Van Assche sg_get_unaligned_be64(bp + 8), true);
2232*44704f69SBart Van Assche sgj_haj_vi(jsp, jo2p, 4, "Number of LBAs", SGJ_SEP_COLON_1_SPACE,
2233*44704f69SBart Van Assche sg_get_unaligned_be64(bp + 16), true);
2234*44704f69SBart Van Assche sgj_js_nv_o(jsp, jap, NULL /* name */, jo2p);
2235*44704f69SBart Van Assche }
2236*44704f69SBart Van Assche }
2237*44704f69SBart Van Assche
2238*44704f69SBart Van Assche /* This is xcopy(LID4) related: "ROD" == Representation Of Data
2239*44704f69SBart Van Assche * Used by VPD_3PARTY_COPY 0x8f ["tpc"] */
2240*44704f69SBart Van Assche static void
decode_rod_descriptor(const uint8_t * buff,int len,struct opts_t * op,sgj_opaque_p jap)2241*44704f69SBart Van Assche decode_rod_descriptor(const uint8_t * buff, int len, struct opts_t * op,
2242*44704f69SBart Van Assche sgj_opaque_p jap)
2243*44704f69SBart Van Assche {
2244*44704f69SBart Van Assche uint8_t pdt;
2245*44704f69SBart Van Assche uint32_t u;
2246*44704f69SBart Van Assche int k, bump;
2247*44704f69SBart Van Assche uint64_t ull;
2248*44704f69SBart Van Assche const uint8_t * bp = buff;
2249*44704f69SBart Van Assche sgj_state * jsp = &op->json_st;
2250*44704f69SBart Van Assche sgj_opaque_p jo2p;
2251*44704f69SBart Van Assche char b[80];
2252*44704f69SBart Van Assche static const int blen = sizeof(b);
2253*44704f69SBart Van Assche static const char * ab_pdt = "abnormal use of 'pdt'";
2254*44704f69SBart Van Assche
2255*44704f69SBart Van Assche for (k = 0; k < len; k += bump, bp += bump) {
2256*44704f69SBart Van Assche jo2p = sgj_new_unattached_object_r(jsp);
2257*44704f69SBart Van Assche bump = sg_get_unaligned_be16(bp + 2) + 4;
2258*44704f69SBart Van Assche pdt = 0x1f & bp[0];
2259*44704f69SBart Van Assche u = (bp[0] >> 5) & 0x7;
2260*44704f69SBart Van Assche sgj_js_nv_i(jsp, jo2p, "descriptor_format", u);
2261*44704f69SBart Van Assche if (0 != u) {
2262*44704f69SBart Van Assche sgj_pr_hr(jsp, " Unhandled descriptor (format %u, device type "
2263*44704f69SBart Van Assche "%u)\n", u, pdt);
2264*44704f69SBart Van Assche sgj_js_nv_o(jsp, jap, NULL /* name */, jo2p);
2265*44704f69SBart Van Assche break;
2266*44704f69SBart Van Assche }
2267*44704f69SBart Van Assche switch (pdt) {
2268*44704f69SBart Van Assche case 0:
2269*44704f69SBart Van Assche /* Block ROD device type specific descriptor */
2270*44704f69SBart Van Assche sgj_js_nv_ihexstr_nex(jsp, jo2p, "peripheral_device_type",
2271*44704f69SBart Van Assche pdt, false, NULL, "Block ROD device "
2272*44704f69SBart Van Assche "type specific descriptor", ab_pdt);
2273*44704f69SBart Van Assche sgj_haj_vi_nex(jsp, jo2p, 4, "Optimal block ROD length "
2274*44704f69SBart Van Assche "granularity", SGJ_SEP_COLON_1_SPACE,
2275*44704f69SBart Van Assche sg_get_unaligned_be16(bp + 6), true, "unit: LB");
2276*44704f69SBart Van Assche ull = sg_get_unaligned_be64(bp + 8);
2277*44704f69SBart Van Assche sgj_haj_vi(jsp, jo2p, 4, "Maximum bytes in block ROD",
2278*44704f69SBart Van Assche SGJ_SEP_COLON_1_SPACE, ull, true);
2279*44704f69SBart Van Assche ull = sg_get_unaligned_be64(bp + 16);
2280*44704f69SBart Van Assche sgj_haj_vistr(jsp, jo2p, 4, "Optimal Bytes in block ROD "
2281*44704f69SBart Van Assche "transfer", SGJ_SEP_COLON_1_SPACE, ull, true,
2282*44704f69SBart Van Assche (SG_LIB_UNBOUNDED_64BIT == ull) ? nl_s : NULL);
2283*44704f69SBart Van Assche ull = sg_get_unaligned_be64(bp + 24);
2284*44704f69SBart Van Assche sgj_haj_vistr(jsp, jo2p, 4, "Optimal Bytes to token per "
2285*44704f69SBart Van Assche "segment", SGJ_SEP_COLON_1_SPACE, ull, true,
2286*44704f69SBart Van Assche (SG_LIB_UNBOUNDED_64BIT == ull) ? nl_s : NULL);
2287*44704f69SBart Van Assche ull = sg_get_unaligned_be64(bp + 32);
2288*44704f69SBart Van Assche sgj_haj_vistr(jsp, jo2p, 4, "Optimal Bytes from token per "
2289*44704f69SBart Van Assche "segment", SGJ_SEP_COLON_1_SPACE, ull, true,
2290*44704f69SBart Van Assche (SG_LIB_UNBOUNDED_64BIT == ull) ? nl_s : NULL);
2291*44704f69SBart Van Assche break;
2292*44704f69SBart Van Assche case 1:
2293*44704f69SBart Van Assche /* Stream ROD device type specific descriptor */
2294*44704f69SBart Van Assche sgj_js_nv_ihexstr_nex(jsp, jo2p, "peripheral_device_type",
2295*44704f69SBart Van Assche pdt, false, NULL, "Stream ROD device "
2296*44704f69SBart Van Assche "type specific descriptor", ab_pdt);
2297*44704f69SBart Van Assche ull = sg_get_unaligned_be64(bp + 8);
2298*44704f69SBart Van Assche sgj_haj_vi(jsp, jo2p, 4, "Maximum bytes in stream ROD",
2299*44704f69SBart Van Assche SGJ_SEP_COLON_1_SPACE, ull, true);
2300*44704f69SBart Van Assche ull = sg_get_unaligned_be64(bp + 16);
2301*44704f69SBart Van Assche snprintf(b, blen, " Optimal Bytes in stream ROD transfer: ");
2302*44704f69SBart Van Assche if (SG_LIB_UNBOUNDED_64BIT == ull)
2303*44704f69SBart Van Assche sgj_pr_hr(jsp, "%s-1 [no limit]\n", b);
2304*44704f69SBart Van Assche else
2305*44704f69SBart Van Assche sgj_pr_hr(jsp, "%s%" PRIu64 "\n", b, ull);
2306*44704f69SBart Van Assche break;
2307*44704f69SBart Van Assche case 3:
2308*44704f69SBart Van Assche /* Copy manager ROD device type specific descriptor */
2309*44704f69SBart Van Assche sgj_js_nv_ihexstr_nex(jsp, jo2p, "peripheral_device_type",
2310*44704f69SBart Van Assche pdt, false, NULL, "Copy manager ROD "
2311*44704f69SBart Van Assche "device type specific descriptor",
2312*44704f69SBart Van Assche ab_pdt);
2313*44704f69SBart Van Assche sgj_pr_hr(jsp, " Maximum Bytes in processor ROD: %" PRIu64 "\n",
2314*44704f69SBart Van Assche sg_get_unaligned_be64(bp + 8));
2315*44704f69SBart Van Assche ull = sg_get_unaligned_be64(bp + 16);
2316*44704f69SBart Van Assche snprintf(b, blen, " Optimal Bytes in processor ROD transfer: ");
2317*44704f69SBart Van Assche if (SG_LIB_UNBOUNDED_64BIT == ull)
2318*44704f69SBart Van Assche sgj_pr_hr(jsp, "%s-1 [no limit]\n", b);
2319*44704f69SBart Van Assche else
2320*44704f69SBart Van Assche sgj_pr_hr(jsp, "%s%" PRIu64 "\n", b, ull);
2321*44704f69SBart Van Assche break;
2322*44704f69SBart Van Assche default:
2323*44704f69SBart Van Assche sgj_js_nv_ihexstr(jsp, jo2p, "peripheral_device_type",
2324*44704f69SBart Van Assche pdt, NULL, "unknown");
2325*44704f69SBart Van Assche break;
2326*44704f69SBart Van Assche }
2327*44704f69SBart Van Assche sgj_js_nv_o(jsp, jap, NULL /* name */, jo2p);
2328*44704f69SBart Van Assche }
2329*44704f69SBart Van Assche }
2330*44704f69SBart Van Assche
2331*44704f69SBart Van Assche struct tpc_desc_type {
2332*44704f69SBart Van Assche uint8_t code;
2333*44704f69SBart Van Assche const char * name;
2334*44704f69SBart Van Assche };
2335*44704f69SBart Van Assche
2336*44704f69SBart Van Assche static struct tpc_desc_type tpc_desc_arr[] = {
2337*44704f69SBart Van Assche {0x0, "block -> stream"},
2338*44704f69SBart Van Assche {0x1, "stream -> block"},
2339*44704f69SBart Van Assche {0x2, "block -> block"},
2340*44704f69SBart Van Assche {0x3, "stream -> stream"},
2341*44704f69SBart Van Assche {0x4, "inline -> stream"},
2342*44704f69SBart Van Assche {0x5, "embedded -> stream"},
2343*44704f69SBart Van Assche {0x6, "stream -> discard"},
2344*44704f69SBart Van Assche {0x7, "verify CSCD"},
2345*44704f69SBart Van Assche {0x8, "block<o> -> stream"},
2346*44704f69SBart Van Assche {0x9, "stream -> block<o>"},
2347*44704f69SBart Van Assche {0xa, "block<o> -> block<o>"},
2348*44704f69SBart Van Assche {0xb, "block -> stream & application_client"},
2349*44704f69SBart Van Assche {0xc, "stream -> block & application_client"},
2350*44704f69SBart Van Assche {0xd, "block -> block & application_client"},
2351*44704f69SBart Van Assche {0xe, "stream -> stream&application_client"},
2352*44704f69SBart Van Assche {0xf, "stream -> discard&application_client"},
2353*44704f69SBart Van Assche {0x10, "filemark -> tape"},
2354*44704f69SBart Van Assche {0x11, "space -> tape"}, /* obsolete: spc5r02 */
2355*44704f69SBart Van Assche {0x12, "locate -> tape"}, /* obsolete: spc5r02 */
2356*44704f69SBart Van Assche {0x13, "<i>tape -> <i>tape"},
2357*44704f69SBart Van Assche {0x14, "register persistent reservation key"},
2358*44704f69SBart Van Assche {0x15, "third party persistent reservation source I_T nexus"},
2359*44704f69SBart Van Assche {0x16, "<i>block -> <i>block"},
2360*44704f69SBart Van Assche {0x17, "positioning -> tape"}, /* this and next added spc5r02 */
2361*44704f69SBart Van Assche {0x18, "<loi>tape -> <loi>tape"}, /* loi: logical object identifier */
2362*44704f69SBart Van Assche {0xbe, "ROD <- block range(n)"},
2363*44704f69SBart Van Assche {0xbf, "ROD <- block range(1)"},
2364*44704f69SBart Van Assche {0xe0, "CSCD: FC N_Port_Name"},
2365*44704f69SBart Van Assche {0xe1, "CSCD: FC N_Port_ID"},
2366*44704f69SBart Van Assche {0xe2, "CSCD: FC N_Port_ID with N_Port_Name, checking"},
2367*44704f69SBart Van Assche {0xe3, "CSCD: Parallel interface: I_T"},
2368*44704f69SBart Van Assche {0xe4, "CSCD: Identification Descriptor"},
2369*44704f69SBart Van Assche {0xe5, "CSCD: IPv4"},
2370*44704f69SBart Van Assche {0xe6, "CSCD: Alias"},
2371*44704f69SBart Van Assche {0xe7, "CSCD: RDMA"},
2372*44704f69SBart Van Assche {0xe8, "CSCD: IEEE 1394 EUI-64"},
2373*44704f69SBart Van Assche {0xe9, "CSCD: SAS SSP"},
2374*44704f69SBart Van Assche {0xea, "CSCD: IPv6"},
2375*44704f69SBart Van Assche {0xeb, "CSCD: IP copy service"},
2376*44704f69SBart Van Assche {0xfe, "CSCD: ROD"},
2377*44704f69SBart Van Assche {0xff, "CSCD: extension"},
2378*44704f69SBart Van Assche {0x0, NULL},
2379*44704f69SBart Van Assche };
2380*44704f69SBart Van Assche
2381*44704f69SBart Van Assche static const char *
get_tpc_desc_name(uint8_t code)2382*44704f69SBart Van Assche get_tpc_desc_name(uint8_t code)
2383*44704f69SBart Van Assche {
2384*44704f69SBart Van Assche const struct tpc_desc_type * dtp;
2385*44704f69SBart Van Assche
2386*44704f69SBart Van Assche for (dtp = tpc_desc_arr; dtp->name; ++dtp) {
2387*44704f69SBart Van Assche if (code == dtp->code)
2388*44704f69SBart Van Assche return dtp->name;
2389*44704f69SBart Van Assche }
2390*44704f69SBart Van Assche return "";
2391*44704f69SBart Van Assche }
2392*44704f69SBart Van Assche
2393*44704f69SBart Van Assche struct tpc_rod_type {
2394*44704f69SBart Van Assche uint32_t type;
2395*44704f69SBart Van Assche const char * name;
2396*44704f69SBart Van Assche };
2397*44704f69SBart Van Assche
2398*44704f69SBart Van Assche static struct tpc_rod_type tpc_rod_arr[] = {
2399*44704f69SBart Van Assche {0x0, "copy manager internal"},
2400*44704f69SBart Van Assche {0x10000, "access upon reference"},
2401*44704f69SBart Van Assche {0x800000, "point in time copy - default"},
2402*44704f69SBart Van Assche {0x800001, "point in time copy - change vulnerable"},
2403*44704f69SBart Van Assche {0x800002, "point in time copy - persistent"},
2404*44704f69SBart Van Assche {0x80ffff, "point in time copy - any"},
2405*44704f69SBart Van Assche {0xffff0001, "block device zero"},
2406*44704f69SBart Van Assche {0x0, NULL},
2407*44704f69SBart Van Assche };
2408*44704f69SBart Van Assche
2409*44704f69SBart Van Assche static const char *
get_tpc_rod_name(uint32_t rod_type)2410*44704f69SBart Van Assche get_tpc_rod_name(uint32_t rod_type)
2411*44704f69SBart Van Assche {
2412*44704f69SBart Van Assche const struct tpc_rod_type * rtp;
2413*44704f69SBart Van Assche
2414*44704f69SBart Van Assche for (rtp = tpc_rod_arr; rtp->name; ++rtp) {
2415*44704f69SBart Van Assche if (rod_type == rtp->type)
2416*44704f69SBart Van Assche return rtp->name;
2417*44704f69SBart Van Assche }
2418*44704f69SBart Van Assche return "";
2419*44704f69SBart Van Assche }
2420*44704f69SBart Van Assche
2421*44704f69SBart Van Assche struct cscd_desc_id_t {
2422*44704f69SBart Van Assche uint16_t id;
2423*44704f69SBart Van Assche const char * name;
2424*44704f69SBart Van Assche };
2425*44704f69SBart Van Assche
2426*44704f69SBart Van Assche static struct cscd_desc_id_t cscd_desc_id_arr[] = {
2427*44704f69SBart Van Assche /* only values higher than 0x7ff are listed */
2428*44704f69SBart Van Assche {0xc000, "copy src or dst null LU, pdt=0"},
2429*44704f69SBart Van Assche {0xc001, "copy src or dst null LU, pdt=1"},
2430*44704f69SBart Van Assche {0xf800, "copy src or dst in ROD token"},
2431*44704f69SBart Van Assche {0xffff, "copy src or dst is copy manager LU"},
2432*44704f69SBart Van Assche {0x0, NULL},
2433*44704f69SBart Van Assche };
2434*44704f69SBart Van Assche
2435*44704f69SBart Van Assche static const char *
get_cscd_desc_id_name(uint16_t cscd_desc_id)2436*44704f69SBart Van Assche get_cscd_desc_id_name(uint16_t cscd_desc_id)
2437*44704f69SBart Van Assche {
2438*44704f69SBart Van Assche const struct cscd_desc_id_t * cdip;
2439*44704f69SBart Van Assche
2440*44704f69SBart Van Assche for (cdip = cscd_desc_id_arr; cdip->name; ++cdip) {
2441*44704f69SBart Van Assche if (cscd_desc_id == cdip->id)
2442*44704f69SBart Van Assche return cdip->name;
2443*44704f69SBart Van Assche }
2444*44704f69SBart Van Assche return "";
2445*44704f69SBart Van Assche }
2446*44704f69SBart Van Assche
2447*44704f69SBart Van Assche static const char *
get_tpc_desc_type_s(uint32_t desc_type)2448*44704f69SBart Van Assche get_tpc_desc_type_s(uint32_t desc_type)
2449*44704f69SBart Van Assche {
2450*44704f69SBart Van Assche switch(desc_type) {
2451*44704f69SBart Van Assche case 0:
2452*44704f69SBart Van Assche return "Block Device ROD Limits";
2453*44704f69SBart Van Assche case 1:
2454*44704f69SBart Van Assche return "Supported Commands";
2455*44704f69SBart Van Assche case 4:
2456*44704f69SBart Van Assche return "Parameter Data";
2457*44704f69SBart Van Assche case 8:
2458*44704f69SBart Van Assche return "Supported Descriptors";
2459*44704f69SBart Van Assche case 0xc:
2460*44704f69SBart Van Assche return "Supported CSCD Descriptor IDs";
2461*44704f69SBart Van Assche case 0xd:
2462*44704f69SBart Van Assche return "Copy Group Identifier";
2463*44704f69SBart Van Assche case 0x106:
2464*44704f69SBart Van Assche return "ROD Token Features";
2465*44704f69SBart Van Assche case 0x108:
2466*44704f69SBart Van Assche return "Supported ROD Token and ROD Types";
2467*44704f69SBart Van Assche case 0x8001:
2468*44704f69SBart Van Assche return "General Copy Operations";
2469*44704f69SBart Van Assche case 0x9101:
2470*44704f69SBart Van Assche return "Stream Copy Operations";
2471*44704f69SBart Van Assche case 0xC001:
2472*44704f69SBart Van Assche return "Held Data";
2473*44704f69SBart Van Assche default:
2474*44704f69SBart Van Assche if ((desc_type >= 0xE000) && (desc_type <= 0xEFFF))
2475*44704f69SBart Van Assche return "Restricted";
2476*44704f69SBart Van Assche else
2477*44704f69SBart Van Assche return "Reserved";
2478*44704f69SBart Van Assche }
2479*44704f69SBart Van Assche }
2480*44704f69SBart Van Assche
2481*44704f69SBart Van Assche /* VPD_3PARTY_COPY 3PC, third party copy 0x8f ["tpc"] */
2482*44704f69SBart Van Assche void
decode_3party_copy_vpd(const uint8_t * buff,int len,struct opts_t * op,sgj_opaque_p jap)2483*44704f69SBart Van Assche decode_3party_copy_vpd(const uint8_t * buff, int len,
2484*44704f69SBart Van Assche struct opts_t * op, sgj_opaque_p jap)
2485*44704f69SBart Van Assche {
2486*44704f69SBart Van Assche int j, k, m, bump, desc_type, desc_len, sa_len, pdt;
2487*44704f69SBart Van Assche uint32_t u, v;
2488*44704f69SBart Van Assche uint64_t ull;
2489*44704f69SBart Van Assche const uint8_t * bp;
2490*44704f69SBart Van Assche const char * cp;
2491*44704f69SBart Van Assche const char * dtp;
2492*44704f69SBart Van Assche sgj_state * jsp = &op->json_st;
2493*44704f69SBart Van Assche sgj_opaque_p jo2p = NULL;
2494*44704f69SBart Van Assche sgj_opaque_p ja2p = NULL;
2495*44704f69SBart Van Assche sgj_opaque_p jo3p = NULL;
2496*44704f69SBart Van Assche char b[144];
2497*44704f69SBart Van Assche static const int blen = sizeof(b);
2498*44704f69SBart Van Assche
2499*44704f69SBart Van Assche if (len < 4) {
2500*44704f69SBart Van Assche pr2serr("VPD page length too short=%d\n", len);
2501*44704f69SBart Van Assche return;
2502*44704f69SBart Van Assche }
2503*44704f69SBart Van Assche if (3 == op->do_hex) {
2504*44704f69SBart Van Assche hex2stdout(buff, len, -1);
2505*44704f69SBart Van Assche return;
2506*44704f69SBart Van Assche }
2507*44704f69SBart Van Assche pdt = buff[0] & PDT_MASK;
2508*44704f69SBart Van Assche len -= 4;
2509*44704f69SBart Van Assche bp = buff + 4;
2510*44704f69SBart Van Assche for (k = 0; k < len; k += bump, bp += bump) {
2511*44704f69SBart Van Assche jo2p = sgj_new_unattached_object_r(jsp);
2512*44704f69SBart Van Assche desc_type = sg_get_unaligned_be16(bp);
2513*44704f69SBart Van Assche desc_len = sg_get_unaligned_be16(bp + 2);
2514*44704f69SBart Van Assche if (op->verbose)
2515*44704f69SBart Van Assche sgj_pr_hr(jsp, "Descriptor type=%d [0x%x] , len %d\n", desc_type,
2516*44704f69SBart Van Assche desc_type, desc_len);
2517*44704f69SBart Van Assche bump = 4 + desc_len;
2518*44704f69SBart Van Assche if ((k + bump) > len) {
2519*44704f69SBart Van Assche pr2serr("VPD page, short descriptor length=%d, left=%d\n", bump,
2520*44704f69SBart Van Assche (len - k));
2521*44704f69SBart Van Assche break;
2522*44704f69SBart Van Assche }
2523*44704f69SBart Van Assche if (0 == desc_len)
2524*44704f69SBart Van Assche goto skip; /* continue plus attach jo2p */
2525*44704f69SBart Van Assche if (2 == op->do_hex)
2526*44704f69SBart Van Assche hex2stdout(bp + 4, desc_len, 1);
2527*44704f69SBart Van Assche else if (op->do_hex > 2)
2528*44704f69SBart Van Assche hex2stdout(bp, bump, 1);
2529*44704f69SBart Van Assche else {
2530*44704f69SBart Van Assche int csll;
2531*44704f69SBart Van Assche
2532*44704f69SBart Van Assche dtp = get_tpc_desc_type_s(desc_type);
2533*44704f69SBart Van Assche sgj_js_nv_ihexstr(jsp, jo2p, "third_party_copy_descriptor_type",
2534*44704f69SBart Van Assche desc_type, NULL, dtp);
2535*44704f69SBart Van Assche sgj_js_nv_ihex(jsp, jo2p, "third_party_copy_descriptor_length",
2536*44704f69SBart Van Assche desc_len);
2537*44704f69SBart Van Assche
2538*44704f69SBart Van Assche switch (desc_type) {
2539*44704f69SBart Van Assche case 0x0000: /* Required if POPULATE TOKEN (or friend) used */
2540*44704f69SBart Van Assche sgj_pr_hr(jsp, " %s:\n", dtp);
2541*44704f69SBart Van Assche u = sg_get_unaligned_be16(bp + 10);
2542*44704f69SBart Van Assche sgj_haj_vistr(jsp, jo2p, 2, "Maximum range descriptors",
2543*44704f69SBart Van Assche SGJ_SEP_COLON_1_SPACE, u, true,
2544*44704f69SBart Van Assche (0 == u) ? nr_s : NULL);
2545*44704f69SBart Van Assche u = sg_get_unaligned_be32(bp + 12);
2546*44704f69SBart Van Assche if (0 == u)
2547*44704f69SBart Van Assche cp = nr_s;
2548*44704f69SBart Van Assche else if (SG_LIB_UNBOUNDED_32BIT == u)
2549*44704f69SBart Van Assche cp = "No maximum given";
2550*44704f69SBart Van Assche else
2551*44704f69SBart Van Assche cp = NULL;
2552*44704f69SBart Van Assche sgj_haj_vistr_nex(jsp, jo2p, 2, "Maximum inactivity timeout",
2553*44704f69SBart Van Assche SGJ_SEP_COLON_1_SPACE, u, true, cp,
2554*44704f69SBart Van Assche "unit: second");
2555*44704f69SBart Van Assche u = sg_get_unaligned_be32(bp + 16);
2556*44704f69SBart Van Assche sgj_haj_vistr_nex(jsp, jo2p, 2, "Default inactivity timeout",
2557*44704f69SBart Van Assche SGJ_SEP_COLON_1_SPACE, u, true,
2558*44704f69SBart Van Assche (0 == u) ? nr_s : NULL, "unit: second");
2559*44704f69SBart Van Assche ull = sg_get_unaligned_be64(bp + 20);
2560*44704f69SBart Van Assche sgj_haj_vistr_nex(jsp, jo2p, 2, "Maximum token transfer size",
2561*44704f69SBart Van Assche SGJ_SEP_COLON_1_SPACE, ull, true,
2562*44704f69SBart Van Assche (0 == ull) ? nr_s : NULL, "unit: LB");
2563*44704f69SBart Van Assche ull = sg_get_unaligned_be64(bp + 28);
2564*44704f69SBart Van Assche sgj_haj_vistr_nex(jsp, jo2p, 2, "Optimal transfer count",
2565*44704f69SBart Van Assche SGJ_SEP_COLON_1_SPACE, ull, true,
2566*44704f69SBart Van Assche (0 == ull) ? nr_s : NULL, "unit: LB");
2567*44704f69SBart Van Assche break;
2568*44704f69SBart Van Assche case 0x0001: /* Mandatory (SPC-4) */
2569*44704f69SBart Van Assche sgj_pr_hr(jsp, " %s:\n", "Commands supported list");
2570*44704f69SBart Van Assche ja2p = sgj_named_subarray_r(jsp, jo2p,
2571*44704f69SBart Van Assche "commands_supported_list");
2572*44704f69SBart Van Assche j = 0;
2573*44704f69SBart Van Assche csll = bp[4];
2574*44704f69SBart Van Assche if (csll >= desc_len) {
2575*44704f69SBart Van Assche pr2serr("Command supported list length (%d) >= "
2576*44704f69SBart Van Assche "descriptor length (%d), wrong so trim\n",
2577*44704f69SBart Van Assche csll, desc_len);
2578*44704f69SBart Van Assche csll = desc_len - 1;
2579*44704f69SBart Van Assche }
2580*44704f69SBart Van Assche while (j < csll) {
2581*44704f69SBart Van Assche uint8_t opc, sa;
2582*44704f69SBart Van Assche static const char * soc = "supported_operation_code";
2583*44704f69SBart Van Assche static const char * ssa = "supported_service_action";
2584*44704f69SBart Van Assche
2585*44704f69SBart Van Assche jo3p = NULL;
2586*44704f69SBart Van Assche opc = bp[5 + j];
2587*44704f69SBart Van Assche sa_len = bp[6 + j];
2588*44704f69SBart Van Assche for (m = 0; (m < sa_len) && ((j + m) < csll); ++m) {
2589*44704f69SBart Van Assche jo3p = sgj_new_unattached_object_r(jsp);
2590*44704f69SBart Van Assche sa = bp[7 + j + m];
2591*44704f69SBart Van Assche sg_get_opcode_sa_name(opc, sa, pdt, blen, b);
2592*44704f69SBart Van Assche sgj_pr_hr(jsp, " %s\n", b);
2593*44704f69SBart Van Assche sgj_js_nv_s(jsp, jo3p, "name", b);
2594*44704f69SBart Van Assche sgj_js_nv_ihex(jsp, jo3p, soc, opc);
2595*44704f69SBart Van Assche sgj_js_nv_ihex(jsp, jo3p, ssa, sa);
2596*44704f69SBart Van Assche sgj_js_nv_o(jsp, ja2p, NULL /* name */, jo3p);
2597*44704f69SBart Van Assche }
2598*44704f69SBart Van Assche if (0 == sa_len) {
2599*44704f69SBart Van Assche jo3p = sgj_new_unattached_object_r(jsp);
2600*44704f69SBart Van Assche sg_get_opcode_name(opc, pdt, blen, b);
2601*44704f69SBart Van Assche sgj_pr_hr(jsp, " %s\n", b);
2602*44704f69SBart Van Assche sgj_js_nv_s(jsp, jo3p, "name", b);
2603*44704f69SBart Van Assche sgj_js_nv_ihex(jsp, jo3p, soc, opc);
2604*44704f69SBart Van Assche sgj_js_nv_o(jsp, ja2p, NULL /* name */, jo3p);
2605*44704f69SBart Van Assche } else if (m < sa_len)
2606*44704f69SBart Van Assche pr2serr("Supported service actions list length (%d) "
2607*44704f69SBart Van Assche "is too large\n", sa_len);
2608*44704f69SBart Van Assche j += m + 2;
2609*44704f69SBart Van Assche }
2610*44704f69SBart Van Assche break;
2611*44704f69SBart Van Assche case 0x0004:
2612*44704f69SBart Van Assche sgj_pr_hr(jsp, " %s:\n", dtp);
2613*44704f69SBart Van Assche sgj_haj_vi(jsp, jo2p, 2, "Maximum CSCD descriptor count",
2614*44704f69SBart Van Assche SGJ_SEP_COLON_1_SPACE,
2615*44704f69SBart Van Assche sg_get_unaligned_be16(bp + 8), true);
2616*44704f69SBart Van Assche sgj_haj_vi(jsp, jo2p, 2, "Maximum segment descriptor count",
2617*44704f69SBart Van Assche SGJ_SEP_COLON_1_SPACE,
2618*44704f69SBart Van Assche sg_get_unaligned_be16(bp + 10), true);
2619*44704f69SBart Van Assche sgj_haj_vi(jsp, jo2p, 2, "Maximum descriptor list length",
2620*44704f69SBart Van Assche SGJ_SEP_COLON_1_SPACE,
2621*44704f69SBart Van Assche sg_get_unaligned_be32(bp + 12), true);
2622*44704f69SBart Van Assche sgj_haj_vi(jsp, jo2p, 2, "Maximum inline data length",
2623*44704f69SBart Van Assche SGJ_SEP_COLON_1_SPACE,
2624*44704f69SBart Van Assche sg_get_unaligned_be32(bp + 17), true);
2625*44704f69SBart Van Assche break;
2626*44704f69SBart Van Assche case 0x0008:
2627*44704f69SBart Van Assche sgj_pr_hr(jsp, " Supported descriptors:\n");
2628*44704f69SBart Van Assche ja2p = sgj_named_subarray_r(jsp, jo2p,
2629*44704f69SBart Van Assche "supported_descriptor_list");
2630*44704f69SBart Van Assche for (j = 0; j < bp[4]; j++) {
2631*44704f69SBart Van Assche bool found_name;
2632*44704f69SBart Van Assche
2633*44704f69SBart Van Assche jo3p = sgj_new_unattached_object_r(jsp);
2634*44704f69SBart Van Assche u = bp[5 + j];
2635*44704f69SBart Van Assche cp = get_tpc_desc_name(u);
2636*44704f69SBart Van Assche found_name = (strlen(cp) > 0);
2637*44704f69SBart Van Assche if (found_name)
2638*44704f69SBart Van Assche sgj_pr_hr(jsp, " %s [0x%x]\n", cp, u);
2639*44704f69SBart Van Assche else
2640*44704f69SBart Van Assche sgj_pr_hr(jsp, " 0x%x\n", u);
2641*44704f69SBart Van Assche sgj_js_nv_s(jsp, jo3p, "name", found_name ? cp : nr_s);
2642*44704f69SBart Van Assche sgj_js_nv_ihex(jsp, jo3p, "code", u);
2643*44704f69SBart Van Assche sgj_js_nv_o(jsp, ja2p, NULL /* name */, jo3p);
2644*44704f69SBart Van Assche }
2645*44704f69SBart Van Assche break;
2646*44704f69SBart Van Assche case 0x000C:
2647*44704f69SBart Van Assche sgj_pr_hr(jsp, " Supported CSCD IDs (above 0x7ff):\n");
2648*44704f69SBart Van Assche ja2p = sgj_named_subarray_r(jsp, jo2p, "supported_cscd_"
2649*44704f69SBart Van Assche "descriptor_id_list");
2650*44704f69SBart Van Assche v = sg_get_unaligned_be16(bp + 4);
2651*44704f69SBart Van Assche for (j = 0; j < (int)v; j += 2) {
2652*44704f69SBart Van Assche bool found_name;
2653*44704f69SBart Van Assche
2654*44704f69SBart Van Assche jo3p = sgj_new_unattached_object_r(jsp);
2655*44704f69SBart Van Assche u = sg_get_unaligned_be16(bp + 6 + j);
2656*44704f69SBart Van Assche cp = get_cscd_desc_id_name(u);
2657*44704f69SBart Van Assche found_name = (strlen(cp) > 0);
2658*44704f69SBart Van Assche if (found_name)
2659*44704f69SBart Van Assche sgj_pr_hr(jsp, " %s [0x%04x]\n", cp, u);
2660*44704f69SBart Van Assche else
2661*44704f69SBart Van Assche sgj_pr_hr(jsp, " 0x%04x\n", u);
2662*44704f69SBart Van Assche sgj_js_nv_s(jsp, jo3p, "name", found_name ? cp : nr_s);
2663*44704f69SBart Van Assche sgj_js_nv_ihex(jsp, jo3p, "id", u);
2664*44704f69SBart Van Assche sgj_js_nv_o(jsp, ja2p, NULL /* name */, jo3p);
2665*44704f69SBart Van Assche }
2666*44704f69SBart Van Assche break;
2667*44704f69SBart Van Assche case 0x000D:
2668*44704f69SBart Van Assche sgj_pr_hr(jsp, " Copy group identifier:\n");
2669*44704f69SBart Van Assche u = bp[4];
2670*44704f69SBart Van Assche sg_t10_uuid_desig2str(bp + 5, u, 1 /* c_set */, false,
2671*44704f69SBart Van Assche true, NULL, blen, b);
2672*44704f69SBart Van Assche sgj_pr_hr(jsp, " Locally assigned UUID: %s", b);
2673*44704f69SBart Van Assche sgj_js_nv_s(jsp, jo2p, "locally_assigned_uuid", b);
2674*44704f69SBart Van Assche break;
2675*44704f69SBart Van Assche case 0x0106:
2676*44704f69SBart Van Assche sgj_pr_hr(jsp, " ROD token features:\n");
2677*44704f69SBart Van Assche sgj_haj_vi(jsp, jo2p, 2, "Remote tokens",
2678*44704f69SBart Van Assche SGJ_SEP_COLON_1_SPACE, bp[4] & 0x0f, true);
2679*44704f69SBart Van Assche u = sg_get_unaligned_be32(bp + 16);
2680*44704f69SBart Van Assche sgj_pr_hr(jsp, " Minimum token lifetime: %u seconds\n", u);
2681*44704f69SBart Van Assche sgj_js_nv_ihex_nex(jsp, jo2p, "minimum_token_lifetime", u,
2682*44704f69SBart Van Assche true, "unit: second");
2683*44704f69SBart Van Assche u = sg_get_unaligned_be32(bp + 20);
2684*44704f69SBart Van Assche sgj_pr_hr(jsp, " Maximum token lifetime: %u seconds\n", u);
2685*44704f69SBart Van Assche sgj_js_nv_ihex_nex(jsp, jo2p, "maximum_token_lifetime", u,
2686*44704f69SBart Van Assche true, "unit: second");
2687*44704f69SBart Van Assche u = sg_get_unaligned_be32(bp + 24);
2688*44704f69SBart Van Assche sgj_haj_vi_nex(jsp, jo2p, 2, "Maximum token inactivity "
2689*44704f69SBart Van Assche "timeout", SGJ_SEP_COLON_1_SPACE, u,
2690*44704f69SBart Van Assche true, "unit: second");
2691*44704f69SBart Van Assche u = sg_get_unaligned_be16(bp + 46);
2692*44704f69SBart Van Assche ja2p = sgj_named_subarray_r(jsp, jo2p,
2693*44704f69SBart Van Assche "rod_device_type_specific_features_descriptor_list");
2694*44704f69SBart Van Assche decode_rod_descriptor(bp + 48, u, op, ja2p);
2695*44704f69SBart Van Assche break;
2696*44704f69SBart Van Assche case 0x0108:
2697*44704f69SBart Van Assche sgj_pr_hr(jsp, " Supported ROD token and ROD types:\n");
2698*44704f69SBart Van Assche ja2p = sgj_named_subarray_r(jsp, jo2p, "rod_type_"
2699*44704f69SBart Van Assche "descriptor_list");
2700*44704f69SBart Van Assche for (j = 0; j < sg_get_unaligned_be16(bp + 6); j+= 64) {
2701*44704f69SBart Van Assche bool found_name;
2702*44704f69SBart Van Assche
2703*44704f69SBart Van Assche jo3p = sgj_new_unattached_object_r(jsp);
2704*44704f69SBart Van Assche u = sg_get_unaligned_be32(bp + 8 + j);
2705*44704f69SBart Van Assche cp = get_tpc_rod_name(u);
2706*44704f69SBart Van Assche found_name = (strlen(cp) > 0);
2707*44704f69SBart Van Assche if (found_name > 0)
2708*44704f69SBart Van Assche sgj_pr_hr(jsp, " ROD type: %s [0x%x]\n", cp, u);
2709*44704f69SBart Van Assche else
2710*44704f69SBart Van Assche sgj_pr_hr(jsp, " ROD type: 0x%x\n", u);
2711*44704f69SBart Van Assche sgj_js_nv_ihexstr(jsp, jo3p, "rod_type", u, NULL,
2712*44704f69SBart Van Assche found_name ? cp : NULL);
2713*44704f69SBart Van Assche u = bp[8 + j + 4];
2714*44704f69SBart Van Assche sgj_pr_hr(jsp, " ECPY_INT: %s\n",
2715*44704f69SBart Van Assche (u & 0x80) ? y_s : n_s);
2716*44704f69SBart Van Assche sgj_js_nv_ihex_nex(jsp, jo3p, "ecpy_int", !!(0x80 & u),
2717*44704f69SBart Van Assche false, "Extended CoPY INTernal rods");
2718*44704f69SBart Van Assche sgj_pr_hr(jsp, " Token in: %s\n",
2719*44704f69SBart Van Assche (u & 0x2) ? y_s : n_s);
2720*44704f69SBart Van Assche sgj_js_nv_i(jsp, jo3p, "token_in", !!(0x2 & u));
2721*44704f69SBart Van Assche sgj_pr_hr(jsp, " Token out: %s\n",
2722*44704f69SBart Van Assche (u & 0x1) ? y_s : n_s);
2723*44704f69SBart Van Assche sgj_js_nv_i(jsp, jo3p, "token_out", !!(0x2 & u));
2724*44704f69SBart Van Assche u = sg_get_unaligned_be16(bp + 8 + j + 6);
2725*44704f69SBart Van Assche sgj_haj_vi(jsp, jo3p, 4, "Preference indicator",
2726*44704f69SBart Van Assche SGJ_SEP_COLON_1_SPACE, u, true);
2727*44704f69SBart Van Assche sgj_js_nv_o(jsp, ja2p, NULL /* name */, jo3p);
2728*44704f69SBart Van Assche }
2729*44704f69SBart Van Assche break;
2730*44704f69SBart Van Assche case 0x8001: /* Mandatory (SPC-4) */
2731*44704f69SBart Van Assche sgj_pr_hr(jsp, " General copy operations:\n");
2732*44704f69SBart Van Assche u = sg_get_unaligned_be32(bp + 4);
2733*44704f69SBart Van Assche sgj_haj_vi(jsp, jo2p, 2, "Total concurrent copies",
2734*44704f69SBart Van Assche SGJ_SEP_COLON_1_SPACE, u, true);
2735*44704f69SBart Van Assche u = sg_get_unaligned_be32(bp + 8);
2736*44704f69SBart Van Assche sgj_haj_vi(jsp, jo2p, 2, "Maximum identified concurrent "
2737*44704f69SBart Van Assche "copies", SGJ_SEP_COLON_1_SPACE, u, true);
2738*44704f69SBart Van Assche u = sg_get_unaligned_be32(bp + 12);
2739*44704f69SBart Van Assche sgj_haj_vi_nex(jsp, jo2p, 2, "Maximum segment length",
2740*44704f69SBart Van Assche SGJ_SEP_COLON_1_SPACE, u, true, "unit: byte");
2741*44704f69SBart Van Assche u = bp[16]; /* field is power of 2 */
2742*44704f69SBart Van Assche sgj_haj_vi_nex(jsp, jo2p, 2, "Data segment granularity",
2743*44704f69SBart Van Assche SGJ_SEP_COLON_1_SPACE, u, true,
2744*44704f69SBart Van Assche "unit: 2^val LB");
2745*44704f69SBart Van Assche u = bp[17]; /* field is power of 2 */
2746*44704f69SBart Van Assche sgj_haj_vi_nex(jsp, jo2p, 2, "Inline data granularity",
2747*44704f69SBart Van Assche SGJ_SEP_COLON_1_SPACE, u, true,
2748*44704f69SBart Van Assche "unit: 2^val LB");
2749*44704f69SBart Van Assche break;
2750*44704f69SBart Van Assche case 0x9101:
2751*44704f69SBart Van Assche sgj_pr_hr(jsp, " Stream copy operations:\n");
2752*44704f69SBart Van Assche u = sg_get_unaligned_be32(bp + 4);
2753*44704f69SBart Van Assche sgj_haj_vi_nex(jsp, jo2p, 2, "Maximum stream device transfer "
2754*44704f69SBart Van Assche "size", SGJ_SEP_COLON_1_SPACE, u, true,
2755*44704f69SBart Van Assche "unit: byte");
2756*44704f69SBart Van Assche break;
2757*44704f69SBart Van Assche case 0xC001:
2758*44704f69SBart Van Assche sgj_pr_hr(jsp, " Held data:\n");
2759*44704f69SBart Van Assche u = sg_get_unaligned_be32(bp + 4);
2760*44704f69SBart Van Assche sgj_haj_vi_nex(jsp, jo2p, 2, "Held data limit",
2761*44704f69SBart Van Assche SGJ_SEP_COLON_1_SPACE, u, true,
2762*44704f69SBart Van Assche "unit: byte; (lower limit: minimum)");
2763*44704f69SBart Van Assche sgj_haj_vi_nex(jsp, jo2p, 2, "Held data granularity",
2764*44704f69SBart Van Assche SGJ_SEP_COLON_1_SPACE, bp[8], true,
2765*44704f69SBart Van Assche "unit: 2^val byte");
2766*44704f69SBart Van Assche break;
2767*44704f69SBart Van Assche default:
2768*44704f69SBart Van Assche pr2serr("Unexpected type=%d\n", desc_type);
2769*44704f69SBart Van Assche hex2stderr(bp, bump, 1);
2770*44704f69SBart Van Assche break;
2771*44704f69SBart Van Assche }
2772*44704f69SBart Van Assche }
2773*44704f69SBart Van Assche skip:
2774*44704f69SBart Van Assche sgj_js_nv_o(jsp, jap, NULL /* name */, jo2p);
2775*44704f69SBart Van Assche jo2p = NULL;
2776*44704f69SBart Van Assche }
2777*44704f69SBart Van Assche if (jo2p)
2778*44704f69SBart Van Assche sgj_js_nv_o(jsp, jap, NULL /* name */, jo2p);
2779*44704f69SBart Van Assche }
2780*44704f69SBart Van Assche
2781*44704f69SBart Van Assche /* VPD_PROTO_LU 0x90 ["pslu"] */
2782*44704f69SBart Van Assche void
decode_proto_lu_vpd(const uint8_t * buff,int len,struct opts_t * op,sgj_opaque_p jap)2783*44704f69SBart Van Assche decode_proto_lu_vpd(const uint8_t * buff, int len, struct opts_t * op,
2784*44704f69SBart Van Assche sgj_opaque_p jap)
2785*44704f69SBart Van Assche {
2786*44704f69SBart Van Assche int k, bump, rel_port, desc_len, proto;
2787*44704f69SBart Van Assche const uint8_t * bp;
2788*44704f69SBart Van Assche sgj_state * jsp = &op->json_st;
2789*44704f69SBart Van Assche sgj_opaque_p jo2p = NULL;
2790*44704f69SBart Van Assche char b[128];
2791*44704f69SBart Van Assche static const int blen = sizeof(b);
2792*44704f69SBart Van Assche
2793*44704f69SBart Van Assche if ((1 == op->do_hex) || (op->do_hex > 2)) {
2794*44704f69SBart Van Assche hex2stdout(buff, len, (1 == op->do_hex) ? 1 : -1);
2795*44704f69SBart Van Assche return;
2796*44704f69SBart Van Assche }
2797*44704f69SBart Van Assche if (len < 4) {
2798*44704f69SBart Van Assche pr2serr("VPD page length too short=%d\n", len);
2799*44704f69SBart Van Assche return;
2800*44704f69SBart Van Assche }
2801*44704f69SBart Van Assche len -= 4;
2802*44704f69SBart Van Assche bp = buff + 4;
2803*44704f69SBart Van Assche for (k = 0; k < len; k += bump, bp += bump) {
2804*44704f69SBart Van Assche jo2p = sgj_new_unattached_object_r(jsp);
2805*44704f69SBart Van Assche rel_port = sg_get_unaligned_be16(bp);
2806*44704f69SBart Van Assche sgj_haj_vi(jsp, jo2p, 2, "Relative port",
2807*44704f69SBart Van Assche SGJ_SEP_COLON_1_SPACE, rel_port, true);
2808*44704f69SBart Van Assche proto = bp[2] & 0xf;
2809*44704f69SBart Van Assche sg_get_trans_proto_str(proto, blen, b);
2810*44704f69SBart Van Assche sgj_haj_vistr(jsp, jo2p, 4, "Protocol identifier",
2811*44704f69SBart Van Assche SGJ_SEP_COLON_1_SPACE, proto, false, b);
2812*44704f69SBart Van Assche desc_len = sg_get_unaligned_be16(bp + 6);
2813*44704f69SBart Van Assche bump = 8 + desc_len;
2814*44704f69SBart Van Assche if ((k + bump) > len) {
2815*44704f69SBart Van Assche pr2serr("Protocol-specific logical unit information VPD page, "
2816*44704f69SBart Van Assche "short descriptor length=%d, left=%d\n", bump, (len - k));
2817*44704f69SBart Van Assche sgj_js_nv_o(jsp, jap, NULL /* name */, jo2p);
2818*44704f69SBart Van Assche return;
2819*44704f69SBart Van Assche }
2820*44704f69SBart Van Assche if (0 == desc_len)
2821*44704f69SBart Van Assche goto again;
2822*44704f69SBart Van Assche if (2 == op->do_hex) {
2823*44704f69SBart Van Assche hex2stdout(bp + 8, desc_len, 1);
2824*44704f69SBart Van Assche goto again;
2825*44704f69SBart Van Assche }
2826*44704f69SBart Van Assche switch (proto) {
2827*44704f69SBart Van Assche case TPROTO_SAS:
2828*44704f69SBart Van Assche sgj_haj_vi(jsp, jo2p, 2, "TLR control supported",
2829*44704f69SBart Van Assche SGJ_SEP_COLON_1_SPACE, !!(bp[8] & 0x1), false);
2830*44704f69SBart Van Assche break;
2831*44704f69SBart Van Assche default:
2832*44704f69SBart Van Assche pr2serr("Unexpected proto=%d\n", proto);
2833*44704f69SBart Van Assche hex2stderr(bp, bump, 1);
2834*44704f69SBart Van Assche break;
2835*44704f69SBart Van Assche }
2836*44704f69SBart Van Assche again:
2837*44704f69SBart Van Assche sgj_js_nv_o(jsp, jap, NULL /* name */, jo2p);
2838*44704f69SBart Van Assche }
2839*44704f69SBart Van Assche }
2840*44704f69SBart Van Assche
2841*44704f69SBart Van Assche /* VPD_PROTO_PORT 0x91 ["pspo"] */
2842*44704f69SBart Van Assche void
decode_proto_port_vpd(const uint8_t * buff,int len,struct opts_t * op,sgj_opaque_p jap)2843*44704f69SBart Van Assche decode_proto_port_vpd(const uint8_t * buff, int len, struct opts_t * op,
2844*44704f69SBart Van Assche sgj_opaque_p jap)
2845*44704f69SBart Van Assche {
2846*44704f69SBart Van Assche bool pds, ssp_pers;
2847*44704f69SBart Van Assche int k, j, bump, rel_port, desc_len, proto, phy;
2848*44704f69SBart Van Assche const uint8_t * bp;
2849*44704f69SBart Van Assche const uint8_t * pidp;
2850*44704f69SBart Van Assche sgj_state * jsp = &op->json_st;
2851*44704f69SBart Van Assche sgj_opaque_p jo2p = NULL;
2852*44704f69SBart Van Assche sgj_opaque_p ja2p = NULL;
2853*44704f69SBart Van Assche sgj_opaque_p jo3p = NULL;
2854*44704f69SBart Van Assche char b[128];
2855*44704f69SBart Van Assche static const int blen = sizeof(b);
2856*44704f69SBart Van Assche
2857*44704f69SBart Van Assche if ((1 == op->do_hex) || (op->do_hex > 2)) {
2858*44704f69SBart Van Assche hex2stdout(buff, len, (1 == op->do_hex) ? 1 : -1);
2859*44704f69SBart Van Assche return;
2860*44704f69SBart Van Assche }
2861*44704f69SBart Van Assche if (len < 4) {
2862*44704f69SBart Van Assche pr2serr("VPD page length too short=%d\n", len);
2863*44704f69SBart Van Assche return;
2864*44704f69SBart Van Assche }
2865*44704f69SBart Van Assche len -= 4;
2866*44704f69SBart Van Assche bp = buff + 4;
2867*44704f69SBart Van Assche for (k = 0; k < len; k += bump, bp += bump) {
2868*44704f69SBart Van Assche jo2p = sgj_new_unattached_object_r(jsp);
2869*44704f69SBart Van Assche rel_port = sg_get_unaligned_be16(bp);
2870*44704f69SBart Van Assche sgj_haj_vi(jsp, jo2p, 2, "Relative port",
2871*44704f69SBart Van Assche SGJ_SEP_COLON_1_SPACE, rel_port, true);
2872*44704f69SBart Van Assche proto = bp[2] & 0xf;
2873*44704f69SBart Van Assche sg_get_trans_proto_str(proto, blen, b);
2874*44704f69SBart Van Assche sgj_haj_vistr(jsp, jo2p, 4, "Protocol identifier",
2875*44704f69SBart Van Assche SGJ_SEP_COLON_1_SPACE, proto, false, b);
2876*44704f69SBart Van Assche desc_len = sg_get_unaligned_be16(bp + 6);
2877*44704f69SBart Van Assche bump = 8 + desc_len;
2878*44704f69SBart Van Assche if ((k + bump) > len) {
2879*44704f69SBart Van Assche pr2serr("VPD page, short descriptor length=%d, left=%d\n",
2880*44704f69SBart Van Assche bump, (len - k));
2881*44704f69SBart Van Assche sgj_js_nv_o(jsp, jap, NULL /* name */, jo2p);
2882*44704f69SBart Van Assche return;
2883*44704f69SBart Van Assche }
2884*44704f69SBart Van Assche if (0 == desc_len)
2885*44704f69SBart Van Assche goto again;
2886*44704f69SBart Van Assche if (2 == op->do_hex) {
2887*44704f69SBart Van Assche hex2stdout(bp + 8, desc_len, 1);
2888*44704f69SBart Van Assche goto again;
2889*44704f69SBart Van Assche }
2890*44704f69SBart Van Assche switch (proto) {
2891*44704f69SBart Van Assche case TPROTO_SAS: /* page added in spl3r02 */
2892*44704f69SBart Van Assche pds = !!(bp[3] & 0x1);
2893*44704f69SBart Van Assche sgj_pr_hr(jsp, " power disable supported (pwr_d_s)=%d\n", pds);
2894*44704f69SBart Van Assche sgj_js_nv_ihex_nex(jsp, jo2p, "pwr_d_s", pds, false,
2895*44704f69SBart Van Assche "PoWeR Disable Supported");
2896*44704f69SBart Van Assche ja2p = sgj_named_subarray_r(jsp, jo2p,
2897*44704f69SBart Van Assche "sas_phy_information_descriptor_list");
2898*44704f69SBart Van Assche pidp = bp + 8;
2899*44704f69SBart Van Assche for (j = 0; j < desc_len; j += 4, pidp += 4) {
2900*44704f69SBart Van Assche jo3p = sgj_new_unattached_object_r(jsp);
2901*44704f69SBart Van Assche phy = pidp[1];
2902*44704f69SBart Van Assche ssp_pers = !!(0x1 & pidp[2]);
2903*44704f69SBart Van Assche sgj_pr_hr(jsp, " phy id=%d, SSP persistent capable=%d\n",
2904*44704f69SBart Van Assche phy, ssp_pers);
2905*44704f69SBart Van Assche sgj_js_nv_ihex(jsp, jo3p, "phy_identifier", phy);
2906*44704f69SBart Van Assche sgj_js_nv_i(jsp, jo3p, "ssp_persistent_capable", ssp_pers);
2907*44704f69SBart Van Assche sgj_js_nv_o(jsp, ja2p, NULL /* name */, jo3p);
2908*44704f69SBart Van Assche }
2909*44704f69SBart Van Assche break;
2910*44704f69SBart Van Assche default:
2911*44704f69SBart Van Assche pr2serr("Unexpected proto=%d\n", proto);
2912*44704f69SBart Van Assche hex2stderr(bp, bump, 1);
2913*44704f69SBart Van Assche break;
2914*44704f69SBart Van Assche }
2915*44704f69SBart Van Assche again:
2916*44704f69SBart Van Assche sgj_js_nv_o(jsp, jap, NULL /* name */, jo2p);
2917*44704f69SBart Van Assche }
2918*44704f69SBart Van Assche }
2919*44704f69SBart Van Assche
2920*44704f69SBart Van Assche /* VPD_LB_PROTECTION 0xb5 (SSC) [added in ssc5r02a] */
2921*44704f69SBart Van Assche void
decode_lb_protection_vpd(const uint8_t * buff,int len,struct opts_t * op,sgj_opaque_p jap)2922*44704f69SBart Van Assche decode_lb_protection_vpd(const uint8_t * buff, int len, struct opts_t * op,
2923*44704f69SBart Van Assche sgj_opaque_p jap)
2924*44704f69SBart Van Assche {
2925*44704f69SBart Van Assche int k, bump;
2926*44704f69SBart Van Assche const uint8_t * bp;
2927*44704f69SBart Van Assche sgj_state * jsp = &op->json_st;
2928*44704f69SBart Van Assche sgj_opaque_p jo2p = NULL;
2929*44704f69SBart Van Assche
2930*44704f69SBart Van Assche if ((1 == op->do_hex) || (op->do_hex > 2)) {
2931*44704f69SBart Van Assche hex2stdout(buff, len, (1 == op->do_hex) ? 0 : -1);
2932*44704f69SBart Van Assche return;
2933*44704f69SBart Van Assche }
2934*44704f69SBart Van Assche if (len < 8) {
2935*44704f69SBart Van Assche pr2serr("VPD page length too short=%d\n", len);
2936*44704f69SBart Van Assche return;
2937*44704f69SBart Van Assche }
2938*44704f69SBart Van Assche len -= 8;
2939*44704f69SBart Van Assche bp = buff + 8;
2940*44704f69SBart Van Assche for (k = 0; k < len; k += bump, bp += bump) {
2941*44704f69SBart Van Assche jo2p = sgj_new_unattached_object_r(jsp);
2942*44704f69SBart Van Assche bump = 1 + bp[0];
2943*44704f69SBart Van Assche sgj_pr_hr(jsp, " method: %d, info_len: %d, LBP_W_C=%d, LBP_R_C=%d, "
2944*44704f69SBart Van Assche "RBDP_C=%d\n", bp[1], 0x3f & bp[2], !!(0x80 & bp[3]),
2945*44704f69SBart Van Assche !!(0x40 & bp[3]), !!(0x20 & bp[3]));
2946*44704f69SBart Van Assche sgj_js_nv_ihex(jsp, jo2p, "logical_block_protection_method", bp[1]);
2947*44704f69SBart Van Assche sgj_js_nv_ihex_nex(jsp, jo2p,
2948*44704f69SBart Van Assche "logical_block_protection_information_length",
2949*44704f69SBart Van Assche 0x3f & bp[2], true, "unit: byte");
2950*44704f69SBart Van Assche sgj_js_nv_ihex_nex(jsp, jo2p, "lbp_w_c", !!(0x80 & bp[3]), false,
2951*44704f69SBart Van Assche "Logical Blocks Protected during Write supported");
2952*44704f69SBart Van Assche sgj_js_nv_ihex_nex(jsp, jo2p, "lbp_r_c", !!(0x40 & bp[3]), false,
2953*44704f69SBart Van Assche "Logical Blocks Protected during Read supported");
2954*44704f69SBart Van Assche sgj_js_nv_ihex_nex(jsp, jo2p, "rbdp_c", !!(0x20 & bp[3]), false,
2955*44704f69SBart Van Assche "Recover Buffered Data Protected supported");
2956*44704f69SBart Van Assche if ((k + bump) > len) {
2957*44704f69SBart Van Assche pr2serr("Logical block protection VPD page, short "
2958*44704f69SBart Van Assche "descriptor length=%d, left=%d\n", bump, (len - k));
2959*44704f69SBart Van Assche sgj_js_nv_o(jsp, jap, NULL /* name */, jo2p);
2960*44704f69SBart Van Assche return;
2961*44704f69SBart Van Assche }
2962*44704f69SBart Van Assche sgj_js_nv_o(jsp, jap, NULL /* name */, jo2p);
2963*44704f69SBart Van Assche }
2964*44704f69SBart Van Assche }
2965*44704f69SBart Van Assche
2966*44704f69SBart Van Assche /* VPD_TA_SUPPORTED 0xb2 ["tas"] */
2967*44704f69SBart Van Assche void
decode_tapealert_supported_vpd(const uint8_t * buff,int len,struct opts_t * op,sgj_opaque_p jop)2968*44704f69SBart Van Assche decode_tapealert_supported_vpd(const uint8_t * buff, int len,
2969*44704f69SBart Van Assche struct opts_t * op, sgj_opaque_p jop)
2970*44704f69SBart Van Assche {
2971*44704f69SBart Van Assche bool have_ta_strs = !! sg_lib_tapealert_strs[0];
2972*44704f69SBart Van Assche int k, mod, div, n;
2973*44704f69SBart Van Assche unsigned int supp;
2974*44704f69SBart Van Assche sgj_state * jsp = &op->json_st;
2975*44704f69SBart Van Assche char b[144];
2976*44704f69SBart Van Assche char d[64];
2977*44704f69SBart Van Assche static const int blen = sizeof(b);
2978*44704f69SBart Van Assche
2979*44704f69SBart Van Assche if (len < 12) {
2980*44704f69SBart Van Assche pr2serr("VPD page length too short=%d\n", len);
2981*44704f69SBart Van Assche return;
2982*44704f69SBart Van Assche }
2983*44704f69SBart Van Assche b[0] ='\0';
2984*44704f69SBart Van Assche for (k = 1, n = 0; k < 0x41; ++k) {
2985*44704f69SBart Van Assche mod = ((k - 1) % 8);
2986*44704f69SBart Van Assche div = (k - 1) / 8;
2987*44704f69SBart Van Assche supp = !! (buff[4 + div] & (1 << (7 - mod)));
2988*44704f69SBart Van Assche if (jsp->pr_as_json) {
2989*44704f69SBart Van Assche snprintf(d, sizeof(d), "flag%02xh", k);
2990*44704f69SBart Van Assche if (have_ta_strs)
2991*44704f69SBart Van Assche sgj_js_nv_ihex_nex(jsp, jop, d, supp, false,
2992*44704f69SBart Van Assche sg_lib_tapealert_strs[k]);
2993*44704f69SBart Van Assche else
2994*44704f69SBart Van Assche sgj_js_nv_i(jsp, jop, d, supp);
2995*44704f69SBart Van Assche }
2996*44704f69SBart Van Assche if (0 == mod) {
2997*44704f69SBart Van Assche if (div > 0) {
2998*44704f69SBart Van Assche sgj_pr_hr(jsp, "%s\n", b);
2999*44704f69SBart Van Assche n = 0;
3000*44704f69SBart Van Assche }
3001*44704f69SBart Van Assche n += sg_scnpr(b + n, blen - n, " Flag%02Xh: %d", k, supp);
3002*44704f69SBart Van Assche } else
3003*44704f69SBart Van Assche n += sg_scnpr(b + n, blen - n, " %02Xh: %d", k, supp);
3004*44704f69SBart Van Assche }
3005*44704f69SBart Van Assche sgj_pr_hr(jsp, "%s\n", b);
3006*44704f69SBart Van Assche }
3007*44704f69SBart Van Assche
3008*44704f69SBart Van Assche /*
3009*44704f69SBart Van Assche * Some of the vendor specific VPD pages are common as well. So place them here
3010*44704f69SBart Van Assche * to save on code duplication.
3011*44704f69SBart Van Assche */
3012*44704f69SBart Van Assche
3013*44704f69SBart Van Assche static const char * lun_state_arr[] =
3014*44704f69SBart Van Assche {
3015*44704f69SBart Van Assche "LUN not bound or LUN_Z report",
3016*44704f69SBart Van Assche "LUN bound, but not owned by this SP",
3017*44704f69SBart Van Assche "LUN bound and owned by this SP",
3018*44704f69SBart Van Assche };
3019*44704f69SBart Van Assche
3020*44704f69SBart Van Assche static const char * ip_mgmt_arr[] =
3021*44704f69SBart Van Assche {
3022*44704f69SBart Van Assche "No IP access",
3023*44704f69SBart Van Assche "Reserved (undefined)",
3024*44704f69SBart Van Assche "via IPv4",
3025*44704f69SBart Van Assche "via IPv6",
3026*44704f69SBart Van Assche };
3027*44704f69SBart Van Assche
3028*44704f69SBart Van Assche static const char * sp_arr[] =
3029*44704f69SBart Van Assche {
3030*44704f69SBart Van Assche "SP A",
3031*44704f69SBart Van Assche "SP B",
3032*44704f69SBart Van Assche };
3033*44704f69SBart Van Assche
3034*44704f69SBart Van Assche static const char * lun_op_arr[] =
3035*44704f69SBart Van Assche {
3036*44704f69SBart Van Assche "Normal operations",
3037*44704f69SBart Van Assche "I/O Operations being rejected, SP reboot or NDU in progress",
3038*44704f69SBart Van Assche };
3039*44704f69SBart Van Assche
3040*44704f69SBart Van Assche static const char * failover_mode_arr[] =
3041*44704f69SBart Van Assche {
3042*44704f69SBart Van Assche "Legacy mode 0",
3043*44704f69SBart Van Assche "Unknown mode (1)",
3044*44704f69SBart Van Assche "Unknown mode (2)",
3045*44704f69SBart Van Assche "Unknown mode (3)",
3046*44704f69SBart Van Assche "Active/Passive (PNR) mode 1",
3047*44704f69SBart Van Assche "Unknown mode (5)",
3048*44704f69SBart Van Assche "Active/Active (ALUA) mode 4",
3049*44704f69SBart Van Assche "Unknown mode (7)",
3050*44704f69SBart Van Assche "Legacy mode 2",
3051*44704f69SBart Van Assche "Unknown mode (9)",
3052*44704f69SBart Van Assche "Unknown mode (10)",
3053*44704f69SBart Van Assche "Unknown mode (11)",
3054*44704f69SBart Van Assche "Unknown mode (12)",
3055*44704f69SBart Van Assche "Unknown mode (13)",
3056*44704f69SBart Van Assche "AIX Active/Passive (PAR) mode 3",
3057*44704f69SBart Van Assche "Unknown mode (15)",
3058*44704f69SBart Van Assche };
3059*44704f69SBart Van Assche
3060*44704f69SBart Van Assche /* VPD_UPR_EMC,VPD_V_UPR_EMC 0xc0 ["upr","upr"] */
3061*44704f69SBart Van Assche void
decode_upr_vpd_c0_emc(uint8_t * buff,int len,struct opts_t * op,sgj_opaque_p jop)3062*44704f69SBart Van Assche decode_upr_vpd_c0_emc(uint8_t * buff, int len, struct opts_t * op,
3063*44704f69SBart Van Assche sgj_opaque_p jop)
3064*44704f69SBart Van Assche {
3065*44704f69SBart Van Assche uint8_t uc;
3066*44704f69SBart Van Assche int k, n, ip_mgmt, vpp80, lun_z;
3067*44704f69SBart Van Assche sgj_state * jsp = &op->json_st;
3068*44704f69SBart Van Assche const char * cp;
3069*44704f69SBart Van Assche const char * c2p;
3070*44704f69SBart Van Assche char b[256];
3071*44704f69SBart Van Assche static const int blen = sizeof(b);
3072*44704f69SBart Van Assche
3073*44704f69SBart Van Assche if (len < 3) {
3074*44704f69SBart Van Assche pr2serr("EMC upr VPD page [0xc0]: length too short=%d\n", len);
3075*44704f69SBart Van Assche return;
3076*44704f69SBart Van Assche }
3077*44704f69SBart Van Assche if (op->do_hex) {
3078*44704f69SBart Van Assche hex2stdout(buff, len, no_ascii_4hex(op));
3079*44704f69SBart Van Assche return;
3080*44704f69SBart Van Assche }
3081*44704f69SBart Van Assche if (buff[9] != 0x00) {
3082*44704f69SBart Van Assche pr2serr("Unsupported page revision %d, decoding not possible.\n",
3083*44704f69SBart Van Assche buff[9]);
3084*44704f69SBart Van Assche return;
3085*44704f69SBart Van Assche }
3086*44704f69SBart Van Assche for (k = 0, n = 0; k < 16; ++k)
3087*44704f69SBart Van Assche n += sg_scnpr(b + n, blen - n, "%02x", buff[10 + k]);
3088*44704f69SBart Van Assche sgj_haj_vs(jsp, jop, 2, "LUN WWN", SGJ_SEP_COLON_1_SPACE, b);
3089*44704f69SBart Van Assche snprintf(b, blen, "%.*s", buff[49], buff + 50);
3090*44704f69SBart Van Assche sgj_haj_vs(jsp, jop, 2, "Array Serial Number", SGJ_SEP_COLON_1_SPACE, b);
3091*44704f69SBart Van Assche
3092*44704f69SBart Van Assche if (buff[4] > 0x02)
3093*44704f69SBart Van Assche snprintf(b, blen, "Unknown (%x)", buff[4]);
3094*44704f69SBart Van Assche else
3095*44704f69SBart Van Assche snprintf(b, blen, "%s", lun_state_arr[buff[4]]);
3096*44704f69SBart Van Assche sgj_haj_vistr(jsp, jop, 2, "LUN State", SGJ_SEP_COLON_1_SPACE,
3097*44704f69SBart Van Assche buff[4], true, b);
3098*44704f69SBart Van Assche
3099*44704f69SBart Van Assche uc = buff[8];
3100*44704f69SBart Van Assche n = 0;
3101*44704f69SBart Van Assche if (uc > 0x01)
3102*44704f69SBart Van Assche n += sg_scnpr(b + n, blen - n, "Unknown SP (%x)", uc);
3103*44704f69SBart Van Assche else
3104*44704f69SBart Van Assche n += sg_scnpr(b + n, blen - n, "%s", sp_arr[uc]);
3105*44704f69SBart Van Assche sgj_js_nv_ihexstr(jsp, jop, "path_connects_to", uc, NULL, b);
3106*44704f69SBart Van Assche n += sg_scnpr(b + n, blen - n, ", Port Number: %u", buff[7]);
3107*44704f69SBart Van Assche sgj_pr_hr(jsp, " This path connects to: %s\n", b);
3108*44704f69SBart Van Assche sgj_js_nv_ihex(jsp, jop, "port_number", buff[7]);
3109*44704f69SBart Van Assche
3110*44704f69SBart Van Assche if (buff[5] > 0x01)
3111*44704f69SBart Van Assche snprintf(b, blen, "Unknown (%x)\n", buff[5]);
3112*44704f69SBart Van Assche else
3113*44704f69SBart Van Assche snprintf(b, blen, "%s\n", sp_arr[buff[5]]);
3114*44704f69SBart Van Assche sgj_haj_vistr(jsp, jop, 2, "Default owner", SGJ_SEP_COLON_1_SPACE,
3115*44704f69SBart Van Assche buff[5], true, b);
3116*44704f69SBart Van Assche
3117*44704f69SBart Van Assche cp = (buff[6] & 0x40) ? "supported" : "not supported";
3118*44704f69SBart Van Assche sgj_pr_hr(jsp, " NO_ATF: %s, Access Logix: %s\n",
3119*44704f69SBart Van Assche buff[6] & 0x80 ? "set" : "not set", cp);
3120*44704f69SBart Van Assche sgj_js_nv_i(jsp, jop, "no_atf", !! (buff[6] & 0x80));
3121*44704f69SBart Van Assche sgj_js_nv_istr(jsp, jop, "access_logix", !! (buff[6] & 0x40),
3122*44704f69SBart Van Assche NULL, cp);
3123*44704f69SBart Van Assche
3124*44704f69SBart Van Assche ip_mgmt = (buff[6] >> 4) & 0x3;
3125*44704f69SBart Van Assche cp = ip_mgmt_arr[ip_mgmt];
3126*44704f69SBart Van Assche sgj_pr_hr(jsp, " SP IP Management Mode: %s\n", cp);
3127*44704f69SBart Van Assche sgj_js_nv_istr(jsp, jop, "sp_ip_management_mode", !! ip_mgmt,
3128*44704f69SBart Van Assche NULL, cp);
3129*44704f69SBart Van Assche if (ip_mgmt == 2) {
3130*44704f69SBart Van Assche snprintf(b, blen, "%u.%u.%u.%u", buff[44], buff[45], buff[46],
3131*44704f69SBart Van Assche buff[47]);
3132*44704f69SBart Van Assche sgj_pr_hr(jsp, " SP IPv4 address: %s\n", b);
3133*44704f69SBart Van Assche sgj_js_nv_s(jsp, jop, "sp_ipv4_address", b);
3134*44704f69SBart Van Assche } else if (ip_mgmt == 3) {
3135*44704f69SBart Van Assche printf(" SP IPv6 address: ");
3136*44704f69SBart Van Assche n = 0;
3137*44704f69SBart Van Assche for (k = 0; k < 16; ++k)
3138*44704f69SBart Van Assche n += sg_scnpr(b + n, blen - n, "%02x", buff[32 + k]);
3139*44704f69SBart Van Assche sgj_pr_hr(jsp, " SP IPv6 address: %s\n", b);
3140*44704f69SBart Van Assche sgj_js_nv_hex_bytes(jsp, jop, "sp_ipv6_address", buff + 32, 16);
3141*44704f69SBart Van Assche }
3142*44704f69SBart Van Assche
3143*44704f69SBart Van Assche k = buff[28] & 0x0f;
3144*44704f69SBart Van Assche sgj_pr_hr(jsp, " System Type: %x, Failover mode: %s\n",
3145*44704f69SBart Van Assche buff[27], failover_mode_arr[k]);
3146*44704f69SBart Van Assche sgj_js_nv_ihex(jsp, jop, "system_type", buff[27]);
3147*44704f69SBart Van Assche sgj_js_nv_ihexstr(jsp, jop, "failover_mode", k, NULL,
3148*44704f69SBart Van Assche failover_mode_arr[k]);
3149*44704f69SBart Van Assche
3150*44704f69SBart Van Assche vpp80 = buff[30] & 0x08;
3151*44704f69SBart Van Assche lun_z = buff[30] & 0x04;
3152*44704f69SBart Van Assche cp = vpp80 ? "array serial#" : "LUN serial#";
3153*44704f69SBart Van Assche c2p = lun_z ? "Set to 1" : "Unknown";
3154*44704f69SBart Van Assche sgj_pr_hr(jsp, " Inquiry VPP 0x80 returns: %s, Arraycommpath: %s\n",
3155*44704f69SBart Van Assche cp, c2p);
3156*44704f69SBart Van Assche sgj_js_nv_istr(jsp, jop, "inquiry_vpp_0x80_returns", !! vpp80, NULL, cp);
3157*44704f69SBart Van Assche sgj_js_nv_istr(jsp, jop, "arraycommpath", !! lun_z, NULL, c2p);
3158*44704f69SBart Van Assche
3159*44704f69SBart Van Assche cp = buff[48] > 1 ? "undefined" : lun_op_arr[buff[48]];
3160*44704f69SBart Van Assche sgj_pr_hr(jsp, " Lun operations: %s\n", cp);
3161*44704f69SBart Van Assche sgj_js_nv_istr(jsp, jop, "lun_operations", 0x1 & buff[48], NULL, cp);
3162*44704f69SBart Van Assche
3163*44704f69SBart Van Assche return;
3164*44704f69SBart Van Assche }
3165*44704f69SBart Van Assche
3166*44704f69SBart Van Assche /* VPD_RDAC_VERS,VPD_V_SVER_RDAC 0xc2 ["rdac_vers", "swr4"] */
3167*44704f69SBart Van Assche void
decode_rdac_vpd_c2(uint8_t * buff,int len,struct opts_t * op,sgj_opaque_p jop)3168*44704f69SBart Van Assche decode_rdac_vpd_c2(uint8_t * buff, int len, struct opts_t * op,
3169*44704f69SBart Van Assche sgj_opaque_p jop)
3170*44704f69SBart Van Assche {
3171*44704f69SBart Van Assche int i, n, v, r, m, p, d, y, num_part;
3172*44704f69SBart Van Assche sgj_state * jsp = &op->json_st;
3173*44704f69SBart Van Assche sgj_opaque_p jo2p = NULL;
3174*44704f69SBart Van Assche sgj_opaque_p jap = NULL;
3175*44704f69SBart Van Assche // const char * cp;
3176*44704f69SBart Van Assche // const char * c2p;
3177*44704f69SBart Van Assche char b[256];
3178*44704f69SBart Van Assche static const int blen = sizeof(b);
3179*44704f69SBart Van Assche char part[5];
3180*44704f69SBart Van Assche
3181*44704f69SBart Van Assche if (len < 3) {
3182*44704f69SBart Van Assche pr2serr("Software Version VPD page length too short=%d\n", len);
3183*44704f69SBart Van Assche return;
3184*44704f69SBart Van Assche }
3185*44704f69SBart Van Assche if (op->do_hex) {
3186*44704f69SBart Van Assche hex2stdout(buff, len, no_ascii_4hex(op));
3187*44704f69SBart Van Assche return;
3188*44704f69SBart Van Assche }
3189*44704f69SBart Van Assche if (buff[4] != 's' && buff[5] != 'w' && buff[6] != 'r') {
3190*44704f69SBart Van Assche pr2serr("Invalid page identifier %c%c%c%c, decoding not possible.\n",
3191*44704f69SBart Van Assche buff[4], buff[5], buff[6], buff[7]);
3192*44704f69SBart Van Assche return;
3193*44704f69SBart Van Assche }
3194*44704f69SBart Van Assche snprintf(b, blen, "%02x.%02x.%02x", buff[8], buff[9], buff[10]);
3195*44704f69SBart Van Assche sgj_haj_vs(jsp, jop, 2, "Software Version", SGJ_SEP_COLON_1_SPACE, b);
3196*44704f69SBart Van Assche snprintf(b, blen, "%02d/%02d/%02d\n", buff[11], buff[12], buff[13]);
3197*44704f69SBart Van Assche sgj_haj_vs(jsp, jop, 2, "Software Date", SGJ_SEP_COLON_1_SPACE, b);
3198*44704f69SBart Van Assche n = 0;
3199*44704f69SBart Van Assche n += sg_scnpr(b + n, blen - n, " Features:");
3200*44704f69SBart Van Assche if (buff[14] & 0x01)
3201*44704f69SBart Van Assche n += sg_scnpr(b + n, blen - n, " Dual Active,");
3202*44704f69SBart Van Assche if (buff[14] & 0x02)
3203*44704f69SBart Van Assche n += sg_scnpr(b + n, blen - n, " Series 3,");
3204*44704f69SBart Van Assche if (buff[14] & 0x04)
3205*44704f69SBart Van Assche n += sg_scnpr(b + n, blen - n, " Multiple Sub-enclosures,");
3206*44704f69SBart Van Assche if (buff[14] & 0x08)
3207*44704f69SBart Van Assche n += sg_scnpr(b + n, blen - n, " DCE/DRM/DSS/DVE,");
3208*44704f69SBart Van Assche if (buff[14] & 0x10)
3209*44704f69SBart Van Assche n += sg_scnpr(b + n, blen - n, " Asymmetric Logical Unit Access,");
3210*44704f69SBart Van Assche sgj_pr_hr(jsp, "%s\n", b);
3211*44704f69SBart Van Assche if (jsp->pr_as_json) {
3212*44704f69SBart Van Assche jo2p = sgj_snake_named_subobject_r(jsp, jop, "features");
3213*44704f69SBart Van Assche sgj_js_nv_i(jsp, jo2p, "dual_active", !! (buff[14] & 0x01));
3214*44704f69SBart Van Assche sgj_js_nv_i(jsp, jo2p, "series_3", !! (buff[14] & 0x02));
3215*44704f69SBart Van Assche sgj_js_nv_i(jsp, jo2p, "multiple_sub_enclosures",
3216*44704f69SBart Van Assche !! (buff[14] & 0x04));
3217*44704f69SBart Van Assche sgj_js_nv_i(jsp, jo2p, "dcm_drm_dss_dve", !! (buff[14] & 0x08));
3218*44704f69SBart Van Assche sgj_js_nv_i(jsp, jo2p, "asymmetric_logical_unit_access",
3219*44704f69SBart Van Assche !! (buff[14] & 0x10));
3220*44704f69SBart Van Assche }
3221*44704f69SBart Van Assche sgj_haj_vi(jsp, jop, 2, "Maximum number of LUNS",
3222*44704f69SBart Van Assche SGJ_SEP_COLON_1_SPACE, buff[15], true);
3223*44704f69SBart Van Assche
3224*44704f69SBart Van Assche num_part = (len - 12) / 16;
3225*44704f69SBart Van Assche n = 16;
3226*44704f69SBart Van Assche printf(" Partitions: %d\n", num_part);
3227*44704f69SBart Van Assche sgj_haj_vi(jsp, jop, 2, "Partitions", SGJ_SEP_COLON_1_SPACE, num_part,
3228*44704f69SBart Van Assche true);
3229*44704f69SBart Van Assche if (num_part > 0)
3230*44704f69SBart Van Assche jap = sgj_named_subarray_r(jsp, jop, "partition_list");
3231*44704f69SBart Van Assche for (i = 0; i < num_part; i++) {
3232*44704f69SBart Van Assche memset(part,0, 5);
3233*44704f69SBart Van Assche memcpy(part, &buff[n], 4);
3234*44704f69SBart Van Assche sgj_pr_hr(jsp, " Name: %s\n", part);
3235*44704f69SBart Van Assche if (jsp->pr_as_json) {
3236*44704f69SBart Van Assche jo2p = sgj_new_unattached_object_r(jsp);
3237*44704f69SBart Van Assche sgj_js_nv_s(jsp, jo2p, "name", part);
3238*44704f69SBart Van Assche }
3239*44704f69SBart Van Assche n += 4;
3240*44704f69SBart Van Assche v = buff[n++];
3241*44704f69SBart Van Assche r = buff[n++];
3242*44704f69SBart Van Assche m = buff[n++];
3243*44704f69SBart Van Assche p = buff[n++];
3244*44704f69SBart Van Assche snprintf(b, blen, "%d.%d.%d.%d", v, r, m, p);
3245*44704f69SBart Van Assche sgj_pr_hr(jsp, " Version: %s\n", b);
3246*44704f69SBart Van Assche if (jsp->pr_as_json)
3247*44704f69SBart Van Assche sgj_js_nv_s(jsp, jo2p, "version", b);
3248*44704f69SBart Van Assche m = buff[n++];
3249*44704f69SBart Van Assche d = buff[n++];
3250*44704f69SBart Van Assche y = buff[n++];
3251*44704f69SBart Van Assche snprintf(b, blen, "%d/%d/%d\n", m, d, y);
3252*44704f69SBart Van Assche sgj_pr_hr(jsp, " Date: %s\n", b);
3253*44704f69SBart Van Assche if (jsp->pr_as_json) {
3254*44704f69SBart Van Assche sgj_js_nv_s(jsp, jo2p, "date", b);
3255*44704f69SBart Van Assche sgj_js_nv_o(jsp, jap, NULL /* name */, jo2p);
3256*44704f69SBart Van Assche }
3257*44704f69SBart Van Assche
3258*44704f69SBart Van Assche n += 5;
3259*44704f69SBart Van Assche }
3260*44704f69SBart Van Assche return;
3261*44704f69SBart Van Assche }
3262*44704f69SBart Van Assche
3263*44704f69SBart Van Assche static char *
decode_rdac_vpd_c9_aas_s(uint8_t aas,char * b,int blen)3264*44704f69SBart Van Assche decode_rdac_vpd_c9_aas_s(uint8_t aas, char * b, int blen)
3265*44704f69SBart Van Assche {
3266*44704f69SBart Van Assche // snprintf(" Asymmetric Access State:");
3267*44704f69SBart Van Assche switch(aas & 0x0F) {
3268*44704f69SBart Van Assche case 0x0:
3269*44704f69SBart Van Assche snprintf(b, blen, "Active/Optimized");
3270*44704f69SBart Van Assche break;
3271*44704f69SBart Van Assche case 0x1:
3272*44704f69SBart Van Assche snprintf(b, blen, "Active/Non-Optimized");
3273*44704f69SBart Van Assche break;
3274*44704f69SBart Van Assche case 0x2:
3275*44704f69SBart Van Assche snprintf(b, blen, "Standby");
3276*44704f69SBart Van Assche break;
3277*44704f69SBart Van Assche case 0x3:
3278*44704f69SBart Van Assche snprintf(b, blen, "Unavailable");
3279*44704f69SBart Van Assche break;
3280*44704f69SBart Van Assche case 0xE:
3281*44704f69SBart Van Assche snprintf(b, blen, "Offline");
3282*44704f69SBart Van Assche break;
3283*44704f69SBart Van Assche case 0xF:
3284*44704f69SBart Van Assche snprintf(b, blen, "Transitioning");
3285*44704f69SBart Van Assche break;
3286*44704f69SBart Van Assche default:
3287*44704f69SBart Van Assche snprintf(b, blen, "(unknown)");
3288*44704f69SBart Van Assche break;
3289*44704f69SBart Van Assche }
3290*44704f69SBart Van Assche return b;
3291*44704f69SBart Van Assche }
3292*44704f69SBart Van Assche
3293*44704f69SBart Van Assche static char *
decode_rdac_vpd_c9_vs_s(uint8_t vendor,char * b,int blen)3294*44704f69SBart Van Assche decode_rdac_vpd_c9_vs_s(uint8_t vendor, char * b, int blen)
3295*44704f69SBart Van Assche {
3296*44704f69SBart Van Assche // printf(" Vendor Specific Field:");
3297*44704f69SBart Van Assche switch(vendor) {
3298*44704f69SBart Van Assche case 0x01:
3299*44704f69SBart Van Assche snprintf(b, blen, "Operating normally");
3300*44704f69SBart Van Assche break;
3301*44704f69SBart Van Assche case 0x02:
3302*44704f69SBart Van Assche snprintf(b, blen, "Non-responsive to queries");
3303*44704f69SBart Van Assche break;
3304*44704f69SBart Van Assche case 0x03:
3305*44704f69SBart Van Assche snprintf(b, blen, "Controller being held in reset");
3306*44704f69SBart Van Assche break;
3307*44704f69SBart Van Assche case 0x04:
3308*44704f69SBart Van Assche snprintf(b, blen, "Performing controller firmware download (1st "
3309*44704f69SBart Van Assche "controller)");
3310*44704f69SBart Van Assche break;
3311*44704f69SBart Van Assche case 0x05:
3312*44704f69SBart Van Assche snprintf(b, blen, "Performing controller firmware download (2nd "
3313*44704f69SBart Van Assche "controller)");
3314*44704f69SBart Van Assche break;
3315*44704f69SBart Van Assche case 0x06:
3316*44704f69SBart Van Assche snprintf(b, blen,
3317*44704f69SBart Van Assche "Quiesced as a result of an administrative request");
3318*44704f69SBart Van Assche break;
3319*44704f69SBart Van Assche case 0x07:
3320*44704f69SBart Van Assche snprintf(b, blen,
3321*44704f69SBart Van Assche "Service mode as a result of an administrative request");
3322*44704f69SBart Van Assche break;
3323*44704f69SBart Van Assche case 0xFF:
3324*44704f69SBart Van Assche snprintf(b, blen, "Details are not available");
3325*44704f69SBart Van Assche break;
3326*44704f69SBart Van Assche default:
3327*44704f69SBart Van Assche snprintf(b, blen, "(unknown)");
3328*44704f69SBart Van Assche break;
3329*44704f69SBart Van Assche }
3330*44704f69SBart Van Assche return b;
3331*44704f69SBart Van Assche }
3332*44704f69SBart Van Assche
3333*44704f69SBart Van Assche /* VPD_RDAC_VAC,VPD_V_VAC_RDAC 0xc9 ["rdac_vac", "vac1"] */
3334*44704f69SBart Van Assche void
decode_rdac_vpd_c9(uint8_t * buff,int len,struct opts_t * op,sgj_opaque_p jop)3335*44704f69SBart Van Assche decode_rdac_vpd_c9(uint8_t * buff, int len, struct opts_t * op,
3336*44704f69SBart Van Assche sgj_opaque_p jop)
3337*44704f69SBart Van Assche {
3338*44704f69SBart Van Assche bool vav;
3339*44704f69SBart Van Assche int n, n_hold;
3340*44704f69SBart Van Assche sgj_state * jsp = &op->json_st;
3341*44704f69SBart Van Assche char b[196];
3342*44704f69SBart Van Assche static const int blen = sizeof(b);
3343*44704f69SBart Van Assche
3344*44704f69SBart Van Assche if (len < 3) {
3345*44704f69SBart Van Assche pr2serr("Volume Access Control VPD page length too short=%d\n", len);
3346*44704f69SBart Van Assche return;
3347*44704f69SBart Van Assche }
3348*44704f69SBart Van Assche if (op->do_hex) {
3349*44704f69SBart Van Assche hex2stdout(buff, len, no_ascii_4hex(op));
3350*44704f69SBart Van Assche return;
3351*44704f69SBart Van Assche }
3352*44704f69SBart Van Assche if (buff[4] != 'v' && buff[5] != 'a' && buff[6] != 'c') {
3353*44704f69SBart Van Assche pr2serr("Invalid page identifier %c%c%c%c, decoding "
3354*44704f69SBart Van Assche "not possible.\n" , buff[4], buff[5], buff[6], buff[7]);
3355*44704f69SBart Van Assche return;
3356*44704f69SBart Van Assche }
3357*44704f69SBart Van Assche if (buff[7] != '1') {
3358*44704f69SBart Van Assche pr2serr("Invalid page version '%c' (should be 1)\n", buff[7]);
3359*44704f69SBart Van Assche }
3360*44704f69SBart Van Assche n = ((buff[8] & 0xE0) == 0xE0 );
3361*44704f69SBart Van Assche if (n) {
3362*44704f69SBart Van Assche sgj_pr_hr(jsp, " IOShipping (ALUA): Enabled\n");
3363*44704f69SBart Van Assche sgj_js_nv_ihexstr_nex(jsp, jop, "ioshipping", n, true, NULL,
3364*44704f69SBart Van Assche "Enabled",
3365*44704f69SBart Van Assche "a.k.a. ALUA (Asymmetric Logical Unit Access)");
3366*44704f69SBart Van Assche } else {
3367*44704f69SBart Van Assche n = 0;
3368*44704f69SBart Van Assche n = snprintf(b, blen, " AVT:");
3369*44704f69SBart Van Assche n_hold = n;
3370*44704f69SBart Van Assche if (buff[8] & 0x80) {
3371*44704f69SBart Van Assche n += sg_scnpr(b + n, blen - n, " Enabled");
3372*44704f69SBart Van Assche if (buff[8] & 0x40)
3373*44704f69SBart Van Assche n += sg_scnpr(b + n, blen - n, " (Allow reads on sector 0)");
3374*44704f69SBart Van Assche sgj_pr_hr(jsp, "%s\n", b);
3375*44704f69SBart Van Assche sgj_js_nv_ihexstr(jsp, jop, "avt", buff[8], NULL, b + n_hold);
3376*44704f69SBart Van Assche
3377*44704f69SBart Van Assche } else {
3378*44704f69SBart Van Assche sgj_pr_hr(jsp, "%s: Disabled\n", b);
3379*44704f69SBart Van Assche sgj_js_nv_ihexstr(jsp, jop, "avt", buff[8], NULL, "Disabled");
3380*44704f69SBart Van Assche }
3381*44704f69SBart Van Assche }
3382*44704f69SBart Van Assche vav = !! (0x1 & buff[8]);
3383*44704f69SBart Van Assche sgj_haj_vistr(jsp, jop, 2, "Volume access via", SGJ_SEP_COLON_1_SPACE,
3384*44704f69SBart Van Assche (int)vav, false,
3385*44704f69SBart Van Assche (vav ? "primary controller" : "alternate controller"));
3386*44704f69SBart Van Assche
3387*44704f69SBart Van Assche if (buff[8] & 0x08) {
3388*44704f69SBart Van Assche n = buff[15] & 0xf;
3389*44704f69SBart Van Assche // printf(" Path priority: %d ", n);
3390*44704f69SBart Van Assche switch (n) {
3391*44704f69SBart Van Assche case 0x1:
3392*44704f69SBart Van Assche snprintf(b, blen, "(preferred path)");
3393*44704f69SBart Van Assche break;
3394*44704f69SBart Van Assche case 0x2:
3395*44704f69SBart Van Assche snprintf(b, blen, "(secondary path)");
3396*44704f69SBart Van Assche break;
3397*44704f69SBart Van Assche default:
3398*44704f69SBart Van Assche snprintf(b, blen, "(unknown)");
3399*44704f69SBart Van Assche break;
3400*44704f69SBart Van Assche }
3401*44704f69SBart Van Assche sgj_haj_vistr(jsp, jop, 2, "Path priority", SGJ_SEP_COLON_1_SPACE, n,
3402*44704f69SBart Van Assche true, b);
3403*44704f69SBart Van Assche
3404*44704f69SBart Van Assche // printf(" Preferred Path Auto Changeable:");
3405*44704f69SBart Van Assche n = buff[14] & 0x3C;
3406*44704f69SBart Van Assche switch (n) {
3407*44704f69SBart Van Assche case 0x14:
3408*44704f69SBart Van Assche snprintf(b, blen, "No (User Disabled and Host Type Restricted)");
3409*44704f69SBart Van Assche break;
3410*44704f69SBart Van Assche case 0x18:
3411*44704f69SBart Van Assche snprintf(b, blen, "No (User Disabled)");
3412*44704f69SBart Van Assche break;
3413*44704f69SBart Van Assche case 0x24:
3414*44704f69SBart Van Assche snprintf(b, blen, "No (Host Type Restricted)");
3415*44704f69SBart Van Assche break;
3416*44704f69SBart Van Assche case 0x28:
3417*44704f69SBart Van Assche snprintf(b, blen, "Yes");
3418*44704f69SBart Van Assche break;
3419*44704f69SBart Van Assche default:
3420*44704f69SBart Van Assche snprintf(b, blen, "(Unknown)");
3421*44704f69SBart Van Assche break;
3422*44704f69SBart Van Assche }
3423*44704f69SBart Van Assche sgj_haj_vistr(jsp, jop, 2, "Preferred path auto changeable",
3424*44704f69SBart Van Assche SGJ_SEP_COLON_1_SPACE, n, true, b);
3425*44704f69SBart Van Assche
3426*44704f69SBart Van Assche n = buff[14] & 0x03;
3427*44704f69SBart Van Assche // printf(" Implicit Failback:");
3428*44704f69SBart Van Assche switch (n) {
3429*44704f69SBart Van Assche case 0x1:
3430*44704f69SBart Van Assche snprintf(b, blen, "Disabled");
3431*44704f69SBart Van Assche break;
3432*44704f69SBart Van Assche case 0x2:
3433*44704f69SBart Van Assche snprintf(b, blen, "Enabled");
3434*44704f69SBart Van Assche break;
3435*44704f69SBart Van Assche default:
3436*44704f69SBart Van Assche snprintf(b, blen, "(Unknown)");
3437*44704f69SBart Van Assche break;
3438*44704f69SBart Van Assche }
3439*44704f69SBart Van Assche sgj_haj_vistr(jsp, jop, 2, "Implicit failback",
3440*44704f69SBart Van Assche SGJ_SEP_COLON_1_SPACE, n, false, b);
3441*44704f69SBart Van Assche } else {
3442*44704f69SBart Van Assche n = buff[9] & 0xf;
3443*44704f69SBart Van Assche // printf(" Path priority: %d ", buff[9] & 0xf);
3444*44704f69SBart Van Assche switch (n) {
3445*44704f69SBart Van Assche case 0x1:
3446*44704f69SBart Van Assche snprintf(b, blen, "(preferred path)");
3447*44704f69SBart Van Assche break;
3448*44704f69SBart Van Assche case 0x2:
3449*44704f69SBart Van Assche snprintf(b, blen, "(secondary path)");
3450*44704f69SBart Van Assche break;
3451*44704f69SBart Van Assche default:
3452*44704f69SBart Van Assche snprintf(b, blen, "(unknown)");
3453*44704f69SBart Van Assche break;
3454*44704f69SBart Van Assche }
3455*44704f69SBart Van Assche sgj_haj_vistr(jsp, jop, 2, "Path priority",
3456*44704f69SBart Van Assche SGJ_SEP_COLON_1_SPACE, n, false, b);
3457*44704f69SBart Van Assche }
3458*44704f69SBart Van Assche
3459*44704f69SBart Van Assche n = !! (buff[8] & 0x80);
3460*44704f69SBart Van Assche sgj_haj_vi(jsp, jop, 2, "Target port group present",
3461*44704f69SBart Van Assche SGJ_SEP_COLON_1_SPACE, n, false);
3462*44704f69SBart Van Assche if (n) {
3463*44704f69SBart Van Assche sgj_opaque_p jo2p = NULL;
3464*44704f69SBart Van Assche sgj_opaque_p jo3p = NULL;
3465*44704f69SBart Van Assche static const char * tpg_s = "Target port group data";
3466*44704f69SBart Van Assche static const char * aas_s = "Asymmetric access state";
3467*44704f69SBart Van Assche static const char * vsf_s = "Vendor specific field";
3468*44704f69SBart Van Assche char d1[80];
3469*44704f69SBart Van Assche char d2[80];
3470*44704f69SBart Van Assche
3471*44704f69SBart Van Assche sgj_pr_hr(jsp, " Target Port Group Data (This controller):\n");
3472*44704f69SBart Van Assche decode_rdac_vpd_c9_aas_s(buff[10], d1, sizeof(d1));
3473*44704f69SBart Van Assche decode_rdac_vpd_c9_vs_s(buff[11], d2, sizeof(d2));
3474*44704f69SBart Van Assche sgj_pr_hr(jsp, " %s: %s\n", aas_s, d1);
3475*44704f69SBart Van Assche sgj_pr_hr(jsp, " %s: %s\n", vsf_s, d2);
3476*44704f69SBart Van Assche if (jsp->pr_as_json) {
3477*44704f69SBart Van Assche jo2p = sgj_snake_named_subobject_r(jsp, jop, tpg_s);
3478*44704f69SBart Van Assche jo3p = sgj_snake_named_subobject_r(jsp, jo2p, "this_controller");
3479*44704f69SBart Van Assche sgj_convert_to_snake_name(aas_s, b, blen);
3480*44704f69SBart Van Assche sgj_js_nv_ihexstr(jsp, jo3p, b, buff[10], NULL, d1);
3481*44704f69SBart Van Assche sgj_convert_to_snake_name(vsf_s, b, blen);
3482*44704f69SBart Van Assche sgj_js_nv_ihexstr(jsp, jo3p, b, buff[11], NULL, d2);
3483*44704f69SBart Van Assche }
3484*44704f69SBart Van Assche sgj_pr_hr(jsp, " Target Port Group Data (Alternate controller):\n");
3485*44704f69SBart Van Assche // decode_rdac_vpd_c9_rtpg_data(buff[12], buff[13]);
3486*44704f69SBart Van Assche
3487*44704f69SBart Van Assche decode_rdac_vpd_c9_aas_s(buff[12], d1, sizeof(d1));
3488*44704f69SBart Van Assche decode_rdac_vpd_c9_vs_s(buff[13], d2, sizeof(d2));
3489*44704f69SBart Van Assche sgj_pr_hr(jsp, " %s: %s\n", aas_s, d1);
3490*44704f69SBart Van Assche sgj_pr_hr(jsp, " %s: %s\n", vsf_s, d2);
3491*44704f69SBart Van Assche if (jsp->pr_as_json) {
3492*44704f69SBart Van Assche jo2p = sgj_snake_named_subobject_r(jsp, jop, tpg_s);
3493*44704f69SBart Van Assche jo3p = sgj_snake_named_subobject_r(jsp, jo2p,
3494*44704f69SBart Van Assche "alternate_controller");
3495*44704f69SBart Van Assche sgj_convert_to_snake_name(aas_s, b, blen);
3496*44704f69SBart Van Assche sgj_js_nv_ihexstr(jsp, jo3p, b, buff[12], NULL, d1);
3497*44704f69SBart Van Assche sgj_convert_to_snake_name(vsf_s, b, blen);
3498*44704f69SBart Van Assche sgj_js_nv_ihexstr(jsp, jo3p, b, buff[13], NULL, d2);
3499*44704f69SBart Van Assche }
3500*44704f69SBart Van Assche }
3501*44704f69SBart Van Assche }
3502