diff options
author | Douglas Gilbert <dgilbert@interlog.com> | 2013-05-18 01:50:52 +0000 |
---|---|---|
committer | Douglas Gilbert <dgilbert@interlog.com> | 2013-05-18 01:50:52 +0000 |
commit | 69d4248ca767c54623606e505f2d535ba127f927 (patch) | |
tree | 772bc21bc3b55425b8a2dba11b86f2c84353a07b /src | |
parent | faeffd098cd2e1cc79b225b148ef96dd722bcdac (diff) | |
download | sg3_utils-69d4248ca767c54623606e505f2d535ba127f927.tar.gz |
sg_write_same: add --ndob; sg_sync: add --16; sg_vpd: add FUAB bit
git-svn-id: https://svn.bingwo.ca/repos/sg3_utils/trunk@496 6180dd3e-e324-4e3e-922d-17de1ae2f315
Diffstat (limited to 'src')
-rw-r--r-- | src/sg_compare_and_write.c | 4 | ||||
-rw-r--r-- | src/sg_dd.c | 2 | ||||
-rw-r--r-- | src/sg_logs.c | 46 | ||||
-rw-r--r-- | src/sg_opcodes.c | 2 | ||||
-rw-r--r-- | src/sg_read.c | 2 | ||||
-rw-r--r-- | src/sg_safte.c | 2 | ||||
-rw-r--r-- | src/sg_sync.c | 152 | ||||
-rw-r--r-- | src/sg_vpd.c | 3 | ||||
-rw-r--r-- | src/sg_write_same.c | 225 | ||||
-rw-r--r-- | src/sg_xcopy.c | 2 | ||||
-rw-r--r-- | src/sginfo.c | 2 | ||||
-rw-r--r-- | src/sgm_dd.c | 4 | ||||
-rw-r--r-- | src/sgp_dd.c | 2 |
13 files changed, 291 insertions, 157 deletions
diff --git a/src/sg_compare_and_write.c b/src/sg_compare_and_write.c index b13d5220..fddcba64 100644 --- a/src/sg_compare_and_write.c +++ b/src/sg_compare_and_write.c @@ -48,7 +48,7 @@ * */ -static const char * version_str = "1.03 20130507"; +static const char * version_str = "1.04 20130516"; #define DEF_BLOCK_SIZE 512 #define DEF_NUM_BLOCKS (1) @@ -58,7 +58,7 @@ static const char * version_str = "1.03 20130507"; #define COMPARE_AND_WRITE_OPCODE (0x89) #define COMPARE_AND_WRITE_CDB_SIZE (16) -#define SENSE_BUFF_LEN 32 /* Arbitrary, could be larger */ +#define SENSE_BUFF_LEN 64 /* Arbitrary, could be larger */ #define ME "sg_compare_and_write: " diff --git a/src/sg_dd.c b/src/sg_dd.c index 10746a09..5f8af5fd 100644 --- a/src/sg_dd.c +++ b/src/sg_dd.c @@ -80,7 +80,7 @@ static const char * version_str = "5.77 20130507"; #define CACHING_MP 8 #define CONTROL_MP 0xa -#define SENSE_BUFF_LEN 32 /* Arbitrary, could be larger */ +#define SENSE_BUFF_LEN 64 /* Arbitrary, could be larger */ #define READ_CAP_REPLY_LEN 8 #define RCAP16_REPLY_LEN 32 #define READ_LONG_OPCODE 0x3E diff --git a/src/sg_logs.c b/src/sg_logs.c index 71196c3c..6b04165f 100644 --- a/src/sg_logs.c +++ b/src/sg_logs.c @@ -25,7 +25,7 @@ #include "sg_lib.h" #include "sg_cmds_basic.h" -static const char * version_str = "1.10 20130507"; /* spc4r35 + sbc3r30 */ +static const char * version_str = "1.11 20130517"; /* spc4r35 + sbc3r30 */ #define MX_ALLOC_LEN (0xfffc) #define SHORT_RESP_LEN 128 @@ -904,7 +904,7 @@ get_pcb_str(int pcb, char * outp, int maxoutlen) outp[0] = '\0'; } -/* BUFF_OVER_UNDER_LPAGE, 0x1 */ +/* BUFF_OVER_UNDER_LPAGE [0x1] */ static void show_buffer_under_overrun_page(unsigned char * resp, int len, int show_pcb) { @@ -971,7 +971,7 @@ show_buffer_under_overrun_page(unsigned char * resp, int len, int show_pcb) } /* WRITE_ERR_LPAGE; READ_ERR_LPAGE; READ_REV_ERR_LPAGE; VERIFY_ERR_LPAGE */ -/* 0x2, 0x3, 0x4, 0x5 */ +/* [0x2, 0x3, 0x4, 0x5] */ static void show_error_counter_page(unsigned char * resp, int len, int show_pcb) { @@ -1039,7 +1039,7 @@ show_error_counter_page(unsigned char * resp, int len, int show_pcb) } } -/* NON_MEDIUM_LPAGE, 0x6 */ +/* NON_MEDIUM_LPAGE [0x6] */ static void show_non_medium_error_page(unsigned char * resp, int len, int show_pcb) { @@ -1089,7 +1089,7 @@ show_non_medium_error_page(unsigned char * resp, int len, int show_pcb) } } -/* PCT_LPAGE, 0x1a */ +/* PCT_LPAGE [0x1a] */ static void show_power_condition_transitions_page(unsigned char * resp, int len, int show_pcb) @@ -1368,7 +1368,7 @@ skip_para: } } -/* LAST_N_ERR_LPAGE, 0x7 */ +/* LAST_N_ERR_LPAGE [0x7] */ static void show_last_n_error_page(unsigned char * resp, int len, int show_pcb) { @@ -1410,7 +1410,7 @@ show_last_n_error_page(unsigned char * resp, int len, int show_pcb) } } -/* LAST_N_DEFERRED_LPAGE, 0xb */ +/* LAST_N_DEFERRED_LPAGE [0xb] */ static void show_last_n_deferred_error_page(unsigned char * resp, int len, int show_pcb) { @@ -1460,7 +1460,7 @@ static const char * self_test_result[] = { "reserved", "self test in progress"}; -/* SELF_TEST_LPAGE, 0x10 */ +/* SELF_TEST_LPAGE [0x10] */ static void show_self_test_page(unsigned char * resp, int len, int show_pcb) { @@ -1507,7 +1507,7 @@ show_self_test_page(unsigned char * resp, int len, int show_pcb) } } -/* TEMPERATURE_LPAGE, 0xd */ +/* TEMPERATURE_LPAGE [0xd] */ static void show_temperature_page(unsigned char * resp, int len, int show_pcb, int hdr, int show_unknown) @@ -1560,7 +1560,7 @@ show_temperature_page(unsigned char * resp, int len, int show_pcb, int hdr, } } -/* START_STOP_LPAGE, 0xe */ +/* START_STOP_LPAGE [0xe] */ static void show_start_stop_page(unsigned char * resp, int len, int show_pcb, int verbose) { @@ -1658,7 +1658,7 @@ show_start_stop_page(unsigned char * resp, int len, int show_pcb, int verbose) } } -/* IE_LPAGE, 0x2f */ +/* IE_LPAGE [0x2f] */ static void show_ie_page(unsigned char * resp, int len, int show_pcb, int full) { @@ -2063,7 +2063,7 @@ show_sas_port_param(unsigned char * ucp, int param_len, } } -/* PROTO_SPECIFIC_LPAGE, 0x18 */ +/* PROTO_SPECIFIC_LPAGE [0x18] */ static int show_protocol_specific_page(unsigned char * resp, int len, const struct opts_t * optsp) @@ -2088,7 +2088,7 @@ show_protocol_specific_page(unsigned char * resp, int len, } /* Returns 1 if processed page, 0 otherwise */ -/* STATS_LPAGE, 0x0 to 0x1f */ +/* STATS_LPAGE [0x19], subpages: 0x0 to 0x1f */ static int show_stats_perform_page(unsigned char * resp, int len, const struct opts_t * optsp) @@ -2415,7 +2415,7 @@ show_stats_perform_page(unsigned char * resp, int len, } /* Returns 1 if processed page, 0 otherwise */ -/* STATS_LPAGE [0x16], CACHE_STATS_SUBPG [0x18, 0x20] */ +/* STATS_LPAGE [0x19], CACHE_STATS_SUBPG [0x20] */ static int show_cache_stats_page(unsigned char * resp, int len, const struct opts_t * optsp) @@ -2548,7 +2548,7 @@ show_cache_stats_page(unsigned char * resp, int len, return 1; } -/* FORMAT_STATUS_LPAGE, 0x8 */ +/* FORMAT_STATUS_LPAGE [0x8] */ static void show_format_status_page(unsigned char * resp, int len, int show_pcb) { @@ -2618,7 +2618,7 @@ show_format_status_page(unsigned char * resp, int len, int show_pcb) } } -/* 0x17 */ +/* Non-volatile cache page [0x17] */ static void show_non_volatile_cache_page(unsigned char * resp, int len, int show_pcb) { @@ -2690,7 +2690,7 @@ show_non_volatile_cache_page(unsigned char * resp, int len, int show_pcb) } } -/* LB_PROV_LPAGE, 0xc */ +/* LB_PROV_LPAGE [0xc] */ static void show_lb_provisioning_page(unsigned char * resp, int len, int show_pcb) { @@ -2764,7 +2764,7 @@ show_lb_provisioning_page(unsigned char * resp, int len, int show_pcb) } } -/* SOLID_STATE_MEDIA_LPAGE, 0x11 */ +/* SOLID_STATE_MEDIA_LPAGE [0x11] */ static void show_solid_state_media_page(unsigned char * resp, int len, int show_pcb) { @@ -2804,7 +2804,7 @@ show_solid_state_media_page(unsigned char * resp, int len, int show_pcb) } } -/* SAT_ATA_RESULTS_LPAGE (SAT-2), 0x16 */ +/* SAT_ATA_RESULTS_LPAGE (SAT-2) [0x16] */ static void show_ata_pt_results_page(unsigned char * resp, int len, int show_pcb) { @@ -2859,6 +2859,8 @@ static const char * bms_status[] = { "background scan halted due to temperature out of range", "background scan enabled, none active (waiting for BMS interval timer " "to expire)", /* 8 */ + "background scan halted - scan results list full", + "background scan halted - pre-scan time limit timer expired" /* 10 */, }; static const char * reassign_status[] = { @@ -2873,7 +2875,7 @@ static const char * reassign_status[] = { "Logical block unsuccessfully reassigned by application client", /* 8 */ }; -/* 0x15 for disk */ +/* Background scan results [0x15] for disk */ static void show_background_scan_results_page(unsigned char * resp, int len, int show_pcb, int verbose) @@ -2984,7 +2986,7 @@ show_background_scan_results_page(unsigned char * resp, int len, int show_pcb, } } -/* 0xc for tape */ +/* Sequential access device page [0xc] for tape */ static void show_sequential_access_page(unsigned char * resp, int len, int show_pcb, int verbose) @@ -3505,7 +3507,7 @@ static const char * tape_alert_strs[] = { "WORM medium - overwrite attempted", }; -/* TAPE_ALERT_LPAGE, 0x2e */ +/* TAPE_ALERT_LPAGE [0x2e] */ static void show_tape_alert_ssc_page(unsigned char * resp, int len, int show_pcb, const struct opts_t * optsp) diff --git a/src/sg_opcodes.c b/src/sg_opcodes.c index c9132fad..25f58a6d 100644 --- a/src/sg_opcodes.c +++ b/src/sg_opcodes.c @@ -29,7 +29,7 @@ static const char * version_str = "0.38 20130507"; /* spc4r26 */ -#define SENSE_BUFF_LEN 32 /* Arbitrary, could be larger */ +#define SENSE_BUFF_LEN 64 /* Arbitrary, could be larger */ #define DEF_TIMEOUT_SECS 60 #define SG_MAINTENANCE_IN 0xa3 diff --git a/src/sg_read.c b/src/sg_read.c index d5e5a8bd..9c7dbffb 100644 --- a/src/sg_read.c +++ b/src/sg_read.c @@ -61,7 +61,7 @@ static const char * version_str = "1.19 20121211"; #define SG_FLAG_MMAP_IO 4 #endif -#define SENSE_BUFF_LEN 32 /* Arbitrary, could be larger */ +#define SENSE_BUFF_LEN 64 /* Arbitrary, could be larger */ #define DEF_TIMEOUT 40000 /* 40,000 millisecs == 40 seconds */ #ifndef RAW_MAJOR diff --git a/src/sg_safte.c b/src/sg_safte.c index 0eba852d..e8c3446e 100644 --- a/src/sg_safte.c +++ b/src/sg_safte.c @@ -29,7 +29,7 @@ static const char * version_str = "0.24 20130507"; -#define SENSE_BUFF_LEN 32 /* Arbitrary, could be larger */ +#define SENSE_BUFF_LEN 64 /* Arbitrary, could be larger */ #define DEF_TIMEOUT 60000 /* 60,000 millisecs == 60 seconds */ #define EBUFF_SZ 256 diff --git a/src/sg_sync.c b/src/sg_sync.c index 6ba5e018..55f789fd 100644 --- a/src/sg_sync.c +++ b/src/sg_sync.c @@ -10,44 +10,58 @@ #include <stdio.h> #include <stdlib.h> #include <string.h> +#include <limits.h> #include <getopt.h> #include "sg_lib.h" #include "sg_cmds_basic.h" +#include "sg_pt.h" /* A utility program for the Linux OS SCSI subsystem. * * - * This program issues the SCSI command SYNCHRONIZE CACHE(10) to the given - * device. This command is defined for SCSI "direct access" devices + * This program issues the SCSI command SYNCHRONIZE CACHE(10 or 16) to the + * given device. This command is defined for SCSI "direct access" devices * (e.g. disks). */ -static const char * version_str = "1.09 20130507"; +static const char * version_str = "1.10 20130516"; + +#define SYNCHRONIZE_CACHE16_CMD 0x91 +#define SYNCHRONIZE_CACHE16_CMDLEN 16 +#define SENSE_BUFF_LEN 64 +#define DEF_PT_TIMEOUT 60 /* 60 seconds */ static struct option long_options[] = { - {"count", 1, 0, 'c'}, - {"group", 1, 0, 'g'}, - {"help", 0, 0, 'h'}, - {"immed", 0, 0, 'i'}, - {"lba", 1, 0, 'l'}, - {"sync-nv", 0, 0, 's'}, - {"verbose", 0, 0, 'v'}, - {"version", 0, 0, 'V'}, + {"16", no_argument, 0, 'S'}, + {"count", required_argument, 0, 'c'}, + {"group", required_argument, 0, 'g'}, + {"help", no_argument, 0, 'h'}, + {"immed", no_argument, 0, 'i'}, + {"lba", required_argument, 0, 'l'}, + {"sync-nv", no_argument, 0, 's'}, + {"timeout", required_argument, 0, 't'}, + {"verbose", no_argument, 0, 'v'}, + {"version", no_argument, 0, 'V'}, {0, 0, 0, 0}, }; static void usage() { fprintf(stderr, "Usage: " - "sg_sync [--count=COUNT] [--group=GN] [--help] [--immed]\n" - " [--lba=LBA] [--sync-nv] [--verbose] [--version] " - "DEVICE\n" + "sg_sync [--16] [--count=COUNT] [--group=GN] [--help] " + "[--immed]\n" + " [--lba=LBA] [--sync-nv] [--timeout=SECS] " + "[--verbose]\n" + " [--version] DEVICE\n" " where:\n" + " --16|-S calls SYNCHRONIZE CACHE(16) (def: is " + "10 byte\n" + " variant)\n" " --count=COUNT|-c COUNT number of blocks to sync (def: 0 " - "which implies\n" - " rest of device)\n" + "which\n" + " implies rest of device)\n" " --group=GN|-g GN set group number field to GN (def: 0)\n" " --help|-h print out usage message\n" " --immed|-i command returns immediately when set " @@ -58,22 +72,100 @@ static void usage() " from (def: 0)\n" " --sync-nv|-s synchronize to non-volatile storage " "(if distinct\n" - " from medium)\n" + " from medium). Obsolete in sbc3r35d.\n" + " --timeout=SECS|-t SECS command timeout in seconds, only " + "active\n" + " if '--16' given (def: 60 seconds)\n" " --verbose|-v increase verbosity\n" " --version|-V print version string and exit\n\n" - "Performs a SCSI SYNCHRONIZE CACHE(10) command\n" + "Performs a SCSI SYNCHRONIZE CACHE(10 or 16) command\n" ); } +static int +ll_sync_cache_16(int sg_fd, int sync_nv, int immed, int group, + uint64_t lba, unsigned int num_lb, int to_secs, + int noisy, int verbose) +{ + int res, ret, k, sense_cat; + unsigned char scCmdBlk[SYNCHRONIZE_CACHE16_CMDLEN] = + {SYNCHRONIZE_CACHE16_CMD, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0}; + unsigned char sense_b[SENSE_BUFF_LEN]; + struct sg_pt_base * ptvp; + + if (sync_nv) + scCmdBlk[1] |= 4; /* obsolete in sbc3r35d */ + if (immed) + scCmdBlk[1] |= 2; + scCmdBlk[2] = (lba >> 56) & 0xff; + scCmdBlk[3] = (lba >> 48) & 0xff; + scCmdBlk[4] = (lba >> 40) & 0xff; + scCmdBlk[5] = (lba >> 32) & 0xff; + scCmdBlk[6] = (lba >> 24) & 0xff; + scCmdBlk[7] = (lba >> 16) & 0xff; + scCmdBlk[8] = (lba >> 8) & 0xff; + scCmdBlk[9] = lba & 0xff; + scCmdBlk[14] = group & 0x1f; + scCmdBlk[10] = (num_lb >> 24) & 0xff; + scCmdBlk[11] = (num_lb >> 16) & 0xff; + scCmdBlk[12] = (num_lb >> 8) & 0xff; + scCmdBlk[13] = num_lb & 0xff; + + if (verbose) { + fprintf(stderr, " synchronize cache(16) cdb: "); + for (k = 0; k < SYNCHRONIZE_CACHE16_CMDLEN; ++k) + fprintf(stderr, "%02x ", scCmdBlk[k]); + fprintf(sg_warnings_strm, "\n"); + } + ptvp = construct_scsi_pt_obj(); + if (NULL == ptvp) { + fprintf(stderr, "synchronize cache(16): out of memory\n"); + return -1; + } + set_scsi_pt_cdb(ptvp, scCmdBlk, sizeof(scCmdBlk)); + set_scsi_pt_sense(ptvp, sense_b, sizeof(sense_b)); + res = do_scsi_pt(ptvp, sg_fd, to_secs, verbose); + ret = sg_cmds_process_resp(ptvp, "synchronize cache(16)", res, 0, + sense_b, noisy, verbose, &sense_cat); + if (-1 == ret) + ; + else if (-2 == ret) { + switch (sense_cat) { + case SG_LIB_CAT_NOT_READY: + case SG_LIB_CAT_UNIT_ATTENTION: + case SG_LIB_CAT_INVALID_OP: + case SG_LIB_CAT_ILLEGAL_REQ: + case SG_LIB_CAT_ABORTED_COMMAND: + ret = sense_cat; + break; + case SG_LIB_CAT_RECOVERED: + case SG_LIB_CAT_NO_SENSE: + ret = 0; + break; + default: + ret = -1; + break; + } + } else + ret = 0; + + destruct_scsi_pt_obj(ptvp); + return ret; +} + int main(int argc, char * argv[]) { int sg_fd, res, c; int64_t count = 0; + unsigned int num_lb = 0; + int do_16 = 0; int group = 0; int64_t lba = 0; int immed = 0; int sync_nv = 0; + int to_secs = DEF_PT_TIMEOUT; int verbose = 0; const char * device_name = NULL; int ret = 0; @@ -81,7 +173,7 @@ int main(int argc, char * argv[]) while (1) { int option_index = 0; - c = getopt_long(argc, argv, "c:g:hil:svV", long_options, + c = getopt_long(argc, argv, "c:g:hil:sSt:vV", long_options, &option_index); if (c == -1) break; @@ -89,10 +181,11 @@ int main(int argc, char * argv[]) switch (c) { case 'c': count = sg_get_llnum(optarg); - if (count < 0) { + if ((count < 0) || (count > UINT_MAX)) { fprintf(stderr, "bad argument to '--count'\n"); return SG_LIB_SYNTAX_ERROR; } + num_lb = (unsigned int)count; break; case 'g': group = sg_get_num(optarg); @@ -118,6 +211,16 @@ int main(int argc, char * argv[]) case 's': sync_nv = 1; break; + case 'S': + do_16 = 1; + break; + case 't': + to_secs = sg_get_num(optarg); + if (to_secs < 0) { + fprintf(stderr, "bad argument to '--timeout'\n"); + return SG_LIB_SYNTAX_ERROR; + } + break; case 'v': ++verbose; break; @@ -156,9 +259,12 @@ int main(int argc, char * argv[]) return SG_LIB_FILE_ERROR; } - res = sg_ll_sync_cache_10(sg_fd, sync_nv, immed, group, - (unsigned int)lba, (unsigned int)count, - 1, verbose); + if (do_16) + res = ll_sync_cache_16(sg_fd, sync_nv, immed, group, lba, num_lb, + to_secs, 1, verbose); + else + res = sg_ll_sync_cache_10(sg_fd, sync_nv, immed, group, + (unsigned int)lba, num_lb, 1, verbose); ret = res; if (0 == res) ; diff --git a/src/sg_vpd.c b/src/sg_vpd.c index 00547ae7..275b69eb 100644 --- a/src/sg_vpd.c +++ b/src/sg_vpd.c @@ -30,7 +30,7 @@ */ -static const char * version_str = "0.66 20130510"; /* spc4r36 + sbc3r35 */ +static const char * version_str = "0.67 20130517"; /* spc4r36 + sbc3r35 */ /* And with sbc3r35, vale Mark Evans */ extern void svpd_enumerate_vendor(void); @@ -1723,6 +1723,7 @@ decode_b1_vpd(unsigned char * buff, int len, int do_hex, int pdt) printf(": reserved\n"); break; } + printf(" FUAB=%d\n", buff[8] & 0x2); printf(" VBULS=%d\n", buff[8] & 0x1); break; case PDT_TAPE: case PDT_MCHANGER: case PDT_ADC: diff --git a/src/sg_write_same.c b/src/sg_write_same.c index c0f49463..7f10217b 100644 --- a/src/sg_write_same.c +++ b/src/sg_write_same.c @@ -26,7 +26,7 @@ #include "sg_cmds_basic.h" #include "sg_cmds_extra.h" -static const char * version_str = "1.01 20130507"; +static const char * version_str = "1.02 20130516"; #define ME "sg_write_same: " @@ -41,7 +41,7 @@ static const char * version_str = "1.01 20130507"; #define WRITE_SAME32_LEN 32 #define RCAP10_RESP_LEN 8 #define RCAP16_RESP_LEN 32 -#define SENSE_BUFF_LEN 32 /* Arbitrary, could be larger */ +#define SENSE_BUFF_LEN 64 /* Arbitrary, could be larger */ #define DEF_TIMEOUT_SECS 60 #define DEF_WS_CDB_SIZE WRITE_SAME10_LEN #define DEF_WS_NUMBLOCKS 1 @@ -58,6 +58,7 @@ static struct option long_options[] = { {"in", required_argument, 0, 'i'}, {"lba", required_argument, 0, 'l'}, {"lbdata", no_argument, 0, 'L'}, + {"ndob", no_argument, 0, 'N'}, {"num", required_argument, 0, 'n'}, {"pbdata", no_argument, 0, 'P'}, {"timeout", required_argument, 0, 'r'}, @@ -75,6 +76,7 @@ struct opts_t { char ifilename[256]; uint64_t lba; int lbdata; + int ndob; int numblocks; int pbdata; int timeout; @@ -95,10 +97,12 @@ usage() "sg_write_same [--10] [--16] [--32] [--anchor] [--grpnum=GN] " "[--help]\n" " [--in=IF] [--lba=LBA] [--lbdata] " - "[--num=NUM] [--pbdata]\n" - " [--timeout=TO] [--unmap] [--verbose] " - "[--version]\n" - " [--wrprotect=WRP] [xferlen=LEN] DEVICE\n" + "[--ndob] [--num=NUM]\n" + " [--pbdata] [--timeout=TO] [--unmap] " + "[--verbose]\n" + " [--version] [--wrprotect=WRP] " + "[xferlen=LEN]\n" + " DEVICE\n" " where:\n" " --10|-R do WRITE SAME(10) (even if '--unmap' " "is given)\n" @@ -116,6 +120,7 @@ usage() " --lba=LBA|-l LBA LBA is the logical block address to " "start (def: 0)\n" " --lbdata|-L set LBDATA bit\n" + " --ndob|-N set 'no data-out buffer' bit\n" " --num=NUM|-n NUM NUM is number of logical blocks to " "write (def: 1)\n" " [Beware NUM==0 means rest of device]\n" @@ -149,7 +154,7 @@ do_write_same(int sg_fd, const struct opts_t * optsp, const void * dataoutp, if (WRITE_SAME10_LEN == cdb_len) { llba = optsp->lba + optsp->numblocks; if ((optsp->numblocks > 0xffff) || (llba > ULONG_MAX) || - (optsp->unmap && (0 == optsp->want_ws10))) { + optsp->ndob || (optsp->unmap && (0 == optsp->want_ws10))) { cdb_len = WRITE_SAME16_LEN; if (optsp->verbose) fprintf(stderr, "do_write_same: use WRITE SAME(16) instead " @@ -193,6 +198,8 @@ do_write_same(int sg_fd, const struct opts_t * optsp, const void * dataoutp, wsCmdBlk[1] |= 0x4; if (optsp->lbdata) wsCmdBlk[1] |= 0x2; + if (optsp->ndob) + wsCmdBlk[1] |= 0x1; llba = optsp->lba; for (k = 7; k >= 0; --k) { wsCmdBlk[2 + k] = (llba & 0xff); @@ -222,6 +229,8 @@ do_write_same(int sg_fd, const struct opts_t * optsp, const void * dataoutp, wsCmdBlk[10] |= 0x4; if (optsp->lbdata) wsCmdBlk[10] |= 0x2; + if (optsp->ndob) + wsCmdBlk[10] |= 0x1; llba = optsp->lba; for (k = 7; k >= 0; --k) { wsCmdBlk[12 + k] = (llba & 0xff); @@ -326,8 +335,8 @@ main(int argc, char * argv[]) while (1) { int option_index = 0; - c = getopt_long(argc, argv, "ag:hi:l:Ln:PRSt:TUvVw:x:", long_options, - &option_index); + c = getopt_long(argc, argv, "ag:hi:l:Ln:NPRSt:TUvVw:x:", + long_options, &option_index); if (c == -1) break; @@ -370,6 +379,9 @@ main(int argc, char * argv[]) } num_given = 1; break; + case 'N': + ++opts.ndob; + break; case 'P': ++opts.pbdata; break; @@ -458,10 +470,20 @@ main(int argc, char * argv[]) return SG_LIB_SYNTAX_ERROR; } - memset(&a_stat, 0, sizeof(a_stat)); - if (opts.ifilename[0]) { + if (opts.ndob) { + if (if_given) { + fprintf(stderr, "Can't have both --ndob and '--in='\n"); + return SG_LIB_SYNTAX_ERROR; + } + if (0 != opts.xfer_len) { + fprintf(stderr, "With --ndob only '--xferlen=0' (or not given) " + "is acceptable\n"); + return SG_LIB_SYNTAX_ERROR; + } + } else if (opts.ifilename[0]) { got_stdin = (0 == strcmp(opts.ifilename, "-")) ? 1 : 0; if (! got_stdin) { + memset(&a_stat, 0, sizeof(a_stat)); if (stat(opts.ifilename, &a_stat) < 0) { if (vb) fprintf(stderr, "unable to stat(%s): %s\n", @@ -480,105 +502,108 @@ main(int argc, char * argv[]) return SG_LIB_FILE_ERROR; } - prot_en = 0; - if (0 == opts.xfer_len) { - res = sg_ll_readcap_16(sg_fd, 0 /* pmi */, 0 /* llba */, resp_buff, - RCAP16_RESP_LEN, 0, (vb ? (vb - 1): 0)); - if (0 == res) { - if (vb > 3) - dStrHex((const char *)resp_buff, RCAP16_RESP_LEN, 1); - block_size = ((resp_buff[8] << 24) | - (resp_buff[9] << 16) | - (resp_buff[10] << 8) | - resp_buff[11]); - prot_en = !!(resp_buff[12] & 0x1); - opts.xfer_len = block_size; - if (prot_en && (opts.wrprotect > 0)) - opts.xfer_len += 8; - } else if ((SG_LIB_CAT_INVALID_OP == res) || - (SG_LIB_CAT_ILLEGAL_REQ == res)) { - if (vb) - fprintf(stderr, "Read capacity(16) not supported, try Read " - "capacity(10)\n"); - res = sg_ll_readcap_10(sg_fd, 0 /* pmi */, 0 /* lba */, resp_buff, - RCAP10_RESP_LEN, 0, (vb ? (vb - 1): 0)); + if (! opts.ndob) { + prot_en = 0; + if (0 == opts.xfer_len) { + res = sg_ll_readcap_16(sg_fd, 0 /* pmi */, 0 /* llba */, resp_buff, + RCAP16_RESP_LEN, 0, (vb ? (vb - 1): 0)); if (0 == res) { if (vb > 3) - dStrHex((const char *)resp_buff, RCAP10_RESP_LEN, 1); - block_size = ((resp_buff[4] << 24) | - (resp_buff[5] << 16) | - (resp_buff[6] << 8) | - resp_buff[7]); + dStrHex((const char *)resp_buff, RCAP16_RESP_LEN, 1); + block_size = ((resp_buff[8] << 24) | + (resp_buff[9] << 16) | + (resp_buff[10] << 8) | + resp_buff[11]); + prot_en = !!(resp_buff[12] & 0x1); opts.xfer_len = block_size; + if (prot_en && (opts.wrprotect > 0)) + opts.xfer_len += 8; + } else if ((SG_LIB_CAT_INVALID_OP == res) || + (SG_LIB_CAT_ILLEGAL_REQ == res)) { + if (vb) + fprintf(stderr, "Read capacity(16) not supported, try " + "Read capacity(10)\n"); + res = sg_ll_readcap_10(sg_fd, 0 /* pmi */, 0 /* lba */, + resp_buff, RCAP10_RESP_LEN, 0, + (vb ? (vb - 1): 0)); + if (0 == res) { + if (vb > 3) + dStrHex((const char *)resp_buff, RCAP10_RESP_LEN, 1); + block_size = ((resp_buff[4] << 24) | + (resp_buff[5] << 16) | + (resp_buff[6] << 8) | + resp_buff[7]); + opts.xfer_len = block_size; + } + } else if (vb) + fprintf(stderr, "Read capacity(16) failed. Unable to " + "calculate block size\n"); + if (res) + fprintf(stderr, "Read capacity(10) failed. Unable to " + "calculate block size\n"); + } + if (opts.xfer_len < 1) { + fprintf(stderr, "unable to deduce block size, please give " + "'--xferlen=' argument\n"); + ret = SG_LIB_SYNTAX_ERROR; + goto err_out; + } + if (opts.xfer_len > MAX_XFER_LEN) { + fprintf(stderr, "'--xferlen=%d is out of range ( want <= %d)\n", + opts.xfer_len, MAX_XFER_LEN); + ret = SG_LIB_SYNTAX_ERROR; + goto err_out; + } + wBuff = (unsigned char*)calloc(opts.xfer_len, 1); + if (NULL == wBuff) { + fprintf(stderr, "unable to allocate %d bytes of memory with " + "calloc()\n", opts.xfer_len); + ret = SG_LIB_SYNTAX_ERROR; + goto err_out; + } + if (opts.ifilename[0]) { + if (got_stdin) { + infd = STDIN_FILENO; + if (sg_set_binary_mode(STDIN_FILENO) < 0) + perror("sg_set_binary_mode"); + } else { + if ((infd = open(opts.ifilename, O_RDONLY)) < 0) { + snprintf(ebuff, EBUFF_SZ, ME "could not open %s for " + "reading", opts.ifilename); + perror(ebuff); + ret = SG_LIB_FILE_ERROR; + goto err_out; + } else if (sg_set_binary_mode(infd) < 0) + perror("sg_set_binary_mode"); } - } else if (vb) - fprintf(stderr, "Read capacity(16) failed. Unable to calculate " - "block size\n"); - if (res) - fprintf(stderr, "Read capacity(10) failed. Unable to calculate " - "block size\n"); - } - if (opts.xfer_len < 1) { - fprintf(stderr, "unable to deduce block size, please give " - "'--xferlen=' argument\n"); - ret = SG_LIB_SYNTAX_ERROR; - goto err_out; - } - if (opts.xfer_len > MAX_XFER_LEN) { - fprintf(stderr, "'--xferlen=%d is out of range ( want <= %d)\n", - opts.xfer_len, MAX_XFER_LEN); - ret = SG_LIB_SYNTAX_ERROR; - goto err_out; - } - wBuff = (unsigned char*)calloc(opts.xfer_len, 1); - if (NULL == wBuff) { - fprintf(stderr, "unable to allocate %d bytes of memory with " - "calloc()\n", opts.xfer_len); - ret = SG_LIB_SYNTAX_ERROR; - goto err_out; - } - if (opts.ifilename[0]) { - if (got_stdin) { - infd = STDIN_FILENO; - if (sg_set_binary_mode(STDIN_FILENO) < 0) - perror("sg_set_binary_mode"); - } else { - if ((infd = open(opts.ifilename, O_RDONLY)) < 0) { - snprintf(ebuff, EBUFF_SZ, - ME "could not open %s for reading", opts.ifilename); + res = read(infd, wBuff, opts.xfer_len); + if (res < 0) { + snprintf(ebuff, EBUFF_SZ, ME "couldn't read from %s", + opts.ifilename); perror(ebuff); + if (! got_stdin) + close(infd); ret = SG_LIB_FILE_ERROR; goto err_out; - } else if (sg_set_binary_mode(infd) < 0) - perror("sg_set_binary_mode"); - } - res = read(infd, wBuff, opts.xfer_len); - if (res < 0) { - snprintf(ebuff, EBUFF_SZ, ME "couldn't read from %s", - opts.ifilename); - perror(ebuff); + } + if (res < opts.xfer_len) { + fprintf(stderr, "tried to read %d bytes from %s, got %d " + "bytes\n", opts.xfer_len, opts.ifilename, res); + fprintf(stderr, " so pad with 0x0 bytes and continue\n"); + } if (! got_stdin) close(infd); - ret = SG_LIB_FILE_ERROR; - goto err_out; - } - if (res < opts.xfer_len) { - fprintf(stderr, "tried to read %d bytes from %s, got %d " - "bytes\n", opts.xfer_len, opts.ifilename, res); - fprintf(stderr, " so pad with 0x0 bytes and continue\n"); - } - if (! got_stdin) - close(infd); - } else { - if (vb) - fprintf(stderr, "Default data-out buffer set to %d zeros\n", - opts.xfer_len); - if (prot_en && (opts.wrprotect > 0)) { - /* default for protection is 0xff, rest get 0x0 */ - memset(wBuff + opts.xfer_len - 8, 0xff, 8); + } else { if (vb) - fprintf(stderr, " ... apart from last 8 bytes which are set " - "to 0xff\n"); + fprintf(stderr, "Default data-out buffer set to %d zeros\n", + opts.xfer_len); + if (prot_en && (opts.wrprotect > 0)) { + /* default for protection is 0xff, rest get 0x0 */ + memset(wBuff + opts.xfer_len - 8, 0xff, 8); + if (vb) + fprintf(stderr, " ... apart from last 8 bytes which are " + "set to 0xff\n"); + } } } diff --git a/src/sg_xcopy.c b/src/sg_xcopy.c index 82c7bd71..b2f3a015 100644 --- a/src/sg_xcopy.c +++ b/src/sg_xcopy.c @@ -80,7 +80,7 @@ static const char * version_str = "0.34 20130507"; #define CACHING_MP 8 #define CONTROL_MP 0xa -#define SENSE_BUFF_LEN 32 /* Arbitrary, could be larger */ +#define SENSE_BUFF_LEN 64 /* Arbitrary, could be larger */ #define READ_CAP_REPLY_LEN 8 #define RCAP16_REPLY_LEN 32 diff --git a/src/sginfo.c b/src/sginfo.c index b6396793..6a8f0b93 100644 --- a/src/sginfo.c +++ b/src/sginfo.c @@ -371,7 +371,7 @@ struct scsi_cmnd_io size_t dxfer_len; /* bytes to be transferred to/from dxferp */ }; -#define SENSE_BUFF_LEN 32 +#define SENSE_BUFF_LEN 64 #define CMD_TIMEOUT 60000 /* 60,000 milliseconds (60 seconds) */ #define EBUFF_SZ 256 diff --git a/src/sgm_dd.c b/src/sgm_dd.c index 84bd445b..f6d8e3e4 100644 --- a/src/sgm_dd.c +++ b/src/sgm_dd.c @@ -1,7 +1,7 @@ /* A utility program for copying files. Specialised for "files" that * represent devices that understand the SCSI command set. * - * Copyright (C) 1999 - 2012 D. Gilbert and P. Allworth + * Copyright (C) 1999 - 2013 D. Gilbert and P. Allworth * 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) @@ -84,7 +84,7 @@ static const char * version_str = "1.37 20130507"; #define SG_FLAG_MMAP_IO 4 #endif -#define SENSE_BUFF_LEN 32 /* Arbitrary, could be larger */ +#define SENSE_BUFF_LEN 64 /* Arbitrary, could be larger */ #define READ_CAP_REPLY_LEN 8 #define RCAP16_REPLY_LEN 32 diff --git a/src/sgp_dd.c b/src/sgp_dd.c index 96cd7a8a..06a0fa38 100644 --- a/src/sgp_dd.c +++ b/src/sgp_dd.c @@ -69,7 +69,7 @@ static const char * version_str = "5.43 20130507"; /* #define SG_DEBUG */ -#define SENSE_BUFF_LEN 32 /* Arbitrary, could be larger */ +#define SENSE_BUFF_LEN 64 /* Arbitrary, could be larger */ #define READ_CAP_REPLY_LEN 8 #define RCAP16_REPLY_LEN 32 |