Imported Upstream version 5.39.1+svn3077

This commit is contained in:
Giuseppe Iuculano 2010-03-26 21:37:06 +01:00
parent a23d51175f
commit 7f0798ef6f
22 changed files with 883 additions and 455 deletions

View File

@ -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)

31
INSTALL
View File

@ -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

View 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

10
NEWS
View File

@ -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

View 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,

View File

@ -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,7 +566,7 @@ 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 option_flags; // Bit 0: persistent, Bits 1-15: reserved
unsigned short words005_255[251]; // reserved
} ATTR_PACKED;
#pragma pack()
@ -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

View 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)
}
}
// Print SCT status and temperature history table
if (options.sct_temp_sts || options.sct_temp_hist || options.sct_temp_int) {
for (;;) {
// 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);
break;
}
else
sct_ok = true;
}
// Print SCT status and temperature history table
if (sct_ok && (options.sct_temp_sts || options.sct_temp_hist || options.sct_temp_int)) {
for (;;) {
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);

View 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),

View 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()],

View File

@ -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",

View 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;

View 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)

View 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;

View File

@ -1037,6 +1037,10 @@
RelativePath="..\TODO"
>
</File>
<File
RelativePath="..\update-smart-drivedb.in"
>
</File>
<File
RelativePath="..\utility.cpp"
>

View File

@ -989,6 +989,10 @@
RelativePath="..\TODO"
>
</File>
<File
RelativePath="..\update-smart-drivedb.in"
>
</File>
<File
RelativePath="..\utility.cpp"
>

View 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)

View 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:

View 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;

View 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 $

View 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 $

View 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);

144
update-smart-drivedb.in Normal file
View File

@ -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"