1*44704f69SBart Van Assche /* A utility program originally written for the Linux OS SCSI subsystem.
2*44704f69SBart Van Assche * Copyright (C) 2000-2022 D. Gilbert
3*44704f69SBart Van Assche * This program is free software; you can redistribute it and/or modify
4*44704f69SBart Van Assche * it under the terms of the GNU General Public License as published by
5*44704f69SBart Van Assche * the Free Software Foundation; either version 2, or (at your option)
6*44704f69SBart Van Assche * any later version.
7*44704f69SBart Van Assche *
8*44704f69SBart Van Assche * SPDX-License-Identifier: GPL-2.0-or-later
9*44704f69SBart Van Assche *
10*44704f69SBart Van Assche * This program outputs information provided by a SCSI LOG SENSE command
11*44704f69SBart Van Assche * and in some cases issues a LOG SELECT command.
12*44704f69SBart Van Assche *
13*44704f69SBart Van Assche */
14*44704f69SBart Van Assche
15*44704f69SBart Van Assche #include <unistd.h>
16*44704f69SBart Van Assche #include <fcntl.h>
17*44704f69SBart Van Assche #include <stdio.h>
18*44704f69SBart Van Assche #include <stdlib.h>
19*44704f69SBart Van Assche #include <stdarg.h>
20*44704f69SBart Van Assche #include <stdbool.h>
21*44704f69SBart Van Assche #include <string.h>
22*44704f69SBart Van Assche #include <ctype.h>
23*44704f69SBart Van Assche #include <getopt.h>
24*44704f69SBart Van Assche #define __STDC_FORMAT_MACROS 1
25*44704f69SBart Van Assche #include <inttypes.h>
26*44704f69SBart Van Assche #include <errno.h>
27*44704f69SBart Van Assche
28*44704f69SBart Van Assche #ifdef HAVE_CONFIG_H
29*44704f69SBart Van Assche #include "config.h"
30*44704f69SBart Van Assche #endif
31*44704f69SBart Van Assche #include "sg_lib.h"
32*44704f69SBart Van Assche #include "sg_lib_names.h"
33*44704f69SBart Van Assche #include "sg_cmds_basic.h"
34*44704f69SBart Van Assche #ifdef SG_LIB_WIN32
35*44704f69SBart Van Assche #include "sg_pt.h" /* needed for scsi_pt_win32_direct() */
36*44704f69SBart Van Assche #endif
37*44704f69SBart Van Assche #include "sg_unaligned.h"
38*44704f69SBart Van Assche #include "sg_pr2serr.h"
39*44704f69SBart Van Assche
40*44704f69SBart Van Assche static const char * version_str = "2.08 20221112"; /* spc6r06 + sbc5r03 */
41*44704f69SBart Van Assche
42*44704f69SBart Van Assche #define MY_NAME "sg_logs"
43*44704f69SBart Van Assche
44*44704f69SBart Van Assche #define MX_ALLOC_LEN (0xfffc)
45*44704f69SBart Van Assche #define MX_INLEN_ALLOC_LEN (0x800000)
46*44704f69SBart Van Assche #define DEF_INLEN_ALLOC_LEN (0x40000)
47*44704f69SBart Van Assche #define SHORT_RESP_LEN 128
48*44704f69SBart Van Assche
49*44704f69SBart Van Assche #define SUPP_PAGES_LPAGE 0x0
50*44704f69SBart Van Assche #define BUFF_OVER_UNDER_LPAGE 0x1
51*44704f69SBart Van Assche #define WRITE_ERR_LPAGE 0x2
52*44704f69SBart Van Assche #define READ_ERR_LPAGE 0x3
53*44704f69SBart Van Assche #define READ_REV_ERR_LPAGE 0x4
54*44704f69SBart Van Assche #define VERIFY_ERR_LPAGE 0x5
55*44704f69SBart Van Assche #define NON_MEDIUM_LPAGE 0x6
56*44704f69SBart Van Assche #define LAST_N_ERR_LPAGE 0x7
57*44704f69SBart Van Assche #define FORMAT_STATUS_LPAGE 0x8
58*44704f69SBart Van Assche #define LAST_N_DEFERRED_LPAGE 0xb
59*44704f69SBart Van Assche #define LB_PROV_LPAGE 0xc
60*44704f69SBart Van Assche #define TEMPERATURE_LPAGE 0xd
61*44704f69SBart Van Assche #define START_STOP_LPAGE 0xe
62*44704f69SBart Van Assche #define APP_CLIENT_LPAGE 0xf
63*44704f69SBart Van Assche #define SELF_TEST_LPAGE 0x10
64*44704f69SBart Van Assche #define SOLID_STATE_MEDIA_LPAGE 0x11
65*44704f69SBart Van Assche #define REQ_RECOVERY_LPAGE 0x13
66*44704f69SBart Van Assche #define DEVICE_STATS_LPAGE 0x14
67*44704f69SBart Van Assche #define BACKGROUND_SCAN_LPAGE 0x15
68*44704f69SBart Van Assche #define SAT_ATA_RESULTS_LPAGE 0x16
69*44704f69SBart Van Assche #define PROTO_SPECIFIC_LPAGE 0x18
70*44704f69SBart Van Assche #define STATS_LPAGE 0x19
71*44704f69SBart Van Assche #define PCT_LPAGE 0x1a
72*44704f69SBart Van Assche #define TAPE_ALERT_LPAGE 0x2e
73*44704f69SBart Van Assche #define IE_LPAGE 0x2f
74*44704f69SBart Van Assche #define NOT_SPG_SUBPG 0x0 /* any page: no subpages */
75*44704f69SBart Van Assche #define SUPP_SPGS_SUBPG 0xff /* all subpages of ... */
76*44704f69SBart Van Assche #define PENDING_DEFECTS_SUBPG 0x1 /* page 0x15 */
77*44704f69SBart Van Assche #define BACKGROUND_OP_SUBPG 0x2 /* page 0x15 */
78*44704f69SBart Van Assche #define CACHE_STATS_SUBPG 0x20 /* page 0x19 */
79*44704f69SBart Van Assche #define CMD_DUR_LIMITS_SUBPG 0x21 /* page 0x19 */
80*44704f69SBart Van Assche #define ENV_REPORTING_SUBPG 0x1 /* page 0xd */
81*44704f69SBart Van Assche #define UTILIZATION_SUBPG 0x1 /* page 0xe */
82*44704f69SBart Van Assche #define ENV_LIMITS_SUBPG 0x2 /* page 0xd */
83*44704f69SBart Van Assche #define LPS_MISALIGNMENT_SUBPG 0x3 /* page 0x15 */
84*44704f69SBart Van Assche #define ZONED_BLOCK_DEV_STATS_SUBPG 0x1 /* page 0x14 */
85*44704f69SBart Van Assche #define LAST_N_INQUIRY_DATA_CH_SUBPG 0x1 /* page 0xb */
86*44704f69SBart Van Assche #define LAST_N_MODE_PG_DATA_CH_SUBPG 0x2 /* page 0xb */
87*44704f69SBart Van Assche
88*44704f69SBart Van Assche /* Vendor product numbers/identifiers */
89*44704f69SBart Van Assche #define VP_NONE (-1)
90*44704f69SBart Van Assche #define VP_SEAG 0
91*44704f69SBart Van Assche #define VP_HITA 1
92*44704f69SBart Van Assche #define VP_TOSH 2
93*44704f69SBart Van Assche #define VP_LTO5 3
94*44704f69SBart Van Assche #define VP_LTO6 4
95*44704f69SBart Van Assche #define VP_ALL 99
96*44704f69SBart Van Assche
97*44704f69SBart Van Assche #define MVP_OFFSET 8
98*44704f69SBart Van Assche
99*44704f69SBart Van Assche /* Vendor product masks
100*44704f69SBart Van Assche * MVP_STD OR-ed with MVP_<vendor> is a T10 defined lpage with vendor
101*44704f69SBart Van Assche * specific parameter codes (e.g. Information Exceptions lpage [0x2f]) */
102*44704f69SBart Van Assche #define MVP_STD (1 << (MVP_OFFSET - 1))
103*44704f69SBart Van Assche #define MVP_SEAG (1 << (VP_SEAG + MVP_OFFSET))
104*44704f69SBart Van Assche #define MVP_HITA (1 << (VP_HITA + MVP_OFFSET))
105*44704f69SBart Van Assche #define MVP_TOSH (1 << (VP_TOSH + MVP_OFFSET))
106*44704f69SBart Van Assche #define MVP_LTO5 (1 << (VP_LTO5 + MVP_OFFSET))
107*44704f69SBart Van Assche #define MVP_LTO6 (1 << (VP_LTO6 + MVP_OFFSET))
108*44704f69SBart Van Assche
109*44704f69SBart Van Assche #define OVP_LTO (MVP_LTO5 | MVP_LTO6)
110*44704f69SBart Van Assche #define OVP_ALL (~0)
111*44704f69SBart Van Assche
112*44704f69SBart Van Assche
113*44704f69SBart Van Assche #define PCB_STR_LEN 128
114*44704f69SBart Van Assche
115*44704f69SBart Van Assche #define LOG_SENSE_PROBE_ALLOC_LEN 4
116*44704f69SBart Van Assche #define LOG_SENSE_DEF_TIMEOUT 64 /* seconds */
117*44704f69SBart Van Assche
118*44704f69SBart Van Assche static uint8_t * rsp_buff;
119*44704f69SBart Van Assche static uint8_t * free_rsp_buff;
120*44704f69SBart Van Assche static int rsp_buff_sz = MX_ALLOC_LEN + 4;
121*44704f69SBart Van Assche static const int parr_sz = 4096;
122*44704f69SBart Van Assche
123*44704f69SBart Van Assche static const char * const unknown_s = "unknown";
124*44704f69SBart Van Assche static const char * const not_avail = "not available";
125*44704f69SBart Van Assche static const char * const param_c = "Parameter code";
126*44704f69SBart Van Assche static const char * const param_c_sn = "parameter_code";
127*44704f69SBart Van Assche static const char * const as_s_s = "as_string";
128*44704f69SBart Van Assche static const char * const rstrict_s = "restricted";
129*44704f69SBart Van Assche static const char * const rsv_s = "reserved";
130*44704f69SBart Van Assche static const char * const vend_spec = "vendor specific";
131*44704f69SBart Van Assche static const char * const not_rep = "not reported";
132*44704f69SBart Van Assche static const char * const in_hex = "in hex";
133*44704f69SBart Van Assche static const char * const s_key = "sense key";
134*44704f69SBart Van Assche
135*44704f69SBart Van Assche static struct option long_options[] = {
136*44704f69SBart Van Assche {"All", no_argument, 0, 'A'}, /* equivalent to '-aa' */
137*44704f69SBart Van Assche {"ALL", no_argument, 0, 'A'}, /* equivalent to '-aa' */
138*44704f69SBart Van Assche {"all", no_argument, 0, 'a'},
139*44704f69SBart Van Assche {"brief", no_argument, 0, 'b'},
140*44704f69SBart Van Assche {"control", required_argument, 0, 'c'},
141*44704f69SBart Van Assche {"enumerate", no_argument, 0, 'e'},
142*44704f69SBart Van Assche {"exclude", no_argument, 0, 'E'},
143*44704f69SBart Van Assche {"filter", required_argument, 0, 'f'},
144*44704f69SBart Van Assche {"full", no_argument, 0, 'F'},
145*44704f69SBart Van Assche {"help", no_argument, 0, 'h'},
146*44704f69SBart Van Assche {"hex", no_argument, 0, 'H'},
147*44704f69SBart Van Assche {"in", required_argument, 0, 'i'},
148*44704f69SBart Van Assche {"inhex", required_argument, 0, 'i'},
149*44704f69SBart Van Assche {"json", optional_argument, 0, 'j'},
150*44704f69SBart Van Assche {"list", no_argument, 0, 'l'},
151*44704f69SBart Van Assche {"maxlen", required_argument, 0, 'm'},
152*44704f69SBart Van Assche {"name", no_argument, 0, 'n'},
153*44704f69SBart Van Assche {"new", no_argument, 0, 'N'},
154*44704f69SBart Van Assche {"no_inq", no_argument, 0, 'x'},
155*44704f69SBart Van Assche {"no-inq", no_argument, 0, 'x'},
156*44704f69SBart Van Assche {"old", no_argument, 0, 'O'},
157*44704f69SBart Van Assche {"page", required_argument, 0, 'p'},
158*44704f69SBart Van Assche {"paramp", required_argument, 0, 'P'},
159*44704f69SBart Van Assche {"pcb", no_argument, 0, 'q'},
160*44704f69SBart Van Assche {"ppc", no_argument, 0, 'Q'},
161*44704f69SBart Van Assche {"pdt", required_argument, 0, 'D'},
162*44704f69SBart Van Assche {"raw", no_argument, 0, 'r'},
163*44704f69SBart Van Assche {"readonly", no_argument, 0, 'X'},
164*44704f69SBart Van Assche {"reset", no_argument, 0, 'R'},
165*44704f69SBart Van Assche {"sp", no_argument, 0, 's'},
166*44704f69SBart Van Assche {"select", no_argument, 0, 'S'},
167*44704f69SBart Van Assche {"temperature", no_argument, 0, 't'},
168*44704f69SBart Van Assche {"transport", no_argument, 0, 'T'},
169*44704f69SBart Van Assche {"undefined", no_argument, 0, 'u'},
170*44704f69SBart Van Assche {"vendor", required_argument, 0, 'M'},
171*44704f69SBart Van Assche {"verbose", no_argument, 0, 'v'},
172*44704f69SBart Van Assche {"version", no_argument, 0, 'V'},
173*44704f69SBart Van Assche {0, 0, 0, 0},
174*44704f69SBart Van Assche };
175*44704f69SBart Van Assche
176*44704f69SBart Van Assche struct opts_t {
177*44704f69SBart Van Assche bool do_full;
178*44704f69SBart Van Assche bool do_name;
179*44704f69SBart Van Assche bool do_pcb;
180*44704f69SBart Van Assche bool do_ppc;
181*44704f69SBart Van Assche bool do_raw;
182*44704f69SBart Van Assche bool do_pcreset;
183*44704f69SBart Van Assche bool do_select;
184*44704f69SBart Van Assche bool do_sp;
185*44704f69SBart Van Assche bool do_temperature;
186*44704f69SBart Van Assche bool do_transport;
187*44704f69SBart Van Assche bool exclude_vendor;
188*44704f69SBart Van Assche bool filter_given;
189*44704f69SBart Van Assche bool maxlen_given;
190*44704f69SBart Van Assche bool o_readonly;
191*44704f69SBart Van Assche bool opt_new;
192*44704f69SBart Van Assche bool verbose_given;
193*44704f69SBart Van Assche bool version_given;
194*44704f69SBart Van Assche int do_all;
195*44704f69SBart Van Assche int do_brief;
196*44704f69SBart Van Assche int do_enumerate;
197*44704f69SBart Van Assche int do_help;
198*44704f69SBart Van Assche int do_hex;
199*44704f69SBart Van Assche int do_list;
200*44704f69SBart Van Assche int dstrhex_no_ascii; /* value for dStrHex() no_ascii argument */
201*44704f69SBart Van Assche int hex2str_oformat; /* value for hex2str() oformat argument */
202*44704f69SBart Van Assche int vend_prod_num; /* one of the VP_* constants or -1 (def) */
203*44704f69SBart Van Assche int deduced_vpn; /* deduced vendor_prod_num; from INQUIRY, etc */
204*44704f69SBart Van Assche int verbose;
205*44704f69SBart Van Assche int filter;
206*44704f69SBart Van Assche int page_control;
207*44704f69SBart Van Assche int maxlen;
208*44704f69SBart Van Assche int pg_code;
209*44704f69SBart Van Assche int subpg_code;
210*44704f69SBart Van Assche int paramp;
211*44704f69SBart Van Assche int no_inq;
212*44704f69SBart Van Assche int dev_pdt; /* from device or --pdt=DT */
213*44704f69SBart Van Assche int decod_subpg_code;
214*44704f69SBart Van Assche int undefined_hex; /* hex format of undefined/unrecognized fields */
215*44704f69SBart Van Assche const char * device_name;
216*44704f69SBart Van Assche const char * in_fn;
217*44704f69SBart Van Assche const char * pg_arg;
218*44704f69SBart Van Assche const char * vend_prod;
219*44704f69SBart Van Assche const struct log_elem * lep;
220*44704f69SBart Van Assche sgj_state json_st;
221*44704f69SBart Van Assche };
222*44704f69SBart Van Assche
223*44704f69SBart Van Assche
224*44704f69SBart Van Assche struct log_elem {
225*44704f69SBart Van Assche int pg_code;
226*44704f69SBart Van Assche int subpg_code; /* only unless subpg_high>0 then this is only */
227*44704f69SBart Van Assche int subpg_high; /* when >0 this is high end of subpage range */
228*44704f69SBart Van Assche int pdt; /* -1 for all */
229*44704f69SBart Van Assche int flags; /* bit mask; or-ed with MVP_* constants */
230*44704f69SBart Van Assche const char * name;
231*44704f69SBart Van Assche const char * acron;
232*44704f69SBart Van Assche bool (*show_pagep)(const uint8_t * resp, int len,
233*44704f69SBart Van Assche struct opts_t * op, sgj_opaque_p jop);
234*44704f69SBart Van Assche /* Returns true if done */
235*44704f69SBart Van Assche };
236*44704f69SBart Van Assche
237*44704f69SBart Van Assche struct vp_name_t {
238*44704f69SBart Van Assche int vend_prod_num; /* vendor/product identifier */
239*44704f69SBart Van Assche const char * acron;
240*44704f69SBart Van Assche const char * name;
241*44704f69SBart Van Assche const char * t10_vendorp;
242*44704f69SBart Van Assche const char * t10_productp;
243*44704f69SBart Van Assche };
244*44704f69SBart Van Assche
245*44704f69SBart Van Assche static const char * ls_s = "log_sense: ";
246*44704f69SBart Van Assche
247*44704f69SBart Van Assche static bool show_supported_pgs_page(const uint8_t * resp, int len,
248*44704f69SBart Van Assche struct opts_t * op, sgj_opaque_p jop);
249*44704f69SBart Van Assche static bool show_supported_pgs_sub_page(const uint8_t * resp, int len,
250*44704f69SBart Van Assche struct opts_t * op, sgj_opaque_p jop);
251*44704f69SBart Van Assche static bool show_buffer_over_under_run_page(const uint8_t * resp, int len,
252*44704f69SBart Van Assche struct opts_t * op,
253*44704f69SBart Van Assche sgj_opaque_p jop);
254*44704f69SBart Van Assche static bool show_error_counter_page(const uint8_t * resp, int len,
255*44704f69SBart Van Assche struct opts_t * op, sgj_opaque_p jop);
256*44704f69SBart Van Assche static bool show_non_medium_error_page(const uint8_t * resp, int len,
257*44704f69SBart Van Assche struct opts_t * op, sgj_opaque_p jop);
258*44704f69SBart Van Assche static bool show_last_n_error_page(const uint8_t * resp, int len,
259*44704f69SBart Van Assche struct opts_t * op, sgj_opaque_p jop);
260*44704f69SBart Van Assche static bool show_format_status_page(const uint8_t * resp, int len,
261*44704f69SBart Van Assche struct opts_t * op, sgj_opaque_p jop);
262*44704f69SBart Van Assche static bool show_last_n_deferred_error_page(const uint8_t * resp, int len,
263*44704f69SBart Van Assche struct opts_t * op,
264*44704f69SBart Van Assche sgj_opaque_p jop);
265*44704f69SBart Van Assche static bool show_last_n_inq_data_ch_page(const uint8_t * resp, int len,
266*44704f69SBart Van Assche struct opts_t * op,
267*44704f69SBart Van Assche sgj_opaque_p jop);
268*44704f69SBart Van Assche static bool show_last_n_mode_pg_data_ch_page(const uint8_t * resp, int len,
269*44704f69SBart Van Assche struct opts_t * op,
270*44704f69SBart Van Assche sgj_opaque_p jop);
271*44704f69SBart Van Assche static bool show_lb_provisioning_page(const uint8_t * resp, int len,
272*44704f69SBart Van Assche struct opts_t * op, sgj_opaque_p jop);
273*44704f69SBart Van Assche static bool show_sequential_access_page(const uint8_t * resp, int len,
274*44704f69SBart Van Assche struct opts_t * op, sgj_opaque_p jop);
275*44704f69SBart Van Assche static bool show_temperature_page(const uint8_t * resp, int len,
276*44704f69SBart Van Assche struct opts_t * op, sgj_opaque_p jop);
277*44704f69SBart Van Assche static bool show_start_stop_page(const uint8_t * resp, int len,
278*44704f69SBart Van Assche struct opts_t * op, sgj_opaque_p jop);
279*44704f69SBart Van Assche static bool show_utilization_page(const uint8_t * resp, int len,
280*44704f69SBart Van Assche struct opts_t * op, sgj_opaque_p jop);
281*44704f69SBart Van Assche static bool show_app_client_page(const uint8_t * resp, int len,
282*44704f69SBart Van Assche struct opts_t * op, sgj_opaque_p jop);
283*44704f69SBart Van Assche static bool show_self_test_page(const uint8_t * resp, int len,
284*44704f69SBart Van Assche struct opts_t * op, sgj_opaque_p jop);
285*44704f69SBart Van Assche static bool show_solid_state_media_page(const uint8_t * resp, int len,
286*44704f69SBart Van Assche struct opts_t * op, sgj_opaque_p jop);
287*44704f69SBart Van Assche static bool show_device_stats_page(const uint8_t * resp, int len,
288*44704f69SBart Van Assche struct opts_t * op, sgj_opaque_p jop);
289*44704f69SBart Van Assche static bool show_media_stats_page(const uint8_t * resp, int len,
290*44704f69SBart Van Assche struct opts_t * op, sgj_opaque_p jop);
291*44704f69SBart Van Assche static bool show_dt_device_status_page(const uint8_t * resp, int len,
292*44704f69SBart Van Assche struct opts_t * op, sgj_opaque_p jop);
293*44704f69SBart Van Assche static bool show_tapealert_response_page(const uint8_t * resp, int len,
294*44704f69SBart Van Assche struct opts_t * op,
295*44704f69SBart Van Assche sgj_opaque_p jop);
296*44704f69SBart Van Assche static bool show_requested_recovery_page(const uint8_t * resp, int len,
297*44704f69SBart Van Assche struct opts_t * op,
298*44704f69SBart Van Assche sgj_opaque_p jop);
299*44704f69SBart Van Assche static bool show_background_scan_results_page(const uint8_t * resp, int len,
300*44704f69SBart Van Assche struct opts_t * op,
301*44704f69SBart Van Assche sgj_opaque_p jop);
302*44704f69SBart Van Assche static bool show_zoned_block_dev_stats(const uint8_t * resp, int len,
303*44704f69SBart Van Assche struct opts_t * op, sgj_opaque_p jop);
304*44704f69SBart Van Assche static bool show_pending_defects_page(const uint8_t * resp, int len,
305*44704f69SBart Van Assche struct opts_t * op, sgj_opaque_p jop);
306*44704f69SBart Van Assche static bool show_background_op_page(const uint8_t * resp, int len,
307*44704f69SBart Van Assche struct opts_t * op, sgj_opaque_p jop);
308*44704f69SBart Van Assche static bool show_lps_misalignment_page(const uint8_t * resp, int len,
309*44704f69SBart Van Assche struct opts_t * op, sgj_opaque_p jop);
310*44704f69SBart Van Assche static bool show_element_stats_page(const uint8_t * resp, int len,
311*44704f69SBart Van Assche struct opts_t * op, sgj_opaque_p jop);
312*44704f69SBart Van Assche static bool show_service_buffer_info_page(const uint8_t * resp, int len,
313*44704f69SBart Van Assche struct opts_t * op,
314*44704f69SBart Van Assche sgj_opaque_p jop);
315*44704f69SBart Van Assche static bool show_ata_pt_results_page(const uint8_t * resp, int len,
316*44704f69SBart Van Assche struct opts_t * op, sgj_opaque_p jop);
317*44704f69SBart Van Assche static bool show_tape_diag_data_page(const uint8_t * resp, int len,
318*44704f69SBart Van Assche struct opts_t * op, sgj_opaque_p jop);
319*44704f69SBart Van Assche static bool show_mchanger_diag_data_page(const uint8_t * resp, int len,
320*44704f69SBart Van Assche struct opts_t * op,
321*44704f69SBart Van Assche sgj_opaque_p jop);
322*44704f69SBart Van Assche static bool show_non_volatile_cache_page(const uint8_t * resp, int len,
323*44704f69SBart Van Assche struct opts_t * op,
324*44704f69SBart Van Assche sgj_opaque_p jop);
325*44704f69SBart Van Assche static bool show_volume_stats_pages(const uint8_t * resp, int len,
326*44704f69SBart Van Assche struct opts_t * op, sgj_opaque_p jop);
327*44704f69SBart Van Assche static bool show_protocol_specific_port_page(const uint8_t * resp, int len,
328*44704f69SBart Van Assche struct opts_t * op,
329*44704f69SBart Van Assche sgj_opaque_p jop);
330*44704f69SBart Van Assche static bool show_stats_perform_pages(const uint8_t * resp, int len,
331*44704f69SBart Van Assche struct opts_t * op, sgj_opaque_p jop);
332*44704f69SBart Van Assche static bool show_cache_stats_page(const uint8_t * resp, int len,
333*44704f69SBart Van Assche struct opts_t * op, sgj_opaque_p jop);
334*44704f69SBart Van Assche static bool show_power_condition_transitions_page(const uint8_t * resp,
335*44704f69SBart Van Assche int len, struct opts_t * op,
336*44704f69SBart Van Assche sgj_opaque_p jop);
337*44704f69SBart Van Assche static bool show_environmental_reporting_page(const uint8_t * resp, int len,
338*44704f69SBart Van Assche struct opts_t * op,
339*44704f69SBart Van Assche sgj_opaque_p jop);
340*44704f69SBart Van Assche static bool show_environmental_limits_page(const uint8_t * resp, int len,
341*44704f69SBart Van Assche struct opts_t * op,
342*44704f69SBart Van Assche sgj_opaque_p jop);
343*44704f69SBart Van Assche static bool show_cmd_dur_limits_page(const uint8_t * resp, int len,
344*44704f69SBart Van Assche struct opts_t * op, sgj_opaque_p jop);
345*44704f69SBart Van Assche static bool show_data_compression_page(const uint8_t * resp, int len,
346*44704f69SBart Van Assche struct opts_t * op, sgj_opaque_p jop);
347*44704f69SBart Van Assche static bool show_tape_alert_ssc_page(const uint8_t * resp, int len,
348*44704f69SBart Van Assche struct opts_t * op, sgj_opaque_p jop);
349*44704f69SBart Van Assche static bool show_ie_page(const uint8_t * resp, int len,
350*44704f69SBart Van Assche struct opts_t * op, sgj_opaque_p jop);
351*44704f69SBart Van Assche static bool show_tape_usage_page(const uint8_t * resp, int len,
352*44704f69SBart Van Assche struct opts_t * op, sgj_opaque_p jop);
353*44704f69SBart Van Assche static bool show_tape_capacity_page(const uint8_t * resp, int len,
354*44704f69SBart Van Assche struct opts_t * op, sgj_opaque_p jop);
355*44704f69SBart Van Assche static bool show_seagate_cache_page(const uint8_t * resp, int len,
356*44704f69SBart Van Assche struct opts_t * op, sgj_opaque_p jop);
357*44704f69SBart Van Assche static bool show_seagate_factory_page(const uint8_t * resp, int len,
358*44704f69SBart Van Assche struct opts_t * op, sgj_opaque_p jop);
359*44704f69SBart Van Assche static bool show_hgst_perf_page(const uint8_t * resp, int len,
360*44704f69SBart Van Assche struct opts_t * op, sgj_opaque_p jop);
361*44704f69SBart Van Assche static bool show_hgst_misc_page(const uint8_t * resp, int len,
362*44704f69SBart Van Assche struct opts_t * op, sgj_opaque_p jop);
363*44704f69SBart Van Assche
364*44704f69SBart Van Assche /* elements in page_number/subpage_number order */
365*44704f69SBart Van Assche static struct log_elem log_arr[] = {
366*44704f69SBart Van Assche {SUPP_PAGES_LPAGE, 0, 0, -1, MVP_STD, "Supported log pages", "sp",
367*44704f69SBart Van Assche show_supported_pgs_page}, /* 0, 0 */
368*44704f69SBart Van Assche {SUPP_PAGES_LPAGE, SUPP_SPGS_SUBPG, 0, -1, MVP_STD, "Supported log pages "
369*44704f69SBart Van Assche "and subpages", "ssp", show_supported_pgs_sub_page}, /* 0, 0xff */
370*44704f69SBart Van Assche {BUFF_OVER_UNDER_LPAGE, 0, 0, -1, MVP_STD, "Buffer over-run/under-run",
371*44704f69SBart Van Assche "bou", show_buffer_over_under_run_page}, /* 0x1, 0x0 */
372*44704f69SBart Van Assche {WRITE_ERR_LPAGE, 0, 0, -1, MVP_STD, "Write error counters", "we",
373*44704f69SBart Van Assche show_error_counter_page}, /* 0x2, 0x0 */
374*44704f69SBart Van Assche {READ_ERR_LPAGE, 0, 0, -1, MVP_STD, "Read error counters", "re",
375*44704f69SBart Van Assche show_error_counter_page}, /* 0x3, 0x0 */
376*44704f69SBart Van Assche {READ_REV_ERR_LPAGE, 0, 0, -1, MVP_STD, "Read reverse error counters",
377*44704f69SBart Van Assche "rre", show_error_counter_page}, /* 0x4, 0x0 */
378*44704f69SBart Van Assche {VERIFY_ERR_LPAGE, 0, 0, -1, MVP_STD, "Verify error counters", "ve",
379*44704f69SBart Van Assche show_error_counter_page}, /* 0x5, 0x0 */
380*44704f69SBart Van Assche {NON_MEDIUM_LPAGE, 0, 0, -1, MVP_STD, "Non medium", "nm",
381*44704f69SBart Van Assche show_non_medium_error_page}, /* 0x6, 0x0 */
382*44704f69SBart Van Assche {LAST_N_ERR_LPAGE, 0, 0, -1, MVP_STD, "Last n error", "lne",
383*44704f69SBart Van Assche show_last_n_error_page}, /* 0x7, 0x0 */
384*44704f69SBart Van Assche {FORMAT_STATUS_LPAGE, 0, 0, 0, MVP_STD, "Format status", "fs",
385*44704f69SBart Van Assche show_format_status_page}, /* 0x8, 0x0 SBC */
386*44704f69SBart Van Assche {LAST_N_DEFERRED_LPAGE, 0, 0, -1, MVP_STD, "Last n deferred error", "lnd",
387*44704f69SBart Van Assche show_last_n_deferred_error_page}, /* 0xb, 0x0 */
388*44704f69SBart Van Assche {LAST_N_DEFERRED_LPAGE, LAST_N_INQUIRY_DATA_CH_SUBPG, 0, -1, MVP_STD,
389*44704f69SBart Van Assche "Last n inquiry data changed", "lnic",
390*44704f69SBart Van Assche show_last_n_inq_data_ch_page}, /* 0xb, 0x1 */
391*44704f69SBart Van Assche {LAST_N_DEFERRED_LPAGE, LAST_N_MODE_PG_DATA_CH_SUBPG, 0, -1, MVP_STD,
392*44704f69SBart Van Assche "Last n mode page data changed", "lnmc",
393*44704f69SBart Van Assche show_last_n_mode_pg_data_ch_page}, /* 0xb, 0x2 */
394*44704f69SBart Van Assche {LB_PROV_LPAGE, 0, 0, 0, MVP_STD, "Logical block provisioning", "lbp",
395*44704f69SBart Van Assche show_lb_provisioning_page}, /* 0xc, 0x0 SBC */
396*44704f69SBart Van Assche {0xc, 0, 0, PDT_TAPE, MVP_STD, "Sequential access device", "sad",
397*44704f69SBart Van Assche show_sequential_access_page}, /* 0xc, 0x0 SSC */
398*44704f69SBart Van Assche {TEMPERATURE_LPAGE, 0, 0, -1, MVP_STD, "Temperature", "temp",
399*44704f69SBart Van Assche show_temperature_page}, /* 0xd, 0x0 */
400*44704f69SBart Van Assche {TEMPERATURE_LPAGE, ENV_REPORTING_SUBPG, 0, -1, MVP_STD, /* 0xd, 0x1 */
401*44704f69SBart Van Assche "Environmental reporting", "enr", show_environmental_reporting_page},
402*44704f69SBart Van Assche {TEMPERATURE_LPAGE, ENV_LIMITS_SUBPG, 0, -1, MVP_STD, /* 0xd, 0x2 */
403*44704f69SBart Van Assche "Environmental limits", "enl", show_environmental_limits_page},
404*44704f69SBart Van Assche {START_STOP_LPAGE, 0, 0, -1, MVP_STD, "Start-stop cycle counter", "sscc",
405*44704f69SBart Van Assche show_start_stop_page}, /* 0xe, 0x0 */
406*44704f69SBart Van Assche {START_STOP_LPAGE, UTILIZATION_SUBPG, 0, 0, MVP_STD, "Utilization",
407*44704f69SBart Van Assche "util", show_utilization_page}, /* 0xe, 0x1 SBC */ /* sbc4r04 */
408*44704f69SBart Van Assche {APP_CLIENT_LPAGE, 0, 0, -1, MVP_STD, "Application client", "ac",
409*44704f69SBart Van Assche show_app_client_page}, /* 0xf, 0x0 */
410*44704f69SBart Van Assche {SELF_TEST_LPAGE, 0, 0, -1, MVP_STD, "Self test results", "str",
411*44704f69SBart Van Assche show_self_test_page}, /* 0x10, 0x0 */
412*44704f69SBart Van Assche {SOLID_STATE_MEDIA_LPAGE, 0, 0, 0, MVP_STD, "Solid state media", "ssm",
413*44704f69SBart Van Assche show_solid_state_media_page}, /* 0x11, 0x0 SBC */
414*44704f69SBart Van Assche {0x11, 0, 0, PDT_TAPE, MVP_STD, "DT Device status", "dtds",
415*44704f69SBart Van Assche show_dt_device_status_page}, /* 0x11, 0x0 SSC,ADC */
416*44704f69SBart Van Assche {0x12, 0, 0, PDT_TAPE, MVP_STD, "Tape alert response", "tar",
417*44704f69SBart Van Assche show_tapealert_response_page}, /* 0x12, 0x0 SSC,ADC */
418*44704f69SBart Van Assche {REQ_RECOVERY_LPAGE, 0, 0, PDT_TAPE, MVP_STD, "Requested recovery", "rr",
419*44704f69SBart Van Assche show_requested_recovery_page}, /* 0x13, 0x0 SSC,ADC */
420*44704f69SBart Van Assche {DEVICE_STATS_LPAGE, 0, 0, PDT_TAPE, MVP_STD, "Device statistics", "ds",
421*44704f69SBart Van Assche show_device_stats_page}, /* 0x14, 0x0 SSC,ADC */
422*44704f69SBart Van Assche {DEVICE_STATS_LPAGE, 0, 0, PDT_MCHANGER, MVP_STD, /* 0x14, 0x0 SMC */
423*44704f69SBart Van Assche "Media changer statistics", "mcs", show_media_stats_page},
424*44704f69SBart Van Assche {DEVICE_STATS_LPAGE, ZONED_BLOCK_DEV_STATS_SUBPG, /* 0x14,0x1 zbc2r01 */
425*44704f69SBart Van Assche 0, 0, MVP_STD, "Zoned block device statistics", "zbds",
426*44704f69SBart Van Assche show_zoned_block_dev_stats},
427*44704f69SBart Van Assche {BACKGROUND_SCAN_LPAGE, 0, 0, 0, MVP_STD, "Background scan results",
428*44704f69SBart Van Assche "bsr", show_background_scan_results_page}, /* 0x15, 0x0 SBC */
429*44704f69SBart Van Assche {BACKGROUND_SCAN_LPAGE, BACKGROUND_OP_SUBPG, 0, 0, MVP_STD,
430*44704f69SBart Van Assche "Background operation", "bop", show_background_op_page},
431*44704f69SBart Van Assche /* 0x15, 0x2 SBC */
432*44704f69SBart Van Assche {BACKGROUND_SCAN_LPAGE, LPS_MISALIGNMENT_SUBPG, 0, 0, MVP_STD,
433*44704f69SBart Van Assche "LPS misalignment", "lps", show_lps_misalignment_page},
434*44704f69SBart Van Assche /* 0x15, 0x3 SBC-4 */
435*44704f69SBart Van Assche {0x15, 0, 0, PDT_MCHANGER, MVP_STD, "Element statistics", "els",
436*44704f69SBart Van Assche show_element_stats_page}, /* 0x15, 0x0 SMC */
437*44704f69SBart Van Assche {0x15, 0, 0, PDT_ADC, MVP_STD, "Service buffers information", "sbi",
438*44704f69SBart Van Assche show_service_buffer_info_page}, /* 0x15, 0x0 ADC */
439*44704f69SBart Van Assche {BACKGROUND_SCAN_LPAGE, PENDING_DEFECTS_SUBPG, 0, 0, MVP_STD,
440*44704f69SBart Van Assche "Pending defects", "pd", show_pending_defects_page}, /* 0x15, 0x1 SBC */
441*44704f69SBart Van Assche {SAT_ATA_RESULTS_LPAGE, 0, 0, 0, MVP_STD, "ATA pass-through results",
442*44704f69SBart Van Assche "aptr", show_ata_pt_results_page}, /* 0x16, 0x0 SAT */
443*44704f69SBart Van Assche {0x16, 0, 0, PDT_TAPE, MVP_STD, "Tape diagnostic data", "tdd",
444*44704f69SBart Van Assche show_tape_diag_data_page}, /* 0x16, 0x0 SSC */
445*44704f69SBart Van Assche {0x16, 0, 0, PDT_MCHANGER, MVP_STD, "Media changer diagnostic data",
446*44704f69SBart Van Assche "mcdd", show_mchanger_diag_data_page}, /* 0x16, 0x0 SMC */
447*44704f69SBart Van Assche {0x17, 0, 0, 0, MVP_STD, "Non volatile cache", "nvc",
448*44704f69SBart Van Assche show_non_volatile_cache_page}, /* 0x17, 0x0 SBC */
449*44704f69SBart Van Assche {0x17, 0, 0xf, PDT_TAPE, MVP_STD, "Volume statistics", "vs",
450*44704f69SBart Van Assche show_volume_stats_pages}, /* 0x17, 0x0...0xf SSC */
451*44704f69SBart Van Assche {PROTO_SPECIFIC_LPAGE, 0, 0, -1, MVP_STD, "Protocol specific port",
452*44704f69SBart Van Assche "psp", show_protocol_specific_port_page}, /* 0x18, 0x0 */
453*44704f69SBart Van Assche {STATS_LPAGE, 0, 0, -1, MVP_STD, "General Statistics and Performance",
454*44704f69SBart Van Assche "gsp", show_stats_perform_pages}, /* 0x19, 0x0 */
455*44704f69SBart Van Assche {STATS_LPAGE, 0x1, 0x1f, -1, MVP_STD, "Group Statistics and Performance",
456*44704f69SBart Van Assche "grsp", show_stats_perform_pages}, /* 0x19, 0x1...0x1f */
457*44704f69SBart Van Assche {STATS_LPAGE, CACHE_STATS_SUBPG, 0, -1, MVP_STD, /* 0x19, 0x20 */
458*44704f69SBart Van Assche "Cache memory statistics", "cms", show_cache_stats_page},
459*44704f69SBart Van Assche {STATS_LPAGE, CMD_DUR_LIMITS_SUBPG, 0, -1, MVP_STD, /* 0x19, 0x21 */
460*44704f69SBart Van Assche "Command duration limits statistics", "cdl",
461*44704f69SBart Van Assche show_cmd_dur_limits_page /* spc6r01 */ },
462*44704f69SBart Van Assche {PCT_LPAGE, 0, 0, -1, MVP_STD, "Power condition transitions", "pct",
463*44704f69SBart Van Assche show_power_condition_transitions_page}, /* 0x1a, 0 */
464*44704f69SBart Van Assche {0x1b, 0, 0, PDT_TAPE, MVP_STD, "Data compression", "dc",
465*44704f69SBart Van Assche show_data_compression_page}, /* 0x1b, 0 SSC */
466*44704f69SBart Van Assche {0x2d, 0, 0, PDT_TAPE, MVP_STD, "Current service information", "csi",
467*44704f69SBart Van Assche NULL}, /* 0x2d, 0 SSC */
468*44704f69SBart Van Assche {TAPE_ALERT_LPAGE, 0, 0, PDT_TAPE, MVP_STD, "Tape alert", "ta",
469*44704f69SBart Van Assche show_tape_alert_ssc_page}, /* 0x2e, 0 SSC */
470*44704f69SBart Van Assche {IE_LPAGE, 0, 0, -1, (MVP_STD | MVP_HITA),
471*44704f69SBart Van Assche "Informational exceptions", "ie", show_ie_page}, /* 0x2f, 0 */
472*44704f69SBart Van Assche /* vendor specific */
473*44704f69SBart Van Assche {0x30, 0, 0, PDT_DISK, MVP_HITA, "Performance counters (Hitachi)",
474*44704f69SBart Van Assche "pc_hi", show_hgst_perf_page}, /* 0x30, 0 SBC */
475*44704f69SBart Van Assche {0x30, 0, 0, PDT_TAPE, OVP_LTO, "Tape usage (lto-5, 6)", "tu_",
476*44704f69SBart Van Assche show_tape_usage_page}, /* 0x30, 0 SSC */
477*44704f69SBart Van Assche {0x31, 0, 0, PDT_TAPE, OVP_LTO, "Tape capacity (lto-5, 6)",
478*44704f69SBart Van Assche "tc_", show_tape_capacity_page}, /* 0x31, 0 SSC */
479*44704f69SBart Van Assche {0x32, 0, 0, PDT_TAPE, MVP_LTO5, "Data compression (lto-5)",
480*44704f69SBart Van Assche "dc_", show_data_compression_page}, /* 0x32, 0 SSC; redirect to 0x1b */
481*44704f69SBart Van Assche {0x33, 0, 0, PDT_TAPE, MVP_LTO5, "Write errors (lto-5)", "we_",
482*44704f69SBart Van Assche NULL}, /* 0x33, 0 SSC */
483*44704f69SBart Van Assche {0x34, 0, 0, PDT_TAPE, MVP_LTO5, "Read forward errors (lto-5)",
484*44704f69SBart Van Assche "rfe_", NULL}, /* 0x34, 0 SSC */
485*44704f69SBart Van Assche {0x35, 0, 0, PDT_TAPE, OVP_LTO, "DT Device Error (lto-5, 6)",
486*44704f69SBart Van Assche "dtde_", NULL}, /* 0x35, 0 SSC */
487*44704f69SBart Van Assche {0x37, 0, 0, PDT_DISK, MVP_SEAG, "Cache (seagate)", "c_se",
488*44704f69SBart Van Assche show_seagate_cache_page}, /* 0x37, 0 SBC */
489*44704f69SBart Van Assche {0x37, 0, 0, PDT_DISK, MVP_HITA, "Miscellaneous (hitachi)", "mi_hi",
490*44704f69SBart Van Assche show_hgst_misc_page}, /* 0x37, 0 SBC */
491*44704f69SBart Van Assche {0x37, 0, 0, PDT_TAPE, MVP_LTO5, "Performance characteristics "
492*44704f69SBart Van Assche "(lto-5)", "pc_", NULL}, /* 0x37, 0 SSC */
493*44704f69SBart Van Assche {0x38, 0, 0, PDT_TAPE, MVP_LTO5, "Blocks/bytes transferred "
494*44704f69SBart Van Assche "(lto-5)", "bbt_", NULL}, /* 0x38, 0 SSC */
495*44704f69SBart Van Assche {0x39, 0, 0, PDT_TAPE, MVP_LTO5, "Host port 0 interface errors "
496*44704f69SBart Van Assche "(lto-5)", "hp0_", NULL}, /* 0x39, 0 SSC */
497*44704f69SBart Van Assche {0x3a, 0, 0, PDT_TAPE, MVP_LTO5, "Drive control verification "
498*44704f69SBart Van Assche "(lto-5)", "dcv_", NULL}, /* 0x3a, 0 SSC */
499*44704f69SBart Van Assche {0x3b, 0, 0, PDT_TAPE, MVP_LTO5, "Host port 1 interface errors "
500*44704f69SBart Van Assche "(lto-5)", "hp1_", NULL}, /* 0x3b, 0 SSC */
501*44704f69SBart Van Assche {0x3c, 0, 0, PDT_TAPE, MVP_LTO5, "Drive usage information "
502*44704f69SBart Van Assche "(lto-5)", "dui_", NULL}, /* 0x3c, 0 SSC */
503*44704f69SBart Van Assche {0x3d, 0, 0, PDT_TAPE, MVP_LTO5, "Subsystem statistics (lto-5)",
504*44704f69SBart Van Assche "ss_", NULL}, /* 0x3d, 0 SSC */
505*44704f69SBart Van Assche {0x3e, 0, 0, PDT_DISK, MVP_SEAG, "Factory (seagate)", "f_se",
506*44704f69SBart Van Assche show_seagate_factory_page}, /* 0x3e, 0 SBC */
507*44704f69SBart Van Assche {0x3e, 0, 0, PDT_DISK, MVP_HITA, "Factory (hitachi)", "f_hi",
508*44704f69SBart Van Assche NULL}, /* 0x3e, 0 SBC */
509*44704f69SBart Van Assche {0x3e, 0, 0, PDT_TAPE, OVP_LTO, "Device Status (lto-5, 6)",
510*44704f69SBart Van Assche "ds_", NULL}, /* 0x3e, 0 SSC */
511*44704f69SBart Van Assche
512*44704f69SBart Van Assche {-1, -1, -1, -1, 0, NULL, "zzzzz", NULL}, /* end sentinel */
513*44704f69SBart Van Assche };
514*44704f69SBart Van Assche
515*44704f69SBart Van Assche /* Supported vendor product codes */
516*44704f69SBart Van Assche /* Arrange in alphabetical order by acronym */
517*44704f69SBart Van Assche static struct vp_name_t vp_arr[] = {
518*44704f69SBart Van Assche {VP_SEAG, "sea", "Seagate", "SEAGATE", NULL},
519*44704f69SBart Van Assche {VP_HITA, "hit", "Hitachi", "HGST", NULL},
520*44704f69SBart Van Assche {VP_HITA, "wdc", "WDC/Hitachi", "WDC", NULL},
521*44704f69SBart Van Assche {VP_TOSH, "tos", "Toshiba", "TOSHIBA", NULL},
522*44704f69SBart Van Assche {VP_LTO5, "lto5", "LTO-5 (tape drive consortium)", NULL, NULL},
523*44704f69SBart Van Assche {VP_LTO6, "lto6", "LTO-6 (tape drive consortium)", NULL, NULL},
524*44704f69SBart Van Assche {VP_ALL, "all", "enumerate all vendor specific", NULL, NULL},
525*44704f69SBart Van Assche {0, NULL, NULL, NULL, NULL},
526*44704f69SBart Van Assche };
527*44704f69SBart Van Assche
528*44704f69SBart Van Assche static char t10_vendor_str[10];
529*44704f69SBart Van Assche static char t10_product_str[18];
530*44704f69SBart Van Assche
531*44704f69SBart Van Assche #ifdef SG_LIB_WIN32
532*44704f69SBart Van Assche static bool win32_spt_init_state = false;
533*44704f69SBart Van Assche static bool win32_spt_curr_state = false;
534*44704f69SBart Van Assche #endif
535*44704f69SBart Van Assche
536*44704f69SBart Van Assche
537*44704f69SBart Van Assche static void
usage(int hval)538*44704f69SBart Van Assche usage(int hval)
539*44704f69SBart Van Assche {
540*44704f69SBart Van Assche if (1 == hval) {
541*44704f69SBart Van Assche pr2serr(
542*44704f69SBart Van Assche "Usage: sg_logs [-ALL] [--all] [--brief] [--control=PC] "
543*44704f69SBart Van Assche "[--enumerate]\n"
544*44704f69SBart Van Assche " [--exclude] [--filter=FL] [--full] [--help] "
545*44704f69SBart Van Assche "[--hex]\n"
546*44704f69SBart Van Assche " [--in=FN] [--json[=JO]] [--list] [--maxlen=LEN] "
547*44704f69SBart Van Assche "[--name]\n"
548*44704f69SBart Van Assche " [--no_inq] [--page=PG] [--paramp=PP] [--pcb] "
549*44704f69SBart Van Assche "[--ppc]\n"
550*44704f69SBart Van Assche " [--pdt=DT] [--raw] [--readonly] [--reset] "
551*44704f69SBart Van Assche "[--select]\n"
552*44704f69SBart Van Assche " [--sp] [--temperature] [--transport] "
553*44704f69SBart Van Assche "[--undefined]\n"
554*44704f69SBart Van Assche " [--vendor=VP] [--verbose] [--version] DEVICE\n"
555*44704f69SBart Van Assche " where the main options are:\n"
556*44704f69SBart Van Assche " --ALL|-A fetch and decode all log pages and "
557*44704f69SBart Van Assche "subpages\n"
558*44704f69SBart Van Assche " --all|-a fetch and decode all log pages, but not "
559*44704f69SBart Van Assche "subpages; use\n"
560*44704f69SBart Van Assche " twice to fetch and decode all log pages "
561*44704f69SBart Van Assche "and subpages\n"
562*44704f69SBart Van Assche " --brief|-b shorten the output of some log pages\n"
563*44704f69SBart Van Assche " --enumerate|-e enumerate known pages, ignore DEVICE. "
564*44704f69SBart Van Assche "Sort order,\n"
565*44704f69SBart Van Assche " '-e': all by acronym; '-ee': non-vendor "
566*44704f69SBart Van Assche "by acronym;\n"
567*44704f69SBart Van Assche " '-eee': all numerically; '-eeee': "
568*44704f69SBart Van Assche "non-v numerically\n"
569*44704f69SBart Van Assche " --filter=FL|-f FL FL is parameter code to display (def: "
570*44704f69SBart Van Assche "all);\n"
571*44704f69SBart Van Assche " with '-e' then FL>=0 enumerate that "
572*44704f69SBart Van Assche "pdt + spc\n"
573*44704f69SBart Van Assche " FL=-1 all (default), FL=-2 spc only\n"
574*44704f69SBart Van Assche " --full|-F drill down in application client log page\n"
575*44704f69SBart Van Assche " --help|-h print usage message then exit. Use twice "
576*44704f69SBart Van Assche "for more help\n"
577*44704f69SBart Van Assche " --hex|-H output response in hex (default: decode if "
578*44704f69SBart Van Assche "known)\n"
579*44704f69SBart Van Assche " --in=FN|-i FN FN is a filename containing a log page "
580*44704f69SBart Van Assche "in ASCII hex\n"
581*44704f69SBart Van Assche " or binary if --raw also given. --inhex=FN "
582*44704f69SBart Van Assche "also accepted\n"
583*44704f69SBart Van Assche " --json[=JO]|-j[JO] output in JSON instead of human "
584*44704f69SBart Van Assche "readable\n"
585*44704f69SBart Van Assche " test. Use --json=? for JSON help\n"
586*44704f69SBart Van Assche " --list|-l list supported log pages; twice: list "
587*44704f69SBart Van Assche "supported log\n"
588*44704f69SBart Van Assche " pages and subpages page; thrice: merge of "
589*44704f69SBart Van Assche "both pages\n"
590*44704f69SBart Van Assche " --page=PG|-p PG PG is either log page acronym, PGN or "
591*44704f69SBart Van Assche "PGN,SPGN\n"
592*44704f69SBart Van Assche " where (S)PGN is a (sub) page number\n");
593*44704f69SBart Van Assche pr2serr(
594*44704f69SBart Van Assche " --raw|-r either output response in binary to stdout "
595*44704f69SBart Van Assche "or, if\n"
596*44704f69SBart Van Assche " '--in=FN' is given, FN is decoded as "
597*44704f69SBart Van Assche "binary\n"
598*44704f69SBart Van Assche " --temperature|-t decode temperature (log page 0xd or "
599*44704f69SBart Van Assche "0x2f)\n"
600*44704f69SBart Van Assche " --transport|-T decode transport (protocol specific port "
601*44704f69SBart Van Assche "0x18) page\n"
602*44704f69SBart Van Assche " --vendor=VP|-M VP vendor/product abbreviation [or "
603*44704f69SBart Van Assche "number]\n"
604*44704f69SBart Van Assche " --verbose|-v increase verbosity\n\n"
605*44704f69SBart Van Assche "Performs a SCSI LOG SENSE (or LOG SELECT) command and decodes "
606*44704f69SBart Van Assche "the response.\nIf only DEVICE is given then '-p sp' (supported "
607*44704f69SBart Van Assche "pages) is assumed. Use\n'-e' to see known pages and their "
608*44704f69SBart Van Assche "acronyms. For more help use '-hh'.\n");
609*44704f69SBart Van Assche } else if (hval > 1) {
610*44704f69SBart Van Assche pr2serr(
611*44704f69SBart Van Assche " where sg_logs' lesser used options are:\n"
612*44704f69SBart Van Assche " --control=PC|-c PC page control(PC) (default: 1)\n"
613*44704f69SBart Van Assche " 0: current threshold, 1: current "
614*44704f69SBart Van Assche "cumulative\n"
615*44704f69SBart Van Assche " 2: default threshold, 3: default "
616*44704f69SBart Van Assche "cumulative\n"
617*44704f69SBart Van Assche " --exclude|-E exclude vendor specific pages and "
618*44704f69SBart Van Assche "parameters\n"
619*44704f69SBart Van Assche " --list|-l list supported log page names (equivalent to "
620*44704f69SBart Van Assche "'-p sp')\n"
621*44704f69SBart Van Assche " use twice to list supported log page and "
622*44704f69SBart Van Assche "subpage names\n"
623*44704f69SBart Van Assche " --maxlen=LEN|-m LEN max response length (def: 0 "
624*44704f69SBart Van Assche "-> everything)\n"
625*44704f69SBart Van Assche " when > 1 will request LEN bytes\n"
626*44704f69SBart Van Assche " --name|-n decode some pages into multiple name=value "
627*44704f69SBart Van Assche "lines\n"
628*44704f69SBart Van Assche " --no_inq|-x no initial INQUIRY output (twice: and no "
629*44704f69SBart Van Assche "INQUIRY call)\n"
630*44704f69SBart Van Assche " --old|-O use old interface (use as first option)\n"
631*44704f69SBart Van Assche " --paramp=PP|-P PP place PP in parameter pointer field in "
632*44704f69SBart Van Assche "cdb (def: 0)\n"
633*44704f69SBart Van Assche " --pcb|-q show parameter control bytes in decoded "
634*44704f69SBart Van Assche "output\n"
635*44704f69SBart Van Assche " --ppc|-Q set the Parameter Pointer Control (PPC) bit "
636*44704f69SBart Van Assche "(def: 0)\n"
637*44704f69SBart Van Assche " --pdt=DT|-D DT DT is peripheral device type to use with "
638*44704f69SBart Van Assche "'--in=FN'\n"
639*44704f69SBart Van Assche " or when '--no_inq' is used\n"
640*44704f69SBart Van Assche " --readonly|-X open DEVICE read-only (def: first "
641*44704f69SBart Van Assche "read-write then if\n"
642*44704f69SBart Van Assche " fails try open again read-only)\n"
643*44704f69SBart Van Assche " --reset|-R reset log parameters (takes PC and SP into "
644*44704f69SBart Van Assche "account)\n"
645*44704f69SBart Van Assche " (uses PCR bit in LOG SELECT)\n"
646*44704f69SBart Van Assche " --select|-S perform LOG SELECT (def: LOG SENSE)\n"
647*44704f69SBart Van Assche " --sp|-s set the Saving Parameters (SP) bit (def: "
648*44704f69SBart Van Assche "0)\n"
649*44704f69SBart Van Assche " --undefined|-u hex format for undefined/unrecognized "
650*44704f69SBart Van Assche "fields,\n"
651*44704f69SBart Van Assche " use one or more times; format as per "
652*44704f69SBart Van Assche "--hex\n"
653*44704f69SBart Van Assche " --version|-V output version string then exit\n\n"
654*44704f69SBart Van Assche "If DEVICE and --select are given, a LOG SELECT command will be "
655*44704f69SBart Van Assche "issued.\nIf DEVICE is not given and '--in=FN' is given then FN "
656*44704f69SBart Van Assche "will decoded as if\nit were a log page. The contents of FN "
657*44704f69SBart Van Assche "generated by either a prior\n'sg_logs -HHH ...' invocation or "
658*44704f69SBart Van Assche "by a text editor.\nLog pages defined in SPC are common "
659*44704f69SBart Van Assche "to all device types.\n");
660*44704f69SBart Van Assche }
661*44704f69SBart Van Assche }
662*44704f69SBart Van Assche
663*44704f69SBart Van Assche static void
usage_old()664*44704f69SBart Van Assche usage_old()
665*44704f69SBart Van Assche {
666*44704f69SBart Van Assche printf("Usage: sg_logs [-a] [-A] [-b] [-c=PC] [-D=DT] [-e] [-E] [-f=FL] "
667*44704f69SBart Van Assche "[-F]\n"
668*44704f69SBart Van Assche " [-h] [-H] [-i=FN] [-l] [-L] [-m=LEN] [-M=VP] "
669*44704f69SBart Van Assche "[-n] [-p=PG]\n"
670*44704f69SBart Van Assche " [-paramp=PP] [-pcb] [-ppc] [-r] [-select] [-sp] "
671*44704f69SBart Van Assche "[-t] [-T]\n"
672*44704f69SBart Van Assche " [-u] [-v] [-V] [-x] [-X] [-?] DEVICE\n"
673*44704f69SBart Van Assche " where:\n"
674*44704f69SBart Van Assche " -a fetch and decode all log pages\n"
675*44704f69SBart Van Assche " -A fetch and decode all log pages and subpages\n"
676*44704f69SBart Van Assche " -b shorten the output of some log pages\n"
677*44704f69SBart Van Assche " -c=PC page control(PC) (default: 1)\n"
678*44704f69SBart Van Assche " 0: current threshold, 1: current cumulative\n"
679*44704f69SBart Van Assche " 2: default threshold, 3: default cumulative\n"
680*44704f69SBart Van Assche " -e enumerate known log pages\n"
681*44704f69SBart Van Assche " -D=DT DT is peripheral device type to use with "
682*44704f69SBart Van Assche "'--in=FN'\n"
683*44704f69SBart Van Assche " -E exclude vendor specific pages and parameters\n"
684*44704f69SBart Van Assche " -f=FL filter match parameter code or pdt\n"
685*44704f69SBart Van Assche " -F drill down in application client log page\n"
686*44704f69SBart Van Assche " -h output in hex (default: decode if known)\n"
687*44704f69SBart Van Assche " -H output in hex (same as '-h')\n"
688*44704f69SBart Van Assche " -i=FN FN is a filename containing a log page "
689*44704f69SBart Van Assche "in ASCII hex.\n"
690*44704f69SBart Van Assche " -l list supported log page names (equivalent to "
691*44704f69SBart Van Assche "'-p=0')\n"
692*44704f69SBart Van Assche " -L list supported log page and subpages names "
693*44704f69SBart Van Assche "(equivalent to\n"
694*44704f69SBart Van Assche " '-p=0,ff')\n"
695*44704f69SBart Van Assche " -m=LEN max response length (decimal) (def: 0 "
696*44704f69SBart Van Assche "-> everything)\n"
697*44704f69SBart Van Assche " -M=VP vendor/product abbreviation [or number]\n"
698*44704f69SBart Van Assche " -n decode some pages into multiple name=value "
699*44704f69SBart Van Assche "lines\n"
700*44704f69SBart Van Assche " -N|--new use new interface\n"
701*44704f69SBart Van Assche " -p=PG PG is an acronym (def: 'sp')\n"
702*44704f69SBart Van Assche " -p=PGN page code in hex (def: 0)\n"
703*44704f69SBart Van Assche " -p=PGN,SPGN page and subpage codes in hex, (defs: 0,0)\n"
704*44704f69SBart Van Assche " -paramp=PP (in hex) (def: 0)\n"
705*44704f69SBart Van Assche " -pcb show parameter control bytes in decoded "
706*44704f69SBart Van Assche "output\n");
707*44704f69SBart Van Assche printf(" -ppc set the Parameter Pointer Control (PPC) bit "
708*44704f69SBart Van Assche "(def: 0)\n"
709*44704f69SBart Van Assche " -r reset log parameters (takes PC and SP into "
710*44704f69SBart Van Assche "account)\n"
711*44704f69SBart Van Assche " (uses PCR bit in LOG SELECT)\n"
712*44704f69SBart Van Assche " -select perform LOG SELECT (def: LOG SENSE)\n"
713*44704f69SBart Van Assche " -sp set the Saving Parameters (SP) bit (def: 0)\n"
714*44704f69SBart Van Assche " -t outputs temperature log page (0xd)\n"
715*44704f69SBart Van Assche " -T outputs transport (protocol specific port) log "
716*44704f69SBart Van Assche "page (0x18)\n"
717*44704f69SBart Van Assche " -u hex format for undefined/unrecognized fields\n"
718*44704f69SBart Van Assche " -v increase verbosity\n"
719*44704f69SBart Van Assche " -V output version string\n"
720*44704f69SBart Van Assche " -x no initial INQUIRY output (twice: no INQUIRY call)\n"
721*44704f69SBart Van Assche " -X open DEVICE read-only (def: first read-write then "
722*44704f69SBart Van Assche "if fails\n"
723*44704f69SBart Van Assche " try open again with read-only)\n"
724*44704f69SBart Van Assche " -? output this usage message\n\n"
725*44704f69SBart Van Assche "Performs a SCSI LOG SENSE (or LOG SELECT) command\n");
726*44704f69SBart Van Assche }
727*44704f69SBart Van Assche
728*44704f69SBart Van Assche /* Return vendor product mask given vendor product number */
729*44704f69SBart Van Assche static int
get_vp_mask(int vpn)730*44704f69SBart Van Assche get_vp_mask(int vpn)
731*44704f69SBart Van Assche {
732*44704f69SBart Van Assche if (vpn < 0)
733*44704f69SBart Van Assche return 0;
734*44704f69SBart Van Assche else
735*44704f69SBart Van Assche return (vpn >= (32 - MVP_OFFSET)) ? OVP_ALL :
736*44704f69SBart Van Assche (1 << (vpn + MVP_OFFSET));
737*44704f69SBart Van Assche }
738*44704f69SBart Van Assche
739*44704f69SBart Van Assche static int
asort_comp(const void * lp,const void * rp)740*44704f69SBart Van Assche asort_comp(const void * lp, const void * rp)
741*44704f69SBart Van Assche {
742*44704f69SBart Van Assche const struct log_elem * const * lepp =
743*44704f69SBart Van Assche (const struct log_elem * const *)lp;
744*44704f69SBart Van Assche const struct log_elem * const * repp =
745*44704f69SBart Van Assche (const struct log_elem * const *)rp;
746*44704f69SBart Van Assche
747*44704f69SBart Van Assche return strcmp((*lepp)->acron, (*repp)->acron);
748*44704f69SBart Van Assche }
749*44704f69SBart Van Assche
750*44704f69SBart Van Assche static void
enumerate_helper(const struct log_elem * lep,bool first,const struct opts_t * op)751*44704f69SBart Van Assche enumerate_helper(const struct log_elem * lep, bool first,
752*44704f69SBart Van Assche const struct opts_t * op)
753*44704f69SBart Van Assche {
754*44704f69SBart Van Assche char b[80];
755*44704f69SBart Van Assche char bb[80];
756*44704f69SBart Van Assche const char * cp;
757*44704f69SBart Van Assche bool vendor_lpage = ! (MVP_STD & lep->flags);
758*44704f69SBart Van Assche
759*44704f69SBart Van Assche if (first) {
760*44704f69SBart Van Assche if (1 == op->verbose) {
761*44704f69SBart Van Assche printf("acronym pg[,spg] name\n");
762*44704f69SBart Van Assche printf("===============================================\n");
763*44704f69SBart Van Assche } else if (2 == op->verbose) {
764*44704f69SBart Van Assche printf("acronym pg[,spg] pdt name\n");
765*44704f69SBart Van Assche printf("===================================================\n");
766*44704f69SBart Van Assche }
767*44704f69SBart Van Assche }
768*44704f69SBart Van Assche if ((0 == (op->do_enumerate % 2)) && vendor_lpage)
769*44704f69SBart Van Assche return; /* if do_enumerate is even then skip vendor pages */
770*44704f69SBart Van Assche else if ((! op->filter_given) || (-1 == op->filter))
771*44704f69SBart Van Assche ; /* otherwise enumerate all lpages if no --filter= */
772*44704f69SBart Van Assche else if (-2 == op->filter) { /* skip non-SPC pages */
773*44704f69SBart Van Assche if (lep->pdt >= 0)
774*44704f69SBart Van Assche return;
775*44704f69SBart Van Assche } else if (-10 == op->filter) { /* skip non-disk like pages */
776*44704f69SBart Van Assche if (sg_lib_pdt_decay(lep->pdt) != 0)
777*44704f69SBart Van Assche return;
778*44704f69SBart Van Assche } else if (-11 == op->filter) { /* skip tape like device pages */
779*44704f69SBart Van Assche if (sg_lib_pdt_decay(lep->pdt) != 1)
780*44704f69SBart Van Assche return;
781*44704f69SBart Van Assche } else if ((op->filter >= 0) && (op->filter <= 0x1f)) {
782*44704f69SBart Van Assche if ((lep->pdt >= 0) && (lep->pdt != op->filter) &&
783*44704f69SBart Van Assche (lep->pdt != sg_lib_pdt_decay(op->filter)))
784*44704f69SBart Van Assche return;
785*44704f69SBart Van Assche }
786*44704f69SBart Van Assche if (op->vend_prod_num >= 0) {
787*44704f69SBart Van Assche if (! (lep->flags & get_vp_mask(op->vend_prod_num)))
788*44704f69SBart Van Assche return;
789*44704f69SBart Van Assche }
790*44704f69SBart Van Assche if (op->deduced_vpn >= 0) {
791*44704f69SBart Van Assche if (! (lep->flags & get_vp_mask(op->deduced_vpn)))
792*44704f69SBart Van Assche return;
793*44704f69SBart Van Assche }
794*44704f69SBart Van Assche if (lep->subpg_high > 0)
795*44704f69SBart Van Assche snprintf(b, sizeof(b), "0x%x,0x%x->0x%x", lep->pg_code,
796*44704f69SBart Van Assche lep->subpg_code, lep->subpg_high);
797*44704f69SBart Van Assche else if (lep->subpg_code > 0)
798*44704f69SBart Van Assche snprintf(b, sizeof(b), "0x%x,0x%x", lep->pg_code,
799*44704f69SBart Van Assche lep->subpg_code);
800*44704f69SBart Van Assche else
801*44704f69SBart Van Assche snprintf(b, sizeof(b), "0x%x", lep->pg_code);
802*44704f69SBart Van Assche snprintf(bb, sizeof(bb), "%-16s", b);
803*44704f69SBart Van Assche cp = (op->verbose && (! lep->show_pagep)) ? " [hex only]" : "";
804*44704f69SBart Van Assche if (op->verbose > 1) {
805*44704f69SBart Van Assche if (lep->pdt < 0)
806*44704f69SBart Van Assche printf(" %-8s%s- %s%s\n", lep->acron, bb, lep->name, cp);
807*44704f69SBart Van Assche else
808*44704f69SBart Van Assche printf(" %-8s%s0x%02x %s%s\n", lep->acron, bb, lep->pdt,
809*44704f69SBart Van Assche lep->name, cp);
810*44704f69SBart Van Assche } else
811*44704f69SBart Van Assche printf(" %-8s%s%s%s\n", lep->acron, bb, lep->name, cp);
812*44704f69SBart Van Assche }
813*44704f69SBart Van Assche
814*44704f69SBart Van Assche static void
enumerate_pages(const struct opts_t * op)815*44704f69SBart Van Assche enumerate_pages(const struct opts_t * op)
816*44704f69SBart Van Assche {
817*44704f69SBart Van Assche int j;
818*44704f69SBart Van Assche struct log_elem * lep;
819*44704f69SBart Van Assche struct log_elem ** lep_arr;
820*44704f69SBart Van Assche
821*44704f69SBart Van Assche if (op->do_enumerate < 3) { /* -e, -ee: sort by acronym */
822*44704f69SBart Van Assche int k;
823*44704f69SBart Van Assche struct log_elem ** lepp;
824*44704f69SBart Van Assche
825*44704f69SBart Van Assche for (k = 0, lep = log_arr; lep->pg_code >=0; ++lep, ++k)
826*44704f69SBart Van Assche ;
827*44704f69SBart Van Assche ++k;
828*44704f69SBart Van Assche lep_arr = (struct log_elem **)calloc(k, sizeof(struct log_elem *));
829*44704f69SBart Van Assche if (NULL == lep_arr) {
830*44704f69SBart Van Assche pr2serr("%s: out of memory\n", __func__);
831*44704f69SBart Van Assche return;
832*44704f69SBart Van Assche }
833*44704f69SBart Van Assche for (k = 0, lep = log_arr; lep->pg_code >=0; ++lep, ++k)
834*44704f69SBart Van Assche lep_arr[k] = lep;
835*44704f69SBart Van Assche lep_arr[k++] = lep; /* put sentinel on end */
836*44704f69SBart Van Assche qsort(lep_arr, k, sizeof(struct log_elem *), asort_comp);
837*44704f69SBart Van Assche printf("Known log pages in acronym order:\n");
838*44704f69SBart Van Assche for (lepp = lep_arr, j = 0; (*lepp)->pg_code >=0; ++lepp, ++j)
839*44704f69SBart Van Assche enumerate_helper(*lepp, (0 == j), op);
840*44704f69SBart Van Assche free(lep_arr);
841*44704f69SBart Van Assche } else { /* -eee, -eeee numeric sort (as per table) */
842*44704f69SBart Van Assche printf("Known log pages in numerical order:\n");
843*44704f69SBart Van Assche for (lep = log_arr, j = 0; lep->pg_code >=0; ++lep, ++j)
844*44704f69SBart Van Assche enumerate_helper(lep, (0 == j), op);
845*44704f69SBart Van Assche }
846*44704f69SBart Van Assche }
847*44704f69SBart Van Assche
848*44704f69SBart Van Assche static const struct log_elem *
acron_search(const char * acron)849*44704f69SBart Van Assche acron_search(const char * acron)
850*44704f69SBart Van Assche {
851*44704f69SBart Van Assche const struct log_elem * lep;
852*44704f69SBart Van Assche
853*44704f69SBart Van Assche for (lep = log_arr; lep->pg_code >=0; ++lep) {
854*44704f69SBart Van Assche if (0 == strcmp(acron, lep->acron))
855*44704f69SBart Van Assche return lep;
856*44704f69SBart Van Assche }
857*44704f69SBart Van Assche return NULL;
858*44704f69SBart Van Assche }
859*44704f69SBart Van Assche
860*44704f69SBart Van Assche static int
find_vpn_by_acron(const char * vp_ap)861*44704f69SBart Van Assche find_vpn_by_acron(const char * vp_ap)
862*44704f69SBart Van Assche {
863*44704f69SBart Van Assche const struct vp_name_t * vpp;
864*44704f69SBart Van Assche
865*44704f69SBart Van Assche for (vpp = vp_arr; vpp->acron; ++vpp) {
866*44704f69SBart Van Assche size_t k;
867*44704f69SBart Van Assche size_t len = strlen(vpp->acron);
868*44704f69SBart Van Assche
869*44704f69SBart Van Assche for (k = 0; k < len; ++k) {
870*44704f69SBart Van Assche if (tolower((uint8_t)vp_ap[k]) != (uint8_t)vpp->acron[k])
871*44704f69SBart Van Assche break;
872*44704f69SBart Van Assche }
873*44704f69SBart Van Assche if (k < len)
874*44704f69SBart Van Assche continue;
875*44704f69SBart Van Assche return vpp->vend_prod_num;
876*44704f69SBart Van Assche }
877*44704f69SBart Van Assche return VP_NONE;
878*44704f69SBart Van Assche }
879*44704f69SBart Van Assche
880*44704f69SBart Van Assche /* Find vendor product number using T10 VENDOR and PRODUCT ID fields in a
881*44704f69SBart Van Assche INQUIRY response. */
882*44704f69SBart Van Assche static int
find_vpn_by_inquiry(void)883*44704f69SBart Van Assche find_vpn_by_inquiry(void)
884*44704f69SBart Van Assche {
885*44704f69SBart Van Assche size_t len;
886*44704f69SBart Van Assche size_t t10_v_len = strlen(t10_vendor_str);
887*44704f69SBart Van Assche size_t t10_p_len = strlen(t10_product_str);
888*44704f69SBart Van Assche const struct vp_name_t * vpp;
889*44704f69SBart Van Assche
890*44704f69SBart Van Assche if ((0 == t10_v_len) && (0 == t10_p_len))
891*44704f69SBart Van Assche return VP_NONE;
892*44704f69SBart Van Assche for (vpp = vp_arr; vpp->acron; ++vpp) {
893*44704f69SBart Van Assche bool matched = false;
894*44704f69SBart Van Assche
895*44704f69SBart Van Assche if (vpp->t10_vendorp && (t10_v_len > 0)) {
896*44704f69SBart Van Assche len = strlen(vpp->t10_vendorp);
897*44704f69SBart Van Assche len = (len > t10_v_len) ? t10_v_len : len;
898*44704f69SBart Van Assche if (strncmp(vpp->t10_vendorp, t10_vendor_str, len))
899*44704f69SBart Van Assche continue;
900*44704f69SBart Van Assche matched = true;
901*44704f69SBart Van Assche }
902*44704f69SBart Van Assche if (vpp->t10_productp && (t10_p_len > 0)) {
903*44704f69SBart Van Assche len = strlen(vpp->t10_productp);
904*44704f69SBart Van Assche len = (len > t10_p_len) ? t10_p_len : len;
905*44704f69SBart Van Assche if (strncmp(vpp->t10_productp, t10_product_str, len))
906*44704f69SBart Van Assche continue;
907*44704f69SBart Van Assche matched = true;
908*44704f69SBart Van Assche }
909*44704f69SBart Van Assche if (matched)
910*44704f69SBart Van Assche return vpp->vend_prod_num;
911*44704f69SBart Van Assche }
912*44704f69SBart Van Assche return VP_NONE;
913*44704f69SBart Van Assche }
914*44704f69SBart Van Assche
915*44704f69SBart Van Assche static void
enumerate_vp(void)916*44704f69SBart Van Assche enumerate_vp(void)
917*44704f69SBart Van Assche {
918*44704f69SBart Van Assche const struct vp_name_t * vpp;
919*44704f69SBart Van Assche bool seen = false;
920*44704f69SBart Van Assche
921*44704f69SBart Van Assche for (vpp = vp_arr; vpp->acron; ++vpp) {
922*44704f69SBart Van Assche if (vpp->name) {
923*44704f69SBart Van Assche if (! seen) {
924*44704f69SBart Van Assche printf("\nVendor/product identifiers:\n");
925*44704f69SBart Van Assche seen = true;
926*44704f69SBart Van Assche }
927*44704f69SBart Van Assche printf(" %-10s %d %s\n", vpp->acron,
928*44704f69SBart Van Assche vpp->vend_prod_num, vpp->name);
929*44704f69SBart Van Assche }
930*44704f69SBart Van Assche }
931*44704f69SBart Van Assche }
932*44704f69SBart Van Assche
933*44704f69SBart Van Assche static const struct log_elem *
pg_subpg_pdt_search(int pg_code,int subpg_code,int pdt,int vpn)934*44704f69SBart Van Assche pg_subpg_pdt_search(int pg_code, int subpg_code, int pdt, int vpn)
935*44704f69SBart Van Assche {
936*44704f69SBart Van Assche const struct log_elem * lep;
937*44704f69SBart Van Assche int d_pdt;
938*44704f69SBart Van Assche int vp_mask = get_vp_mask(vpn);
939*44704f69SBart Van Assche
940*44704f69SBart Van Assche d_pdt = sg_lib_pdt_decay(pdt);
941*44704f69SBart Van Assche for (lep = log_arr; lep->pg_code >=0; ++lep) {
942*44704f69SBart Van Assche if (pg_code == lep->pg_code) {
943*44704f69SBart Van Assche if (subpg_code == lep->subpg_code) {
944*44704f69SBart Van Assche if ((MVP_STD & lep->flags) || (0 == vp_mask) ||
945*44704f69SBart Van Assche (vp_mask & lep->flags))
946*44704f69SBart Van Assche ;
947*44704f69SBart Van Assche else
948*44704f69SBart Van Assche continue;
949*44704f69SBart Van Assche if ((lep->pdt < 0) || (pdt == lep->pdt) || (pdt < 0))
950*44704f69SBart Van Assche return lep;
951*44704f69SBart Van Assche else if (d_pdt == lep->pdt)
952*44704f69SBart Van Assche return lep;
953*44704f69SBart Van Assche else if (pdt == sg_lib_pdt_decay(lep->pdt))
954*44704f69SBart Van Assche return lep;
955*44704f69SBart Van Assche } else if ((lep->subpg_high > 0) &&
956*44704f69SBart Van Assche (subpg_code > lep->subpg_code) &&
957*44704f69SBart Van Assche (subpg_code <= lep->subpg_high))
958*44704f69SBart Van Assche return lep;
959*44704f69SBart Van Assche }
960*44704f69SBart Van Assche }
961*44704f69SBart Van Assche return NULL;
962*44704f69SBart Van Assche }
963*44704f69SBart Van Assche
964*44704f69SBart Van Assche static void
js_snakenv_ihexstr_nex(sgj_state * jsp,sgj_opaque_p jop,const char * conv2sname,int64_t val_i,bool hex_as_well,const char * str_name,const char * val_s,const char * nex_s)965*44704f69SBart Van Assche js_snakenv_ihexstr_nex(sgj_state * jsp, sgj_opaque_p jop,
966*44704f69SBart Van Assche const char * conv2sname, int64_t val_i,
967*44704f69SBart Van Assche bool hex_as_well, const char * str_name,
968*44704f69SBart Van Assche const char * val_s, const char * nex_s)
969*44704f69SBart Van Assche {
970*44704f69SBart Van Assche
971*44704f69SBart Van Assche if ((NULL == jsp) || (NULL == jop))
972*44704f69SBart Van Assche return;
973*44704f69SBart Van Assche if (sgj_is_snake_name(conv2sname))
974*44704f69SBart Van Assche sgj_js_nv_ihexstr_nex(jsp, jop, conv2sname, val_i, hex_as_well,
975*44704f69SBart Van Assche str_name, val_s, nex_s);
976*44704f69SBart Van Assche else {
977*44704f69SBart Van Assche char b[128];
978*44704f69SBart Van Assche
979*44704f69SBart Van Assche sgj_convert_to_snake_name(conv2sname, b, sizeof(b));
980*44704f69SBart Van Assche sgj_js_nv_ihexstr_nex(jsp, jop, b, val_i, hex_as_well, str_name,
981*44704f69SBart Van Assche val_s, nex_s);
982*44704f69SBart Van Assche }
983*44704f69SBart Van Assche }
984*44704f69SBart Van Assche
985*44704f69SBart Van Assche static void
usage_for(int hval,const struct opts_t * op)986*44704f69SBart Van Assche usage_for(int hval, const struct opts_t * op)
987*44704f69SBart Van Assche {
988*44704f69SBart Van Assche if (op->opt_new)
989*44704f69SBart Van Assche usage(hval);
990*44704f69SBart Van Assche else
991*44704f69SBart Van Assche usage_old();
992*44704f69SBart Van Assche }
993*44704f69SBart Van Assche
994*44704f69SBart Van Assche /* Processes command line options according to new option format. Returns
995*44704f69SBart Van Assche * 0 is ok, else SG_LIB_SYNTAX_ERROR is returned. */
996*44704f69SBart Van Assche static int
new_parse_cmd_line(struct opts_t * op,int argc,char * argv[])997*44704f69SBart Van Assche new_parse_cmd_line(struct opts_t * op, int argc, char * argv[])
998*44704f69SBart Van Assche {
999*44704f69SBart Van Assche while (1) {
1000*44704f69SBart Van Assche int c, n;
1001*44704f69SBart Van Assche int option_index = 0;
1002*44704f69SBart Van Assche
1003*44704f69SBart Van Assche c = getopt_long(argc, argv, "aAbc:D:eEf:FhHi:j::lLm:M:nNOp:P:qQrRsStT"
1004*44704f69SBart Van Assche "uvVxX", long_options, &option_index);
1005*44704f69SBart Van Assche if (c == -1)
1006*44704f69SBart Van Assche break;
1007*44704f69SBart Van Assche
1008*44704f69SBart Van Assche switch (c) {
1009*44704f69SBart Van Assche case 'a':
1010*44704f69SBart Van Assche ++op->do_all;
1011*44704f69SBart Van Assche break;
1012*44704f69SBart Van Assche case 'A':
1013*44704f69SBart Van Assche op->do_all += 2;
1014*44704f69SBart Van Assche break;
1015*44704f69SBart Van Assche case 'b':
1016*44704f69SBart Van Assche ++op->do_brief;
1017*44704f69SBart Van Assche break;
1018*44704f69SBart Van Assche case 'c':
1019*44704f69SBart Van Assche n = sg_get_num(optarg);
1020*44704f69SBart Van Assche if ((n < 0) || (n > 3)) {
1021*44704f69SBart Van Assche pr2serr("bad argument to '--control='\n");
1022*44704f69SBart Van Assche usage(2);
1023*44704f69SBart Van Assche return SG_LIB_SYNTAX_ERROR;
1024*44704f69SBart Van Assche }
1025*44704f69SBart Van Assche op->page_control = n;
1026*44704f69SBart Van Assche break;
1027*44704f69SBart Van Assche case 'D':
1028*44704f69SBart Van Assche if (0 == memcmp("-1", optarg, 3))
1029*44704f69SBart Van Assche op->dev_pdt = -1;
1030*44704f69SBart Van Assche else {
1031*44704f69SBart Van Assche n = sg_get_num(optarg);
1032*44704f69SBart Van Assche if ((n < 0) || (n > 31)) {
1033*44704f69SBart Van Assche pr2serr("bad argument to '--pdt='\n");
1034*44704f69SBart Van Assche return SG_LIB_SYNTAX_ERROR;
1035*44704f69SBart Van Assche }
1036*44704f69SBart Van Assche op->dev_pdt = n;
1037*44704f69SBart Van Assche }
1038*44704f69SBart Van Assche break;
1039*44704f69SBart Van Assche case 'e':
1040*44704f69SBart Van Assche ++op->do_enumerate;
1041*44704f69SBart Van Assche break;
1042*44704f69SBart Van Assche case 'E':
1043*44704f69SBart Van Assche op->exclude_vendor = true;
1044*44704f69SBart Van Assche break;
1045*44704f69SBart Van Assche case 'f':
1046*44704f69SBart Van Assche if ('-' == optarg[0]) {
1047*44704f69SBart Van Assche n = sg_get_num(optarg + 1);
1048*44704f69SBart Van Assche if ((n < 0) || (n > 0x30)) {
1049*44704f69SBart Van Assche pr2serr("bad negated argument to '--filter='\n");
1050*44704f69SBart Van Assche return SG_LIB_SYNTAX_ERROR;
1051*44704f69SBart Van Assche }
1052*44704f69SBart Van Assche op->filter = -n;
1053*44704f69SBart Van Assche } else {
1054*44704f69SBart Van Assche n = sg_get_num(optarg);
1055*44704f69SBart Van Assche if ((n < 0) || (n > 0xffff)) {
1056*44704f69SBart Van Assche pr2serr("bad argument to '--filter='\n");
1057*44704f69SBart Van Assche usage(1);
1058*44704f69SBart Van Assche return SG_LIB_SYNTAX_ERROR;
1059*44704f69SBart Van Assche }
1060*44704f69SBart Van Assche op->filter = n;
1061*44704f69SBart Van Assche }
1062*44704f69SBart Van Assche op->filter_given = true;
1063*44704f69SBart Van Assche break;
1064*44704f69SBart Van Assche case 'F':
1065*44704f69SBart Van Assche op->do_full = true;
1066*44704f69SBart Van Assche break;
1067*44704f69SBart Van Assche case 'h':
1068*44704f69SBart Van Assche case '?':
1069*44704f69SBart Van Assche ++op->do_help;
1070*44704f69SBart Van Assche break;
1071*44704f69SBart Van Assche case 'H':
1072*44704f69SBart Van Assche ++op->do_hex;
1073*44704f69SBart Van Assche break;
1074*44704f69SBart Van Assche case 'i':
1075*44704f69SBart Van Assche op->in_fn = optarg;
1076*44704f69SBart Van Assche break;
1077*44704f69SBart Van Assche case 'j':
1078*44704f69SBart Van Assche if (! sgj_init_state(&op->json_st, optarg)) {
1079*44704f69SBart Van Assche int bad_char = op->json_st.first_bad_char;
1080*44704f69SBart Van Assche char e[1500];
1081*44704f69SBart Van Assche
1082*44704f69SBart Van Assche if (bad_char) {
1083*44704f69SBart Van Assche pr2serr("bad argument to --json= option, unrecognized "
1084*44704f69SBart Van Assche "character '%c'\n\n", bad_char);
1085*44704f69SBart Van Assche }
1086*44704f69SBart Van Assche sg_json_usage(0, e, sizeof(e));
1087*44704f69SBart Van Assche pr2serr("%s", e);
1088*44704f69SBart Van Assche return SG_LIB_SYNTAX_ERROR;
1089*44704f69SBart Van Assche }
1090*44704f69SBart Van Assche break;
1091*44704f69SBart Van Assche case 'l':
1092*44704f69SBart Van Assche ++op->do_list;
1093*44704f69SBart Van Assche break;
1094*44704f69SBart Van Assche case 'L':
1095*44704f69SBart Van Assche op->do_list += 2;
1096*44704f69SBart Van Assche break;
1097*44704f69SBart Van Assche case 'm':
1098*44704f69SBart Van Assche n = sg_get_num(optarg);
1099*44704f69SBart Van Assche if ((n < 0) || (1 == n)) {
1100*44704f69SBart Van Assche pr2serr("bad argument to '--maxlen=', from 2 and up "
1101*44704f69SBart Van Assche "expected\n");
1102*44704f69SBart Van Assche usage(2);
1103*44704f69SBart Van Assche return SG_LIB_SYNTAX_ERROR;
1104*44704f69SBart Van Assche } else if (n < 4) {
1105*44704f69SBart Van Assche pr2serr("Warning: setting '--maxlen' to 4\n");
1106*44704f69SBart Van Assche n = 4;
1107*44704f69SBart Van Assche }
1108*44704f69SBart Van Assche op->maxlen = n;
1109*44704f69SBart Van Assche op->maxlen_given = true;
1110*44704f69SBart Van Assche break;
1111*44704f69SBart Van Assche case 'M':
1112*44704f69SBart Van Assche if (op->vend_prod) {
1113*44704f69SBart Van Assche pr2serr("only one '--vendor=' option permitted\n");
1114*44704f69SBart Van Assche usage(2);
1115*44704f69SBart Van Assche return SG_LIB_SYNTAX_ERROR;
1116*44704f69SBart Van Assche } else
1117*44704f69SBart Van Assche op->vend_prod = optarg;
1118*44704f69SBart Van Assche break;
1119*44704f69SBart Van Assche case 'n':
1120*44704f69SBart Van Assche op->do_name = true;
1121*44704f69SBart Van Assche break;
1122*44704f69SBart Van Assche case 'N':
1123*44704f69SBart Van Assche break; /* ignore */
1124*44704f69SBart Van Assche case 'O':
1125*44704f69SBart Van Assche op->opt_new = false;
1126*44704f69SBart Van Assche return 0;
1127*44704f69SBart Van Assche case 'p':
1128*44704f69SBart Van Assche op->pg_arg = optarg;
1129*44704f69SBart Van Assche break;
1130*44704f69SBart Van Assche case 'P':
1131*44704f69SBart Van Assche n = sg_get_num(optarg);
1132*44704f69SBart Van Assche if (n < 0) {
1133*44704f69SBart Van Assche pr2serr("bad argument to '--paramp='\n");
1134*44704f69SBart Van Assche usage(2);
1135*44704f69SBart Van Assche return SG_LIB_SYNTAX_ERROR;
1136*44704f69SBart Van Assche }
1137*44704f69SBart Van Assche op->paramp = n;
1138*44704f69SBart Van Assche break;
1139*44704f69SBart Van Assche case 'q':
1140*44704f69SBart Van Assche op->do_pcb = true;
1141*44704f69SBart Van Assche break;
1142*44704f69SBart Van Assche case 'Q': /* N.B. PPC bit obsoleted in SPC-4 rev 18 */
1143*44704f69SBart Van Assche op->do_ppc = true;
1144*44704f69SBart Van Assche break;
1145*44704f69SBart Van Assche case 'r':
1146*44704f69SBart Van Assche op->do_raw = true;
1147*44704f69SBart Van Assche break;
1148*44704f69SBart Van Assche case 'R':
1149*44704f69SBart Van Assche op->do_pcreset = true;
1150*44704f69SBart Van Assche op->do_select = true;
1151*44704f69SBart Van Assche break;
1152*44704f69SBart Van Assche case 's':
1153*44704f69SBart Van Assche op->do_sp = true;
1154*44704f69SBart Van Assche break;
1155*44704f69SBart Van Assche case 'S':
1156*44704f69SBart Van Assche op->do_select = true;
1157*44704f69SBart Van Assche break;
1158*44704f69SBart Van Assche case 't':
1159*44704f69SBart Van Assche op->do_temperature = true;
1160*44704f69SBart Van Assche break;
1161*44704f69SBart Van Assche case 'T':
1162*44704f69SBart Van Assche op->do_transport = true;
1163*44704f69SBart Van Assche break;
1164*44704f69SBart Van Assche case 'u':
1165*44704f69SBart Van Assche ++op->undefined_hex;
1166*44704f69SBart Van Assche break;
1167*44704f69SBart Van Assche case 'v':
1168*44704f69SBart Van Assche op->verbose_given = true;
1169*44704f69SBart Van Assche ++op->verbose;
1170*44704f69SBart Van Assche break;
1171*44704f69SBart Van Assche case 'V':
1172*44704f69SBart Van Assche op->version_given = true;
1173*44704f69SBart Van Assche break;
1174*44704f69SBart Van Assche case 'x':
1175*44704f69SBart Van Assche ++op->no_inq;
1176*44704f69SBart Van Assche break;
1177*44704f69SBart Van Assche case 'X':
1178*44704f69SBart Van Assche op->o_readonly = true;
1179*44704f69SBart Van Assche break;
1180*44704f69SBart Van Assche default:
1181*44704f69SBart Van Assche pr2serr("unrecognised option code %c [0x%x]\n", c, c);
1182*44704f69SBart Van Assche if (op->do_help)
1183*44704f69SBart Van Assche break;
1184*44704f69SBart Van Assche usage(1);
1185*44704f69SBart Van Assche return SG_LIB_SYNTAX_ERROR;
1186*44704f69SBart Van Assche }
1187*44704f69SBart Van Assche }
1188*44704f69SBart Van Assche if (optind < argc) {
1189*44704f69SBart Van Assche if (NULL == op->device_name) {
1190*44704f69SBart Van Assche op->device_name = argv[optind];
1191*44704f69SBart Van Assche ++optind;
1192*44704f69SBart Van Assche }
1193*44704f69SBart Van Assche if (optind < argc) {
1194*44704f69SBart Van Assche for (; optind < argc; ++optind)
1195*44704f69SBart Van Assche pr2serr("Unexpected extra argument: %s\n", argv[optind]);
1196*44704f69SBart Van Assche usage(1);
1197*44704f69SBart Van Assche return SG_LIB_SYNTAX_ERROR;
1198*44704f69SBart Van Assche }
1199*44704f69SBart Van Assche }
1200*44704f69SBart Van Assche return 0;
1201*44704f69SBart Van Assche }
1202*44704f69SBart Van Assche
1203*44704f69SBart Van Assche /* Processes command line options according to old option format. Returns
1204*44704f69SBart Van Assche * 0 is ok, else SG_LIB_SYNTAX_ERROR is returned. */
1205*44704f69SBart Van Assche static int
old_parse_cmd_line(struct opts_t * op,int argc,char * argv[])1206*44704f69SBart Van Assche old_parse_cmd_line(struct opts_t * op, int argc, char * argv[])
1207*44704f69SBart Van Assche {
1208*44704f69SBart Van Assche bool jmp_out;
1209*44704f69SBart Van Assche int k, num, n;
1210*44704f69SBart Van Assche unsigned int u, uu;
1211*44704f69SBart Van Assche const char * cp;
1212*44704f69SBart Van Assche
1213*44704f69SBart Van Assche for (k = 1; k < argc; ++k) {
1214*44704f69SBart Van Assche int plen;
1215*44704f69SBart Van Assche
1216*44704f69SBart Van Assche cp = argv[k];
1217*44704f69SBart Van Assche plen = strlen(cp);
1218*44704f69SBart Van Assche if (plen <= 0)
1219*44704f69SBart Van Assche continue;
1220*44704f69SBart Van Assche if ('-' == *cp) {
1221*44704f69SBart Van Assche for (--plen, ++cp, jmp_out = false; plen > 0; --plen, ++cp) {
1222*44704f69SBart Van Assche switch (*cp) {
1223*44704f69SBart Van Assche case 'a':
1224*44704f69SBart Van Assche ++op->do_all;
1225*44704f69SBart Van Assche break;
1226*44704f69SBart Van Assche case 'A':
1227*44704f69SBart Van Assche op->do_all += 2;
1228*44704f69SBart Van Assche break;
1229*44704f69SBart Van Assche case 'b':
1230*44704f69SBart Van Assche ++op->do_brief;
1231*44704f69SBart Van Assche break;
1232*44704f69SBart Van Assche case 'e':
1233*44704f69SBart Van Assche ++op->do_enumerate;
1234*44704f69SBart Van Assche break;
1235*44704f69SBart Van Assche case 'E':
1236*44704f69SBart Van Assche op->exclude_vendor = true;
1237*44704f69SBart Van Assche break;
1238*44704f69SBart Van Assche case 'F':
1239*44704f69SBart Van Assche op->do_full = true;
1240*44704f69SBart Van Assche break;
1241*44704f69SBart Van Assche case 'h':
1242*44704f69SBart Van Assche case 'H':
1243*44704f69SBart Van Assche ++op->do_hex;
1244*44704f69SBart Van Assche break;
1245*44704f69SBart Van Assche case 'l':
1246*44704f69SBart Van Assche ++op->do_list;
1247*44704f69SBart Van Assche break;
1248*44704f69SBart Van Assche case 'L':
1249*44704f69SBart Van Assche op->do_list += 2;
1250*44704f69SBart Van Assche break;
1251*44704f69SBart Van Assche case 'n':
1252*44704f69SBart Van Assche op->do_name = true;
1253*44704f69SBart Van Assche break;
1254*44704f69SBart Van Assche case 'N':
1255*44704f69SBart Van Assche op->opt_new = true;
1256*44704f69SBart Van Assche return 0;
1257*44704f69SBart Van Assche case 'O':
1258*44704f69SBart Van Assche break;
1259*44704f69SBart Van Assche case 'r':
1260*44704f69SBart Van Assche op->do_pcreset = true;
1261*44704f69SBart Van Assche op->do_select = true;
1262*44704f69SBart Van Assche break;
1263*44704f69SBart Van Assche case 't':
1264*44704f69SBart Van Assche op->do_temperature = true;
1265*44704f69SBart Van Assche break;
1266*44704f69SBart Van Assche case 'T':
1267*44704f69SBart Van Assche op->do_transport = true;
1268*44704f69SBart Van Assche break;
1269*44704f69SBart Van Assche case 'u':
1270*44704f69SBart Van Assche ++op->undefined_hex;
1271*44704f69SBart Van Assche break;
1272*44704f69SBart Van Assche case 'v':
1273*44704f69SBart Van Assche op->verbose_given = true;
1274*44704f69SBart Van Assche ++op->verbose;
1275*44704f69SBart Van Assche break;
1276*44704f69SBart Van Assche case 'V':
1277*44704f69SBart Van Assche op->version_given = true;
1278*44704f69SBart Van Assche break;
1279*44704f69SBart Van Assche case 'x':
1280*44704f69SBart Van Assche ++op->no_inq;
1281*44704f69SBart Van Assche break;
1282*44704f69SBart Van Assche case 'X':
1283*44704f69SBart Van Assche op->o_readonly = true;
1284*44704f69SBart Van Assche break;
1285*44704f69SBart Van Assche case '?':
1286*44704f69SBart Van Assche ++op->do_help;
1287*44704f69SBart Van Assche break;
1288*44704f69SBart Van Assche case '-':
1289*44704f69SBart Van Assche ++cp;
1290*44704f69SBart Van Assche jmp_out = true;
1291*44704f69SBart Van Assche break;
1292*44704f69SBart Van Assche default:
1293*44704f69SBart Van Assche jmp_out = true;
1294*44704f69SBart Van Assche break;
1295*44704f69SBart Van Assche }
1296*44704f69SBart Van Assche if (jmp_out)
1297*44704f69SBart Van Assche break;
1298*44704f69SBart Van Assche }
1299*44704f69SBart Van Assche if (plen <= 0)
1300*44704f69SBart Van Assche continue;
1301*44704f69SBart Van Assche if (0 == strncmp("c=", cp, 2)) {
1302*44704f69SBart Van Assche num = sscanf(cp + 2, "%6x", &u);
1303*44704f69SBart Van Assche if ((1 != num) || (u > 3)) {
1304*44704f69SBart Van Assche pr2serr("Bad page control after '-c=' option [0..3]\n");
1305*44704f69SBart Van Assche usage_old();
1306*44704f69SBart Van Assche return SG_LIB_SYNTAX_ERROR;
1307*44704f69SBart Van Assche }
1308*44704f69SBart Van Assche op->page_control = u;
1309*44704f69SBart Van Assche } else if (0 == strncmp("D=", cp, 2)) {
1310*44704f69SBart Van Assche n = sg_get_num(cp + 2);
1311*44704f69SBart Van Assche if ((n < 0) || (n > 31)) {
1312*44704f69SBart Van Assche pr2serr("Bad argument after '-D=' option\n");
1313*44704f69SBart Van Assche usage_old();
1314*44704f69SBart Van Assche return SG_LIB_SYNTAX_ERROR;
1315*44704f69SBart Van Assche }
1316*44704f69SBart Van Assche op->dev_pdt = n;
1317*44704f69SBart Van Assche } else if (0 == strncmp("f=", cp, 2)) {
1318*44704f69SBart Van Assche n = sg_get_num(cp + 2);
1319*44704f69SBart Van Assche if ((n < 0) || (n > 0xffff)) {
1320*44704f69SBart Van Assche pr2serr("Bad argument after '-f=' option\n");
1321*44704f69SBart Van Assche usage_old();
1322*44704f69SBart Van Assche return SG_LIB_SYNTAX_ERROR;
1323*44704f69SBart Van Assche }
1324*44704f69SBart Van Assche op->filter = n;
1325*44704f69SBart Van Assche op->filter_given = true;
1326*44704f69SBart Van Assche } else if (0 == strncmp("i=", cp, 2))
1327*44704f69SBart Van Assche op->in_fn = cp + 2;
1328*44704f69SBart Van Assche else if (0 == strncmp("m=", cp, 2)) {
1329*44704f69SBart Van Assche num = sscanf(cp + 2, "%8d", &n);
1330*44704f69SBart Van Assche if ((1 != num) || (n < 0)) {
1331*44704f69SBart Van Assche pr2serr("Bad maximum response length after '-m=' "
1332*44704f69SBart Van Assche "option\n");
1333*44704f69SBart Van Assche usage_old();
1334*44704f69SBart Van Assche return SG_LIB_SYNTAX_ERROR;
1335*44704f69SBart Van Assche }
1336*44704f69SBart Van Assche op->maxlen_given = true;
1337*44704f69SBart Van Assche op->maxlen = n;
1338*44704f69SBart Van Assche } else if (0 == strncmp("M=", cp, 2)) {
1339*44704f69SBart Van Assche if (op->vend_prod) {
1340*44704f69SBart Van Assche pr2serr("only one '-M=' option permitted\n");
1341*44704f69SBart Van Assche usage(2);
1342*44704f69SBart Van Assche return SG_LIB_SYNTAX_ERROR;
1343*44704f69SBart Van Assche } else
1344*44704f69SBart Van Assche op->vend_prod = cp + 2;
1345*44704f69SBart Van Assche } else if (0 == strncmp("p=", cp, 2)) {
1346*44704f69SBart Van Assche const char * ccp = cp + 2;
1347*44704f69SBart Van Assche const struct log_elem * lep;
1348*44704f69SBart Van Assche
1349*44704f69SBart Van Assche if (isalpha((uint8_t)ccp[0])) {
1350*44704f69SBart Van Assche char * xp;
1351*44704f69SBart Van Assche char b[80];
1352*44704f69SBart Van Assche
1353*44704f69SBart Van Assche if (strlen(ccp) >= (sizeof(b) - 1)) {
1354*44704f69SBart Van Assche pr2serr("argument to '-p=' is too long\n");
1355*44704f69SBart Van Assche return SG_LIB_SYNTAX_ERROR;
1356*44704f69SBart Van Assche }
1357*44704f69SBart Van Assche strcpy(b, ccp);
1358*44704f69SBart Van Assche xp = (char *)strchr(b, ',');
1359*44704f69SBart Van Assche if (xp)
1360*44704f69SBart Van Assche *xp = '\0';
1361*44704f69SBart Van Assche lep = acron_search(b);
1362*44704f69SBart Van Assche if (NULL == lep) {
1363*44704f69SBart Van Assche pr2serr("bad argument to '--page=' no acronyn match "
1364*44704f69SBart Van Assche "to '%s'\n", b);
1365*44704f69SBart Van Assche pr2serr(" Try using '-e' or'-ee' to see available "
1366*44704f69SBart Van Assche "acronyns\n");
1367*44704f69SBart Van Assche return SG_LIB_SYNTAX_ERROR;
1368*44704f69SBart Van Assche }
1369*44704f69SBart Van Assche op->lep = lep;
1370*44704f69SBart Van Assche op->pg_code = lep->pg_code;
1371*44704f69SBart Van Assche if (xp) {
1372*44704f69SBart Van Assche n = sg_get_num_nomult(xp + 1);
1373*44704f69SBart Van Assche if ((n < 0) || (n > 255)) {
1374*44704f69SBart Van Assche pr2serr("Bad second value in argument to "
1375*44704f69SBart Van Assche "'--page='\n");
1376*44704f69SBart Van Assche return SG_LIB_SYNTAX_ERROR;
1377*44704f69SBart Van Assche }
1378*44704f69SBart Van Assche op->subpg_code = n;
1379*44704f69SBart Van Assche } else
1380*44704f69SBart Van Assche op->subpg_code = lep->subpg_code;
1381*44704f69SBart Van Assche } else {
1382*44704f69SBart Van Assche /* numeric arg: either 'pg_num' or 'pg_num,subpg_num' */
1383*44704f69SBart Van Assche if (NULL == strchr(cp + 2, ',')) {
1384*44704f69SBart Van Assche num = sscanf(cp + 2, "%6x", &u);
1385*44704f69SBart Van Assche if ((1 != num) || (u > 63)) {
1386*44704f69SBart Van Assche pr2serr("Bad page code value after '-p=' "
1387*44704f69SBart Van Assche "option\n");
1388*44704f69SBart Van Assche usage_old();
1389*44704f69SBart Van Assche return SG_LIB_SYNTAX_ERROR;
1390*44704f69SBart Van Assche }
1391*44704f69SBart Van Assche op->pg_code = u;
1392*44704f69SBart Van Assche } else if (2 == sscanf(cp + 2, "%4x,%4x", &u, &uu)) {
1393*44704f69SBart Van Assche if (uu > 255) {
1394*44704f69SBart Van Assche pr2serr("Bad sub page code value after '-p=' "
1395*44704f69SBart Van Assche "option\n");
1396*44704f69SBart Van Assche usage_old();
1397*44704f69SBart Van Assche return SG_LIB_SYNTAX_ERROR;
1398*44704f69SBart Van Assche }
1399*44704f69SBart Van Assche op->pg_code = u;
1400*44704f69SBart Van Assche op->subpg_code = uu;
1401*44704f69SBart Van Assche } else {
1402*44704f69SBart Van Assche pr2serr("Bad page code, subpage code sequence after "
1403*44704f69SBart Van Assche "'-p=' option\n");
1404*44704f69SBart Van Assche usage_old();
1405*44704f69SBart Van Assche return SG_LIB_SYNTAX_ERROR;
1406*44704f69SBart Van Assche }
1407*44704f69SBart Van Assche }
1408*44704f69SBart Van Assche } else if (0 == strncmp("paramp=", cp, 7)) {
1409*44704f69SBart Van Assche num = sscanf(cp + 7, "%8x", &u);
1410*44704f69SBart Van Assche if ((1 != num) || (u > 0xffff)) {
1411*44704f69SBart Van Assche pr2serr("Bad parameter pointer after '-paramp=' "
1412*44704f69SBart Van Assche "option\n");
1413*44704f69SBart Van Assche usage_old();
1414*44704f69SBart Van Assche return SG_LIB_SYNTAX_ERROR;
1415*44704f69SBart Van Assche }
1416*44704f69SBart Van Assche op->paramp = u;
1417*44704f69SBart Van Assche } else if (0 == strncmp("pcb", cp, 3))
1418*44704f69SBart Van Assche op->do_pcb = true;
1419*44704f69SBart Van Assche else if (0 == strncmp("ppc", cp, 3))
1420*44704f69SBart Van Assche op->do_ppc = true;
1421*44704f69SBart Van Assche else if (0 == strncmp("select", cp, 6))
1422*44704f69SBart Van Assche op->do_select = true;
1423*44704f69SBart Van Assche else if (0 == strncmp("sp", cp, 2))
1424*44704f69SBart Van Assche op->do_sp = true;
1425*44704f69SBart Van Assche else if (0 == strncmp("old", cp, 3))
1426*44704f69SBart Van Assche ;
1427*44704f69SBart Van Assche else if (jmp_out) {
1428*44704f69SBart Van Assche pr2serr("Unrecognized option: %s\n", cp);
1429*44704f69SBart Van Assche usage_old();
1430*44704f69SBart Van Assche return SG_LIB_SYNTAX_ERROR;
1431*44704f69SBart Van Assche }
1432*44704f69SBart Van Assche } else if (0 == op->device_name)
1433*44704f69SBart Van Assche op->device_name = cp;
1434*44704f69SBart Van Assche else {
1435*44704f69SBart Van Assche pr2serr("too many arguments, got: %s, not expecting: %s\n",
1436*44704f69SBart Van Assche op->device_name, cp);
1437*44704f69SBart Van Assche usage_old();
1438*44704f69SBart Van Assche return SG_LIB_SYNTAX_ERROR;
1439*44704f69SBart Van Assche }
1440*44704f69SBart Van Assche }
1441*44704f69SBart Van Assche return 0;
1442*44704f69SBart Van Assche }
1443*44704f69SBart Van Assche
1444*44704f69SBart Van Assche /* Process command line options. First check using new option format unless
1445*44704f69SBart Van Assche * the SG3_UTILS_OLD_OPTS environment variable is defined which causes the
1446*44704f69SBart Van Assche * old option format to be checked first. Both new and old format can be
1447*44704f69SBart Van Assche * countermanded by a '-O' and '-N' options respectively. As soon as either
1448*44704f69SBart Van Assche * of these options is detected (when processing the other format), processing
1449*44704f69SBart Van Assche * stops and is restarted using the other format. Clear? */
1450*44704f69SBart Van Assche static int
parse_cmd_line(struct opts_t * op,int argc,char * argv[])1451*44704f69SBart Van Assche parse_cmd_line(struct opts_t * op, int argc, char * argv[])
1452*44704f69SBart Van Assche {
1453*44704f69SBart Van Assche int res;
1454*44704f69SBart Van Assche char * cp;
1455*44704f69SBart Van Assche
1456*44704f69SBart Van Assche cp = getenv("SG3_UTILS_OLD_OPTS");
1457*44704f69SBart Van Assche if (cp) {
1458*44704f69SBart Van Assche op->opt_new = false;
1459*44704f69SBart Van Assche res = old_parse_cmd_line(op, argc, argv);
1460*44704f69SBart Van Assche if ((0 == res) && op->opt_new)
1461*44704f69SBart Van Assche res = new_parse_cmd_line(op, argc, argv);
1462*44704f69SBart Van Assche } else {
1463*44704f69SBart Van Assche op->opt_new = true;
1464*44704f69SBart Van Assche res = new_parse_cmd_line(op, argc, argv);
1465*44704f69SBart Van Assche if ((0 == res) && (0 == op->opt_new))
1466*44704f69SBart Van Assche res = old_parse_cmd_line(op, argc, argv);
1467*44704f69SBart Van Assche }
1468*44704f69SBart Van Assche return res;
1469*44704f69SBart Van Assche }
1470*44704f69SBart Van Assche
1471*44704f69SBart Van Assche static void
dStrRaw(const uint8_t * str,int len)1472*44704f69SBart Van Assche dStrRaw(const uint8_t * str, int len)
1473*44704f69SBart Van Assche {
1474*44704f69SBart Van Assche int k;
1475*44704f69SBart Van Assche
1476*44704f69SBart Van Assche for (k = 0; k < len; ++k)
1477*44704f69SBart Van Assche printf("%c", str[k]);
1478*44704f69SBart Van Assche }
1479*44704f69SBart Van Assche
1480*44704f69SBart Van Assche /* Returns 'xp' with "unknown" if all bits set; otherwise decoded (big endian)
1481*44704f69SBart Van Assche * number in 'xp'. Number rendered in decimal if pr_in_hex=false otherwise in
1482*44704f69SBart Van Assche * hex with leading '0x' prepended. */
1483*44704f69SBart Van Assche static char *
num_or_unknown(const uint8_t * xp,int num_bytes,bool pr_in_hex,char * b,int blen)1484*44704f69SBart Van Assche num_or_unknown(const uint8_t * xp, int num_bytes /* max is 8 */,
1485*44704f69SBart Van Assche bool pr_in_hex, char * b, int blen)
1486*44704f69SBart Van Assche {
1487*44704f69SBart Van Assche if (sg_all_ffs(xp, num_bytes))
1488*44704f69SBart Van Assche snprintf(b, blen, "%s", unknown_s);
1489*44704f69SBart Van Assche else {
1490*44704f69SBart Van Assche uint64_t num = sg_get_unaligned_be(num_bytes, xp);
1491*44704f69SBart Van Assche
1492*44704f69SBart Van Assche if (pr_in_hex)
1493*44704f69SBart Van Assche snprintf(b, blen, "0x%" PRIx64, num);
1494*44704f69SBart Van Assche else
1495*44704f69SBart Van Assche snprintf(b, blen, "%" PRIu64, num);
1496*44704f69SBart Van Assche }
1497*44704f69SBart Van Assche return b;
1498*44704f69SBart Van Assche }
1499*44704f69SBart Van Assche
1500*44704f69SBart Van Assche /* Call LOG SENSE twice: the first time ask for 4 byte response to determine
1501*44704f69SBart Van Assche actual length of response; then a second time requesting the
1502*44704f69SBart Van Assche min(actual_len, mx_resp_len) bytes. If the calculated length for the
1503*44704f69SBart Van Assche second fetch is odd then it is incremented (perhaps should be made modulo
1504*44704f69SBart Van Assche 4 in the future for SAS). Returns 0 if ok, SG_LIB_CAT_INVALID_OP for
1505*44704f69SBart Van Assche log_sense not supported, SG_LIB_CAT_ILLEGAL_REQ for bad field in log sense
1506*44704f69SBart Van Assche command, SG_LIB_CAT_NOT_READY, SG_LIB_CAT_UNIT_ATTENTION,
1507*44704f69SBart Van Assche SG_LIB_CAT_ABORTED_COMMAND and -1 for other errors. */
1508*44704f69SBart Van Assche static int
do_logs(int sg_fd,uint8_t * resp,int mx_resp_len,const struct opts_t * op)1509*44704f69SBart Van Assche do_logs(int sg_fd, uint8_t * resp, int mx_resp_len,
1510*44704f69SBart Van Assche const struct opts_t * op)
1511*44704f69SBart Van Assche {
1512*44704f69SBart Van Assche int calc_len, request_len, res, resid, vb;
1513*44704f69SBart Van Assche
1514*44704f69SBart Van Assche #ifdef SG_LIB_WIN32
1515*44704f69SBart Van Assche #ifdef SG_LIB_WIN32_DIRECT
1516*44704f69SBart Van Assche if (! win32_spt_init_state) {
1517*44704f69SBart Van Assche if (win32_spt_curr_state) {
1518*44704f69SBart Van Assche if (mx_resp_len < 16384) {
1519*44704f69SBart Van Assche scsi_pt_win32_direct(0);
1520*44704f69SBart Van Assche win32_spt_curr_state = false;
1521*44704f69SBart Van Assche }
1522*44704f69SBart Van Assche } else {
1523*44704f69SBart Van Assche if (mx_resp_len >= 16384) {
1524*44704f69SBart Van Assche scsi_pt_win32_direct(SG_LIB_WIN32_DIRECT /* SPT direct */);
1525*44704f69SBart Van Assche win32_spt_curr_state = true;
1526*44704f69SBart Van Assche }
1527*44704f69SBart Van Assche }
1528*44704f69SBart Van Assche }
1529*44704f69SBart Van Assche #endif
1530*44704f69SBart Van Assche #endif
1531*44704f69SBart Van Assche memset(resp, 0, mx_resp_len);
1532*44704f69SBart Van Assche vb = op->verbose;
1533*44704f69SBart Van Assche if (op->maxlen > 1)
1534*44704f69SBart Van Assche request_len = mx_resp_len;
1535*44704f69SBart Van Assche else {
1536*44704f69SBart Van Assche request_len = LOG_SENSE_PROBE_ALLOC_LEN;
1537*44704f69SBart Van Assche if ((res = sg_ll_log_sense_v2(sg_fd, op->do_ppc, op->do_sp,
1538*44704f69SBart Van Assche op->page_control, op->pg_code,
1539*44704f69SBart Van Assche op->subpg_code, op->paramp,
1540*44704f69SBart Van Assche resp, request_len, LOG_SENSE_DEF_TIMEOUT,
1541*44704f69SBart Van Assche &resid, true /* noisy */, vb)))
1542*44704f69SBart Van Assche return res;
1543*44704f69SBart Van Assche if (resid > 0) {
1544*44704f69SBart Van Assche res = SG_LIB_WILD_RESID;
1545*44704f69SBart Van Assche goto resid_err;
1546*44704f69SBart Van Assche }
1547*44704f69SBart Van Assche calc_len = sg_get_unaligned_be16(resp + 2) + 4;
1548*44704f69SBart Van Assche if ((! op->do_raw) && (vb > 1)) {
1549*44704f69SBart Van Assche pr2serr(" Log sense (find length) response:\n");
1550*44704f69SBart Van Assche hex2stderr(resp, LOG_SENSE_PROBE_ALLOC_LEN, 1);
1551*44704f69SBart Van Assche pr2serr(" hence calculated response length=%d\n", calc_len);
1552*44704f69SBart Van Assche }
1553*44704f69SBart Van Assche if (op->pg_code != (0x3f & resp[0])) {
1554*44704f69SBart Van Assche if (vb)
1555*44704f69SBart Van Assche pr2serr("Page code does not appear in first byte of "
1556*44704f69SBart Van Assche "response so it's suspect\n");
1557*44704f69SBart Van Assche if (calc_len > 0x40) {
1558*44704f69SBart Van Assche calc_len = 0x40;
1559*44704f69SBart Van Assche if (vb)
1560*44704f69SBart Van Assche pr2serr("Trim response length to 64 bytes due to "
1561*44704f69SBart Van Assche "suspect response format\n");
1562*44704f69SBart Van Assche }
1563*44704f69SBart Van Assche }
1564*44704f69SBart Van Assche /* Some HBAs don't like odd transfer lengths */
1565*44704f69SBart Van Assche if (calc_len % 2)
1566*44704f69SBart Van Assche calc_len += 1;
1567*44704f69SBart Van Assche if (calc_len > mx_resp_len)
1568*44704f69SBart Van Assche calc_len = mx_resp_len;
1569*44704f69SBart Van Assche request_len = calc_len;
1570*44704f69SBart Van Assche }
1571*44704f69SBart Van Assche if ((res = sg_ll_log_sense_v2(sg_fd, op->do_ppc, op->do_sp,
1572*44704f69SBart Van Assche op->page_control, op->pg_code,
1573*44704f69SBart Van Assche op->subpg_code, op->paramp,
1574*44704f69SBart Van Assche resp, request_len,
1575*44704f69SBart Van Assche LOG_SENSE_DEF_TIMEOUT, &resid,
1576*44704f69SBart Van Assche true /* noisy */, vb)))
1577*44704f69SBart Van Assche return res;
1578*44704f69SBart Van Assche if (resid > 0) {
1579*44704f69SBart Van Assche request_len -= resid;
1580*44704f69SBart Van Assche if (request_len < 4) {
1581*44704f69SBart Van Assche request_len += resid;
1582*44704f69SBart Van Assche res = SG_LIB_WILD_RESID;
1583*44704f69SBart Van Assche goto resid_err;
1584*44704f69SBart Van Assche }
1585*44704f69SBart Van Assche }
1586*44704f69SBart Van Assche if ((! op->do_raw) && (vb > 1)) {
1587*44704f69SBart Van Assche pr2serr(" Log sense response:\n");
1588*44704f69SBart Van Assche hex2stderr(resp, request_len, 1);
1589*44704f69SBart Van Assche }
1590*44704f69SBart Van Assche return 0;
1591*44704f69SBart Van Assche resid_err:
1592*44704f69SBart Van Assche pr2serr("%s: request_len=%d, resid=%d, problems\n", __func__, request_len,
1593*44704f69SBart Van Assche resid);
1594*44704f69SBart Van Assche request_len -= resid;
1595*44704f69SBart Van Assche if ((request_len > 0) && (! op->do_raw) && (vb > 1)) {
1596*44704f69SBart Van Assche pr2serr(" Log sense (resid_err) response:\n");
1597*44704f69SBart Van Assche hex2stderr(resp, request_len, 1);
1598*44704f69SBart Van Assche }
1599*44704f69SBart Van Assche return res;
1600*44704f69SBart Van Assche }
1601*44704f69SBart Van Assche
1602*44704f69SBart Van Assche sgj_opaque_p
sg_log_js_hdr(sgj_state * jsp,sgj_opaque_p jop,const char * name,const uint8_t * log_hdrp)1603*44704f69SBart Van Assche sg_log_js_hdr(sgj_state * jsp, sgj_opaque_p jop, const char * name,
1604*44704f69SBart Van Assche const uint8_t * log_hdrp)
1605*44704f69SBart Van Assche {
1606*44704f69SBart Van Assche bool ds = !! (log_hdrp[0] & 0x80);
1607*44704f69SBart Van Assche bool spf = !! (log_hdrp[0] & 0x40);
1608*44704f69SBart Van Assche int pg = log_hdrp[0] & 0x3f;
1609*44704f69SBart Van Assche int subpg = log_hdrp[1];
1610*44704f69SBart Van Assche size_t nlen = strlen(name);
1611*44704f69SBart Van Assche sgj_opaque_p jo2p;
1612*44704f69SBart Van Assche char b[80];
1613*44704f69SBart Van Assche
1614*44704f69SBart Van Assche if ((nlen < 4) || (0 != strcmp("age", name + nlen - 3))) {
1615*44704f69SBart Van Assche memcpy(b, name, nlen);
1616*44704f69SBart Van Assche memcpy(b + nlen, " log page", 10);
1617*44704f69SBart Van Assche jo2p = sgj_snake_named_subobject_r(jsp, jop, b);
1618*44704f69SBart Van Assche } else
1619*44704f69SBart Van Assche jo2p = sgj_snake_named_subobject_r(jsp, jop, name);
1620*44704f69SBart Van Assche
1621*44704f69SBart Van Assche sgj_js_nv_ihex_nex(jsp, jo2p, "ds", (int)ds, false, "Did not Save");
1622*44704f69SBart Van Assche sgj_js_nv_ihex_nex(jsp, jo2p, "spf", (int)spf, NULL, "SubPage Format");
1623*44704f69SBart Van Assche sgj_js_nv_ihex(jsp, jo2p, "page_code", pg);
1624*44704f69SBart Van Assche sgj_js_nv_ihex(jsp, jo2p, "subpage_code", subpg);
1625*44704f69SBart Van Assche return jo2p;
1626*44704f69SBart Van Assche }
1627*44704f69SBart Van Assche
1628*44704f69SBart Van Assche
1629*44704f69SBart Van Assche
1630*44704f69SBart Van Assche /* DS made obsolete in spc4r03; TMC and ETC made obsolete in spc5r03. */
1631*44704f69SBart Van Assche static char *
get_pcb_str(int pcb,char * outp,int maxoutlen)1632*44704f69SBart Van Assche get_pcb_str(int pcb, char * outp, int maxoutlen)
1633*44704f69SBart Van Assche {
1634*44704f69SBart Van Assche char buff[PCB_STR_LEN];
1635*44704f69SBart Van Assche int n;
1636*44704f69SBart Van Assche
1637*44704f69SBart Van Assche n = sprintf(buff, "du=%d [ds=%d] tsd=%d [etc=%d] ", ((pcb & 0x80) ? 1 : 0),
1638*44704f69SBart Van Assche ((pcb & 0x40) ? 1 : 0), ((pcb & 0x20) ? 1 : 0),
1639*44704f69SBart Van Assche ((pcb & 0x10) ? 1 : 0));
1640*44704f69SBart Van Assche if (pcb & 0x10)
1641*44704f69SBart Van Assche n += sprintf(buff + n, "[tmc=%d] ", ((pcb & 0xc) >> 2));
1642*44704f69SBart Van Assche #if 1
1643*44704f69SBart Van Assche n += sprintf(buff + n, "format+linking=%d [0x%.2x]", pcb & 3,
1644*44704f69SBart Van Assche pcb);
1645*44704f69SBart Van Assche #else
1646*44704f69SBart Van Assche if (pcb & 0x1)
1647*44704f69SBart Van Assche n += sprintf(buff + n, "lbin=%d ", ((pcb & 0x2) >> 1));
1648*44704f69SBart Van Assche n += sprintf(buff + n, "lp=%d [0x%.2x]", pcb & 0x1, pcb);
1649*44704f69SBart Van Assche #endif
1650*44704f69SBart Van Assche if (outp && (n < maxoutlen)) {
1651*44704f69SBart Van Assche memcpy(outp, buff, n);
1652*44704f69SBart Van Assche outp[n] = '\0';
1653*44704f69SBart Van Assche } else if (outp && (maxoutlen > 0))
1654*44704f69SBart Van Assche outp[0] = '\0';
1655*44704f69SBart Van Assche return outp;
1656*44704f69SBart Van Assche }
1657*44704f69SBart Van Assche
1658*44704f69SBart Van Assche static void
js_pcb(sgj_state * jsp,sgj_opaque_p jop,int pcb)1659*44704f69SBart Van Assche js_pcb(sgj_state * jsp, sgj_opaque_p jop, int pcb)
1660*44704f69SBart Van Assche {
1661*44704f69SBart Van Assche sgj_opaque_p jo2p = sgj_snake_named_subobject_r(jsp, jop,
1662*44704f69SBart Van Assche "parameter_control_byte");
1663*44704f69SBart Van Assche
1664*44704f69SBart Van Assche sgj_js_nv_ihex_nex(jsp, jo2p, "du", (pcb & 0x80) ? 1 : 0, false,
1665*44704f69SBart Van Assche "Disable Update");
1666*44704f69SBart Van Assche sgj_js_nv_ihex_nex(jsp, jo2p, "ds", (pcb & 0x40) ? 1 : 0, false,
1667*44704f69SBart Van Assche "Disable Save [obsolete]");
1668*44704f69SBart Van Assche sgj_js_nv_ihex_nex(jsp, jo2p, "tsd", (pcb & 0x20) ? 1 : 0, false,
1669*44704f69SBart Van Assche "Target Save Disable");
1670*44704f69SBart Van Assche sgj_js_nv_ihex_nex(jsp, jo2p, "etc", (pcb & 0x10) ? 1 : 0, false,
1671*44704f69SBart Van Assche "Enable Threshold Comparison [obsolete]");
1672*44704f69SBart Van Assche sgj_js_nv_ihex_nex(jsp, jo2p, "tmc", (pcb & 0xc) >> 2, false,
1673*44704f69SBart Van Assche "Threshold Met Criteria [obsolete]");
1674*44704f69SBart Van Assche sgj_js_nv_ihex_nex(jsp, jo2p, "format_and_linking", pcb & 0x3, false,
1675*44704f69SBart Van Assche NULL);
1676*44704f69SBart Van Assche }
1677*44704f69SBart Van Assche
1678*44704f69SBart Van Assche /* SUPP_PAGES_LPAGE [0x0,0x0] <sp> */
1679*44704f69SBart Van Assche static bool
show_supported_pgs_page(const uint8_t * resp,int len,struct opts_t * op,sgj_opaque_p jop)1680*44704f69SBart Van Assche show_supported_pgs_page(const uint8_t * resp, int len,
1681*44704f69SBart Van Assche struct opts_t * op, sgj_opaque_p jop)
1682*44704f69SBart Van Assche {
1683*44704f69SBart Van Assche int num, k;
1684*44704f69SBart Van Assche const uint8_t * bp;
1685*44704f69SBart Van Assche sgj_state * jsp = &op->json_st;
1686*44704f69SBart Van Assche sgj_opaque_p jo2p, jo3p;
1687*44704f69SBart Van Assche sgj_opaque_p jap = NULL;
1688*44704f69SBart Van Assche char b[64];
1689*44704f69SBart Van Assche static const char * slpgs = "Supported log pages";
1690*44704f69SBart Van Assche
1691*44704f69SBart Van Assche if (op->verbose || ((! op->do_raw) && (0 == op->do_hex)))
1692*44704f69SBart Van Assche sgj_pr_hr(jsp, "%s [0x0]:\n", slpgs); /* introduced in: SPC-2 */
1693*44704f69SBart Van Assche num = len - 4;
1694*44704f69SBart Van Assche bp = &resp[0] + 4;
1695*44704f69SBart Van Assche if ((op->do_hex > 0) || op->do_raw) {
1696*44704f69SBart Van Assche if (op->do_raw)
1697*44704f69SBart Van Assche dStrRaw(resp, len);
1698*44704f69SBart Van Assche else
1699*44704f69SBart Van Assche hex2stdout(resp, len, op->dstrhex_no_ascii);
1700*44704f69SBart Van Assche return true;
1701*44704f69SBart Van Assche }
1702*44704f69SBart Van Assche if (jsp->pr_as_json) {
1703*44704f69SBart Van Assche jo2p = sg_log_js_hdr(jsp, jop, slpgs, resp);
1704*44704f69SBart Van Assche jap = sgj_named_subarray_r(jsp, jo2p, "supported_pages_list");
1705*44704f69SBart Van Assche }
1706*44704f69SBart Van Assche
1707*44704f69SBart Van Assche for (k = 0; k < num; ++k) {
1708*44704f69SBart Van Assche int pg_code = bp[k] & 0x3f;
1709*44704f69SBart Van Assche const struct log_elem * lep;
1710*44704f69SBart Van Assche
1711*44704f69SBart Van Assche snprintf(b, sizeof(b) - 1, " 0x%02x ", pg_code);
1712*44704f69SBart Van Assche lep = pg_subpg_pdt_search(pg_code, 0, op->dev_pdt, -1);
1713*44704f69SBart Van Assche if (lep) {
1714*44704f69SBart Van Assche if (op->do_brief > 1)
1715*44704f69SBart Van Assche sgj_pr_hr(jsp, " %s\n", lep->name);
1716*44704f69SBart Van Assche else if (op->do_brief)
1717*44704f69SBart Van Assche sgj_pr_hr(jsp, "%s%s\n", b, lep->name);
1718*44704f69SBart Van Assche else
1719*44704f69SBart Van Assche sgj_pr_hr(jsp, "%s%s [%s]\n", b, lep->name, lep->acron);
1720*44704f69SBart Van Assche } else
1721*44704f69SBart Van Assche sgj_pr_hr(jsp, "%s\n", b);
1722*44704f69SBart Van Assche if (jsp->pr_as_json) {
1723*44704f69SBart Van Assche jo3p = sgj_new_unattached_object_r(jsp);
1724*44704f69SBart Van Assche sgj_js_nv_ihex(jsp, jo3p, "page_code", pg_code);
1725*44704f69SBart Van Assche sgj_js_nv_s(jsp, jo3p, "name", lep ? lep->name : unknown_s);
1726*44704f69SBart Van Assche sgj_js_nv_s(jsp, jo3p, "acronym", lep ? lep->acron : unknown_s);
1727*44704f69SBart Van Assche sgj_js_nv_o(jsp, jap, NULL /* name */, jo3p);
1728*44704f69SBart Van Assche }
1729*44704f69SBart Van Assche }
1730*44704f69SBart Van Assche return true;
1731*44704f69SBart Van Assche }
1732*44704f69SBart Van Assche
1733*44704f69SBart Van Assche /* SUPP_PAGES_LPAGE,SUPP_SPGS_SUBPG [0x0,0xff] <ssp> or all subpages of a
1734*44704f69SBart Van Assche * given page code: [<pg_code>,0xff] where <pg_code> > 0 */
1735*44704f69SBart Van Assche static bool
show_supported_pgs_sub_page(const uint8_t * resp,int len,struct opts_t * op,sgj_opaque_p jop)1736*44704f69SBart Van Assche show_supported_pgs_sub_page(const uint8_t * resp, int len,
1737*44704f69SBart Van Assche struct opts_t * op, sgj_opaque_p jop)
1738*44704f69SBart Van Assche {
1739*44704f69SBart Van Assche int num, k;
1740*44704f69SBart Van Assche const uint8_t * bp;
1741*44704f69SBart Van Assche const struct log_elem * lep = NULL;
1742*44704f69SBart Van Assche sgj_state * jsp = &op->json_st;
1743*44704f69SBart Van Assche sgj_opaque_p jo2p, jo3p;
1744*44704f69SBart Van Assche sgj_opaque_p jap = NULL;
1745*44704f69SBart Van Assche char b[64];
1746*44704f69SBart Van Assche static const char * slpass = "Supported log pages and subpages";
1747*44704f69SBart Van Assche static const char * sss = "Supported subpages";
1748*44704f69SBart Van Assche
1749*44704f69SBart Van Assche if (op->verbose || ((! op->do_raw) && (0 == op->do_hex))) {
1750*44704f69SBart Van Assche if (op->pg_code > 0)
1751*44704f69SBart Van Assche sgj_pr_hr(jsp, "%s [0x%x, 0xff]:\n", sss, op->pg_code);
1752*44704f69SBart Van Assche else
1753*44704f69SBart Van Assche sgj_pr_hr(jsp, "%s [0x0, 0xff]:\n", sss);
1754*44704f69SBart Van Assche }
1755*44704f69SBart Van Assche num = len - 4;
1756*44704f69SBart Van Assche bp = &resp[0] + 4;
1757*44704f69SBart Van Assche if ((op->do_hex > 0) || op->do_raw) {
1758*44704f69SBart Van Assche if (op->do_raw)
1759*44704f69SBart Van Assche dStrRaw(resp, len);
1760*44704f69SBart Van Assche else
1761*44704f69SBart Van Assche hex2stdout(resp, len, op->dstrhex_no_ascii);
1762*44704f69SBart Van Assche return true;
1763*44704f69SBart Van Assche }
1764*44704f69SBart Van Assche if (jsp->pr_as_json) {
1765*44704f69SBart Van Assche if (op->pg_code > 0) {
1766*44704f69SBart Van Assche jo2p = sg_log_js_hdr(jsp, jop, sss, resp);
1767*44704f69SBart Van Assche jap = sgj_named_subarray_r(jsp, jo2p,
1768*44704f69SBart Van Assche "supported_subpage_descriptors");
1769*44704f69SBart Van Assche } else {
1770*44704f69SBart Van Assche jo2p = sg_log_js_hdr(jsp, jop, slpass, resp);
1771*44704f69SBart Van Assche jap = sgj_named_subarray_r(jsp, jo2p,
1772*44704f69SBart Van Assche "supported_page_subpage_descriptors");
1773*44704f69SBart Van Assche }
1774*44704f69SBart Van Assche }
1775*44704f69SBart Van Assche
1776*44704f69SBart Van Assche for (k = 0; k < num; k += 2) {
1777*44704f69SBart Van Assche bool pr_name = true;
1778*44704f69SBart Van Assche int pg_code = bp[k];
1779*44704f69SBart Van Assche int subpg_code = bp[k + 1];
1780*44704f69SBart Van Assche
1781*44704f69SBart Van Assche /* formerly ignored [pg, 0xff] when pg > 0, don't know why */
1782*44704f69SBart Van Assche if (NOT_SPG_SUBPG == subpg_code)
1783*44704f69SBart Van Assche snprintf(b, sizeof(b) - 1, " 0x%02x ", pg_code);
1784*44704f69SBart Van Assche else
1785*44704f69SBart Van Assche snprintf(b, sizeof(b) - 1, " 0x%02x,0x%02x ", pg_code,
1786*44704f69SBart Van Assche subpg_code);
1787*44704f69SBart Van Assche if ((pg_code > 0) && (subpg_code == 0xff)) {
1788*44704f69SBart Van Assche sgj_pr_hr(jsp, "%s\n", b);
1789*44704f69SBart Van Assche pr_name = false;
1790*44704f69SBart Van Assche } else {
1791*44704f69SBart Van Assche lep = pg_subpg_pdt_search(pg_code, subpg_code, op->dev_pdt, -1);
1792*44704f69SBart Van Assche if (lep) {
1793*44704f69SBart Van Assche if (op->do_brief > 1)
1794*44704f69SBart Van Assche sgj_pr_hr(jsp, " %s\n", lep->name);
1795*44704f69SBart Van Assche else if (op->do_brief)
1796*44704f69SBart Van Assche sgj_pr_hr(jsp, "%s%s\n", b, lep->name);
1797*44704f69SBart Van Assche else
1798*44704f69SBart Van Assche sgj_pr_hr(jsp, "%s%s [%s]\n", b, lep->name, lep->acron);
1799*44704f69SBart Van Assche } else
1800*44704f69SBart Van Assche sgj_pr_hr(jsp, "%s\n", b);
1801*44704f69SBart Van Assche }
1802*44704f69SBart Van Assche if (jsp->pr_as_json) {
1803*44704f69SBart Van Assche jo3p = sgj_new_unattached_object_r(jsp);
1804*44704f69SBart Van Assche sgj_js_nv_ihex(jsp, jo3p, "page_code", pg_code);
1805*44704f69SBart Van Assche sgj_js_nv_ihex(jsp, jo3p, "subpage_code", subpg_code);
1806*44704f69SBart Van Assche if (pr_name) {
1807*44704f69SBart Van Assche sgj_js_nv_s(jsp, jo3p, "name", lep ? lep->name : unknown_s);
1808*44704f69SBart Van Assche sgj_js_nv_s(jsp, jo3p, "acronym", lep ? lep->acron :
1809*44704f69SBart Van Assche unknown_s);
1810*44704f69SBart Van Assche }
1811*44704f69SBart Van Assche sgj_js_nv_o(jsp, jap, NULL /* name */, jo3p);
1812*44704f69SBart Van Assche }
1813*44704f69SBart Van Assche }
1814*44704f69SBart Van Assche return true;
1815*44704f69SBart Van Assche }
1816*44704f69SBart Van Assche
1817*44704f69SBart Van Assche /* BUFF_OVER_UNDER_LPAGE [0x1] <bou> introduced: SPC-2 */
1818*44704f69SBart Van Assche static bool
show_buffer_over_under_run_page(const uint8_t * resp,int len,struct opts_t * op,sgj_opaque_p jop)1819*44704f69SBart Van Assche show_buffer_over_under_run_page(const uint8_t * resp, int len,
1820*44704f69SBart Van Assche struct opts_t * op, sgj_opaque_p jop)
1821*44704f69SBart Van Assche {
1822*44704f69SBart Van Assche int num, pl, pc;
1823*44704f69SBart Van Assche uint64_t count;
1824*44704f69SBart Van Assche const uint8_t * bp;
1825*44704f69SBart Van Assche const char * cp;
1826*44704f69SBart Van Assche sgj_state * jsp = &op->json_st;
1827*44704f69SBart Van Assche sgj_opaque_p jo2p;
1828*44704f69SBart Van Assche sgj_opaque_p jo3p = NULL;
1829*44704f69SBart Van Assche sgj_opaque_p jap = NULL;
1830*44704f69SBart Van Assche char str[PCB_STR_LEN];
1831*44704f69SBart Van Assche static const char * bourlp = "Buffer over-run/under-run log page";
1832*44704f69SBart Van Assche static const char * orurc = "over_run_under_run_counter";
1833*44704f69SBart Van Assche
1834*44704f69SBart Van Assche if (op->verbose || ((! op->do_raw) && (0 == op->do_hex)))
1835*44704f69SBart Van Assche sgj_pr_hr(jsp, "%s [0x1]\n", bourlp);
1836*44704f69SBart Van Assche num = len - 4;
1837*44704f69SBart Van Assche bp = &resp[0] + 4;
1838*44704f69SBart Van Assche if (jsp->pr_as_json) {
1839*44704f69SBart Van Assche jo2p = sg_log_js_hdr(jsp, jop, bourlp, resp);
1840*44704f69SBart Van Assche jap = sgj_named_subarray_r(jsp, jo2p,
1841*44704f69SBart Van Assche "buffer_over_run_under_run_log_parameters");
1842*44704f69SBart Van Assche }
1843*44704f69SBart Van Assche while (num > 3) {
1844*44704f69SBart Van Assche cp = NULL;
1845*44704f69SBart Van Assche pl = bp[3] + 4;
1846*44704f69SBart Van Assche count = (pl > 4) ? sg_get_unaligned_be(pl - 4, bp + 4) : 0;
1847*44704f69SBart Van Assche pc = sg_get_unaligned_be16(bp + 0);
1848*44704f69SBart Van Assche if (op->filter_given) {
1849*44704f69SBart Van Assche if (pc != op->filter)
1850*44704f69SBart Van Assche goto skip;
1851*44704f69SBart Van Assche }
1852*44704f69SBart Van Assche if (op->do_raw) {
1853*44704f69SBart Van Assche dStrRaw(bp, pl);
1854*44704f69SBart Van Assche break;
1855*44704f69SBart Van Assche } else if (op->do_hex) {
1856*44704f69SBart Van Assche hex2stdout(bp, pl, op->dstrhex_no_ascii);
1857*44704f69SBart Van Assche break;
1858*44704f69SBart Van Assche }
1859*44704f69SBart Van Assche if (jsp->pr_as_json) {
1860*44704f69SBart Van Assche jo3p = sgj_new_unattached_object_r(jsp);
1861*44704f69SBart Van Assche if (op->do_pcb)
1862*44704f69SBart Van Assche js_pcb(jsp, jo3p, bp[2]);
1863*44704f69SBart Van Assche }
1864*44704f69SBart Van Assche
1865*44704f69SBart Van Assche switch (pc) {
1866*44704f69SBart Van Assche case 0x0:
1867*44704f69SBart Van Assche cp = "under-run";
1868*44704f69SBart Van Assche break;
1869*44704f69SBart Van Assche case 0x1:
1870*44704f69SBart Van Assche cp = "over-run";
1871*44704f69SBart Van Assche break;
1872*44704f69SBart Van Assche case 0x2:
1873*44704f69SBart Van Assche cp = "service delivery subsystem busy, under-run";
1874*44704f69SBart Van Assche break;
1875*44704f69SBart Van Assche case 0x3:
1876*44704f69SBart Van Assche cp = "service delivery subsystem busy, over-run";
1877*44704f69SBart Van Assche break;
1878*44704f69SBart Van Assche case 0x4:
1879*44704f69SBart Van Assche cp = "transfer too slow, under-run";
1880*44704f69SBart Van Assche break;
1881*44704f69SBart Van Assche case 0x5:
1882*44704f69SBart Van Assche cp = "transfer too slow, over-run";
1883*44704f69SBart Van Assche break;
1884*44704f69SBart Van Assche case 0x20:
1885*44704f69SBart Van Assche cp = "command, under-run";
1886*44704f69SBart Van Assche break;
1887*44704f69SBart Van Assche case 0x21:
1888*44704f69SBart Van Assche cp = "command, over-run";
1889*44704f69SBart Van Assche break;
1890*44704f69SBart Van Assche case 0x22:
1891*44704f69SBart Van Assche cp = "command, service delivery subsystem busy, under-run";
1892*44704f69SBart Van Assche break;
1893*44704f69SBart Van Assche case 0x23:
1894*44704f69SBart Van Assche cp = "command, service delivery subsystem busy, over-run";
1895*44704f69SBart Van Assche break;
1896*44704f69SBart Van Assche case 0x24:
1897*44704f69SBart Van Assche cp = "command, transfer too slow, under-run";
1898*44704f69SBart Van Assche break;
1899*44704f69SBart Van Assche case 0x25:
1900*44704f69SBart Van Assche cp = "command, transfer too slow, over-run";
1901*44704f69SBart Van Assche break;
1902*44704f69SBart Van Assche case 0x40:
1903*44704f69SBart Van Assche cp = "I_T nexus, under-run";
1904*44704f69SBart Van Assche break;
1905*44704f69SBart Van Assche case 0x41:
1906*44704f69SBart Van Assche cp = "I_T nexus, over-run";
1907*44704f69SBart Van Assche break;
1908*44704f69SBart Van Assche case 0x42:
1909*44704f69SBart Van Assche cp = "I_T nexus, service delivery subsystem busy, under-run";
1910*44704f69SBart Van Assche break;
1911*44704f69SBart Van Assche case 0x43:
1912*44704f69SBart Van Assche cp = "I_T nexus, service delivery subsystem busy, over-run";
1913*44704f69SBart Van Assche break;
1914*44704f69SBart Van Assche case 0x44:
1915*44704f69SBart Van Assche cp = "I_T nexus, transfer too slow, under-run";
1916*44704f69SBart Van Assche break;
1917*44704f69SBart Van Assche case 0x45:
1918*44704f69SBart Van Assche cp = "I_T nexus, transfer too slow, over-run";
1919*44704f69SBart Van Assche break;
1920*44704f69SBart Van Assche case 0x80:
1921*44704f69SBart Van Assche cp = "time, under-run";
1922*44704f69SBart Van Assche break;
1923*44704f69SBart Van Assche case 0x81:
1924*44704f69SBart Van Assche cp = "time, over-run";
1925*44704f69SBart Van Assche break;
1926*44704f69SBart Van Assche case 0x82:
1927*44704f69SBart Van Assche cp = "time, service delivery subsystem busy, under-run";
1928*44704f69SBart Van Assche break;
1929*44704f69SBart Van Assche case 0x83:
1930*44704f69SBart Van Assche cp = "time, service delivery subsystem busy, over-run";
1931*44704f69SBart Van Assche break;
1932*44704f69SBart Van Assche case 0x84:
1933*44704f69SBart Van Assche cp = "time, transfer too slow, under-run";
1934*44704f69SBart Van Assche break;
1935*44704f69SBart Van Assche case 0x85:
1936*44704f69SBart Van Assche cp = "time, transfer too slow, over-run";
1937*44704f69SBart Van Assche break;
1938*44704f69SBart Van Assche default:
1939*44704f69SBart Van Assche pr2serr(" undefined %s [0x%x], count = %" PRIu64 "\n",
1940*44704f69SBart Van Assche param_c, pc, count);
1941*44704f69SBart Van Assche break;
1942*44704f69SBart Van Assche }
1943*44704f69SBart Van Assche sgj_js_nv_ihex(jsp, jo3p, param_c_sn, pc);
1944*44704f69SBart Van Assche sgj_pr_hr(jsp, " %s=0x%x\n", param_c, pc);
1945*44704f69SBart Van Assche if (cp) {
1946*44704f69SBart Van Assche sgj_pr_hr(jsp, " %s = %" PRIu64 "\n", cp, count);
1947*44704f69SBart Van Assche js_snakenv_ihexstr_nex(jsp, jo3p, param_c, pc, true,
1948*44704f69SBart Van Assche NULL, cp, NULL);
1949*44704f69SBart Van Assche sgj_js_nv_ihex(jsp, jo3p, orurc, count);
1950*44704f69SBart Van Assche } else
1951*44704f69SBart Van Assche sgj_pr_hr(jsp, " counter = %" PRIu64 "\n", count);
1952*44704f69SBart Van Assche
1953*44704f69SBart Van Assche if (op->do_pcb)
1954*44704f69SBart Van Assche sgj_pr_hr(jsp, " <%s>\n", get_pcb_str(bp[2],
1955*44704f69SBart Van Assche str, sizeof(str)));
1956*44704f69SBart Van Assche if (jsp->pr_as_json)
1957*44704f69SBart Van Assche sgj_js_nv_o(jsp, jap, NULL /* name */, jo3p);
1958*44704f69SBart Van Assche if (op->filter_given)
1959*44704f69SBart Van Assche break;
1960*44704f69SBart Van Assche skip:
1961*44704f69SBart Van Assche num -= pl;
1962*44704f69SBart Van Assche bp += pl;
1963*44704f69SBart Van Assche }
1964*44704f69SBart Van Assche return true;
1965*44704f69SBart Van Assche }
1966*44704f69SBart Van Assche
1967*44704f69SBart Van Assche /* WRITE_ERR_LPAGE; READ_ERR_LPAGE; READ_REV_ERR_LPAGE; VERIFY_ERR_LPAGE */
1968*44704f69SBart Van Assche /* [0x2, 0x3, 0x4, 0x5] <we, re, rre, ve> introduced: SPC-3 */
1969*44704f69SBart Van Assche static bool
show_error_counter_page(const uint8_t * resp,int len,struct opts_t * op,sgj_opaque_p jop)1970*44704f69SBart Van Assche show_error_counter_page(const uint8_t * resp, int len,
1971*44704f69SBart Van Assche struct opts_t * op, sgj_opaque_p jop)
1972*44704f69SBart Van Assche {
1973*44704f69SBart Van Assche bool skip_out = false;
1974*44704f69SBart Van Assche bool evsm_output = false;
1975*44704f69SBart Van Assche int n, num, pl, pc, pg_code;
1976*44704f69SBart Van Assche uint64_t val;
1977*44704f69SBart Van Assche const uint8_t * bp;
1978*44704f69SBart Van Assche const char * pg_cp = NULL;
1979*44704f69SBart Van Assche const char * par_cp = NULL;
1980*44704f69SBart Van Assche sgj_state * jsp = &op->json_st;
1981*44704f69SBart Van Assche sgj_opaque_p jo2p;
1982*44704f69SBart Van Assche sgj_opaque_p jo3p = NULL;
1983*44704f69SBart Van Assche sgj_opaque_p jap = NULL;
1984*44704f69SBart Van Assche char str[PCB_STR_LEN];
1985*44704f69SBart Van Assche char b[128] SG_C_CPP_ZERO_INIT;
1986*44704f69SBart Van Assche char d[128];
1987*44704f69SBart Van Assche char e[64];
1988*44704f69SBart Van Assche static const char * wec = "Write error counter";
1989*44704f69SBart Van Assche static const char * rec = "Read error counter";
1990*44704f69SBart Van Assche static const char * rrec = "Read reverse error counter";
1991*44704f69SBart Van Assche static const char * vec = "Verify error counter";
1992*44704f69SBart Van Assche
1993*44704f69SBart Van Assche pg_code = resp[0] & 0x3f;
1994*44704f69SBart Van Assche switch(pg_code) {
1995*44704f69SBart Van Assche case WRITE_ERR_LPAGE:
1996*44704f69SBart Van Assche pg_cp = wec;
1997*44704f69SBart Van Assche break;
1998*44704f69SBart Van Assche case READ_ERR_LPAGE:
1999*44704f69SBart Van Assche pg_cp = rec;
2000*44704f69SBart Van Assche break;
2001*44704f69SBart Van Assche case READ_REV_ERR_LPAGE:
2002*44704f69SBart Van Assche pg_cp = rrec;
2003*44704f69SBart Van Assche break;
2004*44704f69SBart Van Assche case VERIFY_ERR_LPAGE:
2005*44704f69SBart Van Assche pg_cp = vec;
2006*44704f69SBart Van Assche break;
2007*44704f69SBart Van Assche default:
2008*44704f69SBart Van Assche pr2serr("expecting error counter page, got page = 0x%x\n",
2009*44704f69SBart Van Assche pg_code);
2010*44704f69SBart Van Assche return false;
2011*44704f69SBart Van Assche }
2012*44704f69SBart Van Assche if (op->verbose || ((! op->do_raw) && (0 == op->do_hex)))
2013*44704f69SBart Van Assche sgj_pr_hr(jsp, "%s log page [0x%x]\n", pg_cp, pg_code);
2014*44704f69SBart Van Assche if (jsp->pr_as_json) {
2015*44704f69SBart Van Assche n = strlen(pg_cp);
2016*44704f69SBart Van Assche memcpy(b, pg_cp, n);
2017*44704f69SBart Van Assche memcpy(b + n, " log", 4);
2018*44704f69SBart Van Assche n = strlen(b);
2019*44704f69SBart Van Assche memcpy(b + n, " page", 5);
2020*44704f69SBart Van Assche jo2p = sg_log_js_hdr(jsp, jop, b, resp);
2021*44704f69SBart Van Assche memcpy(b + n, " parameters", 11);
2022*44704f69SBart Van Assche sgj_convert_to_snake_name(b, d, sizeof(d) - 1);
2023*44704f69SBart Van Assche jap = sgj_named_subarray_r(jsp, jo2p, d);
2024*44704f69SBart Van Assche }
2025*44704f69SBart Van Assche num = len - 4;
2026*44704f69SBart Van Assche bp = &resp[0] + 4;
2027*44704f69SBart Van Assche while (num > 3) {
2028*44704f69SBart Van Assche pc = sg_get_unaligned_be16(bp + 0);
2029*44704f69SBart Van Assche pl = bp[3] + 4;
2030*44704f69SBart Van Assche if (op->filter_given) {
2031*44704f69SBart Van Assche if (pc != op->filter)
2032*44704f69SBart Van Assche goto skip;
2033*44704f69SBart Van Assche }
2034*44704f69SBart Van Assche if (op->do_raw) {
2035*44704f69SBart Van Assche dStrRaw(bp, pl);
2036*44704f69SBart Van Assche break;
2037*44704f69SBart Van Assche } else if (op->do_hex) {
2038*44704f69SBart Van Assche hex2stdout(bp, pl, op->dstrhex_no_ascii);
2039*44704f69SBart Van Assche break;
2040*44704f69SBart Van Assche }
2041*44704f69SBart Van Assche if (jsp->pr_as_json) {
2042*44704f69SBart Van Assche jo3p = sgj_new_unattached_object_r(jsp);
2043*44704f69SBart Van Assche if (op->do_pcb)
2044*44704f69SBart Van Assche js_pcb(jsp, jo3p, bp[2]);
2045*44704f69SBart Van Assche }
2046*44704f69SBart Van Assche
2047*44704f69SBart Van Assche par_cp = NULL;
2048*44704f69SBart Van Assche switch (pc) {
2049*44704f69SBart Van Assche case 0:
2050*44704f69SBart Van Assche par_cp = "Errors corrected without substantial delay";
2051*44704f69SBart Van Assche break;
2052*44704f69SBart Van Assche case 1:
2053*44704f69SBart Van Assche par_cp = "Errors corrected with possible delays";
2054*44704f69SBart Van Assche break;
2055*44704f69SBart Van Assche case 2:
2056*44704f69SBart Van Assche par_cp = "Total rewrites or rereads";
2057*44704f69SBart Van Assche break;
2058*44704f69SBart Van Assche case 3:
2059*44704f69SBart Van Assche par_cp = "Total errors corrected";
2060*44704f69SBart Van Assche break;
2061*44704f69SBart Van Assche case 4:
2062*44704f69SBart Van Assche par_cp = "Total times correction algorithm processed";
2063*44704f69SBart Van Assche break;
2064*44704f69SBart Van Assche case 5:
2065*44704f69SBart Van Assche par_cp = "Total bytes processed";
2066*44704f69SBart Van Assche break;
2067*44704f69SBart Van Assche case 6:
2068*44704f69SBart Van Assche par_cp = "Total uncorrected errors";
2069*44704f69SBart Van Assche break;
2070*44704f69SBart Van Assche default:
2071*44704f69SBart Van Assche if (op->exclude_vendor) {
2072*44704f69SBart Van Assche skip_out = true;
2073*44704f69SBart Van Assche if ((op->verbose > 0) && (0 == op->do_brief) &&
2074*44704f69SBart Van Assche (! evsm_output)) {
2075*44704f69SBart Van Assche evsm_output = true;
2076*44704f69SBart Van Assche pr2serr(" %s parameter(s) being ignored\n", vend_spec);
2077*44704f69SBart Van Assche }
2078*44704f69SBart Van Assche } else {
2079*44704f69SBart Van Assche if (0x8009 == pc)
2080*44704f69SBart Van Assche par_cp = "Track following errors [Hitachi]";
2081*44704f69SBart Van Assche else if (0x8015 == pc)
2082*44704f69SBart Van Assche par_cp = "Positioning errors [Hitachi]";
2083*44704f69SBart Van Assche else {
2084*44704f69SBart Van Assche snprintf(e, sizeof(e), "Reserved or %s [0x%x]", vend_spec,
2085*44704f69SBart Van Assche pc);
2086*44704f69SBart Van Assche par_cp = e;
2087*44704f69SBart Van Assche }
2088*44704f69SBart Van Assche }
2089*44704f69SBart Van Assche break;
2090*44704f69SBart Van Assche }
2091*44704f69SBart Van Assche
2092*44704f69SBart Van Assche if (skip_out)
2093*44704f69SBart Van Assche skip_out = false;
2094*44704f69SBart Van Assche else if (par_cp) {
2095*44704f69SBart Van Assche val = sg_get_unaligned_be(pl - 4, bp + 4);
2096*44704f69SBart Van Assche if (val > ((uint64_t)1 << 40))
2097*44704f69SBart Van Assche snprintf(d, sizeof(d), "%" PRIu64 " [%" PRIu64 " TB]",
2098*44704f69SBart Van Assche val, (val / (1000UL * 1000 * 1000 * 1000)));
2099*44704f69SBart Van Assche else if (val > ((uint64_t)1 << 30))
2100*44704f69SBart Van Assche snprintf(d, sizeof(d), "%" PRIu64 " [%" PRIu64 " GB]",
2101*44704f69SBart Van Assche val, (val / (1000UL * 1000 * 1000)));
2102*44704f69SBart Van Assche else
2103*44704f69SBart Van Assche snprintf(d, sizeof(d), "%" PRIu64, val);
2104*44704f69SBart Van Assche sgj_pr_hr(jsp, " %s = %s\n", par_cp, d);
2105*44704f69SBart Van Assche if (jsp->pr_as_json) {
2106*44704f69SBart Van Assche js_snakenv_ihexstr_nex(jsp, jo3p, param_c, pc, true,
2107*44704f69SBart Van Assche NULL, par_cp, NULL);
2108*44704f69SBart Van Assche sgj_convert_to_snake_name(pg_cp, e, sizeof(e) - 1);
2109*44704f69SBart Van Assche n = strlen(e);
2110*44704f69SBart Van Assche memcpy(e + n, "_counter", 9); /* take trailing null */
2111*44704f69SBart Van Assche sgj_js_nv_ihexstr(jsp, jo3p, e, val, as_s_s, d);
2112*44704f69SBart Van Assche }
2113*44704f69SBart Van Assche }
2114*44704f69SBart Van Assche if (op->do_pcb)
2115*44704f69SBart Van Assche sgj_pr_hr(jsp, " <%s>\n", get_pcb_str(bp[2],
2116*44704f69SBart Van Assche str, sizeof(str)));
2117*44704f69SBart Van Assche if (jsp->pr_as_json)
2118*44704f69SBart Van Assche sgj_js_nv_o(jsp, jap, NULL /* name */, jo3p);
2119*44704f69SBart Van Assche if (op->filter_given)
2120*44704f69SBart Van Assche break;
2121*44704f69SBart Van Assche skip:
2122*44704f69SBart Van Assche num -= pl;
2123*44704f69SBart Van Assche bp += pl;
2124*44704f69SBart Van Assche }
2125*44704f69SBart Van Assche return true;
2126*44704f69SBart Van Assche }
2127*44704f69SBart Van Assche
2128*44704f69SBart Van Assche /* NON_MEDIUM_LPAGE [0x6] <nm> introduced: SPC-2 */
2129*44704f69SBart Van Assche static bool
show_non_medium_error_page(const uint8_t * resp,int len,struct opts_t * op,sgj_opaque_p jop)2130*44704f69SBart Van Assche show_non_medium_error_page(const uint8_t * resp, int len,
2131*44704f69SBart Van Assche struct opts_t * op, sgj_opaque_p jop)
2132*44704f69SBart Van Assche {
2133*44704f69SBart Van Assche bool skip_out = false;
2134*44704f69SBart Van Assche bool evsm_output = false;
2135*44704f69SBart Van Assche int num, pl, pc;
2136*44704f69SBart Van Assche uint64_t count;
2137*44704f69SBart Van Assche const uint8_t * bp;
2138*44704f69SBart Van Assche sgj_state * jsp = &op->json_st;
2139*44704f69SBart Van Assche sgj_opaque_p jo2p;
2140*44704f69SBart Van Assche sgj_opaque_p jo3p = NULL;
2141*44704f69SBart Van Assche sgj_opaque_p jap = NULL;
2142*44704f69SBart Van Assche char str[PCB_STR_LEN];
2143*44704f69SBart Van Assche char b[128] SG_C_CPP_ZERO_INIT;
2144*44704f69SBart Van Assche static const char * nmelp = "Non-medium error log page";
2145*44704f69SBart Van Assche static const char * nmec = "Non-medium error count";
2146*44704f69SBart Van Assche
2147*44704f69SBart Van Assche if (op->verbose || ((! op->do_raw) && (0 == op->do_hex)))
2148*44704f69SBart Van Assche sgj_pr_hr(jsp, "%s [0x6]\n", nmelp);
2149*44704f69SBart Van Assche num = len - 4;
2150*44704f69SBart Van Assche bp = &resp[0] + 4;
2151*44704f69SBart Van Assche if (jsp->pr_as_json) {
2152*44704f69SBart Van Assche jo2p = sg_log_js_hdr(jsp, jop, nmelp, resp);
2153*44704f69SBart Van Assche jap = sgj_named_subarray_r(jsp, jo2p,
2154*44704f69SBart Van Assche "non_medium_error_log_parameters");
2155*44704f69SBart Van Assche }
2156*44704f69SBart Van Assche while (num > 3) {
2157*44704f69SBart Van Assche pc = sg_get_unaligned_be16(bp + 0);
2158*44704f69SBart Van Assche pl = bp[3] + 4;
2159*44704f69SBart Van Assche if (op->filter_given) {
2160*44704f69SBart Van Assche if (pc != op->filter)
2161*44704f69SBart Van Assche goto skip;
2162*44704f69SBart Van Assche }
2163*44704f69SBart Van Assche if (op->do_raw) {
2164*44704f69SBart Van Assche dStrRaw(bp, pl);
2165*44704f69SBart Van Assche break;
2166*44704f69SBart Van Assche } else if (op->do_hex) {
2167*44704f69SBart Van Assche hex2stdout(bp, pl, op->dstrhex_no_ascii);
2168*44704f69SBart Van Assche break;
2169*44704f69SBart Van Assche }
2170*44704f69SBart Van Assche if (jsp->pr_as_json) {
2171*44704f69SBart Van Assche jo3p = sgj_new_unattached_object_r(jsp);
2172*44704f69SBart Van Assche if (op->do_pcb)
2173*44704f69SBart Van Assche js_pcb(jsp, jo3p, bp[2]);
2174*44704f69SBart Van Assche }
2175*44704f69SBart Van Assche
2176*44704f69SBart Van Assche switch (pc) {
2177*44704f69SBart Van Assche case 0:
2178*44704f69SBart Van Assche snprintf(b, sizeof(b), "%s", nmec);
2179*44704f69SBart Van Assche break;
2180*44704f69SBart Van Assche default:
2181*44704f69SBart Van Assche if (pc <= 0x7fff)
2182*44704f69SBart Van Assche snprintf(b, sizeof(b), " Reserved [0x%x]", pc);
2183*44704f69SBart Van Assche else {
2184*44704f69SBart Van Assche if (op->exclude_vendor) {
2185*44704f69SBart Van Assche skip_out = true;
2186*44704f69SBart Van Assche if ((op->verbose > 0) && (0 == op->do_brief) &&
2187*44704f69SBart Van Assche (! evsm_output)) {
2188*44704f69SBart Van Assche evsm_output = true;
2189*44704f69SBart Van Assche pr2serr(" %s parameter(s) being ignored\n",
2190*44704f69SBart Van Assche vend_spec);
2191*44704f69SBart Van Assche }
2192*44704f69SBart Van Assche } else
2193*44704f69SBart Van Assche snprintf(b, sizeof(b), "%s [0x%x]", vend_spec, pc);
2194*44704f69SBart Van Assche }
2195*44704f69SBart Van Assche break;
2196*44704f69SBart Van Assche }
2197*44704f69SBart Van Assche if (skip_out)
2198*44704f69SBart Van Assche skip_out = false;
2199*44704f69SBart Van Assche else {
2200*44704f69SBart Van Assche count = sg_get_unaligned_be(pl - 4, bp + 4);
2201*44704f69SBart Van Assche sgj_pr_hr(jsp, " %s = %" PRIu64 "\n", b, count);
2202*44704f69SBart Van Assche js_snakenv_ihexstr_nex(jsp, jo3p, param_c, pc, true,
2203*44704f69SBart Van Assche NULL, b, NULL);
2204*44704f69SBart Van Assche js_snakenv_ihexstr_nex(jsp, jo3p, nmec, count, true, NULL, NULL,
2205*44704f69SBart Van Assche NULL);
2206*44704f69SBart Van Assche }
2207*44704f69SBart Van Assche if (op->do_pcb)
2208*44704f69SBart Van Assche sgj_pr_hr(jsp, " <%s>\n", get_pcb_str(bp[2],
2209*44704f69SBart Van Assche str, sizeof(str)));
2210*44704f69SBart Van Assche if (jsp->pr_as_json)
2211*44704f69SBart Van Assche sgj_js_nv_o(jsp, jap, NULL /* name */, jo3p);
2212*44704f69SBart Van Assche if (op->filter_given)
2213*44704f69SBart Van Assche break;
2214*44704f69SBart Van Assche skip:
2215*44704f69SBart Van Assche num -= pl;
2216*44704f69SBart Van Assche bp += pl;
2217*44704f69SBart Van Assche }
2218*44704f69SBart Van Assche return true;
2219*44704f69SBart Van Assche }
2220*44704f69SBart Van Assche
2221*44704f69SBart Van Assche /* PCT_LPAGE [0x1a] <pct> introduced: SPC-4 */
2222*44704f69SBart Van Assche static bool
show_power_condition_transitions_page(const uint8_t * resp,int len,struct opts_t * op,sgj_opaque_p jop)2223*44704f69SBart Van Assche show_power_condition_transitions_page(const uint8_t * resp, int len,
2224*44704f69SBart Van Assche struct opts_t * op, sgj_opaque_p jop)
2225*44704f69SBart Van Assche {
2226*44704f69SBart Van Assche bool partial;
2227*44704f69SBart Van Assche int num, pl, pc;
2228*44704f69SBart Van Assche uint64_t count;
2229*44704f69SBart Van Assche const uint8_t * bp;
2230*44704f69SBart Van Assche const char * cp;
2231*44704f69SBart Van Assche sgj_state * jsp = &op->json_st;
2232*44704f69SBart Van Assche sgj_opaque_p jo2p;
2233*44704f69SBart Van Assche sgj_opaque_p jo3p = NULL;
2234*44704f69SBart Van Assche sgj_opaque_p jap = NULL;
2235*44704f69SBart Van Assche char str[PCB_STR_LEN];
2236*44704f69SBart Van Assche char b[128];
2237*44704f69SBart Van Assche char bb[64];
2238*44704f69SBart Van Assche static const char * pctlp = "Power condition transitions log page";
2239*44704f69SBart Van Assche static const char * att = "Accumulated transitions to";
2240*44704f69SBart Van Assche
2241*44704f69SBart Van Assche if (op->verbose || ((! op->do_raw) && (0 == op->do_hex)))
2242*44704f69SBart Van Assche sgj_pr_hr(jsp, "%s [0x1a]\n", pctlp);
2243*44704f69SBart Van Assche num = len - 4;
2244*44704f69SBart Van Assche bp = &resp[0] + 4;
2245*44704f69SBart Van Assche if (jsp->pr_as_json) {
2246*44704f69SBart Van Assche jo2p = sg_log_js_hdr(jsp, jop, pctlp, resp);
2247*44704f69SBart Van Assche jap = sgj_named_subarray_r(jsp, jo2p,
2248*44704f69SBart Van Assche "power_condition_transition_log_parameters");
2249*44704f69SBart Van Assche }
2250*44704f69SBart Van Assche
2251*44704f69SBart Van Assche while (num > 3) {
2252*44704f69SBart Van Assche pc = sg_get_unaligned_be16(bp + 0);
2253*44704f69SBart Van Assche pl = bp[3] + 4;
2254*44704f69SBart Van Assche if (op->filter_given) {
2255*44704f69SBart Van Assche if (pc != op->filter)
2256*44704f69SBart Van Assche goto skip;
2257*44704f69SBart Van Assche }
2258*44704f69SBart Van Assche if (op->do_raw) {
2259*44704f69SBart Van Assche dStrRaw(bp, pl);
2260*44704f69SBart Van Assche break;
2261*44704f69SBart Van Assche } else if (op->do_hex) {
2262*44704f69SBart Van Assche hex2stdout(bp, pl, op->dstrhex_no_ascii);
2263*44704f69SBart Van Assche break;
2264*44704f69SBart Van Assche }
2265*44704f69SBart Van Assche if (jsp->pr_as_json) {
2266*44704f69SBart Van Assche jo3p = sgj_new_unattached_object_r(jsp);
2267*44704f69SBart Van Assche if (op->do_pcb)
2268*44704f69SBart Van Assche js_pcb(jsp, jo3p, bp[2]);
2269*44704f69SBart Van Assche }
2270*44704f69SBart Van Assche
2271*44704f69SBart Van Assche cp = NULL;
2272*44704f69SBart Van Assche partial = true;
2273*44704f69SBart Van Assche switch (pc) {
2274*44704f69SBart Van Assche case 1:
2275*44704f69SBart Van Assche cp = "active";
2276*44704f69SBart Van Assche break;
2277*44704f69SBart Van Assche case 2:
2278*44704f69SBart Van Assche cp = "idle_a";
2279*44704f69SBart Van Assche break;
2280*44704f69SBart Van Assche case 3:
2281*44704f69SBart Van Assche cp = "idle_b";
2282*44704f69SBart Van Assche break;
2283*44704f69SBart Van Assche case 4:
2284*44704f69SBart Van Assche cp = "idle_c";
2285*44704f69SBart Van Assche break;
2286*44704f69SBart Van Assche case 8:
2287*44704f69SBart Van Assche cp = "standby_z";
2288*44704f69SBart Van Assche break;
2289*44704f69SBart Van Assche case 9:
2290*44704f69SBart Van Assche cp = "standby_y";
2291*44704f69SBart Van Assche break;
2292*44704f69SBart Van Assche default:
2293*44704f69SBart Van Assche snprintf(bb, sizeof(bb), "Reserved [0x%x]", pc);
2294*44704f69SBart Van Assche cp = bb;
2295*44704f69SBart Van Assche partial = false;
2296*44704f69SBart Van Assche break;
2297*44704f69SBart Van Assche }
2298*44704f69SBart Van Assche if (partial) {
2299*44704f69SBart Van Assche snprintf(b, sizeof(b), "%s %s", att, cp);
2300*44704f69SBart Van Assche cp = b;
2301*44704f69SBart Van Assche }
2302*44704f69SBart Van Assche count = sg_get_unaligned_be(pl - 4, bp + 4);
2303*44704f69SBart Van Assche sgj_pr_hr(jsp, " %s = %" PRIu64 "\n", cp, count);
2304*44704f69SBart Van Assche if (op->do_pcb)
2305*44704f69SBart Van Assche sgj_pr_hr(jsp, " <%s>\n", get_pcb_str(bp[2],
2306*44704f69SBart Van Assche str, sizeof(str)));
2307*44704f69SBart Van Assche if (jsp->pr_as_json) {
2308*44704f69SBart Van Assche js_snakenv_ihexstr_nex(jsp, jo3p, cp, count, true,
2309*44704f69SBart Van Assche NULL, NULL, "saturating counter");
2310*44704f69SBart Van Assche sgj_js_nv_o(jsp, jap, NULL /* name */, jo3p);
2311*44704f69SBart Van Assche }
2312*44704f69SBart Van Assche if (op->filter_given)
2313*44704f69SBart Van Assche break;
2314*44704f69SBart Van Assche skip:
2315*44704f69SBart Van Assche num -= pl;
2316*44704f69SBart Van Assche bp += pl;
2317*44704f69SBart Van Assche }
2318*44704f69SBart Van Assche return true;
2319*44704f69SBart Van Assche }
2320*44704f69SBart Van Assche
2321*44704f69SBart Van Assche static char *
temperature_str(int8_t t,bool reporting,char * b,int blen)2322*44704f69SBart Van Assche temperature_str(int8_t t, bool reporting, char * b, int blen)
2323*44704f69SBart Van Assche {
2324*44704f69SBart Van Assche if (-128 == t) {
2325*44704f69SBart Van Assche if (reporting)
2326*44704f69SBart Van Assche snprintf(b, blen, "%s", not_avail);
2327*44704f69SBart Van Assche else
2328*44704f69SBart Van Assche snprintf(b, blen, "no limit");
2329*44704f69SBart Van Assche } else
2330*44704f69SBart Van Assche snprintf(b, blen, "%d C", t);
2331*44704f69SBart Van Assche return b;
2332*44704f69SBart Van Assche }
2333*44704f69SBart Van Assche
2334*44704f69SBart Van Assche static char *
humidity_str(uint8_t h,bool reporting,char * b,int blen)2335*44704f69SBart Van Assche humidity_str(uint8_t h, bool reporting, char * b, int blen)
2336*44704f69SBart Van Assche {
2337*44704f69SBart Van Assche if (255 == h) {
2338*44704f69SBart Van Assche if (reporting)
2339*44704f69SBart Van Assche snprintf(b, blen, "%s", not_avail);
2340*44704f69SBart Van Assche else
2341*44704f69SBart Van Assche snprintf(b, blen, "no limit");
2342*44704f69SBart Van Assche } else if (h <= 100)
2343*44704f69SBart Van Assche snprintf(b, blen, "%u %%", h);
2344*44704f69SBart Van Assche else
2345*44704f69SBart Van Assche snprintf(b, blen, "%s value [%u]", rsv_s, h);
2346*44704f69SBart Van Assche return b;
2347*44704f69SBart Van Assche }
2348*44704f69SBart Van Assche
2349*44704f69SBart Van Assche /* ENV_REPORTING_SUBPG [0xd,0x1] <env> introduced: SPC-5 (rev 02). "mounted"
2350*44704f69SBart Van Assche * changed to "other" in spc5r11 */
2351*44704f69SBart Van Assche static bool
show_environmental_reporting_page(const uint8_t * resp,int len,struct opts_t * op,sgj_opaque_p jop)2352*44704f69SBart Van Assche show_environmental_reporting_page(const uint8_t * resp, int len,
2353*44704f69SBart Van Assche struct opts_t * op, sgj_opaque_p jop)
2354*44704f69SBart Van Assche {
2355*44704f69SBart Van Assche int num, pl, pc, blen;
2356*44704f69SBart Van Assche bool other_valid;
2357*44704f69SBart Van Assche const uint8_t * bp;
2358*44704f69SBart Van Assche sgj_state * jsp = &op->json_st;
2359*44704f69SBart Van Assche sgj_opaque_p jo2p;
2360*44704f69SBart Van Assche sgj_opaque_p jo3p = NULL;
2361*44704f69SBart Van Assche sgj_opaque_p jap = NULL;
2362*44704f69SBart Van Assche char str[PCB_STR_LEN];
2363*44704f69SBart Van Assche char b[32];
2364*44704f69SBart Van Assche static const char * erlp = "Environmental reporting log page";
2365*44704f69SBart Van Assche static const char * temp = "Temperature";
2366*44704f69SBart Van Assche static const char * lmaxt = "Lifetime maximum temperature";
2367*44704f69SBart Van Assche static const char * lmint = "Lifetime minimum temperature";
2368*44704f69SBart Van Assche static const char * maxtspo = "Maximum temperature since power on";
2369*44704f69SBart Van Assche static const char * mintspo = "Minimum temperature since power on";
2370*44704f69SBart Van Assche static const char * maxot = "Maximum other temperature";
2371*44704f69SBart Van Assche static const char * minot = "Minimum other temperature";
2372*44704f69SBart Van Assche static const char * relhum = "Relative humidity";
2373*44704f69SBart Van Assche static const char * lmaxrh = "Lifetime maximum relative humidity";
2374*44704f69SBart Van Assche static const char * lminrh = "Lifetime minimum relative humidity";
2375*44704f69SBart Van Assche static const char * maxrhspo = "Maximum relative humidity since power on";
2376*44704f69SBart Van Assche static const char * minrhspo = "Minimum relative humidity since power on";
2377*44704f69SBart Van Assche static const char * maxorh = "Maximum other relative humidity";
2378*44704f69SBart Van Assche static const char * minorh = "Minimum other relative humidity";
2379*44704f69SBart Van Assche
2380*44704f69SBart Van Assche blen = sizeof(b);
2381*44704f69SBart Van Assche if (op->verbose || ((! op->do_raw) && (0 == op->do_hex)))
2382*44704f69SBart Van Assche sgj_pr_hr(jsp, "%s [0xd,0x1]\n", erlp);
2383*44704f69SBart Van Assche if (jsp->pr_as_json) {
2384*44704f69SBart Van Assche jo2p = sg_log_js_hdr(jsp, jop, erlp, resp);
2385*44704f69SBart Van Assche jap = sgj_named_subarray_r(jsp, jo2p,
2386*44704f69SBart Van Assche "environmental_reporting_log_parameters");
2387*44704f69SBart Van Assche }
2388*44704f69SBart Van Assche num = len - 4;
2389*44704f69SBart Van Assche bp = &resp[0] + 4;
2390*44704f69SBart Van Assche while (num > 3) {
2391*44704f69SBart Van Assche pc = sg_get_unaligned_be16(bp + 0);
2392*44704f69SBart Van Assche pl = bp[3] + 4;
2393*44704f69SBart Van Assche if (op->filter_given) {
2394*44704f69SBart Van Assche if (pc != op->filter)
2395*44704f69SBart Van Assche goto skip;
2396*44704f69SBart Van Assche }
2397*44704f69SBart Van Assche if (op->do_raw) {
2398*44704f69SBart Van Assche dStrRaw(bp, pl);
2399*44704f69SBart Van Assche break;
2400*44704f69SBart Van Assche } else if (op->do_hex) {
2401*44704f69SBart Van Assche hex2stdout(bp, pl, op->dstrhex_no_ascii);
2402*44704f69SBart Van Assche break;
2403*44704f69SBart Van Assche }
2404*44704f69SBart Van Assche if (jsp->pr_as_json) {
2405*44704f69SBart Van Assche jo3p = sgj_new_unattached_object_r(jsp);
2406*44704f69SBart Van Assche if (op->do_pcb)
2407*44704f69SBart Van Assche js_pcb(jsp, jo3p, bp[2]);
2408*44704f69SBart Van Assche }
2409*44704f69SBart Van Assche other_valid = !!(bp[4] & 1);
2410*44704f69SBart Van Assche if (pc < 0x100) {
2411*44704f69SBart Van Assche if (pl < 12) {
2412*44704f69SBart Van Assche pr2serr(" <<expect parameter 0x%x to be at least 12 bytes "
2413*44704f69SBart Van Assche "long, got %d, skip>>\n", pc, pl);
2414*44704f69SBart Van Assche goto inner;
2415*44704f69SBart Van Assche }
2416*44704f69SBart Van Assche sgj_pr_hr(jsp, " %s=0x%x\n", param_c, pc);
2417*44704f69SBart Van Assche sgj_js_nv_ihex(jsp, jo3p, param_c_sn, pc);
2418*44704f69SBart Van Assche sgj_pr_hr(jsp, " OTV=%d\n", (int)other_valid);
2419*44704f69SBart Van Assche sgj_js_nv_ihex_nex(jsp, jo3p, "otv", (int)other_valid,
2420*44704f69SBart Van Assche false, "Other Temperature Valid");
2421*44704f69SBart Van Assche
2422*44704f69SBart Van Assche temperature_str(bp[5], true, b, blen);
2423*44704f69SBart Van Assche sgj_pr_hr(jsp, " %s: %s\n", temp, b);
2424*44704f69SBart Van Assche js_snakenv_ihexstr_nex(jsp, jo3p, temp, bp[5], false,
2425*44704f69SBart Van Assche NULL, b, "current [Celsius]");
2426*44704f69SBart Van Assche temperature_str(bp[6], true, b, blen);
2427*44704f69SBart Van Assche sgj_pr_hr(jsp, " %s: %s\n", lmaxt, b);
2428*44704f69SBart Van Assche js_snakenv_ihexstr_nex(jsp, jo3p, lmaxt, bp[6], false,
2429*44704f69SBart Van Assche NULL, b, NULL);
2430*44704f69SBart Van Assche temperature_str(bp[7], true, b, blen);
2431*44704f69SBart Van Assche sgj_pr_hr(jsp, " %s: %s\n", lmint, b);
2432*44704f69SBart Van Assche js_snakenv_ihexstr_nex(jsp, jo3p, lmint, bp[7], false,
2433*44704f69SBart Van Assche NULL, b, NULL);
2434*44704f69SBart Van Assche temperature_str(bp[8], true, b, blen);
2435*44704f69SBart Van Assche sgj_pr_hr(jsp, " %s: %s\n", maxtspo, b);
2436*44704f69SBart Van Assche js_snakenv_ihexstr_nex(jsp, jo3p, maxtspo, bp[8], false,
2437*44704f69SBart Van Assche NULL, b, NULL);
2438*44704f69SBart Van Assche temperature_str(bp[9], true, b, blen);
2439*44704f69SBart Van Assche sgj_pr_hr(jsp, " %s: %s\n", mintspo, b);
2440*44704f69SBart Van Assche js_snakenv_ihexstr_nex(jsp, jo3p, mintspo, bp[9], false,
2441*44704f69SBart Van Assche NULL, b, NULL);
2442*44704f69SBart Van Assche if (other_valid) {
2443*44704f69SBart Van Assche temperature_str(bp[10], true, b, blen);
2444*44704f69SBart Van Assche sgj_pr_hr(jsp, " %s: %s\n", maxot, b);
2445*44704f69SBart Van Assche js_snakenv_ihexstr_nex(jsp, jo3p, maxot, bp[10], false,
2446*44704f69SBart Van Assche NULL, b, NULL);
2447*44704f69SBart Van Assche temperature_str(bp[11], true, b, blen);
2448*44704f69SBart Van Assche sgj_pr_hr(jsp, " %s: %s\n", minot, b);
2449*44704f69SBart Van Assche js_snakenv_ihexstr_nex(jsp, jo3p, minot, bp[11], false,
2450*44704f69SBart Van Assche NULL, b, NULL);
2451*44704f69SBart Van Assche }
2452*44704f69SBart Van Assche } else if (pc < 0x200) {
2453*44704f69SBart Van Assche if (pl < 12) {
2454*44704f69SBart Van Assche pr2serr(" <<expect parameter 0x%x to be at least 12 bytes "
2455*44704f69SBart Van Assche "long, got %d, skip>>\n", pc, pl);
2456*44704f69SBart Van Assche goto inner;
2457*44704f69SBart Van Assche }
2458*44704f69SBart Van Assche sgj_pr_hr(jsp, " %s=0x%x\n", param_c, pc);
2459*44704f69SBart Van Assche sgj_js_nv_ihex(jsp, jo3p, param_c_sn, pc);
2460*44704f69SBart Van Assche sgj_pr_hr(jsp, " ORHV=%d\n", (int)other_valid);
2461*44704f69SBart Van Assche sgj_js_nv_ihex_nex(jsp, jo3p, "orhv", (int)other_valid,
2462*44704f69SBart Van Assche false, "Other Relative Humidity Valid");
2463*44704f69SBart Van Assche
2464*44704f69SBart Van Assche humidity_str(bp[5], true, b, blen);
2465*44704f69SBart Van Assche sgj_pr_hr(jsp, " %s: %s\n", relhum, b);
2466*44704f69SBart Van Assche js_snakenv_ihexstr_nex(jsp, jo3p, relhum, bp[5], false,
2467*44704f69SBart Van Assche NULL, b, NULL);
2468*44704f69SBart Van Assche humidity_str(bp[6], true, b, blen);
2469*44704f69SBart Van Assche sgj_pr_hr(jsp, " %s: %s\n", lmaxrh, b);
2470*44704f69SBart Van Assche js_snakenv_ihexstr_nex(jsp, jo3p, lmaxrh, bp[6], false,
2471*44704f69SBart Van Assche NULL, b, NULL);
2472*44704f69SBart Van Assche humidity_str(bp[7], true, b, blen);
2473*44704f69SBart Van Assche sgj_pr_hr(jsp, " %s: %s\n", lminrh, b);
2474*44704f69SBart Van Assche js_snakenv_ihexstr_nex(jsp, jo3p, lminrh, bp[7], false,
2475*44704f69SBart Van Assche NULL, b, NULL);
2476*44704f69SBart Van Assche humidity_str(bp[8], true, b, blen);
2477*44704f69SBart Van Assche sgj_pr_hr(jsp, " %s: %s\n", maxrhspo, b);
2478*44704f69SBart Van Assche js_snakenv_ihexstr_nex(jsp, jo3p, maxrhspo, bp[8], false,
2479*44704f69SBart Van Assche NULL, b, NULL);
2480*44704f69SBart Van Assche humidity_str(bp[9], true, b, blen);
2481*44704f69SBart Van Assche sgj_pr_hr(jsp, " %s: %s\n", minrhspo, b);
2482*44704f69SBart Van Assche js_snakenv_ihexstr_nex(jsp, jo3p, minrhspo, bp[9], false,
2483*44704f69SBart Van Assche NULL, b, NULL);
2484*44704f69SBart Van Assche if (other_valid) {
2485*44704f69SBart Van Assche humidity_str(bp[10], true, b, blen);
2486*44704f69SBart Van Assche sgj_pr_hr(jsp, " %s: %s\n", maxorh, b);
2487*44704f69SBart Van Assche js_snakenv_ihexstr_nex(jsp, jo3p, maxorh, bp[10], false,
2488*44704f69SBart Van Assche NULL, b, NULL);
2489*44704f69SBart Van Assche humidity_str(bp[11], true, b, blen);
2490*44704f69SBart Van Assche sgj_pr_hr(jsp, " %s: %s\n", minorh, b);
2491*44704f69SBart Van Assche js_snakenv_ihexstr_nex(jsp, jo3p, minorh, bp[11], false,
2492*44704f69SBart Van Assche NULL, b, NULL);
2493*44704f69SBart Van Assche }
2494*44704f69SBart Van Assche } else
2495*44704f69SBart Van Assche sgj_pr_hr(jsp, " <<unexpected %s 0x%x\n", param_c, pc);
2496*44704f69SBart Van Assche if (op->do_pcb)
2497*44704f69SBart Van Assche sgj_pr_hr(jsp, " <%s>\n", get_pcb_str(bp[2], str,
2498*44704f69SBart Van Assche sizeof(str)));
2499*44704f69SBart Van Assche inner:
2500*44704f69SBart Van Assche if (jsp->pr_as_json)
2501*44704f69SBart Van Assche sgj_js_nv_o(jsp, jap, NULL /* name */, jo3p);
2502*44704f69SBart Van Assche if (op->filter_given)
2503*44704f69SBart Van Assche break;
2504*44704f69SBart Van Assche skip:
2505*44704f69SBart Van Assche num -= pl;
2506*44704f69SBart Van Assche bp += pl;
2507*44704f69SBart Van Assche }
2508*44704f69SBart Van Assche return true;
2509*44704f69SBart Van Assche }
2510*44704f69SBart Van Assche
2511*44704f69SBart Van Assche /* ENV_LIMITS_SUBPG [0xd,0x2] <enl> introduced: SPC-5 (rev 02) */
2512*44704f69SBart Van Assche static bool
show_environmental_limits_page(const uint8_t * resp,int len,struct opts_t * op,sgj_opaque_p jop)2513*44704f69SBart Van Assche show_environmental_limits_page(const uint8_t * resp, int len,
2514*44704f69SBart Van Assche struct opts_t * op, sgj_opaque_p jop)
2515*44704f69SBart Van Assche {
2516*44704f69SBart Van Assche int num, pl, pc, blen;
2517*44704f69SBart Van Assche const uint8_t * bp;
2518*44704f69SBart Van Assche sgj_state * jsp = &op->json_st;
2519*44704f69SBart Van Assche sgj_opaque_p jo2p;
2520*44704f69SBart Van Assche sgj_opaque_p jo3p = NULL;
2521*44704f69SBart Van Assche sgj_opaque_p jap = NULL;
2522*44704f69SBart Van Assche char str[PCB_STR_LEN];
2523*44704f69SBart Van Assche char b[32];
2524*44704f69SBart Van Assche static const char * ellp = "Environmental limits log page";
2525*44704f69SBart Van Assche static const char * hctlt = "High critical temperature limit trigger";
2526*44704f69SBart Van Assche static const char * hctlr = "High critical temperature limit reset";
2527*44704f69SBart Van Assche static const char * lctlr = "High critical temperature limit reset";
2528*44704f69SBart Van Assche static const char * lctlt = "High critical temperature limit trigger";
2529*44704f69SBart Van Assche static const char * hotlt = "High operating temperature limit trigger";
2530*44704f69SBart Van Assche static const char * hotlr = "High operating temperature limit reset";
2531*44704f69SBart Van Assche static const char * lotlr = "High operating temperature limit reset";
2532*44704f69SBart Van Assche static const char * lotlt = "High operating temperature limit trigger";
2533*44704f69SBart Van Assche static const char * hcrhlt =
2534*44704f69SBart Van Assche "High critical relative humidity limit trigger";
2535*44704f69SBart Van Assche static const char * hcrhlr =
2536*44704f69SBart Van Assche "High critical relative humidity limit reset";
2537*44704f69SBart Van Assche static const char * lcrhlr =
2538*44704f69SBart Van Assche "High critical relative humidity limit reset";
2539*44704f69SBart Van Assche static const char * lcrhlt =
2540*44704f69SBart Van Assche "High critical relative humidity limit trigger";
2541*44704f69SBart Van Assche static const char * horhlt =
2542*44704f69SBart Van Assche "High operating relative humidity limit trigger";
2543*44704f69SBart Van Assche static const char * horhlr =
2544*44704f69SBart Van Assche "High operating relative humidity limit reset";
2545*44704f69SBart Van Assche static const char * lorhlr =
2546*44704f69SBart Van Assche "High operating relative humidity limit reset";
2547*44704f69SBart Van Assche static const char * lorhlt =
2548*44704f69SBart Van Assche "High operating relative humidity limit trigger";
2549*44704f69SBart Van Assche
2550*44704f69SBart Van Assche blen = sizeof(b);
2551*44704f69SBart Van Assche if (op->verbose || ((! op->do_raw) && (0 == op->do_hex)))
2552*44704f69SBart Van Assche sgj_pr_hr(jsp, "%s [0xd,0x2]\n", ellp);
2553*44704f69SBart Van Assche if (jsp->pr_as_json) {
2554*44704f69SBart Van Assche jo2p = sg_log_js_hdr(jsp, jop, ellp, resp);
2555*44704f69SBart Van Assche jap = sgj_named_subarray_r(jsp, jo2p,
2556*44704f69SBart Van Assche "environmental_limits_log_parameters");
2557*44704f69SBart Van Assche }
2558*44704f69SBart Van Assche num = len - 4;
2559*44704f69SBart Van Assche bp = &resp[0] + 4;
2560*44704f69SBart Van Assche while (num > 3) {
2561*44704f69SBart Van Assche pc = sg_get_unaligned_be16(bp + 0);
2562*44704f69SBart Van Assche pl = bp[3] + 4;
2563*44704f69SBart Van Assche if (op->filter_given) {
2564*44704f69SBart Van Assche if (pc != op->filter)
2565*44704f69SBart Van Assche goto skip;
2566*44704f69SBart Van Assche }
2567*44704f69SBart Van Assche if (op->do_raw) {
2568*44704f69SBart Van Assche dStrRaw(bp, pl);
2569*44704f69SBart Van Assche break;
2570*44704f69SBart Van Assche } else if (op->do_hex) {
2571*44704f69SBart Van Assche hex2stdout(bp, pl, op->dstrhex_no_ascii);
2572*44704f69SBart Van Assche break;
2573*44704f69SBart Van Assche }
2574*44704f69SBart Van Assche if (jsp->pr_as_json) {
2575*44704f69SBart Van Assche jo3p = sgj_new_unattached_object_r(jsp);
2576*44704f69SBart Van Assche if (op->do_pcb)
2577*44704f69SBart Van Assche js_pcb(jsp, jo3p, bp[2]);
2578*44704f69SBart Van Assche }
2579*44704f69SBart Van Assche if (pc < 0x100) {
2580*44704f69SBart Van Assche if (pl < 12) {
2581*44704f69SBart Van Assche pr2serr(" <<expect parameter 0x%x to be at least 12 bytes "
2582*44704f69SBart Van Assche "long, got %d, skip>>\n", pc, pl);
2583*44704f69SBart Van Assche goto inner;
2584*44704f69SBart Van Assche }
2585*44704f69SBart Van Assche sgj_pr_hr(jsp, " %s=0x%x\n", param_c, pc);
2586*44704f69SBart Van Assche sgj_js_nv_ihex(jsp, jo3p, param_c_sn, pc);
2587*44704f69SBart Van Assche
2588*44704f69SBart Van Assche temperature_str(bp[4], true, b, blen);
2589*44704f69SBart Van Assche sgj_pr_hr(jsp, " %s: %s\n", hctlt, b);
2590*44704f69SBart Van Assche js_snakenv_ihexstr_nex(jsp, jo3p, hctlt, bp[4], false,
2591*44704f69SBart Van Assche NULL, b, "[Celsius]");
2592*44704f69SBart Van Assche temperature_str(bp[5], true, b, blen);
2593*44704f69SBart Van Assche sgj_pr_hr(jsp, " %s: %s\n", hctlr, b);
2594*44704f69SBart Van Assche js_snakenv_ihexstr_nex(jsp, jo3p, hctlr, bp[5], false,
2595*44704f69SBart Van Assche NULL, b, NULL);
2596*44704f69SBart Van Assche temperature_str(bp[6], true, b, blen);
2597*44704f69SBart Van Assche sgj_pr_hr(jsp, " %s: %s\n", lctlr, b);
2598*44704f69SBart Van Assche js_snakenv_ihexstr_nex(jsp, jo3p, lctlr, bp[6], false,
2599*44704f69SBart Van Assche NULL, b, NULL);
2600*44704f69SBart Van Assche temperature_str(bp[7], true, b, blen);
2601*44704f69SBart Van Assche sgj_pr_hr(jsp, " %s: %s\n", lctlt, b);
2602*44704f69SBart Van Assche js_snakenv_ihexstr_nex(jsp, jo3p, lctlt, bp[7], false,
2603*44704f69SBart Van Assche NULL, b, NULL);
2604*44704f69SBart Van Assche temperature_str(bp[8], true, b, blen);
2605*44704f69SBart Van Assche sgj_pr_hr(jsp, " %s: %s\n", hotlt, b);
2606*44704f69SBart Van Assche js_snakenv_ihexstr_nex(jsp, jo3p, hotlt, bp[8], false,
2607*44704f69SBart Van Assche NULL, b, NULL);
2608*44704f69SBart Van Assche temperature_str(bp[9], true, b, blen);
2609*44704f69SBart Van Assche sgj_pr_hr(jsp, " %s: %s\n", hotlr, b);
2610*44704f69SBart Van Assche js_snakenv_ihexstr_nex(jsp, jo3p, hotlr, bp[9], false,
2611*44704f69SBart Van Assche NULL, b, NULL);
2612*44704f69SBart Van Assche temperature_str(bp[10], true, b, blen);
2613*44704f69SBart Van Assche sgj_pr_hr(jsp, " %s: %s\n", lotlr, b);
2614*44704f69SBart Van Assche js_snakenv_ihexstr_nex(jsp, jo3p, lotlr, bp[10], false,
2615*44704f69SBart Van Assche NULL, b, NULL);
2616*44704f69SBart Van Assche temperature_str(bp[11], true, b, blen);
2617*44704f69SBart Van Assche sgj_pr_hr(jsp, " %s: %s\n", lotlt, b);
2618*44704f69SBart Van Assche js_snakenv_ihexstr_nex(jsp, jo3p, lotlt, bp[11], false,
2619*44704f69SBart Van Assche NULL, b, NULL);
2620*44704f69SBart Van Assche } else if (pc < 0x200) {
2621*44704f69SBart Van Assche if (pl < 12) {
2622*44704f69SBart Van Assche pr2serr(" <<expect parameter 0x%x to be at least 12 bytes "
2623*44704f69SBart Van Assche "long, got %d, skip>>\n", pc, pl);
2624*44704f69SBart Van Assche goto inner;
2625*44704f69SBart Van Assche }
2626*44704f69SBart Van Assche sgj_pr_hr(jsp, " %s=0x%x\n", param_c, pc);
2627*44704f69SBart Van Assche sgj_js_nv_ihex(jsp, jo3p, param_c_sn, pc);
2628*44704f69SBart Van Assche
2629*44704f69SBart Van Assche humidity_str(bp[4], true, b, blen);
2630*44704f69SBart Van Assche sgj_pr_hr(jsp, " %s: %s\n", hcrhlt, b);
2631*44704f69SBart Van Assche js_snakenv_ihexstr_nex(jsp, jo3p, hcrhlt, bp[4], false,
2632*44704f69SBart Van Assche NULL, b, "[percentage]");
2633*44704f69SBart Van Assche humidity_str(bp[5], true, b, blen);
2634*44704f69SBart Van Assche sgj_pr_hr(jsp, " %s: %s\n", hcrhlr, b);
2635*44704f69SBart Van Assche js_snakenv_ihexstr_nex(jsp, jo3p, hcrhlr, bp[5], false,
2636*44704f69SBart Van Assche NULL, b, NULL);
2637*44704f69SBart Van Assche humidity_str(bp[6], true, b, blen);
2638*44704f69SBart Van Assche sgj_pr_hr(jsp, " %s: %s\n", lcrhlr, b);
2639*44704f69SBart Van Assche js_snakenv_ihexstr_nex(jsp, jo3p, lcrhlr, bp[6], false,
2640*44704f69SBart Van Assche NULL, b, NULL);
2641*44704f69SBart Van Assche humidity_str(bp[7], true, b, blen);
2642*44704f69SBart Van Assche sgj_pr_hr(jsp, " %s: %s\n", lcrhlt, b);
2643*44704f69SBart Van Assche js_snakenv_ihexstr_nex(jsp, jo3p, lcrhlt, bp[7], false,
2644*44704f69SBart Van Assche NULL, b, NULL);
2645*44704f69SBart Van Assche humidity_str(bp[8], true, b, blen);
2646*44704f69SBart Van Assche sgj_pr_hr(jsp, " %s: %s\n", horhlt, b);
2647*44704f69SBart Van Assche js_snakenv_ihexstr_nex(jsp, jo3p, horhlt, bp[8], false,
2648*44704f69SBart Van Assche NULL, b, NULL);
2649*44704f69SBart Van Assche humidity_str(bp[9], true, b, blen);
2650*44704f69SBart Van Assche sgj_pr_hr(jsp, " %s: %s\n", horhlr, b);
2651*44704f69SBart Van Assche js_snakenv_ihexstr_nex(jsp, jo3p, horhlr, bp[9], false,
2652*44704f69SBart Van Assche NULL, b, NULL);
2653*44704f69SBart Van Assche humidity_str(bp[10], true, b, blen);
2654*44704f69SBart Van Assche sgj_pr_hr(jsp, " %s: %s\n", lorhlr, b);
2655*44704f69SBart Van Assche js_snakenv_ihexstr_nex(jsp, jo3p, lorhlr, bp[10], false,
2656*44704f69SBart Van Assche NULL, b, NULL);
2657*44704f69SBart Van Assche humidity_str(bp[11], true, b, blen);
2658*44704f69SBart Van Assche sgj_pr_hr(jsp, " %s: %s\n", lorhlt, b);
2659*44704f69SBart Van Assche js_snakenv_ihexstr_nex(jsp, jo3p, lorhlt, bp[11], false,
2660*44704f69SBart Van Assche NULL, b, NULL);
2661*44704f69SBart Van Assche } else
2662*44704f69SBart Van Assche sgj_pr_hr(jsp, " <<unexpected %s 0x%x\n", param_c, pc);
2663*44704f69SBart Van Assche if (op->do_pcb)
2664*44704f69SBart Van Assche sgj_pr_hr(jsp, " <%s>\n", get_pcb_str(bp[2],
2665*44704f69SBart Van Assche str, sizeof(str)));
2666*44704f69SBart Van Assche inner:
2667*44704f69SBart Van Assche if (jsp->pr_as_json)
2668*44704f69SBart Van Assche sgj_js_nv_o(jsp, jap, NULL /* name */, jo3p);
2669*44704f69SBart Van Assche if (op->filter_given)
2670*44704f69SBart Van Assche break;
2671*44704f69SBart Van Assche skip:
2672*44704f69SBart Van Assche num -= pl;
2673*44704f69SBart Van Assche bp += pl;
2674*44704f69SBart Van Assche }
2675*44704f69SBart Van Assche return true;
2676*44704f69SBart Van Assche }
2677*44704f69SBart Van Assche
2678*44704f69SBart Van Assche /* CMD_DUR_LIMITS_SUBPG [0x19,0x21] <cdl>
2679*44704f69SBart Van Assche * introduced: SPC-6 rev 1, significantly changed rev 6 */
2680*44704f69SBart Van Assche static bool
show_cmd_dur_limits_page(const uint8_t * resp,int len,struct opts_t * op,sgj_opaque_p jop)2681*44704f69SBart Van Assche show_cmd_dur_limits_page(const uint8_t * resp, int len,
2682*44704f69SBart Van Assche struct opts_t * op, sgj_opaque_p jop)
2683*44704f69SBart Van Assche {
2684*44704f69SBart Van Assche int num, pl, pc;
2685*44704f69SBart Van Assche uint32_t count, noitmc_v, noatmc_v, noitatmc_v, noc_v;
2686*44704f69SBart Van Assche const uint8_t * bp;
2687*44704f69SBart Van Assche const char * cp;
2688*44704f69SBart Van Assche const char * thp;
2689*44704f69SBart Van Assche sgj_state * jsp = &op->json_st;
2690*44704f69SBart Van Assche sgj_opaque_p jo2p;
2691*44704f69SBart Van Assche sgj_opaque_p jo3p = NULL;
2692*44704f69SBart Van Assche sgj_opaque_p jap = NULL;
2693*44704f69SBart Van Assche char str[PCB_STR_LEN];
2694*44704f69SBart Van Assche char b[144];
2695*44704f69SBart Van Assche static const char * cdllp = "Command duration limits statistics log page";
2696*44704f69SBart Van Assche static const char * t2cdld = "T2 command duration limit descriptor";
2697*44704f69SBart Van Assche static const char * cdlt2amp = "CDL T2A mode page";
2698*44704f69SBart Van Assche static const char * cdlt2bmp = "CDL T2B mode page";
2699*44704f69SBart Van Assche static const char * first_7[] = {"First", "Second", "Third", "Fourth",
2700*44704f69SBart Van Assche "Fifth", "Sixth", "Seventh"};
2701*44704f69SBart Van Assche static const char * noitmc = "Number of inactive target miss commands";
2702*44704f69SBart Van Assche static const char * noatmc = "Number of active target miss commands";
2703*44704f69SBart Van Assche static const char * noitatmc =
2704*44704f69SBart Van Assche "Number of inactive target and active target miss commands";
2705*44704f69SBart Van Assche static const char * noc = "Number of commands";
2706*44704f69SBart Van Assche
2707*44704f69SBart Van Assche if (op->verbose || ((! op->do_raw) && (0 == op->do_hex)))
2708*44704f69SBart Van Assche sgj_pr_hr(jsp, "%s [0x19,0x21]\n", cdllp);
2709*44704f69SBart Van Assche num = len - 4;
2710*44704f69SBart Van Assche bp = &resp[0] + 4;
2711*44704f69SBart Van Assche if (jsp->pr_as_json) {
2712*44704f69SBart Van Assche jo2p = sg_log_js_hdr(jsp, jop, cdllp, resp);
2713*44704f69SBart Van Assche jap = sgj_named_subarray_r(jsp, jo2p,
2714*44704f69SBart Van Assche "command_duration_limits_statistcs_log_parameters");
2715*44704f69SBart Van Assche }
2716*44704f69SBart Van Assche
2717*44704f69SBart Van Assche while (num > 3) {
2718*44704f69SBart Van Assche pc = sg_get_unaligned_be16(bp + 0);
2719*44704f69SBart Van Assche pl = bp[3] + 4; /* parameter length */
2720*44704f69SBart Van Assche if (op->filter_given) {
2721*44704f69SBart Van Assche if (pc != op->filter)
2722*44704f69SBart Van Assche goto skip;
2723*44704f69SBart Van Assche }
2724*44704f69SBart Van Assche if (op->do_raw) {
2725*44704f69SBart Van Assche dStrRaw(bp, pl);
2726*44704f69SBart Van Assche break;
2727*44704f69SBart Van Assche } else if (op->do_hex) {
2728*44704f69SBart Van Assche hex2stdout(bp, pl, op->dstrhex_no_ascii);
2729*44704f69SBart Van Assche break;
2730*44704f69SBart Van Assche }
2731*44704f69SBart Van Assche if (jsp->pr_as_json) {
2732*44704f69SBart Van Assche jo3p = sgj_new_unattached_object_r(jsp);
2733*44704f69SBart Van Assche if (op->do_pcb)
2734*44704f69SBart Van Assche js_pcb(jsp, jo3p, bp[2]);
2735*44704f69SBart Van Assche }
2736*44704f69SBart Van Assche
2737*44704f69SBart Van Assche switch (pc) {
2738*44704f69SBart Van Assche case 0x1:
2739*44704f69SBart Van Assche /* spc6r06: table 349 name "Number of READ commands" seems to
2740*44704f69SBart Van Assche * be wrong. Use what surrounding text and table 347 suggest */
2741*44704f69SBart Van Assche cp = "Achievable latency target";
2742*44704f69SBart Van Assche count = sg_get_unaligned_be32(bp + 4);
2743*44704f69SBart Van Assche sgj_pr_hr(jsp, " %s = %" PRIu32 "\n", cp, count);
2744*44704f69SBart Van Assche if (jsp->pr_as_json) {
2745*44704f69SBart Van Assche sgj_js_nv_ihexstr(jsp, jo3p, param_c_sn, pc, NULL, cp);
2746*44704f69SBart Van Assche js_snakenv_ihexstr_nex(jsp, jop, cp, count, true, NULL, NULL,
2747*44704f69SBart Van Assche "unit: microsecond");
2748*44704f69SBart Van Assche }
2749*44704f69SBart Van Assche break;
2750*44704f69SBart Van Assche case 0x11:
2751*44704f69SBart Van Assche case 0x12:
2752*44704f69SBart Van Assche case 0x13:
2753*44704f69SBart Van Assche case 0x14:
2754*44704f69SBart Van Assche case 0x15:
2755*44704f69SBart Van Assche case 0x16:
2756*44704f69SBart Van Assche case 0x17:
2757*44704f69SBart Van Assche sgj_pr_hr(jsp, " %s code 0x%x restricted\n", param_c, pc);
2758*44704f69SBart Van Assche if (jsp->pr_as_json)
2759*44704f69SBart Van Assche sgj_js_nv_ihexstr(jsp, jo3p, param_c_sn, pc, NULL, rstrict_s);
2760*44704f69SBart Van Assche break;
2761*44704f69SBart Van Assche case 0x21:
2762*44704f69SBart Van Assche case 0x22:
2763*44704f69SBart Van Assche case 0x23:
2764*44704f69SBart Van Assche case 0x24:
2765*44704f69SBart Van Assche case 0x25:
2766*44704f69SBart Van Assche case 0x26:
2767*44704f69SBart Van Assche case 0x27:
2768*44704f69SBart Van Assche thp = first_7[pc - 0x21];
2769*44704f69SBart Van Assche sgj_pr_hr(jsp, " %s %s for %s [pc=0x%x]:\n", thp, t2cdld,
2770*44704f69SBart Van Assche cdlt2amp, pc);
2771*44704f69SBart Van Assche noitmc_v = sg_get_unaligned_be32(bp + 4);
2772*44704f69SBart Van Assche sgj_pr_hr(jsp, " %s = %u\n", noitmc, noitmc_v);
2773*44704f69SBart Van Assche noatmc_v = sg_get_unaligned_be32(bp + 8);
2774*44704f69SBart Van Assche sgj_pr_hr(jsp, " %s = %u\n", noatmc, noatmc_v);
2775*44704f69SBart Van Assche noitatmc_v = sg_get_unaligned_be32(bp + 12);
2776*44704f69SBart Van Assche sgj_pr_hr(jsp, " %s = %u\n", noitatmc, noitatmc_v);
2777*44704f69SBart Van Assche noc_v = sg_get_unaligned_be32(bp + 16);
2778*44704f69SBart Van Assche sgj_pr_hr(jsp, " %s = %u\n", noc, noc_v);
2779*44704f69SBart Van Assche if (jsp->pr_as_json) {
2780*44704f69SBart Van Assche snprintf(b, sizeof(b), "%s %s for %s", thp, t2cdld, cdlt2amp);
2781*44704f69SBart Van Assche sgj_js_nv_ihexstr(jsp, jo3p, param_c_sn, pc, NULL, b);
2782*44704f69SBart Van Assche
2783*44704f69SBart Van Assche js_snakenv_ihexstr_nex(jsp, jop, noitmc, noitmc_v, true, NULL,
2784*44704f69SBart Van Assche NULL, NULL);
2785*44704f69SBart Van Assche js_snakenv_ihexstr_nex(jsp, jop, noatmc, noatmc_v, true, NULL,
2786*44704f69SBart Van Assche NULL, NULL);
2787*44704f69SBart Van Assche js_snakenv_ihexstr_nex(jsp, jop, noitatmc, noitatmc_v, true,
2788*44704f69SBart Van Assche NULL, NULL, NULL);
2789*44704f69SBart Van Assche js_snakenv_ihexstr_nex(jsp, jop, noc, noc_v, true, NULL,
2790*44704f69SBart Van Assche NULL, NULL);
2791*44704f69SBart Van Assche }
2792*44704f69SBart Van Assche break;
2793*44704f69SBart Van Assche case 0x31:
2794*44704f69SBart Van Assche case 0x32:
2795*44704f69SBart Van Assche case 0x33:
2796*44704f69SBart Van Assche case 0x34:
2797*44704f69SBart Van Assche case 0x35:
2798*44704f69SBart Van Assche case 0x36:
2799*44704f69SBart Van Assche case 0x37:
2800*44704f69SBart Van Assche sgj_pr_hr(jsp, " %s 0x%x restricted\n", param_c, pc);
2801*44704f69SBart Van Assche if (jsp->pr_as_json)
2802*44704f69SBart Van Assche sgj_js_nv_ihexstr(jsp, jo3p, param_c_sn, pc, NULL, rstrict_s);
2803*44704f69SBart Van Assche break;
2804*44704f69SBart Van Assche case 0x41:
2805*44704f69SBart Van Assche case 0x42:
2806*44704f69SBart Van Assche case 0x43:
2807*44704f69SBart Van Assche case 0x44:
2808*44704f69SBart Van Assche case 0x45:
2809*44704f69SBart Van Assche case 0x46:
2810*44704f69SBart Van Assche case 0x47:
2811*44704f69SBart Van Assche /* This short form introduced in draft spc6r06 */
2812*44704f69SBart Van Assche thp = first_7[pc - 0x41];
2813*44704f69SBart Van Assche sgj_pr_hr(jsp, " %s %s for %s [pc=0x%x]:\n", thp, t2cdld,
2814*44704f69SBart Van Assche cdlt2bmp, pc);
2815*44704f69SBart Van Assche noitmc_v = sg_get_unaligned_be32(bp + 4);
2816*44704f69SBart Van Assche sgj_pr_hr(jsp, " %s = %u\n", noitmc, noitmc_v);
2817*44704f69SBart Van Assche noatmc_v = sg_get_unaligned_be32(bp + 8);
2818*44704f69SBart Van Assche sgj_pr_hr(jsp, " %s = %u\n", noatmc, noatmc_v);
2819*44704f69SBart Van Assche noitatmc_v = sg_get_unaligned_be32(bp + 12);
2820*44704f69SBart Van Assche sgj_pr_hr(jsp, " %s = %u\n", noitatmc, noitatmc_v);
2821*44704f69SBart Van Assche noc_v = sg_get_unaligned_be32(bp + 16);
2822*44704f69SBart Van Assche sgj_pr_hr(jsp, " %s = %u\n", noc, noc_v);
2823*44704f69SBart Van Assche if (jsp->pr_as_json) {
2824*44704f69SBart Van Assche snprintf(b, sizeof(b), "%s %s for %s", thp, t2cdld, cdlt2amp);
2825*44704f69SBart Van Assche sgj_js_nv_ihexstr(jsp, jo3p, param_c_sn, pc, NULL, b);
2826*44704f69SBart Van Assche
2827*44704f69SBart Van Assche js_snakenv_ihexstr_nex(jsp, jop, noitmc, noitmc_v, true, NULL,
2828*44704f69SBart Van Assche NULL, NULL);
2829*44704f69SBart Van Assche js_snakenv_ihexstr_nex(jsp, jop, noatmc, noatmc_v, true, NULL,
2830*44704f69SBart Van Assche NULL, NULL);
2831*44704f69SBart Van Assche js_snakenv_ihexstr_nex(jsp, jop, noitatmc, noitatmc_v, true,
2832*44704f69SBart Van Assche NULL, NULL, NULL);
2833*44704f69SBart Van Assche js_snakenv_ihexstr_nex(jsp, jop, noc, noc_v, true, NULL,
2834*44704f69SBart Van Assche NULL, NULL);
2835*44704f69SBart Van Assche }
2836*44704f69SBart Van Assche
2837*44704f69SBart Van Assche break;
2838*44704f69SBart Van Assche default:
2839*44704f69SBart Van Assche sgj_pr_hr(jsp, " <<unexpected %s 0x%x\n", param_c, pc);
2840*44704f69SBart Van Assche break;
2841*44704f69SBart Van Assche }
2842*44704f69SBart Van Assche if (op->do_pcb)
2843*44704f69SBart Van Assche sgj_pr_hr(jsp, " <%s>\n", get_pcb_str(bp[2],
2844*44704f69SBart Van Assche str, sizeof(str)));
2845*44704f69SBart Van Assche if (jsp->pr_as_json)
2846*44704f69SBart Van Assche sgj_js_nv_o(jsp, jap, NULL /* name */, jo3p);
2847*44704f69SBart Van Assche if (op->filter_given)
2848*44704f69SBart Van Assche break;
2849*44704f69SBart Van Assche skip:
2850*44704f69SBart Van Assche num -= pl;
2851*44704f69SBart Van Assche bp += pl;
2852*44704f69SBart Van Assche }
2853*44704f69SBart Van Assche return true;
2854*44704f69SBart Van Assche }
2855*44704f69SBart Van Assche
2856*44704f69SBart Van Assche /* Tape usage: Vendor specific (LTO-5 and LTO-6): 0x30 */
2857*44704f69SBart Van Assche static bool
show_tape_usage_page(const uint8_t * resp,int len,struct opts_t * op,sgj_opaque_p jop)2858*44704f69SBart Van Assche show_tape_usage_page(const uint8_t * resp, int len, struct opts_t * op,
2859*44704f69SBart Van Assche sgj_opaque_p jop)
2860*44704f69SBart Van Assche {
2861*44704f69SBart Van Assche int k, num, extra;
2862*44704f69SBart Van Assche unsigned int n;
2863*44704f69SBart Van Assche uint64_t ull;
2864*44704f69SBart Van Assche const uint8_t * bp;
2865*44704f69SBart Van Assche char str[PCB_STR_LEN];
2866*44704f69SBart Van Assche
2867*44704f69SBart Van Assche if (jop) { };
2868*44704f69SBart Van Assche num = len - 4;
2869*44704f69SBart Van Assche bp = &resp[0] + 4;
2870*44704f69SBart Van Assche if (num < 4) {
2871*44704f69SBart Van Assche pr2serr("badly formed tape usage page\n");
2872*44704f69SBart Van Assche return false;
2873*44704f69SBart Van Assche }
2874*44704f69SBart Van Assche if (op->verbose || ((! op->do_raw) && (0 == op->do_hex)))
2875*44704f69SBart Van Assche printf("Tape usage page (LTO-5 and LTO-6 specific) [0x30]\n");
2876*44704f69SBart Van Assche for (k = num; k > 0; k -= extra, bp += extra) {
2877*44704f69SBart Van Assche int pc = sg_get_unaligned_be16(bp + 0);
2878*44704f69SBart Van Assche
2879*44704f69SBart Van Assche extra = bp[3] + 4;
2880*44704f69SBart Van Assche if (op->filter_given) {
2881*44704f69SBart Van Assche if (pc != op->filter)
2882*44704f69SBart Van Assche continue;
2883*44704f69SBart Van Assche }
2884*44704f69SBart Van Assche if (op->do_raw) {
2885*44704f69SBart Van Assche dStrRaw(bp, extra);
2886*44704f69SBart Van Assche break;
2887*44704f69SBart Van Assche } else if (op->do_hex) {
2888*44704f69SBart Van Assche hex2stdout(bp, extra, op->dstrhex_no_ascii);
2889*44704f69SBart Van Assche break;
2890*44704f69SBart Van Assche }
2891*44704f69SBart Van Assche ull = n = 0;
2892*44704f69SBart Van Assche switch (bp[3]) {
2893*44704f69SBart Van Assche case 2:
2894*44704f69SBart Van Assche n = sg_get_unaligned_be16(bp + 4);
2895*44704f69SBart Van Assche break;
2896*44704f69SBart Van Assche case 4:
2897*44704f69SBart Van Assche n = sg_get_unaligned_be32(bp + 4);
2898*44704f69SBart Van Assche break;
2899*44704f69SBart Van Assche case 8:
2900*44704f69SBart Van Assche ull = sg_get_unaligned_be64(bp + 4);
2901*44704f69SBart Van Assche break;
2902*44704f69SBart Van Assche }
2903*44704f69SBart Van Assche switch (pc) {
2904*44704f69SBart Van Assche case 0x01:
2905*44704f69SBart Van Assche if (extra == 8)
2906*44704f69SBart Van Assche printf(" Thread count: %u", n);
2907*44704f69SBart Van Assche break;
2908*44704f69SBart Van Assche case 0x02:
2909*44704f69SBart Van Assche if (extra == 12)
2910*44704f69SBart Van Assche printf(" Total data sets written: %" PRIu64, ull);
2911*44704f69SBart Van Assche break;
2912*44704f69SBart Van Assche case 0x03:
2913*44704f69SBart Van Assche if (extra == 8)
2914*44704f69SBart Van Assche printf(" Total write retries: %u", n);
2915*44704f69SBart Van Assche break;
2916*44704f69SBart Van Assche case 0x04:
2917*44704f69SBart Van Assche if (extra == 6)
2918*44704f69SBart Van Assche printf(" Total unrecovered write errors: %u", n);
2919*44704f69SBart Van Assche break;
2920*44704f69SBart Van Assche case 0x05:
2921*44704f69SBart Van Assche if (extra == 6)
2922*44704f69SBart Van Assche printf(" Total suspended writes: %u", n);
2923*44704f69SBart Van Assche break;
2924*44704f69SBart Van Assche case 0x06:
2925*44704f69SBart Van Assche if (extra == 6)
2926*44704f69SBart Van Assche printf(" Total fatal suspended writes: %u", n);
2927*44704f69SBart Van Assche break;
2928*44704f69SBart Van Assche case 0x07:
2929*44704f69SBart Van Assche if (extra == 12)
2930*44704f69SBart Van Assche printf(" Total data sets read: %" PRIu64, ull);
2931*44704f69SBart Van Assche break;
2932*44704f69SBart Van Assche case 0x08:
2933*44704f69SBart Van Assche if (extra == 8)
2934*44704f69SBart Van Assche printf(" Total read retries: %u", n);
2935*44704f69SBart Van Assche break;
2936*44704f69SBart Van Assche case 0x09:
2937*44704f69SBart Van Assche if (extra == 6)
2938*44704f69SBart Van Assche printf(" Total unrecovered read errors: %u", n);
2939*44704f69SBart Van Assche break;
2940*44704f69SBart Van Assche case 0x0a:
2941*44704f69SBart Van Assche if (extra == 6)
2942*44704f69SBart Van Assche printf(" Total suspended reads: %u", n);
2943*44704f69SBart Van Assche break;
2944*44704f69SBart Van Assche case 0x0b:
2945*44704f69SBart Van Assche if (extra == 6)
2946*44704f69SBart Van Assche printf(" Total fatal suspended reads: %u", n);
2947*44704f69SBart Van Assche break;
2948*44704f69SBart Van Assche default:
2949*44704f69SBart Van Assche printf(" unknown %s = 0x%x, contents in hex:\n", param_c, pc);
2950*44704f69SBart Van Assche hex2stdout(bp, extra, 1);
2951*44704f69SBart Van Assche break;
2952*44704f69SBart Van Assche }
2953*44704f69SBart Van Assche printf("\n");
2954*44704f69SBart Van Assche if (op->do_pcb)
2955*44704f69SBart Van Assche printf(" <%s>\n", get_pcb_str(bp[2], str, sizeof(str)));
2956*44704f69SBart Van Assche if (op->filter_given)
2957*44704f69SBart Van Assche break;
2958*44704f69SBart Van Assche }
2959*44704f69SBart Van Assche return true;
2960*44704f69SBart Van Assche }
2961*44704f69SBart Van Assche
2962*44704f69SBart Van Assche /* 0x30 */
2963*44704f69SBart Van Assche static bool
show_hgst_perf_page(const uint8_t * resp,int len,struct opts_t * op,sgj_opaque_p jop)2964*44704f69SBart Van Assche show_hgst_perf_page(const uint8_t * resp, int len, struct opts_t * op,
2965*44704f69SBart Van Assche sgj_opaque_p jop)
2966*44704f69SBart Van Assche {
2967*44704f69SBart Van Assche bool valid = false;
2968*44704f69SBart Van Assche int num, pl;
2969*44704f69SBart Van Assche const uint8_t * bp;
2970*44704f69SBart Van Assche char str[PCB_STR_LEN];
2971*44704f69SBart Van Assche
2972*44704f69SBart Van Assche if (jop) { };
2973*44704f69SBart Van Assche if (op->verbose || ((! op->do_raw) && (0 == op->do_hex)))
2974*44704f69SBart Van Assche printf("HGST/WDC performance counters page [0x30]\n");
2975*44704f69SBart Van Assche num = len - 4;
2976*44704f69SBart Van Assche if (num < 0x30) {
2977*44704f69SBart Van Assche printf("HGST/WDC performance counters page too short (%d) < 48\n",
2978*44704f69SBart Van Assche num);
2979*44704f69SBart Van Assche return valid;
2980*44704f69SBart Van Assche }
2981*44704f69SBart Van Assche bp = &resp[0] + 4;
2982*44704f69SBart Van Assche while (num > 3) {
2983*44704f69SBart Van Assche int pc = sg_get_unaligned_be16(bp + 0);
2984*44704f69SBart Van Assche
2985*44704f69SBart Van Assche pl = bp[3] + 4;
2986*44704f69SBart Van Assche if (op->filter_given) {
2987*44704f69SBart Van Assche if (pc != op->filter)
2988*44704f69SBart Van Assche goto skip;
2989*44704f69SBart Van Assche }
2990*44704f69SBart Van Assche if (op->do_raw) {
2991*44704f69SBart Van Assche dStrRaw(bp, pl);
2992*44704f69SBart Van Assche break;
2993*44704f69SBart Van Assche } else if (op->do_hex) {
2994*44704f69SBart Van Assche hex2stdout(bp, pl, op->dstrhex_no_ascii);
2995*44704f69SBart Van Assche break;
2996*44704f69SBart Van Assche }
2997*44704f69SBart Van Assche switch (pc) {
2998*44704f69SBart Van Assche case 0:
2999*44704f69SBart Van Assche valid = true;
3000*44704f69SBart Van Assche printf(" Zero Seeks = %u\n", sg_get_unaligned_be16(bp + 4));
3001*44704f69SBart Van Assche printf(" Seeks >= 2/3 = %u\n", sg_get_unaligned_be16(bp + 6));
3002*44704f69SBart Van Assche printf(" Seeks >= 1/3 and < 2/3 = %u\n",
3003*44704f69SBart Van Assche sg_get_unaligned_be16(bp + 8));
3004*44704f69SBart Van Assche printf(" Seeks >= 1/6 and < 1/3 = %u\n",
3005*44704f69SBart Van Assche sg_get_unaligned_be16(bp + 10));
3006*44704f69SBart Van Assche printf(" Seeks >= 1/12 and < 1/6 = %u\n",
3007*44704f69SBart Van Assche sg_get_unaligned_be16(bp + 12));
3008*44704f69SBart Van Assche printf(" Seeks > 0 and < 1/12 = %u\n",
3009*44704f69SBart Van Assche sg_get_unaligned_be16(bp + 14));
3010*44704f69SBart Van Assche printf(" Overrun Counter = %u\n",
3011*44704f69SBart Van Assche sg_get_unaligned_be16(bp + 20));
3012*44704f69SBart Van Assche printf(" Underrun Counter = %u\n",
3013*44704f69SBart Van Assche sg_get_unaligned_be16(bp + 22));
3014*44704f69SBart Van Assche printf(" Device Cache Full Read Hits = %u\n",
3015*44704f69SBart Van Assche sg_get_unaligned_be32(bp + 24));
3016*44704f69SBart Van Assche printf(" Device Cache Partial Read Hits = %u\n",
3017*44704f69SBart Van Assche sg_get_unaligned_be32(bp + 28));
3018*44704f69SBart Van Assche printf(" Device Cache Write Hits = %u\n",
3019*44704f69SBart Van Assche sg_get_unaligned_be32(bp + 32));
3020*44704f69SBart Van Assche printf(" Device Cache Fast Writes = %u\n",
3021*44704f69SBart Van Assche sg_get_unaligned_be32(bp + 36));
3022*44704f69SBart Van Assche printf(" Device Cache Read Misses = %u\n",
3023*44704f69SBart Van Assche sg_get_unaligned_be32(bp + 40));
3024*44704f69SBart Van Assche break;
3025*44704f69SBart Van Assche default:
3026*44704f69SBart Van Assche valid = false;
3027*44704f69SBart Van Assche printf(" Unknown HGST/WDC %s = 0x%x", param_c, pc);
3028*44704f69SBart Van Assche break;
3029*44704f69SBart Van Assche }
3030*44704f69SBart Van Assche if (op->do_pcb)
3031*44704f69SBart Van Assche printf(" <%s>\n", get_pcb_str(bp[2], str, sizeof(str)));
3032*44704f69SBart Van Assche if (op->filter_given)
3033*44704f69SBart Van Assche break;
3034*44704f69SBart Van Assche skip:
3035*44704f69SBart Van Assche num -= pl;
3036*44704f69SBart Van Assche bp += pl;
3037*44704f69SBart Van Assche }
3038*44704f69SBart Van Assche return valid;
3039*44704f69SBart Van Assche }
3040*44704f69SBart Van Assche
3041*44704f69SBart Van Assche /* Tape capacity: vendor specific (LTO-5 and LTO-6 ?): 0x31 */
3042*44704f69SBart Van Assche static bool
show_tape_capacity_page(const uint8_t * resp,int len,struct opts_t * op,sgj_opaque_p jop)3043*44704f69SBart Van Assche show_tape_capacity_page(const uint8_t * resp, int len,
3044*44704f69SBart Van Assche struct opts_t * op, sgj_opaque_p jop)
3045*44704f69SBart Van Assche {
3046*44704f69SBart Van Assche int k, num, extra;
3047*44704f69SBart Van Assche unsigned int n;
3048*44704f69SBart Van Assche const uint8_t * bp;
3049*44704f69SBart Van Assche char str[PCB_STR_LEN];
3050*44704f69SBart Van Assche
3051*44704f69SBart Van Assche if (jop) { };
3052*44704f69SBart Van Assche num = len - 4;
3053*44704f69SBart Van Assche bp = &resp[0] + 4;
3054*44704f69SBart Van Assche if (num < 4) {
3055*44704f69SBart Van Assche pr2serr("badly formed tape capacity page\n");
3056*44704f69SBart Van Assche return false;
3057*44704f69SBart Van Assche }
3058*44704f69SBart Van Assche if (op->verbose || ((! op->do_raw) && (0 == op->do_hex)))
3059*44704f69SBart Van Assche printf("Tape capacity page (LTO-5 and LTO-6 specific) [0x31]\n");
3060*44704f69SBart Van Assche for (k = num; k > 0; k -= extra, bp += extra) {
3061*44704f69SBart Van Assche int pc = sg_get_unaligned_be16(bp + 0);
3062*44704f69SBart Van Assche
3063*44704f69SBart Van Assche extra = bp[3] + 4;
3064*44704f69SBart Van Assche if (op->filter_given) {
3065*44704f69SBart Van Assche if (pc != op->filter)
3066*44704f69SBart Van Assche continue;
3067*44704f69SBart Van Assche }
3068*44704f69SBart Van Assche if (op->do_raw) {
3069*44704f69SBart Van Assche dStrRaw(bp, extra);
3070*44704f69SBart Van Assche break;
3071*44704f69SBart Van Assche } else if (op->do_hex) {
3072*44704f69SBart Van Assche hex2stdout(bp, extra, op->dstrhex_no_ascii);
3073*44704f69SBart Van Assche break;
3074*44704f69SBart Van Assche }
3075*44704f69SBart Van Assche if (extra != 8)
3076*44704f69SBart Van Assche continue;
3077*44704f69SBart Van Assche n = sg_get_unaligned_be32(bp + 4);
3078*44704f69SBart Van Assche switch (pc) {
3079*44704f69SBart Van Assche case 0x01:
3080*44704f69SBart Van Assche printf(" Main partition remaining capacity (in MiB): %u", n);
3081*44704f69SBart Van Assche break;
3082*44704f69SBart Van Assche case 0x02:
3083*44704f69SBart Van Assche printf(" Alternate partition remaining capacity (in MiB): %u", n);
3084*44704f69SBart Van Assche break;
3085*44704f69SBart Van Assche case 0x03:
3086*44704f69SBart Van Assche printf(" Main partition maximum capacity (in MiB): %u", n);
3087*44704f69SBart Van Assche break;
3088*44704f69SBart Van Assche case 0x04:
3089*44704f69SBart Van Assche printf(" Alternate partition maximum capacity (in MiB): %u", n);
3090*44704f69SBart Van Assche break;
3091*44704f69SBart Van Assche default:
3092*44704f69SBart Van Assche printf(" unknown %s = 0x%x, contents in hex:\n", param_c, pc);
3093*44704f69SBart Van Assche hex2stdout(bp, extra, 1);
3094*44704f69SBart Van Assche break;
3095*44704f69SBart Van Assche }
3096*44704f69SBart Van Assche printf("\n");
3097*44704f69SBart Van Assche if (op->do_pcb)
3098*44704f69SBart Van Assche printf(" <%s>\n", get_pcb_str(bp[2], str, sizeof(str)));
3099*44704f69SBart Van Assche if (op->filter_given)
3100*44704f69SBart Van Assche break;
3101*44704f69SBart Van Assche }
3102*44704f69SBart Van Assche return true;
3103*44704f69SBart Van Assche }
3104*44704f69SBart Van Assche
3105*44704f69SBart Van Assche /* Data compression: originally vendor specific 0x32 (LTO-5), then
3106*44704f69SBart Van Assche * ssc-4 standardizes it at 0x1b <dc> */
3107*44704f69SBart Van Assche static bool
show_data_compression_page(const uint8_t * resp,int len,struct opts_t * op,sgj_opaque_p jop)3108*44704f69SBart Van Assche show_data_compression_page(const uint8_t * resp, int len,
3109*44704f69SBart Van Assche struct opts_t * op, sgj_opaque_p jop)
3110*44704f69SBart Van Assche {
3111*44704f69SBart Van Assche int k, j, pl, num, extra, pc, pg_code;
3112*44704f69SBart Van Assche uint64_t n;
3113*44704f69SBart Van Assche const uint8_t * bp;
3114*44704f69SBart Van Assche char str[PCB_STR_LEN];
3115*44704f69SBart Van Assche
3116*44704f69SBart Van Assche if (jop) { };
3117*44704f69SBart Van Assche pg_code = resp[0] & 0x3f;
3118*44704f69SBart Van Assche num = len - 4;
3119*44704f69SBart Van Assche bp = &resp[0] + 4;
3120*44704f69SBart Van Assche if (num < 4) {
3121*44704f69SBart Van Assche pr2serr("badly formed data compression page\n");
3122*44704f69SBart Van Assche return false;
3123*44704f69SBart Van Assche }
3124*44704f69SBart Van Assche if (op->verbose || ((! op->do_raw) && (0 == op->do_hex))) {
3125*44704f69SBart Van Assche if (0x1b == pg_code)
3126*44704f69SBart Van Assche printf("Data compression page (ssc-4) [0x1b]\n");
3127*44704f69SBart Van Assche else
3128*44704f69SBart Van Assche printf("Data compression page (LTO-5 specific) [0x%x]\n",
3129*44704f69SBart Van Assche pg_code);
3130*44704f69SBart Van Assche }
3131*44704f69SBart Van Assche for (k = num; k > 0; k -= extra, bp += extra) {
3132*44704f69SBart Van Assche pc = sg_get_unaligned_be16(bp + 0);
3133*44704f69SBart Van Assche pl = bp[3];
3134*44704f69SBart Van Assche extra = pl + 4;
3135*44704f69SBart Van Assche if (op->filter_given) {
3136*44704f69SBart Van Assche if (pc != op->filter)
3137*44704f69SBart Van Assche continue;
3138*44704f69SBart Van Assche }
3139*44704f69SBart Van Assche if (op->do_raw) {
3140*44704f69SBart Van Assche dStrRaw(bp, extra);
3141*44704f69SBart Van Assche break;
3142*44704f69SBart Van Assche } else if (op->do_hex) {
3143*44704f69SBart Van Assche hex2stdout(bp, extra, op->dstrhex_no_ascii);
3144*44704f69SBart Van Assche break;
3145*44704f69SBart Van Assche }
3146*44704f69SBart Van Assche if ((0 == pl) || (pl > 8)) {
3147*44704f69SBart Van Assche printf("badly formed data compression log parameter\n");
3148*44704f69SBart Van Assche printf(" %s = 0x%x, contents in hex:\n", param_c, pc);
3149*44704f69SBart Van Assche hex2stdout(bp, extra, op->dstrhex_no_ascii);
3150*44704f69SBart Van Assche goto skip_para;
3151*44704f69SBart Van Assche }
3152*44704f69SBart Van Assche /* variable length integer, max length 8 bytes */
3153*44704f69SBart Van Assche for (j = 0, n = 0; j < pl; ++j) {
3154*44704f69SBart Van Assche if (j > 0)
3155*44704f69SBart Van Assche n <<= 8;
3156*44704f69SBart Van Assche n |= bp[4 + j];
3157*44704f69SBart Van Assche }
3158*44704f69SBart Van Assche switch (pc) {
3159*44704f69SBart Van Assche case 0x00:
3160*44704f69SBart Van Assche printf(" Read compression ratio x100: %" PRIu64 , n);
3161*44704f69SBart Van Assche break;
3162*44704f69SBart Van Assche case 0x01:
3163*44704f69SBart Van Assche printf(" Write compression ratio x100: %" PRIu64 , n);
3164*44704f69SBart Van Assche break;
3165*44704f69SBart Van Assche case 0x02:
3166*44704f69SBart Van Assche printf(" Megabytes transferred to server: %" PRIu64 , n);
3167*44704f69SBart Van Assche break;
3168*44704f69SBart Van Assche case 0x03:
3169*44704f69SBart Van Assche printf(" Bytes transferred to server: %" PRIu64 , n);
3170*44704f69SBart Van Assche break;
3171*44704f69SBart Van Assche case 0x04:
3172*44704f69SBart Van Assche printf(" Megabytes read from tape: %" PRIu64 , n);
3173*44704f69SBart Van Assche break;
3174*44704f69SBart Van Assche case 0x05:
3175*44704f69SBart Van Assche printf(" Bytes read from tape: %" PRIu64 , n);
3176*44704f69SBart Van Assche break;
3177*44704f69SBart Van Assche case 0x06:
3178*44704f69SBart Van Assche printf(" Megabytes transferred from server: %" PRIu64 , n);
3179*44704f69SBart Van Assche break;
3180*44704f69SBart Van Assche case 0x07:
3181*44704f69SBart Van Assche printf(" Bytes transferred from server: %" PRIu64 , n);
3182*44704f69SBart Van Assche break;
3183*44704f69SBart Van Assche case 0x08:
3184*44704f69SBart Van Assche printf(" Megabytes written to tape: %" PRIu64 , n);
3185*44704f69SBart Van Assche break;
3186*44704f69SBart Van Assche case 0x09:
3187*44704f69SBart Van Assche printf(" Bytes written to tape: %" PRIu64 , n);
3188*44704f69SBart Van Assche break;
3189*44704f69SBart Van Assche case 0x100:
3190*44704f69SBart Van Assche printf(" Data compression enabled: 0x%" PRIx64, n);
3191*44704f69SBart Van Assche break;
3192*44704f69SBart Van Assche default:
3193*44704f69SBart Van Assche printf(" unknown %s = 0x%x, contents in hex:\n", param_c, pc);
3194*44704f69SBart Van Assche hex2stdout(bp, extra, op->dstrhex_no_ascii);
3195*44704f69SBart Van Assche break;
3196*44704f69SBart Van Assche }
3197*44704f69SBart Van Assche skip_para:
3198*44704f69SBart Van Assche printf("\n");
3199*44704f69SBart Van Assche if (op->do_pcb)
3200*44704f69SBart Van Assche printf(" <%s>\n", get_pcb_str(bp[2], str, sizeof(str)));
3201*44704f69SBart Van Assche if (op->filter_given)
3202*44704f69SBart Van Assche break;
3203*44704f69SBart Van Assche }
3204*44704f69SBart Van Assche return true;
3205*44704f69SBart Van Assche }
3206*44704f69SBart Van Assche
3207*44704f69SBart Van Assche /* LAST_N_ERR_LPAGE [0x7] <lne> introduced: SPC-2 */
3208*44704f69SBart Van Assche static bool
show_last_n_error_page(const uint8_t * resp,int len,struct opts_t * op,sgj_opaque_p jop)3209*44704f69SBart Van Assche show_last_n_error_page(const uint8_t * resp, int len,
3210*44704f69SBart Van Assche struct opts_t * op, sgj_opaque_p jop)
3211*44704f69SBart Van Assche {
3212*44704f69SBart Van Assche int k, num, pl;
3213*44704f69SBart Van Assche const uint8_t * bp;
3214*44704f69SBart Van Assche sgj_state * jsp = &op->json_st;
3215*44704f69SBart Van Assche sgj_opaque_p jo2p;
3216*44704f69SBart Van Assche sgj_opaque_p jo3p = NULL;
3217*44704f69SBart Van Assche sgj_opaque_p jap = NULL;
3218*44704f69SBart Van Assche char str[PCB_STR_LEN];
3219*44704f69SBart Van Assche char b[256];
3220*44704f69SBart Van Assche static const char * lneelp = "Last n error events log page";
3221*44704f69SBart Van Assche static const char * eed = "error_event_data";
3222*44704f69SBart Van Assche
3223*44704f69SBart Van Assche num = len - 4;
3224*44704f69SBart Van Assche bp = &resp[0] + 4;
3225*44704f69SBart Van Assche if (num < 4) {
3226*44704f69SBart Van Assche sgj_pr_hr(jsp, "No error events logged\n");
3227*44704f69SBart Van Assche return true;
3228*44704f69SBart Van Assche }
3229*44704f69SBart Van Assche if (op->verbose || ((! op->do_raw) && (0 == op->do_hex)))
3230*44704f69SBart Van Assche sgj_pr_hr(jsp, "%s [0x7]\n", lneelp);
3231*44704f69SBart Van Assche if (jsp->pr_as_json) {
3232*44704f69SBart Van Assche jo2p = sg_log_js_hdr(jsp, jop, lneelp, resp);
3233*44704f69SBart Van Assche jap = sgj_named_subarray_r(jsp, jo2p, "error_event_log_parameters");
3234*44704f69SBart Van Assche }
3235*44704f69SBart Van Assche
3236*44704f69SBart Van Assche for (k = num; k > 0; k -= pl, bp += pl) {
3237*44704f69SBart Van Assche uint16_t pc;
3238*44704f69SBart Van Assche
3239*44704f69SBart Van Assche if (k < 3) {
3240*44704f69SBart Van Assche pr2serr("short %s\n", lneelp);
3241*44704f69SBart Van Assche return false;
3242*44704f69SBart Van Assche }
3243*44704f69SBart Van Assche pl = bp[3] + 4;
3244*44704f69SBart Van Assche pc = sg_get_unaligned_be16(bp + 0);
3245*44704f69SBart Van Assche if (op->filter_given) {
3246*44704f69SBart Van Assche if (pc != op->filter)
3247*44704f69SBart Van Assche continue;
3248*44704f69SBart Van Assche }
3249*44704f69SBart Van Assche if (op->do_raw) {
3250*44704f69SBart Van Assche dStrRaw(bp, pl);
3251*44704f69SBart Van Assche break;
3252*44704f69SBart Van Assche } else if (op->do_hex) {
3253*44704f69SBart Van Assche hex2stdout(bp, pl, op->dstrhex_no_ascii);
3254*44704f69SBart Van Assche break;
3255*44704f69SBart Van Assche }
3256*44704f69SBart Van Assche if (jsp->pr_as_json) {
3257*44704f69SBart Van Assche jo3p = sgj_new_unattached_object_r(jsp);
3258*44704f69SBart Van Assche if (op->do_pcb)
3259*44704f69SBart Van Assche js_pcb(jsp, jo3p, bp[2]);
3260*44704f69SBart Van Assche sgj_js_nv_ihexstr(jsp, jo3p, param_c_sn, pc, NULL, NULL);
3261*44704f69SBart Van Assche }
3262*44704f69SBart Van Assche
3263*44704f69SBart Van Assche sgj_pr_hr(jsp, " Error event %u [0x%x]:\n", pc, pc);
3264*44704f69SBart Van Assche if (pl > 4) {
3265*44704f69SBart Van Assche if ((bp[2] & 0x1) && (bp[2] & 0x2)) {
3266*44704f69SBart Van Assche sgj_pr_hr(jsp, " [binary]:\n");
3267*44704f69SBart Van Assche hex2str(bp + 4, pl - 4, " ", op->hex2str_oformat,
3268*44704f69SBart Van Assche sizeof(b), b);
3269*44704f69SBart Van Assche sgj_pr_hr(jsp, "%s\n", b);
3270*44704f69SBart Van Assche if (jsp->pr_as_json)
3271*44704f69SBart Van Assche sgj_js_nv_hex_bytes(jsp, jo3p, eed, bp + 4, pl - 4);
3272*44704f69SBart Van Assche } else if (0x01 == (bp[2] & 0x3)) { /* ASCII */
3273*44704f69SBart Van Assche sgj_pr_hr(jsp, " %.*s\n", pl - 4, (const char *)(bp + 4));
3274*44704f69SBart Van Assche if (jsp->pr_as_json)
3275*44704f69SBart Van Assche sgj_js_nv_s_len(jsp, jo3p, eed,
3276*44704f69SBart Van Assche (const char *)(bp + 4), pl - 4);
3277*44704f69SBart Van Assche } else {
3278*44704f69SBart Van Assche sgj_pr_hr(jsp, " [data counter?? (LP bit should be "
3279*44704f69SBart Van Assche "set)]:\n");
3280*44704f69SBart Van Assche hex2str(bp + 4, pl - 4, " ", op->hex2str_oformat,
3281*44704f69SBart Van Assche sizeof(b), b);
3282*44704f69SBart Van Assche sgj_pr_hr(jsp, "%s\n", b);
3283*44704f69SBart Van Assche if (jsp->pr_as_json)
3284*44704f69SBart Van Assche sgj_js_nv_hex_bytes(jsp, jo3p, eed, bp + 4, pl - 4);
3285*44704f69SBart Van Assche }
3286*44704f69SBart Van Assche }
3287*44704f69SBart Van Assche if (op->do_pcb)
3288*44704f69SBart Van Assche sgj_pr_hr(jsp, " <%s>\n", get_pcb_str(bp[2],
3289*44704f69SBart Van Assche str, sizeof(str)));
3290*44704f69SBart Van Assche if (jsp->pr_as_json)
3291*44704f69SBart Van Assche sgj_js_nv_o(jsp, jap, NULL /* name */, jo3p);
3292*44704f69SBart Van Assche if (op->filter_given)
3293*44704f69SBart Van Assche break;
3294*44704f69SBart Van Assche }
3295*44704f69SBart Van Assche return true;
3296*44704f69SBart Van Assche }
3297*44704f69SBart Van Assche
3298*44704f69SBart Van Assche /* LAST_N_DEFERRED_LPAGE [0xb] <lnd> introduced: SPC-2 */
3299*44704f69SBart Van Assche static bool
show_last_n_deferred_error_page(const uint8_t * resp,int len,struct opts_t * op,sgj_opaque_p jop)3300*44704f69SBart Van Assche show_last_n_deferred_error_page(const uint8_t * resp, int len,
3301*44704f69SBart Van Assche struct opts_t * op, sgj_opaque_p jop)
3302*44704f69SBart Van Assche {
3303*44704f69SBart Van Assche int k, n, num, pl;
3304*44704f69SBart Van Assche const uint8_t * bp;
3305*44704f69SBart Van Assche sgj_state * jsp = &op->json_st;
3306*44704f69SBart Van Assche sgj_opaque_p jo2p, jo4p;
3307*44704f69SBart Van Assche sgj_opaque_p jo3p = NULL;
3308*44704f69SBart Van Assche sgj_opaque_p jap = NULL;
3309*44704f69SBart Van Assche char str[PCB_STR_LEN];
3310*44704f69SBart Van Assche char b[512];
3311*44704f69SBart Van Assche static const char * lndeoaelp =
3312*44704f69SBart Van Assche "Last n deferred errors or asynchronous events log page";
3313*44704f69SBart Van Assche static const char * deoae = "Deferred error or asynchronous event";
3314*44704f69SBart Van Assche static const char * sd = "sense_data";
3315*44704f69SBart Van Assche
3316*44704f69SBart Van Assche num = len - 4;
3317*44704f69SBart Van Assche bp = &resp[0] + 4;
3318*44704f69SBart Van Assche if (num < 4) {
3319*44704f69SBart Van Assche pr2serr("No deferred errors logged\n");
3320*44704f69SBart Van Assche return true;
3321*44704f69SBart Van Assche }
3322*44704f69SBart Van Assche if (op->verbose || ((! op->do_raw) && (0 == op->do_hex)))
3323*44704f69SBart Van Assche sgj_pr_hr(jsp, "%s [0xb]\n", lndeoaelp);
3324*44704f69SBart Van Assche if (jsp->pr_as_json) {
3325*44704f69SBart Van Assche jo2p = sg_log_js_hdr(jsp, jop, lndeoaelp, resp);
3326*44704f69SBart Van Assche jap = sgj_named_subarray_r(jsp, jo2p,
3327*44704f69SBart Van Assche "deferred_error_or_asynchronous_event_log_parameters");
3328*44704f69SBart Van Assche }
3329*44704f69SBart Van Assche
3330*44704f69SBart Van Assche for (k = num; k > 0; k -= pl, bp += pl) {
3331*44704f69SBart Van Assche int pc;
3332*44704f69SBart Van Assche
3333*44704f69SBart Van Assche if (k < 3) {
3334*44704f69SBart Van Assche pr2serr("short %s\n", lndeoaelp);
3335*44704f69SBart Van Assche return false;
3336*44704f69SBart Van Assche }
3337*44704f69SBart Van Assche pl = bp[3] + 4;
3338*44704f69SBart Van Assche pc = sg_get_unaligned_be16(bp + 0);
3339*44704f69SBart Van Assche if (op->filter_given) {
3340*44704f69SBart Van Assche if (pc != op->filter)
3341*44704f69SBart Van Assche continue;
3342*44704f69SBart Van Assche }
3343*44704f69SBart Van Assche if (op->do_raw) {
3344*44704f69SBart Van Assche dStrRaw(bp, pl);
3345*44704f69SBart Van Assche break;
3346*44704f69SBart Van Assche } else if (op->do_hex) {
3347*44704f69SBart Van Assche hex2stdout(bp, pl, op->dstrhex_no_ascii);
3348*44704f69SBart Van Assche break;
3349*44704f69SBart Van Assche }
3350*44704f69SBart Van Assche if (jsp->pr_as_json) {
3351*44704f69SBart Van Assche jo3p = sgj_new_unattached_object_r(jsp);
3352*44704f69SBart Van Assche if (op->do_pcb)
3353*44704f69SBart Van Assche js_pcb(jsp, jo3p, bp[2]);
3354*44704f69SBart Van Assche sgj_js_nv_ihexstr(jsp, jo3p, param_c_sn, pc, NULL, deoae);
3355*44704f69SBart Van Assche }
3356*44704f69SBart Van Assche sgj_pr_hr(jsp, " %s [0x%x]:\n", deoae, pc);
3357*44704f69SBart Van Assche if (op->do_brief > 0) {
3358*44704f69SBart Van Assche hex2stdout(bp + 4, pl - 4, op->dstrhex_no_ascii);
3359*44704f69SBart Van Assche hex2str(bp + 4, pl - 4, " ", op->hex2str_oformat,
3360*44704f69SBart Van Assche sizeof(b), b);
3361*44704f69SBart Van Assche sgj_pr_hr(jsp, "%s\n", b);
3362*44704f69SBart Van Assche if (jsp->pr_as_json)
3363*44704f69SBart Van Assche sgj_js_nv_hex_bytes(jsp, jo3p, sd, bp + 4, pl - 4);
3364*44704f69SBart Van Assche } else {
3365*44704f69SBart Van Assche
3366*44704f69SBart Van Assche n = sg_get_sense_str(" ", bp + 4, pl - 4, false, sizeof(b),
3367*44704f69SBart Van Assche b);
3368*44704f69SBart Van Assche sgj_pr_hr(jsp, "%.*s\n", n, b);
3369*44704f69SBart Van Assche if (jsp->pr_as_json) {
3370*44704f69SBart Van Assche jo4p = sgj_named_subobject_r(jsp, jo3p, sd);
3371*44704f69SBart Van Assche sgj_js_sense(jsp, jo4p, bp + 4, pl - 4);
3372*44704f69SBart Van Assche }
3373*44704f69SBart Van Assche }
3374*44704f69SBart Van Assche if (op->do_pcb)
3375*44704f69SBart Van Assche sgj_pr_hr(jsp, " <%s>\n", get_pcb_str(bp[2],
3376*44704f69SBart Van Assche str, sizeof(str)));
3377*44704f69SBart Van Assche if (jsp->pr_as_json)
3378*44704f69SBart Van Assche sgj_js_nv_o(jsp, jap, NULL /* name */, jo3p);
3379*44704f69SBart Van Assche if (op->filter_given)
3380*44704f69SBart Van Assche break;
3381*44704f69SBart Van Assche }
3382*44704f69SBart Van Assche return true;
3383*44704f69SBart Van Assche }
3384*44704f69SBart Van Assche
3385*44704f69SBart Van Assche static const char * clgc = "Change list generation code";
3386*44704f69SBart Van Assche static const char * cgn = "Changed generation number";
3387*44704f69SBart Van Assche
3388*44704f69SBart Van Assche /* LAST_N_INQUIRY_DATA_CH_SUBPG [0xb,0x1] <lnic> introduced: SPC-5 (rev 17) */
3389*44704f69SBart Van Assche static bool
show_last_n_inq_data_ch_page(const uint8_t * resp,int len,struct opts_t * op,sgj_opaque_p jop)3390*44704f69SBart Van Assche show_last_n_inq_data_ch_page(const uint8_t * resp, int len,
3391*44704f69SBart Van Assche struct opts_t * op, sgj_opaque_p jop)
3392*44704f69SBart Van Assche {
3393*44704f69SBart Van Assche bool vpd;
3394*44704f69SBart Van Assche int j, num, pl, vpd_pg;
3395*44704f69SBart Van Assche uint32_t k, n;
3396*44704f69SBart Van Assche const uint8_t * bp;
3397*44704f69SBart Van Assche const char * vpd_pg_name = NULL;
3398*44704f69SBart Van Assche sgj_state * jsp = &op->json_st;
3399*44704f69SBart Van Assche sgj_opaque_p jo2p, jo4p;
3400*44704f69SBart Van Assche sgj_opaque_p jo3p = NULL;
3401*44704f69SBart Van Assche sgj_opaque_p jap = NULL;
3402*44704f69SBart Van Assche sgj_opaque_p ja2p;
3403*44704f69SBart Van Assche char str[PCB_STR_LEN];
3404*44704f69SBart Van Assche char b[128];
3405*44704f69SBart Van Assche static const char * lnidclp = "Last n inquiry data changed log page";
3406*44704f69SBart Van Assche static const char * idci = "Inquiry data changed indicator";
3407*44704f69SBart Van Assche
3408*44704f69SBart Van Assche if (op->verbose || ((! op->do_raw) && (0 == op->do_hex)))
3409*44704f69SBart Van Assche sgj_pr_hr(jsp, "%s [0xb,0x1]\n", lnidclp);
3410*44704f69SBart Van Assche num = len - 4;
3411*44704f69SBart Van Assche bp = &resp[0] + 4;
3412*44704f69SBart Van Assche if (jsp->pr_as_json) {
3413*44704f69SBart Van Assche jo2p = sg_log_js_hdr(jsp, jop, lnidclp, resp);
3414*44704f69SBart Van Assche jap = sgj_named_subarray_r(jsp, jo2p,
3415*44704f69SBart Van Assche "inquiry_data_changed_log_parameters");
3416*44704f69SBart Van Assche }
3417*44704f69SBart Van Assche
3418*44704f69SBart Van Assche while (num > 3) {
3419*44704f69SBart Van Assche int pc = sg_get_unaligned_be16(bp + 0);
3420*44704f69SBart Van Assche
3421*44704f69SBart Van Assche pl = bp[3] + 4;
3422*44704f69SBart Van Assche if (op->filter_given) {
3423*44704f69SBart Van Assche if (pc != op->filter)
3424*44704f69SBart Van Assche goto skip;
3425*44704f69SBart Van Assche }
3426*44704f69SBart Van Assche if (op->do_raw) {
3427*44704f69SBart Van Assche dStrRaw(bp, pl);
3428*44704f69SBart Van Assche break;
3429*44704f69SBart Van Assche } else if (op->do_hex) {
3430*44704f69SBart Van Assche hex2stdout(bp, pl, op->dstrhex_no_ascii);
3431*44704f69SBart Van Assche break;
3432*44704f69SBart Van Assche }
3433*44704f69SBart Van Assche if (jsp->pr_as_json) {
3434*44704f69SBart Van Assche jo3p = sgj_new_unattached_object_r(jsp);
3435*44704f69SBart Van Assche if (op->do_pcb)
3436*44704f69SBart Van Assche js_pcb(jsp, jo3p, bp[2]);
3437*44704f69SBart Van Assche sgj_js_nv_ihexstr(jsp, jo3p, param_c_sn, pc, NULL,
3438*44704f69SBart Van Assche 0 == pc ? clgc : idci);
3439*44704f69SBart Van Assche }
3440*44704f69SBart Van Assche if (0 == pc) {
3441*44704f69SBart Van Assche if (pl < 8) {
3442*44704f69SBart Van Assche pr2serr(" <<expect parameter 0x%x to be at least 8 bytes "
3443*44704f69SBart Van Assche "long, got %d, skip>>\n", pc, pl);
3444*44704f69SBart Van Assche goto skip;
3445*44704f69SBart Van Assche }
3446*44704f69SBart Van Assche sgj_pr_hr(jsp, " %s [pc=0x0]:\n", clgc);
3447*44704f69SBart Van Assche for (j = 4, k = 1; j < pl; j +=4, ++k) {
3448*44704f69SBart Van Assche n = sg_get_unaligned_be32(bp + j);
3449*44704f69SBart Van Assche sgj_pr_hr(jsp, " %s [0x%x]: %u\n", cgn, k, n);
3450*44704f69SBart Van Assche }
3451*44704f69SBart Van Assche if (jsp->pr_as_json) {
3452*44704f69SBart Van Assche ja2p = sgj_named_subarray_r(jsp, jo3p,
3453*44704f69SBart Van Assche "changed_generation_numbers");
3454*44704f69SBart Van Assche for (j = 4, k = 1; j < pl; j +=4, ++k) {
3455*44704f69SBart Van Assche jo4p = sgj_new_unattached_object_r(jsp);
3456*44704f69SBart Van Assche n = sg_get_unaligned_be32(bp + j);
3457*44704f69SBart Van Assche js_snakenv_ihexstr_nex(jsp, jo4p, cgn, n, true, NULL,
3458*44704f69SBart Van Assche NULL, NULL);
3459*44704f69SBart Van Assche sgj_js_nv_o(jsp, ja2p, NULL /* name */, jo4p);
3460*44704f69SBart Van Assche }
3461*44704f69SBart Van Assche }
3462*44704f69SBart Van Assche } else { /* pc > 0x0 */
3463*44704f69SBart Van Assche int m;
3464*44704f69SBart Van Assche const int nn = sg_lib_names_mode_len;
3465*44704f69SBart Van Assche struct sg_lib_simple_value_name_t * nvp = sg_lib_names_vpd_arr;
3466*44704f69SBart Van Assche
3467*44704f69SBart Van Assche snprintf(b, sizeof(b), " %s 0x%x, ", param_c, pc);
3468*44704f69SBart Van Assche vpd = !! (1 & *(bp + 4));
3469*44704f69SBart Van Assche vpd_pg = *(bp + 5);
3470*44704f69SBart Van Assche if (vpd) {
3471*44704f69SBart Van Assche for (m = 0; m < nn; ++m, ++nvp) {
3472*44704f69SBart Van Assche if (nvp->value == vpd_pg)
3473*44704f69SBart Van Assche break;
3474*44704f69SBart Van Assche }
3475*44704f69SBart Van Assche vpd_pg_name = (m < nn) ? nvp->name : NULL;
3476*44704f69SBart Van Assche } else
3477*44704f69SBart Van Assche vpd_pg_name = "Standard INQUIRY";
3478*44704f69SBart Van Assche
3479*44704f69SBart Van Assche if (jsp->pr_as_json) {
3480*44704f69SBart Van Assche sgj_js_nv_i(jsp, jo3p, "vpd", (int)vpd);
3481*44704f69SBart Van Assche sgj_js_nv_ihex(jsp, jo3p, "changed_page_code", vpd_pg);
3482*44704f69SBart Van Assche if (vpd_pg_name)
3483*44704f69SBart Van Assche sgj_js_nv_s(jsp, jo3p, "changed_page_name", vpd_pg_name);
3484*44704f69SBart Van Assche }
3485*44704f69SBart Van Assche if (vpd) {
3486*44704f69SBart Van Assche sgj_pr_hr(jsp, "%sVPD page 0x%x changed\n", b, vpd_pg);
3487*44704f69SBart Van Assche if (0 == op->do_brief) {
3488*44704f69SBart Van Assche if (vpd_pg_name)
3489*44704f69SBart Van Assche sgj_pr_hr(jsp, " name: %s\n", vpd_pg_name);
3490*44704f69SBart Van Assche }
3491*44704f69SBart Van Assche } else
3492*44704f69SBart Van Assche sgj_pr_hr(jsp, "%sStandard INQUIRY data changed\n", b);
3493*44704f69SBart Van Assche }
3494*44704f69SBart Van Assche if (op->do_pcb)
3495*44704f69SBart Van Assche sgj_pr_hr(jsp, " <%s>\n", get_pcb_str(bp[2],
3496*44704f69SBart Van Assche str, sizeof(str)));
3497*44704f69SBart Van Assche skip:
3498*44704f69SBart Van Assche if (jsp->pr_as_json)
3499*44704f69SBart Van Assche sgj_js_nv_o(jsp, jap, NULL /* name */, jo3p);
3500*44704f69SBart Van Assche if (op->filter_given)
3501*44704f69SBart Van Assche break;
3502*44704f69SBart Van Assche num -= pl;
3503*44704f69SBart Van Assche bp += pl;
3504*44704f69SBart Van Assche }
3505*44704f69SBart Van Assche return true;
3506*44704f69SBart Van Assche }
3507*44704f69SBart Van Assche
3508*44704f69SBart Van Assche /* LAST_N_MODE_PG_DATA_CH_SUBPG [0xb,0x2] <lnmc> introduced: SPC-5 (rev 17) */
3509*44704f69SBart Van Assche static bool
show_last_n_mode_pg_data_ch_page(const uint8_t * resp,int len,struct opts_t * op,sgj_opaque_p jop)3510*44704f69SBart Van Assche show_last_n_mode_pg_data_ch_page(const uint8_t * resp, int len,
3511*44704f69SBart Van Assche struct opts_t * op, sgj_opaque_p jop)
3512*44704f69SBart Van Assche {
3513*44704f69SBart Van Assche bool spf;
3514*44704f69SBart Van Assche int j, k, num, pl, pg_code, spg_code;
3515*44704f69SBart Van Assche uint32_t n;
3516*44704f69SBart Van Assche const uint8_t * bp;
3517*44704f69SBart Van Assche const char * mode_pg_name = NULL;
3518*44704f69SBart Van Assche sgj_state * jsp = &op->json_st;
3519*44704f69SBart Van Assche sgj_opaque_p jo2p, jo4p;
3520*44704f69SBart Van Assche sgj_opaque_p jo3p = NULL;
3521*44704f69SBart Van Assche sgj_opaque_p jap = NULL;
3522*44704f69SBart Van Assche sgj_opaque_p ja2p;
3523*44704f69SBart Van Assche char str[PCB_STR_LEN];
3524*44704f69SBart Van Assche char b[128];
3525*44704f69SBart Van Assche static const char * lnmpdclp = "Last n mode page data changed log page";
3526*44704f69SBart Van Assche static const char * mpdci = "Mode page data changed indicator";
3527*44704f69SBart Van Assche
3528*44704f69SBart Van Assche if (op->verbose || ((! op->do_raw) && (0 == op->do_hex)))
3529*44704f69SBart Van Assche sgj_pr_hr(jsp, "%s [0xb,0x2]\n", lnmpdclp);
3530*44704f69SBart Van Assche num = len - 4;
3531*44704f69SBart Van Assche bp = &resp[0] + 4;
3532*44704f69SBart Van Assche if (jsp->pr_as_json) {
3533*44704f69SBart Van Assche jo2p = sg_log_js_hdr(jsp, jop, lnmpdclp, resp);
3534*44704f69SBart Van Assche jap = sgj_named_subarray_r(jsp, jo2p,
3535*44704f69SBart Van Assche "mode_page_data_changed_log_parameters");
3536*44704f69SBart Van Assche }
3537*44704f69SBart Van Assche
3538*44704f69SBart Van Assche while (num > 3) {
3539*44704f69SBart Van Assche int pc = sg_get_unaligned_be16(bp + 0);
3540*44704f69SBart Van Assche
3541*44704f69SBart Van Assche pl = bp[3] + 4;
3542*44704f69SBart Van Assche if (op->filter_given) {
3543*44704f69SBart Van Assche if (pc != op->filter)
3544*44704f69SBart Van Assche goto skip;
3545*44704f69SBart Van Assche }
3546*44704f69SBart Van Assche if (op->do_raw) {
3547*44704f69SBart Van Assche dStrRaw(bp, pl);
3548*44704f69SBart Van Assche break;
3549*44704f69SBart Van Assche } else if (op->do_hex) {
3550*44704f69SBart Van Assche hex2stdout(bp, pl, op->dstrhex_no_ascii);
3551*44704f69SBart Van Assche break;
3552*44704f69SBart Van Assche }
3553*44704f69SBart Van Assche if (jsp->pr_as_json) {
3554*44704f69SBart Van Assche jo3p = sgj_new_unattached_object_r(jsp);
3555*44704f69SBart Van Assche if (op->do_pcb)
3556*44704f69SBart Van Assche js_pcb(jsp, jo3p, bp[2]);
3557*44704f69SBart Van Assche sgj_js_nv_ihexstr(jsp, jo3p, param_c_sn, pc, NULL,
3558*44704f69SBart Van Assche 0 == pc ? clgc : mpdci);
3559*44704f69SBart Van Assche }
3560*44704f69SBart Van Assche if (0 == pc) { /* Same as LAST_N_INQUIRY_DATA_CH_SUBPG [0xb,0x1] */
3561*44704f69SBart Van Assche if (pl < 8) {
3562*44704f69SBart Van Assche pr2serr(" <<expect parameter 0x%x to be at least 8 bytes "
3563*44704f69SBart Van Assche "long, got %d, skip>>\n", pc, pl);
3564*44704f69SBart Van Assche goto skip;
3565*44704f69SBart Van Assche }
3566*44704f69SBart Van Assche sgj_pr_hr(jsp, " %s [pc=0x0]:\n", clgc);
3567*44704f69SBart Van Assche for (j = 4, k = 1; j < pl; j +=4, ++k) {
3568*44704f69SBart Van Assche n = sg_get_unaligned_be32(bp + j);
3569*44704f69SBart Van Assche sgj_pr_hr(jsp, " %s [0x%x]: %u\n", cgn, k, n);
3570*44704f69SBart Van Assche }
3571*44704f69SBart Van Assche if (jsp->pr_as_json) {
3572*44704f69SBart Van Assche ja2p = sgj_named_subarray_r(jsp, jo3p,
3573*44704f69SBart Van Assche "changed_generation_numbers");
3574*44704f69SBart Van Assche for (j = 4, k = 1; j < pl; j +=4, ++k) {
3575*44704f69SBart Van Assche jo4p = sgj_new_unattached_object_r(jsp);
3576*44704f69SBart Van Assche n = sg_get_unaligned_be32(bp + j);
3577*44704f69SBart Van Assche js_snakenv_ihexstr_nex(jsp, jo4p, cgn, n, true, NULL,
3578*44704f69SBart Van Assche NULL, NULL);
3579*44704f69SBart Van Assche sgj_js_nv_o(jsp, ja2p, NULL /* name */, jo4p);
3580*44704f69SBart Van Assche }
3581*44704f69SBart Van Assche }
3582*44704f69SBart Van Assche } else { /* pc > 0x0 */
3583*44704f69SBart Van Assche int k, val;
3584*44704f69SBart Van Assche const int nn = sg_lib_names_mode_len;
3585*44704f69SBart Van Assche struct sg_lib_simple_value_name_t * nmp = sg_lib_names_mode_arr;
3586*44704f69SBart Van Assche
3587*44704f69SBart Van Assche snprintf(b, sizeof(b), " %s 0x%x, ", param_c, pc);
3588*44704f69SBart Van Assche spf = !! (0x40 & *(bp + 4));
3589*44704f69SBart Van Assche pg_code = 0x3f & *(bp + 4);
3590*44704f69SBart Van Assche spg_code = *(bp + 5);
3591*44704f69SBart Van Assche if (spf) /* SPF bit set */
3592*44704f69SBart Van Assche sgj_pr_hr(jsp, "%smode page 0x%x,0%x changed\n", b, pg_code,
3593*44704f69SBart Van Assche spg_code);
3594*44704f69SBart Van Assche else
3595*44704f69SBart Van Assche sgj_pr_hr(jsp, "%smode page 0x%x changed\n", b, pg_code);
3596*44704f69SBart Van Assche
3597*44704f69SBart Van Assche val = (pg_code << 8) | spg_code;
3598*44704f69SBart Van Assche for (k = 0; k < nn; ++k, ++nmp) {
3599*44704f69SBart Van Assche if (nmp->value == val)
3600*44704f69SBart Van Assche break;
3601*44704f69SBart Van Assche }
3602*44704f69SBart Van Assche mode_pg_name = (k < nn) ? nmp->name : NULL;
3603*44704f69SBart Van Assche if ((0 == op->do_brief) && mode_pg_name)
3604*44704f69SBart Van Assche sgj_pr_hr(jsp, " name: %s\n", nmp->name);
3605*44704f69SBart Van Assche if (jsp->pr_as_json) {
3606*44704f69SBart Van Assche sgj_js_nv_i(jsp, jo3p, "spf", (int)spf);
3607*44704f69SBart Van Assche sgj_js_nv_ihex(jsp, jo3p, "mode_page_code", pg_code);
3608*44704f69SBart Van Assche sgj_js_nv_ihex(jsp, jo3p, "subpage_code", spg_code);
3609*44704f69SBart Van Assche if (mode_pg_name)
3610*44704f69SBart Van Assche sgj_js_nv_s(jsp, jo3p, "mode_page_name", mode_pg_name);
3611*44704f69SBart Van Assche }
3612*44704f69SBart Van Assche }
3613*44704f69SBart Van Assche if (op->do_pcb)
3614*44704f69SBart Van Assche sgj_pr_hr(jsp, " <%s>\n", get_pcb_str(bp[2],
3615*44704f69SBart Van Assche str, sizeof(str)));
3616*44704f69SBart Van Assche skip:
3617*44704f69SBart Van Assche if (jsp->pr_as_json)
3618*44704f69SBart Van Assche sgj_js_nv_o(jsp, jap, NULL /* name */, jo3p);
3619*44704f69SBart Van Assche if (op->filter_given)
3620*44704f69SBart Van Assche break;
3621*44704f69SBart Van Assche num -= pl;
3622*44704f69SBart Van Assche bp += pl;
3623*44704f69SBart Van Assche }
3624*44704f69SBart Van Assche return true;
3625*44704f69SBart Van Assche }
3626*44704f69SBart Van Assche
3627*44704f69SBart Van Assche static const char * self_test_code[] = {
3628*44704f69SBart Van Assche "default", "background short", "background extended", rsv_s,
3629*44704f69SBart Van Assche "aborted background", "foreground short", "foreground extended",
3630*44704f69SBart Van Assche rsv_s};
3631*44704f69SBart Van Assche
3632*44704f69SBart Van Assche static const char * self_test_result[] = {
3633*44704f69SBart Van Assche "completed without error",
3634*44704f69SBart Van Assche "aborted by SEND DIAGNOSTIC",
3635*44704f69SBart Van Assche "aborted other than by SEND DIAGNOSTIC",
3636*44704f69SBart Van Assche "unknown error, unable to complete",
3637*44704f69SBart Van Assche "self test completed with failure in test segment (which one unknown)",
3638*44704f69SBart Van Assche "first segment in self test failed",
3639*44704f69SBart Van Assche "second segment in self test failed",
3640*44704f69SBart Van Assche "another segment in self test failed",
3641*44704f69SBart Van Assche rsv_s, rsv_s, rsv_s, rsv_s, rsv_s, rsv_s,
3642*44704f69SBart Van Assche rsv_s,
3643*44704f69SBart Van Assche "self test in progress"};
3644*44704f69SBart Van Assche
3645*44704f69SBart Van Assche /* SELF_TEST_LPAGE [0x10] <str> introduced: SPC-3 */
3646*44704f69SBart Van Assche static bool
show_self_test_page(const uint8_t * resp,int len,struct opts_t * op,sgj_opaque_p jop)3647*44704f69SBart Van Assche show_self_test_page(const uint8_t * resp, int len, struct opts_t * op,
3648*44704f69SBart Van Assche sgj_opaque_p jop)
3649*44704f69SBart Van Assche {
3650*44704f69SBart Van Assche bool addr_all_ffs;
3651*44704f69SBart Van Assche int k, num, res, st_c;
3652*44704f69SBart Van Assche unsigned int v;
3653*44704f69SBart Van Assche uint32_t n;
3654*44704f69SBart Van Assche uint64_t ull;
3655*44704f69SBart Van Assche const uint8_t * bp;
3656*44704f69SBart Van Assche sgj_state * jsp = &op->json_st;
3657*44704f69SBart Van Assche sgj_opaque_p jo2p;
3658*44704f69SBart Van Assche sgj_opaque_p jo3p = NULL;
3659*44704f69SBart Van Assche sgj_opaque_p jap = NULL;
3660*44704f69SBart Van Assche char str[PCB_STR_LEN];
3661*44704f69SBart Van Assche char b[80];
3662*44704f69SBart Van Assche static const char * strlp = "Self-test results log page";
3663*44704f69SBart Van Assche static const char * stc_s = "Self-test code";
3664*44704f69SBart Van Assche static const char * str_s = "Self-test result";
3665*44704f69SBart Van Assche static const char * stn_s = "Self-test number";
3666*44704f69SBart Van Assche static const char * apoh = "Accumulated power on hours";
3667*44704f69SBart Van Assche
3668*44704f69SBart Van Assche num = len - 4;
3669*44704f69SBart Van Assche if (num < 0x190) {
3670*44704f69SBart Van Assche pr2serr("short %s [length 0x%x rather than 0x190 bytes]\n", strlp,
3671*44704f69SBart Van Assche num);
3672*44704f69SBart Van Assche return false;
3673*44704f69SBart Van Assche }
3674*44704f69SBart Van Assche if (op->verbose || ((! op->do_raw) && (0 == op->do_hex)))
3675*44704f69SBart Van Assche sgj_pr_hr(jsp, "%s [0x10]\n", strlp);
3676*44704f69SBart Van Assche if (jsp->pr_as_json) {
3677*44704f69SBart Van Assche jo2p = sg_log_js_hdr(jsp, jop, strlp, resp);
3678*44704f69SBart Van Assche jap = sgj_named_subarray_r(jsp, jo2p,
3679*44704f69SBart Van Assche "self_test_results_log_parameters");
3680*44704f69SBart Van Assche }
3681*44704f69SBart Van Assche
3682*44704f69SBart Van Assche for (k = 0, bp = resp + 4; k < 20; ++k, bp += 20 ) {
3683*44704f69SBart Van Assche int pc = sg_get_unaligned_be16(bp + 0);
3684*44704f69SBart Van Assche int pl = bp[3] + 4;
3685*44704f69SBart Van Assche
3686*44704f69SBart Van Assche if (op->filter_given) {
3687*44704f69SBart Van Assche if (pc != op->filter)
3688*44704f69SBart Van Assche continue;
3689*44704f69SBart Van Assche }
3690*44704f69SBart Van Assche if (op->do_raw) {
3691*44704f69SBart Van Assche dStrRaw(bp, pl);
3692*44704f69SBart Van Assche break;
3693*44704f69SBart Van Assche } else if (op->do_hex) {
3694*44704f69SBart Van Assche hex2stdout(bp, pl, op->dstrhex_no_ascii);
3695*44704f69SBart Van Assche break;
3696*44704f69SBart Van Assche }
3697*44704f69SBart Van Assche if (jsp->pr_as_json) {
3698*44704f69SBart Van Assche jo3p = sgj_new_unattached_object_r(jsp);
3699*44704f69SBart Van Assche if (op->do_pcb)
3700*44704f69SBart Van Assche js_pcb(jsp, jo3p, bp[2]);
3701*44704f69SBart Van Assche sgj_js_nv_ihexstr(jsp, jo3p, param_c_sn, pc, NULL,
3702*44704f69SBart Van Assche "Self-test results");
3703*44704f69SBart Van Assche }
3704*44704f69SBart Van Assche n = sg_get_unaligned_be16(bp + 6);
3705*44704f69SBart Van Assche if ((0 == n) && (0 == bp[4])) {
3706*44704f69SBart Van Assche if (jsp->pr_as_json)
3707*44704f69SBart Van Assche sgj_js_nv_o(jsp, jap, NULL /* name */, jo3p);
3708*44704f69SBart Van Assche break;
3709*44704f69SBart Van Assche }
3710*44704f69SBart Van Assche sgj_pr_hr(jsp, " %s = %d, accumulated power-on hours = %d\n",
3711*44704f69SBart Van Assche param_c, pc, n);
3712*44704f69SBart Van Assche st_c = (bp[4] >> 5) & 0x7;
3713*44704f69SBart Van Assche sgj_pr_hr(jsp, " %s: %s [%d]\n", stc_s, self_test_code[st_c],
3714*44704f69SBart Van Assche st_c);
3715*44704f69SBart Van Assche res = bp[4] & 0xf;
3716*44704f69SBart Van Assche sgj_pr_hr(jsp, " %s: %s [%d]\n", str_s, self_test_result[res],
3717*44704f69SBart Van Assche res);
3718*44704f69SBart Van Assche if (bp[5])
3719*44704f69SBart Van Assche sgj_pr_hr(jsp, " %s = %d\n", stn_s, (int)bp[5]);
3720*44704f69SBart Van Assche ull = sg_get_unaligned_be64(bp + 8);
3721*44704f69SBart Van Assche
3722*44704f69SBart Van Assche addr_all_ffs = sg_all_ffs(bp + 8, 8);
3723*44704f69SBart Van Assche if (! addr_all_ffs) {
3724*44704f69SBart Van Assche addr_all_ffs = false;
3725*44704f69SBart Van Assche if ((res > 0) && ( res < 0xf))
3726*44704f69SBart Van Assche sgj_pr_hr(jsp, " address of first error = 0x%" PRIx64 "\n",
3727*44704f69SBart Van Assche ull);
3728*44704f69SBart Van Assche }
3729*44704f69SBart Van Assche addr_all_ffs = false;
3730*44704f69SBart Van Assche v = bp[16] & 0xf;
3731*44704f69SBart Van Assche if (v) {
3732*44704f69SBart Van Assche if (op->do_brief)
3733*44704f69SBart Van Assche sgj_pr_hr(jsp, " %s = 0x%x , asc = 0x%x, ascq = 0x%x\n",
3734*44704f69SBart Van Assche s_key, v, bp[17], bp[18]);
3735*44704f69SBart Van Assche else {
3736*44704f69SBart Van Assche sgj_pr_hr(jsp, " %s = 0x%x [%s]\n", s_key, v,
3737*44704f69SBart Van Assche sg_get_sense_key_str(v, sizeof(b), b));
3738*44704f69SBart Van Assche
3739*44704f69SBart Van Assche sgj_pr_hr(jsp, " asc = 0x%x, ascq = 0x%x [%s]\n",
3740*44704f69SBart Van Assche bp[17], bp[18], sg_get_asc_ascq_str(bp[17], bp[18],
3741*44704f69SBart Van Assche sizeof(b), b));
3742*44704f69SBart Van Assche }
3743*44704f69SBart Van Assche }
3744*44704f69SBart Van Assche if (op->do_pcb)
3745*44704f69SBart Van Assche sgj_pr_hr(jsp, " <%s>\n", get_pcb_str(bp[2],
3746*44704f69SBart Van Assche str, sizeof(str)));
3747*44704f69SBart Van Assche if (jsp->pr_as_json) {
3748*44704f69SBart Van Assche js_snakenv_ihexstr_nex(jsp, jo3p, stc_s, st_c, true, NULL,
3749*44704f69SBart Van Assche self_test_code[st_c], NULL);
3750*44704f69SBart Van Assche js_snakenv_ihexstr_nex(jsp, jo3p, str_s, res, true, NULL,
3751*44704f69SBart Van Assche self_test_result[res], NULL);
3752*44704f69SBart Van Assche js_snakenv_ihexstr_nex(jsp, jo3p, stn_s, bp[5], false, NULL,
3753*44704f69SBart Van Assche NULL, "segment number that failed");
3754*44704f69SBart Van Assche js_snakenv_ihexstr_nex(jsp, jo3p, apoh, n, true, NULL,
3755*44704f69SBart Van Assche (0xffff == n ? "65535 hours or more" : NULL), NULL);
3756*44704f69SBart Van Assche sgj_js_nv_ihexstr(jsp, jo3p, "address_of_first_failure", pc, NULL,
3757*44704f69SBart Van Assche addr_all_ffs ? "no errors detected" : NULL);
3758*44704f69SBart Van Assche sgj_js_nv_ihexstr(jsp, jo3p, "sense_key", v, NULL,
3759*44704f69SBart Van Assche sg_get_sense_key_str(v, sizeof(b), b));
3760*44704f69SBart Van Assche sgj_js_nv_ihexstr(jsp, jo3p, "additional_sense_code", bp[17],
3761*44704f69SBart Van Assche NULL, NULL);
3762*44704f69SBart Van Assche sgj_js_nv_ihexstr(jsp, jo3p, "additional_sense_code_qualifier",
3763*44704f69SBart Van Assche bp[18], NULL, sg_get_asc_ascq_str(bp[17],
3764*44704f69SBart Van Assche bp[18], sizeof(b), b));
3765*44704f69SBart Van Assche sgj_js_nv_o(jsp, jap, NULL /* name */, jo3p);
3766*44704f69SBart Van Assche }
3767*44704f69SBart Van Assche if (op->filter_given)
3768*44704f69SBart Van Assche break;
3769*44704f69SBart Van Assche }
3770*44704f69SBart Van Assche return true;
3771*44704f69SBart Van Assche }
3772*44704f69SBart Van Assche
3773*44704f69SBart Van Assche /* TEMPERATURE_LPAGE [0xd] <temp> introduced: SPC-3
3774*44704f69SBart Van Assche * N.B. The ENV_REPORTING_SUBPG [0xd,0x1] and the ENV_LIMITS_SUBPG [0xd,0x2]
3775*44704f69SBart Van Assche * (both added SPC-5) are a superset of this page. */
3776*44704f69SBart Van Assche static bool
show_temperature_page(const uint8_t * resp,int len,struct opts_t * op,sgj_opaque_p jop)3777*44704f69SBart Van Assche show_temperature_page(const uint8_t * resp, int len, struct opts_t * op,
3778*44704f69SBart Van Assche sgj_opaque_p jop)
3779*44704f69SBart Van Assche {
3780*44704f69SBart Van Assche int k, num, extra;
3781*44704f69SBart Van Assche const uint8_t * bp;
3782*44704f69SBart Van Assche sgj_state * jsp = &op->json_st;
3783*44704f69SBart Van Assche sgj_opaque_p jo2p;
3784*44704f69SBart Van Assche sgj_opaque_p jo3p = NULL;
3785*44704f69SBart Van Assche sgj_opaque_p jap = NULL;
3786*44704f69SBart Van Assche char str[PCB_STR_LEN];
3787*44704f69SBart Van Assche static const char * tlp = "Temperature log page";
3788*44704f69SBart Van Assche static const char * ctemp = "Current temperature";
3789*44704f69SBart Van Assche static const char * rtemp = "Reference temperature";
3790*44704f69SBart Van Assche
3791*44704f69SBart Van Assche num = len - 4;
3792*44704f69SBart Van Assche bp = &resp[0] + 4;
3793*44704f69SBart Van Assche if (num < 4) {
3794*44704f69SBart Van Assche pr2serr("badly formed Temperature page\n");
3795*44704f69SBart Van Assche return false;
3796*44704f69SBart Van Assche }
3797*44704f69SBart Van Assche if (op->verbose || ((! op->do_raw) && (0 == op->do_hex))) {
3798*44704f69SBart Van Assche if (! op->do_temperature)
3799*44704f69SBart Van Assche sgj_pr_hr(jsp, "%s [0xd]\n", tlp);
3800*44704f69SBart Van Assche }
3801*44704f69SBart Van Assche if (jsp->pr_as_json) {
3802*44704f69SBart Van Assche jo2p = sg_log_js_hdr(jsp, jop, tlp, resp);
3803*44704f69SBart Van Assche jap = sgj_named_subarray_r(jsp, jo2p, "temperature_log_parameters");
3804*44704f69SBart Van Assche }
3805*44704f69SBart Van Assche
3806*44704f69SBart Van Assche for (k = num; k > 0; k -= extra, bp += extra) {
3807*44704f69SBart Van Assche int pc;
3808*44704f69SBart Van Assche
3809*44704f69SBart Van Assche if (k < 3) {
3810*44704f69SBart Van Assche pr2serr("short Temperature page\n");
3811*44704f69SBart Van Assche return true;
3812*44704f69SBart Van Assche }
3813*44704f69SBart Van Assche extra = bp[3] + 4;
3814*44704f69SBart Van Assche pc = sg_get_unaligned_be16(bp + 0);
3815*44704f69SBart Van Assche if (op->filter_given) {
3816*44704f69SBart Van Assche if (pc != op->filter)
3817*44704f69SBart Van Assche continue;
3818*44704f69SBart Van Assche }
3819*44704f69SBart Van Assche if (op->do_raw) {
3820*44704f69SBart Van Assche dStrRaw(bp, extra);
3821*44704f69SBart Van Assche goto skip;
3822*44704f69SBart Van Assche } else if (op->do_hex) {
3823*44704f69SBart Van Assche hex2stdout(bp, extra, op->dstrhex_no_ascii);
3824*44704f69SBart Van Assche goto skip;
3825*44704f69SBart Van Assche }
3826*44704f69SBart Van Assche if (jsp->pr_as_json) {
3827*44704f69SBart Van Assche jo3p = sgj_new_unattached_object_r(jsp);
3828*44704f69SBart Van Assche if (op->do_pcb)
3829*44704f69SBart Van Assche js_pcb(jsp, jo3p, bp[2]);
3830*44704f69SBart Van Assche sgj_js_nv_ihex(jsp, jo3p, param_c_sn, pc);
3831*44704f69SBart Van Assche }
3832*44704f69SBart Van Assche
3833*44704f69SBart Van Assche switch (pc) {
3834*44704f69SBart Van Assche case 0:
3835*44704f69SBart Van Assche if ((extra > 5) && (k > 5)) {
3836*44704f69SBart Van Assche if (0 == bp[5])
3837*44704f69SBart Van Assche sgj_pr_hr(jsp, " %s = 0 C (or less)\n", ctemp);
3838*44704f69SBart Van Assche else if (bp[5] < 0xff)
3839*44704f69SBart Van Assche sgj_pr_hr(jsp, " %s = %d C\n", ctemp, bp[5]);
3840*44704f69SBart Van Assche else
3841*44704f69SBart Van Assche sgj_pr_hr(jsp, " %s = <%s>\n", ctemp, not_avail);
3842*44704f69SBart Van Assche if (jsp->pr_as_json) {
3843*44704f69SBart Van Assche const char * cp = NULL;
3844*44704f69SBart Van Assche
3845*44704f69SBart Van Assche if (0 == bp[5])
3846*44704f69SBart Van Assche cp = "0 or less Celsius";
3847*44704f69SBart Van Assche else if (0xff == bp[5])
3848*44704f69SBart Van Assche cp = "temperature not available";
3849*44704f69SBart Van Assche js_snakenv_ihexstr_nex(jsp, jo3p, "temperature", bp[5],
3850*44704f69SBart Van Assche false, NULL, cp,
3851*44704f69SBart Van Assche "current [unit: celsius]");
3852*44704f69SBart Van Assche }
3853*44704f69SBart Van Assche }
3854*44704f69SBart Van Assche break;
3855*44704f69SBart Van Assche case 1:
3856*44704f69SBart Van Assche if ((extra > 5) && (k > 5)) {
3857*44704f69SBart Van Assche if (bp[5] < 0xff)
3858*44704f69SBart Van Assche sgj_pr_hr(jsp, " %s = %d C\n", rtemp, bp[5]);
3859*44704f69SBart Van Assche else
3860*44704f69SBart Van Assche sgj_pr_hr(jsp, " %s = <%s>\n", rtemp, not_avail);
3861*44704f69SBart Van Assche if (jsp->pr_as_json) {
3862*44704f69SBart Van Assche const char * cp;
3863*44704f69SBart Van Assche
3864*44704f69SBart Van Assche if (0 == bp[5])
3865*44704f69SBart Van Assche cp = "in C (or less)";
3866*44704f69SBart Van Assche else if (0xff == bp[5])
3867*44704f69SBart Van Assche cp = not_avail;
3868*44704f69SBart Van Assche else
3869*44704f69SBart Van Assche cp = "in C";
3870*44704f69SBart Van Assche sgj_js_nv_ihex_nex(jsp, jo3p, "reference_temperature",
3871*44704f69SBart Van Assche bp[5], true, cp);
3872*44704f69SBart Van Assche }
3873*44704f69SBart Van Assche }
3874*44704f69SBart Van Assche break;
3875*44704f69SBart Van Assche default:
3876*44704f69SBart Van Assche if (! op->do_temperature) {
3877*44704f69SBart Van Assche sgj_pr_hr(jsp, " unknown %s = 0x%x, contents in hex:\n",
3878*44704f69SBart Van Assche param_c, pc);
3879*44704f69SBart Van Assche hex2stdout(bp, extra, op->dstrhex_no_ascii);
3880*44704f69SBart Van Assche } else {
3881*44704f69SBart Van Assche if (jsp->pr_as_json)
3882*44704f69SBart Van Assche sgj_js_nv_o(jsp, jap, NULL /* name */, jo3p);
3883*44704f69SBart Van Assche continue;
3884*44704f69SBart Van Assche }
3885*44704f69SBart Van Assche break;
3886*44704f69SBart Van Assche }
3887*44704f69SBart Van Assche if (jsp->pr_as_json)
3888*44704f69SBart Van Assche sgj_js_nv_o(jsp, jap, NULL /* name */, jo3p);
3889*44704f69SBart Van Assche if (op->do_pcb)
3890*44704f69SBart Van Assche sgj_pr_hr(jsp, " <%s>\n", get_pcb_str(bp[2], str,
3891*44704f69SBart Van Assche sizeof(str)));
3892*44704f69SBart Van Assche skip:
3893*44704f69SBart Van Assche if (op->filter_given)
3894*44704f69SBart Van Assche break;
3895*44704f69SBart Van Assche }
3896*44704f69SBart Van Assche return true;
3897*44704f69SBart Van Assche }
3898*44704f69SBart Van Assche
3899*44704f69SBart Van Assche /* START_STOP_LPAGE [0xe] <sscc> introduced: SPC-3 */
3900*44704f69SBart Van Assche static bool
show_start_stop_page(const uint8_t * resp,int len,struct opts_t * op,sgj_opaque_p jop)3901*44704f69SBart Van Assche show_start_stop_page(const uint8_t * resp, int len, struct opts_t * op,
3902*44704f69SBart Van Assche sgj_opaque_p jop)
3903*44704f69SBart Van Assche {
3904*44704f69SBart Van Assche int k, num, extra;
3905*44704f69SBart Van Assche uint32_t val;
3906*44704f69SBart Van Assche const uint8_t * bp;
3907*44704f69SBart Van Assche sgj_state * jsp = &op->json_st;
3908*44704f69SBart Van Assche sgj_opaque_p jo2p;
3909*44704f69SBart Van Assche sgj_opaque_p jo3p = NULL;
3910*44704f69SBart Van Assche sgj_opaque_p jap = NULL;
3911*44704f69SBart Van Assche char str[PCB_STR_LEN];
3912*44704f69SBart Van Assche char b[256];
3913*44704f69SBart Van Assche static const char * sscclp = "Start-stop cycle counter log page";
3914*44704f69SBart Van Assche static const char * dom = "Date of manufacture";
3915*44704f69SBart Van Assche static const char * ad = "Accounting date";
3916*44704f69SBart Van Assche static const char * sccodl = "Specified cycle count over device lifetime";
3917*44704f69SBart Van Assche static const char * assc = "Accumulated start-stop cycles";
3918*44704f69SBart Van Assche static const char * slucodl =
3919*44704f69SBart Van Assche "Specified load-unload count over device lifetime";
3920*44704f69SBart Van Assche static const char * aluc = "Accumulated load-unload cycles";
3921*44704f69SBart Van Assche
3922*44704f69SBart Van Assche num = len - 4;
3923*44704f69SBart Van Assche bp = &resp[0] + 4;
3924*44704f69SBart Van Assche if (num < 4) {
3925*44704f69SBart Van Assche pr2serr("badly formed Start-stop cycle counter page\n");
3926*44704f69SBart Van Assche return false;
3927*44704f69SBart Van Assche }
3928*44704f69SBart Van Assche if (op->verbose || ((! op->do_raw) && (0 == op->do_hex)))
3929*44704f69SBart Van Assche sgj_pr_hr(jsp, "%s [0xe]\n", sscclp);
3930*44704f69SBart Van Assche if (jsp->pr_as_json) {
3931*44704f69SBart Van Assche jo2p = sg_log_js_hdr(jsp, jop, sscclp, resp);
3932*44704f69SBart Van Assche jap = sgj_named_subarray_r(jsp, jo2p,
3933*44704f69SBart Van Assche "start_stop_cycle_log_parameters");
3934*44704f69SBart Van Assche }
3935*44704f69SBart Van Assche
3936*44704f69SBart Van Assche for (k = num; k > 0; k -= extra, bp += extra) {
3937*44704f69SBart Van Assche int pc;
3938*44704f69SBart Van Assche
3939*44704f69SBart Van Assche if (k < 3) {
3940*44704f69SBart Van Assche pr2serr("short %s\n", sscclp);
3941*44704f69SBart Van Assche return false;
3942*44704f69SBart Van Assche }
3943*44704f69SBart Van Assche extra = bp[3] + 4;
3944*44704f69SBart Van Assche pc = sg_get_unaligned_be16(bp + 0);
3945*44704f69SBart Van Assche if (op->filter_given) {
3946*44704f69SBart Van Assche if (pc != op->filter)
3947*44704f69SBart Van Assche continue;
3948*44704f69SBart Van Assche }
3949*44704f69SBart Van Assche if (op->do_raw) {
3950*44704f69SBart Van Assche dStrRaw(bp, extra);
3951*44704f69SBart Van Assche goto skip;
3952*44704f69SBart Van Assche } else if (op->do_hex) {
3953*44704f69SBart Van Assche hex2stdout(bp, extra, op->dstrhex_no_ascii);
3954*44704f69SBart Van Assche goto skip;
3955*44704f69SBart Van Assche }
3956*44704f69SBart Van Assche if (jsp->pr_as_json) {
3957*44704f69SBart Van Assche jo3p = sgj_new_unattached_object_r(jsp);
3958*44704f69SBart Van Assche if (op->do_pcb)
3959*44704f69SBart Van Assche js_pcb(jsp, jo3p, bp[2]);
3960*44704f69SBart Van Assche }
3961*44704f69SBart Van Assche
3962*44704f69SBart Van Assche switch (pc) {
3963*44704f69SBart Van Assche case 1:
3964*44704f69SBart Van Assche if (10 == extra) {
3965*44704f69SBart Van Assche sgj_pr_hr(jsp, " %s, year: %.4s, week: %.2s\n", dom,
3966*44704f69SBart Van Assche bp + 4, bp + 8);
3967*44704f69SBart Van Assche if (jsp->pr_as_json) {
3968*44704f69SBart Van Assche sgj_js_nv_ihexstr(jsp, jo3p, param_c_sn, pc, NULL,
3969*44704f69SBart Van Assche "Date of manufacture");
3970*44704f69SBart Van Assche sgj_js_nv_s_len(jsp, jo3p, "year_of_manufacture",
3971*44704f69SBart Van Assche (const char *)(bp + 4), 4);
3972*44704f69SBart Van Assche sgj_js_nv_s_len(jsp, jo3p, "week_of_manufacture",
3973*44704f69SBart Van Assche (const char *)(bp + 8), 2);
3974*44704f69SBart Van Assche }
3975*44704f69SBart Van Assche } else if (op->verbose) {
3976*44704f69SBart Van Assche pr2serr("%s parameter length strange: %d\n", dom, extra - 4);
3977*44704f69SBart Van Assche hex2stderr(bp, extra, 1);
3978*44704f69SBart Van Assche }
3979*44704f69SBart Van Assche break;
3980*44704f69SBart Van Assche case 2:
3981*44704f69SBart Van Assche if (10 == extra) {
3982*44704f69SBart Van Assche sgj_pr_hr(jsp, " %s, year: %.4s, week: %.2s\n", ad, bp + 4,
3983*44704f69SBart Van Assche bp + 8);
3984*44704f69SBart Van Assche if (jsp->pr_as_json) {
3985*44704f69SBart Van Assche sgj_js_nv_ihexstr(jsp, jo3p, param_c_sn, pc, NULL,
3986*44704f69SBart Van Assche "Accounting date");
3987*44704f69SBart Van Assche sgj_js_nv_s_len(jsp, jo3p, "year_of_manufacture",
3988*44704f69SBart Van Assche (const char *)(bp + 4), 4);
3989*44704f69SBart Van Assche sgj_js_nv_s_len(jsp, jo3p, "week_of_manufacture",
3990*44704f69SBart Van Assche (const char *)(bp + 8), 2);
3991*44704f69SBart Van Assche }
3992*44704f69SBart Van Assche } else if (op->verbose) {
3993*44704f69SBart Van Assche pr2serr("%s parameter length strange: %d\n", ad, extra - 4);
3994*44704f69SBart Van Assche hex2stderr(bp, extra, 1);
3995*44704f69SBart Van Assche }
3996*44704f69SBart Van Assche break;
3997*44704f69SBart Van Assche case 3:
3998*44704f69SBart Van Assche if (extra > 7) {
3999*44704f69SBart Van Assche val = sg_get_unaligned_be32(bp + 4);
4000*44704f69SBart Van Assche sgj_pr_hr(jsp, " %s = %u\n", sccodl, val);
4001*44704f69SBart Van Assche if (jsp->pr_as_json) {
4002*44704f69SBart Van Assche sgj_js_nv_ihexstr(jsp, jo3p, param_c_sn, pc, NULL,
4003*44704f69SBart Van Assche sccodl);
4004*44704f69SBart Van Assche js_snakenv_ihexstr_nex(jsp, jo3p, sccodl, val, false,
4005*44704f69SBart Van Assche NULL, NULL, NULL);
4006*44704f69SBart Van Assche }
4007*44704f69SBart Van Assche }
4008*44704f69SBart Van Assche break;
4009*44704f69SBart Van Assche case 4:
4010*44704f69SBart Van Assche if (extra > 7) {
4011*44704f69SBart Van Assche val = sg_get_unaligned_be32(bp + 4);
4012*44704f69SBart Van Assche sgj_pr_hr(jsp, " %s = %u\n", assc, val);
4013*44704f69SBart Van Assche if (jsp->pr_as_json) {
4014*44704f69SBart Van Assche sgj_js_nv_ihexstr(jsp, jo3p, param_c_sn, pc, NULL,
4015*44704f69SBart Van Assche assc);
4016*44704f69SBart Van Assche js_snakenv_ihexstr_nex(jsp, jo3p, assc, val, false,
4017*44704f69SBart Van Assche NULL, NULL, NULL);
4018*44704f69SBart Van Assche }
4019*44704f69SBart Van Assche }
4020*44704f69SBart Van Assche break;
4021*44704f69SBart Van Assche case 5:
4022*44704f69SBart Van Assche if (extra > 7) {
4023*44704f69SBart Van Assche val = sg_get_unaligned_be32(bp + 4);
4024*44704f69SBart Van Assche sgj_pr_hr(jsp, " %s = %u\n", slucodl, val);
4025*44704f69SBart Van Assche if (jsp->pr_as_json) {
4026*44704f69SBart Van Assche sgj_js_nv_ihexstr(jsp, jo3p, param_c_sn, pc, NULL,
4027*44704f69SBart Van Assche slucodl);
4028*44704f69SBart Van Assche js_snakenv_ihexstr_nex(jsp, jo3p, slucodl, val, false,
4029*44704f69SBart Van Assche NULL, NULL, NULL);
4030*44704f69SBart Van Assche }
4031*44704f69SBart Van Assche }
4032*44704f69SBart Van Assche break;
4033*44704f69SBart Van Assche case 6:
4034*44704f69SBart Van Assche if (extra > 7) {
4035*44704f69SBart Van Assche val = sg_get_unaligned_be32(bp + 4);
4036*44704f69SBart Van Assche sgj_pr_hr(jsp, " %s = %u\n", aluc, val);
4037*44704f69SBart Van Assche if (jsp->pr_as_json) {
4038*44704f69SBart Van Assche sgj_js_nv_ihexstr(jsp, jo3p, param_c_sn, pc, NULL, aluc);
4039*44704f69SBart Van Assche js_snakenv_ihexstr_nex(jsp, jo3p, aluc, val, false,
4040*44704f69SBart Van Assche NULL, NULL, NULL);
4041*44704f69SBart Van Assche }
4042*44704f69SBart Van Assche }
4043*44704f69SBart Van Assche break;
4044*44704f69SBart Van Assche default:
4045*44704f69SBart Van Assche sgj_pr_hr(jsp, " unknown %s = 0x%x, contents in hex:\n",
4046*44704f69SBart Van Assche param_c, pc);
4047*44704f69SBart Van Assche hex2str(bp, extra, " ", op->hex2str_oformat, sizeof(b), b);
4048*44704f69SBart Van Assche sgj_pr_hr(jsp, "%s\n", b);
4049*44704f69SBart Van Assche if (jsp->pr_as_json) {
4050*44704f69SBart Van Assche sgj_js_nv_ihexstr(jsp, jo3p, param_c_sn, pc, NULL, unknown_s);
4051*44704f69SBart Van Assche sgj_js_nv_hex_bytes(jsp, jo3p, in_hex, bp, extra);
4052*44704f69SBart Van Assche }
4053*44704f69SBart Van Assche break;
4054*44704f69SBart Van Assche }
4055*44704f69SBart Van Assche if (jsp->pr_as_json)
4056*44704f69SBart Van Assche sgj_js_nv_o(jsp, jap, NULL /* name */, jo3p);
4057*44704f69SBart Van Assche if (op->do_pcb)
4058*44704f69SBart Van Assche sgj_pr_hr(jsp, " <%s>\n", get_pcb_str(bp[2], str,
4059*44704f69SBart Van Assche sizeof(str)));
4060*44704f69SBart Van Assche skip:
4061*44704f69SBart Van Assche if (op->filter_given)
4062*44704f69SBart Van Assche break;
4063*44704f69SBart Van Assche }
4064*44704f69SBart Van Assche return true;
4065*44704f69SBart Van Assche }
4066*44704f69SBart Van Assche
4067*44704f69SBart Van Assche /* APP_CLIENT_LPAGE [0xf] <ac> introduced: SPC-3 */
4068*44704f69SBart Van Assche static bool
show_app_client_page(const uint8_t * resp,int len,struct opts_t * op,sgj_opaque_p jop)4069*44704f69SBart Van Assche show_app_client_page(const uint8_t * resp, int len, struct opts_t * op,
4070*44704f69SBart Van Assche sgj_opaque_p jop)
4071*44704f69SBart Van Assche {
4072*44704f69SBart Van Assche int k, n, num, extra;
4073*44704f69SBart Van Assche char * mp;
4074*44704f69SBart Van Assche const uint8_t * bp;
4075*44704f69SBart Van Assche sgj_state * jsp = &op->json_st;
4076*44704f69SBart Van Assche sgj_opaque_p jo2p = NULL;
4077*44704f69SBart Van Assche sgj_opaque_p jo3p = NULL;
4078*44704f69SBart Van Assche sgj_opaque_p jap = NULL;
4079*44704f69SBart Van Assche char str[PCB_STR_LEN];
4080*44704f69SBart Van Assche static const char * aclp = "Application Client log page";
4081*44704f69SBart Van Assche static const char * guac = "General Usage Application Client";
4082*44704f69SBart Van Assche
4083*44704f69SBart Van Assche num = len - 4;
4084*44704f69SBart Van Assche bp = &resp[0] + 4;
4085*44704f69SBart Van Assche if (num < 4) {
4086*44704f69SBart Van Assche pr2serr("badly formed %s\n", aclp);
4087*44704f69SBart Van Assche return false;
4088*44704f69SBart Van Assche }
4089*44704f69SBart Van Assche if (op->verbose || ((! op->do_raw) && (op->do_hex == 0)))
4090*44704f69SBart Van Assche sgj_pr_hr(jsp, "%s [0xf]\n", aclp);
4091*44704f69SBart Van Assche if (jsp->pr_as_json)
4092*44704f69SBart Van Assche jo2p = sg_log_js_hdr(jsp, jop, aclp, resp);
4093*44704f69SBart Van Assche if ((0 == op->filter_given) && (! op->do_full)) {
4094*44704f69SBart Van Assche if ((len > 128) && (0 == op->do_hex) && (0 == op->undefined_hex)) {
4095*44704f69SBart Van Assche char d[256];
4096*44704f69SBart Van Assche
4097*44704f69SBart Van Assche hex2str(resp, 64, " ", op->hex2str_oformat, sizeof(d), d);
4098*44704f69SBart Van Assche sgj_pr_hr(jsp, "%s", d);
4099*44704f69SBart Van Assche sgj_pr_hr(jsp, " ..... [truncated after 64 of %d bytes (use "
4100*44704f69SBart Van Assche "'-H' to see the rest)]\n", len);
4101*44704f69SBart Van Assche if (jsp->pr_as_json) {
4102*44704f69SBart Van Assche sgj_js_nv_ihex(jsp, jo2p, "actual_length", len);
4103*44704f69SBart Van Assche sgj_js_nv_ihex(jsp, jo2p, "truncated_length", 64);
4104*44704f69SBart Van Assche sgj_js_nv_hex_bytes(jsp, jo2p, in_hex, resp, 64);
4105*44704f69SBart Van Assche }
4106*44704f69SBart Van Assche } else {
4107*44704f69SBart Van Assche n = len * 4 + 32;
4108*44704f69SBart Van Assche mp = malloc(n);
4109*44704f69SBart Van Assche if (mp) {
4110*44704f69SBart Van Assche hex2str(resp, len, " ", op->hex2str_oformat, n, mp);
4111*44704f69SBart Van Assche sgj_pr_hr(jsp, "%s", mp);
4112*44704f69SBart Van Assche if (jsp->pr_as_json) {
4113*44704f69SBart Van Assche sgj_js_nv_ihex(jsp, jo2p, "length", len);
4114*44704f69SBart Van Assche sgj_js_nv_hex_bytes(jsp, jo2p, in_hex, resp, len);
4115*44704f69SBart Van Assche }
4116*44704f69SBart Van Assche free(mp);
4117*44704f69SBart Van Assche }
4118*44704f69SBart Van Assche }
4119*44704f69SBart Van Assche return true;
4120*44704f69SBart Van Assche }
4121*44704f69SBart Van Assche if (jsp->pr_as_json)
4122*44704f69SBart Van Assche jap = sgj_named_subarray_r(jsp, jo2p,
4123*44704f69SBart Van Assche "application_client_log_parameters");
4124*44704f69SBart Van Assche
4125*44704f69SBart Van Assche /* here if filter_given set or --full given */
4126*44704f69SBart Van Assche for (k = num; k > 0; k -= extra, bp += extra) {
4127*44704f69SBart Van Assche int pc;
4128*44704f69SBart Van Assche char d[1024];
4129*44704f69SBart Van Assche
4130*44704f69SBart Van Assche if (k < 3) {
4131*44704f69SBart Van Assche pr2serr("short %s\n", aclp);
4132*44704f69SBart Van Assche return true;
4133*44704f69SBart Van Assche }
4134*44704f69SBart Van Assche extra = bp[3] + 4;
4135*44704f69SBart Van Assche pc = sg_get_unaligned_be16(bp + 0);
4136*44704f69SBart Van Assche if (op->filter_given) {
4137*44704f69SBart Van Assche if (pc != op->filter)
4138*44704f69SBart Van Assche continue;
4139*44704f69SBart Van Assche }
4140*44704f69SBart Van Assche if (op->do_raw) {
4141*44704f69SBart Van Assche dStrRaw(bp, extra);
4142*44704f69SBart Van Assche break;
4143*44704f69SBart Van Assche }
4144*44704f69SBart Van Assche if (jsp->pr_as_json) {
4145*44704f69SBart Van Assche jo3p = sgj_new_unattached_object_r(jsp);
4146*44704f69SBart Van Assche if (op->do_pcb)
4147*44704f69SBart Van Assche js_pcb(jsp, jo3p, bp[2]);
4148*44704f69SBart Van Assche }
4149*44704f69SBart Van Assche sgj_pr_hr(jsp, " %s = %d [0x%x] %s\n", param_c, pc, pc,
4150*44704f69SBart Van Assche (pc <= 0xfff) ? guac : "");
4151*44704f69SBart Van Assche hex2str(bp, extra, " ", op->hex2str_oformat, sizeof(d), d);
4152*44704f69SBart Van Assche sgj_pr_hr(jsp, "%s", d);
4153*44704f69SBart Van Assche if (jsp->pr_as_json) {
4154*44704f69SBart Van Assche sgj_js_nv_ihexstr(jsp, jo3p, param_c_sn, pc, NULL,
4155*44704f69SBart Van Assche (pc <= 0xfff) ? guac : NULL);
4156*44704f69SBart Van Assche sgj_js_nv_hex_bytes(jsp, jo3p, in_hex, bp, extra);
4157*44704f69SBart Van Assche sgj_js_nv_o(jsp, jap, NULL /* name */, jo3p);
4158*44704f69SBart Van Assche }
4159*44704f69SBart Van Assche if (op->do_pcb)
4160*44704f69SBart Van Assche sgj_pr_hr(jsp, " <%s>\n", get_pcb_str(bp[2], str,
4161*44704f69SBart Van Assche sizeof(str)));
4162*44704f69SBart Van Assche if (op->filter_given)
4163*44704f69SBart Van Assche break;
4164*44704f69SBart Van Assche }
4165*44704f69SBart Van Assche return true;
4166*44704f69SBart Van Assche }
4167*44704f69SBart Van Assche
4168*44704f69SBart Van Assche /* IE_LPAGE [0x2f] <ie> "Informational Exceptions" introduced: SPC-3
4169*44704f69SBart Van Assche * Previously known as "SMART Status and Temperature Reading" lpage. */
4170*44704f69SBart Van Assche static bool
show_ie_page(const uint8_t * resp,int len,struct opts_t * op,sgj_opaque_p jop)4171*44704f69SBart Van Assche show_ie_page(const uint8_t * resp, int len, struct opts_t * op,
4172*44704f69SBart Van Assche sgj_opaque_p jop)
4173*44704f69SBart Van Assche {
4174*44704f69SBart Van Assche bool skip = false;
4175*44704f69SBart Van Assche int k, num, param_len;
4176*44704f69SBart Van Assche const uint8_t * bp;
4177*44704f69SBart Van Assche const char * cp;
4178*44704f69SBart Van Assche sgj_state * jsp = &op->json_st;
4179*44704f69SBart Van Assche sgj_opaque_p jo2p;
4180*44704f69SBart Van Assche sgj_opaque_p jo3p = NULL;
4181*44704f69SBart Van Assche sgj_opaque_p jap = NULL;
4182*44704f69SBart Van Assche char str[PCB_STR_LEN];
4183*44704f69SBart Van Assche char b[512];
4184*44704f69SBart Van Assche char bb[64];
4185*44704f69SBart Van Assche bool full, decoded;
4186*44704f69SBart Van Assche static const char * ielp = "Informational exceptions log page";
4187*44704f69SBart Van Assche static const char * ieasc =
4188*44704f69SBart Van Assche "informational_exceptions_additional_sense_code";
4189*44704f69SBart Van Assche static const char * ct = "Current temperature";
4190*44704f69SBart Van Assche static const char * tt = "Threshold temperature";
4191*44704f69SBart Van Assche static const char * mt = "Maximum temperature";
4192*44704f69SBart Van Assche static const char * ce = "common extension";
4193*44704f69SBart Van Assche
4194*44704f69SBart Van Assche full = ! op->do_temperature;
4195*44704f69SBart Van Assche num = len - 4;
4196*44704f69SBart Van Assche bp = &resp[0] + 4;
4197*44704f69SBart Van Assche if (num < 4) {
4198*44704f69SBart Van Assche pr2serr("badly formed %s\n", ielp);
4199*44704f69SBart Van Assche return false;
4200*44704f69SBart Van Assche }
4201*44704f69SBart Van Assche if (op->verbose || ((! op->do_raw) && (0 == op->do_hex))) {
4202*44704f69SBart Van Assche if (full)
4203*44704f69SBart Van Assche sgj_pr_hr(jsp, "%s [0x2f]\n", ielp);
4204*44704f69SBart Van Assche }
4205*44704f69SBart Van Assche if (jsp->pr_as_json) {
4206*44704f69SBart Van Assche jo2p = sg_log_js_hdr(jsp, jop, ielp, resp);
4207*44704f69SBart Van Assche jap = sgj_named_subarray_r(jsp, jo2p,
4208*44704f69SBart Van Assche "informational_exceptions_log_parameters");
4209*44704f69SBart Van Assche }
4210*44704f69SBart Van Assche
4211*44704f69SBart Van Assche for (k = num; k > 0; k -= param_len, bp += param_len) {
4212*44704f69SBart Van Assche int pc;
4213*44704f69SBart Van Assche
4214*44704f69SBart Van Assche if (k < 3) {
4215*44704f69SBart Van Assche pr2serr("short %s\n", ielp);
4216*44704f69SBart Van Assche return false;
4217*44704f69SBart Van Assche }
4218*44704f69SBart Van Assche param_len = bp[3] + 4;
4219*44704f69SBart Van Assche pc = sg_get_unaligned_be16(bp + 0);
4220*44704f69SBart Van Assche if (op->filter_given) {
4221*44704f69SBart Van Assche if (pc != op->filter)
4222*44704f69SBart Van Assche continue;
4223*44704f69SBart Van Assche }
4224*44704f69SBart Van Assche if (op->do_raw) {
4225*44704f69SBart Van Assche dStrRaw(bp, param_len);
4226*44704f69SBart Van Assche goto skip;
4227*44704f69SBart Van Assche } else if (op->do_hex) {
4228*44704f69SBart Van Assche hex2stdout(bp, param_len, op->dstrhex_no_ascii);
4229*44704f69SBart Van Assche goto skip;
4230*44704f69SBart Van Assche }
4231*44704f69SBart Van Assche if (jsp->pr_as_json) {
4232*44704f69SBart Van Assche jo3p = sgj_new_unattached_object_r(jsp);
4233*44704f69SBart Van Assche if (op->do_pcb)
4234*44704f69SBart Van Assche js_pcb(jsp, jo3p, bp[2]);
4235*44704f69SBart Van Assche }
4236*44704f69SBart Van Assche decoded = true;
4237*44704f69SBart Van Assche cp = NULL;
4238*44704f69SBart Van Assche
4239*44704f69SBart Van Assche switch (pc) {
4240*44704f69SBart Van Assche case 0x0:
4241*44704f69SBart Van Assche if (param_len > 5) {
4242*44704f69SBart Van Assche bool na;
4243*44704f69SBart Van Assche uint8_t t;
4244*44704f69SBart Van Assche
4245*44704f69SBart Van Assche if (full) {
4246*44704f69SBart Van Assche sgj_pr_hr(jsp, " IE asc = 0x%x, ascq = 0x%x\n", bp[4],
4247*44704f69SBart Van Assche bp[5]);
4248*44704f69SBart Van Assche if (bp[4] || bp[5])
4249*44704f69SBart Van Assche if(sg_get_asc_ascq_str(bp[4], bp[5], sizeof(b), b))
4250*44704f69SBart Van Assche sgj_pr_hr(jsp, " [%s]\n", b);
4251*44704f69SBart Van Assche if (jsp->pr_as_json) {
4252*44704f69SBart Van Assche sgj_js_nv_ihexstr(jsp, jo3p, param_c_sn, pc, NULL,
4253*44704f69SBart Van Assche "Informational exceptions general");
4254*44704f69SBart Van Assche sgj_js_nv_ihexstr(jsp, jo3p, ieasc, bp[4], NULL,
4255*44704f69SBart Van Assche NULL);
4256*44704f69SBart Van Assche snprintf(b, sizeof(b), "%s_qualifier", ieasc);
4257*44704f69SBart Van Assche sgj_js_nv_ihexstr(jsp, jo3p, b, bp[5], NULL,
4258*44704f69SBart Van Assche sg_get_asc_ascq_str(bp[4], bp[5],
4259*44704f69SBart Van Assche sizeof(bb), bb));
4260*44704f69SBart Van Assche }
4261*44704f69SBart Van Assche }
4262*44704f69SBart Van Assche if (param_len <= 6)
4263*44704f69SBart Van Assche break;
4264*44704f69SBart Van Assche t = bp[6];
4265*44704f69SBart Van Assche na = (0xff == t);
4266*44704f69SBart Van Assche if (na)
4267*44704f69SBart Van Assche snprintf(b, sizeof(b), "%u C", t);
4268*44704f69SBart Van Assche else
4269*44704f69SBart Van Assche snprintf(b, sizeof(b), "<%s>", unknown_s);
4270*44704f69SBart Van Assche sgj_pr_hr(jsp, " %s = %s\n", ct, b);
4271*44704f69SBart Van Assche if (jsp->pr_as_json)
4272*44704f69SBart Van Assche js_snakenv_ihexstr_nex(jsp, jo3p, ct, t, true,
4273*44704f69SBart Van Assche NULL, na ? unknown_s : NULL,
4274*44704f69SBart Van Assche "[unit: celsius]");
4275*44704f69SBart Van Assche if (param_len > 7) {
4276*44704f69SBart Van Assche t = bp[7];
4277*44704f69SBart Van Assche na = (0xff == t);
4278*44704f69SBart Van Assche if (na)
4279*44704f69SBart Van Assche snprintf(b, sizeof(b), "%u C", t);
4280*44704f69SBart Van Assche else
4281*44704f69SBart Van Assche snprintf(b, sizeof(b), "<%s>", unknown_s);
4282*44704f69SBart Van Assche sgj_pr_hr(jsp, " %s = %s [%s]\n", tt, b, ce);
4283*44704f69SBart Van Assche if (jsp->pr_as_json)
4284*44704f69SBart Van Assche js_snakenv_ihexstr_nex(jsp, jo3p, tt, t, true, NULL,
4285*44704f69SBart Van Assche na ? unknown_s : NULL, ce);
4286*44704f69SBart Van Assche t = bp[8];
4287*44704f69SBart Van Assche if ((param_len > 8) && (t >= bp[6])) {
4288*44704f69SBart Van Assche na = (0xff == t);
4289*44704f69SBart Van Assche if (na)
4290*44704f69SBart Van Assche snprintf(b, sizeof(b), "%u C", t);
4291*44704f69SBart Van Assche else
4292*44704f69SBart Van Assche snprintf(b, sizeof(b), "<%s>", unknown_s);
4293*44704f69SBart Van Assche sgj_pr_hr(jsp, " %s = %s [%s]\n", mt, b, ce);
4294*44704f69SBart Van Assche if (jsp->pr_as_json)
4295*44704f69SBart Van Assche js_snakenv_ihexstr_nex(jsp, jo3p, mt, t, true,
4296*44704f69SBart Van Assche NULL,
4297*44704f69SBart Van Assche na ? unknown_s : NULL, ce);
4298*44704f69SBart Van Assche }
4299*44704f69SBart Van Assche }
4300*44704f69SBart Van Assche }
4301*44704f69SBart Van Assche decoded = true;
4302*44704f69SBart Van Assche break;
4303*44704f69SBart Van Assche default:
4304*44704f69SBart Van Assche if (op->do_brief > 0) {
4305*44704f69SBart Van Assche cp = NULL;
4306*44704f69SBart Van Assche skip = true;
4307*44704f69SBart Van Assche break;
4308*44704f69SBart Van Assche }
4309*44704f69SBart Van Assche if (VP_HITA == op->vend_prod_num) {
4310*44704f69SBart Van Assche switch (pc) {
4311*44704f69SBart Van Assche case 0x1:
4312*44704f69SBart Van Assche cp = "Remaining reserve 1";
4313*44704f69SBart Van Assche break;
4314*44704f69SBart Van Assche case 0x2:
4315*44704f69SBart Van Assche cp = "Remaining reserve XOR";
4316*44704f69SBart Van Assche break;
4317*44704f69SBart Van Assche case 0x3:
4318*44704f69SBart Van Assche cp = "XOR depletion";
4319*44704f69SBart Van Assche break;
4320*44704f69SBart Van Assche case 0x4:
4321*44704f69SBart Van Assche cp = "Volatile memory backup failure";
4322*44704f69SBart Van Assche break;
4323*44704f69SBart Van Assche case 0x5:
4324*44704f69SBart Van Assche cp = "Wear indicator";
4325*44704f69SBart Van Assche break;
4326*44704f69SBart Van Assche case 0x6:
4327*44704f69SBart Van Assche cp = "System area wear indicator";
4328*44704f69SBart Van Assche break;
4329*44704f69SBart Van Assche case 0x7:
4330*44704f69SBart Van Assche cp = "Channel hangs";
4331*44704f69SBart Van Assche break;
4332*44704f69SBart Van Assche case 0x8:
4333*44704f69SBart Van Assche cp = "Flash scan failure";
4334*44704f69SBart Van Assche break;
4335*44704f69SBart Van Assche default:
4336*44704f69SBart Van Assche decoded = false;
4337*44704f69SBart Van Assche break;
4338*44704f69SBart Van Assche }
4339*44704f69SBart Van Assche if (cp) {
4340*44704f69SBart Van Assche sgj_pr_hr(jsp, " %s:\n", cp);
4341*44704f69SBart Van Assche sgj_pr_hr(jsp, " SMART sense_code=0x%x sense_qualifier"
4342*44704f69SBart Van Assche "=0x%x threshold=%d%% trip=%d\n", bp[4], bp[5],
4343*44704f69SBart Van Assche bp[6], bp[7]);
4344*44704f69SBart Van Assche if (jsp->pr_as_json) {
4345*44704f69SBart Van Assche sgj_js_nv_ihexstr(jsp, jo3p, param_c_sn, pc, NULL,
4346*44704f69SBart Van Assche cp);
4347*44704f69SBart Van Assche sgj_js_nv_ihex(jsp, jo3p, "smart_sense_code", bp[4]);
4348*44704f69SBart Van Assche sgj_js_nv_ihex(jsp, jo3p, "smart_sense_qualifier",
4349*44704f69SBart Van Assche bp[5]);
4350*44704f69SBart Van Assche sgj_js_nv_ihex(jsp, jo3p, "smart_threshold", bp[6]);
4351*44704f69SBart Van Assche sgj_js_nv_ihex(jsp, jo3p, "smart_trip", bp[7]);
4352*44704f69SBart Van Assche }
4353*44704f69SBart Van Assche }
4354*44704f69SBart Van Assche } else {
4355*44704f69SBart Van Assche decoded = false;
4356*44704f69SBart Van Assche if (jsp->pr_as_json)
4357*44704f69SBart Van Assche sgj_js_nv_ihexstr(jsp, jo3p, param_c_sn, pc, NULL,
4358*44704f69SBart Van Assche unknown_s);
4359*44704f69SBart Van Assche }
4360*44704f69SBart Van Assche break;
4361*44704f69SBart Van Assche } /* end of switch statement */
4362*44704f69SBart Van Assche if (skip)
4363*44704f69SBart Van Assche skip = false;
4364*44704f69SBart Van Assche else if ((! decoded) && full) {
4365*44704f69SBart Van Assche hex2str(bp, param_len, " ", op->hex2str_oformat, sizeof(b), b);
4366*44704f69SBart Van Assche sgj_pr_hr(jsp, " %s = 0x%x, contents in hex:\n%s", param_c, pc,
4367*44704f69SBart Van Assche b);
4368*44704f69SBart Van Assche }
4369*44704f69SBart Van Assche
4370*44704f69SBart Van Assche if (jsp->pr_as_json)
4371*44704f69SBart Van Assche sgj_js_nv_o(jsp, jap, NULL /* name */, jo3p);
4372*44704f69SBart Van Assche if (op->do_pcb)
4373*44704f69SBart Van Assche sgj_pr_hr(jsp, " <%s>\n", get_pcb_str(bp[2], str,
4374*44704f69SBart Van Assche sizeof(str)));
4375*44704f69SBart Van Assche skip:
4376*44704f69SBart Van Assche if (op->filter_given)
4377*44704f69SBart Van Assche break;
4378*44704f69SBart Van Assche } /* end of for loop */
4379*44704f69SBart Van Assche return true;
4380*44704f69SBart Van Assche }
4381*44704f69SBart Van Assche
4382*44704f69SBart Van Assche /* called for SAS port of PROTO_SPECIFIC_LPAGE [0x18] */
4383*44704f69SBart Van Assche static const char *
show_sas_phy_event_info(int pes,unsigned int val,unsigned int thresh_val,char * b,int blen)4384*44704f69SBart Van Assche show_sas_phy_event_info(int pes, unsigned int val, unsigned int thresh_val,
4385*44704f69SBart Van Assche char * b, int blen)
4386*44704f69SBart Van Assche {
4387*44704f69SBart Van Assche int n = 0;
4388*44704f69SBart Van Assche unsigned int u;
4389*44704f69SBart Van Assche const char * cp = "";
4390*44704f69SBart Van Assche static const char * pvdt = "Peak value detector threshold";
4391*44704f69SBart Van Assche
4392*44704f69SBart Van Assche switch (pes) {
4393*44704f69SBart Van Assche case 0:
4394*44704f69SBart Van Assche cp = "No event";
4395*44704f69SBart Van Assche snprintf(b, blen, "%s", cp);
4396*44704f69SBart Van Assche break;
4397*44704f69SBart Van Assche case 0x1:
4398*44704f69SBart Van Assche cp = "Invalid word count";
4399*44704f69SBart Van Assche snprintf(b, blen, "%s: %u", cp, val);
4400*44704f69SBart Van Assche break;
4401*44704f69SBart Van Assche case 0x2:
4402*44704f69SBart Van Assche cp = "Running disparity error count";
4403*44704f69SBart Van Assche snprintf(b, blen, "%s: %u", cp, val);
4404*44704f69SBart Van Assche break;
4405*44704f69SBart Van Assche case 0x3:
4406*44704f69SBart Van Assche cp = "Loss of dword synchronization count";
4407*44704f69SBart Van Assche snprintf(b, blen, "%s: %u", cp, val);
4408*44704f69SBart Van Assche break;
4409*44704f69SBart Van Assche case 0x4:
4410*44704f69SBart Van Assche cp = "Phy reset problem count";
4411*44704f69SBart Van Assche snprintf(b, blen, "%s: %u", cp, val);
4412*44704f69SBart Van Assche break;
4413*44704f69SBart Van Assche case 0x5:
4414*44704f69SBart Van Assche cp = "Elasticity buffer overflow count";
4415*44704f69SBart Van Assche snprintf(b, blen, "%s: %u", cp, val);
4416*44704f69SBart Van Assche break;
4417*44704f69SBart Van Assche case 0x6:
4418*44704f69SBart Van Assche cp = "Received ERROR count";
4419*44704f69SBart Van Assche snprintf(b, blen, "%s: %u", cp, val);
4420*44704f69SBart Van Assche break;
4421*44704f69SBart Van Assche case 0x7:
4422*44704f69SBart Van Assche cp = "Invalid SPL packet count";
4423*44704f69SBart Van Assche snprintf(b, blen, "%s: %u", cp, val);
4424*44704f69SBart Van Assche break;
4425*44704f69SBart Van Assche case 0x8:
4426*44704f69SBart Van Assche cp = "Loss of SPL packet synchronization count";
4427*44704f69SBart Van Assche snprintf(b, blen, "%s: %u", cp, val);
4428*44704f69SBart Van Assche break;
4429*44704f69SBart Van Assche case 0x20:
4430*44704f69SBart Van Assche cp = "Received address frame error count";
4431*44704f69SBart Van Assche snprintf(b, blen, "%s: %u", cp, val);
4432*44704f69SBart Van Assche break;
4433*44704f69SBart Van Assche case 0x21:
4434*44704f69SBart Van Assche cp = "Transmitted abandon-class OPEN_REJECT count";
4435*44704f69SBart Van Assche snprintf(b, blen, "%s: %u", cp, val);
4436*44704f69SBart Van Assche break;
4437*44704f69SBart Van Assche case 0x22:
4438*44704f69SBart Van Assche cp = "Received abandon-class OPEN_REJECT count";
4439*44704f69SBart Van Assche snprintf(b, blen, "%s: %u", cp, val);
4440*44704f69SBart Van Assche break;
4441*44704f69SBart Van Assche case 0x23:
4442*44704f69SBart Van Assche cp = "Transmitted retry-class OPEN_REJECT count";
4443*44704f69SBart Van Assche snprintf(b, blen, "%s: %u", cp, val);
4444*44704f69SBart Van Assche break;
4445*44704f69SBart Van Assche case 0x24:
4446*44704f69SBart Van Assche cp = "Received retry-class OPEN_REJECT count";
4447*44704f69SBart Van Assche snprintf(b, blen, "%s: %u", cp, val);
4448*44704f69SBart Van Assche break;
4449*44704f69SBart Van Assche case 0x25:
4450*44704f69SBart Van Assche cp = "Received AIP (WAITING ON PARTIAL) count";
4451*44704f69SBart Van Assche snprintf(b, blen, "%s: %u", cp, val);
4452*44704f69SBart Van Assche break;
4453*44704f69SBart Van Assche case 0x26:
4454*44704f69SBart Van Assche cp = "Received AIP (WAITING ON CONNECTION) count";
4455*44704f69SBart Van Assche snprintf(b, blen, "%s: %u", cp, val);
4456*44704f69SBart Van Assche break;
4457*44704f69SBart Van Assche case 0x27:
4458*44704f69SBart Van Assche cp = "Transmitted BREAK count";
4459*44704f69SBart Van Assche snprintf(b, blen, "%s: %u", cp, val);
4460*44704f69SBart Van Assche break;
4461*44704f69SBart Van Assche case 0x28:
4462*44704f69SBart Van Assche cp = "Received BREAK count";
4463*44704f69SBart Van Assche snprintf(b, blen, "%s: %u", cp, val);
4464*44704f69SBart Van Assche break;
4465*44704f69SBart Van Assche case 0x29:
4466*44704f69SBart Van Assche cp = "Break timeout count";
4467*44704f69SBart Van Assche snprintf(b, blen, "%s: %u", cp, val);
4468*44704f69SBart Van Assche break;
4469*44704f69SBart Van Assche case 0x2a:
4470*44704f69SBart Van Assche cp = "Connection count";
4471*44704f69SBart Van Assche snprintf(b, blen, "%s: %u", cp, val);
4472*44704f69SBart Van Assche break;
4473*44704f69SBart Van Assche case 0x2b:
4474*44704f69SBart Van Assche cp = "Peak transmitted pathway blocked count";
4475*44704f69SBart Van Assche n = sg_scnpr(b, blen, "%s: %u", cp, val & 0xff);
4476*44704f69SBart Van Assche sg_scnpr(b + n, blen - n, "\t%s: %u", pvdt, thresh_val & 0xff);
4477*44704f69SBart Van Assche break;
4478*44704f69SBart Van Assche case 0x2c:
4479*44704f69SBart Van Assche cp = "Peak transmitted arbitration wait time";
4480*44704f69SBart Van Assche u = val & 0xffff;
4481*44704f69SBart Van Assche if (u < 0x8000)
4482*44704f69SBart Van Assche n = sg_scnpr(b, blen, "%s (us): %u", cp, u);
4483*44704f69SBart Van Assche else
4484*44704f69SBart Van Assche n = sg_scnpr(b, blen, "%s (ms): %u", cp, 33 + (u - 0x8000));
4485*44704f69SBart Van Assche u = thresh_val & 0xffff;
4486*44704f69SBart Van Assche if (u < 0x8000)
4487*44704f69SBart Van Assche sg_scnpr(b + n, blen - n, "\t%s (us): %u", pvdt, u);
4488*44704f69SBart Van Assche else
4489*44704f69SBart Van Assche sg_scnpr(b + n, blen - n, "\t%s (ms): %u", pvdt,
4490*44704f69SBart Van Assche 33 + (u - 0x8000));
4491*44704f69SBart Van Assche break;
4492*44704f69SBart Van Assche case 0x2d:
4493*44704f69SBart Van Assche cp = "Peak arbitration time";
4494*44704f69SBart Van Assche n = sg_scnpr(b, blen, "%s (us): %u", cp, val);
4495*44704f69SBart Van Assche sg_scnpr(b + n, blen - n, "\t%s: %u", pvdt, thresh_val);
4496*44704f69SBart Van Assche break;
4497*44704f69SBart Van Assche case 0x2e:
4498*44704f69SBart Van Assche cp = "Peak connection time";
4499*44704f69SBart Van Assche n = sg_scnpr(b, blen, "%s (us): %u", cp, val);
4500*44704f69SBart Van Assche sg_scnpr(b + n, blen - n, "\t%s: %u", pvdt, thresh_val);
4501*44704f69SBart Van Assche break;
4502*44704f69SBart Van Assche case 0x2f:
4503*44704f69SBart Van Assche cp = "Persistent connection count";
4504*44704f69SBart Van Assche snprintf(b, blen, "%s: %u", cp, val);
4505*44704f69SBart Van Assche break;
4506*44704f69SBart Van Assche case 0x40:
4507*44704f69SBart Van Assche cp = "Transmitted SSP frame count";
4508*44704f69SBart Van Assche snprintf(b, blen, "%s: %u", cp, val);
4509*44704f69SBart Van Assche break;
4510*44704f69SBart Van Assche case 0x41:
4511*44704f69SBart Van Assche cp = "Received SSP frame count";
4512*44704f69SBart Van Assche snprintf(b, blen, "%s: %u", cp, val);
4513*44704f69SBart Van Assche break;
4514*44704f69SBart Van Assche case 0x42:
4515*44704f69SBart Van Assche cp = "Transmitted SSP frame error count";
4516*44704f69SBart Van Assche snprintf(b, blen, "%s: %u", cp, val);
4517*44704f69SBart Van Assche break;
4518*44704f69SBart Van Assche case 0x43:
4519*44704f69SBart Van Assche cp = "Received SSP frame error count";
4520*44704f69SBart Van Assche snprintf(b, blen, "%s: %u", cp, val);
4521*44704f69SBart Van Assche break;
4522*44704f69SBart Van Assche case 0x44:
4523*44704f69SBart Van Assche cp = "Transmitted CREDIT_BLOCKED count";
4524*44704f69SBart Van Assche snprintf(b, blen, "%s: %u", cp, val);
4525*44704f69SBart Van Assche break;
4526*44704f69SBart Van Assche case 0x45:
4527*44704f69SBart Van Assche cp = "Received CREDIT_BLOCKED count";
4528*44704f69SBart Van Assche snprintf(b, blen, "%s: %u", cp, val);
4529*44704f69SBart Van Assche break;
4530*44704f69SBart Van Assche case 0x50:
4531*44704f69SBart Van Assche cp = "Transmitted SATA frame count";
4532*44704f69SBart Van Assche snprintf(b, blen, "%s: %u", cp, val);
4533*44704f69SBart Van Assche break;
4534*44704f69SBart Van Assche case 0x51:
4535*44704f69SBart Van Assche cp = "Received SATA frame count";
4536*44704f69SBart Van Assche snprintf(b, blen, "%s: %u", cp, val);
4537*44704f69SBart Van Assche break;
4538*44704f69SBart Van Assche case 0x52:
4539*44704f69SBart Van Assche cp = "SATA flow control buffer overflow count";
4540*44704f69SBart Van Assche snprintf(b, blen, "%s: %u", cp, val);
4541*44704f69SBart Van Assche break;
4542*44704f69SBart Van Assche case 0x60:
4543*44704f69SBart Van Assche cp = "Transmitted SMP frame count";
4544*44704f69SBart Van Assche snprintf(b, blen, "%s: %u", cp, val);
4545*44704f69SBart Van Assche break;
4546*44704f69SBart Van Assche case 0x61:
4547*44704f69SBart Van Assche cp = "Received SMP frame count";
4548*44704f69SBart Van Assche snprintf(b, blen, "%s: %u", cp, val);
4549*44704f69SBart Van Assche break;
4550*44704f69SBart Van Assche case 0x63:
4551*44704f69SBart Van Assche cp = "Received SMP frame error count";
4552*44704f69SBart Van Assche snprintf(b, blen, "%s: %u", cp, val);
4553*44704f69SBart Van Assche break;
4554*44704f69SBart Van Assche default:
4555*44704f69SBart Van Assche cp = "";
4556*44704f69SBart Van Assche snprintf(b, blen, "Unknown phy event source: %d, val=%u, "
4557*44704f69SBart Van Assche "thresh_val=%u", pes, val, thresh_val);
4558*44704f69SBart Van Assche break;
4559*44704f69SBart Van Assche }
4560*44704f69SBart Van Assche return cp;
4561*44704f69SBart Van Assche }
4562*44704f69SBart Van Assche
4563*44704f69SBart Van Assche static const char * sas_link_rate_arr[16] = {
4564*44704f69SBart Van Assche "phy enabled; unknown rate",
4565*44704f69SBart Van Assche "phy disabled",
4566*44704f69SBart Van Assche "phy enabled; speed negotiation failed",
4567*44704f69SBart Van Assche "phy enabled; SATA spinup hold state",
4568*44704f69SBart Van Assche "phy enabled; port selector",
4569*44704f69SBart Van Assche "phy enabled; reset in progress",
4570*44704f69SBart Van Assche "phy enabled; unsupported phy attached",
4571*44704f69SBart Van Assche "reserved [0x7]",
4572*44704f69SBart Van Assche "1.5 Gbps", /* 0x8 */
4573*44704f69SBart Van Assche "3 Gbps",
4574*44704f69SBart Van Assche "6 Gbps",
4575*44704f69SBart Van Assche "12 Gbps",
4576*44704f69SBart Van Assche "22.5 Gbps",
4577*44704f69SBart Van Assche "reserved [0xd]",
4578*44704f69SBart Van Assche "reserved [0xe]",
4579*44704f69SBart Van Assche "reserved [0xf]",
4580*44704f69SBart Van Assche };
4581*44704f69SBart Van Assche
4582*44704f69SBart Van Assche static char *
sas_negot_link_rate(int lrate,char * b,int blen)4583*44704f69SBart Van Assche sas_negot_link_rate(int lrate, char * b, int blen)
4584*44704f69SBart Van Assche {
4585*44704f69SBart Van Assche int mask = 0xf;
4586*44704f69SBart Van Assche
4587*44704f69SBart Van Assche if (~mask & lrate)
4588*44704f69SBart Van Assche snprintf(b, blen, "bad link_rate value=0x%x\n", lrate);
4589*44704f69SBart Van Assche else
4590*44704f69SBart Van Assche snprintf(b, blen, "%s", sas_link_rate_arr[lrate]);
4591*44704f69SBart Van Assche return b;
4592*44704f69SBart Van Assche }
4593*44704f69SBart Van Assche
4594*44704f69SBart Van Assche /* helper for SAS port of PROTO_SPECIFIC_LPAGE [0x18] */
4595*44704f69SBart Van Assche static void
show_sas_port_param(const uint8_t * bp,int param_len,struct opts_t * op,sgj_opaque_p jop)4596*44704f69SBart Van Assche show_sas_port_param(const uint8_t * bp, int param_len, struct opts_t * op,
4597*44704f69SBart Van Assche sgj_opaque_p jop)
4598*44704f69SBart Van Assche {
4599*44704f69SBart Van Assche int j, m, nphys, t, spld_len, pi;
4600*44704f69SBart Van Assche uint64_t ull;
4601*44704f69SBart Van Assche unsigned int ui, ui2, ui3, ui4;
4602*44704f69SBart Van Assche char * cp;
4603*44704f69SBart Van Assche const char * ccp;
4604*44704f69SBart Van Assche const char * cc2p;
4605*44704f69SBart Van Assche const char * cc3p;
4606*44704f69SBart Van Assche const char * cc4p;
4607*44704f69SBart Van Assche const uint8_t * vcp;
4608*44704f69SBart Van Assche sgj_state * jsp = &op->json_st;
4609*44704f69SBart Van Assche sgj_opaque_p jo2p = NULL;
4610*44704f69SBart Van Assche sgj_opaque_p jo3p = NULL;
4611*44704f69SBart Van Assche sgj_opaque_p jap = NULL;
4612*44704f69SBart Van Assche sgj_opaque_p ja2p = NULL;
4613*44704f69SBart Van Assche char b[160];
4614*44704f69SBart Van Assche char s[80];
4615*44704f69SBart Van Assche static char * rtpi = "Relative target port identifier";
4616*44704f69SBart Van Assche static char * psplpfstp =
4617*44704f69SBart Van Assche "Protocol Specific Port log parameter for SAS target port";
4618*44704f69SBart Van Assche static char * at = "attached";
4619*44704f69SBart Van Assche static char * ip = "initiator_port";
4620*44704f69SBart Van Assche static char * tp = "target_port";
4621*44704f69SBart Van Assche static char * pvdt = "peak_value_detector_threshold";
4622*44704f69SBart Van Assche static const int sz = sizeof(s);
4623*44704f69SBart Van Assche static const int blen = sizeof(b);
4624*44704f69SBart Van Assche
4625*44704f69SBart Van Assche t = sg_get_unaligned_be16(bp + 0);
4626*44704f69SBart Van Assche if (op->do_name)
4627*44704f69SBart Van Assche sgj_pr_hr(jsp, " rel_target_port=%d\n", t);
4628*44704f69SBart Van Assche else
4629*44704f69SBart Van Assche sgj_pr_hr(jsp, " %s = %d\n", rtpi, t);
4630*44704f69SBart Van Assche if (op->do_name)
4631*44704f69SBart Van Assche sgj_pr_hr(jsp, " gen_code=%d\n", bp[6]);
4632*44704f69SBart Van Assche else
4633*44704f69SBart Van Assche sgj_pr_hr(jsp, " generation code = %d\n", bp[6]);
4634*44704f69SBart Van Assche nphys = bp[7];
4635*44704f69SBart Van Assche if (op->do_name)
4636*44704f69SBart Van Assche sgj_pr_hr(jsp, " num_phys=%d\n", nphys);
4637*44704f69SBart Van Assche else
4638*44704f69SBart Van Assche sgj_pr_hr(jsp, " number of phys = %d\n", nphys);
4639*44704f69SBart Van Assche if (jsp->pr_as_json) {
4640*44704f69SBart Van Assche js_snakenv_ihexstr_nex(jsp, jop, param_c , t, true,
4641*44704f69SBart Van Assche NULL, psplpfstp, rtpi);
4642*44704f69SBart Van Assche pi = 0xf & bp[4];
4643*44704f69SBart Van Assche sgj_js_nv_ihexstr(jsp, jop, "protocol_identifier", pi, NULL,
4644*44704f69SBart Van Assche sg_get_trans_proto_str(pi, blen, b));
4645*44704f69SBart Van Assche sgj_js_nv_ihex(jsp, jop, "generation_code", bp[6]);
4646*44704f69SBart Van Assche sgj_js_nv_ihex(jsp, jop, "number_of_phys", bp[7]);
4647*44704f69SBart Van Assche jap = sgj_named_subarray_r(jsp, jop, "sas_phy_log_descriptor_list");
4648*44704f69SBart Van Assche }
4649*44704f69SBart Van Assche
4650*44704f69SBart Van Assche for (j = 0, vcp = bp + 8; j < (param_len - 8);
4651*44704f69SBart Van Assche vcp += spld_len, j += spld_len) {
4652*44704f69SBart Van Assche if (jsp->pr_as_json) {
4653*44704f69SBart Van Assche jo2p = sgj_new_unattached_object_r(jsp);
4654*44704f69SBart Van Assche if (op->do_pcb)
4655*44704f69SBart Van Assche js_pcb(jsp, jo2p, vcp[2]);
4656*44704f69SBart Van Assche }
4657*44704f69SBart Van Assche if (op->do_name)
4658*44704f69SBart Van Assche sgj_pr_hr(jsp, " phy_id=%d\n", vcp[1]);
4659*44704f69SBart Van Assche else
4660*44704f69SBart Van Assche sgj_haj_vi(jsp, jo2p, 2, "phy identifier", SGJ_SEP_EQUAL_1_SPACE,
4661*44704f69SBart Van Assche vcp[1], true);
4662*44704f69SBart Van Assche spld_len = vcp[3];
4663*44704f69SBart Van Assche if (spld_len < 44)
4664*44704f69SBart Van Assche spld_len = 48; /* in SAS-1 and SAS-1.1 vcp[3]==0 */
4665*44704f69SBart Van Assche else
4666*44704f69SBart Van Assche spld_len += 4;
4667*44704f69SBart Van Assche if (op->do_name) {
4668*44704f69SBart Van Assche t = ((0x70 & vcp[4]) >> 4);
4669*44704f69SBart Van Assche sgj_pr_hr(jsp, " att_dev_type=%d\n", t);
4670*44704f69SBart Van Assche sgj_pr_hr(jsp, " att_iport_mask=0x%x\n", vcp[6]);
4671*44704f69SBart Van Assche sgj_pr_hr(jsp, " att_phy_id=%d\n", vcp[24]);
4672*44704f69SBart Van Assche sgj_pr_hr(jsp, " att_reason=0x%x\n", (vcp[4] & 0xf));
4673*44704f69SBart Van Assche ull = sg_get_unaligned_be64(vcp + 16);
4674*44704f69SBart Van Assche sgj_pr_hr(jsp, " att_sas_addr=0x%" PRIx64 "\n", ull);
4675*44704f69SBart Van Assche sgj_pr_hr(jsp, " att_tport_mask=0x%x\n", vcp[7]);
4676*44704f69SBart Van Assche ui = sg_get_unaligned_be32(vcp + 32);
4677*44704f69SBart Van Assche sgj_pr_hr(jsp, " inv_dwords=%u\n", ui);
4678*44704f69SBart Van Assche ui = sg_get_unaligned_be32(vcp + 40);
4679*44704f69SBart Van Assche sgj_pr_hr(jsp, " loss_dword_sync=%u\n", ui);
4680*44704f69SBart Van Assche sgj_pr_hr(jsp, " neg_log_lrate=%d\n", 0xf & vcp[5]);
4681*44704f69SBart Van Assche ui = sg_get_unaligned_be32(vcp + 44);
4682*44704f69SBart Van Assche sgj_pr_hr(jsp, " phy_reset_probs=%u\n", ui);
4683*44704f69SBart Van Assche ui = sg_get_unaligned_be32(vcp + 36);
4684*44704f69SBart Van Assche sgj_pr_hr(jsp, " running_disparity=%u\n", ui);
4685*44704f69SBart Van Assche sgj_pr_hr(jsp, " reason=0x%x\n", (vcp[5] & 0xf0) >> 4);
4686*44704f69SBart Van Assche ull = sg_get_unaligned_be64(vcp + 8);
4687*44704f69SBart Van Assche sgj_pr_hr(jsp, " sas_addr=0x%" PRIx64 "\n", ull);
4688*44704f69SBart Van Assche } else {
4689*44704f69SBart Van Assche t = ((0x70 & vcp[4]) >> 4);
4690*44704f69SBart Van Assche /* attached SAS device type. In SAS-1.1 case 2 was an edge
4691*44704f69SBart Van Assche * expander; in SAS-2 case 3 is marked as obsolete. */
4692*44704f69SBart Van Assche switch (t) {
4693*44704f69SBart Van Assche case 0: snprintf(s, sz, "no device %s", at); break;
4694*44704f69SBart Van Assche case 1: snprintf(s, sz, "SAS or SATA device"); break;
4695*44704f69SBart Van Assche case 2: snprintf(s, sz, "expander device"); break;
4696*44704f69SBart Van Assche case 3: snprintf(s, sz, "expander device (fanout)"); break;
4697*44704f69SBart Van Assche default: snprintf(s, sz, "%s [%d]", rsv_s, t); break;
4698*44704f69SBart Van Assche }
4699*44704f69SBart Van Assche /* the word 'SAS' in following added in spl4r01 */
4700*44704f69SBart Van Assche sgj_pr_hr(jsp, " %s SAS device type: %s\n", at, s);
4701*44704f69SBart Van Assche if (jsp->pr_as_json)
4702*44704f69SBart Van Assche sgj_js_nv_ihexstr(jsp, jo2p, "attached_sas_device_type", t,
4703*44704f69SBart Van Assche NULL, s);
4704*44704f69SBart Van Assche t = 0xf & vcp[4];
4705*44704f69SBart Van Assche switch (t) {
4706*44704f69SBart Van Assche case 0: snprintf(s, sz, "%s", unknown_s); break;
4707*44704f69SBart Van Assche case 1: snprintf(s, sz, "power on"); break;
4708*44704f69SBart Van Assche case 2: snprintf(s, sz, "hard reset"); break;
4709*44704f69SBart Van Assche case 3: snprintf(s, sz, "SMP phy control function"); break;
4710*44704f69SBart Van Assche case 4: snprintf(s, sz, "loss of dword synchronization"); break;
4711*44704f69SBart Van Assche case 5: snprintf(s, sz, "mux mix up"); break;
4712*44704f69SBart Van Assche case 6: snprintf(s, sz, "I_T nexus loss timeout for STP/SATA");
4713*44704f69SBart Van Assche break;
4714*44704f69SBart Van Assche case 7: snprintf(s, sz, "break timeout timer expired"); break;
4715*44704f69SBart Van Assche case 8: snprintf(s, sz, "phy test function stopped"); break;
4716*44704f69SBart Van Assche case 9: snprintf(s, sz, "expander device reduced functionality");
4717*44704f69SBart Van Assche break;
4718*44704f69SBart Van Assche default: snprintf(s, sz, "%s [0x%x]", rsv_s, t); break;
4719*44704f69SBart Van Assche }
4720*44704f69SBart Van Assche sgj_pr_hr(jsp, " %s reason: %s\n", at, s);
4721*44704f69SBart Van Assche if (jsp->pr_as_json)
4722*44704f69SBart Van Assche sgj_js_nv_ihexstr(jsp, jo2p, "attached_reason", t, NULL, s);
4723*44704f69SBart Van Assche t = (vcp[5] & 0xf0) >> 4;
4724*44704f69SBart Van Assche switch (t) {
4725*44704f69SBart Van Assche case 0: snprintf(s, sz, "%s", unknown_s); break;
4726*44704f69SBart Van Assche case 1: snprintf(s, sz, "power on"); break;
4727*44704f69SBart Van Assche case 2: snprintf(s, sz, "hard reset"); break;
4728*44704f69SBart Van Assche case 3: snprintf(s, sz, "SMP phy control function"); break;
4729*44704f69SBart Van Assche case 4: snprintf(s, sz, "loss of dword synchronization"); break;
4730*44704f69SBart Van Assche case 5: snprintf(s, sz, "mux mix up"); break;
4731*44704f69SBart Van Assche case 6: snprintf(s, sz, "I_T nexus loss timeout for STP/SATA");
4732*44704f69SBart Van Assche break;
4733*44704f69SBart Van Assche case 7: snprintf(s, sz, "break timeout timer expired"); break;
4734*44704f69SBart Van Assche case 8: snprintf(s, sz, "phy test function stopped"); break;
4735*44704f69SBart Van Assche case 9: snprintf(s, sz, "expander device reduced functionality");
4736*44704f69SBart Van Assche break;
4737*44704f69SBart Van Assche default: snprintf(s, sz, "%s [0x%x]", rsv_s, t); break;
4738*44704f69SBart Van Assche }
4739*44704f69SBart Van Assche sgj_pr_hr(jsp, " reason: %s\n", s);
4740*44704f69SBart Van Assche if (jsp->pr_as_json)
4741*44704f69SBart Van Assche sgj_js_nv_ihexstr(jsp, jo2p, "reason", t, NULL, s);
4742*44704f69SBart Van Assche t = (0xf & vcp[5]);
4743*44704f69SBart Van Assche ccp = "negotiated logical link rate";
4744*44704f69SBart Van Assche cc2p = sas_negot_link_rate(t, s, sz);
4745*44704f69SBart Van Assche sgj_pr_hr(jsp, " %s: %s\n", ccp, cc2p);
4746*44704f69SBart Van Assche if (jsp->pr_as_json) {
4747*44704f69SBart Van Assche sgj_convert_to_snake_name(ccp, b, blen);
4748*44704f69SBart Van Assche sgj_js_nv_ihexstr(jsp, jo2p, b, t, NULL, cc2p);
4749*44704f69SBart Van Assche }
4750*44704f69SBart Van Assche
4751*44704f69SBart Van Assche sgj_pr_hr(jsp, " %s initiator port: ssp=%d stp=%d smp=%d\n",
4752*44704f69SBart Van Assche at, !! (vcp[6] & 8), !! (vcp[6] & 4), !! (vcp[6] & 2));
4753*44704f69SBart Van Assche if (jsp->pr_as_json) {
4754*44704f69SBart Van Assche snprintf(b, blen, "%s_ssp_%s", at, ip);
4755*44704f69SBart Van Assche sgj_js_nv_i(jsp, jo2p, b, !! (vcp[6] & 8));
4756*44704f69SBart Van Assche snprintf(b, blen, "%s_stp_%s", at, ip);
4757*44704f69SBart Van Assche sgj_js_nv_i(jsp, jo2p, b, !! (vcp[6] & 4));
4758*44704f69SBart Van Assche snprintf(b, blen, "%s_smp_%s", at, ip);
4759*44704f69SBart Van Assche sgj_js_nv_i(jsp, jo2p, b, !! (vcp[6] & 2));
4760*44704f69SBart Van Assche }
4761*44704f69SBart Van Assche sgj_pr_hr(jsp, " %s target port: ssp=%d stp=%d smp=%d\n", at,
4762*44704f69SBart Van Assche !! (vcp[7] & 8), !! (vcp[7] & 4), !! (vcp[7] & 2));
4763*44704f69SBart Van Assche if (jsp->pr_as_json) {
4764*44704f69SBart Van Assche snprintf(b, blen, "%s_ssp_%s", at, tp);
4765*44704f69SBart Van Assche sgj_js_nv_i(jsp, jo2p, b, !! (vcp[7] & 8));
4766*44704f69SBart Van Assche snprintf(b, blen, "%s_stp_%s", at, tp);
4767*44704f69SBart Van Assche sgj_js_nv_i(jsp, jo2p, b, !! (vcp[7] & 4));
4768*44704f69SBart Van Assche snprintf(b, blen, "%s_smp_%s", at, tp);
4769*44704f69SBart Van Assche sgj_js_nv_i(jsp, jo2p, b, !! (vcp[7] & 2));
4770*44704f69SBart Van Assche }
4771*44704f69SBart Van Assche ull = sg_get_unaligned_be64(vcp + 8);
4772*44704f69SBart Van Assche sgj_pr_hr(jsp, " SAS address = 0x%" PRIx64 "\n", ull);
4773*44704f69SBart Van Assche if (jsp->pr_as_json)
4774*44704f69SBart Van Assche sgj_js_nv_ihex(jsp, jo2p, "sas_address", ull);
4775*44704f69SBart Van Assche ull = sg_get_unaligned_be64(vcp + 16);
4776*44704f69SBart Van Assche sgj_pr_hr(jsp, " %s SAS address = 0x%" PRIx64 "\n", at, ull);
4777*44704f69SBart Van Assche if (jsp->pr_as_json)
4778*44704f69SBart Van Assche sgj_js_nv_ihex(jsp, jo2p, "attached_sas_address", ull);
4779*44704f69SBart Van Assche ccp = "attached phy identifier";
4780*44704f69SBart Van Assche sgj_haj_vi(jsp, jo2p, 4, ccp, SGJ_SEP_EQUAL_1_SPACE, vcp[24],
4781*44704f69SBart Van Assche true);
4782*44704f69SBart Van Assche ccp = "Invalid DWORD count";
4783*44704f69SBart Van Assche ui = sg_get_unaligned_be32(vcp + 32);
4784*44704f69SBart Van Assche cc2p = "Running disparity error count";
4785*44704f69SBart Van Assche ui2 = sg_get_unaligned_be32(vcp + 36);
4786*44704f69SBart Van Assche cc3p = "Loss of DWORD synchronization count";
4787*44704f69SBart Van Assche ui3 = sg_get_unaligned_be32(vcp + 40);
4788*44704f69SBart Van Assche cc4p = "Phy reset problem count";
4789*44704f69SBart Van Assche ui4 = sg_get_unaligned_be32(vcp + 44);
4790*44704f69SBart Van Assche if (jsp->pr_as_json) {
4791*44704f69SBart Van Assche sgj_convert_to_snake_name(ccp, b, blen);
4792*44704f69SBart Van Assche sgj_js_nv_ihex(jsp, jo2p, b, ui);
4793*44704f69SBart Van Assche sgj_convert_to_snake_name(cc2p, b, blen);
4794*44704f69SBart Van Assche sgj_js_nv_ihex(jsp, jo2p, b, ui2);
4795*44704f69SBart Van Assche sgj_convert_to_snake_name(cc3p, b, blen);
4796*44704f69SBart Van Assche sgj_js_nv_ihex(jsp, jo2p, b, ui3);
4797*44704f69SBart Van Assche sgj_convert_to_snake_name(cc4p, b, blen);
4798*44704f69SBart Van Assche sgj_js_nv_ihex(jsp, jo2p, b, ui4);
4799*44704f69SBart Van Assche } else {
4800*44704f69SBart Van Assche if (0 == op->do_brief) {
4801*44704f69SBart Van Assche sgj_pr_hr(jsp, " %s = %u\n", ccp, ui);
4802*44704f69SBart Van Assche sgj_pr_hr(jsp, " %s = %u\n", cc2p, ui2);
4803*44704f69SBart Van Assche sgj_pr_hr(jsp, " %s = %u\n", cc3p, ui3);
4804*44704f69SBart Van Assche sgj_pr_hr(jsp, " %s = %u\n", cc4p, ui4);
4805*44704f69SBart Van Assche }
4806*44704f69SBart Van Assche }
4807*44704f69SBart Van Assche }
4808*44704f69SBart Van Assche if (op->do_brief > 0)
4809*44704f69SBart Van Assche goto skip;
4810*44704f69SBart Van Assche if (spld_len > 51) {
4811*44704f69SBart Van Assche int num_ped;
4812*44704f69SBart Van Assche const uint8_t * xcp;
4813*44704f69SBart Van Assche
4814*44704f69SBart Van Assche num_ped = vcp[51];
4815*44704f69SBart Van Assche if (op->verbose > 1)
4816*44704f69SBart Van Assche sgj_pr_hr(jsp, " <<Phy event descriptors: %d, spld_len: "
4817*44704f69SBart Van Assche "%d, calc_ped: %d>>\n", num_ped, spld_len,
4818*44704f69SBart Van Assche (spld_len - 52) / 12);
4819*44704f69SBart Van Assche if (num_ped > 0) {
4820*44704f69SBart Van Assche if (op->do_name) {
4821*44704f69SBart Van Assche sgj_pr_hr(jsp, " phy_event_desc_num=%d\n", num_ped);
4822*44704f69SBart Van Assche return; /* don't decode at this stage */
4823*44704f69SBart Van Assche } else
4824*44704f69SBart Van Assche sgj_pr_hr(jsp, " Phy event descriptors:\n");
4825*44704f69SBart Van Assche }
4826*44704f69SBart Van Assche if (jsp->pr_as_json) {
4827*44704f69SBart Van Assche sgj_js_nv_i(jsp, jo2p, "number_of_phy_event_descriptors",
4828*44704f69SBart Van Assche num_ped);
4829*44704f69SBart Van Assche if (num_ped > 0)
4830*44704f69SBart Van Assche ja2p = sgj_named_subarray_r(jsp, jo2p,
4831*44704f69SBart Van Assche "phy_event_descriptor_list");
4832*44704f69SBart Van Assche }
4833*44704f69SBart Van Assche xcp = vcp + 52;
4834*44704f69SBart Van Assche for (m = 0; m < (num_ped * 12); m += 12, xcp += 12) {
4835*44704f69SBart Van Assche int pes = xcp[3];
4836*44704f69SBart Van Assche unsigned int pvdt_v;
4837*44704f69SBart Van Assche
4838*44704f69SBart Van Assche if (jsp->pr_as_json)
4839*44704f69SBart Van Assche jo3p = sgj_new_unattached_object_r(jsp);
4840*44704f69SBart Van Assche ui = sg_get_unaligned_be32(xcp + 4);
4841*44704f69SBart Van Assche pvdt_v = sg_get_unaligned_be32(xcp + 8);
4842*44704f69SBart Van Assche ccp = show_sas_phy_event_info(pes, ui, pvdt_v, b, blen);
4843*44704f69SBart Van Assche if (0 == strlen(ccp)) {
4844*44704f69SBart Van Assche sgj_pr_hr(jsp, " %s\n", b); /* unknown pvdt_v */
4845*44704f69SBart Van Assche if (jsp->pr_as_json) {
4846*44704f69SBart Van Assche int n;
4847*44704f69SBart Van Assche
4848*44704f69SBart Van Assche snprintf(s, sz, "%s_pes_0x%x", unknown_s, pes);
4849*44704f69SBart Van Assche sgj_js_nv_ihex(jsp, jo3p, s, ui);
4850*44704f69SBart Van Assche n = strlen(s);
4851*44704f69SBart Van Assche sg_scnpr(s + n, sz - n, "_%s", "threshold");
4852*44704f69SBart Van Assche sgj_js_nv_ihex(jsp, jo3p, s, pvdt_v);
4853*44704f69SBart Van Assche }
4854*44704f69SBart Van Assche } else {
4855*44704f69SBart Van Assche if (jsp->pr_as_json) {
4856*44704f69SBart Van Assche sgj_convert_to_snake_name(ccp, s, sz);
4857*44704f69SBart Van Assche sgj_js_nv_ihex(jsp, jo3p, s, ui);
4858*44704f69SBart Van Assche if (0x2b == pes)
4859*44704f69SBart Van Assche sgj_js_nv_ihex(jsp, jo3p, pvdt, pvdt_v);
4860*44704f69SBart Van Assche else if (0x2c == pes)
4861*44704f69SBart Van Assche sgj_js_nv_ihex(jsp, jo3p, pvdt, pvdt_v);
4862*44704f69SBart Van Assche else if (0x2d == pes)
4863*44704f69SBart Van Assche sgj_js_nv_ihex(jsp, jo3p, pvdt, pvdt_v);
4864*44704f69SBart Van Assche else if (0x2e == pes)
4865*44704f69SBart Van Assche sgj_js_nv_ihex(jsp, jo3p, pvdt, pvdt_v);
4866*44704f69SBart Van Assche } else {
4867*44704f69SBart Van Assche cp = strchr(b, '\t');
4868*44704f69SBart Van Assche if (cp) {
4869*44704f69SBart Van Assche *cp = '\0';
4870*44704f69SBart Van Assche sgj_pr_hr(jsp, " %s\n", b);
4871*44704f69SBart Van Assche sgj_pr_hr(jsp, " %s\n", cp + 1);
4872*44704f69SBart Van Assche } else
4873*44704f69SBart Van Assche sgj_pr_hr(jsp, " %s\n", b);
4874*44704f69SBart Van Assche }
4875*44704f69SBart Van Assche }
4876*44704f69SBart Van Assche if (jsp->pr_as_json)
4877*44704f69SBart Van Assche sgj_js_nv_o(jsp, ja2p, NULL /* name */, jo3p);
4878*44704f69SBart Van Assche }
4879*44704f69SBart Van Assche } else if (op->verbose)
4880*44704f69SBart Van Assche printf(" <<No phy event descriptors>>\n");
4881*44704f69SBart Van Assche skip:
4882*44704f69SBart Van Assche if (jsp->pr_as_json)
4883*44704f69SBart Van Assche sgj_js_nv_o(jsp, jap, NULL /* name */, jo2p);
4884*44704f69SBart Van Assche } /* end of for loop over phys with this relative port */
4885*44704f69SBart Van Assche }
4886*44704f69SBart Van Assche
4887*44704f69SBart Van Assche /* PROTO_SPECIFIC_LPAGE [0x18] <psp> */
4888*44704f69SBart Van Assche static bool
show_protocol_specific_port_page(const uint8_t * resp,int len,struct opts_t * op,sgj_opaque_p jop)4889*44704f69SBart Van Assche show_protocol_specific_port_page(const uint8_t * resp, int len,
4890*44704f69SBart Van Assche struct opts_t * op, sgj_opaque_p jop)
4891*44704f69SBart Van Assche {
4892*44704f69SBart Van Assche int k, num, pl, pid;
4893*44704f69SBart Van Assche const uint8_t * bp;
4894*44704f69SBart Van Assche sgj_state * jsp = &op->json_st;
4895*44704f69SBart Van Assche sgj_opaque_p jo2p;
4896*44704f69SBart Van Assche sgj_opaque_p jo3p = NULL;
4897*44704f69SBart Van Assche sgj_opaque_p jap = NULL;
4898*44704f69SBart Van Assche char b[128];
4899*44704f69SBart Van Assche static const char * psplp = "Protocol specific port log page";
4900*44704f69SBart Van Assche static const char * fss = "for SAS SSP";
4901*44704f69SBart Van Assche
4902*44704f69SBart Van Assche num = len - 4;
4903*44704f69SBart Van Assche if (op->verbose || ((! op->do_raw) && (0 == op->do_hex))) {
4904*44704f69SBart Van Assche if (op->do_name)
4905*44704f69SBart Van Assche sgj_pr_hr(jsp, "log_page=0x%x\n", PROTO_SPECIFIC_LPAGE);
4906*44704f69SBart Van Assche else
4907*44704f69SBart Van Assche sgj_pr_hr(jsp, "%s [0x18]\n", psplp);
4908*44704f69SBart Van Assche }
4909*44704f69SBart Van Assche if (jsp->pr_as_json) {
4910*44704f69SBart Van Assche jo2p = sg_log_js_hdr(jsp, jop, psplp, resp);
4911*44704f69SBart Van Assche jap = sgj_named_subarray_r(jsp, jo2p,
4912*44704f69SBart Van Assche "protocol_specific_port_log_parameter_list");
4913*44704f69SBart Van Assche }
4914*44704f69SBart Van Assche
4915*44704f69SBart Van Assche for (k = 0, bp = resp + 4; k < num; ) {
4916*44704f69SBart Van Assche int pc = sg_get_unaligned_be16(bp + 0);
4917*44704f69SBart Van Assche
4918*44704f69SBart Van Assche pl = bp[3] + 4;
4919*44704f69SBart Van Assche if (op->filter_given) {
4920*44704f69SBart Van Assche if (pc != op->filter)
4921*44704f69SBart Van Assche goto skip;
4922*44704f69SBart Van Assche }
4923*44704f69SBart Van Assche if (op->do_raw) {
4924*44704f69SBart Van Assche dStrRaw(bp, pl);
4925*44704f69SBart Van Assche goto skip;
4926*44704f69SBart Van Assche } else if (op->do_hex) {
4927*44704f69SBart Van Assche hex2stdout(bp, pl, op->dstrhex_no_ascii);
4928*44704f69SBart Van Assche goto skip;
4929*44704f69SBart Van Assche }
4930*44704f69SBart Van Assche pid = 0xf & bp[4];
4931*44704f69SBart Van Assche if (6 != pid) {
4932*44704f69SBart Van Assche pr2serr("Protocol identifier: %d, only support SAS (SPL) which "
4933*44704f69SBart Van Assche "is 6\n", pid);
4934*44704f69SBart Van Assche return false; /* only decode SAS log page */
4935*44704f69SBart Van Assche }
4936*44704f69SBart Van Assche if (jsp->pr_as_json) {
4937*44704f69SBart Van Assche jo3p = sgj_new_unattached_object_r(jsp);
4938*44704f69SBart Van Assche if (op->do_pcb)
4939*44704f69SBart Van Assche js_pcb(jsp, jo3p, bp[2]);
4940*44704f69SBart Van Assche }
4941*44704f69SBart Van Assche if ((0 == k) && (! op->do_name))
4942*44704f69SBart Van Assche sgj_pr_hr(jsp, "%s %s [0x18]\n", psplp, fss);
4943*44704f69SBart Van Assche /* call helper */
4944*44704f69SBart Van Assche show_sas_port_param(bp, pl, op, jo3p);
4945*44704f69SBart Van Assche if (jsp->pr_as_json)
4946*44704f69SBart Van Assche sgj_js_nv_o(jsp, jap, NULL /* name */, jo3p);
4947*44704f69SBart Van Assche if ((op->do_pcb) && (! op->do_name))
4948*44704f69SBart Van Assche sgj_pr_hr(jsp, " <%s>\n", get_pcb_str(bp[2], b,
4949*44704f69SBart Van Assche sizeof(b)));
4950*44704f69SBart Van Assche if (op->filter_given)
4951*44704f69SBart Van Assche break;
4952*44704f69SBart Van Assche skip:
4953*44704f69SBart Van Assche k += pl;
4954*44704f69SBart Van Assche bp += pl;
4955*44704f69SBart Van Assche }
4956*44704f69SBart Van Assche return true;
4957*44704f69SBart Van Assche }
4958*44704f69SBart Van Assche
4959*44704f69SBart Van Assche /* Returns true if processed page, false otherwise */
4960*44704f69SBart Van Assche /* STATS_LPAGE [0x19], subpages: 0x0 to 0x1f <gsp,grsp> introduced: SPC-4 */
4961*44704f69SBart Van Assche static bool
show_stats_perform_pages(const uint8_t * resp,int len,struct opts_t * op,sgj_opaque_p jop)4962*44704f69SBart Van Assche show_stats_perform_pages(const uint8_t * resp, int len,
4963*44704f69SBart Van Assche struct opts_t * op, sgj_opaque_p jop)
4964*44704f69SBart Van Assche {
4965*44704f69SBart Van Assche bool nam, spf;
4966*44704f69SBart Van Assche int k, num, param_len, param_code, subpg_code, extra;
4967*44704f69SBart Van Assche uint64_t ull;
4968*44704f69SBart Van Assche const uint8_t * bp;
4969*44704f69SBart Van Assche const char * ccp;
4970*44704f69SBart Van Assche const char * pg_name;
4971*44704f69SBart Van Assche sgj_state * jsp = &op->json_st;
4972*44704f69SBart Van Assche sgj_opaque_p jo2p;
4973*44704f69SBart Van Assche sgj_opaque_p jo3p = NULL;
4974*44704f69SBart Van Assche sgj_opaque_p jap = NULL;
4975*44704f69SBart Van Assche char str[PCB_STR_LEN];
4976*44704f69SBart Van Assche static const char * gsaplp =
4977*44704f69SBart Van Assche "General statistics and performance log page";
4978*44704f69SBart Van Assche static const char * gr_saplp =
4979*44704f69SBart Van Assche "Group statistics and performance log page";
4980*44704f69SBart Van Assche
4981*44704f69SBart Van Assche // yyyyyyyyyyyyyyyyyy
4982*44704f69SBart Van Assche nam = op->do_name;
4983*44704f69SBart Van Assche num = len - 4;
4984*44704f69SBart Van Assche bp = resp + 4;
4985*44704f69SBart Van Assche spf = !!(resp[0] & 0x40);
4986*44704f69SBart Van Assche subpg_code = spf ? resp[1] : NOT_SPG_SUBPG;
4987*44704f69SBart Van Assche if (0 == subpg_code)
4988*44704f69SBart Van Assche pg_name = gsaplp;
4989*44704f69SBart Van Assche else if (subpg_code < 0x20)
4990*44704f69SBart Van Assche pg_name = gr_saplp;
4991*44704f69SBart Van Assche else
4992*44704f69SBart Van Assche pg_name = "Unknown subpage";
4993*44704f69SBart Van Assche if (op->verbose || ((! op->do_raw) && (0 == op->do_hex))) {
4994*44704f69SBart Van Assche if (nam) {
4995*44704f69SBart Van Assche sgj_pr_hr(jsp, "log_page=0x%x\n", STATS_LPAGE);
4996*44704f69SBart Van Assche if (subpg_code > 0)
4997*44704f69SBart Van Assche sgj_pr_hr(jsp, "log_subpage=0x%x\n", subpg_code);
4998*44704f69SBart Van Assche } else {
4999*44704f69SBart Van Assche if (0 == subpg_code)
5000*44704f69SBart Van Assche sgj_pr_hr(jsp, "%s [0x19]\n", gsaplp);
5001*44704f69SBart Van Assche else if (subpg_code < 0x20)
5002*44704f69SBart Van Assche sgj_pr_hr(jsp, "%s (%d) [0x19,0x%x]\n", gr_saplp, subpg_code,
5003*44704f69SBart Van Assche subpg_code);
5004*44704f69SBart Van Assche else
5005*44704f69SBart Van Assche sgj_pr_hr(jsp, "%s: %d [0x19,0x%x]\n", pg_name, subpg_code,
5006*44704f69SBart Van Assche subpg_code);
5007*44704f69SBart Van Assche }
5008*44704f69SBart Van Assche }
5009*44704f69SBart Van Assche if (jsp->pr_as_json)
5010*44704f69SBart Van Assche jo2p = sg_log_js_hdr(jsp, jop, pg_name, resp);
5011*44704f69SBart Van Assche if (subpg_code > 31)
5012*44704f69SBart Van Assche return false;
5013*44704f69SBart Van Assche if (jsp->pr_as_json)
5014*44704f69SBart Van Assche jap = sgj_named_subarray_r(jsp, jo2p, 0 == subpg_code ?
5015*44704f69SBart Van Assche "general_statistics_and_performance_log_parameters" :
5016*44704f69SBart Van Assche "group_statistics_and_performance_log_parameters");
5017*44704f69SBart Van Assche if (0 == subpg_code) { /* General statistics and performance log page */
5018*44704f69SBart Van Assche if (num < 0x5c)
5019*44704f69SBart Van Assche return false;
5020*44704f69SBart Van Assche for (k = num; k > 0; k -= extra, bp += extra) {
5021*44704f69SBart Van Assche unsigned int ui;
5022*44704f69SBart Van Assche
5023*44704f69SBart Van Assche if (k < 3)
5024*44704f69SBart Van Assche return false;
5025*44704f69SBart Van Assche param_len = bp[3];
5026*44704f69SBart Van Assche extra = param_len + 4;
5027*44704f69SBart Van Assche param_code = sg_get_unaligned_be16(bp + 0);
5028*44704f69SBart Van Assche if (op->filter_given) {
5029*44704f69SBart Van Assche if (param_code != op->filter)
5030*44704f69SBart Van Assche continue;
5031*44704f69SBart Van Assche }
5032*44704f69SBart Van Assche if (op->do_raw) {
5033*44704f69SBart Van Assche dStrRaw(bp, extra);
5034*44704f69SBart Van Assche goto skip;
5035*44704f69SBart Van Assche } else if (op->do_hex) {
5036*44704f69SBart Van Assche hex2stdout(bp, extra, op->dstrhex_no_ascii);
5037*44704f69SBart Van Assche goto skip;
5038*44704f69SBart Van Assche }
5039*44704f69SBart Van Assche if (jsp->pr_as_json) {
5040*44704f69SBart Van Assche jo3p = sgj_new_unattached_object_r(jsp);
5041*44704f69SBart Van Assche if (op->do_pcb)
5042*44704f69SBart Van Assche js_pcb(jsp, jo3p, bp[2]);
5043*44704f69SBart Van Assche }
5044*44704f69SBart Van Assche
5045*44704f69SBart Van Assche switch (param_code) {
5046*44704f69SBart Van Assche case 1: /* Statistics and performance log parameter */
5047*44704f69SBart Van Assche ccp = nam ? "parameter_code=1" : "Statistics and performance "
5048*44704f69SBart Van Assche "log parameter";
5049*44704f69SBart Van Assche sgj_pr_hr(jsp, "%s\n", ccp);
5050*44704f69SBart Van Assche ull = sg_get_unaligned_be64(bp + 4);
5051*44704f69SBart Van Assche ccp = nam ? "read_commands=" : "number of read commands = ";
5052*44704f69SBart Van Assche sgj_pr_hr(jsp, " %s%" PRIu64 "\n", ccp, ull);
5053*44704f69SBart Van Assche ull = sg_get_unaligned_be64(bp + 12);
5054*44704f69SBart Van Assche ccp = nam ? "write_commands=" : "number of write commands = ";
5055*44704f69SBart Van Assche sgj_pr_hr(jsp, " %s%" PRIu64 "\n", ccp, ull);
5056*44704f69SBart Van Assche ull = sg_get_unaligned_be64(bp + 20);
5057*44704f69SBart Van Assche ccp = nam ? "lb_received="
5058*44704f69SBart Van Assche : "number of logical blocks received = ";
5059*44704f69SBart Van Assche sgj_pr_hr(jsp, " %s%" PRIu64 "\n", ccp, ull);
5060*44704f69SBart Van Assche ull = sg_get_unaligned_be64(bp + 28);
5061*44704f69SBart Van Assche ccp = nam ? "lb_transmitted="
5062*44704f69SBart Van Assche : "number of logical blocks transmitted = ";
5063*44704f69SBart Van Assche sgj_pr_hr(jsp, " %s%" PRIu64 "\n", ccp, ull);
5064*44704f69SBart Van Assche ull = sg_get_unaligned_be64(bp + 36);
5065*44704f69SBart Van Assche ccp = nam ? "read_proc_intervals="
5066*44704f69SBart Van Assche : "read command processing intervals = ";
5067*44704f69SBart Van Assche sgj_pr_hr(jsp, " %s%" PRIu64 "\n", ccp, ull);
5068*44704f69SBart Van Assche ull = sg_get_unaligned_be64(bp + 44);
5069*44704f69SBart Van Assche ccp = nam ? "write_proc_intervals="
5070*44704f69SBart Van Assche : "write command processing intervals = ";
5071*44704f69SBart Van Assche sgj_pr_hr(jsp, " %s%" PRIu64 "\n", ccp, ull);
5072*44704f69SBart Van Assche ull = sg_get_unaligned_be64(bp + 52);
5073*44704f69SBart Van Assche ccp = nam ? "weight_rw_commands=" : "weighted number of "
5074*44704f69SBart Van Assche "read commands plus write commands = ";
5075*44704f69SBart Van Assche sgj_pr_hr(jsp, " %s%" PRIu64 "\n", ccp, ull);
5076*44704f69SBart Van Assche ull = sg_get_unaligned_be64(bp + 60);
5077*44704f69SBart Van Assche ccp = nam ? "weight_rw_processing=" : "weighted read command "
5078*44704f69SBart Van Assche "processing plus write command processing = ";
5079*44704f69SBart Van Assche sgj_pr_hr(jsp, " %s%" PRIu64 "\n", ccp, ull);
5080*44704f69SBart Van Assche break;
5081*44704f69SBart Van Assche case 2: /* Idle time log parameter */
5082*44704f69SBart Van Assche ccp = nam ? "parameter_code=2" : "Idle time log parameter";
5083*44704f69SBart Van Assche sgj_pr_hr(jsp, "%s\n", ccp);
5084*44704f69SBart Van Assche ull = sg_get_unaligned_be64(bp + 4);
5085*44704f69SBart Van Assche ccp = nam ? "idle_time_intervals=" : "idle time "
5086*44704f69SBart Van Assche "intervals = ";
5087*44704f69SBart Van Assche sgj_pr_hr(jsp, " %s%" PRIu64 "\n", ccp, ull);
5088*44704f69SBart Van Assche break;
5089*44704f69SBart Van Assche case 3: /* Time interval log parameter for general stats */
5090*44704f69SBart Van Assche ccp = nam ? "parameter_code=3" : "Time interval log "
5091*44704f69SBart Van Assche "parameter for general stats";
5092*44704f69SBart Van Assche sgj_pr_hr(jsp, "%s\n", ccp);
5093*44704f69SBart Van Assche ui = sg_get_unaligned_be32(bp + 4);
5094*44704f69SBart Van Assche ccp = nam ? "time_interval_neg_exp=" : "time interval "
5095*44704f69SBart Van Assche "negative exponent = ";
5096*44704f69SBart Van Assche sgj_pr_hr(jsp, " %s%u\n", ccp, ui);
5097*44704f69SBart Van Assche ui = sg_get_unaligned_be32(bp + 8);
5098*44704f69SBart Van Assche ccp = nam ? "time_interval_int=" : "time interval "
5099*44704f69SBart Van Assche "integer = ";
5100*44704f69SBart Van Assche sgj_pr_hr(jsp, " %s%u\n", ccp, ui);
5101*44704f69SBart Van Assche break;
5102*44704f69SBart Van Assche case 4: /* FUA statistics and performance log parameter */
5103*44704f69SBart Van Assche ccp = nam ? "parameter_code=4" : "Force unit access "
5104*44704f69SBart Van Assche "statistics and performance log parameter ";
5105*44704f69SBart Van Assche sgj_pr_hr(jsp, "%s\n", ccp);
5106*44704f69SBart Van Assche ull = sg_get_unaligned_be64(bp + 4);
5107*44704f69SBart Van Assche ccp = nam ? "read_fua_commands=" : "number of read FUA "
5108*44704f69SBart Van Assche "commands = ";
5109*44704f69SBart Van Assche sgj_pr_hr(jsp, " %s%" PRIu64 "\n", ccp, ull);
5110*44704f69SBart Van Assche ull = sg_get_unaligned_be64(bp + 12);
5111*44704f69SBart Van Assche ccp = nam ? "write_fua_commands=" : "number of write FUA "
5112*44704f69SBart Van Assche "commands = ";
5113*44704f69SBart Van Assche sgj_pr_hr(jsp, " %s%" PRIu64 "\n", ccp, ull);
5114*44704f69SBart Van Assche ull = sg_get_unaligned_be64(bp + 20);
5115*44704f69SBart Van Assche ccp = nam ? "read_fua_nv_commands="
5116*44704f69SBart Van Assche : "number of read FUA_NV commands = ";
5117*44704f69SBart Van Assche sgj_pr_hr(jsp, " %s%" PRIu64 "\n", ccp, ull);
5118*44704f69SBart Van Assche ull = sg_get_unaligned_be64(bp + 28);
5119*44704f69SBart Van Assche ccp = nam ? "write_fua_nv_commands="
5120*44704f69SBart Van Assche : "number of write FUA_NV commands = ";
5121*44704f69SBart Van Assche sgj_pr_hr(jsp, " %s%" PRIu64 "\n", ccp, ull);
5122*44704f69SBart Van Assche ull = sg_get_unaligned_be64(bp + 36);
5123*44704f69SBart Van Assche ccp = nam ? "read_fua_proc_intervals="
5124*44704f69SBart Van Assche : "read FUA command processing intervals = ";
5125*44704f69SBart Van Assche sgj_pr_hr(jsp, " %s%" PRIu64 "\n", ccp, ull);
5126*44704f69SBart Van Assche ull = sg_get_unaligned_be64(bp + 44);
5127*44704f69SBart Van Assche ccp = nam ? "write_fua_proc_intervals="
5128*44704f69SBart Van Assche : "write FUA command processing intervals = ";
5129*44704f69SBart Van Assche sgj_pr_hr(jsp, " %s%" PRIu64 "\n", ccp, ull);
5130*44704f69SBart Van Assche ull = sg_get_unaligned_be64(bp + 52);
5131*44704f69SBart Van Assche ccp = nam ? "read_fua_nv_proc_intervals="
5132*44704f69SBart Van Assche : "read FUA_NV command processing intervals = ";
5133*44704f69SBart Van Assche sgj_pr_hr(jsp, " %s%" PRIu64 "\n", ccp, ull);
5134*44704f69SBart Van Assche ull = sg_get_unaligned_be64(bp + 60);
5135*44704f69SBart Van Assche ccp = nam ? "write_fua_nv_proc_intervals="
5136*44704f69SBart Van Assche : "write FUA_NV command processing intervals = ";
5137*44704f69SBart Van Assche sgj_pr_hr(jsp, " %s%" PRIu64 "\n", ccp, ull);
5138*44704f69SBart Van Assche break;
5139*44704f69SBart Van Assche case 6: /* Time interval log parameter for cache stats */
5140*44704f69SBart Van Assche ccp = nam ? "parameter_code=6" : "Time interval log "
5141*44704f69SBart Van Assche "parameter for cache stats";
5142*44704f69SBart Van Assche sgj_pr_hr(jsp, "%s\n", ccp);
5143*44704f69SBart Van Assche ull = sg_get_unaligned_be64(bp + 4);
5144*44704f69SBart Van Assche ccp = nam ? "time_interval_neg_exp=" : "time interval "
5145*44704f69SBart Van Assche "negative exponent = ";
5146*44704f69SBart Van Assche sgj_pr_hr(jsp, " %s%" PRIu64 "\n", ccp, ull);
5147*44704f69SBart Van Assche ull = sg_get_unaligned_be64(bp + 8);
5148*44704f69SBart Van Assche ccp = nam ? "time_interval_int=" : "time interval "
5149*44704f69SBart Van Assche "integer = ";
5150*44704f69SBart Van Assche sgj_pr_hr(jsp, " %s%" PRIu64 "\n", ccp, ull);
5151*44704f69SBart Van Assche break;
5152*44704f69SBart Van Assche default:
5153*44704f69SBart Van Assche if (nam) {
5154*44704f69SBart Van Assche sgj_pr_hr(jsp, "parameter_code=%d\n", param_code);
5155*44704f69SBart Van Assche sgj_pr_hr(jsp, " unknown=1\n");
5156*44704f69SBart Van Assche } else
5157*44704f69SBart Van Assche pr2serr("show_performance... unknown %s %d\n", param_c,
5158*44704f69SBart Van Assche param_code);
5159*44704f69SBart Van Assche if (op->verbose)
5160*44704f69SBart Van Assche hex2stderr(bp, extra, 1);
5161*44704f69SBart Van Assche break;
5162*44704f69SBart Van Assche }
5163*44704f69SBart Van Assche if (jsp->pr_as_json)
5164*44704f69SBart Van Assche sgj_js_nv_o(jsp, jap, NULL /* name */, jo3p);
5165*44704f69SBart Van Assche if ((op->do_pcb) && (! op->do_name))
5166*44704f69SBart Van Assche sgj_pr_hr(jsp, " <%s>\n", get_pcb_str(bp[2], str,
5167*44704f69SBart Van Assche sizeof(str)));
5168*44704f69SBart Van Assche skip:
5169*44704f69SBart Van Assche if (op->filter_given)
5170*44704f69SBart Van Assche break;
5171*44704f69SBart Van Assche }
5172*44704f69SBart Van Assche } else { /* Group statistics and performance (n) log page */
5173*44704f69SBart Van Assche if (num < 0x34)
5174*44704f69SBart Van Assche return false;
5175*44704f69SBart Van Assche for (k = num; k > 0; k -= extra, bp += extra) {
5176*44704f69SBart Van Assche if (k < 3)
5177*44704f69SBart Van Assche return false;
5178*44704f69SBart Van Assche param_len = bp[3];
5179*44704f69SBart Van Assche extra = param_len + 4;
5180*44704f69SBart Van Assche param_code = sg_get_unaligned_be16(bp + 0);
5181*44704f69SBart Van Assche if (op->filter_given) {
5182*44704f69SBart Van Assche if (param_code != op->filter)
5183*44704f69SBart Van Assche continue;
5184*44704f69SBart Van Assche }
5185*44704f69SBart Van Assche if (op->do_raw) {
5186*44704f69SBart Van Assche dStrRaw(bp, extra);
5187*44704f69SBart Van Assche goto skip2;
5188*44704f69SBart Van Assche } else if (op->do_hex) {
5189*44704f69SBart Van Assche hex2stdout(bp, extra, op->dstrhex_no_ascii);
5190*44704f69SBart Van Assche goto skip2;
5191*44704f69SBart Van Assche }
5192*44704f69SBart Van Assche if (jsp->pr_as_json) {
5193*44704f69SBart Van Assche jo3p = sgj_new_unattached_object_r(jsp);
5194*44704f69SBart Van Assche if (op->do_pcb)
5195*44704f69SBart Van Assche js_pcb(jsp, jo3p, bp[2]);
5196*44704f69SBart Van Assche }
5197*44704f69SBart Van Assche
5198*44704f69SBart Van Assche switch (param_code) {
5199*44704f69SBart Van Assche case 1: /* Group n Statistics and performance log parameter */
5200*44704f69SBart Van Assche if (nam)
5201*44704f69SBart Van Assche sgj_pr_hr(jsp, "parameter_code=1\n");
5202*44704f69SBart Van Assche else
5203*44704f69SBart Van Assche sgj_pr_hr(jsp, "Group %d Statistics and performance log "
5204*44704f69SBart Van Assche "parameter\n", subpg_code);
5205*44704f69SBart Van Assche ull = sg_get_unaligned_be64(bp + 4);
5206*44704f69SBart Van Assche ccp = nam ? "gn_read_commands=" : "group n number of read "
5207*44704f69SBart Van Assche "commands = ";
5208*44704f69SBart Van Assche sgj_pr_hr(jsp, " %s%" PRIu64 "\n", ccp, ull);
5209*44704f69SBart Van Assche ull = sg_get_unaligned_be64(bp + 12);
5210*44704f69SBart Van Assche ccp = nam ? "gn_write_commands=" : "group n number of write "
5211*44704f69SBart Van Assche "commands = ";
5212*44704f69SBart Van Assche sgj_pr_hr(jsp, " %s%" PRIu64 "\n", ccp, ull);
5213*44704f69SBart Van Assche ull = sg_get_unaligned_be64(bp + 20);
5214*44704f69SBart Van Assche ccp = nam ? "gn_lb_received="
5215*44704f69SBart Van Assche : "group n number of logical blocks received = ";
5216*44704f69SBart Van Assche sgj_pr_hr(jsp, " %s%" PRIu64 "\n", ccp, ull);
5217*44704f69SBart Van Assche ull = sg_get_unaligned_be64(bp + 28);
5218*44704f69SBart Van Assche ccp = nam ? "gn_lb_transmitted="
5219*44704f69SBart Van Assche : "group n number of logical blocks transmitted = ";
5220*44704f69SBart Van Assche sgj_pr_hr(jsp, " %s%" PRIu64 "\n", ccp, ull);
5221*44704f69SBart Van Assche ull = sg_get_unaligned_be64(bp + 36);
5222*44704f69SBart Van Assche ccp = nam ? "gn_read_proc_intervals="
5223*44704f69SBart Van Assche : "group n read command processing intervals = ";
5224*44704f69SBart Van Assche sgj_pr_hr(jsp, " %s%" PRIu64 "\n", ccp, ull);
5225*44704f69SBart Van Assche ull = sg_get_unaligned_be64(bp + 44);
5226*44704f69SBart Van Assche ccp = nam ? "gn_write_proc_intervals="
5227*44704f69SBart Van Assche : "group n write command processing intervals = ";
5228*44704f69SBart Van Assche sgj_pr_hr(jsp, " %s%" PRIu64 "\n", ccp, ull);
5229*44704f69SBart Van Assche break;
5230*44704f69SBart Van Assche case 4: /* Group n FUA statistics and performance log parameter */
5231*44704f69SBart Van Assche ccp = nam ? "parameter_code=4" : "Group n force unit access "
5232*44704f69SBart Van Assche "statistics and performance log parameter";
5233*44704f69SBart Van Assche sgj_pr_hr(jsp, "%s\n", ccp);
5234*44704f69SBart Van Assche ull = sg_get_unaligned_be64(bp + 4);
5235*44704f69SBart Van Assche ccp = nam ? "gn_read_fua_commands="
5236*44704f69SBart Van Assche : "group n number of read FUA commands = ";
5237*44704f69SBart Van Assche sgj_pr_hr(jsp, " %s%" PRIu64 "\n", ccp, ull);
5238*44704f69SBart Van Assche ull = sg_get_unaligned_be64(bp + 12);
5239*44704f69SBart Van Assche ccp = nam ? "gn_write_fua_commands="
5240*44704f69SBart Van Assche : "group n number of write FUA commands = ";
5241*44704f69SBart Van Assche sgj_pr_hr(jsp, " %s%" PRIu64 "\n", ccp, ull);
5242*44704f69SBart Van Assche ull = sg_get_unaligned_be64(bp + 20);
5243*44704f69SBart Van Assche ccp = nam ? "gn_read_fua_nv_commands="
5244*44704f69SBart Van Assche : "group n number of read FUA_NV commands = ";
5245*44704f69SBart Van Assche sgj_pr_hr(jsp, " %s%" PRIu64 "\n", ccp, ull);
5246*44704f69SBart Van Assche ull = sg_get_unaligned_be64(bp + 28);
5247*44704f69SBart Van Assche ccp = nam ? "gn_write_fua_nv_commands="
5248*44704f69SBart Van Assche : "group n number of write FUA_NV commands = ";
5249*44704f69SBart Van Assche sgj_pr_hr(jsp, " %s%" PRIu64 "\n", ccp, ull);
5250*44704f69SBart Van Assche ull = sg_get_unaligned_be64(bp + 36);
5251*44704f69SBart Van Assche ccp = nam ? "gn_read_fua_proc_intervals="
5252*44704f69SBart Van Assche : "group n read FUA command processing intervals = ";
5253*44704f69SBart Van Assche sgj_pr_hr(jsp, " %s%" PRIu64 "\n", ccp, ull);
5254*44704f69SBart Van Assche ull = sg_get_unaligned_be64(bp + 44);
5255*44704f69SBart Van Assche ccp = nam ? "gn_write_fua_proc_intervals=" : "group n write "
5256*44704f69SBart Van Assche "FUA command processing intervals = ";
5257*44704f69SBart Van Assche sgj_pr_hr(jsp, " %s%" PRIu64 "\n", ccp, ull);
5258*44704f69SBart Van Assche ull = sg_get_unaligned_be64(bp + 52);
5259*44704f69SBart Van Assche ccp = nam ? "gn_read_fua_nv_proc_intervals=" : "group n "
5260*44704f69SBart Van Assche "read FUA_NV command processing intervals = ";
5261*44704f69SBart Van Assche sgj_pr_hr(jsp, " %s%" PRIu64 "\n", ccp, ull);
5262*44704f69SBart Van Assche ull = sg_get_unaligned_be64(bp + 60);
5263*44704f69SBart Van Assche ccp = nam ? "gn_write_fua_nv_proc_intervals=" : "group n "
5264*44704f69SBart Van Assche "write FUA_NV command processing intervals = ";
5265*44704f69SBart Van Assche sgj_pr_hr(jsp, " %s%" PRIu64 "\n", ccp, ull);
5266*44704f69SBart Van Assche break;
5267*44704f69SBart Van Assche default:
5268*44704f69SBart Van Assche if (nam) {
5269*44704f69SBart Van Assche sgj_pr_hr(jsp, "parameter_code=%d\n", param_code);
5270*44704f69SBart Van Assche sgj_pr_hr(jsp, " unknown=1\n");
5271*44704f69SBart Van Assche } else
5272*44704f69SBart Van Assche pr2serr("show_performance... unknown %s %d\n", param_c,
5273*44704f69SBart Van Assche param_code);
5274*44704f69SBart Van Assche if (op->verbose)
5275*44704f69SBart Van Assche hex2stderr(bp, extra, 1);
5276*44704f69SBart Van Assche break;
5277*44704f69SBart Van Assche }
5278*44704f69SBart Van Assche if (jsp->pr_as_json)
5279*44704f69SBart Van Assche sgj_js_nv_o(jsp, jap, NULL /* name */, jo3p);
5280*44704f69SBart Van Assche if ((op->do_pcb) && (! op->do_name))
5281*44704f69SBart Van Assche sgj_pr_hr(jsp, " <%s>\n", get_pcb_str(bp[2], str,
5282*44704f69SBart Van Assche sizeof(str)));
5283*44704f69SBart Van Assche skip2:
5284*44704f69SBart Van Assche if (op->filter_given)
5285*44704f69SBart Van Assche break;
5286*44704f69SBart Van Assche }
5287*44704f69SBart Van Assche }
5288*44704f69SBart Van Assche return true;
5289*44704f69SBart Van Assche }
5290*44704f69SBart Van Assche
5291*44704f69SBart Van Assche /* Returns true if processed page, false otherwise */
5292*44704f69SBart Van Assche /* STATS_LPAGE [0x19], CACHE_STATS_SUBPG [0x20] <cms> introduced: SPC-4 */
5293*44704f69SBart Van Assche static bool
show_cache_stats_page(const uint8_t * resp,int len,struct opts_t * op,sgj_opaque_p jop)5294*44704f69SBart Van Assche show_cache_stats_page(const uint8_t * resp, int len, struct opts_t * op,
5295*44704f69SBart Van Assche sgj_opaque_p jop)
5296*44704f69SBart Van Assche {
5297*44704f69SBart Van Assche int k, num, subpg_code, extra;
5298*44704f69SBart Van Assche bool nam, spf;
5299*44704f69SBart Van Assche unsigned int ui;
5300*44704f69SBart Van Assche const uint8_t * bp;
5301*44704f69SBart Van Assche const char * ccp;
5302*44704f69SBart Van Assche uint64_t ull;
5303*44704f69SBart Van Assche char str[PCB_STR_LEN];
5304*44704f69SBart Van Assche
5305*44704f69SBart Van Assche if (jop) { };
5306*44704f69SBart Van Assche nam = op->do_name;
5307*44704f69SBart Van Assche num = len - 4;
5308*44704f69SBart Van Assche bp = resp + 4;
5309*44704f69SBart Van Assche if (num < 4) {
5310*44704f69SBart Van Assche pr2serr("badly formed Cache memory statistics page\n");
5311*44704f69SBart Van Assche return false;
5312*44704f69SBart Van Assche }
5313*44704f69SBart Van Assche spf = !!(resp[0] & 0x40);
5314*44704f69SBart Van Assche subpg_code = spf ? resp[1] : NOT_SPG_SUBPG;
5315*44704f69SBart Van Assche if (op->verbose || ((! op->do_raw) && (0 == op->do_hex))) {
5316*44704f69SBart Van Assche if (nam) {
5317*44704f69SBart Van Assche printf("log_page=0x%x\n", STATS_LPAGE);
5318*44704f69SBart Van Assche if (subpg_code > 0)
5319*44704f69SBart Van Assche printf("log_subpage=0x%x\n", subpg_code);
5320*44704f69SBart Van Assche } else
5321*44704f69SBart Van Assche printf("Cache memory statistics page [0x19,0x20]\n");
5322*44704f69SBart Van Assche }
5323*44704f69SBart Van Assche
5324*44704f69SBart Van Assche for (k = num; k > 0; k -= extra, bp += extra) {
5325*44704f69SBart Van Assche int pc;
5326*44704f69SBart Van Assche
5327*44704f69SBart Van Assche if (k < 3) {
5328*44704f69SBart Van Assche pr2serr("short Cache memory statistics page\n");
5329*44704f69SBart Van Assche return false;
5330*44704f69SBart Van Assche }
5331*44704f69SBart Van Assche if (8 != bp[3]) {
5332*44704f69SBart Van Assche printf("Cache memory statistics page parameter length not "
5333*44704f69SBart Van Assche "8\n");
5334*44704f69SBart Van Assche return false;
5335*44704f69SBart Van Assche }
5336*44704f69SBart Van Assche extra = bp[3] + 4;
5337*44704f69SBart Van Assche pc = sg_get_unaligned_be16(bp + 0);
5338*44704f69SBart Van Assche if (op->filter_given) {
5339*44704f69SBart Van Assche if (pc != op->filter)
5340*44704f69SBart Van Assche continue;
5341*44704f69SBart Van Assche }
5342*44704f69SBart Van Assche if (op->do_raw) {
5343*44704f69SBart Van Assche dStrRaw(bp, extra);
5344*44704f69SBart Van Assche goto skip;
5345*44704f69SBart Van Assche } else if (op->do_hex) {
5346*44704f69SBart Van Assche hex2stdout(bp, extra, op->dstrhex_no_ascii);
5347*44704f69SBart Van Assche goto skip;
5348*44704f69SBart Van Assche }
5349*44704f69SBart Van Assche switch (pc) {
5350*44704f69SBart Van Assche case 1: /* Read cache memory hits log parameter */
5351*44704f69SBart Van Assche ccp = nam ? "parameter_code=1" :
5352*44704f69SBart Van Assche "Read cache memory hits log parameter";
5353*44704f69SBart Van Assche printf("%s\n", ccp);
5354*44704f69SBart Van Assche ull = sg_get_unaligned_be64(bp + 4);
5355*44704f69SBart Van Assche ccp = nam ? "read_cache_memory_hits=" :
5356*44704f69SBart Van Assche "read cache memory hits = ";
5357*44704f69SBart Van Assche printf(" %s%" PRIu64 "\n", ccp, ull);
5358*44704f69SBart Van Assche break;
5359*44704f69SBart Van Assche case 2: /* Reads to cache memory log parameter */
5360*44704f69SBart Van Assche ccp = nam ? "parameter_code=2" :
5361*44704f69SBart Van Assche "Reads to cache memory log parameter";
5362*44704f69SBart Van Assche printf("%s\n", ccp);
5363*44704f69SBart Van Assche ull = sg_get_unaligned_be64(bp + 4);
5364*44704f69SBart Van Assche ccp = nam ? "reads_to_cache_memory=" :
5365*44704f69SBart Van Assche "reads to cache memory = ";
5366*44704f69SBart Van Assche printf(" %s%" PRIu64 "\n", ccp, ull);
5367*44704f69SBart Van Assche break;
5368*44704f69SBart Van Assche case 3: /* Write cache memory hits log parameter */
5369*44704f69SBart Van Assche ccp = nam ? "parameter_code=3" :
5370*44704f69SBart Van Assche "Write cache memory hits log parameter";
5371*44704f69SBart Van Assche printf("%s\n", ccp);
5372*44704f69SBart Van Assche ull = sg_get_unaligned_be64(bp + 4);
5373*44704f69SBart Van Assche ccp = nam ? "write_cache_memory_hits=" :
5374*44704f69SBart Van Assche "write cache memory hits = ";
5375*44704f69SBart Van Assche printf(" %s%" PRIu64 "\n", ccp, ull);
5376*44704f69SBart Van Assche break;
5377*44704f69SBart Van Assche case 4: /* Writes from cache memory log parameter */
5378*44704f69SBart Van Assche ccp = nam ? "parameter_code=4" :
5379*44704f69SBart Van Assche "Writes from cache memory log parameter";
5380*44704f69SBart Van Assche printf("%s\n", ccp);
5381*44704f69SBart Van Assche ull = sg_get_unaligned_be64(bp + 4);
5382*44704f69SBart Van Assche ccp = nam ? "writes_from_cache_memory=" :
5383*44704f69SBart Van Assche "writes from cache memory = ";
5384*44704f69SBart Van Assche printf(" %s%" PRIu64 "\n", ccp, ull);
5385*44704f69SBart Van Assche break;
5386*44704f69SBart Van Assche case 5: /* Time from last hard reset log parameter */
5387*44704f69SBart Van Assche ccp = nam ? "parameter_code=5" :
5388*44704f69SBart Van Assche "Time from last hard reset log parameter";
5389*44704f69SBart Van Assche printf("%s\n", ccp);
5390*44704f69SBart Van Assche ull = sg_get_unaligned_be64(bp + 4);
5391*44704f69SBart Van Assche ccp = nam ? "time_from_last_hard_reset=" :
5392*44704f69SBart Van Assche "time from last hard reset = ";
5393*44704f69SBart Van Assche printf(" %s%" PRIu64 "\n", ccp, ull);
5394*44704f69SBart Van Assche break;
5395*44704f69SBart Van Assche case 6: /* Time interval log parameter for cache stats */
5396*44704f69SBart Van Assche ccp = nam ? "parameter_code=6" :
5397*44704f69SBart Van Assche "Time interval log parameter";
5398*44704f69SBart Van Assche printf("%s\n", ccp);
5399*44704f69SBart Van Assche ui = sg_get_unaligned_be32(bp + 4);
5400*44704f69SBart Van Assche ccp = nam ? "time_interval_neg_exp=" : "time interval "
5401*44704f69SBart Van Assche "negative exponent = ";
5402*44704f69SBart Van Assche printf(" %s%u\n", ccp, ui);
5403*44704f69SBart Van Assche ui = sg_get_unaligned_be32(bp + 8);
5404*44704f69SBart Van Assche ccp = nam ? "time_interval_int=" : "time interval "
5405*44704f69SBart Van Assche "integer = ";
5406*44704f69SBart Van Assche printf(" %s%u\n", ccp, ui);
5407*44704f69SBart Van Assche break;
5408*44704f69SBart Van Assche default:
5409*44704f69SBart Van Assche if (nam) {
5410*44704f69SBart Van Assche printf("parameter_code=%d\n", pc);
5411*44704f69SBart Van Assche printf(" unknown=1\n");
5412*44704f69SBart Van Assche } else
5413*44704f69SBart Van Assche pr2serr("show_performance... unknown %s %d\n", param_c,
5414*44704f69SBart Van Assche pc);
5415*44704f69SBart Van Assche if (op->verbose)
5416*44704f69SBart Van Assche hex2stderr(bp, extra, 1);
5417*44704f69SBart Van Assche break;
5418*44704f69SBart Van Assche }
5419*44704f69SBart Van Assche if ((op->do_pcb) && (! op->do_name))
5420*44704f69SBart Van Assche printf(" <%s>\n", get_pcb_str(bp[2], str, sizeof(str)));
5421*44704f69SBart Van Assche skip:
5422*44704f69SBart Van Assche if (op->filter_given)
5423*44704f69SBart Van Assche break;
5424*44704f69SBart Van Assche }
5425*44704f69SBart Van Assche return true;
5426*44704f69SBart Van Assche }
5427*44704f69SBart Van Assche
5428*44704f69SBart Van Assche /* FORMAT_STATUS_LPAGE [0x8] <fs> introduced: SBC-2 */
5429*44704f69SBart Van Assche static bool
show_format_status_page(const uint8_t * resp,int len,struct opts_t * op,sgj_opaque_p jop)5430*44704f69SBart Van Assche show_format_status_page(const uint8_t * resp, int len,
5431*44704f69SBart Van Assche struct opts_t * op, sgj_opaque_p jop)
5432*44704f69SBart Van Assche {
5433*44704f69SBart Van Assche bool is_count, is_not_avail;
5434*44704f69SBart Van Assche int k, num, pl, pc;
5435*44704f69SBart Van Assche uint64_t ull;
5436*44704f69SBart Van Assche const char * cp = "";
5437*44704f69SBart Van Assche const uint8_t * bp;
5438*44704f69SBart Van Assche const uint8_t * xp;
5439*44704f69SBart Van Assche sgj_state * jsp = &op->json_st;
5440*44704f69SBart Van Assche sgj_opaque_p jo2p;
5441*44704f69SBart Van Assche sgj_opaque_p jo3p = NULL;
5442*44704f69SBart Van Assche sgj_opaque_p jap = NULL;
5443*44704f69SBart Van Assche char str[PCB_STR_LEN];
5444*44704f69SBart Van Assche char b[512];
5445*44704f69SBart Van Assche static const char * fslp = "Format status log page";
5446*44704f69SBart Van Assche static const char * fso = "Format status out";
5447*44704f69SBart Van Assche static const char * fso_sn = "format_status_out";
5448*44704f69SBart Van Assche
5449*44704f69SBart Van Assche if (op->verbose || ((! op->do_raw) && (0 == op->do_hex)))
5450*44704f69SBart Van Assche sgj_pr_hr(jsp, "%s [0x8]\n", fslp);
5451*44704f69SBart Van Assche num = len - 4;
5452*44704f69SBart Van Assche bp = &resp[0] + 4;
5453*44704f69SBart Van Assche if (jsp->pr_as_json) {
5454*44704f69SBart Van Assche jo2p = sg_log_js_hdr(jsp, jop, fslp, resp);
5455*44704f69SBart Van Assche jap = sgj_named_subarray_r(jsp, jo2p, "format_status_log_parameters");
5456*44704f69SBart Van Assche }
5457*44704f69SBart Van Assche
5458*44704f69SBart Van Assche
5459*44704f69SBart Van Assche while (num > 3) {
5460*44704f69SBart Van Assche pc = sg_get_unaligned_be16(bp + 0);
5461*44704f69SBart Van Assche pl = bp[3] + 4;
5462*44704f69SBart Van Assche if (op->filter_given) {
5463*44704f69SBart Van Assche if (pc != op->filter)
5464*44704f69SBart Van Assche goto skip;
5465*44704f69SBart Van Assche }
5466*44704f69SBart Van Assche if (op->do_raw) {
5467*44704f69SBart Van Assche dStrRaw(bp, pl);
5468*44704f69SBart Van Assche goto filter_chk;
5469*44704f69SBart Van Assche } else if (op->do_hex) {
5470*44704f69SBart Van Assche hex2stdout(bp, pl, op->dstrhex_no_ascii);
5471*44704f69SBart Van Assche goto filter_chk;
5472*44704f69SBart Van Assche }
5473*44704f69SBart Van Assche if (jsp->pr_as_json) {
5474*44704f69SBart Van Assche jo3p = sgj_new_unattached_object_r(jsp);
5475*44704f69SBart Van Assche if (op->do_pcb)
5476*44704f69SBart Van Assche js_pcb(jsp, jo3p, bp[2]);
5477*44704f69SBart Van Assche }
5478*44704f69SBart Van Assche is_count = true;
5479*44704f69SBart Van Assche
5480*44704f69SBart Van Assche switch (pc) {
5481*44704f69SBart Van Assche case 0:
5482*44704f69SBart Van Assche is_not_avail = false;
5483*44704f69SBart Van Assche if (pl < 5)
5484*44704f69SBart Van Assche sgj_pr_hr(jsp, " %s: <empty>\n", fso);
5485*44704f69SBart Van Assche else {
5486*44704f69SBart Van Assche if (sg_all_ffs(bp + 4, pl - 4)) {
5487*44704f69SBart Van Assche sgj_pr_hr(jsp, " %s: <%s>\n", fso, not_avail);
5488*44704f69SBart Van Assche is_not_avail = true;
5489*44704f69SBart Van Assche } else {
5490*44704f69SBart Van Assche hex2str(bp + 4, pl - 4, " ", op->hex2str_oformat,
5491*44704f69SBart Van Assche sizeof(b), b);
5492*44704f69SBart Van Assche sgj_pr_hr(jsp, " %s:\n%s", fso, b);
5493*44704f69SBart Van Assche
5494*44704f69SBart Van Assche
5495*44704f69SBart Van Assche }
5496*44704f69SBart Van Assche }
5497*44704f69SBart Van Assche if (jsp->pr_as_json) {
5498*44704f69SBart Van Assche sgj_js_nv_ihexstr(jsp, jo3p, param_c_sn, pc, NULL, fso);
5499*44704f69SBart Van Assche if (is_not_avail)
5500*44704f69SBart Van Assche sgj_js_nv_ihexstr(jsp, jo3p, fso_sn, 0, NULL, not_avail);
5501*44704f69SBart Van Assche else
5502*44704f69SBart Van Assche sgj_js_nv_hex_bytes(jsp, jo3p, fso_sn, bp + 4, pl - 4);
5503*44704f69SBart Van Assche }
5504*44704f69SBart Van Assche is_count = false;
5505*44704f69SBart Van Assche break;
5506*44704f69SBart Van Assche case 1:
5507*44704f69SBart Van Assche cp = "Grown defects during certification";
5508*44704f69SBart Van Assche break;
5509*44704f69SBart Van Assche case 2:
5510*44704f69SBart Van Assche cp = "Total blocks reassigned during format";
5511*44704f69SBart Van Assche break;
5512*44704f69SBart Van Assche case 3:
5513*44704f69SBart Van Assche cp = "Total new blocks reassigned";
5514*44704f69SBart Van Assche break;
5515*44704f69SBart Van Assche case 4:
5516*44704f69SBart Van Assche cp = "Power on minutes since format";
5517*44704f69SBart Van Assche break;
5518*44704f69SBart Van Assche default:
5519*44704f69SBart Van Assche sgj_pr_hr(jsp, " Unknown Format %s = 0x%x\n", param_c, pc);
5520*44704f69SBart Van Assche is_count = false;
5521*44704f69SBart Van Assche hex2fp(bp, pl, " ", op->hex2str_oformat, stdout);
5522*44704f69SBart Van Assche if (jsp->pr_as_json) {
5523*44704f69SBart Van Assche sgj_js_nv_ihexstr(jsp, jo3p, param_c_sn, pc, NULL, unknown_s);
5524*44704f69SBart Van Assche sgj_js_nv_hex_bytes(jsp, jo3p, in_hex, bp, pl);
5525*44704f69SBart Van Assche }
5526*44704f69SBart Van Assche break;
5527*44704f69SBart Van Assche }
5528*44704f69SBart Van Assche if (is_count) {
5529*44704f69SBart Van Assche k = pl - 4;
5530*44704f69SBart Van Assche xp = bp + 4;
5531*44704f69SBart Van Assche is_not_avail = false;
5532*44704f69SBart Van Assche ull = 0;
5533*44704f69SBart Van Assche if (sg_all_ffs(xp, k)) {
5534*44704f69SBart Van Assche sgj_pr_hr(jsp, " %s: <%s>\n", cp, not_avail);
5535*44704f69SBart Van Assche is_not_avail = true;
5536*44704f69SBart Van Assche } else {
5537*44704f69SBart Van Assche if (k > (int)sizeof(ull)) {
5538*44704f69SBart Van Assche xp += (k - sizeof(ull));
5539*44704f69SBart Van Assche k = sizeof(ull);
5540*44704f69SBart Van Assche }
5541*44704f69SBart Van Assche ull = sg_get_unaligned_be(k, xp);
5542*44704f69SBart Van Assche sgj_pr_hr(jsp, " %s = %" PRIu64 "\n", cp, ull);
5543*44704f69SBart Van Assche }
5544*44704f69SBart Van Assche if (jsp->pr_as_json) {
5545*44704f69SBart Van Assche sgj_js_nv_ihexstr(jsp, jo3p, param_c_sn, pc, NULL, cp);
5546*44704f69SBart Van Assche sgj_convert_to_snake_name(cp, b, sizeof(b));
5547*44704f69SBart Van Assche if (is_not_avail)
5548*44704f69SBart Van Assche sgj_js_nv_ihexstr(jsp, jo3p, b, 0, NULL, not_avail);
5549*44704f69SBart Van Assche else
5550*44704f69SBart Van Assche sgj_js_nv_ihex(jsp, jo3p, b, ull);
5551*44704f69SBart Van Assche }
5552*44704f69SBart Van Assche }
5553*44704f69SBart Van Assche if (jsp->pr_as_json)
5554*44704f69SBart Van Assche sgj_js_nv_o(jsp, jap, NULL /* name */, jo3p);
5555*44704f69SBart Van Assche if ((op->do_pcb) && (! op->do_name))
5556*44704f69SBart Van Assche sgj_pr_hr(jsp, " <%s>\n", get_pcb_str(bp[2], str,
5557*44704f69SBart Van Assche sizeof(str)));
5558*44704f69SBart Van Assche filter_chk:
5559*44704f69SBart Van Assche if (op->filter_given)
5560*44704f69SBart Van Assche break;
5561*44704f69SBart Van Assche skip:
5562*44704f69SBart Van Assche num -= pl;
5563*44704f69SBart Van Assche bp += pl;
5564*44704f69SBart Van Assche }
5565*44704f69SBart Van Assche return true;
5566*44704f69SBart Van Assche }
5567*44704f69SBart Van Assche
5568*44704f69SBart Van Assche /* Non-volatile cache page [0x17] <nvc> introduced: SBC-2
5569*44704f69SBart Van Assche * Standard vacillates between "non-volatile" and "nonvolatile" */
5570*44704f69SBart Van Assche static bool
show_non_volatile_cache_page(const uint8_t * resp,int len,struct opts_t * op,sgj_opaque_p jop)5571*44704f69SBart Van Assche show_non_volatile_cache_page(const uint8_t * resp, int len,
5572*44704f69SBart Van Assche struct opts_t * op, sgj_opaque_p jop)
5573*44704f69SBart Van Assche {
5574*44704f69SBart Van Assche int j, num, pl, pc;
5575*44704f69SBart Van Assche const char * cp;
5576*44704f69SBart Van Assche const char * c2p;
5577*44704f69SBart Van Assche const uint8_t * bp;
5578*44704f69SBart Van Assche sgj_state * jsp = &op->json_st;
5579*44704f69SBart Van Assche sgj_opaque_p jo2p;
5580*44704f69SBart Van Assche sgj_opaque_p jo3p = NULL;
5581*44704f69SBart Van Assche sgj_opaque_p jap = NULL;
5582*44704f69SBart Van Assche char str[PCB_STR_LEN];
5583*44704f69SBart Van Assche char b[96];
5584*44704f69SBart Van Assche static const char * nvclp = "Non-volatile cache log page";
5585*44704f69SBart Van Assche static const char * ziinv = "0 (i.e. it is now volatile)";
5586*44704f69SBart Van Assche static const char * indef = "indefinite";
5587*44704f69SBart Van Assche
5588*44704f69SBart Van Assche if (op->verbose || ((! op->do_raw) && (0 == op->do_hex)))
5589*44704f69SBart Van Assche sgj_pr_hr(jsp, "%s [0x17]\n", nvclp);
5590*44704f69SBart Van Assche num = len - 4;
5591*44704f69SBart Van Assche bp = &resp[0] + 4;
5592*44704f69SBart Van Assche if (jsp->pr_as_json) {
5593*44704f69SBart Van Assche jo2p = sg_log_js_hdr(jsp, jop, nvclp, resp);
5594*44704f69SBart Van Assche jap = sgj_named_subarray_r(jsp, jo2p,
5595*44704f69SBart Van Assche "nonvolatile_cache_log_parameters");
5596*44704f69SBart Van Assche }
5597*44704f69SBart Van Assche
5598*44704f69SBart Van Assche while (num > 3) {
5599*44704f69SBart Van Assche pc = sg_get_unaligned_be16(bp + 0);
5600*44704f69SBart Van Assche pl = bp[3] + 4;
5601*44704f69SBart Van Assche if (op->filter_given) {
5602*44704f69SBart Van Assche if (pc != op->filter)
5603*44704f69SBart Van Assche goto skip;
5604*44704f69SBart Van Assche }
5605*44704f69SBart Van Assche if (op->do_raw) {
5606*44704f69SBart Van Assche dStrRaw(bp, pl);
5607*44704f69SBart Van Assche goto filter_chk;
5608*44704f69SBart Van Assche } else if (op->do_hex) {
5609*44704f69SBart Van Assche hex2stdout(bp, pl, op->dstrhex_no_ascii);
5610*44704f69SBart Van Assche goto filter_chk;
5611*44704f69SBart Van Assche }
5612*44704f69SBart Van Assche if (jsp->pr_as_json) {
5613*44704f69SBart Van Assche jo3p = sgj_new_unattached_object_r(jsp);
5614*44704f69SBart Van Assche if (op->do_pcb)
5615*44704f69SBart Van Assche js_pcb(jsp, jo3p, bp[2]);
5616*44704f69SBart Van Assche }
5617*44704f69SBart Van Assche
5618*44704f69SBart Van Assche cp = NULL;
5619*44704f69SBart Van Assche switch (pc) {
5620*44704f69SBart Van Assche case 0:
5621*44704f69SBart Van Assche cp = "Remaining nonvolatile time";
5622*44704f69SBart Van Assche c2p = NULL;
5623*44704f69SBart Van Assche j = sg_get_unaligned_be24(bp + 5);
5624*44704f69SBart Van Assche switch (j) {
5625*44704f69SBart Van Assche case 0:
5626*44704f69SBart Van Assche c2p = ziinv;
5627*44704f69SBart Van Assche sgj_pr_hr(jsp, " %s: %s\n", cp, c2p);
5628*44704f69SBart Van Assche break;
5629*44704f69SBart Van Assche case 1:
5630*44704f69SBart Van Assche c2p = unknown_s;
5631*44704f69SBart Van Assche sgj_pr_hr(jsp, " %s: <%s>\n", cp, c2p);
5632*44704f69SBart Van Assche break;
5633*44704f69SBart Van Assche case 0xffffff:
5634*44704f69SBart Van Assche c2p = indef;
5635*44704f69SBart Van Assche sgj_pr_hr(jsp, " %s: <%s>\n", cp, c2p);
5636*44704f69SBart Van Assche break;
5637*44704f69SBart Van Assche default:
5638*44704f69SBart Van Assche snprintf(b, sizeof(b), "%d minutes [%d:%d]", j, (j / 60),
5639*44704f69SBart Van Assche (j % 60));
5640*44704f69SBart Van Assche c2p = b;
5641*44704f69SBart Van Assche sgj_pr_hr(jsp, " %s: %s\n", cp, c2p);
5642*44704f69SBart Van Assche break;
5643*44704f69SBart Van Assche }
5644*44704f69SBart Van Assche break;
5645*44704f69SBart Van Assche case 1:
5646*44704f69SBart Van Assche cp = "Maximum non-volatile time";
5647*44704f69SBart Van Assche c2p = NULL;
5648*44704f69SBart Van Assche j = sg_get_unaligned_be24(bp + 5);
5649*44704f69SBart Van Assche switch (j) {
5650*44704f69SBart Van Assche case 0:
5651*44704f69SBart Van Assche c2p = ziinv;
5652*44704f69SBart Van Assche sgj_pr_hr(jsp, " %s: %s\n", cp, c2p);
5653*44704f69SBart Van Assche break;
5654*44704f69SBart Van Assche case 1:
5655*44704f69SBart Van Assche c2p = rsv_s;
5656*44704f69SBart Van Assche sgj_pr_hr(jsp, " %s: <%s>\n", cp, c2p);
5657*44704f69SBart Van Assche break;
5658*44704f69SBart Van Assche case 0xffffff:
5659*44704f69SBart Van Assche c2p = indef;
5660*44704f69SBart Van Assche sgj_pr_hr(jsp, " %s: <%s>\n", cp, c2p);
5661*44704f69SBart Van Assche break;
5662*44704f69SBart Van Assche default:
5663*44704f69SBart Van Assche snprintf(b, sizeof(b), "%d minutes [%d:%d]", j, (j / 60),
5664*44704f69SBart Van Assche (j % 60));
5665*44704f69SBart Van Assche c2p = b;
5666*44704f69SBart Van Assche sgj_pr_hr(jsp, " %s: %s\n", cp, c2p);
5667*44704f69SBart Van Assche break;
5668*44704f69SBart Van Assche }
5669*44704f69SBart Van Assche break;
5670*44704f69SBart Van Assche default:
5671*44704f69SBart Van Assche sgj_pr_hr(jsp, " Unknown %s = 0x%x\n", param_c, pc);
5672*44704f69SBart Van Assche hex2stdout(bp, pl, op->dstrhex_no_ascii);
5673*44704f69SBart Van Assche break;
5674*44704f69SBart Van Assche }
5675*44704f69SBart Van Assche if (jsp->pr_as_json) {
5676*44704f69SBart Van Assche sgj_js_nv_ihexstr(jsp, jo3p, param_c_sn, pc, NULL,
5677*44704f69SBart Van Assche cp ? cp : unknown_s);
5678*44704f69SBart Van Assche if (cp)
5679*44704f69SBart Van Assche js_snakenv_ihexstr_nex(jsp, jo3p, cp , j, true,
5680*44704f69SBart Van Assche NULL, c2p, NULL);
5681*44704f69SBart Van Assche else if (pl > 4)
5682*44704f69SBart Van Assche sgj_js_nv_hex_bytes(jsp, jo3p, in_hex, bp + 4, pl - 4);
5683*44704f69SBart Van Assche
5684*44704f69SBart Van Assche sgj_js_nv_o(jsp, jap, NULL /* name */, jo3p);
5685*44704f69SBart Van Assche }
5686*44704f69SBart Van Assche if ((op->do_pcb) && (! op->do_name))
5687*44704f69SBart Van Assche sgj_pr_hr(jsp, " <%s>\n", get_pcb_str(bp[2], str,
5688*44704f69SBart Van Assche sizeof(str)));
5689*44704f69SBart Van Assche filter_chk:
5690*44704f69SBart Van Assche if (op->filter_given)
5691*44704f69SBart Van Assche break;
5692*44704f69SBart Van Assche skip:
5693*44704f69SBart Van Assche num -= pl;
5694*44704f69SBart Van Assche bp += pl;
5695*44704f69SBart Van Assche }
5696*44704f69SBart Van Assche return true;
5697*44704f69SBart Van Assche }
5698*44704f69SBart Van Assche
5699*44704f69SBart Van Assche /* LB_PROV_LPAGE [0xc] <lbp> introduced: SBC-3 */
5700*44704f69SBart Van Assche static bool
show_lb_provisioning_page(const uint8_t * resp,int len,struct opts_t * op,sgj_opaque_p jop)5701*44704f69SBart Van Assche show_lb_provisioning_page(const uint8_t * resp, int len,
5702*44704f69SBart Van Assche struct opts_t * op, sgj_opaque_p jop)
5703*44704f69SBart Van Assche {
5704*44704f69SBart Van Assche bool evsm_output = false;
5705*44704f69SBart Van Assche int num, pl, pc;
5706*44704f69SBart Van Assche const uint8_t * bp;
5707*44704f69SBart Van Assche const char * cp;
5708*44704f69SBart Van Assche char str[PCB_STR_LEN];
5709*44704f69SBart Van Assche
5710*44704f69SBart Van Assche if (jop) { };
5711*44704f69SBart Van Assche if (op->verbose || ((! op->do_raw) && (0 == op->do_hex)))
5712*44704f69SBart Van Assche printf("Logical block provisioning page [0xc]\n");
5713*44704f69SBart Van Assche num = len - 4;
5714*44704f69SBart Van Assche bp = &resp[0] + 4;
5715*44704f69SBart Van Assche while (num > 3) {
5716*44704f69SBart Van Assche pc = sg_get_unaligned_be16(bp + 0);
5717*44704f69SBart Van Assche pl = bp[3] + 4;
5718*44704f69SBart Van Assche if (op->filter_given) {
5719*44704f69SBart Van Assche if (pc != op->filter)
5720*44704f69SBart Van Assche goto skip;
5721*44704f69SBart Van Assche }
5722*44704f69SBart Van Assche if (op->do_raw) {
5723*44704f69SBart Van Assche dStrRaw(bp, pl);
5724*44704f69SBart Van Assche goto filter_chk;
5725*44704f69SBart Van Assche } else if (op->do_hex) {
5726*44704f69SBart Van Assche hex2stdout(bp, pl, op->dstrhex_no_ascii);
5727*44704f69SBart Van Assche goto filter_chk;
5728*44704f69SBart Van Assche }
5729*44704f69SBart Van Assche switch (pc) {
5730*44704f69SBart Van Assche case 0x1:
5731*44704f69SBart Van Assche cp = " Available LBA mapping threshold";
5732*44704f69SBart Van Assche break;
5733*44704f69SBart Van Assche case 0x2:
5734*44704f69SBart Van Assche cp = " Used LBA mapping threshold";
5735*44704f69SBart Van Assche break;
5736*44704f69SBart Van Assche case 0x3:
5737*44704f69SBart Van Assche cp = " Available provisioning resource percentage";
5738*44704f69SBart Van Assche break;
5739*44704f69SBart Van Assche case 0x100:
5740*44704f69SBart Van Assche cp = " De-duplicated LBA";
5741*44704f69SBart Van Assche break;
5742*44704f69SBart Van Assche case 0x101:
5743*44704f69SBart Van Assche cp = " Compressed LBA";
5744*44704f69SBart Van Assche break;
5745*44704f69SBart Van Assche case 0x102:
5746*44704f69SBart Van Assche cp = " Total efficiency LBA";
5747*44704f69SBart Van Assche break;
5748*44704f69SBart Van Assche default:
5749*44704f69SBart Van Assche cp = NULL;
5750*44704f69SBart Van Assche break;
5751*44704f69SBart Van Assche }
5752*44704f69SBart Van Assche if (cp) {
5753*44704f69SBart Van Assche if ((pl < 8) || (num < 8)) {
5754*44704f69SBart Van Assche if (num < 8)
5755*44704f69SBart Van Assche pr2serr("\n truncated by response length, expected at "
5756*44704f69SBart Van Assche "least 8 bytes\n");
5757*44704f69SBart Van Assche else
5758*44704f69SBart Van Assche pr2serr("\n parameter length >= 8 expected, got %d\n",
5759*44704f69SBart Van Assche pl);
5760*44704f69SBart Van Assche break;
5761*44704f69SBart Van Assche }
5762*44704f69SBart Van Assche if (0x3 == pc) /* resource percentage log parameter */
5763*44704f69SBart Van Assche printf(" %s: %u %%\n", cp, sg_get_unaligned_be16(bp + 4));
5764*44704f69SBart Van Assche else /* resource count log parameters */
5765*44704f69SBart Van Assche printf(" %s resource count: %u\n", cp,
5766*44704f69SBart Van Assche sg_get_unaligned_be32(bp + 4));
5767*44704f69SBart Van Assche if (pl > 8) {
5768*44704f69SBart Van Assche switch (bp[8] & 0x3) { /* SCOPE field */
5769*44704f69SBart Van Assche case 0: cp = not_rep; break;
5770*44704f69SBart Van Assche case 1: cp = "dedicated to lu"; break;
5771*44704f69SBart Van Assche case 2: cp = "not dedicated to lu"; break;
5772*44704f69SBart Van Assche case 3: cp = rsv_s; break;
5773*44704f69SBart Van Assche }
5774*44704f69SBart Van Assche printf(" Scope: %s\n", cp);
5775*44704f69SBart Van Assche }
5776*44704f69SBart Van Assche } else if ((pc >= 0xfff0) && (pc <= 0xffff)) {
5777*44704f69SBart Van Assche if (op->exclude_vendor) {
5778*44704f69SBart Van Assche if ((op->verbose > 0) && (0 == op->do_brief) &&
5779*44704f69SBart Van Assche (! evsm_output)) {
5780*44704f69SBart Van Assche evsm_output = true;
5781*44704f69SBart Van Assche printf(" %s parameter(s) being ignored\n", vend_spec);
5782*44704f69SBart Van Assche }
5783*44704f69SBart Van Assche } else {
5784*44704f69SBart Van Assche printf(" %s [0x%x]:", vend_spec, pc);
5785*44704f69SBart Van Assche hex2stdout(bp, ((pl < num) ? pl : num), op->dstrhex_no_ascii);
5786*44704f69SBart Van Assche }
5787*44704f69SBart Van Assche } else {
5788*44704f69SBart Van Assche printf(" Reserved [%s=0x%x]:\n", param_c_sn, pc);
5789*44704f69SBart Van Assche hex2stdout(bp, ((pl < num) ? pl : num), op->dstrhex_no_ascii);
5790*44704f69SBart Van Assche }
5791*44704f69SBart Van Assche if (op->do_pcb)
5792*44704f69SBart Van Assche printf(" <%s>\n", get_pcb_str(bp[2], str, sizeof(str)));
5793*44704f69SBart Van Assche filter_chk:
5794*44704f69SBart Van Assche if (op->filter_given)
5795*44704f69SBart Van Assche break;
5796*44704f69SBart Van Assche skip:
5797*44704f69SBart Van Assche num -= pl;
5798*44704f69SBart Van Assche bp += pl;
5799*44704f69SBart Van Assche }
5800*44704f69SBart Van Assche return true;
5801*44704f69SBart Van Assche }
5802*44704f69SBart Van Assche
5803*44704f69SBart Van Assche /* UTILIZATION_SUBPG [0xe,0x1] <util> introduced: SBC-4 */
5804*44704f69SBart Van Assche static bool
show_utilization_page(const uint8_t * resp,int len,struct opts_t * op,sgj_opaque_p jop)5805*44704f69SBart Van Assche show_utilization_page(const uint8_t * resp, int len, struct opts_t * op,
5806*44704f69SBart Van Assche sgj_opaque_p jop)
5807*44704f69SBart Van Assche {
5808*44704f69SBart Van Assche int num, pl, pc, k;
5809*44704f69SBart Van Assche const uint8_t * bp;
5810*44704f69SBart Van Assche char str[PCB_STR_LEN];
5811*44704f69SBart Van Assche
5812*44704f69SBart Van Assche if (jop) { };
5813*44704f69SBart Van Assche if (op->verbose || ((! op->do_raw) && (0 == op->do_hex)))
5814*44704f69SBart Van Assche printf("Utilization page [0xe,0x1]\n");
5815*44704f69SBart Van Assche num = len - 4;
5816*44704f69SBart Van Assche bp = &resp[0] + 4;
5817*44704f69SBart Van Assche while (num > 3) {
5818*44704f69SBart Van Assche pc = sg_get_unaligned_be16(bp + 0);
5819*44704f69SBart Van Assche pl = bp[3] + 4;
5820*44704f69SBart Van Assche if (op->filter_given) {
5821*44704f69SBart Van Assche if (pc != op->filter)
5822*44704f69SBart Van Assche goto skip;
5823*44704f69SBart Van Assche }
5824*44704f69SBart Van Assche if (op->do_raw) {
5825*44704f69SBart Van Assche dStrRaw(bp, pl);
5826*44704f69SBart Van Assche goto filter_chk;
5827*44704f69SBart Van Assche } else if (op->do_hex) {
5828*44704f69SBart Van Assche hex2stdout(bp, pl, op->dstrhex_no_ascii);
5829*44704f69SBart Van Assche goto filter_chk;
5830*44704f69SBart Van Assche }
5831*44704f69SBart Van Assche switch (pc) {
5832*44704f69SBart Van Assche case 0x0:
5833*44704f69SBart Van Assche printf(" Workload utilization:");
5834*44704f69SBart Van Assche if ((pl < 6) || (num < 6)) {
5835*44704f69SBart Van Assche if (num < 6)
5836*44704f69SBart Van Assche pr2serr("\n truncated by response length, expected "
5837*44704f69SBart Van Assche "at least 6 bytes\n");
5838*44704f69SBart Van Assche else
5839*44704f69SBart Van Assche pr2serr("\n parameter length >= 6 expected, got %d\n",
5840*44704f69SBart Van Assche pl);
5841*44704f69SBart Van Assche break;
5842*44704f69SBart Van Assche }
5843*44704f69SBart Van Assche k = sg_get_unaligned_be16(bp + 4);
5844*44704f69SBart Van Assche printf(" %d.%02d %%\n", k / 100, k % 100);
5845*44704f69SBart Van Assche break;
5846*44704f69SBart Van Assche case 0x1:
5847*44704f69SBart Van Assche printf(" Utilization usage rate based on date and time:");
5848*44704f69SBart Van Assche if ((pl < 6) || (num < 6)) {
5849*44704f69SBart Van Assche if (num < 6)
5850*44704f69SBart Van Assche pr2serr("\n truncated by response length, expected "
5851*44704f69SBart Van Assche "at least 6 bytes\n");
5852*44704f69SBart Van Assche else
5853*44704f69SBart Van Assche pr2serr("\n parameter length >= 6 expected, got %d\n",
5854*44704f69SBart Van Assche pl);
5855*44704f69SBart Van Assche break;
5856*44704f69SBart Van Assche }
5857*44704f69SBart Van Assche printf(" %d %%\n", bp[4]);
5858*44704f69SBart Van Assche break;
5859*44704f69SBart Van Assche default:
5860*44704f69SBart Van Assche printf(" Reserved [parameter_code=0x%x]:\n", pc);
5861*44704f69SBart Van Assche hex2stdout(bp, ((pl < num) ? pl : num), op->dstrhex_no_ascii);
5862*44704f69SBart Van Assche break;
5863*44704f69SBart Van Assche }
5864*44704f69SBart Van Assche if (op->do_pcb)
5865*44704f69SBart Van Assche printf(" <%s>\n", get_pcb_str(bp[2], str, sizeof(str)));
5866*44704f69SBart Van Assche filter_chk:
5867*44704f69SBart Van Assche if (op->filter_given)
5868*44704f69SBart Van Assche break;
5869*44704f69SBart Van Assche skip:
5870*44704f69SBart Van Assche num -= pl;
5871*44704f69SBart Van Assche bp += pl;
5872*44704f69SBart Van Assche }
5873*44704f69SBart Van Assche return true;
5874*44704f69SBart Van Assche }
5875*44704f69SBart Van Assche
5876*44704f69SBart Van Assche /* SOLID_STATE_MEDIA_LPAGE [0x11] <ssm> introduced: SBC-3 */
5877*44704f69SBart Van Assche static bool
show_solid_state_media_page(const uint8_t * resp,int len,struct opts_t * op,sgj_opaque_p jop)5878*44704f69SBart Van Assche show_solid_state_media_page(const uint8_t * resp, int len,
5879*44704f69SBart Van Assche struct opts_t * op, sgj_opaque_p jop)
5880*44704f69SBart Van Assche {
5881*44704f69SBart Van Assche int num, pl, pc;
5882*44704f69SBart Van Assche const uint8_t * bp;
5883*44704f69SBart Van Assche sgj_state * jsp = &op->json_st;
5884*44704f69SBart Van Assche sgj_opaque_p jo2p;
5885*44704f69SBart Van Assche sgj_opaque_p jo3p = NULL;
5886*44704f69SBart Van Assche sgj_opaque_p jap = NULL;
5887*44704f69SBart Van Assche char str[PCB_STR_LEN];
5888*44704f69SBart Van Assche static const char * ssmlp = "Solid state media log page";
5889*44704f69SBart Van Assche static const char * puei = "Percentage used endurance indicator";
5890*44704f69SBart Van Assche
5891*44704f69SBart Van Assche if (op->verbose || ((! op->do_raw) && (0 == op->do_hex)))
5892*44704f69SBart Van Assche sgj_pr_hr(jsp, "%s [0x11]\n", ssmlp);
5893*44704f69SBart Van Assche if (jsp->pr_as_json) {
5894*44704f69SBart Van Assche jo2p = sg_log_js_hdr(jsp, jop, ssmlp, resp);
5895*44704f69SBart Van Assche jap = sgj_named_subarray_r(jsp, jo2p,
5896*44704f69SBart Van Assche "solid_state_media_log_parameters");
5897*44704f69SBart Van Assche }
5898*44704f69SBart Van Assche num = len - 4;
5899*44704f69SBart Van Assche bp = &resp[0] + 4;
5900*44704f69SBart Van Assche while (num > 3) {
5901*44704f69SBart Van Assche pc = sg_get_unaligned_be16(bp + 0);
5902*44704f69SBart Van Assche pl = bp[3] + 4;
5903*44704f69SBart Van Assche if (op->filter_given) {
5904*44704f69SBart Van Assche if (pc != op->filter)
5905*44704f69SBart Van Assche goto skip;
5906*44704f69SBart Van Assche }
5907*44704f69SBart Van Assche if (op->do_raw) {
5908*44704f69SBart Van Assche dStrRaw(bp, pl);
5909*44704f69SBart Van Assche goto filter_chk;
5910*44704f69SBart Van Assche } else if (op->do_hex) {
5911*44704f69SBart Van Assche hex2stdout(bp, pl, op->dstrhex_no_ascii);
5912*44704f69SBart Van Assche goto filter_chk;
5913*44704f69SBart Van Assche }
5914*44704f69SBart Van Assche if (jsp->pr_as_json) {
5915*44704f69SBart Van Assche jo3p = sgj_new_unattached_object_r(jsp);
5916*44704f69SBart Van Assche if (op->do_pcb)
5917*44704f69SBart Van Assche js_pcb(jsp, jo3p, bp[2]);
5918*44704f69SBart Van Assche }
5919*44704f69SBart Van Assche
5920*44704f69SBart Van Assche switch (pc) {
5921*44704f69SBart Van Assche case 0x1:
5922*44704f69SBart Van Assche if ((pl < 8) || (num < 8)) {
5923*44704f69SBart Van Assche if (num < 8)
5924*44704f69SBart Van Assche pr2serr("\n truncated by response length, expected "
5925*44704f69SBart Van Assche "at least 8 bytes\n");
5926*44704f69SBart Van Assche else
5927*44704f69SBart Van Assche pr2serr("\n parameter length >= 8 expected, got %d\n",
5928*44704f69SBart Van Assche pl);
5929*44704f69SBart Van Assche break;
5930*44704f69SBart Van Assche }
5931*44704f69SBart Van Assche sgj_pr_hr(jsp, " %s: %u %%\n", puei, bp[7]);
5932*44704f69SBart Van Assche if (jsp->pr_as_json) {
5933*44704f69SBart Van Assche js_snakenv_ihexstr_nex(jsp, jo3p, param_c, pc, true,
5934*44704f69SBart Van Assche NULL, puei, NULL);
5935*44704f69SBart Van Assche js_snakenv_ihexstr_nex(jsp, jo3p, puei, bp[7], false,
5936*44704f69SBart Van Assche NULL, NULL, NULL);
5937*44704f69SBart Van Assche }
5938*44704f69SBart Van Assche break;
5939*44704f69SBart Van Assche default:
5940*44704f69SBart Van Assche printf(" Reserved [parameter_code=0x%x]:\n", pc);
5941*44704f69SBart Van Assche hex2stdout(bp, ((pl < num) ? pl : num), op->dstrhex_no_ascii);
5942*44704f69SBart Van Assche break;
5943*44704f69SBart Van Assche }
5944*44704f69SBart Van Assche if (jsp->pr_as_json)
5945*44704f69SBart Van Assche sgj_js_nv_o(jsp, jap, NULL /* name */, jo3p);
5946*44704f69SBart Van Assche if (op->do_pcb)
5947*44704f69SBart Van Assche sgj_pr_hr(jsp, " <%s>\n", get_pcb_str(bp[2], str,
5948*44704f69SBart Van Assche sizeof(str)));
5949*44704f69SBart Van Assche filter_chk:
5950*44704f69SBart Van Assche if (op->filter_given)
5951*44704f69SBart Van Assche break;
5952*44704f69SBart Van Assche skip:
5953*44704f69SBart Van Assche num -= pl;
5954*44704f69SBart Van Assche bp += pl;
5955*44704f69SBart Van Assche }
5956*44704f69SBart Van Assche return true;
5957*44704f69SBart Van Assche }
5958*44704f69SBart Van Assche
5959*44704f69SBart Van Assche static const char * dt_dev_activity[] = {
5960*44704f69SBart Van Assche "No DT device activity",
5961*44704f69SBart Van Assche "Cleaning operation in progress",
5962*44704f69SBart Van Assche "Volume is being loaded",
5963*44704f69SBart Van Assche "Volume is being unloaded",
5964*44704f69SBart Van Assche "Other medium activity",
5965*44704f69SBart Van Assche "Reading from medium",
5966*44704f69SBart Van Assche "Writing to medium",
5967*44704f69SBart Van Assche "Locating medium",
5968*44704f69SBart Van Assche "Rewinding medium", /* 8 */
5969*44704f69SBart Van Assche "Erasing volume",
5970*44704f69SBart Van Assche "Formatting volume",
5971*44704f69SBart Van Assche "Calibrating",
5972*44704f69SBart Van Assche "Other DT device activity",
5973*44704f69SBart Van Assche "Microcode update in progress",
5974*44704f69SBart Van Assche "Reading encrypted from medium",
5975*44704f69SBart Van Assche "Writing encrypted to medium",
5976*44704f69SBart Van Assche "Diagnostic operation in progress", /* 10 */
5977*44704f69SBart Van Assche };
5978*44704f69SBart Van Assche
5979*44704f69SBart Van Assche /* DT device status [0x11] <dtds> (ssc, adc) */
5980*44704f69SBart Van Assche static bool
show_dt_device_status_page(const uint8_t * resp,int len,struct opts_t * op,sgj_opaque_p jop)5981*44704f69SBart Van Assche show_dt_device_status_page(const uint8_t * resp, int len,
5982*44704f69SBart Van Assche struct opts_t * op, sgj_opaque_p jop)
5983*44704f69SBart Van Assche {
5984*44704f69SBart Van Assche bool evsm_output = false;
5985*44704f69SBart Van Assche int num, pl, pc, j;
5986*44704f69SBart Van Assche const uint8_t * bp;
5987*44704f69SBart Van Assche char str[PCB_STR_LEN];
5988*44704f69SBart Van Assche char b[512];
5989*44704f69SBart Van Assche
5990*44704f69SBart Van Assche if (jop) { };
5991*44704f69SBart Van Assche if (op->verbose || ((! op->do_raw) && (0 == op->do_hex)))
5992*44704f69SBart Van Assche printf("DT device status page (ssc-3, adc-3) [0x11]\n");
5993*44704f69SBart Van Assche num = len - 4;
5994*44704f69SBart Van Assche bp = &resp[0] + 4;
5995*44704f69SBart Van Assche while (num > 3) {
5996*44704f69SBart Van Assche pc = sg_get_unaligned_be16(bp + 0);
5997*44704f69SBart Van Assche pl = bp[3] + 4;
5998*44704f69SBart Van Assche if (op->filter_given) {
5999*44704f69SBart Van Assche if (pc != op->filter)
6000*44704f69SBart Van Assche goto skip;
6001*44704f69SBart Van Assche }
6002*44704f69SBart Van Assche if (op->do_raw) {
6003*44704f69SBart Van Assche dStrRaw(bp, pl);
6004*44704f69SBart Van Assche goto filter_chk;
6005*44704f69SBart Van Assche } else if (op->do_hex) {
6006*44704f69SBart Van Assche hex2stdout(bp, pl, op->dstrhex_no_ascii);
6007*44704f69SBart Van Assche goto filter_chk;
6008*44704f69SBart Van Assche }
6009*44704f69SBart Van Assche switch (pc) {
6010*44704f69SBart Van Assche case 0x0:
6011*44704f69SBart Van Assche printf(" Very high frequency data:\n");
6012*44704f69SBart Van Assche if ((pl < 8) || (num < 8)) {
6013*44704f69SBart Van Assche if (num < 8)
6014*44704f69SBart Van Assche pr2serr(" truncated by response length, expected at "
6015*44704f69SBart Van Assche "least 8 bytes\n");
6016*44704f69SBart Van Assche else
6017*44704f69SBart Van Assche pr2serr(" parameter length >= 8 expected, got %d\n",
6018*44704f69SBart Van Assche pl);
6019*44704f69SBart Van Assche break;
6020*44704f69SBart Van Assche }
6021*44704f69SBart Van Assche printf(" PAMR=%d HUI=%d MACC=%d CMPR=%d ", !!(0x80 & bp[4]),
6022*44704f69SBart Van Assche !!(0x40 & bp[4]), !!(0x20 & bp[4]), !!(0x10 & bp[4]));
6023*44704f69SBart Van Assche printf("WRTP=%d CRQST=%d CRQRD=%d DINIT=%d\n", !!(0x8 & bp[4]),
6024*44704f69SBart Van Assche !!(0x4 & bp[4]), !!(0x2 & bp[4]), !!(0x1 & bp[4]));
6025*44704f69SBart Van Assche printf(" INXTN=%d RAA=%d MPRSNT=%d ", !!(0x80 & bp[5]),
6026*44704f69SBart Van Assche !!(0x20 & bp[5]), !!(0x10 & bp[5]));
6027*44704f69SBart Van Assche printf("MSTD=%d MTHRD=%d MOUNTED=%d\n",
6028*44704f69SBart Van Assche !!(0x4 & bp[5]), !!(0x2 & bp[5]), !!(0x1 & bp[5]));
6029*44704f69SBart Van Assche printf(" DT device activity: ");
6030*44704f69SBart Van Assche j = bp[6];
6031*44704f69SBart Van Assche if (j < (int)SG_ARRAY_SIZE(dt_dev_activity))
6032*44704f69SBart Van Assche printf("%s\n", dt_dev_activity[j]);
6033*44704f69SBart Van Assche else if (j < 0x80)
6034*44704f69SBart Van Assche printf("Reserved [0x%x]\n", j);
6035*44704f69SBart Van Assche else
6036*44704f69SBart Van Assche printf("%s [0x%x]\n", vend_spec, j);
6037*44704f69SBart Van Assche printf(" VS=%d TDDEC=%d EPP=%d ", !!(0x80 & bp[7]),
6038*44704f69SBart Van Assche !!(0x20 & bp[7]), !!(0x10 & bp[7]));
6039*44704f69SBart Van Assche printf("ESR=%d RRQST=%d INTFC=%d TAFC=%d\n", !!(0x8 & bp[7]),
6040*44704f69SBart Van Assche !!(0x4 & bp[7]), !!(0x2 & bp[7]), !!(0x1 & bp[7]));
6041*44704f69SBart Van Assche break;
6042*44704f69SBart Van Assche case 0x1:
6043*44704f69SBart Van Assche printf(" Very high frequency polling delay: ");
6044*44704f69SBart Van Assche if ((pl < 6) || (num < 6)) {
6045*44704f69SBart Van Assche if (num < 6)
6046*44704f69SBart Van Assche pr2serr("\n truncated by response length, expected at "
6047*44704f69SBart Van Assche "least 6 bytes\n");
6048*44704f69SBart Van Assche else
6049*44704f69SBart Van Assche pr2serr("\n parameter length >= 6 expected, got %d\n",
6050*44704f69SBart Van Assche pl);
6051*44704f69SBart Van Assche break;
6052*44704f69SBart Van Assche }
6053*44704f69SBart Van Assche printf(" %d milliseconds\n", sg_get_unaligned_be16(bp + 4));
6054*44704f69SBart Van Assche break;
6055*44704f69SBart Van Assche case 0x2:
6056*44704f69SBart Van Assche printf(" DT device ADC data encryption control status (hex "
6057*44704f69SBart Van Assche "only now):\n");
6058*44704f69SBart Van Assche if ((pl < 12) || (num < 12)) {
6059*44704f69SBart Van Assche if (num < 12)
6060*44704f69SBart Van Assche pr2serr(" truncated by response length, expected at "
6061*44704f69SBart Van Assche "least 12 bytes\n");
6062*44704f69SBart Van Assche else
6063*44704f69SBart Van Assche pr2serr(" parameter length >= 12 expected, got %d\n",
6064*44704f69SBart Van Assche pl);
6065*44704f69SBart Van Assche break;
6066*44704f69SBart Van Assche }
6067*44704f69SBart Van Assche hex2fp(bp + 4, 8, " ", op->hex2str_oformat, stdout);
6068*44704f69SBart Van Assche break;
6069*44704f69SBart Van Assche case 0x3:
6070*44704f69SBart Van Assche printf(" Key management error data (hex only now):\n");
6071*44704f69SBart Van Assche if ((pl < 16) || (num < 16)) {
6072*44704f69SBart Van Assche if (num < 16)
6073*44704f69SBart Van Assche pr2serr(" truncated by response length, expected at "
6074*44704f69SBart Van Assche "least 16 bytes\n");
6075*44704f69SBart Van Assche else
6076*44704f69SBart Van Assche pr2serr(" parameter length >= 16 expected, got %d\n",
6077*44704f69SBart Van Assche pl);
6078*44704f69SBart Van Assche break;
6079*44704f69SBart Van Assche }
6080*44704f69SBart Van Assche hex2fp(bp + 4, 12, " ", op->hex2str_oformat, stdout);
6081*44704f69SBart Van Assche break;
6082*44704f69SBart Van Assche default:
6083*44704f69SBart Van Assche if ((pc >= 0x101) && (pc <= 0x1ff)) {
6084*44704f69SBart Van Assche printf(" Primary port %d status:\n", pc - 0x100);
6085*44704f69SBart Van Assche if (12 == bp[3]) { /* if length of desc is 12, assume SAS */
6086*44704f69SBart Van Assche printf(" SAS: negotiated physical link rate: %s\n",
6087*44704f69SBart Van Assche sas_negot_link_rate((0xf & (bp[4] >> 4)), b,
6088*44704f69SBart Van Assche sizeof(b)));
6089*44704f69SBart Van Assche printf(" signal=%d, pic=%d, ", !!(0x2 & bp[4]),
6090*44704f69SBart Van Assche !!(0x1 & bp[4]));
6091*44704f69SBart Van Assche printf("hashed SAS addr: 0x%u\n",
6092*44704f69SBart Van Assche sg_get_unaligned_be24(bp + 5));
6093*44704f69SBart Van Assche printf(" SAS addr: 0x%" PRIx64 "\n",
6094*44704f69SBart Van Assche sg_get_unaligned_be64(bp + 8));
6095*44704f69SBart Van Assche } else {
6096*44704f69SBart Van Assche printf(" non-SAS transport, in hex:\n");
6097*44704f69SBart Van Assche hex2fp(bp + 4, ((pl < num) ? pl : num) - 4, " ",
6098*44704f69SBart Van Assche op->hex2str_oformat, stdout);
6099*44704f69SBart Van Assche }
6100*44704f69SBart Van Assche } else if (pc >= 0x8000) {
6101*44704f69SBart Van Assche if (op->exclude_vendor) {
6102*44704f69SBart Van Assche if ((op->verbose > 0) && (0 == op->do_brief) &&
6103*44704f69SBart Van Assche (! evsm_output)) {
6104*44704f69SBart Van Assche evsm_output = true;
6105*44704f69SBart Van Assche printf(" %s parameter(s) being ignored\n",
6106*44704f69SBart Van Assche vend_spec);
6107*44704f69SBart Van Assche }
6108*44704f69SBart Van Assche } else {
6109*44704f69SBart Van Assche printf(" %s [%s=0x%x]:\n", vend_spec, param_c_sn, pc);
6110*44704f69SBart Van Assche hex2fp(bp, ((pl < num) ? pl : num), " ",
6111*44704f69SBart Van Assche op->hex2str_oformat, stdout);
6112*44704f69SBart Van Assche }
6113*44704f69SBart Van Assche } else {
6114*44704f69SBart Van Assche printf(" Reserved [%s=0x%x]:\n", param_c_sn, pc);
6115*44704f69SBart Van Assche hex2fp(bp, ((pl < num) ? pl : num), " ",
6116*44704f69SBart Van Assche op->hex2str_oformat, stdout);
6117*44704f69SBart Van Assche }
6118*44704f69SBart Van Assche break;
6119*44704f69SBart Van Assche }
6120*44704f69SBart Van Assche if (op->do_pcb)
6121*44704f69SBart Van Assche printf(" <%s>\n", get_pcb_str(bp[2], str, sizeof(str)));
6122*44704f69SBart Van Assche filter_chk:
6123*44704f69SBart Van Assche if (op->filter_given)
6124*44704f69SBart Van Assche break;
6125*44704f69SBart Van Assche skip:
6126*44704f69SBart Van Assche num -= pl;
6127*44704f69SBart Van Assche bp += pl;
6128*44704f69SBart Van Assche }
6129*44704f69SBart Van Assche return true;
6130*44704f69SBart Van Assche }
6131*44704f69SBart Van Assche
6132*44704f69SBart Van Assche /* TapeAlert response [0x12] <tar> (adc,ssc) */
6133*44704f69SBart Van Assche static bool
show_tapealert_response_page(const uint8_t * resp,int len,struct opts_t * op,sgj_opaque_p jop)6134*44704f69SBart Van Assche show_tapealert_response_page(const uint8_t * resp, int len,
6135*44704f69SBart Van Assche struct opts_t * op, sgj_opaque_p jop)
6136*44704f69SBart Van Assche {
6137*44704f69SBart Van Assche bool evsm_output = false;
6138*44704f69SBart Van Assche int num, pl, pc, k, mod, div;
6139*44704f69SBart Van Assche const uint8_t * bp;
6140*44704f69SBart Van Assche char str[PCB_STR_LEN];
6141*44704f69SBart Van Assche
6142*44704f69SBart Van Assche if (jop) { };
6143*44704f69SBart Van Assche if (op->verbose || ((! op->do_raw) && (0 == op->do_hex)))
6144*44704f69SBart Van Assche printf("TapeAlert response page (ssc-3, adc-3) [0x12]\n");
6145*44704f69SBart Van Assche num = len - 4;
6146*44704f69SBart Van Assche bp = &resp[0] + 4;
6147*44704f69SBart Van Assche while (num > 3) {
6148*44704f69SBart Van Assche pc = sg_get_unaligned_be16(bp + 0);
6149*44704f69SBart Van Assche pl = bp[3] + 4;
6150*44704f69SBart Van Assche if (op->filter_given) {
6151*44704f69SBart Van Assche if (pc != op->filter)
6152*44704f69SBart Van Assche goto skip;
6153*44704f69SBart Van Assche }
6154*44704f69SBart Van Assche if (op->do_raw) {
6155*44704f69SBart Van Assche dStrRaw(bp, pl);
6156*44704f69SBart Van Assche goto filter_chk;
6157*44704f69SBart Van Assche } else if (op->do_hex) {
6158*44704f69SBart Van Assche hex2stdout(bp, pl, op->dstrhex_no_ascii);
6159*44704f69SBart Van Assche goto filter_chk;
6160*44704f69SBart Van Assche }
6161*44704f69SBart Van Assche switch (pc) {
6162*44704f69SBart Van Assche case 0x0:
6163*44704f69SBart Van Assche if (pl < 12) {
6164*44704f69SBart Van Assche
6165*44704f69SBart Van Assche }
6166*44704f69SBart Van Assche for (k = 1; k < 0x41; ++k) {
6167*44704f69SBart Van Assche mod = ((k - 1) % 8);
6168*44704f69SBart Van Assche div = (k - 1) / 8;
6169*44704f69SBart Van Assche if (0 == mod) {
6170*44704f69SBart Van Assche if (div > 0)
6171*44704f69SBart Van Assche printf("\n");
6172*44704f69SBart Van Assche printf(" Flag%02Xh: %d", k, !! (bp[4 + div] & 0x80));
6173*44704f69SBart Van Assche } else
6174*44704f69SBart Van Assche printf(" %02Xh: %d", k,
6175*44704f69SBart Van Assche !! (bp[4 + div] & (1 << (7 - mod))));
6176*44704f69SBart Van Assche }
6177*44704f69SBart Van Assche printf("\n");
6178*44704f69SBart Van Assche break;
6179*44704f69SBart Van Assche default:
6180*44704f69SBart Van Assche if (pc <= 0x8000) {
6181*44704f69SBart Van Assche printf(" Reserved [parameter_code=0x%x]:\n", pc);
6182*44704f69SBart Van Assche hex2fp(bp, ((pl < num) ? pl : num), " ",
6183*44704f69SBart Van Assche op->hex2str_oformat, stdout);
6184*44704f69SBart Van Assche } else {
6185*44704f69SBart Van Assche if (op->exclude_vendor) {
6186*44704f69SBart Van Assche if ((op->verbose > 0) && (0 == op->do_brief) &&
6187*44704f69SBart Van Assche (! evsm_output)) {
6188*44704f69SBart Van Assche evsm_output = true;
6189*44704f69SBart Van Assche printf(" %s parameter(s) being ignored\n",
6190*44704f69SBart Van Assche vend_spec);
6191*44704f69SBart Van Assche }
6192*44704f69SBart Van Assche } else {
6193*44704f69SBart Van Assche printf(" %s [%s=0x%x]:\n", vend_spec, param_c_sn, pc);
6194*44704f69SBart Van Assche hex2fp(bp, ((pl < num) ? pl : num), " ",
6195*44704f69SBart Van Assche op->hex2str_oformat, stdout);
6196*44704f69SBart Van Assche }
6197*44704f69SBart Van Assche }
6198*44704f69SBart Van Assche break;
6199*44704f69SBart Van Assche }
6200*44704f69SBart Van Assche if (op->do_pcb)
6201*44704f69SBart Van Assche printf(" <%s>\n", get_pcb_str(bp[2], str, sizeof(str)));
6202*44704f69SBart Van Assche filter_chk:
6203*44704f69SBart Van Assche if (op->filter_given)
6204*44704f69SBart Van Assche break;
6205*44704f69SBart Van Assche skip:
6206*44704f69SBart Van Assche num -= pl;
6207*44704f69SBart Van Assche bp += pl;
6208*44704f69SBart Van Assche }
6209*44704f69SBart Van Assche return true;
6210*44704f69SBart Van Assche }
6211*44704f69SBart Van Assche
6212*44704f69SBart Van Assche #define NUM_REQ_REC_ARR_ELEMS 16
6213*44704f69SBart Van Assche static const char * req_rec_arr[NUM_REQ_REC_ARR_ELEMS] = {
6214*44704f69SBart Van Assche "Recovery not requested",
6215*44704f69SBart Van Assche "Recovery requested, no recovery procedure defined",
6216*44704f69SBart Van Assche "Instruct operator to push volume",
6217*44704f69SBart Van Assche "Instruct operator to remove and re-insert volume",
6218*44704f69SBart Van Assche "Issue UNLOAD command. Instruct operator to remove and re-insert volume",
6219*44704f69SBart Van Assche "Instruct operator to power cycle target device",
6220*44704f69SBart Van Assche "Issue LOAD command",
6221*44704f69SBart Van Assche "Issue UNLOAD command",
6222*44704f69SBart Van Assche "Issue LOGICAL UNIT RESET task management function", /* 0x8 */
6223*44704f69SBart Van Assche "No recovery procedure defined. Contact service organization",
6224*44704f69SBart Van Assche "Issue UNLOAD command. Instruct operator to remove and quarantine "
6225*44704f69SBart Van Assche "volume",
6226*44704f69SBart Van Assche "Instruct operator to not insert a volume. Contact service organization",
6227*44704f69SBart Van Assche "Issue UNLOAD command. Instruct operator to remove volume. Contact "
6228*44704f69SBart Van Assche "service organization",
6229*44704f69SBart Van Assche "Request creation of target device error log",
6230*44704f69SBart Van Assche "Retrieve a target device error log",
6231*44704f69SBart Van Assche "Modify configuration to all microcode update and instruct operator to "
6232*44704f69SBart Van Assche "re-insert volume", /* 0xf */
6233*44704f69SBart Van Assche };
6234*44704f69SBart Van Assche
6235*44704f69SBart Van Assche /* REQ_RECOVERY_LPAGE Requested recovery [0x13] <rr> (ssc) */
6236*44704f69SBart Van Assche static bool
show_requested_recovery_page(const uint8_t * resp,int len,struct opts_t * op,sgj_opaque_p jop)6237*44704f69SBart Van Assche show_requested_recovery_page(const uint8_t * resp, int len,
6238*44704f69SBart Van Assche struct opts_t * op, sgj_opaque_p jop)
6239*44704f69SBart Van Assche {
6240*44704f69SBart Van Assche bool evsm_output = false;
6241*44704f69SBart Van Assche int num, pl, pc, j, k;
6242*44704f69SBart Van Assche const uint8_t * bp;
6243*44704f69SBart Van Assche char str[PCB_STR_LEN];
6244*44704f69SBart Van Assche
6245*44704f69SBart Van Assche if (jop) { };
6246*44704f69SBart Van Assche if (op->verbose || ((! op->do_raw) && (0 == op->do_hex)))
6247*44704f69SBart Van Assche printf("Requested recovery page (ssc-3) [0x13]\n");
6248*44704f69SBart Van Assche num = len - 4;
6249*44704f69SBart Van Assche bp = &resp[0] + 4;
6250*44704f69SBart Van Assche while (num > 3) {
6251*44704f69SBart Van Assche pc = sg_get_unaligned_be16(bp + 0);
6252*44704f69SBart Van Assche pl = bp[3] + 4;
6253*44704f69SBart Van Assche if (op->filter_given) {
6254*44704f69SBart Van Assche if (pc != op->filter)
6255*44704f69SBart Van Assche goto skip;
6256*44704f69SBart Van Assche }
6257*44704f69SBart Van Assche if (op->do_raw) {
6258*44704f69SBart Van Assche dStrRaw(bp, pl);
6259*44704f69SBart Van Assche goto filter_chk;
6260*44704f69SBart Van Assche } else if (op->do_hex) {
6261*44704f69SBart Van Assche hex2stdout(bp, pl, op->dstrhex_no_ascii);
6262*44704f69SBart Van Assche goto filter_chk;
6263*44704f69SBart Van Assche }
6264*44704f69SBart Van Assche switch (pc) {
6265*44704f69SBart Van Assche case 0x0:
6266*44704f69SBart Van Assche printf(" Recovery procedures:\n");
6267*44704f69SBart Van Assche for (k = 4; k < pl; ++ k) {
6268*44704f69SBart Van Assche j = bp[k];
6269*44704f69SBart Van Assche if (j < NUM_REQ_REC_ARR_ELEMS)
6270*44704f69SBart Van Assche printf(" %s\n", req_rec_arr[j]);
6271*44704f69SBart Van Assche else if (j < 0x80)
6272*44704f69SBart Van Assche printf(" Reserved [0x%x]\n", j);
6273*44704f69SBart Van Assche else
6274*44704f69SBart Van Assche printf(" Vendor specific [0x%x]\n", j);
6275*44704f69SBart Van Assche }
6276*44704f69SBart Van Assche break;
6277*44704f69SBart Van Assche default:
6278*44704f69SBart Van Assche if (pc <= 0x8000) {
6279*44704f69SBart Van Assche printf(" Reserved [parameter_code=0x%x]:\n", pc);
6280*44704f69SBart Van Assche hex2fp(bp, ((pl < num) ? pl : num), " ",
6281*44704f69SBart Van Assche op->hex2str_oformat, stdout);
6282*44704f69SBart Van Assche } else {
6283*44704f69SBart Van Assche if (op->exclude_vendor) {
6284*44704f69SBart Van Assche if ((op->verbose > 0) && (0 == op->do_brief) &&
6285*44704f69SBart Van Assche (! evsm_output)) {
6286*44704f69SBart Van Assche evsm_output = true;
6287*44704f69SBart Van Assche printf(" Vendor specific parameter(s) being "
6288*44704f69SBart Van Assche "ignored\n");
6289*44704f69SBart Van Assche }
6290*44704f69SBart Van Assche } else {
6291*44704f69SBart Van Assche printf(" Vendor specific [parameter_code=0x%x]:\n", pc);
6292*44704f69SBart Van Assche hex2fp(bp, ((pl < num) ? pl : num), " ",
6293*44704f69SBart Van Assche op->hex2str_oformat, stdout);
6294*44704f69SBart Van Assche }
6295*44704f69SBart Van Assche }
6296*44704f69SBart Van Assche break;
6297*44704f69SBart Van Assche }
6298*44704f69SBart Van Assche if (op->do_pcb)
6299*44704f69SBart Van Assche printf(" <%s>\n", get_pcb_str(bp[2], str, sizeof(str)));
6300*44704f69SBart Van Assche filter_chk:
6301*44704f69SBart Van Assche if (op->filter_given)
6302*44704f69SBart Van Assche break;
6303*44704f69SBart Van Assche skip:
6304*44704f69SBart Van Assche num -= pl;
6305*44704f69SBart Van Assche bp += pl;
6306*44704f69SBart Van Assche }
6307*44704f69SBart Van Assche return true;
6308*44704f69SBart Van Assche }
6309*44704f69SBart Van Assche
6310*44704f69SBart Van Assche /* SAT_ATA_RESULTS_LPAGE (SAT-2) [0x16] <aptr> */
6311*44704f69SBart Van Assche static bool
show_ata_pt_results_page(const uint8_t * resp,int len,struct opts_t * op,sgj_opaque_p jop)6312*44704f69SBart Van Assche show_ata_pt_results_page(const uint8_t * resp, int len,
6313*44704f69SBart Van Assche struct opts_t * op, sgj_opaque_p jop)
6314*44704f69SBart Van Assche {
6315*44704f69SBart Van Assche int num, pl, pc;
6316*44704f69SBart Van Assche const uint8_t * bp;
6317*44704f69SBart Van Assche const uint8_t * dp;
6318*44704f69SBart Van Assche char str[PCB_STR_LEN];
6319*44704f69SBart Van Assche
6320*44704f69SBart Van Assche if (jop) { };
6321*44704f69SBart Van Assche if (op->verbose || ((! op->do_raw) && (0 == op->do_hex)))
6322*44704f69SBart Van Assche printf("ATA pass-through results page (sat-2) [0x16]\n");
6323*44704f69SBart Van Assche num = len - 4;
6324*44704f69SBart Van Assche bp = &resp[0] + 4;
6325*44704f69SBart Van Assche while (num > 3) {
6326*44704f69SBart Van Assche pc = sg_get_unaligned_be16(bp + 0);
6327*44704f69SBart Van Assche pl = bp[3] + 4;
6328*44704f69SBart Van Assche if (op->filter_given) {
6329*44704f69SBart Van Assche if (pc != op->filter)
6330*44704f69SBart Van Assche goto skip;
6331*44704f69SBart Van Assche }
6332*44704f69SBart Van Assche if (op->do_raw) {
6333*44704f69SBart Van Assche dStrRaw(bp, pl);
6334*44704f69SBart Van Assche goto filter_chk;
6335*44704f69SBart Van Assche } else if (op->do_hex) {
6336*44704f69SBart Van Assche hex2stdout(bp, pl, op->dstrhex_no_ascii);
6337*44704f69SBart Van Assche goto filter_chk;
6338*44704f69SBart Van Assche }
6339*44704f69SBart Van Assche if ((pc < 0xf) && (pl > 17)) {
6340*44704f69SBart Van Assche int extend, count;
6341*44704f69SBart Van Assche
6342*44704f69SBart Van Assche printf(" Log_index=0x%x (parameter_code=0x%x)\n", pc + 1, pc);
6343*44704f69SBart Van Assche dp = bp + 4; /* dp is start of ATA Return descriptor
6344*44704f69SBart Van Assche * which is 14 bytes long */
6345*44704f69SBart Van Assche extend = dp[2] & 1;
6346*44704f69SBart Van Assche count = dp[5] + (extend ? (dp[4] << 8) : 0);
6347*44704f69SBart Van Assche printf(" extend=%d error=0x%x count=0x%x\n", extend,
6348*44704f69SBart Van Assche dp[3], count);
6349*44704f69SBart Van Assche if (extend)
6350*44704f69SBart Van Assche printf(" lba=0x%02x%02x%02x%02x%02x%02x\n", dp[10], dp[8],
6351*44704f69SBart Van Assche dp[6], dp[11], dp[9], dp[7]);
6352*44704f69SBart Van Assche else
6353*44704f69SBart Van Assche printf(" lba=0x%02x%02x%02x\n", dp[11], dp[9], dp[7]);
6354*44704f69SBart Van Assche printf(" device=0x%x status=0x%x\n", dp[12], dp[13]);
6355*44704f69SBart Van Assche } else if (pl > 17) {
6356*44704f69SBart Van Assche printf(" Reserved [parameter_code=0x%x]:\n", pc);
6357*44704f69SBart Van Assche hex2fp(bp, ((pl < num) ? pl : num), " ",
6358*44704f69SBart Van Assche op->hex2str_oformat, stdout);
6359*44704f69SBart Van Assche } else {
6360*44704f69SBart Van Assche printf(" short parameter length: %d [parameter_code=0x%x]:\n",
6361*44704f69SBart Van Assche pl, pc);
6362*44704f69SBart Van Assche hex2fp(bp, ((pl < num) ? pl : num), " ",
6363*44704f69SBart Van Assche op->hex2str_oformat, stdout);
6364*44704f69SBart Van Assche }
6365*44704f69SBart Van Assche if (op->do_pcb)
6366*44704f69SBart Van Assche printf(" <%s>\n", get_pcb_str(bp[2], str, sizeof(str)));
6367*44704f69SBart Van Assche filter_chk:
6368*44704f69SBart Van Assche if (op->filter_given)
6369*44704f69SBart Van Assche break;
6370*44704f69SBart Van Assche skip:
6371*44704f69SBart Van Assche num -= pl;
6372*44704f69SBart Van Assche bp += pl;
6373*44704f69SBart Van Assche }
6374*44704f69SBart Van Assche return true;
6375*44704f69SBart Van Assche }
6376*44704f69SBart Van Assche
6377*44704f69SBart Van Assche static const char * bms_status[] = {
6378*44704f69SBart Van Assche "no background scans active",
6379*44704f69SBart Van Assche "background medium scan is active",
6380*44704f69SBart Van Assche "background pre-scan is active",
6381*44704f69SBart Van Assche "background scan halted due to fatal error",
6382*44704f69SBart Van Assche "background scan halted due to a vendor specific pattern of error",
6383*44704f69SBart Van Assche "background scan halted due to medium formatted without P-List",
6384*44704f69SBart Van Assche "background scan halted - vendor specific cause",
6385*44704f69SBart Van Assche "background scan halted due to temperature out of range",
6386*44704f69SBart Van Assche ("background scan enabled, none active (waiting for BMS interval timer "
6387*44704f69SBart Van Assche "to expire)"), /* clang warns about this, add parens to quieten */
6388*44704f69SBart Van Assche "background scan halted - scan results list full",
6389*44704f69SBart Van Assche "background scan halted - pre-scan time limit timer expired" /* 10 */,
6390*44704f69SBart Van Assche };
6391*44704f69SBart Van Assche
6392*44704f69SBart Van Assche static const char * reassign_status[] = {
6393*44704f69SBart Van Assche "Reserved [0x0]",
6394*44704f69SBart Van Assche "Reassignment pending receipt of Reassign or Write command",
6395*44704f69SBart Van Assche "Logical block successfully reassigned by device server",
6396*44704f69SBart Van Assche "Reserved [0x3]",
6397*44704f69SBart Van Assche "Reassignment by device server failed",
6398*44704f69SBart Van Assche "Logical block recovered by device server via rewrite",
6399*44704f69SBart Van Assche "Logical block reassigned by application client, has valid data",
6400*44704f69SBart Van Assche "Logical block reassigned by application client, contains no valid data",
6401*44704f69SBart Van Assche "Logical block unsuccessfully reassigned by application client", /* 8 */
6402*44704f69SBart Van Assche };
6403*44704f69SBart Van Assche
6404*44704f69SBart Van Assche /* Background scan results [0x15,0] <bsr> for disk introduced: SBC-3 */
6405*44704f69SBart Van Assche static bool
show_background_scan_results_page(const uint8_t * resp,int len,struct opts_t * op,sgj_opaque_p jop)6406*44704f69SBart Van Assche show_background_scan_results_page(const uint8_t * resp, int len,
6407*44704f69SBart Van Assche struct opts_t * op, sgj_opaque_p jop)
6408*44704f69SBart Van Assche {
6409*44704f69SBart Van Assche bool skip_out = false;
6410*44704f69SBart Van Assche bool evsm_output = false;
6411*44704f69SBart Van Assche bool ok;
6412*44704f69SBart Van Assche int j, m, n, num, pl, pc;
6413*44704f69SBart Van Assche const uint8_t * bp;
6414*44704f69SBart Van Assche double d;
6415*44704f69SBart Van Assche sgj_state * jsp = &op->json_st;
6416*44704f69SBart Van Assche sgj_opaque_p jo2p;
6417*44704f69SBart Van Assche sgj_opaque_p jo3p = NULL;
6418*44704f69SBart Van Assche sgj_opaque_p jap = NULL;
6419*44704f69SBart Van Assche char str[PCB_STR_LEN];
6420*44704f69SBart Van Assche char b[144];
6421*44704f69SBart Van Assche char e[80];
6422*44704f69SBart Van Assche static const int blen = sizeof(b);
6423*44704f69SBart Van Assche static const int elen = sizeof(e);
6424*44704f69SBart Van Assche static const char * bsrlp = "Background scan results log page";
6425*44704f69SBart Van Assche static const char * bss = "Background scan status";
6426*44704f69SBart Van Assche static const char * bms = "Background medium scan";
6427*44704f69SBart Van Assche static const char * bsr = "Background scan results";
6428*44704f69SBart Van Assche static const char * bs = "background scan";
6429*44704f69SBart Van Assche static const char * ms = "Medium scan";
6430*44704f69SBart Van Assche static const char * apom = "Accumulated power on minutes";
6431*44704f69SBart Van Assche static const char * rs = "Reassign status";
6432*44704f69SBart Van Assche
6433*44704f69SBart Van Assche if (op->verbose || ((! op->do_raw) && (0 == op->do_hex)))
6434*44704f69SBart Van Assche sgj_pr_hr(jsp, "%s [0x15]\n", bsrlp);
6435*44704f69SBart Van Assche num = len - 4;
6436*44704f69SBart Van Assche bp = &resp[0] + 4;
6437*44704f69SBart Van Assche if (jsp->pr_as_json) {
6438*44704f69SBart Van Assche jo2p = sg_log_js_hdr(jsp, jop, bsrlp, resp);
6439*44704f69SBart Van Assche jap = sgj_named_subarray_r(jsp, jo2p, "background_scan_parameters");
6440*44704f69SBart Van Assche }
6441*44704f69SBart Van Assche
6442*44704f69SBart Van Assche while (num > 3) {
6443*44704f69SBart Van Assche pc = sg_get_unaligned_be16(bp + 0);
6444*44704f69SBart Van Assche pl = bp[3] + 4;
6445*44704f69SBart Van Assche if (op->filter_given) {
6446*44704f69SBart Van Assche if (pc != op->filter)
6447*44704f69SBart Van Assche goto skip;
6448*44704f69SBart Van Assche }
6449*44704f69SBart Van Assche if (op->do_raw) {
6450*44704f69SBart Van Assche dStrRaw(bp, pl);
6451*44704f69SBart Van Assche goto filter_chk;
6452*44704f69SBart Van Assche } else if (op->do_hex) {
6453*44704f69SBart Van Assche hex2stdout(bp, pl, op->dstrhex_no_ascii);
6454*44704f69SBart Van Assche goto filter_chk;
6455*44704f69SBart Van Assche }
6456*44704f69SBart Van Assche if (jsp->pr_as_json) {
6457*44704f69SBart Van Assche jo3p = sgj_new_unattached_object_r(jsp);
6458*44704f69SBart Van Assche if (op->do_pcb)
6459*44704f69SBart Van Assche js_pcb(jsp, jo3p, bp[2]);
6460*44704f69SBart Van Assche }
6461*44704f69SBart Van Assche
6462*44704f69SBart Van Assche switch (pc) {
6463*44704f69SBart Van Assche case 0:
6464*44704f69SBart Van Assche sgj_pr_hr(jsp, " Status parameters:\n");
6465*44704f69SBart Van Assche if (jsp->pr_as_json)
6466*44704f69SBart Van Assche sgj_js_nv_ihexstr(jsp, jo3p, param_c_sn, pc, NULL, bss);
6467*44704f69SBart Van Assche if ((pl < 16) || (num < 16)) {
6468*44704f69SBart Van Assche if (num < 16)
6469*44704f69SBart Van Assche pr2serr(" truncated by response length, expected at "
6470*44704f69SBart Van Assche "least 16 bytes\n");
6471*44704f69SBart Van Assche else
6472*44704f69SBart Van Assche pr2serr(" parameter length >= 16 expected, got %d\n",
6473*44704f69SBart Van Assche pl);
6474*44704f69SBart Van Assche break;
6475*44704f69SBart Van Assche }
6476*44704f69SBart Van Assche sg_scnpr(b, blen, " %s: ", apom);
6477*44704f69SBart Van Assche j = sg_get_unaligned_be32(bp + 4);
6478*44704f69SBart Van Assche sgj_pr_hr(jsp, "%s%d [h:m %d:%d]\n", b, j, (j / 60), (j % 60));
6479*44704f69SBart Van Assche if (jsp->pr_as_json)
6480*44704f69SBart Van Assche js_snakenv_ihexstr_nex(jsp, jo3p, apom, j, false, NULL, NULL,
6481*44704f69SBart Van Assche NULL);
6482*44704f69SBart Van Assche sg_scnpr(b, blen, " Status: ");
6483*44704f69SBart Van Assche j = bp[9];
6484*44704f69SBart Van Assche ok = (j < (int)SG_ARRAY_SIZE(bms_status));
6485*44704f69SBart Van Assche if (ok)
6486*44704f69SBart Van Assche sgj_pr_hr(jsp, "%s%s\n", b, bms_status[j]);
6487*44704f69SBart Van Assche else
6488*44704f69SBart Van Assche sgj_pr_hr(jsp, "%sunknown [0x%x] %s value\n", b, j, bss);
6489*44704f69SBart Van Assche if (jsp->pr_as_json)
6490*44704f69SBart Van Assche js_snakenv_ihexstr_nex(jsp, jo3p, bss, j, true, NULL,
6491*44704f69SBart Van Assche ok ? bms_status[j] : unknown_s, NULL);
6492*44704f69SBart Van Assche j = sg_get_unaligned_be16(bp + 10);
6493*44704f69SBart Van Assche snprintf(b, blen, "Number of %ss performed", bs);
6494*44704f69SBart Van Assche sgj_pr_hr(jsp, " %s: %d\n", b, j);
6495*44704f69SBart Van Assche if (jsp->pr_as_json)
6496*44704f69SBart Van Assche js_snakenv_ihexstr_nex(jsp, jo3p, b, j, true, NULL, NULL,
6497*44704f69SBart Van Assche NULL);
6498*44704f69SBart Van Assche j = sg_get_unaligned_be16(bp + 12);
6499*44704f69SBart Van Assche snprintf(b, blen, "%s progress", bms);
6500*44704f69SBart Van Assche d = (100.0 * j / 65536.0);
6501*44704f69SBart Van Assche #ifdef SG_LIB_MINGW
6502*44704f69SBart Van Assche snprintf(e, elen, "%g %%", d);
6503*44704f69SBart Van Assche #else
6504*44704f69SBart Van Assche snprintf(e, elen, "%.2f %%", d);
6505*44704f69SBart Van Assche #endif
6506*44704f69SBart Van Assche sgj_pr_hr(jsp, " %s: %s\n", b, e);
6507*44704f69SBart Van Assche if (jsp->pr_as_json)
6508*44704f69SBart Van Assche js_snakenv_ihexstr_nex(jsp, jo3p, b, j, true, NULL, e,
6509*44704f69SBart Van Assche NULL);
6510*44704f69SBart Van Assche j = sg_get_unaligned_be16(bp + 14);
6511*44704f69SBart Van Assche snprintf(b, blen, "Number of %ss performed", bms);
6512*44704f69SBart Van Assche
6513*44704f69SBart Van Assche ok = (j > 0);
6514*44704f69SBart Van Assche if (ok)
6515*44704f69SBart Van Assche sgj_pr_hr(jsp, " %s: %d\n", b, j);
6516*44704f69SBart Van Assche else
6517*44704f69SBart Van Assche sgj_pr_hr(jsp, " %s: 0 [%s]\n", b, not_rep);
6518*44704f69SBart Van Assche if (jsp->pr_as_json)
6519*44704f69SBart Van Assche js_snakenv_ihexstr_nex(jsp, jo3p, b, j, true, NULL,
6520*44704f69SBart Van Assche ok ? NULL : not_rep, NULL);
6521*44704f69SBart Van Assche break;
6522*44704f69SBart Van Assche default:
6523*44704f69SBart Van Assche if (pc > 0x800) {
6524*44704f69SBart Van Assche if (jsp->pr_as_json)
6525*44704f69SBart Van Assche sgj_js_nv_ihexstr(jsp, jo3p, param_c_sn, pc, NULL,
6526*44704f69SBart Van Assche (pc >= 0x8000) ? vend_spec : NULL);
6527*44704f69SBart Van Assche if ((pc >= 0x8000) && (pc <= 0xafff)) {
6528*44704f69SBart Van Assche if (op->exclude_vendor) {
6529*44704f69SBart Van Assche skip_out = true;
6530*44704f69SBart Van Assche if ((op->verbose > 0) && (0 == op->do_brief) &&
6531*44704f69SBart Van Assche (! evsm_output)) {
6532*44704f69SBart Van Assche evsm_output = true;
6533*44704f69SBart Van Assche sgj_pr_hr(jsp, " %s parameter(s) being "
6534*44704f69SBart Van Assche "ignored\n", vend_spec);
6535*44704f69SBart Van Assche }
6536*44704f69SBart Van Assche } else
6537*44704f69SBart Van Assche sgj_pr_hr(jsp, " %s parameter # %d [0x%x], %s\n",
6538*44704f69SBart Van Assche ms, pc, pc, vend_spec);
6539*44704f69SBart Van Assche } else
6540*44704f69SBart Van Assche sgj_pr_hr(jsp, " %s parameter # %d [0x%x], %s\n", ms, pc,
6541*44704f69SBart Van Assche pc, rsv_s);
6542*44704f69SBart Van Assche if (skip_out)
6543*44704f69SBart Van Assche skip_out = false;
6544*44704f69SBart Van Assche else
6545*44704f69SBart Van Assche hex2fp(bp, ((pl < num) ? pl : num), " ",
6546*44704f69SBart Van Assche op->hex2str_oformat, stdout);
6547*44704f69SBart Van Assche break;
6548*44704f69SBart Van Assche } else {
6549*44704f69SBart Van Assche sgj_pr_hr(jsp, " %s parameter # %d [0x%x]\n", ms, pc, pc);
6550*44704f69SBart Van Assche if (jsp->pr_as_json)
6551*44704f69SBart Van Assche sgj_js_nv_ihexstr(jsp, jo3p, param_c_sn, pc, NULL, bsr);
6552*44704f69SBart Van Assche }
6553*44704f69SBart Van Assche if ((pl < 24) || (num < 24)) {
6554*44704f69SBart Van Assche if (num < 24)
6555*44704f69SBart Van Assche pr2serr(" truncated by response length, expected at "
6556*44704f69SBart Van Assche "least 24 bytes\n");
6557*44704f69SBart Van Assche else
6558*44704f69SBart Van Assche pr2serr(" parameter length >= 24 expected, got %d\n",
6559*44704f69SBart Van Assche pl);
6560*44704f69SBart Van Assche break;
6561*44704f69SBart Van Assche }
6562*44704f69SBart Van Assche j = sg_get_unaligned_be32(bp + 4);
6563*44704f69SBart Van Assche n = (j % 60);
6564*44704f69SBart Van Assche sgj_pr_hr(jsp, " %s when error detected: %d [%d:%d]\n", apom,
6565*44704f69SBart Van Assche j, (j / 60), n);
6566*44704f69SBart Van Assche if (jsp->pr_as_json) {
6567*44704f69SBart Van Assche snprintf(b, blen, "%d hours, %d minute%s", (j / 60), n,
6568*44704f69SBart Van Assche n != 1 ? "s" : "");
6569*44704f69SBart Van Assche js_snakenv_ihexstr_nex(jsp, jo3p, apom, j, true, NULL, b,
6570*44704f69SBart Van Assche "when error detected [unit: minute]");
6571*44704f69SBart Van Assche }
6572*44704f69SBart Van Assche j = (bp[8] >> 4) & 0xf;
6573*44704f69SBart Van Assche ok = (j < (int)SG_ARRAY_SIZE(reassign_status));
6574*44704f69SBart Van Assche if (ok)
6575*44704f69SBart Van Assche sgj_pr_hr(jsp, " %s: %s\n", rs, reassign_status[j]);
6576*44704f69SBart Van Assche else
6577*44704f69SBart Van Assche sgj_pr_hr(jsp, " %s: %s [0x%x]\n", rs, rsv_s, j);
6578*44704f69SBart Van Assche if (jsp->pr_as_json)
6579*44704f69SBart Van Assche js_snakenv_ihexstr_nex(jsp, jo3p, rs, j, true, NULL,
6580*44704f69SBart Van Assche ok ? reassign_status[j] : NULL, NULL);
6581*44704f69SBart Van Assche n = 0xf & b[8];
6582*44704f69SBart Van Assche sgj_pr_hr(jsp, " %s: %s [sk,asc,ascq: 0x%x,0x%x,0x%x]\n",
6583*44704f69SBart Van Assche s_key, sg_get_sense_key_str(n, blen, b), n, bp[9],
6584*44704f69SBart Van Assche bp[10]);
6585*44704f69SBart Van Assche if (bp[9] || bp[10])
6586*44704f69SBart Van Assche sgj_pr_hr(jsp, " %s\n",
6587*44704f69SBart Van Assche sg_get_asc_ascq_str(bp[9], bp[10], blen, b));
6588*44704f69SBart Van Assche if (jsp->pr_as_json) {
6589*44704f69SBart Van Assche sgj_js_nv_ihexstr(jsp, jo3p, "sense_key", n, NULL,
6590*44704f69SBart Van Assche sg_get_sense_key_str(n, blen, b));
6591*44704f69SBart Van Assche sgj_js_nv_ihexstr(jsp, jo3p, "additional_sense_code", bp[9],
6592*44704f69SBart Van Assche NULL, NULL);
6593*44704f69SBart Van Assche sgj_js_nv_ihexstr(jsp, jo3p, "additional_sense_code_qualifier",
6594*44704f69SBart Van Assche bp[10], NULL, sg_get_asc_ascq_str(bp[9],
6595*44704f69SBart Van Assche bp[10], blen, b));
6596*44704f69SBart Van Assche }
6597*44704f69SBart Van Assche if (op->verbose) {
6598*44704f69SBart Van Assche n = sg_scnpr(b, blen, " vendor bytes [11 -> 15]: ");
6599*44704f69SBart Van Assche for (m = 0; m < 5; ++m)
6600*44704f69SBart Van Assche n += sg_scnpr(b + n, blen - n, "0x%02x ", bp[11 + m]);
6601*44704f69SBart Van Assche sgj_pr_hr(jsp, "%s\n", b);
6602*44704f69SBart Van Assche }
6603*44704f69SBart Van Assche n = sg_scnpr(b, blen, " LBA (associated with medium error): "
6604*44704f69SBart Van Assche "0x");
6605*44704f69SBart Van Assche if (sg_all_zeros(bp + 16, 8))
6606*44704f69SBart Van Assche sgj_pr_hr(jsp, "%s0\n", b);
6607*44704f69SBart Van Assche else {
6608*44704f69SBart Van Assche for (m = 0; m < 8; ++m)
6609*44704f69SBart Van Assche n += sg_scnpr(b + n, blen - n, "%02x", bp[16 + m]);
6610*44704f69SBart Van Assche sgj_pr_hr(jsp, "%s\n", b);
6611*44704f69SBart Van Assche }
6612*44704f69SBart Van Assche if (jsp->pr_as_json)
6613*44704f69SBart Van Assche js_snakenv_ihexstr_nex(jsp, jo3p, "logical_block_address",
6614*44704f69SBart Van Assche sg_get_unaligned_be64(bp + 16), true,
6615*44704f69SBart Van Assche NULL, NULL, "of medium error");
6616*44704f69SBart Van Assche break;
6617*44704f69SBart Van Assche } /* end of switch statement block */
6618*44704f69SBart Van Assche if (jsp->pr_as_json)
6619*44704f69SBart Van Assche sgj_js_nv_o(jsp, jap, NULL /* name */, jo3p);
6620*44704f69SBart Van Assche if (op->do_pcb)
6621*44704f69SBart Van Assche sgj_pr_hr(jsp, " <%s>\n", get_pcb_str(bp[2], str,
6622*44704f69SBart Van Assche sizeof(str)));
6623*44704f69SBart Van Assche filter_chk:
6624*44704f69SBart Van Assche if (op->filter_given)
6625*44704f69SBart Van Assche break;
6626*44704f69SBart Van Assche skip:
6627*44704f69SBart Van Assche num -= pl;
6628*44704f69SBart Van Assche bp += pl;
6629*44704f69SBart Van Assche }
6630*44704f69SBart Van Assche return true;
6631*44704f69SBart Van Assche }
6632*44704f69SBart Van Assche
6633*44704f69SBart Van Assche /* ZONED_BLOCK_DEV_STATS_SUBPG [0x14,0x1] <zbds> introduced: zbc2r01 */
6634*44704f69SBart Van Assche static bool
show_zoned_block_dev_stats(const uint8_t * resp,int len,struct opts_t * op,sgj_opaque_p jop)6635*44704f69SBart Van Assche show_zoned_block_dev_stats(const uint8_t * resp, int len,
6636*44704f69SBart Van Assche struct opts_t * op, sgj_opaque_p jop)
6637*44704f69SBart Van Assche {
6638*44704f69SBart Van Assche bool trunc, bad_pl;
6639*44704f69SBart Van Assche int num, pl, pc;
6640*44704f69SBart Van Assche const uint8_t * bp;
6641*44704f69SBart Van Assche char str[PCB_STR_LEN];
6642*44704f69SBart Van Assche
6643*44704f69SBart Van Assche if (jop) { };
6644*44704f69SBart Van Assche if (op->verbose || ((! op->do_raw) && (0 == op->do_hex)))
6645*44704f69SBart Van Assche printf("Zoned block device statistics page [0x14,0x1]\n");
6646*44704f69SBart Van Assche num = len - 4;
6647*44704f69SBart Van Assche bp = &resp[0] + 4;
6648*44704f69SBart Van Assche while (num > 3) {
6649*44704f69SBart Van Assche trunc = false;
6650*44704f69SBart Van Assche bad_pl = false;
6651*44704f69SBart Van Assche pc = sg_get_unaligned_be16(bp + 0);
6652*44704f69SBart Van Assche pl = bp[3] + 4;
6653*44704f69SBart Van Assche if (4 == pl) /* DC HC560 has empty descriptors */
6654*44704f69SBart Van Assche goto skip;
6655*44704f69SBart Van Assche if (op->filter_given) {
6656*44704f69SBart Van Assche if (pc != op->filter)
6657*44704f69SBart Van Assche goto skip;
6658*44704f69SBart Van Assche }
6659*44704f69SBart Van Assche if (op->do_raw) {
6660*44704f69SBart Van Assche dStrRaw(bp, pl);
6661*44704f69SBart Van Assche goto filter_chk;
6662*44704f69SBart Van Assche } else if (op->do_hex) {
6663*44704f69SBart Van Assche hex2stdout(bp, pl, op->dstrhex_no_ascii);
6664*44704f69SBart Van Assche goto filter_chk;
6665*44704f69SBart Van Assche }
6666*44704f69SBart Van Assche switch (pc) {
6667*44704f69SBart Van Assche case 0x0:
6668*44704f69SBart Van Assche if ((pl < 8) || (num < 8)) {
6669*44704f69SBart Van Assche if (num < 8)
6670*44704f69SBart Van Assche trunc = true;
6671*44704f69SBart Van Assche else
6672*44704f69SBart Van Assche bad_pl = true;
6673*44704f69SBart Van Assche } else
6674*44704f69SBart Van Assche printf(" Maximum open zones: %" PRIu32 "\n",
6675*44704f69SBart Van Assche sg_get_unaligned_be32(bp + 8));
6676*44704f69SBart Van Assche break;
6677*44704f69SBart Van Assche case 0x1:
6678*44704f69SBart Van Assche if ((pl < 8) || (num < 8)) {
6679*44704f69SBart Van Assche if (num < 8)
6680*44704f69SBart Van Assche trunc = true;
6681*44704f69SBart Van Assche else
6682*44704f69SBart Van Assche bad_pl = true;
6683*44704f69SBart Van Assche } else
6684*44704f69SBart Van Assche printf(" Maximum explicitly open zones: %" PRIu32 "\n",
6685*44704f69SBart Van Assche sg_get_unaligned_be32(bp + 8));
6686*44704f69SBart Van Assche break;
6687*44704f69SBart Van Assche case 0x2:
6688*44704f69SBart Van Assche if ((pl < 8) || (num < 8)) {
6689*44704f69SBart Van Assche if (num < 8)
6690*44704f69SBart Van Assche trunc = true;
6691*44704f69SBart Van Assche else
6692*44704f69SBart Van Assche bad_pl = true;
6693*44704f69SBart Van Assche } else
6694*44704f69SBart Van Assche printf(" Maximum implicitly open zones: %" PRIu32 "\n",
6695*44704f69SBart Van Assche sg_get_unaligned_be32(bp + 8));
6696*44704f69SBart Van Assche break;
6697*44704f69SBart Van Assche case 0x3:
6698*44704f69SBart Van Assche if ((pl < 8) || (num < 8)) {
6699*44704f69SBart Van Assche if (num < 8)
6700*44704f69SBart Van Assche trunc = true;
6701*44704f69SBart Van Assche else
6702*44704f69SBart Van Assche bad_pl = true;
6703*44704f69SBart Van Assche } else
6704*44704f69SBart Van Assche printf(" Minimum empty zones: %" PRIu32 "\n",
6705*44704f69SBart Van Assche sg_get_unaligned_be32(bp + 8));
6706*44704f69SBart Van Assche break;
6707*44704f69SBart Van Assche case 0x4:
6708*44704f69SBart Van Assche if ((pl < 8) || (num < 8)) {
6709*44704f69SBart Van Assche if (num < 8)
6710*44704f69SBart Van Assche trunc = true;
6711*44704f69SBart Van Assche else
6712*44704f69SBart Van Assche bad_pl = true;
6713*44704f69SBart Van Assche } else
6714*44704f69SBart Van Assche printf(" Maximum non-sequential zones: %" PRIu32 "\n",
6715*44704f69SBart Van Assche sg_get_unaligned_be32(bp + 8));
6716*44704f69SBart Van Assche break;
6717*44704f69SBart Van Assche case 0x5:
6718*44704f69SBart Van Assche if ((pl < 8) || (num < 8)) {
6719*44704f69SBart Van Assche if (num < 8)
6720*44704f69SBart Van Assche trunc = true;
6721*44704f69SBart Van Assche else
6722*44704f69SBart Van Assche bad_pl = true;
6723*44704f69SBart Van Assche } else
6724*44704f69SBart Van Assche printf(" Zones emptied: %" PRIu32 "\n",
6725*44704f69SBart Van Assche sg_get_unaligned_be32(bp + 8));
6726*44704f69SBart Van Assche break;
6727*44704f69SBart Van Assche case 0x6:
6728*44704f69SBart Van Assche if ((pl < 8) || (num < 8)) {
6729*44704f69SBart Van Assche if (num < 8)
6730*44704f69SBart Van Assche trunc = true;
6731*44704f69SBart Van Assche else
6732*44704f69SBart Van Assche bad_pl = true;
6733*44704f69SBart Van Assche } else
6734*44704f69SBart Van Assche printf(" Suboptimal write commands: %" PRIu32 "\n",
6735*44704f69SBart Van Assche sg_get_unaligned_be32(bp + 8));
6736*44704f69SBart Van Assche break;
6737*44704f69SBart Van Assche case 0x7:
6738*44704f69SBart Van Assche if ((pl < 8) || (num < 8)) {
6739*44704f69SBart Van Assche if (num < 8)
6740*44704f69SBart Van Assche trunc = true;
6741*44704f69SBart Van Assche else
6742*44704f69SBart Van Assche bad_pl = true;
6743*44704f69SBart Van Assche } else
6744*44704f69SBart Van Assche printf(" Commands exceeding optimal limit: %" PRIu32 "\n",
6745*44704f69SBart Van Assche sg_get_unaligned_be32(bp + 8));
6746*44704f69SBart Van Assche break;
6747*44704f69SBart Van Assche case 0x8:
6748*44704f69SBart Van Assche if ((pl < 8) || (num < 8)) {
6749*44704f69SBart Van Assche if (num < 8)
6750*44704f69SBart Van Assche trunc = true;
6751*44704f69SBart Van Assche else
6752*44704f69SBart Van Assche bad_pl = true;
6753*44704f69SBart Van Assche } else
6754*44704f69SBart Van Assche printf(" Failed explicit opens: %" PRIu32 "\n",
6755*44704f69SBart Van Assche sg_get_unaligned_be32(bp + 8));
6756*44704f69SBart Van Assche break;
6757*44704f69SBart Van Assche case 0x9:
6758*44704f69SBart Van Assche if ((pl < 8) || (num < 8)) {
6759*44704f69SBart Van Assche if (num < 8)
6760*44704f69SBart Van Assche trunc = true;
6761*44704f69SBart Van Assche else
6762*44704f69SBart Van Assche bad_pl = true;
6763*44704f69SBart Van Assche } else
6764*44704f69SBart Van Assche printf(" Read rule violations: %" PRIu32 "\n",
6765*44704f69SBart Van Assche sg_get_unaligned_be32(bp + 8));
6766*44704f69SBart Van Assche break;
6767*44704f69SBart Van Assche case 0xa:
6768*44704f69SBart Van Assche if ((pl < 8) || (num < 8)) {
6769*44704f69SBart Van Assche if (num < 8)
6770*44704f69SBart Van Assche trunc = true;
6771*44704f69SBart Van Assche else
6772*44704f69SBart Van Assche bad_pl = true;
6773*44704f69SBart Van Assche } else
6774*44704f69SBart Van Assche printf(" Write rule violations: %" PRIu32 "\n",
6775*44704f69SBart Van Assche sg_get_unaligned_be32(bp + 8));
6776*44704f69SBart Van Assche break;
6777*44704f69SBart Van Assche case 0xb: /* added zbc2r04 */
6778*44704f69SBart Van Assche if ((pl < 8) || (num < 8)) {
6779*44704f69SBart Van Assche if (num < 8)
6780*44704f69SBart Van Assche trunc = true;
6781*44704f69SBart Van Assche else
6782*44704f69SBart Van Assche bad_pl = true;
6783*44704f69SBart Van Assche } else
6784*44704f69SBart Van Assche printf(" Maximum implicitly open or before required zones: "
6785*44704f69SBart Van Assche "%" PRIu32 "\n", sg_get_unaligned_be32(bp + 8));
6786*44704f69SBart Van Assche break;
6787*44704f69SBart Van Assche default:
6788*44704f69SBart Van Assche printf(" Reserved [parameter_code=0x%x]:\n", pc);
6789*44704f69SBart Van Assche hex2fp(bp, ((pl < num) ? pl : num), " ",
6790*44704f69SBart Van Assche op->hex2str_oformat, stdout);
6791*44704f69SBart Van Assche break;
6792*44704f69SBart Van Assche }
6793*44704f69SBart Van Assche if (trunc)
6794*44704f69SBart Van Assche pr2serr(" truncated by response length, expected at least "
6795*44704f69SBart Van Assche "8 bytes\n");
6796*44704f69SBart Van Assche if (bad_pl)
6797*44704f69SBart Van Assche pr2serr(" parameter length >= 8 expected, got %d\n", pl);
6798*44704f69SBart Van Assche if (op->do_pcb)
6799*44704f69SBart Van Assche printf(" <%s>\n", get_pcb_str(bp[2], str, sizeof(str)));
6800*44704f69SBart Van Assche filter_chk:
6801*44704f69SBart Van Assche if (op->filter_given)
6802*44704f69SBart Van Assche break;
6803*44704f69SBart Van Assche skip:
6804*44704f69SBart Van Assche num -= pl;
6805*44704f69SBart Van Assche bp += pl;
6806*44704f69SBart Van Assche }
6807*44704f69SBart Van Assche return true;
6808*44704f69SBart Van Assche }
6809*44704f69SBart Van Assche
6810*44704f69SBart Van Assche /* PENDING_DEFECTS_SUBPG [0x15,0x1] <pd> introduced: SBC-4 */
6811*44704f69SBart Van Assche static bool
show_pending_defects_page(const uint8_t * resp,int len,struct opts_t * op,sgj_opaque_p jop)6812*44704f69SBart Van Assche show_pending_defects_page(const uint8_t * resp, int len,
6813*44704f69SBart Van Assche struct opts_t * op, sgj_opaque_p jop)
6814*44704f69SBart Van Assche {
6815*44704f69SBart Van Assche int num, pl, pc;
6816*44704f69SBart Van Assche uint32_t count;
6817*44704f69SBart Van Assche const uint8_t * bp;
6818*44704f69SBart Van Assche char str[PCB_STR_LEN];
6819*44704f69SBart Van Assche
6820*44704f69SBart Van Assche if (jop) { };
6821*44704f69SBart Van Assche if (op->verbose || ((! op->do_raw) && (0 == op->do_hex)))
6822*44704f69SBart Van Assche printf("Pending defects page [0x15,0x1]\n");
6823*44704f69SBart Van Assche num = len - 4;
6824*44704f69SBart Van Assche bp = &resp[0] + 4;
6825*44704f69SBart Van Assche while (num > 3) {
6826*44704f69SBart Van Assche pc = sg_get_unaligned_be16(bp + 0);
6827*44704f69SBart Van Assche pl = bp[3] + 4;
6828*44704f69SBart Van Assche if (op->filter_given) {
6829*44704f69SBart Van Assche if (pc != op->filter)
6830*44704f69SBart Van Assche goto skip;
6831*44704f69SBart Van Assche }
6832*44704f69SBart Van Assche if (op->do_raw) {
6833*44704f69SBart Van Assche dStrRaw(bp, pl);
6834*44704f69SBart Van Assche goto filter_chk;
6835*44704f69SBart Van Assche } else if (op->do_hex) {
6836*44704f69SBart Van Assche hex2stdout(bp, pl, op->dstrhex_no_ascii);
6837*44704f69SBart Van Assche goto filter_chk;
6838*44704f69SBart Van Assche }
6839*44704f69SBart Van Assche switch (pc) {
6840*44704f69SBart Van Assche case 0x0:
6841*44704f69SBart Van Assche printf(" Pending defect count: ");
6842*44704f69SBart Van Assche if ((pl < 8) || (num < 8)) {
6843*44704f69SBart Van Assche if (num < 8)
6844*44704f69SBart Van Assche pr2serr("\n truncated by response length, expected "
6845*44704f69SBart Van Assche "at least 8 bytes\n");
6846*44704f69SBart Van Assche else
6847*44704f69SBart Van Assche pr2serr("\n parameter length >= 8 expected, got %d\n",
6848*44704f69SBart Van Assche pl);
6849*44704f69SBart Van Assche break;
6850*44704f69SBart Van Assche }
6851*44704f69SBart Van Assche count = sg_get_unaligned_be32(bp + 4);
6852*44704f69SBart Van Assche if (0 == count) {
6853*44704f69SBart Van Assche printf("0\n");
6854*44704f69SBart Van Assche break;
6855*44704f69SBart Van Assche }
6856*44704f69SBart Van Assche printf("%3u | LBA Accumulated power_on\n", count);
6857*44704f69SBart Van Assche printf("-----------------------------|---------------");
6858*44704f69SBart Van Assche printf("-----------hours---------\n");
6859*44704f69SBart Van Assche break;
6860*44704f69SBart Van Assche default:
6861*44704f69SBart Van Assche printf(" Pending defect %4d: ", pc);
6862*44704f69SBart Van Assche if ((pl < 16) || (num < 16)) {
6863*44704f69SBart Van Assche if (num < 16)
6864*44704f69SBart Van Assche pr2serr("\n truncated by response length, expected "
6865*44704f69SBart Van Assche "at least 16 bytes\n");
6866*44704f69SBart Van Assche else
6867*44704f69SBart Van Assche pr2serr("\n parameter length >= 16 expected, got %d\n",
6868*44704f69SBart Van Assche pl);
6869*44704f69SBart Van Assche break;
6870*44704f69SBart Van Assche }
6871*44704f69SBart Van Assche printf(" 0x%-16" PRIx64 " %5u\n",
6872*44704f69SBart Van Assche sg_get_unaligned_be64(bp + 8),
6873*44704f69SBart Van Assche sg_get_unaligned_be32(bp + 4));
6874*44704f69SBart Van Assche break;
6875*44704f69SBart Van Assche }
6876*44704f69SBart Van Assche if (op->do_pcb)
6877*44704f69SBart Van Assche printf(" <%s>\n", get_pcb_str(bp[2], str, sizeof(str)));
6878*44704f69SBart Van Assche filter_chk:
6879*44704f69SBart Van Assche if (op->filter_given)
6880*44704f69SBart Van Assche break;
6881*44704f69SBart Van Assche skip:
6882*44704f69SBart Van Assche num -= pl;
6883*44704f69SBart Van Assche bp += pl;
6884*44704f69SBart Van Assche }
6885*44704f69SBart Van Assche return true;
6886*44704f69SBart Van Assche }
6887*44704f69SBart Van Assche
6888*44704f69SBart Van Assche /* BACKGROUND_OP_SUBPG [0x15,0x2] <bop> introduced: SBC-4 rev 7 */
6889*44704f69SBart Van Assche static bool
show_background_op_page(const uint8_t * resp,int len,struct opts_t * op,sgj_opaque_p jop)6890*44704f69SBart Van Assche show_background_op_page(const uint8_t * resp, int len,
6891*44704f69SBart Van Assche struct opts_t * op, sgj_opaque_p jop)
6892*44704f69SBart Van Assche {
6893*44704f69SBart Van Assche int num, pl, pc;
6894*44704f69SBart Van Assche const uint8_t * bp;
6895*44704f69SBart Van Assche char str[PCB_STR_LEN];
6896*44704f69SBart Van Assche
6897*44704f69SBart Van Assche if (jop) { };
6898*44704f69SBart Van Assche if (op->verbose || ((! op->do_raw) && (0 == op->do_hex)))
6899*44704f69SBart Van Assche printf("Background operation page [0x15,0x2]\n");
6900*44704f69SBart Van Assche num = len - 4;
6901*44704f69SBart Van Assche bp = &resp[0] + 4;
6902*44704f69SBart Van Assche while (num > 3) {
6903*44704f69SBart Van Assche pc = sg_get_unaligned_be16(bp + 0);
6904*44704f69SBart Van Assche pl = bp[3] + 4;
6905*44704f69SBart Van Assche if (op->filter_given) {
6906*44704f69SBart Van Assche if (pc != op->filter)
6907*44704f69SBart Van Assche goto skip;
6908*44704f69SBart Van Assche }
6909*44704f69SBart Van Assche if (op->do_raw) {
6910*44704f69SBart Van Assche dStrRaw(bp, pl);
6911*44704f69SBart Van Assche goto filter_chk;
6912*44704f69SBart Van Assche } else if (op->do_hex) {
6913*44704f69SBart Van Assche hex2stdout(bp, pl, op->dstrhex_no_ascii);
6914*44704f69SBart Van Assche goto filter_chk;
6915*44704f69SBart Van Assche }
6916*44704f69SBart Van Assche switch (pc) {
6917*44704f69SBart Van Assche case 0x0:
6918*44704f69SBart Van Assche printf(" Background operation:");
6919*44704f69SBart Van Assche if ((pl < 8) || (num < 8)) {
6920*44704f69SBart Van Assche if (num < 8)
6921*44704f69SBart Van Assche pr2serr("\n truncated by response length, expected "
6922*44704f69SBart Van Assche "at least 8 bytes\n");
6923*44704f69SBart Van Assche else
6924*44704f69SBart Van Assche pr2serr("\n parameter length >= 8 expected, got %d\n",
6925*44704f69SBart Van Assche pl);
6926*44704f69SBart Van Assche break;
6927*44704f69SBart Van Assche }
6928*44704f69SBart Van Assche printf(" BO_STATUS=%d\n", bp[4]);
6929*44704f69SBart Van Assche break;
6930*44704f69SBart Van Assche default:
6931*44704f69SBart Van Assche printf(" Reserved [parameter_code=0x%x]:\n", pc);
6932*44704f69SBart Van Assche hex2fp(bp, ((pl < num) ? pl : num), " ",
6933*44704f69SBart Van Assche op->hex2str_oformat, stdout);
6934*44704f69SBart Van Assche break;
6935*44704f69SBart Van Assche }
6936*44704f69SBart Van Assche if (op->do_pcb)
6937*44704f69SBart Van Assche printf(" <%s>\n", get_pcb_str(bp[2], str, sizeof(str)));
6938*44704f69SBart Van Assche filter_chk:
6939*44704f69SBart Van Assche if (op->filter_given)
6940*44704f69SBart Van Assche break;
6941*44704f69SBart Van Assche skip:
6942*44704f69SBart Van Assche num -= pl;
6943*44704f69SBart Van Assche bp += pl;
6944*44704f69SBart Van Assche }
6945*44704f69SBart Van Assche return true;
6946*44704f69SBart Van Assche }
6947*44704f69SBart Van Assche
6948*44704f69SBart Van Assche /* LPS misalignment page [0x15,0x3] <lps> introduced: SBC-4 rev 10
6949*44704f69SBart Van Assche LPS: "Long Physical Sector" a term from an ATA feature set */
6950*44704f69SBart Van Assche static bool
show_lps_misalignment_page(const uint8_t * resp,int len,struct opts_t * op,sgj_opaque_p jop)6951*44704f69SBart Van Assche show_lps_misalignment_page(const uint8_t * resp, int len,
6952*44704f69SBart Van Assche struct opts_t * op, sgj_opaque_p jop)
6953*44704f69SBart Van Assche {
6954*44704f69SBart Van Assche int num, pl, pc;
6955*44704f69SBart Van Assche const uint8_t * bp;
6956*44704f69SBart Van Assche char str[PCB_STR_LEN];
6957*44704f69SBart Van Assche
6958*44704f69SBart Van Assche if (jop) { };
6959*44704f69SBart Van Assche if (op->verbose || ((! op->do_raw) && (0 == op->do_hex)))
6960*44704f69SBart Van Assche printf("LPS misalignment page [0x15,0x3]\n");
6961*44704f69SBart Van Assche num = len - 4;
6962*44704f69SBart Van Assche bp = &resp[0] + 4;
6963*44704f69SBart Van Assche while (num > 3) {
6964*44704f69SBart Van Assche pc = sg_get_unaligned_be16(bp + 0);
6965*44704f69SBart Van Assche pl = bp[3] + 4;
6966*44704f69SBart Van Assche if (op->filter_given) {
6967*44704f69SBart Van Assche if (pc != op->filter)
6968*44704f69SBart Van Assche goto skip;
6969*44704f69SBart Van Assche }
6970*44704f69SBart Van Assche if (op->do_raw) {
6971*44704f69SBart Van Assche dStrRaw(bp, pl);
6972*44704f69SBart Van Assche goto filter_chk;
6973*44704f69SBart Van Assche } else if (op->do_hex) {
6974*44704f69SBart Van Assche hex2stdout(bp, pl, op->dstrhex_no_ascii);
6975*44704f69SBart Van Assche goto filter_chk;
6976*44704f69SBart Van Assche }
6977*44704f69SBart Van Assche switch (pc) {
6978*44704f69SBart Van Assche case 0x0:
6979*44704f69SBart Van Assche printf(" LPS misalignment count: ");
6980*44704f69SBart Van Assche if (4 == bp[3])
6981*44704f69SBart Van Assche printf("max lpsm: %" PRIu16 ", count=%" PRIu16 "\n",
6982*44704f69SBart Van Assche sg_get_unaligned_be16(bp + 4),
6983*44704f69SBart Van Assche sg_get_unaligned_be16(bp + 6));
6984*44704f69SBart Van Assche else
6985*44704f69SBart Van Assche printf("<unexpected pc=0 parameter length=%d>\n", bp[4]);
6986*44704f69SBart Van Assche break;
6987*44704f69SBart Van Assche default:
6988*44704f69SBart Van Assche if (pc <= 0xf000) { /* parameter codes 0x1 to 0xf000 */
6989*44704f69SBart Van Assche if (8 == bp[3])
6990*44704f69SBart Van Assche printf(" LBA of misaligned block: 0x%" PRIx64 "\n",
6991*44704f69SBart Van Assche sg_get_unaligned_be64(bp + 4));
6992*44704f69SBart Van Assche else
6993*44704f69SBart Van Assche printf("<unexpected pc=0x%x parameter length=%d>\n",
6994*44704f69SBart Van Assche pc, bp[4]);
6995*44704f69SBart Van Assche } else {
6996*44704f69SBart Van Assche printf("<unexpected pc=0x%x>\n", pc);
6997*44704f69SBart Van Assche hex2fp(bp, ((pl < num) ? pl : num), " ",
6998*44704f69SBart Van Assche op->hex2str_oformat, stdout);
6999*44704f69SBart Van Assche }
7000*44704f69SBart Van Assche break;
7001*44704f69SBart Van Assche }
7002*44704f69SBart Van Assche if (op->do_pcb)
7003*44704f69SBart Van Assche printf(" <%s>\n", get_pcb_str(bp[2], str, sizeof(str)));
7004*44704f69SBart Van Assche filter_chk:
7005*44704f69SBart Van Assche if (op->filter_given)
7006*44704f69SBart Van Assche break;
7007*44704f69SBart Van Assche skip:
7008*44704f69SBart Van Assche num -= pl;
7009*44704f69SBart Van Assche bp += pl;
7010*44704f69SBart Van Assche }
7011*44704f69SBart Van Assche return true;
7012*44704f69SBart Van Assche }
7013*44704f69SBart Van Assche
7014*44704f69SBart Van Assche /* Service buffer information [0x15] <sbi> (adc) */
7015*44704f69SBart Van Assche static bool
show_service_buffer_info_page(const uint8_t * resp,int len,struct opts_t * op,sgj_opaque_p jop)7016*44704f69SBart Van Assche show_service_buffer_info_page(const uint8_t * resp, int len,
7017*44704f69SBart Van Assche struct opts_t * op, sgj_opaque_p jop)
7018*44704f69SBart Van Assche {
7019*44704f69SBart Van Assche bool evsm_output = false;
7020*44704f69SBart Van Assche int num, pl, pc;
7021*44704f69SBart Van Assche const uint8_t * bp;
7022*44704f69SBart Van Assche char str[PCB_STR_LEN];
7023*44704f69SBart Van Assche
7024*44704f69SBart Van Assche if (jop) { };
7025*44704f69SBart Van Assche if (op->verbose || ((! op->do_raw) && (0 == op->do_hex)))
7026*44704f69SBart Van Assche printf("Service buffer information page (adc-3) [0x15]\n");
7027*44704f69SBart Van Assche num = len - 4;
7028*44704f69SBart Van Assche bp = &resp[0] + 4;
7029*44704f69SBart Van Assche while (num > 3) {
7030*44704f69SBart Van Assche pc = sg_get_unaligned_be16(bp + 0);
7031*44704f69SBart Van Assche pl = bp[3] + 4;
7032*44704f69SBart Van Assche if (op->filter_given) {
7033*44704f69SBart Van Assche if (pc != op->filter)
7034*44704f69SBart Van Assche goto skip;
7035*44704f69SBart Van Assche }
7036*44704f69SBart Van Assche if (op->do_raw) {
7037*44704f69SBart Van Assche dStrRaw(bp, pl);
7038*44704f69SBart Van Assche goto filter_chk;
7039*44704f69SBart Van Assche } else if (op->do_hex) {
7040*44704f69SBart Van Assche hex2stdout(bp, pl, op->dstrhex_no_ascii);
7041*44704f69SBart Van Assche goto filter_chk;
7042*44704f69SBart Van Assche }
7043*44704f69SBart Van Assche if (pc < 0x100) {
7044*44704f69SBart Van Assche printf(" Service buffer identifier: 0x%x\n", pc);
7045*44704f69SBart Van Assche printf(" Buffer id: 0x%x, tu=%d, nmp=%d, nmm=%d, "
7046*44704f69SBart Van Assche "offline=%d\n", bp[4], !!(0x10 & bp[5]),
7047*44704f69SBart Van Assche !!(0x8 & bp[5]), !!(0x4 & bp[5]), !!(0x2 & bp[5]));
7048*44704f69SBart Van Assche printf(" pd=%d, code_set: %s, Service buffer title:\n",
7049*44704f69SBart Van Assche !!(0x1 & bp[5]), sg_get_desig_code_set_str(0xf & bp[6]));
7050*44704f69SBart Van Assche printf(" %.*s\n", pl - 8, bp + 8);
7051*44704f69SBart Van Assche } else if (pc < 0x8000) {
7052*44704f69SBart Van Assche printf(" parameter_code=0x%x, Reserved, parameter in hex:\n",
7053*44704f69SBart Van Assche pc);
7054*44704f69SBart Van Assche hex2fp(bp + 4, pl - 4, " ", op->hex2str_oformat, stdout);
7055*44704f69SBart Van Assche } else {
7056*44704f69SBart Van Assche if (op->exclude_vendor) {
7057*44704f69SBart Van Assche if ((op->verbose > 0) && (0 == op->do_brief) &&
7058*44704f69SBart Van Assche (! evsm_output)) {
7059*44704f69SBart Van Assche evsm_output = true;
7060*44704f69SBart Van Assche printf(" Vendor specific parameter(s) being "
7061*44704f69SBart Van Assche "ignored\n");
7062*44704f69SBart Van Assche }
7063*44704f69SBart Van Assche } else {
7064*44704f69SBart Van Assche printf(" parameter_code=0x%x, Vendor-specific, parameter in "
7065*44704f69SBart Van Assche "hex:\n", pc);
7066*44704f69SBart Van Assche hex2fp(bp + 4, pl - 4, " ", op->hex2str_oformat, stdout);
7067*44704f69SBart Van Assche }
7068*44704f69SBart Van Assche }
7069*44704f69SBart Van Assche if (op->do_pcb)
7070*44704f69SBart Van Assche printf(" <%s>\n", get_pcb_str(bp[2], str, sizeof(str)));
7071*44704f69SBart Van Assche filter_chk:
7072*44704f69SBart Van Assche if (op->filter_given)
7073*44704f69SBart Van Assche break;
7074*44704f69SBart Van Assche skip:
7075*44704f69SBart Van Assche num -= pl;
7076*44704f69SBart Van Assche bp += pl;
7077*44704f69SBart Van Assche }
7078*44704f69SBart Van Assche return true;
7079*44704f69SBart Van Assche }
7080*44704f69SBart Van Assche
7081*44704f69SBart Van Assche /* Sequential access device page [0xc] <sad> for tape */
7082*44704f69SBart Van Assche static bool
show_sequential_access_page(const uint8_t * resp,int len,struct opts_t * op,sgj_opaque_p jop)7083*44704f69SBart Van Assche show_sequential_access_page(const uint8_t * resp, int len,
7084*44704f69SBart Van Assche struct opts_t * op, sgj_opaque_p jop)
7085*44704f69SBart Van Assche {
7086*44704f69SBart Van Assche bool evsm_output = false;
7087*44704f69SBart Van Assche int num, pl, pc;
7088*44704f69SBart Van Assche const uint8_t * bp;
7089*44704f69SBart Van Assche uint64_t ull, gbytes;
7090*44704f69SBart Van Assche bool all_set;
7091*44704f69SBart Van Assche char str[PCB_STR_LEN];
7092*44704f69SBart Van Assche
7093*44704f69SBart Van Assche if (jop) { };
7094*44704f69SBart Van Assche if (op->verbose || ((! op->do_raw) && (0 == op->do_hex)))
7095*44704f69SBart Van Assche printf("Sequential access device page (ssc-3)\n");
7096*44704f69SBart Van Assche num = len - 4;
7097*44704f69SBart Van Assche bp = &resp[0] + 4;
7098*44704f69SBart Van Assche while (num > 3) {
7099*44704f69SBart Van Assche pc = sg_get_unaligned_be16(bp + 0);
7100*44704f69SBart Van Assche pl = bp[3] + 4;
7101*44704f69SBart Van Assche if (op->filter_given) {
7102*44704f69SBart Van Assche if (pc != op->filter)
7103*44704f69SBart Van Assche goto skip;
7104*44704f69SBart Van Assche }
7105*44704f69SBart Van Assche if (op->do_raw) {
7106*44704f69SBart Van Assche dStrRaw(bp, pl);
7107*44704f69SBart Van Assche goto filter_chk;
7108*44704f69SBart Van Assche } else if (op->do_hex) {
7109*44704f69SBart Van Assche hex2stdout(bp, pl, op->dstrhex_no_ascii);
7110*44704f69SBart Van Assche goto filter_chk;
7111*44704f69SBart Van Assche }
7112*44704f69SBart Van Assche ull = sg_get_unaligned_be(pl - 4, bp + 4);
7113*44704f69SBart Van Assche all_set = sg_all_ffs(bp + 4, pl - 4);
7114*44704f69SBart Van Assche gbytes = ull / 1000000000;
7115*44704f69SBart Van Assche switch (pc) {
7116*44704f69SBart Van Assche case 0:
7117*44704f69SBart Van Assche printf(" Data bytes received with WRITE commands: %" PRIu64
7118*44704f69SBart Van Assche " GB", gbytes);
7119*44704f69SBart Van Assche if (op->verbose)
7120*44704f69SBart Van Assche printf(" [%" PRIu64 " bytes]", ull);
7121*44704f69SBart Van Assche printf("\n");
7122*44704f69SBart Van Assche break;
7123*44704f69SBart Van Assche case 1:
7124*44704f69SBart Van Assche printf(" Data bytes written to media by WRITE commands: %" PRIu64
7125*44704f69SBart Van Assche " GB", gbytes);
7126*44704f69SBart Van Assche if (op->verbose)
7127*44704f69SBart Van Assche printf(" [%" PRIu64 " bytes]", ull);
7128*44704f69SBart Van Assche printf("\n");
7129*44704f69SBart Van Assche break;
7130*44704f69SBart Van Assche case 2:
7131*44704f69SBart Van Assche printf(" Data bytes read from media by READ commands: %" PRIu64
7132*44704f69SBart Van Assche " GB", gbytes);
7133*44704f69SBart Van Assche if (op->verbose)
7134*44704f69SBart Van Assche printf(" [%" PRIu64 " bytes]", ull);
7135*44704f69SBart Van Assche printf("\n");
7136*44704f69SBart Van Assche break;
7137*44704f69SBart Van Assche case 3:
7138*44704f69SBart Van Assche printf(" Data bytes transferred by READ commands: %" PRIu64
7139*44704f69SBart Van Assche " GB", gbytes);
7140*44704f69SBart Van Assche if (op->verbose)
7141*44704f69SBart Van Assche printf(" [%" PRIu64 " bytes]", ull);
7142*44704f69SBart Van Assche printf("\n");
7143*44704f69SBart Van Assche break;
7144*44704f69SBart Van Assche case 4:
7145*44704f69SBart Van Assche if (! all_set)
7146*44704f69SBart Van Assche printf(" Native capacity from BOP to EOD: %" PRIu64 " MB\n",
7147*44704f69SBart Van Assche ull);
7148*44704f69SBart Van Assche break;
7149*44704f69SBart Van Assche case 5:
7150*44704f69SBart Van Assche if (! all_set)
7151*44704f69SBart Van Assche printf(" Native capacity from BOP to EW of current "
7152*44704f69SBart Van Assche "partition: %" PRIu64 " MB\n", ull);
7153*44704f69SBart Van Assche break;
7154*44704f69SBart Van Assche case 6:
7155*44704f69SBart Van Assche if (! all_set)
7156*44704f69SBart Van Assche printf(" Minimum native capacity from EW to EOP of current "
7157*44704f69SBart Van Assche "partition: %" PRIu64 " MB\n", ull);
7158*44704f69SBart Van Assche break;
7159*44704f69SBart Van Assche case 7:
7160*44704f69SBart Van Assche if (! all_set)
7161*44704f69SBart Van Assche printf(" Native capacity from BOP to current position: %"
7162*44704f69SBart Van Assche PRIu64 " MB\n", ull);
7163*44704f69SBart Van Assche break;
7164*44704f69SBart Van Assche case 8:
7165*44704f69SBart Van Assche if (! all_set)
7166*44704f69SBart Van Assche printf(" Maximum native capacity in device object buffer: %"
7167*44704f69SBart Van Assche PRIu64 " MB\n", ull);
7168*44704f69SBart Van Assche break;
7169*44704f69SBart Van Assche case 0x100:
7170*44704f69SBart Van Assche if (ull > 0)
7171*44704f69SBart Van Assche printf(" Cleaning action required\n");
7172*44704f69SBart Van Assche else
7173*44704f69SBart Van Assche printf(" Cleaning action not required (or completed)\n");
7174*44704f69SBart Van Assche if (op->verbose)
7175*44704f69SBart Van Assche printf(" cleaning value: %" PRIu64 "\n", ull);
7176*44704f69SBart Van Assche break;
7177*44704f69SBart Van Assche default:
7178*44704f69SBart Van Assche if (pc >= 0x8000) {
7179*44704f69SBart Van Assche if (op->exclude_vendor) {
7180*44704f69SBart Van Assche if ((op->verbose > 0) && (0 == op->do_brief) &&
7181*44704f69SBart Van Assche (! evsm_output)) {
7182*44704f69SBart Van Assche evsm_output = true;
7183*44704f69SBart Van Assche printf(" Vendor specific parameter(s) being "
7184*44704f69SBart Van Assche "ignored\n");
7185*44704f69SBart Van Assche }
7186*44704f69SBart Van Assche } else
7187*44704f69SBart Van Assche printf(" Vendor specific parameter [0x%x] value: %"
7188*44704f69SBart Van Assche PRIu64 "\n", pc, ull);
7189*44704f69SBart Van Assche } else
7190*44704f69SBart Van Assche printf(" Reserved parameter [0x%x] value: %" PRIu64 "\n",
7191*44704f69SBart Van Assche pc, ull);
7192*44704f69SBart Van Assche break;
7193*44704f69SBart Van Assche }
7194*44704f69SBart Van Assche if (op->do_pcb)
7195*44704f69SBart Van Assche printf(" <%s>\n", get_pcb_str(bp[2], str, sizeof(str)));
7196*44704f69SBart Van Assche filter_chk:
7197*44704f69SBart Van Assche if (op->filter_given)
7198*44704f69SBart Van Assche break;
7199*44704f69SBart Van Assche skip:
7200*44704f69SBart Van Assche num -= pl;
7201*44704f69SBart Van Assche bp += pl;
7202*44704f69SBart Van Assche }
7203*44704f69SBart Van Assche return true;
7204*44704f69SBart Van Assche }
7205*44704f69SBart Van Assche
7206*44704f69SBart Van Assche /* Device statistics 0x14 <ds> for tape and ADC */
7207*44704f69SBart Van Assche static bool
show_device_stats_page(const uint8_t * resp,int len,struct opts_t * op,sgj_opaque_p jop)7208*44704f69SBart Van Assche show_device_stats_page(const uint8_t * resp, int len,
7209*44704f69SBart Van Assche struct opts_t * op, sgj_opaque_p jop)
7210*44704f69SBart Van Assche {
7211*44704f69SBart Van Assche bool evsm_output = false;
7212*44704f69SBart Van Assche int num, pl, pc;
7213*44704f69SBart Van Assche const uint8_t * bp;
7214*44704f69SBart Van Assche char str[PCB_STR_LEN];
7215*44704f69SBart Van Assche
7216*44704f69SBart Van Assche if (jop) { };
7217*44704f69SBart Van Assche if (op->verbose || ((! op->do_raw) && (0 == op->do_hex)))
7218*44704f69SBart Van Assche printf("Device statistics page (ssc-3 and adc)\n");
7219*44704f69SBart Van Assche num = len - 4;
7220*44704f69SBart Van Assche bp = &resp[0] + 4;
7221*44704f69SBart Van Assche while (num > 3) {
7222*44704f69SBart Van Assche pc = sg_get_unaligned_be16(bp + 0);
7223*44704f69SBart Van Assche pl = bp[3] + 4;
7224*44704f69SBart Van Assche if (op->filter_given) {
7225*44704f69SBart Van Assche if (pc != op->filter)
7226*44704f69SBart Van Assche goto skip;
7227*44704f69SBart Van Assche }
7228*44704f69SBart Van Assche if (op->do_raw) {
7229*44704f69SBart Van Assche dStrRaw(bp, pl);
7230*44704f69SBart Van Assche goto filter_chk;
7231*44704f69SBart Van Assche } else if (op->do_hex) {
7232*44704f69SBart Van Assche hex2stdout(bp, pl, op->dstrhex_no_ascii);
7233*44704f69SBart Van Assche goto filter_chk;
7234*44704f69SBart Van Assche }
7235*44704f69SBart Van Assche if (pc < 0x1000) {
7236*44704f69SBart Van Assche bool vl_num = true;
7237*44704f69SBart Van Assche
7238*44704f69SBart Van Assche switch (pc) {
7239*44704f69SBart Van Assche case 0:
7240*44704f69SBart Van Assche printf(" Lifetime media loads:");
7241*44704f69SBart Van Assche break;
7242*44704f69SBart Van Assche case 1:
7243*44704f69SBart Van Assche printf(" Lifetime cleaning operations:");
7244*44704f69SBart Van Assche break;
7245*44704f69SBart Van Assche case 2:
7246*44704f69SBart Van Assche printf(" Lifetime power on hours:");
7247*44704f69SBart Van Assche break;
7248*44704f69SBart Van Assche case 3:
7249*44704f69SBart Van Assche printf(" Lifetime media motion (head) hours:");
7250*44704f69SBart Van Assche break;
7251*44704f69SBart Van Assche case 4:
7252*44704f69SBart Van Assche printf(" Lifetime metres of tape processed:");
7253*44704f69SBart Van Assche break;
7254*44704f69SBart Van Assche case 5:
7255*44704f69SBart Van Assche printf(" Lifetime media motion (head) hours when "
7256*44704f69SBart Van Assche "incompatible media last loaded:");
7257*44704f69SBart Van Assche break;
7258*44704f69SBart Van Assche case 6:
7259*44704f69SBart Van Assche printf(" Lifetime power on hours when last temperature "
7260*44704f69SBart Van Assche "condition occurred:");
7261*44704f69SBart Van Assche break;
7262*44704f69SBart Van Assche case 7:
7263*44704f69SBart Van Assche printf(" Lifetime power on hours when last power "
7264*44704f69SBart Van Assche "consumption condition occurred:");
7265*44704f69SBart Van Assche break;
7266*44704f69SBart Van Assche case 8:
7267*44704f69SBart Van Assche printf(" Media motion (head) hours since last successful "
7268*44704f69SBart Van Assche "cleaning operation:");
7269*44704f69SBart Van Assche break;
7270*44704f69SBart Van Assche case 9:
7271*44704f69SBart Van Assche printf(" Media motion (head) hours since 2nd to last "
7272*44704f69SBart Van Assche "successful cleaning:");
7273*44704f69SBart Van Assche break;
7274*44704f69SBart Van Assche case 0xa:
7275*44704f69SBart Van Assche printf(" Media motion (head) hours since 3rd to last "
7276*44704f69SBart Van Assche "successful cleaning:");
7277*44704f69SBart Van Assche break;
7278*44704f69SBart Van Assche case 0xb:
7279*44704f69SBart Van Assche printf(" Lifetime power on hours when last operator "
7280*44704f69SBart Van Assche "initiated forced reset\n and/or emergency "
7281*44704f69SBart Van Assche "eject occurred:");
7282*44704f69SBart Van Assche break;
7283*44704f69SBart Van Assche case 0xc:
7284*44704f69SBart Van Assche printf(" Lifetime power cycles:");
7285*44704f69SBart Van Assche break;
7286*44704f69SBart Van Assche case 0xd:
7287*44704f69SBart Van Assche printf(" Volume loads since last parameter reset:");
7288*44704f69SBart Van Assche break;
7289*44704f69SBart Van Assche case 0xe:
7290*44704f69SBart Van Assche printf(" Hard write errors:");
7291*44704f69SBart Van Assche break;
7292*44704f69SBart Van Assche case 0xf:
7293*44704f69SBart Van Assche printf(" Hard read errors:");
7294*44704f69SBart Van Assche break;
7295*44704f69SBart Van Assche case 0x10:
7296*44704f69SBart Van Assche printf(" Duty cycle sample time (ms):");
7297*44704f69SBart Van Assche break;
7298*44704f69SBart Van Assche case 0x11:
7299*44704f69SBart Van Assche printf(" Read duty cycle:");
7300*44704f69SBart Van Assche break;
7301*44704f69SBart Van Assche case 0x12:
7302*44704f69SBart Van Assche printf(" Write duty cycle:");
7303*44704f69SBart Van Assche break;
7304*44704f69SBart Van Assche case 0x13:
7305*44704f69SBart Van Assche printf(" Activity duty cycle:");
7306*44704f69SBart Van Assche break;
7307*44704f69SBart Van Assche case 0x14:
7308*44704f69SBart Van Assche printf(" Volume not present duty cycle:");
7309*44704f69SBart Van Assche break;
7310*44704f69SBart Van Assche case 0x15:
7311*44704f69SBart Van Assche printf(" Ready duty cycle:");
7312*44704f69SBart Van Assche break;
7313*44704f69SBart Van Assche case 0x16:
7314*44704f69SBart Van Assche printf(" MBs transferred from app client in duty cycle "
7315*44704f69SBart Van Assche "sample time:");
7316*44704f69SBart Van Assche break;
7317*44704f69SBart Van Assche case 0x17:
7318*44704f69SBart Van Assche printf(" MBs transferred to app client in duty cycle "
7319*44704f69SBart Van Assche "sample time:");
7320*44704f69SBart Van Assche break;
7321*44704f69SBart Van Assche case 0x40:
7322*44704f69SBart Van Assche printf(" Drive manufacturer's serial number:");
7323*44704f69SBart Van Assche break;
7324*44704f69SBart Van Assche case 0x41:
7325*44704f69SBart Van Assche printf(" Drive serial number:");
7326*44704f69SBart Van Assche break;
7327*44704f69SBart Van Assche case 0x42: /* added ssc5r02b */
7328*44704f69SBart Van Assche vl_num = false;
7329*44704f69SBart Van Assche printf(" Manufacturing date (yyyymmdd): %.*s\n", pl - 4,
7330*44704f69SBart Van Assche bp + 4);
7331*44704f69SBart Van Assche break;
7332*44704f69SBart Van Assche case 0x43: /* added ssc5r02b */
7333*44704f69SBart Van Assche vl_num = false;
7334*44704f69SBart Van Assche printf(" Manufacturing date (yyyyww): %.*s\n", pl - 4,
7335*44704f69SBart Van Assche bp + 4);
7336*44704f69SBart Van Assche break;
7337*44704f69SBart Van Assche case 0x80:
7338*44704f69SBart Van Assche printf(" Medium removal prevented:");
7339*44704f69SBart Van Assche break;
7340*44704f69SBart Van Assche case 0x81:
7341*44704f69SBart Van Assche printf(" Maximum recommended mechanism temperature "
7342*44704f69SBart Van Assche "exceeded:");
7343*44704f69SBart Van Assche break;
7344*44704f69SBart Van Assche default:
7345*44704f69SBart Van Assche vl_num = false;
7346*44704f69SBart Van Assche printf(" Reserved %s [0x%x] data in hex:\n", param_c, pc);
7347*44704f69SBart Van Assche hex2fp(bp + 4, pl - 4, " ", op->hex2str_oformat, stdout);
7348*44704f69SBart Van Assche break;
7349*44704f69SBart Van Assche }
7350*44704f69SBart Van Assche if (vl_num)
7351*44704f69SBart Van Assche printf(" %" PRIu64 "\n", sg_get_unaligned_be(pl - 4, bp + 4));
7352*44704f69SBart Van Assche } else { /* parameter_code >= 0x1000 */
7353*44704f69SBart Van Assche int k;
7354*44704f69SBart Van Assche const uint8_t * p = bp + 4;
7355*44704f69SBart Van Assche
7356*44704f69SBart Van Assche switch (pc) {
7357*44704f69SBart Van Assche case 0x1000:
7358*44704f69SBart Van Assche printf(" Media motion (head) hours for each medium type:\n");
7359*44704f69SBart Van Assche for (k = 0; ((pl - 4) - k) >= 8; k += 8, p += 8)
7360*44704f69SBart Van Assche printf(" [%d] Density code: %u, Medium type: 0x%x, "
7361*44704f69SBart Van Assche "hours: %u\n", ((k / 8) + 1), p[2], p[3],
7362*44704f69SBart Van Assche sg_get_unaligned_be32(p + 4));
7363*44704f69SBart Van Assche break;
7364*44704f69SBart Van Assche default:
7365*44704f69SBart Van Assche if (pc >= 0x8000) {
7366*44704f69SBart Van Assche if (op->exclude_vendor) {
7367*44704f69SBart Van Assche if ((op->verbose > 0) && (0 == op->do_brief) &&
7368*44704f69SBart Van Assche (! evsm_output)) {
7369*44704f69SBart Van Assche evsm_output = true;
7370*44704f69SBart Van Assche printf(" Vendor specific parameter(s) being "
7371*44704f69SBart Van Assche "ignored\n");
7372*44704f69SBart Van Assche }
7373*44704f69SBart Van Assche } else
7374*44704f69SBart Van Assche printf(" Vendor specific parameter [0x%x], dump in "
7375*44704f69SBart Van Assche "hex:\n", pc);
7376*44704f69SBart Van Assche } else {
7377*44704f69SBart Van Assche printf(" Reserved parameter [0x%x], dump in hex:\n", pc);
7378*44704f69SBart Van Assche hex2fp(bp + 4, pl - 4, " ", op->hex2str_oformat,
7379*44704f69SBart Van Assche stdout);
7380*44704f69SBart Van Assche }
7381*44704f69SBart Van Assche break;
7382*44704f69SBart Van Assche }
7383*44704f69SBart Van Assche }
7384*44704f69SBart Van Assche if (op->do_pcb)
7385*44704f69SBart Van Assche printf(" <%s>\n", get_pcb_str(bp[2], str, sizeof(str)));
7386*44704f69SBart Van Assche filter_chk:
7387*44704f69SBart Van Assche if (op->filter_given)
7388*44704f69SBart Van Assche break;
7389*44704f69SBart Van Assche skip:
7390*44704f69SBart Van Assche num -= pl;
7391*44704f69SBart Van Assche bp += pl;
7392*44704f69SBart Van Assche }
7393*44704f69SBart Van Assche return true;
7394*44704f69SBart Van Assche }
7395*44704f69SBart Van Assche
7396*44704f69SBart Van Assche /* Media changer statistics 0x14 <mcs> for media changer */
7397*44704f69SBart Van Assche static bool
show_media_stats_page(const uint8_t * resp,int len,struct opts_t * op,sgj_opaque_p jop)7398*44704f69SBart Van Assche show_media_stats_page(const uint8_t * resp, int len, struct opts_t * op,
7399*44704f69SBart Van Assche sgj_opaque_p jop)
7400*44704f69SBart Van Assche {
7401*44704f69SBart Van Assche int num, pl, pc;
7402*44704f69SBart Van Assche const uint8_t * bp;
7403*44704f69SBart Van Assche uint64_t ull;
7404*44704f69SBart Van Assche char str[PCB_STR_LEN];
7405*44704f69SBart Van Assche
7406*44704f69SBart Van Assche if (jop) { };
7407*44704f69SBart Van Assche if (op->verbose || ((! op->do_raw) && (0 == op->do_hex)))
7408*44704f69SBart Van Assche printf("Media statistics page (smc-3)\n");
7409*44704f69SBart Van Assche num = len - 4;
7410*44704f69SBart Van Assche bp = &resp[0] + 4;
7411*44704f69SBart Van Assche while (num > 3) {
7412*44704f69SBart Van Assche pc = sg_get_unaligned_be16(bp + 0);
7413*44704f69SBart Van Assche pl = bp[3] + 4;
7414*44704f69SBart Van Assche if (op->filter_given) {
7415*44704f69SBart Van Assche if (pc != op->filter)
7416*44704f69SBart Van Assche goto skip;
7417*44704f69SBart Van Assche }
7418*44704f69SBart Van Assche if (op->do_raw) {
7419*44704f69SBart Van Assche dStrRaw(bp, pl);
7420*44704f69SBart Van Assche goto filter_chk;
7421*44704f69SBart Van Assche } else if (op->do_hex) {
7422*44704f69SBart Van Assche hex2stdout(bp, pl, op->dstrhex_no_ascii);
7423*44704f69SBart Van Assche goto filter_chk;
7424*44704f69SBart Van Assche }
7425*44704f69SBart Van Assche ull = sg_get_unaligned_be(pl - 4, bp + 4);
7426*44704f69SBart Van Assche switch (pc) {
7427*44704f69SBart Van Assche case 0:
7428*44704f69SBart Van Assche printf(" Number of moves: %" PRIu64 "\n", ull);
7429*44704f69SBart Van Assche break;
7430*44704f69SBart Van Assche case 1:
7431*44704f69SBart Van Assche printf(" Number of picks: %" PRIu64 "\n", ull);
7432*44704f69SBart Van Assche break;
7433*44704f69SBart Van Assche case 2:
7434*44704f69SBart Van Assche printf(" Number of pick retries: %" PRIu64 "\n", ull);
7435*44704f69SBart Van Assche break;
7436*44704f69SBart Van Assche case 3:
7437*44704f69SBart Van Assche printf(" Number of places: %" PRIu64 "\n", ull);
7438*44704f69SBart Van Assche break;
7439*44704f69SBart Van Assche case 4:
7440*44704f69SBart Van Assche printf(" Number of place retries: %" PRIu64 "\n", ull);
7441*44704f69SBart Van Assche break;
7442*44704f69SBart Van Assche case 5:
7443*44704f69SBart Van Assche printf(" Number of volume tags read by volume "
7444*44704f69SBart Van Assche "tag reader: %" PRIu64 "\n", ull);
7445*44704f69SBart Van Assche break;
7446*44704f69SBart Van Assche case 6:
7447*44704f69SBart Van Assche printf(" Number of invalid volume tags returned by "
7448*44704f69SBart Van Assche "volume tag reader: %" PRIu64 "\n", ull);
7449*44704f69SBart Van Assche break;
7450*44704f69SBart Van Assche case 7:
7451*44704f69SBart Van Assche printf(" Number of library door opens: %" PRIu64 "\n", ull);
7452*44704f69SBart Van Assche break;
7453*44704f69SBart Van Assche case 8:
7454*44704f69SBart Van Assche printf(" Number of import/export door opens: %" PRIu64 "\n",
7455*44704f69SBart Van Assche ull);
7456*44704f69SBart Van Assche break;
7457*44704f69SBart Van Assche case 9:
7458*44704f69SBart Van Assche printf(" Number of physical inventory scans: %" PRIu64 "\n",
7459*44704f69SBart Van Assche ull);
7460*44704f69SBart Van Assche break;
7461*44704f69SBart Van Assche case 0xa:
7462*44704f69SBart Van Assche printf(" Number of medium transport unrecovered errors: "
7463*44704f69SBart Van Assche "%" PRIu64 "\n", ull);
7464*44704f69SBart Van Assche break;
7465*44704f69SBart Van Assche case 0xb:
7466*44704f69SBart Van Assche printf(" Number of medium transport recovered errors: "
7467*44704f69SBart Van Assche "%" PRIu64 "\n", ull);
7468*44704f69SBart Van Assche break;
7469*44704f69SBart Van Assche case 0xc:
7470*44704f69SBart Van Assche printf(" Number of medium transport X axis translation "
7471*44704f69SBart Van Assche "unrecovered errors: %" PRIu64 "\n", ull);
7472*44704f69SBart Van Assche break;
7473*44704f69SBart Van Assche case 0xd:
7474*44704f69SBart Van Assche printf(" Number of medium transport X axis translation "
7475*44704f69SBart Van Assche "recovered errors: %" PRIu64 "\n", ull);
7476*44704f69SBart Van Assche break;
7477*44704f69SBart Van Assche case 0xe:
7478*44704f69SBart Van Assche printf(" Number of medium transport Y axis translation "
7479*44704f69SBart Van Assche "unrecovered errors: %" PRIu64 "\n", ull);
7480*44704f69SBart Van Assche break;
7481*44704f69SBart Van Assche case 0xf:
7482*44704f69SBart Van Assche printf(" Number of medium transport Y axis translation "
7483*44704f69SBart Van Assche "recovered errors: %" PRIu64 "\n", ull);
7484*44704f69SBart Van Assche break;
7485*44704f69SBart Van Assche case 0x10:
7486*44704f69SBart Van Assche printf(" Number of medium transport Z axis translation "
7487*44704f69SBart Van Assche "unrecovered errors: %" PRIu64 "\n", ull);
7488*44704f69SBart Van Assche break;
7489*44704f69SBart Van Assche case 0x11:
7490*44704f69SBart Van Assche printf(" Number of medium transport Z axis translation "
7491*44704f69SBart Van Assche "recovered errors: %" PRIu64 "\n", ull);
7492*44704f69SBart Van Assche break;
7493*44704f69SBart Van Assche case 0x12:
7494*44704f69SBart Van Assche printf(" Number of medium transport rotational translation "
7495*44704f69SBart Van Assche "unrecovered errors: %" PRIu64 "\n", ull);
7496*44704f69SBart Van Assche break;
7497*44704f69SBart Van Assche case 0x13:
7498*44704f69SBart Van Assche printf(" Number of medium transport rotational translation "
7499*44704f69SBart Van Assche "recovered errors: %" PRIu64 "\n", ull);
7500*44704f69SBart Van Assche break;
7501*44704f69SBart Van Assche case 0x14:
7502*44704f69SBart Van Assche printf(" Number of medium transport inversion translation "
7503*44704f69SBart Van Assche "unrecovered errors: %" PRIu64 "\n", ull);
7504*44704f69SBart Van Assche break;
7505*44704f69SBart Van Assche case 0x15:
7506*44704f69SBart Van Assche printf(" Number of medium transport inversion translation "
7507*44704f69SBart Van Assche "recovered errors: %" PRIu64 "\n", ull);
7508*44704f69SBart Van Assche break;
7509*44704f69SBart Van Assche case 0x16:
7510*44704f69SBart Van Assche printf(" Number of medium transport auxiliary translation "
7511*44704f69SBart Van Assche "unrecovered errors: %" PRIu64 "\n", ull);
7512*44704f69SBart Van Assche break;
7513*44704f69SBart Van Assche case 0x17:
7514*44704f69SBart Van Assche printf(" Number of medium transport auxiliary translation "
7515*44704f69SBart Van Assche "recovered errors: %" PRIu64 "\n", ull);
7516*44704f69SBart Van Assche break;
7517*44704f69SBart Van Assche default:
7518*44704f69SBart Van Assche printf(" Reserved parameter [0x%x] value: %" PRIu64 "\n",
7519*44704f69SBart Van Assche pc, ull);
7520*44704f69SBart Van Assche break;
7521*44704f69SBart Van Assche }
7522*44704f69SBart Van Assche if (op->do_pcb)
7523*44704f69SBart Van Assche printf(" <%s>\n", get_pcb_str(bp[2], str, sizeof(str)));
7524*44704f69SBart Van Assche filter_chk:
7525*44704f69SBart Van Assche if (op->filter_given)
7526*44704f69SBart Van Assche break;
7527*44704f69SBart Van Assche skip:
7528*44704f69SBart Van Assche num -= pl;
7529*44704f69SBart Van Assche bp += pl;
7530*44704f69SBart Van Assche }
7531*44704f69SBart Van Assche return true;
7532*44704f69SBart Van Assche }
7533*44704f69SBart Van Assche
7534*44704f69SBart Van Assche /* Element statistics page, 0x15 <els> for SMC */
7535*44704f69SBart Van Assche static bool
show_element_stats_page(const uint8_t * resp,int len,struct opts_t * op,sgj_opaque_p jop)7536*44704f69SBart Van Assche show_element_stats_page(const uint8_t * resp, int len,
7537*44704f69SBart Van Assche struct opts_t * op, sgj_opaque_p jop)
7538*44704f69SBart Van Assche {
7539*44704f69SBart Van Assche int num, pl, pc;
7540*44704f69SBart Van Assche unsigned int v;
7541*44704f69SBart Van Assche const uint8_t * bp;
7542*44704f69SBart Van Assche char str[PCB_STR_LEN];
7543*44704f69SBart Van Assche
7544*44704f69SBart Van Assche if (jop) { };
7545*44704f69SBart Van Assche if (op->verbose || ((! op->do_raw) && (0 == op->do_hex)))
7546*44704f69SBart Van Assche printf("Element statistics page (smc-3) [0x15]\n");
7547*44704f69SBart Van Assche num = len - 4;
7548*44704f69SBart Van Assche bp = &resp[0] + 4;
7549*44704f69SBart Van Assche while (num > 3) {
7550*44704f69SBart Van Assche pc = sg_get_unaligned_be16(bp + 0);
7551*44704f69SBart Van Assche pl = bp[3] + 4;
7552*44704f69SBart Van Assche if (op->filter_given) {
7553*44704f69SBart Van Assche if (pc != op->filter)
7554*44704f69SBart Van Assche goto skip;
7555*44704f69SBart Van Assche }
7556*44704f69SBart Van Assche if (op->do_raw) {
7557*44704f69SBart Van Assche dStrRaw(bp, pl);
7558*44704f69SBart Van Assche goto filter_chk;
7559*44704f69SBart Van Assche } else if (op->do_hex) {
7560*44704f69SBart Van Assche hex2stdout(bp, pl, op->dstrhex_no_ascii);
7561*44704f69SBart Van Assche goto filter_chk;
7562*44704f69SBart Van Assche }
7563*44704f69SBart Van Assche printf(" Element address: %d\n", pc);
7564*44704f69SBart Van Assche v = sg_get_unaligned_be32(bp + 4);
7565*44704f69SBart Van Assche printf(" Number of places: %u\n", v);
7566*44704f69SBart Van Assche v = sg_get_unaligned_be32(bp + 8);
7567*44704f69SBart Van Assche printf(" Number of place retries: %u\n", v);
7568*44704f69SBart Van Assche v = sg_get_unaligned_be32(bp + 12);
7569*44704f69SBart Van Assche printf(" Number of picks: %u\n", v);
7570*44704f69SBart Van Assche v = sg_get_unaligned_be32(bp + 16);
7571*44704f69SBart Van Assche printf(" Number of pick retries: %u\n", v);
7572*44704f69SBart Van Assche v = sg_get_unaligned_be32(bp + 20);
7573*44704f69SBart Van Assche printf(" Number of determined volume identifiers: %u\n", v);
7574*44704f69SBart Van Assche v = sg_get_unaligned_be32(bp + 24);
7575*44704f69SBart Van Assche printf(" Number of unreadable volume identifiers: %u\n", v);
7576*44704f69SBart Van Assche if (op->do_pcb)
7577*44704f69SBart Van Assche printf(" <%s>\n", get_pcb_str(bp[2], str, sizeof(str)));
7578*44704f69SBart Van Assche filter_chk:
7579*44704f69SBart Van Assche if (op->filter_given)
7580*44704f69SBart Van Assche break;
7581*44704f69SBart Van Assche skip:
7582*44704f69SBart Van Assche num -= pl;
7583*44704f69SBart Van Assche bp += pl;
7584*44704f69SBart Van Assche }
7585*44704f69SBart Van Assche return true;
7586*44704f69SBart Van Assche }
7587*44704f69SBart Van Assche
7588*44704f69SBart Van Assche /* Tape diagnostic data [0x16] <tdd> for tape */
7589*44704f69SBart Van Assche static bool
show_tape_diag_data_page(const uint8_t * resp,int len,struct opts_t * op,sgj_opaque_p jop)7590*44704f69SBart Van Assche show_tape_diag_data_page(const uint8_t * resp, int len,
7591*44704f69SBart Van Assche struct opts_t * op, sgj_opaque_p jop)
7592*44704f69SBart Van Assche {
7593*44704f69SBart Van Assche int k, n, num, pl, pc;
7594*44704f69SBart Van Assche unsigned int v;
7595*44704f69SBart Van Assche const uint8_t * bp;
7596*44704f69SBart Van Assche char str[PCB_STR_LEN];
7597*44704f69SBart Van Assche char b[512];
7598*44704f69SBart Van Assche
7599*44704f69SBart Van Assche if (jop) { };
7600*44704f69SBart Van Assche if (op->verbose || ((! op->do_raw) && (0 == op->do_hex)))
7601*44704f69SBart Van Assche printf("Tape diagnostics data page (ssc-3) [0x16]\n");
7602*44704f69SBart Van Assche num = len - 4;
7603*44704f69SBart Van Assche bp = &resp[0] + 4;
7604*44704f69SBart Van Assche while (num > 3) {
7605*44704f69SBart Van Assche pc = sg_get_unaligned_be16(bp + 0);
7606*44704f69SBart Van Assche pl = bp[3] + 4;
7607*44704f69SBart Van Assche if (op->filter_given) {
7608*44704f69SBart Van Assche if (pc != op->filter)
7609*44704f69SBart Van Assche goto skip;
7610*44704f69SBart Van Assche }
7611*44704f69SBart Van Assche if (op->do_raw) {
7612*44704f69SBart Van Assche dStrRaw(bp, pl);
7613*44704f69SBart Van Assche goto filter_chk;
7614*44704f69SBart Van Assche } else if (op->do_hex) {
7615*44704f69SBart Van Assche hex2stdout(bp, pl, op->dstrhex_no_ascii);
7616*44704f69SBart Van Assche goto filter_chk;
7617*44704f69SBart Van Assche }
7618*44704f69SBart Van Assche printf(" %s: %d\n", param_c, pc);
7619*44704f69SBart Van Assche printf(" Density code: 0x%x\n", bp[6]);
7620*44704f69SBart Van Assche printf(" Medium type: 0x%x\n", bp[7]);
7621*44704f69SBart Van Assche v = sg_get_unaligned_be32(bp + 8);
7622*44704f69SBart Van Assche printf(" Lifetime media motion hours: %u\n", v);
7623*44704f69SBart Van Assche printf(" Repeat: %d\n", !!(bp[13] & 0x80));
7624*44704f69SBart Van Assche v = bp[13] & 0xf;
7625*44704f69SBart Van Assche printf(" Sense key: 0x%x [%s]\n", v,
7626*44704f69SBart Van Assche sg_get_sense_key_str(v, sizeof(b), b));
7627*44704f69SBart Van Assche printf(" Additional sense code: 0x%x\n", bp[14]);
7628*44704f69SBart Van Assche printf(" Additional sense code qualifier: 0x%x\n", bp[15]);
7629*44704f69SBart Van Assche if (bp[14] || bp[15])
7630*44704f69SBart Van Assche printf(" [%s]\n", sg_get_asc_ascq_str(bp[14], bp[15],
7631*44704f69SBart Van Assche sizeof(b), b));
7632*44704f69SBart Van Assche v = sg_get_unaligned_be32(bp + 16);
7633*44704f69SBart Van Assche printf(" Vendor specific code qualifier: 0x%x\n", v);
7634*44704f69SBart Van Assche v = sg_get_unaligned_be32(bp + 20);
7635*44704f69SBart Van Assche printf(" Product revision level: %u\n", v);
7636*44704f69SBart Van Assche v = sg_get_unaligned_be32(bp + 24);
7637*44704f69SBart Van Assche printf(" Hours since last clean: %u\n", v);
7638*44704f69SBart Van Assche printf(" Operation code: 0x%x\n", bp[28]);
7639*44704f69SBart Van Assche printf(" Service action: 0x%x\n", bp[29] & 0xf);
7640*44704f69SBart Van Assche // Check Medium id number for all zeros
7641*44704f69SBart Van Assche // ssc4r03.pdf does not define this field, why? xxxxxx
7642*44704f69SBart Van Assche if (sg_all_zeros(bp + 32, 32))
7643*44704f69SBart Van Assche printf(" Medium id number is 32 bytes of zero\n");
7644*44704f69SBart Van Assche else {
7645*44704f69SBart Van Assche hex2str(bp + 32, 32, " ", 0 /* with ASCII */, sizeof(b), b);
7646*44704f69SBart Van Assche printf(" Medium id number (in hex):\n%s", b);
7647*44704f69SBart Van Assche }
7648*44704f69SBart Van Assche printf(" Timestamp origin: 0x%x\n", bp[64] & 0xf);
7649*44704f69SBart Van Assche // Check Timestamp for all zeros
7650*44704f69SBart Van Assche if (sg_all_zeros(bp + 66, 6))
7651*44704f69SBart Van Assche printf(" Timestamp is all zeros:\n");
7652*44704f69SBart Van Assche else {
7653*44704f69SBart Van Assche hex2str(bp + 66, 6, NULL, op->hex2str_oformat, sizeof(b), b);
7654*44704f69SBart Van Assche printf(" Timestamp: %s", b);
7655*44704f69SBart Van Assche }
7656*44704f69SBart Van Assche if (pl > 72) {
7657*44704f69SBart Van Assche n = pl - 72;
7658*44704f69SBart Van Assche k = hex2str(bp + 72, n, " ", op->hex2str_oformat,
7659*44704f69SBart Van Assche sizeof(b), b);
7660*44704f69SBart Van Assche printf(" Vendor specific:\n");
7661*44704f69SBart Van Assche printf("%s", b);
7662*44704f69SBart Van Assche if (k >= (int)sizeof(b) - 1)
7663*44704f69SBart Van Assche printf(" <truncated>\n");
7664*44704f69SBart Van Assche }
7665*44704f69SBart Van Assche if (op->do_pcb)
7666*44704f69SBart Van Assche printf(" <%s>\n", get_pcb_str(bp[2], str, sizeof(str)));
7667*44704f69SBart Van Assche filter_chk:
7668*44704f69SBart Van Assche if (op->filter_given)
7669*44704f69SBart Van Assche break;
7670*44704f69SBart Van Assche skip:
7671*44704f69SBart Van Assche num -= pl;
7672*44704f69SBart Van Assche bp += pl;
7673*44704f69SBart Van Assche }
7674*44704f69SBart Van Assche return true;
7675*44704f69SBart Van Assche }
7676*44704f69SBart Van Assche
7677*44704f69SBart Van Assche /* Media changer diagnostic data [0x16] <mcdd> for media changer */
7678*44704f69SBart Van Assche static bool
show_mchanger_diag_data_page(const uint8_t * resp,int len,struct opts_t * op,sgj_opaque_p jop)7679*44704f69SBart Van Assche show_mchanger_diag_data_page(const uint8_t * resp, int len,
7680*44704f69SBart Van Assche struct opts_t * op, sgj_opaque_p jop)
7681*44704f69SBart Van Assche {
7682*44704f69SBart Van Assche int num, pl, pc;
7683*44704f69SBart Van Assche unsigned int v;
7684*44704f69SBart Van Assche const uint8_t * bp;
7685*44704f69SBart Van Assche char str[PCB_STR_LEN];
7686*44704f69SBart Van Assche char b[512];
7687*44704f69SBart Van Assche
7688*44704f69SBart Van Assche if (jop) { };
7689*44704f69SBart Van Assche if (op->verbose || ((! op->do_raw) && (0 == op->do_hex)))
7690*44704f69SBart Van Assche printf("Media changer diagnostics data page (smc-3) [0x16]\n");
7691*44704f69SBart Van Assche num = len - 4;
7692*44704f69SBart Van Assche bp = &resp[0] + 4;
7693*44704f69SBart Van Assche while (num > 3) {
7694*44704f69SBart Van Assche pc = sg_get_unaligned_be16(bp + 0);
7695*44704f69SBart Van Assche pl = bp[3] + 4;
7696*44704f69SBart Van Assche if (op->filter_given) {
7697*44704f69SBart Van Assche if (pc != op->filter)
7698*44704f69SBart Van Assche goto skip;
7699*44704f69SBart Van Assche }
7700*44704f69SBart Van Assche if (op->do_raw) {
7701*44704f69SBart Van Assche dStrRaw(bp, pl);
7702*44704f69SBart Van Assche goto filter_chk;
7703*44704f69SBart Van Assche } else if (op->do_hex) {
7704*44704f69SBart Van Assche hex2stdout(bp, pl, op->dstrhex_no_ascii);
7705*44704f69SBart Van Assche goto filter_chk;
7706*44704f69SBart Van Assche }
7707*44704f69SBart Van Assche printf(" %s: %d\n", param_c, pc);
7708*44704f69SBart Van Assche printf(" Repeat: %d\n", !!(bp[5] & 0x80));
7709*44704f69SBart Van Assche v = bp[5] & 0xf;
7710*44704f69SBart Van Assche printf(" Sense key: 0x%x [%s]\n", v,
7711*44704f69SBart Van Assche sg_get_sense_key_str(v, sizeof(b), b));
7712*44704f69SBart Van Assche printf(" Additional sense code: 0x%x\n", bp[6]);
7713*44704f69SBart Van Assche printf(" Additional sense code qualifier: 0x%x\n", bp[7]);
7714*44704f69SBart Van Assche if (bp[6] || bp[7])
7715*44704f69SBart Van Assche printf(" [%s]\n", sg_get_asc_ascq_str(bp[6], bp[7],
7716*44704f69SBart Van Assche sizeof(b), b));
7717*44704f69SBart Van Assche v = sg_get_unaligned_be32(bp + 8);
7718*44704f69SBart Van Assche printf(" Vendor specific code qualifier: 0x%x\n", v);
7719*44704f69SBart Van Assche v = sg_get_unaligned_be32(bp + 12);
7720*44704f69SBart Van Assche printf(" Product revision level: %u\n", v);
7721*44704f69SBart Van Assche v = sg_get_unaligned_be32(bp + 16);
7722*44704f69SBart Van Assche printf(" Number of moves: %u\n", v);
7723*44704f69SBart Van Assche v = sg_get_unaligned_be32(bp + 20);
7724*44704f69SBart Van Assche printf(" Number of pick: %u\n", v);
7725*44704f69SBart Van Assche v = sg_get_unaligned_be32(bp + 24);
7726*44704f69SBart Van Assche printf(" Number of pick retries: %u\n", v);
7727*44704f69SBart Van Assche v = sg_get_unaligned_be32(bp + 28);
7728*44704f69SBart Van Assche printf(" Number of places: %u\n", v);
7729*44704f69SBart Van Assche v = sg_get_unaligned_be32(bp + 32);
7730*44704f69SBart Van Assche printf(" Number of place retries: %u\n", v);
7731*44704f69SBart Van Assche v = sg_get_unaligned_be32(bp + 36);
7732*44704f69SBart Van Assche printf(" Number of determined volume identifiers: %u\n", v);
7733*44704f69SBart Van Assche v = sg_get_unaligned_be32(bp + 40);
7734*44704f69SBart Van Assche printf(" Number of unreadable volume identifiers: %u\n", v);
7735*44704f69SBart Van Assche printf(" Operation code: 0x%x\n", bp[44]);
7736*44704f69SBart Van Assche printf(" Service action: 0x%x\n", bp[45] & 0xf);
7737*44704f69SBart Van Assche printf(" Media changer error type: 0x%x\n", bp[46]);
7738*44704f69SBart Van Assche printf(" MTAV: %d\n", !!(bp[47] & 0x8));
7739*44704f69SBart Van Assche printf(" IAV: %d\n", !!(bp[47] & 0x4));
7740*44704f69SBart Van Assche printf(" LSAV: %d\n", !!(bp[47] & 0x2));
7741*44704f69SBart Van Assche printf(" DAV: %d\n", !!(bp[47] & 0x1));
7742*44704f69SBart Van Assche v = sg_get_unaligned_be16(bp + 48);
7743*44704f69SBart Van Assche printf(" Medium transport address: 0x%x\n", v);
7744*44704f69SBart Van Assche v = sg_get_unaligned_be16(bp + 50);
7745*44704f69SBart Van Assche printf(" Initial address: 0x%x\n", v);
7746*44704f69SBart Van Assche v = sg_get_unaligned_be16(bp + 52);
7747*44704f69SBart Van Assche printf(" Last successful address: 0x%x\n", v);
7748*44704f69SBart Van Assche v = sg_get_unaligned_be16(bp + 54);
7749*44704f69SBart Van Assche printf(" Destination address: 0x%x\n", v);
7750*44704f69SBart Van Assche if (pl > 91) {
7751*44704f69SBart Van Assche printf(" Volume tag information:\n");
7752*44704f69SBart Van Assche hex2fp(bp + 56, 36, " ", op->hex2str_oformat, stdout);
7753*44704f69SBart Van Assche }
7754*44704f69SBart Van Assche if (pl > 99) {
7755*44704f69SBart Van Assche printf(" Timestamp origin: 0x%x\n", bp[92] & 0xf);
7756*44704f69SBart Van Assche printf(" Timestamp:\n");
7757*44704f69SBart Van Assche hex2fp(bp + 94, 6, " ", op->hex2str_oformat, stdout);
7758*44704f69SBart Van Assche }
7759*44704f69SBart Van Assche if (op->do_pcb)
7760*44704f69SBart Van Assche printf(" <%s>\n", get_pcb_str(bp[2], str, sizeof(str)));
7761*44704f69SBart Van Assche filter_chk:
7762*44704f69SBart Van Assche if (op->filter_given)
7763*44704f69SBart Van Assche break;
7764*44704f69SBart Van Assche skip:
7765*44704f69SBart Van Assche num -= pl;
7766*44704f69SBart Van Assche bp += pl;
7767*44704f69SBart Van Assche }
7768*44704f69SBart Van Assche return true;
7769*44704f69SBart Van Assche }
7770*44704f69SBart Van Assche
7771*44704f69SBart Van Assche /* Helper for show_volume_stats_pages() */
7772*44704f69SBart Van Assche static void
volume_stats_partition(const uint8_t * xp,int len,bool pr_in_hex)7773*44704f69SBart Van Assche volume_stats_partition(const uint8_t * xp, int len, bool pr_in_hex)
7774*44704f69SBart Van Assche {
7775*44704f69SBart Van Assche uint64_t ull;
7776*44704f69SBart Van Assche
7777*44704f69SBart Van Assche while (len > 3) {
7778*44704f69SBart Van Assche bool all_ffs, ffs_last_fe;
7779*44704f69SBart Van Assche int dl, pn;
7780*44704f69SBart Van Assche
7781*44704f69SBart Van Assche dl = xp[0] + 1;
7782*44704f69SBart Van Assche if (dl < 3)
7783*44704f69SBart Van Assche return;
7784*44704f69SBart Van Assche pn = sg_get_unaligned_be16(xp + 2);
7785*44704f69SBart Van Assche ffs_last_fe = false;
7786*44704f69SBart Van Assche all_ffs = false;
7787*44704f69SBart Van Assche if (sg_all_ffs(xp + 4, dl - 3)) {
7788*44704f69SBart Van Assche switch (xp[4 + dl - 3]) {
7789*44704f69SBart Van Assche case 0xff:
7790*44704f69SBart Van Assche all_ffs = true;
7791*44704f69SBart Van Assche break;
7792*44704f69SBart Van Assche case 0xfe:
7793*44704f69SBart Van Assche ffs_last_fe = true;
7794*44704f69SBart Van Assche break;
7795*44704f69SBart Van Assche default:
7796*44704f69SBart Van Assche break;
7797*44704f69SBart Van Assche }
7798*44704f69SBart Van Assche }
7799*44704f69SBart Van Assche if (! (all_ffs || ffs_last_fe)) {
7800*44704f69SBart Van Assche ull = sg_get_unaligned_be(dl - 4, xp + 4);
7801*44704f69SBart Van Assche if (pr_in_hex)
7802*44704f69SBart Van Assche printf(" partition number: %d, partition record data "
7803*44704f69SBart Van Assche "counter: 0x%" PRIx64 "\n", pn, ull);
7804*44704f69SBart Van Assche else
7805*44704f69SBart Van Assche printf(" partition number: %d, partition record data "
7806*44704f69SBart Van Assche "counter: %" PRIu64 "\n", pn, ull);
7807*44704f69SBart Van Assche } else if (all_ffs)
7808*44704f69SBart Van Assche printf(" partition number: %d, partition record data "
7809*44704f69SBart Van Assche "counter is all 0xFFs\n", pn);
7810*44704f69SBart Van Assche else /* ffs_last_fe is true */
7811*44704f69SBart Van Assche printf(" partition number: %d, partition record data "
7812*44704f69SBart Van Assche "counter is all 0xFFs apart\n from a trailing "
7813*44704f69SBart Van Assche "0xFE\n", pn);
7814*44704f69SBart Van Assche xp += dl;
7815*44704f69SBart Van Assche len -= dl;
7816*44704f69SBart Van Assche }
7817*44704f69SBart Van Assche }
7818*44704f69SBart Van Assche
7819*44704f69SBart Van Assche /* Helper for show_volume_stats_pages() */
7820*44704f69SBart Van Assche static void
volume_stats_history(const uint8_t * xp,int len)7821*44704f69SBart Van Assche volume_stats_history(const uint8_t * xp, int len)
7822*44704f69SBart Van Assche {
7823*44704f69SBart Van Assche while (len > 3) {
7824*44704f69SBart Van Assche int dl, mhi;
7825*44704f69SBart Van Assche
7826*44704f69SBart Van Assche dl = xp[0] + 1;
7827*44704f69SBart Van Assche if (dl < 4)
7828*44704f69SBart Van Assche return;
7829*44704f69SBart Van Assche mhi = sg_get_unaligned_be16(xp + 2);
7830*44704f69SBart Van Assche if (dl < 12)
7831*44704f69SBart Van Assche printf(" index: %d\n", mhi);
7832*44704f69SBart Van Assche else if (12 == dl)
7833*44704f69SBart Van Assche printf(" index: %d, vendor: %.8s\n", mhi, xp + 4);
7834*44704f69SBart Van Assche else
7835*44704f69SBart Van Assche printf(" index: %d, vendor: %.8s, unit serial number: %.*s\n",
7836*44704f69SBart Van Assche mhi, xp + 4, dl - 12, xp + 12);
7837*44704f69SBart Van Assche xp += dl;
7838*44704f69SBart Van Assche len -= dl;
7839*44704f69SBart Van Assche }
7840*44704f69SBart Van Assche }
7841*44704f69SBart Van Assche
7842*44704f69SBart Van Assche /* Volume Statistics log page and subpages (ssc-4) [0x17, 0x0-0xf] <vs> */
7843*44704f69SBart Van Assche static bool
show_volume_stats_pages(const uint8_t * resp,int len,struct opts_t * op,sgj_opaque_p jop)7844*44704f69SBart Van Assche show_volume_stats_pages(const uint8_t * resp, int len,
7845*44704f69SBart Van Assche struct opts_t * op, sgj_opaque_p jop)
7846*44704f69SBart Van Assche {
7847*44704f69SBart Van Assche bool skip_out = false;
7848*44704f69SBart Van Assche bool evsm_output = false;
7849*44704f69SBart Van Assche int num, pl, pc, subpg_code;
7850*44704f69SBart Van Assche bool spf;
7851*44704f69SBart Van Assche const uint8_t * bp;
7852*44704f69SBart Van Assche char str[PCB_STR_LEN];
7853*44704f69SBart Van Assche char b[512];
7854*44704f69SBart Van Assche
7855*44704f69SBart Van Assche if (jop) { };
7856*44704f69SBart Van Assche spf = !!(resp[0] & 0x40);
7857*44704f69SBart Van Assche subpg_code = spf ? resp[1] : NOT_SPG_SUBPG;
7858*44704f69SBart Van Assche if (op->verbose || ((! op->do_raw) && (0 == op->do_hex))) {
7859*44704f69SBart Van Assche if (subpg_code < 0x10)
7860*44704f69SBart Van Assche printf("Volume statistics page (ssc-4), subpage=%d\n",
7861*44704f69SBart Van Assche subpg_code);
7862*44704f69SBart Van Assche else {
7863*44704f69SBart Van Assche printf("Volume statistics page (ssc-4), subpage=%d; Reserved, "
7864*44704f69SBart Van Assche "skip\n", subpg_code);
7865*44704f69SBart Van Assche return false;
7866*44704f69SBart Van Assche }
7867*44704f69SBart Van Assche }
7868*44704f69SBart Van Assche num = len - 4;
7869*44704f69SBart Van Assche bp = &resp[0] + 4;
7870*44704f69SBart Van Assche while (num > 3) {
7871*44704f69SBart Van Assche pc = sg_get_unaligned_be16(bp + 0);
7872*44704f69SBart Van Assche pl = bp[3] + 4;
7873*44704f69SBart Van Assche if (op->filter_given) {
7874*44704f69SBart Van Assche if (pc != op->filter)
7875*44704f69SBart Van Assche goto skip;
7876*44704f69SBart Van Assche }
7877*44704f69SBart Van Assche if (op->do_raw) {
7878*44704f69SBart Van Assche dStrRaw(bp, pl);
7879*44704f69SBart Van Assche goto filter_chk;
7880*44704f69SBart Van Assche } else if (op->do_hex) {
7881*44704f69SBart Van Assche hex2stdout(bp, pl, op->dstrhex_no_ascii);
7882*44704f69SBart Van Assche goto filter_chk;
7883*44704f69SBart Van Assche }
7884*44704f69SBart Van Assche
7885*44704f69SBart Van Assche switch (pc) {
7886*44704f69SBart Van Assche case 0:
7887*44704f69SBart Van Assche printf(" Page valid: %" PRIu64 "\n",
7888*44704f69SBart Van Assche sg_get_unaligned_be(pl - 4, bp + 4));
7889*44704f69SBart Van Assche break;
7890*44704f69SBart Van Assche case 1:
7891*44704f69SBart Van Assche printf(" Thread count: %" PRIu64 "\n",
7892*44704f69SBart Van Assche sg_get_unaligned_be(pl - 4, bp + 4));
7893*44704f69SBart Van Assche break;
7894*44704f69SBart Van Assche case 2:
7895*44704f69SBart Van Assche printf(" Total data sets written: %" PRIu64 "\n",
7896*44704f69SBart Van Assche sg_get_unaligned_be(pl - 4, bp + 4));
7897*44704f69SBart Van Assche break;
7898*44704f69SBart Van Assche case 3:
7899*44704f69SBart Van Assche printf(" Total write retries: %" PRIu64 "\n",
7900*44704f69SBart Van Assche sg_get_unaligned_be(pl - 4, bp + 4));
7901*44704f69SBart Van Assche break;
7902*44704f69SBart Van Assche case 4:
7903*44704f69SBart Van Assche printf(" Total unrecovered write errors: %" PRIu64 "\n",
7904*44704f69SBart Van Assche sg_get_unaligned_be(pl - 4, bp + 4));
7905*44704f69SBart Van Assche break;
7906*44704f69SBart Van Assche case 5:
7907*44704f69SBart Van Assche printf(" Total suspended writes: %" PRIu64 "\n",
7908*44704f69SBart Van Assche sg_get_unaligned_be(pl - 4, bp + 4));
7909*44704f69SBart Van Assche break;
7910*44704f69SBart Van Assche case 6:
7911*44704f69SBart Van Assche printf(" Total fatal suspended writes: %" PRIu64 "\n",
7912*44704f69SBart Van Assche sg_get_unaligned_be(pl - 4, bp + 4));
7913*44704f69SBart Van Assche break;
7914*44704f69SBart Van Assche case 7:
7915*44704f69SBart Van Assche printf(" Total data sets read: %" PRIu64 "\n",
7916*44704f69SBart Van Assche sg_get_unaligned_be(pl - 4, bp + 4));
7917*44704f69SBart Van Assche break;
7918*44704f69SBart Van Assche case 8:
7919*44704f69SBart Van Assche printf(" Total read retries: %" PRIu64 "\n",
7920*44704f69SBart Van Assche sg_get_unaligned_be(pl - 4, bp + 4));
7921*44704f69SBart Van Assche break;
7922*44704f69SBart Van Assche case 9:
7923*44704f69SBart Van Assche printf(" Total unrecovered read errors: %" PRIu64 "\n",
7924*44704f69SBart Van Assche sg_get_unaligned_be(pl - 4, bp + 4));
7925*44704f69SBart Van Assche break;
7926*44704f69SBart Van Assche case 0xa:
7927*44704f69SBart Van Assche printf(" Total suspended reads: %" PRIu64 "\n",
7928*44704f69SBart Van Assche sg_get_unaligned_be(pl - 4, bp + 4));
7929*44704f69SBart Van Assche break;
7930*44704f69SBart Van Assche case 0xb:
7931*44704f69SBart Van Assche printf(" Total fatal suspended reads: %" PRIu64 "\n",
7932*44704f69SBart Van Assche sg_get_unaligned_be(pl - 4, bp + 4));
7933*44704f69SBart Van Assche break;
7934*44704f69SBart Van Assche case 0xc:
7935*44704f69SBart Van Assche printf(" Last mount unrecovered write errors: %" PRIu64 "\n",
7936*44704f69SBart Van Assche sg_get_unaligned_be(pl - 4, bp + 4));
7937*44704f69SBart Van Assche break;
7938*44704f69SBart Van Assche case 0xd:
7939*44704f69SBart Van Assche printf(" Last mount unrecovered read errors: %" PRIu64 "\n",
7940*44704f69SBart Van Assche sg_get_unaligned_be(pl - 4, bp + 4));
7941*44704f69SBart Van Assche break;
7942*44704f69SBart Van Assche case 0xe:
7943*44704f69SBart Van Assche printf(" Last mount megabytes written: %" PRIu64 "\n",
7944*44704f69SBart Van Assche sg_get_unaligned_be(pl - 4, bp + 4));
7945*44704f69SBart Van Assche break;
7946*44704f69SBart Van Assche case 0xf:
7947*44704f69SBart Van Assche printf(" Last mount megabytes read: %" PRIu64 "\n",
7948*44704f69SBart Van Assche sg_get_unaligned_be(pl - 4, bp + 4));
7949*44704f69SBart Van Assche break;
7950*44704f69SBart Van Assche case 0x10:
7951*44704f69SBart Van Assche printf(" Lifetime megabytes written: %" PRIu64 "\n",
7952*44704f69SBart Van Assche sg_get_unaligned_be(pl - 4, bp + 4));
7953*44704f69SBart Van Assche break;
7954*44704f69SBart Van Assche case 0x11:
7955*44704f69SBart Van Assche printf(" Lifetime megabytes read: %" PRIu64 "\n",
7956*44704f69SBart Van Assche sg_get_unaligned_be(pl - 4, bp + 4));
7957*44704f69SBart Van Assche break;
7958*44704f69SBart Van Assche case 0x12:
7959*44704f69SBart Van Assche printf(" Last load write compression ratio: %" PRIu64 "\n",
7960*44704f69SBart Van Assche sg_get_unaligned_be(pl - 4, bp + 4));
7961*44704f69SBart Van Assche break;
7962*44704f69SBart Van Assche case 0x13:
7963*44704f69SBart Van Assche printf(" Last load read compression ratio: %" PRIu64 "\n",
7964*44704f69SBart Van Assche sg_get_unaligned_be(pl - 4, bp + 4));
7965*44704f69SBart Van Assche break;
7966*44704f69SBart Van Assche case 0x14:
7967*44704f69SBart Van Assche printf(" Medium mount time: %" PRIu64 "\n",
7968*44704f69SBart Van Assche sg_get_unaligned_be(pl - 4, bp + 4));
7969*44704f69SBart Van Assche break;
7970*44704f69SBart Van Assche case 0x15:
7971*44704f69SBart Van Assche printf(" Medium ready time: %" PRIu64 "\n",
7972*44704f69SBart Van Assche sg_get_unaligned_be(pl - 4, bp + 4));
7973*44704f69SBart Van Assche break;
7974*44704f69SBart Van Assche case 0x16:
7975*44704f69SBart Van Assche printf(" Total native capacity [MB]: %s\n",
7976*44704f69SBart Van Assche num_or_unknown(bp + 4, pl - 4, false, b, sizeof(b)));
7977*44704f69SBart Van Assche break;
7978*44704f69SBart Van Assche case 0x17:
7979*44704f69SBart Van Assche printf(" Total used native capacity [MB]: %s\n",
7980*44704f69SBart Van Assche num_or_unknown(bp + 4, pl - 4, false, b, sizeof(b)));
7981*44704f69SBart Van Assche break;
7982*44704f69SBart Van Assche case 0x1a:
7983*44704f69SBart Van Assche printf(" Volume stop writes of forward wraps: %" PRIu64 "\n",
7984*44704f69SBart Van Assche sg_get_unaligned_be(pl - 4, bp + 4));
7985*44704f69SBart Van Assche break;
7986*44704f69SBart Van Assche case 0x1b:
7987*44704f69SBart Van Assche printf(" Volume stop writes of backward wraps: %" PRIu64 "\n",
7988*44704f69SBart Van Assche sg_get_unaligned_be(pl - 4, bp + 4));
7989*44704f69SBart Van Assche break;
7990*44704f69SBart Van Assche case 0x40:
7991*44704f69SBart Van Assche printf(" Volume serial number: %.*s\n", pl - 4, bp + 4);
7992*44704f69SBart Van Assche break;
7993*44704f69SBart Van Assche case 0x41:
7994*44704f69SBart Van Assche printf(" Tape lot identifier: %.*s\n", pl - 4, bp + 4);
7995*44704f69SBart Van Assche break;
7996*44704f69SBart Van Assche case 0x42:
7997*44704f69SBart Van Assche printf(" Volume barcode: %.*s\n", pl - 4, bp + 4);
7998*44704f69SBart Van Assche break;
7999*44704f69SBart Van Assche case 0x43:
8000*44704f69SBart Van Assche printf(" Volume manufacturer: %.*s\n", pl - 4, bp + 4);
8001*44704f69SBart Van Assche break;
8002*44704f69SBart Van Assche case 0x44:
8003*44704f69SBart Van Assche printf(" Volume license code: %.*s\n", pl - 4, bp + 4);
8004*44704f69SBart Van Assche break;
8005*44704f69SBart Van Assche case 0x45:
8006*44704f69SBart Van Assche printf(" Volume personality: %.*s\n", pl - 4, bp + 4);
8007*44704f69SBart Van Assche break;
8008*44704f69SBart Van Assche case 0x80:
8009*44704f69SBart Van Assche printf(" Write protect: %s\n",
8010*44704f69SBart Van Assche num_or_unknown(bp + 4, pl - 4, false, b, sizeof(b)));
8011*44704f69SBart Van Assche break;
8012*44704f69SBart Van Assche case 0x81:
8013*44704f69SBart Van Assche printf(" WORM: %s\n",
8014*44704f69SBart Van Assche num_or_unknown(bp + 4, pl - 4, false, b, sizeof(b)));
8015*44704f69SBart Van Assche break;
8016*44704f69SBart Van Assche case 0x82:
8017*44704f69SBart Van Assche printf(" Maximum recommended tape path temperature exceeded: "
8018*44704f69SBart Van Assche "%s\n", num_or_unknown(bp + 4, pl - 4, false, b,
8019*44704f69SBart Van Assche sizeof(b)));
8020*44704f69SBart Van Assche break;
8021*44704f69SBart Van Assche case 0x100:
8022*44704f69SBart Van Assche printf(" Volume write mounts: %" PRIu64 "\n",
8023*44704f69SBart Van Assche sg_get_unaligned_be(pl - 4, bp + 4));
8024*44704f69SBart Van Assche break;
8025*44704f69SBart Van Assche case 0x101:
8026*44704f69SBart Van Assche printf(" Beginning of medium passes: %" PRIu64 "\n",
8027*44704f69SBart Van Assche sg_get_unaligned_be(pl - 4, bp + 4));
8028*44704f69SBart Van Assche break;
8029*44704f69SBart Van Assche case 0x102:
8030*44704f69SBart Van Assche printf(" Middle of medium passes: %" PRIu64 "\n",
8031*44704f69SBart Van Assche sg_get_unaligned_be(pl - 4, bp + 4));
8032*44704f69SBart Van Assche break;
8033*44704f69SBart Van Assche case 0x200:
8034*44704f69SBart Van Assche printf(" Logical position of first encrypted logical object:\n");
8035*44704f69SBart Van Assche volume_stats_partition(bp + 4, pl - 4, true);
8036*44704f69SBart Van Assche break;
8037*44704f69SBart Van Assche case 0x201:
8038*44704f69SBart Van Assche printf(" Logical position of first unencrypted logical object "
8039*44704f69SBart Van Assche "after first\n encrypted logical object:\n");
8040*44704f69SBart Van Assche volume_stats_partition(bp + 4, pl - 4, true);
8041*44704f69SBart Van Assche break;
8042*44704f69SBart Van Assche case 0x202:
8043*44704f69SBart Van Assche printf(" Native capacity partition(s) [MB]:\n");
8044*44704f69SBart Van Assche volume_stats_partition(bp + 4, pl - 4, false);
8045*44704f69SBart Van Assche break;
8046*44704f69SBart Van Assche case 0x203:
8047*44704f69SBart Van Assche printf(" Used native capacity partition(s) [MB]:\n");
8048*44704f69SBart Van Assche volume_stats_partition(bp + 4, pl - 4, false);
8049*44704f69SBart Van Assche break;
8050*44704f69SBart Van Assche case 0x204:
8051*44704f69SBart Van Assche printf(" Remaining native capacity partition(s) [MB]:\n");
8052*44704f69SBart Van Assche volume_stats_partition(bp + 4, pl - 4, false);
8053*44704f69SBart Van Assche break;
8054*44704f69SBart Van Assche case 0x300:
8055*44704f69SBart Van Assche printf(" Mount history:\n");
8056*44704f69SBart Van Assche volume_stats_history(bp + 4, pl - 4);
8057*44704f69SBart Van Assche break;
8058*44704f69SBart Van Assche
8059*44704f69SBart Van Assche default:
8060*44704f69SBart Van Assche if (pc >= 0xf000) {
8061*44704f69SBart Van Assche if (op->exclude_vendor) {
8062*44704f69SBart Van Assche skip_out = true;
8063*44704f69SBart Van Assche if ((op->verbose > 0) && (0 == op->do_brief) &&
8064*44704f69SBart Van Assche (! evsm_output)) {
8065*44704f69SBart Van Assche evsm_output = true;
8066*44704f69SBart Van Assche printf(" Vendor specific parameter(s) being "
8067*44704f69SBart Van Assche "ignored\n");
8068*44704f69SBart Van Assche }
8069*44704f69SBart Van Assche } else
8070*44704f69SBart Van Assche printf(" Vendor specific %s (0x%x), payload in hex\n",
8071*44704f69SBart Van Assche param_c, pc);
8072*44704f69SBart Van Assche } else
8073*44704f69SBart Van Assche printf(" Reserved %s (0x%x), payload in hex\n", param_c, pc);
8074*44704f69SBart Van Assche if (skip_out)
8075*44704f69SBart Van Assche skip_out = false;
8076*44704f69SBart Van Assche else
8077*44704f69SBart Van Assche hex2fp(bp + 4, pl - 4, " ", op->hex2str_oformat, stdout);
8078*44704f69SBart Van Assche break;
8079*44704f69SBart Van Assche }
8080*44704f69SBart Van Assche if (op->do_pcb)
8081*44704f69SBart Van Assche printf(" <%s>\n", get_pcb_str(bp[2], str, sizeof(str)));
8082*44704f69SBart Van Assche filter_chk:
8083*44704f69SBart Van Assche if (op->filter_given)
8084*44704f69SBart Van Assche break;
8085*44704f69SBart Van Assche skip:
8086*44704f69SBart Van Assche num -= pl;
8087*44704f69SBart Van Assche bp += pl;
8088*44704f69SBart Van Assche }
8089*44704f69SBart Van Assche return true;
8090*44704f69SBart Van Assche }
8091*44704f69SBart Van Assche
8092*44704f69SBart Van Assche /* TAPE_ALERT_LPAGE [0x2e] <ta> */
8093*44704f69SBart Van Assche static bool
show_tape_alert_ssc_page(const uint8_t * resp,int len,struct opts_t * op,sgj_opaque_p jop)8094*44704f69SBart Van Assche show_tape_alert_ssc_page(const uint8_t * resp, int len,
8095*44704f69SBart Van Assche struct opts_t * op, sgj_opaque_p jop)
8096*44704f69SBart Van Assche {
8097*44704f69SBart Van Assche int num, pl, pc, flag;
8098*44704f69SBart Van Assche const uint8_t * bp;
8099*44704f69SBart Van Assche char str[PCB_STR_LEN];
8100*44704f69SBart Van Assche
8101*44704f69SBart Van Assche if (jop) { };
8102*44704f69SBart Van Assche /* N.B. the Tape alert log page for smc-3 is different */
8103*44704f69SBart Van Assche if (op->verbose || ((! op->do_raw) && (0 == op->do_hex)))
8104*44704f69SBart Van Assche printf("Tape alert page (ssc-3) [0x2e]\n");
8105*44704f69SBart Van Assche num = len - 4;
8106*44704f69SBart Van Assche bp = &resp[0] + 4;
8107*44704f69SBart Van Assche while (num > 3) {
8108*44704f69SBart Van Assche pc = sg_get_unaligned_be16(bp + 0);
8109*44704f69SBart Van Assche pl = bp[3] + 4;
8110*44704f69SBart Van Assche if (op->filter_given) {
8111*44704f69SBart Van Assche if (pc != op->filter)
8112*44704f69SBart Van Assche goto skip;
8113*44704f69SBart Van Assche }
8114*44704f69SBart Van Assche if (op->do_raw) {
8115*44704f69SBart Van Assche dStrRaw(bp, pl);
8116*44704f69SBart Van Assche goto filter_chk;
8117*44704f69SBart Van Assche } else if (op->do_hex) {
8118*44704f69SBart Van Assche hex2stdout(bp, pl, op->dstrhex_no_ascii);
8119*44704f69SBart Van Assche goto filter_chk;
8120*44704f69SBart Van Assche }
8121*44704f69SBart Van Assche flag = bp[4] & 1;
8122*44704f69SBart Van Assche if (op->verbose && (0 == op->do_brief) && flag)
8123*44704f69SBart Van Assche printf(" >>>> ");
8124*44704f69SBart Van Assche if ((0 == op->do_brief) || op->verbose || flag) {
8125*44704f69SBart Van Assche if (NULL == sg_lib_tapealert_strs[0])
8126*44704f69SBart Van Assche printf(" No string available for code 0x%x, flag: %d\n",
8127*44704f69SBart Van Assche pc, flag);
8128*44704f69SBart Van Assche else if (pc <= 0x40)
8129*44704f69SBart Van Assche printf(" %s: %d\n", sg_lib_tapealert_strs[pc], flag);
8130*44704f69SBart Van Assche else
8131*44704f69SBart Van Assche printf(" Reserved %s 0x%x, flag: %d\n", param_c, pc, flag);
8132*44704f69SBart Van Assche }
8133*44704f69SBart Van Assche if (op->do_pcb)
8134*44704f69SBart Van Assche printf(" <%s>\n", get_pcb_str(bp[2], str, sizeof(str)));
8135*44704f69SBart Van Assche filter_chk:
8136*44704f69SBart Van Assche if (op->filter_given)
8137*44704f69SBart Van Assche break;
8138*44704f69SBart Van Assche skip:
8139*44704f69SBart Van Assche num -= pl;
8140*44704f69SBart Van Assche bp += pl;
8141*44704f69SBart Van Assche }
8142*44704f69SBart Van Assche return true;
8143*44704f69SBart Van Assche }
8144*44704f69SBart Van Assche
8145*44704f69SBart Van Assche /* 0x37 */
8146*44704f69SBart Van Assche static bool
show_seagate_cache_page(const uint8_t * resp,int len,struct opts_t * op,sgj_opaque_p jop)8147*44704f69SBart Van Assche show_seagate_cache_page(const uint8_t * resp, int len,
8148*44704f69SBart Van Assche struct opts_t * op, sgj_opaque_p jop)
8149*44704f69SBart Van Assche {
8150*44704f69SBart Van Assche bool skip = false;
8151*44704f69SBart Van Assche int num, pl, pc;
8152*44704f69SBart Van Assche int bsti = 0;
8153*44704f69SBart Van Assche const uint8_t * bp;
8154*44704f69SBart Van Assche char str[PCB_STR_LEN];
8155*44704f69SBart Van Assche
8156*44704f69SBart Van Assche if (jop) { };
8157*44704f69SBart Van Assche if (op->verbose || ((! op->do_raw) && (0 == op->do_hex))) {
8158*44704f69SBart Van Assche if (resp[1] > 0) {
8159*44704f69SBart Van Assche printf("Suspicious page 0x37, SPF=0 but subpage=0x%x\n", resp[1]);
8160*44704f69SBart Van Assche if (op->verbose)
8161*44704f69SBart Van Assche printf("... try vendor=wdc\n");
8162*44704f69SBart Van Assche if (op->do_brief > 0)
8163*44704f69SBart Van Assche return true;
8164*44704f69SBart Van Assche } else
8165*44704f69SBart Van Assche printf("Seagate cache page [0x37]\n");
8166*44704f69SBart Van Assche }
8167*44704f69SBart Van Assche num = len - 4;
8168*44704f69SBart Van Assche bp = &resp[0] + 4;
8169*44704f69SBart Van Assche while (num > 3) {
8170*44704f69SBart Van Assche pc = sg_get_unaligned_be16(bp + 0);
8171*44704f69SBart Van Assche pl = bp[3] + 4;
8172*44704f69SBart Van Assche if (op->filter_given) {
8173*44704f69SBart Van Assche if (pc != op->filter)
8174*44704f69SBart Van Assche goto skip;
8175*44704f69SBart Van Assche }
8176*44704f69SBart Van Assche if (op->do_raw) {
8177*44704f69SBart Van Assche dStrRaw(bp, pl);
8178*44704f69SBart Van Assche goto filter_chk;
8179*44704f69SBart Van Assche } else if (op->do_hex) {
8180*44704f69SBart Van Assche hex2stdout(bp, pl, op->dstrhex_no_ascii);
8181*44704f69SBart Van Assche goto filter_chk;
8182*44704f69SBart Van Assche }
8183*44704f69SBart Van Assche switch (pc) {
8184*44704f69SBart Van Assche case 0:
8185*44704f69SBart Van Assche ++bsti;
8186*44704f69SBart Van Assche if (bsti < 2)
8187*44704f69SBart Van Assche printf(" Blocks sent to initiator");
8188*44704f69SBart Van Assche else
8189*44704f69SBart Van Assche skip = true;
8190*44704f69SBart Van Assche break;
8191*44704f69SBart Van Assche case 1:
8192*44704f69SBart Van Assche printf(" Blocks received from initiator");
8193*44704f69SBart Van Assche break;
8194*44704f69SBart Van Assche case 2:
8195*44704f69SBart Van Assche printf(" Blocks read from cache and sent to initiator");
8196*44704f69SBart Van Assche break;
8197*44704f69SBart Van Assche case 3:
8198*44704f69SBart Van Assche printf(" Number of read and write commands whose size "
8199*44704f69SBart Van Assche "<= segment size");
8200*44704f69SBart Van Assche break;
8201*44704f69SBart Van Assche case 4:
8202*44704f69SBart Van Assche printf(" Number of read and write commands whose size "
8203*44704f69SBart Van Assche "> segment size");
8204*44704f69SBart Van Assche break;
8205*44704f69SBart Van Assche default:
8206*44704f69SBart Van Assche printf(" Unknown Seagate %s = 0x%x", param_c, pc);
8207*44704f69SBart Van Assche break;
8208*44704f69SBart Van Assche }
8209*44704f69SBart Van Assche if (skip)
8210*44704f69SBart Van Assche skip = false;
8211*44704f69SBart Van Assche else {
8212*44704f69SBart Van Assche printf(" = %" PRIu64 "", sg_get_unaligned_be(pl - 4, bp + 4));
8213*44704f69SBart Van Assche printf("\n");
8214*44704f69SBart Van Assche if (op->do_pcb)
8215*44704f69SBart Van Assche printf(" <%s>\n", get_pcb_str(bp[2], str,
8216*44704f69SBart Van Assche sizeof(str)));
8217*44704f69SBart Van Assche }
8218*44704f69SBart Van Assche filter_chk:
8219*44704f69SBart Van Assche if (op->filter_given)
8220*44704f69SBart Van Assche break;
8221*44704f69SBart Van Assche skip:
8222*44704f69SBart Van Assche num -= pl;
8223*44704f69SBart Van Assche bp += pl;
8224*44704f69SBart Van Assche }
8225*44704f69SBart Van Assche return true;
8226*44704f69SBart Van Assche }
8227*44704f69SBart Van Assche
8228*44704f69SBart Van Assche /* 0x37 */
8229*44704f69SBart Van Assche static bool
show_hgst_misc_page(const uint8_t * resp,int len,struct opts_t * op,sgj_opaque_p jop)8230*44704f69SBart Van Assche show_hgst_misc_page(const uint8_t * resp, int len, struct opts_t * op,
8231*44704f69SBart Van Assche sgj_opaque_p jop)
8232*44704f69SBart Van Assche {
8233*44704f69SBart Van Assche bool valid = false;
8234*44704f69SBart Van Assche int num, pl, pc;
8235*44704f69SBart Van Assche const uint8_t * bp;
8236*44704f69SBart Van Assche char str[PCB_STR_LEN];
8237*44704f69SBart Van Assche
8238*44704f69SBart Van Assche if (jop) { };
8239*44704f69SBart Van Assche if (op->verbose || ((! op->do_raw) && (0 == op->do_hex)))
8240*44704f69SBart Van Assche printf("HGST/WDC miscellaneous page [0x37, 0x%x]\n",
8241*44704f69SBart Van Assche op->decod_subpg_code);
8242*44704f69SBart Van Assche num = len - 4;
8243*44704f69SBart Van Assche if (num < 0x30) {
8244*44704f69SBart Van Assche printf("HGST/WDC miscellaneous page too short (%d) < 48\n", num);
8245*44704f69SBart Van Assche return valid;
8246*44704f69SBart Van Assche }
8247*44704f69SBart Van Assche bp = &resp[0] + 4;
8248*44704f69SBart Van Assche while (num > 3) {
8249*44704f69SBart Van Assche pc = sg_get_unaligned_be16(bp + 0);
8250*44704f69SBart Van Assche pl = bp[3] + 4;
8251*44704f69SBart Van Assche if (op->filter_given) {
8252*44704f69SBart Van Assche if (pc != op->filter)
8253*44704f69SBart Van Assche goto skip;
8254*44704f69SBart Van Assche }
8255*44704f69SBart Van Assche if (op->do_raw) {
8256*44704f69SBart Van Assche dStrRaw(bp, pl);
8257*44704f69SBart Van Assche goto filter_chk;
8258*44704f69SBart Van Assche } else if (op->do_hex) {
8259*44704f69SBart Van Assche hex2stdout(bp, pl, op->dstrhex_no_ascii);
8260*44704f69SBart Van Assche goto filter_chk;
8261*44704f69SBart Van Assche }
8262*44704f69SBart Van Assche switch (pc) {
8263*44704f69SBart Van Assche case 0:
8264*44704f69SBart Van Assche valid = true;
8265*44704f69SBart Van Assche printf(" Power on hours = %u\n", sg_get_unaligned_be32(bp + 4));
8266*44704f69SBart Van Assche printf(" Total Bytes Read = %" PRIu64 "\n",
8267*44704f69SBart Van Assche sg_get_unaligned_be64(bp + 8));
8268*44704f69SBart Van Assche printf(" Total Bytes Written = %" PRIu64 "\n",
8269*44704f69SBart Van Assche sg_get_unaligned_be64(bp + 16));
8270*44704f69SBart Van Assche printf(" Max Drive Temp (Celsius) = %u\n", bp[24]);
8271*44704f69SBart Van Assche printf(" GList Size = %u\n", sg_get_unaligned_be16(bp + 25));
8272*44704f69SBart Van Assche printf(" Number of Information Exceptions = %u\n", bp[27]);
8273*44704f69SBart Van Assche printf(" MED EXC = %u\n", !! (0x80 & bp[28]));
8274*44704f69SBart Van Assche printf(" HDW EXC = %u\n", !! (0x40 & bp[28]));
8275*44704f69SBart Van Assche printf(" Total Read Commands = %" PRIu64 "\n",
8276*44704f69SBart Van Assche sg_get_unaligned_be64(bp + 29));
8277*44704f69SBart Van Assche printf(" Total Write Commands = %" PRIu64 "\n",
8278*44704f69SBart Van Assche sg_get_unaligned_be64(bp + 37));
8279*44704f69SBart Van Assche printf(" Flash Correction Count = %u\n",
8280*44704f69SBart Van Assche sg_get_unaligned_be16(bp + 46));
8281*44704f69SBart Van Assche break;
8282*44704f69SBart Van Assche default:
8283*44704f69SBart Van Assche valid = false;
8284*44704f69SBart Van Assche printf(" Unknown HGST/WDC %s = 0x%x", param_c, pc);
8285*44704f69SBart Van Assche break;
8286*44704f69SBart Van Assche }
8287*44704f69SBart Van Assche if (op->do_pcb)
8288*44704f69SBart Van Assche printf(" <%s>\n", get_pcb_str(bp[2], str, sizeof(str)));
8289*44704f69SBart Van Assche filter_chk:
8290*44704f69SBart Van Assche if (op->filter_given)
8291*44704f69SBart Van Assche break;
8292*44704f69SBart Van Assche skip:
8293*44704f69SBart Van Assche num -= pl;
8294*44704f69SBart Van Assche bp += pl;
8295*44704f69SBart Van Assche }
8296*44704f69SBart Van Assche return valid;
8297*44704f69SBart Van Assche }
8298*44704f69SBart Van Assche
8299*44704f69SBart Van Assche /* 0x3e */
8300*44704f69SBart Van Assche static bool
show_seagate_factory_page(const uint8_t * resp,int len,struct opts_t * op,sgj_opaque_p jop)8301*44704f69SBart Van Assche show_seagate_factory_page(const uint8_t * resp, int len,
8302*44704f69SBart Van Assche struct opts_t * op, sgj_opaque_p jop)
8303*44704f69SBart Van Assche {
8304*44704f69SBart Van Assche bool valid = false;
8305*44704f69SBart Van Assche int num, pl, pc;
8306*44704f69SBart Van Assche const uint8_t * bp;
8307*44704f69SBart Van Assche uint64_t ull;
8308*44704f69SBart Van Assche char str[PCB_STR_LEN];
8309*44704f69SBart Van Assche
8310*44704f69SBart Van Assche if (jop) { };
8311*44704f69SBart Van Assche if (op->verbose || ((! op->do_raw) && (0 == op->do_hex)))
8312*44704f69SBart Van Assche printf("Seagate/Hitachi factory page [0x3e]\n");
8313*44704f69SBart Van Assche num = len - 4;
8314*44704f69SBart Van Assche bp = &resp[0] + 4;
8315*44704f69SBart Van Assche while (num > 3) {
8316*44704f69SBart Van Assche pc = sg_get_unaligned_be16(bp + 0);
8317*44704f69SBart Van Assche pl = bp[3] + 4;
8318*44704f69SBart Van Assche if (op->filter_given) {
8319*44704f69SBart Van Assche if (pc != op->filter)
8320*44704f69SBart Van Assche goto skip;
8321*44704f69SBart Van Assche }
8322*44704f69SBart Van Assche if (op->do_raw) {
8323*44704f69SBart Van Assche dStrRaw(bp, pl);
8324*44704f69SBart Van Assche goto filter_chk;
8325*44704f69SBart Van Assche } else if (op->do_hex) {
8326*44704f69SBart Van Assche hex2stdout(bp, pl, op->dstrhex_no_ascii);
8327*44704f69SBart Van Assche goto filter_chk;
8328*44704f69SBart Van Assche }
8329*44704f69SBart Van Assche valid = true;
8330*44704f69SBart Van Assche switch (pc) {
8331*44704f69SBart Van Assche case 0:
8332*44704f69SBart Van Assche printf(" number of hours powered up");
8333*44704f69SBart Van Assche break;
8334*44704f69SBart Van Assche case 8:
8335*44704f69SBart Van Assche printf(" number of minutes until next internal SMART test");
8336*44704f69SBart Van Assche break;
8337*44704f69SBart Van Assche default:
8338*44704f69SBart Van Assche valid = false;
8339*44704f69SBart Van Assche printf(" Unknown Seagate/Hitachi %s = 0x%x", param_c, pc);
8340*44704f69SBart Van Assche break;
8341*44704f69SBart Van Assche }
8342*44704f69SBart Van Assche if (valid) {
8343*44704f69SBart Van Assche ull = sg_get_unaligned_be(pl - 4, bp + 4);
8344*44704f69SBart Van Assche if (0 == pc)
8345*44704f69SBart Van Assche printf(" = %.2f", ((double)ull) / 60.0 );
8346*44704f69SBart Van Assche else
8347*44704f69SBart Van Assche printf(" = %" PRIu64 "", ull);
8348*44704f69SBart Van Assche }
8349*44704f69SBart Van Assche printf("\n");
8350*44704f69SBart Van Assche if (op->do_pcb)
8351*44704f69SBart Van Assche printf(" <%s>\n", get_pcb_str(bp[2], str, sizeof(str)));
8352*44704f69SBart Van Assche filter_chk:
8353*44704f69SBart Van Assche if (op->filter_given)
8354*44704f69SBart Van Assche break;
8355*44704f69SBart Van Assche skip:
8356*44704f69SBart Van Assche num -= pl;
8357*44704f69SBart Van Assche bp += pl;
8358*44704f69SBart Van Assche }
8359*44704f69SBart Van Assche return true;
8360*44704f69SBart Van Assche }
8361*44704f69SBart Van Assche
8362*44704f69SBart Van Assche static void
decode_page_contents(const uint8_t * resp,int len,struct opts_t * op,sgj_opaque_p jop)8363*44704f69SBart Van Assche decode_page_contents(const uint8_t * resp, int len, struct opts_t * op,
8364*44704f69SBart Van Assche sgj_opaque_p jop)
8365*44704f69SBart Van Assche {
8366*44704f69SBart Van Assche int pg_code, subpg_code, vpn;
8367*44704f69SBart Van Assche bool spf;
8368*44704f69SBart Van Assche bool done = false;
8369*44704f69SBart Van Assche const struct log_elem * lep;
8370*44704f69SBart Van Assche
8371*44704f69SBart Van Assche if (len < 3) {
8372*44704f69SBart Van Assche pr2serr("%s: response has bad length: %d\n", __func__, len);
8373*44704f69SBart Van Assche return;
8374*44704f69SBart Van Assche }
8375*44704f69SBart Van Assche spf = !!(resp[0] & 0x40);
8376*44704f69SBart Van Assche pg_code = resp[0] & 0x3f;
8377*44704f69SBart Van Assche if ((VP_HITA == op->vend_prod_num) && (pg_code >= 0x30))
8378*44704f69SBart Van Assche subpg_code = resp[1]; /* Hitachi don't set SPF on VS pages */
8379*44704f69SBart Van Assche else
8380*44704f69SBart Van Assche subpg_code = spf ? resp[1] : NOT_SPG_SUBPG;
8381*44704f69SBart Van Assche op->decod_subpg_code = subpg_code;
8382*44704f69SBart Van Assche if ((SUPP_SPGS_SUBPG == subpg_code) && (SUPP_PAGES_LPAGE != pg_code)) {
8383*44704f69SBart Van Assche done = show_supported_pgs_sub_page(resp, len, op, jop);
8384*44704f69SBart Van Assche if (done)
8385*44704f69SBart Van Assche return;
8386*44704f69SBart Van Assche }
8387*44704f69SBart Van Assche vpn = (op->vend_prod_num >= 0) ? op->vend_prod_num : op->deduced_vpn;
8388*44704f69SBart Van Assche lep = pg_subpg_pdt_search(pg_code, subpg_code, op->dev_pdt, vpn);
8389*44704f69SBart Van Assche
8390*44704f69SBart Van Assche /* Below is the indirect function call to all the show_* functions */
8391*44704f69SBart Van Assche if (lep && lep->show_pagep)
8392*44704f69SBart Van Assche done = (*lep->show_pagep)(resp, len, op, jop);
8393*44704f69SBart Van Assche
8394*44704f69SBart Van Assche if (! done) {
8395*44704f69SBart Van Assche if (0 == op->do_hex) {
8396*44704f69SBart Van Assche static const char * unable_s = "Unable to decode page = 0x";
8397*44704f69SBart Van Assche
8398*44704f69SBart Van Assche if (subpg_code > 0)
8399*44704f69SBart Van Assche printf("%s%x, subpage = 0x%x, here is hex:\n", unable_s,
8400*44704f69SBart Van Assche pg_code, subpg_code);
8401*44704f69SBart Van Assche else
8402*44704f69SBart Van Assche printf("%s%x, here is hex:\n", unable_s, pg_code);
8403*44704f69SBart Van Assche }
8404*44704f69SBart Van Assche if ((len > 128) && (0 == op->do_hex)) {
8405*44704f69SBart Van Assche hex2fp(resp, 64, " ", op->hex2str_oformat, stdout);
8406*44704f69SBart Van Assche printf(" ..... [truncated after 64 of %d bytes (use '-H' to "
8407*44704f69SBart Van Assche "see the rest)]\n", len);
8408*44704f69SBart Van Assche } else {
8409*44704f69SBart Van Assche if (0 == op->do_hex)
8410*44704f69SBart Van Assche hex2fp(resp, len, " ", op->hex2str_oformat, stdout);
8411*44704f69SBart Van Assche else
8412*44704f69SBart Van Assche hex2stdout(resp, len, op->dstrhex_no_ascii);
8413*44704f69SBart Van Assche }
8414*44704f69SBart Van Assche }
8415*44704f69SBart Van Assche }
8416*44704f69SBart Van Assche
8417*44704f69SBart Van Assche /* Tries to fetch the TEMPERATURE_LPAGE [0xd] page first. If that fails
8418*44704f69SBart Van Assche * tries to get the Informational Exceptions (IE_LPAGE) page. */
8419*44704f69SBart Van Assche static int
fetchTemperature(int sg_fd,uint8_t * resp,int max_len,struct opts_t * op,sgj_opaque_p jop)8420*44704f69SBart Van Assche fetchTemperature(int sg_fd, uint8_t * resp, int max_len, struct opts_t * op,
8421*44704f69SBart Van Assche sgj_opaque_p jop)
8422*44704f69SBart Van Assche {
8423*44704f69SBart Van Assche int len;
8424*44704f69SBart Van Assche int res = 0;
8425*44704f69SBart Van Assche
8426*44704f69SBart Van Assche op->pg_code = TEMPERATURE_LPAGE;
8427*44704f69SBart Van Assche op->subpg_code = NOT_SPG_SUBPG;
8428*44704f69SBart Van Assche res = do_logs(sg_fd, resp, max_len, op);
8429*44704f69SBart Van Assche if (0 == res) {
8430*44704f69SBart Van Assche len = sg_get_unaligned_be16(resp + 2) + 4;
8431*44704f69SBart Van Assche if (op->do_raw)
8432*44704f69SBart Van Assche dStrRaw(resp, len);
8433*44704f69SBart Van Assche else if (op->do_hex)
8434*44704f69SBart Van Assche hex2stdout(resp, len, op->dstrhex_no_ascii);
8435*44704f69SBart Van Assche else
8436*44704f69SBart Van Assche show_temperature_page(resp, len, op, jop);
8437*44704f69SBart Van Assche } else if (SG_LIB_CAT_NOT_READY == res)
8438*44704f69SBart Van Assche pr2serr("Device not ready\n");
8439*44704f69SBart Van Assche else {
8440*44704f69SBart Van Assche op->pg_code = IE_LPAGE;
8441*44704f69SBart Van Assche res = do_logs(sg_fd, resp, max_len, op);
8442*44704f69SBart Van Assche if (0 == res) {
8443*44704f69SBart Van Assche len = sg_get_unaligned_be16(resp + 2) + 4;
8444*44704f69SBart Van Assche if (op->do_raw)
8445*44704f69SBart Van Assche dStrRaw(resp, len);
8446*44704f69SBart Van Assche else if (op->do_hex)
8447*44704f69SBart Van Assche hex2stdout(resp, len, op->dstrhex_no_ascii);
8448*44704f69SBart Van Assche else
8449*44704f69SBart Van Assche show_ie_page(resp, len, op, jop);
8450*44704f69SBart Van Assche } else
8451*44704f69SBart Van Assche pr2serr("Unable to find temperature in either Temperature or "
8452*44704f69SBart Van Assche "IE log page\n");
8453*44704f69SBart Van Assche }
8454*44704f69SBart Van Assche sg_cmds_close_device(sg_fd);
8455*44704f69SBart Van Assche return (res >= 0) ? res : SG_LIB_CAT_OTHER;
8456*44704f69SBart Van Assche }
8457*44704f69SBart Van Assche
8458*44704f69SBart Van Assche /* Returns 0 if successful else SG_LIB_SYNTAX_ERROR. */
8459*44704f69SBart Van Assche static int
decode_pg_arg(struct opts_t * op)8460*44704f69SBart Van Assche decode_pg_arg(struct opts_t * op)
8461*44704f69SBart Van Assche {
8462*44704f69SBart Van Assche int nn;
8463*44704f69SBart Van Assche const struct log_elem * lep;
8464*44704f69SBart Van Assche char * cp;
8465*44704f69SBart Van Assche
8466*44704f69SBart Van Assche if (isalpha((uint8_t)op->pg_arg[0])) {
8467*44704f69SBart Van Assche char b[80];
8468*44704f69SBart Van Assche
8469*44704f69SBart Van Assche if (strlen(op->pg_arg) >= (sizeof(b) - 1)) {
8470*44704f69SBart Van Assche pr2serr("argument to '--page=' is too long\n");
8471*44704f69SBart Van Assche return SG_LIB_SYNTAX_ERROR;
8472*44704f69SBart Van Assche }
8473*44704f69SBart Van Assche strcpy(b, op->pg_arg);
8474*44704f69SBart Van Assche cp = (char *)strchr(b, ',');
8475*44704f69SBart Van Assche if (cp)
8476*44704f69SBart Van Assche *cp = '\0';
8477*44704f69SBart Van Assche lep = acron_search(b);
8478*44704f69SBart Van Assche if (NULL == lep) {
8479*44704f69SBart Van Assche pr2serr("bad argument to '--page=' no acronyn match to "
8480*44704f69SBart Van Assche "'%s'\n", b);
8481*44704f69SBart Van Assche pr2serr(" Try using '-e' or'-ee' to see available "
8482*44704f69SBart Van Assche "acronyns\n");
8483*44704f69SBart Van Assche return SG_LIB_SYNTAX_ERROR;
8484*44704f69SBart Van Assche }
8485*44704f69SBart Van Assche op->lep = lep;
8486*44704f69SBart Van Assche op->pg_code = lep->pg_code;
8487*44704f69SBart Van Assche if (cp) {
8488*44704f69SBart Van Assche nn = sg_get_num_nomult(cp + 1);
8489*44704f69SBart Van Assche if ((nn < 0) || (nn > 255)) {
8490*44704f69SBart Van Assche pr2serr("Bad second value in argument to "
8491*44704f69SBart Van Assche "'--page='\n");
8492*44704f69SBart Van Assche return SG_LIB_SYNTAX_ERROR;
8493*44704f69SBart Van Assche }
8494*44704f69SBart Van Assche op->subpg_code = nn;
8495*44704f69SBart Van Assche } else
8496*44704f69SBart Van Assche op->subpg_code = lep->subpg_code;
8497*44704f69SBart Van Assche } else { /* numeric arg: either 'pg_num' or 'pg_num,subpg_num' */
8498*44704f69SBart Van Assche int n;
8499*44704f69SBart Van Assche
8500*44704f69SBart Van Assche cp = (char *)strchr(op->pg_arg, ',');
8501*44704f69SBart Van Assche n = sg_get_num_nomult(op->pg_arg);
8502*44704f69SBart Van Assche if ((n < 0) || (n > 63)) {
8503*44704f69SBart Van Assche pr2serr("Bad argument to '--page='\n");
8504*44704f69SBart Van Assche usage(1);
8505*44704f69SBart Van Assche return SG_LIB_SYNTAX_ERROR;
8506*44704f69SBart Van Assche }
8507*44704f69SBart Van Assche if (cp) {
8508*44704f69SBart Van Assche nn = sg_get_num_nomult(cp + 1);
8509*44704f69SBart Van Assche if ((nn < 0) || (nn > 255)) {
8510*44704f69SBart Van Assche pr2serr("Bad second value in argument to "
8511*44704f69SBart Van Assche "'--page='\n");
8512*44704f69SBart Van Assche usage(1);
8513*44704f69SBart Van Assche return SG_LIB_SYNTAX_ERROR;
8514*44704f69SBart Van Assche }
8515*44704f69SBart Van Assche } else
8516*44704f69SBart Van Assche nn = 0;
8517*44704f69SBart Van Assche op->pg_code = n;
8518*44704f69SBart Van Assche op->subpg_code = nn;
8519*44704f69SBart Van Assche }
8520*44704f69SBart Van Assche return 0;
8521*44704f69SBart Van Assche }
8522*44704f69SBart Van Assche
8523*44704f69SBart Van Assche /* Since the Supported subpages page is sitting in the rsp_buff which is
8524*44704f69SBart Van Assche * MX_ALLOC_LEN bytes long (~ 64 KB) then move it (from rsp_buff+0 to
8525*44704f69SBart Van Assche * rsp_buff+pg_len-1) to the top end of that buffer. Then there is room
8526*44704f69SBart Van Assche * to merge supp_pgs_rsp with the supported subpages with the result back
8527*44704f69SBart Van Assche * at the bottom of rsp_buff. The new length of the merged subpages page
8528*44704f69SBart Van Assche * (excluding its 4 byte header) is returned.
8529*44704f69SBart Van Assche * Assumes both pages are in ascending order (as required by SPC-4). */
8530*44704f69SBart Van Assche static int
merge_both_supported(const uint8_t * supp_pgs_p,int su_p_pg_len,int pg_len)8531*44704f69SBart Van Assche merge_both_supported(const uint8_t * supp_pgs_p, int su_p_pg_len, int pg_len)
8532*44704f69SBart Van Assche {
8533*44704f69SBart Van Assche uint8_t pg;
8534*44704f69SBart Van Assche int k, kp, ks;
8535*44704f69SBart Van Assche int max_blen = (2 * su_p_pg_len) + pg_len;
8536*44704f69SBart Van Assche uint8_t * m_buff = rsp_buff + (rsp_buff_sz - pg_len);
8537*44704f69SBart Van Assche uint8_t * r_buff = rsp_buff + 4;
8538*44704f69SBart Van Assche
8539*44704f69SBart Van Assche if (pg_len > 0)
8540*44704f69SBart Van Assche memmove(m_buff, rsp_buff + 4, pg_len);
8541*44704f69SBart Van Assche for (k = 0, kp = 0, ks = 0; k < max_blen; k += 2) {
8542*44704f69SBart Van Assche if (kp < su_p_pg_len)
8543*44704f69SBart Van Assche pg = supp_pgs_p[kp];
8544*44704f69SBart Van Assche else
8545*44704f69SBart Van Assche pg = 0xff;
8546*44704f69SBart Van Assche if (ks < pg_len) {
8547*44704f69SBart Van Assche if (m_buff[ks] < pg) {
8548*44704f69SBart Van Assche r_buff[k] = m_buff[ks];
8549*44704f69SBart Van Assche r_buff[k + 1] = m_buff[ks + 1];
8550*44704f69SBart Van Assche ks += 2;
8551*44704f69SBart Van Assche } else if ((m_buff[ks] == pg) && (m_buff[ks + 1] == 0)) {
8552*44704f69SBart Van Assche r_buff[k] = m_buff[ks];
8553*44704f69SBart Van Assche r_buff[k + 1] = m_buff[ks + 1];
8554*44704f69SBart Van Assche ks += 2;
8555*44704f69SBart Van Assche ++kp;
8556*44704f69SBart Van Assche } else {
8557*44704f69SBart Van Assche r_buff[k] = pg;
8558*44704f69SBart Van Assche r_buff[k + 1] = 0;
8559*44704f69SBart Van Assche ++kp;
8560*44704f69SBart Van Assche }
8561*44704f69SBart Van Assche } else {
8562*44704f69SBart Van Assche if (0xff == pg)
8563*44704f69SBart Van Assche break;
8564*44704f69SBart Van Assche r_buff[k] = pg;
8565*44704f69SBart Van Assche r_buff[k + 1] = 0;
8566*44704f69SBart Van Assche ++kp;
8567*44704f69SBart Van Assche }
8568*44704f69SBart Van Assche }
8569*44704f69SBart Van Assche sg_put_unaligned_be16(k, rsp_buff + 2);
8570*44704f69SBart Van Assche return k;
8571*44704f69SBart Van Assche }
8572*44704f69SBart Van Assche
8573*44704f69SBart Van Assche
8574*44704f69SBart Van Assche int
main(int argc,char * argv[])8575*44704f69SBart Van Assche main(int argc, char * argv[])
8576*44704f69SBart Van Assche {
8577*44704f69SBart Van Assche bool as_json;
8578*44704f69SBart Van Assche int k, nn, pg_len, res, vb;
8579*44704f69SBart Van Assche int resp_len = 0;
8580*44704f69SBart Van Assche int su_p_pg_len = 0;
8581*44704f69SBart Van Assche int in_len = -1;
8582*44704f69SBart Van Assche int sg_fd = -1;
8583*44704f69SBart Van Assche int ret = 0;
8584*44704f69SBart Van Assche uint8_t * parr;
8585*44704f69SBart Van Assche uint8_t * free_parr = NULL;
8586*44704f69SBart Van Assche struct opts_t * op;
8587*44704f69SBart Van Assche sgj_state * jsp;
8588*44704f69SBart Van Assche sgj_opaque_p jop = NULL;
8589*44704f69SBart Van Assche struct sg_simple_inquiry_resp inq_out;
8590*44704f69SBart Van Assche struct opts_t opts SG_C_CPP_ZERO_INIT;
8591*44704f69SBart Van Assche uint8_t supp_pgs_rsp[256];
8592*44704f69SBart Van Assche char b[128];
8593*44704f69SBart Van Assche static const int blen = sizeof(b);
8594*44704f69SBart Van Assche
8595*44704f69SBart Van Assche op = &opts;
8596*44704f69SBart Van Assche /* N.B. some disks only give data for current cumulative */
8597*44704f69SBart Van Assche op->page_control = 1;
8598*44704f69SBart Van Assche op->dev_pdt = -1;
8599*44704f69SBart Van Assche op->vend_prod_num = VP_NONE;
8600*44704f69SBart Van Assche op->deduced_vpn = VP_NONE;
8601*44704f69SBart Van Assche res = parse_cmd_line(op, argc, argv);
8602*44704f69SBart Van Assche if (res)
8603*44704f69SBart Van Assche return SG_LIB_SYNTAX_ERROR;
8604*44704f69SBart Van Assche if (op->do_help) {
8605*44704f69SBart Van Assche usage_for(op->do_help, op);
8606*44704f69SBart Van Assche return 0;
8607*44704f69SBart Van Assche }
8608*44704f69SBart Van Assche jsp = &op->json_st;
8609*44704f69SBart Van Assche as_json = jsp->pr_as_json;
8610*44704f69SBart Van Assche if (as_json) {
8611*44704f69SBart Van Assche if (op->do_name) {
8612*44704f69SBart Van Assche pr2serr(">>> The --json option is superior to the --name "
8613*44704f69SBart Van Assche "option.\n");
8614*44704f69SBart Van Assche pr2serr(">>> Ignoring the --name option.\n");
8615*44704f69SBart Van Assche op->do_name = false;
8616*44704f69SBart Van Assche }
8617*44704f69SBart Van Assche jop = sgj_start_r(MY_NAME, version_str, argc, argv, jsp);
8618*44704f69SBart Van Assche }
8619*44704f69SBart Van Assche #ifdef DEBUG
8620*44704f69SBart Van Assche pr2serr("In DEBUG mode, ");
8621*44704f69SBart Van Assche if (op->verbose_given && op->version_given) {
8622*44704f69SBart Van Assche pr2serr("but override: '-vV' given, zero verbose and continue\n");
8623*44704f69SBart Van Assche op->verbose_given = false;
8624*44704f69SBart Van Assche op->version_given = false;
8625*44704f69SBart Van Assche op->verbose = 0;
8626*44704f69SBart Van Assche } else if (! op->verbose_given) {
8627*44704f69SBart Van Assche pr2serr("set '-vv'\n");
8628*44704f69SBart Van Assche op->verbose = 2;
8629*44704f69SBart Van Assche } else
8630*44704f69SBart Van Assche pr2serr("keep verbose=%d\n", op->verbose);
8631*44704f69SBart Van Assche #else
8632*44704f69SBart Van Assche if (op->verbose_given && op->version_given)
8633*44704f69SBart Van Assche pr2serr("Not in DEBUG mode, so '-vV' has no special action\n");
8634*44704f69SBart Van Assche #endif
8635*44704f69SBart Van Assche if (op->version_given) {
8636*44704f69SBart Van Assche pr2serr("Version string: %s\n", version_str);
8637*44704f69SBart Van Assche return 0;
8638*44704f69SBart Van Assche }
8639*44704f69SBart Van Assche if (op->do_hex > 0) {
8640*44704f69SBart Van Assche if (op->do_hex > 2) {
8641*44704f69SBart Van Assche op->dstrhex_no_ascii = -1;
8642*44704f69SBart Van Assche op->hex2str_oformat = 1;
8643*44704f69SBart Van Assche } else {
8644*44704f69SBart Van Assche op->dstrhex_no_ascii = (1 == op->do_hex);
8645*44704f69SBart Van Assche op->hex2str_oformat = (1 == op->do_hex);
8646*44704f69SBart Van Assche }
8647*44704f69SBart Van Assche } else {
8648*44704f69SBart Van Assche if (op->undefined_hex > 0) {
8649*44704f69SBart Van Assche if (op->undefined_hex > 2) {
8650*44704f69SBart Van Assche op->dstrhex_no_ascii = -1;
8651*44704f69SBart Van Assche op->hex2str_oformat = 1;
8652*44704f69SBart Van Assche } else {
8653*44704f69SBart Van Assche op->dstrhex_no_ascii = (1 == op->undefined_hex);
8654*44704f69SBart Van Assche op->hex2str_oformat = (1 == op->undefined_hex);
8655*44704f69SBart Van Assche }
8656*44704f69SBart Van Assche } else { /* default when no --hex nor --undefined */
8657*44704f69SBart Van Assche op->dstrhex_no_ascii = -1;
8658*44704f69SBart Van Assche op->hex2str_oformat = 1;
8659*44704f69SBart Van Assche }
8660*44704f69SBart Van Assche }
8661*44704f69SBart Van Assche vb = op->verbose;
8662*44704f69SBart Van Assche if (op->vend_prod) {
8663*44704f69SBart Van Assche if (0 == memcmp("-1", op->vend_prod,3))
8664*44704f69SBart Van Assche k = VP_NONE;
8665*44704f69SBart Van Assche else if (isdigit((uint8_t)op->vend_prod[0]))
8666*44704f69SBart Van Assche k = sg_get_num_nomult(op->vend_prod);
8667*44704f69SBart Van Assche else
8668*44704f69SBart Van Assche k = find_vpn_by_acron(op->vend_prod);
8669*44704f69SBart Van Assche op->vend_prod_num = k;
8670*44704f69SBart Van Assche if (VP_ALL == k)
8671*44704f69SBart Van Assche ;
8672*44704f69SBart Van Assche else if ((k < 0) || (k > (32 - MVP_OFFSET))) {
8673*44704f69SBart Van Assche pr2serr("Bad vendor/product acronym after '--vendor=' "
8674*44704f69SBart Van Assche " ('-M ') option\n");
8675*44704f69SBart Van Assche enumerate_vp();
8676*44704f69SBart Van Assche return SG_LIB_SYNTAX_ERROR;
8677*44704f69SBart Van Assche }
8678*44704f69SBart Van Assche }
8679*44704f69SBart Van Assche if (op->do_enumerate > 0) {
8680*44704f69SBart Van Assche if (op->device_name && vb)
8681*44704f69SBart Van Assche pr2serr("Warning: device: %s is being ignored\n",
8682*44704f69SBart Van Assche op->device_name);
8683*44704f69SBart Van Assche enumerate_pages(op);
8684*44704f69SBart Van Assche return 0;
8685*44704f69SBart Van Assche }
8686*44704f69SBart Van Assche if (op->in_fn) {
8687*44704f69SBart Van Assche if (op->maxlen_given) {
8688*44704f69SBart Van Assche if (op->maxlen > MX_INLEN_ALLOC_LEN) {
8689*44704f69SBart Van Assche pr2serr("bad argument to '--maxlen=' when --in= given, from "
8690*44704f69SBart Van Assche "2 to %d (inclusive) expected\n", MX_INLEN_ALLOC_LEN);
8691*44704f69SBart Van Assche return SG_LIB_SYNTAX_ERROR;
8692*44704f69SBart Van Assche }
8693*44704f69SBart Van Assche rsp_buff_sz = op->maxlen;
8694*44704f69SBart Van Assche } else
8695*44704f69SBart Van Assche rsp_buff_sz = DEF_INLEN_ALLOC_LEN;
8696*44704f69SBart Van Assche } else {
8697*44704f69SBart Van Assche if (op->maxlen_given) {
8698*44704f69SBart Van Assche if (op->maxlen > MX_ALLOC_LEN) {
8699*44704f69SBart Van Assche pr2serr("bad argument to '--maxlen=', from 2 to 65535 "
8700*44704f69SBart Van Assche "(inclusive) expected\n");
8701*44704f69SBart Van Assche return SG_LIB_SYNTAX_ERROR;
8702*44704f69SBart Van Assche }
8703*44704f69SBart Van Assche rsp_buff_sz = op->maxlen;
8704*44704f69SBart Van Assche }
8705*44704f69SBart Van Assche }
8706*44704f69SBart Van Assche rsp_buff = sg_memalign(rsp_buff_sz, 0 /* page aligned */, &free_rsp_buff,
8707*44704f69SBart Van Assche false);
8708*44704f69SBart Van Assche if (NULL == rsp_buff) {
8709*44704f69SBart Van Assche pr2serr("Unable to allocate %d bytes on the heap\n", rsp_buff_sz);
8710*44704f69SBart Van Assche ret = sg_convert_errno(ENOMEM);
8711*44704f69SBart Van Assche goto err_out;
8712*44704f69SBart Van Assche }
8713*44704f69SBart Van Assche if (NULL == op->device_name) {
8714*44704f69SBart Van Assche if (op->in_fn) {
8715*44704f69SBart Van Assche bool found = false;
8716*44704f69SBart Van Assche bool r_spf = false;
8717*44704f69SBart Van Assche uint16_t u;
8718*44704f69SBart Van Assche int pg_code, subpg_code, pdt, n;
8719*44704f69SBart Van Assche const struct log_elem * lep;
8720*44704f69SBart Van Assche const uint8_t * bp;
8721*44704f69SBart Van Assche
8722*44704f69SBart Van Assche if ((ret = sg_f2hex_arr(op->in_fn, op->do_raw, false, rsp_buff,
8723*44704f69SBart Van Assche &in_len, rsp_buff_sz)))
8724*44704f69SBart Van Assche goto err_out;
8725*44704f69SBart Van Assche if (vb > 2)
8726*44704f69SBart Van Assche pr2serr("Read %d [0x%x] bytes of user supplied data\n",
8727*44704f69SBart Van Assche in_len, in_len);
8728*44704f69SBart Van Assche if (op->do_raw)
8729*44704f69SBart Van Assche op->do_raw = false; /* can interfere on decode */
8730*44704f69SBart Van Assche if (in_len < 4) {
8731*44704f69SBart Van Assche pr2serr("--in=%s only decoded %d bytes (needs 4 at least)\n",
8732*44704f69SBart Van Assche op->in_fn, in_len);
8733*44704f69SBart Van Assche ret = SG_LIB_SYNTAX_ERROR;
8734*44704f69SBart Van Assche goto err_out;
8735*44704f69SBart Van Assche }
8736*44704f69SBart Van Assche if (op->pg_arg) {
8737*44704f69SBart Van Assche char b[144];
8738*44704f69SBart Van Assche char * cp;
8739*44704f69SBart Van Assche
8740*44704f69SBart Van Assche strcpy(b, op->pg_arg);
8741*44704f69SBart Van Assche cp = (char *)strchr(b, ',');
8742*44704f69SBart Van Assche if (cp)
8743*44704f69SBart Van Assche *cp = '\0';
8744*44704f69SBart Van Assche lep = acron_search(b);
8745*44704f69SBart Van Assche if (NULL == lep) {
8746*44704f69SBart Van Assche pr2serr("bad argument to '--page=' no acronyn match to "
8747*44704f69SBart Van Assche "'%s'\n", b);
8748*44704f69SBart Van Assche pr2serr(" Try using '-e' or'-ee' to see available "
8749*44704f69SBart Van Assche "acronyns\n");
8750*44704f69SBart Van Assche return SG_LIB_SYNTAX_ERROR;
8751*44704f69SBart Van Assche }
8752*44704f69SBart Van Assche op->lep = lep;
8753*44704f69SBart Van Assche op->pg_code = lep->pg_code;
8754*44704f69SBart Van Assche op->subpg_code = lep->subpg_code;
8755*44704f69SBart Van Assche if (op->subpg_code > 0)
8756*44704f69SBart Van Assche r_spf = true;
8757*44704f69SBart Van Assche }
8758*44704f69SBart Van Assche
8759*44704f69SBart Van Assche for (bp = rsp_buff, k = 0; k < in_len; bp += n, k += n) {
8760*44704f69SBart Van Assche bool spf = !! (bp[0] & 0x40);
8761*44704f69SBart Van Assche
8762*44704f69SBart Van Assche pg_code = bp[0] & 0x3f;
8763*44704f69SBart Van Assche subpg_code = spf ? bp[1] : NOT_SPG_SUBPG;
8764*44704f69SBart Van Assche u = sg_get_unaligned_be16(bp + 2);
8765*44704f69SBart Van Assche n = u + 4;
8766*44704f69SBart Van Assche if (n > (in_len - k)) {
8767*44704f69SBart Van Assche pr2serr("bytes decoded remaining (%d) less than lpage "
8768*44704f69SBart Van Assche "length (%d), try decoding anyway\n", in_len - k,
8769*44704f69SBart Van Assche n);
8770*44704f69SBart Van Assche n = in_len - k;
8771*44704f69SBart Van Assche }
8772*44704f69SBart Van Assche if (op->pg_arg) {
8773*44704f69SBart Van Assche if ((NOT_SPG_SUBPG == op->subpg_code) && spf) {
8774*44704f69SBart Van Assche continue;
8775*44704f69SBart Van Assche } else if ((! spf) && (! r_spf)) {
8776*44704f69SBart Van Assche if (pg_code != op->pg_code)
8777*44704f69SBart Van Assche continue;
8778*44704f69SBart Van Assche } else if ((SUPP_SPGS_SUBPG == op->subpg_code) &&
8779*44704f69SBart Van Assche (SUPP_PAGES_LPAGE != op->pg_code)) {
8780*44704f69SBart Van Assche if (pg_code != op->pg_code)
8781*44704f69SBart Van Assche continue;
8782*44704f69SBart Van Assche } else if ((SUPP_SPGS_SUBPG != op->subpg_code) &&
8783*44704f69SBart Van Assche (SUPP_PAGES_LPAGE == op->pg_code)) {
8784*44704f69SBart Van Assche if (subpg_code != op->subpg_code)
8785*44704f69SBart Van Assche continue;
8786*44704f69SBart Van Assche } else if ((SUPP_SPGS_SUBPG != op->subpg_code) &&
8787*44704f69SBart Van Assche (SUPP_PAGES_LPAGE != op->pg_code)) {
8788*44704f69SBart Van Assche if ((pg_code != op->pg_code) ||
8789*44704f69SBart Van Assche (subpg_code != op->subpg_code))
8790*44704f69SBart Van Assche continue;
8791*44704f69SBart Van Assche }
8792*44704f69SBart Van Assche }
8793*44704f69SBart Van Assche if (op->exclude_vendor && (pg_code >= 0x30))
8794*44704f69SBart Van Assche continue;
8795*44704f69SBart Van Assche found = true;
8796*44704f69SBart Van Assche if (op->do_hex > 2) {
8797*44704f69SBart Van Assche hex2fp(bp, n, NULL, op->hex2str_oformat, stdout);
8798*44704f69SBart Van Assche continue;
8799*44704f69SBart Van Assche }
8800*44704f69SBart Van Assche pdt = op->dev_pdt;
8801*44704f69SBart Van Assche lep = pg_subpg_pdt_search(pg_code, subpg_code, pdt,
8802*44704f69SBart Van Assche op->vend_prod_num);
8803*44704f69SBart Van Assche if (lep) {
8804*44704f69SBart Van Assche /* Below is the indirect function call to all the
8805*44704f69SBart Van Assche * show_* functions */
8806*44704f69SBart Van Assche if (lep->show_pagep)
8807*44704f69SBart Van Assche (*lep->show_pagep)(bp, n, op, jop);
8808*44704f69SBart Van Assche else
8809*44704f69SBart Van Assche sgj_pr_hr(jsp, "Unable to decode %s [%s]\n",
8810*44704f69SBart Van Assche lep->name, lep->acron);
8811*44704f69SBart Van Assche } else {
8812*44704f69SBart Van Assche nn = sg_scnpr(b, blen, "Unable to decode page=0x%x",
8813*44704f69SBart Van Assche pg_code);
8814*44704f69SBart Van Assche if (subpg_code > 0)
8815*44704f69SBart Van Assche sg_scnpr(b + nn, blen - nn, ", subpage=0x%x",
8816*44704f69SBart Van Assche subpg_code);
8817*44704f69SBart Van Assche if (pdt >= 0)
8818*44704f69SBart Van Assche sg_scnpr(b + nn, blen - nn, ", pdt=0x%x\n", pdt);
8819*44704f69SBart Van Assche sgj_pr_hr(jsp, "%s\n", b);
8820*44704f69SBart Van Assche }
8821*44704f69SBart Van Assche } /* end of page/subpage search loop */
8822*44704f69SBart Van Assche if (op->pg_arg && (! found)) {
8823*44704f69SBart Van Assche nn = sg_scnpr(b, blen, "Unable to find page=0x%x",
8824*44704f69SBart Van Assche op->pg_code);
8825*44704f69SBart Van Assche if (op->subpg_code > 0)
8826*44704f69SBart Van Assche sg_scnpr(b + nn, blen - nn, ", subpage=0x%x",
8827*44704f69SBart Van Assche op->subpg_code);
8828*44704f69SBart Van Assche sgj_pr_hr(jsp, "%s\n", b);
8829*44704f69SBart Van Assche if (jsp->pr_as_json)
8830*44704f69SBart Van Assche sgj_js_nv_i(jsp, jop, "page_not_found", 1);
8831*44704f69SBart Van Assche }
8832*44704f69SBart Van Assche ret = 0;
8833*44704f69SBart Van Assche goto err_out;
8834*44704f69SBart Van Assche }
8835*44704f69SBart Van Assche if (op->pg_arg) { /* do this for 'sg_logs -p xxx' */
8836*44704f69SBart Van Assche ret = decode_pg_arg(op);
8837*44704f69SBart Van Assche if (ret)
8838*44704f69SBart Van Assche goto err_out;
8839*44704f69SBart Van Assche }
8840*44704f69SBart Van Assche pr2serr("No DEVICE argument given\n\n");
8841*44704f69SBart Van Assche usage_for(1, op);
8842*44704f69SBart Van Assche ret = SG_LIB_FILE_ERROR;
8843*44704f69SBart Van Assche goto err_out;
8844*44704f69SBart Van Assche }
8845*44704f69SBart Van Assche if (op->do_select) {
8846*44704f69SBart Van Assche if (op->do_temperature) {
8847*44704f69SBart Van Assche pr2serr("--select cannot be used with --temperature\n");
8848*44704f69SBart Van Assche ret = SG_LIB_CONTRADICT;
8849*44704f69SBart Van Assche goto err_out;
8850*44704f69SBart Van Assche }
8851*44704f69SBart Van Assche if (op->do_transport) {
8852*44704f69SBart Van Assche pr2serr("--select cannot be used with --transport\n");
8853*44704f69SBart Van Assche ret = SG_LIB_CONTRADICT;
8854*44704f69SBart Van Assche goto err_out;
8855*44704f69SBart Van Assche }
8856*44704f69SBart Van Assche } else if (op->do_raw) {
8857*44704f69SBart Van Assche if (sg_set_binary_mode(STDOUT_FILENO) < 0) {
8858*44704f69SBart Van Assche perror("sg_set_binary_mode");
8859*44704f69SBart Van Assche ret = SG_LIB_FILE_ERROR;
8860*44704f69SBart Van Assche goto err_out;
8861*44704f69SBart Van Assche }
8862*44704f69SBart Van Assche }
8863*44704f69SBart Van Assche if (op->do_all) {
8864*44704f69SBart Van Assche if (op->do_select) {
8865*44704f69SBart Van Assche pr2serr("--all conflicts with --select\n");
8866*44704f69SBart Van Assche ret = SG_LIB_CONTRADICT;
8867*44704f69SBart Van Assche goto err_out;
8868*44704f69SBart Van Assche }
8869*44704f69SBart Van Assche }
8870*44704f69SBart Van Assche if (op->in_fn) {
8871*44704f69SBart Van Assche if (! op->do_select) {
8872*44704f69SBart Van Assche pr2serr("--in=FN can only be used with --select when DEVICE "
8873*44704f69SBart Van Assche "given\n");
8874*44704f69SBart Van Assche ret = SG_LIB_CONTRADICT;
8875*44704f69SBart Van Assche goto err_out;
8876*44704f69SBart Van Assche }
8877*44704f69SBart Van Assche if ((ret = sg_f2hex_arr(op->in_fn, op->do_raw, false, rsp_buff,
8878*44704f69SBart Van Assche &in_len, rsp_buff_sz)))
8879*44704f69SBart Van Assche goto err_out;
8880*44704f69SBart Van Assche if (vb > 2)
8881*44704f69SBart Van Assche pr2serr("Read %d [0x%x] bytes of user supplied data\n", in_len,
8882*44704f69SBart Van Assche in_len);
8883*44704f69SBart Van Assche }
8884*44704f69SBart Van Assche if (op->pg_arg) {
8885*44704f69SBart Van Assche if (op->do_all) {
8886*44704f69SBart Van Assche if (0 == op->do_brief)
8887*44704f69SBart Van Assche pr2serr(">>> warning: --page=%s ignored when --all given\n",
8888*44704f69SBart Van Assche op->pg_arg);
8889*44704f69SBart Van Assche } else {
8890*44704f69SBart Van Assche ret = decode_pg_arg(op);
8891*44704f69SBart Van Assche if (ret)
8892*44704f69SBart Van Assche goto err_out;
8893*44704f69SBart Van Assche }
8894*44704f69SBart Van Assche }
8895*44704f69SBart Van Assche
8896*44704f69SBart Van Assche #ifdef SG_LIB_WIN32
8897*44704f69SBart Van Assche #ifdef SG_LIB_WIN32_DIRECT
8898*44704f69SBart Van Assche win32_spt_init_state = !! scsi_pt_win32_spt_state();
8899*44704f69SBart Van Assche if (vb > 4)
8900*44704f69SBart Van Assche pr2serr("Initial win32 SPT interface state: %s\n",
8901*44704f69SBart Van Assche win32_spt_init_state ? "direct" : "indirect");
8902*44704f69SBart Van Assche #endif
8903*44704f69SBart Van Assche #endif
8904*44704f69SBart Van Assche sg_fd = sg_cmds_open_device(op->device_name, op->o_readonly, vb);
8905*44704f69SBart Van Assche if ((sg_fd < 0) && (! op->o_readonly))
8906*44704f69SBart Van Assche sg_fd = sg_cmds_open_device(op->device_name, true /* ro */, vb);
8907*44704f69SBart Van Assche if (sg_fd < 0) {
8908*44704f69SBart Van Assche pr2serr("error opening file: %s: %s \n", op->device_name,
8909*44704f69SBart Van Assche safe_strerror(-sg_fd));
8910*44704f69SBart Van Assche ret = sg_convert_errno(-sg_fd);
8911*44704f69SBart Van Assche goto err_out;
8912*44704f69SBart Van Assche }
8913*44704f69SBart Van Assche if (op->do_list || op->do_all) {
8914*44704f69SBart Van Assche op->pg_code = SUPP_PAGES_LPAGE;
8915*44704f69SBart Van Assche if ((op->do_list > 1) || (op->do_all > 1))
8916*44704f69SBart Van Assche op->subpg_code = SUPP_SPGS_SUBPG;
8917*44704f69SBart Van Assche }
8918*44704f69SBart Van Assche if (op->do_transport) {
8919*44704f69SBart Van Assche if ((op->pg_code > 0) || (op->subpg_code > 0) ||
8920*44704f69SBart Van Assche op->do_temperature) {
8921*44704f69SBart Van Assche pr2serr("'-T' should not be mixed with options implying other "
8922*44704f69SBart Van Assche "pages\n");
8923*44704f69SBart Van Assche ret = SG_LIB_FILE_ERROR;
8924*44704f69SBart Van Assche goto err_out;
8925*44704f69SBart Van Assche }
8926*44704f69SBart Van Assche op->pg_code = PROTO_SPECIFIC_LPAGE;
8927*44704f69SBart Van Assche }
8928*44704f69SBart Van Assche
8929*44704f69SBart Van Assche memset(&inq_out, 0, sizeof(inq_out));
8930*44704f69SBart Van Assche if (op->no_inq < 2) {
8931*44704f69SBart Van Assche if (sg_simple_inquiry(sg_fd, &inq_out, true, vb)) {
8932*44704f69SBart Van Assche pr2serr("%s doesn't respond to a SCSI INQUIRY\n",
8933*44704f69SBart Van Assche op->device_name);
8934*44704f69SBart Van Assche ret = SG_LIB_CAT_OTHER;
8935*44704f69SBart Van Assche goto err_out;
8936*44704f69SBart Van Assche }
8937*44704f69SBart Van Assche op->dev_pdt = inq_out.peripheral_type;
8938*44704f69SBart Van Assche if ((! op->do_raw) && (0 == op->do_hex) && (! op->do_name) &&
8939*44704f69SBart Van Assche (0 == op->no_inq) && (0 == op->do_brief))
8940*44704f69SBart Van Assche sgj_pr_hr(jsp, " %.8s %.16s %.4s\n", inq_out.vendor,
8941*44704f69SBart Van Assche inq_out.product, inq_out.revision);
8942*44704f69SBart Van Assche memcpy(t10_vendor_str, inq_out.vendor, 8);
8943*44704f69SBart Van Assche memcpy(t10_product_str, inq_out.product, 16);
8944*44704f69SBart Van Assche if (VP_NONE == op->vend_prod_num)
8945*44704f69SBart Van Assche op->deduced_vpn = find_vpn_by_inquiry();
8946*44704f69SBart Van Assche }
8947*44704f69SBart Van Assche
8948*44704f69SBart Van Assche if (op->do_temperature) {
8949*44704f69SBart Van Assche ret = fetchTemperature(sg_fd, rsp_buff, SHORT_RESP_LEN, op, jop);
8950*44704f69SBart Van Assche goto err_out;
8951*44704f69SBart Van Assche }
8952*44704f69SBart Van Assche if (op->do_select) {
8953*44704f69SBart Van Assche k = sg_ll_log_select(sg_fd, op->do_pcreset, op->do_sp,
8954*44704f69SBart Van Assche op->page_control, op->pg_code, op->subpg_code,
8955*44704f69SBart Van Assche rsp_buff, ((in_len > 0) ? in_len : 0), true, vb);
8956*44704f69SBart Van Assche if (k) {
8957*44704f69SBart Van Assche if (SG_LIB_CAT_NOT_READY == k)
8958*44704f69SBart Van Assche pr2serr("log_select: device not ready\n");
8959*44704f69SBart Van Assche else if (SG_LIB_CAT_ILLEGAL_REQ == k)
8960*44704f69SBart Van Assche pr2serr("log_select: field in cdb illegal\n");
8961*44704f69SBart Van Assche else if (SG_LIB_CAT_INVALID_OP == k)
8962*44704f69SBart Van Assche pr2serr("log_select: not supported\n");
8963*44704f69SBart Van Assche else if (SG_LIB_CAT_UNIT_ATTENTION == k)
8964*44704f69SBart Van Assche pr2serr("log_select: unit attention\n");
8965*44704f69SBart Van Assche else if (SG_LIB_CAT_ABORTED_COMMAND == k)
8966*44704f69SBart Van Assche pr2serr("log_select: aborted command\n");
8967*44704f69SBart Van Assche else
8968*44704f69SBart Van Assche pr2serr("log_select: failed (%d), try '-v' for more "
8969*44704f69SBart Van Assche "information\n", k);
8970*44704f69SBart Van Assche }
8971*44704f69SBart Van Assche ret = (k >= 0) ? k : SG_LIB_CAT_OTHER;
8972*44704f69SBart Van Assche goto err_out;
8973*44704f69SBart Van Assche }
8974*44704f69SBart Van Assche if (op->do_list > 2) {
8975*44704f69SBart Van Assche const int supp_pgs_blen = sizeof(supp_pgs_rsp);
8976*44704f69SBart Van Assche
8977*44704f69SBart Van Assche op->subpg_code = NOT_SPG_SUBPG;
8978*44704f69SBart Van Assche res = do_logs(sg_fd, supp_pgs_rsp, supp_pgs_blen, op);
8979*44704f69SBart Van Assche if (res != 0)
8980*44704f69SBart Van Assche goto bad;
8981*44704f69SBart Van Assche su_p_pg_len = sg_get_unaligned_be16(supp_pgs_rsp + 2);
8982*44704f69SBart Van Assche if ((su_p_pg_len + 4) > supp_pgs_blen) {
8983*44704f69SBart Van Assche pr2serr("Supported log pages log page is too long [%d], exit\n",
8984*44704f69SBart Van Assche su_p_pg_len);
8985*44704f69SBart Van Assche res = SG_LIB_CAT_OTHER;
8986*44704f69SBart Van Assche goto bad;
8987*44704f69SBart Van Assche }
8988*44704f69SBart Van Assche op->subpg_code = SUPP_SPGS_SUBPG;
8989*44704f69SBart Van Assche }
8990*44704f69SBart Van Assche resp_len = (op->maxlen > 0) ? op->maxlen : MX_ALLOC_LEN;
8991*44704f69SBart Van Assche res = do_logs(sg_fd, rsp_buff, resp_len, op);
8992*44704f69SBart Van Assche if (0 == res) {
8993*44704f69SBart Van Assche pg_len = sg_get_unaligned_be16(rsp_buff + 2);
8994*44704f69SBart Van Assche if ((pg_len + 4) > resp_len) {
8995*44704f69SBart Van Assche pr2serr("Only fetched %d bytes of response (available: %d "
8996*44704f69SBart Van Assche "bytes)\n truncate output\n",
8997*44704f69SBart Van Assche resp_len, pg_len + 4);
8998*44704f69SBart Van Assche pg_len = resp_len - 4;
8999*44704f69SBart Van Assche }
9000*44704f69SBart Van Assche goto good;
9001*44704f69SBart Van Assche }
9002*44704f69SBart Van Assche bad:
9003*44704f69SBart Van Assche if (SG_LIB_CAT_INVALID_OP == res)
9004*44704f69SBart Van Assche pr2serr("%snot supported\n", ls_s);
9005*44704f69SBart Van Assche else if (SG_LIB_CAT_NOT_READY == res)
9006*44704f69SBart Van Assche pr2serr("%sdevice not ready\n", ls_s);
9007*44704f69SBart Van Assche else if (SG_LIB_CAT_ILLEGAL_REQ == res) {
9008*44704f69SBart Van Assche if ((op->do_list > 2) && (SUPP_SPGS_SUBPG == op->subpg_code)) {
9009*44704f69SBart Van Assche rsp_buff[0] = 0x40;
9010*44704f69SBart Van Assche rsp_buff[1] = SUPP_SPGS_SUBPG;
9011*44704f69SBart Van Assche pg_len = 0;
9012*44704f69SBart Van Assche res = 0;
9013*44704f69SBart Van Assche if (op->verbose)
9014*44704f69SBart Van Assche pr2serr("%sfield in cdb illegal in [0,0xff], "
9015*44704f69SBart Van Assche "continue with merge\n", ls_s);
9016*44704f69SBart Van Assche goto good;
9017*44704f69SBart Van Assche } else
9018*44704f69SBart Van Assche pr2serr("%sfield in cdb illegal\n", ls_s);
9019*44704f69SBart Van Assche } else if (SG_LIB_CAT_UNIT_ATTENTION == res)
9020*44704f69SBart Van Assche pr2serr("%sunit attention\n", ls_s);
9021*44704f69SBart Van Assche else if (SG_LIB_CAT_ABORTED_COMMAND == res)
9022*44704f69SBart Van Assche pr2serr("%saborted command\n", ls_s);
9023*44704f69SBart Van Assche else if (SG_LIB_TRANSPORT_ERROR == res)
9024*44704f69SBart Van Assche pr2serr("%stransport error\n", ls_s);
9025*44704f69SBart Van Assche else
9026*44704f69SBart Van Assche pr2serr("%sother error [%d]\n", ls_s, res);
9027*44704f69SBart Van Assche ret = res;
9028*44704f69SBart Van Assche goto err_out;
9029*44704f69SBart Van Assche
9030*44704f69SBart Van Assche good:
9031*44704f69SBart Van Assche if (op->do_list > 2)
9032*44704f69SBart Van Assche pg_len = merge_both_supported(supp_pgs_rsp + 4, su_p_pg_len, pg_len);
9033*44704f69SBart Van Assche
9034*44704f69SBart Van Assche if (0 == op->do_all) {
9035*44704f69SBart Van Assche if (op->filter_given) {
9036*44704f69SBart Van Assche if (op->do_hex > 2)
9037*44704f69SBart Van Assche hex2stdout(rsp_buff, pg_len + 4, op->dstrhex_no_ascii);
9038*44704f69SBart Van Assche else
9039*44704f69SBart Van Assche decode_page_contents(rsp_buff, pg_len + 4, op, jop);
9040*44704f69SBart Van Assche } else if (op->do_raw)
9041*44704f69SBart Van Assche dStrRaw(rsp_buff, pg_len + 4);
9042*44704f69SBart Van Assche else if (op->do_hex > 1)
9043*44704f69SBart Van Assche hex2stdout(rsp_buff, pg_len + 4, op->dstrhex_no_ascii);
9044*44704f69SBart Van Assche else if (pg_len > 1) {
9045*44704f69SBart Van Assche if (op->do_hex) {
9046*44704f69SBart Van Assche if (rsp_buff[0] & 0x40)
9047*44704f69SBart Van Assche printf("Log page code=0x%x,0x%x, DS=%d, SPF=1, "
9048*44704f69SBart Van Assche "page_len=0x%x\n", rsp_buff[0] & 0x3f, rsp_buff[1],
9049*44704f69SBart Van Assche !!(rsp_buff[0] & 0x80), pg_len);
9050*44704f69SBart Van Assche else
9051*44704f69SBart Van Assche printf("Log page code=0x%x, DS=%d, SPF=0, page_len=0x%x\n",
9052*44704f69SBart Van Assche rsp_buff[0] & 0x3f, !!(rsp_buff[0] & 0x80), pg_len);
9053*44704f69SBart Van Assche hex2stdout(rsp_buff, pg_len + 4, op->dstrhex_no_ascii);
9054*44704f69SBart Van Assche }
9055*44704f69SBart Van Assche else
9056*44704f69SBart Van Assche decode_page_contents(rsp_buff, pg_len + 4, op, jop);
9057*44704f69SBart Van Assche }
9058*44704f69SBart Van Assche }
9059*44704f69SBart Van Assche ret = res;
9060*44704f69SBart Van Assche
9061*44704f69SBart Van Assche if (op->do_all && (pg_len > 1)) {
9062*44704f69SBart Van Assche int my_len = pg_len;
9063*44704f69SBart Van Assche bool spf;
9064*44704f69SBart Van Assche
9065*44704f69SBart Van Assche parr = sg_memalign(parr_sz, 0, &free_parr, false);
9066*44704f69SBart Van Assche if (NULL == parr) {
9067*44704f69SBart Van Assche pr2serr("Unable to allocate heap for parr\n");
9068*44704f69SBart Van Assche ret = sg_convert_errno(ENOMEM);
9069*44704f69SBart Van Assche goto err_out;
9070*44704f69SBart Van Assche }
9071*44704f69SBart Van Assche spf = !!(rsp_buff[0] & 0x40);
9072*44704f69SBart Van Assche if (my_len > parr_sz) {
9073*44704f69SBart Van Assche pr2serr("Unexpectedly large page_len=%d, trim to %d\n", my_len,
9074*44704f69SBart Van Assche parr_sz);
9075*44704f69SBart Van Assche my_len = parr_sz;
9076*44704f69SBart Van Assche }
9077*44704f69SBart Van Assche memcpy(parr, rsp_buff + 4, my_len);
9078*44704f69SBart Van Assche for (k = 0; k < my_len; ++k) {
9079*44704f69SBart Van Assche op->pg_code = parr[k] & 0x3f;
9080*44704f69SBart Van Assche if (spf)
9081*44704f69SBart Van Assche op->subpg_code = parr[++k];
9082*44704f69SBart Van Assche else
9083*44704f69SBart Van Assche op->subpg_code = NOT_SPG_SUBPG;
9084*44704f69SBart Van Assche
9085*44704f69SBart Van Assche /* Some devices include [pg_code, 0xff] for all pg_code > 0 */
9086*44704f69SBart Van Assche if ((op->pg_code > 0) && (SUPP_SPGS_SUBPG == op->subpg_code))
9087*44704f69SBart Van Assche continue; /* skip since no new information */
9088*44704f69SBart Van Assche if ((op->pg_code >= 0x30) && op->exclude_vendor)
9089*44704f69SBart Van Assche continue;
9090*44704f69SBart Van Assche if (! op->do_raw)
9091*44704f69SBart Van Assche sgj_pr_hr(jsp, "\n");
9092*44704f69SBart Van Assche res = do_logs(sg_fd, rsp_buff, resp_len, op);
9093*44704f69SBart Van Assche if (0 == res) {
9094*44704f69SBart Van Assche pg_len = sg_get_unaligned_be16(rsp_buff + 2);
9095*44704f69SBart Van Assche if ((pg_len + 4) > resp_len) {
9096*44704f69SBart Van Assche pr2serr("Only fetched %d bytes of response, truncate "
9097*44704f69SBart Van Assche "output\n", resp_len);
9098*44704f69SBart Van Assche pg_len = resp_len - 4;
9099*44704f69SBart Van Assche }
9100*44704f69SBart Van Assche if (op->do_raw && (! op->filter_given))
9101*44704f69SBart Van Assche dStrRaw(rsp_buff, pg_len + 4);
9102*44704f69SBart Van Assche else if (op->do_hex > 4)
9103*44704f69SBart Van Assche decode_page_contents(rsp_buff, pg_len + 4, op, jop);
9104*44704f69SBart Van Assche else if (op->do_hex > 1)
9105*44704f69SBart Van Assche hex2stdout(rsp_buff, pg_len + 4, op->dstrhex_no_ascii);
9106*44704f69SBart Van Assche else if (1 == op->do_hex) {
9107*44704f69SBart Van Assche if (0 == op->do_brief) {
9108*44704f69SBart Van Assche if (rsp_buff[0] & 0x40)
9109*44704f69SBart Van Assche printf("Log page code=0x%x,0x%x, DS=%d, SPF=1, "
9110*44704f69SBart Van Assche "page_len=0x%x\n", rsp_buff[0] & 0x3f,
9111*44704f69SBart Van Assche rsp_buff[1], !!(rsp_buff[0] & 0x80),
9112*44704f69SBart Van Assche pg_len);
9113*44704f69SBart Van Assche else
9114*44704f69SBart Van Assche printf("Log page code=0x%x, DS=%d, SPF=0, "
9115*44704f69SBart Van Assche "page_len=0x%x\n", rsp_buff[0] & 0x3f,
9116*44704f69SBart Van Assche !!(rsp_buff[0] & 0x80), pg_len);
9117*44704f69SBart Van Assche }
9118*44704f69SBart Van Assche hex2stdout(rsp_buff, pg_len + 4, op->dstrhex_no_ascii);
9119*44704f69SBart Van Assche }
9120*44704f69SBart Van Assche else
9121*44704f69SBart Van Assche decode_page_contents(rsp_buff, pg_len + 4, op, jop);
9122*44704f69SBart Van Assche } else if (SG_LIB_CAT_INVALID_OP == res)
9123*44704f69SBart Van Assche pr2serr("%spage=0x%x,0x%x not supported\n", ls_s,
9124*44704f69SBart Van Assche op->pg_code, op->subpg_code);
9125*44704f69SBart Van Assche else if (SG_LIB_CAT_NOT_READY == res)
9126*44704f69SBart Van Assche pr2serr("%sdevice not ready\n", ls_s);
9127*44704f69SBart Van Assche else if (SG_LIB_CAT_ILLEGAL_REQ == res)
9128*44704f69SBart Van Assche pr2serr("%sfield in cdb illegal [page=0x%x,0x%x]\n", ls_s,
9129*44704f69SBart Van Assche op->pg_code, op->subpg_code);
9130*44704f69SBart Van Assche else if (SG_LIB_CAT_UNIT_ATTENTION == res)
9131*44704f69SBart Van Assche pr2serr("%sunit attention\n", ls_s);
9132*44704f69SBart Van Assche else if (SG_LIB_CAT_ABORTED_COMMAND == res)
9133*44704f69SBart Van Assche pr2serr("%saborted command\n", ls_s);
9134*44704f69SBart Van Assche else
9135*44704f69SBart Van Assche pr2serr("%sfailed, try '-v' for more information\n", ls_s);
9136*44704f69SBart Van Assche }
9137*44704f69SBart Van Assche }
9138*44704f69SBart Van Assche err_out:
9139*44704f69SBart Van Assche if (free_rsp_buff)
9140*44704f69SBart Van Assche free(free_rsp_buff);
9141*44704f69SBart Van Assche if (free_parr)
9142*44704f69SBart Van Assche free(free_parr);
9143*44704f69SBart Van Assche if (sg_fd >= 0)
9144*44704f69SBart Van Assche sg_cmds_close_device(sg_fd);
9145*44704f69SBart Van Assche if (0 == vb) {
9146*44704f69SBart Van Assche if (! sg_if_can2stderr("sg_logs failed: ", ret))
9147*44704f69SBart Van Assche pr2serr("Some error occurred, try again with '-v' or '-vv' for "
9148*44704f69SBart Van Assche "more information\n");
9149*44704f69SBart Van Assche }
9150*44704f69SBart Van Assche if (as_json) {
9151*44704f69SBart Van Assche if (0 == op->do_hex)
9152*44704f69SBart Van Assche sgj_js2file(jsp, NULL, ret, stdout);
9153*44704f69SBart Van Assche sgj_finish(jsp);
9154*44704f69SBart Van Assche }
9155*44704f69SBart Van Assche return (ret >= 0) ? ret : SG_LIB_CAT_OTHER;
9156*44704f69SBart Van Assche }
9157