aboutsummaryrefslogtreecommitdiff
path: root/src/sg_readcap.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/sg_readcap.c')
-rw-r--r--src/sg_readcap.c152
1 files changed, 101 insertions, 51 deletions
diff --git a/src/sg_readcap.c b/src/sg_readcap.c
index 6b55cbb5..4a0220cf 100644
--- a/src/sg_readcap.c
+++ b/src/sg_readcap.c
@@ -27,9 +27,10 @@
#endif
#include "sg_lib.h"
#include "sg_cmds_basic.h"
+#include "sg_unaligned.h"
-static const char * version_str = "3.92 20140515";
+static const char * version_str = "3.93 20141220";
#define ME "sg_readcap: "
@@ -37,20 +38,21 @@ static const char * version_str = "3.92 20140515";
#define RCAP16_REPLY_LEN 32
static struct option long_options[] = {
- {"brief", 0, 0, 'b'},
- {"help", 0, 0, 'h'},
- {"hex", 0, 0, 'H'},
- {"lba", 1, 0, 'L'},
- {"long", 0, 0, 'l'},
- {"16", 0, 0, 'l'},
- {"new", 0, 0, 'N'},
- {"old", 0, 0, 'O'},
- {"pmi", 0, 0, 'p'},
- {"raw", 0, 0, 'r'},
- {"readonly", 0, 0, 'R'},
- {"verbose", 0, 0, 'v'},
- {"version", 0, 0, 'V'},
- {0, 0, 0, 0},
+ {"brief", 0, 0, 'b'},
+ {"help", 0, 0, 'h'},
+ {"hex", 0, 0, 'H'},
+ {"lba", 1, 0, 'L'},
+ {"long", 0, 0, 'l'},
+ {"16", 0, 0, 'l'},
+ {"new", 0, 0, 'N'},
+ {"old", 0, 0, 'O'},
+ {"pmi", 0, 0, 'p'},
+ {"raw", 0, 0, 'r'},
+ {"readonly", 0, 0, 'R'},
+ {"verbose", 0, 0, 'v'},
+ {"version", 0, 0, 'V'},
+ {"zbc", 0, 0, 'z'},
+ {0, 0, 0, 0},
};
struct opts_t {
@@ -64,18 +66,22 @@ struct opts_t {
int o_readonly;
int do_verbose;
int do_version;
+ int do_zbc;
uint64_t llba;
const char * device_name;
int opt_new;
};
-static void usage()
+
+static void
+usage()
{
- fprintf(stderr, "Usage: sg_readcap [--brief] [--help] [--hex] "
- "[--lba=LBA] [--long] [--16]\n"
+ fprintf(stderr,
+ "Usage: sg_readcap [--brief] [--help] [--hex] [--lba=LBA] "
+ "[--long] [--16]\n"
" [--pmi] [--raw] [--readonly] [--verbose] "
"[--version]\n"
- " DEVICE\n"
+ " [--zbc] DEVICE\n"
" where:\n"
" --brief|-b brief, two hex numbers: number of blocks "
"and block size\n"
@@ -97,15 +103,17 @@ static void usage()
" --readonly|-R open DEVICE read-only (def: RCAP(16) "
"read-write)\n"
" --verbose|-v increase verbosity\n"
- " --version|-V print version string and exit\n\n"
+ " --version|-V print version string and exit\n"
+ " --zbc|-z show rc_basis ZBC field (implies --16)\n\n"
"Perform a SCSI READ CAPACITY (10 or 16) command\n");
}
-static void usage_old()
+static void
+usage_old()
{
fprintf(stderr, "Usage: sg_readcap [-16] [-b] [-h] [-H] [-lba=LBA] "
- "[-pmi] [-r] [-R] [-v] [-V]\n"
- " DEVICE\n"
+ "[-pmi] [-r] [-R]\n"
+ " [-v] [-V] [-z] DEVICE\n"
" where:\n"
" -16 use READ CAPACITY (16) cdb (def: use "
"10 byte cdb)\n"
@@ -123,11 +131,13 @@ static void usage_old()
" -r output response in binary to stdout\n"
" -R open DEVICE read-only (def: RCAP(16) read-write)\n"
" -v increase verbosity\n"
- " -V print version string and exit\n\n"
- "Perform a SCSI READ CAPACITY command\n");
+ " -V print version string and exit\n"
+ " -z show rc_basis ZBC field (implies -16)\n\n"
+ "Perform a SCSI READ CAPACITY (10 or 16) command\n");
}
-static void usage_for(const struct opts_t * op)
+static void
+usage_for(const struct opts_t * op)
{
if (op->opt_new)
usage();
@@ -135,7 +145,8 @@ static void usage_for(const struct opts_t * op)
usage_old();
}
-static int process_cl_new(struct opts_t * op, int argc, char * argv[])
+static int
+process_cl_new(struct opts_t * op, int argc, char * argv[])
{
int c;
int a_one = 0;
@@ -144,7 +155,7 @@ static int process_cl_new(struct opts_t * op, int argc, char * argv[])
while (1) {
int option_index = 0;
- c = getopt_long(argc, argv, "16bhHlL:NOprRvV", long_options,
+ c = getopt_long(argc, argv, "16bhHlL:NOprRvVz", long_options,
&option_index);
if (c == -1)
break;
@@ -203,6 +214,9 @@ static int process_cl_new(struct opts_t * op, int argc, char * argv[])
case 'V':
++op->do_version;
break;
+ case 'z':
+ ++op->do_zbc;
+ break;
default:
fprintf(stderr, "unrecognised option code %c [0x%x]\n", c, c);
if (op->do_help)
@@ -227,7 +241,8 @@ static int process_cl_new(struct opts_t * op, int argc, char * argv[])
return 0;
}
-static int process_cl_old(struct opts_t * op, int argc, char * argv[])
+static int
+process_cl_old(struct opts_t * op, int argc, char * argv[])
{
int k, jmp_out, plen, num;
const char * cp;
@@ -284,6 +299,9 @@ static int process_cl_old(struct opts_t * op, int argc, char * argv[])
case 'V':
++op->do_version;
break;
+ case 'z':
+ ++op->do_zbc;
+ break;
default:
jmp_out = 1;
break;
@@ -324,7 +342,8 @@ static int process_cl_old(struct opts_t * op, int argc, char * argv[])
return 0;
}
-static int process_cl(struct opts_t * op, int argc, char * argv[])
+static int
+process_cl(struct opts_t * op, int argc, char * argv[])
{
int res;
char * cp;
@@ -344,7 +363,8 @@ static int process_cl(struct opts_t * op, int argc, char * argv[])
return res;
}
-static void dStrRaw(const char* str, int len)
+static void
+dStrRaw(const char* str, int len)
{
int k;
@@ -352,12 +372,31 @@ static void dStrRaw(const char* str, int len)
printf("%c", str[k]);
}
-int main(int argc, char * argv[])
+static const char *
+rc_basis_str(int rc_basis, char * b, int blen)
+{
+ switch (rc_basis) {
+ case 0:
+ snprintf(b, blen, "last contiguous that's not seq write required");
+ break;
+ case 1:
+ snprintf(b, blen, "last LBA on device");
+ break;
+ default:
+ snprintf(b, blen, "reserved (0x%x)", rc_basis);
+ break;
+ }
+ return b;
+}
+
+
+int
+main(int argc, char * argv[])
{
- int sg_fd, k, res, prot_en, p_type, lbppbe, rw_0_flag;
+ int sg_fd, res, prot_en, p_type, lbppbe, rw_0_flag;
uint64_t llast_blk_addr;
int ret = 0;
- unsigned int last_blk_addr, block_size;
+ uint32_t last_blk_addr, block_size;
unsigned char resp_buff[RCAP16_REPLY_LEN];
char b[80];
struct opts_t opts;
@@ -388,6 +427,10 @@ int main(int argc, char * argv[])
return SG_LIB_FILE_ERROR;
}
}
+ if (op->do_zbc) {
+ if (! op->do_long)
+ ++op->do_long;
+ }
memset(resp_buff, 0, sizeof(resp_buff));
@@ -415,27 +458,29 @@ int main(int argc, char * argv[])
if (op->do_hex || op->do_raw) {
if (op->do_raw)
dStrRaw((const char *)resp_buff, RCAP_REPLY_LEN);
+ else if (op->do_hex > 2)
+ dStrHex((const char *)resp_buff, RCAP_REPLY_LEN, -1);
else
dStrHex((const char *)resp_buff, RCAP_REPLY_LEN, 1);
goto good;
}
- last_blk_addr = ((resp_buff[0] << 24) | (resp_buff[1] << 16) |
- (resp_buff[2] << 8) | resp_buff[3]);
+ last_blk_addr = sg_get_unaligned_be32(resp_buff + 0);
if (0xffffffff != last_blk_addr) {
- block_size = ((resp_buff[4] << 24) | (resp_buff[5] << 16) |
- (resp_buff[6] << 8) | resp_buff[7]);
+ block_size = sg_get_unaligned_be32(resp_buff + 4);
if (op->do_brief) {
- printf("0x%x 0x%x\n", last_blk_addr + 1, block_size);
+ printf("0x%" PRIx32 " 0x%" PRIx32 "\n",
+ last_blk_addr + 1, block_size);
goto good;
}
printf("Read Capacity results:\n");
if (op->do_pmi)
printf(" PMI mode: given lba=0x%" PRIx64 ", last lba "
- "before delay=0x%x\n", op->llba, last_blk_addr);
+ "before delay=0x%" PRIx32 "\n", op->llba,
+ last_blk_addr);
else
- printf(" Last logical block address=%u (0x%x), Number "
- "of blocks=%u\n", last_blk_addr, last_blk_addr,
- last_blk_addr + 1);
+ printf(" Last logical block address=%" PRIu32 " (0x%"
+ PRIx32 "), Number of blocks=%" PRIu32 "\n",
+ last_blk_addr, last_blk_addr, last_blk_addr + 1);
printf(" Logical block length=%u bytes\n", block_size);
if (! op->do_pmi) {
uint64_t total_sz = last_blk_addr + 1;
@@ -486,18 +531,17 @@ int main(int argc, char * argv[])
if (op->do_hex || op->do_raw) {
if (op->do_raw)
dStrRaw((const char *)resp_buff, RCAP16_REPLY_LEN);
+ else if (op->do_hex > 2)
+ dStrHex((const char *)resp_buff, RCAP16_REPLY_LEN, -1);
else
dStrHex((const char *)resp_buff, RCAP16_REPLY_LEN, 1);
goto good;
}
- for (k = 0, llast_blk_addr = 0; k < 8; ++k) {
- llast_blk_addr <<= 8;
- llast_blk_addr |= resp_buff[k];
- }
- block_size = ((resp_buff[8] << 24) | (resp_buff[9] << 16) |
- (resp_buff[10] << 8) | resp_buff[11]);
+ llast_blk_addr = sg_get_unaligned_be64(resp_buff + 0);
+ block_size = sg_get_unaligned_be32(resp_buff + 8);
if (op->do_brief) {
- printf("0x%" PRIx64 " 0x%x\n", llast_blk_addr + 1, block_size);
+ printf("0x%" PRIx64 " 0x%" PRIx32 "\n", llast_blk_addr + 1,
+ block_size);
goto good;
}
prot_en = !!(resp_buff[12] & 0x1);
@@ -509,6 +553,12 @@ int main(int argc, char * argv[])
printf(" [type %d protection]\n", p_type + 1);
else
printf("\n");
+ if (op->do_zbc) {
+ int rc_basis = (resp_buff[12] >> 4) & 0x3;
+
+ printf(" ZBC's rc_basis=%d [%s]\n", rc_basis,
+ rc_basis_str(rc_basis, b, sizeof(b)));
+ }
printf(" Logical block provisioning: lbpme=%d, lbprz=%d\n",
!!(resp_buff[14] & 0x80), !!(resp_buff[14] & 0x40));
if (op->do_pmi)
@@ -519,7 +569,7 @@ int main(int argc, char * argv[])
printf(" Last logical block address=%" PRIu64 " (0x%"
PRIx64 "), Number of logical blocks=%" PRIu64 "\n",
llast_blk_addr, llast_blk_addr, llast_blk_addr + 1);
- printf(" Logical block length=%u bytes\n", block_size);
+ printf(" Logical block length=%" PRIu32 " bytes\n", block_size);
lbppbe = resp_buff[13] & 0xf;
printf(" Logical blocks per physical block exponent=%d",
lbppbe);