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
<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)
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/
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:
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
## 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@
sbin_PROGRAMS = smartd \
smartctl
+if ENABLE_DRIVEDB
+sbin_SCRIPTS = update-smart-drivedb
+endif
+
+
smartd_SOURCES = smartd.cpp \
atacmdnames.cpp \
atacmdnames.h \
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 \
smartd.conf.5.txt \
smartd.initd \
svnversion.h \
+ update-smart-drivedb \
SMART
if SMARTD_SUFFIX
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 \
$(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
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
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
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; \
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
$(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
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
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
#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
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");
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");
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,
#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
#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)
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);
// 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);
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
#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
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)
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.
}
}
+ // 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;
}
}
+ // 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);
#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>
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;
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),
#
-# $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)
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"
# 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
# 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)
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'])
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']) ;;
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.
# 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()],
/*
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",
""
"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.*",
"", "",
" -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"
},
"GB1000EAFJL",
"", "", ""
},
+ { "HP 500GB SATA disk MM0500EANCR",
+ "MM0500EANCR",
+ "", "", ""
+ },
{ "IBM Deskstar 60GXP series", // ER60A46A firmware
"(IBM-|Hitachi )?IC35L0[12346]0AVER07.*",
"ER60A46A",
"FUJITSU MHZ2(12|25)0BS.*",
"", "", ""
},
+ { "Fujitsu MHZ2 BK series",
+ "FUJITSU MHZ2(08|12|16|25)0BK.*",
+ "", "", ""
+ },
{ "", // Samsung SV4012H (known firmware)
"SAMSUNG SV4012H",
"RM100-08",
"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",
"", "", ""
"",
"-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
"", "", ""
},
{ "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
"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",
"", "", ""
},
{ "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",
"", "", ""
},
{ "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",
#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;
// 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
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;
#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 */
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)
*/
#include "config.h"
+#define _WIN32_WINNT 0x0510
+
#include "int64.h"
#include "atacmds.h"
#include "extern.h"
#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
#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)
#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
//////////////////////////////////////////////////////////////////////
+#ifndef _WIN64
// Running on 64-bit Windows as 32-bit app ?
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()
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"),
" 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"
// 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",
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;
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"
/////////////////////////////////////////////////////////////////////////////
-
// 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) {
/////////////////////////////////////////////////////////////////////////////
-
// 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
/////////////////////////////////////////////////////////////////////////////
-
// 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 {
/////////////////////////////////////////////////////////////////////////////
-
// SMART IOCTL via SCSI MINIPORT ioctl
// This function is handled by ATAPI port driver (atapi.sys) or by SCSI
// 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
/////////////////////////////////////////////////////////////////////////////
-
// 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];
/////////////////////////////////////////////////////////////////////////////
-
// 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)
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;
}
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;
}
-#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;
RelativePath="..\TODO"
>
</File>
+ <File
+ RelativePath="..\update-smart-drivedb.in"
+ >
+ </File>
<File
RelativePath="..\utility.cpp"
>
RelativePath="..\TODO"
>
</File>
+ <File
+ RelativePath="..\update-smart-drivedb.in"
+ >
+ </File>
<File
RelativePath="..\utility.cpp"
>
#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;
// 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
{ 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
{ 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)
.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
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
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
.\" 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
.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:
#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
" -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"
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':
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")) {
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;
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;
.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
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
.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
.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.
.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 $
.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
.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
.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.
.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 $
#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;
// -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;
// 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
// 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
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
// 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)
// 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);
--- /dev/null
+#! /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"
+