aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CHANGELOG26
-rw-r--r--COVERAGE4
-rw-r--r--INSTALL33
-rw-r--r--Makefile13
-rw-r--r--Makefile.asroot13
-rw-r--r--README16
-rw-r--r--archive/scsi_devfs_scan.c2
-rw-r--r--archive/sg_bus_xfer.c12
-rw-r--r--archive/sg_poll.c6
-rw-r--r--archive/sgq_dd.c562
-rw-r--r--debian/changelog61
-rw-r--r--debian/control74
-rw-r--r--debian/copyright15
-rw-r--r--debian/docs4
-rw-r--r--debian/libsgutils1-0-dev.dirs2
-rw-r--r--debian/libsgutils1-0-dev.install5
-rw-r--r--debian/libsgutils1-0.dirs1
-rw-r--r--debian/libsgutils1-0.install1
-rw-r--r--debian/rules77
-rw-r--r--debian/sg3-utils.dirs1
-rw-r--r--debian/sg3-utils.examples2
-rw-r--r--debian/sg3-utils.install2
-rw-r--r--debian/sg3-utils.preinst48
-rw-r--r--examples/sg_excl.c10
-rw-r--r--examples/sg_iovec_tst.c20
-rw-r--r--examples/sg_sense_test.c10
-rw-r--r--examples/sg_simple1.c6
-rw-r--r--examples/sg_simple16.c10
-rw-r--r--examples/sg_simple3.c6
-rw-r--r--examples/sg_simple4.c46
-rw-r--r--html/sg_dd.html104
-rw-r--r--html/u_index.html58
-rw-r--r--lib_no_lib/Makefile.no_lib11
-rw-r--r--lib_no_lib/sg3_utils.spec.no_lib8
-rw-r--r--sg3_utils.spec6
-rw-r--r--sg_cmds.c509
-rw-r--r--sg_cmds.h20
-rw-r--r--sg_dd.824
-rw-r--r--sg_dd.c46
-rw-r--r--sg_format.88
-rw-r--r--sg_format.c38
-rw-r--r--sg_get_config.836
-rw-r--r--sg_get_config.c47
-rw-r--r--sg_ident.8115
-rw-r--r--sg_ident.c275
-rw-r--r--sg_inq.842
-rw-r--r--sg_inq.c251
-rw-r--r--sg_lib.c50
-rw-r--r--sg_lib.h11
-rw-r--r--sg_logs.c44
-rw-r--r--sg_luns.c10
-rw-r--r--sg_map.c13
-rw-r--r--sg_modes.816
-rw-r--r--sg_modes.c5
-rw-r--r--sg_opcodes.c16
-rw-r--r--sg_persist.c15
-rw-r--r--sg_prevent.c76
-rw-r--r--sg_rbuf.c13
-rw-r--r--sg_read.c6
-rw-r--r--sg_read_long.c11
-rw-r--r--sg_readcap.812
-rw-r--r--sg_readcap.c58
-rw-r--r--sg_reassign.84
-rw-r--r--sg_reassign.c9
-rw-r--r--sg_requests.827
-rw-r--r--sg_requests.c16
-rw-r--r--sg_rmsn.c92
-rw-r--r--sg_rtpg.c10
-rw-r--r--sg_scan.c6
-rw-r--r--sg_senddiag.825
-rw-r--r--sg_senddiag.c10
-rw-r--r--sg_ses.89
-rw-r--r--sg_ses.c9
-rw-r--r--sg_start.861
-rw-r--r--sg_start.c133
-rw-r--r--sg_sync.c5
-rw-r--r--sg_test_rwbuf.c17
-rw-r--r--sg_turs.c6
-rw-r--r--sg_verify.c11
-rw-r--r--sg_wr_mode.c5
-rw-r--r--sg_write_long.c11
-rw-r--r--sginfo.c155
-rw-r--r--sgm_dd.c14
-rw-r--r--sgp_dd.c10
84 files changed, 2569 insertions, 1118 deletions
diff --git a/CHANGELOG b/CHANGELOG
index 8af623c9..9450dd60 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -2,6 +2,30 @@ 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.
+Changelog for sg3_utils-1.16 [20050810]
+ - sg_ident: new utility to report+set device identifier
+ - sg_map: increase MAX_SG_DEVS from 256 to 2048
+ - debian: new directory to support deb package builds
+ - sg_get_config: add '--current' option, same as '--rt=1'
+ - update for DVD+RW Dual Layer
+ - sg_inq: add notes in source about use of SCSI INQUIRY
+ - decode Management network addresses VPD page ('-m')
+ - decode Mode page policy VPD page ('-M')
+ - sginfo: increase device mapping capability (> 78 disks)
+ - add '-r' option to scan /dev/raw* device nodes [Tim Hunt]
+ - sg_dd: change bpt default value to 32 when bs >= 2048 bytes
+ - sg_ses: mention SAF-TE in man page
+ - sg_readcap: add '-b' option for brief output (2 hex numbers)
+ - sg_cmds: add sg_ll_start_stop_unit(), sg_ll_prevent_allow(),
+ sg_ll_report_dev_id() and sg_ll_set_dev_id()
+ - sg_lib: add extra argument to sense print functions to enable
+ the suppression of the raw output of the sense buffer
+ - resid > 0 warnings now includes number actually fetched
+ - sg_start: add '-load' and '-eject' options
+ - default to start action when no other indication given
+ - change -imm=0|1 option default to 0 (was 1)
+ - gcc 4.0: cleanup warnings (apart from sgp_dd: revisit later)
+
Changelog for sg3_utils-1.15 [20050605]
- sg_cmds: sg_get_mode_page_controls(): improve error processing,
add double fetch
@@ -136,7 +160,7 @@ Changelog for sg3_utils-1.09 [20041022]
- decode last n error events and last n deferred errors pages
- add names of ADC log pages
- sg_inq: update to SPC-3 rev 21
- - decode Extended INQUIRY VPD page [0x86] {'-x'}
+ - decode Extended INQUIRY data VPD page [0x86] {'-x'}
- decode Unit Path Report VPD page [0xc0] (EMC) {'-P'}
- sginfo: decode SAS protocol specific lu mode page
- sg_err: convert to sg_lib + update to SPC-3 rev 21
diff --git a/COVERAGE b/COVERAGE
index 2818b989..0ddb24da 100644
--- a/COVERAGE
+++ b/COVERAGE
@@ -35,12 +35,14 @@ READ LONG sg_read_long, sg_dd
READ MEDIA SERIAL NUMBER sg_rmsn
REASSIGN BLOCKS sg_reassign
RECEIVE DIAGNOSTIC sg_senddiag, sg_ses
+REPORT DEVICE IDENTIFIER sg_ident
REPORT LUNS sg_luns
REPORT SUPPORTED OPERATION CODES sg_opcodes
REPORT SUPPORTED TASK MANAGEMENT FUNCTIONS sg_opcodes
REPORT TARGET PORT GROUPS sg_rtpg
REQUEST SENSE sg_requests
SEND DIAGNOSTIC sg_senddiag, sg_ses
+SET DEVICE IDENTIFIER sg_ident
START STOP sg_start
SYNCHRONIZE CACHE sg_sync, sg_dd, sgm_dd, sgp_dd
TEST UNIT READY sg_turs, sg_format
@@ -61,4 +63,4 @@ IDENTIFY sg_inq, sg_scan
** sdparm is now in its own package called sdparm (rather than sg3_utils)
Doug Gilbert
-18th April 2005
+5th August 2005
diff --git a/INSTALL b/INSTALL
index e0133288..365734c7 100644
--- a/INSTALL
+++ b/INSTALL
@@ -35,24 +35,29 @@ directory. If an executable cannot find the libsgutils shared library
(check with 'ldd sg_inq' for example) then the addition of "/usr/local/lib"
to the /etc/ld.so.conf file may be required in some distributions.
-A "spec" file is included for building rpm packages. To build binary and
+A "spec" file is included for building rpm packages. It is called
+sg3_utils.spec and is in the "rpm" subdirectory. To build binary and
source rpms place a copy of the gzipped tarball in the "SOURCES" directory
-and place a copy of sg3_utils.spec in the "SPEC" directory. This directories
-are found under /usr/src/redhat on redhat distributions. Then from the
-"SPEC" directory execute "rpmbuild -ba sg3_utils.spec". If all goes well
-a source rpm should be found in the SRPMS directory and a binary rpm in the
-RPMS/i386 directory (for i386 architecture). Note the spec file will only
-build those utilities in the main directory. When the binary rpm is
-installed the executables and their associated man pages should be placed
-in appropriate places. The sg3_utils.spec file also builds an
-sg3-utils-devel rpm that contains the libsgutils static library and
-the sg_lib.h and sg_cmds.h header files.
+and place a copy of sg3_utils.spec in the "SPEC" directory. These
+directories are found under /usr/src/redhat on redhat distributions. Then
+from the "SPEC" directory execute "rpmbuild -ba sg3_utils.spec". If all
+goes well a source rpm should be found in the SRPMS directory and binary
+rpms in the RPMS/i386 directory (for i386 architecture). Note the spec
+file will only build those utilities in the main directory. When the
+sg3_utils binary rpm is installed the executables and their associated man
+pages should be placed in appropriate places. The sg3_utils.spec file also
+builds a libsgutils shared object (shared library) and a libsgutils-*-devel
+shared object with a static library and the sg_lib.h and sg_cmds.h header
+files.
Binary rpms (at least in the RedHat distribution) tend to install
executables in /usr/bin and libraries in /usr/lib .
-If the libsgutils.so shared library is troublesome or unwanted
-then "no_lib" versions of the Makefile and the sg3_utils.spec file
+If the shared object (library) is troublesome or unwanted then
+a "no_lib" version of the Makefile and the sg3_utils.spec file
can be found in the "lib_no_lib" subdirectory.
-26th November 2004
+There is also infrastructure in the debian subdirectory to build
+deb packages.
+
+8th June 2005
diff --git a/Makefile b/Makefile
index 0f9ef79f..535d5ce6 100644
--- a/Makefile
+++ b/Makefile
@@ -3,7 +3,7 @@ SHELL = /bin/sh
PREFIX=/usr/local
LIBDIR=$(DESTDIR)/$(PREFIX)/lib
INSTDIR=$(DESTDIR)/$(PREFIX)/bin
-MANDIR=$(DESTDIR)/$(PREFIX)/man
+MANDIR=$(DESTDIR)/$(PREFIX)/share/man
INCLUDEDIR=$(DESTDIR)/$(PREFIX)/include
CC = gcc
@@ -15,7 +15,7 @@ EXECS = sg_dd sgp_dd sgm_dd sg_read sg_map sg_scan sg_rbuf \
sg_persist sg_write_long sg_read_long sg_requests sg_ses \
sg_verify sg_emc_trespass sg_luns sg_sync sg_prevent \
sg_get_config sg_wr_mode sg_rtpg sg_reassign sg_format \
- sg_rmsn
+ sg_rmsn sg_ident
MAN_PGS = sg_dd.8 sgp_dd.8 sgm_dd.8 sg_read.8 sg_map.8 sg_scan.8 sg_rbuf.8 \
sginfo.8 sg_readcap.8 sg_turs.8 sg_inq.8 sg_test_rwbuf.8 \
@@ -23,7 +23,7 @@ MAN_PGS = sg_dd.8 sgp_dd.8 sgm_dd.8 sg_read.8 sg_map.8 sg_scan.8 sg_rbuf.8 \
sg_opcodes.8 sg_persist.8 sg_write_long.8 sg_read_long.8 \
sg_requests.8 sg_ses.8 sg_verify.8 sg_emc_trespass.8 \
sg_luns.8 sg_sync.8 sg_prevent.8 sg_get_config.8 sg_wr_mode.8 \
- sg_rtpg.8 sg_reassign.8 sg_format.8 sg_rmsn.8
+ sg_rtpg.8 sg_reassign.8 sg_format.8 sg_rmsn.8 sg_ident.8
MAN_PREF = man8
HEADERS = sg_lib.h sg_cmds.h
@@ -67,8 +67,8 @@ libsgutils.la: sg_lib.lo sg_cmds.lo
-rpath $(LIBDIR) -version-info $(LIB_VINFO)
# libsgutils.la: sg_lib.lo sg_cmds.lo
-# libtool --mode=link $(LD) -o libsgutils.la sg_lib.lo sg_cmds.lo \
-# -rpath $(LIBDIR) -release $(RELEASE)
+# libtool --mode=link $(LD) -o libsgutils.la sg_lib.lo sg_cmds.lo \
+# -rpath $(LIBDIR) -release $(RELEASE)
sg_inq: sg_inq.o libsgutils.la
libtool --mode=link $(LD) -o $@ $(LDFLAGS) $^
@@ -175,6 +175,9 @@ sg_format: sg_format.o libsgutils.la
sg_rmsn: sg_rmsn.o libsgutils.la
libtool --mode=link $(LD) -o $@ $(LDFLAGS) $^
+sg_ident: sg_ident.o libsgutils.la
+ libtool --mode=link $(LD) -o $@ $(LDFLAGS) $^
+
install: $(EXECS)
install -d $(INSTDIR)
install -d $(LIBDIR)
diff --git a/Makefile.asroot b/Makefile.asroot
index 6356d468..c005950e 100644
--- a/Makefile.asroot
+++ b/Makefile.asroot
@@ -3,7 +3,7 @@ SHELL = /bin/sh
PREFIX=/usr/local
LIBDIR=$(DESTDIR)/$(PREFIX)/lib
INSTDIR=$(DESTDIR)/$(PREFIX)/bin
-MANDIR=$(DESTDIR)/$(PREFIX)/man
+MANDIR=$(DESTDIR)/$(PREFIX)/share/man
INCLUDEDIR=$(DESTDIR)/$(PREFIX)/include
CC = gcc
@@ -15,7 +15,7 @@ EXECS = sg_dd sgp_dd sgm_dd sg_read sg_map sg_scan sg_rbuf \
sg_persist sg_write_long sg_read_long sg_requests sg_ses \
sg_verify sg_emc_trespass sg_luns sg_sync sg_prevent \
sg_get_config sg_wr_mode sg_rtpg sg_reassign sg_format \
- sg_rmsn
+ sg_rmsn sg_ident
MAN_PGS = sg_dd.8 sgp_dd.8 sgm_dd.8 sg_read.8 sg_map.8 sg_scan.8 sg_rbuf.8 \
sginfo.8 sg_readcap.8 sg_turs.8 sg_inq.8 sg_test_rwbuf.8 \
@@ -23,7 +23,7 @@ MAN_PGS = sg_dd.8 sgp_dd.8 sgm_dd.8 sg_read.8 sg_map.8 sg_scan.8 sg_rbuf.8 \
sg_opcodes.8 sg_persist.8 sg_write_long.8 sg_read_long.8 \
sg_requests.8 sg_ses.8 sg_verify.8 sg_emc_trespass.8 \
sg_luns.8 sg_sync.8 sg_prevent.8 sg_get_config.8 sg_wr_mode.8 \
- sg_rtpg.8 sg_reassign.8 sg_format.8 sg_rmsn.8
+ sg_rtpg.8 sg_reassign.8 sg_format.8 sg_rmsn.8 sg_ident.8
MAN_PREF = man8
HEADERS = sg_lib.h sg_cmds.h
@@ -34,7 +34,7 @@ LARGE_FILE_FLAGS = -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64
# CFLAGS = -O2 -Wall -W $(LARGE_FILE_FLAGS)
CFLAGS = -g -O2 -Wall -W $(LARGE_FILE_FLAGS)
# CFLAGS = -g -O2 -W -DSG_KERNEL_INCLUDES $(LARGE_FILE_FLAGS)
-# CFLAGS = -g -O2 -Wall -pedantic -std=c99 $(LARGE_FILE_FLAGS)
+# CFLAGS = -g -O2 -Wall -W -pedantic -std=c99 $(LARGE_FILE_FLAGS)
CFLAGS_PTHREADS = -D_REENTRANT
@@ -92,7 +92,7 @@ sg_readcap: sg_readcap.o libsgutils.la
libtool --mode=link $(LD) -o $@ $(LDFLAGS) $^
sgp_dd.o: sgp_dd.c
- $(CC) $(INCLUDES) $(CFLAGS) $(CFLAGS_PTHREADS) -o $@ -c $^
+ $(CC) $(INCLUDES) $(CFLAGS) $(CFLAGS_PTHREADS) -c $<
sgp_dd: sgp_dd.o llseek.o libsgutils.la
libtool --mode=link $(LD) -o $@ $(LDFLAGS) $^ -lpthread
@@ -175,6 +175,9 @@ sg_format: sg_format.o libsgutils.la
sg_rmsn: sg_rmsn.o libsgutils.la
libtool --mode=link $(LD) -o $@ $(LDFLAGS) $^
+sg_ident: sg_ident.o libsgutils.la
+ libtool --mode=link $(LD) -o $@ $(LDFLAGS) $^
+
install: $(EXECS)
install -d $(INSTDIR)
install -d $(LIBDIR)
diff --git a/README b/README
index f21ccae7..319b56e1 100644
--- a/README
+++ b/README
@@ -137,11 +137,11 @@ Utilities
Here is list in alphabetical order of utilities found in the main directory
of the sg3_utils directory:
- sginfo, sgm_dd, sgp_dd, sg_dd, sg_emc_trespass, sg_get_config,
- sg_format, sg_inq, sg_logs, sg_luns, sg_map, sg_modes, sg_opcodes,
- sg_persist, sg_prevent, sg_rbuf, sg_read, sg_readcap, sg_read_long,
- sg_reassign, sg_request, sg_reset, sg_rmsn, sg_rtpg, sg_scan,
- sg_senddiag, sg_ses, sg_start, sg_sync, sg_test_rwbuff, sg_turs,
- sg_verify, sg_write_long, sg_wr_mode
+ sg_format, sg_ident, sg_inq, sg_logs, sg_luns, sg_map, sg_modes,
+ sg_opcodes, sg_persist, sg_prevent, sg_rbuf, sg_read, sg_readcap,
+ sg_read_long, sg_reassign, sg_request, sg_reset, sg_rmsn, sg_rtpg,
+ sg_scan, sg_senddiag, sg_ses, sg_start, sg_sync, sg_test_rwbuff,
+ sg_turs, sg_verify, sg_write_long, sg_wr_mode
These utilities and the libsgutils.so library which they depend on are built
by the Makefile in the main directory. This Makefile does not invoke the
@@ -241,7 +241,9 @@ glibc have removed this symlink. Hence this technique is no longer
recommended.
The include file path issues are now all addressed in one file called
-"sg_include.h". Please read that file.
+"sg_include.h". Please read that file. This fetching of the scsi.h and
+sg.h header files has not been a problem in the latter lk 2.4 and lk 2.6
+series.
scsirastools
============
@@ -260,4 +262,4 @@ user). It is available for Linux and other operating systems.
See http://members.aol.com/plscsi .
Doug Gilbert
-5th June 2005
+10th August 2005
diff --git a/archive/scsi_devfs_scan.c b/archive/scsi_devfs_scan.c
index fdb13773..bf23a3fc 100644
--- a/archive/scsi_devfs_scan.c
+++ b/archive/scsi_devfs_scan.c
@@ -135,7 +135,7 @@ static int do_inquiry(int sg_fd, void * resp, int mx_resp_len)
case SG_LIB_CAT_RECOVERED:
return 0;
default:
- sg_chk_n_print3("Failed INQUIRY", &io_hdr);
+ sg_chk_n_print3("Failed INQUIRY", &io_hdr, 1);
return -1;
}
}
diff --git a/archive/sg_bus_xfer.c b/archive/sg_bus_xfer.c
index e75ab84b..5fd45e5a 100644
--- a/archive/sg_bus_xfer.c
+++ b/archive/sg_bus_xfer.c
@@ -118,18 +118,18 @@ int main(int argc, char * argv[])
file_name = argv[j];
}
if ((0 == file_name) || (count < 0) || (do_wr < 0) || (addr == ULONG_MAX)
- || (skip < 0)) {
- printf("Probabably missing parameter\n\n");
+ || (skip < 0)) {
+ printf("Probabably missing parameter\n\n");
printf(
"Usage: 'sg_bus_xfer -r|w -a=hex_num [-bs=num] -skip=num"
- " <sg_device>'\n");
+ " <sg_device>'\n");
printf(" where: -r|w read from (or write to) sg device\n");
printf(" -a=hex_num memory address (virtual ?)\n");
printf(" -bs=num blocks size in bytes (default 512)\n");
printf(" -skip=num num is blocks to skip/seek on sg dev\n");
printf(" -count=num num of blocks to xfer\n");
printf("\n BEWARE you could do damage with this command "
- "(needs root access)\n");
+ "(needs root access)\n");
printf("\n bs, skip and count may take k,K,m,M etc multipliers\n");
return 1;
}
@@ -161,7 +161,7 @@ int main(int argc, char * argv[])
io_hdr.mx_sb_len = sizeof(sense_buffer);
io_hdr.dxfer_direction = do_wr ? SG_DXFER_TO_DEV : SG_DXFER_FROM_DEV;
io_hdr.dxfer_len = bs * count;
- // io_hdr.dxferp = malloc(1024 * 1024); /* <<<<<<<<<<<<<<<< */
+ // io_hdr.dxferp = malloc(1024 * 1024); /* <<<<<<<<<<<<<<<< */
io_hdr.dxferp = (void *)addr;
io_hdr.cmdp = rwCmdBlk;
io_hdr.flags = SG_FLAG_BUS_ADDR;
@@ -187,7 +187,7 @@ int main(int argc, char * argv[])
printf("Recovered error, continuing\n");
break;
default: /* won't bother decoding other categories */
- sg_chk_n_print3("SG_IO error", &io_hdr);
+ sg_chk_n_print3("SG_IO error", &io_hdr, 1);
return 1;
}
return 0;
diff --git a/archive/sg_poll.c b/archive/sg_poll.c
index 28957505..8dcf6f0b 100644
--- a/archive/sg_poll.c
+++ b/archive/sg_poll.c
@@ -101,9 +101,9 @@ void sg_sa_handler(int sig, siginfo_t *si, void * data)
{
signo = sig;
if (SIGRTMIN != sig)
- fprintf(stderr, "Unexpected signal, signum=%d\n", sig);
+ fprintf(stderr, "Unexpected signal, signum=%d\n", sig);
if (sg_fd != si->si_fd)
- fprintf(stderr, "Unexpected fd, fd=%d\n", si->si_fd);
+ fprintf(stderr, "Unexpected fd, fd=%d\n", si->si_fd);
++hand_count;
if (do_poll()) {
struct sembuf a_sembuf;
@@ -314,7 +314,7 @@ printf("Usage: 'sg_poll [-deb] <generic_device>' eg: sg_poll /dev/sg0\n");
}
sg_chk_n_print("after read(rd)", rsghp->target_status,
rsghp->host_status, rsghp->driver_status,
- rsghp->sense_buffer, SG_MAX_SENSE);
+ rsghp->sense_buffer, SG_MAX_SENSE, 1);
}
printf("\treq_len=%d, dma_count=%d\n", rsghp->reply_len, rsghp->pack_len);
diff --git a/archive/sgq_dd.c b/archive/sgq_dd.c
index 8dd95563..84d03904 100644
--- a/archive/sgq_dd.c
+++ b/archive/sgq_dd.c
@@ -61,7 +61,7 @@ static char * version_str = "0.55 20020509";
#define SGP_READ10 0x28
#define SGP_WRITE10 0x2a
-#define DEF_NUM_THREADS 4 /* actually degree of concurrency */
+#define DEF_NUM_THREADS 4 /* actually degree of concurrency */
#define MAX_NUM_THREADS 32
#ifndef RAW_MAJOR
@@ -72,10 +72,10 @@ static char * version_str = "0.55 20020509";
#define FT_SG 1 /* filetype is sg char device */
#define FT_RAW 2 /* filetype is raw char device */
-#define QS_IDLE 0 /* ready to start a copy cycle */
-#define QS_IN_STARTED 1 /* commenced read */
-#define QS_IN_FINISHED 2 /* finished read, ready for write */
-#define QS_OUT_STARTED 3 /* commenced write */
+#define QS_IDLE 0 /* ready to start a copy cycle */
+#define QS_IN_STARTED 1 /* commenced read */
+#define QS_IN_FINISHED 2 /* finished read, ready for write */
+#define QS_OUT_STARTED 3 /* commenced write */
#define QS_IN_POLL 11
#define QS_OUT_POLL 12
@@ -118,7 +118,7 @@ typedef struct request_collection
typedef struct request_element
{ /* one instance per worker thread */
- int qstate; /* "QS" state */
+ int qstate; /* "QS" state */
int infd;
int outfd;
int wr;
@@ -218,15 +218,15 @@ void usage()
"sgq_dd [if=<infile>] [skip=<n>] [of=<ofile>] [seek=<n>] "
"[bs=<num>]\n"
" [bpt=<num>] [count=<n>] [dio=0|1] [thr=<n>] "
- "[coe=0|1] [gen=<n>]\n"
+ "[coe=0|1] [gen=<n>]\n"
" [time=0|1] [deb=<n>] [--version]\n"
" usually either 'if' or 'of' is a sg or raw device\n"
" 'bpt' is blocks_per_transfer (default is 128)\n"
" 'dio' is direct IO, 1->attempt, 0->indirect IO (def)\n"
" 'thr' is number of queues, must be > 0, default 4, max 32\n");
fprintf(stderr, " 'coe' continue on sg error, 0->exit (def), "
- "1->zero + continue\n"
- " 'time' 0->no timing(def), 1->time plus calculate throughput\n"
+ "1->zero + continue\n"
+ " 'time' 0->no timing(def), 1->time plus calculate throughput\n"
" 'gen' 0-> 1 file is special(def), 1-> any files allowed\n"
" 'deb' is debug, 0->none (def), > 0->varying degrees of debug\n");
}
@@ -237,40 +237,40 @@ int do_poll(Rq_coll * clp, int timeout, int * req_indexp)
int k, res;
if (FT_SG == clp->out_type) {
- while (((res = poll(out_pollfd_arr, clp->num_rq_elems, timeout)) < 0)
- && (EINTR == errno))
- ;
- if (res < 0) {
- perror("poll error on output fds");
- return -1;
- }
- else if (res > 0) {
- for (k = 0; k < clp->num_rq_elems; ++k) {
- if (out_pollfd_arr[k].revents & POLLIN) {
- if (req_indexp)
- *req_indexp = k;
- return QS_OUT_POLL;
- }
- }
- }
+ while (((res = poll(out_pollfd_arr, clp->num_rq_elems, timeout)) < 0)
+ && (EINTR == errno))
+ ;
+ if (res < 0) {
+ perror("poll error on output fds");
+ return -1;
+ }
+ else if (res > 0) {
+ for (k = 0; k < clp->num_rq_elems; ++k) {
+ if (out_pollfd_arr[k].revents & POLLIN) {
+ if (req_indexp)
+ *req_indexp = k;
+ return QS_OUT_POLL;
+ }
+ }
+ }
}
if (FT_SG == clp->in_type) {
- while (((res = poll(in_pollfd_arr, clp->num_rq_elems, timeout)) < 0)
- && (EINTR == errno))
- ;
- if (res < 0) {
- perror("poll error on input fds");
- return -1;
- }
- else if (res > 0) {
- for (k = 0; k < clp->num_rq_elems; ++k) {
- if (in_pollfd_arr[k].revents & POLLIN) {
- if (req_indexp)
- *req_indexp = k;
- return QS_IN_POLL;
- }
- }
- }
+ while (((res = poll(in_pollfd_arr, clp->num_rq_elems, timeout)) < 0)
+ && (EINTR == errno))
+ ;
+ if (res < 0) {
+ perror("poll error on input fds");
+ return -1;
+ }
+ else if (res > 0) {
+ for (k = 0; k < clp->num_rq_elems; ++k) {
+ if (in_pollfd_arr[k].revents & POLLIN) {
+ if (req_indexp)
+ *req_indexp = k;
+ return QS_IN_POLL;
+ }
+ }
+ }
}
return 0;
}
@@ -304,7 +304,7 @@ int read_capacity(int sg_fd, int * num_sect, int * sect_sz)
if (SG_LIB_CAT_MEDIA_CHANGED == res)
return 2; /* probably have another go ... */
else if (SG_LIB_CAT_CLEAN != res) {
- sg_chk_n_print3("read capacity", &io_hdr);
+ sg_chk_n_print3("read capacity", &io_hdr, 1);
return -1;
}
*num_sect = 1 + ((rcBuff[0] << 24) | (rcBuff[1] << 16) |
@@ -327,13 +327,13 @@ int normal_in_operation(Rq_coll * clp, Rq_elem * rep, int blocks)
rep->qstate = QS_IN_STARTED;
if (rep->debug > 8)
fprintf(stderr, "normal_in_operation: start blk=%d num_blks=%d\n",
- rep->blk, rep->num_blks);
+ rep->blk, rep->num_blks);
while (((res = read(rep->infd, rep->buffp,
blocks * rep->bs)) < 0) && (EINTR == errno))
;
if (res < 0) {
fprintf(stderr, "sgq_dd: reading, in_blk=%d, errno=%d\n", rep->blk,
- errno);
+ errno);
return -1;
}
if (res < blocks * rep->bs) {
@@ -364,13 +364,13 @@ int normal_out_operation(Rq_coll * clp, Rq_elem * rep, int blocks)
rep->qstate = QS_OUT_STARTED;
if (rep->debug > 8)
fprintf(stderr, "normal_out_operation: start blk=%d num_blks=%d\n",
- rep->blk, rep->num_blks);
+ rep->blk, rep->num_blks);
while (((res = write(rep->outfd, rep->buffp,
rep->num_blks * rep->bs)) < 0) && (EINTR == errno))
;
if (res < 0) {
fprintf(stderr, "sgq_dd: output, out_blk=%d, errno=%d\n", rep->blk,
- errno);
+ errno);
return -1;
}
if (res < blocks * rep->bs) {
@@ -394,23 +394,23 @@ int sg_fin_in_operation(Rq_coll * clp, Rq_elem * rep)
rep->qstate = QS_IN_FINISHED;
res = sg_finish_io(rep->wr, rep);
if (res < 0) {
- if (clp->coe) {
- memset(rep->buffp, 0, rep->num_blks * rep->bs);
- fprintf(stderr, ">> substituted zeros for in blk=%d for "
- "%d bytes\n", rep->blk, rep->num_blks * rep->bs);
- res = 0;
- }
- else {
- fprintf(stderr, "error finishing sg in command\n");
- return res;
- }
+ if (clp->coe) {
+ memset(rep->buffp, 0, rep->num_blks * rep->bs);
+ fprintf(stderr, ">> substituted zeros for in blk=%d for "
+ "%d bytes\n", rep->blk, rep->num_blks * rep->bs);
+ res = 0;
+ }
+ else {
+ fprintf(stderr, "error finishing sg in command\n");
+ return res;
+ }
}
if (0 == res) { /* looks good, going to return */
- if (rep->dio_incomplete || rep->resid) {
- clp->dio_incomplete += rep->dio_incomplete;
- clp->sum_of_resids += rep->resid;
- }
- clp->in_done_count -= rep->num_blks;
+ if (rep->dio_incomplete || rep->resid) {
+ clp->dio_incomplete += rep->dio_incomplete;
+ clp->sum_of_resids += rep->resid;
+ }
+ clp->in_done_count -= rep->num_blks;
}
return res;
}
@@ -423,22 +423,22 @@ int sg_fin_out_operation(Rq_coll * clp, Rq_elem * rep)
rep->qstate = QS_IDLE;
res = sg_finish_io(rep->wr, rep);
if (res < 0) {
- if (clp->coe) {
- fprintf(stderr, ">> ignored error for out blk=%d for "
- "%d bytes\n", rep->blk, rep->num_blks * rep->bs);
- res = 0;
- }
- else {
- fprintf(stderr, "error finishing sg out command\n");
- return res;
- }
+ if (clp->coe) {
+ fprintf(stderr, ">> ignored error for out blk=%d for "
+ "%d bytes\n", rep->blk, rep->num_blks * rep->bs);
+ res = 0;
+ }
+ else {
+ fprintf(stderr, "error finishing sg out command\n");
+ return res;
+ }
}
if (0 == res) {
- if (rep->dio_incomplete || rep->resid) {
- clp->dio_incomplete += rep->dio_incomplete;
- clp->sum_of_resids += rep->resid;
- }
- clp->out_done_count -= rep->num_blks;
+ if (rep->dio_incomplete || rep->resid) {
+ clp->dio_incomplete += rep->dio_incomplete;
+ clp->sum_of_resids += rep->resid;
+ }
+ clp->out_done_count -= rep->num_blks;
}
return res;
}
@@ -515,8 +515,8 @@ int sg_finish_io(int wr, Rq_elem * rep)
}
if (rep != (Rq_elem *)io_hdr.usr_ptr) {
fprintf(stderr,
- "sg_finish_io: bad usr_ptr, request-response mismatch\n");
- exit(1);
+ "sg_finish_io: bad usr_ptr, request-response mismatch\n");
+ exit(1);
}
memcpy(&rep->io_hdr, &io_hdr, sizeof(sg_io_hdr_t));
hp = &rep->io_hdr;
@@ -534,8 +534,8 @@ int sg_finish_io(int wr, Rq_elem * rep)
{
char ebuff[EBUFF_SZ];
snprintf(ebuff, EBUFF_SZ, "%s blk=%d",
- rep->wr ? "writing": "reading", rep->blk);
- sg_chk_n_print3(ebuff, hp);
+ rep->wr ? "writing": "reading", rep->blk);
+ sg_chk_n_print3(ebuff, hp, 1);
return -1;
}
}
@@ -550,7 +550,7 @@ int sg_finish_io(int wr, Rq_elem * rep)
rep->resid = hp->resid;
if (rep->debug > 8)
fprintf(stderr, "sg_finish_io: completed %s, blk=%d\n",
- wr ? "WRITE" : "READ", rep->blk);
+ wr ? "WRITE" : "READ", rep->blk);
return 0;
}
@@ -576,8 +576,8 @@ int sg_prepare(int fd, int sz)
#endif
res = ioctl(fd, SG_GET_SCSI_ID, &info);
if (res < 0) {
- perror("sgq_dd: SG_SET_SCSI_ID error");
- return -1;
+ perror("sgq_dd: SG_SET_SCSI_ID error");
+ return -1;
}
else
return info.scsi_type;
@@ -595,63 +595,63 @@ int prepare_rq_elems(Rq_coll * clp, const char * inf, const char * outf)
clp->req_arr = malloc(sizeof(Rq_elem) * clp->num_rq_elems);
if (NULL == clp->req_arr)
- return 1;
+ return 1;
for (k = 0; k < clp->num_rq_elems; ++k) {
- rep = &clp->req_arr[k];
- memset(rep, 0, sizeof(Rq_elem));
- psz = getpagesize();
- if (NULL == (rep->alloc_bp = malloc(sz + psz)))
- return 1;
- rep->buffp = (unsigned char *)
- (((unsigned long)rep->alloc_bp + psz - 1) & (~(psz - 1)));
- rep->qstate = QS_IDLE;
- rep->bs = clp->bs;
- rep->dio = clp->dio;
- rep->debug = clp->debug;
- rep->out_scsi_type = clp->out_scsi_type;
- if (FT_SG == clp->in_type) {
- if (0 == k)
- rep->infd = clp->infd;
- else {
- if ((rep->infd = open(inf, O_RDWR)) < 0) {
+ rep = &clp->req_arr[k];
+ memset(rep, 0, sizeof(Rq_elem));
+ psz = getpagesize();
+ if (NULL == (rep->alloc_bp = malloc(sz + psz)))
+ return 1;
+ rep->buffp = (unsigned char *)
+ (((unsigned long)rep->alloc_bp + psz - 1) & (~(psz - 1)));
+ rep->qstate = QS_IDLE;
+ rep->bs = clp->bs;
+ rep->dio = clp->dio;
+ rep->debug = clp->debug;
+ rep->out_scsi_type = clp->out_scsi_type;
+ if (FT_SG == clp->in_type) {
+ if (0 == k)
+ rep->infd = clp->infd;
+ else {
+ if ((rep->infd = open(inf, O_RDWR)) < 0) {
snprintf(ebuff, EBUFF_SZ,
- "sgq_dd: could not open %s for sg reading", inf);
+ "sgq_dd: could not open %s for sg reading", inf);
perror(ebuff);
return 1;
}
- }
- in_pollfd_arr[k].fd = rep->infd;
- in_pollfd_arr[k].events = POLLIN;
- if ((scsi_type = sg_prepare(rep->infd, sz)) < 0)
- return 1;
- if (0 == k)
- clp->in_scsi_type = scsi_type;
- rep->in_scsi_type = clp->in_scsi_type;
- }
- else
- rep->infd = clp->infd;
-
- if (FT_SG == clp->out_type) {
- if (0 == k)
- rep->outfd = clp->outfd;
- else {
- if ((rep->outfd = open(outf, O_RDWR)) < 0) {
+ }
+ in_pollfd_arr[k].fd = rep->infd;
+ in_pollfd_arr[k].events = POLLIN;
+ if ((scsi_type = sg_prepare(rep->infd, sz)) < 0)
+ return 1;
+ if (0 == k)
+ clp->in_scsi_type = scsi_type;
+ rep->in_scsi_type = clp->in_scsi_type;
+ }
+ else
+ rep->infd = clp->infd;
+
+ if (FT_SG == clp->out_type) {
+ if (0 == k)
+ rep->outfd = clp->outfd;
+ else {
+ if ((rep->outfd = open(outf, O_RDWR)) < 0) {
snprintf(ebuff, EBUFF_SZ,
- "sgq_dd: could not open %s for sg writing", outf);
+ "sgq_dd: could not open %s for sg writing", outf);
perror(ebuff);
return 1;
}
- }
- out_pollfd_arr[k].fd = rep->outfd;
- out_pollfd_arr[k].events = POLLIN;
- if ((scsi_type = sg_prepare(rep->outfd, sz)) < 0)
- return 1;
- if (0 == k)
- clp->out_scsi_type = scsi_type;
- rep->out_scsi_type = clp->out_scsi_type;
- }
- else
- rep->outfd = clp->outfd;
+ }
+ out_pollfd_arr[k].fd = rep->outfd;
+ out_pollfd_arr[k].events = POLLIN;
+ if ((scsi_type = sg_prepare(rep->outfd, sz)) < 0)
+ return 1;
+ if (0 == k)
+ clp->out_scsi_type = scsi_type;
+ rep->out_scsi_type = clp->out_scsi_type;
+ }
+ else
+ rep->outfd = clp->outfd;
}
return 0;
}
@@ -670,37 +670,37 @@ int decider(Rq_coll * clp, int first_xfer, int * req_indexp)
times = first_xfer ? 1 : clp->num_rq_elems;
for (k = 0; k < times; ++k) {
- rep = &clp->req_arr[k];
- if ((QS_IN_STARTED == rep->qstate) ||
- (QS_OUT_STARTED == rep->qstate))
- try_poll = 1;
- else if ((QS_IN_FINISHED == rep->qstate) && (rep->blk < lowest_blk)) {
- lowest_blk = rep->blk;
- lowest_blk_index = k;
- }
- else if ((QS_IDLE == rep->qstate) && (first_idle_index < 0))
- first_idle_index = k;
+ rep = &clp->req_arr[k];
+ if ((QS_IN_STARTED == rep->qstate) ||
+ (QS_OUT_STARTED == rep->qstate))
+ try_poll = 1;
+ else if ((QS_IN_FINISHED == rep->qstate) && (rep->blk < lowest_blk)) {
+ lowest_blk = rep->blk;
+ lowest_blk_index = k;
+ }
+ else if ((QS_IDLE == rep->qstate) && (first_idle_index < 0))
+ first_idle_index = k;
}
if (try_poll) {
- res = do_poll(clp, 0, req_indexp);
- if (0 != res)
- return res;
+ res = do_poll(clp, 0, req_indexp);
+ if (0 != res)
+ return res;
}
if (lowest_blk_index >= 0) {
- if (req_indexp)
- *req_indexp = lowest_blk_index;
- return QS_IN_FINISHED;
+ if (req_indexp)
+ *req_indexp = lowest_blk_index;
+ return QS_IN_FINISHED;
}
#if 0
if (try_poll) {
- res = do_poll(clp, 2, req_indexp);
- if (0 != res)
- return res;
+ res = do_poll(clp, 2, req_indexp);
+ if (0 != res)
+ return res;
}
#endif
if (req_indexp)
- *req_indexp = first_idle_index;
+ *req_indexp = first_idle_index;
return QS_IDLE;
}
@@ -780,7 +780,7 @@ int main(int argc, char * argv[])
do_time = sg_get_num(buf);
else if (0 == strncmp(key, "--vers", 6)) {
fprintf(stderr, "sgq_dd for sg version 3 driver: %s\n",
- version_str);
+ version_str);
return 0;
}
else {
@@ -819,12 +819,12 @@ int main(int argc, char * argv[])
rcoll.infd = STDIN_FILENO;
rcoll.outfd = STDOUT_FILENO;
if (inf[0] && ('-' != inf[0])) {
- rcoll.in_type = dd_filetype(inf);
+ rcoll.in_type = dd_filetype(inf);
if (FT_SG == rcoll.in_type) {
if ((rcoll.infd = open(inf, O_RDWR)) < 0) {
snprintf(ebuff, EBUFF_SZ,
- "sgq_dd: could not open %s for sg reading", inf);
+ "sgq_dd: could not open %s for sg reading", inf);
perror(ebuff);
return 1;
}
@@ -832,7 +832,7 @@ int main(int argc, char * argv[])
if (FT_SG != rcoll.in_type) {
if ((rcoll.infd = open(inf, O_RDONLY)) < 0) {
snprintf(ebuff, EBUFF_SZ,
- "sgq_dd: could not open %s for reading", inf);
+ "sgq_dd: could not open %s for reading", inf);
perror(ebuff);
return 1;
}
@@ -850,27 +850,27 @@ int main(int argc, char * argv[])
}
}
if (outf[0] && ('-' != outf[0])) {
- rcoll.out_type = dd_filetype(outf);
+ rcoll.out_type = dd_filetype(outf);
if (FT_SG == rcoll.out_type) {
- if ((rcoll.outfd = open(outf, O_RDWR)) < 0) {
+ if ((rcoll.outfd = open(outf, O_RDWR)) < 0) {
snprintf(ebuff, EBUFF_SZ,
- "sgq_dd: could not open %s for sg writing", outf);
+ "sgq_dd: could not open %s for sg writing", outf);
perror(ebuff);
return 1;
}
}
- else {
- if (FT_OTHER == rcoll.out_type) {
- if ((rcoll.outfd = open(outf, O_WRONLY | O_CREAT, 0666)) < 0) {
+ else {
+ if (FT_OTHER == rcoll.out_type) {
+ if ((rcoll.outfd = open(outf, O_WRONLY | O_CREAT, 0666)) < 0) {
snprintf(ebuff, EBUFF_SZ,
"sgq_dd: could not open %s for writing", outf);
perror(ebuff);
return 1;
}
- }
- else {
- if ((rcoll.outfd = open(outf, O_WRONLY)) < 0) {
+ }
+ else {
+ if ((rcoll.outfd = open(outf, O_WRONLY)) < 0) {
snprintf(ebuff, EBUFF_SZ,
"sgq_dd: could not open %s for raw writing", outf);
perror(ebuff);
@@ -881,14 +881,14 @@ int main(int argc, char * argv[])
llse_loff_t offset = seek;
offset *= rcoll.bs; /* could exceed 32 bits here! */
- if (llse_llseek(rcoll.outfd, offset, SEEK_SET) < 0) {
+ if (llse_llseek(rcoll.outfd, offset, SEEK_SET) < 0) {
snprintf(ebuff, EBUFF_SZ,
"sgq_dd: couldn't seek to required position on %s", outf);
perror(ebuff);
return 1;
}
}
- }
+ }
}
if ((STDIN_FILENO == rcoll.infd) && (STDOUT_FILENO == rcoll.outfd)) {
fprintf(stderr, "Disallow both if and of to be stdin and stdout");
@@ -959,12 +959,12 @@ int main(int argc, char * argv[])
rcoll.out_blk = seek;
if ((FT_SG == rcoll.in_type) || (FT_SG == rcoll.out_type))
- rcoll.num_rq_elems = num_threads;
+ rcoll.num_rq_elems = num_threads;
else
- rcoll.num_rq_elems = 1;
+ rcoll.num_rq_elems = 1;
if (prepare_rq_elems(&rcoll, inf, outf)) {
fprintf(stderr, "Setup failure, perhaps no memory\n");
- return 1;
+ return 1;
}
first_xfer = 1;
@@ -978,123 +978,123 @@ int main(int argc, char * argv[])
}
while (rcoll.out_done_count > 0) { /* >>>>>>>>> main loop */
req_index = -1;
- qstate = decider(&rcoll, first_xfer, &req_index);
- rep = (req_index < 0) ? NULL : (rcoll.req_arr + req_index);
- switch (qstate) {
- case QS_IDLE:
- if ((NULL == rep) || (rcoll.in_count <= 0)) {
- /* usleep(1000); */
- /* do_poll(&rcoll, 10, NULL); */
- /* do_poll(&rcoll, 0, NULL); */
- break;
- }
- if (rcoll.debug > 8)
- fprintf(stderr, " sgq_dd: non-sleeping QS_IDLE state, "
- "req_index=%d\n", req_index);
- if (first_xfer >= 2)
- first_xfer = 0;
- else if (1 == first_xfer)
- ++first_xfer;
- if (stop_after_write) {
- terminate = 1;
- break;
- }
- blocks = (rcoll.in_count > rcoll.bpt) ? rcoll.bpt : rcoll.in_count;
- rep->wr = 0;
- rep->blk = rcoll.in_blk;
- rep->num_blks = blocks;
- rcoll.in_blk += blocks;
- rcoll.in_count -= blocks;
-
- if (FT_SG == rcoll.in_type) {
- res = sg_start_io(rep);
- if (0 != res) {
- if (1 == res)
- fprintf(stderr, "Out of memory starting sg io\n");
- terminate = 1;
- }
- }
- else {
- res = normal_in_operation(&rcoll, rep, blocks);
- if (res < 0)
- terminate = 1;
- else if (res > 0)
- stop_after_write = 1;
- }
- break;
- case QS_IN_FINISHED:
- if (rcoll.debug > 8)
- fprintf(stderr, " sgq_dd: state is QS_IN_FINISHED, "
- "req_index=%d\n", req_index);
- if ((rep->blk + seek_skip) != rcoll.out_blk) {
- /* if write would be out of sequence then wait */
- if (rcoll.debug > 4)
- fprintf(stderr, " sgq_dd: QS_IN_FINISHED, "
- "out of sequence\n");
- usleep(200);
- break;
- }
+ qstate = decider(&rcoll, first_xfer, &req_index);
+ rep = (req_index < 0) ? NULL : (rcoll.req_arr + req_index);
+ switch (qstate) {
+ case QS_IDLE:
+ if ((NULL == rep) || (rcoll.in_count <= 0)) {
+ /* usleep(1000); */
+ /* do_poll(&rcoll, 10, NULL); */
+ /* do_poll(&rcoll, 0, NULL); */
+ break;
+ }
+ if (rcoll.debug > 8)
+ fprintf(stderr, " sgq_dd: non-sleeping QS_IDLE state, "
+ "req_index=%d\n", req_index);
+ if (first_xfer >= 2)
+ first_xfer = 0;
+ else if (1 == first_xfer)
+ ++first_xfer;
+ if (stop_after_write) {
+ terminate = 1;
+ break;
+ }
+ blocks = (rcoll.in_count > rcoll.bpt) ? rcoll.bpt : rcoll.in_count;
+ rep->wr = 0;
+ rep->blk = rcoll.in_blk;
+ rep->num_blks = blocks;
+ rcoll.in_blk += blocks;
+ rcoll.in_count -= blocks;
+
+ if (FT_SG == rcoll.in_type) {
+ res = sg_start_io(rep);
+ if (0 != res) {
+ if (1 == res)
+ fprintf(stderr, "Out of memory starting sg io\n");
+ terminate = 1;
+ }
+ }
+ else {
+ res = normal_in_operation(&rcoll, rep, blocks);
+ if (res < 0)
+ terminate = 1;
+ else if (res > 0)
+ stop_after_write = 1;
+ }
+ break;
+ case QS_IN_FINISHED:
+ if (rcoll.debug > 8)
+ fprintf(stderr, " sgq_dd: state is QS_IN_FINISHED, "
+ "req_index=%d\n", req_index);
+ if ((rep->blk + seek_skip) != rcoll.out_blk) {
+ /* if write would be out of sequence then wait */
+ if (rcoll.debug > 4)
+ fprintf(stderr, " sgq_dd: QS_IN_FINISHED, "
+ "out of sequence\n");
+ usleep(200);
+ break;
+ }
rep->wr = 1;
rep->blk = rcoll.out_blk;
- blocks = rep->num_blks;
+ blocks = rep->num_blks;
rcoll.out_blk += blocks;
rcoll.out_count -= blocks;
- if (FT_SG == rcoll.out_type) {
- res = sg_start_io(rep);
- if (0 != res) {
- if (1 == res)
- fprintf(stderr, "Out of memory starting sg io\n");
- terminate = 1;
- }
- }
- else {
- if (normal_out_operation(&rcoll, rep, blocks) < 0)
- terminate = 1;
- }
- break;
- case QS_IN_POLL:
- if (rcoll.debug > 8)
- fprintf(stderr, " sgq_dd: state is QS_IN_POLL, "
- "req_index=%d\n", req_index);
- res = sg_fin_in_operation(&rcoll, rep);
- if (res < 0)
- terminate = 1;
- else if (res > 1) {
- if (first_xfer) {
- /* only retry on first xfer */
- if (0 != sg_start_io(rep))
- terminate = 1;
- }
- else
- terminate = 1;
- }
- break;
- case QS_OUT_POLL:
- if (rcoll.debug > 8)
- fprintf(stderr, " sgq_dd: state is QS_OUT_POLL, "
- "req_index=%d\n", req_index);
- res = sg_fin_out_operation(&rcoll, rep);
- if (res < 0)
- terminate = 1;
- else if (res > 1) {
- if (first_xfer) {
- /* only retry on first xfer */
- if (0 != sg_start_io(rep))
- terminate = 1;
- }
- else
- terminate = 1;
- }
- break;
- default:
- if (rcoll.debug > 8)
- fprintf(stderr, " sgq_dd: state is ?????\n");
- terminate = 1;
- break;
- }
- if (terminate)
- break;
+ if (FT_SG == rcoll.out_type) {
+ res = sg_start_io(rep);
+ if (0 != res) {
+ if (1 == res)
+ fprintf(stderr, "Out of memory starting sg io\n");
+ terminate = 1;
+ }
+ }
+ else {
+ if (normal_out_operation(&rcoll, rep, blocks) < 0)
+ terminate = 1;
+ }
+ break;
+ case QS_IN_POLL:
+ if (rcoll.debug > 8)
+ fprintf(stderr, " sgq_dd: state is QS_IN_POLL, "
+ "req_index=%d\n", req_index);
+ res = sg_fin_in_operation(&rcoll, rep);
+ if (res < 0)
+ terminate = 1;
+ else if (res > 1) {
+ if (first_xfer) {
+ /* only retry on first xfer */
+ if (0 != sg_start_io(rep))
+ terminate = 1;
+ }
+ else
+ terminate = 1;
+ }
+ break;
+ case QS_OUT_POLL:
+ if (rcoll.debug > 8)
+ fprintf(stderr, " sgq_dd: state is QS_OUT_POLL, "
+ "req_index=%d\n", req_index);
+ res = sg_fin_out_operation(&rcoll, rep);
+ if (res < 0)
+ terminate = 1;
+ else if (res > 1) {
+ if (first_xfer) {
+ /* only retry on first xfer */
+ if (0 != sg_start_io(rep))
+ terminate = 1;
+ }
+ else
+ terminate = 1;
+ }
+ break;
+ default:
+ if (rcoll.debug > 8)
+ fprintf(stderr, " sgq_dd: state is ?????\n");
+ terminate = 1;
+ break;
+ }
+ if (terminate)
+ break;
} /* >>>>>>>>>>>>> end of main loop */
if ((do_time) && (start_tm.tv_sec || start_tm.tv_usec)) {
@@ -1126,7 +1126,7 @@ int main(int argc, char * argv[])
res = 0;
if (0 != rcoll.out_count) {
fprintf(stderr, ">>>> Some error occurred,\n");
- res = 2;
+ res = 2;
}
print_stats();
if (rcoll.dio_incomplete) {
diff --git a/debian/changelog b/debian/changelog
new file mode 100644
index 00000000..677cf259
--- /dev/null
+++ b/debian/changelog
@@ -0,0 +1,61 @@
+sg3-utils (1.16-0.1) unstable; urgency=low
+
+ * New upstream version
+
+ -- Doug Gilbert <dgilbert@interlog.com> Wed, 10 Aug 2005 14:20:00 +1000
+
+sg3-utils (1.15-0.1) unstable; urgency=low
+
+ * New upstream version
+
+ -- Martin Schwenke <martin@meltin.net> Tue, 7 Jun 2005 13:22:44 +1000
+
+sg3-utils (1.08-1) unstable; urgency=low
+
+ * New upstream version
+ * Unified package description with list of tools actually installed
+ (closes: #271093)
+
+ -- Eric Schwartz (Skif) <emschwar@debian.org> Sun, 12 Sep 2004 21:22:42 -0600
+
+sg3-utils (1.05-1) unstable; urgency=low
+
+ * New upstream release
+ * updated description to match tools in package (closes: #221143)
+
+ -- Eric Schwartz <emschwar@debian.org> Tue, 18 Nov 2003 22:22:29 -0700
+
+sg3-utils (1.03-1) unstable; urgency=low
+
+ * New upstream release (closes: #181999)
+
+ -- Eric Schwartz <emschwar@debian.org> Tue, 29 Apr 2003 20:18:30 -0600
+
+sg3-utils (0.95-4) unstable; urgency=low
+
+ * Only warns if installed on a kernel version < 2.4 (closes: #136434)
+
+ -- Eric Schwartz <emschwar@debian.org> Tue, 28 May 2002 22:55:29 -0600
+
+sg3-utils (0.95-3) unstable; urgency=low
+
+ * Extended description to include descriptions of all tools included in
+ the package. (closes: #121968)
+
+ -- Eric Schwartz <emschwar@debian.org> Sun, 13 Jan 2002 17:09:27 -0700
+
+sg3-utils (0.95-2) unstable; urgency=low
+
+ * Packaging manpages (closes: #122692)
+ * Conflicts with cdwrite (closes: #123779)
+
+ -- Eric Schwartz <emschwar@debian.org> Wed, 2 Jan 2002 01:05:08 -0700
+
+sg3-utils (0.95-1) unstable; urgency=low
+
+ * Initial Release.
+ * Adjusted Makefile to include $DESTDIR
+
+ -- Eric Schwartz <emschwar@debian.org> Wed, 14 Nov 2001 17:05:56 -0700
+
+
diff --git a/debian/control b/debian/control
new file mode 100644
index 00000000..5f901398
--- /dev/null
+++ b/debian/control
@@ -0,0 +1,74 @@
+Source: sg3-utils
+Section: admin
+Priority: optional
+Maintainer: Eric Schwartz (Skif) <emschwar@debian.org>
+Build-Depends: debhelper (>> 4.0.0)
+Standards-Version: 3.6.1
+
+Package: sg3-utils
+Architecture: any
+Depends: ${shlibs:Depends}, libsgutils1-0
+Conflicts: sg-utils, cdwrite
+Replaces: sg-utils
+Description: Collection of Linux utilities for devices that use the
+ SCSI command set. See the README, CHANGELOG and COVERAGE files.
+ .
+ Requires the linux kernel 2.4 series or later. In the 2.4 series
+ SCSI generic device names (e.g. /dev/sg0) must be used. In the 2.6
+ series other device names may be used as well (e.g. /dev/sda).
+ .
+ The package includes:
+ * sg_dd - a variant of 'dd' that works at the SCSI command level
+ * sg_emc_trespass - vendor specific for Clariion hardware
+ * sg_format - format SCSI disks
+ * sg_get_config - get features and profiles of MMC devices
+ * sginfo - a re-porting of the 'scsiinfo' program, updated
+ * sg_inq - a utility for poking around with the SCSI INQUIRY command
+ * sg_logs - prints out log sense pages
+ * sg_luns - prints out REPORT LUNS response
+ * sg_map - shows the mapping between SCSI devices and sg devices
+ * sgm_dd - like sg_dd, but uses mmap()'d IO
+ * sg_modes - prints out mode sense pages
+ * sg_opcodes - reports supported opcodes and task management fcns
+ * sgp_dd - like sg_dd, only multithreaded
+ * sg_persist - accesses the Persistent Reservation In and Out commands
+ * sg_prevent - issues PREVENT ALLOW MEDIUM REMOVAL command (MMC + SSC)
+ * sg_rbuf - tests SCSI bus speed
+ * sg_read - reads multiple blocks, useful for timing
+ * sg_read_long - read a "long" block from the given device
+ * sg_readcap - prints the output of a READ CAPACITY command
+ * sg_reassign - issues a REASSIGN BLOCKS command (map out bad sectors)
+ * sg_requests - issues a REQUEST SENSE command (event polling)
+ * sg_reset - exercises SCSI device/bus/host reset capability
+ * sg_rmsn - READ SERIAL SERIAL NUMBER
+ * sg_rtpg - REPORT TARGET PORT GROUPS
+ * sg_scan - displays the SCSI bus on stdout
+ * sg_senddiag - runs SCSI self tests
+ * sg_ses - fetches status and send control to a SES device
+ * sg_start - spins up (or down) disks and cd/dvds
+ * sg_sync - issues a SYNCHRONIZE CACHE command
+ * sg_test_rwbuf - tests the SCSI host adapter
+ * sg_turs - execute a TEST UNIT READY command on the given device
+ * sg_verify - issues VERIFY command on SCSI disks
+ * sg_write_long - write a "long" block to the given device
+ * sg_wr_mode - low level utility to change mode pages
+ .
+ It also includes source code for some example programs that demonstrate
+ how to use the scsi generic driver.
+
+Package: libsgutils1-0
+Section: libraries
+Architecture: any
+Recommends: sg3-utils
+Description: Utilities for working with generic SCSI devices (shared libraries)
+ This package contains the shared libraries.
+
+Package: libsgutils1-0-dev
+Section: devel
+Architecture: any
+Depends: libsgutils1-0
+Recommends: sg3-utils
+Description: Utilities for working with generic SCSI devices (developer files)
+ This package contains the <scsi/sg_cmds.h> and <scsi/sg_lib.h> header
+ files, the /usr/lib/libsgutils.a static library and other assorted
+ development tidbits.
diff --git a/debian/copyright b/debian/copyright
new file mode 100644
index 00000000..3f924ace
--- /dev/null
+++ b/debian/copyright
@@ -0,0 +1,15 @@
+This package was debianized by Eric Schwartz <emschwar@debian.org> on
+Wed, 14 Nov 2001 17:05:56 -0700.
+
+It was downloaded from <URL:http://www.torque.net/sg/>
+
+Upstream Authors: Andries Brouwer, Remy Card, Douglas Gilbert <dgilbert@interlog.com>, P. Allworth, Eric Youngdale, Kurt Garloff <garloff@suse.de>, Michael Weller <eowmob@exp-math.uni-essen.de>
+
+Copyright:
+
+This software is copyright(c) 1994-2001 by the authors
+
+You are free to distribute this software under the terms of
+the GNU General Public License.
+On Debian systems, the complete text of the GNU General Public
+License can be found in /usr/share/common-licenses/GPL file. \ No newline at end of file
diff --git a/debian/docs b/debian/docs
new file mode 100644
index 00000000..f458d89e
--- /dev/null
+++ b/debian/docs
@@ -0,0 +1,4 @@
+README
+README.sg_start
+CREDITS
+COVERAGE
diff --git a/debian/libsgutils1-0-dev.dirs b/debian/libsgutils1-0-dev.dirs
new file mode 100644
index 00000000..c4e5a977
--- /dev/null
+++ b/debian/libsgutils1-0-dev.dirs
@@ -0,0 +1,2 @@
+usr/lib
+usr/include/scsi
diff --git a/debian/libsgutils1-0-dev.install b/debian/libsgutils1-0-dev.install
new file mode 100644
index 00000000..b2320a06
--- /dev/null
+++ b/debian/libsgutils1-0-dev.install
@@ -0,0 +1,5 @@
+usr/include/scsi
+usr/lib/*.so
+usr/lib/*.lo
+usr/lib/*.la
+usr/lib/*.a
diff --git a/debian/libsgutils1-0.dirs b/debian/libsgutils1-0.dirs
new file mode 100644
index 00000000..68457717
--- /dev/null
+++ b/debian/libsgutils1-0.dirs
@@ -0,0 +1 @@
+usr/lib
diff --git a/debian/libsgutils1-0.install b/debian/libsgutils1-0.install
new file mode 100644
index 00000000..093956b1
--- /dev/null
+++ b/debian/libsgutils1-0.install
@@ -0,0 +1 @@
+usr/lib/*.so.*
diff --git a/debian/rules b/debian/rules
new file mode 100644
index 00000000..52d66a97
--- /dev/null
+++ b/debian/rules
@@ -0,0 +1,77 @@
+#!/usr/bin/make -f
+# Sample debian/rules that uses debhelper.
+# GNU copyright 1997 by Joey Hess.
+#
+# This version is for a hypothetical package that builds an
+# architecture-dependant package, as well as an architecture-independent
+# package.
+
+# Uncomment this to turn on verbose mode.
+#export DH_VERBOSE=1
+
+# This is the debhelper compatability version to use.
+export DH_COMPAT=4
+
+configure: configure-stamp
+configure-stamp:
+ dh_testdir
+ # Add here commands to configure the package.
+ touch configure-stamp
+
+build: configure-stamp build-stamp
+build-stamp:
+ dh_testdir
+
+ # Add here commands to compile the package.
+ PREFIX=/usr MANDIR=/usr/share/man $(MAKE) -e
+
+ touch build-stamp
+
+clean:
+ dh_testdir
+ dh_testroot
+ rm -f build-stamp configure-stamp
+
+ # Add here commands to clean up after the build process.
+ -$(MAKE) clean
+
+ dh_clean
+
+install: DH_OPTIONS=
+install: build
+ dh_testdir
+ dh_testroot
+ dh_clean -k
+ dh_installdirs
+
+ # Add here commands to install the package into debian/tmp
+ $(MAKE) -e install DESTDIR=$(CURDIR)/debian/tmp PREFIX=/usr
+
+ dh_install --autodest --sourcedir=debian/tmp
+ dh_installman
+
+# Build architecture-independent files here.
+# Pass -i to all debhelper commands in this target to reduce clutter.
+binary-indep: build install
+# nothing to do here
+
+# Build architecture-dependent files here.
+binary-arch: build install
+ dh_testdir -a
+ dh_testroot -a
+ dh_installdocs -a
+ dh_installexamples -a
+ dh_installmenu -a
+ dh_installchangelogs CHANGELOG -a
+ dh_strip -a
+ dh_link -a
+ dh_compress -a -X archive -X .c -X .h
+ dh_fixperms -a
+ dh_installdeb -a
+ dh_shlibdeps -a
+ dh_gencontrol -a
+ dh_md5sums -a
+ dh_builddeb -a
+
+binary: binary-indep binary-arch
+.PHONY: build clean binary-indep binary-arch binary install configure
diff --git a/debian/sg3-utils.dirs b/debian/sg3-utils.dirs
new file mode 100644
index 00000000..e7724817
--- /dev/null
+++ b/debian/sg3-utils.dirs
@@ -0,0 +1 @@
+usr/bin
diff --git a/debian/sg3-utils.examples b/debian/sg3-utils.examples
new file mode 100644
index 00000000..a9da2053
--- /dev/null
+++ b/debian/sg3-utils.examples
@@ -0,0 +1,2 @@
+examples/*
+archive
diff --git a/debian/sg3-utils.install b/debian/sg3-utils.install
new file mode 100644
index 00000000..6161376a
--- /dev/null
+++ b/debian/sg3-utils.install
@@ -0,0 +1,2 @@
+usr/bin/*
+usr/share/man/man8/*
diff --git a/debian/sg3-utils.preinst b/debian/sg3-utils.preinst
new file mode 100644
index 00000000..6582964e
--- /dev/null
+++ b/debian/sg3-utils.preinst
@@ -0,0 +1,48 @@
+#! /bin/sh
+# preinst script for sg-utils
+#
+# see: dh_installdeb(1)
+
+set -e
+
+# summary of how this script can be called:
+# * <new-preinst> `install'
+# * <new-preinst> `install' <old-version>
+# * <new-preinst> `upgrade' <old-version>
+# * <old-preinst> `abort-upgrade' <new-version>
+#
+# For details see /usr/share/doc/packaging-manual/
+
+case "$1" in
+ install|upgrade)
+ kernel_version=`/bin/uname -r`;
+ major_version=`echo $kernel_version | sed 's/\.[0-9]\+$//'`;
+ minor_version=`echo $kernel_version | sed 's/.*\.\([0-9]\+\)/\1/'`;
+
+ case $major_version in
+ 2.[0-3])
+ echo "You are running linux kernel version $kernel_version."
+ echo "sg3_utils will not work on kernels older than 2.4."
+ echo "If you want to run code with older kernels, please"
+ echo "install sg_utils instead."
+ exit 0;
+ ;;
+ *)
+ esac
+ ;;
+
+ abort-upgrade)
+ ;;
+
+ *)
+ echo "preinst called with unknown argument \`$1'" >&2
+ exit 0
+ ;;
+esac
+
+# dh_installdeb will replace this with shell code automatically
+# generated by other debhelper scripts.
+
+#DEBHELPER#
+
+exit 0
diff --git a/examples/sg_excl.c b/examples/sg_excl.c
index 6199576c..f9c3e175 100644
--- a/examples/sg_excl.c
+++ b/examples/sg_excl.c
@@ -91,12 +91,12 @@ int main(int argc, char * argv[])
#if 0
if ((sg_fd2 = open(file_name, O_RDWR | O_EXCL)) < 0) {
snprintf(ebuff, EBUFF_SZ,
- ME "error opening file: %s a second time", file_name);
+ ME "error opening file: %s a second time", file_name);
perror(ebuff);
return 1;
} else {
- printf(ME "second open of %s in violation of O_EXCL\n", file_name);
- close(sg_fd2);
+ printf(ME "second open of %s in violation of O_EXCL\n", file_name);
+ close(sg_fd2);
}
#endif
@@ -133,7 +133,7 @@ int main(int argc, char * argv[])
ok = 1;
break;
default: /* won't bother decoding other categories */
- sg_chk_n_print3("INQUIRY command error", &io_hdr);
+ sg_chk_n_print3("INQUIRY command error", &io_hdr, 1);
break;
}
@@ -178,7 +178,7 @@ int main(int argc, char * argv[])
ok = 1;
break;
default: /* won't bother decoding other categories */
- sg_chk_n_print3("Test Unit Ready command error", &io_hdr);
+ sg_chk_n_print3("Test Unit Ready command error", &io_hdr, 1);
break;
}
diff --git a/examples/sg_iovec_tst.c b/examples/sg_iovec_tst.c
index ee1c9eb3..dd4c52f7 100644
--- a/examples/sg_iovec_tst.c
+++ b/examples/sg_iovec_tst.c
@@ -34,7 +34,7 @@
#define IOVEC_ELEMS 2048
#define SENSE_BUFF_LEN 32
-#define DEF_TIMEOUT 40000 /* 40,000 milliseconds */
+#define DEF_TIMEOUT 40000 /* 40,000 milliseconds */
struct sg_iovec iovec[IOVEC_ELEMS];
@@ -57,15 +57,15 @@ int sg_read(int sg_fd, unsigned char * buff, int num_blocks, int from_block,
for (k = 0, pos = 0, rem = dxfer_len; k < IOVEC_ELEMS; ++k) {
iovec[k].iov_base = buff + pos;
- iovec[k].iov_len = (rem > A_PRIME) ? A_PRIME : rem;
- if (rem <= A_PRIME)
- break;
+ iovec[k].iov_len = (rem > A_PRIME) ? A_PRIME : rem;
+ if (rem <= A_PRIME)
+ break;
pos += A_PRIME;
rem -= A_PRIME;
}
if (k >= IOVEC_ELEMS) {
fprintf(stderr, "Can't fit dxfer_len=%d bytes in iovec\n", dxfer_len);
- return -1;
+ return -1;
}
memset(&io_hdr, 0, sizeof(sg_io_hdr_t));
io_hdr.interface_id = 'S';
@@ -95,7 +95,7 @@ int sg_read(int sg_fd, unsigned char * buff, int num_blocks, int from_block,
fprintf(stderr, "Media changed\n");
return -1;
default:
- sg_chk_n_print3("reading", &io_hdr);
+ sg_chk_n_print3("reading", &io_hdr, 1);
return -1;
}
return 0;
@@ -146,7 +146,7 @@ int main(int argc, char * argv[])
}
if ((NULL == sg_file_name) || (NULL == out_file_name) || (0 == count)) {
printf("Usage: sg_iovec_tst [-h] [-b=num] -c=num <generic_device> "
- "<output_filename>\n");
+ "<output_filename>\n");
printf(" where: -h this usage message\n");
printf(" -b=num block size (default 512 Bytes)\n");
printf(" -c=num count of blocks to transfer\n");
@@ -174,10 +174,10 @@ int main(int argc, char * argv[])
buffp = malloc(dxfer_len);
if (buffp) {
if (0 == sg_read(sg_fd, buffp, count, 0, blk_size)) {
- if (write(fd, buffp, dxfer_len) < 0)
- perror(ME "output write failed");
+ if (write(fd, buffp, dxfer_len) < 0)
+ perror(ME "output write failed");
}
- free(buffp);
+ free(buffp);
}
res = close(fd);
if (res < 0) {
diff --git a/examples/sg_sense_test.c b/examples/sg_sense_test.c
index 81d634ce..2ecdc447 100644
--- a/examples/sg_sense_test.c
+++ b/examples/sg_sense_test.c
@@ -50,10 +50,10 @@ int main(int argc, char * argv[])
0x33, 0x44, 0xa,
0x0, 0x0, 0, 0, 0x4, 0x1, 0, 0xcf, 0, 5,};
- sg_print_sense("err1 test", err1, sizeof(err1));
- sg_print_sense("\nerr2 test", err2, sizeof(err2));
- sg_print_sense("\nerr3 test", err3, sizeof(err3));
- sg_print_sense("\nerr4 test", err4, sizeof(err4));
- sg_print_sense("\nerr5 test", err5, sizeof(err5));
+ sg_print_sense("err1 test", err1, sizeof(err1), 1);
+ sg_print_sense("\nerr2 test", err2, sizeof(err2), 1);
+ sg_print_sense("\nerr3 test", err3, sizeof(err3), 1);
+ sg_print_sense("\nerr4 test", err4, sizeof(err4), 1);
+ sg_print_sense("\nerr5 test", err5, sizeof(err5), 1);
return 0;
}
diff --git a/examples/sg_simple1.c b/examples/sg_simple1.c
index 374d44b7..623f944f 100644
--- a/examples/sg_simple1.c
+++ b/examples/sg_simple1.c
@@ -78,7 +78,7 @@ int main(int argc, char * argv[])
/* N.B. An access mode of O_RDWR is required for some SCSI commands */
if ((sg_fd = open(file_name, O_RDONLY)) < 0) {
snprintf(ebuff, EBUFF_SZ,
- "sg_simple1: error opening file: %s", file_name);
+ "sg_simple1: error opening file: %s", file_name);
perror(ebuff);
return 1;
}
@@ -123,7 +123,7 @@ int main(int argc, char * argv[])
ok = 1;
break;
default: /* won't bother decoding other categories */
- sg_chk_n_print3("INQUIRY command error", &io_hdr);
+ sg_chk_n_print3("INQUIRY command error", &io_hdr, 1);
break;
}
@@ -168,7 +168,7 @@ int main(int argc, char * argv[])
ok = 1;
break;
default: /* won't bother decoding other categories */
- sg_chk_n_print3("Test Unit Ready command error", &io_hdr);
+ sg_chk_n_print3("Test Unit Ready command error", &io_hdr, 1);
break;
}
diff --git a/examples/sg_simple16.c b/examples/sg_simple16.c
index 314be0fc..12e40609 100644
--- a/examples/sg_simple16.c
+++ b/examples/sg_simple16.c
@@ -34,7 +34,7 @@ int main(int argc, char * argv[])
{
int sg_fd, k, ok;
unsigned char r16CmdBlk [READ16_CMD_LEN] =
- {0x88, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0};
+ {0x88, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0};
sg_io_hdr_t io_hdr;
char * file_name = 0;
char ebuff[EBUFF_SZ];
@@ -62,7 +62,7 @@ int main(int argc, char * argv[])
if ((sg_fd = open(file_name, O_RDWR)) < 0) {
snprintf(ebuff, EBUFF_SZ,
- "sg_simple16: error opening file: %s", file_name);
+ "sg_simple16: error opening file: %s", file_name);
perror(ebuff);
return 1;
}
@@ -107,13 +107,13 @@ int main(int argc, char * argv[])
ok = 1;
break;
default: /* won't bother decoding other categories */
- sg_chk_n_print3("READ_16 command error", &io_hdr);
+ sg_chk_n_print3("READ_16 command error", &io_hdr, 1);
break;
}
if (ok) { /* output result if it is available */
- printf("READ_16 duration=%u millisecs, resid=%d, msg_status=%d\n",
- io_hdr.duration, io_hdr.resid, (int)io_hdr.msg_status);
+ printf("READ_16 duration=%u millisecs, resid=%d, msg_status=%d\n",
+ io_hdr.duration, io_hdr.resid, (int)io_hdr.msg_status);
}
close(sg_fd);
diff --git a/examples/sg_simple3.c b/examples/sg_simple3.c
index 9c154e51..ead162de 100644
--- a/examples/sg_simple3.c
+++ b/examples/sg_simple3.c
@@ -87,7 +87,7 @@ int main(int argc, char * argv[])
/* N.B. An access mode of O_RDWR is required for some SCSI commands */
if ((sg_fd = open(file_name, O_RDONLY)) < 0) {
snprintf(ebuff, EBUFF_SZ,
- "sg_simple3: error opening file: %s", file_name);
+ "sg_simple3: error opening file: %s", file_name);
perror(ebuff);
return 1;
}
@@ -141,7 +141,7 @@ int main(int argc, char * argv[])
ok = 1;
break;
default: /* won't bother decoding other categories */
- sg_chk_n_print3("INQUIRY command error", &io_hdr);
+ sg_chk_n_print3("INQUIRY command error", &io_hdr, 1);
break;
}
@@ -186,7 +186,7 @@ int main(int argc, char * argv[])
ok = 1;
break;
default: /* won't bother decoding other categories */
- sg_chk_n_print3("Test Unit Ready command error", &io_hdr);
+ sg_chk_n_print3("Test Unit Ready command error", &io_hdr, 1);
break;
}
diff --git a/examples/sg_simple4.c b/examples/sg_simple4.c
index 0ba953c6..64c8f31f 100644
--- a/examples/sg_simple4.c
+++ b/examples/sg_simple4.c
@@ -36,7 +36,7 @@
#ifndef SG_FLAG_MMAP_IO
#define SG_FLAG_MMAP_IO 4
-#endif /* since /usr/include/scsi/sg.h doesn't know about this yet */
+#endif /* since /usr/include/scsi/sg.h doesn't know about this yet */
#define INQ_REPLY_LEN 96
#define INQ_CMD_LEN 6
@@ -83,7 +83,7 @@ int main(int argc, char * argv[])
/* N.B. An access mode of O_RDWR is required for some SCSI commands */
if ((sg_fd = open(file_name, O_RDWR)) < 0) {
snprintf(ebuff, EBUFF_SZ,
- "sg_simple4: error opening file: %s", file_name);
+ "sg_simple4: error opening file: %s", file_name);
perror(ebuff);
return 1;
}
@@ -100,14 +100,14 @@ int main(int argc, char * argv[])
inqBuff = mmap(NULL, 8000, PROT_READ | PROT_WRITE, MAP_SHARED, sg_fd, 0);
if (MAP_FAILED == inqBuff) {
snprintf(ebuff, EBUFF_SZ, "sg_simple4: error using mmap() on "
- "file: %s", file_name);
+ "file: %s", file_name);
perror(ebuff);
return 1;
}
if (inqBuff[0])
- printf("non-null char at inqBuff[0]\n");
+ printf("non-null char at inqBuff[0]\n");
if (inqBuff[5000])
- printf("non-null char at inqBuff[5000]\n");
+ printf("non-null char at inqBuff[5000]\n");
/* Prepare INQUIRY command */
memset(&io_hdr, 0, sizeof(sg_io_hdr_t));
@@ -142,7 +142,7 @@ int main(int argc, char * argv[])
ok = 1;
break;
default: /* won't bother decoding other categories */
- sg_chk_n_print3("INQUIRY command error", &io_hdr);
+ sg_chk_n_print3("INQUIRY command error", &io_hdr, 1);
break;
}
@@ -187,7 +187,7 @@ int main(int argc, char * argv[])
ok = 1;
break;
default: /* won't bother decoding other categories */
- sg_chk_n_print3("Test Unit Ready command error", &io_hdr);
+ sg_chk_n_print3("Test Unit Ready command error", &io_hdr, 1);
break;
}
@@ -198,7 +198,7 @@ int main(int argc, char * argv[])
if (do_extra)
printf("TEST UNIT READY duration=%u millisecs, resid=%d, "
- "msg_status=%d\n",
+ "msg_status=%d\n",
io_hdr.duration, io_hdr.resid, (int)io_hdr.msg_status);
/* munmap(inqBuff, 8000); */
@@ -208,27 +208,27 @@ int main(int argc, char * argv[])
inqBuff2 = mmap(NULL, 8000, PROT_READ | PROT_WRITE, MAP_SHARED, sg_fd, 0);
if (MAP_FAILED == inqBuff2) {
snprintf(ebuff, EBUFF_SZ, "sg_simple4: error using mmap() 2 on "
- "file: %s", file_name);
+ "file: %s", file_name);
perror(ebuff);
return 1;
}
if (inqBuff2[0])
- printf("non-null char at inqBuff2[0]\n");
+ printf("non-null char at inqBuff2[0]\n");
if (inqBuff2[5000])
- printf("non-null char at inqBuff2[5000]\n");
+ printf("non-null char at inqBuff2[5000]\n");
{
- pid_t pid;
- pid = fork();
- if (pid) {
- inqBuff2[5000] = 33;
- munmap(inqBuff, 8000);
- sleep(3);
- }
- else {
- inqBuff[5000] = 0xaa;
- munmap(inqBuff, 8000);
- sleep(1);
- }
+ pid_t pid;
+ pid = fork();
+ if (pid) {
+ inqBuff2[5000] = 33;
+ munmap(inqBuff, 8000);
+ sleep(3);
+ }
+ else {
+ inqBuff[5000] = 0xaa;
+ munmap(inqBuff, 8000);
+ sleep(1);
+ }
}
#endif
close(sg_fd);
diff --git a/html/sg_dd.html b/html/sg_dd.html
index 8977c220..93a2cac8 100644
--- a/html/sg_dd.html
+++ b/html/sg_dd.html
@@ -57,9 +57,9 @@ transport is ATAPI (i.e. the ATA packet interface) is irrelevant, to
the
sg_dd utility they are SCSI devices.<br>
<br>
-This page outlines the features of the sg_dd utility version 5.41 found
-in the <a href="u_index.html">sg3_utils</a> version 1.15 package. This
-was released on the 5th June 2005.<br>
+This page outlines the features of the sg_dd utility version 5.42 found
+in the <a href="u_index.html">sg3_utils</a> version 1.16 package. This
+was released on the 9th August 2005.<br>
<h2><a name="dd_like_features"></a> dd like features</h2>
The basic syntax of the sg_dd utility is the same as the dd command in
Unix. That said, the syntax of the dd command in Unix is different from
@@ -276,10 +276,11 @@ commands (SG_IO ioctl)<br>
<tr>
<td style="vertical-align: top;">bpt<br>
</td>
- <td style="vertical-align: top;">128<br>
+ <td style="vertical-align: top;">128 or 32<br>
</td>
<td style="vertical-align: top;">blocks_per_transfer (granularity
-of each IO). Default may be too large for cd/dvd drives<br>
+of each IO). Default is 128 when bs &lt; 2048 (bytes) else the default
+is 32<br>
</td>
</tr>
<tr>
@@ -388,8 +389,6 @@ method</span><br>
</td>
<td style="vertical-align: top;"><span style="font-weight: bold;">Notes</span><br>
</td>
- <td style="vertical-align: top;"><br>
- </td>
</tr>
<tr>
<td style="vertical-align: top;">normal<br>
@@ -405,8 +404,6 @@ method</span><br>
<td style="vertical-align: top;">Add O_DIRECT if<br>
'odir=1'<br>
</td>
- <td style="vertical-align: top;"><br>
- </td>
</tr>
<tr>
<td style="vertical-align: top;">stdin or stdout<br>
@@ -419,8 +416,6 @@ method</span><br>
</td>
<td style="vertical-align: top;"><br>
</td>
- <td style="vertical-align: top;"><br>
- </td>
</tr>
<tr>
<td style="vertical-align: top;">/dev/null<br>
@@ -432,8 +427,6 @@ method</span><br>
</td>
<td style="vertical-align: top;">if output then no IO<br>
</td>
- <td style="vertical-align: top;"><br>
- </td>
</tr>
<tr>
<td style="vertical-align: top;">block device<br>
@@ -444,8 +437,6 @@ method</span><br>
<td style="vertical-align: top;">Unix read() write()</td>
<td style="vertical-align: top;">Add O_DIRECT if<br>
'odir=1'</td>
- <td style="vertical-align: top;"><br>
- </td>
</tr>
<tr>
<td style="vertical-align: top;">block device [blk_sgio=1]<br>
@@ -456,8 +447,6 @@ method</span><br>
<td style="vertical-align: top;">Opens input O_RDONLY <br>
if O_RDWR fails. Adds <br>
O_DIRECT if 'odir=1' </td>
- <td style="vertical-align: top;"><br>
- </td>
</tr>
<tr>
<td style="vertical-align: top;">sg device<br>
@@ -470,8 +459,6 @@ O_DIRECT if 'odir=1' </td>
</td>
<td style="vertical-align: top;">Opens input O_RDONLY<br>
if O_RDWR fails</td>
- <td style="vertical-align: top;"><br>
- </td>
</tr>
<tr>
<td style="vertical-align: top;">raw device<br>
@@ -483,8 +470,6 @@ if O_RDWR fails</td>
</td>
<td style="vertical-align: top;"><br>
</td>
- <td style="vertical-align: top;"><br>
- </td>
</tr>
<tr>
<td style="vertical-align: top;">scsi tape device<br>
@@ -497,8 +482,6 @@ if O_RDWR fails</td>
</td>
<td style="vertical-align: top;">error reported<br>
</td>
- <td style="vertical-align: top;"><br>
- </td>
</tr>
</tbody>
</table>
@@ -507,7 +490,12 @@ Some of the above combinations are not sensible (e.g. 'append=1' on a
block device). Raw devices were introduced in the lk 2.4 series and are
still available in the lk 2.6 series but opening a block device or a
normal file with O_DIRECT (in sg_dd using the option 'odir=1') is
-preferred.<br>
+preferred in the lk 2.6 series. If either the input or output file is a
+raw device, or 'odir=1' is given then the internal buffers used by
+sg_dd are aligned to a memory page boundary. A memory page is 4
+kilobytes in the i386 architecture. This memory alignment is a
+technical requirement of both raw devices and normal block devices that
+implement O_DIRECT.<br>
<br>
The 'blk_sgio=1' option is only valid in the lk 2.6 series. This option
instructs the sg_dd utility to use the SG_IO ioctl to issue SCSI
@@ -520,12 +508,12 @@ sg_dd utility expects direct access devices (whereas tapes are
sequential access) so sg_dd generates an error if a st device is
detected. When the input or output file is a sg device then the
'blk_sgio' option is ignored as IO with that file is always via SCSI
-commands. When 'blk_sgio=1' is used on an ATAPI dvd/cd drive the
-combination of 2048 byte block size and the default 'bpt' value of 128
-may cause read errors. The solution is to reduce the 'bpt' value (try
-64 first) so the number of bytes transferred per SCSI command is below
-a limit imposed of the native device node (e.g. /dev/hdd). [When 'bpt'
-is to high the first read will report an EIO (input/output) error.]<br>
+commands. When 'blk_sgio=1' is used with a block device and the value
+given to 'bpt'
+is too high then the first read will report an EIO (input/output)
+error; the solution is to lower the 'bpt' value. [The EIO error
+occurred often with CD/DVD drives which have 2048 bytes sectors, so the
+'bpt' default value was reduced for block size &gt;= 2048 bytes.]<br>
<br>
If a partition of block device is accessed (e.g. /dev/sda2) when
'blk_sgio=0' (or is not given) then logical block address 0 for the
@@ -719,7 +707,15 @@ will automatically reallocate a logical block address (to another
sector)
if a recoverable error is detected on a WRITE operation. RECOVERED
ERRORs are only report on read and write operations when the PER [Post
-Error] bit is set.<br>
+Error] bit is set. The values shown in brackets are:<br>
+<ul>
+ <li>whether the field is changeable (i.e. "cha: y" for yes it is
+changeable)</li>
+ <li>its default value (i.e. "def:") which is supplied by the vendor</li>
+ <li>the saved value (i.e. "sav:") which will become current <span
+ style="font-style: italic;">after</span> the next device power cycle
+or reset</li>
+</ul>
<br>
<span style="font-family: monospace;">$ sg_dd if=/dev/sda of=. bs=512
verbose=1 count=0 blk_sgio=0</span><br style="font-family: monospace;">
@@ -751,39 +747,39 @@ ST39173LC&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 1234&nbsp;
<span style="font-family: monospace;">&nbsp; Read write error recovery
mode page:</span><br style="font-family: monospace;">
<span style="font-family: monospace;">&nbsp;&nbsp;&nbsp;
-AWRE:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 1&nbsp; [Changeable: y, def: 1,
-saved: 1]</span><br style="font-family: monospace;">
+AWRE:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 1&nbsp; [cha: y, def: 1,
+sav: 1]</span><br style="font-family: monospace;">
<span style="font-family: monospace;">&nbsp;&nbsp;&nbsp;
-ARRE:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 1&nbsp; [Changeable: y, def: 1,
-saved: 1]</span><br style="font-family: monospace;">
+ARRE:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 1&nbsp; [cha: y, def: 1,
+sav: 1]</span><br style="font-family: monospace;">
<span style="font-family: monospace;">&nbsp;&nbsp;&nbsp;
-RC:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 0&nbsp; [Changeable: y,
-def: 0, saved: 0]</span><br style="font-family: monospace;">
+RC:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 0&nbsp; [cha: y,
+def: 0, sav: 0]</span><br style="font-family: monospace;">
<span style="font-family: monospace;">&nbsp;&nbsp;&nbsp;
-EER:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 1&nbsp; [Changeable: y, def:
-0, saved: 1]</span><br style="font-family: monospace;">
+EER:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 1&nbsp; [cha: y, def:
+0, sav: 1]</span><br style="font-family: monospace;">
<span style="font-family: monospace;">&nbsp;&nbsp;&nbsp;
-PER:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 1&nbsp; [Changeable: y, def:
-0, saved: 1]</span><br style="font-family: monospace;">
+PER:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 1&nbsp; [cha: y, def:
+0, sav: 1]</span><br style="font-family: monospace;">
<span style="font-family: monospace;">&nbsp;&nbsp;&nbsp;
-DTE:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 0&nbsp; [Changeable: y, def:
-0, saved: 0]</span><br style="font-family: monospace;">
+DTE:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 0&nbsp; [cha: y, def:
+0, sav: 0]</span><br style="font-family: monospace;">
<span style="font-family: monospace;">&nbsp;&nbsp;&nbsp;
-DCR:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 0&nbsp; [Changeable: y, def:
-0, saved: 0]</span><br style="font-family: monospace;">
+DCR:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 0&nbsp; [cha: y, def:
+0, sav: 0]</span><br style="font-family: monospace;">
<span style="font-family: monospace;">&nbsp; Caching mode page:</span><br
style="font-family: monospace;">
<span style="font-family: monospace;">&nbsp;&nbsp;&nbsp;
-WRE:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 1&nbsp; [Changeable: y, def:
-1, saved: 1]</span><br style="font-family: monospace;">
+WRE:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 1&nbsp; [cha: y, def:
+1, sav: 1]</span><br style="font-family: monospace;">
<span style="font-family: monospace;">&nbsp;&nbsp;&nbsp;
-RCD:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 0&nbsp; [Changeable: y, def:
-0, saved: 0]</span><br style="font-family: monospace;">
+RCD:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 0&nbsp; [cha: y, def:
+0, sav: 0]</span><br style="font-family: monospace;">
<span style="font-family: monospace;">&nbsp; Control mode page:</span><br
style="font-family: monospace;">
<span style="font-family: monospace;">&nbsp;&nbsp;&nbsp;
-SWP:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 0&nbsp; [Changeable: n, def:
-0, saved: 0]</span><br style="font-family: monospace;">
+SWP:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 0&nbsp; [cha: n, def:
+0, sav: 0]</span><br style="font-family: monospace;">
<span style="font-family: monospace;">&nbsp;&gt;&gt; Output file type:
null device</span><br style="font-family: monospace;">
<span style="font-family: monospace;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
@@ -795,6 +791,9 @@ number of blocks=17781521 [0x10f5311], block size=512</span><br
<br>
Some of the output above is out of order, the "number of blocks" line
relates to the input file.<br>
+<br>
+Mode page settings can be examined and changed with a utility like <a
+ href="sdparm.html">sdparm</a> .<br>
<h2><a name="Conclusion"></a>Conclusion</h2>
The sg_dd utility maintains syntactic and semantic compatibility with
the Unix dd command while allowing precise control over SCSI devices
@@ -802,10 +801,9 @@ such as SCSI disks and CD/DVD drives. Amongst other uses it can copy
data from failing media, continuing as best it can when medium errors
are encountered.<br>
<br>
-<br>
<p>Return to <a href="index.html">main</a> page. </p>
<center>
-<p>Last updated: 5th June 2005<br>
+<p>Last updated: 8th August 2005<br>
<br>
</p>
</center>
diff --git a/html/u_index.html b/html/u_index.html
index 82b7aaf5..ed4554cb 100644
--- a/html/u_index.html
+++ b/html/u_index.html
@@ -41,7 +41,8 @@ targeted the&nbsp; linux kernel 2.2 series with some support for the
2.0 series. See an earlier version of this web <a href="uu_index.html">page</a>&nbsp;
for further information about sg_utils.&nbsp; This
document describes
-version 1.15 of sg3_utils . <br>
+<span style="font-weight: bold;">version 1.16</span> of <span
+ style="font-weight: bold;">sg3_utils</span> . <br>
<br>
In the linux kernel 2.4 series most these utilities must be
used with a SCSI generic (sg) driver device name (e.g. <span
@@ -56,8 +57,7 @@ still represents a cleaner interface than the primary device names
since the drivers behind primary device names have their
own policies, may interfere with error processing and in some cases
run their own
-state machines (e.g. the cdrom driver interferes with attempts to
-prevent media removal with sg_prevent).<br>
+state machines.<br>
<p>SCSI utility programs for Linux from other sources are listed and
briefly described in
the final section. </p>
@@ -157,7 +157,8 @@ time; now in own package, see <a href="sdparm.html">sdparm</a><br>
<td style="vertical-align: top;">symbolic decoding (optional
changing) of mode pages. Can also output (disk) defect lists. In lk 2.4
can be given primary device nodes (e.g. /dev/sda) as well as sg device
-nodes.<br>
+nodes. See <span style="font-weight: bold;">scsiinfo</span> package
+notes below.<br>
</td>
</tr>
<tr>
@@ -238,6 +239,18 @@ cd/dvd drive and/or its current media<br>
</td>
</tr>
<tr>
+ <td style="vertical-align: top;">sg_ident<br>
+ </td>
+ <td style="vertical-align: top;">REPORT/SET DEVICE IDENTIFIER<br>
+ </td>
+ <td style="vertical-align: top;"><br>
+ </td>
+ <td style="vertical-align: top;">default is to report (fetch) the
+device identifier. With the '--set' option a new identifier can be sent
+to the device.<br>
+ </td>
+ </tr>
+ <tr>
<td style="vertical-align: top;">sg_inq<br>
</td>
<td style="vertical-align: top;">INQUIRY<br>
@@ -605,12 +618,13 @@ nodes.]<br>
<br>
Irrespective of the Unix device node used to access a device, care
should be taken not to interfere with a device while it is "active".
-Obviously invoking a "sg_format -F" utility a disk with mounted file
+For example invoking a "sg_format -F" utility on a disk with mounted
+file
systems on it is going to cause damage.<br>
<h2><a name="Changing_mode_page_settings"></a>Changing mode page
settings</h2>
SCSI devices store settings (metadata) that could possibly be changed
-by the user (called the "application client" in SCSI speak) in mode
+by the user (called the "application client" in SCSI jargon) in mode
pages. It is a common requirement to find mode page settings and in
some cases change them. An example is the Writeback Cache Enable (WCE)
bit
@@ -619,7 +633,8 @@ default setting for WCE is set (on) but the user may want it off. <br>
<br>
Generic command line tools to change mode page settings tend to be
difficult to use (which in some small part is due to the SCSI rules for
-manipulating mode pages). Here is a list of some utilities for changing
+manipulating mode pages). Here is a list of some linux utilities for
+changing
mode pages followed by some notes:<br>
<ul>
<li><span style="font-weight: bold;">scsiinfo</span> (old utility):
@@ -649,7 +664,8 @@ page values but awkward for manipulating a specific mode page field.</li>
<li><span style="font-weight: bold;">hdparm</span> (hdparm):
abstracts over ATA (mainly) and SCSI (where convenient) disks. Write
caching can be turned on and off but that is one of the few mode fields
-that can be changed.</li>
+that can be changed on a SCSI device.<br>
+ </li>
<li><span style="font-weight: bold;">blktool</span> (blktool): much
newer and cleaner version of hdparm which targets the lk 2.6 series.
For SCSI devices only a relatively small (but important) number of mode
@@ -898,7 +914,21 @@ See&nbsp;<a class="moz-txt-link-freetext"
href="http://www.scsifaq.org/RMiller_Tools/index.html"><span
style="font-family: monospace;"></span>www.scsifaq.org/RMiller_Tools/index.html</a>&nbsp;for
more details. Both <b>scu</b> and <b>dt </b>are written by Robin
-T. Miller &lt;Robin.Miller at hp dot com&gt;
+T. Miller &lt;Robin.Miller at hp dot com&gt;<br>
+<h3>scsiinfo</h3>
+Older package that includes the <span style="font-weight: bold;">scsiinfo</span>
+and <span style="font-weight: bold;">scsiformat</span> utilities plus
+tcl/tk GUI interfaces for those utilities. The last update of the <span
+ style="font-weight: bold;">scsiinfo</span> package was in 1997. The
+function and syntax of the <span style="font-weight: bold;">scsiinfo</span>
+utility have inspired <span style="font-weight: bold;">sginfo</span>
+which now can be considered as a "drop in" replacement for <span
+ style="font-weight: bold;">scsiinfo</span> . Recent changes to SCSI
+standards (e.g. extra and extended mode pages) are reflected in <span
+ style="font-weight: bold;">sginfo</span> . In a similar way the <span
+ style="font-weight: bold;">sg_format</span> utility can be thought of
+as a modern replacement for the <span style="font-weight: bold;">scsiformat</span>
+utility.<br>
<h3> scsidev</h3>
Kurt Garloff &lt;garloff@suse.de&gt; describes this utility thus: "This
program scans the SCSI bus and creates device nodes in /dev/scsi/,
@@ -997,10 +1027,18 @@ author's "to do" list. See <a href="http://www.lerhaupt.com/linux.html">http://w
This utility allows arbitrary SCSI commands to be sent to a device. See
<a href="http://members.aol.com/plscsi">http://members.aol.com/plscsi</a>
. It is similar to FreeBSD's camcontrol command.<br>
+<h3>safte-monitor</h3>
+SAF-TE (SCSI Attached Fault-Tolerant Enclosure) is a SCSI command set
+for monitoring and controlling enclosures and RAIDs. SAF-TE devices
+report "processor" peripheral device type (0x3) in their INQUIRY
+responses. More recent products tend to use SES (drafts at
+http://www.t10.org ) which covers similar functionality. For a SAF-TE
+monitoring tool for linux see: <a
+ href="http://oss.metaparadigm.com/safte-monitor">http://oss.metaparadigm.com/safte-monitor</a><br>
<br>
<p>Return to <a href="index.html">main</a> page. </p>
<center>
-<p>Last updated: 5th June 2005<br>
+<p>Last updated: 5th August 2005<br>
<br>
</p>
</center>
diff --git a/lib_no_lib/Makefile.no_lib b/lib_no_lib/Makefile.no_lib
index fe150cf9..1ff83f14 100644
--- a/lib_no_lib/Makefile.no_lib
+++ b/lib_no_lib/Makefile.no_lib
@@ -2,7 +2,7 @@ SHELL = /bin/sh
PREFIX=/usr/local
INSTDIR=$(DESTDIR)/$(PREFIX)/bin
-MANDIR=$(DESTDIR)/$(PREFIX)/man
+MANDIR=$(DESTDIR)/$(PREFIX)/share/man
ifndef CC
CC = gcc
@@ -15,7 +15,7 @@ EXECS = sg_dd sgp_dd sgm_dd sg_read sg_map sg_scan sg_rbuf \
sg_persist sg_write_long sg_read_long sg_requests sg_ses \
sg_verify sg_emc_trespass sg_luns sg_sync sg_prevent \
sg_get_config sg_wr_mode sg_rtpg sg_reassign sg_format \
- sg_rmsn
+ sg_rmsn sg_ident
MAN_PGS = sg_dd.8 sgp_dd.8 sgm_dd.8 sg_read.8 sg_map.8 sg_scan.8 sg_rbuf.8 \
sginfo.8 sg_readcap.8 sg_turs.8 sg_inq.8 sg_test_rwbuf.8 \
@@ -23,7 +23,7 @@ MAN_PGS = sg_dd.8 sgp_dd.8 sgm_dd.8 sg_read.8 sg_map.8 sg_scan.8 sg_rbuf.8 \
sg_opcodes.8 sg_persist.8 sg_write_long.8 sg_read_long.8 \
sg_requests.8 sg_ses.8 sg_verify.8 sg_emc_trespass.8 \
sg_luns.8 sg_sync.8 sg_prevent.8 sg_get_config.8 sg_wr_mode.8 \
- sg_rtpg.8 sg_reassign.8 sg_format.8 sg_rmsn.8
+ sg_rtpg.8 sg_reassign.8 sg_format.8 sg_rmsn.8 sg_ident.8
MAN_PREF = man8
LARGE_FILE_FLAGS = -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64
@@ -132,7 +132,7 @@ sg_luns: sg_luns.o sg_lib.o sg_cmds.o
sg_sync: sg_sync.o sg_lib.o sg_cmds.o
$(LD) -o $@ $(LDFLAGS) $^
-sg_prevent: sg_prevent.o sg_lib.o
+sg_prevent: sg_prevent.o sg_lib.o sg_cmds.o
$(LD) -o $@ $(LDFLAGS) $^
sg_get_config: sg_get_config.o sg_lib.o sg_cmds.o
@@ -153,6 +153,9 @@ sg_format: sg_format.o sg_lib.o sg_cmds.o
sg_rmsn: sg_rmsn.o sg_lib.o sg_cmds.o
$(LD) -o $@ $(LDFLAGS) $^
+sg_ident: sg_ident.o sg_lib.o sg_cmds.o
+ $(LD) -o $@ $(LDFLAGS) $^
+
install: $(EXECS)
install -d $(INSTDIR)
for name in $^; \
diff --git a/lib_no_lib/sg3_utils.spec.no_lib b/lib_no_lib/sg3_utils.spec.no_lib
index 8ad26c28..6785e45e 100644
--- a/lib_no_lib/sg3_utils.spec.no_lib
+++ b/lib_no_lib/sg3_utils.spec.no_lib
@@ -1,6 +1,6 @@
Summary: Utilities for SCSI devices in Linux
Name: sg3_utils
-Version: 1.15
+Version: 1.16
Release: 1
Packager: Douglas Gilbert <dgilbert at interlog dot com>
License: GPL/FreeBSD
@@ -82,6 +82,7 @@ rm -rf $RPM_BUILD_ROOT
%attr(755,root,root) %{_bindir}/sg_reassign
%attr(755,root,root) %{_bindir}/sg_format
%attr(755,root,root) %{_bindir}/sg_rmsn
+%attr(755,root,root) %{_bindir}/sg_ident
# Mandrake compresses man pages with bzip2, RedHat with gzip
%attr(-,root,root) %doc %{_mandir}/man8/sg_dd.8*
%attr(-,root,root) %doc %{_mandir}/man8/sgp_dd.8*
@@ -117,9 +118,14 @@ rm -rf $RPM_BUILD_ROOT
%attr(-,root,root) %doc %{_mandir}/man8/sg_reassign.8*
%attr(-,root,root) %doc %{_mandir}/man8/sg_format.8*
%attr(-,root,root) %doc %{_mandir}/man8/sg_rmsn.8*
+%attr(-,root,root) %doc %{_mandir}/man8/sg_ident.8*
%changelog
+* Wed Aug 10 2005 - dgilbert at interlog dot com
+- add sg_ident, sg_inq VPD page extensions
+ * sg3_utils-1.16
+
* Sun Jun 05 2005 - dgilbert at interlog dot com
- use O_NONBLOCK on all fds that use SG_IO iotcl
* sg3_utils-1.15
diff --git a/sg3_utils.spec b/sg3_utils.spec
index db648ed8..47e937f4 100644
--- a/sg3_utils.spec
+++ b/sg3_utils.spec
@@ -1,5 +1,5 @@
%define name sg3_utils
-%define version 1.15
+%define version 1.16
%define release 1
%define major 1
@@ -96,6 +96,10 @@ make install \
%{_libdir}/*.la
%changelog
+* Wed Aug 10 2005 - dgilbert at interlog dot com
+- add sg_ident, sg_inq VPD page extensions
+ * sg3_utils-1.16
+
* Sun Jun 05 2005 - dgilbert at interlog dot com
- use O_NONBLOCK on all fds that use SG_IO ioctl
* sg3_utils-1.15
diff --git a/sg_cmds.c b/sg_cmds.c
index 107eced3..a82156a1 100644
--- a/sg_cmds.c
+++ b/sg_cmds.c
@@ -54,11 +54,12 @@
#include "sg_lib.h"
#include "sg_cmds.h"
-static char * version_str = "1.13 20050523";
+static char * version_str = "1.18 20050809";
#define SENSE_BUFF_LEN 32 /* Arbitrary, could be larger */
#define DEF_TIMEOUT 60000 /* 60,000 millisecs == 60 seconds */
+#define START_TIMEOUT 120000 /* 120,000 millisecs == 2 minutes */
#define LONG_TIMEOUT 7200000 /* 7,200,000 millisecs == 120 minutes */
#define EBUFF_SZ 256
@@ -85,7 +86,11 @@ static char * version_str = "1.13 20050523";
#define REPORT_LUNS_CMDLEN 12
#define MAINTENANCE_IN_CMD 0xa3
#define MAINTENANCE_IN_CMDLEN 12
-#define REPORT_TGT_PRT_GRP_SA 0x0a
+#define REPORT_TGT_PRT_GRP_SA 0xa
+#define REPORT_DEVICE_IDENTIFIER_SA 0x5
+#define MAINTENANCE_OUT_CMD 0xa4
+#define MAINTENANCE_OUT_CMDLEN 12
+#define SET_DEVICE_IDENTIFIER_SA 0x6
#define LOG_SENSE_CMD 0x4d
#define LOG_SENSE_CMDLEN 10
#define LOG_SELECT_CMD 0x4c
@@ -101,11 +106,17 @@ static char * version_str = "1.13 20050523";
#define SERVICE_ACTION_IN_12_CMD 0xab
#define SERVICE_ACTION_IN_12_CMDLEN 12
#define READ_MEDIA_SERIAL_NUM_SA 0x1
+#define START_STOP_CMD 0x1b
+#define START_STOP_CMDLEN 6
+#define PREVENT_ALLOW_CMD 0x1e
+#define PREVENT_ALLOW_CMDLEN 6
#define MODE6_RESP_HDR_LEN 4
#define MODE10_RESP_HDR_LEN 8
#define MODE_RESP_ARB_LEN 1024
+#define INQUIRY_RESP_INITIAL_LEN 36
+
const char * sg_cmds_version()
{
@@ -117,7 +128,7 @@ const char * sg_cmds_version()
int sg_ll_inquiry(int sg_fd, int cmddt, int evpd, int pg_op,
void * resp, int mx_resp_len, int noisy, int verbose)
{
- int res, k;
+ int res, k, got;
unsigned char inqCmdBlk[INQUIRY_CMDLEN] = {INQUIRY_CMD, 0, 0, 0, 0, 0};
unsigned char sense_b[SENSE_BUFF_LEN];
struct sg_io_hdr io_hdr;
@@ -162,11 +173,19 @@ int sg_ll_inquiry(int sg_fd, int cmddt, int evpd, int pg_op,
switch (res) {
case SG_LIB_CAT_RECOVERED:
if (noisy || verbose)
- sg_chk_n_print3("Inquiry", &io_hdr);
+ sg_chk_n_print3("Inquiry", &io_hdr, verbose);
/* fall through */
case SG_LIB_CAT_CLEAN:
+ got = io_hdr.dxfer_len - io_hdr.resid;
+ if (got < 4) {
+ if (verbose)
+ fprintf(sg_warnings_str, "inquiry: got too few (%d) "
+ "bytes\n", got);
+ return -2;
+ }
if (verbose && io_hdr.resid)
- fprintf(sg_warnings_str, " inquiry: resid=%d\n", io_hdr.resid);
+ fprintf(sg_warnings_str, " inquiry: resid=%d (got %d "
+ "bytes)\n", io_hdr.resid, got);
return 0;
default:
if (noisy || verbose) {
@@ -180,7 +199,7 @@ int sg_ll_inquiry(int sg_fd, int cmddt, int evpd, int pg_op,
pg_op);
else
snprintf(ebuff, EBUFF_SZ, "Inquiry error, [standard]");
- sg_chk_n_print3(ebuff, &io_hdr);
+ sg_chk_n_print3(ebuff, &io_hdr, verbose);
}
return -2;
}
@@ -191,11 +210,11 @@ int sg_ll_inquiry(int sg_fd, int cmddt, int evpd, int pg_op,
int sg_simple_inquiry(int sg_fd, struct sg_simple_inquiry_resp * inq_data,
int noisy, int verbose)
{
- int res, k;
+ int res, k, got;
unsigned char inqCmdBlk[INQUIRY_CMDLEN] = {INQUIRY_CMD, 0, 0, 0, 0, 0};
unsigned char sense_b[SENSE_BUFF_LEN];
struct sg_io_hdr io_hdr;
- unsigned char inq_resp[36];
+ unsigned char inq_resp[INQUIRY_RESP_INITIAL_LEN];
if (inq_data) {
memset(inq_data, 0, sizeof(* inq_data));
@@ -235,9 +254,16 @@ int sg_simple_inquiry(int sg_fd, struct sg_simple_inquiry_resp * inq_data,
switch (res) {
case SG_LIB_CAT_RECOVERED:
if (noisy || verbose)
- sg_chk_n_print3("Inquiry", &io_hdr);
+ sg_chk_n_print3("Inquiry", &io_hdr, verbose);
/* fall through */
case SG_LIB_CAT_CLEAN:
+ got = io_hdr.dxfer_len - io_hdr.resid;
+ if (got < 4) {
+ if (verbose)
+ fprintf(sg_warnings_str, "inquiry: got too few (%d) "
+ "bytes\n", got);
+ return -2;
+ }
if (inq_data) {
inq_data->peripheral_qualifier = (inq_resp[0] >> 5) & 0x7;
inq_data->peripheral_type = inq_resp[0] & 0x1f;
@@ -252,14 +278,15 @@ int sg_simple_inquiry(int sg_fd, struct sg_simple_inquiry_resp * inq_data,
memcpy(inq_data->revision, inq_resp + 32, 4);
}
if (verbose && io_hdr.resid)
- fprintf(sg_warnings_str, " inquiry: resid=%d\n", io_hdr.resid);
+ fprintf(sg_warnings_str, " inquiry: resid=%d (got %d "
+ "bytes)\n", io_hdr.resid, got);
return 0;
default:
- if (noisy) {
+ if (noisy || verbose) {
char ebuff[EBUFF_SZ];
snprintf(ebuff, EBUFF_SZ, "Inquiry error ");
- sg_chk_n_print3(ebuff, &io_hdr);
+ sg_chk_n_print3(ebuff, &io_hdr, verbose);
}
return -2;
}
@@ -310,7 +337,7 @@ int sg_ll_test_unit_ready(int sg_fd, int pack_id, int noisy, int verbose)
return 0;
default:
if (noisy || verbose)
- sg_chk_n_print3("test unit ready", &io_hdr);
+ sg_chk_n_print3("test unit ready", &io_hdr, verbose);
return -1;
}
}
@@ -380,11 +407,11 @@ int sg_ll_sync_cache_10(int sg_fd, int sync_nv, int immed, int group,
case SG_LIB_CAT_INVALID_OP:
case SG_LIB_CAT_ILLEGAL_REQ:
if (verbose > 1)
- sg_chk_n_print3("synchronize cache", &io_hdr);
+ sg_chk_n_print3("synchronize cache", &io_hdr, 1);
return res;
default:
if (noisy || verbose)
- sg_chk_n_print3("synchronize cache", &io_hdr);
+ sg_chk_n_print3("synchronize cache", &io_hdr, verbose);
return -1;
}
return 0;
@@ -395,7 +422,7 @@ int sg_ll_sync_cache_10(int sg_fd, int sync_nv, int immed, int group,
* -1 -> failure, SG_LIB_CAT_MEDIA_CHANGED -> repeat, SG_LIB_CAT_INVALID_OP
* -> cdb not supported, SG_LIB_CAT_IlLEGAL_REQ -> bad field in cdb */
int sg_ll_readcap_16(int sg_fd, int pmi, unsigned long long llba,
- void * resp, int mx_resp_len, int verbose)
+ void * resp, int mx_resp_len, int noisy, int verbose)
{
int k, res;
unsigned char rcCmdBlk[SERVICE_ACTION_IN_16_CMDLEN] =
@@ -452,21 +479,24 @@ int sg_ll_readcap_16(int sg_fd, int pmi, unsigned long long llba,
switch (res) {
case SG_LIB_CAT_RECOVERED:
if (verbose)
- sg_chk_n_print3("Read capacity (16)", &io_hdr);
+ sg_chk_n_print3("Read capacity (16)", &io_hdr, 1);
/* fall through */
case SG_LIB_CAT_CLEAN:
if (verbose && io_hdr.resid)
- fprintf(sg_warnings_str, " read_capacity16: resid=%d\n",
- io_hdr.resid);
+ fprintf(sg_warnings_str, " read_capacity16: resid=%d (got"
+ " %d bytes)\n", io_hdr.resid,
+ io_hdr.dxfer_len - io_hdr.resid);
return 0;
case SG_LIB_CAT_INVALID_OP:
case SG_LIB_CAT_ILLEGAL_REQ:
case SG_LIB_CAT_MEDIA_CHANGED:
if (verbose > 1)
- sg_chk_n_print3("READ CAPACITY 16 command error", &io_hdr);
+ sg_chk_n_print3("READ CAPACITY 16 command error", &io_hdr, 1);
return res;
default:
- sg_chk_n_print3("READ CAPACITY 16 command error", &io_hdr);
+ if (noisy || verbose)
+ sg_chk_n_print3("READ CAPACITY 16 command error", &io_hdr,
+ verbose);
return -1;
}
}
@@ -476,7 +506,7 @@ int sg_ll_readcap_16(int sg_fd, int pmi, unsigned long long llba,
* -> media changed, SG_LIB_CAT_ILLEGAL_REQ -> bad field in cdb,
* -1 -> other failure */
int sg_ll_readcap_10(int sg_fd, int pmi, unsigned int lba,
- void * resp, int mx_resp_len, int verbose)
+ void * resp, int mx_resp_len, int noisy, int verbose)
{
int k, res;
unsigned char rcCmdBlk[READ_CAPACITY_10_CMDLEN] =
@@ -523,21 +553,24 @@ int sg_ll_readcap_10(int sg_fd, int pmi, unsigned int lba,
switch (res) {
case SG_LIB_CAT_RECOVERED:
if (verbose)
- sg_chk_n_print3("Read capacity (10)", &io_hdr);
+ sg_chk_n_print3("Read capacity (10)", &io_hdr, 1);
/* fall through */
case SG_LIB_CAT_CLEAN:
if (verbose && io_hdr.resid)
- fprintf(sg_warnings_str, " read_capacity10: resid=%d\n",
- io_hdr.resid);
+ fprintf(sg_warnings_str, " read_capacity10: resid=%d (got"
+ " %d bytes)\n", io_hdr.resid,
+ io_hdr.dxfer_len - io_hdr.resid);
return 0;
case SG_LIB_CAT_INVALID_OP:
case SG_LIB_CAT_ILLEGAL_REQ:
case SG_LIB_CAT_MEDIA_CHANGED:
if (verbose > 1)
- sg_chk_n_print3("READ CAPACITY 10 command error", &io_hdr);
+ sg_chk_n_print3("READ CAPACITY 10 command error", &io_hdr, 1);
return res;
default:
- sg_chk_n_print3("READ CAPACITY 10 command error", &io_hdr);
+ if (noisy || verbose)
+ sg_chk_n_print3("READ CAPACITY 10 command error", &io_hdr,
+ verbose);
return -1;
}
}
@@ -595,12 +628,13 @@ int sg_ll_mode_sense6(int sg_fd, int dbd, int pc, int pg_code, int sub_pg_code,
switch (res) {
case SG_LIB_CAT_RECOVERED:
if (noisy || verbose)
- sg_chk_n_print3("Mode sense (6)", &io_hdr);
+ sg_chk_n_print3("Mode sense (6)", &io_hdr, verbose);
/* fall through */
case SG_LIB_CAT_CLEAN:
if (verbose && io_hdr.resid)
- fprintf(sg_warnings_str, " mode sense (6): resid=%d\n",
- io_hdr.resid);
+ fprintf(sg_warnings_str, " mode sense (6): resid=%d (got "
+ "%d bytes)\n", io_hdr.resid,
+ io_hdr.dxfer_len - io_hdr.resid);
if (verbose > 2) {
k = mx_resp_len - io_hdr.resid;
if (k > 0) {
@@ -613,7 +647,7 @@ int sg_ll_mode_sense6(int sg_fd, int dbd, int pc, int pg_code, int sub_pg_code,
case SG_LIB_CAT_INVALID_OP:
case SG_LIB_CAT_ILLEGAL_REQ:
if (verbose > 1)
- sg_chk_n_print3("Mode sense (6) error", &io_hdr);
+ sg_chk_n_print3("Mode sense (6) error", &io_hdr, 1);
return res;
default:
if (noisy || verbose) {
@@ -622,7 +656,7 @@ int sg_ll_mode_sense6(int sg_fd, int dbd, int pc, int pg_code, int sub_pg_code,
snprintf(ebuff, EBUFF_SZ, "Mode sense (6) error, dbd=%d "
"pc=%d page_code=%x sub_page_code=%x\n ", dbd,
pc, pg_code, sub_pg_code);
- sg_chk_n_print3(ebuff, &io_hdr);
+ sg_chk_n_print3(ebuff, &io_hdr, verbose);
}
return -1;
}
@@ -683,12 +717,13 @@ int sg_ll_mode_sense10(int sg_fd, int llbaa, int dbd, int pc, int pg_code,
switch (res) {
case SG_LIB_CAT_RECOVERED:
if (noisy || verbose)
- sg_chk_n_print3("Mode sense (10)", &io_hdr);
+ sg_chk_n_print3("Mode sense (10)", &io_hdr, verbose);
/* fall through */
case SG_LIB_CAT_CLEAN:
if (verbose && io_hdr.resid)
- fprintf(sg_warnings_str, " mode sense (10): resid=%d\n",
- io_hdr.resid);
+ fprintf(sg_warnings_str, " mode sense (10): resid=%d (got "
+ "%d bytes)\n", io_hdr.resid,
+ io_hdr.dxfer_len - io_hdr.resid);
if (verbose > 2) {
k = mx_resp_len - io_hdr.resid;
if (k > 0) {
@@ -701,7 +736,7 @@ int sg_ll_mode_sense10(int sg_fd, int llbaa, int dbd, int pc, int pg_code,
case SG_LIB_CAT_INVALID_OP:
case SG_LIB_CAT_ILLEGAL_REQ:
if (verbose > 1)
- sg_chk_n_print3("Mode sense (10) error", &io_hdr);
+ sg_chk_n_print3("Mode sense (10) error", &io_hdr, 1);
return res;
default:
if (noisy || verbose) {
@@ -710,7 +745,7 @@ int sg_ll_mode_sense10(int sg_fd, int llbaa, int dbd, int pc, int pg_code,
snprintf(ebuff, EBUFF_SZ, "Mode sense (10) error, dbd=%d "
"pc=%d page_code=%x sub_page_code=%x\n ", dbd,
pc, pg_code, sub_pg_code);
- sg_chk_n_print3(ebuff, &io_hdr);
+ sg_chk_n_print3(ebuff, &io_hdr, verbose);
}
return -1;
}
@@ -771,14 +806,14 @@ int sg_ll_mode_select6(int sg_fd, int pf, int sp, void * paramp,
switch (res) {
case SG_LIB_CAT_RECOVERED:
if (noisy || verbose)
- sg_chk_n_print3("Mode select (6)", &io_hdr);
+ sg_chk_n_print3("Mode select (6)", &io_hdr, verbose);
/* fall through */
case SG_LIB_CAT_CLEAN:
return 0;
case SG_LIB_CAT_INVALID_OP:
case SG_LIB_CAT_ILLEGAL_REQ:
if (verbose > 1)
- sg_chk_n_print3("Mode select (6) error", &io_hdr);
+ sg_chk_n_print3("Mode select (6) error", &io_hdr, 1);
return res;
default:
if (noisy || verbose) {
@@ -786,7 +821,7 @@ int sg_ll_mode_select6(int sg_fd, int pf, int sp, void * paramp,
snprintf(ebuff, EBUFF_SZ, "Mode select (6) error, pf=%d "
"sp=%d\n ", pf, sp);
- sg_chk_n_print3(ebuff, &io_hdr);
+ sg_chk_n_print3(ebuff, &io_hdr, verbose);
}
return -1;
}
@@ -848,14 +883,14 @@ int sg_ll_mode_select10(int sg_fd, int pf, int sp, void * paramp,
switch (res) {
case SG_LIB_CAT_RECOVERED:
if (noisy || verbose)
- sg_chk_n_print3("Mode select (10)", &io_hdr);
+ sg_chk_n_print3("Mode select (10)", &io_hdr, verbose);
/* fall through */
case SG_LIB_CAT_CLEAN:
return 0;
case SG_LIB_CAT_INVALID_OP:
case SG_LIB_CAT_ILLEGAL_REQ:
if (verbose > 1)
- sg_chk_n_print3("Mode select (10) error", &io_hdr);
+ sg_chk_n_print3("Mode select (10) error", &io_hdr, 1);
return res;
default:
if (noisy || verbose) {
@@ -863,7 +898,7 @@ int sg_ll_mode_select10(int sg_fd, int pf, int sp, void * paramp,
snprintf(ebuff, EBUFF_SZ, "Mode select (10) error, pf=%d "
"sp=%d\n ", pf, sp);
- sg_chk_n_print3(ebuff, &io_hdr);
+ sg_chk_n_print3(ebuff, &io_hdr, verbose);
}
return -1;
}
@@ -1033,7 +1068,7 @@ int sg_get_mode_page_controls(int sg_fd, int mode6, int pg_code,
* SG_LIB_CAT_INVALID_OP -> Request Sense not * supported??,
* SG_LIB_CAT_ILEGAL_REQ -> bad field in cdb, -1 -> other failure */
int sg_ll_request_sense(int sg_fd, int desc, void * resp, int mx_resp_len,
- int verbose)
+ int noisy, int verbose)
{
int k, res;
unsigned char rsCmdBlk[REQUEST_SENSE_CMDLEN] =
@@ -1084,24 +1119,28 @@ int sg_ll_request_sense(int sg_fd, int desc, void * resp, int mx_resp_len,
switch (res) {
case SG_LIB_CAT_RECOVERED:
if (verbose)
- sg_chk_n_print3("Request sense", &io_hdr);
+ sg_chk_n_print3("Request sense", &io_hdr, 1);
/* fall through */
case SG_LIB_CAT_CLEAN:
if ((mx_resp_len >= 8) && (io_hdr.resid > (mx_resp_len - 8))) {
- fprintf(sg_warnings_str, " request sense: resid=%d "
- "indicates response too short\n", io_hdr.resid);
+ if (verbose)
+ fprintf(sg_warnings_str, " request sense: resid=%d "
+ "indicates response too short\n", io_hdr.resid);
return -1;
} else if (verbose && io_hdr.resid)
- fprintf(sg_warnings_str, " request sense: resid=%d\n",
- io_hdr.resid);
+ fprintf(sg_warnings_str, " request sense: resid=%d (got "
+ "%d bytes)\n", io_hdr.resid,
+ io_hdr.dxfer_len - io_hdr.resid);
return 0;
case SG_LIB_CAT_INVALID_OP:
case SG_LIB_CAT_ILLEGAL_REQ:
if (verbose > 1)
- sg_chk_n_print3("REQUEST SENSE command problem", &io_hdr);
+ sg_chk_n_print3("REQUEST SENSE command problem", &io_hdr, 1);
return res;
default:
- sg_chk_n_print3("REQUEST SENSE command problem", &io_hdr);
+ if (noisy || verbose)
+ sg_chk_n_print3("REQUEST SENSE command problem", &io_hdr,
+ verbose);
return -1;
}
}
@@ -1155,23 +1194,24 @@ int sg_ll_report_luns(int sg_fd, int select_report, void * resp,
switch (res) {
case SG_LIB_CAT_RECOVERED:
if (noisy || verbose)
- sg_chk_n_print3("Report luns", &io_hdr);
+ sg_chk_n_print3("Report luns", &io_hdr, verbose);
/* fall through */
case SG_LIB_CAT_CLEAN:
if (verbose && io_hdr.resid)
- fprintf(sg_warnings_str, " report_luns: resid=%d\n",
- io_hdr.resid);
+ fprintf(sg_warnings_str, " report luns: resid=%d (got "
+ "%d bytes)\n", io_hdr.resid,
+ io_hdr.dxfer_len - io_hdr.resid);
return 0;
case SG_LIB_CAT_INVALID_OP:
case SG_LIB_CAT_ILLEGAL_REQ:
if (verbose > 1)
- sg_chk_n_print3("REPORTS LUNS command error", &io_hdr);
+ sg_chk_n_print3("REPORTS LUNS command error", &io_hdr, 1);
return res;
case SG_LIB_CAT_MEDIA_CHANGED:
return 2;
default:
if (noisy || verbose)
- sg_chk_n_print3("REPORT LUNS command error", &io_hdr);
+ sg_chk_n_print3("REPORT LUNS command error", &io_hdr, verbose);
return -1;
}
}
@@ -1232,17 +1272,18 @@ int sg_ll_log_sense(int sg_fd, int ppc, int sp, int pc, int pg_code,
switch (res) {
case SG_LIB_CAT_RECOVERED:
if (noisy || verbose)
- sg_chk_n_print3("Log sense", &io_hdr);
+ sg_chk_n_print3("Log sense", &io_hdr, verbose);
/* fall through */
case SG_LIB_CAT_CLEAN:
if (verbose && io_hdr.resid)
- fprintf(sg_warnings_str, " log_sense: resid=%d\n",
- io_hdr.resid);
+ fprintf(sg_warnings_str, " log sense: resid=%d (got "
+ "%d bytes)\n", io_hdr.resid,
+ io_hdr.dxfer_len - io_hdr.resid);
return 0;
case SG_LIB_CAT_INVALID_OP:
case SG_LIB_CAT_ILLEGAL_REQ:
if (verbose > 1)
- sg_chk_n_print3("log_sense error", &io_hdr);
+ sg_chk_n_print3("log_sense error", &io_hdr, 1);
return res;
default:
if (noisy || verbose) {
@@ -1250,7 +1291,7 @@ int sg_ll_log_sense(int sg_fd, int ppc, int sp, int pc, int pg_code,
snprintf(ebuff, EBUFF_SZ, "log_sense: ppc=%d, sp=%d, "
"pc=%d, page_code=%x, paramp=%x\n ", ppc, sp, pc,
pg_code, paramp);
- sg_chk_n_print3(ebuff, &io_hdr);
+ sg_chk_n_print3(ebuff, &io_hdr, verbose);
}
return -1;
}
@@ -1315,24 +1356,21 @@ int sg_ll_log_select(int sg_fd, int pcr, int sp, int pc,
switch (res) {
case SG_LIB_CAT_RECOVERED:
if (noisy || verbose)
- sg_chk_n_print3("Log select", &io_hdr);
+ sg_chk_n_print3("Log select", &io_hdr, verbose);
/* fall through */
case SG_LIB_CAT_CLEAN:
- if (verbose && io_hdr.resid)
- fprintf(sg_warnings_str, " log_select: resid=%d\n",
- io_hdr.resid);
return 0;
case SG_LIB_CAT_INVALID_OP:
case SG_LIB_CAT_ILLEGAL_REQ:
if (verbose > 1)
- sg_chk_n_print3("log_select error", &io_hdr);
+ sg_chk_n_print3("log_select error", &io_hdr, 1);
return res;
default:
if (noisy || verbose) {
char ebuff[EBUFF_SZ];
snprintf(ebuff, EBUFF_SZ, "log_select: pcr=%d, sp=%d, "
"pc=%d\n ", pcr, sp, pc);
- sg_chk_n_print3(ebuff, &io_hdr);
+ sg_chk_n_print3(ebuff, &io_hdr, verbose);
}
return -1;
}
@@ -1387,21 +1425,23 @@ int sg_ll_report_tgt_prt_grp(int sg_fd, void * resp,
switch (res) {
case SG_LIB_CAT_RECOVERED:
if (noisy || verbose)
- sg_chk_n_print3("Report target port groups", &io_hdr);
+ sg_chk_n_print3("Report target port groups", &io_hdr, verbose);
/* fall through */
case SG_LIB_CAT_CLEAN:
if (verbose && io_hdr.resid)
- fprintf(sg_warnings_str, " report_tgt_prt_grp: resid=%d\n",
- io_hdr.resid);
+ fprintf(sg_warnings_str, " report_tgt_prt_grp: resid=%d (got "
+ "%d bytes)\n", io_hdr.resid,
+ io_hdr.dxfer_len - io_hdr.resid);
return 0;
case SG_LIB_CAT_INVALID_OP:
case SG_LIB_CAT_ILLEGAL_REQ:
if (verbose > 1)
- sg_chk_n_print3("REPORT TARGET PORT GROUPS", &io_hdr);
+ sg_chk_n_print3("REPORT TARGET PORT GROUPS", &io_hdr, 1);
return res;
default:
if (noisy || verbose)
- sg_chk_n_print3("REPORT TARGET PORT GROUPS command error", &io_hdr);
+ sg_chk_n_print3("REPORT TARGET PORT GROUPS command error",
+ &io_hdr, verbose);
return -1;
}
}
@@ -1463,21 +1503,21 @@ int sg_ll_send_diag(int sg_fd, int sf_code, int pf_bit, int sf_bit,
switch (res) {
case SG_LIB_CAT_RECOVERED:
if (noisy || verbose)
- sg_chk_n_print3("Send diagnostic, continuing", &io_hdr);
+ sg_chk_n_print3("Send diagnostic, continuing", &io_hdr, verbose);
/* fall through */
case SG_LIB_CAT_CLEAN:
return 0;
case SG_LIB_CAT_INVALID_OP:
case SG_LIB_CAT_ILLEGAL_REQ:
if (verbose > 1)
- sg_chk_n_print3("SEND DIAGNOSTIC", &io_hdr);
+ sg_chk_n_print3("SEND DIAGNOSTIC", &io_hdr, 1);
return res;
default:
- if (noisy) {
+ if (noisy || verbose) {
char ebuff[EBUFF_SZ];
snprintf(ebuff, EBUFF_SZ, "Send diagnostic error, sf_code=0x%x, "
"pf_bit=%d, sf_bit=%d ", sf_code, pf_bit, sf_bit);
- sg_chk_n_print3(ebuff, &io_hdr);
+ sg_chk_n_print3(ebuff, &io_hdr, verbose);
}
return -1;
}
@@ -1533,21 +1573,21 @@ int sg_ll_receive_diag(int sg_fd, int pcv, int pg_code, void * resp,
case SG_LIB_CAT_RECOVERED:
if (noisy || verbose)
sg_chk_n_print3("Receive diagnostics results, continuing",
- &io_hdr);
+ &io_hdr, verbose);
/* fall through */
case SG_LIB_CAT_CLEAN:
return 0;
case SG_LIB_CAT_INVALID_OP:
case SG_LIB_CAT_ILLEGAL_REQ:
if (verbose > 1)
- sg_chk_n_print3("RECEIVE DIAGNOSTICS RESULTS", &io_hdr);
+ sg_chk_n_print3("RECEIVE DIAGNOSTICS RESULTS", &io_hdr, 1);
return res;
default:
if (noisy) {
char ebuff[EBUFF_SZ];
snprintf(ebuff, EBUFF_SZ, "Receive diagnostics results error, "
"pcv=%d, page_code=%x ", pcv, pg_code);
- sg_chk_n_print3(ebuff, &io_hdr);
+ sg_chk_n_print3(ebuff, &io_hdr, verbose);
}
return -1;
}
@@ -1607,12 +1647,13 @@ int sg_ll_read_defect10(int sg_fd, int req_plist, int req_glist,
switch (res) {
case SG_LIB_CAT_RECOVERED:
if (noisy || verbose)
- sg_chk_n_print3("Read defect (10)", &io_hdr);
+ sg_chk_n_print3("Read defect (10)", &io_hdr, verbose);
/* fall through */
case SG_LIB_CAT_CLEAN:
if (verbose && io_hdr.resid)
- fprintf(sg_warnings_str, " read defect (10): resid=%d\n",
- io_hdr.resid);
+ fprintf(sg_warnings_str, " report defect(10): resid=%d (got "
+ "%d bytes)\n", io_hdr.resid,
+ io_hdr.dxfer_len - io_hdr.resid);
if (verbose > 2) {
k = mx_resp_len - io_hdr.resid;
if (k > 0) {
@@ -1625,7 +1666,7 @@ int sg_ll_read_defect10(int sg_fd, int req_plist, int req_glist,
case SG_LIB_CAT_INVALID_OP:
case SG_LIB_CAT_ILLEGAL_REQ:
if (verbose > 1)
- sg_chk_n_print3("Read defect (10) error", &io_hdr);
+ sg_chk_n_print3("Read defect (10) error", &io_hdr, 1);
return res;
default:
if (noisy || verbose) {
@@ -1634,7 +1675,7 @@ int sg_ll_read_defect10(int sg_fd, int req_plist, int req_glist,
snprintf(ebuff, EBUFF_SZ, "Read defect (10) error, req_plist=%d "
"req_glist=%d dl_format=%x\n ", req_plist, req_glist,
dl_format);
- sg_chk_n_print3(ebuff, &io_hdr);
+ sg_chk_n_print3(ebuff, &io_hdr, verbose);
}
return -1;
}
@@ -1643,8 +1684,8 @@ int sg_ll_read_defect10(int sg_fd, int req_plist, int req_glist,
/* Invokes a SCSI READ MEDIA SERIAL NUMBER command. Return of 0 -> success,
* SG_LIB_CAT_INVALID_OP -> Read media serial number not supported,
* SG_LIB_CAT_ILLEGAL_REQ -> bad field in cdb, -1 -> other failure */
-int sg_ll_read_media_serial_num(int sg_fd, void * resp,
- int mx_resp_len, int noisy, int verbose)
+int sg_ll_read_media_serial_num(int sg_fd, void * resp, int mx_resp_len,
+ int noisy, int verbose)
{
int k, res;
unsigned char rmsnCmdBlk[SERVICE_ACTION_IN_12_CMDLEN] =
@@ -1689,22 +1730,308 @@ int sg_ll_read_media_serial_num(int sg_fd, void * resp,
switch (res) {
case SG_LIB_CAT_RECOVERED:
if (noisy || verbose)
- sg_chk_n_print3("Read media serial number", &io_hdr);
+ sg_chk_n_print3("Read media serial number", &io_hdr, verbose);
/* fall through */
case SG_LIB_CAT_CLEAN:
if (verbose && io_hdr.resid)
- fprintf(sg_warnings_str, " read_media_serial_num: resid=%d\n",
- io_hdr.resid);
+ fprintf(sg_warnings_str, " read_media_serial_num: resid=%d ("
+ "got %d bytes)\n", io_hdr.resid,
+ io_hdr.dxfer_len - io_hdr.resid);
+ if (verbose > 2) {
+ k = mx_resp_len - io_hdr.resid;
+ if (k > 0) {
+ fprintf(sg_warnings_str, " report media serial number: "
+ "response%s\n", (k > 256 ? ", first 256 bytes" : ""));
+ dStrHex(resp, (k > 256 ? 256 : k), -1);
+ }
+ }
return 0;
case SG_LIB_CAT_INVALID_OP:
case SG_LIB_CAT_ILLEGAL_REQ:
if (verbose > 1)
- sg_chk_n_print3("READ MEDIA SERIAL NUMBER", &io_hdr);
+ sg_chk_n_print3("READ MEDIA SERIAL NUMBER", &io_hdr, 1);
return res;
default:
if (noisy || verbose)
sg_chk_n_print3("READ MEDIA SERIAL NUMBER command error",
- &io_hdr);
+ &io_hdr, verbose);
+ return -1;
+ }
+}
+
+/* Invokes a SCSI START STOP UNIT command (MMC + SBC).
+ * Return of 0 -> success,
+ * SG_LIB_CAT_INVALID_OP -> Start stop unit not supported,
+ * SG_LIB_CAT_ILLEGAL_REQ -> bad field in cdb, -1 -> other failure */
+int sg_ll_start_stop_unit(int sg_fd, int immed, int power_cond,
+ int loej, int start, int noisy, int verbose)
+{
+ unsigned char ssuBlk[START_STOP_CMDLEN] = {START_STOP_CMD, 0, 0, 0, 0, 0};
+ unsigned char sense_b[SENSE_BUFF_LEN];
+ struct sg_io_hdr io_hdr;
+ int k, res;
+
+ memset(&io_hdr, 0, sizeof(struct sg_io_hdr));
+ ssuBlk[1] = immed & 1;
+ ssuBlk[4] = ((power_cond & 0xf) << 4) | ((loej & 1) << 1) |
+ (start & 1);
+ if (NULL == sg_warnings_str)
+ sg_warnings_str = stderr;
+ if (verbose) {
+ fprintf(sg_warnings_str, " Start stop unit command:");
+ for (k = 0; k < (int)sizeof(ssuBlk); ++k)
+ fprintf (stderr, " %02x", ssuBlk[k]);
+ fprintf(stderr, "\n");
+ }
+ io_hdr.interface_id = 'S';
+ io_hdr.cmd_len = sizeof(ssuBlk);
+ io_hdr.mx_sb_len = sizeof(sense_b);
+ io_hdr.dxfer_direction = SG_DXFER_NONE;
+ io_hdr.dxfer_len = 0;
+ io_hdr.dxferp = NULL;
+ io_hdr.cmdp = ssuBlk;
+ io_hdr.sbp = sense_b;
+ io_hdr.timeout = START_TIMEOUT;
+
+ if (ioctl(sg_fd, SG_IO, &io_hdr) < 0) {
+ if (verbose)
+ fprintf(sg_warnings_str, "start_stop_unit (SG_IO) error:"
+ " %s\n", safe_strerror(errno));
+ return -1;
+ }
+ if (verbose > 2)
+ fprintf(sg_warnings_str, " duration=%u ms\n", io_hdr.duration);
+ res = sg_err_category3(&io_hdr);
+ switch (res) {
+ case SG_LIB_CAT_RECOVERED:
+ if (verbose)
+ sg_chk_n_print3("Start stop unit", &io_hdr, verbose);
+ /* fall through */
+ case SG_LIB_CAT_CLEAN:
+ return 0;
+ case SG_LIB_CAT_INVALID_OP:
+ case SG_LIB_CAT_ILLEGAL_REQ:
+ if (verbose > 1)
+ sg_chk_n_print3("START STOP UNIT", &io_hdr, 1);
+ return res;
+ default:
+ if (noisy || verbose)
+ sg_chk_n_print3("START STOP UNIT command error", &io_hdr,
+ verbose);
+ return -1;
+ }
+}
+
+/* Invokes a SCSI PREVENT ALLOW MEDIUM REMOVAL command (SPC-3)
+ * prevent==0 allows removal, prevent==1 prevents removal ...
+ * Return of 0 -> success,
+ * SG_LIB_CAT_INVALID_OP -> command not supported
+ * SG_LIB_CAT_ILLEGAL_REQ -> bad field in cdb, -1 -> other failure */
+int sg_ll_prevent_allow(int sg_fd, int prevent, int noisy, int verbose)
+{
+ int k, res;
+ unsigned char pCmdBlk[PREVENT_ALLOW_CMDLEN] =
+ {PREVENT_ALLOW_CMD, 0, 0, 0, 0, 0};
+ unsigned char sense_b[SENSE_BUFF_LEN];
+ struct sg_io_hdr io_hdr;
+
+ if (NULL == sg_warnings_str)
+ sg_warnings_str = stderr;
+ if ((prevent < 0) || (prevent > 3)) {
+ fprintf(sg_warnings_str, "prevent argument should be 0, 1, 2 or 3\n");
+ return -1;
+ }
+ pCmdBlk[4] |= (prevent & 0x3);
+ if (verbose) {
+ fprintf(sg_warnings_str, " Prevent allow medium removal cdb: ");
+ for (k = 0; k < PREVENT_ALLOW_CMDLEN; ++k)
+ fprintf(sg_warnings_str, "%02x ", pCmdBlk[k]);
+ fprintf(sg_warnings_str, "\n");
+ }
+
+ memset(&io_hdr, 0, sizeof(struct sg_io_hdr));
+ io_hdr.interface_id = 'S';
+ io_hdr.cmd_len = PREVENT_ALLOW_CMDLEN;
+ io_hdr.mx_sb_len = sizeof(sense_b);
+ io_hdr.dxfer_direction = SG_DXFER_NONE;
+ io_hdr.dxfer_len = 0;
+ io_hdr.dxferp = NULL;
+ io_hdr.cmdp = pCmdBlk;
+ io_hdr.sbp = sense_b;
+ io_hdr.timeout = DEF_TIMEOUT;
+
+ if (ioctl(sg_fd, SG_IO, &io_hdr) < 0) {
+ fprintf(sg_warnings_str, "prevent allow medium removal SG_IO "
+ "error: %s\n", safe_strerror(errno));
+ return -1;
+ }
+ res = sg_err_category3(&io_hdr);
+ switch (res) {
+ case SG_LIB_CAT_RECOVERED:
+ if (verbose)
+ sg_chk_n_print3("Prevent allow medium removal", &io_hdr, verbose);
+ /* fall through */
+ case SG_LIB_CAT_CLEAN:
+ return 0;
+ case SG_LIB_CAT_INVALID_OP:
+ case SG_LIB_CAT_ILLEGAL_REQ:
+ if (verbose > 1)
+ sg_chk_n_print3("Prevent allow medium removal command problem",
+ &io_hdr, 1);
+ return res;
+ default:
+ if (noisy || verbose)
+ sg_chk_n_print3("Prevent allow medium removal command problem",
+ &io_hdr, verbose);
+ return -1;
+ }
+}
+
+/* Invokes a SCSI REPORT DEVICE IDENTIFIER command. Return of 0 -> success,
+ * SG_LIB_CAT_INVALID_OP -> Read media serial number not supported,
+ * SG_LIB_CAT_ILLEGAL_REQ -> bad field in cdb, -1 -> other failure */
+int sg_ll_report_dev_id(int sg_fd, void * resp, int mx_resp_len,
+ int noisy, int verbose)
+{
+ int k, res;
+ unsigned char rdiCmdBlk[MAINTENANCE_IN_CMDLEN] =
+ {MAINTENANCE_IN_CMD, REPORT_DEVICE_IDENTIFIER_SA,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+ unsigned char sense_b[SENSE_BUFF_LEN];
+ struct sg_io_hdr io_hdr;
+
+ rdiCmdBlk[6] = (mx_resp_len >> 24) & 0xff;
+ rdiCmdBlk[7] = (mx_resp_len >> 16) & 0xff;
+ rdiCmdBlk[8] = (mx_resp_len >> 8) & 0xff;
+ rdiCmdBlk[9] = mx_resp_len & 0xff;
+ if (NULL == sg_warnings_str)
+ sg_warnings_str = stderr;
+ if (verbose) {
+ fprintf(sg_warnings_str, " Report device identifier cdb: ");
+ for (k = 0; k < MAINTENANCE_IN_CMDLEN; ++k)
+ fprintf(sg_warnings_str, "%02x ", rdiCmdBlk[k]);
+ fprintf(sg_warnings_str, "\n");
+ }
+ memset(&io_hdr, 0, sizeof(struct sg_io_hdr));
+ memset(sense_b, 0, sizeof(sense_b));
+ io_hdr.interface_id = 'S';
+ io_hdr.cmd_len = sizeof(rdiCmdBlk);
+ io_hdr.mx_sb_len = sizeof(sense_b);
+ io_hdr.dxfer_direction = SG_DXFER_FROM_DEV;
+ io_hdr.dxfer_len = mx_resp_len;
+ io_hdr.dxferp = resp;
+ io_hdr.cmdp = rdiCmdBlk;
+ io_hdr.sbp = sense_b;
+ io_hdr.timeout = DEF_TIMEOUT;
+
+ if (ioctl(sg_fd, SG_IO, &io_hdr) < 0) {
+ if (noisy || verbose)
+ fprintf(sg_warnings_str, "report_device_idenifier (SG_IO) error:"
+ " %s\n", safe_strerror(errno));
+ return -1;
+ }
+ if (verbose > 2)
+ fprintf(sg_warnings_str, " duration=%u ms\n", io_hdr.duration);
+ res = sg_err_category3(&io_hdr);
+ switch (res) {
+ case SG_LIB_CAT_RECOVERED:
+ if (noisy || verbose)
+ sg_chk_n_print3("Report device identifier", &io_hdr, verbose);
+ /* fall through */
+ case SG_LIB_CAT_CLEAN:
+ if (verbose && io_hdr.resid)
+ fprintf(sg_warnings_str, " report_device_identifier: resid=%d ("
+ "got %d bytes)\n", io_hdr.resid,
+ io_hdr.dxfer_len - io_hdr.resid);
+ if (verbose > 2) {
+ k = mx_resp_len - io_hdr.resid;
+ if (k > 0) {
+ fprintf(sg_warnings_str, " report device identifier: "
+ "response%s\n", (k > 256 ? ", first 256 bytes" : ""));
+ dStrHex(resp, (k > 256 ? 256 : k), -1);
+ }
+ }
+ return 0;
+ case SG_LIB_CAT_INVALID_OP:
+ case SG_LIB_CAT_ILLEGAL_REQ:
+ if (verbose > 1)
+ sg_chk_n_print3("REPORT DEVICE IDENTIFIER", &io_hdr, 1);
+ return res;
+ default:
+ if (noisy || verbose)
+ sg_chk_n_print3("REPORT DEVICE IDENTIFIER command error",
+ &io_hdr, verbose);
+ return -1;
+ }
+}
+
+/* Invokes a SCSI SET DEVICE IDENTIFIER command. Return of 0 -> success,
+ * SG_LIB_CAT_INVALID_OP -> Read media serial number not supported,
+ * SG_LIB_CAT_ILLEGAL_REQ -> bad field in cdb, -1 -> other failure */
+int sg_ll_set_dev_id(int sg_fd, void * paramp, int param_len,
+ int noisy, int verbose)
+{
+ int k, res;
+ unsigned char sdiCmdBlk[MAINTENANCE_OUT_CMDLEN] =
+ {MAINTENANCE_OUT_CMD, SET_DEVICE_IDENTIFIER_SA,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+ unsigned char sense_b[SENSE_BUFF_LEN];
+ struct sg_io_hdr io_hdr;
+
+ sdiCmdBlk[6] = (param_len >> 24) & 0xff;
+ sdiCmdBlk[7] = (param_len >> 16) & 0xff;
+ sdiCmdBlk[8] = (param_len >> 8) & 0xff;
+ sdiCmdBlk[9] = param_len & 0xff;
+ if (NULL == sg_warnings_str)
+ sg_warnings_str = stderr;
+ if (verbose) {
+ fprintf(sg_warnings_str, " Set device identifier cdb: ");
+ for (k = 0; k < MAINTENANCE_OUT_CMDLEN; ++k)
+ fprintf(sg_warnings_str, "%02x ", sdiCmdBlk[k]);
+ fprintf(sg_warnings_str, "\n");
+ if ((verbose > 1) && paramp && param_len) {
+ fprintf(sg_warnings_str, " Set device identifier parameter "
+ "block:\n");
+ dStrHex(paramp, param_len, -1);
+ }
+ }
+ memset(&io_hdr, 0, sizeof(struct sg_io_hdr));
+ memset(sense_b, 0, sizeof(sense_b));
+ io_hdr.interface_id = 'S';
+ io_hdr.cmd_len = sizeof(sdiCmdBlk);
+ io_hdr.mx_sb_len = sizeof(sense_b);
+ io_hdr.dxfer_direction = SG_DXFER_TO_DEV;
+ io_hdr.dxfer_len = param_len;
+ io_hdr.dxferp = paramp;
+ io_hdr.cmdp = sdiCmdBlk;
+ io_hdr.sbp = sense_b;
+ io_hdr.timeout = DEF_TIMEOUT;
+
+ if (ioctl(sg_fd, SG_IO, &io_hdr) < 0) {
+ if (noisy || verbose)
+ fprintf(sg_warnings_str, "set_device_idenifier (SG_IO) error:"
+ " %s\n", safe_strerror(errno));
+ return -1;
+ }
+ if (verbose > 2)
+ fprintf(sg_warnings_str, " duration=%u ms\n", io_hdr.duration);
+ res = sg_err_category3(&io_hdr);
+ switch (res) {
+ case SG_LIB_CAT_RECOVERED:
+ if (noisy || verbose)
+ sg_chk_n_print3("Set device identifier", &io_hdr, verbose);
+ /* fall through */
+ case SG_LIB_CAT_CLEAN:
+ return 0;
+ case SG_LIB_CAT_INVALID_OP:
+ case SG_LIB_CAT_ILLEGAL_REQ:
+ if (verbose > 1)
+ sg_chk_n_print3("SET DEVICE IDENTIFIER", &io_hdr, 1);
+ return res;
+ default:
+ if (noisy || verbose)
+ sg_chk_n_print3("SET DEVICE IDENTIFIER command error",
+ &io_hdr, verbose);
return -1;
}
}
diff --git a/sg_cmds.h b/sg_cmds.h
index c8816c83..e8340394 100644
--- a/sg_cmds.h
+++ b/sg_cmds.h
@@ -31,10 +31,12 @@ extern int sg_ll_mode_sense10(int sg_fd, int llbaa, int dbd, int pc,
int mx_resp_len, int noisy, int verbose);
extern int sg_ll_readcap_10(int sg_fd, int pmi, unsigned int lba,
- void * resp, int mx_resp_len, int verbose);
+ void * resp, int mx_resp_len, int noisy,
+ int verbose);
extern int sg_ll_readcap_16(int sg_fd, int pmi, unsigned long long llba,
- void * resp, int mx_resp_len, int verbose);
+ void * resp, int mx_resp_len, int noisy,
+ int verbose);
extern int sg_ll_read_defect10(int sg_fd, int req_plist, int req_glist,
int dl_format, void * resp, int mx_resp_len,
@@ -54,7 +56,7 @@ extern int sg_ll_report_tgt_prt_grp(int sg_fd, void * resp,
int mx_resp_len, int noisy, int verbose);
extern int sg_ll_request_sense(int sg_fd, int desc, void * resp,
- int mx_resp_len, int verbose);
+ int mx_resp_len, int noisy, int verbose);
extern int sg_ll_send_diag(int sg_fd, int sf_code, int pf_bit, int sf_bit,
int devofl_bit, int unitofl_bit, int long_duration,
@@ -68,6 +70,18 @@ extern int sg_ll_sync_cache_10(int sg_fd, int sync_nv, int immed, int group,
extern int sg_ll_test_unit_ready(int sg_fd, int pack_id, int noisy,
int verbose);
+extern int sg_ll_start_stop_unit(int sg_fd, int immed, int power_cond,
+ int loej, int start, int noisy, int verbose);
+
+extern int sg_ll_prevent_allow(int sg_fd, int prevent, int noisy,
+ int verbose);
+
+extern int sg_ll_report_dev_id(int sg_fd, void * resp, int max_resp_len,
+ int noisy, int verbose);
+
+extern int sg_ll_set_dev_id(int sg_fd, void * paramp, int param_len,
+ int noisy, int verbose);
+
struct sg_simple_inquiry_resp {
unsigned char peripheral_qualifier;
diff --git a/sg_dd.8 b/sg_dd.8
index deec14ef..3e7888f7 100644
--- a/sg_dd.8
+++ b/sg_dd.8
@@ -1,4 +1,4 @@
-.TH SG_DD "8" "April 2005" "sg3_utils-1.14" SG3_UTILS
+.TH SG_DD "8" "August 2005" "sg3_utils-1.16" SG3_UTILS
.SH NAME
sg_dd \- copies data to and from files and devices. Specialised for
devices that understand the SCSI command set.
@@ -44,12 +44,14 @@ is directly to the underlying device). Default is 0.
.TP
bpt=BLOCKS
each IO transaction will be made using this number of blocks (or less if
-near the end of count). Default is 128. So for bs=512 the reads and writes
+near the end of count). Default is 128 for block sizes less that 2048
+bytes, otherwise the default is 32. So for bs=512 the reads and writes
will each convey 64 KiB of data by default (less if near the end of the
transfer or memory restrictions). When cd/dvd drives are accessed, the
-block size is typically 2048 bytes and the default bpt value may be too
-high, especially when blk_sgio is set. The solution is to reduce the bpt
-value (64 or 32 may be more appropriate).
+block size is typically 2048 bytes and bpt defaults to 32 which again
+implies 64 KiB transfers. The block layer when the blk_sgio=1 option
+is used has relatively low upper limits for transfer sizes (compared
+to sg device nodes).
.TP
bs=BYTES
this
@@ -150,7 +152,11 @@ A value of 1 reports extra information that is not repetitive. A value
2 reports cdbs and responses for SCSI commands that are not repetitive
(i.e. other that READ and WRITE). Error processing is not considered
repetitive. Values of 3 and 4 yield output for all SCSI commands (and
-Unix read() and write() calls).
+Unix read() and write() calls) so there can be a lot of output.
+Non-zero verbose settings result in some caching mode page and read write
+error recovery mode page information being output prior to the copy.
+This only occurs for scsi generic (sg) devices and block devices when
+the 'blk_sgio=1' option is set.
.TP
--version
outputs version number information and exits
@@ -280,5 +286,9 @@ The lmbench package contains
.B lmdd
which is also interesting. For moving data to and from tapes see
.B dt
-which is found at http://www.bit-net.com/~rmiller/dt.html. See also
+which is found at http://www.scsifaq.org/RMiller_Tools/index.html
+To change mode parameters that effect SCSI devices caching and error
+recovery see
+.B sdparm
+See also
.B raw(8), dd(1)
diff --git a/sg_dd.c b/sg_dd.c
index 8b348002..1773f3db 100644
--- a/sg_dd.c
+++ b/sg_dd.c
@@ -49,7 +49,7 @@
This version is designed for the linux kernel 2.4 and 2.6 series.
*/
-static char * version_str = "5.41 20050523";
+static char * version_str = "5.42 20050807";
#define ME "sg_dd: "
@@ -61,6 +61,7 @@ static char * version_str = "5.41 20050523";
#define DEF_BLOCK_SIZE 512
#define DEF_BLOCKS_PER_TRANSFER 128
+#define DEF_BLOCKS_PER_2048TRANSFER 32
#define DEF_SCSI_CDBSZ 10
#define MAX_SCSI_CDBSZ 16
@@ -233,7 +234,8 @@ static void usage()
" where:\n"
" append 1->append output to normal <ofile>, (default is 0)\n"
" blk_sgio 0->block device use normal I/O(def), 1->use SG_IO\n"
- " bpt is blocks_per_transfer (default is 128)\n"
+ " bpt is blocks_per_transfer (default is 128 or 32 when bs="
+ "2048)\n"
" bs block size (default is 512)\n");
fprintf(stderr,
" cdbsz size of SCSI READ or WRITE command (default is 10)\n"
@@ -269,7 +271,7 @@ static int scsi_read_capacity(int sg_fd, long long * num_sect, int * sect_sz)
int verb;
verb = (verbose ? verbose - 1: 0);
- res = sg_ll_readcap_10(sg_fd, 0, 0, rcBuff, READ_CAP_REPLY_LEN, verb);
+ res = sg_ll_readcap_10(sg_fd, 0, 0, rcBuff, READ_CAP_REPLY_LEN, 0, verb);
if (0 != res)
return res;
@@ -277,7 +279,8 @@ static int scsi_read_capacity(int sg_fd, long long * num_sect, int * sect_sz)
(0xff == rcBuff[3])) {
long long ls;
- res = sg_ll_readcap_16(sg_fd, 0, 0, rcBuff, RCAP16_REPLY_LEN, verb);
+ res = sg_ll_readcap_16(sg_fd, 0, 0, rcBuff, RCAP16_REPLY_LEN, 0,
+ verb);
if (0 != res)
return res;
for (k = 0, ls = 0; k < 8; ++k) {
@@ -438,17 +441,17 @@ static int sg_ll_read_long10(int sg_fd, int correct, unsigned long lba,
res = sg_err_category3(&io_hdr);
switch (res) {
case SG_LIB_CAT_RECOVERED:
- sg_chk_n_print3("READ LONG(10), continuing", &io_hdr);
+ sg_chk_n_print3("READ LONG(10), continuing", &io_hdr, vverbose);
/* fall through */
case SG_LIB_CAT_CLEAN:
return 0;
case SG_LIB_CAT_INVALID_OP:
if (vverbose > 1)
- sg_chk_n_print3("READ LONG(10) command problem", &io_hdr);
+ sg_chk_n_print3("READ LONG(10) command problem", &io_hdr, 1);
return res;
default:
if (vverbose > 1)
- sg_chk_n_print3("READ LONG(10) sense", &io_hdr);
+ sg_chk_n_print3("READ LONG(10) sense", &io_hdr, 1);
if ((sg_normalize_sense(&io_hdr, &ssh)) &&
(ssh.sense_key == ILLEGAL_REQUEST) &&
((offset = info_offset(io_hdr.sbp, io_hdr.sb_len_wr)))) {
@@ -617,20 +620,20 @@ static int sg_read_low(int sg_fd, unsigned char * buff, int blocks,
fprintf(stderr, " lba of last recovered error in this "
"READ=0x%llx\n", *io_addrp);
if (verbose > 1)
- sg_chk_n_print3("reading", &io_hdr);
+ sg_chk_n_print3("reading", &io_hdr, 1);
} else {
fprintf(stderr, "Recovered error: [no info] reading from "
"block=0x%llx, num=%d\n", from_block, blocks);
- sg_chk_n_print3("reading", &io_hdr);
+ sg_chk_n_print3("reading", &io_hdr, verbose);
}
break;
case SG_LIB_CAT_MEDIA_CHANGED:
if (verbose > 1)
- sg_chk_n_print3("reading", &io_hdr);
+ sg_chk_n_print3("reading", &io_hdr, 1);
return 2;
case SG_LIB_CAT_MEDIUM_HARD:
if (verbose > 1)
- sg_chk_n_print3("reading", &io_hdr);
+ sg_chk_n_print3("reading", &io_hdr, 1);
++unrecovered_errs;
info_valid = sg_get_sense_info_fld(io_hdr.sbp, io_hdr.sb_len_wr,
io_addrp);
@@ -644,7 +647,7 @@ static int sg_read_low(int sg_fd, unsigned char * buff, int blocks,
break;
default:
++unrecovered_errs;
- sg_chk_n_print3("reading", &io_hdr);
+ sg_chk_n_print3("reading", &io_hdr, verbose);
return -1;
}
if (diop && *diop &&
@@ -872,19 +875,19 @@ static int sg_write(int sg_fd, unsigned char * buff, int blocks,
fprintf(stderr, " lba of last recovered error in this "
"WRITE=0x%llx\n", io_addr);
if (verbose > 1)
- sg_chk_n_print3("writing", &io_hdr);
+ sg_chk_n_print3("writing", &io_hdr, 1);
} else {
fprintf(stderr, "Recovered error: [no info] writing to "
"block=0x%llx, num=%d\n", to_block, blocks);
- sg_chk_n_print3("writing", &io_hdr);
+ sg_chk_n_print3("writing", &io_hdr, verbose);
}
break;
case SG_LIB_CAT_MEDIA_CHANGED:
if (verbose > 1)
- sg_chk_n_print3("writing", &io_hdr);
+ sg_chk_n_print3("writing", &io_hdr, 1);
return -3;
default:
- sg_chk_n_print3("writing", &io_hdr);
+ sg_chk_n_print3("writing", &io_hdr, verbose);
if (do_coe) {
fprintf(stderr, ">> ignored errors for out blk=%lld for "
"%d bytes\n", to_block, bs * blocks);
@@ -935,7 +938,7 @@ static void print_mp_bit(const char * pre, int smask, int byte_off,
if (smask & 0xe) {
fprintf(stderr, " [");
if (smask & 2) {
- fprintf(stderr, "Changeable: %s",
+ fprintf(stderr, "cha: %s",
(cha_mp[byte_off] & bit_mask) ? "y" : "n");
sep = 1;
}
@@ -945,7 +948,7 @@ static void print_mp_bit(const char * pre, int smask, int byte_off,
sep = 1;
}
if (smask & 8)
- fprintf(stderr, "%ssaved: %d", (sep ? ", " : " "),
+ fprintf(stderr, "%ssav: %d", (sep ? ", " : " "),
!!(sav_mp[2] & bit_mask));
fprintf(stderr, "]\n");
} else
@@ -1049,6 +1052,7 @@ int main(int argc, char * argv[])
int ibs = 0;
int obs = 0;
int bpt = DEF_BLOCKS_PER_TRANSFER;
+ int bpt_given = 0;
char str[STR_SZ];
char * key;
char * buf;
@@ -1125,6 +1129,7 @@ int main(int argc, char * argv[])
fprintf(stderr, ME "bad argument to 'bpt'\n");
return 1;
}
+ bpt_given = 1;
} else if (0 == strcmp(key,"skip")) {
skip = sg_get_llnum(buf);
if (-1LL == skip) {
@@ -1196,6 +1201,11 @@ int main(int argc, char * argv[])
fprintf(stderr, "bpt must be greater than 0\n");
return 1;
}
+ /* defaulting transfer size to 128*2048 for CD/DVDs is too large
+ for the block layer in lk 2.6 and results in an EIO on the
+ SG_IO ioctl. So reduce it in that case. */
+ if ((blk_sz >= 2048) && (0 == bpt_given))
+ bpt = DEF_BLOCKS_PER_2048TRANSFER;
#ifdef SG_DEBUG
fprintf(stderr, ME "if=%s skip=%lld of=%s seek=%lld count=%lld\n",
inf, skip, outf, seek, dd_count);
diff --git a/sg_format.8 b/sg_format.8
index 87fcaa52..0d81332d 100644
--- a/sg_format.8
+++ b/sg_format.8
@@ -1,4 +1,4 @@
-.TH SG_FORMAT "8" "May 2005" "sg3_utils-1.15" SG3_UTILS
+.TH SG_FORMAT "8" "July 2005" "sg3_utils-1.16" SG3_UTILS
.SH NAME
sg_format \- format or resize a SCSI disk (perhaps change its block size)
.SH SYNOPSIS
@@ -230,6 +230,10 @@ information (e.g. the PROTECT bit) and to fetch the extended INQUIRY
VPD page (e.g. RTO and GRD_CHK bits). The sdparm (or sginfo) utility can be
used to access and potentially change the now obsolete format mode page.
.PP
+scsiformat is another utility available for formatting SCSI disks
+with linux. It dates from 1997 (most recent update) and may be useful for
+disks whose firmware is of that vintage.
+.PP
The argument to "--count" is a number which may be followed by one of
these multiplicative suffixes: c C *1; w W *2; b B *512; k K KiB *1,024;
KB *1,000; m M MiB *1,048,576; MB *1,000,000 . This pattern continues
@@ -283,4 +287,4 @@ 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_turs, sg_requests, sg_inq, sg_modes, sginfo, sg_wr_mode
-.B (all in sg3_utils), sdparm
+.B (all in sg3_utils), sdparm, scsiformat
diff --git a/sg_format.c b/sg_format.c
index 25d0f94b..7e3761d2 100644
--- a/sg_format.c
+++ b/sg_format.c
@@ -67,7 +67,7 @@ static unsigned char sbuff[MAX_SENSE_SZ];
#define MAX_BUFF_SZ 252
static unsigned char dbuff[MAX_BUFF_SZ];
-static char * version_str = "1.04 20050511";
+static char * version_str = "1.05 20050808";
static struct option long_options[] = {
{"count", 1, 0, 'c'},
@@ -177,23 +177,23 @@ scsi_format(int fd, int pinfo, int rto_req, int immed, int early, int verbose)
res = sg_err_category3(&io_hdr);
switch (res) {
case SG_LIB_CAT_RECOVERED:
- sg_chk_n_print3("Format, continuing", &io_hdr);
+ sg_chk_n_print3("Format, continuing", &io_hdr, verbose);
/* fall through */
case SG_LIB_CAT_CLEAN:
break;
case SG_LIB_CAT_INVALID_OP:
fprintf(stderr, "Format command not supported\n");
if (verbose > 1)
- sg_chk_n_print3("Format", &io_hdr);
+ sg_chk_n_print3("Format", &io_hdr, 1);
return -1;
case SG_LIB_CAT_ILLEGAL_REQ:
fprintf(stderr, "Format command illegal parameter\n");
if (verbose > 1)
- sg_chk_n_print3("Format", &io_hdr);
+ sg_chk_n_print3("Format", &io_hdr, 1);
return -1;
default:
if (verbose > 1)
- sg_chk_n_print3("Format", &io_hdr);
+ sg_chk_n_print3("Format", &io_hdr, 1);
return -1;
}
if (! immed)
@@ -251,11 +251,11 @@ scsi_format(int fd, int pinfo, int rto_req, int immed, int early, int verbose)
progress * 100 / 65536);
if (verbose > 1)
sg_print_sense("tur", sbuff,
- io_hdr.sb_len_wr);
+ io_hdr.sb_len_wr, 1);
continue;
} else {
sg_print_sense("tur: unexpected sense", sbuff,
- io_hdr.sb_len_wr);
+ io_hdr.sb_len_wr, verbose);
continue;
}
} else
@@ -277,7 +277,7 @@ print_read_cap(int fd, int do_16, int verbose)
if (do_16) {
res = sg_ll_readcap_16(fd, 0 /* pmi */, 0 /* llba */,
- resp_buff, 32, verbose);
+ resp_buff, 32, 0, verbose);
if (0 == res) {
for (k = 0, llast_blk_addr = 0; k < 8; ++k) {
llast_blk_addr <<= 8;
@@ -298,7 +298,7 @@ print_read_cap(int fd, int do_16, int verbose)
}
} else {
res = sg_ll_readcap_10(fd, 0 /* pmi */, 0 /* lba */,
- resp_buff, 8, verbose);
+ resp_buff, 8, 0, verbose);
if (0 == res) {
last_blk_addr = ((resp_buff[0] << 24) |
(resp_buff[1] << 16) |
@@ -364,8 +364,9 @@ static void usage()
" --version | -V print version details and exit\n"
" --wait | -w format command waits till complete (def: "
"poll)\n\n"
- "\tExample: sg_format --format /dev/sdc\n");
- printf("\nWARNING: This program will destroy all the data on the "
+ "\tExample: sg_format --format /dev/sdc\n\n"
+ "This utility formats or resizes SCSI disks.\n");
+ printf("WARNING: This utility will destroy all the data on the "
"target device when\n\t '--format' is given. Check that you "
"have the correct device.\n");
}
@@ -559,6 +560,9 @@ int main(int argc, char **argv)
} else
fprintf(stderr, "MODE SENSE (%d) command failed\n",
(mode6 ? 6 : 10));
+ if (0 == verbose)
+ fprintf(stderr, " try '-v' for more "
+ "information\n");
goto out;
}
if (mode6) {
@@ -701,6 +705,9 @@ int main(int argc, char **argv)
else
fprintf(stderr, "MODE SELECT (%d) command "
"failed\n", (mode6 ? 6 : 10));
+ if (0 == verbose)
+ fprintf(stderr, " try '-v' for "
+ "more information\n");
goto out;
}
}
@@ -734,7 +741,14 @@ int main(int argc, char **argv)
printf(" ALL data on %s will be DESTROYED\n", device_name);
printf(" Press control-C to abort\n");
sleep(5);
- scsi_format(fd, pinfo, rto_req, ! fwait, early, verbose);
+ res = scsi_format(fd, pinfo, rto_req, ! fwait, early,
+ verbose);
+ if (res) {
+ fprintf(stderr, "FORMAT failed\n");
+ if (0 == verbose)
+ fprintf(stderr, " try '-v' for more "
+ "information\n");
+ }
#else
fprintf(stderr, "FORMAT ignored, testing\n");
#endif
diff --git a/sg_get_config.8 b/sg_get_config.8
index 02d8f0f1..559fbba4 100644
--- a/sg_get_config.8
+++ b/sg_get_config.8
@@ -1,11 +1,11 @@
-.TH SG_GET_CONFIG "8" "February 2005" "sg3_utils-1.13" SG3_UTILS
+.TH SG_GET_CONFIG "8" "August 2005" "sg3_utils-1.16" SG3_UTILS
.SH NAME
sg_get_config \- invoke SCSI GET CONFIGURATION command on a (cd/dvd) device
.SH SYNOPSIS
.B sg_get_config
-[\fI--brief\fR] [\fI--help\fR] [\fI--hex\fR] [\fI--inner-hex\fR]
-[\fI--list\fR] [\fI--rt=<n>\fR] [\fI--starting=<n>\fR] [\fI--verbose\fR]
-[\fI--version\fR] \fI<device>\fR
+[\fI--brief\fR] [\fI--current\fR] [\fI--help\fR] [\fI--hex\fR]
+[\fI--inner-hex\fR] [\fI--list\fR] [\fI--rt=<n>\fR] [\fI--starting=<n>\fR]
+[\fI--verbose\fR] [\fI--version\fR] \fI<device>\fR
.SH DESCRIPTION
.\" Add any additional description here
.PP
@@ -15,7 +15,7 @@ of the device. Typically these devices are CD and DVD players that
may (but not necessarily) have media in them. These devices may well
be connected via ATAPI, USB or IEEE 1394 transports. In such
cases they are "SCSI" devices only in the sense that they use
-the "Multi-Media command set" (MMC). MMC is a specialized SCSI
+the "Multi-Media command" set (MMC). MMC is a specialized SCSI
command set whose definition can be found at http://www.t10.org .
.PP
This utility is based on the MMC-4 and MMC-5 draft standards. See
@@ -28,7 +28,7 @@ output from this utility can be large. There are various ways to cut down
the output. If the '--brief' option is used only the feature names are shown
and the feature parameters are not decoded. Alternatively if only one
feature is of interest then this combination of options is
-appropriate: "--rt=2 --starting=<feature_code>". Another possibility it to
+appropriate: "--rt=2 --starting=<feature_code>". Another possibility is to
show only the features that are relevant to the media in the
drive (i.e. "current") with the "--rt=1" option.
.TP
@@ -37,6 +37,9 @@ show the feature names but don't decode the parameters of those features.
When used with '--list' outputs known feature names but not known profile
names.
.TP
+--current | -c
+output features marked as current. This option is equivalent to '--rt=1'.
+.TP
--help | -h
output the usage message then exit.
.TP
@@ -49,19 +52,19 @@ decode to the feature name level then output each feature's data in hex.
--list | -l
list all known feature and profile names. Ignore the device name (if given).
Simply lists the feature names and profiles (followed by their hex values)
-that this utility knows about. If --brief is also given then only list
-feature names.
+that this utility knows about. If '--brief' is also given then only feature
+names are listed.
.TP
--rt=<n> | -r <n>
RT value given to GET CONFIGURATION command. Allowable values are 0,
1, 2, or 3 . The command's action also depends on the value given
-to --starting. The default value is 0.
+to '--starting='. The default value is 0.
When <n> is 0 then all features, regardless of currency, are returned (whose
-feature code is greater than or equal to the value given to --starting).
+feature code is greater than or equal to the value given to '--starting=').
When <n> is 1 then all current features are returned (whose
-feature code is greater than or equal to the value given to --starting).
+feature code is greater than or equal to the value given to '--starting=').
When <n> is 2 then the feature whose feature code is equal to the value
-given to --starting, if any, is returned.
+given to '--starting=', if any, is returned.
When <n> is 3 the response is reserved (probably yields an "illegal
field in cdb" error).
.TP
@@ -79,18 +82,18 @@ print the version string and then exit.
There are multiple versions of the MMC (draft) standards: MMC [1997],
MMC-2 [2000], MMC-3 [2002], MMC-4 and MMC-5. The first three are now
ANSI INCITS standards with the year they became standards shown in
-brackets. Luckily the draft immediately prior to standardization can
+brackets. The draft immediately prior to standardization can
be found at http://www.t10.org . In the initial MMC standard there
was no GET CONFIGURATION command and the relevant information was
obtained from the "CD capabilities and mechanical status mode
-page" (page 0x2a). It was later renamed the "MM capabilities and
+page" (mode page 0x2a). It was later renamed the "MM capabilities and
mechanical status mode page" and has been made obsolete in MMC-4 and
MMC-5. The GET CONFIGURATION command was introduced in MMC-2 and has
-become a replacement for the mode page. New features such as support
+become a replacement for that mode page. New features such as support
for "BD" (blue ray) media type can only be found by using the
GET CONFIGURATION command. Hence older CD players may not support
the GET CONFIGURATION command in which case the "MM capabilities ..."
-mode page can be checked with sginfo or sg_modes.
+mode page can be checked with sdpar, sginfo or sg_modes.
.PP
In the 2.4 series of Linux kernels the given device must be
a SCSI generic (sg) device. In the 2.6 series block devices
@@ -109,3 +112,4 @@ This software is distributed under a FreeBSD license. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
.SH "SEE ALSO"
.B sginfo, sg_modes, sg_inq, sg_prevent, sg_start (all in sg3_utils)
+.B sdparm
diff --git a/sg_get_config.c b/sg_get_config.c
index 5e7f37df..971e1dc3 100644
--- a/sg_get_config.c
+++ b/sg_get_config.c
@@ -49,7 +49,7 @@
*/
-static char * version_str = "0.16 20050324";
+static char * version_str = "0.19 20050806";
#define SENSE_BUFF_LEN 32 /* Arbitrary, could be larger */
@@ -71,6 +71,7 @@ static char ebuff[EBUFF_SZ];
static struct option long_options[] = {
{"brief", 0, 0, '1'},
+ {"current", 0, 0, 'c'},
{"help", 0, 0, 'h'},
{"hex", 0, 0, 'H'},
{"inner-hex", 0, 0, 'i'},
@@ -136,7 +137,7 @@ static int sg_ll_get_config(int sg_fd, int rt, int starting, void * resp,
res = sg_err_category3(&io_hdr);
switch (res) {
case SG_LIB_CAT_RECOVERED:
- sg_chk_n_print3("Get config, continuing", &io_hdr);
+ sg_chk_n_print3("Get config, continuing", &io_hdr, verbose);
/* fall through */
case SG_LIB_CAT_CLEAN:
if (verbose && io_hdr.resid)
@@ -145,13 +146,13 @@ static int sg_ll_get_config(int sg_fd, int rt, int starting, void * resp,
case SG_LIB_CAT_INVALID_OP:
case SG_LIB_CAT_ILLEGAL_REQ:
if (verbose > 1)
- sg_chk_n_print3("get config error", &io_hdr);
+ sg_chk_n_print3("get config error", &io_hdr, 1);
return res;
default:
if (verbose | noisy) {
snprintf(ebuff, EBUFF_SZ, "get config error, rt=%d, "
"starting=0x%x ", rt, starting);
- sg_chk_n_print3(ebuff, &io_hdr);
+ sg_chk_n_print3(ebuff, &io_hdr, verbose);
}
return -1;
}
@@ -160,20 +161,22 @@ static int sg_ll_get_config(int sg_fd, int rt, int starting, void * resp,
static void usage()
{
fprintf(stderr,
- "Usage: 'sg_get_config [--brief] [--help] [--hex] [--inner-hex] "
- "[--list]\n"
- " [--rt=<num>] [--starting=<num>] "
+ "Usage: 'sg_get_config [--brief] [--current] [--help] [--hex] "
+ "[--inner-hex]\n"
+ " [--list] [--rt=<num>] [--starting=<num>] "
"[--verbose]\n"
" [--version] <device>'\n"
" where --brief | -b only give feature names of <device> "
"(don't decode)\n"
" --help | -h output usage message\n"
+ " --current | -c equivalent to '--rt=1' (show "
+ "current)\n"
" --hex | -H output response in hex\n"
" --inner-hex | -i decode to feature name, then output "
"features in hex\n"
" --list | -l list all known features + profiles "
"(ignore <device>)\n"
- " --rt=<num> | -r <num>\n"
+ " --rt=<num> | -r <num> default value is 0\n"
" 0 -> all feature descriptors (regardless "
"of currency)\n"
" 1 -> all current feature descriptors\n"
@@ -182,7 +185,8 @@ static void usage()
" --starting=<num> | -s <num> starting from feature "
"<num>\n"
" --verbose | -v verbose\n"
- " --version | -V output version string\n");
+ " --version | -V output version string\n\n"
+ "Get configuration information for MMC drive and/or media\n");
}
static const char * scsi_ptype_strs[] = {
@@ -245,6 +249,7 @@ static struct code_desc profile_desc_arr[] = {
{0x20, "DDCD-ROM"},
{0x21, "DDCD-R"},
{0x22, "DDCD-RW"},
+ {0x2a, "DVD+RW double layer"},
{0x2b, "DVD+R double layer"},
{0x40, "BD-ROM"},
{0x41, "BD-R sequential recording (SRM)"},
@@ -300,6 +305,7 @@ static struct code_desc feature_desc_arr[] = {
{0x33, "Layer jump recording"},
{0x37, "CD-RW media write support"},
{0x38, "BD-R pseudo-overwrite (POW)"},
+ {0x3a, "DVD+RW double layer"},
{0x3b, "DVD+R double layer"},
{0x40, "BD read"},
{0x41, "BD write"},
@@ -633,6 +639,17 @@ static void decode_feature(int feature, unsigned char * ucp, int len)
}
printf(" CD-RW media sub-type support (bitmask)=0x%x\n", ucp[5]);
break;
+ case 0x3a: /* DVD+RW double layer */
+ printf(" version=%d, persist=%d, current=%d [0x%x]\n",
+ ((ucp[2] >> 2) & 0xf), !!(ucp[2] & 0x2), !!(ucp[2] & 0x1),
+ feature);
+ if (len < 8) {
+ printf(" additional length [%d] too short\n", len - 4);
+ break;
+ }
+ printf(" write=%d, quick_start=%d, close_only=%d\n",
+ !!(ucp[4] & 0x1), !!(ucp[5] & 0x2), !!(ucp[5] & 0x1));
+ break;
case 0x3b: /* DVD+R double layer */
printf(" version=%d, persist=%d, current=%d [0x%x]\n",
((ucp[2] >> 2) & 0xf), !!(ucp[2] & 0x2), !!(ucp[2] & 0x1),
@@ -641,7 +658,7 @@ static void decode_feature(int feature, unsigned char * ucp, int len)
printf(" additional length [%d] too short\n", len - 4);
break;
}
- printf(" Write=%d\n", !!(ucp[4] & 0x1));
+ printf(" write=%d\n", !!(ucp[4] & 0x1));
break;
case 0x40: /* BD Read */
printf(" version=%d, persist=%d, current=%d [0x%x]\n",
@@ -905,7 +922,7 @@ int main(int argc, char * argv[])
while (1) {
int option_index = 0;
- c = getopt_long(argc, argv, "bhHilr:s:vV", long_options,
+ c = getopt_long(argc, argv, "bchHilr:s:vV", long_options,
&option_index);
if (c == -1)
break;
@@ -914,6 +931,9 @@ int main(int argc, char * argv[])
case 'b':
brief = 1;
break;
+ case 'c':
+ rt = 1;
+ break;
case 'h':
case '?':
usage();
@@ -1021,8 +1041,11 @@ int main(int argc, char * argv[])
fprintf(stderr, "Get Configuration command not supported\n");
else if (SG_LIB_CAT_ILLEGAL_REQ == res)
fprintf(stderr, "field in Get Configuration command illegal\n");
- else
+ else {
fprintf(stderr, "Get Configuration command failed\n");
+ if (0 == verbose)
+ fprintf(stderr, " try '-v' option for more information\n");
+ }
res = close(sg_fd);
if (res < 0) {
diff --git a/sg_ident.8 b/sg_ident.8
new file mode 100644
index 00000000..f29c3739
--- /dev/null
+++ b/sg_ident.8
@@ -0,0 +1,115 @@
+.TH SG_IDENT "8" "August 2005" "sg3_utils-1.16" SG3_UTILS
+.SH NAME
+sg_ident \- report or set device identifier
+.SH SYNOPSIS
+.B sg_ident
+[\fI--ascii\fR] [\fI--clear\fR] [\fI--help\fR] [\fI--raw\fR]
+[\fI--set\fR] [\fI--verbose\fR] [\fI--version\fR] \fI<scsi_device>\fR
+.SH DESCRIPTION
+.\" Add any additional description here
+.PP
+Send a REPORT DEVICE IDENTIFIER or SET DEVICE IDENTIFIER SCSI command
+to the given device. SCSI devices that support these two commands
+allow users to write (set) an identifier and report it back at some
+later time. The identifier is persistent (i.e. stored on some
+non-volatile medium within the SCSI device that will survive a power
+outage).
+.PP
+Typically the space allocated for the identifier is limited:
+SPC-4 (revision 0) states the maximum length is 512 bytes and
+all devices (that support these commands) shall support lengths
+up to 64 bytes. The author has seen older disks that only support
+16 bytes.
+.PP
+The default action when no options are given is to invoke the
+Report Device Identifier command. Error reports are sent to
+stderr. If no errors occur then the length of the device identifier
+is output (to stdout). This is followed by an ASCII-HEX rendering of
+each byte of the identifier (up to 16 bytes per line) which an ASCII
+representation to the right with dots replacing non printable characters.
+each
+.TP
+--ascii | -A
+invokes the Report Device Identifier command and if anything is
+found interprets it as ASCII (or UTF-8 depending on the environment)
+and prints the identifier to stdout.
+.TP
+--clear | -C
+invokes the Set Device Identifier command with an identifier length
+of zero. This has the effect of clearing the existing device
+identifier.
+.TP
+--help | -h
+output the usage message then exit.
+.TP
+--raw | -r
+invokes the Report Device Identifier command and if anything is found
+sends the identifier (which may be binary) to stdout. Nothing else
+is sent to stdout however error reports are sent to stderr.
+.TP
+--set | -S
+first read stdin until an EOF is detected then invokes the Set Device
+Identifier command to set what has been fetched from stdin as the
+device identifier. The amount of data read must be between 1 and
+512 bytes length (inclusive).
+.TP
+--verbose | -v
+increase the level of verbosity, (i.e. debug output).
+.TP
+--version | -V
+print the version string and then exit.
+.PP
+This utility facilitates users writing their own identifiers to
+their SCSI devices. There are several other types of identifiers
+that the user cannot change. These include the SCSI INQUIRY command
+with its standard vendor and product identification strings and
+the product revision level; plus the large amount of information
+provided by the "Device Identification" VPD page (see sg_inq).
+There is also the READ MEDIA SERIAL NUMBER command (see sg_rmsn).
+The MMC-4 command set for CDs and DVDs has a "media serial number"
+feature (0x109) [and a "logical unit serial number" feature]. These
+can be viewed with sg_get_config.
+.PP
+When this utility succeeds its process exits with a status of 0;
+if problems are encountered the process status is 1 .
+.SH EXAMPLES
+First, to see if there is an existing device identifier whose format
+is unknown, use no options:
+.PP
+ # sg_ident /dev/sdb
+.br
+ Reported device identifier length = 10
+.br
+ Device identifier:
+.br
+ 00 31 32 33 34 35 36 37 38 39 30 1234567890
+.PP
+If it is ASCII then it can printed as such:
+.PP
+ # sg_ident --ascii /dev/sdb
+.br
+ Reported device identifier length = 10
+.br
+ Device identifier:
+.br
+ 1234567890
+.PP
+The device identifier can be copied to a file, cleared and then
+re-asserted with this sequence:
+.PP
+ # sg_ident --raw /dev/sdb > t
+.br
+ # sg_ident --clear /dev/sdb
+.br
+ # cat t | sg_ident --set /dev/sdb
+.SH AUTHORS
+Written by Douglas Gilbert.
+.SH "REPORTING BUGS"
+Report bugs to <dgilbert at interlog dot com>.
+.SH COPYRIGHT
+Copyright \(co 2005 Douglas Gilbert
+.br
+This software is distributed under a FreeBSD license. There is NO
+warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+.SH "SEE ALSO"
+.B sg_inq(sg3_utils), sg_rmsn(sg3_utils), sg_get_config(sg3_utils)
diff --git a/sg_ident.c b/sg_ident.c
new file mode 100644
index 00000000..7ab9229c
--- /dev/null
+++ b/sg_ident.c
@@ -0,0 +1,275 @@
+/*
+ * Copyright (c) 2005 Douglas Gilbert.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ */
+
+#include <unistd.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <getopt.h>
+#include <sys/ioctl.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include "sg_include.h"
+#include "sg_lib.h"
+#include "sg_cmds.h"
+
+/* A utility program for the Linux OS SCSI subsystem.
+ *
+ *
+ * This program issues these SCSI commands: REPORT DEVICE IDENTIFIER,
+ * SET DEVICE IDENTIFIER and/or INQUIRY (VPD=0x83 [device identifier]).
+ */
+
+static char * version_str = "1.00 20050808";
+
+#define ME "sg_ident: "
+
+#define REPORT_DEV_ID_SANITY_LEN 512
+
+
+static struct option long_options[] = {
+ {"ascii", 0, 0, 'A'},
+ {"clear", 0, 0, 'C'},
+ {"help", 0, 0, 'h'},
+ {"raw", 0, 0, 'r'},
+ {"set", 0, 0, 'S'},
+ {"verbose", 0, 0, 'v'},
+ {"version", 0, 0, 'V'},
+ {0, 0, 0, 0},
+};
+
+static void usage()
+{
+ fprintf(stderr, "Usage: "
+ "sg_ident [--ascii] [--clear] [--help] [--raw] [--set] "
+ "[--verbose]\n"
+ " [--version] <scsi_device>\n"
+ " where: --ascii|-A report device identifier as ASCII "
+ "string\n"
+ " --clear|-C clear (set to zero length) device "
+ "identifier\n"
+ " --help|-h print out usage message\n"
+ " --raw|-r output device identifier to stdout\n"
+ " fetch from stdin (when '--set')\n"
+ " --set|-S invoke set device identifier with data "
+ "from stdin\n"
+ " --verbose|-v set device identifier\n"
+ " --version|-V print version string and exit\n\n"
+ "Performs a REPORT or SET DEVICE IDENTIFIER SCSI command\n"
+ );
+}
+
+int main(int argc, char * argv[])
+{
+ int sg_fd, res, c, di_len, n;
+ unsigned char rdi_buff[REPORT_DEV_ID_SANITY_LEN + 4];
+ unsigned char * ucp = NULL;
+ int ascii = 0;
+ int do_clear = 0;
+ int raw = 0;
+ int do_set = 0;
+ int verbose = 0;
+ char device_name[512];
+ int ret = 1;
+
+ memset(device_name, 0, sizeof device_name);
+ while (1) {
+ int option_index = 0;
+
+ c = getopt_long(argc, argv, "AChrSvV", long_options,
+ &option_index);
+ if (c == -1)
+ break;
+
+ switch (c) {
+ case 'A':
+ ascii = 1;
+ break;
+ case 'C':
+ do_clear = 1;
+ break;
+ case 'h':
+ case '?':
+ usage();
+ return 0;
+ case 'r':
+ raw = 1;
+ break;
+ case 'S':
+ do_set = 1;
+ break;
+ case 'v':
+ ++verbose;
+ break;
+ case 'V':
+ fprintf(stderr, ME "version: %s\n", version_str);
+ return 0;
+ default:
+ fprintf(stderr, "unrecognised switch code 0x%x ??\n", c);
+ usage();
+ return 1;
+ }
+ }
+ if (optind < argc) {
+ if ('\0' == device_name[0]) {
+ strncpy(device_name, argv[optind], sizeof(device_name) - 1);
+ device_name[sizeof(device_name) - 1] = '\0';
+ ++optind;
+ }
+ if (optind < argc) {
+ for (; optind < argc; ++optind)
+ fprintf(stderr, "Unexpected extra argument: %s\n",
+ argv[optind]);
+ usage();
+ return 1;
+ }
+ }
+
+ if (0 == device_name[0]) {
+ fprintf(stderr, "missing device name!\n");
+ usage();
+ return 1;
+ }
+ if (do_set && do_clear) {
+ fprintf(stderr, "only one of '--clear' and '--set' can be given\n");
+ usage();
+ return 1;
+ }
+ if (ascii && raw) {
+ fprintf(stderr, "only one of '--ascii' and '--raw' can be given\n");
+ usage();
+ return 1;
+ }
+ if ((do_set || do_clear) && (raw || ascii)) {
+ fprintf(stderr, "'--set' cannot be used with either '--ascii' or "
+ "'--raw'\n");
+ usage();
+ return 1;
+ }
+ sg_fd = open(device_name, O_RDWR | O_NONBLOCK);
+ if (sg_fd < 0) {
+ fprintf(stderr, ME "open error: %s: ", device_name);
+ perror("");
+ return 1;
+ }
+
+ memset(rdi_buff, 0x0, sizeof(rdi_buff));
+ if (do_set || do_clear) {
+ if (do_set) {
+ res = fread(rdi_buff, 1, REPORT_DEV_ID_SANITY_LEN + 2, stdin);
+ if (res <= 0) {
+ fprintf(stderr, "no data read from stdin; to clear "
+ "identifier use '--clear' instead\n");
+ goto err_out;
+ } else if (res > REPORT_DEV_ID_SANITY_LEN) {
+ fprintf(stderr, "SPC-3 limits identifier length to 512 "
+ "bytes\n");
+ goto err_out;
+ }
+ di_len = res;
+ res = sg_ll_set_dev_id(sg_fd, rdi_buff, di_len, 1, verbose);
+ } else /* do_clear */
+ res = sg_ll_set_dev_id(sg_fd, rdi_buff, 0, 1, verbose);
+ if (0 == res)
+ ret = 0;
+ else {
+ if (SG_LIB_CAT_INVALID_OP == res)
+ fprintf(stderr, "Set Device Identifier command not "
+ "supported\n");
+ else if (SG_LIB_CAT_ILLEGAL_REQ == res)
+ fprintf(stderr, "bad field in Set Device Identifier "
+ "cdb\n");
+ else {
+ fprintf(stderr, "Set Device Identifier command failed\n");
+ if (0 == verbose)
+ fprintf(stderr, " try '-v' for more information\n");
+ }
+ }
+ } else { /* do report device identifier */
+ res = sg_ll_report_dev_id(sg_fd, rdi_buff, 4, 1, verbose);
+ if (0 == res) {
+ di_len = (rdi_buff[0] << 24) + (rdi_buff[1] << 16) +
+ (rdi_buff[2] << 8) + rdi_buff[3];
+ if (! raw)
+ printf("Reported device identifier length = %d\n", di_len);
+ if (0 == di_len) {
+ fprintf(stderr, " This implies the device has an empty "
+ "identifier\n");
+ goto err_out;
+ }
+ if (di_len > REPORT_DEV_ID_SANITY_LEN) {
+ fprintf(stderr, " That length (%d) seems too long for a "
+ "device identifier\n", di_len);
+ goto err_out;
+ }
+ ucp = rdi_buff;
+ res = sg_ll_report_dev_id(sg_fd, ucp, di_len + 4, 1, verbose);
+ if (0 == res) {
+ di_len = (ucp[0] << 24) + (ucp[1] << 16) + (ucp[2] << 8) +
+ ucp[3];
+ if (raw) {
+ if (di_len > 0)
+ n = fwrite(ucp + 4, 1, di_len, stdout);
+ } else {
+ printf("Device identifier:\n");
+ if (di_len > 0) {
+ if (ascii)
+ printf("%.*s\n", di_len, (const char *)ucp + 4);
+ else
+ dStrHex((const char *)ucp + 4, di_len, 0);
+ }
+ }
+ ret = 0;
+ }
+ }
+ if (0 != res) {
+ if (SG_LIB_CAT_INVALID_OP == res)
+ fprintf(stderr, "Report Device Identifier command not "
+ "supported\n");
+ else if (SG_LIB_CAT_ILLEGAL_REQ == res)
+ fprintf(stderr, "bad field in Report Device Identifier "
+ "cdb\n");
+ else {
+ fprintf(stderr, "Report Device Identifier command failed\n");
+ if (0 == verbose)
+ fprintf(stderr, " try '-v' for more information\n");
+ }
+ }
+ }
+
+err_out:
+ res = close(sg_fd);
+ if (res < 0) {
+ perror(ME "close error");
+ return 1;
+ }
+ return ret;
+}
diff --git a/sg_inq.8 b/sg_inq.8
index d35893d8..e2bda356 100644
--- a/sg_inq.8
+++ b/sg_inq.8
@@ -1,12 +1,12 @@
-.TH SG_INQ "8" "March 2005" "sg3_utils-1.14" SG3_UTILS
+.TH SG_INQ "8" "August 2005" "sg3_utils-1.16" SG3_UTILS
.SH NAME
sg_inq \- outputs data retrieved from the SCSI INQUIRY command
.SH SYNOPSIS
.B sg_inq
-[\fI-c\fR] [\fI-cl\fR] [\fI-d\fR] [\fI-e\fR] [\fI-h\fR] [\fI-i\fR]
-[\fI-o=<opcode_page>\fR] [\fI-p=<vpd_page>\fR] [\fI-P\fR]
-[\fI-r\fR] [\fI-s\fR] [\fI-v\fR] [\fI-V\fR] [\fI-x\fR] [\fI-36\fR] [\fI-?\fR]
-\fI<scsi_device>\fR
+[\fI-c\fR] [\fI-cl\fR] [\fI-d\fR] [\fI-e\fR] [\fI-h\fR] [\fI-H\fR]
+[\fI-i\fR] [\fI-m\fR] [\fI-m\fR] [\fI-o=<opcode_page>\fR]
+[\fI-p=<vpd_page>\fR] [\fI-P\fR] [\fI-r\fR] [\fI-s\fR] [\fI-v\fR]
+[\fI-V\fR] [\fI-x\fR] [\fI-36\fR] [\fI-?\fR] \fI<scsi_device>\fR
.SH DESCRIPTION
.\" Add any additional description here
.PP
@@ -26,9 +26,9 @@ ioctl is unknown) then an ATA IDENTIFY is tried. If it succeeds then
device identification strings are output. If the "-r" option is given
then the 256 byte IDENTIFY block is output in binary.
.PP
-The reference document used for interpreting an INQUIRY is T10/1416-D Revision
-21d (SPC-3, 14th February 2005) found at http://www.t10.org . Obsolete items
-in the standard INQUIRY response are displayed in brackets.
+The reference document used for interpreting an INQUIRY is T10/1416-D
+Revision 23 (SPC-3, 4th May 2005) found at http://www.t10.org . Obsolete
+items in the standard INQUIRY response are displayed in brackets.
.TP
-c
set the Command Support Data (CmdDt) bit (defaults to clear(0)). Used
@@ -46,11 +46,11 @@ name) by looping through all 256 opcodes. This option uses the CmdDt bit
which is now obsolete. See the sg_opcodes utility.
.TP
-d
-lists version descriptors. There are up to 8 version descriptors in the
-upper bytes of a standard INQUIRY, If the code is recognised then the
-corresponding string is output. Version descriptors are versions of
-standards and drafts that the device claims to comply with (e.g. SAM,
-SPC, SBC, SAS etc).
+lists version descriptors (if any) after a standard INQUIRY response.
+There are up to 8 version descriptors in the upper bytes of a standard
+INQUIRY, If the code is recognised then the corresponding string is output.
+Version descriptors are versions of standards and drafts that the device
+claims to comply with (e.g. SAM, SPC, SBC, SPI, FCP, SAS etc).
.TP
-e
enable (i.e. sets) the Vital Product Data (EVPD) bit (defaults to clear(0)).
@@ -76,6 +76,18 @@ descriptor header is decoded and the identifier itself is output in hex.
To see the whole VPD 0x83 page response in hex use '-p=83 -h'. Recent SPC-3
drafts have made support of the device identification VPD page mandatory.
.TP
+-m
+outputs the Management network addresses Vital Product Data (VPD)
+page [0x85]. If '-r' is not given then attempts to decode the response
+which can be made up of several "network service descriptors". If '-h' is
+given then each descriptor payload is output in hex.
+.TP
+-M
+outputs the Mode page policy Vital Product Data (VPD) page [0x87].
+If '-r' is not given then attempts to decode the response which can be
+made up of several "mode page policy descriptors". If '-h' is given
+then each descriptor payload is output in hex.
+.TP
-o=<opcode_page>
used in conjunction with the '-e' or '-c' option. If neither given then
the '-e' option assumed. When the '-e' option is also given (or assumed)
@@ -123,8 +135,8 @@ and '-vvv' are also accepted yielding greater verbosity.
-V
print out version string
.TP
--i
-outputs the Extended INQUIRY Vital Product Data (VPD) [0x86] page.
+-x
+outputs the Extended INQUIRY data Vital Product Data (VPD) [0x86] page.
If '-r' is not given then attempts to decode the response.
If '-h' is given then prints out VPD page in hex which is similar to
using '-p=86 -h'.
diff --git a/sg_inq.c b/sg_inq.c
index e6a6b1f1..4680d47d 100644
--- a/sg_inq.c
+++ b/sg_inq.c
@@ -27,15 +27,37 @@
other improvements [20020814]
- Lars Marowsky-Bree <lmb at suse dot de> contributed Unit Path Report
VPD page decoding for EMC CLARiiON devices [20041016]
-
-From SPC-3 revision 16 the CmdDt bit in an INQUIRY is obsolete. There is
-now a REPORT SUPPORTED OPERATION CODES command that yields similar
-information [MAINTENANCE IN, service action = 0xc]. Support will be added
-in the future.
-
*/
-static char * version_str = "0.51 20050602";
+/* INQUIRY notes:
+ * It is recommended that the initial allocation length given to a
+ * standard INQUIRY is 36 (bytes), especially if this is the first
+ * SCSI command sent to a logical unit. This is compliant with SCSI-2
+ * and another major operating system. There are devices out there
+ * that use one of the SCSI commands sets and lock up if they receive
+ * an allocation length other than 36. This technique is sometimes
+ * referred to as a "36 byte INQUIRY".
+ *
+ * A "standard" INQUIRY is one that has the EVPD and the CmdDt bits
+ * clear.
+ *
+ * When doing device discovery on a SCSI transport (e.g. bus scanning)
+ * the first SCSI command sent to a device should be a standard (36
+ * byte) INQUIRY.
+ *
+ * The allocation length field in the INQUIRY command was changed
+ * from 1 to 2 bytes in SPC-3, revision 9, 17 September 2002.
+ * Be careful using allocation lengths greater than 252 bytes, especially
+ * if the lower byte is 0x0 (e.g. a 512 byte allocation length may
+ * not be a good arbitrary choice (as 512 == 0x200) ).
+ *
+ * From SPC-3 revision 16 the CmdDt bit in an INQUIRY is obsolete. There
+ * is now a REPORT SUPPORTED OPERATION CODES command that yields similar
+ * information [MAINTENANCE IN, service action = 0xc]. Support will be
+ * added in the future.
+ */
+
+static char * version_str = "0.52 20050808";
#define SENSE_BUFF_LEN 32 /* Arbitrary, could be larger */
@@ -43,14 +65,18 @@ static char * version_str = "0.51 20050602";
#define INQUIRY_CMD 0x12
#define INQUIRY_CMDLEN 6
+
#define SUPPORTED_VPDS_VPD 0x0
#define UNIT_SERIAL_NUM_VPD 0x80
#define DEV_ID_VPD 0x83
+#define MAN_NET_ADDR_VPD 0x85
#define X_INQ_VPD 0x86
+#define MODE_PG_POLICY_VPD 0x87
#define SCSI_PORTS_VPD 0x88
#define UPR_EMC_VPD 0xc0
+
#define DEF_ALLOC_LEN 252
-#define MX_ALLOC_LEN 4096
+#define MX_ALLOC_LEN (0xc000 + 0x80)
#define EBUFF_SZ 256
@@ -69,7 +95,7 @@ static void decode_transport_id(const char * leadin, unsigned char * ucp,
static void usage()
{
fprintf(stderr,
- "Usage: sg_inq [-c] [-cl] [-d] [-e] [-h] [-H] [-i] "
+ "Usage: sg_inq [-c] [-cl] [-d] [-e] [-h] [-H] [-i] [-m] "
"[-o=<opcode_page>]\n"
" [-p=<vpd_page>] [-P] [-r] [-s] [-v] [-V] [-x] "
"[-36] [-?]\n"
@@ -81,6 +107,9 @@ static void usage()
" -h output in hex (ASCII to the right)\n"
" -H output in hex (ASCII to the right) [same as '-h']\n"
" -i decode device identification VPD page (0x83)\n"
+ " -m decode management network addresses VPD page "
+ "(0x85)\n"
+ " -M decode mode page policy VPD page (0x87)\n"
" -o=<opcode_page> opcode or page code in hex (def: 0)\n"
" -p=<vpd_page> vpd page code in hex (def: 0)\n"
" -P decode Unit Path Report VPD page (0xc0) (EMC)\n"
@@ -88,11 +117,11 @@ static void usage()
" -s decode SCSI Ports VPD page (0x88)\n"
" -v verbose (output cdb and, if non-zero, resid)\n"
" -V output version string\n"
- " -x decode extented INQUIRY VPD page (0x86)\n"
- " -36 only perform a 36 byte INQUIRY\n"
+ " -x decode extented INQUIRY data VPD page (0x86)\n"
+ " -36 perform standard INQUIRY with a 36 byte response\n"
" -? output this usage message\n"
" If no optional switches given then does"
- " a standard INQUIRY\n");
+ " a standard SCSI INQUIRY\n");
}
@@ -108,7 +137,7 @@ static const char * scsi_ptype_strs[] = {
/* 0 */ "disk",
"tape",
"printer",
- "processor",
+ "processor", /* often SAF-TE (seldom scanner) device */
"write once optical disk",
/* 5 */ "cd/dvd",
"scanner",
@@ -144,16 +173,16 @@ struct vpd_name {
};
static struct vpd_name vpd_name_arr[] = {
- {0x0, 0, "Supported VPD pages"},
- {0x80, 0, "Unit serial number"},
+ {SUPPORTED_VPDS_VPD, 0, "Supported VPD pages"},
+ {UNIT_SERIAL_NUM_VPD, 0, "Unit serial number"},
{0x81, 0, "Implemented operating definitions"},
{0x82, 0, "ASCII implemented operating definition (obsolete)"},
- {0x83, 0, "Device identification"},
+ {DEV_ID_VPD, 0, "Device identification"},
{0x84, 0, "Software interface identification"},
- {0x85, 0, "Management network addresses"},
- {0x86, 0, "Extended INQUIRY data"},
- {0x87, 0, "Mode page policy"},
- {0x88, 0, "SCSI ports"},
+ {MAN_NET_ADDR_VPD, 0, "Management network addresses"},
+ {X_INQ_VPD, 0, "Extended INQUIRY data"},
+ {MODE_PG_POLICY_VPD, 0, "Mode page policy"},
+ {SCSI_PORTS_VPD, 0, "SCSI ports"},
{0x89, 0, "ATA information"},
{0xb0, 0, "Block limits (sbc2)"},
{0xb0, 0x1, "SSC device capabilities (ssc3)"},
@@ -212,6 +241,105 @@ static void decode_id_vpd(unsigned char * buff, int len, int do_hex)
decode_dev_ids("Device identification", buff + 4, len - 4, do_hex);
}
+static const char * assoc_arr[] =
+{
+ "addressed logical unit",
+ "target port that received request",
+ "target device that contains addressed lu",
+ "reserved [0x3]",
+};
+
+static const char * network_service_type_arr[] =
+{
+ "unspecified",
+ "storage configuration service",
+ "diagnostics",
+ "status",
+ "logging",
+ "code download",
+ "reserved[0x6]", "reserved[0x7]", "reserved[0x8]", "reserved[0x9]",
+ "reserved[0xa]", "reserved[0xb]", "reserved[0xc]", "reserved[0xd]",
+ "reserved[0xe]", "reserved[0xf]", "reserved[0x10]", "reserved[0x11]",
+ "reserved[0x12]", "reserved[0x13]", "reserved[0x14]", "reserved[0x15]",
+ "reserved[0x16]", "reserved[0x17]", "reserved[0x18]", "reserved[0x19]",
+ "reserved[0x1a]", "reserved[0x1b]", "reserved[0x1c]", "reserved[0x1d]",
+ "reserved[0x1e]", "reserved[0x1f]",
+};
+
+static void decode_net_man_vpd(unsigned char * buff, int len, int do_hex)
+{
+ int k, bump, na_len;
+ unsigned char * ucp;
+
+ if (len < 4) {
+ fprintf(stderr, "Management network addresses VPD page length too "
+ "short=%d\n", len);
+ return;
+ }
+ len -= 4;
+ ucp = buff + 4;
+ for (k = 0; k < len; k += bump, ucp += bump) {
+ printf(" %s, Service type: %s\n",
+ assoc_arr[(ucp[0] >> 5) & 0x3],
+ network_service_type_arr[ucp[0] & 0x1f]);
+ na_len = (ucp[2] << 8) + ucp[3];
+ bump = 4 + na_len;
+ if ((k + bump) > len) {
+ fprintf(stderr, "Management network addresses VPD page, short "
+ "descriptor length=%d, left=%d\n", bump, (len - k));
+ return;
+ }
+ if (na_len > 0) {
+ if (do_hex) {
+ printf(" Network address:\n");
+ dStrHex((const char *)(ucp + 4), na_len, 0);
+ } else
+ printf(" %s\n", ucp + 4);
+ }
+ }
+}
+
+static const char * mode_page_policy_arr[] =
+{
+ "shared",
+ "per target port",
+ "per initiator port",
+ "per I_T nexus",
+};
+
+static void decode_mode_policy_vpd(unsigned char * buff, int len, int do_hex)
+{
+ int k, bump;
+ unsigned char * ucp;
+
+ if (len < 4) {
+ fprintf(stderr, "Mode page policy VPD page length too short=%d\n",
+ len);
+ return;
+ }
+ len -= 4;
+ ucp = buff + 4;
+ for (k = 0; k < len; k += bump, ucp += bump) {
+ bump = 4;
+ if ((k + bump) > len) {
+ fprintf(stderr, "Mode page policy VPD page, short "
+ "descriptor length=%d, left=%d\n", bump, (len - k));
+ return;
+ }
+ if (do_hex)
+ dStrHex((const char *)ucp, 4, 1);
+ else {
+ printf(" Policy page code: 0x%x", (ucp[0] & 0x3f));
+ if (ucp[1])
+ printf(", subpage code: 0x%x\n", ucp[1]);
+ else
+ printf("\n");
+ printf(" MLUS=%d, Policy: %s\n", !!(ucp[2] & 0x80),
+ mode_page_policy_arr[ucp[2] & 0x3]);
+ }
+ }
+}
+
static void decode_scsi_ports_vpd(unsigned char * buff, int len, int do_hex)
{
int k, bump, rel_port, ip_tid_len, tpd_len;
@@ -284,14 +412,6 @@ static const char * code_set_arr[] =
"Reserved [0xc]", "Reserved [0xd]", "Reserved [0xe]", "Reserved [0xf]",
};
-static const char * assoc_arr[] =
-{
- "addressed logical unit",
- "target port that received request",
- "target device that contains addressed lu",
- "reserved [0x3]",
-};
-
static const char * id_type_arr[] =
{
"vendor specific [0x0]",
@@ -322,7 +442,7 @@ static void decode_dev_ids(const char * leadin, unsigned char * buff,
for (k = 0, j = 1; k < len; k += id_len, ucp += id_len, ++j) {
i_len = ucp[3];
id_len = i_len + 4;
- printf(" Identification descriptor number %d, "
+ printf(" Descriptor number %d, "
"descriptor length: %d\n", j, id_len);
if ((k + id_len) > len) {
fprintf(stderr, "%s VPD page error: descriptor length longer "
@@ -651,8 +771,8 @@ static void decode_transport_id(const char * leadin, unsigned char * ucp,
static void decode_x_inq_vpd(unsigned char * buff, int len, int do_hex)
{
if (len < 7) {
- fprintf(stderr, "Extended INQUIRY VPD page length too short=%d\n",
- len);
+ fprintf(stderr, "Extended INQUIRY data VPD page length too "
+ "short=%d\n", len);
return;
}
if (do_hex) {
@@ -664,7 +784,7 @@ static void decode_x_inq_vpd(unsigned char * buff, int len, int do_hex)
printf(" GRP_SUP=%d PRIOR_SUP=%d HEADSUP=%d ORDSUP=%d SIMPSUP=%d\n",
!!(buff[5] & 0x10), !!(buff[5] & 0x8), !!(buff[5] & 0x4),
!!(buff[5] & 0x2), !!(buff[5] & 0x1));
- printf(" NV_SUP=%d V_SUP=%d", !!(buff[6] & 0x2), !!(buff[6] & 0x1));
+ printf(" NV_SUP=%d V_SUP=%d\n", !!(buff[6] & 0x2), !!(buff[6] & 0x1));
}
static const char * lun_state_arr[] =
@@ -1177,6 +1297,8 @@ int main(int argc, char * argv[])
int do_cmdlst = 0;
int do_di_vpd = 0;
int do_hex = 0;
+ int do_man_net_vpd = 0;
+ int do_mode_policy_vpd = 0;
int do_raw = 0;
int do_scsi_ports_vpd = 0;
int do_xtended = 0;
@@ -1226,6 +1348,12 @@ int main(int argc, char * argv[])
case 'i':
do_di_vpd = 1;
break;
+ case 'm':
+ do_man_net_vpd = 1;
+ break;
+ case 'M':
+ do_mode_policy_vpd = 1;
+ break;
case 'P':
do_upr_c0_emc = 1;
break;
@@ -1288,7 +1416,8 @@ int main(int argc, char * argv[])
}
}
- decode = do_di_vpd + do_xtended + do_upr_c0_emc + do_scsi_ports_vpd;
+ decode = do_di_vpd + do_xtended + do_upr_c0_emc + do_scsi_ports_vpd +
+ do_man_net_vpd + do_mode_policy_vpd;
if (do_raw && do_hex) {
fprintf(stderr, "Can't do hex and raw at the same time\n");
usage();
@@ -1372,9 +1501,63 @@ int main(int argc, char * argv[])
else
decode_id_vpd(rsp_buff, len, do_hex);
}
+ } else if (do_man_net_vpd) {
+ if (!do_raw)
+ printf("VPD INQUIRY: Management network addresses page\n");
+ if (0 == sg_ll_inquiry(sg_fd, 0, 1, MAN_NET_ADDR_VPD, rsp_buff,
+ DEF_ALLOC_LEN, 1, do_verbose)) {
+ len = ((rsp_buff[2] << 8) + rsp_buff[3]) + 4;
+ ret = 3;
+ if (MAN_NET_ADDR_VPD != rsp_buff[1]) {
+ fprintf(stderr, "invalid VPD response; probably a STANDARD "
+ "INQUIRY response\n");
+ goto err_out;
+ }
+ if (len > MX_ALLOC_LEN) {
+ fprintf(stderr, "response length too long: %d > %d\n", len,
+ MX_ALLOC_LEN);
+ goto err_out;
+ } else if (len > DEF_ALLOC_LEN) {
+ if (sg_ll_inquiry(sg_fd, 0, 1, MAN_NET_ADDR_VPD, rsp_buff,
+ len, 1, do_verbose))
+ goto err_out;
+ }
+ ret = 0;
+ if (do_raw)
+ dStrRaw((const char *)rsp_buff, len);
+ else
+ decode_net_man_vpd(rsp_buff, len, do_hex);
+ }
+ } else if (do_mode_policy_vpd) {
+ if (!do_raw)
+ printf("VPD INQUIRY: Mode page policy\n");
+ if (0 == sg_ll_inquiry(sg_fd, 0, 1, MODE_PG_POLICY_VPD, rsp_buff,
+ DEF_ALLOC_LEN, 1, do_verbose)) {
+ len = ((rsp_buff[2] << 8) + rsp_buff[3]) + 4;
+ ret = 3;
+ if (MODE_PG_POLICY_VPD != rsp_buff[1]) {
+ fprintf(stderr, "invalid VPD response; probably a STANDARD "
+ "INQUIRY response\n");
+ goto err_out;
+ }
+ if (len > MX_ALLOC_LEN) {
+ fprintf(stderr, "response length too long: %d > %d\n", len,
+ MX_ALLOC_LEN);
+ goto err_out;
+ } else if (len > DEF_ALLOC_LEN) {
+ if (sg_ll_inquiry(sg_fd, 0, 1, MODE_PG_POLICY_VPD, rsp_buff,
+ len, 1, do_verbose))
+ goto err_out;
+ }
+ ret = 0;
+ if (do_raw)
+ dStrRaw((const char *)rsp_buff, len);
+ else
+ decode_mode_policy_vpd(rsp_buff, len, do_hex);
+ }
} else if (do_xtended) {
if (!do_raw)
- printf("VPD INQUIRY: extended INQUIRY page\n");
+ printf("VPD INQUIRY: extended INQUIRY data page\n");
if (0 == sg_ll_inquiry(sg_fd, 0, 1, X_INQ_VPD, rsp_buff,
DEF_ALLOC_LEN, 1, do_verbose)) {
len = ((rsp_buff[2] << 8) + rsp_buff[3]) + 4;
diff --git a/sg_lib.c b/sg_lib.c
index c715d1b2..127e0f47 100644
--- a/sg_lib.c
+++ b/sg_lib.c
@@ -68,7 +68,7 @@
#include "sg_include.h"
#include "sg_lib.h"
-static char * version_str = "1.10 20050521"; /* spc-3 rev 23+ */
+static char * version_str = "1.11 20050807"; /* spc-3 rev 23+ */
FILE * sg_warnings_str = NULL; /* would like to default to stderr */
@@ -1040,7 +1040,9 @@ static struct error_info additional[] =
};
static const char *sense_key_desc[] = {
- "No Sense", /* There is no sense information */
+ "No Sense", /* Filemark, ILI and/or EOM; progress
+ indication (during FORMAT); power
+ condition sensing (REQUEST SENSE) */
"Recovered Error", /* The last command completed successfully
but used error correction */
"Not Ready", /* The addressed target is not ready */
@@ -1410,7 +1412,7 @@ static void sg_print_sense_descriptors(const unsigned char * sense_buffer,
/* Print sense information */
void sg_print_sense(const char * leadin, const unsigned char * sense_buffer,
- int sb_len)
+ int sb_len, int raw_sinfo)
{
int len, valid, progress;
unsigned int info;
@@ -1482,7 +1484,8 @@ void sg_print_sense(const char * leadin, const unsigned char * sense_buffer,
else if (info > 0)
fprintf(sg_warnings_str, " Valid=0, Info fld=0x%x [%u] ",
info, info);
- }
+ } else
+ info = 0;
if (sense_buffer[2] & 0xe0) {
if (sense_buffer[2] & 0x80)
fprintf(sg_warnings_str, " FMK");
@@ -1494,7 +1497,8 @@ void sg_print_sense(const char * leadin, const unsigned char * sense_buffer,
fprintf(sg_warnings_str, " ILI");
/* incorrect block length requested */
fprintf(sg_warnings_str, "\n");
- }
+ } else if (valid || (info > 0))
+ fprintf(sg_warnings_str, "\n");
if ((len >= 14) && sense_buffer[14])
fprintf(sg_warnings_str, " Field replaceable unit code: "
"%d\n", sense_buffer[14]);
@@ -1549,7 +1553,7 @@ void sg_print_sense(const char * leadin, const unsigned char * sense_buffer,
} else { /* non-extended sense data */
/*
- * Standard says:
+ * A (very old) Standard says:
* sense_buffer[0] & 0200 : address valid
* sense_buffer[0] & 0177 : vendor-specific error code
* sense_buffer[1] & 0340 : vendor-specific
@@ -1574,9 +1578,10 @@ void sg_print_sense(const char * leadin, const unsigned char * sense_buffer,
(sense_buffer[0] >> 4) & 0x07, sense_buffer[0] & 0xf);
len = 4;
}
-
- fprintf(sg_warnings_str, " Raw sense data (in hex):\n");
- dStrHexErr((const char *)sense_buffer, len);
+ if (raw_sinfo) {
+ fprintf(sg_warnings_str, " Raw sense data (in hex):\n");
+ dStrHexErr((const char *)sense_buffer, len);
+ }
}
static const char * linux_host_bytes[] = {
@@ -1639,9 +1644,10 @@ void sg_print_driver_status(int driver_status)
/* Returns 1 if no errors found and thus nothing printed; otherwise
prints error/warning (prefix by 'leadin') and returns 0. */
-static int sg_sense_print(const char * leadin, int scsi_status,
- int host_status, int driver_status,
- const unsigned char * sense_buffer, int sb_len)
+static int sg_linux_sense_print(const char * leadin, int scsi_status,
+ int host_status, int driver_status,
+ const unsigned char * sense_buffer,
+ int sb_len, int raw_sinfo)
{
int done_leadin = 0;
int done_sense = 0;
@@ -1661,7 +1667,7 @@ static int sg_sense_print(const char * leadin, int scsi_status,
if (sense_buffer && ((scsi_status == SCSI_CHECK_CONDITION) ||
(scsi_status == SCSI_COMMAND_TERMINATED))) {
/* SCSI_COMMAND_TERMINATED is obsolete */
- sg_print_sense(0, sense_buffer, sb_len);
+ sg_print_sense(0, sense_buffer, sb_len, raw_sinfo);
done_sense = 1;
}
}
@@ -1686,7 +1692,7 @@ static int sg_sense_print(const char * leadin, int scsi_status,
fprintf(sg_warnings_str, "\n");
if (sense_buffer && (! done_sense) &&
(SG_LIB_DRIVER_SENSE == (SG_LIB_DRIVER_MASK & driver_status)))
- sg_print_sense(0, sense_buffer, sb_len);
+ sg_print_sense(0, sense_buffer, sb_len, raw_sinfo);
}
return 0;
}
@@ -1740,10 +1746,12 @@ int sg_normalize_sense(const struct sg_io_hdr * hp,
/* Returns 1 if no errors found and thus nothing printed; otherwise
returns 0. */
-int sg_chk_n_print3(const char * leadin, struct sg_io_hdr * hp)
+int sg_chk_n_print3(const char * leadin, struct sg_io_hdr * hp,
+ int raw_sinfo)
{
- return sg_sense_print(leadin, hp->status, hp->host_status,
- hp->driver_status, hp->sbp, hp->sb_len_wr);
+ return sg_linux_sense_print(leadin, hp->status, hp->host_status,
+ hp->driver_status, hp->sbp, hp->sb_len_wr,
+ raw_sinfo);
}
#endif
@@ -1751,12 +1759,14 @@ int sg_chk_n_print3(const char * leadin, struct sg_io_hdr * hp)
returns 0. */
int sg_chk_n_print(const char * leadin, int masked_status,
int host_status, int driver_status,
- const unsigned char * sense_buffer, int sb_len)
+ const unsigned char * sense_buffer, int sb_len,
+ int raw_sinfo)
{
int scsi_status = (masked_status << 1) & 0x7e;
- return sg_sense_print(leadin, scsi_status, host_status, driver_status,
- sense_buffer, sb_len);
+ return sg_linux_sense_print(leadin, scsi_status, host_status,
+ driver_status, sense_buffer, sb_len,
+ raw_sinfo);
}
#ifdef SG_IO
diff --git a/sg_lib.h b/sg_lib.h
index 60f9535f..685ad71d 100644
--- a/sg_lib.h
+++ b/sg_lib.h
@@ -30,7 +30,7 @@
*
*/
-/* Version 1.10 [20050521]
+/* Version 1.11 [20050806]
*
* On 5th October 2004 a FreeBSD license was added to this file.
* The intention is to keep this file and the related sg_lib.c file
@@ -289,7 +289,8 @@ extern void sg_set_warnings_str(FILE * warnings_str);
descriptor (default value is stderr) */
extern void sg_print_command(const unsigned char * command);
extern void sg_print_sense(const char * leadin,
- const unsigned char * sense_buffer, int sb_len);
+ const unsigned char * sense_buffer, int sb_len,
+ int raw_info);
extern void sg_print_status(int masked_status);
extern void sg_print_scsi_status(int scsi_status);
extern void sg_print_host_status(int host_status);
@@ -300,14 +301,16 @@ extern void sg_print_driver_status(int driver_status);
'sg_warnings_fd' and returns 0. */
extern int sg_chk_n_print(const char * leadin, int masked_status,
int host_status, int driver_status,
- const unsigned char * sense_buffer, int sb_len);
+ const unsigned char * sense_buffer, int sb_len,
+ int raw_sinfo);
/* The following function declaration is for the sg version 3 driver. */
struct sg_io_hdr;
/* sg_chk_n_print3() returns 1 quietly if there are no errors/warnings;
else it prints errors/warnings (prefixed by 'leadin') to
'sg_warnings_fd' and returns 0. */
-extern int sg_chk_n_print3(const char * leadin, struct sg_io_hdr * hp);
+extern int sg_chk_n_print3(const char * leadin, struct sg_io_hdr * hp,
+ int raw_sinfo);
/* Calls sg_scsi_normalize_sense() after obtaining the sense buffer and
its length from the struct sg_io_hdr pointer. If these cannot be
diff --git a/sg_logs.c b/sg_logs.c
index c4e7a834..97b65eec 100644
--- a/sg_logs.c
+++ b/sg_logs.c
@@ -23,7 +23,7 @@
*/
-static char * version_str = "0.41 20050601";
+static char * version_str = "0.43 20050808";
#define ME "sg_logs: "
@@ -54,6 +54,12 @@ static int do_logs(int sg_fd, int ppc, int sp, int pc, int pg_code,
return -1;
}
actual_len = (resp[2] << 8) + resp[3] + 4;
+ if (verbose > 1) {
+ fprintf(stderr, " Log sense (find length) response:\n");
+ dStrHex((const char *)resp, 4, 1);
+ fprintf(stderr, " hence calculated response length=%d\n",
+ actual_len);
+ }
/* Some HBAs don't like odd transfer lengths */
if (actual_len % 2)
actual_len += 1;
@@ -65,6 +71,10 @@ static int do_logs(int sg_fd, int ppc, int sp, int pc, int pg_code,
return res;
return -1;
}
+ if (verbose > 1) {
+ fprintf(stderr, " Log sense response:\n");
+ dStrHex((const char *)resp, actual_len, 1);
+ }
return 0;
}
@@ -83,15 +93,16 @@ static void usage()
" -l list supported log page names\n"
" -p=<page_code> page code (in hex)\n"
" -paramp=<parameter_pointer> (in hex) (def: 0)\n"
- " -pcb show parameter control bytes (ignored if -h given)\n"
- " -ppc set the Parameter Pointer Control (PPC) bit (def: 0)\n"
+ " -pcb show parameter control bytes (ignored if -h given)\n");
+ printf(" -ppc set the Parameter Pointer Control (PPC) bit (def: 0)\n"
" -r reset all implemented parameters to target defined "
"defaults\n"
" -sp set the Saving Parameters (SP) bit (def: 0)\n"
" -t outputs temperature log page (0xd)\n"
" -v verbose: output cdbs prior to execution\n"
" -V output version string\n"
- " -? output this usage message\n");
+ " -? output this usage message\n\n"
+ "Performs a SCSI LOG SENSE command\n");
}
static void show_page_name(int page_no,
@@ -926,15 +937,15 @@ static void show_non_volatile_cache_page(unsigned char * resp, int len,
}
static const char * bms_status[] = {
- "no scans active",
- "background medium scan is active",
- "pre-scan is active",
- "scan halted due to fatal error",
- "scan halted due to unusual pattern of error",
- "scan halted due to medium formatted without P-List",
- "scan halted - vendor specific cause",
- "scan halted due to temperature out of range",
- "scan suspended until BMS Interval Time expires",
+ "no scans active",
+ "background medium scan is active",
+ "pre-scan is active",
+ "scan halted due to fatal error",
+ "scan halted due to unusual pattern of error",
+ "scan halted due to medium formatted without P-List",
+ "scan halted - vendor specific cause",
+ "scan halted due to temperature out of range",
+ "scan suspended until BMS Interval Time expires", /* 8 */
};
static const char * reassign_status[] = {
@@ -972,10 +983,10 @@ static void show_background_scan_results_page(unsigned char * resp, int len,
printf("%s\n", bms_status[j]);
else
printf("unknown [0x%x]\n", j);
- printf(" Number of scan performed: %d\n",
+ printf(" Number of scans performed: %d\n",
(ucp[10] << 8) + ucp[11]);
- printf(" Progress of medium scan: %d%%\n",
- ((ucp[12] << 8) + ucp[13]) * 100 / 65536);
+ printf(" Progress of medium scan: %.2f%%\n",
+ (double)((ucp[12] << 8) + ucp[13]) * 100.0 / 65536.0);
break;
default:
@@ -1417,6 +1428,7 @@ int main(int argc, char * argv[])
int oroflags = O_RDONLY | O_NONBLOCK;
struct sg_simple_inquiry_resp inq_out;
+ memset(rsp_buff, 0, sizeof(rsp_buff));
for (k = 1; k < argc; ++k) {
cp = argv[k];
plen = strlen(cp);
diff --git a/sg_luns.c b/sg_luns.c
index 866619d1..033db57a 100644
--- a/sg_luns.c
+++ b/sg_luns.c
@@ -47,7 +47,7 @@
* This program issues the SCSI command REPORT LUNS to the given SCSI device.
*/
-static char * version_str = "1.02 20041229";
+static char * version_str = "1.03 20050808";
#define REPORT_LUNS_BUFF_LEN 1024
@@ -78,7 +78,8 @@ static void usage()
"logical unit numbers\n"
" 2 -> all luns\n"
" --verbose|-v increase verbosity\n"
- " --version|-V print version string and exit\n"
+ " --version|-V print version string and exit\n\n"
+ "Performs a REPORT LUNS SCSI command\n"
);
}
@@ -298,6 +299,11 @@ int main(int argc, char * argv[])
"mandatory in SPC-3)\n");
else if (SG_LIB_CAT_ILLEGAL_REQ == res)
fprintf(stderr, "Report Luns command has bad fields in cdb\n");
+ else {
+ fprintf(stderr, "Report Luns command failed\n");
+ if (0 == verbose)
+ fprintf(stderr, " try '-v' option for more information\n");
+ }
res = close(sg_fd);
if (res < 0) {
diff --git a/sg_map.c b/sg_map.c
index 67fc466f..bd413c73 100644
--- a/sg_map.c
+++ b/sg_map.c
@@ -36,12 +36,14 @@
#error "Need version 2 sg driver (linux kernel >= 2.2.6)"
#endif
-static char * version_str = "1.02 20050511";
+static char * version_str = "1.04 20050810";
static const char * devfs_id = "/dev/.devfsd";
#define NUMERIC_SCAN_DEF 1 /* change to 0 to make alpha scan default */
+#define INQUIRY_RESP_INITIAL_LEN 36
+
typedef struct my_map_info
{
@@ -55,8 +57,9 @@ typedef struct my_map_info
} my_map_info_t;
-#define MAX_SG_DEVS 256
-#define MAX_SD_DEVS 26 + 26*26 + 26*26*26 /* sdX, sdXX, sdXXX */
+#define MAX_SG_DEVS 2048
+#define MAX_SD_DEVS (26 + 26*26 + 26*26*26) /* sdX, sdXX, sdXXX */
+ /* (26 + 676 + 17576) = 18278 */
#define MAX_SR_DEVS 128
#define MAX_ST_DEVS 128
#define MAX_OSST_DEVS 128
@@ -87,7 +90,7 @@ static void scan_dev_type(const char * leadin, int max_dev, int do_numeric,
static void usage()
{
- printf("Usage: 'sg_map [-a] [-h] [i] [-n] [-sd] [-scd or -sr] [-st] "
+ printf("Usage: 'sg_map [-a] [-h] [-i] [-n] [-sd] [-scd or -sr] [-st] "
"[-V] [-x]'\n");
printf(" where: -a do alphabetic scan (ie sga, sgb, sgc)\n");
printf(" -h or -? show this usage message then exit\n");
@@ -244,7 +247,7 @@ int main(int argc, char * argv[])
continue;
}
if (do_inquiry) {
- char buff[36];
+ char buff[INQUIRY_RESP_INITIAL_LEN];
if (0 == sg_ll_inquiry(sg_fd, 0, 0, 0, buff, sizeof(buff),
1, 0)) {
diff --git a/sg_modes.8 b/sg_modes.8
index 8022ddcc..0862ba9f 100644
--- a/sg_modes.8
+++ b/sg_modes.8
@@ -1,4 +1,4 @@
-.TH SG_MODES "8" "May 2005" "sg3_utils-1.15" SG3_UTILS
+.TH SG_MODES "8" "August 2005" "sg3_utils-1.16" SG3_UTILS
.SH NAME
sg_modes \- reads SCSI MODE SENSE pages
.SH SYNOPSIS
@@ -116,13 +116,12 @@ tape drives). This parameter forces the use of 6 byte MODE SENSE commands.
output usage message. Ignore all other parameters.
.PP
If the normal sg_modes utility fails with "illegal command
-operation code" then try the "-6" parameter. To alter page settings
-see the program listed in the "See Also" section below.
+operation code" then try the "-6" parameter.
.PP
Mode pages cannot be modified with this utility. Mode pages (and subpages)
can be modified with the sg_wr_mode and sginfo utilities in the sg3_utils
-package. Some other utilities for displaying and modifying mode pages are
-listed in the "see also" section below.
+package. See this sdparm utility and those other utilities that are
+listed in the "SEE ALSO" section below.
.PP
This utility performs a SCSI INQUIRY command to determine the peripheral
type of the device (e.g. 0 -> Direct Access Device (disk)) prior to
@@ -138,13 +137,14 @@ Written by Doug Gilbert
.SH "REPORTING BUGS"
Report bugs to <dgilbert at interlog dot com>.
.SH COPYRIGHT
-Copyright \(co 2000-2004 Douglas Gilbert
+Copyright \(co 2000-2005 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_wr_mode(sg3_utils), sginfo(sg3_utils), sgmode(scsirastools),
-.B scsiinfo(see net), scu(see net), seatools(see seagate)
+.B sdparm(net), sg_wr_mode(sg3_utils), sginfo(sg3_utils),
+.B sgmode(scsirastools), scsiinfo(net), scu(net),
+.B seatools(seagate)
.PP
All these utilities offer some facility to change mode page (or block
descriptor) parameters.
diff --git a/sg_modes.c b/sg_modes.c
index 08e707e6..03e9876d 100644
--- a/sg_modes.c
+++ b/sg_modes.c
@@ -24,7 +24,7 @@
*/
-static char * version_str = "1.08 20050601";
+static char * version_str = "1.09 20050808";
#define ME "sg_modes: "
@@ -463,7 +463,8 @@ static void usage()
" -v verbose\n"
" -V output version string\n"
" -6 Use MODE SENSE(6), by default uses MODE SENSE(10)\n"
- " -? output this usage message\n");
+ " -? output this usage message\n\n"
+ "Performs a SCSI MODE SENSE commmand\n");
}
diff --git a/sg_opcodes.c b/sg_opcodes.c
index 8cb08bc0..8af75743 100644
--- a/sg_opcodes.c
+++ b/sg_opcodes.c
@@ -24,7 +24,7 @@
*/
-static char * version_str = "0.19 20050601";
+static char * version_str = "0.20 20050808";
#define SENSE_BUFF_LEN 32 /* Arbitrary, could be larger */
@@ -142,7 +142,8 @@ static int do_rsoc(int sg_fd, int rep_opts, int rq_opcode, int rq_servact,
res = sg_err_category3(&io_hdr);
switch (res) {
case SG_LIB_CAT_RECOVERED:
- sg_chk_n_print3("Report supported operation codes", &io_hdr);
+ sg_chk_n_print3("Report supported operation codes", &io_hdr,
+ verbose);
/* fall through */
case SG_LIB_CAT_CLEAN:
return 0;
@@ -158,7 +159,7 @@ static int do_rsoc(int sg_fd, int rep_opts, int rq_opcode, int rq_servact,
else
snprintf(ebuff, EBUFF_SZ, "RSOC error, rq_opcode=0x%x, "
"rq_sa=0x%x ", rq_opcode, rq_servact);
- sg_chk_n_print3(ebuff, &io_hdr);
+ sg_chk_n_print3(ebuff, &io_hdr, verbose);
}
return -1;
}
@@ -206,7 +207,8 @@ static int do_rstmf(int sg_fd, void * resp, int mx_resp_len, int noisy,
res = sg_err_category3(&io_hdr);
switch (res) {
case SG_LIB_CAT_RECOVERED:
- sg_chk_n_print3("Report supported task management fns", &io_hdr);
+ sg_chk_n_print3("Report supported task management fns", &io_hdr,
+ verbose);
/* fall through */
case SG_LIB_CAT_CLEAN:
return 0;
@@ -214,7 +216,7 @@ static int do_rstmf(int sg_fd, void * resp, int mx_resp_len, int noisy,
if (noisy | verbose) {
char ebuff[EBUFF_SZ];
snprintf(ebuff, EBUFF_SZ, "RSTMF error ");
- sg_chk_n_print3(ebuff, &io_hdr);
+ sg_chk_n_print3(ebuff, &io_hdr, verbose);
}
return -1;
}
@@ -234,7 +236,9 @@ static void usage()
" -u output list of operation codes as is (unsorted)\n"
" -v verbose\n"
" -V output version string\n"
- " -? output this usage message\n");
+ " -? output this usage message\n\n"
+ "Performs a REPORT SUPPORTED OPERATION CODES (or supported task "
+ "management\nfunctions) SCSI command\n");
}
static const char * scsi_ptype_strs[] = {
diff --git a/sg_persist.c b/sg_persist.c
index ba7e7578..ffd8eed8 100644
--- a/sg_persist.c
+++ b/sg_persist.c
@@ -24,7 +24,7 @@
*/
-static char * version_str = "0.22 20050309";
+static char * version_str = "0.23 20050808";
#define SENSE_BUFF_LEN 32 /* Arbitrary, could be larger */
@@ -153,17 +153,17 @@ static int do_prin(int sg_fd, int rq_servact, void * resp, int mx_resp_len,
res = sg_err_category3(&io_hdr);
switch (res) {
case SG_LIB_CAT_RECOVERED:
- sg_chk_n_print3("PRIN, continuing", &io_hdr);
+ sg_chk_n_print3("PRIN, continuing", &io_hdr, verbose);
/* fall through */
case SG_LIB_CAT_CLEAN:
return 0;
default:
- if (noisy) {
+ if (noisy || verbose) {
char ebuff[EBUFF_SZ];
snprintf(ebuff, EBUFF_SZ, "PRIN error, service_action: %s",
((rq_servact < num_prin_sa_strs) ?
prin_sa_strs[rq_servact] : "??"));
- sg_chk_n_print3(ebuff, &io_hdr);
+ sg_chk_n_print3(ebuff, &io_hdr, verbose);
}
return -1;
}
@@ -216,7 +216,7 @@ static int do_prout(int sg_fd, int rq_servact, int rq_scope,
res = sg_err_category3(&io_hdr);
switch (res) {
case SG_LIB_CAT_RECOVERED:
- sg_chk_n_print3("PROUT, continuing", &io_hdr);
+ sg_chk_n_print3("PROUT, continuing", &io_hdr, verbose);
/* fall through */
case SG_LIB_CAT_CLEAN:
return 0;
@@ -226,7 +226,7 @@ static int do_prout(int sg_fd, int rq_servact, int rq_scope,
snprintf(ebuff, EBUFF_SZ, "PROUT error, service_action: %s",
((rq_servact < num_prout_sa_strs) ?
prout_sa_strs[rq_servact] : "??"));
- sg_chk_n_print3(ebuff, &io_hdr);
+ sg_chk_n_print3(ebuff, &io_hdr, verbose);
}
return -1;
}
@@ -276,7 +276,8 @@ static void usage()
" --unreg|-U optional with PR Out Register and Move\n"
" --verbose|-v output additional debug information\n"
" --version|-V output version string\n"
- " -? output this usage message\n");
+ " -? output this usage message\n\n"
+ "Performs a PERSISTENT RESERVATION (IN or OUT) SCSI command\n");
}
static const char * scsi_ptype_strs[] = {
diff --git a/sg_prevent.c b/sg_prevent.c
index d6b5daeb..e0fa20c3 100644
--- a/sg_prevent.c
+++ b/sg_prevent.c
@@ -47,13 +47,7 @@
* given SCSI device.
*/
-static char * version_str = "1.02 20050309";
-
-#define SENSE_BUFF_LEN 32 /* Arbitrary, could be larger */
-#define DEF_TIMEOUT 60000 /* 60,000 millisecs == 60 seconds */
-
-#define PREVENT_REMOVAL_CMD 0x1e
-#define PREVENT_REMOVAL_CMDLEN 6
+static char * version_str = "1.03 20050808";
#define ME "sg_prevent: "
@@ -82,70 +76,11 @@ static void usage()
"persistent prevent\n"
" --verbose|-v increase verbosity\n"
" --version|-V print version string and exit\n\n"
- " performs a PREVENT ALLOW MEDIUM REMOVAL SCSI command\n"
+ "Performs a PREVENT ALLOW MEDIUM REMOVAL SCSI command\n"
);
}
-/* Invokes a SCSI PREVENT ALLOW MEDIUM REMOVAL command */
-/* Return of 0 -> success, -1 -> failure, SG_LIB_CAT_INVALID_OP ->
- command not supported */
-int sg_ll_prevent(int sg_fd, int prevent, int verbose)
-{
- int k, res;
- unsigned char pCmdBlk[PREVENT_REMOVAL_CMDLEN] =
- {PREVENT_REMOVAL_CMD, 0, 0, 0, 0, 0};
- unsigned char sense_b[SENSE_BUFF_LEN];
- struct sg_io_hdr io_hdr;
-
- if ((prevent < 0) || (prevent > 3)) {
- fprintf(stderr, "prevent argument should be 0, 1, 2 or 3\n");
- return -1;
- }
- pCmdBlk[4] |= (prevent & 0x3);
- if (verbose) {
- fprintf(stderr, " Prevent allow medium removal cdb: ");
- for (k = 0; k < PREVENT_REMOVAL_CMDLEN; ++k)
- fprintf(stderr, "%02x ", pCmdBlk[k]);
- fprintf(stderr, "\n");
- }
-
- memset(&io_hdr, 0, sizeof(struct sg_io_hdr));
- io_hdr.interface_id = 'S';
- io_hdr.cmd_len = PREVENT_REMOVAL_CMDLEN;
- io_hdr.mx_sb_len = sizeof(sense_b);
- io_hdr.dxfer_direction = SG_DXFER_NONE;
- io_hdr.dxfer_len = 0;
- io_hdr.dxferp = NULL;
- io_hdr.cmdp = pCmdBlk;
- io_hdr.sbp = sense_b;
- io_hdr.timeout = DEF_TIMEOUT;
-
- if (ioctl(sg_fd, SG_IO, &io_hdr) < 0) {
- fprintf(stderr, "prevent allow medium removal SG_IO error: %s\n",
- safe_strerror(errno));
- return -1;
- }
- res = sg_err_category3(&io_hdr);
- switch (res) {
- case SG_LIB_CAT_RECOVERED:
- sg_chk_n_print3("Prevent allow medium removal", &io_hdr);
- /* fall through */
- case SG_LIB_CAT_CLEAN:
- return 0;
- case SG_LIB_CAT_INVALID_OP:
- case SG_LIB_CAT_ILLEGAL_REQ:
- if (verbose > 1)
- sg_chk_n_print3("Prevent allow medium removal command problem",
- &io_hdr);
- return res;
- default:
- sg_chk_n_print3("Prevent allow medium removal command problem",
- &io_hdr);
- return -1;
- }
-}
-
int main(int argc, char * argv[])
{
int sg_fd, res, c;
@@ -226,14 +161,17 @@ int main(int argc, char * argv[])
perror("");
return 1;
}
- res = sg_ll_prevent(sg_fd, prevent, verbose);
+ res = sg_ll_prevent_allow(sg_fd, prevent, 1, verbose);
if (0 == res)
ret = 0;
else if (SG_LIB_CAT_INVALID_OP == res)
fprintf(stderr, "Prevent allow medium removal command not "
"supported\n");
+ else if (SG_LIB_CAT_ILLEGAL_REQ == res)
+ fprintf(stderr, "Prevent allow medium removal, bad field in "
+ "command\n");
else
- fprintf(stderr, "Prevent allow medium removal failed\n");
+ fprintf(stderr, "Prevent allow medium removal command failed\n");
res = close(sg_fd);
if (res < 0) {
diff --git a/sg_rbuf.c b/sg_rbuf.c
index 81e7a431..d2192e36 100644
--- a/sg_rbuf.c
+++ b/sg_rbuf.c
@@ -45,7 +45,7 @@
#define ME "sg_rbuf: "
-static char * version_str = "4.82 20050601";
+static char * version_str = "4.83 20050808";
static void usage()
{
@@ -60,7 +60,7 @@ static void usage()
printf(" max total size is 4000 MiB\n");
printf(" -t time the data transfer\n");
printf(" -v increase verbosity (more debug)\n");
- printf(" -V print version string then exit\n");
+ printf(" -V print version string then exit\n\n");
printf("Use SCSI READ BUFFER command (data mode, buffer id 0) "
"repeatedly\n");
}
@@ -216,12 +216,13 @@ int main(int argc, char * argv[])
/* now for the error processing */
switch (sg_err_category3(&io_hdr)) {
case SG_LIB_CAT_RECOVERED:
- sg_chk_n_print3("READ BUFFER descriptor, continuing", &io_hdr);
+ sg_chk_n_print3("READ BUFFER descriptor, continuing", &io_hdr,
+ verbose);
/* fall through */
case SG_LIB_CAT_CLEAN:
break;
default: /* won't bother decoding other categories */
- sg_chk_n_print3("READ BUFFER descriptor error", &io_hdr);
+ sg_chk_n_print3("READ BUFFER descriptor error", &io_hdr, verbose);
if (rawp) free(rawp);
return 1;
}
@@ -337,10 +338,10 @@ int main(int argc, char * argv[])
case SG_LIB_CAT_CLEAN:
break;
case SG_LIB_CAT_RECOVERED:
- sg_chk_n_print3("READ BUFFER data, continuing", &io_hdr);
+ sg_chk_n_print3("READ BUFFER data, continuing", &io_hdr, verbose);
break;
default: /* won't bother decoding other categories */
- sg_chk_n_print3("READ BUFFER data error", &io_hdr);
+ sg_chk_n_print3("READ BUFFER data error", &io_hdr, verbose);
if (rawp) free(rawp);
return 1;
}
diff --git a/sg_read.c b/sg_read.c
index 6c742d0b..a224272e 100644
--- a/sg_read.c
+++ b/sg_read.c
@@ -40,7 +40,7 @@
*/
-static const char * version_str = "1.05 20050329";
+static const char * version_str = "1.06 20050806";
#define DEF_BLOCK_SIZE 512
#define DEF_BLOCKS_PER_TRANSFER 128
@@ -292,14 +292,14 @@ int sg_bread(int sg_fd, unsigned char * buff, int blocks, int from_block,
switch (sg_err_category3(&io_hdr)) {
case SG_LIB_CAT_RECOVERED:
if (verbose > 1)
- sg_chk_n_print3("reading, continue", &io_hdr);
+ sg_chk_n_print3("reading, continue", &io_hdr, 1);
/* fall through */
case SG_LIB_CAT_CLEAN:
break;
case SG_LIB_CAT_MEDIA_CHANGED:
return 2;
default:
- sg_chk_n_print3("reading", &io_hdr);
+ sg_chk_n_print3("reading", &io_hdr, verbose);
return -1;
}
if (diop && *diop &&
diff --git a/sg_read_long.c b/sg_read_long.c
index 0cd080d5..49cb1848 100644
--- a/sg_read_long.c
+++ b/sg_read_long.c
@@ -25,7 +25,7 @@
the sector data and the ECC bytes.
*/
-static char * version_str = "1.05 20050309";
+static char * version_str = "1.06 20050808";
#define READ_LONG_OPCODE 0x3E
#define READ_LONG_CMD_LEN 10
@@ -64,7 +64,8 @@ static void usage()
" --version|-V print version string and"
" exit\n"
" --xfer_len=<num>|-x <num> transfer length (< 10000)"
- " default 520\n"
+ " default 520\n\n"
+ "Perform a READ LONG SCSI command\n"
);
}
@@ -162,17 +163,17 @@ static int sg_ll_read_long10(int sg_fd, int correct, unsigned long lba,
res = sg_err_category3(&io_hdr);
switch (res) {
case SG_LIB_CAT_RECOVERED:
- sg_chk_n_print3("READ LONG(10), continuing", &io_hdr);
+ sg_chk_n_print3("READ LONG(10), continuing", &io_hdr, verbose);
/* fall through */
case SG_LIB_CAT_CLEAN:
return 0;
case SG_LIB_CAT_INVALID_OP:
if (verbose > 1)
- sg_chk_n_print3("READ LONG(10) command problem", &io_hdr);
+ sg_chk_n_print3("READ LONG(10) command problem", &io_hdr, 1);
return res;
default:
if (verbose > 1)
- sg_chk_n_print3("READ LONG(10) sense", &io_hdr);
+ sg_chk_n_print3("READ LONG(10) sense", &io_hdr, 1);
if ((sg_normalize_sense(&io_hdr, &ssh)) &&
(ssh.sense_key == ILLEGAL_REQUEST) &&
((offset = info_offset(io_hdr.sbp, io_hdr.sb_len_wr)))) {
diff --git a/sg_readcap.8 b/sg_readcap.8
index 3a8ba65a..d2f58756 100644
--- a/sg_readcap.8
+++ b/sg_readcap.8
@@ -1,4 +1,4 @@
-.TH SG_READCAP "8" "April 2005" "sg3_utils-1.14" SG3_UTILS
+.TH SG_READCAP "8" "July 2005" "sg3_utils-1.16" SG3_UTILS
.SH NAME
sg_readcap \- calls a READ CAPACITY command on a SCSI device
.SH SYNOPSIS
@@ -30,6 +30,13 @@ block address to (2**32 - 2). When a 10 byte cdb READ CAPACITY command
is used on a device whose size is too large then a last block address
of 0xffffffff is returned (if the device complies with SBC-2).
.TP
+-b
+utility outputs two hex numbers (prefixed with '0x' and space separated)
+to stdout. The first number is the maximum number of blocks on the
+device (which is one plus the lba of the last accessible block). The
+second number is the size of each block. If the operation fails
+then "0x0 0x0" is writtent to stdout.
+.TP
-h
output the usage message then exit.
.TP
@@ -52,6 +59,9 @@ and '-vvv' are also accepted yielding greater verbosity.
-V
outputs version string then exits.
.PP
+On exit this utility returns 0 if it succeeded otherwise a process status
+value of 1 is returned.
+.PP
In the 2.4 series of Linux kernels the given device must be
a SCSI generic (sg) device. In the 2.6 series block devices (e.g. disks
and SCSI DVDs) can also be specified. For example "sg_readcap /dev/sda"
diff --git a/sg_readcap.c b/sg_readcap.c
index 4cd1724e..cce6ba98 100644
--- a/sg_readcap.c
+++ b/sg_readcap.c
@@ -27,7 +27,7 @@
*/
-static char * version_str = "3.72 20050601";
+static char * version_str = "3.74 20050808";
#define ME "sg_readcap: "
@@ -39,21 +39,23 @@ static char * version_str = "3.72 20050601";
void usage ()
{
- fprintf(stderr, "Usage: sg_readcap [-16] [-h] [-lba=<block>] [-pmi] "
- "[-v] [-V]"
- " <device>\n"
- " where -16: use 16 byte read capacity command\n"
- " -h: output this usage message and exit\n"
- " -lba=<block>: yields the last block prior to (head "
+ fprintf(stderr, "Usage: sg_readcap [-16] [-b] [-h] [-lba=<block>] "
+ "[-pmi] [-v] [-V] <device>\n"
+ " where -16 use 16 byte read capacity command\n"
+ " -b brief, two hex numbers: number of blocks "
+ "and block size\n"
+ " -h output this usage message and exit\n"
+ " -lba=<block> yields the last block prior to (head "
"movement) delay\n"
" after <block> [in hex (def: 0) "
"valid with -pmi]\n"
- " -pmi: partial medium indicator (without this switch "
+ " -pmi partial medium indicator (without this switch "
"shows total\n"
" disk capacity)\n"
- " -v: increase verbosity\n"
- " -V: output version string and exit\n"
- " <device>: sg device (or block device in lk 2.6)\n");
+ " -v increase verbosity\n"
+ " -V output version string and exit\n"
+ " <device> sg device (or block device in lk 2.6)\n\n"
+ "Perform a READ CAPACITY SCSI command\n");
}
int main(int argc, char * argv[])
@@ -62,6 +64,7 @@ int main(int argc, char * argv[])
unsigned int lba = 0;
unsigned long long llba = 0;
unsigned long long u, llast_blk_addr;
+ int brief = 0;
int pmi = 0;
int do16 = 0;
int verbose = 0;
@@ -88,6 +91,9 @@ int main(int argc, char * argv[])
} else
jmp_out = 1;
break;
+ case 'b':
+ brief = 1;
+ break;
case 'p':
if (0 == strncmp("pmi", cp, 3)) {
pmi = 1;
@@ -160,13 +166,17 @@ int main(int argc, char * argv[])
if (! do16) {
res = sg_ll_readcap_10(sg_fd, pmi, lba, resp_buff, RCAP_REPLY_LEN,
- verbose);
+ 1, verbose);
if (0 == res) {
last_blk_addr = ((resp_buff[0] << 24) | (resp_buff[1] << 16) |
(resp_buff[2] << 8) | resp_buff[3]);
if (0xffffffff != last_blk_addr) {
block_size = ((resp_buff[4] << 24) | (resp_buff[5] << 16) |
(resp_buff[6] << 8) | resp_buff[7]);
+ if (brief) {
+ printf("0x%x 0x%x\n", last_blk_addr + 1, block_size);
+ goto good;
+ }
printf("Read Capacity results:\n");
if (pmi)
printf(" PMI mode: given lba=0x%x, last block before "
@@ -189,6 +199,7 @@ int main(int argc, char * argv[])
printf(" Device size: %llu bytes, %.1f MiB, %.2f GB\n",
total_sz, sz_mb, sz_gb);
}
+ goto good;
} else {
printf("READ CAPACITY (10) indicates device capacity too "
"large\n now trying 16 byte cdb variant\n");
@@ -208,12 +219,13 @@ int main(int argc, char * argv[])
"READ CAPACITY (16)\n");
} else if (SG_LIB_CAT_ILLEGAL_REQ == res)
fprintf(stderr, "bad field in READ CAPACITY (10) cdb\n");
- else if (verbose)
- fprintf(stderr, "READ CAPACITY (10) failed [res=%d]\n", res);
+ else if (! verbose)
+ fprintf(stderr, "READ CAPACITY (10) failed [res=%d], try "
+ "with '-v'\n", res);
}
if (do16) {
res = sg_ll_readcap_16(sg_fd, pmi, llba, resp_buff, RCAP16_REPLY_LEN,
- verbose);
+ 1, verbose);
if (0 == res) {
for (k = 0, llast_blk_addr = 0; k < 8; ++k) {
llast_blk_addr <<= 8;
@@ -221,6 +233,10 @@ int main(int argc, char * argv[])
}
block_size = ((resp_buff[8] << 24) | (resp_buff[9] << 16) |
(resp_buff[10] << 8) | resp_buff[11]);
+ if (brief) {
+ printf("0x%llx 0x%x\n", llast_blk_addr + 1, block_size);
+ goto good;
+ }
printf("Read Capacity results:\n");
printf(" Protection: prot_en=%d, rto_en=%d\n",
!!(resp_buff[12] & 0x1), !!(resp_buff[12] & 0x2));
@@ -245,14 +261,22 @@ int main(int argc, char * argv[])
printf(" Device size: %llu bytes, %.1f MiB, %.2f GB\n",
total_sz, sz_mb, sz_gb);
}
+ goto good;
}
else if (SG_LIB_CAT_INVALID_OP == res)
fprintf(stderr, "READ CAPACITY (16) not supported\n");
else if (SG_LIB_CAT_ILLEGAL_REQ == res)
fprintf(stderr, "bad field in READ CAPACITY (10) cdb\n");
- else if (verbose)
- fprintf(stderr, "READ CAPACITY (16) failed [res=%d]\n", res);
+ else if (! verbose)
+ fprintf(stderr, "READ CAPACITY (16) failed [res=%d], try "
+ "with '-v'\n", res);
}
+ if (brief)
+ printf("0x0 0x0\n");
+ close(sg_fd);
+ return 1;
+
+good:
close(sg_fd);
return 0;
}
diff --git a/sg_reassign.8 b/sg_reassign.8
index c10e26c1..5ad3e130 100644
--- a/sg_reassign.8
+++ b/sg_reassign.8
@@ -1,4 +1,4 @@
-.TH SG_REASSIGN "8" "March 2005" "sg3_utils-1.14" SG3_UTILS
+.TH SG_REASSIGN "8" "August 2005" "sg3_utils-1.16" SG3_UTILS
.SH NAME
sg_reassign \- reassign defective blocks on the given (disk) device
.SH SYNOPSIS
@@ -93,7 +93,7 @@ a reasonable metric of its health. If the grown list starts growing
quickly that is an ominous sign. The best grown defect lists are empty
ones. The number of elements in the grown defect list can be viewed with
the '--grown' option. The contents of the grown defect list can be
-viewed with 'sginfo -G' utility.
+viewed with the 'sginfo -G' utility.
.PP
If an unrecoverable error is detected at a logical block address then
REASSIGN BLOCKS is needed to reassign the block. Also if the ARRE and/or
diff --git a/sg_reassign.c b/sg_reassign.c
index c08adcbb..08d6b87e 100644
--- a/sg_reassign.c
+++ b/sg_reassign.c
@@ -50,7 +50,7 @@
* vendor specific data is written.
*/
-static char * version_str = "1.02 20050331";
+static char * version_str = "1.03 20050808";
#define ME "sg_reassign: "
@@ -111,6 +111,7 @@ static void usage()
"list length\n"
" --verbose | -v increase verbosity\n"
" --version | -V print version string and exit\n\n"
+ "Perform a REASSIGN BLOCKS SCSI command\n"
);
}
@@ -163,14 +164,14 @@ int sg_ll_reassign_blocks(int sg_fd, int dummy, int longlba, int longlist,
res = sg_err_category3(&io_hdr);
switch (res) {
case SG_LIB_CAT_RECOVERED:
- sg_chk_n_print3("Reassign blocks, continuing", &io_hdr);
+ sg_chk_n_print3("Reassign blocks, continuing", &io_hdr, verbose);
/* fall through */
case SG_LIB_CAT_CLEAN:
return 0;
case SG_LIB_CAT_INVALID_OP:
case SG_LIB_CAT_ILLEGAL_REQ:
if (verbose > 1)
- sg_chk_n_print3("Reassign blocks error", &io_hdr);
+ sg_chk_n_print3("Reassign blocks error", &io_hdr, 1);
return res;
default:
if (noisy || verbose) {
@@ -178,7 +179,7 @@ int sg_ll_reassign_blocks(int sg_fd, int dummy, int longlba, int longlist,
snprintf(ebuff, EBUFF_SZ, "Reassign blocks error, longlba=%d "
"longlist=%d\n ", longlba, longlist);
- sg_chk_n_print3(ebuff, &io_hdr);
+ sg_chk_n_print3(ebuff, &io_hdr, verbose);
}
return -1;
}
diff --git a/sg_requests.8 b/sg_requests.8
index 334ca4cb..b5b000de 100644
--- a/sg_requests.8
+++ b/sg_requests.8
@@ -1,4 +1,4 @@
-.TH SG_REQUESTS "8" "November 2004" "sg3_utils-1.11" SG3_UTILS
+.TH SG_REQUESTS "8" "August 2005" "sg3_utils-1.16" SG3_UTILS
.SH NAME
sg_requests \- send the scsi command request sense
.SH SYNOPSIS
@@ -24,23 +24,34 @@ output the usage message then exit.
.TP
--verbose | -v
increase the level of verbosity, (i.e. debug output).
+Additionally the response (if received) is output in ASCII-HEX. Use
+this option multiple times for greater verbosity.
.TP
--version | -V
print the version string and then exit.
.PP
-Some time ago the REQUEST SENSE command was very important for error
+In SCSI 1 and 2 the REQUEST SENSE command was very important for error
and warning processing in SCSI. The autosense capability rendered this
-command almost superfluous. However recent SCSI drafts (e.g. SBC-2 rev
-16) increase the utility of the REQUEST SENSE command. Idle and standby
-power conditions can now be detected with this command. Interestingly
-the sense key is set to "no sense" while the asc/ascq code convey the
-information (e.g. 0x5e/0x4 "Standby condition activated by command").
+command almost superfluous.
+.PP
+However recent SCSI drafts (e.g. SPC rev 23 and SBC-2 rev 16) increase
+the utility of the REQUEST SENSE command. Idle and standby power
+conditions can now be detected with this command; a progress indication
+is given during FORMAT (when that command was started with with IMMED=1
+in its parameter header); and the Filemark, ILI and EOM bits may be
+set (e.g. by a tape drive). Interestingly the sense key is set
+to "no sense" while the asc/ascq code convey the information (e.g.
+0x5e/0x4 "Standby condition activated by command").
+.PP
+The REQUEST SENSE command is not marked as mandatory in SPC-3 (i.e. for
+all SCSI devices) but is marked as mandatory in SBC-2 (i.e. for disks),
+SSC-3 (i.e. for tapes) and MMC-4 (i.e. for CD/DVD drives).
.SH AUTHORS
Written by Douglas Gilbert.
.SH "REPORTING BUGS"
Report bugs to <dgilbert at interlog dot com>.
.SH COPYRIGHT
-Copyright \(co 2004 Douglas Gilbert
+Copyright \(co 2004-2005 Douglas Gilbert
.br
This software is distributed under a FreeBSD license. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
diff --git a/sg_requests.c b/sg_requests.c
index c9c7d226..78d5c503 100644
--- a/sg_requests.c
+++ b/sg_requests.c
@@ -47,7 +47,7 @@
* This program issues the SCSI command REQUEST SENSE to the given SCSI device.
*/
-static char * version_str = "1.07 20050511";
+static char * version_str = "1.09 20050808";
#define REQUEST_SENSE_BUFF_LEN 252
@@ -71,7 +71,8 @@ static void usage()
"format\n"
" --help|-h print out usage message\n"
" --verbose|-v increase verbosity\n"
- " --version|-V print version string and exit\n"
+ " --version|-V print version string and exit\n\n"
+ "Perform a REQUEST SENSE SCSI command\n"
);
}
@@ -144,11 +145,11 @@ int main(int argc, char * argv[])
memset(requestSenseBuff, 0x0, sizeof(requestSenseBuff));
res = sg_ll_request_sense(sg_fd, desc, requestSenseBuff,
- sizeof(requestSenseBuff), verbose);
+ sizeof(requestSenseBuff), 1, verbose);
if (0 == res) {
resp_len = requestSenseBuff[7] + 8;
fprintf(stderr, "Decode response as sense data:\n");
- sg_print_sense(NULL, requestSenseBuff, resp_len);
+ sg_print_sense(NULL, requestSenseBuff, resp_len, verbose);
if (verbose) {
fprintf(stderr, "\nOutput response in hex\n");
dStrHex((const char *)requestSenseBuff, resp_len, 1);
@@ -158,9 +159,12 @@ int main(int argc, char * argv[])
fprintf(stderr, "Request Sense command not supported\n");
else if (SG_LIB_CAT_ILLEGAL_REQ == res)
fprintf(stderr, "bad field in Request Sense cdb\n");
- else
+ else {
fprintf(stderr, "Request Sense command failed\n");
-
+ if (0 == verbose)
+ fprintf(stderr, " try the '-v' option for "
+ "more information\n");
+ }
res = close(sg_fd);
if (res < 0) {
perror(ME "close error");
diff --git a/sg_rmsn.c b/sg_rmsn.c
index 84eddbcb..9b831cc2 100644
--- a/sg_rmsn.c
+++ b/sg_rmsn.c
@@ -48,7 +48,7 @@
* to the given SCSI device.
*/
-static char * version_str = "1.00 20050329";
+static char * version_str = "1.01 20050808";
#define ME "sg_rmsn: "
@@ -66,19 +66,19 @@ static struct option long_options[] = {
static void usage()
{
fprintf(stderr, "Usage: "
- "sg_rmsn [--help] [--verbose] [--version] <scsi_device>\n"
- " where: --help|-h print out usage message\n"
- " --raw|-r output serial number to stdout\n"
- " --verbose|-v increase verbosity\n"
- " --version|-V print version string and exit\n"
- "Sends SCSI READ MEDIA SERIAL NUMBER command\n"
+ "sg_rmsn [--help] [--raw] [--verbose] [--version] <scsi_device>\n"
+ " where: --help|-h print out usage message\n"
+ " --raw|-r output serial number to stdout "
+ "(potentially binary)\n"
+ " --verbose|-v increase verbosity\n"
+ " --version|-V print version string and exit\n\n"
+ "Performs a READ MEDIA SERIAL NUMBER SCSI command\n"
);
-
}
int main(int argc, char * argv[])
{
- int sg_fd, res, c, sn_len;
+ int sg_fd, res, c, sn_len, n;
unsigned char rmsn_buff[4];
unsigned char * ucp = NULL;
int raw = 0;
@@ -145,55 +145,59 @@ int main(int argc, char * argv[])
memset(rmsn_buff, 0x0, sizeof(rmsn_buff));
res = sg_ll_read_media_serial_num(sg_fd, rmsn_buff, sizeof(rmsn_buff),
- 1, verbose);
+ 1, verbose);
if (0 == res) {
sn_len = (rmsn_buff[0] << 24) + (rmsn_buff[1] << 16) +
- (rmsn_buff[2] << 8) + rmsn_buff[3] + 4;
- if (! raw)
+ (rmsn_buff[2] << 8) + rmsn_buff[3];
+ if (! raw)
printf("Reported serial number length = %d\n", sn_len);
- if (0 == sn_len) {
- fprintf(stderr, " This implies the media has no serial "
- "number\n");
- goto err_out;
- }
- if (sn_len > SERIAL_NUM_SANITY_LEN) {
+ if (0 == sn_len) {
+ fprintf(stderr, " This implies the media has no serial "
+ "number\n");
+ goto err_out;
+ }
+ if (sn_len > SERIAL_NUM_SANITY_LEN) {
fprintf(stderr, " That length (%d) seems too long for a "
- "serial number\n", sn_len);
- goto err_out;
- }
- sn_len += 4;
- ucp = malloc(sn_len);
- if (NULL == ucp) {
+ "serial number\n", sn_len);
+ goto err_out;
+ }
+ sn_len += 4;
+ ucp = malloc(sn_len);
+ if (NULL == ucp) {
fprintf(stderr, " Out of memory (ram)\n");
- goto err_out;
- }
+ goto err_out;
+ }
res = sg_ll_read_media_serial_num(sg_fd, ucp, sn_len, 1, verbose);
- if (0 == res) {
+ if (0 == res) {
sn_len = (ucp[0] << 24) + (ucp[1] << 16) + (ucp[2] << 8) +
- ucp[3] + 4;
- if (raw) {
- if (sn_len > 0)
- fwrite(ucp + 4, 1, sn_len, stdout);
- } else {
+ ucp[3];
+ if (raw) {
+ if (sn_len > 0)
+ n = fwrite(ucp + 4, 1, sn_len, stdout);
+ } else {
printf("Serial number:\n");
- if (sn_len > 0)
+ if (sn_len > 0)
dStrHex((const char *)ucp + 4, sn_len, 0);
- ret = 0;
- }
- } else if (SG_LIB_CAT_INVALID_OP == res)
+ }
+ ret = 0;
+ }
+ }
+ if (0 != res) {
+ if (SG_LIB_CAT_INVALID_OP == res)
fprintf(stderr, "Read Media Serial Number command not "
- "supported (b)\n");
+ "supported\n");
else if (SG_LIB_CAT_ILLEGAL_REQ == res)
- fprintf(stderr, "bad field in Read Media Serial Number cdb "
- "(b)\n");
- } else if (SG_LIB_CAT_INVALID_OP == res)
- fprintf(stderr, "Read Media Serial Number command not supported\n");
- else if (SG_LIB_CAT_ILLEGAL_REQ == res)
- fprintf(stderr, "bad field in Read Media Serial Number cdb\n");
+ fprintf(stderr, "bad field in Read Media Serial Number cdb\n");
+ else {
+ fprintf(stderr, "Read Media Serial Number failed\n");
+ if (0 == verbose)
+ fprintf(stderr, " try '-v' for more information\n");
+ }
+ }
err_out:
if (ucp)
- free(ucp);
+ free(ucp);
res = close(sg_fd);
if (res < 0) {
perror(ME "close error");
diff --git a/sg_rtpg.c b/sg_rtpg.c
index c0956bd5..1d685ad9 100644
--- a/sg_rtpg.c
+++ b/sg_rtpg.c
@@ -48,7 +48,7 @@
* to the given SCSI device.
*/
-static char * version_str = "1.04 20050314";
+static char * version_str = "1.05 20050808";
#define REPORT_TGT_GRP_BUFF_LEN 1024
@@ -103,7 +103,8 @@ static void usage()
" --help|-h print out usage message\n"
" --hex|-H print out response in hex\n"
" --verbose|-v increase verbosity\n"
- " --version|-V print version string and exit\n"
+ " --version|-V print version string and exit\n\n"
+ "Performs a REPORT TARGET PORT GROUPS SCSI command\n"
);
}
@@ -292,6 +293,11 @@ int main(int argc, char * argv[])
fprintf(stderr, "Report Target Port Groups command not supported\n");
else if (SG_LIB_CAT_ILLEGAL_REQ == res)
fprintf(stderr, "bad field in Report Target Port Groups cdb\n");
+ else {
+ fprintf(stderr, "Report Target Port Groups command failed\n");
+ if (0 == verbose)
+ fprintf(stderr, " try '-v' for more information\n");
+ }
err_out:
res = close(sg_fd);
diff --git a/sg_scan.c b/sg_scan.c
index 160167a1..5d31c495 100644
--- a/sg_scan.c
+++ b/sg_scan.c
@@ -38,7 +38,7 @@
F. Jansen - modification to extend beyond 26 sg devices.
*/
-static char * version_str = "4.03 20050603";
+static char * version_str = "4.04 20050806";
#define ME "sg_scan: "
@@ -362,13 +362,13 @@ int sg3_inq(int sg_fd, unsigned char * inqBuff, int do_extra)
/* now for the error processing */
switch (sg_err_category3(&io_hdr)) {
case SG_LIB_CAT_RECOVERED:
- sg_chk_n_print3("Inquiry, continuing", &io_hdr);
+ sg_chk_n_print3("Inquiry, continuing", &io_hdr, 1);
/* fall through */
case SG_LIB_CAT_CLEAN:
break;
default: /* won't bother decoding other categories */
ok = 0;
- sg_chk_n_print3("INQUIRY command error", &io_hdr);
+ sg_chk_n_print3("INQUIRY command error", &io_hdr, 1);
break;
}
}
diff --git a/sg_senddiag.8 b/sg_senddiag.8
index 1dcaae27..1b46d5cd 100644
--- a/sg_senddiag.8
+++ b/sg_senddiag.8
@@ -1,4 +1,4 @@
-.TH SG_SENDDIAG "8" "June 2005" "sg3_utils-1.15" SG3_UTILS
+.TH SG_SENDDIAG "8" "August 2005" "sg3_utils-1.16" SG3_UTILS
.SH NAME
sg_senddiag \- performs a SCSI SEND DIAGNOSTIC command
.SH SYNOPSIS
@@ -15,7 +15,7 @@ It can issue self tests, find supported diagnostic pages or
send arbitrary diagnostic pages.
.PP
When the '-l' option and a <scsi_device> are given then the utility
-sends a RECEIVE DIAGNOSTIC SCSI command to fetch the response (i.e.
+sends a RECEIVE DIAGNOSTIC RESULTS SCSI command to fetch the response (i.e.
the page numbers of supported diagnostic pages).
.PP
When the '-l' option is given without a <scsi_device> then a
@@ -34,18 +34,19 @@ is given in seconds (and minutes in parentheses). This figure is obtained
from mode page 0xa (control page).
.TP
-h
-outputs response from RECEIVE DIAGNOSTIC in hex rather than decode it.
+outputs response from RECEIVE DIAGNOSTIC RESULTS in hex rather than decode
+it.
.TP
-H
-outputs response from RECEIVE DIAGNOSTIC in hex rather than decode it.
+outputs response from RECEIVE DIAGNOSTIC RESULTS in hex rather than decode it.
.TP
-l
when a <scsi_device> is also given lists the names of all diagnostic
pages supported by this device. The request is sent via a SEND DIAGNOSTIC
-command (with the "pf" bit set) and the response is fetched by a RECEIVE DIAGNOSTIC command.
-When used in the absence of a <scsi_device> argument then a
-list of diagnostic page names and their numbers, known by this
-utility, are listed.
+command (with the "pf" bit set) and the response is fetched by a RECEIVE
+DIAGNOSTIC RESULTS command. When used in the absence of a <scsi_device>
+argument then a list of diagnostic page names and their numbers, known
+by this utility, are listed.
.TP
-pf
set Page Format (PF) bit. By default it is clear (i.e. 0) unless
@@ -123,7 +124,7 @@ Arbitrary diagnostic pages can be read (in hex) with the sg_ses
utility (not only those defined in SES-2).
.PP
If the utility is used with no options (e.g. "sg_senddiag /dev/sg1")
-Then a degenerate SEND DIAGNOSTICS SCSI command is sent with zero
+Then a degenerate SEND DIAGNOSTIC SCSI command is sent with zero
in all its fields apart from the opcode. Some devices report this
as an error while others ignore it. It is not entirely clear from
SPC-3 if it is invalid to send such a command.
@@ -133,9 +134,9 @@ a SCSI generic (sg) device. In the 2.6 series block devices (e.g. disks
and SCSI DVDs) can also be specified. For example 'sg_senddiag -t /dev/sda'
will work in the 2.6 series kernels.
.PP
-To access SCSI enclosures see the sg_ses utility. sg_ses uses SCSI
-SEND and RECEIVE DIAGNOSTICS commands as outlined in the SES-2 (draft)
-standard.
+To access SCSI enclosures see the sg_ses utility. sg_ses uses the
+SEND DIAGNOSTIC and RECEIVE DIAGNOSTIC RESULTS SCSI commands as outlined
+in the SES-2 (draft) standard.
.SH AUTHOR
Written by Doug Gilbert
.SH "REPORTING BUGS"
diff --git a/sg_senddiag.c b/sg_senddiag.c
index 897181c3..56d590d3 100644
--- a/sg_senddiag.c
+++ b/sg_senddiag.c
@@ -22,7 +22,7 @@
the SCSI RECEIVE DIAGNOSTIC command to list supported diagnostic pages.
*/
-static char * version_str = "0.26 20050604";
+static char * version_str = "0.27 20050808";
#define ME "sg_senddiag: "
@@ -260,13 +260,16 @@ static void usage()
" -uoff unit online (def: 0, only with '-t')\n"
" -v increase verbosity (print issued SCSI cmds)\n"
" -V output version string\n"
- " -? output this usage message\n");
+ " -? output this usage message\n\n"
+ "Performs a SEND DIAGNOSTIC (and/or a RECEIVE DIAGNOSTIC RESULTS)"
+ " SCSI command\n"
+ );
}
int main(int argc, char * argv[])
{
- int sg_fd, k, num, rsp_len, read_in_len, plen, jmp_out;
+ int sg_fd, k, num, rsp_len, plen, jmp_out;
const char * file_name = 0;
char ebuff[EBUFF_SZ];
unsigned char rsp_buff[MX_ALLOC_LEN];
@@ -283,6 +286,7 @@ int main(int argc, char * argv[])
int do_raw = 0;
int verbose = 0;
int oflags = O_RDWR | O_NONBLOCK;
+ int read_in_len = 0;
const char * cp;
unsigned char read_in[MX_ALLOC_LEN];
int ret = 1;
diff --git a/sg_ses.8 b/sg_ses.8
index e82237a4..4e5230cc 100644
--- a/sg_ses.8
+++ b/sg_ses.8
@@ -1,4 +1,4 @@
-.TH SG_SES "8" "May 2005" "sg3_utils-1.15" SG3_UTILS
+.TH SG_SES "8" "July 2005" "sg3_utils-1.16" SG3_UTILS
.SH NAME
sg_ses \- send controls and fetch status from a SCSI Enclosure
Services (SES) device
@@ -92,6 +92,11 @@ This utility can be used to fetch arbitrary (i.e. non SES) diagnostic
pages (using the READ DIAGNOSTIC SCSI command). To this end the '--page='
and '--hex' options would be appropriate. Arbitrary diagnostic pages can
be sent to a device with the sg_senddiag utility.
+.PP
+There is a related command set called SAF-TE (SCSI attached fault-tolerant
+enclosure) for enclosure (including RAID) status and control. SCSI devices
+that support SAF-TE report "Processor" peripheral device type (0x3) in their
+INQUIRY reponse. See safte-monitor on the internet.
.SH EXAMPLE
Changing a temperature threshold is possible, if a little awkward. The
current thresholds can be shown with:
@@ -125,4 +130,4 @@ Copyright \(co 2004-2005 Douglas Gilbert
This software is distributed under a FreeBSD liense. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
.SH "SEE ALSO"
-.B sg_inq, sg_senddiag (in sg3_utils package)
+.B sg_inq, sg_senddiag (in sg3_utils package); safte-monitor (internet)
diff --git a/sg_ses.c b/sg_ses.c
index 663fbc59..6aa436c7 100644
--- a/sg_ses.c
+++ b/sg_ses.c
@@ -43,11 +43,11 @@
/* A utility program for the Linux OS SCSI subsystem.
*
- * This program issues SCSI SEND DIAGNOSTIC and RECEIVE DIAGNOSTIC commands
- * tailored for SES (enclosure) devices.
+ * This program issues SCSI SEND DIAGNOSTIC and RECEIVE DIAGNOSTIC RESULTS
+ *commands tailored for SES (enclosure) devices.
*/
-static char * version_str = "1.17 20050512";
+static char * version_str = "1.18 20050808";
#define MX_ALLOC_LEN 4096
#define MX_ELEM_HDR 512
@@ -103,7 +103,8 @@ static void usage()
"for '-d'\n"
" --status|-s fetch status information\n"
" --verbose|-v increase verbosity\n"
- " --version|-V print version string and exit\n"
+ " --version|-V print version string and exit\n\n"
+ "Fetches status or sends control data to a SCSI enclosure\n"
);
}
diff --git a/sg_start.8 b/sg_start.8
index e7ff9c60..2796103f 100644
--- a/sg_start.8
+++ b/sg_start.8
@@ -1,26 +1,31 @@
-.TH SG_START "8" "June 2005" "sg3_utils-1.15" SG3_UTILS
+.TH SG_START "8" "August 2005" "sg3_utils-1.16" SG3_UTILS
.SH NAME
-sg_start \- starts (spins-up) or stops (spins down) SCSI devices
+sg_start \- starts (spins-up) or stops (spins down) SCSI device, load or
+eject medium
.SH SYNOPSIS
.B sg_start
-[\fI-imm=0|1\fR] [\fI-loej\fR] [\fI-pc=<n>\fR]
-[\fI-start\fR] [\fI-start\fR] [\fI-v\fR] [\fI-V\fR] [\fI0|1\fR]
+[\fI-eject\fR] [\fI-imm=0|1\fR] [\fI-load\fR] [\fI-loej\fR] [\fI-pc=<n>\fR]
+[\fI-start\fR] [\fI-stop\fR] [\fI-v\fR] [\fI-V\fR] [\fI0|1\fR]
\fI<scsi_device>\fR
.SH DESCRIPTION
.\" Add any additional description here
.PP
sg_start sends a START STOP UNIT SCSI command to the given device with
-the selected options. The most used options are "-stop" to spin down a disk
-and "-start" to spin up a disk. Using "sg_start -start /dev/sda" on a disk
+the selected options. The most used options are '-stop' to spin down a disk
+and '-start' to spin up a disk. Using 'sg_start -start /dev/sda' on a disk
that is already spinning is harmless. There is also finer grain control
with "power conditions": active, idle and standby. In some contexts
the "stop" state can be considered an additional power condition.
.PP
Devices that contain removable media such as cd/dvds can use the '-loej'
-flag to load the media when used in conjunction with "-start" (i.e. load
-media then spin up). Alternatively '-loej' may be used to eject the media
-when used alone or when used in conjunction with "-stop" (i.e. spin down
-then eject media).
+flag to load the medium when used in conjunction with '-start' (i.e. load
+medium then spin up). Alternatively '-loej' may be used to eject the medium
+when used alone or when used in conjunction with '-stop' (i.e. spin down
+then eject medium). More simply the loading and ejecting of a removable
+medium can be requested with the '-load' and '-eject' options.
+.PP
+If no option or argument is given that implies some action, a '-start'
+is assumed.
.TP
0
stop (spin-down) given device.
@@ -31,11 +36,19 @@ start (spin-up) given device.
Active when '-pc=" is not given or '-pc=0'. Harmless if device has
already started (or is in the process of starting).
.TP
+-eject
+stop the medium and eject it from the drive. Only appropriate for a
+removable medium.
+.TP
-imm=0|1
-when the immediate bit is 1 (default) then this command (and hence this
-utility) return immediately after the device has received the command.
-When this option is 0 then the command returns when the action it
-requests has been completed.
+when the immediate bit is 1 then this utility returns immediately after
+the device has received the command. When this option is 0 (the default)
+then the utility returns once the command has completed its action
+(i.e. it waits until the device is started or stopped).
+.TP
+-load
+load the medium in the drive and start it. Only appropriate for a
+removable medium.
.TP
-loej
load the media when the unit is started or eject it when the unit is
@@ -48,13 +61,15 @@ stop and eject action is assumed.
set the 'power conditions' value (in hex); 0 to f (inclusive) are valid.
Default value is 0.
When '-pc=0' then '-start', '-stop' and '-loej' are active.
-Some common values are 1 for the active power condition; 2 for the idle
-power condition; 3 for the standby power condition, 7 for LU_CONTROL,
-a (hex == decimal 10) for FORCE_IDLE_0 and b (hex) for FORCE_STANDBY_0.
-See recent SBC-2 or SAS drafts at www.t10.org for more information.
+Some common values are 1 for the active power condition (SBC); 2 for the
+idle power condition; 3 for the standby power condition; 5 for sleep
+power condition (MMC); 7 for LU_CONTROL (SBC), 0xa (decimal 10) for
+FORCE_IDLE_0 (SBC) and 0xb (decimal 11) for FORCE_STANDBY_0 (SBC).
+See recent SBC-2, MMC-4 and SAS drafts at www.t10.org for more information.
.TP
-start
-start (spin-up) given device. Same meaning as "1" argument.
+start (spin-up) given device. Using this option on an already started
+device is harmless. Same meaning as "1" argument.
.TP
-stop
stop (spin-down) given device. Same meaning as "0" argument.
@@ -66,7 +81,11 @@ it. '-vv' and '-vvv' are also accepted yielding greater verbosity.
-V
print out version string then exit.
.PP
-Only one of "0", "1", "-start" and "-stop" is accepted to avoid confusion.
+To avoid confusion, only one of "0", "1", "-start" and "-stop" can
+be given.
+.PP
+If this utility succeeds then its process exits with a status of 0;
+otherwise it exits with a non-zero status.
.PP
There is an associated "power condition" mode page (0x1a) in which timer
values can be set for transitioning to either idle or standby state after
@@ -77,7 +96,7 @@ a REQUEST SENSE command (see the sg_requests utility) should yield
a sense key of "no sense" and an additional sense code of "Low
power condition on".
.PP
-Ejection of removable media (e.g. 'sg_start 0 -loej /dev/hdd' where
+Ejection of removable media (e.g. 'sg_start -eject /dev/hdd' where
the device is an ATAPI cd/dvd drive) may be prevented by a prior
PREVENT ALLOW MEDIUM REMOVAL SCSI command (see sg_prevent). In this
case this utility should fail with an error generated by the device:
diff --git a/sg_start.c b/sg_start.c
index d7bbeaba..14955d90 100644
--- a/sg_start.c
+++ b/sg_start.c
@@ -8,6 +8,7 @@
#include <sys/types.h>
#include "sg_include.h"
#include "sg_lib.h"
+#include "sg_cmds.h"
/*
* Copyright (C) 1999-2005 D. Gilbert
@@ -28,95 +29,39 @@
*/
-static char * version_str = "0.43 20050603";
+static char * version_str = "0.45 20050810";
-#define START_STOP_CMD 0x1b
-#define START_STOP_CMDLEN 6
-#define DEF_TIMEOUT 120000 /* 120,000 millisecs == 2 minutes */
-
-
-/* Returns 0 if successful, else -1. */
-static int do_start_stop(int fd, int start, int immed, int loej,
- int power_conditions, int verbose)
-{
- unsigned char cmdblk[START_STOP_CMDLEN] = {
- START_STOP, /* Command */
- 0, /* Resvd/Immed */
- 0, /* Reserved */
- 0, /* Reserved */
- 0, /* PowCond/Resvd/LoEj/Start */
- 0 }; /* Reserved/Flag/Link */
- unsigned char sense_b[32];
- struct sg_io_hdr io_hdr;
- int k, res;
-
- memset(&io_hdr, 0, sizeof(struct sg_io_hdr));
- cmdblk[1] = immed & 1;
- cmdblk[4] = ((power_conditions & 0xf) << 4) |
- ((loej & 1) << 1) | (start & 1);
- io_hdr.interface_id = 'S';
- io_hdr.cmd_len = sizeof(cmdblk);
- io_hdr.mx_sb_len = sizeof(sense_b);
- io_hdr.dxfer_direction = SG_DXFER_NONE;
- io_hdr.dxfer_len = 0;
- io_hdr.dxferp = NULL;
- io_hdr.cmdp = cmdblk;
- io_hdr.sbp = sense_b;
- io_hdr.timeout = DEF_TIMEOUT;
- if (verbose) {
- printf(" Start/Stop command:");
- for (k = 0; k < (int)sizeof(cmdblk); ++k)
- printf (" %02x", cmdblk[k]);
- printf("\n");
- }
-
- if (ioctl(fd, SG_IO, &io_hdr) < 0) {
- perror("start_stop (SG_IO) error");
- return -1;
- }
- if (verbose > 2)
- fprintf(stderr, " duration=%u ms\n",
- io_hdr.duration);
- res = sg_err_category3(&io_hdr);
- if (SG_LIB_CAT_MEDIA_CHANGED == res) {
- fprintf(stderr, "media change report, try start_stop again\n");
- if (ioctl(fd, SG_IO, &io_hdr) < 0) {
- perror("start_stop (SG_IO) error");
- return -1;
- }
- res = sg_err_category3(&io_hdr);
- }
- if (SG_LIB_CAT_CLEAN != res) {
- sg_chk_n_print3("start_stop", &io_hdr);
- return -1;
- }
- return 0;
-}
void usage ()
{
- fprintf(stderr, "Usage: sg_start [0|-stop|1|-start] [-imm=0|1] "
- "[-loej] [-pc=<n>] [-v] [-V]\n"
- " <scsi_device>\n"
+ fprintf(stderr, "Usage: sg_start [0|-stop|1|-start] [-eject] "
+ "[-imm=0|1] [-load]\n"
+ " [-loej] [-pc=<n>] [-v] [-V] "
+ "<scsi_device>\n"
" where: 0 stop unit (e.g. spin down a disk or a "
"cd/dvd)\n"
" 1 start unit (e.g. spin up a disk or a "
"cd/dvd)\n"
- " -imm=0|1 0->await completion, 1->return "
- "immediately(def)\n"
+ " -eject stop then eject the medium\n"
+ " -imm=0|1 0->await completion(def), 1->return "
+ "immediately\n"
+ " -load load then start the medium\n"
" -loej load the medium if '-start' option is "
"also given\n"
" or stop unit and eject\n"
" -pc=<n> power conditions (in hex, default 0 -> no "
"power condition)\n"
- " 1 -> active, 2 -> idle, 3 -> standby\n"
+ " 1 -> active, 2 -> idle, 3 -> standby, "
+ "5 -> sleep (MMC)\n"
" -start start unit (same as '1')\n"
" -stop stop unit (same as '0')\n"
" -v verbose (print out SCSI commands)\n"
" -V print version string then exit\n\n"
- " Example: 'sg_start -stop /dev/sdb' stops unit\n"
- " 'sg_start -loej /dev/scd0' stops unit and "
- "ejects media\n");
+ " Example: 'sg_start -stop /dev/sdb' stops unit\n"
+ " 'sg_start -eject /dev/scd0' stops unit and "
+ "ejects medium\n\n"
+ "Performs a START STOP UNIT SCSI command\n"
+ );
exit (1);
}
@@ -127,14 +72,11 @@ int main(int argc, char * argv[])
const char * cp;
int k, fd, num, res, plen, jmp_out;
unsigned int u;
- int immed = 1;
+ int immed = 0;
int loej = 0;
int power_conds = 0;
int verbose = 0;
- if (argc < 2)
- usage ();
-
for (k = 1; k < argc; ++k) {
cp = argv[k];
plen = strlen(cp);
@@ -144,11 +86,26 @@ int main(int argc, char * argv[])
for (--plen, ++cp, jmp_out = 0; plen > 0;
--plen, ++cp) {
switch (*cp) {
+ case 'e':
+ if (0 == strncmp(cp, "eject", 5)) {
+ loej = 1;
+ startstop = 0;
+ cp += 4;
+ plen -= 4;
+ } else
+ jmp_out = 1;
+ break;
case 'l':
if (0 == strncmp(cp, "loej", 4)) {
loej = 1;
cp += 3;
plen -= 3;
+ } else if (0 ==
+ strncmp(cp, "load", 4)) {
+ loej = 1;
+ startstop = 1;
+ cp += 3;
+ plen -= 3;
} else
jmp_out = 1;
break;
@@ -248,12 +205,8 @@ int main(int argc, char * argv[])
if ((startstop == -1) && loej)
startstop = 0;
- if ((startstop == -1) && (0 == power_conds)) {
- fprintf(stderr, "need either -start|-stop indication or"
- " non-zero power condition\n");
- usage ();
- return 1;
- }
+ if ((startstop == -1) && (0 == power_conds))
+ startstop = 1;
fd = open(file_name, O_RDWR | O_NONBLOCK);
if (fd < 0) {
@@ -264,10 +217,20 @@ int main(int argc, char * argv[])
res = 0;
if (power_conds > 0)
- res = do_start_stop(fd, 0, immed, 0, power_conds, verbose);
+ res = sg_ll_start_stop_unit(fd, immed, power_conds, 0, 0,
+ 1, verbose);
else if (startstop != -1)
- res = do_start_stop(fd, startstop, immed, loej, 0, verbose);
-
+ res = sg_ll_start_stop_unit(fd, immed, 0, loej, startstop,
+ 1, verbose);
+ if (res) {
+ if (verbose < 2) {
+ if (SG_LIB_CAT_INVALID_OP == res)
+ fprintf(stderr, "command not supported\n");
+ else if (SG_LIB_CAT_ILLEGAL_REQ == res)
+ fprintf(stderr, "command malformed\n");
+ }
+ fprintf(stderr, "START STOP UNIT command failed\n");
+ }
close (fd);
return res ? 1 : 0;
}
diff --git a/sg_sync.c b/sg_sync.c
index ce3a2109..feeca13d 100644
--- a/sg_sync.c
+++ b/sg_sync.c
@@ -49,7 +49,7 @@
* (e.g. disks)
*/
-static char * version_str = "1.02 20050210";
+static char * version_str = "1.03 20050808";
#define ME "sg_sync: "
@@ -89,7 +89,8 @@ static void usage()
"(if distinct\n"
" from medium)\n"
" --verbose|-v increase verbosity\n"
- " --version|-V print version string and exit\n"
+ " --version|-V print version string and exit\n\n"
+ "Performs a SYNCHRONIZE CACHE SCSI command\n"
);
}
diff --git a/sg_test_rwbuf.c b/sg_test_rwbuf.c
index d6ebd736..bc9ff5db 100644
--- a/sg_test_rwbuf.c
+++ b/sg_test_rwbuf.c
@@ -35,7 +35,7 @@
#include "sg_lib.h"
-static char * version_str = "1.02 20050511";
+static char * version_str = "1.03 20050806";
#define BPI (signed)(sizeof(int))
@@ -110,12 +110,13 @@ int find_out_about_buffer (int sg_fd)
/* now for the error processing */
switch (sg_err_category3(&io_hdr)) {
case SG_LIB_CAT_RECOVERED:
- sg_chk_n_print3("READ BUFFER descriptor, continuing", &io_hdr);
- /* fall through */
+ sg_chk_n_print3("READ BUFFER descriptor, continuing",
+ &io_hdr, 1);
+ /* fall through */
case SG_LIB_CAT_CLEAN:
break;
default: /* won't bother decoding other categories */
- sg_chk_n_print3("READ BUFFER descriptor error", &io_hdr);
+ sg_chk_n_print3("READ BUFFER descriptor error", &io_hdr, 1);
return 1;
}
@@ -244,12 +245,12 @@ int read_buffer (int sg_fd, unsigned size)
/* now for the error processing */
switch (sg_err_category3(&io_hdr)) {
case SG_LIB_CAT_RECOVERED:
- sg_chk_n_print3("READ BUFFER data, continuing", &io_hdr);
+ sg_chk_n_print3("READ BUFFER data, continuing", &io_hdr, 1);
/* fall through */
case SG_LIB_CAT_CLEAN:
break;
default: /* won't bother decoding other categories */
- sg_chk_n_print3("READ BUFFER data error", &io_hdr);
+ sg_chk_n_print3("READ BUFFER data error", &io_hdr, 1);
free(rbBuff);
return 1;
}
@@ -302,12 +303,12 @@ int write_buffer (int sg_fd, unsigned size)
/* now for the error processing */
switch (sg_err_category3(&io_hdr)) {
case SG_LIB_CAT_RECOVERED:
- sg_chk_n_print3("WRITE BUFFER data, continuing", &io_hdr);
+ sg_chk_n_print3("WRITE BUFFER data, continuing", &io_hdr, 1);
/* fall through */
case SG_LIB_CAT_CLEAN:
break;
default: /* won't bother decoding other categories */
- sg_chk_n_print3("WRITE BUFFER data error", &io_hdr);
+ sg_chk_n_print3("WRITE BUFFER data error", &io_hdr, 1);
free(wbBuff);
return 1;
}
diff --git a/sg_turs.c b/sg_turs.c
index def62536..8220743a 100644
--- a/sg_turs.c
+++ b/sg_turs.c
@@ -26,7 +26,7 @@
*/
-static char * version_str = "3.16 20050603";
+static char * version_str = "3.17 20050808";
#define EBUFF_SZ 256
@@ -39,8 +39,8 @@ static void usage()
" '-t' outputs total duration and commands per "
"second\n"
" '-v' increase verbosity\n"
- " '-V' print version string then exit\n"
- "Send Test Unit Ready SCSI command(s)\n");
+ " '-V' print version string then exit\n\n"
+ "Performs a TEST UNIT READY SCSI command (or many of them)\n");
}
int main(int argc, char * argv[])
diff --git a/sg_verify.c b/sg_verify.c
index 05622702..0ee2fc59 100644
--- a/sg_verify.c
+++ b/sg_verify.c
@@ -45,7 +45,7 @@
* This program issues the SCSI VERIFY command to the given SCSI block device.
*/
-static char * version_str = "1.03 20050404";
+static char * version_str = "1.04 20050808";
#define SENSE_BUFF_LEN 32 /* Arbitrary, could be larger */
#define DEF_TIMEOUT 60000 /* 60,000 millisecs == 60 seconds */
@@ -81,7 +81,8 @@ static void usage()
" --lba=<n>|-l <n> logical block address to start "
"verify (def 0)\n"
" --verbose|-v increase verbosity\n"
- " --version|-V print version string and exit\n"
+ " --version|-V print version string and exit\n\n"
+ "Performs a VERIFY SCSI command\n"
);
}
@@ -148,17 +149,17 @@ int sg_ll_verify10(int sg_fd, int dpo, int bytechk, unsigned long lba,
res = sg_err_category3(&io_hdr);
switch (res) {
case SG_LIB_CAT_RECOVERED:
- sg_chk_n_print3("VERIFY(10), continuing", &io_hdr);
+ sg_chk_n_print3("VERIFY(10), continuing", &io_hdr, verbose);
/* fall through */
case SG_LIB_CAT_CLEAN:
return 0;
case SG_LIB_CAT_INVALID_OP:
case SG_LIB_CAT_ILLEGAL_REQ:
if (verbose > 1)
- sg_chk_n_print3("VERIFY(10) command problem", &io_hdr);
+ sg_chk_n_print3("VERIFY(10) command problem", &io_hdr, 1);
return res;
default:
- sg_chk_n_print3("VERIFY(10) command problem", &io_hdr);
+ sg_chk_n_print3("VERIFY(10) command problem", &io_hdr, verbose);
return -1;
}
}
diff --git a/sg_wr_mode.c b/sg_wr_mode.c
index 2e915f51..44a71a3d 100644
--- a/sg_wr_mode.c
+++ b/sg_wr_mode.c
@@ -46,7 +46,7 @@
* mode page on the given device.
*/
-static char * version_str = "1.04 20050405";
+static char * version_str = "1.04 20050722";
#define ME "sg_wr_mode: "
@@ -280,7 +280,7 @@ static int build_mask(const char * inp, unsigned char * mask_arr,
int main(int argc, char * argv[])
{
- int sg_fd, res, c, num, read_in_len, alloc_len, off;
+ int sg_fd, res, c, num, alloc_len, off;
int k, md_len, hdr_len, bd_len, mask_in_len;
unsigned u, uu;
int dbd = 0;
@@ -292,6 +292,7 @@ int main(int argc, char * argv[])
int sub_pg_code = 0;
int save = 0;
int verbose = 0;
+ int read_in_len = 0;
char device_name[256];
unsigned char read_in[MX_ALLOC_LEN];
unsigned char mask_in[MX_ALLOC_LEN];
diff --git a/sg_write_long.c b/sg_write_long.c
index ed8531b8..e1496ee9 100644
--- a/sg_write_long.c
+++ b/sg_write_long.c
@@ -27,7 +27,7 @@
This code was contributed by Saeed Bishara
*/
-static char * version_str = "1.05 20050309";
+static char * version_str = "1.06 20050808";
#define WRITE_LONG_OPCODE 0x3F
#define WRITE_LONG_CMD_LEN 10
@@ -69,7 +69,8 @@ static void usage()
"count=1\n"
" To write to a defected sector use:\n"
" sg_dd of=<scsi_device> seek=<lba> if=/dev/zero bs=512 "
- "count=1\n"
+ "count=1\n\n"
+ "Performs a WRITE LONG SCSI command\n"
);
}
@@ -283,7 +284,7 @@ int main(int argc, char * argv[])
/* now for the error processing */
switch (sg_err_category3(&io_hdr)) {
case SG_LIB_CAT_RECOVERED:
- sg_chk_n_print3("WRITE LONG, continuing", &io_hdr);
+ sg_chk_n_print3("WRITE LONG, continuing", &io_hdr, verbose);
/* fall through */
case SG_LIB_CAT_CLEAN:
break;
@@ -292,7 +293,7 @@ int main(int argc, char * argv[])
(ssh.sense_key == ILLEGAL_REQUEST) &&
((offset = info_offset(io_hdr.sbp, io_hdr.sb_len_wr)))) {
if (verbose)
- sg_chk_n_print3("WRITE LONG command problem", &io_hdr);
+ sg_chk_n_print3("WRITE LONG command problem", &io_hdr, 1);
fprintf(stderr, "<<< nothing written to device >>>\n");
fprintf(stderr, "<<< device indicates 'xfer_len' should be %d "
">>>\n", xfer_len - offset);
@@ -301,7 +302,7 @@ int main(int argc, char * argv[])
"expected but not found]\n");
goto err_out;
}
- sg_chk_n_print3("WRITE LONG problem error", &io_hdr);
+ sg_chk_n_print3("WRITE LONG problem error", &io_hdr, verbose);
goto err_out;
}
diff --git a/sginfo.c b/sginfo.c
index be2272fc..9a89a784 100644
--- a/sginfo.c
+++ b/sginfo.c
@@ -25,6 +25,7 @@
* -n access notch parameters page.
* -N Negate (stop) storing to saved page (active with -R)
* -P access Power Condition Page.
+ * -r list known raw scsi devices on the system
* -s display serial number (from INQUIRY VPD page)
* -t <n[,spn]> access page number <n> [and subpage <spn>], try to decode
* -u <n[,spn]> access page number <n> [and subpage <spn>] in hex.
@@ -109,7 +110,7 @@
#define _XOPEN_SOURCE 500
#define _GNU_SOURCE
-static const char * sginfo_version_str = "sginfo version 2.14 [20050412]";
+static const char * sginfo_version_str = "sginfo version 2.17 [20050806]";
#include <stdio.h>
#include <string.h>
@@ -119,9 +120,11 @@ static const char * sginfo_version_str = "sginfo version 2.14 [20050412]";
#include <fcntl.h>
#include <errno.h>
#include <stdlib.h>
+#include <ctype.h>
#include <sys/ioctl.h>
#include <sys/types.h>
#include <sys/stat.h>
+#include <dirent.h>
#include "sg_include.h"
#include "sg_lib.h"
@@ -134,6 +137,8 @@ static char *device_name;
#define MAX_RESP10_SIZE (4*1024)
#define MAX_BUFFER_SIZE MAX_RESP10_SIZE
+#define INQUIRY_RESP_INITIAL_LEN 36
+
#define MAX_HEADS 127
#define HEAD_SORT_TOKEN 0x55
@@ -414,7 +419,7 @@ static int do_scsi_io(struct scsi_cmnd_io * sio)
res = sg_err_category3(&io_hdr);
switch (res) {
case SG_LIB_CAT_RECOVERED:
- sg_chk_n_print3("do_scsi_cmd, continuing", &io_hdr);
+ sg_chk_n_print3("do_scsi_cmd, continuing", &io_hdr, 1);
/* fall through */
case SG_LIB_CAT_CLEAN:
return 0;
@@ -423,7 +428,7 @@ static int do_scsi_io(struct scsi_cmnd_io * sio)
char ebuff[EBUFF_SZ];
snprintf(ebuff, EBUFF_SZ, "do_scsi_io: opcode=0x%x", sio->cmnd[0]);
- sg_chk_n_print3(ebuff, &io_hdr);
+ sg_chk_n_print3(ebuff, &io_hdr, 1);
}
if (sg_normalize_sense(&io_hdr, &ssh)) {
if (ILLEGAL_REQUEST == ssh.sense_key) {
@@ -2897,24 +2902,23 @@ static int do_inquiry(int * peri_type, int * resp_byte6,
int inquiry_verbosity)
{
int status;
- const int inq_resp_len = 36;
unsigned char cmd[6];
unsigned char *pagestart;
struct scsi_cmnd_io sci;
- memset(cbuffer, 0, inq_resp_len);
+ memset(cbuffer, 0, INQUIRY_RESP_INITIAL_LEN);
cmd[0] = 0x12; /* INQUIRY */
cmd[1] = 0x00; /* evpd=0 */
cmd[2] = 0x00; /* page code = 0 */
cmd[3] = 0x00; /* (reserved) */
- cmd[4] = inq_resp_len; /* allocation length */
+ cmd[4] = INQUIRY_RESP_INITIAL_LEN; /* allocation length */
cmd[5] = 0x00; /* control */
sci.cmnd = cmd;
sci.cmnd_len = sizeof(cmd);
sci.dxfer_dir = DXFER_FROM_DEVICE;
- sci.dxfer_len = inq_resp_len;
+ sci.dxfer_len = INQUIRY_RESP_INITIAL_LEN;
sci.dxferp = cbuffer;
status = do_scsi_io(&sci);
if (status) {
@@ -2923,7 +2927,7 @@ static int do_inquiry(int * peri_type, int * resp_byte6,
}
if (trace_cmd > 1) {
printf(" inquiry response:\n");
- dump(cbuffer, inq_resp_len);
+ dump(cbuffer, INQUIRY_RESP_INITIAL_LEN);
}
pagestart = cbuffer;
if (peri_type)
@@ -2932,7 +2936,7 @@ static int do_inquiry(int * peri_type, int * resp_byte6,
*resp_byte6 = pagestart[6];
if (0 == inquiry_verbosity)
return 0;
- if ((pagestart[4] + 5) < 36) {
+ if ((pagestart[4] + 5) < INQUIRY_RESP_INITIAL_LEN) {
printf("INQUIRY response too short: expected 36 bytes, got %d\n",
pagestart[4] + 5);
return -EINVAL;
@@ -3106,65 +3110,77 @@ static void make_dev_name(char * fname, int k, int do_numeric)
}
}
-#define MAX_SG_DEVS 256
-
-char *ul_devices[] =
-{"/dev/sda", "/dev/sdb", "/dev/sdc", "/dev/sdd", "/dev/sde", "/dev/sdf",
- "/dev/sdg", "/dev/sdh", "/dev/sdi", "/dev/sdj", "/dev/sdk", "/dev/sdl",
- "/dev/sdm", "/dev/sdn", "/dev/sdo", "/dev/sdp", "/dev/sdq", "/dev/sdr",
- "/dev/sds", "/dev/sdt", "/dev/sdu", "/dev/sdv", "/dev/sdw", "/dev/sdx",
- "/dev/sdy", "/dev/sdz",
- "/dev/sdaa", "/dev/sdab", "/dev/sdac", "/dev/sdad", "/dev/sdae",
- "/dev/sdaf", "/dev/sdag", "/dev/sdah", "/dev/sdai", "/dev/sdaj",
- "/dev/sdak", "/dev/sdal", "/dev/sdam", "/dev/sdan", "/dev/sdao",
- "/dev/sdap", "/dev/sdaq", "/dev/sdar", "/dev/sdas", "/dev/sdat",
- "/dev/sdau", "/dev/sdav", "/dev/sdaw", "/dev/sdax", "/dev/sday",
- "/dev/sdaz", "/dev/sdba", "/dev/sdbb", "/dev/sdbc", "/dev/sdbd",
- "/dev/sdbe", "/dev/sdbf", "/dev/sdbg", "/dev/sdbh", "/dev/sdbi",
- "/dev/sdbj", "/dev/sdbk", "/dev/sdbl", "/dev/sdbm", "/dev/sdbn",
- "/dev/sdbo", "/dev/sdbp", "/dev/sdbq", "/dev/sdbr", "/dev/sdbs",
- "/dev/sdbt", "/dev/sdbu", "/dev/sdbv", "/dev/sdbw", "/dev/sdbx",
- "/dev/sdby", "/dev/sdbz",
- "/dev/scd0", "/dev/scd1", "/dev/scd2", "/dev/scd3", "/dev/scd4", "/dev/scd5",
- "/dev/scd6", "/dev/scd7", "/dev/scd8", "/dev/scd9", "/dev/scd10", "/dev/scd11",
- "/dev/sr0", "/dev/sr1", "/dev/sr2", "/dev/sr3", "/dev/sr4", "/dev/sr5",
- "/dev/sr6", "/dev/sr7", "/dev/sr8", "/dev/sr9", "/dev/sr10", "/dev/sr11",
- "/dev/nst0", "/dev/nst1", "/dev/nst2", "/dev/nst3", "/dev/nst4", "/dev/nst5",
- "/dev/nosst0", "/dev/nosst1", "/dev/nosst2", "/dev/nosst3", "/dev/nosst4"
-};
-
-static const int ul_devices_num = (sizeof(ul_devices) / sizeof(char *));
+#define MAX_SG_DEVS 1024
-static Sg_map sg_map_arr[(sizeof(ul_devices) / sizeof(char *)) + 1];
+static Sg_map sg_map_arr[MAX_SG_DEVS];
#define MAX_HOLES 4
/* Print out a list of the known devices on the system */
-static void show_devices()
+static void show_devices(int raw)
{
int k, j, fd, err, bus;
My_scsi_idlun m_idlun;
char name[MDEV_NAME_SZ];
+ char dev_name[MDEV_NAME_SZ];
char ebuff[EBUFF_SZ];
int do_numeric = 1;
int max_holes = MAX_HOLES;
+ DIR *dir_ptr;
+ struct dirent *entry;
+ char *tmpptr;
+
+ dir_ptr=opendir("/dev");
+ if ( dir_ptr == NULL ) {
+ perror("/dev");
+ exit(1);
+ }
+
+ j=0;
+ while ( (entry=readdir(dir_ptr)) != NULL ) {
+ switch(entry->d_type) {
+ case DT_LNK:
+ case DT_CHR:
+ case DT_BLK:
+ break;
+ default:
+ continue;
+ }
- for (k = 0, j = 0; k < ul_devices_num; k++) {
- fd = open(ul_devices[k], O_RDONLY | O_NONBLOCK);
+ switch(entry->d_name[0]) {
+ case 's':
+ case 'n':
+ break;
+ default:
+ continue;
+ }
+
+ if ( strncmp("sg",entry->d_name,2) == 0 ) {
+ continue;
+ }
+ if ( strncmp("sd",entry->d_name,2) == 0 && isdigit(entry->d_name[strlen(entry->d_name)-1]) ) {
+ continue;
+ }
+
+ snprintf(dev_name, sizeof(dev_name),"/dev/%s",entry->d_name);
+
+ fd = open(dev_name, O_RDONLY | O_NONBLOCK);
if (fd < 0)
continue;
err = ioctl(fd, SCSI_IOCTL_GET_BUS_NUMBER, &(sg_map_arr[j].bus));
if (err < 0) {
+#if 0
snprintf(ebuff, EBUFF_SZ,
- "SCSI(1) ioctl on %s failed", ul_devices[k]);
+ "SCSI(1) ioctl on %s failed", dev_name);
perror(ebuff);
+#endif
close(fd);
continue;
}
err = ioctl(fd, SCSI_IOCTL_GET_IDLUN, &m_idlun);
if (err < 0) {
snprintf(ebuff, EBUFF_SZ,
- "SCSI(2) ioctl on %s failed", ul_devices[k]);
+ "SCSI(2) ioctl on %s failed", dev_name);
perror(ebuff);
close(fd);
continue;
@@ -3172,20 +3188,32 @@ static void show_devices()
sg_map_arr[j].channel = (m_idlun.mux4 >> 16) & 0xff;
sg_map_arr[j].lun = (m_idlun.mux4 >> 8) & 0xff;
sg_map_arr[j].target_id = m_idlun.mux4 & 0xff;
- sg_map_arr[j].dev_name = ul_devices[k];
+ tmpptr=(char *)malloc(strlen(dev_name)+1);
+ strncpy(tmpptr,dev_name,strlen(dev_name)+1);
+ sg_map_arr[j].dev_name = tmpptr;
#if 0
printf("[scsi%d ch=%d id=%d lun=%d %s] ", sg_map_arr[j].bus,
sg_map_arr[j].channel, sg_map_arr[j].target_id, sg_map_arr[j].lun,
sg_map_arr[j].dev_name);
#endif
++j;
- printf("%s ", ul_devices[k]);
+ printf("%s ", dev_name);
close(fd);
};
+ closedir(dir_ptr);
+
printf("\n"); /* <<<<<<<<<<<<<<<<<<<<< */
for (k = 0; k < MAX_SG_DEVS; k++) {
- make_dev_name(name, k, do_numeric);
- fd = open(name, O_RDWR | O_NONBLOCK);
+ if ( raw ) {
+ sprintf(name,"/dev/raw/raw%d",k);
+ fd = open(name, O_RDWR | O_NONBLOCK);
+ if (fd < 0) {
+ continue;
+ }
+ }
+ else {
+ make_dev_name(name, k, do_numeric);
+ fd = open(name, O_RDWR | O_NONBLOCK);
if (fd < 0) {
if ((ENOENT == errno) && (0 == k)) {
do_numeric = 0;
@@ -3208,18 +3236,23 @@ static void show_devices()
}
}
}
+ }
max_holes = MAX_HOLES;
err = ioctl(fd, SCSI_IOCTL_GET_BUS_NUMBER, &bus);
if (err < 0) {
- snprintf(ebuff, EBUFF_SZ, "SCSI(3) ioctl on %s failed", name);
- perror(ebuff);
+ if ( ! raw ) {
+ snprintf(ebuff, EBUFF_SZ, "SCSI(3) ioctl on %s failed", name);
+ perror(ebuff);
+ }
close(fd);
continue;
}
err = ioctl(fd, SCSI_IOCTL_GET_IDLUN, &m_idlun);
if (err < 0) {
- snprintf(ebuff, EBUFF_SZ, "SCSI(3) ioctl on %s failed", name);
- perror(ebuff);
+ if ( ! raw ) {
+ snprintf(ebuff, EBUFF_SZ, "SCSI(3) ioctl on %s failed", name);
+ perror(ebuff);
+ }
close(fd);
continue;
}
@@ -3381,6 +3414,7 @@ static void usage(char *errtext)
"\t-n Access Notch and Partition Page.\n"
"\t-N Negate (stop) storing to saved page (active with -R).\n"
"\t-P Access Power Condition Page.\n"
+ "\t-r List known raw scsi devices on the system\n"
"\t-s Display serial number (from INQUIRY VPD page).\n"
"\t-t<pn[,sp]> Access mode page <pn> [subpage <sp>] and decode.\n"
"\t-T Trace commands (for debugging, double for more)\n"
@@ -3405,7 +3439,7 @@ static void usage(char *errtext)
int main(int argc, char *argv[])
{
- int k, j;
+ int k, j, n;
unsigned int unum, unum2;
int decode_in_hex = 0;
char c;
@@ -3413,13 +3447,13 @@ int main(int argc, char *argv[])
long tmp;
struct mpage_info mp_i;
int inquiry_verbosity = 0;
- int show_devs = 0;
+ int show_devs = 0, show_raw = 0;
int found = 0;
if (argc < 2)
usage(NULL);
memset(&mp_i, 0, sizeof(mp_i));
- while ((k = getopt(argc, argv, "6aAcCdDeEfgGiIlmMnNPRsSTvVXzF:t:u:")) !=
+ while ((k = getopt(argc, argv, "6aAcCdDeEfgGiIlmMnNPrRsSTvVXzF:t:u:")) !=
EOF) {
c = (char)k;
switch (c) {
@@ -3510,6 +3544,9 @@ int main(int argc, char *argv[])
case 'P':
mp_i.page = 0x1a;
break;
+ case 'r':
+ show_raw = 1;
+ break;
case 'R':
replace = 1;
break;
@@ -3608,13 +3645,17 @@ int main(int argc, char *argv[])
continue;
}
/* Using a tmp here is silly but the most clean approach */
- sscanf(argv[optind + j], "%ld", &tmp);
- replacement_values[j] = tmp;
+ n = sscanf(argv[optind + j], "%ld", &tmp);
+ replacement_values[j] = ((1 == n) ? tmp : 0);
}
n_replacement_values = argc - optind - 1;
}
if (show_devs) {
- show_devices();
+ show_devices(0);
+ exit(0);
+ }
+ if (show_raw) {
+ show_devices(1);
exit(0);
}
if (optind >= argc)
diff --git a/sgm_dd.c b/sgm_dd.c
index 8ff369da..f5f7ec5a 100644
--- a/sgm_dd.c
+++ b/sgm_dd.c
@@ -54,7 +54,7 @@
This version is designed for the linux kernel 2.4 and 2.6 series.
*/
-static char * version_str = "1.20 20050511";
+static char * version_str = "1.21 20050806";
#define DEF_BLOCK_SIZE 512
#define DEF_BLOCKS_PER_TRANSFER 128
@@ -197,7 +197,7 @@ int scsi_read_capacity(int sg_fd, long long * num_sect, int * sect_sz)
int k, res;
unsigned char rcBuff[RCAP16_REPLY_LEN];
- res = sg_ll_readcap_10(sg_fd, 0, 0, rcBuff, READ_CAP_REPLY_LEN, 0);
+ res = sg_ll_readcap_10(sg_fd, 0, 0, rcBuff, READ_CAP_REPLY_LEN, 0, 0);
if (0 != res)
return res;
@@ -205,7 +205,7 @@ int scsi_read_capacity(int sg_fd, long long * num_sect, int * sect_sz)
(0xff == rcBuff[3])) {
long long ls;
- res = sg_ll_readcap_16(sg_fd, 0, 0, rcBuff, RCAP16_REPLY_LEN, 0);
+ res = sg_ll_readcap_16(sg_fd, 0, 0, rcBuff, RCAP16_REPLY_LEN, 0, 0);
if (0 != res)
return res;
for (k = 0, ls = 0; k < 8; ++k) {
@@ -409,12 +409,12 @@ int sg_read(int sg_fd, unsigned char * buff, int blocks, long long from_block,
case SG_LIB_CAT_CLEAN:
break;
case SG_LIB_CAT_RECOVERED:
- sg_chk_n_print3("Reading, continuing", &io_hdr);
+ sg_chk_n_print3("Reading, continuing", &io_hdr, 0);
break;
case SG_LIB_CAT_MEDIA_CHANGED:
return 2;
default:
- sg_chk_n_print3("reading", &io_hdr);
+ sg_chk_n_print3("reading", &io_hdr, 0);
return -1;
}
sum_of_resids += io_hdr.resid;
@@ -484,12 +484,12 @@ int sg_write(int sg_fd, unsigned char * buff, int blocks, long long to_block,
case SG_LIB_CAT_CLEAN:
break;
case SG_LIB_CAT_RECOVERED:
- sg_chk_n_print3("Writing, continuing", &io_hdr);
+ sg_chk_n_print3("Writing, continuing", &io_hdr, 0);
break;
case SG_LIB_CAT_MEDIA_CHANGED:
return 2;
default:
- sg_chk_n_print3("writing", &io_hdr);
+ sg_chk_n_print3("writing", &io_hdr, 0);
return -1;
}
if (diop && *diop &&
diff --git a/sgp_dd.c b/sgp_dd.c
index 5593a2a6..8c00e3d9 100644
--- a/sgp_dd.c
+++ b/sgp_dd.c
@@ -49,7 +49,7 @@
*/
-static char * version_str = "5.23 20050309";
+static char * version_str = "5.24 20050806";
#define DEF_BLOCK_SIZE 512
#define DEF_BLOCKS_PER_TRANSFER 128
@@ -266,7 +266,7 @@ int scsi_read_capacity(int sg_fd, long long * num_sect, int * sect_sz)
int k, res;
unsigned char rcBuff[RCAP16_REPLY_LEN];
- res = sg_ll_readcap_10(sg_fd, 0, 0, rcBuff, READ_CAP_REPLY_LEN, 0);
+ res = sg_ll_readcap_10(sg_fd, 0, 0, rcBuff, READ_CAP_REPLY_LEN, 0, 0);
if (0 != res)
return res;
@@ -274,7 +274,7 @@ int scsi_read_capacity(int sg_fd, long long * num_sect, int * sect_sz)
(0xff == rcBuff[3])) {
long long ls;
- res = sg_ll_readcap_16(sg_fd, 0, 0, rcBuff, RCAP16_REPLY_LEN, 0);
+ res = sg_ll_readcap_16(sg_fd, 0, 0, rcBuff, RCAP16_REPLY_LEN, 0, 0);
if (0 != res)
return res;
for (k = 0, ls = 0; k < 8; ++k) {
@@ -858,7 +858,7 @@ int sg_finish_io(int wr, Rq_elem * rep, pthread_mutex_t * a_mutp)
break;
case SG_LIB_CAT_RECOVERED:
sg_chk_n_print3((rep->wr ? "writing continuing":
- "reading continuing"), hp);
+ "reading continuing"), hp, 0);
break;
case SG_LIB_CAT_MEDIA_CHANGED:
return 1;
@@ -870,7 +870,7 @@ int sg_finish_io(int wr, Rq_elem * rep, pthread_mutex_t * a_mutp)
"%s blk=%d", rep->wr ? "writing": "reading", rep->blk);
status = pthread_mutex_lock(a_mutp);
if (0 != status) err_exit(status, "lock aux_mutex");
- sg_chk_n_print3(ebuff, hp);
+ sg_chk_n_print3(ebuff, hp, 0);
status = pthread_mutex_unlock(a_mutp);
if (0 != status) err_exit(status, "unlock aux_mutex");
return -1;