]> git.proxmox.com Git - mirror_smartmontools-debian.git/commitdiff
Imported Upstream version 5.39.1+svn3077
authorGiuseppe Iuculano <iuculano@debian.org>
Fri, 26 Mar 2010 20:37:06 +0000 (21:37 +0100)
committerGiuseppe Iuculano <iuculano@debian.org>
Fri, 26 Mar 2010 20:37:06 +0000 (21:37 +0100)
22 files changed:
CHANGELOG
INSTALL
Makefile.am
NEWS
atacmds.cpp
atacmds.h
ataprint.cpp
ataprint.h
configure.in
drivedb.h
os_freebsd.cpp
os_linux.cpp
os_win32.cpp
os_win32/smartctl_vc8.vcproj
os_win32/smartd_vc8.vcproj
scsiata.cpp
smartctl.8.in
smartctl.cpp
smartd.8.in
smartd.conf.5.in
smartd.cpp
update-smart-drivedb.in [new file with mode: 0644]

index d1aef0213c9916c007f8b689d8c02bc12c48b50b..574545d943e743dd126739f765de23588a418b7d 100644 (file)
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -1,6 +1,6 @@
 CHANGELOG for smartmontools
 
-$Id: CHANGELOG 3060 2010-02-03 22:16:40Z chrfranke $
+$Id: CHANGELOG 3077 2010-03-16 20:48:06Z chrfranke $
 
 The most recent version of this file is:
 http://smartmontools.svn.sourceforge.net/viewvc/smartmontools/trunk/smartmontools/CHANGELOG?view=markup
@@ -43,6 +43,71 @@ NOTES FOR FUTURE RELEASES: see TODO file.
 
 <DEVELOPERS: ADDITIONS TO THE CHANGE LOG GO JUST BELOW HERE, PLEASE>
 
