aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDouglas Gilbert <dgilbert@interlog.com>2007-06-27 03:53:07 +0000
committerDouglas Gilbert <dgilbert@interlog.com>2007-06-27 03:53:07 +0000
commit2e37f3d2a90d421affd06e01dd05cd7c8194ca84 (patch)
treed55084e9efd7a1e3426b0389f58338f09faef41b
parent7502647d46389b2e0e659f658b51f56abd1f9511 (diff)
downloadsg3_utils-2e37f3d2a90d421affd06e01dd05cd7c8194ca84.tar.gz
Load sg3_utils-1.24 into trunk/.
git-svn-id: https://svn.bingwo.ca/repos/sg3_utils/trunk@76 6180dd3e-e324-4e3e-922d-17de1ae2f315
-rw-r--r--CHANGELOG38
-rw-r--r--COVERAGE3
-rw-r--r--CREDITS5
-rw-r--r--INSTALL14
-rw-r--r--Makefile7
-rw-r--r--Makefile.asroot7
-rw-r--r--Makefile.freebsd9
-rw-r--r--Makefile.mingw9
-rw-r--r--Makefile.osf18
-rw-r--r--Makefile.solaris205
-rw-r--r--Makefile.win3211
-rw-r--r--README58
-rw-r--r--README.freebsd5
-rw-r--r--README.solaris78
-rw-r--r--README.tru643
-rw-r--r--README.win323
-rwxr-xr-xarchive/o_scsi_logging_level295
-rw-r--r--archive/sg3_utils_123o.spec193
-rw-r--r--debian/changelog6
-rw-r--r--debian/control1
-rw-r--r--debian/docs5
-rw-r--r--doc/README.doc23
-rw-r--r--doc/sg3_utils.html1634
-rw-r--r--doc/sg_dd.html1175
-rw-r--r--doc/sg_io.html1649
-rw-r--r--doc/tools.html318
-rw-r--r--examples/Makefile5
-rw-r--r--examples/sdiag_sas_p0_cjtpat.txt2
-rw-r--r--examples/sdiag_sas_p1_cjtpat.txt2
-rw-r--r--examples/sdiag_sas_p1_stop.txt2
-rw-r--r--examples/sg_io_linux.h (renamed from examples/sg_io_linux.hh)0
-rw-r--r--examples/sg_lib.h (renamed from examples/sg_lib.hh)0
-rw-r--r--examples/sg_linux_inc.h (renamed from examples/sg_linux_inc.hh)0
-rwxr-xr-xexamples/sg_persist_tst.sh26
-rw-r--r--examples/sg_pt.h (renamed from examples/sg_pt.hh)0
-rw-r--r--examples/sg_sat_phy_event.c350
-rw-r--r--examples/sg_sat_set_features.885
-rw-r--r--examples/sg_sat_set_features.c149
-rw-r--r--examples/sg_simple1.c8
-rw-r--r--examples/sg_simple16.c2
-rw-r--r--examples/sg_simple2.c8
-rw-r--r--examples/sg_simple5.c8
-rw-r--r--examples/transport_ids.txt10
-rwxr-xr-xmake_no_lib_solaris.sh3
-rw-r--r--no_lib/Makefile.freebsd11
-rw-r--r--no_lib/Makefile.linux8
-rw-r--r--no_lib/Makefile.linux_static7
-rw-r--r--no_lib/Makefile.osf19
-rw-r--r--no_lib/Makefile.solaris161
-rw-r--r--no_lib/Makefile.win329
-rw-r--r--no_lib/sg3_utils.spec8
-rwxr-xr-xscripts/sas_disk_blink2
-rwxr-xr-xscripts/scsi_logging_level85
-rwxr-xr-xscripts/scsi_mandat2
-rwxr-xr-xscripts/scsi_satl2
-rw-r--r--sg3_utils.812
-rw-r--r--sg3_utils.spec6
-rw-r--r--sg_cmds_basic.c46
-rw-r--r--sg_cmds_basic.h9
-rw-r--r--sg_cmds_extra.c56
-rw-r--r--sg_cmds_extra.h11
-rw-r--r--sg_dd.813
-rw-r--r--sg_dd.c35
-rw-r--r--sg_format.8109
-rw-r--r--sg_format.c155
-rw-r--r--sg_get_config.821
-rw-r--r--sg_get_config.c4
-rw-r--r--sg_ident.c4
-rw-r--r--sg_inq.816
-rw-r--r--sg_inq.c43
-rw-r--r--sg_io_linux.h4
-rw-r--r--sg_lib.c5
-rw-r--r--sg_lib.h13
-rw-r--r--sg_logs.854
-rw-r--r--sg_logs.c820
-rw-r--r--sg_luns.822
-rw-r--r--sg_luns.c49
-rw-r--r--sg_map26.c4
-rw-r--r--sg_modes.828
-rw-r--r--sg_modes.c21
-rw-r--r--sg_opcodes.c14
-rw-r--r--sg_persist.830
-rw-r--r--sg_persist.c25
-rw-r--r--sg_prevent.c4
-rw-r--r--sg_pt.h68
-rw-r--r--sg_pt_freebsd.c99
-rw-r--r--sg_pt_linux.c103
-rw-r--r--sg_pt_osf1.c96
-rw-r--r--sg_pt_solaris.c325
-rw-r--r--sg_pt_win32.c95
-rw-r--r--sg_raw.899
-rw-r--r--sg_raw.c448
-rw-r--r--sg_rbuf.c4
-rw-r--r--sg_read_buffer.c4
-rw-r--r--sg_read_long.c4
-rw-r--r--sg_readcap.c4
-rw-r--r--sg_reassign.c4
-rw-r--r--sg_requests.c4
-rw-r--r--sg_rmsn.c4
-rw-r--r--sg_rtpg.c21
-rw-r--r--sg_sat_identify.810
-rw-r--r--sg_sat_identify.c27
-rw-r--r--sg_scan.c4
-rw-r--r--sg_senddiag.829
-rw-r--r--sg_senddiag.c4
-rw-r--r--sg_ses.84
-rw-r--r--sg_ses.c408
-rw-r--r--sg_start.c4
-rw-r--r--sg_sync.c4
-rw-r--r--sg_turs.c4
-rw-r--r--sg_verify.c4
-rw-r--r--sg_vpd.86
-rw-r--r--sg_vpd.c96
-rw-r--r--sg_wr_mode.c4
-rw-r--r--sg_write_buffer.c4
-rw-r--r--sg_write_long.c4
-rw-r--r--sginfo.816
-rw-r--r--sgm_dd.824
-rw-r--r--sgm_dd.c75
-rw-r--r--sgp_dd.811
-rw-r--r--sgp_dd.c39
-rw-r--r--utils/Makefile.solaris54
-rw-r--r--utils/sg_lib.h1
-rw-r--r--utils/sg_lib.hh307
124 files changed, 4464 insertions, 6420 deletions
diff --git a/CHANGELOG b/CHANGELOG
index 7db75b0f..05800b85 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -2,6 +2,44 @@ Each utility has its own version number, date of last change and
some description at the top of its ".c" file. All utilities in the main
directory have their own "man" pages. There is also a sg3_utils man page.
+Changelog for sg3_utils-1.24 [20070507]
+ - sg_raw: new utility to send arbirary SCSI commands
+ - sg_luns: increase number of luns that can be fetched
+ - fix length of raw and hex output
+ - add '--quiet' option to output only ASCII hex
+ representation of each lun
+ - sg_rtpg: update for changes in spc4r09
+ - sg_persist: update documentation, spc-4 references
+ - fix exit status values
+ - sg_inq: update version descriptors per spc4r09
+ - fix '--id' and '--extended'
+ - extend block limits VPD page (sbc3r09)
+ - sg_vpd: extend block limits VPD page (sbc3r09)
+ - append relative target port identifier to SAS target
+ port address with '-iq' option
+ - sg_logs: add decoding for stats+performance log pages
+ - fix showing of page names for pdt > 0
+ - implement '-HH' for single and all pages, fix '-r'
+ - when '--maxlen=' given, only do single fetch
+ - add Tape Alert (ssc), Media and Element statistics (smc) pages
+ - add '--brief' option
+ - sg_ses: sync with ses2r16
+ - fix bay number for SAS
+ - sg_format: add '--dcrt' and '--security' options
+ - sgm_dd: add 'smmap' oflag for shared_mmap_io testing
+ - add 'dio' oflag
+ - sg_dd, sgp_dd: add 'dio' iflag and oflag
+ - sg_modes: change SAS mode page names per sas2r09
+ - check validity of block descriptors length
+ - sg_pt: change opaque context object from 'void *'
+ to 'struct sg_pt_base *'
+ - sg_opcodes: anticipate extra tmfs from 07-159r0
+ - sg_sat_set_features: add more usage information
+ - add man page
+ - sg_sat_phy_event: add to examples directory
+ - sg_lib: sync asc/ascq codes with spc4r10
+ - Solaris port: using uscsi interface
+
Changelog for sg3_utils-1.23 [20070131]
- sg_read_buffer: new utility
- sg_write_buffer: new utility
diff --git a/COVERAGE b/COVERAGE
index d126cada..afdc7010 100644
--- a/COVERAGE
+++ b/COVERAGE
@@ -72,6 +72,7 @@ IDENTIFY DEVICE sg_inq, sg_scan, sg_sat_identify,
examples/sg__sat_identify
IDENTIFY PACKET DEVICE sg_inq, sg_sat_identify,
examples/sg__sat_identify
+READ LOG EXT examples/sg_sat_phy_event
SET FEATURES examples/sg_sat_set_features
SMART READ DATA examples/sg_sat_smart_rd_data
@@ -83,4 +84,4 @@ SMART READ DATA examples/sg_sat_smart_rd_data
Doug Gilbert
-2nd November 2006
+21st April 2007
diff --git a/CREDITS b/CREDITS
index 8acbc04b..592badb7 100644
--- a/CREDITS
+++ b/CREDITS
@@ -35,6 +35,9 @@ Hayashi Naoyuki <titan at culzean dot org>
Heiko Eissfeldt <heiko at colossus dot escape dot de> sg based example
programs for the original sg driver
+Ingo van Lil <inguin at gmx dot de>
+ contributed sg_raw [20070331]
+
James Bottomley <jejb at parisc-linux dot org> co-author of blk512-linux
that has become sg_format [20050201]
@@ -73,4 +76,4 @@ Trent Piepho <xyzzy at speakeasy dot org> print out some "sense key specific"
Doug Gilbert
-31st October 2006
+31st March 2007
diff --git a/INSTALL b/INSTALL
index 71fb126d..7cf0a33a 100644
--- a/INSTALL
+++ b/INSTALL
@@ -86,6 +86,18 @@ Utilities that are linux specific (e.g. sg_map) are not built for
FreeBSD.
+Solaris
+=======
+In Solaris, the utilities can be built with "make -f Makefile.solaris".
+This will build a shared object (i.e. libsgutils.so and friends) that
+the utilities depend on. To install use "make -f Makefile.solaris install".
+These makes depend on gcc and libtool. To build without reliance on a shared
+library (and thus libtool) use "make -f no_lib/Makefile.solaris" (or
+execute the "make_no_lib_solaris.sh" script which does the same thing).
+Utilities that are linux specific (e.g. sg_map) are not built for
+Solaris.
+
+
Tru64 (OSF)
===========
In Tru64, the utilities can be built with "make -f Makefile.osf1".
@@ -128,5 +140,5 @@ will be placed in that directory. They can be executed in a MSYS or "cmd"
shell.
-21st January 2007
+3rd May 2007
Doug Gilbert
diff --git a/Makefile b/Makefile
index 0254cfff..4ada4238 100644
--- a/Makefile
+++ b/Makefile
@@ -16,7 +16,7 @@ EXECS = sg_dd sgp_dd sgm_dd sg_read sg_map sg_scan sg_rbuf \
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_ident sg_map26 sg_rdac sg_vpd sg_sat_identify \
- sg_read_buffer sg_write_buffer
+ sg_read_buffer sg_write_buffer sg_raw
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 \
@@ -26,7 +26,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_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_ident.8 \
sg_map26.8 sg_rdac.8 sg_vpd.8 sg3_utils.8 sg_sat_identify.8 \
- sg_read_buffer.8 sg_write_buffer.8
+ sg_read_buffer.8 sg_write_buffer.8 sg_raw.8
MAN_PREF = man8
HEADERS = sg_lib.h sg_cmds.h sg_cmds_basic.h sg_cmds_extra.h sg_pt.h \
@@ -211,6 +211,9 @@ sg_read_buffer: sg_read_buffer.o libsgutils.la
sg_write_buffer: sg_write_buffer.o libsgutils.la
libtool --mode=link $(LD) -o $@ $(LDFLAGS) $^
+sg_raw: sg_raw.o libsgutils.la
+ libtool --mode=link $(LD) -o $@ $(LDFLAGS) $^
+
install: $(EXECS)
install -d $(INSTDIR)
diff --git a/Makefile.asroot b/Makefile.asroot
index 1f6a5f02..dc3d1990 100644
--- a/Makefile.asroot
+++ b/Makefile.asroot
@@ -16,7 +16,7 @@ EXECS = sg_dd sgp_dd sgm_dd sg_read sg_map sg_scan sg_rbuf \
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_ident sg_map26 sg_rdac sg_vpd sg_sat_identify \
- sg_read_buffer sg_write_buffer
+ sg_read_buffer sg_write_buffer sg_raw
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 \
@@ -26,7 +26,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_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_ident.8 \
sg_map26.8 sg_rdac.8 sg_vpd.8 sg3_utils.8 sg_sat_identify.8 \
- sg_read_buffer.8 sg_write_buffer.8
+ sg_read_buffer.8 sg_write_buffer.8 sg_raw.8
MAN_PREF = man8
HEADERS = sg_lib.h sg_cmds.h sg_cmds_basic.h sg_cmds_extra.h sg_pt.h \
@@ -211,6 +211,9 @@ sg_read_buffer: sg_read_buffer.o libsgutils.la
sg_write_buffer: sg_write_buffer.o libsgutils.la
libtool --mode=link $(LD) -o $@ $(LDFLAGS) $^
+sg_raw: sg_raw.o libsgutils.la
+ libtool --mode=link $(LD) -o $@ $(LDFLAGS) $^
+
install: $(EXECS)
install -d $(INSTDIR)
diff --git a/Makefile.freebsd b/Makefile.freebsd
index 7fa14dfe..53cddce4 100644
--- a/Makefile.freebsd
+++ b/Makefile.freebsd
@@ -17,7 +17,8 @@ EXECS = sg_readcap sg_turs sg_inq sg_start sg_modes sg_logs \
sg_sync sg_prevent sg_get_config sg_wr_mode \
sg_rtpg sg_reassign sg_format sg_rmsn sg_ident \
sg_read_long sg_write_long sg_verify sg_rdac sg_vpd \
- sg_sat_identify sg_read_buffer sg_write_buffer sg_opcodes
+ sg_sat_identify sg_read_buffer sg_write_buffer sg_opcodes \
+ sg_raw
MAN_PGS = sg_readcap.8 sg_turs.8 sg_inq.8 sg_start.8 sg_modes.8 sg_logs.8 \
sg_senddiag.8 sg_persist.8 sg_requests.8 sg_ses.8 sg_luns.8 \
@@ -25,8 +26,7 @@ MAN_PGS = sg_readcap.8 sg_turs.8 sg_inq.8 sg_start.8 sg_modes.8 sg_logs.8 \
sg_rtpg.8 sg_reassign.8 sg_format.8 sg_rmsn.8 sg_ident.8 \
sg_read_long.8 sg_write_long.8 sg_verify.8 sg_rdac.8 sg_vpd.8 \
sg3_utils.8 sg_sat_identify.8 sg_read_buffer.8 sg_write_buffer.8 \
- sg_opcodes.8
-
+ sg_opcodes.8 sg_raw.8
MAN_PREF = man8
HEADERS = sg_lib.h sg_cmds.h sg_cmds_basic.h sg_cmds_extra.h sg_pt.h
@@ -169,6 +169,9 @@ sg_write_buffer: sg_write_buffer.o libsgutils.la
sg_opcodes: sg_opcodes.o libsgutils.la
$(LIBTOOL) $(LT_EXTRA) --mode=link $(LD) -o $@ $(LDFLAGS) $@.o libsgutils.la
+sg_raw: sg_raw.o libsgutils.la
+ $(LIBTOOL) $(LT_EXTRA) --mode=link $(LD) -o $@ $(LDFLAGS) $@.o libsgutils.la
+
install: $(EXECS)
install -d $(INSTDIR)
install -d $(LIBDIR)
diff --git a/Makefile.mingw b/Makefile.mingw
index 1e44cfb9..9b4e240b 100644
--- a/Makefile.mingw
+++ b/Makefile.mingw
@@ -14,7 +14,8 @@ EXECS = sg_readcap sg_turs sg_inq sg_start sg_modes sg_logs sg_senddiag \
sg_sync sg_prevent sg_get_config sg_wr_mode \
sg_rtpg sg_reassign sg_format sg_rmsn sg_ident \
sg_read_long sg_write_long sg_verify sg_rdac sg_vpd \
- sg_sat_identify sg_read_buffer sg_write_buffer sg_opcodes
+ sg_sat_identify sg_read_buffer sg_write_buffer sg_opcodes \
+ sg_raw
EXE_S = sg_readcap.exe sg_turs.exe sg_inq.exe sg_start.exe sg_modes.exe \
sg_logs.exe sg_senddiag.exe sg_persist.exe sg_requests.exe \
@@ -23,7 +24,7 @@ EXE_S = sg_readcap.exe sg_turs.exe sg_inq.exe sg_start.exe sg_modes.exe \
sg_format.exe sg_rmsn.exe sg_ident.exe sg_read_long.exe \
sg_write_long.exe sg_verify.exe sg_rdac.exe sg_vpd.exe \
sg_sat_identify.exe sg_read_buffer.exe sg_write_buffer.exe \
- sg_opcodes.exe
+ sg_opcodes.exe sg_raw.exe
OS_FLAGS = -DSG3_UTILS_WIN32 -DSG3_UTILS_MINGW -DSPTD
# OS_FLAGS = -DSG3_UTILS_WIN32 -DSG3_UTILS_MINGW
@@ -36,6 +37,7 @@ CFLAGS = -g -O2 -Wall -W $(EXTRA_FLAGS)
O_FILES = sg_lib.o sg_cmds_basic.o sg_cmds_extra.o sg_pt_win32.o
O_BFILES = sg_lib.o sg_cmds_basic.o sg_pt_win32.o
+O_RFILES = sg_lib.o sg_pt_win32.o
O_SFILES = sg_lib.o
LDFLAGS =
@@ -138,3 +140,6 @@ sg_write_buffer: sg_write_buffer.o $(O_FILES)
sg_opcodes: sg_opcodes.o $(O_BFILES)
$(LD) -o $@ $(LDFLAGS) $@.o $(O_BFILES)
+sg_raw: sg_raw.o $(O_RFILES)
+ $(LD) -o $@ $(LDFLAGS) $@.o $(O_RFILES)
+
diff --git a/Makefile.osf1 b/Makefile.osf1
index f57c9d28..13a7066a 100644
--- a/Makefile.osf1
+++ b/Makefile.osf1
@@ -16,7 +16,8 @@ EXECS = sg_readcap sg_turs sg_inq sg_start sg_modes sg_logs \
sg_sync sg_prevent sg_get_config sg_wr_mode \
sg_rtpg sg_reassign sg_format sg_rmsn sg_ident \
sg_read_long sg_write_long sg_verify sg_rdac sg_vpd \
- sg_sat_identify sg_read_buffer sg_write_buffer sg_opcodes
+ sg_sat_identify sg_read_buffer sg_write_buffer sg_opcodes \
+ sg_raw
MAN_PGS = sg_readcap.8 sg_turs.8 sg_inq.8 sg_start.8 sg_modes.8 sg_logs.8 \
sg_senddiag.8 sg_persist.8 sg_requests.8 sg_ses.8 sg_luns.8 \
@@ -24,7 +25,7 @@ MAN_PGS = sg_readcap.8 sg_turs.8 sg_inq.8 sg_start.8 sg_modes.8 sg_logs.8 \
sg_rtpg.8 sg_reassign.8 sg_format.8 sg_rmsn.8 sg_ident.8 \
sg_read_long.8 sg_write_long.8 sg_verify.8 sg_rdac.8 sg_vpd.8 \
sg3_utils.8 sg_sat_identify.8 sg_read_buffer.8 sg_write_buffer.8 \
- sg_opcodes.8
+ sg_opcodes.8 sg_raw.8
MAN_PREF = man8
@@ -169,6 +170,9 @@ sg_write_buffer: sg_write_buffer.o libsgutils.la getopt_long/getopt_long.o
sg_opcodes: sg_opcodes.o libsgutils.la getopt_long/getopt_long.o
$(LIBTOOL) $(LT_EXTRA) --mode=link $(LD) -o $@ $(LDFLAGS) $@.o libsgutils.la getopt_long/getopt_long.o
+sg_raw: sg_raw.o libsgutils.la getopt_long/getopt_long.o
+ $(LIBTOOL) $(LT_EXTRA) --mode=link $(LD) -o $@ $(LDFLAGS) $@.o libsgutils.la getopt_long/getopt_long.o
+
install: $(EXECS)
test -d $(INSTDIR) || mkdir -p $(INSTDIR)
test -d $(LIBDIR) || mkdir -p $(LIBDIR)
diff --git a/Makefile.solaris b/Makefile.solaris
new file mode 100644
index 00000000..408e4500
--- /dev/null
+++ b/Makefile.solaris
@@ -0,0 +1,205 @@
+SHELL = /bin/sh
+
+PREFIX=/usr/local
+LIBDIR=$(DESTDIR)/$(PREFIX)/lib
+INSTDIR=$(DESTDIR)/$(PREFIX)/bin
+MANDIR=$(DESTDIR)/$(PREFIX)/man
+INCLUDEDIR=$(DESTDIR)/$(PREFIX)/include
+
+CC = gcc
+LD = gcc
+# LIBTOOL = libtool15
+LIBTOOL = libtool
+LT_EXTRA = --tag=junk
+
+EXECS = sg_readcap sg_turs sg_inq sg_start sg_modes sg_logs \
+ sg_senddiag sg_persist sg_requests sg_ses sg_luns \
+ sg_sync sg_prevent sg_get_config sg_wr_mode \
+ sg_rtpg sg_reassign sg_format sg_rmsn sg_ident \
+ sg_read_long sg_write_long sg_verify sg_rdac sg_vpd \
+ sg_sat_identify sg_read_buffer sg_write_buffer sg_opcodes \
+ sg_raw
+
+MAN_PGS = sg_readcap.8 sg_turs.8 sg_inq.8 sg_start.8 sg_modes.8 sg_logs.8 \
+ sg_senddiag.8 sg_persist.8 sg_requests.8 sg_ses.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_ident.8 \
+ sg_read_long.8 sg_write_long.8 sg_verify.8 sg_rdac.8 sg_vpd.8 \
+ sg3_utils.8 sg_sat_identify.8 sg_read_buffer.8 sg_write_buffer.8 \
+ sg_opcodes.8 sg_raw.8
+MAN_PREF = man8
+
+HEADERS = sg_lib.h sg_cmds.h sg_cmds_basic.h sg_cmds_extra.h sg_pt.h
+
+OS_FLAGS = -DSG3_UTILS_SOLARIS
+LARGE_FILE_FLAGS = -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64
+S_CFLAGS = $(OS_FLAGS) $(LARGE_FILE_FLAGS)
+
+# CFLAGS = -O2 -Wall -W
+CFLAGS = -g -O2 -Wall -W
+# CFLAGS = -g -O2 -Wall -W -pedantic -std=c99
+
+CFLAGS_PTHREADS = -D_REENTRANT
+
+# LDFLAGS = -lcam
+# LDFLAGS = -v -lm
+
+LIB_VINFO = 1:0:0
+# Perhaps should use "-release RELEASE" instead
+# RELEASE = 1.1
+
+all: $(EXECS)
+
+depend dep:
+ for i in *.c; do $(CC) $(INCLUDES) $(CFLAGS) -M $$i; \
+ done > .depend
+
+clean:
+ /bin/rm -f *.o $(EXECS) core* .depend *.a *.la *.lo
+ /bin/rm -rf .libs
+
+.c.o:
+ $(CC) $(INCLUDES) $(CFLAGS) $(S_CFLAGS) -c -o $@ $<
+
+sg_lib.lo: sg_lib.o
+ $(LIBTOOL) $(LT_EXTRA) --mode=compile $(CC) -c sg_lib.c
+
+sg_cmds_basic.lo: sg_cmds_basic.o
+ $(LIBTOOL) $(LT_EXTRA) --mode=compile $(CC) -c sg_cmds_basic.c
+
+sg_cmds_extra.lo: sg_cmds_extra.o
+ $(LIBTOOL) $(LT_EXTRA) --mode=compile $(CC) -c sg_cmds_extra.c
+
+sg_pt_solaris.lo: sg_pt_solaris.o
+ $(LIBTOOL) $(LT_EXTRA) --mode=compile $(CC) -c sg_pt_solaris.c
+
+libsgutils.la: sg_lib.lo sg_cmds_basic.lo sg_cmds_extra.lo sg_pt_solaris.lo
+ $(LIBTOOL) $(LT_EXTRA) --mode=link $(LD) -o libsgutils.la sg_lib.lo \
+ sg_cmds_basic.lo sg_cmds_extra.lo sg_pt_solaris.lo -rpath $(LIBDIR) \
+ -version-info $(LIB_VINFO)
+
+# libsgutils.la: sg_lib.lo sg_cmds_basic.lo sg_cmds_extra.lo
+# $(LIBTOOL) --mode=link $(LD) -o libsgutils.la sg_lib.lo \
+# sg_cmds_basic.lo sg_cmds_extra.lo -rpath $(LIBDIR) -release $(RELEASE)
+
+sg_readcap: sg_readcap.o libsgutils.la
+ $(LIBTOOL) $(LT_EXTRA) --mode=link $(LD) -o $@ $(LDFLAGS) $@.o libsgutils.la
+
+sg_turs: sg_turs.o libsgutils.la
+ $(LIBTOOL) $(LT_EXTRA) --mode=link $(LD) -o $@ $(LDFLAGS) $@.o libsgutils.la
+
+sg_inq: sg_inq.o libsgutils.la
+ $(LIBTOOL) $(LT_EXTRA) --mode=link $(LD) -o $@ $(LDFLAGS) $@.o libsgutils.la
+
+sg_start: sg_start.o libsgutils.la
+ $(LIBTOOL) $(LT_EXTRA) --mode=link $(LD) -o $@ $(LDFLAGS) $@.o libsgutils.la
+
+sg_modes: sg_modes.o libsgutils.la
+ $(LIBTOOL) $(LT_EXTRA) --mode=link $(LD) -o $@ $(LDFLAGS) $@.o libsgutils.la
+
+sg_logs: sg_logs.o libsgutils.la
+ $(LIBTOOL) $(LT_EXTRA) --mode=link $(LD) -o $@ $(LDFLAGS) $@.o libsgutils.la
+
+sg_senddiag: sg_senddiag.o libsgutils.la
+ $(LIBTOOL) $(LT_EXTRA) --mode=link $(LD) -o $@ $(LDFLAGS) $@.o libsgutils.la
+
+sg_persist: sg_persist.o libsgutils.la
+ $(LIBTOOL) $(LT_EXTRA) --mode=link $(LD) -o $@ $(LDFLAGS) $@.o libsgutils.la
+
+sg_requests: sg_requests.o libsgutils.la
+ $(LIBTOOL) $(LT_EXTRA) --mode=link $(LD) -o $@ $(LDFLAGS) $@.o libsgutils.la
+
+sg_ses: sg_ses.o libsgutils.la
+ $(LIBTOOL) $(LT_EXTRA) --mode=link $(LD) -o $@ $(LDFLAGS) $@.o libsgutils.la
+
+sg_luns: sg_luns.o libsgutils.la
+ $(LIBTOOL) $(LT_EXTRA) --mode=link $(LD) -o $@ $(LDFLAGS) $@.o libsgutils.la
+
+sg_sync: sg_sync.o libsgutils.la
+ $(LIBTOOL) $(LT_EXTRA) --mode=link $(LD) -o $@ $(LDFLAGS) $@.o libsgutils.la
+
+sg_prevent: sg_prevent.o libsgutils.la
+ $(LIBTOOL) $(LT_EXTRA) --mode=link $(LD) -o $@ $(LDFLAGS) $@.o libsgutils.la
+
+sg_get_config: sg_get_config.o libsgutils.la
+ $(LIBTOOL) $(LT_EXTRA) --mode=link $(LD) -o $@ $(LDFLAGS) $@.o libsgutils.la
+
+sg_wr_mode: sg_wr_mode.o libsgutils.la
+ $(LIBTOOL) $(LT_EXTRA) --mode=link $(LD) -o $@ $(LDFLAGS) $@.o libsgutils.la
+
+sg_rtpg: sg_rtpg.o libsgutils.la
+ $(LIBTOOL) $(LT_EXTRA) --mode=link $(LD) -o $@ $(LDFLAGS) $@.o libsgutils.la
+
+sg_reassign: sg_reassign.o libsgutils.la
+ $(LIBTOOL) $(LT_EXTRA) --mode=link $(LD) -o $@ $(LDFLAGS) $@.o libsgutils.la
+
+sg_format: sg_format.o libsgutils.la
+ $(LIBTOOL) $(LT_EXTRA) --mode=link $(LD) -o $@ $(LDFLAGS) $@.o libsgutils.la
+
+sg_rmsn: sg_rmsn.o libsgutils.la
+ $(LIBTOOL) $(LT_EXTRA) --mode=link $(LD) -o $@ $(LDFLAGS) $@.o libsgutils.la
+
+sg_ident: sg_ident.o libsgutils.la
+ $(LIBTOOL) $(LT_EXTRA) --mode=link $(LD) -o $@ $(LDFLAGS) $@.o libsgutils.la
+
+sg_read_long: sg_read_long.o libsgutils.la
+ $(LIBTOOL) $(LT_EXTRA) --mode=link $(LD) -o $@ $(LDFLAGS) $@.o libsgutils.la
+
+sg_write_long: sg_write_long.o libsgutils.la
+ $(LIBTOOL) $(LT_EXTRA) --mode=link $(LD) -o $@ $(LDFLAGS) $@.o libsgutils.la
+
+sg_verify: sg_verify.o libsgutils.la
+ $(LIBTOOL) $(LT_EXTRA) --mode=link $(LD) -o $@ $(LDFLAGS) $@.o libsgutils.la
+
+sg_rdac: sg_rdac.o libsgutils.la
+ $(LIBTOOL) $(LT_EXTRA) --mode=link $(LD) -o $@ $(LDFLAGS) $@.o libsgutils.la
+
+sg_vpd: sg_vpd.o sg_vpd_vendor.o libsgutils.la
+ $(LIBTOOL) $(LT_EXTRA) --mode=link $(LD) -o $@ $(LDFLAGS) $@.o sg_vpd_vendor.o libsgutils.la
+
+sg_sat_identify: sg_sat_identify.o libsgutils.la
+ $(LIBTOOL) $(LT_EXTRA) --mode=link $(LD) -o $@ $(LDFLAGS) $@.o libsgutils.la
+
+sg_read_buffer: sg_read_buffer.o libsgutils.la
+ $(LIBTOOL) $(LT_EXTRA) --mode=link $(LD) -o $@ $(LDFLAGS) $@.o libsgutils.la
+
+sg_write_buffer: sg_write_buffer.o libsgutils.la
+ $(LIBTOOL) $(LT_EXTRA) --mode=link $(LD) -o $@ $(LDFLAGS) $@.o libsgutils.la
+
+sg_opcodes: sg_opcodes.o libsgutils.la
+ $(LIBTOOL) $(LT_EXTRA) --mode=link $(LD) -o $@ $(LDFLAGS) $@.o libsgutils.la
+
+sg_raw: sg_raw.o libsgutils.la
+ $(LIBTOOL) $(LT_EXTRA) --mode=link $(LD) -o $@ $(LDFLAGS) $@.o libsgutils.la
+
+install: $(EXECS)
+ install -d $(INSTDIR)
+ install -d $(LIBDIR)
+ $(LIBTOOL) --mode=install $(LT_EXTRA) install -c libsgutils.la $(LIBDIR)/libsgutils.la
+ $(LIBTOOL) $(LT_EXTRA) --finish $(LIBDIR)
+ for name in $(EXECS); \
+ do $(LIBTOOL) $(LT_EXTRA) --mode=install install -m 755 \
+ -f $(INSTDIR) $$name; \
+ done
+ install -d $(MANDIR)/$(MAN_PREF)
+ for mp in $(MAN_PGS); \
+ do install -s -m 644 -f $(MANDIR)/$(MAN_PREF) $$mp; \
+ done
+# install -d $(INCLUDEDIR)/scsi
+# for hdr in $(HEADERS); \
+# do install -m 644 $$hdr $(INCLUDEDIR)/scsi ; \
+# done
+
+uninstall:
+ $(LIBTOOL) $(LT_EXTRA) --mode=uninstall rm -f $(LIBDIR)/libsgutils.la
+ dists="$(EXECS)"; \
+ for name in $$dists; do \
+ rm -f $(INSTDIR)/$$name; \
+ done
+ for mp in $(MAN_PGS); do \
+ rm -f $(MANDIR)/$(MAN_PREF)/$$mp; \
+ done
+# for hdr in $(HEADERS); do \
+# rm -f $(INCLUDEDIR)/scsi/$$hdr ; \
+# done
+
diff --git a/Makefile.win32 b/Makefile.win32
index 64b70569..a3708461 100644
--- a/Makefile.win32
+++ b/Makefile.win32
@@ -12,7 +12,8 @@ EXECS = sg_readcap sg_turs sg_inq sg_start sg_modes sg_logs sg_senddiag \
sg_sync sg_prevent sg_get_config sg_wr_mode \
sg_rtpg sg_reassign sg_format sg_rmsn sg_ident \
sg_read_long sg_write_long sg_verify sg_rdac sg_vpd \
- sg_sat_identify sg_read_buffer sg_write_buffer sg_opcodes
+ sg_sat_identify sg_read_buffer sg_write_buffer sg_opcodes \
+ sg_raw
EXE_S = sg_readcap.exe sg_turs.exe sg_inq.exe sg_start.exe sg_modes.exe \
sg_logs.exe sg_senddiag.exe sg_persist.exe sg_requests.exe \
@@ -21,7 +22,7 @@ EXE_S = sg_readcap.exe sg_turs.exe sg_inq.exe sg_start.exe sg_modes.exe \
sg_format.exe sg_rmsn.exe sg_ident.exe sg_read_long.exe \
sg_write_long.exe sg_verify.exe sg_rdac.exe sg_vpd.exe \
sg_sat_identify.exe sg_read_buffer.exe sg_write_buffer.exe \
- sg_opcodes.exe
+ sg_opcodes.exe sg_raw.exe
MAN_PGS = sg_readcap.8 sg_turs.8 sg_inq.8 sg_start.8 sg_modes.8 sg_logs.8 \
sg_senddiag.8 sg_persist.8 sg_requests.8 sg_ses.8 sg_luns.8 \
@@ -29,7 +30,7 @@ MAN_PGS = sg_readcap.8 sg_turs.8 sg_inq.8 sg_start.8 sg_modes.8 sg_logs.8 \
sg_rtpg.8 sg_reassign.8 sg_format.8 sg_rmsn.8 sg_ident.8 \
sg_read_long.8 sg_write_long.8 sg_verify.8 sg_rdac.8 sg_vpd.8 \
sg3_utils.8 sg_sat_identify.8 sg_read_buffer.8 sg_write_buffer.8 \
- sg_opcodes.8
+ sg_opcodes.8 sg_raw.8
MAN_PREF = man8
@@ -44,6 +45,7 @@ CFLAGS = -g -O2 -Wall -W $(EXTRA_FLAGS)
O_FILES = sg_lib.o sg_cmds_basic.o sg_cmds_extra.o sg_pt_win32.o
O_BFILES = sg_lib.o sg_cmds_basic.o sg_pt_win32.o
+O_RFILES = sg_lib.o sg_pt_win32.o
O_SFILES = sg_lib.o
LDFLAGS =
@@ -151,6 +153,9 @@ sg_write_buffer: sg_write_buffer.o $(O_FILES)
sg_opcodes: sg_opcodes.o $(O_BFILES)
$(LD) -o $@ $(LDFLAGS) $@.o $(O_BFILES)
+sg_raw: sg_raw.o $(O_RFILES)
+ $(LD) -o $@ $(LDFLAGS) $@.o $(O_RFILES)
+
install: $(EXECS)
cp sg_scan.8w sg_scan.8
install -d $(INSTDIR)
diff --git a/README b/README
index 13364916..f9a522b1 100644
--- a/README
+++ b/README
@@ -8,12 +8,12 @@ command set is used by ATAPI devices (CD/DVDs and tapes), USB
mass storage devices, Fibre Channel disks, IEEE 1394 storage
devices (that use the "SBP" protocol), SAS and iSCSI.
-This package originally targetted the Linux SCSI subsystem. Since most
+This package originally targeted the Linux SCSI subsystem. Since most
operating systems contain a SCSI command pass-through mechanism, many
utilities within this package have been ported. This README mainly
concentrates on Linux: see the README.freebsd file for the FreeBSD port,
-the README.tru64 file for the Tru64 (OSF) port and README.win32 for the
-Windows port.
+README.solaris for the Solaris port, the README.tru64 file for the Tru64
+(OSF) port and README.win32 for the Windows port.
Most utilities within the sg3_utils package work at the SCSI command level.
For example the sg_inq utility issues a SCSI INQUIRY command and decodes the
@@ -151,11 +151,11 @@ 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_ident, sg_inq, sg_logs, sg_luns, sg_map, sg_map26,
- sg_modes, sg_opcodes, sg_persist, sg_prevent, sg_rbuf, sg_rdac, sg_read,
- sg_readcap, sg_read_buffer, sg_read_long, sg_reassign, sg_request,
- sg_reset, sg_rmsn, sg_rtpg, sg_sat_identify, sg_scan, sg_senddiag,
- sg_ses, sg_start, sg_sync, sg_test_rwbuff, sg_turs, sg_verify, sg_vpd,
- sg_write_buffer, sg_write_long, sg_wr_mode
+ sg_modes, sg_opcodes, sg_persist, sg_prevent, sg_raw, sg_rbuf, sg_rdac,
+ sg_read, sg_readcap, sg_read_buffer, sg_read_long, sg_reassign,
+ sg_request, sg_reset, sg_rmsn, sg_rtpg, sg_sat_identify, sg_scan,
+ sg_senddiag, sg_ses, sg_start, sg_sync, sg_test_rwbuff, sg_turs,
+ sg_verify, sg_vpd, sg_write_buffer, 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
@@ -181,10 +181,10 @@ Some of these utilities have man pages.
Here is a list in alphabetical order of utilities found in the examples
subdirectory:
- - sg_excl.c, scsi_inquiry, sg_iovec_tst.c, sg_sat_chk_power.c,
- sg__sat_identify.c, sg_sat_set_features.c, sg_sat_smart_rd_data.c,
- sg_simple1, sg_simple2, sg_simple3, sg_simple4, sg_simple5 and
- sg_simple16.c
+ - sg_excl, scsi_inquiry, sg_iovec_tst, sg_sat_chk_power,
+ sg__sat_identify, sg_sat_phy_event, sg_sat_set_features,
+ sg_sat_smart_rd_data, sg_simple1, sg_simple2, sg_simple3, sg_simple4,
+ sg_simple5 and sg_simple16
Also in that subdirectory is a script to test sg_persist, an example
data file for sg_persist (called "transport_ids.txt") and an example
@@ -199,15 +199,8 @@ Unix od command. There is also code to sg_chk_asc.c which checks a given
text file (typically a copy of http://www.t10.org/lists/asc-num.txt ) and
checks it against the asc/ascq text strings held in sg_lib.c .
-The "doc" subdirectory contains copies of web pages relevant to
-the sg3_utils package. Currently it contains:
- - sg3_utils.html : a description of the sg3_utils package contents
- - sg_dd.html : describes the sg_dd utility and compares it with the
- Unix dd command
- - sg_io.html : describes the SG_IO ioctl used by sg3_utils. Looks
- at differences between the lk 2.4 and 2.6 series;
- including its use with block devices
- - tools.html : a list of SCSI and storage tools with a summary and url
+The "doc" subdirectory contains a README.doc file containing the urls of
+various related documents.
The "scripts" subdirectory contains some bourne (bash) shell scripts
that rely on utilities in the main directory. One script uses the sdparm
@@ -292,7 +285,7 @@ or using '-O' as the first command line option.
The more recent utilities that use "getopt_long" only are:
- sg_format sg_get_config sg_ident sg_luns sg_map26 sg_persist
- sg_prevent sg_read_buffer sg_read_long sg_reassign sg_requests
+ sg_prevent sg_raw sg_read_buffer sg_read_long sg_reassign sg_requests
sg_rmsn sg_rtpg sg_sat_identify sg_scan (w), sg_ses sg_sync
sg_test_rwbuf sg_verify sg_vpd sg_write_buffer sg_write_long
sg_wr_mode
@@ -326,21 +319,10 @@ The include file path issues are now all addressed in one file called
sg.h header files has not been a problem in the latter lk 2.4 and lk 2.6
series.
-scsirastools
-============
-This package found at http://scsirastools.sourceforge.net contains utilities
-which overlap with the functionality offered in sg3_utils. Utilities of note
-in scsirastools are:
- - sgdskfl: for loading firmware into SCSI disks
- - sgmode: get and set mode pages
- - sgdefects: list primary and grown defect lists
- - sgdiag to perform format and other test functions
-
-plscsi
-======
-This is a utility which can issue arbitrary SCSI commands (i.e. supplied by
-user). It is available for Linux and other operating systems.
-See http://members.aol.com/plscsi .
+Other SCSI and storage tools
+============================
+See http://www.torque.net/sg/tools.html
+
Doug Gilbert
-31st January 2007
+7th May 2007
diff --git a/README.freebsd b/README.freebsd
index 53e769db..19dd7d79 100644
--- a/README.freebsd
+++ b/README.freebsd
@@ -18,6 +18,7 @@ Here is a list of utilities that have been ported:
sg_persist
sg_opcodes
sg_prevent
+ sg_raw
sg_rdac
sg_read_buffer
sg_read_long
@@ -76,6 +77,8 @@ At the present time these utilities have been lightly tested on a
FreeBSD version 6.2 system with some SCSI disks, a SCSI tape
drive and an ATAPI CD drive.
+See the FreeBSD section in the INSTALL file for install directions.
+
Doug Gilbert
-15th January 2007
+3rd May 2007
diff --git a/README.solaris b/README.solaris
new file mode 100644
index 00000000..9c0f245e
--- /dev/null
+++ b/README.solaris
@@ -0,0 +1,78 @@
+Introduction
+============
+The Solaris port of sg3_utils contains those utilities that are _not_
+specific to Linux. In some cases a utility could be ported but
+requires more work. An example is sg_dd which needs more work
+beyond the SCSI command pass through mechanism.
+
+Supported Utilities
+===================
+Here is a list of utilities that have been ported:
+ sg_format
+ sg_get_config
+ sg_ident
+ sg_inq [dropped ATA IDENTIFY DEVICE capability]
+ sg_logs
+ sg_luns
+ sg_modes
+ sg_persist
+ sg_opcodes
+ sg_prevent
+ sg_raw
+ sg_rdac
+ sg_read_buffer
+ sg_read_long
+ sg_readcap
+ sg_reassign
+ sg_requests
+ sg_rmsn
+ sg_rtpg
+ sg_sat_identify
+ sg_senddiag
+ sg_ses
+ sg_start
+ sg_sync
+ sg_turs
+ sg_verify
+ sg_vpd
+ sg_wr_mode
+ sg_write_buffer
+ sg_write_long
+
+Most utility names are indicative of the main SCSI command
+that they execute. Some utilities are slightly higher level, for
+example sg_ses fetches SCSI Enclosure Services (SES) status pages and
+can send control pages. Each utility has a man page (placed in
+section 8). An overview of sg3_utils can be found at:
+http://www.torque.net/sg/sg3_utils.html .
+A copy of the "sg3_utils.html" file is in the "doc" subdirectory.
+
+
+See the INSTALL file (at the end) for instructions on how to build
+sg3_utils on FreeBSD. Some man pages have examples which use linux
+device names which hopefully will not confuse the FreeBSD users.
+
+
+Details
+=======
+The ported utilities listed above, all use SCSI command functions
+declared in sg_cmds_basic.h and sg_cmds_extra.h . Those SCSI command
+functions are implemented in the corresponding ".c" files. The ".c"
+files pass SCSI commands to the host operating system via
+an interface declared in sg_pt.h . There are currently four
+implementations of that interface depending on the host operating
+system:
+ - sg_pt_linux.c
+ - sg_pt_freebsd.c
+ - sg_pt_osf1.c [Tru64]
+ - sg_pt_solaris.c
+ - sg_pt_win32.c
+
+The sg_pt_solaris.c file uses the "uscsi" SCSI pass through
+mechanism.
+
+See the Solaris section in the INSTALL file for install directions.
+
+
+Doug Gilbert
+3rd May 2007
diff --git a/README.tru64 b/README.tru64
index f8d90b67..a2db4554 100644
--- a/README.tru64
+++ b/README.tru64
@@ -18,6 +18,7 @@ Here is a list of utilities that have been ported:
sg_opcodes
sg_persist
sg_prevent
+ sg_raw
sg_rdac
sg_read_buffer
sg_read_long
@@ -79,4 +80,4 @@ subdirectory. Currently only the Tru64 port uses it.
Doug Gilbert
-12th January 2006
+3rd May 2007
diff --git a/README.win32 b/README.win32
index 34f8bc1a..ffad80bf 100644
--- a/README.win32
+++ b/README.win32
@@ -29,6 +29,7 @@ Here is a list of utilities that have been ported:
sg_persist
sg_opcodes
sg_prevent
+ sg_raw
sg_rdac
sg_read_buffer
sg_read_long
@@ -128,4 +129,4 @@ See the INSTALL file for more details.
Doug Gilbert
-21st January 2007
+3rd May 2007
diff --git a/archive/o_scsi_logging_level b/archive/o_scsi_logging_level
new file mode 100755
index 00000000..ecbc8277
--- /dev/null
+++ b/archive/o_scsi_logging_level
@@ -0,0 +1,295 @@
+#! /bin/bash
+###############################################################################
+# Conveniently create and set scsi logging level, show SCSI_LOG fields in human
+# readable form.
+#
+# Copyright (C) IBM Corp. 2006
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or (at
+# your option) any later version.
+#
+# This program is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+# 02110-1301, USA.
+###############################################################################
+
+# Contributed by Andreas Herrmann <aherrman@de.ibm.com> 2006/08/18
+
+SCRIPTNAME="scsi_logging_level"
+
+declare -i LOG_ERROR=0
+declare -i LOG_TIMEOUT=0
+declare -i LOG_SCAN=0
+declare -i LOG_MLQUEUE=0
+declare -i LOG_MLCOMPLETE=0
+declare -i LOG_LLQUEUE=0
+declare -i LOG_LLCOMPLETE=0
+declare -i LOG_HLQUEUE=0
+declare -i LOG_HLCOMPLETE=0
+declare -i LOG_IOCTL=0
+
+declare -i LEVEL=0
+
+_ERROR_SHIFT=0
+_TIMEOUT_SHIFT=3
+_SCAN_SHIFT=6
+_MLQUEUE_SHIFT=9
+_MLCOMPLETE_SHIFT=12
+_LLQUEUE_SHIFT=15
+_LLCOMPLETE_SHIFT=18
+_HLQUEUE_SHIFT=21
+_HLCOMPLETE_SHIFT=24
+_IOCTL_SHIFT=27
+
+SET=0
+GET=0
+CREATE=0
+
+OPTS=`getopt -o hvcgsa:E:T:S:I:M:L:H: --long \
+help,version,create,get,set,all:,error:,timeout:,scan:,ioctl:,\
+midlevel:,mlqueue:,mlcomplete:,lowlevel:,llqueue:,llcomplete:,\
+highlevel:,hlqueue:,hlcomplete: -n \'$SCRIPTNAME\' -- "$@"`
+eval set -- "$OPTS"
+
+# print version info
+printversion()
+{
+ cat <<EOF
+$SCRIPTNAME (s390-tools) %S390_TOOLS_VERSION%
+(C) Copyright IBM Corp. 2006
+EOF
+}
+
+# print usage and help
+printhelp()
+{
+ cat <<EOF
+Usage: $SCRIPTNAME [OPTIONS]
+
+Create, get or set scsi logging level.
+
+Options:
+
+ -h, --help print this help
+ -v, --version print version information
+ -s, --set create and set logging level as specified on
+ command line
+ -g, --get get current logging level and display it
+ -c, --create create logging level as specified on command line
+ -a, --all specify value for all SCSI_LOG fields
+ -E, --error specify SCSI_LOG_ERROR
+ -T, --timeout specify SCSI_LOG_TIMEOUT
+ -S, --scan specify SCSI_LOG_SCAN
+ -M, --midlevel specify SCSI_LOG_MLQUEUE and SCSI_LOG_MLCOMPLETE
+ --mlqueue specify SCSI_LOG_MLQUEUE
+ --mlcomplete specify SCSI_LOG_MLCOMPLETE
+ -L, --lowlevel specify SCSI_LOG_LLQUEUE and SCSI_LOG_LLCOMPLETE
+ --llqueue specify SCSI_LOG_LLQUEUE
+ --llcomplete specify SCSI_LOG_LLCOMPLETE
+ -H, --highlevel specify SCSI_LOG_HLQUEUE and SCSI_LOG_HLCOMPLETE
+ --hlqueue specify SCSI_LOG_HLQUEUE
+ --hlcomplete specify SCSI_LOG_HLCOMPLETE
+ -I, --ioctl specify SCSI_LOG_IOCTL
+
+Exactly one of the options "-c", "-g" and "-s" has to be specified.
+Valid values for SCSI_LOG fields are integers from 0 to 7.
+
+Note: Several SCSI_LOG fields can be specified using several options.
+When multiple options specify same SCSI_LOG field the most specific
+option has precedence.
+
+Example: "scsi_logging_level --hlqueue 3 --hlcomplete 2 --all 1 -s" sets
+SCSI_LOG_HLQUEUE=3, SCSI_LOG_HLCOMPLETE=2 and assigns all other SCSI_LOG
+fields the value 1.
+EOF
+}
+
+check_level()
+{
+# something is wrong with the following if ... dpg 20061027
+# if [ `echo -n $1 | tr --complement [:digit:] 'a' | grep -s 'a'` ]
+# then
+# invalid_cmdline "log level '$1' out of range [0, 7]"
+# fi
+
+ if [ $1 -lt 0 -o $1 -gt 7 ]
+ then
+ invalid_cmdline "log level '$1' out of range [0, 7]"
+ fi
+}
+
+# check cmd line arguments
+check_cmdline()
+{
+ while true ; do
+ case "$1" in
+ -a|--all) _ALL=$2; check_level $2
+ shift 2;;
+ -c|--create) CREATE=1;
+ shift 1;;
+ -g|--get) GET=1
+ shift 1;;
+ -h|--help) printhelp
+ exit 0;;
+ -s|--set) SET=1
+ shift 1;;
+ -v|--version) printversion
+ exit 0;;
+ -E|--error) _ERROR=$2; check_level $2
+ shift 2;;
+ -T|--timeout) _TIMEOUT=$2; check_level $2
+ shift 2;;
+ -S|--scan) _SCAN=$2; check_level $2
+ shift 2;;
+ -M|--midlevel) _ML=$2; check_level $2
+ shift 2;;
+ --mlqueue) _MLQUEUE=$2; check_level $2
+ shift 2;;
+ --mlcomplete) _MLCOMPLETE=$2; check_level $2
+ shift 2;;
+ -L|--lowlevel) _LL=$2; check_level $2
+ shift 2;;
+ --llqueue) _LLQUEUE=$2; check_level $2
+ shift 2;;
+ --llcomplete) _LLCOMPLETE=$2; check_level $2
+ shift 2;;
+ -H|--highlevel) _HL=$2; check_level $2
+ shift 2;;
+ --hlqueue) _HLQUEUE=$2; check_level $2
+ shift 2;;
+ --hlcomplete) _HLCOMPLETE=$2; check_level $2
+ shift 2;;
+ -I|--ioctl) _IOCTL=$2; check_level $2
+ shift 2;;
+ --) shift; break;;
+ *) echo "Internal error!" ; exit 1;;
+ esac
+ done
+
+ if [ -n "$*" ]
+ then
+ invalid_cmdline invalid parameter $*
+ fi
+
+ if [ $GET = "1" -a $SET = "1" ]
+ then
+ invalid_cmdline options \'-c\', \'-g\' and \'-s\' are mutual exclusive
+ elif [ $GET = "1" -a $CREATE = "1" ]
+ then
+ invalid_cmdline options \'-c\', \'-g\' and \'-s\' are mutual exclusive
+ elif [ $SET = "1" -a $CREATE = "1" ]
+ then
+ invalid_cmdline options \'-c\', \'-g\' and \'-s\' are mutual exclusive
+ fi
+
+ LOG_ERROR=${_ERROR:-${_ALL:-0}}
+ LOG_TIMEOUT=${_TIMEOUT:-${_ALL:-0}}
+ LOG_SCAN=${_SCAN:-${_ALL:-0}}
+ LOG_MLQUEUE=${_MLQUEUE:-${_ML:-${_ALL:-0}}}
+ LOG_MLCOMPLETE=${_MLCOMPLETE:-${_ML:-${_ALL:-0}}}
+ LOG_LLQUEUE=${_LLQUEUE:-${_LL:-${_ALL:-0}}}
+ LOG_LLCOMPLETE=${_LLCOMPLETE:-${_LL:-${_ALL:-0}}}
+ LOG_HLQUEUE=${_HLQUEUE:-${_HL:-${_ALL:-0}}}
+ LOG_HLCOMPLETE=${_HLCOMPLETE:-${_HL:-${_ALL:-0}}}
+ LOG_IOCTL=${_IOCTL:-${_ALL:-0}}
+}
+
+invalid_cmdline()
+{
+ echo "$SCRIPTNAME: $*"
+ echo "$SCRIPTNAME: Try '$SCRIPTNAME --help' for more information."
+ exit 1
+}
+
+get_logging_level()
+{
+ echo "Current scsi logging level:"
+ LEVEL=`sysctl -n dev.scsi.logging_level`
+ if [ $? != 0 ]
+ then
+ echo "$SCRIPTNAME: could not read scsi logging level" \
+ "(kernel probably without SCSI_LOGGING support)"
+ exit 1
+ fi
+}
+
+show_logging_level()
+{
+ echo "dev.scsi.logging_level = $LEVEL"
+
+ LOG_ERROR=$((($LEVEL>>$_ERROR_SHIFT) & 7))
+ LOG_TIMEOUT=$((($LEVEL>>$_TIMEOUT_SHIFT) & 7))
+ LOG_SCAN=$((($LEVEL>>$_SCAN_SHIFT) & 7))
+ LOG_MLQUEUE=$((($LEVEL>>$_MLQUEUE_SHIFT) & 7))
+ LOG_MLCOMPLETE=$((($LEVEL>>$_MLCOMPLETE_SHIFT) & 7))
+ LOG_LLQUEUE=$((($LEVEL>>$_LLQUEUE_SHIFT) & 7))
+ LOG_LLCOMPLETE=$((($LEVEL>>$_LLCOMPLETE_SHIFT) & 7))
+ LOG_HLQUEUE=$((($LEVEL>>$_HLQUEUE_SHIFT) & 7))
+ LOG_HLCOMPLETE=$((($LEVEL>>$_HLCOMPLETE_SHIFT) & 7))
+ LOG_IOCTL=$((($LEVEL>>$_IOCTL_SHIFT) & 7))
+
+ echo "SCSI_LOG_ERROR=$LOG_ERROR"
+ echo "SCSI_LOG_TIMEOUT=$LOG_TIMEOUT"
+ echo "SCSI_LOG_SCAN=$LOG_SCAN"
+ echo "SCSI_LOG_MLQUEUE=$LOG_MLQUEUE"
+ echo "SCSI_LOG_MLCOMPLETE=$LOG_MLCOMPLETE"
+ echo "SCSI_LOG_LLQUEUE=$LOG_LLQUEUE"
+ echo "SCSI_LOG_LLCOMPLETE=$LOG_LLCOMPLETE"
+ echo "SCSI_LOG_HLQUEUE=$LOG_HLQUEUE"
+ echo "SCSI_LOG_HLCOMPLETE=$LOG_HLCOMPLETE"
+ echo "SCSI_LOG_IOCTL=$LOG_IOCTL"
+}
+
+set_logging_level()
+{
+ echo "New scsi logging level:"
+ sysctl -q -w dev.scsi.logging_level=$LEVEL
+ if [ $? != 0 ]
+ then
+ echo "$SCRIPTNAME: could not write scsi logging level" \
+ "(kernel probably without SCSI_LOGGING support)"
+ exit 1
+ fi
+}
+
+create_logging_level()
+{
+ LEVEL=$((($LOG_ERROR & 7)<<$_ERROR_SHIFT))
+ LEVEL=$(($LEVEL|(($LOG_TIMEOUT & 7)<<$_TIMEOUT_SHIFT)))
+ LEVEL=$(($LEVEL|(($LOG_SCAN & 7)<<$_SCAN_SHIFT)))
+ LEVEL=$(($LEVEL|(($LOG_MLQUEUE & 7)<<$_MLQUEUE_SHIFT)))
+ LEVEL=$(($LEVEL|(($LOG_MLCOMPLETE & 7)<<$_MLCOMPLETE_SHIFT)))
+ LEVEL=$(($LEVEL|(($LOG_LLQUEUE & 7)<<$_LLQUEUE_SHIFT)))
+ LEVEL=$(($LEVEL|(($LOG_LLCOMPLETE & 7)<<$_LLCOMPLETE_SHIFT)))
+ LEVEL=$(($LEVEL|(($LOG_HLQUEUE & 7)<<$_HLQUEUE_SHIFT)))
+ LEVEL=$(($LEVEL|(($LOG_HLCOMPLETE & 7)<<$_HLCOMPLETE_SHIFT)))
+ LEVEL=$(($LEVEL|(($LOG_IOCTL & 7)<<$_IOCTL_SHIFT)))
+}
+
+check_cmdline $*
+
+if [ $SET = "1" ]
+then
+ create_logging_level
+ set_logging_level
+ show_logging_level
+elif [ $GET = "1" ]
+then
+ get_logging_level
+ show_logging_level
+elif [ $CREATE = "1" ]
+then
+ create_logging_level
+ show_logging_level
+else
+ invalid_cmdline missing option \'-g\', \'-s\' or \'-c\'
+fi
+
diff --git a/archive/sg3_utils_123o.spec b/archive/sg3_utils_123o.spec
deleted file mode 100644
index ee8295fa..00000000
--- a/archive/sg3_utils_123o.spec
+++ /dev/null
@@ -1,193 +0,0 @@
-%define name sg3_utils
-%define version 1.23
-%define release 1
-
-%define major 1
-%define minor 0
-%define libname %{_lib}sgutils-%{major}_%{minor}
-
-Summary: Utilities for SCSI devices in Linux
-Name: %{name}
-Version: %{version}
-Release: %{release}
-License: GPL/FreeBSD
-Group: Utilities/System
-URL: http://www.torque.net/sg/sg3_utils.html
-Source0: http://www.torque.net/sg/p/%{name}-%{version}.tgz
-BuildRoot: %{_tmppath}/%{name}-%{version}-root
-Packager: Douglas Gilbert <dgilbert at interlog dot com>
-
-%description
-Collection of Linux utilities for devices that use the SCSI command set.
-Includes utilities to copy data based on "dd" syntax and semantics (called
-sg_dd, sgp_dd and sgm_dd); check INQUIRY data and VPD pages (sg_inq); check
-mode and log pages (sginfo, sg_modes and sg_logs); spin up and down
-disks (sg_start); do self tests (sg_senddiag); and various other functions.
-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).
-
-Warning: Some of these tools access the internals of your system
-and the incorrect usage of them may render your system inoperable.
-
-%package -n %{libname}
-Summary: Shared library for %{name}
-Group: System/Libraries
-
-%description -n %{libname}
-This package contains the shared library for %{name}.
-
-%package -n %{libname}-devel
-Summary: Static library and header files for the sgutils library
-Group: Development/C
-Obsoletes: %{name}-devel
-Provides: %{name}-devel
-Provides: libsgutils-devel
-Requires: %{libname} = %{version}-%{release}
-
-%description -n %{libname}-devel
-This package contains the static sgutils library and its header
-files.
-
-%prep
-
-%setup -q
-
-%build
-
-make \
- CFLAGS="%{optflags}" \
- LIBDIR="%{_libdir}"
-
-%install
-[ "%{buildroot}" != "/" ] && rm -rf %{buildroot}
-
-make install \
- PREFIX=%{_prefix} \
- LIBDIR=%{buildroot}/%{_libdir} \
- INSTDIR=%{buildroot}/%{_bindir} \
- MANDIR=%{buildroot}/%{_mandir} \
- INCLUDEDIR=%{buildroot}/%{_includedir} \
- LIB_VINFO=1:0:0
-
-%post -n %{libname} -p /sbin/ldconfig
-
-%postun -n %{libname} -p /sbin/ldconfig
-
-%clean
-[ "%{buildroot}" != "/" ] && rm -rf %{buildroot}
-
-%files
-%defattr(-,root,root)
-%doc CHANGELOG COPYING COVERAGE CREDITS INSTALL README README.sg_start
-%attr(0755,root,root) %{_bindir}/*
-%{_mandir}/man8/*
-
-%files -n %{libname}
-%defattr(-,root,root)
-%{_libdir}/*.so.*
-
-%files -n %{libname}-devel
-%defattr(-,root,root)
-%{_includedir}/scsi/*.h
-%{_libdir}/*.so
-%{_libdir}/*.a
-%{_libdir}/*.la
-
-%changelog
-* Tue Jan 30 2007 - dgilbert at interlog dot com
-- add sg_read_buffer + sg_write_buffer
- * sg3_utils-1.23
-
-* Mon Oct 16 2006 - dgilbert at interlog dot com
-- add sg_sat_identify, expand sg_format and sg_requests
- * sg3_utils-1.22
-
-* Thu Jul 06 2006 - dgilbert at interlog dot com
-- add sg_vpd and sg_rdac, uniform exit statuses
- * sg3_utils-1.21
-
-* Tue Apr 18 2006 - dgilbert at interlog dot com
-- sg_logs: sas port specific page decoding, sg*_dd updates
- * sg3_utils-1.20
-
-* Fri Jan 27 2006 - dgilbert at interlog dot com
-- sg_get_config: resync features with mmc5 rev 1
- * sg3_utils-1.19
-
-* Fri Nov 18 2005 - dgilbert at interlog dot com
-- add sg_map26; sg_inq '-rr' option to play with hdparm
- * sg3_utils-1.18
-
-* Thu Sep 22 2005 - dgilbert at interlog dot com
-- add ATA information VPD page to sg_inq
- * sg3_utils-1.17
-
-* 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
-
-* Fri May 06 2005 - dgilbert at interlog dot com
-- produce libsgutils (+ -devel variant) as well as sg3_utils binary rpm
- * sg3_utils-1.14
-
-* Sun Mar 13 2005 - dgilbert at interlog dot com
-- add sg_format, sg_dd extensions
- * sg3_utils-1.13
-
-* Fri Jan 21 2005 - dgilbert at interlog dot com
-- add sg_wr_mode, sg_rtpg + sg_reassign; sginfo sas tweaks
- * sg3_utils-1.12
-
-* Fri Nov 26 2004 - dgilbert at interlog dot com
-- add sg_sync, sg_prevent and sg_get_config; fix sg_requests
- * sg3_utils-1.11
-
-* Sat Oct 30 2004 - dgilbert at interlog dot com
-- fix read capacity (10+16), add sg_luns
- * sg3_utils-1.10
-
-* Thu Oct 21 2004 - dgilbert at interlog dot com
-- sg_requests, sg_ses, sg_verify, libsgutils(sg_lib.c+sg_cmds.c), devel rpm
- * sg3_utils-1.09
-
-* Tue Aug 31 2004 - dgilbert at interlog dot com
-- 'register+move' in sg_persist, sg_opcodes sorts, sg_write_long
- * sg3_utils-1.08
-
-* Thu Jul 08 2004 - dgilbert at interlog dot com
-- add '-fHead' to sginfo, '-i' for sg_inq, new sg_opcodes + sg_persist
- * sg3_utils-1.07
-
-* Mon Apr 26 2004 - dgilbert at interlog dot com
-- sg3_utils.spec for mandrake; more sginfo work, sg_scan, sg_logs
- * sg3_utils-1.06
-
-* Wed Nov 12 2003 - dgilbert at interlog dot com
-- sg_readcap: sizes; sg_logs: double fetch; sg_map 256 sg devices; sginfo
- * sg3_utils-1.05
-
-* Tue May 13 2003 - dgilbert at interlog dot com
-- default sg_turs '-n=' to 1, sg_logs gets '-t' for temperature, CREDITS
- * sg3_utils-1.04
-
-* Wed Apr 02 2003 - dgilbert at interlog dot com
-- 6 byte CDBs for sg_modes, sg_start on block devs, sg_senddiag, man pages
- * sg3_utils-1.03
-
-* Wed Jan 01 2003 - dgilbert at interlog dot com
-- interwork with block SG_IO, fix in sginfo, '-t' for sg_turs
- * sg3_utils-1.02
-
-* Wed Aug 14 2002 - dgilbert at interlog dot com
-- raw switch in sg_inq
- * sg3_utils-1.01
-
-* Sun Jul 28 2002 - dgilbert at interlog dot com
-- decode sg_logs pages, add dio to sgm_dd, drop "gen=1" arg, "of=/dev/null"
- * sg3_utils-1.00
diff --git a/debian/changelog b/debian/changelog
index 5642bd70..63e9ed54 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,3 +1,9 @@
+sg3-utils (1.24-0.1) unstable; urgency=low
+
+ * New upstream version
+
+ -- Doug Gilbert <dgilbert@interlog.com> Mon, 07 May 2007 16:00:00 -0400
+
sg3-utils (1.23-0.1) unstable; urgency=low
* New upstream version
diff --git a/debian/control b/debian/control
index ee0040be..31672eeb 100644
--- a/debian/control
+++ b/debian/control
@@ -35,6 +35,7 @@ Description: Collection of Linux utilities for devices that use the
* 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_raw - send arbitrary SCSI commands
* sg_rbuf - tests SCSI bus speed
* sg_rdac - vendor specific for RDAC hardware
* sg_read - reads multiple blocks, useful for timing
diff --git a/debian/docs b/debian/docs
index 34ad7eeb..3efd96cd 100644
--- a/debian/docs
+++ b/debian/docs
@@ -4,7 +4,4 @@ CREDITS
INSTALL
README
README.sg_start
-doc/sg3_utils.html
-doc/sg_dd.html
-doc/sg_io.html
-doc/tools.html
+doc/README.doc
diff --git a/doc/README.doc b/doc/README.doc
new file mode 100644
index 00000000..8218362f
--- /dev/null
+++ b/doc/README.doc
@@ -0,0 +1,23 @@
+Various html files used to be included in this directory but they were
+beginning to bloat the size of the source tarball so they have been
+removed in version 1.24 .
+
+Here are the urls of the files that were previously here plus a brief
+summary:
+
+http://www.torque.net/sg/sg3_utils.html
+ - overview and examples of this package
+
+http://www.torque.net/sg/sg_dd.html
+ - discussion and examples of the sg_dd utility which is a dd variant
+ (also discusses the sgm_dd, sgp_dd and sg_read utilities)
+
+http://www.torque.net/sg/sg_io.html
+ - discussion of Linux SG_IO ioctl (SCSI pass-through)
+
+http://www.torque.net/sg/tools.html
+ - overview of around 25 storage and SCSI tools
+
+
+Doug Gilbert
+28th February 2007
diff --git a/doc/sg3_utils.html b/doc/sg3_utils.html
deleted file mode 100644
index 5016a9f8..00000000
--- a/doc/sg3_utils.html
+++ /dev/null
@@ -1,1634 +0,0 @@
-<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
-<html>
-<head>
- <title>Linux sg3_utils package</title>
- <meta http-equiv="Content-Type"
- content="text/html; charset=iso-8859-1">
- <meta name="keywords" content="sg3_utils, SCSI utilities, linux">
- <meta name="GENERATOR"
- content="Mozilla/4.79 [en] (X11; U; Linux 2.5.31 i686) [Netscape]">
-</head>
-<body alink="#ff0000" background="paper.jpg" bgcolor="#ffffff"
- link="#0000ff" text="#000000" vlink="#000080">
-<center>
-<h1><a class="mozTocH1" name="mozTocId697451"></a> The&nbsp; Linux
-sg3_utils package</h1>
-</center>
-<a href="#intro"></a>
-<ol id="mozToc">
-<!--mozToc h1 1 h2 2 h3 3 h4 4 h5 5 h6 6-->
- <li><a href="#mozTocId697451"> The&nbsp; Linux
-sg3_utils package</a>
- <ol>
- <li><a href="#mozTocId746876"> Introduction</a></li>
- <li><a href="#mozTocId832900"> Contents of sg3_utils</a></li>
- <li><a href="#mozTocId736867">Exit status</a></li>
- <li><a href="#mozTocId143590">Changing mode page
-settings</a></li>
- <li><a href="#mozTocId301018">Examples</a></li>
- <li><a href="#mozTocId585558"> Notes</a></li>
- <li><a href="#mozTocId479511"> Download</a></li>
- </ol>
- </li>
-</ol>
-<h2><a class="mozTocH2" name="mozTocId746876"></a> Introduction</h2>
-The <span style="font-weight: bold;">sg3_utils</span> package contains
-utilities
-that send SCSI commands to devices. As well as devices on
-transports traditionally associated with SCSI (e.g. Fibre Channel
-(FCP), Serial
-Attached SCSI (SAS) and the SCSI
-Parallel Interface(SPI)) many
-other devices use SCSI command sets. ATAPI cd/dvd drives
-and SATA disks that connect via a translation layer or a bridge device
-are
-examples of devices that use SCSI command sets.<br>
-<br>
-SCSI command sets are divided into a common set and several device
-class specific sets. The common set of commands is referred to as the
-SCSI Primary Commands (SPC) with SPC-3 being the most recent standard.
-The mandatory SCSI INQUIRY command is defined in SPC-3. The SCSI Block
-Commands (SBC)
-cover direct access devices such as disks. The MultiMedia Commands
-(MMC) cover CD and DVD drives and the media within them. SCSI
-command sets and transport
-definitions can be found at the <a href="http://www.t10.org">www.t10.org</a>
-site with this page giving a good diagrammatic overview: <a
- href="http://www.t10.org/scsi-3.htm">www.t10.org/scsi-3.htm</a> .<br>
-<br>
-The
-<span style="font-weight: bold;">sg3_utils</span> package targets the
-linux kernel 2.4 and 2.6 series and is
-still being enhanced. An earlier package called sg_utils
-targeted the 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>
-for further information about sg_utils.&nbsp; This
-document describes
-<span style="font-weight: bold;">version 1.23</span> of <span
- style="font-weight: bold;">sg3_utils</span> .&nbsp; A subset of these
-utilities have been ported to the FreeBSD, Tru64 and the Windows
-operating
-systems.<br>
-<br>
-In the linux kernel 2.4 series most of these utilities must be
-used with a SCSI generic (sg) driver device name (e.g. <span
- style="font-family: monospace;">/dev/sg0</span>). In
-the lk 2.6 series almost all of these utilities can be used with the
-primary device names as well (e.g. <span
- style="font-family: monospace;">/dev/sda, /dev/scd0, /dev/st0</span>
-and
-<span style="font-family: monospace;">/dev/hdd</span> (if it is an
-ATAPI device)). The SCSI generic (sg) interface
-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.<br>
-<p>A list of SCSI and storage utility programs that was at the bottom
-of this page has been moved to the <a href="tools.html">tools</a> page.<span
- style="font-weight: bold;"><br>
-</span></p>
-<h2><a class="mozTocH2" name="mozTocId832900"></a> Contents of sg3_utils</h2>
-This package contains over 30 utilities, their "man" pages, build files
-and general documentation (e.g. several README files). The utilities
-have a command line interface which in general has this form:<br>
-<br>
-<span style="font-family: monospace;">UTILITY_NAME [OPTIONS] DEVICE</span><br>
-<br>
-No more than one DEVICE name can be given (and in a few cases, no
-DEVICE name is required). Here is a listing in alphabetical order of
-the utilities in the
-sg3_utils package:<br>
-<br>
-<table style="width: 100%; text-align: left;" border="1" cellpadding="2"
- cellspacing="2">
- <caption><span style="font-weight: bold;">Table 1
-Utilities in sg3_utils</span><br>
- </caption> <tbody>
- <tr>
- <td style="vertical-align: top;"><span style="font-weight: bold;">Utility</span><br>
- </td>
- <td style="vertical-align: top;"><span style="font-weight: bold;">Main
-SCSI commands</span><br>
- </td>
- <td style="vertical-align: top;"><span style="font-weight: bold;">directory<br>
- </span> </td>
- <td style="vertical-align: top;"><span style="font-weight: bold;">CLI</span><br>
- </td>
- <td style="vertical-align: top;"><span style="font-weight: bold;">Ported</span><br>
- </td>
- <td style="vertical-align: top;"><span style="font-weight: bold;">Notes</span><br>
- </td>
- </tr>
- <tr>
- <td style="vertical-align: top;">hxascdmp<br>
- </td>
- <td style="vertical-align: top;">-<br>
- </td>
- <td style="vertical-align: top;">utils<br>
- </td>
- <td style="vertical-align: top;">adhoc<br>
- </td>
- <td style="vertical-align: top;">fb<br>
- </td>
- <td style="vertical-align: top;">converts stdin (assumed binary)
-to ASCII hex and ASCII, sending its output to stdout (like the Unix <span
- style="font-weight: bold;">od</span> command)<br>
- </td>
- </tr>
- <tr>
- <td style="vertical-align: top;">rescan-scsi-bus.sh<br>
- </td>
- <td style="vertical-align: top;">-<br>
- </td>
- <td style="vertical-align: top;">archive<br>
- </td>
- <td style="vertical-align: top;">adhoc<br>
- </td>
- <td style="vertical-align: top;"><br>
- </td>
- <td style="vertical-align: top;">copy of Kurt Garloff's useful
-script<br>
- </td>
- </tr>
- <tr>
- <td style="vertical-align: top;">scsi_inquiry<br>
- </td>
- <td style="vertical-align: top;">INQUIRY<br>
- </td>
- <td style="vertical-align: top;">examples<br>
- </td>
- <td style="vertical-align: top;">adhoc<br>
- </td>
- <td style="vertical-align: top;"><br>
- </td>
- <td style="vertical-align: top;">uses deprecated
-SCSI_IOCTL_SEND_COMMAND ioctl<br>
- </td>
- </tr>
- <tr>
- <td style="vertical-align: top;">sdparm<br>
- </td>
- <td style="vertical-align: top;">MODE SENSE/SELECT, INQUIRY<br>
- </td>
- <td style="vertical-align: top;">--&gt;<br>
- </td>
- <td style="vertical-align: top;">getopt<br>
- </td>
- <td style="vertical-align: top;">fb,t64,w<br>
- </td>
- <td style="vertical-align: top;">was in sg3_utils for a short
-time; now in own package, see <a href="sdparm.html">sdparm</a> .
-sdparm manipulates mode pages, reads VPD pages and sends simple
-commands.<br>
- </td>
- </tr>
- <tr>
- <td style="vertical-align: top;">sg_chk_asc<br>
- </td>
- <td style="vertical-align: top;">-<br>
- </td>
- <td style="vertical-align: top;">utils<br>
- </td>
- <td style="vertical-align: top;">getopt<br>
- </td>
- <td style="vertical-align: top;">fb<br>
- </td>
- <td style="vertical-align: top;">check asc/ascq codes from <a
- href="http://www.t10.org">www.t10.org</a> page against
-sg3_utils table<br>
- </td>
- </tr>
- <tr>
- <td style="vertical-align: top;">sginfo<br>
- </td>
- <td style="vertical-align: top;">MODE SENSE/SELECT, READ DEFECT<br>
- </td>
- <td style="vertical-align: top;"><br>
- </td>
- <td style="vertical-align: top;">adhoc<br>
- </td>
- <td style="vertical-align: top;"><br>
- </td>
- <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. <span
- style="font-family: monospace;">/dev/sda</span>) as well as sg device
-nodes. Port of older <span style="font-weight: bold;">scsiinfo</span>
-utility.<br>
- </td>
- </tr>
- <tr>
- <td style="vertical-align: top;">sgm_dd<br>
- </td>
- <td style="vertical-align: top;">READ, WRITE<br>
- </td>
- <td style="vertical-align: top;"><br>
- </td>
- <td style="vertical-align: top;">dd<br>
- </td>
- <td style="vertical-align: top;"><br>
- </td>
- <td style="vertical-align: top;">sg_dd variant that uses memory
-mapped IO (only on linux sg devices)<br>
- </td>
- </tr>
- <tr>
- <td style="vertical-align: top;">sgp_dd<br>
- </td>
- <td style="vertical-align: top;">READ, WRITE<br>
- </td>
- <td style="vertical-align: top;"><br>
- </td>
- <td style="vertical-align: top;">dd<br>
- </td>
- <td style="vertical-align: top;"><br>
- </td>
- <td style="vertical-align: top;">sg_dd variant that uses POSIX
-threads<br>
- </td>
- </tr>
- <tr>
- <td style="vertical-align: top;">sg_dd<br>
- </td>
- <td style="vertical-align: top;">READ, WRITE<br>
- </td>
- <td style="vertical-align: top;"><br>
- </td>
- <td style="vertical-align: top;">dd<br>
- </td>
- <td style="vertical-align: top;"><br>
- </td>
- <td style="vertical-align: top;">Unix <span
- style="font-weight: bold;">dd</span> command variant, uses
-SG_IO ioctl to send SCSI commands to copy data. See the <a
- href="sg_dd.html">sg_dd</a> page. </td>
- </tr>
- <tr>
- <td style="vertical-align: top;">sg_emc_trespass<br>
- </td>
- <td style="vertical-align: top;">MODE SELECT<br>
- </td>
- <td style="vertical-align: top;"><br>
- </td>
- <td style="vertical-align: top;">adhoc<br>
- </td>
- <td style="vertical-align: top;"><br>
- </td>
- <td style="vertical-align: top;">utility specialized for EMC
-Clariion series<br>
- </td>
- </tr>
- <tr>
- <td style="vertical-align: top;">sg_format<br>
- </td>
- <td style="vertical-align: top;">FORMAT<br>
- </td>
- <td style="vertical-align: top;"><br>
- </td>
- <td style="vertical-align: top;">getopt<br>
- </td>
- <td style="vertical-align: top;">fb,t64,w<br>
- </td>
- <td style="vertical-align: top;">format or resize a SCSI disk<br>
- </td>
- </tr>
- <tr>
- <td style="vertical-align: top;">sg_get_config<br>
- </td>
- <td style="vertical-align: top;">GET CONFIGURATION<br>
- </td>
- <td style="vertical-align: top;"><br>
- </td>
- <td style="vertical-align: top;">getopt<br>
- </td>
- <td style="vertical-align: top;">fb,t64,w </td>
- <td style="vertical-align: top;">fetch features and profiles of a
-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 IDENTIFYING
-INFORMATION<br>
- </td>
- <td style="vertical-align: top;"><br>
- </td>
- <td style="vertical-align: top;">getopt<br>
- </td>
- <td style="vertical-align: top;">fb,t64,w </td>
- <td style="vertical-align: top;">default is to report (fetch) the
-device identifier. With the '<span style="font-family: monospace;">--set</span>'
-option a new identifier is sent
-to the device.<br>
- </td>
- </tr>
- <tr>
- <td style="vertical-align: top;">sg_inq<br>
- </td>
- <td style="vertical-align: top;">INQUIRY<br>
- </td>
- <td style="vertical-align: top;"><br>
- </td>
- <td style="vertical-align: top;">getopt+<br>
- </td>
- <td style="vertical-align: top;">fb,t64,w </td>
- <td style="vertical-align: top;">fetch standard response, VPD
-pages or version descriptors. Also
-can perform IDENTIFY (PACKET) DEVICE ATA command. VPD page decoding
-also performed by sg_vpd and sdparm.<br>
- </td>
- </tr>
- <tr>
- <td style="vertical-align: top;">sg_logs<br>
- </td>
- <td style="vertical-align: top;">LOG SENSE<br>
- </td>
- <td style="vertical-align: top;"><br>
- </td>
- <td style="vertical-align: top;">getopt+<br>
- </td>
- <td style="vertical-align: top;">fb,t64,w </td>
- <td style="vertical-align: top;">fetch log sense pages, decode
-standard and some vendor pages<br>
- </td>
- </tr>
- <tr>
- <td style="vertical-align: top;">sg_luns<br>
- </td>
- <td style="vertical-align: top;">REPORT LUNS<br>
- </td>
- <td style="vertical-align: top;"><br>
- </td>
- <td style="vertical-align: top;">getopt<br>
- </td>
- <td style="vertical-align: top;">fb,t64,w </td>
- <td style="vertical-align: top;">fetch luns reported by a device
-(lun 0 or "well known lu")<br>
- </td>
- </tr>
- <tr>
- <td style="vertical-align: top;">sg_map<br>
- </td>
- <td style="vertical-align: top;">INQUIRY<br>
- </td>
- <td style="vertical-align: top;"><br>
- </td>
- <td style="vertical-align: top;">adhoc<br>
- </td>
- <td style="vertical-align: top;"><br>
- </td>
- <td style="vertical-align: top;">shows mapping between sg devices
-and primary device node (if any). In lk 2.6 see <a
- href="../scsi/lsscsi.html">lsscsi</a> .<br>
- </td>
- </tr>
- <tr>
- <td style="vertical-align: top;">sg_map26<br>
- </td>
- <td style="vertical-align: top;"><br>
- </td>
- <td style="vertical-align: top;"><br>
- </td>
- <td style="vertical-align: top;">getopt<br>
- </td>
- <td style="vertical-align: top;"><br>
- </td>
- <td style="vertical-align: top;">maps between single linux sg
-device
-and primary device node (and vice versa). Also does mapping in to, and
-out of, sysfs. For the linux 2.6 series.<br>
- </td>
- </tr>
- <tr>
- <td style="vertical-align: top;">sg_modes<br>
- </td>
- <td style="vertical-align: top;">MODE SENSE<br>
- </td>
- <td style="vertical-align: top;"><br>
- </td>
- <td style="vertical-align: top;">getopt+<br>
- </td>
- <td style="vertical-align: top;">fb,t64,w </td>
- <td style="vertical-align: top;">fetch mode pages (mainly in hex)<br>
- </td>
- </tr>
- <tr>
- <td style="vertical-align: top;">sg_opcodes<br>
- </td>
- <td style="vertical-align: top;">REPORT SUPPORTED OPERATION CODES<br>
- </td>
- <td style="vertical-align: top;"><br>
- </td>
- <td style="vertical-align: top;">getopt+<br>
- </td>
- <td style="vertical-align: top;">fb,t64,w<br>
- </td>
- <td style="vertical-align: top;">fetch supported SCSI commands or
-supported task management functions<br>
- </td>
- </tr>
- <tr>
- <td style="vertical-align: top;">sg_persist<br>
- </td>
- <td style="vertical-align: top;">PERSISTENT RESERVE IN/OUT<br>
- </td>
- <td style="vertical-align: top;"><br>
- </td>
- <td style="vertical-align: top;">getopt<br>
- </td>
- <td style="vertical-align: top;">fb,t64,w </td>
- <td style="vertical-align: top;">control persistent reservations
-and report
-reservation status<br>
- </td>
- </tr>
- <tr>
- <td style="vertical-align: top;">sg_prevent<br>
- </td>
- <td style="vertical-align: top;">PREVENT ALLOW MEDIUM REMOVAL<br>
- </td>
- <td style="vertical-align: top;"><br>
- </td>
- <td style="vertical-align: top;">getopt<br>
- </td>
- <td style="vertical-align: top;">fb,t64,w </td>
- <td style="vertical-align: top;">control media removal, mainly
-for those SCSI devices which have removable media (e.g. CD/DVD and tape
-drives)<br>
- </td>
- </tr>
- <tr>
- <td style="vertical-align: top;">sg_rbuf<br>
- </td>
- <td style="vertical-align: top;">READ BUFFER<br>
- </td>
- <td style="vertical-align: top;"><br>
- </td>
- <td style="vertical-align: top;">getopt+<br>
- </td>
- <td style="vertical-align: top;"><br>
- </td>
- <td style="vertical-align: top;">read from SCSI device cache.
-Typically for testing the SCSI transport (for throughput or errors)<br>
- </td>
- </tr>
- <tr>
- <td style="vertical-align: top;">sg_rdac<br>
- </td>
- <td style="vertical-align: top;">MODE SENSE/SELECT<br>
- </td>
- <td style="vertical-align: top;"><br>
- </td>
- <td style="vertical-align: top;">adhoc<br>
- </td>
- <td style="vertical-align: top;">fb,t64,w</td>
- <td style="vertical-align: top;">display or modify RDAC redundant
-controller mode page<br>
- </td>
- </tr>
- <tr>
- <td style="vertical-align: top;">sg_read<br>
- </td>
- <td style="vertical-align: top;">READ<br>
- </td>
- <td style="vertical-align: top;"><br>
- </td>
- <td style="vertical-align: top;">dd<br>
- </td>
- <td style="vertical-align: top;"><br>
- </td>
- <td style="vertical-align: top;">read continually from same
-offset. Syntax similar to sg_dd (without write side). Can test SCSI
-device cache and transport performance.<br>
- </td>
- </tr>
- <tr>
- <td style="vertical-align: top;">sg_readcap<br>
- </td>
- <td style="vertical-align: top;">READ CAPACITY<br>
- </td>
- <td style="vertical-align: top;"><br>
- </td>
- <td style="vertical-align: top;">getopt+<br>
- </td>
- <td style="vertical-align: top;">fb,t64,w </td>
- <td style="vertical-align: top;">fetch the number of blocks and
-the individual block size for disks and CD/DVD media<br>
- </td>
- </tr>
- <tr>
- <td style="vertical-align: top;">sg_read_buffer<br>
- </td>
- <td style="vertical-align: top;">READ BUFFER<br>
- </td>
- <td style="vertical-align: top;"><br>
- </td>
- <td style="vertical-align: top;">getopt<br>
- </td>
- <td style="vertical-align: top;">fb,t64,w<br>
- </td>
- <td style="vertical-align: top;">read descriptors or data<br>
- </td>
- </tr>
- <tr>
- <td style="vertical-align: top;">sg_read_long<br>
- </td>
- <td style="vertical-align: top;">READ LONG<br>
- </td>
- <td style="vertical-align: top;"><br>
- </td>
- <td style="vertical-align: top;">getopt<br>
- </td>
- <td style="vertical-align: top;">fb,t64,w </td>
- <td style="vertical-align: top;">read data from given lba which
-includes the block and ECC data.<br>
- </td>
- </tr>
- <tr>
- <td style="vertical-align: top;">sg_reassign<br>
- </td>
- <td style="vertical-align: top;">REASSIGN BLOCKS<br>
- </td>
- <td style="vertical-align: top;"><br>
- </td>
- <td style="vertical-align: top;">getopt<br>
- </td>
- <td style="vertical-align: top;">fb,t64,w </td>
- <td style="vertical-align: top;">reassign a lba from one sector
-on a disk (typically damaged) to a new (spare) sector. User data copied
-if it is recoverable.<br>
- </td>
- </tr>
- <tr>
- <td style="vertical-align: top;">sg_requests<br>
- </td>
- <td style="vertical-align: top;">REQUEST SENSE<br>
- </td>
- <td style="vertical-align: top;"><br>
- </td>
- <td style="vertical-align: top;">getopt<br>
- </td>
- <td style="vertical-align: top;">fb,t64,w </td>
- <td style="vertical-align: top;">fetch sense data from the given
-device. Modern uses include getting a progress indication (e.g.
-during a format) or finding the power condition state.<br>
- </td>
- </tr>
- <tr>
- <td style="vertical-align: top;">sg_reset<br>
- </td>
- <td style="vertical-align: top;">-<br>
- </td>
- <td style="vertical-align: top;"><br>
- </td>
- <td style="vertical-align: top;">adhoc<br>
- </td>
- <td style="vertical-align: top;"><br>
- </td>
- <td style="vertical-align: top;">Issue a driver, (SCSI) bus or
-device (target or lun?) reset.<br>
- </td>
- </tr>
- <tr>
- <td style="vertical-align: top;">sg_rmsn<br>
- </td>
- <td style="vertical-align: top;">READ MEDIA SERIAL NUMBER<br>
- </td>
- <td style="vertical-align: top;"><br>
- </td>
- <td style="vertical-align: top;">getopt<br>
- </td>
- <td style="vertical-align: top;">fb,t64,w </td>
- <td style="vertical-align: top;">Relatively new command
-added to SPC-3. Format of response is vendor specific so this utility
-outputs it in hex (default) or binary.<br>
- </td>
- </tr>
- <tr>
- <td style="vertical-align: top;">sg_rtpg<br>
- </td>
- <td style="vertical-align: top;">REPORT TARGET PORT GROUPS<br>
- </td>
- <td style="vertical-align: top;"><br>
- </td>
- <td style="vertical-align: top;">getopt<br>
- </td>
- <td style="vertical-align: top;">fb,t64,w </td>
- <td style="vertical-align: top;">Specialized for multi-ported
-SCSI devices where one port (or a group of them) is preferred for IO
-over another (or others).<br>
- </td>
- </tr>
- <tr>
- <td style="vertical-align: top;">sg_sat_identify<br>
- </td>
- <td style="vertical-align: top;">ATA PASS-THROUGH</td>
- <td style="vertical-align: top;"><br>
- </td>
- <td style="vertical-align: top;">getopt<br>
- </td>
- <td style="vertical-align: top;">fb,t64,w<br>
- </td>
- <td style="vertical-align: top;">Sends IDENTIFY DEVICE or
-IDENTIFY PACKET DEVICE ATA commands via the SAT ATA PASS-THROUGH (16 or
-12) SCSI command.</td>
- </tr>
- <tr>
- <td style="vertical-align: top;">sg__sat_identify<br>
- </td>
- <td style="vertical-align: top;">ATA PASS-THROUGH<br>
- </td>
- <td style="vertical-align: top;">examples<br>
- </td>
- <td style="vertical-align: top;">adhoc<br>
- </td>
- <td style="vertical-align: top;"><br>
- </td>
- <td style="vertical-align: top;">Simpler version of
-sg_sat_identify that uses the linux SG_IO ioctl directly. See also
-sg_sat_chk_power, sg_sat_set_features and sg_sat_smart_rd_data in the
-examples subdirectory.<br>
- </td>
- </tr>
- <tr>
- <td style="vertical-align: top;">sg_scan<br>
- </td>
- <td style="vertical-align: top;">[INQUIRY]<br>
- </td>
- <td style="vertical-align: top;"><br>
- </td>
- <td style="vertical-align: top;">adhoc<br>
-[win:<br>
-getopt]<br>
- </td>
- <td style="vertical-align: top;">w<br>
- </td>
- <td style="vertical-align: top;">maps each sg device name to
-the corresponding numeric &lt;host, channel, target, lun&gt; tuple. In
-lk 2.6 series the "<a href="scsi/lsscsi.html">lsscsi</a> -g" command is
-similar. In Windows shows one device per line, with the device's
-various names and INQUIRY response string on that line.<br>
- </td>
- </tr>
- <tr>
- <td style="vertical-align: top;">sg_senddiag<br>
- </td>
- <td style="vertical-align: top;">SEND DIAGNOSTIC<br>
- </td>
- <td style="vertical-align: top;"><br>
- </td>
- <td style="vertical-align: top;">getopt+<br>
- </td>
- <td style="vertical-align: top;">fb,t64,w </td>
- <td style="vertical-align: top;">Issues either a default self
-test or a short/extended foreground/background self test. With no
-arguments it uses RECEIVE DIAGNOSTIC RESULTS to list all supported
-diagnostic
-pages.<br>
- </td>
- </tr>
- <tr>
- <td style="vertical-align: top;">sg_ses<br>
- </td>
- <td style="vertical-align: top;">SEND/RECEIVE DIAGNOSTIC<br>
- </td>
- <td style="vertical-align: top;"><br>
- </td>
- <td style="vertical-align: top;">getopt<br>
- </td>
- <td style="vertical-align: top;">fb,t64,w </td>
- <td style="vertical-align: top;">Fetches status diagnostic
-pages from, and sends some control pages to, a SCSI Enclosure Services
-(SES) device.<br>
- </td>
- </tr>
- <tr>
- <td style="vertical-align: top;">sg_simple1,2,3,4,5<br>
- </td>
- <td style="vertical-align: top;">INQUIRY, TEST UNIT READY<br>
- </td>
- <td style="vertical-align: top;">examples<br>
- </td>
- <td style="vertical-align: top;">adhoc<br>
- </td>
- <td style="vertical-align: top;"><br>
- </td>
- <td style="vertical-align: top;">Simple code examples of using
-the scsi generic (sg) driver interface<br>
- </td>
- </tr>
- <tr>
- <td style="vertical-align: top;">sg_simple16<br>
- </td>
- <td style="vertical-align: top;">READ<br>
- </td>
- <td style="vertical-align: top;">examples<br>
- </td>
- <td style="vertical-align: top;">adhoc<br>
- </td>
- <td style="vertical-align: top;"><br>
- </td>
- <td style="vertical-align: top;">Simple code example of sending a
-16 byte cdb SCSI READ command<br>
- </td>
- </tr>
- <tr>
- <td style="vertical-align: top;">sg_start<br>
- </td>
- <td style="vertical-align: top;">START STOP UNIT<br>
- </td>
- <td style="vertical-align: top;"><br>
- </td>
- <td style="vertical-align: top;">getopt+<br>
- </td>
- <td style="vertical-align: top;">fb,t64,w </td>
- <td style="vertical-align: top;">Controls the power condition
-state of a SCSI device. Primary use is to spin up and down SCSI disks.
-Can also load and eject removable media.<br>
- </td>
- </tr>
- <tr>
- <td style="vertical-align: top;">sg_sync<br>
- </td>
- <td style="vertical-align: top;">SYNCHRONIZE CACHE<br>
- </td>
- <td style="vertical-align: top;"><br>
- </td>
- <td style="vertical-align: top;">getopt<br>
- </td>
- <td style="vertical-align: top;">fb,t64,w </td>
- <td style="vertical-align: top;">Causes disk caches to be flushed
-to media<br>
- </td>
- </tr>
- <tr>
- <td style="vertical-align: top;">sg_test_rwbuf<br>
- </td>
- <td style="vertical-align: top;">READ/WRITE BUFFER<br>
- </td>
- <td style="vertical-align: top;"><br>
- </td>
- <td style="vertical-align: top;">getopt<br>
- </td>
- <td style="vertical-align: top;"><br>
- </td>
- <td style="vertical-align: top;">Random pattern written to SCSI
-device buffer then read back and checked. Used in testing for data
-corruption.<br>
- </td>
- </tr>
- <tr>
- <td style="vertical-align: top;">sg_turs<br>
- </td>
- <td style="vertical-align: top;">TEST UNIT READY<br>
- </td>
- <td style="vertical-align: top;"><br>
- </td>
- <td style="vertical-align: top;">getopt+<br>
- </td>
- <td style="vertical-align: top;">fb,t64,w </td>
- <td style="vertical-align: top;">Issue one or more Test Unit
-Ready commands. Can be used to time SCSI command overhead.<br>
- </td>
- </tr>
- <tr>
- <td style="vertical-align: top;">sg_verify</td>
- <td style="vertical-align: top;">VERIFY</td>
- <td style="vertical-align: top;"><br>
- </td>
- <td style="vertical-align: top;">getopt<br>
- </td>
- <td style="vertical-align: top;">fb,t64,w </td>
- <td style="vertical-align: top;">reads indicated blocks on a SCSI
-disks, stops on the first error found. Does not yield any data. Useful
-for media scans.</td>
- </tr>
- <tr>
- <td style="vertical-align: top;">sg_vpd<br>
- </td>
- <td style="vertical-align: top;">INQUIRY<br>
- </td>
- <td style="vertical-align: top;"><br>
- </td>
- <td style="vertical-align: top;">getopt<br>
- </td>
- <td style="vertical-align: top;">fb,t64,w<br>
- </td>
- <td style="vertical-align: top;">Decodes standard and some vendor
-Vital Product Data (VPD) pages.<br>
- </td>
- </tr>
- <tr>
- <td style="vertical-align: top;">sg_write_buffer<br>
- </td>
- <td style="vertical-align: top;">WRITE BUFFER<br>
- </td>
- <td style="vertical-align: top;"><br>
- </td>
- <td style="vertical-align: top;">getopt<br>
- </td>
- <td style="vertical-align: top;">fb,t64,w<br>
- </td>
- <td style="vertical-align: top;">write data; can be used to
-download firmware<br>
- </td>
- </tr>
- <tr>
- <td style="vertical-align: top;">sg_write_long<br>
- </td>
- <td style="vertical-align: top;">WRITE LONG<br>
- </td>
- <td style="vertical-align: top;"><br>
- </td>
- <td style="vertical-align: top;">getopt<br>
- </td>
- <td style="vertical-align: top;">fb,t64,w </td>
- <td style="vertical-align: top;">writes to a lba, data which
-includes the block and ECC data. Suitable data typically fetched by
-prior
-sg_read_long utility.<br>
- </td>
- </tr>
- <tr>
- <td style="vertical-align: top;">sg_wr_mode<br>
- </td>
- <td style="vertical-align: top;">MODE SELECT<br>
- </td>
- <td style="vertical-align: top;"><br>
- </td>
- <td style="vertical-align: top;">getopt<br>
- </td>
- <td style="vertical-align: top;">fb,t64,w </td>
- <td style="vertical-align: top;">writes mode pages supplied in
-ASCII hex (e.g. from "<span style="font-family: monospace;">sg_modes -r</span>")
-to the&nbsp; SCSI device. See <a href="sdparm.html">sdparm</a> for
-another method of setting mode page
-parameters.<br>
- </td>
- </tr>
- </tbody>
-</table>
-<br>
-More SCSI commands may be issued than shown in the <span
- style="font-weight: bold;">Main SCSI
-commands</span> column. For example many utilities issue a SCSI INQUIRY
-command to find out the peripheral device type of the given
-device. Some SCSI commands listed above are only relevant to a specific
-device type (e.g. FORMAT UNIT) and should not be sent to a device
-belonging to other peripheral device types (and in some cases these
-utilities will
-block inappropriate attempts). See the COVERAGE file in the main
-directory of the tarball for a more exhaustive list of SCSI (and ATA)
-commands
-issued by the sg3_utils utilities.<br>
-<br>
-If the <span style="font-weight: bold;">directory</span>
-column is empty in the above table then that utility is in the main
-directory and more
-documentation can be found in its "man" page. Some utilities in the
-subdirectories have "man"
-pages.<br>
-<br>
-The <span style="font-weight: bold;">CLI</span> column indicates what
-kind of command line interface the utility has. Recent utilities have a
-cli based on the getopt_long() function which offers both long option
-names (e.g. "<span style="font-family: monospace;">--verbose</span>")
-and a short form (e.g. '<span style="font-family: monospace;">-v</span>'),
-both forms can
-take an argument. Experience has led to consistent use of various
-options such as "<span style="font-family: monospace;">--help</span>", "<span
- style="font-family: monospace;">--verbose</span>" and "<span
- style="font-family: monospace;">--version</span>" across these
-utilities. Utilities with this type of cli are marked with "getopt".
-The original utilities had an "ad hoc" type cli that unfortunately
-lacked consistency and had a mix of long and short forms (with the long
-form sometime prefixed with "-" and on other occasions with "--".
-Utilities with this type of cli are marked with "adhoc". There is also
-a group of utilities that are related to the Unix dd command and share
-its quirky cli. Finally a group of well used utilities with ad hoc
-command line interfaces had a getop_long() based interface added in
-sg3_utils version 1.23 . These utilities include sg_inq, sg_logs and
-sg_modes. The default cli for this group is "getopt" but by using
-"<span style="font-family: monospace;">--old</span>" or "-O" as the
-first option the older ad hoc options can be
-used. This group will default to the older ad hoc interface if the
-environment variable SG3_UTILS_OLD_OPTS is defined. Utilities with this
-type of cli are marked with "getopt+".<br>
-<br>
-If the <span style="font-weight: bold;">Ported</span> column is empty
-then the utility is only found in
-Linux. Support for other ports is indicated by "fb" for FreeBSD, "t64"
-for Tru64 (OSF) and "w" for Windows. See the README.freebsd,
-README.tru64 and README.win32 files
-for more information.<br>
-<br>
-This paragraph contains Linux specific information. All utilities that
-issue SCSI commands and that appear in the main directory of table 1,
-with the exception of sgp_dd,
-issue SG_IO ioctls. The sgp_dd utility issues SCSI commands using the
-sg
-driver's asynchronous ( write()/read() ) interface to device nodes that
-have the sg driver's major device number (i.e. "char" major 21). This
-means that all utilities in the main directory are "safe" with any
-given device node. If the device node does not support the SG_IO ioctl
-then that is reported and the utility exits. [In version 1.14 sgm_dd
-also use the sg
-driver's asynchronous ( write()/read() ) interface but that has been
-changed to the SG_IO ioctl in version 1.15 since the asynchronous
-action is not needed. sgm_dd will only use mmapped IO on sg device
-nodes.]<br>
-<br>
-Irrespective of the device node used to access a device, care
-should be taken not to interfere with a device while it is "active".
-For example invoking a "<span style="font-family: monospace;">sg_format
--F</span>" utility on a disk with mounted
-file
-systems on it is obviously going to cause damage.<br>
-<h2><a class="mozTocH2" name="mozTocId736867"></a>Exit status</h2>
-Each process containing one of sg3_utils' command line utilities
-completes
-with an exit status of 0 when
-successful. Prior to version 1.21 all errors yielded an exit status of
-1. Having finer grain error reporting via the exit status from
-relatively low level sg3_utils utilities allows higher level scripts
-and other program wrappers to do more useful error processing.<br>
-<br>
-From version 1.22 the exit status value is one of:<br>
-<ul>
- <li><span style="font-weight: bold;">1</span>&nbsp;&nbsp; syntax
-error in command line options or their arguments, or an illegal
-combination of options.</li>
- <li><span style="font-weight: bold;">2</span>&nbsp;&nbsp; the device
-reports that it is not ready for the operation requested. The device
-may be in the process of becoming ready (e.g. spinning up but not at
-speed) so the utility may work a little while later.</li>
- <li><span style="font-weight: bold;">3</span>&nbsp;&nbsp; the device
-reports a medium or hardware error (or a blank check). For example an
-attempt to read a corrupted block on a disk will yield this value. <br>
- </li>
- <li><span style="font-weight: bold;">5</span>&nbsp;&nbsp; the device
-reports an "illegal request" with an additional sense code other than
-"invalid operation code". This is often a supported command with a
-field set requesting an unsupported capability. For commands that
-require a "service action" field (e.g. READ CAPACITY(16) ) this value
-can indicate that the
-command is not supported.</li>
- <li><span style="font-weight: bold;">6</span>&nbsp;&nbsp; the device
-reports a "unit attention" condition. This usually indicates that
-something unrelated to the requested command has occurred (e.g. a
-device reset) potentially before the current SCSI command was sent. The
-requested command has not been executed by the device. Note that unit
-attention conditions are usually only reported once by a device.</li>
- <li><span style="font-weight: bold;">9</span>&nbsp;&nbsp; the device
-reports an illegal request with an additional sense code of "invalid
-operation code" which means that it doesn't support the requested
-command.</li>
- <li><span style="font-weight: bold;">11</span>&nbsp; the device (or
-transport) reports an aborted command. In some cases this can be caused
-by congestion on the transport and retrying the command may be
-successful.<br>
- </li>
- <li><span style="font-weight: bold;">15</span> &nbsp; the utility is
-unable to open, close or use the given device. The given file name
-could be incorrect or there may be permission problems. Adding the '<span
- style="font-family: monospace;">-v</span>'
-option may give more information.</li>
- <li><span style="font-weight: bold;">20</span>&nbsp;&nbsp; the DEVICE
-reports it has a check condition but "no sense".
-Some polling commands (e.g. REQUEST SENSE) can react this way. It is
-unlikely that this value will occur as an exit status.</li>
- <li><span style="font-weight: bold;">21</span>&nbsp;&nbsp; the device
-reports a "recovered error". The requested command was successful. Most
-likely a utility will report a recovered error to stderr and continue,
-probably leaving the utility with an exit status of 0 .</li>
- <li><span style="font-weight: bold;">33</span>&nbsp;&nbsp; the
-command sent to the device has timed out. This appears on in Linux, in
-other ports a command timeout will appear as a transport (or OS) error.<br>
- </li>
- <li><span style="font-weight: bold;">97</span>&nbsp;&nbsp; the
-response to a SCSI command failed sanity checks.</li>
- <li><span style="font-weight: bold;">98</span>&nbsp;&nbsp; the device
-reports it has a check condition but the error doesn't fit into any of
-the above categories.</li>
- <li><span style="font-weight: bold;">99</span>&nbsp;&nbsp; any errors
-that can't be categorized into values 1 to 98 may yield this value.
-This includes transport and operating system errors.<br>
- </li>
-</ul>
-Many of the above exit statuses will be repeatable so executing the
-utility again with one or more '<span style="font-family: monospace;">-v</span>'
-options may yield more information.
-Unit attentions (exit status 6) are only reported once per condition.
-Notice that some of the lower exit status values correspond to the SCSI
-sense key values. Some examples of bash scripts that use these exit
-values see the <span style="font-style: italic;">scripts</span>
-subdirectory.<br>
-<h2><a class="mozTocH2" name="mozTocId143590"></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 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
-in the Caching mode page of SCSI disks. Usually the manufacturer's
-default setting for WCE is set (on) however in some RAID configurations
-it may be cleared (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 linux utilities for
-changing
-mode pages followed by some notes:<br>
-<ul>
- <li><span style="font-weight: bold;">scsiinfo</span> (old utility):
-awkward command line interface with double invocation (first to get,
-second to set). Only mode page fields that the utility knows about can
-be changed.<br>
- </li>
- <li><span style="font-weight: bold;">sginfo</span> (sg3_utils version
-of scsiinfo): same awkward interface as scsiinfo but the mode pages are
-more up to date. Supports other modern features such as mode subpages.<br>
- </li>
- <li><span style="font-weight: bold;">sg_wr_mode</span> (sg3_utils):
-low level mode page settings based on ASCII hex representation. Used
-with sg_modes to get a mode page in raw form and assumes ACSII hex will
-be edited. Low level but general.</li>
- <li><span style="font-weight: bold;">sdparm</span> (sdparm): uses
-acronyms (e.g. WCE) or numeric addressing to fetch and/or change mode
-page settings.
-Allows device to be reset to default settings for a specific mode page.
-The user can choose whether changes are also made to the "saved" mode
-page values. The
-numeric addressing allows arbitrary fields to be changed (i.e. sdparm
-doesn't need to know about a mode page or its field structure in
-advance).<br>
- </li>
- <li><span style="font-weight: bold;">sgmode</span> (scsirastools):
-interactive utility for setting mode pages with data held in preset
-".mdf" files. Useful to setting a large number of disks to preset mode
-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 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 linux kernel 2.6
-series.
-For SCSI devices only a relatively small (but important) number of mode
-page fields can be changed.</li>
- <li>vendor specific (e.g. seatools from Seagate): several vendors
-have utilities like this. Worth investigating and often useful with
-disks from other manufacturers. Vendor extensions can be controlled
-(e.g. Seagate's desktop/server mode (also see sdparm's man page about
-this particular feature)).<br>
- </li>
-</ul>
-The author's recommendation is to use <a href="sdparm.html">sdparm</a>
-unless the features of
-another utility better suit your needs.<br>
-<h2><a class="mozTocH2" name="mozTocId301018"></a>Examples</h2>
-The fundamental SCSI command whose support is mandatory for all SCSI
-devices is INQUIRY. All devices should respond to a "standard" (i.e.
-when no Vital Product Pages are requested) INQUIRY.<br>
-<br>
-<span style="font-family: monospace;">$ sg_inq /dev/sda</span><br
- style="font-family: monospace;">
-<span style="font-family: monospace;">standard INQUIRY:</span><br
- style="font-family: monospace;">
-<span style="font-family: monospace;">&nbsp; PQual=0&nbsp;
-Device_type=0&nbsp; RMB=0&nbsp; version=0x03&nbsp; [SPC]</span><br
- style="font-family: monospace;">
-<span style="font-family: monospace;">&nbsp; [AERC=0]&nbsp;
-[TrmTsk=0]&nbsp; NormACA=0&nbsp; HiSUP=1&nbsp; Resp_data_format=2</span><br
- style="font-family: monospace;">
-<span style="font-family: monospace;">&nbsp; SCCS=0&nbsp; ACC=0&nbsp;
-TGPS=0&nbsp; 3PC=0&nbsp; Protect=0</span><br
- style="font-family: monospace;">
-<span style="font-family: monospace;">&nbsp; BQue=0&nbsp;
-EncServ=0&nbsp; MultiP=0&nbsp; MChngr=0&nbsp; [ACKREQQ=0]&nbsp; Addr16=1</span><br
- style="font-family: monospace;">
-<span style="font-family: monospace;">&nbsp; [RelAdr=0]&nbsp;
-WBus16=1&nbsp; Sync=1&nbsp; Linked=1&nbsp; [TranDis=1]&nbsp; CmdQue=1</span><br
- style="font-family: monospace;">
-<span style="font-family: monospace;">&nbsp; Clocking=0x3&nbsp;
-QAS=0&nbsp; IUS=0</span><br style="font-family: monospace;">
-<span style="font-family: monospace;">&nbsp;&nbsp;&nbsp; length=144
-(0x90)&nbsp;&nbsp; Peripheral device type: disk</span><br
- style="font-family: monospace;">
-<span style="font-family: monospace;">&nbsp;Vendor identification:
-SEAGATE</span><br style="font-family: monospace;">
-<span style="font-family: monospace;">&nbsp;Product identification:
-ST318451LW</span><br style="font-family: monospace;">
-<span style="font-family: monospace;">&nbsp;Product revision level: 0003</span><br
- style="font-family: monospace;">
-<span style="font-family: monospace;">&nbsp;Unit serial number:
-xxxxxxxxx</span><br>
-<br>
-Some SCSI devices have version descriptor information showing which
-standards (and drafts) they support:<br>
-<br>
-<span style="font-family: monospace;">$ sg_inq -d /dev/sdb</span><br
- style="font-family: monospace;">
-<span style="font-family: monospace;">standard INQUIRY:</span><br
- style="font-family: monospace;">
-<span style="font-family: monospace;">&nbsp; PQual=0&nbsp;
-Device_type=0&nbsp; RMB=0&nbsp; version=0x03&nbsp; [SPC]</span><br
- style="font-family: monospace;">
-<span style="font-family: monospace;">&nbsp; [AERC=0]&nbsp;
-[TrmTsk=0]&nbsp; NormACA=0&nbsp; HiSUP=0&nbsp; Resp_data_format=2</span><br
- style="font-family: monospace;">
-<span style="font-family: monospace;">&nbsp; SCCS=0&nbsp; ACC=0&nbsp;
-TGPS=0&nbsp; 3PC=0&nbsp; Protect=0</span><br
- style="font-family: monospace;">
-<span style="font-family: monospace;">&nbsp; BQue=0&nbsp;
-EncServ=0&nbsp; MultiP=0&nbsp; MChngr=0&nbsp; [ACKREQQ=0]&nbsp; Addr16=1</span><br
- style="font-family: monospace;">
-<span style="font-family: monospace;">&nbsp; [RelAdr=0]&nbsp;
-WBus16=1&nbsp; Sync=1&nbsp; Linked=1&nbsp; [TranDis=1]&nbsp; CmdQue=1</span><br
- style="font-family: monospace;">
-<span style="font-family: monospace;">&nbsp; Clocking=0x0&nbsp;
-QAS=0&nbsp; IUS=0</span><br style="font-family: monospace;">
-<span style="font-family: monospace;">&nbsp;&nbsp;&nbsp; length=96
-(0x60)&nbsp;&nbsp; Peripheral device type: disk</span><br
- style="font-family: monospace;">
-<span style="font-family: monospace;">&nbsp;Vendor identification:
-FUJITSU</span><br style="font-family: monospace;">
-<span style="font-family: monospace;">&nbsp;Product identification:
-MAM3184MP</span><br style="font-family: monospace;">
-<span style="font-family: monospace;">&nbsp;Product revision level: 0106</span><br
- style="font-family: monospace;">
-<span style="font-family: monospace;">&nbsp;Unit serial number:
-xxxxxxxxx</span><br style="font-family: monospace;">
-<br style="font-family: monospace;">
-<span style="font-family: monospace;">&nbsp; Version descriptors:</span><br
- style="font-family: monospace;">
-<span style="font-family: monospace;">&nbsp;&nbsp;&nbsp; SAM-2 (no
-version claimed)</span><br style="font-family: monospace;">
-<span style="font-family: monospace;">&nbsp;&nbsp;&nbsp; SPI-3
-T10/1302-D revision 10</span><br style="font-family: monospace;">
-<span style="font-family: monospace;">&nbsp;&nbsp;&nbsp; SPC ANSI
-X3.301:1997</span><br style="font-family: monospace;">
-<span style="font-family: monospace;">&nbsp;&nbsp;&nbsp; SBC T10/0996-D
-revision 08c</span><br>
-<br>
-Many modern SCSI devices also support "Vital Product Data" (VPD) pages.
-Here is a request to list available VPD pages:<br>
-<br>
-<span style="font-family: monospace;">$ sg_inq -e /dev/sg1</span><br
- style="font-family: monospace;">
-<span style="font-family: monospace;">VPD INQUIRY, page code=0x00:</span><br
- style="font-family: monospace;">
-<span style="font-family: monospace;">&nbsp;&nbsp; [PQual=0&nbsp;
-Peripheral device type: disk]</span><br style="font-family: monospace;">
-<span style="font-family: monospace;">&nbsp;&nbsp; Supported VPD pages:</span><br
- style="font-family: monospace;">
-<span style="font-family: monospace;">&nbsp;&nbsp;&nbsp;&nbsp;
-0x0&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Supported VPD pages</span><br
- style="font-family: monospace;">
-<span style="font-family: monospace;">&nbsp;&nbsp;&nbsp;&nbsp;
-0x80&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Unit serial number</span><br
- style="font-family: monospace;">
-<span style="font-family: monospace;">&nbsp;&nbsp;&nbsp;&nbsp;
-0x83&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Device identification</span><br>
-<br>
-For displaying VPD pages, sg_vpd (or sdparm) may be a better choice
-than sg_inq as sg_vpd has a simpler, less cluttered command line
-interface and additional support for vendor specific VPD pages.<br>
-<br>
-<span style="font-family: monospace;"># sg_vpd /dev/sdh</span><br
- style="font-family: monospace;">
-<span style="font-family: monospace;">Supported VPD pages VPD page:</span><br
- style="font-family: monospace;">
-<span style="font-family: monospace;">&nbsp; Supported VPD pages [sv]</span><br
- style="font-family: monospace;">
-<span style="font-family: monospace;">&nbsp; Unit serial number [sn]</span><br
- style="font-family: monospace;">
-<span style="font-family: monospace;">&nbsp; Implemented operating
-definition (obs) [iod]</span><br style="font-family: monospace;">
-<span style="font-family: monospace;">&nbsp; Device identification [di]</span><br>
-<br>
-The following displays a subset of the device identification VPD page,
-namely the designators for the target port:<br>
-<br>
-<span style="font-family: monospace;"># sg_vpd --page=di_port /dev/sdh</span><br
- style="font-family: monospace;">
-<span style="font-family: monospace;">Device Identification VPD page:</span><br
- style="font-family: monospace;">
-<span style="font-family: monospace;">&nbsp; Target port:</span><br
- style="font-family: monospace;">
-<span style="font-family: monospace;">&nbsp;&nbsp;&nbsp; desig_type:
-NAA,&nbsp; code_set: Binary</span><br style="font-family: monospace;">
-<span style="font-family: monospace;">&nbsp;&nbsp;&nbsp;&nbsp;
-transport: Serial Attached SCSI (SAS)</span><br
- style="font-family: monospace;">
-<span style="font-family: monospace;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
-0x5000c500005208ee</span><br style="font-family: monospace;">
-<span style="font-family: monospace;">&nbsp;&nbsp;&nbsp; desig_type:
-Relative target port,&nbsp; code_set: Binary</span><br
- style="font-family: monospace;">
-<span style="font-family: monospace;">&nbsp;&nbsp;&nbsp;&nbsp;
-transport: Serial Attached SCSI (SAS)</span><br
- style="font-family: monospace;">
-<span style="font-family: monospace;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
-Relative target port: 0x2</span><br>
-<br>
-The sg_scan and sg_map utilities show the relationships between linux
-sg
-devices and their &lt;bus, channel, target, lun&gt; tuples and their
-primary device node names:<br>
-<p>Example: given these 3 SCSI devices: <br>
-<tt style="font-family: monospace;">$ cat /proc/scsi/scsi</tt><span
- style="font-family: monospace;"> </span><br
- style="font-family: monospace;">
-<tt style="font-family: monospace;">Attached devices:</tt><span
- style="font-family: monospace;"> </span><br
- style="font-family: monospace;">
-<tt style="font-family: monospace;">Host: scsi1 Channel: 00 Id: 00 Lun:
-00</tt><span style="font-family: monospace;"> </span><br
- style="font-family: monospace;">
-<tt style="font-family: monospace;">&nbsp; Vendor: SEAGATE&nbsp; Model:
-ST318451LW&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Rev: 0003</tt><span
- style="font-family: monospace;"> </span><br
- style="font-family: monospace;">
-<tt style="font-family: monospace;">&nbsp; Type:&nbsp;&nbsp;
-Direct-Access&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
-ANSI SCSI revision: 03</tt><span style="font-family: monospace;"> </span><br
- style="font-family: monospace;">
-<tt style="font-family: monospace;">Host: scsi2 Channel: 00 Id: 04 Lun:
-00</tt><span style="font-family: monospace;"> </span><br
- style="font-family: monospace;">
-<tt style="font-family: monospace;">&nbsp; Vendor: PIONEER&nbsp; Model:
-DVD-ROM DVD-303&nbsp; Rev: 1.10</tt><span
- style="font-family: monospace;">
-</span><br style="font-family: monospace;">
-<tt style="font-family: monospace;">&nbsp; Type:&nbsp;&nbsp;
-CD-ROM&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
-ANSI SCSI revision: 02</tt><span style="font-family: monospace;"> </span><br
- style="font-family: monospace;">
-<tt style="font-family: monospace;">Host: scsi2 Channel: 00 Id: 06 Lun:
-00</tt><span style="font-family: monospace;"> </span><br
- style="font-family: monospace;">
-<tt style="font-family: monospace;">&nbsp; Vendor: YAMAHA&nbsp;&nbsp;
-Model:
-CRW4416S&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Rev: 1.0g</tt><span
- style="font-family: monospace;">
-</span><br style="font-family: monospace;">
-<tt style="font-family: monospace;">&nbsp; Type:&nbsp;&nbsp;
-CD-ROM&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
-ANSI SCSI revision: 02</tt> </p>
-<p>then the output from sg_scan is: <br>
-<tt style="font-family: monospace;">$ sg_scan</tt><span
- style="font-family: monospace;"> </span><br
- style="font-family: monospace;">
-<tt style="font-family: monospace;">/dev/sg0: scsi1 channel=0 id=0
-lun=0&nbsp; type=0</tt><span style="font-family: monospace;"> </span><tt
- style="font-family: monospace;"><br>
-/dev/sg1: scsi2 channel=0 id=4 lun=0&nbsp; type=5</tt><span
- style="font-family: monospace;"> </span><br
- style="font-family: monospace;">
-<tt style="font-family: monospace;">/dev/sg2: scsi2 channel=0 id=6
-lun=0&nbsp; type=5</tt> </p>
-<p>INQUIRY data can be added to that output with the '<span
- style="font-family: monospace;">-i</span>' option. The
-sg_map utility shows the mapping between scsi generic (sg) devices and
-the corresponding primary device node. For some peripheral device
-types, SCSI enclosures for example, there is no mapping and the
-enclosure device must be accessed via a sg device node.<br>
-</p>
-<p></p>
-<p style="font-family: monospace;"><code>$ sg_map <br>
-/dev/sg0&nbsp; /dev/sda <br>
-/dev/sg1&nbsp; /dev/scd0 <br>
-/dev/sg2&nbsp; /dev/scd1</code></p>
-In the lk 2.6 series of kernels sg_scan and sg_map are less important
-as most
-utilities in the sg3_utils package can be issued directly against the
-primary device node (e.g. <span style="font-family: monospace;">/dev/sda</span>).&nbsp;
-However the sg driver is
-still needed to "talk" to devices such as enclosures which have no
-specialized driver in linux.<br>
-<br>
-The Windows port has its own sg_scan utility which attempts to place
-all the device names for one device on a line. Here is an example:<br>
-<span style="font-family: monospace;">$ sg_scan</span><br
- style="font-family: monospace;">
-<span style="font-family: monospace;">SCSI0:0,0,0&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
-C:&nbsp;&nbsp;&nbsp; PD0&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
-IC25N040ATCS05-0&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; CS4O&nbsp; *</span><br
- style="font-family: monospace;">
-<span style="font-family: monospace;">SCSI1:0,0,0&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
-D:&nbsp;&nbsp;&nbsp; CDROM0&nbsp;&nbsp; HITACHI DVD-ROM GD-S200 0034</span><br
- style="font-family: monospace;">
-<span style="font-family: monospace;">SCSI2:0,0,0&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
-I: +&nbsp; PD5&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; QUANTUM
-LPS525S&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 3110</span><br
- style="font-family: monospace;">
-<span style="font-family: monospace;">SCSI2:0,6,0&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
-TAPE0&nbsp;&nbsp;&nbsp; SONY&nbsp;&nbsp;&nbsp;
-SDT-7000&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 0192</span><br
- style="font-family: monospace;">
-<span style="font-family: monospace;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
-E:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
-Generic USB SD Reader&nbsp;&nbsp; 1.00&nbsp; pdt=0</span><br
- style="font-family: monospace;">
-<span style="font-family: monospace;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
-PD1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Generic USB SD Reader&nbsp;&nbsp; 1.00</span><br>
-<br>
-The first half of each line contains the various device names for a
-device. The second half are INQUIRY reponse strings. So device names
-like "PD1" (or the longer "physicalDrive1" form), "D:" and "TAPE0" can
-be used in the Windows port. <br>
-<h2><a class="mozTocH2" name="mozTocId585558"></a> Notes</h2>
-Starting with sg3_utils-1.09 a library called libsgutils is built in
-some environments and
-is required by most utilities. The library is made up of three source
-files: <span style="font-family: monospace;">sg_lib.c</span>, <span
- style="font-family: monospace;">sg_cmds_basic.c</span> and <span
- style="font-family: monospace;">sg_cmds_extra.c</span>; and their
-associated header files . The
-<span style="font-family: monospace;">sg_lib.c</span> file contains
-tables of SCSI
-command names,
-sense key and additional sense code strings and various related helper
-functions. The <span style="font-family: monospace;">sg_cmds_basic.c</span>
-file contains low level wrapper
-functions for
-commonly used SCSI commands. The <span style="font-family: monospace;">sg_cmds_extra.c</span>
-file contains low
-level wrapper functions for
-less commonly used SCSI commands. The library can be built both as a
-shared
-object and a static library. The binary rpm package only contains the
-shared library while the sg3_utils-devel rpm package contains the
-static library, <span style="font-family: monospace;">sg_lib.h</span>,
-<span style="font-family: monospace;">sg_cmds.h</span>, <span
- style="font-family: monospace;">sg_cmds_basic.h</span>, <span
- style="font-family: monospace;">sg_cmds_extra.h</span>
-and some header files associated with the generic SCSI pass through
-interface. If users do not want libraries
-(shared or static) then they can refer to the "no_lib" subdirectory
-in the tarball which contains "no_lib" versions of the Makefile and the
-rpm "spec" file.<br>
-<br>
-In Linux many of the utilities in the sg3_utils package ultimately use
-the SG_IO ioctl
-(rather than the older write()/read() interface) in the sg driver. In
-the lk 2.6&nbsp; series the SG_IO ioctl (or at least a stripped
-down version of it) has been implemented in the block subsystem (see <a
- href="sg_io.html">sg_io.html</a> for more information). This
-means that commands which previously only worked on sg device names
-will
-now work on block device names as well (e.g. "<span
- style="font-family: monospace;">sg_inq /dev/sda</span>"). To use
-this facility safely version sg3_utils-1.02 or later should be used.
-Note that SCSI tape devices (both st and osst device drivers) are char
-devices and support the SG_IO ioctl from lk 2.6.6 onwards.<br>
-<p>See the notes about header file problems in the README file inside
-each package. </p>
-<h2><a class="mozTocH2" name="mozTocId479511"></a> Download</h2>
-Several recent versions of the sg3_utils package are listed below. The
-tarballs contain README, CHANGELOG, INSTALL
-files and man pages as well as source and build files. The build files
-include Makefiles for various architectures, a linux rpm "spec" file
-and a debian directory for building "deb" packages.&nbsp; Here is the
-most recently released sg3_utils <a href="p/sg3_utils.CHANGELOG">CHANGELOG</a>
-.<br>
-<br>
-<table border="1" width="100%">
- <caption><b>Table 2. sg3_utils tarballs and packages</b></caption> <tbody>
- <tr>
- <td><span style="font-weight: bold;">sg3_utils version</span><br>
-release date<br>
- </td>
- <td valign="top">&nbsp; <b>tarballs</b>&nbsp;<br>
- </td>
- <td><b>rpm source rpms **<br>
- </b></td>
- <td><b>i386 rpm binaries **<br>
- </b></td>
- <td valign="top">&nbsp;&nbsp; <span style="font-weight: bold;">debian
-packages</span><br>
- </td>
- </tr>
- <tr>
- <td style="vertical-align: top;"><span style="font-weight: bold;">1.20</span><br>
-20060418<br>
- </td>
- <td style="vertical-align: top;"><a href="p/sg3_utils-1.20.tgz">sg3_utils-1.20.tgz</a></td>
- <td style="vertical-align: top;"><a
- href="p/sg3_utils-1.20-1.src.rpm">sg3_utils-1.20-1.src.rpm</a></td>
- <td style="vertical-align: top;"><a
- href="p/sg3_utils-1.20-1.i386.rpm">sg3_utils-1.20-1.i386.rpm</a><br>
- <a href="p/libsgutils-1_0-1.20-1.i386.rpm">libsgutils-1_0-1.20-1.i386.rpm</a></td>
- <td style="vertical-align: top;"><a
- href="p/sg3-utils_1.20-0.1_i386.deb">sg3-utils_1.20-0.1_i386.deb</a><br>
- <a href="p/libsgutils1-0_1.20-0.1_i386.deb">libsgutils1-0_1.20-0.1_i386.deb</a></td>
- </tr>
- <tr>
- <td style="vertical-align: top;"><span style="font-weight: bold;">1.21<br>
- </span>20060706<span style="font-weight: bold;"><br>
- </span></td>
- <td style="vertical-align: top;"><a href="p/sg3_utils-1.21.tgz">sg3_utils-1.21.tgz</a></td>
- <td style="vertical-align: top;"><a
- href="p/sg3_utils-1.21-1.src.rpm">sg3_utils-1.21-1.src.rpm</a></td>
- <td style="vertical-align: top;"><a
- href="p/sg3_utils-1.21-1.i386.rpm">sg3_utils-1.21-1.i386.rpm</a><br>
- <a href="p/libsgutils-1_0-1.21-1.i386.rpm">libsgutils-1_0-1.21-1.i386.rpm</a></td>
- <td style="vertical-align: top;"><a
- href="p/sg3-utils_1.21-0.1_i386.deb">sg3-utils_1.21-0.1_i386.deb</a><br>
- <a href="p/libsgutils1-0_1.21-0.1_i386.deb">libsgutils1-0_1.21-0.1_i386.deb</a></td>
- </tr>
- <tr>
- <td><b>1.22<br>
- </b>20061016<b><br>
- </b></td>
- <td valign="top"><a href="p/sg3_utils-1.22.tgz">sg3_utils-1.22.tgz</a><br>
- </td>
- <td><a href="p/sg3_utils-1.22-1.src.rpm">sg3_utils-1.22-1.src.rpm</a></td>
- <td><a href="p/sg3_utils-1.22-1.i386.rpm">sg3_utils-1.22-1.i386.rpm</a><br>
- <a href="p/libsgutils-1_0-1.22-1.i386.rpm">libsgutils-1_0-1.22-1.i386.rpm</a><br>
- </td>
- <td valign="top"><a href="p/sg3-utils_1.22-0.1_i386.deb">sg3-utils_1.22-0.1_i386.deb</a><br>
- <a href="p/libsgutils1-0_1.22-0.1_i386.deb">libsgutils1-0_1.22-0.1_i386.deb</a><br>
- </td>
- </tr>
- <tr>
- <td style="vertical-align: top;"><span style="font-weight: bold;">1.23</span><br>
-20070127<br>
- <b> </b></td>
- <td style="vertical-align: top;"><a href="p/sg3_utils-1.23.tgz">sg3_utils-1.23.tgz</a></td>
- <td style="vertical-align: top;"><a
- href="p/sg3_utils-1.23-1.src.rpm">sg3_utils-1.23-1.src.rpm</a></td>
- <td style="vertical-align: top;"><a
- href="p/sg3_utils-1.23-1.i386.rpm">sg3_utils-1.23-1.i386.rpm</a><br>
- <a href="p/sg3_utils-libs-1.23-1.i386.rpm">sg3_utils-libs-1.23-1.i386.rpm</a><br>
- </td>
- <td style="vertical-align: top;"><a
- href="p/sg3-utils_1.23-0.1_i386.deb">sg3-utils_1.23-0.1_i386.deb</a><br>
- <a href="p/libsgutils1-0_1.23-0.1_i386.deb">libsgutils1-0_1.23-0.1_i386.deb</a></td>
- </tr>
- </tbody>
-</table>
-<br>
-This <a href="p/sg3_utils_exe.zip">sg3_utils_exe.zip</a> file is a zip
-archive of the most recent version Windows executables made in a MinGW
-environment. This <a href="p/sg3_utils_man_html.tgz">sg3_utils_man_html.tgz</a>
-file is a tarball of man pages converted to html by man2html.<br>
-<br>
-Version 1.14 of sg3_utils introduced a shared object (library) called
-libsgutils. When binary packages are built then libsgutils is in its
-own package (and there is another "libsgutils*-devel" package which
-contains C header files and a static libsgutils.o library). The
-sg3_utils binaries for version 1.14 to 1.23 normally require the
-libsgutils library but can be built without it. In the future
-other utilities such as <a href="sdparm.html">sdparm</a> may also
-depend on the libsgutils
-package.<br>
-<br>
-** Some browsers (e.g. firefox) may interpret a file with an extension
-of "rpm" as an audio file. In which case press the right button over
-the link and select "Save link as ..." to download the file.<br>
-<br>
-Below is the most recent version of the sg_utils package which targets
-the linux kernel 2.2 series with some support for the lk 2.0 series. No
-further work is being done on this package.<br>
-<table border="1" width="100%">
- <caption><b>Table 3.&nbsp; sg_utils tarballs and packages</b></caption>
- <tbody>
- <tr>
- <td><span style="font-weight: bold;">sg_utils</span><br
- style="font-weight: bold;">
- <span style="font-weight: bold;">version</span><br>
- </td>
- <td valign="top">&nbsp; <b>tarballs</b>&nbsp;<br>
- </td>
- <td><b>rpm source rpms **<br>
- </b></td>
- <td><b>i386 rpm binaries **<br>
- </b></td>
- </tr>
- <tr>
- <td style="vertical-align: top;"><b>1.02</b></td>
- <td style="vertical-align: top;"><a href="p/sg_utils-1.02.tgz">sg_utils-1.02.tgz</a></td>
- <td style="vertical-align: top;"><a
- href="p/sg_utils-1.02-1.src.rpm">sg_utils-1.02-1.src.rpm</a></td>
- <td style="vertical-align: top;"><a
- href="p/sg_utils-1.02-1.i386.rpm">sg_utils-1.02-1.i386.rpm</a></td>
- </tr>
- </tbody>
-</table>
-<br>
-There is no '<span style="font-family: monospace;">./configure</span>'
-logic in sg3_utils so the correct Makefile must be chosen taking into
-account the
-operating system and several other attributes.<br>
-<br>
-<table style="width: 100%; text-align: left;" border="1" cellpadding="2"
- cellspacing="2">
- <caption><span style="font-weight: bold;">Table 4.&nbsp;
-Building from a source tarball</span><br>
- </caption><tbody>
- <tr>
- <td style="vertical-align: top;"><span style="font-weight: bold;">OS</span><br>
- </td>
- <td style="vertical-align: top;"><span style="font-weight: bold;">build
-to use shared library</span><br>
- </td>
- <td style="vertical-align: top;"><span style="font-weight: bold;">build
-without library</span><br>
- </td>
- <td style="vertical-align: top;"><span style="font-weight: bold;">build
-static executables</span><br>
- </td>
- <td style="vertical-align: top;"><span style="font-weight: bold;">Notes</span><br>
- </td>
- </tr>
- <tr>
- <td style="vertical-align: top;"><span style="font-weight: bold;">Linux</span><br>
- </td>
- <td style="vertical-align: top;">make<br>
- </td>
- <td style="vertical-align: top;">./make_no_lib.sh<br>
- </td>
- <td style="vertical-align: top;">./make_no_lib_static.sh<br>
- </td>
- <td style="vertical-align: top;">rpm spec file and debian
-subdirectory included<br>
- </td>
- </tr>
- <tr>
- <td style="vertical-align: top;"><span style="font-weight: bold;">FreeBSD</span><br>
- </td>
- <td style="vertical-align: top;">make -f Makefile.freebsd<br>
- </td>
- <td style="vertical-align: top;">./make_no_lib_freebsd.sh<br>
- </td>
- <td style="vertical-align: top;">&nbsp;<br>
- </td>
- <td style="vertical-align: top;">&nbsp;<br>
- </td>
- </tr>
- <tr>
- <td style="vertical-align: top;"><span style="font-weight: bold;">Tru64
-(OSF1)</span><br>
- </td>
- <td style="vertical-align: top;">make -f Makefile.osf1<br>
- </td>
- <td style="vertical-align: top;">./make_no_lib_osf1.sh<br>
- </td>
- <td style="vertical-align: top;">&nbsp;<br>
- </td>
- <td style="vertical-align: top;">&nbsp;<br>
- </td>
- </tr>
- <tr>
- <td style="vertical-align: top;"><span style="font-weight: bold;">Windows</span><br>
- </td>
- <td style="vertical-align: top;"><br>
- </td>
- <td style="vertical-align: top;">make -f Makefile.win32<br>
- </td>
- <td style="vertical-align: top;">&nbsp;<br>
- </td>
- <td style="vertical-align: top;">Windows NT and later supported
-(uses SPT interface). Builds in a cygwin environment and requires
-cygwin1.dll to run.<br>
- </td>
- </tr>
- <tr>
- <td style="vertical-align: top;"><span style="font-weight: bold;">Windows</span><br>
- </td>
- <td style="vertical-align: top;"><br>
- </td>
- <td style="vertical-align: top;">make -f Makefile.mingw<br>
- </td>
- <td style="vertical-align: top;"><br>
- </td>
- <td style="vertical-align: top;">Builds in a MinGW/MSYS
-environment and requires no third party dll<br>
- </td>
- </tr>
- </tbody>
-</table>
-<br>
-<br>
-Both sg3_utils and the
-older sg_utils packages can
-be found on <a href="http://freshmeat.net">http://freshmeat.net</a> .
-Most of the above invocations can
-take the name of a specific utility (e.g. "<span
- style="font-family: monospace;">make sg_inq</span>") to build only
-that utility. There are also
-"install", "uninstall" and "clean" targets in most Makefiles.<br>
-<br>
-<p>Return to <a href="index.html">main</a> page. </p>
-<center>
-<p>Last updated: 31st January 2007<br>
-<br>
-</p>
-</center>
-</body>
-</html>
diff --git a/doc/sg_dd.html b/doc/sg_dd.html
deleted file mode 100644
index 0250541e..00000000
--- a/doc/sg_dd.html
+++ /dev/null
@@ -1,1175 +0,0 @@
-<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
-<html>
-<head>
- <title>Linux sg_dd utility (a dd variant)</title>
- <meta http-equiv="Content-Type"
- content="text/html; charset=iso-8859-1">
- <meta name="keywords" content="Linux, SCSI, sg_dd, dd variant">
- <meta name="GENERATOR"
- content="Mozilla/4.79 [en] (X11; U; Linux 2.5.31 i686) [Netscape]">
-</head>
-<body alink="#ff0000" background="paper.jpg" bgcolor="#ffffff"
- link="#0000ff" text="#000000" vlink="#000080">
-<center>
-<h1><a class="mozTocH1" name="mozTocId228087"></a> The&nbsp; Linux
-sg_dd utility<br>
-</h1>
-</center>
-<a href="#Conclusion"></a>
-<ol id="mozToc">
-<!--mozToc h1 1 h2 2 h3 3 h4 4 h5 5 h6 6-->
- <li><a href="#mozTocId228087"> The&nbsp; Linux
-sg_dd utility
- </a>
- <ol>
- <li><a href="#mozTocId370866">Introduction</a></li>
- <li><a href="#mozTocId352668">dd like features</a></li>
- <li><a href="#mozTocId703997">sg_dd extras</a></li>
- <li><a href="#mozTocId657084">Retries</a></li>
- <li><a href="#mozTocId437677">Continue on error
-(coe)</a></li>
- <li><a href="#mozTocId566094">Recovered errors</a></li>
- <li><a href="#mozTocId899152">Verbose</a></li>
- <li><a href="#mozTocId443896">sgp_dd, sgm_dd and
-sg_read</a></li>
- <li><a href="#mozTocId157981">Conclusion</a></li>
- </ol>
- </li>
-</ol>
-<h2><a class="mozTocH2" name="mozTocId370866"></a>Introduction</h2>
-The <span style="font-weight: bold;">sg_dd</span> utility is a variant
-of the standard Unix command <span style="font-weight: bold;">dd</span>
-which
-copies files. The sg_dd utility is specialized for devices that use the
-SCSI command set in the Linux operating system. The sg_dd utility is
-found in the <a href="sg3_utils.html">sg3_utils</a> package which
-targets the linux kernel 2.4 and
-2.6 series and has ports to various other operating systems.<br>
-<br>
-Only block oriented SCSI peripheral device types are supported by the
-sg_dd utility. Obviously
-those device types that deal with enclosures and medium changers don't
-have addressable blocks and are not supported. The supported device
-types are direct access devices (e.g. disks) and cd/dvd devices. The
-SCSI tape device type is not be supported (but could be to a limited
-degree). When instructed, the sg_dd utility issues SCSI
-commands that are defined in SPC-3 (primary commands), SBC-2 (commands
-for direct access devices (e.g. disks)) and MMC-4 (commands for CD/DVD
-devices). These SCSI command sets can be found at <a
- href="http://www.t10.org/">www.t10.org</a>
-. <br>
-<br>
-It is becoming common for non-SCSI devices (e.g. ATA disks) to appear
-as SCSI devices to an operating system via a protocol conversion in an
-external enclosure and via some transport such as USB or IEEE 1394. The
-sg_dd utility should work with most of these devices as it tends to use
-exactly the same SCSI commands that the normal block layer would use.
-However, advanced options (e.g. using the cdbsz=16 and iflag=fua) most
-likely will be ignored. Apart from CD players over 10 years old, almost
-all CD/DVD players use the Multi Media Command set (MMC or&nbsp;
-MMC-2,3,4,5) as their native command set. The fact that the most common
-transport for CD/DVD drives is ATAPI (i.e. the ATA packet interface) is
-irrelevant to
-the
-sg_dd utility; they use SCSI command sets.<br>
-<br>
-This page outlines the features of the sg_dd utility version 5.60 found
-in the <a href="sg3_utils.html">sg3_utils</a> version 1.23 package.<br>
-<h2><a class="mozTocH2" name="mozTocId352668"></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
-almost all other standard Unix commands. Those familiar with the dd
-command
-should not be too surprised by the syntax and semantics of the sg_dd
-utility. Those not familiar with the dd syntax should be very careful,
-especially with the 'of=' and 'seek=' options, both with dd and sg_dd.
-The recent GNU implementation of the dd command is used as a reference
-point.<br>
-<br>
-The main options of dd are:<br>
-<br>
-<table style="width: 100%; text-align: left;" border="1" cellpadding="2"
- cellspacing="2">
- <tbody>
- <tr>
- <td style="vertical-align: top;"><span style="font-weight: bold;">Standard
-dd options</span><br>
- </td>
- <td style="vertical-align: top;"><span style="font-weight: bold;">Default</span><br>
- </td>
- <td style="vertical-align: top;"><span style="font-weight: bold;">Brief
-description</span><br>
- </td>
- </tr>
- <tr>
- <td style="vertical-align: top;">bs=<span
- style="font-style: italic;">BS</span><br>
- </td>
- <td style="vertical-align: top;">512<br>
- </td>
- <td style="vertical-align: top;">Number of bytes in each block.<br>
- </td>
- </tr>
- <tr>
- <td style="vertical-align: top;">count=<span
- style="font-style: italic;">COUNT</span></td>
- <td style="vertical-align: top;">blocks in <span
- style="font-style: italic;">IFILE</span><br>
- </td>
- <td style="vertical-align: top;">Number of blocks to copy.<br>
- </td>
- </tr>
- <tr>
- <td style="vertical-align: top;">if=<span
- style="font-style: italic;">IFILE</span></td>
- <td style="vertical-align: top;">stdin<br>
- </td>
- <td style="vertical-align: top;">file (or device) to read from.<br>
- </td>
- </tr>
- <tr>
- <td style="vertical-align: top;">of=<span
- style="font-style: italic;">OFILE</span></td>
- <td style="vertical-align: top;">stdout<br>
- </td>
- <td style="vertical-align: top;">file (or device) to write to.
-sg_dd doesn't bother writing anything if <span
- style="font-style: italic;">OFILE</span> is <span
- style="font-family: monospace;">/dev/null</span> or
-. (period).<br>
- </td>
- </tr>
- </tbody>
-</table>
-<br>
-<br>
-When either dd or sg_dd are given these options with suitable
-arguments, they will copy
-(<span style="font-style: italic;">BS</span> * <span
- style="font-style: italic;">COUNT</span>) bytes from the beginning
-of <span style="font-style: italic;">IFILE</span> to the
-beginning of <span style="font-style: italic;">OFILE</span>. One
-restriction that sg_dd imposes
-when either the <span style="font-style: italic;">IFILE</span> or <span
- style="font-style: italic;">OFILE</span> are accessed
-via SCSI commands is that <span style="font-style: italic;">BS</span>
-(i.e. the block size) must match that of the
-device. Further, if both the <span style="font-style: italic;">IFILE</span>
-and <span style="font-style: italic;">OFILE</span>
-are accessed via SCSI commands then <span style="font-style: italic;">BS</span>
-must match that
-of both devices. <br>
-<br>
-The following extensions are found in sg_dd. An <span
- style="font-style: italic;">IFILE</span> of
-"-" is interpreted as stdin; an <span style="font-style: italic;">OFILE</span>
-of "-" is
-interpreted as stdout while an <span style="font-style: italic;">OFILE</span>
-of "." is
-interpreted as <span style="font-family: monospace;">/dev/null</span>.
-[dd interprets input and output file names of
-"-" literally; dd interprets an output file of "." as the current
-directory and will not accept it.] The sg_dd utility does not truncate
-the <span style="font-style: italic;">OFILE</span> before starting the
-copy (the dd command does
-if it is a normal file). Hence a user may need to delete the output
-file before using the sg_dd utility (if the size of that file is
-greater than what sg_dd is going to copy over it).<br>
-<br>
-If the 'count=' option is not given then an attempt is made to
-determine
-the remaining blocks in the file, device or partition. If the input
-file is stdin and no count is given then a copy will continue until an
-EOF is detected on the input stream (or something else goes wrong). If
-the 'count' option is not given then the remaining blocks on both the
-input and output files are determined (if possible) and if both are
-found then the minimum of
-the two counts is used.&nbsp; The 'skip' option for an input file and
-the 'seek' option for an output file are taken into account when
-calculating the remaining number of blocks in a file, device or
-partition.<br>
-<br>
-If the 'count' option is given then no further checks regarding the
-remaining length of the input and output files are done and the sg_dd
-will attempt to copy that number of blocks. A 'count=0' option is valid
-and all the normal preparations are made including files being opened
-but no copy takes place. Hence the 'count=0' option can be used to
-check that the syntax is in order and that the files are present (see
-the
-"<a href="#mozTocId899152">Verbose</a>" section below).<br>
-<br>
-Other dd options supported by sg_dd:<br>
-<br>
-<table style="width: 100%; text-align: left;" border="1" cellpadding="2"
- cellspacing="2">
- <tbody>
- <tr>
- <td style="vertical-align: top;"><span style="font-weight: bold;">Standard
-dd options</span><br>
- </td>
- <td style="vertical-align: top;"><span style="font-weight: bold;">Default</span><br>
- </td>
- <td style="vertical-align: top;"><span style="font-weight: bold;">Brief
-description</span><br>
- </td>
- </tr>
- <tr>
- <td style="vertical-align: top;">ibs=<span
- style="font-style: italic;">BS</span></td>
- <td style="vertical-align: top;">same as bs=<span
- style="font-style: italic;">BS</span><br>
- </td>
- <td style="vertical-align: top;">number of bytes in each block of
- <span style="font-style: italic;">IFILE</span><br>
- </td>
- </tr>
- <tr>
- <td style="vertical-align: top;">iflag=<span
- style="font-style: italic;">FLAGS</span><br>
- </td>
- <td style="vertical-align: top;"><br>
- </td>
- <td style="vertical-align: top;">similar
-to option found in recent GNU dd versions, see below<br>
- </td>
- </tr>
- <tr>
- <td style="vertical-align: top;">obs=<span
- style="font-style: italic;">BS</span></td>
- <td style="vertical-align: top;">same as bs=<span
- style="font-style: italic;">BS</span><br>
- </td>
- <td style="vertical-align: top;">number of bytes in each block of
- <span style="font-style: italic;">OFILE</span></td>
- </tr>
- <tr>
- <td style="vertical-align: top;">oflag=<span
- style="font-style: italic;">FLAGS</span><br>
- </td>
- <td style="vertical-align: top;"><br>
- </td>
- <td style="vertical-align: top;">similar
-to option found in recent GNU dd versions, see below<br>
- </td>
- </tr>
- <tr>
- <td style="vertical-align: top;">seek=<span
- style="font-style: italic;">SEEK</span></td>
- <td style="vertical-align: top;">0<br>
- </td>
- <td style="vertical-align: top;">block number (origin 0) in <span
- style="font-style: italic;">OFILE</span> to commence writing<br>
- </td>
- </tr>
- <tr>
- <td style="vertical-align: top;">skip=<span
- style="font-style: italic;">SKIP</span></td>
- <td style="vertical-align: top;">0<br>
- </td>
- <td style="vertical-align: top;">block number (origin 0) in <span
- style="font-style: italic;">IFILE</span> to commence reading</td>
- </tr>
- <tr>
- <td style="vertical-align: top;">--help<br>
- </td>
- <td style="vertical-align: top;"><br>
- </td>
- <td style="vertical-align: top;">print usage message then exit<br>
- </td>
- </tr>
- <tr>
- <td style="vertical-align: top;">--version<br>
- </td>
- <td style="vertical-align: top;"><br>
- </td>
- <td style="vertical-align: top;">print version number and its
-date then exit<br>
- </td>
- </tr>
- </tbody>
-</table>
-<br>
-If either ibs= and/or obs= are given to sg_dd then they must have the
-same value
-as bs=
-(i.e. they are essentially dummies).&nbsp; The skip= option cannot be
-used on an input stream
-(e.g. stdin) while the seek= option cannot be used on an output stream
-(e.g. stdout).<br>
-<br>
-All numeric arguments can take a multiplier suffix. From sg3_utils
-version 1.13 sg_dd's multiplier prefixes have been brought into line
-with those of GNU's dd. GNU's dd is found in coreutils and its
-changelog notes the change to this suffix pattern on&nbsp; 2001-12-18:<br>
-<br>
-<table style="width: 50%; text-align: left;" border="1" cellpadding="2"
- cellspacing="2">
- <tbody>
- <tr>
- <td style="vertical-align: top;"><span style="font-weight: bold;">Multiplier</span><br>
- </td>
- <td style="vertical-align: top;"><span style="font-weight: bold;">Meaning</span><br>
- </td>
- </tr>
- <tr>
- <td style="vertical-align: top;">x&lt;n&gt;<br>
- </td>
- <td style="vertical-align: top;">*&lt;n&gt;<br>
- </td>
- </tr>
- <tr>
- <td style="vertical-align: top;">c<br>
- </td>
- <td style="vertical-align: top;">*1<br>
- </td>
- </tr>
- <tr>
- <td style="vertical-align: top;">w<br>
- </td>
- <td style="vertical-align: top;">*2<br>
- </td>
- </tr>
- <tr>
- <td style="vertical-align: top;">b<br>
- </td>
- <td style="vertical-align: top;">*512<br>
- </td>
- </tr>
- <tr>
- <td style="vertical-align: top;">k&nbsp; K&nbsp; KiB<br>
- </td>
- <td style="vertical-align: top;">*1024<br>
- </td>
- </tr>
- <tr>
- <td style="vertical-align: top;">KB<br>
- </td>
- <td style="vertical-align: top;">*1000<br>
- </td>
- </tr>
- <tr>
- <td style="vertical-align: top;">m&nbsp; M&nbsp; MiB<br>
- </td>
- <td style="vertical-align: top;">*1048576 </td>
- </tr>
- <tr>
- <td style="vertical-align: top;">MB<br>
- </td>
- <td style="vertical-align: top;">*1000000<br>
- </td>
- </tr>
- <tr>
- <td style="vertical-align: top;">g&nbsp; G&nbsp; GiB<br>
- </td>
- <td style="vertical-align: top;">2**30<br>
- </td>
- </tr>
- <tr>
- <td style="vertical-align: top;">GB<br>
- </td>
- <td style="vertical-align: top;">10**9<br>
- </td>
- </tr>
- <tr>
- <td style="vertical-align: top;">t&nbsp; T&nbsp; TiB<br>
- </td>
- <td style="vertical-align: top;">2**40 </td>
- </tr>
- <tr>
- <td style="vertical-align: top;">TB<br>
- </td>
- <td style="vertical-align: top;">10**12<br>
- </td>
- </tr>
- </tbody>
-</table>
-<br>
-The pattern that starts with "k" and proceeds to "m", "g" and "t" then
-to "p", "e", "z" and "y"&nbsp; (not shown in above table). sg_dd only
-implements as far as "p" (10**15 or 2**50). sg_dd only allows
-multipliers based on "t" and "p" for 'count', 'skip' and 'seek'.<br>
-<br>
-sg_dd allows numeric arguments to be given in hexadecimal in which case
-they must be prefixed by either "0x" or "0X". A numeric argument cannot
-both be in hex and have a suffix multiplier. Hence "0x9" is interpreted
-as hexadecimal 9 [not (0 * 9)==0]. This is valid "2x4x0xa" and yields
-80 (but it isn't very clear).<br>
-<br>
-From sg3_utils version 1.19 (sg_dd version 5.46) hexadecimal numbers
-can also be indicated by a trailing "h" or "H". The "h" suffix cannot
-be used together with a suffix multiplier.<br>
-<br>
-The <span style="font-style: italic;">FLAGS</span> argument of
-"iflag=" and "oflag=" is a comma
-separated list of items chosen from one or more entries in this table:<br>
-<br>
-<table style="width: 100%; text-align: left;" border="1" cellpadding="2"
- cellspacing="2">
- <tbody>
- <tr>
- <td style="vertical-align: top;"><span style="font-weight: bold;">flag</span><br>
- </td>
- <td style="vertical-align: top;"><span style="font-weight: bold;">sg
-device</span><br>
- </td>
- <td style="vertical-align: top;"><span style="font-weight: bold;">block
-device</span><br>
- </td>
- <td style="vertical-align: top;"><span style="font-weight: bold;">regular
-file</span><br>
- </td>
- <td style="vertical-align: top;"><span style="font-weight: bold;">comments</span><br>
- </td>
- </tr>
- <tr>
- <td style="vertical-align: top;">append<br>
- </td>
- <td style="vertical-align: top;">ignored<br>
- </td>
- <td style="vertical-align: top;">applied on <span
- style="font-style: italic;">OFILE</span><br>
- </td>
- <td style="vertical-align: top;">applied on <span
- style="font-style: italic;">OFILE</span><br>
- </td>
- <td style="vertical-align: top;">use O_APPEND open flag.
-Conflicts with 'seek=<span style="font-style: italic;">SEEK</span>'
-when "<span style="font-style: italic;">SEEK</span> &gt; 0"<br>
- </td>
- </tr>
- <tr>
- <td style="vertical-align: top;">coe<br>
- </td>
- <td style="vertical-align: top;">applied<br>
- </td>
- <td style="vertical-align: top;">applied if using SG_IO ioctl</td>
- <td style="vertical-align: top;">ignored<br>
- </td>
- <td style="vertical-align: top;">continue on error; best effort
-recovery then continue. N.B. can be used multiple times (e.g.
-'iflag=coe,coe')<br>
- </td>
- </tr>
- <tr>
- <td style="vertical-align: top;">direct<br>
- </td>
- <td style="vertical-align: top;">applied<br>
- </td>
- <td style="vertical-align: top;">applied<br>
- </td>
- <td style="vertical-align: top;">applied<br>
- </td>
- <td style="vertical-align: top;">use O_DIRECT open flag, no
-effect with sg devices<br>
- </td>
- </tr>
- <tr>
- <td style="vertical-align: top;">dpo<br>
- </td>
- <td style="vertical-align: top;">applied<br>
- </td>
- <td style="vertical-align: top;">applied if using SG_IO ioctl</td>
- <td style="vertical-align: top;">ignored</td>
- <td style="vertical-align: top;">"disable page out" set for READ
-and/or WRITE SCSI commands</td>
- </tr>
- <tr>
- <td style="vertical-align: top;">dsync<br>
- </td>
- <td style="vertical-align: top;">applied<br>
- </td>
- <td style="vertical-align: top;">applied<br>
- </td>
- <td style="vertical-align: top;">applied<br>
- </td>
- <td style="vertical-align: top;">use O_SYNC open flag, no effect
-with sg devices<br>
- </td>
- </tr>
- <tr>
- <td style="vertical-align: top;">excl<br>
- </td>
- <td style="vertical-align: top;">applied<br>
- </td>
- <td style="vertical-align: top;">applied<br>
- </td>
- <td style="vertical-align: top;">applied<br>
- </td>
- <td style="vertical-align: top;">Use O_EXCL open flag<br>
- </td>
- </tr>
- <tr>
- <td style="vertical-align: top;">fua<br>
- </td>
- <td style="vertical-align: top;">applied<br>
- </td>
- <td style="vertical-align: top;">applied if using SG_IO ioctl<br>
- </td>
- <td style="vertical-align: top;">ignored<br>
- </td>
- <td style="vertical-align: top;">"force unit access" set for READ
-and/or WRITE SCSI commands<br>
- </td>
- </tr>
- <tr>
- <td style="vertical-align: top;">sgio<br>
- </td>
- <td style="vertical-align: top;">ignored<br>
- </td>
- <td style="vertical-align: top;">use SG_IO ioctl<br>
- </td>
- <td style="vertical-align: top;">ignored<br>
- </td>
- <td style="vertical-align: top;">access block device via SG_IO
-ioctl (only supported in lk 2.6 series)<br>
- </td>
- </tr>
- </tbody>
-</table>
-<br>
-Recent versions of GNU's dd command have these flags with similar
-semantics:&nbsp; 'append', 'direct' and 'sync' (which is called 'dsync'
-in sg_dd). So 'coe', 'dpo', 'excl', 'fua' and 'sgio' are sg_dd
-extensions.<br>
-<br>
-The following dd options are <span style="font-weight: bold;">not</span>
-supported by sg_dd:<br>
-<ul>
- <li>cbs=&lt;bytes&gt;</li>
- <li>conv=&lt;keyword&gt;</li>
-</ul>
-Basically sg_dd does not supported the conversion features of dd. If a
-conversion is really needed then sg_dd could be piped through dd (or
-vice versa).<br>
-<h2><a class="mozTocH2" name="mozTocId703997"></a>sg_dd extras</h2>
-The extra options of sg_dd (not found in GNU's dd) are:<br>
-<br>
-<ul>
-</ul>
-<table style="width: 100%; text-align: left;" border="1" cellpadding="2"
- cellspacing="2">
- <tbody>
- <tr>
- <td style="vertical-align: top;"><span style="font-weight: bold;">extra
-options in sg_dd</span><br>
- </td>
- <td style="vertical-align: top;"><span style="font-weight: bold;">default</span><br>
- </td>
- <td style="vertical-align: top;"><span style="font-weight: bold;">sgm_dd
- </span>and<span style="font-weight: bold;"> sgp_dd</span><br>
- </td>
- <td style="vertical-align: top;"><span style="font-weight: bold;">Brief
-description</span><br>
- </td>
- </tr>
- <tr>
- <td style="vertical-align: top;">blk_sgio=0 | 1<br>
- </td>
- <td style="vertical-align: top;">0<br>
- </td>
- <td style="vertical-align: top;"><br>
- </td>
- <td style="vertical-align: top;">when set access devices via SCSI
-commands (SG_IO ioctl). May use iflag=sgio and/or oflag=sgio
-instead.<br>
- </td>
- </tr>
- <tr>
- <td style="vertical-align: top;">bpt=<span
- style="font-style: italic;">BPT</span><br>
- </td>
- <td style="vertical-align: top;">128 or 32<br>
- </td>
- <td style="vertical-align: top;">both<br>
- </td>
- <td style="vertical-align: top;">where <span
- style="font-style: italic;">BPT</span> is the blocks per transfer
-(granularity
-of each IO). Default is 128 when <span style="font-style: italic;">BS</span>
-&lt; 2048 (bytes) else the default
-is 32. For block devices (<span style="font-style: italic;">BPT</span>
-* <span style="font-style: italic;">BS</span>) is constrained by <span
- style="font-family: monospace;">/sys/block/&lt;device&gt;/queue/max_sectors_kb</span>
-.<br>
- </td>
- </tr>
- <tr>
- <td style="vertical-align: top;">cdbsz=6 | 10 | 12 | 16<br>
- </td>
- <td style="vertical-align: top;">10 or 16<br>
- </td>
- <td style="vertical-align: top;">both<br>
- </td>
- <td style="vertical-align: top;">cdb size of SCSI READ and/or
-WRITE commands. Only applicable to sg devices or when the SG_IO ioctl
-is being used (e.g. when blk_sgio=1). Defaults to 10 byte cdb unless
-the largest address exceeds 32 bits or bpt exceeds 16 bits. In either
-case a 16 cdb is used.<br>
- </td>
- </tr>
- <tr>
- <td style="vertical-align: top;">coe=0 | 1 | 2 | 3<br>
- </td>
- <td style="vertical-align: top;">0<br>
- </td>
- <td style="vertical-align: top;">sgp_dd<br>
- </td>
- <td style="vertical-align: top;">when non-zero, continue_on_error
-for
-sg devices and block devices using the SG_IO ioctl. May use iflag=coe
-and/or oflag=coe
-instead. An equivalent of coe=2 is 'iflag=coe,coe'<br>
- </td>
- </tr>
- <tr>
- <td style="vertical-align: top;">coe_limit=<span
- style="font-style: italic;">CL</span><br>
- </td>
- <td style="vertical-align: top;">0<br>
- </td>
- <td style="vertical-align: top;">&nbsp;<br>
- </td>
- <td style="vertical-align: top;">number of consecutive "bad"
-block errors allowed when reading and 'coe &gt; 0'. Default of 0 is
-interpreted as no limit.<br>
- </td>
- </tr>
- <tr>
- <td style="vertical-align: top;">dio=0 | 1<br>
- </td>
- <td style="vertical-align: top;">0<br>
- </td>
- <td style="vertical-align: top;">both<br>
- </td>
- <td style="vertical-align: top;">direct IO (only via sg device
-nodes)<br>
- </td>
- </tr>
- <tr>
- <td style="vertical-align: top;">odir=0 | 1<br>
- </td>
- <td style="vertical-align: top;">0<br>
- </td>
- <td style="vertical-align: top;"><br>
- </td>
- <td style="vertical-align: top;">O_DIRECT flag on open() when
-set. Better to use iflag=direct and/or oflag=direct. </td>
- </tr>
- <tr>
- <td style="vertical-align: top;">retries=<span
- style="font-style: italic;">RETR</span><br>
- </td>
- <td style="vertical-align: top;">0<br>
- </td>
- <td style="vertical-align: top;"><br>
- </td>
- <td style="vertical-align: top;">number of times to retry an
-error on a sg device READ or WRITE command<br>
- </td>
- </tr>
- <tr>
- <td style="vertical-align: top;">sync=0 | 1<br>
- </td>
- <td style="vertical-align: top;">0<br>
- </td>
- <td style="vertical-align: top;">both<br>
- </td>
- <td style="vertical-align: top;">when set, sends SYNCHRONIZE
-CACHE SCSI command to <span style="font-style: italic;">OFILE</span>
-if it is a sg device or accessed
-via the SG_IO ioctl.<br>
- </td>
- </tr>
- <tr>
- <td style="vertical-align: top;">time=0 | 1<br>
- </td>
- <td style="vertical-align: top;">0<br>
- </td>
- <td style="vertical-align: top;">both<br>
- </td>
- <td style="vertical-align: top;">when set print elapsed time and
-throughput calculation at the completion of the copy<br>
- </td>
- </tr>
- <tr>
- <td style="vertical-align: top;">verbose=<span
- style="font-style: italic;">VERB</span><br>
- </td>
- <td style="vertical-align: top;">0<br>
- </td>
- <td style="vertical-align: top;">sgm_dd<br>
- </td>
- <td style="vertical-align: top;">larger <span
- style="font-style: italic;">VERB</span> is the greater
-the debug output. 1 and 2 print the cdbs for setup commands; 3 and 4
-print the cdbs for all commands<br>
- </td>
- </tr>
- </tbody>
-</table>
-<br>
-<br>
-The sg_dd utility examines the files it is given and treats them
-differently depending on their file type. Depending on iflag=<span
- style="font-style: italic;">FLAGS</span> and oflag=<span
- style="font-style: italic;">FLAGS</span> settings: O_DIRECT,
-O_SYNC, O_APPEND and O_EXCL flags may be added to the relevant open()
-command.<br>
-<br>
-<table style="width: 100%; text-align: left;" border="1" cellpadding="2"
- cellspacing="2">
- <tbody>
- <tr>
- <td style="vertical-align: top;"><span style="font-weight: bold;">File
-type</span><br>
- </td>
- <td style="vertical-align: top;"><span style="font-weight: bold;">open
-[when input]</span><br>
- </td>
- <td style="vertical-align: top;"><span style="font-weight: bold;">open
-[when output]</span><br>
- </td>
- <td style="vertical-align: top;"><span style="font-weight: bold;">IO
-method</span><br>
- </td>
- <td style="vertical-align: top;"><span style="font-weight: bold;">Notes</span><br>
- </td>
- </tr>
- <tr>
- <td style="vertical-align: top;">normal<br>
- </td>
- <td style="vertical-align: top;">O_RDONLY<br>
- <br>
- </td>
- <td style="vertical-align: top;">O_WRONLY | O_CREAT<br>
- </td>
- <td style="vertical-align: top;">Unix read() write()<br>
- </td>
- <td style="vertical-align: top;">N.B. A normal output file is
-overwritten (not truncated).<br>
- </td>
- </tr>
- <tr>
- <td style="vertical-align: top;">stdin or stdout<br>
- </td>
- <td style="vertical-align: top;">[do nothing]<br>
- </td>
- <td style="vertical-align: top;">[do nothing]<br>
- </td>
- <td style="vertical-align: top;">Unix read() write()<br>
- </td>
- <td style="vertical-align: top;">hence open() flags have no
-effect (e.g. 'oflag=direct' is ignored)<br>
- </td>
- </tr>
- <tr>
- <td style="vertical-align: top;"><span
- style="font-family: monospace;">/dev/null</span> or . (period)<br>
- </td>
- <td style="vertical-align: top;">O_RDONLY</td>
- <td style="vertical-align: top;">[do nothing]<br>
- </td>
- <td style="vertical-align: top;">Unix read() if input<br>
- </td>
- <td style="vertical-align: top;">if output file then nothing is
-written<br>
- </td>
- </tr>
- <tr>
- <td style="vertical-align: top;">block device<br>
- </td>
- <td style="vertical-align: top;">O_RDONLY</td>
- <td style="vertical-align: top;">O_WRONLY | O_CREAT<br>
- </td>
- <td style="vertical-align: top;">Unix read() write()</td>
- <td style="vertical-align: top;"><br>
- </td>
- </tr>
- <tr>
- <td style="vertical-align: top;">block device [sgio flag given]<br>
- </td>
- <td style="vertical-align: top;">O_RDWR or O_RDONLY</td>
- <td style="vertical-align: top;">O_RDWR</td>
- <td style="vertical-align: top;">SCSI commands</td>
- <td style="vertical-align: top;">Opens input O_RDONLY if O_RDWR
-fails.&nbsp; The blk_sgio=1 option equates to both iflag=sgio and
-oflag=sgio. Partitions ignored. </td>
- </tr>
- <tr>
- <td style="vertical-align: top;">sg device<br>
- </td>
- <td style="vertical-align: top;">O_RDWR or O_RDONLY<br>
- </td>
- <td style="vertical-align: top;">O_RDWR<br>
- </td>
- <td style="vertical-align: top;">SCSI commands<br>
- </td>
- <td style="vertical-align: top;">Opens input O_RDONLY if O_RDWR
-fails</td>
- </tr>
- <tr>
- <td style="vertical-align: top;">raw device<br>
- </td>
- <td style="vertical-align: top;">O_RDONLY</td>
- <td style="vertical-align: top;">O_WRONLY<br>
- </td>
- <td style="vertical-align: top;">Unix read() write()<br>
- </td>
- <td style="vertical-align: top;">O_DIRECT open flag in lk 2.6
-series is a replacement for raw devices<br>
- </td>
- </tr>
- <tr>
- <td style="vertical-align: top;">scsi tape device<br>
- </td>
- <td style="vertical-align: top;">x<br>
- </td>
- <td style="vertical-align: top;">x<br>
- </td>
- <td style="vertical-align: top;">no IO<br>
- </td>
- <td style="vertical-align: top;">error reported<br>
- </td>
- </tr>
- </tbody>
-</table>
-<br>
-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 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 required
-by both raw devices and normal block devices that
-implement O_DIRECT.<br>
-<br>
-The blk_sgio=1 option (or iflag=sgio and/or oflag=sgio) 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
-commands even though the file type is not a scsi generic (sg) device.
-Currently this will work for all cd/dvd devices irrespective of the
-transport (except for some very old devices ( &gt; 10 years old)) and
-block devices representing SCSI disks (e.g. <span
- style="font-family: monospace;">/dev/sda</span>). Even though SCSI
-tape (st) devices now accept the SG_IO ioctl in the lk 2.6 series, the
-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 with a block device and the <span
- style="font-style: italic;">BPT</span> value
-is too high then the first read may report an EIO (input/output)
-error; the solution is to lower the <span style="font-style: italic;">BPT</span>
-value. [The EIO error
-occurred often with CD/DVD drives which have 2048 bytes sectors, so the
-<span style="font-style: italic;">BPT</span> default value was reduced
-for block size &gt;= 2048 bytes.]<br>
-<br>
-If a partition of block device is accessed (e.g. <span
- style="font-family: monospace;">/dev/sda2</span>) when blk_sgio=0 (or
-is not given) then logical block address 0 for the
-purposes of sg_dd (and its skip and seek options) is the beginning of
-that partition while the calculated count (e.g. when a 'count' option
-is not given) is the extent of that partition. However if a partition
-of block device is accessed (e.g. <span style="font-family: monospace;">/dev/sda2</span>)
-when blk_sgio=1 then the
-partition is ignored and the underlying device is accessed. This means
-logical block address 0 for the purposes of sg_dd (and its skip and
-seek options) is the beginning of the device while the calculated count
-(e.g. when a 'count' option is not given) is the extent of that device.<br>
-<br>
-<span style="font-weight: bold;"></span>When a
-CD is accessed via SCSI commands and the 'count' option is not given
-then the READ CAPACITY SCSI command is used by sg_dd to determine the
-number of blocks to read. Unfortunately some MMC standards allow a few
-of the final blocks to be invalid ("run out" sectors) and this can
-result in IO errors when the sg_dd utility is used to copy such a CD.
-The isosize utility can be used to determine the actual size of an
-ISO9660 file system residing on such a CD. It is often a few blocks
-shorter than READ CAPACITY reports (for good reason).<br>
-<br>
-If a SIGUSR1 signal is sent to the process identifier (pid) of a
-running sg_dd utility then the number of blocks copied to that point is
-output. The copy continues.<br>
-<br>
-When the 'time=1' option is given, the elapsed time for the copy plus
-the
-throughput measured in megabytes (10**6 bytes)&nbsp; per second is
-output when the copy is complete (or an error stops the copy). If a
-SIGUSR1 signal is sent to the process identifier (pid) of a running
-sg_dd utility which has the 'time' option set the elapsed time and the
-throughput of the copy to that point is output and the copy continues.<br>
-<h2><a class="mozTocH2" name="mozTocId657084"></a>Retries</h2>
-Often retries are of little use, especially on medium errors, since the
-device has probably already done multiple retries (probably
-interspersed with moving the heads to the extreme ends of the media)
-before the medium error is reported. However a transport error (e.g.
-causing a CRC error in returned data) is not necessarily seen by the
-device and a retry may quickly solve the problem. In SAS a Transport
-Layer Retries (TLR) state machine is optional and requires both the
-initiator and target to implement the capability. Most first generation
-SAS disks do not implement TLR. So transport errors in the form of
-"aborted commands" can be reported due to corruption (marginal cables)
-or congestion.<br>
-<br>
-When the retries=<span style="font-style: italic;">RETR</span> option
-is given and <span style="font-style: italic;">RETR</span> is greater
-than 0 then most errors on a READ or WRITE SCSI command are retried up
-to <span style="font-style: italic;">RETR</span> times. Device not
-ready errors are not retried and "unit
-attention" conditions are automatically retried (without looking at or
-decrementing <span style="font-style: italic;">RETR</span>). Once the
-number of retries is exhausted on the
-same operation without success then sg_dd will refer to the 'coe'
-option as to what to do next. Each new operation,<br>
-READ or WRITE, or to a different logical block address has its own
-retry count initialized to <span style="font-style: italic;">RETR</span>.<br>
-<h2><a class="mozTocH2" name="mozTocId437677"></a>Continue on error
-(coe)</h2>
-Recent additions to the sg_dd utility allow it to be used as a copy "of
-last resort" from failing media. Read errors on an input file
-taking SCSI commands are "tolerated" when the 'coe' option is non-zero.
-Write errors from SCSI commands are reported and ignored and the sg_dd
-utility continues when the 'coe' option is non-zero. [In the case where
-media errors are causing write errors the user should check the setting
-of the AWRE bit in the SCSI "read write
-error recovery" mode page (see SBC-2 at <a href="http://www.t10.org">http://www.t10.org</a>).]<br>
-<br>
-When a SCSI READ command detects an unrecoverable read error it
-responds with a sense key of MEDIUM ERROR or HARDWARE ERROR.
-Additionally it responds with the logical block address of the first
-(lowest) block that it failed to read in the current READ command. Any
-valid blocks prior to the "bad" block may or may not have been
-transferred (depending on several other settings). If coe=0 then the
-sg_dd utility will simply terminate at this point (with a reasonable
-amount of debug information sent to stderr) <span
- style="font-weight: bold;">and</span> good blocks prior to the bad
-block may not be copied (depending on the setting of <span
- style="font-style: italic;">BPT</span>). If 'coe'
-is non-zero then the first
-thing sg_dd will try to do is a truncated read up to, but not
-including,
-the
-bad block. The remaining discussion in this section assumes 'coe' is
-non-zero.<br>
-<br>
-The "bad" block may or may not be readable by the device. If it is
-readable then most likely the associated ECC data indicates that it is
-corrupt and the ECC data cannot recover it. [It is possible that all
-the corruption is in the ECC data and the payload data is ok.] Such
-blocks can be retrieved with the READ LONG command. If the READ LONG
-fails then a block of zeros is
-substituted for the bad block in the transfer buffer. When 'coe=1' then
-READ LONG is not attempted and the "bad" block is replaced by zeros.
-When coe=2'(or 'iflag=coe,coe') then a READ LONG is attempted. When
-coe=3 then a READ LONG with its CORRCT bit set is attempted. Only SBC
-devices (primarily SCSI disks) optionally support READ LONG. CD/DVD
-devices (covered in the MMC-4 (draft) standard) do not, so a block of
-zeros is substituted for them. Even if READ LONG succeeds on a "bad"
-block, the recovered data may not be useful. There are no guarantees
-that the user data will appear "as is" in the first 512 bytes.<br>
-<br>
-There still remain blocks after the "bad" block that need to be
-fetched. Further bad blocks may be detected and if so
-the algorithm in the last two paragraphs is repeated. The result of
-this
-process is an imperfect copy with blocks that were read properly placed
-in the correct relative position in the output. When the coe=1 option
-is given two addition counters are output on completion:<br>
-<ul>
- <li>unrecovered errors (number of bad blocks)<br>
- </li>
- <li>read_longs that "successfully" fetched part of those bad blocks<br>
- </li>
-</ul>
-The first counter is the number of unrecovered (read) errors
-encountered. Any number greater than zero flags an imperfect copy. The
-second counter (always less than or equal to the first) is the number
-of "successful" READ LONG SCSI commands performed. If the source media
-is a CD or DVD then this number will be zero.<br>
-<br>
-The coe_limit=<span style="font-style: italic;">CL</span> option is
-meant to stop sg_dd continuing ad
-nausum if errors are being detected during reading. The input media may
-be blank (unrecorded) or beyond its logical block address limit. The
-coe_limit=<span style="font-style: italic;">CL</span> option is only
-active on read operations when
-'coe &gt; 0' which itself is only active on sg device nodes (or block
-devices when blk_sgio=1 (or iflag=sgio) is given).<br>
-<br>
-<h2><a class="mozTocH2" name="mozTocId566094"></a>Recovered errors</h2>
-Often errors are recovered using ECC data or by the device retrying
-(usually re-reading) the media. Typically at the first sign of trouble,
-recoverable errors lead to the block in question being reassigned to
-another location on the media (automatically when the AWRE and ARRE
-bits are set in the "read write error recovery" mode page).&nbsp; The
-user of such a disk may be blissfully unaware that the disk may be
-reaching the end of its useful life. Error counters are maintained in
-the "Read error counter" and "Write error counter" logs pages which can
-be viewed with smartctl (from smartmontools) and sg_logs (from the same
-sg3_utils package that sg_dd comes from). Any block that is
-automatically or manually re-assigned adds a new entry to the "grown"
-defect list which can be viewed with '<span
- style="font-family: monospace;">sginfo -G</span>' or '<span
- style="font-family: monospace;">sg_reassign -g</span>'
-(both found in the
-sg3_utils package).<br>
-<br>
-A disk can be instructed to report RECOVERED ERRORs by setting the PER
-bit in the "read write error recover" mode page. Most often this bit is
-clear. When sg_dd detects RECOVERED ERRORs it reports them, counts
-them and continues the copy. Only the lba of the last recovered error
-in a READ or WRITE SCSI
-command is reported so there could be more than one recovered error per
-SCSI command. The bpt=1 option
-could be chosen to limit every SCSI command to a single block transfer
-(but that would slow things down a fair amount). If the count of
-recovered errors is greater than zero at the end of the copy then this
-count is output as well.<br>
-<br>
-There can be other reasons for a sense key of RECOVERED ERROR not
-directly related to data being currently read or written. SMART alerts
-(called in SCSI documents "Informational Exceptions") can be conveyed
-via a RECOVERED ERROR sense key (see the MRIE field in the
-Informational Exceptions mode page). Such alerts have additional sense
-codes like "Failure prediction threshold exceeded" and those that
-contain "impending failure".<br>
-<h2><a class="mozTocH2" name="mozTocId899152"></a>Verbose</h2>
-In the Unix style, sg_dd doesn't output anything (to stderr) during
-large IO transfers. To get a progress report the SIGUSR1 signal can be
-sent to the sg_dd process. In the Unix dd command style, sg_dd outputs
-two lines on completion that show the number of full and partial
-records
-in (on the first line) and out (on the second line). Some modern
-versions of the dd command also output elapsed time and throughput
-figures (to get this with sg_dd use the "time=1" option).<br>
-<br>
-The sg_dd has a 'verbose' option whose default value is zero. When set
-this option has the following actions:<br>
-<ol>
- <li>show categorization and INQUIRY data (where applicable) for the
-input and output files. For files, other than streams, the file/device
-size (and device block size) are output.<br>
- </li>
- <li>same output as 1 plus data for Unix and SCSI commands (cdbs) that
-are not repeated (i.e. other than Unix read/write and SCSI READ/WRITE
-commands). Increased error reporting for all SCSI commands</li>
- <li>same output as 2 plus data for Unix and SCSI commands (cdbs) that
-are repeated. For a large copy this will be a lot of output.</li>
- <li>maximum amount of debug output. For a large copy this will be a
-lot of output.</li>
-</ol>
-All verbose output is sent to stderr (so that sg_dd usage with "of=-"
-(copy output to stdout) is not corrupted).<br>
-<br>
-Following is an example of using verbose=1 to find information about
-<span style="font-family: monospace;">/dev/sda</span> . If no copy is
-required then setting count=0 will see to
-that. Since <span style="font-family: monospace;">/dev/sda</span> is a
-block device then it would normally be
-accessed via Unix system commands. The verbose=1 output is relatively
-short when blk_sgio=0 (its default value). The second invocation is
-with blk_sgio=1 and a lot more is output. That includes INQUIRY
-standard response data (e.g. "SEAGATE ..." line).
-See the SBC-2 drafts at <a href="http://www.t10.org/">www.t10.org</a>
-for more information.<br>
-<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;">
-<span style="font-family: monospace;">&nbsp;&gt;&gt; Input file type:
-block device</span><br style="font-family: monospace;">
-<span style="font-family: monospace;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
-open input, flags=0x0</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;
-[bgs64] number of blocks=17781521 [0x10f5311], block size=512</span><br
- style="font-family: monospace;">
-<span style="font-family: monospace;">0+0 records in</span><br
- style="font-family: monospace;">
-<span style="font-family: monospace;">0+0 records out</span><br
- style="font-family: monospace;">
-<span style="font-family: monospace;"><br>
-<br>
-$ sg_dd if=/dev/sda of=. bs=512 verbose=1 count=0 blk_sgio=1</span><br
- style="font-family: monospace;">
-<span style="font-family: monospace;">&nbsp;&gt;&gt; Input file type:
-block device</span><br style="font-family: monospace;">
-<span style="font-family: monospace;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
-open input(sg_io), flags=0x2</span><br style="font-family: monospace;">
-<span style="font-family: monospace;">&nbsp;&nbsp;&nbsp; /dev/sda:
-SEAGATE&nbsp;&nbsp;
-ST39173LC&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 1234&nbsp;
-[pdt=0]</span><span style="font-family: monospace;"></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;
-number of blocks=17781521 [0x10f5311], block size=512</span><br
- style="font-family: monospace;">
-<span style="font-family: monospace;">0+0 records in</span><br
- style="font-family: monospace;">
-<span style="font-family: monospace;">0+0 records out</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 class="mozTocH2" name="mozTocId443896"></a>sgp_dd, sgm_dd and
-sg_read</h2>
-These three sg3_utils utilities are closely related to sg_dd . They all
-have their own man pages.<br>
-<br>
-<span style="font-weight: bold;">sgp_dd</span> uses POSIX threads
-(default: 4 threads) to potentially speed the copy. The syntax and
-semantics of sgp_dd are very similar to sg_dd. The "continue on error"
-processing in sgp_dd is simpler than what is described above for sg_dd.
-Instead of the verbose=<span style="font-style: italic;">VERB</span>
-option used by sg_dd, sgp_dd uses
-'deb=<span style="font-style: italic;">VERB</span>' which does a
-similar thing.<br>
-<br>
-<span style="font-weight: bold;">sgm_dd</span> uses memory mapped IO to
-speed copies from or to sg device nodes. Memory mapped IO will bypass
-the kernel buffers used by the sg driver for normal data transfers.
-With memory mapped IO the Host Bus Adapter (HBA) DMA mechanism will
-transfer data directly from the external bus (e.g. fibre channel) to
-the user space. Even though this may seem like a major performance win,
-there are various low level details (e.g. alignment and signal
-processing) that complicate the picture.<br>
-<br>
-<span style="font-weight: bold;">sg_read</span> uses a similar syntax
-to sg_dd but has no 'of=<span style="font-style: italic;">OFILE</span>'.
-It is designed to measure the
-performance of device (e.g. disk) caches, the throughput of the
-transport and command overhead. It perform a read (either a SCSI READ
-command or a Unix read()) from the given skip block address (default is
-logical block address 0) and continues doing reads until count=<span
- style="font-style: italic;">COUNT</span> is exhausted. If multiple
-reads are&nbsp;
-performed (i.e. when "<span style="font-style: italic;">COUNT</span>
-&gt; <span style="font-style: italic;">BPT</span>") then they are all
-from the same
-logical address. For example, with SCSI READs, exactly the same READ
-cdb is issued for each read operation. The data is thrown away. Zero
-block reads can also be issued using a negative count value. This is
-useful for measuring SCSI command overhead.<br>
-<h2><a class="mozTocH2" name="mozTocId157981"></a>Conclusion</h2>
-The sg_dd utility maintains syntactic and semantic compatibility with
-the Unix/GNU dd command while allowing precise control over SCSI
-devices
-such as SCSI disks and CD/DVD drives. Amongst other uses, it can copy
-data from failing media, continuing as best it can in the presence of
-MEDIUM errors, while recovering as much data as possible.<br>
-<br>
-<p>Return to <a href="index.html">main</a> page. </p>
-<center>
-<p>Last updated: 24th January 2007<br>
-<br>
-</p>
-</center>
-</body>
-</html>
diff --git a/doc/sg_io.html b/doc/sg_io.html
deleted file mode 100644
index 1eb55052..00000000
--- a/doc/sg_io.html
+++ /dev/null
@@ -1,1649 +0,0 @@
-<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
-<html>
-<head>
- <title>Linux SG_IO ioctl in the 2.6 series</title>
- <meta http-equiv="Content-Type"
- content="text/html; charset=iso-8859-1">
- <meta name="keywords" content="Linux, SCSI, SG_IO, ioctl">
- <meta name="GENERATOR"
- content="Mozilla/4.79 [en] (X11; U; Linux 2.5.31 i686) [Netscape]">
-</head>
-<body alink="#ff0000" background="paper.jpg" bgcolor="#ffffff"
- link="#0000ff" text="#000000" vlink="#000080">
-<center>
-<h1><a class="mozTocH1" name="mozTocId288504"></a> The&nbsp; Linux
-SG_IO ioctl in the 2.6 series<br>
-</h1>
-</center>
-<a href="#Conclusion"></a>
-<ol id="mozToc">
-<!--mozToc h1 1 h2 2 h3 3 h4 4 h5 5 h6 6--><li><a href="#mozTocId288504">
-The&nbsp; Linux
-SG_IO ioctl in the 2.6 series </a>
- <ol>
- <li><a href="#mozTocId857690">Introduction</a></li>
- <li><a href="#mozTocId844428">SCSI and related
-command sets </a></li>
- <li><a href="#mozTocId568229">SG_IO ioctl overview</a></li>
- <li><a href="#mozTocId575826">SG_IO ioctl in the sg
-driver </a></li>
- <li><a href="#mozTocId104192">SG_IO ioctl
-differences </a></li>
- <li><a href="#mozTocId830340">open() considerations</a></li>
- <li><a href="#mozTocId645134">SCSI command
-permissions</a></li>
- <li><a href="#mozTocId154063">Maximum transfer size per command</a></li>
- <li><a href="#mozTocId267334">Conclusion</a></li>
- </ol>
- </li>
-</ol>
-<h2><a class="mozTocH2" name="mozTocId857690"></a>Introduction</h2>
-The <span style="font-weight: bold;">SG_IO</span> ioctl permits user
-applications to send SCSI commands to a device. In the linux 2.4 series
-this ioctl was only available via the SCSI generic (sg) driver. In the
-linux 2.6 series the SG_IO ioctl is additionally available for block
-devices
-and SCSI tape (st) devices.&nbsp; So there are multiple implementations
-of this ioctl within the kernel with slightly different characteristics
-and describing these is the purpose of this document.<br>
-<br>
-The information in this page is valid for linux kernel 2.6.16 .<br>
-<h2><a class="mozTocH2" name="mozTocId844428"></a>SCSI and related
-command sets<br>
-</h2>
-All SCSI devices should respond to an INQUIRY command and part of their
-response is the so-called peripheral device type. This is used by the
-linux kernel to decide which upper level driver controls the device.
-There are also devices that belong to other (i.e. not considered SCSI)
-transports that use SCSI command sets, the primary examples of this are
-(S-)ATAPI CD and DVD drives. Not all peripheral device types map to
-upper level drivers and devices of these types are usually accessed via
-the SCSI generic (sg) driver.<br>
-<br>
-SCSI (draft) standards are found at <a href="http://www.t10.org/">www.t10.org</a>
-. SCSI commands common to all
-SCSI devices are found in SPC-4 while those specific to block devices
-are found in SBC-2, those for CD/DVD drives are found in MMC-5 and
-those for SCSI tape drives are found in SSC-3.<br>
-<br>
-The major non-SCSI command set in the storage area is for ATA
-<span style="font-style: italic;">non-packet</span> devices which are
-typically disks. ATA <span style="font-style: italic;">packet</span>
-devices use ATAPI which in
-the vast majority of cases carry a SCSI command set. The most recent
-draft ATA command set standard is ATA8-ACS and can be found at <a
- href="http://www.t13.org/">www.t13.org</a> . To complicate things
-(non-packet) ATA devices may have their native command set translated
-into SCSI. This can happen in the kernel (e.g. libata in linux) or in
-an intermediate device (e.g. in a USB external disk enclosure). Yet
-another possibility are disks
-whose firmware can be changed to allow them to use either the SCSI or
-ATA command set, this may happen in the SAS/SATA area since the
-physical (cabling) and phy (electrical signalling) levels are so
-similar.<br>
-<h2><a class="mozTocH2" name="mozTocId568229"></a>SG_IO ioctl overview</h2>
-The third argument given to the SG_IO ioctl is a pointer to an instance
-of the sg_io_hdr structure which is defined in the &lt;scsi/sg.h&gt;
-header file. The execution of the SG_IO ioctl can viewed as going
-through three phases:<br>
-<ol>
- <li>do sanity checks on the metadata in the sg_io_hdr instance; read
-the input fields and the data pointed to by some of those fields; build
-a SCSI command and issue it to the device</li>
- <li>wait for either a response from the device, the command to
-timeout or
-the user to terminate the process (or thread) that invoked the SG_IO
-ioctl</li>
- <li>write the output fields and in some cases write data to locations
-pointed to by some fields, then return</li>
-</ol>
-Only phase 1 returns an ioctl error (i.e. a return value of -1 and a
-value
-set in errno). In phase 2, command timeouts should be used sparingly as
-the device (and some others on the same interconnect) may end up being
-reset. If the user terminates the process or thread that invoked the
-SG_IO ioctl then obviously phase 3 never occurs but the command
-execution runs to completion (or timeout) and the kernel "throws away"
-the results. If the command yields a SCSI status of CHECK
-CONDITION (in field "status") then sense data is written out in
-phase 3 .<br>
-<br>
-Now we will assume that the SCSI command involves user data being
-transferred to or from the device. The SCSI subsystem does not support
-true bidirectional data transfers to a device. All data DMA transfers
-(assuming the hardware supports DMA) occur in phase 2. However, if
-indirect IO is being used (i.e. neither direct IO nor mmap-ed
-transfers) then either:<br>
-<ul>
- <li>data is read from the user space in phase 1 into kernel buffers
-and DMA-ed to the device in phase 2, or</li>
- <li>data is read from the device into kernel buffers in phase 2 and
-written into the user space in phase 3</li>
-</ul>
-When direct IO or mmap-ed transfers are being used then all user data
-is moved in phase 2 . If a process is terminated during such a data
-transfer then the kernel gracefully handles this (by pinning the
-associated memory pages until the transfer is complete).<br>
-<br>
-The sg_io_hdr structure has 22 fields (members) but typically only a
-small number of them need to be set. The following code fragment shows
-the setup for a simple TEST UNIT READY SCSI command which has no
-associated data transfers:<br>
-&nbsp;&nbsp;&nbsp; <br>
-<span style="font-family: monospace;">&nbsp;&nbsp;&nbsp; unsigned char
-sense_b[32];</span><br style="font-family: monospace;">
-<span style="font-family: monospace;">&nbsp;&nbsp;&nbsp; unsigned char
-turCmbBlk[] = {TUR_CMD, 0, 0, 0, 0, 0};<br>
-&nbsp;&nbsp;&nbsp; struct sg_io_hdr io_hdr;<br
- style="font-family: monospace;">
-</span><br style="font-family: monospace;">
-<span style="font-family: monospace;">&nbsp;&nbsp;&nbsp;
-memset(&amp;io_hdr, 0, sizeof(struct sg_io_hdr));</span><br
- style="font-family: monospace;">
-<span style="font-family: monospace;">&nbsp;&nbsp;&nbsp;
-io_hdr.interface_id = 'S';</span><br style="font-family: monospace;">
-<span style="font-family: monospace;">&nbsp;&nbsp;&nbsp; io_hdr.cmd_len
-= sizeof(turCmbBlk);</span><br style="font-family: monospace;">
-<span style="font-family: monospace;">&nbsp;&nbsp;&nbsp;
-io_hdr.mx_sb_len = sizeof(sense_b);</span><br
- style="font-family: monospace;">
-<span style="font-family: monospace;">&nbsp;&nbsp;&nbsp;
-io_hdr.dxfer_direction = SG_DXFER_NONE;</span><br
- style="font-family: monospace;">
-<span style="font-family: monospace;">&nbsp;&nbsp;&nbsp; io_hdr.cmdp =
-turCmbBlk;</span><br style="font-family: monospace;">
-<span style="font-family: monospace;">&nbsp;&nbsp;&nbsp; io_hdr.sbp =
-sense_b;</span><br style="font-family: monospace;">
-<span style="font-family: monospace;">&nbsp;&nbsp;&nbsp; io_hdr.timeout
-= DEF_TIMEOUT;</span><br style="font-family: monospace;">
-<br style="font-family: monospace;">
-<span style="font-family: monospace;">&nbsp;&nbsp;&nbsp; if (ioctl(fd,
-SG_IO, &amp;io_hdr) &lt; 0) {</span><br>
-<br>
-The memset() call is pretty important, setting unused input fields to
-safe values. Setting the timeout field to zero is not a good idea;
-30,000 (for 30 seconds) is a reasonable default for most SCSI commands.
-As always, good error
-processing consumes a lot more code. This is especially the case with
-SCSI commands that yield "sense data" when something goes wrong. For
-example, if there is a medium error during a disk read, the sense data
-will contain the logical block address (lba) of the failure. Another
-error processing example is a SCSI command that the device considers an
-"illegal
-request", the sense data may show the byte and bit position of the
-field in the command block (usually referred to as a "cdb") that it
-objects to. For examples on error processing please refer to the
-sg3_utils package, its "examples" directory and its library components:
-sg_lib.c (SCSI error processing and tables) and sg_cmds.c (common SCSI
-commands).<br>
-<br>
-Below is a grouping of important sg_io_hdr structure fields with brief
-summaries:<br>
-Command block (historically referred to as the "cdb"):<br>
-<ul>
- <li>cmdp - pointer to cdb (the SCSI command block)</li>
- <li>cmd_len - length (in bytes) of cdb</li>
-</ul>
-Data transfer:<br>
-<ul>
- <li>dxferp - pointer to user data to start reading from or start
-writing to</li>
- <li>dxfer_len - number of bytes to transfer</li>
- <li>dxfer_direction - whether to read from device (into user memory)
-or write to device (from user memory) or transfer no data:
-DXFER_FROM_DEV, DXFER_TO_DEV or DXFER_NONE respectively<br>
- </li>
- <li>resid - requested number of bytes to transfer (i.e. dxfer_len)
-less the actual number transferred</li>
-</ul>
-Error indication:<br>
-<ul>
- <li>status - SCSI status returned from the device</li>
- <li>host_status - error from Host Bus Adapter including initiator
-(port)<br>
- </li>
- <li>driver_status - driver (mid level or low level driver) error and
-suggestion mask</li>
-</ul>
-Sense data (only used when 'status' is CHECK CONDITION or
-(driver_status &amp; DRIVER_SENSE) is true):<br>
-<ul>
- <li>sbp - pointer to start writing sense data to<br>
- </li>
- <li>mx_sb_len - maximum number of bytes to write to sbp</li>
- <li>sb_len_wr - actual number of bytes written to sbp</li>
-</ul>
-The fields in the sg_io_hdr structure are defined in more detail in the
-<a href="http://www.tldp.org/HOWTO/SCSI-Generic-HOWTO/index.html">SCSI-Generic-HOWTO</a>
-document.<br>
-<h2><a class="mozTocH2" name="mozTocId575826"></a>SG_IO ioctl in the sg
-driver<br>
-</h2>
-Linux kernel 2.4.0 was the first production kernel in which the SG_IO
-ioctl appeared in the SCSI generic (sg) driver. The sg driver itself
-has been in linux since around 1993.
-An instance of the sg_io_hdr structure in the sg driver can either be:<br>
-<ul>
- <li>pointed to by the third argument of the SG_IO ioctl</li>
- <li>pointed to by the second argument of UNIX write() or read()
-system
-calls which have a file descriptor of a sg device node as their first
-argument<br>
- </li>
-</ul>
-The <a href="http://www.tldp.org/HOWTO/SCSI-Generic-HOWTO/index.html">SCSI-Generic-HOWTO</a>
-document describes the sg driver in the lk 2.4 series including its use
-of the SG_IO ioctl. Prior to the lk 2.4 series the sg driver only had
-the sg_header structure. It was used as an asynchronous
-command interface in which command, metadata and optionally user data
-was sent via a Unix write() system call. The corresponding response
-which included
-error information (e.g. sense data) or optionally user data was
-received via a Unix read() system call. Two major additions were made
-to the sg
-driver at the beginning of the lk 2.4 series:<br>
-<ul>
- <li>a new metadata structure (sg_io_hdr) as an alternative to the
-original mixed metadata and data structure (sg_header)</li>
- <li>the SG_IO ioctl that used the new metadata structure and was
-synchronous: it sent a SCSI command and waited for its reply</li>
-</ul>
-The sg_io_hdr only contains metadata in the sense that it contains
-pointers to locations of where data will come from (command or data in)
-or go to (sense data or data out). These pointers have caused problems
-in mixed 32/64 bit environments, especially when the user application
-(e.g. cdrecord) is built for 32 bits and the kernel is 64 bits. The lk
-2.6 series has a compatibility layer to cope with this via code
-specialized for the SG_IO ioctl. Unfortunately this problem was not
-foreseen when the sg_io_hdr structure was designed.<br>
-<br>
-A significant feature of the SG_IO ioctl in the sg driver is that it
-is user interruptible. This means between issuing a command (e.g. a
-long duration command like a disk format) and its response arriving a
-user could hit control-C on the associated application. The kernel
-would remain stable and resources would be cleared up at the
-appropriate time. The sg driver does not attempt to abort such a
-command that is "in flight", it simply throws away the response and
-cleans up. Naturally the user has no direct way of finding out whether
-an interrupted command succeeded or not, by there may be indirect ways.<br>
-<br>
-A warning may also be in order here: a long duration command such as
-format would typically be given a long timeout value. If the user
-interrupted the application that sent the format command then the
-device may remain
-busy doing the format (especially if the IMMED bit is not set). So if
-the user then sent a short duration command such as TEST UNIT READY or
-REQUEST SENSE to see what the device was doing, these commands may
-timeout. This would invoke the SCSI subsystem error handler which would
-most likely
-send a device reset, thus aborting the format, to get the device's
-attention. This is probably not what the user had in mind!<br>
-<br>
-<h2><a class="mozTocH2" name="mozTocId104192"></a>SG_IO ioctl
-differences<br>
-</h2>
-In the following table,
-sg_io_hdr structure fields are listed in the order they appear in that
-structure. Basically the "in" fields appear at the top of the structure
-and are read in phase 1. The latter fields are termed as "out" and are
-written by the SG_IO implementation in phase 3.<br>
-&nbsp;<br>
-<table style="width: 100%; text-align: left;" border="1" cellpadding="2"
- cellspacing="2">
- <caption><span style="font-weight: bold;">Table 1. sg_io_hdr
-structure&nbsp; summary and implementation differences</span><br>
- </caption> <tbody>
- <tr>
- <td style="vertical-align: top;"><span style="font-weight: bold;">sg_io_hdr
-field</span><br>
- </td>
- <td style="vertical-align: top;"><span style="font-weight: bold;">in
-or out</span><br>
- </td>
- <td style="vertical-align: top;"><span style="font-weight: bold;">type</span><br>
- </td>
- <td style="vertical-align: top;"><span style="font-weight: bold;">different</span><br>
- </td>
- <td style="vertical-align: top;"><span style="font-weight: bold;">brief
-description including differences between implementations</span><br>
- </td>
- </tr>
- <tr>
- <td style="vertical-align: top;">interface_id<br>
- </td>
- <td style="vertical-align: top;">in<br>
- </td>
- <td style="vertical-align: top;">int<br>
- </td>
- <td style="vertical-align: top;"><br>
- </td>
- <td style="vertical-align: top;">guard field. Current
-implementations only accept " (int)'S' ". If not set, the sg driver
-sets errno to ENOSYS
-while the block layer sets it to EINVAL<br>
- </td>
- </tr>
- <tr>
- <td style="vertical-align: top;">dxfer_direction<br>
- </td>
- <td style="vertical-align: top;">in<br>
- </td>
- <td style="vertical-align: top;">(-ve) int<br>
- </td>
- <td style="vertical-align: top;">minor<br>
- </td>
- <td style="vertical-align: top;">direction of data transfer.
-SG_DXFER_NONE and friends are defined as negative integers so the sg
-driver can discriminate between sg_io_hdr instances and those of
-sg_header. This nuance is irrelevant to non-sg driver usage of SG_IO.
-See below.<br>
- </td>
- </tr>
- <tr>
- <td style="vertical-align: top;">cmd_len<br>
- </td>
- <td style="vertical-align: top;">in<br>
- </td>
- <td style="vertical-align: top;">unsigned char<br>
- </td>
- <td style="vertical-align: top;"><br>
- </td>
- <td style="vertical-align: top;">limits command length to 255
-bytes. No SCSI commands (even variable length ones in OSD) are this
-long (yet)<br>
- </td>
- </tr>
- <tr>
- <td style="vertical-align: top;">max_sb_len<br>
- </td>
- <td style="vertical-align: top;">in<br>
- </td>
- <td style="vertical-align: top;">unsigned char<br>
- </td>
- <td style="vertical-align: top;"><br>
- </td>
- <td style="vertical-align: top;">maximum number of bytes of sense
-data that the driver can output via the sbp pointer<br>
- </td>
- </tr>
- <tr>
- <td style="vertical-align: top;">iovec_count<br>
- </td>
- <td style="vertical-align: top;">in<br>
- </td>
- <td style="vertical-align: top;">unsigned short<br>
- </td>
- <td style="vertical-align: top;">yes<br>
- </td>
- <td style="vertical-align: top;">if not sg driver and greater
-than zero then the SG_IO ioctl fails with errno set to EOPNOTSUPP; sg
-driver treats dxferp as a pointer to an array struct sg_iovec when this
-field is greater than zero<br>
- </td>
- </tr>
- <tr>
- <td style="vertical-align: top;">dxfer_len<br>
- </td>
- <td style="vertical-align: top;">in<br>
- <br>
- </td>
- <td style="vertical-align: top;">unsigned int<br>
- </td>
- <td style="vertical-align: top;">minor<br>
- </td>
- <td style="vertical-align: top;">number of bytes of data to
-transfer to or from the device. Upper limit for block devices related
-to <span style="font-family: monospace;">/sys/block/&lt;device&gt;/queue/max_sectors_kb</span><br>
- </td>
- </tr>
- <tr>
- <td style="vertical-align: top;">dxferp </td>
- <td style="vertical-align: top;">in [*in or *out]<br>
- </td>
- <td style="vertical-align: top;">void *<br>
- </td>
- <td style="vertical-align: top;">minor<br>
- </td>
- <td style="vertical-align: top;">pointer to (user space) data to
-transfer to (if reading from device) or transfer from (if writing to
-device). Further level of indirection in the sg driver when iovec_count
-is greater than 0 .<br>
- </td>
- </tr>
- <tr>
- <td style="vertical-align: top;">cmdp </td>
- <td style="vertical-align: top;">in [*in]<br>
- </td>
- <td style="vertical-align: top;">unsigned char *<br>
- </td>
- <td style="vertical-align: top;"><br>
- </td>
- <td style="vertical-align: top;">pointer to SCSI command. The
-SG_IO ioctl in the sg drive fails with errno set to&nbsp; EMSGSIZE if
-cmdp is NULL and EFAULT if it is invalid; the block layer sets errno to
-EFAULT&nbsp; in both cases.<br>
- </td>
- </tr>
- <tr>
- <td style="vertical-align: top;">sbp<br>
- </td>
- <td style="vertical-align: top;">in [*out]<br>
- </td>
- <td style="vertical-align: top;">unsigned char *<br>
- </td>
- <td style="vertical-align: top;"><br>
- </td>
- <td style="vertical-align: top;">pointer to user data area where
-no more than max_sb_len bytes of sense data from the device will be
-written if the SCSI status is CHECK CONDITION. <br>
- </td>
- </tr>
- <tr>
- <td style="vertical-align: top;">timeout<br>
- </td>
- <td style="vertical-align: top;">in<br>
- </td>
- <td style="vertical-align: top;">unsigned int<br>
- </td>
- <td style="vertical-align: top;">yes <br>
-(if = 0)<br>
- </td>
- <td style="vertical-align: top;">time in milliseconds that the
-SCSI mid-level will wait for a response. If that timer expires
-before the command finishes, then the command may be aborted, the
-device (and maybe others on the same interconnect) may be reset
-depending on error
-handler settings. Dangerous stuff, the SG_IO ioctl has no control
-(through this interface) of exactly what happens. In the sg driver a
-timeout value of 0 means 0 milliseconds, in the block layer (currently)
-it means 60 seconds.<br>
- </td>
- </tr>
- <tr>
- <td style="vertical-align: top;">flags<br>
- </td>
- <td style="vertical-align: top;">in<br>
- </td>
- <td style="vertical-align: top;">unsigned int<br>
- </td>
- <td style="vertical-align: top;">yes<br>
- </td>
- <td style="vertical-align: top;">Block layer SG_IO ioctl ignores
-this field; the sg driver uses it to request special services like
-direct IO or mmap-ed transfers. It is a bit mask.<br>
- </td>
- </tr>
- <tr>
- <td style="vertical-align: top;">pack_id<br>
- </td>
- <td style="vertical-align: top;">in -&gt; out<br>
- </td>
- <td style="vertical-align: top;">int<br>
- </td>
- <td style="vertical-align: top;"><br>
- </td>
- <td style="vertical-align: top;">unused (for user space program
-tag)<br>
- </td>
- </tr>
- <tr>
- <td style="vertical-align: top;">usr_ptr<br>
- </td>
- <td style="vertical-align: top;">in -&gt; out<br>
- </td>
- <td style="vertical-align: top;">void *<br>
- </td>
- <td style="vertical-align: top;"><br>
- </td>
- <td style="vertical-align: top;">unused (for user space pointer
-tag)<br>
- </td>
- </tr>
- <tr>
- <td style="vertical-align: top;">status<br>
- </td>
- <td style="vertical-align: top;">out<br>
- </td>
- <td style="vertical-align: top;">unsigned char<br>
- </td>
- <td style="vertical-align: top;"><br>
- </td>
- <td style="vertical-align: top;">SCSI command status, zero
-implies GOOD<br>
- </td>
- </tr>
- <tr>
- <td style="vertical-align: top;">masked_status<br>
- </td>
- <td style="vertical-align: top;">out<br>
- </td>
- <td style="vertical-align: top;">unsigned char<br>
- </td>
- <td style="vertical-align: top;"><br>
- </td>
- <td style="vertical-align: top;">Logically: masked_status ==
-((status &amp; 0x3e) &gt;&gt; 1). Old linux SCSI subsystem usage,
-deprecated. </td>
- </tr>
- <tr>
- <td style="vertical-align: top;">msg_status<br>
- </td>
- <td style="vertical-align: top;">out<br>
- </td>
- <td style="vertical-align: top;">unsigned char<br>
- </td>
- <td style="vertical-align: top;"><br>
- </td>
- <td style="vertical-align: top;">SCSI parallel interface (SPI)
-message status (very
-old, deprecated)<br>
- </td>
- </tr>
- <tr>
- <td style="vertical-align: top;">sb_len_wr<br>
- </td>
- <td style="vertical-align: top;">out<br>
- </td>
- <td style="vertical-align: top;">unsigned char<br>
- </td>
- <td style="vertical-align: top;"><br>
- </td>
- <td style="vertical-align: top;">actual length of sense data (in
-bytes) output via sbp pointer.<br>
- </td>
- </tr>
- <tr>
- <td style="vertical-align: top;">host_status<br>
- </td>
- <td style="vertical-align: top;">out<br>
- </td>
- <td style="vertical-align: top;">unsigned short<br>
- </td>
- <td style="vertical-align: top;"><br>
- </td>
- <td style="vertical-align: top;">error reported by the initiator
-(port). These are the "DID_*" error codes in scsi.h<br>
- </td>
- </tr>
- <tr>
- <td style="vertical-align: top;">driver_status<br>
- </td>
- <td style="vertical-align: top;">out<br>
- </td>
- <td style="vertical-align: top;">unsigned short<br>
- </td>
- <td style="vertical-align: top;"><br>
- </td>
- <td style="vertical-align: top;">bit mask: error and suggestion
-reported by the low level driver (LLD). These are the "DRIVER_*" error
-codes in scsi.h</td>
- </tr>
- <tr>
- <td style="vertical-align: top;">resid<br>
- </td>
- <td style="vertical-align: top;">out<br>
- </td>
- <td style="vertical-align: top;">int<br>
- </td>
- <td style="vertical-align: top;"><br>
- </td>
- <td style="vertical-align: top;">(dxfer_len -
-number_of_bytes_actually_transferred). Typically only set when there is
-a shortened DMA transfer from the device.&nbsp; Not necessarily an
-error. Older LLDs always yield zero.</td>
- </tr>
- <tr>
- <td style="vertical-align: top;">duration<br>
- </td>
- <td style="vertical-align: top;">out<br>
- </td>
- <td style="vertical-align: top;">unsigned int<br>
- </td>
- <td style="vertical-align: top;"><br>
- </td>
- <td style="vertical-align: top;">number of milliseconds that
-elapsed between when the command was injected into the SCSI mid level
-and the corresponding "done" callback was invoked. Roughly the duration
-of the SCSI command in milliseconds.<br>
- </td>
- </tr>
- <tr>
- <td style="vertical-align: top;">info<br>
- </td>
- <td style="vertical-align: top;">out<br>
- </td>
- <td style="vertical-align: top;">unsigned int<br>
- </td>
- <td style="vertical-align: top;">minor<br>
- </td>
- <td style="vertical-align: top;">bit mask indicating what was
-done (or not) and whether any error was detected. Block layer SG_IO
-ioctl only sets SG_INFO_CHECK if an error was detected<br>
- </td>
- </tr>
- </tbody>
-</table>
-<br>
-The DID_* and DRIVER_* error and suggestion codes (associated with
-host_status and driver_status) are discussed in more detail in the
-<a href="http://www.tldp.org/HOWTO/SCSI-Generic-HOWTO/index.html">SCSI-Generic-HOWTO</a>
-document.
-<h2><a class="mozTocH2" name="mozTocId830340"></a>open() considerations</h2>
-Various drivers have different characteristics when a device node is
-opened. One problem with the ioctl system call is that a user only
-needs read permissions to execute it but may, with the ioctls like
-SG_IO, write to a device (e.g. format it).&nbsp; Command (operation
-code) sniffing logic is used to overcome this security problem. Also
-users of the SG_IO ioctl need to be aware when they "share" a device
-with sd, st or a cdrom driver that state machines within those drivers
-may be tricked. This may be unavoidable but the users of the SG_IO
-ioctl should take appropriate care.<br>
-<br>
-Opening a file in linux with flags of zero implies the O_RDONLY flag
-and hence read only access. All open() system calls can yield ENOENT
-(no such file or directory); ENODEV (no such device) if the file exists
-but there is no attached device and EACCES (permission denied) if the
-user doesn't have appropriate permissions.<br>
-<br>
-A user with CAP_SYS_RAWIO capability (normally associated with the
-"root" user) bypasses all command sniffing and other access controls
-that would otherwise lead to EACCES or EPERM errors. With the sg driver
-such a user may still need to open() a device node with O_RDWR (rather
-than O_RDONLY) to use all SCSI commands.<br>
-<br>
-<table style="width: 100%; text-align: left;" border="1" cellpadding="2"
- cellspacing="2">
- <caption><span style="font-weight: bold;">Table 2. open() flags for
-SG_IO ioctl usage</span><br>
- </caption> <tbody>
- <tr>
- <td style="vertical-align: top;"><span style="font-weight: bold;">open()
-flags</span><br>
- </td>
- <td style="vertical-align: top;"><span style="font-weight: bold;">sg<br>
-notes<br>
- </span> </td>
- <td style="vertical-align: top;"><span style="font-weight: bold;">sd<br>
-notes<br>
- </span> </td>
- <td style="vertical-align: top;"><span style="font-weight: bold;">st<br>
-notes<br>
- </span> </td>
- <td style="vertical-align: top;"><span style="font-weight: bold;">cdrom<br>
-notes<br>
- </span> </td>
- <td style="vertical-align: top;"><span style="font-weight: bold;">Comments</span><br>
- </td>
- </tr>
- <tr>
- <td style="vertical-align: top;">&lt;none&gt; or<br>
-O_RDONLY<br>
- </td>
- <td style="vertical-align: top;">1, 2<br>
- </td>
- <td style="vertical-align: top;">3,4<br>
- </td>
- <td style="vertical-align: top;">3,5<br>
- </td>
- <td style="vertical-align: top;">3,6<br>
- </td>
- <td style="vertical-align: top;">best to add O_NONBLOCK. For a
-device with removable media (e.g. tape drive) that depends on whether
-the drive or its media is being accessed.<br>
- </td>
- </tr>
- <tr>
- <td style="vertical-align: top;">O_RDONLY | O_NONBLOCK<br>
- </td>
- <td style="vertical-align: top;">1,7<br>
- </td>
- <td style="vertical-align: top;">3<br>
- </td>
- <td style="vertical-align: top;">3,13<br>
- </td>
- <td style="vertical-align: top;">3<br>
- </td>
- <td style="vertical-align: top;">recommended when SCSI commands
-are recognized as reading information from the device<br>
- </td>
- </tr>
- <tr>
- <td style="vertical-align: top;">O_RDWR<br>
- </td>
- <td style="vertical-align: top;">2<br>
- </td>
- <td style="vertical-align: top;">4,8,9<br>
- </td>
- <td style="vertical-align: top;">5,8,9<br>
- </td>
- <td style="vertical-align: top;">6,8,9<br>
- </td>
- <td style="vertical-align: top;">again, could be better to add
-O_NONBLOCK</td>
- </tr>
- <tr>
- <td style="vertical-align: top;">O_RDWR | O_NONBLOCK<br>
- </td>
- <td style="vertical-align: top;">7<br>
- </td>
- <td style="vertical-align: top;">8,9<br>
- </td>
- <td style="vertical-align: top;">8,9,13<br>
- </td>
- <td style="vertical-align: top;">8,9<br>
- </td>
- <td style="vertical-align: top;">recommended when arbitrary
-(including vendor specific) SCSI commands are to be sent<br>
- </td>
- </tr>
- <tr>
- <td style="vertical-align: top;">&lt;&lt; interaction with
-O_EXCL&gt;&gt;<br>
- </td>
- <td style="vertical-align: top;">10<br>
- </td>
- <td style="vertical-align: top;">11<br>
- </td>
- <td style="vertical-align: top;">12<br>
- </td>
- <td style="vertical-align: top;">11<br>
- </td>
- <td style="vertical-align: top;">only use when sure that no other
-application may want to access the device (or partition). A surprising
-number of applications do "poke around" devices.<br>
- </td>
- </tr>
- <tr>
- <td style="vertical-align: top;">&lt;&lt; interaction with
-O_DIRECT&gt;&gt;<br>
- </td>
- <td style="vertical-align: top;">-<br>
- </td>
- <td style="vertical-align: top;">--&gt;<br>
- </td>
- <td style="vertical-align: top;">-<br>
- </td>
- <td style="vertical-align: top;">--&gt;<br>
- </td>
- <td style="vertical-align: top;">requires sector alignment on
-data transfers (ignored by sg and st)<br>
- </td>
- </tr>
- </tbody>
-</table>
-<br>
-<span style="font-weight: bold;">Notes</span>:<br>
-<ol>
- <li>on subsequent SG_IO ioctl calls, the sg driver will only allow
-SCSI commands in its allow_ops array, others result in EPERM (operation
-not permitted) in errno. See <a href="#SCSI_command_permissions">below</a>
-.<br>
- </li>
- <li>if previous open() of this sg device node still holds O_EXCL then
-this open() waits until it clears.</li>
- <li>on subsequent SG_IO ioctl calls, the block layer will only allow
-SCSI commands listed as "safe_for_read" in the verify_command()
-function in the drivers/block/scsi_ioctl.c file; others result in EPERM
-(operation not permitted) in errno. See <a
- href="#SCSI_command_permissions">below</a> .<br>
- </li>
- <li>if removable media and it is not present then yields ENOMEDIUM
-(no medium found)</li>
- <li>if a tape is not present in drive then yields EIO (input/output
-error), if tape is "in use" then yields EBUSY (resource busy). Only one
-open file descriptor is allowed per st device node at a time (although
-dup() can be used).<br>
- </li>
- <li>if tray closed and media is not present then yields ENOMEDIUM (no
-medium found); if tray open then tries to close it and if no media
-present then yields ENOMEDIUM</li>
- <li>if previous open() of this sg device node still holds O_EXCL then
-yields EBUSY (resource busy).<br>
- </li>
- <li>on subsequent SG_IO ioctl calls, the block layer will allow SCSI
-commands listed as either "safe_for_read" or "safe_for_write". For
-other SCSI commands the user requires the CAP_SYS_RAWIO capability
-(usually associated with the "root" user); if not yields EPERM
-(operation
-not permitted). The first instance of other SCSI commands since boot,
-sends an annoying "scsi: unknown opcode" message to the log.<br>
- </li>
- <li>if the media or drive is marked as not writable then yields EROFS
-(read-only file system).</li>
- <li>if sg device node already has exclusive lock then a subsequent
-attempt to open(O_EXCL) will wait unless O_NONBLOCK is given in which
-case it yields EBUSY (resource busy)<br>
- </li>
- <li>implemented at block device level (which knows about partitions
-within devices). If a previous open(O_EXCL) is active then a subsequent
-open(O_EXCL) yields EBUSY (resource busy). Mounted file systems
-typically open a device/partition with O_EXCL; as long as an
-application using the SG_IO ioctl does not also try and use the O_EXCL
-flag then it will be allowed access to the device.</li>
- <li>the st driver does not support (i.e. ignores) the O_EXCL flag.
-However the fact that it only permits one active open() per tape device
-is similar functionality.<br>
- </li>
- <li>if tape is "in use" then yields EBUSY (resource busy). Only one
-open file descriptor is allowed per st device node at a time.</li>
-</ol>
-The O_EXCL flag has a different effect in the sg driver and the block
-layer. In the sg driver, once O_EXCL is held on a device, all
-subsequent open() attempts will either wait or yield EBUSY
-(irrespective of whether they attempt to use the O_EXCL flag). Once a
-partition/device is opened successfully in the block layer (with the sd
-or cdrom driver) only subsequent open() attempts that also use the
-O_EXCL flag are rejected (with EBUSY). A O_EXCL lock held on a device
-in the block layer has no effect on accessing the same device via the
-sg driver (and vice versa).<br>
-<br>
-The first successful open on a sd or a cdrom device node that has
-removable media will send a PREVENT ALLOW MEDIUM REMOVAL (prevent) SCSI
-command to the device. If successful, this will inhibit a subsequent
-START STOP UNIT (eject) SCSI command and de-activate the eject button
-on the drive. In emergencies, the SG_IO ioctl can be used to defeat
-this action, an example of this is the <a href="sdparm.html">sdparm</a>
-utility, specifically "sdparm --command=unlock".<br>
-<br>
-The open() flag O_NDELAY has the same value and meaning as O_NONBLOCK.
-Other flags such as O_DIRECT, O_TRUNC and O_APPEND have no effect on
-the SG_IO ioctl.<br>
-<h2><a class="mozTocH2" name="mozTocId645134"></a>SCSI command
-permissions</h2>
-In linux a user only needs read permissions on a file descriptor to
-execute an ioctl() system command. In the case of the SG_IO ioctl, a
-SCSI command could be sent that obviously changes the state of a device
-(e.g. WRITE to a disk). So both implementations of the SG_IO ioctl
-require more than read permissions for some commands, especially those
-that are known to change the state of a device or those that have some
-unknown action (e.g. vendor specific commands).<br>
-<br>
-Here is a table of SCSI commands that don't need the user to have write
-permissions (or in some cases CAP_SYS_RAWIO capability which usually
-equates to "root" user):<br>
-<table style="width: 100%; text-align: left;" border="1" cellpadding="2"
- cellspacing="2">
- <caption><span style="font-weight: bold;">Table 3. SCSI command
-minimum permission requirements</span><br>
- </caption> <tbody>
- <tr>
- <td style="vertical-align: top;"><span style="font-weight: bold;">SCSI
-command</span><br>
- </td>
- <td style="vertical-align: top;"><span style="font-weight: bold;">(draft)
-standard</span><br>
- </td>
- <td style="vertical-align: top;"><span style="font-weight: bold;">sg
-driver requires</span><br>
- </td>
- <td style="vertical-align: top;"><span style="font-weight: bold;">block
-layer SG_IO<br>
-requires (except st)</span><br>
- </td>
- <td style="vertical-align: top;"><span style="font-weight: bold;">Comments</span><br>
- </td>
- </tr>
- <tr>
- <td style="vertical-align: top;">BLANK<br>
- </td>
- <td style="vertical-align: top;">MMC-4<br>
- </td>
- <td style="vertical-align: top;">O_RDWR</td>
- <td style="vertical-align: top;">O_RDWR</td>
- <td style="vertical-align: top;"><br>
- </td>
- </tr>
- <tr>
- <td style="vertical-align: top;">CLOSE TRACK/SESSION<br>
- </td>
- <td style="vertical-align: top;">MMC-4<br>
- </td>
- <td style="vertical-align: top;">O_RDWR</td>
- <td style="vertical-align: top;">O_RDWR</td>
- <td style="vertical-align: top;"><br>
- </td>
- </tr>
- <tr>
- <td style="vertical-align: top;">ERASE<br>
- </td>
- <td style="vertical-align: top;">MMC-4<br>
- </td>
- <td style="vertical-align: top;">O_RDWR</td>
- <td style="vertical-align: top;">O_RDWR</td>
- <td style="vertical-align: top;"><br>
- </td>
- </tr>
- <tr>
- <td style="vertical-align: top;">FLUSH CACHE<br>
- </td>
- <td style="vertical-align: top;">SBC-3, MMC-4<br>
- </td>
- <td style="vertical-align: top;">O_RDWR</td>
- <td style="vertical-align: top;">O_RDWR</td>
- <td style="vertical-align: top;">Really SYNCHRONIZE CACHE command<br>
- </td>
- </tr>
- <tr>
- <td style="vertical-align: top;">FORMAT UNIT<br>
- </td>
- <td style="vertical-align: top;">SBC-3, MMC-4<br>
- </td>
- <td style="vertical-align: top;">O_RDWR</td>
- <td style="vertical-align: top;">O_RDWR</td>
- <td style="vertical-align: top;">default command timeout may not
-be long enough<br>
- </td>
- </tr>
- <tr>
- <td style="vertical-align: top;">GET CONFIGURATION<br>
- </td>
- <td style="vertical-align: top;">MMC-4<br>
- </td>
- <td style="vertical-align: top;">O_RDWR</td>
- <td style="vertical-align: top;">O_RDONLY</td>
- <td style="vertical-align: top;">reads CD/DVD metadata<br>
- </td>
- </tr>
- <tr>
- <td style="vertical-align: top;">GET EVENT STATUS NOTIFICATION<br>
- </td>
- <td style="vertical-align: top;">MMC-4<br>
- </td>
- <td style="vertical-align: top;">O_RDWR</td>
- <td style="vertical-align: top;">O_RDONLY</td>
- <td style="vertical-align: top;"><br>
- </td>
- </tr>
- <tr>
- <td style="vertical-align: top;">GET PERFORMANCE<br>
- </td>
- <td style="vertical-align: top;">MMC-4</td>
- <td style="vertical-align: top;">O_RDWR</td>
- <td style="vertical-align: top;">O_RDONLY</td>
- <td style="vertical-align: top;"><br>
- </td>
- </tr>
- <tr>
- <td style="vertical-align: top;">INQUIRY<br>
- </td>
- <td style="vertical-align: top;">SPC-4<br>
- </td>
- <td style="vertical-align: top;">O_RDONLY<br>
- </td>
- <td style="vertical-align: top;">O_RDONLY<br>
- </td>
- <td style="vertical-align: top;">All SCSI devices should respond
-to this command<br>
- </td>
- </tr>
- <tr>
- <td style="vertical-align: top;">LOAD UNLOAD MEDIUM<br>
- </td>
- <td style="vertical-align: top;">MMC-4<br>
- </td>
- <td style="vertical-align: top;">O_RDWR</td>
- <td style="vertical-align: top;">O_RDWR</td>
- <td style="vertical-align: top;">MEDIUM may be replaced by CD,
-DVD or nothing<br>
- </td>
- </tr>
- <tr>
- <td style="vertical-align: top;">LOG SELECT<br>
- </td>
- <td style="vertical-align: top;">SPC-4<br>
- </td>
- <td style="vertical-align: top;">O_RDWR</td>
- <td style="vertical-align: top;">O_RDWR</td>
- <td style="vertical-align: top;">used to change logging or clear
-logged data<br>
- </td>
- </tr>
- <tr>
- <td style="vertical-align: top;">LOG SENSE<br>
- </td>
- <td style="vertical-align: top;">SPC-4<br>
- </td>
- <td style="vertical-align: top;">O_RDONLY</td>
- <td style="vertical-align: top;">O_RDONLY</td>
- <td style="vertical-align: top;">used to fetch logged data<br>
- </td>
- </tr>
- <tr>
- <td style="vertical-align: top;">MAINTENANCE COMMAND IN<br>
- </td>
- <td style="vertical-align: top;">SPC-4<br>
- </td>
- <td style="vertical-align: top;">O_RDONLY<br>
- </td>
- <td style="vertical-align: top;">CAP_SYS_RAW_IO<br>
- <br>
- </td>
- <td style="vertical-align: top;">various "REPORT ..." commands
-such as REPORT SUPPORTED OPERATION CODES in here<br>
- </td>
- </tr>
- <tr>
- <td style="vertical-align: top;">MODE SELECT (6+10)<br>
- </td>
- <td style="vertical-align: top;">SPC-4<br>
- </td>
- <td style="vertical-align: top;">O_RDWR</td>
- <td style="vertical-align: top;">O_RDWR</td>
- <td style="vertical-align: top;">Used to change SCSI device
-metadata<br>
- </td>
- </tr>
- <tr>
- <td style="vertical-align: top;">MODE SENSE (6+10)<br>
- </td>
- <td style="vertical-align: top;">SPC-4<br>
- </td>
- <td style="vertical-align: top;">O_RDONLY </td>
- <td style="vertical-align: top;">O_RDONLY </td>
- <td style="vertical-align: top;">Used to read SCSI device metadata<br>
- </td>
- </tr>
- <tr>
- <td style="vertical-align: top;">PAUSE RESUME</td>
- <td style="vertical-align: top;">MMC-4</td>
- <td style="vertical-align: top;">O_RDWR</td>
- <td style="vertical-align: top;">O_RDONLY</td>
- <td style="vertical-align: top;"><br>
- </td>
- </tr>
- <tr>
- <td style="vertical-align: top;">PLAY AUDIO (10)<br>
- </td>
- <td style="vertical-align: top;">MMC-4<br>
- </td>
- <td style="vertical-align: top;">O_RDWR</td>
- <td style="vertical-align: top;">O_RDONLY</td>
- <td style="vertical-align: top;"><br>
- </td>
- </tr>
- <tr>
- <td style="vertical-align: top;">PLAY AUDIO MSF<br>
- </td>
- <td style="vertical-align: top;">MMC-4<br>
- </td>
- <td style="vertical-align: top;">O_RDWR</td>
- <td style="vertical-align: top;">O_RDONLY</td>
- <td style="vertical-align: top;"><br>
- </td>
- </tr>
- <tr>
- <td style="vertical-align: top;">PLAY AUDIO TI<br>
- </td>
- <td style="vertical-align: top;">??<br>
- </td>
- <td style="vertical-align: top;">O_RDWR</td>
- <td style="vertical-align: top;">O_RDONLY</td>
- <td style="vertical-align: top;">opcode 0x48, unassigned to&nbsp;
-any spec in SPC-4<br>
- </td>
- </tr>
- <tr>
- <td style="vertical-align: top;">PLAY CD</td>
- <td style="vertical-align: top;">MMC-2<br>
- </td>
- <td style="vertical-align: top;">O_RDWR</td>
- <td style="vertical-align: top;">O_RDONLY</td>
- <td style="vertical-align: top;">old, now SPARE IN in SPC-4<br>
- </td>
- </tr>
- <tr>
- <td style="vertical-align: top;">PREVENT ALLOW MEDIUM REMOVAL<br>
- </td>
- <td style="vertical-align: top;">SPC-4, MMC-4<br>
- </td>
- <td style="vertical-align: top;">O_RDWR</td>
- <td style="vertical-align: top;">O_RDWR</td>
- <td style="vertical-align: top;">sd, st and cdrom drivers use
-this internally<br>
- </td>
- </tr>
- <tr>
- <td style="vertical-align: top;">READ (6+10+12+16)<br>
- </td>
- <td style="vertical-align: top;">SBC-3<br>
- </td>
- <td style="vertical-align: top;">O_RDONLY</td>
- <td style="vertical-align: top;">O_RDONLY</td>
- <td style="vertical-align: top;"><br>
- </td>
- </tr>
- <tr>
- <td style="vertical-align: top;">READ BUFFER<br>
- </td>
- <td style="vertical-align: top;">SPC-4<br>
- </td>
- <td style="vertical-align: top;">O_RDONLY</td>
- <td style="vertical-align: top;">O_RDONLY</td>
- <td style="vertical-align: top;"><br>
- </td>
- </tr>
- <tr>
- <td style="vertical-align: top;">READ BUFFER CAPACITY<br>
- </td>
- <td style="vertical-align: top;">MMC-4<br>
- </td>
- <td style="vertical-align: top;">O_RDWR</td>
- <td style="vertical-align: top;">O_RDONLY</td>
- <td style="vertical-align: top;"><br>
- </td>
- </tr>
- <tr>
- <td style="vertical-align: top;">READ CAPACITY(10)<br>
- </td>
- <td style="vertical-align: top;">SBC-3, MMC-4<br>
- </td>
- <td style="vertical-align: top;">O_RDONLY</td>
- <td style="vertical-align: top;">O_RDONLY</td>
- <td style="vertical-align: top;"><br>
- </td>
- </tr>
- <tr>
- <td style="vertical-align: top;">READ CAPACITY(16)<br>
- </td>
- <td style="vertical-align: top;">SBC-3,<br>
-MMC-4<br>
- </td>
- <td style="vertical-align: top;">O_RDONLY<br>
- </td>
- <td style="vertical-align: top;">CAP_SYS_RAW_IO<br>
- </td>
- <td style="vertical-align: top;">within SERVICE ACTION IN
-command. Needed for RAIDs larger than 2 TB<br>
- </td>
- </tr>
- <tr>
- <td style="vertical-align: top;">READ CD<br>
- </td>
- <td style="vertical-align: top;">MMC-4<br>
- </td>
- <td style="vertical-align: top;">O_RDWR</td>
- <td style="vertical-align: top;">O_RDONLY</td>
- <td style="vertical-align: top;"><br>
- </td>
- </tr>
- <tr>
- <td style="vertical-align: top;">READ CD MSF<br>
- </td>
- <td style="vertical-align: top;">MMC-4<br>
- </td>
- <td style="vertical-align: top;">O_RDWR</td>
- <td style="vertical-align: top;">O_RDONLY</td>
- <td style="vertical-align: top;"><br>
- </td>
- </tr>
- <tr>
- <td style="vertical-align: top;">READ CDVD CAPACITY<br>
- </td>
- <td style="vertical-align: top;">SBC-3, MMC-4<br>
- </td>
- <td style="vertical-align: top;">O_RDONLY</td>
- <td style="vertical-align: top;">O_RDONLY</td>
- <td style="vertical-align: top;">Strange (old ?) name from
-cdrom.h . Actually is READ CAPACITY.<br>
- </td>
- </tr>
- <tr>
- <td style="vertical-align: top;">READ DEFECT (10)<br>
- </td>
- <td style="vertical-align: top;">SBC-3<br>
- </td>
- <td style="vertical-align: top;">O_RDWR<br>
- </td>
- <td style="vertical-align: top;">O_RDONLY</td>
- <td style="vertical-align: top;"><br>
- </td>
- </tr>
- <tr>
- <td style="vertical-align: top;">READ DISC INFO<br>
- </td>
- <td style="vertical-align: top;">MMC-4<br>
- </td>
- <td style="vertical-align: top;">O_RDWR</td>
- <td style="vertical-align: top;">O_RDONLY</td>
- <td style="vertical-align: top;"><br>
- </td>
- </tr>
- <tr>
- <td style="vertical-align: top;">READ DVD STRUCTURE<br>
- </td>
- <td style="vertical-align: top;">MMC-4<br>
- </td>
- <td style="vertical-align: top;">O_RDWR</td>
- <td style="vertical-align: top;">O_RDONLY</td>
- <td style="vertical-align: top;"><br>
- </td>
- </tr>
- <tr>
- <td style="vertical-align: top;">READ FORMAT CAPACITIES<br>
- </td>
- <td style="vertical-align: top;">MMC-4<br>
- </td>
- <td style="vertical-align: top;">O_RDWR</td>
- <td style="vertical-align: top;">O_RDONLY</td>
- <td style="vertical-align: top;"><br>
- </td>
- </tr>
- <tr>
- <td style="vertical-align: top;">READ HEADER<br>
- </td>
- <td style="vertical-align: top;">MMC-2<br>
- </td>
- <td style="vertical-align: top;">O_RDWR</td>
- <td style="vertical-align: top;">O_RDONLY</td>
- <td style="vertical-align: top;"><br>
- </td>
- </tr>
- <tr>
- <td style="vertical-align: top;">READ LONG (10)<br>
- </td>
- <td style="vertical-align: top;">SBC-3<br>
- </td>
- <td style="vertical-align: top;">O_RDONLY</td>
- <td style="vertical-align: top;">O_RDONLY</td>
- <td style="vertical-align: top;">but not READ LONG (16)<br>
- </td>
- </tr>
- <tr>
- <td style="vertical-align: top;">READ SUB-CHANNEL<br>
- </td>
- <td style="vertical-align: top;">MMC-4<br>
- </td>
- <td style="vertical-align: top;">O_RDWR</td>
- <td style="vertical-align: top;">O_RDONLY</td>
- <td style="vertical-align: top;"><br>
- </td>
- </tr>
- <tr>
- <td style="vertical-align: top;">READ TOC/PMA/ATIP<br>
- </td>
- <td style="vertical-align: top;">MMC-4<br>
- </td>
- <td style="vertical-align: top;">O_RDWR</td>
- <td style="vertical-align: top;">O_RDONLY</td>
- <td style="vertical-align: top;"><br>
- </td>
- </tr>
- <tr>
- <td style="vertical-align: top;">READ TRACK (RZONE) INFO<br>
- </td>
- <td style="vertical-align: top;">MMC-4<br>
- </td>
- <td style="vertical-align: top;">O_RDWR</td>
- <td style="vertical-align: top;">O_RDONLY</td>
- <td style="vertical-align: top;">In MMC-4 called READ TRACK INFO<br>
- </td>
- </tr>
- <tr>
- <td style="vertical-align: top;">RECEIVE DIAGNOSTIC<br>
- </td>
- <td style="vertical-align: top;">SPC-4<br>
- </td>
- <td style="vertical-align: top;">O_RDONLY</td>
- <td style="vertical-align: top;">CAP_SYS_RAW_IO</td>
- <td style="vertical-align: top;">the SES command set uses this
-command a lot. An SES device is only accessible via an sg device node<br>
- </td>
- </tr>
- <tr>
- <td style="vertical-align: top;">REPAIR (RZONE) TRACK<br>
- </td>
- <td style="vertical-align: top;">MMC-4</td>
- <td style="vertical-align: top;">O_RDWR</td>
- <td style="vertical-align: top;">O_RDWR</td>
- <td style="vertical-align: top;"><br>
- </td>
- </tr>
- <tr>
- <td style="vertical-align: top;">REPORT KEY<br>
- </td>
- <td style="vertical-align: top;">MMC-4<br>
- </td>
- <td style="vertical-align: top;">O_RDWR</td>
- <td style="vertical-align: top;">O_RDONLY</td>
- <td style="vertical-align: top;"><br>
- </td>
- </tr>
- <tr>
- <td style="vertical-align: top;">REPORT LUNS<br>
- </td>
- <td style="vertical-align: top;">SPC-4<br>
- </td>
- <td style="vertical-align: top;">O_RDONLY</td>
- <td style="vertical-align: top;">CAP_SYS_RAW_IO</td>
- <td style="vertical-align: top;">mandatory since SPC-3<br>
- </td>
- </tr>
- <tr>
- <td style="vertical-align: top;">REQUEST SENSE<br>
- </td>
- <td style="vertical-align: top;">SPC-4<br>
- </td>
- <td style="vertical-align: top;">O_RDONLY</td>
- <td style="vertical-align: top;">O_RDONLY</td>
- <td style="vertical-align: top;">has uses other than those
-displaced by autosense<br>
- </td>
- </tr>
- <tr>
- <td style="vertical-align: top;">RESERVE (RZONE) TRACK<br>
- </td>
- <td style="vertical-align: top;">MMC-4<br>
- </td>
- <td style="vertical-align: top;">O_RDWR</td>
- <td style="vertical-align: top;">O_RDWR</td>
- <td style="vertical-align: top;"><br>
- </td>
- </tr>
- <tr>
- <td style="vertical-align: top;">SCAN<br>
- </td>
- <td style="vertical-align: top;">MMC-4<br>
- </td>
- <td style="vertical-align: top;">O_RDWR</td>
- <td style="vertical-align: top;">O_RDONLY</td>
- <td style="vertical-align: top;"><br>
- </td>
- </tr>
- <tr>
- <td style="vertical-align: top;">SEEK<br>
- </td>
- <td style="vertical-align: top;">MMC-4</td>
- <td style="vertical-align: top;">O_RDWR</td>
- <td style="vertical-align: top;">O_RDONLY</td>
- <td style="vertical-align: top;"><br>
- </td>
- </tr>
- <tr>
- <td style="vertical-align: top;">SEND CUE SHEET<br>
- </td>
- <td style="vertical-align: top;">MMC-4<br>
- </td>
- <td style="vertical-align: top;">O_RDWR</td>
- <td style="vertical-align: top;">O_RDWR</td>
- <td style="vertical-align: top;"><br>
- </td>
- </tr>
- <tr>
- <td style="vertical-align: top;">SEND DVD STRUCTURE<br>
- </td>
- <td style="vertical-align: top;">MMC-4<br>
- </td>
- <td style="vertical-align: top;">O_RDWR</td>
- <td style="vertical-align: top;">O_RDWR</td>
- <td style="vertical-align: top;"><br>
- </td>
- </tr>
- <tr>
- <td style="vertical-align: top;">[SEND EVENT]<br>
- </td>
- <td style="vertical-align: top;">MMC-2<br>
- </td>
- <td style="vertical-align: top;"><br>
- </td>
- <td style="vertical-align: top;">O_RDWR</td>
- <td style="vertical-align: top;">cdrom.h associates opcode 0xa2
-but MMC-2 uses opcode 0x5d ??<br>
- </td>
- </tr>
- <tr>
- <td style="vertical-align: top;">SEND KEY<br>
- </td>
- <td style="vertical-align: top;">MMC-4<br>
- </td>
- <td style="vertical-align: top;">O_RDWR</td>
- <td style="vertical-align: top;">O_RDWR</td>
- <td style="vertical-align: top;"><br>
- </td>
- </tr>
- <tr>
- <td style="vertical-align: top;">SEND OPC INFORMATION<br>
- </td>
- <td style="vertical-align: top;">MMC-4<br>
- </td>
- <td style="vertical-align: top;">O_RDWR</td>
- <td style="vertical-align: top;">O_RDWR</td>
- <td style="vertical-align: top;"><br>
- </td>
- </tr>
- <tr>
- <td style="vertical-align: top;">SERVICE ACTION IN<br>
- </td>
- <td style="vertical-align: top;">SPC-4, SBC-3<br>
- </td>
- <td style="vertical-align: top;">O_RDONLY</td>
- <td style="vertical-align: top;">CAP_SYS_RAW_IO</td>
- <td style="vertical-align: top;">READ CAPACITY (16) service
-action in here<br>
- </td>
- </tr>
- <tr>
- <td style="vertical-align: top;">SET CD SPEED<br>
- </td>
- <td style="vertical-align: top;">MMC-4<br>
- </td>
- <td style="vertical-align: top;">O_RDWR</td>
- <td style="vertical-align: top;">O_RDWR</td>
- <td style="vertical-align: top;">cdrom.h calls this SET SPEED<br>
- </td>
- </tr>
- <tr>
- <td style="vertical-align: top;">SET STREAMING<br>
- </td>
- <td style="vertical-align: top;">MMC-4<br>
- </td>
- <td style="vertical-align: top;">O_RDWR</td>
- <td style="vertical-align: top;">O_RDWR</td>
- <td style="vertical-align: top;"><br>
- </td>
- </tr>
- <tr>
- <td style="vertical-align: top;">START STOP UNIT<br>
- </td>
- <td style="vertical-align: top;">SBC-3, MMC-4<br>
- </td>
- <td style="vertical-align: top;">O_RDWR</td>
- <td style="vertical-align: top;">O_RDONLY</td>
- <td style="vertical-align: top;">hmm<br>
- </td>
- </tr>
- <tr>
- <td style="vertical-align: top;">STOP PLAY/SCAN<br>
- </td>
- <td style="vertical-align: top;">MMC-4</td>
- <td style="vertical-align: top;">O_RDWR</td>
- <td style="vertical-align: top;">O_RDONLY</td>
- <td style="vertical-align: top;"><br>
- </td>
- </tr>
- <tr>
- <td style="vertical-align: top;">SYNCHRONIZE CACHE</td>
- <td style="vertical-align: top;">SBC-3, MMC-4<br>
- </td>
- <td style="vertical-align: top;">O_RDWR</td>
- <td style="vertical-align: top;">O_RDWR</td>
- <td style="vertical-align: top;">cdrom.h calls this FLUSH CACHE<br>
- </td>
- </tr>
- <tr>
- <td style="vertical-align: top;">TEST UNIT READY<br>
- </td>
- <td style="vertical-align: top;">SPC-4<br>
- </td>
- <td style="vertical-align: top;">O_RDONLY</td>
- <td style="vertical-align: top;">O_RDONLY</td>
- <td style="vertical-align: top;">All SCSI devices should respond
-to this command</td>
- </tr>
- <tr>
- <td style="vertical-align: top;">VERIFY (10+16)<br>
- </td>
- <td style="vertical-align: top;">SBC-3, MMC-4<br>
- </td>
- <td style="vertical-align: top;">O_RDWR</td>
- <td style="vertical-align: top;">O_RDONLY</td>
- <td style="vertical-align: top;"><br>
- </td>
- </tr>
- <tr>
- <td style="vertical-align: top;">WRITE (6+10+12+16)</td>
- <td style="vertical-align: top;">SBC-3<br>
- </td>
- <td style="vertical-align: top;">O_RDWR</td>
- <td style="vertical-align: top;">O_RDWR</td>
- <td style="vertical-align: top;"><br>
- </td>
- </tr>
- <tr>
- <td style="vertical-align: top;">WRITE LONG (10+16)<br>
- </td>
- <td style="vertical-align: top;">SBC-3<br>
- </td>
- <td style="vertical-align: top;">O_RDWR</td>
- <td style="vertical-align: top;">O_RDWR</td>
- <td style="vertical-align: top;"><br>
- </td>
- </tr>
- <tr>
- <td style="vertical-align: top;">WRITE VERIFY (10+16)<br>
- </td>
- <td style="vertical-align: top;">SBC-3, MMC-4<br>
- </td>
- <td style="vertical-align: top;">O_RDWR</td>
- <td style="vertical-align: top;">O_RDWR</td>
- <td style="vertical-align: top;">only WRITE VERIFY(10) is in MMC-4<br>
- </td>
- </tr>
- </tbody>
-</table>
-<br>
-Any other SCSI command (opcode) not mentioned for the sg driver needs
-O_RDWR. Any other SCSI command (opcode) not mentioned for the block
-layer SG_IO ioctl needs a user with CAP_SYS_RAW_IO capability. All
-"block" SG_IO ioctl calls on st device nodes need a user with
-CAP_SYS_RAW_IO capability. If a
-user does not have sufficient permissions to execute a SCSI command via
-the SG_IO ioctl then the system calls fails (i.e. no SCSI command is
-sent) and errno is set to EPERM (operation not permitted).<br>
-<br>
-Both the sg driver and the block layer SG_IO code use internal tables
-to enforce the permissions shown in the above table (allow_ops and
-cmd_type [safe_for_read and safe_for_write] respectively). This
-technique doesn't scale well, since more advanced command sets (e.g.
-OSD) use service actions (and one opcode: 0x7f in the case of OSD).
-There may also be overlap in opcode usage between command sets, for
-example between SBC, MMC and SSC.<br>
-<h2><a class="mozTocH2" name="mozTocId154063"></a>Maximum transfer size
-per command</h2>
-The largest amount of data that can be transferred by a single SCSI
-command is often a concern. Various SCSI command sets (e.g. SBC-3 for
-disk
-READs and WRITEs, SSC-3 for tape READs and WRITEs, and SPC-4 for
-READ+WRITE BUFFER) allow very large
-data transfer sizes but Linux is not so accommodating. The Host Bus
-Adapter (HBA)
-could have transfer size limits as could the transport and finally the
-SCSI device
-itself. In the latter case SBC-3 defines a "Block Limits" Vital Product
-Data (VPD) while SSC has the READ BLOCK LIMITS SCSI command. SBC-3's
-optional Block Limits VPD page contains both maximum and optimal
-counts. In the author's opinion that latter distinction is very
-important: the block susbsystem should try and use optimal sizes while
-pass through users should only be constrained by maximum sizes. Also if
-a pass through user exceeds a maximum transfer size imposed by a SCSI
-device, then the device can report an error. There is an
-underlying assumption that the applications using a pass through
-interface know what they are doing, or at least know more than the
-various kernel susbsystems. On the other hand, the kernel has the
-responsibility to allocate critical shared resources such as memory.<br>
-<br>
-In the past, Linux used a single, "big-enough", block of memory for the
-source or destination of large data transfers. Then scatter-gather
-lists where added to break transfers up into smaller (often "page" size
-(4 KB on i386 architecture)) chunks which made memory management easier
-for the kernel. Now, in the lk 2.6 series, the single block of memory
-option is being phased out. <br>
-<br>
-The Linux SCSI subsystem imposes a 128
-element limit on scatter gather lists via its SCSI_MAX_PHYS_SEGMENTS
-define. The way various memory pools are allocated by the linux SCSI
-subsystem, SCSI_MAX_PHYS_SEGMENTS could be increased to 256. Associated
-with each type of HBA there is normally a low level driver (LLD). Each
-LLD can further limit the maximum number of elements with
-the scsi_host_template::sg_tablesize field. Prior to lk 2.6.16 the sg
-and
-st drivers used the .sg_tablesize field only, since lk 2.6.16 those
-drivers are also constrained by SCSI_MAX_PHYS_SEGMENTS. This leads to a
-potential halving of the maximum transfer size. Many LLDs set the
-.sg_tablesize field to SG_ALL (which is 255) but they may as well set
-that field to 256 unless the HBA hardware has a constraint.<br>
-<br>
-User space
-memory may be allocated as the source and/or destination for DMA
-transfers from
-the HBA (i.e. direct IO). Even if the user space allocated a large
-amount of memory
-with a single malloc(), the HBA DMA element typically has a different
-view of
-memory. This view may well contain many "page" size discontinuous
-pieces. This has the
-effect of using up, or perhaps exhausting, scatter-gather elements.<br>
-<br>
-The sg driver attempts to build scatter gather lists with each element
-up to SG_SCATTER_SZ bytes large. This define is found in
-include/scsi/sg.h
-and has been set to 32 KB for some years. That is 8 times the page size
-(of 4 KB) on the i386 architecture. Some users who need really
-large transfers increase this define (and it is best to keep it a power
-of 2). However since lk 2.6.16 another limit comes into play: the
-MAX_SEGMENT_SIZE define which is set to 64 KB. MAX_SEGMENT_SIZE is a
-default and can be overridden by the LLD calling
-blk_queue_max_segment_size().<br>
-<br>
-In lk 2.6.16 two further LLD parameters
-come into play even when the sg (and st) driver is used. These are
-scsi_host_template::max_sectors and scsi_host_template::use_clustering
-.&nbsp; <br>
-<br>
-The .max_sectors setting in the LLD is the maximum number of 512 byte
-sectors allowed in a single SCSI command's scatter gather lists (for
-data transfers). Yes, that is a strange limit when trying to send a
-SCSI
-WRITE BUFFER command to upload firmware. Sysfs makes the LLD's
-.max_sectors setting visible (converted to kilobytes) in
-/sys/block/sd&lt;x&gt;/queue/max_hw_sectors_kb . The maximum allowable
-value in a LLD's .max_sector seems to be 65535 (0xffff in hexadecimal).
-This limits the maximum transfer size to (32*1024*1024 - 512) bytes,
-assuming other limitations have been overcome. [The 65535 sector limit
-is because Scsi_Host::max_sectors has type "unsigned short". Hopefully
-this type is expanded to "int" in the future (or removed).]<br>
-<br>
-The .use_clustering field should be set to ENABLE_CLUSTERING . If not,
-the block subsystem rebuilds the scatter gather list it gets from the
-sg driver with page size (e.g. 4 KB) elements. [Actually is does that
-anyway, but
-when ENABLE_CLUSTERING is set, it coalesces them again!]<br>
-<br>
-<h2><a class="mozTocH2" name="mozTocId267334"></a>Conclusion</h2>
-In some situations, sending commands via the SG_IO ioctl may interfere
-with a higher level driver's use of a device. Users of the SG_IO ioctl
-should be aware that they are using a powerful, but low level facility,
-and write code accordingly. An example of this would be a utility to
-perform self tests on a disk: "background" self tests should be
-preferred over "foreground" self tests if there is a chance the
-computer may be using a file system on that disk at the time. Even a
-short foreground self test may take up to two minutes which is a long
-time to lock out a file system.<br>
-<br>
-<p>Return to <a href="index.html">main</a> page. </p>
-<center>
-<p>Last updated: 2nd Aprl 2006<br>
-<br>
-</p>
-</center>
-</body>
-</html>
diff --git a/doc/tools.html b/doc/tools.html
deleted file mode 100644
index 71c60b3e..00000000
--- a/doc/tools.html
+++ /dev/null
@@ -1,318 +0,0 @@
-<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
-<html>
-<head>
- <title>Storage and SCSI tools</title>
- <meta http-equiv="Content-Type"
- content="text/html; charset=iso-8859-1">
- <meta name="keywords" content="tool, storgae, SCSI, linux">
- <meta name="GENERATOR"
- content="Mozilla/4.79 [en] (X11; U; Linux 2.5.31 i686) [Netscape]">
-</head>
-<body alink="#ff0000" background="paper.jpg" bgcolor="#ffffff"
- link="#0000ff" text="#000000" vlink="#000080">
-<center>
-<h1><a class="mozTocH1" name="mozTocId697451"></a> Tools for storage
-and SCSI<br>
-</h1>
-</center>
-<a href="#intro"></a>
-<ol id="mozToc">
-<!--mozToc h1 1 h2 2 h3 3 h4 4 h5 5 h6 6-->
- <li><a href="#mozTocId697451"> Tools for storage
-and SCSI
- </a>
- <ol>
- <li><a href="#mozTocId746876"> Introduction</a></li>
- <li><a href="#mozTocId520511">blktool</a></li>
- <li><a href="#mozTocId212850"> ddrescue</a></li>
- <li><a href="#mozTocId264328"> devlabel</a></li>
- <li><a href="#mozTocId668788"> dt</a></li>
- <li><a href="#mozTocId231383">fio</a></li>
- <li><a href="#mozTocId851510">hdparm</a></li>
- <li><a href="#mozTocId777351">lsscsi</a></li>
- <li><a href="#mozTocId380766"> mapscsi</a></li>
- <li><a href="#mozTocId295637">plscsi</a></li>
- <li><a href="#mozTocId325127">safte-monitor</a></li>
- <li><a href="#mozTocId222172">scsiadd</a></li>
- <li><a href="#mozTocId550034"> scsidev</a></li>
- <li><a href="#mozTocId520455">scsi_id</a></li>
- <li><a href="#mozTocId673853">scsiinfo</a></li>
- <li><a href="#mozTocId108175"> scsimap</a></li>
- <li><a href="#mozTocId974127">scsirastools</a></li>
- <li><a href="#mozTocId348388"> scu</a></li>
- <li><a href="#mozTocId382975">sdparm</a></li>
- <li><a href="#mozTocId783871">SeaTools</a></li>
- <li><a href="#mozTocId847247">sg3_utils</a></li>
- <li><a href="#mozTocId705237">sg_utils</a></li>
- <li><a href="#mozTocId535090">smartmontools</a></li>
- <li><a href="#mozTocId143073"> smartsuite</a></li>
- <li><a href="#mozTocId53551">smp_utils</a></li>
- <li><a href="#mozTocId440267">spew</a></li>
- <li><a href="#mozTocId45065">testdisk</a></li>
- <li><a href="#mozTocId708282">udev</a></li>
- <li><a href="#mozTocId728109">Conclusion</a></li>
- </ol>
- </li>
-</ol>
-<h2><a class="mozTocH2" name="mozTocId746876"></a> Introduction</h2>
-The page is a resource for those looking for tools for storage devices
-with an emphasis on SCSI devices. These tools are user space prorams
-rather than kernel drivers. The entries are brief abstracts with links
-to pages that have more information. The entries are in alphabetical
-order.<br>
-<h2><a class="mozTocH2" name="mozTocId520511"></a>blktool</h2>
-This is a utility for fetching and changing parameters in the linux
-block susbsystem. It supports ATA and SCSI disks with some support for
-cd/dvd drives. See this <a
- href="http://sourceforge.net/projects/gkernel/">site</a> . For finer
-grain control of SCSI devices (and SATA(PI) devices connected via a
-SCSI
-transport) see the <a href="#mozTocId382975">sdparm</a> utility below.<br>
-<h2><a class="mozTocH3" name="mozTocId212850"></a> ddrescue</h2>
-This is another utility from&nbsp; Kurt Garloff &lt;garloff@suse.de&gt;
-for rescuing damaged media. It is a variant of dd that will continue
-passed errors on the input file. It is applicable to any device that
-can be read by dd (e.g. IDE and SCSI disks, cds and tapes). For more
-information see: <a href="http://www.garloff.de/kurt/linux/ddrescue">www.garloff.de/kurt/linux/ddrescue</a><br>
-<br>
-There is also a GNU program of the same name that has a similar
-function. See <a href="http://ftp.gnu.org/gnu/ddrescue/">
-http://ftp.gnu.org/gnu/ddrescue/</a> . John Gilmour has some
-information on disk recovery utilities at&nbsp; <a
- href="http://www.toad.com/gnu/sysadmin/">http://www.toad.com/gnu/sysadmin/</a>
-.<br>
-<h2><a class="mozTocH3" name="mozTocId264328"></a> devlabel</h2>
-Devlabel is "a small userspace app which maps symlinks to underlying
-disk names. It uses [INQUIRY VPD] Page83/Page80 data to track the
-true locations of disks even if their hd/sd name changes and simply
-updates the symlink to point to the right place." Sysfs support for the
-lk 2.6 series and support for multi-path configurations is on the
-author's "to do" list. See <a href="http://www.lerhaupt.com/linux.html">http://www.lerhaupt.com/linux.html</a>
-. Probably better to use scsi_id/udev in the lk 2.6 series kernels<br>
-<h2><a class="mozTocH3" name="mozTocId668788"></a> dt</h2>
-The Data Test (DT) program is modelled on dd's syntax but <b>dt </b>can
-do a lot more than sequential copies. It is a comprehensive data test
-program for SCSI devices such as disks, tapes and cdrom/dvds. It is
-available on several Unix platforms (and NT), and its source is
-available (unlike its stable mate <b>scu</b> discussed earlier).
-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. dt is written by Robin
-T. Miller &lt;Robin.Miller at netapp dot com&gt;<br>
-<h2><a class="mozTocH2" name="mozTocId231383"></a>fio</h2>
-This utility tests the performance of Linux/Unix block devices or file<span
- style="font-family: monospace;"> </span>systems. <a
- href="http://brick.kernel.dk/snaps/">fio</a> is a tool that will spawn
-a number of threads doing a<span style="font-family: monospace;"> </span>particular
-type of io action as specified by the user in a defined job<span
- style="font-family: monospace;"> </span>file. <a
- href="http://brick.kernel.dk/snaps/">fio</a> supports various types of
-io backends, such as regular sync<span style="font-family: monospace;">
-</span>io, linux aio, posix aio, and sg v3 io (SG_IO and queued
-read/write).<span style="font-family: monospace;"> </span>fio can be
-used for both performance testing, data/media verification,<span
- style="font-family: monospace;"> </span>etc.<br>
-<h2><a class="mozTocH2" name="mozTocId851510"></a>hdparm</h2>
-This utility gets and sets ATA drive parameters under Linux. Can also
-get transport parameters for ATAPI devices. There is also limited
-support for SCSI devices. See this <a
- href="http://sourceforge.net/projects/hdparm/">site</a> . Overlaps in
-functionality with blktool (see <a href="#mozTocId520511">above</a> ).<br>
-<h2><a class="mozTocH2" name="mozTocId777351"></a>lsscsi</h2>
-This utility lists SCSI devices (or hosts) that are present in the
-linux kernel 2.6 series. It is a passive tools in the sense that it
-"data mines" the linux sysfs file system rather than attempting to
-query devices. See <a href="../scsi/lsscsi.html">lsscsi</a>&nbsp; .<br>
-<h2><a class="mozTocH3" name="mozTocId380766"></a> mapscsi</h2>
-Michael Clark &lt;michael@metaparadigm.com&gt; describes his utility
-thus: "mapscsi is a small utility that creates a consistent mapping
-to Linux scsi devices. mapscsi achieves this by creating symbolic
-links to linux scsi disk devices after scanning all scsi disk devices,
-finding out their host, channel, id, lun, pci location (if available),
-Fibre Channel world wide node and port names, loop and port ids (with
-qla2x00 v4.46.5 driver) vendor, product and serial number details and
-using this information plus a mapping rules file containing device
-templates to dynamically create link names". For more information see: <a
- href="http://gort.metaparadigm.com/mapscsi">http://gort.metaparadigm.com/mapscsi</a>
-. In the linux 2.6 series the scsi_id/udev pair is probably appropriate.<br>
-<h2><a class="mozTocH3" name="mozTocId295637"></a>plscsi</h2>
-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>
-<h2><a class="mozTocH3" name="mozTocId325127"></a>safte-monitor</h2>
-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>
-<h2><a class="mozTocH2" name="mozTocId222172"></a>scsiadd</h2>
-This utility permits a user to add and remove scsi devices from the
-Linux scsi subsystem on the
-fly. See scsiadd on this <a href="http://llg.cubic.org/tools/">page</a>
-.
-<h2><a class="mozTocH3" name="mozTocId550034"></a> scsidev</h2>
-Kurt Garloff &lt;garloff@suse.de&gt; describes this utility thus: "This
-program scans the SCSI bus and creates device nodes in /dev/scsi/,
-which have a naming corresponding to their SCSI IDs and LUNs, just
-like with devfs. (The devfs has no notion of host adapter IDs,
-scsidev is better here.) Furthermore, the devices are inquired to
-tell their names and serial numbers. Those can be compared with the
-entries in a database /etc/scsi.alias and device nodes corresponding
-to these entries are being built. So,this will even work if you change
-the SCSI IDs of a device, where the devfs approach would fail". For
-more information see: <a
- href="http://www.garloff.de/kurt/linux/scsidev">www.garloff.de/kurt/linux/scsidev</a>
-. He also has the useful <b>rescan-scsi-bus.sh</b> script at the same
-location.<br>
-<h2><a class="mozTocH2" name="mozTocId520455"></a>scsi_id</h2>
-This utility is used by various linux 2.6 series distributions together
-udev to dynamically add and remove scsi device nodes. See <a
- href="http://www.kernel.org/pub/linux/utils/kernel/hotplug/udev.html">udev</a>
-'s page.<br>
-<h2><a class="mozTocH3" name="mozTocId673853"></a>scsiinfo</h2>
-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. <span style="font-weight: bold;">sdparm</span> can do most of
-the things that scsiinfo and sginfo can.<br>
-<h2><a class="mozTocH3" name="mozTocId108175"></a> scsimap</h2>
-Steve Cameron &lt;smcameron@yahoo.com&gt; has the following description
-at his site:
-<p>This is a utility to create and maintain symbolic links mapping a
-predictable set of names to the rather unpredictable names used by
-linux for disk devices. For example, you might map: <br>
-<tt>/dev/mydisk1 -&gt; /dev/sda1</tt> <br>
-<tt>/dev/mydisk2 -&gt; /dev/sdb1</tt> <br>
-<tt>/dev/mydisk3 -&gt; /dev/sdc1</tt> <br>
-If you removed the disk corresponding to /dev/sdb1, then on reboot,
-/dev/sdc1 will become /dev/sdb1, and /dev/sdc1 will be gone. and your
-fstab will be wrong, etc. (Especially problematic on a SAN). <b>scsimap</b>
-will maintain the mapping so that after the reboot, /dev/mydisk3 -&gt;
-will point to /dev/sdb1 and /dev/mydisk2 will be gone. scsimap also
-handles later generation Compaq array controllers (those which use
-the cciss driver.) </p>
-<p>See: <a href="http://www.geocities.com/smcameron">www.geocities.com/smcameron</a>
-.<br>
-</p>
-<h2><a class="mozTocH3" name="mozTocId974127"></a>scsirastools</h2>
-"This project includes changes that enhance the Reliability,
-Availability and Serviceability (RAS) of the drivers that are
-commonly used in a Linux software RAID-1 configuration. Other
-efforts have been made to enable various common hardware RAID
-adapters and their drivers on Linux." See <a
- href="http://scsirastools.sourceforge.net/">http://scsirastools.sourceforge.net</a>
-. The package contains some low level scsi utilities including <b>sgdskfl</b>
-to load disk firmware, <b>sgmode</b> to get and set mode pages, <b>sgdefects</b>
-to read primary and grown defect lists and <b>sgdiag</b> to perform
-format and other test functions.
-<h2><a class="mozTocH3" name="mozTocId348388"></a> scu</h2>
-The SCSI Command Utility (SCU) implements various SCSI commands
-necessary for normal maintenance and diagnostics of SCSI
-peripherals. Some of its features include: formatting, scanning for
-(and reassigning) bad blocks, downloading new firmware, executing
-diagnostics and obtaining performance information. It is available on
-several Unix platforms (and NT), however it is only currently available
-in binary form. 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>
-for more details. scu is written by Robin
-T. Miller &lt;Robin.Miller at netapp dot com&gt;
-<h2><a class="mozTocH2" name="mozTocId382975"></a>sdparm</h2>
-This utility allows information from SCSI mode pages to be fetched and
-potentially modified. <a href="sdparm.html">sdparm</a> also decodes
-Vital Product Data pages. It was written for the Linux 2.4 and 2.6
-series and has been ported to FreeBSD and Tru64.<br>
-<h2><a class="mozTocH3" name="mozTocId783871"></a>SeaTools</h2>
-SeaTools is a freely available (binary, not source) utility for disk
-diagnostics from Seagate which is a disk manufacturer. It can be found
-at <a href="http://www.seagate.com/">http://www.seagate.com</a> under
-the support tab. They have both a command line and a graphical utility.
-&nbsp;Some of the facilities will work on any SCSI disks while others
-are Seagate specific. Self tests, mode page settings and formats (to
-different block sizes) are amongst the facilities available. Other disk
-vendors have similar tools.<br>
-<h2><a class="mozTocH2" name="mozTocId847247"></a>sg3_utils</h2>
-This is a package of utilities that send SCSI commands and decodes the
-response. It also includes slightly higher level utilities such as
-sg_dd which permits a finer level of control over SCSI devices involved
-in copies compared to the standard Unix dd command. <a
- href="sg3_utils.html">sg3_utils</a> is written for the Linux 2.4 and
-2.6
-series and a large subset of its utilities have been ported to FreeBSD
-and Tru64 .<br>
-<h2><a class="mozTocH2" name="mozTocId705237"></a>sg_utils</h2>
-This package is the precursor of sg3_utils. <a href="uu_index.html">sg_utils</a>
-was written for the Linux 2.2 series with some support for the linux
-2.0 series.<br>
-<br>
-<h2><a class="mozTocH3" name="mozTocId535090"></a>smartmontools</h2>
-This project has taken over from the aforementioned
-smartsuite which is currently not actively maintained. See <a
- href="http://smartmontools.sourceforge.net/">http://smartmontools.sourceforge.net</a>
-. The author is a maintainer of the SCSI component of this project.
-[The lead maintainer is Bruce Allen.]<br>
-<p> </p>
-<h2><a class="mozTocH3" name="mozTocId143073"></a> smartsuite</h2>
-This is a package that supports S.M.A.R.T. capabilities built into
-modern IDE and SCSI-3 disks. Self-Monitoring, Analysis and Reporting
-Technology (S.M.A.R.T.) is described at <a
- href="http://www.pc.ibm.com/us/infobrf/ibsmart.html">www.pc.ibm.com/us/infobrf/ibsmart.html</a>.
-For smartsuite see <a href="http://sourceforge.net/projects/smartsuite">sourceforge.net/projects/smartsuite</a>
-.<br>
-<h2><a class="mozTocH2" name="mozTocId53551"></a>smp_utils</h2>
-This is a package of utilities that sends Serial Attached SCSI (SAS)
-Management Protocol (SMP) requests to a device (typically a SAS
-expander) and decodes the response. See the <a href="smp_utils.html">smp_utils</a>
-page.<br>
-<h2><a class="mozTocH2" name="mozTocId440267"></a>spew<span
- style="font-weight: bold;"></span></h2>
-This utility is used to measure I/O performance of character devices,
-block devices, and regular files. It can also be used to generate high
-I/O loads to stress systems while verifying data integrity. It is easy
-to use and is flexible. No configuration files or complicated
-client/server configurations are needed. Spew also generates its own
-data patterns that are designed to make it easy to find and debug data
-integrity problems. See <a href="http://spew.berlios.de">spew.berlios.de</a>
-.<br>
-<h2><a class="mozTocH2" name="mozTocId45065"></a>testdisk</h2>
-For those occasion when the master boot record is overwritten, <a
- href="http://www.cgsecurity.org/wiki/TestDisk">testdisk</a> can find
-many different types of partitions and help with data recovery.<br>
-<h2><a class="mozTocH2" name="mozTocId708282"></a>udev</h2>
-<a href="http://www.kernel.org/pub/linux/utils/kernel/hotplug/udev.html">udev</a>
-provides a dynamic device directory containing only the files for
-actually present devices in linux 2.6 series kernels. It creates or
-removes device node files usually located in the /dev directory,
-or it renames network interfaces.<br>
-<h2><a class="mozTocH2" name="mozTocId728109"></a>Conclusion</h2>
-If readers have corrections or suggested additions to this list of
-tools, please contact the author.<br>
-<br>
-<a href="http://oss.metaparadigm.com/safte-monitor"></a><br>
-<p>Return to <a href="index.html">main</a> page.<br>
-</p>
-<div style="text-align: center;"><a
- href="mailto:dgilbert%20at%20interlog%20dot%20com">Douglas
-Gilbert</a> can
-be emailed at this address (also at dougg at torque dot net). <br>
-</div>
-<center>
-<p>Last updated: 10th January 2007<br>
-<br>
-</p>
-</center>
-</body>
-</html>
diff --git a/examples/Makefile b/examples/Makefile
index f44381d8..91c98242 100644
--- a/examples/Makefile
+++ b/examples/Makefile
@@ -10,7 +10,7 @@ LD = gcc
EXECS = sg_simple1 sg_simple2 sg_simple3 sg_simple4 sg_simple16 \
sg_iovec_tst scsi_inquiry sg_excl sg_sense_test sg_simple5 \
sg__sat_identify sg_sat_chk_power sg_sat_smart_rd_data \
- sg_sat_set_features
+ sg_sat_set_features sg_sat_phy_event
# EXECS = sg_simple1 sg_simple2 sg_simple3 sg_simple4 sg_simple16 \
# sg_simple_aio sg_iovec_tst scsi_inquiry sg_excl
@@ -80,6 +80,9 @@ sg_sat_smart_rd_data: sg_sat_smart_rd_data.o ../sg_lib.o ../sg_io_linux.o
sg_sat_set_features: sg_sat_set_features.o ../sg_lib.o ../sg_io_linux.o
$(LD) -o $@ $(LDFLAGS) $^
+sg_sat_phy_event: sg_sat_phy_event.o ../sg_lib.o ../sg_io_linux.o
+ $(LD) -o $@ $(LDFLAGS) $^
+
install: $(EXECS)
install -d $(INSTDIR)
for name in $^; \
diff --git a/examples/sdiag_sas_p0_cjtpat.txt b/examples/sdiag_sas_p0_cjtpat.txt
index b663ca11..4ea4e56e 100644
--- a/examples/sdiag_sas_p0_cjtpat.txt
+++ b/examples/sdiag_sas_p0_cjtpat.txt
@@ -3,7 +3,7 @@
# given device into CJTPAT (jitter pattern) generation mode.
# N.B. This will turn the receiver off on phy id 0.
#
-# Usage example: 'sg_senddiag -pf -raw=- /dev/sg2 < {this_file}'
+# Usage example: 'sg_senddiag --pf --raw=- /dev/sg2 < {this_file}'
#
3f,6,0,1c,0,1,2,9,
0,0,0,0,0,0,0,0,
diff --git a/examples/sdiag_sas_p1_cjtpat.txt b/examples/sdiag_sas_p1_cjtpat.txt
index f8b09daf..43fe8e8c 100644
--- a/examples/sdiag_sas_p1_cjtpat.txt
+++ b/examples/sdiag_sas_p1_cjtpat.txt
@@ -4,7 +4,7 @@
# See sdiag_sas_p1_stop.txt to turn off this test pattern.
# N.B. This will turn the receiver off on phy id 1.
#
-# Usage example: 'sg_senddiag -pf -raw=- /dev/sg2 < {this_file}'
+# Usage example: 'sg_senddiag --pf --raw=- /dev/sg2 < {this_file}'
#
3f,6,0,1c,1,1,2,9,
0,0,0,0,0,0,0,0,
diff --git a/examples/sdiag_sas_p1_stop.txt b/examples/sdiag_sas_p1_stop.txt
index c4046adb..55b95c34 100644
--- a/examples/sdiag_sas_p1_stop.txt
+++ b/examples/sdiag_sas_p1_stop.txt
@@ -3,7 +3,7 @@
# given device producing a test pattern.
# N.B. This should make phy id 1 usable for SAS protocols again.
#
-# Usage example: 'sg_senddiag -pf -raw=- /dev/sg2 < {this_file}'
+# Usage example: 'sg_senddiag --pf --raw=- /dev/sg2 < {this_file}'
#
3f,6,0,1c,1,0,2,9,
0,0,0,0,0,0,0,0,
diff --git a/examples/sg_io_linux.hh b/examples/sg_io_linux.h
index 459a7cd9..459a7cd9 100644
--- a/examples/sg_io_linux.hh
+++ b/examples/sg_io_linux.h
diff --git a/examples/sg_lib.hh b/examples/sg_lib.h
index e2f826a1..e2f826a1 100644
--- a/examples/sg_lib.hh
+++ b/examples/sg_lib.h
diff --git a/examples/sg_linux_inc.hh b/examples/sg_linux_inc.h
index a5bf738d..a5bf738d 100644
--- a/examples/sg_linux_inc.hh
+++ b/examples/sg_linux_inc.h
diff --git a/examples/sg_persist_tst.sh b/examples/sg_persist_tst.sh
index 95a09a82..f0cd4d38 100755
--- a/examples/sg_persist_tst.sh
+++ b/examples/sg_persist_tst.sh
@@ -2,6 +2,8 @@
# This script is meant as an example of using the sg_persist utility
# in the sg3_utils package. This script works as expected on the
# author's Fujitsu MAM3184 and a Seagate ST373455 disk.
+#
+# Version 1.5 20070314
# N.B. make sure the device name is correct for your environment.
@@ -13,6 +15,30 @@ if [ ! -n "$1" ];then
exit 1
fi
+echo ">>> try to report capabilities:"
+sg_persist -c $1
+res=$?
+case "$res" in
+ 0) ;;
+ 1) echo " syntax error" ;;
+ 2) echo " not ready" ;;
+ 3) echo " medium error" ;;
+ 5) echo " illegal request, report capabilities not supported?" ;;
+ 6) echo " unit attention" ;;
+ 9) echo " illegal request, Persistent Reserve (In) not supported" ;;
+ 11) echo " aborted command" ;;
+ 15) echo " file error with $1 " ;;
+ 20) echo " no sense" ;;
+ 21) echo " recovered error" ;;
+ 33) echo " timeout" ;;
+ 97) echo " response fails sanity" ;;
+ 98) echo " other SCSI error" ;;
+ 99) echo " other error" ;;
+ *) echo " unknown exit status for sg_persist: $res" ;;
+esac
+echo ""
+sleep 1
+
echo ">>> check if any keys are registered:"
sg_persist -k $1
sleep 1
diff --git a/examples/sg_pt.hh b/examples/sg_pt.h
index 2be7b43b..2be7b43b 100644
--- a/examples/sg_pt.hh
+++ b/examples/sg_pt.h
diff --git a/examples/sg_sat_phy_event.c b/examples/sg_sat_phy_event.c
new file mode 100644
index 00000000..a2922857
--- /dev/null
+++ b/examples/sg_sat_phy_event.c
@@ -0,0 +1,350 @@
+/*
+ * Copyright (c) 2006-2007 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>
+#define __STDC_FORMAT_MACROS 1
+#include <inttypes.h>
+#include <sys/ioctl.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#include "sg_lib.h"
+#include "sg_io_linux.h"
+
+/* This program uses a ATA PASS-THROUGH (16) SCSI command defined
+ by SAT to package an ATA READ LOG EXT (2Fh) command to fetch
+ log page 11h. That page contains SATA phy event counters.
+ For SAT see http://www.t10.org [draft prior to standard: sat-r09.pdf]
+ For ATA READ LOG EXT command see ATA-8/ACS at www.t13.org .
+ For SATA phy counter definitions see SATA 2.5 .
+
+ Invocation: sg_sat_phy_event [-v] [-V] <device>
+
+*/
+
+#define SAT_ATA_PASS_THROUGH16 0x85
+#define SAT_ATA_PASS_THROUGH16_LEN 16
+#define SAT_ATA_RETURN_DESC 9 /* ATA Return Descriptor */
+
+#define ATA_READ_LOG_EXT 0x2f
+#define SATA_PHY_EVENT_LPAGE 0x11
+#define READ_LOG_EXT_RESPONSE_LEN 512
+
+#define EBUFF_SZ 256
+
+static char * version_str = "1.00 20070507";
+
+static struct option long_options[] = {
+ {"help", no_argument, 0, 'h'},
+ {"hex", no_argument, 0, 'H'},
+ {"ignore", no_argument, 0, 'i'},
+ {"raw", no_argument, 0, 'r'},
+ {"reset", no_argument, 0, 'R'},
+ {"verbose", no_argument, 0, 'v'},
+ {"version", no_argument, 0, 'V'},
+ {0, 0, 0, 0},
+};
+
+static void usage()
+{
+ fprintf(stderr, "Usage: "
+ "sg_sat_phy_event [--help] [--hex] [--raw] [--reset] [--verbose]\n"
+ " [--version] DEVICE\n"
+ " where:\n"
+ " --help|-h print this usage message then exit\n"
+ " --hex|-H output response in hex bytes, use twice for\n"
+ " hex words\n"
+ " --ignore|-i ignore identifier names, output id value "
+ "instead\n"
+ " --raw|-r output response in binary to stdout\n"
+ " --reset|-R reset counters (after read)\n"
+ " --verbose|-v increase verbosity\n"
+ " --version|-V print version string then exit\n\n"
+ "Sends an ATA READ LOG EXT command via a SAT pass through to "
+ "fetch\nlog page 11h which contains SATA phy event counters\n");
+}
+
+struct phy_event_t {
+ int id;
+ char * desc;
+};
+
+static struct phy_event_t phy_event_arr[] = {
+ {0x1, "Command failed and ICRC error bit set in Error register"},
+ {0x2, "R_ERR(p) response for data FIS"},
+ {0x3, "R_ERR(p) response for device-to-host data FIS"},
+ {0x4, "R_ERR(p) response for host-to-device data FIS"},
+ {0x5, "R_ERR(p) response for non-data FIS"},
+ {0x6, "R_ERR(p) response for device-to-host non-data FIS"},
+ {0x7, "R_ERR(p) response for host-to-device non-data FIS"},
+ {0x8, "Device-to-host non-data FIS retries"},
+ {0x9, "Transition from drive PHYRDY to drive PHYRDYn"},
+ {0xa, "Signature device-to-host register FISes due to COMRESET"},
+ {0xb, "CRC errors within host-to-device FIS"},
+ {0xd, "non CRC errors within host-to-device FIS"},
+ {0xf, "R_ERR(p) response for host-to-device data FIS, CRC"},
+ {0x10, "R_ERR(p) response for host-to-device data FIS, non-CRC"},
+ {0x12, "R_ERR(p) response for host-to-device non-data FIS, CRC"},
+ {0x13, "R_ERR(p) response for host-to-device non-data FIS, non-CRC"},
+ {0xc00, "PM: host-to-device non-data FIS, R_ERR(p) due to collision"},
+ {0xc01, "PM: signature register - device-to-host FISes"},
+ {0xc02, "PM: corrupts CRC propagation of device-to-host FISes"},
+ {0x0, NULL},
+};
+
+static const char * find_phy_desc(int id)
+{
+ const struct phy_event_t * pep;
+
+ for (pep = phy_event_arr; pep->desc; ++pep) {
+ if ((id & 0xfff) == pep->id)
+ return pep->desc;
+ }
+ return NULL;
+}
+
+static void dStrRaw(const char* str, int len)
+{
+ int k;
+
+ for (k = 0 ; k < len; ++k)
+ printf("%c", str[k]);
+}
+
+int main(int argc, char * argv[])
+{
+ int sg_fd, c, k, j, ok, res, id, len, vendor;
+ unsigned char aptCmdBlk[SAT_ATA_PASS_THROUGH16_LEN] =
+ {SAT_ATA_PASS_THROUGH16, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0};
+ sg_io_hdr_t io_hdr;
+ char * device_name = 0;
+ char ebuff[EBUFF_SZ];
+ unsigned char inBuff[READ_LOG_EXT_RESPONSE_LEN];
+ unsigned char sense_buffer[64];
+ int hex = 0;
+ int ignore = 0;
+ int raw = 0;
+ int reset = 0;
+ int verbose = 0;
+ int extend = 0;
+ int chk_cond = 0; /* set to 1 to read register(s) back */
+ int protocol = 4; /* PIO data-in */
+ int t_dir = 1; /* 0 -> to device, 1 -> from device */
+ int byte_block = 1; /* 0 -> bytes, 1 -> 512 byte blocks */
+ int t_length = 2; /* 0 -> no data transferred, 2 -> sector count */
+ const unsigned char * cucp;
+ int ret = 0;
+ unsigned long long ull;
+ const char * cp;
+
+ memset(inBuff, 0, sizeof(inBuff));
+ while (1) {
+ int option_index = 0;
+
+ c = getopt_long(argc, argv, "hHirRvV",
+ long_options, &option_index);
+ if (c == -1)
+ break;
+
+ switch (c) {
+ case 'h':
+ usage();
+ exit(0);
+ case 'H':
+ ++hex;
+ break;
+ case 'i':
+ ++ignore;
+ break;
+ case 'r':
+ ++raw;
+ break;
+ case 'R':
+ ++reset;
+ break;
+ case 'v':
+ ++verbose;
+ break;
+ case 'V':
+ fprintf(stderr, "version: %s\n", version_str);
+ exit(0);
+ default:
+ fprintf(stderr, "unrecognised option code %c [0x%x]\n", c, c);
+ usage();
+ return SG_LIB_SYNTAX_ERROR;
+ }
+ }
+ if (optind < argc) {
+ if (NULL == device_name) {
+ device_name = argv[optind];
+ ++optind;
+ }
+ if (optind < argc) {
+ for (; optind < argc; ++optind)
+ fprintf(stderr, "Unexpected extra argument: %s\n",
+ argv[optind]);
+ usage();
+ return SG_LIB_SYNTAX_ERROR;
+ }
+ }
+ if (0 == device_name) {
+ fprintf(stderr, "no DEVICE name detected\n");
+ usage();
+ return SG_LIB_SYNTAX_ERROR;
+ }
+
+ if ((sg_fd = open(device_name, O_RDWR)) < 0) {
+ snprintf(ebuff, EBUFF_SZ,
+ "sg_sat_phy_event: error opening file: %s", device_name);
+ perror(ebuff);
+ return SG_LIB_FILE_ERROR;
+ }
+
+ /* Prepare SCSI ATA PASS-THROUGH COMMAND (16) command */
+ if (reset > 0)
+ aptCmdBlk[4] = 1; /* features (7:0) */
+ aptCmdBlk[6] = 1; /* sector count */
+ aptCmdBlk[8] = SATA_PHY_EVENT_LPAGE; /* lba_low (7:0) */
+ aptCmdBlk[14] = ATA_READ_LOG_EXT; /* command */
+ aptCmdBlk[1] = (protocol << 1) | extend;
+ aptCmdBlk[2] = (chk_cond << 5) | (t_dir << 3) |
+ (byte_block << 2) | t_length;
+ if (verbose) {
+ fprintf(stderr, " ata pass through(16) cdb: ");
+ for (k = 0; k < SAT_ATA_PASS_THROUGH16_LEN; ++k)
+ fprintf(stderr, "%02x ", aptCmdBlk[k]);
+ fprintf(stderr, "\n");
+ }
+
+ memset(&io_hdr, 0, sizeof(sg_io_hdr_t));
+ io_hdr.interface_id = 'S';
+ io_hdr.cmd_len = sizeof(aptCmdBlk);
+ /* io_hdr.iovec_count = 0; */ /* memset takes care of this */
+ io_hdr.mx_sb_len = sizeof(sense_buffer);
+ io_hdr.dxfer_direction = SG_DXFER_FROM_DEV;
+ io_hdr.dxfer_len = READ_LOG_EXT_RESPONSE_LEN;
+ io_hdr.dxferp = inBuff;
+ io_hdr.cmdp = aptCmdBlk;
+ io_hdr.sbp = sense_buffer;
+ io_hdr.timeout = 20000; /* 20000 millisecs == 20 seconds */
+ /* io_hdr.flags = 0; */ /* take defaults: indirect IO, etc */
+ /* io_hdr.pack_id = 0; */
+ /* io_hdr.usr_ptr = NULL; */
+
+ if (ioctl(sg_fd, SG_IO, &io_hdr) < 0) {
+ perror("sg_sat_phy_event: SG_IO ioctl error");
+ close(sg_fd);
+ return SG_LIB_CAT_OTHER;
+ }
+
+ /* now for the error processing */
+ ok = 0;
+ ret = sg_err_category3(&io_hdr);
+ switch (ret) {
+ case SG_LIB_CAT_CLEAN:
+ ok = 1;
+ break;
+ case SG_LIB_CAT_RECOVERED:
+ if (verbose)
+ sg_chk_n_print3(">>> ATA_16 command", &io_hdr, 1);
+ /* check for ATA Return Descriptor */
+ cucp = sg_scsi_sense_desc_find(io_hdr.sbp, io_hdr.sb_len_wr,
+ SAT_ATA_RETURN_DESC);
+ if (cucp && (cucp[3])) {
+ if (cucp[3] & 0x4) {
+ fprintf(stderr, "error in returned FIS: aborted command\n");
+ break;
+ }
+ }
+ ret = 0;
+ ok = 1; /* not sure what is happening so output response */
+ if (0 == verbose) {
+ fprintf(stderr, ">>> Recovered error on ATA_16, may have "
+ "failed\n");
+ fprintf(stderr, " Add '-v' for more information\n");
+ }
+ break;
+ default: /* won't bother decoding other categories */
+ sg_chk_n_print3("ATA_16 command error", &io_hdr, 1);
+ break;
+ }
+
+ if (ok) { /* output result if it is available */
+ if (raw > 0)
+ dStrRaw((const char *)inBuff, 512);
+ else {
+ if (verbose && hex)
+ fprintf(stderr, "Response to READ LOG EXT (page=11h):\n");
+ if (1 == hex)
+ dStrHex((const char *)inBuff, 512, 0);
+ else if (hex > 1)
+ dWordHex((const unsigned short *)inBuff, 256, 0,
+ sg_is_big_endian());
+ else {
+ printf("SATA phy event counters:\n");
+ for (k = 4; k < 512; k += (len + 2)) {
+ id = (inBuff[k + 1] << 8) + inBuff[k];
+ if (0 == id)
+ break;
+ len = ((id >> 12) & 0x7) * 2;
+ vendor = !!(id & 0x8000);
+ id = id & 0xfff;
+ ull = 0;
+ for (j = len - 1; j >= 0; --j) {
+ if (j < (len - 1))
+ ull <<= 8;
+ ull |= inBuff[k + 2 + j];
+ }
+ cp = NULL;
+ if ((0 == vendor) && (0 == ignore))
+ cp = find_phy_desc(id);
+ if (cp)
+ printf(" %s: %" PRIu64 "\n", cp, ull);
+ else
+ printf(" id=0x%x, vendor=%d, data_len=%d, "
+ "val=%" PRIu64 "\n", id, vendor, len, ull);
+ }
+ }
+ }
+ }
+ res = close(sg_fd);
+ if (res < 0) {
+ fprintf(stderr, "close error: %s\n", safe_strerror(-res));
+ if (0 == ret)
+ return SG_LIB_FILE_ERROR;
+ }
+ return (ret >= 0) ? ret : SG_LIB_CAT_OTHER;
+}
diff --git a/examples/sg_sat_set_features.8 b/examples/sg_sat_set_features.8
new file mode 100644
index 00000000..8cced221
--- /dev/null
+++ b/examples/sg_sat_set_features.8
@@ -0,0 +1,85 @@
+.TH SG_SAT_SET_FEATURES "8" "May 2007" "sg3_utils\-1.24" SG3_UTILS
+.SH NAME
+sg_sat_set_featutes \- sends a ATA SET FEATURES command via a
+SCSI to ATA Translation (SAT) layer
+.SH SYNOPSIS
+.B sg_sat_set_features
+[\fI\-\-count=\fRC] [\fI\-\-chk_cond\fR] [\fI\-\-feature=\fRF] [\fI\-\-help\fR]
+[\fI\-\-lba=\fRLBA] [\fI\-\-verbose\fR] [\fI\-\-version\fR]
+\fIDEVICE\fR
+.SH DESCRIPTION
+.\" Add any additional description here
+.PP
+This utility sends an ATA SET FEATURES command to the \fIDEVICE\fR.
+This command is used to change settings of ATA non-packet (i.e. disks) and
+packet devices (e.g. cd/dvd drives). Rather than send the SET FEATURES
+command directly to the device it is sent via a SCSI transport which is
+assumed to contain a SCSI to ATA Translation (SAT) Layer (SATL). The SAT
+standard (SAT ANSI INCITS 431-2007; prior draft: sat\-r09.pdf at www.t10.org)
+defines two SCSI "ATA PASS\-THROUGH" commands: one using a 16 byte "cdb" and
+the other with a 12 byte cdb. This utility uses the 16 byte cdb variant.
+.PP
+The SATL may be in an operating system driver, in host bus adapter firmware
+or in some external enclosure.
+.PP
+The features can be read using the sg_sat_identify utility which uses either
+the ATA IDENTIFY DEVICE (for non-packet devices) or the IDENTIFY PACKET
+DEVICE (for packet devices) command.
+.SH OPTIONS
+Arguments to long options are mandatory for short options as well.
+.TP
+\fB\-c\fR, \fB\-\-count\fR=\fIC\fR
+the number \fIC\fR is placed in the "count" field in the ATA SET
+FEATURES command. Only some subcommands (a term used for the value
+placed in the "feature" field) require the count field to be set.
+The default value placed in the "count" field is 0.
+.TP
+\fB\-C\fR, \fB\-\-chk_cond\fR
+sets the CK_COND bit in the ATA PASS\-THROUGH SCSI cdb. The
+default setting is clear (i.e. 0). When set the SATL should yield a
+sense buffer containing a ATA Result descriptor irrespective of whether
+the command succeeded or failed. When clear the SATL should only yield
+a sense buffer containing a ATA Result descriptor if the command failed.
+.TP
+\fB\-f\fR, \fB\-\-feature\fR=\fIF\fR
+the number \fIF\fR is placed in the "feature" field in the ATA SET
+FEATURES command. The term "subcommand" is sometimes used for this
+value. The default value placed in the "feature" field is 0 which
+is reserved and hence should not change anything.
+.TP
+\fB\-h\fR, \fB\-\-help\fR
+outputs the usage message summarizing command line options
+then exits. Ignores \fIDEVICE\fR if given.
+.TP
+\fB\-l\fR, \fB\-\-lba\fR=\fILBA\fR
+the number \fILBA\fR is placed in the "lba" field in the ATA SET
+FEATURES command. Only some subcommands (a term used for the value
+placed in the "feature" field) require the lba field to be set.
+This value is not a "logical block address". The default value
+placed in the "lba" field is 0.
+.TP
+\fB\-v\fR, \fB\-\-verbose\fR
+increases the level or verbosity.
+.TP
+\fB\-V\fR, \fB\-\-version\fR
+print out version string
+.SH NOTES
+In the 2.4 series of Linux kernels the \fIDEVICE\fR must be
+a SCSI generic (sg) device. In the 2.6 series block devices (e.g. disks
+and ATAPI DVDs) can also be specified. For example "sg_inq /dev/sda"
+will work in the 2.6 series kernels. From lk 2.6.6 other SCSI "char"
+device names may be used as well (e.g. "/dev/st0m").
+.SH EXIT STATUS
+The exit status of sg_sat_set_features is 0 when it is successful. Otherwise
+see the sg3_utils(8) man page.
+.SH AUTHOR
+Written by Doug Gilbert
+.SH "REPORTING BUGS"
+Report bugs to <dgilbert at interlog dot com>.
+.SH COPYRIGHT
+Copyright \(co 2007 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_sat_identify(sg3_utils), sg_inq(sg3_utils), sdparm(sdparm), hdparm(hdparm)
diff --git a/examples/sg_sat_set_features.c b/examples/sg_sat_set_features.c
index 0ae6738d..b7257737 100644
--- a/examples/sg_sat_set_features.c
+++ b/examples/sg_sat_set_features.c
@@ -33,18 +33,20 @@
#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_lib.h"
#include "sg_io_linux.h"
/* This program performs a ATA PASS-THROUGH (16) SCSI command in order
to perform an ATA SET FEATURES command. See http://www.t10.org
- SAT draft at time of writing: sat-r08a.pdf
+ SAT draft at time of writing: sat-r09.pdf
Invocation:
- sg_sat_set_features [-c <n>] [-f <n>] [-l <n>] [-v] [-V] <device>
+ sg_sat_set_features [-c <n>] [-f <n>] [-h] [-l <n>] [-v] [-V] <device>
*/
@@ -56,16 +58,53 @@
#define EBUFF_SZ 256
-static char * version_str = "1.02 20070130";
+static char * version_str = "1.02 20070406";
+
+static struct option long_options[] = {
+ {"count", required_argument, 0, 'c'},
+ {"chk_cond", no_argument, 0, 'C'},
+ {"feature", required_argument, 0, 'f'},
+ {"help", no_argument, 0, 'h'},
+ {"lba", required_argument, 0, 'l'},
+ {"verbose", no_argument, 0, 'v'},
+ {"version", no_argument, 0, 'V'},
+ {0, 0, 0, 0},
+};
+
+void usage()
+{
+ fprintf(stderr, "Usage: "
+ "sg_sat_set_features [--count=C] [--chk_cond] [--feature=F] "
+ "[--help]\n"
+ " [-lba=LBA] [--verbose] [--version] "
+ "DEVICE\n"
+ " where:\n"
+ " --count=C|-c C count field contents (def: 0)\n"
+ " --chk_cond|-C set chk_cond field in pass-through "
+ "(def: 0)\n"
+ " --feature=F|-f F feature field contents (def: 0)\n"
+ " --help|-h output this usage message\n"
+ " --lba=LBA| -l LBA LBA field contents (def: 0)\n"
+ " --verbose|-v increase verbosity\n"
+ " --version|-V print version string and exit\n\n"
+ "Sends an ATA SET FEATURES command via a SAT pass through.\n"
+ "Primary feature code is placed in '--feature=F' with '--count=C' "
+ "and\n"
+ "'--lba=LBA' being auxiliaries for some features. The arguments C, "
+ "F and LBA\n"
+ "are decimal unless prefixed by '0x' or have a trailing 'h'.\n"
+ "Example enabling write cache: 'sg_sat_set_feature --feature=2 "
+ "/dev/sdc'\n");
+}
int main(int argc, char * argv[])
{
- int sg_fd, k;
+ int sg_fd, c, k;
unsigned char aptCmdBlk[SAT_ATA_PASS_THROUGH16_LEN] =
{SAT_ATA_PASS_THROUGH16, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0};
sg_io_hdr_t io_hdr;
- char * file_name = 0;
+ char device_name[256];
char ebuff[EBUFF_SZ];
unsigned char sense_buffer[64];
int count = 0;
@@ -80,58 +119,80 @@ int main(int argc, char * argv[])
int t_length = 0; /* 0 -> no data transferred, 2 -> sector count */
const unsigned char * ucp = NULL;
- for (k = 1; k < argc; ++k) {
- if (0 == strncmp(argv[k], "-c", 2)) {
- count = sg_get_num(argv[++k]);
+ memset(device_name, 0, sizeof(device_name));
+ while (1) {
+ int option_index = 0;
+
+ c = getopt_long(argc, argv, "c:Cf:hl:vV", long_options,
+ &option_index);
+ if (c == -1)
+ break;
+
+ switch (c) {
+ case 'c':
+ count = sg_get_num(optarg);
if ((count < 0) || (count > 255)) {
- fprintf(stderr, "bad argument for '-c'\n");
- file_name = 0;
- break;
+ fprintf(stderr, "bad argument for '--count'\n");
+ return SG_LIB_SYNTAX_ERROR;
}
- } else if (0 == strncmp(argv[k], "-f", 2)) {
- feature = sg_get_num(argv[++k]);
+ break;
+ case 'C':
+ chk_cond = 1;
+ break;
+ case 'f':
+ feature = sg_get_num(optarg);
if ((feature < 0) || (feature > 255)) {
- fprintf(stderr, "bad argument for '-f'\n");
- file_name = 0;
- break;
+ fprintf(stderr, "bad argument for '--feature'\n");
+ return SG_LIB_SYNTAX_ERROR;
}
- } else if (0 == strncmp(argv[k], "-l", 2)) {
- lba = sg_get_num(argv[++k]);
- if (lba < 0) {
- fprintf(stderr, "bad argument for '-l'\n");
- file_name = 0;
- break;
+ break;
+ case 'h':
+ case '?':
+ usage();
+ return 0;
+ case 'l':
+ lba = sg_get_num(optarg);
+ if ((lba < 0) || (lba > 255)) {
+ fprintf(stderr, "bad argument for '--lba'\n");
+ return SG_LIB_SYNTAX_ERROR;
}
- } else if (0 == strcmp(argv[k], "-v"))
- ++verbose;
- else if (0 == strcmp(argv[k], "-vv"))
- verbose += 2;
- else if (0 == strcmp(argv[k], "-vvv"))
- verbose += 3;
- else if (0 == strcmp(argv[k], "-V")) {
- fprintf(stderr, "version: %s\n", version_str);
- exit(0);
- } else if (*argv[k] == '-') {
- printf("Unrecognized switch: %s\n", argv[k]);
- file_name = 0;
break;
- } else if (0 == file_name)
- file_name = argv[k];
- else {
- fprintf(stderr, "too many arguments\n");
- file_name = 0;
+ case 'v':
+ ++verbose;
break;
+ case 'V':
+ fprintf(stderr, "version: %s\n", version_str);
+ return 0;
+ default:
+ fprintf(stderr, "unrecognised option code 0x%x ??\n", c);
+ usage();
+ return SG_LIB_SYNTAX_ERROR;
}
}
- if (0 == file_name) {
- fprintf(stderr, "Usage: 'sg_sat_set_features [-c <n>] [-f <n>] "
- "[-l <n>] [-v] [-V] <device>'\n");
+ 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 SG_LIB_SYNTAX_ERROR;
+ }
+ }
+
+ if ('\0' == device_name[0]) {
+ fprintf(stderr, "missing device name!\n");
+ usage();
return 1;
}
- if ((sg_fd = open(file_name, O_RDWR)) < 0) {
+ if ((sg_fd = open(device_name, O_RDWR)) < 0) {
snprintf(ebuff, EBUFF_SZ,
- "sg_sat_set_features: error opening file: %s", file_name);
+ "sg_sat_set_features: error opening file: %s", device_name);
perror(ebuff);
return 1;
}
diff --git a/examples/sg_simple1.c b/examples/sg_simple1.c
index a59979a4..f25414cc 100644
--- a/examples/sg_simple1.c
+++ b/examples/sg_simple1.c
@@ -15,16 +15,18 @@
There is another variant of this program called "sg_simple2"
which does not include the sg_lib.h header and logic and so has
simpler but more primitive error processing.
+ In the lk 2.6 series devices nodes such as /dev/sda also support
+ the SG_IO ioctl.
-* Copyright (C) 1999 D. Gilbert
+* Copyright (C) 1999-2007 D. Gilbert
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
- Invocation: sg_simple1 [-x] <sg_device>
+ Invocation: sg_simple1 [-x] <scsi_device>
- Version 03.57 (20020226)
+ Version 03.58 (20070312)
6 byte INQUIRY command:
[0x12][ |lu][pg cde][res ][al len][cntrl ]
diff --git a/examples/sg_simple16.c b/examples/sg_simple16.c
index 33625859..9f8a48ca 100644
--- a/examples/sg_simple16.c
+++ b/examples/sg_simple16.c
@@ -19,7 +19,7 @@
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
- Invocation: sg_simple16 <sg_device>
+ Invocation: sg_simple16 <scsi_device>
Version 1.02 (20020206)
diff --git a/examples/sg_simple2.c b/examples/sg_simple2.c
index acc01328..249c44bb 100644
--- a/examples/sg_simple2.c
+++ b/examples/sg_simple2.c
@@ -15,16 +15,18 @@
which includes the sg_lib.h header and logic and so has more
advanced error processing.
This version demonstrates the "sg3" interface.
+ In the lk 2.6 series devices nodes such as /dev/sda also support
+ the SG_IO ioctl.
-* Copyright (C) 1999 D. Gilbert
+* Copyright (C) 1999-2007 D. Gilbert
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
- Invocation: sg_simple2 [-x] <sg_device>
+ Invocation: sg_simple2 [-x] <scsi_device>
- Version 03.57 (20020226)
+ Version 03.58 (20070312)
6 byte INQUIRY command:
[0x12][ |lu][pg cde][res ][al len][cntrl ]
diff --git a/examples/sg_simple5.c b/examples/sg_simple5.c
index 2179570b..3a09d8f7 100644
--- a/examples/sg_simple5.c
+++ b/examples/sg_simple5.c
@@ -11,15 +11,15 @@
interface. This allows this example program to be ported to
OSes other than linux.
-* Copyright (C) 2006 D. Gilbert
+* Copyright (C) 2006-2007 D. Gilbert
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
- Invocation: sg_simple5 [-x] <sg_device>
+ Invocation: sg_simple5 [-x] <scsi_device>
- Version 1.00 (20060105)
+ Version 1.01 (20070331)
*/
@@ -42,7 +42,7 @@ int main(int argc, char * argv[])
char b[512];
unsigned char sense_b[32];
int verbose = 0;
- void * ptvp;
+ struct sg_pt_base * ptvp;
for (k = 1; k < argc; ++k) {
if (0 == strcmp("-v", argv[k]))
diff --git a/examples/transport_ids.txt b/examples/transport_ids.txt
index 8982afdc..6ef3883c 100644
--- a/examples/transport_ids.txt
+++ b/examples/transport_ids.txt
@@ -1,6 +1,10 @@
# This file is an example for the sg_persist utility.
-# That utility can take one or more "transportID"s from stdin when either
-# the '--transport-id=-" or "-X -" option is given on the command line.
+# It discusses using "TransportID"s which are defined (most recently)
+# in SPC-4 revison 9 section 7.5.4 titled: "TransportID identifiers".
+#
+# The sg_persist utility can take one or more "transportID"s from stdin when
+# either the '--transport-id=-" or "-X -" option is given on the command
+# line.
# To see transport IDs decoded after they have been read in (e.g. to check
# they are well formed) use the verbose flag 3 times (i.e. "... -vvv ...").
@@ -34,4 +38,4 @@
# ... since there is only one line in this file that has a
# transportID on it that will be decoded (i.e. the "SPI" one above).
-# dpg 20041124
+# dpg 20070223
diff --git a/make_no_lib_solaris.sh b/make_no_lib_solaris.sh
new file mode 100755
index 00000000..bf0aeff6
--- /dev/null
+++ b/make_no_lib_solaris.sh
@@ -0,0 +1,3 @@
+#!/bin/sh
+
+make -f no_lib/Makefile.solaris $@
diff --git a/no_lib/Makefile.freebsd b/no_lib/Makefile.freebsd
index dae08b74..c2de140e 100644
--- a/no_lib/Makefile.freebsd
+++ b/no_lib/Makefile.freebsd
@@ -12,7 +12,8 @@ EXECS = sg_readcap sg_turs sg_inq sg_start sg_modes sg_logs sg_senddiag \
sg_sync sg_prevent sg_get_config sg_wr_mode \
sg_rtpg sg_reassign sg_format sg_rmsn sg_ident \
sg_read_long sg_write_long sg_verify sg_rdac sg_vpd \
- sg_sat_identify sg_read_buffer sg_write_buffer sg_opcodes
+ sg_sat_identify sg_read_buffer sg_write_buffer sg_opcodes \
+ sg_raw
MAN_PGS = sg_readcap.8 sg_turs.8 sg_inq.8 sg_start.8 sg_modes.8 sg_logs.8 \
sg_senddiag.8 sg_persist.8 sg_requests.8 sg_ses.8 sg_luns.8 \
@@ -20,7 +21,7 @@ MAN_PGS = sg_readcap.8 sg_turs.8 sg_inq.8 sg_start.8 sg_modes.8 sg_logs.8 \
sg_rtpg.8 sg_reassign.8 sg_format.8 sg_rmsn.8 sg_ident.8 \
sg_read_long.8 sg_write_long.8 sg_verify.8 sg_rdac.8 sg_vpd.8 \
sg3_utils.8 sg_sat_identify.8 sg_read_buffer.8 sg_write_buffer.8 \
- sg_opcodes.8
+ sg_opcodes.8 sg_raw.8
MAN_PREF = man8
@@ -34,6 +35,7 @@ CFLAGS = -g -O2 -Wall -W $(EXTRA_FLAGS)
O_FILES = sg_lib.o sg_cmds_basic.o sg_cmds_extra.o sg_pt_freebsd.o
O_BFILES = sg_lib.o sg_cmds_basic.o sg_pt_freebsd.o
+O_RFILES = sg_lib.o sg_pt_freebsd.o
LDFLAGS = -lcam
# LDFLAGS = -v -lm
@@ -132,9 +134,12 @@ sg_read_buffer: sg_read_buffer.o $(O_FILES)
sg_write_buffer: sg_write_buffer.o $(O_FILES)
$(LD) -o $@ $(LDFLAGS) $@.o $(O_FILES)
-sg_opcodes: sg_opcodes.o $(O_FILES)
+sg_opcodes: sg_opcodes.o $(O_BFILES)
$(LD) -o $@ $(LDFLAGS) $@.o $(O_BFILES)
+sg_raw: sg_raw.o $(O_RFILES)
+ $(LD) -o $@ $(LDFLAGS) $@.o $(O_RFILES)
+
install: $(EXECS)
install -d $(INSTDIR)
for name in $(EXECS); \
diff --git a/no_lib/Makefile.linux b/no_lib/Makefile.linux
index d4537326..f3b90170 100644
--- a/no_lib/Makefile.linux
+++ b/no_lib/Makefile.linux
@@ -16,7 +16,7 @@ EXECS = sg_dd sgp_dd sgm_dd sg_read sg_map sg_scan sg_rbuf \
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_ident sg_map26 sg_rdac sg_vpd sg_sat_identify \
- sg_read_buffer sg_write_buffer
+ sg_read_buffer sg_write_buffer sg_raw
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 \
@@ -26,7 +26,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_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_ident.8 \
sg_map26.8 sg_rdac.8 sg_vpd.8 sg3_utils.8 sg_sat_identify.8 \
- sg_read_buffer.8 sg_write_buffer.8
+ sg_read_buffer.8 sg_write_buffer.8 sg_raw.8
MAN_PREF = man8
OS_FLAGS = -DSG3_UTILS_LINUX
@@ -37,6 +37,7 @@ EXTRA_FLAGS = $(OS_FLAGS) $(LARGE_FILE_FLAGS)
CFLAGS = -g -O2 -Wall -W $(EXTRA_FLAGS)
# CFLAGS = -g -O2 -W -DSG_KERNEL_INCLUDES $(EXTRA_FLAGS)
# CFLAGS = -g -O2 -Wall -W -pedantic -std=c99 $(EXTRA_FLAGS)
+# CFLAGS = -g -O2 -Wall -W -pedantic -std=gnu++98 $(EXTRA_FLAGS)
CFLAGS_PTHREADS = -D_REENTRANT
@@ -179,6 +180,9 @@ sg_read_buffer: sg_read_buffer.o sg_lib.o sg_cmds_basic.o sg_cmds_extra.o sg_pt_
sg_write_buffer: sg_write_buffer.o sg_lib.o sg_cmds_basic.o sg_cmds_extra.o sg_pt_linux.o
$(LD) -o $@ $(LDFLAGS) $^
+sg_raw: sg_raw.o sg_lib.o sg_pt_linux.o
+ $(LD) -o $@ $(LDFLAGS) $^
+
install: $(EXECS)
install -d $(INSTDIR)
for name in $^; \
diff --git a/no_lib/Makefile.linux_static b/no_lib/Makefile.linux_static
index b3f5f0f9..12ad5172 100644
--- a/no_lib/Makefile.linux_static
+++ b/no_lib/Makefile.linux_static
@@ -16,7 +16,7 @@ EXECS = sg_dd sgp_dd sgm_dd sg_read sg_map sg_scan sg_rbuf \
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_ident sg_map26 sg_rdac sg_vpd sg_sat_identify \
- sg_read_buffer sg_write_buffer
+ sg_read_buffer sg_write_buffer sg_raw
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 \
@@ -26,7 +26,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_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_ident.8 \
sg_map26.8 sg_rdac.8 sg_vpd.8 sg3_utils.8 sg_sat_identify.8 \
- sg_read_buffer.8 sg_write_buffer.8
+ sg_read_buffer.8 sg_write_buffer.8 sg_raw.8
MAN_PREF = man8
OS_FLAGS = -DSG3_UTILS_LINUX
@@ -179,6 +179,9 @@ sg_read_buffer: sg_read_buffer.o sg_lib.o sg_cmds_basic.o sg_cmds_extra.o sg_pt_
sg_write_buffer: sg_write_buffer.o sg_lib.o sg_cmds_basic.o sg_cmds_extra.o sg_pt_linux.o
$(LD) -o $@ $(LDFLAGS) $^
+sg_raw: sg_raw.o sg_lib.o sg_pt_linux.o
+ $(LD) -o $@ $(LDFLAGS) $^
+
install: $(EXECS)
install -d $(INSTDIR)
for name in $^; \
diff --git a/no_lib/Makefile.osf1 b/no_lib/Makefile.osf1
index ab02bb7c..9fdeeb33 100644
--- a/no_lib/Makefile.osf1
+++ b/no_lib/Makefile.osf1
@@ -12,7 +12,8 @@ EXECS = sg_readcap sg_turs sg_inq sg_start sg_modes sg_logs sg_senddiag \
sg_sync sg_prevent sg_get_config sg_wr_mode \
sg_rtpg sg_reassign sg_format sg_rmsn sg_ident \
sg_read_long sg_write_long sg_verify sg_rdac sg_vpd \
- sg_sat_identify sg_read_buffer sg_write_buffer sg_opcodes
+ sg_sat_identify sg_read_buffer sg_write_buffer sg_opcodes \
+ sg_raw
MAN_PGS = sg_readcap.8 sg_turs.8 sg_inq.8 sg_start.8 sg_modes.8 sg_logs.8 \
sg_senddiag.8 sg_persist.8 sg_requests.8 sg_ses.8 sg_luns.8 \
@@ -20,7 +21,7 @@ MAN_PGS = sg_readcap.8 sg_turs.8 sg_inq.8 sg_start.8 sg_modes.8 sg_logs.8 \
sg_rtpg.8 sg_reassign.8 sg_format.8 sg_rmsn.8 sg_ident.8 \
sg_read_long.8 sg_write_long.8 sg_verify.8 sg_rdac.8 sg_vpd.8 \
sg3_utils.8 sg_sat_identify.8 sg_read_buffer.8 sg_write_buffer.8 \
- sg_opcodes.8
+ sg_opcodes.8 sg_raw.8
MAN_PREF = man8
@@ -34,6 +35,7 @@ CFLAGS = -g -I./getopt_long $(S_CFLAGS)
O_FILES = sg_lib.o sg_cmds_basic.o sg_cmds_extra.o sg_pt_osf1.o
O_BFILES = sg_lib.o sg_cmds_basic.o sg_pt_osf1.o
+O_RFILES = sg_lib.o sg_pt_osf1.o
O_GETOPT_LONG = getopt_long/getopt_long.o
LDFLAGS =
@@ -140,6 +142,9 @@ sg_write_buffer: sg_write_buffer.o $(O_FILES) $(O_GETOPT_LONG)
sg_opcodes: sg_opcodes.o $(O_BFILES) $(O_GETOPT_LONG)
$(LD) -o $@ $(LDFLAGS) $@.o $(O_BFILES) $(O_GETOPT_LONG)
+sg_raw: sg_raw.o $(O_RFILES) $(O_GETOPT_LONG)
+ $(LD) -o $@ $(LDFLAGS) $@.o $(O_RFILES) $(O_GETOPT_LONG)
+
install: $(EXECS)
test -d $(INSTDIR) || mkdir -p $(INSTDIR)
for name in $(EXECS); \
diff --git a/no_lib/Makefile.solaris b/no_lib/Makefile.solaris
new file mode 100644
index 00000000..089617ed
--- /dev/null
+++ b/no_lib/Makefile.solaris
@@ -0,0 +1,161 @@
+SHELL = /bin/sh
+
+PREFIX=/usr/local
+INSTDIR=$(DESTDIR)/$(PREFIX)/bin
+MANDIR=$(DESTDIR)/$(PREFIX)/man
+
+CC = gcc
+LD = gcc
+
+EXECS = sg_readcap sg_turs sg_inq sg_start sg_modes sg_logs sg_senddiag \
+ sg_persist sg_requests sg_ses sg_luns \
+ sg_sync sg_prevent sg_get_config sg_wr_mode \
+ sg_rtpg sg_reassign sg_format sg_rmsn sg_ident \
+ sg_read_long sg_write_long sg_verify sg_rdac sg_vpd \
+ sg_sat_identify sg_read_buffer sg_write_buffer sg_opcodes \
+ sg_raw
+
+MAN_PGS = sg_readcap.8 sg_turs.8 sg_inq.8 sg_start.8 sg_modes.8 sg_logs.8 \
+ sg_senddiag.8 sg_persist.8 sg_requests.8 sg_ses.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_ident.8 \
+ sg_read_long.8 sg_write_long.8 sg_verify.8 sg_rdac.8 sg_vpd.8 \
+ sg3_utils.8 sg_sat_identify.8 sg_read_buffer.8 sg_write_buffer.8 \
+ sg_opcodes.8 sg_raw.8
+
+MAN_PREF = man8
+
+OS_FLAGS = -DSG3_UTILS_SOLARIS
+LARGE_FILE_FLAGS = -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64
+EXTRA_FLAGS = $(OS_FLAGS) $(LARGE_FILE_FLAGS)
+
+# CFLAGS = -O2 -Wall -W $(EXTRA_FLAGS)
+CFLAGS = -g -O2 -Wall -W $(EXTRA_FLAGS)
+# CFLAGS = -g -O2 -Wall -W -pedantic -std=c99 $(EXTRA_FLAGS)
+
+O_FILES = sg_lib.o sg_cmds_basic.o sg_cmds_extra.o sg_pt_solaris.o
+O_BFILES = sg_lib.o sg_cmds_basic.o sg_pt_solaris.o
+O_RFILES = sg_lib.o sg_pt_solaris.o
+
+# LDFLAGS = -lcam
+# LDFLAGS = -v -lm
+
+all: $(EXECS)
+
+depend dep:
+ for i in *.c; do $(CC) $(INCLUDES) $(CFLAGS) -M $$i; \
+ done > .depend
+
+clean:
+ /bin/rm -f *.o $(EXECS) core* .depend *.a *.la *.lo
+ /bin/rm -rf .libs
+
+sg_readcap: sg_readcap.o $(O_BFILES)
+ $(LD) -o $@ $(LDFLAGS) $@.o $(O_BFILES)
+
+sg_turs: sg_turs.o $(O_BFILES)
+ $(LD) -o $@ $(LDFLAGS) $@.o $(O_BFILES)
+
+sg_inq: sg_inq.o $(O_BFILES)
+ $(LD) -o $@ $(LDFLAGS) $@.o $(O_BFILES)
+
+sg_start: sg_start.o $(O_BFILES)
+ $(LD) -o $@ $(LDFLAGS) $@.o $(O_BFILES)
+
+sg_modes: sg_modes.o $(O_BFILES)
+ $(LD) -o $@ $(LDFLAGS) $@.o $(O_BFILES)
+
+sg_logs: sg_logs.o $(O_BFILES)
+ $(LD) -o $@ $(LDFLAGS) $@.o $(O_BFILES)
+
+sg_senddiag: sg_senddiag.o $(O_FILES)
+ $(LD) -o $@ $(LDFLAGS) $@.o $(O_FILES)
+
+sg_persist: sg_persist.o $(O_FILES)
+ $(LD) -o $@ $(LDFLAGS) $@.o $(O_FILES)
+
+sg_requests: sg_requests.o $(O_BFILES)
+ $(LD) -o $@ $(LDFLAGS) $@.o $(O_BFILES)
+
+sg_ses: sg_ses.o $(O_FILES)
+ $(LD) -o $@ $(LDFLAGS) $@.o $(O_FILES)
+
+sg_luns: sg_luns.o $(O_BFILES)
+ $(LD) -o $@ $(LDFLAGS) $@.o $(O_BFILES)
+
+sg_sync: sg_sync.o $(O_BFILES)
+ $(LD) -o $@ $(LDFLAGS) $@.o $(O_BFILES)
+
+sg_prevent: sg_prevent.o $(O_BFILES)
+ $(LD) -o $@ $(LDFLAGS) $@.o $(O_BFILES)
+
+sg_get_config: sg_get_config.o $(O_FILES)
+ $(LD) -o $@ $(LDFLAGS) $@.o $(O_FILES)
+
+sg_wr_mode: sg_wr_mode.o $(O_BFILES)
+ $(LD) -o $@ $(LDFLAGS) $@.o $(O_BFILES)
+
+sg_rtpg: sg_rtpg.o $(O_FILES)
+ $(LD) -o $@ $(LDFLAGS) $@.o $(O_FILES)
+
+sg_reassign: sg_reassign.o $(O_FILES)
+ $(LD) -o $@ $(LDFLAGS) $@.o $(O_FILES)
+
+sg_format: sg_format.o $(O_FILES)
+ $(LD) -o $@ $(LDFLAGS) $@.o $(O_FILES)
+
+sg_rmsn: sg_rmsn.o $(O_FILES)
+ $(LD) -o $@ $(LDFLAGS) $@.o $(O_FILES)
+
+sg_ident: sg_ident.o $(O_FILES)
+ $(LD) -o $@ $(LDFLAGS) $@.o $(O_FILES)
+
+sg_read_long: sg_read_long.o $(O_FILES)
+ $(LD) -o $@ $(LDFLAGS) $@.o $(O_FILES)
+
+sg_write_long: sg_write_long.o $(O_FILES)
+ $(LD) -o $@ $(LDFLAGS) $@.o $(O_FILES)
+
+sg_verify: sg_verify.o $(O_FILES)
+ $(LD) -o $@ $(LDFLAGS) $@.o $(O_FILES)
+
+sg_rdac: sg_rdac.o $(O_BFILES)
+ $(LD) -o $@ $(LDFLAGS) $@.o $(O_BFILES)
+
+sg_vpd: sg_vpd.o sg_vpd_vendor.o $(O_BFILES)
+ $(LD) -o $@ $(LDFLAGS) $@.o sg_vpd_vendor.o $(O_BFILES)
+
+sg_sat_identify: sg_sat_identify.o $(O_FILES)
+ $(LD) -o $@ $(LDFLAGS) $@.o $(O_FILES)
+
+sg_read_buffer: sg_read_buffer.o $(O_FILES)
+ $(LD) -o $@ $(LDFLAGS) $@.o $(O_FILES)
+
+sg_write_buffer: sg_write_buffer.o $(O_FILES)
+ $(LD) -o $@ $(LDFLAGS) $@.o $(O_FILES)
+
+sg_opcodes: sg_opcodes.o $(O_BFILES)
+ $(LD) -o $@ $(LDFLAGS) $@.o $(O_BFILES)
+
+sg_raw: sg_raw.o $(O_RFILES)
+ $(LD) -o $@ $(LDFLAGS) $@.o $(O_RFILES)
+
+install: $(EXECS)
+ install -d $(INSTDIR)
+ for name in $(EXECS); \
+ do install -s -f $(INSTDIR) $$name; \
+ done
+ install -d $(MANDIR)/$(MAN_PREF)
+ for mp in $(MAN_PGS); \
+ do install -s -m 644 -f $(MANDIR)/$(MAN_PREF) $$mp; \
+ done
+
+uninstall:
+ dists="$(EXECS)"; \
+ for name in $$dists; do \
+ rm -f $(INSTDIR)/$$name; \
+ done
+ for mp in $(MAN_PGS); do \
+ rm -f $(MANDIR)/$(MAN_PREF)/$$mp; \
+ done
+
diff --git a/no_lib/Makefile.win32 b/no_lib/Makefile.win32
index 22cc0fb6..9a621422 100644
--- a/no_lib/Makefile.win32
+++ b/no_lib/Makefile.win32
@@ -12,7 +12,8 @@ EXECS = sg_readcap sg_turs sg_inq sg_start sg_modes sg_logs sg_senddiag \
sg_sync sg_prevent sg_get_config sg_wr_mode \
sg_rtpg sg_reassign sg_format sg_rmsn sg_ident \
sg_read_long sg_write_long sg_verify sg_rdac sg_vpd \
- sg_sat_identify sg_read_buffer sg_write_buffer sg_opcodes
+ sg_sat_identify sg_read_buffer sg_write_buffer sg_opcodes \
+ sg_raw
MAN_PGS = sg_readcap.8 sg_turs.8 sg_inq.8 sg_start.8 sg_modes.8 sg_logs.8 \
sg_senddiag.8 sg_persist.8 sg_requests.8 sg_ses.8 sg_luns.8 \
@@ -20,7 +21,7 @@ MAN_PGS = sg_readcap.8 sg_turs.8 sg_inq.8 sg_start.8 sg_modes.8 sg_logs.8 \
sg_rtpg.8 sg_reassign.8 sg_format.8 sg_rmsn.8 sg_ident.8 \
sg_read_long.8 sg_write_long.8 sg_verify.8 sg_rdac.8 sg_vpd.8 \
sg3_utils.8 sg_sat_identify.8 sg_read_buffer.8 sg_write_buffer.8 \
- sg_opcodes.8
+ sg_opcodes.8 sg_raw.8
MAN_PREF = man8
@@ -35,6 +36,7 @@ CFLAGS = -g -O2 -Wall -W $(EXTRA_FLAGS)
O_FILES = sg_lib.o sg_cmds_basic.o sg_cmds_extra.o sg_pt_win32.o
O_BFILES = sg_lib.o sg_cmds_basic.o sg_pt_win32.o
+O_RFILES = sg_lib.o sg_pt_win32.o
O_SFILES = sg_lib.o
LDFLAGS = -static
@@ -143,6 +145,9 @@ sg_write_buffer: sg_write_buffer.o $(O_FILES)
sg_opcodes: sg_opcodes.o $(O_BFILES)
$(LD) -o $@ $(LDFLAGS) $@.o $(O_BFILES)
+sg_raw: sg_raw.o $(O_RFILES)
+ $(LD) -o $@ $(LDFLAGS) $@.o $(O_RFILES)
+
install: $(EXECS)
cp sg_scan.8w sg_scan.8
install -d $(INSTDIR)
diff --git a/no_lib/sg3_utils.spec b/no_lib/sg3_utils.spec
index 6056b517..2773d655 100644
--- a/no_lib/sg3_utils.spec
+++ b/no_lib/sg3_utils.spec
@@ -1,6 +1,6 @@
Summary: Utilities for devices that use SCSI command sets
Name: sg3_utils
-Version: 1.23
+Version: 1.24
Release: 1
Packager: Douglas Gilbert <dgilbert at interlog dot com>
License: GPL/FreeBSD
@@ -89,6 +89,7 @@ rm -rf $RPM_BUILD_ROOT
%attr(755,root,root) %{_bindir}/sg_sat_identify
%attr(755,root,root) %{_bindir}/sg_read_buffer
%attr(755,root,root) %{_bindir}/sg_write_buffer
+%attr(755,root,root) %{_bindir}/sg_raw
# 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*
@@ -131,10 +132,15 @@ rm -rf $RPM_BUILD_ROOT
%attr(-,root,root) %doc %{_mandir}/man8/sg_sat_identify.8*
%attr(-,root,root) %doc %{_mandir}/man8/sg_read_buffer.8*
%attr(-,root,root) %doc %{_mandir}/man8/sg_write_buffer.8*
+%attr(-,root,root) %doc %{_mandir}/man8/sg_raw.8*
%attr(-,root,root) %doc %{_mandir}/man8/sg3_utils.8*
%changelog
+* Mon May 07 2007 - dgilbert at interlog dot com
+- add sg_raw; sg_rtpg, sg_log, sg_inq and sg_format updates
+ * sg3_utils-1.24
+
* Wed Jan 31 2007 - dgilbert at interlog dot com
- add sg_read_buffer + sg_write_buffer
* sg3_utils-1.23
diff --git a/scripts/sas_disk_blink b/scripts/sas_disk_blink
index d569fb00..2cb83ca2 100755
--- a/scripts/sas_disk_blink
+++ b/scripts/sas_disk_blink
@@ -9,7 +9,7 @@
# Uses sdparm rather than sg3_utils as the former is simpler to
# use for setting mode page value.
#
-# Douglas Gilbert 20061208
+# Douglas Gilbert 20070317
seconds=30
diff --git a/scripts/scsi_logging_level b/scripts/scsi_logging_level
index ecbc8277..7dbac540 100755
--- a/scripts/scsi_logging_level
+++ b/scripts/scsi_logging_level
@@ -3,26 +3,11 @@
# Conveniently create and set scsi logging level, show SCSI_LOG fields in human
# readable form.
#
-# Copyright (C) IBM Corp. 2006
-#
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation; either version 2 of the License, or (at
-# your option) any later version.
-#
-# This program is distributed in the hope that it will be useful, but
-# WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-# General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
-# 02110-1301, USA.
+# (C) Copyright IBM Corp. 2006
###############################################################################
-# Contributed by Andreas Herrmann <aherrman@de.ibm.com> 2006/08/18
+REVISION="1.0"
SCRIPTNAME="scsi_logging_level"
declare -i LOG_ERROR=0
@@ -38,17 +23,6 @@ declare -i LOG_IOCTL=0
declare -i LEVEL=0
-_ERROR_SHIFT=0
-_TIMEOUT_SHIFT=3
-_SCAN_SHIFT=6
-_MLQUEUE_SHIFT=9
-_MLCOMPLETE_SHIFT=12
-_LLQUEUE_SHIFT=15
-_LLCOMPLETE_SHIFT=18
-_HLQUEUE_SHIFT=21
-_HLCOMPLETE_SHIFT=24
-_IOCTL_SHIFT=27
-
SET=0
GET=0
CREATE=0
@@ -63,7 +37,7 @@ eval set -- "$OPTS"
printversion()
{
cat <<EOF
-$SCRIPTNAME (s390-tools) %S390_TOOLS_VERSION%
+%S390_TOOLS_VERSION% ($SCRIPTNAME $REVISION)
(C) Copyright IBM Corp. 2006
EOF
}
@@ -106,7 +80,7 @@ Note: Several SCSI_LOG fields can be specified using several options.
When multiple options specify same SCSI_LOG field the most specific
option has precedence.
-Example: "scsi_logging_level --hlqueue 3 --hlcomplete 2 --all 1 -s" sets
+Example: "scsi_logging_level --hlqueue 3 --highlevel 2 --all 1 -s" sets
SCSI_LOG_HLQUEUE=3, SCSI_LOG_HLCOMPLETE=2 and assigns all other SCSI_LOG
fields the value 1.
EOF
@@ -114,11 +88,10 @@ EOF
check_level()
{
-# something is wrong with the following if ... dpg 20061027
-# if [ `echo -n $1 | tr --complement [:digit:] 'a' | grep -s 'a'` ]
-# then
-# invalid_cmdline "log level '$1' out of range [0, 7]"
-# fi
+ if [ `echo -n $1 | tr --complement [:digit:] 'a' | grep -s 'a'` ]
+ then
+ invalid_cmdline "log level '$1' out of range [0, 7]"
+ fi
if [ $1 -lt 0 -o $1 -gt 7 ]
then
@@ -225,16 +198,16 @@ show_logging_level()
{
echo "dev.scsi.logging_level = $LEVEL"
- LOG_ERROR=$((($LEVEL>>$_ERROR_SHIFT) & 7))
- LOG_TIMEOUT=$((($LEVEL>>$_TIMEOUT_SHIFT) & 7))
- LOG_SCAN=$((($LEVEL>>$_SCAN_SHIFT) & 7))
- LOG_MLQUEUE=$((($LEVEL>>$_MLQUEUE_SHIFT) & 7))
- LOG_MLCOMPLETE=$((($LEVEL>>$_MLCOMPLETE_SHIFT) & 7))
- LOG_LLQUEUE=$((($LEVEL>>$_LLQUEUE_SHIFT) & 7))
- LOG_LLCOMPLETE=$((($LEVEL>>$_LLCOMPLETE_SHIFT) & 7))
- LOG_HLQUEUE=$((($LEVEL>>$_HLQUEUE_SHIFT) & 7))
- LOG_HLCOMPLETE=$((($LEVEL>>$_HLCOMPLETE_SHIFT) & 7))
- LOG_IOCTL=$((($LEVEL>>$_IOCTL_SHIFT) & 7))
+ LOG_ERROR=$(($LEVEL & 7)); LEVEL=$(($LEVEL>>3))
+ LOG_TIMEOUT=$(($LEVEL & 7)); LEVEL=$(($LEVEL>>3))
+ LOG_SCAN=$(($LEVEL & 7)); LEVEL=$(($LEVEL>>3))
+ LOG_MLQUEUE=$(($LEVEL & 7)); LEVEL=$(($LEVEL>>3))
+ LOG_MLCOMPLETE=$(($LEVEL & 7)); LEVEL=$(($LEVEL>>3))
+ LOG_LLQUEUE=$(($LEVEL & 7)); LEVEL=$(($LEVEL>>3))
+ LOG_LLCOMPLETE=$(($LEVEL & 7)); LEVEL=$(($LEVEL>>3))
+ LOG_HLQUEUE=$(($LEVEL & 7)); LEVEL=$(($LEVEL>>3));
+ LOG_HLCOMPLETE=$(($LEVEL & 7)); LEVEL=$(($LEVEL>>3));
+ LOG_IOCTL=$(($LEVEL & 7))
echo "SCSI_LOG_ERROR=$LOG_ERROR"
echo "SCSI_LOG_TIMEOUT=$LOG_TIMEOUT"
@@ -259,19 +232,18 @@ set_logging_level()
exit 1
fi
}
-
create_logging_level()
{
- LEVEL=$((($LOG_ERROR & 7)<<$_ERROR_SHIFT))
- LEVEL=$(($LEVEL|(($LOG_TIMEOUT & 7)<<$_TIMEOUT_SHIFT)))
- LEVEL=$(($LEVEL|(($LOG_SCAN & 7)<<$_SCAN_SHIFT)))
- LEVEL=$(($LEVEL|(($LOG_MLQUEUE & 7)<<$_MLQUEUE_SHIFT)))
- LEVEL=$(($LEVEL|(($LOG_MLCOMPLETE & 7)<<$_MLCOMPLETE_SHIFT)))
- LEVEL=$(($LEVEL|(($LOG_LLQUEUE & 7)<<$_LLQUEUE_SHIFT)))
- LEVEL=$(($LEVEL|(($LOG_LLCOMPLETE & 7)<<$_LLCOMPLETE_SHIFT)))
- LEVEL=$(($LEVEL|(($LOG_HLQUEUE & 7)<<$_HLQUEUE_SHIFT)))
- LEVEL=$(($LEVEL|(($LOG_HLCOMPLETE & 7)<<$_HLCOMPLETE_SHIFT)))
- LEVEL=$(($LEVEL|(($LOG_IOCTL & 7)<<$_IOCTL_SHIFT)))
+ LEVEL=$(($LOG_IOCTL & 7)); LEVEL=$(($LEVEL<<3))
+ LEVEL=$(($LEVEL|($LOG_HLCOMPLETE & 7))); LEVEL=$(($LEVEL<<3))
+ LEVEL=$(($LEVEL|($LOG_HLQUEUE & 7))); LEVEL=$(($LEVEL<<3))
+ LEVEL=$(($LEVEL|($LOG_LLCOMPLETE & 7))); LEVEL=$(($LEVEL<<3))
+ LEVEL=$(($LEVEL|($LOG_LLQUEUE & 7))); LEVEL=$(($LEVEL<<3))
+ LEVEL=$(($LEVEL|($LOG_MLCOMPLETE & 7))); LEVEL=$(($LEVEL<<3))
+ LEVEL=$(($LEVEL|($LOG_MLQUEUE & 7))); LEVEL=$(($LEVEL<<3))
+ LEVEL=$(($LEVEL|($LOG_SCAN & 7))); LEVEL=$(($LEVEL<<3))
+ LEVEL=$(($LEVEL|($LOG_TIMEOUT & 7))); LEVEL=$(($LEVEL<<3))
+ LEVEL=$(($LEVEL|($LOG_ERROR & 7)))
}
check_cmdline $*
@@ -292,4 +264,3 @@ then
else
invalid_cmdline missing option \'-g\', \'-s\' or \'-c\'
fi
-
diff --git a/scripts/scsi_mandat b/scripts/scsi_mandat
index 6e9e3c97..85d989c5 100755
--- a/scripts/scsi_mandat
+++ b/scripts/scsi_mandat
@@ -17,7 +17,7 @@
# This script uses utilities frim sg3_utils package (version
# 1.21 or later) and sdparm (version 0.99 or later)
#
-# Douglas Gilbert 20061230
+# Douglas Gilbert 20070317
log=0
diff --git a/scripts/scsi_satl b/scripts/scsi_satl
index 2758eae7..0fe829fc 100755
--- a/scripts/scsi_satl
+++ b/scripts/scsi_satl
@@ -24,7 +24,7 @@
# This script uses utilities from sg3_utils package (version
# 1.22 or later) and sdparm (version 0.99 or later)
#
-# Douglas Gilbert 20061230
+# Douglas Gilbert 20070317
quiet=0
diff --git a/sg3_utils.8 b/sg3_utils.8
index 2a60c35a..4e636a3d 100644
--- a/sg3_utils.8
+++ b/sg3_utils.8
@@ -1,4 +1,4 @@
-.TH SG3_UTILS "8" "Jamuary 2007" "sg3_utils\-1.23" SG3_UTILS
+.TH SG3_UTILS "8" "March 2007" "sg3_utils\-1.24" SG3_UTILS
.SH NAME
sg3_utils \- a package of utilities for sending SCSI commands
.SH SYNOPSIS
@@ -78,10 +78,10 @@ example an attempt to read a corrupted block on a disk will yield this value.
.TP
.B 5
the \fIDEVICE\fR reports an "illegal request" with an additional sense code
-other than "invalid operation code". This is often a supported command with
-a field set requesting an unsupported capability. For commands that require
-a "service action" field this value can indicate that the command with that
-service action value is not supported.
+other than "invalid command operation code". This is often a supported
+command with a field set requesting an unsupported capability. For commands
+that require a "service action" field this value can indicate that the
+command with that service action value is not supported.
.TP
.B 6
the \fIDEVICE\fR reports a "unit attention" condition. This usually indicates
@@ -92,7 +92,7 @@ conditions are usually only reported once by a device.
.TP
.B 9
the \fIDEVICE\fR reports an illegal request with an additional sense code
-of "invalid operation code" which means that it doesn't support the
+of "invalid command operation code" which means that it doesn't support the
requested command.
.TP
.B 11
diff --git a/sg3_utils.spec b/sg3_utils.spec
index 390b7f46..c3c765db 100644
--- a/sg3_utils.spec
+++ b/sg3_utils.spec
@@ -1,6 +1,6 @@
Summary: Utilities for devices that use SCSI command sets
Name: sg3_utils
-Version: 1.23
+Version: 1.24
Release: 1%{?dist}
License: GPL
Group: Utilities/System
@@ -78,6 +78,10 @@ rm -rf $RPM_BUILD_ROOT
%{_libdir}/*.la
%changelog
+* Mon May 07 2007 - dgilbert at interlog dot com
+- add sg_raw; sg_rtpg, sg_log, sg_inq and sg_format updates
+ * sg3_utils-1.24
+
* Wed Jan 31 2007 - dgilbert at interlog dot com
- add sg_read_buffer + sg_write_buffer
* sg3_utils-1.23
diff --git a/sg_cmds_basic.c b/sg_cmds_basic.c
index d9613e14..5d1462eb 100644
--- a/sg_cmds_basic.c
+++ b/sg_cmds_basic.c
@@ -45,7 +45,7 @@
#include "sg_pt.h"
-static char * version_str = "1.38 20070124";
+static char * version_str = "1.40 20070331";
#define SENSE_BUFF_LEN 32 /* Arbitrary, could be larger */
@@ -120,7 +120,7 @@ int sg_cmds_close_device(int device_fd)
output via 'o_sense_cat' pointer (if not NULL). Outputs to
sg_warnings_strm (def: stderr) if problems; depending on 'noisy'
and 'verbose' */
-int sg_cmds_process_resp(void * ptvp, const char * leadin, int res,
+int sg_cmds_process_resp(struct sg_pt_base * ptvp, const char * leadin, int res,
int mx_resp_len, const unsigned char * sense_b,
int noisy, int verbose, int * o_sense_cat)
{
@@ -223,7 +223,7 @@ int sg_ll_inquiry(int sg_fd, int cmddt, int evpd, int pg_op,
unsigned char inqCmdBlk[INQUIRY_CMDLEN] = {INQUIRY_CMD, 0, 0, 0, 0, 0};
unsigned char sense_b[SENSE_BUFF_LEN];
unsigned char * up;
- void * ptvp;
+ struct sg_pt_base * ptvp;
if (cmddt)
inqCmdBlk[1] |= 2;
@@ -298,7 +298,7 @@ int sg_simple_inquiry(int sg_fd, struct sg_simple_inquiry_resp * inq_data,
unsigned char inqCmdBlk[INQUIRY_CMDLEN] = {INQUIRY_CMD, 0, 0, 0, 0, 0};
unsigned char sense_b[SENSE_BUFF_LEN];
unsigned char inq_resp[INQUIRY_RESP_INITIAL_LEN];
- void * ptvp;
+ struct sg_pt_base * ptvp;
if (inq_data) {
memset(inq_data, 0, sizeof(* inq_data));
@@ -382,7 +382,7 @@ int sg_ll_test_unit_ready_progress(int sg_fd, int pack_id, int * progress,
int res, ret, k, sense_cat;
unsigned char turCmdBlk[TUR_CMDLEN] = {TUR_CMD, 0, 0, 0, 0, 0};
unsigned char sense_b[SENSE_BUFF_LEN];
- void * ptvp;
+ struct sg_pt_base * ptvp;
if (NULL == sg_warnings_strm)
sg_warnings_strm = stderr;
@@ -460,7 +460,7 @@ int sg_ll_sync_cache_10(int sg_fd, int sync_nv, int immed, int group,
unsigned char scCmdBlk[SYNCHRONIZE_CACHE_CMDLEN] =
{SYNCHRONIZE_CACHE_CMD, 0, 0, 0, 0, 0, 0, 0, 0, 0};
unsigned char sense_b[SENSE_BUFF_LEN];
- void * ptvp;
+ struct sg_pt_base * ptvp;
if (sync_nv)
scCmdBlk[1] |= 4;
@@ -535,7 +535,7 @@ int sg_ll_readcap_16(int sg_fd, int pmi, unsigned long long llba,
{SERVICE_ACTION_IN_16_CMD, READ_CAPACITY_16_SA,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
unsigned char sense_b[SENSE_BUFF_LEN];
- void * ptvp;
+ struct sg_pt_base * ptvp;
if (pmi) { /* lbs only valid when pmi set */
rcCmdBlk[14] |= 1;
@@ -610,7 +610,7 @@ int sg_ll_readcap_10(int sg_fd, int pmi, unsigned int lba,
unsigned char rcCmdBlk[READ_CAPACITY_10_CMDLEN] =
{READ_CAPACITY_10_CMD, 0, 0, 0, 0, 0, 0, 0, 0, 0};
unsigned char sense_b[SENSE_BUFF_LEN];
- void * ptvp;
+ struct sg_pt_base * ptvp;
if (pmi) { /* lbs only valid when pmi set */
rcCmdBlk[8] |= 1;
@@ -676,7 +676,7 @@ int sg_ll_mode_sense6(int sg_fd, int dbd, int pc, int pg_code, int sub_pg_code,
unsigned char modesCmdBlk[MODE_SENSE6_CMDLEN] =
{MODE_SENSE6_CMD, 0, 0, 0, 0, 0};
unsigned char sense_b[SENSE_BUFF_LEN];
- void * ptvp;
+ struct sg_pt_base * ptvp;
modesCmdBlk[1] = (unsigned char)(dbd ? 0x8 : 0);
modesCmdBlk[2] = (unsigned char)(((pc << 6) & 0xc0) | (pg_code & 0x3f));
@@ -749,7 +749,7 @@ int sg_ll_mode_sense10(int sg_fd, int llbaa, int dbd, int pc, int pg_code,
unsigned char modesCmdBlk[MODE_SENSE10_CMDLEN] =
{MODE_SENSE10_CMD, 0, 0, 0, 0, 0, 0, 0, 0, 0};
unsigned char sense_b[SENSE_BUFF_LEN];
- void * ptvp;
+ struct sg_pt_base * ptvp;
modesCmdBlk[1] = (unsigned char)((dbd ? 0x8 : 0) | (llbaa ? 0x10 : 0));
modesCmdBlk[2] = (unsigned char)(((pc << 6) & 0xc0) | (pg_code & 0x3f));
@@ -822,7 +822,7 @@ int sg_ll_mode_select6(int sg_fd, int pf, int sp, void * paramp,
unsigned char modesCmdBlk[MODE_SELECT6_CMDLEN] =
{MODE_SELECT6_CMD, 0, 0, 0, 0, 0};
unsigned char sense_b[SENSE_BUFF_LEN];
- void * ptvp;
+ struct sg_pt_base * ptvp;
modesCmdBlk[1] = (unsigned char)(((pf << 4) & 0x10) | (sp & 0x1));
modesCmdBlk[4] = (unsigned char)(param_len & 0xff);
@@ -839,7 +839,7 @@ int sg_ll_mode_select6(int sg_fd, int pf, int sp, void * paramp,
fprintf(sg_warnings_strm, "\n");
}
if (verbose > 1) {
- fprintf(sg_warnings_strm, " mode select (6) parameter block\n");
+ fprintf(sg_warnings_strm, " mode select (6) parameter list\n");
dStrHex((const char *)paramp, param_len, -1);
}
@@ -892,7 +892,7 @@ int sg_ll_mode_select10(int sg_fd, int pf, int sp, void * paramp,
unsigned char modesCmdBlk[MODE_SELECT10_CMDLEN] =
{MODE_SELECT10_CMD, 0, 0, 0, 0, 0, 0, 0, 0, 0};
unsigned char sense_b[SENSE_BUFF_LEN];
- void * ptvp;
+ struct sg_pt_base * ptvp;
modesCmdBlk[1] = (unsigned char)(((pf << 4) & 0x10) | (sp & 0x1));
modesCmdBlk[7] = (unsigned char)((param_len >> 8) & 0xff);
@@ -910,7 +910,7 @@ int sg_ll_mode_select10(int sg_fd, int pf, int sp, void * paramp,
fprintf(sg_warnings_strm, "\n");
}
if (verbose > 1) {
- fprintf(sg_warnings_strm, " mode select (10) parameter block\n");
+ fprintf(sg_warnings_strm, " mode select (10) parameter list\n");
dStrHex((const char *)paramp, param_len, -1);
}
@@ -1077,8 +1077,8 @@ int sg_get_mode_page_controls(int sg_fd, int mode6, int pg_code,
ebuff, EBUFF_SZ);
if (offset < 0) {
if (('\0' != ebuff[0]) && (verbose > 0))
- fprintf(sg_warnings_strm, "sg_get_mode_page_types: "
- "current values: %s\n", ebuff);
+ fprintf(sg_warnings_strm, "sg_get_mode_page_controls: %s\n",
+ ebuff);
return SG_LIB_CAT_MALFORMED;
}
xfer_len = calc_len - offset;
@@ -1124,7 +1124,7 @@ int sg_ll_request_sense(int sg_fd, int desc, void * resp, int mx_resp_len,
unsigned char rsCmdBlk[REQUEST_SENSE_CMDLEN] =
{REQUEST_SENSE_CMD, 0, 0, 0, 0, 0};
unsigned char sense_b[SENSE_BUFF_LEN];
- void * ptvp;
+ struct sg_pt_base * ptvp;
if (desc)
rsCmdBlk[1] |= 0x1;
@@ -1197,7 +1197,7 @@ int sg_ll_report_luns(int sg_fd, int select_report, void * resp,
unsigned char rlCmdBlk[REPORT_LUNS_CMDLEN] =
{REPORT_LUNS_CMD, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
unsigned char sense_b[SENSE_BUFF_LEN];
- void * ptvp;
+ struct sg_pt_base * ptvp;
rlCmdBlk[2] = select_report & 0xff;
rlCmdBlk[6] = (mx_resp_len >> 24) & 0xff;
@@ -1261,7 +1261,7 @@ int sg_ll_log_sense(int sg_fd, int ppc, int sp, int pc, int pg_code,
unsigned char logsCmdBlk[LOG_SENSE_CMDLEN] =
{LOG_SENSE_CMD, 0, 0, 0, 0, 0, 0, 0, 0, 0};
unsigned char sense_b[SENSE_BUFF_LEN];
- void * ptvp;
+ struct sg_pt_base * ptvp;
if (NULL == sg_warnings_strm)
sg_warnings_strm = stderr;
@@ -1333,7 +1333,7 @@ int sg_ll_log_select(int sg_fd, int pcr, int sp, int pc,
unsigned char logsCmdBlk[LOG_SELECT_CMDLEN] =
{LOG_SELECT_CMD, 0, 0, 0, 0, 0, 0, 0, 0, 0};
unsigned char sense_b[SENSE_BUFF_LEN];
- void * ptvp;
+ struct sg_pt_base * ptvp;
if (NULL == sg_warnings_strm)
sg_warnings_strm = stderr;
@@ -1353,7 +1353,7 @@ int sg_ll_log_select(int sg_fd, int pcr, int sp, int pc,
fprintf(sg_warnings_strm, "\n");
}
if ((verbose > 1) && (param_len > 0)) {
- fprintf(sg_warnings_strm, " log select parameter block\n");
+ fprintf(sg_warnings_strm, " log select parameter list\n");
dStrHex((const char *)paramp, param_len, -1);
}
@@ -1406,7 +1406,7 @@ int sg_ll_start_stop_unit(int sg_fd, int immed, int fl_num, int power_cond,
unsigned char ssuBlk[START_STOP_CMDLEN] = {START_STOP_CMD, 0, 0, 0, 0, 0};
unsigned char sense_b[SENSE_BUFF_LEN];
int k, res, ret, sense_cat;
- void * ptvp;
+ struct sg_pt_base * ptvp;
ssuBlk[1] = immed & 1;
ssuBlk[3] = fl_num & 3;
@@ -1469,7 +1469,7 @@ int sg_ll_prevent_allow(int sg_fd, int prevent, int noisy, int verbose)
unsigned char pCmdBlk[PREVENT_ALLOW_CMDLEN] =
{PREVENT_ALLOW_CMD, 0, 0, 0, 0, 0};
unsigned char sense_b[SENSE_BUFF_LEN];
- void * ptvp;
+ struct sg_pt_base * ptvp;
if (NULL == sg_warnings_strm)
sg_warnings_strm = stderr;
diff --git a/sg_cmds_basic.h b/sg_cmds_basic.h
index c6890daf..2f6413b0 100644
--- a/sg_cmds_basic.h
+++ b/sg_cmds_basic.h
@@ -244,6 +244,8 @@ extern int sg_cmds_close_device(int device_fd);
extern const char * sg_cmds_version();
+struct sg_pt_base;
+
/* This is an internal worker used by both sg_cmds_basic and sg_cmds_extra */
/* Returns -2 for sense data (may not be fatal), -1 for failed or the
number of bytes fetched. For data out (to device) or no data, set
@@ -251,9 +253,10 @@ extern const char * sg_cmds_version();
output via 'o_sense_cat' pointer (if not NULL). Outputs to
sg_warnings_strm (def: stderr) if problems; depending on 'noisy'
and 'verbose' settings */
-extern int sg_cmds_process_resp(void * ptvp, const char * leadin, int res,
- int mx_resp_len, const unsigned char * sense_b,
- int noisy, int verbose, int * o_sense_cat);
+extern int sg_cmds_process_resp(struct sg_pt_base * ptvp, const char * leadin,
+ int res, int mx_resp_len,
+ const unsigned char * sense_b, int noisy,
+ int verbose, int * o_sense_cat);
#ifdef __cplusplus
}
diff --git a/sg_cmds_extra.c b/sg_cmds_extra.c
index d8c58192..ea25b300 100644
--- a/sg_cmds_extra.c
+++ b/sg_cmds_extra.c
@@ -107,7 +107,7 @@ int sg_ll_report_tgt_prt_grp(int sg_fd, void * resp,
{MAINTENANCE_IN_CMD, REPORT_TGT_PRT_GRP_SA,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
unsigned char sense_b[SENSE_BUFF_LEN];
- void * ptvp;
+ struct sg_pt_base * ptvp;
rtpgCmdBlk[6] = (mx_resp_len >> 24) & 0xff;
rtpgCmdBlk[7] = (mx_resp_len >> 16) & 0xff;
@@ -132,7 +132,7 @@ int sg_ll_report_tgt_prt_grp(int sg_fd, void * resp,
set_scsi_pt_sense(ptvp, sense_b, sizeof(sense_b));
set_scsi_pt_data_in(ptvp, (unsigned char *)resp, mx_resp_len);
res = do_scsi_pt(ptvp, sg_fd, DEF_PT_TIMEOUT, verbose);
- ret = sg_cmds_process_resp(ptvp, "report Target port group", res,
+ ret = sg_cmds_process_resp(ptvp, "report target port group", res,
mx_resp_len, sense_b, noisy, verbose,
&sense_cat);
if (-1 == ret)
@@ -174,7 +174,7 @@ int sg_ll_send_diag(int sg_fd, int sf_code, int pf_bit, int sf_bit,
unsigned char senddiagCmdBlk[SEND_DIAGNOSTIC_CMDLEN] =
{SEND_DIAGNOSTIC_CMD, 0, 0, 0, 0, 0};
unsigned char sense_b[SENSE_BUFF_LEN];
- void * ptvp;
+ struct sg_pt_base * ptvp;
senddiagCmdBlk[1] = (unsigned char)((sf_code << 5) | (pf_bit << 4) |
(sf_bit << 2) | (devofl_bit << 1) | unitofl_bit);
@@ -190,7 +190,7 @@ int sg_ll_send_diag(int sg_fd, int sf_code, int pf_bit, int sf_bit,
fprintf(sg_warnings_strm, "\n");
if ((verbose > 1) && paramp && param_len) {
fprintf(sg_warnings_strm, " Send diagnostic parameter "
- "block:\n");
+ "list:\n");
dStrHex((const char *)paramp, param_len, -1);
}
}
@@ -246,7 +246,7 @@ int sg_ll_receive_diag(int sg_fd, int pcv, int pg_code, void * resp,
unsigned char rcvdiagCmdBlk[RECEIVE_DIAGNOSTICS_CMDLEN] =
{RECEIVE_DIAGNOSTICS_CMD, 0, 0, 0, 0, 0};
unsigned char sense_b[SENSE_BUFF_LEN];
- void * ptvp;
+ struct sg_pt_base * ptvp;
rcvdiagCmdBlk[1] = (unsigned char)(pcv ? 0x1 : 0);
rcvdiagCmdBlk[2] = (unsigned char)(pg_code);
@@ -313,7 +313,7 @@ int sg_ll_read_defect10(int sg_fd, int req_plist, int req_glist,
unsigned char rdefCmdBlk[READ_DEFECT10_CMDLEN] =
{READ_DEFECT10_CMD, 0, 0, 0, 0, 0, 0, 0, 0, 0};
unsigned char sense_b[SENSE_BUFF_LEN];
- void * ptvp;
+ struct sg_pt_base * ptvp;
rdefCmdBlk[2] = (unsigned char)(((req_plist << 4) & 0x10) |
((req_glist << 3) & 0x8) | (dl_format & 0x7));
@@ -387,7 +387,7 @@ int sg_ll_read_media_serial_num(int sg_fd, void * resp, int mx_resp_len,
{SERVICE_ACTION_IN_12_CMD, READ_MEDIA_SERIAL_NUM_SA,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
unsigned char sense_b[SENSE_BUFF_LEN];
- void * ptvp;
+ struct sg_pt_base * ptvp;
rmsnCmdBlk[6] = (mx_resp_len >> 24) & 0xff;
rmsnCmdBlk[7] = (mx_resp_len >> 16) & 0xff;
@@ -460,7 +460,7 @@ int sg_ll_report_id_info(int sg_fd, int itype, void * resp,
REPORT_IDENTIFYING_INFORMATION_SA,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
unsigned char sense_b[SENSE_BUFF_LEN];
- void * ptvp;
+ struct sg_pt_base * ptvp;
riiCmdBlk[6] = (max_resp_len >> 24) & 0xff;
riiCmdBlk[7] = (max_resp_len >> 16) & 0xff;
@@ -535,7 +535,7 @@ int sg_ll_set_id_info(int sg_fd, int itype, void * paramp,
SET_IDENTIFYING_INFORMATION_SA,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
unsigned char sense_b[SENSE_BUFF_LEN];
- void * ptvp;
+ struct sg_pt_base * ptvp;
siiCmdBlk[6] = (param_len >> 24) & 0xff;
siiCmdBlk[7] = (param_len >> 16) & 0xff;
@@ -551,7 +551,7 @@ int sg_ll_set_id_info(int sg_fd, int itype, void * paramp,
fprintf(sg_warnings_strm, "\n");
if ((verbose > 1) && paramp && param_len) {
fprintf(sg_warnings_strm, " Set identifying information "
- "parameter block:\n");
+ "parameter list:\n");
dStrHex((const char *)paramp, param_len, -1);
}
}
@@ -600,7 +600,7 @@ int sg_ll_set_id_info(int sg_fd, int itype, void * paramp,
* SG_LIB_CAT_NOT_READY -> device not ready, SG_LIB_CAT_ABORTED_COMMAND,
* -1 -> other failure */
int sg_ll_format_unit(int sg_fd, int fmtpinfo, int rto_req, int longlist,
- int fmtdata, int cmplist, int dlist_format,
+ int fmtdata, int cmplst, int dlist_format,
int timeout_secs, void * paramp, int param_len,
int noisy, int verbose)
{
@@ -608,7 +608,7 @@ int sg_ll_format_unit(int sg_fd, int fmtpinfo, int rto_req, int longlist,
unsigned char fuCmdBlk[FORMAT_UNIT_CMDLEN] =
{FORMAT_UNIT_CMD, 0, 0, 0, 0, 0};
unsigned char sense_b[SENSE_BUFF_LEN];
- void * ptvp;
+ struct sg_pt_base * ptvp;
if (fmtpinfo)
fuCmdBlk[1] |= 0x80;
@@ -618,7 +618,7 @@ int sg_ll_format_unit(int sg_fd, int fmtpinfo, int rto_req, int longlist,
fuCmdBlk[1] |= 0x20;
if (fmtdata)
fuCmdBlk[1] |= 0x10;
- if (cmplist)
+ if (cmplst)
fuCmdBlk[1] |= 0x8;
if (dlist_format)
fuCmdBlk[1] |= (dlist_format & 0x7);
@@ -632,7 +632,7 @@ int sg_ll_format_unit(int sg_fd, int fmtpinfo, int rto_req, int longlist,
fprintf(sg_warnings_strm, "\n");
}
if ((verbose > 1) && (param_len > 0)) {
- fprintf(sg_warnings_strm, " format parameter block:\n");
+ fprintf(sg_warnings_strm, " format parameter list:\n");
dStrHex((const char *)paramp, param_len, -1);
}
@@ -685,7 +685,7 @@ int sg_ll_reassign_blocks(int sg_fd, int longlba, int longlist,
unsigned char reassCmdBlk[REASSIGN_BLKS_CMDLEN] =
{REASSIGN_BLKS_CMD, 0, 0, 0, 0, 0};
unsigned char sense_b[SENSE_BUFF_LEN];
- void * ptvp;
+ struct sg_pt_base * ptvp;
reassCmdBlk[1] = (unsigned char)(((longlba << 1) & 0x2) | (longlist & 0x1));
if (NULL == sg_warnings_strm)
@@ -697,7 +697,7 @@ int sg_ll_reassign_blocks(int sg_fd, int longlba, int longlist,
fprintf(sg_warnings_strm, "\n");
}
if (verbose > 1) {
- fprintf(sg_warnings_strm, " reassign blocks parameter block\n");
+ fprintf(sg_warnings_strm, " reassign blocks parameter list\n");
dStrHex((const char *)paramp, param_len, -1);
}
@@ -749,7 +749,7 @@ int sg_ll_get_config(int sg_fd, int rt, int starting, void * resp,
unsigned char gcCmdBlk[GET_CONFIG_CMD_LEN] = {GET_CONFIG_CMD, 0, 0, 0,
0, 0, 0, 0, 0, 0};
unsigned char sense_b[SENSE_BUFF_LEN];
- void * ptvp;
+ struct sg_pt_base * ptvp;
if (NULL == sg_warnings_strm)
sg_warnings_strm = stderr;
@@ -831,7 +831,7 @@ int sg_ll_persistent_reserve_in(int sg_fd, int rq_servact, void * resp,
unsigned char prinCmdBlk[PERSISTENT_RESERVE_IN_CMDLEN] =
{PERSISTENT_RESERVE_IN_CMD, 0, 0, 0, 0, 0, 0, 0, 0, 0};
unsigned char sense_b[SENSE_BUFF_LEN];
- void * ptvp;
+ struct sg_pt_base * ptvp;
if (rq_servact > 0)
prinCmdBlk[1] = (unsigned char)(rq_servact & 0x1f);
@@ -901,7 +901,7 @@ int sg_ll_persistent_reserve_out(int sg_fd, int rq_servact, int rq_scope,
unsigned char proutCmdBlk[PERSISTENT_RESERVE_OUT_CMDLEN] =
{PERSISTENT_RESERVE_OUT_CMD, 0, 0, 0, 0, 0, 0, 0, 0, 0};
unsigned char sense_b[SENSE_BUFF_LEN];
- void * ptvp;
+ struct sg_pt_base * ptvp;
if (rq_servact > 0)
proutCmdBlk[1] = (unsigned char)(rq_servact & 0x1f);
@@ -989,7 +989,7 @@ int sg_ll_read_long10(int sg_fd, int pblock, int correct, unsigned long lba,
int k, res, sense_cat, ret;
unsigned char readLongCmdBlk[READ_LONG10_CMDLEN];
unsigned char sense_b[SENSE_BUFF_LEN];
- void * ptvp;
+ struct sg_pt_base * ptvp;
memset(readLongCmdBlk, 0, READ_LONG10_CMDLEN);
readLongCmdBlk[0] = READ_LONG10_CMD;
@@ -1082,7 +1082,7 @@ int sg_ll_read_long16(int sg_fd, int pblock, int correct,
int k, res, sense_cat, ret;
unsigned char readLongCmdBlk[SERVICE_ACTION_IN_16_CMDLEN];
unsigned char sense_b[SENSE_BUFF_LEN];
- void * ptvp;
+ struct sg_pt_base * ptvp;
memset(readLongCmdBlk, 0, sizeof(readLongCmdBlk));
readLongCmdBlk[0] = SERVICE_ACTION_IN_16_CMD;
@@ -1181,7 +1181,7 @@ int sg_ll_write_long10(int sg_fd, int cor_dis, int wr_uncor, int pblock,
int k, res, sense_cat, ret;
unsigned char writeLongCmdBlk[WRITE_LONG10_CMDLEN];
unsigned char sense_b[SENSE_BUFF_LEN];
- void * ptvp;
+ struct sg_pt_base * ptvp;
memset(writeLongCmdBlk, 0, WRITE_LONG10_CMDLEN);
writeLongCmdBlk[0] = WRITE_LONG10_CMD;
@@ -1278,7 +1278,7 @@ int sg_ll_write_long16(int sg_fd, int cor_dis, int wr_uncor, int pblock,
int k, res, sense_cat, ret;
unsigned char writeLongCmdBlk[SERVICE_ACTION_OUT_16_CMDLEN];
unsigned char sense_b[SENSE_BUFF_LEN];
- void * ptvp;
+ struct sg_pt_base * ptvp;
memset(writeLongCmdBlk, 0, sizeof(writeLongCmdBlk));
writeLongCmdBlk[0] = SERVICE_ACTION_OUT_16_CMD;
@@ -1382,7 +1382,7 @@ int sg_ll_verify10(int sg_fd, int dpo, int bytechk, unsigned long lba,
unsigned char vCmdBlk[VERIFY10_CMDLEN] =
{VERIFY10_CMD, 0, 0, 0, 0, 0, 0, 0, 0, 0};
unsigned char sense_b[SENSE_BUFF_LEN];
- void * ptvp;
+ struct sg_pt_base * ptvp;
if (dpo)
vCmdBlk[1] |= 0x10;
@@ -1484,7 +1484,7 @@ int sg_ll_ata_pt(int sg_fd, const unsigned char * cdbp, int cdb_len,
unsigned char sense_b[SENSE_BUFF_LEN];
unsigned char * sp;
const unsigned char * ucp;
- void * ptvp;
+ struct sg_pt_base * ptvp;
const char * cnamep;
char b[256];
int ret = -1;
@@ -1626,7 +1626,7 @@ int sg_ll_read_buffer(int sg_fd, int mode, int buffer_id, int buffer_offset,
unsigned char rbufCmdBlk[READ_BUFFER_CMDLEN] =
{READ_BUFFER_CMD, 0, 0, 0, 0, 0, 0, 0, 0, 0};
unsigned char sense_b[SENSE_BUFF_LEN];
- void * ptvp;
+ struct sg_pt_base * ptvp;
rbufCmdBlk[1] = (unsigned char)(mode & 0x1f);
rbufCmdBlk[2] = (unsigned char)(buffer_id & 0xff);
@@ -1699,7 +1699,7 @@ int sg_ll_write_buffer(int sg_fd, int mode, int buffer_id, int buffer_offset,
unsigned char wbufCmdBlk[WRITE_BUFFER_CMDLEN] =
{WRITE_BUFFER_CMD, 0, 0, 0, 0, 0, 0, 0, 0, 0};
unsigned char sense_b[SENSE_BUFF_LEN];
- void * ptvp;
+ struct sg_pt_base * ptvp;
wbufCmdBlk[1] = (unsigned char)(mode & 0x1f);
wbufCmdBlk[2] = (unsigned char)(buffer_id & 0xff);
@@ -1717,7 +1717,7 @@ int sg_ll_write_buffer(int sg_fd, int mode, int buffer_id, int buffer_offset,
fprintf(sg_warnings_strm, "%02x ", wbufCmdBlk[k]);
fprintf(sg_warnings_strm, "\n");
if ((verbose > 1) && paramp && param_len) {
- fprintf(sg_warnings_strm, " Write buffer parameter block%s:\n",
+ fprintf(sg_warnings_strm, " Write buffer parameter list%s:\n",
((param_len > 256) ? " (first 256 bytes)" : ""));
dStrHex((const char *)paramp,
((param_len > 256) ? 256 : param_len), -1);
diff --git a/sg_cmds_extra.h b/sg_cmds_extra.h
index d4c091de..274af120 100644
--- a/sg_cmds_extra.h
+++ b/sg_cmds_extra.h
@@ -34,17 +34,6 @@
extern "C" {
#endif
-/*
- * Additional sense data categories (to those defined in sg_lib.h).
- */
-
-#define SG_LIB_CAT_ILLEGAL_REQ_WITH_INFO 17 /* Illegal request (other than */
- /* invalid opcode) plus 'info' field: */
- /* [sk,asc,ascq: 0x5,*,*] */
-#define SG_LIB_CAT_MEDIUM_HARD_WITH_INFO 18 /* medium or hardware error */
- /* sense key plus 'info' field: */
- /* [sk,asc,ascq: 0x3/0x4,*,*] */
-
/* Invokes a ATA PASS-THROUGH (12 or 16) SCSI command (SAT). If cdb_len
* is 12 then a ATA PASS-THROUGH (12) command is called. If cdb_len is 16
diff --git a/sg_dd.8 b/sg_dd.8
index 7f8be021..2f906f13 100644
--- a/sg_dd.8
+++ b/sg_dd.8
@@ -1,4 +1,4 @@
-.TH SG_DD "8" "January 2007" "sg3_utils\-1.23" SG3_UTILS
+.TH SG_DD "8" "April 2007" "sg3_utils\-1.24" SG3_UTILS
.SH NAME
sg_dd \- copies data to and from files and devices. Specialised for
devices that understand the SCSI command set.
@@ -103,6 +103,7 @@ default is 0 which selects indirect (buffered) IO on sg devices. Value of 1
attempts direct IO which, if not available, falls back to indirect IO and
notes this at completion. If direct IO is selected and /proc/scsi/sg/allow_dio
has the value of 0 then a warning is issued (and indirect IO is performed).
+For finer grain control use 'iflag=dio' or 'oflag=dio'.
.TP
\fBibs\fR=\fIBS\fR
if given must be the same as \fIBS\fR given to 'bs=' option.
@@ -206,11 +207,17 @@ will set its CORRCT bit if 'coe' given thrice. SCSI disks may automatically
try and remap faulty sectors (see the AWRE and ARRE in the read write
error recovery mode page (the sdparm utility to access and possibly change
these attributes)). Errors occurring on other files types will stop sg_dd.
-Error messages are sent to stderr. This flag is similar to 'conv=noerror'
-in the
+Error messages are sent to stderr. This flag is similar
+ o 'conv=noerror,sync' in the
.B dd(1)
utility. See note about READ LONG below.
.TP
+dio
+request the sg device node associated with this flag does direct IO.
+If direct IO is not available, falls back to indirect IO and notes
+this at completion. If direct IO is selected and /proc/scsi/sg/allow_dio
+has the value of 0 then a warning is issued (and indirect IO is performed).
+.TP
direct
causes the O_DIRECT flag to be added to the open of \fIIFILE\fR and/or
\fIOFILE\fR. This flag requires some memory alignment on IO. Hence user
diff --git a/sg_dd.c b/sg_dd.c
index 2f4b6c44..c3585d27 100644
--- a/sg_dd.c
+++ b/sg_dd.c
@@ -51,7 +51,7 @@
This version is designed for the linux kernel 2.4 and 2.6 series.
*/
-static char * version_str = "5.60 20070124";
+static char * version_str = "5.61 20070318";
#define ME "sg_dd: "
@@ -134,6 +134,7 @@ static const char * proc_allow_dio = "/proc/scsi/sg/allow_dio";
struct flags_t {
int append;
int coe;
+ int dio;
int direct;
int dpo;
int dsync;
@@ -288,9 +289,9 @@ static void usage()
" ibs input block size (if given must be same as "
"'bs=')\n"
" if file or device to read from (def: stdin)\n"
- " iflag comma separated list from: [coe,direct,dpo,"
- "dsync,excl,fua,\n"
- " sgio]\n"
+ " iflag comma separated list from: [coe,dio,direct,"
+ "dpo,dsync,excl,\n"
+ " fua,sgio]\n"
" obs output block size (if given must be same as "
"'bs=')\n"
" odir 1->use O_DIRECT when opening block dev, "
@@ -299,9 +300,9 @@ static void usage()
"OFILE of '.'\n");
fprintf(stderr,
" treated as /dev/null\n"
- " oflag comma separated list from: [append,coe,direct"
- ",dpo,dsync,excl,\n"
- " fua,sgio]\n"
+ " oflag comma separated list from: [append,coe,dio,"
+ "direct,dpo,dsync,\n"
+ " excl,fua,sgio]\n"
" retries retry sgio errors RETR times (def: 0)\n"
" seek block position to start writing to OFILE\n"
" skip block position to start reading from IFILE\n"
@@ -992,6 +993,8 @@ static int process_flags(const char * arg, struct flags_t * fp)
fp->append = 1;
else if (0 == strcmp(cp, "coe"))
++fp->coe;
+ else if (0 == strcmp(cp, "dio"))
+ fp->dio = 1;
else if (0 == strcmp(cp, "direct"))
fp->direct = 1;
else if (0 == strcmp(cp, "dpo"))
@@ -1029,7 +1032,6 @@ int main(int argc, char * argv[])
int in_type = FT_OTHER;
char outf[INOUTF_SZ];
int out_type = FT_OTHER;
- int dio = 0;
int dio_incomplete = 0;
int cdbsz_given = 0;
int do_sync = 0;
@@ -1105,9 +1107,10 @@ int main(int argc, char * argv[])
fprintf(stderr, ME "bad argument to 'count='\n");
return SG_LIB_SYNTAX_ERROR;
}
- } else if (0 == strcmp(key, "dio"))
- dio = sg_get_num(buf);
- else if (0 == strcmp(key, "fua")) {
+ } else if (0 == strcmp(key, "dio")) {
+ oflag.dio = sg_get_num(buf);
+ iflag.dio = oflag.dio;
+ } else if (0 == strcmp(key, "fua")) {
t = sg_get_num(buf);
oflag.fua = (t & 1) ? 1 : 0;
iflag.fua = (t & 2) ? 1 : 0;
@@ -1536,7 +1539,7 @@ int main(int argc, char * argv[])
}
}
- if (dio || iflag.direct || oflag.direct || (FT_RAW & in_type) ||
+ if (iflag.dio || iflag.direct || oflag.direct || (FT_RAW & in_type) ||
(FT_RAW & out_type)) {
size_t psz = getpagesize();
wrkBuff = (unsigned char*)malloc(blk_sz * bpt + psz);
@@ -1572,7 +1575,7 @@ int main(int argc, char * argv[])
while (dd_count > 0) {
blocks = (dd_count > blocks_per) ? blocks_per : dd_count;
if (FT_SG & in_type) {
- dio_tmp = dio;
+ dio_tmp = iflag.dio;
res = sg_read(infd, wrkPos, blocks, skip, blk_sz, &iflag,
&dio_tmp, &blks_read);
if (-2 == res) { /* ENOMEM, find what's available+try that */
@@ -1604,7 +1607,7 @@ int main(int argc, char * argv[])
blocks = blks_read;
}
in_full += blocks;
- if (dio && (0 == dio_tmp))
+ if (iflag.dio && (0 == dio_tmp))
dio_incomplete++;
}
} else {
@@ -1634,7 +1637,7 @@ int main(int argc, char * argv[])
break; /* nothing read so leave loop */
if (FT_SG & out_type) {
- dio_tmp = dio;
+ dio_tmp = oflag.dio;
retries_tmp = oflag.retries;
first = 1;
while (1) {
@@ -1693,7 +1696,7 @@ int main(int argc, char * argv[])
break;
} else {
out_full += blocks;
- if (dio && (0 == dio_tmp))
+ if (oflag.dio && (0 == dio_tmp))
dio_incomplete++;
}
} else if (FT_DEV_NULL & out_type)
diff --git a/sg_format.8 b/sg_format.8
index e25d60be..be7842fe 100644
--- a/sg_format.8
+++ b/sg_format.8
@@ -1,13 +1,13 @@
-.TH SG_FORMAT "8" "January 2007" "sg3_utils\-1.23" SG3_UTILS
+.TH SG_FORMAT "8" "May 2007" "sg3_utils\-1.24" SG3_UTILS
.SH NAME
sg_format \- format or resize a SCSI disk (perhaps change its block size)
.SH SYNOPSIS
.B sg_format
-[\fI\-\-cmplst=\fR0|1] [\fI\-\-count=COUNT\fR] [\fI\-\-early\fR]
-[\fI\-\-format\fR] [\fI\-\-help\fR] [\fI\-\-long\fR] [\fI\-\-pfu=PFU\fR]
-[\fI\-\-pinfo\fR] [\fI\-\-resize\fR] [\fI\-\-rto_req\fR] [\fI\-\-six\fR]
-[\fI\-\-size=SIZE\fR] [\fI\-\-verbose\fR] [\fI\-\-version\fR]
-[\fI\-\-wait\fR] \fIDEVICE\fR
+[\fI\-\-cmplst=\fR0|1] [\fI\-\-count=COUNT\fR] [\fI\-\-dcrt\fR]
+[\fI\-\-early\fR] [\fI\-\-format\fR] [\fI\-\-help\fR] [\fI\-\-long\fR]
+[\fI\-\-pfu=PFU\fR] [\fI\-\-pinfo\fR] [\fI\-\-resize\fR] [\fI\-\-rto_req\fR]
+[\fI\-\-security\fR] [\fI\-\-six\fR] [\fI\-\-size=SIZE\fR] [\fI\-\-verbose\fR]
+[\fI\-\-version\fR] [\fI\-\-wait\fR] \fIDEVICE\fR
.SH DESCRIPTION
.\" Add any additional description here
.PP
@@ -24,10 +24,10 @@ block size (if permitted) and the block count (i.e. number of accessible
blocks on the media also known as "resizing"). Resizing a disk to less
than the manufacturer's recommended block count is sometimes called "short
stroking" (see NOTES section). Resizing the block count while not changing
-the block size may not require a format operation. Recent changes to the
-SBC\-2 draft standard (see www.t10.org) have obsoleted the "format device"
-mode page. Many of the low level details found in that mode page are now
-left up to the discretion of the manufacturer.
+the block size may not require a format operation. The SBC\-2 standard (see
+www.t10.org) has obsoleted the "format device" mode page. Many of the low
+level details found in that mode page are now left up to the discretion of
+the manufacturer.
.PP
When this utility is used without options (apart from a device name)
then it prints out the existing block size and block count derived
@@ -36,25 +36,26 @@ to a MODE SENSE command and the response to a READ CAPACITY command.
The reason for this double check is to detect a "format corrupt"
state (see NOTES section).
.PP
-A recent addition in the SBC\-2 is "protection information". See
-the section of that name (section 4.16 in draft SBC\-2 rev 16). It adds
-an extra 8 bytes of protection information to each block (a 2 byte "logical
-block guard" (CRC), a 2 byte "logical block application guard", and a
-4 byte "logical block reference tag"). A device that supports
-protection information sets the "protect" bit in a standard INQUIRY
-response. The "FMTPINFO" and "RTO_REQ" bits in the FORMAT command cdb
-are associated with protection information and can be set by this
-utility.
+Recent SBC\-3 drafts add several "protection types" to the "protection
+information" introduced in the SBC\-2 standard. See the "protection
+information" section (section 4.17 in draft SBC\-3 rev 8). 8 bytes of
+protection information are added to each block (a 2 byte "logical block
+guard" (CRC), a 2 byte "logical block application guard", and a 4
+byte "logical block reference tag"). A device that supports protection
+information sets the "protect" bit in a standard INQUIRY response.
+The "FMTPINFO" and "RTO_REQ" bits in the FORMAT command cdb plus
+the "Protection Field Usage" in the parameter header are associated with
+protection information and can be set by this utility.
.SH OPTIONS
Arguments to long options are mandatory for short options as well.
.TP
\fB\-C\fR, \fB\-\-cmplst\fR=0 | 1
sets the CMPLST ("complete list") bit in the FORMAT cdb to 0 or 1.
The default is 1 in which case the existing GLIST (grown list) is ignored.
-If the value is 0 then th existing GLIST is taken into account. See the
+If the value is 0 then the existing GLIST is taken into account. See the
LISTS section below. Active when the \fI\-\-format\fR option is given. In
most cases this bit should be left set; some MO disk drives need this bit
-cleared. The SCSI to ATA Translation (SAT) draft standard (sat\-r09)
+cleared. The SCSI to ATA Translation (SAT) standard (prior draft: sat\-r09)
requires this bit to be cleared.
.TP
\fB\-c\fR, \fB\-\-count\fR=\fICOUNT\fR
@@ -97,14 +98,23 @@ In both cases if the given \fICOUNT\fR exceeds the maximum number of
blocks (for the block size) then the disk reports an error.
See NOTES section below.
.TP
+\fB\-D\fR, \fB\-\-dcrt\fR
+this option sets the DCRT bit in the FORMAT command's parameter list header.
+It will "disable certification" which is the verification step used to check
+during the format process that blocks are usable. Using this option may
+speed the format. The default action of this utility (i.e. when this option
+is not given) is to clear the DCRT bit thereby requesting "media
+certification". When the DCRT bit is set, the FOV bit must also be set hence
+sg_format does that.
+.TP
\fB\-e\fR, \fB\-\-early\fR
this option is active when \fI\-\-format\fR is given. The default action of
this utility is to poll the disk every 30 seconds to determine the progress
of the format operation until it is finished. When this option is given this
utility will exit "early" as soon as the format has commenced. Then the
user can monitor the progress of the ongoing format operation with other
-utilities (e.g. sg_turs or sg_requests). This option and \fI\-\-wait\fR
-cannot both be given.
+utilities (e.g. sg_turs(8) or sg_requests(8)). This option and
+\fI\-\-wait\fR cannot both be given.
.TP
\fB\-F\fR, \fB\-\-format\fR
issue a SCSI FORMAT command.
@@ -130,8 +140,10 @@ supports "protection information" then this option may also be useful.
.TP
\fB\-P\fR, \fB\-\-pfu\fR=\fIPFU\fR
sets the "Protection Field Usage" field in the parameter block associated
-with a FORMAT command to \fIPFU\fR. The default value is 0, values in the
-range 0 to 7 may be given.
+with a FORMAT command to \fIPFU\fR. The default value is 0, the only other
+defined value currently is 1. Used together with \fI\-\-pinfo\fR and
+\fI\-\-rto_req\fR to specify the "protection type" to format the disk
+to (see SBC\-3).
.TP
\fB\-p\fR, \fB\-\-pinfo\fR
instructs a format operation to add an extra 8 bytes of protection
@@ -156,6 +168,12 @@ FORMAT cdb). The default action is to disable application client
ownership of that field. Has no action unless both \fI\-\-format\fR
and \fI\-\-pinfo\fR are given.
.TP
+\fB\-S\fR, \fB\-\-security\fR
+sets the "Security Initialization" (SI) bit in the FORMAT command's
+initialization pattern descriptor within the parameter list. According
+to SBC\-3 the default initialization pattern "shall be written using a
+security erasure write technique".
+.TP
\fB\-6\fR, \fB\-\-six\fR
Use 6 byte variants of MODE SENSE and MODE SELECT. The default action
is to use the 10 byte variants. Some MO drives need this option set
@@ -190,15 +208,15 @@ until the format operation completes before returning its response. This
can be several hours on large disks. This utility sets a four hour timeout
on such a FORMAT UNIT command.
.SH LISTS
-The SBC\-3 draft (revision 6) defines PLIST, CLIST, DLIST and GLIST in
+The SBC\-3 draft (revision 8) defines PLIST, CLIST, DLIST and GLIST in
section 4.8 on "Medium defects". Briefly, the PLIST is the "primary"
list of manufacturer detected defects, the CLIST ("certification" list)
-are those detected during the format operation, the DLIST is a list
-of defects that can be given to the format operation. The GLIST
-is the grown list which starts in the format process as CLIST+DLIST
-and can "grow" later due to automatic reallocation (see the
-ARRE and AWRE bits in the read\-write error recovery mode page (see
-sdparm)) and use of the SCSI REASSIGN BLOCKS command (see sg_reassign).
+are those detected during the format operation, the DLIST is a list of
+defects that can be given to the format operation. The GLIST is the grown
+list which starts in the format process as CLIST+DLIST and can "grow" later
+due to automatic reallocation (see the ARRE and AWRE bits in the
+read\-write error recovery mode page (see sdparm(8))) and use of the
+SCSI REASSIGN BLOCKS command (see sg_reassign(8)).
.PP
The CMPLST bit (controlled by the \fI\-\-cmplst=\fR0|1 option) determines
whether the existing GLIST, when the format operation is invoked,
@@ -210,13 +228,12 @@ The sg_format utility does not permit a user to provide a defect
list (i.e. DLIST). All protection information options are
defaulted to off.
.SH NOTES
-The SBC\-2 draft standard (revision 16) says that the REQUEST SENSE command
-should be used for obtaining a progress indication when the format
-command returns prior to the completion of the format operation.
-However, tests on a selection of recent disks shows that TEST UNIT READY
-commands yield progress indications (but not REQUEST SENSE commands). A
-new option may be required to handle this when disks catch up to the current
-draft.
+The SBC\-2 standard states that the REQUEST SENSE command should be used
+for obtaining a progress indication when the format command returns prior
+to the completion of the format operation. However, tests on a selection
+of recent disks shows that TEST UNIT READY commands yield progress
+indications (but not REQUEST SENSE commands). A new option may be required
+to handle this when disks catch up.
.PP
When the \fI\-\-format\fR option is given then there is a 10 second window
during which the user is invited to abort sg_format. This is just prior the
@@ -236,7 +253,7 @@ corrupt".
.PP
When the \fI\-\-format\fR and \fI\-\-wait\fR options are both given then
this utility may take a long time to return. In this case care should be
-taken not to send any other SCSI commands to the disk as it may not respon
+taken not to send any other SCSI commands to the disk as it may not respond
leaving those commands queued behind the active format command. This may
cause a timeout in the OS driver (in a lot shorter period than 4 hours
applicable to the format command). This may result in the OS resetting
@@ -256,7 +273,7 @@ potentially requiring a format. The solution to this situation is to
do a format again (and this time the new block size does not have to
be given) or change the block size back to the original size.
.PP
-The draft SBC\-2 standard states that the block count can be set back
+The SBC\-2 standard states that the block count can be set back
to the manufacturer's maximum recommended value in a format or resize
operation. This can be done by placing an address of 0xffffffff (or the
64 bit equivalent) in the appropriate block descriptor field to a MODE
@@ -272,9 +289,9 @@ logical block addresses) so by resizing or reformatting a disk to
a smaller capacity, average performance will usually be increased.
.PP
Other utilities may be useful in finding information associated with
-formatting. These include sg_inq to fetch standard INQUIRY
+formatting. These include sg_inq(8) to fetch standard INQUIRY
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
+VPD page (e.g. RTO and GRD_CHK bits). The sdparm(8) 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
@@ -328,7 +345,7 @@ Now resize the disk back to its normal (maximum) block count:
The exit status of sg_format is 0 when it is successful. Otherwise see
the sg3_utils(8) man page. Unless the \fI\-\-wait\fR option is given, the
exit status may not reflect to success of otherwise of the format.
-Using sg_turs and sg_readcap after the format operation may be wise.
+Using sg_turs(8) and sg_readcap(8) after the format operation may be wise.
.SH AUTHORS
Written by Grant Grundler, James Bottomley and Douglas Gilbert.
.SH "REPORTING BUGS"
@@ -339,5 +356,5 @@ Copyright \(co 2005\-2007 Grant Grundler, James Bottomley and Douglas Gilbert
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_reassign
-.B (all in sg3_utils), sdparm, scsiformat, setblocksize
+.B sg_turs(8), sg_requests(8), sg_inq(8), sg_modes(8), sg_vpd(8)
+.B sg_reassign(8) [all in sg3_utils], sdparm(8), scsiformat (old)
diff --git a/sg_format.c b/sg_format.c
index 6f89229f..4867d2b8 100644
--- a/sg_format.c
+++ b/sg_format.c
@@ -69,11 +69,12 @@
#define MAX_BUFF_SZ 252
static unsigned char dbuff[MAX_BUFF_SZ];
-static char * version_str = "1.13 20070125";
+static char * version_str = "1.14 20070327";
static struct option long_options[] = {
{"count", 1, 0, 'c'},
{"cmplst", 1, 0, 'C'},
+ {"dcrt", 0, 0, 'D'},
{"early", 0, 0, 'e'},
{"format", 0, 0, 'F'},
{"help", 0, 0, 'h'},
@@ -82,6 +83,7 @@ static struct option long_options[] = {
{"pfu", 1, 0, 'P'},
{"resize", 0, 0, 'r'},
{"rto_req", 0, 0, 'R'},
+ {"security", 0, 0, 'X'},
{"six", 0, 0, '6'},
{"size", 1, 0, 's'},
{"verbose", 0, 0, 'v'},
@@ -93,24 +95,35 @@ static struct option long_options[] = {
/* Return 0 on success, else see sg_ll_format_unit() */
static int
scsi_format(int fd, int fmtpinfo, int rto_req, int cmplst, int pf_usage,
- int immed, int early, int verbose)
+ int immed, int dcrt, int si, int early, int verbose)
{
- int res, need_hdr, progress, verb;
- const char FORMAT_HEADER_SIZE = 4;
- unsigned char fmt_hdr[FORMAT_HEADER_SIZE];
-
- fmt_hdr[0] = pf_usage & 0x7; /* protection_field_usage (bits 2-0) */
- fmt_hdr[1] = (immed ? 0x2 : 0); /* fov=0, [dpry,dcrt,stpf,ip=0] */
- fmt_hdr[2] = 0; /* defect list length MSB */
- fmt_hdr[3] = 0; /* defect list length LSB */
+ int res, need_hdr, progress, verb, pl_sz;
+ const char FORMAT_HEADER_SZ = 4;
+ const char INIT_PATTERN_DESC_SZ = 4;
+ unsigned char fmt_pl[FORMAT_HEADER_SZ + INIT_PATTERN_DESC_SZ];
+
+ memset(fmt_pl, 0, sizeof(fmt_pl));
+ fmt_pl[0] = pf_usage & 0x7; /* protection_field_usage (bits 2-0) */
+ fmt_pl[1] = (immed ? 0x2 : 0); /* fov=0, [dpry,dcrt,stpf,ip=0] */
+ if (dcrt)
+ fmt_pl[1] |= 0xa0; /* fov=1, dcrt=1 */
+ if (si) {
+ fmt_pl[1] |= 0x88; /* fov=1, ip=1 */
+ fmt_pl[4] = 0x20; /* si=1 in init. pattern desc */
+ }
+ fmt_pl[2] = 0; /* defect list length MSB */
+ fmt_pl[3] = 0; /* defect list length LSB */
- need_hdr = (immed || cmplst || (pf_usage > 0));
+ need_hdr = (immed || cmplst || dcrt || si || (pf_usage > 0));
+ if (need_hdr)
+ pl_sz = si ? 8 : 4;
+ else
+ pl_sz = 0;
res = sg_ll_format_unit(fd, fmtpinfo, rto_req, 0 /* longlist */,
need_hdr /* fmtdata */, cmplst,
0 /* dlist_format */,
(immed ? SHORT_TIMEOUT : FORMAT_TIMEOUT),
- fmt_hdr, (need_hdr ? sizeof(fmt_hdr) : 0),
- 1, verbose);
+ fmt_pl, pl_sz, 1, verbose);
switch (res) {
case 0:
@@ -232,54 +245,59 @@ print_read_cap(int fd, int do_16, int verbose)
static void usage()
{
- printf("usage: sg_format [--cmplst=0|1] [--count=COUNT] [--early] "
- "[--format] [--help]\n"
- " [--long] [--pfu=PFU] [--pinfo] [--resize] "
- "[--rto_req] [--six]\n"
- " [--size=SIZE] [--verbose] [--version] "
- "[--wait] DEVICE\n"
- " where:\n"
- " --cmplst=0|1\n"
- " -C 0|1 sets CMPLST bit in format cdb "
- "(default: 1)\n"
- " --count=COUNT|-c COUNT number of blocks to "
- "report after format or\n"
- " resize. With format "
- "defaults to same as current\n"
- " --early|-e exit once format started (user can "
- "monitor progress)\n"
- " --format|-F format unit (default: report current count"
- " and size)\n"
- " --help|-h prints out this usage message\n"
- " --long|-l allow for 64 bit lbas (default: assume "
- "32 bit lbas)\n"
- " --pfu=PFU|-P PFU Protection Field Usage value "
- "(default: 0)\n"
- " --pinfo|-p set the FMTPINFO bit to format with "
- "protection\n");
- printf( " information (defaults to no protection "
- "information)\n"
- " --resize|-r resize (rather than format) to COUNT "
- "value\n"
- " --rto_req|-R set the RTO_REQ bit in format (only "
- "vaid with '--pinfo')\n"
- " --six|-6 use 6 byte MODE SENSE/SELECT\n"
- " --size=SIZE|-s SIZE bytes per block, defaults to "
- "DEVICE's current\n"
- " block size. Only needed to "
- "change current block\n"
- " size\n"
- " --verbose|-v increase verbosity\n"
- " --version|-V print version details and exit\n"
- " --wait|-w format command waits until format "
- "operation completes\n"
- " (default: set IMMED=1 and poll with "
- "Test Unit Ready)\n\n"
- "\tExample: sg_format --format /dev/sdc\n\n"
- "This utility formats or resizes SCSI disks.\n");
+ printf("usage: sg_format [--cmplst=0|1] [--count=COUNT] [--dcrt] "
+ "[--early] [--format]\n"
+ " [--help] [--long] [--pfu=PFU] [--pinfo] "
+ "[--resize]\n"
+ " [--rto_req] [--security] [--six] "
+ "[--size=SIZE] [--verbose]\n"
+ " [--version] [--wait] "
+ "DEVICE\n"
+ " where:\n"
+ " --cmplst=0|1\n"
+ " -C 0|1 sets CMPLST bit in format cdb "
+ "(default: 1)\n"
+ " --count=COUNT|-c COUNT number of blocks to "
+ "report after format or\n"
+ " resize. With format "
+ "defaults to same as current\n"
+ " --dcrt|-D disable certification (doesn't "
+ "verify media)\n"
+ " --early|-e exit once format started (user can "
+ "monitor progress)\n"
+ " --format|-F format unit (default: report current count"
+ " and size)\n"
+ " --help|-h prints out this usage message\n"
+ " --long|-l allow for 64 bit lbas (default: assume "
+ "32 bit lbas)\n"
+ " --pfu=PFU|-P PFU Protection Field Usage value "
+ "(default: 0)\n"
+ " --pinfo|-p set the FMTPINFO bit to format with "
+ "protection\n");
+ printf(" information (defaults to no protection "
+ "information)\n"
+ " --resize|-r resize (rather than format) to COUNT "
+ "value\n"
+ " --rto_req|-R set the RTO_REQ bit in format (only "
+ "vaid with '--pinfo')\n"
+ " --security|-S set security initialization (SI) bit\n"
+ " --six|-6 use 6 byte MODE SENSE/SELECT\n"
+ " --size=SIZE|-s SIZE bytes per block, defaults to "
+ "DEVICE's current\n"
+ " block size. Only needed to "
+ "change current block\n"
+ " size\n"
+ " --verbose|-v increase verbosity\n"
+ " --version|-V print version details and exit\n"
+ " --wait|-w format command waits until format "
+ "operation completes\n"
+ " (default: set IMMED=1 and poll with "
+ "Test Unit Ready)\n\n"
+ "\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 "
- "DEVICE when\n\t '--format' is given. Check that you "
- "have the correct DEVICE.\n");
+ "DEVICE when\n\t '--format' is given. Check that you "
+ "have the correct DEVICE.\n");
}
@@ -302,6 +320,8 @@ int main(int argc, char **argv)
int cmplst = 1;
int do_rcap16 = 0;
int long_lba = 0;
+ int dcrt = 0;
+ int do_si = 0;
int early = 0;
char device_name[256];
char pdt_name[64];
@@ -313,7 +333,7 @@ int main(int argc, char **argv)
int option_index = 0;
int c;
- c = getopt_long(argc, argv, "c:C:eFhlpP:rRs:vVw6",
+ c = getopt_long(argc, argv, "c:C:DeFhlpP:rRs:SvVw6",
long_options, &option_index);
if (c == -1)
break;
@@ -339,6 +359,9 @@ int main(int argc, char **argv)
return SG_LIB_SYNTAX_ERROR;
}
break;
+ case 'D':
+ dcrt = 1;
+ break;
case 'e':
early = 1;
break;
@@ -377,6 +400,9 @@ int main(int argc, char **argv)
return SG_LIB_SYNTAX_ERROR;
}
break;
+ case 'S':
+ do_si = 1;
+ break;
case 'v':
verbose++;
break;
@@ -434,11 +460,6 @@ int main(int argc, char **argv)
}
}
- /* FIXME: add more sanity checks:
- ** o block size/count might already be set...don't repeat
- ** o verify SCSI device is a disk (get inquiry data first)
- */
-
if ((fd = sg_cmds_open_device(device_name, 0 /* rw */, verbose)) < 0) {
fprintf(stderr, "error opening device file: %s: %s\n",
device_name, safe_strerror(-fd));
@@ -702,7 +723,7 @@ int main(int argc, char **argv)
printf(" Press control-C to abort\n");
sleep_for(5);
res = scsi_format(fd, pinfo, rto_req, cmplst, pfu, ! fwait,
- early, verbose);
+ dcrt, do_si, early, verbose);
ret = res;
if (res) {
fprintf(stderr, "FORMAT failed\n");
diff --git a/sg_get_config.8 b/sg_get_config.8
index 6bff500c..ff81eeae 100644
--- a/sg_get_config.8
+++ b/sg_get_config.8
@@ -1,4 +1,4 @@
-.TH SG_GET_CONFIG "8" "January 2007" "sg3_utils\-1.23" SG3_UTILS
+.TH SG_GET_CONFIG "8" "February 2007" "sg3_utils\-1.24" SG3_UTILS
.SH NAME
sg_get_config \- sends a SCSI GET CONFIGURATION command
.SH SYNOPSIS
@@ -68,7 +68,17 @@ to \fI\-\-starting=\fR). When \fIRT\fR is 1 then all current features are
returned (whose feature code is greater than or equal to \fIFC\fR). When
\fIRT\fR is 2 then the feature whose feature code is equal to \fIFC\fR,
if any, is returned. When \fIRT\fR is 3 the response is reserved (probably
-yields an "illegal field in cdb" error).
+yields an "illegal field in cdb" error). To simplify the meanings of the
+\fIRT\fR values are:
+.br
+ \fB0\fR : all features, current on not
+.br
+ \fB1\fR : only current features
+.br
+ \fB2\fR : only feature whose code is \fIFC\fR
+.br
+ \fB3\fR : reserved
+.br
.TP
\fB\-s\fR, \fB\-\-starting\fR=\fIFC\fR
where \fIFC\fR is the feature code value. This option works closely with
@@ -96,7 +106,7 @@ 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 sdpar, sginfo or sg_modes.
+mode page can be checked with sdparm(8), sginfo(8) or sg_modes(8).
.PP
In the 2.4 series of Linux kernels the \fIDEVICE\fR must be
a SCSI generic (sg) device. In the 2.6 series block devices
@@ -117,5 +127,6 @@ Copyright \(co 2004\-2007 Douglas Gilbert
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
+.B sginfo(8), sg_modes(8), sg_inq(8), sg_prevent(8),
+.B sg_start(8) [all in sg3_utils],
+.B sdparm(8)
diff --git a/sg_get_config.c b/sg_get_config.c
index 17fec041..f528884f 100644
--- a/sg_get_config.c
+++ b/sg_get_config.c
@@ -46,7 +46,7 @@
*/
-static char * version_str = "0.30 20070125";
+static char * version_str = "0.30 20070419";
#define MX_ALLOC_LEN 8192
#define NAME_BUFF_SZ 64
@@ -938,7 +938,7 @@ int main(int argc, char * argv[])
fprintf(stderr, ME "version: %s\n", version_str);
return 0;
default:
- fprintf(stderr, "unrecognised switch code 0x%x ??\n", c);
+ fprintf(stderr, "unrecognised option code 0x%x ??\n", c);
usage();
return SG_LIB_SYNTAX_ERROR;
}
diff --git a/sg_ident.c b/sg_ident.c
index 57cf307a..d15d98ba 100644
--- a/sg_ident.c
+++ b/sg_ident.c
@@ -46,7 +46,7 @@
* DEVICE IDENTIFIER and SET DEVICE IDENTIFIER prior to spc4r07.
*/
-static char * version_str = "1.06 20070127";
+static char * version_str = "1.06 20070419";
#define ME "sg_ident: "
@@ -169,7 +169,7 @@ int main(int argc, char * argv[])
fprintf(stderr, ME "version: %s\n", version_str);
return 0;
default:
- fprintf(stderr, "unrecognised switch code 0x%x ??\n", c);
+ fprintf(stderr, "unrecognised option code 0x%x ??\n", c);
usage();
return SG_LIB_SYNTAX_ERROR;
}
diff --git a/sg_inq.8 b/sg_inq.8
index 205d9492..bc2b535b 100644
--- a/sg_inq.8
+++ b/sg_inq.8
@@ -1,4 +1,4 @@
-.TH SG_INQ "8" "January 2007" "sg3_utils\-1.23" SG3_UTILS
+.TH SG_INQ "8" "February 2007" "sg3_utils\-1.24" SG3_UTILS
.SH NAME
sg_inq \- sends a SCSI INQUIRY or ATA IDENTIFY (PACKET) DEVICE command
and outputs the response
@@ -33,9 +33,7 @@ An important "non\-standard" INQUIRY page is the Device Identification
Vital Product Data (VPD) page [0x83]. Since SPC\-3, support for this page
has been flagged as mandatory. The \fI\-\-id\fR option decodes this page.
To get fine grained decoding of this VPD page and others, including
-some vendor specific VPD pages, see the
-.B sg_vpd
-utility.
+some vendor specific VPD pages, see the sg_vpd(8) utility.
.PP
If the \fIDEVICE\fR exists and the SCSI INQUIRY fails (because the SG_IO ioctl
is not supported) then an ATA IDENTIFY (PACKET) DEVICE is tried. If it
@@ -65,7 +63,7 @@ SCSI command opcode to query. When used twice (e.g. '\-cc') this utility
forms a list by looping over all 256 opcodes (0 to 255 inclusive) only
outputting a line for found commands. The CmdDt bit is now obsolete.
It has been replaced by the REPORT SUPPORTED OPERATION CODES command,
-see the sg_opcodes utility.
+see the sg_opcodes(8) utility.
.TP
\fB\-d\fR, \fB\-\-descriptors\fR
decodes and prints the version descriptors found in a standard INQUIRY
@@ -219,7 +217,7 @@ opcode to query. Equivalent to \fI\-\-cmddt\fR in the main description.
\fB\-cl\fR
lists the command data for all supported commands (followed by the command
name) by looping through all 256 opcodes. This option uses the CmdDt bit
-which is now obsolete. See the sg_opcodes utility.
+which is now obsolete. See the sg_opcodes(8) utility.
Equivalent to '\-\-cmddt \-\-cmddt' in the main description.
.TP
\fB\-d\fR
@@ -271,8 +269,8 @@ and their names (if known). To decode the mandatory device identification
page (0x83) use the \fI\-i\fR option. A now obsolete usage is when the
\fI\-c\fR option is given in which case the argument to this option is assumed
to be a command opcode number. Recent SCSI draft standards have moved this
-facility to a separate command (see sg_opcodes). Defaults to 0 so if \fI\-e\fR
-is given without this option then VPD page 0 is output.
+facility to a separate command (see sg_opcodes(8)). Defaults to 0 so if
+\fI\-e\fR is given without this option then VPD page 0 is output.
.TP
\fB\-p\fR=\fIVPD_PG\fR
same action as \fI\-o=OPCODE_PG\fR option described in the previous entry.
@@ -319,4 +317,4 @@ Copyright \(co 2001\-2007 Douglas Gilbert
This software is distributed under the GPL version 2. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
.SH "SEE ALSO"
-.B sg_opcodes sg_vpd(sg3_utils), hdparm(hdparm), sgdiag(scsirastools)
+.B sg_opcodes(8), sg_vpd(8), hdparm(8), sgdiag(scsirastools)
diff --git a/sg_inq.c b/sg_inq.c
index 98996c0c..59ce3fde 100644
--- a/sg_inq.c
+++ b/sg_inq.c
@@ -63,7 +63,7 @@
* information [MAINTENANCE IN, service action = 0xc]; see sg_opcodes.
*/
-static char * version_str = "0.70 20070125"; /* spc-4 rev 08 */
+static char * version_str = "0.70 20070429"; /* spc-4 rev 10 */
#define VPD_SUPPORTED_VPDS 0x0
@@ -329,6 +329,7 @@ static int process_cl_new(struct opts_t * optsp, int argc, char * argv[])
case 'e':
case 'x':
++optsp->do_decode;
+ ++optsp->do_vpd;
optsp->page_num = VPD_EXT_INQ;
break;
case 'h':
@@ -340,6 +341,7 @@ static int process_cl_new(struct opts_t * optsp, int argc, char * argv[])
break;
case 'i':
++optsp->do_decode;
+ ++optsp->do_vpd;
optsp->page_num = VPD_DEVICE_ID;
break;
case 'l':
@@ -369,7 +371,7 @@ static int process_cl_new(struct opts_t * optsp, int argc, char * argv[])
++optsp->do_version;
break;
default:
- fprintf(stderr, "unrecognised switch code %c [0x%x]\n", c, c);
+ fprintf(stderr, "unrecognised option code %c [0x%x]\n", c, c);
if (optsp->do_help)
break;
usage_for(optsp);
@@ -847,7 +849,7 @@ static const char * id_type_arr[] =
"EUI-64 based",
"NAA",
"Relative target port",
- "Target port group",
+ "Target port group", /* spc4r09: _primary_ target port group */
"Logical unit group",
"MD5 logical unit identifier",
"SCSI name string",
@@ -1047,7 +1049,7 @@ static void decode_dev_ids(const char * leadin, unsigned char * buff,
d_id = ((ip[2] << 8) | ip[3]);
printf(" Relative target port: 0x%x\n", d_id);
break;
- case 5: /* Target port group */
+ case 5: /* (primary) Target port group */
if ((1 != c_set) || (1 != assoc) || (4 != i_len)) {
fprintf(stderr, " << expected binary code_set, target "
"port association, length 4>>\n");
@@ -1312,7 +1314,7 @@ static void decode_b0_vpd(unsigned char * buff, int len, int do_hex, int pdt)
return;
}
switch (pdt) {
- case 0: case 4: case 7:
+ case 0: case 4: case 7:
if (len < 16) {
fprintf(stderr, "Block limits VPD page length too "
"short=%d\n", len);
@@ -1322,10 +1324,16 @@ static void decode_b0_vpd(unsigned char * buff, int len, int do_hex, int pdt)
printf(" Optimal transfer length granularity: %u blocks\n", u);
u = (buff[8] << 24) | (buff[9] << 16) | (buff[10] << 8) |
buff[11];
- printf(" Maximum transfer length: %u blocks\n", u);
+ printf(" Maximum transfer length: %u blocks\n", u);
u = (buff[12] << 24) | (buff[13] << 16) | (buff[14] << 8) |
buff[15];
printf(" Optimal transfer length: %u blocks\n", u);
+ if (len > 19) { /* added in sbc3r09 */
+ u = (buff[16] << 24) | (buff[17] << 16) | (buff[18] << 8) |
+ buff[19];
+ printf(" Maximum prefetch, xdread, xdwrite transfer length: %u "
+ "blocks\n", u);
+ }
break;
case 1: case 8:
printf(" WORM=%d\n", !!(buff[4] & 0x1));
@@ -2421,6 +2429,8 @@ int main(int argc, char * argv[])
usage_for(&opts);
return SG_LIB_SYNTAX_ERROR;
}
+ if (((opts.do_vpd || opts.do_cmddt)) && (opts.page_num < 0))
+ opts.page_num = 0;
if (opts.num_pages > 1) {
fprintf(stderr, "Can only fetch one page (VPD or Cmd) at a time\n");
usage_for(&opts);
@@ -2575,7 +2585,8 @@ static int ata_command_interface(int device, char *data, int * atapi_flag,
"\t%s [%d]\n", safe_strerror(errno), errno);
return errno;
}
- }
+ } else if (verbose > 1)
+ fprintf(stderr, "HDIO_GET_IDENTITY succeeded\n");
if (0x2 == ((get_ident[0] >> 14) &0x3)) { /* ATAPI device */
if (verbose > 1)
fprintf(stderr, "assume ATAPI device from HDIO_GET_IDENTITY "
@@ -2597,8 +2608,11 @@ static int ata_command_interface(int device, char *data, int * atapi_flag,
errno);
return errno;
}
- } else if (atapi_flag)
+ } else if (atapi_flag) {
*atapi_flag = 1;
+ if (verbose > 1)
+ fprintf(stderr, "HDIO_DRIVE_CMD(ATA_IDENTIFY_DEVICE) succeeded\n");
+ }
} else { /* assume non-packet device */
buff[0] = ATA_IDENTIFY_DEVICE;
buff[3] = 1;
@@ -2608,7 +2622,8 @@ static int ata_command_interface(int device, char *data, int * atapi_flag,
"ioctl failed:\n\t%s [%d]\n", safe_strerror(errno),
errno);
return errno;
- }
+ } else if (verbose > 1)
+ fprintf(stderr, "HDIO_DRIVE_CMD(ATA_IDENTIFY_DEVICE) succeeded\n");
}
/* if the command returns data, copy it back */
memcpy(data, buff + HDIO_DRIVE_CMD_OFFSET, ATA_IDENTIFY_BUFF_SZ);
@@ -2713,6 +2728,7 @@ static struct version_descriptor version_descriptor_arr[] = {
{0x1a0, "SMC (no version claimed)"},
{0x1bb, "SMC T10/0999-D revision 10a"},
{0x1bc, "SMC ANSI INCITS 314-1998"},
+ {0x1be, "SMC ISO/IEC 14776-351"},
{0x1c0, "SES (no version claimed)"},
{0x1db, "SES T10/1212-D revision 08b"},
{0x1dc, "SES ANSI INCITS 305-1998"},
@@ -2740,6 +2756,7 @@ static struct version_descriptor version_descriptor_arr[] = {
{0x275, "SPC-2 T10/1236-D revision 19"},
{0x276, "SPC-2 T10/1236-D revision 20"},
{0x277, "SPC-2 ANSI INCITS 351-2001"},
+ {0x278, "SPC-2 ISO/IEC 14776-452"},
{0x280, "OCRW (no version claimed)"},
{0x29e, "OCRW ISO/IEC 14776-381"},
{0x2a0, "MMC-3 (no version claimed)"},
@@ -2775,7 +2792,7 @@ static struct version_descriptor version_descriptor_arr[] = {
{0x37d, "SSC-2 ANSI INCITS 380-2003"},
{0x380, "BCC (no version claimed)"},
{0x3a0, "MMC-4 (no version claimed)"},
- {0x3b0, "MMC-4 T10/1545-D revision 5"},
+ {0x3b0, "MMC-4 T10/1545-D revision 5"}, /* dropped in spc4r09 */
{0x3b1, "MMC-4 T10/1545-D revision 5a"},
{0x3bd, "MMC-4 T10/1545-D revision 3"},
{0x3be, "MMC-4 T10/1545-D revision 3d"},
@@ -2794,6 +2811,7 @@ static struct version_descriptor version_descriptor_arr[] = {
{0x460, "SPC-4 (no version claimed)"},
{0x480, "SMC-3 (no version claimed)"},
{0x4a0, "ADC-2 (no version claimed)"},
+ {0x4a7, "ADC-2 T10/1741-D revision 7"},
{0x4c0, "SBC-3 (no version claimed)"},
{0x4e0, "MMC-6 (no version claimed)"},
{0x820, "SSA-TL2 (no version claimed)"},
@@ -2845,6 +2863,7 @@ static struct version_descriptor version_descriptor_arr[] = {
{0xa00, "FCP-3 (no version claimed)"},
{0xa07, "FCP-3 T10/1560-D revision 3f"},
{0xa0f, "FCP-3 T10/1560-D revision 4"},
+ {0xa11, "FCP-3 ANSI INCITS 416-2006"},
{0xa20, "ADT-2 (no version claimed)"},
{0xa40, "FCP-4 (no version claimed)"},
{0xaa0, "SPI (no version claimed)"},
@@ -2911,7 +2930,10 @@ static struct version_descriptor version_descriptor_arr[] = {
{0xddc, "FC-PI ANSI INCITS 352-2002"},
{0xde0, "FC-PI-2 (no version claimed)"},
{0xde2, "FC-PI-2 T11/1506-D revision 5.0"},
+ {0xde4, "FC-PI-2 ANSI INCITS 404-2006"},
{0xe00, "FC-FS-2 (no version claimed)"},
+ {0xe02, "FC-FS-2 ANSI INCITS 242-2007"},
+ {0xe04, "FC-FS-2 ANSI INCITS 242-2007 with AM1 ANSI INCITS 242/AM1-2007"},
{0xe20, "FC-LS (no version claimed)"},
{0xe40, "FC-SP (no version claimed)"},
{0xe42, "FC-SP T11/1570-D revision 1.6"},
@@ -2958,6 +2980,7 @@ static struct version_descriptor version_descriptor_arr[] = {
{0x1ea0, "SAT (no version claimed)"},
{0x1ea7, "SAT T10/1711-D rev 8"},
{0x1eab, "SAT T10/1711-D rev 9"},
+ {0x1ead, "SAT ANSI INCITS 431-2007"},
{0x1ec0, "SAT-2 (no version claimed)"},
};
diff --git a/sg_io_linux.h b/sg_io_linux.h
index 30047c11..08d0b405 100644
--- a/sg_io_linux.h
+++ b/sg_io_linux.h
@@ -162,10 +162,6 @@ extern int sg_chk_n_print3(const char * leadin, struct sg_io_hdr * hp,
extern int sg_normalize_sense(const struct sg_io_hdr * hp,
struct sg_scsi_sense_hdr * sshp);
-
-/* Some extra "category" function returns (beyond those in sg_lib.h) */
-#define SG_LIB_CAT_TIMEOUT 33
-
extern int sg_err_category(int masked_status, int host_status,
int driver_status, const unsigned char * sense_buffer,
int sb_len);
diff --git a/sg_lib.c b/sg_lib.c
index 0dac2f4d..063d209c 100644
--- a/sg_lib.c
+++ b/sg_lib.c
@@ -71,7 +71,7 @@
#include "sg_lib.h"
-static char * version_str = "1.32 20070129"; /* spc-4 rev 8 */
+static char * version_str = "1.34 20070422"; /* spc-4 rev 10 */
FILE * sg_warnings_strm = NULL; /* would like to default to stderr */
@@ -1086,6 +1086,9 @@ static struct error_info additional[] =
{0x74,0x03,"Incorrect data encryption key"},
{0x74,0x04,"Cryptographic integrity validation failed"},
{0x74,0x05,"Error decrypting data"},
+ {0x74,0x06,"Unknown signature verification key"},
+ {0x74,0x07,"Encryption parameters not useable"},
+ {0x74,0x08,"Digital signature validation failure"},
{0x74,0x71,"Logical unit access not authorized"},
{0, 0, NULL}
};
diff --git a/sg_lib.h b/sg_lib.h
index c650c885..71549f4c 100644
--- a/sg_lib.h
+++ b/sg_lib.h
@@ -30,7 +30,7 @@
*
*/
-/* Version 1.32 [20070129]
+/* Version 1.34 [20070422]
*
* 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
@@ -223,6 +223,17 @@ extern void sg_print_scsi_status(int scsi_status);
extern int sg_err_category_sense(const unsigned char * sense_buffer,
int sb_len);
+/* Here are some additional sense data categories that are not returned
+ by sg_err_category_sense() but are returned by some related functions. */
+#define SG_LIB_CAT_ILLEGAL_REQ_WITH_INFO 17 /* Illegal request (other than */
+ /* invalid opcode) plus 'info' field: */
+ /* [sk,asc,ascq: 0x5,*,*] */
+#define SG_LIB_CAT_MEDIUM_HARD_WITH_INFO 18 /* medium or hardware error */
+ /* sense key plus 'info' field: */
+ /* [sk,asc,ascq: 0x3/0x4,*,*] */
+#define SG_LIB_CAT_TIMEOUT 33
+
+
/* Iterates to next designation descriptor in the device identification
VPD page. The 'initial_desig_desc' should point to start of first
descriptor with 'page_len' being the number of valid bytes in that
diff --git a/sg_logs.8 b/sg_logs.8
index 2e4abd45..7f1336eb 100644
--- a/sg_logs.8
+++ b/sg_logs.8
@@ -1,18 +1,18 @@
-.TH SG_LOGS "8" "January 2007" "sg3_utils\-1.23" SG3_UTILS
+.TH SG_LOGS "8" "April 2007" "sg3_utils\-1.24" SG3_UTILS
.SH NAME
sg_logs \- access log pages with SCSI LOG SENSE command
.SH SYNOPSIS
.B sg_logs
-[\fI\-\-all\fR] [\fI\-\-control=PC\fR] [\fI\-\-help\fR] [\fI\-\-hex\fR]
-[\fI\-\-list\fR] [\fI\-\-maxlen=LEN\fR] [\fI\-\-name\fR]
+[\fI\-\-all\fR] [\fI\-\-brief\fR] [\fI\-\-control=PC\fR] [\fI\-\-help\fR]
+[\fI\-\-hex\fR] [\fI\-\-list\fR] [\fI\-\-maxlen=LEN\fR] [\fI\-\-name\fR]
[\fI\-\-page=PG[,SPG]\fR] [\fI\-\-paramp=PP\fR] [\fI\-\-pcb\fR]
[\fI\-\-ppc\fR] [\fI\-\-raw\fR] [\fI\-\-reset\fR] [\fI\-\-select\fR]
[\fI\-\-sp\fR] [\fI\-\-temperature\fR] [\fI\-\-transport\fR]
[\fI\-\-verbose\fR] [\fI\-\-version\fR] \fIDEVICE\fR
.PP
.B sg_logs
-[\fI\-a\fR] [\fI\-A\fR] [\fI\-c=PC\fR] [\fI\-h\fR] [\fI\-H\fR] [\fI\-l\fR]
-[\fI\-L\fR] [\fI\-m=LEN\fR] [\fI\-n\fR] [\fI\-p=PG[,SPG]\fR]
+[\fI\-a\fR] [\fI\-A\fR] [\fI\-b\fR] [\fI\-c=PC\fR] [\fI\-h\fR] [\fI\-H\fR]
+[\fI\-l\fR] [\fI\-L\fR] [\fI\-m=LEN\fR] [\fI\-n\fR] [\fI\-p=PG[,SPG]\fR]
[\fI\-paramp=PP\fR] [\fI\-pcb\fR] [\fI\-ppc\fR] [\fI\-r\fR] [\fI\-select\fR]
[\fI\-sp\fR] [\fI\-t\fR] [\fI\-T\fR] [\fI\-v\fR] [\fI\-V\fR] [\fI\-?\fR]
\fIDEVICE\fR
@@ -42,11 +42,23 @@ process: first the "supported log pages" log page is fetched, then for each
entry in the response, the corresponding log page is fetched and displayed.
When used twice (e.g. '-aa') all log pages and subpages are fetched.
.TP
+\fB\-b\fR, \fB\-\-brief\fR
+shorten the amount of output for some log pages. For example the Tape
+Alert log page only outputs parameters whose flags are set when
+\fI\-\-brief\fR is given.
+.TP
\fB\-c\fR, \fB\-\-control\fR=\fIPC\fR
-accepts 0, 1, 2 or 3 for the \fIPC\fR argument. 0 for current threshold
-values, 1 for current cumulative values, 2 for default threshold values and
-3 for default cumulative values. The default is 1 (i.e. current threshold
-values).
+accepts 0, 1, 2 or 3 for the \fIPC\fR argument:
+.br
+ \fB0\fR : current threshold values
+.br
+ \fB1\fR : current cumulative values
+.br
+ \fB2\fR : default threshold values
+.br
+ \fB3\fR : default cumulative values
+.br
+The default value is 1 (i.e. current cumulative values).
.TP
\fB\-h\fR, \fB\-\-help\fR
print out the usage message then exit.
@@ -66,9 +78,10 @@ supported by this device. There is a list of common log page codes below.
sets the "allocation length" field in the LOG SENSE cdb. The is the maximum
length in bytes that the response will be. Without this option (or \fILEN\fR
equal to 0) this utility first fetches the 4 byte response then does a second
-access with the length indicated in the first (4 byte) response. Responses
-can be quite large (e.g. the background scan results log page) and this
-option can be used to limit the amount of information returned.
+access with the length indicated in the first (4 byte) response. Negative
+values and 1 for \fILEN\fR are not accepted. Responses can be quite
+large (e.g. the background scan results log page) and this option can be
+used to limit the amount of information returned.
.TP
\fB\-n\fR, \fB\-\-name\fR
decode some log pages into 'name=value' entries, one per line. The name
@@ -149,9 +162,18 @@ increase level of verbosity.
\fB\-V\fR, \fB\-\-version\fR
print out version string then exit.
.SH NOTES
+This utility will usually do a double fetch of log pages with the SCSI LOG
+SENSE command. The first fetch requests a 4 byte response (i.e. place 4 in
+the "allocation length" field in the cdb). From that response it can
+calculate the actual length of the response which is what it asks for
+on the second fetch. This is typical practice in SCSI and guaranteed to
+work in the standards. However some older devices don't comply. For
+those devices using the \fI\-\-maxlen=LEN\fR option will do a single fetch.
+A value of 252 should be a safe starting point.
+.PP
Various log pages hold information error rates, device temperature,
start stop cycles since device produced and the results of the last
-20 self tests. Self tests can be initiated by the sg_senddiag utility.
+20 self tests. Self tests can be initiated by the sg_senddiag(8) utility.
The smartmontools package provides much of the information found with
sg_logs in a form suitable for monitoring the health of SCSI disks and
tape drives.
@@ -196,6 +218,8 @@ the leading "0x", or as their decimal equivalents.]:
.br
0x18 Protocol specific port (SAS transport)
.br
+0x19 General statistics and performance
+.br
0x2f Informational exceptions
.br
0x37 Seagate cache (vendor, disk)
@@ -207,7 +231,7 @@ generic (sg) device. In the 2.6 series block devices (e.g. SCSI disks
and DVD drives) can also be specified. For example "sg_logs \-a /dev/sda"
will work in the 2.6 series kernels.
.SH EXIT STATUS
-The exit status of sg_modes is 0 when it is successful. Otherwise see
+The exit status of sg_logs is 0 when it is successful. Otherwise see
the sg3_utils(8) man page.
.SH OLDER COMMAND LINE OPTIONS
The options in this section were the only ones available prior to sg3_utils
@@ -312,4 +336,4 @@ Copyright \(co 2002\-2007 Douglas Gilbert
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 smartctl(smartmontools), sg_senddiag(sg3_utils)
+.B smartctl(smartmontools), sg_senddiag(8)
diff --git a/sg_logs.c b/sg_logs.c
index 88c93168..409a733b 100644
--- a/sg_logs.c
+++ b/sg_logs.c
@@ -22,7 +22,7 @@
*/
-static char * version_str = "0.69 20070129"; /* SPC-4 revision 8 */
+static char * version_str = "0.73 20070419"; /* SPC-4 revision 9 */
#define MX_ALLOC_LEN (0xfffc)
#define SHORT_RESP_LEN 128
@@ -42,41 +42,46 @@ static char * version_str = "0.69 20070129"; /* SPC-4 revision 8 */
#define SELF_TEST_LPAGE 0x10
#define PORT_SPECIFIC_LPAGE 0x18
#define GSP_LPAGE 0x19
+#define TAPE_ALERT_LPAGE 0x2e
#define IE_LPAGE 0x2f
#define NOT_SUBPG_LOG 0x0
#define ALL_SUBPG_LOG 0xff
#define PCB_STR_LEN 128
+#define LOG_SENSE_PROBE_ALLOC_LEN 4
+
static unsigned char rsp_buff[MX_ALLOC_LEN];
static struct option long_options[] = {
- {"all", 0, 0, 'a'},
- {"control", 1, 0, 'c'},
- {"help", 0, 0, 'h'},
- {"hex", 0, 0, 'H'},
- {"list", 0, 0, 'l'},
- {"maxlen", 1, 0, 'm'},
- {"name", 0, 0, 'n'},
- {"new", 0, 0, 'N'},
- {"old", 0, 0, 'O'},
- {"page", 1, 0, 'p'},
- {"paramp", 1, 0, 'P'},
- {"pcb", 0, 0, 'q'},
- {"ppc", 0, 0, 'Q'},
- {"raw", 0, 0, 'r'},
- {"reset", 0, 0, 'R'},
- {"sp", 0, 0, 's'},
- {"select", 0, 0, 'S'},
- {"temperature", 0, 0, 't'},
- {"transport", 0, 0, 'T'},
- {"verbose", 0, 0, 'v'},
- {"version", 0, 0, 'V'},
+ {"all", no_argument, 0, 'a'},
+ {"brief", no_argument, 0, 'b'},
+ {"control", required_argument, 0, 'c'},
+ {"help", no_argument, 0, 'h'},
+ {"hex", no_argument, 0, 'H'},
+ {"list", no_argument, 0, 'l'},
+ {"maxlen", required_argument, 0, 'm'},
+ {"name", no_argument, 0, 'n'},
+ {"new", no_argument, 0, 'N'},
+ {"old", no_argument, 0, 'O'},
+ {"page", required_argument, 0, 'p'},
+ {"paramp", required_argument, 0, 'P'},
+ {"pcb", no_argument, 0, 'q'},
+ {"ppc", no_argument, 0, 'Q'},
+ {"raw", no_argument, 0, 'r'},
+ {"reset", no_argument, 0, 'R'},
+ {"sp", no_argument, 0, 's'},
+ {"select", no_argument, 0, 'S'},
+ {"temperature", no_argument, 0, 't'},
+ {"transport", no_argument, 0, 'T'},
+ {"verbose", no_argument, 0, 'v'},
+ {"version", no_argument, 0, 'V'},
{0, 0, 0, 0},
};
struct opts_t {
int do_all;
+ int do_brief;
int do_help;
int do_hex;
int do_list;
@@ -102,17 +107,18 @@ struct opts_t {
static void usage()
{
- printf("Usage: sg_logs [--all] [--control=PC] [--help] [--hex] "
- "[--list] [--maxlen=LEN]\n"
- " [--name] [--page=PG[,SPG]] [--paramp=PP] [--pcb] "
- "[--ppc]\n"
- " [--raw] [--reset] [--select] [--sp] "
+ printf("Usage: sg_logs [--all] [--brief] [--control=PC] [--help] [--hex] "
+ "[--list]\n"
+ " [--maxlen=LEN] [--name] [--page=PG[,SPG]] "
+ "[--paramp=PP] [--pcb]\n"
+ " [--ppc] [--raw] [--reset] [--select] [--sp] "
"[--temperature]\n"
" [--transport] [--verbose] [--version] DEVICE\n"
" where:\n"
" --all|-a fetch and decode all log pages\n"
" use twice to fetch and decode all log pages "
"and subpages\n"
+ " --brief|-b shorten the output of some log pages\n"
" --control=PC|-c PC page control(PC) (default: 1)\n"
" 0: current threshhold, 1: current "
"cumulative\n"
@@ -127,6 +133,7 @@ static void usage()
"subpage names\n"
" --maxlen=LEN|-m LEN max response length (def: 0 "
"-> everything)\n"
+ " when > 1 will request LEN bytes\n"
" --name|-n decode some pages into multiple name=value "
"lines\n"
" --page=PG|-p PG page code (in decimal)\n"
@@ -155,7 +162,7 @@ static void usage()
static void usage_old()
{
- printf("Usage: sg_logs [-a] [-A] [-c=PC] [-h] [-H] [-l] [-L] "
+ printf("Usage: sg_logs [-a] [-A] [-b] [-c=PC] [-h] [-H] [-l] [-L] "
"[-m=LEN] [-n]\n"
" [-p=PG[,SPG]] [-paramp=PP] [-pcb] [-ppc] "
"[-r] [-select]\n"
@@ -163,6 +170,7 @@ static void usage_old()
" where:\n"
" -a fetch and decode all log pages\n"
" -A fetch and decode all log pages and subpages\n"
+ " -b shorten the output of some log pages\n"
" -c=PC page control(PC) (default: 1)\n"
" 0: current threshhold, 1: current cumulative\n"
" 2: default threshhold, 3: default cumulative\n"
@@ -243,7 +251,7 @@ static int process_cl_new(struct opts_t * optsp, int argc, char * argv[])
while (1) {
int option_index = 0;
- c = getopt_long(argc, argv, "aAc:hHlLm:nNOp:P:qQrRsStTvV",
+ c = getopt_long(argc, argv, "aAbc:hHlLm:nNOp:P:qQrRsStTvV",
long_options, &option_index);
if (c == -1)
break;
@@ -255,6 +263,9 @@ static int process_cl_new(struct opts_t * optsp, int argc, char * argv[])
case 'A':
optsp->do_all += 2;
break;
+ case 'b':
+ ++optsp->do_brief;
+ break;
case 'c':
n = sg_get_num(optarg);
if ((n < 0) || (n > 3)) {
@@ -279,7 +290,7 @@ static int process_cl_new(struct opts_t * optsp, int argc, char * argv[])
break;
case 'm':
n = sg_get_num(optarg);
- if (n < 0) {
+ if ((n < 0) || (1 == n)) {
fprintf(stderr, "bad argument to '--maxlen='\n");
usage();
return SG_LIB_SYNTAX_ERROR;
@@ -356,7 +367,7 @@ static int process_cl_new(struct opts_t * optsp, int argc, char * argv[])
++optsp->do_version;
break;
default:
- fprintf(stderr, "unrecognised switch code %c [0x%x]\n", c, c);
+ fprintf(stderr, "unrecognised option code %c [0x%x]\n", c, c);
if (optsp->do_help)
break;
usage();
@@ -399,6 +410,9 @@ static int process_cl_old(struct opts_t * optsp, int argc, char * argv[])
case 'A':
optsp->do_all += 2;
break;
+ case 'b':
+ ++optsp->do_brief;
+ break;
case 'h':
case 'H':
++optsp->do_hex;
@@ -568,33 +582,38 @@ static int do_logs(int sg_fd, unsigned char * resp, int mx_resp_len,
int res;
memset(resp, 0, mx_resp_len);
- if ((res = sg_ll_log_sense(sg_fd, optsp->do_ppc, optsp->do_sp,
- optsp->page_control, optsp->pg_code,
- optsp->subpg_code, optsp->paramp,
- resp, 4, noisy, optsp->do_verbose))) {
- switch (res) {
- case SG_LIB_CAT_NOT_READY:
- case SG_LIB_CAT_INVALID_OP:
- case SG_LIB_CAT_ILLEGAL_REQ:
- case SG_LIB_CAT_UNIT_ATTENTION:
- case SG_LIB_CAT_ABORTED_COMMAND:
- return res;
- default:
- return -1;
+ if (optsp->maxlen > 1)
+ actual_len = mx_resp_len;
+ else {
+ if ((res = sg_ll_log_sense(sg_fd, optsp->do_ppc, optsp->do_sp,
+ optsp->page_control, optsp->pg_code,
+ optsp->subpg_code, optsp->paramp,
+ resp, LOG_SENSE_PROBE_ALLOC_LEN,
+ noisy, optsp->do_verbose))) {
+ switch (res) {
+ case SG_LIB_CAT_NOT_READY:
+ case SG_LIB_CAT_INVALID_OP:
+ case SG_LIB_CAT_ILLEGAL_REQ:
+ case SG_LIB_CAT_UNIT_ATTENTION:
+ case SG_LIB_CAT_ABORTED_COMMAND:
+ return res;
+ default:
+ return -1;
+ }
}
+ actual_len = (resp[2] << 8) + resp[3] + 4;
+ if ((0 == optsp->do_raw) && (optsp->do_verbose > 1)) {
+ fprintf(stderr, " Log sense (find length) response:\n");
+ dStrHex((const char *)resp, LOG_SENSE_PROBE_ALLOC_LEN, 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;
+ if (actual_len > mx_resp_len)
+ actual_len = mx_resp_len;
}
- actual_len = (resp[2] << 8) + resp[3] + 4;
- if ((0 == optsp->do_raw) && (optsp->do_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;
- if (actual_len > mx_resp_len)
- actual_len = mx_resp_len;
if ((res = sg_ll_log_sense(sg_fd, optsp->do_ppc, optsp->do_sp,
optsp->page_control, optsp->pg_code,
optsp->subpg_code, optsp->paramp,
@@ -718,7 +737,7 @@ static void show_page_name(int pg_code, int subpg_code,
case 0x16:
printf("%sTape diagnostic (ssc-3)\n", b);
break;
- case 0x2e:
+ case TAPE_ALERT_LPAGE:
printf("%sTapeAlert (ssc-2)\n", b);
break;
default:
@@ -726,6 +745,7 @@ static void show_page_name(int pg_code, int subpg_code,
break;
}
}
+ break;
case 8:
/* medium changer type devices */
{
@@ -733,6 +753,9 @@ static void show_page_name(int pg_code, int subpg_code,
case 0x14:
printf("%sMedia changer statistics (smc-3)\n", b);
break;
+ case 0x15:
+ printf("%sElement statistics (smc-3)\n", b);
+ break;
case 0x2e:
printf("%sTapeAlert (smc-3)\n", b);
break;
@@ -741,6 +764,7 @@ static void show_page_name(int pg_code, int subpg_code,
break;
}
}
+ break;
case 0x12: /* Automation Device interface (ADC) */
{
switch (pg_code) {
@@ -764,12 +788,13 @@ static void show_page_name(int pg_code, int subpg_code,
break;
}
}
-
- default: done = 0; break;
+ break;
+ default:
+ done = 0;
+ break;
}
if (done)
return;
-
printf("%s??\n", b);
}
@@ -1457,14 +1482,15 @@ static void show_sas_rel_target_port(unsigned char * ucp, int param_len,
printf(" phy identifier = %d\n", vcp[1]);
spld_len = vcp[3];
if (spld_len < 44)
- spld_len = 48;
+ spld_len = 48; /* in SAS-1 and SAS-1.1 vcp[3]==0 */
else
spld_len += 4;
- t = ((0x70 & vcp[4]) >> 4);
if (optsp->do_name) {
+ t = ((0x70 & vcp[4]) >> 4);
printf(" att_dev_type=%d\n", t);
printf(" att_iport_mask=0x%x\n", vcp[6]);
printf(" att_phy_id=%d\n", vcp[24]);
+ printf(" att_reason=0x%x\n", (vcp[4] & 0xf));
for (n = 0, ull = vcp[16]; n < 8; ++n) {
ull <<= 8; ull |= vcp[16 + n];
}
@@ -1479,11 +1505,13 @@ static void show_sas_rel_target_port(unsigned char * ucp, int param_len,
printf(" phy_reset_probs=%ld\n", ul);
ul = (vcp[36] << 24) | (vcp[37] << 16) | (vcp[38] << 8) | vcp[39];
printf(" running_disparity=%ld\n", ul);
+ printf(" reason=0x%x\n", (vcp[5] & 0xf0) >> 4);
for (n = 0, ull = vcp[8]; n < 8; ++n) {
ull <<= 8; ull |= vcp[8 + n];
}
printf(" sas_addr=0x%" PRIx64 "\n", ull);
} else {
+ t = ((0x70 & vcp[4]) >> 4);
switch (t) {
case 0: snprintf(s, sz, "no device attached"); break;
case 1: snprintf(s, sz, "end device"); break;
@@ -1492,6 +1520,40 @@ static void show_sas_rel_target_port(unsigned char * ucp, int param_len,
default: snprintf(s, sz, "reserved [%d]", t); break;
}
printf(" attached device type: %s\n", s);
+ t = 0xf & vcp[4];
+ switch (t) {
+ case 0: snprintf(s, sz, "unknown"); break;
+ case 1: snprintf(s, sz, "power on"); break;
+ case 2: snprintf(s, sz, "hard reset"); break;
+ case 3: snprintf(s, sz, "SMP phy control function"); break;
+ case 4: snprintf(s, sz, "loss of dword synchronization"); break;
+ case 5: snprintf(s, sz, "mux mix up"); break;
+ case 6: snprintf(s, sz, "I_T nexus loss timeout for STP/SATA");
+ break;
+ case 7: snprintf(s, sz, "break timeout timer expired"); break;
+ case 8: snprintf(s, sz, "phy test function stopped"); break;
+ case 9: snprintf(s, sz, "expander device reduced functionality");
+ break;
+ default: snprintf(s, sz, "reserved [0x%x]", t); break;
+ }
+ printf(" attached reason: %s\n", s);
+ t = (vcp[5] & 0xf0) >> 4;
+ switch (t) {
+ case 0: snprintf(s, sz, "unknown"); break;
+ case 1: snprintf(s, sz, "power on"); break;
+ case 2: snprintf(s, sz, "hard reset"); break;
+ case 3: snprintf(s, sz, "SMP phy control function"); break;
+ case 4: snprintf(s, sz, "loss of dword synchronization"); break;
+ case 5: snprintf(s, sz, "mux mix up"); break;
+ case 6: snprintf(s, sz, "I_T nexus loss timeout for STP/SATA");
+ break;
+ case 7: snprintf(s, sz, "break timeout timer expired"); break;
+ case 8: snprintf(s, sz, "phy test function stopped"); break;
+ case 9: snprintf(s, sz, "expander device reduced functionality");
+ break;
+ default: snprintf(s, sz, "reserved [0x%x]", t); break;
+ }
+ printf(" reason: %s\n", s);
t = (0xf & vcp[5]);
switch (t) {
case 0: snprintf(s, sz, "phy enabled; unknown");
@@ -1505,12 +1567,14 @@ static void show_sas_rel_target_port(unsigned char * ucp, int param_len,
break;
case 5: snprintf(s, sz, "phy enabled; reset in progress");
break;
+ case 6: snprintf(s, sz, "phy enabled; unsupported phy attached");
+ break;
case 8: snprintf(s, sz, "phy enabled; 1.5 Gbps"); break;
case 9: snprintf(s, sz, "phy enabled; 3 Gbps"); break;
case 0xa: snprintf(s, sz, "phy enabled; 6 Gbps"); break;
default: snprintf(s, sz, "reserved [%d]", t); break;
}
- printf(" negotiated logical link rate: %s\n", s);/* sas2r07 */
+ printf(" negotiated logical link rate: %s\n", s);
printf(" attached initiator port: ssp=%d stp=%d smp=%d\n",
!! (vcp[6] & 8), !! (vcp[6] & 4), !! (vcp[6] & 2));
printf(" attached target port: ssp=%d stp=%d smp=%d\n",
@@ -1559,13 +1623,15 @@ static void show_sas_rel_target_port(unsigned char * ucp, int param_len,
}
}
-static int show_protocol_specific_page(unsigned char * resp, int len,
+static int show_protocol_specific_page(unsigned char * resp, int len,
const struct opts_t * optsp)
{
int k, num, param_len;
unsigned char * ucp;
num = len - 4;
+ if (optsp->do_name)
+ printf("log_page=0x%x\n", PORT_SPECIFIC_LPAGE);
for (k = 0, ucp = resp + 4; k < num; ) {
param_len = ucp[3] + 4;
/* each phy has a 48 byte descriptor but since param_len is
@@ -1582,6 +1648,313 @@ static int show_protocol_specific_page(unsigned char * resp, int len,
return 1;
}
+static int show_stats_perform_page(unsigned char * resp, int len,
+ const struct opts_t * optsp)
+{
+ int k, num, n, param_len, param_code, spf, subpg_code, extra;
+ int pcb, nam;
+ unsigned char * ucp;
+ const char * ccp;
+ unsigned long long ull;
+ char pcb_str[PCB_STR_LEN];
+
+ nam = optsp->do_name;
+ num = len - 4;
+ ucp = resp + 4;
+ spf = !!(resp[0] & 0x40);
+ subpg_code = spf ? resp[1] : 0;
+ if (nam) {
+ printf("log_page=0x%x\n", GSP_LPAGE);
+ if (subpg_code > 0)
+ printf("log_subpage=0x%x\n", subpg_code);
+ }
+ if (subpg_code > 31)
+ return 0;
+ if (0 == subpg_code) { /* General statistics and performance log page */
+ if (num < 0x5c)
+ return 0;
+ for (k = num; k > 0; k -= extra, ucp += extra) {
+ if (k < 3)
+ return 0;
+ param_len = ucp[3];
+ extra = param_len + 4;
+ param_code = (ucp[0] << 8) + ucp[1];
+ pcb = ucp[2];
+ switch (param_code) {
+ case 1: /* Statistics and performance log parameter */
+ ccp = nam ? "parameter_code=1" : "Statistics and performance "
+ "log parameter";
+ printf("%s\n", ccp);
+ for (n = 0, ull = ucp[4]; n < 8; ++n) {
+ ull <<= 8; ull |= ucp[4 + n];
+ }
+ ccp = nam ? "read_commands=" : "number of read commands = ";
+ printf(" %s%" PRIu64 "\n", ccp, ull);
+ for (n = 0, ull = ucp[12]; n < 8; ++n) {
+ ull <<= 8; ull |= ucp[12 + n];
+ }
+ ccp = nam ? "write_commands=" : "number of write commands = ";
+ printf(" %s%" PRIu64 "\n", ccp, ull);
+ for (n = 0, ull = ucp[20]; n < 8; ++n) {
+ ull <<= 8; ull |= ucp[20 + n];
+ }
+ ccp = nam ? "lb_received="
+ : "number of logical blocks received = ";
+ printf(" %s%" PRIu64 "\n", ccp, ull);
+ for (n = 0, ull = ucp[28]; n < 8; ++n) {
+ ull <<= 8; ull |= ucp[28 + n];
+ }
+ ccp = nam ? "lb_transmitted="
+ : "number of logical blocks transmitted = ";
+ printf(" %s%" PRIu64 "\n", ccp, ull);
+ for (n = 0, ull = ucp[36]; n < 8; ++n) {
+ ull <<= 8; ull |= ucp[36 + n];
+ }
+ ccp = nam ? "read_proc_intervals="
+ : "read command processing intervals = ";
+ printf(" %s%" PRIu64 "\n", ccp, ull);
+ for (n = 0, ull = ucp[44]; n < 8; ++n) {
+ ull <<= 8; ull |= ucp[44 + n];
+ }
+ ccp = nam ? "write_proc_intervals="
+ : "write command processing intervals = ";
+ printf(" %s%" PRIu64 "\n", ccp, ull);
+ for (n = 0, ull = ucp[52]; n < 8; ++n) {
+ ull <<= 8; ull |= ucp[52 + n];
+ }
+ ccp = nam ? "weight_rw_commands=" : "weighted number of "
+ "read commands plus write commands = ";
+ printf(" %s%" PRIu64 "\n", ccp, ull);
+ for (n = 0, ull = ucp[60]; n < 8; ++n) {
+ ull <<= 8; ull |= ucp[60 + n];
+ }
+ ccp = nam ? "weight_rw_processing=" : "weighted read command "
+ "processing plus write command processing = ";
+ printf(" %s%" PRIu64 "\n", ccp, ull);
+ break;
+ case 2: /* Idle time log parameter */
+ ccp = nam ? "parameter_code=2" : "Idle time log parameter";
+ printf("%s\n", ccp);
+ for (n = 0, ull = ucp[4]; n < 8; ++n) {
+ ull <<= 8; ull |= ucp[4 + n];
+ }
+ ccp = nam ? "idle_time_intervals=" : "idle time "
+ "intervals = ";
+ printf(" %s%" PRIu64 "\n", ccp, ull);
+ break;
+ case 3: /* Time interval log parameter */
+ ccp = nam ? "parameter_code=3" : "Time interval log "
+ "parameter";
+ printf("%s\n", ccp);
+ for (n = 0, ull = ucp[4]; n < 4; ++n) {
+ ull <<= 8; ull |= ucp[4 + n];
+ }
+ ccp = nam ? "time_interval_exp=" : "time interval "
+ "exponent = ";
+ printf(" %s%" PRIu64 "\n", ccp, ull);
+ for (n = 0, ull = ucp[8]; n < 4; ++n) {
+ ull <<= 8; ull |= ucp[8 + n];
+ }
+ ccp = nam ? "time_interval_int=" : "time interval "
+ "integer = ";
+ printf(" %s%" PRIu64 "\n", ccp, ull);
+ break;
+ case 4: /* FUA statistics and performance log parameter */
+ ccp = nam ? "parameter_code=4" : "Force unit access "
+ "statistics and performance log parameter ";
+ printf("%s\n", ccp);
+ for (n = 0, ull = ucp[4]; n < 8; ++n) {
+ ull <<= 8; ull |= ucp[4 + n];
+ }
+ ccp = nam ? "read_fua_commands=" : "number of read FUA "
+ "commands = ";
+ printf(" %s%" PRIu64 "\n", ccp, ull);
+ for (n = 0, ull = ucp[12]; n < 8; ++n) {
+ ull <<= 8; ull |= ucp[12 + n];
+ }
+ ccp = nam ? "write_fua_commands=" : "number of write FUA "
+ "commands = ";
+ printf(" %s%" PRIu64 "\n", ccp, ull);
+ for (n = 0, ull = ucp[20]; n < 8; ++n) {
+ ull <<= 8; ull |= ucp[20 + n];
+ }
+ ccp = nam ? "read_fua_nv_commands="
+ : "number of read FUA_NV commands = ";
+ printf(" %s%" PRIu64 "\n", ccp, ull);
+ for (n = 0, ull = ucp[28]; n < 8; ++n) {
+ ull <<= 8; ull |= ucp[28 + n];
+ }
+ ccp = nam ? "write_fua_nv_commands="
+ : "number of write FUA_NV commands = ";
+ printf(" %s%" PRIu64 "\n", ccp, ull);
+ for (n = 0, ull = ucp[36]; n < 8; ++n) {
+ ull <<= 8; ull |= ucp[36 + n];
+ }
+ ccp = nam ? "read_fua_proc_intervals="
+ : "read FUA command processing intervals = ";
+ printf(" %s%" PRIu64 "\n", ccp, ull);
+ for (n = 0, ull = ucp[44]; n < 8; ++n) {
+ ull <<= 8; ull |= ucp[44 + n];
+ }
+ ccp = nam ? "write_fua_proc_intervals="
+ : "write FUA command processing intervals = ";
+ printf(" %s%" PRIu64 "\n", ccp, ull);
+ for (n = 0, ull = ucp[52]; n < 8; ++n) {
+ ull <<= 8; ull |= ucp[52 + n];
+ }
+ ccp = nam ? "read_fua_nv_proc_intervals="
+ : "read FUA_NV command processing intervals = ";
+ printf(" %s%" PRIu64 "\n", ccp, ull);
+ for (n = 0, ull = ucp[60]; n < 8; ++n) {
+ ull <<= 8; ull |= ucp[60 + n];
+ }
+ ccp = nam ? "write_fua_nv_proc_intervals="
+ : "write FUA_NV command processing intervals = ";
+ printf(" %s%" PRIu64 "\n", ccp, ull);
+ break;
+ default:
+ if (nam) {
+ printf("parameter_code=%d\n", param_code);
+ printf(" unknown=1\n");
+ } else
+ fprintf(stderr, "show_performance... unknown parameter "
+ "code %d\n", param_code);
+ if (optsp->do_verbose)
+ dStrHex((const char *)ucp, extra, 1);
+ break;
+ }
+ if ((optsp->do_pcb) && (0 == optsp->do_name)) {
+ get_pcb_str(pcb, pcb_str, sizeof(pcb_str));
+ printf(" <%s>\n", pcb_str);
+ }
+ }
+ } else { /* Group statistics and performance (n) log page */
+ if (num < 0x34)
+ return 0;
+ for (k = num; k > 0; k -= extra, ucp += extra) {
+ if (k < 3)
+ return 0;
+ param_len = ucp[3];
+ extra = param_len + 4;
+ param_code = (ucp[0] << 8) + ucp[1];
+ pcb = ucp[2];
+ switch (param_code) {
+ case 1: /* Group n Statistics and performance log parameter */
+ if (nam)
+ printf("parameter_code=1\n");
+ else
+ printf("Group %d Statistics and performance log "
+ "parameter\n", subpg_code);
+ for (n = 0, ull = ucp[4]; n < 8; ++n) {
+ ull <<= 8; ull |= ucp[4 + n];
+ }
+ ccp = nam ? "gn_read_commands=" : "group n number of read "
+ "commands = ";
+ printf(" %s%" PRIu64 "\n", ccp, ull);
+ for (n = 0, ull = ucp[12]; n < 8; ++n) {
+ ull <<= 8; ull |= ucp[12 + n];
+ }
+ ccp = nam ? "gn_write_commands=" : "group n number of write "
+ "commands = ";
+ printf(" %s%" PRIu64 "\n", ccp, ull);
+ for (n = 0, ull = ucp[20]; n < 8; ++n) {
+ ull <<= 8; ull |= ucp[20 + n];
+ }
+ ccp = nam ? "gn_lb_received="
+ : "group n number of logical blocks received = ";
+ printf(" %s%" PRIu64 "\n", ccp, ull);
+ for (n = 0, ull = ucp[28]; n < 8; ++n) {
+ ull <<= 8; ull |= ucp[28 + n];
+ }
+ ccp = nam ? "gn_lb_transmitted="
+ : "group n number of logical blocks transmitted = ";
+ printf(" %s%" PRIu64 "\n", ccp, ull);
+ for (n = 0, ull = ucp[36]; n < 8; ++n) {
+ ull <<= 8; ull |= ucp[36 + n];
+ }
+ ccp = nam ? "gn_read_proc_intervals="
+ : "group n read command processing intervals = ";
+ printf(" %s%" PRIu64 "\n", ccp, ull);
+ for (n = 0, ull = ucp[44]; n < 8; ++n) {
+ ull <<= 8; ull |= ucp[44 + n];
+ }
+ ccp = nam ? "gn_write_proc_intervals="
+ : "group n write command processing intervals = ";
+ printf(" %s%" PRIu64 "\n", ccp, ull);
+ break;
+ case 4: /* Group n FUA statistics and performance log parameter */
+ ccp = nam ? "parameter_code=4" : "Group n force unit access "
+ "statistics and performance log parameter";
+ printf("%s\n", ccp);
+ for (n = 0, ull = ucp[4]; n < 8; ++n) {
+ ull <<= 8; ull |= ucp[4 + n];
+ }
+ ccp = nam ? "gn_read_fua_commands="
+ : "group n number of read FUA commands = ";
+ printf(" %s%" PRIu64 "\n", ccp, ull);
+ for (n = 0, ull = ucp[12]; n < 8; ++n) {
+ ull <<= 8; ull |= ucp[12 + n];
+ }
+ ccp = nam ? "gn_write_fua_commands="
+ : "group n number of write FUA commands = ";
+ printf(" %s%" PRIu64 "\n", ccp, ull);
+ for (n = 0, ull = ucp[20]; n < 8; ++n) {
+ ull <<= 8; ull |= ucp[20 + n];
+ }
+ ccp = nam ? "gn_read_fua_nv_commands="
+ : "group n number of read FUA_NV commands = ";
+ printf(" %s%" PRIu64 "\n", ccp, ull);
+ for (n = 0, ull = ucp[28]; n < 8; ++n) {
+ ull <<= 8; ull |= ucp[28 + n];
+ }
+ ccp = nam ? "gn_write_fua_nv_commands="
+ : "group n number of write FUA_NV commands = ";
+ printf(" %s%" PRIu64 "\n", ccp, ull);
+ for (n = 0, ull = ucp[36]; n < 8; ++n) {
+ ull <<= 8; ull |= ucp[36 + n];
+ }
+ ccp = nam ? "gn_read_fua_proc_intervals="
+ : "group n read FUA command processing intervals = ";
+ printf(" %s%" PRIu64 "\n", ccp, ull);
+ for (n = 0, ull = ucp[44]; n < 8; ++n) {
+ ull <<= 8; ull |= ucp[44 + n];
+ }
+ ccp = nam ? "gn_write_fua_proc_intervals=" : "group n write "
+ "FUA command processing intervals = ";
+ printf(" %s%" PRIu64 "\n", ccp, ull);
+ for (n = 0, ull = ucp[52]; n < 8; ++n) {
+ ull <<= 8; ull |= ucp[52 + n];
+ }
+ ccp = nam ? "gn_read_fua_nv_proc_intervals=" : "group n "
+ "read FUA_NV command processing intervals = ";
+ printf(" %s%" PRIu64 "\n", ccp, ull);
+ for (n = 0, ull = ucp[60]; n < 8; ++n) {
+ ull <<= 8; ull |= ucp[60 + n];
+ }
+ ccp = nam ? "gn_write_fua_nv_proc_intervals=" : "group n "
+ "write FUA_NV command processing intervals = ";
+ printf(" %s%" PRIu64 "\n", ccp, ull);
+ break;
+ default:
+ if (nam) {
+ printf("parameter_code=%d\n", param_code);
+ printf(" unknown=1\n");
+ } else
+ fprintf(stderr, "show_performance... unknown parameter "
+ "code %d\n", param_code);
+ if (optsp->do_verbose)
+ dStrHex((const char *)ucp, extra, 1);
+ break;
+ }
+ if ((optsp->do_pcb) && (0 == optsp->do_name)) {
+ get_pcb_str(pcb, pcb_str, sizeof(pcb_str));
+ printf(" <%s>\n", pcb_str);
+ }
+ }
+ }
+ return 1;
+}
+
static void show_format_status_page(unsigned char * resp, int len,
int show_pcb)
{
@@ -2046,6 +2419,277 @@ static void show_device_stats_page(unsigned char * resp, int len,
}
}
+static void show_media_stats_page(unsigned char * resp, int len,
+ int show_pcb)
+{
+ int k, j, num, pl, pc, pcb;
+ unsigned char * ucp;
+ unsigned char * xp;
+ unsigned long long ull;
+ char pcb_str[PCB_STR_LEN];
+
+ printf("Media statistics page (smc-3)\n");
+ num = len - 4;
+ ucp = &resp[0] + 4;
+ while (num > 3) {
+ pc = (ucp[0] << 8) | ucp[1];
+ pcb = ucp[2];
+ pl = ucp[3] + 4;
+ k = pl - 4;
+ xp = ucp + 4;
+ if (k > (int)sizeof(ull)) {
+ xp += (k - sizeof(ull));
+ k = sizeof(ull);
+ }
+ ull = 0;
+ for (j = 0; j < k; ++j) {
+ if (j > 0)
+ ull <<= 8;
+ ull |= xp[j];
+ }
+ switch (pc) {
+ case 0:
+ printf(" Number of moves: %" PRIu64 "\n", ull);
+ break;
+ case 1:
+ printf(" Number of picks: %" PRIu64 "\n", ull);
+ break;
+ case 2:
+ printf(" Number of pick retries: %" PRIu64 "\n", ull);
+ break;
+ case 3:
+ printf(" Number of places: %" PRIu64 "\n", ull);
+ break;
+ case 4:
+ printf(" Number of place retries: %" PRIu64 "\n", ull);
+ break;
+ case 5:
+ printf(" Number of volume tags read by volume "
+ "tag reader: %" PRIu64 "\n", ull);
+ break;
+ case 6:
+ printf(" Number of invalid volume tags returned by "
+ "volume tag reader: %" PRIu64 "\n", ull);
+ break;
+ case 7:
+ printf(" Number of library door opens: %" PRIu64 "\n", ull);
+ break;
+ case 8:
+ printf(" Number of import/export door opens: %" PRIu64 "\n",
+ ull);
+ break;
+ case 9:
+ printf(" Number of physical inventory scans: %" PRIu64 "\n",
+ ull);
+ break;
+ case 0xa:
+ printf(" Number of medium transport unrecovered errors: "
+ "%" PRIu64 "\n", ull);
+ break;
+ case 0xb:
+ printf(" Number of medium transport recovered errors: "
+ "%" PRIu64 "\n", ull);
+ break;
+ case 0xc:
+ printf(" Number of medium transport X axis translation "
+ "unrecovered errors: %" PRIu64 "\n", ull);
+ break;
+ case 0xd:
+ printf(" Number of medium transport X axis translation "
+ "recovered errors: %" PRIu64 "\n", ull);
+ break;
+ case 0xe:
+ printf(" Number of medium transport Y axis translation "
+ "unrecovered errors: %" PRIu64 "\n", ull);
+ break;
+ case 0xf:
+ printf(" Number of medium transport Y axis translation "
+ "recovered errors: %" PRIu64 "\n", ull);
+ break;
+ case 0x10:
+ printf(" Number of medium transport Z axis translation "
+ "unrecovered errors: %" PRIu64 "\n", ull);
+ break;
+ case 0x11:
+ printf(" Number of medium transport Z axis translation "
+ "recovered errors: %" PRIu64 "\n", ull);
+ break;
+ case 0x12:
+ printf(" Number of medium transport rotational translation "
+ "unrecovered errors: %" PRIu64 "\n", ull);
+ break;
+ case 0x13:
+ printf(" Number of medium transport rotational translation "
+ "recovered errors: %" PRIu64 "\n", ull);
+ break;
+ case 0x14:
+ printf(" Number of medium transport inversion translation "
+ "unrecovered errors: %" PRIu64 "\n", ull);
+ break;
+ case 0x15:
+ printf(" Number of medium transport inversion translation "
+ "recovered errors: %" PRIu64 "\n", ull);
+ break;
+ case 0x16:
+ printf(" Number of medium transport auxiliary translation "
+ "unrecovered errors: %" PRIu64 "\n", ull);
+ break;
+ case 0x17:
+ printf(" Number of medium transport auxiliary translation "
+ "recovered errors: %" PRIu64 "\n", ull);
+ break;
+ default:
+ printf(" Reserved parameter [0x%x] value: %" PRIu64 "\n",
+ pc, ull);
+ break;
+ }
+ if (show_pcb) {
+ get_pcb_str(pcb, pcb_str, sizeof(pcb_str));
+ printf("\n <%s>\n", pcb_str);
+ } else
+ printf("\n");
+ num -= pl;
+ ucp += pl;
+ }
+}
+
+static void show_element_stats_page(unsigned char * resp, int len,
+ int show_pcb)
+{
+ int num, pl, pc, pcb;
+ unsigned int v;
+ unsigned char * ucp;
+ char str[PCB_STR_LEN];
+
+ printf("Element statistics page (smc-3) [0x15]\n");
+ num = len - 4;
+ ucp = &resp[0] + 4;
+ while (num > 3) {
+ pc = (ucp[0] << 8) | ucp[1];
+ pcb = ucp[2];
+ pl = ucp[3] + 4;
+ printf(" Element address: %d\n", pc);
+ v = (ucp[4] << 24) + (ucp[5] << 16) + (ucp[6] << 8) + ucp[7];
+ printf(" Number of places: %u\n", v);
+ v = (ucp[8] << 24) + (ucp[9] << 16) + (ucp[10] << 8) + ucp[11];
+ printf(" Number of place retries: %u\n", v);
+ v = (ucp[12] << 24) + (ucp[13] << 16) + (ucp[14] << 8) + ucp[15];
+ printf(" Number of picks: %u\n", v);
+ v = (ucp[16] << 24) + (ucp[17] << 16) + (ucp[18] << 8) + ucp[19];
+ printf(" Number of pick retries: %u\n", v);
+ v = (ucp[20] << 24) + (ucp[21] << 16) + (ucp[22] << 8) + ucp[23];
+ printf(" Number of determined volume identifiers: %u\n", v);
+ v = (ucp[24] << 24) + (ucp[25] << 16) + (ucp[26] << 8) + ucp[27];
+ printf(" Number of unreadable volume identifiers: %u\n", v);
+ if (show_pcb) {
+ get_pcb_str(pcb, str, sizeof(str));
+ printf("\n <%s>\n", str);
+ }
+ num -= pl;
+ ucp += pl;
+ }
+}
+
+static char * tape_alert_strs[] = {
+ "<parameter code 0, unknown>", /* 0x0 */
+ "Read warning",
+ "Write warning",
+ "Hard error",
+ "Media",
+ "Read failure",
+ "Write failure",
+ "Media life",
+ "Not data grade", /* 0x8 */
+ "Write protect",
+ "No removal",
+ "Cleaning media",
+ "Unsupported format",
+ "Recoverable mechanical cartridge failure",
+ "Unrecoverable mechanical cartridge failure",
+ "Memory chip in cartridge failure",
+ "Forced eject", /* 0x10 */
+ "Read only format",
+ "Tape directory corrupted on load",
+ "Nearing media life",
+ "Cleaning required",
+ "Cleaning requested",
+ "Expired cleaning media",
+ "Invalid cleaning tape",
+ "Retension requested", /* 0x18 */
+ "Dual port interface error",
+ "Cooling fan failing",
+ "Power supply failure",
+ "Power consumption",
+ "Drive maintenance",
+ "Hardware A",
+ "Hardware B",
+ "Interface", /* 0x20 */
+ "Eject media",
+ "Microcode update fail",
+ "Drive humidity",
+ "Drive temperature",
+ "Drive voltage",
+ "Predictive failure",
+ "Diagnostics required",
+ "Obsolete (28h)", /* 0x28 */
+ "Obsolete (29h)",
+ "Obsolete (2Ah)",
+ "Obsolete (2Bh)",
+ "Obsolete (2Ch)",
+ "Obsolete (2Dh)",
+ "Obsolete (2Eh)",
+ "Reserved (2Fh)",
+ "Reserved (30h)", /* 0x30 */
+ "Reserved (31h)",
+ "Lost statistics",
+ "Tape directory invalid at unload",
+ "Tape system area write failure",
+ "Tape system area read failure",
+ "No start of data",
+ "Loading failure",
+ "Unrecoverable unload failure", /* 0x38 */
+ "Automation interface failure",
+ "Firmware failure",
+ "WORM medium - integrity check failed",
+ "WORM medium - overwrite attempted",
+};
+
+static void show_tape_alert_ssc_page(unsigned char * resp, int len,
+ int show_pcb,
+ const struct opts_t * optsp)
+{
+ int num, pl, pc, pcb, flag;
+ unsigned char * ucp;
+ char str[PCB_STR_LEN];
+
+ /* N.B. the Tape alert log page for smc-3 is different */
+ printf("Tape alert page (ssc-3) [0x2e]\n");
+ num = len - 4;
+ ucp = &resp[0] + 4;
+ while (num > 3) {
+ pc = (ucp[0] << 8) | ucp[1];
+ pcb = ucp[2];
+ pl = ucp[3] + 4;
+ flag = ucp[4] & 1;
+ if (optsp->do_verbose && (0 == optsp->do_brief) && flag)
+ printf(" >>>> ");
+ if ((0 == optsp->do_brief) || optsp->do_verbose || flag) {
+ if (pc < (int)(sizeof(tape_alert_strs) /
+ sizeof(tape_alert_strs[0])))
+ printf(" %s: %d\n", tape_alert_strs[pc], flag);
+ else
+ printf(" Reserved parameter code 0x%x, flag: %d\n", pc,
+ flag);
+ }
+ if (show_pcb) {
+ get_pcb_str(pcb, str, sizeof(str));
+ printf("\n <%s>\n", str);
+ }
+ num -= pl;
+ ucp += pl;
+ }
+}
+
static void show_seagate_cache_page(unsigned char * resp, int len,
int show_pcb)
{
@@ -2219,8 +2863,8 @@ static void show_ascii_page(unsigned char * resp, int len,
case 0xc:
{
switch (inq_dat->peripheral_type) {
- case 1: case 2: case 8:
- /* tape, (printer) and medium changer type devices */
+ case 1: case 2:
+ /* tape and (printer) type devices */
show_sequential_access_page(resp, len, optsp->do_pcb,
optsp->do_verbose);
break;
@@ -2242,10 +2886,13 @@ static void show_ascii_page(unsigned char * resp, int len,
case 0x14:
{
switch (inq_dat->peripheral_type) {
- case 1: case 8: case 0x12:
- /* tape, medium changer and adc type devices */
+ case 1: case 0x12:
+ /* tape and adc type devices */
show_device_stats_page(resp, len, optsp->do_pcb);
break;
+ case 8: /* smc-3 */
+ show_media_stats_page(resp, len, optsp->do_pcb);
+ break;
default:
done = 0;
break;
@@ -2260,6 +2907,9 @@ static void show_ascii_page(unsigned char * resp, int len,
show_background_scan_results_page(resp, len, optsp->do_pcb,
optsp->do_verbose);
break;
+ case 8: /* smc-3 */
+ show_element_stats_page(resp, len, optsp->do_pcb);
+ break;
default:
done = 0;
break;
@@ -2282,6 +2932,21 @@ static void show_ascii_page(unsigned char * resp, int len,
case PORT_SPECIFIC_LPAGE:
done = show_protocol_specific_page(resp, len, optsp);
break;
+ case GSP_LPAGE: /* defined for subpages 0 to 31 inclusive */
+ done = show_stats_perform_page(resp, len, optsp);
+ break;
+ case TAPE_ALERT_LPAGE:
+ {
+ switch (inq_dat->peripheral_type) {
+ case 1: /* ssc only */
+ show_tape_alert_ssc_page(resp, len, optsp->do_pcb, optsp);
+ break;
+ default:
+ done = 0;
+ break;
+ }
+ }
+ break;
case IE_LPAGE:
show_IE_page(resp, len, optsp->do_pcb, 1);
break;
@@ -2305,10 +2970,6 @@ static void show_ascii_page(unsigned char * resp, int len,
/* disk (direct access) type devices */
show_seagate_factory_page(resp, len, optsp->do_pcb);
break;
- case 1: case 2: case 8:
- /* streaming or medium changer devices */
- /* call ssc_device_status_log_page() */
- break;
default:
done = 0;
break;
@@ -2479,6 +3140,8 @@ int main(int argc, char * argv[])
if (0 == opts.do_all) {
if (opts.do_raw)
dStrRaw((const char *)rsp_buff, pg_len + 4);
+ else if (opts.do_hex > 1)
+ dStrHex((const char *)rsp_buff, pg_len + 4, 1);
else if (pg_len > 1) {
if (opts.do_hex) {
if (rsp_buff[0] & 0x40)
@@ -2509,7 +3172,8 @@ int main(int argc, char * argv[])
}
memcpy(parr, rsp_buff + 4, my_len);
for (k = 0; k < my_len; ++k) {
- printf("\n");
+ if (0 == opts.do_raw)
+ printf("\n");
opts.pg_code = parr[k] & 0x3f;
if (spf)
opts.subpg_code = parr[++k];
@@ -2520,11 +3184,15 @@ int main(int argc, char * argv[])
if (0 == res) {
pg_len = (rsp_buff[2] << 8) + rsp_buff[3];
if ((pg_len + 4) > resp_len) {
- printf("Only fetched %d bytes of response, truncate "
- "output\n", resp_len);
+ fprintf(stderr, "Only fetched %d bytes of response, "
+ "truncate output\n", resp_len);
pg_len = resp_len - 4;
}
- if (opts.do_hex) {
+ if (opts.do_raw)
+ dStrRaw((const char *)rsp_buff, pg_len + 4);
+ else if (opts.do_hex > 1)
+ dStrHex((const char *)rsp_buff, pg_len + 4, 1);
+ else if (opts.do_hex) {
if (rsp_buff[0] & 0x40)
printf("Log page code=0x%x,0x%x, DS=%d, SPF=1, page_"
"len=0x%x\n", rsp_buff[0] & 0x3f, rsp_buff[1],
diff --git a/sg_luns.8 b/sg_luns.8
index 230b4d52..4e1e1bf1 100644
--- a/sg_luns.8
+++ b/sg_luns.8
@@ -1,10 +1,10 @@
-.TH SG_LUNS "8" "January 2007" "sg3_utils\-1.23" SG3_UTILS
+.TH SG_LUNS "8" "March 2007" "sg3_utils\-1.24" SG3_UTILS
.SH NAME
sg_luns \- send the SCSI REPORT LUNS command
.SH SYNOPSIS
.B sg_luns
-[\fI\-\-decode\fR] [\fI\-\-help\fR] [\fI\-\-hex\fR] [\fI\-\-raw\fR]
-[\fI\-\-select=SR\fR] [\fI\-\-verbose\fR] [\fI\-\-version\fR]
+[\fI\-\-decode\fR] [\fI\-\-help\fR] [\fI\-\-hex\fR] [\fI\-\-quiet\fR]
+[\fI\-\-raw\fR] [\fI\-\-select=SR\fR] [\fI\-\-verbose\fR] [\fI\-\-version\fR]
\fIDEVICE\fR
.SH DESCRIPTION
.\" Add any additional description here
@@ -25,6 +25,9 @@ output the usage message then exit.
\fB\-H\fR, \fB\-\-hex\fR
output response to this command in ASCII hex.
.TP
+\fB\-q\fR, \fB\-\-quiet\fR
+output ASCII hex rendering of each report lun, one per line.
+.TP
\fB\-r\fR, \fB\-\-raw\fR
output response in binary (to stdout).
.TP
@@ -37,7 +40,16 @@ unit addressing, peripheral device addressing and flat space addressing.
When 1 is given the \fIDEVICE\fR should yield a list of only "well known"
logical units addressable via this "I_T" nexus. When 2 is given the
\fIDEVICE\fR should yield all luns addressable via this "I_T" nexus.
-Currently SPC\-3 (rev 23) doesn't specify any other values.
+To simplify, for the I_T nexus associated with the \fIDEVICE\fR, the
+meanings of the \fISR\fR values are:
+.br
+ \fB0\fR : all luns excluding well known logical units
+.br
+ \fB1\fR : well known logical units
+.br
+ \fB2\fR : all luns
+.br
+Values greater than 2 are reserved (at SPC\-4 (rev 8)).
.TP
\fB\-v\fR, \fB\-\-verbose\fR
increase the level of verbosity, (i.e. debug output).
@@ -57,4 +69,4 @@ Copyright \(co 2004\-2007 Douglas Gilbert
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)
+.B sg_inq(8)
diff --git a/sg_luns.c b/sg_luns.c
index dfcf36c5..fd3588ec 100644
--- a/sg_luns.c
+++ b/sg_luns.c
@@ -45,17 +45,18 @@
* This program issues the SCSI command REPORT LUNS to the given SCSI device.
*/
-static char * version_str = "1.10 20070128";
+static char * version_str = "1.12 20070419";
-#define REPORT_LUNS_BUFF_LEN 1024
-
-#define ME "sg_luns: "
+#define REPORT_LUNS_BUFF_LEN (1024*64)
+
+static unsigned char reportLunsBuff[REPORT_LUNS_BUFF_LEN];
static struct option long_options[] = {
{"decode", 0, 0, 'd'},
{"help", 0, 0, 'h'},
{"hex", 0, 0, 'H'},
+ {"quiet", 0, 0, 'q'},
{"raw", 0, 0, 'r'},
{"select", 1, 0, 's'},
{"verbose", 0, 0, 'v'},
@@ -66,12 +67,14 @@ static struct option long_options[] = {
static void usage()
{
fprintf(stderr, "Usage: "
- "sg_luns [--decode] [--help] [--hex] [--raw] [--select=SR]\n"
+ "sg_luns [--decode] [--help] [--hex] [--quiet] [--raw] "
+ "[--select=SR]\n"
" [--verbose] [--version] DEVICE\n"
" where:\n"
" --decode|-d decode all luns into component parts\n"
" --help|-h print out usage message\n"
" --hex|-H output in hexadecimal\n"
+ " --quiet|-q output only ASCII hex lun values\n"
" --raw|-r output in binary\n"
" --select=SR|-s SR select report SR (def: 0)\n"
" 0 -> luns apart from 'well "
@@ -212,9 +215,9 @@ static void dStrRaw(const char* str, int len)
int main(int argc, char * argv[])
{
int sg_fd, k, m, off, res, c, list_len, luns, trunc;
- unsigned char reportLunsBuff[REPORT_LUNS_BUFF_LEN];
int decode = 0;
int do_hex = 0;
+ int do_quiet = 0;
int do_raw = 0;
int select_rep = 0;
int verbose = 0;
@@ -225,7 +228,7 @@ int main(int argc, char * argv[])
while (1) {
int option_index = 0;
- c = getopt_long(argc, argv, "dhHrs:vV", long_options,
+ c = getopt_long(argc, argv, "dhHqrs:vV", long_options,
&option_index);
if (c == -1)
break;
@@ -241,6 +244,9 @@ int main(int argc, char * argv[])
case 'H':
++do_hex;
break;
+ case 'q':
+ ++do_quiet;
+ break;
case 'r':
++do_raw;
break;
@@ -255,10 +261,10 @@ int main(int argc, char * argv[])
++verbose;
break;
case 'V':
- fprintf(stderr, ME "version: %s\n", version_str);
+ fprintf(stderr, "version: %s\n", version_str);
return 0;
default:
- fprintf(stderr, "unrecognised switch code 0x%x ??\n", c);
+ fprintf(stderr, "unrecognised option code 0x%x ??\n", c);
usage();
return SG_LIB_SYNTAX_ERROR;
}
@@ -285,7 +291,7 @@ int main(int argc, char * argv[])
}
sg_fd = sg_cmds_open_device(device_name, 0 /* rw */, verbose);
if (sg_fd < 0) {
- fprintf(stderr, ME "open error: %s: %s\n", device_name,
+ fprintf(stderr, "open error: %s: %s\n", device_name,
safe_strerror(-sg_fd));
return SG_LIB_FILE_ERROR;
}
@@ -300,31 +306,34 @@ int main(int argc, char * argv[])
list_len = (reportLunsBuff[0] << 24) + (reportLunsBuff[1] << 16) +
(reportLunsBuff[2] << 8) + reportLunsBuff[3];
if (do_raw) {
- dStrRaw((const char *)reportLunsBuff, list_len + 4);
+ dStrRaw((const char *)reportLunsBuff, list_len + 8);
goto the_end;
}
if (do_hex) {
- dStrHex((const char *)reportLunsBuff, list_len + 4, 1);
+ dStrHex((const char *)reportLunsBuff, list_len + 8, 1);
goto the_end;
}
luns = (list_len / 8);
- printf("Lun list length = %d which imples %d lun entr%s\n",
- list_len, luns, ((1 == luns) ? "y" : "ies"));
+ if (0 == do_quiet)
+ printf("Lun list length = %d which imples %d lun entr%s\n",
+ list_len, luns, ((1 == luns) ? "y" : "ies"));
if ((list_len + 8) > (int)sizeof(reportLunsBuff)) {
luns = ((sizeof(reportLunsBuff) - 8) / 8);
trunc = 1;
- printf(" <<too many luns for internal buffer, will show %d "
- "luns>>\n", luns);
+ fprintf(stderr, " <<too many luns for internal buffer, will "
+ "show %d luns>>\n", luns);
}
- if (verbose) {
+ if (verbose > 1) {
fprintf(stderr, "\nOutput response in hex\n");
dStrHex((const char *)reportLunsBuff,
(trunc ? (int)sizeof(reportLunsBuff) : list_len + 8), 1);
}
for (k = 0, off = 8; k < luns; ++k) {
- if (0 == k)
- printf("Report luns [select_report=%d]:\n", select_rep);
- printf(" ");
+ if (0 == do_quiet) {
+ if (0 == k)
+ printf("Report luns [select_report=%d]:\n", select_rep);
+ printf(" ");
+ }
for (m = 0; m < 8; ++m, ++off)
printf("%02x", reportLunsBuff[off]);
printf("\n");
diff --git a/sg_map26.c b/sg_map26.c
index 5f92ca36..72a51af6 100644
--- a/sg_map26.c
+++ b/sg_map26.c
@@ -58,7 +58,7 @@
#include "sg_lib.h"
-static char * version_str = "1.05 20070127";
+static char * version_str = "1.05 20070419";
#define ME "sg_map26: "
@@ -1044,7 +1044,7 @@ int main(int argc, char * argv[])
fprintf(stderr, ME "version: %s\n", version_str);
return 0;
default:
- fprintf(stderr, "unrecognised switch code 0x%x ??\n",
+ fprintf(stderr, "unrecognised option code 0x%x ??\n",
c);
usage();
return SG_LIB_SYNTAX_ERROR;
diff --git a/sg_modes.8 b/sg_modes.8
index 0b6b7033..5b580bf6 100644
--- a/sg_modes.8
+++ b/sg_modes.8
@@ -1,4 +1,4 @@
-.TH SG_MODES "8" "January 2007" "sg3_utils\-1.23" SG3_UTILS
+.TH SG_MODES "8" "February 2007" "sg3_utils\-1.24" SG3_UTILS
.SH NAME
sg_modes \- reads mode pages with SCSI MODE SENSE command
.SH SYNOPSIS
@@ -47,12 +47,20 @@ are requested which is equivalent to '\-\-page=63,255'.
.TP
\fB\-c\fR, \fB\-\-control\fR=\fIPC\fR
\fIPC\fR is the page control value. Up to four different versions of each
-page are held by the device: the current values [0] (i.e. those active at
-the moment), the changeable values [1] (bit mask showing which fields could
-be changed with a MODE SELECT), default values [2] (the manufacturer's
-settings). Finally there are the saved values [3] which are the values that
-will be re\-instated the next time the device is power cycled. If this option
-is not given then current values [0] are assumed.
+page are held by the device:
+.br
+ \fB0\fR : current values (i.e. those active at present)
+.br
+ \fB1\fR : changeable values
+.br
+ \fB2\fR : default values (i.e. the manufacturer's settings)
+.br
+ \fB3\fR : saved values
+.br
+The changeable values are bit masks showing which fields could be changed
+with a MODE SELECT. The saved values will be re\-instated the next time
+the device is power cycled or reset. If this option is not given then
+current values [0] are assumed.
.TP
\fB\-d\fR, \fB\-\-dbd\fR
disable block descriptors. By default, block descriptors (usually
@@ -134,7 +142,7 @@ then has the same action as '\-R'
\fB\-R\fR
output the selected mode page to stdout a byte per line. Each line contains
two hexadecimal digits (e.g. "3e"). Useful as input (after editing) to
-the sg_wr_mode utility.
+the sg_wr_mode(8) utility.
.TP
\fB\-6\fR, \fB\-\-six\fR
by default this utility sends a 10 byte MODE SENSE command to
@@ -228,7 +236,7 @@ for the subpage code is 0.
\fB\-r\fR
output the selected mode page to stdout a byte per line. Each line contains
two hexadecimal digits (e.g. "3e"). Useful as input (after editing) to
-the sg_wr_mode utility.
+the sg_wr_mode(8) utility.
.TP
\fB\-subp\fR=\fISPG\fR
sub page code to fetch. Should be a hexadecimal number between 0 and
@@ -252,7 +260,7 @@ Copyright \(co 2000\-2007 Douglas Gilbert
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 sdparm(sdparm), sg_wr_mode(sg3_utils), sginfo(sg3_utils),
+.B sdparm(8), sg_wr_mode(8), sginfo(8),
.B sgmode(scsirastools), scsiinfo(net), scu(net),
.B seatools(seagate)
.PP
diff --git a/sg_modes.c b/sg_modes.c
index e663a9f9..607ab532 100644
--- a/sg_modes.c
+++ b/sg_modes.c
@@ -23,7 +23,7 @@
*/
-static char * version_str = "1.23 20070127";
+static char * version_str = "1.25 20070425";
#define MX_ALLOC_LEN (1024 * 4)
#define PG_CODE_ALL 0x3f
@@ -297,7 +297,7 @@ static int process_cl_new(struct opts_t * optsp, int argc, char * argv[])
++optsp->do_version;
break;
default:
- fprintf(stderr, "unrecognised switch code %c [0x%x]\n", c, c);
+ fprintf(stderr, "unrecognised option code %c [0x%x]\n", c, c);
if (optsp->do_help)
break;
usage();
@@ -646,10 +646,10 @@ static struct page_code_desc pc_desc_t_spi4[] = {
};
static struct page_code_desc pc_desc_t_sas[] = {
- {0x18, 0x0, "LU SSP, short format"},
- {0x19, 0x0, "Port SSP, short format"},
- {0x19, 0x1, "Port SSP, phy control and discover"},
- {0x19, 0x2, "Port SSP, shared"},
+ {0x18, 0x0, "Protocol specific logical unit (SAS)"},
+ {0x19, 0x0, "Protocol specific port (SAS)"},
+ {0x19, 0x1, "Phy control and discover (SAS)"},
+ {0x19, 0x2, "Shared port control (SAS)"},
};
static struct page_code_desc pc_desc_t_adt[] = {
@@ -851,7 +851,7 @@ static int examine_pages(int sg_fd, int inq_pdt, int inq_byte6,
const char * cp;
mresp_len = (optsp->do_raw || optsp->do_hex) ? sizeof(rbuf) : 4;
- for (header = 0, k = 0; k < 0x3f; ++k) {
+ for (header = 0, k = 0; k < PG_CODE_MAX; ++k) {
if (optsp->do_six) {
res = sg_ll_mode_sense6(sg_fd, 0, 0, k, 0, rbuf, mresp_len,
0, optsp->do_verbose);
@@ -940,7 +940,7 @@ int main(int argc, char * argv[])
if (NULL == opts.device_name) {
if (opts.do_list) {
- if ((opts.pg_code < 0) || (opts.pg_code > 0x3f)) {
+ if ((opts.pg_code < 0) || (opts.pg_code > PG_CODE_MAX)) {
printf(" Assume peripheral device type: disk\n");
list_page_codes(0, 0, -1);
} else {
@@ -1107,6 +1107,11 @@ int main(int argc, char * argv[])
specific = rsp_buff[3];
longlba = rsp_buff[4] & 1;
}
+ if ((bd_len + headerlen) > md_len) {
+ fprintf(stderr, "Invalid block descriptor length=%d, ignore\n",
+ bd_len);
+ bd_len = 0;
+ }
if (opts.do_raw) {
if (1 == opts.do_raw)
dStrRaw((const char *)rsp_buff, md_len);
diff --git a/sg_opcodes.c b/sg_opcodes.c
index 017fb38c..1c36e327 100644
--- a/sg_opcodes.c
+++ b/sg_opcodes.c
@@ -21,7 +21,7 @@
#include "sg_cmds_basic.h"
#include "sg_cmds_extra.h"
-static char * version_str = "0.29 20070127";
+static char * version_str = "0.30 20070419"; /* spc4r09+07-159r0 */
// #define USE_LINUX_SG_IO_IF 1
@@ -30,7 +30,7 @@ static char * version_str = "0.29 20070127";
* SG_IO ioctl and a more generic sg_pt mechanism that is portable
* to other OSes. The code is conditionally compiled depending
* on the USE_LINUX_SG_IO_IF define and whether the Makefile
- * indicates the OS is linux.
+ * indicates the OS is Linux.
* N.B. Various Makefiles are set assuming this is not defined.
*
* - since support for the SCSI REPORT SUPPORTED OPERATION CODES and
@@ -306,7 +306,7 @@ static int process_cl_new(struct opts_t * optsp, int argc, char * argv[])
++optsp->do_version;
break;
default:
- fprintf(stderr, "unrecognised switch code %c [0x%x]\n", c, c);
+ fprintf(stderr, "unrecognised option code %c [0x%x]\n", c, c);
if (optsp->do_help)
break;
usage();
@@ -884,6 +884,10 @@ int main(int argc, char * argv[])
printf(" Target reset\n");
if (rsoc_buff[0] & 0x1)
printf(" Wakeup\n");
+ if (rsoc_buff[1] & 0x4)
+ printf(" Query unit attention\n");
+ if (rsoc_buff[1] & 0x2)
+ printf(" Query task set\n");
if (rsoc_buff[1] & 0x1)
printf(" I_T nexus reset\n");
} else if (0 == rep_opts) { /* list all supported operation codes */
@@ -1075,7 +1079,7 @@ static int do_rsoc(int sg_fd, int rctd, int rep_opts, int rq_opcode,
unsigned char rsocCmdBlk[RSOC_CMD_LEN] = {SG_MAINTENANCE_IN, RSOC_SA, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0};
unsigned char sense_b[SENSE_BUFF_LEN];
- void * ptvp;
+ struct sg_pt_base * ptvp;
if (rctd)
rsocCmdBlk[2] |= 0x80;
@@ -1145,7 +1149,7 @@ static int do_rstmf(int sg_fd, void * resp, int mx_resp_len, int noisy,
unsigned char rstmfCmdBlk[RSTMF_CMD_LEN] = {SG_MAINTENANCE_IN, RSTMF_SA,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
unsigned char sense_b[SENSE_BUFF_LEN];
- void * ptvp;
+ struct sg_pt_base * ptvp;
rstmfCmdBlk[6] = (unsigned char)((mx_resp_len >> 24) & 0xff);
rstmfCmdBlk[7] = (unsigned char)((mx_resp_len >> 16) & 0xff);
diff --git a/sg_persist.8 b/sg_persist.8
index 5d132e07..6447cbdb 100644
--- a/sg_persist.8
+++ b/sg_persist.8
@@ -1,4 +1,4 @@
-.TH SG_PERSIST "8" "January 2007" "sg3_utils\-1.23" SG3_UTILS
+.TH SG_PERSIST "8" "March 2007" "sg3_utils\-1.24" SG3_UTILS
.SH NAME
sg_persist \- sends a SCSI PERSISTENT RESERVE (IN or OUT) command
to manipulate registrations and reservations
@@ -28,12 +28,12 @@ sub\-command of the PRIN command. Other PRIN sub\-commands are
READ RESERVATION, REPORT CAPABILITIES and READ FULL STATUS.
.PP
Before trying to change Persistent reservations and registrations users
-should be aware of what they are doing! The relevant sections of the
-SCSI Primary Commands document (SPC\-4 most recent draft revision 5a
-dated 14th June 2006) are sections 5.6 (general information), 6.11 (for
-PRIN) and 6.12 (for PROUT). To safeguard against accidental use,
-the \fI\-\-out\fR option must be given when a PROUT sub\-command (e.g.
-\fI\-\-register\fR) is used.
+should be aware of what they are doing. The relevant sections of the
+SCSI Primary Commands document (i.e. SPC\-4 whose most recent draft is
+revision 9 dated 17th February 2007) are sections 5.6 (titled "Reservation"),
+6.13 (for the PRIN command) and 6.14 (for the PROUT command). To safeguard
+against accidental use, the \fI\-\-out\fR option must be given when a
+PROUT sub\-command (e.g. \fI\-\-register\fR) is used.
.PP
The older SCSI RESERVE and RELEASE commands (both 6 and 10 byte variants)
are not supported by this utility. In SPC\-3, RESERVE and RELEASE are
@@ -131,7 +131,7 @@ exclusive access \- registrants only, 7\-> write exclusive \- all registrants,
8\-> exclusive access \- all registrants. Default value is 0 (which is
an invalid type). Each "persistent reservation type" is explained in more
detail in a subsection of that name in the read reservation section of
-the PRIN command (section 6.11.3.4 of SPC\-4 revision 5a).
+the PRIN command (section 6.13.3.4 of SPC\-4 revision 9).
.TP
\fB\-s\fR, \fB\-\-read\-full\-status\fR
Read Full Status is a sub\-command of the PRIN command. For each registration
@@ -188,7 +188,7 @@ current persistent reservation. The \fI\-\-prout\-type=TYPE\fR
and \fI\-\-param\-rk=RK\fR options, matching the reservation, must also be
specified.
.TP
-\fB\-c\fR, \fB\-\-report/-capabilities\fR
+\fB\-c\fR, \fB\-\-report\-capabilities\fR
Report Capabilities is a sub\-command of the PRIN command. It lists
information about the aspects of persistent reservations that the
\fIDEVICE\fR supports.
@@ -202,10 +202,11 @@ and \fI\-\-param\-rk=RK\fR options must also be specified.
a transportID is required for the PROUT 'register and move' sub\-command
and is optional for the PROUT 'register' and 'register and ignore
existing key' sub\-commands. The latter two sub\-commands can take multiple
-transportIDs in a list but only one is supported on the command line.
-\fIH,H...\fR is a comma separated list of hex numbers representing
-the bytes of the transportID. The list of hex numbers will be padded
-out with zeros to 24 bytes which is the minimum length of a
+transportIDs in a list but only one is supported with this option
+variant (use the following option variant that reads stdin if multiple
+transportIDs are required). \fIH,H...\fR is a comma separated list of hex
+bytes which represent the transportID. The list of hex numbers will be
+padded out with zeros to 24 bytes which is the minimum length of a
transportID. A transportID longer than 24 bytes (e.g. for iSCSI) is
padded with zeros so its length is a multiple of 4.
.TP
@@ -257,6 +258,9 @@ mismatched \fI\-\-prout\-type=TYPE\fR) will result in a RESERVATION
CONFLICT status. This can be a bit confusing when you know there is
only one (active) initiator: the "conflict" is with the SPC standard, not
another initiator.
+.PP
+TransportIDs are defined in SPC\-4 and their structures vary depending
+on the underlying transport.
.SH EXAMPLES
.PP
Due to defaults the simplest example executes the 'read keys' sub\-command
diff --git a/sg_persist.c b/sg_persist.c
index 3e00cb95..afbe3627 100644
--- a/sg_persist.c
+++ b/sg_persist.c
@@ -24,7 +24,7 @@
*/
-static char * version_str = "0.31 20070129";
+static char * version_str = "0.33 20070314";
#define PRIN_RKEY_SA 0x0
@@ -143,7 +143,7 @@ static void usage()
" --reserve|-R PR Out: Reserve\n"
" --transport-id=H,H...|-X H,H... TransportID "
"hex number(s),\n"
- " comma separated list\n"
+ " comma separated list of bytes\n"
" --transport-id=-|-X - read TransportID from stdin\n"
" --unreg|-U optional with PR Out Register "
"and Move\n"
@@ -295,30 +295,29 @@ static int prin_work(int sg_fd, int prin_sa, int do_verbose, int do_hex)
fprintf(stderr, "PR in: aborted command\n");
else
fprintf(stderr, "PR in: command failed\n");
- return 1;
+ return res;
}
if (PRIN_RCAP_SA == prin_sa) {
if (8 != pr_buff[1]) {
fprintf(stderr, "Unexpected response for PRIN Report "
"Capabilities\n");
- return 1;
+ return SG_LIB_CAT_MALFORMED;
}
if (do_hex)
dStrHex((const char *)pr_buff, 8, 1);
else {
printf("Report capabilities response:\n");
- printf(" Compatible Reservation handling(CRH): %d\n",
+ printf(" Compatible Reservation Handling(CRH): %d\n",
!!(pr_buff[2] & 0x10));
- printf(" Specify Initiator Ports capable(SIP_C): %d\n",
+ printf(" Specify Initiator Ports Capable(SIP_C): %d\n",
!!(pr_buff[2] & 0x8));
- printf(" All target ports capable(ATP_C): %d\n",
+ printf(" All Target Ports Capable(ATP_C): %d\n",
!!(pr_buff[2] & 0x4));
- printf(" Persist Through Power Loss capable(PTPL_C): %d\n",
+ printf(" Persist Through Power Loss Capable(PTPL_C): %d\n",
!!(pr_buff[2] & 0x1));
- printf(" Type Mask Valid(TMV): %d\n",
- !!(pr_buff[3] & 0x80));
+ printf(" Type Mask Valid(TMV): %d\n", !!(pr_buff[3] & 0x80));
printf(" Allow commands: %d\n", (pr_buff[3] >> 4) & 0x7);
- printf(" Persist Through Power Loss active(PTPL_A): %d\n",
+ printf(" Persist Through Power Loss Active(PTPL_A): %d\n",
!!(pr_buff[3] & 0x1));
if (pr_buff[3] & 0x80) {
printf(" Support indicated in Type mask:\n");
@@ -482,7 +481,7 @@ static int prout_work(int sg_fd, int prout_sa, unsigned int prout_type,
fprintf(stderr, "PR out: aborted command\n");
else
fprintf(stderr, "PR out: command failed\n");
- return 1;
+ return res;
} else if (do_verbose) {
char buff[64];
@@ -544,7 +543,7 @@ static int prout_rmove_work(int sg_fd, unsigned int prout_type,
fprintf(stderr, "PR out: aborted command\n");
else
fprintf(stderr, "PR out: command failed\n");
- return 1;
+ return res;
} else if (do_verbose)
fprintf(stderr, "PR out: 'register and move' "
"command successful\n");
diff --git a/sg_prevent.c b/sg_prevent.c
index ef0ee58e..ee697442 100644
--- a/sg_prevent.c
+++ b/sg_prevent.c
@@ -42,7 +42,7 @@
* given SCSI device.
*/
-static char * version_str = "1.06 20070129";
+static char * version_str = "1.06 20070419";
#define ME "sg_prevent: "
@@ -117,7 +117,7 @@ int main(int argc, char * argv[])
fprintf(stderr, ME "version: %s\n", version_str);
return 0;
default:
- fprintf(stderr, "unrecognised switch code 0x%x ??\n", c);
+ fprintf(stderr, "unrecognised option code 0x%x ??\n", c);
usage();
return SG_LIB_SYNTAX_ERROR;
}
diff --git a/sg_pt.h b/sg_pt.h
index 9a5cab67..672c1131 100644
--- a/sg_pt.h
+++ b/sg_pt.h
@@ -34,6 +34,15 @@
extern "C" {
#endif
+/* This declaration hides the fact that each implementation has its own
+ structure "derived" (using a C++ term) from this one. It compiles
+ because 'struct sg_pt_base' is only referenced (by pointer: 'objp')
+ in this interface. An instance of this structure represents the
+ context of one SCSI command. */
+struct sg_pt_base;
+
+
+
/* Returns >= 0 if successful. If error in Unix returns negated errno. */
extern int scsi_pt_open_device(const char * device_name, int read_only,
int verbose);
@@ -42,26 +51,27 @@ extern int scsi_pt_open_device(const char * device_name, int read_only,
extern int scsi_pt_close_device(int device_fd);
-/* One scsi_pt_obj per SCSI command issued */
-extern void * construct_scsi_pt_obj();
+/* Create one struct sg_pt_base object per SCSI command issued */
+extern struct sg_pt_base * construct_scsi_pt_obj(void);
-/* Only invoke once per scsi_pt_obj */
-extern void set_scsi_pt_cdb(void * scsi_pt_obj, const unsigned char * cdb,
- int cdb_len);
-/* Only invoke once per scsi_pt_obj. Zeroes given 'sense' buffer. */
-extern void set_scsi_pt_sense(void * scsi_pt_obj, unsigned char * sense,
+/* Only invoke once per objp */
+extern void set_scsi_pt_cdb(struct sg_pt_base * objp,
+ const unsigned char * cdb, int cdb_len);
+/* Only invoke once per objp. Zeroes given 'sense' buffer. */
+extern void set_scsi_pt_sense(struct sg_pt_base * objp, unsigned char * sense,
int max_sense_len);
-/* Invoke at most once per scsi_pt_obj */
-extern void set_scsi_pt_data_in(void * scsi_pt_obj, /* from device */
+/* Invoke at most once per objp */
+extern void set_scsi_pt_data_in(struct sg_pt_base * objp, /* from device */
unsigned char * dxferp, int dxfer_len);
-/* Invoke at most once per scsi_pt_obj */
-extern void set_scsi_pt_data_out(void * scsi_pt_obj, /* to device */
+/* Invoke at most once per objp */
+extern void set_scsi_pt_data_out(struct sg_pt_base * objp, /* to device */
const unsigned char * dxferp, int dxfer_len);
/* The following "set_"s implementations may be dummies */
-extern void set_scsi_pt_packet_id(void * scsi_pt_obj, int pack_id);
-extern void set_scsi_pt_tag(void * scsi_pt_obj, int tag);
-extern void set_scsi_pt_task_management(void * scsi_pt_obj, int tmf_code);
-extern void set_scsi_pt_task_attr(void * scsi_pt_obj, int attribute,
+extern void set_scsi_pt_packet_id(struct sg_pt_base * objp, int pack_id);
+extern void set_scsi_pt_tag(struct sg_pt_base * objp, unsigned long long tag);
+extern void set_scsi_pt_task_management(struct sg_pt_base * objp,
+ int tmf_code);
+extern void set_scsi_pt_task_attr(struct sg_pt_base * objp, int attribute,
int priority);
#define SCSI_PT_DO_START_OK 0
@@ -70,7 +80,7 @@ extern void set_scsi_pt_task_attr(void * scsi_pt_obj, int attribute,
/* If OS start error, negated error value (e.g. Unix '-errno') returned,
return 0 if okay (i.e. at the very least: command sent). Positive
return values are errors (see SCSI_PT_DO_* defines). */
-extern int do_scsi_pt(void * scsi_pt_obj, int fd, int timeout_secs,
+extern int do_scsi_pt(struct sg_pt_base * objp, int fd, int timeout_secs,
int verbose);
#define SCSI_PT_RESULT_GOOD 0
@@ -79,31 +89,33 @@ extern int do_scsi_pt(void * scsi_pt_obj, int fd, int timeout_secs,
#define SCSI_PT_RESULT_TRANSPORT_ERR 3
#define SCSI_PT_RESULT_OS_ERR 4
/* highest numbered applicable category returned */
-extern int get_scsi_pt_result_category(const void * scsi_pt_obj);
+extern int get_scsi_pt_result_category(const struct sg_pt_base * objp);
/* If not available return 0 */
-extern int get_scsi_pt_resid(const void * scsi_pt_obj);
+extern int get_scsi_pt_resid(const struct sg_pt_base * objp);
/* Returns SCSI status value (from device that received the
command). */
-extern int get_scsi_pt_status_response(const void * scsi_pt_obj);
+extern int get_scsi_pt_status_response(const struct sg_pt_base * objp);
/* Actual sense length returned. If sense data is present but
actual sense length is not known, return 'max_sense_len' */
-extern int get_scsi_pt_sense_len(const void * scsi_pt_obj);
+extern int get_scsi_pt_sense_len(const struct sg_pt_base * objp);
/* If not available return 0 */
-extern int get_scsi_pt_os_err(const void * scsi_pt_obj);
-extern char * get_scsi_pt_os_err_str(const void * scsi_pt_obj,
+extern int get_scsi_pt_os_err(const struct sg_pt_base * objp);
+extern char * get_scsi_pt_os_err_str(const struct sg_pt_base * objp,
int max_b_len, char * b);
/* If not available return 0 */
-extern int get_scsi_pt_transport_err(const void * scsi_pt_obj);
-extern char * get_scsi_pt_transport_err_str(const void * scsi_pt_obj,
+extern int get_scsi_pt_transport_err(const struct sg_pt_base * objp);
+extern char * get_scsi_pt_transport_err_str(const struct sg_pt_base * objp,
int max_b_len, char * b);
/* If not available return -1 */
-extern int get_scsi_pt_duration_ms(const void * scsi_pt_obj);
+extern int get_scsi_pt_duration_ms(const struct sg_pt_base * objp);
+
-/* Should be invoked once per scsi_pt_obj object after other
- processing is complete in order to clean up resources. */
-extern void destruct_scsi_pt_obj(void * scsi_pt_obj);
+/* Should be invoked once per objp after other processing is complete in
+ order to clean up resources. For ever successful construct_scsi_pt_obj()
+ call there should be one destruct_scsi_pt_obj(). */
+extern void destruct_scsi_pt_obj(struct sg_pt_base * objp);
#ifdef __cplusplus
}
diff --git a/sg_pt_freebsd.c b/sg_pt_freebsd.c
index f8f59b90..4ed7c69b 100644
--- a/sg_pt_freebsd.c
+++ b/sg_pt_freebsd.c
@@ -27,7 +27,7 @@
*
*/
-/* version 1.05 2007/1/21 */
+/* version 1.07 2007/4/3 */
#include <stdio.h>
#include <stdlib.h>
@@ -85,6 +85,10 @@ struct sg_pt_freebsd_scsi {
int transport_err;
};
+struct sg_pt_base {
+ struct sg_pt_freebsd_scsi impl;
+};
+
/* Returns >= 0 if successful. If error in Unix returns negated errno. */
int scsi_pt_open_device(const char * device_name,
@@ -168,7 +172,7 @@ int scsi_pt_close_device(int device_fd)
return 0;
}
-void * construct_scsi_pt_obj()
+struct sg_pt_base * construct_scsi_pt_obj()
{
struct sg_pt_freebsd_scsi * ptp;
@@ -178,12 +182,12 @@ void * construct_scsi_pt_obj()
memset(ptp, 0, sizeof(struct sg_pt_freebsd_scsi));
ptp->dxfer_dir = CAM_DIR_NONE;
}
- return ptp;
+ return (struct sg_pt_base *)ptp;
}
-void destruct_scsi_pt_obj(void * vp)
+void destruct_scsi_pt_obj(struct sg_pt_base * vp)
{
- struct sg_pt_freebsd_scsi * ptp = (struct sg_pt_freebsd_scsi *)vp;
+ struct sg_pt_freebsd_scsi * ptp = &vp->impl;
if (ptp) {
if (ptp->ccb)
@@ -192,9 +196,10 @@ void destruct_scsi_pt_obj(void * vp)
}
}
-void set_scsi_pt_cdb(void * vp, const unsigned char * cdb, int cdb_len)
+void set_scsi_pt_cdb(struct sg_pt_base * vp, const unsigned char * cdb,
+ int cdb_len)
{
- struct sg_pt_freebsd_scsi * ptp = (struct sg_pt_freebsd_scsi *)vp;
+ struct sg_pt_freebsd_scsi * ptp = &vp->impl;
if (ptp->cdb)
++ptp->in_err;
@@ -202,10 +207,10 @@ void set_scsi_pt_cdb(void * vp, const unsigned char * cdb, int cdb_len)
ptp->cdb_len = cdb_len;
}
-void set_scsi_pt_sense(void * vp, unsigned char * sense,
+void set_scsi_pt_sense(struct sg_pt_base * vp, unsigned char * sense,
int max_sense_len)
{
- struct sg_pt_freebsd_scsi * ptp = (struct sg_pt_freebsd_scsi *)vp;
+ struct sg_pt_freebsd_scsi * ptp = &vp->impl;
if (ptp->sense)
++ptp->in_err;
@@ -214,10 +219,10 @@ void set_scsi_pt_sense(void * vp, unsigned char * sense,
ptp->sense_len = max_sense_len;
}
-void set_scsi_pt_data_in(void * vp, /* from device */
+void set_scsi_pt_data_in(struct sg_pt_base * vp, /* from device */
unsigned char * dxferp, int dxfer_len)
{
- struct sg_pt_freebsd_scsi * ptp = (struct sg_pt_freebsd_scsi *)vp;
+ struct sg_pt_freebsd_scsi * ptp = &vp->impl;
if (ptp->dxferp)
++ptp->in_err;
@@ -228,10 +233,10 @@ void set_scsi_pt_data_in(void * vp, /* from device */
}
}
-void set_scsi_pt_data_out(void * vp, /* to device */
+void set_scsi_pt_data_out(struct sg_pt_base * vp, /* to device */
const unsigned char * dxferp, int dxfer_len)
{
- struct sg_pt_freebsd_scsi * ptp = (struct sg_pt_freebsd_scsi *)vp;
+ struct sg_pt_freebsd_scsi * ptp = &vp->impl;
if (ptp->dxferp)
++ptp->in_err;
@@ -242,38 +247,41 @@ void set_scsi_pt_data_out(void * vp, /* to device */
}
}
-void set_scsi_pt_packet_id(void * vp __attribute__ ((unused)),
+void set_scsi_pt_packet_id(struct sg_pt_base * vp __attribute__ ((unused)),
int pack_id __attribute__ ((unused)))
{
}
-void set_scsi_pt_tag(void * vp, int tag __attribute__ ((unused)))
+void set_scsi_pt_tag(struct sg_pt_base * vp,
+ unsigned long long tag __attribute__ ((unused)))
{
- struct sg_pt_freebsd_scsi * ptp = (struct sg_pt_freebsd_scsi *)vp;
+ struct sg_pt_freebsd_scsi * ptp = &vp->impl;
++ptp->in_err;
}
-void set_scsi_pt_task_management(void * vp,
+void set_scsi_pt_task_management(struct sg_pt_base * vp,
int tmf_code __attribute__ ((unused)))
{
- struct sg_pt_freebsd_scsi * ptp = (struct sg_pt_freebsd_scsi *)vp;
+ struct sg_pt_freebsd_scsi * ptp = &vp->impl;
++ptp->in_err;
}
-void set_scsi_pt_task_attr(void * vp, int attrib __attribute__ ((unused)),
- int priority __attribute__ ((unused)))
+void set_scsi_pt_task_attr(struct sg_pt_base * vp,
+ int attrib __attribute__ ((unused)),
+ int priority __attribute__ ((unused)))
{
- struct sg_pt_freebsd_scsi * ptp = (struct sg_pt_freebsd_scsi *)vp;
+ struct sg_pt_freebsd_scsi * ptp = &vp->impl;
++ptp->in_err;
}
-int do_scsi_pt(void * vp, int device_fd, int time_secs, int verbose)
+int do_scsi_pt(struct sg_pt_base * vp, int device_fd, int time_secs,
+ int verbose)
{
int fd = device_fd - FREEBSD_FDOFFSET;
- struct sg_pt_freebsd_scsi * ptp = (struct sg_pt_freebsd_scsi *)vp;
+ struct sg_pt_freebsd_scsi * ptp = &vp->impl;
struct freebsd_dev_channel *fdchan;
union ccb *ccb;
int len, timout_ms;
@@ -368,10 +376,9 @@ int do_scsi_pt(void * vp, int device_fd, int time_secs, int verbose)
return 0;
}
-int get_scsi_pt_result_category(const void * vp)
+int get_scsi_pt_result_category(const struct sg_pt_base * vp)
{
- const struct sg_pt_freebsd_scsi * ptp =
- (const struct sg_pt_freebsd_scsi *)vp;
+ const struct sg_pt_freebsd_scsi * ptp = &vp->impl;
if (ptp->os_err)
return SCSI_PT_RESULT_OS_ERR;
@@ -386,60 +393,55 @@ int get_scsi_pt_result_category(const void * vp)
return SCSI_PT_RESULT_GOOD;
}
-int get_scsi_pt_resid(const void * vp)
+int get_scsi_pt_resid(const struct sg_pt_base * vp)
{
- const struct sg_pt_freebsd_scsi * ptp =
- (const struct sg_pt_freebsd_scsi *)vp;
+ const struct sg_pt_freebsd_scsi * ptp = &vp->impl;
return ptp->resid;
}
-int get_scsi_pt_status_response(const void * vp)
+int get_scsi_pt_status_response(const struct sg_pt_base * vp)
{
- const struct sg_pt_freebsd_scsi * ptp =
- (const struct sg_pt_freebsd_scsi *)vp;
+ const struct sg_pt_freebsd_scsi * ptp = &vp->impl;
return ptp->scsi_status;
}
-int get_scsi_pt_sense_len(const void * vp)
+int get_scsi_pt_sense_len(const struct sg_pt_base * vp)
{
- const struct sg_pt_freebsd_scsi * ptp =
- (const struct sg_pt_freebsd_scsi *)vp;
+ const struct sg_pt_freebsd_scsi * ptp = &vp->impl;
int len;
len = ptp->sense_len - ptp->sense_resid;
return (len > 0) ? len : 0;
}
-int get_scsi_pt_duration_ms(const void * vp __attribute__ ((unused)))
+int get_scsi_pt_duration_ms(const struct sg_pt_base * vp __attribute__ ((unused)))
{
- // const struct sg_pt_freebsd_scsi * ptp = vp;
+ // const struct sg_pt_freebsd_scsi * ptp = &vp->impl;
return -1;
}
-int get_scsi_pt_transport_err(const void * vp)
+int get_scsi_pt_transport_err(const struct sg_pt_base * vp)
{
- const struct sg_pt_freebsd_scsi * ptp =
- (const struct sg_pt_freebsd_scsi *)vp;
+ const struct sg_pt_freebsd_scsi * ptp = &vp->impl;
return ptp->transport_err;
}
-int get_scsi_pt_os_err(const void * vp)
+int get_scsi_pt_os_err(const struct sg_pt_base * vp)
{
- const struct sg_pt_freebsd_scsi * ptp =
- (const struct sg_pt_freebsd_scsi *)vp;
+ const struct sg_pt_freebsd_scsi * ptp = &vp->impl;
return ptp->os_err;
}
-char * get_scsi_pt_transport_err_str(const void * vp, int max_b_len, char * b)
+char * get_scsi_pt_transport_err_str(const struct sg_pt_base * vp,
+ int max_b_len, char * b)
{
- const struct sg_pt_freebsd_scsi * ptp =
- (const struct sg_pt_freebsd_scsi *)vp;
+ const struct sg_pt_freebsd_scsi * ptp = &vp->impl;
if (0 == ptp->transport_err) {
strncpy(b, "no transport error available", max_b_len);
@@ -461,11 +463,10 @@ char * get_scsi_pt_transport_err_str(const void * vp, int max_b_len, char * b)
return b;
}
-char * get_scsi_pt_os_err_str(const void * vp,
+char * get_scsi_pt_os_err_str(const struct sg_pt_base * vp,
int max_b_len, char * b)
{
- const struct sg_pt_freebsd_scsi * ptp =
- (const struct sg_pt_freebsd_scsi *)vp;
+ const struct sg_pt_freebsd_scsi * ptp = &vp->impl;
const char * cp;
cp = safe_strerror(ptp->os_err);
diff --git a/sg_pt_linux.c b/sg_pt_linux.c
index ff56879b..b57b016b 100644
--- a/sg_pt_linux.c
+++ b/sg_pt_linux.c
@@ -27,7 +27,7 @@
*
*/
-/* version 1.02 2007/1/21 */
+/* version 1.03 2007/4/3 */
#include <stdio.h>
#include <stdlib.h>
@@ -47,6 +47,17 @@
#define DEF_TIMEOUT 60000 /* 60,000 millisecs (60 seconds) */
+struct sg_pt_linux_scsi {
+ struct sg_io_hdr io_hdr;
+ int in_err;
+ int os_err;
+};
+
+struct sg_pt_base {
+ struct sg_pt_linux_scsi impl;
+};
+
+
/* Returns >= 0 if successful. If error in Unix returns negated errno. */
int scsi_pt_open_device(const char * device_name, int read_only,
@@ -80,13 +91,7 @@ int scsi_pt_close_device(int device_fd)
}
-struct sg_pt_linux_scsi {
- struct sg_io_hdr io_hdr;
- int in_err;
- int os_err;
-};
-
-void * construct_scsi_pt_obj()
+struct sg_pt_base * construct_scsi_pt_obj()
{
struct sg_pt_linux_scsi * ptp;
@@ -97,20 +102,21 @@ void * construct_scsi_pt_obj()
ptp->io_hdr.interface_id = 'S';
ptp->io_hdr.dxfer_direction = SG_DXFER_NONE;
}
- return ptp;
+ return (struct sg_pt_base *)ptp;
}
-void destruct_scsi_pt_obj(void * vp)
+void destruct_scsi_pt_obj(struct sg_pt_base * vp)
{
- struct sg_pt_linux_scsi * ptp = (struct sg_pt_linux_scsi *)vp;
+ struct sg_pt_linux_scsi * ptp = &vp->impl;
if (ptp)
free(ptp);
}
-void set_scsi_pt_cdb(void * vp, const unsigned char * cdb, int cdb_len)
+void set_scsi_pt_cdb(struct sg_pt_base * vp, const unsigned char * cdb,
+ int cdb_len)
{
- struct sg_pt_linux_scsi * ptp = (struct sg_pt_linux_scsi *)vp;
+ struct sg_pt_linux_scsi * ptp = &vp->impl;
if (ptp->io_hdr.cmdp)
++ptp->in_err;
@@ -118,10 +124,10 @@ void set_scsi_pt_cdb(void * vp, const unsigned char * cdb, int cdb_len)
ptp->io_hdr.cmd_len = cdb_len;
}
-void set_scsi_pt_sense(void * vp, unsigned char * sense,
+void set_scsi_pt_sense(struct sg_pt_base * vp, unsigned char * sense,
int max_sense_len)
{
- struct sg_pt_linux_scsi * ptp = (struct sg_pt_linux_scsi *)vp;
+ struct sg_pt_linux_scsi * ptp = &vp->impl;
if (ptp->io_hdr.sbp)
++ptp->in_err;
@@ -130,10 +136,10 @@ void set_scsi_pt_sense(void * vp, unsigned char * sense,
ptp->io_hdr.mx_sb_len = max_sense_len;
}
-void set_scsi_pt_data_in(void * vp, /* from device */
+void set_scsi_pt_data_in(struct sg_pt_base * vp, /* from device */
unsigned char * dxferp, int dxfer_len)
{
- struct sg_pt_linux_scsi * ptp = (struct sg_pt_linux_scsi *)vp;
+ struct sg_pt_linux_scsi * ptp = &vp->impl;
if (ptp->io_hdr.dxferp)
++ptp->in_err;
@@ -144,10 +150,10 @@ void set_scsi_pt_data_in(void * vp, /* from device */
}
}
-void set_scsi_pt_data_out(void * vp, /* to device */
+void set_scsi_pt_data_out(struct sg_pt_base * vp, /* to device */
const unsigned char * dxferp, int dxfer_len)
{
- struct sg_pt_linux_scsi * ptp = (struct sg_pt_linux_scsi *)vp;
+ struct sg_pt_linux_scsi * ptp = &vp->impl;
if (ptp->io_hdr.dxferp)
++ptp->in_err;
@@ -158,41 +164,43 @@ void set_scsi_pt_data_out(void * vp, /* to device */
}
}
-void set_scsi_pt_packet_id(void * vp, int pack_id)
+void set_scsi_pt_packet_id(struct sg_pt_base * vp, int pack_id)
{
- struct sg_pt_linux_scsi * ptp = (struct sg_pt_linux_scsi *)vp;
+ struct sg_pt_linux_scsi * ptp = &vp->impl;
ptp->io_hdr.pack_id = pack_id;
}
-void set_scsi_pt_tag(void * vp, int tag)
+void set_scsi_pt_tag(struct sg_pt_base * vp, unsigned long long tag)
{
- struct sg_pt_linux_scsi * ptp = (struct sg_pt_linux_scsi *)vp;
+ struct sg_pt_linux_scsi * ptp = &vp->impl;
++ptp->in_err;
tag = tag; /* dummy to silence compiler */
}
-void set_scsi_pt_task_management(void * vp, int tmf_code)
+/* Note that task management function codes are transport specific */
+void set_scsi_pt_task_management(struct sg_pt_base * vp, int tmf_code)
{
- struct sg_pt_linux_scsi * ptp = (struct sg_pt_linux_scsi *)vp;
+ struct sg_pt_linux_scsi * ptp = &vp->impl;
++ptp->in_err;
tmf_code = tmf_code; /* dummy to silence compiler */
}
-void set_scsi_pt_task_attr(void * vp, int attribute, int priority)
+void set_scsi_pt_task_attr(struct sg_pt_base * vp, int attribute,
+ int priority)
{
- struct sg_pt_linux_scsi * ptp = (struct sg_pt_linux_scsi *)vp;
+ struct sg_pt_linux_scsi * ptp = &vp->impl;
++ptp->in_err;
attribute = attribute; /* dummy to silence compiler */
priority = priority; /* dummy to silence compiler */
}
-int do_scsi_pt(void * vp, int fd, int time_secs, int verbose)
+int do_scsi_pt(struct sg_pt_base * vp, int fd, int time_secs, int verbose)
{
- struct sg_pt_linux_scsi * ptp = (struct sg_pt_linux_scsi *)vp;
+ struct sg_pt_linux_scsi * ptp = &vp->impl;
if (NULL == sg_warnings_strm)
sg_warnings_strm = stderr;
@@ -241,9 +249,9 @@ int do_scsi_pt(void * vp, int fd, int time_secs, int verbose)
#define SG_LIB_SUGGEST_MASK SUGGEST_MASK
#define SG_LIB_DRIVER_SENSE DRIVER_SENSE
-int get_scsi_pt_result_category(const void * vp)
+int get_scsi_pt_result_category(const struct sg_pt_base * vp)
{
- const struct sg_pt_linux_scsi * ptp = (const struct sg_pt_linux_scsi *)vp;
+ const struct sg_pt_linux_scsi * ptp = &vp->impl;
int dr_st = ptp->io_hdr.driver_status & SG_LIB_DRIVER_MASK;
int scsi_st = ptp->io_hdr.status & 0x7e;
@@ -263,44 +271,44 @@ int get_scsi_pt_result_category(const void * vp)
return SCSI_PT_RESULT_GOOD;
}
-int get_scsi_pt_resid(const void * vp)
+int get_scsi_pt_resid(const struct sg_pt_base * vp)
{
- const struct sg_pt_linux_scsi * ptp = (const struct sg_pt_linux_scsi *)vp;
+ const struct sg_pt_linux_scsi * ptp = &vp->impl;
return ptp->io_hdr.resid;
}
-int get_scsi_pt_status_response(const void * vp)
+int get_scsi_pt_status_response(const struct sg_pt_base * vp)
{
- const struct sg_pt_linux_scsi * ptp = (const struct sg_pt_linux_scsi *)vp;
+ const struct sg_pt_linux_scsi * ptp = &vp->impl;
return ptp->io_hdr.status;
}
-int get_scsi_pt_sense_len(const void * vp)
+int get_scsi_pt_sense_len(const struct sg_pt_base * vp)
{
- const struct sg_pt_linux_scsi * ptp = (const struct sg_pt_linux_scsi *)vp;
+ const struct sg_pt_linux_scsi * ptp = &vp->impl;
return ptp->io_hdr.sb_len_wr;
}
-int get_scsi_pt_duration_ms(const void * vp)
+int get_scsi_pt_duration_ms(const struct sg_pt_base * vp)
{
- const struct sg_pt_linux_scsi * ptp = (const struct sg_pt_linux_scsi *)vp;
+ const struct sg_pt_linux_scsi * ptp = &vp->impl;
return ptp->io_hdr.duration;
}
-int get_scsi_pt_transport_err(const void * vp)
+int get_scsi_pt_transport_err(const struct sg_pt_base * vp)
{
- const struct sg_pt_linux_scsi * ptp = (const struct sg_pt_linux_scsi *)vp;
+ const struct sg_pt_linux_scsi * ptp = &vp->impl;
return (ptp->io_hdr.host_status << 8) + ptp->io_hdr.driver_status;
}
-int get_scsi_pt_os_err(const void * vp)
+int get_scsi_pt_os_err(const struct sg_pt_base * vp)
{
- const struct sg_pt_linux_scsi * ptp = (const struct sg_pt_linux_scsi *)vp;
+ const struct sg_pt_linux_scsi * ptp = &vp->impl;
return ptp->os_err;
}
@@ -334,9 +342,10 @@ static const char * linux_driver_suggests[] = {
(int)(sizeof(linux_driver_suggests) / sizeof(linux_driver_suggests[0]))
-char * get_scsi_pt_transport_err_str(const void * vp, int max_b_len, char * b)
+char * get_scsi_pt_transport_err_str(const struct sg_pt_base * vp,
+ int max_b_len, char * b)
{
- const struct sg_pt_linux_scsi * ptp = (const struct sg_pt_linux_scsi *)vp;
+ const struct sg_pt_linux_scsi * ptp = &vp->impl;
int ds = ptp->io_hdr.driver_status;
int hs = ptp->io_hdr.host_status;
int n, m;
@@ -374,10 +383,10 @@ char * get_scsi_pt_transport_err_str(const void * vp, int max_b_len, char * b)
return b;
}
-char * get_scsi_pt_os_err_str(const void * vp,
+char * get_scsi_pt_os_err_str(const struct sg_pt_base * vp,
int max_b_len, char * b)
{
- const struct sg_pt_linux_scsi * ptp = (const struct sg_pt_linux_scsi *)vp;
+ const struct sg_pt_linux_scsi * ptp = &vp->impl;
const char * cp;
cp = safe_strerror(ptp->os_err);
diff --git a/sg_pt_osf1.c b/sg_pt_osf1.c
index 60f0cdd4..419c8cf7 100644
--- a/sg_pt_osf1.c
+++ b/sg_pt_osf1.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2005-2006 Douglas Gilbert.
+ * Copyright (c) 2005-2007 Douglas Gilbert.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -47,6 +47,8 @@
#include "sg_pt.h"
#include "sg_lib.h"
+/* Changed to use struct sg_pt_base 20070403 */
+
#define OSF1_MAXDEV 64
@@ -79,6 +81,10 @@ struct sg_pt_osf1_scsi {
int transport_err;
};
+struct sg_pt_base {
+ struct sg_pt_osf1_scsi impl;
+};
+
/* Returns >= 0 if successful. If error in Unix returns negated errno. */
int scsi_pt_open_device(const char * device_name,
@@ -111,7 +117,8 @@ int scsi_pt_open_device(const char * device_name,
return -1;
}
- fdchan = calloc(1,sizeof(struct osf1_dev_channel));
+ fdchan = (struct osf1_dev_channel *)calloc(1,
+ sizeof(struct osf1_dev_channel));
if (fdchan == NULL) {
// errno already set by call to malloc()
return -1;
@@ -167,29 +174,30 @@ int scsi_pt_close_device(int device_fd)
return 0;
}
-void * construct_scsi_pt_obj()
+struct sg_pt_base * construct_scsi_pt_obj()
{
struct sg_pt_osf1_scsi * ptp;
- ptp = malloc(sizeof(struct sg_pt_osf1_scsi));
+ ptp = (struct sg_pt_osf1_scsi *)malloc(sizeof(struct sg_pt_osf1_scsi));
if (ptp) {
bzero(ptp, sizeof(struct sg_pt_osf1_scsi));
ptp->dxfer_dir = CAM_DIR_NONE;
}
- return ptp;
+ return (struct sg_pt_base *)ptp;
}
-void destruct_scsi_pt_obj(void * vp)
+void destruct_scsi_pt_obj(struct sg_pt_base * vp)
{
- struct sg_pt_osf1_scsi * ptp = vp;
+ struct sg_pt_osf1_scsi * ptp = &vp->impl;
if (ptp)
free(ptp);
}
-void set_scsi_pt_cdb(void * vp, const unsigned char * cdb, int cdb_len)
+void set_scsi_pt_cdb(struct sg_pt_base * vp, const unsigned char * cdb,
+ int cdb_len)
{
- struct sg_pt_osf1_scsi * ptp = vp;
+ struct sg_pt_osf1_scsi * ptp = &vp->impl;
if (ptp->cdb)
++ptp->in_err;
@@ -197,10 +205,10 @@ void set_scsi_pt_cdb(void * vp, const unsigned char * cdb, int cdb_len)
ptp->cdb_len = cdb_len;
}
-void set_scsi_pt_sense(void * vp, unsigned char * sense,
+void set_scsi_pt_sense(struct sg_pt_base * vp, unsigned char * sense,
int max_sense_len)
{
- struct sg_pt_osf1_scsi * ptp = vp;
+ struct sg_pt_osf1_scsi * ptp = &vp->impl;
if (ptp->sense)
++ptp->in_err;
@@ -209,10 +217,10 @@ void set_scsi_pt_sense(void * vp, unsigned char * sense,
ptp->sense_len = max_sense_len;
}
-void set_scsi_pt_data_in(void * vp, /* from device */
+void set_scsi_pt_data_in(struct sg_pt_base * vp, /* from device */
unsigned char * dxferp, int dxfer_len)
{
- struct sg_pt_osf1_scsi * ptp = vp;
+ struct sg_pt_osf1_scsi * ptp = &vp->impl;
if (ptp->dxferp)
++ptp->in_err;
@@ -223,10 +231,10 @@ void set_scsi_pt_data_in(void * vp, /* from device */
}
}
-void set_scsi_pt_data_out(void * vp, /* to device */
+void set_scsi_pt_data_out(struct sg_pt_base * vp, /* to device */
const unsigned char * dxferp, int dxfer_len)
{
- struct sg_pt_osf1_scsi * ptp = vp;
+ struct sg_pt_osf1_scsi * ptp = &vp->impl;
if (ptp->dxferp)
++ptp->in_err;
@@ -237,33 +245,33 @@ void set_scsi_pt_data_out(void * vp, /* to device */
}
}
-void set_scsi_pt_packet_id(void * vp, int pack_id)
+void set_scsi_pt_packet_id(struct sg_pt_base * vp, int pack_id)
{
}
-void set_scsi_pt_tag(void * vp, int tag)
+void set_scsi_pt_tag(struct sg_pt_base * vp, unsigned long long tag)
{
- struct sg_pt_osf1_scsi * ptp = vp;
+ struct sg_pt_osf1_scsi * ptp = &vp->impl;
++ptp->in_err;
}
-void set_scsi_pt_task_management(void * vp, int tmf_code)
+void set_scsi_pt_task_management(struct sg_pt_base * vp, int tmf_code)
{
- struct sg_pt_osf1_scsi * ptp = vp;
+ struct sg_pt_osf1_scsi * ptp = &vp->impl;
++ptp->in_err;
}
-void set_scsi_pt_task_attr(void * vp, int attrib, int priority)
+void set_scsi_pt_task_attr(struct sg_pt_base * vp, int attrib, int priority)
{
- struct sg_pt_osf1_scsi * ptp = vp;
+ struct sg_pt_osf1_scsi * ptp = &vp->impl;
++ptp->in_err;
}
-static int release_sim(void *vp, int device_fd, int verbose) {
- struct sg_pt_osf1_scsi * ptp = vp;
+static int release_sim(struct sg_pt_base *vp, int device_fd, int verbose) {
+ struct sg_pt_osf1_scsi * ptp = &vp->impl;
struct osf1_dev_channel *fdchan = devicetable[device_fd];
UAGT_CAM_CCB uagt;
CCB_RELSIM relsim;
@@ -293,9 +301,9 @@ static int release_sim(void *vp, int device_fd, int verbose) {
return retval;
}
-int do_scsi_pt(void * vp, int device_fd, int time_secs, int verbose)
+int do_scsi_pt(struct sg_pt_base * vp, int device_fd, int time_secs, int verbose)
{
- struct sg_pt_osf1_scsi * ptp = vp;
+ struct sg_pt_osf1_scsi * ptp = &vp->impl;
struct osf1_dev_channel *fdchan;
int len, retval;
CCB_SCSIIO ccb;
@@ -381,9 +389,9 @@ int do_scsi_pt(void * vp, int device_fd, int time_secs, int verbose)
return 0;
}
-int get_scsi_pt_result_category(const void * vp)
+int get_scsi_pt_result_category(const struct sg_pt_base * vp)
{
- const struct sg_pt_osf1_scsi * ptp = vp;
+ const struct sg_pt_osf1_scsi * ptp = &vp->impl;
if (ptp->os_err)
return SCSI_PT_RESULT_OS_ERR;
@@ -398,54 +406,54 @@ int get_scsi_pt_result_category(const void * vp)
return SCSI_PT_RESULT_GOOD;
}
-int get_scsi_pt_resid(const void * vp)
+int get_scsi_pt_resid(const struct sg_pt_base * vp)
{
- const struct sg_pt_osf1_scsi * ptp = vp;
+ const struct sg_pt_osf1_scsi * ptp = &vp->impl;
return ptp->resid;
}
-int get_scsi_pt_status_response(const void * vp)
+int get_scsi_pt_status_response(const struct sg_pt_base * vp)
{
- const struct sg_pt_osf1_scsi * ptp = vp;
+ const struct sg_pt_osf1_scsi * ptp = &vp->impl;
return ptp->scsi_status;
}
-int get_scsi_pt_sense_len(const void * vp)
+int get_scsi_pt_sense_len(const struct sg_pt_base * vp)
{
- const struct sg_pt_osf1_scsi * ptp = vp;
+ const struct sg_pt_osf1_scsi * ptp = &vp->impl;
int len;
len = ptp->sense_len - ptp->sense_resid;
return (len > 0) ? len : 0;
}
-int get_scsi_pt_duration_ms(const void * vp)
+int get_scsi_pt_duration_ms(const struct sg_pt_base * vp)
{
- // const struct sg_pt_osf1_scsi * ptp = vp;
+ // const struct sg_pt_osf1_scsi * ptp = &vp->impl;
return -1;
}
-int get_scsi_pt_transport_err(const void * vp)
+int get_scsi_pt_transport_err(const struct sg_pt_base * vp)
{
- const struct sg_pt_osf1_scsi * ptp = vp;
+ const struct sg_pt_osf1_scsi * ptp = &vp->impl;
return ptp->transport_err;
}
-int get_scsi_pt_os_err(const void * vp)
+int get_scsi_pt_os_err(const struct sg_pt_base * vp)
{
- const struct sg_pt_osf1_scsi * ptp = vp;
+ const struct sg_pt_osf1_scsi * ptp = &vp->impl;
return ptp->os_err;
}
-char * get_scsi_pt_transport_err_str(const void * vp, int max_b_len, char * b)
+char * get_scsi_pt_transport_err_str(const struct sg_pt_base * vp, int max_b_len, char * b)
{
- struct sg_pt_osf1_scsi * ptp = (void *)vp;
+ const struct sg_pt_osf1_scsi * ptp = &vp->impl;
if (0 == ptp->transport_err) {
strncpy(b, "no transport error available", max_b_len);
@@ -457,10 +465,10 @@ char * get_scsi_pt_transport_err_str(const void * vp, int max_b_len, char * b)
return b;
}
-char * get_scsi_pt_os_err_str(const void * vp,
+char * get_scsi_pt_os_err_str(const struct sg_pt_base * vp,
int max_b_len, char * b)
{
- const struct sg_pt_osf1_scsi * ptp = vp;
+ const struct sg_pt_osf1_scsi * ptp = &vp->impl;
const char * cp;
cp = safe_strerror(ptp->os_err);
diff --git a/sg_pt_solaris.c b/sg_pt_solaris.c
new file mode 100644
index 00000000..3a829a77
--- /dev/null
+++ b/sg_pt_solaris.c
@@ -0,0 +1,325 @@
+/*
+ * Copyright (c) 2007 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.
+ *
+ */
+
+/* version 1.00 2007/5/3 */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include <unistd.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <sys/param.h>
+
+/* Solaris headers */
+#include <sys/scsi/generic/commands.h>
+#include <sys/scsi/generic/status.h>
+#include <sys/scsi/impl/types.h>
+#include <sys/scsi/impl/uscsi.h>
+
+#include "sg_pt.h"
+#include "sg_lib.h"
+
+
+#define DEF_TIMEOUT 60 /* 60 seconds */
+
+struct sg_pt_solaris_scsi {
+ struct uscsi_cmd uscsi;
+ int max_sense_len;
+ int in_err;
+ int os_err;
+};
+
+struct sg_pt_base {
+ struct sg_pt_solaris_scsi impl;
+};
+
+
+
+/* Returns >= 0 if successful. If error in Unix returns negated errno. */
+int scsi_pt_open_device(const char * device_name, int read_only,
+ int verbose)
+{
+ int oflags = O_NONBLOCK | O_RDWR;
+ int fd;
+
+ read_only = read_only; /* ignore read_only, suppress warning */
+ if (verbose > 1) {
+ fprintf(stderr, "open %s with flags=0x%x\n", device_name, oflags);
+ }
+ fd = open(device_name, oflags);
+ if (fd < 0)
+ fd = -errno;
+ return fd;
+}
+
+/* Returns 0 if successful. If error in Unix returns negated errno. */
+int scsi_pt_close_device(int device_fd)
+{
+ int res;
+
+ res = close(device_fd);
+ if (res < 0)
+ res = -errno;
+ return res;
+}
+
+
+struct sg_pt_base * construct_scsi_pt_obj()
+{
+ struct sg_pt_solaris_scsi * ptp;
+
+ ptp = (struct sg_pt_solaris_scsi *)
+ malloc(sizeof(struct sg_pt_solaris_scsi));
+ if (ptp) {
+ memset(ptp, 0, sizeof(struct sg_pt_solaris_scsi));
+ ptp->uscsi.uscsi_timeout = DEF_TIMEOUT;
+ ptp->uscsi.uscsi_flags = USCSI_READ | USCSI_ISOLATE | USCSI_RQENABLE;
+ ptp->uscsi.uscsi_timeout = DEF_TIMEOUT;
+ }
+ return (struct sg_pt_base *)ptp;
+}
+
+void destruct_scsi_pt_obj(struct sg_pt_base * vp)
+{
+ struct sg_pt_solaris_scsi * ptp = &vp->impl;
+
+ if (ptp)
+ free(ptp);
+}
+
+void set_scsi_pt_cdb(struct sg_pt_base * vp, const unsigned char * cdb,
+ int cdb_len)
+{
+ struct sg_pt_solaris_scsi * ptp = &vp->impl;
+
+ if (ptp->uscsi.uscsi_cdb)
+ ++ptp->in_err;
+ ptp->uscsi.uscsi_cdb = (char *)cdb;
+ ptp->uscsi.uscsi_cdblen = cdb_len;
+}
+
+void set_scsi_pt_sense(struct sg_pt_base * vp, unsigned char * sense,
+ int max_sense_len)
+{
+ struct sg_pt_solaris_scsi * ptp = &vp->impl;
+
+ if (ptp->uscsi.uscsi_rqbuf)
+ ++ptp->in_err;
+ memset(sense, 0, max_sense_len);
+ ptp->uscsi.uscsi_rqbuf = (char *)sense;
+ ptp->uscsi.uscsi_rqlen = max_sense_len;
+ ptp->max_sense_len = max_sense_len;
+}
+
+void set_scsi_pt_data_in(struct sg_pt_base * vp, /* from device */
+ unsigned char * dxferp, int dxfer_len)
+{
+ struct sg_pt_solaris_scsi * ptp = &vp->impl;
+
+ if (ptp->uscsi.uscsi_bufaddr)
+ ++ptp->in_err;
+ if (dxfer_len > 0) {
+ ptp->uscsi.uscsi_bufaddr = (char *)dxferp;
+ ptp->uscsi.uscsi_buflen = dxfer_len;
+ ptp->uscsi.uscsi_flags = USCSI_READ | USCSI_ISOLATE | USCSI_RQENABLE;
+ }
+}
+
+void set_scsi_pt_data_out(struct sg_pt_base * vp, /* to device */
+ const unsigned char * dxferp, int dxfer_len)
+{
+ struct sg_pt_solaris_scsi * ptp = &vp->impl;
+
+ if (ptp->uscsi.uscsi_bufaddr)
+ ++ptp->in_err;
+ if (dxfer_len > 0) {
+ ptp->uscsi.uscsi_bufaddr = (char *)dxferp;
+ ptp->uscsi.uscsi_buflen = dxfer_len;
+ ptp->uscsi.uscsi_flags = USCSI_WRITE | USCSI_ISOLATE | USCSI_RQENABLE;
+ }
+}
+
+void set_scsi_pt_packet_id(struct sg_pt_base * vp, int pack_id)
+{
+ // struct sg_pt_solaris_scsi * ptp = &vp->impl;
+
+ vp = vp; /* ignore and suppress warning */
+ pack_id = pack_id; /* ignore and suppress warning */
+}
+
+void set_scsi_pt_tag(struct sg_pt_base * vp, unsigned long long tag)
+{
+ // struct sg_pt_solaris_scsi * ptp = &vp->impl;
+
+ vp = vp; /* ignore and suppress warning */
+ tag = tag; /* ignore and suppress warning */
+}
+
+/* Note that task management function codes are transport specific */
+void set_scsi_pt_task_management(struct sg_pt_base * vp, int tmf_code)
+{
+ struct sg_pt_solaris_scsi * ptp = &vp->impl;
+
+ ++ptp->in_err;
+ tmf_code = tmf_code; /* dummy to silence compiler */
+}
+
+void set_scsi_pt_task_attr(struct sg_pt_base * vp, int attribute,
+ int priority)
+{
+ struct sg_pt_solaris_scsi * ptp = &vp->impl;
+
+ ++ptp->in_err;
+ attribute = attribute; /* dummy to silence compiler */
+ priority = priority; /* dummy to silence compiler */
+}
+
+int do_scsi_pt(struct sg_pt_base * vp, int fd, int time_secs, int verbose)
+{
+ struct sg_pt_solaris_scsi * ptp = &vp->impl;
+
+ if (ptp->in_err) {
+ if (verbose)
+ fprintf(stderr, "Replicated or unused set_scsi_pt... "
+ "functions\n");
+ return SCSI_PT_DO_BAD_PARAMS;
+ }
+ if (NULL == ptp->uscsi.uscsi_cdb) {
+ if (verbose)
+ fprintf(stderr, "No SCSI command (cdb) given\n");
+ return SCSI_PT_DO_BAD_PARAMS;
+ }
+ if (time_secs > 0)
+ ptp->uscsi.uscsi_timeout = time_secs;
+
+ if (ioctl(fd, USCSICMD, &ptp->uscsi)) {
+ ptp->os_err = errno;
+ if ((EIO == ptp->os_err) && ptp->uscsi.uscsi_status) {
+ ptp->os_err = 0;
+ return 0;
+ }
+ if (verbose)
+ fprintf(stderr, "ioctl(USCSICMD) failed with os_err "
+ "(errno) = %d\n", ptp->os_err);
+ return -ptp->os_err;
+ }
+ return 0;
+}
+
+int get_scsi_pt_result_category(const struct sg_pt_base * vp)
+{
+ const struct sg_pt_solaris_scsi * ptp = &vp->impl;
+ int scsi_st = ptp->uscsi.uscsi_status;
+
+ if (ptp->os_err)
+ return SCSI_PT_RESULT_OS_ERR;
+ else if ((SAM_STAT_CHECK_CONDITION == scsi_st) ||
+ (SAM_STAT_COMMAND_TERMINATED == scsi_st))
+ return SCSI_PT_RESULT_SENSE;
+ else if (scsi_st)
+ return SCSI_PT_RESULT_STATUS;
+ else
+ return SCSI_PT_RESULT_GOOD;
+}
+
+int get_scsi_pt_resid(const struct sg_pt_base * vp)
+{
+ const struct sg_pt_solaris_scsi * ptp = &vp->impl;
+
+ return ptp->uscsi.uscsi_resid;
+}
+
+int get_scsi_pt_status_response(const struct sg_pt_base * vp)
+{
+ const struct sg_pt_solaris_scsi * ptp = &vp->impl;
+
+ return ptp->uscsi.uscsi_status;
+}
+
+int get_scsi_pt_sense_len(const struct sg_pt_base * vp)
+{
+ const struct sg_pt_solaris_scsi * ptp = &vp->impl;
+ int res;
+
+ if (ptp->max_sense_len > 0) {
+ res = ptp->max_sense_len - ptp->uscsi.uscsi_rqresid;
+ return (res > 0) ? res : 0;
+ }
+ return 0;
+}
+
+int get_scsi_pt_duration_ms(const struct sg_pt_base * vp)
+{
+ // const struct sg_pt_solaris_scsi * ptp = &vp->impl;
+
+ vp = vp; /* ignore and suppress warning */
+ return -1; /* not available */
+}
+
+int get_scsi_pt_transport_err(const struct sg_pt_base * vp)
+{
+ // const struct sg_pt_solaris_scsi * ptp = &vp->impl;
+
+ vp = vp; /* ignore and suppress warning */
+ return 0;
+}
+
+int get_scsi_pt_os_err(const struct sg_pt_base * vp)
+{
+ const struct sg_pt_solaris_scsi * ptp = &vp->impl;
+
+ return ptp->os_err;
+}
+
+char * get_scsi_pt_transport_err_str(const struct sg_pt_base * vp,
+ int max_b_len, char * b)
+{
+ // const struct sg_pt_solaris_scsi * ptp = &vp->impl;
+
+ vp = vp; /* ignore and suppress warning */
+ if (max_b_len > 0)
+ b[0] = '\0';
+
+ return b;
+}
+
+char * get_scsi_pt_os_err_str(const struct sg_pt_base * vp,
+ int max_b_len, char * b)
+{
+ const struct sg_pt_solaris_scsi * ptp = &vp->impl;
+ const char * cp;
+
+ cp = safe_strerror(ptp->os_err);
+ strncpy(b, cp, max_b_len);
+ if ((int)strlen(cp) >= max_b_len)
+ b[max_b_len - 1] = '\0';
+ return b;
+}
diff --git a/sg_pt_win32.c b/sg_pt_win32.c
index 7434b9c3..213292d6 100644
--- a/sg_pt_win32.c
+++ b/sg_pt_win32.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2006 Douglas Gilbert.
+ * Copyright (c) 2006-2007 Douglas Gilbert.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -27,7 +27,7 @@
*
*/
-/* version 1.01 2006/11/19 */
+/* version 1.04 2007/04/3 */
#include <stdio.h>
#include <stdlib.h>
@@ -84,6 +84,10 @@ struct sg_pt_win32_scsi {
int transport_err; /* windows error number */
};
+struct sg_pt_base {
+ struct sg_pt_win32_scsi impl;
+};
+
/* Returns >= 0 if successful. If error in Unix returns negated errno.
* Optionally accept leading "\\.\". If given something of the form
* "ScSi<num>:<bus>,<target>,<lun>" where the values in angle brackets
@@ -202,11 +206,11 @@ int scsi_pt_close_device(int device_fd)
return 0;
}
-void * construct_scsi_pt_obj()
+struct sg_pt_base * construct_scsi_pt_obj()
{
struct sg_pt_win32_scsi * psp;
- psp = malloc(sizeof(struct sg_pt_win32_scsi));
+ psp = (struct sg_pt_win32_scsi *)malloc(sizeof(struct sg_pt_win32_scsi));
if (psp) {
memset(psp, 0, sizeof(struct sg_pt_win32_scsi));
psp->swb.spt.DataIn = SCSI_IOCTL_DATA_UNSPECIFIED;
@@ -215,21 +219,22 @@ void * construct_scsi_pt_obj()
offsetof(SCSI_PASS_THROUGH_WITH_BUFFERS, ucSenseBuf);
psp->swb.spt.TimeOutValue = DEF_TIMEOUT;
}
- return psp;
+ return (struct sg_pt_base *)psp;
}
-void destruct_scsi_pt_obj(void * vp)
+void destruct_scsi_pt_obj(struct sg_pt_base * vp)
{
- struct sg_pt_win32_scsi * psp = vp;
+ struct sg_pt_win32_scsi * psp = &vp->impl;
if (psp) {
free(psp);
}
}
-void set_scsi_pt_cdb(void * vp, const unsigned char * cdb, int cdb_len)
+void set_scsi_pt_cdb(struct sg_pt_base * vp, const unsigned char * cdb,
+ int cdb_len)
{
- struct sg_pt_win32_scsi * psp = vp;
+ struct sg_pt_win32_scsi * psp = &vp->impl;
if (psp->swb.spt.CdbLength > 0)
++psp->in_err;
@@ -241,10 +246,10 @@ void set_scsi_pt_cdb(void * vp, const unsigned char * cdb, int cdb_len)
psp->swb.spt.CdbLength = cdb_len;
}
-void set_scsi_pt_sense(void * vp, unsigned char * sense,
+void set_scsi_pt_sense(struct sg_pt_base * vp, unsigned char * sense,
int sense_len)
{
- struct sg_pt_win32_scsi * psp = vp;
+ struct sg_pt_win32_scsi * psp = &vp->impl;
if (psp->sensep)
++psp->in_err;
@@ -253,10 +258,10 @@ void set_scsi_pt_sense(void * vp, unsigned char * sense,
psp->sense_len = sense_len;
}
-void set_scsi_pt_data_in(void * vp, /* from device */
+void set_scsi_pt_data_in(struct sg_pt_base * vp, /* from device */
unsigned char * dxferp, int dxfer_len)
{
- struct sg_pt_win32_scsi * psp = vp;
+ struct sg_pt_win32_scsi * psp = &vp->impl;
if (psp->dxferp)
++psp->in_err;
@@ -267,10 +272,10 @@ void set_scsi_pt_data_in(void * vp, /* from device */
}
}
-void set_scsi_pt_data_out(void * vp, /* to device */
+void set_scsi_pt_data_out(struct sg_pt_base * vp, /* to device */
const unsigned char * dxferp, int dxfer_len)
{
- struct sg_pt_win32_scsi * psp = vp;
+ struct sg_pt_win32_scsi * psp = &vp->impl;
if (psp->dxferp)
++psp->in_err;
@@ -281,38 +286,41 @@ void set_scsi_pt_data_out(void * vp, /* to device */
}
}
-void set_scsi_pt_packet_id(void * vp __attribute__ ((unused)),
+void set_scsi_pt_packet_id(struct sg_pt_base * vp __attribute__ ((unused)),
int pack_id __attribute__ ((unused)))
{
}
-void set_scsi_pt_tag(void * vp, int tag __attribute__ ((unused)))
+void set_scsi_pt_tag(struct sg_pt_base * vp,
+ unsigned long long tag __attribute__ ((unused)))
{
- struct sg_pt_win32_scsi * psp = vp;
+ struct sg_pt_win32_scsi * psp = &vp->impl;
++psp->in_err;
}
-void set_scsi_pt_task_management(void * vp,
+void set_scsi_pt_task_management(struct sg_pt_base * vp,
int tmf_code __attribute__ ((unused)))
{
- struct sg_pt_win32_scsi * psp = vp;
+ struct sg_pt_win32_scsi * psp = &vp->impl;
++psp->in_err;
}
-void set_scsi_pt_task_attr(void * vp, int attrib __attribute__ ((unused)),
- int priority __attribute__ ((unused)))
+void set_scsi_pt_task_attr(struct sg_pt_base * vp,
+ int attrib __attribute__ ((unused)),
+ int priority __attribute__ ((unused)))
{
- struct sg_pt_win32_scsi * psp = vp;
+ struct sg_pt_win32_scsi * psp = &vp->impl;
++psp->in_err;
}
-int do_scsi_pt(void * vp, int device_fd, int time_secs, int verbose)
+int do_scsi_pt(struct sg_pt_base * vp, int device_fd, int time_secs,
+ int verbose)
{
int index = device_fd - WIN32_FDOFFSET;
- struct sg_pt_win32_scsi * psp = vp;
+ struct sg_pt_win32_scsi * psp = &vp->impl;
struct sg_pt_handle * shp;
BOOL status;
ULONG returned;
@@ -431,9 +439,9 @@ int do_scsi_pt(void * vp, int device_fd, int time_secs, int verbose)
return 0;
}
-int get_scsi_pt_result_category(const void * vp)
+int get_scsi_pt_result_category(const struct sg_pt_base * vp)
{
- const struct sg_pt_win32_scsi * psp = vp;
+ const struct sg_pt_win32_scsi * psp = &vp->impl;
if (psp->transport_err) /* give transport error highest priority */
return SCSI_PT_RESULT_TRANSPORT_ERR;
@@ -448,54 +456,55 @@ int get_scsi_pt_result_category(const void * vp)
return SCSI_PT_RESULT_GOOD;
}
-int get_scsi_pt_resid(const void * vp)
+int get_scsi_pt_resid(const struct sg_pt_base * vp)
{
- const struct sg_pt_win32_scsi * psp = vp;
+ const struct sg_pt_win32_scsi * psp = &vp->impl;
return psp->resid;
}
-int get_scsi_pt_status_response(const void * vp)
+int get_scsi_pt_status_response(const struct sg_pt_base * vp)
{
- const struct sg_pt_win32_scsi * psp = vp;
+ const struct sg_pt_win32_scsi * psp = &vp->impl;
return psp->scsi_status;
}
-int get_scsi_pt_sense_len(const void * vp)
+int get_scsi_pt_sense_len(const struct sg_pt_base * vp)
{
- const struct sg_pt_win32_scsi * psp = vp;
+ const struct sg_pt_win32_scsi * psp = &vp->impl;
int len;
len = psp->sense_len - psp->sense_resid;
return (len > 0) ? len : 0;
}
-int get_scsi_pt_duration_ms(const void * vp __attribute__ ((unused)))
+int get_scsi_pt_duration_ms(const struct sg_pt_base * vp __attribute__ ((unused)))
{
- // const struct sg_pt_freebsd_scsi * psp = vp;
+ // const struct sg_pt_freebsd_scsi * psp = &vp->impl;
return -1;
}
-int get_scsi_pt_transport_err(const void * vp)
+int get_scsi_pt_transport_err(const struct sg_pt_base * vp)
{
- const struct sg_pt_win32_scsi * psp = vp;
+ const struct sg_pt_win32_scsi * psp = &vp->impl;
return psp->transport_err;
}
-int get_scsi_pt_os_err(const void * vp)
+int get_scsi_pt_os_err(const struct sg_pt_base * vp)
{
- const struct sg_pt_win32_scsi * psp = vp;
+ const struct sg_pt_win32_scsi * psp = &vp->impl;
return psp->os_err;
}
-char * get_scsi_pt_transport_err_str(const void * vp, int max_b_len, char * b)
+char * get_scsi_pt_transport_err_str(const struct sg_pt_base * vp,
+ int max_b_len, char * b)
{
- struct sg_pt_win32_scsi * psp = (void *)vp;
+ struct sg_pt_win32_scsi * psp = (struct sg_pt_win32_scsi *)&vp->impl;
LPVOID lpMsgBuf;
int k, num, ch;
@@ -527,10 +536,10 @@ char * get_scsi_pt_transport_err_str(const void * vp, int max_b_len, char * b)
return b;
}
-char * get_scsi_pt_os_err_str(const void * vp,
+char * get_scsi_pt_os_err_str(const struct sg_pt_base * vp,
int max_b_len, char * b)
{
- const struct sg_pt_win32_scsi * psp = vp;
+ const struct sg_pt_win32_scsi * psp = &vp->impl;
const char * cp;
cp = safe_strerror(psp->os_err);
diff --git a/sg_raw.8 b/sg_raw.8
new file mode 100644
index 00000000..8e4094ba
--- /dev/null
+++ b/sg_raw.8
@@ -0,0 +1,99 @@
+.TH SG_RAW "8" "April 2007" "sg3_utils\-1.24" SG3_UTILS
+.SH NAME
+sg_raw \- sends an arbitrary SCSI command (with an optional data phase) to a
+device
+.SH SYNOPSIS
+.B sg_raw [\fIOPTIONS\fR] \fIDEVICE\fR CDB0 CDB1 ...
+.SH DESCRIPTION
+This utility sends an arbitrary SCSI command (between 6 and 16 bytes) to
+the \fIDEVICE\fR. For the optional data phase, data can either be
+read from a file and sent to the \fIDEVICE\fR or received from
+the \fIDEVICE\fR and then displayed or written to a file.
+.PP
+The SCSI command may be between 6 and 16 bytes long. Each command byte is
+specified in plain hex format (00..FF) without a prefix or suffix. See
+EXAMPLES section below.
+.PP
+The commands pass through a generic SCSI interface which is implemented
+for several operating systems including Linux, FreeBSD and Windows.
+.SH OPTIONS
+Arguments to long options are mandatory for short options as well.
+.TP
+\fB\-b\fR, \fB\-\-binary\fR
+Dump data in binary form, even when writing to stdout.
+.TP
+\fB\-h\fR, \fB\-\-help\fR
+Display usage information and exit.
+.TP
+\fB\-i\fR, \fB\-\-infile\fR=\fIIFILE\fR
+Read data from \fIIFILE\fR instead of stdin. This option is ignored if
+\fB\-\-send\fR is not specified.
+.TP
+\fB\-k\fR, \fB\-\-skip\fR=\fILEN\fR
+Skip the first \fILEN\fR bytes of the input file or stream. This option
+is ignored if \fB\-\-send\fR is not specified.
+.TP
+\fB\-n\fR, \fB\-\-nosense\fR
+Don't display SCSI Sense information.
+.TP
+\fB\-o\fR, \fB\-\-outfile\fR=\fIOFILE\fR
+Write data received from the \fIDEVICE\fR to \fIOFILE\fR. By default,
+data is dumped in hex format to stdout. This option is ignored if
+\fB\-\-request\fR is not specified.
+.TP
+\fB\-r\fR, \fB\-\-request\fR=\fIRLEN\fR
+Expect to receive up to \fIRLEN\fR bytes of data from the \fIDEVICE\fR.
+\fIRLEN\fR may be suffixed with 'k' to use kilobytes (1024 bytes) instead
+of bytes. This option and \fB\-\-send\fR are mutually exclusive.
+.TP
+\fB\-s\fR, \fB\-\-send\fR=\fISLEN\fR
+Read \fISLEN\fR bytes of data, either from stdin or from a file, and send
+them to the \fIDEVICE\fR. This option and \fB\-\-request\fR are mutually
+exclusive.
+.TP
+\fB\-t\fR, \fB\-\-timeout\fR=\fISEC\fR
+Wait up to \fISEC\fR seconds for command completion (default: 20).
+Note that if a command times out the operating system may start by
+aborting the command and if that is unsuccessful it may attempt
+to reset the device.
+.TP
+\fB\-v\fR, \fB\-\-verbose\fR
+Increase level of verbosity. Can be used multiple times.
+.TP
+\fB\-V\fR, \fB\-\-version\fR
+Display version and license information and exit.
+.SH EXAMPLES
+.TP
+sg_raw /dev/scd0 1b 00 00 00 02 00
+Eject the medium in CD drive /dev/scd0.
+.TP
+sg_raw \-r 1k /dev/sg0 12 00 00 00 60 00
+Perform an INQUIRY on /dev/sg0 and dump the response data (up to
+1024 bytes) to stdout.
+.TP
+sg_raw \-s 512 \-i i512.bin /dev/sda 3b 02 00 00 00 00 00 02 00 00
+Showing an example of writing 512 bytes to a sector on a disk
+is a little dangerous. Instead this example will read i512.bin (assumed
+to be 512 bytes long) and use the SCSI WRITE BUFFER command to send
+it to the "data" buffer (that is mode 2). This is a safe operation.
+.TP
+sg_raw \-r 512 \-o o512.bin /dev/sda 3c 02 00 00 00 00 00 02 00 00
+This will use the SCSI READ BUFFER command to read 512 bytes from
+the "data" buffer (i.e. mode 2) then write it to the o512.bin file.
+When used in conjunction with the previous example, if both commands
+work then 'cmp i512.bin o512.bin' should show a match.
+.SH EXIT STATUS
+The exit status of sg_raw is 0 when it is successful. Otherwise see
+the sg3_utils(8) man page.
+.SH AUTHOR
+Written by Ingo van Lil
+.SH "REPORTING BUGS"
+Report bugs to <inguin at gmx dot de>.
+.SH COPYRIGHT
+Copyright \(co 2001\-2007 Ingo van Lil
+.br
+This software is distributed under the GPL version 2. There is NO
+warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+.SH "SEE ALSO"
+.B sg_opcodes sg_vpd(sg3_utils), hdparm(hdparm), sgdiag(scsirastools)
+
diff --git a/sg_raw.c b/sg_raw.c
new file mode 100644
index 00000000..b68a6773
--- /dev/null
+++ b/sg_raw.c
@@ -0,0 +1,448 @@
+/*
+ * A utility program originally written for the Linux OS SCSI subsystem.
+ *
+ * Copyright (C) 2000-2007 Ingo van Lil <inguin@gmx.de>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program can be used to send raw SCSI commands (with an optional
+ * data phase) through a Generic SCSI interface.
+ */
+
+#include <stdlib.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <string.h>
+#include <getopt.h>
+
+#include "sg_lib.h"
+#include "sg_pt.h"
+
+#define VERSION "0.3.4 (2007-04-03)"
+
+#define DEFAULT_TIMEOUT 20
+#define MIN_SCSI_CDBSZ 6
+#define MAX_SCSI_CDBSZ 16
+#define MAX_SCSI_DXLEN (64 * 1024)
+
+static struct option long_options[] = {
+ { "binary", no_argument, NULL, 'b' },
+ { "help", no_argument, NULL, 'h' },
+ { "infile", required_argument, NULL, 'i' },
+ { "skip", required_argument, NULL, 'k' },
+ { "nosense", no_argument, NULL, 'n' },
+ { "outfile", required_argument, NULL, 'o' },
+ { "request", required_argument, NULL, 'r' },
+ { "send", required_argument, NULL, 's' },
+ { "timeout", required_argument, NULL, 't' },
+ { "verbose", no_argument, NULL, 'v' },
+ { "version", no_argument, NULL, 'V' },
+ { 0, 0, 0, 0 }
+};
+
+struct opts_t {
+ char *device_name;
+ unsigned char cdb[MAX_SCSI_CDBSZ];
+ int cdb_length;
+ int do_datain;
+ int datain_len;
+ const char *datain_file;
+ int datain_binary;
+ int do_dataout;
+ int dataout_len;
+ const char *dataout_file;
+ off_t dataout_offset;
+ int timeout;
+ int no_sense;
+ int do_help;
+ int do_verbose;
+ int do_version;
+};
+
+static void version()
+{
+ fprintf(stderr,
+ "sg_raw " VERSION "\n"
+ "Copyright (C) 2007 Ingo van Lil <inguin@gmx.de>\n"
+ "This is free software. You may redistribute copies of it "
+ "under the terms of\n"
+ "the GNU General Public License "
+ "<http://www.gnu.org/licenses/gpl.html>.\n"
+ "There is NO WARRANTY, to the extent permitted by law.\n");
+}
+
+static void usage()
+{
+ fprintf(stderr,
+ "Usage: sg_raw [OPTION] DEVICE CDB0 CDB1 ...\n"
+ "\n"
+ "Options:\n"
+ " -b, --binary Dump data in binary form, even when "
+ "writing to stdout\n"
+ " -h, --help Show this message and exit\n"
+ " -i, --infile=FILE Read data to send from FILE (default: "
+ "stdin)\n"
+ " -k, --skip=LEN Skip the first LEN bytes when reading "
+ "data to send\n"
+ " -n, --nosense Don't display sense information\n"
+ " -o, --outfile=FILE Write data to FILE (default: hexdump "
+ "to stdout)\n"
+ " -r, --request=LEN Request up to LEN bytes of data\n"
+ " -s, --send=LEN Send LEN bytes of data\n"
+ " -t, --timeout=SEC Timeout in seconds (default: 20)\n"
+ " -v, --verbose Increase verbosity\n"
+ " -V, --version Show version information and exit\n"
+ "\n"
+ "Between 6 and 16 command bytes (two hex digits each) can be\n"
+ "specified and will be sent to DEVICE.\n"
+ "\n"
+ "Example: Perform INQUIRY on /dev/sg0:\n"
+ " sg_raw -r 1k /dev/sg0 12 00 00 00 60 00\n");
+}
+
+static int process_cl(struct opts_t *optsp, int argc, char *argv[])
+{
+ while (1) {
+ int c, n;
+
+ c = getopt_long(argc, argv, "r:o:bs:i:k:t:nvhV", long_options, NULL);
+ if (c == -1)
+ break;
+
+ switch (c) {
+ case 'r':
+ optsp->do_datain = 1;
+ n = sg_get_num(optarg);
+ if (n < 0 || n > MAX_SCSI_DXLEN) {
+ fprintf(stderr, "Invalid argument to '--request'\n");
+ return SG_LIB_SYNTAX_ERROR;
+ }
+ optsp->datain_len = n;
+ break;
+ case 'o':
+ if (optsp->datain_file) {
+ fprintf(stderr, "Too many '--outfile=' options\n");
+ return SG_LIB_SYNTAX_ERROR;
+ }
+ optsp->datain_file = optarg;
+ break;
+ case 'b':
+ optsp->datain_binary = 1;
+ break;
+ case 's':
+ optsp->do_dataout = 1;
+ n = sg_get_num(optarg);
+ if (n < 0 || n > MAX_SCSI_DXLEN) {
+ fprintf(stderr, "Invalid argument to '--send'\n");
+ return SG_LIB_SYNTAX_ERROR;
+ }
+ optsp->dataout_len = n;
+ break;
+ case 'i':
+ if (optsp->dataout_file) {
+ fprintf(stderr, "Too many '--infile=' options\n");
+ return SG_LIB_SYNTAX_ERROR;
+ }
+ optsp->dataout_file = optarg;
+ break;
+ case 'k':
+ n = sg_get_num(optarg);
+ if (n < 0) {
+ fprintf(stderr, "Invalid argument to '--skip'\n");
+ return SG_LIB_SYNTAX_ERROR;
+ }
+ optsp->dataout_offset = n;
+ break;
+ case 't':
+ n = sg_get_num(optarg);
+ if (n < 0) {
+ fprintf(stderr, "Invalid argument to '--timeout'\n");
+ return SG_LIB_SYNTAX_ERROR;
+ }
+ optsp->timeout = n;
+ break;
+ case 'n':
+ optsp->no_sense = 1;
+ break;
+ case 'v':
+ ++optsp->do_verbose;
+ break;
+ case 'h':
+ case '?':
+ optsp->do_help = 1;
+ return 0;
+ case 'V':
+ optsp->do_version = 1;
+ return 0;
+ default:
+ return SG_LIB_SYNTAX_ERROR;
+ }
+ }
+
+ if (optsp->do_datain && optsp->do_dataout) {
+ fprintf(stderr, "Can't use '--request' and '--send' together\n");
+ return SG_LIB_SYNTAX_ERROR;
+ }
+
+ if (optind >= argc) {
+ fprintf(stderr, "No device specified\n");
+ return SG_LIB_SYNTAX_ERROR;
+ }
+ optsp->device_name = argv[optind];
+ ++optind;
+
+ while (optind < argc) {
+ char *opt = argv[optind++];
+ char *endptr;
+ int cmd = strtol(opt, &endptr, 16);
+ if (*opt == '\0' || *endptr != '\0' || cmd < 0x00 || cmd > 0xff) {
+ fprintf(stderr, "Invalid command byte '%s'\n", opt);
+ return SG_LIB_SYNTAX_ERROR;
+ }
+
+ if (optsp->cdb_length > MAX_SCSI_CDBSZ) {
+ fprintf(stderr, "CDB too long (max. %d bytes)\n", MAX_SCSI_CDBSZ);
+ return SG_LIB_SYNTAX_ERROR;
+ }
+ optsp->cdb[optsp->cdb_length] = cmd;
+ ++optsp->cdb_length;
+ }
+
+ if (optsp->cdb_length < MIN_SCSI_CDBSZ) {
+ fprintf(stderr, "CDB too short (min. %d bytes)\n", MIN_SCSI_CDBSZ);
+ return SG_LIB_SYNTAX_ERROR;
+ }
+
+ return 0;
+}
+
+static int skip(int fd, off_t offset)
+{
+ off_t remain;
+ char buffer[512];
+
+ if (lseek(fd, offset, SEEK_SET) >= 0) {
+ return 0;
+ }
+
+ // lseek failed; fall back to reading and discarding data
+ remain = offset;
+ while (remain > 0) {
+ ssize_t amount, done;
+ amount = (remain < (off_t)sizeof(buffer)) ? remain
+ : (off_t)sizeof(buffer);
+ done = read(fd, buffer, amount);
+ if (done < 0) {
+ perror("Error reading input data");
+ return SG_LIB_CAT_OTHER;
+ } else if (done == 0) {
+ fprintf(stderr, "EOF on input file/stream\n");
+ return SG_LIB_CAT_OTHER;
+ } else {
+ remain -= done;
+ }
+ }
+
+ return 0;
+}
+
+static unsigned char *fetch_dataout(struct opts_t *optsp)
+{
+ unsigned char *buf = NULL;
+ int fd, len;
+ int ok = 0;
+
+ if (optsp->dataout_file) {
+ fd = open(optsp->dataout_file, O_RDONLY);
+ if (fd < 0) {
+ perror(optsp->dataout_file);
+ goto bail;
+ }
+
+ } else {
+ fd = STDIN_FILENO;
+ }
+
+ if (optsp->dataout_offset > 0) {
+ if (skip(fd, optsp->dataout_offset) != 0) {
+ goto bail;
+ }
+ }
+
+ buf = (unsigned char *)malloc(optsp->dataout_len);
+ if (buf == NULL) {
+ perror("malloc");
+ goto bail;
+ }
+
+ len = read(fd, buf, optsp->dataout_len);
+ if (len < 0) {
+ perror("Failed to read input data");
+ goto bail;
+ } else if (len < optsp->dataout_len) {
+ fprintf(stderr, "EOF on input file/stream\n");
+ goto bail;
+ }
+
+ ok = 1;
+
+bail:
+ if (fd >= 0 && fd != STDIN_FILENO)
+ close(fd);
+ if (!ok) {
+ free(buf);
+ return NULL;
+ }
+ return buf;
+}
+
+static int write_dataout(const char *filename, unsigned char *buf, int len)
+{
+ int ret = SG_LIB_CAT_OTHER;
+ int fd;
+
+ if (filename != NULL) {
+ fd = creat(filename, 0666);
+ if (fd < 0) {
+ perror(filename);
+ goto bail;
+ }
+ } else {
+ fd = STDOUT_FILENO;
+ }
+
+ if (write(fd, buf, len) != len) {
+ perror(filename? filename : "stdout");
+ goto bail;
+ }
+
+ ret = 0;
+
+bail:
+ if (fd >= 0)
+ close(fd);
+ return ret;
+}
+
+int main(int argc, char *argv[])
+{
+ int ret = 0;
+ int res_cat;
+ int slen;
+ struct opts_t opts;
+ int sg_fd = -1;
+ struct sg_pt_base *ptvp = NULL;
+ unsigned char sense_buffer[32];
+ unsigned char *dxfer_buffer = NULL;
+
+ memset(&opts, 0, sizeof(opts));
+ opts.timeout = DEFAULT_TIMEOUT;
+ ret = process_cl(&opts, argc, argv);
+ if (ret != 0) {
+ usage();
+ goto done;
+ } else if (opts.do_help) {
+ usage();
+ goto done;
+ } else if (opts.do_version) {
+ version();
+ goto done;
+ }
+
+ sg_fd = scsi_pt_open_device(opts.device_name, 0 /* RDWR */,
+ opts.do_verbose);
+ if (sg_fd < 0) {
+ fprintf(stderr, "%s: %s\n", opts.device_name, safe_strerror(-sg_fd));
+ ret = SG_LIB_FILE_ERROR;
+ goto done;
+ }
+
+ ptvp = construct_scsi_pt_obj();
+ if (ptvp == NULL) {
+ fprintf(stderr, "out of memory\n");
+ goto done;
+ }
+ set_scsi_pt_cdb(ptvp, opts.cdb, opts.cdb_length);
+ set_scsi_pt_sense(ptvp, sense_buffer, sizeof(sense_buffer));
+
+ if (opts.do_dataout) {
+ dxfer_buffer = fetch_dataout(&opts);
+ if (dxfer_buffer == NULL) {
+ ret = SG_LIB_CAT_OTHER;
+ goto done;
+ }
+ set_scsi_pt_data_out(ptvp, dxfer_buffer, opts.dataout_len);
+ } else if (opts.do_datain) {
+ dxfer_buffer = (unsigned char *)malloc(opts.datain_len);
+ if (dxfer_buffer == NULL) {
+ perror("malloc");
+ ret = SG_LIB_CAT_OTHER;
+ goto done;
+ }
+ set_scsi_pt_data_in(ptvp, dxfer_buffer, opts.datain_len);
+ }
+
+ ret = do_scsi_pt(ptvp, sg_fd, opts.timeout, opts.do_verbose);
+ if (ret > 0) {
+ if (SCSI_PT_DO_BAD_PARAMS == ret) {
+ fprintf(stderr, "do_scsi_pt: bad pass through setup\n");
+ ret = SG_LIB_CAT_OTHER;
+ } else if (SCSI_PT_DO_TIMEOUT == ret) {
+ fprintf(stderr, "do_scsi_pt: timeout\n");
+ ret = SG_LIB_CAT_TIMEOUT;
+ } else
+ ret = SG_LIB_CAT_OTHER;
+ goto done;
+ } else if (ret < 0) {
+ fprintf(stderr, "do_scsi_pt: %s\n", safe_strerror(-sg_fd));
+ ret = SG_LIB_CAT_OTHER;
+ goto done;
+ }
+ slen = 0;
+ res_cat = get_scsi_pt_result_category(ptvp);
+ if (SCSI_PT_RESULT_GOOD == res_cat)
+ ret = 0;
+ else if (SCSI_PT_RESULT_SENSE == res_cat) {
+ slen = get_scsi_pt_sense_len(ptvp);
+ ret = sg_err_category_sense(sense_buffer, slen);
+ } else
+ ret = SG_LIB_CAT_OTHER;
+
+ fprintf(stderr, "SCSI Status: ");
+ sg_print_scsi_status(get_scsi_pt_status_response(ptvp));
+ fprintf(stderr, "\n\n");
+ if (!opts.no_sense) {
+ fprintf(stderr, "Sense Information:\n");
+ sg_print_sense(NULL, sense_buffer, slen, (opts.do_verbose > 0));
+ fprintf(stderr, "\n");
+ }
+
+ if (opts.do_datain) {
+ int data_len = opts.datain_len - get_scsi_pt_resid(ptvp);
+ if (data_len == 0) {
+ fprintf(stderr, "No data received\n");
+ } else {
+ if (opts.datain_file == NULL && !opts.datain_binary) {
+ fprintf(stderr, "Received %d bytes of data:\n", data_len);
+ dStrHex((const char *)dxfer_buffer, data_len, 0);
+ } else {
+ fprintf(stderr, "Writing %d bytes of data to %s\n", data_len,
+ opts.datain_file? opts.datain_file : "stdout");
+ ret = write_dataout(opts.datain_file, dxfer_buffer, data_len);
+ if (ret != 0)
+ goto done;
+ }
+ }
+ }
+
+done:
+ free(dxfer_buffer);
+ if (ptvp) destruct_scsi_pt_obj(ptvp);
+ if (sg_fd >= 0) scsi_pt_close_device(sg_fd);
+ return ret;
+}
+
diff --git a/sg_rbuf.c b/sg_rbuf.c
index f4a71499..bb1bffa3 100644
--- a/sg_rbuf.c
+++ b/sg_rbuf.c
@@ -47,7 +47,7 @@
#endif
-static char * version_str = "4.87 20070129";
+static char * version_str = "4.87 20070419";
static struct option long_options[] = {
{"buffer", 1, 0, 'b'},
@@ -187,7 +187,7 @@ static int process_cl_new(struct opts_t * optsp, int argc, char * argv[])
++optsp->do_version;
break;
default:
- fprintf(stderr, "unrecognised switch code %c [0x%x]\n", c, c);
+ fprintf(stderr, "unrecognised option code %c [0x%x]\n", c, c);
if (optsp->do_help)
break;
usage_for(optsp);
diff --git a/sg_read_buffer.c b/sg_read_buffer.c
index 84d39c81..1dc2105b 100644
--- a/sg_read_buffer.c
+++ b/sg_read_buffer.c
@@ -43,7 +43,7 @@
* This utility issues the SCSI READ BUFFER command to the given device.
*/
-static char * version_str = "1.03 20070121";
+static char * version_str = "1.03 20070419";
#define ME "sg_read_buffer: "
@@ -219,7 +219,7 @@ int main(int argc, char * argv[])
fprintf(stderr, ME "version: %s\n", version_str);
return 0;
default:
- fprintf(stderr, "unrecognised switch code 0x%x ??\n", c);
+ fprintf(stderr, "unrecognised option code 0x%x ??\n", c);
usage();
return SG_LIB_SYNTAX_ERROR;
}
diff --git a/sg_read_long.c b/sg_read_long.c
index 5a576a23..db2f4efc 100644
--- a/sg_read_long.c
+++ b/sg_read_long.c
@@ -26,7 +26,7 @@
the sector data and the ECC bytes.
*/
-static char * version_str = "1.14 20070129";
+static char * version_str = "1.14 20070419";
#define MAX_XFER_LEN 10000
@@ -192,7 +192,7 @@ int main(int argc, char * argv[])
}
break;
default:
- fprintf(stderr, "unrecognised switch code 0x%x ??\n", c);
+ fprintf(stderr, "unrecognised option code 0x%x ??\n", c);
usage();
return SG_LIB_SYNTAX_ERROR;
}
diff --git a/sg_readcap.c b/sg_readcap.c
index 76f08134..dcea4956 100644
--- a/sg_readcap.c
+++ b/sg_readcap.c
@@ -25,7 +25,7 @@
*/
-static char * version_str = "3.81 20070129";
+static char * version_str = "3.81 20070419";
#define ME "sg_readcap: "
@@ -187,7 +187,7 @@ static int process_cl_new(struct opts_t * optsp, int argc, char * argv[])
++optsp->do_version;
break;
default:
- fprintf(stderr, "unrecognised switch code %c [0x%x]\n", c, c);
+ fprintf(stderr, "unrecognised option code %c [0x%x]\n", c, c);
if (optsp->do_help)
break;
usage();
diff --git a/sg_reassign.c b/sg_reassign.c
index 3a8f99fd..5a0baaed 100644
--- a/sg_reassign.c
+++ b/sg_reassign.c
@@ -51,7 +51,7 @@
* vendor specific data is written.
*/
-static char * version_str = "1.11 20070127";
+static char * version_str = "1.11 20070419";
#define ME "sg_reassign: "
@@ -330,7 +330,7 @@ int main(int argc, char * argv[])
fprintf(stderr, ME "version: %s\n", version_str);
return 0;
default:
- fprintf(stderr, "unrecognised switch code 0x%x ??\n", c);
+ fprintf(stderr, "unrecognised option code 0x%x ??\n", c);
usage();
return SG_LIB_SYNTAX_ERROR;
}
diff --git a/sg_requests.c b/sg_requests.c
index 1959a96e..e090bab9 100644
--- a/sg_requests.c
+++ b/sg_requests.c
@@ -44,7 +44,7 @@
* This program issues the SCSI command REQUEST SENSE to the given SCSI device.
*/
-static char * version_str = "1.17 20070127";
+static char * version_str = "1.17 20070419";
#define REQUEST_SENSE_BUFF_LEN 252
@@ -158,7 +158,7 @@ int main(int argc, char * argv[])
fprintf(stderr, ME "version: %s\n", version_str);
return 0;
default:
- fprintf(stderr, "unrecognised switch code 0x%x ??\n", c);
+ fprintf(stderr, "unrecognised option code 0x%x ??\n", c);
usage();
return SG_LIB_SYNTAX_ERROR;
}
diff --git a/sg_rmsn.c b/sg_rmsn.c
index edb48eb3..431ff61a 100644
--- a/sg_rmsn.c
+++ b/sg_rmsn.c
@@ -45,7 +45,7 @@
* to the given SCSI device.
*/
-static char * version_str = "1.06 20070127";
+static char * version_str = "1.06 20070419";
#define ME "sg_rmsn: "
@@ -108,7 +108,7 @@ int main(int argc, char * argv[])
fprintf(stderr, ME "version: %s\n", version_str);
return 0;
default:
- fprintf(stderr, "unrecognised switch code 0x%x ??\n", c);
+ fprintf(stderr, "unrecognised option code 0x%x ??\n", c);
usage();
return SG_LIB_SYNTAX_ERROR;
}
diff --git a/sg_rtpg.c b/sg_rtpg.c
index 7798ea93..b30a1af2 100644
--- a/sg_rtpg.c
+++ b/sg_rtpg.c
@@ -45,16 +45,15 @@
* to the given SCSI device.
*/
-static char * version_str = "1.11 20070127";
+static char * version_str = "1.12 20070419";
#define REPORT_TGT_GRP_BUFF_LEN 1024
-#define ME "sg_rtpg: "
-
#define TPGS_STATE_OPTIMIZED 0x0
#define TPGS_STATE_NONOPTIMIZED 0x1
#define TPGS_STATE_STANDBY 0x2
#define TPGS_STATE_UNAVAILABLE 0x3
+#define TPGS_STATE_OFFLINE 0xe /* SPC-4 rev 9 */
#define TPGS_STATE_TRANSITIONING 0xf
#define STATUS_CODE_NOSTATUS 0x0
@@ -125,10 +124,12 @@ static void decode_status(const int st)
printf(" (no status available)");
break;
case STATUS_CODE_CHANGED_BY_SET:
- printf(" (status changed by SET TARGET PORT GROUPS)");
+ printf(" (target port asym. state changed by SET TARGET PORT "
+ "GROUPS command)");
break;
case STATUS_CODE_CHANGED_BY_IMPLICIT:
- printf(" (status changed by implicit TPGS behaviour)");
+ printf(" (target port asym. state changed by implicit lu "
+ "behaviour)");
break;
default:
printf(" (unknown status code)");
@@ -151,6 +152,9 @@ static void decode_tpgs_state(const int st)
case TPGS_STATE_UNAVAILABLE:
printf(" (unavailable)");
break;
+ case TPGS_STATE_OFFLINE:
+ printf(" (offline)");
+ break;
case TPGS_STATE_TRANSITIONING:
printf(" (transitioning between states)");
break;
@@ -199,10 +203,10 @@ int main(int argc, char * argv[])
++verbose;
break;
case 'V':
- fprintf(stderr, ME "version: %s\n", version_str);
+ fprintf(stderr, "Version: %s\n", version_str);
return 0;
default:
- fprintf(stderr, "unrecognised switch code 0x%x ??\n", c);
+ fprintf(stderr, "unrecognised option code 0x%x ??\n", c);
usage();
return SG_LIB_SYNTAX_ERROR;
}
@@ -229,7 +233,7 @@ int main(int argc, char * argv[])
}
sg_fd = sg_cmds_open_device(device_name, 0 /* rw */, verbose);
if (sg_fd < 0) {
- fprintf(stderr, ME "open error: %s: %s\n", device_name,
+ fprintf(stderr, "open error: %s: %s\n", device_name,
safe_strerror(-sg_fd));
return SG_LIB_FILE_ERROR;
}
@@ -281,6 +285,7 @@ int main(int argc, char * argv[])
printf("\n");
printf(" T_SUP : %d, ", !!(ucp[1] & 0x80));
+ printf("O_SUP : %d, ", !!(ucp[1] & 0x40));
printf("U_SUP : %d, ", !!(ucp[1] & 0x08));
printf("S_SUP : %d, ", !!(ucp[1] & 0x04));
printf("AN_SUP : %d, ", !!(ucp[1] & 0x02));
diff --git a/sg_sat_identify.8 b/sg_sat_identify.8
index 7e7ef973..572cf276 100644
--- a/sg_sat_identify.8
+++ b/sg_sat_identify.8
@@ -1,4 +1,4 @@
-.TH SG_SAT_IDENTIFY "8" "January 2007" "sg3_utils\-1.23" SG3_UTILS
+.TH SG_SAT_IDENTIFY "8" "May 2007" "sg3_utils\-1.24" SG3_UTILS
.SH NAME
sg_sat_identify \- sends a ATA IDENTIFY (PACKET) DEVICE command via a
SCSI to ATA Translation (SAT) layer
@@ -15,10 +15,10 @@ PACKET DEVICE command to \fIDEVICE\fR and outputs the response. The devices
that respond to these commands are ATA disks and ATAPI devices respectively.
Rather than send these commands directly to the device they are sent via a
SCSI transport which is assumed to contain a SCSI to ATA Translation (SAT)
-Layer (SATL). The SAT standard (latest draft: sat\-r09.pdf at www.t10.org)
-defines two SCSI "ATA PASS\-THROUGH" commands: one using a 16 byte "cdb"
-and the other with a 12 byte cdb. This utility defaults to using the 16
-byte cdb variant.
+Layer (SATL). The SAT standard (SAT ANSI INCITS 431-2007, prior draft:
+sat\-r09.pdf at www.t10.org) defines two SCSI "ATA PASS\-THROUGH" commands:
+one using a 16 byte "cdb" and the other with a 12 byte cdb. This utility
+defaults to using the 16 byte cdb variant.
.PP
The SATL may be in an operating system driver, in host bus adapter firmware
or in some external enclosure.
diff --git a/sg_sat_identify.c b/sg_sat_identify.c
index 99117e0b..4840c5e5 100644
--- a/sg_sat_identify.c
+++ b/sg_sat_identify.c
@@ -41,7 +41,8 @@
/* This program uses a ATA PASS-THROUGH SCSI command to package
an ATA IDENTIFY (PACKAGE) DEVICE command. See http://www.t10.org
- SAT draft at time of writing: sat-r09.pdf
+ for the most recent SAT: sat-r09.pdf . SAT is now a standard:
+ SAT ANSI INCITS 431-2007.
*/
@@ -50,6 +51,7 @@
#define SAT_ATA_PASS_THROUGH12 0xa1 /* clashes with MMC BLANK comand */
#define SAT_ATA_PASS_THROUGH12_LEN 12
#define SAT_ATA_RETURN_DESC 9 /* ATA Return (sense) Descriptor */
+#define ASCQ_ATA_PT_INFO_AVAILABLE 0x1d
#define ATA_IDENTIFY_DEVICE 0xec
#define ATA_IDENTIFY_PACKET_DEVICE 0xa1
@@ -59,17 +61,17 @@
#define EBUFF_SZ 256
-static char * version_str = "1.03 20070130";
+static char * version_str = "1.03 20070501";
static struct option long_options[] = {
- {"chk_cond", 0, 0, 'c'},
- {"help", 0, 0, 'h'},
- {"hex", 0, 0, 'H'},
- {"len", 1, 0, 'l'},
- {"packet", 0, 0, 'p'},
- {"raw", 0, 0, 'r'},
- {"verbose", 0, 0, 'v'},
- {"version", 0, 0, 'V'},
+ {"chk_cond", no_argument, 0, 'c'},
+ {"help", no_argument, 0, 'h'},
+ {"hex", no_argument, 0, 'H'},
+ {"len", required_argument, 0, 'l'},
+ {"packet", no_argument, 0, 'p'},
+ {"raw", no_argument, 0, 'r'},
+ {"verbose", no_argument, 0, 'v'},
+ {"version", no_argument, 0, 'V'},
{0, 0, 0, 0},
};
@@ -180,7 +182,8 @@ static int do_identify_dev(int sg_fd, int do_packet, int cdb_len,
return ret;
case SPC_SK_NO_SENSE:
case SPC_SK_RECOVERED_ERROR:
- if ((0x0 == ssh.asc) && (0x1d == ssh.ascq)) {
+ if ((0x0 == ssh.asc) &&
+ (ASCQ_ATA_PT_INFO_AVAILABLE == ssh.ascq)) {
if (SAT_ATA_RETURN_DESC != ata_return_desc[0]) {
if (verbose)
fprintf(stderr, "did not find ATA Return "
@@ -327,7 +330,7 @@ int main(int argc, char * argv[])
fprintf(stderr, "version: %s\n", version_str);
return 0;
default:
- fprintf(stderr, "unrecognised switch code 0x%x ??\n", c);
+ fprintf(stderr, "unrecognised option code 0x%x ??\n", c);
usage();
return SG_LIB_SYNTAX_ERROR;
}
diff --git a/sg_scan.c b/sg_scan.c
index 9676b9b8..f9af8173 100644
--- a/sg_scan.c
+++ b/sg_scan.c
@@ -49,7 +49,7 @@
F. Jansen - modification to extend beyond 26 sg devices.
*/
-static char * version_str = "4.09 20070125";
+static char * version_str = "4.09 20070419";
#define ME "sg_scan: "
@@ -1385,7 +1385,7 @@ int main(int argc, char * argv[])
fprintf(stderr, "version: %s\n", version_str);
return 0;
default:
- fprintf(stderr, "unrecognised switch code 0x%x ??\n", c);
+ fprintf(stderr, "unrecognised option code 0x%x ??\n", c);
usage();
return SG_LIB_SYNTAX_ERROR;
}
diff --git a/sg_senddiag.8 b/sg_senddiag.8
index c04767ab..52f3446d 100644
--- a/sg_senddiag.8
+++ b/sg_senddiag.8
@@ -1,4 +1,4 @@
-.TH SG_SENDDIAG "8" "January 2007" "sg3_utils\-1.23" SG3_UTILS
+.TH SG_SENDDIAG "8" "February 2007" "sg3_utils\-1.24" SG3_UTILS
.SH NAME
sg_senddiag \- performs a SCSI SEND DIAGNOSTIC command
.SH SYNOPSIS
@@ -81,11 +81,20 @@ likely the \fI\-\-pf\fR option should also be given.
.TP
\fB\-s\fR, \fB\-\-selftest\fR=\fIST\fR
where \fIST\fR is the self-test code. The default value is 0 which is
-inactive. A value of 1 selects a background short self-test; 2 selects a
-background extended self-test; 5 selects a foreground short self-test; 6
-selects a foreground extended test. A value of 4 will abort a (background)
-self-test that is in progress. This option is mutually exclusive with
-default self-test (i.e. \fI\-\-test\fR).
+inactive. Some other values:
+.br
+ \fB1\fR : background short self-test
+.br
+ \fB2\fR : background extended self-test
+.br
+ \fB4\fR : aborts a (background) self-test that is in progress
+.br
+ \fB5\fR : foreground short self-test
+.br
+ \fB6\fR : foreground extended self-test
+.br
+This option is mutually exclusive with default self-test (i.e.
+can't have (\fIST\fR > 0) and \fI\-\-test\fR).
.TP
\fB\-t\fR, \fB\-\-test\fR
sets the _default_ Self Test (SelfTest) bit. By default this is clear (0).
@@ -112,7 +121,7 @@ codes' maximum duration is vendor specific (e.g. a little over 10 minutes
with the author's disks). The foreground self-test codes wait until they
are completed while the background self-test codes return immediately. The
results of both foreground and background self-test codes are placed in
-the 'self-test results' log page (see sg_logs). The SCSI command timeout
+the 'self-test results' log page (see sg_logs(8)). The SCSI command timeout
for this utility is set to 60 minutes to allow for slow foreground extended
self-tests.
.PP
@@ -132,7 +141,7 @@ turn on the CJTPAT (jitter pattern) on some SAS disks (one script for each
phy). One possible invocation
is: 'sg_senddiag \-\-pf \-\-raw=\- /dev/sg2 < .../sdiag_sas_p1_cjtpat.txt'
.PP
-Arbitrary diagnostic pages can be read (in hex) with the sg_ses
+Arbitrary diagnostic pages can be read (in hex) with the sg_ses(8)
utility (not only those defined in SES\-2).
.PP
If the utility is used with no options (e.g. "sg_senddiag /dev/sg1")
@@ -146,7 +155,7 @@ generic (sg) device. In the 2.6 series block devices (e.g. SCSI disks and
DVD drives) 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 the
+To access SCSI enclosures see the sg_ses(8) utility. sg_ses uses the
SCSI SEND DIAGNOSTIC and RECEIVE DIAGNOSTIC RESULTS commands as outlined
in the SES\-2 (draft) standard.
.SH EXIT STATUS
@@ -240,4 +249,4 @@ Copyright \(co 2003\-2007 Douglas Gilbert
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_ses(sg3_utils), smartmontools(see net), sg_logs(sg3_utils)
+.B sg_ses(8), sg_logs(8), smartmontools(see net)
diff --git a/sg_senddiag.c b/sg_senddiag.c
index 1b354219..3c843f21 100644
--- a/sg_senddiag.c
+++ b/sg_senddiag.c
@@ -21,7 +21,7 @@
the SCSI RECEIVE DIAGNOSTIC command to list supported diagnostic pages.
*/
-static char * version_str = "0.34 20070127";
+static char * version_str = "0.34 20070419";
#define ME "sg_senddiag: "
@@ -193,7 +193,7 @@ static int process_cl_new(struct opts_t * optsp, int argc, char * argv[])
++optsp->do_version;
break;
default:
- fprintf(stderr, "unrecognised switch code %c [0x%x]\n", c, c);
+ fprintf(stderr, "unrecognised option code %c [0x%x]\n", c, c);
if (optsp->do_help)
break;
usage();
diff --git a/sg_ses.8 b/sg_ses.8
index cff80d70..6a9a9af0 100644
--- a/sg_ses.8
+++ b/sg_ses.8
@@ -1,4 +1,4 @@
-.TH SG_SES "8" "January 2007" "sg3_utils\-1.23" SG3_UTILS
+.TH SG_SES "8" "March 2007" "sg3_utils\-1.24" SG3_UTILS
.SH NAME
sg_ses \- send controls and fetch status from a SCSI Enclosure
Services (SES) device
@@ -61,7 +61,7 @@ output the response in hexadecimal.
\fB\-i\fR, \fB\-\-inner\-hex\fR
the outer levels of a status diagnostic page are decoded and printed out
but the innermost level (e.g. the element status descriptor) is output in
-hex.
+hex. Implemented for the more complex diagnostic pages.
.TP
\fB\-l\fR, \fB\-\-list\fR
list all known diagnostic page names and SES elements. \fIDEVICE\fR
diff --git a/sg_ses.c b/sg_ses.c
index 89db718c..f88b25c2 100644
--- a/sg_ses.c
+++ b/sg_ses.c
@@ -43,15 +43,39 @@
* commands tailored for SES (enclosure) devices.
*/
-static char * version_str = "1.32 20070128"; /* ses2r15 */
+static char * version_str = "1.34 20070419"; /* ses2r16 */
#define MX_ALLOC_LEN 4096
-#define MX_ELEM_HDR 512
+#define MX_ELEM_HDR 1024
#define TEMPERATURE_OFFSET 20 /* 8 bits represents -19 C to +235 C */
/* value of 0 (would imply -20 C) reserved */
-#define ME "sg_ses: "
+#define DEVICE_EL 0x1
+#define POWER_SUPPLY_EL 0x2
+#define COOLING_EL 0x3
+#define TEMPERATURE_EL 0x4
+#define DOOR_LOCK_EL 0x5
+#define AUD_ALARM_EL 0x6
+#define ENC_SC_ELECTR_EL 0x7
+#define SCC_CELECTR_EL 0x8
+#define NV_CACHE_EL 0x9
+#define INV_OP_REASON_EL 0xa
+#define UI_POWER_SUPPLY_EL 0xb
+#define DISPLAY_EL 0xc
+#define KEY_PAD_EL 0xd
+#define ENCLOSURE_EL 0xe
+#define SCSI_PORT_TRAN_EL 0xf
+#define LANGUAGE_EL 0x10
+#define COMM_PORT_EL 0x11
+#define VOLT_SENSOR_EL 0x12
+#define CURR_SENSOR_EL 0x13
+#define SCSI_TPORT_EL 0x14
+#define SCSI_IPORT_EL 0x15
+#define SIMPLE_SUBENC_EL 0x16
+#define ARRAY_DEV_EL 0x17
+#define SAS_EXPANDER_EL 0x18
+#define SAS_CONNECTOR_EL 0x19
static struct option long_options[] = {
@@ -200,53 +224,69 @@ static const char * find_in_page_code_desc(int page_num)
}
struct element_desc {
- int type_code;
+ int elem_code;
const char * desc;
};
static struct element_desc element_desc_arr[] = {
{0x0, "Unspecified"},
- {0x1, "Device"},
- {0x2, "Power supply"},
- {0x3, "Cooling"},
- {0x4, "Temperature sense"},
- {0x5, "Door lock"},
- {0x6, "Audible alarm"},
- {0x7, "Enclosure service controller electronics"},
- {0x8, "SCC controller electronics"},
- {0x9, "Nonvolatile cache"},
- {0xa, "Invalid operation reason"},
- {0xb, "Uninterruptible power supply"},
- {0xc, "Display"},
- {0xd, "Key pad entry"},
- {0xe, "Enclosure"},
- {0xf, "SCSI port/transceiver"},
- {0x10, "Language"},
- {0x11, "Communication port"},
- {0x12, "Voltage sensor"},
- {0x13, "Current sensor"},
- {0x14, "SCSI target port"},
- {0x15, "SCSI initiator port"},
- {0x16, "Simple subenclosure"},
- {0x17, "Array device"},
- {0x18, "SAS expander"},
- {0x19, "SAS connector"},
+ {DEVICE_EL, "Device"},
+ {POWER_SUPPLY_EL, "Power supply"},
+ {COOLING_EL, "Cooling"},
+ {TEMPERATURE_EL, "Temperature sense"},
+ {DOOR_LOCK_EL, "Door lock"},
+ {AUD_ALARM_EL, "Audible alarm"},
+ {ENC_SC_ELECTR_EL, "Enclosure services controller electronics"},
+ {SCC_CELECTR_EL, "SCC controller electronics"},
+ {NV_CACHE_EL, "Nonvolatile cache"},
+ {INV_OP_REASON_EL, "Invalid operation reason"},
+ {UI_POWER_SUPPLY_EL, "Uninterruptible power supply"},
+ {DISPLAY_EL, "Display"},
+ {KEY_PAD_EL, "Key pad entry"},
+ {ENCLOSURE_EL, "Enclosure"},
+ {SCSI_PORT_TRAN_EL, "SCSI port/transceiver"},
+ {LANGUAGE_EL, "Language"},
+ {COMM_PORT_EL, "Communication port"},
+ {VOLT_SENSOR_EL, "Voltage sensor"},
+ {CURR_SENSOR_EL, "Current sensor"},
+ {SCSI_TPORT_EL, "SCSI target port"},
+ {SCSI_IPORT_EL, "SCSI initiator port"},
+ {SIMPLE_SUBENC_EL, "Simple subenclosure"},
+ {ARRAY_DEV_EL, "Array device"},
+ {SAS_EXPANDER_EL, "SAS expander"},
+ {SAS_CONNECTOR_EL, "SAS connector"},
};
-static const char * find_element_desc(int type_code)
+static const char * find_element_desc(int elem_code)
{
int k;
int num = sizeof(element_desc_arr) / sizeof(element_desc_arr[0]);
const struct element_desc * edp = &element_desc_arr[0];
for (k = 0; k < num; ++k, ++edp) {
- if (type_code == edp->type_code)
+ if (elem_code == edp->elem_code)
return edp->desc;
- else if (type_code < edp->type_code)
+ else if (elem_code < edp->elem_code)
return NULL;
}
return NULL;
}
+#if 0
+static const char * get_element_desc(int elem_code, int b_len, char * b)
+{
+ const char * elem_desc;
+
+ if (b_len > 0)
+ b[b_len - 1] = '\0';
+ elem_desc = find_element_desc(elem_code);
+ if (elem_desc)
+ snprintf(b, b_len - 1, "%s", elem_desc);
+ else
+ snprintf(b, b_len - 1, "unknown element code=0x%x", elem_code);
+ return b;
+}
+#endif
+
struct element_hdr {
unsigned char etype;
unsigned char num_elements;
@@ -330,7 +370,7 @@ static void ses_configuration_sdg(const unsigned char * resp, int resp_len)
}
return;
truncated:
- fprintf(stderr, " <<<response too short>>>\n");
+ fprintf(stderr, " <<<ses_configuration_sdg: response too short>>>\n");
return;
}
@@ -446,6 +486,9 @@ static char * find_sas_connector_type(int conn_type, char * buff,
case 0x23:
snprintf(buff, buff_len, "SATA device plug [max 1 phy]");
break;
+ case 0x2f:
+ snprintf(buff, buff_len, "SAS virtual connector [max 1 phy]");
+ break;
case 0x3f:
snprintf(buff, buff_len, "Vendor specific internal connector");
break;
@@ -474,7 +517,7 @@ static char * find_sas_connector_type(int conn_type, char * buff,
}
static const char * element_status_desc[] = {
- "Unsupported", "OK", "Critical", "Non-critical",
+ "Unsupported", "OK", "Critical", "Noncritical",
"Unrecoverable", "Not installed", "Unknown", "Not available",
"reserved [8]", "reserved [9]", "reserved [10]", "reserved [11]",
"reserved [12]", "reserved [13]", "reserved [14]", "reserved [15]",
@@ -510,7 +553,7 @@ static void print_element_status(const char * pad,
printf("%sstatus in hex: %02x %02x %02x %02x\n",
pad, statp[0], statp[1], statp[2], statp[3]);
break;
- case 1: /* device */
+ case DEVICE_EL:
printf("%sSlot address: %d\n", pad, statp[1]);
if ((! filter) || (0xe0 & statp[2]))
printf("%sApp client bypassed A=%d, Do not remove=%d, Enc "
@@ -532,7 +575,7 @@ static void print_element_status(const char * pad,
if ((! filter) || (0x1 & statp[3]))
printf("%sDevice bypassed B=%d\n", pad, !!(statp[3] & 0x1));
break;
- case 2: /* power supply */
+ case POWER_SUPPLY_EL:
if ((! filter) || ((0x80 & statp[1]) || (0xe & statp[2])))
printf("%sIdent=%d, DC overvoltage=%d, DC undervoltage=%d, DC "
"overcurrent=%d\n", pad, !!(statp[1] & 0x80),
@@ -546,8 +589,8 @@ static void print_element_status(const char * pad,
pad, !!(statp[3] & 0x4), !!(statp[3] & 0x2),
!!(statp[3] & 0x1));
break;
- case 3: /* cooling */
- if ((! filter) || ((0x80 & statp[1]) || (0x70 & statp[3])))
+ case COOLING_EL:
+ if ((! filter) || ((0xc0 & statp[1]) || (0x70 & statp[3])))
printf("%sIdent=%d, Fail=%d, Requested on=%d, Off=%d\n", pad,
!!(statp[1] & 0x80), !!(statp[3] & 0x40),
!!(statp[3] & 0x20), !!(statp[3] & 0x10));
@@ -555,52 +598,58 @@ static void print_element_status(const char * pad,
(((0x7 & statp[1]) << 8) + statp[2]) * 10,
actual_speed_desc[7 & statp[3]]);
break;
- case 4: /* temperature sensor */
- if ((! filter) || ((0x80 & statp[1]) || (0xf & statp[3])))
- printf("%sIdent=%d, OT Failure=%d, OT warning=%d, UT failure=%d, "
- "UT warning=%d\n", pad, !!(statp[1] & 0x80),
- !!(statp[3] & 0x8), !!(statp[3] & 0x4), !!(statp[3] & 0x2),
- !!(statp[3] & 0x1));
+ case TEMPERATURE_EL: /* temperature sensor */
+ if ((! filter) || ((0xc0 & statp[1]) || (0xf & statp[3]))) {
+ printf("%sIdent=%d, Fail=%d, OT failure=%d, OT warning=%d, "
+ "UT failure=%d\n", pad, !!(statp[1] & 0x80),
+ !!(statp[1] & 0x40), !!(statp[3] & 0x8),
+ !!(statp[3] & 0x4), !!(statp[3] & 0x2));
+ printf("%sUT warning=%d\n", pad, !!(statp[3] & 0x1));
+ }
if (statp[2])
printf("%sTemperature=%d C\n", pad,
(int)statp[2] - TEMPERATURE_OFFSET);
else
printf("%sTemperature: <reserved>\n", pad);
break;
- case 5: /* door lock */
- if ((! filter) || ((0x80 & statp[1]) || (0x1 & statp[3])))
- printf("%sIdent=%d, Unlock=%d\n", pad, !!(statp[1] & 0x80),
+ case DOOR_LOCK_EL:
+ if ((! filter) || ((0xc0 & statp[1]) || (0x1 & statp[3])))
+ printf("%sIdent=%d, Fail=%d, Unlock=%d\n", pad,
+ !!(statp[1] & 0x80), !!(statp[1] & 0x40),
!!(statp[3] & 0x1));
break;
- case 6: /* audible alarm */
- if ((! filter) || ((0x80 & statp[1]) || (0xd0 & statp[3])))
- printf("%sIdent=%d, Request mute=%d, Mute=%d, Remind=%d\n", pad,
- !!(statp[1] & 0x80), !!(statp[3] & 0x80),
+ case AUD_ALARM_EL: /* audible alarm */
+ if ((! filter) || ((0xc0 & statp[1]) || (0xd0 & statp[3])))
+ printf("%sIdent=%d, Fail=%d, Request mute=%d, Mute=%d, "
+ "Remind=%d\n", pad, !!(statp[1] & 0x80),
+ !!(statp[1] & 0x40), !!(statp[3] & 0x80),
!!(statp[3] & 0x40), !!(statp[3] & 0x10));
if ((! filter) || (0xf & statp[3]))
printf("%sTone indicator: Info=%d, Non-crit=%d, Crit=%d, "
"Unrecov=%d\n", pad, !!(statp[3] & 0x8), !!(statp[3] & 0x4),
!!(statp[3] & 0x2), !!(statp[3] & 0x1));
break;
- case 7: /* enclosure services controller electronics element */
- if ((! filter) || ((0x80 & statp[1]) || (0x1 & statp[2])))
- printf("%sIdent=%d, Report=%d\n", pad, !!(statp[1] & 0x80),
+ case ENC_SC_ELECTR_EL: /* enclosure services controller electronics */
+ if ((! filter) || ((0xc0 & statp[1]) || (0x1 & statp[2])))
+ printf("%sIdent=%d, Fail=%d, Report=%d\n", pad,
+ !!(statp[1] & 0x80), !!(statp[1] & 0x40),
!!(statp[2] & 0x1));
break;
- case 8: /* SCC controller electronics element */
- if ((! filter) || ((0x80 & statp[1]) || (0x1 & statp[2])))
- printf("%sIdent=%d, Report=%d\n", pad, !!(statp[1] & 0x80),
+ case SCC_CELECTR_EL: /* SCC controller electronics */
+ if ((! filter) || ((0xc0 & statp[1]) || (0x1 & statp[2])))
+ printf("%sIdent=%d, Fail=%d, Report=%d\n", pad,
+ !!(statp[1] & 0x80), !!(statp[1] & 0x40),
!!(statp[2] & 0x1));
break;
- case 9: /* Non volatile cache element */
+ case NV_CACHE_EL: /* Non volatile cache */
res = (statp[2] << 8) + statp[3];
- printf("%sIdent=%d, Size multiplier=%d, Non volatile cache "
- "size=0x%x\n", pad, !!(statp[1] & 0x80),
+ printf("%sIdent=%d, Fail=%d, Size multiplier=%d, Non volatile cache "
+ "size=0x%x\n", pad, !!(statp[1] & 0x80), !!(statp[1] & 0x40),
(statp[1] & 0x3), res);
printf("%sHence non volatile cache size: %d %s\n", pad, res,
nv_cache_unit[statp[1] & 0x3]);
break;
- case 0xa: /* Invalid operation reason element */
+ case INV_OP_REASON_EL: /* Invalid operation reason */
res = ((statp[1] >> 6) & 3);
printf("%sInvop type=%d %s\n", pad, res, invop_type_desc[res]);
switch (res) {
@@ -620,7 +669,7 @@ static void print_element_status(const char * pad,
break;
}
break;
- case 0xb: /* Uninterruptible power supply */
+ case UI_POWER_SUPPLY_EL: /* Uninterruptible power supply */
if (0 == statp[1])
printf("%sBattery status: discharged or unknown\n", pad);
else if (255 == statp[1])
@@ -632,24 +681,28 @@ static void print_element_status(const char * pad,
"%d\n", pad, !!(statp[2] & 0x80), !!(statp[2] & 0x40),
!!(statp[2] & 0x20), !!(statp[2] & 0x10),
!!(statp[2] & 0x8));
- if ((! filter) || ((0x7 & statp[2]) || (0x83 & statp[3])))
- printf("%sUPS fail=%d, Warn=%d, Intf fail=%d, Ident=%d, Batt fail"
- "=%d, BPF=%d\n", pad, !!(statp[2] & 0x4), !!(statp[2] & 0x2),
- !!(statp[2] & 0x1), !!(statp[3] & 0x80), !!(statp[3] & 0x2),
- !!(statp[3] & 0x1));
+ if ((! filter) || ((0x7 & statp[2]) || (0xc3 & statp[3]))) {
+ printf("%sUPS fail=%d, Warn=%d, Intf fail=%d, Ident=%d, Fail=%d, "
+ "Batt fail=%d\n", pad, !!(statp[2] & 0x4),
+ !!(statp[2] & 0x2), !!(statp[2] & 0x1),
+ !!(statp[3] & 0x80), !!(statp[3] & 0x40),
+ !!(statp[3] & 0x2));
+ printf("%sBPF=%d\n", pad, !!(statp[3] & 0x1));
+ }
break;
- case 0xc: /* Display (ses2r15) */
- if ((! filter) || (0x80 & statp[1]))
- printf("%sIdent=%d, Display mode status=%d, Display "
- "character status=0x%x\n", pad,
- !!(statp[1] & 0x80), (statp[1] & 0x3),
+ case DISPLAY_EL: /* Display (ses2r15) */
+ if ((! filter) || (0xc0 & statp[1]))
+ printf("%sIdent=%d, Fail=%d, Display mode status=%d, Display "
+ "character status=0x%x\n", pad, !!(statp[1] & 0x80),
+ !!(statp[1] & 0x40), (statp[1] & 0x3),
((statp[2] << 8) & statp[3]));
break;
- case 0xd: /* Key pad entry */
- if ((! filter) || (0x80 & statp[1]))
- printf("%sIdent=%d\n", pad, !!(statp[1] & 0x80));
+ case KEY_PAD_EL: /* Key pad entry */
+ if ((! filter) || (0xc0 & statp[1]))
+ printf("%sIdent=%d, Fail=%d\n", pad, !!(statp[1] & 0x80),
+ !!(statp[1] & 0x40));
break;
- case 0xe: /* Enclosure */
+ case ENCLOSURE_EL:
if ((! filter) || ((0x80 & statp[1]) || (0x3 & statp[2])))
printf("%sIdent=%d, Failure indication=%d, Warning indication="
"%d\n", pad, !!(statp[1] & 0x80), !!(statp[2] & 0x2),
@@ -658,29 +711,33 @@ static void print_element_status(const char * pad,
printf("%sFailure requested=%d, Warning requested=%d\n",
pad, !!(statp[3] & 0x2), !!(statp[3] & 0x1));
break;
- case 0xf: /* SCSI port/transceiver */
- if ((! filter) || ((0x80 & statp[1]) || (0x1 & statp[2]) ||
+ case SCSI_PORT_TRAN_EL: /* SCSI port/transceiver */
+ if ((! filter) || ((0xc0 & statp[1]) || (0x1 & statp[2]) ||
(0x13 & statp[3])))
- printf("%sIdent=%d, Report=%d, Disabled=%d, Loss of link=%d, Xmit"
- " fail=%d\n", pad, !!(statp[1] & 0x80), !!(statp[2] & 0x1),
+ printf("%sIdent=%d, Fail=%d, Report=%d, Disabled=%d, Loss of "
+ "link=%d, Xmit fail=%d\n", pad, !!(statp[1] & 0x80),
+ !!(statp[1] & 0x40), !!(statp[2] & 0x1),
!!(statp[3] & 0x10), !!(statp[3] & 0x2),
!!(statp[3] & 0x1));
break;
- case 0x10: /* Language */
+ case LANGUAGE_EL:
printf("%sIdent=%d, Language code: %.2s\n", pad, !!(statp[1] & 0x80),
statp + 2);
break;
- case 0x11: /* Communication port */
- if ((! filter) || ((0x80 & statp[1]) || (0x1 & statp[3])))
- printf("%sIdent=%d, Disabled=%d\n", pad, !!(statp[1] & 0x80),
+ case COMM_PORT_EL: /* Communication port */
+ if ((! filter) || ((0xc0 & statp[1]) || (0x1 & statp[3])))
+ printf("%sIdent=%d, Fail=%d, Disabled=%d\n", pad,
+ !!(statp[1] & 0x80), !!(statp[1] & 0x40),
!!(statp[3] & 0x1));
break;
- case 0x12: /* Voltage sensor */
- if ((! filter) || (0x8f & statp[1]))
- printf("%sIdent=%d, Warn Over=%d, Warn Under=%d, Crit Over=%d, "
- "Crit Under=%d\n", pad, !!(statp[1] & 0x80),
- !!(statp[1] & 0x8), !!(statp[1] & 0x4),!!(statp[1] & 0x2),
- !!(statp[1] & 0x1));
+ case VOLT_SENSOR_EL: /* Voltage sensor */
+ if ((! filter) || (0xcf & statp[1])) {
+ printf("%sIdent=%d, Fail=%d, Warn Over=%d, Warn Under=%d, "
+ "Crit Over=%d\n", pad, !!(statp[1] & 0x80),
+ !!(statp[1] & 0x40), !!(statp[1] & 0x8),
+ !!(statp[1] & 0x4), !!(statp[1] & 0x2));
+ printf("Crit Under=%d\n", !!(statp[1] & 0x1));
+ }
#ifdef SG3_UTILS_MINGW
printf("%sVoltage: %g volts\n", pad,
((int)(short)((statp[2] << 8) + statp[3]) / 100.0));
@@ -689,11 +746,11 @@ static void print_element_status(const char * pad,
((int)(short)((statp[2] << 8) + statp[3]) / 100.0));
#endif
break;
- case 0x13: /* Current sensor */
- if ((! filter) || (0x8a & statp[1]))
- printf("%sIdent=%d, Warn Over=%d, Crit Over=%d\n", pad,
- !!(statp[1] & 0x80), !!(statp[1] & 0x8),
- !!(statp[1] & 0x2));
+ case CURR_SENSOR_EL: /* Current sensor */
+ if ((! filter) || (0xca & statp[1]))
+ printf("%sIdent=%d, Fail=%d, Warn Over=%d, Crit Over=%d\n",
+ pad, !!(statp[1] & 0x80), !!(statp[1] & 0x40),
+ !!(statp[1] & 0x8), !!(statp[1] & 0x2));
#ifdef SG3_UTILS_MINGW
printf("%sCurrent: %g amps\n", pad,
((int)(short)((statp[2] << 8) + statp[3]) / 100.0));
@@ -702,25 +759,25 @@ static void print_element_status(const char * pad,
((int)(short)((statp[2] << 8) + statp[3]) / 100.0));
#endif
break;
- case 0x14: /* SCSI target port */
- if ((! filter) || ((0x80 & statp[1]) || (0x1 & statp[2]) ||
+ case SCSI_TPORT_EL: /* SCSI target port */
+ if ((! filter) || ((0xc0 & statp[1]) || (0x1 & statp[2]) ||
(0x1 & statp[3])))
- printf("%sIdent=%d, Report=%d, Enabled=%d\n", pad,
- !!(statp[1] & 0x80), !!(statp[2] & 0x1),
- !!(statp[3] & 0x1));
+ printf("%sIdent=%d, Fail=%d, Report=%d, Enabled=%d\n", pad,
+ !!(statp[1] & 0x80), !!(statp[1] & 0x40),
+ !!(statp[2] & 0x1), !!(statp[3] & 0x1));
break;
- case 0x15: /* SCSI initiator port */
- if ((! filter) || ((0x80 & statp[1]) || (0x1 & statp[2]) ||
+ case SCSI_IPORT_EL: /* SCSI initiator port */
+ if ((! filter) || ((0xc0 & statp[1]) || (0x1 & statp[2]) ||
(0x1 & statp[3])))
- printf("%sIdent=%d, Report=%d, Enabled=%d\n", pad,
- !!(statp[1] & 0x80), !!(statp[2] & 0x1),
- !!(statp[3] & 0x1));
+ printf("%sIdent=%d, Fail=%d, Report=%d, Enabled=%d\n", pad,
+ !!(statp[1] & 0x80), !!(statp[1] & 0x40),
+ !!(statp[2] & 0x1), !!(statp[3] & 0x1));
break;
- case 0x16: /* Simple subenclosure */
- printf("%sIdent=%d, Short enclosure status: 0x%x\n", pad,
- !!(statp[1] & 0x80), statp[3]);
+ case SIMPLE_SUBENC_EL: /* Simple subenclosure */
+ printf("%sIdent=%d, Fail=%d, Short enclosure status: 0x%x\n", pad,
+ !!(statp[1] & 0x80), !!(statp[1] & 0x40), statp[3]);
break;
- case 0x17: /* Array device */
+ case ARRAY_DEV_EL: /* Array device */
if ((! filter) || (0xf0 & statp[1]))
printf("%sOK=%d, Reserved device=%d, Hot spare=%d, Cons check="
"%d\n", pad, !!(statp[1] & 0x80), !!(statp[1] & 0x40),
@@ -750,14 +807,16 @@ static void print_element_status(const char * pad,
pad, !!(statp[3] & 0x8), !!(statp[3] & 0x4),
!!(statp[3] & 0x2), !!(statp[3] & 0x1));
break;
- case 0x18: /* SAS expander */
- printf("%sIdent=%d\n", pad, !!(statp[1] & 0x80));
+ case SAS_EXPANDER_EL:
+ printf("%sIdent=%d, Fail=%d\n", pad, !!(statp[1] & 0x80),
+ !!(statp[1] & 0x40));
break;
- case 0x19: /* SAS connector */
+ case SAS_CONNECTOR_EL:
printf("%sIdent=%d, %s, Connector physical "
"link=0x%x\n", pad, !!(statp[1] & 0x80),
find_sas_connector_type((statp[1] & 0x7f), buff, sizeof(buff)),
statp[2]);
+ printf("%sFail=%d\n", pad, !!(statp[3] & 0x40));
break;
default:
printf("%sUnknown element type, status in hex: %02x %02x %02x %02x\n",
@@ -824,7 +883,7 @@ static void ses_enclosure_sdg(const struct element_hdr * ehp, int num_telems,
}
return;
truncated:
- fprintf(stderr, " <<<response too short>>>\n");
+ fprintf(stderr, " <<<enc: response too short>>>\n");
return;
}
@@ -958,7 +1017,7 @@ static void ses_threshold_sdg(const struct element_hdr * ehp, int num_telems,
}
return;
truncated:
- fprintf(stderr, " <<<response too short>>>\n");
+ fprintf(stderr, " <<<thresh: response too short>>>\n");
return;
}
@@ -1013,7 +1072,7 @@ static void ses_element_desc_sdg(const struct element_hdr * ehp,
}
return;
truncated:
- fprintf(stderr, " <<<response too short>>>\n");
+ fprintf(stderr, " <<<element: response too short>>>\n");
return;
}
@@ -1049,16 +1108,21 @@ static void ses_additional_elem_each(const unsigned char * ucp, int len,
switch (0xf & ucp[0]) {
case 0: /* FCP */
ports = ucp[2 + eip_offset];
- printf(" [%d] Transport protocol: FCP, number of ports: %d\n",
- elem_num + 1, ports);
+ printf(" Transport protocol: FCP\n");
+#if 0
+ printf("%s element\n", get_element_desc(elem_type, sizeof(b), b));
+#endif
+ printf(" number of ports: %d\n", ports);
printf(" node_name: ");
for (m = 0; m < 8; ++m)
printf("%02x", ucp[6 + eip_offset + m]);
+ if (eip_offset)
+ printf(", bay number: %d", ucp[5 + eip_offset]);
printf("\n");
per_ucp = ucp + 14 + eip_offset;
for (j = 0; j < ports; ++j, per_ucp += 16) {
- printf(" [%d] port loop position: %d, port requested hard "
- "address: %d\n", j + 1, per_ucp[0], per_ucp[4]);
+ printf(" port index: %d, port loop position: %d, port "
+ "requested hard address: %d\n", j, per_ucp[0], per_ucp[4]);
printf(" n_port identifier: %02x%02x%02x\n",
per_ucp[5], per_ucp[6], per_ucp[7]);
printf(" n_port name: ");
@@ -1069,26 +1133,32 @@ static void ses_additional_elem_each(const unsigned char * ucp, int len,
break;
case 6: /* SAS */
desc_type = (ucp[3 + eip_offset] >> 6) & 0x3;
- printf(" [%d] Transport protocol: SAS, ", elem_num + 1);
+ printf(" Transport protocol: SAS\n");
+#if 0
+ printf("%s element\n", get_element_desc(elem_type, sizeof(b), b));
+#endif
if (0 == desc_type) {
phys = ucp[2 + eip_offset];
- printf("SAS and SATA device descriptor type [%d]\n", desc_type);
- printf(" number of phys: %d, not all phys: %d\n", phys,
+ printf(" number of phys: %d, not all phys: %d", phys,
ucp[3 + eip_offset] & 1);
+ if (eip_offset)
+ printf(", bay number: %d", ucp[5 + eip_offset]);
+ printf("\n");
per_ucp = ucp + 4 + eip_offset + eip_offset;
for (j = 0; j < phys; ++j, per_ucp += 28) {
- printf(" [%d] device type: %s\n", phys + 1,
+ printf(" phy index: %d\n", j);
+ printf(" device type: %s\n",
sas_device_type[(0x70 & per_ucp[0]) >> 4]);
- printf(" initiator port for: %s %s %s\n",
- ((per_ucp[2] & 8) ? "SSP" : ""),
- ((per_ucp[2] & 4) ? "STP" : ""),
- ((per_ucp[2] & 2) ? "SMP" : ""));
- printf(" target port for: %s %s %s %s %s\n",
- ((per_ucp[3] & 0x80) ? "SATA_port_selector" : ""),
- ((per_ucp[3] & 8) ? "SSP" : ""),
- ((per_ucp[3] & 4) ? "STP" : ""),
- ((per_ucp[3] & 2) ? "SMP" : ""),
- ((per_ucp[3] & 1) ? "SATA_device" : ""));
+ printf(" initiator port for:%s%s%s\n",
+ ((per_ucp[2] & 8) ? " SSP" : ""),
+ ((per_ucp[2] & 4) ? " STP" : ""),
+ ((per_ucp[2] & 2) ? " SMP" : ""));
+ printf(" target port for:%s%s%s%s%s\n",
+ ((per_ucp[3] & 0x80) ? " SATA_port_selector" : ""),
+ ((per_ucp[3] & 8) ? " SSP" : ""),
+ ((per_ucp[3] & 4) ? " STP" : ""),
+ ((per_ucp[3] & 2) ? " SMP" : ""),
+ ((per_ucp[3] & 1) ? " SATA_device" : ""));
printf(" attached SAS address: 0x");
for (m = 0; m < 8; ++m)
printf("%02x", per_ucp[4 + m]);
@@ -1099,8 +1169,7 @@ static void ses_additional_elem_each(const unsigned char * ucp, int len,
}
} else if (1 == desc_type) {
phys = ucp[2 + eip_offset];
- if (0x18 == elem_type) {
- printf("expander descriptor type\n");
+ if (SAS_EXPANDER_EL == elem_type) {
printf(" number of phys: %d\n", phys);
printf(" SAS address: 0x");
for (m = 0; m < 8; ++m)
@@ -1108,7 +1177,7 @@ static void ses_additional_elem_each(const unsigned char * ucp, int len,
printf("\n");
per_ucp = ucp + 14 + eip_offset;
for (j = 0; j < phys; ++j, per_ucp += 2) {
- printf(" [%d] ", j + 1);
+ printf(" [%d] ", j);
if (0xff == per_ucp[0])
printf("no attached connector");
else
@@ -1117,13 +1186,14 @@ static void ses_additional_elem_each(const unsigned char * ucp, int len,
printf(", other element index: %d", per_ucp[1]);
printf("\n");
}
- } else if ((0x14 == elem_type) || (0x15 == elem_type)) {
- printf("SCSI %s port descriptor type\n",
- ((0x14 == elem_type) ? "target" : "initiator"));
+ } else if ((SCSI_TPORT_EL == elem_type) ||
+ (SCSI_IPORT_EL == elem_type) ||
+ (ENC_SC_ELECTR_EL == elem_type)) {
printf(" number of phys: %d\n", phys);
per_ucp = ucp + 6 + eip_offset;
for (j = 0; j < phys; ++j, per_ucp += 12) {
- printf(" phy identifier: 0x%x\n", per_ucp[0]);
+ printf(" phy index: %d\n", j);
+ printf(" phy identifier: 0x%x\n", per_ucp[0]);
if (0xff == per_ucp[2])
printf(" no attached connector");
else
@@ -1155,9 +1225,10 @@ static void ses_additional_elem_each(const unsigned char * ucp, int len,
to "additional" to allow for SAS expander and SATA devices */
static void ses_additional_elem_sdg(const struct element_hdr * ehp,
int num_telems, unsigned int ref_gen_code,
- const unsigned char * resp, int resp_len)
+ const unsigned char * resp, int resp_len,
+ int inner_hex)
{
- int j, k, desc_len, elem_type, invalid, proto, desc_type, eip;
+ int j, k, desc_len, elem_type, invalid;
unsigned int gen_code;
const unsigned char * ucp;
const unsigned char * last_ucp;
@@ -1178,11 +1249,12 @@ static void ses_additional_elem_sdg(const struct element_hdr * ehp,
ucp = resp + 8;
for (k = 0; k < num_telems; ++k) {
elem_type = ehp[k].etype;
- if (! ((1 == elem_type) || /* device */
- (0x14 == elem_type) || /* scsi target */
- (0x15 == elem_type) || /* scsi initiator */
- (0x17 == elem_type) || /* array */
- (0x18 == elem_type))) /* SAS expander */
+ if (! ((DEVICE_EL == elem_type) ||
+ (SCSI_TPORT_EL == elem_type) ||
+ (SCSI_IPORT_EL == elem_type) ||
+ (ARRAY_DEV_EL == elem_type) ||
+ (SAS_EXPANDER_EL == elem_type) ||
+ (ENC_SC_ELECTR_EL == elem_type)))
continue; /* skip if not one of above element types */
if ((ucp + 1) > last_ucp)
goto truncated;
@@ -1195,24 +1267,12 @@ static void ses_additional_elem_sdg(const struct element_hdr * ehp,
ehp[k].etype, ehp[k].se_id);
for (j = 0; j < ehp[k].num_elements; ++j, ucp += desc_len) {
invalid = !!(ucp[0] & 0x80);
- eip = !!(ucp[0] & 0x10);
- proto = (ucp[0] & 0xf);
- if (0x6 == proto) { /* SAS */
- desc_type = ((eip ? ucp[5] : ucp[3]) >> 6) & 0x3;
- if (eip) {
- if (0 == desc_type) /* device or array element */
- printf(" element index: %d [0x%x], bay number: %d"
- " [0x%x]\n", ucp[3], ucp[3], ucp[7], ucp[7]);
- else /* target, initiator or SAS expander element */
- printf(" element index: %d [0x%x]\n", ucp[3],
- ucp[3]);
- }
- } else { /* FCP most likely */
- if (eip)
- printf(" element index: %d [0x%x]\n", ucp[3], ucp[3]);
- }
+ if (ucp[0] & 0x10) /* eip=1 */
+ printf(" element index: %d [0x%x]\n", ucp[3], ucp[3]);
desc_len = ucp[1] + 2;
- if (invalid)
+ if (inner_hex)
+ dStrHex((const char *)ucp + 4, desc_len, 0);
+ else if (invalid)
printf(" flagged as invalid (no further information)\n");
else
ses_additional_elem_each(ucp, desc_len, j, elem_type);
@@ -1220,7 +1280,7 @@ static void ses_additional_elem_sdg(const struct element_hdr * ehp,
}
return;
truncated:
- fprintf(stderr, " <<<response too short>>>\n");
+ fprintf(stderr, " <<<additional: response too short>>>\n");
return;
}
@@ -1254,7 +1314,7 @@ static void ses_subenc_help_sdg(const unsigned char * resp, int resp_len)
}
return;
truncated:
- fprintf(stderr, " <<<response too short>>>\n");
+ fprintf(stderr, " <<<subenc: response too short>>>\n");
return;
}
@@ -1288,7 +1348,7 @@ static void ses_subenc_string_sdg(const unsigned char * resp, int resp_len)
}
return;
truncated:
- fprintf(stderr, " <<<response too short>>>\n");
+ fprintf(stderr, " <<<subence str: response too short>>>\n");
return;
}
@@ -1340,7 +1400,7 @@ static void ses_download_code_sdg(const unsigned char * resp, int resp_len)
}
return;
truncated:
- fprintf(stderr, " <<<response too short>>>\n");
+ fprintf(stderr, " <<<download: response too short>>>\n");
return;
}
@@ -1552,7 +1612,7 @@ static int ses_process_status(int sg_fd, int page_code, int do_raw,
if (res < 0)
break;
ses_additional_elem_sdg(element_hdr_arr, res, ref_gen_code,
- rsp_buff, rsp_len);
+ rsp_buff, rsp_len, inner_hex);
break;
case 0xb:
ses_subenc_help_sdg(rsp_buff, rsp_len);
@@ -1693,10 +1753,10 @@ int main(int argc, char * argv[])
++verbose;
break;
case 'V':
- fprintf(stderr, ME "version: %s\n", version_str);
+ fprintf(stderr, "version: %s\n", version_str);
return 0;
default:
- fprintf(stderr, "unrecognised switch code 0x%x ??\n", c);
+ fprintf(stderr, "unrecognised option code 0x%x ??\n", c);
usage();
return SG_LIB_SYNTAX_ERROR;
}
@@ -1729,7 +1789,7 @@ int main(int argc, char * argv[])
"code):\n");
num = sizeof(element_desc_arr) / sizeof(element_desc_arr[0]);
for (k = 0; k < num; ++k, ++edp)
- printf(" %s [0x%x]\n", edp->desc, edp->type_code);
+ printf(" %s [0x%x]\n", edp->desc, edp->elem_code);
return 0;
}
if (do_control && do_status) {
@@ -1753,13 +1813,13 @@ int main(int argc, char * argv[])
sg_fd = sg_cmds_open_device(device_name, 0 /* rw */, verbose);
if (sg_fd < 0) {
- fprintf(stderr, ME "open error: %s: %s\n", device_name,
+ fprintf(stderr, "open error: %s: %s\n", device_name,
safe_strerror(-sg_fd));
return SG_LIB_FILE_ERROR;
}
if (! do_raw) {
if (sg_simple_inquiry(sg_fd, &inq_resp, 1, verbose)) {
- fprintf(stderr, ME "%s doesn't respond to a SCSI INQUIRY\n",
+ fprintf(stderr, "%s doesn't respond to a SCSI INQUIRY\n",
device_name);
ret = SG_LIB_CAT_OTHER;
goto err_out;
diff --git a/sg_start.c b/sg_start.c
index 4e08880d..85488ed7 100644
--- a/sg_start.c
+++ b/sg_start.c
@@ -27,7 +27,7 @@
*/
-static char * version_str = "0.55 20070128";
+static char * version_str = "0.55 20070419";
static struct option long_options[] = {
{"eject", 0, 0, 'e'},
@@ -206,7 +206,7 @@ static int process_cl_new(struct opts_t * optsp, int argc, char * argv[])
++optsp->do_version;
break;
default:
- fprintf(stderr, "unrecognised switch code %c [0x%x]\n", c, c);
+ fprintf(stderr, "unrecognised option code %c [0x%x]\n", c, c);
if (optsp->do_help)
break;
usage();
diff --git a/sg_sync.c b/sg_sync.c
index e6c250d2..3ace34cd 100644
--- a/sg_sync.c
+++ b/sg_sync.c
@@ -45,7 +45,7 @@
* (e.g. disks).
*/
-static char * version_str = "1.07 20070127";
+static char * version_str = "1.07 20070419";
#define ME "sg_sync: "
@@ -151,7 +151,7 @@ int main(int argc, char * argv[])
fprintf(stderr, ME "version: %s\n", version_str);
return 0;
default:
- fprintf(stderr, "unrecognised switch code 0x%x ??\n", c);
+ fprintf(stderr, "unrecognised option code 0x%x ??\n", c);
usage();
return SG_LIB_SYNTAX_ERROR;
}
diff --git a/sg_turs.c b/sg_turs.c
index b8dcb340..3e19e23b 100644
--- a/sg_turs.c
+++ b/sg_turs.c
@@ -24,7 +24,7 @@
*/
-static char * version_str = "3.26 20070127";
+static char * version_str = "3.26 20070419";
#if defined(MSC_VER) || defined(__MINGW32__)
#define HAVE_MS_SLEEP
@@ -147,7 +147,7 @@ static int process_cl_new(struct opts_t * optsp, int argc, char * argv[])
++optsp->do_version;
break;
default:
- fprintf(stderr, "unrecognised switch code %c [0x%x]\n", c, c);
+ fprintf(stderr, "unrecognised option code %c [0x%x]\n", c, c);
if (optsp->do_help)
break;
usage();
diff --git a/sg_verify.c b/sg_verify.c
index ebe408e9..27c6ddf0 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.09 20070121";
+static char * version_str = "1.09 20070419";
#define ME "sg_verify: "
@@ -145,7 +145,7 @@ int main(int argc, char * argv[])
fprintf(stderr, ME "version: %s\n", version_str);
return 0;
default:
- fprintf(stderr, "unrecognised switch code 0x%x ??\n", c);
+ fprintf(stderr, "unrecognised option code 0x%x ??\n", c);
usage();
return SG_LIB_SYNTAX_ERROR;
}
diff --git a/sg_vpd.8 b/sg_vpd.8
index 1e0d6c51..2212360a 100644
--- a/sg_vpd.8
+++ b/sg_vpd.8
@@ -1,4 +1,4 @@
-.TH SG_VPD "8" "January 2007" "sg3_utils\-1.23" SG3_UTILS
+.TH SG_VPD "8" "April 2007" "sg3_utils\-1.24" SG3_UTILS
.SH NAME
sg_vpd \- fetches Vital Product Data (VPD) pages using a SCSI INQUIRY command
.SH SYNOPSIS
@@ -39,7 +39,7 @@ times, see section on the ATA information vpd page.
.TP
\fB\-i\fR, \fB\-\-ident\fR
decode the device identification (0x83) VPD page. When used once this option
-has the same effect as '\-\-page=di'. When use twice then the short form o
+has the same effect as '\-\-page=di'. When use twice then the short form of
the device identification VPD page's logical unit designator is decoded. In
the latter case this option has the same effect as '\-\-quiet \-\-page=di_lu'.
.TP
@@ -75,7 +75,7 @@ increases the level or verbosity.
print out version string then exit.
.SH ATA INFORMATION VPD PAGE
This VPD page (0x89 or 'ai') is defined by the SCSI to ATA Translation
-draft. It contains information about the SAT layer, the "signature" of
+standard. It contains information about the SAT layer, the "signature" of
the ATA device and the response to the ATA IDENTIFY (PACKET) DEVICE
command. The latter part has 512 bytes of identity, capability and
settings data which the hdparm utility is capable of decoding (so this
diff --git a/sg_vpd.c b/sg_vpd.c
index bcca5cd7..1385b400 100644
--- a/sg_vpd.c
+++ b/sg_vpd.c
@@ -49,7 +49,7 @@
*/
-static char * version_str = "0.18 20070121"; /* spc-4 rev 8 */
+static char * version_str = "0.19 20070419"; /* spc-4 rev 9 */
extern void svpd_enumerate_vendor(void);
extern int svpd_decode_vendor(int sg_fd, int num_vpd, int subvalue,
@@ -508,7 +508,7 @@ static const char * desig_type_arr[] =
"EUI-64 based",
"NAA",
"Relative target port",
- "Target port group",
+ "Target port group", /* spc4r09: _primary_ target port group */
"Logical unit group",
"MD5 logical unit identifier",
"SCSI name string",
@@ -523,11 +523,14 @@ static int decode_dev_ids_quiet(unsigned char * buff, int len,
int m_assoc, int m_desig_type,
int m_code_set)
{
- int m, p_id, c_set, piv, assoc, desig_type, i_len;
- int c_id, d_id, naa, vsi, off, u;
+ int m, p_id, c_set, piv, desig_type, i_len, naa, off, u;
+ int assoc, is_sas, rtp;
const unsigned char * ucp;
const unsigned char * ip;
+ unsigned char sas_tport_addr[8];
+ rtp = 0;
+ memset(sas_tport_addr, 0, sizeof(sas_tport_addr));
off = -1;
while ((u = sg_vpd_dev_id_iter(buff, len, &off, m_assoc, m_desig_type,
m_code_set)) == 0) {
@@ -542,6 +545,7 @@ static int decode_dev_ids_quiet(unsigned char * buff, int len,
p_id = ((ucp[0] >> 4) & 0xf);
c_set = (ucp[0] & 0xf);
piv = ((ucp[1] & 0x80) ? 1 : 0);
+ is_sas = (piv && (6 == p_id)) ? 1 : 0;
assoc = ((ucp[1] >> 4) & 0x3);
desig_type = (ucp[1] & 0xf);
switch (desig_type) {
@@ -552,7 +556,7 @@ static int decode_dev_ids_quiet(unsigned char * buff, int len,
case 2: /* EUI-64 based */
if ((8 != i_len) && (12 != i_len) && (16 != i_len))
fprintf(stderr, " << expect 8, 12 and 16 byte "
- "ids, got %d>>\n", i_len);
+ "EUI, got %d>>\n", i_len);
printf("0x");
for (m = 0; m < i_len; ++m)
printf("%02x", (unsigned int)ip[m]);
@@ -560,44 +564,58 @@ static int decode_dev_ids_quiet(unsigned char * buff, int len,
break;
case 3: /* NAA */
if (1 != c_set) {
- fprintf(stderr, " << expected binary code_set (1)>>\n");
+ fprintf(stderr, " << unexpected code set %d for "
+ "NAA>>\n", c_set);
dStrHex((const char *)ip, i_len, 0);
break;
}
naa = (ip[0] >> 4) & 0xff;
if (! ((2 == naa) || (5 == naa) || (6 == naa))) {
- fprintf(stderr, " << expected naa [0x%x]>>\n", naa);
+ fprintf(stderr, " << unexpected NAA [0x%x]>>\n", naa);
dStrHex((const char *)ip, i_len, 0);
break;
}
if (2 == naa) {
if (8 != i_len) {
- fprintf(stderr, " << expected NAA 2 identifier "
+ fprintf(stderr, " << unexpected NAA 2 identifier "
"length: 0x%x>>\n", i_len);
dStrHex((const char *)ip, i_len, 0);
break;
}
- d_id = (((ip[0] & 0xf) << 8) | ip[1]);
- c_id = ((ip[2] << 16) | (ip[3] << 8) | ip[4]);
- vsi = ((ip[5] << 16) | (ip[6] << 8) | ip[7]);
printf("0x");
for (m = 0; m < 8; ++m)
printf("%02x", (unsigned int)ip[m]);
printf("\n");
} else if (5 == naa) {
if (8 != i_len) {
- fprintf(stderr, " << expected NAA 5 identifier "
+ fprintf(stderr, " << unexpected NAA 5 identifier "
"length: 0x%x>>\n", i_len);
dStrHex((const char *)ip, i_len, 0);
break;
}
- printf("0x");
- for (m = 0; m < 8; ++m)
- printf("%02x", (unsigned int)ip[m]);
- printf("\n");
+ if ((0 == is_sas) || (1 != assoc)) {
+ printf("0x");
+ for (m = 0; m < 8; ++m)
+ printf("%02x", (unsigned int)ip[m]);
+ printf("\n");
+ } else if (rtp) {
+ printf("0x");
+ for (m = 0; m < 8; ++m)
+ printf("%02x", (unsigned int)ip[m]);
+ printf(",0x%x\n", rtp);
+ rtp = 0;
+ } else {
+ if (sas_tport_addr[0]) {
+ printf("0x");
+ for (m = 0; m < 8; ++m)
+ printf("%02x", (unsigned int)sas_tport_addr[m]);
+ printf("\n");
+ }
+ memcpy(sas_tport_addr, ip, sizeof(sas_tport_addr));
+ }
} else if (6 == naa) {
if (16 != i_len) {
- fprintf(stderr, " << expected NAA 6 identifier "
+ fprintf(stderr, " << unexpected NAA 6 identifier "
"length: 0x%x>>\n", i_len);
dStrHex((const char *)ip, i_len, 0);
break;
@@ -609,8 +627,19 @@ static int decode_dev_ids_quiet(unsigned char * buff, int len,
}
break;
case 4: /* Relative target port */
+ if ((0 == is_sas) || (1 != c_set) || (1 != assoc) || (4 != i_len))
+ break;
+ rtp = ((ip[2] << 8) | ip[3]);
+ if (sas_tport_addr[0]) {
+ printf("0x");
+ for (m = 0; m < 8; ++m)
+ printf("%02x", (unsigned int)sas_tport_addr[m]);
+ printf(",0x%x\n", rtp);
+ memset(sas_tport_addr, 0, sizeof(sas_tport_addr));
+ rtp = 0;
+ }
break;
- case 5: /* Target port group */
+ case 5: /* (primary) Target port group */
break;
case 6: /* Logical unit group */
break;
@@ -632,6 +661,12 @@ static int decode_dev_ids_quiet(unsigned char * buff, int len,
break;
}
}
+ if (sas_tport_addr[0]) {
+ printf("0x");
+ for (m = 0; m < 8; ++m)
+ printf("%02x", (unsigned int)sas_tport_addr[m]);
+ printf("\n");
+ }
if (-2 == u) {
fprintf(stderr, "VPD page error: short designator around "
"offset %d\n", off);
@@ -679,7 +714,7 @@ static int decode_dev_ids(const char * print_if_found, unsigned char * buff,
}
if (NULL == print_if_found)
printf(" %s:\n", assoc_arr[assoc]);
- printf(" desig_type: %s, code_set: %s\n",
+ printf(" designator type: %s, code_set: %s\n",
desig_type_arr[desig_type], code_set_arr[c_set]);
if (piv && ((1 == assoc) || (2 == assoc)))
printf(" transport: %s\n", transport_proto_arr[p_id]);
@@ -748,19 +783,20 @@ static int decode_dev_ids(const char * print_if_found, unsigned char * buff,
break;
case 3: /* NAA */
if (1 != c_set) {
- fprintf(stderr, " << expected binary code_set (1)>>\n");
+ fprintf(stderr, " << unexpected code set %d for "
+ "NAA>>\n", c_set);
dStrHex((const char *)ip, i_len, 0);
break;
}
naa = (ip[0] >> 4) & 0xff;
if (! ((2 == naa) || (5 == naa) || (6 == naa))) {
- fprintf(stderr, " << expected naa [0x%x]>>\n", naa);
+ fprintf(stderr, " << unexpected NAA [0x%x]>>\n", naa);
dStrHex((const char *)ip, i_len, 0);
break;
}
if (2 == naa) {
if (8 != i_len) {
- fprintf(stderr, " << expected NAA 2 identifier "
+ fprintf(stderr, " << unexpected NAA 2 identifier "
"length: 0x%x>>\n", i_len);
dStrHex((const char *)ip, i_len, 0);
break;
@@ -784,7 +820,7 @@ static int decode_dev_ids(const char * print_if_found, unsigned char * buff,
printf("\n");
} else if (5 == naa) {
if (8 != i_len) {
- fprintf(stderr, " << expected NAA 5 identifier "
+ fprintf(stderr, " << unexpected NAA 5 identifier "
"length: 0x%x>>\n", i_len);
dStrHex((const char *)ip, i_len, 0);
break;
@@ -812,7 +848,7 @@ static int decode_dev_ids(const char * print_if_found, unsigned char * buff,
}
} else if (6 == naa) {
if (16 != i_len) {
- fprintf(stderr, " << expected NAA 6 identifier "
+ fprintf(stderr, " << unexpected NAA 6 identifier "
"length: 0x%x>>\n", i_len);
dStrHex((const char *)ip, i_len, 0);
break;
@@ -858,7 +894,7 @@ static int decode_dev_ids(const char * print_if_found, unsigned char * buff,
d_id = ((ip[2] << 8) | ip[3]);
printf(" Relative target port: 0x%x\n", d_id);
break;
- case 5: /* Target port group */
+ case 5: /* (primary) Target port group */
if ((1 != c_set) || (1 != assoc) || (4 != i_len)) {
fprintf(stderr, " << expected binary code_set, target "
"port association, length 4>>\n");
@@ -1131,7 +1167,7 @@ static void decode_b0_vpd(unsigned char * buff, int len, int do_hex, int pdt)
return;
}
switch (pdt) {
- case 0: case 4: case 7:
+ case 0: case 4: case 7:
if (len < 16) {
fprintf(stderr, "Block limits VPD page length too "
"short=%d\n", len);
@@ -1145,6 +1181,12 @@ static void decode_b0_vpd(unsigned char * buff, int len, int do_hex, int pdt)
u = (buff[12] << 24) | (buff[13] << 16) | (buff[14] << 8) |
buff[15];
printf(" Optimal transfer length: %u blocks\n", u);
+ if (len > 19) { /* added in sbc3r09 */
+ u = (buff[16] << 24) | (buff[17] << 16) | (buff[18] << 8) |
+ buff[19];
+ printf(" Maximum prefetch, xdread, xdwrite transfer length: "
+ "%u blocks\n", u);
+ }
break;
case 1: case 8:
printf(" WORM=%d\n", !!(buff[4] & 0x1));
@@ -1683,7 +1725,7 @@ int main(int argc, char * argv[])
fprintf(stderr, "version: %s\n", version_str);
return 0;
default:
- fprintf(stderr, "unrecognised switch code 0x%x ??\n", c);
+ fprintf(stderr, "unrecognised option code 0x%x ??\n", c);
usage();
return SG_LIB_SYNTAX_ERROR;
}
diff --git a/sg_wr_mode.c b/sg_wr_mode.c
index 12b1dc67..9ff3436e 100644
--- a/sg_wr_mode.c
+++ b/sg_wr_mode.c
@@ -43,7 +43,7 @@
* mode page on the given device.
*/
-static char * version_str = "1.08 20070127";
+static char * version_str = "1.08 20070419";
#define ME "sg_wr_mode: "
@@ -379,7 +379,7 @@ int main(int argc, char * argv[])
fprintf(stderr, ME "version: %s\n", version_str);
return 0;
default:
- fprintf(stderr, "unrecognised switch code 0x%x ??\n", c);
+ fprintf(stderr, "unrecognised option code 0x%x ??\n", c);
usage();
return SG_LIB_SYNTAX_ERROR;
}
diff --git a/sg_write_buffer.c b/sg_write_buffer.c
index 13de4d51..88f79c78 100644
--- a/sg_write_buffer.c
+++ b/sg_write_buffer.c
@@ -43,7 +43,7 @@
* This utility issues the SCSI WRITE BUFFER command to the given device.
*/
-static char * version_str = "1.04 20070127"; /* spc4r08 */
+static char * version_str = "1.04 20070419"; /* spc4r08 */
#define ME "sg_write_buffer: "
#define DEF_XFER_LEN (8 * 1024 * 1024)
@@ -249,7 +249,7 @@ int main(int argc, char * argv[])
fprintf(stderr, ME "version: %s\n", version_str);
return 0;
default:
- fprintf(stderr, "unrecognised switch code 0x%x ??\n", c);
+ fprintf(stderr, "unrecognised option code 0x%x ??\n", c);
usage();
return SG_LIB_SYNTAX_ERROR;
}
diff --git a/sg_write_long.c b/sg_write_long.c
index b252e557..d6a8014a 100644
--- a/sg_write_long.c
+++ b/sg_write_long.c
@@ -28,7 +28,7 @@
This code was contributed by Saeed Bishara
*/
-static char * version_str = "1.14 20070129";
+static char * version_str = "1.14 20070419";
#define MAX_XFER_LEN 10000
@@ -155,7 +155,7 @@ int main(int argc, char * argv[])
}
break;
default:
- fprintf(stderr, "unrecognised switch code 0x%x ??\n", c);
+ fprintf(stderr, "unrecognised option code 0x%x ??\n", c);
usage();
return SG_LIB_SYNTAX_ERROR;
}
diff --git a/sginfo.8 b/sginfo.8
index 70cad43a..44526c43 100644
--- a/sginfo.8
+++ b/sginfo.8
@@ -1,4 +1,4 @@
-.TH SGINFO "8" "December 2006" "sg3_utils\-1.23" SG3_UTILS
+.TH SGINFO "8" "April 2007" "sg3_utils\-1.24" SG3_UTILS
.SH NAME
sginfo \- access mode page information for a SCSI (or ATAPI) device
.SH SYNOPSIS
@@ -303,18 +303,10 @@ by Michael Weller. sginfo is derived from scsiinfo and uses the sg
interface to get around the 4 KB buffer limit in scsiinfo that cramped
the display of defect lists especially. sginfo was written by Douglas
Gilbert with patches from Kurt Garloff. This manpage corresponds with
-version 2.01 of sginfo. It may be backported (or just copied) soon to
-become scsiinfo 2.01 .
+version 2.25 of sginfo.
.PP
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 plscsi(internet), scsiinfo(internet), sg_modes(sg3_utils),
-.B sg_inq(sg3_utils), sdparm(sdparm)
-.PP
-plscsi can send arbitrary (user supplied) SCSI commands; scsiinfo is the
-predecessor of this utility; sg_modes is a low level MODE SENSE based
-utility and sg_inq is specialized for the mandatory SCSI INQUIRY
-command which contains a lot of information about advanced devices.
-Users may find sdparm more convenient for getting and setting mode
-page parameters.
+.B scsiinfo(internet); sg_modes, sg_inq, sg_vpd (sg3_utils),
+.B sdparm(sdparm)
diff --git a/sgm_dd.8 b/sgm_dd.8
index f130d00f..97f4fddb 100644
--- a/sgm_dd.8
+++ b/sgm_dd.8
@@ -1,4 +1,4 @@
-.TH SGM_DD "8" "January 2007" "sg3_utils\-1.23" SG3_UTILS
+.TH SGM_DD "8" "March 2007" "sg3_utils\-1.24" SG3_UTILS
.SH NAME
sgm_dd \- copies data to and from files and devices. Specialized for
devices that understand the SCSI command set and does memory mapped
@@ -21,8 +21,16 @@ transfers on sg devices. Similar syntax and semantics to
but does not perform any conversions.
.PP
Will only perform memory mapped transfers when \fIIFILE\fR or \fIOFILE\fR
-are SCSI generic (sg) devices. If both \fIIFILE\fR and \fIOFILE\fR are
-sg devices then memory mapped transfers are only performed on \fIIFILE\fR.
+are SCSI generic (sg) devices.
+.PP
+If both \fIIFILE\fR and \fIOFILE\fR are sg devices then memory mapped
+transfers are performed on \fIIFILE\fR. If no other flags are specified
+then indirect IO is performed on \fIOFILE\fR. If 'oflag=dio' is given then
+direct IO is attempted on \fIOFILE\fR. If 'oflag=smmap' is given then
+shared mmap-ed IO (sharing the mmap-ed reserve buffer associated with
+\fIIFILE\fR) is attempted. In both latter cases if the faster IO option
+is not available, they fall back to indirect IO and report this at
+the end of the copy.
.PP
The first group in the synopsis above are "standard" Unix
.B dd(1)
@@ -73,6 +81,7 @@ Only allowed when the read\-side (i.e. \fIIFILE\fR) is a sg device. When
1 there may be a "zero copy" copy (i.e. mmap\-ed transfer on the read into
the user space and direct IO from there on the write, potentially two DMAs
and no data copying from the CPU). Default is 0.
+The same action as 'dio=1' is also available with 'oflag=dio'.
.TP
\fBibs\fR=\fIBS\fR
if given must be the same as \fIBS\fR given to 'bs=' option.
@@ -145,6 +154,10 @@ from the beginning of the file or, if \fISEEK\fR is given, starting at
block \fISEEK\fR. Note that attempting to 'append' to a device file (e.g.
a disk) will usually be ignored or may cause an error to be reported.
.TP
+dio
+is only active with oflag (i.e. 'oflag=dio'). Its action is described in
+the 'dio=1' option description above.
+.TP
direct
causes the O_DIRECT flag to be added to the open of \fIIFILE\fR and/or
\fIOFILE\fR. This flag requires some memory alignment on IO. Hence user
@@ -173,6 +186,11 @@ causes the FUA (force unit access) bit to be set in SCSI READ and/or WRITE
commands. This only has effect with sg devices. The 6 byte variants
of the SCSI READ and WRITE commands do not support the FUA bit.
Only active for sg device file names.
+.TP
+smmap
+is only active for oflag. It sets shared mmap IO usage on \fIOFILE\fR if
+it is a sg device node. The \fIIFILE\fR also needs to be a sg device
+node (or there is no mmap-ed reserve buffer to share).
.SH RETIRED OPTIONS
Here are some retired options that are still present:
.TP
diff --git a/sgm_dd.c b/sgm_dd.c
index d2c3bbd0..870924b6 100644
--- a/sgm_dd.c
+++ b/sgm_dd.c
@@ -55,7 +55,7 @@
This version is designed for the linux kernel 2.4 and 2.6 series.
*/
-static char * version_str = "1.31 20070123";
+static char * version_str = "1.32 20070318 shared_mmap";
#define DEF_BLOCK_SIZE 512
#define DEF_BLOCKS_PER_TRANSFER 128
@@ -82,6 +82,13 @@ static char * version_str = "1.31 20070123";
#define SAI_READ_CAPACITY_16 0x10
#endif
+#ifndef SG_FLAG_SHARED_MMAP_IO
+#define SG_FLAG_SHARED_MMAP_IO 8
+#endif
+#ifndef SG_INFO_SHARED_MMAP_IO
+#define SG_INFO_SHARED_MMAP_IO 8
+#endif
+
#define DEF_TIMEOUT 60000 /* 60,000 millisecs == 60 seconds */
#ifndef RAW_MAJOR
@@ -115,15 +122,20 @@ static int start_tm_valid = 0;
static struct timeval start_tm;
static int blk_sz = 0;
+static int shared_mm_req = 0;
+static int shared_mm_done = 0;
+
static const char * proc_allow_dio = "/proc/scsi/sg/allow_dio";
struct flags_t {
int append;
+ int dio;
int direct;
int dpo;
int dsync;
int excl;
int fua;
+ int smmap;
};
@@ -273,8 +285,9 @@ void usage()
" of file or device to write to (def: stdout), "
"OFILE of '.'\n"
" treated as /dev/null\n"
- " oflag comma separated list from: [append,direct,dpo,"
- "dsync,excl,fua]\n"
+ " oflag comma separated list from: [append,dio,direct,"
+ "dpo,dsync,\n"
+ " excl,fua,smmap]\n"
" seek block position to start writing to OFILE\n"
" skip block position to start reading from IFILE\n"
" sync 0->no sync(def), 1->SYNCHRONIZE CACHE on OFILE "
@@ -286,7 +299,7 @@ void usage()
" --help print usage message then exit\n"
" --version print version information then exit\n\n"
"Copy from IFILE to OFILE, similar to dd command\n"
- "specialized for SCSI devices for which mmap-ed IO attemped\n");
+ "specialized for SCSI devices for which mmap-ed IO attempted\n");
}
/* Return of 0 -> success, see sg_ll_read_capacity*() otherwise */
@@ -563,7 +576,8 @@ int sg_read(int sg_fd, unsigned char * buff, int blocks, long long from_block,
* SG_LIB_CAT_ABORTED_COMMAND, -2 -> recoverable (ENOMEM),
* -1 -> unrecoverable error */
int sg_write(int sg_fd, unsigned char * buff, int blocks, long long to_block,
- int bs, int cdbsz, int fua, int dpo, int do_mmap, int * diop)
+ int bs, int cdbsz, int fua, int dpo, int do_mmap,
+ int mmap_shareable, int * diop)
{
unsigned char wrCmd[MAX_SCSI_CDBSZ];
unsigned char senseBuff[SENSE_BUFF_LEN];
@@ -582,15 +596,18 @@ int sg_write(int sg_fd, unsigned char * buff, int blocks, long long to_block,
io_hdr.cmdp = wrCmd;
io_hdr.dxfer_direction = SG_DXFER_TO_DEV;
io_hdr.dxfer_len = bs * blocks;
- if (! do_mmap)
+ if (mmap_shareable || (! do_mmap))
io_hdr.dxferp = buff;
io_hdr.mx_sb_len = SENSE_BUFF_LEN;
io_hdr.sbp = senseBuff;
io_hdr.timeout = DEF_TIMEOUT;
io_hdr.pack_id = (int)to_block;
- if (do_mmap)
+ if (mmap_shareable) {
+ io_hdr.flags |= SG_FLAG_SHARED_MMAP_IO;
+ ++shared_mm_req;
+ } else if (do_mmap)
io_hdr.flags |= SG_FLAG_MMAP_IO;
- if (diop && *diop)
+ else if (diop && *diop)
io_hdr.flags |= SG_FLAG_DIRECT_IO;
if (verbose > 2) {
fprintf(stderr, " write cdb: ");
@@ -644,6 +661,8 @@ int sg_write(int sg_fd, unsigned char * buff, int blocks, long long to_block,
sg_chk_n_print3("writing", &io_hdr, verbose > 1);
return res;
}
+ if ((mmap_shareable) && (SG_INFO_SHARED_MMAP_IO & io_hdr.info))
+ ++shared_mm_done;
if (diop && *diop &&
((io_hdr.info & SG_INFO_DIRECT_IO_MASK) != SG_INFO_DIRECT_IO))
*diop = 0; /* flag that dio not done (completely) */
@@ -669,6 +688,8 @@ static int process_flags(const char * arg, struct flags_t * fp)
*np++ = '\0';
if (0 == strcmp(cp, "append"))
fp->append = 1;
+ else if (0 == strcmp(cp, "dio"))
+ fp->dio = 1;
else if (0 == strcmp(cp, "direct"))
fp->direct = 1;
else if (0 == strcmp(cp, "dpo"))
@@ -679,6 +700,8 @@ static int process_flags(const char * arg, struct flags_t * fp)
fp->excl = 1;
else if (0 == strcmp(cp, "fua"))
fp->fua = 1;
+ else if (0 == strcmp(cp, "smmap"))
+ fp->smmap = 1;
else {
fprintf(stderr, "unrecognised flag: %s\n", cp);
return 1;
@@ -723,7 +746,6 @@ int main(int argc, char * argv[])
int cdbsz_given = 0;
int do_coe = 0; /* dummy, just accept + ignore */
int do_sync = 0;
- int do_dio = 0;
int num_dio_not_done = 0;
int in_sect_sz, out_sect_sz;
int n, flags;
@@ -732,6 +754,7 @@ int main(int argc, char * argv[])
size_t psz = getpagesize();
struct flags_t in_flags;
struct flags_t out_flags;
+ int mmap_shareable = 0;
int ret = 0;
inf[0] = '\0';
@@ -774,7 +797,7 @@ int main(int argc, char * argv[])
return SG_LIB_SYNTAX_ERROR;
}
} else if (0 == strcmp(key,"dio"))
- do_dio = sg_get_num(buf);
+ out_flags.dio = sg_get_num(buf);
else if (0 == strcmp(key,"fua")) {
n = sg_get_num(buf);
if (n & 1)
@@ -939,6 +962,7 @@ int main(int argc, char * argv[])
perror(ebuff);
return SG_LIB_FILE_ERROR;
}
+ mmap_shareable = 1;
}
else {
flags = O_RDONLY;
@@ -1183,12 +1207,12 @@ int main(int argc, char * argv[])
}
}
- if (do_dio && (FT_SG != in_type)) {
- do_dio = 0;
+ if (out_flags.dio && (FT_SG != in_type)) {
+ out_flags.dio = 0;
fprintf(stderr, ">>> dio only performed on 'of' side when 'if' is"
" an sg device\n");
}
- if (do_dio) {
+ if (out_flags.dio) {
int fd;
char c;
@@ -1202,9 +1226,11 @@ int main(int argc, char * argv[])
}
}
- if (wrkMmap)
+ if (wrkMmap) {
wrkPos = wrkMmap;
- else {
+ if (! (mmap_shareable && out_flags.smmap && (FT_SG == out_type)))
+ mmap_shareable = 0;
+ } else {
if ((FT_RAW == in_type) || (FT_RAW == out_type)) {
wrkBuff = (unsigned char *)malloc(blk_sz * bpt + psz);
if (0 == wrkBuff) {
@@ -1237,8 +1263,8 @@ int main(int argc, char * argv[])
}
req_count = dd_count;
- if (verbose && (dd_count > 0) && (0 == do_dio) &&
- (FT_SG == in_type) && (FT_SG == out_type))
+ if (verbose && (dd_count > 0) && (0 == out_flags.dio) &&
+ (FT_SG == in_type) && (FT_SG == out_type) && (! mmap_shareable))
fprintf(stderr, "Since both 'if' and 'of' are sg devices, only do "
"mmap-ed transfers on 'if'\n");
@@ -1290,18 +1316,19 @@ int main(int argc, char * argv[])
if (FT_SG == out_type) {
int do_mmap = (FT_SG == in_type) ? 0 : 1;
- int dio_res = do_dio;
+ int dio_res = out_flags.dio;
ret = sg_write(outfd, wrkPos, blocks, seek, blk_sz, scsi_cdbsz_out,
- out_flags.fua, out_flags.dpo, do_mmap, &dio_res);
+ out_flags.fua, out_flags.dpo, do_mmap,
+ mmap_shareable, &dio_res);
if ((SG_LIB_CAT_UNIT_ATTENTION == ret) ||
(SG_LIB_CAT_ABORTED_COMMAND == ret)) {
fprintf(stderr, "Unit attention or aborted command, "
"continuing (w)\n");
- dio_res = do_dio;
+ dio_res = out_flags.dio;
ret = sg_write(outfd, wrkPos, blocks, seek, blk_sz,
scsi_cdbsz_out, out_flags.fua, out_flags.dpo,
- do_mmap, &dio_res);
+ do_mmap, mmap_shareable, &dio_res);
}
if (0 != ret) {
fprintf(stderr, "sg_write failed, seek=%lld\n", seek);
@@ -1309,7 +1336,7 @@ int main(int argc, char * argv[])
}
else {
out_full += blocks;
- if (do_dio && (0 == dio_res))
+ if (out_flags.dio && (0 == dio_res))
num_dio_not_done++;
}
}
@@ -1376,5 +1403,9 @@ int main(int argc, char * argv[])
if (num_dio_not_done)
fprintf(stderr, ">> dio requested but _not_ done %d times\n",
num_dio_not_done);
+ if ((verbose > 0) && out_flags.smmap && (shared_mm_req > 0)) {
+ fprintf(stderr, ">> shared_mm_req=%d, shared_mm_done=%d\n",
+ shared_mm_req, shared_mm_done);
+ }
return (ret >= 0) ? ret : SG_LIB_CAT_OTHER;
}
diff --git a/sgp_dd.8 b/sgp_dd.8
index 03343237..7f5b4368 100644
--- a/sgp_dd.8
+++ b/sgp_dd.8
@@ -1,4 +1,4 @@
-.TH SGP_DD "8" "January 2007" "sg3_utils\-1.23" SG3_UTILS
+.TH SGP_DD "8" "April 2007" "sg3_utils\-1.24" SG3_UTILS
.SH NAME
sgp_dd \- copies data to and from files and devices. Specialized for
devices that understand the SCSI command set.
@@ -77,6 +77,7 @@ default is 0 which selects indirect IO. Value of 1 attempts direct
IO which, if not available, falls back to indirect IO and notes this
at completion. If direct IO is selected and /proc/scsi/sg/allow_dio
has the value of 0 then a warning is issued (and indirect IO is performed)
+For finer grain control use 'iflag=dio' or 'oflag=dio'.
.TP
\fBibs\fR=\fIBS\fR
if given must be the same as \fIBS\fR given to 'bs=' option.
@@ -159,6 +160,12 @@ utility is more sophisticated in such error situations when 'iflag=coe'.
When given with 'oflag=', any error reported by a SCSI WRITE command is
reported to stderr and the copy continues (as if nothing went wrong).
.TP
+dio
+request the sg device node associated with this flag does direct IO.
+If direct IO is not available, falls back to indirect IO and notes
+this at completion. If direct IO is selected and /proc/scsi/sg/allow_dio
+has the value of 0 then a warning is issued (and indirect IO is performed).
+.TP
direct
causes the O_DIRECT flag to be added to the open of \fIIFILE\fR and/or
\fIOFILE\fR. This flag requires some memory alignment on IO. Hence user
@@ -193,7 +200,7 @@ Here are some retired options that are still present:
coe=0 | 1
continue on error is 0 (off) by default. When it is 1, it is
equivalent to 'iflag=coe oflag=coe' described in the FLAGS section
-above. Similar to 'conv=noerror' in
+above. Similar to 'conv=noerror,sync' in
.B dd(1)
utility. Default is 0 which implies stop on error. More advanced
coe=1 processing on reads is performed by the sg_dd utility.
diff --git a/sgp_dd.c b/sgp_dd.c
index d531a892..1f5bf028 100644
--- a/sgp_dd.c
+++ b/sgp_dd.c
@@ -50,7 +50,7 @@
*/
-static char * version_str = "5.36 20070121";
+static char * version_str = "5.37 20070319";
#define DEF_BLOCK_SIZE 512
#define DEF_BLOCKS_PER_TRANSFER 128
@@ -99,6 +99,7 @@ static char * version_str = "5.36 20070121";
struct flags_t {
int append;
int coe;
+ int dio;
int direct;
int dpo;
int dsync;
@@ -133,7 +134,6 @@ typedef struct request_collection
pthread_cond_t out_sync_cv; /* -/ hold writes until "in order" */
int bs;
int bpt;
- int dio;
int dio_incomplete; /* -\ */
int sum_of_resids; /* | */
pthread_mutex_t aux_mutex; /* -/ (also serializes some printf()s */
@@ -153,7 +153,6 @@ typedef struct request_element
unsigned char cmd[MAX_SCSI_CDBSZ];
unsigned char sb[SENSE_BUFF_LEN];
int bs;
- int dio;
int dio_incomplete;
int resid;
int cdbsz_in;
@@ -342,14 +341,15 @@ static void usage()
"2->IFILE,\n"
" 3->OFILE+IFILE\n"
" if file or device to read from (def: stdin)\n"
- " iflag comma separated list from: [coe,direct,dpo,dsync,"
- "excl,fua]\n"
+ " iflag comma separated list from: [coe,dio,direct,dpo,"
+ "dsync,excl,\n"
+ " fua]\n"
" of file or device to write to (def: stdout), "
"OFILE of '.'\n"
" treated as /dev/null\n"
- " oflag comma separated list from: [append,coe,direct,dpo,"
- "dsync,excl,\n"
- " fua]\n"
+ " oflag comma separated list from: [append,coe,dio,direct,"
+ "dpo,dsync,\n"
+ " excl,fua]\n"
" sync 0->no sync(def), 1->SYNCHRONIZE CACHE on OFILE "
"after copy\n"
" thr is number of threads, must be > 0, default 4, "
@@ -512,7 +512,6 @@ static void * read_write_thread(void * v_clp)
(~(psz - 1)));
/* Follow clp members are constant during lifetime of thread */
rep->bs = clp->bs;
- rep->dio = clp->dio;
rep->infd = clp->infd;
rep->outfd = clp->outfd;
rep->debug = clp->debug;
@@ -930,6 +929,7 @@ static int sg_start_io(Rq_elem * rep)
struct sg_io_hdr * hp = &rep->io_hdr;
int fua = rep->wr ? rep->out_flags.fua : rep->in_flags.fua;
int dpo = rep->wr ? rep->out_flags.dpo : rep->in_flags.dpo;
+ int dio = rep->wr ? rep->out_flags.dio : rep->in_flags.dio;
int cdbsz = rep->wr ? rep->cdbsz_out : rep->cdbsz_in;
int res;
@@ -951,7 +951,7 @@ static int sg_start_io(Rq_elem * rep)
hp->timeout = DEF_TIMEOUT;
hp->usr_ptr = rep;
hp->pack_id = (int)rep->blk;
- if (rep->dio)
+ if (dio)
hp->flags |= SG_FLAG_DIRECT_IO;
if (rep->debug > 8) {
fprintf(stderr, "sg_start_io: SCSI %s, blk=%lld num_blks=%d\n",
@@ -986,7 +986,7 @@ static int sg_finish_io(int wr, Rq_elem * rep, pthread_mutex_t * a_mutp)
memset(&io_hdr, 0 , sizeof(struct sg_io_hdr));
/* FORCE_PACK_ID active set only read packet with matching pack_id */
io_hdr.interface_id = 'S';
- io_hdr.dxfer_direction = rep->wr ? SG_DXFER_TO_DEV : SG_DXFER_FROM_DEV;
+ io_hdr.dxfer_direction = wr ? SG_DXFER_TO_DEV : SG_DXFER_FROM_DEV;
io_hdr.pack_id = (int)rep->blk;
while (((res = read(wr ? rep->outfd : rep->infd, &io_hdr,
@@ -1006,13 +1006,13 @@ static int sg_finish_io(int wr, Rq_elem * rep, pthread_mutex_t * a_mutp)
case SG_LIB_CAT_CLEAN:
break;
case SG_LIB_CAT_RECOVERED:
- sg_chk_n_print3((rep->wr ? "writing continuing":
+ sg_chk_n_print3((wr ? "writing continuing":
"reading continuing"), hp, 0);
break;
case SG_LIB_CAT_ABORTED_COMMAND:
case SG_LIB_CAT_UNIT_ATTENTION:
if (rep->debug > 8)
- sg_chk_n_print3((rep->wr ? "writing": "reading"), hp, 0);
+ sg_chk_n_print3((wr ? "writing": "reading"), hp, 0);
return res;
case SG_LIB_CAT_NOT_READY:
default:
@@ -1020,7 +1020,7 @@ static int sg_finish_io(int wr, Rq_elem * rep, pthread_mutex_t * a_mutp)
char ebuff[EBUFF_SZ];
snprintf(ebuff, EBUFF_SZ, "%s blk=%lld",
- rep->wr ? "writing": "reading", rep->blk);
+ 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, 0);
@@ -1032,7 +1032,7 @@ static int sg_finish_io(int wr, Rq_elem * rep, pthread_mutex_t * a_mutp)
#if 0
if (0 == (++testing % 100)) return -1;
#endif
- if (rep->dio &&
+ if ((wr ? rep->out_flags.dio : rep->in_flags.dio) &&
((hp->info & SG_INFO_DIRECT_IO_MASK) != SG_INFO_DIRECT_IO))
rep->dio_incomplete = 1; /* count dios done as indirect IO */
else
@@ -1085,6 +1085,8 @@ static int process_flags(const char * arg, struct flags_t * fp)
fp->append = 1;
else if (0 == strcmp(cp, "coe"))
fp->coe = 1;
+ else if (0 == strcmp(cp, "dio"))
+ fp->dio = 1;
else if (0 == strcmp(cp, "direct"))
fp->direct = 1;
else if (0 == strcmp(cp, "dpo"))
@@ -1179,9 +1181,10 @@ int main(int argc, char * argv[])
} else if ((0 == strncmp(key,"deb", 3)) ||
(0 == strncmp(key,"verb", 4)))
rcoll.debug = sg_get_num(buf);
- else if (0 == strcmp(key,"dio"))
- rcoll.dio = sg_get_num(buf);
- else if (0 == strcmp(key,"fua")) {
+ else if (0 == strcmp(key,"dio")) {
+ rcoll.in_flags.dio = sg_get_num(buf);
+ rcoll.out_flags.dio = rcoll.in_flags.dio;
+ } else if (0 == strcmp(key,"fua")) {
n = sg_get_num(buf);
if (n & 1)
rcoll.out_flags.fua = 1;
diff --git a/utils/Makefile.solaris b/utils/Makefile.solaris
new file mode 100644
index 00000000..e72e5bf5
--- /dev/null
+++ b/utils/Makefile.solaris
@@ -0,0 +1,54 @@
+SHELL = /bin/sh
+
+PREFIX=/usr/local
+INSTDIR=$(DESTDIR)/$(PREFIX)/bin
+MANDIR=$(DESTDIR)/$(PREFIX)/man
+
+CC = gcc
+LD = gcc
+
+EXECS = hxascdmp sg_chk_asc
+
+MAN_PGS =
+MAN_PREF = man8
+
+CFLAGS = -g -O2 -W
+# CFLAGS = -g -O2 -W -pedantic -std=c99
+
+LDFLAGS =
+
+all: $(EXECS)
+
+depend dep:
+ for i in *.c; do $(CC) $(INCLUDES) $(CFLAGS) -M $$i; \
+ done > .depend
+
+clean:
+ /bin/rm -f *.o $(EXECS) core .depend
+
+hxascdmp: hxascdmp.o
+ $(LD) -o $@ $(LDFLAGS) $@.o
+
+sg_chk_asc: sg_chk_asc.o ../sg_lib.o
+ $(LD) -o $@ $(LDFLAGS) $@.o ../sg_lib.o
+
+
+install: $(EXECS)
+ install -d $(INSTDIR)
+ for name in $(EXECS); \
+ do install -s -f $(INSTDIR) $$name; \
+ done
+ install -d $(MANDIR)/$(MAN_PREF)
+ for mp in $(MAN_PGS); \
+ do install -m 644 -f $(MANDIR)/$(MAN_PREF) $$mp; \
+ done
+
+uninstall:
+ dists="$(EXECS)"; \
+ for name in $$dists; do \
+ rm -f $(INSTDIR)/$$name; \
+ done
+ for mp in $(MAN_PGS); do \
+ rm -f $(MANDIR)/$(MAN_PREF)/$$mp.gz; \
+ done
+
diff --git a/utils/sg_lib.h b/utils/sg_lib.h
new file mode 100644
index 00000000..e2f826a1
--- /dev/null
+++ b/utils/sg_lib.h
@@ -0,0 +1 @@
+#include "../sg_lib.h"
diff --git a/utils/sg_lib.hh b/utils/sg_lib.hh
deleted file mode 100644
index c650c885..00000000
--- a/utils/sg_lib.hh
+++ /dev/null
@@ -1,307 +0,0 @@
-#ifndef SG_LIB_H
-#define SG_LIB_H
-
-/*
- * Copyright (c) 2004-2007 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.
- *
- */
-
-/* Version 1.32 [20070129]
- *
- * 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
- * as open source and encourage their unencumbered use.
- */
-
-
-/*
- * This header file contains defines and function declarations that may
- * be useful to applications that communicate with devices that use a
- * SCSI command set. These command sets have names like SPC-4, SBC-3,
- * SSC-3, SES-2 and draft standards defining them can be found at
- * http://www.t10.org . Virtually all devices in the Linux SCSI subsystem
- * utilize SCSI command sets. Many devices in other Linux device subsystems
- * utilize SCSI command sets either natively or via emulation (e.g. a
- * parallel ATA disk in a USB enclosure).
- */
-
-#include <stdio.h>
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#ifndef SAM_STAT_GOOD
-/* The SCSI status codes as found in SAM-4 at www.t10.org */
-#define SAM_STAT_GOOD 0x0
-#define SAM_STAT_CHECK_CONDITION 0x2
-#define SAM_STAT_CONDITION_MET 0x4
-#define SAM_STAT_BUSY 0x8
-#define SAM_STAT_INTERMEDIATE 0x10 /* obsolete in SAM-4 */
-#define SAM_STAT_INTERMEDIATE_CONDITION_MET 0x14 /* obsolete in SAM-4 */
-#define SAM_STAT_RESERVATION_CONFLICT 0x18
-#define SAM_STAT_COMMAND_TERMINATED 0x22 /* obsolete in SAM-3 */
-#define SAM_STAT_TASK_SET_FULL 0x28
-#define SAM_STAT_ACA_ACTIVE 0x30
-#define SAM_STAT_TASK_ABORTED 0x40
-#endif
-
-/* The SCSI sense key codes as found in SPC-4 at www.t10.org */
-#define SPC_SK_NO_SENSE 0x0
-#define SPC_SK_RECOVERED_ERROR 0x1
-#define SPC_SK_NOT_READY 0x2
-#define SPC_SK_MEDIUM_ERROR 0x3
-#define SPC_SK_HARDWARE_ERROR 0x4
-#define SPC_SK_ILLEGAL_REQUEST 0x5
-#define SPC_SK_UNIT_ATTENTION 0x6
-#define SPC_SK_DATA_PROTECT 0x7
-#define SPC_SK_BLANK_CHECK 0x8
-#define SPC_SK_COPY_ABORTED 0xa
-#define SPC_SK_ABORTED_COMMAND 0xb
-#define SPC_SK_VOLUME_OVERFLOW 0xd
-#define SPC_SK_MISCOMPARE 0xe
-
-
-/* Returns length of SCSI command given the opcode (first byte).
- Yields the wrong answer for variable length commands (opcode=0x7f)
- and potentially some vendor specific commands. */
-extern int sg_get_command_size(unsigned char cdb_byte0);
-
-/* Command name given pointer to the cdb. Certain command names
- depend on peripheral type (give 0 if unknown). Places command
- name into buff and will write no more than buff_len bytes. */
-extern void sg_get_command_name(const unsigned char * cdbp, int peri_type,
- int buff_len, char * buff);
-
-/* Command name given only the first byte (byte 0) of a cdb and
- * peripheral type. */
-extern void sg_get_opcode_name(unsigned char cdb_byte0, int peri_type,
- int buff_len, char * buff);
-
-/* Command name given opcode (byte 0), service action and peripheral type.
- If no service action give 0, if unknown peripheral type give 0. */
-extern void sg_get_opcode_sa_name(unsigned char cdb_byte0, int service_action,
- int peri_type, int buff_len, char * buff);
-
-/* Fetch scsi status string. */
-extern void sg_get_scsi_status_str(int scsi_status, int buff_len, char * buff);
-
-/* This is a slightly stretched SCSI sense "descriptor" format header.
- The addition is to allow the 0x70 and 0x71 response codes. The idea
- is to place the salient data of both "fixed" and "descriptor" sense
- format into one structure to ease application processing.
- The original sense buffer should be kept around for those cases
- in which more information is required (e.g. the LBA of a MEDIUM ERROR). */
-struct sg_scsi_sense_hdr {
- unsigned char response_code; /* permit: 0x0, 0x70, 0x71, 0x72, 0x73 */
- unsigned char sense_key;
- unsigned char asc;
- unsigned char ascq;
- unsigned char byte4;
- unsigned char byte5;
- unsigned char byte6;
- unsigned char additional_length;
-};
-
-/* Maps the salient data from a sense buffer which is in either fixed or
- descriptor format into a structure mimicking a descriptor format
- header (i.e. the first 8 bytes of sense descriptor format).
- If zero response code returns 0. Otherwise returns 1 and if 'sshp' is
- non-NULL then zero all fields and then set the appropriate fields in
- that structure. sshp::additional_length is always 0 for response
- codes 0x70 and 0x71 (fixed format). */
-extern int sg_scsi_normalize_sense(const unsigned char * sensep,
- int sense_len,
- struct sg_scsi_sense_hdr * sshp);
-
-/* Attempt to find the first SCSI sense data descriptor that matches the
- given 'desc_type'. If found return pointer to start of sense data
- descriptor; otherwise (including fixed format sense data) returns NULL. */
-extern const unsigned char * sg_scsi_sense_desc_find(
- const unsigned char * sensep, int sense_len, int desc_type);
-
-/* Yield string associated with sense_key value. Returns 'buff'. */
-extern char * sg_get_sense_key_str(int sense_key, int buff_len, char * buff);
-
-/* Yield string associated with ASC/ASCQ values. Returns 'buff'. */
-extern char * sg_get_asc_ascq_str(int asc, int ascq, int buff_len,
- char * buff);
-
-/* Returns 1 if valid bit set, 0 if valid bit clear. Irrespective the
- information field is written out via 'info_outp' (except when it is
- NULL). Handles both fixed and descriptor sense formats. */
-extern int sg_get_sense_info_fld(const unsigned char * sensep, int sb_len,
- unsigned long long * info_outp);
-
-/* Returns 1 if sense key is NO_SENSE or NOT_READY and SKSV is set. Places
- progress field from sense data where progress_outp points. If progress
- field is not available returns 0. Handles both fixed and descriptor
- sense formats. N.B. App should multiply by 100 and divide by 65536
- to get percentage completion from given value. */
-extern int sg_get_sense_progress_fld(const unsigned char * sensep,
- int sb_len, int * progress_outp);
-
-/* Closely related to sg_print_sense(). Puts decode sense data in 'buff'.
- Usually multiline with multiple '\n' including one trailing. If
- 'raw_sinfo' set appends sense buffer in hex. */
-extern void sg_get_sense_str(const char * leadin,
- const unsigned char * sense_buffer, int sb_len,
- int raw_sinfo, int buff_len, char * buff);
-
-/* Yield string associated with peripheral device type (pdt). Returns
- 'buff'. If 'pdt' out of range yields "bad pdt" string. */
-extern char * sg_get_pdt_str(int pdt, int buff_len, char * buff);
-
-extern FILE * sg_warnings_strm;
-
-extern void sg_set_warnings_strm(FILE * warnings_strm);
-
-/* The following "print" functions send ACSII to 'sg_warnings_strm' file
- 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,
- int raw_info);
-extern void sg_print_scsi_status(int scsi_status);
-
-/* Utilities can use these process status values for syntax errors and
- file (device node) problems (e.g. not found or permissions). */
-#define SG_LIB_SYNTAX_ERROR 1
-#define SG_LIB_FILE_ERROR 15
-
-/* The sg_err_category_sense() function returns one of the following.
- These may be used as process status values (on exit). Notice that
- some of the lower values correspond to SCSI sense key values. */
-#define SG_LIB_CAT_CLEAN 0 /* No errors or other information */
-/* Value 1 left unused for utilities to use SG_LIB_SYNTAX_ERROR */
-#define SG_LIB_CAT_NOT_READY 2 /* interpreted from sense buffer */
- /* [sk,asc,ascq: 0x2,*,*] */
-#define SG_LIB_CAT_MEDIUM_HARD 3 /* medium or hardware error, blank check */
- /* [sk,asc,ascq: 0x3/0x4/0x8,*,*] */
-#define SG_LIB_CAT_ILLEGAL_REQ 5 /* Illegal request (other than invalid */
- /* opcode): [sk,asc,ascq: 0x5,*,*] */
-#define SG_LIB_CAT_UNIT_ATTENTION 6 /* interpreted from sense buffer */
- /* [sk,asc,ascq: 0x6,*,*] */
- /* was SG_LIB_CAT_MEDIA_CHANGED earlier [sk,asc,ascq: 0x6,0x28,*] */
-#define SG_LIB_CAT_INVALID_OP 9 /* (Illegal request,) Invalid opcode: */
- /* [sk,asc,ascq: 0x5,0x20,0x0] */
-#define SG_LIB_CAT_ABORTED_COMMAND 11 /* interpreted from sense buffer */
- /* [sk,asc,ascq: 0xb,*,*] */
-#define SG_LIB_CAT_NO_SENSE 20 /* sense data with key of "no sense" */
- /* [sk,asc,ascq: 0x0,*,*] */
-#define SG_LIB_CAT_RECOVERED 21 /* Successful command after recovered err */
- /* [sk,asc,ascq: 0x1,*,*] */
-#define SG_LIB_CAT_MALFORMED 97 /* Response to SCSI command malformed */
-#define SG_LIB_CAT_SENSE 98 /* Something else is in the sense buffer */
-#define SG_LIB_CAT_OTHER 99 /* Some other error/warning has occurred
- (e.g. a transport or driver error) */
-
-extern int sg_err_category_sense(const unsigned char * sense_buffer,
- int sb_len);
-
-/* Iterates to next designation descriptor in the device identification
- VPD page. The 'initial_desig_desc' should point to start of first
- descriptor with 'page_len' being the number of valid bytes in that
- and following descriptors. To start, 'off' should point to a negative
- value, thereafter it should point to the value yielded by the previous
- call. If 0 returned then 'initial_desig_desc + *off' should be a valid
- descriptor; returns -1 if normal end condition and -2 for an abnormal
- termination. Matches association, designator_type and/or code_set when
- any of those values are greater than or equal to zero. */
-extern int sg_vpd_dev_id_iter(const unsigned char * initial_desig_desc,
- int page_len, int * off, int m_assoc,
- int m_desig_type, int m_code_set);
-
-
-/* <<< General purpose (i.e. not SCSI specific) utility functions >>> */
-
-/* Always returns valid string even if errnum is wild (or library problem).
- If errnum is negative, flip its sign. */
-extern char * safe_strerror(int errnum);
-
-
-/* Print (to stdout) 'str' of bytes in hex, 16 bytes per line optionally
- followed at the right hand side of the line with an ASCII interpretation.
- Each line is prefixed with an address, starting at 0 for str[0]..str[15].
- All output numbers are in hex. 'no_ascii' allows for 3 output types:
- > 0 each line has address then up to 16 ASCII-hex bytes
- = 0 in addition, the bytes are listed in ASCII to the right
- < 0 only the ASCII-hex bytes are listed (i.e. without address)
-*/
-extern void dStrHex(const char* str, int len, int no_ascii);
-
-/* Returns 1 when executed on big endian machine; else returns 0.
- Useful for displaying ATA identify words (which need swapping on a
- big endian machine).
-*/
-extern int sg_is_big_endian();
-
-/* Extract character sequence from ATA words as in the model string
- in a IDENTIFY DEVICE response. Returns number of characters
- written to 'ochars' before 0 character is found or 'num' words
- are processed. */
-extern int sg_ata_get_chars(const unsigned short * word_arr, int start_word,
- int num_words, int is_big_endian, char * ochars);
-
-/* Print (to stdout) 16 bit 'words' in hex, 8 words per line optionally
- followed at the right hand side of the line with an ASCII interpretation
- (pairs of ASCII characters in big endian order (upper first)).
- Each line is prefixed with an address, starting at 0.
- All output numbers are in hex. 'no_ascii' allows for 3 output types:
- > 0 each line has address then up to 8 ASCII-hex words
- = 0 in addition, the words are listed in ASCII pairs to the right
- = -1 only the ASCII-hex words are listed (i.e. without address)
- = -2 only the ASCII-hex words, formatted for "hdparm --Istdin"
- < -2 same as -1
- If 'swapb' non-zero then bytes in each word swapped. Needs to be set
- for ATA IDENTIFY DEVICE response on big-endian machines.
-*/
-extern void dWordHex(const unsigned short* words, int num, int no_ascii,
- int swapb);
-
-/* If the number in 'buf' can not be decoded or the multiplier is unknown
- then -1 is returned. Accepts a hex prefix (0x or 0X) or a 'h' (or 'H')
- suffix. Otherwise a decimal multiplier suffix may be given. Recognised
- multipliers: 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; g G GiB *1,073,741,824;
- GB *1,000,000,000 and <n>x<m> which multiplies <n> by <m> . */
-extern int sg_get_num(const char * buf);
-
-/* If the number in 'buf' can not be decoded or the multiplier is unknown
- then -1LL is returned. Accepts a hex prefix (0x or 0X) or a 'h' (or 'H')
- suffix. Otherwise a decimal multiplier suffix may be given. In addition
- to supporting the multipliers of sg_get_num(), this function supports:
- t T TiB *(2**40); TB *(10**12); p P PiB *(2**50); PB *(10**15) . */
-extern long long sg_get_llnum(const char * buf);
-
-extern const char * sg_lib_version();
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif