diff options
-rw-r--r-- | COVERAGE | 5 | ||||
-rw-r--r-- | ChangeLog | 16 | ||||
-rw-r--r-- | README | 6 | ||||
-rw-r--r-- | debian/changelog | 2 | ||||
-rw-r--r-- | doc/sg_logs.8 | 7 | ||||
-rw-r--r-- | doc/sg_ses.8 | 6 | ||||
-rw-r--r-- | lib/sg_lib_data.c | 3 | ||||
-rw-r--r-- | scripts/55-scsi-sg3_id.rules | 13 | ||||
-rw-r--r-- | scripts/58-scsi-sg3_symlink.rules | 25 | ||||
-rwxr-xr-x | scripts/rescan-scsi-bus.sh | 53 | ||||
-rw-r--r-- | sg3_utils.spec | 2 | ||||
-rw-r--r-- | src/sg_inq.c | 34 | ||||
-rw-r--r-- | src/sg_logs.c | 145 | ||||
-rw-r--r-- | src/sg_readcap.c | 152 | ||||
-rw-r--r-- | src/sg_senddiag.c | 5 | ||||
-rw-r--r-- | src/sg_ses.c | 258 | ||||
-rw-r--r-- | src/sg_vpd.c | 8 | ||||
-rw-r--r-- | src/sg_write_verify.c | 6 |
18 files changed, 480 insertions, 266 deletions
@@ -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 @@ -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 @@ -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 " |