+  [CF] USB ID updates:
+       - LaCie Desktop Hard Drive
+       - Prolific PL2507 (unsupported)
+       - Seagate FreeAgent Go FW
+       - WD My Book Essential
+
+  [CF] Linux: Add '/dev/sd[a-c][a-z]' to smartd DEVICESCAN.
+
+  [CF] smartd: Other config entries may precede DEVICESCAN.
+       Very first step towards a more flexible device scanning.
+
+  [CF] Windows: Use '.win64' in names of 64-bit binary packages.
+       Use correct 'strip' program when cross-compiling.
+
+  [CF] Add update script to make targets 'dist' and 'clean',
+       set +x permission, update svn:ignore.
+
+  [CF] Add 'update-smart-drivedb' script (ticket #59).
+       The script updates the drive database from SVN.
+       It is installed if '--enable-drivedb' is configured.
+
+  [MS] drivedb.h updates:
+       - Seagate Medalist 1720
+       - SuperTalent UltraDrive GX SSD
+       - Intel X25-M SSD
+
+  [CF] Makefile.am: Fix unix2dos and makensis parameters to allow
+       to build the Windows installer on Linux also.
+
+  [CF] Makefile.am: Use a separate build rule for each man page to
+       avoid compatibility problems with BSD make.
+
+  [AS] drivedb.h updates:
+       - Fujitsu MHZ2 BK series
+
+  [MS] drivedb.h updates:
+       - SAMSUNG SpinPoint F3 series
+       - SAMSUNG SpinPoint F3 EG series
+       - SAMSUNG SpinPoint M5 series
+       - Western Digital Caviar Green 6400AADS
+       - more Western Digital VelociRaptor variants
+
+  [AS] FreeBSD: disable 48-bit commands in the ata_pass_through interface, 
+       there is no 48-bit support in the IOCATAREQUEST ioctl.
+
+  [CF] smartctl: Add option '-l scterc[,READTIME,WRITETIME]' to get/set
+       the SCT Error Recovery Control time limit (ticket #50).
+
+       Patch was provided by Richard Gregory:
+       http://www.csc.liv.ac.uk/~greg/projects/erc/
+       Modified for new ata_pass_through() interface.
+       Linux HPT fixes ommitted for now.
+
+  [CF] Fix SCT temperature table commands on big endian CPUs.
+
+  [MS] drivedb.h updates:
+       - more Seagate Momentus 5400.6 drives
+       - HP 500GB drive MM0500EANCR
+
+  [CF] Windows: Cleanup I/O-control declarations, rely on include
+       files if possible.
+
+  [CF] Windows: Compile fixes for 64-bit exe (EXPERIMENTAL).
+       Update build info in INSTALL file.
+
   [CF] drivedb.h update:
        - Patriot Torqx SSD (patch provided by Gianpaolo Cugola)
 
diff --git a/INSTALL b/INSTALL
index bb0f4d7b8825da4095d09f406550b8e1651eb6d0..0fd6a4c84f7157eec417c3ab582582e5e00b3bf4 100644 (file)
--- a/INSTALL
+++ b/INSTALL
@@ -1,7 +1,7 @@
 Smartmontools installation instructions
 =======================================
 
-$Id: INSTALL 3057 2010-02-03 20:56:41Z chrfranke $
+$Id: INSTALL 3074 2010-03-05 23:00:30Z chrfranke $
 
 Please also see the smartmontools home page:
 http://smartmontools.sourceforge.net/
@@ -443,20 +443,28 @@ To compile the Windows release with MinGW gcc on MSYS, use:
   Instead of using "make install", copy the .exe files into
   some directory in the PATH.
 
-To compile with MinGW gcc 3.x on Cygwin, use:
+To compile on Cygwin with MinGW gcc 3.x (option '-mno-cygwin'):
 
-  ./configure --build=i686-pc-mingw32
+  ./configure --build=i686-pc-mingw32 \
+               CC=gcc-3               \
+              CXX=g++-3
 
-  The above does not work if gcc 4.x is installed and selected as
-  default by /usr/sbin/alternatives.  If the configure command aborts
-  with error message '... does not support -mno-cygwin', select
-  gcc 3.x by:
+To cross-compile on Debian Linux with gcc-mingw32:
 
-  CC=gcc-3 CXX=g++-3 ./configure --build=i686-pc-mingw32
+  ./configure --build=$(./config.guess) \
+              --host=i686-pc-mingw32    \
+               CC=i586-mingw32msvc-gcc  \
+              CXX=i586-mingw32msvc-g++
 
-  Alternatively, a MinGW-targeted cross-compiler can be used if available:
+To compile statically linked 64-bit version with MinGW-w64:
 
-  ./configure --build=i686-pc-cygwin --host=i686-pc-mingw32
+  ./configure --build=$(./config.guess)  \
+              --host=x86_64-w64-mingw32   \
+              LDFLAGS=-static
+
+  Tested on Cygwin and Linux with MinGW-w64 from
+  http://mingw-w64.sourceforge.net/.
+  WARNING: 64-bit version is still EXPERIMENTAL.
 
 
 To build the Windows binary distribution, use:
@@ -484,6 +492,9 @@ To create a Windows installer, use:
   package. See http://nsis.sourceforge.net/ for documentation and
   download location.
 
+  It is also possible to (cross-)build the installer on Linux.
+  This was successfully tested on Debian with package "nsis".
+
 To both create and run the (interactive) installer, use:
 
   make install-win32
index fe1d2b348e5b724ea4388a7bb2d7e1c1dcb49d05..d2bc9222046e3b830f5b5ec4aec2d8a102278c33 100644 (file)
@@ -1,6 +1,6 @@
 ## Process this file with automake to produce Makefile.in
 #
-# $Id: Makefile.am 3059 2010-02-03 21:42:09Z chrfranke $
+# $Id: Makefile.am 3074 2010-03-05 23:00:30Z chrfranke $
 #
 
 @SET_MAKE@
@@ -25,6 +25,11 @@ endif
 sbin_PROGRAMS = smartd         \
                smartctl
 
+if ENABLE_DRIVEDB
+sbin_SCRIPTS = update-smart-drivedb
+endif
+
+
 smartd_SOURCES =  smartd.cpp      \
                   atacmdnames.cpp \
                   atacmdnames.h   \
@@ -238,6 +243,7 @@ EXTRA_DIST = smartd.initd.in                       \
              smartd.conf.5.in                      \
              smartd.conf                           \
              autogen.sh                            \
+             update-smart-drivedb.in               \
              os_darwin/SMART.in                    \
              os_darwin/StartupParameters.plist     \
              os_darwin/English_Localizable.strings \
@@ -258,6 +264,7 @@ CLEANFILES = smartd.conf.5      \
              smartd.conf.5.txt  \
              smartd.initd       \
              svnversion.h       \
+             update-smart-drivedb \
              SMART
 
 if SMARTD_SUFFIX
@@ -327,6 +334,11 @@ smartd.conf.5.in: smartd.8.in
        cat $(top_builddir)/tmp.tail >> $(srcdir)/smartd.conf.5.in
        rm -f $(top_builddir)/tmp.head $(top_builddir)/tmp.tail $(top_builddir)/tmp.directives
 
+update-smart-drivedb: update-smart-drivedb.in config.status
+       $(SHELL) ./config.status --file=$@
+       chmod +x $@
+
+
 if INSTALL_INITSCRIPT
 if OS_DARWIN
 initd_DATA = SMART                            \
@@ -444,15 +456,15 @@ MAN_FILTER = \
     $(MAN_SAVESTATES) | \
     $(MAN_ATTRIBUTELOG)
 
-if OS_FREEBSD
-.for file in $(man_MANS)
-${file}: $(srcdir)/${file}.in Makefile svnversion.h
-       cat ${.ALLSRC:M*.in} | $(MAN_FILTER) > $@
-.endfor
-else
-smart%: $(srcdir)/smart%.in Makefile svnversion.h
-       cat $< | $(MAN_FILTER) > $@
-endif
+# Implicit rule 'smart%: smart%.in ...' does not work with BSD make
+smartctl.8: smartctl.8.in Makefile svnversion.h
+       cat $(srcdir)/smartctl.8.in | $(MAN_FILTER) > $@
+
+smartd.8: smartd.8.in Makefile svnversion.h
+       cat $(srcdir)/smartd.8.in | $(MAN_FILTER) > $@
+
+smartd.conf.5: smartd.conf.5.in Makefile svnversion.h
+       cat $(srcdir)/smartd.conf.5.in | $(MAN_FILTER) > $@
 
 # Commands to convert man pages into .html and .txt
 # TODO: configure
@@ -508,9 +520,15 @@ check:
 if OS_WIN32_MINGW
 # Definitions for Windows distribution
 
-distdir_win32 = $(PACKAGE)-$(VERSION).win32
-distzip_win32 = $(PACKAGE)-$(VERSION).win32.zip
-distinst_win32= $(PACKAGE)-$(VERSION).win32-setup.exe
+if OS_WIN64
+win_bits = 64
+else
+win_bits = 32
+endif
+
+distdir_win32  = $(PACKAGE)-$(VERSION).win$(win_bits)
+distzip_win32  = $(PACKAGE)-$(VERSION).win$(win_bits).zip
+distinst_win32 = $(PACKAGE)-$(VERSION).win$(win_bits)-setup.exe
 
 exedir_win32 = $(distdir_win32)/bin
 docdir_win32 = $(distdir_win32)/doc
@@ -538,9 +556,10 @@ CLEANFILES += $(FILES_WIN32) $(exedir_win32)/syslogevt.exe \
               smartctl-nc.exe smartctl-nc.exe.tmp \
               distdir.mkdir syslogevt.check
 
-# Textfile converter from cygutils
-UNIX2DOS = unix2dos -D
-DOS2UNIX = dos2unix -U
+# Textfile converter from package cygutils or tofrodos
+# Note: Only use without options to be compatible with both packages
+UNIX2DOS = unix2dos
+DOS2UNIX = dos2unix
 
 # Build Windows distribution
 
@@ -558,11 +577,12 @@ $(distzip_win32): distdir.mkdir $(FILES_WIN32) syslogevt.check
        cd $(distdir_win32) && zip -9Dr ../$(distzip_win32) .
 
 # Build NSIS installer, try to locate makensis in default location first
+# Note: Only option character '-' is also compatible with Linux version of makensis
 $(distinst_win32): $(srcdir)/os_win32/installer.nsi distdir.mkdir $(FILES_WIN32) syslogevt.check
        @makensis="$(MAKENSIS)"; if [ -z "$$makensis" ]; then \
-         if [ ! -z "$$PROGRAMFILES" ] && "$$PROGRAMFILES/NSIS/makensis" /VERSION >/dev/null 2>&1; then \
+         if [ ! -z "$$PROGRAMFILES" ] && "$$PROGRAMFILES/NSIS/makensis" -VERSION >/dev/null 2>&1; then \
            makensis="$$PROGRAMFILES/NSIS/makensis"; \
-         elif makensis /VERSION >/dev/null 2>&1; then \
+         elif makensis -VERSION >/dev/null 2>&1; then \
            makensis=makensis; \
          else \
            echo 'makensis: command not found. Please download and install NSIS' 1>&2; \
@@ -572,8 +592,8 @@ $(distinst_win32): $(srcdir)/os_win32/installer.nsi distdir.mkdir $(FILES_WIN32)
        date=`sed -n 's,^.*DATE[^"]*"\([^"]*\)".*$$,\1,p' svnversion.h`; \
        rev=`sed -n 's,^.*REV[^"]*"\([^"]*\)".*$$,r\1,p' svnversion.h`; \
        verstr="$(PACKAGE_VERSION) $$date $$rev "$(BUILD_INFO); \
-       echo "$$makensis /V2 /NOCD /DINPDIR=$(distdir_win32) /DOUTFILE=$(distinst_win32) /DVERSTR='$$verstr' $(srcdir)/os_win32/installer.nsi"; \
-       "$$makensis" /V2 /NOCD /DINPDIR="$(distdir_win32)" /DOUTFILE="$(distinst_win32)" /DVERSTR="$$verstr" "$(srcdir)/os_win32/installer.nsi"
+       echo "$$makensis -V2 -NOCD -DINPDIR=$(distdir_win32) -DOUTFILE=$(distinst_win32) -DVERSTR='$$verstr' $(srcdir)/os_win32/installer.nsi"; \
+       "$$makensis" -V2 -NOCD -DINPDIR="$(distdir_win32)" -DOUTFILE="$(distinst_win32)" -DVERSTR="$$verstr" "$(srcdir)/os_win32/installer.nsi"
 
 cleandist-win32:
        rm -rf $(distdir_win32) distdir.mkdir syslogevt.check
@@ -591,7 +611,7 @@ syslogevt.check:
 
 $(exedir_win32)/%.exe: %.exe
        cp -p $< $@
-       strip -s $@
+       if test -n '$(STRIP)'; then $(STRIP) -s $@; else strip -s $@; fi
        touch -r $< $@
 
 $(docdir_win32)/%.html: %.html
diff --git a/NEWS b/NEWS
index 6892d0cd143f2648ab1ca0d8490fd40a1fb4b965..3e9241984f94194029efee5c35bf3689a38e1fb1 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -1,6 +1,6 @@
 smartmontools NEWS
 ------------------
-$Id: NEWS 3057 2010-02-03 20:56:41Z chrfranke $
+$Id: NEWS 3076 2010-03-12 22:23:08Z chrfranke $
 
 The most up-to-date version of this file is:
 http://smartmontools.svn.sourceforge.net/viewvc/smartmontools/trunk/smartmontools/NEWS?view=markup
@@ -8,11 +8,19 @@ http://smartmontools.svn.sourceforge.net/viewvc/smartmontools/trunk/smartmontool
 Date <Not released yet, please try current SVN>
 Summary: smartmontools release 5.40
 -----------------------------------------------------------
+- Other config entries may precede smartd DEVICESCAN.
 - Option '-v' allows to specify byte order of attribute raw value
 - configure: New default value for '--with-docdir'.
 - Drive database is in a separate source file 'drivedb.h'
   which can be downloaded from SVN.
+- New script 'update-smart-drivedb'.
 - smartd libcap-ng support, option '-C, --capabilities'.
+- smartctl option '-l scterc[,...]' to get/set the
+  SCT Error Recovery Control time limit.
+- Linux: Add '/dev/sd[a-c][a-z]' to smartd DEVICESCAN.
+- Windows: Support for 64-bit executables.
+- Windows: Support for cross compilation on Linux.
+- Fix SCT temperature table commands on big endian CPUs.
 
 Date 2010-01-28
 Summary: smartmontools release 5.39.1
index 06024e5231b195b34ce9c161cedf3685af7d64dd..663a5854dd7713583a2bde1eef35cc7aaf2c7703 100644 (file)
@@ -37,7 +37,7 @@
 #include "utility.h"
 #include "dev_ata_cmd_set.h" // for parsed_ata_device
 
-const char * atacmds_cpp_cvsid = "$Id: atacmds.cpp 3040 2010-01-18 20:57:39Z chrfranke $"
+const char * atacmds_cpp_cvsid = "$Id: atacmds.cpp 3065 2010-02-10 22:16:50Z chrfranke $"
                                  ATACMDS_H_CVSID;
 
 // for passing global control variables
@@ -2214,6 +2214,13 @@ int ataReadSCTTempHist(ata_device * device, ata_sct_temperature_history_table *
   cmd.function_code = 1; // Read table
   cmd.table_id      = 2; // Temperature History Table
 
+  // swap endian order if needed
+  if (isbigendian()) {
+    swapx(&cmd.action_code);
+    swapx(&cmd.function_code);
+    swapx(&cmd.table_id);
+  }
+
   // write command via SMART log page 0xe0
   if (smartcommandhandler(device, WRITE_LOG, 0xe0, (char *)&cmd)){
     syserror("Error Write SCT Data Table command failed");
@@ -2276,6 +2283,15 @@ int ataSetSCTTempInterval(ata_device * device, unsigned interval, bool persisten
   cmd.state         = interval;
   cmd.option_flags  = (persistent ? 0x01 : 0x00);
 
+  // swap endian order if needed
+  if (isbigendian()) {
+    swapx(&cmd.action_code);
+    swapx(&cmd.function_code);
+    swapx(&cmd.feature_code);
+    swapx(&cmd.state);
+    swapx(&cmd.option_flags);
+  }
+
   // write command via SMART log page 0xe0
   if (smartcommandhandler(device, WRITE_LOG, 0xe0, (char *)&cmd)){
     syserror("Error Write SCT Feature Control Command failed");
@@ -2294,6 +2310,96 @@ int ataSetSCTTempInterval(ata_device * device, unsigned interval, bool persisten
   return 0;
 }
 
+// Get/Set SCT Error Recovery Control
+static int ataGetSetSCTErrorRecoveryControltime(ata_device * device, unsigned type,
+                                                bool set, unsigned short & time_limit)
+{
+  // Check initial status
+  ata_sct_status_response sts;
+  if (ataReadSCTStatus(device, &sts))
+    return -1;
+
+  // Do nothing if other SCT command is executing
+  if (sts.ext_status_code == 0xffff) {
+    pout("Another SCT command is executing, abort Error Recovery Control\n"
+         "(SCT ext_status_code 0x%04x, action_code=%u, function_code=%u)\n",
+      sts.ext_status_code, sts.action_code, sts.function_code);
+    return -1;
+  }
+
+  ata_sct_error_recovery_control_command cmd; memset(&cmd, 0, sizeof(cmd));
+  // CAUTION: DO NOT CHANGE THIS VALUE (SOME ACTION CODES MAY ERASE DISK)
+  cmd.action_code    = 3; // Error Recovery Control command
+  cmd.function_code  = (set ? 1 : 2); // 1=Set timer, 2=Get timer
+  cmd.selection_code = type; // 1=Read timer, 2=Write timer
+  if (set)
+    cmd.time_limit   = time_limit;
+
+  // swap endian order if needed
+  if (isbigendian()) {
+    swapx(&cmd.action_code);
+    swapx(&cmd.function_code);
+    swapx(&cmd.selection_code);
+    swapx(&cmd.time_limit);
+  }
+
+  // write command via SMART log page 0xe0
+  // TODO: Debug output
+  ata_cmd_in in;
+  in.in_regs.command = ATA_SMART_CMD;
+  in.in_regs.lba_high = SMART_CYL_HI; in.in_regs.lba_mid = SMART_CYL_LOW;
+  in.in_regs.features = ATA_SMART_WRITE_LOG_SECTOR;
+  in.in_regs.lba_low = 0xe0;
+  in.set_data_out(&cmd, 1);
+
+  if (!set)
+    // Time limit returned in ATA registers
+    in.out_needed.sector_count = in.out_needed.lba_low = true;
+
+  ata_cmd_out out;
+  if (!device->ata_pass_through(in, out)) {
+    pout("Error Write SCT Error Recovery Control Command failed: %s\n", device->get_errmsg());
+    return -1;
+  }
+
+  // re-read and check SCT status
+  if (ataReadSCTStatus(device, &sts))
+    return -1;
+
+  if (!(sts.ext_status_code == 0 && sts.action_code == 3 && sts.function_code == (set ? 1 : 2))) {
+    pout("Error unexcepted SCT status 0x%04x (action_code=%u, function_code=%u)\n",
+      sts.ext_status_code, sts.action_code, sts.function_code);
+    return -1;
+  }
+
+  if (!set) {
+    // Check whether registers are properly returned by ioctl()
+    if (!(out.out_regs.sector_count.is_set() && out.out_regs.lba_low.is_set())) {
+      // TODO: Output register support should be checked within each ata_pass_through()
+      // implementation before command is issued.
+      pout("Error SMART WRITE LOG does not return COUNT and LBA_LOW register\n");
+      return -1;
+    }
+    // Return value to caller
+    time_limit = out.out_regs.sector_count | (out.out_regs.lba_low << 8);
+  }
+
+  return 0;
+}
+
+// Get SCT Error Recovery Control
+int ataGetSCTErrorRecoveryControltime(ata_device * device, unsigned type, unsigned short & time_limit)
+{
+  return ataGetSetSCTErrorRecoveryControltime(device, type, false/*get*/, time_limit);
+}
+
+// Set SCT Error Recovery Control
+int ataSetSCTErrorRecoveryControltime(ata_device * device, unsigned type, unsigned short time_limit)
+{
+  return ataGetSetSCTErrorRecoveryControltime(device, type, true/*set*/, time_limit);
+}
+
+
 // Print one self-test log entry.
 // Returns true if self-test showed an error.
 bool ataPrintSmartSelfTestEntry(unsigned testnum, unsigned char test_type,
index f0a15a0266ca1a8e4b803ae15fab239d34c4b504..8dc913a875a023e2af862723f4caa89889bfc362 100644 (file)
--- a/atacmds.h
+++ b/atacmds.h
@@ -26,7 +26,7 @@
 #ifndef ATACMDS_H_
 #define ATACMDS_H_
 
-#define ATACMDS_H_CVSID "$Id: atacmds.h 3020 2009-12-31 01:11:51Z dlukes $"
+#define ATACMDS_H_CVSID "$Id: atacmds.h 3065 2010-02-10 22:16:50Z chrfranke $"
 
 #include "dev_interface.h" // ata_device
 
@@ -543,6 +543,20 @@ struct ata_sct_status_response
 #pragma pack()
 ASSERT_SIZEOF_STRUCT(ata_sct_status_response, 512);
 
+// SCT Error Recovery Control command (send with SMART_WRITE_LOG page 0xe0)
+// Table 88 of T13/1699-D Revision 6a
+#pragma pack(1)
+struct ata_sct_error_recovery_control_command
+{
+  unsigned short action_code;       // 3 = Error Recovery Control
+  unsigned short function_code;     // 1 = Set, 2 = Return
+  unsigned short selection_code;    // 1 = Read Timer, 2 = Write Timer
+  unsigned short time_limit;        // If set: Recovery time limit in 100ms units
+  unsigned short words004_255[252]; // reserved
+} ATTR_PACKED;
+#pragma pack()
+ASSERT_SIZEOF_STRUCT(ata_sct_error_recovery_control_command, 512);
+
 // SCT Feature Control command (send with SMART_WRITE_LOG page 0xe0)
 // Table 72 of T13/1699-D Revision 3f
 #pragma pack(1)
@@ -552,8 +566,8 @@ struct ata_sct_feature_control_command
   unsigned short function_code;     // 1 = Set, 2 = Return, 3 = Return options
   unsigned short feature_code;      // 3 = Temperature logging interval
   unsigned short state;             // Interval
-  unsigned short option_flags;      // Bit 0: persistent, Bits 1-31: reserved
-  unsigned short words005_255[251]; // reserved 
+  unsigned short option_flags;      // Bit 0: persistent, Bits 1-15: reserved
+  unsigned short words005_255[251]; // reserved
 } ATTR_PACKED;
 #pragma pack()
 ASSERT_SIZEOF_STRUCT(ata_sct_feature_control_command, 512);
@@ -727,6 +741,10 @@ int ataReadSCTTempHist(ata_device * device, ata_sct_temperature_history_table *
 // Set SCT temperature logging interval
 int ataSetSCTTempInterval(ata_device * device, unsigned interval, bool persistent);
 
+// Get/Set SCT Error Recovery Control
+int ataGetSCTErrorRecoveryControltime(ata_device * device, unsigned type, unsigned short & time_limit);
+int ataSetSCTErrorRecoveryControltime(ata_device * device, unsigned type, unsigned short time_limit);
+
 
 /* Enable/Disable SMART on device */
 int ataEnableSmart (ata_device * device);
@@ -789,6 +807,9 @@ int isSupportSelectiveSelfTest(const ata_smart_values * data);
 inline bool isSCTCapable(const ata_identify_device *drive)
   { return !!(drive->words088_255[206-88] & 0x01); } // 0x01 = SCT support
 
+inline bool isSCTErrorRecoveryControlCapable(const ata_identify_device *drive)
+  { return ((drive->words088_255[206-88] & 0x09) == 0x09); } // 0x08 = SCT Error Recovery Control support
+
 inline bool isSCTFeatureControlCapable(const ata_identify_device *drive)
   { return ((drive->words088_255[206-88] & 0x11) == 0x11); } // 0x10 = SCT Feature Control support
 
index 11d6be95687e9b047e8bcd72dc168f1280a43fb3..30b7a0b995edf3d8f1e24be38e0ada89272d4001 100644 (file)
@@ -44,7 +44,7 @@
 #include "utility.h"
 #include "knowndrives.h"
 
-const char * ataprint_cpp_cvsid = "$Id: ataprint.cpp 3037 2010-01-16 20:07:13Z chrfranke $"
+const char * ataprint_cpp_cvsid = "$Id: ataprint.cpp 3065 2010-02-10 22:16:50Z chrfranke $"
                                   ATAPRINT_H_CVSID;
 
 // for passing global control variables
@@ -883,6 +883,8 @@ static void ataPrintSCTCapability(const ata_identify_device *drive)
   if (!(sctcaps & 0x01))
     return;
   pout("SCT capabilities: \t       (0x%04x)\tSCT Status supported.\n", sctcaps);
+  if (sctcaps & 0x08)
+    pout("\t\t\t\t\tSCT Error Recovery Control supported.\n");
   if (sctcaps & 0x10)
     pout("\t\t\t\t\tSCT Feature Control supported.\n");
   if (sctcaps & 0x20)
@@ -1698,6 +1700,20 @@ static int ataPrintSCTTempHist(const ata_sct_temperature_history_table * tmh)
   return 0;
 }
 
+// Print SCT Error Recovery Control timers
+static void ataPrintSCTErrorRecoveryControl(unsigned short read_timer, unsigned short write_timer)
+{
+  pout("SCT Error Recovery Control:\n");
+  if (!read_timer)
+    pout("           Read: Disabled\n");
+  else
+    pout("           Read: %6d (%0.1f seconds)\n", read_timer, read_timer/10.0);
+  if (!write_timer)
+    pout("          Write: Disabled\n");
+  else
+    pout("          Write: %6d (%0.1f seconds)\n", write_timer, write_timer/10.0);
+}
+
 
 // Compares failure type to policy in effect, and either exits or
 // simply returns to the calling routine.
@@ -2285,14 +2301,21 @@ int ataPrintMain (ata_device * device, const ata_print_options & options)
     }
   }
 
+  // SCT commands
+  bool sct_ok = false;
+  if (   options.sct_temp_sts || options.sct_temp_hist || options.sct_temp_int
+      || options.sct_erc_get  || options.sct_erc_set                          ) {
+    if (!isSCTCapable(&drive)) {
+      pout("Warning: device does not support SCT Commands\n");
+      failuretest(OPTIONAL_CMD, returnval|=FAILSMART);
+    }
+    else
+      sct_ok = true;
+  }
+
   // Print SCT status and temperature history table
-  if (options.sct_temp_sts || options.sct_temp_hist || options.sct_temp_int) {
+  if (sct_ok && (options.sct_temp_sts || options.sct_temp_hist || options.sct_temp_int)) {
     for (;;) {
-      if (!isSCTCapable(&drive)) {
-        pout("Warning: device does not support SCT Commands\n");
-        failuretest(OPTIONAL_CMD, returnval|=FAILSMART);
-        break;
-      }
       if (options.sct_temp_sts || options.sct_temp_hist) {
         ata_sct_status_response sts;
         ata_sct_temperature_history_table tmh;
@@ -2340,6 +2363,44 @@ int ataPrintMain (ata_device * device, const ata_print_options & options)
     }
   }
 
+  // SCT Error Recovery Control
+  if (sct_ok && (options.sct_erc_get || options.sct_erc_set)) {
+    if (!isSCTErrorRecoveryControlCapable(&drive)) {
+      pout("Warning: device does not support SCT Error Recovery Control command\n");
+      failuretest(OPTIONAL_CMD, returnval|=FAILSMART);
+    }
+    else {
+      bool sct_erc_get = options.sct_erc_get;
+      if (options.sct_erc_set) {
+        // Set SCT Error Recovery Control
+        if (   ataSetSCTErrorRecoveryControltime(device, 1, options.sct_erc_readtime )
+            || ataSetSCTErrorRecoveryControltime(device, 2, options.sct_erc_writetime)) {
+          pout("Warning: device does not support SCT (Set) Error Recovery Control command\n");
+          pout("Suggest common arguments: scterc,70,70 to enable ERC or sct,0,0 to disable\n");
+          failuretest(OPTIONAL_CMD, returnval|=FAILSMART);
+          sct_erc_get = false;
+        }
+        else
+          sct_erc_get = true;
+      }
+
+      if (sct_erc_get) {
+        // Print SCT Error Recovery Control
+        unsigned short read_timer, write_timer;
+        if (   ataGetSCTErrorRecoveryControltime(device, 1, read_timer )
+            || ataGetSCTErrorRecoveryControltime(device, 2, write_timer)) {
+          pout("Warning: device does not support SCT (Get) Error Recovery Control command\n");
+          if (options.sct_erc_set)
+            pout("The previous SCT (Set) Error Recovery Control command succeeded\n");
+          failuretest(OPTIONAL_CMD, returnval|=FAILSMART);
+        }
+        else
+          ataPrintSCTErrorRecoveryControl(read_timer, write_timer);
+      }
+      pout("\n");
+    }
+  }
+
   // Print SATA Phy Event Counters
   if (options.sataphy) {
     unsigned nsectors = GetNumLogSectors(gplogdir, 0x11, true);
index 7fd3be795a88b76aa8fad62da835527babddcd49..0194cca9bee546004a24d0ca464c37b66ffb8bf5 100644 (file)
@@ -26,7 +26,7 @@
 #ifndef ATAPRINT_H_
 #define ATAPRINT_H_
 
-#define ATAPRINT_H_CVSID "$Id: ataprint.h 3020 2009-12-31 01:11:51Z dlukes $\n"
+#define ATAPRINT_H_CVSID "$Id: ataprint.h 3065 2010-02-10 22:16:50Z chrfranke $\n"
 
 #include <vector>
 
@@ -63,6 +63,9 @@ struct ata_print_options
   std::vector<ata_log_request> log_requests;
 
   bool sct_temp_sts, sct_temp_hist;
+  bool sct_erc_get;
+  bool sct_erc_set;
+  unsigned sct_erc_readtime, sct_erc_writetime;
   bool sataphy, sataphy_reset;
 
   bool smart_disable, smart_enable;
@@ -97,6 +100,9 @@ struct ata_print_options
       smart_ext_selftest_log(0),
       retry_error_log(false), retry_selftest_log(false),
       sct_temp_sts(false), sct_temp_hist(false),
+      sct_erc_get(false),
+      sct_erc_set(false),
+      sct_erc_readtime(0), sct_erc_writetime(0),
       sataphy(false), sataphy_reset(false),
       smart_disable(false), smart_enable(false),
       smart_auto_offl_disable(false), smart_auto_offl_enable(false),
index 136526d870bdfad2f5e8e739427439f1d83c766a..9db5131b1e252d387fc80cf014bd842f88780bff 100644 (file)
@@ -1,5 +1,5 @@
 #
-# $Id: configure.in 3057 2010-02-03 20:56:41Z chrfranke $
+# $Id: configure.in 3074 2010-03-05 23:00:30Z chrfranke $
 #
 dnl Process this file with autoconf to produce a configure script.
 AC_PREREQ(2.50)
@@ -7,7 +7,7 @@ AC_INIT(smartmontools, 5.40, smartmontools-support@lists.sourceforge.net)
 AC_CONFIG_SRCDIR(smartctl.cpp)
 
 smartmontools_configure_date=`date -u +'%Y-%m-%d %T %Z'`
-smartmontools_cvs_tag=`echo '$Id: configure.in 3057 2010-02-03 20:56:41Z chrfranke $'`
+smartmontools_cvs_tag=`echo '$Id: configure.in 3074 2010-03-05 23:00:30Z chrfranke $'`
 smartmontools_release_date=2009-12-09
 smartmontools_release_time="21:00:32 UTC"
 
@@ -38,7 +38,7 @@ case "${host}" in
                # to select MinGW gcc. This does no longer work for gcc 4.x.
                if test "${build}" = "${host}" && test -x /usr/bin/uname && \
                   /usr/bin/uname | grep -i '^CYGWIN' >/dev/null; then
-                 AC_MSG_CHECKING([whether C and C++ compiler support -mno-cygwin])
+                 AC_MSG_CHECKING([whether $CC and $CXX support -mno-cygwin])
                  gcc_support_m_no_cygwin=no
                  if $CC  -v -mno-cygwin >/dev/null 2>&1 && \
                     $CXX -v -mno-cygwin >/dev/null 2>&1; then
@@ -138,7 +138,7 @@ AC_MSG_RESULT([$libc_have_working_snprintf])
 
 # check for __attribute__((packed))
 AH_TEMPLATE(HAVE_ATTR_PACKED, [Define to 1 if C++ compiler supports __attribute__((packed))])
-AC_MSG_CHECKING([whether C++ compiler supports __attribute__((packed))])
+AC_MSG_CHECKING([whether $CXX supports __attribute__((packed))])
 AC_COMPILE_IFELSE([AC_LANG_PROGRAM(, [[struct a { int b; } __attribute__((packed));]])],
                   [gcc_have_attr_packed=yes], [gcc_have_attr_packed=no])
 AC_COMPILE_IFELSE([AC_LANG_PROGRAM(, [[#if defined(__SUNPRO_C) || defined(__SUNPRO_CC)
@@ -269,6 +269,7 @@ AC_SUBST(smartmontools_release_time)
 
 AC_MSG_CHECKING([for OS dependent modules and libraries])
 dnl if OS not recognized, then use the os_generic modules
+os_win64=no
 case "${host}" in
        *-*-linux*)
                AC_SUBST([os_deps], ['os_linux.o cciss.o']) 
@@ -302,7 +303,8 @@ case "${host}" in
                AC_SUBST([os_libs], ['']) ;;
        *-*-mingw*)
                AC_SUBST([os_deps], ['os_win32.o'])
-               AC_SUBST([os_libs], ['']) ;;
+               AC_SUBST([os_libs], [''])
+               test "$host_cpu" = "x86_64" && os_win64=yes ;;
        *-*-darwin*)
                AC_SUBST([os_deps], ['os_darwin.o'])
                AC_SUBST([os_libs], ['-framework CoreFoundation -framework IOKit']) ;;
@@ -345,6 +347,7 @@ dnl Define platform-specific symbol.
 AM_CONDITIONAL(OS_DARWIN, [echo $host_os | grep '^darwin' > /dev/null])
 AM_CONDITIONAL(OS_SOLARIS, [echo $host_os | grep '^solaris' > /dev/null])
 AM_CONDITIONAL(OS_WIN32_MINGW, [echo $host_os | grep '^mingw' > /dev/null])
+AM_CONDITIONAL(OS_WIN64, [test "$os_win64" = "yes"])
 AM_CONDITIONAL(OS_FREEBSD, [echo $host_os | grep '^freebsd' > /dev/null])
 
 dnl Add -Wall and -W if using g++ and its not already specified.
@@ -364,7 +367,7 @@ if test "$GXX" = "yes"; then
 
   # Disable strict aliasing rules by default (see ticket #23).
   if test -z "`echo "$CXXFLAGS" | grep "\-f[[no-]]*strict-aliasing" 2> /dev/null`" ; then
-    AC_MSG_CHECKING([whether g++ supports -fno-strict-aliasing])
+    AC_MSG_CHECKING([whether $CXX supports -fno-strict-aliasing])
     ac_save_CXXFLAGS="$CXXFLAGS"
     CXXFLAGS="-fno-strict-aliasing"
     AC_COMPILE_IFELSE([AC_LANG_PROGRAM()],
index d87c3d40673370ea90ba0753eaed7807a8879f14..48a544aeab3b4ddd38f793b79102613f3519bec3 100644 (file)
--- a/drivedb.h
+++ b/drivedb.h
@@ -58,7 +58,7 @@
 /*
 const drive_settings builtin_knowndrives[] = {
  */
-  { "$Id: drivedb.h 3060 2010-02-03 22:16:40Z chrfranke $",
+  { "$Id: drivedb.h 3071 2010-03-04 21:17:09Z manfred99 $",
     "-", "-",
     "This is a dummy entry to hold the SVN-Id of drivedb.h",
     ""
@@ -71,6 +71,28 @@ const drive_settings builtin_knowndrives[] = {
     "ASUS-PHISON SSD",
     "", "", ""
   },
+  { "SuperTalent UltraDrive GX SSD",
+    "STT_FT[MD](28|32|56|64)GX25H",
+    "", "",
+    " -v 9,raw64"
+    " -v 12,raw64"
+    " -v 184,raw64,Initial_Bad_Block_Count"
+    " -v 195,raw64,Program_Failure_Blk_Ct"
+    " -v 196,raw64,Erase_Failure_Blk_Ct"
+    " -v 197,raw64,Read_Failure_Blk_Ct"
+    " -v 198,raw64,Read_Sectors_Tot_Ct"
+    " -v 199,raw64,Write_Sectors_Tot_Ct"
+    " -v 200,raw64,Read_Commands_Tot_Ct"
+    " -v 201,raw64,Write_Commands_Tot_Ct"
+    " -v 202,raw64,Error_Bits_Flash_Tot_Ct"
+    " -v 203,raw64,Corr_Read_Errors_Tot_Ct"
+    " -v 204,raw64,Bad_Block_Full_Flag"
+    " -v 205,raw64,Max_PE_Count_Spec"
+    " -v 206,raw64,Min_Erase_Count"
+    " -v 207,raw64,Max_Erase_Count"
+    " -v 208,raw64,Average_Erase_Count"
+    " -v 209,raw64,Remaining_Lifetime_Perc"
+  },
   { "Patriot Torqx SSD",
     "Patriot[ -]Torqx.*",
     "", "",
@@ -163,7 +185,12 @@ const drive_settings builtin_knowndrives[] = {
     " -v 211,raw64"
   },
   { "Intel X25-E SSD",
-    "SSDSA2SH(032|064)G1.* INTEL",
+    "SSDSA2SH(032|064)G1.* INTEL",  // G1 = first generation
+    "", "",
+    "-v 225,raw48,Host_Writes_Count"
+  },
+  { "Intel X25-M SSD",
+    "INTEL SSDSA2M(080|160)G2.*",  // G2 = second generation
     "", "",
     "-v 225,raw48,Host_Writes_Count"
   },
@@ -183,6 +210,10 @@ const drive_settings builtin_knowndrives[] = {
     "GB1000EAFJL",
     "", "", ""
   },
+  { "HP 500GB SATA disk MM0500EANCR",
+    "MM0500EANCR",
+    "", "", ""
+  },
   { "IBM Deskstar 60GXP series",  // ER60A46A firmware
     "(IBM-|Hitachi )?IC35L0[12346]0AVER07.*",
     "ER60A46A",
@@ -335,6 +366,10 @@ const drive_settings builtin_knowndrives[] = {
     "FUJITSU MHZ2(12|25)0BS.*",
     "", "", ""
   },
+  { "Fujitsu MHZ2 BK series",
+    "FUJITSU MHZ2(08|12|16|25)0BK.*",
+    "", "", ""
+  },
   { "", // Samsung SV4012H (known firmware)
     "SAMSUNG SV4012H",
     "RM100-08",
@@ -405,6 +440,14 @@ const drive_settings builtin_knowndrives[] = {
     "SAMSUNG HD(502H|10[23]S|15[34]U)I",
     "", "", ""
   },
+  { "SAMSUNG SpinPoint F3 series", // tested with HD502HJ/1AJ100E4
+    "SAMSUNG HD(502H|754J|103S)J",
+    "", "", ""
+  },
+  { "SAMSUNG SpinPoint F3 EG series", // tested with HD503HI/1AJ100E4
+    "SAMSUNG HD(253G|(324|503)H|754J|105S)I",
+    "", "", ""
+  },
   { "SAMSUNG SpinPoint S250 series", // tested with HD200HJ/KF100-06
     "SAMSUNG HD(162|200|250)HJ",
     "", "", ""
@@ -472,6 +515,10 @@ const drive_settings builtin_knowndrives[] = {
     "",
     "-v 9,halfminutes"
   },
+  { "SAMSUNG SpinPoint M5 series", // tested with HM160HI/HH100-12
+    "SAMSUNG HM((061|080)G|(121|160)H|250J)I",
+    "", "", ""
+  },
 /*
   // TODO: Make the entries below more specific.
   // These entries produce misleading results, because newer
@@ -1031,7 +1078,7 @@ const drive_settings builtin_knowndrives[] = {
     "", "", ""
   },
   { "Seagate Momentus 5400.6 series",
-    "ST9((12|25)0315AS|500325)ASG?",
+    "ST9(80313|160(301|314)|(12|25)0315|250317|(320|500)325|500327|640320)ASG?",
     "", "", ""
   },
   { "Seagate Momentus 5400 PSD series", // Hybrid drives
@@ -1058,8 +1105,8 @@ const drive_settings builtin_knowndrives[] = {
     "ST9((160413|25041[12]|320426|50042[12])AS|(16041[89]|2504[16]4|32042[67]|500426)ASG)",
     "", "", ""
   },
-  { "Seagate Medalist 1010, 1721, 2120, 3230 and 4340",  // ATA2, with -t permissive
-    "ST3(1010|1721|2120|3230|4340)A",
+  { "Seagate Medalist 1010, 1720, 1721, 2120, 3230 and 4340",  // ATA2, with -t permissive
+    "ST3(1010|1720|1721|2120|3230|4340)A",
     "", "", ""
   },
   { "Seagate Medalist 2110, 3221, 4321, 6531, and 8641",
@@ -1333,7 +1380,7 @@ const drive_settings builtin_knowndrives[] = {
     "", "", ""
   },
   { "Western Digital Caviar Green family",
-    "WDC WD((50|64|75)00AA(C|V)S|(50|75)00AADS|10EA(C|V)S|(10|15|20)EADS)-.*",
+    "WDC WD((50|64|75)00AA(C|V)S|(50|64|75)00AADS|10EA(C|V)S|(10|15|20)EADS)-.*",
     "", "", ""
   },
   { "Western Digital Caviar Black family",
@@ -1357,7 +1404,7 @@ const drive_settings builtin_knowndrives[] = {
     "", "", ""
   },
   { "Western Digital VelociRaptor family",
-    "WDC WD((1500|3000)B|3000G)LFS-.*",
+    "WDC WD(800H|(1500|3000)[BH]|1600H|3000G)LFS-.*",
     "", "", ""
   },
   { "Western Digital Scorpio EIDE family",
index df58b925bc7b101a812764abdc6d09db2b76e518..c9df5fe6837822ba77ae60efdcfb190168b493c8 100644 (file)
@@ -71,9 +71,9 @@
 #define PATHINQ_SETTINGS_SIZE   128
 #endif
 
-static __unused const char *filenameandversion="$Id: os_freebsd.cpp 3037 2010-01-16 20:07:13Z chrfranke $";
+static __unused const char *filenameandversion="$Id: os_freebsd.cpp 3066 2010-02-15 23:10:49Z samm2 $";
 
-const char *os_XXXX_c_cvsid="$Id: os_freebsd.cpp 3037 2010-01-16 20:07:13Z chrfranke $" \
+const char *os_XXXX_c_cvsid="$Id: os_freebsd.cpp 3066 2010-02-15 23:10:49Z samm2 $" \
 ATACMDS_H_CVSID CCISS_H_CVSID CONFIG_H_CVSID INT64_H_CVSID OS_FREEBSD_H_CVSID SCSICMDS_H_CVSID UTILITY_H_CVSID;
 
 extern smartmonctrl * con;
@@ -121,7 +121,7 @@ void printwarning(int msgNo, const char* extra) {
 // global variable holding byte count of allocated memory
 long long bytes;
 
-const char * dev_freebsd_cpp_cvsid = "$Id: os_freebsd.cpp 3037 2010-01-16 20:07:13Z chrfranke $"
+const char * dev_freebsd_cpp_cvsid = "$Id: os_freebsd.cpp 3066 2010-02-15 23:10:49Z samm2 $"
   DEV_INTERFACE_H_CVSID;
 
 extern smartmonctrl * con; // con->reportscsiioctl
@@ -261,7 +261,11 @@ int freebsd_ata_device::do_cmd( struct ata_ioc_request* request)
 
 bool freebsd_ata_device::ata_pass_through(const ata_cmd_in & in, ata_cmd_out & out)
 {
-  if (!ata_cmd_is_ok(in, true, true, true)) // data_out_support
+  if (!ata_cmd_is_ok(in,
+    true,  // data_out_support
+    true,  // multi_sector_support
+    false) // no ata_48bit_support via IOCATAREQUEST
+    ) 
     return false;
 
   struct ata_ioc_request request;
index 20f66b9bbcb72068fd5d97b60fc4db8bab6b843f..16722eae77381b2ec55108388dd8a9c08624cf35 100644 (file)
@@ -90,7 +90,7 @@
 
 #define ARGUSED(x) ((void)(x))
 
-const char *os_XXXX_c_cvsid="$Id: os_linux.cpp 3052 2010-01-28 19:51:24Z chrfranke $" \
+const char *os_XXXX_c_cvsid="$Id: os_linux.cpp 3076 2010-03-12 22:23:08Z chrfranke $" \
 ATACMDS_H_CVSID CONFIG_H_CVSID INT64_H_CVSID OS_LINUX_H_CVSID SCSICMDS_H_CVSID UTILITY_H_CVSID;
 
 /* for passing global control variables */
@@ -2948,8 +2948,12 @@ bool linux_smart_interface::scan_smart_devices(smart_device_list & devlist,
 
   if (scan_ata)
     get_dev_list(devlist, "/dev/hd[a-t]", true, false, type, false);
-  if (scan_scsi) // Try USB autodetection if no type specifed
-    get_dev_list(devlist, "/dev/sd[a-z]", false, true, type, !*type);
+  if (scan_scsi) {
+    bool autodetect = !*type; // Try USB autodetection if no type specifed
+    get_dev_list(devlist, "/dev/sd[a-z]", false, true, type, autodetect);
+    // Support up to 104 devices
+    get_dev_list(devlist, "/dev/sd[a-c][a-z]", false, true, type, autodetect);
+  }
 
   // if we found traditional links, we are done
   if (devlist.size() > 0)
index 2bf2b5a2e397a878a8a18614a4bbec5442774416..49a1e656c9650574954e05584e33d0f2addcd38e 100644 (file)
@@ -16,6 +16,8 @@
  */
 
 #include "config.h"
+#define _WIN32_WINNT 0x0510
+
 #include "int64.h"
 #include "atacmds.h"
 #include "extern.h"
@@ -40,6 +42,17 @@ extern smartmonctrl * con; // con->permissive,reportataioctl
 #include <stddef.h> // offsetof()
 #include <io.h> // access()
 
+// TODO: Add a configure test
+#if defined(__CYGWIN__) || (defined(__MINGW32__) && !defined(__MINGW64__))
+#include <ddk/ntdddisk.h>
+#include <ddk/ntddscsi.h>
+#include <ddk/ntddstor.h>
+#else
+// Win SDK, no DDK
+#include <winioctl.h>
+#include <ntddscsi.h>
+#endif
+
 #ifdef __CYGWIN__
 #include <cygwin/version.h> // CYGWIN_VERSION_DLL_MAJOR
 #endif
@@ -50,10 +63,18 @@ extern smartmonctrl * con; // con->permissive,reportataioctl
 #define ASSERT_SIZEOF(t, n) \
   typedef char assert_sizeof_##t[(sizeof(t) == (n)) ? 1 : -1]
 
-const char * os_win32_cpp_cvsid = "$Id: os_win32.cpp 3049 2010-01-27 19:47:09Z chrfranke $";
+#ifndef _WIN64
+#define SELECT_WIN_32_64(x32, x64) (x32)
+#else
+#define SELECT_WIN_32_64(x32, x64) (x64)
+#endif
+
+const char * os_win32_cpp_cvsid = "$Id: os_win32.cpp 3062 2010-02-09 21:02:27Z chrfranke $";
 
 // Disable Win9x/ME specific code if no longer supported by compiler.
-#ifndef WIN9X_SUPPORT
+#ifdef _WIN64
+  #undef WIN9X_SUPPORT
+#elif !defined(WIN9X_SUPPORT)
   #if defined(CYGWIN_VERSION_DLL_MAJOR) && (CYGWIN_VERSION_DLL_MAJOR >= 1007)
     // Win9x/ME support was dropped in Cygwin 1.7
   #elif defined(_MSC_VER) && (_MSC_VER >= 1500)
@@ -63,6 +84,207 @@ const char * os_win32_cpp_cvsid = "$Id: os_win32.cpp 3049 2010-01-27 19:47:09Z c
   #endif
 #endif
 
+/////////////////////////////////////////////////////////////////////////////
+// Windows I/O-controls, some declarations are missing in the include files
+
+extern "C" {
+
+// SMART_* IOCTLs, also known as DFP_* (Disk Fault Protection)
+
+ASSERT_CONST(SMART_GET_VERSION, 0x074080);
+ASSERT_CONST(SMART_SEND_DRIVE_COMMAND, 0x07c084);
+ASSERT_CONST(SMART_RCV_DRIVE_DATA, 0x07c088);
+ASSERT_SIZEOF(GETVERSIONINPARAMS, 24);
+ASSERT_SIZEOF(SENDCMDINPARAMS, 32+1);
+ASSERT_SIZEOF(SENDCMDOUTPARAMS, 16+1);
+
+
+// IDE PASS THROUGH (2000, XP, undocumented)
+
+#ifndef IOCTL_IDE_PASS_THROUGH
+
+#define IOCTL_IDE_PASS_THROUGH \
+  CTL_CODE(IOCTL_SCSI_BASE, 0x040A, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
+
+#endif // IOCTL_IDE_PASS_THROUGH
+
+#pragma pack(1)
+
+typedef struct {
+  IDEREGS IdeReg;
+  ULONG DataBufferSize;
+  UCHAR DataBuffer[1];
+} ATA_PASS_THROUGH;
+
+#pragma pack()
+
+ASSERT_CONST(IOCTL_IDE_PASS_THROUGH, 0x04d028);
+ASSERT_SIZEOF(ATA_PASS_THROUGH, 12+1);
+
+
+// ATA PASS THROUGH (Win2003, XP SP2)
+
+#ifndef IOCTL_ATA_PASS_THROUGH
+
+#define IOCTL_ATA_PASS_THROUGH \
+  CTL_CODE(IOCTL_SCSI_BASE, 0x040B, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
+
+typedef struct _ATA_PASS_THROUGH_EX {
+  USHORT Length;
+  USHORT AtaFlags;
+  UCHAR PathId;
+  UCHAR TargetId;
+  UCHAR Lun;
+  UCHAR ReservedAsUchar;
+  ULONG DataTransferLength;
+  ULONG TimeOutValue;
+  ULONG ReservedAsUlong;
+  ULONG_PTR DataBufferOffset;
+  UCHAR PreviousTaskFile[8];
+  UCHAR CurrentTaskFile[8];
+} ATA_PASS_THROUGH_EX;
+
+#define ATA_FLAGS_DRDY_REQUIRED 0x01
+#define ATA_FLAGS_DATA_IN       0x02
+#define ATA_FLAGS_DATA_OUT      0x04
+#define ATA_FLAGS_48BIT_COMMAND 0x08
+#define ATA_FLAGS_USE_DMA       0x10
+#define ATA_FLAGS_NO_MULTIPLE   0x20 // Vista
+
+#endif // IOCTL_ATA_PASS_THROUGH
+
+ASSERT_CONST(IOCTL_ATA_PASS_THROUGH, 0x04d02c);
+ASSERT_SIZEOF(ATA_PASS_THROUGH_EX, SELECT_WIN_32_64(40, 48));
+
+
+// IOCTL_SCSI_PASS_THROUGH[_DIRECT]
+
+ASSERT_CONST(IOCTL_SCSI_PASS_THROUGH, 0x04d004);
+ASSERT_CONST(IOCTL_SCSI_PASS_THROUGH_DIRECT, 0x04d014);
+ASSERT_SIZEOF(SCSI_PASS_THROUGH, SELECT_WIN_32_64(44, 56));
+ASSERT_SIZEOF(SCSI_PASS_THROUGH_DIRECT, SELECT_WIN_32_64(44, 56));
+
+
+// SMART IOCTL via SCSI MINIPORT ioctl
+
+#ifndef FILE_DEVICE_SCSI
+
+#define FILE_DEVICE_SCSI 0x001b
+
+#define IOCTL_SCSI_MINIPORT_SMART_VERSION               ((FILE_DEVICE_SCSI << 16) + 0x0500)
+#define IOCTL_SCSI_MINIPORT_IDENTIFY                    ((FILE_DEVICE_SCSI << 16) + 0x0501)
+#define IOCTL_SCSI_MINIPORT_READ_SMART_ATTRIBS          ((FILE_DEVICE_SCSI << 16) + 0x0502)
+#define IOCTL_SCSI_MINIPORT_READ_SMART_THRESHOLDS       ((FILE_DEVICE_SCSI << 16) + 0x0503)
+#define IOCTL_SCSI_MINIPORT_ENABLE_SMART                ((FILE_DEVICE_SCSI << 16) + 0x0504)
+#define IOCTL_SCSI_MINIPORT_DISABLE_SMART               ((FILE_DEVICE_SCSI << 16) + 0x0505)
+#define IOCTL_SCSI_MINIPORT_RETURN_STATUS               ((FILE_DEVICE_SCSI << 16) + 0x0506)
+#define IOCTL_SCSI_MINIPORT_ENABLE_DISABLE_AUTOSAVE     ((FILE_DEVICE_SCSI << 16) + 0x0507)
+#define IOCTL_SCSI_MINIPORT_SAVE_ATTRIBUTE_VALUES       ((FILE_DEVICE_SCSI << 16) + 0x0508)
+#define IOCTL_SCSI_MINIPORT_EXECUTE_OFFLINE_DIAGS       ((FILE_DEVICE_SCSI << 16) + 0x0509)
+#define IOCTL_SCSI_MINIPORT_ENABLE_DISABLE_AUTO_OFFLINE ((FILE_DEVICE_SCSI << 16) + 0x050a)
+#define IOCTL_SCSI_MINIPORT_READ_SMART_LOG              ((FILE_DEVICE_SCSI << 16) + 0x050b)
+#define IOCTL_SCSI_MINIPORT_WRITE_SMART_LOG             ((FILE_DEVICE_SCSI << 16) + 0x050c)
+
+#endif // FILE_DEVICE_SCSI
+
+ASSERT_CONST(IOCTL_SCSI_MINIPORT, 0x04d008);
+ASSERT_SIZEOF(SRB_IO_CONTROL, 28);
+
+
+// IOCTL_STORAGE_QUERY_PROPERTY
+
+#ifndef IOCTL_STORAGE_QUERY_PROPERTY
+
+#define IOCTL_STORAGE_QUERY_PROPERTY \
+  CTL_CODE(IOCTL_STORAGE_BASE, 0x0500, METHOD_BUFFERED, FILE_ANY_ACCESS)
+
+typedef struct _STORAGE_DEVICE_DESCRIPTOR {
+  ULONG Version;
+  ULONG Size;
+  UCHAR DeviceType;
+  UCHAR DeviceTypeModifier;
+  BOOLEAN RemovableMedia;
+  BOOLEAN CommandQueueing;
+  ULONG VendorIdOffset;
+  ULONG ProductIdOffset;
+  ULONG ProductRevisionOffset;
+  ULONG SerialNumberOffset;
+  STORAGE_BUS_TYPE BusType;
+  ULONG RawPropertiesLength;
+  UCHAR RawDeviceProperties[1];
+} STORAGE_DEVICE_DESCRIPTOR;
+
+typedef enum _STORAGE_QUERY_TYPE {
+  PropertyStandardQuery = 0,
+  PropertyExistsQuery,
+  PropertyMaskQuery,
+  PropertyQueryMaxDefined
+} STORAGE_QUERY_TYPE;
+
+typedef enum _STORAGE_PROPERTY_ID {
+  StorageDeviceProperty = 0,
+  StorageAdapterProperty,
+  StorageDeviceIdProperty,
+  StorageDeviceUniqueIdProperty,
+  StorageDeviceWriteCacheProperty,
+  StorageMiniportProperty,
+  StorageAccessAlignmentProperty
+} STORAGE_PROPERTY_ID;
+
+typedef struct _STORAGE_PROPERTY_QUERY {
+  STORAGE_PROPERTY_ID PropertyId;
+  STORAGE_QUERY_TYPE QueryType;
+  UCHAR AdditionalParameters[1];
+} STORAGE_PROPERTY_QUERY;
+
+#endif // IOCTL_STORAGE_QUERY_PROPERTY
+
+ASSERT_CONST(IOCTL_STORAGE_QUERY_PROPERTY, 0x002d1400);
+ASSERT_SIZEOF(STORAGE_DEVICE_DESCRIPTOR, 36+1+3);
+ASSERT_SIZEOF(STORAGE_PROPERTY_QUERY, 8+1+3);
+
+
+// IOCTL_STORAGE_PREDICT_FAILURE
+
+ASSERT_CONST(IOCTL_STORAGE_PREDICT_FAILURE, 0x002d1100);
+ASSERT_SIZEOF(STORAGE_PREDICT_FAILURE, 4+512);
+
+
+// 3ware specific versions of SMART ioctl structs
+
+#define SMART_VENDOR_3WARE      0x13C1  // identifies 3ware specific parameters
+
+#pragma pack(1)
+
+typedef struct _GETVERSIONINPARAMS_EX {
+  BYTE bVersion;
+  BYTE bRevision;
+  BYTE bReserved;
+  BYTE bIDEDeviceMap;
+  DWORD fCapabilities;
+  DWORD dwDeviceMapEx;  // 3ware specific: RAID drive bit map
+  WORD wIdentifier;     // Vendor specific identifier
+  WORD wControllerId;   // 3ware specific: Controller ID (0,1,...)
+  ULONG dwReserved[2];
+} GETVERSIONINPARAMS_EX;
+
+typedef struct _SENDCMDINPARAMS_EX {
+  DWORD cBufferSize;
+  IDEREGS irDriveRegs;
+  BYTE bDriveNumber;
+  BYTE bPortNumber;     // 3ware specific: port number
+  WORD wIdentifier;     // Vendor specific identifier
+  DWORD dwReserved[4];
+  BYTE bBuffer[1];
+} SENDCMDINPARAMS_EX;
+
+#pragma pack()
+
+ASSERT_SIZEOF(GETVERSIONINPARAMS_EX, sizeof(GETVERSIONINPARAMS));
+ASSERT_SIZEOF(SENDCMDINPARAMS_EX, sizeof(SENDCMDINPARAMS));
+
+} // extern "C"
+
 /////////////////////////////////////////////////////////////////////////////
 
 namespace os_win32 { // no need to publish anything, name provided for Doxygen
@@ -270,6 +492,7 @@ protected:
 
 //////////////////////////////////////////////////////////////////////
 
+#ifndef _WIN64
 // Running on 64-bit Windows as 32-bit app ?
 static bool is_wow64()
 {
@@ -285,6 +508,7 @@ static bool is_wow64()
     return false;
   return !!w64;
 }
+#endif // _WIN64
 
 // Return info string about build host and OS version
 std::string win_smart_interface::get_os_version_str()
@@ -335,7 +559,12 @@ std::string win_smart_interface::get_os_version_str()
     default: w = 0; break;
   }
 
-  const char * w64 = (is_wow64() ? "(64)" : "");
+  const char * w64 = "";
+#ifndef _WIN64
+  if (is_wow64())
+    w64 = "(64)";
+#endif
+
   if (!w)
     snprintf(vptr, vlen, "-%s%lu.%lu%s",
       (vi.dwPlatformId==VER_PLATFORM_WIN32_NT ? "nt" : "9x"),
@@ -527,8 +756,10 @@ std::string win_smart_interface::get_app_examples(const char * appname)
          "  smartctl -t long /dev/hda              (Executes extended disk self-test)\n\n"
          "  smartctl --attributes --log=selftest --quietmode=errorsonly /dev/hda\n"
          "                                      (Prints Self-Test & Attribute errors)\n"
+#if WIN9X_SUPPORT
          "  smartctl -a /dev/scsi21\n"
          "             (Prints all information for SCSI disk on ASPI adapter 2, ID 1)\n"
+#endif
          "  smartctl -a /dev/sda\n"
          "             (Prints all information for SCSI disk on PhysicalDrive 0)\n"
          "  smartctl -a /dev/pd3\n"
@@ -555,133 +786,9 @@ std::string win_smart_interface::get_app_examples(const char * appname)
 // ATA Interface
 /////////////////////////////////////////////////////////////////////////////
 
-// SMART_* IOCTLs, also known as DFP_* (Disk Fault Protection)
-
-#define FILE_READ_ACCESS       0x0001
-#define FILE_WRITE_ACCESS      0x0002
-#define METHOD_BUFFERED             0
-#define CTL_CODE(DeviceType, Function, Method, Access) (((DeviceType) << 16) | ((Access) << 14) | ((Function) << 2) | (Method))
-
-#define FILE_DEVICE_DISK       7
-#define IOCTL_DISK_BASE        FILE_DEVICE_DISK
-
-#define SMART_GET_VERSION \
-  CTL_CODE(IOCTL_DISK_BASE, 0x0020, METHOD_BUFFERED, FILE_READ_ACCESS)
-
-#define SMART_SEND_DRIVE_COMMAND \
-  CTL_CODE(IOCTL_DISK_BASE, 0x0021, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
-
-#define SMART_RCV_DRIVE_DATA \
-  CTL_CODE(IOCTL_DISK_BASE, 0x0022, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
-
-ASSERT_CONST(SMART_GET_VERSION       , 0x074080);
-ASSERT_CONST(SMART_SEND_DRIVE_COMMAND, 0x07c084);
-ASSERT_CONST(SMART_RCV_DRIVE_DATA    , 0x07c088);
-
 #define SMART_CYL_LOW  0x4F
 #define SMART_CYL_HI   0xC2
 
-
-#pragma pack(1)
-
-typedef struct _GETVERSIONOUTPARAMS {
-  UCHAR  bVersion;
-  UCHAR  bRevision;
-  UCHAR  bReserved;
-  UCHAR  bIDEDeviceMap;
-  ULONG  fCapabilities;
-  ULONG  dwReserved[4];
-} GETVERSIONOUTPARAMS, *PGETVERSIONOUTPARAMS, *LPGETVERSIONOUTPARAMS;
-
-ASSERT_SIZEOF(GETVERSIONOUTPARAMS, 24);
-
-
-#define SMART_VENDOR_3WARE      0x13C1  // identifies 3ware specific parameters
-
-typedef struct _GETVERSIONINPARAMS_EX {
-  BYTE    bVersion;
-  BYTE    bRevision;
-  BYTE    bReserved;
-  BYTE    bIDEDeviceMap;
-  DWORD   fCapabilities;
-  DWORD   dwDeviceMapEx;  // 3ware specific: RAID drive bit map
-  WORD    wIdentifier;    // Vendor specific identifier
-  WORD    wControllerId;  // 3ware specific: Controller ID (0,1,...)
-  ULONG   dwReserved[2];
-} GETVERSIONINPARAMS_EX, *PGETVERSIONINPARAMS_EX, *LPGETVERSIONINPARAMS_EX;
-
-ASSERT_SIZEOF(GETVERSIONINPARAMS_EX, sizeof(GETVERSIONOUTPARAMS));
-
-
-typedef struct _IDEREGS {
-  UCHAR  bFeaturesReg;
-  UCHAR  bSectorCountReg;
-  UCHAR  bSectorNumberReg;
-  UCHAR  bCylLowReg;
-  UCHAR  bCylHighReg;
-  UCHAR  bDriveHeadReg;
-  UCHAR  bCommandReg;
-  UCHAR  bReserved;
-} IDEREGS, *PIDEREGS, *LPIDEREGS;
-
-typedef struct _SENDCMDINPARAMS {
-  ULONG  cBufferSize;
-  IDEREGS  irDriveRegs;
-  UCHAR  bDriveNumber;
-  UCHAR  bReserved[3];
-  ULONG  dwReserved[4];
-  UCHAR  bBuffer[1];
-} SENDCMDINPARAMS, *PSENDCMDINPARAMS, *LPSENDCMDINPARAMS;
-
-ASSERT_SIZEOF(SENDCMDINPARAMS, 32+1);
-
-typedef struct _SENDCMDINPARAMS_EX {
-  DWORD   cBufferSize;
-  IDEREGS irDriveRegs;
-  BYTE    bDriveNumber;
-  BYTE    bPortNumber;   // 3ware specific: port number
-  WORD    wIdentifier;   // Vendor specific identifier
-  DWORD   dwReserved[4];
-  BYTE    bBuffer[1];
-} SENDCMDINPARAMS_EX, *PSENDCMDINPARAMS_EX, *LPSENDCMDINPARAMS_EX;
-
-ASSERT_SIZEOF(SENDCMDINPARAMS_EX, sizeof(SENDCMDINPARAMS));
-
-
-/* DRIVERSTATUS.bDriverError constants (just for info, not used)
-#define SMART_NO_ERROR                    0
-#define SMART_IDE_ERROR                   1
-#define SMART_INVALID_FLAG                2
-#define SMART_INVALID_COMMAND             3
-#define SMART_INVALID_BUFFER              4
-#define SMART_INVALID_DRIVE               5
-#define SMART_INVALID_IOCTL               6
-#define SMART_ERROR_NO_MEM                7
-#define SMART_INVALID_REGISTER            8
-#define SMART_NOT_SUPPORTED               9
-#define SMART_NO_IDE_DEVICE               10
-*/
-
-typedef struct _DRIVERSTATUS {
-  UCHAR  bDriverError;
-  UCHAR  bIDEError;
-  UCHAR  bReserved[2];
-  ULONG  dwReserved[2];
-} DRIVERSTATUS, *PDRIVERSTATUS, *LPDRIVERSTATUS;
-
-typedef struct _SENDCMDOUTPARAMS {
-  ULONG  cBufferSize;
-  DRIVERSTATUS  DriverStatus;
-  UCHAR  bBuffer[1];
-} SENDCMDOUTPARAMS, *PSENDCMDOUTPARAMS, *LPSENDCMDOUTPARAMS;
-
-ASSERT_SIZEOF(SENDCMDOUTPARAMS, 16+1);
-
-#pragma pack()
-
-
-/////////////////////////////////////////////////////////////////////////////
-
 static void print_ide_regs(const IDEREGS * r, int out)
 {
   pout("%s=0x%02x,%s=0x%02x, SC=0x%02x, SN=0x%02x, CL=0x%02x, CH=0x%02x, SEL=0x%02x\n",
@@ -703,7 +810,7 @@ static void print_ide_regs_io(const IDEREGS * ri, const IDEREGS * ro)
 
 static int smart_get_version(HANDLE hdevice, GETVERSIONINPARAMS_EX * ata_version_ex = 0)
 {
-  GETVERSIONOUTPARAMS vers; memset(&vers, 0, sizeof(vers));
+  GETVERSIONINPARAMS vers; memset(&vers, 0, sizeof(vers));
   const GETVERSIONINPARAMS_EX & vers_ex = (const GETVERSIONINPARAMS_EX &)vers;
   DWORD num_out;
 
@@ -714,7 +821,7 @@ static int smart_get_version(HANDLE hdevice, GETVERSIONINPARAMS_EX * ata_version
     errno = ENOSYS;
     return -1;
   }
-  assert(num_out == sizeof(GETVERSIONOUTPARAMS));
+  assert(num_out == sizeof(GETVERSIONINPARAMS));
 
   if (con->reportataioctl > 1) {
     pout("  SMART_GET_VERSION suceeded, bytes returned: %lu\n"
@@ -829,35 +936,11 @@ static int smart_ioctl(HANDLE hdevice, int drive, IDEREGS * regs, char * data, u
 
 
 /////////////////////////////////////////////////////////////////////////////
-
 // IDE PASS THROUGH (2000, XP, undocumented)
 //
 // Based on WinATA.cpp, 2002 c't/Matthias Withopf
 // ftp://ftp.heise.de/pub/ct/listings/0207-218.zip
 
-#define FILE_DEVICE_CONTROLLER  4
-#define IOCTL_SCSI_BASE         FILE_DEVICE_CONTROLLER
-
-#define IOCTL_IDE_PASS_THROUGH \
-  CTL_CODE(IOCTL_SCSI_BASE, 0x040A, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
-
-ASSERT_CONST(IOCTL_IDE_PASS_THROUGH, 0x04d028);
-
-#pragma pack(1)
-
-typedef struct {
-  IDEREGS IdeReg;
-  ULONG   DataBufferSize;
-  UCHAR   DataBuffer[1];
-} ATA_PASS_THROUGH;
-
-ASSERT_SIZEOF(ATA_PASS_THROUGH, 12+1);
-
-#pragma pack()
-
-
-/////////////////////////////////////////////////////////////////////////////
-
 static int ide_pass_through_ioctl(HANDLE hdevice, IDEREGS * regs, char * data, unsigned datasize)
 {
   if (datasize > 512) {
@@ -932,41 +1015,8 @@ static int ide_pass_through_ioctl(HANDLE hdevice, IDEREGS * regs, char * data, u
 
 
 /////////////////////////////////////////////////////////////////////////////
-
 // ATA PASS THROUGH (Win2003, XP SP2)
 
-#define IOCTL_ATA_PASS_THROUGH \
-  CTL_CODE(IOCTL_SCSI_BASE, 0x040B, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
-
-ASSERT_CONST(IOCTL_ATA_PASS_THROUGH, 0x04d02c);
-
-typedef struct _ATA_PASS_THROUGH_EX {
-  USHORT  Length;
-  USHORT  AtaFlags;
-  UCHAR  PathId;
-  UCHAR  TargetId;
-  UCHAR  Lun;
-  UCHAR  ReservedAsUchar;
-  ULONG  DataTransferLength;
-  ULONG  TimeOutValue;
-  ULONG  ReservedAsUlong;
-  ULONG/*_PTR*/ DataBufferOffset;
-  UCHAR  PreviousTaskFile[8];
-  UCHAR  CurrentTaskFile[8];
-} ATA_PASS_THROUGH_EX, *PATA_PASS_THROUGH_EX;
-
-ASSERT_SIZEOF(ATA_PASS_THROUGH_EX, 40);
-
-#define ATA_FLAGS_DRDY_REQUIRED 0x01
-#define ATA_FLAGS_DATA_IN       0x02
-#define ATA_FLAGS_DATA_OUT      0x04
-#define ATA_FLAGS_48BIT_COMMAND 0x08
-#define ATA_FLAGS_USE_DMA       0x10
-#define ATA_FLAGS_NO_MULTIPLE   0x20 // Vista
-
-
-/////////////////////////////////////////////////////////////////////////////
-
 // Warning:
 // IOCTL_ATA_PASS_THROUGH[_DIRECT] can only handle one interrupt/DRQ data
 // transfer per command. Therefore, multi-sector transfers are only supported
@@ -1081,41 +1131,11 @@ static int ata_pass_through_ioctl(HANDLE hdevice, IDEREGS * regs, IDEREGS * prev
 
 
 /////////////////////////////////////////////////////////////////////////////
-
 // ATA PASS THROUGH via SCSI PASS THROUGH (WinNT4 only)
 
-#define IOCTL_SCSI_PASS_THROUGH \
-  CTL_CODE(IOCTL_SCSI_BASE, 0x0401, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
-
-ASSERT_CONST(IOCTL_SCSI_PASS_THROUGH, 0x04d004);
-
-#define SCSI_IOCTL_DATA_OUT          0
-#define SCSI_IOCTL_DATA_IN           1
-#define SCSI_IOCTL_DATA_UNSPECIFIED  2
 // undocumented SCSI opcode to for ATA passthrough
 #define SCSIOP_ATA_PASSTHROUGH    0xCC
 
-typedef struct _SCSI_PASS_THROUGH {
-  USHORT  Length;
-  UCHAR  ScsiStatus;
-  UCHAR  PathId;
-  UCHAR  TargetId;
-  UCHAR  Lun;
-  UCHAR  CdbLength;
-  UCHAR  SenseInfoLength;
-  UCHAR  DataIn;
-  ULONG  DataTransferLength;
-  ULONG  TimeOutValue;
-  ULONG/*_PTR*/ DataBufferOffset;
-  ULONG  SenseInfoOffset;
-  UCHAR  Cdb[16];
-} SCSI_PASS_THROUGH, *PSCSI_PASS_THROUGH;
-
-ASSERT_SIZEOF(SCSI_PASS_THROUGH, 44);
-
-
-/////////////////////////////////////////////////////////////////////////////
-
 static int ata_via_scsi_pass_through_ioctl(HANDLE hdevice, IDEREGS * regs, char * data, unsigned datasize)
 {
   typedef struct {
@@ -1196,7 +1216,6 @@ static int ata_via_scsi_pass_through_ioctl(HANDLE hdevice, IDEREGS * regs, char
 
 
 /////////////////////////////////////////////////////////////////////////////
-
 // SMART IOCTL via SCSI MINIPORT ioctl
 
 // This function is handled by ATAPI port driver (atapi.sys) or by SCSI
@@ -1204,40 +1223,6 @@ static int ata_via_scsi_pass_through_ioctl(HANDLE hdevice, IDEREGS * regs, char
 // It can be used to skip the missing or broken handling of some SMART
 // command codes (e.g. READ_LOG) in the disk class driver (disk.sys)
 
-#define IOCTL_SCSI_MINIPORT \
-  CTL_CODE(IOCTL_SCSI_BASE, 0x0402, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
-
-ASSERT_CONST(IOCTL_SCSI_MINIPORT, 0x04d008);
-
-typedef struct _SRB_IO_CONTROL {
-  ULONG HeaderLength;
-  UCHAR Signature[8];
-  ULONG Timeout;
-  ULONG ControlCode;
-  ULONG ReturnCode;
-  ULONG Length;
-} SRB_IO_CONTROL, *PSRB_IO_CONTROL;
-
-ASSERT_SIZEOF(SRB_IO_CONTROL, 28);
-
-#define FILE_DEVICE_SCSI 0x001b
-
-#define IOCTL_SCSI_MINIPORT_SMART_VERSION               ((FILE_DEVICE_SCSI << 16) + 0x0500)
-#define IOCTL_SCSI_MINIPORT_IDENTIFY                    ((FILE_DEVICE_SCSI << 16) + 0x0501)
-#define IOCTL_SCSI_MINIPORT_READ_SMART_ATTRIBS          ((FILE_DEVICE_SCSI << 16) + 0x0502)
-#define IOCTL_SCSI_MINIPORT_READ_SMART_THRESHOLDS       ((FILE_DEVICE_SCSI << 16) + 0x0503)
-#define IOCTL_SCSI_MINIPORT_ENABLE_SMART                ((FILE_DEVICE_SCSI << 16) + 0x0504)
-#define IOCTL_SCSI_MINIPORT_DISABLE_SMART               ((FILE_DEVICE_SCSI << 16) + 0x0505)
-#define IOCTL_SCSI_MINIPORT_RETURN_STATUS               ((FILE_DEVICE_SCSI << 16) + 0x0506)
-#define IOCTL_SCSI_MINIPORT_ENABLE_DISABLE_AUTOSAVE     ((FILE_DEVICE_SCSI << 16) + 0x0507)
-#define IOCTL_SCSI_MINIPORT_SAVE_ATTRIBUTE_VALUES       ((FILE_DEVICE_SCSI << 16) + 0x0508)
-#define IOCTL_SCSI_MINIPORT_EXECUTE_OFFLINE_DIAGS       ((FILE_DEVICE_SCSI << 16) + 0x0509)
-#define IOCTL_SCSI_MINIPORT_ENABLE_DISABLE_AUTO_OFFLINE ((FILE_DEVICE_SCSI << 16) + 0x050a)
-#define IOCTL_SCSI_MINIPORT_READ_SMART_LOG              ((FILE_DEVICE_SCSI << 16) + 0x050b)
-#define IOCTL_SCSI_MINIPORT_WRITE_SMART_LOG             ((FILE_DEVICE_SCSI << 16) + 0x050c)
-
-/////////////////////////////////////////////////////////////////////////////
-
 static int ata_via_scsi_miniport_smart_ioctl(HANDLE hdevice, IDEREGS * regs, char * data, int datasize)
 {
   // Select code
@@ -1724,77 +1709,8 @@ int win_tw_cli_device::ata_command_interface(smart_command_set command, int /*se
 
 
 /////////////////////////////////////////////////////////////////////////////
-
 // IOCTL_STORAGE_QUERY_PROPERTY
 
-#define FILE_DEVICE_MASS_STORAGE    0x0000002d
-#define IOCTL_STORAGE_BASE          FILE_DEVICE_MASS_STORAGE
-#define FILE_ANY_ACCESS             0
-
-#define IOCTL_STORAGE_QUERY_PROPERTY \
-  CTL_CODE(IOCTL_STORAGE_BASE, 0x0500, METHOD_BUFFERED, FILE_ANY_ACCESS)
-
-typedef enum _STORAGE_BUS_TYPE {
-  BusTypeUnknown      = 0x00,
-  BusTypeScsi         = 0x01,
-  BusTypeAtapi        = 0x02,
-  BusTypeAta          = 0x03,
-  BusType1394         = 0x04,
-  BusTypeSsa          = 0x05,
-  BusTypeFibre        = 0x06,
-  BusTypeUsb          = 0x07,
-  BusTypeRAID         = 0x08,
-  BusTypeiScsi        = 0x09,
-  BusTypeSas          = 0x0A,
-  BusTypeSata         = 0x0B,
-  BusTypeSd           = 0x0C,
-  BusTypeMmc          = 0x0D,
-  BusTypeMax          = 0x0E,
-  BusTypeMaxReserved  = 0x7F
-} STORAGE_BUS_TYPE, *PSTORAGE_BUS_TYPE;
-
-typedef struct _STORAGE_DEVICE_DESCRIPTOR {
-  ULONG Version;
-  ULONG Size;
-  UCHAR DeviceType;
-  UCHAR DeviceTypeModifier;
-  BOOLEAN RemovableMedia;
-  BOOLEAN CommandQueueing;
-  ULONG VendorIdOffset;
-  ULONG ProductIdOffset;
-  ULONG ProductRevisionOffset;
-  ULONG SerialNumberOffset;
-  STORAGE_BUS_TYPE BusType;
-  ULONG RawPropertiesLength;
-  UCHAR RawDeviceProperties[1];
-} STORAGE_DEVICE_DESCRIPTOR, *PSTORAGE_DEVICE_DESCRIPTOR;
-
-typedef enum _STORAGE_QUERY_TYPE {
-  PropertyStandardQuery = 0,
-  PropertyExistsQuery,
-  PropertyMaskQuery,
-  PropertyQueryMaxDefined
-} STORAGE_QUERY_TYPE, *PSTORAGE_QUERY_TYPE;
-
-typedef enum _STORAGE_PROPERTY_ID {
-  StorageDeviceProperty = 0,
-  StorageAdapterProperty,
-  StorageDeviceIdProperty,
-  StorageDeviceUniqueIdProperty,
-  StorageDeviceWriteCacheProperty,
-  StorageMiniportProperty,
-  StorageAccessAlignmentProperty
-} STORAGE_PROPERTY_ID, *PSTORAGE_PROPERTY_ID;
-
-typedef struct _STORAGE_PROPERTY_QUERY {
-  STORAGE_PROPERTY_ID PropertyId;
-  STORAGE_QUERY_TYPE QueryType;
-  UCHAR AdditionalParameters[1];
-} STORAGE_PROPERTY_QUERY, *PSTORAGE_PROPERTY_QUERY;
-
-
-/////////////////////////////////////////////////////////////////////////////
-
 union STORAGE_DEVICE_DESCRIPTOR_DATA {
   STORAGE_DEVICE_DESCRIPTOR desc;
   char raw[256];
@@ -1835,23 +1751,8 @@ static int storage_query_property_ioctl(HANDLE hdevice, STORAGE_DEVICE_DESCRIPTO
 
 
 /////////////////////////////////////////////////////////////////////////////
-
 // IOCTL_STORAGE_PREDICT_FAILURE
 
-#define IOCTL_STORAGE_PREDICT_FAILURE \
-  CTL_CODE(IOCTL_STORAGE_BASE, 0x0440, METHOD_BUFFERED, FILE_ANY_ACCESS)
-
-typedef struct _STORAGE_PREDICT_FAILURE {
-  ULONG  PredictFailure;
-  UCHAR  VendorSpecific[512];
-} STORAGE_PREDICT_FAILURE, *PSTORAGE_PREDICT_FAILURE;
-
-ASSERT_SIZEOF(STORAGE_PREDICT_FAILURE, 4+512);
-
-
-/////////////////////////////////////////////////////////////////////////////
-
-
 // Call IOCTL_STORAGE_PREDICT_FAILURE, return PredictFailure value
 // or -1 on error, opionally return VendorSpecific data.
 // (This works without admin rights)
@@ -1900,15 +1801,16 @@ static win_dev_type get_controller_type(HANDLE hdevice, bool admin, GETVERSIONIN
   if (storage_query_property_ioctl(hdevice, &data))
     return DEV_UNKNOWN;
 
+  // Newer BusType* values are missing in older includes
   switch (data.desc.BusType) {
     case BusTypeAta:
-    case BusTypeSata:
+    case (STORAGE_BUS_TYPE)0x0b: // BusTypeSata
       if (ata_version_ex)
         memset(ata_version_ex, 0, sizeof(*ata_version_ex));
       return DEV_ATA;
     case BusTypeScsi:
-    case BusTypeiScsi:
-    case BusTypeSas:
+    case (STORAGE_BUS_TYPE)0x09: // BusTypeiScsi
+    case (STORAGE_BUS_TYPE)0x0a: // BusTypeSas
       return DEV_SCSI;
     case BusTypeUsb:
       return DEV_USB;
@@ -3116,7 +3018,7 @@ static int aspi_io_call(ASPI_SRB * srb, unsigned timeout)
       }
       else {
         pout("WaitForSingleObject(%lx) = 0x%lx,%ld, Error=%ld\n",
-          (unsigned long)event, rc, rc, GetLastError());
+          (unsigned long)(ULONG_PTR)event, rc, rc, GetLastError());
       }
       // TODO: ASPI_ABORT_IO command
       aspi_entry = 0;
@@ -3478,25 +3380,6 @@ bool winnt_smart_interface::scsi_scan(smart_device_list & devlist)
 }
 
 
-#define IOCTL_SCSI_PASS_THROUGH_DIRECT  \
-  CTL_CODE(IOCTL_SCSI_BASE, 0x0405, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
-
-typedef struct _SCSI_PASS_THROUGH_DIRECT {
-  USHORT          Length;
-  UCHAR           ScsiStatus;
-  UCHAR           PathId;
-  UCHAR           TargetId;
-  UCHAR           Lun;
-  UCHAR           CdbLength;
-  UCHAR           SenseInfoLength;
-  UCHAR           DataIn;
-  ULONG           DataTransferLength;
-  ULONG           TimeOutValue;
-  PVOID           DataBuffer;
-  ULONG           SenseInfoOffset;
-  UCHAR           Cdb[16];
-} SCSI_PASS_THROUGH_DIRECT;
-
 typedef struct {
   SCSI_PASS_THROUGH_DIRECT spt;
   ULONG           Filler;
index d53105252e1bd1d7bd15c7bc091d555ff38546aa..980ff787f23c3d09029980d1f68f3577b9be3c26 100644 (file)
                        RelativePath="..\TODO"
                        >
                </File>
+               <File
+                       RelativePath="..\update-smart-drivedb.in"
+                       >
+               </File>
                <File
                        RelativePath="..\utility.cpp"
                        >
index 2f7b69b9060ef7b86640a1d70ceab3227019bc58..807d4a2f0f5678355a1d2510a75a9571b69e6204 100644 (file)
                        RelativePath="..\TODO"
                        >
                </File>
+               <File
+                       RelativePath="..\update-smart-drivedb.in"
+                       >
+               </File>
                <File
                        RelativePath="..\utility.cpp"
                        >
index 0727017ddf16ea627c5a4a09ed40705395b8d808..a70a4084251df9fb121b35a98526313eab02ff7c 100644 (file)
@@ -61,7 +61,7 @@
 #include "dev_ata_cmd_set.h" // ata_device_with_command_set
 #include "dev_tunnelled.h" // tunnelled_device<>
 
-const char * scsiata_cpp_cvsid = "$Id: scsiata.cpp 3048 2010-01-23 17:54:42Z chrfranke $";
+const char * scsiata_cpp_cvsid = "$Id: scsiata.cpp 3077 2010-03-16 20:48:06Z chrfranke $";
 
 /* for passing global control variables */
 extern smartmonctrl *con;
@@ -1352,13 +1352,15 @@ const usb_id_entry usb_ids[] = {
   // LaCie
   { 0x059f, 0x0651,     -1, d_unsup   }, // LaCie hard disk (FA Porsche design)
   { 0x059f, 0x1018,     -1, d_sat     }, // LaCie hard disk (Neil Poulton design)
+  { 0x059f, 0x1019,     -1, d_jmicron }, // LaCie Desktop Hard Drive
   // In-System Design
   { 0x05ab, 0x0060, 0x1101, d_cypress }, // In-System/Cypress ISD-300A1
   // Genesys Logic
   { 0x05e3, 0x0702,     -1, d_unsup   }, // Genesys Logic GL881E
   { 0x05e3, 0x0718, 0x0041, d_sat     }, // Genesys Logic ? (TODO: requires '-T permissive')
   // Prolific
-  { 0x067b, 0x3507, 0x0001, d_unsup   }, // Prolific PL3507
+  { 0x067b, 0x2507,     -1, d_unsup   }, // Prolific PL2507 (USB->PATA)
+  { 0x067b, 0x3507, 0x0001, d_unsup   }, // Prolific PL3507 (USB+IEE1394->PATA)
   // Freecom
   { 0x07ab, 0xfc8e, 0x010f, d_sunplus }, // Freecom Hard Drive XS
   // Toshiba
@@ -1368,6 +1370,7 @@ const usb_id_entry usb_ids[] = {
   { 0x0bc2, 0x2000,     -1, d_sat     }, // Seagate FreeAgent Go
   { 0x0bc2, 0x2100,     -1, d_sat     }, // Seagate FreeAgent Go
   { 0x0bc2, 0x2101,     -1, d_sat     }, // Seagate FreeAgent Go
+  { 0x0bc2, 0x2200,     -1, d_sat     }, // Seagate FreeAgent Go FW
   { 0x0bc2, 0x2300,     -1, d_sat     }, // Seagate Expansion Portable
   { 0x0bc2, 0x3000,     -1, d_sat     }, // Seagate FreeAgent Desktop
   { 0x0bc2, 0x3001,     -1, d_sat     }, // Seagate FreeAgent Desk
@@ -1390,6 +1393,7 @@ const usb_id_entry usb_ids[] = {
   { 0x1058, 0x1010, 0x0105, d_sat     }, // WD Elements
   { 0x1058, 0x1100, 0x0165, d_sat     }, // WD My Book Essential
   { 0x1058, 0x1102, 0x1028, d_sat     }, // WD My Book
+  { 0x1058, 0x1110, 0x1030, d_sat     }, // WD My Book Essential
   // Initio
   { 0x13fd, 0x0540,     -1, d_unsup   }, // Initio 316000
   { 0x13fd, 0x1240, 0x0104, d_sat     }, // Initio ? (USB->SATA)
index 9df3d04e1182a2bc7af7a8bed7082ec8c28f9bd9..a70fcaab19dba32151dcb6b1bbe6832c9bf7d1bd 100644 (file)
@@ -1,7 +1,7 @@
 .ig
  Copyright (C) 2002-9 Bruce Allen <smartmontools-support@lists.sourceforge.net>
 
- $Id: smartctl.8.in 3001 2009-12-19 15:25:27Z chrfranke $
+ $Id: smartctl.8.in 3072 2010-03-04 21:56:41Z chrfranke $
  
  This program is free software; you can redistribute it and/or modify it
  under the terms of the GNU General Public License as published by the Free
@@ -189,7 +189,7 @@ Prints all SMART and non-SMART information about the device. For ATA
 devices this is equivalent to
 .nf
 \'\-H \-i \-c \-A \-l xerror,error \-l xselftest,selftest \-l selective
-\-l directory \-l scttemp \-l sataphy\'.
+\-l directory \-l scttemp \-l scterc \-l sataphy\'.
 .fi
 and for SCSI, this is equivalent to
 .nf
@@ -974,6 +974,16 @@ configured with the \'\-t scttempint,N[,p]\' option, see below.
 The SCT commands are specified in the proposed ATA\-8 Command Set
 (ACS), and are already implemented in some recent ATA\-7 disks.
 
+.I scterc[,READTIME,WRITETIME]
+\- [ATA only] [NEW EXPERIMENTAL SMARTCTL FEATURE] prints values
+and descriptions of the SCT Error Recovery Control settings. These
+are equivalent to TLER (as used by Western Digital), CCTL (as used
+by Samsung and Hitachi) and ERC (as used by Seagate. READTIME and
+WRITETIME arguments (deciseconds) set the specified values. Values of 0
+disable the feature, other values less than 65 are probably not
+supported. For RAID configurations, this is typically set to
+70,70 deciseconds.
+
 .I sataphy[,reset]
 \- [SATA only] [NEW EXPERIMENTAL SMARTCTL FEATURE] prints values
 and descriptions of the SATA Phy Event Counters (General Purpose Log
@@ -1303,6 +1313,9 @@ If this option is not specified, optional entries are read from the file
 .\" BEGIN ENABLE_DRIVEDB
 If \fB/usr/local/share/smartmontools/drivedb.h\fP is present, the
 contents of this file is used instead of the built in table.
+
+Run the script \fB/usr/local/sbin/update-smart-drivedb\fP to update this
+file from the smartmontools SVN repository.
 .\" END ENABLE_DRIVEDB
 
 The database files use the same C/C++ syntax that is used to initialize
@@ -1840,7 +1853,7 @@ these documents may be found in the References section of the
 
 .SH
 SVN ID OF THIS PAGE:
-$Id: smartctl.8.in 3001 2009-12-19 15:25:27Z chrfranke $
+$Id: smartctl.8.in 3072 2010-03-04 21:56:41Z chrfranke $
 .\" Local Variables:            
 .\" mode: nroff         
 .\" End:
index 76924af1ae6594f114e07bb17075ac8912495640..cffca12c2e040e7f5ff939c8a0d331e3c1881467 100644 (file)
@@ -56,7 +56,7 @@
 #include "smartctl.h"
 #include "utility.h"
 
-const char * smartctl_cpp_cvsid = "$Id: smartctl.cpp 3032 2010-01-16 13:04:55Z chrfranke $"
+const char * smartctl_cpp_cvsid = "$Id: smartctl.cpp 3065 2010-02-10 22:16:50Z chrfranke $"
                                   CONFIG_H_CVSID EXTERN_H_CVSID SMARTCTL_H_CVSID;
 
 // This is a block containing all the "control variables".  We declare
@@ -126,7 +126,7 @@ void Usage (void){
 "  -l TYPE, --log=TYPE\n"
 "        Show device log. TYPE: error, selftest, selective, directory[,g|s],\n"
 "                               background, sasphy[,reset], sataphy[,reset],\n"
-"                               scttemp[sts,hist],\n"
+"                               scttemp[sts,hist], scterc[,N,M],\n"
 "                               gplog,N[,RANGE], smartlog,N[,RANGE],\n"
 "                               xerror[,N][,error], xselftest[,N][,selftest]\n\n"
 "  -v N,OPTION , --vendorattribute=N,OPTION                            (ATA)\n"
@@ -178,7 +178,7 @@ static std::string getvalidarglist(char opt)
   case 'S':
     return "on, off";
   case 'l':
-    return "error, selftest, selective, directory[,g|s], background, scttemp[sts|hist], "
+    return "error, selftest, selective, directory[,g|s], background, scttemp[sts|hist], scterc[,N,M], "
            "sasphy[,reset], sataphy[,reset], gplog,N[,RANGE], smartlog,N[,RANGE], "
           "xerror[,N][,error], xselftest[,N][,selftest]";
   case 'P':
@@ -430,6 +430,8 @@ const char * parse_options(int argc, char** argv,
         ataopts.sataphy = ataopts.sataphy_reset = true;
       } else if (!strcmp(optarg,"background")) {
         scsiopts.smart_background_log = true;
+      } else if (!strcmp(optarg,"scterc")) {
+        ataopts.sct_erc_get = true;
       } else if (!strcmp(optarg,"scttemp")) {
         ataopts.sct_temp_sts = ataopts.sct_temp_hist = true;
       } else if (!strcmp(optarg,"scttempsts")) {
@@ -467,6 +469,18 @@ const char * parse_options(int argc, char** argv,
         else
           badarg = true;
 
+      } else if (!strncmp(optarg, "scterc,", sizeof("scterc,")-1)) {
+        unsigned rt = ~0, wt = ~0; int n = -1;
+        sscanf(optarg,"scterc,%u,%u%n", &rt, &wt, &n);
+        if (n == (int)strlen(optarg) && rt <= 999 && wt <= 999) {
+          ataopts.sct_erc_set = true;
+          ataopts.sct_erc_readtime = rt;
+          ataopts.sct_erc_writetime = wt;
+        }
+        else {
+          sprintf(extraerror, "Option -l scterc,[READTIME,WRITETIME] syntax error\n");
+          badarg = true;
+        }
       } else if (   !strncmp(optarg, "gplog,"   , sizeof("gplog,"   )-1)
                  || !strncmp(optarg, "smartlog,", sizeof("smartlog,")-1)) {
         unsigned logaddr = ~0U; unsigned page = 0, nsectors = 1; char sign = 0;
@@ -526,6 +540,7 @@ const char * parse_options(int argc, char** argv,
       ataopts.smart_selective_selftest_log = true;
       ataopts.smart_logdir = ataopts.gp_logdir = true;
       ataopts.sct_temp_sts = ataopts.sct_temp_hist = true;
+      ataopts.sct_erc_get = true;
       ataopts.sataphy = true;
       scsiopts.smart_background_log = true;
       scsiopts.sasphy = true;
index 4568e4560186c2e7ad2d38bb792fb3cabfa00726..f6931f9dc8b5ee1f849e9f70b040a0f65ecc3eb2 100644 (file)
@@ -1,7 +1,7 @@
 .ig
 Copyright (C) 2002-8 Bruce Allen <smartmontools-support@lists.sourceforge.net>
  
-$Id: smartd.8.in 3057 2010-02-03 20:56:41Z chrfranke $
+$Id: smartd.8.in 3076 2010-03-12 22:23:08Z chrfranke $
 
 This program is free software; you can redistribute it and/or modify
 it under the terms of the GNU General Public License as published by
@@ -89,7 +89,8 @@ On startup, in the absence of the configuration file
 devices that support SMART.  The scanning is done as follows:
 .IP \fBLINUX:\fP 9
 Examine all entries \fB"/dev/hd[a-t]"\fP for IDE/ATA
-devices, and \fB"/dev/sd[a-z]"\fP for SCSI devices.
+devices, and \fB"/dev/sd[a-z]"\fP, \fB"/dev/sd[a-c][a-z]"\fP
+for SCSI or SATA devices.
 .IP \fBFREEBSD:\fP 9
 Authoritative list of disk devices is obtained from SCSI (CAM) and ATA subsystems.
 .IP \fBNETBSD/OPENBSD:\fP 9
@@ -680,8 +681,7 @@ Section below!
 .SH CONFIGURATION FILE DIRECTIVES
 .PP
 
-If the first non-comment entry in the configuration file is the text
-string
+If a non-comment entry in the configuration file is the text string
 .B DEVICESCAN
 in capital letters, then
 \fBsmartd\fP
@@ -1699,11 +1699,15 @@ If you want more frequent information, use:
 
 .TP
 .B ADDITIONAL DETAILS ABOUT DEVICESCAN
-If the first non-comment entry in the configuration file is the text
+If a non-comment entry in the configuration file is the text
 string \fBDEVICESCAN\fP in capital letters, then \fBsmartd\fP will
 ignore any remaining lines in the configuration file, and will scan
 for devices.
 
+[NEW EXPERIMENTAL SMARTD FEATURE] Configuration entries for devices
+not found by the platform\-specific device scanning may precede the
+\fBDEVICESCAN\fP entry.
+
 If \fBDEVICESCAN\fP is not followed by any Directives, then smartd
 will scan for both ATA and SCSI devices, and will monitor all possible
 SMART properties of any devices that are found.
@@ -2075,4 +2079,4 @@ smartmontools home page at \fBhttp://smartmontools.sourceforge.net/#references\f
 
 .SH
 SVN ID OF THIS PAGE:
-$Id: smartd.8.in 3057 2010-02-03 20:56:41Z chrfranke $
+$Id: smartd.8.in 3076 2010-03-12 22:23:08Z chrfranke $
index ab717709b883f65cfce488829655416df74f7571..5a0e5516b2f7f9bed705985b0428104c3c5ac1a8 100644 (file)
@@ -1,7 +1,7 @@
 .ig
 Copyright (C) 2002-8 Bruce Allen <smartmontools-support@lists.sourceforge.net>
 
-$Id: smartd.conf.5.in 3001 2009-12-19 15:25:27Z chrfranke $
+$Id: smartd.conf.5.in 3075 2010-03-12 22:01:44Z chrfranke $
 
 This program is free software; you can redistribute it and/or modify it
 under the terms of the GNU General Public License as published by the Free
@@ -234,8 +234,7 @@ Section below!
 .SH CONFIGURATION FILE DIRECTIVES
 .PP
 
-If the first non-comment entry in the configuration file is the text
-string
+If a non-comment entry in the configuration file is the text string
 .B DEVICESCAN
 in capital letters, then
 \fBsmartd\fP
@@ -1253,11 +1252,15 @@ If you want more frequent information, use:
 
 .TP
 .B ADDITIONAL DETAILS ABOUT DEVICESCAN
-If the first non-comment entry in the configuration file is the text
+If a non-comment entry in the configuration file is the text
 string \fBDEVICESCAN\fP in capital letters, then \fBsmartd\fP will
 ignore any remaining lines in the configuration file, and will scan
 for devices.
 
+[NEW EXPERIMENTAL SMARTD FEATURE] Configuration entries for devices
+not found by the platform\-specific device scanning may precede the
+\fBDEVICESCAN\fP entry.
+
 If \fBDEVICESCAN\fP is not followed by any Directives, then smartd
 will scan for both ATA and SCSI devices, and will monitor all possible
 SMART properties of any devices that are found.
@@ -1399,4 +1402,4 @@ SEE ALSO:
 
 .SH
 SVN ID OF THIS PAGE:
-$Id: smartd.conf.5.in 3001 2009-12-19 15:25:27Z chrfranke $
+$Id: smartd.conf.5.in 3075 2010-03-12 22:01:44Z chrfranke $
index a2a053b6136bbe2403a5ebbec668c0af08be3df5..4be546f267f3053fee10c90fe591fc017ba59458 100644 (file)
@@ -126,7 +126,7 @@ extern "C" int getdomainname(char *, int); // no declaration in header files!
 
 #define ARGUSED(x) ((void)(x))
 
-const char * smartd_cpp_cvsid = "$Id: smartd.cpp 3058 2010-02-03 21:04:24Z chrfranke $"
+const char * smartd_cpp_cvsid = "$Id: smartd.cpp 3075 2010-03-12 22:01:44Z chrfranke $"
                                 CONFIG_H_CVSID EXTERN_H_CVSID;
 
 extern const char *reportbug;
@@ -3455,7 +3455,7 @@ static int ParseToken(char * token, dev_config & cfg)
 // -2: found an error
 //
 // Note: this routine modifies *line from the caller!
-static int ParseConfigLine(dev_config_vector & conf_entries, int entry, int lineno, /*const*/ char * line)
+static int ParseConfigLine(dev_config_vector & conf_entries, int /*entry*/, int lineno, /*const*/ char * line)
 {
   char *token=NULL;
   char *name=NULL;
@@ -3470,10 +3470,6 @@ static int ParseConfigLine(dev_config_vector & conf_entries, int entry, int line
   // Have we detected the SCANDIRECTIVE directive?
   if (!strcmp(SCANDIRECTIVE,name)){
     devscan=1;
-    if (entry) {
-      PrintOut(LOG_INFO,"Scan Directive %s (line %d) must be the first entry in %s\n",name, lineno, configfile);
-      return -2;
-    }
   }
   
   // We've got a legit entry, make space to store it
@@ -3562,7 +3558,7 @@ static int ParseConfigLine(dev_config_vector & conf_entries, int entry, int line
 // possiblities:
 // Empty configuration file ==> conf_entries.empty()
 // No configuration file    ==> conf_entries[0].lineno == 0
-// SCANDIRECTIVE found      ==> conf_entries[0].lineno != 0
+// SCANDIRECTIVE found      ==> conf_entries.back().lineno != 0 (size >= 1)
 static int ParseConfigFile(dev_config_vector & conf_entries)
 {
   // maximum line length in configuration file
@@ -4046,6 +4042,10 @@ static int MakeConfigEntries(const dev_config & base_cfg,
   if (devlist.size() <= 0)
     return 0;
 
+  // add empty device slots for existing config entries
+  while (scanned_devs.size() < conf_entries.size())
+    scanned_devs.push_back((smart_device *)0);
+
   // loop over entries to create
   for (unsigned i = 0; i < devlist.size(); i++) {
     // Move device pointer
@@ -4078,8 +4078,6 @@ static void CanNotRegister(const char *name, const char *type, int line, bool sc
 
 // Returns negative value (see ParseConfigFile()) if config file
 // had errors, else number of entries which may be zero or positive. 
-// If we found no configuration file, or it contained SCANDIRECTIVE,
-// then *scanning is set to 1, else 0.
 static int ReadOrMakeConfigEntries(dev_config_vector & conf_entries, smart_device_list & scanned_devs)
 {
   // parse configuration file configfile (normally /etc/smartd.conf)  
@@ -4098,12 +4096,12 @@ static int ReadOrMakeConfigEntries(dev_config_vector & conf_entries, smart_devic
     // we did not find a SCANDIRECTIVE and did find valid entries
     PrintOut(LOG_INFO, "Configuration file %s parsed.\n", configfile);
   }
-  else if (conf_entries.size() == 1) {
+  else if (!conf_entries.empty()) {
     // we found a SCANDIRECTIVE or there was no configuration file so
-    // scan.  Configuration file's first entry contains all options
+    // scan.  Configuration file's last entry contains all options
     // that were set
-    dev_config first = conf_entries.front();
-    conf_entries.clear();
+    dev_config first = conf_entries.back();
+    conf_entries.pop_back();
 
     if (first.lineno)
       PrintOut(LOG_INFO,"Configuration file %s was parsed, found %s, scanning devices\n", configfile, SCANDIRECTIVE);
diff --git a/update-smart-drivedb.in b/update-smart-drivedb.in
new file mode 100644 (file)
index 0000000..467531a
--- /dev/null
@@ -0,0 +1,144 @@
+#! /bin/sh
+#
+# smartmontools drive database update script
+#
+# Copyright (C) 2010 Christian Franke <smartmontools-support@lists.sourceforge.net>
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2, or (at your option)
+# any later version.
+#
+# You should have received a copy of the GNU General Public License
+# (for example COPYING); If not, see <http://www.gnu.org/licenses/>.
+#
+# $Id: update-smart-drivedb.in 3072 2010-03-04 21:56:41Z chrfranke $
+#
+
+set -e
+
+# Set by config.status
+PACKAGE="@PACKAGE@"
+VERSION="@VERSION@"
+prefix="@prefix@"
+exec_prefix="@exec_prefix@"
+sbindir="@sbindir@"
+datarootdir="@datarootdir@"
+datadir="@datadir@"
+drivedbdir="@drivedbdir@"
+
+# Default drivedb location
+DEST="$drivedbdir/drivedb.h"
+
+# Smartctl used for syntax check
+SMARTCTL="$sbindir/smartctl"
+
+# Trac repository browser (does not return HTTP 404 errors)
+#SRCEXPR='http://sourceforge.net/apps/trac/smartmontools/export/HEAD/$location/smartmontools/drivedb.h'
+
+# ViewVC repository browser
+SRCEXPR='http://smartmontools.svn.sourceforge.net/viewvc/smartmontools/$location/smartmontools/drivedb.h?revision=HEAD'
+
+# Convert version into branch name: 5.41[.X] -> "RELEASE_5_41_DRIVEDB"
+BRANCH="`echo $VERSION | sed -n 's|^\([0-9][0-9]*\)\.\([0-9][0-9]*\)\([^0-9].*\)\?$|RELEASE_\1_\2_DRIVEDB|p'`"
+
+if [ -z "$BRANCH" ]; then
+  echo "$0: syntax error in version number: $VERSION" >&2; exit 1
+fi
+
+
+# Parse options
+q="-q "
+case "$1" in
+  -v) q=; shift ;;
+esac
+
+case "$*" in
+  -*|*\ *)
+    cat <<EOF
+smartmontools $VERSION drive database update script
+
+Usage: $0 [-v] [DESTFILE]
+
+  -v    verbose output
+
+Updates $DEST
+or DESTFILE from smartmontools SVN repository.
+Tries to download first from branch $BRANCH
+and then from trunk.
+EOF
+    exit 1
+    ;;
+
+  "") ;;
+  *)  DEST="$1" ;;
+esac
+
+# Abort if 'which' is not available
+which which >/dev/null || exit 1
+
+# Find download tool
+if which curl >/dev/null 2>/dev/null; then
+  DOWNLOAD="curl ${q:+-s }"'-f -o "$DEST.new" "$SRC"'
+elif which wget >/dev/null 2>/dev/null; then
+  DOWNLOAD="wget $q"'-O "$DEST.new" "$SRC"'
+elif which lynx >/dev/null 2>/dev/null; then
+  DOWNLOAD='lynx -source "$SRC" >"$DEST.new"'
+else
+  echo "$0: curl, wget or lynx not available" >&2; exit 1
+fi
+
+# Try possible branch first, then trunk
+for location in "branches/$BRANCH" "trunk"; do
+  test -n "$q" || echo "Download from $location"
+
+  errmsg=
+  rm -f "$DEST.new"
+  SRC="`eval echo "$SRCEXPR"`"
+
+  if eval $DOWNLOAD; then :; else
+    errmsg="download from $location failed (HTTP error)"
+    continue
+  fi
+  if grep -i 'ViewVC Exception' "$DEST.new" >/dev/null; then
+    errmsg="download from $location failed (ViewVC error)"
+    continue
+  fi
+
+  break
+done
+
+if [ -n "$errmsg" ]; then
+  rm -f "$DEST.new"
+  echo "$0: $errmsg" >&2
+  exit 1
+fi
+
+# Adjust timestamp and permissions
+touch "$DEST.new"
+chmod 0644 "$DEST.new"
+
+# Check syntax
+rm -f "$DEST.error"
+if $SMARTCTL -B "$DEST.new" -P showall >/dev/null; then :; else
+  mv "$DEST.new" "$DEST.error"
+  echo "$DEST.error: rejected by $SMARTCTL, probably no longer compatible" >&2
+  exit 1
+fi
+
+# Keep old file if identical, ignore differences in Id string
+rm -f "$DEST.lastcheck"
+if [ -f "$DEST" ]; then
+  if cat "$DEST" | sed 's|\$''Id''[^$]*\$|$''Id''$|' | cmp - "$DEST.new" >/dev/null; then
+    rm -f "$DEST.new"
+    touch "$DEST.lastcheck"
+    echo "$DEST is already up to date"
+    exit 0
+  fi
+  mv "$DEST" "$DEST.old"
+fi
+
+mv "$DEST.new" "$DEST"
+
+echo "$DEST updated from $location"
+