mirror of
https://git.proxmox.com/git/mirror_smartmontools-debian
synced 2025-07-27 03:20:08 +00:00
Imported Upstream version 5.39.1+svn3077
This commit is contained in:
parent
a23d51175f
commit
7f0798ef6f
67
CHANGELOG
67
CHANGELOG
@ -1,6 +1,6 @@
|
||||
CHANGELOG for smartmontools
|
||||
|
||||
$Id: CHANGELOG 3060 2010-02-03 22:16:40Z chrfranke $
|
||||
$Id: CHANGELOG 3077 2010-03-16 20:48:06Z chrfranke $
|
||||
|
||||
The most recent version of this file is:
|
||||
http://smartmontools.svn.sourceforge.net/viewvc/smartmontools/trunk/smartmontools/CHANGELOG?view=markup
|
||||
@ -43,6 +43,71 @@ NOTES FOR FUTURE RELEASES: see TODO file.
|
||||
|
||||
<DEVELOPERS: ADDITIONS TO THE CHANGE LOG GO JUST BELOW HERE, PLEASE>
|
||||
|
||||
[CF] USB ID updates:
|
||||
- LaCie Desktop Hard Drive
|
||||
- Prolific PL2507 (unsupported)
|
||||
- Seagate FreeAgent Go FW
|
||||
- WD My Book Essential
|
||||
|
||||
[CF] Linux: Add '/dev/sd[a-c][a-z]' to smartd DEVICESCAN.
|
||||
|
||||
[CF] smartd: Other config entries may precede DEVICESCAN.
|
||||
Very first step towards a more flexible device scanning.
|
||||
|
||||
[CF] Windows: Use '.win64' in names of 64-bit binary packages.
|
||||
Use correct 'strip' program when cross-compiling.
|
||||
|
||||
[CF] Add update script to make targets 'dist' and 'clean',
|
||||
set +x permission, update svn:ignore.
|
||||
|
||||
[CF] Add 'update-smart-drivedb' script (ticket #59).
|
||||
The script updates the drive database from SVN.
|
||||
It is installed if '--enable-drivedb' is configured.
|
||||
|
||||
[MS] drivedb.h updates:
|
||||
- Seagate Medalist 1720
|
||||
- SuperTalent UltraDrive GX SSD
|
||||
- Intel X25-M SSD
|
||||
|
||||
[CF] Makefile.am: Fix unix2dos and makensis parameters to allow
|
||||
to build the Windows installer on Linux also.
|
||||
|
||||
[CF] Makefile.am: Use a separate build rule for each man page to
|
||||
avoid compatibility problems with BSD make.
|
||||
|
||||
[AS] drivedb.h updates:
|
||||
- Fujitsu MHZ2 BK series
|
||||
|
||||
[MS] drivedb.h updates:
|
||||
- SAMSUNG SpinPoint F3 series
|
||||
- SAMSUNG SpinPoint F3 EG series
|
||||
- SAMSUNG SpinPoint M5 series
|
||||
- Western Digital Caviar Green 6400AADS
|
||||
- more Western Digital VelociRaptor variants
|
||||
|
||||
[AS] FreeBSD: disable 48-bit commands in the ata_pass_through interface,
|
||||
there is no 48-bit support in the IOCATAREQUEST ioctl.
|
||||
|
||||
[CF] smartctl: Add option '-l scterc[,READTIME,WRITETIME]' to get/set
|
||||
the SCT Error Recovery Control time limit (ticket #50).
|
||||
|
||||
Patch was provided by Richard Gregory:
|
||||
http://www.csc.liv.ac.uk/~greg/projects/erc/
|
||||
Modified for new ata_pass_through() interface.
|
||||
Linux HPT fixes ommitted for now.
|
||||
|
||||
[CF] Fix SCT temperature table commands on big endian CPUs.
|
||||
|
||||
[MS] drivedb.h updates:
|
||||
- more Seagate Momentus 5400.6 drives
|
||||
- HP 500GB drive MM0500EANCR
|
||||
|
||||
[CF] Windows: Cleanup I/O-control declarations, rely on include
|
||||
files if possible.
|
||||
|
||||
[CF] Windows: Compile fixes for 64-bit exe (EXPERIMENTAL).
|
||||
Update build info in INSTALL file.
|
||||
|
||||
[CF] drivedb.h update:
|
||||
- Patriot Torqx SSD (patch provided by Gianpaolo Cugola)
|
||||
|
||||
|
31
INSTALL
31
INSTALL
@ -1,7 +1,7 @@
|
||||
Smartmontools installation instructions
|
||||
=======================================
|
||||
|
||||
$Id: INSTALL 3057 2010-02-03 20:56:41Z chrfranke $
|
||||
$Id: INSTALL 3074 2010-03-05 23:00:30Z chrfranke $
|
||||
|
||||
Please also see the smartmontools home page:
|
||||
http://smartmontools.sourceforge.net/
|
||||
@ -443,20 +443,28 @@ To compile the Windows release with MinGW gcc on MSYS, use:
|
||||
Instead of using "make install", copy the .exe files into
|
||||
some directory in the PATH.
|
||||
|
||||
To compile with MinGW gcc 3.x on Cygwin, use:
|
||||
To compile on Cygwin with MinGW gcc 3.x (option '-mno-cygwin'):
|
||||
|
||||
./configure --build=i686-pc-mingw32
|
||||
./configure --build=i686-pc-mingw32 \
|
||||
CC=gcc-3 \
|
||||
CXX=g++-3
|
||||
|
||||
The above does not work if gcc 4.x is installed and selected as
|
||||
default by /usr/sbin/alternatives. If the configure command aborts
|
||||
with error message '... does not support -mno-cygwin', select
|
||||
gcc 3.x by:
|
||||
To cross-compile on Debian Linux with gcc-mingw32:
|
||||
|
||||
CC=gcc-3 CXX=g++-3 ./configure --build=i686-pc-mingw32
|
||||
./configure --build=$(./config.guess) \
|
||||
--host=i686-pc-mingw32 \
|
||||
CC=i586-mingw32msvc-gcc \
|
||||
CXX=i586-mingw32msvc-g++
|
||||
|
||||
Alternatively, a MinGW-targeted cross-compiler can be used if available:
|
||||
To compile statically linked 64-bit version with MinGW-w64:
|
||||
|
||||
./configure --build=i686-pc-cygwin --host=i686-pc-mingw32
|
||||
./configure --build=$(./config.guess) \
|
||||
--host=x86_64-w64-mingw32 \
|
||||
LDFLAGS=-static
|
||||
|
||||
Tested on Cygwin and Linux with MinGW-w64 from
|
||||
http://mingw-w64.sourceforge.net/.
|
||||
WARNING: 64-bit version is still EXPERIMENTAL.
|
||||
|
||||
|
||||
To build the Windows binary distribution, use:
|
||||
@ -484,6 +492,9 @@ To create a Windows installer, use:
|
||||
package. See http://nsis.sourceforge.net/ for documentation and
|
||||
download location.
|
||||
|
||||
It is also possible to (cross-)build the installer on Linux.
|
||||
This was successfully tested on Debian with package "nsis".
|
||||
|
||||
To both create and run the (interactive) installer, use:
|
||||
|
||||
make install-win32
|
||||
|
62
Makefile.am
62
Makefile.am
@ -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
10
NEWS
@ -1,6 +1,6 @@
|
||||
smartmontools NEWS
|
||||
------------------
|
||||
$Id: NEWS 3057 2010-02-03 20:56:41Z chrfranke $
|
||||
$Id: NEWS 3076 2010-03-12 22:23:08Z chrfranke $
|
||||
|
||||
The most up-to-date version of this file is:
|
||||
http://smartmontools.svn.sourceforge.net/viewvc/smartmontools/trunk/smartmontools/NEWS?view=markup
|
||||
@ -8,11 +8,19 @@ http://smartmontools.svn.sourceforge.net/viewvc/smartmontools/trunk/smartmontool
|
||||
Date <Not released yet, please try current SVN>
|
||||
Summary: smartmontools release 5.40
|
||||
-----------------------------------------------------------
|
||||
- Other config entries may precede smartd DEVICESCAN.
|
||||
- Option '-v' allows to specify byte order of attribute raw value
|
||||
- configure: New default value for '--with-docdir'.
|
||||
- Drive database is in a separate source file 'drivedb.h'
|
||||
which can be downloaded from SVN.
|
||||
- New script 'update-smart-drivedb'.
|
||||
- smartd libcap-ng support, option '-C, --capabilities'.
|
||||
- smartctl option '-l scterc[,...]' to get/set the
|
||||
SCT Error Recovery Control time limit.
|
||||
- Linux: Add '/dev/sd[a-c][a-z]' to smartd DEVICESCAN.
|
||||
- Windows: Support for 64-bit executables.
|
||||
- Windows: Support for cross compilation on Linux.
|
||||
- Fix SCT temperature table commands on big endian CPUs.
|
||||
|
||||
Date 2010-01-28
|
||||
Summary: smartmontools release 5.39.1
|
||||
|
108
atacmds.cpp
108
atacmds.cpp
@ -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,
|
||||
|
27
atacmds.h
27
atacmds.h
@ -26,7 +26,7 @@
|
||||
#ifndef ATACMDS_H_
|
||||
#define ATACMDS_H_
|
||||
|
||||
#define ATACMDS_H_CVSID "$Id: atacmds.h 3020 2009-12-31 01:11:51Z dlukes $"
|
||||
#define ATACMDS_H_CVSID "$Id: atacmds.h 3065 2010-02-10 22:16:50Z chrfranke $"
|
||||
|
||||
#include "dev_interface.h" // ata_device
|
||||
|
||||
@ -543,6 +543,20 @@ struct ata_sct_status_response
|
||||
#pragma pack()
|
||||
ASSERT_SIZEOF_STRUCT(ata_sct_status_response, 512);
|
||||
|
||||
// SCT Error Recovery Control command (send with SMART_WRITE_LOG page 0xe0)
|
||||
// Table 88 of T13/1699-D Revision 6a
|
||||
#pragma pack(1)
|
||||
struct ata_sct_error_recovery_control_command
|
||||
{
|
||||
unsigned short action_code; // 3 = Error Recovery Control
|
||||
unsigned short function_code; // 1 = Set, 2 = Return
|
||||
unsigned short selection_code; // 1 = Read Timer, 2 = Write Timer
|
||||
unsigned short time_limit; // If set: Recovery time limit in 100ms units
|
||||
unsigned short words004_255[252]; // reserved
|
||||
} ATTR_PACKED;
|
||||
#pragma pack()
|
||||
ASSERT_SIZEOF_STRUCT(ata_sct_error_recovery_control_command, 512);
|
||||
|
||||
// SCT Feature Control command (send with SMART_WRITE_LOG page 0xe0)
|
||||
// Table 72 of T13/1699-D Revision 3f
|
||||
#pragma pack(1)
|
||||
@ -552,8 +566,8 @@ struct ata_sct_feature_control_command
|
||||
unsigned short function_code; // 1 = Set, 2 = Return, 3 = Return options
|
||||
unsigned short feature_code; // 3 = Temperature logging interval
|
||||
unsigned short state; // Interval
|
||||
unsigned short option_flags; // Bit 0: persistent, Bits 1-31: reserved
|
||||
unsigned short words005_255[251]; // reserved
|
||||
unsigned short option_flags; // Bit 0: persistent, Bits 1-15: reserved
|
||||
unsigned short words005_255[251]; // reserved
|
||||
} ATTR_PACKED;
|
||||
#pragma pack()
|
||||
ASSERT_SIZEOF_STRUCT(ata_sct_feature_control_command, 512);
|
||||
@ -727,6 +741,10 @@ int ataReadSCTTempHist(ata_device * device, ata_sct_temperature_history_table *
|
||||
// Set SCT temperature logging interval
|
||||
int ataSetSCTTempInterval(ata_device * device, unsigned interval, bool persistent);
|
||||
|
||||
// Get/Set SCT Error Recovery Control
|
||||
int ataGetSCTErrorRecoveryControltime(ata_device * device, unsigned type, unsigned short & time_limit);
|
||||
int ataSetSCTErrorRecoveryControltime(ata_device * device, unsigned type, unsigned short time_limit);
|
||||
|
||||
|
||||
/* Enable/Disable SMART on device */
|
||||
int ataEnableSmart (ata_device * device);
|
||||
@ -789,6 +807,9 @@ int isSupportSelectiveSelfTest(const ata_smart_values * data);
|
||||
inline bool isSCTCapable(const ata_identify_device *drive)
|
||||
{ return !!(drive->words088_255[206-88] & 0x01); } // 0x01 = SCT support
|
||||
|
||||
inline bool isSCTErrorRecoveryControlCapable(const ata_identify_device *drive)
|
||||
{ return ((drive->words088_255[206-88] & 0x09) == 0x09); } // 0x08 = SCT Error Recovery Control support
|
||||
|
||||
inline bool isSCTFeatureControlCapable(const ata_identify_device *drive)
|
||||
{ return ((drive->words088_255[206-88] & 0x11) == 0x11); } // 0x10 = SCT Feature Control support
|
||||
|
||||
|
75
ataprint.cpp
75
ataprint.cpp
@ -44,7 +44,7 @@
|
||||
#include "utility.h"
|
||||
#include "knowndrives.h"
|
||||
|
||||
const char * ataprint_cpp_cvsid = "$Id: ataprint.cpp 3037 2010-01-16 20:07:13Z chrfranke $"
|
||||
const char * ataprint_cpp_cvsid = "$Id: ataprint.cpp 3065 2010-02-10 22:16:50Z chrfranke $"
|
||||
ATAPRINT_H_CVSID;
|
||||
|
||||
// for passing global control variables
|
||||
@ -883,6 +883,8 @@ static void ataPrintSCTCapability(const ata_identify_device *drive)
|
||||
if (!(sctcaps & 0x01))
|
||||
return;
|
||||
pout("SCT capabilities: \t (0x%04x)\tSCT Status supported.\n", sctcaps);
|
||||
if (sctcaps & 0x08)
|
||||
pout("\t\t\t\t\tSCT Error Recovery Control supported.\n");
|
||||
if (sctcaps & 0x10)
|
||||
pout("\t\t\t\t\tSCT Feature Control supported.\n");
|
||||
if (sctcaps & 0x20)
|
||||
@ -1698,6 +1700,20 @@ static int ataPrintSCTTempHist(const ata_sct_temperature_history_table * tmh)
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Print SCT Error Recovery Control timers
|
||||
static void ataPrintSCTErrorRecoveryControl(unsigned short read_timer, unsigned short write_timer)
|
||||
{
|
||||
pout("SCT Error Recovery Control:\n");
|
||||
if (!read_timer)
|
||||
pout(" Read: Disabled\n");
|
||||
else
|
||||
pout(" Read: %6d (%0.1f seconds)\n", read_timer, read_timer/10.0);
|
||||
if (!write_timer)
|
||||
pout(" Write: Disabled\n");
|
||||
else
|
||||
pout(" Write: %6d (%0.1f seconds)\n", write_timer, write_timer/10.0);
|
||||
}
|
||||
|
||||
|
||||
// Compares failure type to policy in effect, and either exits or
|
||||
// simply returns to the calling routine.
|
||||
@ -2285,14 +2301,21 @@ int ataPrintMain (ata_device * device, const ata_print_options & options)
|
||||
}
|
||||
}
|
||||
|
||||
// SCT commands
|
||||
bool sct_ok = false;
|
||||
if ( options.sct_temp_sts || options.sct_temp_hist || options.sct_temp_int
|
||||
|| options.sct_erc_get || options.sct_erc_set ) {
|
||||
if (!isSCTCapable(&drive)) {
|
||||
pout("Warning: device does not support SCT Commands\n");
|
||||
failuretest(OPTIONAL_CMD, returnval|=FAILSMART);
|
||||
}
|
||||
else
|
||||
sct_ok = true;
|
||||
}
|
||||
|
||||
// Print SCT status and temperature history table
|
||||
if (options.sct_temp_sts || options.sct_temp_hist || options.sct_temp_int) {
|
||||
if (sct_ok && (options.sct_temp_sts || options.sct_temp_hist || options.sct_temp_int)) {
|
||||
for (;;) {
|
||||
if (!isSCTCapable(&drive)) {
|
||||
pout("Warning: device does not support SCT Commands\n");
|
||||
failuretest(OPTIONAL_CMD, returnval|=FAILSMART);
|
||||
break;
|
||||
}
|
||||
if (options.sct_temp_sts || options.sct_temp_hist) {
|
||||
ata_sct_status_response sts;
|
||||
ata_sct_temperature_history_table tmh;
|
||||
@ -2340,6 +2363,44 @@ int ataPrintMain (ata_device * device, const ata_print_options & options)
|
||||
}
|
||||
}
|
||||
|
||||
// SCT Error Recovery Control
|
||||
if (sct_ok && (options.sct_erc_get || options.sct_erc_set)) {
|
||||
if (!isSCTErrorRecoveryControlCapable(&drive)) {
|
||||
pout("Warning: device does not support SCT Error Recovery Control command\n");
|
||||
failuretest(OPTIONAL_CMD, returnval|=FAILSMART);
|
||||
}
|
||||
else {
|
||||
bool sct_erc_get = options.sct_erc_get;
|
||||
if (options.sct_erc_set) {
|
||||
// Set SCT Error Recovery Control
|
||||
if ( ataSetSCTErrorRecoveryControltime(device, 1, options.sct_erc_readtime )
|
||||
|| ataSetSCTErrorRecoveryControltime(device, 2, options.sct_erc_writetime)) {
|
||||
pout("Warning: device does not support SCT (Set) Error Recovery Control command\n");
|
||||
pout("Suggest common arguments: scterc,70,70 to enable ERC or sct,0,0 to disable\n");
|
||||
failuretest(OPTIONAL_CMD, returnval|=FAILSMART);
|
||||
sct_erc_get = false;
|
||||
}
|
||||
else
|
||||
sct_erc_get = true;
|
||||
}
|
||||
|
||||
if (sct_erc_get) {
|
||||
// Print SCT Error Recovery Control
|
||||
unsigned short read_timer, write_timer;
|
||||
if ( ataGetSCTErrorRecoveryControltime(device, 1, read_timer )
|
||||
|| ataGetSCTErrorRecoveryControltime(device, 2, write_timer)) {
|
||||
pout("Warning: device does not support SCT (Get) Error Recovery Control command\n");
|
||||
if (options.sct_erc_set)
|
||||
pout("The previous SCT (Set) Error Recovery Control command succeeded\n");
|
||||
failuretest(OPTIONAL_CMD, returnval|=FAILSMART);
|
||||
}
|
||||
else
|
||||
ataPrintSCTErrorRecoveryControl(read_timer, write_timer);
|
||||
}
|
||||
pout("\n");
|
||||
}
|
||||
}
|
||||
|
||||
// Print SATA Phy Event Counters
|
||||
if (options.sataphy) {
|
||||
unsigned nsectors = GetNumLogSectors(gplogdir, 0x11, true);
|
||||
|
@ -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),
|
||||
|
15
configure.in
15
configure.in
@ -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()],
|
||||
|
61
drivedb.h
61
drivedb.h
@ -58,7 +58,7 @@
|
||||
/*
|
||||
const drive_settings builtin_knowndrives[] = {
|
||||
*/
|
||||
{ "$Id: drivedb.h 3060 2010-02-03 22:16:40Z chrfranke $",
|
||||
{ "$Id: drivedb.h 3071 2010-03-04 21:17:09Z manfred99 $",
|
||||
"-", "-",
|
||||
"This is a dummy entry to hold the SVN-Id of drivedb.h",
|
||||
""
|
||||
@ -71,6 +71,28 @@ const drive_settings builtin_knowndrives[] = {
|
||||
"ASUS-PHISON SSD",
|
||||
"", "", ""
|
||||
},
|
||||
{ "SuperTalent UltraDrive GX SSD",
|
||||
"STT_FT[MD](28|32|56|64)GX25H",
|
||||
"", "",
|
||||
" -v 9,raw64"
|
||||
" -v 12,raw64"
|
||||
" -v 184,raw64,Initial_Bad_Block_Count"
|
||||
" -v 195,raw64,Program_Failure_Blk_Ct"
|
||||
" -v 196,raw64,Erase_Failure_Blk_Ct"
|
||||
" -v 197,raw64,Read_Failure_Blk_Ct"
|
||||
" -v 198,raw64,Read_Sectors_Tot_Ct"
|
||||
" -v 199,raw64,Write_Sectors_Tot_Ct"
|
||||
" -v 200,raw64,Read_Commands_Tot_Ct"
|
||||
" -v 201,raw64,Write_Commands_Tot_Ct"
|
||||
" -v 202,raw64,Error_Bits_Flash_Tot_Ct"
|
||||
" -v 203,raw64,Corr_Read_Errors_Tot_Ct"
|
||||
" -v 204,raw64,Bad_Block_Full_Flag"
|
||||
" -v 205,raw64,Max_PE_Count_Spec"
|
||||
" -v 206,raw64,Min_Erase_Count"
|
||||
" -v 207,raw64,Max_Erase_Count"
|
||||
" -v 208,raw64,Average_Erase_Count"
|
||||
" -v 209,raw64,Remaining_Lifetime_Perc"
|
||||
},
|
||||
{ "Patriot Torqx SSD",
|
||||
"Patriot[ -]Torqx.*",
|
||||
"", "",
|
||||
@ -163,7 +185,12 @@ const drive_settings builtin_knowndrives[] = {
|
||||
" -v 211,raw64"
|
||||
},
|
||||
{ "Intel X25-E SSD",
|
||||
"SSDSA2SH(032|064)G1.* INTEL",
|
||||
"SSDSA2SH(032|064)G1.* INTEL", // G1 = first generation
|
||||
"", "",
|
||||
"-v 225,raw48,Host_Writes_Count"
|
||||
},
|
||||
{ "Intel X25-M SSD",
|
||||
"INTEL SSDSA2M(080|160)G2.*", // G2 = second generation
|
||||
"", "",
|
||||
"-v 225,raw48,Host_Writes_Count"
|
||||
},
|
||||
@ -183,6 +210,10 @@ const drive_settings builtin_knowndrives[] = {
|
||||
"GB1000EAFJL",
|
||||
"", "", ""
|
||||
},
|
||||
{ "HP 500GB SATA disk MM0500EANCR",
|
||||
"MM0500EANCR",
|
||||
"", "", ""
|
||||
},
|
||||
{ "IBM Deskstar 60GXP series", // ER60A46A firmware
|
||||
"(IBM-|Hitachi )?IC35L0[12346]0AVER07.*",
|
||||
"ER60A46A",
|
||||
@ -335,6 +366,10 @@ const drive_settings builtin_knowndrives[] = {
|
||||
"FUJITSU MHZ2(12|25)0BS.*",
|
||||
"", "", ""
|
||||
},
|
||||
{ "Fujitsu MHZ2 BK series",
|
||||
"FUJITSU MHZ2(08|12|16|25)0BK.*",
|
||||
"", "", ""
|
||||
},
|
||||
{ "", // Samsung SV4012H (known firmware)
|
||||
"SAMSUNG SV4012H",
|
||||
"RM100-08",
|
||||
@ -405,6 +440,14 @@ const drive_settings builtin_knowndrives[] = {
|
||||
"SAMSUNG HD(502H|10[23]S|15[34]U)I",
|
||||
"", "", ""
|
||||
},
|
||||
{ "SAMSUNG SpinPoint F3 series", // tested with HD502HJ/1AJ100E4
|
||||
"SAMSUNG HD(502H|754J|103S)J",
|
||||
"", "", ""
|
||||
},
|
||||
{ "SAMSUNG SpinPoint F3 EG series", // tested with HD503HI/1AJ100E4
|
||||
"SAMSUNG HD(253G|(324|503)H|754J|105S)I",
|
||||
"", "", ""
|
||||
},
|
||||
{ "SAMSUNG SpinPoint S250 series", // tested with HD200HJ/KF100-06
|
||||
"SAMSUNG HD(162|200|250)HJ",
|
||||
"", "", ""
|
||||
@ -472,6 +515,10 @@ const drive_settings builtin_knowndrives[] = {
|
||||
"",
|
||||
"-v 9,halfminutes"
|
||||
},
|
||||
{ "SAMSUNG SpinPoint M5 series", // tested with HM160HI/HH100-12
|
||||
"SAMSUNG HM((061|080)G|(121|160)H|250J)I",
|
||||
"", "", ""
|
||||
},
|
||||
/*
|
||||
// TODO: Make the entries below more specific.
|
||||
// These entries produce misleading results, because newer
|
||||
@ -1031,7 +1078,7 @@ const drive_settings builtin_knowndrives[] = {
|
||||
"", "", ""
|
||||
},
|
||||
{ "Seagate Momentus 5400.6 series",
|
||||
"ST9((12|25)0315AS|500325)ASG?",
|
||||
"ST9(80313|160(301|314)|(12|25)0315|250317|(320|500)325|500327|640320)ASG?",
|
||||
"", "", ""
|
||||
},
|
||||
{ "Seagate Momentus 5400 PSD series", // Hybrid drives
|
||||
@ -1058,8 +1105,8 @@ const drive_settings builtin_knowndrives[] = {
|
||||
"ST9((160413|25041[12]|320426|50042[12])AS|(16041[89]|2504[16]4|32042[67]|500426)ASG)",
|
||||
"", "", ""
|
||||
},
|
||||
{ "Seagate Medalist 1010, 1721, 2120, 3230 and 4340", // ATA2, with -t permissive
|
||||
"ST3(1010|1721|2120|3230|4340)A",
|
||||
{ "Seagate Medalist 1010, 1720, 1721, 2120, 3230 and 4340", // ATA2, with -t permissive
|
||||
"ST3(1010|1720|1721|2120|3230|4340)A",
|
||||
"", "", ""
|
||||
},
|
||||
{ "Seagate Medalist 2110, 3221, 4321, 6531, and 8641",
|
||||
@ -1333,7 +1380,7 @@ const drive_settings builtin_knowndrives[] = {
|
||||
"", "", ""
|
||||
},
|
||||
{ "Western Digital Caviar Green family",
|
||||
"WDC WD((50|64|75)00AA(C|V)S|(50|75)00AADS|10EA(C|V)S|(10|15|20)EADS)-.*",
|
||||
"WDC WD((50|64|75)00AA(C|V)S|(50|64|75)00AADS|10EA(C|V)S|(10|15|20)EADS)-.*",
|
||||
"", "", ""
|
||||
},
|
||||
{ "Western Digital Caviar Black family",
|
||||
@ -1357,7 +1404,7 @@ const drive_settings builtin_knowndrives[] = {
|
||||
"", "", ""
|
||||
},
|
||||
{ "Western Digital VelociRaptor family",
|
||||
"WDC WD((1500|3000)B|3000G)LFS-.*",
|
||||
"WDC WD(800H|(1500|3000)[BH]|1600H|3000G)LFS-.*",
|
||||
"", "", ""
|
||||
},
|
||||
{ "Western Digital Scorpio EIDE family",
|
||||
|
@ -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;
|
||||
|
10
os_linux.cpp
10
os_linux.cpp
@ -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)
|
||||
|
599
os_win32.cpp
599
os_win32.cpp
@ -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;
|
||||
|
@ -1037,6 +1037,10 @@
|
||||
RelativePath="..\TODO"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\update-smart-drivedb.in"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\utility.cpp"
|
||||
>
|
||||
|
@ -989,6 +989,10 @@
|
||||
RelativePath="..\TODO"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\update-smart-drivedb.in"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\utility.cpp"
|
||||
>
|
||||
|
@ -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)
|
||||
|
@ -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:
|
||||
|
21
smartctl.cpp
21
smartctl.cpp
@ -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;
|
||||
|
16
smartd.8.in
16
smartd.8.in
@ -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 $
|
||||
|
@ -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 $
|
||||
|
24
smartd.cpp
24
smartd.cpp
@ -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
144
update-smart-drivedb.in
Normal 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"
|
||||
|
Loading…
Reference in New Issue
Block a user