aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CREDITS5
-rw-r--r--ChangeLog6
-rw-r--r--README2
-rw-r--r--debian/changelog2
-rw-r--r--doc/sg_inq.812
-rw-r--r--sg3_utils.spec2
-rw-r--r--src/sg_inq.c4
-rw-r--r--src/sg_logs.c245
-rw-r--r--src/sg_modes.c6
-rw-r--r--src/sg_vpd.c108
10 files changed, 371 insertions, 21 deletions
diff --git a/CREDITS b/CREDITS
index abb6b639..d9bff2e0 100644
--- a/CREDITS
+++ b/CREDITS
@@ -67,6 +67,9 @@ Luben Tuikov <ltuikov at yahoo dot com>
help with documentation and other suggestions [20061014]
contribution sg_read_buffer and sg_write_buffer [20061103]
+Marius Konitzer <marius dot konitzer at ruhr-uni-bochum dot de
+ log pages on IBM LTO Ultrium drives [20100225]
+
Mark Knibbs <markk at clara dot co dot uk>
suggested and tested oflag=sparse for sg_dd
@@ -97,4 +100,4 @@ Trent Piepho <xyzzy at speakeasy dot org> print out some "sense key specific"
Doug Gilbert
-15th June 2009
+25th February 2010
diff --git a/ChangeLog b/ChangeLog
index ee74a38a..87e4fa28 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -2,14 +2,18 @@ Each utility has its own version number, date of last change and
some description at the top of its ".c" file. All utilities in the main
directory have their own "man" pages. There is also a sg3_utils man page.
-Changelog for sg3_utils-1.29 [20100218] [svn: r327]
+Changelog for sg3_utils-1.29 [20100228] [svn: r328]
- sg_rtpg: new logical block dependent state and bit (spc4r23)
- sg_start: add '--readonly' option for ATA disks
- sg_lib: update asc/ascq list to spc4r22
- sg_inq: update version descriptor list to spc4r23
- sg_vpd: block device characteristics page: fix form factor
- update Extended Inquiry VPD page to spc4r23
+ - Automation device serial number and Data transfer device
+ element VPD pages (ssc4r01)
- sg_logs: add thin provisioning and solid state media log pages
+ - addition of IBM LTO specific log pages
+ - sg_modes: new page names from ssc4r01
- sg_ses: sync with ses3r02 (SAS-2.1 connector types)
- add AM_MAINTAINER_MODE to configure.ac to lessen build issues
diff --git a/README b/README
index a6f2528b..0e558c14 100644
--- a/README
+++ b/README
@@ -364,4 +364,4 @@ See http://sg.danny.cz/sg/tools.html
Doug Gilbert
-18th February 2010
+28th February 2010
diff --git a/debian/changelog b/debian/changelog
index d81cf792..b337f9c6 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -2,7 +2,7 @@ sg3-utils (1.29-0.1) unstable; urgency=low
* New upstream version
- -- Doug Gilbert <dgilbert@interlog.com> Thu, 18 Feb 2010 16:40:00 +0100
+ -- Doug Gilbert <dgilbert@interlog.com> Sun, 28 Feb 2010 09:30:00 -0500
sg3-utils (1.28-0.1) unstable; urgency=low
diff --git a/doc/sg_inq.8 b/doc/sg_inq.8
index daebd949..b1ce04ea 100644
--- a/doc/sg_inq.8
+++ b/doc/sg_inq.8
@@ -1,4 +1,4 @@
-.TH SG_INQ "8" "September 2009" "sg3_utils\-1.28" SG3_UTILS
+.TH SG_INQ "8" "February 2010" "sg3_utils\-1.29" SG3_UTILS
.SH NAME
sg_inq \- sends a SCSI INQUIRY or ATA IDENTIFY (PACKET) DEVICE command
and outputs the response
@@ -31,9 +31,9 @@ options.
.PP
An important "non\-standard" INQUIRY page is the Device Identification
Vital Product Data (VPD) page [0x83]. Since SPC\-3, support for this page
-is mandatory. The \fI\-\-id\fR option decodes this page. To get fine grained
-decoding of device identification VPD page and recently added VPD pages,
-plus some vendor specific VPD pages, see the sg_vpd(8) utility.
+is mandatory. The \fI\-\-id\fR option decodes this page. New VPD page
+information is no longer being added to this utility. To get information
+on new VPD pages see the sg_vpd(8) or sdparm(8) utilities.
.PP
If the \fIDEVICE\fR exists and the SCSI INQUIRY fails (because the SG_IO ioctl
is not supported) then an ATA IDENTIFY (PACKET) DEVICE is tried. If it
@@ -329,9 +329,9 @@ Written by Doug Gilbert
.SH "REPORTING BUGS"
Report bugs to <dgilbert at interlog dot com>.
.SH COPYRIGHT
-Copyright \(co 2001\-2009 Douglas Gilbert
+Copyright \(co 2001\-2010 Douglas Gilbert
.br
This software is distributed under the GPL version 2. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
.SH "SEE ALSO"
-.B sg_opcodes(8), sg_vpd(8), hdparm(8), sgdiag(scsirastools)
+.B sg_opcodes(8), sg_vpd(8), sdparm(8), hdparm(8), sgdiag(scsirastools)
diff --git a/sg3_utils.spec b/sg3_utils.spec
index 4fd51183..75c66ac4 100644
--- a/sg3_utils.spec
+++ b/sg3_utils.spec
@@ -79,7 +79,7 @@ fi
%{_libdir}/*.la
%changelog
-* Thu Feb 18 2010 - dgilbert at interlog dot com
+* Sun Feb 28 2010 - dgilbert at interlog dot com
- track t10 changes
* sg3_utils-1.29
diff --git a/src/sg_inq.c b/src/sg_inq.c
index 12e7dd14..65c17366 100644
--- a/src/sg_inq.c
+++ b/src/sg_inq.c
@@ -23,7 +23,7 @@
#include "sg_cmds_basic.h"
/* A utility program originally written for the Linux OS SCSI subsystem.
-* Copyright (C) 2000-2009 D. Gilbert
+* Copyright (C) 2000-2010 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)
@@ -66,7 +66,7 @@
* information [MAINTENANCE IN, service action = 0xc]; see sg_opcodes.
*/
-static char * version_str = "0.86 20090916"; /* SPC-4 rev 21 */
+static char * version_str = "0.87 20100228"; /* SPC-4 rev 23 */
#define VPD_SUPPORTED_VPDS 0x0
diff --git a/src/sg_logs.c b/src/sg_logs.c
index e17c528d..6126632b 100644
--- a/src/sg_logs.c
+++ b/src/sg_logs.c
@@ -25,7 +25,7 @@
*/
-static char * version_str = "0.93 20100211"; /* SPC-4 revision 23 */
+static char * version_str = "0.94 20100226"; /* SPC-4 revision 23 */
#define MX_ALLOC_LEN (0xfffc)
#define SHORT_RESP_LEN 128
@@ -761,7 +761,7 @@ show_page_name(int pg_code, int subpg_code,
printf("%sTape diagnostic (ssc-3)\n", b);
break;
case 0x17:
- printf("%sVolume statistics (ssc-3)\n", b);
+ printf("%sVolume statistics (ssc-4)\n", b);
break;
case 0x2d:
printf("%sCurrent service information (ssc-3)\n", b);
@@ -769,6 +769,15 @@ show_page_name(int pg_code, int subpg_code,
case TAPE_ALERT_LPAGE:
printf("%sTapeAlert (ssc-2)\n", b);
break;
+ case 0x30:
+ printf("%sTape usage log (IBM specific)\n", b);
+ break;
+ case 0x31:
+ printf("%sTape capacity log (IBM specific)\n", b);
+ break;
+ case 0x32:
+ printf("%sData compression log (IBM specific)\n", b);
+ break;
default:
done = 0;
break;
@@ -1097,6 +1106,229 @@ show_power_condition_transitions_page(unsigned char * resp, int len,
}
static void
+show_tape_usage_log_page(unsigned char * resp, int len, int show_pcb)
+{
+ int k, num, extra, pc, pcb;
+ unsigned int n;
+ uint64_t ull;
+ unsigned char * ucp;
+ char pcb_str[PCB_STR_LEN];
+
+ num = len - 4;
+ ucp = &resp[0] + 4;
+ if (num < 4) {
+ printf("badly formed tape usage log page\n");
+ return;
+ }
+ printf("Tape usage log page\n");
+ for (k = num; k > 0; k -= extra, ucp += extra) {
+ pc = (ucp[0] << 8) + ucp[1];
+ pcb = ucp[2];
+ extra = ucp[3] + 4;
+ ull = n = 0;
+ switch (ucp[3]) {
+ case 2:
+ n = (ucp[4] << 8) | ucp[5];
+ break;
+ case 4:
+ n = (ucp[4] << 24) | (ucp[5] << 16) | (ucp[6] << 8) | ucp[7];
+ break;
+ case 8:
+ for (n = 0, ull = ucp[4]; n < 8; ++n) {
+ ull <<= 8; ull |= ucp[4 + n];
+ }
+ break;
+ }
+ switch (pc) {
+ case 0x01:
+ if (extra == 8)
+ printf(" Thread count: %u", n);
+ break;
+ case 0x02:
+ if (extra == 12)
+ printf(" Total data sets written: %" PRIu64, ull);
+ break;
+ case 0x03:
+ if (extra == 8)
+ printf(" Total write retries: %u", n);
+ break;
+ case 0x04:
+ if (extra == 6)
+ printf(" Total unrecovered write errors: %u", n);
+ break;
+ case 0x05:
+ if (extra == 6)
+ printf(" Total suspended writes: %u", n);
+ break;
+ case 0x06:
+ if (extra == 6)
+ printf(" Total fatal suspended writes: %u", n);
+ break;
+ case 0x07:
+ if (extra == 12)
+ printf(" Total data sets read: %" PRIu64, ull);
+ break;
+ case 0x08:
+ if (extra == 8)
+ printf(" Total read retries: %u", n);
+ break;
+ case 0x09:
+ if (extra == 6)
+ printf(" Total unrecovered read errors: %u", n);
+ break;
+ case 0x0a:
+ if (extra == 6)
+ printf(" Total suspended reads: %u", n);
+ break;
+ case 0x0b:
+ if (extra == 6)
+ printf(" Total fatal suspended reads: %u", n);
+ break;
+ default:
+ printf(" unknown parameter code = 0x%x, contents in hex:\n", pc);
+ dStrHex((const char *)ucp, extra, 1);
+ break;
+ }
+ if (show_pcb) {
+ get_pcb_str(pcb, pcb_str, sizeof(pcb_str));
+ printf("\n <%s>\n", pcb_str);
+ } else
+ printf("\n");
+ }
+}
+
+static void
+show_tape_capacity_log_page(unsigned char * resp, int len, int show_pcb)
+{
+ int k, num, extra, pc, pcb;
+ unsigned int n;
+ unsigned char * ucp;
+ char pcb_str[PCB_STR_LEN];
+
+ num = len - 4;
+ ucp = &resp[0] + 4;
+ if (num < 4) {
+ printf("badly formed tape capacity log page\n");
+ return;
+ }
+ printf("Tape capacity log page\n");
+ for (k = num; k > 0; k -= extra, ucp += extra) {
+ pc = (ucp[0] << 8) + ucp[1];
+ pcb = ucp[2];
+ extra = ucp[3] + 4;
+ if (extra != 8)
+ continue;
+ n = (ucp[4] << 24) | (ucp[5] << 16) | (ucp[6] << 8) | ucp[7];
+ switch (pc) {
+ case 0x01:
+ printf(" Main partition remaining capacity (in MiB): %u", n);
+ break;
+ case 0x02:
+ printf(" Alternate partition remaining capacity (in MiB): %u", n);
+ break;
+ case 0x03:
+ printf(" Main partition maximum capacity (in MiB): %u", n);
+ break;
+ case 0x04:
+ printf(" Alternate partition maximum capacity (in MiB): %u", n);
+ break;
+ default:
+ printf(" unknown parameter code = 0x%x, contents in hex:\n", pc);
+ dStrHex((const char *)ucp, extra, 1);
+ break;
+ }
+ if (show_pcb) {
+ get_pcb_str(pcb, pcb_str, sizeof(pcb_str));
+ printf("\n <%s>\n", pcb_str);
+ } else
+ printf("\n");
+ }
+}
+
+static void
+show_data_compression_log_page(unsigned char * resp, int len, int show_pcb)
+{
+ int k, num, extra, pc, pcb;
+ unsigned int n;
+ unsigned char * ucp;
+ char pcb_str[PCB_STR_LEN];
+
+ num = len - 4;
+ ucp = &resp[0] + 4;
+ if (num < 4) {
+ printf("badly formed data compression log page\n");
+ return;
+ }
+ printf("Data compression log page\n");
+ for (k = num; k > 0; k -= extra, ucp += extra) {
+ pc = (ucp[0] << 8) + ucp[1];
+ pcb = ucp[2];
+ extra = ucp[3] + 4;
+ switch (ucp[3]) {
+ case 2:
+ n = (ucp[4] << 8) | ucp[5];
+ break;
+ case 4:
+ n = (ucp[4] << 24) | (ucp[5] << 16) | (ucp[6] << 8) | ucp[7];
+ break;
+ default:
+ n = 0;
+ }
+ switch (pc) {
+ case 0x00:
+ if (extra == 6)
+ printf(" Read compression ratio x100: %u", n);
+ break;
+ case 0x01:
+ if (extra == 6)
+ printf(" Write compression ratio x100: %u", n);
+ break;
+ case 0x02:
+ if (extra == 8)
+ printf(" Megabytes transferred to server: %u", n);
+ break;
+ case 0x03:
+ if (extra == 8)
+ printf(" Bytes transferred to server: %u", n);
+ break;
+ case 0x04:
+ if (extra == 8)
+ printf(" Megabytes read from tape: %u", n);
+ break;
+ case 0x05:
+ if (extra == 8)
+ printf(" Bytes read from tape: %u", n);
+ break;
+ case 0x06:
+ if (extra == 8)
+ printf(" Megabytes transferred from server: %u", n);
+ break;
+ case 0x07:
+ if (extra == 8)
+ printf(" Bytes transferred from server: %u", n);
+ break;
+ case 0x08:
+ if (extra == 8)
+ printf(" Megabytes written to tape: %u", n);
+ break;
+ case 0x09:
+ if (extra == 8)
+ printf(" Bytes written to tape: %u", n);
+ break;
+ default:
+ printf(" unknown parameter code = 0x%x, contents in hex:\n", pc);
+ dStrHex((const char *)ucp, extra, 1);
+ break;
+ }
+ if (show_pcb) {
+ get_pcb_str(pcb, pcb_str, sizeof(pcb_str));
+ printf("\n <%s>\n", pcb_str);
+ } else
+ printf("\n");
+ }
+}
+
+static void
show_last_n_error_page(unsigned char * resp, int len, int show_pcb)
{
int k, num, pl, pc, pcb;
@@ -3435,6 +3667,15 @@ show_ascii_page(unsigned char * resp, int len,
}
}
break;
+ case 0x30:
+ show_tape_usage_log_page(resp, len, optsp->do_pcb);
+ break;
+ case 0x31:
+ show_tape_capacity_log_page(resp, len, optsp->do_pcb);
+ break;
+ case 0x32:
+ show_data_compression_log_page(resp, len, optsp->do_pcb);
+ break;
case IE_LPAGE:
show_ie_page(resp, len, optsp->do_pcb, 1);
break;
diff --git a/src/sg_modes.c b/src/sg_modes.c
index 0399c401..31e64670 100644
--- a/src/sg_modes.c
+++ b/src/sg_modes.c
@@ -13,7 +13,7 @@
#include "sg_cmds_basic.h"
/*
-* Copyright (C) 2000-2009 D. Gilbert
+* Copyright (C) 2000-2010 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)
@@ -26,7 +26,7 @@
*/
-static char * version_str = "1.32 20090826";
+static char * version_str = "1.33 20100228";
#define DEF_ALLOC_LEN (1024 * 4)
#define DEF_6_ALLOC_LEN 252
@@ -534,6 +534,8 @@ static struct page_code_desc pc_desc_disk[] = {
};
static struct page_code_desc pc_desc_tape[] = {
+ {0x1, 0x0, "Read-Write error recovery"},
+ {0xa, 0xf0, "Control data protection"},
{0xf, 0x0, "Data Compression"},
{0x10, 0x0, "Device configuration"},
{0x10, 0x1, "Device configuration extension"},
diff --git a/src/sg_vpd.c b/src/sg_vpd.c
index a3fd694a..ff3751d6 100644
--- a/src/sg_vpd.c
+++ b/src/sg_vpd.c
@@ -52,7 +52,7 @@
*/
-static char * version_str = "0.38 20100211"; /* spc4r23 + sbc3r21 */
+static char * version_str = "0.39 20100228"; /* spc4r23 + sbc3r21 */
extern void svpd_enumerate_vendor(void);
extern int svpd_decode_vendor(int sg_fd, int num_vpd, int subvalue,
@@ -87,6 +87,7 @@ extern const struct svpd_values_name_t *
#define VPD_TA_SUPPORTED 0xb2 /* SSC-3 */
#define VPD_THIN_PROVISIONING 0xb2 /* SBC-3 */
#define VPD_AUTOMATION_DEV_SN 0xb3 /* SSC-3 */
+#define VPD_DTDE_ADDRESS 0xb4 /* SSC-4 */
/* Device identification VPD page associations */
#define VPD_ASSOC_LU 0
@@ -163,6 +164,8 @@ static struct svpd_values_name_t standard_vpd_pg[] = {
"identification, target port only"},
{VPD_DEVICE_ID, VPD_DI_SEL_TARGET, -1, 0, "di_target", "Device "
"identification, target device only"},
+ {VPD_DTDE_ADDRESS, 0, 1, 0, "dtde",
+ "Data transfer device element address (SSC)"},
{VPD_EXT_INQ, 0, -1, 0, "ei", "Extended inquiry data"},
{VPD_IMP_OP_DEF, 0, -1, 0, "iod",
"Implemented operating definition (obsolete)"},
@@ -1603,6 +1606,8 @@ svpd_decode_t10(int sg_fd, int num_vpd, int subvalue, int maxlen, int do_hex,
const struct svpd_values_name_t * vnp;
int res = 0;
int alloc_len = maxlen;
+ char obuff[DEF_ALLOC_LEN];
+
if (0 == alloc_len)
alloc_len = (VPD_ATA_INFO == num_vpd) ?
@@ -1699,8 +1704,6 @@ svpd_decode_t10(int sg_fd, int num_vpd, int subvalue, int maxlen, int do_hex,
else if (do_hex)
dStrHex((const char *)rsp_buff, len, 0);
else {
- char obuff[DEF_ALLOC_LEN];
-
pdt = rsp_buff[0] & 0x1f;
if (verbose || do_long)
printf(" [PQual=%d Peripheral device type: %s]\n",
@@ -2025,7 +2028,7 @@ svpd_decode_t10(int sg_fd, int num_vpd, int subvalue, int maxlen, int do_hex,
}
break;
case VPD_POWER_CONDITION: /* 0x8a */
- if ((! do_raw) && (3 != do_hex) && (! do_quiet))
+ if ((! do_raw) && (! do_quiet))
printf("Power condition VPD page:\n");
res = sg_ll_inquiry(sg_fd, 0, 1, num_vpd, rsp_buff, alloc_len, 1,
verbose);
@@ -2339,6 +2342,103 @@ svpd_decode_t10(int sg_fd, int num_vpd, int subvalue, int maxlen, int do_hex,
} else if (! do_raw)
printf("VPD page=0xb2\n");
break;
+ case VPD_AUTOMATION_DEV_SN: /* 0xb3 */
+ if ((! do_raw) && (! do_quiet))
+ printf("Automation device serial number (SSC):\n");
+ res = sg_ll_inquiry(sg_fd, 0, 1, num_vpd, rsp_buff, alloc_len, 1,
+ verbose);
+ if (0 == res) {
+ len = ((rsp_buff[2] << 8) + rsp_buff[3]) + 4;
+ if (num_vpd != rsp_buff[1]) {
+ fprintf(stderr, "invalid VPD response; probably a STANDARD "
+ "INQUIRY response\n");
+ if (verbose) {
+ fprintf(stderr, "First 32 bytes of bad response\n");
+ dStrHex((const char *)rsp_buff, 32, 0);
+ }
+ return SG_LIB_CAT_MALFORMED;
+ }
+ if (len > alloc_len) {
+ if ((0 == maxlen) && (len < MX_ALLOC_LEN)) {
+ res = sg_ll_inquiry(sg_fd, 0, 1, num_vpd, rsp_buff, len,
+ 1, verbose);
+ if (res) {
+ fprintf(stderr, "fetching Automation device serial "
+ "number page (alloc_len=%d) failed\n", len);
+ return res;
+ }
+ } else {
+ fprintf(stderr, ">>> warning: response length (%d) "
+ "longer than requested (%d)\n", len, alloc_len);
+ len = alloc_len;
+ }
+ }
+ if (do_raw)
+ dStrRaw((const char *)rsp_buff, len);
+ else {
+ pdt = rsp_buff[0] & 0x1f;
+ if (verbose || do_long)
+ printf(" [PQual=%d Peripheral device type: %s]\n",
+ (rsp_buff[0] & 0xe0) >> 5,
+ sg_get_pdt_str(pdt, sizeof(buff), buff));
+ memset(obuff, 0, sizeof(obuff));
+ len -= 4;
+ if (len >= (int)sizeof(obuff))
+ len = sizeof(obuff) - 1;
+ memcpy(obuff, rsp_buff + 4, len);
+ printf(" Automation device serial number: %s\n", obuff);
+ }
+ return 0;
+ }
+ break;
+ case VPD_DTDE_ADDRESS: /* 0xb4 */
+ if ((! do_raw) && (! do_quiet))
+ printf("Data transfer device element address (SSC):\n");
+ res = sg_ll_inquiry(sg_fd, 0, 1, num_vpd, rsp_buff, alloc_len, 1,
+ verbose);
+ if (0 == res) {
+ len = ((rsp_buff[2] << 8) + rsp_buff[3]) + 4;
+ if (num_vpd != rsp_buff[1]) {
+ fprintf(stderr, "invalid VPD response; probably a STANDARD "
+ "INQUIRY response\n");
+ if (verbose) {
+ fprintf(stderr, "First 32 bytes of bad response\n");
+ dStrHex((const char *)rsp_buff, 32, 0);
+ }
+ return SG_LIB_CAT_MALFORMED;
+ }
+ if (len > alloc_len) {
+ if ((0 == maxlen) && (len < MX_ALLOC_LEN)) {
+ res = sg_ll_inquiry(sg_fd, 0, 1, num_vpd, rsp_buff, len,
+ 1, verbose);
+ if (res) {
+ fprintf(stderr, "fetching Data transfer device "
+ "element address page (alloc_len=%d) "
+ "failed\n", len);
+ return res;
+ }
+ } else {
+ fprintf(stderr, ">>> warning: response length (%d) "
+ "longer than requested (%d)\n", len, alloc_len);
+ len = alloc_len;
+ }
+ }
+ if (do_raw)
+ dStrRaw((const char *)rsp_buff, len);
+ else {
+ pdt = rsp_buff[0] & 0x1f;
+ if (verbose || do_long)
+ printf(" [PQual=%d Peripheral device type: %s]\n",
+ (rsp_buff[0] & 0xe0) >> 5,
+ sg_get_pdt_str(pdt, sizeof(buff), buff));
+ printf(" Data transfer device element address: 0x");
+ for (k = 4; k < len; ++k)
+ printf("%02x", (unsigned int)rsp_buff[k]);
+ printf("\n");
+ }
+ return 0;
+ }
+ break;
default:
return SG_LIB_SYNTAX_ERROR;
}