aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorDouglas Gilbert <dgilbert@interlog.com>2015-11-26 21:12:02 +0000
committerDouglas Gilbert <dgilbert@interlog.com>2015-11-26 21:12:02 +0000
commit1a66c384bcfd9e8e0368f371e636beb4bd5aa890 (patch)
treeb37126c2c83889c91b997e74bd415fd9e9c95f0c /src
parentd2f05037db8ebdd5620f00bd8098e4a68f2a95ca (diff)
downloadsg3_utils-1a66c384bcfd9e8e0368f371e636beb4bd5aa890.tar.gz
sg_ses->ses3r11, sg_rep_zones->zbc-r04, sg_logs+sg_vpd+sg_sanitize->sbc4r07
git-svn-id: https://svn.bingwo.ca/repos/sg3_utils/trunk@648 6180dd3e-e324-4e3e-922d-17de1ae2f315
Diffstat (limited to 'src')
-rw-r--r--src/sg_inq.c5
-rw-r--r--src/sg_logs.c319
-rw-r--r--src/sg_modes.c3
-rw-r--r--src/sg_readcap.c6
-rw-r--r--src/sg_rep_zones.c51
-rw-r--r--src/sg_reset_wp.c6
-rw-r--r--src/sg_sanitize.c15
-rw-r--r--src/sg_ses.c51
-rw-r--r--src/sg_vpd.c139
-rw-r--r--src/sg_zone.c10
10 files changed, 503 insertions, 102 deletions
diff --git a/src/sg_inq.c b/src/sg_inq.c
index 51e57ded..d8335108 100644
--- a/src/sg_inq.c
+++ b/src/sg_inq.c
@@ -41,7 +41,7 @@
#include "sg_cmds_basic.h"
#include "sg_pt.h"
-static const char * version_str = "1.49 20151116"; /* SPC-5 rev 06 */
+static const char * version_str = "1.50 20151119"; /* SPC-5 rev 06 */
/* INQUIRY notes:
* It is recommended that the initial allocation length given to a
@@ -2269,7 +2269,8 @@ decode_x_inq_vpd(unsigned char * buff, int len, int do_hex)
"SIMPSUP=%d\n", !!(buff[5] & 0x20), !!(buff[5] & 0x10),
!!(buff[5] & 0x8), !!(buff[5] & 0x4), !!(buff[5] & 0x2),
!!(buff[5] & 0x1));
- printf(" WU_SUP=%d CRD_SUP=%d NV_SUP=%d V_SUP=%d\n",
+ /* CRD_SUP made obsolete in spc5r04 */
+ printf(" WU_SUP=%d [CRD_SUP=%d] NV_SUP=%d V_SUP=%d\n",
!!(buff[6] & 0x8), !!(buff[6] & 0x4), !!(buff[6] & 0x2),
!!(buff[6] & 0x1));
printf(" P_I_I_SUP=%d LUICLR=%d R_SUP=%d CBCS=%d\n",
diff --git a/src/sg_logs.c b/src/sg_logs.c
index 7aaa9656..29b4bef4 100644
--- a/src/sg_logs.c
+++ b/src/sg_logs.c
@@ -31,7 +31,7 @@
#include "sg_unaligned.h"
#include "sg_pt.h" /* needed for scsi_pt_win32_direct() */
-static const char * version_str = "1.32 20150127"; /* spc5r03 + sbc4r04 */
+static const char * version_str = "1.33 20151123"; /* spc5r03 + sbc4r05 */
#define MX_ALLOC_LEN (0xfffc)
#define SHORT_RESP_LEN 128
@@ -62,9 +62,12 @@ static const char * version_str = "1.32 20150127"; /* spc5r03 + sbc4r04 */
#define NOT_SPG_SUBPG 0x0
#define SUPP_SPGS_SUBPG 0xff
#define LOW_GRP_STATS_SUBPG 0x1
+#define PENDING_DEFECTS_SUBPG 0x1
+#define BACKGROUND_OP_SUBPG 0x2
#define HIGH_GRP_STATS_SUBPG 0x1f
#define CACHE_STATS_SUBPG 0x20
#define ENV_REPORTING_SUBPG 0x1
+#define UTILIZATION_SUBPG 0x1
#define ENV_LIMITS_SUBPG 0x2
#define VENDOR_M 0x1000
@@ -155,10 +158,10 @@ struct log_elem {
/* Returns true if done */
};
-static bool show_supported_pgs_lpage(const uint8_t * resp, int len,
- const struct opts_t * op);
-static bool show_supported_pgs_sub_lpage(const uint8_t * resp, int len,
- const struct opts_t * op);
+static bool show_supported_pgs_page(const uint8_t * resp, int len,
+ const struct opts_t * op);
+static bool show_supported_pgs_sub_page(const uint8_t * resp, int len,
+ const struct opts_t * op);
static bool show_buffer_over_under_run_page(const uint8_t * resp, int len,
const struct opts_t * op);
static bool show_error_counter_page(const uint8_t * resp, int len,
@@ -179,6 +182,8 @@ static bool show_temperature_page(const uint8_t * resp, int len,
const struct opts_t * op);
static bool show_start_stop_page(const uint8_t * resp, int len,
const struct opts_t * op);
+static bool show_utilization_page(const uint8_t * resp, int len,
+ const struct opts_t * op);
static bool show_app_client_page(const uint8_t * resp, int len,
const struct opts_t * op);
static bool show_self_test_page(const uint8_t * resp, int len,
@@ -193,6 +198,10 @@ static bool show_dt_device_status_page(const uint8_t * resp, int len,
const struct opts_t * op);
static bool show_background_scan_results_page(const uint8_t * resp, int len,
const struct opts_t * op);
+static bool show_pending_defects_page(const uint8_t * resp, int len,
+ const struct opts_t * op);
+static bool show_background_op_page(const uint8_t * resp, int len,
+ const struct opts_t * op);
static bool show_element_stats_page(const uint8_t * resp, int len,
const struct opts_t * op);
static bool show_ata_pt_results_page(const uint8_t * resp, int len,
@@ -217,26 +226,27 @@ static bool show_environmental_reporting_page(const uint8_t * resp, int len,
const struct opts_t * op);
static bool show_environmental_limits_page(const uint8_t * resp, int len,
const struct opts_t * op);
-static bool show_data_compression_lpage(const uint8_t * resp, int len,
- const struct opts_t * op);
+static bool show_data_compression_page(const uint8_t * resp, int len,
+ const struct opts_t * op);
static bool show_tape_alert_ssc_page(const uint8_t * resp, int len,
const struct opts_t * op);
static bool show_ie_page(const uint8_t * resp, int len,
const struct opts_t * op);
-static bool show_tape_usage_lpage(const uint8_t * resp, int len,
- const struct opts_t * op);
-static bool show_tape_capacity_lpage(const uint8_t * resp, int len,
+static bool show_tape_usage_page(const uint8_t * resp, int len,
+ const struct opts_t * op);
+static bool show_tape_capacity_page(const uint8_t * resp, int len,
const struct opts_t * op);
static bool show_seagate_cache_page(const uint8_t * resp, int len,
const struct opts_t * op);
static bool show_seagate_factory_page(const uint8_t * resp, int len,
const struct opts_t * op);
+/* elements in page_number/subpage_number order */
static struct log_elem log_arr[] = {
{SUPP_PAGES_LPAGE, 0, 0, -1, 0, "Supported log pages", "sp",
- show_supported_pgs_lpage}, /* 0, 0 */
+ show_supported_pgs_page}, /* 0, 0 */
{SUPP_PAGES_LPAGE, SUPP_SPGS_SUBPG, 0, -1, 0, "Supported log pages and "
- "subpages", "ssp", show_supported_pgs_sub_lpage}, /* 0, 0xff */
+ "subpages", "ssp", show_supported_pgs_sub_page}, /* 0, 0xff */
{BUFF_OVER_UNDER_LPAGE, 0, 0, -1, 0, "Buffer over-run/under-run", "bou",
show_buffer_over_under_run_page}, /* 0x1, 0x0 */
{WRITE_ERR_LPAGE, 0, 0, -1, 0, "Write error", "we",
@@ -267,8 +277,8 @@ static struct log_elem log_arr[] = {
"Environmental limits", "enl", show_environmental_limits_page},
{START_STOP_LPAGE, 0, 0, -1, 0, "Start-stop cycle counter", "sscc",
show_start_stop_page}, /* 0xe, 0x0 */
- {0xe, 0x1, 0, 0, 0, "Utilization", "util",
- NULL}, /* 0xe, 0x1 SBC */ /* sbc4r04 */
+ {START_STOP_LPAGE, UTILIZATION_SUBPG, 0, 0, 0, "Utilization", "util",
+ show_utilization_page}, /* 0xe, 0x1 SBC */ /* sbc4r04 */
{APP_CLIENT_LPAGE, 0, 0, -1, 0, "Application client", "ac",
show_app_client_page}, /* 0xf, 0x0 */
{SELF_TEST_LPAGE, 0, 0, -1, 0, "Self test results", "str",
@@ -287,12 +297,15 @@ static struct log_elem log_arr[] = {
show_media_stats_page}, /* 0x14, 0x0 SMC */
{BACKGROUND_SCAN_LPAGE, 0, 0, 0, 0, "Background scan results", "bsr",
show_background_scan_results_page}, /* 0x15, 0x0 SBC */
+ {BACKGROUND_SCAN_LPAGE, BACKGROUND_OP_SUBPG, 0, 0, 0,
+ "Background operation", "bop", show_background_op_page},
+ /* 0x15, 0x2 SBC */
{0x15, 0, 0, PDT_MCHANGER, 0, "Element statistics", "els",
- show_element_stats_page}, /* 0x15, 0x0 SMC */
+ show_element_stats_page}, /* 0x15, 0x0 SMC */
{0x15, 0, 0, PDT_ADC, 0, "Service buffers information", "sbi",
- NULL}, /* 0x15, 0x0 ADC */
- {BACKGROUND_SCAN_LPAGE, 0x1, 0, 0, 0, "Pending defects", "pd",
- NULL}, /* 0x15, 0x1 SBC */
+ NULL}, /* 0x15, 0x0 ADC */
+ {BACKGROUND_SCAN_LPAGE, PENDING_DEFECTS_SUBPG, 0, 0, 0,
+ "Pending defects", "pd", show_pending_defects_page}, /* 0x15, 0x1 SBC */
{SAT_ATA_RESULTS_LPAGE, 0, 0, 0, 0, "ATA pass-through results", "aptr",
show_ata_pt_results_page}, /* 0x16, 0x0 SAT */
{0x16, 0, 0, PDT_TAPE, 0, "Tape diagnostic data", "tdd",
@@ -314,7 +327,7 @@ static struct log_elem log_arr[] = {
{PCT_LPAGE, 0, 0, -1, 0, "Power condition transitions", "pct",
show_power_condition_transitions_page}, /* 0x1a, 0 */
{0x1b, 0, 0, PDT_TAPE, 0, "Data compression", "dc",
- show_data_compression_lpage}, /* 0x1b, 0 SSC */
+ show_data_compression_page}, /* 0x1b, 0 SSC */
{TAPE_ALERT_LPAGE, 0, 0, PDT_TAPE, 0, "Tape alert", "ta",
show_tape_alert_ssc_page}, /* 0x2e, 0 SSC */
{IE_LPAGE, 0, 0, -1, 0, "Informational exceptions", "ie",
@@ -323,11 +336,11 @@ static struct log_elem log_arr[] = {
{0x30, 0, 0, PDT_TAPE, VENDOR_M, "Performance counters (Hitachi)", "pc_hi",
NULL}, /* 0x30, 0 SBC */
{0x30, 0, 0, PDT_TAPE, VENDOR_M, "Tape usage (lto-5, 6)", "ta_",
- show_tape_usage_lpage}, /* 0x30, 0 SSC */
+ show_tape_usage_page}, /* 0x30, 0 SSC */
{0x31, 0, 0, PDT_TAPE, VENDOR_M, "Tape capacity (lto-5, 6)", "tc_",
- show_tape_capacity_lpage}, /* 0x31, 0 SSC */
+ show_tape_capacity_page}, /* 0x31, 0 SSC */
{0x32, 0, 0, PDT_TAPE, VENDOR_M, "Data compression (ibm)", "dc_",
- show_data_compression_lpage}, /* 0x32, 0 SSC; redirect to 0x1b */
+ show_data_compression_page}, /* 0x32, 0 SSC; redirect to 0x1b */
{0x33, 0, 0, PDT_TAPE, VENDOR_M, "Write errors (lto-5)", "we_",
NULL}, /* 0x33, 0 SSC */
{0x34, 0, 0, PDT_TAPE, VENDOR_M, "Read forward errors (lto-5)", "rfe_",
@@ -604,7 +617,7 @@ enumerate_helper(const struct log_elem * lep, int pos,
}
static void
-enumerate_lpages(const struct opts_t * op)
+enumerate_pages(const struct opts_t * op)
{
int k, j;
struct log_elem * lep;
@@ -1395,8 +1408,8 @@ get_pcb_str(int pcb, char * outp, int maxoutlen)
/* SUPP_PAGES_LPAGE [0x0,0x0] */
static bool
-show_supported_pgs_lpage(const uint8_t * resp, int len,
- const struct opts_t * op)
+show_supported_pgs_page(const uint8_t * resp, int len,
+ const struct opts_t * op)
{
int num, k, pg_code;
const uint8_t * ucp;
@@ -1427,8 +1440,8 @@ show_supported_pgs_lpage(const uint8_t * resp, int len,
/* SUPP_PAGES_LPAGE,SUPP_SPGS_SUBPG [0x0,0xff] or all subpages of a given
* page code: [<pg_code>,0xff] */
static bool
-show_supported_pgs_sub_lpage(const uint8_t * resp, int len,
- const struct opts_t * op)
+show_supported_pgs_sub_page(const uint8_t * resp, int len,
+ const struct opts_t * op)
{
int num, k, pg_code, subpg_code;
const uint8_t * ucp;
@@ -1969,7 +1982,7 @@ skip:
/* Tape usage: Vendor specific (LTO-5 and LTO-6): 0x30 */
static bool
-show_tape_usage_lpage(const uint8_t * resp, int len, const struct opts_t * op)
+show_tape_usage_page(const uint8_t * resp, int len, const struct opts_t * op)
{
int k, num, extra, pc, pcb;
unsigned int n;
@@ -2079,8 +2092,8 @@ show_tape_usage_lpage(const uint8_t * resp, int len, const struct opts_t * op)
/* Tape capacity: vendor specific (IBM): 0x31 */
static bool
-show_tape_capacity_lpage(const uint8_t * resp, int len,
- const struct opts_t * op)
+show_tape_capacity_page(const uint8_t * resp, int len,
+ const struct opts_t * op)
{
int k, num, extra, pc, pcb;
unsigned int n;
@@ -2147,8 +2160,8 @@ show_tape_capacity_lpage(const uint8_t * resp, int len,
/* Data compression: originally vendor specific 0x32 (IBM), then
* ssc-4 standardizes it at 0x1b */
static bool
-show_data_compression_lpage(const uint8_t * resp, int len,
- const struct opts_t * op)
+show_data_compression_page(const uint8_t * resp, int len,
+ const struct opts_t * op)
{
int k, j, pl, num, extra, pc, pcb, pg_code;
uint64_t n;
@@ -2773,7 +2786,7 @@ show_ie_page(const uint8_t * resp, int len, const struct opts_t * op)
return true;
}
-/* helper for SAS port of PROTO_SPECIFIC_LPAGE [0x18] */
+/* called for SAS port of PROTO_SPECIFIC_LPAGE [0x18] */
static void
show_sas_phy_event_info(int pes, unsigned int val, unsigned int thresh_val)
{
@@ -2801,6 +2814,12 @@ show_sas_phy_event_info(int pes, unsigned int val, unsigned int thresh_val)
case 0x6:
printf(" Received ERROR count: %u\n", val);
break;
+ case 0x7:
+ printf(" Invalid SPL packet count: %u\n", val);
+ break;
+ case 0x8:
+ printf(" Loss of SPL packet synchronization count: %u\n", val);
+ break;
case 0x20:
printf(" Received address frame error count: %u\n", val);
break;
@@ -2864,6 +2883,9 @@ show_sas_phy_event_info(int pes, unsigned int val, unsigned int thresh_val)
printf(" Peak connection time (us): %u\n", val);
printf(" Peak value detector threshold: %u\n", thresh_val);
break;
+ case 0x2f:
+ printf(" Persistent connection count: %u\n", val);
+ break;
case 0x40:
printf(" Transmitted SSP frame count: %u\n", val);
break;
@@ -3060,6 +3082,9 @@ show_sas_port_param(const uint8_t * ucp, int param_len,
case 0xb:
snprintf(s, sz, "12 Gbps");
break;
+ case 0xc:
+ snprintf(s, sz, "22.5 Gbps");
+ break;
default:
snprintf(s, sz, "reserved [%d]", t);
break;
@@ -3880,7 +3905,7 @@ static bool
show_lb_provisioning_page(const uint8_t * resp, int len,
const struct opts_t * op)
{
- int j, num, pl, pc, pcb;
+ int num, pl, pc, pcb;
const uint8_t * ucp;
const char * cp;
char str[PCB_STR_LEN];
@@ -3911,6 +3936,9 @@ show_lb_provisioning_page(const uint8_t * resp, int len,
case 0x2:
cp = " Used LBA mapping threshold";
break;
+ case 0x3:
+ cp = " Available provisioning resource percentage";
+ break;
case 0x100:
cp = " De-duplicated LBA";
break;
@@ -3925,7 +3953,6 @@ show_lb_provisioning_page(const uint8_t * resp, int len,
break;
}
if (cp) {
- printf(" %s resource count:", cp);
if ((pl < 8) || (num < 8)) {
if (num < 8)
pr2serr("\n truncated by response length, expected at "
@@ -3935,8 +3962,12 @@ show_lb_provisioning_page(const uint8_t * resp, int len,
pl);
break;
}
- j = (ucp[4] << 24) + (ucp[5] << 16) + (ucp[6] << 8) + ucp[7];
- printf(" %d\n", j);
+ if (0x3 == pc)
+ printf(" %s: %u %%\n", cp, sg_get_unaligned_be16(ucp + 4));
+ else {
+ printf(" %s resource count:", cp);
+ printf(" %u\n", sg_get_unaligned_be32(ucp + 4));
+ }
if (pl > 8) {
switch (ucp[8] & 0x3) {
case 0: cp = "not reported"; break;
@@ -3966,6 +3997,79 @@ skip:
return true;
}
+/* UTILIZATION_SUBPG [0xe,0x1] introduced: SBC-4 */
+static bool
+show_utilization_page(const uint8_t * resp, int len, const struct opts_t * op)
+{
+ int num, pl, pc, pcb, k;
+ const uint8_t * ucp;
+ char str[PCB_STR_LEN];
+
+ if (op->verbose || ((0 == op->do_raw) && (0 == op->do_hex)))
+ printf("Utilization page [0xe,0x1]\n");
+ num = len - 4;
+ ucp = &resp[0] + 4;
+ while (num > 3) {
+ pc = (ucp[0] << 8) | ucp[1];
+ pcb = ucp[2];
+ pl = ucp[3] + 4;
+ if (op->filter_given) {
+ if (pc != op->filter)
+ goto skip;
+ if (op->do_raw) {
+ dStrRaw((const char *)ucp, pl);
+ break;
+ } else if (op->do_hex) {
+ dStrHex((const char *)ucp, pl, ((1 == op->do_hex) ? 1 : -1));
+ break;
+ }
+ }
+ switch (pc) {
+ case 0x0:
+ printf(" Workload utilization:");
+ if ((pl < 6) || (num < 6)) {
+ if (num < 6)
+ pr2serr("\n truncated by response length, expected "
+ "at least 6 bytes\n");
+ else
+ pr2serr("\n parameter length >= 6 expected, got %d\n",
+ pl);
+ break;
+ }
+ k = sg_get_unaligned_be16(ucp + 4);
+ printf(" %d.%02d %%\n", k / 100, k % 100);
+ break;
+ case 0x1:
+ printf(" Utilization usage rate based on date and time:");
+ if ((pl < 6) || (num < 6)) {
+ if (num < 6)
+ pr2serr("\n truncated by response length, expected "
+ "at least 6 bytes\n");
+ else
+ pr2serr("\n parameter length >= 6 expected, got %d\n",
+ pl);
+ break;
+ }
+ printf(" %d %%\n", ucp[4]);
+ break;
+ default:
+ printf(" Reserved [parameter_code=0x%x]:\n", pc);
+ dStrHex((const char *)ucp, ((pl < num) ? pl : num), 0);
+ break;
+ }
+ if (op->do_pcb) {
+ get_pcb_str(pcb, str, sizeof(str));
+ printf(" <%s>\n", str);
+ }
+ if (op->filter_given)
+ break;
+skip:
+ num -= pl;
+ ucp += pl;
+ }
+ return true;
+}
+
/* SOLID_STATE_MEDIA_LPAGE [0x11] introduced: SBC-3 */
static bool
show_solid_state_media_page(const uint8_t * resp, int len,
@@ -4006,7 +4110,7 @@ show_solid_state_media_page(const uint8_t * resp, int len,
pl);
break;
}
- printf(" %d%%\n", ucp[7]);
+ printf(" %u %%\n", ucp[7]);
break;
default:
printf(" Reserved [parameter_code=0x%x]:\n", pc);
@@ -4308,10 +4412,10 @@ show_background_scan_results_page(const uint8_t * resp, int len,
printf(" Number of background scans performed: %d\n", j);
j = (ucp[12] << 8) + ucp[13];
#ifdef SG_LIB_MINGW
- printf(" Background medium scan progress: %g%%\n",
+ printf(" Background medium scan progress: %g %%\n",
(double)(j * 100.0 / 65536.0));
#else
- printf(" Background medium scan progress: %.2f%%\n",
+ printf(" Background medium scan progress: %.2f %%\n",
(double)(j * 100.0 / 65536.0));
#endif
j = (ucp[14] << 8) + ucp[15];
@@ -4383,6 +4487,137 @@ skip:
return true;
}
+/* PENDING_DEFECTS_SUBPG [0x15,0x1] introduced: SBC-4 */
+static bool
+show_pending_defects_page(const uint8_t * resp, int len,
+ const struct opts_t * op)
+{
+ int num, pl, pc, pcb;
+ const uint8_t * ucp;
+ char str[PCB_STR_LEN];
+
+ if (op->verbose || ((0 == op->do_raw) && (0 == op->do_hex)))
+ printf("Pending defects page [0x15,0x1]\n");
+ num = len - 4;
+ ucp = &resp[0] + 4;
+ while (num > 3) {
+ pc = (ucp[0] << 8) | ucp[1];
+ pcb = ucp[2];
+ pl = ucp[3] + 4;
+ if (op->filter_given) {
+ if (pc != op->filter)
+ goto skip;
+ if (op->do_raw) {
+ dStrRaw((const char *)ucp, pl);
+ break;
+ } else if (op->do_hex) {
+ dStrHex((const char *)ucp, pl, ((1 == op->do_hex) ? 1 : -1));
+ break;
+ }
+ }
+ switch (pc) {
+ case 0x0:
+ printf(" Pending defect count:");
+ if ((pl < 8) || (num < 8)) {
+ if (num < 8)
+ pr2serr("\n truncated by response length, expected "
+ "at least 8 bytes\n");
+ else
+ pr2serr("\n parameter length >= 8 expected, got %d\n",
+ pl);
+ break;
+ }
+ printf(" %u\n", sg_get_unaligned_be32(ucp + 4));
+ break;
+ default:
+ printf(" Pending defect: %d\n", pc);
+ if ((pl < 16) || (num < 16)) {
+ if (num < 16)
+ pr2serr("\n truncated by response length, expected "
+ "at least 16 bytes\n");
+ else
+ pr2serr("\n parameter length >= 16 expected, got %d\n",
+ pl);
+ break;
+ }
+ printf(" LBA: 0x%" PRIx64 " accumulated_power_on_hours: %u\n",
+ sg_get_unaligned_be64(ucp + 8),
+ sg_get_unaligned_be32(ucp + 4));
+ break;
+ }
+ if (op->do_pcb) {
+ get_pcb_str(pcb, str, sizeof(str));
+ printf(" <%s>\n", str);
+ }
+ if (op->filter_given)
+ break;
+skip:
+ num -= pl;
+ ucp += pl;
+ }
+ return true;
+}
+
+/* BACKGROUND_OP_SUBPG [0x15,0x2] introduced: SBC-4 rev 7 */
+static bool
+show_background_op_page(const uint8_t * resp, int len,
+ const struct opts_t * op)
+{
+ int num, pl, pc, pcb;
+ const uint8_t * ucp;
+ char str[PCB_STR_LEN];
+
+ if (op->verbose || ((0 == op->do_raw) && (0 == op->do_hex)))
+ printf("Background operation page [0x15,0x2]\n");
+ num = len - 4;
+ ucp = &resp[0] + 4;
+ while (num > 3) {
+ pc = (ucp[0] << 8) | ucp[1];
+ pcb = ucp[2];
+ pl = ucp[3] + 4;
+ if (op->filter_given) {
+ if (pc != op->filter)
+ goto skip;
+ if (op->do_raw) {
+ dStrRaw((const char *)ucp, pl);
+ break;
+ } else if (op->do_hex) {
+ dStrHex((const char *)ucp, pl, ((1 == op->do_hex) ? 1 : -1));
+ break;
+ }
+ }
+ switch (pc) {
+ case 0x0:
+ printf(" Background operation:");
+ if ((pl < 8) || (num < 8)) {
+ if (num < 8)
+ pr2serr("\n truncated by response length, expected "
+ "at least 8 bytes\n");
+ else
+ pr2serr("\n parameter length >= 8 expected, got %d\n",
+ pl);
+ break;
+ }
+ printf(" BO_STATUS=%d\n", ucp[4]);
+ break;
+ default:
+ printf(" Reserved [parameter_code=0x%x]:\n", pc);
+ dStrHex((const char *)ucp, ((pl < num) ? pl : num), 0);
+ break;
+ }
+ if (op->do_pcb) {
+ get_pcb_str(pcb, str, sizeof(str));
+ printf(" <%s>\n", str);
+ }
+ if (op->filter_given)
+ break;
+skip:
+ num -= pl;
+ ucp += pl;
+ }
+ return true;
+}
+
/* Sequential access device page [0xc] for tape */
static bool
show_sequential_access_page(const uint8_t * resp, int len,
@@ -5516,7 +5751,7 @@ show_ascii_page(const uint8_t * resp, int len, const struct opts_t * op)
pg_code = resp[0] & 0x3f;
subpg_code = spf ? resp[1] : 0;
if ((SUPP_SPGS_SUBPG == subpg_code) && (SUPP_PAGES_LPAGE != pg_code)) {
- done = show_supported_pgs_sub_lpage(resp, len, op);
+ done = show_supported_pgs_sub_page(resp, len, op);
if (done)
return;
}
@@ -5672,7 +5907,7 @@ main(int argc, char * argv[])
if (op->device_name && op->verbose)
pr2serr("Warning: device: %s is being ignored\n",
op->device_name);
- enumerate_lpages(op);
+ enumerate_pages(op);
return 0;
}
diff --git a/src/sg_modes.c b/src/sg_modes.c
index ed6ffdfa..c9383956 100644
--- a/src/sg_modes.c
+++ b/src/sg_modes.c
@@ -26,7 +26,7 @@
#include "sg_lib.h"
#include "sg_cmds_basic.h"
-static const char * version_str = "1.46 20150511";
+static const char * version_str = "1.47 20151123";
#define DEF_ALLOC_LEN (1024 * 4)
#define DEF_6_ALLOC_LEN 252
@@ -555,6 +555,7 @@ static struct page_code_desc pc_desc_disk[] = {
{0x8, 0x0, "Caching"},
{0xa, 0x2, "Application tag"},
{0xa, 0x5, "IO advice hints grouping"}, /* added sbc4r06 */
+ {0xa, 0x6, "Background operation control"}, /* added sbc4r07 */
{0xa, 0xf1, "Parallel ATA control (SAT)"},
{0xa, 0xf2, "Reserved (SATA control) (SAT)"},
{0xb, 0x0, "Medium types supported (obsolete)"},
diff --git a/src/sg_readcap.c b/src/sg_readcap.c
index 4a0220cf..e1d66886 100644
--- a/src/sg_readcap.c
+++ b/src/sg_readcap.c
@@ -1,7 +1,7 @@
/* This code is does a SCSI READ CAPACITY command on the given device
and outputs the result.
-* Copyright (C) 1999 - 2014 D. Gilbert
+* Copyright (C) 1999 - 2015 D. Gilbert
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
@@ -30,7 +30,7 @@
#include "sg_unaligned.h"
-static const char * version_str = "3.93 20141220";
+static const char * version_str = "3.94 20151126";
#define ME "sg_readcap: "
@@ -380,7 +380,7 @@ rc_basis_str(int rc_basis, char * b, int blen)
snprintf(b, blen, "last contiguous that's not seq write required");
break;
case 1:
- snprintf(b, blen, "last LBA on device");
+ snprintf(b, blen, "last LBA on logical unit");
break;
default:
snprintf(b, blen, "reserved (0x%x)", rc_basis);
diff --git a/src/sg_rep_zones.c b/src/sg_rep_zones.c
index d1ba7d80..4ea90f36 100644
--- a/src/sg_rep_zones.c
+++ b/src/sg_rep_zones.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014 Douglas Gilbert.
+ * Copyright (c) 2014-2015 Douglas Gilbert.
* All rights reserved.
* Use of this source code is governed by a BSD-style
* license that can be found in the BSD_LICENSE file.
@@ -32,7 +32,7 @@
* and decodes the response. Based on zbc-r02.pdf
*/
-static const char * version_str = "1.04 20141215";
+static const char * version_str = "1.05 20151126";
#define MAX_RZONES_BUFF_LEN (1024 * 1024)
#define DEF_RZONES_BUFF_LEN (1024 * 8)
@@ -49,6 +49,7 @@ static struct option long_options[] = {
{"help", no_argument, 0, 'h'},
{"hex", no_argument, 0, 'H'},
{"maxlen", required_argument, 0, 'm'},
+ {"partial", no_argument, 0, 'p'},
{"raw", no_argument, 0, 'r'},
{"readonly", no_argument, 0, 'R'},
{"report", required_argument, 0, 'o'},
@@ -83,8 +84,8 @@ static void
usage()
{
pr2serr("Usage: "
- "sg_rep_zones [--help] [--hex] [--maxlen=LEN] [--raw]\n"
- " [--readonly] [--report=OPT] "
+ "sg_rep_zones [--help] [--hex] [--maxlen=LEN] [--partial]\n"
+ " [--raw] [--readonly] [--report=OPT] "
"[--start=LBA]\n"
" [--verbose] [--version] DEVICE\n");
pr2serr(" where:\n"
@@ -95,9 +96,11 @@ usage()
" --maxlen=LEN|-m LEN max response length (allocation "
"length in cdb)\n"
" (def: 0 -> 8192 bytes)\n"
+ " --partial|-p sets PARTIAL bit in cdb\n"
" --raw|-r output response in binary\n"
" --readonly|-R open DEVICE read-only (def: read-write)\n"
- " --report=OPT|-o OP reporting option (def: 0)\n"
+ " --report=OPT|-o OP reporting options (def: 0: all "
+ "zones)\n"
" --start=LBA|-s LBA report zones from the LBA (def: 0)\n"
" need not be a zone starting LBA\n"
" --verbose|-v increase verbosity\n"
@@ -108,8 +111,9 @@ usage()
/* Invokes a SCSI REPORT ZONES command (ZBC). Return of 0 -> success,
* various SG_LIB_CAT_* positive values or -1 -> other errors */
static int
-sg_ll_report_zones(int sg_fd, uint64_t zs_lba, int report_opts, void * resp,
- int mx_resp_len, int * residp, int noisy, int verbose)
+sg_ll_report_zones(int sg_fd, uint64_t zs_lba, int partial, int report_opts,
+ void * resp, int mx_resp_len, int * residp, int noisy,
+ int verbose)
{
int k, ret, res, sense_cat;
unsigned char rzCmdBlk[SG_ZONING_IN_CMDLEN] =
@@ -120,7 +124,9 @@ sg_ll_report_zones(int sg_fd, uint64_t zs_lba, int report_opts, void * resp,
sg_put_unaligned_be64(zs_lba, rzCmdBlk + 2);
sg_put_unaligned_be32((uint32_t)mx_resp_len, rzCmdBlk + 10);
- rzCmdBlk[14] = report_opts & 0xf;
+ rzCmdBlk[14] = report_opts & 0x3f;
+ if (partial)
+ rzCmdBlk[14] |= 0x80;
if (verbose) {
pr2serr(" Report zones cdb: ");
for (k = 0; k < SG_ZONING_IN_CMDLEN; ++k)
@@ -216,6 +222,12 @@ zone_condition_str(int zc, char * b, int blen, int vb)
case 2:
cp = "Open";
break;
+ case 3:
+ cp = "Explicit open";
+ break;
+ case 4:
+ cp = "Closed";
+ break;
case 0xd:
cp = "Read only";
break;
@@ -239,11 +251,14 @@ zone_condition_str(int zc, char * b, int blen, int vb)
return b;
}
-static const char * same_desc_arr[4] = {
+static const char * same_desc_arr[16] = {
"zone type and length may differ in each descriptor",
"zone type and length same in each descriptor",
"zone type and length same apart from length in last descriptor",
- "Reserved",
+ "zone type for each descriptor may be different",
+ "Reserved [0x4]", "Reserved [0x5]", "Reserved [0x6]", "Reserved [0x7]",
+ "Reserved [0x8]", "Reserved [0x9]", "Reserved [0xa]", "Reserved [0xb]",
+ "Reserved [0xc]", "Reserved [0xd]", "Reserved [0xe]", "Reserved [0xf]",
};
@@ -253,6 +268,7 @@ main(int argc, char * argv[])
int sg_fd, k, res, c, zl_len, len, zones, resid, rlen, zt, zc, same;
int do_hex = 0;
int maxlen = 0;
+ int do_partial = 0;
int do_raw = 0;
int o_readonly = 0;
int reporting_opt = 0;
@@ -268,7 +284,7 @@ main(int argc, char * argv[])
while (1) {
int option_index = 0;
- c = getopt_long(argc, argv, "hHm:o:rRs:vV", long_options,
+ c = getopt_long(argc, argv, "hHm:o:prRs:vV", long_options,
&option_index);
if (c == -1)
break;
@@ -291,12 +307,15 @@ main(int argc, char * argv[])
break;
case 'o':
reporting_opt = sg_get_num(optarg);
- if ((reporting_opt < 0) || (reporting_opt > 15)) {
+ if ((reporting_opt < 0) || (reporting_opt > 63)) {
pr2serr("bad argument to '--report=OPT', expect 0 to "
- "15\n");
+ "63\n");
return SG_LIB_SYNTAX_ERROR;
}
break;
+ case 'p':
+ ++do_partial;
+ break;
case 'r':
++do_raw;
break;
@@ -365,8 +384,8 @@ main(int argc, char * argv[])
return SG_LIB_CAT_OTHER;
}
- res = sg_ll_report_zones(sg_fd, st_lba, reporting_opt, reportZonesBuff,
- maxlen, &resid, 1, verbose);
+ res = sg_ll_report_zones(sg_fd, st_lba, do_partial, reporting_opt,
+ reportZonesBuff, maxlen, &resid, 1, verbose);
ret = res;
if (0 == res) {
rlen = maxlen - resid;
@@ -399,7 +418,7 @@ main(int argc, char * argv[])
ret = SG_LIB_CAT_MALFORMED;
goto the_end;
}
- same = reportZonesBuff[4] & 3;
+ same = reportZonesBuff[4] & 0xf;
printf(" Same=%d: %s\n\n", same, same_desc_arr[same]);
zones = (len - 64) / 64;
for (k = 0, ucp = reportZonesBuff + 64; k < zones; ++k, ucp += 64) {
diff --git a/src/sg_reset_wp.c b/src/sg_reset_wp.c
index bc614e02..8d1acc8c 100644
--- a/src/sg_reset_wp.c
+++ b/src/sg_reset_wp.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014 Douglas Gilbert.
+ * Copyright (c) 2014-2015 Douglas Gilbert.
* All rights reserved.
* Use of this source code is governed by a BSD-style
* license that can be found in the BSD_LICENSE file.
@@ -29,10 +29,10 @@
*
*
* This program issues the SCSI RESET WRITE POINTER command to the given SCSI
- * device. Based on zbc-r02.pdf .
+ * device. Based on zbc-r04c.pdf .
*/
-static const char * version_str = "1.02 20141215";
+static const char * version_str = "1.03 20151126";
#define SG_ZONING_OUT_CMDLEN 16
#define RESET_WRITE_POINTER_SA 0x4
diff --git a/src/sg_sanitize.c b/src/sg_sanitize.c
index 96b9e317..4ec2eb0c 100644
--- a/src/sg_sanitize.c
+++ b/src/sg_sanitize.c
@@ -26,7 +26,7 @@
#include "sg_cmds_basic.h"
#include "sg_cmds_extra.h"
-static const char * version_str = "0.97 20150511";
+static const char * version_str = "0.98 20151123";
/* Not all environments support the Unix sleep() */
#if defined(MSC_VER) || defined(__MINGW32__)
@@ -97,6 +97,7 @@ struct opts_t {
int verbose;
int wait;
int zero;
+ int znr;
const char * pattern_fn;
};
@@ -111,7 +112,7 @@ usage()
"[--overwrite]\n"
" [--pattern=PF] [--quick] [--test=TE] "
"[--verbose]\n"
- " [--version] [--wait] DEVICE\n"
+ " [--version] [--wait] [--zero] [--znr] DEVICE\n"
" where:\n"
" --ause|-A set AUSE bit in cdb\n"
" --block|-B do BLOCK ERASE sanitize\n"
@@ -146,7 +147,8 @@ usage()
" --wait|-w wait for command to finish (could "
"take hours)\n"
" --zero|-z use pattern of zeros for "
- "OVERWRITE\n\n"
+ "OVERWRITE\n"
+ " --znr|-Z set ZNR (zone no reset) bit in cdb\n\n"
"Performs a SCSI SANITIZE command.\n <<<WARNING>>>: all data "
"on DEVICE will be lost.\nDefault action is to give user time to "
"reconsider; then execute SANITIZE\ncommand with IMMED bit set; "
@@ -184,6 +186,8 @@ do_sanitize(int sg_fd, const struct opts_t * op, const void * param_lstp,
return SG_LIB_SYNTAX_ERROR;
if (immed)
sanCmdBlk[1] |= 0x80;
+ if (op->znr) /* added sbc4r07 */
+ sanCmdBlk[1] |= 0x40;
if (op->ause)
sanCmdBlk[1] |= 0x20;
sanCmdBlk[7] = ((param_lst_len >> 8) & 0xff);
@@ -433,7 +437,7 @@ main(int argc, char * argv[])
while (1) {
int option_index = 0;
- c = getopt_long(argc, argv, "ABc:CdeFhi:IOp:QT:vVwz", long_options,
+ c = getopt_long(argc, argv, "ABc:CdeFhi:IOp:QT:vVwzZ", long_options,
&option_index);
if (c == -1)
break;
@@ -508,6 +512,9 @@ main(int argc, char * argv[])
case 'z':
++op->zero;
break;
+ case 'Z':
+ ++op->znr;
+ break;
default:
fprintf(stderr, "unrecognised option code 0x%x ??\n", c);
usage();
diff --git a/src/sg_ses.c b/src/sg_ses.c
index ceaa0fdf..29a76a92 100644
--- a/src/sg_ses.c
+++ b/src/sg_ses.c
@@ -30,7 +30,7 @@
* commands tailored for SES (enclosure) devices.
*/
-static const char * version_str = "2.02 20151029"; /* ses3r08 */
+static const char * version_str = "2.03 20151126"; /* ses3r08->11 */
#define MX_ALLOC_LEN ((64 * 1024) - 4) /* max allowable for big enclosures */
#define MX_ELEM_HDR 1024
@@ -416,10 +416,14 @@ static struct acronym2tuple ecs_a2t_arr[] = {
{"disable_elm", COMM_PORT_ETC, 3, 0, 1, "disable communication port"},
{"devoff", DEVICE_ETC, 3, 4, 1, NULL}, /* device off */
{"devoff", ARRAY_DEV_ETC, 3, 4, 1, NULL},
- {"dnr", DEVICE_ETC, 2, 6, 1, "do not remove"},
{"disp_mode", DISPLAY_ETC, 1, 1, 2, NULL},
{"disp_char", DISPLAY_ETC, 2, 7, 16, NULL},
{"dnr", ARRAY_DEV_ETC, 2, 6, 1, "do not remove"},
+ {"dnr", COOLING_ETC, 1, 6, 1, "do not remove"},
+ {"dnr", DEVICE_ETC, 2, 6, 1, "do not remove"},
+ {"dnr", ENC_ELECTRONICS_ETC, 1, 5, 1, "do not remove"},
+ {"dnr", POWER_SUPPLY_ETC, 1, 6, 1, "do not remove"},
+ {"dnr", UI_POWER_SUPPLY_ETC, 3, 3, 1, "do not remove"},
{"enable", SCSI_IPORT_ETC, 3, 0, 1, NULL},
{"enable", SCSI_TPORT_ETC, 3, 0, 1, NULL},
{"fail", AUD_ALARM_ETC, 1, 6, 1, NULL},
@@ -1909,10 +1913,12 @@ enc_status_helper(const char * pad, const unsigned char * statp, int etype,
printf("%sDevice bypassed B=%d\n", pad, !!(statp[3] & 0x1));
break;
case POWER_SUPPLY_ETC:
- if (nofilter || ((0x80 & statp[1]) || (0xe & statp[2])))
- printf("%sIdent=%d, DC overvoltage=%d, DC undervoltage=%d, DC "
- "overcurrent=%d\n", pad, !!(statp[1] & 0x80),
- !!(statp[2] & 0x8), !!(statp[2] & 0x4), !!(statp[2] & 0x2));
+ if (nofilter || ((0xc0 & statp[1]) || (0xe & statp[2])))
+ printf("%sIdent=%d, Do not remove=%d, DC overvoltage=%d, "
+ "DC undervoltage=%d\n", pad, !!(statp[1] & 0x80),
+ !!(statp[1] & 0x40), !!(statp[2] & 0x8),
+ !!(statp[2] & 0x4));
+ printf("%s DC overcurrent=%d\n", pad, !!(statp[2] & 0x2));
if (nofilter || (0xf8 & statp[3]))
printf("%sHot swap=%d, Fail=%d, Requested on=%d, Off=%d, "
"Overtmp fail=%d\n", pad, !!(statp[3] & 0x80),
@@ -1925,12 +1931,12 @@ enc_status_helper(const char * pad, const unsigned char * statp, int etype,
break;
case COOLING_ETC:
if (nofilter || ((0xc0 & statp[1]) || (0xf0 & statp[3])))
- printf("%sIdent=%d, Hot swap=%d, Fail=%d, Requested on=%d, "
- "Off=%d\n", pad, !!(statp[1] & 0x80), !!(statp[3] & 0x80),
- !!(statp[3] & 0x40), !!(statp[3] & 0x20),
- !!(statp[3] & 0x10));
- printf("%sActual speed=%d rpm, Fan %s\n", pad,
- (((0x7 & statp[1]) << 8) + statp[2]) * 10,
+ printf("%sIdent=%d, Do not remove=%d, Hot swap=%d, Fail=%d, "
+ "Requested on=%d\n", pad, !!(statp[1] & 0x80),
+ !!(statp[1] & 0x40), !!(statp[3] & 0x80),
+ !!(statp[3] & 0x40), !!(statp[3] & 0x20));
+ printf("%sOff=%d, Actual speed=%d rpm, Fan %s\n", pad,
+ !!(statp[3] & 0x10), (((0x7 & statp[1]) << 8) + statp[2]) * 10,
actual_speed_desc[7 & statp[3]]);
break;
case TEMPERATURE_ETC: /* temperature sensor */
@@ -1965,10 +1971,11 @@ enc_status_helper(const char * pad, const unsigned char * statp, int etype,
!!(statp[3] & 0x2), !!(statp[3] & 0x1));
break;
case ENC_ELECTRONICS_ETC: /* enclosure services controller electronics */
- if (nofilter || (0xc0 & statp[1]) || (0x1 & statp[2]) ||
+ if (nofilter || (0xe0 & statp[1]) || (0x1 & statp[2]) ||
(0x80 & statp[3]))
- printf("%sIdent=%d, Fail=%d, Report=%d, Hot swap=%d\n", pad,
- !!(statp[1] & 0x80), !!(statp[1] & 0x40),
+ printf("%sIdent=%d, Fail=%d, Do not remove=%d, Report=%d, "
+ "Hot swap=%d\n", pad, !!(statp[1] & 0x80),
+ !!(statp[1] & 0x40), !!(statp[1] & 0x20),
!!(statp[2] & 0x1), !!(statp[3] & 0x80));
break;
case SCC_CELECTR_ETC: /* SCC controller electronics */
@@ -2017,13 +2024,14 @@ enc_status_helper(const char * pad, const unsigned char * statp, int etype,
"%d\n", pad, !!(statp[2] & 0x80), !!(statp[2] & 0x40),
!!(statp[2] & 0x20), !!(statp[2] & 0x10),
!!(statp[2] & 0x8));
- if (nofilter || ((0x7 & statp[2]) || (0xc3 & statp[3]))) {
+ if (nofilter || ((0x7 & statp[2]) || (0xe3 & statp[3]))) {
printf("%sUPS fail=%d, Warn=%d, Intf fail=%d, Ident=%d, Fail=%d, "
- "Batt fail=%d\n", pad, !!(statp[2] & 0x4),
+ "Do not remove=%d\n", pad, !!(statp[2] & 0x4),
!!(statp[2] & 0x2), !!(statp[2] & 0x1),
!!(statp[3] & 0x80), !!(statp[3] & 0x40),
- !!(statp[3] & 0x2));
- printf("%sBPF=%d\n", pad, !!(statp[3] & 0x1));
+ !!(statp[3] & 0x20));
+ printf("%sBatt fail=%d, BPF=%d\n", pad, !!(statp[3] & 0x2),
+ !!(statp[3] & 0x1));
}
break;
case DISPLAY_ETC: /* Display (ses2r15) */
@@ -2164,8 +2172,9 @@ enc_status_helper(const char * pad, const unsigned char * statp, int etype,
case SAS_CONNECTOR_ETC: /* OC (overcurrent) added in ses3r07 */
printf("%sIdent=%d, %s\n", pad, !!(statp[1] & 0x80),
find_sas_connector_type((statp[1] & 0x7f), bb, sizeof(bb)));
- printf("%sConnector physical link=0x%x, Fail=%d, OC=%d\n", pad,
- statp[2], !!(statp[3] & 0x40), !!(statp[3] & 0x20));
+ printf("%sConnector physical link=0x%x, Mated=%d, Fail=%d, OC=%d\n",
+ pad, statp[2], !!(statp[3] & 0x80), !!(statp[3] & 0x40),
+ !!(statp[3] & 0x20));
break;
default:
if (etype < 0x80)
diff --git a/src/sg_vpd.c b/src/sg_vpd.c
index b5ad4155..5a327c7d 100644
--- a/src/sg_vpd.c
+++ b/src/sg_vpd.c
@@ -36,7 +36,7 @@
*/
-static const char * version_str = "1.05 20150529"; /* spc5r02 + sbc4r05 */
+static const char * version_str = "1.07 20151123"; /* spc5r04 + sbc4r07 */
/* These structures are duplicates of those of the same name in
@@ -113,6 +113,7 @@ int vpd_fetch_page_from_dev(int sg_fd, unsigned char * rp, int page,
#define VPD_DTDE_ADDRESS 0xb4 /* SSC-4 */
#define VPD_BLOCK_DEV_C_EXTENS 0xb5 /* SBC-4 */
#define VPD_ZBC_DEV_CHARS 0xb6 /* ZBC */
+#define VPD_BLOCK_LIMITS_EXT 0xb7 /* SBC-4 */
#define VPD_NO_RATHER_STD_INQ -2 /* request for standard inquiry */
/* Device identification VPD page associations */
@@ -172,6 +173,7 @@ static struct svpd_values_name_t standard_vpd_pg[] = {
{VPD_AUTOMATION_DEV_SN, 0, 1, "adsn", "Automation device serial "
"number (SSC)"},
{VPD_BLOCK_LIMITS, 0, 0, "bl", "Block limits (SBC)"},
+ {VPD_BLOCK_LIMITS_EXT, 0, 0, "ble", "Block limits extension (SBC)"},
{VPD_BLOCK_DEV_CHARS, 0, 0, "bdc", "Block device characteristics "
"(SBC)"},
{VPD_BLOCK_DEV_C_EXTENS, 0, 0, "bdce", "Block device characteristics "
@@ -1778,7 +1780,8 @@ decode_x_inq_vpd(unsigned char * b, int len, int do_hex, int do_long,
printf(" UASK_SUP=%d GROUP_SUP=%d PRIOR_SUP=%d HEADSUP=%d ORDSUP=%d "
"SIMPSUP=%d\n", !!(b[5] & 0x20), !!(b[5] & 0x10), !!(b[5] & 0x8),
!!(b[5] & 0x4), !!(b[5] & 0x2), !!(b[5] & 0x1));
- printf(" WU_SUP=%d CRD_SUP=%d NV_SUP=%d V_SUP=%d\n",
+ /* CRD_SUP made obsolete in spc5r04 */
+ printf(" WU_SUP=%d [CRD_SUP=%d] NV_SUP=%d V_SUP=%d\n",
!!(b[6] & 0x8), !!(b[6] & 0x4), !!(b[6] & 0x2), !!(b[6] & 0x1));
/* CBCS, capability-based command security, obsolete in spc5r01 */
printf(" P_I_I_SUP=%d LUICLR=%d R_SUP=%d CBCS=%d\n",
@@ -1873,7 +1876,8 @@ decode_ata_info_vpd(unsigned char * buff, int len, int do_long, int do_hex)
dWordHex((const unsigned short *)(buff + 60), 256, 0, is_be);
}
-/* VPD_POWER_CONDITION */
+
+/* VPD_POWER_CONDITION 0x8a */
static void
decode_power_condition(unsigned char * buff, int len, int do_hex)
{
@@ -1902,6 +1906,53 @@ decode_power_condition(unsigned char * buff, int len, int do_hex)
sg_get_unaligned_be16(buff + 16));
}
+/* VPD_DEVICE_CONSTITUENTS 0x8b */
+static void
+decode_dev_const_vpd(unsigned char * buff, int len, int do_hex)
+{
+ int k, j, bump, cd_len;
+ unsigned char * ucp;
+
+ if ((1 == do_hex) || (do_hex > 2)) {
+ dStrHex((const char *)buff, len, (1 == do_hex) ? 0 : -1);
+ return;
+ }
+ if (len < 4) {
+ pr2serr("Deice constituents VPD page length too short=%d\n",
+ len);
+ return;
+ }
+ len -= 4;
+ ucp = buff + 4;
+ for (k = 0, j = 0; k < len; k += bump, ucp += bump, ++j) {
+
+
+ printf(" Constituent descriptor %d:\n", j + 1);
+ if ((k + 36) > len) {
+ pr2serr("Device constituents VPD page, short descriptor "
+ "length=36, left=%d\n", (len - k));
+ return;
+ }
+ printf(" Constituent type: 0x%x\n",
+ sg_get_unaligned_be16(ucp + 0));
+ printf(" Constituent device type: 0x%x\n", ucp[2]);
+ printf(" Vendor_identification: %.8s\n", ucp + 4);
+ printf(" Product_identification: %.16s\n", ucp + 12);
+ printf(" Product_revision_level: %.4s\n", ucp + 28);
+ cd_len = sg_get_unaligned_be16(ucp + 34);
+ bump = 36 + cd_len;
+ if ((k + bump) > len) {
+ pr2serr("Device constituents VPD page, short descriptor "
+ "length=%d, left=%d\n", bump, (len - k));
+ return;
+ }
+ if (cd_len > 0) {
+ printf(" Constituent specific descriptor list (in hex):\n");
+ dStrHex((const char *)(ucp + 36), cd_len, 1);
+ }
+ }
+}
+
static const char * power_unit_arr[] =
{
"Gigawatts",
@@ -2536,7 +2587,8 @@ decode_b1_vpd(unsigned char * buff, int len, int do_hex, int pdt)
printf(": reserved\n");
break;
}
- printf(" ZONED=%d\n", (buff[8] >> 4) & 0x3); /* sbc4r04 */
+ printf(" ZONED=%d\n", (buff[8] >> 4) & 0x3); /* sbc4r04 */
+ printf(" BOCS=%d\n", !!(buff[8] & 0x4)); /* sbc4r07 */
printf(" FUAB=%d\n", !!(buff[8] & 0x2));
printf(" VBULS=%d\n", !!(buff[8] & 0x1));
break;
@@ -2567,12 +2619,14 @@ decode_block_lb_prov_vpd(unsigned char * b, int len)
printf(" Write same (10) with unmap bit supported (LBWS10): %d\n",
!!(0x20 & b[5]));
printf(" Logical block provisioning read zeros (LBPRZ): %d\n",
- !!(0x4 & b[5]));
+ (0x7 & (b[5] >> 2)));
printf(" Anchored LBAs supported (ANC_SUP): %d\n", !!(0x2 & b[5]));
dp = !!(b[5] & 0x1);
printf(" Threshold exponent: %d\n", b[4]);
printf(" Descriptor present (DP): %d\n", dp);
+ printf(" Minimum percentage: %d\n", 0x1f & (b[6] >> 3));
printf(" Provisioning type: %d\n", b[6] & 0x7);
+ printf(" Threshold percentage: %d\n", b[7]);
if (dp) {
const unsigned char * ucp;
int i_len, p_id, c_set, piv, assoc, desig_type;
@@ -2878,6 +2932,37 @@ decode_zbdc_vpd(unsigned char * b, int len, int do_hex)
printf("%" PRIu32 "\n", u);
}
+/* VPD_BLOCK_LIMITS_EXT sbc */
+static void
+decode_b7_vpd(unsigned char * buff, int len, int do_hex, int pdt)
+{
+ unsigned int u;
+
+ if (do_hex) {
+ dStrHex((const char *)buff, len, (1 == do_hex) ? 0 : -1);
+ return;
+ }
+ switch (pdt) {
+ case PDT_DISK: case PDT_WO: case PDT_OPTICAL: case PDT_ZBC:
+ if (len < 12) {
+ pr2serr("Block limits extension VPD page length too short=%d\n",
+ len);
+ return;
+ }
+ u = sg_get_unaligned_be16(buff + 6);
+ printf(" Maximum number of streams: %u\n", u);
+ u = sg_get_unaligned_be16(buff + 8);
+ printf(" Optimal stream write size: %u logical blocks\n", u);
+ u = sg_get_unaligned_be32(buff + 10);
+ printf(" Stream granularity size: %u\n", u);
+ break;
+ default:
+ pr2serr(" Unable to decode pdt=0x%x, in hex:\n", pdt);
+ dStrHexErr((const char *)buff, len, 0);
+ break;
+ }
+}
+
/* Returns 0 if successful */
static int
svpd_unable_to_decode(int sg_fd, struct opts_t * op, int subvalue, int off)
@@ -3206,6 +3291,18 @@ svpd_decode_t10(int sg_fd, struct opts_t * op, int subvalue, int off)
return 0;
}
break;
+ case VPD_DEVICE_CONSTITUENTS: /* 0x8b */
+ if (allow_name)
+ printf("Device constituents VPD page:\n");
+ res = vpd_fetch_page_from_dev(sg_fd, rp, pn, op->maxlen, vb, &len);
+ if (0 == res) {
+ if (op->do_raw)
+ dStrRaw((const char *)rp, len);
+ else
+ decode_dev_const_vpd(rp, len, op->do_hex);
+ return 0;
+ }
+ break;
case VPD_POWER_CONSUMPTION: /* 0x8d */
if (allow_name)
printf("Power consumption VPD page:\n");
@@ -3501,6 +3598,34 @@ svpd_decode_t10(int sg_fd, struct opts_t * op, int subvalue, int off)
} else if ((! op->do_raw) && (! op->do_quiet) && (op->do_hex < 3))
printf("VPD page=0xb5\n");
break;
+ case 0xb7:
+ res = vpd_fetch_page_from_dev(sg_fd, rp, pn, op->maxlen, vb, &len);
+ if (0 == res) {
+ pdt = rp[0] & 0x1f;
+ if (allow_name) {
+ switch (pdt) {
+ case PDT_DISK: case PDT_WO: case PDT_OPTICAL: case PDT_ZBC:
+ printf("Block limits extension VPD page (SBC):\n");
+ break;
+ default:
+ printf("VPD page=0x%x, pdt=0x%x:\n", pn, pdt);
+ break;
+ }
+ }
+ if (op->do_raw)
+ dStrRaw((const char *)rp, len);
+ else {
+ pdt = rp[0] & 0x1f;
+ if (vb || long_notquiet)
+ printf(" [PQual=%d Peripheral device type: %s]\n",
+ (rp[0] & 0xe0) >> 5,
+ sg_get_pdt_str(pdt, sizeof(b), b));
+ decode_b7_vpd(rp, len, op->do_hex, pdt);
+ }
+ return 0;
+ } else if ((! op->do_raw) && (! op->do_quiet) && (op->do_hex < 3))
+ printf("VPD page=0xb7\n");
+ break;
default:
return SG_LIB_SYNTAX_ERROR;
}
@@ -3847,6 +3972,10 @@ main(int argc, char * argv[])
if (f2hex_arr(op->inhex_fn, op->do_raw, 0, rsp_buff, &inhex_len,
sizeof(rsp_buff)))
return SG_LIB_FILE_ERROR;
+ if (op->verbose > 2)
+ pr2serr("Read %d bytes of user supplied data\n", inhex_len);
+ if (op->verbose > 3)
+ dStrHexErr((const char *)rsp_buff, inhex_len, 0);
op->do_raw = 0; /* don't want raw on output with --inhex= */
if ((NULL == op->page_str) && (0 == op->do_all)) {
/* may be able to deduce VPD page */
diff --git a/src/sg_zone.c b/src/sg_zone.c
index e7882ec0..f8891f16 100644
--- a/src/sg_zone.c
+++ b/src/sg_zone.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014 Douglas Gilbert.
+ * Copyright (c) 2014-2015 Douglas Gilbert.
* All rights reserved.
* Use of this source code is governed by a BSD-style
* license that can be found in the BSD_LICENSE file.
@@ -28,11 +28,11 @@
/* A utility program originally written for the Linux OS SCSI subsystem.
*
*
- * This program issues the SCSI RESET WRITE POINTER command to the given SCSI
- * device. Based on zbc-r02.pdf .
+ * This program issues a SCSI CLOSE ZONE, FINISH ZONE or OPEN ZONE command
+ * to the given SCSI device. Based on zbc-r04c.pdf .
*/
-static const char * version_str = "1.00 20141215";
+static const char * version_str = "1.01 20151126";
#define SG_ZONING_OUT_CMDLEN 16
#define CLOSE_ZONE_SA 0x1
@@ -111,7 +111,7 @@ usage()
* -> success, various SG_LIB_CAT_* positive values or -1 -> other errors */
static int
sg_ll_zone_out(int sg_fd, int sa, uint64_t zid, int all, int noisy,
- int verbose)
+ int verbose)
{
int k, ret, res, sense_cat;
unsigned char zoCmdBlk[SG_ZONING_OUT_CMDLEN] =