aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--COVERAGE5
-rw-r--r--ChangeLog16
-rw-r--r--README6
-rw-r--r--debian/changelog2
-rw-r--r--doc/sg_logs.87
-rw-r--r--doc/sg_ses.86
-rw-r--r--lib/sg_lib_data.c3
-rw-r--r--scripts/55-scsi-sg3_id.rules13
-rw-r--r--scripts/58-scsi-sg3_symlink.rules25
-rwxr-xr-xscripts/rescan-scsi-bus.sh53
-rw-r--r--sg3_utils.spec2
-rw-r--r--src/sg_inq.c34
-rw-r--r--src/sg_logs.c145
-rw-r--r--src/sg_readcap.c152
-rw-r--r--src/sg_senddiag.c5
-rw-r--r--src/sg_ses.c258
-rw-r--r--src/sg_vpd.c8
-rw-r--r--src/sg_write_verify.c6
18 files changed, 480 insertions, 266 deletions
diff --git a/COVERAGE b/COVERAGE
index 5b12c8c4..84960a93 100644
--- a/COVERAGE
+++ b/COVERAGE
@@ -12,6 +12,7 @@ ATA COMMAND PASS-THROUGH(16) sg_sat_identify, sg_sat_set_features,
sg__sat_set_features, sg_sat_smart_rd_data
(previous four in the examples directory)]
ATA COMMAND PASS-THROUGH(12) sg_sat_identify, ++
+CLOSE ZONE sg_zone
COMPARE AND WRITE sg_compare_and_write
COPY OPERATION ABORT ddptctl, ++
EXTENDED COPY(LID1) sg_xcopy, ddpt, ++
@@ -20,6 +21,7 @@ GET LBA STATUS sg_get_lba_status, ++
INQUIRY sg_dd, sg_format, sg_inq, sginfo,
sg_logs, sg_map('-i'), sg_modes, sg_opcodes,
sg_persist, sg_scan, sg_ses, sg_vpd ++
+FINISH ZONE sg_zone
FORMAT UNIT sg_format, ++
LOG SELECT sg_logs('-r' or '-select'), ++
LOG SENSE sg_logs, ++
@@ -31,6 +33,7 @@ MODE SENSE(6) sdparm, sg_modes, sg_wr_mode, sginfo, sg_format,
sg_senddiag('-e'), sg_rdac, ++
MODE SENSE(10) sdparm, sg_modes, sg_wr_mode, sginfo, sg_format,
sg_senddiag('-e'), sg_rdac, ++
+OPEN ZONE sg_zone
PERSISTENT RESERVE IN sg_persist, ++
PERSISTENT RESERVE OUT sg_persist, ++
POPULATE TOKEN ddpt, ddptctl, ++
@@ -125,4 +128,4 @@ THIRD PARTY COPY IN (0x83).
Douglas Gilbert
-7th November 2014
+18th December 2014
diff --git a/ChangeLog b/ChangeLog
index 78f09c33..cbd014fe 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -2,22 +2,28 @@ 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.41 [20141215] [svn: r622]
+Changelog for sg3_utils-1.41 [20141220] [svn: r623]
- sg_zone: new utility for open, close and finish
- zone commands introduced in zbc0r02
+ zone commands introduced in zbc-r02
- sg_rep_zones and sg_reset_wp: change opcodes as
- indicated by zbc0r02
+ indicated in zbc-r02
- sg_logs: add --enumerate and acronyms
- allow decode from hex or binary in file
- sg_lib interface: add sg_lib_pdt_decay(), TPROTO_PCIE
- and support for zoning service actions
- - sg_inq_sg_vpd: fix SCSI name string decoding in
+ plus support for zoning service actions
+ - sg_inq+sg_vpd: fix SCSI name string decoding in
device identification VPD page (0x83)
+ - sg_inq: improve NAA handling in dev_id VPD page
- sg_vpd: add atomic boundary values (sbc4r04)
- block limits VPD page: fix unmap granularity
alignment value
+ - sg_readcap: add support for ZBC's rc_basis field
+ - sg_senddiag: fix bug with --raw option
- sg_ses: enclosure element: add failure and warning
acronyms, fix warning indication output
+ - additional element status dpage: add PCIe/NVMe
+ - rescan-scsi-bus.sh: add --issue-lip-wait option and
+ improve error handling
Changelog for sg3_utils-1.40 [20141110] [svn: r620]
- sg_write_verify: new utility for WRITE AND VERIFY
diff --git a/README b/README
index 4db45e4a..43d54aa0 100644
--- a/README
+++ b/README
@@ -239,7 +239,7 @@ subdirectory of the sg3_utils package:
sg_sat_read_gplog, sg_sat_set_features, sg_scan, sg_senddiag, sg_ses,
sg_ses_microcode, sg_start, sg_stpg, sg_sync, sg_test_rwbuff, sg_turs,
sg_unmap, sg_verify, sg_vpd, sg_write_buffer, sg_write_long,
- sg_write_same, sg_write_verify sg_wr_mode, sg_xcopy
+ sg_write_same, sg_write_verify sg_wr_mode, sg_xcopy, sg_zone
Each of the above utilities depends on header files found in the 'include'
subdirectory and library code found in the 'lib' subdirectory. Associated
@@ -388,7 +388,7 @@ The more recent utilities that use "getopt_long" only are:
sg_sat_identify, sg_sat_phy_event, sg_sat_read_gplog, sg_sat_set_features,
sg_scan(w), sg_ses, sg_ses_microcode, sg_stpg, sg_sync, sg_test_rwbuf,
sg_unmap, sg_verify, sg_vpd, sg_write_buffer, sg_write_long,
- sg_write_same, sg_write_verify, sg_wr_mode
+ sg_write_same, sg_write_verify, sg_wr_mode, sg_zone
Dangerous code
@@ -412,4 +412,4 @@ See http://sg.danny.cz/sg/tools.html
Douglas Gilbert
-14th December 2014
+20th December 2014
diff --git a/debian/changelog b/debian/changelog
index a6a070d5..08d7eac5 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -2,7 +2,7 @@ sg3-utils (1.41-0.1) unstable; urgency=low
* New upstream version
- -- Douglas Gilbert <dgilbert@interlog.com> Sun, 14 Dec 2014 14:00:00 -0500
+ -- Douglas Gilbert <dgilbert@interlog.com> Sat, 20 Dec 2014 19:00:00 -0500
sg3-utils (1.40-0.1) unstable; urgency=low
diff --git a/doc/sg_logs.8 b/doc/sg_logs.8
index 3a51b195..449140ca 100644
--- a/doc/sg_logs.8
+++ b/doc/sg_logs.8
@@ -160,15 +160,16 @@ dependent. It will assume a PDT of 0 (i.e. a disk).
switch to older style options.
.TP
\fB\-p\fR, \fB\-\-page\fR=\fIPG\fR
-log page code to access. \fIPG\fR is either an acronym, a page number, or
-a page, subpage pair. Available acronyms can be listed with the
+log page name/number to access. \fIPG\fR is either an acronym, a page number,
+or a page, subpage number pair. Available acronyms can be listed with the
\fI\-\-enumerate\fR option. Page (0 to 63) and subpage (0 to 255) numbers
are comma separated. They are decimal unless a hexadecimal indication is
given. A hexadecimal number can be specified by a leading "0x" or a
trailing "h".
.br
A few acronyms specify a range of subpage values in which case the acronym
-may be followed by a comma then a subpage number.
+may be followed by a comma then a subpage number. This method can also be
+used to fetch the Supported subpages log page (e.g. \-\-page=temp,0xff).
.TP
\fB\-P\fR, \fB\-\-paramp\fR=\fIPP\fR
\fIPP\fR is the parameter pointer value to place in a field of that name in
diff --git a/doc/sg_ses.8 b/doc/sg_ses.8
index 9d969bbd..ff5cd8a7 100644
--- a/doc/sg_ses.8
+++ b/doc/sg_ses.8
@@ -156,8 +156,10 @@ option. And like this option it has a "given twice" form: '\-ee'.
\fB\-H\fR, \fB\-\-hex\fR
If the \fI\-\-get=STR\fR option is given then output the value found (if
any) in hexadecimal, with a leading "0x". Otherwise output the response
-in hexadecimal. Ignored when all elements from several pages are being
-accessed.
+in hexadecimal; with trailing ASCII if given once, without it if given
+twice, and simple hex if given three or more times. Ignored when all
+elements from several pages are being accessed. Also see the \fI\-\-raw\fR
+option which may be used with this option..
.TP
\fB\-I\fR, \fB\-\-index\fR=\fIIIA\fR
where \fIIIA\fR is either an individual index (II) or an Element type
diff --git a/lib/sg_lib_data.c b/lib/sg_lib_data.c
index 85e75729..c3122f1f 100644
--- a/lib/sg_lib_data.c
+++ b/lib/sg_lib_data.c
@@ -1383,6 +1383,7 @@ const char * sg_lib_transport_proto_strs[] =
"AT Attachment Interface (ACS-2)", /* 0x8 */
"USB Attached SCSI (UAS-2)",
"SCSI over PCI Express (SOP)",
- "Oxb", "Oxc", "Oxd", "Oxe",
+ "PCIe", /* added in spc5r01 */
+ "Oxc", "Oxd", "Oxe",
"No specific protocol"
};
diff --git a/scripts/55-scsi-sg3_id.rules b/scripts/55-scsi-sg3_id.rules
index ab5a8e32..82ef5931 100644
--- a/scripts/55-scsi-sg3_id.rules
+++ b/scripts/55-scsi-sg3_id.rules
@@ -21,16 +21,23 @@ KERNEL=="sd*[!0-9]|sr*", ENV{ID_SCSI}=="1", IMPORT{program}="/usr/bin/sg_inq --e
KERNEL=="sd*[!0-9]|sr*", ENV{ID_SCSI}=="1", IMPORT{program}="/usr/bin/sg_inq --export --page=di $tempnode"
# ID_WWN compat mapping
-ENV{SCSI_IDENT_LUN_NAA}=="?*", ENV{ID_WWN}!="?*", ENV{ID_WWN}="0x$env{SCSI_IDENT_LUN_NAA}"
-ENV{SCSI_IDENT_LUN_NAA}=="?*", ENV{ID_WWN_WITH_EXTENSION}!="?*", ENV{ID_WWN_WITH_EXTENSION}="0x$env{SCSI_IDENT_LUN_NAA}"
+ENV{SCSI_IDENT_LUN_NAA_REGEXT}=="?*", ENV{ID_WWN}!="?*", ENV{ID_WWN}="0x$env{SCSI_IDENT_LUN_NAA_REGEXT}"
+ENV{SCSI_IDENT_LUN_NAA_REG}=="?*", ENV{ID_WWN}!="?*", ENV{ID_WWN}="0x$env{SCSI_IDENT_LUN_NAA_REG}"
+ENV{SCSI_IDENT_LUN_NAA_EXT}=="?*", ENV{ID_WWN}!="?*", ENV{ID_WWN}="0x$env{SCSI_IDENT_LUN_NAA_EXT}"
+ENV{SCSI_IDENT_LUN_NAA_LOCAL}=="?*", ENV{ID_WWN}!="?*", ENV{ID_WWN}="0x$env{SCSI_IDENT_LUN_NAA_LOCAL}"
+ENV{SCSI_IDENT_LUN_NAA_REGEXT}=="?*", ENV{ID_WWN_WITH_EXTENSION}!="?*", ENV{ID_WWN_WITH_EXTENSION}="0x$env{SCSI_IDENT_LUN_NAA_REGEXT}"
+ENV{SCSI_IDENT_LUN_NAA_EXT}=="?*", ENV{ID_WWN_WITH_EXTENSION}!="?*", ENV{ID_WWN_WITH_EXTENSION}="0x$env{SCSI_IDENT_LUN_NAA_EXT}"
# ata_id compability
ENV{ID_SERIAL}!="?*", ENV{SCSI_IDENT_LUN_ATA}=="?*", ENV{ID_BUS}="ata", ENV{ID_ATA}="1", ENV{ID_SERIAL}="$env{SCSI_IDENT_LUN_ATA}"
ENV{ID_SERIAL_SHORT}!="?*", ENV{SCSI_VENDOR}=="ATA", ENV{SCSI_IDENT_LUN_VENDOR}=="?*", ENV{ID_SERIAL_SHORT}="$env{SCSI_IDENT_LUN_VENDOR}"
# Compat ID_SERIAL setting
-ENV{ID_SERIAL}!="?*", ENV{SCSI_IDENT_LUN_NAA}=="?*", ENV{ID_BUS}="scsi", ENV{ID_SERIAL}="3$env{SCSI_IDENT_LUN_NAA}", ENV{ID_SERIAL_SHORT}="$env{SCSI_IDENT_LUN_NAA}"
+ENV{ID_SERIAL}!="?*", ENV{SCSI_IDENT_LUN_NAA_REGEXT}=="?*", ENV{ID_BUS}="scsi", ENV{ID_SERIAL}="3$env{SCSI_IDENT_LUN_NAA_REGEXT}", ENV{ID_SERIAL_SHORT}="$env{SCSI_IDENT_LUN_NAA_REGEXT}"
+ENV{ID_SERIAL}!="?*", ENV{SCSI_IDENT_LUN_NAA_REG}=="?*", ENV{ID_BUS}="scsi", ENV{ID_SERIAL}="3$env{SCSI_IDENT_LUN_NAA_REG}", ENV{ID_SERIAL_SHORT}="$env{SCSI_IDENT_LUN_NAA_REG}"
+ENV{ID_SERIAL}!="?*", ENV{SCSI_IDENT_LUN_NAA_EXT}=="?*", ENV{ID_BUS}="scsi", ENV{ID_SERIAL}="3$env{SCSI_IDENT_LUN_NAA}", ENV{ID_SERIAL_SHORT}="$env{SCSI_IDENT_LUN_NAA_EXT}"
ENV{ID_SERIAL}!="?*", ENV{SCSI_IDENT_LUN_EUI64}=="?*", ENV{ID_BUS}="scsi", ENV{ID_SERIAL}="2$env{SCSI_IDENT_LUN_EUI64}", ENV{ID_SERIAL_SHORT}="$env{SCSI_IDENT_LUN_EUI64}"
ENV{ID_SERIAL}!="?*", ENV{SCSI_IDENT_LUN_NAME}=="?*", ENV{ID_BUS}="scsi", ENV{ID_SERIAL}="8$env{SCSI_IDENT_LUN_NAME}", ENV{ID_SERIAL_SHORT}="$env{SCSI_IDENT_LUN_NAME}"
ENV{ID_SERIAL}!="?*", ENV{SCSI_IDENT_LUN_T10}=="?*", ENV{ID_BUS}="scsi", ENV{ID_SERIAL}="1$env{SCSI_IDENT_LUN_T10}", ENV{ID_SERIAL_SHORT}="$env{SCSI_IDENT_LUN_T10}"
+ENV{ID_SERIAL}!="?*", ENV{SCSI_IDENT_LUN_NAA_LOCAL}=="?*", ENV{ID_BUS}="scsi", ENV{ID_SERIAL}="3$env{SCSI_IDENT_LUN_NAA_LOCAL}", ENV{ID_SERIAL_SHORT}="$env{SCSI_IDENT_LUN_NAA_LOCAL}"
ENV{ID_SERIAL}!="?*", ENV{SCSI_IDENT_LUN_VENDOR}=="?*", ENV{ID_BUS}="scsi", ENV{ID_SERIAL}="0$env{SCSI_VENDOR}_$env{SCSI_MODEL}_$env{SCSI_IDENT_LUN_VENDOR}", ENV{ID_SERIAL_SHORT}="$env{SCSI_IDENT_LUN_VENDOR}"
LABEL="sg3_utils_id_end"
diff --git a/scripts/58-scsi-sg3_symlink.rules b/scripts/58-scsi-sg3_symlink.rules
index 697f92b9..272ff1ee 100644
--- a/scripts/58-scsi-sg3_symlink.rules
+++ b/scripts/58-scsi-sg3_symlink.rules
@@ -11,19 +11,30 @@ ENV{DM_MULTIPATH_DEVICE_PATH}=="1", GOTO="sg3_utils_symlink_end"
# 0: vpd page 0x80 identifier
ENV{SCSI_IDENT_SERIAL}=="?*", ENV{DEVTYPE}=="disk", SYMLINK+="disk/by-id/scsi-S$env{SCSI_VENDOR}_$env{SCSI_MODEL}_$env{SCSI_IDENT_SERIAL}"
ENV{SCSI_IDENT_SERIAL}=="?*", ENV{DEVTYPE}=="partition", SYMLINK+="disk/by-id/scsi-S$env{SCSI_VENDOR}_$env{SCSI_MODEL}_$env{SCSI_IDENT_SERIAL}-part%n"
-# 1: NAA identifier (prefix 3)
-ENV{SCSI_IDENT_LUN_NAA}=="?*", ENV{DEVTYPE}=="disk", SYMLINK+="disk/by-id/scsi-3$env{SCSI_IDENT_LUN_NAA}"
-ENV{SCSI_IDENT_LUN_NAA}=="?*", ENV{DEVTYPE}=="partition", SYMLINK+="disk/by-id/scsi-3$env{SCSI_IDENT_LUN_NAA}-part%n"
-# 2: EUI-64 identifer (prefix 2)
+# NAA identifier (prefix 3)
+# 1: IEEE Registered Extended first
+ENV{SCSI_IDENT_LUN_NAA_REGEXT}=="?*", ENV{DEVTYPE}=="disk", SYMLINK+="disk/by-id/scsi-3$env{SCSI_IDENT_LUN_NAA_REGEXT}"
+ENV{SCSI_IDENT_LUN_NAA_REGEXT}=="?*", ENV{DEVTYPE}=="partition",
+# SYMLINK+="disk/by-id/scsi-3$env{SCSI_IDENT_LUN_NAA_REGEXT}-part%n"
+# 2: IEEE Registered
+ENV{SCSI_IDENT_LUN_NAA_REG}=="?*", ENV{DEVTYPE}=="disk", SYMLINK+="disk/by-id/scsi-3$env{SCSI_IDENT_LUN_NAA_REG}"
+ENV{SCSI_IDENT_LUN_NAA_REG}=="?*", ENV{DEVTYPE}=="partition", SYMLINK+="disk/by-id/scsi-3$env{SCSI_IDENT_LUN_NAA_REG}-part%n"
+# 3: IEEE Extended
+ENV{SCSI_IDENT_LUN_NAA_EXT}=="?*", ENV{DEVTYPE}=="disk", SYMLINK+="disk/by-id/scsi-3$env{SCSI_IDENT_LUN_NAA_EXT}"
+ENV{SCSI_IDENT_LUN_NAA_EXT}=="?*", ENV{DEVTYPE}=="partition", SYMLINK+="disk/by-id/scsi-3$env{SCSI_IDENT_LUN_NAA_EXT}-part%n"
+# 4: EUI-64 identifer (prefix 2)
ENV{SCSI_IDENT_LUN_EUI64}=="?*", ENV{DEVTYPE}=="disk", SYMLINK+="disk/by-id/scsi-2$env{SCSI_IDENT_LUN_EUI64}"
ENV{SCSI_IDENT_LUN_EUI64}=="?*", ENV{DEVTYPE}=="partition", SYMLINK+="disk/by-id/scsi-2$env{SCSI_IDENT_LUN_EUI64}-part%n"
-# 3: SCSI name identifier (prefix 8)
+# 5: SCSI name identifier (prefix 8)
ENV{SCSI_IDENT_LUN_NAME}=="?*", ENV{DEVTYPE}=="disk", SYMLINK+="disk/by-id/scsi-8$env{SCSI_IDENT_LUN_NAME}"
ENV{SCSI_IDENT_LUN_NAME}=="?*", ENV{DEVTYPE}=="partition", SYMLINK+="disk/by-id/scsi-8$env{SCSI_IDENT_LUN_NAME}-part%n"
-# 4: T10 Vendor identifer (prefix 1)
+# 6: T10 Vendor identifer (prefix 1)
ENV{SCSI_IDENT_LUN_T10}=="?*", ENV{DEVTYPE}=="disk", SYMLINK+="disk/by-id/scsi-1$env{SCSI_IDENT_LUN_T10}"
ENV{SCSI_IDENT_LUN_T10}=="?*", ENV{DEVTYPE}=="partition", SYMLINK+="disk/by-id/scsi-1$env{SCSI_IDENT_LUN_T10}-part%n"
-# 5: Vendor-specific identifier (prefix 0)
+# 7: IEEE Locally assigned
+ENV{SCSI_IDENT_LUN_NAA_LOCAL}=="?*", ENV{DEVTYPE}=="disk", SYMLINK+="disk/by-id/scsi-3$env{SCSI_IDENT_LUN_NAA_LOCAL}"
+ENV{SCSI_IDENT_LUN_NAA_LOCAL}=="?*", ENV{DEVTYPE}=="partition", SYMLINK+="disk/by-id/scsi-3$env{SCSI_IDENT_LUN_NAA_LOCAL}-part%n"
+# 8: Vendor-specific identifier (prefix 0)
ENV{SCSI_IDENT_LUN_VENDOR}=="?*", ENV{DEVTYPE}=="disk", SYMLINK+="disk/by-id/scsi-0$env{SCSI_VENDOR}_$env{SCSI_MODEL}_$env{SCSI_IDENT_LUN_VENDOR}"
ENV{SCSI_IDENT_LUN_VENDOR}=="?*", ENV{DEVTYPE}=="partition", SYMLINK+="disk/by-id/scsi-0$env{SCSI_VENDOR}_$env{SCSI_MODEL}_$env{SCSI_IDENT_LUN_VENDOR}-part%n"
diff --git a/scripts/rescan-scsi-bus.sh b/scripts/rescan-scsi-bus.sh
index 8df88c38..51fdfd99 100755
--- a/scripts/rescan-scsi-bus.sh
+++ b/scripts/rescan-scsi-bus.sh
@@ -105,22 +105,22 @@ printtype ()
local type=$1
case "$type" in
- 0) echo "Direct-Access " ;;
+ 0) echo "Direct-Access" ;;
1) echo "Sequential-Access" ;;
- 2) echo "Printer " ;;
- 3) echo "Processor " ;;
- 4) echo "WORM " ;;
- 5) echo "CD-ROM " ;;
- 6) echo "Scanner " ;;
- 7) echo "Optical Device " ;;
- 8) echo "Medium Changer " ;;
- 9) echo "Communications " ;;
- 10) echo "Unknown " ;;
- 11) echo "Unknown " ;;
- 12) echo "RAID " ;;
- 13) echo "Enclosure " ;;
+ 2) echo "Printer" ;;
+ 3) echo "Processor" ;;
+ 4) echo "WORM" ;;
+ 5) echo "CD-ROM" ;;
+ 6) echo "Scanner" ;;
+ 7) echo "Optical Device" ;;
+ 8) echo "Medium Changer" ;;
+ 9) echo "Communications" ;;
+ 10) echo "Unknown" ;;
+ 11) echo "Unknown" ;;
+ 12) echo "RAID" ;;
+ 13) echo "Enclosure" ;;
14) echo "Direct-Access-RBC" ;;
- *) echo "Unknown " ;;
+ *) echo "Unknown" ;;
esac
}
@@ -158,7 +158,7 @@ $SCSIDEV"
ILVL=$(cat ${SCSIPATH}/device/scsi_level)
type=$(cat ${SCSIPATH}/device/type)
ITYPE=$(printtype $type)
- SCSITMP=$(printf ' Type: %-16s ANSI SCSI revision: %02d' "$ITYPE" "$((ILVL - 1))")
+ SCSITMP=$(printf ' Type: %-17s ANSI SCSI revision: %02d' "$ITYPE" "$((ILVL - 1))")
SCSISTR="$SCSISTR
$SCSITMP"
fi
@@ -231,6 +231,9 @@ testonline ()
{
: testonline
RC=0
+ # Set default values
+ IPTYPE=0x1f
+ IPQUAL=3
if test ! -x /usr/bin/sg_turs; then return 0; fi
sgdevice
if test -z "$SGDEV"; then return 0; fi
@@ -256,6 +259,10 @@ testonline ()
RC=0
# OK, device online, compare INQUIRY string
INQ=`sg_inq $sg_len_arg /dev/$SGDEV 2>/dev/null`
+ if [ -z "$INQ" ] ; then
+ echo -e "\e[A\e[A\e[A\e[A${red}$SGDEV changed: ${bold}INQUIRY failed${norm} \n\n\n"
+ return 2
+ fi
IVEND=`echo "$INQ" | grep 'Vendor identification:' | sed 's/^[^:]*: \(.*\)$/\1/'`
IPROD=`echo "$INQ" | grep 'Product identification:' | sed 's/^[^:]*: \(.*\)$/\1/'`
IPREV=`echo "$INQ" | grep 'Product revision level:' | sed 's/^[^:]*: \(.*\)$/\1/'`
@@ -263,6 +270,8 @@ testonline ()
IPTYPE=`echo "$INQ" | sed -n 's/.* Device_type=\([0-9]*\) .*/\1/p'`
IPQUAL=`echo "$INQ" | sed -n 's/ *PQual=\([0-9]*\) Device.*/\1/p'`
if [ "$IPQUAL" != 0 ] ; then
+ [ -z "$IPQUAL" ] && IPQUAL=3
+ [ -z "$IPTYPE" ] && IPTYPE=0x1f
echo -e "\e[A\e[A\e[A\e[A${red}$SGDEV changed: ${bold}LU not available (PQual $IPQUAL)${norm} \n\n\n"
return 2
fi
@@ -278,7 +287,7 @@ testonline ()
return 1
fi
TMPSTR=`echo "$SCSISTR" | sed -n 's/.*Type: *\(.*\) *ANSI.*/\1/p'`
- if [ $TMPSTR != $TYPE ] ; then
+ if [ "$TMPSTR" != "$TYPE" ] ; then
echo -e "\e[A\e[A\e[A\e[A${red}$SGDEV changed: ${bold}\nfrom:${TMPSTR} \nto: $TYPE ${norm} \n\n\n"
return 1
fi
@@ -927,6 +936,7 @@ if test @$1 = @--help -o @$1 = @-h -o @$1 = @-?; then
echo " -f flush failed multipath devices [default: disabled]"
echo " -h help: print this usage message then exit"
echo " -i issue a FibreChannel LIP reset [default: disabled]"
+ echo " -I SECS issue a FibreChannel LIP reset and wait for SECS seconds [default: disabled]"
echo " -l activates scanning for LUNs 0--7 [default: 0]"
echo " -L NUM activates scanning for LUNs 0--NUM [default: 0]"
echo " -r enables removing of devices [default: disabled]"
@@ -944,6 +954,7 @@ if test @$1 = @--help -o @$1 = @-h -o @$1 = @-?; then
echo "--hosts=LIST: Scan only host(s) in LIST"
echo "--ids=LIST: Scan only target ID(s) in LIST"
echo "--issue-lip: same as -i"
+ echo "--issue-lip-wait=SECS: same as -I"
echo "--largelun: Tell kernel to support LUNs > 7 even on SCSI2 devs"
echo "--luns=LIST: Scan only lun(s) in LIST"
echo "--nooptscan: don't stop looking for LUNs is 0 is not found"
@@ -1005,6 +1016,7 @@ optscan=1
sync=1
existing_targets=1
mp_enable=
+lipreset=-1
declare -i scan_flags=0
# Scan options
@@ -1022,7 +1034,8 @@ while test ! -z "$opt" -a -z "${opt##-*}"; do
c) opt_channelsearch="0 1" ;;
r) remove=1 ;;
s) resize=1 ;;
- i) lipreset=1 ;;
+ i) lipreset=0 ;;
+ I) shift; lipreset=$opt ;;
u) update=1 ;;
-alltargets) existing_targets=;;
-flush) flush=1 ;;
@@ -1035,7 +1048,8 @@ while test ! -z "$opt" -a -z "${opt##-*}"; do
-luns=*) arg=${opt#-luns=}; lunsearch=`expandlist $arg` ;;
-color) setcolor ;;
-nooptscan) optscan=0 ;;
- -issue-lip) lipreset=1 ;;
+ -issue-lip) lipreset=0 ;;
+ -issue-lip-wait) lipreset=${opt#-issue-lip-wait=};;
-sync) sync=2 ;;
-nosync) sync=0 ;;
-multipath) mp_enable=1 ;;
@@ -1111,9 +1125,10 @@ else
if test -e /sys/class/fc_host/host$host ; then
# It's pointless to do a target scan on FC
issue_lip=/sys/class/fc_host/host$host/issue_lip
- if test -e $issue_lip -a -n "$lipreset" ; then
+ if test -e $issue_lip -a $lipreset -ge 0 ; then
echo 1 > $issue_lip 2> /dev/null;
udevadm_settle
+ [ $lipreset -gt 0 ] && sleep $lipreset
fi
channelsearch=
idsearch=
diff --git a/sg3_utils.spec b/sg3_utils.spec
index b339dbef..fb3973ea 100644
--- a/sg3_utils.spec
+++ b/sg3_utils.spec
@@ -79,7 +79,7 @@ fi
%{_libdir}/*.la
%changelog
-* Sun Dec 14 2014 - dgilbert at interlog dot com
+* Sat Dec 20 2014 - dgilbert at interlog dot com
- track t10 changes
* sg3_utils-1.41
diff --git a/src/sg_inq.c b/src/sg_inq.c
index 897be758..60c8adeb 100644
--- a/src/sg_inq.c
+++ b/src/sg_inq.c
@@ -1882,6 +1882,11 @@ export_dev_ids(unsigned char * buff, int len, int verbose)
}
break;
}
+ /*
+ * Unfortunately, there are some (broken) implementations
+ * which return _several_ NAA descriptors.
+ * So add a suffix to differentiate between them.
+ */
naa = (ip[0] >> 4) & 0xff;
if ((naa < 2) || (naa > 6) || (4 == naa)) {
if (verbose) {
@@ -1891,15 +1896,36 @@ export_dev_ids(unsigned char * buff, int len, int verbose)
break;
}
if (6 != naa) {
+ const char *suffix;
+
if (8 != i_len) {
if (verbose) {
- pr2serr(" << unexpected NAA 2 identifier "
- "length: 0x%x>>\n", i_len);
+ pr2serr(" << unexpected NAA %d identifier "
+ "length: 0x%x>>\n", naa, i_len);
+ dStrHexErr((const char *)ip, i_len, 0);
+ }
+ break;
+ }
+ if (naa != 2 && naa != 3 && naa != 5) {
+ if (verbose) {
+ pr2serr(" << unexpected NAA format %d>>\n", naa);
dStrHexErr((const char *)ip, i_len, 0);
}
break;
}
- printf("SCSI_IDENT_%s_NAA=", assoc_str);
+ switch (naa) {
+ case 5:
+ suffix="REG";
+ break;
+ case 2:
+ suffix="EXT";
+ break;
+ case 3:
+ default:
+ suffix="LOCAL";
+ break;
+ }
+ printf("SCSI_IDENT_%s_NAA_%s=", assoc_str, suffix);
for (m = 0; m < 8; ++m)
printf("%02x", (unsigned int)ip[m]);
printf("\n");
@@ -1912,7 +1938,7 @@ export_dev_ids(unsigned char * buff, int len, int verbose)
}
break;
}
- printf("SCSI_IDENT_%s_NAA=", assoc_str);
+ printf("SCSI_IDENT_%s_NAA_REGEXT=", assoc_str);
for (m = 0; m < 16; ++m)
printf("%02x", (unsigned int)ip[m]);
printf("\n");
diff --git a/src/sg_logs.c b/src/sg_logs.c
index 84caba14..5766a92b 100644
--- a/src/sg_logs.c
+++ b/src/sg_logs.c
@@ -31,7 +31,7 @@
#include "sg_unaligned.h"
#include "sg_pt.h" /* needed for scsi_pt_win32_direct() */
-static const char * version_str = "1.27 20141214"; /* spc4r37a + sbc4r04 */
+static const char * version_str = "1.28 20141219"; /* spc5r00 + sbc4r04 */
#define MX_ALLOC_LEN (0xfffc)
#define SHORT_RESP_LEN 128
@@ -137,6 +137,7 @@ struct opts_t {
int dev_pdt;
const char * device_name;
const char * in_fn;
+ const char * pg_arg;
const struct log_elem * lep;
};
@@ -678,10 +679,7 @@ usage_for(int hval, const struct opts_t * op)
static int
process_cl_new(struct opts_t * op, int argc, char * argv[])
{
- int c, n, nn;
- char * cp;
- const struct log_elem * lep;
- char b[80];
+ int c, n;
while (1) {
int option_index = 0;
@@ -767,56 +765,7 @@ process_cl_new(struct opts_t * op, int argc, char * argv[])
op->opt_new = 0;
return 0;
case 'p':
- if (isalpha(optarg[0])) {
- if (strlen(optarg) >= (sizeof(b) - 1)) {
- pr2serr("argument to '--page=' is too long\n");
- return SG_LIB_SYNTAX_ERROR;
- }
- strcpy(b, optarg);
- cp = strchr(b, ',');
- if (cp)
- *cp = '\0';
- lep = acron_search(b);
- if (NULL == lep) {
- pr2serr("bad argument to '--page=' no acronyn match to "
- "'%s'\n", b);
- pr2serr(" Try using '-e' or'-ee' to see available "
- "acronyns\n");
- return SG_LIB_SYNTAX_ERROR;
- }
- op->lep = lep;
- op->pg_code = lep->pg_code;
- if (cp) {
- nn = sg_get_num_nomult(cp + 1);
- if ((nn < 0) || (nn > 255)) {
- pr2serr("Bad second value in argument to "
- "'--page='\n");
- return SG_LIB_SYNTAX_ERROR;
- }
- op->subpg_code = nn;
- } else
- op->subpg_code = lep->subpg_code;
- } else { /* numeric arg: either 'pg_num' or 'pg_num,subpg_num' */
- cp = strchr(optarg, ',');
- n = sg_get_num_nomult(optarg);
- if ((n < 0) || (n > 63)) {
- pr2serr("Bad argument to '--page='\n");
- usage(1);
- return SG_LIB_SYNTAX_ERROR;
- }
- if (cp) {
- nn = sg_get_num_nomult(cp + 1);
- if ((nn < 0) || (nn > 255)) {
- pr2serr("Bad second value in argument to "
- "'--page='\n");
- usage(1);
- return SG_LIB_SYNTAX_ERROR;
- }
- } else
- nn = 0;
- op->pg_code = n;
- op->subpg_code = nn;
- }
+ op->pg_arg = optarg;
break;
case 'P':
n = sg_get_num(optarg);
@@ -1012,7 +961,7 @@ process_cl_old(struct opts_t * op, int argc, char * argv[])
return SG_LIB_SYNTAX_ERROR;
}
strcpy(b, ccp);
- xp = strchr(b, ',');
+ xp = (char *)strchr(b, ',');
if (xp)
*xp = '\0';
lep = acron_search(b);
@@ -1480,9 +1429,12 @@ show_supported_pgs_sub_lpage(const uint8_t * resp, int len,
const struct log_elem * lep;
char b[64];
- if (op->verbose || ((0 == op->do_raw) && (0 == op->do_hex)))
- printf("Supported log pages and subpages [0x%x, 0xff]:\n",
- op->pg_code);
+ if (op->verbose || ((0 == op->do_raw) && (0 == op->do_hex))) {
+ if (op->pg_code > 0)
+ printf("Supported subpages [0x%x, 0xff]:\n", op->pg_code);
+ else
+ printf("Supported log pages and subpages [0x0, 0xff]:\n");
+ }
num = len - 4;
ucp = &resp[0] + 4;
for (k = 0; k < num; k += 2) {
@@ -5412,6 +5364,67 @@ fetchTemperature(int sg_fd, uint8_t * resp, int max_len, struct opts_t * op)
return (res >= 0) ? res : SG_LIB_CAT_OTHER;
}
+static int
+decode_pg_arg(struct opts_t * op)
+{
+ int n, nn;
+ const struct log_elem * lep;
+ char * cp;
+ char b[80];
+
+ if (isalpha(op->pg_arg[0])) {
+ if (strlen(op->pg_arg) >= (sizeof(b) - 1)) {
+ pr2serr("argument to '--page=' is too long\n");
+ return SG_LIB_SYNTAX_ERROR;
+ }
+ strcpy(b, op->pg_arg);
+ cp = (char *)strchr(b, ',');
+ if (cp)
+ *cp = '\0';
+ lep = acron_search(b);
+ if (NULL == lep) {
+ pr2serr("bad argument to '--page=' no acronyn match to "
+ "'%s'\n", b);
+ pr2serr(" Try using '-e' or'-ee' to see available "
+ "acronyns\n");
+ return SG_LIB_SYNTAX_ERROR;
+ }
+ op->lep = lep;
+ op->pg_code = lep->pg_code;
+ if (cp) {
+ nn = sg_get_num_nomult(cp + 1);
+ if ((nn < 0) || (nn > 255)) {
+ pr2serr("Bad second value in argument to "
+ "'--page='\n");
+ return SG_LIB_SYNTAX_ERROR;
+ }
+ op->subpg_code = nn;
+ } else
+ op->subpg_code = lep->subpg_code;
+ } else { /* numeric arg: either 'pg_num' or 'pg_num,subpg_num' */
+ cp = (char *)strchr(op->pg_arg, ',');
+ n = sg_get_num_nomult(op->pg_arg);
+ if ((n < 0) || (n > 63)) {
+ pr2serr("Bad argument to '--page='\n");
+ usage(1);
+ return SG_LIB_SYNTAX_ERROR;
+ }
+ if (cp) {
+ nn = sg_get_num_nomult(cp + 1);
+ if ((nn < 0) || (nn > 255)) {
+ pr2serr("Bad second value in argument to "
+ "'--page='\n");
+ usage(1);
+ return SG_LIB_SYNTAX_ERROR;
+ }
+ } else
+ nn = 0;
+ op->pg_code = n;
+ op->subpg_code = nn;
+ }
+ return 0;
+}
+
int
main(int argc, char * argv[])
@@ -5465,6 +5478,9 @@ main(int argc, char * argv[])
op->in_fn, in_len);
return SG_LIB_SYNTAX_ERROR;
}
+ if (op->pg_arg && (0 == op->do_brief))
+ pr2serr(">>> --page=%s option is being ignored, using values "
+ "in file: %s\n", op->pg_arg, op->in_fn);
for (ucp = rsp_buff, k = 0; k < in_len; ucp += n, k += n) {
pg_code = ucp[0] & 0x3f;
subpg_code = (ucp[0] & 0x40) ? ucp[1] : 0;
@@ -5537,6 +5553,17 @@ main(int argc, char * argv[])
sizeof(rsp_buff)))
return SG_LIB_FILE_ERROR;
}
+ if (op->pg_arg) {
+ if (op->do_all) {
+ if (0 == op->do_brief)
+ pr2serr(">>> warning: --page=%s ignored when --all given\n",
+ op->pg_arg);
+ } else {
+ res = decode_pg_arg(op);
+ if (res)
+ return res;
+ }
+ }
#ifdef SG_LIB_WIN32
#ifdef SG_LIB_WIN32_DIRECT
diff --git a/src/sg_readcap.c b/src/sg_readcap.c
index 6b55cbb5..4a0220cf 100644
--- a/src/sg_readcap.c
+++ b/src/sg_readcap.c
@@ -27,9 +27,10 @@
#endif
#include "sg_lib.h"
#include "sg_cmds_basic.h"
+#include "sg_unaligned.h"
-static const char * version_str = "3.92 20140515";
+static const char * version_str = "3.93 20141220";
#define ME "sg_readcap: "
@@ -37,20 +38,21 @@ static const char * version_str = "3.92 20140515";
#define RCAP16_REPLY_LEN 32
static struct option long_options[] = {
- {"brief", 0, 0, 'b'},
- {"help", 0, 0, 'h'},
- {"hex", 0, 0, 'H'},
- {"lba", 1, 0, 'L'},
- {"long", 0, 0, 'l'},
- {"16", 0, 0, 'l'},
- {"new", 0, 0, 'N'},
- {"old", 0, 0, 'O'},
- {"pmi", 0, 0, 'p'},
- {"raw", 0, 0, 'r'},
- {"readonly", 0, 0, 'R'},
- {"verbose", 0, 0, 'v'},
- {"version", 0, 0, 'V'},
- {0, 0, 0, 0},
+ {"brief", 0, 0, 'b'},
+ {"help", 0, 0, 'h'},
+ {"hex", 0, 0, 'H'},
+ {"lba", 1, 0, 'L'},
+ {"long", 0, 0, 'l'},
+ {"16", 0, 0, 'l'},
+ {"new", 0, 0, 'N'},
+ {"old", 0, 0, 'O'},
+ {"pmi", 0, 0, 'p'},
+ {"raw", 0, 0, 'r'},
+ {"readonly", 0, 0, 'R'},
+ {"verbose", 0, 0, 'v'},
+ {"version", 0, 0, 'V'},
+ {"zbc", 0, 0, 'z'},
+ {0, 0, 0, 0},
};
struct opts_t {
@@ -64,18 +66,22 @@ struct opts_t {
int o_readonly;
int do_verbose;
int do_version;
+ int do_zbc;
uint64_t llba;
const char * device_name;
int opt_new;
};
-static void usage()
+
+static void
+usage()
{
- fprintf(stderr, "Usage: sg_readcap [--brief] [--help] [--hex] "
- "[--lba=LBA] [--long] [--16]\n"
+ fprintf(stderr,
+ "Usage: sg_readcap [--brief] [--help] [--hex] [--lba=LBA] "
+ "[--long] [--16]\n"
" [--pmi] [--raw] [--readonly] [--verbose] "
"[--version]\n"
- " DEVICE\n"
+ " [--zbc] DEVICE\n"
" where:\n"
" --brief|-b brief, two hex numbers: number of blocks "
"and block size\n"
@@ -97,15 +103,17 @@ static void usage()
" --readonly|-R open DEVICE read-only (def: RCAP(16) "
"read-write)\n"
" --verbose|-v increase verbosity\n"
- " --version|-V print version string and exit\n\n"
+ " --version|-V print version string and exit\n"
+ " --zbc|-z show rc_basis ZBC field (implies --16)\n\n"
"Perform a SCSI READ CAPACITY (10 or 16) command\n");
}
-static void usage_old()
+static void
+usage_old()
{
fprintf(stderr, "Usage: sg_readcap [-16] [-b] [-h] [-H] [-lba=LBA] "
- "[-pmi] [-r] [-R] [-v] [-V]\n"
- " DEVICE\n"
+ "[-pmi] [-r] [-R]\n"
+ " [-v] [-V] [-z] DEVICE\n"
" where:\n"
" -16 use READ CAPACITY (16) cdb (def: use "
"10 byte cdb)\n"
@@ -123,11 +131,13 @@ static void usage_old()
" -r output response in binary to stdout\n"
" -R open DEVICE read-only (def: RCAP(16) read-write)\n"
" -v increase verbosity\n"
- " -V print version string and exit\n\n"
- "Perform a SCSI READ CAPACITY command\n");
+ " -V print version string and exit\n"
+ " -z show rc_basis ZBC field (implies -16)\n\n"
+ "Perform a SCSI READ CAPACITY (10 or 16) command\n");
}
-static void usage_for(const struct opts_t * op)
+static void
+usage_for(const struct opts_t * op)
{
if (op->opt_new)
usage();
@@ -135,7 +145,8 @@ static void usage_for(const struct opts_t * op)
usage_old();
}
-static int process_cl_new(struct opts_t * op, int argc, char * argv[])
+static int
+process_cl_new(struct opts_t * op, int argc, char * argv[])
{
int c;
int a_one = 0;
@@ -144,7 +155,7 @@ static int process_cl_new(struct opts_t * op, int argc, char * argv[])
while (1) {
int option_index = 0;
- c = getopt_long(argc, argv, "16bhHlL:NOprRvV", long_options,
+ c = getopt_long(argc, argv, "16bhHlL:NOprRvVz", long_options,
&option_index);
if (c == -1)
break;
@@ -203,6 +214,9 @@ static int process_cl_new(struct opts_t * op, int argc, char * argv[])
case 'V':
++op->do_version;
break;
+ case 'z':
+ ++op->do_zbc;
+ break;
default:
fprintf(stderr, "unrecognised option code %c [0x%x]\n", c, c);
if (op->do_help)
@@ -227,7 +241,8 @@ static int process_cl_new(struct opts_t * op, int argc, char * argv[])
return 0;
}
-static int process_cl_old(struct opts_t * op, int argc, char * argv[])
+static int
+process_cl_old(struct opts_t * op, int argc, char * argv[])
{
int k, jmp_out, plen, num;
const char * cp;
@@ -284,6 +299,9 @@ static int process_cl_old(struct opts_t * op, int argc, char * argv[])
case 'V':
++op->do_version;
break;
+ case 'z':
+ ++op->do_zbc;
+ break;
default:
jmp_out = 1;
break;
@@ -324,7 +342,8 @@ static int process_cl_old(struct opts_t * op, int argc, char * argv[])
return 0;
}
-static int process_cl(struct opts_t * op, int argc, char * argv[])
+static int
+process_cl(struct opts_t * op, int argc, char * argv[])
{
int res;
char * cp;
@@ -344,7 +363,8 @@ static int process_cl(struct opts_t * op, int argc, char * argv[])
return res;
}
-static void dStrRaw(const char* str, int len)
+static void
+dStrRaw(const char* str, int len)
{
int k;
@@ -352,12 +372,31 @@ static void dStrRaw(const char* str, int len)
printf("%c", str[k]);
}
-int main(int argc, char * argv[])
+static const char *
+rc_basis_str(int rc_basis, char * b, int blen)
+{
+ switch (rc_basis) {
+ case 0:
+ snprintf(b, blen, "last contiguous that's not seq write required");
+ break;
+ case 1:
+ snprintf(b, blen, "last LBA on device");
+ break;
+ default:
+ snprintf(b, blen, "reserved (0x%x)", rc_basis);
+ break;
+ }
+ return b;
+}
+
+
+int
+main(int argc, char * argv[])
{
- int sg_fd, k, res, prot_en, p_type, lbppbe, rw_0_flag;
+ int sg_fd, res, prot_en, p_type, lbppbe, rw_0_flag;
uint64_t llast_blk_addr;
int ret = 0;
- unsigned int last_blk_addr, block_size;
+ uint32_t last_blk_addr, block_size;
unsigned char resp_buff[RCAP16_REPLY_LEN];
char b[80];
struct opts_t opts;
@@ -388,6 +427,10 @@ int main(int argc, char * argv[])
return SG_LIB_FILE_ERROR;
}
}
+ if (op->do_zbc) {
+ if (! op->do_long)
+ ++op->do_long;
+ }
memset(resp_buff, 0, sizeof(resp_buff));
@@ -415,27 +458,29 @@ int main(int argc, char * argv[])
if (op->do_hex || op->do_raw) {
if (op->do_raw)
dStrRaw((const char *)resp_buff, RCAP_REPLY_LEN);
+ else if (op->do_hex > 2)
+ dStrHex((const char *)resp_buff, RCAP_REPLY_LEN, -1);
else
dStrHex((const char *)resp_buff, RCAP_REPLY_LEN, 1);
goto good;
}
- last_blk_addr = ((resp_buff[0] << 24) | (resp_buff[1] << 16) |
- (resp_buff[2] << 8) | resp_buff[3]);
+ last_blk_addr = sg_get_unaligned_be32(resp_buff + 0);
if (0xffffffff != last_blk_addr) {
- block_size = ((resp_buff[4] << 24) | (resp_buff[5] << 16) |
- (resp_buff[6] << 8) | resp_buff[7]);
+ block_size = sg_get_unaligned_be32(resp_buff + 4);
if (op->do_brief) {
- printf("0x%x 0x%x\n", last_blk_addr + 1, block_size);
+ printf("0x%" PRIx32 " 0x%" PRIx32 "\n",
+ last_blk_addr + 1, block_size);
goto good;
}
printf("Read Capacity results:\n");
if (op->do_pmi)
printf(" PMI mode: given lba=0x%" PRIx64 ", last lba "
- "before delay=0x%x\n", op->llba, last_blk_addr);
+ "before delay=0x%" PRIx32 "\n", op->llba,
+ last_blk_addr);
else
- printf(" Last logical block address=%u (0x%x), Number "
- "of blocks=%u\n", last_blk_addr, last_blk_addr,
- last_blk_addr + 1);
+ printf(" Last logical block address=%" PRIu32 " (0x%"
+ PRIx32 "), Number of blocks=%" PRIu32 "\n",
+ last_blk_addr, last_blk_addr, last_blk_addr + 1);
printf(" Logical block length=%u bytes\n", block_size);
if (! op->do_pmi) {
uint64_t total_sz = last_blk_addr + 1;
@@ -486,18 +531,17 @@ int main(int argc, char * argv[])
if (op->do_hex || op->do_raw) {
if (op->do_raw)
dStrRaw((const char *)resp_buff, RCAP16_REPLY_LEN);
+ else if (op->do_hex > 2)
+ dStrHex((const char *)resp_buff, RCAP16_REPLY_LEN, -1);
else
dStrHex((const char *)resp_buff, RCAP16_REPLY_LEN, 1);
goto good;
}
- for (k = 0, llast_blk_addr = 0; k < 8; ++k) {
- llast_blk_addr <<= 8;
- llast_blk_addr |= resp_buff[k];
- }
- block_size = ((resp_buff[8] << 24) | (resp_buff[9] << 16) |
- (resp_buff[10] << 8) | resp_buff[11]);
+ llast_blk_addr = sg_get_unaligned_be64(resp_buff + 0);
+ block_size = sg_get_unaligned_be32(resp_buff + 8);
if (op->do_brief) {
- printf("0x%" PRIx64 " 0x%x\n", llast_blk_addr + 1, block_size);
+ printf("0x%" PRIx64 " 0x%" PRIx32 "\n", llast_blk_addr + 1,
+ block_size);
goto good;
}
prot_en = !!(resp_buff[12] & 0x1);
@@ -509,6 +553,12 @@ int main(int argc, char * argv[])
printf(" [type %d protection]\n", p_type + 1);
else
printf("\n");
+ if (op->do_zbc) {
+ int rc_basis = (resp_buff[12] >> 4) & 0x3;
+
+ printf(" ZBC's rc_basis=%d [%s]\n", rc_basis,
+ rc_basis_str(rc_basis, b, sizeof(b)));
+ }
printf(" Logical block provisioning: lbpme=%d, lbprz=%d\n",
!!(resp_buff[14] & 0x80), !!(resp_buff[14] & 0x40));
if (op->do_pmi)
@@ -519,7 +569,7 @@ int main(int argc, char * argv[])
printf(" Last logical block address=%" PRIu64 " (0x%"
PRIx64 "), Number of logical blocks=%" PRIu64 "\n",
llast_blk_addr, llast_blk_addr, llast_blk_addr + 1);
- printf(" Logical block length=%u bytes\n", block_size);
+ printf(" Logical block length=%" PRIu32 " bytes\n", block_size);
lbppbe = resp_buff[13] & 0xf;
printf(" Logical blocks per physical block exponent=%d",
lbppbe);
diff --git a/src/sg_senddiag.c b/src/sg_senddiag.c
index 9dc148f2..1a7c6e1e 100644
--- a/src/sg_senddiag.c
+++ b/src/sg_senddiag.c
@@ -27,7 +27,7 @@
#include "sg_unaligned.h"
-static const char * version_str = "0.44 20140919";
+static const char * version_str = "0.45 20141219";
#define ME "sg_senddiag: "
@@ -675,8 +675,7 @@ main(int argc, char * argv[])
fprintf(stderr, "unable to allocate %d bytes\n", op->maxlen);
return SG_LIB_CAT_OTHER;
}
- if (build_diag_page(op->raw_arg, read_in, &read_in_len,
- sizeof(read_in))) {
+ if (build_diag_page(op->raw_arg, read_in, &read_in_len, op->maxlen)) {
if (op->opt_new) {
printf("Bad sequence after '--raw=' option\n");
usage();
diff --git a/src/sg_ses.c b/src/sg_ses.c
index 5f1f6161..e5828895 100644
--- a/src/sg_ses.c
+++ b/src/sg_ses.c
@@ -22,6 +22,7 @@
#include "sg_lib.h"
#include "sg_cmds_basic.h"
#include "sg_cmds_extra.h"
+#include "sg_unaligned.h"
#include "sg_pt.h" /* needed for scsi_pt_win32_direct() */
/*
@@ -29,7 +30,7 @@
* commands tailored for SES (enclosure) devices.
*/
-static const char * version_str = "2.00 20141215"; /* ses3r08 */
+static const char * version_str = "2.00 20141219"; /* ses3r08 */
#define MX_ALLOC_LEN ((64 * 1024) - 4) /* max allowable for big enclosures */
#define MX_ELEM_HDR 1024
@@ -1362,7 +1363,7 @@ do_rec_diag(int sg_fd, int page_code, unsigned char * rsp_buff,
res = sg_ll_receive_diag(sg_fd, 1 /* pcv */, page_code, rsp_buff,
rsp_buff_size, 1, op->verbose);
if (0 == res) {
- rsp_len = (rsp_buff[2] << 8) + rsp_buff[3] + 4;
+ rsp_len = sg_get_unaligned_be16(rsp_buff + 2) + 4;
if (rsp_len > rsp_buff_size) {
if (rsp_buff_size > 8) /* tried to get more than header */
pr2serr("<<< warning response buffer too small [%d but need "
@@ -1414,7 +1415,7 @@ static void
ses_configuration_sdg(const unsigned char * resp, int resp_len)
{
int j, k, el, num_subs, sum_elem_types;
- unsigned int gen_code;
+ uint32_t gen_code;
const unsigned char * ucp;
const unsigned char * last_ucp;
const unsigned char * text_ucp;
@@ -1428,9 +1429,8 @@ ses_configuration_sdg(const unsigned char * resp, int resp_len)
last_ucp = resp + resp_len - 1;
printf(" number of secondary subenclosures: %d\n",
num_subs - 1);
- gen_code = (resp[4] << 24) | (resp[5] << 16) |
- (resp[6] << 8) | resp[7];
- printf(" generation code: 0x%x\n", gen_code);
+ gen_code = sg_get_unaligned_be32(resp + 4);
+ printf(" generation code: 0x%" PRIx32 "\n", gen_code);
printf(" enclosure descriptor list\n");
ucp = resp + 8;
for (k = 0; k < num_subs; ++k, ucp += el) {
@@ -1491,13 +1491,13 @@ truncated:
* if there is a problem */
static int
populate_type_desc_hdr_arr(int fd, struct type_desc_hdr_t * tdhp,
- unsigned int * generationp,
+ uint32_t * generationp,
struct enclosure_info * primary_ip,
struct opts_t * op)
{
int resp_len, k, el, num_subs, sum_type_dheaders, res, n;
int ret = 0;
- unsigned int gen_code;
+ uint32_t gen_code;
unsigned char * resp;
const unsigned char * ucp;
const unsigned char * last_ucp;
@@ -1522,8 +1522,7 @@ populate_type_desc_hdr_arr(int fd, struct type_desc_hdr_t * tdhp,
num_subs = resp[1] + 1;
sum_type_dheaders = 0;
last_ucp = resp + resp_len - 1;
- gen_code = (resp[4] << 24) | (resp[5] << 16) |
- (resp[6] << 8) | resp[7];
+ gen_code = sg_get_unaligned_be32(resp + 4);
if (generationp)
*generationp = gen_code;
ucp = resp + 8;
@@ -1674,10 +1673,27 @@ find_sas_connector_type(int conn_type, char * buff, int buff_len)
snprintf(buff, buff_len, "Micro SAS/SATA plug (SFF-8486) "
"[max 2 phys]");
break;
+ case 0x28:
+ snprintf(buff, buff_len, "12 Gb/s SAS drive backplane receptacle "
+ "(SFF-8680) [max 2 phys]");
+ break;
+ case 0x29:
+ snprintf(buff, buff_len, "12 Gb/s SAS drive plug (SFF-8680) [max 2 "
+ "phys]");
+ break;
+ case 0x2a:
+ snprintf(buff, buff_len, "Multifunction 12 Gb/s 6x unshielded "
+ "receptacle (SFF-8639)");
+ break;
+ case 0x2b:
+ snprintf(buff, buff_len, "Multifunction 12 Gb/s 6x unshielded plug "
+ "(SFF-8639)");
+ break;
case 0x2f:
snprintf(buff, buff_len, "SAS virtual connector [max 1 phy]");
break;
- case 0x3f: snprintf(buff, buff_len, "Vendor specific internal connector");
+ case 0x3f:
+ snprintf(buff, buff_len, "Vendor specific internal connector");
break;
default:
if (conn_type < 0x10)
@@ -1843,7 +1859,7 @@ enc_status_helper(const char * pad, const unsigned char * statp, int etype,
!!(statp[2] & 0x1));
break;
case NV_CACHE_ETC: /* Non volatile cache */
- res = (statp[2] << 8) + statp[3];
+ res = sg_get_unaligned_be16(statp + 2);
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);
@@ -1859,7 +1875,7 @@ enc_status_helper(const char * pad, const unsigned char * statp, int etype,
break;
case 1:
printf("%sByte offset=%d, bit number=%d\n", pad,
- (statp[2] << 8) + statp[3], (statp[1] & 7));
+ sg_get_unaligned_be16(statp + 2), (statp[1] & 7));
break;
case 2:
case 3:
@@ -1892,11 +1908,20 @@ enc_status_helper(const char * pad, const unsigned char * statp, int etype,
}
break;
case DISPLAY_ETC: /* Display (ses2r15) */
- if (nofilter || (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]));
+ if (nofilter || (0xc0 & statp[1])) {
+ int dms = statp[1] & 0x3;
+ uint16_t dcs;
+
+ printf("%sIdent=%d, Fail=%d, Display mode status=%d", pad,
+ !!(statp[1] & 0x80), !!(statp[1] & 0x40), dms);
+ if ((1 == dms) || (2 == dms)) {
+ dcs = sg_get_unaligned_be16(statp + 2);
+ printf(", Display character status=0x%x", dcs);
+ if (statp[2] && (0 == statp[3]))
+ printf(" ['%c']", statp[2]);
+ }
+ printf("\n");
+ }
break;
case KEY_PAD_ETC: /* Key pad entry */
if (nofilter || (0xc0 & statp[1]))
@@ -1946,10 +1971,10 @@ enc_status_helper(const char * pad, const unsigned char * statp, int etype,
}
#ifdef SG_LIB_MINGW
printf("%sVoltage: %g volts\n", pad,
- ((int)(short)((statp[2] << 8) + statp[3]) / 100.0));
+ ((int)(short)sg_get_unaligned_be16(statp + 2) / 100.0));
#else
printf("%sVoltage: %.2f volts\n", pad,
- ((int)(short)((statp[2] << 8) + statp[3]) / 100.0));
+ ((int)(short)sg_get_unaligned_be16(statp + 2) / 100.0));
#endif
break;
case CURR_SENSOR_ETC: /* Current sensor */
@@ -1959,10 +1984,10 @@ enc_status_helper(const char * pad, const unsigned char * statp, int etype,
!!(statp[1] & 0x8), !!(statp[1] & 0x2));
#ifdef SG_LIB_MINGW
printf("%sCurrent: %g amps\n", pad,
- ((int)(short)((statp[2] << 8) + statp[3]) / 100.0));
+ ((int)(short)sg_get_unaligned_be16(statp + 2) / 100.0));
#else
printf("%sCurrent: %.2f amps\n", pad,
- ((int)(short)((statp[2] << 8) + statp[3]) / 100.0));
+ ((int)(short)sg_get_unaligned_be16(statp + 2) / 100.0));
#endif
break;
case SCSI_TPORT_ETC: /* SCSI target port */
@@ -2039,11 +2064,11 @@ enc_status_helper(const char * pad, const unsigned char * statp, int etype,
* Display enclosure status diagnostic page. */
static void
ses_enc_status_dp(const struct type_desc_hdr_t * tdhp, int num_telems,
- unsigned int ref_gen_code, const unsigned char * resp,
+ uint32_t ref_gen_code, const unsigned char * resp,
int resp_len, const struct opts_t * op)
{
int j, k, elem_ind, match_ind_th, got1;
- unsigned int gen_code;
+ uint32_t gen_code;
const unsigned char * ucp;
const unsigned char * last_ucp;
char b[64];
@@ -2057,8 +2082,7 @@ ses_enc_status_dp(const struct type_desc_hdr_t * tdhp, int num_telems,
last_ucp = resp + resp_len - 1;
if (resp_len < 8)
goto truncated;
- gen_code = (resp[4] << 24) | (resp[5] << 16) |
- (resp[6] << 8) | resp[7];
+ gen_code = sg_get_unaligned_be32(resp + 4);
printf(" generation code: 0x%x\n", gen_code);
if (ref_gen_code != gen_code) {
pr2serr(" <<state of enclosure changed, please try again>>\n");
@@ -2176,11 +2200,11 @@ ses_threshold_helper(const char * pad, const unsigned char *tp, int etype,
/* DPC_THRESHOLD [0x5] */
static void
ses_threshold_sdg(const struct type_desc_hdr_t * tdhp, int num_telems,
- unsigned int ref_gen_code, const unsigned char * resp,
+ uint32_t ref_gen_code, const unsigned char * resp,
int resp_len, const struct opts_t * op)
{
int j, k, elem_ind, match_ind_th, got1;
- unsigned int gen_code;
+ uint32_t gen_code;
const unsigned char * ucp;
const unsigned char * last_ucp;
char b[64];
@@ -2192,9 +2216,8 @@ ses_threshold_sdg(const struct type_desc_hdr_t * tdhp, int num_telems,
last_ucp = resp + resp_len - 1;
if (resp_len < 8)
goto truncated;
- gen_code = (resp[4] << 24) | (resp[5] << 16) |
- (resp[6] << 8) | resp[7];
- printf(" generation code: 0x%x\n", gen_code);
+ gen_code = sg_get_unaligned_be32(resp + 4);
+ printf(" generation code: 0x%" PRIx32 "\n", gen_code);
if (ref_gen_code != gen_code) {
pr2serr(" <<state of enclosure changed, please try again>>\n");
return;
@@ -2239,11 +2262,11 @@ truncated:
* elements. */
static void
ses_element_desc_sdg(const struct type_desc_hdr_t * tdhp, int num_telems,
- unsigned int ref_gen_code, const unsigned char * resp,
+ uint32_t ref_gen_code, const unsigned char * resp,
int resp_len, const struct opts_t * op)
{
int j, k, desc_len, elem_ind, match_ind_th, got1;
- unsigned int gen_code;
+ uint32_t gen_code;
const unsigned char * ucp;
const unsigned char * last_ucp;
const struct type_desc_hdr_t * tp;
@@ -2255,9 +2278,8 @@ ses_element_desc_sdg(const struct type_desc_hdr_t * tdhp, int num_telems,
last_ucp = resp + resp_len - 1;
if (resp_len < 8)
goto truncated;
- gen_code = (resp[4] << 24) | (resp[5] << 16) |
- (resp[6] << 8) | resp[7];
- printf(" generation code: 0x%x\n", gen_code);
+ gen_code = sg_get_unaligned_be32(resp + 4);
+ printf(" generation code: 0x%" PRIx32 "\n", gen_code);
if (ref_gen_code != gen_code) {
pr2serr(" <<state of enclosure changed, please try again>>\n");
return;
@@ -2267,7 +2289,7 @@ ses_element_desc_sdg(const struct type_desc_hdr_t * tdhp, int num_telems,
for (k = 0, got1 = 0, tp = tdhp; k < num_telems; ++k, ++tp) {
if ((ucp + 3) > last_ucp)
goto truncated;
- desc_len = (ucp[2] << 8) + ucp[3] + 4;
+ desc_len = sg_get_unaligned_be16(ucp + 2) + 4;
match_ind_th = (op->ind_given && (k == op->ind_th));
if ((! op->ind_given) || (match_ind_th && (-1 == op->ind_indiv))) {
printf(" Element type: %s, subenclosure id: %d [ti=%d]\n",
@@ -2281,7 +2303,7 @@ ses_element_desc_sdg(const struct type_desc_hdr_t * tdhp, int num_telems,
}
for (ucp += desc_len, j = 0, elem_ind = 0; j < tp->num_elements;
++j, ucp += desc_len, ++elem_ind) {
- desc_len = (ucp[2] << 8) + ucp[3] + 4;
+ desc_len = sg_get_unaligned_be16(ucp + 2) + 4;
if (op->ind_given) {
if ((! match_ind_th) || (-1 == op->ind_indiv) ||
(elem_ind != op->ind_indiv))
@@ -2329,8 +2351,10 @@ additional_elem_helper(const char * pad, const unsigned char * ucp, int len,
int elem_type, const struct opts_t * op)
{
int ports, phys, j, m, desc_type, eip_offset, print_sas_addr, saddr_nz;
- const unsigned char * per_ucp;
int nofilter = ! op->do_filter;
+ uint16_t pcie_vid;
+ int pcie_pt, psn_valid, bdf_valid, cid_valid;
+ const unsigned char * per_ucp;
char b[64];
if (op->inner_hex) {
@@ -2470,8 +2494,54 @@ additional_elem_helper(const char * pad, const unsigned char * ucp, int len,
} else
printf("%sunrecognised descriptor type [%d]\n", pad, desc_type);
break;
- case TPROTO_PCIE:
- // added in ses3r08, still looking at this one
+ case TPROTO_PCIE: /* added in ses3r08 */
+ printf("%sTransport protocol: PCIe\n", pad);
+ if (0 == eip_offset) {
+ printf("%sfor this protocol EIP must be set (it isn't)\n", pad);
+ break;
+ }
+ if (len < 6)
+ break;
+ pcie_pt = (ucp[5] >> 5) & 0x7;
+ if (1 == pcie_pt)
+ printf("%sPCIe protocol type: NVMe\n", pad);
+ else {
+ printf("%sTransport protocol: PCIe subprotocol=0x%x not "
+ "decoded\n", pad, pcie_pt);
+ if (op->verbose)
+ dStrHex((const char *)ucp, len, 0);
+ break;
+ }
+ phys = ucp[4];
+ printf("%snumber of ports: %d, not all ports: %d", pad, phys,
+ ucp[5] & 1);
+ printf(", device slot number: %d\n", ucp[7]);
+
+ pcie_vid = sg_get_unaligned_le16(ucp + 10);
+ printf("%svendor id: 0x%" PRIx16 "%s\n", pad, pcie_vid,
+ (0xffff == pcie_vid) ? " (not reported)" : "");
+ printf("%sserial number: %.20s\n", pad, ucp + 12);
+ printf("%smodel number: %.40s\n", pad, ucp + 32);
+ per_ucp = ucp + 72;
+ for (j = 0; j < phys; ++j, per_ucp += 8) {
+ printf("%sport index: %d\n", pad, j);
+ psn_valid = !!(0x4 & per_ucp[0]);
+ bdf_valid = !!(0x2 & per_ucp[0]);
+ cid_valid = !!(0x1 & per_ucp[0]);
+ printf("%s PSN_VALID=%d, BDF_VALID=%d, CID_VALID=%d\n", pad,
+ psn_valid, bdf_valid, cid_valid);
+ if (cid_valid)
+ printf("%s controller id: 0x%" PRIx16 "\n", pad,
+ sg_get_unaligned_le16(per_ucp + 1));
+ if (bdf_valid)
+ printf("%s bus number: 0x%x, device number: 0x%x, "
+ "function number: 0x%x\n", pad, per_ucp[4],
+ (per_ucp[5] >> 3) & 0x1f, 0x7 & per_ucp[5]);
+ if (psn_valid)
+ printf("%s physical slot number: 0x%" PRIx16 "\n", pad,
+ 0x1fff & sg_get_unaligned_le16(per_ucp + 6));
+ }
+ break;
default:
printf("%sTransport protocol: %s not decoded\n", pad,
sg_get_trans_proto_str((0xf & ucp[0]), sizeof(b), b));
@@ -2486,12 +2556,12 @@ additional_elem_helper(const char * pad, const unsigned char * ucp, int len,
* to "additional" to allow for SAS expander and SATA devices */
static void
ses_additional_elem_sdg(const struct type_desc_hdr_t * tdhp, int num_telems,
- unsigned int ref_gen_code, const unsigned char * resp,
+ uint32_t ref_gen_code, const unsigned char * resp,
int resp_len, const struct opts_t * op)
{
int j, k, desc_len, elem_type, invalid, el_num, eip, ind, match_ind_th;
int elem_count, ei, eiioe, my_eiioe_force, num_elems, skip;
- unsigned int gen_code;
+ uint32_t gen_code;
const unsigned char * ucp;
const unsigned char * last_ucp;
const struct type_desc_hdr_t * tp;
@@ -2501,9 +2571,8 @@ ses_additional_elem_sdg(const struct type_desc_hdr_t * tdhp, int num_telems,
if (resp_len < 4)
goto truncated;
last_ucp = resp + resp_len - 1;
- gen_code = (resp[4] << 24) | (resp[5] << 16) |
- (resp[6] << 8) | resp[7];
- printf(" generation code: 0x%x\n", gen_code);
+ gen_code = sg_get_unaligned_be32(resp + 4);
+ printf(" generation code: 0x%" PRIx32 "\n", gen_code);
if (ref_gen_code != gen_code) {
pr2serr(" <<state of enclosure changed, please try again>>\n");
return;
@@ -2595,7 +2664,7 @@ static void
ses_subenc_help_sdg(const unsigned char * resp, int resp_len)
{
int k, el, num_subs;
- unsigned int gen_code;
+ uint32_t gen_code;
const unsigned char * ucp;
const unsigned char * last_ucp;
@@ -2606,14 +2675,13 @@ ses_subenc_help_sdg(const unsigned char * resp, int resp_len)
last_ucp = resp + resp_len - 1;
printf(" number of secondary subenclosures: %d\n",
num_subs - 1);
- gen_code = (resp[4] << 24) | (resp[5] << 16) |
- (resp[6] << 8) | resp[7];
- printf(" generation code: 0x%x\n", gen_code);
+ gen_code = sg_get_unaligned_be32(resp + 4);
+ printf(" generation code: 0x%" PRIx32 "\n", gen_code);
ucp = resp + 8;
for (k = 0; k < num_subs; ++k, ucp += el) {
if ((ucp + 3) > last_ucp)
goto truncated;
- el = (ucp[2] << 8) + ucp[3] + 4;
+ el = sg_get_unaligned_be16(ucp + 2) + 4;
printf(" subenclosure identifier: %d\n", ucp[1]);
if (el > 4)
printf(" %.*s\n", el - 4, ucp + 4);
@@ -2631,7 +2699,7 @@ static void
ses_subenc_string_sdg(const unsigned char * resp, int resp_len)
{
int k, j, el, num_subs;
- unsigned int gen_code;
+ uint32_t gen_code;
const unsigned char * ucp;
const unsigned char * last_ucp;
@@ -2640,16 +2708,14 @@ ses_subenc_string_sdg(const unsigned char * resp, int resp_len)
goto truncated;
num_subs = resp[1] + 1; /* number of subenclosures (add 1 for primary) */
last_ucp = resp + resp_len - 1;
- printf(" number of secondary subenclosures: %d\n",
- num_subs - 1);
- gen_code = (resp[4] << 24) | (resp[5] << 16) |
- (resp[6] << 8) | resp[7];
- printf(" generation code: 0x%x\n", gen_code);
+ printf(" number of secondary subenclosures: %d\n", num_subs - 1);
+ gen_code = sg_get_unaligned_be32(resp + 4);
+ printf(" generation code: 0x%" PRIx32 "\n", gen_code);
ucp = resp + 8;
for (k = 0; k < num_subs; ++k, ucp += el) {
if ((ucp + 3) > last_ucp)
goto truncated;
- el = (ucp[2] << 8) + ucp[3] + 4;
+ el = sg_get_unaligned_be16(ucp + 2) + 4;
printf(" subenclosure identifier: %d\n", ucp[1]);
if (el > 4) {
/* dStrHex((const char *)(ucp + 4), el - 4, 0); */
@@ -2674,7 +2740,7 @@ static void
ses_subenc_nickname_sdg(const unsigned char * resp, int resp_len)
{
int k, el, num_subs;
- unsigned int gen_code;
+ uint32_t gen_code;
const unsigned char * ucp;
const unsigned char * last_ucp;
@@ -2685,9 +2751,8 @@ ses_subenc_nickname_sdg(const unsigned char * resp, int resp_len)
last_ucp = resp + resp_len - 1;
printf(" number of secondary subenclosures: %d\n",
num_subs - 1);
- gen_code = (resp[4] << 24) | (resp[5] << 16) |
- (resp[6] << 8) | resp[7];
- printf(" generation code: 0x%x\n", gen_code);
+ gen_code = sg_get_unaligned_be32(resp + 4);
+ printf(" generation code: 0x%" PRIx32 "\n", gen_code);
ucp = resp + 8;
el = 40;
for (k = 0; k < num_subs; ++k, ucp += el) {
@@ -2771,7 +2836,7 @@ static void
ses_download_code_sdg(const unsigned char * resp, int resp_len)
{
int k, num_subs;
- unsigned int gen_code;
+ uint32_t gen_code;
const unsigned char * ucp;
const unsigned char * last_ucp;
const char * cp;
@@ -2783,9 +2848,8 @@ ses_download_code_sdg(const unsigned char * resp, int resp_len)
last_ucp = resp + resp_len - 1;
printf(" number of secondary subenclosures: %d\n",
num_subs - 1);
- gen_code = (resp[4] << 24) | (resp[5] << 16) |
- (resp[6] << 8) | resp[7];
- printf(" generation code: 0x%x\n", gen_code);
+ gen_code = sg_get_unaligned_be32(resp + 4);
+ printf(" generation code: 0x%" PRIx32 "\n", gen_code);
ucp = resp + 8;
for (k = 0; k < num_subs; ++k, ucp += 16) {
if ((ucp + 3) > last_ucp)
@@ -2801,10 +2865,10 @@ ses_download_code_sdg(const unsigned char * resp, int resp_len)
printf(" download microcode status: 0x%x [additional "
"status: 0x%x]\n", ucp[2], ucp[3]);
printf(" download microcode maximum size: %d bytes\n",
- (ucp[4] << 24) + (ucp[5] << 16) + (ucp[6] << 8) + ucp[7]);
+ sg_get_unaligned_be32(ucp + 4));
printf(" download microcode expected buffer id: 0x%x\n", ucp[11]);
printf(" download microcode expected buffer id offset: %d\n",
- (ucp[12] << 24) + (ucp[13] << 16) + (ucp[14] << 8) + ucp[15]);
+ sg_get_unaligned_be32(ucp + 12));
}
return;
truncated:
@@ -2970,7 +3034,7 @@ ses_process_status_page(int sg_fd, struct opts_t * op)
{
int j, resp_len, res;
int ret = 0;
- unsigned int ref_gen_code;
+ uint32_t ref_gen_code;
unsigned char * resp;
const char * cp;
struct enclosure_info primary_info;
@@ -2995,12 +3059,16 @@ ses_process_status_page(int sg_fd, struct opts_t * op)
dStrRaw((const char *)resp, resp_len);
}
} else if (op->do_hex) {
- if (cp)
- printf("Response in hex from diagnostic page: %s\n", cp);
- else
- printf("Response in hex from unknown diagnostic page "
- "[0x%x]\n", op->page_code);
- dStrHex((const char *)resp, resp_len, 0);
+ if (op->do_hex > 2)
+ dStrHex((const char *)resp, resp_len, -1);
+ else {
+ if (cp)
+ printf("Response in hex from diagnostic page: %s\n", cp);
+ else
+ printf("Response in hex from unknown diagnostic page "
+ "[0x%x]\n", op->page_code);
+ dStrHex((const char *)resp, resp_len, (2 == op->do_hex));
+ }
} else {
memset(&primary_info, 0, sizeof(primary_info));
switch (op->page_code) {
@@ -3157,7 +3225,8 @@ devslotnum_and_sasaddr(struct join_row_t * jrp, unsigned char * ae_ucp)
}
break;
case TPROTO_PCIE:
- // added in ses3r08, still looking at this one
+ jrp->dev_slot_num = ae_ucp[7];
+ break;
default:
;
}
@@ -3172,7 +3241,7 @@ join_work(int sg_fd, struct opts_t * op, int display)
{
int k, j, res, num_t_hdrs, elem_ind, ei, desc_len, dn_len;
int et4aes, broken_ei, ei2, got1, jr_max_ind, mlen;
- unsigned int ref_gen_code, gen_code;
+ uint32_t ref_gen_code, gen_code;
struct join_row_t * jrp;
struct join_row_t * jr2p;
unsigned char * es_ucp;
@@ -3213,8 +3282,7 @@ join_work(int sg_fd, struct opts_t * op, int display)
pr2serr("Enclosure Status response too short\n");
return -1;
}
- gen_code = (enc_stat_rsp[4] << 24) | (enc_stat_rsp[5] << 16) |
- (enc_stat_rsp[6] << 8) | enc_stat_rsp[7];
+ gen_code = sg_get_unaligned_be32(enc_stat_rsp + 4);
if (ref_gen_code != gen_code) {
pr2serr("%s", enc_state_changed);
return -1;
@@ -3232,8 +3300,7 @@ join_work(int sg_fd, struct opts_t * op, int display)
pr2serr("Element Descriptor response too short\n");
return -1;
}
- gen_code = (elem_desc_rsp[4] << 24) | (elem_desc_rsp[5] << 16) |
- (elem_desc_rsp[6] << 8) | elem_desc_rsp[7];
+ gen_code = sg_get_unaligned_be32(elem_desc_rsp + 4);
if (ref_gen_code != gen_code) {
pr2serr("%s", enc_state_changed);
return -1;
@@ -3260,8 +3327,7 @@ join_work(int sg_fd, struct opts_t * op, int display)
pr2serr("Additional Element Status response too short\n");
return -1;
}
- gen_code = (add_elem_rsp[4] << 24) | (add_elem_rsp[5] << 16) |
- (add_elem_rsp[6] << 8) | add_elem_rsp[7];
+ gen_code = sg_get_unaligned_be32(add_elem_rsp + 4);
if (ref_gen_code != gen_code) {
pr2serr("%s", enc_state_changed);
return -1;
@@ -3299,8 +3365,7 @@ join_work(int sg_fd, struct opts_t * op, int display)
pr2serr("Threshold In response too short\n");
return -1;
}
- gen_code = (threshold_rsp[4] << 24) | (threshold_rsp[5] << 16) |
- (threshold_rsp[6] << 8) | threshold_rsp[7];
+ gen_code = sg_get_unaligned_be32(threshold_rsp + 4);
if (ref_gen_code != gen_code) {
pr2serr("%s", enc_state_changed);
return -1;
@@ -3335,7 +3400,7 @@ join_work(int sg_fd, struct opts_t * op, int display)
es_ucp += 4;
jrp->elem_descp = ed_ucp;
if (ed_ucp)
- ed_ucp += (ed_ucp[2] << 8) + ed_ucp[3] + 4;
+ ed_ucp += sg_get_unaligned_be16(ed_ucp + 2) + 4;
jrp->add_elem_statp = NULL;
jrp->thresh_inp = t_ucp;
jrp->dev_slot_num = -1;
@@ -3360,7 +3425,7 @@ join_work(int sg_fd, struct opts_t * op, int display)
es_ucp += 4;
jrp->elem_descp = ed_ucp;
if (ed_ucp)
- ed_ucp += (ed_ucp[2] << 8) + ed_ucp[3] + 4;
+ ed_ucp += sg_get_unaligned_be16(ed_ucp + 2) + 4;
jrp->thresh_inp = t_ucp;
jrp->dev_slot_num = -1;
/* assume sas_addr[8] zeroed since it's static file scope */
@@ -3517,7 +3582,7 @@ try_again:
if (op->desc_name) {
if (NULL == ed_ucp)
continue;
- desc_len = (ed_ucp[2] << 8) + ed_ucp[3];
+ desc_len = sg_get_unaligned_be16(ed_ucp + 2);
/* some element descriptor strings have a trailing NULL and
* count it in their length; adjust */
if ('\0' == ed_ucp[4 + desc_len - 1])
@@ -3543,7 +3608,7 @@ try_again:
continue; /* when '-ff' and status!=OK, skip */
cp = find_element_tname(jrp->etype, b, sizeof(b));
if (ed_ucp) {
- desc_len = (ed_ucp[2] << 8) + ed_ucp[3] + 4;
+ desc_len = sg_get_unaligned_be16(ed_ucp + 2) + 4;
if (desc_len > 4)
printf("%.*s [%d,%d] Element type: %s\n", desc_len - 4,
(const char *)(ed_ucp + 4), jrp->el_ind_th,
@@ -3753,7 +3818,7 @@ cgs_enc_ctl_stat(int sg_fd, const struct join_row_t * jrp,
jrp->enc_statp[0] |= 0x80; /* set SELECT bit */
if (op->byte1_given)
enc_stat_rsp[1] = op->byte1;
- len = (enc_stat_rsp[2] << 8) + enc_stat_rsp[3] + 4;
+ len = sg_get_unaligned_be16(enc_stat_rsp + 2) + 4;
ret = do_senddiag(sg_fd, 1, enc_stat_rsp, len, 1, op->verbose);
if (ret) {
pr2serr("couldn't send Enclosure Control page\n");
@@ -3808,7 +3873,7 @@ cgs_threshold(int sg_fd, const struct join_row_t * jrp,
jrp->thresh_inp + s_byte, s_bit, n_bits);
if (op->byte1_given)
threshold_rsp[1] = op->byte1;
- len = (threshold_rsp[2] << 8) + threshold_rsp[3] + 4;
+ len = sg_get_unaligned_be16(threshold_rsp + 2) + 4;
ret = do_senddiag(sg_fd, 1, threshold_rsp, len, 1, op->verbose);
if (ret) {
pr2serr("couldn't send Threshold Out page\n");
@@ -3911,7 +3976,7 @@ ses_cgs(int sg_fd, const struct tuple_acronym_val * tavp,
ed_ucp = jrp->elem_descp;
if (NULL == ed_ucp)
continue;
- desc_len = (ed_ucp[2] << 8) + ed_ucp[3];
+ desc_len = sg_get_unaligned_be16(ed_ucp + 2);
/* some element descriptor strings have a trailing NULL and
* count it; adjust */
if ('\0' == ed_ucp[4 + desc_len - 1])
@@ -3987,10 +4052,11 @@ ses_set_nickname(int sg_fd, struct opts_t * op)
return -1;
}
if (op->verbose) {
- unsigned int gc;
+ uint32_t gc;
- gc = (b[4] << 24) + (b[5] << 16) + (b[6] << 8) + b[7];
- pr2serr("set_nickname: generation code from status page: %u\n", gc);
+ gc = sg_get_unaligned_be32(b + 4);
+ pr2serr("set_nickname: generation code from status page: %" PRIu32
+ "\n", gc);
}
b[0] = (unsigned char)DPC_SUBENC_NICKNAME; /* just in case */
b[1] = (unsigned char)op->seid;
@@ -4174,7 +4240,7 @@ main(int argc, char * argv[])
safe_strerror(-sg_fd));
return SG_LIB_FILE_ERROR;
}
- if (! (op->do_raw || have_cgs)) {
+ if (! (op->do_raw || have_cgs || (op->do_hex > 2))) {
if (sg_simple_inquiry(sg_fd, &inq_resp, 1, op->verbose)) {
pr2serr("%s doesn't respond to a SCSI INQUIRY\n", op->dev_name);
ret = SG_LIB_CAT_OTHER;
diff --git a/src/sg_vpd.c b/src/sg_vpd.c
index e9c26431..dec7956d 100644
--- a/src/sg_vpd.c
+++ b/src/sg_vpd.c
@@ -2810,20 +2810,20 @@ decode_zbdc_vpd(unsigned char * b, int len, int do_hex)
u = sg_get_unaligned_be32(b + 8);
printf(" Optimal number of open sequential write preferred zones: ");
if (0xffffffff == u)
- printf("0xffffffff\n");
+ printf("not reported\n");
else
printf("%" PRIu32 "\n", u);
u = sg_get_unaligned_be32(b + 12);
printf(" Optimal number of non-sequentially written sequential write "
"preferred zones: ");
if (0xffffffff == u)
- printf("0xffffffff\n");
+ printf("not reported\n");
else
printf("%" PRIu32 "\n", u);
u = sg_get_unaligned_be32(b + 16);
- printf(" Maximum number of open sequential write required: ");
+ printf(" Maximum number of open sequential write required zones: ");
if (0xffffffff == u)
- printf("0xffffffff\n");
+ printf("no limit\n");
else
printf("%" PRIu32 "\n", u);
}
diff --git a/src/sg_write_verify.c b/src/sg_write_verify.c
index e3ae094b..3b5944e9 100644
--- a/src/sg_write_verify.c
+++ b/src/sg_write_verify.c
@@ -33,7 +33,7 @@
#include "sg_pt.h"
#include "sg_cmds_basic.h"
-static const char * version_str = "1.05 20141107";
+static const char * version_str = "1.06 20141217";
#define ME "sg_write_verify: "
@@ -96,8 +96,8 @@ usage()
" --lba=LBA|-l LBA LBA of the first block to write "
"and verify;\n"
" no default, must be given\n"
- " --num=NUM|-n NUM number of logical blocks to write and "
- "verify\n"
+ " --num=NUM|-n NUM logical blocks to write and verify "
+ "(def: 1)\n"
" --repeat|-R while IF still has data to read, send "
"another\n"
" command, bumping LBA with up to NUM "