diff options
author | Douglas Gilbert <dgilbert@interlog.com> | 2015-11-26 21:12:02 +0000 |
---|---|---|
committer | Douglas Gilbert <dgilbert@interlog.com> | 2015-11-26 21:12:02 +0000 |
commit | 1a66c384bcfd9e8e0368f371e636beb4bd5aa890 (patch) | |
tree | b37126c2c83889c91b997e74bd415fd9e9c95f0c /src | |
parent | d2f05037db8ebdd5620f00bd8098e4a68f2a95ca (diff) | |
download | sg3_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.c | 5 | ||||
-rw-r--r-- | src/sg_logs.c | 319 | ||||
-rw-r--r-- | src/sg_modes.c | 3 | ||||
-rw-r--r-- | src/sg_readcap.c | 6 | ||||
-rw-r--r-- | src/sg_rep_zones.c | 51 | ||||
-rw-r--r-- | src/sg_reset_wp.c | 6 | ||||
-rw-r--r-- | src/sg_sanitize.c | 15 | ||||
-rw-r--r-- | src/sg_ses.c | 51 | ||||
-rw-r--r-- | src/sg_vpd.c | 139 | ||||
-rw-r--r-- | src/sg_zone.c | 10 |
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] = |