aboutsummaryrefslogtreecommitdiff
path: root/src/sg_opcodes.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/sg_opcodes.c')
-rw-r--r--src/sg_opcodes.c63
1 files changed, 38 insertions, 25 deletions
diff --git a/src/sg_opcodes.c b/src/sg_opcodes.c
index 6f160ff8..57b92968 100644
--- a/src/sg_opcodes.c
+++ b/src/sg_opcodes.c
@@ -1,5 +1,5 @@
/* A utility program originally written for the Linux OS SCSI subsystem.
- * Copyright (C) 2004-2020 D. Gilbert
+ * Copyright (C) 2004-2021 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)
@@ -33,7 +33,7 @@
#include "sg_pt.h"
-static const char * version_str = "0.68 20200111"; /* spc6r01 */
+static const char * version_str = "0.69 20210319"; /* spc6r05 */
#define SENSE_BUFF_LEN 64 /* Arbitrary, could be larger */
@@ -125,12 +125,8 @@ usage()
"all listed\n"
" --mlu|-M show MLU bit when all listed\n"
" --no-inquiry|-n don't output INQUIRY information\n"
- " --opcode=OP|-o OP first byte of command to query\n"
- " (decimal, prefix with '0x' for hex)\n"
- " --opcode=OP,SA|-o OP,SA opcode (OP) and service action "
- "(SA)\n"
- " (decimal, each prefix with '0x' for "
- "hex)\n"
+ " --opcode=OP[,SA]|-o OP[,SA] opcode (OP) and service "
+ "action (SA)\n"
" --pdt=DT|-p DT give peripheral device type for "
"'--no-inquiry'\n"
" '--enumerate'\n"
@@ -140,7 +136,6 @@ usage()
" --repd|-q set Report Extended Parameter Data bit, "
"with --tmf\n"
" --sa=SA|-s SA service action in addition to opcode\n"
- " (decimal, prefix with '0x' for hex)\n"
" --tmf|-t output list of supported task management "
"functions\n"
" --unsorted|-u output list of operation codes as is\n"
@@ -150,7 +145,9 @@ usage()
" --old|-O use old interface (use as first option)\n"
" --version|-V print version string then exit\n\n"
"Performs a SCSI REPORT SUPPORTED OPERATION CODES or a REPORT "
- "SUPPORTED\nTASK MANAGEMENT FUNCTIONS command.\n");
+ "SUPPORTED\nTASK MANAGEMENT FUNCTIONS command. All values are "
+ "in decimal by default,\nprefix with '0x' or add a trailing 'h' "
+ "for hex numbers.\n");
}
static void
@@ -701,12 +698,12 @@ list_all_codes(uint8_t * rsoc_buff, int rsoc_len, struct opts_t * op,
printf( " (hex) \n");
printf("---------------------------------------\n");
} else if (op->do_mlu) {
- printf("\nOpcode Service CDB CDLP, Name\n");
- printf( "(hex) action(h) size MLU \n");
+ printf("\nOpcode Service CDB MLU Name\n");
+ printf( "(hex) action(h) size \n");
printf("-----------------------------------------------\n");
} else {
- printf("\nOpcode Service CDB CDLP Name\n");
- printf( "(hex) action(h) size \n");
+ printf("\nOpcode Service CDB RWCDLP, Name\n");
+ printf( "(hex) action(h) size CDLP \n");
printf("-----------------------------------------------\n");
}
}
@@ -775,19 +772,21 @@ list_all_codes(uint8_t * rsoc_buff, int rsoc_len, struct opts_t * op,
"%s\n", opcode, sa_buff,
sg_get_unaligned_be16(bp + 6), name_buff);
} else { /* RCTD clear in cdb */
- /* treat RWCDLP (1 bit) and CDLP (2 bits) as a 3 bit field */
- int cdl_mp = ((byt5 >> 2) & 0x3) + ((0x40 & byt5) ? 4 : 0);
+ /* before version 0.69 treated RWCDLP (1 bit) and CDLP (2 bits),
+ * as a 3 bit field, now break them out separately */
+ int rwcdlp = (byt5 >> 2) & 0x3;
+ int cdlp = !!(0x40 & byt5);
if (op->do_compact)
printf(" %.2x%c%.4s %s\n", bp[0], (sa_v ? ',' : ' '),
sa_buff, name_buff);
else if (op->do_mlu)
- printf(" %.2x %.4s %3d %2d,%d %s\n", bp[0],
+ printf(" %.2x %.4s %3d %3d %s\n", bp[0],
sa_buff, sg_get_unaligned_be16(bp + 6),
- cdl_mp, ((byt5 >> 4) & 0x3), name_buff);
+ ((byt5 >> 4) & 0x3), name_buff);
else
- printf(" %.2x %.4s %3d %2d %s\n", bp[0],
- sa_buff, sg_get_unaligned_be16(bp + 6), cdl_mp,
+ printf(" %.2x %.4s %3d %d,%d %s\n", bp[0],
+ sa_buff, sg_get_unaligned_be16(bp + 6), rwcdlp, cdlp,
name_buff);
}
if (op->do_mask) {
@@ -859,7 +858,7 @@ list_one(uint8_t * rsoc_buff, int cd_len, int rep_opts,
struct opts_t * op)
{
bool valid = false;
- int k, mlu;
+ int k, mlu, rwcdlp;
uint8_t * bp;
const char * cp;
const char * dlp;
@@ -898,21 +897,32 @@ list_one(uint8_t * rsoc_buff, int cd_len, int rep_opts,
break;
}
k = 0x3 & (rsoc_buff[1] >> 3);
+ rwcdlp = rsoc_buff[0] & 1;
switch (k) { /* CDLP field */
case 0:
- dlp = "no command duration limit mode page";
+ if (rwcdlp)
+ dlp = "Reserved [RWCDLP=1, CDLP=0]";
+ else
+ dlp = "No command duration limit mode page";
break;
case 1:
- dlp = "command duration limit A mode page";
+ if (rwcdlp)
+ dlp = "Command duration limit T2A mode page";
+ else
+ dlp = "Command duration limit A mode page";
break;
case 2:
- dlp = "command duration limit B mode page";
+ if (rwcdlp)
+ dlp = "Command duration limit T2B mode page";
+ else
+ dlp = "Command duration limit B mode page";
break;
default:
dlp = "reserved [CDLP=3]";
break;
}
- printf(" Command is %s, [%s]\n", cp, dlp);
+ printf(" Command is %s\n", cp);
+ printf(" %s\n", dlp);
mlu = 0x3 & (rsoc_buff[1] >> 5);
switch (mlu) {
case 0:
@@ -1128,6 +1138,9 @@ open_rw: /* if not already open */
if (res) {
sg_get_category_sense_str(res, sizeof(b), b, vb);
pr2serr("%s: %s\n", op_name, b);
+ if ((0 == op->servact) && (op->opcode >= 0))
+ pr2serr(" >> perhaps try again without a service action "
+ "[SA] of 0\n");
goto err_out;
}
act_len = (rq_len < act_len) ? rq_len : act_len;